* Google Author(s): Behdad Esfahbod
*/
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
#include "hb-ot-shape-complex-indic.hh"
#include "hb-ot-shape-complex-vowel-constraints.hh"
#include "hb-ot-layout.hh"
{HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
{HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
{HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS},
- /*
- * Positioning features.
- * We don't care about the types.
- */
- {HB_TAG('d','i','s','t'), F_GLOBAL},
- {HB_TAG('a','b','v','m'), F_GLOBAL},
- {HB_TAG('b','l','w','m'), F_GLOBAL},
};
/*
* Must be in the same order as the indic_features array.
*/
enum {
- _NUKT,
- _AKHN,
- RPHF,
- _RKRF,
- PREF,
- BLWF,
- ABVF,
- HALF,
- PSTF,
- _VATU,
- _CJCT,
-
- INIT,
- _PRES,
- _ABVS,
- _BLWS,
- _PSTS,
- _HALN,
-
- _DIST,
- _ABVM,
- _BLWM,
+ _INDIC_NUKT,
+ _INDIC_AKHN,
+ INDIC_RPHF,
+ _INDIC_RKRF,
+ INDIC_PREF,
+ INDIC_BLWF,
+ INDIC_ABVF,
+ INDIC_HALF,
+ INDIC_PSTF,
+ _INDIC_VATU,
+ _INDIC_CJCT,
+
+ INDIC_INIT,
+ _INDIC_PRES,
+ _INDIC_ABVS,
+ _INDIC_BLWS,
+ _INDIC_PSTS,
+ _INDIC_HALN,
INDIC_NUM_FEATURES,
- INDIC_BASIC_FEATURES = INIT, /* Don't forget to update this! */
+ INDIC_BASIC_FEATURES = INDIC_INIT, /* Don't forget to update this! */
};
static void
-setup_syllables (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
+setup_syllables_indic (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
static void
-final_reordering (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
+initial_reordering_indic (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
static void
-clear_syllables (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
+final_reordering_indic (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
static void
collect_features_indic (hb_ot_shape_planner_t *plan)
hb_ot_map_builder_t *map = &plan->map;
/* Do this before any lookups have been applied. */
- map->add_gsub_pause (setup_syllables);
+ map->add_gsub_pause (setup_syllables_indic);
map->enable_feature (HB_TAG('l','o','c','l'));
/* The Indic specs do not require ccmp, but we apply it here since if
unsigned int i = 0;
- map->add_gsub_pause (initial_reordering);
+ map->add_gsub_pause (initial_reordering_indic);
for (; i < INDIC_BASIC_FEATURES; i++) {
map->add_feature (indic_features[i]);
map->add_gsub_pause (nullptr);
}
- map->add_gsub_pause (final_reordering);
+ map->add_gsub_pause (final_reordering_indic);
for (; i < INDIC_NUM_FEATURES; i++)
map->add_feature (indic_features[i]);
map->enable_feature (HB_TAG('c','a','l','t'));
map->enable_feature (HB_TAG('c','l','i','g'));
- map->add_gsub_pause (clear_syllables);
+ map->add_gsub_pause (_hb_clear_syllables);
}
static void
}
-struct would_substitute_feature_t
-{
- void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
- {
- zero_context = zero_context_;
- map->get_stage_lookups (0/*GSUB*/,
- map->get_feature_stage (0/*GSUB*/, feature_tag),
- &lookups, &count);
- }
-
- bool would_substitute (const hb_codepoint_t *glyphs,
- unsigned int glyphs_count,
- hb_face_t *face) const
- {
- for (unsigned int i = 0; i < count; i++)
- if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context))
- return true;
- return false;
- }
-
- private:
- const hb_ot_map_t::lookup_map_t *lookups;
- unsigned int count;
- bool zero_context;
-};
-
struct indic_shape_plan_t
{
bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
const indic_config_t *config;
bool is_old_spec;
+#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE
bool uniscribe_bug_compatible;
+#else
+ static constexpr bool uniscribe_bug_compatible = false;
+#endif
mutable hb_atomic_int_t virama_glyph;
- would_substitute_feature_t rphf;
- would_substitute_feature_t pref;
- would_substitute_feature_t blwf;
- would_substitute_feature_t pstf;
+ hb_indic_would_substitute_feature_t rphf;
+ hb_indic_would_substitute_feature_t pref;
+ hb_indic_would_substitute_feature_t blwf;
+ hb_indic_would_substitute_feature_t pstf;
+ hb_indic_would_substitute_feature_t vatu;
hb_mask_t mask_array[INDIC_NUM_FEATURES];
};
}
indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
+#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE
indic_plan->uniscribe_bug_compatible = hb_options ().uniscribe_bug_compatible;
+#endif
indic_plan->virama_glyph.set_relaxed (-1);
/* Use zero-context would_substitute() matching for new-spec of the main
indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context);
indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context);
indic_plan->pstf.init (&plan->map, HB_TAG('p','s','t','f'), zero_context);
+ indic_plan->vatu.init (&plan->map, HB_TAG('v','a','t','u'), zero_context);
for (unsigned int i = 0; i < ARRAY_LENGTH (indic_plan->mask_array); i++)
indic_plan->mask_array[i] = (indic_features[i].flags & F_GLOBAL) ?
* base at 0. The font however, only has lookups matching
* 930,94D in 'blwf', not the expected 94D,930 (with new-spec
* table). As such, we simply match both sequences. Seems
- * to work. */
+ * to work.
+ *
+ * Vatu is done as well, for:
+ * https://github.com/harfbuzz/harfbuzz/issues/1587
+ */
hb_codepoint_t glyphs[3] = {virama, consonant, virama};
if (indic_plan->blwf.would_substitute (glyphs , 2, face) ||
- indic_plan->blwf.would_substitute (glyphs+1, 2, face))
+ indic_plan->blwf.would_substitute (glyphs+1, 2, face) ||
+ indic_plan->vatu.would_substitute (glyphs , 2, face) ||
+ indic_plan->vatu.would_substitute (glyphs+1, 2, face))
return POS_BELOW_C;
if (indic_plan->pstf.would_substitute (glyphs , 2, face) ||
indic_plan->pstf.would_substitute (glyphs+1, 2, face))
}
-enum syllable_type_t {
- consonant_syllable,
- vowel_syllable,
- standalone_cluster,
- symbol_cluster,
- broken_cluster,
- non_indic_cluster,
+enum indic_syllable_type_t {
+ indic_consonant_syllable,
+ indic_vowel_syllable,
+ indic_standalone_cluster,
+ indic_symbol_cluster,
+ indic_broken_cluster,
+ indic_non_indic_cluster,
};
#include "hb-ot-shape-complex-indic-machine.hh"
}
static void
-setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
+setup_syllables_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_font_t *font HB_UNUSED,
+ hb_buffer_t *buffer)
{
- find_syllables (buffer);
+ find_syllables_indic (buffer);
foreach_syllable (buffer, start, end)
buffer->unsafe_to_break (start, end);
}
static void
-update_consonant_positions (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer)
+update_consonant_positions_indic (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
{
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
* and has more than one consonant, Ra is excluded from candidates for
* base consonants. */
unsigned int limit = start;
- if (indic_plan->mask_array[RPHF] &&
+ if (indic_plan->mask_array[INDIC_RPHF] &&
start + 3 <= end &&
(
(indic_plan->config->reph_mode == REPH_MODE_IMPLICIT && !is_joiner (info[start + 2])) ||
case BASE_POS_LAST_SINHALA:
{
- /* Sinhala base positioning is slightly different from main Indic, in that:
+ /* Sinhala base positioning is slightly different from main Indic, in that:
* 1. Its ZWJ behavior is different,
* 2. We don't need to look into the font for consonant positions.
*/
/* Reorder characters */
for (unsigned int i = start; i < base; i++)
- info[i].indic_position() = MIN (POS_PRE_C, (indic_position_t) info[i].indic_position());
+ info[i].indic_position() = hb_min (POS_PRE_C, (indic_position_t) info[i].indic_position());
if (base < end)
info[base].indic_position() = POS_BASE_C;
for (unsigned int i = base + 1; i < end; i++)
if (info[i].indic_category() == OT_H)
{
- unsigned int j;
- for (j = end - 1; j > i; j--)
+ unsigned int j;
+ for (j = end - 1; j > i; j--)
if (is_consonant (info[j]) ||
(disallow_double_halants && info[j].indic_category() == OT_H))
break;
memmove (&info[i], &info[i + 1], (j - i) * sizeof (info[0]));
info[j] = t;
}
- break;
+ break;
}
}
}
}
} else if (info[i].indic_position() != POS_SMVD) {
- last_pos = (indic_position_t) info[i].indic_position();
+ last_pos = (indic_position_t) info[i].indic_position();
}
}
}
info[j].indic_position() = info[i].indic_position();
last = i;
} else if (info[i].indic_category() == OT_M)
- last = i;
+ last = i;
}
{
/* Note! syllable() is a one-byte field. */
for (unsigned int i = base; i < end; i++)
- if (info[i].syllable() != 255)
+ if (info[i].syllable() != 255)
{
unsigned int max = i;
unsigned int j = start + info[i].syllable();
while (j != i)
{
- max = MAX (max, j);
+ max = hb_max (max, j);
unsigned int next = start + info[j].syllable();
info[j].syllable() = 255; /* So we don't process j later again. */
j = next;
/* Reph */
for (unsigned int i = start; i < end && info[i].indic_position() == POS_RA_TO_BECOME_REPH; i++)
- info[i].mask |= indic_plan->mask_array[RPHF];
+ info[i].mask |= indic_plan->mask_array[INDIC_RPHF];
/* Pre-base */
- mask = indic_plan->mask_array[HALF];
+ mask = indic_plan->mask_array[INDIC_HALF];
if (!indic_plan->is_old_spec &&
indic_plan->config->blwf_mode == BLWF_MODE_PRE_AND_POST)
- mask |= indic_plan->mask_array[BLWF];
+ mask |= indic_plan->mask_array[INDIC_BLWF];
for (unsigned int i = start; i < base; i++)
info[i].mask |= mask;
/* Base */
if (base < end)
info[base].mask |= mask;
/* Post-base */
- mask = indic_plan->mask_array[BLWF] | indic_plan->mask_array[ABVF] | indic_plan->mask_array[PSTF];
+ mask = indic_plan->mask_array[INDIC_BLWF] |
+ indic_plan->mask_array[INDIC_ABVF] |
+ indic_plan->mask_array[INDIC_PSTF];
for (unsigned int i = base + 1; i < end; i++)
info[i].mask |= mask;
}
(i + 2 == base ||
info[i+2].indic_category() != OT_ZWJ))
{
- info[i ].mask |= indic_plan->mask_array[BLWF];
- info[i+1].mask |= indic_plan->mask_array[BLWF];
+ info[i ].mask |= indic_plan->mask_array[INDIC_BLWF];
+ info[i+1].mask |= indic_plan->mask_array[INDIC_BLWF];
}
}
unsigned int pref_len = 2;
- if (indic_plan->mask_array[PREF] && base + pref_len < end)
+ if (indic_plan->mask_array[INDIC_PREF] && base + pref_len < end)
{
/* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */
for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
hb_codepoint_t glyphs[2];
for (unsigned int j = 0; j < pref_len; j++)
- glyphs[j] = info[i + j].codepoint;
+ glyphs[j] = info[i + j].codepoint;
if (indic_plan->pref.would_substitute (glyphs, pref_len, face))
{
for (unsigned int j = 0; j < pref_len; j++)
- info[i++].mask |= indic_plan->mask_array[PREF];
+ info[i++].mask |= indic_plan->mask_array[INDIC_PREF];
break;
}
}
/* A ZWNJ disables HALF. */
if (non_joiner)
- info[j].mask &= ~indic_plan->mask_array[HALF];
+ info[j].mask &= ~indic_plan->mask_array[INDIC_HALF];
} while (j > start && !is_consonant (info[j]));
}
hb_buffer_t *buffer,
unsigned int start, unsigned int end)
{
- const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
-
/* We treat placeholder/dotted-circle as if they are consonants, so we
* should just chain. Only if not in compatibility mode that is... */
+ const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
if (indic_plan->uniscribe_bug_compatible)
{
/* For dotted-circle, this is what Uniscribe does:
}
static void
-initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
- hb_face_t *face,
- hb_buffer_t *buffer,
- unsigned int start, unsigned int end)
+initial_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ unsigned int start, unsigned int end)
{
- syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
+ indic_syllable_type_t syllable_type = (indic_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
switch (syllable_type)
{
- case vowel_syllable: /* We made the vowels look like consonants. So let's call the consonant logic! */
- case consonant_syllable:
+ case indic_vowel_syllable: /* We made the vowels look like consonants. So let's call the consonant logic! */
+ case indic_consonant_syllable:
initial_reordering_consonant_syllable (plan, face, buffer, start, end);
break;
- case broken_cluster: /* We already inserted dotted-circles, so just call the standalone_cluster. */
- case standalone_cluster:
+ case indic_broken_cluster: /* We already inserted dotted-circles, so just call the standalone_cluster. */
+ case indic_standalone_cluster:
initial_reordering_standalone_cluster (plan, face, buffer, start, end);
break;
- case symbol_cluster:
- case non_indic_cluster:
+ case indic_symbol_cluster:
+ case indic_non_indic_cluster:
break;
}
}
static inline void
-insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font,
- hb_buffer_t *buffer)
+insert_dotted_circles_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
{
if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
return;
unsigned int count = buffer->len;
hb_glyph_info_t *info = buffer->info;
for (unsigned int i = 0; i < count; i++)
- if ((info[i].syllable() & 0x0F) == broken_cluster)
+ if ((info[i].syllable() & 0x0F) == indic_broken_cluster)
{
has_broken_syllables = true;
break;
while (buffer->idx < buffer->len && buffer->successful)
{
unsigned int syllable = buffer->cur().syllable();
- syllable_type_t syllable_type = (syllable_type_t) (syllable & 0x0F);
- if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
+ indic_syllable_type_t syllable_type = (indic_syllable_type_t) (syllable & 0x0F);
+ if (unlikely (last_syllable != syllable && syllable_type == indic_broken_cluster))
{
last_syllable = syllable;
ginfo.cluster = buffer->cur().cluster;
ginfo.mask = buffer->cur().mask;
ginfo.syllable() = buffer->cur().syllable();
- /* TODO Set glyph_props? */
/* Insert dottedcircle after possible Repha. */
while (buffer->idx < buffer->len && buffer->successful &&
last_syllable == buffer->cur().syllable() &&
buffer->cur().indic_category() == OT_Repha)
- buffer->next_glyph ();
+ buffer->next_glyph ();
buffer->output_info (ginfo);
}
}
static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer)
+initial_reordering_indic (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
{
- update_consonant_positions (plan, font, buffer);
- insert_dotted_circles (plan, font, buffer);
+ update_consonant_positions_indic (plan, font, buffer);
+ insert_dotted_circles_indic (plan, font, buffer);
foreach_syllable (buffer, start, end)
- initial_reordering_syllable (plan, font->face, buffer, start, end);
+ initial_reordering_syllable_indic (plan, font->face, buffer, start, end);
}
static void
-final_reordering_syllable (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- unsigned int start, unsigned int end)
+final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ unsigned int start, unsigned int end)
{
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
hb_glyph_info_t *info = buffer->info;
_hb_glyph_info_ligated (&info[i]) &&
_hb_glyph_info_multiplied (&info[i]))
{
- /* This will make sure that this glyph passes is_halant() test. */
+ /* This will make sure that this glyph passes is_halant() test. */
info[i].indic_category() = OT_H;
_hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
}
* syllable.
*/
- bool try_pref = !!indic_plan->mask_array[PREF];
+ bool try_pref = !!indic_plan->mask_array[INDIC_PREF];
/* Find base again */
unsigned int base;
if (try_pref && base + 1 < end)
{
for (unsigned int i = base + 1; i < end; i++)
- if ((info[i].mask & indic_plan->mask_array[PREF]) != 0)
+ if ((info[i].mask & indic_plan->mask_array[INDIC_PREF]) != 0)
{
if (!(_hb_glyph_info_substituted (&info[i]) &&
_hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
}
if (start < base && info[base].indic_position() > POS_BASE_C)
- base--;
+ base--;
break;
}
if (base == end && start < base &&
}
}
else
- new_pos = start; /* No move. */
+ new_pos = start; /* No move. */
}
if (start < new_pos && info[new_pos].indic_position () != POS_PRE_M)
/* Note: this merge_clusters() is intentionally *after* the reordering.
* Indic matra reordering is special and tricky... */
- buffer->merge_clusters (new_pos, MIN (end, base + 1));
+ buffer->merge_clusters (new_pos, hb_min (end, base + 1));
new_pos--;
}
} else {
for (unsigned int i = start; i < base; i++)
if (info[i].indic_position () == POS_PRE_M) {
- buffer->merge_clusters (i, MIN (end, base + 1));
+ buffer->merge_clusters (i, hb_min (end, base + 1));
break;
}
}
while (new_reph_pos + 1 < end && info[new_reph_pos + 1].indic_position() <= POS_AFTER_MAIN)
new_reph_pos++;
if (new_reph_pos < end)
- goto reph_move;
+ goto reph_move;
}
/* 4. If reph should be positioned before post-base consonant, find
!( FLAG_UNSAFE (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD))))
new_reph_pos++;
if (new_reph_pos < end)
- goto reph_move;
+ goto reph_move;
}
/* 5. If no consonant is found in steps 3 or 4, move reph to a position
* TEST: U+0930,U+094D,U+0915,U+094B,U+094D
*/
if (!indic_plan->uniscribe_bug_compatible &&
- unlikely (is_halant (info[new_reph_pos]))) {
+ unlikely (is_halant (info[new_reph_pos])))
+ {
for (unsigned int i = base + 1; i < new_reph_pos; i++)
if (info[i].indic_category() == OT_M) {
/* Ok, got it. */
new_reph_pos--;
}
}
+
goto reph_move;
}
if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */
{
for (unsigned int i = base + 1; i < end; i++)
- if ((info[i].mask & indic_plan->mask_array[PREF]) != 0)
+ if ((info[i].mask & indic_plan->mask_array[INDIC_PREF]) != 0)
{
/* 1. Only reorder a glyph produced by substitution during application
* of the <pref> feature. (Note that a font may shape a Ra consonant with
* the feature generally but block it in certain contexts.)
*/
- /* Note: We just check that something got substituted. We don't check that
+ /* Note: We just check that something got substituted. We don't check that
* the <pref> feature actually did it...
*
* Reorder pref only if it ligated. */
}
}
- break;
+ break;
}
}
if (!start ||
!(FLAG_UNSAFE (_hb_glyph_info_get_general_category (&info[start - 1])) &
FLAG_RANGE (HB_UNICODE_GENERAL_CATEGORY_FORMAT, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
- info[start].mask |= indic_plan->mask_array[INIT];
+ info[start].mask |= indic_plan->mask_array[INDIC_INIT];
else
buffer->unsafe_to_break (start - 1, start + 1);
}
{
case HB_SCRIPT_TAMIL:
case HB_SCRIPT_SINHALA:
- break;
+ break;
default:
/* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala.
static void
-final_reordering (const hb_ot_shape_plan_t *plan,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
+final_reordering_indic (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font HB_UNUSED,
+ hb_buffer_t *buffer)
{
unsigned int count = buffer->len;
if (unlikely (!count)) return;
foreach_syllable (buffer, start, end)
- final_reordering_syllable (plan, buffer, start, end);
+ final_reordering_syllable_indic (plan, buffer, start, end);
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);
static void
-clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
-{
- hb_glyph_info_t *info = buffer->info;
- unsigned int count = buffer->len;
- for (unsigned int i = 0; i < count; i++)
- info[i].syllable() = 0;
-}
-
-
-static void
preprocess_text_indic (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer,
hb_font_t *font)
* https://docs.microsoft.com/en-us/typography/script-development/sinhala#shaping
*/
- const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) c->plan->data;
+ const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) c->plan->data;
hb_codepoint_t glyph;
-
- if (hb_options ().uniscribe_bug_compatible ||
+ if (indic_plan->uniscribe_bug_compatible ||
(c->font->get_nominal_glyph (ab, &glyph) &&
indic_plan->pstf.would_substitute (&glyph, 1, c->font->face)))
{
HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
false, /* fallback_position */
};
+
+
+#endif