📄 ft_font.c
字号:
return GF_OK; } if (fontName) { /*font not on system...*/ gf_modules_set_option((GF_BaseInterface *)dr, "FontEngine", fname, "UNKNOWN"); if (!styles) { /*remove cache if default fonts not found*/ if (!OrigFontName || !stricmp(OrigFontName, "SERIF")) { gf_modules_set_option((GF_BaseInterface *)dr, "FontEngine", "FontSerif", NULL); strcpy(ftpriv->font_serif, ""); } else if (!stricmp(OrigFontName, "SANS")) { gf_modules_set_option((GF_BaseInterface *)dr, "FontEngine", "FontSans", NULL); strcpy(ftpriv->font_sans, ""); } else if (!stricmp(OrigFontName, "TYPEWRITTER")) { gf_modules_set_option((GF_BaseInterface *)dr, "FontEngine", "FontFixed", NULL); strcpy(ftpriv->font_fixed, ""); } } } GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[FreeType] Font not found\n")); return GF_NOT_SUPPORTED;}static GF_Err ft_set_font_size(GF_FontRaster *dr, Fixed pixel_size){ FTBuilder *ftpriv = (FTBuilder *)dr->priv; if (!ftpriv->active_face || !pixel_size) return GF_BAD_PARAM; ftpriv->pixel_size = pixel_size; return GF_OK;}static GF_Err ft_get_font_metrics(GF_FontRaster *dr, Fixed *ascent, Fixed *descent, Fixed *lineSpacing){ FTBuilder *ftpriv = (FTBuilder *)dr->priv; if (!ftpriv->active_face || !ftpriv->pixel_size) return GF_BAD_PARAM; *ascent = (ftpriv->pixel_size / ftpriv->active_face->units_per_EM) * ftpriv->active_face->ascender; *descent = - (ftpriv->pixel_size / ftpriv->active_face->units_per_EM) * ftpriv->active_face->descender; *lineSpacing = (ftpriv->pixel_size / ftpriv->active_face->units_per_EM) * ftpriv->active_face->height; return GF_OK;}static GF_Err ft_get_text_size(GF_FontRaster *dr, const unsigned short *string, Fixed *width, Fixed *height){ u32 i, count, glyph_idx, w, h; FT_Glyph glyph; FT_BBox bbox; FTBuilder *ftpriv = (FTBuilder *)dr->priv; if (!ftpriv->active_face || !ftpriv->pixel_size) return GF_BAD_PARAM; FT_Select_Charmap(ftpriv->active_face, FT_ENCODING_UNICODE); count = gf_utf8_wcslen(string); if (count == (size_t) (-1)) return GF_BAD_PARAM; w = h = 0; for (i=0; i<count; i++) { glyph_idx = FT_Get_Char_Index(ftpriv->active_face, string[i]); /*missing glyph*/ if (!glyph_idx) continue; /*work in design units*/ FT_Load_Glyph(ftpriv->active_face, glyph_idx, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP); FT_Get_Glyph(ftpriv->active_face->glyph, &glyph); FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_unscaled, &bbox); if (h < (u32) (bbox.yMax - bbox.yMin)) h = (bbox.yMax - bbox.yMin); if (!i) w = -1 * bbox.xMin; if (i+1<count) { w += ftpriv->active_face->glyph->metrics.horiAdvance; } else { w += bbox.xMax; } FT_Done_Glyph(glyph); } /*convert to font size*/ *width = (ftpriv->pixel_size / ftpriv->active_face->units_per_EM) * w; *height = (ftpriv->pixel_size / ftpriv->active_face->units_per_EM) * h; return GF_OK;}typedef struct{// Fixed font_scale; Fixed top; Fixed pos_x; FTBuilder *ftpriv; GF_Path *path; Fixed x_scale, y_scale; Fixed last_x, last_y;} ft_outliner;#define GETX(_x) (ftol->pos_x + gf_mulfix(ftol->x_scale, INT2FIX(_x)))#define GETY(_y) (ftol->top + gf_mulfix(ftol->y_scale, INT2FIX(_y)))/* this is not explicit in FreeType doc, i assume each line/curve ending at last moveTo shall be closed*/int ft_move_to(FT_Vector *to, void *user){ Fixed x, y; ft_outliner *ftol = (ft_outliner *)user; x = GETX(to->x); y = GETY(to->y); gf_path_add_move_to(ftol->path, x, y); ftol->last_x = x; ftol->last_y = y; return 0;}int ft_line_to(FT_Vector *to, void *user){ Fixed x, y; ft_outliner *ftol = (ft_outliner *)user; x = GETX(to->x); y = GETY(to->y); if ( (ftol->last_x == x) && (ftol->last_y == y)) { gf_path_close(ftol->path); } else { gf_path_add_line_to(ftol->path, x, y); } return 0;}int ft_conic_to(FT_Vector * control, FT_Vector *to, void *user){ Fixed x, y, cx, cy; ft_outliner *ftol = (ft_outliner *)user; cx = GETX(control->x); cy = GETY(control->y); x = GETX(to->x); y = GETY(to->y); gf_path_add_quadratic_to(ftol->path, cx, cy, x, y); if ( (ftol->last_x == x) && (ftol->last_y == y)) gf_path_close(ftol->path); return 0;}int ft_cubic_to(FT_Vector *control1, FT_Vector *control2, FT_Vector *to, void *user){ Fixed x, y, c1x, c1y, c2x, c2y; ft_outliner *ftol = (ft_outliner *)user; c1x = GETX(control1->x); c1y = GETY(control1->y); c2x = GETX(control2->x); c2y = GETY(control2->y); x = GETX(to->x); y = GETY(to->y); gf_path_add_cubic_to(ftol->path, c1x, c1y, c1x, c1y, x, y); if ( (ftol->last_x == x) && (ftol->last_y == y)) gf_path_close(ftol->path); return 0;}static GF_Err ft_add_text_to_path(GF_FontRaster *dr, GF_Path *path, Bool flipText, const unsigned short *string, Fixed left, Fixed top, Fixed x_scaling, Fixed y_scaling, Fixed ascent, GF_Rect *bounds){ u32 i, count, glyph_idx; Fixed def_inc_x, font_scale; s32 ymin, ymax; FT_BBox bbox; FT_OutlineGlyph outline; ft_outliner outl; FT_Outline_Funcs ft_outl_funcs; FTBuilder *ftpriv = (FTBuilder *)dr->priv; if (!ftpriv->active_face || !ftpriv->pixel_size) return GF_BAD_PARAM; FT_Select_Charmap(ftpriv->active_face, FT_ENCODING_UNICODE); /*setup outliner*/ ft_outl_funcs.shift = 0; ft_outl_funcs.delta = 0; ft_outl_funcs.move_to = ft_move_to; ft_outl_funcs.line_to = ft_line_to; ft_outl_funcs.conic_to = ft_conic_to; ft_outl_funcs.cubic_to = ft_cubic_to; /*units per EM are 24.6 fixed point in freetype, consider them as integers (no risk of overflow)*/ font_scale = ftpriv->pixel_size / ftpriv->active_face->units_per_EM; outl.path = path; outl.ftpriv = ftpriv; outl.x_scale = gf_mulfix(x_scaling, font_scale); outl.y_scale = gf_mulfix(y_scaling, font_scale); if (!flipText) outl.y_scale *= -1; bounds->x = outl.pos_x = gf_mulfix(left, x_scaling); if (flipText) bounds->y = outl.top = gf_mulfix(top - ascent, y_scaling); else bounds->y = outl.top = gf_mulfix(top, y_scaling); /*same remark as above*/ def_inc_x = ftpriv->active_face->max_advance_width * outl.x_scale; /*TODO: reverse layout (for arabic fonts) and glyph substitution / ligature once openType is in place in freetype*/ bounds->height = 0; count = gf_utf8_wcslen(string); if (count == (size_t) (-1)) return GF_BAD_PARAM; ymin = ymax = 0; for (i=0; i<count; i++) { glyph_idx = FT_Get_Char_Index(ftpriv->active_face, string[i]); /*missing glyph*/ if (!glyph_idx) continue; /*work in design units*/ FT_Load_Glyph(ftpriv->active_face, glyph_idx, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP); FT_Get_Glyph(ftpriv->active_face->glyph, (FT_Glyph*)&outline);#ifdef FT_GLYPH_FORMAT_OUTLINE /*oops not vectorial...*/ if (outline->root.format != FT_GLYPH_FORMAT_OUTLINE) { outl.pos_x += def_inc_x; FT_Done_Glyph((FT_Glyph) outline); continue; }#endif /*freeType is marvelous and gives back the right advance on space char !!!*/ FT_Outline_Decompose(&outline->outline, &ft_outl_funcs, &outl); FT_Glyph_Get_CBox((FT_Glyph) outline, ft_glyph_bbox_unscaled, &bbox); if (ymax < bbox.yMax ) ymax = bbox.yMax ; if (ymin > bbox.yMin) ymin = bbox.yMin; /*update start of bounding box on first char*/ if (!i) bounds->x += bbox.xMin * outl.x_scale; /*take care of last char (may be AFTER last horiz_advanced with certain glyphs)*/ if ((i+1==count) && (bbox.xMax)) { outl.pos_x += bbox.xMax * outl.x_scale; } else { outl.pos_x += ftpriv->active_face->glyph->metrics.horiAdvance * outl.x_scale; } FT_Done_Glyph((FT_Glyph) outline); } bounds->width = outl.pos_x - bounds->x; bounds->height = (ymax - ymin) * outl.y_scale; bounds->y = ymax * outl.y_scale; if (!bounds->height && count) bounds->height = FIX_ONE/1000; /*add underline/strikeout*/ if (ftpriv->strike_style) { Fixed sy; if (ftpriv->strike_style==1) { sy = top - ascent + ftpriv->active_face->underline_position * font_scale; } else { sy = top - 3 * ascent / 4; } gf_path_add_rect_center(path, bounds->x + bounds->width / 2, sy, bounds->width, ftpriv->active_face->underline_thickness * font_scale); } return GF_OK;}GF_FontRaster *FT_Load(){ GF_FontRaster *dr; FTBuilder *ftpriv; dr = malloc(sizeof(GF_FontRaster)); memset(dr, 0, sizeof(GF_FontRaster)); GF_REGISTER_MODULE_INTERFACE(dr, GF_FONT_RASTER_INTERFACE, "FreeType Font Engine", "gpac distribution"); ftpriv = malloc(sizeof(FTBuilder)); memset(ftpriv, 0, sizeof(FTBuilder)); ftpriv->loaded_fonts = gf_list_new(); dr->priv = ftpriv; dr->init_font_engine = ft_init_font_engine; dr->shutdown_font_engine = ft_shutdown_font_engine; dr->set_font = ft_set_font; dr->set_font_size = ft_set_font_size; dr->get_font_metrics = ft_get_font_metrics; dr->get_text_size = ft_get_text_size; dr->add_text_to_path = ft_add_text_to_path; return dr;}void FT_Delete(GF_BaseInterface *ifce){ GF_FontRaster *dr = (GF_FontRaster *) ifce; FTBuilder *ftpriv = dr->priv; if (ftpriv->font_dir) free(ftpriv->font_dir); assert(!gf_list_count(ftpriv->loaded_fonts) ); gf_list_del(ftpriv->loaded_fonts); free(dr->priv); free(dr);}#ifndef GPAC_STANDALONE_RENDER_2DGF_EXPORTBool QueryInterface(u32 InterfaceType) { if (InterfaceType == GF_FONT_RASTER_INTERFACE) return 1; return 0;}GF_EXPORTGF_BaseInterface *LoadInterface(u32 InterfaceType) { if (InterfaceType == GF_FONT_RASTER_INTERFACE) return (GF_BaseInterface *)FT_Load(); return NULL;}GF_EXPORTvoid ShutdownInterface(GF_BaseInterface *ifce){ switch (ifce->InterfaceType) { case GF_FONT_RASTER_INTERFACE: FT_Delete(ifce); break; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -