HarfBuzz: Update to version 5.1.0, use new FLAG_SAFE_TO_INSERT_TATWEEL flag to improve justification.
This commit is contained in:
parent
ea4b8de2b4
commit
2980c0d60c
|
@ -1679,6 +1679,9 @@
|
|||
<constant name="GRAPHEME_IS_CONNECTED" value="1024" enum="GraphemeFlag" is_bitfield="true">
|
||||
Grapheme is connected to the previous grapheme. Breaking line before this grapheme is not safe.
|
||||
</constant>
|
||||
<constant name="GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL" value="2048" enum="GraphemeFlag" is_bitfield="true">
|
||||
It is safe to insert a U+0640 before this grapheme for elongation.
|
||||
</constant>
|
||||
<constant name="HINTING_NONE" value="0" enum="Hinting">
|
||||
Disables font hinting (smoother but less crisp).
|
||||
</constant>
|
||||
|
|
|
@ -4718,6 +4718,11 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(const RID &p_shape
|
|||
if (sd_glyphs[i].font_rid != RID()) {
|
||||
Glyph gl = _shape_single_glyph(sd, 0x0640, HB_SCRIPT_ARABIC, HB_DIRECTION_RTL, sd->glyphs[i].font_rid, sd->glyphs[i].font_size);
|
||||
if ((sd_glyphs[i].flags & GRAPHEME_IS_VALID) == GRAPHEME_IS_VALID) {
|
||||
#if HB_VERSION_ATLEAST(5, 1, 0)
|
||||
if ((i > 0) && ((sd_glyphs[i - 1].flags & GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL) != GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
gl.start = sd_glyphs[i].start;
|
||||
gl.end = sd_glyphs[i].end;
|
||||
gl.repeat = 0;
|
||||
|
@ -4908,11 +4913,16 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
|
|||
|
||||
hb_buffer_clear_contents(p_sd->hb_buffer);
|
||||
hb_buffer_set_direction(p_sd->hb_buffer, p_direction);
|
||||
int flags = (p_start == 0 ? HB_BUFFER_FLAG_BOT : 0) | (p_end == p_sd->text.length() ? HB_BUFFER_FLAG_EOT : 0);
|
||||
if (p_sd->preserve_control) {
|
||||
hb_buffer_set_flags(p_sd->hb_buffer, (hb_buffer_flags_t)(HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES | (p_start == 0 ? HB_BUFFER_FLAG_BOT : 0) | (p_end == p_sd->text.length() ? HB_BUFFER_FLAG_EOT : 0)));
|
||||
flags |= HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES;
|
||||
} else {
|
||||
hb_buffer_set_flags(p_sd->hb_buffer, (hb_buffer_flags_t)(HB_BUFFER_FLAG_DEFAULT | (p_start == 0 ? HB_BUFFER_FLAG_BOT : 0) | (p_end == p_sd->text.length() ? HB_BUFFER_FLAG_EOT : 0)));
|
||||
flags |= HB_BUFFER_FLAG_DEFAULT;
|
||||
}
|
||||
#if HB_VERSION_ATLEAST(5, 1, 0)
|
||||
flags |= HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL;
|
||||
#endif
|
||||
hb_buffer_set_flags(p_sd->hb_buffer, (hb_buffer_flags_t)flags);
|
||||
hb_buffer_set_script(p_sd->hb_buffer, p_script);
|
||||
|
||||
if (p_sd->spans[p_span].language.is_empty()) {
|
||||
|
@ -4980,6 +4990,12 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
|
|||
gl.flags |= GRAPHEME_IS_CONNECTED;
|
||||
}
|
||||
|
||||
#if HB_VERSION_ATLEAST(5, 1, 0)
|
||||
if (glyph_info[i].mask & HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL) {
|
||||
gl.flags |= GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL;
|
||||
}
|
||||
#endif
|
||||
|
||||
gl.index = glyph_info[i].codepoint;
|
||||
if (gl.index != 0) {
|
||||
_ensure_glyph(fd, fss, gl.index);
|
||||
|
|
|
@ -521,6 +521,7 @@ void TextServer::_bind_methods() {
|
|||
BIND_BITFIELD_FLAG(GRAPHEME_IS_PUNCTUATION);
|
||||
BIND_BITFIELD_FLAG(GRAPHEME_IS_UNDERSCORE);
|
||||
BIND_BITFIELD_FLAG(GRAPHEME_IS_CONNECTED);
|
||||
BIND_BITFIELD_FLAG(GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL);
|
||||
|
||||
/* Hinting */
|
||||
BIND_ENUM_CONSTANT(HINTING_NONE);
|
||||
|
|
|
@ -116,6 +116,7 @@ public:
|
|||
GRAPHEME_IS_PUNCTUATION = 1 << 8, // Punctuation, except underscore (can be used as word break, but not line break or justifiction).
|
||||
GRAPHEME_IS_UNDERSCORE = 1 << 9, // Underscore (can be used as word break).
|
||||
GRAPHEME_IS_CONNECTED = 1 << 10, // Connected to previous grapheme.
|
||||
GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL = 1 << 11, // It is safe to insert a U+0640 before this grapheme for elongation.
|
||||
};
|
||||
|
||||
enum Hinting {
|
||||
|
|
|
@ -213,7 +213,7 @@ Files extracted from upstream source:
|
|||
## harfbuzz
|
||||
|
||||
- Upstream: https://github.com/harfbuzz/harfbuzz
|
||||
- Version: 5.0.1 (cbccadba8d1e51d6cc03a891b7c3a17f598e774c, 2022)
|
||||
- Version: 5.1.0 (f1f2be776bcd994fa9262622e1a7098a066e5cf7, 2022)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
|
@ -140,6 +140,13 @@ struct CursivePosFormat1
|
|||
unsigned int i = skippy_iter.idx;
|
||||
unsigned int j = buffer->idx;
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"cursive attaching glyph at %d to glyph at %d",
|
||||
i, j);
|
||||
}
|
||||
|
||||
buffer->unsafe_to_break (i, j + 1);
|
||||
float entry_x, entry_y, exit_x, exit_y;
|
||||
(this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
|
||||
|
@ -231,6 +238,13 @@ struct CursivePosFormat1
|
|||
pos[parent].x_offset = 0;
|
||||
}
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"cursive attached glyph at %d to glyph at %d",
|
||||
i, j);
|
||||
}
|
||||
|
||||
buffer->idx++;
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,13 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
|
|||
mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
|
||||
glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"attaching mark glyph at %d to glyph at %d",
|
||||
c->buffer->idx, glyph_pos);
|
||||
}
|
||||
|
||||
hb_glyph_position_t &o = buffer->cur_pos();
|
||||
o.x_offset = roundf (base_x - mark_x);
|
||||
o.y_offset = roundf (base_y - mark_y);
|
||||
|
@ -46,6 +53,13 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
|
|||
o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"attached mark glyph at %d to glyph at %d",
|
||||
c->buffer->idx, glyph_pos);
|
||||
}
|
||||
|
||||
buffer->idx++;
|
||||
return_trace (true);
|
||||
}
|
||||
|
@ -83,10 +97,11 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
|
|||
}
|
||||
};
|
||||
|
||||
static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
|
||||
const MarkArray &mark_array,
|
||||
const hb_set_t &glyphset,
|
||||
hb_map_t* klass_mapping /* INOUT */)
|
||||
HB_INTERNAL inline
|
||||
void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
|
||||
const MarkArray &mark_array,
|
||||
const hb_set_t &glyphset,
|
||||
hb_map_t* klass_mapping /* INOUT */)
|
||||
{
|
||||
hb_set_t orig_classes;
|
||||
|
||||
|
|
|
@ -217,10 +217,23 @@ struct PairPosFormat2_4
|
|||
}
|
||||
bail:
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"kerning glyphs at %d,%d",
|
||||
c->buffer->idx, skippy_iter.idx);
|
||||
}
|
||||
|
||||
applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
|
||||
applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"kerned glyphs at %d,%d",
|
||||
c->buffer->idx, skippy_iter.idx);
|
||||
}
|
||||
|
||||
success:
|
||||
if (applied_first || applied_second)
|
||||
buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
|
||||
|
|
|
@ -109,12 +109,28 @@ struct PairSet
|
|||
record_size);
|
||||
if (record)
|
||||
{
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"kerning glyphs at %d,%d",
|
||||
c->buffer->idx, pos);
|
||||
}
|
||||
|
||||
bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
|
||||
bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"kerned glyphs at %d,%d",
|
||||
c->buffer->idx, pos);
|
||||
}
|
||||
|
||||
if (applied_first || applied_second)
|
||||
buffer->unsafe_to_break (buffer->idx, pos + 1);
|
||||
if (len2)
|
||||
pos++;
|
||||
|
||||
buffer->idx = pos;
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
|
||||
#define OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
|
||||
|
||||
#include "ValueFormat.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
|
|
@ -39,12 +39,10 @@ struct SinglePosFormat1
|
|||
{
|
||||
if (!valueFormat.has_device ()) return;
|
||||
|
||||
auto it =
|
||||
+ hb_iter (this+coverage)
|
||||
| hb_filter (c->glyph_set)
|
||||
;
|
||||
hb_set_t intersection;
|
||||
(this+coverage).intersect_set (*c->glyph_set, intersection);
|
||||
if (!intersection) return;
|
||||
|
||||
if (!it) return;
|
||||
valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ()));
|
||||
}
|
||||
|
||||
|
@ -62,8 +60,22 @@ struct SinglePosFormat1
|
|||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioning glyph at %d",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
valueFormat.apply_value (c, this, values, buffer->cur_pos());
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioned glyph at %d",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
buffer->idx++;
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
|
@ -70,10 +70,24 @@ struct SinglePosFormat2
|
|||
|
||||
if (likely (index >= valueCount)) return_trace (false);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioning glyph at %d",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
valueFormat.apply_value (c, this,
|
||||
&values[index * valueFormat.get_len ()],
|
||||
buffer->cur_pos());
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioned glyph at %d",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
buffer->idx++;
|
||||
return_trace (true);
|
||||
}
|
||||
|
|
|
@ -57,8 +57,23 @@ struct AlternateSet
|
|||
|
||||
if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %d (alternate substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
c->replace_glyph (alternates[alt_index - 1]);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %d (alternate substitution)",
|
||||
c->buffer->idx - 1);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,24 @@ struct Ligature
|
|||
* as a "ligated" substitution. */
|
||||
if (unlikely (count == 1))
|
||||
{
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %d (ligature substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
c->replace_glyph (ligGlyph);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %d (ligature substitution)",
|
||||
c->buffer->idx - 1);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
@ -85,6 +102,31 @@ struct Ligature
|
|||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned pos = 0;
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
unsigned delta = c->buffer->sync_so_far ();
|
||||
|
||||
pos = c->buffer->idx;
|
||||
|
||||
char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0};
|
||||
char *p = buf;
|
||||
|
||||
match_end += delta;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
match_positions[i] += delta;
|
||||
if (i)
|
||||
*p++ = ',';
|
||||
sprintf (p, "%u", match_positions[i]);
|
||||
p += strlen(p);
|
||||
}
|
||||
|
||||
c->buffer->message (c->font,
|
||||
"ligating glyphs at %s",
|
||||
buf);
|
||||
}
|
||||
|
||||
ligate_input (c,
|
||||
count,
|
||||
match_positions,
|
||||
|
@ -92,6 +134,14 @@ struct Ligature
|
|||
ligGlyph,
|
||||
total_component_count);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"ligated glyph at %d",
|
||||
pos);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,23 @@ struct ReverseChainSingleSubstFormat1
|
|||
c->buffer->idx + 1, &end_index))
|
||||
{
|
||||
c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %d (reverse chaining substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
c->replace_glyph_inplace (substitute[index]);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %d (reverse chaining substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
/* Note: We DON'T decrease buffer->idx. The main loop does it
|
||||
* for us. This is useful for preventing surprises if someone
|
||||
* calls us through a Context lookup. */
|
||||
|
|
|
@ -40,17 +40,58 @@ struct Sequence
|
|||
* as a "multiplied" substitution. */
|
||||
if (unlikely (count == 1))
|
||||
{
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %d (multiple substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
c->replace_glyph (substitute.arrayZ[0]);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %d (multiple subtitution)",
|
||||
c->buffer->idx - 1);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
/* Spec disallows this, but Uniscribe allows it.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/253 */
|
||||
else if (unlikely (count == 0))
|
||||
{
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"deleting glyph at %d (multiple substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
c->buffer->delete_glyph ();
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"deleted glyph at %d (multiple substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"multiplying glyph at %d",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
|
||||
HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
|
||||
unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur());
|
||||
|
@ -65,6 +106,26 @@ struct Sequence
|
|||
}
|
||||
c->buffer->skip_glyph ();
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->sync_so_far ();
|
||||
|
||||
char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0};
|
||||
char *p = buf;
|
||||
|
||||
for (unsigned i = c->buffer->idx - count; i < c->buffer->idx; i++)
|
||||
{
|
||||
if (buf < p)
|
||||
*p++ = ',';
|
||||
sprintf (p, "%u", i);
|
||||
p += strlen(p);
|
||||
}
|
||||
|
||||
c->buffer->message (c->font,
|
||||
"multiplied glyphs at %s",
|
||||
buf);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,18 @@ struct SingleSubstFormat1_3
|
|||
hb_set_t intersection;
|
||||
(this+coverage).intersect_set (c->parent_active_glyphs (), intersection);
|
||||
|
||||
/* In degenerate fuzzer-found fonts, but not real fonts,
|
||||
* this table can keep adding new glyphs in each round of closure.
|
||||
* Refuse to close-over, if it maps glyph range to overlapping range. */
|
||||
hb_codepoint_t min_before = intersection.get_min ();
|
||||
hb_codepoint_t max_before = intersection.get_max ();
|
||||
hb_codepoint_t min_after = (min_before + d) & mask;
|
||||
hb_codepoint_t max_after = (max_before + d) & mask;
|
||||
if ((this+coverage).get_population () >= max_before - min_before &&
|
||||
((min_before <= min_after && min_after <= max_before) ||
|
||||
(min_before <= max_after && max_after <= max_before)))
|
||||
return;
|
||||
|
||||
+ hb_iter (intersection)
|
||||
| hb_map ([d, mask] (hb_codepoint_t g) { return (g + d) & mask; })
|
||||
| hb_sink (c->output)
|
||||
|
@ -82,8 +94,23 @@ struct SingleSubstFormat1_3
|
|||
|
||||
glyph_id = (glyph_id + d) & mask;
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %d (single substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
c->replace_glyph (glyph_id);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %d (single substitution)",
|
||||
c->buffer->idx - 1);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,8 +68,23 @@ struct SingleSubstFormat2_4
|
|||
|
||||
if (unlikely (index >= substitute.len)) return_trace (false);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %d (single substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
c->replace_glyph (substitute[index]);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %d (single substitution)",
|
||||
c->buffer->idx - 1);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,9 @@ struct CompositeGlyphRecord
|
|||
OVERLAP_COMPOUND = 0x0400,
|
||||
SCALED_COMPONENT_OFFSET = 0x0800,
|
||||
UNSCALED_COMPONENT_OFFSET = 0x1000,
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
GID_IS_24BIT = 0x2000
|
||||
#endif
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -34,7 +36,9 @@ struct CompositeGlyphRecord
|
|||
{
|
||||
unsigned int size = min_size;
|
||||
/* glyphIndex is 24bit instead of 16bit */
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
if (flags & GID_IS_24BIT) size += HBGlyphID24::static_size - HBGlyphID16::static_size;
|
||||
#endif
|
||||
/* arg1 and 2 are int16 */
|
||||
if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
|
||||
/* arg1 and 2 are int8 */
|
||||
|
@ -64,9 +68,11 @@ struct CompositeGlyphRecord
|
|||
void get_anchor_points (unsigned int &point1, unsigned int &point2) const
|
||||
{
|
||||
const auto *p = &StructAfter<const HBUINT8> (flags);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
if (flags & GID_IS_24BIT)
|
||||
p += HBGlyphID24::static_size;
|
||||
else
|
||||
#endif
|
||||
p += HBGlyphID16::static_size;
|
||||
if (flags & ARG_1_AND_2_ARE_WORDS)
|
||||
{
|
||||
|
@ -109,9 +115,11 @@ struct CompositeGlyphRecord
|
|||
matrix[1] = matrix[2] = 0.f;
|
||||
|
||||
const auto *p = &StructAfter<const HBINT8> (flags);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
if (flags & GID_IS_24BIT)
|
||||
p += HBGlyphID24::static_size;
|
||||
else
|
||||
#endif
|
||||
p += HBGlyphID16::static_size;
|
||||
int tx, ty;
|
||||
if (flags & ARG_1_AND_2_ARE_WORDS)
|
||||
|
@ -158,16 +166,20 @@ struct CompositeGlyphRecord
|
|||
public:
|
||||
hb_codepoint_t get_gid () const
|
||||
{
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
if (flags & GID_IS_24BIT)
|
||||
return StructAfter<const HBGlyphID24> (flags);
|
||||
else
|
||||
#endif
|
||||
return StructAfter<const HBGlyphID16> (flags);
|
||||
}
|
||||
void set_gid (hb_codepoint_t gid)
|
||||
{
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
if (flags & GID_IS_24BIT)
|
||||
StructAfter<HBGlyphID24> (flags) = gid;
|
||||
else
|
||||
#endif
|
||||
/* TODO assert? */
|
||||
StructAfter<HBGlyphID16> (flags) = gid;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright © 2022 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Garret Rieger
|
||||
*/
|
||||
|
||||
#include "graph.hh"
|
||||
#include "../OT/Layout/Common/Coverage.hh"
|
||||
|
||||
#ifndef GRAPH_COVERAGE_GRAPH_HH
|
||||
#define GRAPH_COVERAGE_GRAPH_HH
|
||||
|
||||
namespace graph {
|
||||
|
||||
struct CoverageFormat1 : public OT::Layout::Common::CoverageFormat1_3<SmallTypes>
|
||||
{
|
||||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
constexpr unsigned min_size = OT::Layout::Common::CoverageFormat1_3<SmallTypes>::min_size;
|
||||
if (vertex_len < min_size) return false;
|
||||
return vertex_len >= min_size + glyphArray.get_size () - glyphArray.len.get_size ();
|
||||
}
|
||||
};
|
||||
|
||||
struct CoverageFormat2 : public OT::Layout::Common::CoverageFormat2_4<SmallTypes>
|
||||
{
|
||||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
constexpr unsigned min_size = OT::Layout::Common::CoverageFormat2_4<SmallTypes>::min_size;
|
||||
if (vertex_len < min_size) return false;
|
||||
return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size ();
|
||||
}
|
||||
};
|
||||
|
||||
struct Coverage : public OT::Layout::Common::Coverage
|
||||
{
|
||||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
if (vertex_len < OT::Layout::Common::Coverage::min_size) return false;
|
||||
switch (u.format)
|
||||
{
|
||||
case 1: return ((CoverageFormat1*)this)->sanitize (vertex);
|
||||
case 2: return ((CoverageFormat2*)this)->sanitize (vertex);
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
// Not currently supported
|
||||
case 3:
|
||||
case 4:
|
||||
#endif
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // GRAPH_COVERAGE_GRAPH_HH
|
|
@ -24,6 +24,10 @@
|
|||
* Google Author(s): Garret Rieger
|
||||
*/
|
||||
|
||||
#include "../hb-set.hh"
|
||||
#include "../hb-priority-queue.hh"
|
||||
#include "../hb-serialize.hh"
|
||||
|
||||
#ifndef GRAPH_GRAPH_HH
|
||||
#define GRAPH_GRAPH_HH
|
||||
|
||||
|
@ -76,6 +80,22 @@ struct graph_t
|
|||
}
|
||||
}
|
||||
|
||||
void remove_real_link (unsigned child_index, const void* offset)
|
||||
{
|
||||
for (unsigned i = 0; i < obj.real_links.length; i++)
|
||||
{
|
||||
auto& link = obj.real_links[i];
|
||||
if (link.objidx != child_index)
|
||||
continue;
|
||||
|
||||
if ((obj.head + link.position) != offset)
|
||||
continue;
|
||||
|
||||
obj.real_links.remove (i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void remap_parents (const hb_vector_t<unsigned>& id_map)
|
||||
{
|
||||
for (unsigned i = 0; i < parents.length; i++)
|
||||
|
@ -107,6 +127,10 @@ struct graph_t
|
|||
return priority >= 3;
|
||||
}
|
||||
|
||||
size_t table_size () const {
|
||||
return obj.tail - obj.head;
|
||||
}
|
||||
|
||||
int64_t modified_distance (unsigned order) const
|
||||
{
|
||||
// TODO(garretrieger): once priority is high enough, should try
|
||||
|
@ -199,11 +223,22 @@ struct graph_t
|
|||
return vertices_.length - 1;
|
||||
}
|
||||
|
||||
const hb_serialize_context_t::object_t& object(unsigned i) const
|
||||
const hb_serialize_context_t::object_t& object (unsigned i) const
|
||||
{
|
||||
return vertices_[i].obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates a new topological sorting of graph ordered by the shortest
|
||||
* distance to each node if positions are marked as invalid.
|
||||
*/
|
||||
void sort_shortest_distance_if_needed ()
|
||||
{
|
||||
if (!positions_invalid) return;
|
||||
sort_shortest_distance ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Generates a new topological sorting of graph ordered by the shortest
|
||||
* distance to each node.
|
||||
|
@ -256,12 +291,12 @@ struct graph_t
|
|||
|
||||
check_success (!queue.in_error ());
|
||||
check_success (!sorted_graph.in_error ());
|
||||
if (!check_success (new_id == -1))
|
||||
print_orphaned_nodes ();
|
||||
|
||||
remap_all_obj_indices (id_map, &sorted_graph);
|
||||
|
||||
hb_swap (vertices_, sorted_graph);
|
||||
|
||||
if (!check_success (new_id == -1))
|
||||
print_orphaned_nodes ();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -310,6 +345,22 @@ struct graph_t
|
|||
}
|
||||
}
|
||||
|
||||
unsigned index_for_offset(unsigned node_idx, const void* offset) const
|
||||
{
|
||||
const auto& node = object (node_idx);
|
||||
if (offset < node.head || offset >= node.tail) return -1;
|
||||
|
||||
for (const auto& link : node.real_links)
|
||||
{
|
||||
if (offset != node.head + link.position)
|
||||
continue;
|
||||
return link.objidx;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Assign unique space numbers to each connected subgraph of 24 bit and/or 32 bit offset(s).
|
||||
* Currently, this is implemented specifically tailored to the structure of a GPOS/GSUB
|
||||
|
@ -317,6 +368,8 @@ struct graph_t
|
|||
*/
|
||||
bool assign_spaces ()
|
||||
{
|
||||
update_parents ();
|
||||
|
||||
hb_set_t visited;
|
||||
hb_set_t roots;
|
||||
find_space_roots (visited, roots);
|
||||
|
@ -458,6 +511,21 @@ struct graph_t
|
|||
find_subgraph (link.objidx, subgraph);
|
||||
}
|
||||
|
||||
size_t find_subgraph_size (unsigned node_idx, hb_set_t& subgraph, unsigned max_depth = -1)
|
||||
{
|
||||
if (subgraph.has (node_idx)) return 0;
|
||||
subgraph.add (node_idx);
|
||||
|
||||
const auto& o = vertices_[node_idx].obj;
|
||||
size_t size = o.tail - o.head;
|
||||
if (max_depth == 0)
|
||||
return size;
|
||||
|
||||
for (const auto& link : o.all_links ())
|
||||
size += find_subgraph_size (link.objidx, subgraph, max_depth - 1);
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds the topmost children of 32bit offsets in the subgraph starting
|
||||
* at node_idx. Found indices are placed into 'found'.
|
||||
|
@ -474,6 +542,37 @@ struct graph_t
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Moves the child of old_parent_idx pointed to by old_offset to a new
|
||||
* vertex at the new_offset.
|
||||
*/
|
||||
template<typename O>
|
||||
void move_child (unsigned old_parent_idx,
|
||||
const O* old_offset,
|
||||
unsigned new_parent_idx,
|
||||
const O* new_offset)
|
||||
{
|
||||
distance_invalid = true;
|
||||
positions_invalid = true;
|
||||
|
||||
auto& old_v = vertices_[old_parent_idx];
|
||||
auto& new_v = vertices_[new_parent_idx];
|
||||
|
||||
unsigned child_id = index_for_offset (old_parent_idx,
|
||||
old_offset);
|
||||
|
||||
auto* new_link = new_v.obj.real_links.push ();
|
||||
new_link->width = O::static_size;
|
||||
new_link->objidx = child_id;
|
||||
new_link->position = (const char*) new_offset - (const char*) new_v.obj.head;
|
||||
|
||||
auto& child = vertices_[child_id];
|
||||
child.parents.push (new_parent_idx);
|
||||
|
||||
old_v.remove_real_link (child_id, old_offset);
|
||||
child.remove_parent (old_parent_idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign
|
||||
* links. index_map is updated with mappings from old id to new id. If a duplication has already
|
||||
|
@ -581,6 +680,39 @@ struct graph_t
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Adds a new node to the graph, not connected to anything.
|
||||
*/
|
||||
unsigned new_node (char* head, char* tail)
|
||||
{
|
||||
positions_invalid = true;
|
||||
distance_invalid = true;
|
||||
|
||||
auto* clone = vertices_.push ();
|
||||
if (vertices_.in_error ()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
clone->obj.head = head;
|
||||
clone->obj.tail = tail;
|
||||
clone->distance = 0;
|
||||
clone->space = 0;
|
||||
|
||||
unsigned clone_idx = vertices_.length - 2;
|
||||
|
||||
// The last object is the root of the graph, so swap back the root to the end.
|
||||
// The root's obj idx does change, however since it's root nothing else refers to it.
|
||||
// all other obj idx's will be unaffected.
|
||||
hb_swap (vertices_[vertices_.length - 2], *clone);
|
||||
|
||||
// Since the root moved, update the parents arrays of all children on the root.
|
||||
for (const auto& l : root ().obj.all_links ())
|
||||
vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());
|
||||
|
||||
return clone_idx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Raises the sorting priority of all children.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright © 2022 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Garret Rieger
|
||||
*/
|
||||
|
||||
#include "gsubgpos-graph.hh"
|
||||
|
||||
namespace graph {
|
||||
|
||||
gsubgpos_graph_context_t::gsubgpos_graph_context_t (hb_tag_t table_tag_,
|
||||
graph_t& graph_)
|
||||
: table_tag (table_tag_),
|
||||
graph (graph_),
|
||||
lookup_list_index (0),
|
||||
lookups (),
|
||||
buffers ()
|
||||
{
|
||||
if (table_tag_ != HB_OT_TAG_GPOS
|
||||
&& table_tag_ != HB_OT_TAG_GSUB)
|
||||
return;
|
||||
|
||||
GSTAR* gstar = graph::GSTAR::graph_to_gstar (graph_);
|
||||
if (gstar) {
|
||||
gstar->find_lookups (graph, lookups);
|
||||
lookup_list_index = gstar->get_lookup_list_index (graph_);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned gsubgpos_graph_context_t::create_node (unsigned size)
|
||||
{
|
||||
char* buffer = (char*) hb_calloc (1, size);
|
||||
if (!buffer)
|
||||
return -1;
|
||||
|
||||
buffers.push (buffer);
|
||||
|
||||
return graph.new_node (buffer, buffer + size);
|
||||
}
|
||||
|
||||
unsigned gsubgpos_graph_context_t::num_non_ext_subtables () {
|
||||
unsigned count = 0;
|
||||
for (auto l : lookups.values ())
|
||||
{
|
||||
if (l->is_extension (table_tag)) continue;
|
||||
count += l->number_of_subtables ();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright © 2022 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Garret Rieger
|
||||
*/
|
||||
|
||||
#include "graph.hh"
|
||||
#include "../hb-ot-layout-gsubgpos.hh"
|
||||
|
||||
#ifndef GRAPH_GSUBGPOS_CONTEXT_HH
|
||||
#define GRAPH_GSUBGPOS_CONTEXT_HH
|
||||
|
||||
namespace graph {
|
||||
|
||||
struct Lookup;
|
||||
|
||||
struct gsubgpos_graph_context_t
|
||||
{
|
||||
hb_tag_t table_tag;
|
||||
graph_t& graph;
|
||||
unsigned lookup_list_index;
|
||||
hb_hashmap_t<unsigned, graph::Lookup*> lookups;
|
||||
hb_vector_t<char*> buffers;
|
||||
|
||||
HB_INTERNAL gsubgpos_graph_context_t (hb_tag_t table_tag_,
|
||||
graph_t& graph_);
|
||||
|
||||
~gsubgpos_graph_context_t ()
|
||||
{
|
||||
for (char* b : buffers)
|
||||
hb_free (b);
|
||||
}
|
||||
|
||||
HB_INTERNAL unsigned create_node (unsigned size);
|
||||
|
||||
void add_buffer (char* buffer)
|
||||
{
|
||||
buffers.push (buffer);
|
||||
}
|
||||
|
||||
private:
|
||||
HB_INTERNAL unsigned num_non_ext_subtables ();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // GRAPH_GSUBGPOS_CONTEXT
|
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
* Copyright © 2022 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Garret Rieger
|
||||
*/
|
||||
|
||||
#include "graph.hh"
|
||||
#include "../hb-ot-layout-gsubgpos.hh"
|
||||
#include "../OT/Layout/GSUB/ExtensionSubst.hh"
|
||||
#include "gsubgpos-context.hh"
|
||||
#include "pairpos-graph.hh"
|
||||
|
||||
#ifndef GRAPH_GSUBGPOS_GRAPH_HH
|
||||
#define GRAPH_GSUBGPOS_GRAPH_HH
|
||||
|
||||
namespace graph {
|
||||
|
||||
struct Lookup;
|
||||
|
||||
template<typename T>
|
||||
struct ExtensionFormat1 : public OT::ExtensionFormat1<T>
|
||||
{
|
||||
void reset(unsigned type)
|
||||
{
|
||||
this->format = 1;
|
||||
this->extensionLookupType = type;
|
||||
this->extensionOffset = 0;
|
||||
}
|
||||
|
||||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
return vertex_len >= OT::ExtensionFormat1<T>::static_size;
|
||||
}
|
||||
|
||||
unsigned get_lookup_type () const
|
||||
{
|
||||
return this->extensionLookupType;
|
||||
}
|
||||
|
||||
unsigned get_subtable_index (graph_t& graph, unsigned this_index) const
|
||||
{
|
||||
return graph.index_for_offset (this_index, &this->extensionOffset);
|
||||
}
|
||||
};
|
||||
|
||||
struct Lookup : public OT::Lookup
|
||||
{
|
||||
unsigned number_of_subtables () const
|
||||
{
|
||||
return subTable.len;
|
||||
}
|
||||
|
||||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
if (vertex_len < OT::Lookup::min_size) return false;
|
||||
return vertex_len >= this->get_size ();
|
||||
}
|
||||
|
||||
bool is_extension (hb_tag_t table_tag) const
|
||||
{
|
||||
return lookupType == extension_type (table_tag);
|
||||
}
|
||||
|
||||
bool make_extension (gsubgpos_graph_context_t& c,
|
||||
unsigned this_index)
|
||||
{
|
||||
unsigned type = lookupType;
|
||||
unsigned ext_type = extension_type (c.table_tag);
|
||||
if (!ext_type || is_extension (c.table_tag))
|
||||
{
|
||||
// NOOP
|
||||
return true;
|
||||
}
|
||||
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
||||
"Promoting lookup type %u (obj %u) to extension.",
|
||||
type,
|
||||
this_index);
|
||||
|
||||
for (unsigned i = 0; i < subTable.len; i++)
|
||||
{
|
||||
unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
|
||||
if (!make_subtable_extension (c,
|
||||
this_index,
|
||||
subtable_index))
|
||||
return false;
|
||||
}
|
||||
|
||||
lookupType = ext_type;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool split_subtables_if_needed (gsubgpos_graph_context_t& c,
|
||||
unsigned this_index)
|
||||
{
|
||||
unsigned type = lookupType;
|
||||
bool is_ext = is_extension (c.table_tag);
|
||||
|
||||
if (c.table_tag != HB_OT_TAG_GPOS)
|
||||
return true;
|
||||
|
||||
if (!is_ext && type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair)
|
||||
return true;
|
||||
|
||||
hb_vector_t<unsigned> all_new_subtables;
|
||||
for (unsigned i = 0; i < subTable.len; i++)
|
||||
{
|
||||
unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
|
||||
if (is_ext) {
|
||||
unsigned ext_subtable_index = subtable_index;
|
||||
ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
|
||||
(ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*)
|
||||
c.graph.object (ext_subtable_index).head;
|
||||
if (!extension->sanitize (c.graph.vertices_[ext_subtable_index]))
|
||||
continue;
|
||||
|
||||
subtable_index = extension->get_subtable_index (c.graph, ext_subtable_index);
|
||||
type = extension->get_lookup_type ();
|
||||
if (type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair)
|
||||
continue;
|
||||
}
|
||||
|
||||
PairPos* pairPos = (PairPos*) c.graph.object (subtable_index).head;
|
||||
if (!pairPos->sanitize (c.graph.vertices_[subtable_index])) continue;
|
||||
|
||||
hb_vector_t<unsigned> new_sub_tables = pairPos->split_subtables (c, subtable_index);
|
||||
if (new_sub_tables.in_error ()) return false;
|
||||
+ new_sub_tables.iter() | hb_sink (all_new_subtables);
|
||||
}
|
||||
|
||||
if (all_new_subtables)
|
||||
add_sub_tables (c, this_index, type, all_new_subtables);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void add_sub_tables (gsubgpos_graph_context_t& c,
|
||||
unsigned this_index,
|
||||
unsigned type,
|
||||
hb_vector_t<unsigned>& subtable_indices)
|
||||
{
|
||||
bool is_ext = is_extension (c.table_tag);
|
||||
auto& v = c.graph.vertices_[this_index];
|
||||
|
||||
size_t new_size = v.table_size ()
|
||||
+ subtable_indices.length * OT::Offset16::static_size;
|
||||
char* buffer = (char*) hb_calloc (1, new_size);
|
||||
c.add_buffer (buffer);
|
||||
memcpy (buffer, v.obj.head, v.table_size());
|
||||
|
||||
v.obj.head = buffer;
|
||||
v.obj.tail = buffer + new_size;
|
||||
|
||||
Lookup* new_lookup = (Lookup*) buffer;
|
||||
|
||||
new_lookup->subTable.len = subTable.len + subtable_indices.length;
|
||||
unsigned offset_index = subTable.len;
|
||||
for (unsigned subtable_id : subtable_indices)
|
||||
{
|
||||
if (is_ext)
|
||||
{
|
||||
unsigned ext_id = create_extension_subtable (c, subtable_id, type);
|
||||
c.graph.vertices_[subtable_id].parents.push (ext_id);
|
||||
subtable_id = ext_id;
|
||||
}
|
||||
|
||||
auto* link = v.obj.real_links.push ();
|
||||
link->width = 2;
|
||||
link->objidx = subtable_id;
|
||||
link->position = (char*) &new_lookup->subTable[offset_index++] -
|
||||
(char*) new_lookup;
|
||||
c.graph.vertices_[subtable_id].parents.push (this_index);
|
||||
}
|
||||
|
||||
// The head location of the lookup has changed, invalidating the lookups map entry
|
||||
// in the context. Update the map.
|
||||
c.lookups.set (this_index, new_lookup);
|
||||
}
|
||||
|
||||
unsigned create_extension_subtable (gsubgpos_graph_context_t& c,
|
||||
unsigned subtable_index,
|
||||
unsigned type)
|
||||
{
|
||||
unsigned extension_size = OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::static_size;
|
||||
|
||||
unsigned ext_index = c.create_node (extension_size);
|
||||
if (ext_index == (unsigned) -1)
|
||||
return -1;
|
||||
|
||||
auto& ext_vertex = c.graph.vertices_[ext_index];
|
||||
ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
|
||||
(ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*) ext_vertex.obj.head;
|
||||
extension->reset (type);
|
||||
|
||||
// Make extension point at the subtable.
|
||||
auto* l = ext_vertex.obj.real_links.push ();
|
||||
|
||||
l->width = 4;
|
||||
l->objidx = subtable_index;
|
||||
l->position = 4;
|
||||
|
||||
return ext_index;
|
||||
}
|
||||
|
||||
bool make_subtable_extension (gsubgpos_graph_context_t& c,
|
||||
unsigned lookup_index,
|
||||
unsigned subtable_index)
|
||||
{
|
||||
unsigned type = lookupType;
|
||||
|
||||
unsigned ext_index = create_extension_subtable(c, subtable_index, type);
|
||||
if (ext_index == (unsigned) -1)
|
||||
return false;
|
||||
|
||||
auto& lookup_vertex = c.graph.vertices_[lookup_index];
|
||||
for (auto& l : lookup_vertex.obj.real_links.writer ())
|
||||
{
|
||||
if (l.objidx == subtable_index)
|
||||
// Change lookup to point at the extension.
|
||||
l.objidx = ext_index;
|
||||
}
|
||||
|
||||
// Make extension point at the subtable.
|
||||
auto& ext_vertex = c.graph.vertices_[ext_index];
|
||||
auto& subtable_vertex = c.graph.vertices_[subtable_index];
|
||||
ext_vertex.parents.push (lookup_index);
|
||||
subtable_vertex.remap_parent (lookup_index, ext_index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned extension_type (hb_tag_t table_tag) const
|
||||
{
|
||||
switch (table_tag)
|
||||
{
|
||||
case HB_OT_TAG_GPOS: return 9;
|
||||
case HB_OT_TAG_GSUB: return 7;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct LookupList : public OT::LookupList<T>
|
||||
{
|
||||
bool sanitize (const graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
if (vertex_len < OT::LookupList<T>::min_size) return false;
|
||||
return vertex_len >= OT::LookupList<T>::item_size * this->len;
|
||||
}
|
||||
};
|
||||
|
||||
struct GSTAR : public OT::GSUBGPOS
|
||||
{
|
||||
static GSTAR* graph_to_gstar (graph_t& graph)
|
||||
{
|
||||
const auto& r = graph.root ();
|
||||
|
||||
GSTAR* gstar = (GSTAR*) r.obj.head;
|
||||
if (!gstar->sanitize (r))
|
||||
return nullptr;
|
||||
|
||||
return gstar;
|
||||
}
|
||||
|
||||
const void* get_lookup_list_field_offset () const
|
||||
{
|
||||
switch (u.version.major) {
|
||||
case 1: return u.version1.get_lookup_list_offset ();
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 2: return u.version2.get_lookup_list_offset ();
|
||||
#endif
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool sanitize (const graph_t::vertex_t& vertex)
|
||||
{
|
||||
int64_t len = vertex.obj.tail - vertex.obj.head;
|
||||
if (len < OT::GSUBGPOS::min_size) return false;
|
||||
return len >= get_size ();
|
||||
}
|
||||
|
||||
void find_lookups (graph_t& graph,
|
||||
hb_hashmap_t<unsigned, Lookup*>& lookups /* OUT */)
|
||||
{
|
||||
switch (u.version.major) {
|
||||
case 1: find_lookups<SmallTypes> (graph, lookups); break;
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 2: find_lookups<MediumTypes> (graph, lookups); break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
unsigned get_lookup_list_index (graph_t& graph)
|
||||
{
|
||||
return graph.index_for_offset (graph.root_idx (),
|
||||
get_lookup_list_field_offset());
|
||||
}
|
||||
|
||||
template<typename Types>
|
||||
void find_lookups (graph_t& graph,
|
||||
hb_hashmap_t<unsigned, Lookup*>& lookups /* OUT */)
|
||||
{
|
||||
unsigned lookup_list_idx = get_lookup_list_index (graph);
|
||||
|
||||
const LookupList<Types>* lookupList =
|
||||
(const LookupList<Types>*) graph.object (lookup_list_idx).head;
|
||||
if (!lookupList->sanitize (graph.vertices_[lookup_list_idx]))
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < lookupList->len; i++)
|
||||
{
|
||||
unsigned lookup_idx = graph.index_for_offset (lookup_list_idx, &(lookupList->arrayZ[i]));
|
||||
Lookup* lookup = (Lookup*) graph.object (lookup_idx).head;
|
||||
if (!lookup->sanitize (graph.vertices_[lookup_idx])) continue;
|
||||
lookups.set (lookup_idx, lookup);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif /* GRAPH_GSUBGPOS_GRAPH_HH */
|
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* Copyright © 2022 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Garret Rieger
|
||||
*/
|
||||
|
||||
#ifndef GRAPH_PAIRPOS_GRAPH_HH
|
||||
#define GRAPH_PAIRPOS_GRAPH_HH
|
||||
|
||||
#include "coverage-graph.hh"
|
||||
#include "../OT/Layout/GPOS/PairPos.hh"
|
||||
#include "../OT/Layout/GPOS/PosLookupSubTable.hh"
|
||||
|
||||
namespace graph {
|
||||
|
||||
struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>
|
||||
{
|
||||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
unsigned min_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size;
|
||||
if (vertex_len < min_size) return false;
|
||||
|
||||
return vertex_len >=
|
||||
min_size + pairSet.get_size () - pairSet.len.get_size();
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
{
|
||||
hb_set_t visited;
|
||||
|
||||
const unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
|
||||
const unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
|
||||
const unsigned base_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size
|
||||
+ coverage_size;
|
||||
|
||||
unsigned accumulated = base_size;
|
||||
hb_vector_t<unsigned> split_points;
|
||||
for (unsigned i = 0; i < pairSet.len; i++)
|
||||
{
|
||||
unsigned pair_set_index = pair_set_graph_index (c, this_index, i);
|
||||
accumulated += c.graph.find_subgraph_size (pair_set_index, visited);
|
||||
accumulated += SmallTypes::size; // for PairSet offset.
|
||||
|
||||
// TODO(garretrieger): don't count the size of the largest pairset against the limit, since
|
||||
// it will be packed last in the order and does not contribute to
|
||||
// the 64kb limit.
|
||||
|
||||
if (accumulated > (1 << 16))
|
||||
{
|
||||
split_points.push (i);
|
||||
accumulated = base_size;
|
||||
visited.clear (); // Pretend node sharing isn't allowed between splits.
|
||||
}
|
||||
}
|
||||
|
||||
return do_split (c, this_index, split_points);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Split this PairPos into two or more PairPos's. split_points defines
|
||||
// the indices (first index to include in the new table) to split at.
|
||||
// Returns the object id's of the newly created PairPos subtables.
|
||||
hb_vector_t<unsigned> do_split (gsubgpos_graph_context_t& c,
|
||||
unsigned this_index,
|
||||
const hb_vector_t<unsigned> split_points)
|
||||
{
|
||||
hb_vector_t<unsigned> new_objects;
|
||||
if (!split_points)
|
||||
return new_objects;
|
||||
|
||||
for (unsigned i = 0; i < split_points.length; i++)
|
||||
{
|
||||
unsigned start = split_points[i];
|
||||
unsigned end = (i < split_points.length - 1) ? split_points[i + 1] : pairSet.len;
|
||||
unsigned id = clone_range (c, this_index, start, end);
|
||||
|
||||
if (id == (unsigned) -1)
|
||||
{
|
||||
new_objects.reset ();
|
||||
new_objects.allocated = -1; // mark error
|
||||
return new_objects;
|
||||
}
|
||||
new_objects.push (id);
|
||||
}
|
||||
|
||||
if (!shrink (c, this_index, split_points[0]))
|
||||
{
|
||||
new_objects.reset ();
|
||||
new_objects.allocated = -1; // mark error
|
||||
}
|
||||
|
||||
return new_objects;
|
||||
}
|
||||
|
||||
bool shrink (gsubgpos_graph_context_t& c,
|
||||
unsigned this_index,
|
||||
unsigned count)
|
||||
{
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
||||
" Shrinking PairPosFormat1 (%u) to [0, %u).",
|
||||
this_index,
|
||||
count);
|
||||
unsigned old_count = pairSet.len;
|
||||
if (count >= old_count)
|
||||
return true;
|
||||
|
||||
pairSet.len = count;
|
||||
c.graph.vertices_[this_index].obj.tail -= (old_count - count) * SmallTypes::size;
|
||||
|
||||
unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
|
||||
unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
|
||||
auto& coverage_v = c.graph.vertices_[coverage_id];
|
||||
Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
|
||||
if (!coverage_table->sanitize (coverage_v))
|
||||
return false;
|
||||
|
||||
auto new_coverage =
|
||||
+ hb_zip (coverage_table->iter (), hb_range ())
|
||||
| hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
|
||||
return p.second < count;
|
||||
})
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
return make_coverage (c, new_coverage, coverage_id, coverage_size);
|
||||
}
|
||||
|
||||
// Create a new PairPos including PairSet's from start (inclusive) to end (exclusive).
|
||||
// Returns object id of the new object.
|
||||
unsigned clone_range (gsubgpos_graph_context_t& c,
|
||||
unsigned this_index,
|
||||
unsigned start, unsigned end) const
|
||||
{
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
||||
" Cloning PairPosFormat1 (%u) range [%u, %u).", this_index, start, end);
|
||||
|
||||
unsigned num_pair_sets = end - start;
|
||||
unsigned prime_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size
|
||||
+ num_pair_sets * SmallTypes::size;
|
||||
|
||||
unsigned pair_pos_prime_id = c.create_node (prime_size);
|
||||
if (pair_pos_prime_id == (unsigned) -1) return -1;
|
||||
|
||||
PairPosFormat1* pair_pos_prime = (PairPosFormat1*) c.graph.object (pair_pos_prime_id).head;
|
||||
pair_pos_prime->format = this->format;
|
||||
pair_pos_prime->valueFormat[0] = this->valueFormat[0];
|
||||
pair_pos_prime->valueFormat[1] = this->valueFormat[1];
|
||||
pair_pos_prime->pairSet.len = num_pair_sets;
|
||||
|
||||
for (unsigned i = start; i < end; i++)
|
||||
{
|
||||
c.graph.move_child<> (this_index,
|
||||
&pairSet[i],
|
||||
pair_pos_prime_id,
|
||||
&pair_pos_prime->pairSet[i - start]);
|
||||
}
|
||||
|
||||
unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
|
||||
unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
|
||||
auto& coverage_v = c.graph.vertices_[coverage_id];
|
||||
Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
|
||||
if (!coverage_table->sanitize (coverage_v))
|
||||
return false;
|
||||
|
||||
auto new_coverage =
|
||||
+ hb_zip (coverage_table->iter (), hb_range ())
|
||||
| hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
|
||||
return p.second >= start && p.second < end;
|
||||
})
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
unsigned coverage_prime_id = c.graph.new_node (nullptr, nullptr);
|
||||
auto& coverage_prime_vertex = c.graph.vertices_[coverage_prime_id];
|
||||
if (!make_coverage (c, new_coverage, coverage_prime_id, coverage_size))
|
||||
return -1;
|
||||
|
||||
auto* coverage_link = c.graph.vertices_[pair_pos_prime_id].obj.real_links.push ();
|
||||
coverage_link->width = SmallTypes::size;
|
||||
coverage_link->objidx = coverage_prime_id;
|
||||
coverage_link->position = 2;
|
||||
coverage_prime_vertex.parents.push (pair_pos_prime_id);
|
||||
|
||||
return pair_pos_prime_id;
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
bool make_coverage (gsubgpos_graph_context_t& c,
|
||||
It glyphs,
|
||||
unsigned dest_obj,
|
||||
unsigned max_size) const
|
||||
{
|
||||
char* buffer = (char*) hb_calloc (1, max_size);
|
||||
hb_serialize_context_t serializer (buffer, max_size);
|
||||
Coverage_serialize (&serializer, glyphs);
|
||||
serializer.end_serialize ();
|
||||
if (serializer.in_error ())
|
||||
{
|
||||
hb_free (buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
hb_bytes_t coverage_copy = serializer.copy_bytes ();
|
||||
c.add_buffer ((char *) coverage_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer.
|
||||
|
||||
auto& obj = c.graph.vertices_[dest_obj].obj;
|
||||
obj.head = (char *) coverage_copy.arrayZ;
|
||||
obj.tail = obj.head + coverage_copy.length;
|
||||
|
||||
hb_free (buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned pair_set_graph_index (gsubgpos_graph_context_t& c, unsigned this_index, unsigned i) const
|
||||
{
|
||||
return c.graph.index_for_offset (this_index, &pairSet[i]);
|
||||
}
|
||||
};
|
||||
|
||||
struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>
|
||||
{
|
||||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
// TODO(garretrieger): implement me!
|
||||
return true;
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
{
|
||||
// TODO(garretrieger): implement me!
|
||||
return hb_vector_t<unsigned> ();
|
||||
}
|
||||
};
|
||||
|
||||
struct PairPos : public OT::Layout::GPOS_impl::PairPos
|
||||
{
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1:
|
||||
return ((PairPosFormat1*)(&u.format1))->split_subtables (c, this_index);
|
||||
case 2:
|
||||
return ((PairPosFormat2*)(&u.format2))->split_subtables (c, this_index);
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 3: HB_FALLTHROUGH;
|
||||
case 4: HB_FALLTHROUGH;
|
||||
// Don't split 24bit PairPos's.
|
||||
#endif
|
||||
default:
|
||||
return hb_vector_t<unsigned> ();
|
||||
}
|
||||
}
|
||||
|
||||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
if (vertex_len < u.format.get_size ()) return false;
|
||||
|
||||
switch (u.format) {
|
||||
case 1:
|
||||
return ((PairPosFormat1*)(&u.format1))->sanitize (vertex);
|
||||
case 2:
|
||||
return ((PairPosFormat2*)(&u.format2))->sanitize (vertex);
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 3: HB_FALLTHROUGH;
|
||||
case 4: HB_FALLTHROUGH;
|
||||
#endif
|
||||
default:
|
||||
// We don't handle format 3 and 4 here.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // GRAPH_PAIRPOS_GRAPH_HH
|
|
@ -303,7 +303,7 @@ hb_blob_set_user_data (hb_blob_t *blob,
|
|||
* Since: 0.9.2
|
||||
**/
|
||||
void *
|
||||
hb_blob_get_user_data (hb_blob_t *blob,
|
||||
hb_blob_get_user_data (const hb_blob_t *blob,
|
||||
hb_user_data_key_t *key)
|
||||
{
|
||||
return hb_object_get_user_data (blob, key);
|
||||
|
|
|
@ -135,7 +135,7 @@ hb_blob_set_user_data (hb_blob_t *blob,
|
|||
|
||||
|
||||
HB_EXTERN void *
|
||||
hb_blob_get_user_data (hb_blob_t *blob,
|
||||
hb_blob_get_user_data (const hb_blob_t *blob,
|
||||
hb_user_data_key_t *key);
|
||||
|
||||
|
||||
|
|
|
@ -387,9 +387,11 @@ hb_buffer_t::clear_positions ()
|
|||
hb_memset (pos, 0, sizeof (pos[0]) * len);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
hb_buffer_t::sync ()
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
assert (have_output);
|
||||
|
||||
assert (idx <= len);
|
||||
|
@ -403,12 +405,39 @@ hb_buffer_t::sync ()
|
|||
info = out_info;
|
||||
}
|
||||
len = out_len;
|
||||
ret = true;
|
||||
|
||||
reset:
|
||||
have_output = false;
|
||||
out_len = 0;
|
||||
out_info = info;
|
||||
idx = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
hb_buffer_t::sync_so_far ()
|
||||
{
|
||||
bool had_output = have_output;
|
||||
unsigned out_i = out_len;
|
||||
unsigned i = idx;
|
||||
unsigned old_idx = idx;
|
||||
|
||||
if (sync ())
|
||||
idx = out_i;
|
||||
else
|
||||
idx = i;
|
||||
|
||||
if (had_output)
|
||||
{
|
||||
have_output = true;
|
||||
out_len = idx;
|
||||
}
|
||||
|
||||
assert (idx <= len);
|
||||
|
||||
return idx - old_idx;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -802,7 +831,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer,
|
|||
* Since: 0.9.2
|
||||
**/
|
||||
void *
|
||||
hb_buffer_get_user_data (hb_buffer_t *buffer,
|
||||
hb_buffer_get_user_data (const hb_buffer_t *buffer,
|
||||
hb_user_data_key_t *key)
|
||||
{
|
||||
return hb_object_get_user_data (buffer, key);
|
||||
|
@ -2090,8 +2119,16 @@ hb_buffer_set_message_func (hb_buffer_t *buffer,
|
|||
bool
|
||||
hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
|
||||
{
|
||||
assert (!have_output || (out_info == info && out_len == idx));
|
||||
|
||||
message_depth++;
|
||||
|
||||
char buf[100];
|
||||
vsnprintf (buf, sizeof (buf), fmt, ap);
|
||||
return (bool) this->message_func (this, font, buf, this->message_data);
|
||||
bool ret = (bool) this->message_func (this, font, buf, this->message_data);
|
||||
|
||||
message_depth--;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -142,6 +142,15 @@ typedef struct hb_glyph_info_t {
|
|||
* shaping, otherwise the buffer flag will not be
|
||||
* reliably produced.
|
||||
* Since: 4.0.0
|
||||
* @HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL: In scripts that use elongation (Arabic,
|
||||
Mongolian, Syriac, etc.), this flag signifies
|
||||
that it is safe to insert a U+0640 TATWEEL
|
||||
character *before* this cluster for elongation.
|
||||
This flag does not determine the
|
||||
script-specific elongation places, but only
|
||||
when it is safe to do the elongation without
|
||||
interrupting text shaping.
|
||||
Since: 5.1.0
|
||||
* @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
|
||||
*
|
||||
* Flags for #hb_glyph_info_t.
|
||||
|
@ -149,10 +158,11 @@ typedef struct hb_glyph_info_t {
|
|||
* Since: 1.5.0
|
||||
*/
|
||||
typedef enum { /*< flags >*/
|
||||
HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
|
||||
HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002,
|
||||
HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
|
||||
HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002,
|
||||
HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL = 0x00000004,
|
||||
|
||||
HB_GLYPH_FLAG_DEFINED = 0x00000003 /* OR of all defined flags */
|
||||
HB_GLYPH_FLAG_DEFINED = 0x00000007 /* OR of all defined flags */
|
||||
} hb_glyph_flags_t;
|
||||
|
||||
HB_EXTERN hb_glyph_flags_t
|
||||
|
@ -266,7 +276,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer,
|
|||
hb_bool_t replace);
|
||||
|
||||
HB_EXTERN void *
|
||||
hb_buffer_get_user_data (hb_buffer_t *buffer,
|
||||
hb_buffer_get_user_data (const hb_buffer_t *buffer,
|
||||
hb_user_data_key_t *key);
|
||||
|
||||
|
||||
|
@ -373,6 +383,10 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
|
|||
* flag indicating that the @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT
|
||||
* glyph-flag should be produced by the shaper. By default
|
||||
* it will not be produced since it incurs a cost. Since: 4.0.0
|
||||
* @HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL:
|
||||
* flag indicating that the @HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL
|
||||
* glyph-flag should be produced by the shaper. By default
|
||||
* it will not be produced. Since: 5.1.0
|
||||
* @HB_BUFFER_FLAG_DEFINED: All currently defined flags: Since: 4.4.0
|
||||
*
|
||||
* Flags for #hb_buffer_t.
|
||||
|
@ -388,8 +402,9 @@ typedef enum { /*< flags >*/
|
|||
HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u,
|
||||
HB_BUFFER_FLAG_VERIFY = 0x00000020u,
|
||||
HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u,
|
||||
HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL = 0x00000080u,
|
||||
|
||||
HB_BUFFER_FLAG_DEFINED = 0x0000007Fu
|
||||
HB_BUFFER_FLAG_DEFINED = 0x000000FFu
|
||||
} hb_buffer_flags_t;
|
||||
|
||||
HB_EXTERN void
|
||||
|
|
|
@ -288,7 +288,8 @@ struct hb_buffer_t
|
|||
|
||||
HB_INTERNAL void guess_segment_properties ();
|
||||
|
||||
HB_INTERNAL void sync ();
|
||||
HB_INTERNAL bool sync ();
|
||||
HB_INTERNAL int sync_so_far ();
|
||||
HB_INTERNAL void clear_output ();
|
||||
HB_INTERNAL void clear_positions ();
|
||||
|
||||
|
@ -461,6 +462,17 @@ struct hb_buffer_t
|
|||
start, end,
|
||||
true);
|
||||
}
|
||||
void safe_to_insert_tatweel (unsigned int start = 0, unsigned int end = -1)
|
||||
{
|
||||
if ((flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL) == 0)
|
||||
{
|
||||
unsafe_to_break (start, end);
|
||||
return;
|
||||
}
|
||||
_set_glyph_flags (HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL,
|
||||
start, end,
|
||||
true);
|
||||
}
|
||||
void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1)
|
||||
{
|
||||
if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
|
||||
|
@ -555,15 +567,11 @@ struct hb_buffer_t
|
|||
if (likely (!messaging ()))
|
||||
return true;
|
||||
|
||||
message_depth++;
|
||||
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
bool ret = message_impl (font, fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
message_depth--;
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ template <typename T,
|
|||
void *,
|
||||
hb_destroy_func_t,
|
||||
hb_bool_t),
|
||||
void * (*_get_user_data) (T *,
|
||||
void * (*_get_user_data) (const T *,
|
||||
hb_user_data_key_t *)>
|
||||
struct vtable_t
|
||||
{
|
||||
|
@ -164,6 +164,27 @@ HB_DEFINE_VTABLE (unicode_funcs);
|
|||
#undef HB_DEFINE_VTABLE
|
||||
|
||||
|
||||
#ifdef HB_SUBSET_H
|
||||
|
||||
#define HB_DEFINE_VTABLE(name) \
|
||||
template<> \
|
||||
struct vtable<hb_##name##_t> \
|
||||
: vtable_t<hb_##name##_t, \
|
||||
nullptr, \
|
||||
&hb_##name##_reference, \
|
||||
&hb_##name##_destroy, \
|
||||
&hb_##name##_set_user_data, \
|
||||
&hb_##name##_get_user_data> {}
|
||||
|
||||
|
||||
HB_DEFINE_VTABLE (subset_input);
|
||||
HB_DEFINE_VTABLE (subset_plan);
|
||||
|
||||
#undef HB_DEFINE_VTABLE
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace hb
|
||||
|
||||
/* Workaround for GCC < 7, see:
|
||||
|
|
|
@ -460,4 +460,9 @@ struct hb_no_trace_t {
|
|||
#endif
|
||||
|
||||
|
||||
#ifndef HB_BUFFER_MESSAGE_MORE
|
||||
#define HB_BUFFER_MESSAGE_MORE (HB_DEBUG+1)
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HB_DEBUG_HH */
|
||||
|
|
|
@ -342,7 +342,7 @@ hb_face_set_user_data (hb_face_t *face,
|
|||
* Since: 0.9.2
|
||||
**/
|
||||
void *
|
||||
hb_face_get_user_data (hb_face_t *face,
|
||||
hb_face_get_user_data (const hb_face_t *face,
|
||||
hb_user_data_key_t *key)
|
||||
{
|
||||
return hb_object_get_user_data (face, key);
|
||||
|
|
|
@ -96,7 +96,7 @@ hb_face_set_user_data (hb_face_t *face,
|
|||
hb_bool_t replace);
|
||||
|
||||
HB_EXTERN void *
|
||||
hb_face_get_user_data (hb_face_t *face,
|
||||
hb_face_get_user_data (const hb_face_t *face,
|
||||
hb_user_data_key_t *key);
|
||||
|
||||
HB_EXTERN void
|
||||
|
|
|
@ -781,8 +781,8 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
|
|||
* Since: 0.9.2
|
||||
**/
|
||||
void *
|
||||
hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
|
||||
hb_user_data_key_t *key)
|
||||
hb_font_funcs_get_user_data (const hb_font_funcs_t *ffuncs,
|
||||
hb_user_data_key_t *key)
|
||||
{
|
||||
return hb_object_get_user_data (ffuncs, key);
|
||||
}
|
||||
|
@ -1897,7 +1897,7 @@ hb_font_set_user_data (hb_font_t *font,
|
|||
* Since: 0.9.2
|
||||
**/
|
||||
void *
|
||||
hb_font_get_user_data (hb_font_t *font,
|
||||
hb_font_get_user_data (const hb_font_t *font,
|
||||
hb_user_data_key_t *key)
|
||||
{
|
||||
return hb_object_get_user_data (font, key);
|
||||
|
|
|
@ -86,8 +86,8 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
|
|||
|
||||
|
||||
HB_EXTERN void *
|
||||
hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
|
||||
hb_user_data_key_t *key);
|
||||
hb_font_funcs_get_user_data (const hb_font_funcs_t *ffuncs,
|
||||
hb_user_data_key_t *key);
|
||||
|
||||
|
||||
HB_EXTERN void
|
||||
|
@ -993,7 +993,7 @@ hb_font_set_user_data (hb_font_t *font,
|
|||
|
||||
|
||||
HB_EXTERN void *
|
||||
hb_font_get_user_data (hb_font_t *font,
|
||||
hb_font_get_user_data (const hb_font_t *font,
|
||||
hb_user_data_key_t *key);
|
||||
|
||||
HB_EXTERN void
|
||||
|
|
|
@ -1086,7 +1086,8 @@ hb_ft_font_changed (hb_font_t *font)
|
|||
}
|
||||
#endif
|
||||
|
||||
_hb_ft_hb_font_check_changed (font, ft_font);
|
||||
ft_font->advance_cache.clear ();
|
||||
ft_font->cached_serial = font->serial;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -145,7 +145,7 @@ hb_map_set_user_data (hb_map_t *map,
|
|||
* Since: 1.7.7
|
||||
**/
|
||||
void *
|
||||
hb_map_get_user_data (hb_map_t *map,
|
||||
hb_map_get_user_data (const hb_map_t *map,
|
||||
hb_user_data_key_t *key)
|
||||
{
|
||||
return hb_object_get_user_data (map, key);
|
||||
|
|
|
@ -74,7 +74,7 @@ hb_map_set_user_data (hb_map_t *map,
|
|||
hb_bool_t replace);
|
||||
|
||||
HB_EXTERN void *
|
||||
hb_map_get_user_data (hb_map_t *map,
|
||||
hb_map_get_user_data (const hb_map_t *map,
|
||||
hb_user_data_key_t *key);
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include "hb.hh"
|
||||
|
||||
|
||||
#line 32 "hb-number-parser.hh"
|
||||
#line 35 "hb-number-parser.hh"
|
||||
static const unsigned char _double_parser_trans_keys[] = {
|
||||
0u, 0u, 43u, 57u, 46u, 57u, 48u, 57u, 43u, 57u, 48u, 57u, 48u, 101u, 48u, 57u,
|
||||
46u, 101u, 0
|
||||
|
@ -135,12 +135,12 @@ strtod_rl (const char *p, const char **end_ptr /* IN/OUT */)
|
|||
|
||||
int cs;
|
||||
|
||||
#line 132 "hb-number-parser.hh"
|
||||
#line 139 "hb-number-parser.hh"
|
||||
{
|
||||
cs = double_parser_start;
|
||||
}
|
||||
|
||||
#line 135 "hb-number-parser.hh"
|
||||
#line 144 "hb-number-parser.hh"
|
||||
{
|
||||
int _slen;
|
||||
int _trans;
|
||||
|
@ -198,7 +198,7 @@ _resume:
|
|||
exp_overflow = true;
|
||||
}
|
||||
break;
|
||||
#line 187 "hb-number-parser.hh"
|
||||
#line 202 "hb-number-parser.hh"
|
||||
}
|
||||
|
||||
_again:
|
||||
|
|
|
@ -72,10 +72,6 @@ using OT::Layout::MediumTypes;
|
|||
#define HB_MAX_LANGSYS_FEATURE_COUNT 50000
|
||||
#endif
|
||||
|
||||
#ifndef HB_MAX_FEATURES
|
||||
#define HB_MAX_FEATURES 750
|
||||
#endif
|
||||
|
||||
#ifndef HB_MAX_FEATURE_INDICES
|
||||
#define HB_MAX_FEATURE_INDICES 1500
|
||||
#endif
|
||||
|
@ -1337,7 +1333,7 @@ struct Lookup
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
HBUINT16 lookupType; /* Different enumerations for GSUB and GPOS */
|
||||
HBUINT16 lookupFlag; /* Lookup qualifiers */
|
||||
Array16Of<Offset16>
|
||||
|
|
|
@ -1602,9 +1602,28 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
|
|||
if (unlikely (buffer->max_ops <= 0))
|
||||
break;
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
if (buffer->have_output)
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"recursing to lookup %u at %d",
|
||||
(unsigned) lookupRecord[i].lookupListIndex,
|
||||
buffer->idx);
|
||||
}
|
||||
|
||||
if (!c->recurse (lookupRecord[i].lookupListIndex))
|
||||
continue;
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
if (buffer->have_output)
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"recursed to lookup %u",
|
||||
(unsigned) lookupRecord[i].lookupListIndex);
|
||||
}
|
||||
|
||||
unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
|
||||
int delta = new_len - orig_len;
|
||||
|
||||
|
@ -4010,6 +4029,11 @@ struct GSUBGPOSVersion1_2
|
|||
(version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
|
||||
}
|
||||
|
||||
const typename Types::template OffsetTo<LookupList<Types>>* get_lookup_list_offset () const
|
||||
{
|
||||
return &lookupList;
|
||||
}
|
||||
|
||||
template <typename TLookup>
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
|
|
|
@ -1141,6 +1141,18 @@ hb_propagate_flags (hb_buffer_t *buffer)
|
|||
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS))
|
||||
return;
|
||||
|
||||
/* If we are producing SAFE_TO_INSERT_TATWEEL, then do two things:
|
||||
*
|
||||
* - If the places that the Arabic shaper marked as SAFE_TO_INSERT_TATWEEL,
|
||||
* are UNSAFE_TO_BREAK, then clear the SAFE_TO_INSERT_TATWEEL,
|
||||
* - Any place that is SAFE_TO_INSERT_TATWEEL, is also now UNSAFE_TO_BREAK.
|
||||
*
|
||||
* We couldn't make this interaction earlier. It has to be done here.
|
||||
*/
|
||||
bool flip_tatweel = buffer->flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL;
|
||||
|
||||
bool clear_concat = (buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0;
|
||||
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
|
||||
foreach_cluster (buffer, start, end)
|
||||
|
@ -1148,9 +1160,20 @@ hb_propagate_flags (hb_buffer_t *buffer)
|
|||
unsigned int mask = 0;
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
mask |= info[i].mask & HB_GLYPH_FLAG_DEFINED;
|
||||
if (mask)
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
info[i].mask |= mask;
|
||||
|
||||
if (flip_tatweel)
|
||||
{
|
||||
if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
|
||||
mask &= ~HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL;
|
||||
if (mask & HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL)
|
||||
mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT;
|
||||
}
|
||||
|
||||
if (clear_concat)
|
||||
mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_CONCAT;
|
||||
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
info[i].mask = mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -331,7 +331,7 @@ arabic_joining (hb_buffer_t *buffer)
|
|||
if (entry->prev_action != NONE && prev != UINT_MAX)
|
||||
{
|
||||
info[prev].arabic_shaping_action() = entry->prev_action;
|
||||
buffer->unsafe_to_break (prev, i + 1);
|
||||
buffer->safe_to_insert_tatweel (prev, i + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -365,7 +365,7 @@ arabic_joining (hb_buffer_t *buffer)
|
|||
if (entry->prev_action != NONE && prev != UINT_MAX)
|
||||
{
|
||||
info[prev].arabic_shaping_action() = entry->prev_action;
|
||||
buffer->unsafe_to_break (prev, buffer->len);
|
||||
buffer->safe_to_insert_tatweel (prev, buffer->len);
|
||||
}
|
||||
else if (2 <= state && state <= 5) /* States that have a possible prev_action. */
|
||||
{
|
||||
|
|
|
@ -90,263 +90,264 @@
|
|||
#pragma GCC diagnostic pop
|
||||
|
||||
static const uint8_t
|
||||
hb_use_u8[1842] =
|
||||
hb_use_u8[3083] =
|
||||
{
|
||||
0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 5,
|
||||
6, 7, 3, 8, 3, 3, 9, 3, 10, 3, 3, 11, 3, 12, 13, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
14, 0, 0, 1, 1, 2, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
1, 11, 12, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 17, 18, 19,
|
||||
1, 1, 20, 1, 1, 1, 1, 21, 1, 1, 1, 1, 1, 1, 1, 22,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 24, 25, 26, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
27, 28, 1, 1, 1, 1, 1, 29, 1, 1, 1, 1, 30, 31, 1, 32,
|
||||
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 1, 46, 47,
|
||||
48, 1, 49, 49, 49, 49, 50, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51, 52, 1, 1,
|
||||
1, 53, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 49, 54, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 55, 1,
|
||||
1, 1, 1, 56, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 57, 58, 1, 1, 1, 1, 1, 1, 59, 1, 1, 1, 1,
|
||||
1, 1, 60, 61, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
|
||||
60, 60, O, O, O, O, O, GB, O, O, B, B, B, B, B, B,
|
||||
O, O, GB, O, O, O, O, WJ, O, O, O, O,FMPst,FMPst, O, O,
|
||||
O, GB, O, O, O, CGJ, B, O, O, O, O, O, B, B, B, B,
|
||||
B,VMAbv,VMAbv,VMAbv,VMAbv,VMAbv, O, O, B, O, O,VMAbv, O, O, B,CMBlw,
|
||||
CMBlw,CMBlw,VMAbv,VMAbv,VMAbv,VMPst, B, B, VAbv, VPst,CMBlw, B, VPst, VPre, VPst, VBlw,
|
||||
VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VPst, VPst, VPst, VPst, H, VPre, VPst, O,VMAbv,
|
||||
VMBlw, O, O, VAbv, VBlw, VBlw, B, B, VBlw, VBlw, GB,VMAbv,VMPst,VMPst, O, B,
|
||||
B, B, B, O, O, B, B, O, B, B, B, O, B, O, VBlw, O,
|
||||
O, VPre, VPre, O, O, VPre, VPre, H, O, O, O, O, O, VPst, B, B,
|
||||
O, B, B, O,FMAbv, O, O,VMAbv,VMAbv,VMPst, B, B, B, O, O, O,
|
||||
O, B, O, B, B, O,CMBlw, O, VPst, VPre, VPst, VBlw, VBlw, O, O, O,
|
||||
O, VAbv, VAbv, O, O, VAbv, VAbv, H, O, O, O,VMBlw, O, O,VMAbv,CMAbv,
|
||||
GB, GB, O, MBlw, O, O, VBlw, VAbv, O, VAbv, VAbv, VAbv, O, VPst, VPst, H,
|
||||
O, O, O, B,VMAbv,VMAbv,VMAbv,CMAbv,CMAbv,CMAbv, O,VMAbv,VMPst,VMPst,CMBlw, B,
|
||||
VPst, VAbv, O, VAbv, VAbv, VAbv, O, B, O, O, O, O,VMAbv, O, O, O,
|
||||
VPst, VPst, VAbv, VPst, VPst, O, O, O, VPre, VPre, VPre, O, VPre, VPre,VMAbv,VMPst,
|
||||
VMPst,VMPst,VMAbv, B, B, B,CMBlw, B, VAbv, VAbv, VPst, O, VAbv, VAbv, VAbv, O,
|
||||
VAbv, VAbv, O, VAbv, VBlw, O, B,VMAbv,VMPst,VMPst, O, VPst, VPst, O, O, CS,
|
||||
CS, O,VMAbv,VMAbv,VMPst,VMPst, B, B, B, VAbv, VAbv, B, VPst, VPst, VPst, VPst,
|
||||
VPst, VBlw, VBlw, O, VPre, VPre, VPre, H, R, O, O, O, HVM, O, VPst, VPst,
|
||||
VAbv, VAbv, VBlw, O, VBlw, O, VPst, VPre, VPre, VPre, VPre, VPre, VPre, VPst, VBlw, VBlw,
|
||||
O, O, O, FBlw, O, FBlw, O,CMAbv, O, O, O, O, VPst, VPre, O,CMBlw,
|
||||
VBlw, VAbv, VAbv, VBlw, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw,VMAbv, O, VBlw, VAbv,
|
||||
VMAbv,VMAbv, VBlw, O,VMAbv,VMAbv, B, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB,
|
||||
SUB, SUB, SUB, O, O, O, O, O, FBlw, O, B, B, B, VPst, VPst, VAbv,
|
||||
VAbv, VBlw, VBlw, VPre, VAbv, VAbv, VAbv, VAbv,VMAbv,VMBlw,VMPst, IS, VAbv, MPst, MPre, MBlw,
|
||||
MBlw, B, B, B, O, GB, O, O, GB, O, B, B, VPst, VPst, VBlw, VBlw,
|
||||
B, B, B, B, MBlw, MBlw, MBlw, B, VPst,VMPst,VMPst, B, B, VPst, VPst,VMPst,
|
||||
VMPst,VMPst,VMPst,VMPst, B, B, B, VAbv, VAbv, VAbv, VAbv, B, B, B, B, B,
|
||||
MBlw, VPst, VPre, VAbv, VAbv,VMPst,VMPst,VMPst,VMPst,VMPst,VMPst,VMBlw, B,VMPst, B, B,
|
||||
VMPst,VMPst, VPst, VAbv, O, O, B, B, VAbv, VBlw, VBlw, VPst, O, O, VPst, O,
|
||||
O, O, B, O, VAbv, VBlw, CGJ, CGJ, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw,
|
||||
VPre, VPre, VPre, VPre, VPre, VPre, VPre, VPre,VMAbv,VMPst, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,
|
||||
FMAbv,VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, O, O, O, O, B, CGJ, CGJ, CGJ,
|
||||
WJ, CGJ, GB, GB, GB, GB, GB,CMAbv,CMAbv, B, B,CMBlw, B, O, GB, B,
|
||||
B, B, VAbv, VAbv, VBlw, VPst, VPst, VAbv, VAbv, VAbv, VAbv, SUB, SUB, SUB, FPst, FPst,
|
||||
VMBlw, FPst, FPst, FPst, FPst, FPst, FPst, FBlw,VMAbv,FMBlw,VMPst,VMPst, O, O, VAbv, VPre,
|
||||
VPst, VAbv, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, SUB, SUB, SUB, O, Sk, VPst,
|
||||
VAbv, VPst, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre, VPre, VPre, VPre, VAbv,VMAbv,VMAbv,
|
||||
VAbv,VMAbv,VMAbv, O, O,VMBlw,VMAbv,VMAbv,VMAbv, FAbv,VMPst, B, B, B,CMAbv, VPst,
|
||||
VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre, VPre, VPre, VAbv, VAbv, H, B,
|
||||
B, B, O, O, O,SMAbv,SMBlw,SMAbv,SMAbv,SMAbv,SMAbv,SMAbv,SMAbv,SMAbv,VMAbv, FAbv,
|
||||
VMPst, B, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, IS, SUB, SUB, B, B, B, B,
|
||||
CMAbv, VPst, VAbv, VAbv, VPst, VPst, VPst, VAbv, VPst, VAbv, FAbv, FAbv,CMBlw,CMBlw, SUB, SUB,
|
||||
VPst, VPre, VPre, VPre, VPst, VPst, VBlw, FAbv, FAbv, FAbv, FAbv, FAbv, FAbv, FAbv,VMPre,VMPre,
|
||||
FMAbv,CMBlw,VMAbv,VMAbv,VMAbv, O,VMBlw,VMBlw,VMBlw,VMBlw,VMBlw,VMBlw,VMAbv,VMAbv,VMAbv,VMPst,
|
||||
VMBlw,VMBlw,VMBlw, O, O, O,VMAbv, CS, CS,VMPst,VMAbv,VMAbv, GB, O, O, O,
|
||||
O,FMAbv, O, O, O, WJ, ZWNJ, CGJ, WJ, WJ, O, O, WJ, WJ, WJ, WJ,
|
||||
WJ, O, WJ, WJ, WJ, WJ,FMPst, O, O, O,VMAbv, O, O, O, O, O,
|
||||
O, H, B, B, VAbv, B, B, B, H, B, VPst, VBlw, VAbv, VPst, VBlw, O,
|
||||
O, O, MPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, H,VMAbv, O, O,VMAbv,VMAbv,
|
||||
B, B, O, O, B, VAbv, B, B, VAbv, VAbv, VAbv, VAbv, VAbv,VMBlw,VMBlw,VMBlw,
|
||||
O, O, B, B, B, VBlw, VBlw, VBlw, VAbv, VBlw, VBlw, VBlw, VBlw, FAbv, FAbv, FAbv,
|
||||
FPst, VPst,VMAbv,VMAbv, FAbv,VMPst, B, B, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, O,
|
||||
O, O, B, VAbv, O, B, B,VMAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre, VPre, VAbv,
|
||||
VBlw, MPst, MPre, MAbv, MBlw, O, B, B, B, FAbv, FAbv, FPst, O, O, GB, GB,
|
||||
GB, O, O, O, B,VMPst,VMAbv,VMPst, B, B, VAbv, B, VAbv, VAbv, VBlw, B,
|
||||
B, VAbv, B, B, VAbv,VMAbv, B,VMAbv, B, O, B, B, B, VPre, VBlw, VAbv,
|
||||
VPre, VPst, O,VMPst, IS, O, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O,VMPst, VBlw,
|
||||
O, O, CGJ, CGJ, CGJ, CGJ, WJ, O, O, O, B, VBlw, VBlw, VBlw, VPst,VMBlw,
|
||||
VMBlw,VMAbv,CMBlw,CMBlw,CMBlw, O, O, O, O, IS, B,CMBlw,CMBlw, O,VMAbv,VMAbv,
|
||||
VMAbv,CMAbv, B, B, O, VAbv, VAbv, O, O, O, B, B,VMBlw,VMBlw,VMBlw, B,
|
||||
B, B, B, B,CMBlw,CMBlw,CMBlw,CMBlw, O, O,VMPst,VMAbv,VMPst, CS, CS, B,
|
||||
B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O,
|
||||
N, N, N, N, N, N, N, N, B, B, VAbv, B, B, VAbv, VAbv, B,
|
||||
O, O, O, O, O, HN,VMAbv,VMAbv,VMPst, B, VPst, VPre, VPst, VBlw, VBlw, VAbv,
|
||||
VAbv, VPst, VPst, H,CMBlw, O, O, O, VBlw, O,VMAbv,VMAbv,VMAbv, B, VPre, VBlw,
|
||||
VAbv, VAbv, VBlw, VAbv, VAbv, IS,CMAbv, O, B, B, B, VPst, VPst, B, B, B,
|
||||
B,CMBlw, VPre, VPst, VBlw, VBlw, H, B, R, R, O,FMBlw,CMBlw, VAbv, VBlw, O,
|
||||
VPre,VMAbv,VMAbv, H,CMAbv,CMAbv, VAbv,CMBlw, VBlw, O, B, B, O,CMBlw,CMBlw, B,
|
||||
VPst, VPst, VPst, O, O, VPre, O, O,VMAbv,VMAbv, B, VPst, VPre, VPst, VPst, VPst,
|
||||
H,VMAbv,VMAbv,VMPst,CMBlw, B, O, O,FMAbv, B, CS, CS, O, O, VBlw, VPre,
|
||||
VAbv, VPre, VPre, VPst, VPre,VMAbv,VMAbv,VMAbv, H,CMBlw,VMAbv,VMAbv,VMPst, H,CMBlw, O,
|
||||
O, O, VPst,VMAbv,VMPst, H,VMPst, VAbv, VPre, VPst, VAbv, VAbv, H,CMBlw, O, MBlw,
|
||||
MPre, MAbv, VBlw, VBlw, VPre, VAbv, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv,VMAbv,VMPst, H,
|
||||
CMBlw, O, VPst, VPre, O, VPre, VPre, O, O,VMAbv,VMAbv, VPst, IS, R, MPst, R,
|
||||
MPst,CMBlw, O, O, VAbv, VAbv, VPst, VPst,VMPst,VMPst, H, B, O, O, VPre, O,
|
||||
O, O, B, VAbv, VBlw, VBlw, VAbv, VAbv, VBlw, B, B, B, B,FMBlw, VBlw,VMAbv,
|
||||
VMAbv,VMAbv,VMAbv,VMPst, R, MBlw, MBlw, MBlw, MBlw, GB, O, GB, O, IS, VAbv, VAbv,
|
||||
VAbv, VPst, R, R, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw,
|
||||
VMAbv,VMPst,CMAbv, IS, O, O, VBlw, VBlw, VBlw, O, O, O, SUB, SUB, VBlw, VPre,
|
||||
VBlw, VAbv, VPst,VMAbv,VMAbv, O, VAbv, VAbv, VBlw, O, O, O, VAbv, O, VAbv, VAbv,
|
||||
O, VAbv,VMAbv,VMAbv,CMBlw, VAbv, VBlw, IS, R, MBlw, VPst, VPst, VPst, O, VPst,VMAbv,
|
||||
VMPst, IS, B, B, GB, VAbv, VBlw, VPre, VPst, O, H, H, H, H, H, H,
|
||||
H, B, O, O, O,CMBlw, O, VBlw, VBlw, VBlw, O, O, O,VMBlw,VMBlw,VMBlw,
|
||||
VMBlw, O, O,CMBlw,CMBlw, O, B, B,VMAbv, O,CMAbv,CMAbv,CMAbv,CMAbv,CMAbv,CMAbv,
|
||||
CMAbv, B,
|
||||
16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 51, 57, 58, 179, 195, 61,
|
||||
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
|
||||
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
|
||||
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
|
||||
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
|
||||
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
|
||||
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
|
||||
14, 0, 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 4, 2, 2,
|
||||
5, 6, 2, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 2, 2, 17,
|
||||
18, 19, 20, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21,
|
||||
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 2, 33, 2, 2, 2,
|
||||
2, 34, 35, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 37, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 38, 39, 40, 41, 42, 43, 2, 44, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 46, 2,
|
||||
47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 48, 49, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 50, 51, 2, 52, 2, 2, 53, 2, 2, 54, 55,
|
||||
56, 57, 58, 59, 60, 61, 62, 63, 2, 64, 65, 2, 66, 67, 68, 69,
|
||||
2, 70, 2, 71, 72, 73, 74, 2, 2, 75, 76, 77, 78, 2, 79, 2,
|
||||
2, 80, 80, 80, 80, 80, 80, 80, 80, 81, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 82, 83, 2, 2, 2, 2, 2, 2, 2, 84,
|
||||
85, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 80, 80, 80, 86, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 87, 88, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 89, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 90, 2, 2, 91, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 92, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 93, 93, 94, 95, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
|
||||
93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
|
||||
93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||
0, 2, 2, 2, 2, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4,
|
||||
0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 8, 9, 9, 9, 9, 0, 0, 0, 7, 10,
|
||||
0, 2, 2, 2, 2, 11, 12, 0, 0, 9, 13, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 14, 15, 16, 17, 18, 19, 20, 14, 21, 22,
|
||||
23, 10, 24, 25, 18, 2, 2, 2, 2, 2, 18, 0, 2, 2, 2, 2,
|
||||
2, 0, 2, 2, 2, 2, 2, 2, 2, 26, 27, 28, 2, 2, 2, 7,
|
||||
28, 7, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 2, 2,
|
||||
2, 7, 7, 0, 2, 2, 0, 15, 16, 17, 18, 29, 30, 31, 30, 32,
|
||||
0, 0, 0, 0, 33, 0, 0, 2, 28, 2, 0, 0, 0, 0, 0, 7,
|
||||
34, 10, 13, 28, 2, 2, 7, 0, 28, 7, 2, 28, 7, 2, 0, 35,
|
||||
16, 17, 29, 0, 25, 36, 25, 37, 0, 38, 0, 0, 0, 28, 2, 7,
|
||||
7, 0, 0, 0, 2, 2, 2, 2, 2, 39, 40, 41, 0, 0, 0, 0,
|
||||
0, 10, 13, 28, 2, 2, 2, 2, 28, 2, 28, 2, 2, 2, 2, 2,
|
||||
2, 7, 2, 28, 2, 2, 0, 15, 16, 17, 18, 19, 25, 20, 33, 22,
|
||||
0, 0, 0, 0, 0, 28, 9, 39, 42, 10, 27, 28, 2, 2, 2, 7,
|
||||
28, 7, 2, 28, 2, 2, 0, 15, 43, 0, 0, 25, 20, 0, 0, 2,
|
||||
28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 44, 28, 2, 2, 7, 0,
|
||||
2, 7, 2, 2, 0, 28, 7, 7, 2, 0, 28, 7, 0, 2, 7, 0,
|
||||
2, 2, 2, 2, 2, 2, 0, 0, 21, 14, 45, 0, 46, 31, 46, 32,
|
||||
0, 0, 0, 0, 33, 0, 0, 0, 0, 13, 27, 47, 2, 2, 2, 7,
|
||||
2, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 15,
|
||||
20, 14, 21, 45, 20, 36, 20, 37, 0, 0, 0, 25, 29, 2, 7, 0,
|
||||
0, 8, 27, 28, 2, 2, 2, 7, 2, 2, 2, 28, 2, 2, 0, 15,
|
||||
43, 0, 0, 33, 45, 0, 0, 0, 7, 48, 49, 0, 0, 0, 0, 0,
|
||||
0, 9, 27, 2, 2, 2, 2, 7, 2, 2, 2, 2, 2, 2, 50, 51,
|
||||
21, 21, 17, 29, 46, 31, 46, 32, 52, 0, 0, 0, 33, 0, 0, 0,
|
||||
28, 10, 27, 28, 2, 2, 2, 2, 2, 2, 2, 2, 7, 0, 2, 2,
|
||||
2, 2, 28, 2, 2, 2, 2, 28, 0, 2, 2, 2, 7, 0, 53, 0,
|
||||
33, 21, 20, 29, 29, 16, 46, 46, 23, 0, 21, 0, 0, 0, 0, 0,
|
||||
0, 2, 0, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0,
|
||||
0, 2, 2, 54, 54, 55, 0, 0, 16, 2, 2, 2, 2, 28, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 7, 0, 56, 19, 57, 20, 20, 18, 18,
|
||||
44, 19, 9, 29, 9, 2, 2, 58, 59, 59, 59, 59, 59, 60, 59, 59,
|
||||
59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61,
|
||||
0, 0, 0, 0, 62, 0, 0, 0, 0, 2, 2, 2, 2, 2, 63, 43,
|
||||
57, 64, 20, 20, 65, 66, 67, 68, 69, 2, 2, 2, 2, 2, 1, 0,
|
||||
3, 2, 2, 2, 21, 18, 2, 2, 70, 69, 71, 72, 63, 71, 27, 27,
|
||||
2, 50, 20, 51, 2, 2, 2, 2, 2, 2, 73, 74, 75, 27, 27, 76,
|
||||
77, 2, 2, 2, 2, 2, 27, 43, 0, 2, 57, 78, 0, 0, 0, 0,
|
||||
28, 2, 57, 45, 0, 0, 0, 0, 0, 2, 57, 0, 0, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 2, 2, 7, 2, 7, 57, 0, 0, 0, 0, 0,
|
||||
0, 2, 2, 79, 43, 20, 57, 18, 46, 46, 46, 46, 13, 80, 81, 82,
|
||||
83, 84, 85, 0, 0, 0, 0, 86, 0, 7, 0, 0, 28, 0, 87, 79,
|
||||
88, 2, 2, 2, 2, 7, 0, 0, 0, 40, 40, 89, 90, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 11, 7, 0, 0, 91, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 7, 20, 78, 43, 20, 92, 59, 0,
|
||||
0, 93, 94, 93, 93, 95, 96, 0, 0, 2, 2, 2, 2, 2, 2, 2,
|
||||
0, 2, 2, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0,
|
||||
0, 2, 2, 2, 2, 27, 0, 0, 0, 2, 2, 2, 2, 2, 7, 0,
|
||||
0, 2, 2, 2, 50, 97, 43, 0, 0, 2, 2, 98, 99, 100, 101, 59,
|
||||
61, 102, 14, 43, 20, 57, 19, 78, 46, 46, 74, 9, 9, 9, 103, 44,
|
||||
38, 9, 104, 72, 2, 2, 2, 2, 2, 2, 2, 105, 20, 18, 18, 20,
|
||||
46, 46, 20, 106, 2, 2, 2, 7, 0, 0, 0, 0, 0, 0, 107, 108,
|
||||
109, 109, 109, 0, 0, 0, 0, 0, 0, 104, 72, 2, 2, 2, 2, 2,
|
||||
2, 58, 59, 57, 23, 20, 110, 59, 2, 2, 2, 2, 105, 20, 21, 43,
|
||||
43, 100, 12, 0, 0, 0, 0, 0, 0, 2, 2, 59, 16, 46, 21, 111,
|
||||
100, 100, 100, 112, 113, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 28,
|
||||
2, 9, 44, 114, 114, 114, 9, 114, 114, 13, 114, 114, 114, 24, 0, 38,
|
||||
0, 0, 0, 115, 116, 9, 3, 0, 0, 0, 0, 0, 0, 0, 117, 0,
|
||||
0, 0, 0, 0, 0, 0, 4, 118, 119, 40, 40, 3, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 119, 119, 120, 119, 119, 119, 119, 119, 119, 119,
|
||||
119, 0, 0, 121, 0, 0, 0, 0, 0, 0, 5, 121, 0, 0, 0, 0,
|
||||
0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,
|
||||
0, 2, 2, 2, 2, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0,
|
||||
122, 2, 51, 2, 106, 2, 8, 2, 2, 2, 63, 17, 14, 0, 0, 29,
|
||||
0, 2, 2, 0, 0, 0, 0, 0, 0, 27, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 123, 21, 21, 21, 21, 21, 21, 21, 124, 0, 0, 0, 0,
|
||||
0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0,
|
||||
50, 2, 2, 2, 20, 20, 125, 114, 0, 2, 2, 2, 126, 18, 57, 18,
|
||||
111, 100, 127, 0, 0, 0, 0, 0, 0, 9, 128, 2, 2, 2, 2, 2,
|
||||
2, 2, 129, 21, 20, 18, 46, 130, 131, 132, 0, 0, 0, 0, 0, 0,
|
||||
0, 2, 2, 50, 28, 2, 2, 2, 2, 2, 2, 2, 2, 8, 20, 57,
|
||||
97, 74, 133, 134, 135, 0, 0, 0, 0, 2, 136, 2, 2, 2, 2, 137,
|
||||
0, 28, 2, 40, 3, 0, 77, 13, 2, 51, 20, 138, 50, 51, 2, 2,
|
||||
103, 8, 7, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 139, 19,
|
||||
23, 0, 0, 140, 141, 0, 0, 0, 0, 2, 63, 43, 21, 78, 45, 142,
|
||||
0, 79, 79, 79, 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 119, 119, 119, 119, 120, 0, 0, 0, 2, 2, 2, 2, 2, 7, 2,
|
||||
2, 2, 7, 2, 28, 2, 2, 2, 2, 2, 28, 2, 2, 2, 28, 7,
|
||||
0, 126, 18, 25, 29, 0, 0, 143, 144, 2, 2, 28, 2, 28, 2, 2,
|
||||
2, 2, 2, 2, 0, 12, 35, 0, 145, 2, 2, 11, 35, 0, 28, 2,
|
||||
2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 2, 2,
|
||||
7, 2, 2, 9, 39, 0, 0, 0, 0, 2, 2, 2, 2, 2, 25, 36,
|
||||
0, 2, 2, 2, 114, 114, 114, 114, 114, 146, 2, 7, 0, 0, 0, 0,
|
||||
0, 2, 12, 12, 0, 0, 0, 0, 0, 7, 2, 2, 7, 2, 2, 2,
|
||||
2, 28, 2, 7, 0, 28, 2, 0, 0, 147, 148, 149, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 20, 20, 18, 18, 18, 20, 20, 132, 0, 0, 0,
|
||||
0, 0, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 2, 2, 2, 2,
|
||||
2, 51, 50, 51, 0, 0, 0, 0, 151, 9, 72, 2, 2, 2, 2, 2,
|
||||
2, 16, 17, 19, 14, 22, 35, 0, 0, 0, 29, 0, 0, 0, 0, 0,
|
||||
0, 9, 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 126, 18, 20, 152,
|
||||
20, 19, 153, 154, 2, 2, 2, 2, 2, 0, 0, 63, 155, 0, 0, 0,
|
||||
0, 2, 11, 0, 0, 0, 0, 0, 0, 2, 63, 23, 18, 18, 18, 20,
|
||||
20, 106, 156, 0, 0, 157, 158, 29, 159, 28, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 160, 42, 0, 0, 0,
|
||||
44, 2, 2, 2, 7, 7, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2,
|
||||
28, 2, 2, 2, 2, 2, 2, 2, 8, 16, 17, 19, 20, 161, 29, 0,
|
||||
0, 9, 9, 28, 2, 2, 2, 7, 28, 7, 2, 28, 2, 2, 56, 15,
|
||||
21, 14, 21, 45, 30, 31, 30, 32, 0, 0, 0, 0, 33, 0, 0, 0,
|
||||
2, 2, 21, 0, 9, 9, 9, 44, 0, 9, 9, 44, 0, 0, 0, 0,
|
||||
0, 2, 2, 63, 23, 18, 18, 18, 20, 21, 124, 13, 15, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 2, 0, 0, 162, 163, 0, 0, 0, 0, 0, 0,
|
||||
0, 16, 17, 18, 18, 64, 97, 23, 159, 9, 164, 7, 0, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 2, 2, 2, 63, 23, 18, 18, 0, 46, 46, 9,
|
||||
165, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 18,
|
||||
0, 21, 17, 18, 18, 19, 14, 80, 165, 36, 0, 0, 0, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 2, 8, 166, 23, 18, 20, 20, 164, 7, 0, 0,
|
||||
0, 2, 2, 2, 2, 2, 7, 41, 134, 21, 20, 18, 74, 19, 20, 0,
|
||||
0, 2, 2, 2, 7, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 16,
|
||||
17, 18, 19, 20, 103, 165, 35, 0, 0, 2, 2, 2, 7, 28, 0, 2,
|
||||
2, 2, 2, 28, 7, 2, 2, 2, 2, 21, 21, 16, 30, 31, 10, 167,
|
||||
168, 169, 170, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2,
|
||||
2, 63, 23, 18, 18, 0, 20, 21, 27, 106, 0, 31, 0, 0, 0, 0,
|
||||
0, 50, 18, 20, 20, 20, 138, 2, 2, 2, 171, 172, 9, 13, 173, 70,
|
||||
174, 0, 0, 1, 145, 0, 0, 0, 0, 50, 18, 20, 14, 17, 18, 2,
|
||||
2, 2, 2, 156, 156, 156, 175, 175, 175, 175, 175, 175, 13, 176, 0, 28,
|
||||
0, 20, 18, 18, 29, 20, 20, 9, 165, 0, 59, 59, 59, 59, 59, 59,
|
||||
59, 64, 19, 80, 44, 0, 0, 0, 0, 2, 2, 2, 7, 2, 28, 2,
|
||||
2, 50, 20, 20, 29, 0, 36, 20, 25, 9, 158, 177, 173, 0, 0, 0,
|
||||
0, 2, 2, 2, 28, 7, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21,
|
||||
45, 20, 33, 80, 66, 0, 0, 0, 0, 2, 178, 64, 45, 0, 0, 0,
|
||||
0, 179, 179, 179, 106, 7, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 2, 7, 0, 56, 180, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0,
|
||||
38, 114, 24, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,
|
||||
0, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 56,
|
||||
35, 0, 4, 119, 119, 119, 120, 0, 0, 9, 9, 9, 47, 2, 2, 2,
|
||||
0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
44, 2, 2, 2, 2, 2, 2, 9, 9, 2, 2, 42, 42, 42, 90, 0,
|
||||
0, O, O, O, GB, B, B, GB, O, O, WJ,FMPst,FMPst, O, CGJ, B,
|
||||
O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B,CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw,
|
||||
B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre,
|
||||
VPst,VMBlw, O, O, VAbv, GB,VMAbv,VMPst,VMPst, O, B, VBlw, O, O, VPre, VPre,
|
||||
O, VPre, H, O, VPst,FMAbv, O,CMBlw, O, VAbv, O, VAbv, H, O,VMBlw,VMAbv,
|
||||
CMAbv, GB, GB, O, MBlw,CMAbv,CMAbv, VPst, VAbv,VMAbv, O, VPst, O, VPre, VPre,VMAbv,
|
||||
B, O, CS, CS, O, B, VAbv, VAbv, B, R, O, HVM, O, O, FBlw, O,
|
||||
CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB, SUB, O, SUB, SUB, O, FBlw, O, B,
|
||||
VPst, VBlw, VPre,VMAbv,VMBlw,VMPst, IS, VAbv, MPst, MPre, MBlw, MBlw, B, MBlw, MBlw, VPst,
|
||||
VMPst,VMPst, B, MBlw, VPst, VPre, VAbv, VAbv,VMPst,VMPst,VMBlw, B,VMPst, VBlw, VPst, CGJ,
|
||||
CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B,
|
||||
CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB, B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst,
|
||||
FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv,
|
||||
VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O,SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw,
|
||||
FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, CS, CS,VMPst, O,FMAbv, ZWNJ, CGJ, WJ,
|
||||
WJ, WJ, O,FMPst, O, O, H, MPst, VPst, H,VMAbv, VAbv,VMBlw, B, VBlw, FPst,
|
||||
VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, MPst, MPre, MAbv, MBlw,
|
||||
O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O,VMPst, IS, O,VMPst, VBlw, VPst,
|
||||
VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, B, N, N, O,
|
||||
HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R, R, O,FMBlw,CMBlw, VAbv, VPre,
|
||||
VMAbv,VMAbv, H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv,
|
||||
VPst, IS, R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R, MBlw, MBlw, GB, FBlw,
|
||||
FBlw,CMAbv, IS, VBlw, IS, GB, VAbv, H, H, O, VBlw,
|
||||
};
|
||||
static const uint16_t
|
||||
hb_use_u16[2056] =
|
||||
hb_use_u16[768] =
|
||||
{
|
||||
0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 5, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 10, 11,
|
||||
0, 0, 0, 0, 9, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
13, 9, 9, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 17, 25,
|
||||
26, 20, 21, 27, 28, 29, 30, 31, 32, 33, 21, 34, 35, 0, 17, 36,
|
||||
37, 20, 21, 38, 23, 39, 17, 40, 41, 42, 43, 44, 45, 46, 30, 0,
|
||||
47, 48, 21, 49, 50, 51, 17, 0, 52, 48, 21, 53, 50, 54, 17, 55,
|
||||
56, 48, 9, 57, 58, 59, 17, 0, 60, 61, 9, 62, 63, 64, 30, 65,
|
||||
66, 67, 9, 68, 69, 9, 70, 71, 72, 73, 74, 75, 76, 0, 0, 0,
|
||||
9, 9, 77, 78, 79, 80, 81, 82, 83, 84, 0, 0, 0, 0, 0, 0,
|
||||
9, 85, 9, 86, 9, 87, 88, 89, 9, 9, 9, 90, 91, 92, 2, 0,
|
||||
93, 0, 9, 9, 9, 9, 9, 94, 95, 9, 96, 0, 0, 0, 0, 0,
|
||||
97, 98, 99,100, 30, 9,101,102, 9, 9,103, 9,104,105, 0, 0,
|
||||
9,106, 9, 9, 9,107,108,109, 2, 2, 0, 0, 0, 0, 0, 0,
|
||||
110, 9, 9,111,112, 2,113,114,115, 9,116, 9, 9, 9,117,118,
|
||||
9, 9,119,120,121, 0, 0, 0, 0, 0, 0, 0, 0,122,123,124,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,125,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0,
|
||||
0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 9, 10, 11,
|
||||
0, 0, 0, 0, 9, 12, 0, 0, 13, 9, 9, 14, 15, 16, 17, 18,
|
||||
19, 20, 21, 22, 23, 24, 17, 25, 26, 20, 21, 27, 28, 29, 30, 31,
|
||||
32, 33, 21, 34, 35, 0, 17, 36, 37, 20, 21, 38, 23, 39, 17, 40,
|
||||
41, 42, 43, 44, 45, 46, 30, 0, 47, 48, 21, 49, 50, 51, 17, 0,
|
||||
52, 48, 21, 53, 50, 54, 17, 55, 56, 48, 9, 57, 58, 59, 17, 0,
|
||||
60, 61, 9, 62, 63, 64, 30, 65, 66, 67, 9, 68, 69, 9, 70, 71,
|
||||
72, 73, 74, 75, 76, 0, 0, 0, 9, 9, 77, 78, 79, 80, 81, 82,
|
||||
83, 84, 0, 0, 0, 0, 0, 0, 9, 85, 9, 86, 9, 87, 88, 89,
|
||||
9, 9, 9, 90, 91, 92, 2, 0, 93, 0, 9, 9, 9, 9, 9, 94,
|
||||
95, 9, 96, 0, 0, 0, 0, 0, 97, 98, 99,100, 30, 9,101,102,
|
||||
9, 9,103, 9,104,105, 0, 0, 9,106, 9, 9, 9,107,108,109,
|
||||
2, 2, 0, 0, 0, 0, 0, 0,110, 9, 9,111,112, 2,113,114,
|
||||
115, 9,116, 9, 9, 9,117,118, 9, 9,119,120,121, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,122,123,124, 0, 0, 0, 0, 0, 0, 0,125,
|
||||
126,127,128, 0, 0, 0,129,130,131, 0, 0, 0, 0, 0, 0,132,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,133, 0, 0, 0,
|
||||
0, 0, 0, 9, 9, 9,134,135, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0,133, 0, 0, 0, 0, 0, 0, 9, 9, 9,134,135,
|
||||
136, 9,137, 0, 9, 9, 9,138,139, 9, 9,140,141, 2,142,143,
|
||||
9, 9,144, 9,145,146, 0, 0,147, 9, 9,148,149, 2,150, 98,
|
||||
9, 9,151,152,153, 2, 9,154, 9, 9, 9,155,156, 0,157,158,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9,159, 2,
|
||||
160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,161,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,162,
|
||||
0, 0, 0, 0, 9, 9,159, 2,160, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,161, 0, 0, 0, 0, 0, 0, 0,162,
|
||||
0, 0, 0, 0, 0, 0, 0,163,163,164, 33,165, 0, 0, 0, 0,
|
||||
166,167, 9,168, 94, 0, 0, 0, 0, 0, 0, 0, 69, 9,169, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 9,170,171, 0, 0, 0, 0, 0,
|
||||
9, 9,172, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 9, 9,173,170, 0, 0, 0, 0,
|
||||
0, 0, 0, 9,174,175, 0, 9,176, 0, 0,177,178, 0, 0, 0,
|
||||
179, 9, 9,180,181,182,183,184,185, 9, 9,186,187, 0, 0, 0,
|
||||
188, 9,189,190,191, 9, 9,192,185, 9, 9,193,194,105,195,102,
|
||||
9, 33,196,197, 0, 0, 0, 0,198,199, 94, 9, 9,200,201, 2,
|
||||
202, 20, 21,203,204,205,206,207, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9,170,171, 0, 0, 0, 0, 0, 9, 9,172, 2, 0, 0, 0, 0,
|
||||
9, 9,173,170, 0, 0, 0, 0, 0, 0, 0, 9,174,175, 0, 9,
|
||||
176, 0, 0,177,178, 0, 0, 0,179, 9, 9,180,181,182,183,184,
|
||||
185, 9, 9,186,187, 0, 0, 0,188, 9,189,190,191, 9, 9,192,
|
||||
185, 9, 9,193,194,105,195,102, 9, 33,196,197, 0, 0, 0, 0,
|
||||
198,199, 94, 9, 9,200,201, 2,202, 20, 21,203,204,205,206,207,
|
||||
9, 9, 9,208,209,210,211, 0,195, 9, 9,212,213, 2, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 9, 9,214,215,216,217, 0, 0,
|
||||
9, 9, 9,218,219, 2, 0, 0, 9, 9,220,221, 2, 0, 0, 0,
|
||||
9,222,223,103,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9, 9,225,226, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
227,228, 9,229,230, 2, 0, 0, 0, 0,231, 9, 9,232,233, 0,
|
||||
234, 9, 9,235,236,237, 9, 9,238,239, 0, 0, 0, 0, 0, 0,
|
||||
21, 9,214,240, 7, 9, 70, 18, 9,241, 73,242, 0, 0, 0, 0,
|
||||
243, 9, 9,244,245, 2,246, 9,247,248, 2, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,249,
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 98,250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
|
||||
9, 9, 9,251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9, 9,214,215,216,217, 0, 0, 9, 9, 9,218,219, 2, 0, 0,
|
||||
9, 9,220,221, 2, 0, 0, 0, 9,222,223,103,224, 0, 0, 0,
|
||||
9, 9,225,226, 0, 0, 0, 0,227,228, 9,229,230, 2, 0, 0,
|
||||
0, 0,231, 9, 9,232,233, 0,234, 9, 9,235,236,237, 9, 9,
|
||||
238,239, 0, 0, 0, 0, 0, 0, 21, 9,214,240, 7, 9, 70, 18,
|
||||
9,241, 73,242, 0, 0, 0, 0,243, 9, 9,244,245, 2,246, 9,
|
||||
247,248, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,249,
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 98,250, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 2, 0, 0, 0, 9, 9, 9,251, 0, 0, 0, 0,
|
||||
9, 9, 9, 9,252,253,254,254,255,256, 0, 0, 0, 0,257, 0,
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,258, 0, 0,
|
||||
9, 9, 9, 9, 9, 9,105, 70, 94,259, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,260, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
9, 9, 70,261,262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 9,263, 0, 9, 9,264, 2,
|
||||
9, 9, 9, 9,265, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
|
||||
9, 9, 9, 9, 9,258, 0, 0, 9, 9, 9, 9, 9, 9,105, 70,
|
||||
94,259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,260,
|
||||
9, 9, 70,261,262, 0, 0, 0, 0, 9,263, 0, 9, 9,264, 2,
|
||||
9, 9, 9, 9,265, 2, 0, 0,129,129,129,129,129,129,129,129,
|
||||
160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,129,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 3, 0, 4, 0, 0, 5,
|
||||
6, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0,
|
||||
0, 0, 10, 2, 2, 2, 2, 2, 2, 2, 11, 12, 12, 0, 13, 14,
|
||||
2, 2, 15, 0, 16, 2, 2, 2, 2, 2, 17, 18, 19, 20, 21, 22,
|
||||
23, 24, 2, 2, 25, 10, 2, 2, 10, 2, 2, 2, 26, 27, 2, 28,
|
||||
28, 2, 2, 2, 2, 2, 29, 2, 30, 10, 3, 18, 19, 31, 32, 33,
|
||||
0, 34, 0, 35, 3, 0, 0, 36, 37, 27, 38, 39, 29, 40, 3, 41,
|
||||
42, 43, 44, 45, 46, 0, 27, 30, 0, 10, 2, 2, 47, 48, 0, 0,
|
||||
37, 27, 2, 35, 35, 2, 2, 2, 29, 27, 3, 18, 19, 49, 50, 51,
|
||||
0, 0, 52, 53, 54, 27, 2, 28, 29, 27, 3, 55, 0, 56, 0, 35,
|
||||
57, 0, 0, 0, 58, 27, 38, 10, 29, 3, 40, 29, 39, 9, 38, 10,
|
||||
2, 2, 3, 59, 60, 61, 62, 33, 0, 34, 0, 0, 63, 64, 2, 29,
|
||||
29, 2, 2, 2, 2, 2, 3, 65, 21, 66, 67, 45, 0, 68, 38, 0,
|
||||
69, 27, 2, 29, 2, 27, 3, 55, 0, 70, 0, 13, 71, 0, 0, 0,
|
||||
72, 2, 2, 29, 2, 2, 73, 74, 75, 76, 62, 77, 0, 34, 0, 39,
|
||||
54, 27, 2, 2, 2, 38, 10, 2, 35, 2, 2, 57, 2, 38, 78, 34,
|
||||
79, 80, 81, 82, 59, 0, 0, 0, 3, 38, 0, 0, 0, 0, 83, 0,
|
||||
2, 84, 85, 86, 2, 2, 27, 2, 2, 2, 2, 9, 87, 88, 89, 90,
|
||||
91, 92, 2, 93, 94, 94, 95, 94, 94, 94, 94, 94, 94, 94, 94, 96,
|
||||
0, 97, 0, 0, 2, 2, 98, 99,100,101,102,103, 2, 2,104,105,
|
||||
2,106,107,108,109,110,111,112,113,114, 2, 2,115,116,117,118,
|
||||
2, 2,119,120,121,122, 0, 39,121,123, 0, 0,121, 0, 0, 0,
|
||||
2, 2, 2, 29,124, 0, 0, 0, 2,125,126,127,128,129,130,131,
|
||||
132, 0, 0,133, 9, 39,134,135, 2, 2, 9, 0,136,137, 2, 2,
|
||||
2, 2,138, 0,139, 2, 2, 2, 2, 2, 2, 38,140,141,142, 0,
|
||||
143,144,145, 0, 2, 2, 2, 3, 2, 9, 0, 0, 2, 2, 2, 0,
|
||||
2, 2,146, 0, 2, 2, 38, 0, 2, 73,147, 0, 2,148,149,150,
|
||||
151,141,152,153,154, 12,155,156,157,158, 2, 2, 2,159,160,161,
|
||||
162,163, 2, 9, 0, 0,164,165,166, 0, 0, 0,167, 2, 2, 2,
|
||||
93,168,169,170, 2,171,172,173,174, 0, 0, 0, 2,175,176,177,
|
||||
178,179, 0, 0, 2, 2, 3, 27,180,181,182,181,183,181,184, 46,
|
||||
0,185,186, 0, 0, 0,187, 0, 0, 0,188,189,136, 4, 0, 0,
|
||||
0, 0,190,191,192,192,192,192, 0,193, 0, 0, 6,193, 0, 0,
|
||||
194, 0, 0, 0, 0, 0, 0, 9, 2, 2, 0, 39, 0, 0, 0,195,
|
||||
196,197, 11, 2, 98,198, 0,199, 2, 0, 0, 0,112, 2, 2, 2,
|
||||
2,200,201,201,201,202, 0, 0, 12, 12, 12, 12,203, 0, 0,204,
|
||||
2,205,206,207, 2,208,209,210,211, 0, 0, 0,212, 2, 2, 2,
|
||||
213, 79,127,214,215, 0, 0, 0, 2,216, 2, 2, 2, 2,217,218,
|
||||
219,220, 0, 0,221, 2, 2,222, 27,223,224,225,226,227,114,228,
|
||||
229, 0, 0, 0, 2, 2,230,231, 0,232, 0, 0, 98,233,234,235,
|
||||
236,236,236,236, 0, 0, 0,188,192,192,237, 0, 2, 2, 38, 2,
|
||||
38, 35, 2, 2, 35, 2, 35, 9,238, 68, 0,239, 2, 27, 27, 2,
|
||||
2, 3,240,241, 2,242, 39, 2, 3, 0, 0, 0, 0, 0, 27, 38,
|
||||
2,243, 0, 0, 2, 2,244,245, 2,246,181,181,247, 9, 0, 0,
|
||||
248,249, 0, 0, 29, 38, 2, 2, 27, 9, 27, 0,250,251, 2, 2,
|
||||
2, 2,252,160,253,254, 0, 0,255,256,256,256,256,257, 2, 2,
|
||||
258,259, 0,260,261, 2, 2, 2,262,263,264, 0,265, 0, 0, 0,
|
||||
266, 2, 2, 2, 2,208,253,267,268,269, 2, 2, 0,270, 0, 0,
|
||||
271, 0, 0, 0, 98,272,160,252,273, 0,274,275, 27, 2, 2, 2,
|
||||
2, 2, 2, 75,252,276, 0, 58, 2, 38, 29, 35, 2, 2, 2, 35,
|
||||
2, 2, 2, 11,262, 20,277, 0, 12, 27, 2, 28, 29, 27,278,279,
|
||||
21,280, 32, 33, 0, 34, 0, 10,106,281, 12,194, 12,194, 0, 0,
|
||||
2,282,160,253,283,284, 0, 0, 2, 2, 3,285,286, 0, 0, 0,
|
||||
262,160,287,288,289, 9, 0, 0, 2, 2, 2, 98,272, 83,128,290,
|
||||
291, 0, 0, 0, 0, 0, 2, 83, 75,160,263,292,245, 0, 0, 0,
|
||||
2, 2, 11,293,253,294, 9, 0, 2, 2, 38,295, 79,296, 20, 0,
|
||||
2, 38, 0, 0, 2, 2, 2,262,297,298,299, 0, 2, 38, 57, 2,
|
||||
2, 40, 2, 2,201,300,301,302,303, 0, 0, 0, 2, 2, 10, 2,
|
||||
282,160,304,305,306,307, 0, 0,308,252,309, 2,310,311,312,313,
|
||||
0,314, 0, 0,308,315, 19, 2, 2,316,317,318,318,319,320, 57,
|
||||
89,321,252,290,322, 94, 94, 94,323,324, 0, 0, 2, 38, 35, 2,
|
||||
113,325,326,327,328,329, 0, 0, 2, 35, 29, 2, 2, 2,106,330,
|
||||
50,331, 0, 0,332,333, 0, 0,334,335, 9, 0, 12,180, 0, 0,
|
||||
2, 2, 38,336,337,160,160,160,160,160,160,160,160,160, 0,338,
|
||||
339, 0, 0, 0, 0, 9, 0, 0, 2, 3, 0, 0, 2, 2, 3,340,
|
||||
188,192,191, 0, 12,266, 2, 3, 2, 2, 3, 10, 2, 2, 2,341,
|
||||
2, 2, 2, 12, 2,342,343, 0,
|
||||
};
|
||||
|
||||
static inline unsigned
|
||||
hb_use_b4 (const uint8_t* a, unsigned i)
|
||||
{
|
||||
return (a[i>>1]>>((i&1u)<<2))&15u;
|
||||
}
|
||||
static inline uint_fast8_t
|
||||
hb_use_get_category (unsigned u)
|
||||
{
|
||||
return u<921600u?hb_use_u8[466+(((hb_use_u16[992+(((hb_use_u16[((hb_use_u8[226+(((hb_use_u8[u>>2>>2>>4>>4])<<4)+((u>>2>>2>>4)&15u))])<<4)+((u>>2>>2)&15u)])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:O;
|
||||
return u<921600u?hb_use_u8[2721+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
|
||||
}
|
||||
|
||||
#undef B
|
||||
|
@ -392,5 +393,26 @@ hb_use_get_category (unsigned u)
|
|||
#undef VMPre
|
||||
|
||||
|
||||
#ifdef HB_USE_TABLE_MAIN
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
for (unsigned u = 0; u < 0x10FFFFu; u++)
|
||||
printf ("U+%04X %d\n", u, hb_use_get_category (u));
|
||||
return 0;
|
||||
}
|
||||
|
||||
hb_codepoint_t u;
|
||||
sscanf (argv[1], "%x", &u);
|
||||
|
||||
printf ("%d\n", hb_use_get_category (u));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HB_OT_SHAPER_USE_TABLE_HH */
|
||||
/* == End of generated table == */
|
||||
|
|
|
@ -29,10 +29,9 @@
|
|||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-map.hh"
|
||||
#include "hb-priority-queue.hh"
|
||||
#include "hb-serialize.hh"
|
||||
#include "hb-vector.hh"
|
||||
#include "graph/graph.hh"
|
||||
#include "graph/gsubgpos-graph.hh"
|
||||
#include "graph/serialize.hh"
|
||||
|
||||
using graph::graph_t;
|
||||
|
@ -42,6 +41,143 @@ using graph::graph_t;
|
|||
* docs/repacker.md
|
||||
*/
|
||||
|
||||
struct lookup_size_t
|
||||
{
|
||||
unsigned lookup_index;
|
||||
size_t size;
|
||||
unsigned num_subtables;
|
||||
|
||||
static int cmp (const void* a, const void* b)
|
||||
{
|
||||
return cmp ((const lookup_size_t*) a,
|
||||
(const lookup_size_t*) b);
|
||||
}
|
||||
|
||||
static int cmp (const lookup_size_t* a, const lookup_size_t* b)
|
||||
{
|
||||
double subtables_per_byte_a = (double) a->num_subtables / (double) a->size;
|
||||
double subtables_per_byte_b = (double) b->num_subtables / (double) b->size;
|
||||
if (subtables_per_byte_a == subtables_per_byte_b) {
|
||||
return b->lookup_index - a->lookup_index;
|
||||
}
|
||||
|
||||
double cmp = subtables_per_byte_b - subtables_per_byte_a;
|
||||
if (cmp < 0) return -1;
|
||||
if (cmp > 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
static inline
|
||||
bool _presplit_subtables_if_needed (graph::gsubgpos_graph_context_t& ext_context)
|
||||
{
|
||||
// For each lookup this will check the size of subtables and split them as needed
|
||||
// so that no subtable is at risk of overflowing. (where we support splitting for
|
||||
// that subtable type).
|
||||
//
|
||||
// TODO(grieger): de-dup newly added nodes as necessary. Probably just want a full de-dup
|
||||
// pass after this processing is done. Not super necessary as splits are
|
||||
// only done where overflow is likely, so de-dup probably will get undone
|
||||
// later anyways.
|
||||
for (unsigned lookup_index : ext_context.lookups.keys ())
|
||||
{
|
||||
graph::Lookup* lookup = ext_context.lookups.get(lookup_index);
|
||||
if (!lookup->split_subtables_if_needed (ext_context, lookup_index))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Analyze the lookups in a GSUB/GPOS table and decide if any should be promoted
|
||||
* to extension lookups.
|
||||
*/
|
||||
static inline
|
||||
bool _promote_extensions_if_needed (graph::gsubgpos_graph_context_t& ext_context)
|
||||
{
|
||||
// Simple Algorithm (v1, current):
|
||||
// 1. Calculate how many bytes each non-extension lookup consumes.
|
||||
// 2. Select up to 64k of those to remain as non-extension (greedy, highest subtables per byte first)
|
||||
// 3. Promote the rest.
|
||||
//
|
||||
// Advanced Algorithm (v2, not implemented):
|
||||
// 1. Perform connected component analysis using lookups as roots.
|
||||
// 2. Compute size of each connected component.
|
||||
// 3. Select up to 64k worth of connected components to remain as non-extensions.
|
||||
// (greedy, highest subtables per byte first)
|
||||
// 4. Promote the rest.
|
||||
|
||||
// TODO(garretrieger): support extension demotion, then consider all lookups. Requires advanced algo.
|
||||
// TODO(garretrieger): also support extension promotion during iterative resolution phase, then
|
||||
// we can use a less conservative threshold here.
|
||||
// TODO(grieger): skip this for the 24 bit case.
|
||||
if (!ext_context.lookups) return true;
|
||||
|
||||
hb_vector_t<lookup_size_t> lookup_sizes;
|
||||
lookup_sizes.alloc (ext_context.lookups.get_population ());
|
||||
|
||||
for (unsigned lookup_index : ext_context.lookups.keys ())
|
||||
{
|
||||
const graph::Lookup* lookup = ext_context.lookups.get(lookup_index);
|
||||
hb_set_t visited;
|
||||
lookup_sizes.push (lookup_size_t {
|
||||
lookup_index,
|
||||
ext_context.graph.find_subgraph_size (lookup_index, visited),
|
||||
lookup->number_of_subtables (),
|
||||
});
|
||||
}
|
||||
|
||||
lookup_sizes.qsort ();
|
||||
|
||||
size_t lookup_list_size = ext_context.graph.vertices_[ext_context.lookup_list_index].table_size ();
|
||||
size_t l2_l3_size = lookup_list_size; // Lookup List + Lookups
|
||||
size_t l3_l4_size = 0; // Lookups + SubTables
|
||||
size_t l4_plus_size = 0; // SubTables + their descendants
|
||||
|
||||
// Start by assuming all lookups are using extension subtables, this size will be removed later
|
||||
// if it's decided to not make a lookup extension.
|
||||
for (auto p : lookup_sizes)
|
||||
{
|
||||
unsigned subtables_size = p.num_subtables * 8;
|
||||
l3_l4_size += subtables_size;
|
||||
l4_plus_size += subtables_size;
|
||||
}
|
||||
|
||||
bool layers_full = false;
|
||||
for (auto p : lookup_sizes)
|
||||
{
|
||||
const graph::Lookup* lookup = ext_context.lookups.get(p.lookup_index);
|
||||
if (lookup->is_extension (ext_context.table_tag))
|
||||
// already an extension so size is counted by the loop above.
|
||||
continue;
|
||||
|
||||
if (!layers_full)
|
||||
{
|
||||
size_t lookup_size = ext_context.graph.vertices_[p.lookup_index].table_size ();
|
||||
hb_set_t visited;
|
||||
size_t subtables_size = ext_context.graph.find_subgraph_size (p.lookup_index, visited, 1) - lookup_size;
|
||||
size_t remaining_size = p.size - subtables_size - lookup_size;
|
||||
|
||||
l2_l3_size += lookup_size;
|
||||
l3_l4_size += lookup_size + subtables_size;
|
||||
l3_l4_size -= p.num_subtables * 8;
|
||||
l4_plus_size += subtables_size + remaining_size;
|
||||
|
||||
if (l2_l3_size < (1 << 16)
|
||||
&& l3_l4_size < (1 << 16)
|
||||
&& l4_plus_size < (1 << 16)) continue; // this lookup fits within all layers groups
|
||||
|
||||
layers_full = true;
|
||||
}
|
||||
|
||||
if (!ext_context.lookups.get(p.lookup_index)->make_extension (ext_context, p.lookup_index))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline
|
||||
bool _try_isolating_subgraphs (const hb_vector_t<graph::overflow_record_t>& overflows,
|
||||
graph_t& sorted_graph)
|
||||
|
@ -157,7 +293,8 @@ template<typename T>
|
|||
inline hb_blob_t*
|
||||
hb_resolve_overflows (const T& packed,
|
||||
hb_tag_t table_tag,
|
||||
unsigned max_rounds = 20) {
|
||||
unsigned max_rounds = 20,
|
||||
bool recalculate_extensions = false) {
|
||||
graph_t sorted_graph (packed);
|
||||
sorted_graph.sort_shortest_distance ();
|
||||
|
||||
|
@ -167,13 +304,31 @@ hb_resolve_overflows (const T& packed,
|
|||
return graph::serialize (sorted_graph);
|
||||
}
|
||||
|
||||
graph::gsubgpos_graph_context_t ext_context (table_tag, sorted_graph);
|
||||
if ((table_tag == HB_OT_TAG_GPOS
|
||||
|| table_tag == HB_OT_TAG_GSUB)
|
||||
&& will_overflow)
|
||||
{
|
||||
if (recalculate_extensions)
|
||||
{
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Splitting subtables if needed.");
|
||||
if (!_presplit_subtables_if_needed (ext_context)) {
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Subtable splitting failed.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Promoting lookups to extensions if needed.");
|
||||
if (!_promote_extensions_if_needed (ext_context)) {
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Extensions promotion failed.");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Assigning spaces to 32 bit subgraphs.");
|
||||
if (sorted_graph.assign_spaces ())
|
||||
sorted_graph.sort_shortest_distance ();
|
||||
else
|
||||
sorted_graph.sort_shortest_distance_if_needed ();
|
||||
}
|
||||
|
||||
unsigned round = 0;
|
||||
|
|
|
@ -145,7 +145,7 @@ hb_set_set_user_data (hb_set_t *set,
|
|||
* Since: 0.9.2
|
||||
**/
|
||||
void *
|
||||
hb_set_get_user_data (hb_set_t *set,
|
||||
hb_set_get_user_data (const hb_set_t *set,
|
||||
hb_user_data_key_t *key)
|
||||
{
|
||||
return hb_object_get_user_data (set, key);
|
||||
|
|
|
@ -77,7 +77,7 @@ hb_set_set_user_data (hb_set_t *set,
|
|||
hb_bool_t replace);
|
||||
|
||||
HB_EXTERN void *
|
||||
hb_set_get_user_data (hb_set_t *set,
|
||||
hb_set_get_user_data (const hb_set_t *set,
|
||||
hb_user_data_key_t *key);
|
||||
|
||||
|
||||
|
|
|
@ -358,8 +358,8 @@ hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan,
|
|||
* Since: 0.9.7
|
||||
**/
|
||||
void *
|
||||
hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan,
|
||||
hb_user_data_key_t *key)
|
||||
hb_shape_plan_get_user_data (const hb_shape_plan_t *shape_plan,
|
||||
hb_user_data_key_t *key)
|
||||
{
|
||||
return hb_object_get_user_data (shape_plan, key);
|
||||
}
|
||||
|
|
|
@ -102,8 +102,8 @@ hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan,
|
|||
hb_bool_t replace);
|
||||
|
||||
HB_EXTERN void *
|
||||
hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan,
|
||||
hb_user_data_key_t *key);
|
||||
hb_shape_plan_get_user_data (const hb_shape_plan_t *shape_plan,
|
||||
hb_user_data_key_t *key);
|
||||
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
|
|
|
@ -25,18 +25,24 @@
|
|||
#include "hb-repacker.hh"
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
|
||||
/**
|
||||
* hb_subset_repack_or_fail:
|
||||
* @table_tag: tag of the table being packed, needed to allow table specific optimizations.
|
||||
* @hb_objects: raw array of struct hb_object_t, which provides
|
||||
* object graph info
|
||||
* @num_hb_objs: number of hb_object_t in the hb_objects array.
|
||||
*
|
||||
* Given the input object graph info, repack a table to eliminate
|
||||
* offset overflows. A nullptr is returned if the repacking attempt fails.
|
||||
* Table specific optimizations (eg. extension promotion in GSUB/GPOS) may be performed.
|
||||
* Passing HB_TAG_NONE will disable table specific optimizations.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
hb_blob_t* hb_subset_repack_or_fail (hb_object_t* hb_objects, unsigned num_hb_objs)
|
||||
hb_blob_t* hb_subset_repack_or_fail (hb_tag_t table_tag,
|
||||
hb_object_t* hb_objects,
|
||||
unsigned num_hb_objs)
|
||||
{
|
||||
hb_vector_t<const hb_object_t *> packed;
|
||||
packed.alloc (num_hb_objs + 1);
|
||||
|
@ -44,6 +50,9 @@ hb_blob_t* hb_subset_repack_or_fail (hb_object_t* hb_objects, unsigned num_hb_ob
|
|||
for (unsigned i = 0 ; i < num_hb_objs ; i++)
|
||||
packed.push (&(hb_objects[i]));
|
||||
|
||||
return hb_resolve_overflows (packed, HB_OT_TAG_GSUB);
|
||||
return hb_resolve_overflows (packed,
|
||||
table_tag,
|
||||
20,
|
||||
true);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -70,7 +70,8 @@ struct hb_object_t
|
|||
typedef struct hb_object_t hb_object_t;
|
||||
|
||||
HB_EXTERN hb_blob_t*
|
||||
hb_subset_repack_or_fail (hb_object_t* hb_objects,
|
||||
hb_subset_repack_or_fail (hb_tag_t table_tag,
|
||||
hb_object_t* hb_objects,
|
||||
unsigned num_hb_objs);
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,42 +24,37 @@
|
|||
#include "hb-unicode.hh"
|
||||
|
||||
static const uint8_t
|
||||
_hb_emoji_u8[544] =
|
||||
_hb_emoji_u8[464] =
|
||||
{
|
||||
16, 17, 17, 17, 50, 20, 21, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,118,152,
|
||||
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
2, 3, 0, 0, 4, 0, 5, 0, 0, 0, 0, 0, 6, 0, 7, 8,
|
||||
0, 0, 0, 9, 0, 0, 10, 11, 12, 13, 14, 13, 15, 16, 17, 0,
|
||||
0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 19, 20, 0, 0,
|
||||
21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0,
|
||||
13, 13, 13, 13, 23, 24, 25, 26, 27, 28, 13, 13, 13, 13, 13, 29,
|
||||
13, 13, 13, 13, 30, 31, 13, 13, 13, 32, 13, 13, 0, 33, 0, 34,
|
||||
35, 36, 37, 13, 38, 39, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 30,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 16, 0, 2, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 4, 0, 0, 2, 0, 0,240, 3, 0, 6, 0, 0,
|
||||
0, 0, 0, 12, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
|
||||
0,128, 0, 0, 0,254, 15, 7, 4, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 12, 64, 0, 1, 0, 0, 0, 0, 0, 0,120,
|
||||
191,255,247,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
63, 0,255,255,255,255,255,255, 63,255, 87, 32, 2, 1, 24, 0,
|
||||
144, 80,184, 0,248, 0, 0, 0, 0, 0,224, 0, 2, 0, 1,128,
|
||||
0, 0, 0, 0, 0, 0, 48, 0,224, 0, 0, 24, 0, 0, 0, 0,
|
||||
0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32,
|
||||
0, 0,128, 2, 0, 0, 0, 0, 0,224, 0, 0, 0,128, 0, 0,
|
||||
0, 0, 0, 0, 0,240, 3,192, 0, 64,254, 7, 0,224,255,255,
|
||||
255,255,255,255, 63, 0, 0, 0,254,255, 0, 4, 0,128,252,247,
|
||||
0,254,255,255,255,255,255,255,255,255,255,255,255,255,255, 7,
|
||||
255,255,255,255,255,255,255, 63,192,255,255,255,255,255,255,255,
|
||||
255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,255,
|
||||
0, 0,224,255,255,255,255,255, 0,240, 0, 0, 0, 0, 0, 0,
|
||||
0,255, 0,252, 0, 0, 0, 0, 0,255, 0, 0, 0,192,255,255,
|
||||
0,240,255,255,255,255,255,247,191,255,255,255,255,255,255,255,
|
||||
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
2, 0, 3, 4, 0, 0, 5, 6, 0, 7, 0, 8, 9, 10, 11, 12,
|
||||
0, 0, 13, 0, 0, 0, 14, 0, 15, 0, 0, 0, 0, 16, 0, 0,
|
||||
17, 17, 18, 19, 20, 17, 17, 21, 17, 17, 22, 17, 23, 17, 24, 25,
|
||||
26, 27, 28, 17, 17, 17, 0, 0, 17, 17, 17, 17, 17, 17, 17, 29,
|
||||
0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 4, 0, 0,
|
||||
5, 6, 0, 0, 7, 8, 0, 0, 8, 0, 9, 10, 0, 0, 11, 0,
|
||||
0, 12, 13, 14, 15, 16, 16, 16, 17, 16, 16, 16, 18, 19, 20, 21,
|
||||
22, 23, 0, 0, 0, 24, 0, 0, 25, 0, 26, 0, 0, 27, 0, 0,
|
||||
28, 0, 0, 0, 16, 16, 16, 16, 29, 9, 0, 30, 31, 32, 16, 33,
|
||||
34, 35, 36, 16, 16, 16, 16, 37, 16, 38, 39, 16, 16, 16, 40, 0,
|
||||
0, 0, 0, 41, 0, 0, 42, 16, 43, 0, 44, 0, 45, 46, 16, 16,
|
||||
47, 48, 49, 16, 16, 16, 16, 38, 0, 0, 0, 0, 0, 66, 0, 0,
|
||||
0, 0, 0, 16, 0, 2, 0, 0, 4, 0, 0, 2, 0, 0,240, 3,
|
||||
0, 6, 0, 0, 0, 0, 0, 12, 0, 1, 0, 0, 0,128, 0, 0,
|
||||
0,254, 15, 7, 4, 0, 0, 0, 0, 12, 64, 0, 1, 0, 0, 0,
|
||||
0, 0, 0,120,191,255,247,255,255,255,255,255, 63, 0,255,255,
|
||||
63,255, 87, 32, 2, 1, 24, 0,144, 80,184, 0,248, 0, 0, 0,
|
||||
0, 0,224, 0, 2, 0, 1,128, 0, 0, 48, 0,224, 0, 0, 24,
|
||||
0, 0, 33, 0, 0, 0, 1, 32, 0, 0,128, 2, 0,224, 0, 0,
|
||||
0,240, 3,192, 0, 64,254, 7, 0,224,255,255, 63, 0, 0, 0,
|
||||
254,255, 0, 4, 0,128,252,247, 0,254,255,255,255,255,255, 7,
|
||||
255,255,255, 63,192,255,255,255,255,255, 0, 0, 0, 0,240,255,
|
||||
0, 0,224,255, 0,240, 0, 0, 0,255, 0,252, 0,255, 0, 0,
|
||||
0,192,255,255, 0,240,255,255,255,255,255,247,191,255,255,255,
|
||||
};
|
||||
|
||||
static inline unsigned
|
||||
|
@ -75,7 +70,7 @@ _hb_emoji_b1 (const uint8_t* a, unsigned i)
|
|||
static inline uint_fast8_t
|
||||
_hb_emoji_is_Extended_Pictographic (unsigned u)
|
||||
{
|
||||
return u<131070u?_hb_emoji_b1(224+_hb_emoji_u8,((_hb_emoji_u8[64+(((_hb_emoji_b4(_hb_emoji_u8,u>>6>>4))<<4)+((u>>6)&15u))])<<6)+((u)&63u)):0;
|
||||
return u<131070u?_hb_emoji_b1(264+_hb_emoji_u8,((_hb_emoji_u8[144+(((_hb_emoji_u8[64+(((_hb_emoji_b4(_hb_emoji_u8,u>>5>>2>>3))<<3)+((u>>5>>2)&7u))])<<2)+((u>>5)&3u))])<<5)+((u)&31u)):0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -308,8 +308,8 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
|
|||
* Since: 0.9.2
|
||||
**/
|
||||
void *
|
||||
hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
|
||||
hb_user_data_key_t *key)
|
||||
hb_unicode_funcs_get_user_data (const hb_unicode_funcs_t *ufuncs,
|
||||
hb_user_data_key_t *key)
|
||||
{
|
||||
return hb_object_get_user_data (ufuncs, key);
|
||||
}
|
||||
|
|
|
@ -317,8 +317,8 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
|
|||
|
||||
|
||||
HB_EXTERN void *
|
||||
hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
|
||||
hb_user_data_key_t *key);
|
||||
hb_unicode_funcs_get_user_data (const hb_unicode_funcs_t *ufuncs,
|
||||
hb_user_data_key_t *key);
|
||||
|
||||
|
||||
HB_EXTERN void
|
||||
|
|
|
@ -47,20 +47,20 @@ HB_BEGIN_DECLS
|
|||
*
|
||||
* The minor component of the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_MINOR 0
|
||||
#define HB_VERSION_MINOR 1
|
||||
/**
|
||||
* HB_VERSION_MICRO:
|
||||
*
|
||||
* The micro component of the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_MICRO 1
|
||||
#define HB_VERSION_MICRO 0
|
||||
|
||||
/**
|
||||
* HB_VERSION_STRING:
|
||||
*
|
||||
* A string literal containing the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_STRING "5.0.1"
|
||||
#define HB_VERSION_STRING "5.1.0"
|
||||
|
||||
/**
|
||||
* HB_VERSION_ATLEAST:
|
||||
|
|
Loading…
Reference in New Issue