1/* pango-list.c: List all fonts
2 *
3 * Copyright (C) 2018 Google
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Google Author(s): Behdad Esfahbod
21 */
22
23#include "config.h"
24#include <pango/pangocairo.h>
25#include <hb-ot.h>
26#include <glib/gstdio.h>
27#include <stdlib.h>
28#include <locale.h>
29
30/* FIXME: This doesn't work if the font has an avar table */
31static float
32denorm_coord (hb_ot_var_axis_info_t *axis, int coord)
33{
34 float r = coord / 16384.0;
35
36 if (coord < 0)
37 return axis->default_value + r * (axis->default_value - axis->min_value);
38 else
39 return axis->default_value + r * (axis->max_value - axis->default_value);
40}
41
42int
43main (int argc,
44 char **argv)
45{
46 gboolean opt_verbose = FALSE;
47 gboolean opt_metrics = FALSE;
48 gboolean opt_variations = FALSE;
49 gboolean opt_version = FALSE;
50 GOptionEntry entries[] = {
51 { "verbose", 0, 0, G_OPTION_ARG_NONE, &opt_verbose, "Print verbose information", NULL },
52 { "metrics", 0, 0, G_OPTION_ARG_NONE, &opt_metrics, "Print font metrics", NULL },
53 { "variations", 0, 0, G_OPTION_ARG_NONE, &opt_variations, "Print font variations", NULL },
54 { "version", 0, 0, G_OPTION_ARG_NONE, &opt_version, "Show version" },
55 { NULL, }
56 };
57 GOptionContext *context;
58 PangoContext *ctx;
59 PangoFontMap *fontmap;
60 PangoFontFamily **families;
61 int n_families;
62 int i, j;
63 int width;
64 GError *error = NULL;
65
66 g_set_prgname (prgname: "pango-list");
67 setlocale (LC_ALL, locale: "");
68
69 context = g_option_context_new (parameter_string: "");
70 g_option_context_add_main_entries (context, entries, NULL);
71 if (!g_option_context_parse (context, argc: &argc, argv: &argv, error: &error))
72 {
73 if (error != NULL)
74 g_printerr (format: "%s\n", error->message);
75 else
76 g_printerr (format: "Option parse error\n");
77 exit (status: 1);
78 }
79
80 g_option_context_free (context);
81
82 if (opt_version)
83 {
84 g_print (format: "%s (%s) %s\n", g_get_prgname (), PACKAGE_NAME, PACKAGE_VERSION);
85 exit (status: 0);
86 }
87
88 /* Use PangoCairo to get default fontmap so it works on every platform. */
89 fontmap = pango_cairo_font_map_get_default ();
90 ctx = pango_font_map_create_context (fontmap);
91
92 if (opt_verbose)
93 g_print (format: "Using %s\n\n", G_OBJECT_TYPE_NAME (fontmap));
94
95 pango_font_map_list_families (fontmap, families: &families, n_families: &n_families);
96 for (i = 0; i < n_families; i++)
97 {
98 PangoFontFace **faces;
99 int n_faces;
100 const char *kind;
101
102 const char *family_name = pango_font_family_get_name (family: families[i]);
103 if (pango_font_family_is_monospace (family: families[i]))
104 {
105 if (pango_font_family_is_variable (family: families[i]))
106 kind = "(monospace, variable)";
107 else
108 kind = "(monospace)";
109 }
110 else
111 {
112 if (pango_font_family_is_variable (family: families[i]))
113 kind = "(variable)";
114 else
115 kind = "";
116 }
117
118 g_print (format: "%s %s\n", family_name, kind);
119
120 pango_font_family_list_faces (family: families[i], faces: &faces, n_faces: &n_faces);
121
122 width = 0;
123 for (j = 0; j < n_faces; j++)
124 {
125 const char *face_name = pango_font_face_get_face_name (face: faces[j]);
126 gboolean is_synth = pango_font_face_is_synthesized (face: faces[j]);
127 const char *synth_str = is_synth ? "*" : "";
128 width = MAX (width, strlen (synth_str) + strlen (face_name));
129 }
130
131 for (j = 0; j < n_faces; j++)
132 {
133 const char *face_name = pango_font_face_get_face_name (face: faces[j]);
134 gboolean is_synth = pango_font_face_is_synthesized (face: faces[j]);
135 const char *synth_str = is_synth ? "*" : "";
136 PangoFontDescription *desc = pango_font_face_describe (face: faces[j]);
137 char *desc_str = pango_font_description_to_string (desc);
138
139 g_print (format: " %s%s: %*s%s\n", synth_str, face_name,
140 width - (int)strlen (s: face_name) - (int)strlen (s: synth_str), "", desc_str);
141
142 if (opt_metrics)
143 {
144 PangoFontMetrics *metrics;
145
146 pango_font_description_set_absolute_size (desc, size: 10 * PANGO_SCALE);
147 metrics = pango_context_get_metrics (context: ctx, desc, language: pango_language_from_string (language: "en-us"));
148 g_print (format: " (a %d d %d h %d cw %d dw %d u %d %d s %d %d)\n",
149 pango_font_metrics_get_ascent (metrics),
150 pango_font_metrics_get_descent (metrics),
151 pango_font_metrics_get_height (metrics),
152 pango_font_metrics_get_approximate_char_width (metrics),
153 pango_font_metrics_get_approximate_digit_width (metrics),
154 pango_font_metrics_get_underline_position (metrics),
155 pango_font_metrics_get_underline_thickness (metrics),
156 pango_font_metrics_get_strikethrough_position (metrics),
157 pango_font_metrics_get_strikethrough_thickness (metrics));
158 pango_font_metrics_unref (metrics);
159 }
160
161 if (opt_variations &&
162 pango_font_family_is_variable (family: families[i]))
163 {
164 PangoFont *font;
165 hb_font_t *hb_font;
166 const int *coords;
167 unsigned int length;
168
169 pango_font_description_set_absolute_size (desc, size: 10 * PANGO_SCALE);
170
171 font = pango_context_load_font (context: ctx, desc);
172 hb_font = pango_font_get_hb_font (font);
173 coords = hb_font_get_var_coords_normalized (font: hb_font, length: &length);
174 if (coords)
175 {
176 hb_face_t *hb_face = hb_font_get_face (font: hb_font);
177 hb_ot_var_axis_info_t *axes;
178 unsigned int n_axes;
179 int i;
180
181 axes = g_new (hb_ot_var_axis_info_t, length);
182 n_axes = length;
183
184 hb_ot_var_get_axis_infos (face: hb_face, start_offset: 0, axes_count: &n_axes, axes_array: axes);
185
186 for (i = 0; i < length; i++)
187 {
188 char name[20];
189 unsigned int namelen = 20;
190
191 hb_ot_name_get_utf8 (face: hb_face, name_id: axes[i].name_id, HB_LANGUAGE_INVALID, text_size: &namelen, text: name);
192
193 g_print (format: " %s: %g (%g - %g, %g)\n",
194 name,
195 denorm_coord (axis: &axes[i], coord: coords[i]),
196 axes[i].min_value,
197 axes[i].max_value,
198 axes[i].default_value);
199 }
200 g_free (mem: axes);
201 }
202 }
203
204 g_free (mem: desc_str);
205 pango_font_description_free (desc);
206 }
207
208 g_free (mem: faces);
209 }
210 g_free (mem: families);
211 g_object_unref (object: ctx);
212 g_object_unref (object: fontmap);
213
214 return 0;
215}
216

source code of gtk/subprojects/pango/utils/pango-list.c