Port Arabic fallback ligating to share code with GSUB
This will eventually allow us to skip marks, as well as (fallback) attach marks to ligature components of fallback-shaped Arabic. That would be pretty cool. I kludged GDEF props in, so mark-skipping works, but the produced ligature id/components will be cleared later by substitute_start() et al. Perhaps using a synthetic table for Arabic fallback shaping was a better idea. The current approach has way too many layering violations...
This commit is contained in:
parent
5e399a8a45
commit
2fcbbdb41a
|
@ -134,6 +134,10 @@ struct hb_apply_context_t
|
||||||
has_glyph_classes (gdef.has_glyph_classes ()),
|
has_glyph_classes (gdef.has_glyph_classes ()),
|
||||||
digest (*digest_) {}
|
digest (*digest_) {}
|
||||||
|
|
||||||
|
void set_lookup_props (unsigned int lookup_props_) {
|
||||||
|
lookup_props = lookup_props_;
|
||||||
|
}
|
||||||
|
|
||||||
void set_lookup (const Lookup &l) {
|
void set_lookup (const Lookup &l) {
|
||||||
lookup_props = l.get_props ();
|
lookup_props = l.get_props ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#include "hb-ot-shape-complex-private.hh"
|
#include "hb-ot-shape-complex-private.hh"
|
||||||
#include "hb-ot-shape-private.hh"
|
#include "hb-ot-shape-private.hh"
|
||||||
|
#include "hb-ot-layout-gsubgpos-private.hh"
|
||||||
|
|
||||||
|
|
||||||
/* buffer var allocations */
|
/* buffer var allocations */
|
||||||
|
@ -88,17 +88,6 @@ static hb_codepoint_t get_arabic_shape (hb_codepoint_t u, unsigned int shape)
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t get_ligature (hb_codepoint_t first, hb_codepoint_t second)
|
|
||||||
{
|
|
||||||
if (unlikely (!second)) return 0;
|
|
||||||
for (unsigned i = 0; i < ARRAY_LENGTH (ligature_table); i++)
|
|
||||||
if (ligature_table[i].first == first)
|
|
||||||
for (unsigned j = 0; j < ARRAY_LENGTH (ligature_table[i].ligatures); j++)
|
|
||||||
if (ligature_table[i].ligatures[j].second == second)
|
|
||||||
return ligature_table[i].ligatures[j].ligature;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const hb_tag_t arabic_features[] =
|
static const hb_tag_t arabic_features[] =
|
||||||
{
|
{
|
||||||
HB_TAG('i','n','i','t'),
|
HB_TAG('i','n','i','t'),
|
||||||
|
@ -257,20 +246,57 @@ arabic_fallback_shape (hb_font_t *font, hb_buffer_t *buffer)
|
||||||
buffer->info[i].codepoint = shaped;
|
buffer->info[i].codepoint = shaped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OT::hb_apply_context_t c (font, buffer, 1/*global mask*/, NULL);
|
||||||
|
c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
|
||||||
|
|
||||||
/* Mandatory ligatures */
|
/* Mandatory ligatures */
|
||||||
buffer->clear_output ();
|
buffer->clear_output ();
|
||||||
for (buffer->idx = 0; buffer->idx + 1 < count;) {
|
for (buffer->idx = 0; buffer->idx + 1 < count;)
|
||||||
hb_codepoint_t ligature = get_ligature (buffer->cur().codepoint,
|
{
|
||||||
buffer->cur(+1).codepoint);
|
const unsigned int count = 2;
|
||||||
if (likely (!ligature) || !(font->get_glyph (ligature, 0, &glyph))) {
|
unsigned int end_offset;
|
||||||
buffer->next_glyph ();
|
bool is_mark_ligature;
|
||||||
continue;
|
unsigned int total_component_count;
|
||||||
|
|
||||||
|
bool matched = false;
|
||||||
|
for (unsigned i = 0; i < ARRAY_LENGTH (ligature_table); i++)
|
||||||
|
{
|
||||||
|
if (ligature_table[i].first != buffer->cur().codepoint)
|
||||||
|
continue;
|
||||||
|
for (unsigned j = 0; j < ARRAY_LENGTH (ligature_table[i].ligatures); j++)
|
||||||
|
{
|
||||||
|
OT::USHORT component;
|
||||||
|
component.set (ligature_table[i].ligatures[j].second);
|
||||||
|
hb_codepoint_t ligature = ligature_table[i].ligatures[j].ligature;
|
||||||
|
if (likely (!OT::match_input (&c, count,
|
||||||
|
&component,
|
||||||
|
OT::match_glyph,
|
||||||
|
NULL,
|
||||||
|
&end_offset,
|
||||||
|
&is_mark_ligature,
|
||||||
|
&total_component_count) ||
|
||||||
|
!(font->get_glyph (ligature, 0, &glyph))))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Deal, we are forming the ligature. */
|
||||||
|
buffer->merge_clusters (buffer->idx, buffer->idx + end_offset);
|
||||||
|
|
||||||
|
OT::ligate_input (&c,
|
||||||
|
count,
|
||||||
|
&component,
|
||||||
|
ligature,
|
||||||
|
OT::match_glyph,
|
||||||
|
NULL,
|
||||||
|
is_mark_ligature,
|
||||||
|
total_component_count);
|
||||||
|
matched = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (matched)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (!matched)
|
||||||
buffer->replace_glyphs (2, 1, &ligature);
|
buffer->next_glyph ();
|
||||||
|
|
||||||
/* Technically speaking we can skip marks and stuff, like the GSUB path does.
|
|
||||||
* But who cares, we're in fallback! */
|
|
||||||
}
|
}
|
||||||
for (; buffer->idx < count;)
|
for (; buffer->idx < count;)
|
||||||
buffer->next_glyph ();
|
buffer->next_glyph ();
|
||||||
|
|
|
@ -319,8 +319,10 @@ hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
|
||||||
static inline void
|
static inline void
|
||||||
hb_ot_substitute_default (hb_ot_shape_context_t *c)
|
hb_ot_substitute_default (hb_ot_shape_context_t *c)
|
||||||
{
|
{
|
||||||
if (c->plan->shaper->preprocess_text)
|
if (c->plan->shaper->preprocess_text) {
|
||||||
|
hb_synthesize_glyph_classes (c); /* XXX This is a hack for now. */
|
||||||
c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
|
c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
|
||||||
|
}
|
||||||
|
|
||||||
hb_ot_mirror_chars (c);
|
hb_ot_mirror_chars (c);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue