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); }
static void quit(PgFaceObject *faceobj) { if (faceobj->_internals) { _PGFT_FaceTextFree(faceobj); _PGFT_free(faceobj->_internals); faceobj->_internals = 0; } }
static void quit(PgFontObject *fontobj) { if (fontobj->_internals) { _PGFT_FontTextFree(fontobj); _PGFT_free(fontobj->_internals); fontobj->_internals = 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; }
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); }
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; }
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; }