[cairo] [PATCH] Fix Type 1 fonts on win32

Adrian Johnson ajohnson at redneon.com
Tue Aug 15 07:14:59 PDT 2006


Type 1 fonts using the win32 font backend are broken due to the use of 
the GLYPH_INDEX option
on ExtTextOut() and GetGlyphOutline(). This option is only applicable to 
TrueType and OpenType fonts.

This patch ensures the GLYPH_INDEX option is only used with TrueType and 
OpenType fonts.
It also removes the warning if GetFontData() fails in 
_cairo_win32_scaled_font_load_truetype_table()
as this is normal for non TrueType/OpenType fonts.

As the Type1 subsetting is dependent on FreeType, win32 Type1 fonts will 
fall back to Type 3 for the
PS and PDF backend. Bug 7603 has a patch to fix the Type 3 problem in win32.

-------------- next part --------------
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 5ca5653..95a44e1 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -50,6 +50,8 @@ #ifndef TT_PRIM_CSPLINE
 #define TT_PRIM_CSPLINE 3
 #endif
 
+#define OPENTYPE_CFF_TAG 0x20464643
+
 const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend;
 
 typedef struct {
@@ -97,6 +99,8 @@ typedef struct {
     HFONT scaled_hfont;
     HFONT unscaled_hfont;
 
+    cairo_bool_t glyph_indexing;
+
     cairo_bool_t delete_scaled_hfont;
 } cairo_win32_scaled_font_t;
 
@@ -720,6 +724,12 @@ _cairo_win32_scaled_font_set_metrics (ca
 
     }
 
+    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;
+
     _cairo_scaled_font_set_metrics (&scaled_font->base, &extents);
 
     return CAIRO_STATUS_SUCCESS;
@@ -734,11 +744,17 @@ _cairo_win32_scaled_font_init_glyph_metr
     cairo_status_t status;
     cairo_text_extents_t extents;
     HDC hdc;
+    UINT glyph_index_option;
 
     hdc = _get_global_font_dc ();
     if (!hdc)
 	return CAIRO_STATUS_NO_MEMORY;
 
+    if (scaled_font->glyph_indexing)
+        glyph_index_option = GGO_GLYPH_INDEX;
+    else
+        glyph_index_option = 0;
+
     if (scaled_font->preserve_axes) {
 	/* If we aren't rotating / skewing the axes, then we get the metrics
 	 * from the GDI in device space and convert to font space.
@@ -747,7 +763,7 @@ _cairo_win32_scaled_font_init_glyph_metr
 	if (status)
 	    return status;
 	if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
-			      GGO_METRICS | GGO_GLYPH_INDEX,
+			      GGO_METRICS | glyph_index_option,
 			      &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));
@@ -786,7 +802,7 @@ _cairo_win32_scaled_font_init_glyph_metr
 	 */
 	status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
 	if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
-			      GGO_METRICS | GGO_GLYPH_INDEX,
+			      GGO_METRICS | glyph_index_option,
 			      &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));
@@ -829,6 +845,7 @@ _cairo_win32_scaled_font_glyph_bbox (voi
 	GLYPHMETRICS metrics;
 	cairo_status_t status;
 	int i;
+        UINT glyph_index_option;
 
 	if (!hdc)
 	    return CAIRO_STATUS_NO_MEMORY;
@@ -837,11 +854,16 @@ _cairo_win32_scaled_font_glyph_bbox (voi
 	if (status)
 	    return status;
 
+        if (scaled_font->glyph_indexing)
+            glyph_index_option = GGO_GLYPH_INDEX;
+        else
+            glyph_index_option = 0;
+
 	for (i = 0; i < num_glyphs; i++) {
 	    int x = floor (0.5 + glyphs[i].x);
 	    int y = floor (0.5 + glyphs[i].y);
 
-	    GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | GGO_GLYPH_INDEX,
+	    GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | glyph_index_option,
 			     &metrics, 0, NULL, &matrix);
 
 	    if (i == 0 || x1 > x + metrics.gmptGlyphOrigin.x)
@@ -897,16 +919,22 @@ _flush_glyphs (cairo_glyph_state_t *stat
     int dx = 0;
     WCHAR * elements;
     int * dx_elements;
+    UINT glyph_index_option;
 
     status = _cairo_array_append (&state->dx, &dx);
     if (status)
 	return status;
 
+    if (state->scaled_font->glyph_indexing)
+        glyph_index_option = ETO_GLYPH_INDEX;
+    else
+        glyph_index_option = 0;
+
     elements = _cairo_array_index (&state->glyphs, 0);
     dx_elements = _cairo_array_index (&state->dx, 0);
     if (!ExtTextOutW (state->hdc,
 		      state->start_x, state->last_y,
-		      ETO_GLYPH_INDEX,
+		      glyph_index_option,
 		      NULL,
 		      elements,
 		      state->glyphs.num_elements,
@@ -1239,9 +1267,9 @@ _cairo_win32_scaled_font_load_truetype_t
     status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
 
     *length = GetFontData (hdc, tag, offset, buffer, *length);
-    if (*length == GDI_ERROR) {
-        status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_load_truetype_table:GetFontData");
-    }
+    if (*length == GDI_ERROR)
+        status = CAIRO_INT_STATUS_UNSUPPORTED;
+
     _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
 
     return status;
@@ -1264,6 +1292,7 @@ _cairo_win32_scaled_font_init_glyph_path
     DWORD bytesGlyph;
     unsigned char *buffer, *ptr;
     cairo_path_fixed_t *path;
+    UINT glyph_index_option;
 
     hdc = _get_global_font_dc ();
     if (!hdc)
@@ -1277,8 +1306,13 @@ _cairo_win32_scaled_font_init_glyph_path
     if (status)
         goto CLEANUP_PATH;
 
+    if (scaled_font->glyph_indexing)
+        glyph_index_option = GGO_GLYPH_INDEX;
+    else
+        glyph_index_option = 0;
+
     bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
-				   GGO_NATIVE | GGO_GLYPH_INDEX,
+				   GGO_NATIVE | glyph_index_option,
 				   &metrics, 0, NULL, &matrix);
 
     if (bytesGlyph == GDI_ERROR) {
@@ -1294,7 +1328,7 @@ _cairo_win32_scaled_font_init_glyph_path
     }
 
     if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
-			  GGO_NATIVE | GGO_GLYPH_INDEX,
+			  GGO_NATIVE | glyph_index_option,
 			  &metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) {
 	status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
 	free (buffer);


More information about the cairo mailing list