diff --git a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c --- a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c +++ b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c @@ -1426,16 +1426,104 @@ _cairo_win32_printing_surface_fill (void } fflush(stderr); 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, 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) @@ -1533,77 +1621,24 @@ _cairo_win32_printing_surface_show_glyph } } #endif #if CAIRO_HAS_WIN32_FONT 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) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FINISH; - } - 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) - goto FINISH; - - 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 || surface->has_gdi_ctm) - cairo_scaled_font_destroy (scaled_font); - - if (type1_glyphs != NULL) - free (type1_glyphs); - + status = _cairo_win32_printing_surface_emit_win32_glyphs (surface, + op, + source, + glyphs, + num_glyphs, + scaled_font, + clip, + remaining_glyphs); goto FINISH; } #endif SaveDC (surface->dc); old_ctm = surface->ctm; old_has_ctm = surface->has_ctm; surface->has_ctm = TRUE; diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h --- a/gfx/cairo/cairo/src/cairo-win32-private.h +++ b/gfx/cairo/cairo/src/cairo-win32-private.h @@ -157,16 +157,27 @@ _cairo_win32_surface_get_extents (void uint32_t _cairo_win32_flags_for_dc (HDC dc); 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, 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); diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c --- a/gfx/cairo/cairo/src/cairo-win32-surface.c +++ b/gfx/cairo/cairo/src/cairo-win32-surface.c @@ -1607,24 +1607,25 @@ static cairo_status_t _cairo_win32_surface_flush (void *abstract_surface) { return _cairo_win32_surface_set_clip_region (abstract_surface, NULL); } #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) { #ifdef CAIRO_HAS_WIN32_FONT if (scaled_font->backend->type == CAIRO_FONT_TYPE_DWRITE) { #ifdef CAIRO_HAS_DWRITE_FONT return _cairo_dwrite_show_glyphs_on_surface(surface, op, source, glyphs, num_glyphs, scaled_font, clip); #endif } else { cairo_win32_surface_t *dst = surface; @@ -1737,29 +1738,20 @@ _cairo_win32_surface_show_glyphs (void dxy_buf[j+1] = _cairo_lround (logical_y - next_logical_y); /* note that GDI coordinate system is inverted */ logical_x = next_logical_x; logical_y = next_logical_y; } } - /* 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)) - { + if (glyph_indexing) + glyph_index_option = ETO_GLYPH_INDEX; + else glyph_index_option = 0; - } - else - { - glyph_index_option = ETO_GLYPH_INDEX; - } win_result = ExtTextOutW(dst->dc, start_x, start_y, glyph_index_option | ETO_PDY, NULL, glyph_buf, num_glyphs, @@ -1778,16 +1770,37 @@ _cairo_win32_surface_show_glyphs (void } #else return CAIRO_INT_STATUS_UNSUPPORTED; #endif } #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); +} + static cairo_surface_t * cairo_win32_surface_create_internal (HDC hdc, cairo_format_t format) { cairo_win32_surface_t *surface; RECT rect; surface = malloc (sizeof (cairo_win32_surface_t));