diff options
author | U-JONATHAN-X60S\jonathan <jonathan@Jonathan-X60s.(none)> | 2006-12-15 00:48:54 +0100 |
---|---|---|
committer | U-JONATHAN-X60S\jonathan <jonathan@Jonathan-X60s.(none)> | 2006-12-15 00:48:54 +0100 |
commit | bf78be63fc35dc13899209ee818f37fe3f564fed (patch) | |
tree | 1afb18ed9552f0f28f6de6176f72728a12a7a04c | |
parent | a87f494d4b91f3acc78d6d7dd737939633f28d71 (diff) |
Fix a couple of character spacing issues on Windows
-rwxr-xr-x[-rw-r--r--] | src/cairo-win32-surface.c | 105 | ||||
-rwxr-xr-x[-rw-r--r--] | src/cairo-win32.h | 10 | ||||
-rwxr-xr-x | src/cairoint.h | 10 |
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 */ |