From aaecaa4c0ee5034c4d8becb57ec249c7ad404c0f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 24 Feb 2025 22:03:00 -0700 Subject: [PATCH 1/2] [vector] Disallow accidental creation of transient vectors Fix sites that were doing this under our feet. This lowers precision of some instancing operations from double to float, which modifies a few results by rounding error. TODO: Update tests. --- src/hb-ot-hdmx-table.hh | 2 +- src/hb-ot-hmtx-table.hh | 2 +- src/hb-ot-var-common.hh | 28 ++++++++++++++-------------- src/hb-subset-plan.hh | 6 +++--- src/hb-vector.hh | 2 +- src/test-tuple-varstore.cc | 8 ++++---- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 8582dbe27..5c187ebbb 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -95,7 +95,7 @@ struct hdmx bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it, - const hb_vector_t &new_to_old_gid_list, + hb_array_t new_to_old_gid_list, unsigned num_glyphs) { TRACE_SERIALIZE (this); diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh index 493bc6e7a..8e44f143b 100644 --- a/src/hb-ot-hmtx-table.hh +++ b/src/hb-ot-hmtx-table.hh @@ -182,7 +182,7 @@ struct hmtxvmtx hb_requires (hb_is_iterator (Iterator))> void serialize (hb_serialize_context_t *c, Iterator it, - const hb_vector_t new_to_old_gid_list, + hb_array_t new_to_old_gid_list, unsigned num_long_metrics, unsigned total_num_metrics) { diff --git a/src/hb-ot-var-common.hh b/src/hb-ot-var-common.hh index 3ab58ae30..2e02f9a99 100644 --- a/src/hb-ot-var-common.hh +++ b/src/hb-ot-var-common.hh @@ -231,9 +231,9 @@ struct tuple_delta_t /* indices_length = point_count, indice[i] = 1 means point i is referenced */ hb_vector_t indices; - hb_vector_t deltas_x; + hb_vector_t deltas_x; /* empty for cvar tuples */ - hb_vector_t deltas_y; + hb_vector_t deltas_y; /* compiled data: header and deltas * compiled point data is saved in a hashmap within tuple_variations_t cause @@ -299,9 +299,9 @@ struct tuple_delta_t return *this; } - tuple_delta_t& operator *= (double scalar) + tuple_delta_t& operator *= (float scalar) { - if (scalar == 1.0) + if (scalar == 1.0f) return *this; unsigned num = indices.length; @@ -514,9 +514,9 @@ struct tuple_delta_t bool compile_deltas () { return compile_deltas (indices, deltas_x, deltas_y, compiled_deltas); } - static bool compile_deltas (const hb_vector_t &point_indices, - const hb_vector_t &x_deltas, - const hb_vector_t &y_deltas, + static bool compile_deltas (hb_array_t point_indices, + hb_array_t x_deltas, + hb_array_t y_deltas, hb_vector_t &compiled_deltas /* OUT */) { hb_vector_t rounded_deltas; @@ -692,7 +692,7 @@ struct tuple_delta_t if (ref_count == count) return true; - hb_vector_t opt_deltas_x, opt_deltas_y; + hb_vector_t opt_deltas_x, opt_deltas_y; bool is_comp_glyph_wo_deltas = (is_composite && ref_count == 0); if (is_comp_glyph_wo_deltas) { @@ -875,7 +875,7 @@ struct TupleVariationData private: /* referenced point set->compiled point data map */ - hb_hashmap_t*, hb_vector_t> point_data_map; + hb_hashmap_t*, hb_vector_t> point_data_map; /* referenced point set-> count map, used in finding shared points */ hb_hashmap_t*, unsigned> point_set_count_map; @@ -883,7 +883,7 @@ struct TupleVariationData * shared_points_bytes is a pointer to some value in the point_data_map, * which will be freed during map destruction. Save it for serialization, so * no need to do find_shared_points () again */ - hb_vector_t *shared_points_bytes = nullptr; + hb_vector_t *shared_points_bytes = nullptr; /* total compiled byte size as TupleVariationData format, initialized to 0 */ unsigned compiled_byte_size = 0; @@ -1244,7 +1244,7 @@ struct TupleVariationData for (auto& tuple: tuple_vars) { const hb_vector_t* points_set = &(tuple.indices); - hb_vector_t *points_data; + hb_vector_t *points_data; if (unlikely (!point_data_map.has (points_set, &points_data))) return false; @@ -1289,20 +1289,20 @@ struct TupleVariationData TRACE_SERIALIZE (this); if (is_gvar && shared_points_bytes) { - hb_bytes_t s (shared_points_bytes->arrayZ, shared_points_bytes->length); + hb_ubytes_t s (shared_points_bytes->arrayZ, shared_points_bytes->length); s.copy (c); } for (const auto& tuple: tuple_vars) { const hb_vector_t* points_set = &(tuple.indices); - hb_vector_t *point_data; + hb_vector_t *point_data; if (!point_data_map.has (points_set, &point_data)) return_trace (false); if (!is_gvar || point_data != shared_points_bytes) { - hb_bytes_t s (point_data->arrayZ, point_data->length); + hb_ubytes_t s (point_data->arrayZ, point_data->length); s.copy (c); } diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh index fe80c08bc..2d1bea231 100644 --- a/src/hb-subset-plan.hh +++ b/src/hb-subset-plan.hh @@ -114,9 +114,9 @@ struct contour_point_vector_t : hb_vector_t hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0])); } - bool add_deltas (const hb_vector_t deltas_x, - const hb_vector_t deltas_y, - const hb_vector_t indices) + bool add_deltas (hb_array_t deltas_x, + hb_array_t deltas_y, + hb_array_t indices) { if (indices.length != deltas_x.length || indices.length != deltas_y.length) diff --git a/src/hb-vector.hh b/src/hb-vector.hh index 679c92151..89e4cd337 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -53,7 +53,7 @@ struct hb_vector_t } template - hb_vector_t (const Iterable &o) : hb_vector_t () + explicit hb_vector_t (const Iterable &o) : hb_vector_t () { extend (o); } diff --git a/src/test-tuple-varstore.cc b/src/test-tuple-varstore.cc index 1e07d27d3..afba20f28 100644 --- a/src/test-tuple-varstore.cc +++ b/src/test-tuple-varstore.cc @@ -66,7 +66,7 @@ test_decompile_cvar () assert (tuple_variations.tuple_vars[0].axis_tuples.get (axis_tag) == Triple (-1.0, -1.0, 0.0)); assert (tuple_variations.tuple_vars[1].axis_tuples.get (axis_tag) == Triple (0.0, 1.0, 1.0)); - hb_vector_t deltas_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.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -3.0, 1.0, 0.0, -1.0, 0.0, -3.0, 1.0, 0.0, -37.0, -37.0, -26.0, -26.0, 0.0, 0.0, 0.0, -3.0, 0.0, 0.0, 0.0, 0.0, 0.0, -3.0, 0.0, 2.0, -29.0, -29.0, -20.0, -20.0, 0.0, 0.0, 0.0, 1.0, -29.0, -29.0, -20.0, -20.0, 0.0, 0.0, 0.0, 1.0}; + hb_vector_t deltas_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.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -3.0, 1.0, 0.0, -1.0, 0.0, -3.0, 1.0, 0.0, -37.0, -37.0, -26.0, -26.0, 0.0, 0.0, 0.0, -3.0, 0.0, 0.0, 0.0, 0.0, 0.0, -3.0, 0.0, 2.0, -29.0, -29.0, -20.0, -20.0, 0.0, 0.0, 0.0, 1.0, -29.0, -29.0, -20.0, -20.0, 0.0, 0.0, 0.0, 1.0}; for (unsigned i = 0; i < 65; i++) { if (i < 23) @@ -78,7 +78,7 @@ test_decompile_cvar () } } - hb_vector_t deltas_2 {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.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 5.0, -3.0, 0.0, 1.0, 0.0, 5.0, -3.0, 0.0, 97.0, 97.0, 68.0, 68.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 1.0, -1.0, 1.0, 7.0, -1.0, -5.0, 73.0, 73.0, 53.0, 53.0, 0.0, 0.0, 0.0, -1.0, 73.0, 73.0, 53.0, 53.0, 0.0, 0.0, 0.0, -1.0}; + hb_vector_t deltas_2 {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.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 5.0, -3.0, 0.0, 1.0, 0.0, 5.0, -3.0, 0.0, 97.0, 97.0, 68.0, 68.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 1.0, -1.0, 1.0, 7.0, -1.0, -5.0, 73.0, 73.0, 53.0, 53.0, 0.0, 0.0, 0.0, -1.0, 73.0, 73.0, 53.0, 53.0, 0.0, 0.0, 0.0, -1.0}; for (unsigned i = 0 ; i < 65; i++) { if (i < 23) @@ -106,9 +106,9 @@ test_decompile_cvar () assert (tuple_variations.tuple_vars[0].axis_tuples.get (axis_tag) == Triple (-1.0, -1.0, 0.0)); assert (tuple_variations.tuple_vars[1].axis_tuples.get (axis_tag) == Triple (0.0, 1.0, 1.0)); - hb_vector_t rounded_deltas_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.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1, 0.0, -2, 1, 0.0, -1, 0.0, -2, 1, 0.0, -19, -19, -13, -13, 0.0, 0.0, 0.0, -2, 0.0, 0.0, 0.0, 0.0, 0.0, -2, 0.0, 1, -15, -15, -10.0, -10.0, 0.0, 0.0, 0.0, 1, -15, -15, -10.0, -10.0, 0.0, 0.0, 0.0, 1}; + hb_vector_t rounded_deltas_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.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1, 0.0, -2, 1, 0.0, -1, 0.0, -2, 1, 0.0, -19, -19, -13, -13, 0.0, 0.0, 0.0, -2, 0.0, 0.0, 0.0, 0.0, 0.0, -2, 0.0, 1, -15, -15, -10.0, -10.0, 0.0, 0.0, 0.0, 1, -15, -15, -10.0, -10.0, 0.0, 0.0, 0.0, 1}; - hb_vector_t rounded_deltas_2 {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.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1, 0.0, 4, -2, 0.0, 1, 0.0, 4, -2, 0.0, 68, 68, 48, 48, 0.0, 0.0, 0.0, 4, 0.0, 0.0, 1, -1, 1, 5, -1, -4, 51, 51, 37, 37, 0.0, 0.0, 0.0, -1, 51, 51, 37, 37, 0.0, 0.0, 0.0, -1}; + hb_vector_t rounded_deltas_2 {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.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1, 0.0, 4, -2, 0.0, 1, 0.0, 4, -2, 0.0, 68, 68, 48, 48, 0.0, 0.0, 0.0, 4, 0.0, 0.0, 1, -1, 1, 5, -1, -4, 51, 51, 37, 37, 0.0, 0.0, 0.0, -1, 51, 51, 37, 37, 0.0, 0.0, 0.0, -1}; for (unsigned i = 0; i < 65; i++) { From ea1434b897d4250998154ed95336389e06e28783 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Tue, 25 Feb 2025 19:00:29 +0000 Subject: [PATCH 2/2] Split iup glyf partial instance tests into a separate set which ignores due to IUP rounding differences fonttools. --- ...ht=200-300-500,wdth=80-90.iup_optimize.ttf | Bin 8684 -> 8684 bytes ...efault.all.wght=200-300-500,wdth=80-90.ttf | Bin 8708 -> 8708 bytes ....all.wght=300-600,wdth=85.iup_optimize.ttf | Bin ...e.ABC.default.all.wght=300-600,wdth=85.ttf | Bin 0 -> 7592 bytes ...ht=200-300-500,wdth=80-90.iup_optimize.ttf | Bin 7516 -> 7516 bytes ...efault.all.wght=200-300-500,wdth=80-90.ttf | Bin 7568 -> 7568 bytes ....all.wght=300-600,wdth=85.iup_optimize.ttf | Bin ...osite.default.all.wght=300-600,wdth=85.ttf | Bin 0 -> 6932 bytes .../data/tests/glyf_partial_instancing.tests | 2 -- .../tests/glyf_partial_instancing_iup.tests | 22 ++++++++++++++++++ 10 files changed, 22 insertions(+), 2 deletions(-) rename test/subset/data/expected/{glyf_partial_instancing => glyf_partial_instancing_iup}/Roboto-Variable.ABC.default.all.wght=200-300-500,wdth=80-90.iup_optimize.ttf (94%) rename test/subset/data/expected/{glyf_partial_instancing => glyf_partial_instancing_iup}/Roboto-Variable.ABC.default.all.wght=200-300-500,wdth=80-90.ttf (94%) rename test/subset/data/expected/{glyf_partial_instancing => glyf_partial_instancing_iup}/Roboto-Variable.ABC.default.all.wght=300-600,wdth=85.iup_optimize.ttf (100%) create mode 100644 test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.ABC.default.all.wght=300-600,wdth=85.ttf rename test/subset/data/expected/{glyf_partial_instancing => glyf_partial_instancing_iup}/Roboto-Variable.composite.default.all.wght=200-300-500,wdth=80-90.iup_optimize.ttf (96%) rename test/subset/data/expected/{glyf_partial_instancing => glyf_partial_instancing_iup}/Roboto-Variable.composite.default.all.wght=200-300-500,wdth=80-90.ttf (95%) rename test/subset/data/expected/{glyf_partial_instancing => glyf_partial_instancing_iup}/Roboto-Variable.composite.default.all.wght=300-600,wdth=85.iup_optimize.ttf (100%) create mode 100644 test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.composite.default.all.wght=300-600,wdth=85.ttf create mode 100644 test/subset/data/tests/glyf_partial_instancing_iup.tests diff --git a/test/subset/data/expected/glyf_partial_instancing/Roboto-Variable.ABC.default.all.wght=200-300-500,wdth=80-90.iup_optimize.ttf b/test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.ABC.default.all.wght=200-300-500,wdth=80-90.iup_optimize.ttf similarity index 94% rename from test/subset/data/expected/glyf_partial_instancing/Roboto-Variable.ABC.default.all.wght=200-300-500,wdth=80-90.iup_optimize.ttf rename to test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.ABC.default.all.wght=200-300-500,wdth=80-90.iup_optimize.ttf index edb34365f70b64c90ecda1084a674d1512fd177c..a447b7ba556287ae285868250e3ba91976d3b4a3 100644 GIT binary patch delta 106 zcmaFk{Kk2LGh@a?mpLpUt77;!K3T)a@-{p+b@LRaa7ISa&2N}zb28d)?%>sBWR#q| zjZd3JfRjOV^HaXdj2f(ee|!OgAOE=orRAk1uUvh}A}FS8UzkFRw5#H!^c_ KZhj!ZBM1Ou3?-ca delta 106 zcmaFk{Kk2LGh_NhmpLqfE24QfK3T)a@;N#_d-D{ga7IRv&2N}zb28d&?%>sBWR#e^ zjZd3}pOZmk^HaXdj2bL|e|!OgAOE=orRAk1uUvh}A}FeCUzkFRw5#H!^c@ KYpn0%$PCJWeyAXoS9-9pR8eIsV{o0x_JsyI3uIz<~Piv?ckt>kGD=R~ z%BRgDz{w!G`3c`UMh(`#KfVCLkN;eP((=-hSFXNf5foE4uml2KSzb=&msc2=8<{yd KH~$jg5(EGSASB-a delta 106 zcmZp1X>pn0%$PpWWey9+?CByKpR8eIX)SrKy?F{#I3uIT<~Piv>ckt>kGD=L| z%BRi3&&eRN`3c`UMh%v~KfVCLkN;eP((=-hSFXNf5foK6uml2KSzb=&msc2=8<{yc KHvbaf5(EGTEF|9m diff --git a/test/subset/data/expected/glyf_partial_instancing/Roboto-Variable.ABC.default.all.wght=300-600,wdth=85.iup_optimize.ttf b/test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.ABC.default.all.wght=300-600,wdth=85.iup_optimize.ttf similarity index 100% rename from test/subset/data/expected/glyf_partial_instancing/Roboto-Variable.ABC.default.all.wght=300-600,wdth=85.iup_optimize.ttf rename to test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.ABC.default.all.wght=300-600,wdth=85.iup_optimize.ttf diff --git a/test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.ABC.default.all.wght=300-600,wdth=85.ttf b/test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.ABC.default.all.wght=300-600,wdth=85.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4f5c057613895730c745e4917fefa847b89b2046 GIT binary patch literal 7592 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 B5V8OO delta 43 zcmV+`0M!57I@~&t-~%n>IkDs60Rt1|>$ArK<^};Uv#tp;0S5s90m(N30kh`{brPx& B5V8OO diff --git a/test/subset/data/expected/glyf_partial_instancing/Roboto-Variable.composite.default.all.wght=200-300-500,wdth=80-90.ttf b/test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.composite.default.all.wght=200-300-500,wdth=80-90.ttf similarity index 95% rename from test/subset/data/expected/glyf_partial_instancing/Roboto-Variable.composite.default.all.wght=200-300-500,wdth=80-90.ttf rename to test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.composite.default.all.wght=200-300-500,wdth=80-90.ttf index 4983f0d82b79bf54cfd3ed97f10c4e01ce6c8989..8bfaadef0acee9b50e0889e665dc9bd30fc264e3 100644 GIT binary patch delta 47 zcmV+~0MP%CJCHk&;RC0AS+V5d0RvxSpR>pU`UU|pv%?8e0Sf|yfC9+?H-Ufv0<$0s Fa1z`E5m^8L delta 47 zcmV+~0MP%CJCHk&;RB|8Sh3{c0Rv%Wp|i*W`UU|ov%?8e0Sf_xfC9+?H-Ufv0ka?r Fa1z`c5m^8L diff --git a/test/subset/data/expected/glyf_partial_instancing/Roboto-Variable.composite.default.all.wght=300-600,wdth=85.iup_optimize.ttf b/test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.composite.default.all.wght=300-600,wdth=85.iup_optimize.ttf similarity index 100% rename from test/subset/data/expected/glyf_partial_instancing/Roboto-Variable.composite.default.all.wght=300-600,wdth=85.iup_optimize.ttf rename to test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.composite.default.all.wght=300-600,wdth=85.iup_optimize.ttf diff --git a/test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.composite.default.all.wght=300-600,wdth=85.ttf b/test/subset/data/expected/glyf_partial_instancing_iup/Roboto-Variable.composite.default.all.wght=300-600,wdth=85.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e96c240096f658856affe3adf3d716162c18bb7d GIT binary patch literal 6932 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