From 782e3eb65b143a6e658eda69ba15da3ac432c711 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 21 Aug 2006 12:52:56 -0400 Subject: [PATCH] Get correct unhinted outlines on win32. The documentation for GetGlyphOutline() states that outline returned is grid fitted and if an application requires an unmodified outline it can request an outline for a font whose size is equal to the font's em unit. This seems to suggest that the solution to this bug would be to obtain the unmodified outline data and scale it to the required size. https://bugs.freedesktop.org/show_bug.cgi?id=7603 --- src/cairo-win32-font.c | 86 ++++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 25 deletions(-) diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c index 95a44e178..62c0f46d1 100644 --- a/src/cairo-win32-font.c +++ b/src/cairo-win32-font.c @@ -755,7 +755,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f else glyph_index_option = 0; - if (scaled_font->preserve_axes) { + if (scaled_font->preserve_axes && scaled_font->base.options.hint_style != CAIRO_HINT_METRICS_OFF) { /* If we aren't rotating / skewing the axes, then we get the metrics * from the GDI in device space and convert to font space. */ @@ -1107,7 +1107,7 @@ _compute_a8_mask (cairo_win32_surface_t *mask_surface) return &image8->base; } -static cairo_status_t +static cairo_int_status_t _cairo_win32_scaled_font_glyph_init (void *abstract_font, cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_glyph_info_t info) @@ -1275,10 +1275,18 @@ _cairo_win32_scaled_font_load_truetype_table (void *abstract_font, return status; } -static cairo_fixed_t -_cairo_fixed_from_FIXED (FIXED f) +static void +_cairo_win32_transform_FIXED_to_fixed (cairo_matrix_t *matrix, + FIXED Fx, FIXED Fy, + cairo_fixed_t *fx, cairo_fixed_t *fy) { - return *((cairo_fixed_t *)&f); + double x, y; + + x = _cairo_fixed_to_double (*((cairo_fixed_t *)&Fx)); + y = _cairo_fixed_to_double (*((cairo_fixed_t *)&Fy)); + cairo_matrix_transform_point (matrix, &x, &y); + *fx = _cairo_fixed_from_double (x); + *fy = _cairo_fixed_from_double (y); } static cairo_status_t @@ -1292,6 +1300,8 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font DWORD bytesGlyph; unsigned char *buffer, *ptr; cairo_path_fixed_t *path; + cairo_matrix_t transform; + cairo_fixed_t x, y; UINT glyph_index_option; hdc = _get_global_font_dc (); @@ -1302,7 +1312,14 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font if (!path) return CAIRO_STATUS_NO_MEMORY; - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); + if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE) { + status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); + transform = scaled_font->base.scale; + cairo_matrix_scale (&transform, 1.0/scaled_font->em_square, 1.0/scaled_font->em_square); + } else { + status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); + cairo_matrix_init_identity(&transform); + } if (status) goto CLEANUP_PATH; @@ -1341,9 +1358,11 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font ptr += sizeof (TTPOLYGONHEADER); - _cairo_path_fixed_move_to (path, - _cairo_fixed_from_FIXED (header->pfxStart.x), - _cairo_fixed_from_FIXED (header->pfxStart.y)); + _cairo_win32_transform_FIXED_to_fixed (&transform, + header->pfxStart.x, + header->pfxStart.y, + &x, &y); + _cairo_path_fixed_move_to (path, x, y); while (ptr < endPoly) { TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr; @@ -1352,26 +1371,36 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font switch (curve->wType) { case TT_PRIM_LINE: for (i = 0; i < curve->cpfx; i++) { - _cairo_path_fixed_line_to (path, - _cairo_fixed_from_FIXED (points[i].x), - _cairo_fixed_from_FIXED (points[i].y)); + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i].x, + points[i].y, + &x, &y); + _cairo_path_fixed_line_to (path, x, y); } break; case TT_PRIM_QSPLINE: for (i = 0; i < curve->cpfx - 1; i++) { cairo_fixed_t p1x, p1y, p2x, p2y, cx, cy, c1x, c1y, c2x, c2y; _cairo_path_fixed_get_current_point (path, &p1x, &p1y); - cx = _cairo_fixed_from_FIXED (points[i].x); - cy = _cairo_fixed_from_FIXED (points[i].y); + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i].x, + points[i].y, + &cx, &cy); if (i + 1 == curve->cpfx - 1) { - p2x = _cairo_fixed_from_FIXED (points[i + 1].x); - p2y = _cairo_fixed_from_FIXED (points[i + 1].y); + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i + 1].x, + points[i + 1].y, + &p2x, &p2y); } else { /* records with more than one curve use interpolation for control points, per http://support.microsoft.com/kb/q87115/ */ - p2x = (cx + _cairo_fixed_from_FIXED (points[i + 1].x)) / 2; - p2y = (cy + _cairo_fixed_from_FIXED (points[i + 1].y)) / 2; + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i + 1].x, + points[i + 1].y, + &x, &y); + p2x = (cx + x) / 2; + p2y = (cy + y) / 2; } c1x = 2 * cx / 3 + p1x / 3; @@ -1384,13 +1413,20 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font break; case TT_PRIM_CSPLINE: for (i = 0; i < curve->cpfx - 2; i += 2) { - _cairo_path_fixed_curve_to (path, - _cairo_fixed_from_FIXED (points[i].x), - _cairo_fixed_from_FIXED (points[i].y), - _cairo_fixed_from_FIXED (points[i + 1].x), - _cairo_fixed_from_FIXED (points[i + 1].y), - _cairo_fixed_from_FIXED (points[i + 2].x), - _cairo_fixed_from_FIXED (points[i + 2].y)); + cairo_fixed_t x1, y1, x2, y2; + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i].x, + points[i].y, + &x, &y); + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i + 1].x, + points[i + 1].y, + &x1, &y1); + _cairo_win32_transform_FIXED_to_fixed (&transform, + points[i + 2].x, + points[i + 2].y, + &x2, &y2); + _cairo_path_fixed_curve_to (path, x, y, x1, y1, x2, y2); } break; }