1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
35 static GHashTable *font_name_hash = NULL;
36 static GHashTable *fontset_name_hash = NULL;
39 gdk_font_hash_insert (GdkFontType type,
41 const gchar *font_name)
43 GdkFontPrivateWin32 *private = (GdkFontPrivateWin32 *) font;
44 GHashTable **hashp = (type == GDK_FONT_FONT) ?
45 &font_name_hash : &fontset_name_hash;
48 *hashp = g_hash_table_new (g_str_hash, g_str_equal);
50 private->names = g_slist_prepend (private->names, g_strdup (font_name));
51 g_hash_table_insert (*hashp, private->names->data, font);
55 gdk_font_hash_remove (GdkFontType type,
58 GdkFontPrivateWin32 *private = (GdkFontPrivateWin32 *) font;
60 GHashTable *hash = (type == GDK_FONT_FONT) ?
61 font_name_hash : fontset_name_hash;
63 tmp_list = private->names;
66 g_hash_table_remove (hash, tmp_list->data);
67 g_free (tmp_list->data);
69 tmp_list = tmp_list->next;
72 g_slist_free (private->names);
73 private->names = NULL;
77 gdk_font_hash_lookup (GdkFontType type,
78 const gchar *font_name)
81 GHashTable *hash = (type == GDK_FONT_FONT) ?
82 font_name_hash : fontset_name_hash;
88 result = g_hash_table_lookup (hash, font_name);
90 gdk_font_ref (result);
97 charset_name (DWORD charset)
101 case ANSI_CHARSET: return "ansi";
102 case DEFAULT_CHARSET: return "default";
103 case SYMBOL_CHARSET: return "symbol";
104 case SHIFTJIS_CHARSET: return "shiftjis";
105 case HANGEUL_CHARSET: return "hangeul";
106 case GB2312_CHARSET: return "gb2312";
107 case CHINESEBIG5_CHARSET: return "big5";
108 case JOHAB_CHARSET: return "johab";
109 case HEBREW_CHARSET: return "hebrew";
110 case ARABIC_CHARSET: return "arabic";
111 case GREEK_CHARSET: return "greek";
112 case TURKISH_CHARSET: return "turkish";
113 case VIETNAMESE_CHARSET: return "vietnamese";
114 case THAI_CHARSET: return "thai";
115 case EASTEUROPE_CHARSET: return "easteurope";
116 case RUSSIAN_CHARSET: return "russian";
117 case MAC_CHARSET: return "mac";
118 case BALTIC_CHARSET: return "baltic";
123 static gint num_fonts;
124 static gint font_names_size;
125 static gchar **xfontnames;
128 logfont_to_xlfd (const LOGFONT *lfp,
134 const gchar *registry, *encoding;
136 static int logpixelsy = 0;
137 gchar facename[LF_FACESIZE*5];
138 gchar *utf8_facename;
144 logpixelsy = GetDeviceCaps (gdk_DC, LOGPIXELSY);
147 if (lfp->lfWeight >= FW_HEAVY)
149 else if (lfp->lfWeight >= FW_EXTRABOLD)
150 weight = "extrabold";
151 else if (lfp->lfWeight >= FW_BOLD)
154 else if (lfp->lfWeight >= FW_DEMIBOLD)
157 else if (lfp->lfWeight >= FW_MEDIUM)
159 else if (lfp->lfWeight >= FW_NORMAL)
161 else if (lfp->lfWeight >= FW_LIGHT)
163 else if (lfp->lfWeight >= FW_EXTRALIGHT)
164 weight = "extralight";
165 else if (lfp->lfWeight >= FW_THIN)
170 switch (lfp->lfCharSet)
173 registry = "iso8859";
176 case SHIFTJIS_CHARSET:
177 registry = "jisx0208.1983";
180 case HANGEUL_CHARSET:
181 registry = "ksc5601.1987";
185 registry = "gb2312.1980";
188 case CHINESEBIG5_CHARSET:
193 registry = "iso8859";
196 case TURKISH_CHARSET:
197 registry = "iso8859";
200 #if 0 /* Not a good idea, I think, to use ISO8859-8 and -6 for the Windows
201 * hebrew and arabic codepages, they differ too much.
204 registry = "iso8859";
208 registry = "iso8859";
213 registry = "microsoft";
214 encoding = charset_name (lfp->lfCharSet);
217 point_size = (int) (((double) size/logpixelsy) * 720.);
222 /* Convert the facename Windows fives us from the locale-dependent
225 utf8_facename = g_filename_to_utf8 (lfp->lfFaceName);
227 /* Replace characters illegal in an XLFD with hex escapes. */
232 if (*q == '-' || *q == '*' || *q == '?' || *q == '%')
233 p += sprintf (p, "%%%.02x", *q);
239 g_free (utf8_facename);
241 return g_strdup_printf
242 ("-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d-%s-%s",
247 ((lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN
248 || (lfp->lfPitchAndFamily & 0xF0) == FF_SCRIPT ?
256 ((lfp->lfPitchAndFamily & 0x03) == FIXED_PITCH ? "m" : "p"),
262 gdk_font_full_name_get (GdkFont *font)
264 GdkFontPrivateWin32 *private;
265 GdkWin32SingleFont *singlefont;
272 g_return_val_if_fail (font != NULL, NULL);
274 private = (GdkFontPrivateWin32 *) font;
276 list = private->fonts;
277 string = g_string_new ("");
281 singlefont = (GdkWin32SingleFont *) list->data;
283 if (GetObject (singlefont->xfont, sizeof (LOGFONT), &logfont) == 0)
285 g_warning ("gdk_font_full_name_get: GetObject failed");
289 xlfd = logfont_to_xlfd (&logfont, logfont.lfHeight, -1, 0);
290 string = g_string_append (string, xlfd);
294 string = g_string_append_c (string, ',');
296 result = string->str;
297 g_string_free (string, FALSE);
302 gdk_font_full_name_free (gchar *name)
308 pattern_match (const gchar *pattern,
311 const gchar *p = pattern, *n = string;
314 /* Common case first */
315 if ((pattern[0] == '*'
316 && pattern[1] == '\0')
317 || (pattern[0] == '-'
319 && pattern[2] == '\0'))
322 while ((c = *p++) != '\0')
334 for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
335 if (c == '?' && *n == '\0')
342 for (--p; *n != '\0'; ++n)
343 if (tolower (*n) == c1
344 && pattern_match (p, n))
349 if (c != tolower (*n))
363 InnerEnumFontFamExProc (const LOGFONT *lfp,
364 const TEXTMETRIC *metrics,
371 if (fontType == TRUETYPE_FONTTYPE)
377 size = lfp->lfHeight;
380 xlfd = logfont_to_xlfd (lfp, size, 0, 0);
382 if (!pattern_match ((gchar *) lParam, xlfd))
389 if (num_fonts == font_names_size)
391 font_names_size *= 2;
392 xfontnames = g_realloc (xfontnames, font_names_size * sizeof (gchar *));
394 xfontnames[num_fonts-1] = xlfd;
400 EnumFontFamExProc (const LOGFONT *lfp,
401 const TEXTMETRIC *metrics,
405 if (fontType == TRUETYPE_FONTTYPE)
411 EnumFontFamiliesEx (gdk_DC, &lf, InnerEnumFontFamExProc, lParam, 0);
414 InnerEnumFontFamExProc (lfp, metrics, fontType, lParam);
420 gdk_font_list_new (const gchar *font_pattern,
427 font_names_size = 100;
428 xfontnames = g_new (gchar *, font_names_size);
429 memset (&logfont, 0, sizeof (logfont));
430 logfont.lfCharSet = DEFAULT_CHARSET;
431 EnumFontFamiliesEx (gdk_DC, &logfont, EnumFontFamExProc,
432 (LPARAM) font_pattern, 0);
434 result = g_new (gchar *, num_fonts + 1);
435 memmove (result, xfontnames, num_fonts * sizeof (gchar *));
436 result[num_fonts] = NULL;
439 *n_returned = num_fonts;
444 gdk_font_list_free (gchar **font_list)
446 g_strfreev (font_list);
449 /* This table classifies Unicode characters according to the Microsoft
450 * Unicode subset numbering. This is from the table in "Developing
451 * International Software for Windows 95 and Windows NT". This is almost,
452 * but not quite, the same as the official Unicode block table in
453 * Blocks.txt from ftp.unicode.org. The bit number field is the bitfield
454 * number as in the FONTSIGNATURE struct's fsUsb field.
460 U_LATIN_1_SUPPLEMENT = 1,
461 U_LATIN_EXTENDED_A = 2,
462 U_LATIN_EXTENDED_B = 3,
463 U_IPA_EXTENSIONS = 4,
464 U_SPACING_MODIFIER_LETTERS = 5,
465 U_COMBINING_DIACRITICAL_MARKS = 6,
467 U_GREEK_SYMBOLS_AND_COPTIC = 8,
470 U_HEBREW_EXTENDED = 12,
473 U_ARABIC_EXTENDED = 14,
485 U_GEORGIAN_EXTENDED = 27,
486 U_BASIC_GEORGIAN = 26,
488 U_LATIN_EXTENDED_ADDITIONAL = 29,
489 U_GREEK_EXTENDED = 30,
490 U_GENERAL_PUNCTUATION = 31,
491 U_SUPERSCRIPTS_AND_SUBSCRIPTS = 32,
492 U_CURRENCY_SYMBOLS = 33,
493 U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS = 34,
494 U_LETTERLIKE_SYMBOLS = 35,
497 U_MATHEMATICAL_OPERATORS = 38,
498 U_MISCELLANEOUS_TECHNICAL = 39,
499 U_CONTROL_PICTURES = 40,
500 U_OPTICAL_CHARACTER_RECOGNITION = 41,
501 U_ENCLOSED_ALPHANUMERICS = 42,
503 U_BLOCK_ELEMENTS = 44,
504 U_GEOMETRIC_SHAPES = 45,
505 U_MISCELLANEOUS_SYMBOLS = 46,
507 U_CJK_SYMBOLS_AND_PUNCTUATION = 48,
511 U_HANGUL_COMPATIBILITY_JAMO = 52,
512 U_CJK_MISCELLANEOUS = 53,
514 U_CJK_COMPATIBILITY = 55,
516 U_HANGUL_SUPPLEMENTARY_A = 57,
517 U_HANGUL_SUPPLEMENTARY_B = 58,
518 U_CJK_UNIFIED_IDEOGRAPHS = 59,
519 U_PRIVATE_USE_AREA = 60,
520 U_CJK_COMPATIBILITY_IDEOGRAPHS = 61,
521 U_ALPHABETIC_PRESENTATION_FORMS = 62,
522 U_ARABIC_PRESENTATION_FORMS_A = 63,
523 U_COMBINING_HALF_MARKS = 64,
524 U_CJK_COMPATIBILITY_FORMS = 65,
525 U_SMALL_FORM_VARIANTS = 66,
526 U_ARABIC_PRESENTATION_FORMS_B = 67,
528 U_HALFWIDTH_AND_FULLWIDTH_FORMS = 68,
539 U_BASIC_LATIN, "Basic Latin" },
541 U_LATIN_1_SUPPLEMENT, "Latin-1 Supplement" },
543 U_LATIN_EXTENDED_A, "Latin Extended-A" },
545 U_LATIN_EXTENDED_B, "Latin Extended-B" },
547 U_IPA_EXTENSIONS, "IPA Extensions" },
549 U_SPACING_MODIFIER_LETTERS, "Spacing Modifier Letters" },
551 U_COMBINING_DIACRITICAL_MARKS, "Combining Diacritical Marks" },
553 U_BASIC_GREEK, "Basic Greek" },
555 U_GREEK_SYMBOLS_AND_COPTIC, "Greek Symbols and Coptic" },
557 U_CYRILLIC, "Cyrillic" },
559 U_ARMENIAN, "Armenian" },
561 U_HEBREW_EXTENDED, "Hebrew Extended" },
563 U_BASIC_HEBREW, "Basic Hebrew" },
565 U_BASIC_ARABIC, "Basic Arabic" },
567 U_ARABIC_EXTENDED, "Arabic Extended" },
569 U_DEVANAGARI, "Devanagari" },
571 U_BENGALI, "Bengali" },
573 U_GURMUKHI, "Gurmukhi" },
575 U_GUJARATI, "Gujarati" },
581 U_TELUGU, "Telugu" },
583 U_KANNADA, "Kannada" },
585 U_MALAYALAM, "Malayalam" },
591 U_GEORGIAN_EXTENDED, "Georgian Extended" },
593 U_BASIC_GEORGIAN, "Basic Georgian" },
595 U_HANGUL_JAMO, "Hangul Jamo" },
597 U_LATIN_EXTENDED_ADDITIONAL, "Latin Extended Additional" },
599 U_GREEK_EXTENDED, "Greek Extended" },
601 U_GENERAL_PUNCTUATION, "General Punctuation" },
603 U_SUPERSCRIPTS_AND_SUBSCRIPTS, "Superscripts and Subscripts" },
605 U_CURRENCY_SYMBOLS, "Currency Symbols" },
607 U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS, "Combining Diacritical Marks for Symbols" },
609 U_LETTERLIKE_SYMBOLS, "Letterlike Symbols" },
611 U_NUMBER_FORMS, "Number Forms" },
613 U_ARROWS, "Arrows" },
615 U_MATHEMATICAL_OPERATORS, "Mathematical Operators" },
617 U_MISCELLANEOUS_TECHNICAL, "Miscellaneous Technical" },
619 U_CONTROL_PICTURES, "Control Pictures" },
621 U_OPTICAL_CHARACTER_RECOGNITION, "Optical Character Recognition" },
623 U_ENCLOSED_ALPHANUMERICS, "Enclosed Alphanumerics" },
625 U_BOX_DRAWING, "Box Drawing" },
627 U_BLOCK_ELEMENTS, "Block Elements" },
629 U_GEOMETRIC_SHAPES, "Geometric Shapes" },
631 U_MISCELLANEOUS_SYMBOLS, "Miscellaneous Symbols" },
633 U_DINGBATS, "Dingbats" },
635 U_CJK_SYMBOLS_AND_PUNCTUATION, "CJK Symbols and Punctuation" },
637 U_HIRAGANA, "Hiragana" },
639 U_KATAKANA, "Katakana" },
641 U_BOPOMOFO, "Bopomofo" },
643 U_HANGUL_COMPATIBILITY_JAMO, "Hangul Compatibility Jamo" },
645 U_CJK_MISCELLANEOUS, "CJK Miscellaneous" },
647 U_ENCLOSED_CJK, "Enclosed CJK" },
649 U_CJK_COMPATIBILITY, "CJK Compatibility" },
651 U_HANGUL, "Hangul" },
653 U_HANGUL_SUPPLEMENTARY_A, "Hangul Supplementary-A" },
655 U_HANGUL_SUPPLEMENTARY_B, "Hangul Supplementary-B" },
657 U_CJK_UNIFIED_IDEOGRAPHS, "CJK Unified Ideographs" },
659 U_PRIVATE_USE_AREA, "Private Use Area" },
661 U_CJK_COMPATIBILITY_IDEOGRAPHS, "CJK Compatibility Ideographs" },
663 U_ALPHABETIC_PRESENTATION_FORMS, "Alphabetic Presentation Forms" },
665 U_ARABIC_PRESENTATION_FORMS_A, "Arabic Presentation Forms-A" },
667 U_COMBINING_HALF_MARKS, "Combining Half Marks" },
669 U_CJK_COMPATIBILITY_FORMS, "CJK Compatibility Forms" },
671 U_SMALL_FORM_VARIANTS, "Small Form Variants" },
673 U_ARABIC_PRESENTATION_FORMS_B, "Arabic Presentation Forms-B" },
675 U_SPECIALS, "Specials" },
677 U_HALFWIDTH_AND_FULLWIDTH_FORMS, "Halfwidth and Fullwidth Forms" },
679 U_SPECIALS, "Specials" }
683 print_unicode_subranges (FONTSIGNATURE *fsp)
686 gboolean checked[sizeof (utab) / sizeof (utab[0])];
687 gboolean need_comma = FALSE;
689 memset (checked, 0, sizeof (checked));
691 for (i = 0; i < sizeof (utab) / sizeof (utab[0]); i++)
693 && (fsp->fsUsb[utab[i].bit/32] & (1 << (utab[i].bit % 32))))
695 g_print ("%s %s", (need_comma ? "," : ""), utab[i].name);
705 check_unicode_subranges (UINT charset,
709 gboolean retval = FALSE;
711 /* If the fsUsb bit array has at least one of the bits set, trust it */
712 for (i = 0; i < U_LAST_PLUS_ONE; i++)
713 if (i != U_PRIVATE_USE_AREA && (fsp->fsUsb[i/32] & (1 << (i % 32))))
716 /* Otherwise, guess what subranges there should be in the font */
717 fsp->fsUsb[0] = fsp->fsUsb[1] = fsp->fsUsb[2] = fsp->fsUsb[3] = 0;
719 #define set_bit(bitno) (fsp->fsUsb[(bitno)/32] |= (1 << ((bitno) % 32)))
721 /* Set Unicode subrange bits based on code pages supported.
722 * This is mostly just guesswork.
725 #define check_cp(bit) (fsp->fsCsb[0] & (bit))
727 if (check_cp(FS_LATIN1))
729 set_bit (U_BASIC_LATIN);
730 set_bit (U_LATIN_1_SUPPLEMENT);
731 set_bit (U_CURRENCY_SYMBOLS);
734 if (check_cp (FS_LATIN2))
736 set_bit (U_BASIC_LATIN);
737 set_bit (U_LATIN_1_SUPPLEMENT);
738 set_bit (U_LATIN_EXTENDED_A);
739 set_bit (U_CURRENCY_SYMBOLS);
742 if (check_cp (FS_CYRILLIC))
744 set_bit (U_BASIC_LATIN);
745 set_bit (U_CYRILLIC);
748 if (check_cp (FS_GREEK))
750 set_bit (U_BASIC_LATIN);
751 set_bit (U_BASIC_GREEK);
754 if (check_cp (FS_TURKISH))
756 set_bit (U_BASIC_LATIN);
757 set_bit (U_LATIN_1_SUPPLEMENT);
758 set_bit (U_LATIN_EXTENDED_A);
759 set_bit (U_CURRENCY_SYMBOLS);
762 if (check_cp (FS_HEBREW))
764 set_bit (U_BASIC_LATIN);
765 set_bit (U_CURRENCY_SYMBOLS);
766 set_bit (U_BASIC_HEBREW);
767 set_bit (U_HEBREW_EXTENDED);
770 if (check_cp (FS_ARABIC))
772 set_bit (U_BASIC_LATIN);
773 set_bit (U_CURRENCY_SYMBOLS);
774 set_bit (U_BASIC_ARABIC);
775 set_bit (U_ARABIC_EXTENDED);
778 if (check_cp (FS_BALTIC))
780 set_bit (U_BASIC_LATIN);
781 set_bit (U_LATIN_1_SUPPLEMENT);
782 set_bit (U_CURRENCY_SYMBOLS);
783 set_bit (U_LATIN_EXTENDED_A);
784 set_bit (U_LATIN_EXTENDED_B);
787 if (check_cp (FS_VIETNAMESE))
790 set_bit (U_BASIC_LATIN);
793 if (check_cp (FS_THAI))
795 set_bit (U_BASIC_LATIN);
799 if (check_cp (FS_JISJAPAN))
801 /* Based on MS Gothic */
802 set_bit (U_BASIC_LATIN);
803 set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
804 set_bit (U_HIRAGANA);
805 set_bit (U_KATAKANA);
806 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
807 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
810 if (check_cp (FS_CHINESESIMP))
812 /* Based on MS Hei */
813 set_bit (U_BASIC_LATIN);
814 set_bit (U_HIRAGANA);
815 set_bit (U_KATAKANA);
816 set_bit (U_BOPOMOFO);
817 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
820 if (check_cp (FS_WANSUNG)
821 || check_cp (FS_JOHAB)) /* ??? */
823 /* Based on GulimChe. I wonder if all Korean fonts
824 * really support this large range of Unicode subranges?
826 set_bit (U_BASIC_LATIN);
827 set_bit (U_LATIN_1_SUPPLEMENT);
828 set_bit (U_LATIN_EXTENDED_A);
829 set_bit (U_SPACING_MODIFIER_LETTERS);
830 set_bit (U_BASIC_GREEK);
831 set_bit (U_CYRILLIC);
832 set_bit (U_GENERAL_PUNCTUATION);
833 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
834 set_bit (U_CURRENCY_SYMBOLS);
835 set_bit (U_LETTERLIKE_SYMBOLS);
836 set_bit (U_NUMBER_FORMS);
838 set_bit (U_MATHEMATICAL_OPERATORS);
839 set_bit (U_MISCELLANEOUS_TECHNICAL);
840 set_bit (U_ENCLOSED_ALPHANUMERICS);
841 set_bit (U_BOX_DRAWING);
842 set_bit (U_BLOCK_ELEMENTS);
843 set_bit (U_GEOMETRIC_SHAPES);
844 set_bit (U_MISCELLANEOUS_SYMBOLS);
845 set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
846 set_bit (U_HIRAGANA);
847 set_bit (U_KATAKANA);
848 set_bit (U_HANGUL_COMPATIBILITY_JAMO);
849 set_bit (U_ENCLOSED_CJK);
850 set_bit (U_CJK_COMPATIBILITY_FORMS);
852 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
853 set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
854 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
857 if (check_cp (FS_CHINESETRAD))
859 /* Based on MingLiU */
860 set_bit (U_BASIC_LATIN);
861 set_bit (U_GENERAL_PUNCTUATION);
862 set_bit (U_BOX_DRAWING);
863 set_bit (U_BLOCK_ELEMENTS);
864 set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
865 set_bit (U_BOPOMOFO);
866 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
867 set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
868 set_bit (U_SMALL_FORM_VARIANTS);
869 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
872 if (check_cp (FS_SYMBOL) || charset == MAC_CHARSET)
874 /* Non-Unicode encoding, I guess. Pretend it covers
875 * the single-byte range of values.
877 set_bit (U_BASIC_LATIN);
878 set_bit (U_LATIN_1_SUPPLEMENT);
885 GDK_NOTE (MISC, g_print ("... No code page bits set!\n"));
887 /* Sigh. Not even any code page bits were set. Guess based on
888 * charset, then. These somewhat optimistic guesses are based on the
889 * table in Appendix M in the book "Developing ..." mentioned
895 set_bit (U_BASIC_LATIN);
896 set_bit (U_LATIN_1_SUPPLEMENT);
897 set_bit (U_LATIN_EXTENDED_A);
898 set_bit (U_LATIN_EXTENDED_B);
899 set_bit (U_SPACING_MODIFIER_LETTERS);
900 set_bit (U_COMBINING_DIACRITICAL_MARKS);
901 set_bit (U_GENERAL_PUNCTUATION);
902 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
903 set_bit (U_CURRENCY_SYMBOLS);
904 #if 0 /* I find this too hard to believe... */
905 set_bit (U_BASIC_GREEK);
906 set_bit (U_CYRILLIC);
907 set_bit (U_BASIC_HEBREW);
908 set_bit (U_HEBREW_EXTENDED);
909 set_bit (U_BASIC_ARABIC);
910 set_bit (U_ARABIC_EXTENDED);
911 set_bit (U_LETTERLIKE_SYMBOLS);
912 set_bit (U_NUMBER_FORMS);
914 set_bit (U_MATHEMATICAL_OPERATORS);
915 set_bit (U_MISCELLANEOUS_TECHNICAL);
916 set_bit (U_ENCLOSED_ALPHANUMERICS);
917 set_bit (U_BOX_DRAWING);
918 set_bit (U_BLOCK_ELEMENTS);
919 set_bit (U_GEOMETRIC_SHAPES);
920 set_bit (U_MISCELLANEOUS_SYMBOLS);
921 set_bit (U_HIRAGANA);
922 set_bit (U_KATAKANA);
923 set_bit (U_BOPOMOFO);
924 set_bit (U_HANGUL_COMPATIBILITY_JAMO);
925 set_bit (U_CJK_MISCELLANEOUS);
926 set_bit (U_CJK_COMPATIBILITY);
928 set_bit (U_HANGUL_SUPPLEMENTARY_A);
929 set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
930 set_bit (U_ALPHABETIC_PRESENTATION_FORMS);
931 set_bit (U_SMALL_FORM_VARIANTS);
932 set_bit (U_ARABIC_PRESENTATION_FORMS_B);
933 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
934 set_bit (U_SPECIALS);
940 set_bit (U_BASIC_LATIN);
941 set_bit (U_LATIN_1_SUPPLEMENT);
944 case SHIFTJIS_CHARSET:
945 case HANGEUL_CHARSET:
947 case CHINESEBIG5_CHARSET:
949 /* The table really does claim these "locales" (it doesn't
950 * talk about charsets per se) cover the same Unicode
953 set_bit (U_BASIC_LATIN);
954 set_bit (U_LATIN_1_SUPPLEMENT);
955 set_bit (U_LATIN_EXTENDED_A);
956 set_bit (U_LATIN_EXTENDED_B);
957 set_bit (U_SPACING_MODIFIER_LETTERS);
958 set_bit (U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS);
959 set_bit (U_BASIC_GREEK);
960 set_bit (U_CYRILLIC);
961 set_bit (U_GENERAL_PUNCTUATION);
962 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
963 set_bit (U_CURRENCY_SYMBOLS);
964 set_bit (U_LETTERLIKE_SYMBOLS);
965 set_bit (U_NUMBER_FORMS);
967 set_bit (U_MATHEMATICAL_OPERATORS);
968 set_bit (U_MISCELLANEOUS_TECHNICAL);
969 set_bit (U_ENCLOSED_ALPHANUMERICS);
970 set_bit (U_BOX_DRAWING);
971 set_bit (U_BLOCK_ELEMENTS);
972 set_bit (U_GEOMETRIC_SHAPES);
973 set_bit (U_MISCELLANEOUS_SYMBOLS);
974 set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
975 set_bit (U_HIRAGANA);
976 set_bit (U_KATAKANA);
977 set_bit (U_BOPOMOFO);
978 set_bit (U_HANGUL_COMPATIBILITY_JAMO);
979 set_bit (U_CJK_MISCELLANEOUS);
980 set_bit (U_CJK_COMPATIBILITY);
982 set_bit (U_HANGUL_SUPPLEMENTARY_A);
983 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
984 set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
985 set_bit (U_ALPHABETIC_PRESENTATION_FORMS);
986 set_bit (U_SMALL_FORM_VARIANTS);
987 set_bit (U_ARABIC_PRESENTATION_FORMS_B);
988 set_bit (U_SPECIALS);
992 set_bit (U_BASIC_LATIN);
993 set_bit (U_LATIN_1_SUPPLEMENT);
994 set_bit (U_LATIN_EXTENDED_B);
995 set_bit (U_SPACING_MODIFIER_LETTERS);
996 set_bit (U_BASIC_HEBREW);
997 set_bit (U_HEBREW_EXTENDED);
998 set_bit (U_GENERAL_PUNCTUATION);
999 set_bit (U_LETTERLIKE_SYMBOLS);
1002 case ARABIC_CHARSET:
1003 set_bit (U_BASIC_LATIN);
1004 set_bit (U_LATIN_1_SUPPLEMENT);
1005 set_bit (U_LATIN_EXTENDED_A);
1006 set_bit (U_LATIN_EXTENDED_B);
1007 set_bit (U_SPACING_MODIFIER_LETTERS);
1008 set_bit (U_BASIC_GREEK);
1009 set_bit (U_BASIC_ARABIC);
1010 set_bit (U_ARABIC_EXTENDED);
1011 set_bit (U_GENERAL_PUNCTUATION);
1012 set_bit (U_LETTERLIKE_SYMBOLS);
1014 set_bit (U_MATHEMATICAL_OPERATORS);
1015 set_bit (U_MISCELLANEOUS_TECHNICAL);
1016 set_bit (U_BOX_DRAWING);
1017 set_bit (U_BLOCK_ELEMENTS);
1018 set_bit (U_GEOMETRIC_SHAPES);
1019 set_bit (U_MISCELLANEOUS_SYMBOLS);
1020 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
1024 set_bit (U_BASIC_LATIN);
1025 set_bit (U_LATIN_1_SUPPLEMENT);
1026 set_bit (U_LATIN_EXTENDED_B);
1027 set_bit (U_BASIC_GREEK);
1028 set_bit (U_GENERAL_PUNCTUATION);
1029 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
1030 set_bit (U_LETTERLIKE_SYMBOLS);
1032 set_bit (U_MATHEMATICAL_OPERATORS);
1033 set_bit (U_MISCELLANEOUS_TECHNICAL);
1034 set_bit (U_BOX_DRAWING);
1035 set_bit (U_BLOCK_ELEMENTS);
1036 set_bit (U_GEOMETRIC_SHAPES);
1037 set_bit (U_MISCELLANEOUS_SYMBOLS);
1040 case TURKISH_CHARSET:
1041 set_bit (U_BASIC_LATIN);
1042 set_bit (U_LATIN_1_SUPPLEMENT);
1043 set_bit (U_LATIN_EXTENDED_A);
1044 set_bit (U_LATIN_EXTENDED_B);
1045 set_bit (U_SPACING_MODIFIER_LETTERS);
1046 set_bit (U_BASIC_GREEK);
1047 set_bit (U_GENERAL_PUNCTUATION);
1048 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
1049 set_bit (U_CURRENCY_SYMBOLS);
1050 set_bit (U_LETTERLIKE_SYMBOLS);
1052 set_bit (U_MATHEMATICAL_OPERATORS);
1053 set_bit (U_MISCELLANEOUS_TECHNICAL);
1054 set_bit (U_BOX_DRAWING);
1055 set_bit (U_BLOCK_ELEMENTS);
1056 set_bit (U_GEOMETRIC_SHAPES);
1057 set_bit (U_MISCELLANEOUS_SYMBOLS);
1060 case VIETNAMESE_CHARSET:
1062 /* These are not in the table, so I have no idea */
1064 case BALTIC_CHARSET:
1065 set_bit (U_BASIC_LATIN);
1066 set_bit (U_LATIN_1_SUPPLEMENT);
1067 set_bit (U_LATIN_EXTENDED_A);
1068 set_bit (U_LATIN_EXTENDED_B);
1069 set_bit (U_SPACING_MODIFIER_LETTERS);
1070 set_bit (U_BASIC_GREEK);
1071 set_bit (U_GENERAL_PUNCTUATION);
1072 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
1073 set_bit (U_CURRENCY_SYMBOLS);
1074 set_bit (U_LETTERLIKE_SYMBOLS);
1076 set_bit (U_MATHEMATICAL_OPERATORS);
1077 set_bit (U_MISCELLANEOUS_TECHNICAL);
1078 set_bit (U_BOX_DRAWING);
1079 set_bit (U_BLOCK_ELEMENTS);
1080 set_bit (U_GEOMETRIC_SHAPES);
1081 set_bit (U_MISCELLANEOUS_SYMBOLS);
1084 case EASTEUROPE_CHARSET:
1085 set_bit (U_BASIC_LATIN);
1086 set_bit (U_LATIN_1_SUPPLEMENT);
1087 set_bit (U_LATIN_EXTENDED_A);
1088 set_bit (U_LATIN_EXTENDED_B);
1089 set_bit (U_SPACING_MODIFIER_LETTERS);
1090 set_bit (U_BASIC_GREEK);
1091 set_bit (U_GENERAL_PUNCTUATION);
1092 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
1093 set_bit (U_CURRENCY_SYMBOLS);
1094 set_bit (U_LETTERLIKE_SYMBOLS);
1096 set_bit (U_MATHEMATICAL_OPERATORS);
1097 set_bit (U_MISCELLANEOUS_TECHNICAL);
1098 set_bit (U_BOX_DRAWING);
1099 set_bit (U_BLOCK_ELEMENTS);
1100 set_bit (U_GEOMETRIC_SHAPES);
1101 set_bit (U_MISCELLANEOUS_SYMBOLS);
1104 case RUSSIAN_CHARSET:
1105 set_bit (U_BASIC_LATIN);
1106 set_bit (U_LATIN_1_SUPPLEMENT);
1107 set_bit (U_CYRILLIC);
1108 set_bit (U_GENERAL_PUNCTUATION);
1109 set_bit (U_LETTERLIKE_SYMBOLS);
1111 set_bit (U_MATHEMATICAL_OPERATORS);
1112 set_bit (U_MISCELLANEOUS_TECHNICAL);
1113 set_bit (U_BOX_DRAWING);
1114 set_bit (U_BLOCK_ELEMENTS);
1115 set_bit (U_GEOMETRIC_SHAPES);
1116 set_bit (U_MISCELLANEOUS_SYMBOLS);
1126 gdk_font_load_internal (const gchar *font_name)
1128 GdkWin32SingleFont *singlefont;
1132 DWORD fdwItalic, fdwUnderline, fdwStrikeOut, fdwCharSet,
1133 fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily;
1138 int numfields, n1, n2, tries;
1139 char foundry[32], family[100], weight[32], slant[32], set_width[32],
1140 spacing[32], registry[32], encoding[32];
1141 char pixel_size[10], point_size[10], res_x[10], res_y[10], avg_width[10];
1144 int nHeight, nWidth, nEscapement, nOrientation, fnWeight;
1147 g_return_val_if_fail (font_name != NULL, NULL);
1149 GDK_NOTE (MISC, g_print ("gdk_font_load_internal: %s\n", font_name));
1151 numfields = sscanf (font_name,
1152 "-%30[^-]-%100[^-]-%30[^-]-%30[^-]-%30[^-]-%n",
1161 /* Probably a plain Windows font name */
1166 fnWeight = FW_DONTCARE;
1168 fdwUnderline = FALSE;
1169 fdwStrikeOut = FALSE;
1170 fdwCharSet = ANSI_CHARSET;
1171 fdwOutputPrecision = OUT_TT_PRECIS;
1172 fdwClipPrecision = CLIP_DEFAULT_PRECIS;
1173 fdwQuality = PROOF_QUALITY;
1174 fdwPitchAndFamily = DEFAULT_PITCH;
1175 lpszFace = g_filename_from_utf8 (font_name);
1177 else if (numfields != 5)
1179 g_warning ("gdk_font_load: font name %s illegal", font_name);
1184 /* It must be a XLFD name */
1186 /* Check for hex escapes in the font family,
1187 * put in there by logfont_to_xlfd. Convert them in-place.
1192 if (*p == '%' && isxdigit (p[1]) && isxdigit (p[2]))
1194 sscanf (p+1, "%2x", &c);
1201 /* Skip add_style which often is empty in the requested font name */
1202 while (font_name[n1] && font_name[n1] != '-')
1206 numfields += sscanf (font_name + n1,
1207 "-%8[^-]-%8[^-]-%8[^-]-%8[^-]-%30[^-]-%8[^-]-%30[^-]-%30[^-]%n",
1218 if (numfields != 14 || font_name[n1 + n2] != '\0')
1220 g_warning ("gdk_font_load: font name %s illegal", font_name);
1224 logpixelsy = GetDeviceCaps (gdk_DC, LOGPIXELSY);
1226 if (strcmp (pixel_size, "*") == 0)
1227 if (strcmp (point_size, "*") == 0)
1230 nHeight = (int) (((double) atoi (point_size))/720.*logpixelsy);
1232 nHeight = atoi (pixel_size);
1238 if (g_strcasecmp (weight, "thin") == 0)
1240 else if (g_strcasecmp (weight, "extralight") == 0)
1241 fnWeight = FW_EXTRALIGHT;
1242 else if (g_strcasecmp (weight, "ultralight") == 0)
1243 #ifdef FW_ULTRALIGHT
1244 fnWeight = FW_ULTRALIGHT;
1246 fnWeight = FW_EXTRALIGHT; /* In fact, FW_ULTRALIGHT really is
1247 * defined as FW_EXTRALIGHT anyway.
1250 else if (g_strcasecmp (weight, "light") == 0)
1251 fnWeight = FW_LIGHT;
1252 else if (g_strcasecmp (weight, "normal") == 0)
1253 fnWeight = FW_NORMAL;
1254 else if (g_strcasecmp (weight, "regular") == 0)
1255 fnWeight = FW_REGULAR;
1256 else if (g_strcasecmp (weight, "medium") == 0)
1257 fnWeight = FW_MEDIUM;
1258 else if (g_strcasecmp (weight, "semibold") == 0)
1259 fnWeight = FW_SEMIBOLD;
1260 else if (g_strcasecmp (weight, "demibold") == 0)
1262 fnWeight = FW_DEMIBOLD;
1264 fnWeight = FW_SEMIBOLD; /* As above */
1266 else if (g_strcasecmp (weight, "bold") == 0)
1268 else if (g_strcasecmp (weight, "extrabold") == 0)
1269 fnWeight = FW_EXTRABOLD;
1270 else if (g_strcasecmp (weight, "ultrabold") == 0)
1272 fnWeight = FW_ULTRABOLD;
1274 fnWeight = FW_EXTRABOLD; /* As above */
1276 else if (g_strcasecmp (weight, "heavy") == 0)
1277 fnWeight = FW_HEAVY;
1278 else if (g_strcasecmp (weight, "black") == 0)
1280 fnWeight = FW_BLACK;
1282 fnWeight = FW_HEAVY; /* As above */
1285 fnWeight = FW_DONTCARE;
1287 if (g_strcasecmp (slant, "italic") == 0
1288 || g_strcasecmp (slant, "oblique") == 0
1289 || g_strcasecmp (slant, "i") == 0
1290 || g_strcasecmp (slant, "o") == 0)
1294 fdwUnderline = FALSE;
1295 fdwStrikeOut = FALSE;
1296 if (g_strcasecmp (registry, "iso8859") == 0)
1297 if (strcmp (encoding, "1") == 0)
1298 fdwCharSet = ANSI_CHARSET;
1299 else if (strcmp (encoding, "2") == 0)
1300 fdwCharSet = EASTEUROPE_CHARSET;
1301 else if (strcmp (encoding, "7") == 0)
1302 fdwCharSet = GREEK_CHARSET;
1303 else if (strcmp (encoding, "8") == 0)
1304 fdwCharSet = HEBREW_CHARSET;
1305 else if (strcmp (encoding, "9") == 0)
1306 fdwCharSet = TURKISH_CHARSET;
1308 fdwCharSet = ANSI_CHARSET; /* XXX ??? */
1309 else if (g_strcasecmp (registry, "jisx0208.1983") == 0)
1310 fdwCharSet = SHIFTJIS_CHARSET;
1311 else if (g_strcasecmp (registry, "ksc5601.1987") == 0)
1312 fdwCharSet = HANGEUL_CHARSET;
1313 else if (g_strcasecmp (registry, "gb2312.1980") == 0)
1314 fdwCharSet = GB2312_CHARSET;
1315 else if (g_strcasecmp (registry, "big5") == 0)
1316 fdwCharSet = CHINESEBIG5_CHARSET;
1317 else if (g_strcasecmp (registry, "windows") == 0
1318 || g_strcasecmp (registry, "microsoft") == 0)
1319 if (g_strcasecmp (encoding, "symbol") == 0)
1320 fdwCharSet = SYMBOL_CHARSET;
1321 else if (g_strcasecmp (encoding, "shiftjis") == 0)
1322 fdwCharSet = SHIFTJIS_CHARSET;
1323 else if (g_strcasecmp (encoding, "gb2312") == 0)
1324 fdwCharSet = GB2312_CHARSET;
1325 else if (g_strcasecmp (encoding, "hangeul") == 0)
1326 fdwCharSet = HANGEUL_CHARSET;
1327 else if (g_strcasecmp (encoding, "big5") == 0)
1328 fdwCharSet = CHINESEBIG5_CHARSET;
1329 else if (g_strcasecmp (encoding, "johab") == 0)
1330 fdwCharSet = JOHAB_CHARSET;
1331 else if (g_strcasecmp (encoding, "hebrew") == 0)
1332 fdwCharSet = HEBREW_CHARSET;
1333 else if (g_strcasecmp (encoding, "arabic") == 0)
1334 fdwCharSet = ARABIC_CHARSET;
1335 else if (g_strcasecmp (encoding, "greek") == 0)
1336 fdwCharSet = GREEK_CHARSET;
1337 else if (g_strcasecmp (encoding, "turkish") == 0)
1338 fdwCharSet = TURKISH_CHARSET;
1339 else if (g_strcasecmp (encoding, "easteurope") == 0)
1340 fdwCharSet = EASTEUROPE_CHARSET;
1341 else if (g_strcasecmp (encoding, "russian") == 0)
1342 fdwCharSet = RUSSIAN_CHARSET;
1343 else if (g_strcasecmp (encoding, "mac") == 0)
1344 fdwCharSet = MAC_CHARSET;
1345 else if (g_strcasecmp (encoding, "baltic") == 0)
1346 fdwCharSet = BALTIC_CHARSET;
1347 else if (g_strcasecmp (encoding, "cp1251") == 0)
1348 fdwCharSet = RUSSIAN_CHARSET;
1350 fdwCharSet = ANSI_CHARSET; /* XXX ??? */
1352 fdwCharSet = ANSI_CHARSET; /* XXX ??? */
1353 fdwOutputPrecision = OUT_TT_PRECIS;
1354 fdwClipPrecision = CLIP_DEFAULT_PRECIS;
1355 fdwQuality = PROOF_QUALITY;
1356 if (g_strcasecmp (spacing, "m") == 0)
1357 fdwPitchAndFamily = FIXED_PITCH;
1358 else if (g_strcasecmp (spacing, "p") == 0)
1359 fdwPitchAndFamily = VARIABLE_PITCH;
1361 fdwPitchAndFamily = DEFAULT_PITCH;
1362 lpszFace = g_filename_from_utf8 (family);
1365 for (tries = 0; ; tries++)
1367 GDK_NOTE (MISC, g_print ("...trying CreateFont(%d,%d,%d,%d,"
1370 "%d,%#.02x,\"%s\")\n",
1371 nHeight, nWidth, nEscapement, nOrientation,
1372 fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut,
1373 fdwCharSet, fdwOutputPrecision, fdwClipPrecision,
1374 fdwQuality, fdwPitchAndFamily, lpszFace));
1375 hfont = CreateFont (nHeight, nWidth, nEscapement, nOrientation,
1376 fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut,
1377 fdwCharSet, fdwOutputPrecision, fdwClipPrecision,
1378 fdwQuality, fdwPitchAndFamily, lpszFace);
1379 /* After the first try lpszFace contains a return value
1380 * from g_filename_from_utf8(), so free it.
1388 /* If we fail, try some similar fonts often found on Windows. */
1391 if (g_strcasecmp (family, "helvetica") == 0)
1393 else if (g_strcasecmp (family, "new century schoolbook") == 0)
1394 lpszFace = "century schoolbook";
1395 else if (g_strcasecmp (family, "courier") == 0)
1396 lpszFace = "courier new";
1397 else if (g_strcasecmp (family, "lucida") == 0)
1398 lpszFace = "lucida sans unicode";
1399 else if (g_strcasecmp (family, "lucidatypewriter") == 0)
1400 lpszFace = "lucida console";
1401 else if (g_strcasecmp (family, "times") == 0)
1402 lpszFace = "times new roman";
1404 else if (tries == 1)
1406 if (g_strcasecmp (family, "courier") == 0)
1409 fdwPitchAndFamily |= FF_MODERN;
1411 else if (g_strcasecmp (family, "times new roman") == 0)
1414 fdwPitchAndFamily |= FF_ROMAN;
1416 else if (g_strcasecmp (family, "helvetica") == 0
1417 || g_strcasecmp (family, "lucida") == 0)
1420 fdwPitchAndFamily |= FF_SWISS;
1425 fdwPitchAndFamily = (fdwPitchAndFamily & 0x0F) | FF_DONTCARE;
1436 singlefont = g_new (GdkWin32SingleFont, 1);
1437 singlefont->xfont = hfont;
1438 GetObject (singlefont->xfont, sizeof (logfont), &logfont);
1439 oldfont = SelectObject (gdk_DC, singlefont->xfont);
1440 memset (&singlefont->fs, 0, sizeof (singlefont->fs));
1441 singlefont->charset = GetTextCharsetInfo (gdk_DC, &singlefont->fs, 0);
1442 GetTextFace (gdk_DC, sizeof (face), face);
1443 SelectObject (gdk_DC, oldfont);
1444 if (TranslateCharsetInfo ((DWORD *) singlefont->charset, &csi,
1446 && singlefont->charset != MAC_CHARSET)
1447 singlefont->codepage = csi.ciACP;
1449 singlefont->codepage = 0;
1451 GDK_NOTE (MISC, (g_print ("... = %#x %s cs %s cp%d ",
1452 singlefont->xfont, face,
1453 charset_name (singlefont->charset),
1454 singlefont->codepage),
1455 g_print ("... Unicode subranges:"),
1456 print_unicode_subranges (&singlefont->fs)));
1457 if (check_unicode_subranges (singlefont->charset, &singlefont->fs))
1458 GDK_NOTE (MISC, (g_print ("... Guesstimated Unicode subranges:"),
1459 print_unicode_subranges (&singlefont->fs)));
1465 gdk_font_load (const gchar *font_name)
1468 GdkFontPrivateWin32 *private;
1469 GdkWin32SingleFont *singlefont;
1472 TEXTMETRIC textmetric;
1474 g_return_val_if_fail (font_name != NULL, NULL);
1476 font = gdk_font_hash_lookup (GDK_FONT_FONTSET, font_name);
1480 singlefont = gdk_font_load_internal (font_name);
1482 private = g_new (GdkFontPrivateWin32, 1);
1483 font = (GdkFont*) private;
1485 private->base.ref_count = 1;
1486 private->names = NULL;
1487 private->fonts = g_slist_append (NULL, singlefont);
1489 /* Pretend all fonts are fontsets... Gtktext and gtkentry work better
1490 * that way, they use wide chars, which is necessary for non-ASCII
1491 * chars to work. (Yes, even Latin-1, as we use Unicode internally.)
1493 font->type = GDK_FONT_FONTSET;
1494 oldfont = SelectObject (gdk_DC, singlefont->xfont);
1495 GetTextMetrics (gdk_DC, &textmetric);
1496 SelectObject (gdk_DC, oldfont);
1497 font->ascent = textmetric.tmAscent;
1498 font->descent = textmetric.tmDescent;
1500 GDK_NOTE (MISC, g_print ("... asc %d desc %d\n",
1501 font->ascent, font->descent));
1503 gdk_font_hash_insert (GDK_FONT_FONTSET, font, font_name);
1509 gdk_fontset_load (gchar *fontset_name)
1512 GdkFontPrivateWin32 *private;
1513 GdkWin32SingleFont *singlefont;
1516 TEXTMETRIC textmetric;
1517 GSList *base_font_list = NULL;
1521 g_return_val_if_fail (fontset_name != NULL, NULL);
1523 font = gdk_font_hash_lookup (GDK_FONT_FONTSET, fontset_name);
1527 s = fs = g_strdup (fontset_name);
1528 while (*s && isspace (*s))
1531 g_return_val_if_fail (*s, NULL);
1533 private = g_new (GdkFontPrivateWin32, 1);
1534 font = (GdkFont*) private;
1536 private->base.ref_count = 1;
1537 private->names = NULL;
1538 private->fonts = NULL;
1540 font->type = GDK_FONT_FONTSET;
1546 if ((p = strchr (s, ',')) != NULL)
1551 while (isspace (b[-1]))
1554 singlefont = gdk_font_load_internal (s);
1557 private->fonts = g_slist_append (private->fonts, singlefont);
1558 oldfont = SelectObject (gdk_DC, singlefont->xfont);
1559 GetTextMetrics (gdk_DC, &textmetric);
1560 SelectObject (gdk_DC, oldfont);
1561 font->ascent = MAX (font->ascent, textmetric.tmAscent);
1562 font->descent = MAX (font->descent, textmetric.tmDescent);
1567 while (*s && isspace (*s))
1578 gdk_font_hash_insert (GDK_FONT_FONTSET, font, fontset_name);
1584 _gdk_font_destroy (GdkFont *font)
1586 GdkFontPrivateWin32 *private = (GdkFontPrivateWin32 *) font;
1587 GdkWin32SingleFont *singlefont;
1590 singlefont = (GdkWin32SingleFont *) private->fonts->data;
1591 GDK_NOTE (MISC, g_print ("_gdk_font_destroy %#x\n",
1592 singlefont->xfont));
1594 gdk_font_hash_remove (font->type, font);
1599 DeleteObject (singlefont->xfont);
1602 case GDK_FONT_FONTSET:
1603 list = private->fonts;
1606 singlefont = (GdkWin32SingleFont *) list->data;
1607 DeleteObject (singlefont->xfont);
1611 g_slist_free (private->fonts);
1618 _gdk_font_strlen (GdkFont *font,
1621 g_return_val_if_fail (font != NULL, -1);
1622 g_return_val_if_fail (str != NULL, -1);
1624 return strlen (str);
1628 gdk_font_id (const GdkFont *font)
1630 const GdkFontPrivateWin32 *private;
1632 g_return_val_if_fail (font != NULL, 0);
1634 private = (const GdkFontPrivateWin32 *) font;
1636 if (font->type == GDK_FONT_FONT)
1637 return (gint) ((GdkWin32SingleFont *) private->fonts->data)->xfont;
1643 gdk_font_equal (const GdkFont *fonta,
1644 const GdkFont *fontb)
1646 const GdkFontPrivateWin32 *privatea;
1647 const GdkFontPrivateWin32 *privateb;
1649 g_return_val_if_fail (fonta != NULL, FALSE);
1650 g_return_val_if_fail (fontb != NULL, FALSE);
1652 privatea = (const GdkFontPrivateWin32 *) fonta;
1653 privateb = (const GdkFontPrivateWin32 *) fontb;
1655 if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
1656 return (((GdkWin32SingleFont *) privatea->fonts->data)->xfont
1657 == ((GdkWin32SingleFont *) privateb->fonts->data)->xfont);
1658 else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
1660 GSList *lista = privatea->fonts;
1661 GSList *listb = privateb->fonts;
1663 while (lista && listb)
1665 if (((GdkWin32SingleFont *) lista->data)->xfont
1666 != ((GdkWin32SingleFont *) listb->data)->xfont)
1668 lista = lista->next;
1669 listb = listb->next;
1680 /* Return the Unicode Subset bitfield number for a Unicode character */
1683 unicode_classify (wchar_t wc)
1686 int max = sizeof (utab) / sizeof (utab[0]) - 1;
1691 mid = (min + max) / 2;
1692 if (utab[mid].high < wc)
1694 else if (wc < utab[mid].low)
1696 else if (utab[mid].low <= wc && wc <= utab[mid].high)
1697 return utab[mid].bit;
1704 gdk_wchar_text_handle (GdkFont *font,
1705 const wchar_t *wcstr,
1707 void (*handler)(GdkWin32SingleFont *,
1713 GdkFontPrivateWin32 *private;
1714 GdkWin32SingleFont *singlefont;
1717 const wchar_t *start, *end, *wcp;
1721 private = (GdkFontPrivateWin32 *) font;
1723 g_assert (private->base.ref_count > 0);
1727 /* Split Unicode string into pieces of the same class */
1729 block = unicode_classify (*wcp);
1730 while (wcp + 1 < end && unicode_classify (wcp[1]) == block)
1733 /* Find a font in the fontset that can handle this class */
1734 list = private->fonts;
1737 singlefont = (GdkWin32SingleFont *) list->data;
1739 if (singlefont->fs.fsUsb[block/32] & (1 << (block % 32)))
1748 /* Call the callback function */
1749 (*handler) (singlefont, start, wcp+1 - start, arg);
1757 } gdk_text_size_arg;
1760 gdk_text_size_handler (GdkWin32SingleFont *singlefont,
1761 const wchar_t *wcstr,
1767 gdk_text_size_arg *arg = (gdk_text_size_arg *) argp;
1772 if ((oldfont = SelectObject (gdk_DC, singlefont->xfont)) == NULL)
1774 g_warning ("gdk_text_size_handler: SelectObject failed");
1777 GetTextExtentPoint32W (gdk_DC, wcstr, wclen, &this_size);
1778 SelectObject (gdk_DC, oldfont);
1780 arg->total.cx += this_size.cx;
1781 arg->total.cy = MAX (arg->total.cy, this_size.cy);
1785 gdk_text_size (GdkFont *font,
1788 gdk_text_size_arg *arg)
1793 g_return_val_if_fail (font != NULL, FALSE);
1794 g_return_val_if_fail (text != NULL, FALSE);
1796 if (text_length == 0)
1799 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1801 wcstr = g_new (wchar_t, text_length);
1802 if (text_length == 1)
1804 /* For single characters, don't try to interpret as UTF-8.
1806 wcstr[0] = (guchar) text[0];
1807 gdk_wchar_text_handle (font, wcstr, 1, gdk_text_size_handler, arg);
1811 if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
1812 g_warning ("gdk_text_size: gdk_nmbstowchar_ts failed");
1814 gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, arg);
1823 gdk_text_width (GdkFont *font,
1827 gdk_text_size_arg arg;
1829 arg.total.cx = arg.total.cy = 0;
1831 if (!gdk_text_size (font, text, text_length, &arg))
1834 return arg.total.cx;
1838 gdk_text_width_wc (GdkFont *font,
1839 const GdkWChar *text,
1842 gdk_text_size_arg arg;
1846 g_return_val_if_fail (font != NULL, -1);
1847 g_return_val_if_fail (text != NULL, -1);
1849 if (text_length == 0)
1852 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1854 if (sizeof (wchar_t) != sizeof (GdkWChar))
1856 wcstr = g_new (wchar_t, text_length);
1857 for (i = 0; i < text_length; i++)
1861 wcstr = (wchar_t *) text;
1863 arg.total.cx = arg.total.cy = 0;
1865 gdk_wchar_text_handle (font, wcstr, text_length,
1866 gdk_text_size_handler, &arg);
1868 if (sizeof (wchar_t) != sizeof (GdkWChar))
1871 return arg.total.cx;
1875 gdk_text_extents (GdkFont *font,
1884 gdk_text_size_arg arg;
1888 g_return_if_fail (font != NULL);
1889 g_return_if_fail (text != NULL);
1891 if (text_length == 0)
1906 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1908 arg.total.cx = arg.total.cy = 0;
1910 wcstr = g_new (wchar_t, text_length);
1911 if (text_length == 1)
1913 wcstr[0] = (guchar) text[0];
1914 gdk_wchar_text_handle (font, wcstr, 1, gdk_text_size_handler, &arg);
1918 if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
1919 g_warning ("gdk_text_extents: gdk_nmbstowchar_ts failed");
1921 gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, &arg);
1926 /* XXX This is quite bogus */
1930 *rbearing = arg.total.cx;
1931 /* What should be the difference between width and rbearing? */
1933 *width = arg.total.cx;
1935 *ascent = arg.total.cy + 1;
1937 *descent = font->descent + 1;
1941 gdk_text_extents_wc (GdkFont *font,
1942 const GdkWChar *text,
1950 gdk_text_size_arg arg;
1954 g_return_if_fail (font != NULL);
1955 g_return_if_fail (text != NULL);
1957 if (text_length == 0)
1972 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1974 if (sizeof (wchar_t) != sizeof (GdkWChar))
1976 wcstr = g_new (wchar_t, text_length);
1977 for (i = 0; i < text_length; i++)
1981 wcstr = (wchar_t *) text;
1983 arg.total.cx = arg.total.cy = 0;
1985 gdk_wchar_text_handle (font, wcstr, text_length,
1986 gdk_text_size_handler, &arg);
1988 if (sizeof (wchar_t) != sizeof (GdkWChar))
1991 /* XXX This is quite bogus */
1995 *rbearing = arg.total.cx;
1997 *width = arg.total.cx;
1999 *ascent = arg.total.cy + 1;
2001 *descent = font->descent + 1;