diff options
author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2009-10-16 08:21:27 +0200 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2009-10-16 08:21:27 +0200 |
commit | 0b05d5812d0ceaeb5a9db5a50be0d3f7f16b277a (patch) | |
tree | c564d4accd135ebbd3c3e66a37c1f223996aed12 /src/cairo-win32-printing-surface.c | |
parent | 0e79096a3831c10cf9735a7f518bfb65d0632923 (diff) |
Import upstream version 1.9.4
Diffstat (limited to 'src/cairo-win32-printing-surface.c')
-rw-r--r-- | src/cairo-win32-printing-surface.c | 343 |
1 files changed, 209 insertions, 134 deletions
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c index e7ff3bb..8203e6a 100644 --- a/src/cairo-win32-printing-surface.c +++ b/src/cairo-win32-printing-surface.c @@ -53,6 +53,7 @@ #include "cairo-meta-surface-private.h" #include "cairo-scaled-font-subsets-private.h" #include "cairo-image-info-private.h" +#include "cairo-surface-clipper-private.h" #include <windows.h> @@ -122,13 +123,49 @@ _cairo_win32_printing_surface_init_image_support (cairo_win32_surface_t *surface surface->flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_PNG; } +/* When creating an EMF file, ExtTextOut with ETO_GLYPH_INDEX does not + * work unless the GDI function GdiInitializeLanguagePack() has been + * called. + * + * http://m-a-tech.blogspot.com/2009/04/emf-buffer-idiocracy.html + * + * The only information I could find on the how to use this + * undocumented function is the use in: + * + * http://src.chromium.org/viewvc/chrome/trunk/src/chrome/renderer/render_process.cc?view=markup + * + * to solve the same problem. The above code first checks if LPK.DLL + * is already loaded. If it is not it calls + * GdiInitializeLanguagePack() using the prototype + * BOOL GdiInitializeLanguagePack (int) + * and argument 0. + */ +static void +_cairo_win32_printing_surface_init_language_pack (cairo_win32_surface_t *surface) +{ + typedef BOOL (WINAPI *gdi_init_lang_pack_func_t)(int); + gdi_init_lang_pack_func_t gdi_init_lang_pack; + HMODULE module; + + if (GetModuleHandleW (L"LPK.DLL")) + return; + + module = GetModuleHandleW (L"GDI32.DLL"); + if (module) { + gdi_init_lang_pack = (gdi_init_lang_pack_func_t) + GetProcAddress (module, "GdiInitializeLanguagePack"); + if (gdi_init_lang_pack) + gdi_init_lang_pack (0); + } +} + static cairo_int_status_t analyze_surface_pattern_transparency (cairo_surface_pattern_t *pattern) { cairo_image_surface_t *image; void *image_extra; cairo_int_status_t status; - int x, y; + cairo_image_transparency_t transparency; status = _cairo_surface_acquire_source_image (pattern->surface, &image, @@ -136,38 +173,20 @@ analyze_surface_pattern_transparency (cairo_surface_pattern_t *pattern) if (status) return status; - if (image->base.status) - return image->base.status; - - if (image->format == CAIRO_FORMAT_RGB24) { + transparency = _cairo_image_analyze_transparency (image); + switch (transparency) { + case CAIRO_IMAGE_UNKNOWN: + ASSERT_NOT_REACHED; + case CAIRO_IMAGE_IS_OPAQUE: status = CAIRO_STATUS_SUCCESS; - goto RELEASE_SOURCE; - } + break; - if (image->format != CAIRO_FORMAT_ARGB32) { - /* If the surface does not support the image format, assume - * that it does have alpha. The image will be converted to - * rgb24 when the surface blends the image into the page - * color to remove the transparency. */ + case CAIRO_IMAGE_HAS_BILEVEL_ALPHA: + case CAIRO_IMAGE_HAS_ALPHA: status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; - goto RELEASE_SOURCE; - } - - for (y = 0; y < image->height; y++) { - int a; - uint32_t *pixel = (uint32_t *) (image->data + y * image->stride); - - for (x = 0; x < image->width; x++, pixel++) { - a = (*pixel & 0xff000000) >> 24; - if (a != 255) { - status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; - goto RELEASE_SOURCE; - } - } + break; } - status = CAIRO_STATUS_SUCCESS; -RELEASE_SOURCE: _cairo_surface_release_source_image (pattern->surface, image, image_extra); return status; @@ -176,8 +195,6 @@ RELEASE_SOURCE: static cairo_bool_t surface_pattern_supported (const cairo_surface_pattern_t *pattern) { - cairo_extend_t extend; - if (_cairo_surface_is_meta (pattern->surface)) return TRUE; @@ -187,19 +204,7 @@ surface_pattern_supported (const cairo_surface_pattern_t *pattern) return FALSE; } - extend = cairo_pattern_get_extend ((cairo_pattern_t*)&pattern->base); - switch (extend) { - case CAIRO_EXTEND_NONE: - case CAIRO_EXTEND_REPEAT: - case CAIRO_EXTEND_REFLECT: - /* There's no point returning FALSE for EXTEND_PAD, as the image - * surface does not currently implement it either */ - case CAIRO_EXTEND_PAD: - return TRUE; - } - - ASSERT_NOT_REACHED; - return FALSE; + return TRUE; } static cairo_bool_t @@ -349,11 +354,13 @@ _cairo_win32_printing_surface_get_ctm_clip_box (cairo_win32_surface_t *surface, XFORM xform; _cairo_matrix_to_win32_xform (&surface->ctm, &xform); + if (!ModifyWorldTransform (surface->dc, &xform, MWT_LEFTMULTIPLY)) + return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:ModifyWorldTransform"); + GetClipBox (surface->dc, clip); + + _cairo_matrix_to_win32_xform (&surface->gdi_ctm, &xform); if (!SetWorldTransform (surface->dc, &xform)) return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:SetWorldTransform"); - GetClipBox (surface->dc, clip); - if (!ModifyWorldTransform (surface->dc, &xform, MWT_IDENTITY)) - return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:ModifyWorldTransform"); return CAIRO_STATUS_SUCCESS; } @@ -390,7 +397,8 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t *surfa XFORM xform; int x_tile, y_tile, left, right, top, bottom; RECT clip; - cairo_surface_t *meta_surface = pattern->surface; + cairo_meta_surface_t *meta_surface = (cairo_meta_surface_t *) pattern->surface; + cairo_box_t bbox; extend = cairo_pattern_get_extend (&pattern->base); @@ -406,19 +414,21 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t *surfa SaveDC (surface->dc); _cairo_matrix_to_win32_xform (&p2d, &xform); - status = _cairo_surface_get_extents (meta_surface, &meta_extents); + status = _cairo_meta_surface_get_bbox (meta_surface, &bbox, NULL); if (status) return status; + _cairo_box_round_to_rectangle (&bbox, &meta_extents); + status = _cairo_win32_printing_surface_get_ctm_clip_box (surface, &clip); if (status) return status; if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) { - left = (int) floor((double)clip.left/meta_extents.width); - right = (int) ceil((double)clip.right/meta_extents.width); - top = (int) floor((double)clip.top/meta_extents.height); - bottom = (int) ceil((double)clip.bottom/meta_extents.height); + left = floor (clip.left / _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x)); + right = ceil (clip.right / _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x)); + top = floor (clip.top / _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y)); + bottom = ceil (clip.bottom / _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y)); } else { left = 0; right = 1; @@ -427,7 +437,7 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t *surfa } old_content = surface->content; - if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) { + if (meta_surface->base.content == CAIRO_CONTENT_COLOR) { cairo_pattern_t *source; cairo_solid_pattern_t black; @@ -490,7 +500,8 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t *surfa SelectClipPath (surface->dc, RGN_AND); SaveDC (surface->dc); /* Allow clip path to be reset during replay */ - status = _cairo_meta_surface_replay_region (meta_surface, &surface->base, + status = _cairo_meta_surface_replay_region (&meta_surface->base, + &surface->base, CAIRO_META_REGION_NATIVE); assert (status != CAIRO_INT_STATUS_UNSUPPORTED); /* Restore both the clip save and our earlier path SaveDC */ @@ -594,7 +605,6 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf cairo_extend_t extend; cairo_image_surface_t *image; void *image_extra; - cairo_surface_t *opaque_surface; cairo_image_surface_t *opaque_image = NULL; BITMAPINFO bi; cairo_matrix_t m; @@ -651,13 +661,15 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf &mime_size, &mime_info); } - if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) + if (_cairo_status_is_error (status)) return status; use_mime = (status == CAIRO_STATUS_SUCCESS); if (!use_mime && image->format != CAIRO_FORMAT_RGB24) { - cairo_surface_pattern_t opaque_pattern; + cairo_surface_t *opaque_surface; + cairo_surface_pattern_t image_pattern; + cairo_solid_pattern_t background_pattern; opaque_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, image->width, @@ -667,36 +679,27 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf goto CLEANUP_OPAQUE_IMAGE; } - _cairo_pattern_init_for_surface (&opaque_pattern, &image->base); - - status = _cairo_surface_fill_rectangle (opaque_surface, - CAIRO_OPERATOR_SOURCE, - background_color, - 0, 0, - image->width, image->height); - if (status) { - _cairo_pattern_fini (&opaque_pattern.base); + _cairo_pattern_init_solid (&background_pattern, + background_color, + CAIRO_CONTENT_COLOR); + status = _cairo_surface_paint (opaque_surface, + CAIRO_OPERATOR_SOURCE, + &background_pattern.base, + NULL); + if (status) goto CLEANUP_OPAQUE_IMAGE; - } - status = _cairo_surface_composite (CAIRO_OPERATOR_OVER, - &opaque_pattern.base, - NULL, - opaque_surface, - 0, 0, - 0, 0, - 0, 0, - image->width, - image->height); - if (status) { - _cairo_pattern_fini (&opaque_pattern.base); + _cairo_pattern_init_for_surface (&image_pattern, &image->base); + status = _cairo_surface_paint (opaque_surface, + CAIRO_OPERATOR_OVER, + &image_pattern.base, + NULL); + _cairo_pattern_fini (&image_pattern.base); + if (status) goto CLEANUP_OPAQUE_IMAGE; - } - _cairo_pattern_fini (&opaque_pattern.base); opaque_image = (cairo_image_surface_t *) opaque_surface; } else { - opaque_surface = &image->base; opaque_image = image; } @@ -717,7 +720,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf /* _cairo_pattern_set_matrix guarantees invertibility */ assert (status == CAIRO_STATUS_SUCCESS); - cairo_matrix_multiply (&m, &m, &surface->ctm); + cairo_matrix_multiply (&m, &m, &surface->gdi_ctm); SaveDC (surface->dc); _cairo_matrix_to_win32_xform (&m, &xform); @@ -730,10 +733,10 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf GetClipBox (surface->dc, &clip); if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) { - left = (int) floor((double)clip.left/opaque_image->width); - right = (int) ceil((double)clip.right/opaque_image->width); - top = (int) floor((double)clip.top/opaque_image->height); - bottom = (int) ceil((double)clip.bottom/opaque_image->height); + left = floor ( clip.left / (double) opaque_image->width); + right = ceil (clip.right / (double) opaque_image->width); + top = floor (clip.top / (double) opaque_image->height); + bottom = ceil (clip.bottom / (double) opaque_image->height); } else { left = 0; right = 1; @@ -767,7 +770,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf CLEANUP_OPAQUE_IMAGE: if (opaque_image != image) - cairo_surface_destroy (opaque_surface); + cairo_surface_destroy (&opaque_image->base); CLEANUP_IMAGE: _cairo_surface_release_source_image (pattern->surface, image, image_extra); @@ -850,8 +853,8 @@ _cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_surface_t *surfa GetClipBox (surface->dc, &clip); if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) { - range_start = (int) floor(clip.left/d); - range_stop = (int) ceil(clip.right/d); + range_start = floor (clip.left / d); + range_stop = ceil (clip.right / d); } else { range_start = 0; range_stop = 1; @@ -1085,17 +1088,15 @@ _cairo_win32_printing_surface_emit_path (cairo_win32_surface_t *surface, cairo_path_fixed_t *path) { win32_path_info_t path_info; - cairo_status_t status; path_info.surface = surface; - status = _cairo_path_fixed_interpret (path, - CAIRO_DIRECTION_FORWARD, - _cairo_win32_printing_surface_path_move_to, - _cairo_win32_printing_surface_path_line_to, - _cairo_win32_printing_surface_path_curve_to, - _cairo_win32_printing_surface_path_close_path, - &path_info); - return status; + return _cairo_path_fixed_interpret (path, + CAIRO_DIRECTION_FORWARD, + _cairo_win32_printing_surface_path_move_to, + _cairo_win32_printing_surface_path_line_to, + _cairo_win32_printing_surface_path_curve_to, + _cairo_win32_printing_surface_path_close_path, + &path_info); } static cairo_int_status_t @@ -1109,14 +1110,16 @@ _cairo_win32_printing_surface_show_page (void *abstract_surface) return CAIRO_STATUS_SUCCESS; } -static cairo_int_status_t -_cairo_win32_printing_surface_intersect_clip_path (void *abstract_surface, +static cairo_status_t +_cairo_win32_printing_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias) { - cairo_win32_surface_t *surface = abstract_surface; + cairo_win32_surface_t *surface = cairo_container_of (clipper, + cairo_win32_surface_t, + clipper); cairo_status_t status; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) @@ -1164,10 +1167,15 @@ static cairo_int_status_t _cairo_win32_printing_surface_paint (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, - cairo_rectangle_int_t *extents) + cairo_clip_t *clip) { cairo_win32_surface_t *surface = abstract_surface; cairo_solid_pattern_t clear; + cairo_status_t status; + + status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); + if (status) + return status; if (op == CAIRO_OPERATOR_CLEAR) { _cairo_win32_printing_surface_init_clear_color (surface, &clear); @@ -1242,7 +1250,7 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface, cairo_matrix_t *stroke_ctm_inverse, double tolerance, cairo_antialias_t antialias, - cairo_rectangle_int_t *extents) + cairo_clip_t *clip) { cairo_win32_surface_t *surface = abstract_surface; cairo_int_status_t status; @@ -1258,6 +1266,10 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface, cairo_matrix_t mat; double scale; + status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); + if (status) + return status; + if (op == CAIRO_OPERATOR_CLEAR) { _cairo_win32_printing_surface_init_clear_color (surface, &clear); source = (cairo_pattern_t*) &clear; @@ -1332,7 +1344,7 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface, xform.eDx = 0.0f; xform.eDy = 0.0f; - if (!SetWorldTransform (surface->dc, &xform)) + if (!ModifyWorldTransform (surface->dc, &xform, MWT_LEFTMULTIPLY)) return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SetWorldTransform"); if (source->type == CAIRO_PATTERN_TYPE_SOLID) { @@ -1344,7 +1356,8 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface, return _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectClipPath"); /* Return to device space to paint the pattern */ - if (!ModifyWorldTransform (surface->dc, &xform, MWT_IDENTITY)) + _cairo_matrix_to_win32_xform (&surface->gdi_ctm, &xform); + if (!SetWorldTransform (surface->dc, &xform)) return _cairo_win32_print_gdi_error ("_win32_surface_stroke:ModifyWorldTransform"); status = _cairo_win32_printing_surface_paint_pattern (surface, source); } @@ -1364,12 +1377,16 @@ _cairo_win32_printing_surface_fill (void *abstract_surface, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias, - cairo_rectangle_int_t *extents) + cairo_clip_t *clip) { cairo_win32_surface_t *surface = abstract_surface; cairo_int_status_t status; cairo_solid_pattern_t clear; + status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); + if (status) + return status; + if (op == CAIRO_OPERATOR_CLEAR) { _cairo_win32_printing_surface_init_clear_color (surface, &clear); source = (cairo_pattern_t*) &clear; @@ -1423,8 +1440,8 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac cairo_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font, - int *remaining_glyphs, - cairo_rectangle_int_t *extents) + cairo_clip_t *clip, + int *remaining_glyphs) { cairo_win32_surface_t *surface = abstract_surface; cairo_status_t status = CAIRO_STATUS_SUCCESS; @@ -1435,6 +1452,10 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac cairo_bool_t old_has_ctm; cairo_solid_pattern_t clear; + status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); + if (status) + return status; + if (op == CAIRO_OPERATOR_CLEAR) { _cairo_win32_printing_surface_init_clear_color (surface, &clear); source = (cairo_pattern_t*) &clear; @@ -1458,6 +1479,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac else return _cairo_win32_printing_surface_analyze_operation (surface, op, source); } +#endif /* For non win32 fonts we need to check that each glyph has a * path available. If a path is not available, @@ -1473,7 +1495,6 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac if (status) return status; } -#endif return _cairo_win32_printing_surface_analyze_operation (surface, op, source); } @@ -1535,10 +1556,11 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac glyphs = type1_glyphs; } - if (surface->has_ctm) { + 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 (&surface->ctm, &glyphs[i].x, &glyphs[i].y); - cairo_matrix_multiply (&ctm, &scaled_font->ctm, &surface->ctm); + 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, @@ -1547,8 +1569,8 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac status = _cairo_win32_surface_show_glyphs (surface, op, source, glyphs, num_glyphs, scaled_font, - remaining_glyphs, - extents); + clip, + remaining_glyphs); if (surface->has_ctm) cairo_scaled_font_destroy (scaled_font); @@ -1607,7 +1629,12 @@ _cairo_win32_printing_surface_create_similar (void *abstract_surface, int width, int height) { - return _cairo_meta_surface_create (content, width, height); + cairo_rectangle_t extents; + + extents.x = extents.y = 0; + extents.width = width; + extents.height = height; + return cairo_meta_surface_create (content, &extents); } static cairo_int_status_t @@ -1621,29 +1648,77 @@ _cairo_win32_printing_surface_start_page (void *abstract_surface) SaveDC (surface->dc); /* Save application context first, before doing MWT */ + /* As the logical coordinates used by GDI functions (eg LineTo) + * are integers we need to do some additional work to prevent + * rounding errors. For example the obvious way to paint a meta + * pattern is to: + * + * SaveDC() + * transform the device context DC by the pattern to device matrix + * replay the meta surface + * RestoreDC() + * + * The problem here is that if the pattern to device matrix is + * [100 0 0 100 0 0], coordinates in the meta pattern such as + * (1.56, 2.23) which correspond to (156, 223) in device space + * will be rounded to (100, 200) due to (1.56, 2.23) being + * truncated to integers. + * + * This is solved by saving the current GDI CTM in surface->ctm, + * switch the GDI CTM to identity, and transforming all + * coordinates by surface->ctm before passing them to GDI. When + * painting a meta pattern, surface->ctm is transformed by the + * pattern to device matrix. + * + * For printing device contexts where 1 unit is 1 dpi, switching + * the GDI CTM to identity maximises the possible resolution of + * coordinates. + * + * If the device context is an EMF file, using an identity + * transform often provides insufficent resolution. The workaround + * is to set the GDI CTM to a scale < 1 eg [1.0/16 0 0 1/0/16 0 0] + * and scale the cairo CTM by [16 0 0 16 0 0]. The + * SetWorldTransform function call to scale the GDI CTM by 1.0/16 + * will be recorded in the EMF followed by all the graphics + * functions by their coordinateds multiplied by 16. + * + * To support allowing the user to set a GDI CTM with scale < 1, + * we avoid switching to an identity CTM if the CTM xx and yy is < 1. + */ SetGraphicsMode (surface->dc, GM_ADVANCED); GetWorldTransform(surface->dc, &xform); - surface->ctm.xx = xform.eM11; - surface->ctm.xy = xform.eM21; - surface->ctm.yx = xform.eM12; - surface->ctm.yy = xform.eM22; - surface->ctm.x0 = xform.eDx; - surface->ctm.y0 = xform.eDy; - surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm); + if (xform.eM11 < 1 && xform.eM22 < 1) { + cairo_matrix_init_identity (&surface->ctm); + surface->gdi_ctm.xx = xform.eM11; + surface->gdi_ctm.xy = xform.eM21; + surface->gdi_ctm.yx = xform.eM12; + surface->gdi_ctm.yy = xform.eM22; + surface->gdi_ctm.x0 = xform.eDx; + surface->gdi_ctm.y0 = xform.eDy; + } else { + surface->ctm.xx = xform.eM11; + surface->ctm.xy = xform.eM21; + surface->ctm.yx = xform.eM12; + surface->ctm.yy = xform.eM22; + surface->ctm.x0 = xform.eDx; + surface->ctm.y0 = xform.eDy; + cairo_matrix_init_identity (&surface->gdi_ctm); + if (!ModifyWorldTransform (surface->dc, NULL, MWT_IDENTITY)) + return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_start_page:ModifyWorldTransform"); + } + surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm); + surface->has_gdi_ctm = !_cairo_matrix_is_identity (&surface->gdi_ctm); inverse_ctm = surface->ctm; status = cairo_matrix_invert (&inverse_ctm); if (status) return status; - x_res = (double) GetDeviceCaps(surface->dc, LOGPIXELSX); - y_res = (double) GetDeviceCaps(surface->dc, LOGPIXELSY); + x_res = GetDeviceCaps (surface->dc, LOGPIXELSX); + y_res = GetDeviceCaps (surface->dc, LOGPIXELSY); cairo_matrix_transform_distance (&inverse_ctm, &x_res, &y_res); _cairo_surface_set_resolution (&surface->base, x_res, y_res); - if (!ModifyWorldTransform (surface->dc, NULL, MWT_IDENTITY)) - return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_start_page:ModifyWorldTransform"); - SaveDC (surface->dc); /* Then save Cairo's known-good clip state, so the clip path can be reset */ return CAIRO_STATUS_SUCCESS; @@ -1698,6 +1773,9 @@ cairo_win32_printing_surface_create (HDC hdc) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } + _cairo_surface_clipper_init (&surface->clipper, + _cairo_win32_printing_surface_clipper_intersect_clip_path); + surface->image = NULL; surface->format = CAIRO_FORMAT_RGB24; surface->content = CAIRO_CONTENT_COLOR_ALPHA; @@ -1725,13 +1803,13 @@ cairo_win32_printing_surface_create (HDC hdc) _cairo_win32_printing_surface_init_ps_mode (surface); _cairo_win32_printing_surface_init_image_support (surface); - _cairo_surface_init (&surface->base, &cairo_win32_printing_surface_backend, + _cairo_win32_printing_surface_init_language_pack (surface); + _cairo_surface_init (&surface->base, + &cairo_win32_printing_surface_backend, CAIRO_CONTENT_COLOR_ALPHA); paginated = _cairo_paginated_surface_create (&surface->base, CAIRO_CONTENT_COLOR_ALPHA, - surface->extents.width, - surface->extents.height, &cairo_win32_surface_paginated_backend); /* paginated keeps the only reference to surface now, drop ours */ @@ -1754,7 +1832,7 @@ static const cairo_surface_backend_t cairo_win32_printing_surface_backend = { NULL, /* release_source_image */ NULL, /* acquire_dest_image */ NULL, /* release_dest_image */ - _cairo_win32_surface_clone_similar, + NULL, /* clone_similar */ NULL, /* composite */ NULL, /* fill_rectangles */ NULL, /* composite_trapezoids */ @@ -1762,8 +1840,6 @@ static const cairo_surface_backend_t cairo_win32_printing_surface_backend = { NULL, /* check_span_renderer */ NULL, /* copy_page */ _cairo_win32_printing_surface_show_page, - NULL, /* set_clip_region */ - _cairo_win32_printing_surface_intersect_clip_path, _cairo_win32_surface_get_extents, NULL, /* old_show_glyphs */ _cairo_win32_printing_surface_get_font_options, @@ -1779,7 +1855,6 @@ static const cairo_surface_backend_t cairo_win32_printing_surface_backend = { _cairo_win32_printing_surface_show_glyphs, NULL, /* snapshot */ NULL, /* is_similar */ - NULL, /* reset */ NULL, /* fill_stroke */ }; |