xref: /aosp_15_r20/external/harfbuzz_ng/util/hb-info.cc (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker  * Copyright © 2023  Behdad Esfahbod
3*2d1272b8SAndroid Build Coastguard Worker  *
4*2d1272b8SAndroid Build Coastguard Worker  *  This is part of HarfBuzz, a text shaping library.
5*2d1272b8SAndroid Build Coastguard Worker  *
6*2d1272b8SAndroid Build Coastguard Worker  * Permission is hereby granted, without written agreement and without
7*2d1272b8SAndroid Build Coastguard Worker  * license or royalty fees, to use, copy, modify, and distribute this
8*2d1272b8SAndroid Build Coastguard Worker  * software and its documentation for any purpose, provided that the
9*2d1272b8SAndroid Build Coastguard Worker  * above copyright notice and the following two paragraphs appear in
10*2d1272b8SAndroid Build Coastguard Worker  * all copies of this software.
11*2d1272b8SAndroid Build Coastguard Worker  *
12*2d1272b8SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13*2d1272b8SAndroid Build Coastguard Worker  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14*2d1272b8SAndroid Build Coastguard Worker  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15*2d1272b8SAndroid Build Coastguard Worker  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16*2d1272b8SAndroid Build Coastguard Worker  * DAMAGE.
17*2d1272b8SAndroid Build Coastguard Worker  *
18*2d1272b8SAndroid Build Coastguard Worker  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19*2d1272b8SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20*2d1272b8SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21*2d1272b8SAndroid Build Coastguard Worker  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22*2d1272b8SAndroid Build Coastguard Worker  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23*2d1272b8SAndroid Build Coastguard Worker  *
24*2d1272b8SAndroid Build Coastguard Worker  * Google Author(s): Behdad Esfahbod
25*2d1272b8SAndroid Build Coastguard Worker  */
26*2d1272b8SAndroid Build Coastguard Worker 
27*2d1272b8SAndroid Build Coastguard Worker #include "batch.hh"
28*2d1272b8SAndroid Build Coastguard Worker #include "font-options.hh"
29*2d1272b8SAndroid Build Coastguard Worker 
30*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_HAS_GOBJECT
31*2d1272b8SAndroid Build Coastguard Worker #include <hb-gobject.h>
32*2d1272b8SAndroid Build Coastguard Worker #endif
33*2d1272b8SAndroid Build Coastguard Worker 
34*2d1272b8SAndroid Build Coastguard Worker #ifdef HAVE_CHAFA
35*2d1272b8SAndroid Build Coastguard Worker # include <chafa.h>
36*2d1272b8SAndroid Build Coastguard Worker #endif
37*2d1272b8SAndroid Build Coastguard Worker 
38*2d1272b8SAndroid Build Coastguard Worker const unsigned DEFAULT_FONT_SIZE = FONT_SIZE_UPEM;
39*2d1272b8SAndroid Build Coastguard Worker const unsigned SUBPIXEL_BITS = 0;
40*2d1272b8SAndroid Build Coastguard Worker 
41*2d1272b8SAndroid Build Coastguard Worker static void
_hb_ot_name_get_utf8(hb_face_t * face,hb_ot_name_id_t name_id,hb_language_t language,unsigned int * text_size,char * text)42*2d1272b8SAndroid Build Coastguard Worker _hb_ot_name_get_utf8 (hb_face_t       *face,
43*2d1272b8SAndroid Build Coastguard Worker 		      hb_ot_name_id_t  name_id,
44*2d1272b8SAndroid Build Coastguard Worker 		      hb_language_t    language,
45*2d1272b8SAndroid Build Coastguard Worker 		      unsigned int    *text_size /* IN/OUT */,
46*2d1272b8SAndroid Build Coastguard Worker 		      char            *text      /* OUT */)
47*2d1272b8SAndroid Build Coastguard Worker {
48*2d1272b8SAndroid Build Coastguard Worker   static hb_language_t en = hb_language_from_string ("en", -1);
49*2d1272b8SAndroid Build Coastguard Worker 
50*2d1272b8SAndroid Build Coastguard Worker   unsigned len = *text_size;
51*2d1272b8SAndroid Build Coastguard Worker   if (!hb_ot_name_get_utf8 (face, name_id,
52*2d1272b8SAndroid Build Coastguard Worker 			    language,
53*2d1272b8SAndroid Build Coastguard Worker 			    &len, text))
54*2d1272b8SAndroid Build Coastguard Worker   {
55*2d1272b8SAndroid Build Coastguard Worker     len = *text_size;
56*2d1272b8SAndroid Build Coastguard Worker     hb_ot_name_get_utf8 (face, name_id,
57*2d1272b8SAndroid Build Coastguard Worker 			 en,
58*2d1272b8SAndroid Build Coastguard Worker 			 &len, text);
59*2d1272b8SAndroid Build Coastguard Worker   }
60*2d1272b8SAndroid Build Coastguard Worker   *text_size = len;
61*2d1272b8SAndroid Build Coastguard Worker }
62*2d1272b8SAndroid Build Coastguard Worker 
63*2d1272b8SAndroid Build Coastguard Worker struct info_t :
64*2d1272b8SAndroid Build Coastguard Worker        option_parser_t,
65*2d1272b8SAndroid Build Coastguard Worker        font_options_t
66*2d1272b8SAndroid Build Coastguard Worker {
add_optionsinfo_t67*2d1272b8SAndroid Build Coastguard Worker   void add_options ()
68*2d1272b8SAndroid Build Coastguard Worker   {
69*2d1272b8SAndroid Build Coastguard Worker     font_options_t::add_options (this);
70*2d1272b8SAndroid Build Coastguard Worker 
71*2d1272b8SAndroid Build Coastguard Worker     GOptionEntry misc_entries[] =
72*2d1272b8SAndroid Build Coastguard Worker     {
73*2d1272b8SAndroid Build Coastguard Worker       {"direction",	0, 0, G_OPTION_ARG_STRING,	&this->direction_str,		"Set direction (default: ltr)",		"ltr/rtl/ttb/btt"},
74*2d1272b8SAndroid Build Coastguard Worker       {"script",	0, 0, G_OPTION_ARG_STRING,	&this->script_str,		"Set script (default: none)",		"ISO-15924 tag; eg. 'Latn'"},
75*2d1272b8SAndroid Build Coastguard Worker       {"language",	0, 0, G_OPTION_ARG_STRING,	&this->language_str,		"Set language (default: $LANG)",	"BCP 47 tag; eg. 'en'"},
76*2d1272b8SAndroid Build Coastguard Worker       {"ot-script",	0, 0, G_OPTION_ARG_STRING,	&this->ot_script_str,		"Set OpenType script tag (default: none)","tag; eg. 'latn'"},
77*2d1272b8SAndroid Build Coastguard Worker       {"ot-language",	0, 0, G_OPTION_ARG_STRING,	&this->ot_language_str,		"Set OpenType language tag (default: none)",	"tag; eg. 'ENG'"},
78*2d1272b8SAndroid Build Coastguard Worker 
79*2d1272b8SAndroid Build Coastguard Worker       {nullptr}
80*2d1272b8SAndroid Build Coastguard Worker     };
81*2d1272b8SAndroid Build Coastguard Worker     add_group (misc_entries,
82*2d1272b8SAndroid Build Coastguard Worker 	       "misc",
83*2d1272b8SAndroid Build Coastguard Worker 	       "Miscellaneous options:",
84*2d1272b8SAndroid Build Coastguard Worker 	       "Miscellaneous options affecting queries",
85*2d1272b8SAndroid Build Coastguard Worker 	       this,
86*2d1272b8SAndroid Build Coastguard Worker 	       false /* We add below. */);
87*2d1272b8SAndroid Build Coastguard Worker 
88*2d1272b8SAndroid Build Coastguard Worker     GOptionEntry query_entries[] =
89*2d1272b8SAndroid Build Coastguard Worker     {
90*2d1272b8SAndroid Build Coastguard Worker       {"all",		'a', 0, G_OPTION_ARG_NONE,	&this->all,			"Show everything",		nullptr},
91*2d1272b8SAndroid Build Coastguard Worker 
92*2d1272b8SAndroid Build Coastguard Worker       {"show-all",	0, 0, G_OPTION_ARG_NONE,	&this->show_all,		"Show all short information (default)",	nullptr},
93*2d1272b8SAndroid Build Coastguard Worker       {"show-face-count",0, 0, G_OPTION_ARG_NONE,	&this->show_face_count,		"Show face count",		nullptr},
94*2d1272b8SAndroid Build Coastguard Worker       {"show-family",	0, 0, G_OPTION_ARG_NONE,	&this->show_family,		"Show family name",		nullptr},
95*2d1272b8SAndroid Build Coastguard Worker       {"show-subfamily",0, 0, G_OPTION_ARG_NONE,	&this->show_subfamily,		"Show subfamily name",		nullptr},
96*2d1272b8SAndroid Build Coastguard Worker       {"show-unique-name",0, 0, G_OPTION_ARG_NONE,	&this->show_unique_name,	"Show unique name",		nullptr},
97*2d1272b8SAndroid Build Coastguard Worker       {"show-full-name",0, 0, G_OPTION_ARG_NONE,	&this->show_full_name,		"Show full name",		nullptr},
98*2d1272b8SAndroid Build Coastguard Worker       {"show-postscript-name",0, 0, G_OPTION_ARG_NONE,	&this->show_postscript_name,	"Show Postscript name",		nullptr},
99*2d1272b8SAndroid Build Coastguard Worker       {"show-version",	0, 0, G_OPTION_ARG_NONE,	&this->show_version,		"Show version",			nullptr},
100*2d1272b8SAndroid Build Coastguard Worker       {"show-technology",0, 0, G_OPTION_ARG_NONE,	&this->show_technology,		"Show technology",		nullptr},
101*2d1272b8SAndroid Build Coastguard Worker       {"show-unicode-count",0, 0, G_OPTION_ARG_NONE,	&this->show_unicode_count,	"Show Unicode count",		nullptr},
102*2d1272b8SAndroid Build Coastguard Worker       {"show-glyph-count",0, 0, G_OPTION_ARG_NONE,	&this->show_glyph_count,	"Show glyph count",		nullptr},
103*2d1272b8SAndroid Build Coastguard Worker       {"show-upem",	0, 0, G_OPTION_ARG_NONE,	&this->show_upem,		"Show Units-Per-EM",		nullptr},
104*2d1272b8SAndroid Build Coastguard Worker       {"show-extents",	0, 0, G_OPTION_ARG_NONE,	&this->show_extents,		"Show extents",			nullptr},
105*2d1272b8SAndroid Build Coastguard Worker 
106*2d1272b8SAndroid Build Coastguard Worker       {"get-name",	0, 0, G_OPTION_ARG_STRING_ARRAY,&this->get_name,		"Get name",			"name id; eg. '13'"},
107*2d1272b8SAndroid Build Coastguard Worker       {"get-style",	0, 0, G_OPTION_ARG_STRING_ARRAY,&this->get_style,		"Get style",			"style tag; eg. 'wght'"},
108*2d1272b8SAndroid Build Coastguard Worker       {"get-metric",	0, 0, G_OPTION_ARG_STRING_ARRAY,&this->get_metric,		"Get metric",			"metric tag; eg. 'hasc'"},
109*2d1272b8SAndroid Build Coastguard Worker       {"get-baseline",	0, 0, G_OPTION_ARG_STRING_ARRAY,&this->get_baseline,		"Get baseline",			"baseline tag; eg. 'hang'"},
110*2d1272b8SAndroid Build Coastguard Worker       {"get-meta",	0, 0, G_OPTION_ARG_STRING_ARRAY,&this->get_meta,		"Get meta information",		"tag tag; eg. 'dlng'"},
111*2d1272b8SAndroid Build Coastguard Worker       {"get-table",	0, 0, G_OPTION_ARG_STRING,	&this->get_table,		"Get font table",		"table tag; eg. 'cmap'"},
112*2d1272b8SAndroid Build Coastguard Worker 
113*2d1272b8SAndroid Build Coastguard Worker       {"list-all",	0, 0, G_OPTION_ARG_NONE,	&this->list_all,		"List all long information",	nullptr},
114*2d1272b8SAndroid Build Coastguard Worker       {"list-names",	0, 0, G_OPTION_ARG_NONE,	&this->list_names,		"List names",			nullptr},
115*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_HAS_GOBJECT
116*2d1272b8SAndroid Build Coastguard Worker       {"list-style",	0, 0, G_OPTION_ARG_NONE,	&this->list_style,		"List style",			nullptr},
117*2d1272b8SAndroid Build Coastguard Worker       {"list-metrics",	0, 0, G_OPTION_ARG_NONE,	&this->list_metrics,		"List metrics",			nullptr},
118*2d1272b8SAndroid Build Coastguard Worker       {"list-baselines",0, 0, G_OPTION_ARG_NONE,	&this->list_baselines,		"List baselines",		nullptr},
119*2d1272b8SAndroid Build Coastguard Worker #endif
120*2d1272b8SAndroid Build Coastguard Worker       {"list-tables",	'l', 0, G_OPTION_ARG_NONE,	&this->list_tables,		"List tables",			nullptr},
121*2d1272b8SAndroid Build Coastguard Worker       {"list-unicodes",	0, 0, G_OPTION_ARG_NONE,	&this->list_unicodes,		"List characters",		nullptr},
122*2d1272b8SAndroid Build Coastguard Worker       {"list-glyphs",	0, 0, G_OPTION_ARG_NONE,	&this->list_glyphs,		"List glyphs",			nullptr},
123*2d1272b8SAndroid Build Coastguard Worker       {"list-scripts",	0, 0, G_OPTION_ARG_NONE,	&this->list_scripts,		"List layout scripts",		nullptr},
124*2d1272b8SAndroid Build Coastguard Worker       {"list-features",	0, 0, G_OPTION_ARG_NONE,	&this->list_features,		"List layout features",		nullptr},
125*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
126*2d1272b8SAndroid Build Coastguard Worker       {"list-variations",0, 0, G_OPTION_ARG_NONE,	&this->list_variations,		"List variations",		nullptr},
127*2d1272b8SAndroid Build Coastguard Worker #endif
128*2d1272b8SAndroid Build Coastguard Worker       {"list-palettes",	0, 0, G_OPTION_ARG_NONE,	&this->list_palettes,		"List color palettes",		nullptr},
129*2d1272b8SAndroid Build Coastguard Worker       {"list-meta",	0, 0, G_OPTION_ARG_NONE,	&this->list_meta,		"List meta information",	nullptr},
130*2d1272b8SAndroid Build Coastguard Worker 
131*2d1272b8SAndroid Build Coastguard Worker       {nullptr}
132*2d1272b8SAndroid Build Coastguard Worker     };
133*2d1272b8SAndroid Build Coastguard Worker     add_group (query_entries,
134*2d1272b8SAndroid Build Coastguard Worker 	       "query",
135*2d1272b8SAndroid Build Coastguard Worker 	       "Query options:",
136*2d1272b8SAndroid Build Coastguard Worker 	       "Options to query the font instance",
137*2d1272b8SAndroid Build Coastguard Worker 	       this,
138*2d1272b8SAndroid Build Coastguard Worker 	       true);
139*2d1272b8SAndroid Build Coastguard Worker 
140*2d1272b8SAndroid Build Coastguard Worker     GOptionEntry entries[] =
141*2d1272b8SAndroid Build Coastguard Worker     {
142*2d1272b8SAndroid Build Coastguard Worker       {"quiet",		'q', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE,	&this->verbose,	"Generate machine-readable output",	nullptr},
143*2d1272b8SAndroid Build Coastguard Worker       {G_OPTION_REMAINING,	0, G_OPTION_FLAG_IN_MAIN,
144*2d1272b8SAndroid Build Coastguard Worker 				G_OPTION_ARG_CALLBACK,	(gpointer) &collect_rest,	nullptr,	"[FONT-FILE]"},
145*2d1272b8SAndroid Build Coastguard Worker       {nullptr}
146*2d1272b8SAndroid Build Coastguard Worker     };
147*2d1272b8SAndroid Build Coastguard Worker     add_main_group (entries, this);
148*2d1272b8SAndroid Build Coastguard Worker 
149*2d1272b8SAndroid Build Coastguard Worker     option_parser_t::add_options ();
150*2d1272b8SAndroid Build Coastguard Worker   }
151*2d1272b8SAndroid Build Coastguard Worker 
152*2d1272b8SAndroid Build Coastguard Worker   static gboolean
collect_restinfo_t153*2d1272b8SAndroid Build Coastguard Worker   collect_rest (const char *name G_GNUC_UNUSED,
154*2d1272b8SAndroid Build Coastguard Worker 		const char *arg,
155*2d1272b8SAndroid Build Coastguard Worker 		gpointer    data,
156*2d1272b8SAndroid Build Coastguard Worker 		GError    **error)
157*2d1272b8SAndroid Build Coastguard Worker   {
158*2d1272b8SAndroid Build Coastguard Worker     info_t *thiz = (info_t *) data;
159*2d1272b8SAndroid Build Coastguard Worker 
160*2d1272b8SAndroid Build Coastguard Worker     if (!thiz->font_file)
161*2d1272b8SAndroid Build Coastguard Worker     {
162*2d1272b8SAndroid Build Coastguard Worker       thiz->font_file = g_strdup (arg);
163*2d1272b8SAndroid Build Coastguard Worker       return true;
164*2d1272b8SAndroid Build Coastguard Worker     }
165*2d1272b8SAndroid Build Coastguard Worker 
166*2d1272b8SAndroid Build Coastguard Worker     g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
167*2d1272b8SAndroid Build Coastguard Worker 		 "Too many arguments on the command line");
168*2d1272b8SAndroid Build Coastguard Worker     return false;
169*2d1272b8SAndroid Build Coastguard Worker   }
170*2d1272b8SAndroid Build Coastguard Worker 
171*2d1272b8SAndroid Build Coastguard Worker 
172*2d1272b8SAndroid Build Coastguard Worker   protected:
173*2d1272b8SAndroid Build Coastguard Worker 
174*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t verbose = true;
175*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t first_item = true;
176*2d1272b8SAndroid Build Coastguard Worker 
177*2d1272b8SAndroid Build Coastguard Worker   char *direction_str = nullptr;
178*2d1272b8SAndroid Build Coastguard Worker   char *script_str = nullptr;
179*2d1272b8SAndroid Build Coastguard Worker   char *language_str = nullptr;
180*2d1272b8SAndroid Build Coastguard Worker   hb_direction_t direction = HB_DIRECTION_LTR;
181*2d1272b8SAndroid Build Coastguard Worker   hb_script_t script = HB_SCRIPT_INVALID;
182*2d1272b8SAndroid Build Coastguard Worker   hb_language_t language = HB_LANGUAGE_INVALID;
183*2d1272b8SAndroid Build Coastguard Worker   char *ot_script_str = nullptr;
184*2d1272b8SAndroid Build Coastguard Worker   char *ot_language_str = nullptr;
185*2d1272b8SAndroid Build Coastguard Worker 
186*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t all = false;
187*2d1272b8SAndroid Build Coastguard Worker 
188*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t show_all = false;
189*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t show_face_count = false;
190*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t show_family = false;
191*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t show_subfamily = false;
192*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t show_unique_name = false;
193*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t show_full_name = false;
194*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t show_postscript_name = false;
195*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t show_version = false;
196*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t show_technology = false;
197*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t show_unicode_count = false;
198*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t show_glyph_count = false;
199*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t show_upem = false;
200*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t show_extents = false;
201*2d1272b8SAndroid Build Coastguard Worker 
202*2d1272b8SAndroid Build Coastguard Worker   char **get_name = nullptr;
203*2d1272b8SAndroid Build Coastguard Worker   char **get_style = nullptr;
204*2d1272b8SAndroid Build Coastguard Worker   char **get_metric = nullptr;
205*2d1272b8SAndroid Build Coastguard Worker   char **get_baseline = nullptr;
206*2d1272b8SAndroid Build Coastguard Worker   char **get_meta = nullptr;
207*2d1272b8SAndroid Build Coastguard Worker   char *get_table = nullptr;
208*2d1272b8SAndroid Build Coastguard Worker 
209*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t list_all = false;
210*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t list_names = false;
211*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_HAS_GOBJECT
212*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t list_style = false;
213*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t list_metrics = false;
214*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t list_baselines = false;
215*2d1272b8SAndroid Build Coastguard Worker #endif
216*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t list_tables = false;
217*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t list_unicodes = false;
218*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t list_glyphs = false;
219*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t list_scripts = false;
220*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t list_features = false;
221*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
222*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t list_variations = false;
223*2d1272b8SAndroid Build Coastguard Worker #endif
224*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t list_palettes = false;
225*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t list_meta = false;
226*2d1272b8SAndroid Build Coastguard Worker 
227*2d1272b8SAndroid Build Coastguard Worker   public:
228*2d1272b8SAndroid Build Coastguard Worker 
229*2d1272b8SAndroid Build Coastguard Worker   void
post_parseinfo_t230*2d1272b8SAndroid Build Coastguard Worker   post_parse (GError **error)
231*2d1272b8SAndroid Build Coastguard Worker   {
232*2d1272b8SAndroid Build Coastguard Worker     if (direction_str)
233*2d1272b8SAndroid Build Coastguard Worker       direction = hb_direction_from_string (direction_str, -1);
234*2d1272b8SAndroid Build Coastguard Worker     if (script_str)
235*2d1272b8SAndroid Build Coastguard Worker       script = hb_script_from_string (script_str, -1);
236*2d1272b8SAndroid Build Coastguard Worker     language = hb_language_get_default ();
237*2d1272b8SAndroid Build Coastguard Worker     if (language_str)
238*2d1272b8SAndroid Build Coastguard Worker       language = hb_language_from_string (language_str, -1);
239*2d1272b8SAndroid Build Coastguard Worker   }
240*2d1272b8SAndroid Build Coastguard Worker 
241*2d1272b8SAndroid Build Coastguard Worker   int
operator ()info_t242*2d1272b8SAndroid Build Coastguard Worker   operator () (int argc, char **argv)
243*2d1272b8SAndroid Build Coastguard Worker   {
244*2d1272b8SAndroid Build Coastguard Worker     add_options ();
245*2d1272b8SAndroid Build Coastguard Worker 
246*2d1272b8SAndroid Build Coastguard Worker     if (argc == 2)
247*2d1272b8SAndroid Build Coastguard Worker       show_all = true;
248*2d1272b8SAndroid Build Coastguard Worker 
249*2d1272b8SAndroid Build Coastguard Worker     parse (&argc, &argv);
250*2d1272b8SAndroid Build Coastguard Worker 
251*2d1272b8SAndroid Build Coastguard Worker     if (all)
252*2d1272b8SAndroid Build Coastguard Worker     {
253*2d1272b8SAndroid Build Coastguard Worker       show_all =
254*2d1272b8SAndroid Build Coastguard Worker       list_all =
255*2d1272b8SAndroid Build Coastguard Worker       true;
256*2d1272b8SAndroid Build Coastguard Worker     }
257*2d1272b8SAndroid Build Coastguard Worker 
258*2d1272b8SAndroid Build Coastguard Worker     if (show_all)
259*2d1272b8SAndroid Build Coastguard Worker     {
260*2d1272b8SAndroid Build Coastguard Worker       show_face_count =
261*2d1272b8SAndroid Build Coastguard Worker       show_family =
262*2d1272b8SAndroid Build Coastguard Worker       show_subfamily =
263*2d1272b8SAndroid Build Coastguard Worker       show_unique_name =
264*2d1272b8SAndroid Build Coastguard Worker       show_full_name =
265*2d1272b8SAndroid Build Coastguard Worker       show_postscript_name =
266*2d1272b8SAndroid Build Coastguard Worker       show_version =
267*2d1272b8SAndroid Build Coastguard Worker       show_technology =
268*2d1272b8SAndroid Build Coastguard Worker       show_unicode_count =
269*2d1272b8SAndroid Build Coastguard Worker       show_glyph_count =
270*2d1272b8SAndroid Build Coastguard Worker       show_upem =
271*2d1272b8SAndroid Build Coastguard Worker       show_extents =
272*2d1272b8SAndroid Build Coastguard Worker       true;
273*2d1272b8SAndroid Build Coastguard Worker       first_item = false;
274*2d1272b8SAndroid Build Coastguard Worker     }
275*2d1272b8SAndroid Build Coastguard Worker 
276*2d1272b8SAndroid Build Coastguard Worker     if (list_all)
277*2d1272b8SAndroid Build Coastguard Worker     {
278*2d1272b8SAndroid Build Coastguard Worker       list_names =
279*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_HAS_GOBJECT
280*2d1272b8SAndroid Build Coastguard Worker       list_style =
281*2d1272b8SAndroid Build Coastguard Worker       list_metrics =
282*2d1272b8SAndroid Build Coastguard Worker       list_baselines =
283*2d1272b8SAndroid Build Coastguard Worker #endif
284*2d1272b8SAndroid Build Coastguard Worker       list_tables =
285*2d1272b8SAndroid Build Coastguard Worker       list_unicodes =
286*2d1272b8SAndroid Build Coastguard Worker       list_glyphs =
287*2d1272b8SAndroid Build Coastguard Worker       list_scripts =
288*2d1272b8SAndroid Build Coastguard Worker       list_features =
289*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
290*2d1272b8SAndroid Build Coastguard Worker       list_variations =
291*2d1272b8SAndroid Build Coastguard Worker #endif
292*2d1272b8SAndroid Build Coastguard Worker       list_palettes =
293*2d1272b8SAndroid Build Coastguard Worker       list_meta =
294*2d1272b8SAndroid Build Coastguard Worker       true;
295*2d1272b8SAndroid Build Coastguard Worker     }
296*2d1272b8SAndroid Build Coastguard Worker 
297*2d1272b8SAndroid Build Coastguard Worker     if (show_face_count)  _show_face_count ();
298*2d1272b8SAndroid Build Coastguard Worker     if (show_family)	  _show_family ();
299*2d1272b8SAndroid Build Coastguard Worker     if (show_subfamily)	  _show_subfamily ();
300*2d1272b8SAndroid Build Coastguard Worker     if (show_unique_name) _show_unique_name ();
301*2d1272b8SAndroid Build Coastguard Worker     if (show_full_name)	  _show_full_name ();
302*2d1272b8SAndroid Build Coastguard Worker     if (show_postscript_name)_show_postscript_name ();
303*2d1272b8SAndroid Build Coastguard Worker     if (show_version)	  _show_version ();
304*2d1272b8SAndroid Build Coastguard Worker     if (show_technology)  _show_technology ();
305*2d1272b8SAndroid Build Coastguard Worker     if (show_unicode_count)_show_unicode_count ();
306*2d1272b8SAndroid Build Coastguard Worker     if (show_glyph_count) _show_glyph_count ();
307*2d1272b8SAndroid Build Coastguard Worker     if (show_upem)	  _show_upem ();
308*2d1272b8SAndroid Build Coastguard Worker     if (show_extents)	  _show_extents ();
309*2d1272b8SAndroid Build Coastguard Worker 
310*2d1272b8SAndroid Build Coastguard Worker     if (get_name)	  _get_name ();
311*2d1272b8SAndroid Build Coastguard Worker     if (get_style)	  _get_style ();
312*2d1272b8SAndroid Build Coastguard Worker     if (get_metric)	  _get_metric ();
313*2d1272b8SAndroid Build Coastguard Worker     if (get_baseline)	  _get_baseline ();
314*2d1272b8SAndroid Build Coastguard Worker     if (get_meta)	  _get_meta ();
315*2d1272b8SAndroid Build Coastguard Worker     if (get_table)	  _get_table ();
316*2d1272b8SAndroid Build Coastguard Worker 
317*2d1272b8SAndroid Build Coastguard Worker     if (list_names)	  _list_names ();
318*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_HAS_GOBJECT
319*2d1272b8SAndroid Build Coastguard Worker     if (list_style)	  _list_style ();
320*2d1272b8SAndroid Build Coastguard Worker     if (list_metrics)	  _list_metrics ();
321*2d1272b8SAndroid Build Coastguard Worker     if (list_baselines)	  _list_baselines ();
322*2d1272b8SAndroid Build Coastguard Worker #endif
323*2d1272b8SAndroid Build Coastguard Worker     if (list_tables)	  _list_tables ();
324*2d1272b8SAndroid Build Coastguard Worker     if (list_unicodes)	  _list_unicodes ();
325*2d1272b8SAndroid Build Coastguard Worker     if (list_glyphs)	  _list_glyphs ();
326*2d1272b8SAndroid Build Coastguard Worker     if (list_scripts)	  _list_scripts ();
327*2d1272b8SAndroid Build Coastguard Worker     if (list_features)	  _list_features ();
328*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
329*2d1272b8SAndroid Build Coastguard Worker     if (list_variations)  _list_variations ();
330*2d1272b8SAndroid Build Coastguard Worker #endif
331*2d1272b8SAndroid Build Coastguard Worker     if (list_palettes)	  _list_palettes ();
332*2d1272b8SAndroid Build Coastguard Worker     if (list_meta)	  _list_meta ();
333*2d1272b8SAndroid Build Coastguard Worker 
334*2d1272b8SAndroid Build Coastguard Worker     return 0;
335*2d1272b8SAndroid Build Coastguard Worker   }
336*2d1272b8SAndroid Build Coastguard Worker 
337*2d1272b8SAndroid Build Coastguard Worker   protected:
338*2d1272b8SAndroid Build Coastguard Worker 
separatorinfo_t339*2d1272b8SAndroid Build Coastguard Worker   void separator ()
340*2d1272b8SAndroid Build Coastguard Worker   {
341*2d1272b8SAndroid Build Coastguard Worker     if (first_item)
342*2d1272b8SAndroid Build Coastguard Worker     {
343*2d1272b8SAndroid Build Coastguard Worker       first_item = false;
344*2d1272b8SAndroid Build Coastguard Worker       return;
345*2d1272b8SAndroid Build Coastguard Worker     }
346*2d1272b8SAndroid Build Coastguard Worker     printf ("\n===\n\n");
347*2d1272b8SAndroid Build Coastguard Worker   }
348*2d1272b8SAndroid Build Coastguard Worker 
349*2d1272b8SAndroid Build Coastguard Worker   void
_show_face_countinfo_t350*2d1272b8SAndroid Build Coastguard Worker   _show_face_count ()
351*2d1272b8SAndroid Build Coastguard Worker   {
352*2d1272b8SAndroid Build Coastguard Worker     hb_blob_t *blob = hb_blob_create_from_file (font_file);
353*2d1272b8SAndroid Build Coastguard Worker     printf ("Face count: %u\n", hb_face_count (blob));
354*2d1272b8SAndroid Build Coastguard Worker     hb_blob_destroy (blob);
355*2d1272b8SAndroid Build Coastguard Worker   }
356*2d1272b8SAndroid Build Coastguard Worker 
357*2d1272b8SAndroid Build Coastguard Worker   void
_show_nameinfo_t358*2d1272b8SAndroid Build Coastguard Worker   _show_name (const char *label, hb_ot_name_id_t name_id)
359*2d1272b8SAndroid Build Coastguard Worker   {
360*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
361*2d1272b8SAndroid Build Coastguard Worker     {
362*2d1272b8SAndroid Build Coastguard Worker       printf ("%s: ", label);
363*2d1272b8SAndroid Build Coastguard Worker     }
364*2d1272b8SAndroid Build Coastguard Worker 
365*2d1272b8SAndroid Build Coastguard Worker     char name[16384];
366*2d1272b8SAndroid Build Coastguard Worker     unsigned name_len = sizeof name;
367*2d1272b8SAndroid Build Coastguard Worker     _hb_ot_name_get_utf8 (face, name_id,
368*2d1272b8SAndroid Build Coastguard Worker 			  language,
369*2d1272b8SAndroid Build Coastguard Worker 			  &name_len, name);
370*2d1272b8SAndroid Build Coastguard Worker 
371*2d1272b8SAndroid Build Coastguard Worker     printf ("%s\n", name);
372*2d1272b8SAndroid Build Coastguard Worker   }
_show_familyinfo_t373*2d1272b8SAndroid Build Coastguard Worker   void _show_family ()		{ _show_name ("Family", 1); }
_show_subfamilyinfo_t374*2d1272b8SAndroid Build Coastguard Worker   void _show_subfamily ()
375*2d1272b8SAndroid Build Coastguard Worker   {
376*2d1272b8SAndroid Build Coastguard Worker     hb_ot_name_id_t name_id = 2;
377*2d1272b8SAndroid Build Coastguard Worker 
378*2d1272b8SAndroid Build Coastguard Worker     unsigned named_instance = hb_font_get_var_named_instance (font);
379*2d1272b8SAndroid Build Coastguard Worker     if (named_instance != HB_FONT_NO_VAR_NAMED_INSTANCE)
380*2d1272b8SAndroid Build Coastguard Worker       name_id = hb_ot_var_named_instance_get_subfamily_name_id (face, named_instance);
381*2d1272b8SAndroid Build Coastguard Worker 
382*2d1272b8SAndroid Build Coastguard Worker     _show_name ("Subfamily", name_id);
383*2d1272b8SAndroid Build Coastguard Worker   }
_show_unique_nameinfo_t384*2d1272b8SAndroid Build Coastguard Worker   void _show_unique_name ()	{ _show_name ("Unique name", 3); }
_show_full_nameinfo_t385*2d1272b8SAndroid Build Coastguard Worker   void _show_full_name ()	{ _show_name ("Full name", 4); }
_show_postscript_nameinfo_t386*2d1272b8SAndroid Build Coastguard Worker   void _show_postscript_name ()
387*2d1272b8SAndroid Build Coastguard Worker   {
388*2d1272b8SAndroid Build Coastguard Worker     hb_ot_name_id_t name_id = 6;
389*2d1272b8SAndroid Build Coastguard Worker 
390*2d1272b8SAndroid Build Coastguard Worker     unsigned named_instance = hb_font_get_var_named_instance (font);
391*2d1272b8SAndroid Build Coastguard Worker     if (named_instance != HB_FONT_NO_VAR_NAMED_INSTANCE)
392*2d1272b8SAndroid Build Coastguard Worker       name_id = hb_ot_var_named_instance_get_postscript_name_id (face, named_instance);
393*2d1272b8SAndroid Build Coastguard Worker 
394*2d1272b8SAndroid Build Coastguard Worker 
395*2d1272b8SAndroid Build Coastguard Worker     _show_name ("Postscript name", name_id);
396*2d1272b8SAndroid Build Coastguard Worker   }
_show_versioninfo_t397*2d1272b8SAndroid Build Coastguard Worker   void _show_version ()		{ _show_name ("Version", 5); }
398*2d1272b8SAndroid Build Coastguard Worker 
_has_blobinfo_t399*2d1272b8SAndroid Build Coastguard Worker   bool _has_blob (hb_tag_t tag)
400*2d1272b8SAndroid Build Coastguard Worker   {
401*2d1272b8SAndroid Build Coastguard Worker     hb_blob_t *blob = hb_face_reference_table (face, tag);
402*2d1272b8SAndroid Build Coastguard Worker     bool ret = hb_blob_get_length (blob);
403*2d1272b8SAndroid Build Coastguard Worker     hb_blob_destroy (blob);
404*2d1272b8SAndroid Build Coastguard Worker     return ret;
405*2d1272b8SAndroid Build Coastguard Worker   }
406*2d1272b8SAndroid Build Coastguard Worker 
_show_technologyinfo_t407*2d1272b8SAndroid Build Coastguard Worker   void _show_technology ()
408*2d1272b8SAndroid Build Coastguard Worker   {
409*2d1272b8SAndroid Build Coastguard Worker     if (_has_blob (HB_TAG('g','l','y','f')))
410*2d1272b8SAndroid Build Coastguard Worker       printf ("Has TrueType outlines\n");
411*2d1272b8SAndroid Build Coastguard Worker     if (_has_blob (HB_TAG('C','F','F',' ')) || _has_blob (HB_TAG('C','F','F','2')))
412*2d1272b8SAndroid Build Coastguard Worker       printf ("Has Postscript outlines\n");
413*2d1272b8SAndroid Build Coastguard Worker 
414*2d1272b8SAndroid Build Coastguard Worker     if (_has_blob (HB_TAG('f','p','g','m')) || _has_blob (HB_TAG('p','r','e','p')) || _has_blob (HB_TAG('c','v','t',' ')))
415*2d1272b8SAndroid Build Coastguard Worker       printf ("Has TrueType hinting\n");
416*2d1272b8SAndroid Build Coastguard Worker 
417*2d1272b8SAndroid Build Coastguard Worker     if (_has_blob (HB_TAG('G','S','U','B')) || _has_blob (HB_TAG('G','P','O','S')))
418*2d1272b8SAndroid Build Coastguard Worker       printf ("Has OpenType layout\n");
419*2d1272b8SAndroid Build Coastguard Worker     if (_has_blob (HB_TAG('m','o','r','x')) || _has_blob (HB_TAG('k','e','r','x')))
420*2d1272b8SAndroid Build Coastguard Worker       printf ("Has AAT layout\n");
421*2d1272b8SAndroid Build Coastguard Worker     if (_has_blob (HB_TAG('S','i','l','f')))
422*2d1272b8SAndroid Build Coastguard Worker       printf ("Has Graphite layout\n");
423*2d1272b8SAndroid Build Coastguard Worker     if (_has_blob (HB_TAG('k','e','r','n')))
424*2d1272b8SAndroid Build Coastguard Worker       printf ("Has legacy kerning\n");
425*2d1272b8SAndroid Build Coastguard Worker 
426*2d1272b8SAndroid Build Coastguard Worker     if (_has_blob (HB_TAG('E','B','D','T')))
427*2d1272b8SAndroid Build Coastguard Worker       printf ("Has monochrome bitmaps\n");
428*2d1272b8SAndroid Build Coastguard Worker 
429*2d1272b8SAndroid Build Coastguard Worker     if (_has_blob (HB_TAG('C','B','D','T')) || _has_blob (HB_TAG('s','b','i','x')))
430*2d1272b8SAndroid Build Coastguard Worker       printf ("Has color bitmaps\n");
431*2d1272b8SAndroid Build Coastguard Worker     if (_has_blob (HB_TAG('S','V','G',' ')))
432*2d1272b8SAndroid Build Coastguard Worker       printf ("Has color SVGs\n");
433*2d1272b8SAndroid Build Coastguard Worker     if (_has_blob (HB_TAG('C','O','L','R')))
434*2d1272b8SAndroid Build Coastguard Worker       printf ("Has color paintings\n");
435*2d1272b8SAndroid Build Coastguard Worker 
436*2d1272b8SAndroid Build Coastguard Worker     if (_has_blob (HB_TAG('f','v','a','r')))  printf ("Has variations\n");
437*2d1272b8SAndroid Build Coastguard Worker   }
438*2d1272b8SAndroid Build Coastguard Worker 
_show_unicode_countinfo_t439*2d1272b8SAndroid Build Coastguard Worker   void _show_unicode_count ()
440*2d1272b8SAndroid Build Coastguard Worker   {
441*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
442*2d1272b8SAndroid Build Coastguard Worker     {
443*2d1272b8SAndroid Build Coastguard Worker       printf ("Unicode count: ");
444*2d1272b8SAndroid Build Coastguard Worker     }
445*2d1272b8SAndroid Build Coastguard Worker 
446*2d1272b8SAndroid Build Coastguard Worker     hb_set_t *unicodes = hb_set_create ();
447*2d1272b8SAndroid Build Coastguard Worker     hb_face_collect_unicodes (face, unicodes);
448*2d1272b8SAndroid Build Coastguard Worker 
449*2d1272b8SAndroid Build Coastguard Worker     printf ("%u\n", hb_set_get_population (unicodes));
450*2d1272b8SAndroid Build Coastguard Worker 
451*2d1272b8SAndroid Build Coastguard Worker     hb_set_destroy (unicodes);
452*2d1272b8SAndroid Build Coastguard Worker   }
453*2d1272b8SAndroid Build Coastguard Worker 
_show_glyph_countinfo_t454*2d1272b8SAndroid Build Coastguard Worker   void _show_glyph_count ()
455*2d1272b8SAndroid Build Coastguard Worker   {
456*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
457*2d1272b8SAndroid Build Coastguard Worker     {
458*2d1272b8SAndroid Build Coastguard Worker       printf ("Glyph count: ");
459*2d1272b8SAndroid Build Coastguard Worker     }
460*2d1272b8SAndroid Build Coastguard Worker 
461*2d1272b8SAndroid Build Coastguard Worker     printf ("%u\n", hb_face_get_glyph_count (face));
462*2d1272b8SAndroid Build Coastguard Worker   }
463*2d1272b8SAndroid Build Coastguard Worker 
_show_upeminfo_t464*2d1272b8SAndroid Build Coastguard Worker   void _show_upem ()
465*2d1272b8SAndroid Build Coastguard Worker   {
466*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
467*2d1272b8SAndroid Build Coastguard Worker     {
468*2d1272b8SAndroid Build Coastguard Worker       printf ("Units-Per-EM: ");
469*2d1272b8SAndroid Build Coastguard Worker     }
470*2d1272b8SAndroid Build Coastguard Worker 
471*2d1272b8SAndroid Build Coastguard Worker     printf ("%u\n", hb_face_get_upem (face));
472*2d1272b8SAndroid Build Coastguard Worker   }
473*2d1272b8SAndroid Build Coastguard Worker 
_show_extentsinfo_t474*2d1272b8SAndroid Build Coastguard Worker   void _show_extents ()
475*2d1272b8SAndroid Build Coastguard Worker   {
476*2d1272b8SAndroid Build Coastguard Worker     hb_font_extents_t extents;
477*2d1272b8SAndroid Build Coastguard Worker     hb_font_get_extents_for_direction (font, direction, &extents);
478*2d1272b8SAndroid Build Coastguard Worker 
479*2d1272b8SAndroid Build Coastguard Worker     if (verbose) printf ("Ascender: ");
480*2d1272b8SAndroid Build Coastguard Worker     printf ("%d\n", extents.ascender);
481*2d1272b8SAndroid Build Coastguard Worker 
482*2d1272b8SAndroid Build Coastguard Worker     if (verbose) printf ("Descender: ");
483*2d1272b8SAndroid Build Coastguard Worker     printf ("%d\n", extents.descender);
484*2d1272b8SAndroid Build Coastguard Worker 
485*2d1272b8SAndroid Build Coastguard Worker     if (verbose) printf ("Line gap: ");
486*2d1272b8SAndroid Build Coastguard Worker     printf ("%d\n", extents.line_gap);
487*2d1272b8SAndroid Build Coastguard Worker   }
488*2d1272b8SAndroid Build Coastguard Worker 
_get_nameinfo_t489*2d1272b8SAndroid Build Coastguard Worker   void _get_name ()
490*2d1272b8SAndroid Build Coastguard Worker   {
491*2d1272b8SAndroid Build Coastguard Worker     for (char **p = get_name; *p; p++)
492*2d1272b8SAndroid Build Coastguard Worker     {
493*2d1272b8SAndroid Build Coastguard Worker       hb_ot_name_id_t name_id = (hb_ot_name_id_t) atoi (*p);
494*2d1272b8SAndroid Build Coastguard Worker       _show_name (*p, name_id);
495*2d1272b8SAndroid Build Coastguard Worker     }
496*2d1272b8SAndroid Build Coastguard Worker   }
497*2d1272b8SAndroid Build Coastguard Worker 
_get_styleinfo_t498*2d1272b8SAndroid Build Coastguard Worker   void _get_style ()
499*2d1272b8SAndroid Build Coastguard Worker   {
500*2d1272b8SAndroid Build Coastguard Worker     for (char **p = get_style; *p; p++)
501*2d1272b8SAndroid Build Coastguard Worker     {
502*2d1272b8SAndroid Build Coastguard Worker       hb_style_tag_t tag = (hb_style_tag_t) hb_tag_from_string (*p, -1);
503*2d1272b8SAndroid Build Coastguard Worker 
504*2d1272b8SAndroid Build Coastguard Worker       if (verbose)
505*2d1272b8SAndroid Build Coastguard Worker 	printf ("Style %c%c%c%c: ", HB_UNTAG (tag));
506*2d1272b8SAndroid Build Coastguard Worker 
507*2d1272b8SAndroid Build Coastguard Worker       float v = hb_style_get_value (font, tag);
508*2d1272b8SAndroid Build Coastguard Worker       printf ("%g\n", (double) v);
509*2d1272b8SAndroid Build Coastguard Worker     }
510*2d1272b8SAndroid Build Coastguard Worker   }
511*2d1272b8SAndroid Build Coastguard Worker 
_get_metricinfo_t512*2d1272b8SAndroid Build Coastguard Worker   void _get_metric ()
513*2d1272b8SAndroid Build Coastguard Worker   {
514*2d1272b8SAndroid Build Coastguard Worker     bool fallback = false;
515*2d1272b8SAndroid Build Coastguard Worker     for (char **p = get_metric; *p; p++)
516*2d1272b8SAndroid Build Coastguard Worker     {
517*2d1272b8SAndroid Build Coastguard Worker       hb_ot_metrics_tag_t tag = (hb_ot_metrics_tag_t) hb_tag_from_string (*p, -1);
518*2d1272b8SAndroid Build Coastguard Worker       hb_position_t position;
519*2d1272b8SAndroid Build Coastguard Worker 
520*2d1272b8SAndroid Build Coastguard Worker       if (verbose)
521*2d1272b8SAndroid Build Coastguard Worker 	printf ("Metric %c%c%c%c: ", HB_UNTAG (tag));
522*2d1272b8SAndroid Build Coastguard Worker 
523*2d1272b8SAndroid Build Coastguard Worker       if (hb_ot_metrics_get_position (font, tag, &position))
524*2d1272b8SAndroid Build Coastguard Worker 	printf ("%d	\n", position);
525*2d1272b8SAndroid Build Coastguard Worker       else
526*2d1272b8SAndroid Build Coastguard Worker       {
527*2d1272b8SAndroid Build Coastguard Worker 	hb_ot_metrics_get_position_with_fallback (font, tag, &position);
528*2d1272b8SAndroid Build Coastguard Worker 	printf ("%d	*\n", position);
529*2d1272b8SAndroid Build Coastguard Worker 	fallback = true;
530*2d1272b8SAndroid Build Coastguard Worker       }
531*2d1272b8SAndroid Build Coastguard Worker     }
532*2d1272b8SAndroid Build Coastguard Worker 
533*2d1272b8SAndroid Build Coastguard Worker     if (verbose && fallback)
534*2d1272b8SAndroid Build Coastguard Worker     {
535*2d1272b8SAndroid Build Coastguard Worker       printf ("\n[*] Fallback value\n");
536*2d1272b8SAndroid Build Coastguard Worker     }
537*2d1272b8SAndroid Build Coastguard Worker   }
538*2d1272b8SAndroid Build Coastguard Worker 
_get_baselineinfo_t539*2d1272b8SAndroid Build Coastguard Worker   void _get_baseline ()
540*2d1272b8SAndroid Build Coastguard Worker   {
541*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
542*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
543*2d1272b8SAndroid Build Coastguard Worker     unsigned script_count = HB_OT_MAX_TAGS_PER_SCRIPT;
544*2d1272b8SAndroid Build Coastguard Worker     unsigned language_count = HB_OT_MAX_TAGS_PER_LANGUAGE;
545*2d1272b8SAndroid Build Coastguard Worker 
546*2d1272b8SAndroid Build Coastguard Worker     hb_ot_tags_from_script_and_language (script, language,
547*2d1272b8SAndroid Build Coastguard Worker 					 &script_count, script_tags,
548*2d1272b8SAndroid Build Coastguard Worker 					 &language_count, language_tags);
549*2d1272b8SAndroid Build Coastguard Worker 
550*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t script_tag = script_count ? script_tags[script_count - 1] : HB_TAG_NONE;
551*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t language_tag = language_count ? language_tags[0] : HB_TAG_NONE;
552*2d1272b8SAndroid Build Coastguard Worker 
553*2d1272b8SAndroid Build Coastguard Worker     if (ot_script_str)
554*2d1272b8SAndroid Build Coastguard Worker       script_tag = hb_tag_from_string (ot_script_str, -1);
555*2d1272b8SAndroid Build Coastguard Worker     if (ot_language_str)
556*2d1272b8SAndroid Build Coastguard Worker       language_tag = hb_tag_from_string (ot_language_str, -1);
557*2d1272b8SAndroid Build Coastguard Worker 
558*2d1272b8SAndroid Build Coastguard Worker 
559*2d1272b8SAndroid Build Coastguard Worker     bool fallback = false;
560*2d1272b8SAndroid Build Coastguard Worker     for (char **p = get_baseline; *p; p++)
561*2d1272b8SAndroid Build Coastguard Worker     {
562*2d1272b8SAndroid Build Coastguard Worker       hb_ot_layout_baseline_tag_t tag = (hb_ot_layout_baseline_tag_t) hb_tag_from_string (*p, -1);
563*2d1272b8SAndroid Build Coastguard Worker       hb_position_t position;
564*2d1272b8SAndroid Build Coastguard Worker 
565*2d1272b8SAndroid Build Coastguard Worker       if (verbose)
566*2d1272b8SAndroid Build Coastguard Worker 	printf ("Baseline %c%c%c%c: ", HB_UNTAG (tag));
567*2d1272b8SAndroid Build Coastguard Worker 
568*2d1272b8SAndroid Build Coastguard Worker       if (hb_ot_layout_get_baseline (font, tag, direction, script_tag, language_tag, &position))
569*2d1272b8SAndroid Build Coastguard Worker 	printf ("%d	\n", position);
570*2d1272b8SAndroid Build Coastguard Worker       else
571*2d1272b8SAndroid Build Coastguard Worker       {
572*2d1272b8SAndroid Build Coastguard Worker 	hb_ot_layout_get_baseline_with_fallback (font, tag, direction, script_tag, language_tag, &position);
573*2d1272b8SAndroid Build Coastguard Worker 	printf ("%d	*\n", position);
574*2d1272b8SAndroid Build Coastguard Worker 	fallback = true;
575*2d1272b8SAndroid Build Coastguard Worker       }
576*2d1272b8SAndroid Build Coastguard Worker     }
577*2d1272b8SAndroid Build Coastguard Worker 
578*2d1272b8SAndroid Build Coastguard Worker     if (verbose && fallback)
579*2d1272b8SAndroid Build Coastguard Worker     {
580*2d1272b8SAndroid Build Coastguard Worker       printf ("\n[*] Fallback value\n");
581*2d1272b8SAndroid Build Coastguard Worker     }
582*2d1272b8SAndroid Build Coastguard Worker   }
583*2d1272b8SAndroid Build Coastguard Worker 
_get_metainfo_t584*2d1272b8SAndroid Build Coastguard Worker   void _get_meta ()
585*2d1272b8SAndroid Build Coastguard Worker   {
586*2d1272b8SAndroid Build Coastguard Worker     for (char **p = get_meta; *p; p++)
587*2d1272b8SAndroid Build Coastguard Worker     {
588*2d1272b8SAndroid Build Coastguard Worker       hb_ot_meta_tag_t tag = (hb_ot_meta_tag_t) hb_tag_from_string (*p, -1);
589*2d1272b8SAndroid Build Coastguard Worker 
590*2d1272b8SAndroid Build Coastguard Worker       hb_blob_t *blob = hb_ot_meta_reference_entry (face, tag);
591*2d1272b8SAndroid Build Coastguard Worker 
592*2d1272b8SAndroid Build Coastguard Worker       if (verbose)
593*2d1272b8SAndroid Build Coastguard Worker 	printf ("Meta %c%c%c%c: ", HB_UNTAG (tag));
594*2d1272b8SAndroid Build Coastguard Worker 
595*2d1272b8SAndroid Build Coastguard Worker       printf ("%.*s\n",
596*2d1272b8SAndroid Build Coastguard Worker 	      (int) hb_blob_get_length (blob),
597*2d1272b8SAndroid Build Coastguard Worker 	      hb_blob_get_data (blob, nullptr));
598*2d1272b8SAndroid Build Coastguard Worker 
599*2d1272b8SAndroid Build Coastguard Worker       hb_blob_destroy (blob);
600*2d1272b8SAndroid Build Coastguard Worker     }
601*2d1272b8SAndroid Build Coastguard Worker   }
602*2d1272b8SAndroid Build Coastguard Worker 
603*2d1272b8SAndroid Build Coastguard Worker   void
_get_tableinfo_t604*2d1272b8SAndroid Build Coastguard Worker   _get_table ()
605*2d1272b8SAndroid Build Coastguard Worker   {
606*2d1272b8SAndroid Build Coastguard Worker     hb_blob_t *blob = hb_face_reference_table (face, hb_tag_from_string (get_table, -1));
607*2d1272b8SAndroid Build Coastguard Worker     unsigned count = 0;
608*2d1272b8SAndroid Build Coastguard Worker     const char *data = hb_blob_get_data (blob, &count);
609*2d1272b8SAndroid Build Coastguard Worker     fwrite (data, 1, count, stdout);
610*2d1272b8SAndroid Build Coastguard Worker     hb_blob_destroy (blob);
611*2d1272b8SAndroid Build Coastguard Worker   }
612*2d1272b8SAndroid Build Coastguard Worker 
_list_namesinfo_t613*2d1272b8SAndroid Build Coastguard Worker   void _list_names ()
614*2d1272b8SAndroid Build Coastguard Worker   {
615*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
616*2d1272b8SAndroid Build Coastguard Worker     {
617*2d1272b8SAndroid Build Coastguard Worker       separator ();
618*2d1272b8SAndroid Build Coastguard Worker       printf ("Name information:\n\n");
619*2d1272b8SAndroid Build Coastguard Worker       printf ("Id: Name			Text\n------------------------------------\n");
620*2d1272b8SAndroid Build Coastguard Worker     }
621*2d1272b8SAndroid Build Coastguard Worker 
622*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_HAS_GOBJECT
623*2d1272b8SAndroid Build Coastguard Worker     GEnumClass *enum_class = (GEnumClass *) g_type_class_ref ((GType) HB_GOBJECT_TYPE_OT_NAME_ID_PREDEFINED);
624*2d1272b8SAndroid Build Coastguard Worker #endif
625*2d1272b8SAndroid Build Coastguard Worker 
626*2d1272b8SAndroid Build Coastguard Worker     unsigned count;
627*2d1272b8SAndroid Build Coastguard Worker     const auto *entries = hb_ot_name_list_names (face, &count);
628*2d1272b8SAndroid Build Coastguard Worker     for (unsigned i = 0; i < count; i++)
629*2d1272b8SAndroid Build Coastguard Worker     {
630*2d1272b8SAndroid Build Coastguard Worker       char name[16384];
631*2d1272b8SAndroid Build Coastguard Worker       unsigned name_len = sizeof name;
632*2d1272b8SAndroid Build Coastguard Worker       _hb_ot_name_get_utf8 (face, entries[i].name_id,
633*2d1272b8SAndroid Build Coastguard Worker 			    language,
634*2d1272b8SAndroid Build Coastguard Worker 			    &name_len, name);
635*2d1272b8SAndroid Build Coastguard Worker 
636*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_HAS_GOBJECT
637*2d1272b8SAndroid Build Coastguard Worker       if (verbose)
638*2d1272b8SAndroid Build Coastguard Worker       {
639*2d1272b8SAndroid Build Coastguard Worker 	GEnumValue *enum_value = g_enum_get_value (enum_class, entries[i].name_id);
640*2d1272b8SAndroid Build Coastguard Worker 	printf ("%u: %-27s	%s\n", entries[i].name_id, enum_value ? enum_value->value_nick : "", name);
641*2d1272b8SAndroid Build Coastguard Worker       }
642*2d1272b8SAndroid Build Coastguard Worker       else
643*2d1272b8SAndroid Build Coastguard Worker #endif
644*2d1272b8SAndroid Build Coastguard Worker 	printf ("%u	%s\n", entries[i].name_id, name);
645*2d1272b8SAndroid Build Coastguard Worker     }
646*2d1272b8SAndroid Build Coastguard Worker   }
647*2d1272b8SAndroid Build Coastguard Worker 
648*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_HAS_GOBJECT
_list_styleinfo_t649*2d1272b8SAndroid Build Coastguard Worker   void _list_style ()
650*2d1272b8SAndroid Build Coastguard Worker   {
651*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
652*2d1272b8SAndroid Build Coastguard Worker     {
653*2d1272b8SAndroid Build Coastguard Worker       separator ();
654*2d1272b8SAndroid Build Coastguard Worker       printf ("Style information:\n\n");
655*2d1272b8SAndroid Build Coastguard Worker       printf ("Tag:  Name				Value\n---------------------------------------------\n");
656*2d1272b8SAndroid Build Coastguard Worker     }
657*2d1272b8SAndroid Build Coastguard Worker 
658*2d1272b8SAndroid Build Coastguard Worker     GEnumClass *enum_class = (GEnumClass *) g_type_class_ref ((GType) HB_GOBJECT_TYPE_STYLE_TAG);
659*2d1272b8SAndroid Build Coastguard Worker 
660*2d1272b8SAndroid Build Coastguard Worker     unsigned count = enum_class->n_values;
661*2d1272b8SAndroid Build Coastguard Worker     const auto *entries = enum_class->values;
662*2d1272b8SAndroid Build Coastguard Worker     for (unsigned i = 0; i < count; i++)
663*2d1272b8SAndroid Build Coastguard Worker     {
664*2d1272b8SAndroid Build Coastguard Worker 	float v = hb_style_get_value (font, (hb_style_tag_t) entries[i].value);
665*2d1272b8SAndroid Build Coastguard Worker 	printf ("%c%c%c%c", HB_UNTAG(entries[i].value));
666*2d1272b8SAndroid Build Coastguard Worker 	if (verbose)
667*2d1272b8SAndroid Build Coastguard Worker 	  printf (": %-33s", entries[i].value_nick);
668*2d1272b8SAndroid Build Coastguard Worker 	printf ("	%g\n", (double) v);
669*2d1272b8SAndroid Build Coastguard Worker     }
670*2d1272b8SAndroid Build Coastguard Worker   }
671*2d1272b8SAndroid Build Coastguard Worker 
_list_metricsinfo_t672*2d1272b8SAndroid Build Coastguard Worker   void _list_metrics ()
673*2d1272b8SAndroid Build Coastguard Worker   {
674*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
675*2d1272b8SAndroid Build Coastguard Worker     {
676*2d1272b8SAndroid Build Coastguard Worker       separator ();
677*2d1272b8SAndroid Build Coastguard Worker       printf ("Metrics information:\n\n");
678*2d1272b8SAndroid Build Coastguard Worker       printf ("Tag:  Name				Value\n---------------------------------------------\n");
679*2d1272b8SAndroid Build Coastguard Worker     }
680*2d1272b8SAndroid Build Coastguard Worker 
681*2d1272b8SAndroid Build Coastguard Worker     GEnumClass *enum_class = (GEnumClass *) g_type_class_ref ((GType) HB_GOBJECT_TYPE_OT_METRICS_TAG);
682*2d1272b8SAndroid Build Coastguard Worker 
683*2d1272b8SAndroid Build Coastguard Worker     bool any_fallback = false;
684*2d1272b8SAndroid Build Coastguard Worker 
685*2d1272b8SAndroid Build Coastguard Worker     unsigned count = enum_class->n_values;
686*2d1272b8SAndroid Build Coastguard Worker     const auto *entries = enum_class->values;
687*2d1272b8SAndroid Build Coastguard Worker     for (unsigned i = 0; i < count; i++)
688*2d1272b8SAndroid Build Coastguard Worker     {
689*2d1272b8SAndroid Build Coastguard Worker 	bool fallback = false;
690*2d1272b8SAndroid Build Coastguard Worker 	hb_position_t v;
691*2d1272b8SAndroid Build Coastguard Worker 	if (!hb_ot_metrics_get_position (font,
692*2d1272b8SAndroid Build Coastguard Worker 					(hb_ot_metrics_tag_t) entries[i].value,
693*2d1272b8SAndroid Build Coastguard Worker 					&v))
694*2d1272b8SAndroid Build Coastguard Worker 	{
695*2d1272b8SAndroid Build Coastguard Worker 	  hb_ot_metrics_get_position_with_fallback (font,
696*2d1272b8SAndroid Build Coastguard Worker 						    (hb_ot_metrics_tag_t) entries[i].value,
697*2d1272b8SAndroid Build Coastguard Worker 						    &v);
698*2d1272b8SAndroid Build Coastguard Worker 	  any_fallback = fallback = true;
699*2d1272b8SAndroid Build Coastguard Worker 	}
700*2d1272b8SAndroid Build Coastguard Worker 	printf ("%c%c%c%c", HB_UNTAG(entries[i].value));
701*2d1272b8SAndroid Build Coastguard Worker 	if (verbose)
702*2d1272b8SAndroid Build Coastguard Worker 	  printf (": %-33s", entries[i].value_nick);
703*2d1272b8SAndroid Build Coastguard Worker 	printf ("	%d	", v);
704*2d1272b8SAndroid Build Coastguard Worker 
705*2d1272b8SAndroid Build Coastguard Worker 	if (fallback)
706*2d1272b8SAndroid Build Coastguard Worker 	  printf ("*");
707*2d1272b8SAndroid Build Coastguard Worker 	printf ("\n");
708*2d1272b8SAndroid Build Coastguard Worker     }
709*2d1272b8SAndroid Build Coastguard Worker 
710*2d1272b8SAndroid Build Coastguard Worker     if (verbose && any_fallback)
711*2d1272b8SAndroid Build Coastguard Worker     {
712*2d1272b8SAndroid Build Coastguard Worker       printf ("\n[*] Fallback value\n");
713*2d1272b8SAndroid Build Coastguard Worker     }
714*2d1272b8SAndroid Build Coastguard Worker   }
715*2d1272b8SAndroid Build Coastguard Worker 
_list_baselinesinfo_t716*2d1272b8SAndroid Build Coastguard Worker   void _list_baselines ()
717*2d1272b8SAndroid Build Coastguard Worker   {
718*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
719*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
720*2d1272b8SAndroid Build Coastguard Worker     unsigned script_count = HB_OT_MAX_TAGS_PER_SCRIPT;
721*2d1272b8SAndroid Build Coastguard Worker     unsigned language_count = HB_OT_MAX_TAGS_PER_LANGUAGE;
722*2d1272b8SAndroid Build Coastguard Worker 
723*2d1272b8SAndroid Build Coastguard Worker     hb_ot_tags_from_script_and_language (script, language,
724*2d1272b8SAndroid Build Coastguard Worker 					 &script_count, script_tags,
725*2d1272b8SAndroid Build Coastguard Worker 					 &language_count, language_tags);
726*2d1272b8SAndroid Build Coastguard Worker 
727*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t script_tag = script_count ? script_tags[script_count - 1] : HB_TAG_NONE;
728*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t language_tag = language_count ? language_tags[0] : HB_TAG_NONE;
729*2d1272b8SAndroid Build Coastguard Worker 
730*2d1272b8SAndroid Build Coastguard Worker     if (ot_script_str)
731*2d1272b8SAndroid Build Coastguard Worker       script_tag = hb_tag_from_string (ot_script_str, -1);
732*2d1272b8SAndroid Build Coastguard Worker     if (ot_language_str)
733*2d1272b8SAndroid Build Coastguard Worker       language_tag = hb_tag_from_string (ot_language_str, -1);
734*2d1272b8SAndroid Build Coastguard Worker 
735*2d1272b8SAndroid Build Coastguard Worker 
736*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
737*2d1272b8SAndroid Build Coastguard Worker     {
738*2d1272b8SAndroid Build Coastguard Worker       separator ();
739*2d1272b8SAndroid Build Coastguard Worker       printf ("Baselines information:\n\n");
740*2d1272b8SAndroid Build Coastguard Worker       printf ("Tag:  Name				Value\n---------------------------------------------\n");
741*2d1272b8SAndroid Build Coastguard Worker     }
742*2d1272b8SAndroid Build Coastguard Worker 
743*2d1272b8SAndroid Build Coastguard Worker     GEnumClass *enum_class = (GEnumClass *) g_type_class_ref ((GType) HB_GOBJECT_TYPE_OT_LAYOUT_BASELINE_TAG);
744*2d1272b8SAndroid Build Coastguard Worker 
745*2d1272b8SAndroid Build Coastguard Worker     bool any_fallback = false;
746*2d1272b8SAndroid Build Coastguard Worker 
747*2d1272b8SAndroid Build Coastguard Worker     unsigned count = enum_class->n_values;
748*2d1272b8SAndroid Build Coastguard Worker     const auto *entries = enum_class->values;
749*2d1272b8SAndroid Build Coastguard Worker     for (unsigned i = 0; i < count; i++)
750*2d1272b8SAndroid Build Coastguard Worker     {
751*2d1272b8SAndroid Build Coastguard Worker 	bool fallback = false;
752*2d1272b8SAndroid Build Coastguard Worker 	hb_position_t v;
753*2d1272b8SAndroid Build Coastguard Worker 	if (!hb_ot_layout_get_baseline (font, (hb_ot_layout_baseline_tag_t) entries[i].value,
754*2d1272b8SAndroid Build Coastguard Worker 					direction, script_tag, language_tag,
755*2d1272b8SAndroid Build Coastguard Worker 					&v))
756*2d1272b8SAndroid Build Coastguard Worker 	{
757*2d1272b8SAndroid Build Coastguard Worker 	  hb_ot_layout_get_baseline_with_fallback (font, (hb_ot_layout_baseline_tag_t) entries[i].value,
758*2d1272b8SAndroid Build Coastguard Worker 						   direction, script_tag, language_tag,
759*2d1272b8SAndroid Build Coastguard Worker 						   &v);
760*2d1272b8SAndroid Build Coastguard Worker 	  any_fallback = fallback = true;
761*2d1272b8SAndroid Build Coastguard Worker 	}
762*2d1272b8SAndroid Build Coastguard Worker 	printf ("%c%c%c%c", HB_UNTAG(entries[i].value));
763*2d1272b8SAndroid Build Coastguard Worker 	if (verbose)
764*2d1272b8SAndroid Build Coastguard Worker 	  printf (": %-33s", entries[i].value_nick);
765*2d1272b8SAndroid Build Coastguard Worker 	printf ("	%d	", v);
766*2d1272b8SAndroid Build Coastguard Worker 
767*2d1272b8SAndroid Build Coastguard Worker 	if (fallback)
768*2d1272b8SAndroid Build Coastguard Worker 	  printf ("*");
769*2d1272b8SAndroid Build Coastguard Worker 	printf ("\n");
770*2d1272b8SAndroid Build Coastguard Worker     }
771*2d1272b8SAndroid Build Coastguard Worker 
772*2d1272b8SAndroid Build Coastguard Worker     if (verbose && any_fallback)
773*2d1272b8SAndroid Build Coastguard Worker     {
774*2d1272b8SAndroid Build Coastguard Worker       printf ("\n[*] Fallback value\n");
775*2d1272b8SAndroid Build Coastguard Worker     }
776*2d1272b8SAndroid Build Coastguard Worker   }
777*2d1272b8SAndroid Build Coastguard Worker #endif
778*2d1272b8SAndroid Build Coastguard Worker 
_list_tablesinfo_t779*2d1272b8SAndroid Build Coastguard Worker   void _list_tables ()
780*2d1272b8SAndroid Build Coastguard Worker   {
781*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
782*2d1272b8SAndroid Build Coastguard Worker     {
783*2d1272b8SAndroid Build Coastguard Worker       separator ();
784*2d1272b8SAndroid Build Coastguard Worker       printf ("Table information:\n\n");
785*2d1272b8SAndroid Build Coastguard Worker       printf ("Tag	Size\n------------\n");
786*2d1272b8SAndroid Build Coastguard Worker     }
787*2d1272b8SAndroid Build Coastguard Worker 
788*2d1272b8SAndroid Build Coastguard Worker     unsigned count = hb_face_get_table_tags (face, 0, nullptr, nullptr);
789*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t *tags = (hb_tag_t *) calloc (count, sizeof (hb_tag_t));
790*2d1272b8SAndroid Build Coastguard Worker     hb_face_get_table_tags (face, 0, &count, tags);
791*2d1272b8SAndroid Build Coastguard Worker 
792*2d1272b8SAndroid Build Coastguard Worker     for (unsigned i = 0; i < count; i++)
793*2d1272b8SAndroid Build Coastguard Worker     {
794*2d1272b8SAndroid Build Coastguard Worker       hb_tag_t tag = tags[i];
795*2d1272b8SAndroid Build Coastguard Worker 
796*2d1272b8SAndroid Build Coastguard Worker       hb_blob_t *blob = hb_face_reference_table (face, tag);
797*2d1272b8SAndroid Build Coastguard Worker 
798*2d1272b8SAndroid Build Coastguard Worker       printf ("%c%c%c%c %8u bytes\n", HB_UNTAG (tag), hb_blob_get_length (blob));
799*2d1272b8SAndroid Build Coastguard Worker 
800*2d1272b8SAndroid Build Coastguard Worker       hb_blob_destroy (blob);
801*2d1272b8SAndroid Build Coastguard Worker     }
802*2d1272b8SAndroid Build Coastguard Worker 
803*2d1272b8SAndroid Build Coastguard Worker     free (tags);
804*2d1272b8SAndroid Build Coastguard Worker   }
805*2d1272b8SAndroid Build Coastguard Worker 
806*2d1272b8SAndroid Build Coastguard Worker   void
_list_unicodesinfo_t807*2d1272b8SAndroid Build Coastguard Worker   _list_unicodes ()
808*2d1272b8SAndroid Build Coastguard Worker   {
809*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
810*2d1272b8SAndroid Build Coastguard Worker     {
811*2d1272b8SAndroid Build Coastguard Worker       separator ();
812*2d1272b8SAndroid Build Coastguard Worker       printf ("Character-set information:\n\n");
813*2d1272b8SAndroid Build Coastguard Worker       printf ("Unicode	Glyph name\n------------------\n");
814*2d1272b8SAndroid Build Coastguard Worker     }
815*2d1272b8SAndroid Build Coastguard Worker 
816*2d1272b8SAndroid Build Coastguard Worker     hb_set_t *unicodes = hb_set_create ();
817*2d1272b8SAndroid Build Coastguard Worker     hb_map_t *cmap = hb_map_create ();
818*2d1272b8SAndroid Build Coastguard Worker 
819*2d1272b8SAndroid Build Coastguard Worker     hb_face_collect_nominal_glyph_mapping (face, cmap, unicodes);
820*2d1272b8SAndroid Build Coastguard Worker 
821*2d1272b8SAndroid Build Coastguard Worker     for (hb_codepoint_t u = HB_SET_VALUE_INVALID;
822*2d1272b8SAndroid Build Coastguard Worker 	 hb_set_next (unicodes, &u);)
823*2d1272b8SAndroid Build Coastguard Worker     {
824*2d1272b8SAndroid Build Coastguard Worker       hb_codepoint_t gid = hb_map_get (cmap, u);
825*2d1272b8SAndroid Build Coastguard Worker 
826*2d1272b8SAndroid Build Coastguard Worker       char glyphname[128];
827*2d1272b8SAndroid Build Coastguard Worker       hb_font_glyph_to_string (font, gid,
828*2d1272b8SAndroid Build Coastguard Worker 			       glyphname, sizeof glyphname);
829*2d1272b8SAndroid Build Coastguard Worker 
830*2d1272b8SAndroid Build Coastguard Worker       printf ("U+%04X	%s\n", u, glyphname);
831*2d1272b8SAndroid Build Coastguard Worker     }
832*2d1272b8SAndroid Build Coastguard Worker 
833*2d1272b8SAndroid Build Coastguard Worker     hb_map_destroy (cmap);
834*2d1272b8SAndroid Build Coastguard Worker 
835*2d1272b8SAndroid Build Coastguard Worker 
836*2d1272b8SAndroid Build Coastguard Worker     /* List variation-selector sequences. */
837*2d1272b8SAndroid Build Coastguard Worker     hb_set_t *vars = hb_set_create ();
838*2d1272b8SAndroid Build Coastguard Worker 
839*2d1272b8SAndroid Build Coastguard Worker     hb_face_collect_variation_selectors (face, vars);
840*2d1272b8SAndroid Build Coastguard Worker 
841*2d1272b8SAndroid Build Coastguard Worker     for (hb_codepoint_t vs = HB_SET_VALUE_INVALID;
842*2d1272b8SAndroid Build Coastguard Worker 	 hb_set_next (vars, &vs);)
843*2d1272b8SAndroid Build Coastguard Worker     {
844*2d1272b8SAndroid Build Coastguard Worker       hb_set_clear (unicodes);
845*2d1272b8SAndroid Build Coastguard Worker       hb_face_collect_variation_unicodes (face, vs, unicodes);
846*2d1272b8SAndroid Build Coastguard Worker 
847*2d1272b8SAndroid Build Coastguard Worker       for (hb_codepoint_t u = HB_SET_VALUE_INVALID;
848*2d1272b8SAndroid Build Coastguard Worker 	   hb_set_next (unicodes, &u);)
849*2d1272b8SAndroid Build Coastguard Worker       {
850*2d1272b8SAndroid Build Coastguard Worker 	hb_codepoint_t gid = 0;
851*2d1272b8SAndroid Build Coastguard Worker 	HB_UNUSED bool b = hb_font_get_variation_glyph (font, u, vs, &gid);
852*2d1272b8SAndroid Build Coastguard Worker 	assert (b);
853*2d1272b8SAndroid Build Coastguard Worker 
854*2d1272b8SAndroid Build Coastguard Worker 	char glyphname[128];
855*2d1272b8SAndroid Build Coastguard Worker 	hb_font_glyph_to_string (font, gid,
856*2d1272b8SAndroid Build Coastguard Worker 				 glyphname, sizeof glyphname);
857*2d1272b8SAndroid Build Coastguard Worker 
858*2d1272b8SAndroid Build Coastguard Worker 	printf ("U+%04X,U+%04X	%s\n", vs, u, glyphname);
859*2d1272b8SAndroid Build Coastguard Worker       }
860*2d1272b8SAndroid Build Coastguard Worker     }
861*2d1272b8SAndroid Build Coastguard Worker 
862*2d1272b8SAndroid Build Coastguard Worker     hb_set_destroy (vars);
863*2d1272b8SAndroid Build Coastguard Worker     hb_set_destroy (unicodes);
864*2d1272b8SAndroid Build Coastguard Worker   }
865*2d1272b8SAndroid Build Coastguard Worker 
866*2d1272b8SAndroid Build Coastguard Worker   void
_list_glyphsinfo_t867*2d1272b8SAndroid Build Coastguard Worker   _list_glyphs ()
868*2d1272b8SAndroid Build Coastguard Worker   {
869*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
870*2d1272b8SAndroid Build Coastguard Worker     {
871*2d1272b8SAndroid Build Coastguard Worker       separator ();
872*2d1272b8SAndroid Build Coastguard Worker       printf ("Glyph-set information:\n\n");
873*2d1272b8SAndroid Build Coastguard Worker       printf ("GlyphID	Glyph name\n------------------\n");
874*2d1272b8SAndroid Build Coastguard Worker     }
875*2d1272b8SAndroid Build Coastguard Worker 
876*2d1272b8SAndroid Build Coastguard Worker     unsigned num_glyphs = hb_face_get_glyph_count (face);
877*2d1272b8SAndroid Build Coastguard Worker 
878*2d1272b8SAndroid Build Coastguard Worker     for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
879*2d1272b8SAndroid Build Coastguard Worker     {
880*2d1272b8SAndroid Build Coastguard Worker       char glyphname[128];
881*2d1272b8SAndroid Build Coastguard Worker       hb_font_glyph_to_string (font, gid,
882*2d1272b8SAndroid Build Coastguard Worker 			       glyphname, sizeof glyphname);
883*2d1272b8SAndroid Build Coastguard Worker 
884*2d1272b8SAndroid Build Coastguard Worker       printf ("%u	%s\n", gid, glyphname);
885*2d1272b8SAndroid Build Coastguard Worker     }
886*2d1272b8SAndroid Build Coastguard Worker   }
887*2d1272b8SAndroid Build Coastguard Worker 
888*2d1272b8SAndroid Build Coastguard Worker   void
_list_scriptsinfo_t889*2d1272b8SAndroid Build Coastguard Worker   _list_scripts ()
890*2d1272b8SAndroid Build Coastguard Worker   {
891*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
892*2d1272b8SAndroid Build Coastguard Worker     {
893*2d1272b8SAndroid Build Coastguard Worker       separator ();
894*2d1272b8SAndroid Build Coastguard Worker       printf ("Layout script information:\n\n");
895*2d1272b8SAndroid Build Coastguard Worker     }
896*2d1272b8SAndroid Build Coastguard Worker 
897*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t table_tags[] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS, HB_TAG_NONE};
898*2d1272b8SAndroid Build Coastguard Worker 
899*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; table_tags[i]; i++)
900*2d1272b8SAndroid Build Coastguard Worker     {
901*2d1272b8SAndroid Build Coastguard Worker       if (verbose) printf ("Table: ");
902*2d1272b8SAndroid Build Coastguard Worker       printf ("%c%c%c%c\n", HB_UNTAG (table_tags[i]));
903*2d1272b8SAndroid Build Coastguard Worker 
904*2d1272b8SAndroid Build Coastguard Worker       hb_tag_t script_array[32];
905*2d1272b8SAndroid Build Coastguard Worker       unsigned script_count = sizeof script_array / sizeof script_array[0];
906*2d1272b8SAndroid Build Coastguard Worker       unsigned script_offset = 0;
907*2d1272b8SAndroid Build Coastguard Worker       do
908*2d1272b8SAndroid Build Coastguard Worker       {
909*2d1272b8SAndroid Build Coastguard Worker 	hb_ot_layout_table_get_script_tags (face, table_tags[i],
910*2d1272b8SAndroid Build Coastguard Worker 					    script_offset,
911*2d1272b8SAndroid Build Coastguard Worker 					    &script_count,
912*2d1272b8SAndroid Build Coastguard Worker 					    script_array);
913*2d1272b8SAndroid Build Coastguard Worker 
914*2d1272b8SAndroid Build Coastguard Worker 	for (unsigned script_index = 0; script_index < script_count; script_index++)
915*2d1272b8SAndroid Build Coastguard Worker 	{
916*2d1272b8SAndroid Build Coastguard Worker 	  printf ("	");
917*2d1272b8SAndroid Build Coastguard Worker 	  if (verbose) printf ("Script: ");
918*2d1272b8SAndroid Build Coastguard Worker 
919*2d1272b8SAndroid Build Coastguard Worker 	  hb_tag_t hb_sc = hb_script_to_iso15924_tag (hb_ot_tag_to_script (script_array[script_index]));
920*2d1272b8SAndroid Build Coastguard Worker 	  if (script_array[script_index] == HB_TAG ('D','F','L','T'))
921*2d1272b8SAndroid Build Coastguard Worker 	    hb_sc = HB_SCRIPT_COMMON;
922*2d1272b8SAndroid Build Coastguard Worker 
923*2d1272b8SAndroid Build Coastguard Worker 	  printf ("%c%c%c%c (%c%c%c%c)\n",
924*2d1272b8SAndroid Build Coastguard Worker 		  HB_UNTAG (hb_sc),
925*2d1272b8SAndroid Build Coastguard Worker 		  HB_UNTAG (script_array[script_index]));
926*2d1272b8SAndroid Build Coastguard Worker 
927*2d1272b8SAndroid Build Coastguard Worker 	  hb_tag_t language_array[32];
928*2d1272b8SAndroid Build Coastguard Worker 	  unsigned language_count = sizeof language_array / sizeof language_array[0];
929*2d1272b8SAndroid Build Coastguard Worker 	  unsigned language_offset = 0;
930*2d1272b8SAndroid Build Coastguard Worker 	  do
931*2d1272b8SAndroid Build Coastguard Worker 	  {
932*2d1272b8SAndroid Build Coastguard Worker 	    hb_ot_layout_script_get_language_tags (face, table_tags[i],
933*2d1272b8SAndroid Build Coastguard Worker 						   script_offset + script_index,
934*2d1272b8SAndroid Build Coastguard Worker 						   language_offset,
935*2d1272b8SAndroid Build Coastguard Worker 						   &language_count,
936*2d1272b8SAndroid Build Coastguard Worker 						   language_array);
937*2d1272b8SAndroid Build Coastguard Worker 
938*2d1272b8SAndroid Build Coastguard Worker 	    for (unsigned language_index = 0; language_index < language_count; language_index++)
939*2d1272b8SAndroid Build Coastguard Worker 	    {
940*2d1272b8SAndroid Build Coastguard Worker 	      printf ("		");
941*2d1272b8SAndroid Build Coastguard Worker 	      if (verbose) printf ("Language: ");
942*2d1272b8SAndroid Build Coastguard Worker 	      printf ("%s (%c%c%c%c)\n",
943*2d1272b8SAndroid Build Coastguard Worker 		      hb_language_to_string (hb_ot_tag_to_language (language_array[language_index])),
944*2d1272b8SAndroid Build Coastguard Worker 		      HB_UNTAG (language_array[language_index]));
945*2d1272b8SAndroid Build Coastguard Worker 	    }
946*2d1272b8SAndroid Build Coastguard Worker 
947*2d1272b8SAndroid Build Coastguard Worker 	    language_offset += language_count;
948*2d1272b8SAndroid Build Coastguard Worker 	  }
949*2d1272b8SAndroid Build Coastguard Worker 	  while (language_count == sizeof language_array / sizeof language_array[0]);
950*2d1272b8SAndroid Build Coastguard Worker 	}
951*2d1272b8SAndroid Build Coastguard Worker 
952*2d1272b8SAndroid Build Coastguard Worker 	script_offset += script_count;
953*2d1272b8SAndroid Build Coastguard Worker       }
954*2d1272b8SAndroid Build Coastguard Worker       while (script_count == sizeof script_array / sizeof script_array[0]);
955*2d1272b8SAndroid Build Coastguard Worker 
956*2d1272b8SAndroid Build Coastguard Worker     }
957*2d1272b8SAndroid Build Coastguard Worker 
958*2d1272b8SAndroid Build Coastguard Worker   }
959*2d1272b8SAndroid Build Coastguard Worker 
960*2d1272b8SAndroid Build Coastguard Worker   void
_list_features_no_scriptinfo_t961*2d1272b8SAndroid Build Coastguard Worker   _list_features_no_script ()
962*2d1272b8SAndroid Build Coastguard Worker   {
963*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
964*2d1272b8SAndroid Build Coastguard Worker     {
965*2d1272b8SAndroid Build Coastguard Worker       printf ("Showing all font features with duplicates removed.\n\n");
966*2d1272b8SAndroid Build Coastguard Worker     }
967*2d1272b8SAndroid Build Coastguard Worker 
968*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t table_tags[] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS, HB_TAG_NONE};
969*2d1272b8SAndroid Build Coastguard Worker 
970*2d1272b8SAndroid Build Coastguard Worker     hb_set_t *features = hb_set_create ();
971*2d1272b8SAndroid Build Coastguard Worker 
972*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; table_tags[i]; i++)
973*2d1272b8SAndroid Build Coastguard Worker     {
974*2d1272b8SAndroid Build Coastguard Worker       if (verbose) printf ("Table: ");
975*2d1272b8SAndroid Build Coastguard Worker       printf ("%c%c%c%c\n", HB_UNTAG (table_tags[i]));
976*2d1272b8SAndroid Build Coastguard Worker 
977*2d1272b8SAndroid Build Coastguard Worker       hb_set_clear (features);
978*2d1272b8SAndroid Build Coastguard Worker       hb_tag_t feature_array[32];
979*2d1272b8SAndroid Build Coastguard Worker       unsigned feature_count = sizeof feature_array / sizeof feature_array[0];
980*2d1272b8SAndroid Build Coastguard Worker       unsigned feature_offset = 0;
981*2d1272b8SAndroid Build Coastguard Worker       do
982*2d1272b8SAndroid Build Coastguard Worker       {
983*2d1272b8SAndroid Build Coastguard Worker 	hb_ot_layout_table_get_feature_tags (face, table_tags[i],
984*2d1272b8SAndroid Build Coastguard Worker 					     feature_offset,
985*2d1272b8SAndroid Build Coastguard Worker 					     &feature_count,
986*2d1272b8SAndroid Build Coastguard Worker 					     feature_array);
987*2d1272b8SAndroid Build Coastguard Worker 
988*2d1272b8SAndroid Build Coastguard Worker 	for (unsigned feature_index = 0; feature_index < feature_count; feature_index++)
989*2d1272b8SAndroid Build Coastguard Worker 	{
990*2d1272b8SAndroid Build Coastguard Worker 	  if (hb_set_has (features, feature_array[feature_index]))
991*2d1272b8SAndroid Build Coastguard Worker 	    continue;
992*2d1272b8SAndroid Build Coastguard Worker 	  hb_set_add (features, feature_array[feature_index]);
993*2d1272b8SAndroid Build Coastguard Worker 
994*2d1272b8SAndroid Build Coastguard Worker 	  hb_ot_name_id_t label_id;
995*2d1272b8SAndroid Build Coastguard Worker 
996*2d1272b8SAndroid Build Coastguard Worker 	  hb_ot_layout_feature_get_name_ids (face,
997*2d1272b8SAndroid Build Coastguard Worker 					     table_tags[i],
998*2d1272b8SAndroid Build Coastguard Worker 					     feature_offset + feature_index,
999*2d1272b8SAndroid Build Coastguard Worker 					     &label_id,
1000*2d1272b8SAndroid Build Coastguard Worker 					     nullptr,
1001*2d1272b8SAndroid Build Coastguard Worker 					     nullptr,
1002*2d1272b8SAndroid Build Coastguard Worker 					     nullptr,
1003*2d1272b8SAndroid Build Coastguard Worker 					     nullptr);
1004*2d1272b8SAndroid Build Coastguard Worker 
1005*2d1272b8SAndroid Build Coastguard Worker 	  char name[128];
1006*2d1272b8SAndroid Build Coastguard Worker 	  unsigned name_len = sizeof name;
1007*2d1272b8SAndroid Build Coastguard Worker 
1008*2d1272b8SAndroid Build Coastguard Worker 	  _hb_ot_name_get_utf8 (face, label_id,
1009*2d1272b8SAndroid Build Coastguard Worker 				language,
1010*2d1272b8SAndroid Build Coastguard Worker 				&name_len, name);
1011*2d1272b8SAndroid Build Coastguard Worker 
1012*2d1272b8SAndroid Build Coastguard Worker 	  printf ("	");
1013*2d1272b8SAndroid Build Coastguard Worker 	  if (verbose) printf ("Feature: ");
1014*2d1272b8SAndroid Build Coastguard Worker 	  printf ("%c%c%c%c", HB_UNTAG (feature_array[feature_index]));
1015*2d1272b8SAndroid Build Coastguard Worker 
1016*2d1272b8SAndroid Build Coastguard Worker 	  if (*name)
1017*2d1272b8SAndroid Build Coastguard Worker 	    printf ("	%s", name);
1018*2d1272b8SAndroid Build Coastguard Worker 
1019*2d1272b8SAndroid Build Coastguard Worker 	  printf ("\n");
1020*2d1272b8SAndroid Build Coastguard Worker 	}
1021*2d1272b8SAndroid Build Coastguard Worker 
1022*2d1272b8SAndroid Build Coastguard Worker 	feature_offset += feature_count;
1023*2d1272b8SAndroid Build Coastguard Worker       }
1024*2d1272b8SAndroid Build Coastguard Worker       while (feature_count == sizeof feature_array / sizeof feature_array[0]);
1025*2d1272b8SAndroid Build Coastguard Worker     }
1026*2d1272b8SAndroid Build Coastguard Worker 
1027*2d1272b8SAndroid Build Coastguard Worker     hb_set_destroy (features);
1028*2d1272b8SAndroid Build Coastguard Worker   }
1029*2d1272b8SAndroid Build Coastguard Worker 
1030*2d1272b8SAndroid Build Coastguard Worker   void
_list_featuresinfo_t1031*2d1272b8SAndroid Build Coastguard Worker   _list_features ()
1032*2d1272b8SAndroid Build Coastguard Worker   {
1033*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
1034*2d1272b8SAndroid Build Coastguard Worker     {
1035*2d1272b8SAndroid Build Coastguard Worker       separator ();
1036*2d1272b8SAndroid Build Coastguard Worker       printf ("Layout features information:\n\n");
1037*2d1272b8SAndroid Build Coastguard Worker     }
1038*2d1272b8SAndroid Build Coastguard Worker 
1039*2d1272b8SAndroid Build Coastguard Worker     hb_tag_t table_tags[] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS, HB_TAG_NONE};
1040*2d1272b8SAndroid Build Coastguard Worker 
1041*2d1272b8SAndroid Build Coastguard Worker     if (script == HB_SCRIPT_INVALID && !ot_script_str)
1042*2d1272b8SAndroid Build Coastguard Worker     {
1043*2d1272b8SAndroid Build Coastguard Worker       _list_features_no_script ();
1044*2d1272b8SAndroid Build Coastguard Worker       return;
1045*2d1272b8SAndroid Build Coastguard Worker     }
1046*2d1272b8SAndroid Build Coastguard Worker 
1047*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; table_tags[i]; i++)
1048*2d1272b8SAndroid Build Coastguard Worker     {
1049*2d1272b8SAndroid Build Coastguard Worker       if (verbose) printf ("Table: ");
1050*2d1272b8SAndroid Build Coastguard Worker       printf ("%c%c%c%c\n", HB_UNTAG (table_tags[i]));
1051*2d1272b8SAndroid Build Coastguard Worker 
1052*2d1272b8SAndroid Build Coastguard Worker       auto table_tag = table_tags[i];
1053*2d1272b8SAndroid Build Coastguard Worker 
1054*2d1272b8SAndroid Build Coastguard Worker       hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
1055*2d1272b8SAndroid Build Coastguard Worker       hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
1056*2d1272b8SAndroid Build Coastguard Worker       unsigned script_count = HB_OT_MAX_TAGS_PER_SCRIPT;
1057*2d1272b8SAndroid Build Coastguard Worker       unsigned language_count = HB_OT_MAX_TAGS_PER_LANGUAGE;
1058*2d1272b8SAndroid Build Coastguard Worker 
1059*2d1272b8SAndroid Build Coastguard Worker       hb_ot_tags_from_script_and_language (script, language,
1060*2d1272b8SAndroid Build Coastguard Worker 					   &script_count, script_tags,
1061*2d1272b8SAndroid Build Coastguard Worker 					   &language_count, language_tags);
1062*2d1272b8SAndroid Build Coastguard Worker 
1063*2d1272b8SAndroid Build Coastguard Worker       if (ot_script_str)
1064*2d1272b8SAndroid Build Coastguard Worker       {
1065*2d1272b8SAndroid Build Coastguard Worker 	script_tags[0] = hb_tag_from_string (ot_script_str, -1);
1066*2d1272b8SAndroid Build Coastguard Worker 	script_count = 1;
1067*2d1272b8SAndroid Build Coastguard Worker       }
1068*2d1272b8SAndroid Build Coastguard Worker       if (ot_language_str)
1069*2d1272b8SAndroid Build Coastguard Worker       {
1070*2d1272b8SAndroid Build Coastguard Worker 	language_tags[0] = hb_tag_from_string (ot_language_str, -1);
1071*2d1272b8SAndroid Build Coastguard Worker 	language_count = 1;
1072*2d1272b8SAndroid Build Coastguard Worker       }
1073*2d1272b8SAndroid Build Coastguard Worker 
1074*2d1272b8SAndroid Build Coastguard Worker       unsigned script_index;
1075*2d1272b8SAndroid Build Coastguard Worker       hb_tag_t chosen_script;
1076*2d1272b8SAndroid Build Coastguard Worker       hb_ot_layout_table_select_script (face, table_tag,
1077*2d1272b8SAndroid Build Coastguard Worker 					script_count, script_tags,
1078*2d1272b8SAndroid Build Coastguard Worker 					&script_index, &chosen_script);
1079*2d1272b8SAndroid Build Coastguard Worker 
1080*2d1272b8SAndroid Build Coastguard Worker       unsigned language_index;
1081*2d1272b8SAndroid Build Coastguard Worker       hb_tag_t chosen_language;
1082*2d1272b8SAndroid Build Coastguard Worker       hb_ot_layout_script_select_language2 (face, table_tag,
1083*2d1272b8SAndroid Build Coastguard Worker 					   script_index,
1084*2d1272b8SAndroid Build Coastguard Worker 					   language_count, language_tags,
1085*2d1272b8SAndroid Build Coastguard Worker 					   &language_index, &chosen_language);
1086*2d1272b8SAndroid Build Coastguard Worker 
1087*2d1272b8SAndroid Build Coastguard Worker       if (verbose)
1088*2d1272b8SAndroid Build Coastguard Worker       {
1089*2d1272b8SAndroid Build Coastguard Worker         if (chosen_script)
1090*2d1272b8SAndroid Build Coastguard Worker 	{
1091*2d1272b8SAndroid Build Coastguard Worker 	  printf ("	Script: %c%c%c%c\n", HB_UNTAG (chosen_script));
1092*2d1272b8SAndroid Build Coastguard Worker 	  if (chosen_language)
1093*2d1272b8SAndroid Build Coastguard Worker 	    printf ("	Language: %c%c%c%c\n", HB_UNTAG (chosen_language));
1094*2d1272b8SAndroid Build Coastguard Worker 	  else
1095*2d1272b8SAndroid Build Coastguard Worker 	    printf ("	Language: Default\n");
1096*2d1272b8SAndroid Build Coastguard Worker 	}
1097*2d1272b8SAndroid Build Coastguard Worker       }
1098*2d1272b8SAndroid Build Coastguard Worker 
1099*2d1272b8SAndroid Build Coastguard Worker       unsigned feature_array[32];
1100*2d1272b8SAndroid Build Coastguard Worker       unsigned feature_count = sizeof feature_array / sizeof feature_array[0];
1101*2d1272b8SAndroid Build Coastguard Worker       unsigned feature_offset = 0;
1102*2d1272b8SAndroid Build Coastguard Worker       do
1103*2d1272b8SAndroid Build Coastguard Worker       {
1104*2d1272b8SAndroid Build Coastguard Worker 	hb_ot_layout_language_get_feature_indexes (face, table_tag,
1105*2d1272b8SAndroid Build Coastguard Worker 						   script_index, language_index,
1106*2d1272b8SAndroid Build Coastguard Worker 						   feature_offset,
1107*2d1272b8SAndroid Build Coastguard Worker 						   &feature_count,
1108*2d1272b8SAndroid Build Coastguard Worker 						   feature_array);
1109*2d1272b8SAndroid Build Coastguard Worker 
1110*2d1272b8SAndroid Build Coastguard Worker 	for (unsigned feature_index = 0; feature_index < feature_count; feature_index++)
1111*2d1272b8SAndroid Build Coastguard Worker 	{
1112*2d1272b8SAndroid Build Coastguard Worker 	  hb_ot_name_id_t label_id;
1113*2d1272b8SAndroid Build Coastguard Worker 
1114*2d1272b8SAndroid Build Coastguard Worker 	  hb_ot_layout_feature_get_name_ids (face,
1115*2d1272b8SAndroid Build Coastguard Worker 					     table_tags[i],
1116*2d1272b8SAndroid Build Coastguard Worker 					     feature_array[feature_index],
1117*2d1272b8SAndroid Build Coastguard Worker 					     &label_id,
1118*2d1272b8SAndroid Build Coastguard Worker 					     nullptr,
1119*2d1272b8SAndroid Build Coastguard Worker 					     nullptr,
1120*2d1272b8SAndroid Build Coastguard Worker 					     nullptr,
1121*2d1272b8SAndroid Build Coastguard Worker 					     nullptr);
1122*2d1272b8SAndroid Build Coastguard Worker 
1123*2d1272b8SAndroid Build Coastguard Worker 	  char name[128];
1124*2d1272b8SAndroid Build Coastguard Worker 	  unsigned name_len = sizeof name;
1125*2d1272b8SAndroid Build Coastguard Worker 
1126*2d1272b8SAndroid Build Coastguard Worker 	  _hb_ot_name_get_utf8 (face, label_id,
1127*2d1272b8SAndroid Build Coastguard Worker 				language,
1128*2d1272b8SAndroid Build Coastguard Worker 				&name_len, name);
1129*2d1272b8SAndroid Build Coastguard Worker 
1130*2d1272b8SAndroid Build Coastguard Worker 	  printf ("	");
1131*2d1272b8SAndroid Build Coastguard Worker 	  if (verbose) printf ("Feature: ");
1132*2d1272b8SAndroid Build Coastguard Worker 	  hb_tag_t feature_tag;
1133*2d1272b8SAndroid Build Coastguard Worker 	  unsigned f_count = 1;
1134*2d1272b8SAndroid Build Coastguard Worker 	  hb_ot_layout_table_get_feature_tags (face, table_tag,
1135*2d1272b8SAndroid Build Coastguard Worker 					       feature_array[feature_index],
1136*2d1272b8SAndroid Build Coastguard Worker 					       &f_count, &feature_tag);
1137*2d1272b8SAndroid Build Coastguard Worker 	  printf ("%c%c%c%c", HB_UNTAG (feature_tag));
1138*2d1272b8SAndroid Build Coastguard Worker 
1139*2d1272b8SAndroid Build Coastguard Worker 	  if (*name)
1140*2d1272b8SAndroid Build Coastguard Worker 	    printf ("	%s", name);
1141*2d1272b8SAndroid Build Coastguard Worker 
1142*2d1272b8SAndroid Build Coastguard Worker 	  printf ("\n");
1143*2d1272b8SAndroid Build Coastguard Worker 	}
1144*2d1272b8SAndroid Build Coastguard Worker 
1145*2d1272b8SAndroid Build Coastguard Worker 	feature_offset += feature_count;
1146*2d1272b8SAndroid Build Coastguard Worker       }
1147*2d1272b8SAndroid Build Coastguard Worker       while (feature_count == sizeof feature_array / sizeof feature_array[0]);
1148*2d1272b8SAndroid Build Coastguard Worker     }
1149*2d1272b8SAndroid Build Coastguard Worker   }
1150*2d1272b8SAndroid Build Coastguard Worker 
1151*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR
1152*2d1272b8SAndroid Build Coastguard Worker   void
_list_variationsinfo_t1153*2d1272b8SAndroid Build Coastguard Worker   _list_variations ()
1154*2d1272b8SAndroid Build Coastguard Worker   {
1155*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
1156*2d1272b8SAndroid Build Coastguard Worker     {
1157*2d1272b8SAndroid Build Coastguard Worker       separator ();
1158*2d1272b8SAndroid Build Coastguard Worker       printf ("Variations information:\n\n");
1159*2d1272b8SAndroid Build Coastguard Worker     }
1160*2d1272b8SAndroid Build Coastguard Worker 
1161*2d1272b8SAndroid Build Coastguard Worker     hb_ot_var_axis_info_t *axes;
1162*2d1272b8SAndroid Build Coastguard Worker 
1163*2d1272b8SAndroid Build Coastguard Worker     unsigned count = hb_ot_var_get_axis_infos (face, 0, nullptr, nullptr);
1164*2d1272b8SAndroid Build Coastguard Worker     axes = (hb_ot_var_axis_info_t *) calloc (count, sizeof (hb_ot_var_axis_info_t));
1165*2d1272b8SAndroid Build Coastguard Worker     hb_ot_var_get_axis_infos (face, 0, &count, axes);
1166*2d1272b8SAndroid Build Coastguard Worker 
1167*2d1272b8SAndroid Build Coastguard Worker     bool has_hidden = false;
1168*2d1272b8SAndroid Build Coastguard Worker 
1169*2d1272b8SAndroid Build Coastguard Worker     if (verbose && count)
1170*2d1272b8SAndroid Build Coastguard Worker     {
1171*2d1272b8SAndroid Build Coastguard Worker       printf ("Varitation axes:\n\n");
1172*2d1272b8SAndroid Build Coastguard Worker       printf ("Tag	Minimum	Default	Maximum	Name\n------------------------------------\n");
1173*2d1272b8SAndroid Build Coastguard Worker     }
1174*2d1272b8SAndroid Build Coastguard Worker     for (unsigned i = 0; i < count; i++)
1175*2d1272b8SAndroid Build Coastguard Worker     {
1176*2d1272b8SAndroid Build Coastguard Worker       const auto &axis = axes[i];
1177*2d1272b8SAndroid Build Coastguard Worker       if (axis.flags & HB_OT_VAR_AXIS_FLAG_HIDDEN)
1178*2d1272b8SAndroid Build Coastguard Worker 	has_hidden = true;
1179*2d1272b8SAndroid Build Coastguard Worker 
1180*2d1272b8SAndroid Build Coastguard Worker       char name[128];
1181*2d1272b8SAndroid Build Coastguard Worker       unsigned name_len = sizeof name;
1182*2d1272b8SAndroid Build Coastguard Worker 
1183*2d1272b8SAndroid Build Coastguard Worker       _hb_ot_name_get_utf8 (face, axis.name_id,
1184*2d1272b8SAndroid Build Coastguard Worker 			    language,
1185*2d1272b8SAndroid Build Coastguard Worker 			    &name_len, name);
1186*2d1272b8SAndroid Build Coastguard Worker 
1187*2d1272b8SAndroid Build Coastguard Worker       printf ("%c%c%c%c%s	%g	%g	%g	%s\n",
1188*2d1272b8SAndroid Build Coastguard Worker 	      HB_UNTAG (axis.tag),
1189*2d1272b8SAndroid Build Coastguard Worker 	      axis.flags & HB_OT_VAR_AXIS_FLAG_HIDDEN ? "*" : "",
1190*2d1272b8SAndroid Build Coastguard Worker 	      (double) axis.min_value,
1191*2d1272b8SAndroid Build Coastguard Worker 	      (double) axis.default_value,
1192*2d1272b8SAndroid Build Coastguard Worker 	      (double) axis.max_value,
1193*2d1272b8SAndroid Build Coastguard Worker 	      name);
1194*2d1272b8SAndroid Build Coastguard Worker     }
1195*2d1272b8SAndroid Build Coastguard Worker     if (verbose && has_hidden)
1196*2d1272b8SAndroid Build Coastguard Worker       printf ("\n[*] Hidden axis\n");
1197*2d1272b8SAndroid Build Coastguard Worker 
1198*2d1272b8SAndroid Build Coastguard Worker     free (axes);
1199*2d1272b8SAndroid Build Coastguard Worker     axes = nullptr;
1200*2d1272b8SAndroid Build Coastguard Worker 
1201*2d1272b8SAndroid Build Coastguard Worker     count = hb_ot_var_get_named_instance_count (face);
1202*2d1272b8SAndroid Build Coastguard Worker     if (count)
1203*2d1272b8SAndroid Build Coastguard Worker     {
1204*2d1272b8SAndroid Build Coastguard Worker       if (verbose)
1205*2d1272b8SAndroid Build Coastguard Worker       {
1206*2d1272b8SAndroid Build Coastguard Worker 	printf ("\n\nNamed instances:\n\n");
1207*2d1272b8SAndroid Build Coastguard Worker       printf ("Index	Name				Position\n------------------------------------------------\n");
1208*2d1272b8SAndroid Build Coastguard Worker       }
1209*2d1272b8SAndroid Build Coastguard Worker 
1210*2d1272b8SAndroid Build Coastguard Worker       for (unsigned i = 0; i < count; i++)
1211*2d1272b8SAndroid Build Coastguard Worker       {
1212*2d1272b8SAndroid Build Coastguard Worker 	char name[128];
1213*2d1272b8SAndroid Build Coastguard Worker 	unsigned name_len = sizeof name;
1214*2d1272b8SAndroid Build Coastguard Worker 
1215*2d1272b8SAndroid Build Coastguard Worker 	hb_ot_name_id_t name_id = hb_ot_var_named_instance_get_subfamily_name_id (face, i);
1216*2d1272b8SAndroid Build Coastguard Worker 	_hb_ot_name_get_utf8 (face, name_id,
1217*2d1272b8SAndroid Build Coastguard Worker 			      language,
1218*2d1272b8SAndroid Build Coastguard Worker 			      &name_len, name);
1219*2d1272b8SAndroid Build Coastguard Worker 
1220*2d1272b8SAndroid Build Coastguard Worker 	unsigned coords_count = hb_ot_var_named_instance_get_design_coords (face, i, nullptr, nullptr);
1221*2d1272b8SAndroid Build Coastguard Worker 	float* coords;
1222*2d1272b8SAndroid Build Coastguard Worker 	coords = (float *) calloc (coords_count, sizeof (float));
1223*2d1272b8SAndroid Build Coastguard Worker 	hb_ot_var_named_instance_get_design_coords (face, i, &coords_count, coords);
1224*2d1272b8SAndroid Build Coastguard Worker 
1225*2d1272b8SAndroid Build Coastguard Worker 	printf ("%u	%-32s", i, name);
1226*2d1272b8SAndroid Build Coastguard Worker 	for (unsigned j = 0; j < coords_count; j++)
1227*2d1272b8SAndroid Build Coastguard Worker 	  printf ("%g, ", (double) coords[j]);
1228*2d1272b8SAndroid Build Coastguard Worker 	printf ("\n");
1229*2d1272b8SAndroid Build Coastguard Worker 
1230*2d1272b8SAndroid Build Coastguard Worker 	free (coords);
1231*2d1272b8SAndroid Build Coastguard Worker       }
1232*2d1272b8SAndroid Build Coastguard Worker     }
1233*2d1272b8SAndroid Build Coastguard Worker   }
1234*2d1272b8SAndroid Build Coastguard Worker #endif
1235*2d1272b8SAndroid Build Coastguard Worker 
1236*2d1272b8SAndroid Build Coastguard Worker #ifdef HAVE_CHAFA
1237*2d1272b8SAndroid Build Coastguard Worker   GString *
_palette_chafa_strinfo_t1238*2d1272b8SAndroid Build Coastguard Worker   _palette_chafa_str (unsigned palette_index)
1239*2d1272b8SAndroid Build Coastguard Worker   {
1240*2d1272b8SAndroid Build Coastguard Worker     unsigned count = hb_ot_color_palette_get_colors (face, palette_index, 0,
1241*2d1272b8SAndroid Build Coastguard Worker 						     nullptr, nullptr);
1242*2d1272b8SAndroid Build Coastguard Worker 
1243*2d1272b8SAndroid Build Coastguard Worker     hb_color_t *palette = (hb_color_t *) malloc (count * sizeof (hb_color_t));
1244*2d1272b8SAndroid Build Coastguard Worker     hb_ot_color_palette_get_colors (face, palette_index, 0,
1245*2d1272b8SAndroid Build Coastguard Worker 				    &count, palette);
1246*2d1272b8SAndroid Build Coastguard Worker 
1247*2d1272b8SAndroid Build Coastguard Worker #define REPEAT 16
1248*2d1272b8SAndroid Build Coastguard Worker     hb_color_t *data = (hb_color_t *) malloc (count * REPEAT * sizeof (hb_color_t));
1249*2d1272b8SAndroid Build Coastguard Worker     for (unsigned i = 0; i < count; i++)
1250*2d1272b8SAndroid Build Coastguard Worker       for (unsigned j = 0; j < REPEAT; j++)
1251*2d1272b8SAndroid Build Coastguard Worker 	data[i * REPEAT + j] = palette[i];
1252*2d1272b8SAndroid Build Coastguard Worker     free (palette);
1253*2d1272b8SAndroid Build Coastguard Worker     palette = nullptr;
1254*2d1272b8SAndroid Build Coastguard Worker 
1255*2d1272b8SAndroid Build Coastguard Worker     chafa_set_n_threads (1); // https://github.com/hpjansson/chafa/issues/125#issuecomment-1397475217
1256*2d1272b8SAndroid Build Coastguard Worker 			     //
1257*2d1272b8SAndroid Build Coastguard Worker     gchar **environ = g_get_environ ();
1258*2d1272b8SAndroid Build Coastguard Worker     ChafaTermInfo *term_info = chafa_term_db_detect (chafa_term_db_get_default (),
1259*2d1272b8SAndroid Build Coastguard Worker 						     environ);
1260*2d1272b8SAndroid Build Coastguard Worker 
1261*2d1272b8SAndroid Build Coastguard Worker     ChafaCanvasMode mode;
1262*2d1272b8SAndroid Build Coastguard Worker     ChafaPixelMode pixel_mode = CHAFA_PIXEL_MODE_SYMBOLS;
1263*2d1272b8SAndroid Build Coastguard Worker     if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_SET_COLOR_FGBG_DIRECT))
1264*2d1272b8SAndroid Build Coastguard Worker       mode = CHAFA_CANVAS_MODE_TRUECOLOR;
1265*2d1272b8SAndroid Build Coastguard Worker     else if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_SET_COLOR_FGBG_256))
1266*2d1272b8SAndroid Build Coastguard Worker       mode = CHAFA_CANVAS_MODE_INDEXED_240;
1267*2d1272b8SAndroid Build Coastguard Worker     else if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_SET_COLOR_FGBG_16))
1268*2d1272b8SAndroid Build Coastguard Worker       mode = CHAFA_CANVAS_MODE_INDEXED_16;
1269*2d1272b8SAndroid Build Coastguard Worker     else if (chafa_term_info_have_seq (term_info, CHAFA_TERM_SEQ_INVERT_COLORS))
1270*2d1272b8SAndroid Build Coastguard Worker       mode = CHAFA_CANVAS_MODE_FGBG_BGFG;
1271*2d1272b8SAndroid Build Coastguard Worker     else
1272*2d1272b8SAndroid Build Coastguard Worker       mode = CHAFA_CANVAS_MODE_FGBG;
1273*2d1272b8SAndroid Build Coastguard Worker 
1274*2d1272b8SAndroid Build Coastguard Worker     ChafaSymbolMap *symbol_map = chafa_symbol_map_new ();
1275*2d1272b8SAndroid Build Coastguard Worker     chafa_symbol_map_add_by_tags (symbol_map,
1276*2d1272b8SAndroid Build Coastguard Worker 				  (ChafaSymbolTags) (CHAFA_SYMBOL_TAG_BLOCK));
1277*2d1272b8SAndroid Build Coastguard Worker 
1278*2d1272b8SAndroid Build Coastguard Worker     ChafaCanvasConfig *config = chafa_canvas_config_new ();
1279*2d1272b8SAndroid Build Coastguard Worker     chafa_canvas_config_set_canvas_mode (config, mode);
1280*2d1272b8SAndroid Build Coastguard Worker     chafa_canvas_config_set_pixel_mode (config, pixel_mode);
1281*2d1272b8SAndroid Build Coastguard Worker     chafa_canvas_config_set_cell_geometry (config, REPEAT, 1);
1282*2d1272b8SAndroid Build Coastguard Worker     chafa_canvas_config_set_geometry (config, 2 * count, 1);
1283*2d1272b8SAndroid Build Coastguard Worker     chafa_canvas_config_set_symbol_map (config, symbol_map);
1284*2d1272b8SAndroid Build Coastguard Worker     chafa_canvas_config_set_color_extractor (config, CHAFA_COLOR_EXTRACTOR_MEDIAN);
1285*2d1272b8SAndroid Build Coastguard Worker     chafa_canvas_config_set_work_factor (config, 1.0f);
1286*2d1272b8SAndroid Build Coastguard Worker 
1287*2d1272b8SAndroid Build Coastguard Worker     ChafaCanvas *canvas = chafa_canvas_new (config);
1288*2d1272b8SAndroid Build Coastguard Worker     chafa_canvas_draw_all_pixels (canvas,
1289*2d1272b8SAndroid Build Coastguard Worker 				  G_BYTE_ORDER == G_BIG_ENDIAN
1290*2d1272b8SAndroid Build Coastguard Worker 				    ? CHAFA_PIXEL_BGRA8_UNASSOCIATED
1291*2d1272b8SAndroid Build Coastguard Worker 				    : CHAFA_PIXEL_ARGB8_UNASSOCIATED,
1292*2d1272b8SAndroid Build Coastguard Worker 				  (const guint8 *) data,
1293*2d1272b8SAndroid Build Coastguard Worker 				  count * REPEAT,
1294*2d1272b8SAndroid Build Coastguard Worker 				  1,
1295*2d1272b8SAndroid Build Coastguard Worker 				  sizeof (hb_color_t));
1296*2d1272b8SAndroid Build Coastguard Worker 
1297*2d1272b8SAndroid Build Coastguard Worker     free (data);
1298*2d1272b8SAndroid Build Coastguard Worker 
1299*2d1272b8SAndroid Build Coastguard Worker     auto gs = chafa_canvas_print (canvas, term_info);
1300*2d1272b8SAndroid Build Coastguard Worker 
1301*2d1272b8SAndroid Build Coastguard Worker     chafa_canvas_unref (canvas);
1302*2d1272b8SAndroid Build Coastguard Worker     chafa_canvas_config_unref (config);
1303*2d1272b8SAndroid Build Coastguard Worker     chafa_symbol_map_unref (symbol_map);
1304*2d1272b8SAndroid Build Coastguard Worker     chafa_term_info_unref (term_info);
1305*2d1272b8SAndroid Build Coastguard Worker     g_strfreev (environ);
1306*2d1272b8SAndroid Build Coastguard Worker 
1307*2d1272b8SAndroid Build Coastguard Worker     return gs;
1308*2d1272b8SAndroid Build Coastguard Worker   }
1309*2d1272b8SAndroid Build Coastguard Worker #endif
1310*2d1272b8SAndroid Build Coastguard Worker 
1311*2d1272b8SAndroid Build Coastguard Worker   void
_list_palettesinfo_t1312*2d1272b8SAndroid Build Coastguard Worker   _list_palettes ()
1313*2d1272b8SAndroid Build Coastguard Worker   {
1314*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
1315*2d1272b8SAndroid Build Coastguard Worker     {
1316*2d1272b8SAndroid Build Coastguard Worker       separator ();
1317*2d1272b8SAndroid Build Coastguard Worker       printf ("Color palettes information:\n");
1318*2d1272b8SAndroid Build Coastguard Worker     }
1319*2d1272b8SAndroid Build Coastguard Worker 
1320*2d1272b8SAndroid Build Coastguard Worker     {
1321*2d1272b8SAndroid Build Coastguard Worker       if (verbose)
1322*2d1272b8SAndroid Build Coastguard Worker       {
1323*2d1272b8SAndroid Build Coastguard Worker 	printf ("\nPalettes:\n\n");
1324*2d1272b8SAndroid Build Coastguard Worker 	printf ("Index	Flags	Name\n--------------------\n");
1325*2d1272b8SAndroid Build Coastguard Worker       }
1326*2d1272b8SAndroid Build Coastguard Worker       unsigned count = hb_ot_color_palette_get_count (face);
1327*2d1272b8SAndroid Build Coastguard Worker       for (unsigned i = 0; i < count; i++)
1328*2d1272b8SAndroid Build Coastguard Worker       {
1329*2d1272b8SAndroid Build Coastguard Worker 	hb_ot_name_id_t name_id = hb_ot_color_palette_get_name_id (face, i);
1330*2d1272b8SAndroid Build Coastguard Worker 	hb_ot_color_palette_flags_t flags = hb_ot_color_palette_get_flags (face, i);
1331*2d1272b8SAndroid Build Coastguard Worker 
1332*2d1272b8SAndroid Build Coastguard Worker 	char name[128];
1333*2d1272b8SAndroid Build Coastguard Worker 	unsigned name_len = sizeof name;
1334*2d1272b8SAndroid Build Coastguard Worker 
1335*2d1272b8SAndroid Build Coastguard Worker 	_hb_ot_name_get_utf8 (face, name_id,
1336*2d1272b8SAndroid Build Coastguard Worker 			      language,
1337*2d1272b8SAndroid Build Coastguard Worker 			      &name_len, name);
1338*2d1272b8SAndroid Build Coastguard Worker         const char *type = "";
1339*2d1272b8SAndroid Build Coastguard Worker 	if (flags)
1340*2d1272b8SAndroid Build Coastguard Worker 	{
1341*2d1272b8SAndroid Build Coastguard Worker 	  if (flags & HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND)
1342*2d1272b8SAndroid Build Coastguard Worker           {
1343*2d1272b8SAndroid Build Coastguard Worker 	    if (flags & HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND)
1344*2d1272b8SAndroid Build Coastguard Worker 	      type = "Both";
1345*2d1272b8SAndroid Build Coastguard Worker             else
1346*2d1272b8SAndroid Build Coastguard Worker 	      type = "Light";
1347*2d1272b8SAndroid Build Coastguard Worker           }
1348*2d1272b8SAndroid Build Coastguard Worker           else {
1349*2d1272b8SAndroid Build Coastguard Worker 	    type = "Dark";
1350*2d1272b8SAndroid Build Coastguard Worker           }
1351*2d1272b8SAndroid Build Coastguard Worker 	}
1352*2d1272b8SAndroid Build Coastguard Worker 
1353*2d1272b8SAndroid Build Coastguard Worker #ifdef HAVE_CHAFA
1354*2d1272b8SAndroid Build Coastguard Worker 	char *chafa_env = getenv ("HB_CHAFA");
1355*2d1272b8SAndroid Build Coastguard Worker 	bool use_chafa = !chafa_env || atoi (chafa_env);
1356*2d1272b8SAndroid Build Coastguard Worker 	if (verbose && use_chafa && isatty (fileno (stdout)))
1357*2d1272b8SAndroid Build Coastguard Worker 	{
1358*2d1272b8SAndroid Build Coastguard Worker 	  GString *chafa_str = _palette_chafa_str (i);
1359*2d1272b8SAndroid Build Coastguard Worker 	  printf ("%u	%s	%-23s	%*s\n", i, type, name,
1360*2d1272b8SAndroid Build Coastguard Worker 		  (int) chafa_str->len, chafa_str->str);
1361*2d1272b8SAndroid Build Coastguard Worker 	  g_string_free (chafa_str, TRUE);
1362*2d1272b8SAndroid Build Coastguard Worker 	}
1363*2d1272b8SAndroid Build Coastguard Worker 	else
1364*2d1272b8SAndroid Build Coastguard Worker #endif
1365*2d1272b8SAndroid Build Coastguard Worker 	  printf ("%u	%s	%s\n", i, type, name);
1366*2d1272b8SAndroid Build Coastguard Worker       }
1367*2d1272b8SAndroid Build Coastguard Worker     }
1368*2d1272b8SAndroid Build Coastguard Worker 
1369*2d1272b8SAndroid Build Coastguard Worker     {
1370*2d1272b8SAndroid Build Coastguard Worker       if (verbose)
1371*2d1272b8SAndroid Build Coastguard Worker       {
1372*2d1272b8SAndroid Build Coastguard Worker 	printf ("\nColors:\n\n");
1373*2d1272b8SAndroid Build Coastguard Worker 	printf ("Index	Name\n------------\n");
1374*2d1272b8SAndroid Build Coastguard Worker       }
1375*2d1272b8SAndroid Build Coastguard Worker       unsigned count = hb_ot_color_palette_get_colors (face, 0, 0, nullptr, nullptr);
1376*2d1272b8SAndroid Build Coastguard Worker       for (unsigned i = 0; i < count; i++)
1377*2d1272b8SAndroid Build Coastguard Worker       {
1378*2d1272b8SAndroid Build Coastguard Worker 	hb_ot_name_id_t name_id = hb_ot_color_palette_color_get_name_id (face, i);
1379*2d1272b8SAndroid Build Coastguard Worker 
1380*2d1272b8SAndroid Build Coastguard Worker 	char name[128];
1381*2d1272b8SAndroid Build Coastguard Worker 	unsigned name_len = sizeof name;
1382*2d1272b8SAndroid Build Coastguard Worker 	_hb_ot_name_get_utf8 (face, name_id,
1383*2d1272b8SAndroid Build Coastguard Worker 			      language,
1384*2d1272b8SAndroid Build Coastguard Worker 			      &name_len, name);
1385*2d1272b8SAndroid Build Coastguard Worker 
1386*2d1272b8SAndroid Build Coastguard Worker 	printf ("%u	%s\n", i, name);
1387*2d1272b8SAndroid Build Coastguard Worker       }
1388*2d1272b8SAndroid Build Coastguard Worker     }
1389*2d1272b8SAndroid Build Coastguard Worker   }
1390*2d1272b8SAndroid Build Coastguard Worker 
1391*2d1272b8SAndroid Build Coastguard Worker   void
_list_metainfo_t1392*2d1272b8SAndroid Build Coastguard Worker   _list_meta ()
1393*2d1272b8SAndroid Build Coastguard Worker   {
1394*2d1272b8SAndroid Build Coastguard Worker     if (verbose)
1395*2d1272b8SAndroid Build Coastguard Worker     {
1396*2d1272b8SAndroid Build Coastguard Worker       separator ();
1397*2d1272b8SAndroid Build Coastguard Worker       printf ("Meta information:\n");
1398*2d1272b8SAndroid Build Coastguard Worker     }
1399*2d1272b8SAndroid Build Coastguard Worker 
1400*2d1272b8SAndroid Build Coastguard Worker     {
1401*2d1272b8SAndroid Build Coastguard Worker       if (verbose)
1402*2d1272b8SAndroid Build Coastguard Worker       {
1403*2d1272b8SAndroid Build Coastguard Worker 	printf ("\nTag	Data\n------------\n");
1404*2d1272b8SAndroid Build Coastguard Worker       }
1405*2d1272b8SAndroid Build Coastguard Worker       unsigned count = hb_ot_meta_get_entry_tags (face, 0, nullptr, nullptr);
1406*2d1272b8SAndroid Build Coastguard Worker       for (unsigned i = 0; i < count; i++)
1407*2d1272b8SAndroid Build Coastguard Worker       {
1408*2d1272b8SAndroid Build Coastguard Worker 	hb_ot_meta_tag_t tag;
1409*2d1272b8SAndroid Build Coastguard Worker 	unsigned len = 1;
1410*2d1272b8SAndroid Build Coastguard Worker 	hb_ot_meta_get_entry_tags (face, i, &len, &tag);
1411*2d1272b8SAndroid Build Coastguard Worker 
1412*2d1272b8SAndroid Build Coastguard Worker 	hb_blob_t *blob = hb_ot_meta_reference_entry (face, tag);
1413*2d1272b8SAndroid Build Coastguard Worker 
1414*2d1272b8SAndroid Build Coastguard Worker 	printf ("%c%c%c%c	%.*s\n", HB_UNTAG (tag),
1415*2d1272b8SAndroid Build Coastguard Worker 		(int) hb_blob_get_length (blob),
1416*2d1272b8SAndroid Build Coastguard Worker 		hb_blob_get_data (blob, nullptr));
1417*2d1272b8SAndroid Build Coastguard Worker 
1418*2d1272b8SAndroid Build Coastguard Worker 	hb_blob_destroy (blob);
1419*2d1272b8SAndroid Build Coastguard Worker       }
1420*2d1272b8SAndroid Build Coastguard Worker     }
1421*2d1272b8SAndroid Build Coastguard Worker   }
1422*2d1272b8SAndroid Build Coastguard Worker 
1423*2d1272b8SAndroid Build Coastguard Worker };
1424*2d1272b8SAndroid Build Coastguard Worker 
1425*2d1272b8SAndroid Build Coastguard Worker 
1426*2d1272b8SAndroid Build Coastguard Worker template <typename consumer_t,
1427*2d1272b8SAndroid Build Coastguard Worker 	  typename font_options_type>
1428*2d1272b8SAndroid Build Coastguard Worker struct main_font_t :
1429*2d1272b8SAndroid Build Coastguard Worker        option_parser_t,
1430*2d1272b8SAndroid Build Coastguard Worker        font_options_type,
1431*2d1272b8SAndroid Build Coastguard Worker        consumer_t
1432*2d1272b8SAndroid Build Coastguard Worker {
operator ()main_font_t1433*2d1272b8SAndroid Build Coastguard Worker   int operator () (int argc, char **argv)
1434*2d1272b8SAndroid Build Coastguard Worker   {
1435*2d1272b8SAndroid Build Coastguard Worker     add_options ();
1436*2d1272b8SAndroid Build Coastguard Worker 
1437*2d1272b8SAndroid Build Coastguard Worker     if (argc == 2)
1438*2d1272b8SAndroid Build Coastguard Worker       consumer_t::show_all = true;
1439*2d1272b8SAndroid Build Coastguard Worker 
1440*2d1272b8SAndroid Build Coastguard Worker     parse (&argc, &argv);
1441*2d1272b8SAndroid Build Coastguard Worker 
1442*2d1272b8SAndroid Build Coastguard Worker     consumer_t::operator () (this);
1443*2d1272b8SAndroid Build Coastguard Worker 
1444*2d1272b8SAndroid Build Coastguard Worker     return 0;
1445*2d1272b8SAndroid Build Coastguard Worker   }
1446*2d1272b8SAndroid Build Coastguard Worker };
1447*2d1272b8SAndroid Build Coastguard Worker 
1448*2d1272b8SAndroid Build Coastguard Worker int
main(int argc,char ** argv)1449*2d1272b8SAndroid Build Coastguard Worker main (int argc, char **argv)
1450*2d1272b8SAndroid Build Coastguard Worker {
1451*2d1272b8SAndroid Build Coastguard Worker   return batch_main<info_t> (argc, argv);
1452*2d1272b8SAndroid Build Coastguard Worker }
1453