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
This commit is contained in:
Adrian Johnson 2006-08-21 12:52:56 -04:00 committed by Kristian Høgsberg
parent 6de226be0e
commit 782e3eb65b

View file

@ -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;
}