#ifdef HAVE_FREETYPE
#include <hb-ft.h>
#endif
+#ifdef HAVE_OT
+#include <hb-ot.h>
+#endif
+
+struct supported_font_funcs_t {
+ char name[4];
+ void (*func) (hb_font_t *);
+} supported_font_funcs[] =
+{
+#ifdef HAVE_FREETYPE
+ {"ft", hb_ft_font_set_funcs},
+#endif
+#ifdef HAVE_OT
+ {"ot", hb_ot_font_set_funcs},
+#endif
+};
void
va_list vap;
va_start (vap, format);
msg = g_strdup_vprintf (format, vap);
+ va_end (vap);
const char *prgname = g_get_prgname ();
g_printerr ("%s: %s\n", prgname, msg);
if (suggest_help)
{
view_options_t *view_opts = (view_options_t *) data;
view_options_t::margin_t &m = view_opts->margin;
- switch (sscanf (arg, "%lf %lf %lf %lf", &m.t, &m.r, &m.b, &m.l)) {
+ switch (sscanf (arg, "%lf%*[ ,]%lf%*[ ,]%lf%*[ ,]%lf", &m.t, &m.r, &m.b, &m.l)) {
case 1: m.r = m.t;
case 2: m.b = m.t;
case 3: m.l = m.r;
}
-
-static void
-parse_space (char **pp)
-{
- char c;
-#define ISSPACE(c) ((c)==' '||(c)=='\f'||(c)=='\n'||(c)=='\r'||(c)=='\t'||(c)=='\v')
- while (c = **pp, ISSPACE (c))
- (*pp)++;
-#undef ISSPACE
-}
-
-static hb_bool_t
-parse_char (char **pp, char c)
-{
- parse_space (pp);
-
- if (**pp != c)
- return false;
-
- (*pp)++;
- return true;
-}
-
-static hb_bool_t
-parse_uint (char **pp, unsigned int *pv)
+static gboolean
+parse_features (const char *name G_GNUC_UNUSED,
+ const char *arg,
+ gpointer data,
+ GError **error G_GNUC_UNUSED)
{
- char *p = *pp;
- unsigned int v;
+ shape_options_t *shape_opts = (shape_options_t *) data;
+ char *s = (char *) arg;
+ char *p;
- v = strtol (p, pp, 0);
+ shape_opts->num_features = 0;
+ g_free (shape_opts->features);
+ shape_opts->features = NULL;
- if (p == *pp)
- return false;
+ if (!*s)
+ return true;
- *pv = v;
- return true;
-}
+ /* count the features first, so we can allocate memory */
+ p = s;
+ do {
+ shape_opts->num_features++;
+ p = strchr (p, ',');
+ if (p)
+ p++;
+ } while (p);
+ shape_opts->features = (hb_feature_t *) calloc (shape_opts->num_features, sizeof (*shape_opts->features));
-static hb_bool_t
-parse_feature_value_prefix (char **pp, hb_feature_t *feature)
-{
- if (parse_char (pp, '-'))
- feature->value = 0;
- else {
- parse_char (pp, '+');
- feature->value = 1;
+ /* now do the actual parsing */
+ p = s;
+ shape_opts->num_features = 0;
+ while (p && *p) {
+ char *end = strchr (p, ',');
+ if (hb_feature_from_string (p, end ? end - p : -1, &shape_opts->features[shape_opts->num_features]))
+ shape_opts->num_features++;
+ p = end ? end + 1 : NULL;
}
return true;
}
-static hb_bool_t
-parse_feature_tag (char **pp, hb_feature_t *feature)
-{
- char *p = *pp, c;
-
- parse_space (pp);
-
-#define ISALNUM(c) (('a' <= (c) && (c) <= 'z') || ('A' <= (c) && (c) <= 'Z') || ('0' <= (c) && (c) <= '9'))
- while (c = **pp, ISALNUM(c))
- (*pp)++;
-#undef ISALNUM
-
- if (p == *pp)
- return false;
-
- feature->tag = hb_tag_from_string (p, *pp - p);
- return true;
-}
-
-static hb_bool_t
-parse_feature_indices (char **pp, hb_feature_t *feature)
-{
- parse_space (pp);
-
- hb_bool_t has_start;
-
- feature->start = 0;
- feature->end = (unsigned int) -1;
-
- if (!parse_char (pp, '['))
- return true;
-
- has_start = parse_uint (pp, &feature->start);
-
- if (parse_char (pp, ':')) {
- parse_uint (pp, &feature->end);
- } else {
- if (has_start)
- feature->end = feature->start + 1;
- }
-
- return parse_char (pp, ']');
-}
-
-static hb_bool_t
-parse_feature_value_postfix (char **pp, hb_feature_t *feature)
-{
- return !parse_char (pp, '=') || parse_uint (pp, &feature->value);
-}
-
-
-static hb_bool_t
-parse_one_feature (char **pp, hb_feature_t *feature)
-{
- return parse_feature_value_prefix (pp, feature) &&
- parse_feature_tag (pp, feature) &&
- parse_feature_indices (pp, feature) &&
- parse_feature_value_postfix (pp, feature) &&
- (parse_char (pp, ',') || **pp == '\0');
-}
-
-static void
-skip_one_feature (char **pp)
-{
- char *e;
- e = strchr (*pp, ',');
- if (e)
- *pp = e + 1;
- else
- *pp = *pp + strlen (*pp);
-}
-
static gboolean
-parse_features (const char *name G_GNUC_UNUSED,
+parse_variations (const char *name G_GNUC_UNUSED,
const char *arg,
gpointer data,
GError **error G_GNUC_UNUSED)
{
- shape_options_t *shape_opts = (shape_options_t *) data;
+ font_options_t *font_opts = (font_options_t *) data;
char *s = (char *) arg;
char *p;
- shape_opts->num_features = 0;
- g_free (shape_opts->features);
- shape_opts->features = NULL;
+ font_opts->num_variations = 0;
+ g_free (font_opts->variations);
+ font_opts->variations = NULL;
if (!*s)
return true;
- /* count the features first, so we can allocate memory */
+ /* count the variations first, so we can allocate memory */
p = s;
do {
- shape_opts->num_features++;
+ font_opts->num_variations++;
p = strchr (p, ',');
if (p)
p++;
} while (p);
- shape_opts->features = (hb_feature_t *) calloc (shape_opts->num_features, sizeof (*shape_opts->features));
+ font_opts->variations = (hb_variation_t *) calloc (font_opts->num_variations, sizeof (*font_opts->variations));
/* now do the actual parsing */
p = s;
- shape_opts->num_features = 0;
- while (*p) {
- if (parse_one_feature (&p, &shape_opts->features[shape_opts->num_features]))
- shape_opts->num_features++;
- else
- skip_one_feature (&p);
+ font_opts->num_variations = 0;
+ while (p && *p) {
+ char *end = strchr (p, ',');
+ if (hb_variation_from_string (p, end ? end - p : -1, &font_opts->variations[font_opts->num_variations]))
+ font_opts->num_variations++;
+ p = end ? end + 1 : NULL;
}
return true;
GOptionEntry entries[] =
{
{"annotate", 0, 0, G_OPTION_ARG_NONE, &this->annotate, "Annotate output rendering", NULL},
- {"background", 0, 0, G_OPTION_ARG_STRING, &this->back, "Set background color (default: "DEFAULT_BACK")", "red/#rrggbb/#rrggbbaa"},
- {"foreground", 0, 0, G_OPTION_ARG_STRING, &this->fore, "Set foreground color (default: "DEFAULT_FORE")", "red/#rrggbb/#rrggbbaa"},
+ {"background", 0, 0, G_OPTION_ARG_STRING, &this->back, "Set background color (default: " DEFAULT_BACK ")", "rrggbb/rrggbbaa"},
+ {"foreground", 0, 0, G_OPTION_ARG_STRING, &this->fore, "Set foreground color (default: " DEFAULT_FORE ")", "rrggbb/rrggbbaa"},
{"line-space", 0, 0, G_OPTION_ARG_DOUBLE, &this->line_space, "Set space between lines (default: 0)", "units"},
- {"margin", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_margin, "Margin around output (default: "G_STRINGIFY(DEFAULT_MARGIN)")","one to four numbers"},
- {"font-size", 0, 0, G_OPTION_ARG_DOUBLE, &this->font_size, "Font size (default: "G_STRINGIFY(DEFAULT_FONT_SIZE)")","size"},
+ {"margin", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_margin, "Margin around output (default: " G_STRINGIFY(DEFAULT_MARGIN) ")","one to four numbers"},
{NULL}
};
parser->add_group (entries,
"view",
"View options:",
- "Options controlling output rendering",
+ "Options for output rendering",
this);
}
G_OPTION_ARG_CALLBACK, (gpointer) &list_shapers, "List available shapers and quit", NULL},
{"shaper", 0, G_OPTION_FLAG_HIDDEN,
G_OPTION_ARG_CALLBACK, (gpointer) &parse_shapers, "Hidden duplicate of --shapers", NULL},
- {"shapers", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_shapers, "Comma-separated list of shapers to try","list"},
+ {"shapers", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_shapers, "Set comma-separated list of shapers to try","list"},
{"direction", 0, 0, G_OPTION_ARG_STRING, &this->direction, "Set text direction (default: auto)", "ltr/rtl/ttb/btt"},
{"language", 0, 0, G_OPTION_ARG_STRING, &this->language, "Set text language (default: $LANG)", "langstr"},
{"script", 0, 0, G_OPTION_ARG_STRING, &this->script, "Set text script (default: auto)", "ISO-15924 tag"},
+ {"bot", 0, 0, G_OPTION_ARG_NONE, &this->bot, "Treat text as beginning-of-paragraph", NULL},
+ {"eot", 0, 0, G_OPTION_ARG_NONE, &this->eot, "Treat text as end-of-paragraph", NULL},
+ {"preserve-default-ignorables",0, 0, G_OPTION_ARG_NONE, &this->preserve_default_ignorables, "Preserve Default-Ignorable characters", NULL},
{"utf8-clusters", 0, 0, G_OPTION_ARG_NONE, &this->utf8_clusters, "Use UTF8 byte indices, not char indices", NULL},
+ {"cluster-level", 0, 0, G_OPTION_ARG_INT, &this->cluster_level, "Cluster merging level (default: 0)", "0/1/2"},
{"normalize-glyphs",0, 0, G_OPTION_ARG_NONE, &this->normalize_glyphs, "Rearrange glyph clusters in nominal order", NULL},
+ {"num-iterations", 0, 0, G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"},
{NULL}
};
parser->add_group (entries,
"shape",
"Shape options:",
- "Options controlling the shaping process",
+ "Options for the shaping process",
this);
const gchar *features_help = "Comma-separated list of font features\n"
"\n"
" Features can be enabled or disabled, either globally or limited to\n"
- " specific character ranges.\n"
+ " specific character ranges. The format for specifying feature settings\n"
+ " follows. All valid CSS font-feature-settings values other than 'normal'\n"
+ " and 'inherited' are also accepted, though, not documented below.\n"
"\n"
" The range indices refer to the positions between Unicode characters,\n"
" unless the --utf8-clusters is provided, in which case range indices\n"
"\n"
" Mixing it all:\n"
"\n"
- " \"kern[3:5]=0\" 1 3 5 # Turn feature off for range";
+ " \"aalt[3:5]=2\" 2 3 5 # Turn 2nd alternate on for range";
GOptionEntry entries2[] =
{
parser->add_group (entries2,
"features",
"Features options:",
- "Options controlling font features used",
+ "Options for font features used",
this);
}
+static gboolean
+parse_font_size (const char *name G_GNUC_UNUSED,
+ const char *arg,
+ gpointer data,
+ GError **error G_GNUC_UNUSED)
+{
+ font_options_t *font_opts = (font_options_t *) data;
+ if (0 == strcmp (arg, "upem"))
+ {
+ font_opts->font_size_y = font_opts->font_size_x = FONT_SIZE_UPEM;
+ return true;
+ }
+ switch (sscanf (arg, "%lf%*[ ,]%lf", &font_opts->font_size_x, &font_opts->font_size_y)) {
+ case 1: font_opts->font_size_y = font_opts->font_size_x;
+ case 2: return true;
+ default:
+ g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ "%s argument should be one to four space-separated numbers",
+ name);
+ return false;
+ }
+}
void
font_options_t::add_options (option_parser_t *parser)
{
+ char *text = NULL;
+
+ {
+ ASSERT_STATIC (ARRAY_LENGTH_CONST (supported_font_funcs) > 0);
+ GString *s = g_string_new (NULL);
+ g_string_printf (s, "Set font functions implementation to use (default: %s)\n\n Supported font function implementations are: %s",
+ supported_font_funcs[0].name,
+ supported_font_funcs[0].name);
+ for (unsigned int i = 1; i < ARRAY_LENGTH (supported_font_funcs); i++)
+ {
+ g_string_append_c (s, '/');
+ g_string_append (s, supported_font_funcs[i].name);
+ }
+ text = g_string_free (s, FALSE);
+ parser->free_later (text);
+ }
+
+ char *font_size_text;
+ if (default_font_size == FONT_SIZE_UPEM)
+ font_size_text = (char *) "Font size (default: upem)";
+ else
+ {
+ font_size_text = g_strdup_printf ("Font size (default: %d)", default_font_size);
+ parser->free_later (font_size_text);
+ }
+
GOptionEntry entries[] =
{
- {"font-file", 0, 0, G_OPTION_ARG_STRING, &this->font_file, "Font file-name", "filename"},
- {"face-index", 0, 0, G_OPTION_ARG_INT, &this->face_index, "Face index (default: 0)", "index"},
+ {"font-file", 0, 0, G_OPTION_ARG_STRING, &this->font_file, "Set font file-name", "filename"},
+ {"face-index", 0, 0, G_OPTION_ARG_INT, &this->face_index, "Set face index (default: 0)", "index"},
+ {"font-size", 0, default_font_size ? 0 : G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_size, font_size_text, "1/2 numbers or 'upem'"},
+ {"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"},
{NULL}
};
parser->add_group (entries,
"font",
"Font options:",
- "Options controlling the font",
+ "Options for the font",
+ this);
+
+ const gchar *variations_help = "Comma-separated list of font variations\n"
+ "\n"
+ " Variations are set globally. The format for specifying variation settings\n"
+ " follows. All valid CSS font-variation-settings values other than 'normal'\n"
+ " and 'inherited' are also accepted, though, not documented below.\n"
+ "\n"
+ " The format is a tag, optionally followed by an equals sign, followed by a\n"
+ " number. For example:\n"
+ "\n"
+ " \"wght=500\"\n"
+ " \"slnt=-7.5\"\n";
+
+ GOptionEntry entries2[] =
+ {
+ {"variations", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_variations, variations_help, "list"},
+ {NULL}
+ };
+ parser->add_group (entries2,
+ "variations",
+ "Varitions options:",
+ "Options for font variations used",
this);
}
GOptionEntry entries[] =
{
{"text", 0, 0, G_OPTION_ARG_STRING, &this->text, "Set input text", "string"},
- {"text-file", 0, 0, G_OPTION_ARG_STRING, &this->text_file, "Set input text file-name\n\n If no text is provided, standard input is used for input.", "filename"},
+ {"text-file", 0, 0, G_OPTION_ARG_STRING, &this->text_file, "Set input text file-name\n\n If no text is provided, standard input is used for input.\n", "filename"},
+ {"text-before", 0, 0, G_OPTION_ARG_STRING, &this->text_before, "Set text context before each line", "string"},
+ {"text-after", 0, 0, G_OPTION_ARG_STRING, &this->text_after, "Set text context after each line", "string"},
{NULL}
};
parser->add_group (entries,
"text",
"Text options:",
- "Options controlling the input text",
+ "Options for the input text",
this);
}
void
output_options_t::add_options (option_parser_t *parser)
{
+ const char *text;
+
+ if (NULL == supported_formats)
+ text = "Set output serialization format";
+ else
+ {
+ char *items = g_strjoinv ("/", const_cast<char **> (supported_formats));
+ text = g_strdup_printf ("Set output format\n\n Supported output formats are: %s", items);
+ g_free (items);
+ parser->free_later ((char *) text);
+ }
+
GOptionEntry entries[] =
{
{"output-file", 0, 0, G_OPTION_ARG_STRING, &this->output_file, "Set output file-name (default: stdout)","filename"},
- {"output-format", 0, 0, G_OPTION_ARG_STRING, &this->output_format, "Set output format", "format"},
+ {"output-format", 0, 0, G_OPTION_ARG_STRING, &this->output_format, text, "format"},
{NULL}
};
parser->add_group (entries,
"output",
- "Output options:",
- "Options controlling the output",
+ "Output destination & format options:",
+ "Options for the destination & form of the output",
this);
}
/* read it */
GString *gs = g_string_new (NULL);
char buf[BUFSIZ];
-#ifdef HAVE__SETMODE
- _setmode (fileno (stdin), _O_BINARY);
+#if defined(_WIN32) || defined(__CYGWIN__)
+ setmode (fileno (stdin), O_BINARY);
#endif
while (!feof (stdin)) {
size_t ret = fread (buf, 1, sizeof (buf), stdin);
}
}
+ if (debug)
+ mm = HB_MEMORY_MODE_DUPLICATE;
+
blob = hb_blob_create (font_data, len, mm, user_data, destroy);
}
font = hb_font_create (face);
- unsigned int upem = hb_face_get_upem (face);
- hb_font_set_scale (font, upem, upem);
+ if (font_size_x == FONT_SIZE_UPEM)
+ font_size_x = hb_face_get_upem (face);
+ if (font_size_y == FONT_SIZE_UPEM)
+ font_size_y = hb_face_get_upem (face);
+
+ int scale_x = (int) scalbnf (font_size_x, subpixel_bits);
+ int scale_y = (int) scalbnf (font_size_y, subpixel_bits);
+ hb_font_set_scale (font, scale_x, scale_y);
hb_face_destroy (face);
-#ifdef HAVE_FREETYPE
- hb_ft_font_set_funcs (font);
-#endif
+ hb_font_set_variations (font, variations, num_variations);
+
+ void (*set_font_funcs) (hb_font_t *) = NULL;
+ if (!font_funcs)
+ {
+ set_font_funcs = supported_font_funcs[0].func;
+ }
+ else
+ {
+ for (unsigned int i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
+ if (0 == g_ascii_strcasecmp (font_funcs, supported_font_funcs[i].name))
+ {
+ set_font_funcs = supported_font_funcs[i].func;
+ break;
+ }
+ if (!set_font_funcs)
+ {
+ GString *s = g_string_new (NULL);
+ for (unsigned int i = 0; i < ARRAY_LENGTH (supported_font_funcs); i++)
+ {
+ if (i)
+ g_string_append_c (s, '/');
+ g_string_append (s, supported_font_funcs[i].name);
+ }
+ char *p = g_string_free (s, FALSE);
+ fail (false, "Unknown font function implementation `%s'; supported values are: %s; default is %s",
+ font_funcs,
+ p,
+ supported_font_funcs[0].name);
+ //free (p);
+ }
+ }
+ set_font_funcs (font);
return font;
}
text_options_t::get_line (unsigned int *len)
{
if (text) {
- if (text_len == (unsigned int) -1)
- text_len = strlen (text);
+ if (!line) line = text;
+ if (line_len == (unsigned int) -1)
+ line_len = strlen (line);
- if (!text_len) {
+ if (!line_len) {
*len = 0;
return NULL;
}
- const char *ret = text;
- const char *p = (const char *) memchr (text, '\n', text_len);
+ const char *ret = line;
+ const char *p = (const char *) memchr (line, '\n', line_len);
unsigned int ret_len;
if (!p) {
- ret_len = text_len;
- text += ret_len;
- text_len = 0;
+ ret_len = line_len;
+ line += ret_len;
+ line_len = 0;
} else {
ret_len = p - ret;
- text += ret_len + 1;
- text_len -= ret_len + 1;
+ line += ret_len + 1;
+ line_len -= ret_len + 1;
}
*len = ret_len;
if (output_file)
fp = fopen (output_file, "wb");
else {
-#ifdef HAVE__SETMODE
- _setmode (fileno (stdout), _O_BINARY);
+#if defined(_WIN32) || defined(__CYGWIN__)
+ setmode (fileno (stdout), O_BINARY);
#endif
fp = stdout;
}
{
GOptionEntry entries[] =
{
- {"no-glyph-names", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &this->show_glyph_names, "Use glyph indices instead of names", NULL},
- {"no-positions", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &this->show_positions, "Do not show glyph positions", NULL},
- {"no-clusters", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &this->show_clusters, "Do not show cluster mapping", NULL},
- {"show-text", 0, 0, G_OPTION_ARG_NONE, &this->show_text, "Show input text", NULL},
- {"show-unicode", 0, 0, G_OPTION_ARG_NONE, &this->show_unicode, "Show input Unicode codepoints", NULL},
- {"show-line-num", 0, 0, G_OPTION_ARG_NONE, &this->show_line_num, "Show line numbers", NULL},
- {"verbose", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,(gpointer) &parse_verbose, "Show everything", NULL},
+ {"show-text", 0, 0, G_OPTION_ARG_NONE, &this->show_text, "Prefix each line of output with its corresponding input text", NULL},
+ {"show-unicode", 0, 0, G_OPTION_ARG_NONE, &this->show_unicode, "Prefix each line of output with its corresponding input codepoint(s)", NULL},
+ {"show-line-num", 0, 0, G_OPTION_ARG_NONE, &this->show_line_num, "Prefix each line of output with its corresponding input line number", NULL},
+ {"verbose", 0, G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK, (gpointer) &parse_verbose, "Prefix each line of output with all of the above", NULL},
+ {"no-glyph-names", 0, G_OPTION_FLAG_REVERSE,
+ G_OPTION_ARG_NONE, &this->show_glyph_names, "Output glyph indices instead of names", NULL},
+ {"no-positions", 0, G_OPTION_FLAG_REVERSE,
+ G_OPTION_ARG_NONE, &this->show_positions, "Do not output glyph positions", NULL},
+ {"no-clusters", 0, G_OPTION_FLAG_REVERSE,
+ G_OPTION_ARG_NONE, &this->show_clusters, "Do not output cluster indices", NULL},
+ {"show-extents", 0, 0, G_OPTION_ARG_NONE, &this->show_extents, "Output glyph extents", NULL},
{NULL}
};
parser->add_group (entries,
- "format",
- "Format options:",
- "Options controlling the formatting of buffer contents",
+ "output-syntax",
+ "Output syntax:\n"
+ " text: [<glyph name or index>=<glyph cluster index within input>@<horizontal displacement>,<vertical displacement>+<horizontal advance>,<vertical advance>|...]\n"
+ " json: [{\"g\": <glyph name or index>, \"ax\": <horizontal advance>, \"ay\": <vertical advance>, \"dx\": <horizontal displacement>, \"dy\": <vertical displacement>, \"cl\": <glyph cluster index within input>}, ...]\n"
+ "\nOutput syntax options:",
+ "Options for the syntax of the output",
this);
}
void
format_options_t::serialize_glyphs (hb_buffer_t *buffer,
hb_font_t *font,
- hb_bool_t utf8_clusters,
+ hb_buffer_serialize_format_t output_format,
+ hb_buffer_serialize_flags_t flags,
GString *gs)
{
- unsigned int num_glyphs = hb_buffer_get_length (buffer);
- hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
- hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL);
-
g_string_append_c (gs, '[');
- for (unsigned int i = 0; i < num_glyphs; i++)
- {
- if (i)
- g_string_append_c (gs, '|');
-
- char glyph_name[128];
- if (show_glyph_names) {
- hb_font_glyph_to_string (font, info->codepoint, glyph_name, sizeof (glyph_name));
- g_string_append_printf (gs, "%s", glyph_name);
- } else
- g_string_append_printf (gs, "%u", info->codepoint);
-
- if (show_clusters) {
- g_string_append_printf (gs, "=%u", info->cluster);
- if (utf8_clusters)
- g_string_append (gs, "u8");
- }
-
- if (show_positions && (pos->x_offset || pos->y_offset)) {
- g_string_append_c (gs, '@');
- if (pos->x_offset) g_string_append_printf (gs, "%d", pos->x_offset);
- if (pos->y_offset) g_string_append_printf (gs, ",%d", pos->y_offset);
- }
- if (show_positions && (pos->x_advance || pos->y_advance)) {
- g_string_append_c (gs, '+');
- if (pos->x_advance) g_string_append_printf (gs, "%d", pos->x_advance);
- if (pos->y_advance) g_string_append_printf (gs, ",%d", pos->y_advance);
- }
-
- info++;
- pos++;
+ unsigned int num_glyphs = hb_buffer_get_length (buffer);
+ unsigned int start = 0;
+
+ while (start < num_glyphs) {
+ char buf[1024];
+ unsigned int consumed;
+ start += hb_buffer_serialize_glyphs (buffer, start, num_glyphs,
+ buf, sizeof (buf), &consumed,
+ font, output_format, flags);
+ if (!consumed)
+ break;
+ g_string_append (gs, buf);
}
g_string_append_c (gs, ']');
}
const char *text,
unsigned int text_len,
hb_font_t *font,
- hb_bool_t utf8_clusters,
GString *gs)
{
if (show_text) {
const char *text,
unsigned int text_len,
hb_font_t *font,
- hb_bool_t utf8_clusters,
+ hb_buffer_serialize_format_t output_format,
+ hb_buffer_serialize_flags_t format_flags,
GString *gs)
{
serialize_line_no (line_no, gs);
- serialize_glyphs (buffer, font, utf8_clusters, gs);
+ serialize_glyphs (buffer, font, output_format, format_flags, gs);
g_string_append_c (gs, '\n');
}