diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index bb8040fd9..f2c75930d 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -85,6 +85,8 @@ hb_buffer_get_glyph_positions hb_buffer_has_positions hb_buffer_get_invisible_glyph hb_buffer_set_invisible_glyph +hb_buffer_get_not_found_glyph +hb_buffer_set_not_found_glyph hb_buffer_set_replacement_codepoint hb_buffer_get_replacement_codepoint hb_buffer_normalize_glyphs diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index c6591ca23..caa562939 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -224,6 +224,7 @@ hb_buffer_t::reset () flags = HB_BUFFER_FLAG_DEFAULT; replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT; invisible = 0; + not_found = 0; clear (); } @@ -608,6 +609,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) = HB_BUFFER_CLUSTER_LEVEL_DEFAULT, HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, 0, /* invisible */ + 0, /* not_found */ HB_BUFFER_SCRATCH_FLAG_DEFAULT, HB_BUFFER_MAX_LEN_DEFAULT, HB_BUFFER_MAX_OPS_DEFAULT, @@ -1158,6 +1160,46 @@ hb_buffer_get_invisible_glyph (hb_buffer_t *buffer) return buffer->invisible; } +/** + * hb_buffer_set_not_found_glyph: + * @buffer: An #hb_buffer_t + * @not_found: the not-found #hb_codepoint_t + * + * Sets the #hb_codepoint_t that replaces characters not found in + * the font during shaping. + * + * The not-found glyph defaults to zero, sometimes knows as the + * ".notdef" glyph. This API allows for differentiating the two. + * + * Since: REPLACEME + **/ +void +hb_buffer_set_not_found_glyph (hb_buffer_t *buffer, + hb_codepoint_t not_found) +{ + if (unlikely (hb_object_is_immutable (buffer))) + return; + + buffer->not_found = not_found; +} + +/** + * hb_buffer_get_not_found_glyph: + * @buffer: An #hb_buffer_t + * + * See hb_buffer_set_not_found_glyph(). + * + * Return value: + * The @buffer not-found #hb_codepoint_t + * + * Since: REPLACEME + **/ +hb_codepoint_t +hb_buffer_get_not_found_glyph (hb_buffer_t *buffer) +{ + return buffer->not_found; +} + /** * hb_buffer_reset: diff --git a/src/hb-buffer.h b/src/hb-buffer.h index 865ccb227..a183cb9d4 100644 --- a/src/hb-buffer.h +++ b/src/hb-buffer.h @@ -383,6 +383,13 @@ hb_buffer_set_invisible_glyph (hb_buffer_t *buffer, HB_EXTERN hb_codepoint_t hb_buffer_get_invisible_glyph (hb_buffer_t *buffer); +HB_EXTERN void +hb_buffer_set_not_found_glyph (hb_buffer_t *buffer, + hb_codepoint_t not_found); + +HB_EXTERN hb_codepoint_t +hb_buffer_get_not_found_glyph (hb_buffer_t *buffer); + HB_EXTERN void hb_buffer_reset (hb_buffer_t *buffer); diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh index 8635ebd35..bde28933e 100644 --- a/src/hb-buffer.hh +++ b/src/hb-buffer.hh @@ -93,6 +93,7 @@ struct hb_buffer_t hb_buffer_cluster_level_t cluster_level; hb_codepoint_t replacement; /* U+FFFD or something else. */ hb_codepoint_t invisible; /* 0 or something else. */ + hb_codepoint_t not_found; /* 0 or something else. */ hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */ unsigned int max_len; /* Maximum allowed len. */ int max_ops; /* Maximum allowed operations. */ diff --git a/src/hb-font.hh b/src/hb-font.hh index 8fc7f44d4..dd5cd13db 100644 --- a/src/hb-font.hh +++ b/src/hb-font.hh @@ -217,9 +217,10 @@ struct hb_font_t } hb_bool_t get_nominal_glyph (hb_codepoint_t unicode, - hb_codepoint_t *glyph) + hb_codepoint_t *glyph, + hb_codepoint_t not_found = 0) { - *glyph = 0; + *glyph = not_found; return klass->get.f.nominal_glyph (this, user_data, unicode, glyph, klass->user_data.nominal_glyph); @@ -238,9 +239,10 @@ struct hb_font_t } hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, - hb_codepoint_t *glyph) + hb_codepoint_t *glyph, + hb_codepoint_t not_found = 0) { - *glyph = 0; + *glyph = not_found; return klass->get.f.variation_glyph (this, user_data, unicode, variation_selector, glyph, klass->user_data.variation_glyph); diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index 778b5b8bd..839cc9122 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -171,7 +171,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor hb_codepoint_t u = buffer->cur().codepoint; hb_codepoint_t glyph = 0; - if (shortest && c->font->get_nominal_glyph (u, &glyph)) + if (shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found)) { next_char (buffer, glyph); return; @@ -183,7 +183,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor return; } - if (!shortest && c->font->get_nominal_glyph (u, &glyph)) + if (!shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found)) { next_char (buffer, glyph); return; @@ -312,6 +312,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, buffer, font, buffer->unicode, + buffer->not_found, plan->shaper->decompose ? plan->shaper->decompose : decompose_unicode, plan->shaper->compose ? plan->shaper->compose : compose_unicode }; diff --git a/src/hb-ot-shape-normalize.hh b/src/hb-ot-shape-normalize.hh index 04f1a8009..12c78a235 100644 --- a/src/hb-ot-shape-normalize.hh +++ b/src/hb-ot-shape-normalize.hh @@ -56,6 +56,7 @@ struct hb_ot_shape_normalize_context_t hb_buffer_t *buffer; hb_font_t *font; hb_unicode_funcs_t *unicode; + const hb_codepoint_t not_found; bool (*decompose) (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t ab, hb_codepoint_t *a, diff --git a/util/shape-options.hh b/util/shape-options.hh index 6484085af..8d3318420 100644 --- a/util/shape-options.hh +++ b/util/shape-options.hh @@ -55,6 +55,7 @@ struct shape_options_t (remove_default_ignorables ? HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES : 0) | 0)); hb_buffer_set_invisible_glyph (buffer, invisible_glyph); + hb_buffer_set_not_found_glyph (buffer, not_found_glyph); hb_buffer_set_cluster_level (buffer, cluster_level); hb_buffer_guess_segment_properties (buffer); } @@ -305,6 +306,7 @@ struct shape_options_t char **shapers = nullptr; hb_bool_t utf8_clusters = false; hb_codepoint_t invisible_glyph = 0; + hb_codepoint_t not_found_glyph = 0; hb_buffer_cluster_level_t cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT; hb_bool_t normalize_glyphs = false; hb_bool_t verify = false; @@ -427,6 +429,7 @@ shape_options_t::add_options (option_parser_t *parser) {"preserve-default-ignorables",0, 0, G_OPTION_ARG_NONE, &this->preserve_default_ignorables, "Preserve Default-Ignorable characters", nullptr}, {"remove-default-ignorables",0, 0, G_OPTION_ARG_NONE, &this->remove_default_ignorables, "Remove Default-Ignorable characters", nullptr}, {"invisible-glyph", 0, 0, G_OPTION_ARG_INT, &this->invisible_glyph, "Glyph value to replace Default-Ignorables with", nullptr}, + {"not-found-glyph", 0, 0, G_OPTION_ARG_INT, &this->not_found_glyph, "Glyph value to replace not-found characters with", nullptr}, {"utf8-clusters", 0, 0, G_OPTION_ARG_NONE, &this->utf8_clusters, "Use UTF8 byte indices, not char indices", nullptr}, {"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", nullptr},