[pango/line-height: 5/5] Avoid recursion
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pango/line-height: 5/5] Avoid recursion
- Date: Fri, 5 Jul 2019 12:42:11 +0000 (UTC)
commit a23adfa8bf4a3b5bf8e9e26313ad1b3722951e00
Author: Matthias Clasen <mclasen redhat com>
Date: Fri Jul 5 04:21:16 2019 +0000
Avoid recursion
In an evil twist, getting font metrics creates
a layout to measure the average digit width -
which in turn needs metrics to do its thing.
This is only working by a lucky accident.
Make it explicit.
pango/pangocairo-font.c | 37 +++++++++++++++++++++++--------------
pango/pangofc-font.c | 46 ++++++++++++++++++++++++++++------------------
2 files changed, 51 insertions(+), 32 deletions(-)
---
diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c
index 0769675b..7915be6f 100644
--- a/pango/pangocairo-font.c
+++ b/pango/pangocairo-font.c
@@ -224,6 +224,7 @@ _pango_cairo_font_get_metrics (PangoFont *font,
PangoCairoFontPrivate *cf_priv = PANGO_CAIRO_FONT_PRIVATE (font);
PangoCairoFontMetricsInfo *info = NULL; /* Quiet gcc */
GSList *tmp_list;
+ static int in_get_metrics;
const char *sample_str = pango_language_get_sample_string (language);
@@ -300,29 +301,36 @@ _pango_cairo_font_get_metrics (PangoFont *font,
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);
+ /* Ugly. We need to prevent recursion when we call into
+ * PangoLayout to determine approximate char width.
+ */
+ if (!in_get_metrics)
+ {
+ in_get_metrics = 1;
- pango_layout_set_text (layout, sample_str, -1);
- pango_layout_get_extents (layout, NULL, &extents);
+ /* 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);
- sample_str_width = pango_utf8_strwidth (sample_str);
- g_assert (sample_str_width > 0);
- info->metrics->approximate_char_width = extents.width / sample_str_width;
+ pango_layout_set_text (layout, sample_str, -1);
+ pango_layout_get_extents (layout, NULL, &extents);
- pango_layout_set_text (layout, "0123456789", -1);
- info->metrics->approximate_digit_width = max_glyph_width (layout);
+ sample_str_width = pango_utf8_strwidth (sample_str);
+ g_assert (sample_str_width > 0);
+ info->metrics->approximate_char_width = extents.width / sample_str_width;
- g_object_unref (layout);
+ pango_layout_set_text (layout, "0123456789", -1);
+ info->metrics->approximate_digit_width = max_glyph_width (layout);
+ g_object_unref (layout);
+ in_get_metrics = 0;
+ }
/* We may actually reuse ascent/descent we got from cairo here. that's
* in cf_priv->font_extents.
@@ -356,6 +364,7 @@ _pango_cairo_font_get_metrics (PangoFont *font,
g_object_unref (fontmap);
}
+out:
return pango_font_metrics_ref (info->metrics);
}
diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c
index b8e8928a..79fb07c1 100644
--- a/pango/pangofc-font.c
+++ b/pango/pangofc-font.c
@@ -554,6 +554,7 @@ pango_fc_font_get_metrics (PangoFont *font,
PangoFcFont *fcfont = PANGO_FC_FONT (font);
PangoFcMetricsInfo *info = NULL; /* Quiet gcc */
GSList *tmp_list;
+ static int in_get_metrics;
const char *sample_str = pango_language_get_sample_string (language);
@@ -579,6 +580,9 @@ pango_fc_font_get_metrics (PangoFont *font,
info = g_slice_new0 (PangoFcMetricsInfo);
+ /* Note: we need to add info to the list before calling
+ * into PangoLayout below, to prevent recursion
+ */
fcfont->metrics_by_lang = g_slist_prepend (fcfont->metrics_by_lang,
info);
@@ -589,29 +593,35 @@ pango_fc_font_get_metrics (PangoFont *font,
info->metrics = pango_fc_font_create_base_metrics_for_context (fcfont, context);
- { /* Compute derived metrics */
- PangoLayout *layout;
- PangoRectangle extents;
- const char *sample_str = pango_language_get_sample_string (language);
- PangoFontDescription *desc = pango_font_describe_with_absolute_size (font);
- gulong sample_str_width;
+ if (!in_get_metrics)
+ {
+ in_get_metrics = 1;
- layout = pango_layout_new (context);
- pango_layout_set_font_description (layout, desc);
- pango_font_description_free (desc);
+ /* Compute derived metrics */
+ PangoLayout *layout;
+ PangoRectangle extents;
+ const char *sample_str = pango_language_get_sample_string (language);
+ PangoFontDescription *desc = pango_font_describe_with_absolute_size (font);
+ gulong sample_str_width;
- pango_layout_set_text (layout, sample_str, -1);
- pango_layout_get_extents (layout, NULL, &extents);
+ layout = pango_layout_new (context);
+ pango_layout_set_font_description (layout, desc);
+ pango_font_description_free (desc);
- sample_str_width = pango_utf8_strwidth (sample_str);
- g_assert (sample_str_width > 0);
- info->metrics->approximate_char_width = extents.width / sample_str_width;
+ pango_layout_set_text (layout, sample_str, -1);
+ pango_layout_get_extents (layout, NULL, &extents);
- pango_layout_set_text (layout, "0123456789", -1);
- info->metrics->approximate_digit_width = max_glyph_width (layout);
+ sample_str_width = pango_utf8_strwidth (sample_str);
+ g_assert (sample_str_width > 0);
+ info->metrics->approximate_char_width = extents.width / sample_str_width;
- g_object_unref (layout);
- }
+ pango_layout_set_text (layout, "0123456789", -1);
+ info->metrics->approximate_digit_width = max_glyph_width (layout);
+
+ g_object_unref (layout);
+
+ in_get_metrics = 0;
+ }
g_object_unref (context);
g_object_unref (fontmap);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]