2 * pangowin32-fontmap.c: Win32 font handling
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.
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.
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.
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.
33 #include "pango-fontmap.h"
34 #include "pango-impl-utils.h"
35 #include "pangowin32-private.h"
38 typedef struct _PangoWin32Family PangoWin32Family;
40 struct _PangoWin32Family
42 PangoFontFamily parent_instance;
47 gboolean is_monospace;
50 #if !defined(NTM_PS_OPENTYPE)
51 # define NTM_PS_OPENTYPE 0x20000
54 #if !defined(NTM_TYPE1)
55 # define NTM_TYPE1 0x100000
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))
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))
66 static GType pango_win32_face_get_type (void);
68 static GType pango_win32_family_get_type (void);
70 static void pango_win32_face_list_sizes (PangoFontFace *face,
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,
82 static PangoFont *pango_win32_font_map_real_find_font (PangoWin32FontMap *win32fontmap,
83 PangoContext *context,
85 const PangoFontDescription *description);
87 static void pango_win32_fontmap_cache_clear (PangoWin32FontMap *win32fontmap);
89 static void pango_win32_insert_font (PangoWin32FontMap *fontmap,
91 gboolean is_synthetic);
93 static PangoWin32Family *pango_win32_get_font_family (PangoWin32FontMap *win32fontmap,
94 const char *family_name);
96 static const char *pango_win32_face_get_face_name (PangoFontFace *face);
98 static PangoWin32FontMap *default_fontmap = NULL;
100 G_DEFINE_TYPE (PangoWin32FontMap, _pango_win32_font_map, PANGO_TYPE_FONT_MAP)
103 (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
106 case_insensitive_str_hash (const char *key)
109 guint h = TOLOWER (*p);
113 for (p += 1; *p != '\0'; p++)
114 h = (h << 5) - h + TOLOWER (*p);
121 case_insensitive_str_equal (const char *key1,
124 while (*key1 && *key2 && TOLOWER (*key1) == TOLOWER (*key2))
126 return (!*key1 && !*key2);
130 case_insensitive_wcs_hash (const wchar_t *key)
132 const wchar_t *p = key;
133 guint h = TOLOWER (*p);
137 for (p += 1; *p != '\0'; p++)
138 h = (h << 5) - h + TOLOWER (*p);
145 case_insensitive_wcs_equal (const wchar_t *key1,
148 while (*key1 && *key2 && TOLOWER (*key1) == TOLOWER (*key2))
150 return (!*key1 && !*key2);
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.
158 logfontw_nosize_hash (const LOGFONTW *lfp)
160 return case_insensitive_wcs_hash (lfp->lfFaceName) + (lfp->lfItalic != 0) + lfp->lfWeight;
163 /* Ditto comparison function */
165 logfontw_nosize_equal (const LOGFONTW *lfp1,
166 const LOGFONTW *lfp2)
168 return (case_insensitive_wcs_equal (lfp1->lfFaceName, lfp2->lfFaceName)
169 && (lfp1->lfItalic != 0) == (lfp2->lfItalic != 0)
170 && lfp1->lfWeight == lfp2->lfWeight);
174 pango_win32_inner_enum_proc (LOGFONTW *lfp,
175 TEXTMETRICW *metrics,
179 PangoWin32FontMap *win32fontmap = (PangoWin32FontMap *)lParam;
181 /* Windows generates synthetic vertical writing versions of East
182 * Asian fonts with @ prepended to their name, ignore them.
184 if (lfp->lfFaceName[0] != '@')
185 pango_win32_insert_font (win32fontmap, lfp, FALSE);
191 pango_win32_enum_proc (LOGFONTW *lfp,
192 NEWTEXTMETRICW *metrics,
198 PING (("%S: %lu %lx", lfp->lfFaceName, fontType, metrics->ntmFlags));
200 if (fontType == TRUETYPE_FONTTYPE ||
201 (_pango_win32_os_version_info.dwMajorVersion >= 5 &&
202 ((metrics->ntmFlags & NTM_PS_OPENTYPE) || (metrics->ntmFlags & NTM_TYPE1))))
206 EnumFontFamiliesExW (_pango_win32_hdc, &lf,
207 (FONTENUMPROCW) pango_win32_inner_enum_proc,
215 synthesize_foreach (gpointer key,
219 PangoWin32Family *win32family = value;
220 PangoWin32FontMap *win32fontmap = user_data;
222 enum { NORMAL, BOLDER, SLANTED };
223 PangoWin32Face *variant[4] = { NULL, NULL, NULL, NULL };
229 p = win32family->faces;
232 PangoWin32Face *win32face = p->data;
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))
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;
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;
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;
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;
259 if (variant[NORMAL] != NULL && variant[BOLDER] == NULL)
261 lf = variant[NORMAL]->logfontw;
262 lf.lfWeight = FW_BOLD;
264 pango_win32_insert_font (win32fontmap, &lf, TRUE);
267 if (variant[NORMAL] != NULL && variant[SLANTED] == NULL)
269 lf = variant[NORMAL]->logfontw;
272 pango_win32_insert_font (win32fontmap, &lf, TRUE);
275 if (variant[NORMAL] != NULL &&
276 variant[BOLDER+SLANTED] == NULL)
278 lf = variant[NORMAL]->logfontw;
279 lf.lfWeight = FW_BOLD;
282 pango_win32_insert_font (win32fontmap, &lf, TRUE);
284 else if (variant[BOLDER] != NULL &&
285 variant[BOLDER+SLANTED] == NULL)
287 lf = variant[BOLDER]->logfontw;
290 pango_win32_insert_font (win32fontmap, &lf, TRUE);
292 else if (variant[SLANTED] != NULL &&
293 variant[BOLDER+SLANTED] == NULL)
295 lf = variant[SLANTED]->logfontw;
296 lf.lfWeight = FW_BOLD;
298 pango_win32_insert_font (win32fontmap, &lf, TRUE);
303 create_standard_family (PangoWin32FontMap *win32fontmap,
304 const char *standard_family_name)
310 pango_lookup_aliases (standard_family_name, &aliases, &n_aliases);
311 for (i = 0; i < n_aliases; i++)
313 PangoWin32Family *existing_family = g_hash_table_lookup (win32fontmap->families, aliases[i]);
317 PangoWin32Family *new_family = pango_win32_get_font_family (win32fontmap, standard_family_name);
318 GSList *p = existing_family->faces;
320 new_family->is_monospace = existing_family->is_monospace;
324 const PangoWin32Face *old_face = p->data;
325 PangoWin32Face *new_face = g_object_new (PANGO_WIN32_TYPE_FACE, NULL);
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);
332 for (j = 0; j < PANGO_WIN32_N_COVERAGES; j++)
334 if (old_face->coverages[j] != NULL)
335 new_face->coverages[j] = pango_coverage_ref (old_face->coverages[j]);
337 new_face->coverages[j] = NULL;
340 new_face->is_synthetic = TRUE;
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;
346 new_face->cached_fonts = NULL;
348 new_family->faces = g_slist_append (new_family->faces, new_face);
355 /* XXX What to do if none of the members of aliases for standard_family_name
356 * exists on this machine?
361 _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap)
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);
370 win32fontmap->font_cache = pango_win32_font_cache_new ();
371 win32fontmap->freed_fonts = g_queue_new ();
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);
379 g_hash_table_foreach (win32fontmap->families, synthesize_foreach, win32fontmap);
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");
386 win32fontmap->resolution = (PANGO_SCALE / (double) GetDeviceCaps (_pango_win32_hdc, LOGPIXELSY)) * 72.0;
390 _pango_win32_font_map_class_init (PangoWin32FontMapClass *class)
392 GObjectClass *object_class = G_OBJECT_CLASS (class);
393 PangoFontMapClass *fontmap_class = PANGO_FONT_MAP_CLASS (class);
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;
402 pango_win32_get_dc ();
404 for (i = 0; _pango_included_win32_modules[i].list; i++)
405 pango_module_register (&_pango_included_win32_modules[i]);
409 * pango_win32_font_map_for_display:
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().
415 * Return value: a #PangoFontMap.
418 pango_win32_font_map_for_display (void)
420 /* Make sure that the type system is initialized */
423 if (default_fontmap != NULL)
424 return PANGO_FONT_MAP (default_fontmap);
426 default_fontmap = g_object_new (PANGO_TYPE_WIN32_FONT_MAP, NULL);
428 return PANGO_FONT_MAP (default_fontmap);
432 * pango_win32_shutdown_display:
434 * Free cached resources.
437 pango_win32_shutdown_display (void)
441 pango_win32_fontmap_cache_clear (default_fontmap);
442 g_object_unref (default_fontmap);
444 default_fontmap = NULL;
449 pango_win32_font_map_finalize (GObject *object)
451 PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (object);
453 g_list_foreach (win32fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
454 g_queue_free (win32fontmap->freed_fonts);
456 pango_win32_font_cache_free (win32fontmap->font_cache);
458 G_OBJECT_CLASS (_pango_win32_font_map_parent_class)->finalize (object);
465 pango_win32_family_list_faces (PangoFontFamily *family,
466 PangoFontFace ***faces,
469 PangoWin32Family *win32family = PANGO_WIN32_FAMILY (family);
473 p = win32family->faces;
485 *faces = g_new (PangoFontFace *, n);
487 p = win32family->faces;
491 (*faces)[i++] = p->data;
500 pango_win32_family_get_name (PangoFontFamily *family)
502 PangoWin32Family *win32family = PANGO_WIN32_FAMILY (family);
504 return win32family->family_name;
508 pango_win32_family_is_monospace (PangoFontFamily *family)
510 PangoWin32Family *win32family = PANGO_WIN32_FAMILY (family);
512 return win32family->is_monospace;
516 pango_win32_family_class_init (PangoFontFamilyClass *class)
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;
524 pango_win32_family_get_type (void)
526 static GType object_type = 0;
528 if (G_UNLIKELY (!object_type))
530 const GTypeInfo object_info =
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),
540 (GInstanceInitFunc) NULL,
543 object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY,
544 I_("PangoWin32Family"),
552 list_families_foreach (gpointer key,
556 GSList **list = user_data;
558 *list = g_slist_prepend (*list, value);
562 pango_win32_font_map_list_families (PangoFontMap *fontmap,
563 PangoFontFamily ***families,
566 GSList *family_list = NULL;
568 PangoWin32FontMap *win32fontmap = (PangoWin32FontMap *)fontmap;
573 g_hash_table_foreach (win32fontmap->families, list_families_foreach, &family_list);
575 *n_families = g_slist_length (family_list);
581 *families = g_new (PangoFontFamily *, *n_families);
583 tmp_list = family_list;
586 (*families)[i] = tmp_list->data;
588 tmp_list = tmp_list->next;
592 g_slist_free (family_list);
595 static PangoWin32Family *
596 pango_win32_get_font_family (PangoWin32FontMap *win32fontmap,
597 const char *family_name)
599 PangoWin32Family *win32family = g_hash_table_lookup (win32fontmap->families, family_name);
602 win32family = g_object_new (PANGO_WIN32_TYPE_FAMILY, NULL);
603 win32family->family_name = g_strdup (family_name);
604 win32family->faces = NULL;
606 g_hash_table_insert (win32fontmap->families, win32family->family_name, win32family);
613 pango_win32_font_map_load_font (PangoFontMap *fontmap,
614 PangoContext *context,
615 const PangoFontDescription *description)
617 PangoWin32FontMap *win32fontmap = (PangoWin32FontMap *)fontmap;
618 PangoWin32Family *win32family;
619 PangoFont *result = NULL;
623 g_return_val_if_fail (description != NULL, NULL);
625 family = pango_font_description_get_family (description);
626 family = family ? family : "";
627 PING (("name=%s", family));
629 win32family = g_hash_table_lookup (win32fontmap->families, family);
632 PangoWin32Face *best_match = NULL;
634 PING (("got win32family"));
635 tmp_list = win32family->faces;
638 PangoWin32Face *face = tmp_list->data;
640 if (pango_font_description_better_match (description,
641 best_match ? best_match->description : NULL,
645 tmp_list = tmp_list->next;
649 result = PANGO_WIN32_FONT_MAP_GET_CLASS (win32fontmap)->find_font (win32fontmap, context,
652 /* TODO: Handle the case that result == NULL. */
654 PING (("no best match!"));
660 static PangoWin32Font *
661 pango_win32_font_neww (PangoFontMap *fontmap,
665 PangoWin32Font *result;
667 g_return_val_if_fail (fontmap != NULL, NULL);
668 g_return_val_if_fail (lfp != NULL, NULL);
670 result = (PangoWin32Font *)g_object_new (PANGO_TYPE_WIN32_FONT, NULL);
672 g_assert (result->fontmap == NULL);
673 result->fontmap = fontmap;
674 g_object_add_weak_pointer (G_OBJECT (result->fontmap), (gpointer *) (gpointer) &result->fontmap);
677 _pango_win32_make_matching_logfontw (fontmap, lfp, size, &result->logfontw);
683 pango_win32_font_map_real_find_font (PangoWin32FontMap *win32fontmap,
684 PangoContext *context,
685 PangoWin32Face *face,
686 const PangoFontDescription *description)
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);
693 if (pango_font_description_get_size_is_absolute (description))
694 size = (int) 0.5 + (size * win32fontmap->resolution) / PANGO_SCALE;
696 PING (("got best match:%S size=%d",face->logfontw.lfFaceName,size));
700 win32font = tmp_list->data;
701 if (win32font->size == size)
703 PING (("size matches"));
705 g_object_ref (win32font);
706 if (win32font->in_cache)
707 _pango_win32_fontmap_cache_remove (fontmap, win32font);
709 return (PangoFont *)win32font;
711 tmp_list = tmp_list->next;
714 win32font = pango_win32_font_neww (fontmap, &face->logfontw, size);
719 win32font->win32face = face;
720 face->cached_fonts = g_slist_prepend (face->cached_fonts, win32font);
722 return (PangoFont *)win32font;
726 get_family_nameA (const LOGFONTA *lfp)
731 struct name_header header;
732 struct name_record record;
734 gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1;
738 gchar *string = NULL;
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?
749 l = strlen (lfp->lfFaceName);
750 for (i = 0; i < l; i++)
751 if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~')
755 return g_strdup (lfp->lfFaceName);
757 if ((hfont = CreateFontIndirect (lfp)) == NULL)
760 if ((oldhfont = SelectObject (_pango_win32_hdc, hfont)) == NULL)
763 if (!_pango_win32_get_name_header (_pango_win32_hdc, &header))
766 PING (("%d name records", header.num_records));
768 for (i = 0; i < header.num_records; i++)
770 if (!_pango_win32_get_name_record (_pango_win32_hdc, i, &record))
773 if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
776 PING (("platform:%d encoding:%d language:%04x name_id:%d",
777 record.platform_id, record.encoding_id, record.language_id, record.name_id));
779 if (record.platform_id == APPLE_UNICODE_PLATFORM_ID ||
780 record.platform_id == ISO_PLATFORM_ID)
782 else if (record.platform_id == MACINTOSH_PLATFORM_ID &&
783 record.encoding_id == 0 && /* Roman */
784 record.language_id == 0) /* English */
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))
795 if (microsoft_ix >= 0)
796 name_ix = microsoft_ix;
797 else if (mac_ix >= 0)
799 else if (unicode_ix >= 0)
800 name_ix = unicode_ix;
804 if (!_pango_win32_get_name_record (_pango_win32_hdc, name_ix, &record))
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)
813 string[record.string_length] = '\0';
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";
822 else if (name_ix == mac_ix)
823 codeset = "MacRoman";
824 else /* name_ix == unicode_ix */
827 name = g_convert (string, record.string_length, "UTF-8", codeset, NULL, &nbytes, NULL);
834 SelectObject (_pango_win32_hdc, oldhfont);
835 DeleteObject (hfont);
841 SelectObject (_pango_win32_hdc, oldhfont);
844 DeleteObject (hfont);
847 return g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
851 * pango_win32_font_description_from_logfont:
854 * Creates a #PangoFontDescription that matches the specified LOGFONTA.
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.
864 * Return value: the newly allocated #PangoFontDescription, which
865 * should be freed using pango_font_description_free()
869 PangoFontDescription *
870 pango_win32_font_description_from_logfont (const LOGFONT *lfp)
872 PangoFontDescription *description;
875 PangoVariant variant;
877 PangoStretch stretch;
879 family = get_family_nameA (lfp);
882 style = PANGO_STYLE_NORMAL;
884 style = PANGO_STYLE_ITALIC;
886 variant = PANGO_VARIANT_NORMAL;
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?
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;
907 weight = PANGO_WEIGHT_HEAVY;
909 /* XXX No idea how to figure out the stretch */
910 stretch = PANGO_STRETCH_NORMAL;
912 description = pango_font_description_new ();
913 pango_font_description_set_family (description, 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);
924 get_family_nameW (const LOGFONTW *lfp)
929 struct name_header header;
930 struct name_record record;
932 gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1;
936 gchar *string = NULL;
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?
947 l = wcslen (lfp->lfFaceName);
948 for (i = 0; i < l; i++)
949 if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~')
953 return g_utf16_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
955 if ((hfont = CreateFontIndirectW (lfp)) == NULL)
958 if ((oldhfont = SelectObject (_pango_win32_hdc, hfont)) == NULL)
961 if (!_pango_win32_get_name_header (_pango_win32_hdc, &header))
964 PING (("%d name records", header.num_records));
966 for (i = 0; i < header.num_records; i++)
968 if (!_pango_win32_get_name_record (_pango_win32_hdc, i, &record))
971 if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
974 PING (("platform:%d encoding:%d language:%04x name_id:%d",
975 record.platform_id, record.encoding_id, record.language_id, record.name_id));
977 if (record.platform_id == APPLE_UNICODE_PLATFORM_ID ||
978 record.platform_id == ISO_PLATFORM_ID)
980 else if (record.platform_id == MACINTOSH_PLATFORM_ID &&
981 record.encoding_id == 0 && /* Roman */
982 record.language_id == 0) /* English */
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))
993 if (microsoft_ix >= 0)
994 name_ix = microsoft_ix;
995 else if (mac_ix >= 0)
997 else if (unicode_ix >= 0)
998 name_ix = unicode_ix;
1002 if (!_pango_win32_get_name_record (_pango_win32_hdc, name_ix, &record))
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)
1011 string[record.string_length] = '\0';
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";
1019 codeset = "UCS-4BE";
1020 else if (name_ix == mac_ix)
1021 codeset = "MacRoman";
1022 else /* name_ix == unicode_ix */
1023 codeset = "UCS-4BE";
1025 name = g_convert (string, record.string_length, "UTF-8", codeset, NULL, &nbytes, NULL);
1030 PING (("%s", name));
1032 SelectObject (_pango_win32_hdc, oldhfont);
1033 DeleteObject (hfont);
1039 SelectObject (_pango_win32_hdc, oldhfont);
1042 DeleteObject (hfont);
1045 return g_utf16_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
1049 * pango_win32_font_description_from_logfontw:
1052 * Creates a #PangoFontDescription that matches the specified LOGFONTW.
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.
1062 * Return value: the newly allocated #PangoFontDescription, which
1063 * should be freed using pango_font_description_free()
1067 PangoFontDescription *
1068 pango_win32_font_description_from_logfontw (const LOGFONTW *lfp)
1070 PangoFontDescription *description;
1073 PangoVariant variant;
1075 PangoStretch stretch;
1077 family = get_family_nameW (lfp);
1079 if ((lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN && lfp->lfItalic)
1080 style = PANGO_STYLE_ITALIC;
1081 else if (lfp->lfItalic)
1082 style = PANGO_STYLE_OBLIQUE;
1084 style = PANGO_STYLE_NORMAL;
1086 variant = PANGO_VARIANT_NORMAL;
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?
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;
1107 weight = PANGO_WEIGHT_HEAVY;
1109 /* XXX No idea how to figure out the stretch */
1110 stretch = PANGO_STRETCH_NORMAL;
1112 description = pango_font_description_new ();
1113 pango_font_description_set_family (description, 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);
1124 charset_name (int charset)
1126 static char num[10];
1130 #define CASE(x) case x##_CHARSET: return #x
1152 sprintf (num, "%d", charset);
1160 static char num[10];
1164 #define CASE(x) case FF_##x: return #x
1173 sprintf (num, "%d", ff);
1179 pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
1181 gboolean is_synthetic)
1183 LOGFONTW *lfp2 = NULL;
1184 PangoFontDescription *description;
1185 PangoWin32Family *win32family;
1186 PangoWin32Face *win32face;
1189 PING (("face=%S,charset=%s,it=%s,wt=%ld,ht=%ld,ff=%s%s",
1191 charset_name (lfp->lfCharSet),
1192 lfp->lfItalic ? "yes" : "no",
1195 ff_name (lfp->lfPitchAndFamily & 0xF0),
1196 is_synthetic ? " synthetic" : ""));
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.
1203 if (lfp->lfCharSet == SYMBOL_CHARSET)
1206 if (g_hash_table_lookup (win32fontmap->fonts, lfp))
1208 PING (("already have it"));
1212 PING (("not found"));
1213 lfp2 = g_new (LOGFONTW, 1);
1215 g_hash_table_insert (win32fontmap->fonts, lfp2, lfp2);
1217 description = pango_win32_font_description_from_logfontw (lfp2);
1219 /* In some cases, extracting a name for a font can fail; such fonts
1220 * aren't usable for us
1222 if (!pango_font_description_get_family (description))
1224 pango_font_description_free (description);
1228 win32face = g_object_new (PANGO_WIN32_TYPE_FACE, NULL);
1230 PING (("win32face created: %p for %S", win32face, lfp->lfFaceName));
1232 win32face->logfontw = *lfp;
1233 win32face->description = description;
1235 for (i = 0; i < PANGO_WIN32_N_COVERAGES; i++)
1236 win32face->coverages[i] = NULL;
1238 win32face->is_synthetic = is_synthetic;
1240 win32face->has_cmap = TRUE;
1241 win32face->cmap_format = 0;
1242 win32face->cmap = NULL;
1244 win32face->cached_fonts = NULL;
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;
1252 win32family->faces = g_slist_append (win32family->faces, win32face);
1254 PING (("name=%s, length(faces)=%d",
1255 win32family->family_name, g_slist_length (win32family->faces)));
1258 /* Given a LOGFONTW and size, make a matching LOGFONTW corresponding to
1259 * an installed font.
1262 _pango_win32_make_matching_logfontw (PangoFontMap *fontmap,
1263 const LOGFONTW *lfp,
1267 PangoWin32FontMap *win32fontmap;
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);
1274 match = g_hash_table_lookup (win32fontmap->fonts, lfp);
1278 PING (("not found"));
1282 /* OK, we have a match; let's modify it to fit this size */
1285 out->lfHeight = -(int)((double)size / win32fontmap->resolution + 0.5);
1289 static PangoFontDescription *
1290 pango_win32_face_describe (PangoFontFace *face)
1292 PangoWin32Face *win32face = PANGO_WIN32_FACE (face);
1294 return pango_font_description_copy (win32face->description);
1298 pango_win32_face_get_face_name (PangoFontFace *face)
1300 PangoWin32Face *win32face = PANGO_WIN32_FACE (face);
1302 if (!win32face->face_name)
1304 PangoFontDescription *desc = pango_font_face_describe (face);
1306 pango_font_description_unset_fields (desc,
1307 PANGO_FONT_MASK_FAMILY | PANGO_FONT_MASK_SIZE);
1309 win32face->face_name = pango_font_description_to_string (desc);
1310 pango_font_description_free (desc);
1313 return win32face->face_name;
1317 pango_win32_face_is_synthesized (PangoFontFace *face)
1319 PangoWin32Face *win32face = PANGO_WIN32_FACE (face);
1321 return win32face->is_synthetic;
1325 pango_win32_face_class_init (PangoFontFaceClass *class)
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;
1334 pango_win32_face_list_sizes (PangoFontFace *face,
1339 * for scalable fonts it's simple, and currently we only have such
1340 * see : pango_win32_enum_proc(), TRUETYPE_FONTTYPE
1347 pango_win32_face_get_type (void)
1349 static GType object_type = 0;
1351 if (G_UNLIKELY (!object_type))
1353 static const GTypeInfo object_info =
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,
1366 object_type = g_type_register_static (PANGO_TYPE_FONT_FACE,
1367 I_("PangoWin32Face"),
1375 * pango_win32_font_map_get_font_cache:
1376 * @font_map: a #PangoWin32FontMap.
1378 * Obtains the font cache associated with the given font map.
1380 * Return value: the #PangoWin32FontCache of @font_map.
1382 PangoWin32FontCache *
1383 pango_win32_font_map_get_font_cache (PangoFontMap *font_map)
1385 g_return_val_if_fail (font_map != NULL, NULL);
1386 g_return_val_if_fail (PANGO_WIN32_IS_FONT_MAP (font_map), NULL);
1388 return PANGO_WIN32_FONT_MAP (font_map)->font_cache;
1392 _pango_win32_fontmap_cache_remove (PangoFontMap *fontmap,
1393 PangoWin32Font *win32font)
1395 PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
1396 GList *link = g_queue_find (win32fontmap->freed_fonts, win32font);
1399 g_queue_delete_link (win32fontmap->freed_fonts, link);
1400 win32font->in_cache = FALSE;
1402 g_object_unref (win32font);
1406 pango_win32_fontmap_cache_clear (PangoWin32FontMap *win32fontmap)
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 ();