[cairo] glyph extents

Jeff Muizelaar jeff at infidigm.net
Wed Feb 18 15:16:18 PST 2009


On Mon, Feb 16, 2009 at 03:54:26PM +0000, Jonathan Kew wrote:
> I'd like to ask for clarification of the glyph extents returned by  
> cairo_scaled_font_glyph_extents() (and related APIs that are relying  
> on the same font data). There is an issue here for the Windows back- 
> end that leads to poor visual results in certain situations.
> 
> The Cairo documentation says that:
> 
>     The extents describe a user-space rectangle that encloses the
>     "inked" portion of the glyphs, (as they would be drawn by
>     cairo_show_glyphs() if the cairo graphics state were set to
>     the same font_face, font_matrix, ctm, and font_options as
>     scaled_font).
> 
> It seems to me that the meaning of "inked" is a little unclear in the  
> presence of antialiasing, especially at a subpixel level -- does it  
> mean the area that a user perceives as the "solid ink" of the glyph,  
> or does it mean every pixel that is touched in any way by drawing the  
> glyph? The difference can be quite significant, especially on Windows  
> with ClearType enabled.
> 
> The attached image shows some text (enlarged to make the pixels  
> clearly visible) rendered through Cairo on Vista with no smoothing,  
> with "standard" font smoothing, and with ClearType. Consider what the  
> glyph extents of the initial "f" should be, for example.
> 
> In the first case, the "inked" portion of the "f" is obviously 4  
> pixels wide, from (0,0) to (4,9) relative to the origin at which the  
> glyph was drawn (where co-ordinates refer to the "grid lines" between  
> pixels, not to the pixels themselves).
> 
> In the second case, with standard font smoothing, the inked area of  
> the "f" is still 4 pixels wide (although note that other glyphs have  
> changed their inked extents).
> 
> In the third case, with ClearType, note how many more pixels have been  
> touched. There is a yellow pixel to the left of the crossbar of the  
> "f", so its inked area now begins at (-1,0); not quite so obvious is  
> that it also extends one pixel further right at the top, contributing  
> a slight blue tint to the otherwise yellow antialiasing of the "i".  
> (This faint blue pixel from the "f" can be seen clearly on the  
> subsequent occurrences.) So the ClearType "f" touches pixels within  
> the area (-1,0) to (5,9), two pixels wider than its non-ClearType  
> counterpart. The "x" has similarly extended from 5 to 7 pixels wide,  
> the "i" and "l" from 1 to 3, and the "e" from 4 to 6.
> 
> The problem we have is that on Windows, the "black box" returned in  
> the GLYPHMETRICS structure by GetGlyphOutlineW, which provides the  
> basis for Cairo's glyph extents, does NOT take account of these  
> ClearType pixels that "bleed" beyond what we might call the "visual"  
> ink rect. This means that the glyph extents Cairo uses and returns to  
> callers do not actually include every pixel that is touched by  
> painting the glyph.

Does GetGlyphOutlineW return the proper extents if you change from
GGO_METRICS to GGO_GRAY8_BITMAP? a la.

diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index e9abfda..6c03c5f 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -975,7 +975,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
 	    return status;
 
 	if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
-			      GGO_METRICS | GGO_GLYPH_INDEX,
+			      GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX,
 			      &metrics, 0, NULL, &matrix) == GDI_ERROR) {
 	  status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW");
 	  memset (&metrics, 0, sizeof (GLYPHMETRICS));
@@ -1019,7 +1019,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
 	    return status;
 
 	if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
-	                      GGO_METRICS | GGO_GLYPH_INDEX,
+	                      GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX,
 			      &metrics, 0, NULL, &matrix) == GDI_ERROR) {
 	  status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW");
 	  memset (&metrics, 0, sizeof (GLYPHMETRICS));

-Jeff


More information about the cairo mailing list