📄 cairo-ft-font.c
字号:
fs_metrics.x_advance = 0; fs_metrics.y_advance = DOUBLE_FROM_26_6 (advance) * y_factor; } } else { fs_metrics.width = DOUBLE_FROM_26_6 (metrics->width) * x_factor; fs_metrics.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor; if (!vertical_layout) { fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor; fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor; fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor; fs_metrics.y_advance = 0 * y_factor; } else { fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor; fs_metrics.y_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingY) * y_factor; fs_metrics.x_advance = 0 * x_factor; fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor; } } _cairo_scaled_glyph_set_metrics (scaled_glyph, &scaled_font->base, &fs_metrics); } if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) { cairo_image_surface_t *surface; if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { status = _render_glyph_outline (face, &scaled_font->ft_options.base, &surface); } else { status = _render_glyph_bitmap (face, &scaled_font->ft_options.base, &surface); if (status == CAIRO_STATUS_SUCCESS && unscaled->have_shape) status = _transform_glyph_bitmap (&unscaled->current_shape, &surface); } if (status) goto FAIL; _cairo_scaled_glyph_set_surface (scaled_glyph, &scaled_font->base, surface); } if (info & CAIRO_SCALED_GLYPH_INFO_PATH) { cairo_path_fixed_t *path; /* * A kludge -- the above code will trash the outline, * so reload it. This will probably never occur though */ if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) { error = FT_Load_Glyph (face, _cairo_scaled_glyph_index(scaled_glyph), load_flags | FT_LOAD_NO_BITMAP); if (error) { cairo_ft_scaled_font_unlock_face (abstract_font); return CAIRO_STATUS_NO_MEMORY; }#if HAVE_FT_GLYPHSLOT_EMBOLDEN /* * embolden glyphs if requested */ if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN) FT_GlyphSlot_Embolden (glyph);#endif if (vertical_layout) _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (glyph); } if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) status = _decompose_glyph_outline (face, &scaled_font->ft_options.base, &path); else status = CAIRO_INT_STATUS_UNSUPPORTED; if (status) goto FAIL; _cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, path); } FAIL: cairo_ft_scaled_font_unlock_face (abstract_font); return status;}static unsigned long_cairo_ft_ucs4_to_index (void *abstract_font, uint32_t ucs4){ cairo_ft_scaled_font_t *scaled_font = abstract_font; cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; FT_Face face; FT_UInt index; face = _cairo_ft_unscaled_font_lock_face (unscaled); if (!face) return 0; index = FT_Get_Char_Index (face, ucs4); _cairo_ft_unscaled_font_unlock_face (unscaled); return index;}static cairo_int_status_t_cairo_ft_show_glyphs (void *abstract_font, cairo_operator_t op, cairo_pattern_t *pattern, cairo_surface_t *surface, int source_x, int source_y, int dest_x, int dest_y, unsigned int width, unsigned int height, const cairo_glyph_t *glyphs, int num_glyphs){ return CAIRO_INT_STATUS_UNSUPPORTED;}const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = { CAIRO_FONT_TYPE_FT, _cairo_ft_scaled_font_create_toy, _cairo_ft_scaled_font_fini, _cairo_ft_scaled_glyph_init, NULL, /* text_to_glyphs */ _cairo_ft_ucs4_to_index, _cairo_ft_show_glyphs,};/* cairo_ft_font_face_t */static void_cairo_ft_font_face_destroy (void *abstract_face){ cairo_ft_font_face_t *font_face = abstract_face; cairo_ft_font_face_t *tmp_face = NULL; cairo_ft_font_face_t *last_face = NULL; if (font_face == NULL) return; /* When destroying the face created by cairo_ft_font_face_create_for_ft_face, * we have a special "zombie" state for the face when the unscaled font * is still alive but there are no public references to the font face. * * We go from: * * font_face ------> unscaled * <-....weak....../ * * To: * * font_face <------- unscaled */ if (font_face->unscaled && font_face->unscaled->from_face && font_face->unscaled->base.ref_count > 1) { cairo_font_face_reference (&font_face->base); _cairo_unscaled_font_destroy (&font_face->unscaled->base); font_face->unscaled = NULL; return; } if (font_face->unscaled) { /* Remove face from linked list */ for (tmp_face = font_face->unscaled->faces; tmp_face; tmp_face = tmp_face->next) { if (tmp_face == font_face) { if (last_face) last_face->next = tmp_face->next; else font_face->unscaled->faces = tmp_face->next; } last_face = tmp_face; } _cairo_unscaled_font_destroy (&font_face->unscaled->base); font_face->unscaled = NULL; }}static cairo_status_t_cairo_ft_font_face_scaled_font_create (void *abstract_face, const cairo_matrix_t *font_matrix, const cairo_matrix_t *ctm, const cairo_font_options_t *options, cairo_scaled_font_t **scaled_font){ cairo_ft_font_face_t *font_face = abstract_face; cairo_ft_options_t ft_options; /* The handling of font options is different depending on how the * font face was created. When the user creates a font face with * cairo_ft_font_face_create_for_ft_face(), then the load flags * passed in augment the load flags for the options. But for * cairo_ft_font_face_create_for_pattern(), the load flags are * derived from a pattern where the user has called * cairo_ft_font_options_substitute(), so *just* use those load * flags and ignore the options. */ ft_options = font_face->ft_options; *scaled_font = _cairo_ft_scaled_font_create (font_face->unscaled, &font_face->base, font_matrix, ctm, options, ft_options); if (*scaled_font) return CAIRO_STATUS_SUCCESS; else return CAIRO_STATUS_NO_MEMORY;}static const cairo_font_face_backend_t _cairo_ft_font_face_backend = { CAIRO_FONT_TYPE_FT, _cairo_ft_font_face_destroy, _cairo_ft_font_face_scaled_font_create};static cairo_font_face_t *_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled, cairo_ft_options_t ft_options){ cairo_ft_font_face_t *font_face; /* Looked for an existing matching font face */ for (font_face = unscaled->faces; font_face; font_face = font_face->next) { if (font_face->ft_options.load_flags == ft_options.load_flags && font_face->ft_options.extra_flags == ft_options.extra_flags && cairo_font_options_equal (&font_face->ft_options.base, &ft_options.base)) return cairo_font_face_reference (&font_face->base); } /* No match found, create a new one */ font_face = malloc (sizeof (cairo_ft_font_face_t)); if (!font_face) return NULL; font_face->unscaled = unscaled; _cairo_unscaled_font_reference (&unscaled->base); font_face->ft_options = ft_options; font_face->next = unscaled->faces; unscaled->faces = font_face; _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend); return &font_face->base;}/* implement the platform-specific interface *//** * cairo_ft_font_options_substitute: * @options: a #cairo_font_options_t object * @pattern: an existing #FcPattern * * Add options to a #FcPattern based on a #cairo_font_options_t font * options object. Options that are already in the pattern, are not overriden, * so you should call this function after calling FcConfigSubstitute() (the * user's settings should override options based on the surface type), but * before calling FcDefaultSubstitute(). **/voidcairo_ft_font_options_substitute (const cairo_font_options_t *options, FcPattern *pattern){ FcValue v; if (options->antialias != CAIRO_ANTIALIAS_DEFAULT) { if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch) { FcPatternAddBool (pattern, FC_ANTIALIAS, options->antialias != CAIRO_ANTIALIAS_NONE); } } if (options->antialias != CAIRO_ANTIALIAS_DEFAULT) { if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch) { int rgba; if (options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) { switch (options->subpixel_order) { case CAIRO_SUBPIXEL_ORDER_DEFAULT: case CAIRO_SUBPIXEL_ORDER_RGB: default: rgba = FC_RGBA_RGB; break; case CAIRO_SUBPIXEL_ORDER_BGR: rgba = FC_RGBA_BGR; break; case CAIRO_SUBPIXEL_ORDER_VRGB: rgba = FC_RGBA_VRGB; break; case CAIRO_SUBPIXEL_ORDER_VBGR: rgba = FC_RGBA_VBGR; break; } } else { rgba = FC_RGBA_NONE; } FcPatternAddInteger (pattern, FC_RGBA, rgba); } } if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT) { if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch) { FcPatternAddBool (pattern, FC_HINTING, options->hint_style != CAIRO_HINT_STYLE_NONE); }#ifdef FC_HINT_STYLE if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch) { int hint_style; switch (options->hint_style) { case CAIRO_HINT_STYLE_SLIGHT: hint_style = FC_HINT_SLIGHT; break; case CAIRO_HINT_STYLE_MEDIUM: hint_style = FC_HINT_MEDIUM; break; case CAIRO_HINT_STYLE_FULL: default: hint_style = FC_HINT_FULL; break; } FcPatternAddInteger (pattern, FC_HINT_STYLE, hint_style); }#endif }}/** * cairo_ft_font_face_create_for_pattern: * @pattern: A fully resolved fontconfig * pattern. A pattern can be resolved, by, among other things, calling * FcConfigSubstitute(), FcDefaultSubstitute(), then * FcFontMatch(). Cairo will call FcPatternReference() on this * pattern, so you should not further modify the pattern, but you can * release your reference to the pattern with FcPatternDestroy() if * you no longer need to access it. * * Creates a new font face for the FreeType font backend based on a * fontconfig pattern. This font can then be used with * cairo_set_font_face() or cairo_scaled_font_create(). The * #cairo_scaled_font_t returned from cairo_scaled_font_create() is * also for the FreeType backend and can be used with functions such * as cairo_ft_font_lock_face(). * * Font rendering options are representated both here and when you * call cairo_scaled_font_create(). Font options that have a representation * in a #FcPattern must be passed in here; to modify #FcPattern * appropriately to reflect the options in a #cairo_font_options_t, call * cairo_ft_font_options_substitute(). * * Return value: a newly created #cairo_font_face_t. Free with * cairo_font_face_destroy() when you are done using it. **/cairo_font_face_t *cairo_ft_font_face_create_for_pattern (FcPattern *pattern){ cairo_ft_unscaled_font_t *unscaled; cairo_font_face_t *font_face; unscaled = _cairo_ft_unscaled_font_create_for_pattern (pattern); if (unscaled == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_font_face_t *)&_cairo_font_face_nil; } font_face = _cairo_ft_font_face_create (unscaled, _get_pattern_ft_options (pattern)); _cairo_unscaled_font_destroy (&unscaled->base); if (font_face) return font_face; else { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_font_face_t *)&_cairo_font_face_nil; }}/** * cairo_ft_font_face_create_for_ft_face: * @face: A FreeType face object, already opened. This must * be kept around until the face's ref_count drops to * zero and it is freed. Since the face may be referenced * internally to Cairo, the best way to determine when it * is safe to free the face is to pass a * #cairo_destroy_func_t to cairo_font_face_set_user_data() * @load_flags: flags to pass to FT_Load_Glyph when loading * glyphs from the font. These flags are OR'ed together with * the flags derived from the #cairo_font_options_t passed * to cairo_scaled_font_create(), so only a few values such * as %FT_LOAD_VERTICAL_LAYOUT, and %FT_LOAD_FORCE_AUTOHINT * are useful. You should not pass any of the flags affecting * the load target, such as %FT_LOAD_TARGET_LIGHT. * * Creates a new font face for the FreeType font backend from a * pre-opened FreeType face. This font can then be used with * cairo_set_font_face() or cairo_scaled_font_create(). The * #cairo_scaled_font_t returned from cairo_scaled_font_create() is * also for the FreeType backend and can be used with functions such * as cairo_ft_font_lock_face(). * * Return value: a newly created #cairo_font_face_t. Free with * cairo_font_face_destroy() when you are done using it. **/cairo_font_face_t *cairo_ft_font_face_create_for_ft_face (FT_Face face, int load_flags){ cairo_ft_unscaled_font_t *unscaled; cairo_font_face_t *font_face; cairo_ft_options_t ft_options; unscaled = _cairo_ft_unscaled_font_create_from_face (face); if (unscaled == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_font_face_t *)&_cairo_font_face_nil; } ft_options.load_flags = load_flags; ft_options.extra_flags = 0; _cairo_font_options_init_default (&ft_options.base); font_face = _cairo_ft_font_face_create (unscaled, ft_options); _cairo_unscaled_font_destroy (&unscaled->base); if (font_face) { return font_face; } else { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_font_face_t *)&_cairo_font_face_nil; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -