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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.