Fix severe security issues
[external/pango1.0.git] / pango / pangowin32-fontmap.c
1 /* Pango
2  * pangowin32-fontmap.c: Win32 font handling
3  *
4  * Copyright (C) 2000 Red Hat Software
5  * Copyright (C) 2000 Tor Lillqvist
6  * Copyright (C) 2001 Alexander Larsson
7  * Copyright (C) 2007 Novell, Inc.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 #include "config.h"
26
27 #include <ctype.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32
33 #include "pango-fontmap.h"
34 #include "pango-impl-utils.h"
35 #include "pangowin32-private.h"
36 #include "modules.h"
37
38 typedef struct _PangoWin32Family       PangoWin32Family;
39
40 struct _PangoWin32Family
41 {
42   PangoFontFamily parent_instance;
43
44   char *family_name;
45   GSList *faces;
46
47   gboolean is_monospace;
48 };
49
50 #if !defined(NTM_PS_OPENTYPE)
51 # define NTM_PS_OPENTYPE 0x20000
52 #endif
53
54 #if !defined(NTM_TYPE1)
55 # define NTM_TYPE1 0x100000
56 #endif
57
58 #define PANGO_WIN32_TYPE_FAMILY              (pango_win32_family_get_type ())
59 #define PANGO_WIN32_FAMILY(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_WIN32_TYPE_FAMILY, PangoWin32Family))
60 #define PANGO_WIN32_IS_FAMILY(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_WIN32_TYPE_FAMILY))
61
62 #define PANGO_WIN32_TYPE_FACE              (pango_win32_face_get_type ())
63 #define PANGO_WIN32_FACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_WIN32_TYPE_FACE, PangoWin32Face))
64 #define PANGO_WIN32_IS_FACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_WIN32_TYPE_FACE))
65
66 static GType      pango_win32_face_get_type          (void);
67
68 static GType      pango_win32_family_get_type        (void);
69
70 static void       pango_win32_face_list_sizes        (PangoFontFace  *face,
71                                                       int           **sizes,
72                                                       int            *n_sizes);
73
74 static void       pango_win32_font_map_finalize      (GObject                      *object);
75 static PangoFont *pango_win32_font_map_load_font     (PangoFontMap                 *fontmap,
76                                                       PangoContext                 *context,
77                                                       const PangoFontDescription   *description);
78 static void       pango_win32_font_map_list_families (PangoFontMap                 *fontmap,
79                                                       PangoFontFamily            ***families,
80                                                       int                          *n_families);
81
82 static PangoFont *pango_win32_font_map_real_find_font (PangoWin32FontMap           *win32fontmap,
83                                                        PangoContext                *context,
84                                                        PangoWin32Face              *face,
85                                                        const PangoFontDescription  *description);
86
87 static void       pango_win32_fontmap_cache_clear    (PangoWin32FontMap            *win32fontmap);
88
89 static void       pango_win32_insert_font            (PangoWin32FontMap            *fontmap,
90                                                       LOGFONTW                     *lfp,
91                                                       gboolean                      is_synthetic);
92
93 static PangoWin32Family *pango_win32_get_font_family (PangoWin32FontMap            *win32fontmap,
94                                                       const char                   *family_name);
95
96 static const char *pango_win32_face_get_face_name    (PangoFontFace *face);
97
98 static PangoWin32FontMap *default_fontmap = NULL;
99
100 G_DEFINE_TYPE (PangoWin32FontMap, _pango_win32_font_map, PANGO_TYPE_FONT_MAP)
101
102 #define TOLOWER(c) \
103   (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
104
105 static guint
106 case_insensitive_str_hash (const char *key)
107 {
108   const char *p = key;
109   guint h = TOLOWER (*p);
110
111   if (h)
112     {
113       for (p += 1; *p != '\0'; p++)
114         h = (h << 5) - h + TOLOWER (*p);
115     }
116
117   return h;
118 }
119
120 static gboolean
121 case_insensitive_str_equal (const char *key1,
122                             const char *key2)
123 {
124   while (*key1 && *key2 && TOLOWER (*key1) == TOLOWER (*key2))
125     key1++, key2++;
126   return (!*key1 && !*key2);
127 }
128
129 static guint
130 case_insensitive_wcs_hash (const wchar_t *key)
131 {
132   const wchar_t *p = key;
133   guint h = TOLOWER (*p);
134
135   if (h)
136     {
137       for (p += 1; *p != '\0'; p++)
138         h = (h << 5) - h + TOLOWER (*p);
139     }
140
141   return h;
142 }
143
144 static gboolean
145 case_insensitive_wcs_equal (const wchar_t *key1,
146                             const wchar_t *key2)
147 {
148   while (*key1 && *key2 && TOLOWER (*key1) == TOLOWER (*key2))
149     key1++, key2++;
150   return (!*key1 && !*key2);
151 }
152
153 /* A hash function for LOGFONTWs that takes into consideration only
154  * those fields that indicate a specific .ttf file is in use:
155  * lfFaceName, lfItalic and lfWeight. Dunno how correct this is.
156  */
157 static guint
158 logfontw_nosize_hash (const LOGFONTW *lfp)
159 {
160   return case_insensitive_wcs_hash (lfp->lfFaceName) + (lfp->lfItalic != 0) + lfp->lfWeight;
161 }
162
163 /* Ditto comparison function */
164 static gboolean
165 logfontw_nosize_equal (const LOGFONTW *lfp1,
166                        const LOGFONTW *lfp2)
167 {
168   return (case_insensitive_wcs_equal (lfp1->lfFaceName, lfp2->lfFaceName)
169           && (lfp1->lfItalic != 0) == (lfp2->lfItalic != 0)
170           && lfp1->lfWeight == lfp2->lfWeight);
171 }
172
173 static int CALLBACK
174 pango_win32_inner_enum_proc (LOGFONTW    *lfp,
175                              TEXTMETRICW *metrics,
176                              DWORD        fontType,
177                              LPARAM       lParam)
178 {
179   PangoWin32FontMap *win32fontmap = (PangoWin32FontMap *)lParam;
180
181   /* Windows generates synthetic vertical writing versions of East
182    * Asian fonts with @ prepended to their name, ignore them.
183    */
184   if (lfp->lfFaceName[0] != '@')
185     pango_win32_insert_font (win32fontmap, lfp, FALSE);
186
187   return 1;
188 }
189
190 static int CALLBACK
191 pango_win32_enum_proc (LOGFONTW       *lfp,
192                        NEWTEXTMETRICW *metrics,
193                        DWORD           fontType,
194                        LPARAM          lParam)
195 {
196   LOGFONTW lf;
197
198   PING (("%S: %lu %lx", lfp->lfFaceName, fontType, metrics->ntmFlags));
199
200   if (fontType == TRUETYPE_FONTTYPE ||
201       (_pango_win32_os_version_info.dwMajorVersion >= 5 &&
202        ((metrics->ntmFlags & NTM_PS_OPENTYPE) || (metrics->ntmFlags & NTM_TYPE1))))
203     {
204       lf = *lfp;
205
206       EnumFontFamiliesExW (_pango_win32_hdc, &lf,
207                            (FONTENUMPROCW) pango_win32_inner_enum_proc,
208                            lParam, 0);
209     }
210
211   return 1;
212 }
213
214 static void
215 synthesize_foreach (gpointer key,
216                     gpointer value,
217                     gpointer user_data)
218 {
219   PangoWin32Family *win32family = value;
220   PangoWin32FontMap *win32fontmap = user_data;
221
222   enum { NORMAL, BOLDER, SLANTED };
223   PangoWin32Face *variant[4] = { NULL, NULL, NULL, NULL };
224
225   GSList *p;
226
227   LOGFONTW lf;
228
229   p = win32family->faces;
230   while (p)
231     {
232       PangoWin32Face *win32face = p->data;
233
234       /* Don't synthesize anything unless it's a monospace, serif, or sans font */
235       if (!((win32face->logfontw.lfPitchAndFamily & 0xF0) == FF_MODERN ||
236             (win32face->logfontw.lfPitchAndFamily & 0xF0) == FF_ROMAN ||
237             (win32face->logfontw.lfPitchAndFamily & 0xF0) == FF_SWISS))
238         return;
239
240       if (pango_font_description_get_weight (win32face->description) == PANGO_WEIGHT_NORMAL &&
241           pango_font_description_get_style (win32face->description) == PANGO_STYLE_NORMAL)
242         variant[NORMAL] = win32face;
243
244       if (pango_font_description_get_weight (win32face->description) > PANGO_WEIGHT_NORMAL &&
245           pango_font_description_get_style (win32face->description) == PANGO_STYLE_NORMAL)
246         variant[BOLDER] = win32face;
247
248       if (pango_font_description_get_weight (win32face->description) == PANGO_WEIGHT_NORMAL &&
249           pango_font_description_get_style (win32face->description) >= PANGO_STYLE_OBLIQUE)
250         variant[SLANTED] = win32face;
251
252       if (pango_font_description_get_weight (win32face->description) > PANGO_WEIGHT_NORMAL &&
253           pango_font_description_get_style (win32face->description) >= PANGO_STYLE_OBLIQUE)
254         variant[BOLDER+SLANTED] = win32face;
255
256       p = p->next;
257     }
258
259   if (variant[NORMAL] != NULL && variant[BOLDER] == NULL)
260     {
261       lf = variant[NORMAL]->logfontw;
262       lf.lfWeight = FW_BOLD;
263       
264       pango_win32_insert_font (win32fontmap, &lf, TRUE);
265     }
266
267   if (variant[NORMAL] != NULL && variant[SLANTED] == NULL)
268     {
269       lf = variant[NORMAL]->logfontw;
270       lf.lfItalic = 255;
271       
272       pango_win32_insert_font (win32fontmap, &lf, TRUE);
273     }
274
275   if (variant[NORMAL] != NULL &&
276       variant[BOLDER+SLANTED] == NULL)
277     {
278       lf = variant[NORMAL]->logfontw;
279       lf.lfWeight = FW_BOLD;
280       lf.lfItalic = 255;
281
282       pango_win32_insert_font (win32fontmap, &lf, TRUE);
283     }
284   else if (variant[BOLDER] != NULL &&
285            variant[BOLDER+SLANTED] == NULL)
286     {
287       lf = variant[BOLDER]->logfontw;
288       lf.lfItalic = 255;
289
290       pango_win32_insert_font (win32fontmap, &lf, TRUE);
291     }
292   else if (variant[SLANTED] != NULL &&
293            variant[BOLDER+SLANTED] == NULL)
294     {
295       lf = variant[SLANTED]->logfontw;
296       lf.lfWeight = FW_BOLD;
297
298       pango_win32_insert_font (win32fontmap, &lf, TRUE);
299     }
300 }
301
302 static void
303 create_standard_family (PangoWin32FontMap *win32fontmap,
304                         const char        *standard_family_name)
305 {
306   int i;
307   int n_aliases;
308   char **aliases;
309
310   pango_lookup_aliases (standard_family_name, &aliases, &n_aliases);
311   for (i = 0; i < n_aliases; i++)
312     {
313       PangoWin32Family *existing_family = g_hash_table_lookup (win32fontmap->families, aliases[i]);
314
315       if (existing_family)
316         {
317           PangoWin32Family *new_family = pango_win32_get_font_family (win32fontmap, standard_family_name);
318           GSList *p = existing_family->faces;
319
320           new_family->is_monospace = existing_family->is_monospace;
321
322           while (p)
323             {
324               const PangoWin32Face *old_face = p->data;
325               PangoWin32Face *new_face = g_object_new (PANGO_WIN32_TYPE_FACE, NULL);
326               int j;
327
328               new_face->logfontw = old_face->logfontw;
329               new_face->description = pango_font_description_copy_static (old_face->description);
330               pango_font_description_set_family_static (new_face->description, standard_family_name);
331
332               for (j = 0; j < PANGO_WIN32_N_COVERAGES; j++)
333                 {
334                   if (old_face->coverages[j] != NULL)
335                     new_face->coverages[j] = pango_coverage_ref (old_face->coverages[j]);
336                   else
337                     new_face->coverages[j] = NULL;
338                 }
339
340               new_face->is_synthetic = TRUE;
341
342               new_face->has_cmap = old_face->has_cmap;
343               new_face->cmap_format = old_face->cmap_format;
344               new_face->cmap = old_face->cmap;
345
346               new_face->cached_fonts = NULL;
347
348               new_family->faces = g_slist_append (new_family->faces, new_face);
349
350               p = p->next;
351             }
352           return;
353         }
354     }
355   /* XXX What to do if none of the members of aliases for standard_family_name
356    * exists on this machine?
357    */
358 }
359
360 static void
361 _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap)
362 {
363   LOGFONTW logfont;
364
365   win32fontmap->families = g_hash_table_new ((GHashFunc) case_insensitive_str_hash,
366                                              (GEqualFunc) case_insensitive_str_equal);
367   win32fontmap->fonts =
368     g_hash_table_new ((GHashFunc) logfontw_nosize_hash, (GEqualFunc) logfontw_nosize_equal);
369
370   win32fontmap->font_cache = pango_win32_font_cache_new ();
371   win32fontmap->freed_fonts = g_queue_new ();
372
373   memset (&logfont, 0, sizeof (logfont));
374   logfont.lfCharSet = DEFAULT_CHARSET;
375   EnumFontFamiliesExW (_pango_win32_hdc, &logfont,
376                        (FONTENUMPROCW) pango_win32_enum_proc,
377                        (LPARAM) win32fontmap, 0);
378
379   g_hash_table_foreach (win32fontmap->families, synthesize_foreach, win32fontmap);
380
381   /* Create synthetic "Sans", "Serif" and "Monospace" families */
382   create_standard_family (win32fontmap, "Sans");
383   create_standard_family (win32fontmap, "Serif");
384   create_standard_family (win32fontmap, "Monospace");
385
386   win32fontmap->resolution = (PANGO_SCALE / (double) GetDeviceCaps (_pango_win32_hdc, LOGPIXELSY)) * 72.0;
387 }
388
389 static void
390 _pango_win32_font_map_class_init (PangoWin32FontMapClass *class)
391 {
392   GObjectClass *object_class = G_OBJECT_CLASS (class);
393   PangoFontMapClass *fontmap_class = PANGO_FONT_MAP_CLASS (class);
394   int i;
395
396   class->find_font = pango_win32_font_map_real_find_font;
397   object_class->finalize = pango_win32_font_map_finalize;
398   fontmap_class->load_font = pango_win32_font_map_load_font;
399   fontmap_class->list_families = pango_win32_font_map_list_families;
400   fontmap_class->shape_engine_type = PANGO_RENDER_TYPE_WIN32;
401
402   pango_win32_get_dc ();
403
404   for (i = 0; _pango_included_win32_modules[i].list; i++)
405     pango_module_register (&_pango_included_win32_modules[i]);
406 }
407
408 /**
409  * pango_win32_font_map_for_display:
410  *
411  * Returns a #PangoWin32FontMap. Font maps are cached and should
412  * not be freed. If the font map is no longer needed, it can
413  * be released with pango_win32_shutdown_display().
414  *
415  * Return value: a #PangoFontMap.
416  **/
417 PangoFontMap *
418 pango_win32_font_map_for_display (void)
419 {
420   /* Make sure that the type system is initialized */
421   g_type_init ();
422
423   if (default_fontmap != NULL)
424     return PANGO_FONT_MAP (default_fontmap);
425
426   default_fontmap = g_object_new (PANGO_TYPE_WIN32_FONT_MAP, NULL);
427
428   return PANGO_FONT_MAP (default_fontmap);
429 }
430
431 /**
432  * pango_win32_shutdown_display:
433  *
434  * Free cached resources.
435  **/
436 void
437 pango_win32_shutdown_display (void)
438 {
439   if (default_fontmap)
440     {
441       pango_win32_fontmap_cache_clear (default_fontmap);
442       g_object_unref (default_fontmap);
443
444       default_fontmap = NULL;
445     }
446 }
447
448 static void
449 pango_win32_font_map_finalize (GObject *object)
450 {
451   PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (object);
452
453   g_list_foreach (win32fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
454   g_queue_free (win32fontmap->freed_fonts);
455
456   pango_win32_font_cache_free (win32fontmap->font_cache);
457
458   G_OBJECT_CLASS (_pango_win32_font_map_parent_class)->finalize (object);
459 }
460
461 /*
462  * PangoWin32Family
463  */
464 static void
465 pango_win32_family_list_faces (PangoFontFamily  *family,
466                                PangoFontFace  ***faces,
467                                int              *n_faces)
468 {
469   PangoWin32Family *win32family = PANGO_WIN32_FAMILY (family);
470   GSList *p;
471   int n;
472
473   p = win32family->faces;
474   n = 0;
475   while (p)
476     {
477       n++;
478       p = p->next;
479     }
480
481   if (faces)
482     {
483       int i;
484
485       *faces = g_new (PangoFontFace *, n);
486
487       p = win32family->faces;
488       i = 0;
489       while (p)
490         {
491           (*faces)[i++] = p->data;
492           p = p->next;
493         }
494     }
495   if (n_faces)
496     *n_faces = n;
497 }
498
499 static const char *
500 pango_win32_family_get_name (PangoFontFamily  *family)
501 {
502   PangoWin32Family *win32family = PANGO_WIN32_FAMILY (family);
503
504   return win32family->family_name;
505 }
506
507 static gboolean
508 pango_win32_family_is_monospace (PangoFontFamily *family)
509 {
510   PangoWin32Family *win32family = PANGO_WIN32_FAMILY (family);
511
512   return win32family->is_monospace;
513 }
514
515 static void
516 pango_win32_family_class_init (PangoFontFamilyClass *class)
517 {
518   class->list_faces = pango_win32_family_list_faces;
519   class->get_name = pango_win32_family_get_name;
520   class->is_monospace = pango_win32_family_is_monospace;
521 }
522
523 static GType
524 pango_win32_family_get_type (void)
525 {
526   static GType object_type = 0;
527
528   if (G_UNLIKELY (!object_type))
529     {
530       const GTypeInfo object_info =
531       {
532         sizeof (PangoFontFamilyClass),
533         (GBaseInitFunc) NULL,
534         (GBaseFinalizeFunc) NULL,
535         (GClassInitFunc) pango_win32_family_class_init,
536         NULL,           /* class_finalize */
537         NULL,           /* class_data */
538         sizeof (PangoWin32Family),
539         0,              /* n_preallocs */
540         (GInstanceInitFunc) NULL,
541       };
542
543       object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY,
544                                             I_("PangoWin32Family"),
545                                             &object_info, 0);
546     }
547
548   return object_type;
549 }
550
551 static void
552 list_families_foreach (gpointer key,
553                        gpointer value,
554                        gpointer user_data)
555 {
556   GSList **list = user_data;
557
558   *list = g_slist_prepend (*list, value);
559 }
560
561 static void
562 pango_win32_font_map_list_families (PangoFontMap      *fontmap,
563                                     PangoFontFamily ***families,
564                                     int               *n_families)
565 {
566   GSList *family_list = NULL;
567   GSList *tmp_list;
568   PangoWin32FontMap *win32fontmap = (PangoWin32FontMap *)fontmap;
569
570   if (!n_families)
571     return;
572
573   g_hash_table_foreach (win32fontmap->families, list_families_foreach, &family_list);
574
575   *n_families = g_slist_length (family_list);
576
577   if (families)
578     {
579       int i = 0;
580
581       *families = g_new (PangoFontFamily *, *n_families);
582
583       tmp_list = family_list;
584       while (tmp_list)
585         {
586           (*families)[i] = tmp_list->data;
587           i++;
588           tmp_list = tmp_list->next;
589         }
590     }
591
592   g_slist_free (family_list);
593 }
594
595 static PangoWin32Family *
596 pango_win32_get_font_family (PangoWin32FontMap *win32fontmap,
597                              const char        *family_name)
598 {
599   PangoWin32Family *win32family = g_hash_table_lookup (win32fontmap->families, family_name);
600   if (!win32family)
601     {
602       win32family = g_object_new (PANGO_WIN32_TYPE_FAMILY, NULL);
603       win32family->family_name = g_strdup (family_name);
604       win32family->faces = NULL;
605
606       g_hash_table_insert (win32fontmap->families, win32family->family_name, win32family);
607     }
608
609   return win32family;
610 }
611
612 static PangoFont *
613 pango_win32_font_map_load_font (PangoFontMap               *fontmap,
614                                 PangoContext               *context,
615                                 const PangoFontDescription *description)
616 {
617   PangoWin32FontMap *win32fontmap = (PangoWin32FontMap *)fontmap;
618   PangoWin32Family *win32family;
619   PangoFont *result = NULL;
620   GSList *tmp_list;
621   const char *family;
622
623   g_return_val_if_fail (description != NULL, NULL);
624
625   family = pango_font_description_get_family (description);
626   family = family ? family : "";
627   PING (("name=%s", family));
628
629   win32family = g_hash_table_lookup (win32fontmap->families, family);
630   if (win32family)
631     {
632       PangoWin32Face *best_match = NULL;
633
634       PING (("got win32family"));
635       tmp_list = win32family->faces;
636       while (tmp_list)
637         {
638           PangoWin32Face *face = tmp_list->data;
639
640           if (pango_font_description_better_match (description,
641                                                    best_match ? best_match->description : NULL,
642                                                    face->description))
643             best_match = face;
644
645           tmp_list = tmp_list->next;
646         }
647
648       if (best_match)
649         result = PANGO_WIN32_FONT_MAP_GET_CLASS (win32fontmap)->find_font (win32fontmap, context,
650                                                                            best_match,
651                                                                            description);
652         /* TODO: Handle the case that result == NULL. */
653       else
654         PING (("no best match!"));
655     }
656
657   return result;
658 }
659
660 static PangoWin32Font *
661 pango_win32_font_neww (PangoFontMap   *fontmap,
662                        const LOGFONTW *lfp,
663                        int            size)
664 {
665   PangoWin32Font *result;
666
667   g_return_val_if_fail (fontmap != NULL, NULL);
668   g_return_val_if_fail (lfp != NULL, NULL);
669
670   result = (PangoWin32Font *)g_object_new (PANGO_TYPE_WIN32_FONT, NULL);
671
672   g_assert (result->fontmap == NULL);
673   result->fontmap = fontmap;
674   g_object_add_weak_pointer (G_OBJECT (result->fontmap), (gpointer *) (gpointer) &result->fontmap);
675
676   result->size = size;
677   _pango_win32_make_matching_logfontw (fontmap, lfp, size, &result->logfontw);
678
679   return result;
680 }
681
682 static PangoFont *
683 pango_win32_font_map_real_find_font (PangoWin32FontMap          *win32fontmap,
684                                      PangoContext               *context,
685                                      PangoWin32Face             *face,
686                                      const PangoFontDescription *description)
687 {
688   PangoFontMap *fontmap = PANGO_FONT_MAP (win32fontmap);
689   PangoWin32Font *win32font;
690   GSList *tmp_list = face->cached_fonts;
691   int size = pango_font_description_get_size (description);
692
693   if (pango_font_description_get_size_is_absolute (description))
694     size = (int) 0.5 + (size * win32fontmap->resolution) / PANGO_SCALE;
695
696   PING (("got best match:%S size=%d",face->logfontw.lfFaceName,size));
697
698   while (tmp_list)
699     {
700       win32font = tmp_list->data;
701       if (win32font->size == size)
702         {
703           PING (("size matches"));
704
705           g_object_ref (win32font);
706           if (win32font->in_cache)
707             _pango_win32_fontmap_cache_remove (fontmap, win32font);
708
709           return (PangoFont *)win32font;
710         }
711       tmp_list = tmp_list->next;
712     }
713
714   win32font = pango_win32_font_neww (fontmap, &face->logfontw, size);
715
716   if (!win32font)
717     return NULL;
718
719   win32font->win32face = face;
720   face->cached_fonts = g_slist_prepend (face->cached_fonts, win32font);
721
722   return (PangoFont *)win32font;
723 }
724
725 static gchar *
726 get_family_nameA (const LOGFONTA *lfp)
727 {
728   HFONT hfont;
729   HFONT oldhfont;
730
731   struct name_header header;
732   struct name_record record;
733
734   gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1;
735   gint name_ix;
736   gchar *codeset;
737
738   gchar *string = NULL;
739   gchar *name;
740
741   gint i, l;
742   gsize nbytes;
743
744   /* If lfFaceName is ASCII, assume it is the common (English) name
745    * for the font. Is this valid? Do some TrueType fonts have
746    * different names in French, German, etc, and does the system
747    * return these if the locale is set to use French, German, etc?
748    */
749   l = strlen (lfp->lfFaceName);
750   for (i = 0; i < l; i++)
751     if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~')
752       break;
753
754   if (i == l)
755     return g_strdup (lfp->lfFaceName);
756
757   if ((hfont = CreateFontIndirect (lfp)) == NULL)
758     goto fail0;
759
760   if ((oldhfont = SelectObject (_pango_win32_hdc, hfont)) == NULL)
761     goto fail1;
762
763   if (!_pango_win32_get_name_header (_pango_win32_hdc, &header))
764     goto fail2;
765
766   PING (("%d name records", header.num_records));
767
768   for (i = 0; i < header.num_records; i++)
769     {
770       if (!_pango_win32_get_name_record (_pango_win32_hdc, i, &record))
771         goto fail2;
772
773       if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
774         continue;
775
776       PING (("platform:%d encoding:%d language:%04x name_id:%d",
777              record.platform_id, record.encoding_id, record.language_id, record.name_id));
778
779       if (record.platform_id == APPLE_UNICODE_PLATFORM_ID ||
780           record.platform_id == ISO_PLATFORM_ID)
781         unicode_ix = i;
782       else if (record.platform_id == MACINTOSH_PLATFORM_ID &&
783                record.encoding_id == 0 && /* Roman */
784                record.language_id == 0) /* English */
785         mac_ix = i;
786       else if (record.platform_id == MICROSOFT_PLATFORM_ID)
787         if ((microsoft_ix == -1 ||
788              PRIMARYLANGID (record.language_id) == LANG_ENGLISH) &&
789             (record.encoding_id == SYMBOL_ENCODING_ID ||
790              record.encoding_id == UNICODE_ENCODING_ID ||
791              record.encoding_id == UCS4_ENCODING_ID))
792           microsoft_ix = i;
793     }
794
795   if (microsoft_ix >= 0)
796     name_ix = microsoft_ix;
797   else if (mac_ix >= 0)
798     name_ix = mac_ix;
799   else if (unicode_ix >= 0)
800     name_ix = unicode_ix;
801   else
802     goto fail2;
803
804   if (!_pango_win32_get_name_record (_pango_win32_hdc, name_ix, &record))
805     goto fail2;
806
807   string = g_malloc (record.string_length + 1);
808   if (GetFontData (_pango_win32_hdc, NAME,
809                    header.string_storage_offset + record.string_offset,
810                    string, record.string_length) != record.string_length)
811     goto fail2;
812
813   string[record.string_length] = '\0';
814
815   if (name_ix == microsoft_ix)
816     if (record.encoding_id == SYMBOL_ENCODING_ID ||
817         record.encoding_id == UNICODE_ENCODING_ID ||
818         record.encoding_id == UCS4_ENCODING_ID)
819       codeset = "UTF-16BE";
820     else
821       codeset = "UCS-4BE";
822   else if (name_ix == mac_ix)
823     codeset = "MacRoman";
824   else /* name_ix == unicode_ix */
825     codeset = "UCS-4BE";
826
827   name = g_convert (string, record.string_length, "UTF-8", codeset, NULL, &nbytes, NULL);
828   if (name == NULL)
829     goto fail2;
830   g_free (string);
831
832   PING (("%s", name));
833
834   SelectObject (_pango_win32_hdc, oldhfont);
835   DeleteObject (hfont);
836
837   return name;
838
839  fail2:
840   g_free (string);
841   SelectObject (_pango_win32_hdc, oldhfont);
842
843  fail1:
844   DeleteObject (hfont);
845
846  fail0:
847   return g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
848 }
849
850 /**
851  * pango_win32_font_description_from_logfont:
852  * @lfp: a LOGFONTA
853  *
854  * Creates a #PangoFontDescription that matches the specified LOGFONTA.
855  *
856  * The face name, italicness and weight fields in the LOGFONTA are used
857  * to set up the resulting #PangoFontDescription. If the face name in
858  * the LOGFONTA contains non-ASCII characters the font is temporarily
859  * loaded (using CreateFontIndirect()) and an ASCII (usually English)
860  * name for it is looked up from the font name tables in the font
861  * data. If that doesn't work, the face name is converted from the
862  * system codepage to UTF-8 and that is used.
863  *
864  * Return value: the newly allocated #PangoFontDescription, which
865  *  should be freed using pango_font_description_free()
866  *
867  * Since: 1.12
868  */
869 PangoFontDescription *
870 pango_win32_font_description_from_logfont (const LOGFONT *lfp)
871 {
872   PangoFontDescription *description;
873   gchar *family;
874   PangoStyle style;
875   PangoVariant variant;
876   PangoWeight weight;
877   PangoStretch stretch;
878
879   family = get_family_nameA (lfp);
880
881   if (!lfp->lfItalic)
882     style = PANGO_STYLE_NORMAL;
883   else
884     style = PANGO_STYLE_ITALIC;
885
886   variant = PANGO_VARIANT_NORMAL;
887
888   /* The PangoWeight values PANGO_WEIGHT_* map exactly do Windows FW_*
889    * values.  Is this on purpose? Quantize the weight to exact
890    * PANGO_WEIGHT_* values. Is this a good idea?
891    */
892   if (lfp->lfWeight == FW_DONTCARE)
893     weight = PANGO_WEIGHT_NORMAL;
894   else if (lfp->lfWeight <= (FW_ULTRALIGHT + FW_LIGHT) / 2)
895     weight = PANGO_WEIGHT_ULTRALIGHT;
896   else if (lfp->lfWeight <= (FW_LIGHT + FW_NORMAL) / 2)
897     weight = PANGO_WEIGHT_LIGHT;
898   else if (lfp->lfWeight <= (FW_NORMAL + FW_SEMIBOLD) / 2)
899     weight = PANGO_WEIGHT_NORMAL;
900   else if (lfp->lfWeight <= (FW_SEMIBOLD + FW_BOLD) / 2)
901     weight = PANGO_WEIGHT_SEMIBOLD;
902   else if (lfp->lfWeight <= (FW_BOLD + FW_ULTRABOLD) / 2)
903     weight = PANGO_WEIGHT_BOLD;
904   else if (lfp->lfWeight <= (FW_ULTRABOLD + FW_HEAVY) / 2)
905     weight = PANGO_WEIGHT_ULTRABOLD;
906   else
907     weight = PANGO_WEIGHT_HEAVY;
908
909   /* XXX No idea how to figure out the stretch */
910   stretch = PANGO_STRETCH_NORMAL;
911
912   description = pango_font_description_new ();
913   pango_font_description_set_family (description, family);
914   g_free(family);
915   pango_font_description_set_style (description, style);
916   pango_font_description_set_weight (description, weight);
917   pango_font_description_set_stretch (description, stretch);
918   pango_font_description_set_variant (description, variant);
919
920   return description;
921 }
922
923 static gchar *
924 get_family_nameW (const LOGFONTW *lfp)
925 {
926   HFONT hfont;
927   HFONT oldhfont;
928
929   struct name_header header;
930   struct name_record record;
931
932   gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1;
933   gint name_ix;
934   gchar *codeset;
935
936   gchar *string = NULL;
937   gchar *name;
938
939   gint i, l;
940   gsize nbytes;
941
942   /* If lfFaceName is ASCII, assume it is the common (English) name
943    * for the font. Is this valid? Do some TrueType fonts have
944    * different names in French, German, etc, and does the system
945    * return these if the locale is set to use French, German, etc?
946    */
947   l = wcslen (lfp->lfFaceName);
948   for (i = 0; i < l; i++)
949     if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~')
950       break;
951
952   if (i == l)
953     return g_utf16_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
954
955   if ((hfont = CreateFontIndirectW (lfp)) == NULL)
956     goto fail0;
957
958   if ((oldhfont = SelectObject (_pango_win32_hdc, hfont)) == NULL)
959     goto fail1;
960
961   if (!_pango_win32_get_name_header (_pango_win32_hdc, &header))
962     goto fail2;
963
964   PING (("%d name records", header.num_records));
965
966   for (i = 0; i < header.num_records; i++)
967     {
968       if (!_pango_win32_get_name_record (_pango_win32_hdc, i, &record))
969         goto fail2;
970
971       if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
972         continue;
973
974       PING (("platform:%d encoding:%d language:%04x name_id:%d",
975              record.platform_id, record.encoding_id, record.language_id, record.name_id));
976
977       if (record.platform_id == APPLE_UNICODE_PLATFORM_ID ||
978           record.platform_id == ISO_PLATFORM_ID)
979         unicode_ix = i;
980       else if (record.platform_id == MACINTOSH_PLATFORM_ID &&
981                record.encoding_id == 0 && /* Roman */
982                record.language_id == 0) /* English */
983         mac_ix = i;
984       else if (record.platform_id == MICROSOFT_PLATFORM_ID)
985         if ((microsoft_ix == -1 ||
986              PRIMARYLANGID (record.language_id) == LANG_ENGLISH) &&
987             (record.encoding_id == SYMBOL_ENCODING_ID ||
988              record.encoding_id == UNICODE_ENCODING_ID ||
989              record.encoding_id == UCS4_ENCODING_ID))
990           microsoft_ix = i;
991     }
992
993   if (microsoft_ix >= 0)
994     name_ix = microsoft_ix;
995   else if (mac_ix >= 0)
996     name_ix = mac_ix;
997   else if (unicode_ix >= 0)
998     name_ix = unicode_ix;
999   else
1000     goto fail2;
1001
1002   if (!_pango_win32_get_name_record (_pango_win32_hdc, name_ix, &record))
1003     goto fail2;
1004
1005   string = g_malloc (record.string_length + 1);
1006   if (GetFontData (_pango_win32_hdc, NAME,
1007                    header.string_storage_offset + record.string_offset,
1008                    string, record.string_length) != record.string_length)
1009     goto fail2;
1010
1011   string[record.string_length] = '\0';
1012
1013   if (name_ix == microsoft_ix)
1014     if (record.encoding_id == SYMBOL_ENCODING_ID ||
1015         record.encoding_id == UNICODE_ENCODING_ID ||
1016         record.encoding_id == UCS4_ENCODING_ID)
1017       codeset = "UTF-16BE";
1018     else
1019       codeset = "UCS-4BE";
1020   else if (name_ix == mac_ix)
1021     codeset = "MacRoman";
1022   else /* name_ix == unicode_ix */
1023     codeset = "UCS-4BE";
1024
1025   name = g_convert (string, record.string_length, "UTF-8", codeset, NULL, &nbytes, NULL);
1026   if (name == NULL)
1027     goto fail2;
1028   g_free (string);
1029
1030   PING (("%s", name));
1031
1032   SelectObject (_pango_win32_hdc, oldhfont);
1033   DeleteObject (hfont);
1034
1035   return name;
1036
1037  fail2:
1038   g_free (string);
1039   SelectObject (_pango_win32_hdc, oldhfont);
1040
1041  fail1:
1042   DeleteObject (hfont);
1043
1044  fail0:
1045   return g_utf16_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
1046 }
1047
1048 /**
1049  * pango_win32_font_description_from_logfontw:
1050  * @lfp: a LOGFONTW
1051  *
1052  * Creates a #PangoFontDescription that matches the specified LOGFONTW.
1053  *
1054  * The face name, italicness and weight fields in the LOGFONTW are used
1055  * to set up the resulting #PangoFontDescription. If the face name in
1056  * the LOGFONTW contains non-ASCII characters the font is temporarily
1057  * loaded (using CreateFontIndirect()) and an ASCII (usually English)
1058  * name for it is looked up from the font name tables in the font
1059  * data. If that doesn't work, the face name is converted from UTF-16
1060  * to UTF-8 and that is used.
1061  *
1062  * Return value: the newly allocated #PangoFontDescription, which
1063  *  should be freed using pango_font_description_free()
1064  *
1065  * Since: 1.16
1066  */
1067 PangoFontDescription *
1068 pango_win32_font_description_from_logfontw (const LOGFONTW *lfp)
1069 {
1070   PangoFontDescription *description;
1071   gchar *family;
1072   PangoStyle style;
1073   PangoVariant variant;
1074   PangoWeight weight;
1075   PangoStretch stretch;
1076
1077   family = get_family_nameW (lfp);
1078
1079   if ((lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN && lfp->lfItalic)
1080     style = PANGO_STYLE_ITALIC;
1081   else if (lfp->lfItalic)
1082     style = PANGO_STYLE_OBLIQUE;
1083   else
1084     style = PANGO_STYLE_NORMAL;
1085
1086   variant = PANGO_VARIANT_NORMAL;
1087
1088   /* The PangoWeight values PANGO_WEIGHT_* map exactly do Windows FW_*
1089    * values.  Is this on purpose? Quantize the weight to exact
1090    * PANGO_WEIGHT_* values. Is this a good idea?
1091    */
1092   if (lfp->lfWeight == FW_DONTCARE)
1093     weight = PANGO_WEIGHT_NORMAL;
1094   else if (lfp->lfWeight <= (FW_ULTRALIGHT + FW_LIGHT) / 2)
1095     weight = PANGO_WEIGHT_ULTRALIGHT;
1096   else if (lfp->lfWeight <= (FW_LIGHT + FW_NORMAL) / 2)
1097     weight = PANGO_WEIGHT_LIGHT;
1098   else if (lfp->lfWeight <= (FW_NORMAL + FW_SEMIBOLD) / 2)
1099     weight = PANGO_WEIGHT_NORMAL;
1100   else if (lfp->lfWeight <= (FW_SEMIBOLD + FW_BOLD) / 2)
1101     weight = PANGO_WEIGHT_SEMIBOLD;
1102   else if (lfp->lfWeight <= (FW_BOLD + FW_ULTRABOLD) / 2)
1103     weight = PANGO_WEIGHT_BOLD;
1104   else if (lfp->lfWeight <= (FW_ULTRABOLD + FW_HEAVY) / 2)
1105     weight = PANGO_WEIGHT_ULTRABOLD;
1106   else
1107     weight = PANGO_WEIGHT_HEAVY;
1108
1109   /* XXX No idea how to figure out the stretch */
1110   stretch = PANGO_STRETCH_NORMAL;
1111
1112   description = pango_font_description_new ();
1113   pango_font_description_set_family (description, family);
1114   g_free(family);
1115   pango_font_description_set_style (description, style);
1116   pango_font_description_set_weight (description, weight);
1117   pango_font_description_set_stretch (description, stretch);
1118   pango_font_description_set_variant (description, variant);
1119
1120   return description;
1121 }
1122
1123 static char *
1124 charset_name (int charset)
1125 {
1126   static char num[10];
1127
1128   switch (charset)
1129     {
1130 #define CASE(x) case x##_CHARSET: return #x
1131       CASE (ANSI);
1132       CASE (DEFAULT);
1133       CASE (SYMBOL);
1134       CASE (SHIFTJIS);
1135       CASE (HANGUL);
1136       CASE (GB2312);
1137       CASE (CHINESEBIG5);
1138       CASE (GREEK);
1139       CASE (TURKISH);
1140       CASE (HEBREW);
1141       CASE (ARABIC);
1142       CASE (BALTIC);
1143       CASE (RUSSIAN);
1144       CASE (THAI);
1145       CASE (EASTEUROPE);
1146       CASE (OEM);
1147       CASE (JOHAB);
1148       CASE (VIETNAMESE);
1149       CASE (MAC);
1150 #undef CASE
1151     default:
1152       sprintf (num, "%d", charset);
1153       return num;
1154     }
1155 }
1156
1157 static char *
1158 ff_name (int ff)
1159 {
1160   static char num[10];
1161
1162   switch (ff)
1163     {
1164 #define CASE(x) case FF_##x: return #x
1165       CASE (DECORATIVE);
1166       CASE (DONTCARE);
1167       CASE (MODERN);
1168       CASE (ROMAN);
1169       CASE (SCRIPT);
1170       CASE (SWISS);
1171 #undef CASE
1172     default:
1173       sprintf (num, "%d", ff);
1174       return num;
1175     }
1176 }
1177
1178 static void
1179 pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
1180                          LOGFONTW          *lfp,
1181                          gboolean           is_synthetic)
1182 {
1183   LOGFONTW *lfp2 = NULL;
1184   PangoFontDescription *description;
1185   PangoWin32Family *win32family;
1186   PangoWin32Face *win32face;
1187   gint i;
1188
1189   PING (("face=%S,charset=%s,it=%s,wt=%ld,ht=%ld,ff=%s%s",
1190          lfp->lfFaceName,
1191          charset_name (lfp->lfCharSet),
1192          lfp->lfItalic ? "yes" : "no",
1193          lfp->lfWeight,
1194          lfp->lfHeight,
1195          ff_name (lfp->lfPitchAndFamily & 0xF0),
1196          is_synthetic ? " synthetic" : ""));
1197
1198   /* Ignore Symbol fonts (which don't have any Unicode mapping
1199    * table). We could also be fancy and use the PostScript glyph name
1200    * table for such if present, and build a Unicode map by mapping
1201    * each PostScript glyph name to Unicode character. Oh well.
1202    */
1203   if (lfp->lfCharSet == SYMBOL_CHARSET)
1204     return;
1205
1206   if (g_hash_table_lookup (win32fontmap->fonts, lfp))
1207     {
1208       PING (("already have it"));
1209       return;
1210     }
1211
1212   PING (("not found"));
1213   lfp2 = g_new (LOGFONTW, 1);
1214   *lfp2 = *lfp;
1215   g_hash_table_insert (win32fontmap->fonts, lfp2, lfp2);
1216
1217   description = pango_win32_font_description_from_logfontw (lfp2);
1218
1219   /* In some cases, extracting a name for a font can fail; such fonts
1220    * aren't usable for us
1221    */
1222   if (!pango_font_description_get_family (description))
1223     {
1224       pango_font_description_free (description);
1225       return;
1226     }
1227
1228   win32face = g_object_new (PANGO_WIN32_TYPE_FACE, NULL);
1229
1230   PING (("win32face created: %p for %S", win32face, lfp->lfFaceName));
1231
1232   win32face->logfontw = *lfp;
1233   win32face->description = description;
1234
1235   for (i = 0; i < PANGO_WIN32_N_COVERAGES; i++)
1236      win32face->coverages[i] = NULL;
1237
1238   win32face->is_synthetic = is_synthetic;
1239
1240   win32face->has_cmap = TRUE;
1241   win32face->cmap_format = 0;
1242   win32face->cmap = NULL;
1243
1244   win32face->cached_fonts = NULL;
1245
1246   win32family =
1247     pango_win32_get_font_family (win32fontmap,
1248                                  pango_font_description_get_family (win32face->description));
1249   if ((lfp->lfPitchAndFamily & 0xF0) == FF_MODERN)
1250     win32family->is_monospace = TRUE;
1251     
1252   win32family->faces = g_slist_append (win32family->faces, win32face);
1253
1254   PING (("name=%s, length(faces)=%d",
1255          win32family->family_name, g_slist_length (win32family->faces)));
1256 }
1257
1258 /* Given a LOGFONTW and size, make a matching LOGFONTW corresponding to
1259  * an installed font.
1260  */
1261 void
1262 _pango_win32_make_matching_logfontw (PangoFontMap   *fontmap,
1263                                      const LOGFONTW *lfp,
1264                                      int             size,
1265                                      LOGFONTW       *out)
1266 {
1267   PangoWin32FontMap *win32fontmap;
1268   LOGFONTW *match;
1269
1270   PING (("lfp.face=%S,wt=%ld,ht=%ld,size:%d",
1271          lfp->lfFaceName, lfp->lfWeight, lfp->lfHeight, size));
1272   win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
1273
1274   match = g_hash_table_lookup (win32fontmap->fonts, lfp);
1275
1276   if (!match)
1277     {
1278       PING (("not found"));
1279       return;
1280     }
1281
1282   /* OK, we have a match; let's modify it to fit this size */
1283
1284   *out = *match;
1285   out->lfHeight = -(int)((double)size / win32fontmap->resolution + 0.5);
1286   out->lfWidth = 0;
1287 }
1288
1289 static PangoFontDescription *
1290 pango_win32_face_describe (PangoFontFace *face)
1291 {
1292   PangoWin32Face *win32face = PANGO_WIN32_FACE (face);
1293
1294   return pango_font_description_copy (win32face->description);
1295 }
1296
1297 static const char *
1298 pango_win32_face_get_face_name (PangoFontFace *face)
1299 {
1300   PangoWin32Face *win32face = PANGO_WIN32_FACE (face);
1301
1302   if (!win32face->face_name)
1303     {
1304       PangoFontDescription *desc = pango_font_face_describe (face);
1305
1306       pango_font_description_unset_fields (desc,
1307                                            PANGO_FONT_MASK_FAMILY | PANGO_FONT_MASK_SIZE);
1308
1309       win32face->face_name = pango_font_description_to_string (desc);
1310       pango_font_description_free (desc);
1311     }
1312
1313   return win32face->face_name;
1314 }
1315
1316 static gboolean
1317 pango_win32_face_is_synthesized (PangoFontFace *face)
1318 {
1319   PangoWin32Face *win32face = PANGO_WIN32_FACE (face);
1320
1321   return win32face->is_synthetic;
1322 }
1323
1324 static void
1325 pango_win32_face_class_init (PangoFontFaceClass *class)
1326 {
1327   class->describe = pango_win32_face_describe;
1328   class->get_face_name = pango_win32_face_get_face_name;
1329   class->list_sizes = pango_win32_face_list_sizes;
1330   class->is_synthesized = pango_win32_face_is_synthesized;
1331 }
1332
1333 static void
1334 pango_win32_face_list_sizes (PangoFontFace  *face,
1335                              int           **sizes,
1336                              int            *n_sizes)
1337 {
1338   /*
1339    * for scalable fonts it's simple, and currently we only have such
1340    * see : pango_win32_enum_proc(), TRUETYPE_FONTTYPE
1341    */
1342   *sizes = NULL;
1343   *n_sizes = 0;
1344 }
1345
1346 static GType
1347 pango_win32_face_get_type (void)
1348 {
1349   static GType object_type = 0;
1350
1351   if (G_UNLIKELY (!object_type))
1352     {
1353       static const GTypeInfo object_info =
1354       {
1355         sizeof (PangoFontFaceClass),
1356         (GBaseInitFunc) NULL,
1357         (GBaseFinalizeFunc) NULL,
1358         (GClassInitFunc) pango_win32_face_class_init,
1359         NULL,           /* class_finalize */
1360         NULL,           /* class_data */
1361         sizeof (PangoWin32Face),
1362         0,              /* n_preallocs */
1363         (GInstanceInitFunc) NULL,
1364       };
1365       
1366       object_type = g_type_register_static (PANGO_TYPE_FONT_FACE,
1367                                             I_("PangoWin32Face"),
1368                                             &object_info, 0);
1369     }
1370   
1371   return object_type;
1372 }
1373
1374 /**
1375  * pango_win32_font_map_get_font_cache:
1376  * @font_map: a #PangoWin32FontMap.
1377  *
1378  * Obtains the font cache associated with the given font map.
1379  *
1380  * Return value: the #PangoWin32FontCache of @font_map.
1381  **/
1382 PangoWin32FontCache *
1383 pango_win32_font_map_get_font_cache (PangoFontMap *font_map)
1384 {
1385   g_return_val_if_fail (font_map != NULL, NULL);
1386   g_return_val_if_fail (PANGO_WIN32_IS_FONT_MAP (font_map), NULL);
1387
1388   return PANGO_WIN32_FONT_MAP (font_map)->font_cache;
1389 }
1390
1391 void
1392 _pango_win32_fontmap_cache_remove (PangoFontMap   *fontmap,
1393                                    PangoWin32Font *win32font)
1394 {
1395   PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
1396   GList *link = g_queue_find (win32fontmap->freed_fonts, win32font);
1397
1398   if (link)
1399     g_queue_delete_link (win32fontmap->freed_fonts, link);
1400   win32font->in_cache = FALSE;
1401
1402   g_object_unref (win32font);
1403 }
1404
1405 static void
1406 pango_win32_fontmap_cache_clear (PangoWin32FontMap *win32fontmap)
1407 {
1408   g_list_foreach (win32fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
1409   g_queue_free (win32fontmap->freed_fonts);
1410   win32fontmap->freed_fonts = g_queue_new ();
1411 }