[cairo] [cairo-commit] 8 commits - src/cairo-fixed-private.h src/cairo-paginated-surface.c src/cairo-quartz-surface.c src/cairo-win32-font.c src/cairo-win32-printing-surface.c

Adrian Johnson ajohnson at redneon.com
Tue Nov 20 16:36:28 PST 2007


> commit 0901b83ca56e197d5c96d71ab8cfe53f21b4c8bb
> Author: Vladimir Vukicevic <vladimir at pobox.com>
> Date:   Tue Nov 6 15:49:57 2007 -0800
> 
>     [win32] Don't use GetGlyphOutline on non-TrueType fonts
>     
>     win32-glyph-metrics.patch: GetGlyphOutline only works on Truetype fonts,
>     so for non-Truetype fonts, assume no left or right bearing and use the
>     font ascent and descent for the glyph extents.
> 
> diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
> index dbabbef..7d4a10c 100644
> --- a/src/cairo-win32-font.c
> +++ b/src/cairo-win32-font.c
> @@ -99,6 +99,7 @@ typedef struct {
>      HFONT scaled_hfont;
>      HFONT unscaled_hfont;
>  
> +    cairo_bool_t is_truetype;
>      cairo_bool_t glyph_indexing;
>  
>      cairo_bool_t delete_scaled_hfont;
> @@ -741,11 +742,11 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font)
>  
>      }
>  
> -    if ((metrics.tmPitchAndFamily & TMPF_TRUETYPE) ||
> -        (GetFontData (hdc, OPENTYPE_CFF_TAG, 0, NULL, 0) != GDI_ERROR))
> -        scaled_font->glyph_indexing = TRUE;
> -    else
> -        scaled_font->glyph_indexing = FALSE;
> +    scaled_font->is_truetype = (metrics.tmPitchAndFamily & TMPF_TRUETYPE) != 0;
> +    scaled_font->glyph_indexing = scaled_font->is_truetype ||
> +	(GetFontData (hdc, OPENTYPE_CFF_TAG, 0, NULL, 0) != GDI_ERROR);
> +    // XXX in what situations does this OPENTYPE_CFF thing not have the
> +    // TMPF_TRUETYPE flag? GetFontData says it only works on Truetype fonts...

GetFontData also works with OpenType and Type 1 fonts. I have found that in general
any win32 function that says TrueType only means TrueType/OpenType/Type 1. The one
difference is that only TrueType and OpenType fonts use glyph indexing while Type 1
fonts do not.

The original code above is testing to see if the font is a TrueType or OpenType to
ensure that glyph indexing is used with functions like GetGlyphOutline. Testing
tmPitchAndFamily for the presence of the TMPF_TRUETYPE flag is an easy way to test
for TrueType fonts. However this flag is not set for OpenType fonts with PostScript
outlines. GetFontData() is called to check for the presence of the CFF table which
is unique to OpenType fonts with PostScript outlines.

When I originally wrote that code I first tried using just a call to
GetFontData(hdc, 0, 0, NULL, 0) to test for both TrueType and OpenType fonts however
this was succeeding for Type 1 fonts as well because calling GetFontData() with the
table set to zero is an undocumented way to retrieve a Type 1 font.

What font types was the code failing on? OpenType, Type 1, bitmap?  If it is bitmap
fonts that are failing you can test tmPitchAndFamily for TMPF_VECTOR to determine
whether the font is bitmap or vector.

>  
>      _cairo_scaled_font_set_metrics (&scaled_font->base, &extents);
>  
> @@ -761,18 +762,35 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
>      cairo_status_t status;
>      cairo_text_extents_t extents;
>      HDC hdc;
> -    UINT glyph_index_option;
>  
>      hdc = _get_global_font_dc ();
>      if (!hdc)
>  	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
>  
> -    if (scaled_font->glyph_indexing)
> -        glyph_index_option = GGO_GLYPH_INDEX;
> -    else
> -        glyph_index_option = 0;
> +    if (!scaled_font->is_truetype) {
> +	/* GetGlyphOutline will not work. Assume that the glyph does not extend outside the font box. */
> +	cairo_font_extents_t font_extents;
> +	INT width = 0;
> +	UINT charIndex = _cairo_scaled_glyph_index (scaled_glyph);
> +
> +	cairo_scaled_font_extents (&scaled_font->base, &font_extents);
> +
> +	status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
> +	if (!status) {
> +	    if (!GetCharWidth32(hdc, charIndex, charIndex, &width)) {
> +		status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetCharWidth32");
> +		width = 0;
> +	    }
> +	}
> +	cairo_win32_scaled_font_done_font (&scaled_font->base);
>  
> -    if (scaled_font->preserve_axes && scaled_font->base.options.hint_style != CAIRO_HINT_METRICS_OFF) {
> +	extents.x_bearing = 0;
> +	extents.y_bearing = -font_extents.ascent / scaled_font->y_scale;
> +	extents.width = width / scaled_font->x_scale;
> +	extents.height = (font_extents.ascent + font_extents.descent) / scaled_font->y_scale;
> +	extents.x_advance = extents.width;
> +	extents.y_advance = 0;
> +    } else if (scaled_font->preserve_axes && scaled_font->base.options.hint_style != CAIRO_HINT_METRICS_OFF) {
>  	/* If we aren't rotating / skewing the axes, then we get the metrics
>  	 * from the GDI in device space and convert to font space.
>  	 */
> @@ -780,7 +798,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
>  	if (status)
>  	    return status;
>  	if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
> -			      GGO_METRICS | glyph_index_option,
> +			      GGO_METRICS | 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));
> @@ -819,7 +837,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
>  	 */
>  	status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
>  	if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
> -			      GGO_METRICS | glyph_index_option,
> +	                      GGO_METRICS | 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));



More information about the cairo mailing list