summaryrefslogtreecommitdiffstats
path: root/thirdparty
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty')
-rw-r--r--thirdparty/README.md6
-rw-r--r--thirdparty/astcenc/astcenc_entry.cpp2
-rw-r--r--thirdparty/astcenc/astcenc_integer_sequence.cpp8
-rw-r--r--thirdparty/astcenc/astcenc_internal.h32
-rw-r--r--thirdparty/astcenc/astcenc_internal_entry.h1
-rw-r--r--thirdparty/astcenc/astcenc_symbolic_physical.cpp21
-rw-r--r--thirdparty/astcenc/astcenc_vecmathlib_none_4.h17
-rw-r--r--thirdparty/enet/LICENSE2
-rw-r--r--thirdparty/enet/enet/enet.h2
-rw-r--r--thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh308
-rw-r--r--thirdparty/harfbuzz/src/OT/Color/COLR/colrv1-closure.hh50
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh41
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh15
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-common.hh203
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh183
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh262
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout.cc53
-rw-r--r--thirdparty/harfbuzz/src/hb-algs.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-cplusplus.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-face-table-list.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-face.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-kern-table.hh71
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh75
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-common.hh14
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh83
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.cc8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-os2-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-post-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-stat-table.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-tag-table.hh45
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-common.hh94
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh7
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh5
-rw-r--r--thirdparty/harfbuzz/src/hb-repacker.hh18
-rw-r--r--thirdparty/harfbuzz/src/hb-set-digest.hh20
-rw-r--r--thirdparty/harfbuzz/src/hb-set.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-cff-common.hh57
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-cff2.cc3
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-input.cc15
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-instancer-iup.cc68
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-instancer-iup.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-instancer-solver.cc94
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-instancer-solver.hh32
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan-member-list.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.cc185
-rw-r--r--thirdparty/harfbuzz/src/hb-subset.h11
-rw-r--r--thirdparty/harfbuzz/src/hb-version.h4
50 files changed, 1606 insertions, 564 deletions
diff --git a/thirdparty/README.md b/thirdparty/README.md
index db7f361a66..665c188272 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -47,7 +47,7 @@ Files extracted from upstream source:
## astcenc
- Upstream: https://github.com/ARM-software/astc-encoder
-- Version: 4.7.0 (1a51f2915121275038677317c8bf61f1a78b590c, 2024)
+- Version: 4.8.0 (0d6c9047c5ad19640e2d60fdb8f11a16675e7938, 2024)
- License: Apache 2.0
Files extracted from upstream source:
@@ -194,7 +194,7 @@ commits.
## enet
- Upstream: https://github.com/lsalzman/enet
-- Version: git (c44b7d0f7ff21edb702745e4c019d0537928c373, 2024)
+- Version: 1.3.18 (2662c0de09e36f2a2030ccc2c528a3e4c9e8138a, 2024)
- License: MIT
Files extracted from upstream source:
@@ -377,7 +377,7 @@ Files extracted from upstream source:
## harfbuzz
- Upstream: https://github.com/harfbuzz/harfbuzz
-- Version: 8.4.0 (63973005bc07aba599b47fdd4cf788647b601ccd, 2024)
+- Version: 8.5.0 (30485ee8c3d43c553afb9d78b9924cb71c8d2f19, 2024)
- License: MIT
Files extracted from upstream source:
diff --git a/thirdparty/astcenc/astcenc_entry.cpp b/thirdparty/astcenc/astcenc_entry.cpp
index 71efe9cec4..5dc3801606 100644
--- a/thirdparty/astcenc/astcenc_entry.cpp
+++ b/thirdparty/astcenc/astcenc_entry.cpp
@@ -1167,7 +1167,7 @@ astcenc_error astcenc_decompress_image(
return ASTCENC_ERR_OUT_OF_MEM;
}
- image_block blk;
+ image_block blk {};
blk.texel_count = static_cast<uint8_t>(block_x * block_y * block_z);
// Decode mode inferred from the output data type
diff --git a/thirdparty/astcenc/astcenc_integer_sequence.cpp b/thirdparty/astcenc/astcenc_integer_sequence.cpp
index 416750374d..41dc38b74e 100644
--- a/thirdparty/astcenc/astcenc_integer_sequence.cpp
+++ b/thirdparty/astcenc/astcenc_integer_sequence.cpp
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
// ----------------------------------------------------------------------------
-// Copyright 2011-2021 Arm Limited
+// Copyright 2011-2024 Arm Limited
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
@@ -464,10 +464,10 @@ static inline void write_bits(
}
/**
- * @brief Read up to 8 bits at an arbitrary bit offset.
+ * @brief Read up to 16 bits from two bytes.
*
- * The stored value is at most 8 bits, but can be stored at an offset of between 0 and 7 bits so may
- * span two separate bytes in memory.
+ * This function reads a packed N-bit field from two bytes in memory. The stored value must exist
+ * within the two bytes, but can start at an arbitary bit offset and span the two bytes in memory.
*
* @param bitcount The number of bits to read.
* @param bitoffset The bit offset to read from, between 0 and 7.
diff --git a/thirdparty/astcenc/astcenc_internal.h b/thirdparty/astcenc/astcenc_internal.h
index 715028ac8f..df6e07f9ee 100644
--- a/thirdparty/astcenc/astcenc_internal.h
+++ b/thirdparty/astcenc/astcenc_internal.h
@@ -326,10 +326,10 @@ struct partition_info
uint8_t partition_texel_count[BLOCK_MAX_PARTITIONS];
/** @brief The partition of each texel in the block. */
- uint8_t partition_of_texel[BLOCK_MAX_TEXELS];
+ ASTCENC_ALIGNAS uint8_t partition_of_texel[BLOCK_MAX_TEXELS];
/** @brief The list of texels in each partition. */
- uint8_t texels_of_partition[BLOCK_MAX_PARTITIONS][BLOCK_MAX_TEXELS];
+ ASTCENC_ALIGNAS uint8_t texels_of_partition[BLOCK_MAX_PARTITIONS][BLOCK_MAX_TEXELS];
};
/**
@@ -367,19 +367,19 @@ struct decimation_info
* @brief The number of weights that contribute to each texel.
* Value is between 1 and 4.
*/
- uint8_t texel_weight_count[BLOCK_MAX_TEXELS];
+ ASTCENC_ALIGNAS uint8_t texel_weight_count[BLOCK_MAX_TEXELS];
/**
* @brief The weight index of the N weights that are interpolated for each texel.
* Stored transposed to improve vectorization.
*/
- uint8_t texel_weights_tr[4][BLOCK_MAX_TEXELS];
+ ASTCENC_ALIGNAS uint8_t texel_weights_tr[4][BLOCK_MAX_TEXELS];
/**
* @brief The bilinear contribution of the N weights that are interpolated for each texel.
* Value is between 0 and 16, stored transposed to improve vectorization.
*/
- uint8_t texel_weight_contribs_int_tr[4][BLOCK_MAX_TEXELS];
+ ASTCENC_ALIGNAS uint8_t texel_weight_contribs_int_tr[4][BLOCK_MAX_TEXELS];
/**
* @brief The bilinear contribution of the N weights that are interpolated for each texel.
@@ -388,13 +388,13 @@ struct decimation_info
ASTCENC_ALIGNAS float texel_weight_contribs_float_tr[4][BLOCK_MAX_TEXELS];
/** @brief The number of texels that each stored weight contributes to. */
- uint8_t weight_texel_count[BLOCK_MAX_WEIGHTS];
+ ASTCENC_ALIGNAS uint8_t weight_texel_count[BLOCK_MAX_WEIGHTS];
/**
* @brief The list of texels that use a specific weight index.
* Stored transposed to improve vectorization.
*/
- uint8_t weight_texels_tr[BLOCK_MAX_TEXELS][BLOCK_MAX_WEIGHTS];
+ ASTCENC_ALIGNAS uint8_t weight_texels_tr[BLOCK_MAX_TEXELS][BLOCK_MAX_WEIGHTS];
/**
* @brief The bilinear contribution to the N texels that use each weight.
@@ -732,7 +732,11 @@ struct block_size_descriptor
*
* The @c data_[rgba] fields store the image data in an encoded SoA float form designed for easy
* vectorization. Input data is converted to float and stored as values between 0 and 65535. LDR
- * data is stored as direct UNORM data, HDR data is stored as LNS data.
+ * data is stored as direct UNORM data, HDR data is stored as LNS data. They are allocated SIMD
+ * elements over-size to allow vectorized stores of unaligned and partial SIMD lanes (e.g. in a
+ * 6x6x6 block the final row write will read elements 210-217 (vec8) or 214-217 (vec4), which is
+ * two elements above the last real data element). The overspill values are never written to memory,
+ * and would be benign, but the padding avoids hitting undefined behavior.
*
* The @c rgb_lns and @c alpha_lns fields that assigned a per-texel use of HDR are only used during
* decompression. The current compressor will always use HDR endpoint formats when in HDR mode.
@@ -740,16 +744,16 @@ struct block_size_descriptor
struct image_block
{
/** @brief The input (compress) or output (decompress) data for the red color component. */
- ASTCENC_ALIGNAS float data_r[BLOCK_MAX_TEXELS];
+ ASTCENC_ALIGNAS float data_r[BLOCK_MAX_TEXELS + ASTCENC_SIMD_WIDTH - 1];
/** @brief The input (compress) or output (decompress) data for the green color component. */
- ASTCENC_ALIGNAS float data_g[BLOCK_MAX_TEXELS];
+ ASTCENC_ALIGNAS float data_g[BLOCK_MAX_TEXELS + ASTCENC_SIMD_WIDTH - 1];
/** @brief The input (compress) or output (decompress) data for the blue color component. */
- ASTCENC_ALIGNAS float data_b[BLOCK_MAX_TEXELS];
+ ASTCENC_ALIGNAS float data_b[BLOCK_MAX_TEXELS + ASTCENC_SIMD_WIDTH - 1];
/** @brief The input (compress) or output (decompress) data for the alpha color component. */
- ASTCENC_ALIGNAS float data_a[BLOCK_MAX_TEXELS];
+ ASTCENC_ALIGNAS float data_a[BLOCK_MAX_TEXELS + ASTCENC_SIMD_WIDTH - 1];
/** @brief The number of texels in the block. */
uint8_t texel_count;
@@ -957,7 +961,7 @@ struct ASTCENC_ALIGNAS compression_working_buffers
*
* For two planes, second plane starts at @c WEIGHTS_PLANE2_OFFSET offsets.
*/
- uint8_t dec_weights_uquant[WEIGHTS_MAX_BLOCK_MODES * BLOCK_MAX_WEIGHTS];
+ ASTCENC_ALIGNAS uint8_t dec_weights_uquant[WEIGHTS_MAX_BLOCK_MODES * BLOCK_MAX_WEIGHTS];
/** @brief Error of the best encoding combination for each block mode. */
ASTCENC_ALIGNAS float errors_of_best_combination[WEIGHTS_MAX_BLOCK_MODES];
@@ -1111,7 +1115,7 @@ struct symbolic_compressed_block
*
* If dual plane, the second plane starts at @c weights[WEIGHTS_PLANE2_OFFSET].
*/
- uint8_t weights[BLOCK_MAX_WEIGHTS];
+ ASTCENC_ALIGNAS uint8_t weights[BLOCK_MAX_WEIGHTS];
/**
* @brief Get the weight quantization used by this block mode.
diff --git a/thirdparty/astcenc/astcenc_internal_entry.h b/thirdparty/astcenc/astcenc_internal_entry.h
index 2667714781..c283c5acc6 100644
--- a/thirdparty/astcenc/astcenc_internal_entry.h
+++ b/thirdparty/astcenc/astcenc_internal_entry.h
@@ -150,6 +150,7 @@ public:
m_start_count = 0;
m_done_count = 0;
m_task_count = 0;
+ m_callback = nullptr;
m_callback_last_value = 0.0f;
m_callback_min_diff = 1.0f;
}
diff --git a/thirdparty/astcenc/astcenc_symbolic_physical.cpp b/thirdparty/astcenc/astcenc_symbolic_physical.cpp
index c4da678f1c..45d9abb64b 100644
--- a/thirdparty/astcenc/astcenc_symbolic_physical.cpp
+++ b/thirdparty/astcenc/astcenc_symbolic_physical.cpp
@@ -330,12 +330,14 @@ void physical_to_symbolic(
return;
}
+ // Low values span 3 bytes so need two read_bits calls
int vx_low_s = read_bits(8, 12, pcb) | (read_bits(5, 12 + 8, pcb) << 8);
- int vx_high_s = read_bits(8, 25, pcb) | (read_bits(5, 25 + 8, pcb) << 8);
+ int vx_high_s = read_bits(13, 25, pcb);
int vx_low_t = read_bits(8, 38, pcb) | (read_bits(5, 38 + 8, pcb) << 8);
- int vx_high_t = read_bits(8, 51, pcb) | (read_bits(5, 51 + 8, pcb) << 8);
+ int vx_high_t = read_bits(13, 51, pcb);
- int all_ones = vx_low_s == 0x1FFF && vx_high_s == 0x1FFF && vx_low_t == 0x1FFF && vx_high_t == 0x1FFF;
+ int all_ones = vx_low_s == 0x1FFF && vx_high_s == 0x1FFF &&
+ vx_low_t == 0x1FFF && vx_high_t == 0x1FFF;
if ((vx_low_s >= vx_high_s || vx_low_t >= vx_high_t) && !all_ones)
{
@@ -350,12 +352,14 @@ void physical_to_symbolic(
int vx_high_s = read_bits(9, 19, pcb);
int vx_low_t = read_bits(9, 28, pcb);
int vx_high_t = read_bits(9, 37, pcb);
- int vx_low_p = read_bits(9, 46, pcb);
- int vx_high_p = read_bits(9, 55, pcb);
+ int vx_low_r = read_bits(9, 46, pcb);
+ int vx_high_r = read_bits(9, 55, pcb);
- int all_ones = vx_low_s == 0x1FF && vx_high_s == 0x1FF && vx_low_t == 0x1FF && vx_high_t == 0x1FF && vx_low_p == 0x1FF && vx_high_p == 0x1FF;
+ int all_ones = vx_low_s == 0x1FF && vx_high_s == 0x1FF &&
+ vx_low_t == 0x1FF && vx_high_t == 0x1FF &&
+ vx_low_r == 0x1FF && vx_high_r == 0x1FF;
- if ((vx_low_s >= vx_high_s || vx_low_t >= vx_high_t || vx_low_p >= vx_high_p) && !all_ones)
+ if ((vx_low_s >= vx_high_s || vx_low_t >= vx_high_t || vx_low_r >= vx_high_r) && !all_ones)
{
scb.block_type = SYM_BTYPE_ERROR;
return;
@@ -470,8 +474,7 @@ void physical_to_symbolic(
bitpos += 2;
}
}
- scb.partition_index = static_cast<uint16_t>(read_bits(6, 13, pcb) |
- (read_bits(PARTITION_INDEX_BITS - 6, 19, pcb) << 6));
+ scb.partition_index = static_cast<uint16_t>(read_bits(10, 13, pcb));
}
for (int i = 0; i < partition_count; i++)
diff --git a/thirdparty/astcenc/astcenc_vecmathlib_none_4.h b/thirdparty/astcenc/astcenc_vecmathlib_none_4.h
index 1c95c2ff88..be7348eff1 100644
--- a/thirdparty/astcenc/astcenc_vecmathlib_none_4.h
+++ b/thirdparty/astcenc/astcenc_vecmathlib_none_4.h
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
// ----------------------------------------------------------------------------
-// Copyright 2019-2023 Arm Limited
+// Copyright 2019-2024 Arm Limited
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
@@ -556,10 +556,16 @@ ASTCENC_SIMD_INLINE vmask4 operator>(vint4 a, vint4 b)
*/
template <int s> ASTCENC_SIMD_INLINE vint4 lsl(vint4 a)
{
- return vint4(a.m[0] << s,
- a.m[1] << s,
- a.m[2] << s,
- a.m[3] << s);
+ // Cast to unsigned to avoid shift in/out of sign bit undefined behavior
+ unsigned int as0 = static_cast<unsigned int>(a.m[0]) << s;
+ unsigned int as1 = static_cast<unsigned int>(a.m[1]) << s;
+ unsigned int as2 = static_cast<unsigned int>(a.m[2]) << s;
+ unsigned int as3 = static_cast<unsigned int>(a.m[3]) << s;
+
+ return vint4(static_cast<int>(as0),
+ static_cast<int>(as1),
+ static_cast<int>(as2),
+ static_cast<int>(as3));
}
/**
@@ -567,6 +573,7 @@ template <int s> ASTCENC_SIMD_INLINE vint4 lsl(vint4 a)
*/
template <int s> ASTCENC_SIMD_INLINE vint4 lsr(vint4 a)
{
+ // Cast to unsigned to avoid shift in/out of sign bit undefined behavior
unsigned int as0 = static_cast<unsigned int>(a.m[0]) >> s;
unsigned int as1 = static_cast<unsigned int>(a.m[1]) >> s;
unsigned int as2 = static_cast<unsigned int>(a.m[2]) >> s;
diff --git a/thirdparty/enet/LICENSE b/thirdparty/enet/LICENSE
index 6906f8eb0b..ec14b3f09b 100644
--- a/thirdparty/enet/LICENSE
+++ b/thirdparty/enet/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2002-2020 Lee Salzman
+Copyright (c) 2002-2024 Lee Salzman
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
diff --git a/thirdparty/enet/enet/enet.h b/thirdparty/enet/enet/enet.h
index 5232f8a869..ed0dd65247 100644
--- a/thirdparty/enet/enet/enet.h
+++ b/thirdparty/enet/enet/enet.h
@@ -31,7 +31,7 @@ extern "C"
#define ENET_VERSION_MAJOR 1
#define ENET_VERSION_MINOR 3
-#define ENET_VERSION_PATCH 17
+#define ENET_VERSION_PATCH 18
#define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch))
#define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF)
#define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF)
diff --git a/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh b/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh
index 623775a771..835d87f8c6 100644
--- a/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh
+++ b/thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh
@@ -159,23 +159,35 @@ struct hb_colrv1_closure_context_t :
void add_palette_index (unsigned palette_index)
{ palette_indices->add (palette_index); }
+ void add_var_idxes (unsigned first_var_idx, unsigned num_idxes)
+ {
+ if (!num_idxes || first_var_idx == VarIdx::NO_VARIATION) return;
+ variation_indices->add_range (first_var_idx, first_var_idx + num_idxes - 1);
+ }
+
public:
const void *base;
hb_set_t visited_paint;
hb_set_t *glyphs;
hb_set_t *layer_indices;
hb_set_t *palette_indices;
+ hb_set_t *variation_indices;
+ unsigned num_var_idxes;
unsigned nesting_level_left;
hb_colrv1_closure_context_t (const void *base_,
hb_set_t *glyphs_,
hb_set_t *layer_indices_,
hb_set_t *palette_indices_,
+ hb_set_t *variation_indices_,
+ unsigned num_var_idxes_ = 1,
unsigned nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
base (base_),
glyphs (glyphs_),
layer_indices (layer_indices_),
palette_indices (palette_indices_),
+ variation_indices (variation_indices_),
+ num_var_idxes (num_var_idxes_),
nesting_level_left (nesting_level_left_)
{}
};
@@ -242,7 +254,12 @@ struct Variable
}
void closurev1 (hb_colrv1_closure_context_t* c) const
- { value.closurev1 (c); }
+ {
+ c->num_var_idxes = 0;
+ // update c->num_var_idxes during value closure
+ value.closurev1 (c);
+ c->add_var_idxes (varIdxBase, c->num_var_idxes);
+ }
bool subset (hb_subset_context_t *c,
const ItemVarStoreInstancer &instancer) const
@@ -252,8 +269,18 @@ struct Variable
if (c->plan->all_axes_pinned)
return_trace (true);
- //TODO: update varIdxBase for partial-instancing
- return_trace (c->serializer->embed (varIdxBase));
+ VarIdx new_varidx;
+ new_varidx = varIdxBase;
+ if (varIdxBase != VarIdx::NO_VARIATION)
+ {
+ hb_pair_t<unsigned, int> *new_varidx_delta;
+ if (!c->plan->colrv1_variation_idx_delta_map.has (varIdxBase, &new_varidx_delta))
+ return_trace (false);
+
+ new_varidx = hb_first (*new_varidx_delta);
+ }
+
+ return_trace (c->serializer->embed (new_varidx));
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -345,7 +372,10 @@ struct NoVariable
struct ColorStop
{
void closurev1 (hb_colrv1_closure_context_t* c) const
- { c->add_palette_index (paletteIndex); }
+ {
+ c->add_palette_index (paletteIndex);
+ c->num_var_idxes = 2;
+ }
bool subset (hb_subset_context_t *c,
const ItemVarStoreInstancer &instancer,
@@ -542,6 +572,9 @@ struct Affine2x3
return_trace (c->check_struct (this));
}
+ void closurev1 (hb_colrv1_closure_context_t* c) const
+ { c->num_var_idxes = 6; }
+
bool subset (hb_subset_context_t *c,
const ItemVarStoreInstancer &instancer,
uint32_t varIdxBase) const
@@ -617,7 +650,10 @@ struct PaintColrLayers
struct PaintSolid
{
void closurev1 (hb_colrv1_closure_context_t* c) const
- { c->add_palette_index (paletteIndex); }
+ {
+ c->add_palette_index (paletteIndex);
+ c->num_var_idxes = 1;
+ }
bool subset (hb_subset_context_t *c,
const ItemVarStoreInstancer &instancer,
@@ -666,7 +702,10 @@ template <template<typename> class Var>
struct PaintLinearGradient
{
void closurev1 (hb_colrv1_closure_context_t* c) const
- { (this+colorLine).closurev1 (c); }
+ {
+ (this+colorLine).closurev1 (c);
+ c->num_var_idxes = 6;
+ }
bool subset (hb_subset_context_t *c,
const ItemVarStoreInstancer &instancer,
@@ -733,7 +772,10 @@ template <template<typename> class Var>
struct PaintRadialGradient
{
void closurev1 (hb_colrv1_closure_context_t* c) const
- { (this+colorLine).closurev1 (c); }
+ {
+ (this+colorLine).closurev1 (c);
+ c->num_var_idxes = 6;
+ }
bool subset (hb_subset_context_t *c,
const ItemVarStoreInstancer &instancer,
@@ -800,7 +842,10 @@ template <template<typename> class Var>
struct PaintSweepGradient
{
void closurev1 (hb_colrv1_closure_context_t* c) const
- { (this+colorLine).closurev1 (c); }
+ {
+ (this+colorLine).closurev1 (c);
+ c->num_var_idxes = 4;
+ }
bool subset (hb_subset_context_t *c,
const ItemVarStoreInstancer &instancer,
@@ -1544,6 +1589,9 @@ struct ClipBoxFormat2 : Variable<ClipBoxFormat1>
clip_box.yMax += roundf (instancer (varIdxBase, 3));
}
}
+
+ void closurev1 (hb_colrv1_closure_context_t* c) const
+ { c->variation_indices->add_range (varIdxBase, varIdxBase + 3); }
};
struct ClipBox
@@ -1559,6 +1607,14 @@ struct ClipBox
}
}
+ void closurev1 (hb_colrv1_closure_context_t* c) const
+ {
+ switch (u.format) {
+ case 2: u.format2.closurev1 (c);
+ default:return;
+ }
+ }
+
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
@@ -1606,6 +1662,12 @@ struct ClipRecord
int cmp (hb_codepoint_t g) const
{ return g < startGlyphID ? -1 : g <= endGlyphID ? 0 : +1; }
+ void closurev1 (hb_colrv1_closure_context_t* c, const void *base) const
+ {
+ if (!c->glyphs->intersects (startGlyphID, endGlyphID)) return;
+ (base+clipBox).closurev1 (c);
+ }
+
bool subset (hb_subset_context_t *c,
const void *base,
const ItemVarStoreInstancer &instancer) const
@@ -1941,6 +2003,76 @@ struct LayerList : Array32OfOffset32To<Paint>
}
};
+struct delta_set_index_map_subset_plan_t
+{
+ unsigned get_inner_bit_count () const { return inner_bit_count; }
+ unsigned get_width () const { return ((outer_bit_count + inner_bit_count + 7) / 8); }
+ hb_array_t<const uint32_t> get_output_map () const { return output_map.as_array (); }
+
+ delta_set_index_map_subset_plan_t (const hb_map_t &new_deltaset_idx_varidx_map)
+ {
+ map_count = 0;
+ outer_bit_count = 0;
+ inner_bit_count = 1;
+ output_map.init ();
+
+ /* search backwards */
+ unsigned count = new_deltaset_idx_varidx_map.get_population ();
+ if (!count) return;
+
+ unsigned last_idx = (unsigned)-1;
+ unsigned last_varidx = (unsigned)-1;
+
+ for (unsigned i = count; i; i--)
+ {
+ unsigned delta_set_idx = i - 1;
+ unsigned var_idx = new_deltaset_idx_varidx_map.get (delta_set_idx);
+ if (i == count)
+ {
+ last_idx = delta_set_idx;
+ last_varidx = var_idx;
+ continue;
+ }
+ if (var_idx != last_varidx)
+ break;
+ last_idx = delta_set_idx;
+ }
+
+ map_count = last_idx + 1;
+ }
+
+ bool remap (const hb_map_t &new_deltaset_idx_varidx_map)
+ {
+ /* recalculate bit_count */
+ outer_bit_count = 1;
+ inner_bit_count = 1;
+
+ if (unlikely (!output_map.resize (map_count, false))) return false;
+
+ for (unsigned idx = 0; idx < map_count; idx++)
+ {
+ uint32_t *var_idx;
+ if (!new_deltaset_idx_varidx_map.has (idx, &var_idx)) return false;
+ output_map.arrayZ[idx] = *var_idx;
+
+ unsigned outer = (*var_idx) >> 16;
+ unsigned bit_count = (outer == 0) ? 1 : hb_bit_storage (outer);
+ outer_bit_count = hb_max (bit_count, outer_bit_count);
+
+ unsigned inner = (*var_idx) & 0xFFFF;
+ bit_count = (inner == 0) ? 1 : hb_bit_storage (inner);
+ inner_bit_count = hb_max (bit_count, inner_bit_count);
+ }
+ return true;
+ }
+
+ private:
+ unsigned map_count;
+ unsigned outer_bit_count;
+ unsigned inner_bit_count;
+ hb_vector_t<uint32_t> output_map;
+};
+
struct COLR
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
@@ -1992,8 +2124,22 @@ struct COLR
void closure_forV1 (hb_set_t *glyphset,
hb_set_t *layer_indices,
- hb_set_t *palette_indices) const
- { colr->closure_forV1 (glyphset, layer_indices, palette_indices); }
+ hb_set_t *palette_indices,
+ hb_set_t *variation_indices,
+ hb_set_t *delta_set_indices) const
+ { colr->closure_forV1 (glyphset, layer_indices, palette_indices, variation_indices, delta_set_indices); }
+
+ bool has_var_store () const
+ { return colr->has_var_store (); }
+
+ const ItemVariationStore &get_var_store () const
+ { return colr->get_var_store (); }
+
+ bool has_delta_set_index_map () const
+ { return colr->has_delta_set_index_map (); }
+
+ const DeltaSetIndexMap &get_delta_set_index_map () const
+ { return colr->get_delta_set_index_map (); }
private:
hb_blob_ptr_t<COLR> colr;
@@ -2030,14 +2176,16 @@ struct COLR
void closure_forV1 (hb_set_t *glyphset,
hb_set_t *layer_indices,
- hb_set_t *palette_indices) const
+ hb_set_t *palette_indices,
+ hb_set_t *variation_indices,
+ hb_set_t *delta_set_indices) const
{
if (version != 1) return;
hb_barrier ();
hb_set_t visited_glyphs;
- hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices);
+ hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices, variation_indices);
const BaseGlyphList &baseglyph_paintrecords = this+baseGlyphList;
for (const BaseGlyphPaintRecord &baseglyph_paintrecord: baseglyph_paintrecords.iter ())
@@ -2049,6 +2197,22 @@ struct COLR
paint.dispatch (&c);
}
hb_set_union (glyphset, &visited_glyphs);
+
+ const ClipList &cliplist = this+clipList;
+ c.glyphs = glyphset;
+ for (const ClipRecord &clip_record : cliplist.clips.iter())
+ clip_record.closurev1 (&c, &cliplist);
+
+ // if a DeltaSetIndexMap is included, collected variation indices are
+ // actually delta set indices, we need to map them into variation indices
+ if (has_delta_set_index_map ())
+ {
+ const DeltaSetIndexMap &var_idx_map = this+varIdxMap;
+ delta_set_indices->set (*variation_indices);
+ variation_indices->clear ();
+ for (unsigned delta_set_idx : *delta_set_indices)
+ variation_indices->add (var_idx_map.map (delta_set_idx));
+ }
}
const LayerList& get_layerList () const
@@ -2057,6 +2221,18 @@ struct COLR
const BaseGlyphList& get_baseglyphList () const
{ return (this+baseGlyphList); }
+ bool has_var_store () const
+ { return version >= 1 && varStore != 0; }
+
+ bool has_delta_set_index_map () const
+ { return version >= 1 && varIdxMap != 0; }
+
+ const DeltaSetIndexMap &get_delta_set_index_map () const
+ { return (version == 0 || varIdxMap == 0) ? Null (DeltaSetIndexMap) : this+varIdxMap; }
+
+ const ItemVariationStore &get_var_store () const
+ { return (version == 0 || varStore == 0) ? Null (ItemVariationStore) : this+varStore; }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -2132,6 +2308,88 @@ struct COLR
return record;
}
+ bool downgrade_to_V0 (const hb_set_t &glyphset) const
+ {
+ //no more COLRv1 glyphs, downgrade to version 0
+ for (const BaseGlyphPaintRecord& _ : get_baseglyphList ())
+ if (glyphset.has (_.glyphId))
+ return false;
+
+ return true;
+ }
+
+ bool subset_varstore (hb_subset_context_t *c,
+ COLR* out /* OUT */) const
+ {
+ TRACE_SUBSET (this);
+ if (!varStore || c->plan->all_axes_pinned ||
+ !c->plan->colrv1_variation_idx_delta_map)
+ return_trace (true);
+
+ const ItemVariationStore& var_store = this+varStore;
+ if (c->plan->normalized_coords)
+ {
+ item_variations_t item_vars;
+ /* turn off varstore optimization when varIdxMap is null, so we maintain
+ * original var_idx sequence */
+ bool optimize = (varIdxMap != 0) ? true : false;
+ if (!item_vars.instantiate (var_store, c->plan,
+ optimize, /* optimization */
+ optimize, /* use_no_variation_idx = false */
+ c->plan->colrv1_varstore_inner_maps.as_array ()))
+ return_trace (false);
+
+ if (!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 ()))
+ return_trace (false);
+
+ /* if varstore is optimized, update colrv1_new_deltaset_idx_varidx_map in
+ * subset plan */
+ if (optimize)
+ {
+ const hb_map_t &varidx_map = item_vars.get_varidx_map ();
+ for (auto _ : c->plan->colrv1_new_deltaset_idx_varidx_map.iter_ref ())
+ {
+ uint32_t varidx = _.second;
+ uint32_t *new_varidx;
+ if (varidx_map.has (varidx, &new_varidx))
+ _.second = *new_varidx;
+ else
+ _.second = VarIdx::NO_VARIATION;
+ }
+ }
+ }
+ else
+ {
+ if (unlikely (!out->varStore.serialize_serialize (c->serializer,
+ &var_store,
+ c->plan->colrv1_varstore_inner_maps.as_array ())))
+ return_trace (false);
+ }
+
+ return_trace (true);
+ }
+
+ bool subset_delta_set_index_map (hb_subset_context_t *c,
+ COLR* out /* OUT */) const
+ {
+ TRACE_SUBSET (this);
+ if (!varIdxMap || c->plan->all_axes_pinned ||
+ !c->plan->colrv1_new_deltaset_idx_varidx_map)
+ return_trace (true);
+
+ const hb_map_t &deltaset_idx_varidx_map = c->plan->colrv1_new_deltaset_idx_varidx_map;
+ delta_set_index_map_subset_plan_t index_map_plan (deltaset_idx_varidx_map);
+
+ if (unlikely (!index_map_plan.remap (deltaset_idx_varidx_map)))
+ return_trace (false);
+
+ return_trace (out->varIdxMap.serialize_serialize (c->serializer, index_map_plan));
+ }
+
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
@@ -2200,34 +2458,28 @@ struct COLR
auto *colr_prime = c->serializer->start_embed<COLR> ();
if (unlikely (!c->serializer->extend_min (colr_prime))) return_trace (false);
- if (version == 0)
- return_trace (colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it));
+ if (version == 0 || downgrade_to_V0 (glyphset))
+ return_trace (colr_prime->serialize_V0 (c->serializer, 0, base_it, layer_it));
- auto snap = c->serializer->snapshot ();
+ //start version 1
if (!c->serializer->allocate_size<void> (5 * HBUINT32::static_size)) return_trace (false);
+ if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false);
+
+ /* subset ItemVariationStore first, cause varidx_map needs to be updated
+ * after instancing */
+ if (!subset_varstore (c, colr_prime)) return_trace (false);
ItemVarStoreInstancer instancer (varStore ? &(this+varStore) : nullptr,
varIdxMap ? &(this+varIdxMap) : nullptr,
c->plan->normalized_coords.as_array ());
if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this, instancer))
- {
- if (c->serializer->in_error ()) return_trace (false);
- //no more COLRv1 glyphs: downgrade to version 0
- c->serializer->revert (snap);
- return_trace (colr_prime->serialize_V0 (c->serializer, 0, base_it, layer_it));
- }
-
- if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false);
+ return_trace (false);
colr_prime->layerList.serialize_subset (c, layerList, this, instancer);
colr_prime->clipList.serialize_subset (c, clipList, this, instancer);
- if (!varStore || c->plan->all_axes_pinned)
- return_trace (true);
- colr_prime->varIdxMap.serialize_copy (c->serializer, varIdxMap, this);
- colr_prime->varStore.serialize_copy (c->serializer, varStore, this);
- return_trace (true);
+ return_trace (subset_delta_set_index_map (c, colr_prime));
}
const Paint *get_base_glyph_paint (hb_codepoint_t glyph) const
diff --git a/thirdparty/harfbuzz/src/OT/Color/COLR/colrv1-closure.hh b/thirdparty/harfbuzz/src/OT/Color/COLR/colrv1-closure.hh
index 705863d4ad..9ed0aa5632 100644
--- a/thirdparty/harfbuzz/src/OT/Color/COLR/colrv1-closure.hh
+++ b/thirdparty/harfbuzz/src/OT/Color/COLR/colrv1-closure.hh
@@ -66,34 +66,64 @@ HB_INTERNAL void PaintColrGlyph::closurev1 (hb_colrv1_closure_context_t* c) cons
template <template<typename> class Var>
HB_INTERNAL void PaintTransform<Var>::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+ (this+src).dispatch (c);
+ (this+transform).closurev1 (c);
+}
HB_INTERNAL void PaintTranslate::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+ (this+src).dispatch (c);
+ c->num_var_idxes = 2;
+}
HB_INTERNAL void PaintScale::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+ (this+src).dispatch (c);
+ c->num_var_idxes = 2;
+}
HB_INTERNAL void PaintScaleAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+ (this+src).dispatch (c);
+ c->num_var_idxes = 4;
+}
HB_INTERNAL void PaintScaleUniform::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+ (this+src).dispatch (c);
+ c->num_var_idxes = 1;
+}
HB_INTERNAL void PaintScaleUniformAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+ (this+src).dispatch (c);
+ c->num_var_idxes = 3;
+}
HB_INTERNAL void PaintRotate::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+ (this+src).dispatch (c);
+ c->num_var_idxes = 1;
+}
HB_INTERNAL void PaintRotateAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+ (this+src).dispatch (c);
+ c->num_var_idxes = 3;
+}
HB_INTERNAL void PaintSkew::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+ (this+src).dispatch (c);
+ c->num_var_idxes = 2;
+}
HB_INTERNAL void PaintSkewAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
-{ (this+src).dispatch (c); }
+{
+ (this+src).dispatch (c);
+ c->num_var_idxes = 4;
+}
HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) const
{
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh b/thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh
index 317b96c714..45baeb4ec5 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh
@@ -1022,47 +1022,6 @@ struct GDEF
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
{ get_lig_caret_list ().collect_variation_indices (c); }
- void remap_layout_variation_indices (const hb_set_t *layout_variation_indices,
- const hb_vector_t<int>& normalized_coords,
- bool calculate_delta, /* not pinned at default */
- bool no_variations, /* all axes pinned */
- hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map /* OUT */) const
- {
- 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 ())
- {
- int delta = 0;
- if (calculate_delta)
- delta = roundf (var_store.get_delta (idx, normalized_coords.arrayZ,
- normalized_coords.length, store_cache));
-
- if (no_variations)
- {
- layout_variation_idx_delta_map->set (idx, hb_pair_t<unsigned, int> (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta));
- continue;
- }
-
- uint16_t major = idx >> 16;
- if (major >= var_store.get_sub_table_count ()) break;
- if (major != last_major)
- {
- new_minor = 0;
- ++new_major;
- }
-
- unsigned new_idx = (new_major << 16) + new_minor;
- layout_variation_idx_delta_map->set (idx, hb_pair_t<unsigned, int> (new_idx, delta));
- ++new_minor;
- last_major = major;
- }
- var_store.destroy_cache (store_cache);
- }
-
protected:
union {
FixedVersion<> version; /* Version identifier */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh
index 402ed12ae2..e0ec82a236 100644
--- a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh
@@ -90,8 +90,17 @@ struct Ligature
unsigned int total_component_count = 0;
+ if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return false;
+ unsigned match_positions_stack[4];
+ unsigned *match_positions = match_positions_stack;
+ if (unlikely (count > ARRAY_LENGTH (match_positions_stack)))
+ {
+ match_positions = (unsigned *) hb_malloc (hb_max (count, 1u) * sizeof (unsigned));
+ if (unlikely (!match_positions))
+ return_trace (false);
+ }
+
unsigned int match_end = 0;
- unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
if (likely (!match_input (c, count,
&component[1],
@@ -102,6 +111,8 @@ struct Ligature
&total_component_count)))
{
c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
+ if (match_positions != match_positions_stack)
+ hb_free (match_positions);
return_trace (false);
}
@@ -145,6 +156,8 @@ struct Ligature
pos);
}
+ if (match_positions != match_positions_stack)
+ hb_free (match_positions);
return_trace (true);
}
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh
index 05dd58c6df..c26f376aa6 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh
@@ -46,8 +46,9 @@ struct hb_aat_apply_context_t :
hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
{
const char *get_name () { return "APPLY"; }
- template <typename T>
- return_t dispatch (const T &obj) { return obj.apply (this); }
+ template <typename T, typename ...Ts>
+ return_t dispatch (const T &obj, Ts&&... ds)
+ { return obj.apply (this, std::forward<Ts> (ds)...); }
static return_t default_return_value () { return false; }
bool stop_sublookup_iteration (return_t r) const { return r; }
@@ -59,6 +60,9 @@ struct hb_aat_apply_context_t :
const ankr *ankr_table;
const OT::GDEF *gdef_table;
const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr;
+ hb_set_digest_t machine_glyph_set = hb_set_digest_t::full ();
+ hb_set_digest_t left_set = hb_set_digest_t::full ();
+ hb_set_digest_t right_set = hb_set_digest_t::full ();
hb_mask_t subtable_flags = 0;
/* Unused. For debug tracing only. */
@@ -81,6 +85,8 @@ struct hb_aat_apply_context_t :
* Lookup Table
*/
+enum { DELETED_GLYPH = 0xFFFF };
+
template <typename T> struct Lookup;
template <typename T>
@@ -95,6 +101,12 @@ struct LookupFormat0
return &arrayZ[glyph_id];
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const
+ {
+ glyphs.add_range (0, num_glyphs - 1);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -123,6 +135,14 @@ struct LookupSegmentSingle
int cmp (hb_codepoint_t g) const
{ return g < first ? -1 : g <= last ? 0 : +1 ; }
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ if (first == DELETED_GLYPH)
+ return;
+ glyphs.add_range (first, last);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -153,6 +173,14 @@ struct LookupFormat2
return v ? &v->value : nullptr;
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ unsigned count = segments.get_length ();
+ for (unsigned int i = 0; i < count; i++)
+ segments[i].collect_glyphs (glyphs);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -184,6 +212,14 @@ struct LookupSegmentArray
return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ if (first == DELETED_GLYPH)
+ return;
+ glyphs.add_range (first, last);
+ }
+
int cmp (hb_codepoint_t g) const
{ return g < first ? -1 : g <= last ? 0 : +1; }
@@ -226,6 +262,14 @@ struct LookupFormat4
return v ? v->get_value (glyph_id, this) : nullptr;
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ unsigned count = segments.get_length ();
+ for (unsigned i = 0; i < count; i++)
+ segments[i].collect_glyphs (glyphs);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -254,6 +298,14 @@ struct LookupSingle
int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ if (glyph == DELETED_GLYPH)
+ return;
+ glyphs.add (glyph);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -283,6 +335,14 @@ struct LookupFormat6
return v ? &v->value : nullptr;
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ unsigned count = entries.get_length ();
+ for (unsigned i = 0; i < count; i++)
+ entries[i].collect_glyphs (glyphs);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -314,6 +374,16 @@ struct LookupFormat8
&valueArrayZ[glyph_id - firstGlyph] : nullptr;
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ if (unlikely (!glyphCount))
+ return;
+ if (firstGlyph == DELETED_GLYPH)
+ return;
+ glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -358,6 +428,16 @@ struct LookupFormat10
return v;
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs) const
+ {
+ if (unlikely (!glyphCount))
+ return;
+ if (firstGlyph == DELETED_GLYPH)
+ return;
+ glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -406,6 +486,20 @@ struct Lookup
}
}
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs, unsigned int num_glyphs) const
+ {
+ switch (u.format) {
+ case 0: u.format0.collect_glyphs (glyphs, num_glyphs); return;
+ case 2: u.format2.collect_glyphs (glyphs); return;
+ case 4: u.format4.collect_glyphs (glyphs); return;
+ case 6: u.format6.collect_glyphs (glyphs); return;
+ case 8: u.format8.collect_glyphs (glyphs); return;
+ case 10: u.format10.collect_glyphs (glyphs); return;
+ default:return;
+ }
+ }
+
typename T::type get_class (hb_codepoint_t glyph_id,
unsigned int num_glyphs,
unsigned int outOfRange) const
@@ -460,8 +554,6 @@ struct Lookup
};
DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (AAT, Lookup, 2);
-enum { DELETED_GLYPH = 0xFFFF };
-
/*
* (Extended) State Table
*/
@@ -512,6 +604,14 @@ struct Entry<void>
DEFINE_SIZE_STATIC (4);
};
+enum Class
+{
+ CLASS_END_OF_TEXT = 0,
+ CLASS_OUT_OF_BOUNDS = 1,
+ CLASS_DELETED_GLYPH = 2,
+ CLASS_END_OF_LINE = 3,
+};
+
template <typename Types, typename Extra>
struct StateTable
{
@@ -524,21 +624,24 @@ struct StateTable
STATE_START_OF_TEXT = 0,
STATE_START_OF_LINE = 1,
};
- enum Class
+
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const
{
- CLASS_END_OF_TEXT = 0,
- CLASS_OUT_OF_BOUNDS = 1,
- CLASS_DELETED_GLYPH = 2,
- CLASS_END_OF_LINE = 3,
- };
+ (this+classTable).collect_glyphs (glyphs, num_glyphs);
+ }
int new_state (unsigned int newState) const
{ return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
- unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+ template <typename set_t>
+ unsigned int get_class (hb_codepoint_t glyph_id,
+ unsigned int num_glyphs,
+ const set_t &glyphs) const
{
if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
- return (this+classTable).get_class (glyph_id, num_glyphs, 1);
+ if (!glyphs[glyph_id]) return CLASS_OUT_OF_BOUNDS;
+ return (this+classTable).get_class (glyph_id, num_glyphs, CLASS_OUT_OF_BOUNDS);
}
const Entry<Extra> *get_entries () const
@@ -547,7 +650,7 @@ struct StateTable
const Entry<Extra> &get_entry (int state, unsigned int klass) const
{
if (unlikely (klass >= nClasses))
- klass = StateTable::CLASS_OUT_OF_BOUNDS;
+ klass = CLASS_OUT_OF_BOUNDS;
const HBUSHORT *states = (this+stateArrayTable).arrayZ;
const Entry<Extra> *entries = (this+entryTable).arrayZ;
@@ -690,6 +793,15 @@ struct ClassTable
{
return get_class (glyph_id, outOfRange);
}
+
+ template <typename set_t>
+ void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const
+ {
+ for (unsigned i = 0; i < classArray.len; i++)
+ if (classArray.arrayZ[i] != CLASS_OUT_OF_BOUNDS)
+ glyphs.add (firstGlyph + i);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -703,6 +815,38 @@ struct ClassTable
DEFINE_SIZE_ARRAY (4, classArray);
};
+struct SubtableGlyphCoverage
+{
+ bool sanitize (hb_sanitize_context_t *c, unsigned subtable_count) const
+ {
+ TRACE_SANITIZE (this);
+
+ if (unlikely (!c->check_array (&subtableOffsets, subtable_count)))
+ return_trace (false);
+
+ unsigned bytes = (c->get_num_glyphs () + CHAR_BIT - 1) / CHAR_BIT;
+ for (unsigned i = 0; i < subtable_count; i++)
+ {
+ uint32_t offset = (uint32_t) subtableOffsets[i];
+ if (offset == 0 || offset == 0xFFFFFFFF)
+ continue;
+ if (unlikely (!subtableOffsets[i].sanitize (c, this, bytes)))
+ return_trace (false);
+ }
+
+ return_trace (true);
+ }
+ protected:
+ UnsizedArrayOf<NNOffset32To<UnsizedArrayOf<HBUINT8>>> subtableOffsets;
+ /* Array of offsets from the beginning of the
+ * subtable glyph coverage table to the glyph
+ * coverage bitfield for a given subtable; there
+ * is one offset for each subtable in the chain */
+ /* UnsizedArrayOf<HBUINT8> coverageBitfields; *//* The individual coverage bitfields. */
+ public:
+ DEFINE_SIZE_ARRAY (0, subtableOffsets);
+};
+
struct ObsoleteTypes
{
static constexpr bool extended = false;
@@ -779,15 +923,15 @@ struct StateTableDriver
using EntryT = Entry<EntryData>;
StateTableDriver (const StateTableT &machine_,
- hb_buffer_t *buffer_,
hb_face_t *face_) :
machine (machine_),
- buffer (buffer_),
num_glyphs (face_->get_num_glyphs ()) {}
- template <typename context_t>
+ template <typename context_t, typename set_t = hb_set_digest_t>
void drive (context_t *c, hb_aat_apply_context_t *ac)
{
+ hb_buffer_t *buffer = ac->buffer;
+
if (!c->in_place)
buffer->clear_output ();
@@ -822,9 +966,9 @@ struct StateTableDriver
}
}
- unsigned int klass = buffer->idx < buffer->len ?
- machine.get_class (buffer->cur().codepoint, num_glyphs) :
- (unsigned) StateTableT::CLASS_END_OF_TEXT;
+ unsigned int klass = likely (buffer->idx < buffer->len) ?
+ machine.get_class (buffer->cur().codepoint, num_glyphs, ac->machine_glyph_set) :
+ (unsigned) CLASS_END_OF_TEXT;
DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
const EntryT &entry = machine.get_entry (state, klass);
const int next_state = machine.new_state (entry.newState);
@@ -862,22 +1006,22 @@ struct StateTableDriver
{
/* 2c. */
const auto wouldbe_entry = machine.get_entry(StateTableT::STATE_START_OF_TEXT, klass);
-
+
/* 2c'. */
- if (c->is_actionable (this, wouldbe_entry))
- return false;
-
+ if (c->is_actionable (buffer, this, wouldbe_entry))
+ return false;
+
/* 2c". */
return next_state == machine.new_state(wouldbe_entry.newState)
&& (entry.flags & context_t::DontAdvance) == (wouldbe_entry.flags & context_t::DontAdvance);
};
-
+
const auto is_safe_to_break = [&]()
{
/* 1. */
- if (c->is_actionable (this, entry))
+ if (c->is_actionable (buffer, this, entry))
return false;
-
+
/* 2. */
// This one is meh, I know...
const auto ok =
@@ -886,15 +1030,15 @@ struct StateTableDriver
|| is_safe_to_break_extra();
if (!ok)
return false;
-
+
/* 3. */
- return !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT));
+ return !c->is_actionable (buffer, this, machine.get_entry (state, CLASS_END_OF_TEXT));
};
if (!is_safe_to_break () && buffer->backtrack_len () && buffer->idx < buffer->len)
buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
- c->transition (this, entry);
+ c->transition (buffer, this, entry);
state = next_state;
DEBUG_MSG (APPLY, nullptr, "s%d", state);
@@ -912,7 +1056,6 @@ struct StateTableDriver
public:
const StateTableT &machine;
- hb_buffer_t *buffer;
unsigned int num_glyphs;
};
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh
index 0de54e0a02..8d0d87af02 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh
@@ -30,6 +30,7 @@
#include "hb-kern.hh"
#include "hb-aat-layout-ankr-table.hh"
+#include "hb-set-digest.hh"
/*
* kerx -- Extended Kerning
@@ -82,7 +83,7 @@ struct KernPair
return_trace (c->check_struct (this));
}
- protected:
+ public:
HBGlyphID16 left;
HBGlyphID16 right;
FWORD value;
@@ -118,6 +119,16 @@ struct KerxSubTableFormat0
return_trace (true);
}
+ template <typename set_t>
+ void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+ {
+ for (const KernPair& pair : pairs)
+ {
+ left_set.add (pair.left);
+ right_set.add (pair.right);
+ }
+ }
+
struct accelerator_t
{
const KerxSubTableFormat0 &table;
@@ -128,7 +139,10 @@ struct KerxSubTableFormat0
table (table_), c (c_) {}
int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
- { return table.get_kerning (left, right, c); }
+ {
+ if (!c->left_set[left] || !c->right_set[right]) return 0;
+ return table.get_kerning (left, right, c);
+ }
};
@@ -228,13 +242,14 @@ struct KerxSubTableFormat1
depth (0),
crossStream (table->header.coverage & table->header.CrossStream) {}
- bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+ bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
+ StateTableDriver<Types, EntryData> *driver HB_UNUSED,
const Entry<EntryData> &entry)
{ return Format1EntryT::performAction (entry); }
- void transition (StateTableDriver<Types, EntryData> *driver,
+ void transition (hb_buffer_t *buffer,
+ StateTableDriver<Types, EntryData> *driver,
const Entry<EntryData> &entry)
{
- hb_buffer_t *buffer = driver->buffer;
unsigned int flags = entry.flags;
if (flags & Format1EntryT::Reset)
@@ -351,7 +366,7 @@ struct KerxSubTableFormat1
driver_context_t dc (this, c);
- StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
+ StateTableDriver<Types, EntryData> driver (machine, c->font->face);
driver.drive (&dc, c);
return_trace (true);
@@ -365,12 +380,21 @@ struct KerxSubTableFormat1
machine.sanitize (c)));
}
+ template <typename set_t>
+ void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+ {
+ set_t set;
+ machine.collect_glyphs (set, num_glyphs);
+ left_set.union_ (set);
+ right_set.union_ (set);
+ }
+
protected:
KernSubTableHeader header;
StateTable<Types, EntryData> machine;
NNOffsetTo<UnsizedArrayOf<FWORD>, HBUINT> kernAction;
public:
- DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 5 * sizeof (HBUINT));
+ DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + (StateTable<Types, EntryData>::static_size + HBUINT::static_size));
};
template <typename KernSubTableHeader>
@@ -413,6 +437,13 @@ struct KerxSubTableFormat2
return_trace (true);
}
+ template <typename set_t>
+ void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+ {
+ (this+leftClassTable).collect_glyphs (left_set, num_glyphs);
+ (this+rightClassTable).collect_glyphs (right_set, num_glyphs);
+ }
+
struct accelerator_t
{
const KerxSubTableFormat2 &table;
@@ -423,7 +454,10 @@ struct KerxSubTableFormat2
table (table_), c (c_) {}
int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
- { return table.get_kerning (left, right, c); }
+ {
+ if (!c->left_set[left] || !c->right_set[right]) return 0;
+ return table.get_kerning (left, right, c);
+ }
};
bool sanitize (hb_sanitize_context_t *c) const
@@ -493,14 +527,14 @@ struct KerxSubTableFormat4
mark_set (false),
mark (0) {}
- bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+ bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
+ StateTableDriver<Types, EntryData> *driver HB_UNUSED,
const Entry<EntryData> &entry)
{ return entry.data.ankrActionIndex != 0xFFFF; }
- void transition (StateTableDriver<Types, EntryData> *driver,
+ void transition (hb_buffer_t *buffer,
+ StateTableDriver<Types, EntryData> *driver,
const Entry<EntryData> &entry)
{
- hb_buffer_t *buffer = driver->buffer;
-
if (mark_set && entry.data.ankrActionIndex != 0xFFFF && buffer->idx < buffer->len)
{
hb_glyph_position_t &o = buffer->cur_pos();
@@ -600,7 +634,7 @@ struct KerxSubTableFormat4
driver_context_t dc (this, c);
- StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
+ StateTableDriver<Types, EntryData> driver (machine, c->font->face);
driver.drive (&dc, c);
return_trace (true);
@@ -614,12 +648,21 @@ struct KerxSubTableFormat4
machine.sanitize (c)));
}
+ template <typename set_t>
+ void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+ {
+ set_t set;
+ machine.collect_glyphs (set, num_glyphs);
+ left_set.union_ (set);
+ right_set.union_ (set);
+ }
+
protected:
KernSubTableHeader header;
StateTable<Types, EntryData> machine;
HBUINT32 flags;
public:
- DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 20);
+ DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + (StateTable<Types, EntryData>::static_size + HBUINT32::static_size));
};
template <typename KernSubTableHeader>
@@ -638,7 +681,7 @@ struct KerxSubTableFormat6
unsigned int num_glyphs = c->sanitizer.get_num_glyphs ();
if (is_long ())
{
- const typename U::Long &t = u.l;
+ const auto &t = u.l;
unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
unsigned int offset = l + r;
@@ -651,7 +694,7 @@ struct KerxSubTableFormat6
}
else
{
- const typename U::Short &t = u.s;
+ const auto &t = u.s;
unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
unsigned int offset = l + r;
@@ -698,6 +741,23 @@ struct KerxSubTableFormat6
c->check_range (this, vector))));
}
+ template <typename set_t>
+ void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+ {
+ if (is_long ())
+ {
+ const auto &t = u.l;
+ (this+t.rowIndexTable).collect_glyphs (left_set, num_glyphs);
+ (this+t.columnIndexTable).collect_glyphs (right_set, num_glyphs);
+ }
+ else
+ {
+ const auto &t = u.s;
+ (this+t.rowIndexTable).collect_glyphs (left_set, num_glyphs);
+ (this+t.columnIndexTable).collect_glyphs (right_set, num_glyphs);
+ }
+ }
+
struct accelerator_t
{
const KerxSubTableFormat6 &table;
@@ -708,7 +768,10 @@ struct KerxSubTableFormat6
table (table_), c (c_) {}
int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
- { return table.get_kerning (left, right, c); }
+ {
+ if (!c->left_set[left] || !c->right_set[right]) return 0;
+ return table.get_kerning (left, right, c);
+ }
};
protected:
@@ -794,6 +857,20 @@ struct KerxSubTable
}
}
+ template <typename set_t>
+ void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+ {
+ unsigned int subtable_type = get_type ();
+ switch (subtable_type) {
+ case 0: u.format0.collect_glyphs (left_set, right_set, num_glyphs); return;
+ case 1: u.format1.collect_glyphs (left_set, right_set, num_glyphs); return;
+ case 2: u.format2.collect_glyphs (left_set, right_set, num_glyphs); return;
+ case 4: u.format4.collect_glyphs (left_set, right_set, num_glyphs); return;
+ case 6: u.format6.collect_glyphs (left_set, right_set, num_glyphs); return;
+ default: return;
+ }
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -824,6 +901,8 @@ struct KerxSubTable
* The 'kerx' Table
*/
+using kern_accelerator_data_t = hb_vector_t<hb_pair_t<hb_set_digest_t, hb_set_digest_t>>;
+
template <typename T>
struct KerxTable
{
@@ -878,7 +957,8 @@ struct KerxTable
return v;
}
- bool apply (AAT::hb_aat_apply_context_t *c) const
+ bool apply (AAT::hb_aat_apply_context_t *c,
+ const kern_accelerator_data_t *accel_data = nullptr) const
{
c->buffer->unsafe_to_concat ();
@@ -925,6 +1005,16 @@ struct KerxTable
if (reverse)
c->buffer->reverse ();
+ if (accel_data)
+ {
+ c->left_set = (*accel_data)[i].first;
+ c->right_set = (*accel_data)[i].second;
+ }
+ else
+ {
+ c->left_set = c->right_set = hb_set_digest_t::full ();
+ }
+
{
/* See comment in sanitize() for conditional here. */
hb_sanitize_with_object_t with (&c->sanitizer, i < count - 1 ? st : (const SubTable *) nullptr);
@@ -977,8 +1067,61 @@ struct KerxTable
st = &StructAfter<SubTable> (*st);
}
+ unsigned majorVersion = thiz()->version;
+ if (sizeof (thiz()->version) == 4)
+ majorVersion = majorVersion >> 16;
+ if (majorVersion >= 3)
+ {
+ const SubtableGlyphCoverage *coverage = (const SubtableGlyphCoverage *) st;
+ if (!coverage->sanitize (c, count))
+ return_trace (false);
+ }
+
return_trace (true);
}
+
+ kern_accelerator_data_t create_accelerator_data (unsigned num_glyphs) const
+ {
+ kern_accelerator_data_t accel_data;
+
+ typedef typename T::SubTable SubTable;
+
+ const SubTable *st = &thiz()->firstSubTable;
+ unsigned int count = thiz()->tableCount;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ hb_set_digest_t left_set, right_set;
+ st->collect_glyphs (left_set, right_set, num_glyphs);
+ accel_data.push (hb_pair (left_set, right_set));
+ st = &StructAfter<SubTable> (*st);
+ }
+
+ return accel_data;
+ }
+
+ struct accelerator_t
+ {
+ accelerator_t (hb_face_t *face)
+ {
+ hb_sanitize_context_t sc;
+ this->table = sc.reference_table<T> (face);
+ this->accel_data = this->table->create_accelerator_data (face->get_num_glyphs ());
+ }
+ ~accelerator_t ()
+ {
+ this->table.destroy ();
+ }
+
+ hb_blob_t *get_blob () const { return table.get_blob (); }
+
+ bool apply (AAT::hb_aat_apply_context_t *c) const
+ {
+ return table->apply (c, &accel_data);
+ }
+
+ hb_blob_ptr_t<T> table;
+ kern_accelerator_data_t accel_data;
+ };
};
struct kerx : KerxTable<kerx>
@@ -1007,8 +1150,10 @@ struct kerx : KerxTable<kerx>
DEFINE_SIZE_MIN (8);
};
+struct kerx_accelerator_t : kerx::accelerator_t {
+ kerx_accelerator_t (hb_face_t *face) : kerx::accelerator_t (face) {}
+};
} /* namespace AAT */
-
#endif /* HB_AAT_LAYOUT_KERX_TABLE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
index 8436551324..4a94e6a8ff 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
@@ -74,15 +74,16 @@ struct RearrangementSubtable
ret (false),
start (0), end (0) {}
- bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
- const Entry<EntryData> &entry)
+ bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
+ StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+ const Entry<EntryData> &entry) const
{
return (entry.flags & Verb) && start < end;
}
- void transition (StateTableDriver<Types, EntryData> *driver,
+ void transition (hb_buffer_t *buffer,
+ StateTableDriver<Types, EntryData> *driver,
const Entry<EntryData> &entry)
{
- hb_buffer_t *buffer = driver->buffer;
unsigned int flags = entry.flags;
if (flags & MarkFirst)
@@ -168,7 +169,7 @@ struct RearrangementSubtable
driver_context_t dc (this);
- StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+ StateTableDriver<Types, EntryData> driver (machine, c->face);
driver.drive (&dc, c);
return_trace (dc.ret);
@@ -180,10 +181,10 @@ struct RearrangementSubtable
return_trace (machine.sanitize (c));
}
- protected:
+ public:
StateTable<Types, EntryData> machine;
public:
- DEFINE_SIZE_STATIC (16);
+ DEFINE_SIZE_STATIC ((StateTable<Types, EntryData>::static_size));
};
template <typename Types>
@@ -223,21 +224,19 @@ struct ContextualSubtable
table (table_),
subs (table+table->substitutionTables) {}
- bool is_actionable (StateTableDriver<Types, EntryData> *driver,
- const Entry<EntryData> &entry)
+ bool is_actionable (hb_buffer_t *buffer,
+ StateTableDriver<Types, EntryData> *driver,
+ const Entry<EntryData> &entry) const
{
- hb_buffer_t *buffer = driver->buffer;
-
if (buffer->idx == buffer->len && !mark_set)
return false;
return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
}
- void transition (StateTableDriver<Types, EntryData> *driver,
+ void transition (hb_buffer_t *buffer,
+ StateTableDriver<Types, EntryData> *driver,
const Entry<EntryData> &entry)
{
- hb_buffer_t *buffer = driver->buffer;
-
/* Looks like CoreText applies neither mark nor current substitution for
* end-of-text if mark was not explicitly set. */
if (buffer->idx == buffer->len && !mark_set)
@@ -328,7 +327,7 @@ struct ContextualSubtable
driver_context_t dc (this, c);
- StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+ StateTableDriver<Types, EntryData> driver (machine, c->face);
driver.drive (&dc, c);
return_trace (dc.ret);
@@ -361,13 +360,14 @@ struct ContextualSubtable
return_trace (substitutionTables.sanitize (c, this, num_lookups));
}
- protected:
+ public:
StateTable<Types, EntryData>
machine;
+ protected:
NNOffsetTo<UnsizedListOfOffset16To<Lookup<HBGlyphID16>, HBUINT, void, false>, HBUINT>
substitutionTables;
public:
- DEFINE_SIZE_STATIC (20);
+ DEFINE_SIZE_STATIC ((StateTable<Types, EntryData>::static_size + HBUINT::static_size));
};
@@ -464,16 +464,16 @@ struct LigatureSubtable
ligature (table+table->ligature),
match_length (0) {}
- bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
- const Entry<EntryData> &entry)
+ bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
+ StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+ const Entry<EntryData> &entry) const
{
return LigatureEntryT::performAction (entry);
}
- void transition (StateTableDriver<Types, EntryData> *driver,
+ void transition (hb_buffer_t *buffer,
+ StateTableDriver<Types, EntryData> *driver,
const Entry<EntryData> &entry)
{
- hb_buffer_t *buffer = driver->buffer;
-
DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx);
if (entry.flags & LigatureEntryT::SetComponent)
{
@@ -585,7 +585,7 @@ struct LigatureSubtable
driver_context_t dc (this, c);
- StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+ StateTableDriver<Types, EntryData> driver (machine, c->face);
driver.drive (&dc, c);
return_trace (dc.ret);
@@ -600,9 +600,10 @@ struct LigatureSubtable
ligAction && component && ligature);
}
- protected:
+ public:
StateTable<Types, EntryData>
machine;
+ protected:
NNOffsetTo<UnsizedArrayOf<HBUINT32>, HBUINT>
ligAction; /* Offset to the ligature action table. */
NNOffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT>
@@ -610,7 +611,7 @@ struct LigatureSubtable
NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT>
ligature; /* Offset to the actual ligature lists. */
public:
- DEFINE_SIZE_STATIC (28);
+ DEFINE_SIZE_STATIC ((StateTable<Types, EntryData>::static_size + 3 * HBUINT::static_size));
};
template <typename Types>
@@ -754,16 +755,17 @@ struct InsertionSubtable
mark (0),
insertionAction (table+table->insertionAction) {}
- bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
- const Entry<EntryData> &entry)
+ bool is_actionable (hb_buffer_t *buffer HB_UNUSED,
+ StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+ const Entry<EntryData> &entry) const
{
return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
(entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
}
- void transition (StateTableDriver<Types, EntryData> *driver,
+ void transition (hb_buffer_t *buffer,
+ StateTableDriver<Types, EntryData> *driver,
const Entry<EntryData> &entry)
{
- hb_buffer_t *buffer = driver->buffer;
unsigned int flags = entry.flags;
unsigned mark_loc = buffer->out_len;
@@ -850,7 +852,7 @@ struct InsertionSubtable
driver_context_t dc (this, c);
- StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+ StateTableDriver<Types, EntryData> driver (machine, c->face);
driver.drive (&dc, c);
return_trace (dc.ret);
@@ -865,14 +867,15 @@ struct InsertionSubtable
insertionAction);
}
- protected:
+ public:
StateTable<Types, EntryData>
machine;
+ protected:
NNOffsetTo<UnsizedArrayOf<HBGlyphID16>, HBUINT>
insertionAction; /* Byte offset from stateHeader to the start of
* the insertion glyph table. */
public:
- DEFINE_SIZE_STATIC (20);
+ DEFINE_SIZE_STATIC ((StateTable<Types, EntryData>::static_size + HBUINT::static_size));
};
@@ -896,6 +899,89 @@ struct Feature
DEFINE_SIZE_STATIC (12);
};
+
+struct hb_accelerate_subtables_context_t :
+ hb_dispatch_context_t<hb_accelerate_subtables_context_t>
+{
+ struct hb_applicable_t
+ {
+ friend struct hb_accelerate_subtables_context_t;
+ friend struct hb_aat_layout_lookup_accelerator_t;
+
+ public:
+ hb_set_digest_t digest;
+
+ template <typename T>
+ auto init_ (const T &obj_, unsigned num_glyphs, hb_priority<1>) HB_AUTO_RETURN
+ (
+ obj_.machine.collect_glyphs (this->digest, num_glyphs)
+ )
+
+ template <typename T>
+ void init_ (const T &obj_, unsigned num_glyphs, hb_priority<0>)
+ {
+ digest = digest.full ();
+ }
+
+ template <typename T>
+ void init (const T &obj_, unsigned num_glyphs)
+ {
+ init_ (obj_, num_glyphs, hb_prioritize);
+ }
+ };
+
+ /* Dispatch interface. */
+ template <typename T>
+ return_t dispatch (const T &obj)
+ {
+ hb_applicable_t *entry = &array[i++];
+
+ entry->init (obj, num_glyphs);
+
+ return hb_empty_t ();
+ }
+ static return_t default_return_value () { return hb_empty_t (); }
+
+ bool stop_sublookup_iteration (return_t r) const { return false; }
+
+ hb_accelerate_subtables_context_t (hb_applicable_t *array_, unsigned num_glyphs_) :
+ hb_dispatch_context_t<hb_accelerate_subtables_context_t> (),
+ array (array_), num_glyphs (num_glyphs_) {}
+
+ hb_applicable_t *array;
+ unsigned num_glyphs;
+ unsigned i = 0;
+};
+
+struct hb_aat_layout_chain_accelerator_t
+{
+ template <typename TChain>
+ static hb_aat_layout_chain_accelerator_t *create (const TChain &chain, unsigned num_glyphs)
+ {
+ unsigned count = chain.get_subtable_count ();
+
+ unsigned size = sizeof (hb_aat_layout_chain_accelerator_t) -
+ HB_VAR_ARRAY * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t) +
+ count * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t);
+
+ /* The following is a calloc because when we are collecting subtables,
+ * some of them might be invalid and hence not collect; as a result,
+ * we might not fill in all the count entries of the subtables array.
+ * Zeroing it allows the set digest to gatekeep it without having to
+ * initialize it further. */
+ auto *thiz = (hb_aat_layout_chain_accelerator_t *) hb_calloc (1, size);
+ if (unlikely (!thiz))
+ return nullptr;
+
+ hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables, num_glyphs);
+ chain.dispatch (&c_accelerate_subtables);
+
+ return thiz;
+ }
+
+ hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY];
+};
+
template <typename Types>
struct ChainSubtable
{
@@ -987,6 +1073,8 @@ struct Chain
{
typedef typename Types::HBUINT HBUINT;
+ unsigned get_subtable_count () const { return subtableCount; }
+
hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const
{
hb_mask_t flags = defaultFlags;
@@ -1027,7 +1115,8 @@ struct Chain
return flags;
}
- void apply (hb_aat_apply_context_t *c) const
+ void apply (hb_aat_apply_context_t *c,
+ const hb_aat_layout_chain_accelerator_t *accel) const
{
const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount));
unsigned int count = subtableCount;
@@ -1039,6 +1128,7 @@ struct Chain
hb_map ([&subtable] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable->subFeatureFlags & (_.flags); })))
goto skip;
c->subtable_flags = subtable->subFeatureFlags;
+ c->machine_glyph_set = accel ? accel->subtables[i].digest : hb_set_digest_t::full ();
if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) &&
HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
@@ -1100,7 +1190,22 @@ struct Chain
unsigned int get_size () const { return length; }
- bool sanitize (hb_sanitize_context_t *c, unsigned int version HB_UNUSED) const
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount));
+ unsigned int count = subtableCount;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ typename context_t::return_t ret = subtable->dispatch (c, std::forward<Ts> (ds)...);
+ if (c->stop_sublookup_iteration (ret))
+ return ret;
+ subtable = &StructAfter<ChainSubtable<Types>> (*subtable);
+ }
+ return c->default_return_value ();
+ }
+
+ bool sanitize (hb_sanitize_context_t *c, unsigned int version) const
{
TRACE_SANITIZE (this);
if (!(length.sanitize (c) &&
@@ -1122,6 +1227,13 @@ struct Chain
subtable = &StructAfter<ChainSubtable<Types>> (*subtable);
}
+ if (version >= 3)
+ {
+ const SubtableGlyphCoverage *coverage = (const SubtableGlyphCoverage *) subtable;
+ if (!coverage->sanitize (c, count))
+ return_trace (false);
+ }
+
return_trace (true);
}
@@ -1133,7 +1245,7 @@ struct Chain
UnsizedArrayOf<Feature> featureZ; /* Features. */
/*ChainSubtable firstSubtable;*//* Subtables. */
-/*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */
+/*SubtableGlyphCoverage coverages*//* Only if version >= 3. */
public:
DEFINE_SIZE_MIN (8 + 2 * sizeof (HBUINT));
@@ -1144,13 +1256,69 @@ struct Chain
* The 'mort'/'morx' Table
*/
-template <typename Types, hb_tag_t TAG>
+template <typename T, typename Types, hb_tag_t TAG>
struct mortmorx
{
static constexpr hb_tag_t tableTag = TAG;
bool has_data () const { return version != 0; }
+ struct accelerator_t
+ {
+ accelerator_t (hb_face_t *face)
+ {
+ hb_sanitize_context_t sc;
+ this->table = sc.reference_table<T> (face);
+
+ this->chain_count = table->get_chain_count ();
+
+ this->accels = (hb_atomic_ptr_t<hb_aat_layout_chain_accelerator_t> *) hb_calloc (this->chain_count, sizeof (*accels));
+ if (unlikely (!this->accels))
+ {
+ this->chain_count = 0;
+ this->table.destroy ();
+ this->table = hb_blob_get_empty ();
+ }
+ }
+ ~accelerator_t ()
+ {
+ for (unsigned int i = 0; i < this->chain_count; i++)
+ hb_free (this->accels[i]);
+ hb_free (this->accels);
+ this->table.destroy ();
+ }
+
+ hb_blob_t *get_blob () const { return table.get_blob (); }
+
+ template <typename Chain>
+ hb_aat_layout_chain_accelerator_t *get_accel (unsigned chain_index, const Chain &chain, unsigned num_glyphs) const
+ {
+ if (unlikely (chain_index >= chain_count)) return nullptr;
+
+ retry:
+ auto *accel = accels[chain_index].get_acquire ();
+ if (unlikely (!accel))
+ {
+ accel = hb_aat_layout_chain_accelerator_t::create (chain, num_glyphs);
+ if (unlikely (!accel))
+ return nullptr;
+
+ if (unlikely (!accels[chain_index].cmpexch (nullptr, accel)))
+ {
+ hb_free (accel);
+ goto retry;
+ }
+ }
+
+ return accel;
+ }
+
+ hb_blob_ptr_t<T> table;
+ unsigned int chain_count;
+ hb_atomic_ptr_t<hb_aat_layout_chain_accelerator_t> *accels;
+ };
+
+
void compile_flags (const hb_aat_map_builder_t *mapper,
hb_aat_map_t *map) const
{
@@ -1167,8 +1335,14 @@ struct mortmorx
}
}
+ unsigned get_chain_count () const
+ {
+ return chainCount;
+ }
+
void apply (hb_aat_apply_context_t *c,
- const hb_aat_map_t &map) const
+ const hb_aat_map_t &map,
+ const accelerator_t &accel) const
{
if (unlikely (!c->buffer->successful)) return;
@@ -1179,8 +1353,9 @@ struct mortmorx
unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++)
{
+ auto *chain_accel = accel.get_accel (i, *chain, c->face->get_num_glyphs ());
c->range_flags = &map.chain_flags[i];
- chain->apply (c);
+ chain->apply (c, chain_accel);
if (unlikely (!c->buffer->successful)) return;
chain = &StructAfter<Chain<Types>> (*chain);
}
@@ -1220,8 +1395,15 @@ struct mortmorx
DEFINE_SIZE_MIN (8);
};
-struct morx : mortmorx<ExtendedTypes, HB_AAT_TAG_morx> {};
-struct mort : mortmorx<ObsoleteTypes, HB_AAT_TAG_mort> {};
+struct morx : mortmorx<morx, ExtendedTypes, HB_AAT_TAG_morx> {};
+struct mort : mortmorx<mort, ObsoleteTypes, HB_AAT_TAG_mort> {};
+
+struct morx_accelerator_t : morx::accelerator_t {
+ morx_accelerator_t (hb_face_t *face) : morx::accelerator_t (face) {}
+};
+struct mort_accelerator_t : mort::accelerator_t {
+ mort_accelerator_t (hb_face_t *face) : mort::accelerator_t (face) {}
+};
} /* namespace AAT */
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout.cc b/thirdparty/harfbuzz/src/hb-aat-layout.cc
index 5e4cea2224..9da29e51c9 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout.cc
+++ b/thirdparty/harfbuzz/src/hb-aat-layout.cc
@@ -211,14 +211,14 @@ void
hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
hb_aat_map_t *map)
{
- const AAT::morx& morx = *mapper->face->table.morx;
+ const AAT::morx& morx = *mapper->face->table.morx->table;
if (morx.has_data ())
{
morx.compile_flags (mapper, map);
return;
}
- const AAT::mort& mort = *mapper->face->table.mort;
+ const AAT::mort& mort = *mapper->face->table.mort->table;
if (mort.has_data ())
{
mort.compile_flags (mapper, map);
@@ -243,8 +243,8 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
hb_bool_t
hb_aat_layout_has_substitution (hb_face_t *face)
{
- return face->table.morx->has_data () ||
- face->table.mort->has_data ();
+ return face->table.morx->table->has_data () ||
+ face->table.mort->table->has_data ();
}
void
@@ -260,26 +260,30 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
hb_aat_map_t map;
builder.compile (map);
- hb_blob_t *morx_blob = font->face->table.morx.get_blob ();
- const AAT::morx& morx = *morx_blob->as<AAT::morx> ();
- if (morx.has_data ())
{
- AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob);
- if (!buffer->message (font, "start table morx")) return;
- morx.apply (&c, map);
- (void) buffer->message (font, "end table morx");
- return;
+ auto &accel = *font->face->table.morx;
+ const AAT::morx& morx = *accel.table;
+ if (morx.has_data ())
+ {
+ AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
+ if (!buffer->message (font, "start table morx")) return;
+ morx.apply (&c, map, accel);
+ (void) buffer->message (font, "end table morx");
+ return;
+ }
}
- hb_blob_t *mort_blob = font->face->table.mort.get_blob ();
- const AAT::mort& mort = *mort_blob->as<AAT::mort> ();
- if (mort.has_data ())
{
- AAT::hb_aat_apply_context_t c (plan, font, buffer, mort_blob);
- if (!buffer->message (font, "start table mort")) return;
- mort.apply (&c, map);
- (void) buffer->message (font, "end table mort");
- return;
+ auto &accel = *font->face->table.mort;
+ const AAT::mort& mort = *accel.table;
+ if (mort.has_data ())
+ {
+ AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
+ if (!buffer->message (font, "start table mort")) return;
+ mort.apply (&c, map, accel);
+ (void) buffer->message (font, "end table mort");
+ return;
+ }
}
}
@@ -322,7 +326,7 @@ hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
hb_bool_t
hb_aat_layout_has_positioning (hb_face_t *face)
{
- return face->table.kerx->has_data ();
+ return face->table.kerx->table->has_data ();
}
void
@@ -330,13 +334,12 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer)
{
- hb_blob_t *kerx_blob = font->face->table.kerx.get_blob ();
- const AAT::kerx& kerx = *kerx_blob->as<AAT::kerx> ();
+ auto &accel = *font->face->table.kerx;
- AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob);
+ AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
if (!buffer->message (font, "start table kerx")) return;
c.set_ankr_table (font->face->table.ankr.get ());
- kerx.apply (&c);
+ accel.apply (&c);
(void) buffer->message (font, "end table kerx");
}
diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh
index efa6074a42..b02793a09f 100644
--- a/thirdparty/harfbuzz/src/hb-algs.hh
+++ b/thirdparty/harfbuzz/src/hb-algs.hh
@@ -202,8 +202,12 @@ struct BEInt<Type, 4>
/* Floats. */
/* We want our rounding towards +infinity. */
+static inline double
+_hb_roundf (double x) { return floor (x + .5); }
+
static inline float
_hb_roundf (float x) { return floorf (x + .5f); }
+
#define roundf(x) _hb_roundf(x)
diff --git a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh
index 55b1d3bf8d..06fbb72c61 100644
--- a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh
+++ b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh
@@ -76,16 +76,12 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
coords = coords_;
num_coords = num_coords_;
varStore = acc.varStore;
- seen_blend = false;
- seen_vsindex_ = false;
- scalars.init ();
do_blend = num_coords && coords && varStore->size;
set_ivs (acc.privateDicts[fd].ivs);
}
void fini ()
{
- scalars.fini ();
SUPER::fini ();
}
@@ -173,8 +169,8 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
unsigned int ivs;
hb_vector_t<float> scalars;
bool do_blend;
- bool seen_vsindex_;
- bool seen_blend;
+ bool seen_vsindex_ = false;
+ bool seen_blend = false;
typedef cs_interp_env_t<ELEM, CFF2Subrs> SUPER;
};
diff --git a/thirdparty/harfbuzz/src/hb-cplusplus.hh b/thirdparty/harfbuzz/src/hb-cplusplus.hh
index a640e192de..b6b5c8f781 100644
--- a/thirdparty/harfbuzz/src/hb-cplusplus.hh
+++ b/thirdparty/harfbuzz/src/hb-cplusplus.hh
@@ -27,9 +27,6 @@
#include "hb.h"
-HB_BEGIN_DECLS
-HB_END_DECLS
-
#ifdef __cplusplus
#include <functional>
diff --git a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh
index b552dfdd9d..db1c55490c 100644
--- a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh
@@ -100,7 +100,7 @@ HB_OT_CORE_TABLE (OT, MVAR)
/* Legacy kern. */
#ifndef HB_NO_OT_KERN
-HB_OT_CORE_TABLE (OT, kern)
+HB_OT_ACCELERATOR (OT, kern)
#endif
/* OpenType shaping. */
@@ -118,9 +118,9 @@ HB_OT_CORE_TABLE (OT, BASE)
/* AAT shaping. */
#ifndef HB_NO_AAT
-HB_OT_TABLE (AAT, morx)
-HB_OT_TABLE (AAT, mort)
-HB_OT_TABLE (AAT, kerx)
+HB_OT_ACCELERATOR (AAT, morx)
+HB_OT_ACCELERATOR (AAT, mort)
+HB_OT_ACCELERATOR (AAT, kerx)
HB_OT_TABLE (AAT, ankr)
HB_OT_TABLE (AAT, trak)
HB_OT_TABLE (AAT, ltag)
diff --git a/thirdparty/harfbuzz/src/hb-ot-face.cc b/thirdparty/harfbuzz/src/hb-ot-face.cc
index 2243ee0287..b0c927979e 100644
--- a/thirdparty/harfbuzz/src/hb-ot-face.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-face.cc
@@ -41,6 +41,8 @@
#include "hb-ot-layout-gdef-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
+#include "hb-aat-layout-kerx-table.hh"
+#include "hb-aat-layout-morx-table.hh"
void hb_ot_face_t::init0 (hb_face_t *face)
diff --git a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
index 48bd536121..e259b33748 100644
--- a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
@@ -410,7 +410,8 @@ struct hmtxvmtx
font->coords, font->num_coords,
store_cache));
- return _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+ unsigned glyf_advance = _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+ return glyf_advance ? glyf_advance : advance;
#else
return advance;
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-kern-table.hh b/thirdparty/harfbuzz/src/hb-ot-kern-table.hh
index 39444d803f..b87ac8f494 100644
--- a/thirdparty/harfbuzz/src/hb-ot-kern-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-kern-table.hh
@@ -86,6 +86,16 @@ struct KernSubTableFormat3
leftClassCount * rightClassCount));
}
+ template <typename set_t>
+ void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+ {
+ set_t set;
+ if (likely (glyphCount))
+ set.add_range (0, glyphCount - 1);
+ left_set.union_ (set);
+ right_set.union_ (set);
+ }
+
protected:
KernSubTableHeader
header;
@@ -135,16 +145,29 @@ struct KernSubTable
switch (subtable_type) {
case 0: return_trace (c->dispatch (u.format0));
#ifndef HB_NO_AAT_SHAPE
- case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ());
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
#endif
case 2: return_trace (c->dispatch (u.format2));
#ifndef HB_NO_AAT_SHAPE
- case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ());
+ case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
#endif
default: return_trace (c->default_return_value ());
}
}
+ template <typename set_t>
+ void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
+ {
+ unsigned int subtable_type = get_type ();
+ switch (subtable_type) {
+ case 0: u.format0.collect_glyphs (left_set, right_set, num_glyphs); return;
+ case 1: u.format1.collect_glyphs (left_set, right_set, num_glyphs); return;
+ case 2: u.format2.collect_glyphs (left_set, right_set, num_glyphs); return;
+ case 3: u.format3.collect_glyphs (left_set, right_set, num_glyphs); return;
+ default: return;
+ }
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -318,8 +341,9 @@ struct kern
}
}
- bool apply (AAT::hb_aat_apply_context_t *c) const
- { return dispatch (c); }
+ bool apply (AAT::hb_aat_apply_context_t *c,
+ const AAT::kern_accelerator_data_t *accel_data = nullptr) const
+ { return dispatch (c, accel_data); }
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
@@ -343,6 +367,41 @@ struct kern
return_trace (dispatch (c));
}
+ AAT::kern_accelerator_data_t create_accelerator_data (unsigned num_glyphs) const
+ {
+ switch (get_type ()) {
+ case 0: return u.ot.create_accelerator_data (num_glyphs);
+#ifndef HB_NO_AAT_SHAPE
+ case 1: return u.aat.create_accelerator_data (num_glyphs);
+#endif
+ default:return AAT::kern_accelerator_data_t ();
+ }
+ }
+
+ struct accelerator_t
+ {
+ accelerator_t (hb_face_t *face)
+ {
+ hb_sanitize_context_t sc;
+ this->table = sc.reference_table<kern> (face);
+ this->accel_data = this->table->create_accelerator_data (face->get_num_glyphs ());
+ }
+ ~accelerator_t ()
+ {
+ this->table.destroy ();
+ }
+
+ hb_blob_t *get_blob () const { return table.get_blob (); }
+
+ bool apply (AAT::hb_aat_apply_context_t *c) const
+ {
+ return table->apply (c, &accel_data);
+ }
+
+ hb_blob_ptr_t<kern> table;
+ AAT::kern_accelerator_data_t accel_data;
+ };
+
protected:
union {
HBUINT32 version32;
@@ -356,6 +415,10 @@ struct kern
DEFINE_SIZE_UNION (4, version32);
};
+struct kern_accelerator_t : kern::accelerator_t {
+ kern_accelerator_t (hb_face_t *face) : kern::accelerator_t (face) {}
+};
+
} /* namespace OT */
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh
index 0278399069..56290905ce 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh
@@ -125,6 +125,20 @@ struct BaseCoordFormat3
auto *out = c->serializer->embed (*this);
if (unlikely (!out)) return_trace (false);
+ if (!c->plan->pinned_at_default)
+ {
+ unsigned var_idx = (this+deviceTable).get_variation_index ();
+ if (var_idx != VarIdx::NO_VARIATION)
+ {
+ hb_pair_t<unsigned, int> *v;
+ if (!c->plan->base_variation_idx_map.has (var_idx, &v))
+ return_trace (false);
+
+ if (unlikely (!c->serializer->check_assign (out->coordinate, coordinate + hb_second (*v),
+ HB_SERIALIZE_ERROR_INT_OVERFLOW)))
+ return_trace (false);
+ }
+ }
return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable,
this, 0,
hb_serialize_context_t::Head,
@@ -401,11 +415,12 @@ struct BaseLangSysRecord
bool has_data () const { return baseLangSysTag; }
- const MinMax &get_min_max () const { return this+minMax; }
+ const MinMax &get_min_max (const void* base) const { return base+minMax; }
- void collect_variation_indices (const hb_subset_plan_t* plan,
+ void collect_variation_indices (const void* base,
+ const hb_subset_plan_t* plan,
hb_set_t& varidx_set /* OUT */) const
- { (this+minMax).collect_variation_indices (plan, varidx_set); }
+ { (base+minMax).collect_variation_indices (plan, varidx_set); }
bool subset (hb_subset_context_t *c,
const void *base) const
@@ -438,7 +453,7 @@ struct BaseScript
const MinMax &get_min_max (hb_tag_t language_tag) const
{
const BaseLangSysRecord& record = baseLangSysRecords.bsearch (language_tag);
- return record.has_data () ? record.get_min_max () : this+defaultMinMax;
+ return record.has_data () ? record.get_min_max (this) : this+defaultMinMax;
}
const BaseCoord &get_base_coord (int baseline_tag_index) const
@@ -454,7 +469,7 @@ struct BaseScript
(this+defaultMinMax).collect_variation_indices (plan, varidx_set);
for (const BaseLangSysRecord& _ : baseLangSysRecords)
- _.collect_variation_indices (plan, varidx_set);
+ _.collect_variation_indices (this, plan, varidx_set);
}
bool subset (hb_subset_context_t *c) const
@@ -705,6 +720,46 @@ struct BASE
(this+vAxis).collect_variation_indices (plan, varidx_set);
}
+ bool subset_varstore (hb_subset_context_t *c,
+ BASE *out /* OUT */) const
+ {
+ TRACE_SUBSET (this);
+ if (!c->serializer->allocate_size<Offset32To<ItemVariationStore>> (Offset32To<ItemVariationStore>::static_size))
+ return_trace (false);
+ if (!c->plan->normalized_coords)
+ return_trace (out->varStore.serialize_subset (c, varStore, this, c->plan->base_varstore_inner_maps.as_array ()));
+
+ if (c->plan->all_axes_pinned)
+ return_trace (true);
+
+ item_variations_t item_vars;
+ if (!item_vars.instantiate (this+varStore, c->plan, true, true,
+ c->plan->base_varstore_inner_maps.as_array ()))
+ return_trace (false);
+
+ if (!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 ()))
+ return_trace (false);
+
+ const hb_map_t &varidx_map = item_vars.get_varidx_map ();
+ /* base_variation_idx_map in the plan is old_varidx->(varidx, delta)
+ * mapping, new varidx is generated for subsetting, we need to remap this
+ * after instancing */
+ for (auto _ : c->plan->base_variation_idx_map.iter_ref ())
+ {
+ uint32_t varidx = _.second.first;
+ uint32_t *new_varidx;
+ if (varidx_map.has (varidx, &new_varidx))
+ _.second.first = *new_varidx;
+ else
+ _.second.first = HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
+ }
+ return_trace (true);
+ }
+
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
@@ -712,19 +767,15 @@ struct BASE
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
out->version = version;
+ if (has_var_store () && !subset_varstore (c, out))
+ return_trace (false);
+
if (hAxis && !out->hAxis.serialize_subset (c, hAxis, this))
return_trace (false);
if (vAxis && !out->vAxis.serialize_subset (c, vAxis, this))
return_trace (false);
- if (has_var_store ())
- {
- if (!c->serializer->allocate_size<Offset32To<ItemVariationStore>> (Offset32To<ItemVariationStore>::static_size))
- return_trace (false);
- return_trace (out->varStore.serialize_subset (c, varStore, this, c->plan->base_varstore_inner_maps.as_array ()));
- }
-
return_trace (true);
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
index aba427368c..65c8309573 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
@@ -2641,7 +2641,7 @@ struct VarRegionList
float max_val = axis_region->endCoord.to_float ();
if (def_val != 0.f)
- axis_tuples.set (*axis_tag, Triple (min_val, def_val, max_val));
+ axis_tuples.set (*axis_tag, Triple ((double) min_val, (double) def_val, (double) max_val));
axis_region++;
}
return !axis_tuples.in_error ();
@@ -3208,6 +3208,8 @@ struct ItemVariationStore
for (unsigned i = 0; i < count; i++)
{
hb_inc_bimap_t *map = inner_maps.push ();
+ if (!c->propagate_error(inner_maps))
+ return_trace(nullptr);
auto &data = this+dataSets[i];
unsigned itemCount = data.get_item_count ();
@@ -3326,19 +3328,19 @@ struct ConditionFormat1
return_trace (false);
const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location = c->plan->axes_location;
- Triple axis_limit{-1.f, 0.f, 1.f};
+ Triple axis_limit{-1.0, 0.0, 1.0};
Triple *normalized_limit;
if (normalized_axes_location.has (*axis_tag, &normalized_limit))
axis_limit = *normalized_limit;
const hb_hashmap_t<hb_tag_t, TripleDistances>& axes_triple_distances = c->plan->axes_triple_distances;
- TripleDistances axis_triple_distances{1.f, 1.f};
+ TripleDistances axis_triple_distances{1.0, 1.0};
TripleDistances *triple_dists;
if (axes_triple_distances.has (*axis_tag, &triple_dists))
axis_triple_distances = *triple_dists;
- float normalized_min = renormalizeValue (filterRangeMinValue.to_float (), axis_limit, axis_triple_distances, false);
- float normalized_max = renormalizeValue (filterRangeMaxValue.to_float (), axis_limit, axis_triple_distances, false);
+ float normalized_min = renormalizeValue ((double) filterRangeMinValue.to_float (), axis_limit, axis_triple_distances, false);
+ float normalized_max = renormalizeValue ((double) filterRangeMaxValue.to_float (), axis_limit, axis_triple_distances, false);
out->filterRangeMinValue.set_float (normalized_min);
out->filterRangeMaxValue.set_float (normalized_max);
@@ -3356,7 +3358,7 @@ struct ConditionFormat1
hb_tag_t axis_tag = c->axes_index_tag_map->get (axisIndex);
- Triple axis_range (-1.f, 0.f, 1.f);
+ Triple axis_range (-1.0, 0.0, 1.0);
Triple *axis_limit;
bool axis_set_by_user = false;
if (c->axes_location->has (axis_tag, &axis_limit))
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
index c65ea32b8a..6b760b1108 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
@@ -1254,7 +1254,7 @@ static bool match_input (hb_ot_apply_context_t *c,
match_func_t match_func,
const void *match_data,
unsigned int *end_position,
- unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
+ unsigned int *match_positions,
unsigned int *p_total_component_count = nullptr)
{
TRACE_APPLY (nullptr);
@@ -1378,7 +1378,7 @@ static bool match_input (hb_ot_apply_context_t *c,
}
static inline bool ligate_input (hb_ot_apply_context_t *c,
unsigned int count, /* Including the first glyph */
- const unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
+ const unsigned int *match_positions, /* Including the first glyph */
unsigned int match_end,
hb_codepoint_t lig_glyph,
unsigned int total_component_count)
@@ -1686,7 +1686,7 @@ static inline void recurse_lookups (context_t *c,
static inline void apply_lookup (hb_ot_apply_context_t *c,
unsigned int count, /* Including the first glyph */
- unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
+ unsigned int *match_positions, /* Including the first glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
unsigned int match_end)
@@ -1694,6 +1694,9 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
hb_buffer_t *buffer = c->buffer;
int end;
+ unsigned int *match_positions_input = match_positions;
+ unsigned int match_positions_count = count;
+
/* All positions are distance from beginning of *output* buffer.
* Adjust. */
{
@@ -1797,6 +1800,27 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
{
if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
break;
+ if (unlikely (delta + count > match_positions_count))
+ {
+ unsigned new_match_positions_count = hb_max (delta + count, hb_max(match_positions_count, 4u) * 1.5);
+ if (match_positions == match_positions_input)
+ {
+ match_positions = (unsigned int *) hb_malloc (new_match_positions_count * sizeof (match_positions[0]));
+ if (unlikely (!match_positions))
+ break;
+ memcpy (match_positions, match_positions_input, count * sizeof (match_positions[0]));
+ match_positions_count = new_match_positions_count;
+ }
+ else
+ {
+ unsigned int *new_match_positions = (unsigned int *) hb_realloc (match_positions, new_match_positions_count * sizeof (match_positions[0]));
+ if (unlikely (!new_match_positions))
+ break;
+ match_positions = new_match_positions;
+ match_positions_count = new_match_positions_count;
+ }
+ }
+
}
else
{
@@ -1820,6 +1844,9 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
match_positions[next] += delta;
}
+ if (match_positions != match_positions_input)
+ hb_free (match_positions);
+
(void) buffer->move_to (end);
}
@@ -1920,8 +1947,18 @@ static bool context_apply_lookup (hb_ot_apply_context_t *c,
const LookupRecord lookupRecord[],
const ContextApplyLookupContext &lookup_context)
{
+ if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH)) return false;
+ unsigned match_positions_stack[4];
+ unsigned *match_positions = match_positions_stack;
+ if (unlikely (inputCount > ARRAY_LENGTH (match_positions_stack)))
+ {
+ match_positions = (unsigned *) hb_malloc (hb_max (inputCount, 1u) * sizeof (match_positions[0]));
+ if (unlikely (!match_positions))
+ return false;
+ }
+
unsigned match_end = 0;
- unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
+ bool ret = false;
if (match_input (c,
inputCount, input,
lookup_context.funcs.match, lookup_context.match_data,
@@ -1932,13 +1969,18 @@ static bool context_apply_lookup (hb_ot_apply_context_t *c,
inputCount, match_positions,
lookupCount, lookupRecord,
match_end);
- return true;
+ ret = true;
}
else
{
c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
- return false;
+ ret = false;
}
+
+ if (unlikely (match_positions != match_positions_stack))
+ hb_free (match_positions);
+
+ return ret;
}
template <typename Types>
@@ -3018,9 +3060,20 @@ static bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
const LookupRecord lookupRecord[],
const ChainContextApplyLookupContext &lookup_context)
{
+ if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH)) return false;
+ unsigned match_positions_stack[4];
+ unsigned *match_positions = match_positions_stack;
+ if (unlikely (inputCount > ARRAY_LENGTH (match_positions_stack)))
+ {
+ match_positions = (unsigned *) hb_malloc (hb_max (inputCount, 1u) * sizeof (match_positions[0]));
+ if (unlikely (!match_positions))
+ return false;
+ }
+
+ unsigned start_index = c->buffer->out_len;
unsigned end_index = c->buffer->idx;
unsigned match_end = 0;
- unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
+ bool ret = true;
if (!(match_input (c,
inputCount, input,
lookup_context.funcs.match[1], lookup_context.match_data[1],
@@ -3031,17 +3084,18 @@ static bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
match_end, &end_index)))
{
c->buffer->unsafe_to_concat (c->buffer->idx, end_index);
- return false;
+ ret = false;
+ goto done;
}
- unsigned start_index = c->buffer->out_len;
if (!match_backtrack (c,
backtrackCount, backtrack,
lookup_context.funcs.match[0], lookup_context.match_data[0],
&start_index))
{
c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
- return false;
+ ret = false;
+ goto done;
}
c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
@@ -3049,7 +3103,12 @@ static bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
inputCount, match_positions,
lookupCount, lookupRecord,
match_end);
- return true;
+ done:
+
+ if (unlikely (match_positions != match_positions_stack))
+ hb_free (match_positions);
+
+ return ret;
}
template <typename Types>
@@ -4328,7 +4387,7 @@ struct hb_ot_layout_lookup_accelerator_t
thiz->digest.init ();
for (auto& subtable : hb_iter (thiz->subtables, count))
- thiz->digest.add (subtable.digest);
+ thiz->digest.union_ (subtable.digest);
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
thiz->cache_user_idx = c_accelerate_subtables.cache_user_idx;
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc
index a4c13abadf..613c97fd9e 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc
@@ -87,7 +87,7 @@ using OT::Layout::GPOS;
bool
hb_ot_layout_has_kerning (hb_face_t *face)
{
- return face->table.kern->has_data ();
+ return face->table.kern->table->has_data ();
}
/**
@@ -103,7 +103,7 @@ hb_ot_layout_has_kerning (hb_face_t *face)
bool
hb_ot_layout_has_machine_kerning (hb_face_t *face)
{
- return face->table.kern->has_state_machine ();
+ return face->table.kern->table->has_state_machine ();
}
/**
@@ -123,7 +123,7 @@ hb_ot_layout_has_machine_kerning (hb_face_t *face)
bool
hb_ot_layout_has_cross_kerning (hb_face_t *face)
{
- return face->table.kern->has_cross_stream ();
+ return face->table.kern->table->has_cross_stream ();
}
void
@@ -132,7 +132,7 @@ hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer)
{
hb_blob_t *blob = font->face->table.kern.get_blob ();
- const AAT::kern& kern = *blob->as<AAT::kern> ();
+ const auto& kern = *font->face->table.kern;
AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
diff --git a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
index 43b58d9bbf..6c91402269 100644
--- a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
@@ -272,7 +272,7 @@ struct OS2
Triple *axis_range;
if (c->plan->user_axes_location.has (HB_TAG ('w','g','h','t'), &axis_range))
{
- unsigned weight_class = static_cast<unsigned> (roundf (hb_clamp (axis_range->middle, 1.0f, 1000.0f)));
+ unsigned weight_class = static_cast<unsigned> (roundf (hb_clamp (axis_range->middle, 1.0, 1000.0)));
if (os2_prime->usWeightClass != weight_class)
os2_prime->usWeightClass = weight_class;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table.hh b/thirdparty/harfbuzz/src/hb-ot-post-table.hh
index 8132dcfb91..4191879037 100644
--- a/thirdparty/harfbuzz/src/hb-ot-post-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-post-table.hh
@@ -116,7 +116,7 @@ struct post
Triple *axis_range;
if (c->plan->user_axes_location.has (HB_TAG ('s','l','n','t'), &axis_range))
{
- float italic_angle = hb_max (-90.f, hb_min (axis_range->middle, 90.f));
+ float italic_angle = hb_max (-90.0, hb_min (axis_range->middle, 90.0));
if (post_prime->italicAngle.to_float () != italic_angle)
post_prime->italicAngle.set_float (italic_angle);
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh
index e88c82a13c..ea5459ef4e 100644
--- a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh
@@ -63,8 +63,9 @@ static bool axis_value_is_outside_axis_range (hb_tag_t axis_tag, float axis_valu
if (!user_axes_location->has (axis_tag))
return false;
+ double axis_value_double = static_cast<double>(axis_value);
Triple axis_range = user_axes_location->get (axis_tag);
- return (axis_value < axis_range.minimum || axis_value > axis_range.maximum);
+ return (axis_value_double < axis_range.minimum || axis_value_double > axis_range.maximum);
}
struct StatAxisRecord
diff --git a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh
index db92f4664a..920b06b9c9 100644
--- a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh
@@ -2818,9 +2818,10 @@ out:
* @tag: A language tag.
*
* Converts @tag to a BCP 47 language tag if it is ambiguous (it corresponds to
- * many language tags) and the best tag is not the alphabetically first, or if
- * the best tag consists of multiple subtags, or if the best tag does not appear
- * in #ot_languages.
+ * many language tags) and the best tag is not the first (sorted alphabetically,
+ * with two-letter tags having priority over all three-letter tags), or if the
+ * best tag consists of multiple subtags, or if the best tag does not appear in
+ * #ot_languages2 or #ot_languages3.
*
* Return value: The #hb_language_t corresponding to the BCP 47 language tag,
* or #HB_LANGUAGE_INVALID if @tag is not ambiguous.
@@ -2834,8 +2835,6 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("alt", -1); /* Southern Altai */
case HB_TAG('A','P','P','H'): /* Phonetic transcription—Americanist conventions */
return hb_language_from_string ("und-fonnapa", -1); /* Undetermined; North American Phonetic Alphabet */
- case HB_TAG('A','R','A',' '): /* Arabic */
- return hb_language_from_string ("ar", -1); /* Arabic [macrolanguage] */
case HB_TAG('A','R','K',' '): /* Rakhine */
return hb_language_from_string ("rki", -1); /* Rakhine */
case HB_TAG('A','T','H',' '): /* Athapaskan */
@@ -2856,12 +2855,6 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("din", -1); /* Dinka [macrolanguage] */
case HB_TAG('D','R','I',' '): /* Dari */
return hb_language_from_string ("prs", -1); /* Dari */
- case HB_TAG('D','Z','N',' '): /* Dzongkha */
- return hb_language_from_string ("dz", -1); /* Dzongkha */
- case HB_TAG('E','T','I',' '): /* Estonian */
- return hb_language_from_string ("et", -1); /* Estonian [macrolanguage] */
- case HB_TAG('F','A','R',' '): /* Persian */
- return hb_language_from_string ("fa", -1); /* Persian [macrolanguage] */
case HB_TAG('G','O','N',' '): /* Gondi */
return hb_language_from_string ("gon", -1); /* Gondi [macrolanguage] */
case HB_TAG('H','M','A',' '): /* High Mari */
@@ -2876,10 +2869,6 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("iba", -1); /* Iban */
case HB_TAG('I','J','O',' '): /* Ijo */
return hb_language_from_string ("ijo", -1); /* Ijo [collection] */
- case HB_TAG('I','N','U',' '): /* Inuktitut */
- return hb_language_from_string ("iu", -1); /* Inuktitut [macrolanguage] */
- case HB_TAG('I','P','K',' '): /* Inupiat */
- return hb_language_from_string ("ik", -1); /* Inupiaq [macrolanguage] */
case HB_TAG('I','P','P','H'): /* Phonetic transcription—IPA conventions */
return hb_language_from_string ("und-fonipa", -1); /* Undetermined; International Phonetic Alphabet */
case HB_TAG('I','R','T',' '): /* Irish Traditional */
@@ -2890,36 +2879,24 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("kln", -1); /* Kalenjin [macrolanguage] */
case HB_TAG('K','G','E',' '): /* Khutsuri Georgian */
return hb_language_from_string ("und-Geok", -1); /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
- case HB_TAG('K','N','R',' '): /* Kanuri */
- return hb_language_from_string ("kr", -1); /* Kanuri [macrolanguage] */
case HB_TAG('K','O','H',' '): /* Korean Old Hangul */
return hb_language_from_string ("okm", -1); /* Middle Korean (10th-16th cent.) */
case HB_TAG('K','O','K',' '): /* Konkani */
return hb_language_from_string ("kok", -1); /* Konkani [macrolanguage] */
- case HB_TAG('K','O','M',' '): /* Komi */
- return hb_language_from_string ("kv", -1); /* Komi [macrolanguage] */
case HB_TAG('K','P','L',' '): /* Kpelle */
return hb_language_from_string ("kpe", -1); /* Kpelle [macrolanguage] */
case HB_TAG('K','R','N',' '): /* Karen */
return hb_language_from_string ("kar", -1); /* Karen [collection] */
case HB_TAG('K','U','I',' '): /* Kui */
return hb_language_from_string ("uki", -1); /* Kui (India) */
- case HB_TAG('K','U','R',' '): /* Kurdish */
- return hb_language_from_string ("ku", -1); /* Kurdish [macrolanguage] */
case HB_TAG('L','M','A',' '): /* Low Mari */
return hb_language_from_string ("mhr", -1); /* Eastern Mari */
case HB_TAG('L','U','H',' '): /* Luyia */
return hb_language_from_string ("luy", -1); /* Luyia [macrolanguage] */
- case HB_TAG('L','V','I',' '): /* Latvian */
- return hb_language_from_string ("lv", -1); /* Latvian [macrolanguage] */
case HB_TAG('M','A','W',' '): /* Marwari */
return hb_language_from_string ("mwr", -1); /* Marwari [macrolanguage] */
- case HB_TAG('M','L','G',' '): /* Malagasy */
- return hb_language_from_string ("mg", -1); /* Malagasy [macrolanguage] */
case HB_TAG('M','L','Y',' '): /* Malay */
return hb_language_from_string ("ms", -1); /* Malay [macrolanguage] */
- case HB_TAG('M','N','G',' '): /* Mongolian */
- return hb_language_from_string ("mn", -1); /* Mongolian [macrolanguage] */
case HB_TAG('M','N','K',' '): /* Maninka */
return hb_language_from_string ("man", -1); /* Mandingo [macrolanguage] */
case HB_TAG('M','O','L',' '): /* Romanian (Moldova) */
@@ -2930,26 +2907,16 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("myn", -1); /* Mayan [collection] */
case HB_TAG('N','A','H',' '): /* Nahuatl */
return hb_language_from_string ("nah", -1); /* Nahuatl [collection] */
- case HB_TAG('N','E','P',' '): /* Nepali */
- return hb_language_from_string ("ne", -1); /* Nepali [macrolanguage] */
case HB_TAG('N','I','S',' '): /* Nisi */
return hb_language_from_string ("njz", -1); /* Nyishi */
case HB_TAG('N','O','R',' '): /* Norwegian */
return hb_language_from_string ("no", -1); /* Norwegian [macrolanguage] */
- case HB_TAG('O','J','B',' '): /* Ojibway */
- return hb_language_from_string ("oj", -1); /* Ojibwa [macrolanguage] */
- case HB_TAG('O','R','O',' '): /* Oromo */
- return hb_language_from_string ("om", -1); /* Oromo [macrolanguage] */
- case HB_TAG('P','A','S',' '): /* Pashto */
- return hb_language_from_string ("ps", -1); /* Pashto [macrolanguage] */
case HB_TAG('P','G','R',' '): /* Polytonic Greek */
return hb_language_from_string ("el-polyton", -1); /* Modern Greek (1453-); Polytonic Greek */
case HB_TAG('P','R','O',' '): /* Provençal / Old Provençal */
return hb_language_from_string ("pro", -1); /* Old Provençal (to 1500) */
case HB_TAG('Q','U','H',' '): /* Quechua (Bolivia) */
return hb_language_from_string ("quh", -1); /* South Bolivian Quechua */
- case HB_TAG('Q','U','Z',' '): /* Quechua */
- return hb_language_from_string ("qu", -1); /* Quechua [macrolanguage] */
case HB_TAG('Q','V','I',' '): /* Quechua (Ecuador) */
return hb_language_from_string ("qvi", -1); /* Imbabura Highland Quichua */
case HB_TAG('Q','W','H',' '): /* Quechua (Peru) */
@@ -2960,10 +2927,6 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
return hb_language_from_string ("ro", -1); /* Romanian */
case HB_TAG('R','O','Y',' '): /* Romany */
return hb_language_from_string ("rom", -1); /* Romany [macrolanguage] */
- case HB_TAG('S','A','N',' '): /* Sanskrit */
- return hb_language_from_string ("sa", -1); /* Sanskrit [macrolanguage] */
- case HB_TAG('S','Q','I',' '): /* Albanian */
- return hb_language_from_string ("sq", -1); /* Albanian [macrolanguage] */
case HB_TAG('S','R','B',' '): /* Serbian */
return hb_language_from_string ("sr", -1); /* Serbian */
case HB_TAG('S','X','T',' '): /* Sutu */
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
index 9149959d79..75ea338e2a 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
@@ -80,7 +80,7 @@ struct AxisValueMap
bool is_outside_axis_range (const Triple& axis_range) const
{
- float from_coord = coords[0].to_float ();
+ double from_coord = (double) coords[0].to_float ();
return !axis_range.contains (from_coord);
}
@@ -100,8 +100,8 @@ struct AxisValueMap
float from_coord = coords[0].to_float ();
float to_coord = coords[1].to_float ();
- from_coord = renormalizeValue (from_coord, unmapped_range, triple_distances);
- to_coord = renormalizeValue (to_coord, axis_range, triple_distances);
+ from_coord = renormalizeValue ((double) from_coord, unmapped_range, triple_distances);
+ to_coord = renormalizeValue ((double) to_coord, axis_range, triple_distances);
coords[0].set_float (from_coord);
coords[1].set_float (to_coord);
@@ -197,7 +197,7 @@ struct SegmentMaps : Array16Of<AxisValueMap>
unmapped_val.set_int (unmap (val.to_int ()));
float unmapped_max = unmapped_val.to_float ();
- return Triple{unmapped_min, unmapped_middle, unmapped_max};
+ return Triple{(double) unmapped_min, (double) unmapped_middle, (double) unmapped_max};
}
bool subset (hb_subset_context_t *c, hb_tag_t axis_tag) const
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-common.hh b/thirdparty/harfbuzz/src/hb-ot-var-common.hh
index 379e164059..08227aa1df 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-common.hh
@@ -299,13 +299,13 @@ struct TupleVariationHeader
start = hb_min (peak, 0.f);
end = hb_max (peak, 0.f);
}
- axis_tuples.set (*axis_tag, Triple (start, peak, end));
+ axis_tuples.set (*axis_tag, Triple ((double) start, (double) peak, (double) end));
}
return true;
}
- float calculate_scalar (hb_array_t<int> coords, unsigned int coord_count,
+ double calculate_scalar (hb_array_t<int> coords, unsigned int coord_count,
const hb_array_t<const F2DOT14> shared_tuples,
const hb_vector_t<hb_pair_t<int,int>> *shared_tuple_active_idx = nullptr) const
{
@@ -321,13 +321,13 @@ struct TupleVariationHeader
{
unsigned int index = get_index ();
if (unlikely ((index + 1) * coord_count > shared_tuples.length))
- return 0.f;
+ return 0.0;
peak_tuple = shared_tuples.sub_array (coord_count * index, coord_count).arrayZ;
if (shared_tuple_active_idx)
{
if (unlikely (index >= shared_tuple_active_idx->length))
- return 0.f;
+ return 0.0;
auto _ = (*shared_tuple_active_idx).arrayZ[index];
if (_.second != -1)
{
@@ -352,7 +352,7 @@ struct TupleVariationHeader
end_tuple = get_end_tuple (coord_count).arrayZ;
}
- float scalar = 1.f;
+ double scalar = 1.0;
for (unsigned int i = start_idx; i < end_idx; i += step)
{
int peak = peak_tuple[i].to_int ();
@@ -367,15 +367,15 @@ struct TupleVariationHeader
int end = end_tuple[i].to_int ();
if (unlikely (start > peak || peak > end ||
(start < 0 && end > 0 && peak))) continue;
- if (v < start || v > end) return 0.f;
+ if (v < start || v > end) return 0.0;
if (v < peak)
- { if (peak != start) scalar *= (float) (v - start) / (peak - start); }
+ { if (peak != start) scalar *= (double) (v - start) / (peak - start); }
else
- { if (peak != end) scalar *= (float) (end - v) / (end - peak); }
+ { if (peak != end) scalar *= (double) (end - v) / (end - peak); }
}
- else if (!v || v < hb_min (0, peak) || v > hb_max (0, peak)) return 0.f;
+ else if (!v || v < hb_min (0, peak) || v > hb_max (0, peak)) return 0.0;
else
- scalar *= (float) v / peak;
+ scalar *= (double) v / peak;
}
return scalar;
}
@@ -444,10 +444,10 @@ struct tuple_delta_t
/* indices_length = point_count, indice[i] = 1 means point i is referenced */
hb_vector_t<bool> indices;
-
- hb_vector_t<float> deltas_x;
+
+ hb_vector_t<double> deltas_x;
/* empty for cvar tuples */
- hb_vector_t<float> deltas_y;
+ hb_vector_t<double> deltas_y;
/* compiled data: header and deltas
* compiled point data is saved in a hashmap within tuple_variations_t cause
@@ -513,9 +513,9 @@ struct tuple_delta_t
return *this;
}
- tuple_delta_t& operator *= (float scalar)
+ tuple_delta_t& operator *= (double scalar)
{
- if (scalar == 1.0f)
+ if (scalar == 1.0)
return *this;
unsigned num = indices.length;
@@ -546,18 +546,18 @@ struct tuple_delta_t
return out;
}
- if ((tent->minimum < 0.f && tent->maximum > 0.f) ||
+ if ((tent->minimum < 0.0 && tent->maximum > 0.0) ||
!(tent->minimum <= tent->middle && tent->middle <= tent->maximum))
return out;
- if (tent->middle == 0.f)
+ if (tent->middle == 0.0)
{
out.push (*this);
return out;
}
- result_t solutions = rebase_tent (*tent, axis_limit, axis_triple_distances);
- for (auto t : solutions)
+ rebase_tent_result_t solutions = rebase_tent (*tent, axis_limit, axis_triple_distances);
+ for (auto &t : solutions)
{
tuple_delta_t new_var = *this;
if (t.second == Triple ())
@@ -729,8 +729,8 @@ struct tuple_delta_t
{ return compile_deltas (indices, deltas_x, deltas_y, compiled_deltas); }
bool compile_deltas (const hb_vector_t<bool> &point_indices,
- const hb_vector_t<float> &x_deltas,
- const hb_vector_t<float> &y_deltas,
+ const hb_vector_t<double> &x_deltas,
+ const hb_vector_t<double> &y_deltas,
hb_vector_t<char> &compiled_deltas /* OUT */)
{
hb_vector_t<int> rounded_deltas;
@@ -1000,9 +1000,13 @@ struct tuple_delta_t
{
i = next_index (i, start_point, end_point);
if (i == next) break;
- deltas_x.arrayZ[i] = infer_delta (orig_points.arrayZ[i].x, orig_points.arrayZ[prev].x, orig_points.arrayZ[next].x,
+ deltas_x.arrayZ[i] = infer_delta ((double) orig_points.arrayZ[i].x,
+ (double) orig_points.arrayZ[prev].x,
+ (double) orig_points.arrayZ[next].x,
deltas_x.arrayZ[prev], deltas_x.arrayZ[next]);
- deltas_y.arrayZ[i] = infer_delta (orig_points.arrayZ[i].y, orig_points.arrayZ[prev].y, orig_points.arrayZ[next].y,
+ deltas_y.arrayZ[i] = infer_delta ((double) orig_points.arrayZ[i].y,
+ (double) orig_points.arrayZ[prev].y,
+ (double) orig_points.arrayZ[next].y,
deltas_y.arrayZ[prev], deltas_y.arrayZ[next]);
inferred_idxes.add (i);
if (--unref_count == 0) goto no_more_gaps;
@@ -1020,8 +1024,8 @@ struct tuple_delta_t
{
if (!inferred_idxes.has (i))
{
- deltas_x.arrayZ[i] = 0.f;
- deltas_y.arrayZ[i] = 0.f;
+ deltas_x.arrayZ[i] = 0.0;
+ deltas_y.arrayZ[i] = 0.0;
}
indices[i] = true;
}
@@ -1031,7 +1035,7 @@ struct tuple_delta_t
bool optimize (const contour_point_vector_t& contour_points,
bool is_composite,
- float tolerance = 0.5f)
+ double tolerance = 0.5 + 1e-10)
{
unsigned count = contour_points.length;
if (deltas_x.length != count ||
@@ -1062,7 +1066,7 @@ struct tuple_delta_t
if (ref_count == count) return true;
- hb_vector_t<float> opt_deltas_x, opt_deltas_y;
+ hb_vector_t<double> opt_deltas_x, opt_deltas_y;
bool is_comp_glyph_wo_deltas = (is_composite && ref_count == 0);
if (is_comp_glyph_wo_deltas)
{
@@ -1194,16 +1198,16 @@ struct tuple_delta_t
return compiled_points.resize (pos, false);
}
- static float infer_delta (float target_val, float prev_val, float next_val, float prev_delta, float next_delta)
+ static double infer_delta (double target_val, double prev_val, double next_val, double prev_delta, double next_delta)
{
if (prev_val == next_val)
- return (prev_delta == next_delta) ? prev_delta : 0.f;
+ return (prev_delta == next_delta) ? prev_delta : 0.0;
else if (target_val <= hb_min (prev_val, next_val))
return (prev_val < next_val) ? prev_delta : next_delta;
else if (target_val >= hb_max (prev_val, next_val))
return (prev_val > next_val) ? prev_delta : next_delta;
- float r = (target_val - prev_val) / (next_val - prev_val);
+ double r = (target_val - prev_val) / (next_val - prev_val);
return prev_delta + r * (next_delta - prev_delta);
}
@@ -1347,9 +1351,9 @@ struct TupleVariationData
unsigned idx = apply_to_all ? i : indices[i];
if (idx >= point_count) continue;
var.indices[idx] = true;
- var.deltas_x[idx] = static_cast<float> (deltas_x[i]);
+ var.deltas_x[idx] = deltas_x[i];
if (is_gvar)
- var.deltas_y[idx] = static_cast<float> (deltas_y[i]);
+ var.deltas_y[idx] = deltas_y[i];
}
tuple_vars.push (std::move (var));
} while (iterator.move_to_next ());
@@ -1367,15 +1371,15 @@ struct TupleVariationData
/* NULL offset, to keep original varidx valid, just return */
if (&var_data == &Null (VarData))
return true;
-
+
unsigned num_regions = var_data.get_region_index_count ();
if (!tuple_vars.alloc (num_regions)) return false;
-
+
item_count = inner_map ? inner_map->get_population () : var_data.get_item_count ();
if (!item_count) return true;
unsigned row_size = var_data.get_row_size ();
const HBUINT8 *delta_bytes = var_data.get_delta_bytes ();
-
+
for (unsigned r = 0; r < num_regions; r++)
{
/* In VarData, deltas are organized in rows, convert them into
@@ -1384,14 +1388,14 @@ struct TupleVariationData
if (!tuple.deltas_x.resize (item_count, false) ||
!tuple.indices.resize (item_count, false))
return false;
-
+
for (unsigned i = 0; i < item_count; i++)
{
tuple.indices.arrayZ[i] = true;
tuple.deltas_x.arrayZ[i] = var_data.get_item_delta_fast (inner_map ? inner_map->backward (i) : i,
r, delta_bytes, row_size);
}
-
+
unsigned region_index = var_data.get_region_index (r);
if (region_index >= regions.length) return false;
tuple.axis_tuples = regions.arrayZ[region_index];
@@ -1425,7 +1429,7 @@ struct TupleVariationData
Triple *axis_limit;
if (!normalized_axes_location.has (axis_tag, &axis_limit))
return false;
- TripleDistances axis_triple_distances{1.f, 1.f};
+ TripleDistances axis_triple_distances{1.0, 1.0};
if (axes_triple_distances.has (axis_tag))
axis_triple_distances = axes_triple_distances.get (axis_tag);
@@ -1503,11 +1507,11 @@ struct TupleVariationData
return false;
continue;
}
-
+
hb_vector_t<char> compiled_point_data;
if (!tuple_delta_t::compile_point_set (*points_set, compiled_point_data))
return false;
-
+
if (!point_data_map.set (points_set, std::move (compiled_point_data)) ||
!point_set_count_map.set (points_set, 1))
return false;
@@ -1547,7 +1551,7 @@ struct TupleVariationData
for (tuple_delta_t& var : tuple_vars)
if (!var.calc_inferred_deltas (contour_points))
return false;
-
+
return true;
}
@@ -1874,7 +1878,7 @@ struct TupleVariationData
if (!tuple_variations.serialize_var_headers (c, total_header_len))
return_trace (false);
-
+
unsigned data_offset = min_size + total_header_len;
if (!is_gvar) data_offset += 4;
if (!c->check_assign (out->data, data_offset, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
@@ -2335,12 +2339,12 @@ struct item_variations_t
/* just sanity check, this shouldn't happen */
if (encoding.is_empty ())
return false;
-
+
unsigned num_rows = encoding.items.length;
-
+
/* sort rows, make result deterministic */
encoding.items.qsort (_cmp_row);
-
+
/* compile old to new var_idxes mapping */
for (unsigned minor = 0; minor < num_rows; minor++)
{
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
index 07d7586baa..2cd9afbb70 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
@@ -43,7 +43,7 @@ static bool axis_coord_pinned_or_within_axis_range (const hb_array_t<const F16DO
unsigned axis_index,
Triple axis_limit)
{
- float axis_coord = coords[axis_index].to_float ();
+ double axis_coord = static_cast<double>(coords[axis_index].to_float ());
if (axis_limit.is_point ())
{
if (axis_limit.minimum != axis_coord)
@@ -233,7 +233,10 @@ struct AxisRecord
{
float min, default_, max;
get_coordinates (min, default_, max);
- return TripleDistances (min, default_, max);
+ return TripleDistances (
+ static_cast<double>(min),
+ static_cast<double>(default_),
+ static_cast<double>(max));
}
bool subset (hb_subset_context_t *c) const
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
index 59aad57e37..d713084faf 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
@@ -102,9 +102,8 @@ struct glyph_variations_t
}
bool is_composite_glyph = false;
-#ifdef HB_EXPERIMENTAL_API
is_composite_glyph = plan->composite_new_gids.has (new_gid);
-#endif
+
if (!p->decompile_tuple_variations (all_contour_points->length, true /* is_gvar */,
iterator, &(plan->axes_old_index_tag_map),
shared_indices, shared_tuples,
@@ -120,9 +119,7 @@ struct glyph_variations_t
{
unsigned count = plan->new_to_old_gid_list.length;
bool iup_optimize = false;
-#ifdef HB_EXPERIMENTAL_API
iup_optimize = plan->flags & HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS;
-#endif
for (unsigned i = 0; i < count; i++)
{
hb_codepoint_t new_gid = plan->new_to_old_gid_list[i].first;
diff --git a/thirdparty/harfbuzz/src/hb-repacker.hh b/thirdparty/harfbuzz/src/hb-repacker.hh
index ed40f271cc..cb4fdeead2 100644
--- a/thirdparty/harfbuzz/src/hb-repacker.hh
+++ b/thirdparty/harfbuzz/src/hb-repacker.hh
@@ -337,9 +337,10 @@ bool _process_overflows (const hb_vector_t<graph::overflow_record_t>& overflows,
inline bool
hb_resolve_graph_overflows (hb_tag_t table_tag,
unsigned max_rounds ,
- bool recalculate_extensions,
+ bool always_recalculate_extensions,
graph_t& sorted_graph /* IN/OUT */)
{
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Repacking %c%c%c%c.", HB_UNTAG(table_tag));
sorted_graph.sort_shortest_distance ();
if (sorted_graph.in_error ())
{
@@ -351,12 +352,12 @@ hb_resolve_graph_overflows (hb_tag_t table_tag,
if (!will_overflow)
return true;
+ bool is_gsub_or_gpos = (table_tag == HB_OT_TAG_GPOS || table_tag == HB_OT_TAG_GSUB);
graph::gsubgpos_graph_context_t ext_context (table_tag, sorted_graph);
- if ((table_tag == HB_OT_TAG_GPOS
- || table_tag == HB_OT_TAG_GSUB)
- && will_overflow)
+ if (is_gsub_or_gpos && will_overflow)
{
- if (recalculate_extensions)
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Applying GSUB/GPOS repacking specializations.");
+ if (always_recalculate_extensions)
{
DEBUG_MSG (SUBSET_REPACK, nullptr, "Splitting subtables if needed.");
if (!_presplit_subtables_if_needed (ext_context)) {
@@ -412,6 +413,13 @@ hb_resolve_graph_overflows (hb_tag_t table_tag,
if (graph::will_overflow (sorted_graph))
{
+ if (is_gsub_or_gpos && !always_recalculate_extensions) {
+ // If this a GSUB/GPOS table and we didn't try to extension promotion and table splitting then
+ // as a last ditch effort, re-run the repacker with it enabled.
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Failed to find a resolution. Re-running with extension promotion and table splitting enabled.");
+ return hb_resolve_graph_overflows (table_tag, max_rounds, true, sorted_graph);
+ }
+
DEBUG_MSG (SUBSET_REPACK, nullptr, "Offset overflow resolution failed.");
return false;
}
diff --git a/thirdparty/harfbuzz/src/hb-set-digest.hh b/thirdparty/harfbuzz/src/hb-set-digest.hh
index 5681641baa..b718b94e69 100644
--- a/thirdparty/harfbuzz/src/hb-set-digest.hh
+++ b/thirdparty/harfbuzz/src/hb-set-digest.hh
@@ -82,7 +82,9 @@ struct hb_set_digest_bits_pattern_t
void init () { mask = 0; }
- void add (const hb_set_digest_bits_pattern_t &o) { mask |= o.mask; }
+ static hb_set_digest_bits_pattern_t full () { hb_set_digest_bits_pattern_t d; d.mask = (mask_t) -1; return d; }
+
+ void union_ (const hb_set_digest_bits_pattern_t &o) { mask |= o.mask; }
void add (hb_codepoint_t g) { mask |= mask_for (g); }
@@ -129,11 +131,14 @@ struct hb_set_digest_bits_pattern_t
bool may_have (hb_codepoint_t g) const
{ return mask & mask_for (g); }
+ bool operator [] (hb_codepoint_t g) const
+ { return may_have (g); }
+
private:
static mask_t mask_for (hb_codepoint_t g)
{ return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); }
- mask_t mask;
+ mask_t mask = 0;
};
template <typename head_t, typename tail_t>
@@ -145,10 +150,12 @@ struct hb_set_digest_combiner_t
tail.init ();
}
- void add (const hb_set_digest_combiner_t &o)
+ static hb_set_digest_combiner_t full () { hb_set_digest_combiner_t d; d.head = head_t::full(); d.tail = tail_t::full (); return d; }
+
+ void union_ (const hb_set_digest_combiner_t &o)
{
- head.add (o.head);
- tail.add (o.tail);
+ head.union_ (o.head);
+ tail.union_(o.tail);
}
void add (hb_codepoint_t g)
@@ -188,6 +195,9 @@ struct hb_set_digest_combiner_t
return head.may_have (g) && tail.may_have (g);
}
+ bool operator [] (hb_codepoint_t g) const
+ { return may_have (g); }
+
private:
head_t head;
tail_t tail;
diff --git a/thirdparty/harfbuzz/src/hb-set.hh b/thirdparty/harfbuzz/src/hb-set.hh
index ce69ea2c9b..f6013a4141 100644
--- a/thirdparty/harfbuzz/src/hb-set.hh
+++ b/thirdparty/harfbuzz/src/hb-set.hh
@@ -86,7 +86,7 @@ struct hb_sparseset_t
uint32_t hash () const { return s.hash (); }
void add (hb_codepoint_t g) { s.add (g); }
- bool add_range (hb_codepoint_t a, hb_codepoint_t b) { return s.add_range (a, b); }
+ bool add_range (hb_codepoint_t first, hb_codepoint_t last) { return s.add_range (first, last); }
template <typename T>
void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
diff --git a/thirdparty/harfbuzz/src/hb-subset-cff-common.hh b/thirdparty/harfbuzz/src/hb-subset-cff-common.hh
index 462e99cf8c..4039f9c959 100644
--- a/thirdparty/harfbuzz/src/hb-subset-cff-common.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-cff-common.hh
@@ -115,7 +115,7 @@ struct str_encoder_t
encode_byte (OpCode_BCD);
// Based on:
- // https://github.com/fonttools/fonttools/blob/97ed3a61cde03e17b8be36f866192fbd56f1d1a7/Lib/fontTools/misc/psCharStrings.py#L265-L294
+ // https://github.com/fonttools/fonttools/blob/0738c41dfbcbc213ab9263f486ef0cccc6eb5ce5/Lib/fontTools/misc/psCharStrings.py#L267-L316
char buf[16];
/* FontTools has the following comment:
@@ -133,6 +133,10 @@ struct str_encoder_t
(void) hb_uselocale (((void) freelocale (clocale), oldlocale));
char *s = buf;
+ size_t len;
+ char *comma = strchr (s, ',');
+ if (comma) // Comma for some European locales in case no uselocale available.
+ *comma = '.';
if (s[0] == '0' && s[1] == '.')
s++;
else if (s[0] == '-' && s[1] == '0' && s[2] == '.')
@@ -140,6 +144,45 @@ struct str_encoder_t
s[1] = '-';
s++;
}
+ else if ((len = strlen (s)) > 3 && !strcmp (s + len - 3, "000"))
+ {
+ unsigned exponent = len - 3;
+ char *s2 = s + exponent - 1;
+ while (*s2 == '0' && exponent > 1)
+ {
+ s2--;
+ exponent++;
+ }
+ snprintf (s2 + 1, sizeof (buf) - (s2 + 1 - buf), "E%u", exponent);
+ }
+ else
+ {
+ char *dot = strchr (s, '.');
+ char *e = strchr (s, 'E');
+ if (dot && e)
+ {
+ memmove (dot, dot + 1, e - (dot + 1));
+ int exponent = atoi (e + 1);
+ int new_exponent = exponent - (e - (dot + 1));
+ if (new_exponent == 1)
+ {
+ e[-1] = '0';
+ e[0] = '\0';
+ }
+ else
+ snprintf (e - 1, sizeof (buf) - (e - 1 - buf), "E%d", new_exponent);
+ }
+ }
+ if ((s[0] == '.' && s[1] == '0') || (s[0] == '-' && s[1] == '.' && s[2] == '0'))
+ {
+ int sign = s[0] == '-';
+ char *s2 = s + sign + 1;
+ while (*s2 == '0')
+ s2++;
+ len = strlen (s2);
+ memmove (s + sign, s2, len);
+ snprintf (s + sign + len, sizeof (buf) - (s + sign + len - buf), "E-%u", (unsigned) (strlen (s + sign) - 1));
+ }
hb_vector_t<char> nibbles;
while (*s)
{
@@ -155,20 +198,22 @@ struct str_encoder_t
{
s++;
nibbles.push (0x0C); // E-
- continue;
+ } else {
+ if (c2 == '+')
+ s++;
+ nibbles.push (0x0B); // E
}
- if (c2 == '+')
+ if (*s == '0')
s++;
- nibbles.push (0x0B); // E
continue;
}
- case '.': case ',': // Comma for some European locales in case no uselocale available.
+ case '.':
nibbles.push (0x0A); // .
continue;
case '-':
- nibbles.push (0x0E); // .
+ nibbles.push (0x0E); // -
continue;
}
diff --git a/thirdparty/harfbuzz/src/hb-subset-cff2.cc b/thirdparty/harfbuzz/src/hb-subset-cff2.cc
index eb5cb0c625..9c9117d52f 100644
--- a/thirdparty/harfbuzz/src/hb-subset-cff2.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-cff2.cc
@@ -666,6 +666,9 @@ OT::cff2::accelerator_subset_t::serialize (hb_serialize_context_t *c,
bool
OT::cff2::accelerator_subset_t::subset (hb_subset_context_t *c) const
{
+ if (c->plan->normalized_coords && !c->plan->all_axes_pinned)
+ fprintf (stdout, "warning: CFF partial instancing is not supported.\n");
+
cff2_subset_plan cff2_plan;
if (unlikely (!cff2_plan.create (*this, c->plan))) return false;
diff --git a/thirdparty/harfbuzz/src/hb-subset-input.cc b/thirdparty/harfbuzz/src/hb-subset-input.cc
index 68a3e77788..8974755a75 100644
--- a/thirdparty/harfbuzz/src/hb-subset-input.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-input.cc
@@ -446,7 +446,7 @@ hb_subset_input_pin_all_axes_to_default (hb_subset_input_t *input,
for (unsigned i = 0; i < axis_count; i++)
{
hb_tag_t axis_tag = axis_infos[i].tag;
- float default_val = axis_infos[i].default_value;
+ double default_val = (double) axis_infos[i].default_value;
if (!input->axes_location.set (axis_tag, Triple (default_val, default_val, default_val)))
{
hb_free (axis_infos);
@@ -481,7 +481,7 @@ hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
return false;
- float default_val = axis_info.default_value;
+ double default_val = (double) axis_info.default_value;
return input->axes_location.set (axis_tag, Triple (default_val, default_val, default_val));
}
@@ -511,11 +511,10 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input,
if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
return false;
- float val = hb_clamp(axis_value, axis_info.min_value, axis_info.max_value);
+ double val = hb_clamp((double) axis_value, (double) axis_info.min_value, (double) axis_info.max_value);
return input->axes_location.set (axis_tag, Triple (val, val, val));
}
-#ifdef HB_EXPERIMENTAL_API
/**
* hb_subset_input_set_axis_range: (skip)
* @input: a #hb_subset_input_t object.
@@ -538,7 +537,7 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input,
*
* Return value: `true` if success, `false` otherwise
*
- * XSince: EXPERIMENTAL
+ * Since: 8.5.0
**/
HB_EXTERN hb_bool_t
hb_subset_input_set_axis_range (hb_subset_input_t *input,
@@ -562,7 +561,7 @@ hb_subset_input_set_axis_range (hb_subset_input_t *input,
float new_min_val = hb_clamp(min, axis_info.min_value, axis_info.max_value);
float new_max_val = hb_clamp(max, axis_info.min_value, axis_info.max_value);
float new_default_val = hb_clamp(def, new_min_val, new_max_val);
- return input->axes_location.set (axis_tag, Triple (new_min_val, new_default_val, new_max_val));
+ return input->axes_location.set (axis_tag, Triple ((double) new_min_val, (double) new_default_val, (double) new_max_val));
}
/**
@@ -577,7 +576,7 @@ hb_subset_input_set_axis_range (hb_subset_input_t *input,
*
* Return value: `true` if a range has been set for this axis tag, `false` otherwise.
*
- * XSince: EXPERIMENTAL
+ * Since: 8.5.0
**/
HB_EXTERN hb_bool_t
hb_subset_input_get_axis_range (hb_subset_input_t *input,
@@ -598,7 +597,6 @@ hb_subset_input_get_axis_range (hb_subset_input_t *input,
return true;
}
#endif
-#endif
/**
* hb_subset_preprocess:
@@ -746,5 +744,4 @@ hb_subset_input_override_name_table (hb_subset_input_t *input,
input->name_table_overrides.set (hb_ot_name_record_ids_t (platform_id, encoding_id, language_id, name_id), name_bytes);
return true;
}
-
#endif
diff --git a/thirdparty/harfbuzz/src/hb-subset-instancer-iup.cc b/thirdparty/harfbuzz/src/hb-subset-instancer-iup.cc
index 35a964d082..074657acaf 100644
--- a/thirdparty/harfbuzz/src/hb-subset-instancer-iup.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-instancer-iup.cc
@@ -38,7 +38,7 @@ static void _iup_contour_bound_forced_set (const hb_array_t<const contour_point_
const hb_array_t<const int> x_deltas,
const hb_array_t<const int> y_deltas,
hb_set_t& forced_set, /* OUT */
- float tolerance = 0.f)
+ double tolerance = 0.0)
{
unsigned len = contour_points.length;
unsigned next_i = 0;
@@ -47,28 +47,28 @@ static void _iup_contour_bound_forced_set (const hb_array_t<const contour_point_
unsigned last_i = (len + i -1) % len;
for (unsigned j = 0; j < 2; j++)
{
- float cj, lcj, ncj;
+ double cj, lcj, ncj;
int dj, ldj, ndj;
if (j == 0)
{
- cj = contour_points.arrayZ[i].x;
+ cj = static_cast<double> (contour_points.arrayZ[i].x);
dj = x_deltas.arrayZ[i];
- lcj = contour_points.arrayZ[last_i].x;
+ lcj = static_cast<double> (contour_points.arrayZ[last_i].x);
ldj = x_deltas.arrayZ[last_i];
- ncj = contour_points.arrayZ[next_i].x;
+ ncj = static_cast<double> (contour_points.arrayZ[next_i].x);
ndj = x_deltas.arrayZ[next_i];
}
else
{
- cj = contour_points.arrayZ[i].y;
+ cj = static_cast<double> (contour_points.arrayZ[i].y);
dj = y_deltas.arrayZ[i];
- lcj = contour_points.arrayZ[last_i].y;
+ lcj = static_cast<double> (contour_points.arrayZ[last_i].y);
ldj = y_deltas.arrayZ[last_i];
- ncj = contour_points.arrayZ[next_i].y;
+ ncj = static_cast<double> (contour_points.arrayZ[next_i].y);
ndj = y_deltas.arrayZ[next_i];
}
- float c1, c2;
+ double c1, c2;
int d1, d2;
if (lcj <= ncj)
{
@@ -180,8 +180,8 @@ static bool _iup_segment (const hb_array_t<const contour_point_t> contour_points
const contour_point_t& p1, const contour_point_t& p2,
int p1_dx, int p2_dx,
int p1_dy, int p2_dy,
- hb_vector_t<float>& interp_x_deltas, /* OUT */
- hb_vector_t<float>& interp_y_deltas /* OUT */)
+ hb_vector_t<double>& interp_x_deltas, /* OUT */
+ hb_vector_t<double>& interp_y_deltas /* OUT */)
{
unsigned n = contour_points.length;
if (unlikely (!interp_x_deltas.resize (n, false) ||
@@ -190,20 +190,20 @@ static bool _iup_segment (const hb_array_t<const contour_point_t> contour_points
for (unsigned j = 0; j < 2; j++)
{
- float x1, x2, d1, d2;
- float *out;
+ double x1, x2, d1, d2;
+ double *out;
if (j == 0)
{
- x1 = p1.x;
- x2 = p2.x;
+ x1 = static_cast<double> (p1.x);
+ x2 = static_cast<double> (p2.x);
d1 = p1_dx;
d2 = p2_dx;
out = interp_x_deltas.arrayZ;
}
else
{
- x1 = p1.y;
- x2 = p2.y;
+ x1 = static_cast<double> (p1.y);
+ x2 = static_cast<double> (p2.y);
d1 = p1_dy;
d2 = p2_dy;
out = interp_y_deltas.arrayZ;
@@ -219,7 +219,7 @@ static bool _iup_segment (const hb_array_t<const contour_point_t> contour_points
else
{
for (unsigned i = 0; i < n; i++)
- out[i] = 0.f;
+ out[i] = 0.0;
}
continue;
}
@@ -230,11 +230,11 @@ static bool _iup_segment (const hb_array_t<const contour_point_t> contour_points
hb_swap (d1, d2);
}
- float scale = (d2 - d1) / (x2 - x1);
+ double scale = (d2 - d1) / (x2 - x1);
for (unsigned i = 0; i < n; i++)
{
- float x = j == 0 ? contour_points.arrayZ[i].x : contour_points.arrayZ[i].y;
- float d;
+ double x = (j == 0 ? static_cast<double> (contour_points.arrayZ[i].x) : static_cast<double> (contour_points.arrayZ[i].y));
+ double d;
if (x <= x1)
d = d1;
else if (x >= x2)
@@ -254,9 +254,9 @@ static bool _can_iup_in_between (const hb_array_t<const contour_point_t> contour
const contour_point_t& p1, const contour_point_t& p2,
int p1_dx, int p2_dx,
int p1_dy, int p2_dy,
- float tolerance)
+ double tolerance)
{
- hb_vector_t<float> interp_x_deltas, interp_y_deltas;
+ hb_vector_t<double> interp_x_deltas, interp_y_deltas;
if (!_iup_segment (contour_points, x_deltas, y_deltas,
p1, p2, p1_dx, p2_dx, p1_dy, p2_dy,
interp_x_deltas, interp_y_deltas))
@@ -266,10 +266,10 @@ static bool _can_iup_in_between (const hb_array_t<const contour_point_t> contour
for (unsigned i = 0; i < num; i++)
{
- float dx = x_deltas.arrayZ[i] - interp_x_deltas.arrayZ[i];
- float dy = y_deltas.arrayZ[i] - interp_y_deltas.arrayZ[i];
+ double dx = static_cast<double> (x_deltas.arrayZ[i]) - interp_x_deltas.arrayZ[i];
+ double dy = static_cast<double> (y_deltas.arrayZ[i]) - interp_y_deltas.arrayZ[i];
- if (sqrtf ((float)dx * dx + (float)dy * dy) > tolerance)
+ if (sqrt (dx * dx + dy * dy) > tolerance)
return false;
}
return true;
@@ -279,7 +279,7 @@ static bool _iup_contour_optimize_dp (const contour_point_vector_t& contour_poin
const hb_vector_t<int>& x_deltas,
const hb_vector_t<int>& y_deltas,
const hb_set_t& forced_set,
- float tolerance,
+ double tolerance,
unsigned lookback,
hb_vector_t<unsigned>& costs, /* OUT */
hb_vector_t<int>& chain /* OUT */)
@@ -333,7 +333,7 @@ static bool _iup_contour_optimize (const hb_array_t<const contour_point_t> conto
const hb_array_t<const int> x_deltas,
const hb_array_t<const int> y_deltas,
hb_array_t<bool> opt_indices, /* OUT */
- float tolerance = 0.f)
+ double tolerance = 0.0)
{
unsigned n = contour_points.length;
if (opt_indices.length != n ||
@@ -346,7 +346,7 @@ static bool _iup_contour_optimize (const hb_array_t<const contour_point_t> conto
{
int dx = x_deltas.arrayZ[i];
int dy = y_deltas.arrayZ[i];
- if (sqrtf ((float)dx * dx + (float)dy * dy) > tolerance)
+ if (sqrt ((double) dx * dx + (double) dy * dy) > tolerance)
{
all_within_tolerance = false;
break;
@@ -443,11 +443,11 @@ static bool _iup_contour_optimize (const hb_array_t<const contour_point_t> conto
unsigned contour_point_size = hb_static_size (contour_point_t);
for (unsigned i = 0; i < n; i++)
{
- hb_memcpy ((void *) repeat_x_deltas.arrayZ, (const void *) x_deltas.arrayZ, n * sizeof (float));
- hb_memcpy ((void *) (repeat_x_deltas.arrayZ + n), (const void *) x_deltas.arrayZ, n * sizeof (float));
+ hb_memcpy ((void *) repeat_x_deltas.arrayZ, (const void *) x_deltas.arrayZ, n * sizeof (repeat_x_deltas[0]));
+ hb_memcpy ((void *) (repeat_x_deltas.arrayZ + n), (const void *) x_deltas.arrayZ, n * sizeof (repeat_x_deltas[0]));
- hb_memcpy ((void *) repeat_y_deltas.arrayZ, (const void *) y_deltas.arrayZ, n * sizeof (float));
- hb_memcpy ((void *) (repeat_y_deltas.arrayZ + n), (const void *) y_deltas.arrayZ, n * sizeof (float));
+ hb_memcpy ((void *) repeat_y_deltas.arrayZ, (const void *) y_deltas.arrayZ, n * sizeof (repeat_x_deltas[0]));
+ hb_memcpy ((void *) (repeat_y_deltas.arrayZ + n), (const void *) y_deltas.arrayZ, n * sizeof (repeat_x_deltas[0]));
hb_memcpy ((void *) repeat_points.arrayZ, (const void *) contour_points.arrayZ, n * contour_point_size);
hb_memcpy ((void *) (repeat_points.arrayZ + n), (const void *) contour_points.arrayZ, n * contour_point_size);
@@ -496,7 +496,7 @@ bool iup_delta_optimize (const contour_point_vector_t& contour_points,
const hb_vector_t<int>& x_deltas,
const hb_vector_t<int>& y_deltas,
hb_vector_t<bool>& opt_indices, /* OUT */
- float tolerance)
+ double tolerance)
{
if (!opt_indices.resize (contour_points.length))
return false;
diff --git a/thirdparty/harfbuzz/src/hb-subset-instancer-iup.hh b/thirdparty/harfbuzz/src/hb-subset-instancer-iup.hh
index 7eac5935a4..01987bd258 100644
--- a/thirdparty/harfbuzz/src/hb-subset-instancer-iup.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-instancer-iup.hh
@@ -32,6 +32,6 @@ HB_INTERNAL bool iup_delta_optimize (const contour_point_vector_t& contour_point
const hb_vector_t<int>& x_deltas,
const hb_vector_t<int>& y_deltas,
hb_vector_t<bool>& opt_indices, /* OUT */
- float tolerance = 0.f);
+ double tolerance = 0.0);
#endif /* HB_SUBSET_INSTANCER_IUP_HH */
diff --git a/thirdparty/harfbuzz/src/hb-subset-instancer-solver.cc b/thirdparty/harfbuzz/src/hb-subset-instancer-solver.cc
index 70783c0a0d..ca903e2707 100644
--- a/thirdparty/harfbuzz/src/hb-subset-instancer-solver.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-instancer-solver.cc
@@ -32,17 +32,17 @@
* This should be safe.
*/
-constexpr static float EPSILON = 1.f / (1 << 14);
-constexpr static float MAX_F2DOT14 = float (0x7FFF) / (1 << 14);
+constexpr static double EPSILON = 1.0 / (1 << 14);
+constexpr static double MAX_F2DOT14 = double (0x7FFF) / (1 << 14);
static inline Triple _reverse_negate(const Triple &v)
{ return {-v.maximum, -v.middle, -v.minimum}; }
-static inline float supportScalar (float coord, const Triple &tent)
+static inline double supportScalar (double coord, const Triple &tent)
{
/* Copied from VarRegionAxis::evaluate() */
- float start = tent.minimum, peak = tent.middle, end = tent.maximum;
+ double start = tent.minimum, peak = tent.middle, end = tent.maximum;
if (unlikely (start > peak || peak > end))
return 1.;
@@ -62,20 +62,20 @@ static inline float supportScalar (float coord, const Triple &tent)
return (end - coord) / (end - peak);
}
-static inline result_t
+static inline rebase_tent_result_t
_solve (Triple tent, Triple axisLimit, bool negative = false)
{
- float axisMin = axisLimit.minimum;
- float axisDef = axisLimit.middle;
- float axisMax = axisLimit.maximum;
- float lower = tent.minimum;
- float peak = tent.middle;
- float upper = tent.maximum;
+ double axisMin = axisLimit.minimum;
+ double axisDef = axisLimit.middle;
+ double axisMax = axisLimit.maximum;
+ double lower = tent.minimum;
+ double peak = tent.middle;
+ double upper = tent.maximum;
// Mirror the problem such that axisDef <= peak
if (axisDef > peak)
{
- result_t vec = _solve (_reverse_negate (tent),
+ rebase_tent_result_t vec = _solve (_reverse_negate (tent),
_reverse_negate (axisLimit),
!negative);
@@ -98,7 +98,7 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
* axisMin axisDef axisMax lower upper
*/
if (axisMax <= lower && axisMax < peak)
- return result_t{}; // No overlap
+ return rebase_tent_result_t{}; // No overlap
/* case 2: Only the peak and outermost bound fall outside the new limit;
* we keep the deltaset, update peak and outermost bound and scale deltas
@@ -130,10 +130,10 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
*/
if (axisMax < peak)
{
- float mult = supportScalar (axisMax, tent);
+ double mult = supportScalar (axisMax, tent);
tent = Triple{lower, axisMax, axisMax};
- result_t vec = _solve (tent, axisLimit);
+ rebase_tent_result_t vec = _solve (tent, axisLimit);
for (auto &p : vec)
p = hb_pair (p.first * mult, p.second);
@@ -143,13 +143,13 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
// lower <= axisDef <= peak <= axisMax
- float gain = supportScalar (axisDef, tent);
- result_t out {hb_pair (gain, Triple{})};
+ double gain = supportScalar (axisDef, tent);
+ rebase_tent_result_t out {hb_pair (gain, Triple{})};
// First, the positive side
// outGain is the scalar of axisMax at the tent.
- float outGain = supportScalar (axisMax, tent);
+ double outGain = supportScalar (axisMax, tent);
/* Case 3a: Gain is more than outGain. The tent down-slope crosses
* the axis into negative. We have to split it into multiples.
@@ -173,10 +173,10 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
// Note that this is the branch taken if both gain and outGain are 0.
// Crossing point on the axis.
- float crossing = peak + (1 - gain) * (upper - peak);
+ double crossing = peak + (1 - gain) * (upper - peak);
Triple loc{hb_max (lower, axisDef), peak, crossing};
- float scalar = 1.f;
+ double scalar = 1.0;
// The part before the crossing point.
out.push (hb_pair (scalar - gain, loc));
@@ -191,7 +191,7 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
if (upper >= axisMax)
{
Triple loc {crossing, axisMax, axisMax};
- float scalar = outGain;
+ double scalar = outGain;
out.push (hb_pair (scalar - gain, loc));
}
@@ -221,11 +221,11 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
// Downslope.
Triple loc1 {crossing, upper, axisMax};
- float scalar1 = 0.f;
+ double scalar1 = 0.0;
// Eternity justify.
Triple loc2 {upper, axisMax, axisMax};
- float scalar2 = 0.f;
+ double scalar2 = 0.0;
out.push (hb_pair (scalar1 - gain, loc1));
out.push (hb_pair (scalar2 - gain, loc2));
@@ -254,11 +254,11 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
* | | newUpper
* axisDef axisMax
*/
- float newUpper = peak + (1 - gain) * (upper - peak);
+ double newUpper = peak + (1 - gain) * (upper - peak);
assert (axisMax <= newUpper); // Because outGain > gain
/* Disabled because ots doesn't like us:
* https://github.com/fonttools/fonttools/issues/3350 */
-
+
if (false && (newUpper <= axisDef + (axisMax - axisDef) * 2))
{
upper = newUpper;
@@ -270,7 +270,7 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
}
Triple loc {hb_max (axisDef, lower), peak, upper};
- float scalar = 1.f;
+ double scalar = 1.0;
out.push (hb_pair (scalar - gain, loc));
}
@@ -294,10 +294,10 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
else
{
Triple loc1 {hb_max (axisDef, lower), peak, axisMax};
- float scalar1 = 1.f;
+ double scalar1 = 1.0;
Triple loc2 {peak, axisMax, axisMax};
- float scalar2 = outGain;
+ double scalar2 = outGain;
out.push (hb_pair (scalar1 - gain, loc1));
// Don't add a dirac delta!
@@ -325,7 +325,7 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
if (lower <= axisMin)
{
Triple loc {axisMin, axisMin, axisDef};
- float scalar = supportScalar (axisMin, tent);
+ double scalar = supportScalar (axisMin, tent);
out.push (hb_pair (scalar - gain, loc));
}
@@ -353,11 +353,11 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
// Downslope.
Triple loc1 {axisMin, lower, axisDef};
- float scalar1 = 0.f;
+ double scalar1 = 0.0;
// Eternity justify.
Triple loc2 {axisMin, axisMin, lower};
- float scalar2 = 0.f;
+ double scalar2 = 0.0;
out.push (hb_pair (scalar1 - gain, loc1));
out.push (hb_pair (scalar2 - gain, loc2));
@@ -369,19 +369,19 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
static inline TripleDistances _reverse_triple_distances (const TripleDistances &v)
{ return TripleDistances (v.positive, v.negative); }
-float renormalizeValue (float v, const Triple &triple,
- const TripleDistances &triple_distances, bool extrapolate)
+double renormalizeValue (double v, const Triple &triple,
+ const TripleDistances &triple_distances, bool extrapolate)
{
- float lower = triple.minimum, def = triple.middle, upper = triple.maximum;
+ double lower = triple.minimum, def = triple.middle, upper = triple.maximum;
assert (lower <= def && def <= upper);
if (!extrapolate)
v = hb_max (hb_min (v, upper), lower);
if (v == def)
- return 0.f;
+ return 0.0;
- if (def < 0.f)
+ if (def < 0.0)
return -renormalizeValue (-v, _reverse_negate (triple),
_reverse_triple_distances (triple_distances), extrapolate);
@@ -390,14 +390,14 @@ float renormalizeValue (float v, const Triple &triple,
return (v - def) / (upper - def);
/* v < def */
- if (lower >= 0.f)
+ if (lower >= 0.0)
return (v - def) / (def - lower);
/* lower < 0 and v < default */
- float total_distance = triple_distances.negative * (-lower) + triple_distances.positive * def;
+ double total_distance = triple_distances.negative * (-lower) + triple_distances.positive * def;
- float v_distance;
- if (v >= 0.f)
+ double v_distance;
+ if (v >= 0.0)
v_distance = (def - v) * triple_distances.positive;
else
v_distance = (-v) * triple_distances.negative + triple_distances.positive * def;
@@ -405,18 +405,18 @@ float renormalizeValue (float v, const Triple &triple,
return (-v_distance) /total_distance;
}
-result_t
+rebase_tent_result_t
rebase_tent (Triple tent, Triple axisLimit, TripleDistances axis_triple_distances)
{
- assert (-1.f <= axisLimit.minimum && axisLimit.minimum <= axisLimit.middle && axisLimit.middle <= axisLimit.maximum && axisLimit.maximum <= +1.f);
- assert (-2.f <= tent.minimum && tent.minimum <= tent.middle && tent.middle <= tent.maximum && tent.maximum <= +2.f);
- assert (tent.middle != 0.f);
+ assert (-1.0 <= axisLimit.minimum && axisLimit.minimum <= axisLimit.middle && axisLimit.middle <= axisLimit.maximum && axisLimit.maximum <= +1.0);
+ assert (-2.0 <= tent.minimum && tent.minimum <= tent.middle && tent.middle <= tent.maximum && tent.maximum <= +2.0);
+ assert (tent.middle != 0.0);
- result_t sols = _solve (tent, axisLimit);
+ rebase_tent_result_t sols = _solve (tent, axisLimit);
- auto n = [&axisLimit, &axis_triple_distances] (float v) { return renormalizeValue (v, axisLimit, axis_triple_distances); };
+ auto n = [&axisLimit, &axis_triple_distances] (double v) { return renormalizeValue (v, axisLimit, axis_triple_distances); };
- result_t out;
+ rebase_tent_result_t out;
for (auto &p : sols)
{
if (!p.first) continue;
diff --git a/thirdparty/harfbuzz/src/hb-subset-instancer-solver.hh b/thirdparty/harfbuzz/src/hb-subset-instancer-solver.hh
index 563fccbb59..9aac9fcc7e 100644
--- a/thirdparty/harfbuzz/src/hb-subset-instancer-solver.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-instancer-solver.hh
@@ -30,24 +30,24 @@
/* pre-normalized distances */
struct TripleDistances
{
- TripleDistances (): negative (1.f), positive (1.f) {}
- TripleDistances (float neg_, float pos_): negative (neg_), positive (pos_) {}
- TripleDistances (float min, float default_, float max)
+ TripleDistances (): negative (1.0), positive (1.0) {}
+ TripleDistances (double neg_, double pos_): negative (neg_), positive (pos_) {}
+ TripleDistances (double min, double default_, double max)
{
negative = default_ - min;
positive = max - default_;
}
- float negative;
- float positive;
+ double negative;
+ double positive;
};
struct Triple {
Triple () :
- minimum (0.f), middle (0.f), maximum (0.f) {}
+ minimum (0.0), middle (0.0), maximum (0.0) {}
- Triple (float minimum_, float middle_, float maximum_) :
+ Triple (double minimum_, double middle_, double maximum_) :
minimum (minimum_), middle (middle_), maximum (maximum_) {}
bool operator == (const Triple &o) const
@@ -63,7 +63,7 @@ struct Triple {
bool is_point () const
{ return minimum == middle && middle == maximum; }
- bool contains (float point) const
+ bool contains (double point) const
{ return minimum <= point && point <= maximum; }
/* from hb_array_t hash ()*/
@@ -82,18 +82,18 @@ struct Triple {
}
- float minimum;
- float middle;
- float maximum;
+ double minimum;
+ double middle;
+ double maximum;
};
-using result_item_t = hb_pair_t<float, Triple>;
-using result_t = hb_vector_t<result_item_t>;
+using rebase_tent_result_item_t = hb_pair_t<double, Triple>;
+using rebase_tent_result_t = hb_vector_t<rebase_tent_result_item_t>;
/* renormalize a normalized value v to the range of an axis,
* considering the prenormalized distances as well as the new axis limits.
* Ported from fonttools */
-HB_INTERNAL float renormalizeValue (float v, const Triple &triple,
+HB_INTERNAL double renormalizeValue (double v, const Triple &triple,
const TripleDistances &triple_distances,
bool extrapolate = true);
/* Given a tuple (lower,peak,upper) "tent" and new axis limits
@@ -107,6 +107,8 @@ HB_INTERNAL float renormalizeValue (float v, const Triple &triple,
* If tent value is Triple{}, that is a special deltaset that should
* be always-enabled (called "gain").
*/
-HB_INTERNAL result_t rebase_tent (Triple tent, Triple axisLimit, TripleDistances axis_triple_distances);
+HB_INTERNAL rebase_tent_result_t rebase_tent (Triple tent,
+ Triple axisLimit,
+ TripleDistances axis_triple_distances);
#endif /* HB_SUBSET_INSTANCER_SOLVER_HH */
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan-member-list.hh b/thirdparty/harfbuzz/src/hb-subset-plan-member-list.hh
index 74416b92f9..ade8278c40 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan-member-list.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-plan-member-list.hh
@@ -102,6 +102,12 @@ HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<unsigned, hb_pair_t E(<const void*, const
//active layers/palettes we'd like to retain
HB_SUBSET_PLAN_MEMBER (hb_map_t, colrv1_layers)
HB_SUBSET_PLAN_MEMBER (hb_map_t, colr_palettes)
+//colrv1 varstore retained varidx mapping
+HB_SUBSET_PLAN_MEMBER (hb_vector_t<hb_inc_bimap_t>, colrv1_varstore_inner_maps)
+//colrv1 retained varidx -> (new varidx, delta) mapping
+HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<unsigned, hb_pair_t E(<unsigned, int>)>), colrv1_variation_idx_delta_map)
+//colrv1 retained new delta set index -> new varidx mapping
+HB_SUBSET_PLAN_MEMBER (hb_map_t, colrv1_new_deltaset_idx_varidx_map)
//Old layout item variation index -> (New varidx, delta) mapping
HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<unsigned, hb_pair_t E(<unsigned, int>)>), layout_variation_idx_delta_map)
@@ -144,7 +150,7 @@ HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<hb_codepoint_t, contour_point_vec
HB_SUBSET_PLAN_MEMBER (hb_set_t, composite_new_gids)
//Old BASE item variation index -> (New varidx, 0) mapping
-HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(<unsigned, hb_pair_t E(<unsigned, int>)>), base_variation_idx_map)
+HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<unsigned, hb_pair_t E(<unsigned, int>)>), base_variation_idx_map)
//BASE table varstore retained varidx mapping
HB_SUBSET_PLAN_MEMBER (hb_vector_t<hb_inc_bimap_t>, base_varstore_inner_maps)
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc
index 068fddaedd..d657790d54 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc
@@ -399,12 +399,55 @@ _get_hb_font_with_variations (const hb_subset_plan_t *plan)
}
static inline void
+_remap_variation_indices (const OT::ItemVariationStore &var_store,
+ const hb_set_t &variation_indices,
+ const hb_vector_t<int>& normalized_coords,
+ bool calculate_delta, /* not pinned at default */
+ bool no_variations, /* all axes pinned */
+ hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map /* OUT */)
+{
+ if (&var_store == &Null (OT::ItemVariationStore)) return;
+ unsigned subtable_count = var_store.get_sub_table_count ();
+ float *store_cache = var_store.create_cache ();
+
+ unsigned new_major = 0, new_minor = 0;
+ unsigned last_major = (variation_indices.get_min ()) >> 16;
+ for (unsigned idx : variation_indices)
+ {
+ int delta = 0;
+ if (calculate_delta)
+ delta = roundf (var_store.get_delta (idx, normalized_coords.arrayZ,
+ normalized_coords.length, store_cache));
+
+ if (no_variations)
+ {
+ variation_idx_delta_map.set (idx, hb_pair_t<unsigned, int> (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta));
+ continue;
+ }
+
+ uint16_t major = idx >> 16;
+ if (major >= subtable_count) break;
+ if (major != last_major)
+ {
+ new_minor = 0;
+ ++new_major;
+ }
+
+ unsigned new_idx = (new_major << 16) + new_minor;
+ variation_idx_delta_map.set (idx, hb_pair_t<unsigned, int> (new_idx, delta));
+ ++new_minor;
+ last_major = major;
+ }
+ var_store.destroy_cache (store_cache);
+}
+
+static inline void
_collect_layout_variation_indices (hb_subset_plan_t* plan)
{
hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> ();
hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> ();
- if (!gdef->has_data ())
+ if (!gdef->has_data () || !gdef->has_var_store ())
{
gdef.destroy ();
gpos.destroy ();
@@ -420,13 +463,13 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan)
if (hb_ot_layout_has_positioning (plan->source))
gpos->collect_variation_indices (&c);
- gdef->remap_layout_variation_indices (&varidx_set,
- plan->normalized_coords,
- !plan->pinned_at_default,
- plan->all_axes_pinned,
- &plan->layout_variation_idx_delta_map);
+ _remap_variation_indices (gdef->get_var_store (),
+ varidx_set, plan->normalized_coords,
+ !plan->pinned_at_default,
+ plan->all_axes_pinned,
+ plan->layout_variation_idx_delta_map);
- unsigned subtable_count = gdef->has_var_store () ? gdef->get_var_store ().get_sub_table_count () : 0;
+ unsigned subtable_count = gdef->get_var_store ().get_sub_table_count ();
_generate_varstore_inner_maps (varidx_set, subtable_count, plan->gdef_varstore_inner_maps);
gdef.destroy ();
@@ -434,31 +477,6 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan)
}
#ifndef HB_NO_BASE
-/* used by BASE table only, delta is always set to 0 in the output map */
-static inline void
-_remap_variation_indices (const hb_set_t& indices,
- unsigned subtable_count,
- hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>>& variation_idx_delta_map /* OUT */)
-{
- unsigned new_major = 0, new_minor = 0;
- unsigned last_major = (indices.get_min ()) >> 16;
- for (unsigned idx : indices)
- {
- uint16_t major = idx >> 16;
- if (major >= subtable_count) break;
- if (major != last_major)
- {
- new_minor = 0;
- ++new_major;
- }
-
- unsigned new_idx = (new_major << 16) + new_minor;
- variation_idx_delta_map.set (idx, hb_pair_t<unsigned, int> (new_idx, 0));
- ++new_minor;
- last_major = major;
- }
-}
-
static inline void
_collect_base_variation_indices (hb_subset_plan_t* plan)
{
@@ -471,12 +489,20 @@ _collect_base_variation_indices (hb_subset_plan_t* plan)
hb_set_t varidx_set;
base->collect_variation_indices (plan, varidx_set);
- unsigned subtable_count = base->get_var_store ().get_sub_table_count ();
- base.destroy ();
-
- _remap_variation_indices (varidx_set, subtable_count, plan->base_variation_idx_map);
+ const OT::ItemVariationStore &var_store = base->get_var_store ();
+ unsigned subtable_count = var_store.get_sub_table_count ();
+
+
+ _remap_variation_indices (var_store, varidx_set,
+ plan->normalized_coords,
+ !plan->pinned_at_default,
+ plan->all_axes_pinned,
+ plan->base_variation_idx_map);
_generate_varstore_inner_maps (varidx_set, subtable_count, plan->base_varstore_inner_maps);
+
+ base.destroy ();
}
+
#endif
#endif
@@ -489,12 +515,43 @@ _cmap_closure (hb_face_t *face,
cmap.table->closure_glyphs (unicodes, glyphset);
}
-static void _colr_closure (hb_face_t *face,
- hb_map_t *layers_map,
- hb_map_t *palettes_map,
+static void
+_remap_colrv1_delta_set_index_indices (const OT::DeltaSetIndexMap &index_map,
+ const hb_set_t &delta_set_idxes,
+ hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map, /* IN/OUT */
+ hb_map_t &new_deltaset_idx_varidx_map /* OUT */)
+{
+ if (!index_map.get_map_count ())
+ return;
+
+ hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> delta_set_idx_delta_map;
+ unsigned new_delta_set_idx = 0;
+ for (unsigned delta_set_idx : delta_set_idxes)
+ {
+ unsigned var_idx = index_map.map (delta_set_idx);
+ unsigned new_varidx = HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
+ int delta = 0;
+
+ if (var_idx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
+ {
+ hb_pair_t<unsigned, int> *new_varidx_delta;
+ if (!variation_idx_delta_map.has (var_idx, &new_varidx_delta)) continue;
+
+ new_varidx = hb_first (*new_varidx_delta);
+ delta = hb_second (*new_varidx_delta);
+ }
+
+ new_deltaset_idx_varidx_map.set (new_delta_set_idx, new_varidx);
+ delta_set_idx_delta_map.set (delta_set_idx, hb_pair_t<unsigned, int> (new_delta_set_idx, delta));
+ new_delta_set_idx++;
+ }
+ variation_idx_delta_map = std::move (delta_set_idx_delta_map);
+}
+
+static void _colr_closure (hb_subset_plan_t* plan,
hb_set_t *glyphs_colred)
{
- OT::COLR::accelerator_t colr (face);
+ OT::COLR::accelerator_t colr (plan->source);
if (!colr.is_valid ()) return;
hb_set_t palette_indices, layer_indices;
@@ -506,11 +563,43 @@ static void _colr_closure (hb_face_t *face,
glyphs_colred->union_ (glyphset_colrv0);
//closure for COLRv1
- colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
+ hb_set_t variation_indices, delta_set_indices;
+ colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices, &variation_indices, &delta_set_indices);
colr.closure_V0palette_indices (glyphs_colred, &palette_indices);
- _remap_indexes (&layer_indices, layers_map);
- _remap_palette_indexes (&palette_indices, palettes_map);
+ _remap_indexes (&layer_indices, &plan->colrv1_layers);
+ _remap_palette_indexes (&palette_indices, &plan->colr_palettes);
+
+ if (!colr.has_var_store () || !variation_indices) return;
+
+ const OT::ItemVariationStore &var_store = colr.get_var_store ();
+ // generated inner_maps is used by ItemVariationStore serialize(), which is subset only
+ unsigned subtable_count = var_store.get_sub_table_count ();
+ _generate_varstore_inner_maps (variation_indices, subtable_count, plan->colrv1_varstore_inner_maps);
+
+ /* colr variation indices mapping during planning phase:
+ * generate colrv1_variation_idx_delta_map. When delta set index map is not
+ * included, it's a mapping from varIdx-> (new varIdx,delta). Otherwise, it's
+ * a mapping from old delta set idx-> (new delta set idx, delta). Mapping
+ * delta set indices is the same as gid mapping.
+ * Besides, we need to generate a delta set idx-> new var_idx map for updating
+ * delta set index map if exists. This map will be updated again after
+ * instancing. */
+ if (!plan->all_axes_pinned)
+ {
+ _remap_variation_indices (var_store,
+ variation_indices,
+ plan->normalized_coords,
+ false, /* no need to calculate delta for COLR during planning */
+ plan->all_axes_pinned,
+ plan->colrv1_variation_idx_delta_map);
+
+ if (colr.has_delta_set_index_map ())
+ _remap_colrv1_delta_set_index_indices (colr.get_delta_set_index_map (),
+ delta_set_indices,
+ plan->colrv1_variation_idx_delta_map,
+ plan->colrv1_new_deltaset_idx_varidx_map);
+ }
}
static inline void
@@ -821,7 +910,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
hb_set_t cur_glyphset = plan->_glyphset_mathed;
if (!drop_tables->has (HB_OT_TAG_COLR))
{
- _colr_closure (plan->source, &plan->colrv1_layers, &plan->colr_palettes, &cur_glyphset);
+ _colr_closure (plan, &cur_glyphset);
_remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
}
@@ -1016,9 +1105,9 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
normalized_default = seg_maps->map (normalized_default);
normalized_max = seg_maps->map (normalized_max);
}
- plan->axes_location.set (axis_tag, Triple (static_cast<float> (normalized_min / 16384.f),
- static_cast<float> (normalized_default / 16384.f),
- static_cast<float> (normalized_max / 16384.f)));
+ plan->axes_location.set (axis_tag, Triple (static_cast<double> (normalized_min / 16384.0),
+ static_cast<double> (normalized_default / 16384.0),
+ static_cast<double> (normalized_max / 16384.0)));
if (normalized_default != 0)
plan->pinned_at_default = false;
@@ -1145,11 +1234,9 @@ _get_instance_glyphs_contour_points (hb_subset_plan_t *plan)
if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points)))
return false;
-#ifdef HB_EXPERIMENTAL_API
/* composite new gids are only needed by iup delta optimization */
if ((plan->flags & HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS) && glyph.is_composite ())
plan->composite_new_gids.add (new_gid);
-#endif
}
return true;
}
diff --git a/thirdparty/harfbuzz/src/hb-subset.h b/thirdparty/harfbuzz/src/hb-subset.h
index 73dcae4660..365c21a630 100644
--- a/thirdparty/harfbuzz/src/hb-subset.h
+++ b/thirdparty/harfbuzz/src/hb-subset.h
@@ -73,11 +73,11 @@ typedef struct hb_subset_plan_t hb_subset_plan_t;
* OS/2 will not be recalculated.
* @HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE: If set don't perform glyph closure on layout
* substitution rules (GSUB). Since: 7.2.0.
+ * @HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS: If set perform IUP delta optimization on the
+ * remaining gvar table's deltas. Since: 8.5.0
* @HB_SUBSET_FLAGS_IFTB_REQUIREMENTS: If set enforce requirements on the output subset
* to allow it to be used with incremental font transfer IFTB patches. Primarily,
* this forces all outline data to use long (32 bit) offsets. Since: EXPERIMENTAL
- * @HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS: If set perform IUP delta optimization on the
- * remaining gvar table's deltas. Since: EXPERIMENTAL
*
* List of boolean properties that can be configured on the subset input.
*
@@ -95,9 +95,9 @@ typedef enum { /*< flags >*/
HB_SUBSET_FLAGS_GLYPH_NAMES = 0x00000080u,
HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES = 0x00000100u,
HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE = 0x00000200u,
+ HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS = 0x00000400u,
#ifdef HB_EXPERIMENTAL_API
- HB_SUBSET_FLAGS_IFTB_REQUIREMENTS = 0x00000400u,
- HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS = 0x00000800u,
+ HB_SUBSET_FLAGS_IFTB_REQUIREMENTS = 0x00000800u,
#endif
} hb_subset_flags_t;
@@ -188,7 +188,6 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input,
hb_tag_t axis_tag,
float axis_value);
-#ifdef HB_EXPERIMENTAL_API
HB_EXTERN hb_bool_t
hb_subset_input_get_axis_range (hb_subset_input_t *input,
hb_tag_t axis_tag,
@@ -204,6 +203,7 @@ hb_subset_input_set_axis_range (hb_subset_input_t *input,
float axis_max_value,
float axis_def_value);
+#ifdef HB_EXPERIMENTAL_API
HB_EXTERN hb_bool_t
hb_subset_input_override_name_table (hb_subset_input_t *input,
hb_ot_name_id_t name_id,
@@ -212,7 +212,6 @@ hb_subset_input_override_name_table (hb_subset_input_t *input,
unsigned language_id,
const char *name_str,
int str_len);
-
#endif
HB_EXTERN hb_face_t *
diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h
index 68681874ca..abffbdae9c 100644
--- a/thirdparty/harfbuzz/src/hb-version.h
+++ b/thirdparty/harfbuzz/src/hb-version.h
@@ -47,7 +47,7 @@ HB_BEGIN_DECLS
*
* The minor component of the library version available at compile-time.
*/
-#define HB_VERSION_MINOR 4
+#define HB_VERSION_MINOR 5
/**
* HB_VERSION_MICRO:
*
@@ -60,7 +60,7 @@ HB_BEGIN_DECLS
*
* A string literal containing the library version available at compile-time.
*/
-#define HB_VERSION_STRING "8.4.0"
+#define HB_VERSION_STRING "8.5.0"
/**
* HB_VERSION_ATLEAST: