Ejemplo n.º 1
0
FT_Face
_PGFT_GetFont(FreeTypeInstance *ft, PgFontObject *fontobj)
{
    FT_Error error;
    FT_Face font;

    error = FTC_Manager_LookupFace(ft->cache_manager,
        (FTC_FaceID)(&fontobj->id),
        &font);

    if (error) {
        _PGFT_SetError(ft, "Failed to load font", error);
        return 0;
    }

    return font;
}
Ejemplo n.º 2
0
FT_Face
_PGFT_GetFace(FreeTypeInstance *ft,
    PgFaceObject *faceobj)
{
    FT_Error error;
    FT_Face face;

    error = FTC_Manager_LookupFace(ft->cache_manager,
        (FTC_FaceID)(&faceobj->id),
        &face);

    if (error) {
        _PGFT_SetError(ft, "Failed to load face", error);
        return 0;
    }

    return face;
}
Ejemplo n.º 3
0
/*********************************************************
 *
 * Face access
 *
 *********************************************************/
FT_Face
_PGFT_GetFaceSized(FreeTypeInstance *ft,
    PgFaceObject *faceobj,
    int face_size)
{
    FT_Error error;
    FTC_ScalerRec scale;
    FT_Size _fts;

    _PGFT_BuildScaler(faceobj, &scale, face_size);

    error = FTC_Manager_LookupSize(ft->cache_manager,
        &scale, &_fts);

    if (error) {
        _PGFT_SetError(ft, "Failed to resize face", error);
        return 0;
    }

    return _fts->face;
}
Ejemplo n.º 4
0
FontText *
_PGFT_LoadFontText(FreeTypeInstance *ft, PgFontObject *fontobj,
                   const FontRenderMode *mode, PGFT_String *text)
{
    Py_ssize_t  string_length = PGFT_String_GET_LENGTH(text);

    PGFT_char * buffer = PGFT_String_GET_DATA(text);
    PGFT_char * buffer_end;
    PGFT_char * ch;

    FontText    *ftext = &(PGFT_INTERNALS(fontobj)->active_text);
    FontGlyph   *glyph = 0;
    FontGlyph   **glyph_array = 0;
    FontMetrics *metrics;
    FT_BitmapGlyph image;
    TextContext context;

    FT_Face     font;
    FT_Size_Metrics *sz_metrics;

    FT_Vector   pen = {0, 0};                /* untransformed origin  */
    FT_Vector   pen1 = {0, 0};
    FT_Vector   pen2;

    FT_Vector   *next_pos;

    int         vertical = mode->render_flags & FT_RFLAG_VERTICAL;
    int         use_kerning = mode->render_flags & FT_RFLAG_KERNING;
    int         pad = mode->render_flags & FT_RFLAG_PAD;
    FT_UInt     prev_glyph_index = 0;

    /* All these are 16.16 precision */
    FT_Angle    rotation_angle = mode->rotation_angle;

    /* All these are 26.6 precision */
    FT_Vector   kerning;
    FT_Pos      min_x = FX6_MAX;
    FT_Pos      max_x = FX6_MIN;
    FT_Pos      min_y = FX6_MAX;
    FT_Pos      max_y = FX6_MIN;
    FT_Pos      glyph_width;
    FT_Pos      glyph_height;
    FT_Pos      top = FX6_MIN;
    FT_Fixed    y_scale;

    FT_Error    error = 0;

    /* load our sized font */
    font = _PGFT_GetFontSized(ft, fontobj, mode->pt_size);
    if (!font) {
        PyErr_SetString(PyExc_SDLError, _PGFT_GetError(ft));
        return 0;
    }
    sz_metrics = &font->size->metrics;
    y_scale = sz_metrics->y_scale;

    /* cleanup the cache */
    _PGFT_Cache_Cleanup(&ftext->glyph_cache);

    /* create the text struct */
    if (string_length > ftext->buffer_size) {
        _PGFT_free(ftext->glyphs);
        ftext->glyphs = (FontGlyph **)
                        _PGFT_malloc((size_t)string_length * sizeof(FontGlyph *));
        if (!ftext->glyphs) {
            PyErr_NoMemory();
            return 0;
        }

        _PGFT_free(ftext->posns);
        ftext->posns = (FT_Vector *)
                       _PGFT_malloc((size_t)string_length * sizeof(FT_Vector));
        if (!ftext->posns) {
            PyErr_NoMemory();
            return 0;
        }
        ftext->buffer_size = string_length;
    }
    ftext->length = string_length;
    ftext->ascender = sz_metrics->ascender;
    ftext->underline_pos = -FT_MulFix(font->underline_position, y_scale);
    ftext->underline_size = FT_MulFix(font->underline_thickness, y_scale);
    if (mode->style & FT_STYLE_STRONG) {
        FT_Fixed bold_str = mode->strength * sz_metrics->x_ppem;

        ftext->underline_size = FT_MulFix(ftext->underline_size,
                                          FX16_ONE + bold_str / 4);
    }

    /* fill it with the glyphs */
    fill_context(&context, ft, fontobj, mode, font);
    glyph_array = ftext->glyphs;
    next_pos = ftext->posns;

    for (ch = buffer, buffer_end = ch + string_length; ch < buffer_end; ++ch) {
        pen2.x = pen1.x;
        pen2.y = pen1.y;
        pen1.x = pen.x;
        pen1.y = pen.y;
        /*
         * Load the corresponding glyph from the cache
         */
        glyph = _PGFT_Cache_FindGlyph(*((FT_UInt32 *)ch), mode,
                                      &ftext->glyph_cache, &context);

        if (!glyph) {
            --ftext->length;
            continue;
        }
        image = glyph->image;
        glyph_width = glyph->width;
        glyph_height = glyph->height;

        /*
         * Do size calculations for all the glyphs in the text
         */
        if (use_kerning && prev_glyph_index) {
            error = FT_Get_Kerning(font, prev_glyph_index,
                                   glyph->glyph_index,
                                   FT_KERNING_UNFITTED, &kerning);
            if (error) {
                _PGFT_SetError(ft, "Loading glyphs", error);
                PyErr_SetString(PyExc_SDLError, _PGFT_GetError(ft));
                return 0;
            }
            if (rotation_angle != 0) {
                FT_Vector_Rotate(&kerning, rotation_angle);
            }
            pen.x += FX6_ROUND(kerning.x);
            pen.y += FX6_ROUND(kerning.y);
            if (FT_Vector_Length(&pen2) > FT_Vector_Length(&pen)) {
                pen.x = pen2.x;
                pen.y = pen2.y;
            }
        }

        prev_glyph_index = glyph->glyph_index;
        metrics = vertical ? &glyph->v_metrics : &glyph->h_metrics;
        if (metrics->bearing_rotated.y > top) {
            top = metrics->bearing_rotated.y;
        }
        if (pen.x + metrics->bearing_rotated.x < min_x) {
            min_x = pen.x + metrics->bearing_rotated.x;
        }
        if (pen.x + metrics->bearing_rotated.x + glyph_width > max_x) {
            max_x = pen.x + metrics->bearing_rotated.x + glyph_width;
        }
        next_pos->x = pen.x + metrics->bearing_rotated.x;
        pen.x += metrics->advance_rotated.x;
        if (vertical) {
            if (pen.y + metrics->bearing_rotated.y < min_y) {
                min_y = pen.y + metrics->bearing_rotated.y;
            }
            if (pen.y + metrics->bearing_rotated.y + glyph_height > max_y) {
                max_y = pen.y + metrics->bearing_rotated.y + glyph_height;
            }
            next_pos->y = pen.y + metrics->bearing_rotated.y;
            pen.y += metrics->advance_rotated.y;
        }
        else {
            if (pen.y - metrics->bearing_rotated.y < min_y) {
                min_y = pen.y - metrics->bearing_rotated.y;
            }
            if (pen.y - metrics->bearing_rotated.y + glyph_height > max_y) {
                max_y = pen.y - metrics->bearing_rotated.y + glyph_height;
            }
            next_pos->y = pen.y - metrics->bearing_rotated.y;
            pen.y -= metrics->advance_rotated.y;
        }
        *glyph_array++ = glyph;
        ++next_pos;
    }

    if (ftext->length == 0) {
        min_x = 0;
        max_x = 0;
        if (vertical) {
            ftext->min_y = 0;
            max_y = sz_metrics->height;
        }
        else {
            FT_Size_Metrics *sz_metrics = &font->size->metrics;

            min_y = -sz_metrics->ascender;
            max_y = -sz_metrics->descender;
        }
    }

    if (pad) {
        FT_Size_Metrics *sz_metrics = &font->size->metrics;

        if (pen.x > max_x) {
            max_x = pen.x;
        }
        else if (pen.x < min_x) {
            min_x = pen.x;
        }
        if (pen.y > max_y) {
            max_y = pen.y;
        }
        else if (pen.y < min_y) {
            min_y = pen.y;
        }
        if (vertical) {
            FT_Fixed right = sz_metrics->max_advance / 2;

            if (max_x < right) {
                max_x = right;
            }
            if (min_x > -right) {
                min_x = -right;
            }
            if (min_y > 0) {
                min_y = 0;
            }
            else if (max_y < pen.y) {
                max_y = pen.y;
            }
        }
        else {
            FT_Fixed ascender = sz_metrics->ascender;
            FT_Fixed descender = sz_metrics->descender;

            if (min_x > 0) {
                min_x = 0;
            }
            if (max_x < pen.x) {
                max_x = pen.x;
            }
            if (min_y > -ascender) {
                min_y = -ascender;
            }
            if (max_y <= -descender) {
                max_y = -descender + /* baseline */ FX6_ONE;
            }
        }
    }

    ftext->left = FX6_TRUNC(FX6_FLOOR(min_x));
    ftext->top = FX6_TRUNC(FX6_CEIL(top));
    ftext->min_x = min_x;
    ftext->max_x = max_x;
    ftext->min_y = min_y;
    ftext->max_y = max_y;
    ftext->advance.x = pen.x;
    ftext->advance.y = pen.y;

    return ftext;
}