summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorU-JONATHAN-X60S\jonathan <jonathan@Jonathan-X60s.(none)>2006-12-15 00:48:54 +0100
committerU-JONATHAN-X60S\jonathan <jonathan@Jonathan-X60s.(none)>2006-12-15 00:48:54 +0100
commitbf78be63fc35dc13899209ee818f37fe3f564fed (patch)
tree1afb18ed9552f0f28f6de6176f72728a12a7a04c
parenta87f494d4b91f3acc78d6d7dd737939633f28d71 (diff)
Fix a couple of character spacing issues on Windows
-rwxr-xr-x[-rw-r--r--]src/cairo-win32-surface.c105
-rwxr-xr-x[-rw-r--r--]src/cairo-win32.h10
-rwxr-xr-xsrc/cairoint.h10
3 files changed, 76 insertions, 49 deletions
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 8b34549c..4fb09df1 100644..100755
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1481,19 +1481,21 @@ _cairo_win32_surface_show_glyphs (void *surface,
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 *surface,
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. */
- 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;
- }
+ user_x = glyphs[0].x;
+ user_y = glyphs[0].y;
- output_count = 0;
+ cairo_matrix_transform_point(&device_to_logical,
+ &user_x, &user_y);
- if (i < num_glyphs - 1)
- last_y = glyphs[i+1].y;
- } else {
- last_y = glyphs[i].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;
+ }
+ }
+
+ 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
index 8719d338..17d02c54 100644..100755
--- 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 f855a413..97744334 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 */