summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--pango/pangocairo-atsuifont.c148
-rw-r--r--pango/pangocairo-atsuifontmap.c1
3 files changed, 151 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 454bf5ff..be199323 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2007-05-15 Richard Hult <richard@imendio.com>
+
+ Bug 433805 - [Atsui] Approximate char/digit width width often 0
+
+ * pango/pangocairo-atsuifont.c:
+ (pango_cairo_atsui_font_get_metrics): Improve the metrics so it really
+ is average instead of max glyph width. Also keep the metrics per
+ language in the font so it's not constantly recreated.
+ (pango_cairo_atsui_font_describe_absolute): Implement.
+
+ * pango/pangocairo-atsuifontmap.c: Set default resolution.
+
2007-05-15 Behdad Esfahbod <behdad@gnome.org>
* pango-view/Makefile.am: Add various test txt files recently
diff --git a/pango/pangocairo-atsuifont.c b/pango/pangocairo-atsuifont.c
index d185fa6f..0d830783 100644
--- a/pango/pangocairo-atsuifont.c
+++ b/pango/pangocairo-atsuifont.c
@@ -42,6 +42,9 @@ struct _PangoCairoATSUIFont
cairo_font_options_t *options;
double size;
+ int absolute_size;
+
+ GSList *metrics_by_lang;
};
struct _PangoCairoATSUIFontClass
@@ -202,17 +205,45 @@ pango_cairo_atsui_font_get_glyph_extents (PangoFont *font,
}
}
+static int
+max_glyph_width (PangoLayout *layout)
+{
+ int max_width = 0;
+ GSList *l, *r;
+
+ for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
+ {
+ PangoLayoutLine *line = l->data;
+
+ for (r = line->runs; r; r = r->next)
+ {
+ PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
+ int i;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ if (glyphs->glyphs[i].geometry.width > max_width)
+ max_width = glyphs->glyphs[i].geometry.width;
+ }
+ }
+
+ return max_width;
+}
static PangoFontMetrics *
-pango_cairo_atsui_font_get_metrics (PangoFont *font,
- PangoLanguage *language)
+create_metrics_for_context (PangoFont *font,
+ PangoContext *context)
{
PangoCairoATSUIFont *cafont = PANGO_CAIRO_ATSUI_FONT (font);
ATSFontRef ats_font;
ATSFontMetrics ats_metrics;
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);
- ats_font = FMGetATSFontRefFromFont(cafont->font_id);
+ ats_font = FMGetATSFontRefFromFont (cafont->font_id);
ATSFontGetHorizontalMetrics (ats_font, kATSOptionFlagsDefault, &ats_metrics);
@@ -221,25 +252,110 @@ pango_cairo_atsui_font_get_metrics (PangoFont *font,
metrics->ascent = ats_metrics.ascent * cafont->size * PANGO_SCALE;
metrics->descent = -ats_metrics.descent * cafont->size * PANGO_SCALE;
- /* TODO: the following two are not really what they should be.
- * See bug 433805 */
- metrics->approximate_char_width = ats_metrics.maxAdvanceWidth * cafont->size * PANGO_SCALE;
- metrics->approximate_digit_width = ats_metrics.maxAdvanceWidth * cafont->size * PANGO_SCALE;
-
metrics->underline_position = ats_metrics.underlinePosition * cafont->size * PANGO_SCALE;
metrics->underline_thickness = ats_metrics.underlineThickness * cafont->size * PANGO_SCALE;
metrics->strikethrough_position = metrics->ascent / 3;
metrics->strikethrough_thickness = ats_metrics.underlineThickness * cafont->size * PANGO_SCALE;
+ 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;
}
+typedef struct
+{
+ const char *sample_str;
+ PangoFontMetrics *metrics;
+} PangoATSUIMetricsInfo;
+
+static PangoFontMetrics *
+pango_cairo_atsui_font_get_metrics (PangoFont *font,
+ PangoLanguage *language)
+{
+ PangoCairoATSUIFont *cafont = PANGO_CAIRO_ATSUI_FONT (font);
+ PangoATSUIMetricsInfo *info;
+ GSList *tmp_list;
+ const char *sample_str = pango_language_get_sample_string (language);
+
+ tmp_list = cafont->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 (!pango_font_get_font_map (font))
+ return pango_font_metrics_new ();
+
+ info = g_slice_new0 (PangoATSUIMetricsInfo);
+
+ cafont->metrics_by_lang = g_slist_prepend (cafont->metrics_by_lang,
+ info);
+
+ info->sample_str = sample_str;
+
+ context = pango_context_new ();
+ pango_context_set_font_map (context, pango_font_get_font_map (font));
+ pango_context_set_language (context, language);
+ pango_cairo_context_set_font_options (context, cafont->options);
+
+ info->metrics = create_metrics_for_context (font, context);
+
+ g_object_unref (context);
+ }
+
+ return pango_font_metrics_ref (info->metrics);
+}
+
+static PangoFontDescription *
+pango_cairo_atsui_font_describe_absolute (PangoFont *font)
+{
+ PangoFontDescription *desc;
+ PangoATSUIFont *afont = PANGO_ATSUI_FONT (font);
+ PangoCairoATSUIFont *cafont = PANGO_CAIRO_ATSUI_FONT (font);
+
+ desc = pango_font_description_copy (afont->desc);
+ pango_font_description_set_absolute_size (desc, cafont->absolute_size);
+
+ return desc;
+}
+
+static void
+free_metrics_info (PangoATSUIMetricsInfo *info)
+{
+ pango_font_metrics_unref (info->metrics);
+ g_slice_free (PangoATSUIMetricsInfo, info);
+}
+
static void
pango_cairo_atsui_font_finalize (GObject *object)
{
PangoCairoATSUIFont *cafont = PANGO_CAIRO_ATSUI_FONT (object);
+ g_slist_foreach (cafont->metrics_by_lang, (GFunc)free_metrics_info, NULL);
+ g_slist_free (cafont->metrics_by_lang);
+
cairo_font_face_destroy (cafont->font_face);
cairo_scaled_font_destroy (cafont->scaled_font);
cairo_font_options_destroy (cafont->options);
@@ -257,6 +373,7 @@ pango_cairo_atsui_font_class_init (PangoCairoATSUIFontClass *class)
font_class->get_metrics = pango_cairo_atsui_font_get_metrics;
font_class->get_glyph_extents = pango_cairo_atsui_font_get_glyph_extents;
+ font_class->describe_absolute = pango_cairo_atsui_font_describe_absolute;
}
static void
@@ -278,6 +395,7 @@ _pango_cairo_atsui_font_new (PangoCairoATSUIFontMap *cafontmap,
ATSFontRef font_ref;
const PangoMatrix *pango_ctm;
ATSUFontID font_id;
+ double dpi;
postscript_name = _pango_atsui_face_get_postscript_name (face);
@@ -332,10 +450,20 @@ _pango_cairo_atsui_font_new (PangoCairoATSUIFontMap *cafontmap,
cafont->size = (double) pango_font_description_get_size (desc) / PANGO_SCALE;
cafont->font_id = font_id;
- if (!pango_font_description_get_size_is_absolute (desc))
+ if (context)
{
- /* FIXME: Need to handle dpi here. See other font implementations for more info. */
+ dpi = pango_cairo_context_get_resolution (context);
+
+ if (dpi <= 0)
+ dpi = cafontmap->dpi;
}
+ else
+ dpi = cafontmap->dpi;
+
+ cafont->absolute_size = cafont->size;
+
+ if (!pango_font_description_get_size_is_absolute (desc))
+ cafont->size *= dpi / 72.;
cairo_matrix_init_scale (&cafont->font_matrix, cafont->size, cafont->size);
pango_ctm = pango_context_get_matrix (context);
diff --git a/pango/pangocairo-atsuifontmap.c b/pango/pangocairo-atsuifontmap.c
index 13822b65..df703532 100644
--- a/pango/pangocairo-atsuifontmap.c
+++ b/pango/pangocairo-atsuifontmap.c
@@ -109,4 +109,5 @@ pango_cairo_atsui_font_map_class_init (PangoCairoATSUIFontMapClass *class)
static void
pango_cairo_atsui_font_map_init (PangoCairoATSUIFontMap *cafontmap)
{
+ cafontmap->dpi = 72.;
}