summaryrefslogtreecommitdiff
path: root/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh')
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh394
1 files changed, 233 insertions, 161 deletions
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh
index 9ebd8e417f9..861a5eaedbb 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh
@@ -83,18 +83,16 @@ struct CmapSubtableFormat4
HBUINT16 *endCode = c->start_embed<HBUINT16> ();
hb_codepoint_t prev_endcp = 0xFFFF;
- + it
- | hb_apply ([&] (const hb_item_type<Iterator> _)
- {
- if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first)
- {
- HBUINT16 end_code;
- end_code = prev_endcp;
- c->copy<HBUINT16> (end_code);
- }
- prev_endcp = _.first;
- })
- ;
+ for (const hb_item_type<Iterator> _ : +it)
+ {
+ if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first)
+ {
+ HBUINT16 end_code;
+ end_code = prev_endcp;
+ c->copy<HBUINT16> (end_code);
+ }
+ prev_endcp = _.first;
+ }
{
// last endCode
@@ -121,19 +119,17 @@ struct CmapSubtableFormat4
HBUINT16 *startCode = c->start_embed<HBUINT16> ();
hb_codepoint_t prev_cp = 0xFFFF;
- + it
- | hb_apply ([&] (const hb_item_type<Iterator> _)
- {
- if (prev_cp == 0xFFFF || prev_cp + 1u != _.first)
- {
- HBUINT16 start_code;
- start_code = _.first;
- c->copy<HBUINT16> (start_code);
- }
-
- prev_cp = _.first;
- })
- ;
+ for (const hb_item_type<Iterator> _ : +it)
+ {
+ if (prev_cp == 0xFFFF || prev_cp + 1u != _.first)
+ {
+ HBUINT16 start_code;
+ start_code = _.first;
+ c->copy<HBUINT16> (start_code);
+ }
+
+ prev_cp = _.first;
+ }
// There must be a final entry with end_code == 0xFFFF.
if (it.len () == 0 || prev_cp != 0xFFFF)
@@ -162,30 +158,28 @@ struct CmapSubtableFormat4
if ((char *)idDelta - (char *)startCode != (int) segcount * (int) HBINT16::static_size)
return nullptr;
- + it
- | hb_apply ([&] (const hb_item_type<Iterator> _)
- {
- if (_.first == startCode[i])
- {
- use_delta = true;
- start_gid = _.second;
- }
- else if (_.second != last_gid + 1) use_delta = false;
-
- if (_.first == endCode[i])
- {
- HBINT16 delta;
- if (use_delta) delta = (int)start_gid - (int)startCode[i];
- else delta = 0;
- c->copy<HBINT16> (delta);
-
- i++;
- }
-
- last_gid = _.second;
- last_cp = _.first;
- })
- ;
+ for (const hb_item_type<Iterator> _ : +it)
+ {
+ if (_.first == startCode[i])
+ {
+ use_delta = true;
+ start_gid = _.second;
+ }
+ else if (_.second != last_gid + 1) use_delta = false;
+
+ if (_.first == endCode[i])
+ {
+ HBINT16 delta;
+ if (use_delta) delta = (int)start_gid - (int)startCode[i];
+ else delta = 0;
+ c->copy<HBINT16> (delta);
+
+ i++;
+ }
+
+ last_gid = _.second;
+ last_cp = _.first;
+ }
if (it.len () == 0 || last_cp != 0xFFFF)
{
@@ -238,12 +232,21 @@ struct CmapSubtableFormat4
void serialize (hb_serialize_context_t *c,
Iterator it)
{
+ auto format4_iter =
+ + it
+ | hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
+ { return _.first <= 0xFFFF; })
+ ;
+
+ //comment off temporarily while we're working on supporting --gids option
+ //if (format4_iter.len () == 0) return;
+
unsigned table_initpos = c->length ();
if (unlikely (!c->extend_min (*this))) return;
this->format = 4;
//serialize endCode[]
- HBUINT16 *endCode = serialize_endcode_array (c, it);
+ HBUINT16 *endCode = serialize_endcode_array (c, format4_iter);
if (unlikely (!endCode)) return;
unsigned segcount = (c->length () - min_size) / HBUINT16::static_size;
@@ -252,14 +255,14 @@ struct CmapSubtableFormat4
if (unlikely (!c->allocate_size<HBUINT16> (HBUINT16::static_size))) return; // 2 bytes of padding.
// serialize startCode[]
- HBUINT16 *startCode = serialize_startcode_array (c, it);
+ HBUINT16 *startCode = serialize_startcode_array (c, format4_iter);
if (unlikely (!startCode)) return;
//serialize idDelta[]
- HBINT16 *idDelta = serialize_idDelta_array (c, it, endCode, startCode, segcount);
+ HBINT16 *idDelta = serialize_idDelta_array (c, format4_iter, endCode, startCode, segcount);
if (unlikely (!idDelta)) return;
- HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, it, endCode, startCode, idDelta, segcount);
+ HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount);
if (unlikely (!c->check_success (idRangeOffset))) return;
if (unlikely (!c->check_assign(this->length, c->length () - table_initpos))) return;
@@ -291,27 +294,28 @@ struct CmapSubtableFormat4
bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
- /* Custom two-array bsearch. */
- int min = 0, max = (int) this->segCount - 1;
- const HBUINT16 *startCount = this->startCount;
- const HBUINT16 *endCount = this->endCount;
- unsigned int i;
- while (min <= max)
+ struct CustomRange
{
- int mid = ((unsigned int) min + (unsigned int) max) / 2;
- if (codepoint < startCount[mid])
- max = mid - 1;
- else if (codepoint > endCount[mid])
- min = mid + 1;
- else
+ int cmp (hb_codepoint_t k,
+ unsigned distance) const
{
- i = mid;
- goto found;
+ if (k > last) return +1;
+ if (k < (&last)[distance]) return -1;
+ return 0;
}
- }
- return false;
+ HBUINT16 last;
+ };
+
+ const HBUINT16 *found =hb_bsearch (codepoint,
+ this->endCount,
+ this->segCount,
+ 2,
+ _hb_cmp_method<hb_codepoint_t, CustomRange, unsigned>,
+ this->segCount + 1);
+ if (!found)
+ return false;
+ unsigned int i = found - endCount;
- found:
hb_codepoint_t gid;
unsigned int rangeOffset = this->idRangeOffset[i];
if (rangeOffset == 0)
@@ -333,8 +337,10 @@ struct CmapSubtableFormat4
*glyph = gid;
return true;
}
+
HB_INTERNAL static bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
{ return ((const accelerator_t *) obj)->get_glyph (codepoint, glyph); }
+
void collect_unicodes (hb_set_t *out) const
{
unsigned int count = this->segCount;
@@ -528,20 +534,26 @@ struct CmapSubtableLongSegmented
return true;
}
- void collect_unicodes (hb_set_t *out) const
+ void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
{
for (unsigned int i = 0; i < this->groups.len; i++)
{
hb_codepoint_t start = this->groups[i].startCharCode;
hb_codepoint_t end = hb_min ((hb_codepoint_t) this->groups[i].endCharCode,
(hb_codepoint_t) HB_UNICODE_MAX);
- for (hb_codepoint_t codepoint = start; codepoint <= end; codepoint++)
+ hb_codepoint_t gid = this->groups[i].glyphID;
+ if (!gid)
{
- hb_codepoint_t gid = T::group_get_glyph (this->groups[i], codepoint);
- if (unlikely (!gid))
- continue;
- out->add (codepoint);
+ /* Intention is: if (hb_is_same (T, CmapSubtableFormat13)) continue; */
+ if (! T::group_get_glyph (this->groups[i], end)) continue;
+ start++;
+ gid++;
}
+ if (unlikely ((unsigned int) gid >= num_glyphs)) continue;
+ if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs))
+ end = start + (hb_codepoint_t) num_glyphs - gid;
+
+ out->add_range (start, end);
}
}
@@ -582,33 +594,29 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
hb_codepoint_t glyphID = 0;
- + it
- | hb_apply ([&] (const hb_item_type<Iterator> _)
- {
- if (startCharCode == 0xFFFF)
- {
- startCharCode = _.first;
- endCharCode = _.first;
- glyphID = _.second;
- }
- else if (!_is_gid_consecutive (endCharCode, startCharCode, glyphID, _.first, _.second))
- {
- CmapSubtableLongGroup grouprecord;
- grouprecord.startCharCode = startCharCode;
- grouprecord.endCharCode = endCharCode;
- grouprecord.glyphID = glyphID;
- c->copy<CmapSubtableLongGroup> (grouprecord);
-
- startCharCode = _.first;
- endCharCode = _.first;
- glyphID = _.second;
- }
- else
- {
- endCharCode = _.first;
- }
- })
- ;
+ for (const hb_item_type<Iterator> _ : +it)
+ {
+ if (startCharCode == 0xFFFF)
+ {
+ startCharCode = _.first;
+ endCharCode = _.first;
+ glyphID = _.second;
+ }
+ else if (!_is_gid_consecutive (endCharCode, startCharCode, glyphID, _.first, _.second))
+ {
+ CmapSubtableLongGroup grouprecord;
+ grouprecord.startCharCode = startCharCode;
+ grouprecord.endCharCode = endCharCode;
+ grouprecord.glyphID = glyphID;
+ c->copy<CmapSubtableLongGroup> (grouprecord);
+
+ startCharCode = _.first;
+ endCharCode = _.first;
+ glyphID = _.second;
+ }
+ else
+ endCharCode = _.first;
+ }
CmapSubtableLongGroup record;
record.startCharCode = startCharCode;
@@ -772,7 +780,7 @@ struct NonDefaultUVS : SortedArrayOf<UVSMapping, HBUINT32>
{
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
- out->add (arrayZ[i].glyphID);
+ out->add (arrayZ[i].unicodeValue);
}
void closure_glyphs (const hb_set_t *unicodes,
@@ -839,6 +847,20 @@ struct VariationSelectorRecord
return GLYPH_VARIANT_NOT_FOUND;
}
+ VariationSelectorRecord(const VariationSelectorRecord& other)
+ {
+ *this = other;
+ }
+
+ void operator= (const VariationSelectorRecord& other)
+ {
+ varSelector = other.varSelector;
+ HBUINT32 offset = other.defaultUVS;
+ defaultUVS = offset;
+ offset = other.nonDefaultUVS;
+ nonDefaultUVS = offset;
+ }
+
void collect_unicodes (hb_set_t *out, const void *base) const
{
(base+defaultUVS).collect_unicodes (out);
@@ -856,50 +878,43 @@ struct VariationSelectorRecord
nonDefaultUVS.sanitize (c, base));
}
- VariationSelectorRecord* copy (hb_serialize_context_t *c,
- const hb_set_t *unicodes,
- const hb_set_t *glyphs,
- const hb_map_t *glyph_map,
- const void *src_base,
- const void *dst_base) const
+ hb_pair_t<unsigned, unsigned>
+ copy (hb_serialize_context_t *c,
+ const hb_set_t *unicodes,
+ const hb_set_t *glyphs,
+ const hb_map_t *glyph_map,
+ const void *base) const
{
auto snap = c->snapshot ();
auto *out = c->embed<VariationSelectorRecord> (*this);
- if (unlikely (!out)) return nullptr;
+ if (unlikely (!out)) return hb_pair (0, 0);
out->defaultUVS = 0;
out->nonDefaultUVS = 0;
- bool drop = true;
-
- if (defaultUVS != 0)
+ unsigned non_default_uvs_objidx = 0;
+ if (nonDefaultUVS != 0)
{
c->push ();
- if (c->copy (src_base+defaultUVS, unicodes))
- {
- c->add_link (out->defaultUVS, c->pop_pack (), dst_base);
- drop = false;
- }
+ if (c->copy (base+nonDefaultUVS, unicodes, glyphs, glyph_map))
+ non_default_uvs_objidx = c->pop_pack ();
else c->pop_discard ();
}
- if (nonDefaultUVS != 0)
+ unsigned default_uvs_objidx = 0;
+ if (defaultUVS != 0)
{
c->push ();
- if (c->copy (src_base+nonDefaultUVS, unicodes, glyphs, glyph_map))
- {
- c->add_link (out->nonDefaultUVS, c->pop_pack (), dst_base);
- drop = false;
- }
+ if (c->copy (base+defaultUVS, unicodes))
+ default_uvs_objidx = c->pop_pack ();
else c->pop_discard ();
}
- if (drop)
- {
+
+ if (!default_uvs_objidx && !non_default_uvs_objidx)
c->revert (snap);
- return nullptr;
- }
- else return out;
+
+ return hb_pair (default_uvs_objidx, non_default_uvs_objidx);
}
HBUINT24 varSelector; /* Variation selector. */
@@ -932,7 +947,7 @@ struct CmapSubtableFormat14
const hb_set_t *unicodes,
const hb_set_t *glyphs,
const hb_map_t *glyph_map,
- const void *src_base)
+ const void *base)
{
auto snap = c->snapshot ();
unsigned table_initpos = c->length ();
@@ -941,17 +956,67 @@ struct CmapSubtableFormat14
if (unlikely (!c->extend_min (*this))) return;
this->format = 14;
- const CmapSubtableFormat14 *src_tbl = reinterpret_cast<const CmapSubtableFormat14*> (src_base);
- for (const VariationSelectorRecord& _ : src_tbl->record)
- c->copy (_, unicodes, glyphs, glyph_map, src_base, this);
+ auto src_tbl = reinterpret_cast<const CmapSubtableFormat14*> (base);
+
+ /*
+ * Some versions of OTS require that offsets are in order. Due to the use
+ * of push()/pop_pack() serializing the variation records in order results
+ * in the offsets being in reverse order (first record has the largest
+ * offset). While this is perfectly valid, it will cause some versions of
+ * OTS to consider this table bad.
+ *
+ * So to prevent this issue we serialize the variation records in reverse
+ * order, so that the offsets are ordered from small to large. Since
+ * variation records are supposed to be in increasing order of varSelector
+ * we then have to reverse the order of the written variation selector
+ * records after everything is finalized.
+ */
+ hb_vector_t<hb_pair_t<unsigned, unsigned>> obj_indices;
+ for (int i = src_tbl->record.len - 1; i >= 0; i--)
+ {
+ hb_pair_t<unsigned, unsigned> result = src_tbl->record[i].copy (c, unicodes, glyphs, glyph_map, base);
+ if (result.first || result.second)
+ obj_indices.push (result);
+ }
if (c->length () - table_initpos == CmapSubtableFormat14::min_size)
+ {
c->revert (snap);
- else
+ return;
+ }
+
+ int tail_len = init_tail - c->tail;
+ c->check_assign (this->length, c->length () - table_initpos + tail_len);
+ c->check_assign (this->record.len,
+ (c->length () - table_initpos - CmapSubtableFormat14::min_size) /
+ VariationSelectorRecord::static_size);
+
+ /* Correct the incorrect write order by reversing the order of the variation
+ records array. */
+ _reverse_variation_records ();
+
+ /* Now that records are in the right order, we can set up the offsets. */
+ _add_links_to_variation_records (c, obj_indices);
+ }
+
+ void _reverse_variation_records ()
+ {
+ record.as_array ().reverse ();
+ }
+
+ void _add_links_to_variation_records (hb_serialize_context_t *c,
+ const hb_vector_t<hb_pair_t<unsigned, unsigned>>& obj_indices)
+ {
+ for (unsigned i = 0; i < obj_indices.length; i++)
{
- int tail_len = init_tail - c->tail;
- c->check_assign (this->length, c->length () - table_initpos + tail_len);
- c->check_assign (this->record.len, (c->length () - table_initpos - CmapSubtableFormat14::min_size) / VariationSelectorRecord::static_size);
+ /*
+ * Since the record array has been reversed (see comments in copy())
+ * but obj_indices has not been, the indices at obj_indices[i]
+ * are for the variation record at record[j].
+ */
+ int j = obj_indices.length - 1 - i;
+ c->add_link (record[j].defaultUVS, obj_indices[i].first);
+ c->add_link (record[j].nonDefaultUVS, obj_indices[i].second);
}
}
@@ -966,6 +1031,12 @@ struct CmapSubtableFormat14
;
}
+ void collect_unicodes (hb_set_t *out) const
+ {
+ for (const VariationSelectorRecord& _ : record)
+ _.collect_unicodes (out, this);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -1001,15 +1072,15 @@ struct CmapSubtable
default: return false;
}
}
- void collect_unicodes (hb_set_t *out) const
+ void collect_unicodes (hb_set_t *out, unsigned int num_glyphs = UINT_MAX) const
{
switch (u.format) {
case 0: u.format0 .collect_unicodes (out); return;
case 4: u.format4 .collect_unicodes (out); return;
case 6: u.format6 .collect_unicodes (out); return;
case 10: u.format10.collect_unicodes (out); return;
- case 12: u.format12.collect_unicodes (out); return;
- case 13: u.format13.collect_unicodes (out); return;
+ case 12: u.format12.collect_unicodes (out, num_glyphs); return;
+ case 13: u.format13.collect_unicodes (out, num_glyphs); return;
case 14:
default: return;
}
@@ -1021,12 +1092,12 @@ struct CmapSubtable
Iterator it,
unsigned format,
const hb_subset_plan_t *plan,
- const void *src_base)
+ const void *base)
{
switch (format) {
- case 4: u.format4.serialize (c, it); return;
- case 12: u.format12.serialize (c, it); return;
- case 14: u.format14.serialize (c, plan->unicodes, plan->_glyphset, plan->glyph_map, src_base); return;
+ case 4: return u.format4.serialize (c, it);
+ case 12: return u.format12.serialize (c, it);
+ case 14: return u.format14.serialize (c, plan->unicodes, plan->_glyphset, plan->glyph_map, base);
default: return;
}
}
@@ -1087,8 +1158,7 @@ struct EncodingRecord
EncodingRecord* copy (hb_serialize_context_t *c,
Iterator it,
unsigned format,
- const void *src_base,
- const void *dst_base,
+ const void *base,
const hb_subset_plan_t *plan,
/* INOUT */ unsigned *objidx) const
{
@@ -1102,7 +1172,7 @@ struct EncodingRecord
{
CmapSubtable *cmapsubtable = c->push<CmapSubtable> ();
unsigned origin_length = c->length ();
- cmapsubtable->serialize (c, it, format, plan, &(src_base+subtable));
+ cmapsubtable->serialize (c, it, format, plan, &(base+subtable));
if (c->length () - origin_length > 0) *objidx = c->pop_pack ();
else c->pop_discard ();
}
@@ -1113,7 +1183,7 @@ struct EncodingRecord
return_trace (nullptr);
}
- c->add_link (out->subtable, *objidx, dst_base);
+ c->add_link (out->subtable, *objidx);
return_trace (out);
}
@@ -1134,7 +1204,7 @@ struct cmap
void serialize (hb_serialize_context_t *c,
Iterator it,
EncodingRecIter encodingrec_iter,
- const void *src_base,
+ const void *base,
const hb_subset_plan_t *plan)
{
if (unlikely (!c->extend_min ((*this)))) return;
@@ -1144,11 +1214,14 @@ struct cmap
for (const EncodingRecord& _ : encodingrec_iter)
{
- unsigned format = (src_base+_.subtable).u.format;
+ hb_set_t unicodes_set;
+ (base+_.subtable).collect_unicodes (&unicodes_set);
- if (format == 4) c->copy (_, it, 4u, src_base, this, plan, &format4objidx);
- else if (format == 12) c->copy (_, it, 12u, src_base, this, plan, &format12objidx);
- else if (format == 14) c->copy (_, it, 14u, src_base, this, plan, &format14objidx);
+ unsigned format = (base+_.subtable).u.format;
+
+ if (format == 4) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
+ else if (format == 12) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx);
+ else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
}
c->check_assign(this->encodingRecord.len, (c->length () - cmap::min_size)/EncodingRecord::static_size);
@@ -1187,7 +1260,6 @@ struct cmap
})
;
-
if (unlikely (!encodingrec_iter.len ())) return_trace (false);
const EncodingRecord *unicode_bmp= nullptr, *unicode_ucs4 = nullptr, *ms_bmp = nullptr, *ms_ucs4 = nullptr;
@@ -1205,7 +1277,7 @@ struct cmap
else if (_.platformID == 3 && _.encodingID == 10) ms_ucs4 = table;
}
- if (unlikely (!unicode_bmp && !ms_bmp)) return_trace (false);
+ if (unlikely (!has_format12 && !unicode_bmp && !ms_bmp)) return_trace (false);
if (unlikely (has_format12 && (!unicode_ucs4 && !ms_ucs4))) return_trace (false);
auto it =
@@ -1339,8 +1411,8 @@ struct cmap
return get_nominal_glyph (unicode, glyph);
}
- void collect_unicodes (hb_set_t *out) const
- { subtable->collect_unicodes (out); }
+ void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
+ { subtable->collect_unicodes (out, num_glyphs); }
void collect_variation_selectors (hb_set_t *out) const
{ subtable_uvs->collect_variation_selectors (out); }
void collect_variation_unicodes (hb_codepoint_t variation_selector,
@@ -1413,7 +1485,7 @@ struct cmap
}
const EncodingRecord *find_encodingrec (unsigned int platform_id,
- unsigned int encoding_id) const
+ unsigned int encoding_id) const
{
EncodingRecord key;
key.platformID = platform_id;
@@ -1445,9 +1517,9 @@ struct cmap
}
protected:
- HBUINT16 version; /* Table version number (0). */
+ HBUINT16 version; /* Table version number (0). */
SortedArrayOf<EncodingRecord>
- encodingRecord; /* Encoding tables. */
+ encodingRecord; /* Encoding tables. */
public:
DEFINE_SIZE_ARRAY (4, encodingRecord);
};