Beispiel #1
0
void
_PGFT_FontTextFree(PgFontObject *fontobj)
{
    FontText *ftext = &(PGFT_INTERNALS(fontobj)->active_text);

    if (ftext->buffer_size > 0) {
        _PGFT_free(ftext->glyphs);
        _PGFT_free(ftext->posns);
    }
    _PGFT_Cache_Destroy(&ftext->glyph_cache);
}
Beispiel #2
0
static void
quit(PgFaceObject *faceobj)
{
    if (faceobj->_internals) {
        _PGFT_FaceTextFree(faceobj);
        _PGFT_free(faceobj->_internals);
        faceobj->_internals = 0;
    }
}
Beispiel #3
0
static void
quit(PgFontObject *fontobj)
{
    if (fontobj->_internals) {
        _PGFT_FontTextFree(fontobj);
        _PGFT_free(fontobj->_internals);
        fontobj->_internals = 0;
    }
}
Beispiel #4
0
void
_PGFT_UnloadFace(FreeTypeInstance *ft, PgFaceObject *faceobj)
{
    if (faceobj->id.open_args.flags == 0)
        return;

    if (ft) {
        FTC_Manager_RemoveFaceID(ft->cache_manager, (FTC_FaceID)(&faceobj->id));
        quit(faceobj);
    }

    if (faceobj->id.open_args.flags == FT_OPEN_STREAM) {
        _PGFT_free(faceobj->id.open_args.pathname);
    faceobj->id.open_args.pathname = 0;
    }
    else if (faceobj->id.open_args.flags == FT_OPEN_PATHNAME) {
        _PGFT_free(faceobj->id.open_args.stream);
    }
    faceobj->id.open_args.flags = 0;
}
Beispiel #5
0
void
_PGFT_Quit(FreeTypeInstance *ft)
{
    if (!ft)
        return;

    if (ft->cache_manager)
        FTC_Manager_Done(ft->cache_manager);

    if (ft->library)
        FT_Done_FreeType(ft->library);

    _PGFT_free(ft);
}
Beispiel #6
0
static int init(FreeTypeInstance *ft, PgFaceObject *faceobj)
{
    faceobj->_internals = 0;

    if (!_PGFT_GetFace(ft, faceobj)) {
        RAISE(PyExc_IOError, _PGFT_GetError(ft));
        return -1;
    }

    faceobj->_internals = _PGFT_malloc(sizeof(FaceInternals));
    if (!faceobj->_internals) {
        PyErr_NoMemory();
        return -1;
    }
    memset(faceobj->_internals, 0x0, sizeof(FaceInternals));

    if (_PGFT_FaceTextInit(ft, faceobj)) {
        _PGFT_free(faceobj->_internals);
        faceobj->_internals = 0;
        return -1;
    }

    return 0;
}
Beispiel #7
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;
}