Re: PDF: Font size is rounded
Adrian Johnson <[email protected]>
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <[email protected]> |
I found a problem with my previous patch when testing. I have rewritten the patch, created a test case, and tested it with the test suite. The attached patch is the fix I will push out if there are no objections. A branch including the test case and ref images is at: https://cgit.freedesktop.org/~ajohnson/cairo/log/?h=unhinted-metrics On 16/04/16 22:36, Kouhei Sutou wrote: > Hi, > > In <[email protected]> > "Re: [cairo] PDF: Font size is rounded" on Sat, 2 Apr 2016 14:16:27 +1030, > Adrian Johnson <[email protected]> wrote: > >> I put some printfs in _cairo_ft_scaled_glyph_init (in cairo-ft-font.c). >> It appears that FreeType is returning hinted metrics. I'm guessing that >> to get unhinted metrics of TrueType fonts we need to set the scale to >> the EM size like we do for win32 fonts. >> >> I'm attaching a patch to do this. It fixes your test case. I don't know >> if this patch is the correct way to fix the problem. I am not familiar >> with the FreeType font backend. > > Could someone who know about the FreeType font backend > review the patch and commit the patch to the cairo > repository? I confirmed that the patch fixes the problem I > reported. I want the next cairo release to include this > patch. > > > Thanks, > -- > kou > -- cairo mailing list [email protected] https://lists.cairographics.org/mailman/listinfo/cairo
0001-ft-set-font-size-to-em-size-when-retrieving-unhinted.patch
(text/x-patch, 6.7 KB)
From 1179a21d879f1fcee5c2cae5752e63506e7ce288 Mon Sep 17 00:00:00 2001 From: Adrian Johnson <[email protected]> Date: Sat, 18 Jun 2016 13:16:57 +0930 Subject: [PATCH] ft: set font size to em size when retrieving unhinted metrics fixes text-unhinted-metrics test --- src/cairo-ft-font.c | 140 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 90 insertions(+), 50 deletions(-) diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index a0c7beb..4f31304 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -2209,6 +2209,55 @@ _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void *abstract_font, } static cairo_int_status_t +_cairo_ft_scaled_glyph_load_glyph (cairo_ft_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + FT_Face face, + int load_flags, + cairo_bool_t use_em_size, + cairo_bool_t vertical_layout) +{ + FT_Error error; + cairo_status_t status; + + if (use_em_size) { + cairo_matrix_t em_size; + cairo_matrix_init_scale (&em_size, face->units_per_EM, face->units_per_EM); + status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, &em_size); + } else { + status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, + &scaled_font->base.scale); + } + if (unlikely (status)) + return status; + + error = FT_Load_Glyph (face, + _cairo_scaled_glyph_index(scaled_glyph), + load_flags); + /* XXX ignoring all other errors for now. They are not fatal, typically + * just a glyph-not-found. */ + if (error == FT_Err_Out_Of_Memory) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + /* + * synthesize glyphs if requested + */ +#if HAVE_FT_GLYPHSLOT_EMBOLDEN + if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD) + FT_GlyphSlot_Embolden (face->glyph); +#endif + +#if HAVE_FT_GLYPHSLOT_OBLIQUE + if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_OBLIQUE) + FT_GlyphSlot_Oblique (face->glyph); +#endif + + if (vertical_layout) + _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, face->glyph); + + return CAIRO_STATUS_SUCCESS; +} + +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) @@ -2218,22 +2267,17 @@ _cairo_ft_scaled_glyph_init (void *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_bool_t scaled_glyph_loaded = FALSE; face = _cairo_ft_unscaled_font_lock_face (unscaled); if (!face) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, - &scaled_font->base.scale); - if (unlikely (status)) - goto FAIL; - /* Ignore global advance unconditionally */ load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; @@ -2264,37 +2308,23 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, /* load_flags |= FT_LOAD_COLOR; */ #endif - error = FT_Load_Glyph (face, - _cairo_scaled_glyph_index(scaled_glyph), - load_flags); - /* XXX ignoring all other errors for now. They are not fatal, typically - * just a glyph-not-found. */ - if (error == FT_Err_Out_Of_Memory) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL; - } - - glyph = face->glyph; - /* - * synthesize glyphs if requested - */ -#if HAVE_FT_GLYPHSLOT_EMBOLDEN - if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD) - FT_GlyphSlot_Embolden (glyph); -#endif + if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) { -#if HAVE_FT_GLYPHSLOT_OBLIQUE - if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_OBLIQUE) - FT_GlyphSlot_Oblique (glyph); -#endif + cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF; - if (vertical_layout) - _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph); + status = _cairo_ft_scaled_glyph_load_glyph (scaled_font, + scaled_glyph, + face, + load_flags, + !hint_metrics, + vertical_layout); + if (unlikely (status)) + goto FAIL; - if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) { + glyph = face->glyph; + scaled_glyph_loaded = hint_metrics; - cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF; /* * Compute font-space metrics */ @@ -2392,6 +2422,20 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) { cairo_image_surface_t *surface; + if (!scaled_glyph_loaded) { + status = _cairo_ft_scaled_glyph_load_glyph (scaled_font, + scaled_glyph, + face, + load_flags, + FALSE, + vertical_layout); + if (unlikely (status)) + goto FAIL; + + glyph = face->glyph; + scaled_glyph_loaded = TRUE; + } + if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { status = _render_glyph_outline (face, &scaled_font->ft_options.base, &surface); @@ -2423,27 +2467,23 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, * so reload it. This will probably never occur though */ if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) { - error = FT_Load_Glyph (face, - _cairo_scaled_glyph_index(scaled_glyph), - load_flags | FT_LOAD_NO_BITMAP); - /* XXX ignoring all other errors for now. They are not fatal, typically - * just a glyph-not-found. */ - if (error == FT_Err_Out_Of_Memory) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + scaled_glyph_loaded = FALSE; + load_flags |= FT_LOAD_NO_BITMAP; + } + + if (!scaled_glyph_loaded) { + status = _cairo_ft_scaled_glyph_load_glyph (scaled_font, + scaled_glyph, + face, + load_flags, + FALSE, + vertical_layout); + if (unlikely (status)) goto FAIL; - } -#if HAVE_FT_GLYPHSLOT_EMBOLDEN - if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD) - FT_GlyphSlot_Embolden (glyph); -#endif -#if HAVE_FT_GLYPHSLOT_OBLIQUE - if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_OBLIQUE) - FT_GlyphSlot_Oblique (glyph); -#endif - if (vertical_layout) - _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph); + glyph = face->glyph; } + if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) status = _decompose_glyph_outline (face, &scaled_font->ft_options.base, &path); -- 2.1.4