📄 pangocairo-font.c
字号:
mini_size = size / 2.4; if (is_hinted) { mini_size = HINT_Y (mini_size); if (mini_size < 5.0) { rows = 1; mini_size = MIN (MAX (size - 1, 0), 5.0); } } pango_font_description_set_absolute_size (desc, pango_units_from_double (mini_size)); /* load mini_font */ context = pango_cairo_font_map_create_context ((PangoCairoFontMap *) (fontmap)); pango_context_set_matrix (context, &pango_ctm); pango_context_set_language (context, pango_script_get_sample_language (PANGO_SCRIPT_LATIN)); pango_cairo_context_set_font_options (context, font_options); mini_font = pango_font_map_load_font (fontmap, context, desc); g_object_unref (context); } pango_font_description_free (desc); cairo_font_options_destroy (font_options); scaled_mini_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *) mini_font); for (i = 0 ; i < 16 ; i++) { cairo_text_extents_t extents; c[0] = hexdigits[i]; cairo_scaled_font_text_extents (scaled_mini_font, c, &extents); width = MAX (width, extents.width); height = MAX (height, extents.height); } cairo_scaled_font_extents (scaled_font, &font_extents); if (font_extents.ascent + font_extents.descent <= 0) { font_extents.ascent = PANGO_UNKNOWN_GLYPH_HEIGHT; font_extents.descent = 0; } pad = (font_extents.ascent + font_extents.descent) / 43; pad = MIN (pad, mini_size); hbi = g_slice_new (PangoCairoFontHexBoxInfo); hbi->font = (PangoCairoFont *) mini_font; hbi->rows = rows; hbi->digit_width = width; hbi->digit_height = height; hbi->pad_x = pad; hbi->pad_y = pad; if (is_hinted) { hbi->digit_width = HINT_X (hbi->digit_width); hbi->digit_height = HINT_Y (hbi->digit_height); hbi->pad_x = HINT_X (hbi->pad_x); hbi->pad_y = HINT_Y (hbi->pad_y); } hbi->line_width = MIN (hbi->pad_x, hbi->pad_y); hbi->box_height = 3 * hbi->pad_y + rows * (hbi->pad_y + hbi->digit_height); if (rows == 1 || hbi->box_height <= font_extents.ascent) { hbi->box_descent = 2 * hbi->pad_y; } else if (hbi->box_height <= font_extents.ascent + font_extents.descent - 2 * hbi->pad_y) { hbi->box_descent = 2 * hbi->pad_y + hbi->box_height - font_extents.ascent; } else { hbi->box_descent = font_extents.descent * hbi->box_height / (font_extents.ascent + font_extents.descent); } if (is_hinted) { hbi->box_descent = HINT_Y (hbi->box_descent); } cf_priv->hbi = hbi; return hbi;}static void_pango_cairo_font_hex_box_info_destroy (PangoCairoFontHexBoxInfo *hbi){ if (hbi) { g_object_unref (hbi->font); g_slice_free (PangoCairoFontHexBoxInfo, hbi); }}PangoCairoFontHexBoxInfo *_pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont){ PangoCairoFontPrivate *cf_priv = PANGO_CAIRO_FONT_PRIVATE (cfont); return _pango_cairo_font_private_get_hex_box_info (cf_priv);}void_pango_cairo_font_private_initialize (PangoCairoFontPrivate *cf_priv, PangoCairoFont *cfont, PangoContext *context, const PangoFontDescription *desc, const cairo_matrix_t *font_matrix){ const cairo_font_options_t *font_options; cairo_matrix_t gravity_matrix; const PangoMatrix *pango_ctm; cf_priv->cfont = cfont; cf_priv->gravity = pango_font_description_get_gravity (desc); cf_priv->data = _pango_cairo_font_private_scaled_font_data_create (); /* first apply gravity rotation, then font_matrix, such that * vertical italic text comes out "correct". we don't do anything * like baseline adjustment etc though. should be specially * handled when we support italic correction. */ cairo_matrix_init_rotate(&gravity_matrix, pango_gravity_to_rotation (cf_priv->gravity)); cairo_matrix_multiply (&cf_priv->data->font_matrix, font_matrix, &gravity_matrix); pango_ctm = pango_context_get_matrix (context); if (pango_ctm) cairo_matrix_init (&cf_priv->data->ctm, pango_ctm->xx, pango_ctm->yx, pango_ctm->xy, pango_ctm->yy, 0., 0.); else cairo_matrix_init_identity (&cf_priv->data->ctm); font_options = _pango_cairo_context_get_merged_font_options (context); cf_priv->data->options = cairo_font_options_copy (font_options); cf_priv->is_hinted = cairo_font_options_get_hint_metrics (font_options) != CAIRO_HINT_METRICS_OFF; cf_priv->scaled_font = NULL; cf_priv->hbi = NULL; cf_priv->glyph_extents_cache = NULL; cf_priv->metrics_by_lang = NULL;}static voidfree_metrics_info (PangoCairoFontMetricsInfo *info){ pango_font_metrics_unref (info->metrics); g_slice_free (PangoCairoFontMetricsInfo, info);}void_pango_cairo_font_private_finalize (PangoCairoFontPrivate *cf_priv){ _pango_cairo_font_private_scaled_font_data_destroy (cf_priv->data); if (cf_priv->scaled_font) cairo_scaled_font_destroy (cf_priv->scaled_font); _pango_cairo_font_hex_box_info_destroy (cf_priv->hbi); if (cf_priv->glyph_extents_cache) g_free (cf_priv->glyph_extents_cache); g_slist_foreach (cf_priv->metrics_by_lang, (GFunc)free_metrics_info, NULL); g_slist_free (cf_priv->metrics_by_lang);}gboolean_pango_cairo_font_private_is_metrics_hinted (PangoCairoFontPrivate *cf_priv){ return cf_priv->is_hinted;}static void_pango_cairo_font_private_get_glyph_extents_missing (PangoCairoFontPrivate *cf_priv, PangoGlyph glyph, PangoRectangle *ink_rect, PangoRectangle *logical_rect){ PangoCairoFontHexBoxInfo *hbi; gunichar ch; gint rows, cols; hbi = _pango_cairo_font_private_get_hex_box_info (cf_priv); if (!hbi) { pango_font_get_glyph_extents (NULL, glyph, ink_rect, logical_rect); return; } ch = glyph & ~PANGO_GLYPH_UNKNOWN_FLAG; rows = hbi->rows; if (G_UNLIKELY (glyph == PANGO_GLYPH_INVALID_INPUT || ch > 0x10FFFF)) cols = 1; else cols = ((glyph & ~PANGO_GLYPH_UNKNOWN_FLAG) > 0xffff ? 6 : 4) / rows; if (ink_rect) { ink_rect->x = PANGO_SCALE * hbi->pad_x; ink_rect->y = PANGO_SCALE * (hbi->box_descent - hbi->box_height); ink_rect->width = PANGO_SCALE * (3 * hbi->pad_x + cols * (hbi->digit_width + hbi->pad_x)); ink_rect->height = PANGO_SCALE * hbi->box_height; } if (logical_rect) { logical_rect->x = 0; logical_rect->y = PANGO_SCALE * (hbi->box_descent - (hbi->box_height + hbi->pad_y)); logical_rect->width = PANGO_SCALE * (5 * hbi->pad_x + cols * (hbi->digit_width + hbi->pad_x)); logical_rect->height = PANGO_SCALE * (hbi->box_height + 2 * hbi->pad_y); }}#define GLYPH_CACHE_NUM_ENTRIES 256 /* should be power of two */#define GLYPH_CACHE_MASK (GLYPH_CACHE_NUM_ENTRIES - 1)/* An entry in the fixed-size cache for the glyph->extents mapping. * The cache is indexed by the lower N bits of the glyph (see * GLYPH_CACHE_NUM_ENTRIES). For scripts with few glyphs, * this should provide pretty much instant lookups. */struct _PangoCairoFontGlyphExtentsCacheEntry{ PangoGlyph glyph; int width; PangoRectangle ink_rect;};static gboolean_pango_cairo_font_private_glyph_extents_cache_init (PangoCairoFontPrivate *cf_priv){ cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (cf_priv); cairo_font_extents_t font_extents; if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS)) return FALSE; cairo_scaled_font_extents (scaled_font, &font_extents); cf_priv->font_extents.x = 0; cf_priv->font_extents.width = 0; cf_priv->font_extents.height = pango_units_from_double (font_extents.ascent + font_extents.descent); switch (cf_priv->gravity) { default: case PANGO_GRAVITY_AUTO: case PANGO_GRAVITY_SOUTH: cf_priv->font_extents.y = - pango_units_from_double (font_extents.ascent); break; case PANGO_GRAVITY_NORTH: cf_priv->font_extents.y = - pango_units_from_double (font_extents.descent); break; case PANGO_GRAVITY_EAST: case PANGO_GRAVITY_WEST: { int ascent = pango_units_from_double (font_extents.ascent + font_extents.descent) / 2; if (cf_priv->is_hinted) ascent = PANGO_UNITS_ROUND (ascent); cf_priv->font_extents.y = - ascent; } } cf_priv->glyph_extents_cache = g_new0 (PangoCairoFontGlyphExtentsCacheEntry, GLYPH_CACHE_NUM_ENTRIES); /* Make sure all cache entries are invalid initially */ cf_priv->glyph_extents_cache[0].glyph = 1; /* glyph 1 cannot happen in bucket 0 */ return TRUE;}/* Fills in the glyph extents cache entry */static voidcompute_glyph_extents (PangoCairoFontPrivate *cf_priv, PangoGlyph glyph, PangoCairoFontGlyphExtentsCacheEntry *entry){ cairo_text_extents_t extents; cairo_glyph_t cairo_glyph; cairo_glyph.index = glyph; cairo_glyph.x = 0; cairo_glyph.y = 0; cairo_scaled_font_glyph_extents (_pango_cairo_font_private_get_scaled_font (cf_priv), &cairo_glyph, 1, &extents); entry->glyph = glyph; entry->width = pango_units_from_double (extents.x_advance); entry->ink_rect.x = pango_units_from_double (extents.x_bearing); entry->ink_rect.y = pango_units_from_double (extents.y_bearing); entry->ink_rect.width = pango_units_from_double (extents.width); entry->ink_rect.height = pango_units_from_double (extents.height);}static PangoCairoFontGlyphExtentsCacheEntry *_pango_cairo_font_private_get_glyph_extents_cache_entry (PangoCairoFontPrivate *cf_priv, PangoGlyph glyph){ PangoCairoFontGlyphExtentsCacheEntry *entry; guint idx; idx = glyph & GLYPH_CACHE_MASK; entry = cf_priv->glyph_extents_cache + idx; if (entry->glyph != glyph) { compute_glyph_extents (cf_priv, glyph, entry); } return entry;}void_pango_cairo_font_private_get_glyph_extents (PangoCairoFontPrivate *cf_priv, PangoGlyph glyph, PangoRectangle *ink_rect, PangoRectangle *logical_rect){ PangoCairoFontGlyphExtentsCacheEntry *entry; if (!cf_priv || (cf_priv->glyph_extents_cache == NULL && !_pango_cairo_font_private_glyph_extents_cache_init (cf_priv))) { /* Get generic unknown-glyph extents. */ pango_font_get_glyph_extents (NULL, glyph, ink_rect, logical_rect); return; } if (glyph == PANGO_GLYPH_EMPTY) { if (ink_rect) ink_rect->x = ink_rect->y = ink_rect->width = ink_rect->height = 0; if (logical_rect) *logical_rect = cf_priv->font_extents; return; } else if (glyph & PANGO_GLYPH_UNKNOWN_FLAG) { _pango_cairo_font_private_get_glyph_extents_missing(cf_priv, glyph, ink_rect, logical_rect); return; } entry = _pango_cairo_font_private_get_glyph_extents_cache_entry (cf_priv, glyph); if (ink_rect) *ink_rect = entry->ink_rect; if (logical_rect) { *logical_rect = cf_priv->font_extents; logical_rect->width = entry->width; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -