1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2005 Red Hat, Inc
6 * This library is free software; you can redistribute it and/or
7 * modify it either under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation
9 * (the "LGPL") or, at your option, under the terms of the Mozilla
10 * Public License Version 1.1 (the "MPL"). If you do not alter this
11 * notice, a recipient may use your version of this file under either
12 * the MPL or the LGPL.
14 * You should have received a copy of the LGPL along with this library
15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17 * You should have received a copy of the MPL along with this library
18 * in the file COPYING-MPL-1.1
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License at
23 * http://www.mozilla.org/MPL/
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27 * the specific language governing rights and limitations.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is Red Hat, Inc.
36 #define WIN32_LEAN_AND_MEAN
37 /* We require Windows 2000 features such as GetGlyphIndices */
38 #if !defined(WINVER) || (WINVER < 0x0500)
39 # define WINVER 0x0500
41 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
42 # define _WIN32_WINNT 0x0500
47 #include "cairo-win32-private.h"
49 #include "cairo-array-private.h"
50 #include "cairo-error-private.h"
51 #include "cairo-image-surface-private.h"
52 #include "cairo-pattern-private.h"
53 #include "cairo-scaled-font-subsets-private.h"
57 #ifndef SPI_GETFONTSMOOTHINGTYPE
58 #define SPI_GETFONTSMOOTHINGTYPE 0x200a
60 #ifndef FE_FONTSMOOTHINGCLEARTYPE
61 #define FE_FONTSMOOTHINGCLEARTYPE 2
63 #ifndef CLEARTYPE_QUALITY
64 #define CLEARTYPE_QUALITY 5
66 #ifndef TT_PRIM_CSPLINE
67 #define TT_PRIM_CSPLINE 3
70 #define CMAP_TAG 0x70616d63
73 * SECTION:cairo-win32-fonts
75 * @Short_Description: Font support for Microsoft Windows
76 * @See_Also: #cairo_font_face_t
78 * The Microsoft Windows font backend is primarily used to render text on
79 * Microsoft Windows systems.
83 * CAIRO_HAS_WIN32_FONT:
85 * Defined if the Microsoft Windows font backend is available.
86 * This macro can be used to conditionally compile backend-specific code.
89 const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend;
92 cairo_scaled_font_t base;
98 /* We do drawing and metrics computation in a "logical space" which
99 * is similar to font space, except that it is scaled by a factor
100 * of the (desired font size) * (WIN32_FONT_LOGICAL_SCALE). The multiplication
101 * by WIN32_FONT_LOGICAL_SCALE allows for sub-pixel precision.
103 double logical_scale;
105 /* The size we should actually request the font at from Windows; differs
106 * from the logical_scale because it is quantized for orthogonal
111 /* Transformations from device <=> logical space
113 cairo_matrix_t logical_to_device;
114 cairo_matrix_t device_to_logical;
116 /* We special case combinations of 90-degree-rotations, scales and
117 * flips ... that is transformations that take the axes to the
118 * axes. If preserve_axes is true, then swap_axes/swap_x/swap_y
119 * encode the 8 possibilities for orientation (4 rotation angles with
120 * and without a flip), and scale_x, scale_y the scale components.
122 cairo_bool_t preserve_axes;
123 cairo_bool_t swap_axes;
129 /* The size of the design unit of the font
134 HFONT unscaled_hfont;
136 cairo_bool_t is_bitmap;
137 cairo_bool_t is_type1;
138 cairo_bool_t delete_scaled_hfont;
139 cairo_bool_t has_type1_notdef_index;
140 unsigned long type1_notdef_index;
141 } cairo_win32_scaled_font_t;
143 static cairo_status_t
144 _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font);
146 static cairo_status_t
147 _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font,
148 cairo_scaled_glyph_t *scaled_glyph);
150 static cairo_status_t
151 _cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font,
152 cairo_scaled_glyph_t *scaled_glyph);
154 static cairo_status_t
155 _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font,
156 cairo_scaled_glyph_t *scaled_glyph);
159 _cairo_win32_font_face_destroy (void *abstract_face);
162 #define NEARLY_ZERO(d) (fabs(d) < (1. / 65536.))
165 _get_global_font_dc (void)
170 hdc = CreateCompatibleDC (NULL);
172 _cairo_win32_print_gdi_error ("_get_global_font_dc");
176 if (!SetGraphicsMode (hdc, GM_ADVANCED)) {
177 _cairo_win32_print_gdi_error ("_get_global_font_dc");
186 static cairo_status_t
187 _compute_transform (cairo_win32_scaled_font_t *scaled_font,
190 cairo_status_t status;
192 if (NEARLY_ZERO (sc->yx) && NEARLY_ZERO (sc->xy) &&
193 !NEARLY_ZERO(sc->xx) && !NEARLY_ZERO(sc->yy)) {
194 scaled_font->preserve_axes = TRUE;
195 scaled_font->x_scale = sc->xx;
196 scaled_font->swap_x = (sc->xx < 0);
197 scaled_font->y_scale = sc->yy;
198 scaled_font->swap_y = (sc->yy < 0);
199 scaled_font->swap_axes = FALSE;
201 } else if (NEARLY_ZERO (sc->xx) && NEARLY_ZERO (sc->yy) &&
202 !NEARLY_ZERO(sc->yx) && !NEARLY_ZERO(sc->xy)) {
203 scaled_font->preserve_axes = TRUE;
204 scaled_font->x_scale = sc->yx;
205 scaled_font->swap_x = (sc->yx < 0);
206 scaled_font->y_scale = sc->xy;
207 scaled_font->swap_y = (sc->xy < 0);
208 scaled_font->swap_axes = TRUE;
211 scaled_font->preserve_axes = FALSE;
212 scaled_font->swap_x = scaled_font->swap_y = scaled_font->swap_axes = FALSE;
215 if (scaled_font->preserve_axes) {
216 if (scaled_font->swap_x)
217 scaled_font->x_scale = - scaled_font->x_scale;
218 if (scaled_font->swap_y)
219 scaled_font->y_scale = - scaled_font->y_scale;
221 scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
222 scaled_font->logical_size = WIN32_FONT_LOGICAL_SCALE *
223 _cairo_lround (scaled_font->y_scale);
226 /* The font matrix has x and y "scale" components which we extract and
227 * use as character scale values.
229 cairo_matrix_init (&scaled_font->logical_to_device,
230 sc->xx, sc->yx, sc->xy, sc->yy, 0, 0);
232 if (!scaled_font->preserve_axes) {
233 status = _cairo_matrix_compute_basis_scale_factors (&scaled_font->logical_to_device,
234 &scaled_font->x_scale, &scaled_font->y_scale,
235 TRUE); /* XXX: Handle vertical text */
239 scaled_font->logical_size = _cairo_lround (WIN32_FONT_LOGICAL_SCALE *
240 scaled_font->y_scale);
241 scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
244 cairo_matrix_scale (&scaled_font->logical_to_device,
245 1.0 / scaled_font->logical_scale, 1.0 / scaled_font->logical_scale);
247 scaled_font->device_to_logical = scaled_font->logical_to_device;
249 status = cairo_matrix_invert (&scaled_font->device_to_logical);
251 cairo_matrix_init_identity (&scaled_font->device_to_logical);
253 return CAIRO_STATUS_SUCCESS;
257 _have_cleartype_quality (void)
259 OSVERSIONINFO version_info;
261 version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
263 if (!GetVersionEx (&version_info)) {
264 _cairo_win32_print_gdi_error ("_have_cleartype_quality");
268 return (version_info.dwMajorVersion > 5 ||
269 (version_info.dwMajorVersion == 5 &&
270 version_info.dwMinorVersion >= 1)); /* XP or newer */
274 _get_system_quality (void)
279 if (!SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) {
280 _cairo_win32_print_gdi_error ("_get_system_quality");
281 return DEFAULT_QUALITY;
284 if (font_smoothing) {
285 if (_have_cleartype_quality ()) {
286 if (!SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE,
287 0, &smoothing_type, 0)) {
288 _cairo_win32_print_gdi_error ("_get_system_quality");
289 return DEFAULT_QUALITY;
292 if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE)
293 return CLEARTYPE_QUALITY;
296 return ANTIALIASED_QUALITY;
298 return DEFAULT_QUALITY;
302 /* If face_hfont is non-%NULL then font_matrix must be a simple scale by some
303 * factor S, ctm must be the identity, logfont->lfHeight must be -S,
304 * logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must
305 * all be 0, and face_hfont is the result of calling CreateFontIndirectW on
308 static cairo_status_t
309 _win32_scaled_font_create (LOGFONTW *logfont,
311 cairo_font_face_t *font_face,
312 const cairo_matrix_t *font_matrix,
313 const cairo_matrix_t *ctm,
314 const cairo_font_options_t *options,
315 cairo_scaled_font_t **font_out)
318 cairo_win32_scaled_font_t *f;
319 cairo_matrix_t scale;
320 cairo_status_t status;
322 hdc = _get_global_font_dc ();
324 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
326 f = malloc (sizeof(cairo_win32_scaled_font_t));
328 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
330 f->logfont = *logfont;
332 /* We don't have any control over the hinting style or subpixel
333 * order in the Win32 font API, so we ignore those parts of
334 * cairo_font_options_t. We use the 'antialias' field to set
337 * XXX: The other option we could pay attention to, but don't
338 * here is the hint_metrics options.
340 if (options->antialias == CAIRO_ANTIALIAS_DEFAULT)
341 f->quality = _get_system_quality ();
343 switch (options->antialias) {
344 case CAIRO_ANTIALIAS_NONE:
345 f->quality = NONANTIALIASED_QUALITY;
347 case CAIRO_ANTIALIAS_GRAY:
348 case CAIRO_ANTIALIAS_FAST:
349 case CAIRO_ANTIALIAS_GOOD:
350 f->quality = ANTIALIASED_QUALITY;
352 case CAIRO_ANTIALIAS_SUBPIXEL:
353 case CAIRO_ANTIALIAS_BEST:
354 if (_have_cleartype_quality ())
355 f->quality = CLEARTYPE_QUALITY;
357 f->quality = ANTIALIASED_QUALITY;
359 case CAIRO_ANTIALIAS_DEFAULT:
365 f->scaled_hfont = NULL;
366 f->unscaled_hfont = NULL;
367 f->has_type1_notdef_index = FALSE;
369 if (f->quality == logfont->lfQuality ||
370 (logfont->lfQuality == DEFAULT_QUALITY &&
371 options->antialias == CAIRO_ANTIALIAS_DEFAULT)) {
372 /* If face_hfont is non-NULL, then we can use it to avoid creating our
373 * own --- because the constraints on face_hfont mentioned above
374 * guarantee it was created in exactly the same way that
375 * _win32_scaled_font_get_scaled_hfont would create it.
377 f->scaled_hfont = face_hfont;
379 /* don't delete the hfont if we're using the one passed in to us */
380 f->delete_scaled_hfont = !f->scaled_hfont;
382 cairo_matrix_multiply (&scale, font_matrix, ctm);
383 status = _compute_transform (f, &scale);
387 status = _cairo_scaled_font_init (&f->base, font_face,
388 font_matrix, ctm, options,
389 &_cairo_win32_scaled_font_backend);
393 status = _cairo_win32_scaled_font_set_metrics (f);
395 _cairo_scaled_font_fini (&f->base);
399 *font_out = &f->base;
400 return CAIRO_STATUS_SUCCESS;
407 static cairo_status_t
408 _win32_scaled_font_set_world_transform (cairo_win32_scaled_font_t *scaled_font,
413 _cairo_matrix_to_win32_xform (&scaled_font->logical_to_device, &xform);
415 if (!SetWorldTransform (hdc, &xform))
416 return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");
418 return CAIRO_STATUS_SUCCESS;
421 static cairo_status_t
422 _win32_scaled_font_set_identity_transform (HDC hdc)
424 if (!ModifyWorldTransform (hdc, NULL, MWT_IDENTITY))
425 return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_identity_transform");
427 return CAIRO_STATUS_SUCCESS;
430 static cairo_status_t
431 _win32_scaled_font_get_scaled_hfont (cairo_win32_scaled_font_t *scaled_font,
434 if (!scaled_font->scaled_hfont) {
435 LOGFONTW logfont = scaled_font->logfont;
436 logfont.lfHeight = -scaled_font->logical_size;
438 logfont.lfEscapement = 0;
439 logfont.lfOrientation = 0;
440 logfont.lfQuality = scaled_font->quality;
442 scaled_font->scaled_hfont = CreateFontIndirectW (&logfont);
443 if (!scaled_font->scaled_hfont)
444 return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_scaled_hfont");
447 *hfont_out = scaled_font->scaled_hfont;
448 return CAIRO_STATUS_SUCCESS;
451 static cairo_status_t
452 _win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font,
456 if (scaled_font->unscaled_hfont == NULL) {
457 OUTLINETEXTMETRIC *otm;
458 unsigned int otm_size;
461 cairo_status_t status;
463 status = _win32_scaled_font_get_scaled_hfont (scaled_font,
468 if (! SelectObject (hdc, scaled_hfont))
469 return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:SelectObject");
471 otm_size = GetOutlineTextMetrics (hdc, 0, NULL);
473 return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics");
475 otm = malloc (otm_size);
477 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
479 if (! GetOutlineTextMetrics (hdc, otm_size, otm)) {
480 status = _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics");
485 scaled_font->em_square = otm->otmEMSquare;
488 logfont = scaled_font->logfont;
489 logfont.lfHeight = -scaled_font->em_square;
491 logfont.lfEscapement = 0;
492 logfont.lfOrientation = 0;
493 logfont.lfQuality = scaled_font->quality;
495 scaled_font->unscaled_hfont = CreateFontIndirectW (&logfont);
496 if (! scaled_font->unscaled_hfont)
497 return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:CreateIndirect");
500 *hfont_out = scaled_font->unscaled_hfont;
501 return CAIRO_STATUS_SUCCESS;
504 static cairo_status_t
505 _cairo_win32_scaled_font_select_unscaled_font (cairo_scaled_font_t *scaled_font,
508 cairo_status_t status;
510 HFONT old_hfont = NULL;
512 status = _win32_scaled_font_get_unscaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, hdc, &hfont);
516 old_hfont = SelectObject (hdc, hfont);
518 return _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_select_unscaled_font");
520 status = _win32_scaled_font_set_identity_transform (hdc);
522 SelectObject (hdc, old_hfont);
526 SetMapMode (hdc, MM_TEXT);
528 return CAIRO_STATUS_SUCCESS;
532 _cairo_win32_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font)
534 cairo_win32_scaled_font_t *win32_scaled_font;
536 win32_scaled_font = (cairo_win32_scaled_font_t *) scaled_font;
538 return win32_scaled_font->is_type1;
542 _cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font)
544 cairo_win32_scaled_font_t *win32_scaled_font;
546 win32_scaled_font = (cairo_win32_scaled_font_t *) scaled_font;
548 return win32_scaled_font->is_bitmap;
552 _cairo_win32_scaled_font_done_unscaled_font (cairo_scaled_font_t *scaled_font)
556 /* implement the font backend interface */
558 static cairo_status_t
559 _cairo_win32_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
560 cairo_font_face_t **font_face)
565 cairo_status_t status;
567 status = _cairo_utf8_to_utf16 (toy_face->family, -1,
568 &face_name, &face_name_len);
572 if (face_name_len > LF_FACESIZE - 1)
573 face_name_len = LF_FACESIZE - 1;
575 memcpy (logfont.lfFaceName, face_name, sizeof (uint16_t) * face_name_len);
576 logfont.lfFaceName[face_name_len] = 0;
579 logfont.lfHeight = 0; /* filled in later */
580 logfont.lfWidth = 0; /* filled in later */
581 logfont.lfEscapement = 0; /* filled in later */
582 logfont.lfOrientation = 0; /* filled in later */
584 switch (toy_face->weight) {
585 case CAIRO_FONT_WEIGHT_NORMAL:
587 logfont.lfWeight = FW_NORMAL;
589 case CAIRO_FONT_WEIGHT_BOLD:
590 logfont.lfWeight = FW_BOLD;
594 switch (toy_face->slant) {
595 case CAIRO_FONT_SLANT_NORMAL:
597 logfont.lfItalic = FALSE;
599 case CAIRO_FONT_SLANT_ITALIC:
600 case CAIRO_FONT_SLANT_OBLIQUE:
601 logfont.lfItalic = TRUE;
605 logfont.lfUnderline = FALSE;
606 logfont.lfStrikeOut = FALSE;
607 /* The docs for LOGFONT discourage using this, since the
608 * interpretation is locale-specific, but it's not clear what
609 * would be a better alternative.
611 logfont.lfCharSet = DEFAULT_CHARSET;
612 logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
613 logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
614 logfont.lfQuality = DEFAULT_QUALITY; /* filled in later */
615 logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
617 *font_face = cairo_win32_font_face_create_for_logfontw (&logfont);
619 return CAIRO_STATUS_SUCCESS;
623 _cairo_win32_scaled_font_fini (void *abstract_font)
625 cairo_win32_scaled_font_t *scaled_font = abstract_font;
627 if (scaled_font == NULL)
630 if (scaled_font->scaled_hfont && scaled_font->delete_scaled_hfont)
631 DeleteObject (scaled_font->scaled_hfont);
633 if (scaled_font->unscaled_hfont)
634 DeleteObject (scaled_font->unscaled_hfont);
637 static cairo_int_status_t
638 _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled_font,
642 cairo_glyph_t **glyphs,
648 WORD *glyph_indices = NULL;
649 cairo_status_t status;
654 status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);
658 glyph_indices = _cairo_malloc_ab (n16 + 1, sizeof (WORD));
659 if (!glyph_indices) {
660 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
664 hdc = _get_global_font_dc ();
665 assert (hdc != NULL);
667 status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
671 if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) {
672 status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW");
677 *glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t));
679 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
686 mat = scaled_font->base.ctm;
687 status = cairo_matrix_invert (&mat);
688 assert (status == CAIRO_STATUS_SUCCESS);
690 _cairo_scaled_font_freeze_cache (&scaled_font->base);
692 for (i = 0; i < n16; i++) {
693 cairo_scaled_glyph_t *scaled_glyph;
695 (*glyphs)[i].index = glyph_indices[i];
696 (*glyphs)[i].x = x_pos;
697 (*glyphs)[i].y = y_pos;
699 status = _cairo_scaled_glyph_lookup (&scaled_font->base,
701 CAIRO_SCALED_GLYPH_INFO_METRICS,
709 x = scaled_glyph->x_advance;
710 y = scaled_glyph->y_advance;
711 cairo_matrix_transform_distance (&mat, &x, &y);
716 _cairo_scaled_font_thaw_cache (&scaled_font->base);
719 cairo_win32_scaled_font_done_font (&scaled_font->base);
721 free (glyph_indices);
728 static cairo_int_status_t
729 _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
733 cairo_glyph_t **glyphs,
736 cairo_win32_scaled_font_t *scaled_font = abstract_font;
739 GCP_RESULTSW gcp_results;
740 unsigned int buffer_size, i;
741 WCHAR *glyph_indices = NULL;
743 cairo_status_t status;
745 double x_incr, y_incr;
748 /* GetCharacterPlacement() returns utf16 instead of glyph indices
749 * for Type 1 fonts. Use GetGlyphIndices for Type 1 fonts. */
750 if (scaled_font->is_type1)
751 return _cairo_win32_scaled_font_type1_text_to_glyphs (scaled_font,
758 /* Compute a vector in user space along the baseline of length one logical space unit */
761 cairo_matrix_transform_distance (&scaled_font->base.font_matrix, &x_incr, &y_incr);
762 x_incr /= scaled_font->logical_scale;
763 y_incr /= scaled_font->logical_scale;
765 status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);
769 gcp_results.lStructSize = sizeof (GCP_RESULTS);
770 gcp_results.lpOutString = NULL;
771 gcp_results.lpOrder = NULL;
772 gcp_results.lpCaretPos = NULL;
773 gcp_results.lpClass = NULL;
775 buffer_size = MAX (n16 * 1.2, 16); /* Initially guess number of chars plus a few */
776 if (buffer_size > INT_MAX) {
777 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
781 hdc = _get_global_font_dc ();
782 assert (hdc != NULL);
784 status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
789 free (glyph_indices);
790 glyph_indices = NULL;
795 glyph_indices = _cairo_malloc_ab (buffer_size, sizeof (WCHAR));
796 dx = _cairo_malloc_ab (buffer_size, sizeof (int));
797 if (!glyph_indices || !dx) {
798 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
802 gcp_results.nGlyphs = buffer_size;
803 gcp_results.lpDx = dx;
804 gcp_results.lpGlyphs = glyph_indices;
806 if (!GetCharacterPlacementW (hdc, utf16, n16,
809 GCP_DIACRITIC | GCP_LIGATE | GCP_GLYPHSHAPE | GCP_REORDER)) {
810 status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_text_to_glyphs");
814 if (gcp_results.lpDx && gcp_results.lpGlyphs)
817 /* Too small a buffer, try again */
819 buffer_size += buffer_size / 2;
820 if (buffer_size > INT_MAX) {
821 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
826 *num_glyphs = gcp_results.nGlyphs;
827 *glyphs = _cairo_malloc_ab (gcp_results.nGlyphs, sizeof (cairo_glyph_t));
829 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
836 for (i = 0; i < gcp_results.nGlyphs; i++) {
837 (*glyphs)[i].index = glyph_indices[i];
838 (*glyphs)[i].x = x_pos ;
839 (*glyphs)[i].y = y_pos;
841 x_pos += x_incr * dx[i];
842 y_pos += y_incr * dx[i];
846 free (glyph_indices);
849 cairo_win32_scaled_font_done_font (&scaled_font->base);
858 _cairo_win32_scaled_font_ucs4_to_index (void *abstract_font,
861 cairo_win32_scaled_font_t *scaled_font = abstract_font;
865 cairo_status_t status;
867 hdc = _get_global_font_dc ();
868 assert (hdc != NULL);
870 status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
876 if (GetGlyphIndicesW (hdc, unicode, 1, &glyph_index, 0) == GDI_ERROR) {
877 _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_ucs4_to_index:GetGlyphIndicesW");
881 cairo_win32_scaled_font_done_font (&scaled_font->base);
886 static cairo_status_t
887 _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font)
889 cairo_status_t status;
890 cairo_font_extents_t extents;
895 hdc = _get_global_font_dc ();
896 assert (hdc != NULL);
898 if (scaled_font->preserve_axes || scaled_font->base.options.hint_metrics == CAIRO_HINT_METRICS_OFF) {
899 /* For 90-degree rotations (including 0), we get the metrics
900 * from the GDI in logical space, then convert back to font space
902 status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
905 GetTextMetrics (hdc, &metrics);
906 cairo_win32_scaled_font_done_font (&scaled_font->base);
908 extents.ascent = metrics.tmAscent / scaled_font->logical_scale;
909 extents.descent = metrics.tmDescent / scaled_font->logical_scale;
911 extents.height = (metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->logical_scale;
912 extents.max_x_advance = metrics.tmMaxCharWidth / scaled_font->logical_scale;
913 extents.max_y_advance = 0;
916 /* For all other transformations, we use the design metrics
917 * of the font. The GDI results from GetTextMetrics() on a
918 * transformed font are inexplicably large and we want to
921 status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
924 GetTextMetrics (hdc, &metrics);
925 _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
927 extents.ascent = (double)metrics.tmAscent / scaled_font->em_square;
928 extents.descent = (double)metrics.tmDescent / scaled_font->em_square;
929 extents.height = (double)(metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->em_square;
930 extents.max_x_advance = (double)(metrics.tmMaxCharWidth) / scaled_font->em_square;
931 extents.max_y_advance = 0;
935 scaled_font->is_bitmap = !(metrics.tmPitchAndFamily & TMPF_VECTOR);
937 /* Need to determine if this is a Type 1 font for the special
938 * handling in _text_to_glyphs. Unlike TrueType or OpenType,
939 * Type1 fonts do not have a "cmap" table (or any other table).
940 * However GetFontData() will retrieve a Type1 font when
941 * requesting that GetFontData() retrieve data from the start of
942 * the file. This is to distinguish Type1 from stroke fonts such
943 * as "Script" and "Modern". The TMPF_TRUETYPE test is redundant
944 * but improves performance for the most common fonts.
946 scaled_font->is_type1 = FALSE;
947 if (!(metrics.tmPitchAndFamily & TMPF_TRUETYPE) &&
948 (metrics.tmPitchAndFamily & TMPF_VECTOR))
950 if ((GetFontData (hdc, CMAP_TAG, 0, NULL, 0) == GDI_ERROR) &&
951 (GetFontData (hdc, 0, 0, NULL, 0) != GDI_ERROR))
953 scaled_font->is_type1 = TRUE;
957 return _cairo_scaled_font_set_metrics (&scaled_font->base, &extents);
960 static cairo_status_t
961 _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font,
962 cairo_scaled_glyph_t *scaled_glyph)
964 static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
965 GLYPHMETRICS metrics;
966 cairo_status_t status;
967 cairo_text_extents_t extents;
970 hdc = _get_global_font_dc ();
971 assert (hdc != NULL);
973 if (scaled_font->is_bitmap) {
974 /* GetGlyphOutline will not work. Assume that the glyph does not extend outside the font box. */
975 cairo_font_extents_t font_extents;
977 UINT charIndex = _cairo_scaled_glyph_index (scaled_glyph);
979 cairo_scaled_font_extents (&scaled_font->base, &font_extents);
981 status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
985 if (!GetCharWidth32(hdc, charIndex, charIndex, &width)) {
986 status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetCharWidth32");
989 cairo_win32_scaled_font_done_font (&scaled_font->base);
993 extents.x_bearing = 0;
994 extents.y_bearing = scaled_font->base.ctm.yy * (-font_extents.ascent / scaled_font->y_scale);
995 extents.width = width / (WIN32_FONT_LOGICAL_SCALE * scaled_font->x_scale);
996 extents.height = scaled_font->base.ctm.yy * (font_extents.ascent + font_extents.descent) / scaled_font->y_scale;
997 extents.x_advance = extents.width;
998 extents.y_advance = 0;
999 } else if (scaled_font->preserve_axes && scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
1000 /* If we aren't rotating / skewing the axes, then we get the metrics
1001 * from the GDI in device space and convert to font space.
1003 status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
1007 if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
1008 GGO_METRICS | GGO_GLYPH_INDEX,
1009 &metrics, 0, NULL, &matrix) == GDI_ERROR) {
1010 memset (&metrics, 0, sizeof (GLYPHMETRICS));
1012 if (metrics.gmBlackBoxX > 0 && scaled_font->base.options.antialias != CAIRO_ANTIALIAS_NONE) {
1013 /* The bounding box reported by Windows supposedly contains the glyph's "black" area;
1014 * however, antialiasing (especially with ClearType) means that the actual image that
1015 * needs to be rendered may "bleed" into the adjacent pixels, mainly on the right side.
1016 * To avoid clipping the glyphs when drawn by _cairo_surface_fallback_show_glyphs,
1017 * for example, or other code that uses glyph extents to determine the area to update,
1018 * we add a pixel of "slop" to left side of the nominal "black" area returned by GDI,
1019 * and two pixels to the right (as tests show some glyphs bleed into this column).
1021 metrics.gmptGlyphOrigin.x -= 1;
1022 metrics.gmBlackBoxX += 3;
1025 cairo_win32_scaled_font_done_font (&scaled_font->base);
1027 if (scaled_font->swap_axes) {
1028 extents.x_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;
1029 extents.y_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale;
1030 extents.width = metrics.gmBlackBoxY / scaled_font->y_scale;
1031 extents.height = metrics.gmBlackBoxX / scaled_font->x_scale;
1032 extents.x_advance = metrics.gmCellIncY / scaled_font->x_scale;
1033 extents.y_advance = metrics.gmCellIncX / scaled_font->y_scale;
1035 extents.x_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale;
1036 extents.y_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale;
1037 extents.width = metrics.gmBlackBoxX / scaled_font->x_scale;
1038 extents.height = metrics.gmBlackBoxY / scaled_font->y_scale;
1039 extents.x_advance = metrics.gmCellIncX / scaled_font->x_scale;
1040 extents.y_advance = metrics.gmCellIncY / scaled_font->y_scale;
1043 if (scaled_font->swap_x) {
1044 extents.x_bearing = (- extents.x_bearing - extents.width);
1045 extents.x_advance = - extents.x_advance;
1048 if (scaled_font->swap_y) {
1049 extents.y_bearing = (- extents.y_bearing - extents.height);
1050 extents.y_advance = - extents.y_advance;
1054 /* For all other transformations, we use the design metrics
1057 status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
1061 if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
1062 GGO_METRICS | GGO_GLYPH_INDEX,
1063 &metrics, 0, NULL, &matrix) == GDI_ERROR) {
1064 memset (&metrics, 0, sizeof (GLYPHMETRICS));
1066 _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
1068 extents.x_bearing = (double)metrics.gmptGlyphOrigin.x / scaled_font->em_square;
1069 extents.y_bearing = - (double)metrics.gmptGlyphOrigin.y / scaled_font->em_square;
1070 extents.width = (double)metrics.gmBlackBoxX / scaled_font->em_square;
1071 extents.height = (double)metrics.gmBlackBoxY / scaled_font->em_square;
1072 extents.x_advance = (double)metrics.gmCellIncX / scaled_font->em_square;
1073 extents.y_advance = (double)metrics.gmCellIncY / scaled_font->em_square;
1076 _cairo_scaled_glyph_set_metrics (scaled_glyph,
1080 return CAIRO_STATUS_SUCCESS;
1083 /* Not currently used code, but may be useful in the future if we add
1084 * back the capability to the scaled font backend interface to get the
1085 * actual device space bbox rather than computing it from the
1086 * font-space metrics.
1089 static cairo_status_t
1090 _cairo_win32_scaled_font_glyph_bbox (void *abstract_font,
1091 const cairo_glyph_t *glyphs,
1095 static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
1096 cairo_win32_scaled_font_t *scaled_font = abstract_font;
1097 int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
1099 if (num_glyphs > 0) {
1101 GLYPHMETRICS metrics;
1102 cairo_status_t status;
1105 hdc = _get_global_font_dc ();
1106 assert (hdc != NULL);
1108 status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
1112 for (i = 0; i < num_glyphs; i++) {
1113 int x = _cairo_lround (glyphs[i].x);
1114 int y = _cairo_lround (glyphs[i].y);
1116 GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | GGO_GLYPH_INDEX,
1117 &metrics, 0, NULL, &matrix);
1119 if (i == 0 || x1 > x + metrics.gmptGlyphOrigin.x)
1120 x1 = x + metrics.gmptGlyphOrigin.x;
1121 if (i == 0 || y1 > y - metrics.gmptGlyphOrigin.y)
1122 y1 = y - metrics.gmptGlyphOrigin.y;
1123 if (i == 0 || x2 < x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX)
1124 x2 = x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX;
1125 if (i == 0 || y2 < y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY)
1126 y2 = y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY;
1129 cairo_win32_scaled_font_done_font (&scaled_font->base);
1132 bbox->p1.x = _cairo_fixed_from_int (x1);
1133 bbox->p1.y = _cairo_fixed_from_int (y1);
1134 bbox->p2.x = _cairo_fixed_from_int (x2);
1135 bbox->p2.y = _cairo_fixed_from_int (y2);
1137 return CAIRO_STATUS_SUCCESS;
1142 cairo_win32_scaled_font_t *scaled_font;
1145 cairo_array_t glyphs;
1151 } cairo_glyph_state_t;
1154 _start_glyphs (cairo_glyph_state_t *state,
1155 cairo_win32_scaled_font_t *scaled_font,
1159 state->scaled_font = scaled_font;
1161 _cairo_array_init (&state->glyphs, sizeof (WCHAR));
1162 _cairo_array_init (&state->dx, sizeof (int));
1165 static cairo_status_t
1166 _flush_glyphs (cairo_glyph_state_t *state)
1168 cairo_status_t status;
1173 status = _cairo_array_append (&state->dx, &dx);
1177 elements = _cairo_array_index (&state->glyphs, 0);
1178 dx_elements = _cairo_array_index (&state->dx, 0);
1179 if (!ExtTextOutW (state->hdc,
1180 state->start_x, state->last_y,
1184 state->glyphs.num_elements,
1186 return _cairo_win32_print_gdi_error ("_flush_glyphs");
1189 _cairo_array_truncate (&state->glyphs, 0);
1190 _cairo_array_truncate (&state->dx, 0);
1192 return CAIRO_STATUS_SUCCESS;
1195 static cairo_status_t
1196 _add_glyph (cairo_glyph_state_t *state,
1197 unsigned long index,
1201 cairo_status_t status;
1202 double user_x = device_x;
1203 double user_y = device_y;
1204 WCHAR glyph_index = index;
1205 int logical_x, logical_y;
1207 cairo_matrix_transform_point (&state->scaled_font->device_to_logical, &user_x, &user_y);
1209 logical_x = _cairo_lround (user_x);
1210 logical_y = _cairo_lround (user_y);
1212 if (state->glyphs.num_elements > 0) {
1215 if (logical_y != state->last_y) {
1216 status = _flush_glyphs (state);
1219 state->start_x = logical_x;
1221 dx = logical_x - state->last_x;
1222 status = _cairo_array_append (&state->dx, &dx);
1227 state->start_x = logical_x;
1230 state->last_x = logical_x;
1231 state->last_y = logical_y;
1233 status = _cairo_array_append (&state->glyphs, &glyph_index);
1237 return CAIRO_STATUS_SUCCESS;
1240 static cairo_status_t
1241 _finish_glyphs (cairo_glyph_state_t *state)
1243 cairo_status_t status;
1245 status = _flush_glyphs (state);
1247 _cairo_array_fini (&state->glyphs);
1248 _cairo_array_fini (&state->dx);
1253 static cairo_status_t
1254 _draw_glyphs_on_surface (cairo_win32_surface_t *surface,
1255 cairo_win32_scaled_font_t *scaled_font,
1259 const cairo_glyph_t *glyphs,
1262 cairo_glyph_state_t state;
1263 cairo_status_t status, status2;
1266 if (!SaveDC (surface->dc))
1267 return _cairo_win32_print_gdi_error ("_draw_glyphs_on_surface:SaveDC");
1269 status = cairo_win32_scaled_font_select_font (&scaled_font->base, surface->dc);
1273 SetTextColor (surface->dc, color);
1274 SetTextAlign (surface->dc, TA_BASELINE | TA_LEFT);
1275 SetBkMode (surface->dc, TRANSPARENT);
1277 _start_glyphs (&state, scaled_font, surface->dc);
1279 for (i = 0; i < num_glyphs; i++) {
1280 status = _add_glyph (&state, glyphs[i].index,
1281 glyphs[i].x - x_offset, glyphs[i].y - y_offset);
1287 status2 = _finish_glyphs (&state);
1288 if (status == CAIRO_STATUS_SUCCESS)
1291 cairo_win32_scaled_font_done_font (&scaled_font->base);
1293 RestoreDC (surface->dc, -1);
1298 /* Duplicate the green channel of a 4-channel mask in the alpha channel, then
1299 * invert the whole mask.
1302 _compute_argb32_mask_alpha (cairo_win32_surface_t *mask_surface)
1304 cairo_image_surface_t *image = (cairo_image_surface_t *)mask_surface->image;
1307 for (i = 0; i < image->height; i++) {
1308 uint32_t *p = (uint32_t *) (image->data + i * image->stride);
1309 for (j = 0; j < image->width; j++) {
1310 *p = 0xffffffff ^ (*p | ((*p & 0x0000ff00) << 16));
1319 _invert_argb32_mask (cairo_win32_surface_t *mask_surface)
1321 cairo_image_surface_t *image = (cairo_image_surface_t *)mask_surface->image;
1324 for (i = 0; i < image->height; i++) {
1325 uint32_t *p = (uint32_t *) (image->data + i * image->stride);
1326 for (j = 0; j < image->width; j++) {
1327 *p = 0xffffffff ^ *p;
1333 /* Compute an alpha-mask from a monochrome RGB24 image
1335 static cairo_surface_t *
1336 _compute_a8_mask (cairo_win32_surface_t *mask_surface)
1338 cairo_image_surface_t *image24 = (cairo_image_surface_t *)mask_surface->image;
1339 cairo_image_surface_t *image8;
1342 if (image24->base.status)
1343 return cairo_surface_reference (&image24->base);
1345 image8 = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8,
1346 image24->width, image24->height);
1347 if (image8->base.status)
1348 return &image8->base;
1350 for (i = 0; i < image24->height; i++) {
1351 uint32_t *p = (uint32_t *) (image24->data + i * image24->stride);
1352 unsigned char *q = (unsigned char *) (image8->data + i * image8->stride);
1354 for (j = 0; j < image24->width; j++) {
1355 *q = 255 - ((*p & 0x0000ff00) >> 8);
1361 return &image8->base;
1364 static cairo_int_status_t
1365 _cairo_win32_scaled_font_glyph_init (void *abstract_font,
1366 cairo_scaled_glyph_t *scaled_glyph,
1367 cairo_scaled_glyph_info_t info)
1369 cairo_win32_scaled_font_t *scaled_font = abstract_font;
1370 cairo_status_t status;
1372 if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) {
1373 status = _cairo_win32_scaled_font_init_glyph_metrics (scaled_font, scaled_glyph);
1378 if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
1379 status = _cairo_win32_scaled_font_init_glyph_surface (scaled_font, scaled_glyph);
1384 if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) {
1385 status = _cairo_win32_scaled_font_init_glyph_path (scaled_font, scaled_glyph);
1390 return CAIRO_STATUS_SUCCESS;
1394 static cairo_int_status_t
1395 _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
1396 cairo_operator_t op,
1397 const cairo_pattern_t *pattern,
1398 cairo_surface_t *generic_surface,
1404 unsigned int height,
1405 cairo_glyph_t *glyphs,
1407 cairo_region_t *clip_region,
1408 int *remaining_glyphs)
1410 cairo_win32_scaled_font_t *scaled_font = abstract_font;
1411 cairo_win32_surface_t *surface = (cairo_win32_surface_t *)generic_surface;
1412 cairo_status_t status;
1414 if (width == 0 || height == 0)
1415 return CAIRO_STATUS_SUCCESS;
1417 if (_cairo_surface_is_win32 (generic_surface) &&
1418 surface->format == CAIRO_FORMAT_RGB24 &&
1419 op == CAIRO_OPERATOR_OVER &&
1420 _cairo_pattern_is_opaque_solid (pattern)) {
1422 cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)pattern;
1424 /* When compositing OVER on a GDI-understood surface, with a
1425 * solid opaque color, we can just call ExtTextOut directly.
1429 status = _cairo_win32_surface_set_clip_region (surface, clip_region);
1430 if (unlikely (status))
1433 new_color = RGB (((int)solid_pattern->color.red_short) >> 8,
1434 ((int)solid_pattern->color.green_short) >> 8,
1435 ((int)solid_pattern->color.blue_short) >> 8);
1437 return _draw_glyphs_on_surface (surface, scaled_font, new_color,
1439 glyphs, num_glyphs);
1441 /* Otherwise, we need to draw using software fallbacks. We create a mask
1442 * surface by drawing the the glyphs onto a DIB, black-on-white then
1443 * inverting. GDI outputs gamma-corrected images so inverted black-on-white
1444 * is very different from white-on-black. We favor the more common
1445 * case where the final output is dark-on-light.
1447 cairo_win32_surface_t *tmp_surface;
1448 cairo_surface_t *mask_surface;
1449 cairo_surface_pattern_t mask;
1452 tmp_surface = (cairo_win32_surface_t *)cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
1453 if (tmp_surface->base.status)
1454 return tmp_surface->base.status;
1460 FillRect (tmp_surface->dc, &r, GetStockObject (WHITE_BRUSH));
1462 status = _draw_glyphs_on_surface (tmp_surface,
1463 scaled_font, RGB (0, 0, 0),
1465 glyphs, num_glyphs);
1467 cairo_surface_destroy (&tmp_surface->base);
1471 if (scaled_font->quality == CLEARTYPE_QUALITY) {
1472 /* For ClearType, we need a 4-channel mask. If we are compositing on
1473 * a surface with alpha, we need to compute the alpha channel of
1474 * the mask (we just copy the green channel). But for a destination
1475 * surface without alpha the alpha channel of the mask is ignored
1478 if (surface->format != CAIRO_FORMAT_RGB24)
1479 _compute_argb32_mask_alpha (tmp_surface);
1481 _invert_argb32_mask (tmp_surface);
1483 mask_surface = &tmp_surface->base;
1485 mask_surface = _compute_a8_mask (tmp_surface);
1486 cairo_surface_destroy (&tmp_surface->base);
1487 status = mask_surface->status;
1492 /* For op == OVER, no-cleartype, a possible optimization here is to
1493 * draw onto an intermediate ARGB32 surface and alpha-blend that with the
1496 _cairo_pattern_init_for_surface (&mask, mask_surface);
1497 cairo_surface_destroy (mask_surface);
1499 if (scaled_font->quality == CLEARTYPE_QUALITY)
1500 mask.base.has_component_alpha = TRUE;
1502 status = _cairo_surface_mask (&surface->base, op, pattern, &mask.base,
1505 _cairo_pattern_fini (&mask.base);
1512 static cairo_int_status_t
1513 _cairo_win32_scaled_font_load_truetype_table (void *abstract_font,
1516 unsigned char *buffer,
1517 unsigned long *length)
1519 cairo_win32_scaled_font_t *scaled_font = abstract_font;
1521 cairo_status_t status;
1524 hdc = _get_global_font_dc ();
1525 assert (hdc != NULL);
1527 tag = (tag&0x000000ff)<<24 | (tag&0x0000ff00)<<8 | (tag&0x00ff0000)>>8 | (tag&0xff000000)>>24;
1528 status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
1532 ret = GetFontData (hdc, tag, offset, buffer, *length);
1533 if (ret == GDI_ERROR || (buffer && ret != *length))
1534 status = CAIRO_INT_STATUS_UNSUPPORTED;
1538 cairo_win32_scaled_font_done_font (&scaled_font->base);
1543 static cairo_int_status_t
1544 _cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font,
1545 unsigned long index,
1548 cairo_win32_scaled_font_t *scaled_font = abstract_font;
1549 GLYPHSET *glyph_set;
1550 uint16_t *utf16 = NULL;
1551 WORD *glyph_indices = NULL;
1554 unsigned int i, j, num_glyphs;
1555 cairo_status_t status;
1557 hdc = _get_global_font_dc ();
1558 assert (hdc != NULL);
1560 status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
1564 res = GetFontUnicodeRanges(hdc, NULL);
1566 status = _cairo_win32_print_gdi_error (
1567 "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
1571 glyph_set = malloc (res);
1572 if (glyph_set == NULL) {
1573 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1577 res = GetFontUnicodeRanges(hdc, glyph_set);
1579 status = _cairo_win32_print_gdi_error (
1580 "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
1584 *ucs4 = (uint32_t) -1;
1585 for (i = 0; i < glyph_set->cRanges; i++) {
1586 num_glyphs = glyph_set->ranges[i].cGlyphs;
1588 utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t));
1589 if (utf16 == NULL) {
1590 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1594 glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD));
1595 if (glyph_indices == NULL) {
1596 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1600 for (j = 0; j < num_glyphs; j++)
1601 utf16[j] = glyph_set->ranges[i].wcLow + j;
1604 if (GetGlyphIndicesW (hdc, utf16, num_glyphs, glyph_indices, 0) == GDI_ERROR) {
1605 status = _cairo_win32_print_gdi_error (
1606 "_cairo_win32_scaled_font_index_to_ucs4:GetGlyphIndicesW");
1610 for (j = 0; j < num_glyphs; j++) {
1611 if (glyph_indices[j] == index) {
1617 free (glyph_indices);
1618 glyph_indices = NULL;
1624 free (glyph_indices);
1628 cairo_win32_scaled_font_done_font (&scaled_font->base);
1634 _cairo_win32_scaled_font_is_synthetic (void *abstract_font)
1636 cairo_win32_scaled_font_t *scaled_font = abstract_font;
1637 cairo_status_t status;
1640 cairo_bool_t italic;
1642 status = _cairo_truetype_get_style (&scaled_font->base,
1646 /* If this doesn't work assume it is not synthetic to avoid
1647 * unneccessary subsetting fallbacks. */
1648 if (status != CAIRO_STATUS_SUCCESS)
1651 if (scaled_font->logfont.lfWeight != weight ||
1652 scaled_font->logfont.lfItalic != italic)
1658 static cairo_int_status_t
1659 _cairo_win32_scaled_font_index_to_glyph_name (void *abstract_font,
1661 int num_glyph_names,
1662 unsigned long glyph_index,
1663 unsigned long *glyph_array_index)
1665 cairo_win32_scaled_font_t *scaled_font = abstract_font;
1668 /* Windows puts .notdef at index 0 then numbers the remaining
1669 * glyphs starting from 1 in the order they appear in the font. */
1671 /* Find the position of .notdef in the list of glyph names. We
1672 * only need to do this once per scaled font. */
1673 if (! scaled_font->has_type1_notdef_index) {
1674 for (i = 0; i < num_glyph_names; i++) {
1675 if (strcmp (glyph_names[i], ".notdef") == 0) {
1676 scaled_font->type1_notdef_index = i;
1677 scaled_font->has_type1_notdef_index = TRUE;
1681 if (! scaled_font->has_type1_notdef_index)
1682 return CAIRO_INT_STATUS_UNSUPPORTED;
1685 /* Once we know the position of .notdef the position of any glyph
1686 * in the font can easily be obtained. */
1687 if (glyph_index == 0)
1688 *glyph_array_index = scaled_font->type1_notdef_index;
1689 else if (glyph_index <= scaled_font->type1_notdef_index)
1690 *glyph_array_index = glyph_index - 1;
1691 else if (glyph_index < num_glyph_names)
1692 *glyph_array_index = glyph_index;
1694 return CAIRO_INT_STATUS_UNSUPPORTED;
1696 return CAIRO_STATUS_SUCCESS;
1699 static cairo_int_status_t
1700 _cairo_win32_scaled_font_load_type1_data (void *abstract_font,
1702 unsigned char *buffer,
1703 unsigned long *length)
1705 cairo_win32_scaled_font_t *scaled_font = abstract_font;
1707 if (! scaled_font->is_type1)
1708 return CAIRO_INT_STATUS_UNSUPPORTED;
1710 /* Using the tag 0 retrieves the entire font file. This works with
1711 * Type 1 fonts as well as TTF/OTF fonts. */
1712 return _cairo_win32_scaled_font_load_truetype_table (scaled_font,
1719 static cairo_status_t
1720 _cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font,
1721 cairo_scaled_glyph_t *scaled_glyph)
1723 cairo_status_t status;
1724 cairo_glyph_t glyph;
1725 cairo_win32_surface_t *surface;
1727 cairo_surface_t *image;
1731 x1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
1732 y1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
1733 x2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x);
1734 y2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y);
1738 surface = (cairo_win32_surface_t *)
1739 cairo_win32_surface_create_with_dib (CAIRO_FORMAT_RGB24, width, height);
1741 cr = cairo_create (&surface->base);
1742 cairo_set_source_rgb (cr, 1, 1, 1);
1744 status = cairo_status (cr);
1749 glyph.index = _cairo_scaled_glyph_index (scaled_glyph);
1752 status = _draw_glyphs_on_surface (surface, scaled_font, RGB(0,0,0),
1759 image = _compute_a8_mask (surface);
1760 status = image->status;
1764 cairo_surface_set_device_offset (image, -x1, -y1);
1765 _cairo_scaled_glyph_set_surface (scaled_glyph,
1767 (cairo_image_surface_t *) image);
1770 cairo_surface_destroy (&surface->base);
1776 _cairo_win32_transform_FIXED_to_fixed (cairo_matrix_t *matrix,
1778 cairo_fixed_t *fx, cairo_fixed_t *fy)
1780 double x = Fx.value + Fx.fract / 65536.0;
1781 double y = Fy.value + Fy.fract / 65536.0;
1782 cairo_matrix_transform_point (matrix, &x, &y);
1783 *fx = _cairo_fixed_from_double (x);
1784 *fy = _cairo_fixed_from_double (y);
1787 static cairo_status_t
1788 _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font,
1789 cairo_scaled_glyph_t *scaled_glyph)
1791 static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, -1 } };
1792 cairo_status_t status;
1793 GLYPHMETRICS metrics;
1796 unsigned char *buffer, *ptr;
1797 cairo_path_fixed_t *path;
1798 cairo_matrix_t transform;
1801 if (scaled_font->is_bitmap)
1802 return CAIRO_INT_STATUS_UNSUPPORTED;
1804 hdc = _get_global_font_dc ();
1805 assert (hdc != NULL);
1807 path = _cairo_path_fixed_create ();
1809 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1811 if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE) {
1812 status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
1813 transform = scaled_font->base.scale;
1814 cairo_matrix_scale (&transform, 1.0/scaled_font->em_square, 1.0/scaled_font->em_square);
1816 status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
1817 cairo_matrix_init_identity(&transform);
1822 bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
1823 GGO_NATIVE | GGO_GLYPH_INDEX,
1824 &metrics, 0, NULL, &matrix);
1826 if (bytesGlyph == GDI_ERROR) {
1827 status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
1831 ptr = buffer = malloc (bytesGlyph);
1833 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1837 if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
1838 GGO_NATIVE | GGO_GLYPH_INDEX,
1839 &metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) {
1840 status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
1841 goto CLEANUP_BUFFER;
1844 while (ptr < buffer + bytesGlyph) {
1845 TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)ptr;
1846 unsigned char *endPoly = ptr + header->cb;
1848 ptr += sizeof (TTPOLYGONHEADER);
1850 _cairo_win32_transform_FIXED_to_fixed (&transform,
1854 status = _cairo_path_fixed_move_to (path, x, y);
1856 goto CLEANUP_BUFFER;
1858 while (ptr < endPoly) {
1859 TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr;
1860 POINTFX *points = curve->apfx;
1862 switch (curve->wType) {
1864 for (i = 0; i < curve->cpfx; i++) {
1865 _cairo_win32_transform_FIXED_to_fixed (&transform,
1869 status = _cairo_path_fixed_line_to (path, x, y);
1871 goto CLEANUP_BUFFER;
1874 case TT_PRIM_QSPLINE:
1875 for (i = 0; i < curve->cpfx - 1; i++) {
1876 cairo_fixed_t p1x, p1y, p2x, p2y, cx, cy, c1x, c1y, c2x, c2y;
1877 if (! _cairo_path_fixed_get_current_point (path, &p1x, &p1y))
1878 goto CLEANUP_BUFFER;
1879 _cairo_win32_transform_FIXED_to_fixed (&transform,
1884 if (i + 1 == curve->cpfx - 1) {
1885 _cairo_win32_transform_FIXED_to_fixed (&transform,
1890 /* records with more than one curve use interpolation for
1891 control points, per http://support.microsoft.com/kb/q87115/ */
1892 _cairo_win32_transform_FIXED_to_fixed (&transform,
1900 c1x = 2 * cx / 3 + p1x / 3;
1901 c1y = 2 * cy / 3 + p1y / 3;
1902 c2x = 2 * cx / 3 + p2x / 3;
1903 c2y = 2 * cy / 3 + p2y / 3;
1905 status = _cairo_path_fixed_curve_to (path, c1x, c1y, c2x, c2y, p2x, p2y);
1907 goto CLEANUP_BUFFER;
1910 case TT_PRIM_CSPLINE:
1911 for (i = 0; i < curve->cpfx - 2; i += 2) {
1912 cairo_fixed_t x1, y1, x2, y2;
1913 _cairo_win32_transform_FIXED_to_fixed (&transform,
1917 _cairo_win32_transform_FIXED_to_fixed (&transform,
1921 _cairo_win32_transform_FIXED_to_fixed (&transform,
1925 status = _cairo_path_fixed_curve_to (path, x, y, x1, y1, x2, y2);
1927 goto CLEANUP_BUFFER;
1931 ptr += sizeof(TTPOLYCURVE) + sizeof (POINTFX) * (curve->cpfx - 1);
1933 status = _cairo_path_fixed_close_path (path);
1935 goto CLEANUP_BUFFER;
1938 _cairo_scaled_glyph_set_path (scaled_glyph,
1946 if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE)
1947 _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
1949 cairo_win32_scaled_font_done_font (&scaled_font->base);
1952 if (status != CAIRO_STATUS_SUCCESS)
1953 _cairo_path_fixed_destroy (path);
1958 const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
1959 CAIRO_FONT_TYPE_WIN32,
1960 _cairo_win32_scaled_font_fini,
1961 _cairo_win32_scaled_font_glyph_init,
1962 NULL, /* _cairo_win32_scaled_font_text_to_glyphs, FIXME */
1963 _cairo_win32_scaled_font_ucs4_to_index,
1964 _cairo_win32_scaled_font_load_truetype_table,
1965 _cairo_win32_scaled_font_index_to_ucs4,
1966 _cairo_win32_scaled_font_is_synthetic,
1967 _cairo_win32_scaled_font_index_to_glyph_name,
1968 _cairo_win32_scaled_font_load_type1_data
1971 /* #cairo_win32_font_face_t */
1973 typedef struct _cairo_win32_font_face cairo_win32_font_face_t;
1975 /* If hfont is non-%NULL then logfont->lfHeight must be -S for some S,
1976 * logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must
1977 * all be 0, and hfont is the result of calling CreateFontIndirectW on
1980 struct _cairo_win32_font_face {
1981 cairo_font_face_t base;
1986 /* implement the platform-specific interface */
1989 _is_scale (const cairo_matrix_t *matrix, double scale)
1991 return matrix->xx == scale && matrix->yy == scale &&
1992 matrix->xy == 0. && matrix->yx == 0. &&
1993 matrix->x0 == 0. && matrix->y0 == 0.;
1996 static cairo_status_t
1997 _cairo_win32_font_face_scaled_font_create (void *abstract_face,
1998 const cairo_matrix_t *font_matrix,
1999 const cairo_matrix_t *ctm,
2000 const cairo_font_options_t *options,
2001 cairo_scaled_font_t **font)
2005 cairo_win32_font_face_t *font_face = abstract_face;
2007 if (font_face->hfont) {
2008 /* Check whether it's OK to go ahead and use the font-face's HFONT. */
2009 if (_is_scale (ctm, 1.) &&
2010 _is_scale (font_matrix, -font_face->logfont.lfHeight)) {
2011 hfont = font_face->hfont;
2015 return _win32_scaled_font_create (&font_face->logfont,
2018 font_matrix, ctm, options,
2022 const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
2023 CAIRO_FONT_TYPE_WIN32,
2024 _cairo_win32_font_face_create_for_toy,
2025 _cairo_win32_font_face_destroy,
2026 _cairo_win32_font_face_scaled_font_create
2029 /* We maintain a hash table from LOGFONT,HFONT => #cairo_font_face_t.
2030 * The primary purpose of this mapping is to provide unique
2031 * #cairo_font_face_t values so that our cache and mapping from
2032 * #cairo_font_face_t => #cairo_scaled_font_t works. Once the
2033 * corresponding #cairo_font_face_t objects fall out of downstream
2034 * caches, we don't need them in this hash table anymore.
2036 * Modifications to this hash table are protected by
2037 * _cairo_win32_font_face_mutex.
2040 static cairo_hash_table_t *cairo_win32_font_face_hash_table = NULL;
2043 _cairo_win32_font_face_keys_equal (const void *key_a,
2047 _cairo_win32_font_face_hash_table_destroy (void)
2049 cairo_hash_table_t *hash_table;
2051 /* We manually acquire the lock rather than calling
2052 * _cairo_win32_font_face_hash_table_lock simply to avoid creating
2053 * the table only to destroy it again. */
2054 CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex);
2055 hash_table = cairo_win32_font_face_hash_table;
2056 cairo_win32_font_face_hash_table = NULL;
2057 CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
2059 if (hash_table != NULL)
2060 _cairo_hash_table_destroy (hash_table);
2063 static cairo_hash_table_t *
2064 _cairo_win32_font_face_hash_table_lock (void)
2066 CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex);
2068 if (unlikely (cairo_win32_font_face_hash_table == NULL))
2070 cairo_win32_font_face_hash_table =
2071 _cairo_hash_table_create (_cairo_win32_font_face_keys_equal);
2073 if (unlikely (cairo_win32_font_face_hash_table == NULL)) {
2074 CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
2075 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2080 return cairo_win32_font_face_hash_table;
2084 _cairo_win32_font_face_hash_table_unlock (void)
2086 CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
2090 _cairo_win32_font_face_destroy (void *abstract_face)
2092 cairo_win32_font_face_t *font_face = abstract_face;
2093 cairo_hash_table_t *hash_table;
2095 hash_table = _cairo_win32_font_face_hash_table_lock ();
2096 /* All created objects must have been mapped in the hash table. */
2097 assert (hash_table != NULL);
2099 if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->base.ref_count)) {
2100 /* somebody recreated the font whilst we waited for the lock */
2101 _cairo_win32_font_face_hash_table_unlock ();
2105 /* Font faces in SUCCESS status are guaranteed to be in the
2106 * hashtable. Font faces in an error status are removed from the
2107 * hashtable if they are found during a lookup, thus they should
2108 * only be removed if they are in the hashtable. */
2109 if (likely (font_face->base.status == CAIRO_STATUS_SUCCESS) ||
2110 _cairo_hash_table_lookup (hash_table, &font_face->base.hash_entry) == font_face)
2111 _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
2113 _cairo_win32_font_face_hash_table_unlock ();
2117 _cairo_win32_font_face_init_key (cairo_win32_font_face_t *key,
2121 unsigned long hash = _CAIRO_HASH_INIT_VALUE;
2123 key->logfont = *logfont;
2126 hash = _cairo_hash_bytes (0, logfont->lfFaceName, 2*wcslen(logfont->lfFaceName));
2127 hash = _cairo_hash_bytes (hash, &logfont->lfWeight, sizeof(logfont->lfWeight));
2128 hash = _cairo_hash_bytes (hash, &logfont->lfItalic, sizeof(logfont->lfItalic));
2130 key->base.hash_entry.hash = hash;
2134 _cairo_win32_font_face_keys_equal (const void *key_a,
2137 const cairo_win32_font_face_t *face_a = key_a;
2138 const cairo_win32_font_face_t *face_b = key_b;
2140 if (face_a->logfont.lfWeight == face_b->logfont.lfWeight &&
2141 face_a->logfont.lfItalic == face_b->logfont.lfItalic &&
2142 face_a->logfont.lfUnderline == face_b->logfont.lfUnderline &&
2143 face_a->logfont.lfStrikeOut == face_b->logfont.lfStrikeOut &&
2144 face_a->logfont.lfCharSet == face_b->logfont.lfCharSet &&
2145 face_a->logfont.lfOutPrecision == face_b->logfont.lfOutPrecision &&
2146 face_a->logfont.lfClipPrecision == face_b->logfont.lfClipPrecision &&
2147 face_a->logfont.lfPitchAndFamily == face_b->logfont.lfPitchAndFamily &&
2148 (wcscmp (face_a->logfont.lfFaceName, face_b->logfont.lfFaceName) == 0))
2155 * cairo_win32_font_face_create_for_logfontw_hfont:
2156 * @logfont: A #LOGFONTW structure specifying the font to use.
2157 * If @font is %NULL then the lfHeight, lfWidth, lfOrientation and lfEscapement
2158 * fields of this structure are ignored. Otherwise lfWidth, lfOrientation and
2159 * lfEscapement must be zero.
2160 * @font: An #HFONT that can be used when the font matrix is a scale by
2161 * -lfHeight and the CTM is identity.
2163 * Creates a new font for the Win32 font backend based on a
2164 * #LOGFONT. This font can then be used with
2165 * cairo_set_font_face() or cairo_scaled_font_create().
2166 * The #cairo_scaled_font_t
2167 * returned from cairo_scaled_font_create() is also for the Win32 backend
2168 * and can be used with functions such as cairo_win32_scaled_font_select_font().
2170 * Return value: a newly created #cairo_font_face_t. Free with
2171 * cairo_font_face_destroy() when you are done using it.
2174 cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font)
2176 cairo_win32_font_face_t *font_face, key;
2177 cairo_hash_table_t *hash_table;
2178 cairo_status_t status;
2180 hash_table = _cairo_win32_font_face_hash_table_lock ();
2181 if (unlikely (hash_table == NULL)) {
2182 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2183 return (cairo_font_face_t *)&_cairo_font_face_nil;
2186 _cairo_win32_font_face_init_key (&key, logfont, font);
2188 /* Return existing unscaled font if it exists in the hash table. */
2189 font_face = _cairo_hash_table_lookup (hash_table,
2190 &key.base.hash_entry);
2191 if (font_face != NULL) {
2192 if (font_face->base.status == CAIRO_STATUS_SUCCESS) {
2193 cairo_font_face_reference (&font_face->base);
2194 _cairo_win32_font_face_hash_table_unlock ();
2195 return &font_face->base;
2198 /* remove the bad font from the hash table */
2199 _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
2202 /* Otherwise create it and insert into hash table. */
2203 font_face = malloc (sizeof (cairo_win32_font_face_t));
2205 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2209 _cairo_win32_font_face_init_key (font_face, logfont, font);
2210 _cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
2212 assert (font_face->base.hash_entry.hash == key.base.hash_entry.hash);
2213 status = _cairo_hash_table_insert (hash_table,
2214 &font_face->base.hash_entry);
2215 if (unlikely (status))
2218 _cairo_win32_font_face_hash_table_unlock ();
2219 return &font_face->base;
2222 _cairo_win32_font_face_hash_table_unlock ();
2223 return (cairo_font_face_t *)&_cairo_font_face_nil;
2227 * cairo_win32_font_face_create_for_logfontw:
2228 * @logfont: A #LOGFONTW structure specifying the font to use.
2229 * The lfHeight, lfWidth, lfOrientation and lfEscapement
2230 * fields of this structure are ignored.
2232 * Creates a new font for the Win32 font backend based on a
2233 * #LOGFONT. This font can then be used with
2234 * cairo_set_font_face() or cairo_scaled_font_create().
2235 * The #cairo_scaled_font_t
2236 * returned from cairo_scaled_font_create() is also for the Win32 backend
2237 * and can be used with functions such as cairo_win32_scaled_font_select_font().
2239 * Return value: a newly created #cairo_font_face_t. Free with
2240 * cairo_font_face_destroy() when you are done using it.
2243 cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont)
2245 return cairo_win32_font_face_create_for_logfontw_hfont (logfont, NULL);
2249 * cairo_win32_font_face_create_for_hfont:
2250 * @font: An #HFONT structure specifying the font to use.
2252 * Creates a new font for the Win32 font backend based on a
2253 * #HFONT. This font can then be used with
2254 * cairo_set_font_face() or cairo_scaled_font_create().
2255 * The #cairo_scaled_font_t
2256 * returned from cairo_scaled_font_create() is also for the Win32 backend
2257 * and can be used with functions such as cairo_win32_scaled_font_select_font().
2259 * Return value: a newly created #cairo_font_face_t. Free with
2260 * cairo_font_face_destroy() when you are done using it.
2263 cairo_win32_font_face_create_for_hfont (HFONT font)
2266 GetObjectW (font, sizeof(logfont), &logfont);
2268 if (logfont.lfEscapement != 0 || logfont.lfOrientation != 0 ||
2269 logfont.lfWidth != 0) {
2270 /* We can't use this font because that optimization requires that
2271 * lfEscapement, lfOrientation and lfWidth be zero. */
2275 return cairo_win32_font_face_create_for_logfontw_hfont (&logfont, font);
2279 _cairo_scaled_font_is_win32 (cairo_scaled_font_t *scaled_font)
2281 return scaled_font->backend == &_cairo_win32_scaled_font_backend;
2285 * cairo_win32_scaled_font_select_font:
2286 * @scaled_font: A #cairo_scaled_font_t from the Win32 font backend. Such an
2287 * object can be created with cairo_win32_scaled_font_create_for_logfontw().
2288 * @hdc: a device context
2290 * Selects the font into the given device context and changes the
2291 * map mode and world transformation of the device context to match
2292 * that of the font. This function is intended for use when using
2293 * layout APIs such as Uniscribe to do text layout with the
2294 * cairo font. After finishing using the device context, you must call
2295 * cairo_win32_scaled_font_done_font() to release any resources allocated
2298 * See cairo_win32_scaled_font_get_metrics_factor() for converting logical
2299 * coordinates from the device context to font space.
2301 * Normally, calls to SaveDC() and RestoreDC() would be made around
2302 * the use of this function to preserve the original graphics state.
2304 * Return value: %CAIRO_STATUS_SUCCESS if the operation succeeded.
2305 * otherwise an error such as %CAIRO_STATUS_NO_MEMORY and
2306 * the device context is unchanged.
2309 cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
2312 cairo_status_t status;
2314 HFONT old_hfont = NULL;
2317 if (! _cairo_scaled_font_is_win32 (scaled_font)) {
2318 return _cairo_error (CAIRO_STATUS_FONT_TYPE_MISMATCH);
2321 if (scaled_font->status)
2322 return scaled_font->status;
2324 status = _win32_scaled_font_get_scaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, &hfont);
2328 old_hfont = SelectObject (hdc, hfont);
2330 return _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SelectObject");
2332 old_mode = SetGraphicsMode (hdc, GM_ADVANCED);
2334 status = _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SetGraphicsMode");
2335 SelectObject (hdc, old_hfont);
2339 status = _win32_scaled_font_set_world_transform ((cairo_win32_scaled_font_t *)scaled_font, hdc);
2341 SetGraphicsMode (hdc, old_mode);
2342 SelectObject (hdc, old_hfont);
2346 SetMapMode (hdc, MM_TEXT);
2348 return CAIRO_STATUS_SUCCESS;
2352 * cairo_win32_scaled_font_done_font:
2353 * @scaled_font: A scaled font from the Win32 font backend.
2355 * Releases any resources allocated by cairo_win32_scaled_font_select_font()
2358 cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font)
2360 if (! _cairo_scaled_font_is_win32 (scaled_font)) {
2361 _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
2366 * cairo_win32_scaled_font_get_metrics_factor:
2367 * @scaled_font: a scaled font from the Win32 font backend
2369 * Gets a scale factor between logical coordinates in the coordinate
2370 * space used by cairo_win32_scaled_font_select_font() (that is, the
2371 * coordinate system used by the Windows functions to return metrics) and
2372 * font space coordinates.
2374 * Return value: factor to multiply logical units by to get font space
2378 cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font)
2380 if (! _cairo_scaled_font_is_win32 (scaled_font)) {
2381 _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
2384 return 1. / ((cairo_win32_scaled_font_t *)scaled_font)->logical_scale;
2388 * cairo_win32_scaled_font_get_logical_to_device:
2389 * @scaled_font: a scaled font from the Win32 font backend
2390 * @logical_to_device: matrix to return
2392 * Gets the transformation mapping the logical space used by @scaled_font
2398 cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font,
2399 cairo_matrix_t *logical_to_device)
2401 cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font;
2402 if (! _cairo_scaled_font_is_win32 (scaled_font)) {
2403 _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
2404 cairo_matrix_init_identity (logical_to_device);
2407 *logical_to_device = win_font->logical_to_device;
2411 * cairo_win32_scaled_font_get_device_to_logical:
2412 * @scaled_font: a scaled font from the Win32 font backend
2413 * @device_to_logical: matrix to return
2415 * Gets the transformation mapping device space to the logical space
2416 * used by @scaled_font.
2421 cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
2422 cairo_matrix_t *device_to_logical)
2424 cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font;
2425 if (! _cairo_scaled_font_is_win32 (scaled_font)) {
2426 _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
2427 cairo_matrix_init_identity (device_to_logical);
2430 *device_to_logical = win_font->device_to_logical;
2434 _cairo_win32_font_reset_static_data (void)
2436 _cairo_win32_font_face_hash_table_destroy ();