[cairo-commit] 2 commits - src/cairoint.h src/cairo-win32.h src/cairo-win32-surface.c

Jonathan Watt jwatt at kemper.freedesktop.org
Thu Dec 14 17:38:11 PST 2006


 src/cairo-win32-surface.c |  109 +++++++++++++++++++++++++---------------------
 src/cairo-win32.h         |   10 ++++
 src/cairoint.h            |   10 +++-
 3 files changed, 78 insertions(+), 51 deletions(-)

New commits:
diff-tree 15e8486ef1558b8049a4c7a5c2f50a7e4a2599da (from parents)
Merge: bf78be63fc35dc13899209ee818f37fe3f564fed 8b31038b9fb7f8fc3eb2729c3d14de5c0b130873
Author: U-JONATHAN-X60S\jonathan <jonathan at Jonathan-X60s.(none)>
Date:   Fri Dec 15 02:31:13 2006 +0100

    Merge branch 'master' of git://git.cairographics.org/git/cairo

diff-tree bf78be63fc35dc13899209ee818f37fe3f564fed (from a87f494d4b91f3acc78d6d7dd737939633f28d71)
Author: U-JONATHAN-X60S\jonathan <jonathan at Jonathan-X60s.(none)>
Date:   Fri Dec 15 00:48:54 2006 +0100

    Fix a couple of character spacing issues on Windows

diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
old mode 100644
new mode 100755
index 8b34549..4fb09df
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1481,19 +1481,21 @@ _cairo_win32_surface_show_glyphs (void		
 
     WORD glyph_buf_stack[STACK_GLYPH_SIZE];
     WORD *glyph_buf = glyph_buf_stack;
-    int dx_buf_stack[STACK_GLYPH_SIZE];
-    int *dx_buf = dx_buf_stack;
+    int dxy_buf_stack[2 * STACK_GLYPH_SIZE];
+    int *dxy_buf = dxy_buf_stack;
 
     BOOL win_result = 0;
-    int i;
-    double last_y = glyphs[0].y;
+    int i, j;
 
     cairo_solid_pattern_t *solid_pattern;
     COLORREF color;
-    int output_count = 0;
 
     cairo_matrix_t device_to_logical;
 
+    int start_x, start_y;
+    double user_x, user_y;
+    int logical_x, logical_y;
+
     /* We can only handle win32 fonts */
     if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1531,59 +1533,68 @@ _cairo_win32_surface_show_glyphs (void		
 
     if (num_glyphs > STACK_GLYPH_SIZE) {
 	glyph_buf = (WORD *)malloc(num_glyphs * sizeof(WORD));
-	dx_buf = (int *)malloc(num_glyphs * sizeof(int));
+        dxy_buf = (int *)malloc(num_glyphs * 2 * sizeof(int));
     }
 
-    for (i = 0; i < num_glyphs; ++i) {
-	output_count++;
+    /* It is vital that dx values for dxy_buf are calculated from the delta of
+     * _logical_ x coordinates (not user x coordinates) or else the sum of all
+     * previous dx values may start to diverge from the current glyph's x
+     * coordinate due to accumulated rounding error. As a result strings could
+     * be painted shorter or longer than expected. */
+
+    user_x = glyphs[0].x;
+    user_y = glyphs[0].y;
+
+    cairo_matrix_transform_point(&device_to_logical,
+                                 &user_x, &user_y);
+
+    logical_x = _cairo_lround (user_x);
+    logical_y = _cairo_lround (user_y);
+
+    start_x = logical_x;
+    start_y = logical_y;
+
+    for (i = 0, j = 0; i < num_glyphs; ++i, j = 2 * i) {
+        glyph_buf[i] = (WORD) glyphs[i].index;
+        if (i == num_glyphs - 1) {
+            dxy_buf[j] = 0;
+            dxy_buf[j+1] = 0;
+        } else {
+            double next_user_x = glyphs[i+1].x;
+            double next_user_y = glyphs[i+1].y;
+            int next_logical_x, next_logical_y;
+
+            cairo_matrix_transform_point(&device_to_logical,
+                                         &next_user_x, &next_user_y);
+
+            next_logical_x = _cairo_lround (next_user_x);
+            next_logical_y = _cairo_lround (next_user_y);
+
+            dxy_buf[j] = _cairo_lround ((next_logical_x - logical_x) * WIN32_FONT_LOGICAL_SCALE);
+            dxy_buf[j+1] = _cairo_lround ((logical_y - start_y) * WIN32_FONT_LOGICAL_SCALE);
+
+            logical_x = next_logical_x;
+            logical_y = next_logical_y;
+        }
+    }
 
-	glyph_buf[i] = (WORD) glyphs[i].index;
-	if (i == num_glyphs - 1)
-	    dx_buf[i] = 0;
-	else
-	    dx_buf[i] = _cairo_lround ((glyphs[i+1].x - glyphs[i].x) *
-                                       WIN32_FONT_LOGICAL_SCALE);
-
-	if (i == num_glyphs - 1 || glyphs[i].y != glyphs[i+1].y) {
-	    const int offset = (i - output_count) + 1;
-	    double user_x = glyphs[offset].x;
-	    double user_y = last_y;
-	    int logical_x, logical_y;
-
-	    cairo_matrix_transform_point(&device_to_logical,
-					 &user_x, &user_y);
-
-	    logical_x = _cairo_lround (user_x);
-	    logical_y = _cairo_lround (user_y);
-
-	    win_result = ExtTextOutW(dst->dc,
-				     logical_x,
-				     logical_y,
-				     ETO_GLYPH_INDEX,
-				     NULL,
-				     glyph_buf + offset,
-				     output_count,
-				     dx_buf + offset);
-	    if (!win_result) {
-		_cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)");
-		goto FAIL;
-	    }
-
-	    output_count = 0;
-
-	    if (i < num_glyphs - 1)
-		last_y = glyphs[i+1].y;
-	} else {
-	    last_y = glyphs[i].y;
-	}
+    win_result = ExtTextOutW(dst->dc,
+                             start_x,
+                             start_y,
+                             ETO_GLYPH_INDEX | ETO_PDY,
+                             NULL,
+                             glyph_buf,
+                             num_glyphs,
+                             dxy_buf);
+    if (!win_result) {
+        _cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)");
     }
 
-FAIL:
     RestoreDC(dst->dc, -1);
 
     if (glyph_buf != glyph_buf_stack) {
 	free(glyph_buf);
-	free(dx_buf);
+        free(dxy_buf);
     }
     return (win_result) ? CAIRO_STATUS_SUCCESS : CAIRO_INT_STATUS_UNSUPPORTED;
 }
diff --git a/src/cairo-win32.h b/src/cairo-win32.h
old mode 100644
new mode 100755
index 8719d33..17d02c5
--- a/src/cairo-win32.h
+++ b/src/cairo-win32.h
@@ -40,6 +40,16 @@
 
 #if CAIRO_HAS_WIN32_SURFACE
 
+#define WIN32_LEAN_AND_MEAN
+/* We require Windows 2000 features. Although we don't use them here, things
+ * should still work if this header file ends up being the one to include
+ * windows.h into a source file, so: */
+#if !defined(WINVER) || (WINVER < 0x0500)
+# define WINVER 0x0500
+#endif
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
+# define _WIN32_WINNT 0x0500
+#endif
 #include <windows.h>
 
 CAIRO_BEGIN_DECLS
diff --git a/src/cairoint.h b/src/cairoint.h
index f855a41..9774433 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -149,8 +149,14 @@ CAIRO_BEGIN_DECLS
 
 #if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_WIN32_SURFACE
 # define WIN32_LEAN_AND_MEAN
-# ifndef WINVER
-#  define WINVER 0xFFFFF /* use newest and greatest */
+/* We require Windows 2000 features. Although we don't use them here, things
+ * should still work if this header file ends up being the one to include
+ * windows.h into a source file, so: */
+# if !defined(WINVER) || (WINVER < 0x0500)
+#  define WINVER 0x0500
+# endif
+# if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
+#  define _WIN32_WINNT 0x0500
 # endif
 # include <windows.h>
   /* the real initialization must take place in DllMain */


More information about the cairo-commit mailing list