static PangoFontMetrics * create_metrics_for_context (PangoFont *font, PangoContext *context) { PangoCairoWin32Font *cwfont = PANGO_CAIRO_WIN32_FONT (font); PangoFontMetrics *metrics; PangoFontDescription *font_desc; PangoLayout *layout; PangoRectangle extents; PangoLanguage *language = pango_context_get_language (context); const char *sample_str = pango_language_get_sample_string (language); cairo_scaled_font_t *scaled_font; cairo_font_extents_t font_extents; double height; metrics = pango_font_metrics_new (); scaled_font = pango_cairo_win32_font_get_scaled_font (PANGO_CAIRO_FONT (cwfont)); cairo_scaled_font_extents (scaled_font, &font_extents); cairo_win32_scaled_font_done_font (scaled_font); metrics->ascent = font_extents.ascent * PANGO_SCALE; metrics->descent = font_extents.descent * PANGO_SCALE; /* FIXME: Should get the real settings for these from the TrueType * font file. */ height = metrics->ascent + metrics->descent; metrics->underline_thickness = height / 14; metrics->underline_position = - metrics->underline_thickness; metrics->strikethrough_thickness = metrics->underline_thickness; metrics->strikethrough_position = height / 4; pango_quantize_line_geometry (&metrics->underline_thickness, &metrics->underline_position); pango_quantize_line_geometry (&metrics->strikethrough_thickness, &metrics->strikethrough_position); layout = pango_layout_new (context); font_desc = pango_font_describe_with_absolute_size (font); pango_layout_set_font_description (layout, font_desc); pango_layout_set_text (layout, sample_str, -1); pango_layout_get_extents (layout, NULL, &extents); metrics->approximate_char_width = extents.width / g_utf8_strlen (sample_str, -1); pango_layout_set_text (layout, "0123456789", -1); metrics->approximate_digit_width = max_glyph_width (layout); pango_font_description_free (font_desc); g_object_unref (layout); return metrics; }
static PangoFontMetrics * pango_cairo_win32_font_get_metrics (PangoFont *font, PangoLanguage *language) { PangoWin32Font *win32font = PANGO_WIN32_FONT (font); PangoCairoWin32Font *cwfont = PANGO_CAIRO_WIN32_FONT (font); PangoWin32MetricsInfo *info = NULL; /* Quiet gcc */ GSList *tmp_list; const char *sample_str = pango_language_get_sample_string (language); tmp_list = cwfont->metrics_by_lang; while (tmp_list) { info = tmp_list->data; if (info->sample_str == sample_str) /* We _don't_ need strcmp */ break; tmp_list = tmp_list->next; } if (!tmp_list) { PangoContext *context; if (!win32font->fontmap) return pango_font_metrics_new (); info = g_slice_new0 (PangoWin32MetricsInfo); cwfont->metrics_by_lang = g_slist_prepend (cwfont->metrics_by_lang, info); info->sample_str = sample_str; context = pango_context_new (); pango_context_set_font_map (context, win32font->fontmap); pango_context_set_language (context, language); pango_cairo_context_set_font_options (context, cwfont->options); info->metrics = create_metrics_for_context (font, context); g_object_unref (context); } return pango_font_metrics_ref (info->metrics); }
static PangoFontMetrics * pango_cairo_core_text_font_create_base_metrics_for_context (PangoCairoFont *font, PangoContext *context) { PangoCoreTextFont *cfont = (PangoCoreTextFont *) font; PangoFontMetrics *metrics; PangoFontDescription *font_desc; PangoLayout *layout; PangoRectangle extents; PangoLanguage *language = pango_context_get_language (context); const char *sample_str = pango_language_get_sample_string (language); CTFontRef ctfont; metrics = pango_font_metrics_new (); ctfont = pango_core_text_font_get_ctfont (cfont); metrics->ascent = CTFontGetAscent (ctfont) * PANGO_SCALE; metrics->descent = CTFontGetDescent (ctfont) * PANGO_SCALE; metrics->underline_position = CTFontGetUnderlinePosition (ctfont) * PANGO_SCALE; metrics->underline_thickness = CTFontGetUnderlineThickness (ctfont) * PANGO_SCALE; metrics->strikethrough_position = metrics->ascent / 3; metrics->strikethrough_thickness = CTFontGetUnderlineThickness (ctfont) * PANGO_SCALE; layout = pango_layout_new (context); font_desc = pango_font_describe_with_absolute_size ((PangoFont *) font); pango_layout_set_font_description (layout, font_desc); pango_layout_set_text (layout, sample_str, -1); pango_layout_get_extents (layout, NULL, &extents); metrics->approximate_char_width = extents.width / pango_utf8_strwidth (sample_str); pango_layout_set_text (layout, "0123456789", -1); metrics->approximate_digit_width = max_glyph_width (layout); pango_font_description_free (font_desc); g_object_unref (layout); return metrics; }
PangoFontMetrics * _pango_cairo_font_get_metrics (PangoFont *font, PangoLanguage *language) { PangoCairoFont *cfont = (PangoCairoFont *) font; PangoCairoFontPrivate *cf_priv = PANGO_CAIRO_FONT_PRIVATE (font); PangoCairoFontMetricsInfo *info = NULL; /* Quiet gcc */ GSList *tmp_list; const char *sample_str = pango_language_get_sample_string (language); tmp_list = cf_priv->metrics_by_lang; while (tmp_list) { info = tmp_list->data; if (info->sample_str == sample_str) /* We _don't_ need strcmp */ break; tmp_list = tmp_list->next; } if (!tmp_list) { PangoFontMap *fontmap; PangoContext *context; cairo_font_options_t *font_options; int height, shift; /* XXX this is racy. need a ref'ing getter... */ fontmap = pango_font_get_font_map (font); if (!fontmap) return pango_font_metrics_new (); fontmap = g_object_ref (fontmap); info = g_slice_new0 (PangoCairoFontMetricsInfo); cf_priv->metrics_by_lang = g_slist_prepend (cf_priv->metrics_by_lang, info); info->sample_str = sample_str; context = pango_font_map_create_context (fontmap); pango_context_set_language (context, language); font_options = cairo_font_options_create (); cairo_scaled_font_get_font_options (_pango_cairo_font_private_get_scaled_font (cf_priv), font_options); pango_cairo_context_set_font_options (context, font_options); cairo_font_options_destroy (font_options); info->metrics = (* PANGO_CAIRO_FONT_GET_IFACE (font)->create_metrics_for_context) (cfont, context); /* We may actually reuse ascent/descent we got from cairo here. that's * in cf_priv->font_extents. */ height = info->metrics->ascent + info->metrics->descent; switch (cf_priv->gravity) { default: case PANGO_GRAVITY_AUTO: case PANGO_GRAVITY_SOUTH: break; case PANGO_GRAVITY_NORTH: info->metrics->ascent = info->metrics->descent; break; case PANGO_GRAVITY_EAST: case PANGO_GRAVITY_WEST: { int ascent = height / 2; if (cf_priv->is_hinted) ascent = PANGO_UNITS_ROUND (ascent); info->metrics->ascent = ascent; } } shift = (height - info->metrics->ascent) - info->metrics->descent; info->metrics->descent += shift; info->metrics->underline_position -= shift; info->metrics->strikethrough_position -= shift; info->metrics->ascent = height - info->metrics->descent; g_object_unref (context); g_object_unref (fontmap); } return pango_font_metrics_ref (info->metrics); }
PangoFontMetrics * _pango_cairo_font_get_metrics (PangoFont *font, PangoLanguage *language) { PangoCairoFont *cfont = (PangoCairoFont *) font; PangoCairoFontPrivate *cf_priv = PANGO_CAIRO_FONT_PRIVATE (font); PangoCairoFontMetricsInfo *info = NULL; /* Quiet gcc */ GSList *tmp_list; const char *sample_str = pango_language_get_sample_string (language); tmp_list = cf_priv->metrics_by_lang; while (tmp_list) { info = tmp_list->data; if (info->sample_str == sample_str) /* We _don't_ need strcmp */ break; tmp_list = tmp_list->next; } if (!tmp_list) { PangoFontMap *fontmap; PangoContext *context; cairo_font_options_t *font_options; PangoLayout *layout; PangoRectangle extents; PangoFontDescription *desc; cairo_scaled_font_t *scaled_font; cairo_matrix_t cairo_matrix; PangoMatrix pango_matrix; PangoMatrix identity = PANGO_MATRIX_INIT; int height, shift; /* XXX this is racy. need a ref'ing getter... */ fontmap = pango_font_get_font_map (font); if (!fontmap) return pango_font_metrics_new (); fontmap = g_object_ref (fontmap); info = g_slice_new0 (PangoCairoFontMetricsInfo); cf_priv->metrics_by_lang = g_slist_prepend (cf_priv->metrics_by_lang, info); info->sample_str = sample_str; scaled_font = _pango_cairo_font_private_get_scaled_font (cf_priv); context = pango_font_map_create_context (fontmap); pango_context_set_language (context, language); font_options = cairo_font_options_create (); cairo_scaled_font_get_font_options (scaled_font, font_options); pango_cairo_context_set_font_options (context, font_options); cairo_font_options_destroy (font_options); info->metrics = (* PANGO_CAIRO_FONT_GET_IFACE (font)->create_base_metrics_for_context) (cfont, context); /* We now need to adjust the base metrics for ctm */ cairo_scaled_font_get_ctm (scaled_font, &cairo_matrix); pango_matrix.xx = cairo_matrix.xx; pango_matrix.yx = cairo_matrix.yx; pango_matrix.xy = cairo_matrix.xy; pango_matrix.yy = cairo_matrix.yy; pango_matrix.x0 = 0; pango_matrix.y0 = 0; if (G_UNLIKELY (0 != memcmp (&identity, &pango_matrix, 4 * sizeof (double)))) { double xscale = pango_matrix_get_font_scale_factor (&pango_matrix); if (xscale) xscale = 1 / xscale; info->metrics->ascent *= xscale; info->metrics->descent *= xscale; info->metrics->underline_position *= xscale; info->metrics->underline_thickness *= xscale; info->metrics->strikethrough_position *= xscale; info->metrics->strikethrough_thickness *= xscale; } /* Set the matrix on the context so we don't have to adjust the derived * metrics. */ pango_context_set_matrix (context, &pango_matrix); /* Update approximate_*_width now */ layout = pango_layout_new (context); desc = pango_font_describe_with_absolute_size (font); pango_layout_set_font_description (layout, desc); pango_font_description_free (desc); pango_layout_set_text (layout, sample_str, -1); pango_layout_get_extents (layout, NULL, &extents); info->metrics->approximate_char_width = extents.width / pango_utf8_strwidth (sample_str); pango_layout_set_text (layout, "0123456789", -1); info->metrics->approximate_digit_width = max_glyph_width (layout); g_object_unref (layout); /* We may actually reuse ascent/descent we got from cairo here. that's * in cf_priv->font_extents. */ height = info->metrics->ascent + info->metrics->descent; switch (cf_priv->gravity) { default: case PANGO_GRAVITY_AUTO: case PANGO_GRAVITY_SOUTH: break; case PANGO_GRAVITY_NORTH: info->metrics->ascent = info->metrics->descent; break; case PANGO_GRAVITY_EAST: case PANGO_GRAVITY_WEST: { int ascent = height / 2; if (cf_priv->is_hinted) ascent = PANGO_UNITS_ROUND (ascent); info->metrics->ascent = ascent; } } shift = (height - info->metrics->ascent) - info->metrics->descent; info->metrics->descent += shift; info->metrics->underline_position -= shift; info->metrics->strikethrough_position -= shift; info->metrics->ascent = height - info->metrics->descent; g_object_unref (context); g_object_unref (fontmap); } return pango_font_metrics_ref (info->metrics); }