diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 56c5913a6..6bbf8d8db 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -254,6 +254,7 @@ struct hb_font_t { inline hb_bool_t get_glyph_name (hb_codepoint_t glyph, char *name, unsigned int size) { + if (size) *name = '\0'; return klass->get.glyph_name (this, user_data, glyph, name, size, @@ -263,6 +264,8 @@ struct hb_font_t { inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph) { + *glyph = 0; + if (len == -1) len = strlen (name); return klass->get.glyph_from_name (this, user_data, name, len, glyph, @@ -377,6 +380,46 @@ struct hb_font_t { return ret; } + /* Generates gidDDD if glyph has no name. */ + inline void + glyph_to_string (hb_codepoint_t glyph, + char *s, unsigned int size) + { + if (get_glyph_name (glyph, s, size)) return; + + snprintf (s, size, "gid%u", glyph); + } + + /* Parses gidDDD and uniUUUU strings automatically. */ + inline hb_bool_t + glyph_from_string (const char *s, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph) + { + if (get_glyph_from_name (s, len, glyph)) return true; + + if (len == -1) len = strlen (s); + + /* Straight glyph index. */ + if (hb_codepoint_parse (s, len, 10, glyph)) + return true; + + if (len > 3) + { + /* gidDDD syntax for glyph indices. */ + if (0 == strncmp (s, "gid", 3) && + hb_codepoint_parse (s + 3, len - 3, 10, glyph)) + return true; + + /* uniUUUU and other Unicode character indices. */ + hb_codepoint_t unichar; + if (0 == strncmp (s, "uni", 3) && + hb_codepoint_parse (s + 3, len - 3, 16, &unichar) && + get_glyph (unichar, 0, glyph)) + return true; + } + + return false; + } private: inline hb_position_t em_scale (int16_t v, int scale) { return v * (int64_t) scale / hb_face_get_upem (this->face); } diff --git a/src/hb-font.cc b/src/hb-font.cc index 409b9e888..e5e4af723 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -200,6 +200,7 @@ hb_font_get_glyph_name_nil (hb_font_t *font, if (font->parent) return hb_font_get_glyph_name (font->parent, glyph, name, size); + if (size) *name = '\0'; return false; } @@ -410,10 +411,7 @@ hb_font_get_glyph_name (hb_font_t *font, hb_codepoint_t glyph, char *name, unsigned int size) { - hb_bool_t ret = font->get_glyph_name (glyph, name, size); - if (!ret) - snprintf (name, size, "gid%u", glyph); - return ret; + return font->get_glyph_name (glyph, name, size); } hb_bool_t @@ -490,6 +488,24 @@ hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, return font->get_glyph_contour_point_for_origin (glyph, point_index, direction, x, y); } +/* Generates gidDDD if glyph has no name. */ +void +hb_font_glyph_to_string (hb_font_t *font, + hb_codepoint_t glyph, + char *s, unsigned int size) +{ + font->glyph_to_string (glyph, s, size); +} + +/* Parses gidDDD and uniUUUU strings automatically. */ +hb_bool_t +hb_font_glyph_from_string (hb_font_t *font, + const char *s, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph) +{ + return font->glyph_from_string (s, len, glyph); +} + /* * hb_face_t diff --git a/src/hb-font.h b/src/hb-font.h index ae4fc9bb6..0fde2583d 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -346,6 +346,17 @@ hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, hb_direction_t direction, hb_position_t *x, hb_position_t *y); +/* Generates gidDDD if glyph has no name. */ +void +hb_font_glyph_to_string (hb_font_t *font, + hb_codepoint_t glyph, + char *s, unsigned int size); +/* Parses gidDDD and uniUUUU strings automatically. */ +hb_bool_t +hb_font_glyph_from_string (hb_font_t *font, + const char *s, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph); + /* * hb_font_t diff --git a/src/hb-private.hh b/src/hb-private.hh index 0f1e5cedf..865502051 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -791,6 +791,22 @@ hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *)) hb_bubble_sort (array, len, compar, (int *) NULL); } +static inline hb_bool_t +hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out) +{ + /* Pain because we don't know whether s is nul-terminated. */ + char buf[64]; + strncpy (buf, s, MIN (ARRAY_LENGTH (buf) - 1, len)); + buf[MIN (ARRAY_LENGTH (buf) - 1, len)] = '\0'; + + char *end; + errno = 0; + unsigned long v = strtoul (buf, &end, base); + if (errno) return false; + if (*end) return false; + *out = v; + return true; +} #endif /* HB_PRIVATE_HH */ diff --git a/src/test-would-substitute.cc b/src/test-would-substitute.cc index bf64a2955..95626edf4 100644 --- a/src/test-would-substitute.cc +++ b/src/test-would-substitute.cc @@ -88,7 +88,16 @@ main (int argc, char **argv) hb_blob_destroy (blob); blob = NULL; + hb_font_t *font = hb_font_create (face); +#ifdef HAVE_FREETYPE + hb_ft_font_set_funcs (font); +#endif + unsigned int len = argc - 3; - hb_codepoint_t glyphs[2] = {strtol (argv[3], NULL, 0), argc > 4 ? strtol (argv[4], NULL, 0) : (hb_codepoint_t) -1}; + hb_codepoint_t glyphs[2]; + if (!hb_font_glyph_from_string (font, argv[3], -1, &glyphs[0]) || + (argc > 4 && + !hb_font_glyph_from_string (font, argv[4], -1, &glyphs[1]))) + return 2; return !hb_ot_layout_would_substitute_lookup (face, glyphs, len, strtol (argv[2], NULL, 0)); } diff --git a/util/options.cc b/util/options.cc index d2a3846ee..c05cee6d0 100644 --- a/util/options.cc +++ b/util/options.cc @@ -749,7 +749,7 @@ format_options_t::serialize_glyphs (hb_buffer_t *buffer, char glyph_name[128]; if (show_glyph_names) { - hb_font_get_glyph_name (font, info->codepoint, glyph_name, sizeof (glyph_name)); + 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);