📄 cairo-ft-font.c
字号:
static cairo_scaled_font_t *_cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled, cairo_font_face_t *font_face, const cairo_matrix_t *font_matrix, const cairo_matrix_t *ctm, const cairo_font_options_t *options, cairo_ft_options_t ft_options){ cairo_ft_scaled_font_t *scaled_font = NULL; FT_Face face; FT_Size_Metrics *metrics; cairo_font_extents_t fs_metrics; face = _cairo_ft_unscaled_font_lock_face (unscaled); if (!face) return NULL; scaled_font = malloc (sizeof(cairo_ft_scaled_font_t)); if (scaled_font == NULL) { _cairo_ft_unscaled_font_unlock_face (unscaled); return NULL; } _cairo_unscaled_font_reference (&unscaled->base); scaled_font->unscaled = unscaled; if (options->hint_metrics != CAIRO_HINT_METRICS_OFF) ft_options.extra_flags |= CAIRO_FT_OPTIONS_HINT_METRICS; _cairo_font_options_init_copy (&scaled_font->ft_options.base, options); _cairo_ft_options_merge (&scaled_font->ft_options, &ft_options); _cairo_scaled_font_init (&scaled_font->base, font_face, font_matrix, ctm, options, &cairo_ft_scaled_font_backend); _cairo_ft_unscaled_font_set_scale (unscaled, &scaled_font->base.scale); metrics = &face->size->metrics; /* * Get to unscaled metrics so that the upper level can get back to * user space */ if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) { double x_factor, y_factor; if (unscaled->x_scale == 0) x_factor = 0; else x_factor = 1 / unscaled->x_scale; if (unscaled->y_scale == 0) y_factor = 0; else y_factor = 1 / unscaled->y_scale; fs_metrics.ascent = DOUBLE_FROM_26_6(metrics->ascender) * y_factor; fs_metrics.descent = DOUBLE_FROM_26_6(- metrics->descender) * y_factor; fs_metrics.height = DOUBLE_FROM_26_6(metrics->height) * y_factor; if (!(scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)) { fs_metrics.max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) * x_factor; fs_metrics.max_y_advance = 0; } else { fs_metrics.max_x_advance = 0; fs_metrics.max_y_advance = DOUBLE_FROM_26_6(metrics->max_advance) * y_factor; } } else { double scale = face->units_per_EM; fs_metrics.ascent = face->ascender / scale; fs_metrics.descent = - face->descender / scale; fs_metrics.height = face->height / scale; if (!(scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)) { fs_metrics.max_x_advance = face->max_advance_width / scale; fs_metrics.max_y_advance = 0; } else { fs_metrics.max_x_advance = 0; fs_metrics.max_y_advance = face->max_advance_height / scale; } } _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics); return &scaled_font->base;}cairo_bool_t_cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font){ return scaled_font->backend == &cairo_ft_scaled_font_backend;}static cairo_status_t_cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face, const cairo_matrix_t *font_matrix, const cairo_matrix_t *ctm, const cairo_font_options_t *font_options, cairo_scaled_font_t **font){ FcPattern *pattern, *resolved; cairo_ft_unscaled_font_t *unscaled; cairo_scaled_font_t *new_font = NULL; FcResult result; int fcslant; int fcweight; cairo_matrix_t scale; cairo_ft_font_transform_t sf; cairo_ft_options_t ft_options; unsigned char *family = (unsigned char*) toy_face->family; pattern = FcPatternCreate (); if (!pattern) return CAIRO_STATUS_NO_MEMORY; switch (toy_face->weight) { case CAIRO_FONT_WEIGHT_BOLD: fcweight = FC_WEIGHT_BOLD; break; case CAIRO_FONT_WEIGHT_NORMAL: default: fcweight = FC_WEIGHT_MEDIUM; break; } switch (toy_face->slant) { case CAIRO_FONT_SLANT_ITALIC: fcslant = FC_SLANT_ITALIC; break; case CAIRO_FONT_SLANT_OBLIQUE: fcslant = FC_SLANT_OBLIQUE; break; case CAIRO_FONT_SLANT_NORMAL: default: fcslant = FC_SLANT_ROMAN; break; } if (!FcPatternAddString (pattern, FC_FAMILY, family)) goto FREE_PATTERN; if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant)) goto FREE_PATTERN; if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight)) goto FREE_PATTERN; cairo_matrix_multiply (&scale, font_matrix, ctm); _compute_transform (&sf, &scale); FcPatternAddInteger (pattern, FC_PIXEL_SIZE, sf.y_scale); FcConfigSubstitute (NULL, pattern, FcMatchPattern); cairo_ft_font_options_substitute (font_options, pattern); FcDefaultSubstitute (pattern); resolved = FcFontMatch (NULL, pattern, &result); if (!resolved) goto FREE_PATTERN; unscaled = _cairo_ft_unscaled_font_create_for_pattern (resolved); if (!unscaled) goto FREE_RESOLVED; ft_options = _get_pattern_ft_options (resolved); new_font = _cairo_ft_scaled_font_create (unscaled, &toy_face->base, font_matrix, ctm, font_options, ft_options); _cairo_unscaled_font_destroy (&unscaled->base); FREE_RESOLVED: FcPatternDestroy (resolved); FREE_PATTERN: FcPatternDestroy (pattern); if (new_font) { *font = new_font; return CAIRO_STATUS_SUCCESS; } else { return CAIRO_STATUS_NO_MEMORY; }}static void_cairo_ft_scaled_font_fini (void *abstract_font){ cairo_ft_scaled_font_t *scaled_font = abstract_font; if (scaled_font == NULL) return; _cairo_unscaled_font_destroy (&scaled_font->unscaled->base);}static int_move_to (FT_Vector *to, void *closure){ cairo_path_fixed_t *path = closure; cairo_fixed_t x, y; x = _cairo_fixed_from_26_6 (to->x); y = _cairo_fixed_from_26_6 (to->y); _cairo_path_fixed_close_path (path); _cairo_path_fixed_move_to (path, x, y); return 0;}static int_line_to (FT_Vector *to, void *closure){ cairo_path_fixed_t *path = closure; cairo_fixed_t x, y; x = _cairo_fixed_from_26_6 (to->x); y = _cairo_fixed_from_26_6 (to->y); _cairo_path_fixed_line_to (path, x, y); return 0;}static int_conic_to (FT_Vector *control, FT_Vector *to, void *closure){ cairo_path_fixed_t *path = closure; cairo_fixed_t x0, y0; cairo_fixed_t x1, y1; cairo_fixed_t x2, y2; cairo_fixed_t x3, y3; cairo_point_t conic; _cairo_path_fixed_get_current_point (path, &x0, &y0); conic.x = _cairo_fixed_from_26_6 (control->x); conic.y = _cairo_fixed_from_26_6 (control->y); x3 = _cairo_fixed_from_26_6 (to->x); y3 = _cairo_fixed_from_26_6 (to->y); x1 = x0 + 2.0/3.0 * (conic.x - x0); y1 = y0 + 2.0/3.0 * (conic.y - y0); x2 = x3 + 2.0/3.0 * (conic.x - x3); y2 = y3 + 2.0/3.0 * (conic.y - y3); _cairo_path_fixed_curve_to (path, x1, y1, x2, y2, x3, y3); return 0;}static int_cubic_to (FT_Vector *control1, FT_Vector *control2, FT_Vector *to, void *closure){ cairo_path_fixed_t *path = closure; cairo_fixed_t x0, y0; cairo_fixed_t x1, y1; cairo_fixed_t x2, y2; x0 = _cairo_fixed_from_26_6 (control1->x); y0 = _cairo_fixed_from_26_6 (control1->y); x1 = _cairo_fixed_from_26_6 (control2->x); y1 = _cairo_fixed_from_26_6 (control2->y); x2 = _cairo_fixed_from_26_6 (to->x); y2 = _cairo_fixed_from_26_6 (to->y); _cairo_path_fixed_curve_to (path, x0, y0, x1, y1, x2, y2); return 0;}static cairo_status_t_decompose_glyph_outline (FT_Face face, cairo_font_options_t *options, cairo_path_fixed_t **pathp){ static const FT_Outline_Funcs outline_funcs = { (FT_Outline_MoveToFunc)_move_to, (FT_Outline_LineToFunc)_line_to, (FT_Outline_ConicToFunc)_conic_to, (FT_Outline_CubicToFunc)_cubic_to, 0, /* shift */ 0, /* delta */ }; static const FT_Matrix invert_y = { DOUBLE_TO_16_16 (1.0), 0, 0, DOUBLE_TO_16_16 (-1.0), }; FT_GlyphSlot glyph; cairo_path_fixed_t *path; path = _cairo_path_fixed_create (); if (!path) return CAIRO_STATUS_NO_MEMORY; glyph = face->glyph; /* Font glyphs have an inverted Y axis compared to cairo. */ FT_Outline_Transform (&glyph->outline, &invert_y); FT_Outline_Decompose (&glyph->outline, &outline_funcs, path); _cairo_path_fixed_close_path (path); *pathp = path; return CAIRO_STATUS_SUCCESS;}/* * Translate glyph to match its metrics. */static void_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (FT_GlyphSlot glyph){ FT_Pos x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX; FT_Pos y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY; if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) FT_Outline_Translate(&glyph->outline, x, y); else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { glyph->bitmap_left += x / 64; glyph->bitmap_top += y / 64; }}static cairo_int_status_t_cairo_ft_scaled_glyph_init (void *abstract_font, cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_glyph_info_t info){ cairo_text_extents_t fs_metrics; cairo_ft_scaled_font_t *scaled_font = abstract_font; cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; FT_GlyphSlot glyph; FT_Face face; FT_Error error; int load_flags = scaled_font->ft_options.load_flags; FT_Glyph_Metrics *metrics; double x_factor, y_factor; cairo_bool_t vertical_layout = FALSE; cairo_status_t status = CAIRO_STATUS_SUCCESS; face = cairo_ft_scaled_font_lock_face (abstract_font); if (!face) return CAIRO_STATUS_NO_MEMORY; /* Ignore global advance unconditionally */ load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 && (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0) load_flags |= FT_LOAD_NO_BITMAP; /* * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as * suggested by freetype people. */ if (load_flags & FT_LOAD_VERTICAL_LAYOUT) { load_flags &= ~FT_LOAD_VERTICAL_LAYOUT; vertical_layout = TRUE; } error = FT_Load_Glyph (scaled_font->unscaled->face, _cairo_scaled_glyph_index(scaled_glyph), load_flags); if (error) { status = CAIRO_STATUS_NO_MEMORY; goto FAIL; } glyph = face->glyph;#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 (info & CAIRO_SCALED_GLYPH_INFO_METRICS) { /* * Compute font-space metrics */ metrics = &glyph->metrics; if (unscaled->x_scale == 0) x_factor = 0; else x_factor = 1 / unscaled->x_scale; if (unscaled->y_scale == 0) y_factor = 0; else y_factor = 1 / unscaled->y_scale; /* * Note: the font's coordinate system is upside down from ours, so the * Y coordinates of the bearing and advance need to be negated. * * Scale metrics back to glyph space from the scaled glyph space returned * by FreeType * * If we want hinted metrics but aren't asking for hinted glyphs from * FreeType, then we need to do the metric hinting ourselves. */ if ((scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) && (load_flags & FT_LOAD_NO_HINTING)) { FT_Pos x1, x2; FT_Pos y1, y2; FT_Pos advance; if (!vertical_layout) { x1 = (metrics->horiBearingX) & -64; x2 = (metrics->horiBearingX + metrics->width + 63) & -64; y1 = (-metrics->horiBearingY) & -64; y2 = (-metrics->horiBearingY + metrics->height + 63) & -64; advance = ((metrics->horiAdvance + 32) & -64); fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor; fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor; fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor; fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor; fs_metrics.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor; fs_metrics.y_advance = 0; } else { x1 = (metrics->vertBearingX) & -64; x2 = (metrics->vertBearingX + metrics->width + 63) & -64; y1 = (metrics->vertBearingY) & -64; y2 = (metrics->vertBearingY + metrics->height + 63) & -64; advance = ((metrics->vertAdvance + 32) & -64); fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor; fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor; fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor; fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -