diff options
author | Vladimir Vukicevic <vladimir@pobox.com> | 2007-08-28 10:40:33 -0700 |
---|---|---|
committer | Vladimir Vukicevic <vladimir@pobox.com> | 2007-08-28 10:54:20 -0700 |
commit | ae19b1c9911f95f64657f6ddaa0c924ca7a34b88 (patch) | |
tree | 7fb48701ef8a11948a7cace6de2704e849234c65 | |
parent | 69dae7ee4ace8a92226140ce5ccb690e7f62e35c (diff) |
[win32] Add cairo_win32_font_face_create_for_logfontw_hfont
Patch from: Robert O'Callahan <roc@ocallahans.org>
Add cairo_win32_font_face_create_for_logfontw_hfont, allow win32
scaled_fonts to rescale themselves properly to the required CTM and
only use the font_face's hfont if we're sure it's appropriate.
-rw-r--r-- | src/cairo-win32-font.c | 107 | ||||
-rw-r--r-- | src/cairo-win32.h | 3 |
2 files changed, 88 insertions, 22 deletions
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c index 681dba77..64df7e2f 100644 --- a/src/cairo-win32-font.c +++ b/src/cairo-win32-font.c @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2005 Red Hat, Inc @@ -226,9 +227,15 @@ _get_system_quality (void) } } +/* If face_hfont is non-NULL then font_matrix must be a simple scale by some + * factor S, ctm must be the identity, logfont->lfHeight must be -S, + * logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must + * all be 0, and face_hfont is the result of calling CreateFontIndirectW on + * logfont. + */ static cairo_scaled_font_t * _win32_scaled_font_create (LOGFONTW *logfont, - HFONT hfont, + HFONT face_hfont, cairo_font_face_t *font_face, const cairo_matrix_t *font_matrix, const cairo_matrix_t *ctm, @@ -274,11 +281,21 @@ _win32_scaled_font_create (LOGFONTW *logfont, } f->em_square = 0; - f->scaled_hfont = hfont; + f->scaled_hfont = NULL; f->unscaled_hfont = NULL; - /* don't delete the hfont if it was passed in to us */ - f->delete_scaled_hfont = !hfont; + if (f->quality == logfont->lfQuality || + (logfont->lfQuality == DEFAULT_QUALITY && + options->antialias == CAIRO_ANTIALIAS_DEFAULT)) { + /* If face_hfont is non-NULL, then we can use it to avoid creating our + * own --- because the constraints on face_hfont mentioned above + * guarantee it was created in exactly the same way that + * _win32_scaled_font_get_scaled_hfont would create it. + */ + f->scaled_hfont = face_hfont; + } + /* don't delete the hfont if we're using the one passed in to us */ + f->delete_scaled_hfont = !f->scaled_hfont; cairo_matrix_multiply (&scale, font_matrix, ctm); _compute_transform (f, &scale); @@ -1483,6 +1500,11 @@ const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = { typedef struct _cairo_win32_font_face cairo_win32_font_face_t; +/* If hfont is non-NULL then logfont->lfHeight must be -S for some S, + * logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must + * all be 0, and hfont is the result of calling CreateFontIndirectW on + * logfont. + */ struct _cairo_win32_font_face { cairo_font_face_t base; LOGFONTW logfont; @@ -1496,6 +1518,14 @@ _cairo_win32_font_face_destroy (void *abstract_face) { } +static cairo_bool_t +_is_scale (const cairo_matrix_t *matrix, double scale) +{ + return matrix->xx == scale && matrix->yy == scale && + matrix->xy == 0. && matrix->yx == 0. && + matrix->x0 == 0. && matrix->y0 == 0.; +} + static cairo_status_t _cairo_win32_font_face_scaled_font_create (void *abstract_face, const cairo_matrix_t *font_matrix, @@ -1503,10 +1533,20 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face, const cairo_font_options_t *options, cairo_scaled_font_t **font) { + HFONT hfont = NULL; + cairo_win32_font_face_t *font_face = abstract_face; + if (font_face->hfont) { + /* Check whether it's OK to go ahead and use the font-face's HFONT. */ + if (_is_scale (ctm, 1.) && + _is_scale (font_matrix, -font_face->logfont.lfHeight)) { + hfont = font_face->hfont; + } + } + *font = _win32_scaled_font_create (&font_face->logfont, - font_face->hfont, + hfont, &font_face->base, font_matrix, ctm, options); if (*font) @@ -1522,10 +1562,13 @@ static const cairo_font_face_backend_t _cairo_win32_font_face_backend = { }; /** - * cairo_win32_font_face_create_for_logfontw: + * cairo_win32_font_face_create_for_logfontw_hfont: * @logfont: A #LOGFONTW structure specifying the font to use. - * The lfHeight, lfWidth, lfOrientation and lfEscapement - * fields of this structure are ignored. + * If hfont is null then the lfHeight, lfWidth, lfOrientation and lfEscapement + * fields of this structure are ignored. Otherwise lfWidth, lfOrientation and + * lfEscapement must be zero. + * @font: An #HFONT that can be used when the font matrix is a scale by + * -lfHeight and the CTM is identity. * * Creates a new font for the Win32 font backend based on a * #LOGFONT. This font can then be used with @@ -1538,18 +1581,18 @@ static const cairo_font_face_backend_t _cairo_win32_font_face_backend = { * cairo_font_face_destroy() when you are done using it. **/ cairo_font_face_t * -cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont) +cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font) { cairo_win32_font_face_t *font_face; font_face = malloc (sizeof (cairo_win32_font_face_t)); if (!font_face) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_face_t *)&_cairo_font_face_nil; + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_font_face_t *)&_cairo_font_face_nil; } font_face->logfont = *logfont; - font_face->hfont = NULL; + font_face->hfont = font; _cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend); @@ -1557,6 +1600,28 @@ cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont) } /** + * cairo_win32_font_face_create_for_logfontw: + * @logfont: A #LOGFONTW structure specifying the font to use. + * The lfHeight, lfWidth, lfOrientation and lfEscapement + * fields of this structure are ignored. + * + * Creates a new font for the Win32 font backend based on a + * #LOGFONT. This font can then be used with + * cairo_set_font_face() or cairo_scaled_font_create(). + * The #cairo_scaled_font_t + * returned from cairo_scaled_font_create() is also for the Win32 backend + * and can be used with functions such as cairo_win32_scaled_font_select_font(). + * + * Return value: a newly created #cairo_font_face_t. Free with + * cairo_font_face_destroy() when you are done using it. + **/ +cairo_font_face_t * +cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont) +{ + return cairo_win32_font_face_create_for_logfontw_hfont (logfont, NULL); +} + +/** * cairo_win32_font_face_create_for_hfont: * @font: An #HFONT structure specifying the font to use. * @@ -1573,19 +1638,17 @@ cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont) cairo_font_face_t * cairo_win32_font_face_create_for_hfont (HFONT font) { - cairo_win32_font_face_t *font_face; + LOGFONTW logfont; + GetObject (font, sizeof(logfont), &logfont); - font_face = malloc (sizeof (cairo_win32_font_face_t)); - if (!font_face) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_face_t *)&_cairo_font_face_nil; + if (logfont.lfEscapement != 0 || logfont.lfOrientation != 0 || + logfont.lfWidth != 0) { + /* We can't use this font because that optimization requires that + * lfEscapement, lfOrientation and lfWidth be zero. */ + font = NULL; } - font_face->hfont = font; - - _cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend); - - return &font_face->base; + return cairo_win32_font_face_create_for_logfontw_hfont (&logfont, font); } /** diff --git a/src/cairo-win32.h b/src/cairo-win32.h index 8719d338..56643868 100644 --- a/src/cairo-win32.h +++ b/src/cairo-win32.h @@ -70,6 +70,9 @@ cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont); cairo_public cairo_font_face_t * cairo_win32_font_face_create_for_hfont (HFONT font); +cairo_public cairo_font_face_t * +cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font); + cairo_public cairo_status_t cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font, HDC hdc); |