mirror of
https://github.com/openharmony/third_party_harfbuzz.git
synced 2026-07-01 10:04:31 -04:00
e005ef2500
IssueNo: https://gitee.com/openharmony/third_party_harfbuzz/issues/I8LXPB Feature or Bugfix: Bugfix Binary Source:No Signed-off-by: wyk99 <wangyuekai1@huawei.com>
460 lines
14 KiB
Diff
460 lines
14 KiB
Diff
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
|
|
index 865ccb2..88f1f4c 100644
|
|
--- a/src/hb-buffer.h
|
|
+++ b/src/hb-buffer.h
|
|
@@ -307,7 +307,8 @@ typedef enum { /*< flags >*/
|
|
HB_BUFFER_FLAG_EOT = 0x00000002u, /* End-of-text */
|
|
HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u,
|
|
HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u,
|
|
- HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u
|
|
+ HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u,
|
|
+ HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u
|
|
} hb_buffer_flags_t;
|
|
|
|
HB_EXTERN void
|
|
diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
|
|
index 406771f..b8ac4c5 100644
|
|
--- a/src/hb-open-type.hh
|
|
+++ b/src/hb-open-type.hh
|
|
@@ -575,8 +575,13 @@ struct SortedUnsizedArrayOf : UnsizedArrayOf<Type>
|
|
{ return hb_sorted_array (this->arrayZ, len); }
|
|
hb_sorted_array_t<const Type> as_array (unsigned int len) const
|
|
{ return hb_sorted_array (this->arrayZ, len); }
|
|
+#ifdef ENABLE_ICCARM
|
|
+ operator hb_sorted_array_t<Type> () { return as_array (0); }
|
|
+ operator hb_sorted_array_t<const Type> () const { return as_array (0); }
|
|
+#else
|
|
operator hb_sorted_array_t<Type> () { return as_array (); }
|
|
operator hb_sorted_array_t<const Type> () const { return as_array (); }
|
|
+#endif
|
|
|
|
template <typename T>
|
|
Type &bsearch (unsigned int len, const T &x, Type ¬_found = Crap (Type))
|
|
diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh
|
|
index c78f820..c9d93a7 100644
|
|
--- a/src/hb-ot-layout-common.hh
|
|
+++ b/src/hb-ot-layout-common.hh
|
|
@@ -445,6 +445,7 @@ struct RecordListOf : RecordArrayOf<Type>
|
|
}
|
|
};
|
|
|
|
+#ifndef ENABLE_ICCARM // Adaptive compilation, only changes the order of the code, does not affect the function
|
|
struct Feature;
|
|
|
|
struct RecordListOfFeature : RecordListOf<Feature>
|
|
@@ -797,7 +798,7 @@ struct Script
|
|
};
|
|
|
|
typedef RecordListOfScript ScriptList;
|
|
-
|
|
+#endif // ENABLE_ICCARM
|
|
|
|
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
|
|
struct FeatureParamsSize
|
|
@@ -1081,6 +1082,52 @@ struct FeatureParams
|
|
DEFINE_SIZE_MIN (0);
|
|
};
|
|
|
|
+#ifdef ENABLE_ICCARM // Adaptive compilation, only changes the order of the code, does not affect the function
|
|
+struct IndexArray : Array16Of<Index>
|
|
+{
|
|
+ bool intersects (const hb_map_t *indexes) const
|
|
+ { return hb_any (*this, indexes); }
|
|
+
|
|
+ template <typename Iterator,
|
|
+ hb_requires (hb_is_iterator (Iterator))>
|
|
+ void serialize (hb_serialize_context_t *c,
|
|
+ hb_subset_layout_context_t *l,
|
|
+ Iterator it)
|
|
+ {
|
|
+ if (!it) return;
|
|
+ if (unlikely (!c->extend_min ((*this)))) return;
|
|
+
|
|
+ for (const auto _ : it)
|
|
+ {
|
|
+ if (!l->visitLookupIndex()) break;
|
|
+
|
|
+ Index i;
|
|
+ i = _;
|
|
+ c->copy (i);
|
|
+ this->len++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ unsigned int get_indexes (unsigned int start_offset,
|
|
+ unsigned int *_count /* IN/OUT */,
|
|
+ unsigned int *_indexes /* OUT */) const
|
|
+ {
|
|
+ if (_count)
|
|
+ {
|
|
+ + this->sub_array (start_offset, _count)
|
|
+ | hb_sink (hb_array (_indexes, *_count))
|
|
+ ;
|
|
+ }
|
|
+ return this->len;
|
|
+ }
|
|
+
|
|
+ void add_indexes_to (hb_set_t* output /* OUT */) const
|
|
+ {
|
|
+ output->add_array (as_array ());
|
|
+ }
|
|
+};
|
|
+#endif // ENABLE_ICCARM
|
|
+
|
|
struct Feature
|
|
{
|
|
unsigned int get_lookup_count () const
|
|
@@ -1176,6 +1223,311 @@ struct Feature
|
|
DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
|
|
};
|
|
|
|
+#ifdef ENABLE_ICCARM // Adaptive compilation, only changes the order of the code, does not affect the function
|
|
+struct RecordListOfFeature : RecordListOf<Feature>
|
|
+{
|
|
+ bool subset (hb_subset_context_t *c,
|
|
+ hb_subset_layout_context_t *l) const
|
|
+ {
|
|
+ TRACE_SUBSET (this);
|
|
+ auto *out = c->serializer->start_embed (*this);
|
|
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
|
|
+
|
|
+ unsigned count = this->len;
|
|
+ + hb_zip (*this, hb_range (count))
|
|
+ | hb_filter (l->feature_index_map, hb_second)
|
|
+ | hb_map (hb_first)
|
|
+ | hb_apply (subset_record_array (l, out, this))
|
|
+ ;
|
|
+ return_trace (true);
|
|
+ }
|
|
+};
|
|
+
|
|
+struct LangSys
|
|
+{
|
|
+ unsigned int get_feature_count () const
|
|
+ { return featureIndex.len; }
|
|
+ hb_tag_t get_feature_index (unsigned int i) const
|
|
+ { return featureIndex[i]; }
|
|
+ unsigned int get_feature_indexes (unsigned int start_offset,
|
|
+ unsigned int *feature_count /* IN/OUT */,
|
|
+ unsigned int *feature_indexes /* OUT */) const
|
|
+ { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
|
|
+ void add_feature_indexes_to (hb_set_t *feature_indexes) const
|
|
+ { featureIndex.add_indexes_to (feature_indexes); }
|
|
+
|
|
+ bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
|
|
+ unsigned int get_required_feature_index () const
|
|
+ {
|
|
+ if (reqFeatureIndex == 0xFFFFu)
|
|
+ return Index::NOT_FOUND_INDEX;
|
|
+ return reqFeatureIndex;
|
|
+ }
|
|
+
|
|
+ LangSys* copy (hb_serialize_context_t *c) const
|
|
+ {
|
|
+ TRACE_SERIALIZE (this);
|
|
+ return_trace (c->embed (*this));
|
|
+ }
|
|
+
|
|
+ bool compare (const LangSys& o, const hb_map_t *feature_index_map) const
|
|
+ {
|
|
+ if (reqFeatureIndex != o.reqFeatureIndex)
|
|
+ return false;
|
|
+
|
|
+ auto iter =
|
|
+ + hb_iter (featureIndex)
|
|
+ | hb_filter (feature_index_map)
|
|
+ | hb_map (feature_index_map)
|
|
+ ;
|
|
+
|
|
+ auto o_iter =
|
|
+ + hb_iter (o.featureIndex)
|
|
+ | hb_filter (feature_index_map)
|
|
+ | hb_map (feature_index_map)
|
|
+ ;
|
|
+
|
|
+ if (iter.len () != o_iter.len ())
|
|
+ return false;
|
|
+
|
|
+ for (const auto _ : + hb_zip (iter, o_iter))
|
|
+ if (_.first != _.second) return false;
|
|
+
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ void collect_features (hb_prune_langsys_context_t *c) const
|
|
+ {
|
|
+ if (!has_required_feature () && !get_feature_count ()) return;
|
|
+ if (c->visitedLangsys (this)) return;
|
|
+ if (has_required_feature () &&
|
|
+ c->duplicate_feature_map->has (reqFeatureIndex))
|
|
+ c->new_feature_indexes->add (get_required_feature_index ());
|
|
+
|
|
+ + hb_iter (featureIndex)
|
|
+ | hb_filter (c->duplicate_feature_map)
|
|
+ | hb_sink (c->new_feature_indexes)
|
|
+ ;
|
|
+ }
|
|
+
|
|
+ bool subset (hb_subset_context_t *c,
|
|
+ hb_subset_layout_context_t *l,
|
|
+ const Tag *tag = nullptr) const
|
|
+ {
|
|
+ TRACE_SUBSET (this);
|
|
+ auto *out = c->serializer->start_embed (*this);
|
|
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
|
|
+
|
|
+ out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex) ? l->feature_index_map->get (reqFeatureIndex) : 0xFFFFu;
|
|
+
|
|
+ if (!l->visitFeatureIndex (featureIndex.len))
|
|
+ return_trace (false);
|
|
+
|
|
+ auto it =
|
|
+ + hb_iter (featureIndex)
|
|
+ | hb_filter (l->feature_index_map)
|
|
+ | hb_map (l->feature_index_map)
|
|
+ ;
|
|
+
|
|
+ bool ret = bool (it);
|
|
+ out->featureIndex.serialize (c->serializer, l, it);
|
|
+ return_trace (ret);
|
|
+ }
|
|
+
|
|
+ bool sanitize (hb_sanitize_context_t *c,
|
|
+ const Record_sanitize_closure_t * = nullptr) const
|
|
+ {
|
|
+ TRACE_SANITIZE (this);
|
|
+ return_trace (c->check_struct (this) && featureIndex.sanitize (c));
|
|
+ }
|
|
+
|
|
+ Offset16 lookupOrderZ; /* = Null (reserved for an offset to a
|
|
+ * reordering table) */
|
|
+ HBUINT16 reqFeatureIndex;/* Index of a feature required for this
|
|
+ * language system--if no required features
|
|
+ * = 0xFFFFu */
|
|
+ IndexArray featureIndex; /* Array of indices into the FeatureList */
|
|
+ public:
|
|
+ DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
|
|
+};
|
|
+DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
|
|
+
|
|
+struct Script
|
|
+{
|
|
+ unsigned int get_lang_sys_count () const
|
|
+ { return langSys.len; }
|
|
+ const Tag& get_lang_sys_tag (unsigned int i) const
|
|
+ { return langSys.get_tag (i); }
|
|
+ unsigned int get_lang_sys_tags (unsigned int start_offset,
|
|
+ unsigned int *lang_sys_count /* IN/OUT */,
|
|
+ hb_tag_t *lang_sys_tags /* OUT */) const
|
|
+ { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
|
|
+ const LangSys& get_lang_sys (unsigned int i) const
|
|
+ {
|
|
+ if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
|
|
+ return this+langSys[i].offset;
|
|
+ }
|
|
+ bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
|
|
+ { return langSys.find_index (tag, index); }
|
|
+
|
|
+ bool has_default_lang_sys () const { return defaultLangSys != 0; }
|
|
+ const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
|
|
+
|
|
+ void prune_langsys (hb_prune_langsys_context_t *c,
|
|
+ unsigned script_index) const
|
|
+ {
|
|
+ if (!has_default_lang_sys () && !get_lang_sys_count ()) return;
|
|
+ if (c->visitedScript (this)) return;
|
|
+
|
|
+ if (!c->script_langsys_map->has (script_index))
|
|
+ {
|
|
+ hb_set_t* empty_set = hb_set_create ();
|
|
+ if (unlikely (!c->script_langsys_map->set (script_index, empty_set)))
|
|
+ {
|
|
+ hb_set_destroy (empty_set);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ unsigned langsys_count = get_lang_sys_count ();
|
|
+ if (has_default_lang_sys ())
|
|
+ {
|
|
+ //only collect features from non-redundant langsys
|
|
+ const LangSys& d = get_default_lang_sys ();
|
|
+ d.collect_features (c);
|
|
+
|
|
+ for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
|
|
+ {
|
|
+ const LangSys& l = this+_.first.offset;
|
|
+ if (l.compare (d, c->duplicate_feature_map)) continue;
|
|
+
|
|
+ l.collect_features (c);
|
|
+ c->script_langsys_map->get (script_index)->add (_.second);
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
|
|
+ {
|
|
+ const LangSys& l = this+_.first.offset;
|
|
+ l.collect_features (c);
|
|
+ c->script_langsys_map->get (script_index)->add (_.second);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ bool subset (hb_subset_context_t *c,
|
|
+ hb_subset_layout_context_t *l,
|
|
+ const Tag *tag) const
|
|
+ {
|
|
+ TRACE_SUBSET (this);
|
|
+ if (!l->visitScript ()) return_trace (false);
|
|
+
|
|
+ auto *out = c->serializer->start_embed (*this);
|
|
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
|
|
+
|
|
+ bool defaultLang = false;
|
|
+ if (has_default_lang_sys ())
|
|
+ {
|
|
+ c->serializer->push ();
|
|
+ const LangSys& ls = this+defaultLangSys;
|
|
+ bool ret = ls.subset (c, l);
|
|
+ if (!ret && tag && *tag != HB_TAG ('D', 'F', 'L', 'T'))
|
|
+ {
|
|
+ c->serializer->pop_discard ();
|
|
+ out->defaultLangSys = 0;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ c->serializer->add_link (out->defaultLangSys, c->serializer->pop_pack ());
|
|
+ defaultLang = true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index);
|
|
+ if (active_langsys)
|
|
+ {
|
|
+ unsigned count = langSys.len;
|
|
+ + hb_zip (langSys, hb_range (count))
|
|
+ | hb_filter (active_langsys, hb_second)
|
|
+ | hb_map (hb_first)
|
|
+ | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
|
|
+ | hb_apply (subset_record_array (l, &(out->langSys), this))
|
|
+ ;
|
|
+ }
|
|
+
|
|
+ return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB);
|
|
+ }
|
|
+
|
|
+ bool sanitize (hb_sanitize_context_t *c,
|
|
+ const Record_sanitize_closure_t * = nullptr) const
|
|
+ {
|
|
+ TRACE_SANITIZE (this);
|
|
+ return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
|
|
+ }
|
|
+
|
|
+ protected:
|
|
+ Offset16To<LangSys>
|
|
+ defaultLangSys; /* Offset to DefaultLangSys table--from
|
|
+ * beginning of Script table--may be Null */
|
|
+ RecordArrayOf<LangSys>
|
|
+ langSys; /* Array of LangSysRecords--listed
|
|
+ * alphabetically by LangSysTag */
|
|
+ public:
|
|
+ DEFINE_SIZE_ARRAY_SIZED (4, langSys);
|
|
+};
|
|
+struct RecordListOfScript : RecordListOf<Script>
|
|
+{
|
|
+ bool subset (hb_subset_context_t *c,
|
|
+ hb_subset_layout_context_t *l) const
|
|
+ {
|
|
+ TRACE_SUBSET (this);
|
|
+ auto *out = c->serializer->start_embed (*this);
|
|
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
|
|
+
|
|
+ unsigned count = this->len;
|
|
+ for (auto _ : + hb_zip (*this, hb_range (count)))
|
|
+ {
|
|
+ auto snap = c->serializer->snapshot ();
|
|
+ l->cur_script_index = _.second;
|
|
+ bool ret = _.first.subset (l, this);
|
|
+ if (!ret) c->serializer->revert (snap);
|
|
+ else out->len++;
|
|
+ }
|
|
+
|
|
+ return_trace (true);
|
|
+ }
|
|
+};
|
|
+
|
|
+struct RangeRecord
|
|
+{
|
|
+ int cmp (hb_codepoint_t g) const
|
|
+ { return g < first ? -1 : g <= last ? 0 : +1; }
|
|
+
|
|
+ bool sanitize (hb_sanitize_context_t *c) const
|
|
+ {
|
|
+ TRACE_SANITIZE (this);
|
|
+ return_trace (c->check_struct (this));
|
|
+ }
|
|
+
|
|
+ bool intersects (const hb_set_t *glyphs) const
|
|
+ { return glyphs->intersects (first, last); }
|
|
+
|
|
+ template <typename set_t>
|
|
+ bool collect_coverage (set_t *glyphs) const
|
|
+ { return glyphs->add_range (first, last); }
|
|
+
|
|
+ HBGlyphID first; /* First GlyphID in the range */
|
|
+ HBGlyphID last; /* Last GlyphID in the range */
|
|
+ HBUINT16 value; /* Value */
|
|
+ public:
|
|
+ DEFINE_SIZE_STATIC (6);
|
|
+};
|
|
+DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
|
|
+
|
|
+typedef RecordListOfScript ScriptList;
|
|
+#endif // ENABLE_ICCARM
|
|
+
|
|
typedef RecordListOf<Feature> FeatureList;
|
|
|
|
|
|
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
|
|
index c17bf92..f046c08 100644
|
|
--- a/src/hb-ot-layout-gsubgpos.hh
|
|
+++ b/src/hb-ot-layout-gsubgpos.hh
|
|
@@ -535,7 +535,17 @@ struct hb_ot_apply_context_t :
|
|
bool prev ()
|
|
{
|
|
assert (num_items > 0);
|
|
- while (idx > num_items - 1)
|
|
+ /* The alternate condition below is faster at string boundaries,
|
|
+ * but produces subpar "unsafe-to-concat" values. */
|
|
+ unsigned stop = num_items - 1;
|
|
+ if (c->buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT)
|
|
+ stop = 1 - 1;
|
|
+ /*When looking back, limit how far we search; this function is mostly
|
|
+ * used for looking back for base glyphs when attaching marks. If we
|
|
+ * don't limit, we can get O(n^2) behavior where n is the number of
|
|
+ * consecutive marks. */
|
|
+ stop = (unsigned) hb_max ((int) stop, (int) idx - HB_MAX_CONTEXT_LENGTH);
|
|
+ while (idx > stop)
|
|
{
|
|
idx--;
|
|
const hb_glyph_info_t &info = c->buffer->out_info[idx];
|
|
diff --git a/src/hb-static.cc b/src/hb-static.cc
|
|
index ec4b241..bef2ce9 100644
|
|
--- a/src/hb-static.cc
|
|
+++ b/src/hb-static.cc
|
|
@@ -39,8 +39,13 @@
|
|
#ifndef HB_NO_VISIBILITY
|
|
#include "hb-ot-name-language-static.hh"
|
|
|
|
+#ifndef ENABLE_ICCARM
|
|
uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
|
|
/*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
|
|
+#else
|
|
+uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {0};
|
|
+/*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {0};
|
|
+#endif
|
|
|
|
DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF};
|
|
DEFINE_NULL_NAMESPACE_BYTES (OT, VarIdx) = {0xFF,0xFF,0xFF,0xFF};
|