diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c index 1e8bd269d..806cab857 100644 --- a/src/cairo-win32-printing-surface.c +++ b/src/cairo-win32-printing-surface.c @@ -1430,6 +1430,94 @@ _cairo_win32_printing_surface_fill (void *abstract_surface, return status; } +static cairo_int_status_t +_cairo_win32_printing_surface_emit_win32_glyphs (cairo_win32_surface_t *surface, + cairo_operator_t op, + const cairo_pattern_t *source, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font, + cairo_clip_t *clip, + int *remaining_glyphs) +{ + cairo_matrix_t ctm; + cairo_glyph_t *unicode_glyphs; + cairo_scaled_font_subsets_glyph_t subset_glyph; + int i, first; + cairo_bool_t sequence_is_unicode; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + + /* Where possible reverse the glyph indices back to unicode + * characters. Strings of glyphs that could not be reversed to + * unicode will be printed with ETO_GLYPH_INDEX. + * + * 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 (surface->has_ctm) { + for (i = 0; i < num_glyphs; i++) + cairo_matrix_transform_point (&surface->ctm, &glyphs[i].x, &glyphs[i].y); + cairo_matrix_multiply (&ctm, &scaled_font->ctm, &surface->ctm); + scaled_font = cairo_scaled_font_create (scaled_font->font_face, + &scaled_font->font_matrix, + &ctm, + &scaled_font->options); + } + + unicode_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); + if (unicode_glyphs == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + memcpy (unicode_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, + glyphs[i].index, + NULL, 0, + &subset_glyph); + if (status) + goto fail; + + unicode_glyphs[i].index = subset_glyph.unicode; + } + + i = 0; + first = 0; + sequence_is_unicode = unicode_glyphs[0].index <= 0xffff; + while (i < num_glyphs) { + if (i == num_glyphs - 1 || + ((unicode_glyphs[i + 1].index < 0xffff) != sequence_is_unicode)) + { + status = _cairo_win32_surface_show_glyphs_internal ( + surface, + op, + source, + sequence_is_unicode ? &unicode_glyphs[first] : &glyphs[first], + i - first + 1, + scaled_font, + clip, + remaining_glyphs, + ! sequence_is_unicode); + first = i + 1; + if (i < num_glyphs - 1) + sequence_is_unicode = unicode_glyphs[i + 1].index <= 0xffff; + } + i++; + } + +fail: + if (surface->has_ctm) + cairo_scaled_font_destroy (scaled_font); + + free (unicode_glyphs); + + return status; +} + static cairo_int_status_t _cairo_win32_printing_surface_show_glyphs (void *abstract_surface, cairo_operator_t op, @@ -1514,67 +1602,14 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 && 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 || surface->has_gdi_ctm) { - cairo_matrix_multiply (&ctm, &surface->ctm, &surface->gdi_ctm); - for (i = 0; i < num_glyphs; i++) - cairo_matrix_transform_point (&ctm, &glyphs[i].x, &glyphs[i].y); - cairo_matrix_multiply (&ctm, &scaled_font->ctm, &ctm); - scaled_font = cairo_scaled_font_create (scaled_font->font_face, - &scaled_font->font_matrix, - &ctm, - &scaled_font->options); - } - status = _cairo_win32_surface_show_glyphs (surface, op, - source, glyphs, - num_glyphs, scaled_font, - clip, - remaining_glyphs); - if (surface->has_ctm) - cairo_scaled_font_destroy (scaled_font); - - if (type1_glyphs != NULL) - free (type1_glyphs); - - return status; + return _cairo_win32_printing_surface_emit_win32_glyphs (surface, + op, + source, + glyphs, + num_glyphs, + scaled_font, + clip, + remaining_glyphs); } #endif diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h index cde27b72d..efb0c1eed 100644 --- a/src/cairo-win32-private.h +++ b/src/cairo-win32-private.h @@ -155,6 +155,17 @@ cairo_status_t _cairo_win32_surface_set_clip_region (void *abstract_surface, cairo_region_t *region); +cairo_int_status_t +_cairo_win32_surface_show_glyphs_internal (void *surface, + cairo_operator_t op, + const cairo_pattern_t *source, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font, + cairo_clip_t *clip, + int *remaining_glyphs, + cairo_bool_t glyph_indices); + cairo_int_status_t _cairo_win32_surface_show_glyphs (void *surface, cairo_operator_t op, diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c index 660aaba35..c335d9780 100644 --- a/src/cairo-win32-surface.c +++ b/src/cairo-win32-surface.c @@ -1494,14 +1494,15 @@ _cairo_win32_surface_flush (void *abstract_surface) #define STACK_GLYPH_SIZE 256 cairo_int_status_t -_cairo_win32_surface_show_glyphs (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_clip_t *clip, - int *remaining_glyphs) +_cairo_win32_surface_show_glyphs_internal (void *surface, + cairo_operator_t op, + const cairo_pattern_t *source, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font, + cairo_clip_t *clip, + int *remaining_glyphs, + cairo_bool_t glyph_indexing) { #if CAIRO_HAS_WIN32_FONT cairo_win32_surface_t *dst = surface; @@ -1616,19 +1617,10 @@ _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 - { + if (glyph_indexing) glyph_index_option = ETO_GLYPH_INDEX; - } + else + glyph_index_option = 0; win_result = ExtTextOutW(dst->dc, start_x, @@ -1656,6 +1648,28 @@ _cairo_win32_surface_show_glyphs (void *surface, #undef STACK_GLYPH_SIZE +cairo_int_status_t +_cairo_win32_surface_show_glyphs (void *surface, + cairo_operator_t op, + const cairo_pattern_t *source, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font, + cairo_clip_t *clip, + int *remaining_glyphs) +{ + return _cairo_win32_surface_show_glyphs_internal (surface, + op, + source, + glyphs, + num_glyphs, + scaled_font, + clip, + remaining_glyphs, + TRUE); +} + + /** * cairo_win32_surface_create: * @hdc: the DC to create a surface for