summaryrefslogtreecommitdiffstats
path: root/app/text/gimpfont.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:30:19 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:30:19 +0000
commit5c1676dfe6d2f3c837a5e074117b45613fd29a72 (patch)
treecbffb45144febf451e54061db2b21395faf94bfe /app/text/gimpfont.c
parentInitial commit. (diff)
downloadgimp-63d1391ab989f6cb1b9abeaca4ec268574f16491.tar.xz
gimp-63d1391ab989f6cb1b9abeaca4ec268574f16491.zip
Adding upstream version 2.10.34.upstream/2.10.34upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'app/text/gimpfont.c')
-rw-r--r--app/text/gimpfont.c820
1 files changed, 820 insertions, 0 deletions
diff --git a/app/text/gimpfont.c b/app/text/gimpfont.c
new file mode 100644
index 0000000..23d3a60
--- /dev/null
+++ b/app/text/gimpfont.c
@@ -0,0 +1,820 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpfont.c
+ * Copyright (C) 2003 Michael Natterer <mitch@gimp.org>
+ * Sven Neumann <sven@gimp.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gegl.h>
+
+#include <pango/pangocairo.h>
+
+#include <hb.h>
+#include <hb-ot.h>
+#include <hb-ft.h>
+
+#define PANGO_ENABLE_ENGINE 1 /* Argh */
+#include <pango/pango-ot.h>
+
+#include <ft2build.h>
+#include FT_TRUETYPE_TABLES_H
+
+#include "text-types.h"
+
+#include "core/gimptempbuf.h"
+
+#include "gimpfont.h"
+
+#include "gimp-intl.h"
+
+
+/* This is a so-called pangram; it's supposed to
+ contain all characters found in the alphabet. */
+#define GIMP_TEXT_PANGRAM N_("Pack my box with\nfive dozen liquor jugs.")
+
+#define GIMP_FONT_POPUP_SIZE (PANGO_SCALE * 30)
+
+#define DEBUGPRINT(x) /* g_print x */
+
+enum
+{
+ PROP_0,
+ PROP_PANGO_CONTEXT
+};
+
+
+struct _GimpFont
+{
+ GimpData parent_instance;
+
+ PangoContext *pango_context;
+
+ PangoLayout *popup_layout;
+ gint popup_width;
+ gint popup_height;
+};
+
+struct _GimpFontClass
+{
+ GimpDataClass parent_class;
+};
+
+
+static void gimp_font_constructed (GObject *object);
+static void gimp_font_finalize (GObject *object);
+static void gimp_font_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void gimp_font_get_preview_size (GimpViewable *viewable,
+ gint size,
+ gboolean popup,
+ gboolean dot_for_dot,
+ gint *width,
+ gint *height);
+static gboolean gimp_font_get_popup_size (GimpViewable *viewable,
+ gint width,
+ gint height,
+ gboolean dot_for_dot,
+ gint *popup_width,
+ gint *popup_height);
+static GimpTempBuf * gimp_font_get_new_preview (GimpViewable *viewable,
+ GimpContext *context,
+ gint width,
+ gint height);
+
+static const gchar * gimp_font_get_sample_string (PangoContext *context,
+ PangoFontDescription *font_desc);
+
+
+G_DEFINE_TYPE (GimpFont, gimp_font, GIMP_TYPE_DATA)
+
+#define parent_class gimp_font_parent_class
+
+
+static void
+gimp_font_class_init (GimpFontClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
+
+ object_class->constructed = gimp_font_constructed;
+ object_class->finalize = gimp_font_finalize;
+ object_class->set_property = gimp_font_set_property;
+
+ viewable_class->get_preview_size = gimp_font_get_preview_size;
+ viewable_class->get_popup_size = gimp_font_get_popup_size;
+ viewable_class->get_new_preview = gimp_font_get_new_preview;
+
+ viewable_class->default_icon_name = "gtk-select-font";
+
+ g_object_class_install_property (object_class, PROP_PANGO_CONTEXT,
+ g_param_spec_object ("pango-context",
+ NULL, NULL,
+ PANGO_TYPE_CONTEXT,
+ GIMP_PARAM_WRITABLE));
+}
+
+static void
+gimp_font_init (GimpFont *font)
+{
+}
+
+static void
+gimp_font_constructed (GObject *object)
+{
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ gimp_data_make_internal (GIMP_DATA (object),
+ gimp_object_get_name (object));
+}
+
+static void
+gimp_font_finalize (GObject *object)
+{
+ GimpFont *font = GIMP_FONT (object);
+
+ g_clear_object (&font->pango_context);
+ g_clear_object (&font->popup_layout);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gimp_font_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpFont *font = GIMP_FONT (object);
+
+ switch (property_id)
+ {
+ case PROP_PANGO_CONTEXT:
+ if (font->pango_context)
+ g_object_unref (font->pango_context);
+ font->pango_context = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_font_get_preview_size (GimpViewable *viewable,
+ gint size,
+ gboolean popup,
+ gboolean dot_for_dot,
+ gint *width,
+ gint *height)
+{
+ *width = size;
+ *height = size;
+}
+
+static gboolean
+gimp_font_get_popup_size (GimpViewable *viewable,
+ gint width,
+ gint height,
+ gboolean dot_for_dot,
+ gint *popup_width,
+ gint *popup_height)
+{
+ GimpFont *font = GIMP_FONT (viewable);
+ PangoFontDescription *font_desc;
+ PangoRectangle ink;
+ PangoRectangle logical;
+ const gchar *name;
+
+ if (! font->pango_context)
+ return FALSE;
+
+ name = gimp_object_get_name (font);
+
+ font_desc = pango_font_description_from_string (name);
+ g_return_val_if_fail (font_desc != NULL, FALSE);
+
+ pango_font_description_set_size (font_desc, GIMP_FONT_POPUP_SIZE);
+
+ if (font->popup_layout)
+ g_object_unref (font->popup_layout);
+
+ font->popup_layout = pango_layout_new (font->pango_context);
+ pango_layout_set_font_description (font->popup_layout, font_desc);
+ pango_font_description_free (font_desc);
+
+ pango_layout_set_text (font->popup_layout, gettext (GIMP_TEXT_PANGRAM), -1);
+ pango_layout_get_pixel_extents (font->popup_layout, &ink, &logical);
+
+ *popup_width = MAX (ink.width, logical.width) + 6;
+ *popup_height = MAX (ink.height, logical.height) + 6;
+
+ *popup_width = cairo_format_stride_for_width (CAIRO_FORMAT_A8, *popup_width);
+
+ font->popup_width = *popup_width;
+ font->popup_height = *popup_height;
+
+ return TRUE;
+}
+
+static GimpTempBuf *
+gimp_font_get_new_preview (GimpViewable *viewable,
+ GimpContext *context,
+ gint width,
+ gint height)
+{
+ GimpFont *font = GIMP_FONT (viewable);
+ PangoLayout *layout;
+ PangoRectangle ink;
+ PangoRectangle logical;
+ gint layout_width;
+ gint layout_height;
+ gint layout_x;
+ gint layout_y;
+ GimpTempBuf *temp_buf;
+ cairo_t *cr;
+ cairo_surface_t *surface;
+
+ if (! font->pango_context)
+ return NULL;
+
+ if (! font->popup_layout ||
+ font->popup_width != width || font->popup_height != height)
+ {
+ PangoFontDescription *font_desc;
+ const gchar *name;
+
+ name = gimp_object_get_name (font);
+
+ DEBUGPRINT (("%s: ", name));
+
+ font_desc = pango_font_description_from_string (name);
+ g_return_val_if_fail (font_desc != NULL, NULL);
+
+ pango_font_description_set_size (font_desc,
+ PANGO_SCALE * height * 2.0 / 3.0);
+
+ layout = pango_layout_new (font->pango_context);
+
+ pango_layout_set_font_description (layout, font_desc);
+ pango_layout_set_text (layout,
+ gimp_font_get_sample_string (font->pango_context,
+ font_desc),
+ -1);
+
+ pango_font_description_free (font_desc);
+ }
+ else
+ {
+ layout = g_object_ref (font->popup_layout);
+ }
+
+ width = cairo_format_stride_for_width (CAIRO_FORMAT_A8, width);
+
+ temp_buf = gimp_temp_buf_new (width, height, babl_format ("Y' u8"));
+ memset (gimp_temp_buf_get_data (temp_buf), 255, width * height);
+
+ surface = cairo_image_surface_create_for_data (gimp_temp_buf_get_data (temp_buf),
+ CAIRO_FORMAT_A8,
+ width, height, width);
+
+ pango_layout_get_pixel_extents (layout, &ink, &logical);
+
+ layout_width = MAX (ink.width, logical.width);
+ layout_height = MAX (ink.height, logical.height);
+
+ layout_x = (width - layout_width) / 2;
+ layout_y = (height - layout_height) / 2;
+
+ if (ink.x < logical.x)
+ layout_x += logical.x - ink.x;
+
+ if (ink.y < logical.y)
+ layout_y += logical.y - ink.y;
+
+ cr = cairo_create (surface);
+
+ cairo_translate (cr, layout_x, layout_y);
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ pango_cairo_show_layout (cr, layout);
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+
+ g_object_unref (layout);
+
+ return temp_buf;
+}
+
+GimpData *
+gimp_font_get_standard (void)
+{
+ static GimpData *standard_font = NULL;
+
+ if (! standard_font)
+ {
+ standard_font = g_object_new (GIMP_TYPE_FONT,
+ "name", "Standard",
+ NULL);
+
+ gimp_data_clean (standard_font);
+ gimp_data_make_internal (standard_font, "gimp-font-standard");
+
+ g_object_add_weak_pointer (G_OBJECT (standard_font),
+ (gpointer *) &standard_font);
+ }
+
+ return standard_font;
+}
+
+
+static inline gboolean
+gimp_font_covers_string (PangoFcFont *font,
+ const gchar *sample)
+{
+ const gchar *p;
+
+ for (p = sample; *p; p = g_utf8_next_char (p))
+ {
+ if (! pango_fc_font_has_char (font, g_utf8_get_char (p)))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* This function was picked up from Pango's pango-ot-info.c. Until there
+ * is a better way to get the tag, we use this.
+ */
+static hb_tag_t
+get_hb_table_type (PangoOTTableType table_type)
+{
+ switch (table_type)
+ {
+ case PANGO_OT_TABLE_GSUB:
+ return HB_OT_TAG_GSUB;
+ case PANGO_OT_TABLE_GPOS:
+ return HB_OT_TAG_GPOS;
+ default:
+ return HB_TAG_NONE;
+ }
+}
+
+/* Guess a suitable short sample string for the font. */
+static const gchar *
+gimp_font_get_sample_string (PangoContext *context,
+ PangoFontDescription *font_desc)
+{
+ PangoFont *font;
+ hb_face_t *hb_face;
+ FT_Face face;
+ TT_OS2 *os2;
+ PangoOTTableType tt;
+ gint i;
+
+ /* This is a table of scripts and corresponding short sample strings
+ * to be used instead of the Latin sample string Aa. The script
+ * codes are as in ISO15924 (see
+ * https://www.unicode.org/iso15924/iso15924-codes.html), but in
+ * lower case. The Unicode subrange bit numbers, as used in TrueType
+ * so-called OS/2 tables, are from
+ * https://www.microsoft.com/typography/otspec/os2.htm#ur .
+ *
+ * The table is mostly ordered by Unicode order. But as there are
+ * fonts that support several of these scripts, the ordering is
+ * be modified so that the script which such a font is more likely
+ * to be actually designed for comes first and matches.
+ *
+ * These sample strings are mostly just guesswork as for their
+ * usefulness. Usually they contain what I assume is the first
+ * letter in the corresponding alphabet, or two first letters if the
+ * first one happens to look too "trivial" to be recognizable by
+ * itself.
+ *
+ * This table is used to determine the primary script a font has
+ * been designed for.
+ *
+ * Very useful link: https://www.wazu.jp/index.html
+ */
+ static const struct
+ {
+ const gchar script[4];
+ gint bit;
+ const gchar *sample;
+ } scripts[] = {
+ /* Han is first because fonts that support it presumably are primarily
+ * designed for it.
+ */
+ {
+ "hani", /* Han Ideographic */
+ 59,
+ "\346\260\270" /* U+6C38 "forever". Ed Trager says
+ * this is a "pan-stroke" often used
+ * in teaching Chinese calligraphy. It
+ * contains the eight basic Chinese
+ * stroke forms.
+ */
+ },
+ {
+ "copt", /* Coptic */
+ 7,
+ "\316\221\316\261" /* U+0410 GREEK CAPITAL LETTER ALPHA
+ U+0430 GREEK SMALL LETTER ALPHA
+ */
+ },
+ {
+ "grek", /* Greek */
+ 7,
+ "\316\221\316\261" /* U+0410 GREEK CAPITAL LETTER ALPHA
+ U+0430 GREEK SMALL LETTER ALPHA
+ */
+ },
+ {
+ "cyrl", /* Cyrillic */
+ 9,
+ "\320\220\325\260" /* U+0410 CYRILLIC CAPITAL LETTER A
+ U+0430 CYRILLIC SMALL LETTER A
+ */
+ },
+ {
+ "armn", /* Armenian */
+ 10,
+ "\324\261\325\241" /* U+0531 ARMENIAN CAPITAL LETTER AYB
+ U+0561 ARMENIAN SMALL LETTER AYB
+ */
+ },
+ {
+ "hebr", /* Hebrew */
+ 11,
+ "\327\220" /* U+05D0 HEBREW LETTER ALEF */
+ },
+ {
+ "arab", /* Arabic */
+ 13,
+ "\330\247\330\250" /* U+0627 ARABIC LETTER ALEF
+ * U+0628 ARABIC LETTER BEH
+ */
+ },
+ {
+ "syrc", /* Syriac */
+ 71,
+ "\334\220\334\222" /* U+0710 SYRIAC LETTER ALAPH
+ * U+0712 SYRIAC LETTER BETH
+ */
+ },
+ {
+ "thaa", /* Thaana */
+ 72,
+ "\336\200\336\201" /* U+0780 THAANA LETTER HAA
+ * U+0781 THAANA LETTER SHAVIYANI
+ */
+ },
+ /* Should really use some better sample strings for the complex
+ * scripts. Something that shows how well the font handles the
+ * complex processing for each script.
+ */
+ {
+ "deva", /* Devanagari */
+ 15,
+ "\340\244\205" /* U+0905 DEVANAGARI LETTER A*/
+ },
+ {
+ "beng", /* Bengali */
+ 16,
+ "\340\246\205" /* U+0985 BENGALI LETTER A */
+ },
+ {
+ "guru", /* Gurmukhi */
+ 17,
+ "\340\250\205" /* U+0A05 GURMUKHI LETTER A */
+ },
+ {
+ "gujr", /* Gujarati */
+ 18,
+ "\340\252\205" /* U+0A85 GUJARATI LETTER A */
+ },
+ {
+ "orya", /* Oriya */
+ 19,
+ "\340\254\205" /* U+0B05 ORIYA LETTER A */
+ },
+ {
+ "taml", /* Tamil */
+ 20,
+ "\340\256\205" /* U+0B85 TAMIL LETTER A */
+ },
+ {
+ "telu", /* Telugu */
+ 21,
+ "\340\260\205" /* U+0C05 TELUGU LETTER A */
+ },
+ {
+ "knda", /* Kannada */
+ 22,
+ "\340\262\205" /* U+0C85 KANNADA LETTER A */
+ },
+ {
+ "mylm", /* Malayalam */
+ 23,
+ "\340\264\205" /* U+0D05 MALAYALAM LETTER A */
+ },
+ {
+ "sinh", /* Sinhala */
+ 73,
+ "\340\266\205" /* U+0D85 SINHALA LETTER AYANNA */
+ },
+ {
+ "thai", /* Thai */
+ 24,
+ "\340\270\201\340\270\264"/* U+0E01 THAI CHARACTER KO KAI
+ * U+0E34 THAI CHARACTER SARA I
+ */
+ },
+ {
+ "laoo", /* Lao */
+ 25,
+ "\340\272\201\340\272\264"/* U+0E81 LAO LETTER KO
+ * U+0EB4 LAO VOWEL SIGN I
+ */
+ },
+ {
+ "tibt", /* Tibetan */
+ 70,
+ "\340\274\200" /* U+0F00 TIBETAN SYLLABLE OM */
+ },
+ {
+ "mymr", /* Myanmar */
+ 74,
+ "\341\200\200" /* U+1000 MYANMAR LETTER KA */
+ },
+ {
+ "geor", /* Georgian */
+ 26,
+ "\341\202\240\341\203\200" /* U+10A0 GEORGIAN CAPITAL LETTER AN
+ * U+10D0 GEORGIAN LETTER AN
+ */
+ },
+ {
+ "hang", /* Hangul */
+ 28,
+ "\341\204\200\341\204\201"/* U+1100 HANGUL CHOSEONG KIYEOK
+ * U+1101 HANGUL CHOSEONG SSANGKIYEOK
+ */
+ },
+ {
+ "ethi", /* Ethiopic */
+ 75,
+ "\341\210\200" /* U+1200 ETHIOPIC SYLLABLE HA */
+ },
+ {
+ "cher", /* Cherokee */
+ 76,
+ "\341\216\243" /* U+13A3 CHEROKEE LETTER O */
+ },
+ {
+ "cans", /* Unified Canadian Aboriginal Syllabics */
+ 77,
+ "\341\220\201" /* U+1401 CANADIAN SYLLABICS E */
+ },
+ {
+ "ogam", /* Ogham */
+ 78,
+ "\341\232\201" /* U+1681 OGHAM LETTER BEITH */
+ },
+ {
+ "runr", /* Runic */
+ 79,
+ "\341\232\240" /* U+16A0 RUNIC LETTER FEHU FEOH FE F */
+ },
+ {
+ "tglg", /* Tagalog */
+ 84,
+ "\341\234\200" /* U+1700 TAGALOG LETTER A */
+ },
+ {
+ "hano", /* Hanunoo */
+ -1,
+ "\341\234\240" /* U+1720 HANUNOO LETTER A */
+ },
+ {
+ "buhd", /* Buhid */
+ -1,
+ "\341\235\200" /* U+1740 BUHID LETTER A */
+ },
+ {
+ "tagb", /* Tagbanwa */
+ -1,
+ "\341\235\240" /* U+1760 TAGBANWA LETTER A */
+ },
+ {
+ "khmr", /* Khmer */
+ 80,
+ "\341\236\201\341\237\222\341\236\211\341\236\273\341\237\206"
+ /* U+1781 KHMER LETTER KHA
+ * U+17D2 KHMER LETTER SIGN COENG
+ * U+1789 KHMER LETTER NYO
+ * U+17BB KHMER VOWEL SIGN U
+ * U+17C6 KHMER SIGN NIKAHIT
+ * A common word meaning "I" that contains
+ * lots of complex processing.
+ */
+ },
+ {
+ "mong", /* Mongolian */
+ 81,
+ "\341\240\240" /* U+1820 MONGOLIAN LETTER A */
+ },
+ {
+ "limb", /* Limbu */
+ -1,
+ "\341\244\201" /* U+1901 LIMBU LETTER KA */
+ },
+ {
+ "tale", /* Tai Le */
+ -1,
+ "\341\245\220" /* U+1950 TAI LE LETTER KA */
+ },
+ {
+ "latn", /* Latin */
+ 0,
+ "Aa"
+ }
+ };
+
+ gint ot_alts[4];
+ gint n_ot_alts = 0;
+ gint sr_alts[20];
+ gint n_sr_alts = 0;
+
+ font = pango_context_load_font (context, font_desc);
+
+ g_return_val_if_fail (PANGO_IS_FC_FONT (font), "Aa");
+
+ face = pango_fc_font_lock_face (PANGO_FC_FONT (font));
+ g_return_val_if_fail (face != NULL, "Aa");
+ hb_face = hb_ft_face_create (face, NULL);
+
+ /* First check what script(s), if any, the font has GSUB or GPOS
+ * OpenType layout tables for.
+ */
+ for (tt = PANGO_OT_TABLE_GSUB;
+ n_ot_alts < G_N_ELEMENTS (ot_alts) && tt <= PANGO_OT_TABLE_GPOS;
+ tt++)
+ {
+ hb_tag_t tag;
+ unsigned int count;
+ PangoOTTag *slist;
+
+ tag = get_hb_table_type (tt);
+ count = hb_ot_layout_table_get_script_tags (hb_face, tag, 0, NULL, NULL);
+ slist = g_new (PangoOTTag, count + 1);
+ hb_ot_layout_table_get_script_tags (hb_face, tag, 0, &count, slist);
+ slist[count] = 0;
+
+ for (i = 0;
+ n_ot_alts < G_N_ELEMENTS (ot_alts) && i < G_N_ELEMENTS (scripts);
+ i++)
+ {
+ gint j, k;
+
+ for (k = 0; k < n_ot_alts; k++)
+ if (ot_alts[k] == i)
+ break;
+
+ if (k == n_ot_alts)
+ {
+ for (j = 0;
+ n_ot_alts < G_N_ELEMENTS (ot_alts) && slist[j];
+ j++)
+ {
+#define TAG(s) FT_MAKE_TAG (s[0], s[1], s[2], s[3])
+
+ if (slist[j] == TAG (scripts[i].script) &&
+ gimp_font_covers_string (PANGO_FC_FONT (font),
+ scripts[i].sample))
+ {
+ ot_alts[n_ot_alts++] = i;
+ DEBUGPRINT (("%.4s ", scripts[i].script));
+ }
+#undef TAG
+ }
+ }
+ }
+
+ g_free (slist);
+ }
+
+ hb_face_destroy (hb_face);
+
+ DEBUGPRINT (("; OS/2: "));
+
+ /* Next check the OS/2 table for Unicode ranges the font claims
+ * to cover.
+ */
+
+ os2 = FT_Get_Sfnt_Table (face, ft_sfnt_os2);
+
+ if (os2)
+ {
+ for (i = 0;
+ n_sr_alts < G_N_ELEMENTS (sr_alts) && i < G_N_ELEMENTS (scripts);
+ i++)
+ {
+ if (scripts[i].bit >= 0 &&
+ (&os2->ulUnicodeRange1)[scripts[i].bit/32] & (1 << (scripts[i].bit % 32)) &&
+ gimp_font_covers_string (PANGO_FC_FONT (font),
+ scripts[i].sample))
+ {
+ sr_alts[n_sr_alts++] = i;
+ DEBUGPRINT (("%.4s ", scripts[i].script));
+ }
+ }
+ }
+
+ pango_fc_font_unlock_face (PANGO_FC_FONT (font));
+
+ g_object_unref (font);
+
+ if (n_ot_alts > 2)
+ {
+ /* The font has OpenType tables for several scripts. If it
+ * support Basic Latin as well, use Aa.
+ */
+ gint i;
+
+ for (i = 0; i < n_sr_alts; i++)
+ if (scripts[sr_alts[i]].bit == 0)
+ {
+ DEBUGPRINT (("=> several OT, also latin, use Aa\n"));
+ return "Aa";
+ }
+ }
+
+ if (n_ot_alts > 0 && n_sr_alts >= n_ot_alts + 3)
+ {
+ /* At least one script with an OpenType table, but many more
+ * subranges than such scripts. If it supports Basic Latin,
+ * use Aa, else the highest priority subrange.
+ */
+ gint i;
+
+ for (i = 0; i < n_sr_alts; i++)
+ if (scripts[sr_alts[i]].bit == 0)
+ {
+ DEBUGPRINT (("=> several SR, also latin, use Aa\n"));
+ return "Aa";
+ }
+
+ DEBUGPRINT (("=> several SR, use %.4s\n", scripts[sr_alts[0]].script));
+ return scripts[sr_alts[0]].sample;
+ }
+
+ if (n_ot_alts > 0)
+ {
+ /* OpenType tables for at least one script, use the
+ * highest priority one
+ */
+ DEBUGPRINT (("=> at least one OT, use %.4s\n",
+ scripts[sr_alts[0]].script));
+ return scripts[ot_alts[0]].sample;
+ }
+
+ if (n_sr_alts > 0)
+ {
+ /* Use the highest priority subrange. This means that a
+ * font that supports Greek, Cyrillic and Latin (quite
+ * common), will get the Greek sample string. That is
+ * capital and lowercase alpha, which looks like capital A
+ * and lowercase alpha, so it's actually quite nice, and
+ * doesn't give a too strong impression that the font would
+ * be for Greek only.
+ */
+ DEBUGPRINT (("=> at least one SR, use %.4s\n",
+ scripts[sr_alts[0]].script));
+ return scripts[sr_alts[0]].sample;
+ }
+
+ /* Final fallback */
+ DEBUGPRINT (("=> fallback, use Aa\n"));
+ return "Aa";
+}