From 4c8317941815971f1d060243e1f6153df06866ca Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sun, 10 Aug 2008 14:24:16 +0930 Subject: [PATCH] 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. --- src/cairo-win32-printing-surface.c | 63 +++++++++++++++++++++++++----- src/cairo-win32-private.h | 1 + src/cairo-win32-surface.c | 22 ++++++++++- 3 files changed, 75 insertions(+), 11 deletions(-) diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c index 0846daa40..55d5b196c 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 @@ -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 1cdf597ba..8cbea8782 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 d090ffbd9..236f05260 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 @@ -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,