summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/text_server_adv/SCsub1
-rw-r--r--thirdparty/README.md2
-rw-r--r--thirdparty/harfbuzz/src/hb-algs.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-verify.cc422
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.h64
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.hh18
-rw-r--r--thirdparty/harfbuzz/src/hb-common.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-common.h16
-rw-r--r--thirdparty/harfbuzz/src/hb-config.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-draw.cc376
-rw-r--r--thirdparty/harfbuzz/src/hb-draw.h285
-rw-r--r--thirdparty/harfbuzz/src/hb-draw.hh246
-rw-r--r--thirdparty/harfbuzz/src/hb-font.cc163
-rw-r--r--thirdparty/harfbuzz/src/hb-font.h45
-rw-r--r--thirdparty/harfbuzz/src/hb-font.hh16
-rw-r--r--thirdparty/harfbuzz/src/hb-ft.cc82
-rw-r--r--thirdparty/harfbuzz/src/hb-gobject-structs.cc1
-rw-r--r--thirdparty/harfbuzz/src/hb-gobject-structs.h4
-rw-r--r--thirdparty/harfbuzz/src/hb-machinery.hh14
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff1-table.cc34
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff1-table.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff2-table.cc22
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff2-table.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-deprecated.h15
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-face-table-list.hh13
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-face.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-font.cc21
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-glyf-table.hh55
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh159
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.cc301
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.h62
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-math-table.hh78
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-math.cc45
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-math.h36
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-metrics.cc139
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-metrics.h5
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-name.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc5
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-tag.cc3
-rw-r--r--thirdparty/harfbuzz/src/hb-shape.cc18
-rw-r--r--thirdparty/harfbuzz/src/hb-static.cc37
-rw-r--r--thirdparty/harfbuzz/src/hb-style.cc7
-rw-r--r--thirdparty/harfbuzz/src/hb-style.h4
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.cc143
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.hh9
-rw-r--r--thirdparty/harfbuzz/src/hb-subset.cc37
-rw-r--r--thirdparty/harfbuzz/src/hb-subset.h46
-rw-r--r--thirdparty/harfbuzz/src/hb-version.h8
51 files changed, 2554 insertions, 534 deletions
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub
index 6a06619840..5e5c284b57 100644
--- a/modules/text_server_adv/SCsub
+++ b/modules/text_server_adv/SCsub
@@ -49,6 +49,7 @@ if env["builtin_harfbuzz"]:
"src/hb-aat-map.cc",
"src/hb-blob.cc",
"src/hb-buffer-serialize.cc",
+ "src/hb-buffer-verify.cc",
"src/hb-buffer.cc",
"src/hb-common.cc",
#'src/hb-coretext.cc',
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 97b53a179d..d591d2cbd8 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -206,7 +206,7 @@ Files extracted from upstream source:
## harfbuzz
- Upstream: https://github.com/harfbuzz/harfbuzz
-- Version: 3.3.2 (ac46c3248e8b0316235943175c4d4a11c24dd4a9, 2022)
+- Version: 4.0.0 (8d1b000a3edc90c12267b836b4ef3f81c0e53edc, 2022)
- License: MIT
Files extracted from upstream source:
diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh
index 3a3ab08046..c40a55cd1f 100644
--- a/thirdparty/harfbuzz/src/hb-algs.hh
+++ b/thirdparty/harfbuzz/src/hb-algs.hh
@@ -498,7 +498,7 @@ struct hb_pair_t
template <typename Q1, typename Q2,
hb_enable_if (hb_is_convertible (T1, Q1) &&
- hb_is_convertible (T2, T2))>
+ hb_is_convertible (T2, Q2))>
operator hb_pair_t<Q1, Q2> () { return hb_pair_t<Q1, Q2> (first, second); }
hb_pair_t<T1, T2> reverse () const
diff --git a/thirdparty/harfbuzz/src/hb-buffer-verify.cc b/thirdparty/harfbuzz/src/hb-buffer-verify.cc
new file mode 100644
index 0000000000..dea2c11c35
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-buffer-verify.cc
@@ -0,0 +1,422 @@
+/*
+ * Copyright © 2022 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_BUFFER_VERIFY
+
+#include "hb-buffer.hh"
+
+
+#define BUFFER_VERIFY_ERROR "buffer verify error: "
+static inline void
+buffer_verify_error (hb_buffer_t *buffer,
+ hb_font_t *font,
+ const char *fmt,
+ ...) HB_PRINTF_FUNC(3, 4);
+
+static inline void
+buffer_verify_error (hb_buffer_t *buffer,
+ hb_font_t *font,
+ const char *fmt,
+ ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ if (buffer->messaging ())
+ {
+ buffer->message_impl (font, fmt, ap);
+ }
+ else
+ {
+ fprintf (stderr, "harfbuzz ");
+ vfprintf (stderr, fmt, ap);
+ fprintf (stderr, "\n");
+ }
+ va_end (ap);
+}
+
+static bool
+buffer_verify_monotone (hb_buffer_t *buffer,
+ hb_font_t *font)
+{
+ /* Check that clusters are monotone. */
+ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES ||
+ buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ {
+ bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+
+ unsigned int num_glyphs;
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+
+ for (unsigned int i = 1; i < num_glyphs; i++)
+ if (info[i-1].cluster != info[i].cluster &&
+ (info[i-1].cluster < info[i].cluster) != is_forward)
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool
+buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
+ hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shapers)
+{
+ if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
+ buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ {
+ /* Cannot perform this check without monotone clusters. */
+ return true;
+ }
+
+ /* Check that breaking up shaping at safe-to-break is indeed safe. */
+
+ hb_buffer_t *fragment = hb_buffer_create_similar (buffer);
+ hb_buffer_set_flags (fragment, hb_buffer_get_flags (fragment) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer);
+ hb_buffer_set_flags (reconstruction, hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY);
+
+ unsigned int num_glyphs;
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+
+ unsigned int num_chars;
+ hb_glyph_info_t *text = hb_buffer_get_glyph_infos (text_buffer, &num_chars);
+
+ /* Chop text and shape fragments. */
+ bool forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+ unsigned int start = 0;
+ unsigned int text_start = forward ? 0 : num_chars;
+ unsigned int text_end = text_start;
+ for (unsigned int end = 1; end < num_glyphs + 1; end++)
+ {
+ if (end < num_glyphs &&
+ (info[end].cluster == info[end-1].cluster ||
+ info[end-(forward?0:1)].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK))
+ continue;
+
+ /* Shape segment corresponding to glyphs start..end. */
+ if (end == num_glyphs)
+ {
+ if (forward)
+ text_end = num_chars;
+ else
+ text_start = 0;
+ }
+ else
+ {
+ if (forward)
+ {
+ unsigned int cluster = info[end].cluster;
+ while (text_end < num_chars && text[text_end].cluster < cluster)
+ text_end++;
+ }
+ else
+ {
+ unsigned int cluster = info[end - 1].cluster;
+ while (text_start && text[text_start - 1].cluster >= cluster)
+ text_start--;
+ }
+ }
+ assert (text_start < text_end);
+
+ if (0)
+ printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end);
+
+ hb_buffer_clear_contents (fragment);
+
+ hb_buffer_flags_t flags = hb_buffer_get_flags (fragment);
+ if (0 < text_start)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT);
+ if (text_end < num_chars)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT);
+ hb_buffer_set_flags (fragment, flags);
+
+ hb_buffer_append (fragment, text_buffer, text_start, text_end);
+ if (!hb_shape_full (font, fragment, features, num_features, shapers))
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
+ hb_buffer_destroy (reconstruction);
+ hb_buffer_destroy (fragment);
+ return false;
+ }
+ hb_buffer_append (reconstruction, fragment, 0, -1);
+
+ start = end;
+ if (forward)
+ text_start = text_end;
+ else
+ text_end = text_start;
+ }
+
+ bool ret = true;
+ hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
+ if (diff)
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed.");
+ ret = false;
+
+ /* Return the reconstructed result instead so it can be inspected. */
+ hb_buffer_set_length (buffer, 0);
+ hb_buffer_append (buffer, reconstruction, 0, -1);
+ }
+
+ hb_buffer_destroy (reconstruction);
+ hb_buffer_destroy (fragment);
+
+ return ret;
+}
+
+static bool
+buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
+ hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shapers)
+{
+ if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
+ buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ {
+ /* Cannot perform this check without monotone clusters. */
+ return true;
+ }
+
+ /* Check that shuffling up text before shaping at safe-to-concat points
+ * is indeed safe. */
+
+ /* This is what we do:
+ *
+ * 1. We shape text once. Then segment the text at all the safe-to-concat
+ * points;
+ *
+ * 2. Then we create two buffers, one containing all the even segments and
+ * one all the odd segments.
+ *
+ * 3. Because all these segments were safe-to-concat at both ends, we
+ * expect that concatenating them and shaping should NOT change the
+ * shaping results of each segment. As such, we expect that after
+ * shaping the two buffers, we still get cluster boundaries at the
+ * segment boundaries, and that those all are safe-to-concat points.
+ * Moreover, that there are NOT any safe-to-concat points within the
+ * segments.
+ *
+ * 4. Finally, we reconstruct the shaping results of the original text by
+ * simply interleaving the shaping results of the segments from the two
+ * buffers, and assert that the total shaping results is the same as
+ * the one from original buffer in step 1.
+ */
+
+ hb_buffer_t *fragments[2] {hb_buffer_create_similar (buffer),
+ hb_buffer_create_similar (buffer)};
+ hb_buffer_set_flags (fragments[0], hb_buffer_get_flags (fragments[0]) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_set_flags (fragments[1], hb_buffer_get_flags (fragments[1]) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer);
+ hb_buffer_set_flags (reconstruction, hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY);
+ hb_segment_properties_t props;
+ hb_buffer_get_segment_properties (buffer, &props);
+ hb_buffer_set_segment_properties (fragments[0], &props);
+ hb_buffer_set_segment_properties (fragments[1], &props);
+ hb_buffer_set_segment_properties (reconstruction, &props);
+
+ unsigned num_glyphs;
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+
+ unsigned num_chars;
+ hb_glyph_info_t *text = hb_buffer_get_glyph_infos (text_buffer, &num_chars);
+
+ bool forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+
+ if (!forward)
+ hb_buffer_reverse (buffer);
+
+ /*
+ * Split text into segments and collect into to fragment streams.
+ */
+ {
+ unsigned fragment_idx = 0;
+ unsigned start = 0;
+ unsigned text_start = 0;
+ unsigned text_end = 0;
+ for (unsigned end = 1; end < num_glyphs + 1; end++)
+ {
+ if (end < num_glyphs &&
+ (info[end].cluster == info[end-1].cluster ||
+ info[end].mask & HB_GLYPH_FLAG_UNSAFE_TO_CONCAT))
+ continue;
+
+ /* Accumulate segment corresponding to glyphs start..end. */
+ if (end == num_glyphs)
+ text_end = num_chars;
+ else
+ {
+ unsigned cluster = info[end].cluster;
+ while (text_end < num_chars && text[text_end].cluster < cluster)
+ text_end++;
+ }
+ assert (text_start < text_end);
+
+ if (0)
+ printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end);
+
+#if 0
+ hb_buffer_flags_t flags = hb_buffer_get_flags (fragment);
+ if (0 < text_start)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT);
+ if (text_end < num_chars)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT);
+ hb_buffer_set_flags (fragment, flags);
+#endif
+
+ hb_buffer_append (fragments[fragment_idx], text_buffer, text_start, text_end);
+
+ start = end;
+ text_start = text_end;
+ fragment_idx = 1 - fragment_idx;
+ }
+ }
+
+ bool ret = true;
+ hb_buffer_diff_flags_t diff;
+
+ /*
+ * Shape the two fragment streams.
+ */
+ if (!hb_shape_full (font, fragments[0], features, num_features, shapers))
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
+ ret = false;
+ goto out;
+ }
+ if (!hb_shape_full (font, fragments[1], features, num_features, shapers))
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
+ ret = false;
+ goto out;
+ }
+
+ if (!forward)
+ {
+ hb_buffer_reverse (fragments[0]);
+ hb_buffer_reverse (fragments[1]);
+ }
+
+ /*
+ * Reconstruct results.
+ */
+ {
+ unsigned fragment_idx = 0;
+ unsigned fragment_start[2] {0, 0};
+ unsigned fragment_num_glyphs[2];
+ hb_glyph_info_t *fragment_info[2];
+ for (unsigned i = 0; i < 2; i++)
+ fragment_info[i] = hb_buffer_get_glyph_infos (fragments[i], &fragment_num_glyphs[i]);
+ while (fragment_start[0] < fragment_num_glyphs[0] ||
+ fragment_start[1] < fragment_num_glyphs[1])
+ {
+ unsigned fragment_end = fragment_start[fragment_idx] + 1;
+ while (fragment_end < fragment_num_glyphs[fragment_idx] &&
+ (fragment_info[fragment_idx][fragment_end].cluster == fragment_info[fragment_idx][fragment_end - 1].cluster ||
+ fragment_info[fragment_idx][fragment_end].mask & HB_GLYPH_FLAG_UNSAFE_TO_CONCAT))
+ fragment_end++;
+
+ hb_buffer_append (reconstruction, fragments[fragment_idx], fragment_start[fragment_idx], fragment_end);
+
+ fragment_start[fragment_idx] = fragment_end;
+ fragment_idx = 1 - fragment_idx;
+ }
+ }
+
+ if (!forward)
+ {
+ hb_buffer_reverse (buffer);
+ hb_buffer_reverse (reconstruction);
+ }
+
+ /*
+ * Diff results.
+ */
+ diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
+ if (diff)
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed.");
+ ret = false;
+
+ /* Return the reconstructed result instead so it can be inspected. */
+ hb_buffer_set_length (buffer, 0);
+ hb_buffer_append (buffer, reconstruction, 0, -1);
+ }
+
+
+out:
+ hb_buffer_destroy (reconstruction);
+ hb_buffer_destroy (fragments[0]);
+ hb_buffer_destroy (fragments[1]);
+
+ return ret;
+}
+
+bool
+hb_buffer_t::verify (hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shapers)
+{
+ bool ret = true;
+ if (!buffer_verify_monotone (this, font))
+ ret = false;
+ if (!buffer_verify_unsafe_to_break (this, text_buffer, font, features, num_features, shapers))
+ ret = false;
+ if ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) != 0 &&
+ !buffer_verify_unsafe_to_concat (this, text_buffer, font, features, num_features, shapers))
+ ret = false;
+ if (!ret)
+ {
+ unsigned len = text_buffer->len;
+ hb_vector_t<char> bytes;
+ if (likely (bytes.resize (len * 10 + 16)))
+ {
+ hb_buffer_serialize_unicode (text_buffer,
+ 0, len,
+ bytes.arrayZ, bytes.length,
+ &len,
+ HB_BUFFER_SERIALIZE_FORMAT_TEXT,
+ HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS);
+ buffer_verify_error (this, font, BUFFER_VERIFY_ERROR "text was: %s.", bytes.arrayZ);
+ }
+ }
+ return ret;
+}
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc
index e50afcb203..d36fcfde39 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer.cc
@@ -1789,7 +1789,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
**/
HB_EXTERN void
hb_buffer_append (hb_buffer_t *buffer,
- hb_buffer_t *source,
+ const hb_buffer_t *source,
unsigned int start,
unsigned int end)
{
diff --git a/thirdparty/harfbuzz/src/hb-buffer.h b/thirdparty/harfbuzz/src/hb-buffer.h
index 9fbd7b1ec3..ece7d2d8cf 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.h
+++ b/thirdparty/harfbuzz/src/hb-buffer.h
@@ -137,7 +137,11 @@ typedef struct hb_glyph_info_t {
* clusters.
* The #HB_GLYPH_FLAG_UNSAFE_TO_BREAK flag will
* always imply this flag.
- * Since: 3.3.0
+ * To use this flag, you must enable the buffer flag
+ * @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT during
+ * shaping, otherwise the buffer flag will not be
+ * reliably produced.
+ * Since: 4.0.0
* @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
*
* Flags for #hb_glyph_info_t.
@@ -356,7 +360,19 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
* @HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE:
* flag indicating that a dotted circle should
* not be inserted in the rendering of incorrect
- * character sequences (such at <0905 093E>). Since: 2.4
+ * character sequences (such at <0905 093E>). Since: 2.4.0
+ * @HB_BUFFER_FLAG_VERIFY:
+ * flag indicating that the hb_shape() call and its variants
+ * should perform various verification processes on the results
+ * of the shaping operation on the buffer. If the verification
+ * fails, then either a buffer message is sent, if a message
+ * handler is installed on the buffer, or a message is written
+ * to standard error. In either case, the shaping result might
+ * be modified to show the failed output. Since: 3.4.0
+ * @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT:
+ * flag indicating that the @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT
+ * glyph-flag should be produced by the shaper. By default
+ * it will not be produced since it incurs a cost. Since: 4.0.0
*
* Flags for #hb_buffer_t.
*
@@ -368,7 +384,9 @@ typedef enum { /*< flags >*/
HB_BUFFER_FLAG_EOT = 0x00000002u, /* End-of-text */
HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u,
HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u,
- HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u
+ HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u,
+ HB_BUFFER_FLAG_VERIFY = 0x00000020u,
+ HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u
} hb_buffer_flags_t;
HB_EXTERN void
@@ -522,7 +540,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
HB_EXTERN void
hb_buffer_append (hb_buffer_t *buffer,
- hb_buffer_t *source,
+ const hb_buffer_t *source,
unsigned int start,
unsigned int end);
@@ -619,24 +637,24 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
HB_EXTERN unsigned int
hb_buffer_serialize_unicode (hb_buffer_t *buffer,
- unsigned int start,
- unsigned int end,
- char *buf,
- unsigned int buf_size,
- unsigned int *buf_consumed,
- hb_buffer_serialize_format_t format,
- hb_buffer_serialize_flags_t flags);
+ unsigned int start,
+ unsigned int end,
+ char *buf,
+ unsigned int buf_size,
+ unsigned int *buf_consumed,
+ hb_buffer_serialize_format_t format,
+ hb_buffer_serialize_flags_t flags);
HB_EXTERN unsigned int
hb_buffer_serialize (hb_buffer_t *buffer,
- unsigned int start,
- unsigned int end,
- char *buf,
- unsigned int buf_size,
- unsigned int *buf_consumed,
- hb_font_t *font,
- hb_buffer_serialize_format_t format,
- hb_buffer_serialize_flags_t flags);
+ unsigned int start,
+ unsigned int end,
+ char *buf,
+ unsigned int buf_size,
+ unsigned int *buf_consumed,
+ hb_font_t *font,
+ hb_buffer_serialize_format_t format,
+ hb_buffer_serialize_flags_t flags);
HB_EXTERN hb_bool_t
hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
@@ -648,10 +666,10 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
HB_EXTERN hb_bool_t
hb_buffer_deserialize_unicode (hb_buffer_t *buffer,
- const char *buf,
- int buf_len,
- const char **end_ptr,
- hb_buffer_serialize_format_t format);
+ const char *buf,
+ int buf_len,
+ const char **end_ptr,
+ hb_buffer_serialize_format_t format);
diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh
index ac45f090a5..bc6992905e 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.hh
+++ b/thirdparty/harfbuzz/src/hb-buffer.hh
@@ -212,6 +212,20 @@ struct hb_buffer_t
HB_INTERNAL void enter ();
HB_INTERNAL void leave ();
+#ifndef HB_NO_BUFFER_VERIFY
+ HB_INTERNAL
+#endif
+ bool verify (hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shapers)
+#ifndef HB_NO_BUFFER_VERIFY
+ ;
+#else
+ { return true; }
+#endif
+
unsigned int backtrack_len () const { return have_output ? out_len : idx; }
unsigned int lookahead_len () const { return len - idx; }
uint8_t next_serial () { return ++serial ? serial : ++serial; }
@@ -446,6 +460,8 @@ struct hb_buffer_t
}
void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1)
{
+ if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
+ return;
_set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
start, end,
true);
@@ -458,6 +474,8 @@ struct hb_buffer_t
}
void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1)
{
+ if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
+ return;
_set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
start, end,
false, true);
diff --git a/thirdparty/harfbuzz/src/hb-common.cc b/thirdparty/harfbuzz/src/hb-common.cc
index 249a8a8010..41229b9183 100644
--- a/thirdparty/harfbuzz/src/hb-common.cc
+++ b/thirdparty/harfbuzz/src/hb-common.cc
@@ -1065,7 +1065,7 @@ hb_variation_from_string (const char *str, int len,
static inline void free_static_C_locale ();
static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<hb_locale_t>,
- hb_C_locale_lazy_loader_t>
+ hb_C_locale_lazy_loader_t>
{
static hb_locale_t create ()
{
diff --git a/thirdparty/harfbuzz/src/hb-common.h b/thirdparty/harfbuzz/src/hb-common.h
index 0384117a4d..7b897a6c51 100644
--- a/thirdparty/harfbuzz/src/hb-common.h
+++ b/thirdparty/harfbuzz/src/hb-common.h
@@ -130,6 +130,16 @@ typedef union _hb_var_int_t {
int8_t i8[4];
} hb_var_int_t;
+typedef union _hb_var_num_t {
+ float f;
+ uint32_t u32;
+ int32_t i32;
+ uint16_t u16[2];
+ int16_t i16[2];
+ uint8_t u8[4];
+ int8_t i8[4];
+} hb_var_num_t;
+
/* hb_tag_t */
@@ -481,6 +491,7 @@ hb_language_get_default (void);
* @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0
* @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0
* @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0
+ * @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0
* @HB_SCRIPT_INVALID: No script set
*
* Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
@@ -697,6 +708,11 @@ typedef enum
HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/
HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/
+ /*
+ * Since 3.4.0
+ */
+ HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'),
+
/* No script set. */
HB_SCRIPT_INVALID = HB_TAG_NONE,
diff --git a/thirdparty/harfbuzz/src/hb-config.hh b/thirdparty/harfbuzz/src/hb-config.hh
index 7d00d9088a..4b46dea938 100644
--- a/thirdparty/harfbuzz/src/hb-config.hh
+++ b/thirdparty/harfbuzz/src/hb-config.hh
@@ -55,6 +55,7 @@
#define HB_NO_ATEXIT
#define HB_NO_BUFFER_MESSAGE
#define HB_NO_BUFFER_SERIALIZE
+#define HB_NO_BUFFER_VERIFY
#define HB_NO_BITMAP
#define HB_NO_CFF
#define HB_NO_COLOR
@@ -84,6 +85,7 @@
#ifdef HB_MINI
#define HB_NO_AAT
#define HB_NO_LEGACY
+#define HB_NO_BORING_EXPANSION
#endif
#if defined(HAVE_CONFIG_OVERRIDE_H) || defined(HB_CONFIG_OVERRIDE_H)
diff --git a/thirdparty/harfbuzz/src/hb-draw.cc b/thirdparty/harfbuzz/src/hb-draw.cc
index c0af6ce013..b31019b07e 100644
--- a/thirdparty/harfbuzz/src/hb-draw.cc
+++ b/thirdparty/harfbuzz/src/hb-draw.cc
@@ -25,237 +25,313 @@
#include "hb.hh"
#ifndef HB_NO_DRAW
-#ifdef HB_EXPERIMENTAL_API
#include "hb-draw.hh"
-#include "hb-ot.h"
-#include "hb-ot-glyf-table.hh"
-#include "hb-ot-cff1-table.hh"
-#include "hb-ot-cff2-table.hh"
/**
- * hb_draw_funcs_set_move_to_func:
- * @funcs: draw functions object
- * @move_to: move-to callback
+ * SECTION:hb-draw
+ * @title: hb-draw
+ * @short_description: Glyph drawing
+ * @include: hb.h
*
- * Sets move-to callback to the draw functions object.
- *
- * Since: EXPERIMENTAL
+ * Functions for drawing (extracting) glyph shapes.
**/
-void
-hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
- hb_draw_move_to_func_t move_to)
+
+static void
+hb_draw_move_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+ hb_draw_state_t *st HB_UNUSED,
+ float to_x HB_UNUSED, float to_y HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+static void
+hb_draw_line_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+ hb_draw_state_t *st HB_UNUSED,
+ float to_x HB_UNUSED, float to_y HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+static void
+hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->move_to = move_to;
+ dfuncs->emit_cubic_to (draw_data, *st,
+ (st->current_x + 2.f * control_x) / 3.f,
+ (st->current_y + 2.f * control_y) / 3.f,
+ (to_x + 2.f * control_x) / 3.f,
+ (to_y + 2.f * control_y) / 3.f,
+ to_x, to_y);
+}
+
+static void
+hb_draw_cubic_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+ hb_draw_state_t *st HB_UNUSED,
+ float control1_x HB_UNUSED, float control1_y HB_UNUSED,
+ float control2_x HB_UNUSED, float control2_y HB_UNUSED,
+ float to_x HB_UNUSED, float to_y HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+static void
+hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+ hb_draw_state_t *st HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+
+#define HB_DRAW_FUNC_IMPLEMENT(name) \
+ \
+void \
+hb_draw_funcs_set_##name##_func (hb_draw_funcs_t *dfuncs, \
+ hb_draw_##name##_func_t func, \
+ void *user_data, \
+ hb_destroy_func_t destroy) \
+{ \
+ if (hb_object_is_immutable (dfuncs)) \
+ return; \
+ \
+ if (dfuncs->destroy.name) \
+ dfuncs->destroy.name (dfuncs->user_data.name); \
+ \
+ if (func) { \
+ dfuncs->func.name = func; \
+ dfuncs->user_data.name = user_data; \
+ dfuncs->destroy.name = destroy; \
+ } else { \
+ dfuncs->func.name = hb_draw_##name##_nil; \
+ dfuncs->user_data.name = nullptr; \
+ dfuncs->destroy.name = nullptr; \
+ } \
}
+HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+
/**
- * hb_draw_funcs_set_line_to_func:
- * @funcs: draw functions object
- * @line_to: line-to callback
+ * hb_draw_funcs_create: (Xconstructor)
+ *
+ * Creates a new draw callbacks object.
*
- * Sets line-to callback to the draw functions object.
+ * Return value: (transfer full):
+ * A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial
+ * reference count should be released with hb_draw_funcs_destroy when you are
+ * done using the #hb_draw_funcs_t. This function never returns %NULL. If
+ * memory cannot be allocated, a special singleton #hb_draw_funcs_t object will
+ * be returned.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-void
-hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
- hb_draw_line_to_func_t line_to)
+hb_draw_funcs_t *
+hb_draw_funcs_create ()
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->line_to = line_to;
+ hb_draw_funcs_t *dfuncs;
+ if (unlikely (!(dfuncs = hb_object_create<hb_draw_funcs_t> ())))
+ return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
+
+ dfuncs->func = Null (hb_draw_funcs_t).func;
+
+ return dfuncs;
}
+DEFINE_NULL_INSTANCE (hb_draw_funcs_t) =
+{
+ HB_OBJECT_HEADER_STATIC,
+
+ {
+#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_nil,
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ }
+};
+
+
/**
- * hb_draw_funcs_set_quadratic_to_func:
- * @funcs: draw functions object
- * @move_to: quadratic-to callback
+ * hb_draw_funcs_reference: (skip)
+ * @dfuncs: draw functions
+ *
+ * Increases the reference count on @dfuncs by one. This prevents @buffer from
+ * being destroyed until a matching call to hb_draw_funcs_destroy() is made.
*
- * Sets quadratic-to callback to the draw functions object.
+ * Return value: (transfer full):
+ * The referenced #hb_draw_funcs_t.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-void
-hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
- hb_draw_quadratic_to_func_t quadratic_to)
+hb_draw_funcs_t *
+hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs)
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->quadratic_to = quadratic_to;
- funcs->is_quadratic_to_set = true;
+ return hb_object_reference (dfuncs);
}
/**
- * hb_draw_funcs_set_cubic_to_func:
- * @funcs: draw functions
- * @cubic_to: cubic-to callback
+ * hb_draw_funcs_destroy: (skip)
+ * @dfuncs: draw functions
*
- * Sets cubic-to callback to the draw functions object.
+ * Deallocate the @dfuncs.
+ * Decreases the reference count on @dfuncs by one. If the result is zero, then
+ * @dfuncs and all associated resources are freed. See hb_draw_funcs_reference().
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
void
-hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
- hb_draw_cubic_to_func_t cubic_to)
+hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->cubic_to = cubic_to;
+ if (!hb_object_destroy (dfuncs)) return;
+
+#define HB_DRAW_FUNC_IMPLEMENT(name) \
+ if (dfuncs->destroy.name) dfuncs->destroy.name (dfuncs->user_data.name);
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+
+
+ hb_free (dfuncs);
}
/**
- * hb_draw_funcs_set_close_path_func:
- * @funcs: draw functions object
- * @close_path: close-path callback
+ * hb_draw_funcs_make_immutable:
+ * @dfuncs: draw functions
*
- * Sets close-path callback to the draw functions object.
+ * Makes @dfuncs object immutable.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
void
-hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
- hb_draw_close_path_func_t close_path)
+hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs)
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->close_path = close_path;
-}
-
-static void
-_move_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
-
-static void
-_line_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
-
-static void
-_quadratic_to_nil (hb_position_t control_x HB_UNUSED, hb_position_t control_y HB_UNUSED,
- hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
- void *user_data HB_UNUSED) {}
-
-static void
-_cubic_to_nil (hb_position_t control1_x HB_UNUSED, hb_position_t control1_y HB_UNUSED,
- hb_position_t control2_x HB_UNUSED, hb_position_t control2_y HB_UNUSED,
- hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
- void *user_data HB_UNUSED) {}
+ if (hb_object_is_immutable (dfuncs))
+ return;
-static void
-_close_path_nil (void *user_data HB_UNUSED) {}
+ hb_object_make_immutable (dfuncs);
+}
/**
- * hb_draw_funcs_create:
+ * hb_draw_funcs_is_immutable:
+ * @dfuncs: draw functions
*
- * Creates a new draw callbacks object.
+ * Checks whether @dfuncs is immutable.
+ *
+ * Return value: %true if @dfuncs is immutable, %false otherwise
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-hb_draw_funcs_t *
-hb_draw_funcs_create ()
+hb_bool_t
+hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs)
{
- hb_draw_funcs_t *funcs;
- if (unlikely (!(funcs = hb_object_create<hb_draw_funcs_t> ())))
- return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
-
- funcs->move_to = (hb_draw_move_to_func_t) _move_to_nil;
- funcs->line_to = (hb_draw_line_to_func_t) _line_to_nil;
- funcs->quadratic_to = (hb_draw_quadratic_to_func_t) _quadratic_to_nil;
- funcs->is_quadratic_to_set = false;
- funcs->cubic_to = (hb_draw_cubic_to_func_t) _cubic_to_nil;
- funcs->close_path = (hb_draw_close_path_func_t) _close_path_nil;
- return funcs;
+ return hb_object_is_immutable (dfuncs);
}
+
/**
- * hb_draw_funcs_reference:
- * @funcs: draw functions
+ * hb_draw_move_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
*
- * Add to callbacks object refcount.
+ * Perform a "move-to" draw operation.
*
- * Returns: The same object.
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-hb_draw_funcs_t *
-hb_draw_funcs_reference (hb_draw_funcs_t *funcs)
+void
+hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y)
{
- return hb_object_reference (funcs);
+ dfuncs->move_to (draw_data, *st,
+ to_x, to_y);
}
/**
- * hb_draw_funcs_destroy:
- * @funcs: draw functions
+ * hb_draw_line_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
*
- * Decreases refcount of callbacks object and deletes the object if it reaches
- * to zero.
+ * Perform a "line-to" draw operation.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
void
-hb_draw_funcs_destroy (hb_draw_funcs_t *funcs)
+hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y)
{
- if (!hb_object_destroy (funcs)) return;
-
- hb_free (funcs);
+ dfuncs->line_to (draw_data, *st,
+ to_x, to_y);
}
/**
- * hb_draw_funcs_make_immutable:
- * @funcs: draw functions
+ * hb_draw_quadratic_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @control_x: X component of control point
+ * @control_y: Y component of control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
*
- * Makes funcs object immutable.
+ * Perform a "quadratic-to" draw operation.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
void
-hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs)
+hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y)
{
- if (hb_object_is_immutable (funcs))
- return;
-
- hb_object_make_immutable (funcs);
+ dfuncs->quadratic_to (draw_data, *st,
+ control_x, control_y,
+ to_x, to_y);
}
/**
- * hb_draw_funcs_is_immutable:
- * @funcs: draw functions
+ * hb_draw_cubic_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @control1_x: X component of first control point
+ * @control1_y: Y component of first control point
+ * @control2_x: X component of second control point
+ * @control2_y: Y component of second control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
*
- * Checks whether funcs is immutable.
+ * Perform a "cubic-to" draw operation.
*
- * Returns: If is immutable.
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-hb_bool_t
-hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs)
+void
+hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y)
{
- return hb_object_is_immutable (funcs);
+ dfuncs->cubic_to (draw_data, *st,
+ control1_x, control1_y,
+ control2_x, control2_y,
+ to_x, to_y);
}
/**
- * hb_font_draw_glyph:
- * @font: a font object
- * @glyph: a glyph id
- * @funcs: draw callbacks object
- * @user_data: parameter you like be passed to the callbacks when are called
+ * hb_draw_close_path:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
*
- * Draw a glyph.
+ * Perform a "close-path" draw operation.
*
- * Returns: Whether the font had the glyph and the operation completed successfully.
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-hb_bool_t
-hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
- const hb_draw_funcs_t *funcs,
- void *user_data)
+void
+hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st)
{
- if (unlikely (funcs == &Null (hb_draw_funcs_t) ||
- glyph >= font->face->get_num_glyphs ()))
- return false;
-
- draw_helper_t draw_helper (funcs, user_data);
- if (font->face->table.glyf->get_path (font, glyph, draw_helper)) return true;
-#ifndef HB_NO_CFF
- if (font->face->table.cff1->get_path (font, glyph, draw_helper)) return true;
- if (font->face->table.cff2->get_path (font, glyph, draw_helper)) return true;
-#endif
-
- return false;
+ dfuncs->close_path (draw_data, *st);
}
-#endif
+
#endif
diff --git a/thirdparty/harfbuzz/src/hb-draw.h b/thirdparty/harfbuzz/src/hb-draw.h
index f82cc34842..c45a53212a 100644
--- a/thirdparty/harfbuzz/src/hb-draw.h
+++ b/thirdparty/harfbuzz/src/hb-draw.h
@@ -33,65 +33,292 @@
HB_BEGIN_DECLS
-#ifdef HB_EXPERIMENTAL_API
-typedef void (*hb_draw_move_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
-typedef void (*hb_draw_line_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
-typedef void (*hb_draw_quadratic_to_func_t) (hb_position_t control_x, hb_position_t control_y,
- hb_position_t to_x, hb_position_t to_y,
- void *user_data);
-typedef void (*hb_draw_cubic_to_func_t) (hb_position_t control1_x, hb_position_t control1_y,
- hb_position_t control2_x, hb_position_t control2_y,
- hb_position_t to_x, hb_position_t to_y,
- void *user_data);
-typedef void (*hb_draw_close_path_func_t) (void *user_data);
+
+/**
+ * hb_draw_state_t
+ * @path_open: Whether there is an open path
+ * @path_start_x: X component of the start of current path
+ * @path_start_y: Y component of the start of current path
+ * @current_x: X component of current point
+ * @current_y: Y component of current point
+ *
+ * Current drawing state.
+ *
+ * Since: 4.0.0
+ **/
+typedef struct hb_draw_state_t {
+ hb_bool_t path_open;
+
+ float path_start_x;
+ float path_start_y;
+
+ float current_x;
+ float current_y;
+
+ /*< private >*/
+ hb_var_num_t reserved1;
+ hb_var_num_t reserved2;
+ hb_var_num_t reserved3;
+ hb_var_num_t reserved4;
+ hb_var_num_t reserved5;
+ hb_var_num_t reserved6;
+ hb_var_num_t reserved7;
+} hb_draw_state_t;
+
+/**
+ * HB_DRAW_STATE_DEFAULT:
+ *
+ * The default #hb_draw_state_t at the start of glyph drawing.
+ */
+#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}}
+
/**
* hb_draw_funcs_t:
*
* Glyph draw callbacks.
*
- * _move_to, _line_to and _cubic_to calls are necessary to be defined but we
- * translate _quadratic_to calls to _cubic_to if the callback isn't defined.
+ * #hb_draw_move_to_func_t, #hb_draw_line_to_func_t and
+ * #hb_draw_cubic_to_func_t calls are necessary to be defined but we translate
+ * #hb_draw_quadratic_to_func_t calls to #hb_draw_cubic_to_func_t if the
+ * callback isn't defined.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
+
typedef struct hb_draw_funcs_t hb_draw_funcs_t;
+
+/**
+ * hb_draw_move_to_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "move-to" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_move_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data);
+
+/**
+ * hb_draw_line_to_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "line-to" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_line_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data);
+
+/**
+ * hb_draw_quadratic_to_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @control_x: X component of control point
+ * @control_y: Y component of control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "quadratic-to" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_quadratic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y,
+ void *user_data);
+
+/**
+ * hb_draw_cubic_to_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @control1_x: X component of first control point
+ * @control1_y: Y component of first control point
+ * @control2_x: X component of second control point
+ * @control2_y: Y component of second control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "cubic-to" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_cubic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y,
+ void *user_data);
+
+/**
+ * hb_draw_close_path_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "close-path" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_close_path_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ void *user_data);
+
+/**
+ * hb_draw_funcs_set_move_to_func:
+ * @dfuncs: draw functions object
+ * @func: (closure user_data) (destroy destroy) (scope notified): move-to callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets move-to callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
- hb_draw_move_to_func_t move_to);
+hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_move_to_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_draw_funcs_set_line_to_func:
+ * @dfuncs: draw functions object
+ * @func: (closure user_data) (destroy destroy) (scope notified): line-to callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets line-to callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
- hb_draw_line_to_func_t line_to);
+hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_line_to_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_draw_funcs_set_quadratic_to_func:
+ * @dfuncs: draw functions object
+ * @func: (closure user_data) (destroy destroy) (scope notified): quadratic-to callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets quadratic-to callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
- hb_draw_quadratic_to_func_t quadratic_to);
+hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_quadratic_to_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_draw_funcs_set_cubic_to_func:
+ * @dfuncs: draw functions
+ * @func: (closure user_data) (destroy destroy) (scope notified): cubic-to callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets cubic-to callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
- hb_draw_cubic_to_func_t cubic_to);
+hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_cubic_to_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_draw_funcs_set_close_path_func:
+ * @dfuncs: draw functions object
+ * @func: (closure user_data) (destroy destroy) (scope notified): close-path callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets close-path callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
- hb_draw_close_path_func_t close_path);
+hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_close_path_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
HB_EXTERN hb_draw_funcs_t *
hb_draw_funcs_create (void);
HB_EXTERN hb_draw_funcs_t *
-hb_draw_funcs_reference (hb_draw_funcs_t *funcs);
+hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs);
HB_EXTERN void
-hb_draw_funcs_destroy (hb_draw_funcs_t *funcs);
+hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs);
HB_EXTERN void
-hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs);
+hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs);
HB_EXTERN hb_bool_t
-hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs);
-#endif
+hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs);
+
+
+HB_EXTERN void
+hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y);
+
+HB_EXTERN void
+hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y);
+
+HB_EXTERN void
+hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y);
+
+HB_EXTERN void
+hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y);
+
+HB_EXTERN void
+hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st);
+
HB_END_DECLS
diff --git a/thirdparty/harfbuzz/src/hb-draw.hh b/thirdparty/harfbuzz/src/hb-draw.hh
index 2aa0a5b4db..28bc9218e1 100644
--- a/thirdparty/harfbuzz/src/hb-draw.hh
+++ b/thirdparty/harfbuzz/src/hb-draw.hh
@@ -27,113 +27,205 @@
#include "hb.hh"
-#ifdef HB_EXPERIMENTAL_API
-struct hb_draw_funcs_t
-{
- hb_object_header_t header;
- hb_draw_move_to_func_t move_to;
- hb_draw_line_to_func_t line_to;
- hb_draw_quadratic_to_func_t quadratic_to;
- bool is_quadratic_to_set;
- hb_draw_cubic_to_func_t cubic_to;
- hb_draw_close_path_func_t close_path;
-};
+/*
+ * hb_draw_funcs_t
+ */
+
+#define HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS \
+ HB_DRAW_FUNC_IMPLEMENT (move_to) \
+ HB_DRAW_FUNC_IMPLEMENT (line_to) \
+ HB_DRAW_FUNC_IMPLEMENT (quadratic_to) \
+ HB_DRAW_FUNC_IMPLEMENT (cubic_to) \
+ HB_DRAW_FUNC_IMPLEMENT (close_path) \
+ /* ^--- Add new callbacks here */
-struct draw_helper_t
+struct hb_draw_funcs_t
{
- draw_helper_t (const hb_draw_funcs_t *funcs_, void *user_data_)
- {
- funcs = funcs_;
- user_data = user_data_;
- path_open = false;
- path_start_x = current_x = path_start_y = current_y = 0;
- }
- ~draw_helper_t () { end_path (); }
+ hb_object_header_t header;
- void move_to (hb_position_t x, hb_position_t y)
+ struct {
+#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_func_t name;
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ } func;
+
+ struct {
+#define HB_DRAW_FUNC_IMPLEMENT(name) void *name;
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ } user_data;
+
+ struct {
+#define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ } destroy;
+
+ void emit_move_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
+ { func.move_to (this, draw_data, &st,
+ to_x, to_y,
+ user_data.move_to); }
+ void emit_line_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
+ { func.line_to (this, draw_data, &st,
+ to_x, to_y,
+ user_data.line_to); }
+ void emit_quadratic_to (void *draw_data, hb_draw_state_t &st,
+ float control_x, float control_y,
+ float to_x, float to_y)
+ { func.quadratic_to (this, draw_data, &st,
+ control_x, control_y,
+ to_x, to_y,
+ user_data.quadratic_to); }
+ void emit_cubic_to (void *draw_data, hb_draw_state_t &st,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y)
+ { func.cubic_to (this, draw_data, &st,
+ control1_x, control1_y,
+ control2_x, control2_y,
+ to_x, to_y,
+ user_data.cubic_to); }
+ void emit_close_path (void *draw_data, hb_draw_state_t &st)
+ { func.close_path (this, draw_data, &st,
+ user_data.close_path); }
+
+
+ void move_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
{
- if (path_open) end_path ();
- current_x = path_start_x = x;
- current_y = path_start_y = y;
+ if (st.path_open) close_path (draw_data, st);
+ st.current_x = to_x;
+ st.current_y = to_y;
}
- void line_to (hb_position_t x, hb_position_t y)
+ void line_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
{
- if (equal_to_current (x, y)) return;
- if (!path_open) start_path ();
- funcs->line_to (x, y, user_data);
- current_x = x;
- current_y = y;
+ if (!st.path_open) start_path (draw_data, st);
+ emit_line_to (draw_data, st, to_x, to_y);
+ st.current_x = to_x;
+ st.current_y = to_y;
}
void
- quadratic_to (hb_position_t control_x, hb_position_t control_y,
- hb_position_t to_x, hb_position_t to_y)
+ quadratic_to (void *draw_data, hb_draw_state_t &st,
+ float control_x, float control_y,
+ float to_x, float to_y)
{
- if (equal_to_current (control_x, control_y) && equal_to_current (to_x, to_y))
- return;
- if (!path_open) start_path ();
- if (funcs->is_quadratic_to_set)
- funcs->quadratic_to (control_x, control_y, to_x, to_y, user_data);
- else
- funcs->cubic_to (roundf ((current_x + 2.f * control_x) / 3.f),
- roundf ((current_y + 2.f * control_y) / 3.f),
- roundf ((to_x + 2.f * control_x) / 3.f),
- roundf ((to_y + 2.f * control_y) / 3.f),
- to_x, to_y, user_data);
- current_x = to_x;
- current_y = to_y;
+ if (!st.path_open) start_path (draw_data, st);
+ emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);
+ st.current_x = to_x;
+ st.current_y = to_y;
}
void
- cubic_to (hb_position_t control1_x, hb_position_t control1_y,
- hb_position_t control2_x, hb_position_t control2_y,
- hb_position_t to_x, hb_position_t to_y)
+ cubic_to (void *draw_data, hb_draw_state_t &st,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y)
{
- if (equal_to_current (control1_x, control1_y) &&
- equal_to_current (control2_x, control2_y) &&
- equal_to_current (to_x, to_y))
- return;
- if (!path_open) start_path ();
- funcs->cubic_to (control1_x, control1_y, control2_x, control2_y, to_x, to_y, user_data);
- current_x = to_x;
- current_y = to_y;
+ if (!st.path_open) start_path (draw_data, st);
+ emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
+ st.current_x = to_x;
+ st.current_y = to_y;
}
- void end_path ()
+ void
+ close_path (void *draw_data, hb_draw_state_t &st)
{
- if (path_open)
+ if (st.path_open)
{
- if ((path_start_x != current_x) || (path_start_y != current_y))
- funcs->line_to (path_start_x, path_start_y, user_data);
- funcs->close_path (user_data);
+ if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y))
+ emit_line_to (draw_data, st, st.path_start_x, st.path_start_y);
+ emit_close_path (draw_data, st);
}
- path_open = false;
- path_start_x = current_x = path_start_y = current_y = 0;
+ st.path_open = false;
+ st.path_start_x = st.current_x = st.path_start_y = st.current_y = 0;
}
protected:
- bool equal_to_current (hb_position_t x, hb_position_t y)
- { return current_x == x && current_y == y; }
- void start_path ()
+ void start_path (void *draw_data, hb_draw_state_t &st)
{
- if (path_open) end_path ();
- path_open = true;
- funcs->move_to (path_start_x, path_start_y, user_data);
+ assert (!st.path_open);
+ emit_move_to (draw_data, st, st.current_x, st.current_y);
+ st.path_open = true;
+ st.path_start_x = st.current_x;
+ st.path_start_y = st.current_y;
}
+};
+DECLARE_NULL_INSTANCE (hb_draw_funcs_t);
- hb_position_t path_start_x;
- hb_position_t path_start_y;
+struct hb_draw_session_t
+{
+ hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_ = 0.f)
+ : slant {slant_}, not_slanted {slant == 0.f},
+ funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
+ {}
- hb_position_t current_x;
- hb_position_t current_y;
+ ~hb_draw_session_t () { close_path (); }
- bool path_open;
- const hb_draw_funcs_t *funcs;
- void *user_data;
+ void move_to (float to_x, float to_y)
+ {
+ if (likely (not_slanted))
+ funcs->move_to (draw_data, st,
+ to_x, to_y);
+ else
+ funcs->move_to (draw_data, st,
+ to_x + to_y * slant, to_y);
+ }
+ void line_to (float to_x, float to_y)
+ {
+ if (likely (not_slanted))
+ funcs->line_to (draw_data, st,
+ to_x, to_y);
+ else
+ funcs->line_to (draw_data, st,
+ to_x + to_y * slant, to_y);
+ }
+ void
+ quadratic_to (float control_x, float control_y,
+ float to_x, float to_y)
+ {
+ if (likely (not_slanted))
+ funcs->quadratic_to (draw_data, st,
+ control_x, control_y,
+ to_x, to_y);
+ else
+ funcs->quadratic_to (draw_data, st,
+ control_x + control_y * slant, control_y,
+ to_x + to_y * slant, to_y);
+ }
+ void
+ cubic_to (float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y)
+ {
+ if (likely (not_slanted))
+ funcs->cubic_to (draw_data, st,
+ control1_x, control1_y,
+ control2_x, control2_y,
+ to_x, to_y);
+ else
+ funcs->cubic_to (draw_data, st,
+ control1_x + control1_y * slant, control1_y,
+ control2_x + control2_y * slant, control2_y,
+ to_x + to_y * slant, to_y);
+ }
+ void close_path ()
+ {
+ funcs->close_path (draw_data, st);
+ }
+
+ protected:
+ float slant;
+ bool not_slanted;
+ hb_draw_funcs_t *funcs;
+ void *draw_data;
+ hb_draw_state_t st;
};
-#endif
#endif /* HB_DRAW_HH */
diff --git a/thirdparty/harfbuzz/src/hb-font.cc b/thirdparty/harfbuzz/src/hb-font.cc
index 350fcac139..db05f017a5 100644
--- a/thirdparty/harfbuzz/src/hb-font.cc
+++ b/thirdparty/harfbuzz/src/hb-font.cc
@@ -29,6 +29,7 @@
#include "hb.hh"
#include "hb-font.hh"
+#include "hb-draw.hh"
#include "hb-machinery.hh"
#include "hb-ot.h"
@@ -501,6 +502,136 @@ hb_font_get_glyph_from_name_default (hb_font_t *font,
return font->parent->get_glyph_from_name (name, len, glyph);
}
+static void
+hb_font_get_glyph_shape_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs,
+ void *draw_data,
+ void *user_data HB_UNUSED)
+{
+}
+
+
+typedef struct hb_font_get_glyph_shape_default_adaptor_t {
+ hb_draw_funcs_t *draw_funcs;
+ void *draw_data;
+ float x_scale;
+ float y_scale;
+} hb_font_get_glyph_shape_default_adaptor_t;
+
+static void
+hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+ float x_scale = adaptor->x_scale;
+ float y_scale = adaptor->y_scale;
+
+ adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st,
+ x_scale * to_x, y_scale * to_y);
+}
+
+static void
+hb_draw_line_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+ float x_scale = adaptor->x_scale;
+ float y_scale = adaptor->y_scale;
+
+ st->current_x *= x_scale;
+ st->current_y *= y_scale;
+
+ adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st,
+ x_scale * to_x, y_scale * to_y);
+}
+
+static void
+hb_draw_quadratic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+ float x_scale = adaptor->x_scale;
+ float y_scale = adaptor->y_scale;
+
+ st->current_x *= x_scale;
+ st->current_y *= y_scale;
+
+ adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st,
+ x_scale * control_x, y_scale * control_y,
+ x_scale * to_x, y_scale * to_y);
+}
+
+static void
+hb_draw_cubic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
+ hb_draw_state_t *st,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+ float x_scale = adaptor->x_scale;
+ float y_scale = adaptor->y_scale;
+
+ st->current_x *= x_scale;
+ st->current_y *= y_scale;
+
+ adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st,
+ x_scale * control1_x, y_scale * control1_y,
+ x_scale * control2_x, y_scale * control2_y,
+ x_scale * to_x, y_scale * to_y);
+}
+
+static void
+hb_draw_close_path_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
+ hb_draw_state_t *st,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+
+ adaptor->draw_funcs->emit_close_path (adaptor->draw_data, *st);
+}
+
+static const hb_draw_funcs_t _hb_draw_funcs_default = {
+ HB_OBJECT_HEADER_STATIC,
+
+ {
+#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_default,
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ }
+};
+
+static void
+hb_font_get_glyph_shape_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs,
+ void *draw_data,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t adaptor = {
+ draw_funcs,
+ draw_data,
+ (float) font->x_scale / (float) font->parent->x_scale,
+ (float) font->y_scale / (float) font->parent->y_scale
+ };
+
+ font->parent->get_glyph_shape (glyph,
+ const_cast<hb_draw_funcs_t *> (&_hb_draw_funcs_default),
+ &adaptor);
+}
+
DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
{
HB_OBJECT_HEADER_STATIC,
@@ -1168,6 +1299,26 @@ hb_font_get_glyph_from_name (hb_font_t *font,
return font->get_glyph_from_name (name, len, glyph);
}
+/**
+ * hb_font_get_glyph_shape:
+ * @font: #hb_font_t to work upon
+ * @glyph: : The glyph ID
+ * @dfuncs: #hb_draw_funcs_t to draw to
+ * @draw_data: User data to pass to draw callbacks
+ *
+ * Fetches the glyph shape that corresponds to a glyph in the specified @font.
+ * The shape is returned by way of calls to the callsbacks of the @dfuncs
+ * objects, with @draw_data passed to them.
+ *
+ * Since: 4.0.0
+ **/
+void
+hb_font_get_glyph_shape (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *dfuncs, void *draw_data)
+{
+ font->get_glyph_shape (glyph, dfuncs, draw_data);
+}
/* A bit higher-level, and with fallback */
@@ -1190,7 +1341,7 @@ hb_font_get_extents_for_direction (hb_font_t *font,
hb_direction_t direction,
hb_font_extents_t *extents)
{
- return font->get_extents_for_direction (direction, extents);
+ font->get_extents_for_direction (direction, extents);
}
/**
* hb_font_get_glyph_advance_for_direction:
@@ -1215,7 +1366,7 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font,
hb_position_t *x,
hb_position_t *y)
{
- return font->get_glyph_advance_for_direction (glyph, direction, x, y);
+ font->get_glyph_advance_for_direction (glyph, direction, x, y);
}
/**
* hb_font_get_glyph_advances_for_direction:
@@ -2044,12 +2195,16 @@ hb_font_get_ptem (hb_font_t *font)
* @slant: synthetic slant value.
*
* Sets the "synthetic slant" of a font. By default is zero.
- * Synthetic slant is the graphical skew that the renderer
- * applies to the font at rendering time.
+ * Synthetic slant is the graphical skew applied to the font
+ * at rendering time.
*
* HarfBuzz needs to know this value to adjust shaping results,
* metrics, and style values to match the slanted rendering.
*
+ * <note>Note: The glyph shape fetched via the
+ * hb_font_get_glyph_shape() is slanted to reflect this value
+ * as well.</note>
+ *
* <note>Note: The slant value is a ratio. For example, a
* 20% slant would be represented as a 0.2 value.</note>
*
diff --git a/thirdparty/harfbuzz/src/hb-font.h b/thirdparty/harfbuzz/src/hb-font.h
index a3bbb2e37b..9548857535 100644
--- a/thirdparty/harfbuzz/src/hb-font.h
+++ b/thirdparty/harfbuzz/src/hb-font.h
@@ -511,6 +511,25 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
hb_codepoint_t *glyph,
void *user_data);
+/**
+ * hb_font_get_glyph_shape_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @glyph: The glyph ID to query
+ * @draw_funcs: The draw functions to send the shape data to
+ * @draw_data: The data accompanying the draw functions
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data);
+
/* func setters */
@@ -770,6 +789,22 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_from_name_func_t func,
void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_font_funcs_set_glyph_shape_func:
+ * @ffuncs: A font-function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets the implementation function for #hb_font_get_glyph_shape_func_t.
+ *
+ * Since: 4.0.0
+ **/
+HB_EXTERN void
+hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_shape_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
/* func dispatch */
HB_EXTERN hb_bool_t
@@ -850,6 +885,11 @@ hb_font_get_glyph_from_name (hb_font_t *font,
const char *name, int len, /* -1 means nul-terminated */
hb_codepoint_t *glyph);
+HB_EXTERN void
+hb_font_get_glyph_shape (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *dfuncs, void *draw_data);
+
/* high-level funcs, with fallback */
@@ -1056,11 +1096,6 @@ HB_EXTERN void
hb_font_set_var_named_instance (hb_font_t *font,
unsigned instance_index);
-#ifdef HB_EXPERIMENTAL_API
-HB_EXTERN hb_bool_t
-hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
- const hb_draw_funcs_t *funcs, void *user_data);
-#endif
HB_END_DECLS
diff --git a/thirdparty/harfbuzz/src/hb-font.hh b/thirdparty/harfbuzz/src/hb-font.hh
index 0d73589e8c..70311b4a85 100644
--- a/thirdparty/harfbuzz/src/hb-font.hh
+++ b/thirdparty/harfbuzz/src/hb-font.hh
@@ -57,6 +57,7 @@
HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
HB_FONT_FUNC_IMPLEMENT (glyph_name) \
HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_shape) \
/* ^--- Add new callbacks here */
struct hb_font_funcs_t
@@ -140,6 +141,8 @@ struct hb_font_t
hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); }
float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
+ float em_fscalef_x (float v) { return em_fscalef (v, x_scale); }
+ float em_fscalef_y (float v) { return em_fscalef (v, y_scale); }
hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
{ return em_mult (v, dir_mult (direction)); }
@@ -373,6 +376,15 @@ struct hb_font_t
klass->user_data.glyph_from_name);
}
+ void get_glyph_shape (hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data)
+ {
+ klass->get.f.glyph_shape (this, user_data,
+ glyph,
+ draw_funcs, draw_data,
+ klass->user_data.glyph_shape);
+ }
+
/* A bit higher-level, and with fallback */
@@ -625,7 +637,9 @@ struct hb_font_t
hb_position_t em_mult (int16_t v, int64_t mult)
{ return (hb_position_t) ((v * mult + 32768) >> 16); }
hb_position_t em_scalef (float v, int scale)
- { return (hb_position_t) roundf (v * scale / face->get_upem ()); }
+ { return (hb_position_t) roundf (em_fscalef (v, scale)); }
+ float em_fscalef (float v, int scale)
+ { return v * scale / face->get_upem (); }
float em_fscale (int16_t v, int scale)
{ return (float) v * scale / face->get_upem (); }
};
diff --git a/thirdparty/harfbuzz/src/hb-ft.cc b/thirdparty/harfbuzz/src/hb-ft.cc
index 67691e3ff3..40311e1b91 100644
--- a/thirdparty/harfbuzz/src/hb-ft.cc
+++ b/thirdparty/harfbuzz/src/hb-ft.cc
@@ -33,12 +33,14 @@
#include "hb-ft.h"
+#include "hb-draw.hh"
#include "hb-font.hh"
#include "hb-machinery.hh"
#include "hb-cache.hh"
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
+#include FT_OUTLINE_H
#include FT_TRUETYPE_TABLES_H
@@ -565,6 +567,82 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
return true;
}
+#ifndef HB_NO_DRAW
+
+static int
+_hb_ft_move_to (const FT_Vector *to,
+ hb_draw_session_t *drawing)
+{
+ drawing->move_to (to->x, to->y);
+ return FT_Err_Ok;
+}
+
+static int
+_hb_ft_line_to (const FT_Vector *to,
+ hb_draw_session_t *drawing)
+{
+ drawing->line_to (to->x, to->y);
+ return FT_Err_Ok;
+}
+
+static int
+_hb_ft_conic_to (const FT_Vector *control,
+ const FT_Vector *to,
+ hb_draw_session_t *drawing)
+{
+ drawing->quadratic_to (control->x, control->y,
+ to->x, to->y);
+ return FT_Err_Ok;
+}
+
+static int
+_hb_ft_cubic_to (const FT_Vector *control1,
+ const FT_Vector *control2,
+ const FT_Vector *to,
+ hb_draw_session_t *drawing)
+{
+ drawing->cubic_to (control1->x, control1->y,
+ control2->x, control2->y,
+ to->x, to->y);
+ return FT_Err_Ok;
+}
+
+static void
+hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data HB_UNUSED)
+{
+ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ hb_lock_t lock (ft_font->lock);
+ FT_Face ft_face = ft_font->ft_face;
+
+ if (unlikely (FT_Load_Glyph (ft_face, glyph,
+ FT_LOAD_NO_BITMAP | ft_font->load_flags)))
+ return;
+
+ if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
+ return;
+
+ const FT_Outline_Funcs outline_funcs = {
+ (FT_Outline_MoveToFunc) _hb_ft_move_to,
+ (FT_Outline_LineToFunc) _hb_ft_line_to,
+ (FT_Outline_ConicToFunc) _hb_ft_conic_to,
+ (FT_Outline_CubicToFunc) _hb_ft_cubic_to,
+ 0, /* shift */
+ 0, /* delta */
+ };
+
+ hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
+
+ FT_Outline_Decompose (&ft_face->glyph->outline,
+ &outline_funcs,
+ &draw_session);
+}
+#endif
+
+
static inline void free_static_ft_funcs ();
static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
@@ -596,6 +674,10 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
+#ifndef HB_NO_DRAW
+ hb_font_funcs_set_glyph_shape_func (funcs, hb_ft_get_glyph_shape, nullptr, nullptr);
+#endif
+
hb_font_funcs_make_immutable (funcs);
hb_atexit (free_static_ft_funcs);
diff --git a/thirdparty/harfbuzz/src/hb-gobject-structs.cc b/thirdparty/harfbuzz/src/hb-gobject-structs.cc
index 540b11f911..ef13f1e966 100644
--- a/thirdparty/harfbuzz/src/hb-gobject-structs.cc
+++ b/thirdparty/harfbuzz/src/hb-gobject-structs.cc
@@ -90,6 +90,7 @@ hb_gobject_##name##_get_type () \
HB_DEFINE_OBJECT_TYPE (buffer)
HB_DEFINE_OBJECT_TYPE (blob)
+HB_DEFINE_OBJECT_TYPE (draw_funcs)
HB_DEFINE_OBJECT_TYPE (face)
HB_DEFINE_OBJECT_TYPE (font)
HB_DEFINE_OBJECT_TYPE (font_funcs)
diff --git a/thirdparty/harfbuzz/src/hb-gobject-structs.h b/thirdparty/harfbuzz/src/hb-gobject-structs.h
index 63467f80df..3914a2431a 100644
--- a/thirdparty/harfbuzz/src/hb-gobject-structs.h
+++ b/thirdparty/harfbuzz/src/hb-gobject-structs.h
@@ -49,6 +49,10 @@ hb_gobject_buffer_get_type (void);
#define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ())
HB_EXTERN GType
+hb_gobject_draw_funcs_get_type (void);
+#define HB_GOBJECT_TYPE_DRAW_FUNCS (hb_gobject_draw_funcs_get_type ())
+
+HB_EXTERN GType
hb_gobject_face_get_type (void);
#define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ())
diff --git a/thirdparty/harfbuzz/src/hb-machinery.hh b/thirdparty/harfbuzz/src/hb-machinery.hh
index 5046ac1933..e52a6a4124 100644
--- a/thirdparty/harfbuzz/src/hb-machinery.hh
+++ b/thirdparty/harfbuzz/src/hb-machinery.hh
@@ -194,7 +194,8 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
}
const Returned * operator -> () const { return get (); }
- const Returned & operator * () const { return *get (); }
+ template <typename U = Returned, hb_enable_if (!hb_is_same (U, void))>
+ const U & operator * () const { return *get (); }
explicit operator bool () const
{ return get_stored () != Funcs::get_null (); }
template <typename C> operator const C * () const { return get (); }
@@ -272,14 +273,19 @@ struct hb_face_lazy_loader_t : hb_lazy_loader_t<T,
hb_face_lazy_loader_t<T, WheresFace>,
hb_face_t, WheresFace> {};
-template <typename T, unsigned int WheresFace>
+template <typename T, unsigned int WheresFace, bool core=false>
struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
- hb_table_lazy_loader_t<T, WheresFace>,
+ hb_table_lazy_loader_t<T, WheresFace, core>,
hb_face_t, WheresFace,
hb_blob_t>
{
static hb_blob_t *create (hb_face_t *face)
- { return hb_sanitize_context_t ().reference_table<T> (face); }
+ {
+ auto c = hb_sanitize_context_t ();
+ if (core)
+ c.set_num_glyphs (0); // So we don't recurse ad infinitum...
+ return c.reference_table<T> (face);
+ }
static void destroy (hb_blob_t *p) { hb_blob_destroy (p); }
static const hb_blob_t *get_null ()
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc b/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc
index 3298fa35ae..df4554ac00 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc
@@ -442,13 +442,12 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph
return true;
}
-#ifdef HB_EXPERIMENTAL_API
struct cff1_path_param_t
{
cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_,
- draw_helper_t &draw_helper_, point_t *delta_)
+ hb_draw_session_t &draw_session_, point_t *delta_)
{
- draw_helper = &draw_helper_;
+ draw_session = &draw_session_;
cff = cff_;
font = font_;
delta = delta_;
@@ -458,14 +457,14 @@ struct cff1_path_param_t
{
point_t point = p;
if (delta) point.move (*delta);
- draw_helper->move_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
+ draw_session->move_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
}
void line_to (const point_t &p)
{
point_t point = p;
if (delta) point.move (*delta);
- draw_helper->line_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
+ draw_session->line_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
}
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
@@ -477,15 +476,15 @@ struct cff1_path_param_t
point2.move (*delta);
point3.move (*delta);
}
- draw_helper->cubic_to (font->em_scalef_x (point1.x.to_real ()), font->em_scalef_y (point1.y.to_real ()),
- font->em_scalef_x (point2.x.to_real ()), font->em_scalef_y (point2.y.to_real ()),
- font->em_scalef_x (point3.x.to_real ()), font->em_scalef_y (point3.y.to_real ()));
+ draw_session->cubic_to (font->em_fscalef_x (point1.x.to_real ()), font->em_fscalef_y (point1.y.to_real ()),
+ font->em_fscalef_x (point2.x.to_real ()), font->em_fscalef_y (point2.y.to_real ()),
+ font->em_fscalef_x (point3.x.to_real ()), font->em_fscalef_y (point3.y.to_real ()));
}
- void end_path () { draw_helper->end_path (); }
+ void end_path () { draw_session->close_path (); }
hb_font_t *font;
- draw_helper_t *draw_helper;
+ hb_draw_session_t *draw_session;
point_t *delta;
const OT::cff1::accelerator_t *cff;
@@ -513,7 +512,7 @@ struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_int
};
static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
- draw_helper_t &draw_helper, bool in_seac = false, point_t *delta = nullptr);
+ hb_draw_session_t &draw_session, bool in_seac = false, point_t *delta = nullptr);
struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t>
{
@@ -530,14 +529,14 @@ struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_pa
hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
if (unlikely (!(!env.in_seac && base && accent
- && _get_path (param.cff, param.font, base, *param.draw_helper, true)
- && _get_path (param.cff, param.font, accent, *param.draw_helper, true, &delta))))
+ && _get_path (param.cff, param.font, base, *param.draw_session, true)
+ && _get_path (param.cff, param.font, accent, *param.draw_session, true, &delta))))
env.set_error ();
}
};
bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
- draw_helper_t &draw_helper, bool in_seac, point_t *delta)
+ hb_draw_session_t &draw_session, bool in_seac, point_t *delta)
{
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
@@ -546,7 +545,7 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin
const byte_str_t str = (*cff->charStrings)[glyph];
interp.env.init (str, *cff, fd);
interp.env.set_in_seac (in_seac);
- cff1_path_param_t param (cff, font, draw_helper, delta);
+ cff1_path_param_t param (cff, font, draw_session, delta);
if (unlikely (!interp.interpret (param))) return false;
/* Let's end the path specially since it is called inside seac also */
@@ -555,16 +554,15 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin
return true;
}
-bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
+bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
{
#ifdef HB_NO_OT_FONT_CFF
/* XXX Remove check when this code moves to .hh file. */
return true;
#endif
- return _get_path (this, font, glyph, draw_helper);
+ return _get_path (this, font, glyph, draw_session);
}
-#endif
struct get_seac_param_t
{
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh
index 6fb59315c9..542e3f4de3 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh
@@ -1347,9 +1347,7 @@ struct cff1
HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
-#ifdef HB_EXPERIMENTAL_API
- HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
-#endif
+ HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
private:
struct gname_t
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc b/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc
index 879b7cdb23..817fe064ce 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc
@@ -143,30 +143,29 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
return true;
}
-#ifdef HB_EXPERIMENTAL_API
struct cff2_path_param_t
{
- cff2_path_param_t (hb_font_t *font_, draw_helper_t &draw_helper_)
+ cff2_path_param_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
{
- draw_helper = &draw_helper_;
+ draw_session = &draw_session_;
font = font_;
}
void move_to (const point_t &p)
- { draw_helper->move_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
+ { draw_session->move_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); }
void line_to (const point_t &p)
- { draw_helper->line_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
+ { draw_session->line_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); }
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
{
- draw_helper->cubic_to (font->em_scalef_x (p1.x.to_real ()), font->em_scalef_y (p1.y.to_real ()),
- font->em_scalef_x (p2.x.to_real ()), font->em_scalef_y (p2.y.to_real ()),
- font->em_scalef_x (p3.x.to_real ()), font->em_scalef_y (p3.y.to_real ()));
+ draw_session->cubic_to (font->em_fscalef_x (p1.x.to_real ()), font->em_fscalef_y (p1.y.to_real ()),
+ font->em_fscalef_x (p2.x.to_real ()), font->em_fscalef_y (p2.y.to_real ()),
+ font->em_fscalef_x (p3.x.to_real ()), font->em_fscalef_y (p3.y.to_real ()));
}
protected:
- draw_helper_t *draw_helper;
+ hb_draw_session_t *draw_session;
hb_font_t *font;
};
@@ -193,7 +192,7 @@ struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_int
struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, cff2_path_procs_path_t> {};
-bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
+bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
{
#ifdef HB_NO_OT_FONT_CFF
/* XXX Remove check when this code moves to .hh file. */
@@ -206,10 +205,9 @@ bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, d
cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t> interp;
const byte_str_t str = (*charStrings)[glyph];
interp.env.init (str, *this, fd, font->coords, font->num_coords);
- cff2_path_param_t param (font, draw_helper);
+ cff2_path_param_t param (font, draw_session);
if (unlikely (!interp.interpret (param))) return false;
return true;
}
-#endif
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh
index 6e1b01c8fe..b77e7f53fa 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh
@@ -515,9 +515,7 @@ struct cff2
HB_INTERNAL bool get_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const;
-#ifdef HB_EXPERIMENTAL_API
- HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
-#endif
+ HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
};
typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;
diff --git a/thirdparty/harfbuzz/src/hb-ot-deprecated.h b/thirdparty/harfbuzz/src/hb-ot-deprecated.h
index ce6b6fef11..5192ff73e3 100644
--- a/thirdparty/harfbuzz/src/hb-ot-deprecated.h
+++ b/thirdparty/harfbuzz/src/hb-ot-deprecated.h
@@ -50,6 +50,21 @@ HB_BEGIN_DECLS
*/
#define HB_MATH_GLYPH_PART_FLAG_EXTENDER HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER
+/* https://github.com/harfbuzz/harfbuzz/pull/3417 */
+/**
+ * HB_OT_MATH_SCRIPT:
+ *
+ * Use #HB_SCRIPT_MATH or #HB_OT_TAG_MATH_SCRIPT instead.
+ *
+ * <note>Previous versions of this documentation recommended passing
+ * #HB_OT_MATH_SCRIPT to hb_buffer_set_script() to enable math shaping, but this
+ * usage is no longer supported. Use #HB_SCRIPT_MATH instead.</note>
+ *
+ * Since: 1.3.3
+ * Deprecated: 3.4.0
+ */
+#define HB_OT_MATH_SCRIPT HB_OT_TAG_MATH_SCRIPT
+
/* Like hb_ot_layout_table_find_script, but takes zero-terminated array of scripts to test */
HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_table_select_script) hb_bool_t
diff --git a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh
index eff09838af..c05034b3bb 100644
--- a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh
@@ -32,6 +32,11 @@
#define HB_OT_FACE_TABLE_LIST_HH
#endif /* HB_OT_FACE_TABLE_LIST_HH */ /* Dummy header guards */
+#ifndef HB_OT_CORE_TABLE
+#define HB_OT_CORE_TABLE(Namespace, Type) HB_OT_TABLE (Namespace, Type)
+#define _HB_OT_CORE_TABLE_UNDEF
+#endif
+
#ifndef HB_OT_ACCELERATOR
#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
#define _HB_OT_ACCELERATOR_UNDEF
@@ -46,7 +51,8 @@
/* OpenType fundamentals. */
-HB_OT_TABLE (OT, head)
+HB_OT_CORE_TABLE (OT, head)
+HB_OT_CORE_TABLE (OT, maxp)
#if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT)
HB_OT_ACCELERATOR (OT, cmap)
#endif
@@ -74,6 +80,7 @@ HB_OT_TABLE (OT, VORG)
#endif
/* TrueType outlines. */
+HB_OT_CORE_TABLE (OT, loca) // Also used to determine number of glyphs
HB_OT_ACCELERATOR (OT, glyf)
/* CFF outlines. */
@@ -138,3 +145,7 @@ HB_OT_TABLE (OT, MATH)
#ifdef _HB_OT_ACCELERATOR_UNDEF
#undef HB_OT_ACCELERATOR
#endif
+
+#ifdef _HB_OT_CORE_TABLE_UNDEF
+#undef HB_OT_CORE_TABLE
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-face.hh b/thirdparty/harfbuzz/src/hb-ot-face.hh
index e24d380bca..415dae8e20 100644
--- a/thirdparty/harfbuzz/src/hb-ot-face.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-face.hh
@@ -63,10 +63,13 @@ struct hb_ot_face_t
hb_face_t *face; /* MUST be JUST before the lazy loaders. */
#define HB_OT_TABLE(Namespace, Type) \
hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
+#define HB_OT_CORE_TABLE(Namespace, Type) \
+ hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type), true> Type;
#define HB_OT_ACCELERATOR(Namespace, Type) \
hb_face_lazy_loader_t<Namespace::Type##_accelerator_t, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
#include "hb-ot-face-table-list.hh"
#undef HB_OT_ACCELERATOR
+#undef HB_OT_CORE_TABLE
#undef HB_OT_TABLE
};
diff --git a/thirdparty/harfbuzz/src/hb-ot-font.cc b/thirdparty/harfbuzz/src/hb-ot-font.cc
index 9f0359a773..77d3f639db 100644
--- a/thirdparty/harfbuzz/src/hb-ot-font.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-font.cc
@@ -257,6 +257,23 @@ hb_ot_get_font_v_extents (hb_font_t *font,
}
#endif
+#ifndef HB_NO_DRAW
+static void
+hb_ot_get_glyph_shape (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data)
+{
+ hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
+ if (font->face->table.glyf->get_path (font, glyph, draw_session)) return;
+#ifndef HB_NO_CFF
+ if (font->face->table.cff1->get_path (font, glyph, draw_session)) return;
+ if (font->face->table.cff2->get_path (font, glyph, draw_session)) return;
+#endif
+}
+#endif
+
static inline void free_static_ot_funcs ();
static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
@@ -279,6 +296,10 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
#endif
+#ifndef HB_NO_DRAW
+ hb_font_funcs_set_glyph_shape_func (funcs, hb_ot_get_glyph_shape, nullptr, nullptr);
+#endif
+
hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
//hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
diff --git a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
index 87a7d800c1..066e152da3 100644
--- a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
@@ -936,7 +936,7 @@ struct glyf
return;
short_offset = 0 == head.indexToLocFormat;
- loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
+ loca_table = face->table.loca.get_blob (); // Needs no destruct!
glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
#ifndef HB_NO_VAR
gvar = face->table.gvar;
@@ -951,7 +951,6 @@ struct glyf
}
~accelerator_t ()
{
- loca_table.destroy ();
glyf_table.destroy ();
}
@@ -1152,11 +1151,10 @@ struct glyf
return operation_count;
}
-#ifdef HB_EXPERIMENTAL_API
struct path_builder_t
{
hb_font_t *font;
- draw_helper_t *draw_helper;
+ hb_draw_session_t *draw_session;
struct optional_point_t
{
@@ -1171,10 +1169,10 @@ struct glyf
{ return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
} first_oncurve, first_offcurve, last_offcurve;
- path_builder_t (hb_font_t *font_, draw_helper_t &draw_helper_)
+ path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
{
font = font_;
- draw_helper = &draw_helper_;
+ draw_session = &draw_session_;
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
}
@@ -1184,10 +1182,6 @@ struct glyf
* https://stackoverflow.com/a/20772557 */
void consume_point (const contour_point_t &point)
{
- /* Skip empty contours */
- if (unlikely (point.is_end_point && !first_oncurve.has_data && !first_offcurve.has_data))
- return;
-
bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE;
optional_point_t p (point.x, point.y);
if (!first_oncurve.has_data)
@@ -1195,7 +1189,7 @@ struct glyf
if (is_on_curve)
{
first_oncurve = p;
- draw_helper->move_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
+ draw_session->move_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
}
else
{
@@ -1204,7 +1198,7 @@ struct glyf
optional_point_t mid = first_offcurve.lerp (p, .5f);
first_oncurve = mid;
last_offcurve = p;
- draw_helper->move_to (font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
+ draw_session->move_to (font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
}
else
first_offcurve = p;
@@ -1216,22 +1210,22 @@ struct glyf
{
if (is_on_curve)
{
- draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
- font->em_scalef_x (p.x), font->em_scalef_y (p.y));
+ draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
+ font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
last_offcurve = optional_point_t ();
}
else
{
optional_point_t mid = last_offcurve.lerp (p, .5f);
- draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
- font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
+ draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
+ font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
last_offcurve = p;
}
}
else
{
if (is_on_curve)
- draw_helper->line_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
+ draw_session->line_to (font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
else
last_offcurve = p;
}
@@ -1242,24 +1236,30 @@ struct glyf
if (first_offcurve.has_data && last_offcurve.has_data)
{
optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
- draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
- font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
+ draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
+ font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
last_offcurve = optional_point_t ();
/* now check the rest */
}
if (first_offcurve.has_data && first_oncurve.has_data)
- draw_helper->quadratic_to (font->em_scalef_x (first_offcurve.x), font->em_scalef_y (first_offcurve.y),
- font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
+ draw_session->quadratic_to (font->em_fscalef_x (first_offcurve.x), font->em_fscalef_y (first_offcurve.y),
+ font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
else if (last_offcurve.has_data && first_oncurve.has_data)
- draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
- font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
+ draw_session->quadratic_to (font->em_fscalef_x (last_offcurve.x), font->em_fscalef_y (last_offcurve.y),
+ font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
else if (first_oncurve.has_data)
- draw_helper->line_to (font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
+ draw_session->line_to (font->em_fscalef_x (first_oncurve.x), font->em_fscalef_y (first_oncurve.y));
+ else if (first_offcurve.has_data)
+ {
+ float x = font->em_fscalef_x (first_offcurve.x), y = font->em_fscalef_x (first_offcurve.y);
+ draw_session->move_to (x, y);
+ draw_session->quadratic_to (x, y, x, y);
+ }
/* Getting ready for the next contour */
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
- draw_helper->end_path ();
+ draw_session->close_path ();
}
}
void points_end () {}
@@ -1269,9 +1269,8 @@ struct glyf
};
bool
- get_path (hb_font_t *font, hb_codepoint_t gid, draw_helper_t &draw_helper) const
- { return get_points (font, gid, path_builder_t (font, draw_helper)); }
-#endif
+ get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
+ { return get_points (font, gid, path_builder_t (font, draw_session)); }
#ifndef HB_NO_VAR
const gvar_accelerator_t *gvar;
diff --git a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
index 36bffa70a5..7487e40e6d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
@@ -28,6 +28,7 @@
#define HB_OT_HMTX_TABLE_HH
#include "hb-open-type.hh"
+#include "hb-ot-maxp-table.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-var-hvar-table.hh"
#include "hb-ot-metrics.hh"
@@ -98,12 +99,12 @@ struct hmtxvmtx
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
Iterator it,
- unsigned num_advances)
+ unsigned num_long_metrics)
{
unsigned idx = 0;
for (auto _ : it)
{
- if (idx < num_advances)
+ if (idx < num_long_metrics)
{
LongMetric lm;
lm.advance = _.first;
@@ -128,7 +129,19 @@ struct hmtxvmtx
if (unlikely (!table_prime)) return_trace (false);
accelerator_t _mtx (c->plan->source);
- unsigned num_advances = _mtx.num_advances_for_subset (c->plan);
+ unsigned num_long_metrics;
+ {
+ /* Determine num_long_metrics to encode. */
+ auto& plan = c->plan;
+ num_long_metrics = plan->num_output_glyphs ();
+ hb_codepoint_t old_gid = 0;
+ unsigned int last_advance = plan->old_gid_for_new_gid (num_long_metrics - 1, &old_gid) ? _mtx.get_advance (old_gid) : 0;
+ while (num_long_metrics > 1 &&
+ last_advance == (plan->old_gid_for_new_gid (num_long_metrics - 2, &old_gid) ? _mtx.get_advance (old_gid) : 0))
+ {
+ num_long_metrics--;
+ }
+ }
auto it =
+ hb_range (c->plan->num_output_glyphs ())
@@ -141,13 +154,13 @@ struct hmtxvmtx
})
;
- table_prime->serialize (c->serializer, it, num_advances);
+ table_prime->serialize (c->serializer, it, num_long_metrics);
if (unlikely (c->serializer->in_error ()))
return_trace (false);
// Amend header num hmetrics
- if (unlikely (!subset_update_header (c->plan, num_advances)))
+ if (unlikely (!subset_update_header (c->plan, num_long_metrics)))
return_trace (false);
return_trace (true);
@@ -160,35 +173,46 @@ struct hmtxvmtx
accelerator_t (hb_face_t *face,
unsigned int default_advance_ = 0)
{
+ table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag);
+ var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag);
+
default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
- num_advances = T::is_horizontal ?
- face->table.hhea->numberOfLongMetrics :
+ /* Populate count variables and sort them out as we go */
+
+ unsigned int len = table.get_length ();
+ if (len & 1)
+ len--;
+
+ num_long_metrics = T::is_horizontal ?
+ face->table.hhea->numberOfLongMetrics :
#ifndef HB_NO_VERTICAL
- face->table.vhea->numberOfLongMetrics
+ face->table.vhea->numberOfLongMetrics
#else
- 0
+ 0
#endif
- ;
+ ;
+ if (unlikely (num_long_metrics * 4 > len))
+ num_long_metrics = len / 4;
+ len -= num_long_metrics * 4;
- table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag);
+ num_bearings = face->table.maxp->get_num_glyphs ();
- /* Cap num_metrics() and num_advances() based on table length. */
- unsigned int len = table.get_length ();
- if (unlikely (num_advances * 4 > len))
- num_advances = len / 4;
- num_metrics = num_advances + (len - 4 * num_advances) / 2;
+ if (unlikely (num_bearings < num_long_metrics))
+ num_bearings = num_long_metrics;
+ if (unlikely ((num_bearings - num_long_metrics) * 2 > len))
+ num_bearings = num_long_metrics + len / 2;
+ len -= (num_bearings - num_long_metrics) * 2;
- /* We MUST set num_metrics to zero if num_advances is zero.
+ /* We MUST set num_bearings to zero if num_long_metrics is zero.
* Our get_advance() depends on that. */
- if (unlikely (!num_advances))
- {
- num_metrics = num_advances = 0;
- table.destroy ();
- table = hb_blob_get_empty ();
- }
+ if (unlikely (!num_long_metrics))
+ num_bearings = num_long_metrics = 0;
- var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag);
+ num_advances = num_bearings + len / 2;
+ num_glyphs = face->get_num_glyphs ();
+ if (num_glyphs < num_advances)
+ num_glyphs = num_advances;
}
~accelerator_t ()
{
@@ -198,14 +222,14 @@ struct hmtxvmtx
int get_side_bearing (hb_codepoint_t glyph) const
{
- if (glyph < num_advances)
+ if (glyph < num_long_metrics)
return table->longMetricZ[glyph].sb;
- if (unlikely (glyph >= num_metrics))
+ if (unlikely (glyph >= num_bearings))
return 0;
- const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances];
- return bearings[glyph - num_advances];
+ const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
+ return bearings[glyph - num_long_metrics];
}
int get_side_bearing (hb_font_t *font, hb_codepoint_t glyph) const
@@ -213,7 +237,7 @@ struct hmtxvmtx
int side_bearing = get_side_bearing (glyph);
#ifndef HB_NO_VAR
- if (unlikely (glyph >= num_metrics) || !font->num_coords)
+ if (unlikely (glyph >= num_bearings) || !font->num_coords)
return side_bearing;
if (var_table.get_length ())
@@ -227,18 +251,35 @@ struct hmtxvmtx
unsigned int get_advance (hb_codepoint_t glyph) const
{
- if (unlikely (glyph >= num_metrics))
- {
- /* If num_metrics is zero, it means we don't have the metrics table
- * for this direction: return default advance. Otherwise, it means that the
- * glyph index is out of bound: return zero. */
- if (num_metrics)
- return 0;
- else
- return default_advance;
- }
+ /* OpenType case. */
+ if (glyph < num_bearings)
+ return table->longMetricZ[hb_min (glyph, (uint32_t) num_long_metrics - 1)].advance;
+
+ /* If num_advances is zero, it means we don't have the metrics table
+ * for this direction: return default advance. Otherwise, there's a
+ * well-defined answer. */
+ if (unlikely (!num_advances))
+ return default_advance;
- return table->longMetricZ[hb_min (glyph, (uint32_t) num_advances - 1)].advance;
+#ifdef HB_NO_BORING_EXPANSION
+ return 0;
+#endif
+
+ if (unlikely (glyph >= num_glyphs))
+ return 0;
+
+ /* num_bearings <= glyph < num_glyphs;
+ * num_bearings <= num_advances */
+
+ /* TODO Optimize */
+
+ if (num_bearings == num_advances)
+ return get_advance (num_bearings - 1);
+
+ const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
+ const UFWORD *advances = (const UFWORD *) &bearings[num_bearings - num_long_metrics];
+
+ return advances[hb_min (glyph - num_bearings, num_advances - num_bearings - 1)];
}
unsigned int get_advance (hb_codepoint_t glyph,
@@ -247,7 +288,7 @@ struct hmtxvmtx
unsigned int advance = get_advance (glyph);
#ifndef HB_NO_VAR
- if (unlikely (glyph >= num_metrics) || !font->num_coords)
+ if (unlikely (glyph >= num_bearings) || !font->num_coords)
return advance;
if (var_table.get_length ())
@@ -259,35 +300,13 @@ struct hmtxvmtx
#endif
}
- unsigned int num_advances_for_subset (const hb_subset_plan_t *plan) const
- {
- unsigned int num_advances = plan->num_output_glyphs ();
- unsigned int last_advance = _advance_for_new_gid (plan,
- num_advances - 1);
- while (num_advances > 1 &&
- last_advance == _advance_for_new_gid (plan,
- num_advances - 2))
- {
- num_advances--;
- }
-
- return num_advances;
- }
-
- private:
- unsigned int _advance_for_new_gid (const hb_subset_plan_t *plan,
- hb_codepoint_t new_gid) const
- {
- hb_codepoint_t old_gid;
- if (!plan->old_gid_for_new_gid (new_gid, &old_gid))
- return 0;
-
- return get_advance (old_gid);
- }
-
protected:
- unsigned int num_metrics;
- unsigned int num_advances;
+ // 0 <= num_long_metrics <= num_bearings <= num_advances <= num_glyphs
+ unsigned num_long_metrics;
+ unsigned num_bearings;
+ unsigned num_advances;
+ unsigned num_glyphs;
+
unsigned int default_advance;
private:
@@ -319,6 +338,8 @@ struct hmtxvmtx
* the end. This allows a monospaced
* font to vary the side bearing
* values for each glyph. */
+/*UnsizedArrayOf<UFWORD>advancesX;*/
+ /* TODO Document. */
public:
DEFINE_SIZE_ARRAY (0, longMetricZ);
};
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc
index a599eea6e9..07bbe3bc84 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc
@@ -361,6 +361,13 @@ hb_ot_layout_get_attach_points (hb_face_t *face,
* Fetches a list of the caret positions defined for a ligature glyph in the GDEF
* table of the font. The list returned will begin at the offset provided.
*
+ * Note that a ligature that is formed from n characters will have n-1
+ * caret positions. The first character is not represented in the array,
+ * since its caret position is the glyph position.
+ *
+ * The positions returned by this function are 'unshaped', and will have to
+ * be fixed up for kerning that may be applied to the ligature glyph.
+ *
* Return value: Total number of ligature caret positions for @glyph.
*
**/
@@ -1960,13 +1967,84 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
#ifndef HB_NO_BASE
/**
+ * hb_ot_layout_get_horizontal_baseline_tag_for_script:
+ * @script: a script tag.
+ *
+ * Fetches the dominant horizontal baseline tag used by @script.
+ *
+ * Return value: dominant baseline tag for the @script.
+ *
+ * Since: 4.0.0
+ **/
+hb_ot_layout_baseline_tag_t
+hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script)
+{
+ /* Keep in sync with hb_ot_layout_get_baseline_with_fallback */
+ switch ((int) script)
+ {
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_BENGALI:
+ case HB_SCRIPT_DEVANAGARI:
+ case HB_SCRIPT_GUJARATI:
+ case HB_SCRIPT_GURMUKHI:
+ /* Unicode-2.0 additions */
+ case HB_SCRIPT_TIBETAN:
+ /* Unicode-4.0 additions */
+ case HB_SCRIPT_LIMBU:
+ /* Unicode-4.1 additions */
+ case HB_SCRIPT_SYLOTI_NAGRI:
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_PHAGS_PA:
+ /* Unicode-5.2 additions */
+ case HB_SCRIPT_MEETEI_MAYEK:
+ /* Unicode-6.1 additions */
+ case HB_SCRIPT_SHARADA:
+ case HB_SCRIPT_TAKRI:
+ /* Unicode-7.0 additions */
+ case HB_SCRIPT_MODI:
+ case HB_SCRIPT_SIDDHAM:
+ case HB_SCRIPT_TIRHUTA:
+ /* Unicode-9.0 additions */
+ case HB_SCRIPT_MARCHEN:
+ case HB_SCRIPT_NEWA:
+ /* Unicode-10.0 additions */
+ case HB_SCRIPT_SOYOMBO:
+ case HB_SCRIPT_ZANABAZAR_SQUARE:
+ /* Unicode-11.0 additions */
+ case HB_SCRIPT_DOGRA:
+ case HB_SCRIPT_GUNJALA_GONDI:
+ /* Unicode-12.0 additions */
+ case HB_SCRIPT_NANDINAGARI:
+ return HB_OT_LAYOUT_BASELINE_TAG_HANGING;
+
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_HANGUL:
+ case HB_SCRIPT_HAN:
+ case HB_SCRIPT_HIRAGANA:
+ case HB_SCRIPT_KATAKANA:
+ /* Unicode-3.0 additions */
+ case HB_SCRIPT_BOPOMOFO:
+ /* Unicode-9.0 additions */
+ case HB_SCRIPT_TANGUT:
+ /* Unicode-10.0 additions */
+ case HB_SCRIPT_NUSHU:
+ /* Unicode-13.0 additions */
+ case HB_SCRIPT_KHITAN_SMALL_SCRIPT:
+ return HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT;
+
+ default:
+ return HB_OT_LAYOUT_BASELINE_TAG_ROMAN;
+ }
+}
+
+/**
* hb_ot_layout_get_baseline:
* @font: a font
* @baseline_tag: a baseline tag
* @direction: text direction.
* @script_tag: script tag.
* @language_tag: language tag, currently unused.
- * @coord: (out): baseline value if found.
+ * @coord: (out) (nullable): baseline value if found.
*
* Fetches a baseline value from the face.
*
@@ -1989,6 +2067,227 @@ hb_ot_layout_get_baseline (hb_font_t *font,
return result;
}
+
+/**
+ * hb_ot_layout_get_baseline_with_fallback:
+ * @font: a font
+ * @baseline_tag: a baseline tag
+ * @direction: text direction.
+ * @script_tag: script tag.
+ * @language_tag: language tag, currently unused.
+ * @coord: (out): baseline value if found.
+ *
+ * Fetches a baseline value from the face, and synthesizes
+ * it if the font does not have it.
+ *
+ * Since: 4.0.0
+ **/
+void
+hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
+ hb_ot_layout_baseline_tag_t baseline_tag,
+ hb_direction_t direction,
+ hb_tag_t script_tag,
+ hb_tag_t language_tag,
+ hb_position_t *coord /* OUT */)
+{
+ if (hb_ot_layout_get_baseline (font,
+ baseline_tag,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
+ return;
+
+ /* Synthesize missing baselines.
+ * See https://www.w3.org/TR/css-inline-3/#baseline-synthesis-fonts
+ */
+ switch (baseline_tag)
+ {
+ case HB_OT_LAYOUT_BASELINE_TAG_ROMAN:
+ *coord = 0; // FIXME origin ?
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_MATH:
+ {
+ hb_codepoint_t glyph;
+ hb_glyph_extents_t extents;
+ if (HB_DIRECTION_IS_HORIZONTAL (direction) &&
+ (hb_font_get_nominal_glyph (font, 0x2212u, &glyph) ||
+ hb_font_get_nominal_glyph (font, '-', &glyph)) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ {
+ *coord = extents.y_bearing + extents.height / 2;
+ }
+ else
+ {
+ hb_position_t x_height = 0;
+ hb_ot_metrics_get_position (font, HB_OT_METRICS_TAG_X_HEIGHT, &x_height);
+ *coord = x_height / 2;
+ }
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT:
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT:
+ {
+ hb_position_t embox_top, embox_bottom;
+
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &embox_top);
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &embox_bottom);
+
+ if (baseline_tag == HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT)
+ *coord = embox_top + (embox_bottom - embox_top) / 10;
+ else
+ *coord = embox_bottom + (embox_top - embox_bottom) / 10;
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT:
+ if (hb_ot_layout_get_baseline (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
+ *coord += HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale;
+ else
+ {
+ hb_font_extents_t font_extents;
+ hb_font_get_extents_for_direction (font, direction, &font_extents);
+ *coord = font_extents.ascender;
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT:
+ if (hb_ot_layout_get_baseline (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
+ *coord -= HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale;
+ else
+ {
+ hb_font_extents_t font_extents;
+ hb_font_get_extents_for_direction (font, direction, &font_extents);
+ *coord = font_extents.descender;
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_HANGING:
+ if (HB_DIRECTION_IS_HORIZONTAL (direction))
+ {
+ hb_codepoint_t ch;
+ hb_codepoint_t glyph;
+ hb_glyph_extents_t extents;
+
+ /* Keep in sync with hb_ot_layout_get_horizontal_baseline_for_script */
+ switch ((int) script_tag)
+ {
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_BENGALI: ch = 0x0995u; break;
+ case HB_SCRIPT_DEVANAGARI: ch = 0x0915u; break;
+ case HB_SCRIPT_GUJARATI: ch = 0x0a95u; break;
+ case HB_SCRIPT_GURMUKHI: ch = 0x0a15u; break;
+ /* Unicode-2.0 additions */
+ case HB_SCRIPT_TIBETAN: ch = 0x0f40u; break;
+ /* Unicode-4.0 additions */
+ case HB_SCRIPT_LIMBU: ch = 0x1901u; break;
+ /* Unicode-4.1 additions */
+ case HB_SCRIPT_SYLOTI_NAGRI: ch = 0xa807u; break;
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_PHAGS_PA: ch = 0xa840u; break;
+ /* Unicode-5.2 additions */
+ case HB_SCRIPT_MEETEI_MAYEK: ch = 0xabc0u; break;
+ /* Unicode-6.1 additions */
+ case HB_SCRIPT_SHARADA: ch = 0x11191u; break;
+ case HB_SCRIPT_TAKRI: ch = 0x1168cu; break;
+ /* Unicode-7.0 additions */
+ case HB_SCRIPT_MODI: ch = 0x1160eu;break;
+ case HB_SCRIPT_SIDDHAM: ch = 0x11590u; break;
+ case HB_SCRIPT_TIRHUTA: ch = 0x1148fu; break;
+ /* Unicode-9.0 additions */
+ case HB_SCRIPT_MARCHEN: ch = 0x11c72u; break;
+ case HB_SCRIPT_NEWA: ch = 0x1140eu; break;
+ /* Unicode-10.0 additions */
+ case HB_SCRIPT_SOYOMBO: ch = 0x11a5cu; break;
+ case HB_SCRIPT_ZANABAZAR_SQUARE: ch = 0x11a0bu; break;
+ /* Unicode-11.0 additions */
+ case HB_SCRIPT_DOGRA: ch = 0x1180au; break;
+ case HB_SCRIPT_GUNJALA_GONDI: ch = 0x11d6cu; break;
+ /* Unicode-12.0 additions */
+ case HB_SCRIPT_NANDINAGARI: ch = 0x119b0u; break;
+ default: ch = 0; break;
+ }
+
+ if (ch &&
+ hb_font_get_nominal_glyph (font, ch, &glyph) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ *coord = extents.y_bearing;
+ else
+ *coord = font->y_scale * 6 / 10; // FIXME makes assumptions about origin
+ }
+ else
+ *coord = font->x_scale * 6 / 10; // FIXME makes assumptions about origin
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL:
+ {
+ hb_position_t top, bottom;
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &top);
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &bottom);
+ *coord = (top + bottom) / 2;
+
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL:
+ {
+ hb_position_t top, bottom;
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &top);
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &bottom);
+ *coord = (top + bottom) / 2;
+
+ }
+ break;
+
+ case _HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE:
+ default:
+ *coord = 0;
+ break;
+ }
+}
+
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.h b/thirdparty/harfbuzz/src/hb-ot-layout.h
index d47ba0fc92..4edddd9e0d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.h
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.h
@@ -332,31 +332,6 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
hb_set_t *glyphs_after, /* OUT. May be NULL */
hb_set_t *glyphs_output /* OUT. May be NULL */);
-#ifdef HB_NOT_IMPLEMENTED
-typedef struct
-{
- const hb_codepoint_t *before,
- unsigned int before_length,
- const hb_codepoint_t *input,
- unsigned int input_length,
- const hb_codepoint_t *after,
- unsigned int after_length,
-} hb_ot_layout_glyph_sequence_t;
-
-typedef hb_bool_t
-(*hb_ot_layout_glyph_sequence_func_t) (hb_font_t *font,
- hb_tag_t table_tag,
- unsigned int lookup_index,
- const hb_ot_layout_glyph_sequence_t *sequence,
- void *user_data);
-
-HB_EXTERN void
-Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face,
- hb_tag_t table_tag,
- unsigned int lookup_index,
- hb_ot_layout_glyph_sequence_func_t callback,
- void *user_data);
-#endif
/* Variations support */
@@ -411,19 +386,6 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
hb_set_t *glyphs);
-#ifdef HB_NOT_IMPLEMENTED
-/* Note: You better have GDEF when using this API, or marks won't do much. */
-HB_EXTERN hb_bool_t
-Xhb_ot_layout_lookup_substitute (hb_font_t *font,
- unsigned int lookup_index,
- const hb_ot_layout_glyph_sequence_t *sequence,
- unsigned int out_size,
- hb_codepoint_t *glyphs_out, /* OUT */
- unsigned int *clusters_out, /* OUT */
- unsigned int *out_length /* OUT */);
-#endif
-
-
/*
* GPOS
*/
@@ -431,15 +393,6 @@ Xhb_ot_layout_lookup_substitute (hb_font_t *font,
HB_EXTERN hb_bool_t
hb_ot_layout_has_positioning (hb_face_t *face);
-#ifdef HB_NOT_IMPLEMENTED
-/* Note: You better have GDEF when using this API, or marks won't do much. */
-HB_EXTERN hb_bool_t
-Xhb_ot_layout_lookup_position (hb_font_t *font,
- unsigned int lookup_index,
- const hb_ot_layout_glyph_sequence_t *sequence,
- hb_glyph_position_t *positions /* IN / OUT */);
-#endif
-
/* Optical 'size' feature info. Returns true if found.
* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
HB_EXTERN hb_bool_t
@@ -487,9 +440,11 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
* if the direction is horizontal or vertical, respectively.
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT: Ideographic character face top or right edge,
* if the direction is horizontal or vertical, respectively.
+ * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL: The center of the ideographic character face. Since: 4.0.0
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT: Ideographic em-box bottom or left edge,
* if the direction is horizontal or vertical, respectively.
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT: Ideographic em-box top or right edge baseline,
+ * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL: The center of the ideographic em-box. Since: 4.0.0
* if the direction is horizontal or vertical, respectively.
* @HB_OT_LAYOUT_BASELINE_TAG_MATH: The baseline about which mathematical characters are centered.
* In vertical writing mode when mathematical characters rotated 90 degrees clockwise, are centered.
@@ -503,14 +458,19 @@ typedef enum {
HB_OT_LAYOUT_BASELINE_TAG_HANGING = HB_TAG ('h','a','n','g'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT = HB_TAG ('i','c','f','b'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT = HB_TAG ('i','c','f','t'),
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL = HB_TAG ('I','c','f','c'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT = HB_TAG ('i','d','e','o'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT = HB_TAG ('i','d','t','p'),
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL = HB_TAG ('I','d','c','e'),
HB_OT_LAYOUT_BASELINE_TAG_MATH = HB_TAG ('m','a','t','h'),
/*< private >*/
_HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_layout_baseline_tag_t;
+HB_EXTERN hb_ot_layout_baseline_tag_t
+hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script);
+
HB_EXTERN hb_bool_t
hb_ot_layout_get_baseline (hb_font_t *font,
hb_ot_layout_baseline_tag_t baseline_tag,
@@ -519,6 +479,14 @@ hb_ot_layout_get_baseline (hb_font_t *font,
hb_tag_t language_tag,
hb_position_t *coord /* OUT. May be NULL. */);
+HB_EXTERN void
+hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
+ hb_ot_layout_baseline_tag_t baseline_tag,
+ hb_direction_t direction,
+ hb_tag_t script_tag,
+ hb_tag_t language_tag,
+ hb_position_t *coord /* OUT */);
+
HB_END_DECLS
#endif /* HB_OT_LAYOUT_H */
diff --git a/thirdparty/harfbuzz/src/hb-ot-math-table.hh b/thirdparty/harfbuzz/src/hb-ot-math-table.hh
index 8d0b4317c3..d834d94371 100644
--- a/thirdparty/harfbuzz/src/hb-ot-math-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-math-table.hh
@@ -369,6 +369,37 @@ struct MathKern
return kernValue[i].get_x_value (font, this);
}
+ unsigned int get_entries (unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries, /* OUT */
+ hb_font_t *font) const
+ {
+ const MathValueRecord* correctionHeight = mathValueRecordsZ.arrayZ;
+ const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount;
+ const unsigned int entriesCount = heightCount + 1;
+
+ if (entries_count)
+ {
+ unsigned int start = hb_min (start_offset, entriesCount);
+ unsigned int end = hb_min (start + *entries_count, entriesCount);
+ *entries_count = end - start;
+
+ for (unsigned int i = 0; i < *entries_count; i++) {
+ unsigned int j = start + i;
+
+ hb_position_t max_height;
+ if (j == heightCount) {
+ max_height = INT32_MAX;
+ } else {
+ max_height = correctionHeight[j].get_y_value (font, this);
+ }
+
+ kern_entries[i] = {max_height, kernValue[j].get_x_value (font, this)};
+ }
+ }
+ return entriesCount;
+ }
+
protected:
HBUINT16 heightCount;
UnsizedArrayOf<MathValueRecord>
@@ -423,6 +454,24 @@ struct MathKernInfoRecord
return (base+mathKern[idx]).get_value (correction_height, font);
}
+ unsigned int get_kernings (hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries, /* OUT */
+ hb_font_t *font,
+ const void *base) const
+ {
+ unsigned int idx = kern;
+ if (unlikely (idx >= ARRAY_LENGTH (mathKern)) || !mathKern[idx]) {
+ if (entries_count) *entries_count = 0;
+ return 0;
+ }
+ return (base+mathKern[idx]).get_entries (start_offset,
+ entries_count,
+ kern_entries,
+ font);
+ }
+
protected:
/* Offset to MathKern table for each corner -
* from the beginning of MathKernInfo table. May be NULL. */
@@ -473,6 +522,22 @@ struct MathKernInfo
return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this);
}
+ unsigned int get_kernings (hb_codepoint_t glyph,
+ hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries, /* OUT */
+ hb_font_t *font) const
+ {
+ unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
+ return mathKernInfoRecords[index].get_kernings (kern,
+ start_offset,
+ entries_count,
+ kern_entries,
+ font,
+ this);
+ }
+
protected:
Offset16To<Coverage>
mathKernCoverage;
@@ -545,6 +610,19 @@ struct MathGlyphInfo
hb_font_t *font) const
{ return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); }
+ hb_position_t get_kernings (hb_codepoint_t glyph,
+ hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries, /* OUT */
+ hb_font_t *font) const
+ { return (this+mathKernInfo).get_kernings (glyph,
+ kern,
+ start_offset,
+ entries_count,
+ kern_entries,
+ font); }
+
protected:
/* Offset to MathItalicsCorrectionInfo table -
* from the beginning of MathGlyphInfo table. */
diff --git a/thirdparty/harfbuzz/src/hb-ot-math.cc b/thirdparty/harfbuzz/src/hb-ot-math.cc
index 5781d25f2a..f44ac35849 100644
--- a/thirdparty/harfbuzz/src/hb-ot-math.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-math.cc
@@ -185,6 +185,51 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font,
}
/**
+ * hb_ot_math_get_glyph_kernings:
+ * @font: #hb_font_t to work upon
+ * @glyph: The glyph index from which to retrieve the kernings
+ * @kern: The #hb_ot_math_kern_t from which to retrieve the kernings
+ * @start_offset: offset of the first kern entry to retrieve
+ * @entries_count: (inout) (optional): Input = the maximum number of kern entries to return;
+ * Output = the actual number of kern entries returned
+ * @kern_entries: (out caller-allocates) (array length=entries_count): array of kern entries returned
+ *
+ * Fetches the raw MathKern (cut-in) data for the specified font, glyph index,
+ * and @kern. The corresponding list of kern values and correction heights is
+ * returned as a list of #hb_ot_math_kern_entry_t structs.
+ *
+ * See also #hb_ot_math_get_glyph_kerning, which handles selecting the
+ * appropriate kern value for a given correction height.
+ *
+ * <note>For a glyph with @n defined kern values (where @n > 0), there are only
+ * @n−1 defined correction heights, as each correction height defines a boundary
+ * past which the next kern value should be selected. Therefore, only the
+ * #hb_ot_math_kern_entry_t.kern_value of the uppermost #hb_ot_math_kern_entry_t
+ * actually comes from the font; its corresponding
+ * #hb_ot_math_kern_entry_t.max_correction_height is always set to
+ * <code>INT32_MAX</code>.</note>
+ *
+ * Return value: the total number of kern values available or zero
+ *
+ * Since: 3.4.0
+ **/
+unsigned int
+hb_ot_math_get_glyph_kernings (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries /* OUT */)
+{
+ return font->face->table.MATH->get_glyph_info().get_kernings (glyph,
+ kern,
+ start_offset,
+ entries_count,
+ kern_entries,
+ font);
+}
+
+/**
* hb_ot_math_get_glyph_variants:
* @font: #hb_font_t to work upon
* @glyph: The index of the glyph to stretch
diff --git a/thirdparty/harfbuzz/src/hb-ot-math.h b/thirdparty/harfbuzz/src/hb-ot-math.h
index d3ffa19d85..1378a0639a 100644
--- a/thirdparty/harfbuzz/src/hb-ot-math.h
+++ b/thirdparty/harfbuzz/src/hb-ot-math.h
@@ -50,14 +50,18 @@ HB_BEGIN_DECLS
#define HB_OT_TAG_MATH HB_TAG('M','A','T','H')
/**
- * HB_OT_MATH_SCRIPT:
+ * HB_OT_TAG_MATH_SCRIPT:
*
- * OpenType script tag for math shaping, for use with
- * Use with hb_buffer_set_script().
+ * OpenType script tag, `math`, for features specific to math shaping.
*
- * Since: 1.3.3
+ * <note>#HB_OT_TAG_MATH_SCRIPT is not a valid #hb_script_t and should only be
+ * used with functions that accept raw OpenType script tags, such as
+ * #hb_ot_layout_collect_features. In other cases, #HB_SCRIPT_MATH should be
+ * used instead.</note>
+ *
+ * Since: 3.4.0
*/
-#define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h')
+#define HB_OT_TAG_MATH_SCRIPT HB_TAG('m','a','t','h')
/* Types */
@@ -205,6 +209,20 @@ typedef enum {
} hb_ot_math_kern_t;
/**
+ * hb_ot_math_kern_entry_t:
+ * @max_correction_height: The maximum height at which this entry should be used
+ * @kern_value: The kern value of the entry
+ *
+ * Data type to hold math kerning (cut-in) information for a glyph.
+ *
+ * Since: 3.4.0
+ */
+typedef struct {
+ hb_position_t max_correction_height;
+ hb_position_t kern_value;
+} hb_ot_math_kern_entry_t;
+
+/**
* hb_ot_math_glyph_variant_t:
* @glyph: The glyph index of the variant
* @advance: The advance width of the variant
@@ -281,6 +299,14 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font,
hb_position_t correction_height);
HB_EXTERN unsigned int
+hb_ot_math_get_glyph_kernings (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries /* OUT */);
+
+HB_EXTERN unsigned int
hb_ot_math_get_glyph_variants (hb_font_t *font,
hb_codepoint_t glyph,
hb_direction_t direction,
diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.cc b/thirdparty/harfbuzz/src/hb-ot-metrics.cc
index 103808cf91..43c3cbd41f 100644
--- a/thirdparty/harfbuzz/src/hb-ot-metrics.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-metrics.cc
@@ -238,6 +238,145 @@ hb_ot_metrics_get_position (hb_font_t *font,
}
}
+/**
+ * hb_ot_metrics_get_position_with_fallback:
+ * @font: an #hb_font_t object.
+ * @metrics_tag: tag of metrics value you like to fetch.
+ * @position: (out) (optional): result of metrics value from the font.
+ *
+ * Fetches metrics value corresponding to @metrics_tag from @font,
+ * and synthesizes a value if it the value is missing in the font.
+ *
+ * Since: 4.0.0
+ **/
+void
+hb_ot_metrics_get_position_with_fallback (hb_font_t *font,
+ hb_ot_metrics_tag_t metrics_tag,
+ hb_position_t *position /* OUT */)
+{
+ hb_font_extents_t font_extents;
+ hb_codepoint_t glyph;
+ hb_glyph_extents_t extents;
+
+ if (hb_ot_metrics_get_position (font, metrics_tag, position))
+ {
+ if ((metrics_tag != HB_OT_METRICS_TAG_STRIKEOUT_SIZE &&
+ metrics_tag != HB_OT_METRICS_TAG_UNDERLINE_SIZE) ||
+ *position != 0)
+ return;
+ }
+
+ switch (metrics_tag)
+ {
+ case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER:
+ case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
+ *position = font_extents.ascender;
+ break;
+
+ case HB_OT_METRICS_TAG_VERTICAL_ASCENDER:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents);
+ *position = font_extents.ascender;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER:
+ case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
+ *position = font_extents.descender;
+ break;
+
+ case HB_OT_METRICS_TAG_VERTICAL_DESCENDER:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents);
+ *position = font_extents.ascender;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
+ *position = font_extents.line_gap;
+ break;
+
+ case HB_OT_METRICS_TAG_VERTICAL_LINE_GAP:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents);
+ *position = font_extents.line_gap;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE:
+ case HB_OT_METRICS_TAG_VERTICAL_CARET_RISE:
+ *position = 1;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN:
+ case HB_OT_METRICS_TAG_VERTICAL_CARET_RUN:
+ *position = 0;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET:
+ case HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET:
+ *position = 0;
+ break;
+
+ case HB_OT_METRICS_TAG_X_HEIGHT:
+ if (hb_font_get_nominal_glyph (font, 'o', &glyph) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ *position = extents.height + 2 * extents.y_bearing;
+ else
+ *position = font->y_scale / 2;
+ break;
+
+ case HB_OT_METRICS_TAG_CAP_HEIGHT:
+ if (hb_font_get_nominal_glyph (font, 'O', &glyph) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ *position = extents.height + 2 * extents.y_bearing;
+ else
+ *position = font->y_scale * 2 / 3;
+ break;
+
+ case HB_OT_METRICS_TAG_STRIKEOUT_SIZE:
+ case HB_OT_METRICS_TAG_UNDERLINE_SIZE:
+ *position = font->y_scale / 18;
+ break;
+
+ case HB_OT_METRICS_TAG_STRIKEOUT_OFFSET:
+ {
+ hb_position_t ascender;
+ hb_ot_metrics_get_position_with_fallback (font,
+ HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER,
+ &ascender);
+ *position = ascender / 2;
+ }
+ break;
+
+ case HB_OT_METRICS_TAG_UNDERLINE_OFFSET:
+ *position = - font->y_scale / 18;
+ break;
+
+ case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_SIZE:
+ case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_SIZE:
+ *position = font->x_scale * 10 / 12;
+ break;
+
+ case HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_SIZE:
+ case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_SIZE:
+ *position = font->y_scale * 10 / 12;
+ break;
+
+ case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_OFFSET:
+ case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_OFFSET:
+ *position = 0;
+ break;
+
+ case HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_OFFSET:
+ case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_OFFSET:
+ *position = font->y_scale / 5;
+ break;
+
+ case _HB_OT_METRICS_TAG_MAX_VALUE:
+ default:
+ *position = 0;
+ break;
+ }
+}
+
#ifndef HB_NO_VAR
/**
* hb_ot_metrics_get_variation:
diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.h b/thirdparty/harfbuzz/src/hb-ot-metrics.h
index 5841fc8b0f..30de500088 100644
--- a/thirdparty/harfbuzz/src/hb-ot-metrics.h
+++ b/thirdparty/harfbuzz/src/hb-ot-metrics.h
@@ -110,6 +110,11 @@ hb_ot_metrics_get_position (hb_font_t *font,
hb_ot_metrics_tag_t metrics_tag,
hb_position_t *position /* OUT. May be NULL. */);
+HB_EXTERN void
+hb_ot_metrics_get_position_with_fallback (hb_font_t *font,
+ hb_ot_metrics_tag_t metrics_tag,
+ hb_position_t *position /* OUT */);
+
HB_EXTERN float
hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag);
diff --git a/thirdparty/harfbuzz/src/hb-ot-name.cc b/thirdparty/harfbuzz/src/hb-ot-name.cc
index eff46ef227..c35ac5b3dc 100644
--- a/thirdparty/harfbuzz/src/hb-ot-name.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-name.cc
@@ -52,7 +52,7 @@
* array is owned by the @face and should not be modified. It can be
* used as long as @face is alive.
*
- * Returns: (out) (transfer none) (array length=num_entries): Array of available name entries.
+ * Returns: (transfer none) (array length=num_entries): Array of available name entries.
* Since: 2.1.0
**/
const hb_ot_name_entry_t *
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc
index 2298aa92f2..224f8b842e 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc
@@ -635,6 +635,11 @@ modifier_combining_marks[] =
0x06E3u, /* ARABIC SMALL LOW SEEN */
0x06E7u, /* ARABIC SMALL HIGH YEH */
0x06E8u, /* ARABIC SMALL HIGH NOON */
+ 0x08CAu, /* ARABIC SMALL HIGH FARSI YEH */
+ 0x08CBu, /* ARABIC SMALL HIGH YEH BARREE WITH TWO DOTS BELOW */
+ 0x08CDu, /* ARABIC SMALL HIGH ZAH */
+ 0x08CEu, /* ARABIC LARGE ROUND DOT ABOVE */
+ 0x08CFu, /* ARABIC LARGE ROUND DOT BELOW */
0x08D3u, /* ARABIC SMALL LOW WAW */
0x08F3u, /* ARABIC SMALL HIGH WAW */
};
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
index c3920b2cc6..fb9c60cce9 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
@@ -385,7 +385,9 @@ struct machine_index_t :
typename Iter::item_t>
{
machine_index_t (const Iter& it) : it (it) {}
- machine_index_t (const machine_index_t& o) : it (o.it) {}
+ machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>,
+ typename Iter::item_t> (),
+ it (o.it) {}
static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc b/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc
index 671f30327f..b2eedb027b 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc
@@ -497,14 +497,14 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
#endif
#ifndef HB_DISABLE_DEPRECATED
- if (!buffer->message (font, "start fallback kern"))
- return;
-
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
!font->has_glyph_h_kerning_func () :
!font->has_glyph_v_kerning_func ())
return;
+ if (!buffer->message (font, "start fallback kern"))
+ return;
+
bool reverse = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
if (reverse)
diff --git a/thirdparty/harfbuzz/src/hb-ot-tag.cc b/thirdparty/harfbuzz/src/hb-ot-tag.cc
index 1837063af8..f50be97ad3 100644
--- a/thirdparty/harfbuzz/src/hb-ot-tag.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-tag.cc
@@ -41,6 +41,7 @@ hb_ot_old_tag_from_script (hb_script_t script)
switch ((hb_tag_t) script)
{
case HB_SCRIPT_INVALID: return HB_OT_TAG_DEFAULT_SCRIPT;
+ case HB_SCRIPT_MATH: return HB_OT_TAG_MATH_SCRIPT;
/* KATAKANA and HIRAGANA both map to 'kana' */
case HB_SCRIPT_HIRAGANA: return HB_TAG('k','a','n','a');
@@ -63,6 +64,8 @@ hb_ot_old_tag_to_script (hb_tag_t tag)
{
if (unlikely (tag == HB_OT_TAG_DEFAULT_SCRIPT))
return HB_SCRIPT_INVALID;
+ if (unlikely (tag == HB_OT_TAG_MATH_SCRIPT))
+ return HB_SCRIPT_MATH;
/* This side of the conversion is fully algorithmic. */
diff --git a/thirdparty/harfbuzz/src/hb-shape.cc b/thirdparty/harfbuzz/src/hb-shape.cc
index c1f619c81c..3407e1af42 100644
--- a/thirdparty/harfbuzz/src/hb-shape.cc
+++ b/thirdparty/harfbuzz/src/hb-shape.cc
@@ -126,6 +126,13 @@ hb_shape_full (hb_font_t *font,
unsigned int num_features,
const char * const *shaper_list)
{
+ hb_buffer_t *text_buffer = nullptr;
+ if (buffer->flags & HB_BUFFER_FLAG_VERIFY)
+ {
+ text_buffer = hb_buffer_create ();
+ hb_buffer_append (text_buffer, buffer, 0, -1);
+ }
+
hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached2 (font->face, &buffer->props,
features, num_features,
font->coords, font->num_coords,
@@ -133,6 +140,17 @@ hb_shape_full (hb_font_t *font,
hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
hb_shape_plan_destroy (shape_plan);
+ if (text_buffer)
+ {
+ if (res && !buffer->verify (text_buffer,
+ font,
+ features,
+ num_features,
+ shaper_list))
+ res = false;
+ hb_buffer_destroy (text_buffer);
+ }
+
return res;
}
diff --git a/thirdparty/harfbuzz/src/hb-static.cc b/thirdparty/harfbuzz/src/hb-static.cc
index ec4b241470..bd698814e8 100644
--- a/thirdparty/harfbuzz/src/hb-static.cc
+++ b/thirdparty/harfbuzz/src/hb-static.cc
@@ -33,6 +33,7 @@
#include "hb-aat-layout-feat-table.hh"
#include "hb-ot-layout-common.hh"
#include "hb-ot-cmap-table.hh"
+#include "hb-ot-glyf-table.hh"
#include "hb-ot-head-table.hh"
#include "hb-ot-maxp-table.hh"
@@ -55,17 +56,41 @@ const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
/* hb_face_t */
+static inline unsigned
+load_num_glyphs_from_loca (const hb_face_t *face)
+{
+ unsigned ret = 0;
+
+ unsigned indexToLocFormat = face->table.head->indexToLocFormat;
+
+ if (indexToLocFormat <= 1)
+ {
+ bool short_offset = 0 == indexToLocFormat;
+ hb_blob_t *loca_blob = face->table.loca.get_blob ();
+ ret = hb_max (1u, loca_blob->length / (short_offset ? 2 : 4)) - 1;
+ }
+
+ return ret;
+}
+
+static inline unsigned
+load_num_glyphs_from_maxp (const hb_face_t *face)
+{
+ return face->table.maxp->get_num_glyphs ();
+}
+
unsigned int
hb_face_t::load_num_glyphs () const
{
- hb_sanitize_context_t c = hb_sanitize_context_t ();
- c.set_num_glyphs (0); /* So we don't recurse ad infinitum. */
- hb_blob_t *maxp_blob = c.reference_table<OT::maxp> (this);
- const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
+ unsigned ret = 0;
+
+#ifndef HB_NO_BORING_EXPANSION
+ ret = hb_max (ret, load_num_glyphs_from_loca (this));
+#endif
+
+ ret = hb_max (ret, load_num_glyphs_from_maxp (this));
- unsigned int ret = maxp_table->get_num_glyphs ();
num_glyphs.set_relaxed (ret);
- hb_blob_destroy (maxp_blob);
return ret;
}
diff --git a/thirdparty/harfbuzz/src/hb-style.cc b/thirdparty/harfbuzz/src/hb-style.cc
index c0c5c4832c..c7d7d713c2 100644
--- a/thirdparty/harfbuzz/src/hb-style.cc
+++ b/thirdparty/harfbuzz/src/hb-style.cc
@@ -46,13 +46,13 @@
static inline float
_hb_angle_to_ratio (float a)
{
- return tanf (a * float (M_PI / 180.));
+ return tanf (a * float (-M_PI / 180.));
}
static inline float
_hb_ratio_to_angle (float r)
{
- return atanf (r) * float (180. / M_PI);
+ return atanf (r) * float (-180. / M_PI);
}
/**
@@ -72,8 +72,7 @@ float
hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag)
{
if (unlikely (style_tag == HB_STYLE_TAG_SLANT_RATIO))
- return _hb_angle_to_ratio (hb_style_get_value (font, HB_STYLE_TAG_SLANT_ANGLE))
- + font->slant;
+ return _hb_angle_to_ratio (hb_style_get_value (font, HB_STYLE_TAG_SLANT_ANGLE));
hb_face_t *face = font->face;
diff --git a/thirdparty/harfbuzz/src/hb-style.h b/thirdparty/harfbuzz/src/hb-style.h
index 30a6f2b878..d17d2daa5f 100644
--- a/thirdparty/harfbuzz/src/hb-style.h
+++ b/thirdparty/harfbuzz/src/hb-style.h
@@ -43,8 +43,10 @@ HB_BEGIN_DECLS
* @HB_STYLE_TAG_SLANT_ANGLE: Used to vary between upright and slanted text. Values
* must be greater than -90 and less than +90. Values can be interpreted as
* the angle, in counter-clockwise degrees, of oblique slant from whatever the
- * designer considers to be upright for that font design.
+ * designer considers to be upright for that font design. Typical right-leaning
+ * Italic fonts have a negative slant angle (typically around -12)
* @HB_STYLE_TAG_SLANT_RATIO: same as @HB_STYLE_TAG_SLANT_ANGLE expression as ratio.
+ * Typical right-leaning Italic fonts have a positive slant ratio (typically around 0.2)
* @HB_STYLE_TAG_WIDTH: Used to vary width of text from narrower to wider.
* Non-zero. Values can be interpreted as a percentage of whatever the font
* designer considers “normal width” for that font design.
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc
index af4fcb8137..4481758415 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc
@@ -111,7 +111,7 @@ static void _collect_layout_indices (hb_face_t *face,
retain_all_features = false;
continue;
}
-
+
if (visited_features.has (tag))
continue;
@@ -249,9 +249,9 @@ static void _colr_closure (hb_face_t *face,
hb_set_t glyphset_colrv0;
for (hb_codepoint_t gid : glyphs_colred->iter ())
colr.closure_glyphs (gid, &glyphset_colrv0);
-
+
glyphs_colred->union_ (glyphset_colrv0);
-
+
//closure for COLRv1
colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
} while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
@@ -458,7 +458,7 @@ _nameid_closure (hb_face_t *face,
}
/**
- * hb_subset_plan_create:
+ * hb_subset_plan_create_or_fail:
* @face: font face to create the plan for.
* @input: a #hb_subset_input_t input.
*
@@ -467,17 +467,18 @@ _nameid_closure (hb_face_t *face,
* which tables and glyphs should be retained.
*
* Return value: (transfer full): New subset plan. Destroy with
- * hb_subset_plan_destroy().
+ * hb_subset_plan_destroy(). If there is a failure creating the plan
+ * nullptr will be returned.
*
- * Since: 1.7.5
+ * Since: 4.0.0
**/
hb_subset_plan_t *
-hb_subset_plan_create (hb_face_t *face,
- const hb_subset_input_t *input)
+hb_subset_plan_create_or_fail (hb_face_t *face,
+ const hb_subset_input_t *input)
{
hb_subset_plan_t *plan;
if (unlikely (!(plan = hb_object_create<hb_subset_plan_t> ())))
- return const_cast<hb_subset_plan_t *> (&Null (hb_subset_plan_t));
+ return nullptr;
plan->successful = true;
plan->flags = input->flags;
@@ -514,8 +515,9 @@ hb_subset_plan_create (hb_face_t *face,
plan->layout_variation_indices = hb_set_create ();
plan->layout_variation_idx_map = hb_map_create ();
- if (plan->in_error ()) {
- return plan;
+ if (unlikely (plan->in_error ())) {
+ hb_subset_plan_destroy (plan);
+ return nullptr;
}
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan);
@@ -532,6 +534,10 @@ hb_subset_plan_create (hb_face_t *face,
plan->reverse_glyph_map,
&plan->_num_output_glyphs);
+ if (unlikely (plan->in_error ())) {
+ hb_subset_plan_destroy (plan);
+ return nullptr;
+ }
return plan;
}
@@ -542,7 +548,7 @@ hb_subset_plan_create (hb_face_t *face,
* Decreases the reference count on @plan, and if it reaches zero, destroys
* @plan, freeing all memory.
*
- * Since: 1.7.5
+ * Since: 4.0.0
**/
void
hb_subset_plan_destroy (hb_subset_plan_t *plan)
@@ -596,3 +602,116 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_free (plan);
}
+
+/**
+ * hb_subset_plan_old_to_new_glyph_mapping:
+ * @plan: a subsetting plan.
+ *
+ * Returns the mapping between glyphs in the original font to glyphs in the
+ * subset that will be produced by @plan
+ *
+ * Return value: (transfer none):
+ * A pointer to the #hb_map_t of the mapping.
+ *
+ * Since: 4.0.0
+ **/
+const hb_map_t*
+hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan)
+{
+ return plan->glyph_map;
+}
+
+/**
+ * hb_subset_plan_new_to_old_glyph_mapping:
+ * @plan: a subsetting plan.
+ *
+ * Returns the mapping between glyphs in the subset that will be produced by
+ * @plan and the glyph in the original font.
+ *
+ * Return value: (transfer none):
+ * A pointer to the #hb_map_t of the mapping.
+ *
+ * Since: 4.0.0
+ **/
+const hb_map_t*
+hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan)
+{
+ return plan->reverse_glyph_map;
+}
+
+/**
+ * hb_subset_plan_unicode_to_old_glyph_mapping:
+ * @plan: a subsetting plan.
+ *
+ * Returns the mapping between codepoints in the original font and the
+ * associated glyph id in the original font.
+ *
+ * Return value: (transfer none):
+ * A pointer to the #hb_map_t of the mapping.
+ *
+ * Since: 4.0.0
+ **/
+const hb_map_t*
+hb_subset_plan_unicode_to_old_glyph_mapping (const hb_subset_plan_t *plan)
+{
+ return plan->codepoint_to_glyph;
+}
+
+/**
+ * hb_subset_plan_reference: (skip)
+ * @plan: a #hb_subset_plan_t object.
+ *
+ * Increases the reference count on @plan.
+ *
+ * Return value: @plan.
+ *
+ * Since: 4.0.0
+ **/
+hb_subset_plan_t *
+hb_subset_plan_reference (hb_subset_plan_t *plan)
+{
+ return hb_object_reference (plan);
+}
+
+/**
+ * hb_subset_plan_set_user_data: (skip)
+ * @plan: a #hb_subset_plan_t object.
+ * @key: The user-data key to set
+ * @data: A pointer to the user data
+ * @destroy: (nullable): A callback to call when @data is not needed anymore
+ * @replace: Whether to replace an existing data with the same key
+ *
+ * Attaches a user-data key/data pair to the given subset plan object.
+ *
+ * Return value: %true if success, %false otherwise
+ *
+ * Since: 4.0.0
+ **/
+hb_bool_t
+hb_subset_plan_set_user_data (hb_subset_plan_t *plan,
+ hb_user_data_key_t *key,
+ void *data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ return hb_object_set_user_data (plan, key, data, destroy, replace);
+}
+
+/**
+ * hb_subset_plan_get_user_data: (skip)
+ * @plan: a #hb_subset_plan_t object.
+ * @key: The user-data key to query
+ *
+ * Fetches the user data associated with the specified key,
+ * attached to the specified subset plan object.
+ *
+ * Return value: (transfer none): A pointer to the user data
+ *
+ * Since: 4.0.0
+ **/
+void *
+hb_subset_plan_get_user_data (const hb_subset_plan_t *plan,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (plan, key);
+}
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.hh b/thirdparty/harfbuzz/src/hb-subset-plan.hh
index b9244e5cb2..ab2c4c302c 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.hh
@@ -198,13 +198,4 @@ struct hb_subset_plan_t
}
};
-typedef struct hb_subset_plan_t hb_subset_plan_t;
-
-HB_INTERNAL hb_subset_plan_t *
-hb_subset_plan_create (hb_face_t *face,
- const hb_subset_input_t *input);
-
-HB_INTERNAL void
-hb_subset_plan_destroy (hb_subset_plan_t *plan);
-
#endif /* HB_SUBSET_PLAN_HH */
diff --git a/thirdparty/harfbuzz/src/hb-subset.cc b/thirdparty/harfbuzz/src/hb-subset.cc
index bb46e5b97f..aa8f2c6fb0 100644
--- a/thirdparty/harfbuzz/src/hb-subset.cc
+++ b/thirdparty/harfbuzz/src/hb-subset.cc
@@ -343,9 +343,33 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
{
if (unlikely (!input || !source)) return hb_face_get_empty ();
- hb_subset_plan_t *plan = hb_subset_plan_create (source, input);
- if (unlikely (plan->in_error ())) {
- hb_subset_plan_destroy (plan);
+ hb_subset_plan_t *plan = hb_subset_plan_create_or_fail (source, input);
+ if (unlikely (!plan)) {
+ return nullptr;
+ }
+
+ hb_face_t * result = hb_subset_plan_execute_or_fail (plan);
+ hb_subset_plan_destroy (plan);
+ return result;
+}
+
+
+/**
+ * hb_subset_plan_execute_or_fail:
+ * @plan: a subsetting plan.
+ *
+ * Executes the provided subsetting @plan.
+ *
+ * Return value:
+ * on success returns a reference to generated font subset. If the subsetting operation fails
+ * returns nullptr.
+ *
+ * Since: 4.0.0
+ **/
+hb_face_t *
+hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
+{
+ if (unlikely (!plan || plan->in_error ())) {
return nullptr;
}
@@ -353,7 +377,7 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
bool success = true;
hb_tag_t table_tags[32];
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
- while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
+ while ((hb_face_get_table_tags (plan->source, offset, &num_tables, table_tags), num_tables))
{
for (unsigned i = 0; i < num_tables; ++i)
{
@@ -367,8 +391,5 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
}
end:
- hb_face_t *result = success ? hb_face_reference (plan->dest) : nullptr;
-
- hb_subset_plan_destroy (plan);
- return result;
+ return success ? hb_face_reference (plan->dest) : nullptr;
}
diff --git a/thirdparty/harfbuzz/src/hb-subset.h b/thirdparty/harfbuzz/src/hb-subset.h
index 1c65a4da1c..a2799d91e8 100644
--- a/thirdparty/harfbuzz/src/hb-subset.h
+++ b/thirdparty/harfbuzz/src/hb-subset.h
@@ -40,6 +40,15 @@ HB_BEGIN_DECLS
typedef struct hb_subset_input_t hb_subset_input_t;
/**
+ * hb_subset_plan_t:
+ *
+ * Contains information about how the subset operation will be executed.
+ * Such as mappings from the old glyph ids to the new ones in the subset.
+ */
+
+typedef struct hb_subset_plan_t hb_subset_plan_t;
+
+/**
* hb_subset_flags_t:
* @HB_SUBSET_FLAGS_DEFAULT: all flags at their default value of false.
* @HB_SUBSET_FLAGS_NO_HINTING: If set hinting instructions will be dropped in
@@ -124,7 +133,7 @@ hb_subset_input_set_user_data (hb_subset_input_t *input,
HB_EXTERN void *
hb_subset_input_get_user_data (const hb_subset_input_t *input,
- hb_user_data_key_t *key);
+ hb_user_data_key_t *key);
HB_EXTERN hb_set_t *
hb_subset_input_unicode_set (hb_subset_input_t *input);
@@ -145,6 +154,41 @@ hb_subset_input_set_flags (hb_subset_input_t *input,
HB_EXTERN hb_face_t *
hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input);
+HB_EXTERN hb_face_t *
+hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan);
+
+HB_EXTERN hb_subset_plan_t *
+hb_subset_plan_create_or_fail (hb_face_t *face,
+ const hb_subset_input_t *input);
+
+HB_EXTERN void
+hb_subset_plan_destroy (hb_subset_plan_t *plan);
+
+HB_EXTERN const hb_map_t*
+hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan);
+
+HB_EXTERN const hb_map_t*
+hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan);
+
+HB_EXTERN const hb_map_t*
+hb_subset_plan_unicode_to_old_glyph_mapping (const hb_subset_plan_t *plan);
+
+
+HB_EXTERN hb_subset_plan_t *
+hb_subset_plan_reference (hb_subset_plan_t *plan);
+
+HB_EXTERN hb_bool_t
+hb_subset_plan_set_user_data (hb_subset_plan_t *plan,
+ hb_user_data_key_t *key,
+ void *data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace);
+
+HB_EXTERN void *
+hb_subset_plan_get_user_data (const hb_subset_plan_t *plan,
+ hb_user_data_key_t *key);
+
+
HB_END_DECLS
#endif /* HB_SUBSET_H */
diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h
index 493a09f8cf..dd2c5288cc 100644
--- a/thirdparty/harfbuzz/src/hb-version.h
+++ b/thirdparty/harfbuzz/src/hb-version.h
@@ -41,26 +41,26 @@ HB_BEGIN_DECLS
*
* The major component of the library version available at compile-time.
*/
-#define HB_VERSION_MAJOR 3
+#define HB_VERSION_MAJOR 4
/**
* HB_VERSION_MINOR:
*
* The minor component of the library version available at compile-time.
*/
-#define HB_VERSION_MINOR 3
+#define HB_VERSION_MINOR 0
/**
* HB_VERSION_MICRO:
*
* The micro component of the library version available at compile-time.
*/
-#define HB_VERSION_MICRO 2
+#define HB_VERSION_MICRO 0
/**
* HB_VERSION_STRING:
*
* A string literal containing the library version available at compile-time.
*/
-#define HB_VERSION_STRING "3.3.2"
+#define HB_VERSION_STRING "4.0.0"
/**
* HB_VERSION_ATLEAST: