[cairo-commit] 4 commits - src/cairo-scaled-font-subsets.c src/cairo-scaled-font-subsets-private.h src/cairo-win32-font.c src/cairo-win32-printing-surface.c src/cairo-win32-private.h src/cairo-win32-surface.c

Adrian Johnson ajohnson at kemper.freedesktop.org
Sat Aug 9 22:00:44 PDT 2008


 src/cairo-scaled-font-subsets-private.h |   14 +++++--
 src/cairo-scaled-font-subsets.c         |    8 ++--
 src/cairo-win32-font.c                  |   34 ++++++++++++++++-
 src/cairo-win32-printing-surface.c      |   63 ++++++++++++++++++++++++++------
 src/cairo-win32-private.h               |    1 
 src/cairo-win32-surface.c               |   22 ++++++++++-
 6 files changed, 121 insertions(+), 21 deletions(-)

New commits:
commit bc4635f07729d6a73054971f0e7ec04433f414da
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Aug 10 14:24:48 2008 +0930

    Update _cairo_scaled_font_subsets_map_glyph() docs

diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index 1de3f86..bc1b955 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -127,12 +127,10 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
  * @font_subsets: a #cairo_scaled_font_subsets_t
  * @scaled_font: the font of the glyph to be mapped
  * @scaled_font_glyph_index: the index of the glyph to be mapped
+ * @utf8: a string of text encoded in UTF-8
+ * @utf8_len: length of @utf8 in bytes
  * @subset_glyph_ret: return structure containing subset font and glyph id
  *
- * @font_id_ret: return value giving the font ID of the mapped glyph
- * @subset_id_ret: return value giving the subset ID of the mapped glyph within the @font_id_ret
- * @subset_glyph_index_ret: return value giving the index of the mapped glyph within the @subset_id_ret subset
- *
  * Map a glyph from a #cairo_scaled_font to a new index within a
  * subset of that font. The mapping performed is from the tuple:
  *
@@ -170,6 +168,14 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
  * used by #cairo_scaled_font_subset_t as provided by
  * _cairo_scaled_font_subsets_foreach.
  *
+ * @utf8 and @utf8_len specify a string of unicode characters that the
+ * glyph @scaled_font_glyph_index maps to. If @utf8_is_mapped in
+ * @subset_glyph_ret is TRUE, the font subsetting will (where index to
+ * unicode mapping is supported) ensure that @scaled_font_glyph_index
+ * maps to @utf8. If @utf8_is_mapped is FALSE,
+ * @scaled_font_glyph_index has already been mapped to a different
+ * unicode string.
+ *
  * The returned values in the #cairo_scaled_font_subsets_glyph_t struct are:
  *
  * @font_id: The font ID of the mapped glyph
commit 4c8317941815971f1d060243e1f6153df06866ca
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Aug 10 14:24:16 2008 +0930

    Win32-printing: Fix Type 1 font printing so fallback is not used
    
    Using glyph indices with Type 1 fonts on a printer DC does not work.
    Previously there was a temporary fix where Type 1 fonts were printed
    as filled paths.
    
    Now that _cairo_scaled_font_subsets_map_glyph() provides the reverse
    mapping of the glyph index fix this by converting the glyph indices
    back to the unicode values when printing Type 1 fonts.

diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 0846daa..55d5b19 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -51,6 +51,7 @@
 #include "cairo-clip-private.h"
 #include "cairo-win32-private.h"
 #include "cairo-meta-surface-private.h"
+#include "cairo-scaled-font-subsets-private.h"
 
 #include <windows.h>
 
@@ -1313,16 +1314,14 @@ _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surfac
     }
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
-	/* Calling ExtTextOutW() with ETO_GLYPH_INDEX and a Type 1 or
-	 * bitmap font on a printer DC prints garbled text. The text
-	 * displays correctly on a display DC. It appears that when
-	 * using a printer DC. ExtTextOutW() only works with
-	 * characters and not glyph indices.
+	/* When printing bitmap fonts to a printer DC, Windows may
+	 * substitute an outline font for bitmap font. As the win32
+	 * font backend always uses a screen DC when obtaining the
+	 * font metrics the metrics of the substituted font will not
+	 * match the metrics that the win32 font backend returns.
 	 *
-	 * For now we don't use ExtTextOutW for Type 1 or bitmap
-	 * fonts. These fonts will go through the fallback path for
-	 * non Windows fonts. ie filled outlines for Type 1 fonts and
-	 * fallback images for bitmap fonts.
+	 * If we are printing a bitmap font, use fallback images to
+	 * ensure the font is not substituted.
 	 */
 	if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32) {
 	    if (_cairo_win32_scaled_font_is_bitmap (scaled_font))
@@ -1364,10 +1363,46 @@ _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surfac
     }
 
     if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 &&
-	! _cairo_win32_scaled_font_is_type1 (scaled_font) &&
 	source->type == CAIRO_PATTERN_TYPE_SOLID)
     {
 	cairo_matrix_t ctm;
+	cairo_glyph_t  *type1_glyphs = NULL;
+	cairo_scaled_font_subsets_glyph_t subset_glyph;
+
+	/* Calling ExtTextOutW() with ETO_GLYPH_INDEX and a Type 1
+	 * font on a printer DC prints garbled text. The text displays
+	 * correctly on a display DC. When using a printer
+	 * DC, ExtTextOutW() only works with characters and not glyph
+	 * indices.
+	 *
+	 * For Type 1 fonts the glyph indices are converted back to
+	 * unicode characters before calling _cairo_win32_surface_show_glyphs().
+	 *
+	 * As _cairo_win32_scaled_font_index_to_ucs4() is a slow
+	 * operation, the font subsetting function
+	 * _cairo_scaled_font_subsets_map_glyph() is used to obtain
+	 * the unicode value because it caches the reverse mapping in
+	 * the subsets.
+	 */
+	if (_cairo_win32_scaled_font_is_type1 (scaled_font)) {
+	    type1_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
+	    if (type1_glyphs == NULL)
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	    memcpy (type1_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
+	    for (i = 0; i < num_glyphs; i++) {
+		status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
+							       scaled_font,
+							       type1_glyphs[i].index,
+							       NULL, 0,
+							       &subset_glyph);
+		if (status)
+		    return status;
+
+		type1_glyphs[i].index = subset_glyph.unicode;
+	    }
+	    glyphs = type1_glyphs;
+	}
 
 	if (surface->has_ctm) {
 	    for (i = 0; i < num_glyphs; i++)
@@ -1385,6 +1420,9 @@ _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surfac
 	if (surface->has_ctm)
 	    cairo_scaled_font_destroy (scaled_font);
 
+	if (type1_glyphs != NULL)
+	    free (type1_glyphs);
+
 	return status;
     }
 
@@ -1531,6 +1569,11 @@ cairo_win32_printing_surface_create (HDC hdc)
     surface->saved_dc_bitmap = NULL;
     surface->brush = NULL;
     surface->old_brush = NULL;
+    surface->font_subsets = _cairo_scaled_font_subsets_create_scaled ();
+    if (surface->font_subsets == NULL) {
+	free (surface);
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+    }
 
     GetClipBox(hdc, &rect);
     surface->extents.x = rect.left;
diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h
index 1cdf597..8cbea87 100644
--- a/src/cairo-win32-private.h
+++ b/src/cairo-win32-private.h
@@ -92,6 +92,7 @@ typedef struct _cairo_win32_surface {
     cairo_bool_t has_ctm;
     cairo_matrix_t ctm;
     HBRUSH brush, old_brush;
+    cairo_scaled_font_subsets_t *font_subsets;
 } cairo_win32_surface_t;
 
 /* Surface DC flag values */
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index d090ffb..236f052 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -50,6 +50,7 @@
 #include "cairo-clip-private.h"
 #include "cairo-paginated-private.h"
 #include "cairo-win32-private.h"
+#include "cairo-scaled-font-subsets-private.h"
 
 #include <windows.h>
 
@@ -359,6 +360,7 @@ _cairo_win32_surface_create_for_dc (HDC             original_dc,
     surface->had_simple_clip = FALSE;
 
     surface->extents = surface->clip_rect;
+    surface->font_subsets = NULL;
 
     _cairo_surface_init (&surface->base, &cairo_win32_surface_backend,
 			 _cairo_content_from_format (format));
@@ -497,6 +499,9 @@ _cairo_win32_surface_finish (void *abstract_surface)
     if (surface->initial_clip_rgn)
 	DeleteObject (surface->initial_clip_rgn);
 
+    if (surface->font_subsets != NULL)
+	_cairo_scaled_font_subsets_destroy (surface->font_subsets);
+
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -1578,6 +1583,7 @@ _cairo_win32_surface_show_glyphs (void			*surface,
     int start_x, start_y;
     double user_x, user_y;
     int logical_x, logical_y;
+    unsigned int glyph_index_option;
 
     /* We can only handle win32 fonts */
     if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)
@@ -1663,10 +1669,24 @@ _cairo_win32_surface_show_glyphs (void			*surface,
         }
     }
 
+    /* Using glyph indices for a Type 1 font does not work on a
+     * printer DC. The win32 printing surface will convert the the
+     * glyph indices of Type 1 fonts to the unicode values.
+     */
+    if ((dst->flags & CAIRO_WIN32_SURFACE_FOR_PRINTING) &&
+	_cairo_win32_scaled_font_is_type1 (scaled_font))
+    {
+	glyph_index_option = 0;
+    }
+    else
+    {
+	glyph_index_option = ETO_GLYPH_INDEX;
+    }
+
     win_result = ExtTextOutW(dst->dc,
                              start_x,
                              start_y,
-                             ETO_GLYPH_INDEX | ETO_PDY,
+                             glyph_index_option | ETO_PDY,
                              NULL,
                              glyph_buf,
                              num_glyphs,
commit b34c248b92b2d1544a23c20ecaa12f64792cb1d3
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Aug 10 14:18:52 2008 +0930

    Fix _cairo_sub_font_map_glyph() to return correct unicode value

diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 2740d63..1f87838 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -460,10 +460,9 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
 	if (sub_font_glyph == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-	if (utf8_len < 0)
-	    _cairo_sub_font_glyph_lookup_unicode (sub_font_glyph,
-						  sub_font->scaled_font,
-						  scaled_font_glyph_index);
+	_cairo_sub_font_glyph_lookup_unicode (sub_font_glyph,
+					      sub_font->scaled_font,
+					      scaled_font_glyph_index);
 
 	status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
 	if (status) {
@@ -493,6 +492,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t	*sub_font,
     subset_glyph->x_advance = sub_font_glyph->x_advance;
     subset_glyph->y_advance = sub_font_glyph->y_advance;
     subset_glyph->utf8_is_mapped = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, utf8, utf8_len);
+    subset_glyph->unicode = sub_font_glyph->unicode;
 
     return CAIRO_STATUS_SUCCESS;
 }
commit d1c619bc7d51a8e96eaf391691bec142dbd34e0e
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Aug 10 14:17:01 2008 +0930

    win32-font: Make cairo_show_text() work again
    
    For now implement _ucs4_to_index() and leave _text_to_glyphs()
    disabled.

diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index ef2d2f0..4c1c929 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -826,6 +826,36 @@ _cairo_win32_scaled_font_text_to_glyphs (void		*abstract_font,
     return status;
 }
 
+static unsigned long
+_cairo_win32_scaled_font_ucs4_to_index (void		*abstract_font,
+					uint32_t	 ucs4)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    wchar_t unicode[2];
+    WORD glyph_index;
+    HDC hdc = NULL;
+    cairo_status_t status;
+
+    hdc = _get_global_font_dc ();
+    if (!hdc)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+    if (status)
+	return 0;
+
+    unicode[0] = ucs4;
+    unicode[1] = 0;
+    if (GetGlyphIndicesW (hdc, unicode, 1, &glyph_index, 0) == GDI_ERROR) {
+	_cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_ucs4_to_index:GetGlyphIndicesW");
+	glyph_index = 0;
+    }
+
+    cairo_win32_scaled_font_done_font (&scaled_font->base);
+
+    return glyph_index;
+}
+
 static cairo_status_t
 _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font)
 {
@@ -1780,8 +1810,8 @@ const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
     _cairo_win32_scaled_font_create_toy,
     _cairo_win32_scaled_font_fini,
     _cairo_win32_scaled_font_glyph_init,
-    /* _cairo_win32_scaled_font_text_to_glyphs, FIXME */
-    NULL,			/* ucs4_to_index */
+    NULL, /* _cairo_win32_scaled_font_text_to_glyphs, FIXME */
+    _cairo_win32_scaled_font_ucs4_to_index,
     _cairo_win32_scaled_font_show_glyphs,
     _cairo_win32_scaled_font_load_truetype_table,
     _cairo_win32_scaled_font_index_to_ucs4,


More information about the cairo-commit mailing list