1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpfont.c
5 * Copyright (C) 2003 Michael Natterer <mitch@gimp.org>
6 * Sven Neumann <sven@gimp.org>
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include "config.h"
23
24 #include <gdk-pixbuf/gdk-pixbuf.h>
25 #include <gegl.h>
26
27 #include <pango/pangocairo.h>
28
29 #include <hb.h>
30 #include <hb-ot.h>
31 #include <hb-ft.h>
32
33 #define PANGO_ENABLE_ENGINE 1 /* Argh */
34 #include <pango/pango-ot.h>
35
36 #include <ft2build.h>
37 #include FT_TRUETYPE_TABLES_H
38
39 #include "text-types.h"
40
41 #include "core/gimptempbuf.h"
42
43 #include "gimpfont.h"
44
45 #include "gimp-intl.h"
46
47
48 /* This is a so-called pangram; it's supposed to
49 contain all characters found in the alphabet. */
50 #define GIMP_TEXT_PANGRAM N_("Pack my box with\nfive dozen liquor jugs.")
51
52 #define GIMP_FONT_POPUP_SIZE (PANGO_SCALE * 30)
53
54 #define DEBUGPRINT(x) /* g_print x */
55
56 enum
57 {
58 PROP_0,
59 PROP_PANGO_CONTEXT
60 };
61
62
63 struct _GimpFont
64 {
65 GimpData parent_instance;
66
67 PangoContext *pango_context;
68
69 PangoLayout *popup_layout;
70 gint popup_width;
71 gint popup_height;
72 };
73
74 struct _GimpFontClass
75 {
76 GimpDataClass parent_class;
77 };
78
79
80 static void gimp_font_constructed (GObject *object);
81 static void gimp_font_finalize (GObject *object);
82 static void gimp_font_set_property (GObject *object,
83 guint property_id,
84 const GValue *value,
85 GParamSpec *pspec);
86
87 static void gimp_font_get_preview_size (GimpViewable *viewable,
88 gint size,
89 gboolean popup,
90 gboolean dot_for_dot,
91 gint *width,
92 gint *height);
93 static gboolean gimp_font_get_popup_size (GimpViewable *viewable,
94 gint width,
95 gint height,
96 gboolean dot_for_dot,
97 gint *popup_width,
98 gint *popup_height);
99 static GimpTempBuf * gimp_font_get_new_preview (GimpViewable *viewable,
100 GimpContext *context,
101 gint width,
102 gint height);
103
104 static const gchar * gimp_font_get_sample_string (PangoContext *context,
105 PangoFontDescription *font_desc);
106
107
G_DEFINE_TYPE(GimpFont,gimp_font,GIMP_TYPE_DATA)108 G_DEFINE_TYPE (GimpFont, gimp_font, GIMP_TYPE_DATA)
109
110 #define parent_class gimp_font_parent_class
111
112
113 static void
114 gimp_font_class_init (GimpFontClass *klass)
115 {
116 GObjectClass *object_class = G_OBJECT_CLASS (klass);
117 GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
118
119 object_class->constructed = gimp_font_constructed;
120 object_class->finalize = gimp_font_finalize;
121 object_class->set_property = gimp_font_set_property;
122
123 viewable_class->get_preview_size = gimp_font_get_preview_size;
124 viewable_class->get_popup_size = gimp_font_get_popup_size;
125 viewable_class->get_new_preview = gimp_font_get_new_preview;
126
127 viewable_class->default_icon_name = "gtk-select-font";
128
129 g_object_class_install_property (object_class, PROP_PANGO_CONTEXT,
130 g_param_spec_object ("pango-context",
131 NULL, NULL,
132 PANGO_TYPE_CONTEXT,
133 GIMP_PARAM_WRITABLE));
134 }
135
136 static void
gimp_font_init(GimpFont * font)137 gimp_font_init (GimpFont *font)
138 {
139 }
140
141 static void
gimp_font_constructed(GObject * object)142 gimp_font_constructed (GObject *object)
143 {
144 G_OBJECT_CLASS (parent_class)->constructed (object);
145
146 gimp_data_make_internal (GIMP_DATA (object),
147 gimp_object_get_name (object));
148 }
149
150 static void
gimp_font_finalize(GObject * object)151 gimp_font_finalize (GObject *object)
152 {
153 GimpFont *font = GIMP_FONT (object);
154
155 g_clear_object (&font->pango_context);
156 g_clear_object (&font->popup_layout);
157
158 G_OBJECT_CLASS (parent_class)->finalize (object);
159 }
160
161 static void
gimp_font_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)162 gimp_font_set_property (GObject *object,
163 guint property_id,
164 const GValue *value,
165 GParamSpec *pspec)
166 {
167 GimpFont *font = GIMP_FONT (object);
168
169 switch (property_id)
170 {
171 case PROP_PANGO_CONTEXT:
172 if (font->pango_context)
173 g_object_unref (font->pango_context);
174 font->pango_context = g_value_dup_object (value);
175 break;
176
177 default:
178 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
179 break;
180 }
181 }
182
183 static void
gimp_font_get_preview_size(GimpViewable * viewable,gint size,gboolean popup,gboolean dot_for_dot,gint * width,gint * height)184 gimp_font_get_preview_size (GimpViewable *viewable,
185 gint size,
186 gboolean popup,
187 gboolean dot_for_dot,
188 gint *width,
189 gint *height)
190 {
191 *width = size;
192 *height = size;
193 }
194
195 static gboolean
gimp_font_get_popup_size(GimpViewable * viewable,gint width,gint height,gboolean dot_for_dot,gint * popup_width,gint * popup_height)196 gimp_font_get_popup_size (GimpViewable *viewable,
197 gint width,
198 gint height,
199 gboolean dot_for_dot,
200 gint *popup_width,
201 gint *popup_height)
202 {
203 GimpFont *font = GIMP_FONT (viewable);
204 PangoFontDescription *font_desc;
205 PangoRectangle ink;
206 PangoRectangle logical;
207 const gchar *name;
208
209 if (! font->pango_context)
210 return FALSE;
211
212 name = gimp_object_get_name (font);
213
214 font_desc = pango_font_description_from_string (name);
215 g_return_val_if_fail (font_desc != NULL, FALSE);
216
217 pango_font_description_set_size (font_desc, GIMP_FONT_POPUP_SIZE);
218
219 if (font->popup_layout)
220 g_object_unref (font->popup_layout);
221
222 font->popup_layout = pango_layout_new (font->pango_context);
223 pango_layout_set_font_description (font->popup_layout, font_desc);
224 pango_font_description_free (font_desc);
225
226 pango_layout_set_text (font->popup_layout, gettext (GIMP_TEXT_PANGRAM), -1);
227 pango_layout_get_pixel_extents (font->popup_layout, &ink, &logical);
228
229 *popup_width = MAX (ink.width, logical.width) + 6;
230 *popup_height = MAX (ink.height, logical.height) + 6;
231
232 *popup_width = cairo_format_stride_for_width (CAIRO_FORMAT_A8, *popup_width);
233
234 font->popup_width = *popup_width;
235 font->popup_height = *popup_height;
236
237 return TRUE;
238 }
239
240 static GimpTempBuf *
gimp_font_get_new_preview(GimpViewable * viewable,GimpContext * context,gint width,gint height)241 gimp_font_get_new_preview (GimpViewable *viewable,
242 GimpContext *context,
243 gint width,
244 gint height)
245 {
246 GimpFont *font = GIMP_FONT (viewable);
247 PangoLayout *layout;
248 PangoRectangle ink;
249 PangoRectangle logical;
250 gint layout_width;
251 gint layout_height;
252 gint layout_x;
253 gint layout_y;
254 GimpTempBuf *temp_buf;
255 cairo_t *cr;
256 cairo_surface_t *surface;
257
258 if (! font->pango_context)
259 return NULL;
260
261 if (! font->popup_layout ||
262 font->popup_width != width || font->popup_height != height)
263 {
264 PangoFontDescription *font_desc;
265 const gchar *name;
266
267 name = gimp_object_get_name (font);
268
269 DEBUGPRINT (("%s: ", name));
270
271 font_desc = pango_font_description_from_string (name);
272 g_return_val_if_fail (font_desc != NULL, NULL);
273
274 pango_font_description_set_size (font_desc,
275 PANGO_SCALE * height * 2.0 / 3.0);
276
277 layout = pango_layout_new (font->pango_context);
278
279 pango_layout_set_font_description (layout, font_desc);
280 pango_layout_set_text (layout,
281 gimp_font_get_sample_string (font->pango_context,
282 font_desc),
283 -1);
284
285 pango_font_description_free (font_desc);
286 }
287 else
288 {
289 layout = g_object_ref (font->popup_layout);
290 }
291
292 width = cairo_format_stride_for_width (CAIRO_FORMAT_A8, width);
293
294 temp_buf = gimp_temp_buf_new (width, height, babl_format ("Y' u8"));
295 memset (gimp_temp_buf_get_data (temp_buf), 255, width * height);
296
297 surface = cairo_image_surface_create_for_data (gimp_temp_buf_get_data (temp_buf),
298 CAIRO_FORMAT_A8,
299 width, height, width);
300
301 pango_layout_get_pixel_extents (layout, &ink, &logical);
302
303 layout_width = MAX (ink.width, logical.width);
304 layout_height = MAX (ink.height, logical.height);
305
306 layout_x = (width - layout_width) / 2;
307 layout_y = (height - layout_height) / 2;
308
309 if (ink.x < logical.x)
310 layout_x += logical.x - ink.x;
311
312 if (ink.y < logical.y)
313 layout_y += logical.y - ink.y;
314
315 cr = cairo_create (surface);
316
317 cairo_translate (cr, layout_x, layout_y);
318 cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
319 pango_cairo_show_layout (cr, layout);
320
321 cairo_destroy (cr);
322 cairo_surface_destroy (surface);
323
324 g_object_unref (layout);
325
326 return temp_buf;
327 }
328
329 GimpData *
gimp_font_get_standard(void)330 gimp_font_get_standard (void)
331 {
332 static GimpData *standard_font = NULL;
333
334 if (! standard_font)
335 {
336 standard_font = g_object_new (GIMP_TYPE_FONT,
337 "name", "Standard",
338 NULL);
339
340 gimp_data_clean (standard_font);
341 gimp_data_make_internal (standard_font, "gimp-font-standard");
342
343 g_object_add_weak_pointer (G_OBJECT (standard_font),
344 (gpointer *) &standard_font);
345 }
346
347 return standard_font;
348 }
349
350
351 static inline gboolean
gimp_font_covers_string(PangoFcFont * font,const gchar * sample)352 gimp_font_covers_string (PangoFcFont *font,
353 const gchar *sample)
354 {
355 const gchar *p;
356
357 for (p = sample; *p; p = g_utf8_next_char (p))
358 {
359 if (! pango_fc_font_has_char (font, g_utf8_get_char (p)))
360 return FALSE;
361 }
362
363 return TRUE;
364 }
365
366 /* This function was picked up from Pango's pango-ot-info.c. Until there
367 * is a better way to get the tag, we use this.
368 */
369 static hb_tag_t
get_hb_table_type(PangoOTTableType table_type)370 get_hb_table_type (PangoOTTableType table_type)
371 {
372 switch (table_type)
373 {
374 case PANGO_OT_TABLE_GSUB:
375 return HB_OT_TAG_GSUB;
376 case PANGO_OT_TABLE_GPOS:
377 return HB_OT_TAG_GPOS;
378 default:
379 return HB_TAG_NONE;
380 }
381 }
382
383 /* Guess a suitable short sample string for the font. */
384 static const gchar *
gimp_font_get_sample_string(PangoContext * context,PangoFontDescription * font_desc)385 gimp_font_get_sample_string (PangoContext *context,
386 PangoFontDescription *font_desc)
387 {
388 PangoFont *font;
389 hb_face_t *hb_face;
390 FT_Face face;
391 TT_OS2 *os2;
392 PangoOTTableType tt;
393 gint i;
394
395 /* This is a table of scripts and corresponding short sample strings
396 * to be used instead of the Latin sample string Aa. The script
397 * codes are as in ISO15924 (see
398 * https://www.unicode.org/iso15924/iso15924-codes.html), but in
399 * lower case. The Unicode subrange bit numbers, as used in TrueType
400 * so-called OS/2 tables, are from
401 * https://www.microsoft.com/typography/otspec/os2.htm#ur .
402 *
403 * The table is mostly ordered by Unicode order. But as there are
404 * fonts that support several of these scripts, the ordering is
405 * be modified so that the script which such a font is more likely
406 * to be actually designed for comes first and matches.
407 *
408 * These sample strings are mostly just guesswork as for their
409 * usefulness. Usually they contain what I assume is the first
410 * letter in the corresponding alphabet, or two first letters if the
411 * first one happens to look too "trivial" to be recognizable by
412 * itself.
413 *
414 * This table is used to determine the primary script a font has
415 * been designed for.
416 *
417 * Very useful link: https://www.wazu.jp/index.html
418 */
419 static const struct
420 {
421 const gchar script[4];
422 gint bit;
423 const gchar *sample;
424 } scripts[] = {
425 /* Han is first because fonts that support it presumably are primarily
426 * designed for it.
427 */
428 {
429 "hani", /* Han Ideographic */
430 59,
431 "\346\260\270" /* U+6C38 "forever". Ed Trager says
432 * this is a "pan-stroke" often used
433 * in teaching Chinese calligraphy. It
434 * contains the eight basic Chinese
435 * stroke forms.
436 */
437 },
438 {
439 "copt", /* Coptic */
440 7,
441 "\316\221\316\261" /* U+0410 GREEK CAPITAL LETTER ALPHA
442 U+0430 GREEK SMALL LETTER ALPHA
443 */
444 },
445 {
446 "grek", /* Greek */
447 7,
448 "\316\221\316\261" /* U+0410 GREEK CAPITAL LETTER ALPHA
449 U+0430 GREEK SMALL LETTER ALPHA
450 */
451 },
452 {
453 "cyrl", /* Cyrillic */
454 9,
455 "\320\220\325\260" /* U+0410 CYRILLIC CAPITAL LETTER A
456 U+0430 CYRILLIC SMALL LETTER A
457 */
458 },
459 {
460 "armn", /* Armenian */
461 10,
462 "\324\261\325\241" /* U+0531 ARMENIAN CAPITAL LETTER AYB
463 U+0561 ARMENIAN SMALL LETTER AYB
464 */
465 },
466 {
467 "hebr", /* Hebrew */
468 11,
469 "\327\220" /* U+05D0 HEBREW LETTER ALEF */
470 },
471 {
472 "arab", /* Arabic */
473 13,
474 "\330\247\330\250" /* U+0627 ARABIC LETTER ALEF
475 * U+0628 ARABIC LETTER BEH
476 */
477 },
478 {
479 "syrc", /* Syriac */
480 71,
481 "\334\220\334\222" /* U+0710 SYRIAC LETTER ALAPH
482 * U+0712 SYRIAC LETTER BETH
483 */
484 },
485 {
486 "thaa", /* Thaana */
487 72,
488 "\336\200\336\201" /* U+0780 THAANA LETTER HAA
489 * U+0781 THAANA LETTER SHAVIYANI
490 */
491 },
492 /* Should really use some better sample strings for the complex
493 * scripts. Something that shows how well the font handles the
494 * complex processing for each script.
495 */
496 {
497 "deva", /* Devanagari */
498 15,
499 "\340\244\205" /* U+0905 DEVANAGARI LETTER A*/
500 },
501 {
502 "beng", /* Bengali */
503 16,
504 "\340\246\205" /* U+0985 BENGALI LETTER A */
505 },
506 {
507 "guru", /* Gurmukhi */
508 17,
509 "\340\250\205" /* U+0A05 GURMUKHI LETTER A */
510 },
511 {
512 "gujr", /* Gujarati */
513 18,
514 "\340\252\205" /* U+0A85 GUJARATI LETTER A */
515 },
516 {
517 "orya", /* Oriya */
518 19,
519 "\340\254\205" /* U+0B05 ORIYA LETTER A */
520 },
521 {
522 "taml", /* Tamil */
523 20,
524 "\340\256\205" /* U+0B85 TAMIL LETTER A */
525 },
526 {
527 "telu", /* Telugu */
528 21,
529 "\340\260\205" /* U+0C05 TELUGU LETTER A */
530 },
531 {
532 "knda", /* Kannada */
533 22,
534 "\340\262\205" /* U+0C85 KANNADA LETTER A */
535 },
536 {
537 "mylm", /* Malayalam */
538 23,
539 "\340\264\205" /* U+0D05 MALAYALAM LETTER A */
540 },
541 {
542 "sinh", /* Sinhala */
543 73,
544 "\340\266\205" /* U+0D85 SINHALA LETTER AYANNA */
545 },
546 {
547 "thai", /* Thai */
548 24,
549 "\340\270\201\340\270\264"/* U+0E01 THAI CHARACTER KO KAI
550 * U+0E34 THAI CHARACTER SARA I
551 */
552 },
553 {
554 "laoo", /* Lao */
555 25,
556 "\340\272\201\340\272\264"/* U+0E81 LAO LETTER KO
557 * U+0EB4 LAO VOWEL SIGN I
558 */
559 },
560 {
561 "tibt", /* Tibetan */
562 70,
563 "\340\274\200" /* U+0F00 TIBETAN SYLLABLE OM */
564 },
565 {
566 "mymr", /* Myanmar */
567 74,
568 "\341\200\200" /* U+1000 MYANMAR LETTER KA */
569 },
570 {
571 "geor", /* Georgian */
572 26,
573 "\341\202\240\341\203\200" /* U+10A0 GEORGIAN CAPITAL LETTER AN
574 * U+10D0 GEORGIAN LETTER AN
575 */
576 },
577 {
578 "hang", /* Hangul */
579 28,
580 "\341\204\200\341\204\201"/* U+1100 HANGUL CHOSEONG KIYEOK
581 * U+1101 HANGUL CHOSEONG SSANGKIYEOK
582 */
583 },
584 {
585 "ethi", /* Ethiopic */
586 75,
587 "\341\210\200" /* U+1200 ETHIOPIC SYLLABLE HA */
588 },
589 {
590 "cher", /* Cherokee */
591 76,
592 "\341\216\243" /* U+13A3 CHEROKEE LETTER O */
593 },
594 {
595 "cans", /* Unified Canadian Aboriginal Syllabics */
596 77,
597 "\341\220\201" /* U+1401 CANADIAN SYLLABICS E */
598 },
599 {
600 "ogam", /* Ogham */
601 78,
602 "\341\232\201" /* U+1681 OGHAM LETTER BEITH */
603 },
604 {
605 "runr", /* Runic */
606 79,
607 "\341\232\240" /* U+16A0 RUNIC LETTER FEHU FEOH FE F */
608 },
609 {
610 "tglg", /* Tagalog */
611 84,
612 "\341\234\200" /* U+1700 TAGALOG LETTER A */
613 },
614 {
615 "hano", /* Hanunoo */
616 -1,
617 "\341\234\240" /* U+1720 HANUNOO LETTER A */
618 },
619 {
620 "buhd", /* Buhid */
621 -1,
622 "\341\235\200" /* U+1740 BUHID LETTER A */
623 },
624 {
625 "tagb", /* Tagbanwa */
626 -1,
627 "\341\235\240" /* U+1760 TAGBANWA LETTER A */
628 },
629 {
630 "khmr", /* Khmer */
631 80,
632 "\341\236\201\341\237\222\341\236\211\341\236\273\341\237\206"
633 /* U+1781 KHMER LETTER KHA
634 * U+17D2 KHMER LETTER SIGN COENG
635 * U+1789 KHMER LETTER NYO
636 * U+17BB KHMER VOWEL SIGN U
637 * U+17C6 KHMER SIGN NIKAHIT
638 * A common word meaning "I" that contains
639 * lots of complex processing.
640 */
641 },
642 {
643 "mong", /* Mongolian */
644 81,
645 "\341\240\240" /* U+1820 MONGOLIAN LETTER A */
646 },
647 {
648 "limb", /* Limbu */
649 -1,
650 "\341\244\201" /* U+1901 LIMBU LETTER KA */
651 },
652 {
653 "tale", /* Tai Le */
654 -1,
655 "\341\245\220" /* U+1950 TAI LE LETTER KA */
656 },
657 {
658 "latn", /* Latin */
659 0,
660 "Aa"
661 }
662 };
663
664 gint ot_alts[4];
665 gint n_ot_alts = 0;
666 gint sr_alts[20];
667 gint n_sr_alts = 0;
668
669 font = pango_context_load_font (context, font_desc);
670
671 g_return_val_if_fail (PANGO_IS_FC_FONT (font), "Aa");
672
673 face = pango_fc_font_lock_face (PANGO_FC_FONT (font));
674 g_return_val_if_fail (face != NULL, "Aa");
675 hb_face = hb_ft_face_create (face, NULL);
676
677 /* First check what script(s), if any, the font has GSUB or GPOS
678 * OpenType layout tables for.
679 */
680 for (tt = PANGO_OT_TABLE_GSUB;
681 n_ot_alts < G_N_ELEMENTS (ot_alts) && tt <= PANGO_OT_TABLE_GPOS;
682 tt++)
683 {
684 hb_tag_t tag;
685 unsigned int count;
686 PangoOTTag *slist;
687
688 tag = get_hb_table_type (tt);
689 count = hb_ot_layout_table_get_script_tags (hb_face, tag, 0, NULL, NULL);
690 slist = g_new (PangoOTTag, count + 1);
691 hb_ot_layout_table_get_script_tags (hb_face, tag, 0, &count, slist);
692 slist[count] = 0;
693
694 for (i = 0;
695 n_ot_alts < G_N_ELEMENTS (ot_alts) && i < G_N_ELEMENTS (scripts);
696 i++)
697 {
698 gint j, k;
699
700 for (k = 0; k < n_ot_alts; k++)
701 if (ot_alts[k] == i)
702 break;
703
704 if (k == n_ot_alts)
705 {
706 for (j = 0;
707 n_ot_alts < G_N_ELEMENTS (ot_alts) && slist[j];
708 j++)
709 {
710 #define TAG(s) FT_MAKE_TAG (s[0], s[1], s[2], s[3])
711
712 if (slist[j] == TAG (scripts[i].script) &&
713 gimp_font_covers_string (PANGO_FC_FONT (font),
714 scripts[i].sample))
715 {
716 ot_alts[n_ot_alts++] = i;
717 DEBUGPRINT (("%.4s ", scripts[i].script));
718 }
719 #undef TAG
720 }
721 }
722 }
723
724 g_free (slist);
725 }
726
727 hb_face_destroy (hb_face);
728
729 DEBUGPRINT (("; OS/2: "));
730
731 /* Next check the OS/2 table for Unicode ranges the font claims
732 * to cover.
733 */
734
735 os2 = FT_Get_Sfnt_Table (face, ft_sfnt_os2);
736
737 if (os2)
738 {
739 for (i = 0;
740 n_sr_alts < G_N_ELEMENTS (sr_alts) && i < G_N_ELEMENTS (scripts);
741 i++)
742 {
743 if (scripts[i].bit >= 0 &&
744 (&os2->ulUnicodeRange1)[scripts[i].bit/32] & (1 << (scripts[i].bit % 32)) &&
745 gimp_font_covers_string (PANGO_FC_FONT (font),
746 scripts[i].sample))
747 {
748 sr_alts[n_sr_alts++] = i;
749 DEBUGPRINT (("%.4s ", scripts[i].script));
750 }
751 }
752 }
753
754 pango_fc_font_unlock_face (PANGO_FC_FONT (font));
755
756 g_object_unref (font);
757
758 if (n_ot_alts > 2)
759 {
760 /* The font has OpenType tables for several scripts. If it
761 * support Basic Latin as well, use Aa.
762 */
763 gint i;
764
765 for (i = 0; i < n_sr_alts; i++)
766 if (scripts[sr_alts[i]].bit == 0)
767 {
768 DEBUGPRINT (("=> several OT, also latin, use Aa\n"));
769 return "Aa";
770 }
771 }
772
773 if (n_ot_alts > 0 && n_sr_alts >= n_ot_alts + 3)
774 {
775 /* At least one script with an OpenType table, but many more
776 * subranges than such scripts. If it supports Basic Latin,
777 * use Aa, else the highest priority subrange.
778 */
779 gint i;
780
781 for (i = 0; i < n_sr_alts; i++)
782 if (scripts[sr_alts[i]].bit == 0)
783 {
784 DEBUGPRINT (("=> several SR, also latin, use Aa\n"));
785 return "Aa";
786 }
787
788 DEBUGPRINT (("=> several SR, use %.4s\n", scripts[sr_alts[0]].script));
789 return scripts[sr_alts[0]].sample;
790 }
791
792 if (n_ot_alts > 0)
793 {
794 /* OpenType tables for at least one script, use the
795 * highest priority one
796 */
797 DEBUGPRINT (("=> at least one OT, use %.4s\n",
798 scripts[sr_alts[0]].script));
799 return scripts[ot_alts[0]].sample;
800 }
801
802 if (n_sr_alts > 0)
803 {
804 /* Use the highest priority subrange. This means that a
805 * font that supports Greek, Cyrillic and Latin (quite
806 * common), will get the Greek sample string. That is
807 * capital and lowercase alpha, which looks like capital A
808 * and lowercase alpha, so it's actually quite nice, and
809 * doesn't give a too strong impression that the font would
810 * be for Greek only.
811 */
812 DEBUGPRINT (("=> at least one SR, use %.4s\n",
813 scripts[sr_alts[0]].script));
814 return scripts[sr_alts[0]].sample;
815 }
816
817 /* Final fallback */
818 DEBUGPRINT (("=> fallback, use Aa\n"));
819 return "Aa";
820 }
821