[cairo-commit] 8 commits - src/cairo-mutex-impl-private.h src/cairo-win32-printing-surface.c src/cairo-win32-private.h src/cairo-win32-surface.c
Adrian Johnson
ajohnson at kemper.freedesktop.org
Tue Sep 22 06:18:21 PDT 2009
src/cairo-mutex-impl-private.h | 11 ++-
src/cairo-win32-printing-surface.c | 131 +++++++++++++++++++++++++++++++------
src/cairo-win32-private.h | 2
src/cairo-win32-surface.c | 13 ++-
4 files changed, 133 insertions(+), 24 deletions(-)
New commits:
commit e74cb7fa3eb9a9bcdeb298d969b70fd99ba50f3d
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Tue Sep 22 22:44:34 2009 +0930
win32-printing: correct the use of the CAIRO_HAS_WIN32_FONT #ifdef
it was wrapping code required for non windows fonts.
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 914b4ca..8203e6a 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -1479,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,
@@ -1494,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);
}
commit 3dd2cc8f6d84253f93affecd3022c9fe4a25d60f
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Tue Sep 22 22:40:53 2009 +0930
win32-printing: fix meta surface pattern regression caused by bed2701e
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 00a84a3..914b4ca 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -418,6 +418,8 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t *surfa
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;
commit 7658635c654b694b516e5dd44a43611d94e91abd
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Tue Sep 22 22:36:20 2009 +0930
win32-printing: Allow GDI CTM with scale < 1 to be set
To better support creating EMF files with the win32-printing surface,
allow a GDI CTM with scale < 1 to be used.
http://lists.cairographics.org/archives/cairo/2009-September/018110.html
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index ea5dd35..00a84a3 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -354,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;
}
@@ -716,7 +718,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);
@@ -1340,7 +1342,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) {
@@ -1352,7 +1354,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);
}
@@ -1551,10 +1554,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,
@@ -1642,16 +1646,67 @@ _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)
@@ -1662,9 +1717,6 @@ _cairo_win32_printing_surface_start_page (void *abstract_surface)
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;
diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h
index c1040e8..4d0f85e 100644
--- a/src/cairo-win32-private.h
+++ b/src/cairo-win32-private.h
@@ -96,6 +96,8 @@ typedef struct _cairo_win32_surface {
cairo_bool_t path_empty;
cairo_bool_t has_ctm;
cairo_matrix_t ctm;
+ cairo_bool_t has_gdi_ctm;
+ cairo_matrix_t gdi_ctm;
HBRUSH brush, old_brush;
cairo_scaled_font_subsets_t *font_subsets;
} cairo_win32_surface_t;
commit 19c091670302fd23a676e680308df49a4ba06687
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Tue Sep 22 22:35:33 2009 +0930
Make win32 fonts work in EMF files created by win32-printing
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index f20b5f9..ea5dd35 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -123,6 +123,42 @@ _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)
{
@@ -1713,6 +1749,7 @@ cairo_win32_printing_surface_create (HDC hdc)
_cairo_win32_printing_surface_init_ps_mode (surface);
_cairo_win32_printing_surface_init_image_support (surface);
+ _cairo_win32_printing_surface_init_language_pack (surface);
_cairo_surface_init (&surface->base,
&cairo_win32_printing_surface_backend,
CAIRO_CONTENT_COLOR_ALPHA);
commit f01a54266d57763635f984982bec001a393d8aa2
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Tue Sep 22 22:34:56 2009 +0930
Fix compiler warnings in win32-surface
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index f6fd66b..c250668 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -2149,7 +2149,7 @@ void
_cairo_win32_debug_dump_hrgn (HRGN rgn, char *header)
{
RGNDATA *rd;
- int z;
+ unsigned int z;
if (header)
fprintf (stderr, "%s\n", header);
@@ -2162,11 +2162,17 @@ _cairo_win32_debug_dump_hrgn (HRGN rgn, char *header)
rd = (RGNDATA*) malloc(z);
z = GetRegionData(rgn, z, rd);
- fprintf (stderr, " %d rects, bounds: %d %d %d %d\n", rd->rdh.nCount, rd->rdh.rcBound.left, rd->rdh.rcBound.top, rd->rdh.rcBound.right - rd->rdh.rcBound.left, rd->rdh.rcBound.bottom - rd->rdh.rcBound.top);
+ fprintf (stderr, " %ld rects, bounds: %ld %ld %ld %ld\n",
+ rd->rdh.nCount,
+ rd->rdh.rcBound.left,
+ rd->rdh.rcBound.top,
+ rd->rdh.rcBound.right - rd->rdh.rcBound.left,
+ rd->rdh.rcBound.bottom - rd->rdh.rcBound.top);
for (z = 0; z < rd->rdh.nCount; z++) {
RECT r = ((RECT*)rd->Buffer)[z];
- fprintf (stderr, " [%d]: [%d %d %d %d]\n", z, r.left, r.top, r.right - r.left, r.bottom - r.top);
+ fprintf (stderr, " [%d]: [%ld %ld %ld %ld]\n",
+ z, r.left, r.top, r.right - r.left, r.bottom - r.top);
}
free(rd);
commit 23663e2078e34659af43bd0e62bb1fb7a94cc71e
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Tue Sep 22 22:34:21 2009 +0930
Fix compiler error on cygwin
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 69afa17..f6fd66b 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -53,6 +53,7 @@
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-surface-fallback-private.h"
+#include <wchar.h>
#include <windows.h>
#if defined(__MINGW32__) && !defined(ETO_PDY)
commit 7ecd413fab7c55918c6f3c4c272b5e8b5aa89aa7
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Tue Sep 22 22:33:14 2009 +0930
Add WINVER defines to cairo-mutex-impl-privaye.h
The WINVER defines should always be defined before including windows.h
diff --git a/src/cairo-mutex-impl-private.h b/src/cairo-mutex-impl-private.h
index 4aeaa86..f601db9 100644
--- a/src/cairo-mutex-impl-private.h
+++ b/src/cairo-mutex-impl-private.h
@@ -170,6 +170,15 @@
#elif defined(_WIN32) /******************************************************/
+#define WIN32_LEAN_AND_MEAN
+/* We require Windows 2000 features such as ETO_PDY */
+#if !defined(WINVER) || (WINVER < 0x0500)
+# define WINVER 0x0500
+#endif
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
+# define _WIN32_WINNT 0x0500
+#endif
+
# include <windows.h>
typedef CRITICAL_SECTION cairo_mutex_impl_t;
commit 605ec22ab5103e16052591517f86fe558133fb8e
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Tue Sep 22 22:17:27 2009 +0930
Use _WIN32 to check for win32 mutex
Commit 535bcaa1 moved pthread after win32 to fix mingw build
problems. However this breaks cygwin builds.
On cygwin HAVE_WINDOWS_H is defined but _WIN32 is not. This was
causing windows.h to be included which defines _WIN32. As a result the
win32 code in cairo-misc.c was being compiled but the win32 declaration
in cairint.h was not included.
Fix this by using _WIN32 to enable the win32 mutex functions since
_WIN32 is defined by mingw, visual C++, and winegcc, but not
cygwin. On cygwin, posix functions are preferred as it is a unix
emulation environment.
diff --git a/src/cairo-mutex-impl-private.h b/src/cairo-mutex-impl-private.h
index 8ab7600..4aeaa86 100644
--- a/src/cairo-mutex-impl-private.h
+++ b/src/cairo-mutex-impl-private.h
@@ -168,7 +168,7 @@
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0
-#elif defined(HAVE_WINDOWS_H) || defined(_MSC_VER) /*************************/
+#elif defined(_WIN32) /******************************************************/
# include <windows.h>
More information about the cairo-commit
mailing list