1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * Copyright (C) 1998-2002 Tor Lillqvist
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 */
20
21 /*
22 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
26 */
27
28 #include "config.h"
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32
33 #include "gdkfont.h"
34 #include "gdkpango.h" /* gdk_pango_context_get() */
35 #include "gdkdisplay.h"
36 #include "gdkprivate-win32.h"
37
38 static GHashTable *font_name_hash = NULL;
39 static GHashTable *fontset_name_hash = NULL;
40
41 static void
gdk_font_hash_insert(GdkFontType type,GdkFont * font,const gchar * font_name)42 gdk_font_hash_insert (GdkFontType type,
43 GdkFont *font,
44 const gchar *font_name)
45 {
46 GdkFontPrivateWin32 *private = (GdkFontPrivateWin32 *) font;
47 GHashTable **hashp = (type == GDK_FONT_FONT) ?
48 &font_name_hash : &fontset_name_hash;
49
50 if (!*hashp)
51 *hashp = g_hash_table_new (g_str_hash, g_str_equal);
52
53 private->names = g_slist_prepend (private->names, g_strdup (font_name));
54 g_hash_table_insert (*hashp, private->names->data, font);
55 }
56
57 static void
gdk_font_hash_remove(GdkFontType type,GdkFont * font)58 gdk_font_hash_remove (GdkFontType type,
59 GdkFont *font)
60 {
61 GdkFontPrivateWin32 *private = (GdkFontPrivateWin32 *) font;
62 GSList *tmp_list;
63 GHashTable *hash = (type == GDK_FONT_FONT) ?
64 font_name_hash : fontset_name_hash;
65
66 tmp_list = private->names;
67 while (tmp_list)
68 {
69 g_hash_table_remove (hash, tmp_list->data);
70 g_free (tmp_list->data);
71
72 tmp_list = tmp_list->next;
73 }
74
75 g_slist_free (private->names);
76 private->names = NULL;
77 }
78
79 static GdkFont *
gdk_font_hash_lookup(GdkFontType type,const gchar * font_name)80 gdk_font_hash_lookup (GdkFontType type,
81 const gchar *font_name)
82 {
83 GdkFont *result;
84 GHashTable *hash = (type == GDK_FONT_FONT) ?
85 font_name_hash : fontset_name_hash;
86
87 if (!hash)
88 return NULL;
89 else
90 {
91 result = g_hash_table_lookup (hash, font_name);
92 if (result)
93 gdk_font_ref (result);
94
95 return result;
96 }
97 }
98
99 #ifdef G_ENABLE_DEBUG
100 static const char *
charset_name(DWORD charset)101 charset_name (DWORD charset)
102 {
103 switch (charset)
104 {
105 case ANSI_CHARSET: return "ansi";
106 case DEFAULT_CHARSET: return "default";
107 case SYMBOL_CHARSET: return "symbol";
108 case SHIFTJIS_CHARSET: return "shiftjis";
109 case HANGEUL_CHARSET: return "hangeul";
110 case GB2312_CHARSET: return "gb2312";
111 case CHINESEBIG5_CHARSET: return "big5";
112 case JOHAB_CHARSET: return "johab";
113 case HEBREW_CHARSET: return "hebrew";
114 case ARABIC_CHARSET: return "arabic";
115 case GREEK_CHARSET: return "greek";
116 case TURKISH_CHARSET: return "turkish";
117 case VIETNAMESE_CHARSET: return "vietnamese";
118 case THAI_CHARSET: return "thai";
119 case EASTEUROPE_CHARSET: return "easteurope";
120 case RUSSIAN_CHARSET: return "russian";
121 case MAC_CHARSET: return "mac";
122 case BALTIC_CHARSET: return "baltic";
123 }
124 return "unknown";
125 }
126 #endif
127
128 /* This table classifies Unicode characters according to the Microsoft
129 * Unicode subset numbering. This is based on the table in "Developing
130 * International Software for Windows 95 and Windows NT". This is almost,
131 * but not quite, the same as the official Unicode block table in
132 * Blocks.txt from ftp.unicode.org. The bit number field is the bitfield
133 * number as in the FONTSIGNATURE struct's fsUsb field.
134 * There are some grave bugs in the table in the books. For instance
135 * it claims there are Hangul at U+3400..U+4DFF while this range in
136 * fact contains CJK Unified Ideographs Extension A. Also, the whole
137 * block of Hangul Syllables U+AC00..U+D7A3 is missing from the book.
138 */
139
140 typedef enum
141 {
142 U_BASIC_LATIN = 0,
143 U_LATIN_1_SUPPLEMENT = 1,
144 U_LATIN_EXTENDED_A = 2,
145 U_LATIN_EXTENDED_B = 3,
146 U_IPA_EXTENSIONS = 4,
147 U_SPACING_MODIFIER_LETTERS = 5,
148 U_COMBINING_DIACRITICAL_MARKS = 6,
149 U_BASIC_GREEK = 7,
150 U_GREEK_SYMBOLS_AND_COPTIC = 8,
151 U_CYRILLIC = 9,
152 U_ARMENIAN = 10,
153 U_HEBREW_EXTENDED = 12,
154 U_BASIC_HEBREW = 11,
155 U_BASIC_ARABIC = 13,
156 U_ARABIC_EXTENDED = 14,
157 U_DEVANAGARI = 15,
158 U_BENGALI = 16,
159 U_GURMUKHI = 17,
160 U_GUJARATI = 18,
161 U_ORIYA = 19,
162 U_TAMIL = 20,
163 U_TELUGU = 21,
164 U_KANNADA = 22,
165 U_MALAYALAM = 23,
166 U_THAI = 24,
167 U_LAO = 25,
168 U_GEORGIAN_EXTENDED = 27,
169 U_BASIC_GEORGIAN = 26,
170 U_HANGUL_JAMO = 28,
171 U_LATIN_EXTENDED_ADDITIONAL = 29,
172 U_GREEK_EXTENDED = 30,
173 U_GENERAL_PUNCTUATION = 31,
174 U_SUPERSCRIPTS_AND_SUBSCRIPTS = 32,
175 U_CURRENCY_SYMBOLS = 33,
176 U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS = 34,
177 U_LETTERLIKE_SYMBOLS = 35,
178 U_NUMBER_FORMS = 36,
179 U_ARROWS = 37,
180 U_MATHEMATICAL_OPERATORS = 38,
181 U_MISCELLANEOUS_TECHNICAL = 39,
182 U_CONTROL_PICTURES = 40,
183 U_OPTICAL_CHARACTER_RECOGNITION = 41,
184 U_ENCLOSED_ALPHANUMERICS = 42,
185 U_BOX_DRAWING = 43,
186 U_BLOCK_ELEMENTS = 44,
187 U_GEOMETRIC_SHAPES = 45,
188 U_MISCELLANEOUS_SYMBOLS = 46,
189 U_DINGBATS = 47,
190 U_CJK_SYMBOLS_AND_PUNCTUATION = 48,
191 U_HIRAGANA = 49,
192 U_KATAKANA = 50,
193 U_BOPOMOFO = 51,
194 U_HANGUL_COMPATIBILITY_JAMO = 52,
195 U_CJK_MISCELLANEOUS = 53,
196 U_ENCLOSED_CJK = 54,
197 U_CJK_COMPATIBILITY = 55,
198 U_HANGUL = 56,
199 U_HANGUL_SUPPLEMENTARY_A = 57,
200 U_HANGUL_SUPPLEMENTARY_B = 58,
201 U_CJK_UNIFIED_IDEOGRAPHS = 59,
202 U_PRIVATE_USE_AREA = 60,
203 U_CJK_COMPATIBILITY_IDEOGRAPHS = 61,
204 U_ALPHABETIC_PRESENTATION_FORMS = 62,
205 U_ARABIC_PRESENTATION_FORMS_A = 63,
206 U_COMBINING_HALF_MARKS = 64,
207 U_CJK_COMPATIBILITY_FORMS = 65,
208 U_SMALL_FORM_VARIANTS = 66,
209 U_ARABIC_PRESENTATION_FORMS_B = 67,
210 U_SPECIALS = 69,
211 U_HALFWIDTH_AND_FULLWIDTH_FORMS = 68,
212 U_LAST_PLUS_ONE
213 } unicode_subset;
214
215 static struct {
216 wchar_t low, high;
217 unicode_subset bit;
218 gchar *name;
219 } utab[] =
220 {
221 { 0x0000, 0x007E,
222 U_BASIC_LATIN, "Basic Latin" },
223 { 0x00A0, 0x00FF,
224 U_LATIN_1_SUPPLEMENT, "Latin-1 Supplement" },
225 { 0x0100, 0x017F,
226 U_LATIN_EXTENDED_A, "Latin Extended-A" },
227 { 0x0180, 0x024F,
228 U_LATIN_EXTENDED_B, "Latin Extended-B" },
229 { 0x0250, 0x02AF,
230 U_IPA_EXTENSIONS, "IPA Extensions" },
231 { 0x02B0, 0x02FF,
232 U_SPACING_MODIFIER_LETTERS, "Spacing Modifier Letters" },
233 { 0x0300, 0x036F,
234 U_COMBINING_DIACRITICAL_MARKS, "Combining Diacritical Marks" },
235 { 0x0370, 0x03CF,
236 U_BASIC_GREEK, "Basic Greek" },
237 { 0x03D0, 0x03FF,
238 U_GREEK_SYMBOLS_AND_COPTIC, "Greek Symbols and Coptic" },
239 { 0x0400, 0x04FF,
240 U_CYRILLIC, "Cyrillic" },
241 { 0x0530, 0x058F,
242 U_ARMENIAN, "Armenian" },
243 { 0x0590, 0x05CF,
244 U_HEBREW_EXTENDED, "Hebrew Extended" },
245 { 0x05D0, 0x05FF,
246 U_BASIC_HEBREW, "Basic Hebrew" },
247 { 0x0600, 0x0652,
248 U_BASIC_ARABIC, "Basic Arabic" },
249 { 0x0653, 0x06FF,
250 U_ARABIC_EXTENDED, "Arabic Extended" },
251 { 0x0900, 0x097F,
252 U_DEVANAGARI, "Devanagari" },
253 { 0x0980, 0x09FF,
254 U_BENGALI, "Bengali" },
255 { 0x0A00, 0x0A7F,
256 U_GURMUKHI, "Gurmukhi" },
257 { 0x0A80, 0x0AFF,
258 U_GUJARATI, "Gujarati" },
259 { 0x0B00, 0x0B7F,
260 U_ORIYA, "Oriya" },
261 { 0x0B80, 0x0BFF,
262 U_TAMIL, "Tamil" },
263 { 0x0C00, 0x0C7F,
264 U_TELUGU, "Telugu" },
265 { 0x0C80, 0x0CFF,
266 U_KANNADA, "Kannada" },
267 { 0x0D00, 0x0D7F,
268 U_MALAYALAM, "Malayalam" },
269 { 0x0E00, 0x0E7F,
270 U_THAI, "Thai" },
271 { 0x0E80, 0x0EFF,
272 U_LAO, "Lao" },
273 { 0x10A0, 0x10CF,
274 U_GEORGIAN_EXTENDED, "Georgian Extended" },
275 { 0x10D0, 0x10FF,
276 U_BASIC_GEORGIAN, "Basic Georgian" },
277 { 0x1100, 0x11FF,
278 U_HANGUL_JAMO, "Hangul Jamo" },
279 { 0x1E00, 0x1EFF,
280 U_LATIN_EXTENDED_ADDITIONAL, "Latin Extended Additional" },
281 { 0x1F00, 0x1FFF,
282 U_GREEK_EXTENDED, "Greek Extended" },
283 { 0x2000, 0x206F,
284 U_GENERAL_PUNCTUATION, "General Punctuation" },
285 { 0x2070, 0x209F,
286 U_SUPERSCRIPTS_AND_SUBSCRIPTS, "Superscripts and Subscripts" },
287 { 0x20A0, 0x20CF,
288 U_CURRENCY_SYMBOLS, "Currency Symbols" },
289 { 0x20D0, 0x20FF,
290 U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS, "Combining Diacritical Marks for Symbols" },
291 { 0x2100, 0x214F,
292 U_LETTERLIKE_SYMBOLS, "Letterlike Symbols" },
293 { 0x2150, 0x218F,
294 U_NUMBER_FORMS, "Number Forms" },
295 { 0x2190, 0x21FF,
296 U_ARROWS, "Arrows" },
297 { 0x2200, 0x22FF,
298 U_MATHEMATICAL_OPERATORS, "Mathematical Operators" },
299 { 0x2300, 0x23FF,
300 U_MISCELLANEOUS_TECHNICAL, "Miscellaneous Technical" },
301 { 0x2400, 0x243F,
302 U_CONTROL_PICTURES, "Control Pictures" },
303 { 0x2440, 0x245F,
304 U_OPTICAL_CHARACTER_RECOGNITION, "Optical Character Recognition" },
305 { 0x2460, 0x24FF,
306 U_ENCLOSED_ALPHANUMERICS, "Enclosed Alphanumerics" },
307 { 0x2500, 0x257F,
308 U_BOX_DRAWING, "Box Drawing" },
309 { 0x2580, 0x259F,
310 U_BLOCK_ELEMENTS, "Block Elements" },
311 { 0x25A0, 0x25FF,
312 U_GEOMETRIC_SHAPES, "Geometric Shapes" },
313 { 0x2600, 0x26FF,
314 U_MISCELLANEOUS_SYMBOLS, "Miscellaneous Symbols" },
315 { 0x2700, 0x27BF,
316 U_DINGBATS, "Dingbats" },
317 { 0x3000, 0x303F,
318 U_CJK_SYMBOLS_AND_PUNCTUATION, "CJK Symbols and Punctuation" },
319 { 0x3040, 0x309F,
320 U_HIRAGANA, "Hiragana" },
321 { 0x30A0, 0x30FF,
322 U_KATAKANA, "Katakana" },
323 { 0x3100, 0x312F,
324 U_BOPOMOFO, "Bopomofo" },
325 { 0x3130, 0x318F,
326 U_HANGUL_COMPATIBILITY_JAMO, "Hangul Compatibility Jamo" },
327 { 0x3190, 0x319F,
328 U_CJK_MISCELLANEOUS, "CJK Miscellaneous" },
329 { 0x3200, 0x32FF,
330 U_ENCLOSED_CJK, "Enclosed CJK" },
331 { 0x3300, 0x33FF,
332 U_CJK_COMPATIBILITY, "CJK Compatibility" },
333 /* The book claims:
334 * U+3400..U+3D2D = Hangul
335 * U+3D2E..U+44B7 = Hangul Supplementary A
336 * U+44B8..U+4DFF = Hangul Supplementary B
337 * but actually in Unicode
338 * U+3400..U+4DB5 = CJK Unified Ideographs Extension A
339 */
340 { 0x3400, 0x4DB5,
341 U_CJK_UNIFIED_IDEOGRAPHS, "CJK Unified Ideographs Extension A" },
342 { 0x4E00, 0x9FFF,
343 U_CJK_UNIFIED_IDEOGRAPHS, "CJK Unified Ideographs" },
344 /* This was missing completely from the book's table. */
345 { 0xAC00, 0xD7A3,
346 U_HANGUL, "Hangul Syllables" },
347 { 0xE000, 0xF8FF,
348 U_PRIVATE_USE_AREA, "Private Use Area" },
349 { 0xF900, 0xFAFF,
350 U_CJK_COMPATIBILITY_IDEOGRAPHS, "CJK Compatibility Ideographs" },
351 { 0xFB00, 0xFB4F,
352 U_ALPHABETIC_PRESENTATION_FORMS, "Alphabetic Presentation Forms" },
353 { 0xFB50, 0xFDFF,
354 U_ARABIC_PRESENTATION_FORMS_A, "Arabic Presentation Forms-A" },
355 { 0xFE20, 0xFE2F,
356 U_COMBINING_HALF_MARKS, "Combining Half Marks" },
357 { 0xFE30, 0xFE4F,
358 U_CJK_COMPATIBILITY_FORMS, "CJK Compatibility Forms" },
359 { 0xFE50, 0xFE6F,
360 U_SMALL_FORM_VARIANTS, "Small Form Variants" },
361 { 0xFE70, 0xFEFE,
362 U_ARABIC_PRESENTATION_FORMS_B, "Arabic Presentation Forms-B" },
363 { 0xFEFF, 0xFEFF,
364 U_SPECIALS, "Specials" },
365 { 0xFF00, 0xFFEF,
366 U_HALFWIDTH_AND_FULLWIDTH_FORMS, "Halfwidth and Fullwidth Forms" },
367 { 0xFFF0, 0xFFFD,
368 U_SPECIALS, "Specials" }
369 };
370
371 #ifdef G_ENABLE_DEBUG
372 static void
print_unicode_subranges(FONTSIGNATURE * fsp)373 print_unicode_subranges (FONTSIGNATURE *fsp)
374 {
375 int i;
376 gboolean checked[G_N_ELEMENTS (utab)];
377 gboolean need_comma = FALSE;
378
379 memset (checked, 0, sizeof (checked));
380
381 for (i = 0; i < G_N_ELEMENTS (utab); i++)
382 if (!checked[i]
383 && (fsp->fsUsb[utab[i].bit/32] & (1 << (utab[i].bit % 32))))
384 {
385 g_print ("%s %s", (need_comma ? "," : ""), utab[i].name);
386 need_comma = TRUE;
387 checked[i] = TRUE;
388 }
389 if (!need_comma)
390 g_print (" none!");
391 g_print ("\n");
392 }
393 #endif
394
395 static gboolean
check_unicode_subranges(UINT charset,FONTSIGNATURE * fsp)396 check_unicode_subranges (UINT charset,
397 FONTSIGNATURE *fsp)
398 {
399 gint i;
400 gboolean retval = FALSE;
401
402 /* If the fsUsb bit array has at least one of the bits set, trust it */
403 for (i = 0; i < U_LAST_PLUS_ONE; i++)
404 if (i != U_PRIVATE_USE_AREA && (fsp->fsUsb[i/32] & (1 << (i % 32))))
405 return FALSE;
406
407 /* Otherwise, guess what subranges there should be in the font */
408 fsp->fsUsb[0] = fsp->fsUsb[1] = fsp->fsUsb[2] = fsp->fsUsb[3] = 0;
409
410 #define set_bit(bitno) (fsp->fsUsb[(bitno)/32] |= (1 << ((bitno) % 32)))
411
412 /* Set Unicode subrange bits based on code pages supported.
413 * This is mostly just guesswork.
414 */
415
416 #define check_cp(bit) (fsp->fsCsb[0] & (bit))
417
418 if (check_cp(FS_LATIN1))
419 {
420 set_bit (U_BASIC_LATIN);
421 set_bit (U_LATIN_1_SUPPLEMENT);
422 set_bit (U_CURRENCY_SYMBOLS);
423 retval = TRUE;
424 }
425 if (check_cp (FS_LATIN2))
426 {
427 set_bit (U_BASIC_LATIN);
428 set_bit (U_LATIN_1_SUPPLEMENT);
429 set_bit (U_LATIN_EXTENDED_A);
430 set_bit (U_CURRENCY_SYMBOLS);
431 retval = TRUE;
432 }
433 if (check_cp (FS_CYRILLIC))
434 {
435 set_bit (U_BASIC_LATIN);
436 set_bit (U_CYRILLIC);
437 retval = TRUE;
438 }
439 if (check_cp (FS_GREEK))
440 {
441 set_bit (U_BASIC_LATIN);
442 set_bit (U_BASIC_GREEK);
443 retval = TRUE;
444 }
445 if (check_cp (FS_TURKISH))
446 {
447 set_bit (U_BASIC_LATIN);
448 set_bit (U_LATIN_1_SUPPLEMENT);
449 set_bit (U_LATIN_EXTENDED_A);
450 set_bit (U_CURRENCY_SYMBOLS);
451 retval = TRUE;
452 }
453 if (check_cp (FS_HEBREW))
454 {
455 set_bit (U_BASIC_LATIN);
456 set_bit (U_CURRENCY_SYMBOLS);
457 set_bit (U_BASIC_HEBREW);
458 set_bit (U_HEBREW_EXTENDED);
459 retval = TRUE;
460 }
461 if (check_cp (FS_ARABIC))
462 {
463 set_bit (U_BASIC_LATIN);
464 set_bit (U_CURRENCY_SYMBOLS);
465 set_bit (U_BASIC_ARABIC);
466 set_bit (U_ARABIC_EXTENDED);
467 retval = TRUE;
468 }
469 if (check_cp (FS_BALTIC))
470 {
471 set_bit (U_BASIC_LATIN);
472 set_bit (U_LATIN_1_SUPPLEMENT);
473 set_bit (U_CURRENCY_SYMBOLS);
474 set_bit (U_LATIN_EXTENDED_A);
475 set_bit (U_LATIN_EXTENDED_B);
476 retval = TRUE;
477 }
478 if (check_cp (FS_VIETNAMESE))
479 {
480 /* ??? */
481 set_bit (U_BASIC_LATIN);
482 retval = TRUE;
483 }
484 if (check_cp (FS_THAI))
485 {
486 set_bit (U_BASIC_LATIN);
487 set_bit (U_THAI);
488 retval = TRUE;
489 }
490 if (check_cp (FS_JISJAPAN))
491 {
492 /* Based on MS Gothic */
493 set_bit (U_BASIC_LATIN);
494 set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
495 set_bit (U_HIRAGANA);
496 set_bit (U_KATAKANA);
497 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
498 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
499 retval = TRUE;
500 }
501 if (check_cp (FS_CHINESESIMP))
502 {
503 /* Based on MS Hei */
504 set_bit (U_BASIC_LATIN);
505 set_bit (U_HIRAGANA);
506 set_bit (U_KATAKANA);
507 set_bit (U_BOPOMOFO);
508 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
509 retval = TRUE;
510 }
511 if (check_cp (FS_WANSUNG)
512 || check_cp (FS_JOHAB)) /* ??? */
513 {
514 /* Based on GulimChe. I wonder if all Korean fonts
515 * really support this large range of Unicode subranges?
516 */
517 set_bit (U_BASIC_LATIN);
518 set_bit (U_LATIN_1_SUPPLEMENT);
519 set_bit (U_LATIN_EXTENDED_A);
520 set_bit (U_SPACING_MODIFIER_LETTERS);
521 set_bit (U_BASIC_GREEK);
522 set_bit (U_CYRILLIC);
523 set_bit (U_HANGUL_JAMO);
524 set_bit (U_GENERAL_PUNCTUATION);
525 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
526 set_bit (U_CURRENCY_SYMBOLS);
527 set_bit (U_LETTERLIKE_SYMBOLS);
528 set_bit (U_NUMBER_FORMS);
529 set_bit (U_ARROWS);
530 set_bit (U_MATHEMATICAL_OPERATORS);
531 set_bit (U_MISCELLANEOUS_TECHNICAL);
532 set_bit (U_ENCLOSED_ALPHANUMERICS);
533 set_bit (U_BOX_DRAWING);
534 set_bit (U_BLOCK_ELEMENTS);
535 set_bit (U_GEOMETRIC_SHAPES);
536 set_bit (U_MISCELLANEOUS_SYMBOLS);
537 set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
538 set_bit (U_HIRAGANA);
539 set_bit (U_KATAKANA);
540 set_bit (U_HANGUL_COMPATIBILITY_JAMO);
541 set_bit (U_ENCLOSED_CJK);
542 set_bit (U_CJK_COMPATIBILITY_FORMS);
543 set_bit (U_HANGUL);
544 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
545 set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
546 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
547 retval = TRUE;
548 }
549 if (check_cp (FS_CHINESETRAD))
550 {
551 /* Based on MingLiU */
552 set_bit (U_BASIC_LATIN);
553 set_bit (U_GENERAL_PUNCTUATION);
554 set_bit (U_BOX_DRAWING);
555 set_bit (U_BLOCK_ELEMENTS);
556 set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
557 set_bit (U_BOPOMOFO);
558 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
559 set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
560 set_bit (U_SMALL_FORM_VARIANTS);
561 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
562 retval = TRUE;
563 }
564 if (check_cp (FS_SYMBOL) || charset == MAC_CHARSET)
565 {
566 /* Non-Unicode encoding, I guess. Pretend it covers
567 * the single-byte range of values.
568 */
569 set_bit (U_BASIC_LATIN);
570 set_bit (U_LATIN_1_SUPPLEMENT);
571 retval = TRUE;
572 }
573
574 if (retval)
575 return TRUE;
576
577 GDK_NOTE (MISC, g_print ("... No code page bits set!\n"));
578
579 /* Sigh. Not even any code page bits were set. Guess based on
580 * charset, then. These somewhat optimistic guesses are based on the
581 * table in Appendix M in the book "Developing ..." mentioned
582 * above.
583 */
584 switch (charset)
585 {
586 case ANSI_CHARSET:
587 set_bit (U_BASIC_LATIN);
588 set_bit (U_LATIN_1_SUPPLEMENT);
589 set_bit (U_LATIN_EXTENDED_A);
590 set_bit (U_LATIN_EXTENDED_B);
591 set_bit (U_SPACING_MODIFIER_LETTERS);
592 set_bit (U_COMBINING_DIACRITICAL_MARKS);
593 set_bit (U_GENERAL_PUNCTUATION);
594 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
595 set_bit (U_CURRENCY_SYMBOLS);
596 #if 0 /* I find this too hard to believe... */
597 set_bit (U_BASIC_GREEK);
598 set_bit (U_CYRILLIC);
599 set_bit (U_BASIC_HEBREW);
600 set_bit (U_HEBREW_EXTENDED);
601 set_bit (U_BASIC_ARABIC);
602 set_bit (U_ARABIC_EXTENDED);
603 set_bit (U_LETTERLIKE_SYMBOLS);
604 set_bit (U_NUMBER_FORMS);
605 set_bit (U_ARROWS);
606 set_bit (U_MATHEMATICAL_OPERATORS);
607 set_bit (U_MISCELLANEOUS_TECHNICAL);
608 set_bit (U_ENCLOSED_ALPHANUMERICS);
609 set_bit (U_BOX_DRAWING);
610 set_bit (U_BLOCK_ELEMENTS);
611 set_bit (U_GEOMETRIC_SHAPES);
612 set_bit (U_MISCELLANEOUS_SYMBOLS);
613 set_bit (U_HIRAGANA);
614 set_bit (U_KATAKANA);
615 set_bit (U_BOPOMOFO);
616 set_bit (U_HANGUL_COMPATIBILITY_JAMO);
617 set_bit (U_CJK_MISCELLANEOUS);
618 set_bit (U_CJK_COMPATIBILITY);
619 set_bit (U_HANGUL);
620 set_bit (U_HANGUL_SUPPLEMENTARY_A);
621 set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
622 set_bit (U_ALPHABETIC_PRESENTATION_FORMS);
623 set_bit (U_SMALL_FORM_VARIANTS);
624 set_bit (U_ARABIC_PRESENTATION_FORMS_B);
625 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
626 set_bit (U_SPECIALS);
627 #endif
628 retval = TRUE;
629 break;
630 case SYMBOL_CHARSET:
631 /* Unggh */
632 set_bit (U_BASIC_LATIN);
633 set_bit (U_LATIN_1_SUPPLEMENT);
634 retval = TRUE;
635 break;
636 case SHIFTJIS_CHARSET:
637 case HANGEUL_CHARSET:
638 case GB2312_CHARSET:
639 case CHINESEBIG5_CHARSET:
640 case JOHAB_CHARSET:
641 /* The table really does claim these "locales" (it doesn't
642 * talk about charsets per se) cover the same Unicode
643 * subranges
644 */
645 set_bit (U_BASIC_LATIN);
646 set_bit (U_LATIN_1_SUPPLEMENT);
647 set_bit (U_LATIN_EXTENDED_A);
648 set_bit (U_LATIN_EXTENDED_B);
649 set_bit (U_SPACING_MODIFIER_LETTERS);
650 set_bit (U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS);
651 set_bit (U_BASIC_GREEK);
652 set_bit (U_CYRILLIC);
653 set_bit (U_HANGUL_JAMO);
654 set_bit (U_GENERAL_PUNCTUATION);
655 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
656 set_bit (U_CURRENCY_SYMBOLS);
657 set_bit (U_LETTERLIKE_SYMBOLS);
658 set_bit (U_NUMBER_FORMS);
659 set_bit (U_ARROWS);
660 set_bit (U_MATHEMATICAL_OPERATORS);
661 set_bit (U_MISCELLANEOUS_TECHNICAL);
662 set_bit (U_ENCLOSED_ALPHANUMERICS);
663 set_bit (U_BOX_DRAWING);
664 set_bit (U_BLOCK_ELEMENTS);
665 set_bit (U_GEOMETRIC_SHAPES);
666 set_bit (U_MISCELLANEOUS_SYMBOLS);
667 set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
668 set_bit (U_HIRAGANA);
669 set_bit (U_KATAKANA);
670 set_bit (U_BOPOMOFO);
671 set_bit (U_HANGUL_COMPATIBILITY_JAMO);
672 set_bit (U_CJK_MISCELLANEOUS);
673 set_bit (U_CJK_COMPATIBILITY);
674 set_bit (U_HANGUL);
675 set_bit (U_HANGUL_SUPPLEMENTARY_A);
676 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
677 set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
678 set_bit (U_ALPHABETIC_PRESENTATION_FORMS);
679 set_bit (U_SMALL_FORM_VARIANTS);
680 set_bit (U_ARABIC_PRESENTATION_FORMS_B);
681 set_bit (U_SPECIALS);
682 retval = TRUE;
683 break;
684 case HEBREW_CHARSET:
685 set_bit (U_BASIC_LATIN);
686 set_bit (U_LATIN_1_SUPPLEMENT);
687 set_bit (U_LATIN_EXTENDED_B);
688 set_bit (U_SPACING_MODIFIER_LETTERS);
689 set_bit (U_BASIC_HEBREW);
690 set_bit (U_HEBREW_EXTENDED);
691 set_bit (U_GENERAL_PUNCTUATION);
692 set_bit (U_LETTERLIKE_SYMBOLS);
693 retval = TRUE;
694 break;
695 case ARABIC_CHARSET:
696 set_bit (U_BASIC_LATIN);
697 set_bit (U_LATIN_1_SUPPLEMENT);
698 set_bit (U_LATIN_EXTENDED_A);
699 set_bit (U_LATIN_EXTENDED_B);
700 set_bit (U_SPACING_MODIFIER_LETTERS);
701 set_bit (U_BASIC_GREEK);
702 set_bit (U_BASIC_ARABIC);
703 set_bit (U_ARABIC_EXTENDED);
704 set_bit (U_GENERAL_PUNCTUATION);
705 set_bit (U_LETTERLIKE_SYMBOLS);
706 set_bit (U_ARROWS);
707 set_bit (U_MATHEMATICAL_OPERATORS);
708 set_bit (U_MISCELLANEOUS_TECHNICAL);
709 set_bit (U_BOX_DRAWING);
710 set_bit (U_BLOCK_ELEMENTS);
711 set_bit (U_GEOMETRIC_SHAPES);
712 set_bit (U_MISCELLANEOUS_SYMBOLS);
713 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
714 retval = TRUE;
715 break;
716 case GREEK_CHARSET:
717 set_bit (U_BASIC_LATIN);
718 set_bit (U_LATIN_1_SUPPLEMENT);
719 set_bit (U_LATIN_EXTENDED_B);
720 set_bit (U_BASIC_GREEK);
721 set_bit (U_GENERAL_PUNCTUATION);
722 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
723 set_bit (U_LETTERLIKE_SYMBOLS);
724 set_bit (U_ARROWS);
725 set_bit (U_MATHEMATICAL_OPERATORS);
726 set_bit (U_MISCELLANEOUS_TECHNICAL);
727 set_bit (U_BOX_DRAWING);
728 set_bit (U_BLOCK_ELEMENTS);
729 set_bit (U_GEOMETRIC_SHAPES);
730 set_bit (U_MISCELLANEOUS_SYMBOLS);
731 retval = TRUE;
732 break;
733 case TURKISH_CHARSET:
734 set_bit (U_BASIC_LATIN);
735 set_bit (U_LATIN_1_SUPPLEMENT);
736 set_bit (U_LATIN_EXTENDED_A);
737 set_bit (U_LATIN_EXTENDED_B);
738 set_bit (U_SPACING_MODIFIER_LETTERS);
739 set_bit (U_BASIC_GREEK);
740 set_bit (U_GENERAL_PUNCTUATION);
741 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
742 set_bit (U_CURRENCY_SYMBOLS);
743 set_bit (U_LETTERLIKE_SYMBOLS);
744 set_bit (U_ARROWS);
745 set_bit (U_MATHEMATICAL_OPERATORS);
746 set_bit (U_MISCELLANEOUS_TECHNICAL);
747 set_bit (U_BOX_DRAWING);
748 set_bit (U_BLOCK_ELEMENTS);
749 set_bit (U_GEOMETRIC_SHAPES);
750 set_bit (U_MISCELLANEOUS_SYMBOLS);
751 retval = TRUE;
752 break;
753 case VIETNAMESE_CHARSET:
754 case THAI_CHARSET:
755 /* These are not in the table, so I have no idea */
756 break;
757 case BALTIC_CHARSET:
758 set_bit (U_BASIC_LATIN);
759 set_bit (U_LATIN_1_SUPPLEMENT);
760 set_bit (U_LATIN_EXTENDED_A);
761 set_bit (U_LATIN_EXTENDED_B);
762 set_bit (U_SPACING_MODIFIER_LETTERS);
763 set_bit (U_BASIC_GREEK);
764 set_bit (U_GENERAL_PUNCTUATION);
765 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
766 set_bit (U_CURRENCY_SYMBOLS);
767 set_bit (U_LETTERLIKE_SYMBOLS);
768 set_bit (U_ARROWS);
769 set_bit (U_MATHEMATICAL_OPERATORS);
770 set_bit (U_MISCELLANEOUS_TECHNICAL);
771 set_bit (U_BOX_DRAWING);
772 set_bit (U_BLOCK_ELEMENTS);
773 set_bit (U_GEOMETRIC_SHAPES);
774 set_bit (U_MISCELLANEOUS_SYMBOLS);
775 retval = TRUE;
776 break;
777 case EASTEUROPE_CHARSET:
778 set_bit (U_BASIC_LATIN);
779 set_bit (U_LATIN_1_SUPPLEMENT);
780 set_bit (U_LATIN_EXTENDED_A);
781 set_bit (U_LATIN_EXTENDED_B);
782 set_bit (U_SPACING_MODIFIER_LETTERS);
783 set_bit (U_BASIC_GREEK);
784 set_bit (U_GENERAL_PUNCTUATION);
785 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
786 set_bit (U_CURRENCY_SYMBOLS);
787 set_bit (U_LETTERLIKE_SYMBOLS);
788 set_bit (U_ARROWS);
789 set_bit (U_MATHEMATICAL_OPERATORS);
790 set_bit (U_MISCELLANEOUS_TECHNICAL);
791 set_bit (U_BOX_DRAWING);
792 set_bit (U_BLOCK_ELEMENTS);
793 set_bit (U_GEOMETRIC_SHAPES);
794 set_bit (U_MISCELLANEOUS_SYMBOLS);
795 retval = TRUE;
796 break;
797 case RUSSIAN_CHARSET:
798 set_bit (U_BASIC_LATIN);
799 set_bit (U_LATIN_1_SUPPLEMENT);
800 set_bit (U_CYRILLIC);
801 set_bit (U_GENERAL_PUNCTUATION);
802 set_bit (U_LETTERLIKE_SYMBOLS);
803 set_bit (U_ARROWS);
804 set_bit (U_MATHEMATICAL_OPERATORS);
805 set_bit (U_MISCELLANEOUS_TECHNICAL);
806 set_bit (U_BOX_DRAWING);
807 set_bit (U_BLOCK_ELEMENTS);
808 set_bit (U_GEOMETRIC_SHAPES);
809 set_bit (U_MISCELLANEOUS_SYMBOLS);
810 retval = TRUE;
811 break;
812 }
813
814 #undef set_bit
815 return retval;
816 }
817
818 static GdkWin32SingleFont *
gdk_font_load_logfont(LOGFONT * lfp)819 gdk_font_load_logfont (LOGFONT *lfp)
820 {
821 GdkWin32SingleFont *singlefont;
822 HFONT hfont;
823 LOGFONT logfont;
824 CHARSETINFO csi;
825 HGDIOBJ oldfont;
826 int tries;
827 gchar face[100];
828
829 for (tries = 0; ; tries++)
830 {
831 GDK_NOTE (MISC, g_print ("... trying %ld,%ld,%ld,%ld,"
832 "%ld,%d,%d,%d,"
833 "%d,%d,%d,"
834 "%d,%#.02x,\"%s\"\n",
835 lfp->lfHeight, lfp->lfWidth,
836 lfp->lfEscapement, lfp->lfOrientation,
837 lfp->lfWeight, lfp->lfItalic,
838 lfp->lfUnderline, lfp->lfStrikeOut,
839 lfp->lfCharSet,
840 lfp->lfOutPrecision, lfp->lfClipPrecision,
841 lfp->lfQuality, lfp->lfPitchAndFamily,
842 lfp->lfFaceName));
843 hfont = CreateFontIndirect (lfp);
844
845 if (hfont != NULL)
846 break;
847
848 /* If we fail, try some similar fonts often found on Windows. */
849 if (tries == 0)
850 {
851 if (g_ascii_strcasecmp (lfp->lfFaceName, "helvetica") == 0)
852 strcpy (lfp->lfFaceName, "arial");
853 else if (g_ascii_strcasecmp (lfp->lfFaceName, "new century schoolbook") == 0)
854 strcpy (lfp->lfFaceName, "century schoolbook");
855 else if (g_ascii_strcasecmp (lfp->lfFaceName, "courier") == 0)
856 strcpy (lfp->lfFaceName, "courier new");
857 else if (g_ascii_strcasecmp (lfp->lfFaceName, "lucida") == 0)
858 strcpy (lfp->lfFaceName, "lucida sans unicode");
859 else if (g_ascii_strcasecmp (lfp->lfFaceName, "lucidatypewriter") == 0)
860 strcpy (lfp->lfFaceName, "lucida console");
861 else if (g_ascii_strcasecmp (lfp->lfFaceName, "times") == 0)
862 strcpy (lfp->lfFaceName, "times new roman");
863 }
864 else if (tries == 1)
865 {
866 if (g_ascii_strcasecmp (lfp->lfFaceName, "courier") == 0)
867 {
868 strcpy (lfp->lfFaceName, "");
869 lfp->lfPitchAndFamily |= FF_MODERN;
870 }
871 else if (g_ascii_strcasecmp (lfp->lfFaceName, "times new roman") == 0)
872 {
873 strcpy (lfp->lfFaceName, "");
874 lfp->lfPitchAndFamily |= FF_ROMAN;
875 }
876 else if (g_ascii_strcasecmp (lfp->lfFaceName, "helvetica") == 0
877 || g_ascii_strcasecmp (lfp->lfFaceName, "lucida") == 0)
878 {
879 strcpy (lfp->lfFaceName, "");
880 lfp->lfPitchAndFamily |= FF_SWISS;
881 }
882 else
883 {
884 strcpy (lfp->lfFaceName, "");
885 lfp->lfPitchAndFamily = (lfp->lfPitchAndFamily & 0x0F) | FF_DONTCARE;
886 }
887 }
888 else
889 break;
890 tries++;
891 }
892
893 if (!hfont)
894 return NULL;
895
896 singlefont = g_new (GdkWin32SingleFont, 1);
897 singlefont->hfont = hfont;
898 GetObject (singlefont->hfont, sizeof (logfont), &logfont);
899 oldfont = SelectObject (_gdk_display_hdc, singlefont->hfont);
900 memset (&singlefont->fs, 0, sizeof (singlefont->fs));
901 singlefont->charset = GetTextCharsetInfo (_gdk_display_hdc, &singlefont->fs, 0);
902 GetTextFace (_gdk_display_hdc, sizeof (face), face);
903 SelectObject (_gdk_display_hdc, oldfont);
904 if (TranslateCharsetInfo ((DWORD *) (gintptr) singlefont->charset, &csi,
905 TCI_SRCCHARSET)
906 && singlefont->charset != MAC_CHARSET)
907 singlefont->codepage = csi.ciACP;
908 else
909 singlefont->codepage = 0;
910
911 GDK_NOTE (MISC, (g_print ("... = %p %s cs %s cp%d\n",
912 singlefont->hfont, face,
913 charset_name (singlefont->charset),
914 singlefont->codepage),
915 g_print ("... Unicode subranges:"),
916 print_unicode_subranges (&singlefont->fs)));
917 if (check_unicode_subranges (singlefont->charset, &singlefont->fs))
918 GDK_NOTE (MISC, (g_print ("... Guesstimated Unicode subranges:"),
919 print_unicode_subranges (&singlefont->fs)));
920
921 return singlefont;
922 }
923
924 static GdkWin32SingleFont *
gdk_font_load_internal(const gchar * font_name)925 gdk_font_load_internal (const gchar *font_name)
926 {
927 LOGFONT logfont;
928
929 char *fn;
930 int numfields, n1, n2;
931 char foundry[32], family[100], weight[32], slant[32], set_width[32],
932 spacing[32], registry[32], encoding[32];
933 char pixel_size[10], point_size[10], res_x[10], res_y[10], avg_width[10];
934 int c;
935 char *p;
936 int logpixelsy;
937
938 g_return_val_if_fail (font_name != NULL, NULL);
939
940 GDK_NOTE (MISC, g_print ("gdk_font_load_internal: %s\n", font_name));
941
942 numfields = sscanf (font_name,
943 "-%30[^-]-%100[^-]-%30[^-]-%30[^-]-%30[^-]-%n",
944 foundry,
945 family,
946 weight,
947 slant,
948 set_width,
949 &n1);
950 if (numfields == 0)
951 {
952 /* Probably a plain Windows font name */
953 logfont.lfHeight = 0;
954 logfont.lfWidth = 0;
955 logfont.lfEscapement = 0;
956 logfont.lfOrientation = 0;
957 logfont.lfWeight = FW_DONTCARE;
958 logfont.lfItalic = FALSE;
959 logfont.lfUnderline = FALSE;
960 logfont.lfStrikeOut = FALSE;
961 logfont.lfCharSet = ANSI_CHARSET;
962 logfont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
963 logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
964 logfont.lfQuality = PROOF_QUALITY;
965 logfont.lfPitchAndFamily = DEFAULT_PITCH;
966 fn = g_filename_from_utf8 (font_name, -1, NULL, NULL, NULL);
967 strcpy (logfont.lfFaceName, fn);
968 g_free (fn);
969 }
970 else if (numfields != 5)
971 {
972 g_warning ("gdk_font_load: font name %s illegal", font_name);
973 return NULL;
974 }
975 else
976 {
977 /* It must be a XLFD name */
978
979 /* Check for hex escapes in the font family,
980 * put in there by logfont_to_xlfd. Convert them in-place.
981 */
982 p = family;
983 while (*p)
984 {
985 if (*p == '%' && isxdigit (p[1]) && isxdigit (p[2]))
986 {
987 sscanf (p+1, "%2x", &c);
988 *p = c;
989 strcpy (p+1, p+3);
990 }
991 p++;
992 }
993
994 /* Skip add_style which often is empty in the requested font name */
995 while (font_name[n1] && font_name[n1] != '-')
996 n1++;
997 numfields++;
998
999 numfields += sscanf (font_name + n1,
1000 "-%8[^-]-%8[^-]-%8[^-]-%8[^-]-%30[^-]-%8[^-]-%30[^-]-%30[^-]%n",
1001 pixel_size,
1002 point_size,
1003 res_x,
1004 res_y,
1005 spacing,
1006 avg_width,
1007 registry,
1008 encoding,
1009 &n2);
1010
1011 if (numfields != 14 || font_name[n1 + n2] != '\0')
1012 {
1013 g_warning ("gdk_font_load: font name %s illegal", font_name);
1014 return NULL;
1015 }
1016
1017 logpixelsy = GetDeviceCaps (_gdk_display_hdc, LOGPIXELSY);
1018
1019 if (strcmp (pixel_size, "*") == 0)
1020 if (strcmp (point_size, "*") == 0)
1021 logfont.lfHeight = 0;
1022 else
1023 logfont.lfHeight = -(int) (((double) atoi (point_size))/720.*logpixelsy);
1024 else
1025 logfont.lfHeight = -atoi (pixel_size);
1026
1027 logfont.lfWidth = 0;
1028 logfont.lfEscapement = 0;
1029 logfont.lfOrientation = 0;
1030
1031 if (g_ascii_strcasecmp (weight, "thin") == 0)
1032 logfont.lfWeight = FW_THIN;
1033 else if (g_ascii_strcasecmp (weight, "extralight") == 0)
1034 logfont.lfWeight = FW_EXTRALIGHT;
1035 else if (g_ascii_strcasecmp (weight, "ultralight") == 0)
1036 #ifdef FW_ULTRALIGHT
1037 logfont.lfWeight = FW_ULTRALIGHT;
1038 #else
1039 logfont.lfWeight = FW_EXTRALIGHT; /* In fact, FW_ULTRALIGHT really is
1040 * defined as FW_EXTRALIGHT anyway.
1041 */
1042 #endif
1043 else if (g_ascii_strcasecmp (weight, "light") == 0)
1044 logfont.lfWeight = FW_LIGHT;
1045 else if (g_ascii_strcasecmp (weight, "normal") == 0)
1046 logfont.lfWeight = FW_NORMAL;
1047 else if (g_ascii_strcasecmp (weight, "regular") == 0)
1048 logfont.lfWeight = FW_REGULAR;
1049 else if (g_ascii_strcasecmp (weight, "medium") == 0)
1050 logfont.lfWeight = FW_MEDIUM;
1051 else if (g_ascii_strcasecmp (weight, "semibold") == 0)
1052 logfont.lfWeight = FW_SEMIBOLD;
1053 else if (g_ascii_strcasecmp (weight, "demibold") == 0)
1054 #ifdef FW_DEMIBOLD
1055 logfont.lfWeight = FW_DEMIBOLD;
1056 #else
1057 logfont.lfWeight = FW_SEMIBOLD; /* As above */
1058 #endif
1059 else if (g_ascii_strcasecmp (weight, "bold") == 0)
1060 logfont.lfWeight = FW_BOLD;
1061 else if (g_ascii_strcasecmp (weight, "extrabold") == 0)
1062 logfont.lfWeight = FW_EXTRABOLD;
1063 else if (g_ascii_strcasecmp (weight, "ultrabold") == 0)
1064 #ifdef FW_ULTRABOLD
1065 logfont.lfWeight = FW_ULTRABOLD;
1066 #else
1067 logfont.lfWeight = FW_EXTRABOLD; /* As above */
1068 #endif
1069 else if (g_ascii_strcasecmp (weight, "heavy") == 0)
1070 logfont.lfWeight = FW_HEAVY;
1071 else if (g_ascii_strcasecmp (weight, "black") == 0)
1072 #ifdef FW_BLACK
1073 logfont.lfWeight = FW_BLACK;
1074 #else
1075 logfont.lfWeight = FW_HEAVY; /* As above */
1076 #endif
1077 else
1078 logfont.lfWeight = FW_DONTCARE;
1079
1080 if (g_ascii_strcasecmp (slant, "italic") == 0
1081 || g_ascii_strcasecmp (slant, "oblique") == 0
1082 || g_ascii_strcasecmp (slant, "i") == 0
1083 || g_ascii_strcasecmp (slant, "o") == 0)
1084 logfont.lfItalic = TRUE;
1085 else
1086 logfont.lfItalic = FALSE;
1087 logfont.lfUnderline = FALSE;
1088 logfont.lfStrikeOut = FALSE;
1089 if (g_ascii_strcasecmp (registry, "iso8859") == 0)
1090 if (strcmp (encoding, "1") == 0)
1091 logfont.lfCharSet = ANSI_CHARSET;
1092 else if (strcmp (encoding, "2") == 0)
1093 logfont.lfCharSet = EASTEUROPE_CHARSET;
1094 else if (strcmp (encoding, "7") == 0)
1095 logfont.lfCharSet = GREEK_CHARSET;
1096 else if (strcmp (encoding, "8") == 0)
1097 logfont.lfCharSet = HEBREW_CHARSET;
1098 else if (strcmp (encoding, "9") == 0)
1099 logfont.lfCharSet = TURKISH_CHARSET;
1100 else
1101 logfont.lfCharSet = ANSI_CHARSET; /* XXX ??? */
1102 else if (g_ascii_strcasecmp (registry, "jisx0208.1983") == 0)
1103 logfont.lfCharSet = SHIFTJIS_CHARSET;
1104 else if (g_ascii_strcasecmp (registry, "ksc5601.1987") == 0)
1105 logfont.lfCharSet = HANGEUL_CHARSET;
1106 else if (g_ascii_strcasecmp (registry, "gb2312.1980") == 0)
1107 logfont.lfCharSet = GB2312_CHARSET;
1108 else if (g_ascii_strcasecmp (registry, "big5") == 0)
1109 logfont.lfCharSet = CHINESEBIG5_CHARSET;
1110 else if (g_ascii_strcasecmp (registry, "windows") == 0
1111 || g_ascii_strcasecmp (registry, "microsoft") == 0)
1112 if (g_ascii_strcasecmp (encoding, "symbol") == 0)
1113 logfont.lfCharSet = SYMBOL_CHARSET;
1114 else if (g_ascii_strcasecmp (encoding, "shiftjis") == 0)
1115 logfont.lfCharSet = SHIFTJIS_CHARSET;
1116 else if (g_ascii_strcasecmp (encoding, "gb2312") == 0)
1117 logfont.lfCharSet = GB2312_CHARSET;
1118 else if (g_ascii_strcasecmp (encoding, "hangeul") == 0)
1119 logfont.lfCharSet = HANGEUL_CHARSET;
1120 else if (g_ascii_strcasecmp (encoding, "big5") == 0)
1121 logfont.lfCharSet = CHINESEBIG5_CHARSET;
1122 else if (g_ascii_strcasecmp (encoding, "johab") == 0)
1123 logfont.lfCharSet = JOHAB_CHARSET;
1124 else if (g_ascii_strcasecmp (encoding, "hebrew") == 0)
1125 logfont.lfCharSet = HEBREW_CHARSET;
1126 else if (g_ascii_strcasecmp (encoding, "arabic") == 0)
1127 logfont.lfCharSet = ARABIC_CHARSET;
1128 else if (g_ascii_strcasecmp (encoding, "greek") == 0)
1129 logfont.lfCharSet = GREEK_CHARSET;
1130 else if (g_ascii_strcasecmp (encoding, "turkish") == 0)
1131 logfont.lfCharSet = TURKISH_CHARSET;
1132 else if (g_ascii_strcasecmp (encoding, "easteurope") == 0)
1133 logfont.lfCharSet = EASTEUROPE_CHARSET;
1134 else if (g_ascii_strcasecmp (encoding, "russian") == 0)
1135 logfont.lfCharSet = RUSSIAN_CHARSET;
1136 else if (g_ascii_strcasecmp (encoding, "mac") == 0)
1137 logfont.lfCharSet = MAC_CHARSET;
1138 else if (g_ascii_strcasecmp (encoding, "baltic") == 0)
1139 logfont.lfCharSet = BALTIC_CHARSET;
1140 else if (g_ascii_strcasecmp (encoding, "cp1251") == 0)
1141 logfont.lfCharSet = RUSSIAN_CHARSET;
1142 else
1143 logfont.lfCharSet = ANSI_CHARSET; /* XXX ??? */
1144 else
1145 logfont.lfCharSet = ANSI_CHARSET; /* XXX ??? */
1146 logfont.lfOutPrecision = OUT_TT_PRECIS;
1147 logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1148 logfont.lfQuality = PROOF_QUALITY;
1149 if (g_ascii_strcasecmp (spacing, "m") == 0)
1150 logfont.lfPitchAndFamily = FIXED_PITCH;
1151 else if (g_ascii_strcasecmp (spacing, "p") == 0)
1152 logfont.lfPitchAndFamily = VARIABLE_PITCH;
1153 else
1154 logfont.lfPitchAndFamily = DEFAULT_PITCH;
1155 fn = g_filename_from_utf8 (family, -1, NULL, NULL, NULL);
1156 strcpy (logfont.lfFaceName, fn);
1157 g_free (fn);
1158 }
1159
1160 return gdk_font_load_logfont (&logfont);
1161 }
1162
1163 static GdkFont *
gdk_font_from_one_singlefont(GdkWin32SingleFont * singlefont)1164 gdk_font_from_one_singlefont (GdkWin32SingleFont *singlefont)
1165 {
1166 GdkFont *font;
1167 GdkFontPrivateWin32 *private;
1168 HGDIOBJ oldfont;
1169 TEXTMETRIC textmetric;
1170
1171 private = g_new (GdkFontPrivateWin32, 1);
1172 font = (GdkFont*) private;
1173
1174 private->base.ref_count = 1;
1175 private->names = NULL;
1176 private->fonts = g_slist_append (NULL, singlefont);
1177
1178 /* Pretend all fonts are fontsets... Gtktext and gtkentry work better
1179 * that way, they use wide chars, which is necessary for non-ASCII
1180 * chars to work. (Yes, even Latin-1, as we use Unicode internally.)
1181 */
1182 font->type = GDK_FONT_FONTSET;
1183 oldfont = SelectObject (_gdk_display_hdc, singlefont->hfont);
1184 GetTextMetrics (_gdk_display_hdc, &textmetric);
1185 SelectObject (_gdk_display_hdc, oldfont);
1186 font->ascent = textmetric.tmAscent;
1187 font->descent = textmetric.tmDescent;
1188
1189 GDK_NOTE (MISC, g_print ("... asc %d desc %d\n",
1190 font->ascent, font->descent));
1191
1192 return font;
1193 }
1194
1195 GdkFont*
gdk_font_load_for_display(GdkDisplay * display,const gchar * font_name)1196 gdk_font_load_for_display (GdkDisplay *display,
1197 const gchar *font_name)
1198 {
1199 GdkFont *font;
1200 GdkFontPrivateWin32 *private;
1201 GdkWin32SingleFont *singlefont;
1202 HGDIOBJ oldfont;
1203 TEXTMETRIC textmetric;
1204
1205 g_return_val_if_fail (font_name != NULL, NULL);
1206 g_return_val_if_fail (display == gdk_display_get_default (), NULL);
1207
1208 font = gdk_font_hash_lookup (GDK_FONT_FONTSET, font_name);
1209 if (font)
1210 return font;
1211
1212 private = g_new (GdkFontPrivateWin32, 1);
1213 font = (GdkFont*) private;
1214
1215 singlefont = gdk_font_load_internal (font_name);
1216
1217 private->base.ref_count = 1;
1218 private->names = NULL;
1219 private->fonts = g_slist_append (NULL, singlefont);
1220
1221 /* Pretend all fonts are fontsets... Gtktext and gtkentry work better
1222 * that way, they use wide chars, which is necessary for non-ASCII
1223 * chars to work. (Yes, even Latin-1, as we use Unicode internally.)
1224 */
1225 font->type = GDK_FONT_FONTSET;
1226 oldfont = SelectObject (_gdk_display_hdc, singlefont->hfont);
1227 GetTextMetrics (_gdk_display_hdc, &textmetric);
1228 SelectObject (_gdk_display_hdc, oldfont);
1229 font->ascent = textmetric.tmAscent;
1230 font->descent = textmetric.tmDescent;
1231
1232 GDK_NOTE (MISC, g_print ("... asc %d desc %d\n",
1233 font->ascent, font->descent));
1234
1235 gdk_font_hash_insert (GDK_FONT_FONTSET, font, font_name);
1236
1237 return gdk_font_from_one_singlefont (gdk_font_load_internal (font_name));
1238 }
1239
1240 GdkFont*
gdk_font_from_description_for_display(GdkDisplay * display,PangoFontDescription * font_desc)1241 gdk_font_from_description_for_display (GdkDisplay *display,
1242 PangoFontDescription *font_desc)
1243 {
1244 LOGFONT logfont;
1245 int size;
1246
1247 g_return_val_if_fail (font_desc != NULL, NULL);
1248 g_return_val_if_fail (display == gdk_display_get_default (), NULL);
1249
1250 size = PANGO_PIXELS (pango_font_description_get_size (font_desc));
1251
1252 logfont.lfHeight = - MulDiv (size,
1253 GetDeviceCaps (_gdk_display_hdc, LOGPIXELSY),
1254 72);
1255 logfont.lfWidth = 0;
1256 logfont.lfEscapement = 0;
1257 logfont.lfOrientation = 0;
1258 logfont.lfWeight = FW_DONTCARE;
1259 logfont.lfItalic = FALSE;
1260 logfont.lfUnderline = FALSE;
1261 logfont.lfStrikeOut = FALSE;
1262 logfont.lfCharSet = ANSI_CHARSET;
1263 logfont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
1264 logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1265 logfont.lfQuality = PROOF_QUALITY;
1266 logfont.lfPitchAndFamily = DEFAULT_PITCH;
1267 strcpy (logfont.lfFaceName, "Arial");
1268
1269 return gdk_font_from_one_singlefont (gdk_font_load_logfont (&logfont));
1270 }
1271
1272 GdkFont*
gdk_fontset_load(const gchar * fontset_name)1273 gdk_fontset_load (const gchar *fontset_name)
1274 {
1275 GdkFont *font;
1276 GdkFontPrivateWin32 *private;
1277 GdkWin32SingleFont *singlefont;
1278 HGDIOBJ oldfont;
1279 TEXTMETRIC textmetric;
1280 gchar *fs;
1281 gchar *b, *p, *s;
1282
1283 g_return_val_if_fail (fontset_name != NULL, NULL);
1284
1285 font = gdk_font_hash_lookup (GDK_FONT_FONTSET, fontset_name);
1286 if (font)
1287 return font;
1288
1289 s = fs = g_strdup (fontset_name);
1290 while (*s && isspace (*s))
1291 s++;
1292
1293 g_return_val_if_fail (*s, NULL);
1294
1295 private = g_new (GdkFontPrivateWin32, 1);
1296 font = (GdkFont*) private;
1297
1298 private->base.ref_count = 1;
1299 private->names = NULL;
1300 private->fonts = NULL;
1301
1302 font->type = GDK_FONT_FONTSET;
1303 font->ascent = 0;
1304 font->descent = 0;
1305
1306 while (TRUE)
1307 {
1308 if ((p = strchr (s, ',')) != NULL)
1309 b = p;
1310 else
1311 b = s + strlen (s);
1312
1313 while (isspace (b[-1]))
1314 b--;
1315 *b = '\0';
1316 singlefont = gdk_font_load_internal (s);
1317 if (singlefont)
1318 {
1319 private->fonts = g_slist_append (private->fonts, singlefont);
1320 oldfont = SelectObject (_gdk_display_hdc, singlefont->hfont);
1321 GetTextMetrics (_gdk_display_hdc, &textmetric);
1322 SelectObject (_gdk_display_hdc, oldfont);
1323 font->ascent = MAX (font->ascent, textmetric.tmAscent);
1324 font->descent = MAX (font->descent, textmetric.tmDescent);
1325 }
1326 if (p)
1327 {
1328 s = p + 1;
1329 while (*s && isspace (*s))
1330 s++;
1331 }
1332 else
1333 break;
1334 if (!*s)
1335 break;
1336 }
1337
1338 g_free (fs);
1339
1340 gdk_font_hash_insert (GDK_FONT_FONTSET, font, fontset_name);
1341
1342 return font;
1343 }
1344
1345 GdkFont*
gdk_fontset_load_for_display(GdkDisplay * display,const gchar * fontset_name)1346 gdk_fontset_load_for_display (GdkDisplay *display,
1347 const gchar *fontset_name)
1348 {
1349 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1350
1351 return gdk_fontset_load (fontset_name);
1352 }
1353
1354 void
_gdk_font_destroy(GdkFont * font)1355 _gdk_font_destroy (GdkFont *font)
1356 {
1357 GdkFontPrivateWin32 *private = (GdkFontPrivateWin32 *) font;
1358 GdkWin32SingleFont *singlefont;
1359 GSList *list;
1360
1361 singlefont = (GdkWin32SingleFont *) private->fonts->data;
1362 GDK_NOTE (MISC, g_print ("_gdk_font_destroy %p\n",
1363 singlefont->hfont));
1364
1365 gdk_font_hash_remove (font->type, font);
1366
1367 switch (font->type)
1368 {
1369 case GDK_FONT_FONT:
1370 DeleteObject (singlefont->hfont);
1371 break;
1372
1373 case GDK_FONT_FONTSET:
1374 list = private->fonts;
1375 while (list)
1376 {
1377 singlefont = (GdkWin32SingleFont *) list->data;
1378 DeleteObject (singlefont->hfont);
1379
1380 list = list->next;
1381 }
1382 g_slist_free (private->fonts);
1383 break;
1384 }
1385 g_free (font);
1386 }
1387
1388 gint
_gdk_font_strlen(GdkFont * font,const gchar * str)1389 _gdk_font_strlen (GdkFont *font,
1390 const gchar *str)
1391 {
1392 g_return_val_if_fail (font != NULL, -1);
1393 g_return_val_if_fail (str != NULL, -1);
1394
1395 return strlen (str);
1396 }
1397
1398 gint
gdk_font_id(const GdkFont * font)1399 gdk_font_id (const GdkFont *font)
1400 {
1401 const GdkFontPrivateWin32 *private;
1402
1403 g_return_val_if_fail (font != NULL, 0);
1404
1405 private = (const GdkFontPrivateWin32 *) font;
1406
1407 /* FIXME: What to do on Win64? */
1408 if (font->type == GDK_FONT_FONT)
1409 return (gint) (gintptr) ((GdkWin32SingleFont *) private->fonts->data)->hfont;
1410 else
1411 return 0;
1412 }
1413
1414 gboolean
gdk_font_equal(const GdkFont * fonta,const GdkFont * fontb)1415 gdk_font_equal (const GdkFont *fonta,
1416 const GdkFont *fontb)
1417 {
1418 const GdkFontPrivateWin32 *privatea;
1419 const GdkFontPrivateWin32 *privateb;
1420
1421 g_return_val_if_fail (fonta != NULL, FALSE);
1422 g_return_val_if_fail (fontb != NULL, FALSE);
1423
1424 privatea = (const GdkFontPrivateWin32 *) fonta;
1425 privateb = (const GdkFontPrivateWin32 *) fontb;
1426
1427 if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
1428 return (((GdkWin32SingleFont *) privatea->fonts->data)->hfont
1429 == ((GdkWin32SingleFont *) privateb->fonts->data)->hfont);
1430 else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
1431 {
1432 GSList *lista = privatea->fonts;
1433 GSList *listb = privateb->fonts;
1434
1435 while (lista && listb)
1436 {
1437 if (((GdkWin32SingleFont *) lista->data)->hfont
1438 != ((GdkWin32SingleFont *) listb->data)->hfont)
1439 return FALSE;
1440 lista = lista->next;
1441 listb = listb->next;
1442 }
1443 if (lista || listb)
1444 return FALSE;
1445 else
1446 return TRUE;
1447 }
1448 else
1449 return FALSE;
1450 }
1451
1452 /* Return the Unicode Subset bitfield number for a Unicode character */
1453
1454 static int
unicode_classify(wchar_t wc)1455 unicode_classify (wchar_t wc)
1456 {
1457 int min = 0;
1458 int max = G_N_ELEMENTS (utab) - 1;
1459 int mid;
1460
1461 while (max >= min)
1462 {
1463 mid = (min + max) / 2;
1464 if (utab[mid].high < wc)
1465 min = mid + 1;
1466 else if (wc < utab[mid].low)
1467 max = mid - 1;
1468 else if (utab[mid].low <= wc && wc <= utab[mid].high)
1469 return utab[mid].bit;
1470 else
1471 break;
1472 }
1473 /* Fallback... returning -1 might cause problems. Returning
1474 * U_BASIC_LATIN won't help handling strange characters, but won't
1475 * do harm either.
1476 */
1477 return U_BASIC_LATIN;
1478 }
1479
1480 void
_gdk_wchar_text_handle(GdkFont * font,const wchar_t * wcstr,int wclen,void (* handler)(GdkWin32SingleFont *,const wchar_t *,int,void *),void * arg)1481 _gdk_wchar_text_handle (GdkFont *font,
1482 const wchar_t *wcstr,
1483 int wclen,
1484 void (*handler)(GdkWin32SingleFont *,
1485 const wchar_t *,
1486 int,
1487 void *),
1488 void *arg)
1489 {
1490 GdkFontPrivateWin32 *private;
1491 GdkWin32SingleFont *singlefont;
1492 GSList *list;
1493 int block;
1494 const wchar_t *start, *end, *wcp;
1495
1496 wcp = wcstr;
1497 end = wcp + wclen;
1498 private = (GdkFontPrivateWin32 *) font;
1499
1500 g_assert (private->base.ref_count > 0);
1501
1502 GDK_NOTE (MISC, g_print ("_gdk_wchar_text_handle: "));
1503
1504 while (wcp < end)
1505 {
1506 /* Split Unicode string into pieces of the same class */
1507 start = wcp;
1508 block = unicode_classify (*wcp);
1509 while (wcp + 1 < end && unicode_classify (wcp[1]) == block)
1510 wcp++;
1511
1512 /* Find a font in the fontset that can handle this class */
1513 list = private->fonts;
1514 while (list)
1515 {
1516 singlefont = (GdkWin32SingleFont *) list->data;
1517
1518 if (singlefont->fs.fsUsb[block/32] & (1 << (block % 32)))
1519 break;
1520
1521 list = list->next;
1522 }
1523
1524 if (!list)
1525 singlefont = NULL;
1526
1527 GDK_NOTE (MISC, g_print ("%" G_GSIZE_FORMAT ":%" G_GSIZE_FORMAT ":%d:%p ",
1528 start-wcstr, wcp-wcstr, block,
1529 (singlefont ? singlefont->hfont : 0)));
1530
1531 /* Call the callback function */
1532 (*handler) (singlefont, start, wcp+1 - start, arg);
1533 wcp++;
1534 }
1535 GDK_NOTE (MISC, g_print ("\n"));
1536 }
1537
1538 typedef struct
1539 {
1540 SIZE total;
1541 } gdk_text_size_arg;
1542
1543 static void
gdk_text_size_handler(GdkWin32SingleFont * singlefont,const wchar_t * wcstr,int wclen,void * argp)1544 gdk_text_size_handler (GdkWin32SingleFont *singlefont,
1545 const wchar_t *wcstr,
1546 int wclen,
1547 void *argp)
1548 {
1549 SIZE this_size;
1550 HGDIOBJ oldfont;
1551 gdk_text_size_arg *arg = (gdk_text_size_arg *) argp;
1552
1553 if (!singlefont)
1554 return;
1555
1556 if ((oldfont = SelectObject (_gdk_display_hdc, singlefont->hfont)) == NULL)
1557 {
1558 WIN32_GDI_FAILED ("SelectObject");
1559 return;
1560 }
1561 GetTextExtentPoint32W (_gdk_display_hdc, wcstr, wclen, &this_size);
1562 SelectObject (_gdk_display_hdc, oldfont);
1563
1564 arg->total.cx += this_size.cx;
1565 arg->total.cy = MAX (arg->total.cy, this_size.cy);
1566 }
1567
1568 gint
gdk_text_width(GdkFont * font,const gchar * text,gint text_length)1569 gdk_text_width (GdkFont *font,
1570 const gchar *text,
1571 gint text_length)
1572 {
1573 gint width = -1;
1574
1575 gdk_text_extents (font, text, text_length, NULL, NULL, &width, NULL, NULL);
1576
1577 return width;
1578 }
1579
1580 gint
gdk_text_width_wc(GdkFont * font,const GdkWChar * text,gint text_length)1581 gdk_text_width_wc (GdkFont *font,
1582 const GdkWChar *text,
1583 gint text_length)
1584 {
1585 gint width = -1;
1586
1587 gdk_text_extents_wc (font, text, text_length, NULL, NULL, &width, NULL, NULL);
1588
1589 return width;
1590 }
1591
1592 void
gdk_text_extents(GdkFont * font,const gchar * text,gint text_length,gint * lbearing,gint * rbearing,gint * width,gint * ascent,gint * descent)1593 gdk_text_extents (GdkFont *font,
1594 const gchar *text,
1595 gint text_length,
1596 gint *lbearing,
1597 gint *rbearing,
1598 gint *width,
1599 gint *ascent,
1600 gint *descent)
1601 {
1602 gdk_text_size_arg arg;
1603 glong wlen;
1604 wchar_t *wcstr, wc;
1605
1606 g_return_if_fail (font != NULL);
1607 g_return_if_fail (text != NULL);
1608
1609 if (text_length == 0)
1610 {
1611 if (lbearing)
1612 *lbearing = 0;
1613 if (rbearing)
1614 *rbearing = 0;
1615 if (width)
1616 *width = 0;
1617 if (ascent)
1618 *ascent = 0;
1619 if (descent)
1620 *descent = 0;
1621 return;
1622 }
1623
1624 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1625
1626 arg.total.cx = arg.total.cy = 0;
1627
1628 if (text_length == 1)
1629 {
1630 wc = (guchar) text[0];
1631 _gdk_wchar_text_handle (font, &wc, 1, gdk_text_size_handler, &arg);
1632 }
1633 else
1634 {
1635 wcstr = g_utf8_to_utf16 (text, text_length, NULL, &wlen, NULL);
1636 _gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, &arg);
1637 g_free (wcstr);
1638 }
1639
1640 /* XXX This is quite bogus */
1641 if (lbearing)
1642 *lbearing = 0;
1643 if (rbearing)
1644 *rbearing = arg.total.cx;
1645 /* What should be the difference between width and rbearing? */
1646 if (width)
1647 *width = arg.total.cx;
1648 if (ascent)
1649 *ascent = arg.total.cy + 1;
1650 if (descent)
1651 *descent = font->descent + 1;
1652 }
1653
1654 void
gdk_text_extents_wc(GdkFont * font,const GdkWChar * text,gint text_length,gint * lbearing,gint * rbearing,gint * width,gint * ascent,gint * descent)1655 gdk_text_extents_wc (GdkFont *font,
1656 const GdkWChar *text,
1657 gint text_length,
1658 gint *lbearing,
1659 gint *rbearing,
1660 gint *width,
1661 gint *ascent,
1662 gint *descent)
1663 {
1664 gdk_text_size_arg arg;
1665 wchar_t *wcstr;
1666 gint i;
1667
1668 g_return_if_fail (font != NULL);
1669 g_return_if_fail (text != NULL);
1670
1671 if (text_length == 0)
1672 {
1673 if (lbearing)
1674 *lbearing = 0;
1675 if (rbearing)
1676 *rbearing = 0;
1677 if (width)
1678 *width = 0;
1679 if (ascent)
1680 *ascent = 0;
1681 if (descent)
1682 *descent = 0;
1683 return;
1684 }
1685
1686 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1687
1688 if (sizeof (wchar_t) != sizeof (GdkWChar))
1689 {
1690 wcstr = g_new (wchar_t, text_length);
1691 for (i = 0; i < text_length; i++)
1692 wcstr[i] = text[i];
1693 }
1694 else
1695 wcstr = (wchar_t *) text;
1696
1697 arg.total.cx = arg.total.cy = 0;
1698
1699 _gdk_wchar_text_handle (font, wcstr, text_length,
1700 gdk_text_size_handler, &arg);
1701
1702 if (sizeof (wchar_t) != sizeof (GdkWChar))
1703 g_free (wcstr);
1704
1705 /* XXX This is quite bogus */
1706 if (lbearing)
1707 *lbearing = 0;
1708 if (rbearing)
1709 *rbearing = arg.total.cx;
1710 if (width)
1711 *width = arg.total.cx;
1712 if (ascent)
1713 *ascent = arg.total.cy + 1;
1714 if (descent)
1715 *descent = font->descent + 1;
1716 }
1717
1718 GdkDisplay*
gdk_font_get_display(GdkFont * font)1719 gdk_font_get_display (GdkFont* font)
1720 {
1721 return _gdk_display;
1722 }
1723