diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2020-05-18 10:44:36 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2020-05-18 10:44:36 +0000 |
commit | f71aeb3fe9f385a634c46188515206f91c087b82 (patch) | |
tree | c629a78664446246792fc22a7cf8f36b9e4ffcee /Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh | |
parent | 57f9b626bae9d06ab9a7818a4bf6de15213980bb (diff) |
harfbuzz 2.6.6
git-svn-id: svn://tug.org/texlive/trunk@55197 c570f23f-e606-0410-a88d-b1316a301751
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.hh | 394 |
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); }; |