diff options
Diffstat (limited to 'gfx/harfbuzz')
-rw-r--r-- | gfx/harfbuzz/NEWS | 13 | ||||
-rw-r--r-- | gfx/harfbuzz/README.md | 6 | ||||
-rw-r--r-- | gfx/harfbuzz/configure.ac | 8 | ||||
-rw-r--r-- | gfx/harfbuzz/moz.yaml | 4 | ||||
-rw-r--r-- | gfx/harfbuzz/src/OT/Layout/GDEF/GDEF.hh | 50 | ||||
-rw-r--r-- | gfx/harfbuzz/src/hb-buffer.cc | 44 | ||||
-rw-r--r-- | gfx/harfbuzz/src/hb-buffer.h | 6 | ||||
-rw-r--r-- | gfx/harfbuzz/src/hb-buffer.hh | 1 | ||||
-rw-r--r-- | gfx/harfbuzz/src/hb-common.h | 7 | ||||
-rw-r--r-- | gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh | 5 | ||||
-rw-r--r-- | gfx/harfbuzz/src/hb-ot-os2-table.hh | 8 | ||||
-rw-r--r-- | gfx/harfbuzz/src/hb-ot-shape.cc | 9 | ||||
-rw-r--r-- | gfx/harfbuzz/src/hb-serialize.hh | 60 | ||||
-rw-r--r-- | gfx/harfbuzz/src/hb-version.h | 6 | ||||
-rw-r--r-- | gfx/harfbuzz/src/hb-wasm-shape.cc | 6 |
15 files changed, 181 insertions, 52 deletions
diff --git a/gfx/harfbuzz/NEWS b/gfx/harfbuzz/NEWS index 2d6a4a7d6b..e94c6a8937 100644 --- a/gfx/harfbuzz/NEWS +++ b/gfx/harfbuzz/NEWS @@ -1,3 +1,16 @@ +Overview of changes leading to 8.4.0 +Saturday, March 29, 2024 +==================================== +- Add /bigobj to MSVC compiler flags in meson build, to fix building hb-subset.cc +- Specify minimum versions of various dependencies in meson and autotools build. +- When subsetting, place variation store at the end of “GDEF” table to fix + shaping issues with some versions of Adobe InDesign. +- Various build fixes. + +- New API: ++hb_buffer_set_random_state() ++hb_buffer_get_random_state() + Overview of changes leading to 8.3.1 Saturday, March 16, 2024 ==================================== diff --git a/gfx/harfbuzz/README.md b/gfx/harfbuzz/README.md index d11c489f10..da4de65cf0 100644 --- a/gfx/harfbuzz/README.md +++ b/gfx/harfbuzz/README.md @@ -72,9 +72,9 @@ For a comparison of old vs new HarfBuzz memory consumption see [this][10]. ## Name -HarfBuzz (حرفباز) is my Persian translation of “[OpenType][1]”, -transliterated using the Latin script. It sports a second meaning, but that -ain’t translatable. +HarfBuzz (حرفباز) is the literal Persian translation of “[OpenType][1]”, +transliterated using the Latin script. It also means "talkative" or +"glib" (also a nod to the GNOME project where HarfBuzz originates from). > Background: Originally there was this font format called TrueType. People and > companies started calling their type engines all things ending in Type: diff --git a/gfx/harfbuzz/configure.ac b/gfx/harfbuzz/configure.ac index d7ac9333e2..40f5994e85 100644 --- a/gfx/harfbuzz/configure.ac +++ b/gfx/harfbuzz/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.64]) AC_INIT([HarfBuzz], - [8.3.1], + [8.4.0], [https://github.com/harfbuzz/harfbuzz/issues/new], [harfbuzz], [http://harfbuzz.org/]) @@ -132,7 +132,7 @@ AC_ARG_WITH(glib, [Use glib @<:@default=auto@:>@])],, [with_glib=auto]) have_glib=false -GLIB_DEPS="glib-2.0 >= 2.19.1" +GLIB_DEPS="glib-2.0 >= 2.30" AC_SUBST(GLIB_DEPS) if test "x$with_glib" = "xyes" -o "x$with_glib" = "xauto"; then PKG_CHECK_MODULES(GLIB, $GLIB_DEPS, have_glib=true, :) @@ -193,7 +193,7 @@ AC_ARG_WITH(cairo, [with_cairo=auto]) have_cairo=false if test "x$with_cairo" = "xyes" -o "x$with_cairo" = "xauto"; then - PKG_CHECK_MODULES(CAIRO, cairo >= 1.8.0, have_cairo=true, :) + PKG_CHECK_MODULES(CAIRO, cairo >= 1.10, have_cairo=true, :) save_libs=$LIBS LIBS="$LIBS $CAIRO_LIBS" AC_CHECK_FUNCS(cairo_user_font_face_set_render_color_glyph_func) @@ -242,7 +242,7 @@ AC_ARG_WITH(icu, [with_icu=auto]) have_icu=false if test "x$with_icu" = "xyes" -o "x$with_icu" = "xbuiltin" -o "x$with_icu" = "xauto"; then - PKG_CHECK_MODULES(ICU, icu-uc, have_icu=true, :) + PKG_CHECK_MODULES(ICU, icu-uc >= 49.0, have_icu=true, :) fi if test \( "x$with_icu" = "xyes" -o "x$with_icu" = "xbuiltin" \) -a "x$have_icu" != "xtrue"; then AC_MSG_ERROR([icu support requested but icu-uc not found]) diff --git a/gfx/harfbuzz/moz.yaml b/gfx/harfbuzz/moz.yaml index 182f7f4c28..68f979fc84 100644 --- a/gfx/harfbuzz/moz.yaml +++ b/gfx/harfbuzz/moz.yaml @@ -20,11 +20,11 @@ origin: # Human-readable identifier for this version/release # Generally "version NNN", "tag SSS", "bookmark SSS" - release: 8.3.1 (2024-03-17T07:50:59+02:00). + release: 8.4.0 (2024-03-29T16:32:00+02:00). # Revision to pull in # Must be a long or short commit SHA (long preferred) - revision: 8.3.1 + revision: 8.4.0 # The package's license, where possible using the mnemonic from # https://spdx.org/licenses/ diff --git a/gfx/harfbuzz/src/OT/Layout/GDEF/GDEF.hh b/gfx/harfbuzz/src/OT/Layout/GDEF/GDEF.hh index 475e6d74d1..317b96c714 100644 --- a/gfx/harfbuzz/src/OT/Layout/GDEF/GDEF.hh +++ b/gfx/harfbuzz/src/OT/Layout/GDEF/GDEF.hh @@ -663,21 +663,16 @@ struct GDEFVersion1_2 auto *out = c->serializer->start_embed (*this); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - out->version.major = version.major; - out->version.minor = version.minor; - bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true); - bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this); - bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true); - - bool subset_markglyphsetsdef = false; + // Push var store first (if it's needed) so that it's last in the + // serialization order. Some font consumers assume that varstore runs to + // the end of the GDEF table. + // See: https://github.com/harfbuzz/harfbuzz/issues/4636 auto snapshot_version0 = c->serializer->snapshot (); - if (version.to_int () >= 0x00010002u) - { - if (unlikely (!c->serializer->embed (markGlyphSetsDef))) return_trace (false); - subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this); - } + if (unlikely (version.to_int () >= 0x00010002u && !c->serializer->embed (markGlyphSetsDef))) + return_trace (false); bool subset_varstore = false; + unsigned varstore_index = (unsigned) -1; auto snapshot_version2 = c->serializer->snapshot (); if (version.to_int () >= 0x00010003u) { @@ -690,35 +685,58 @@ struct GDEFVersion1_2 { item_variations_t item_vars; if (item_vars.instantiate (this+varStore, c->plan, true, true, - c->plan->gdef_varstore_inner_maps.as_array ())) + c->plan->gdef_varstore_inner_maps.as_array ())) { subset_varstore = out->varStore.serialize_serialize (c->serializer, item_vars.has_long_word (), c->plan->axis_tags, item_vars.get_region_list (), item_vars.get_vardata_encodings ()); + varstore_index = c->serializer->last_added_child_index(); + } remap_varidx_after_instantiation (item_vars.get_varidx_map (), c->plan->layout_variation_idx_delta_map); } } else + { subset_varstore = out->varStore.serialize_subset (c, varStore, this, c->plan->gdef_varstore_inner_maps.as_array ()); + varstore_index = c->serializer->last_added_child_index(); + } + } + + out->version.major = version.major; + out->version.minor = version.minor; + + if (!subset_varstore && version.to_int () >= 0x00010002u) { + c->serializer->revert (snapshot_version2); } + bool subset_markglyphsetsdef = false; + if (version.to_int () >= 0x00010002u) + { + subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this); + } if (subset_varstore) { out->version.minor = 3; c->plan->has_gdef_varstore = true; } else if (subset_markglyphsetsdef) { - out->version.minor = 2; - c->serializer->revert (snapshot_version2); + out->version.minor = 2; } else { out->version.minor = 0; c->serializer->revert (snapshot_version0); } + bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true); + bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this); + bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true); bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this); + if (subset_varstore && varstore_index != (unsigned) -1) { + c->serializer->repack_last(varstore_index); + } + return_trace (subset_glyphclassdef || subset_attachlist || subset_ligcaretlist || subset_markattachclassdef || (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) || @@ -1013,7 +1031,7 @@ struct GDEF if (!has_var_store ()) return; const ItemVariationStore &var_store = get_var_store (); float *store_cache = var_store.create_cache (); - + unsigned new_major = 0, new_minor = 0; unsigned last_major = (layout_variation_indices->get_min ()) >> 16; for (unsigned idx : layout_variation_indices->iter ()) diff --git a/gfx/harfbuzz/src/hb-buffer.cc b/gfx/harfbuzz/src/hb-buffer.cc index 934c6c2129..d621a7cc55 100644 --- a/gfx/harfbuzz/src/hb-buffer.cc +++ b/gfx/harfbuzz/src/hb-buffer.cc @@ -309,6 +309,7 @@ hb_buffer_t::clear () deallocate_var_all (); serial = 0; + random_state = 1; scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; } @@ -1359,6 +1360,49 @@ hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer) return buffer->not_found; } +/** + * hb_buffer_set_random_state: + * @buffer: An #hb_buffer_t + * @state: the new random state + * + * Sets the random state of the buffer. The state changes + * every time a glyph uses randomness (eg. the `rand` + * OpenType feature). This function together with + * hb_buffer_get_random_state() allow for transferring + * the current random state to a subsequent buffer, to + * get better randomness distribution. + * + * Defaults to 1 and when buffer contents are cleared. + * A value of 0 disables randomness during shaping. + * + * Since: 8.4.0 + **/ +void +hb_buffer_set_random_state (hb_buffer_t *buffer, + unsigned state) +{ + if (unlikely (hb_object_is_immutable (buffer))) + return; + + buffer->random_state = state; +} + +/** + * hb_buffer_get_random_state: + * @buffer: An #hb_buffer_t + * + * See hb_buffer_set_random_state(). + * + * Return value: + * The @buffer random state + * + * Since: 8.4.0 + **/ +unsigned +hb_buffer_get_random_state (const hb_buffer_t *buffer) +{ + return buffer->random_state; +} /** * hb_buffer_clear_contents: diff --git a/gfx/harfbuzz/src/hb-buffer.h b/gfx/harfbuzz/src/hb-buffer.h index 3573127ff0..f75fe96b21 100644 --- a/gfx/harfbuzz/src/hb-buffer.h +++ b/gfx/harfbuzz/src/hb-buffer.h @@ -487,6 +487,12 @@ hb_buffer_set_not_found_glyph (hb_buffer_t *buffer, HB_EXTERN hb_codepoint_t hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer); +HB_EXTERN void +hb_buffer_set_random_state (hb_buffer_t *buffer, + unsigned state); + +HB_EXTERN unsigned +hb_buffer_get_random_state (const hb_buffer_t *buffer); /* * Content API. diff --git a/gfx/harfbuzz/src/hb-buffer.hh b/gfx/harfbuzz/src/hb-buffer.hh index f04ad58f11..0a198722d6 100644 --- a/gfx/harfbuzz/src/hb-buffer.hh +++ b/gfx/harfbuzz/src/hb-buffer.hh @@ -116,6 +116,7 @@ struct hb_buffer_t uint8_t allocated_var_bits; uint8_t serial; + uint32_t random_state; hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */ unsigned int max_len; /* Maximum allowed len. */ int max_ops; /* Maximum allowed operations. */ diff --git a/gfx/harfbuzz/src/hb-common.h b/gfx/harfbuzz/src/hb-common.h index dfdefc627e..533de91562 100644 --- a/gfx/harfbuzz/src/hb-common.h +++ b/gfx/harfbuzz/src/hb-common.h @@ -49,8 +49,8 @@ #if defined (_AIX) # include <sys/inttypes.h> -#elif defined (_MSC_VER) && _MSC_VER < 1800 -/* VS 2013 (_MSC_VER 1800) has inttypes.h */ +#elif defined (_MSC_VER) && _MSC_VER < 1600 +/* VS 2010 (_MSC_VER 1600) has stdint.h */ typedef __int8 int8_t; typedef unsigned __int8 uint8_t; typedef __int16 int16_t; @@ -59,6 +59,9 @@ typedef __int32 int32_t; typedef unsigned __int32 uint32_t; typedef __int64 int64_t; typedef unsigned __int64 uint64_t; +#elif defined (_MSC_VER) && _MSC_VER < 1800 +/* VS 2013 (_MSC_VER 1800) has inttypes.h */ +# include <stdint.h> #else # include <inttypes.h> #endif diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh index 162179d08a..c65ea32b8a 100644 --- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh +++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh @@ -723,7 +723,6 @@ struct hb_ot_apply_context_t : bool auto_zwj = true; bool per_syllable = false; bool random = false; - uint32_t random_state = 1; unsigned new_syllables = (unsigned) -1; signed last_base = -1; // GPOS uses @@ -788,8 +787,8 @@ struct hb_ot_apply_context_t : uint32_t random_number () { /* http://www.cplusplus.com/reference/random/minstd_rand/ */ - random_state = random_state * 48271 % 2147483647; - return random_state; + buffer->random_state = buffer->random_state * 48271 % 2147483647; + return buffer->random_state; } bool match_properties_mark (hb_codepoint_t glyph, diff --git a/gfx/harfbuzz/src/hb-ot-os2-table.hh b/gfx/harfbuzz/src/hb-ot-os2-table.hh index 8c2e696f56..43b58d9bbf 100644 --- a/gfx/harfbuzz/src/hb-ot-os2-table.hh +++ b/gfx/harfbuzz/src/hb-ot-os2-table.hh @@ -223,7 +223,7 @@ struct OS2 } } - return num ? (unsigned) roundf (total_width / num) : 0; + return num ? (unsigned) roundf ((double) total_width / (double) num) : 0; } bool subset (hb_subset_context_t *c) const @@ -284,12 +284,12 @@ struct OS2 os2_prime->usWidthClass = width_class; } - if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES) - return_trace (true); - os2_prime->usFirstCharIndex = hb_min (0xFFFFu, c->plan->unicodes.get_min ()); os2_prime->usLastCharIndex = hb_min (0xFFFFu, c->plan->unicodes.get_max ()); + if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES) + return_trace (true); + _update_unicode_ranges (&c->plan->unicodes, os2_prime->ulUnicodeRange); return_trace (true); diff --git a/gfx/harfbuzz/src/hb-ot-shape.cc b/gfx/harfbuzz/src/hb-ot-shape.cc index 90f596ae79..148830022e 100644 --- a/gfx/harfbuzz/src/hb-ot-shape.cc +++ b/gfx/harfbuzz/src/hb-ot-shape.cc @@ -155,7 +155,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, #endif bool has_gpos = !disable_gpos && hb_ot_layout_has_positioning (face); if (false) - ; + {} #ifndef HB_NO_AAT_SHAPE /* Prefer GPOS over kerx if GSUB is present; * https://github.com/harfbuzz/harfbuzz/issues/3008 */ @@ -167,15 +167,16 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, if (!plan.apply_kerx && (!has_gpos_kern || !plan.apply_gpos)) { + if (false) {} #ifndef HB_NO_AAT_SHAPE - if (has_kerx) + else if (has_kerx) plan.apply_kerx = true; - else #endif #ifndef HB_NO_OT_KERN - if (hb_ot_layout_has_kerning (face)) + else if (hb_ot_layout_has_kerning (face)) plan.apply_kern = true; #endif + else {} } plan.apply_fallback_kern = !(plan.apply_gpos || plan.apply_kerx || plan.apply_kern); diff --git a/gfx/harfbuzz/src/hb-serialize.hh b/gfx/harfbuzz/src/hb-serialize.hh index 73634e6b93..e988451eb3 100644 --- a/gfx/harfbuzz/src/hb-serialize.hh +++ b/gfx/harfbuzz/src/hb-serialize.hh @@ -91,6 +91,26 @@ struct hb_serialize_context_t } #endif + bool add_virtual_link (objidx_t objidx) + { + if (!objidx) + return false; + + auto& link = *virtual_links.push (); + if (virtual_links.in_error ()) + return false; + + link.objidx = objidx; + // Remaining fields were previously zero'd by push(): + // link.width = 0; + // link.is_signed = 0; + // link.whence = 0; + // link.position = 0; + // link.bias = 0; + + return true; + } + friend void swap (object_t& a, object_t& b) noexcept { hb_swap (a.head, b.head); @@ -469,16 +489,40 @@ struct hb_serialize_context_t assert (current); - auto& link = *current->virtual_links.push (); - if (current->virtual_links.in_error ()) + if (!current->add_virtual_link(objidx)) err (HB_SERIALIZE_ERROR_OTHER); + } - link.width = 0; - link.objidx = objidx; - link.is_signed = 0; - link.whence = 0; - link.position = 0; - link.bias = 0; + objidx_t last_added_child_index() const { + if (unlikely (in_error ())) return (objidx_t) -1; + + assert (current); + if (!bool(current->real_links)) { + return (objidx_t) -1; + } + + return current->real_links[current->real_links.length - 1].objidx; + } + + // For the current object ensure that the sub-table bytes for child objidx are always placed + // after the subtable bytes for any other existing children. This only ensures that the + // repacker will not move the target subtable before the other children + // (by adding virtual links). It is up to the caller to ensure the initial serialization + // order is correct. + void repack_last(objidx_t objidx) { + if (unlikely (in_error ())) return; + + if (!objidx) + return; + + assert (current); + for (auto& l : current->real_links) { + if (l.objidx == objidx) { + continue; + } + + packed[l.objidx]->add_virtual_link(objidx); + } } template <typename T> diff --git a/gfx/harfbuzz/src/hb-version.h b/gfx/harfbuzz/src/hb-version.h index d90e36391c..68681874ca 100644 --- a/gfx/harfbuzz/src/hb-version.h +++ b/gfx/harfbuzz/src/hb-version.h @@ -47,20 +47,20 @@ HB_BEGIN_DECLS * * The minor component of the library version available at compile-time. */ -#define HB_VERSION_MINOR 3 +#define HB_VERSION_MINOR 4 /** * 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 "8.3.1" +#define HB_VERSION_STRING "8.4.0" /** * HB_VERSION_ATLEAST: diff --git a/gfx/harfbuzz/src/hb-wasm-shape.cc b/gfx/harfbuzz/src/hb-wasm-shape.cc index a70b766646..a8b91879a4 100644 --- a/gfx/harfbuzz/src/hb-wasm-shape.cc +++ b/gfx/harfbuzz/src/hb-wasm-shape.cc @@ -240,7 +240,7 @@ acquire_shape_plan (hb_face_t *face, goto fail; } - func = wasm_runtime_lookup_function (module_inst, "shape_plan_create", nullptr); + func = wasm_runtime_lookup_function (module_inst, "shape_plan_create"); if (func) { wasm_val_t results[1]; @@ -297,7 +297,7 @@ release_shape_plan (const hb_wasm_face_data_t *face_data, if (plan->wasm_shape_planptr) { - auto *func = wasm_runtime_lookup_function (module_inst, "shape_plan_destroy", nullptr); + auto *func = wasm_runtime_lookup_function (module_inst, "shape_plan_destroy"); if (func) { wasm_val_t arguments[1]; @@ -395,7 +395,7 @@ retry: goto fail; } - func = wasm_runtime_lookup_function (module_inst, "shape", nullptr); + func = wasm_runtime_lookup_function (module_inst, "shape"); if (unlikely (!func)) { DEBUG_MSG (WASM, module_inst, "Shape function not found."); |