73fc052d7f53e19dd031485eb8fdd58d343f3ed4
[framework/graphics/cairo.git] / src / cairo-win32-font.c
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
3  *
4  * Copyright © 2005 Red Hat, Inc
5  *
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.
13  *
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
19  *
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/
24  *
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.
28  *
29  * The Original Code is the cairo graphics library.
30  *
31  * The Initial Developer of the Original Code is Red Hat, Inc.
32  *
33  * Contributor(s):
34  */
35
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
40 #endif
41 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
42 # define _WIN32_WINNT 0x0500
43 #endif
44
45 #include "cairoint.h"
46
47 #include "cairo-win32-private.h"
48
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"
54
55 #include <wchar.h>
56
57 #ifndef SPI_GETFONTSMOOTHINGTYPE
58 #define SPI_GETFONTSMOOTHINGTYPE 0x200a
59 #endif
60 #ifndef FE_FONTSMOOTHINGCLEARTYPE
61 #define FE_FONTSMOOTHINGCLEARTYPE 2
62 #endif
63 #ifndef CLEARTYPE_QUALITY
64 #define CLEARTYPE_QUALITY 5
65 #endif
66 #ifndef TT_PRIM_CSPLINE
67 #define TT_PRIM_CSPLINE 3
68 #endif
69
70 #define CMAP_TAG 0x70616d63
71
72 /**
73  * SECTION:cairo-win32-fonts
74  * @Title: Win32 Fonts
75  * @Short_Description: Font support for Microsoft Windows
76  * @See_Also: #cairo_font_face_t
77  *
78  * The Microsoft Windows font backend is primarily used to render text on
79  * Microsoft Windows systems.
80  */
81
82 /**
83  * CAIRO_HAS_WIN32_FONT:
84  *
85  * Defined if the Microsoft Windows font backend is available.
86  * This macro can be used to conditionally compile backend-specific code.
87  */
88
89 const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend;
90
91 typedef struct {
92     cairo_scaled_font_t base;
93
94     LOGFONTW logfont;
95
96     BYTE quality;
97
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.
102      */
103     double logical_scale;
104
105     /* The size we should actually request the font at from Windows; differs
106      * from the logical_scale because it is quantized for orthogonal
107      * transformations
108      */
109     double logical_size;
110
111     /* Transformations from device <=> logical space
112      */
113     cairo_matrix_t logical_to_device;
114     cairo_matrix_t device_to_logical;
115
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.
121      */
122     cairo_bool_t preserve_axes;
123     cairo_bool_t swap_axes;
124     cairo_bool_t swap_x;
125     cairo_bool_t swap_y;
126     double x_scale;
127     double y_scale;
128
129     /* The size of the design unit of the font
130      */
131     int em_square;
132
133     HFONT scaled_hfont;
134     HFONT unscaled_hfont;
135
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;
142
143 static cairo_status_t
144 _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font);
145
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);
149
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);
153
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);
157
158 static void
159 _cairo_win32_font_face_destroy (void *abstract_face);
160
161
162 #define NEARLY_ZERO(d) (fabs(d) < (1. / 65536.))
163
164 static HDC
165 _get_global_font_dc (void)
166 {
167     static HDC hdc;
168
169     if (!hdc) {
170         hdc = CreateCompatibleDC (NULL);
171         if (!hdc) {
172             _cairo_win32_print_gdi_error ("_get_global_font_dc");
173             return NULL;
174         }
175
176         if (!SetGraphicsMode (hdc, GM_ADVANCED)) {
177             _cairo_win32_print_gdi_error ("_get_global_font_dc");
178             DeleteDC (hdc);
179             return NULL;
180         }
181     }
182
183     return hdc;
184 }
185
186 static cairo_status_t
187 _compute_transform (cairo_win32_scaled_font_t *scaled_font,
188                     cairo_matrix_t            *sc)
189 {
190     cairo_status_t status;
191
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;
200
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;
209
210     } else {
211         scaled_font->preserve_axes = FALSE;
212         scaled_font->swap_x = scaled_font->swap_y = scaled_font->swap_axes = FALSE;
213     }
214
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;
220
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);
224     }
225
226     /* The font matrix has x and y "scale" components which we extract and
227      * use as character scale values.
228      */
229     cairo_matrix_init (&scaled_font->logical_to_device,
230                        sc->xx, sc->yx, sc->xy, sc->yy, 0, 0);
231
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 */
236         if (status)
237             return status;
238
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;
242     }
243
244     cairo_matrix_scale (&scaled_font->logical_to_device,
245                         1.0 / scaled_font->logical_scale, 1.0 / scaled_font->logical_scale);
246
247     scaled_font->device_to_logical = scaled_font->logical_to_device;
248
249     status = cairo_matrix_invert (&scaled_font->device_to_logical);
250     if (status)
251         cairo_matrix_init_identity (&scaled_font->device_to_logical);
252
253     return CAIRO_STATUS_SUCCESS;
254 }
255
256 static cairo_bool_t
257 _have_cleartype_quality (void)
258 {
259     OSVERSIONINFO version_info;
260
261     version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
262
263     if (!GetVersionEx (&version_info)) {
264         _cairo_win32_print_gdi_error ("_have_cleartype_quality");
265         return FALSE;
266     }
267
268     return (version_info.dwMajorVersion > 5 ||
269             (version_info.dwMajorVersion == 5 &&
270              version_info.dwMinorVersion >= 1));        /* XP or newer */
271 }
272
273 static BYTE
274 _get_system_quality (void)
275 {
276     BOOL font_smoothing;
277     UINT smoothing_type;
278
279     if (!SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) {
280         _cairo_win32_print_gdi_error ("_get_system_quality");
281         return DEFAULT_QUALITY;
282     }
283
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;
290             }
291
292             if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE)
293                 return CLEARTYPE_QUALITY;
294         }
295
296         return ANTIALIASED_QUALITY;
297     } else {
298         return DEFAULT_QUALITY;
299     }
300 }
301
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
306  * logfont.
307  */
308 static cairo_status_t
309 _win32_scaled_font_create (LOGFONTW                   *logfont,
310                            HFONT                      face_hfont,
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)
316 {
317     HDC hdc;
318     cairo_win32_scaled_font_t *f;
319     cairo_matrix_t scale;
320     cairo_status_t status;
321
322     hdc = _get_global_font_dc ();
323     if (hdc == NULL)
324         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
325
326     f = malloc (sizeof(cairo_win32_scaled_font_t));
327     if (f == NULL)
328         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
329
330     f->logfont = *logfont;
331
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
335      * the 'quality'.
336      *
337      * XXX: The other option we could pay attention to, but don't
338      *      here is the hint_metrics options.
339      */
340     if (options->antialias == CAIRO_ANTIALIAS_DEFAULT)
341         f->quality = _get_system_quality ();
342     else {
343         switch (options->antialias) {
344         case CAIRO_ANTIALIAS_NONE:
345             f->quality = NONANTIALIASED_QUALITY;
346             break;
347         case CAIRO_ANTIALIAS_GRAY:
348         case CAIRO_ANTIALIAS_FAST:
349         case CAIRO_ANTIALIAS_GOOD:
350             f->quality = ANTIALIASED_QUALITY;
351             break;
352         case CAIRO_ANTIALIAS_SUBPIXEL:
353         case CAIRO_ANTIALIAS_BEST:
354             if (_have_cleartype_quality ())
355                 f->quality = CLEARTYPE_QUALITY;
356             else
357                 f->quality = ANTIALIASED_QUALITY;
358             break;
359         case CAIRO_ANTIALIAS_DEFAULT:
360             ASSERT_NOT_REACHED;
361         }
362     }
363
364     f->em_square = 0;
365     f->scaled_hfont = NULL;
366     f->unscaled_hfont = NULL;
367     f->has_type1_notdef_index = FALSE;
368
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.
376          */
377         f->scaled_hfont = face_hfont;
378     }
379     /* don't delete the hfont if we're using the one passed in to us */
380     f->delete_scaled_hfont = !f->scaled_hfont;
381
382     cairo_matrix_multiply (&scale, font_matrix, ctm);
383     status = _compute_transform (f, &scale);
384     if (status)
385         goto FAIL;
386
387     status = _cairo_scaled_font_init (&f->base, font_face,
388                                       font_matrix, ctm, options,
389                                       &_cairo_win32_scaled_font_backend);
390     if (status)
391         goto FAIL;
392
393     status = _cairo_win32_scaled_font_set_metrics (f);
394     if (status) {
395         _cairo_scaled_font_fini (&f->base);
396         goto FAIL;
397     }
398
399     *font_out = &f->base;
400     return CAIRO_STATUS_SUCCESS;
401
402  FAIL:
403     free (f);
404     return status;
405 }
406
407 static cairo_status_t
408 _win32_scaled_font_set_world_transform (cairo_win32_scaled_font_t *scaled_font,
409                                         HDC                        hdc)
410 {
411     XFORM xform;
412
413     _cairo_matrix_to_win32_xform (&scaled_font->logical_to_device, &xform);
414
415     if (!SetWorldTransform (hdc, &xform))
416         return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");
417
418     return CAIRO_STATUS_SUCCESS;
419 }
420
421 static cairo_status_t
422 _win32_scaled_font_set_identity_transform (HDC hdc)
423 {
424     if (!ModifyWorldTransform (hdc, NULL, MWT_IDENTITY))
425         return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_identity_transform");
426
427     return CAIRO_STATUS_SUCCESS;
428 }
429
430 static cairo_status_t
431 _win32_scaled_font_get_scaled_hfont (cairo_win32_scaled_font_t *scaled_font,
432                                      HFONT *hfont_out)
433 {
434     if (!scaled_font->scaled_hfont) {
435         LOGFONTW logfont = scaled_font->logfont;
436         logfont.lfHeight = -scaled_font->logical_size;
437         logfont.lfWidth = 0;
438         logfont.lfEscapement = 0;
439         logfont.lfOrientation = 0;
440         logfont.lfQuality = scaled_font->quality;
441
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");
445     }
446
447     *hfont_out = scaled_font->scaled_hfont;
448     return CAIRO_STATUS_SUCCESS;
449 }
450
451 static cairo_status_t
452 _win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font,
453                                        HDC                        hdc,
454                                        HFONT                     *hfont_out)
455 {
456     if (scaled_font->unscaled_hfont == NULL) {
457         OUTLINETEXTMETRIC *otm;
458         unsigned int otm_size;
459         HFONT scaled_hfont;
460         LOGFONTW logfont;
461         cairo_status_t status;
462
463         status = _win32_scaled_font_get_scaled_hfont (scaled_font,
464                                                       &scaled_hfont);
465         if (status)
466             return status;
467
468         if (! SelectObject (hdc, scaled_hfont))
469             return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:SelectObject");
470
471         otm_size = GetOutlineTextMetrics (hdc, 0, NULL);
472         if (! otm_size)
473             return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics");
474
475         otm = malloc (otm_size);
476         if (otm == NULL)
477             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
478
479         if (! GetOutlineTextMetrics (hdc, otm_size, otm)) {
480             status = _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics");
481             free (otm);
482             return status;
483         }
484
485         scaled_font->em_square = otm->otmEMSquare;
486         free (otm);
487
488         logfont = scaled_font->logfont;
489         logfont.lfHeight = -scaled_font->em_square;
490         logfont.lfWidth = 0;
491         logfont.lfEscapement = 0;
492         logfont.lfOrientation = 0;
493         logfont.lfQuality = scaled_font->quality;
494
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");
498     }
499
500     *hfont_out = scaled_font->unscaled_hfont;
501     return CAIRO_STATUS_SUCCESS;
502 }
503
504 static cairo_status_t
505 _cairo_win32_scaled_font_select_unscaled_font (cairo_scaled_font_t *scaled_font,
506                                                HDC                  hdc)
507 {
508     cairo_status_t status;
509     HFONT hfont;
510     HFONT old_hfont = NULL;
511
512     status = _win32_scaled_font_get_unscaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, hdc, &hfont);
513     if (status)
514         return status;
515
516     old_hfont = SelectObject (hdc, hfont);
517     if (!old_hfont)
518         return _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_select_unscaled_font");
519
520     status = _win32_scaled_font_set_identity_transform (hdc);
521     if (status) {
522         SelectObject (hdc, old_hfont);
523         return status;
524     }
525
526     SetMapMode (hdc, MM_TEXT);
527
528     return CAIRO_STATUS_SUCCESS;
529 }
530
531 cairo_bool_t
532 _cairo_win32_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font)
533 {
534     cairo_win32_scaled_font_t *win32_scaled_font;
535
536     win32_scaled_font = (cairo_win32_scaled_font_t *) scaled_font;
537
538     return win32_scaled_font->is_type1;
539 }
540
541 cairo_bool_t
542 _cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font)
543 {
544     cairo_win32_scaled_font_t *win32_scaled_font;
545
546     win32_scaled_font = (cairo_win32_scaled_font_t *) scaled_font;
547
548     return win32_scaled_font->is_bitmap;
549 }
550
551 static void
552 _cairo_win32_scaled_font_done_unscaled_font (cairo_scaled_font_t *scaled_font)
553 {
554 }
555
556 /* implement the font backend interface */
557
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)
561 {
562     LOGFONTW logfont;
563     uint16_t *face_name;
564     int face_name_len;
565     cairo_status_t status;
566
567     status = _cairo_utf8_to_utf16 (toy_face->family, -1,
568                                    &face_name, &face_name_len);
569     if (status)
570         return status;
571
572     if (face_name_len > LF_FACESIZE - 1)
573         face_name_len = LF_FACESIZE - 1;
574
575     memcpy (logfont.lfFaceName, face_name, sizeof (uint16_t) * face_name_len);
576     logfont.lfFaceName[face_name_len] = 0;
577     free (face_name);
578
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 */
583
584     switch (toy_face->weight) {
585     case CAIRO_FONT_WEIGHT_NORMAL:
586     default:
587         logfont.lfWeight = FW_NORMAL;
588         break;
589     case CAIRO_FONT_WEIGHT_BOLD:
590         logfont.lfWeight = FW_BOLD;
591         break;
592     }
593
594     switch (toy_face->slant) {
595     case CAIRO_FONT_SLANT_NORMAL:
596     default:
597         logfont.lfItalic = FALSE;
598         break;
599     case CAIRO_FONT_SLANT_ITALIC:
600     case CAIRO_FONT_SLANT_OBLIQUE:
601         logfont.lfItalic = TRUE;
602         break;
603     }
604
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.
610      */
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;
616
617     *font_face = cairo_win32_font_face_create_for_logfontw (&logfont);
618
619     return CAIRO_STATUS_SUCCESS;
620 }
621
622 static void
623 _cairo_win32_scaled_font_fini (void *abstract_font)
624 {
625     cairo_win32_scaled_font_t *scaled_font = abstract_font;
626
627     if (scaled_font == NULL)
628         return;
629
630     if (scaled_font->scaled_hfont && scaled_font->delete_scaled_hfont)
631         DeleteObject (scaled_font->scaled_hfont);
632
633     if (scaled_font->unscaled_hfont)
634         DeleteObject (scaled_font->unscaled_hfont);
635 }
636
637 static cairo_int_status_t
638 _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled_font,
639                                                double                     x,
640                                                double                     y,
641                                                const char                *utf8,
642                                                cairo_glyph_t            **glyphs,
643                                                int                       *num_glyphs)
644 {
645     uint16_t *utf16;
646     int n16;
647     int i;
648     WORD *glyph_indices = NULL;
649     cairo_status_t status;
650     double x_pos, y_pos;
651     HDC hdc = NULL;
652     cairo_matrix_t mat;
653
654     status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);
655     if (status)
656         return status;
657
658     glyph_indices = _cairo_malloc_ab (n16 + 1, sizeof (WORD));
659     if (!glyph_indices) {
660         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
661         goto FAIL1;
662     }
663
664     hdc = _get_global_font_dc ();
665     assert (hdc != NULL);
666
667     status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
668     if (status)
669         goto FAIL2;
670
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");
673         goto FAIL3;
674     }
675
676     *num_glyphs = n16;
677     *glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t));
678     if (!*glyphs) {
679         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
680         goto FAIL3;
681     }
682
683     x_pos = x;
684     y_pos = y;
685
686     mat = scaled_font->base.ctm;
687     status = cairo_matrix_invert (&mat);
688     assert (status == CAIRO_STATUS_SUCCESS);
689
690     _cairo_scaled_font_freeze_cache (&scaled_font->base);
691
692     for (i = 0; i < n16; i++) {
693         cairo_scaled_glyph_t *scaled_glyph;
694
695         (*glyphs)[i].index = glyph_indices[i];
696         (*glyphs)[i].x = x_pos;
697         (*glyphs)[i].y = y_pos;
698
699         status = _cairo_scaled_glyph_lookup (&scaled_font->base,
700                                              glyph_indices[i],
701                                              CAIRO_SCALED_GLYPH_INFO_METRICS,
702                                              &scaled_glyph);
703         if (status) {
704             free (*glyphs);
705             *glyphs = NULL;
706             break;
707         }
708
709         x = scaled_glyph->x_advance;
710         y = scaled_glyph->y_advance;
711         cairo_matrix_transform_distance (&mat, &x, &y);
712         x_pos += x;
713         y_pos += y;
714     }
715
716     _cairo_scaled_font_thaw_cache (&scaled_font->base);
717
718 FAIL3:
719     cairo_win32_scaled_font_done_font (&scaled_font->base);
720 FAIL2:
721     free (glyph_indices);
722 FAIL1:
723     free (utf16);
724
725     return status;
726 }
727
728 static cairo_int_status_t
729 _cairo_win32_scaled_font_text_to_glyphs (void           *abstract_font,
730                                          double         x,
731                                          double         y,
732                                          const char     *utf8,
733                                          cairo_glyph_t **glyphs,
734                                          int            *num_glyphs)
735 {
736     cairo_win32_scaled_font_t *scaled_font = abstract_font;
737     uint16_t *utf16;
738     int n16;
739     GCP_RESULTSW gcp_results;
740     unsigned int buffer_size, i;
741     WCHAR *glyph_indices = NULL;
742     int *dx = NULL;
743     cairo_status_t status;
744     double x_pos, y_pos;
745     double x_incr, y_incr;
746     HDC hdc = NULL;
747
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,
752                                                                x,
753                                                                y,
754                                                                utf8,
755                                                                glyphs,
756                                                                num_glyphs);
757
758     /* Compute a vector in user space along the baseline of length one logical space unit */
759     x_incr = 1;
760     y_incr = 0;
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;
764
765     status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);
766     if (status)
767         return status;
768
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;
774
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);
778         goto FAIL1;
779     }
780
781     hdc = _get_global_font_dc ();
782     assert (hdc != NULL);
783
784     status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
785     if (status)
786         goto FAIL1;
787
788     while (TRUE) {
789         free (glyph_indices);
790         glyph_indices = NULL;
791
792         free (dx);
793         dx = NULL;
794
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);
799             goto FAIL2;
800         }
801
802         gcp_results.nGlyphs = buffer_size;
803         gcp_results.lpDx = dx;
804         gcp_results.lpGlyphs = glyph_indices;
805
806         if (!GetCharacterPlacementW (hdc, utf16, n16,
807                                      0,
808                                      &gcp_results,
809                                      GCP_DIACRITIC | GCP_LIGATE | GCP_GLYPHSHAPE | GCP_REORDER)) {
810             status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_text_to_glyphs");
811             goto FAIL2;
812         }
813
814         if (gcp_results.lpDx && gcp_results.lpGlyphs)
815             break;
816
817         /* Too small a buffer, try again */
818
819         buffer_size += buffer_size / 2;
820         if (buffer_size > INT_MAX) {
821             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
822             goto FAIL2;
823         }
824     }
825
826     *num_glyphs = gcp_results.nGlyphs;
827     *glyphs = _cairo_malloc_ab (gcp_results.nGlyphs, sizeof (cairo_glyph_t));
828     if (!*glyphs) {
829         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
830         goto FAIL2;
831     }
832
833     x_pos = x;
834     y_pos = y;
835
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;
840
841         x_pos += x_incr * dx[i];
842         y_pos += y_incr * dx[i];
843     }
844
845  FAIL2:
846     free (glyph_indices);
847     free (dx);
848
849     cairo_win32_scaled_font_done_font (&scaled_font->base);
850
851  FAIL1:
852     free (utf16);
853
854     return status;
855 }
856
857 static unsigned long
858 _cairo_win32_scaled_font_ucs4_to_index (void            *abstract_font,
859                                         uint32_t         ucs4)
860 {
861     cairo_win32_scaled_font_t *scaled_font = abstract_font;
862     wchar_t unicode[2];
863     WORD glyph_index;
864     HDC hdc = NULL;
865     cairo_status_t status;
866
867     hdc = _get_global_font_dc ();
868     assert (hdc != NULL);
869
870     status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
871     if (status)
872         return 0;
873
874     unicode[0] = ucs4;
875     unicode[1] = 0;
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");
878         glyph_index = 0;
879     }
880
881     cairo_win32_scaled_font_done_font (&scaled_font->base);
882
883     return glyph_index;
884 }
885
886 static cairo_status_t
887 _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font)
888 {
889     cairo_status_t status;
890     cairo_font_extents_t extents;
891
892     TEXTMETRIC metrics;
893     HDC hdc;
894
895     hdc = _get_global_font_dc ();
896     assert (hdc != NULL);
897
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
901          */
902         status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
903         if (status)
904             return status;
905         GetTextMetrics (hdc, &metrics);
906         cairo_win32_scaled_font_done_font (&scaled_font->base);
907
908         extents.ascent = metrics.tmAscent / scaled_font->logical_scale;
909         extents.descent = metrics.tmDescent / scaled_font->logical_scale;
910
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;
914
915     } else {
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
919          * avoid them.
920          */
921         status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
922         if (status)
923             return status;
924         GetTextMetrics (hdc, &metrics);
925         _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
926
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;
932
933     }
934
935     scaled_font->is_bitmap = !(metrics.tmPitchAndFamily & TMPF_VECTOR);
936
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.
945      */
946     scaled_font->is_type1 = FALSE;
947     if (!(metrics.tmPitchAndFamily & TMPF_TRUETYPE) &&
948         (metrics.tmPitchAndFamily & TMPF_VECTOR))
949     {
950          if ((GetFontData (hdc, CMAP_TAG, 0, NULL, 0) == GDI_ERROR) &&
951              (GetFontData (hdc, 0, 0, NULL, 0) != GDI_ERROR))
952          {
953               scaled_font->is_type1 = TRUE;
954          }
955     }
956
957     return _cairo_scaled_font_set_metrics (&scaled_font->base, &extents);
958 }
959
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)
963 {
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;
968     HDC hdc;
969
970     hdc = _get_global_font_dc ();
971     assert (hdc != NULL);
972
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;
976         INT width = 0;
977         UINT charIndex = _cairo_scaled_glyph_index (scaled_glyph);
978
979         cairo_scaled_font_extents (&scaled_font->base, &font_extents);
980
981         status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
982         if (status)
983             return status;
984
985         if (!GetCharWidth32(hdc, charIndex, charIndex, &width)) {
986             status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetCharWidth32");
987             width = 0;
988         }
989         cairo_win32_scaled_font_done_font (&scaled_font->base);
990         if (status)
991             return status;
992
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.
1002          */
1003         status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
1004         if (status)
1005             return status;
1006
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));
1011         } else {
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).
1020                  */
1021                 metrics.gmptGlyphOrigin.x -= 1;
1022                 metrics.gmBlackBoxX += 3;
1023             }
1024         }
1025         cairo_win32_scaled_font_done_font (&scaled_font->base);
1026
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;
1034         } else {
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;
1041         }
1042
1043         if (scaled_font->swap_x) {
1044             extents.x_bearing = (- extents.x_bearing - extents.width);
1045             extents.x_advance = - extents.x_advance;
1046         }
1047
1048         if (scaled_font->swap_y) {
1049             extents.y_bearing = (- extents.y_bearing - extents.height);
1050             extents.y_advance = - extents.y_advance;
1051         }
1052
1053     } else {
1054         /* For all other transformations, we use the design metrics
1055          * of the font.
1056          */
1057         status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
1058         if (status)
1059             return status;
1060
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));
1065         }
1066         _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
1067
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;
1074     }
1075
1076     _cairo_scaled_glyph_set_metrics (scaled_glyph,
1077                                      &scaled_font->base,
1078                                      &extents);
1079
1080     return CAIRO_STATUS_SUCCESS;
1081 }
1082
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.
1087  */
1088 #if 0
1089 static cairo_status_t
1090 _cairo_win32_scaled_font_glyph_bbox (void                *abstract_font,
1091                                      const cairo_glyph_t *glyphs,
1092                                      int                  num_glyphs,
1093                                      cairo_box_t         *bbox)
1094 {
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;
1098
1099     if (num_glyphs > 0) {
1100         HDC hdc;
1101         GLYPHMETRICS metrics;
1102         cairo_status_t status;
1103         int i;
1104
1105         hdc = _get_global_font_dc ();
1106         assert (hdc != NULL);
1107
1108         status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
1109         if (status)
1110             return status;
1111
1112         for (i = 0; i < num_glyphs; i++) {
1113             int x = _cairo_lround (glyphs[i].x);
1114             int y = _cairo_lround (glyphs[i].y);
1115
1116             GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | GGO_GLYPH_INDEX,
1117                              &metrics, 0, NULL, &matrix);
1118
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;
1127         }
1128
1129         cairo_win32_scaled_font_done_font (&scaled_font->base);
1130     }
1131
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);
1136
1137     return CAIRO_STATUS_SUCCESS;
1138 }
1139 #endif
1140
1141 typedef struct {
1142     cairo_win32_scaled_font_t *scaled_font;
1143     HDC hdc;
1144
1145     cairo_array_t glyphs;
1146     cairo_array_t dx;
1147
1148     int start_x;
1149     int last_x;
1150     int last_y;
1151 } cairo_glyph_state_t;
1152
1153 static void
1154 _start_glyphs (cairo_glyph_state_t        *state,
1155                cairo_win32_scaled_font_t  *scaled_font,
1156                HDC                         hdc)
1157 {
1158     state->hdc = hdc;
1159     state->scaled_font = scaled_font;
1160
1161     _cairo_array_init (&state->glyphs, sizeof (WCHAR));
1162     _cairo_array_init (&state->dx, sizeof (int));
1163 }
1164
1165 static cairo_status_t
1166 _flush_glyphs (cairo_glyph_state_t *state)
1167 {
1168     cairo_status_t status;
1169     int dx = 0;
1170     WCHAR * elements;
1171     int * dx_elements;
1172
1173     status = _cairo_array_append (&state->dx, &dx);
1174     if (status)
1175         return status;
1176
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,
1181                       ETO_GLYPH_INDEX,
1182                       NULL,
1183                       elements,
1184                       state->glyphs.num_elements,
1185                       dx_elements)) {
1186         return _cairo_win32_print_gdi_error ("_flush_glyphs");
1187     }
1188
1189     _cairo_array_truncate (&state->glyphs, 0);
1190     _cairo_array_truncate (&state->dx, 0);
1191
1192     return CAIRO_STATUS_SUCCESS;
1193 }
1194
1195 static cairo_status_t
1196 _add_glyph (cairo_glyph_state_t *state,
1197             unsigned long        index,
1198             double               device_x,
1199             double               device_y)
1200 {
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;
1206
1207     cairo_matrix_transform_point (&state->scaled_font->device_to_logical, &user_x, &user_y);
1208
1209     logical_x = _cairo_lround (user_x);
1210     logical_y = _cairo_lround (user_y);
1211
1212     if (state->glyphs.num_elements > 0) {
1213         int dx;
1214
1215         if (logical_y != state->last_y) {
1216             status = _flush_glyphs (state);
1217             if (status)
1218                 return status;
1219             state->start_x = logical_x;
1220         } else {
1221             dx = logical_x - state->last_x;
1222             status = _cairo_array_append (&state->dx, &dx);
1223             if (status)
1224                 return status;
1225         }
1226     } else {
1227         state->start_x = logical_x;
1228     }
1229
1230     state->last_x = logical_x;
1231     state->last_y = logical_y;
1232
1233     status = _cairo_array_append (&state->glyphs, &glyph_index);
1234     if (status)
1235         return status;
1236
1237     return CAIRO_STATUS_SUCCESS;
1238 }
1239
1240 static cairo_status_t
1241 _finish_glyphs (cairo_glyph_state_t *state)
1242 {
1243     cairo_status_t status;
1244
1245     status = _flush_glyphs (state);
1246
1247     _cairo_array_fini (&state->glyphs);
1248     _cairo_array_fini (&state->dx);
1249
1250     return status;
1251 }
1252
1253 static cairo_status_t
1254 _draw_glyphs_on_surface (cairo_win32_surface_t     *surface,
1255                          cairo_win32_scaled_font_t *scaled_font,
1256                          COLORREF                   color,
1257                          int                        x_offset,
1258                          int                        y_offset,
1259                          const cairo_glyph_t       *glyphs,
1260                          int                        num_glyphs)
1261 {
1262     cairo_glyph_state_t state;
1263     cairo_status_t status, status2;
1264     int i;
1265
1266     if (!SaveDC (surface->dc))
1267         return _cairo_win32_print_gdi_error ("_draw_glyphs_on_surface:SaveDC");
1268
1269     status = cairo_win32_scaled_font_select_font (&scaled_font->base, surface->dc);
1270     if (status)
1271         goto FAIL1;
1272
1273     SetTextColor (surface->dc, color);
1274     SetTextAlign (surface->dc, TA_BASELINE | TA_LEFT);
1275     SetBkMode (surface->dc, TRANSPARENT);
1276
1277     _start_glyphs (&state, scaled_font, surface->dc);
1278
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);
1282         if (status)
1283             goto FAIL2;
1284     }
1285
1286  FAIL2:
1287     status2 = _finish_glyphs (&state);
1288     if (status == CAIRO_STATUS_SUCCESS)
1289         status = status2;
1290
1291     cairo_win32_scaled_font_done_font (&scaled_font->base);
1292  FAIL1:
1293     RestoreDC (surface->dc, -1);
1294
1295     return status;
1296 }
1297
1298 /* Duplicate the green channel of a 4-channel mask in the alpha channel, then
1299  * invert the whole mask.
1300  */
1301 static void
1302 _compute_argb32_mask_alpha (cairo_win32_surface_t *mask_surface)
1303 {
1304     cairo_image_surface_t *image = (cairo_image_surface_t *)mask_surface->image;
1305     int i, j;
1306
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));
1311             p++;
1312         }
1313     }
1314 }
1315
1316 /* Invert a mask
1317  */
1318 static void
1319 _invert_argb32_mask (cairo_win32_surface_t *mask_surface)
1320 {
1321     cairo_image_surface_t *image = (cairo_image_surface_t *)mask_surface->image;
1322     int i, j;
1323
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;
1328             p++;
1329         }
1330     }
1331 }
1332
1333 /* Compute an alpha-mask from a monochrome RGB24 image
1334  */
1335 static cairo_surface_t *
1336 _compute_a8_mask (cairo_win32_surface_t *mask_surface)
1337 {
1338     cairo_image_surface_t *image24 = (cairo_image_surface_t *)mask_surface->image;
1339     cairo_image_surface_t *image8;
1340     int i, j;
1341
1342     if (image24->base.status)
1343         return cairo_surface_reference (&image24->base);
1344
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;
1349
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);
1353
1354         for (j = 0; j < image24->width; j++) {
1355             *q = 255 - ((*p & 0x0000ff00) >> 8);
1356             p++;
1357             q++;
1358         }
1359     }
1360
1361     return &image8->base;
1362 }
1363
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)
1368 {
1369     cairo_win32_scaled_font_t *scaled_font = abstract_font;
1370     cairo_status_t status;
1371
1372     if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) {
1373         status = _cairo_win32_scaled_font_init_glyph_metrics (scaled_font, scaled_glyph);
1374         if (status)
1375             return status;
1376     }
1377
1378     if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
1379         status = _cairo_win32_scaled_font_init_glyph_surface (scaled_font, scaled_glyph);
1380         if (status)
1381             return status;
1382     }
1383
1384     if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) {
1385         status = _cairo_win32_scaled_font_init_glyph_path (scaled_font, scaled_glyph);
1386         if (status)
1387             return status;
1388     }
1389
1390     return CAIRO_STATUS_SUCCESS;
1391 }
1392
1393 #if 0
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,
1399                                       int                        source_x,
1400                                       int                        source_y,
1401                                       int                        dest_x,
1402                                       int                        dest_y,
1403                                       unsigned int               width,
1404                                       unsigned int               height,
1405                                       cairo_glyph_t             *glyphs,
1406                                       int                        num_glyphs,
1407                                       cairo_region_t            *clip_region,
1408                                       int                       *remaining_glyphs)
1409 {
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;
1413
1414     if (width == 0 || height == 0)
1415         return CAIRO_STATUS_SUCCESS;
1416
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)) {
1421
1422         cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)pattern;
1423
1424         /* When compositing OVER on a GDI-understood surface, with a
1425          * solid opaque color, we can just call ExtTextOut directly.
1426          */
1427         COLORREF new_color;
1428
1429         status = _cairo_win32_surface_set_clip_region (surface, clip_region);
1430         if (unlikely (status))
1431             return status;
1432
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);
1436
1437         return _draw_glyphs_on_surface (surface, scaled_font, new_color,
1438                                         0, 0,
1439                                         glyphs, num_glyphs);
1440     } else {
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.
1446          */
1447         cairo_win32_surface_t *tmp_surface;
1448         cairo_surface_t *mask_surface;
1449         cairo_surface_pattern_t mask;
1450         RECT r;
1451
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;
1455
1456         r.left = 0;
1457         r.top = 0;
1458         r.right = width;
1459         r.bottom = height;
1460         FillRect (tmp_surface->dc, &r, GetStockObject (WHITE_BRUSH));
1461
1462         status = _draw_glyphs_on_surface (tmp_surface,
1463                                           scaled_font, RGB (0, 0, 0),
1464                                           dest_x, dest_y,
1465                                           glyphs, num_glyphs);
1466         if (status) {
1467             cairo_surface_destroy (&tmp_surface->base);
1468             return status;
1469         }
1470
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
1476              */
1477
1478             if (surface->format != CAIRO_FORMAT_RGB24)
1479                 _compute_argb32_mask_alpha (tmp_surface);
1480             else
1481                 _invert_argb32_mask (tmp_surface);
1482
1483             mask_surface = &tmp_surface->base;
1484         } else {
1485             mask_surface = _compute_a8_mask (tmp_surface);
1486             cairo_surface_destroy (&tmp_surface->base);
1487             status = mask_surface->status;
1488             if (status)
1489                 return status;
1490         }
1491
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
1494          * destination
1495          */
1496         _cairo_pattern_init_for_surface (&mask, mask_surface);
1497         cairo_surface_destroy (mask_surface);
1498
1499         if (scaled_font->quality == CLEARTYPE_QUALITY)
1500             mask.base.has_component_alpha = TRUE;
1501
1502         status = _cairo_surface_mask (&surface->base, op, pattern, &mask.base,
1503                                            clip_region);
1504
1505         _cairo_pattern_fini (&mask.base);
1506
1507         return status;
1508     }
1509 }
1510 #endif
1511
1512 static cairo_int_status_t
1513 _cairo_win32_scaled_font_load_truetype_table (void             *abstract_font,
1514                                              unsigned long      tag,
1515                                              long               offset,
1516                                              unsigned char     *buffer,
1517                                              unsigned long     *length)
1518 {
1519     cairo_win32_scaled_font_t *scaled_font = abstract_font;
1520     HDC hdc;
1521     cairo_status_t status;
1522     DWORD ret;
1523
1524     hdc = _get_global_font_dc ();
1525     assert (hdc != NULL);
1526
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);
1529     if (status)
1530         return status;
1531
1532     ret = GetFontData (hdc, tag, offset, buffer, *length);
1533     if (ret == GDI_ERROR || (buffer && ret != *length))
1534         status = CAIRO_INT_STATUS_UNSUPPORTED;
1535     else
1536         *length = ret;
1537
1538     cairo_win32_scaled_font_done_font (&scaled_font->base);
1539
1540     return status;
1541 }
1542
1543 static cairo_int_status_t
1544 _cairo_win32_scaled_font_index_to_ucs4 (void            *abstract_font,
1545                                         unsigned long    index,
1546                                         uint32_t        *ucs4)
1547 {
1548     cairo_win32_scaled_font_t *scaled_font = abstract_font;
1549     GLYPHSET *glyph_set;
1550     uint16_t *utf16 = NULL;
1551     WORD *glyph_indices = NULL;
1552     HDC hdc = NULL;
1553     int res;
1554     unsigned int i, j, num_glyphs;
1555     cairo_status_t status;
1556
1557     hdc = _get_global_font_dc ();
1558     assert (hdc != NULL);
1559
1560     status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
1561     if (status)
1562         return status;
1563
1564     res = GetFontUnicodeRanges(hdc, NULL);
1565     if (res == 0) {
1566         status = _cairo_win32_print_gdi_error (
1567             "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
1568         goto exit1;
1569     }
1570
1571     glyph_set = malloc (res);
1572     if (glyph_set == NULL) {
1573         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1574         goto exit1;
1575     }
1576
1577     res = GetFontUnicodeRanges(hdc, glyph_set);
1578     if (res == 0) {
1579         status = _cairo_win32_print_gdi_error (
1580             "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
1581         goto exit1;
1582     }
1583
1584     *ucs4 = (uint32_t) -1;
1585     for (i = 0; i < glyph_set->cRanges; i++) {
1586         num_glyphs = glyph_set->ranges[i].cGlyphs;
1587
1588         utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t));
1589         if (utf16 == NULL) {
1590             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1591             goto exit1;
1592         }
1593
1594         glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD));
1595         if (glyph_indices == NULL) {
1596             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1597             goto exit2;
1598         }
1599
1600         for (j = 0; j < num_glyphs; j++)
1601             utf16[j] = glyph_set->ranges[i].wcLow + j;
1602         utf16[j] = 0;
1603
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");
1607             goto exit2;
1608         }
1609
1610         for (j = 0; j < num_glyphs; j++) {
1611             if (glyph_indices[j] == index) {
1612                 *ucs4 = utf16[j];
1613                 goto exit2;
1614             }
1615         }
1616
1617         free (glyph_indices);
1618         glyph_indices = NULL;
1619         free (utf16);
1620         utf16 = NULL;
1621     }
1622
1623 exit2:
1624     free (glyph_indices);
1625     free (utf16);
1626     free (glyph_set);
1627 exit1:
1628     cairo_win32_scaled_font_done_font (&scaled_font->base);
1629
1630     return status;
1631 }
1632
1633 static cairo_bool_t
1634 _cairo_win32_scaled_font_is_synthetic (void            *abstract_font)
1635 {
1636     cairo_win32_scaled_font_t *scaled_font = abstract_font;
1637     cairo_status_t status;
1638     int weight;
1639     cairo_bool_t bold;
1640     cairo_bool_t italic;
1641
1642     status = _cairo_truetype_get_style (&scaled_font->base,
1643                                         &weight,
1644                                         &bold,
1645                                         &italic);
1646     /* If this doesn't work assume it is not synthetic to avoid
1647      * unneccessary subsetting fallbacks. */
1648     if (status != CAIRO_STATUS_SUCCESS)
1649         return FALSE;
1650
1651     if (scaled_font->logfont.lfWeight != weight ||
1652         scaled_font->logfont.lfItalic != italic)
1653         return TRUE;
1654
1655     return FALSE;
1656 }
1657
1658 static cairo_int_status_t
1659 _cairo_win32_scaled_font_index_to_glyph_name (void              *abstract_font,
1660                                               char             **glyph_names,
1661                                               int                num_glyph_names,
1662                                               unsigned long      glyph_index,
1663                                               unsigned long     *glyph_array_index)
1664 {
1665     cairo_win32_scaled_font_t *scaled_font = abstract_font;
1666     int i;
1667
1668     /* Windows puts .notdef at index 0 then numbers the remaining
1669      * glyphs starting from 1 in the order they appear in the font. */
1670
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;
1678                 break;
1679             }
1680         }
1681         if (! scaled_font->has_type1_notdef_index)
1682             return CAIRO_INT_STATUS_UNSUPPORTED;
1683     }
1684
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;
1693     else
1694         return CAIRO_INT_STATUS_UNSUPPORTED;
1695
1696     return CAIRO_STATUS_SUCCESS;
1697 }
1698
1699 static cairo_int_status_t
1700 _cairo_win32_scaled_font_load_type1_data (void              *abstract_font,
1701                                           long               offset,
1702                                           unsigned char     *buffer,
1703                                           unsigned long     *length)
1704 {
1705     cairo_win32_scaled_font_t *scaled_font = abstract_font;
1706
1707     if (! scaled_font->is_type1)
1708         return CAIRO_INT_STATUS_UNSUPPORTED;
1709
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,
1713                                                          0,
1714                                                          offset,
1715                                                          buffer,
1716                                                          length);
1717 }
1718
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)
1722 {
1723     cairo_status_t status;
1724     cairo_glyph_t glyph;
1725     cairo_win32_surface_t *surface;
1726     cairo_t *cr;
1727     cairo_surface_t *image;
1728     int width, height;
1729     int x1, y1, x2, y2;
1730
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);
1735     width = x2 - x1;
1736     height = y2 - y1;
1737
1738     surface = (cairo_win32_surface_t *)
1739         cairo_win32_surface_create_with_dib (CAIRO_FORMAT_RGB24, width, height);
1740
1741     cr = cairo_create (&surface->base);
1742     cairo_set_source_rgb (cr, 1, 1, 1);
1743     cairo_paint (cr);
1744     status = cairo_status (cr);
1745     cairo_destroy(cr);
1746     if (status)
1747         goto FAIL;
1748
1749     glyph.index = _cairo_scaled_glyph_index (scaled_glyph);
1750     glyph.x = -x1;
1751     glyph.y = -y1;
1752     status = _draw_glyphs_on_surface (surface, scaled_font, RGB(0,0,0),
1753                                       0, 0, &glyph, 1);
1754     if (status)
1755         goto FAIL;
1756
1757     GdiFlush();
1758
1759     image = _compute_a8_mask (surface);
1760     status = image->status;
1761     if (status)
1762         goto FAIL;
1763
1764     cairo_surface_set_device_offset (image, -x1, -y1);
1765     _cairo_scaled_glyph_set_surface (scaled_glyph,
1766                                      &scaled_font->base,
1767                                      (cairo_image_surface_t *) image);
1768
1769   FAIL:
1770     cairo_surface_destroy (&surface->base);
1771
1772     return status;
1773 }
1774
1775 static void
1776 _cairo_win32_transform_FIXED_to_fixed (cairo_matrix_t *matrix,
1777                                        FIXED Fx, FIXED Fy,
1778                                        cairo_fixed_t *fx, cairo_fixed_t *fy)
1779 {
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);
1785 }
1786
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)
1790 {
1791     static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, -1 } };
1792     cairo_status_t status;
1793     GLYPHMETRICS metrics;
1794     HDC hdc;
1795     DWORD bytesGlyph;
1796     unsigned char *buffer, *ptr;
1797     cairo_path_fixed_t *path;
1798     cairo_matrix_t transform;
1799     cairo_fixed_t x, y;
1800
1801     if (scaled_font->is_bitmap)
1802         return CAIRO_INT_STATUS_UNSUPPORTED;
1803
1804     hdc = _get_global_font_dc ();
1805     assert (hdc != NULL);
1806
1807     path = _cairo_path_fixed_create ();
1808     if (!path)
1809         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1810
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);
1815     } else {
1816         status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
1817         cairo_matrix_init_identity(&transform);
1818     }
1819     if (status)
1820         goto CLEANUP_PATH;
1821
1822     bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
1823                                    GGO_NATIVE | GGO_GLYPH_INDEX,
1824                                    &metrics, 0, NULL, &matrix);
1825
1826     if (bytesGlyph == GDI_ERROR) {
1827         status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
1828         goto CLEANUP_FONT;
1829     }
1830
1831     ptr = buffer = malloc (bytesGlyph);
1832     if (!buffer) {
1833         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1834         goto CLEANUP_FONT;
1835     }
1836
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;
1842     }
1843
1844     while (ptr < buffer + bytesGlyph) {
1845         TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)ptr;
1846         unsigned char *endPoly = ptr + header->cb;
1847
1848         ptr += sizeof (TTPOLYGONHEADER);
1849
1850         _cairo_win32_transform_FIXED_to_fixed (&transform,
1851                                                header->pfxStart.x,
1852                                                header->pfxStart.y,
1853                                                &x, &y);
1854         status = _cairo_path_fixed_move_to (path, x, y);
1855         if (status)
1856             goto CLEANUP_BUFFER;
1857
1858         while (ptr < endPoly) {
1859             TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr;
1860             POINTFX *points = curve->apfx;
1861             int i;
1862             switch (curve->wType) {
1863             case TT_PRIM_LINE:
1864                 for (i = 0; i < curve->cpfx; i++) {
1865                     _cairo_win32_transform_FIXED_to_fixed (&transform,
1866                                                            points[i].x,
1867                                                            points[i].y,
1868                                                            &x, &y);
1869                     status = _cairo_path_fixed_line_to (path, x, y);
1870                     if (status)
1871                         goto CLEANUP_BUFFER;
1872                 }
1873                 break;
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,
1880                                                            points[i].x,
1881                                                            points[i].y,
1882                                                            &cx, &cy);
1883
1884                     if (i + 1 == curve->cpfx - 1) {
1885                         _cairo_win32_transform_FIXED_to_fixed (&transform,
1886                                                                points[i + 1].x,
1887                                                                points[i + 1].y,
1888                                                                &p2x, &p2y);
1889                     } else {
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,
1893                                                                points[i + 1].x,
1894                                                                points[i + 1].y,
1895                                                                &x, &y);
1896                         p2x = (cx + x) / 2;
1897                         p2y = (cy + y) / 2;
1898                     }
1899
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;
1904
1905                     status = _cairo_path_fixed_curve_to (path, c1x, c1y, c2x, c2y, p2x, p2y);
1906                     if (status)
1907                         goto CLEANUP_BUFFER;
1908                 }
1909                 break;
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,
1914                                                            points[i].x,
1915                                                            points[i].y,
1916                                                            &x, &y);
1917                     _cairo_win32_transform_FIXED_to_fixed (&transform,
1918                                                            points[i + 1].x,
1919                                                            points[i + 1].y,
1920                                                            &x1, &y1);
1921                     _cairo_win32_transform_FIXED_to_fixed (&transform,
1922                                                            points[i + 2].x,
1923                                                            points[i + 2].y,
1924                                                            &x2, &y2);
1925                     status = _cairo_path_fixed_curve_to (path, x, y, x1, y1, x2, y2);
1926                     if (status)
1927                         goto CLEANUP_BUFFER;
1928                 }
1929                 break;
1930             }
1931             ptr += sizeof(TTPOLYCURVE) + sizeof (POINTFX) * (curve->cpfx - 1);
1932         }
1933         status = _cairo_path_fixed_close_path (path);
1934         if (status)
1935             goto CLEANUP_BUFFER;
1936     }
1937
1938     _cairo_scaled_glyph_set_path (scaled_glyph,
1939                                   &scaled_font->base,
1940                                   path);
1941
1942  CLEANUP_BUFFER:
1943     free (buffer);
1944
1945  CLEANUP_FONT:
1946     if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE)
1947         _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
1948     else
1949         cairo_win32_scaled_font_done_font (&scaled_font->base);
1950
1951  CLEANUP_PATH:
1952     if (status != CAIRO_STATUS_SUCCESS)
1953         _cairo_path_fixed_destroy (path);
1954
1955     return status;
1956 }
1957
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
1969 };
1970
1971 /* #cairo_win32_font_face_t */
1972
1973 typedef struct _cairo_win32_font_face cairo_win32_font_face_t;
1974
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
1978  * logfont.
1979  */
1980 struct _cairo_win32_font_face {
1981     cairo_font_face_t base;
1982     LOGFONTW logfont;
1983     HFONT hfont;
1984 };
1985
1986 /* implement the platform-specific interface */
1987
1988 static cairo_bool_t
1989 _is_scale (const cairo_matrix_t *matrix, double scale)
1990 {
1991     return matrix->xx == scale && matrix->yy == scale &&
1992            matrix->xy == 0. && matrix->yx == 0. &&
1993            matrix->x0 == 0. && matrix->y0 == 0.;
1994 }
1995
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)
2002 {
2003     HFONT hfont = NULL;
2004
2005     cairo_win32_font_face_t *font_face = abstract_face;
2006
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;
2012         }
2013     }
2014
2015     return _win32_scaled_font_create (&font_face->logfont,
2016                                       hfont,
2017                                       &font_face->base,
2018                                       font_matrix, ctm, options,
2019                                       font);
2020 }
2021
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
2027 };
2028
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.
2035  *
2036  * Modifications to this hash table are protected by
2037  * _cairo_win32_font_face_mutex.
2038  */
2039
2040 static cairo_hash_table_t *cairo_win32_font_face_hash_table = NULL;
2041
2042 static int
2043 _cairo_win32_font_face_keys_equal (const void *key_a,
2044                                    const void *key_b);
2045
2046 static void
2047 _cairo_win32_font_face_hash_table_destroy (void)
2048 {
2049     cairo_hash_table_t *hash_table;
2050
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);
2058
2059     if (hash_table != NULL)
2060         _cairo_hash_table_destroy (hash_table);
2061 }
2062
2063 static cairo_hash_table_t *
2064 _cairo_win32_font_face_hash_table_lock (void)
2065 {
2066     CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex);
2067
2068     if (unlikely (cairo_win32_font_face_hash_table == NULL))
2069     {
2070         cairo_win32_font_face_hash_table =
2071         _cairo_hash_table_create (_cairo_win32_font_face_keys_equal);
2072
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);
2076             return NULL;
2077         }
2078     }
2079
2080     return cairo_win32_font_face_hash_table;
2081 }
2082
2083 static void
2084 _cairo_win32_font_face_hash_table_unlock (void)
2085 {
2086     CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
2087 }
2088
2089 static void
2090 _cairo_win32_font_face_destroy (void *abstract_face)
2091 {
2092     cairo_win32_font_face_t *font_face = abstract_face;
2093     cairo_hash_table_t *hash_table;
2094
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);
2098
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 ();
2102         return;
2103     }
2104
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);
2112
2113     _cairo_win32_font_face_hash_table_unlock ();
2114 }
2115
2116 static void
2117 _cairo_win32_font_face_init_key (cairo_win32_font_face_t *key,
2118                                  LOGFONTW                *logfont,
2119                                  HFONT                    font)
2120 {
2121     unsigned long hash = _CAIRO_HASH_INIT_VALUE;
2122
2123     key->logfont = *logfont;
2124     key->hfont = font;
2125
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));
2129
2130     key->base.hash_entry.hash = hash;
2131 }
2132
2133 static int
2134 _cairo_win32_font_face_keys_equal (const void *key_a,
2135                                    const void *key_b)
2136 {
2137     const cairo_win32_font_face_t *face_a = key_a;
2138     const cairo_win32_font_face_t *face_b = key_b;
2139
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))
2149         return TRUE;
2150     else
2151         return FALSE;
2152 }
2153
2154 /**
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.
2162  *
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().
2169  *
2170  * Return value: a newly created #cairo_font_face_t. Free with
2171  *  cairo_font_face_destroy() when you are done using it.
2172  **/
2173 cairo_font_face_t *
2174 cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font)
2175 {
2176     cairo_win32_font_face_t *font_face, key;
2177     cairo_hash_table_t *hash_table;
2178     cairo_status_t status;
2179
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;
2184     }
2185
2186     _cairo_win32_font_face_init_key (&key, logfont, font);
2187
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;
2196         }
2197
2198         /* remove the bad font from the hash table */
2199         _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
2200     }
2201
2202     /* Otherwise create it and insert into hash table. */
2203     font_face = malloc (sizeof (cairo_win32_font_face_t));
2204     if (!font_face) {
2205         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2206         goto FAIL;
2207     }
2208
2209     _cairo_win32_font_face_init_key (font_face, logfont, font);
2210     _cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
2211
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))
2216         goto FAIL;
2217
2218     _cairo_win32_font_face_hash_table_unlock ();
2219     return &font_face->base;
2220
2221 FAIL:
2222     _cairo_win32_font_face_hash_table_unlock ();
2223     return (cairo_font_face_t *)&_cairo_font_face_nil;
2224 }
2225
2226 /**
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.
2231  *
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().
2238  *
2239  * Return value: a newly created #cairo_font_face_t. Free with
2240  *  cairo_font_face_destroy() when you are done using it.
2241  **/
2242 cairo_font_face_t *
2243 cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont)
2244 {
2245     return cairo_win32_font_face_create_for_logfontw_hfont (logfont, NULL);
2246 }
2247
2248 /**
2249  * cairo_win32_font_face_create_for_hfont:
2250  * @font: An #HFONT structure specifying the font to use.
2251  *
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().
2258  *
2259  * Return value: a newly created #cairo_font_face_t. Free with
2260  *  cairo_font_face_destroy() when you are done using it.
2261  **/
2262 cairo_font_face_t *
2263 cairo_win32_font_face_create_for_hfont (HFONT font)
2264 {
2265     LOGFONTW logfont;
2266     GetObjectW (font, sizeof(logfont), &logfont);
2267
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. */
2272         font = NULL;
2273     }
2274
2275     return cairo_win32_font_face_create_for_logfontw_hfont (&logfont, font);
2276 }
2277
2278 static cairo_bool_t
2279 _cairo_scaled_font_is_win32 (cairo_scaled_font_t *scaled_font)
2280 {
2281     return scaled_font->backend == &_cairo_win32_scaled_font_backend;
2282 }
2283
2284 /**
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
2289  *
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
2296  * by this function.
2297  *
2298  * See cairo_win32_scaled_font_get_metrics_factor() for converting logical
2299  * coordinates from the device context to font space.
2300  *
2301  * Normally, calls to SaveDC() and RestoreDC() would be made around
2302  * the use of this function to preserve the original graphics state.
2303  *
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.
2307  **/
2308 cairo_status_t
2309 cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
2310                                      HDC                  hdc)
2311 {
2312     cairo_status_t status;
2313     HFONT hfont;
2314     HFONT old_hfont = NULL;
2315     int old_mode;
2316
2317     if (! _cairo_scaled_font_is_win32 (scaled_font)) {
2318         return _cairo_error (CAIRO_STATUS_FONT_TYPE_MISMATCH);
2319     }
2320
2321     if (scaled_font->status)
2322         return scaled_font->status;
2323
2324     status = _win32_scaled_font_get_scaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, &hfont);
2325     if (status)
2326         return status;
2327
2328     old_hfont = SelectObject (hdc, hfont);
2329     if (!old_hfont)
2330         return _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SelectObject");
2331
2332     old_mode = SetGraphicsMode (hdc, GM_ADVANCED);
2333     if (!old_mode) {
2334         status = _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SetGraphicsMode");
2335         SelectObject (hdc, old_hfont);
2336         return status;
2337     }
2338
2339     status = _win32_scaled_font_set_world_transform ((cairo_win32_scaled_font_t *)scaled_font, hdc);
2340     if (status) {
2341         SetGraphicsMode (hdc, old_mode);
2342         SelectObject (hdc, old_hfont);
2343         return status;
2344     }
2345
2346     SetMapMode (hdc, MM_TEXT);
2347
2348     return CAIRO_STATUS_SUCCESS;
2349 }
2350
2351 /**
2352  * cairo_win32_scaled_font_done_font:
2353  * @scaled_font: A scaled font from the Win32 font backend.
2354  *
2355  * Releases any resources allocated by cairo_win32_scaled_font_select_font()
2356  **/
2357 void
2358 cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font)
2359 {
2360     if (! _cairo_scaled_font_is_win32 (scaled_font)) {
2361         _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
2362     }
2363 }
2364
2365 /**
2366  * cairo_win32_scaled_font_get_metrics_factor:
2367  * @scaled_font: a scaled font from the Win32 font backend
2368  *
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.
2373  *
2374  * Return value: factor to multiply logical units by to get font space
2375  *               coordinates.
2376  **/
2377 double
2378 cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font)
2379 {
2380     if (! _cairo_scaled_font_is_win32 (scaled_font)) {
2381         _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
2382         return 1.;
2383     }
2384     return 1. / ((cairo_win32_scaled_font_t *)scaled_font)->logical_scale;
2385 }
2386
2387 /**
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
2391  *
2392  * Gets the transformation mapping the logical space used by @scaled_font
2393  * to device space.
2394  *
2395  * Since: 1.4
2396  **/
2397 void
2398 cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font,
2399                                                cairo_matrix_t *logical_to_device)
2400 {
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);
2405         return;
2406     }
2407     *logical_to_device = win_font->logical_to_device;
2408 }
2409
2410 /**
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
2414  *
2415  * Gets the transformation mapping device space to the logical space
2416  * used by @scaled_font.
2417  *
2418  * Since: 1.4
2419  **/
2420 void
2421 cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
2422                                                cairo_matrix_t *device_to_logical)
2423 {
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);
2428         return;
2429     }
2430     *device_to_logical = win_font->device_to_logical;
2431 }
2432
2433 void
2434 _cairo_win32_font_reset_static_data (void)
2435 {
2436     _cairo_win32_font_face_hash_table_destroy ();
2437 }