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