Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 1 | /* |
Behdad Esfahbod | 2409d5f | 2011-04-21 17:14:28 -0400 | [diff] [blame] | 2 | * Copyright © 2007,2008,2009,2010 Red Hat, Inc. |
Behdad Esfahbod | 2e0c44f | 2013-04-24 16:42:05 -0400 | [diff] [blame] | 3 | * Copyright © 2010,2012,2013 Google, Inc. |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 4 | * |
Behdad Esfahbod | c755cb3 | 2010-04-22 00:11:43 -0400 | [diff] [blame] | 5 | * This is part of HarfBuzz, a text shaping library. |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 6 | * |
| 7 | * Permission is hereby granted, without written agreement and without |
| 8 | * license or royalty fees, to use, copy, modify, and distribute this |
| 9 | * software and its documentation for any purpose, provided that the |
| 10 | * above copyright notice and the following two paragraphs appear in |
| 11 | * all copies of this software. |
| 12 | * |
| 13 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
| 14 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
| 15 | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
| 16 | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| 17 | * DAMAGE. |
| 18 | * |
| 19 | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
| 20 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| 21 | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
| 22 | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
| 23 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| 24 | * |
| 25 | * Red Hat Author(s): Behdad Esfahbod |
Behdad Esfahbod | 98370e8 | 2010-10-27 17:39:01 -0400 | [diff] [blame] | 26 | * Google Author(s): Behdad Esfahbod |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 27 | */ |
| 28 | |
Behdad Esfahbod | 7a750ac | 2011-08-17 14:19:59 +0200 | [diff] [blame] | 29 | #ifndef HB_OT_LAYOUT_GSUB_TABLE_HH |
| 30 | #define HB_OT_LAYOUT_GSUB_TABLE_HH |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 31 | |
Behdad Esfahbod | c77ae40 | 2018-08-25 22:36:36 -0700 | [diff] [blame] | 32 | #include "hb-ot-layout-gsubgpos.hh" |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 33 | |
Behdad Esfahbod | acdba3f | 2010-07-23 15:11:18 -0400 | [diff] [blame] | 34 | |
Behdad Esfahbod | 7c8e844 | 2012-08-28 17:57:49 -0400 | [diff] [blame] | 35 | namespace OT { |
| 36 | |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 37 | typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t; |
Behdad Esfahbod | 6f20f72 | 2009-05-17 20:28:01 -0400 | [diff] [blame] | 38 | |
Behdad Esfahbod | d214b07 | 2019-05-15 19:07:39 -0700 | [diff] [blame] | 39 | template<typename Iterator> |
Behdad Esfahbod | dd3972a | 2019-12-10 13:21:26 -0600 | [diff] [blame] | 40 | static void SingleSubst_serialize (hb_serialize_context_t *c, |
| 41 | Iterator it); |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 42 | |
Behdad Esfahbod | 0d160d5 | 2018-09-03 20:50:11 -0700 | [diff] [blame] | 43 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 44 | struct SingleSubstFormat1 |
| 45 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 46 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 47 | { return (this+coverage).intersects (glyphs); } |
| 48 | |
Qunxin Liu | b4fc593 | 2020-12-09 10:44:18 -0800 | [diff] [blame] | 49 | bool may_have_non_1to1 () const |
| 50 | { return false; } |
| 51 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 52 | void closure (hb_closure_context_t *c) const |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 53 | { |
Behdad Esfahbod | 78d35f0 | 2019-05-15 18:15:05 -0700 | [diff] [blame] | 54 | unsigned d = deltaGlyphID; |
Qunxin Liu | b4fc593 | 2020-12-09 10:44:18 -0800 | [diff] [blame] | 55 | |
Behdad Esfahbod | 896b316 | 2019-03-29 21:16:30 -0700 | [diff] [blame] | 56 | + hb_iter (this+coverage) |
Qunxin Liu | b8a58a0 | 2021-01-10 15:50:04 -0800 | [diff] [blame] | 57 | | hb_filter (c->parent_active_glyphs ()) |
Behdad Esfahbod | 78d35f0 | 2019-05-15 18:15:05 -0700 | [diff] [blame] | 58 | | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; }) |
Behdad Esfahbod | 896b316 | 2019-03-29 21:16:30 -0700 | [diff] [blame] | 59 | | hb_sink (c->output) |
| 60 | ; |
Qunxin Liu | b4fc593 | 2020-12-09 10:44:18 -0800 | [diff] [blame] | 61 | |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 62 | } |
| 63 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 64 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
| 65 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 66 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 67 | { |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 68 | if (unlikely (!(this+coverage).collect_coverage (c->input))) return; |
Behdad Esfahbod | 78d35f0 | 2019-05-15 18:15:05 -0700 | [diff] [blame] | 69 | unsigned d = deltaGlyphID; |
Behdad Esfahbod | 896b316 | 2019-03-29 21:16:30 -0700 | [diff] [blame] | 70 | + hb_iter (this+coverage) |
Behdad Esfahbod | 78d35f0 | 2019-05-15 18:15:05 -0700 | [diff] [blame] | 71 | | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; }) |
Behdad Esfahbod | 896b316 | 2019-03-29 21:16:30 -0700 | [diff] [blame] | 72 | | hb_sink (c->output) |
| 73 | ; |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 74 | } |
| 75 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 76 | const Coverage &get_coverage () const { return this+coverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 77 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 78 | bool would_apply (hb_would_apply_context_t *c) const |
Behdad Esfahbod | 90b60bd | 2019-03-29 22:12:42 -0700 | [diff] [blame] | 79 | { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; } |
Behdad Esfahbod | 2005fa5 | 2012-11-22 14:38:10 -0500 | [diff] [blame] | 80 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 81 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 82 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 83 | TRACE_APPLY (this); |
Behdad Esfahbod | 99c2695 | 2012-05-13 15:45:18 +0200 | [diff] [blame] | 84 | hb_codepoint_t glyph_id = c->buffer->cur().codepoint; |
Behdad Esfahbod | b67881b | 2012-11-24 19:13:55 -0500 | [diff] [blame] | 85 | unsigned int index = (this+coverage).get_coverage (glyph_id); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 86 | if (likely (index == NOT_COVERED)) return_trace (false); |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 87 | |
Behdad Esfahbod | 52ebdff | 2011-09-27 12:38:16 -0400 | [diff] [blame] | 88 | /* According to the Adobe Annotated OpenType Suite, result is always |
| 89 | * limited to 16bit. */ |
Behdad Esfahbod | 7627100 | 2014-07-11 14:54:42 -0400 | [diff] [blame] | 90 | glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu; |
Behdad Esfahbod | 98370e8 | 2010-10-27 17:39:01 -0400 | [diff] [blame] | 91 | c->replace_glyph (glyph_id); |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 92 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 93 | return_trace (true); |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 94 | } |
| 95 | |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 96 | template<typename Iterator, |
Behdad Esfahbod | 2dbdec6 | 2019-05-31 15:38:11 -0700 | [diff] [blame] | 97 | hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 98 | bool serialize (hb_serialize_context_t *c, |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 99 | Iterator glyphs, |
Behdad Esfahbod | 42526d1 | 2019-04-24 10:24:33 -0400 | [diff] [blame] | 100 | unsigned delta) |
Behdad Esfahbod | bc5be24 | 2012-09-01 20:48:22 -0400 | [diff] [blame] | 101 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 102 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | f0a1892 | 2021-07-28 17:36:22 -0600 | [diff] [blame] | 103 | if (unlikely (!c->extend_min (this))) return_trace (false); |
Garret Rieger | 35458b6 | 2021-06-11 13:14:51 -0700 | [diff] [blame] | 104 | if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false); |
Garret Rieger | b14475d | 2021-03-18 10:51:26 -0700 | [diff] [blame] | 105 | c->check_assign (deltaGlyphID, delta, HB_SERIALIZE_ERROR_INT_OVERFLOW); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 106 | return_trace (true); |
Behdad Esfahbod | bc5be24 | 2012-09-01 20:48:22 -0400 | [diff] [blame] | 107 | } |
| 108 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 109 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 110 | { |
| 111 | TRACE_SUBSET (this); |
Garret Rieger | 0af9de1 | 2019-05-20 15:04:20 -0700 | [diff] [blame] | 112 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Behdad Esfahbod | 1aea869 | 2018-12-11 22:53:58 -0500 | [diff] [blame] | 113 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
Behdad Esfahbod | 4c75158 | 2019-03-29 21:46:13 -0700 | [diff] [blame] | 114 | |
Behdad Esfahbod | dc50493 | 2018-09-03 18:23:23 -0700 | [diff] [blame] | 115 | hb_codepoint_t delta = deltaGlyphID; |
Behdad Esfahbod | 4c75158 | 2019-03-29 21:46:13 -0700 | [diff] [blame] | 116 | |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 117 | auto it = |
Behdad Esfahbod | 4c75158 | 2019-03-29 21:46:13 -0700 | [diff] [blame] | 118 | + hb_iter (this+coverage) |
| 119 | | hb_filter (glyphset) |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 120 | | hb_map_retains_sorting ([&] (hb_codepoint_t g) { |
Behdad Esfahbod | 38f95ba | 2019-08-29 13:40:46 -0700 | [diff] [blame] | 121 | return hb_codepoint_pair_t (g, |
| 122 | (g + delta) & 0xFFFF); }) |
| 123 | | hb_filter (glyphset, hb_second) |
| 124 | | hb_map_retains_sorting ([&] (hb_codepoint_pair_t p) -> hb_codepoint_pair_t |
| 125 | { return hb_pair (glyph_map[p.first], glyph_map[p.second]); }) |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 126 | ; |
Behdad Esfahbod | 4c75158 | 2019-03-29 21:46:13 -0700 | [diff] [blame] | 127 | |
Behdad Esfahbod | 05bc5f9 | 2019-05-16 13:05:58 -0700 | [diff] [blame] | 128 | bool ret = bool (it); |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 129 | SingleSubst_serialize (c->serializer, it); |
Behdad Esfahbod | 05bc5f9 | 2019-05-16 13:05:58 -0700 | [diff] [blame] | 130 | return_trace (ret); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 131 | } |
| 132 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 133 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 134 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 135 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 136 | return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c)); |
Behdad Esfahbod | 70de50c | 2009-08-04 00:58:28 -0400 | [diff] [blame] | 137 | } |
| 138 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 139 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 140 | HBUINT16 format; /* Format identifier--format = 1 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 141 | Offset16To<Coverage> |
Behdad Esfahbod | 238c855 | 2009-05-17 00:22:37 -0400 | [diff] [blame] | 142 | coverage; /* Offset to Coverage table--from |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 143 | * beginning of Substitution table */ |
Behdad Esfahbod | 42526d1 | 2019-04-24 10:24:33 -0400 | [diff] [blame] | 144 | HBUINT16 deltaGlyphID; /* Add to original GlyphID to get |
| 145 | * substitute GlyphID, modulo 0x10000 */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 146 | public: |
| 147 | DEFINE_SIZE_STATIC (6); |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 148 | }; |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 149 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 150 | struct SingleSubstFormat2 |
| 151 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 152 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 153 | { return (this+coverage).intersects (glyphs); } |
| 154 | |
Qunxin Liu | b4fc593 | 2020-12-09 10:44:18 -0800 | [diff] [blame] | 155 | bool may_have_non_1to1 () const |
| 156 | { return false; } |
| 157 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 158 | void closure (hb_closure_context_t *c) const |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 159 | { |
Behdad Esfahbod | 16cc313 | 2019-02-14 10:40:05 -0800 | [diff] [blame] | 160 | + hb_zip (this+coverage, substitute) |
Qunxin Liu | b8a58a0 | 2021-01-10 15:50:04 -0800 | [diff] [blame] | 161 | | hb_filter (c->parent_active_glyphs (), hb_first) |
Behdad Esfahbod | 16cc313 | 2019-02-14 10:40:05 -0800 | [diff] [blame] | 162 | | hb_map (hb_second) |
Behdad Esfahbod | f8fcfb2 | 2019-02-14 11:03:29 -0800 | [diff] [blame] | 163 | | hb_sink (c->output) |
Behdad Esfahbod | bb139cb | 2019-02-14 10:51:47 -0800 | [diff] [blame] | 164 | ; |
Qunxin Liu | b4fc593 | 2020-12-09 10:44:18 -0800 | [diff] [blame] | 165 | |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 166 | } |
| 167 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 168 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
| 169 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 170 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 171 | { |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 172 | if (unlikely (!(this+coverage).collect_coverage (c->input))) return; |
Behdad Esfahbod | 16cc313 | 2019-02-14 10:40:05 -0800 | [diff] [blame] | 173 | + hb_zip (this+coverage, substitute) |
| 174 | | hb_map (hb_second) |
Behdad Esfahbod | f8fcfb2 | 2019-02-14 11:03:29 -0800 | [diff] [blame] | 175 | | hb_sink (c->output) |
Behdad Esfahbod | bb139cb | 2019-02-14 10:51:47 -0800 | [diff] [blame] | 176 | ; |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 177 | } |
| 178 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 179 | const Coverage &get_coverage () const { return this+coverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 180 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 181 | bool would_apply (hb_would_apply_context_t *c) const |
Behdad Esfahbod | 90b60bd | 2019-03-29 22:12:42 -0700 | [diff] [blame] | 182 | { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; } |
Behdad Esfahbod | 2005fa5 | 2012-11-22 14:38:10 -0500 | [diff] [blame] | 183 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 184 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 185 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 186 | TRACE_APPLY (this); |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 187 | unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 188 | if (likely (index == NOT_COVERED)) return_trace (false); |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 189 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 190 | if (unlikely (index >= substitute.len)) return_trace (false); |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 191 | |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 192 | c->replace_glyph (substitute[index]); |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 193 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 194 | return_trace (true); |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 195 | } |
| 196 | |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 197 | template<typename Iterator, |
Behdad Esfahbod | f92d188 | 2019-05-15 18:52:57 -0700 | [diff] [blame] | 198 | hb_requires (hb_is_sorted_source_of (Iterator, |
Behdad Esfahbod | 2ad4ba7 | 2019-05-31 15:48:54 -0700 | [diff] [blame] | 199 | hb_codepoint_pair_t))> |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 200 | bool serialize (hb_serialize_context_t *c, |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 201 | Iterator it) |
Behdad Esfahbod | c61be03 | 2012-09-01 21:43:38 -0400 | [diff] [blame] | 202 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 203 | TRACE_SERIALIZE (this); |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 204 | auto substitutes = |
| 205 | + it |
| 206 | | hb_map (hb_second) |
| 207 | ; |
| 208 | auto glyphs = |
| 209 | + it |
| 210 | | hb_map_retains_sorting (hb_first) |
| 211 | ; |
Behdad Esfahbod | f0a1892 | 2021-07-28 17:36:22 -0600 | [diff] [blame] | 212 | if (unlikely (!c->extend_min (this))) return_trace (false); |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 213 | if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false); |
Garret Rieger | 5ba46ed | 2021-06-11 13:34:00 -0700 | [diff] [blame] | 214 | if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 215 | return_trace (true); |
Behdad Esfahbod | c61be03 | 2012-09-01 21:43:38 -0400 | [diff] [blame] | 216 | } |
| 217 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 218 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 219 | { |
| 220 | TRACE_SUBSET (this); |
Garret Rieger | 0af9de1 | 2019-05-20 15:04:20 -0700 | [diff] [blame] | 221 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Behdad Esfahbod | 1aea869 | 2018-12-11 22:53:58 -0500 | [diff] [blame] | 222 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
Behdad Esfahbod | 4c75158 | 2019-03-29 21:46:13 -0700 | [diff] [blame] | 223 | |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 224 | auto it = |
Behdad Esfahbod | 4c75158 | 2019-03-29 21:46:13 -0700 | [diff] [blame] | 225 | + hb_zip (this+coverage, substitute) |
| 226 | | hb_filter (glyphset, hb_first) |
Behdad Esfahbod | 38f95ba | 2019-08-29 13:40:46 -0700 | [diff] [blame] | 227 | | hb_filter (glyphset, hb_second) |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 228 | | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t |
Behdad Esfahbod | bcd3ffc | 2019-05-16 13:22:09 -0700 | [diff] [blame] | 229 | { return hb_pair (glyph_map[p.first], glyph_map[p.second]); }) |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 230 | ; |
Behdad Esfahbod | 4c75158 | 2019-03-29 21:46:13 -0700 | [diff] [blame] | 231 | |
Behdad Esfahbod | 05bc5f9 | 2019-05-16 13:05:58 -0700 | [diff] [blame] | 232 | bool ret = bool (it); |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 233 | SingleSubst_serialize (c->serializer, it); |
Behdad Esfahbod | 05bc5f9 | 2019-05-16 13:05:58 -0700 | [diff] [blame] | 234 | return_trace (ret); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 235 | } |
| 236 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 237 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 238 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 239 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 240 | return_trace (coverage.sanitize (c, this) && substitute.sanitize (c)); |
Behdad Esfahbod | 70de50c | 2009-08-04 00:58:28 -0400 | [diff] [blame] | 241 | } |
| 242 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 243 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 244 | HBUINT16 format; /* Format identifier--format = 2 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 245 | Offset16To<Coverage> |
Behdad Esfahbod | 238c855 | 2009-05-17 00:22:37 -0400 | [diff] [blame] | 246 | coverage; /* Offset to Coverage table--from |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 247 | * beginning of Substitution table */ |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 248 | Array16Of<HBGlyphID16> |
Behdad Esfahbod | c9a7cbe | 2009-05-17 01:22:51 -0400 | [diff] [blame] | 249 | substitute; /* Array of substitute |
| 250 | * GlyphIDs--ordered by Coverage Index */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 251 | public: |
Behdad Esfahbod | 0eb9fc6 | 2010-05-10 19:01:17 -0400 | [diff] [blame] | 252 | DEFINE_SIZE_ARRAY (6, substitute); |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 253 | }; |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 254 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 255 | struct SingleSubst |
| 256 | { |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 257 | |
| 258 | template<typename Iterator, |
Behdad Esfahbod | f92d188 | 2019-05-15 18:52:57 -0700 | [diff] [blame] | 259 | hb_requires (hb_is_sorted_source_of (Iterator, |
| 260 | const hb_codepoint_pair_t))> |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 261 | bool serialize (hb_serialize_context_t *c, |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 262 | Iterator glyphs) |
Behdad Esfahbod | c61be03 | 2012-09-01 21:43:38 -0400 | [diff] [blame] | 263 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 264 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 265 | if (unlikely (!c->extend_min (u.format))) return_trace (false); |
Behdad Esfahbod | 00a00bc | 2019-04-24 10:01:30 -0400 | [diff] [blame] | 266 | unsigned format = 2; |
| 267 | unsigned delta = 0; |
Behdad Esfahbod | 0a18efd | 2019-07-26 14:34:26 -0700 | [diff] [blame] | 268 | if (glyphs) |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 269 | { |
Behdad Esfahbod | c61be03 | 2012-09-01 21:43:38 -0400 | [diff] [blame] | 270 | format = 1; |
Ebrahim Byagowi | 0750456 | 2020-02-21 13:05:44 +0330 | [diff] [blame] | 271 | auto get_delta = [=] (hb_codepoint_pair_t _) |
| 272 | { return (unsigned) (_.second - _.first) & 0xFFFF; }; |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 273 | delta = get_delta (*glyphs); |
| 274 | if (!hb_all (++(+glyphs), delta, get_delta)) format = 2; |
Behdad Esfahbod | c61be03 | 2012-09-01 21:43:38 -0400 | [diff] [blame] | 275 | } |
Behdad Esfahbod | b986c6a | 2019-03-29 20:17:46 -0700 | [diff] [blame] | 276 | u.format = format; |
Behdad Esfahbod | c61be03 | 2012-09-01 21:43:38 -0400 | [diff] [blame] | 277 | switch (u.format) { |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 278 | case 1: return_trace (u.format1.serialize (c, |
Behdad Esfahbod | bcd3ffc | 2019-05-16 13:22:09 -0700 | [diff] [blame] | 279 | + glyphs |
| 280 | | hb_map_retains_sorting (hb_first), |
| 281 | delta)); |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 282 | case 2: return_trace (u.format2.serialize (c, glyphs)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 283 | default:return_trace (false); |
Behdad Esfahbod | c61be03 | 2012-09-01 21:43:38 -0400 | [diff] [blame] | 284 | } |
| 285 | } |
| 286 | |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 287 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 288 | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 289 | { |
Behdad Esfahbod | 00f6a8e | 2014-12-12 20:36:49 -0800 | [diff] [blame] | 290 | TRACE_DISPATCH (this, u.format); |
Behdad Esfahbod | f396fbb | 2015-10-09 12:25:55 -0400 | [diff] [blame] | 291 | if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 292 | switch (u.format) { |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 293 | case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); |
| 294 | case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 295 | default:return_trace (c->default_return_value ()); |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 296 | } |
| 297 | } |
| 298 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 299 | protected: |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 300 | union { |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 301 | HBUINT16 format; /* Format identifier */ |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 302 | SingleSubstFormat1 format1; |
| 303 | SingleSubstFormat2 format2; |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 304 | } u; |
| 305 | }; |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 306 | |
Behdad Esfahbod | 371b55c | 2019-05-15 18:54:07 -0700 | [diff] [blame] | 307 | template<typename Iterator> |
Behdad Esfahbod | dd3972a | 2019-12-10 13:21:26 -0600 | [diff] [blame] | 308 | static void |
Behdad Esfahbod | 0d160d5 | 2018-09-03 20:50:11 -0700 | [diff] [blame] | 309 | SingleSubst_serialize (hb_serialize_context_t *c, |
Garret Rieger | 962f95c | 2019-05-09 13:04:11 -0700 | [diff] [blame] | 310 | Iterator it) |
| 311 | { c->start_embed<SingleSubst> ()->serialize (c, it); } |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 312 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 313 | struct Sequence |
| 314 | { |
Behdad Esfahbod | 23681b6 | 2019-08-28 15:30:37 -0700 | [diff] [blame] | 315 | bool intersects (const hb_set_t *glyphs) const |
| 316 | { return hb_all (substitute, glyphs); } |
| 317 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 318 | void closure (hb_closure_context_t *c) const |
Behdad Esfahbod | 23681b6 | 2019-08-28 15:30:37 -0700 | [diff] [blame] | 319 | { c->output->add_array (substitute.arrayZ, substitute.len); } |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 320 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 321 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | 89bcfb2 | 2019-01-18 14:59:18 -0500 | [diff] [blame] | 322 | { c->output->add_array (substitute.arrayZ, substitute.len); } |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 323 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 324 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 325 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 326 | TRACE_APPLY (this); |
Behdad Esfahbod | aae6945 | 2014-06-05 18:54:44 -0400 | [diff] [blame] | 327 | unsigned int count = substitute.len; |
Behdad Esfahbod | b6b304f | 2014-06-05 17:12:54 -0400 | [diff] [blame] | 328 | |
Behdad Esfahbod | aae6945 | 2014-06-05 18:54:44 -0400 | [diff] [blame] | 329 | /* Special-case to make it in-place and not consider this |
| 330 | * as a "multiplied" substitution. */ |
| 331 | if (unlikely (count == 1)) |
| 332 | { |
Behdad Esfahbod | 63f57f4 | 2018-05-08 16:56:11 -0700 | [diff] [blame] | 333 | c->replace_glyph (substitute.arrayZ[0]); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 334 | return_trace (true); |
Behdad Esfahbod | aae6945 | 2014-06-05 18:54:44 -0400 | [diff] [blame] | 335 | } |
Behdad Esfahbod | 359dead | 2016-05-06 16:19:19 +0100 | [diff] [blame] | 336 | /* Spec disallows this, but Uniscribe allows it. |
ebraminio | 7c6937e | 2017-11-20 14:49:22 -0500 | [diff] [blame] | 337 | * https://github.com/harfbuzz/harfbuzz/issues/253 */ |
Behdad Esfahbod | 359dead | 2016-05-06 16:19:19 +0100 | [diff] [blame] | 338 | else if (unlikely (count == 0)) |
| 339 | { |
| 340 | c->buffer->delete_glyph (); |
| 341 | return_trace (true); |
| 342 | } |
Behdad Esfahbod | c9c6a78 | 2009-05-05 16:22:02 -0400 | [diff] [blame] | 343 | |
Behdad Esfahbod | 101303d | 2013-10-18 00:42:39 +0200 | [diff] [blame] | 344 | unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ? |
Behdad Esfahbod | 03058c3 | 2013-10-17 20:55:34 +0200 | [diff] [blame] | 345 | HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0; |
Behdad Esfahbod | 6fe0d7d | 2021-07-28 12:06:49 -0600 | [diff] [blame] | 346 | unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur()); |
Behdad Esfahbod | aae6945 | 2014-06-05 18:54:44 -0400 | [diff] [blame] | 347 | |
Behdad Esfahbod | 6fe0d7d | 2021-07-28 12:06:49 -0600 | [diff] [blame] | 348 | for (unsigned int i = 0; i < count; i++) |
| 349 | { |
| 350 | /* If is attached to a ligature, don't disturb that. |
| 351 | * https://github.com/harfbuzz/harfbuzz/issues/3069 */ |
| 352 | if (!lig_id) |
| 353 | _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i); |
Behdad Esfahbod | 63f57f4 | 2018-05-08 16:56:11 -0700 | [diff] [blame] | 354 | c->output_glyph_for_component (substitute.arrayZ[i], klass); |
Behdad Esfahbod | ec57e0c | 2012-06-08 21:47:23 -0400 | [diff] [blame] | 355 | } |
Behdad Esfahbod | aae6945 | 2014-06-05 18:54:44 -0400 | [diff] [blame] | 356 | c->buffer->skip_glyph (); |
Behdad Esfahbod | c9c6a78 | 2009-05-05 16:22:02 -0400 | [diff] [blame] | 357 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 358 | return_trace (true); |
Behdad Esfahbod | c9c6a78 | 2009-05-05 16:22:02 -0400 | [diff] [blame] | 359 | } |
| 360 | |
Behdad Esfahbod | 2dbdec6 | 2019-05-31 15:38:11 -0700 | [diff] [blame] | 361 | template <typename Iterator, |
| 362 | hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))> |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 363 | bool serialize (hb_serialize_context_t *c, |
Behdad Esfahbod | 2dbdec6 | 2019-05-31 15:38:11 -0700 | [diff] [blame] | 364 | Iterator subst) |
Behdad Esfahbod | 1f07e33 | 2012-09-03 23:28:34 -0400 | [diff] [blame] | 365 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 366 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | 815cde9 | 2019-01-07 18:33:04 -0500 | [diff] [blame] | 367 | return_trace (substitute.serialize (c, subst)); |
Behdad Esfahbod | 1f07e33 | 2012-09-03 23:28:34 -0400 | [diff] [blame] | 368 | } |
| 369 | |
Behdad Esfahbod | 33c8e23 | 2019-08-28 15:25:55 -0700 | [diff] [blame] | 370 | bool subset (hb_subset_context_t *c) const |
| 371 | { |
| 372 | TRACE_SUBSET (this); |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 373 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Behdad Esfahbod | 33c8e23 | 2019-08-28 15:25:55 -0700 | [diff] [blame] | 374 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 375 | |
Behdad Esfahbod | 23681b6 | 2019-08-28 15:30:37 -0700 | [diff] [blame] | 376 | if (!intersects (&glyphset)) return_trace (false); |
Behdad Esfahbod | 33c8e23 | 2019-08-28 15:25:55 -0700 | [diff] [blame] | 377 | |
| 378 | auto it = |
Ebrahim Byagowi | 0750456 | 2020-02-21 13:05:44 +0330 | [diff] [blame] | 379 | + hb_iter (substitute) |
| 380 | | hb_map (glyph_map) |
| 381 | ; |
Behdad Esfahbod | 33c8e23 | 2019-08-28 15:25:55 -0700 | [diff] [blame] | 382 | |
| 383 | auto *out = c->serializer->start_embed (*this); |
Behdad Esfahbod | dc9222b | 2019-08-28 15:38:46 -0700 | [diff] [blame] | 384 | return_trace (out->serialize (c->serializer, it)); |
Behdad Esfahbod | 33c8e23 | 2019-08-28 15:25:55 -0700 | [diff] [blame] | 385 | } |
| 386 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 387 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 388 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 389 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 390 | return_trace (substitute.sanitize (c)); |
Behdad Esfahbod | 70de50c | 2009-08-04 00:58:28 -0400 | [diff] [blame] | 391 | } |
| 392 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 393 | protected: |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 394 | Array16Of<HBGlyphID16> |
Behdad Esfahbod | c9a7cbe | 2009-05-17 01:22:51 -0400 | [diff] [blame] | 395 | substitute; /* String of GlyphIDs to substitute */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 396 | public: |
Behdad Esfahbod | 0eb9fc6 | 2010-05-10 19:01:17 -0400 | [diff] [blame] | 397 | DEFINE_SIZE_ARRAY (2, substitute); |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 398 | }; |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 399 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 400 | struct MultipleSubstFormat1 |
| 401 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 402 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 403 | { return (this+coverage).intersects (glyphs); } |
| 404 | |
Qunxin Liu | b4fc593 | 2020-12-09 10:44:18 -0800 | [diff] [blame] | 405 | bool may_have_non_1to1 () const |
| 406 | { return true; } |
| 407 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 408 | void closure (hb_closure_context_t *c) const |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 409 | { |
Behdad Esfahbod | 7514a49 | 2019-02-14 13:16:33 -0800 | [diff] [blame] | 410 | + hb_zip (this+coverage, sequence) |
Qunxin Liu | b8a58a0 | 2021-01-10 15:50:04 -0800 | [diff] [blame] | 411 | | hb_filter (c->parent_active_glyphs (), hb_first) |
Behdad Esfahbod | 7514a49 | 2019-02-14 13:16:33 -0800 | [diff] [blame] | 412 | | hb_map (hb_second) |
Behdad Esfahbod | 2376867 | 2019-05-15 21:57:26 -0700 | [diff] [blame] | 413 | | hb_map (hb_add (this)) |
| 414 | | hb_apply ([c] (const Sequence &_) { _.closure (c); }) |
Behdad Esfahbod | 7514a49 | 2019-02-14 13:16:33 -0800 | [diff] [blame] | 415 | ; |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 416 | } |
| 417 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 418 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
| 419 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 420 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 421 | { |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 422 | if (unlikely (!(this+coverage).collect_coverage (c->input))) return; |
Behdad Esfahbod | 7514a49 | 2019-02-14 13:16:33 -0800 | [diff] [blame] | 423 | + hb_zip (this+coverage, sequence) |
| 424 | | hb_map (hb_second) |
Behdad Esfahbod | 2376867 | 2019-05-15 21:57:26 -0700 | [diff] [blame] | 425 | | hb_map (hb_add (this)) |
| 426 | | hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); }) |
Behdad Esfahbod | 7514a49 | 2019-02-14 13:16:33 -0800 | [diff] [blame] | 427 | ; |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 428 | } |
| 429 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 430 | const Coverage &get_coverage () const { return this+coverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 431 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 432 | bool would_apply (hb_would_apply_context_t *c) const |
Behdad Esfahbod | 90b60bd | 2019-03-29 22:12:42 -0700 | [diff] [blame] | 433 | { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; } |
Behdad Esfahbod | 2005fa5 | 2012-11-22 14:38:10 -0500 | [diff] [blame] | 434 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 435 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 436 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 437 | TRACE_APPLY (this); |
Behdad Esfahbod | 30bd763 | 2009-04-15 22:56:15 -0400 | [diff] [blame] | 438 | |
Behdad Esfahbod | b67881b | 2012-11-24 19:13:55 -0500 | [diff] [blame] | 439 | unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 440 | if (likely (index == NOT_COVERED)) return_trace (false); |
Behdad Esfahbod | aa3d7ad | 2009-05-17 23:17:56 -0400 | [diff] [blame] | 441 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 442 | return_trace ((this+sequence[index]).apply (c)); |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 443 | } |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 444 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 445 | bool serialize (hb_serialize_context_t *c, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 446 | hb_sorted_array_t<const HBGlyphID16> glyphs, |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 447 | hb_array_t<const unsigned int> substitute_len_list, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 448 | hb_array_t<const HBGlyphID16> substitute_glyphs_list) |
Behdad Esfahbod | 1f07e33 | 2012-09-03 23:28:34 -0400 | [diff] [blame] | 449 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 450 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | f0a1892 | 2021-07-28 17:36:22 -0600 | [diff] [blame] | 451 | if (unlikely (!c->extend_min (this))) return_trace (false); |
Behdad Esfahbod | 474a120 | 2018-12-21 18:46:51 -0500 | [diff] [blame] | 452 | if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false); |
| 453 | for (unsigned int i = 0; i < glyphs.length; i++) |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 454 | { |
| 455 | unsigned int substitute_len = substitute_len_list[i]; |
Garret Rieger | 5ba46ed | 2021-06-11 13:34:00 -0700 | [diff] [blame] | 456 | if (unlikely (!sequence[i] |
| 457 | .serialize_serialize (c, substitute_glyphs_list.sub_array (0, substitute_len)))) |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 458 | return_trace (false); |
| 459 | substitute_glyphs_list += substitute_len; |
| 460 | } |
Garret Rieger | 5ba46ed | 2021-06-11 13:34:00 -0700 | [diff] [blame] | 461 | return_trace (coverage.serialize_serialize (c, glyphs)); |
Behdad Esfahbod | 1f07e33 | 2012-09-03 23:28:34 -0400 | [diff] [blame] | 462 | } |
| 463 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 464 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 465 | { |
| 466 | TRACE_SUBSET (this); |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 467 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Behdad Esfahbod | 33c8e23 | 2019-08-28 15:25:55 -0700 | [diff] [blame] | 468 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 469 | |
| 470 | auto *out = c->serializer->start_embed (*this); |
| 471 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
| 472 | out->format = format; |
| 473 | |
| 474 | hb_sorted_vector_t<hb_codepoint_t> new_coverage; |
| 475 | + hb_zip (this+coverage, sequence) |
| 476 | | hb_filter (glyphset, hb_first) |
ariza | 188a0a4 | 2020-03-07 11:02:36 -0800 | [diff] [blame] | 477 | | hb_filter (subset_offset_array (c, out->sequence, this), hb_second) |
Behdad Esfahbod | 33c8e23 | 2019-08-28 15:25:55 -0700 | [diff] [blame] | 478 | | hb_map (hb_first) |
| 479 | | hb_map (glyph_map) |
Ebrahim Byagowi | 4990296 | 2019-08-29 15:09:39 +0430 | [diff] [blame] | 480 | | hb_sink (new_coverage) |
Behdad Esfahbod | 33c8e23 | 2019-08-28 15:25:55 -0700 | [diff] [blame] | 481 | ; |
Garret Rieger | 5ba46ed | 2021-06-11 13:34:00 -0700 | [diff] [blame] | 482 | out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); |
Behdad Esfahbod | 33c8e23 | 2019-08-28 15:25:55 -0700 | [diff] [blame] | 483 | return_trace (bool (new_coverage)); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 484 | } |
| 485 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 486 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 487 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 488 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 489 | return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this)); |
Behdad Esfahbod | 70de50c | 2009-08-04 00:58:28 -0400 | [diff] [blame] | 490 | } |
| 491 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 492 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 493 | HBUINT16 format; /* Format identifier--format = 1 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 494 | Offset16To<Coverage> |
Behdad Esfahbod | 238c855 | 2009-05-17 00:22:37 -0400 | [diff] [blame] | 495 | coverage; /* Offset to Coverage table--from |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 496 | * beginning of Substitution table */ |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 497 | Array16OfOffset16To<Sequence> |
Behdad Esfahbod | c9a7cbe | 2009-05-17 01:22:51 -0400 | [diff] [blame] | 498 | sequence; /* Array of Sequence tables |
| 499 | * ordered by Coverage Index */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 500 | public: |
Behdad Esfahbod | 0eb9fc6 | 2010-05-10 19:01:17 -0400 | [diff] [blame] | 501 | DEFINE_SIZE_ARRAY (6, sequence); |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 502 | }; |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 503 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 504 | struct MultipleSubst |
| 505 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 506 | bool serialize (hb_serialize_context_t *c, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 507 | hb_sorted_array_t<const HBGlyphID16> glyphs, |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 508 | hb_array_t<const unsigned int> substitute_len_list, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 509 | hb_array_t<const HBGlyphID16> substitute_glyphs_list) |
Behdad Esfahbod | 1f07e33 | 2012-09-03 23:28:34 -0400 | [diff] [blame] | 510 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 511 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 512 | if (unlikely (!c->extend_min (u.format))) return_trace (false); |
Behdad Esfahbod | 1f07e33 | 2012-09-03 23:28:34 -0400 | [diff] [blame] | 513 | unsigned int format = 1; |
Behdad Esfahbod | b986c6a | 2019-03-29 20:17:46 -0700 | [diff] [blame] | 514 | u.format = format; |
Behdad Esfahbod | 1f07e33 | 2012-09-03 23:28:34 -0400 | [diff] [blame] | 515 | switch (u.format) { |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 516 | case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 517 | default:return_trace (false); |
Behdad Esfahbod | 1f07e33 | 2012-09-03 23:28:34 -0400 | [diff] [blame] | 518 | } |
| 519 | } |
| 520 | |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 521 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 522 | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 523 | { |
Behdad Esfahbod | 00f6a8e | 2014-12-12 20:36:49 -0800 | [diff] [blame] | 524 | TRACE_DISPATCH (this, u.format); |
Behdad Esfahbod | f396fbb | 2015-10-09 12:25:55 -0400 | [diff] [blame] | 525 | if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 526 | switch (u.format) { |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 527 | case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 528 | default:return_trace (c->default_return_value ()); |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 529 | } |
| 530 | } |
| 531 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 532 | protected: |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 533 | union { |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 534 | HBUINT16 format; /* Format identifier */ |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 535 | MultipleSubstFormat1 format1; |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 536 | } u; |
| 537 | }; |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 538 | |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 539 | struct AlternateSet |
| 540 | { |
Behdad Esfahbod | dc9222b | 2019-08-28 15:38:46 -0700 | [diff] [blame] | 541 | bool intersects (const hb_set_t *glyphs) const |
| 542 | { return hb_any (alternates, glyphs); } |
| 543 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 544 | void closure (hb_closure_context_t *c) const |
Behdad Esfahbod | 23681b6 | 2019-08-28 15:30:37 -0700 | [diff] [blame] | 545 | { c->output->add_array (alternates.arrayZ, alternates.len); } |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 546 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 547 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | 89bcfb2 | 2019-01-18 14:59:18 -0500 | [diff] [blame] | 548 | { c->output->add_array (alternates.arrayZ, alternates.len); } |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 549 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 550 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 551 | { |
| 552 | TRACE_APPLY (this); |
| 553 | unsigned int count = alternates.len; |
| 554 | |
| 555 | if (unlikely (!count)) return_trace (false); |
| 556 | |
Behdad Esfahbod | cc1c4fd | 2018-09-10 16:36:05 +0200 | [diff] [blame] | 557 | hb_mask_t glyph_mask = c->buffer->cur().mask; |
| 558 | hb_mask_t lookup_mask = c->lookup_mask; |
| 559 | |
| 560 | /* Note: This breaks badly if two features enabled this lookup together. */ |
| 561 | unsigned int shift = hb_ctz (lookup_mask); |
| 562 | unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift); |
| 563 | |
Behdad Esfahbod | 41248cc | 2019-05-07 20:54:31 -0700 | [diff] [blame] | 564 | /* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */ |
Behdad Esfahbod | 71c9f84 | 2018-09-10 22:37:19 +0200 | [diff] [blame] | 565 | if (alt_index == HB_OT_MAP_MAX_VALUE && c->random) |
Behdad Esfahbod | 40884af | 2021-07-09 17:17:05 -0600 | [diff] [blame] | 566 | { |
| 567 | /* Maybe we can do better than unsafe-to-break all; but since we are |
| 568 | * changing random state, it would be hard to track that. Good 'nough. */ |
| 569 | c->buffer->unsafe_to_break_all (); |
Behdad Esfahbod | 08260c7 | 2018-09-11 10:51:19 +0200 | [diff] [blame] | 570 | alt_index = c->random_number () % count + 1; |
Behdad Esfahbod | 40884af | 2021-07-09 17:17:05 -0600 | [diff] [blame] | 571 | } |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 572 | |
Behdad Esfahbod | 71c9f84 | 2018-09-10 22:37:19 +0200 | [diff] [blame] | 573 | if (unlikely (alt_index > count || alt_index == 0)) return_trace (false); |
| 574 | |
Behdad Esfahbod | cc1c4fd | 2018-09-10 16:36:05 +0200 | [diff] [blame] | 575 | c->replace_glyph (alternates[alt_index - 1]); |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 576 | |
| 577 | return_trace (true); |
| 578 | } |
| 579 | |
Ebrahim Byagowi | d3c1697 | 2020-06-18 08:37:21 +0430 | [diff] [blame] | 580 | unsigned |
Behdad Esfahbod | bedf417 | 2020-06-18 15:49:01 -0700 | [diff] [blame] | 581 | get_alternates (unsigned start_offset, |
| 582 | unsigned *alternate_count /* IN/OUT. May be NULL. */, |
| 583 | hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const |
Ebrahim Byagowi | d3c1697 | 2020-06-18 08:37:21 +0430 | [diff] [blame] | 584 | { |
Behdad Esfahbod | bedf417 | 2020-06-18 15:49:01 -0700 | [diff] [blame] | 585 | if (alternates.len && alternate_count) |
Ebrahim Byagowi | d3c1697 | 2020-06-18 08:37:21 +0430 | [diff] [blame] | 586 | { |
| 587 | + alternates.sub_array (start_offset, alternate_count) |
| 588 | | hb_sink (hb_array (alternate_glyphs, *alternate_count)) |
| 589 | ; |
| 590 | } |
| 591 | return alternates.len; |
| 592 | } |
| 593 | |
Behdad Esfahbod | 2dbdec6 | 2019-05-31 15:38:11 -0700 | [diff] [blame] | 594 | template <typename Iterator, |
| 595 | hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))> |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 596 | bool serialize (hb_serialize_context_t *c, |
Behdad Esfahbod | 2dbdec6 | 2019-05-31 15:38:11 -0700 | [diff] [blame] | 597 | Iterator alts) |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 598 | { |
| 599 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | 815cde9 | 2019-01-07 18:33:04 -0500 | [diff] [blame] | 600 | return_trace (alternates.serialize (c, alts)); |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 601 | } |
| 602 | |
Behdad Esfahbod | dc9222b | 2019-08-28 15:38:46 -0700 | [diff] [blame] | 603 | bool subset (hb_subset_context_t *c) const |
| 604 | { |
| 605 | TRACE_SUBSET (this); |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 606 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Behdad Esfahbod | dc9222b | 2019-08-28 15:38:46 -0700 | [diff] [blame] | 607 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 608 | |
| 609 | auto it = |
| 610 | + hb_iter (alternates) |
| 611 | | hb_filter (glyphset) |
| 612 | | hb_map (glyph_map) |
| 613 | ; |
| 614 | |
| 615 | auto *out = c->serializer->start_embed (*this); |
| 616 | return_trace (out->serialize (c->serializer, it) && |
| 617 | out->alternates); |
| 618 | } |
| 619 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 620 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 621 | { |
| 622 | TRACE_SANITIZE (this); |
| 623 | return_trace (alternates.sanitize (c)); |
| 624 | } |
| 625 | |
| 626 | protected: |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 627 | Array16Of<HBGlyphID16> |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 628 | alternates; /* Array of alternate GlyphIDs--in |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 629 | * arbitrary order */ |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 630 | public: |
| 631 | DEFINE_SIZE_ARRAY (2, alternates); |
| 632 | }; |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 633 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 634 | struct AlternateSubstFormat1 |
| 635 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 636 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 637 | { return (this+coverage).intersects (glyphs); } |
| 638 | |
Qunxin Liu | b4fc593 | 2020-12-09 10:44:18 -0800 | [diff] [blame] | 639 | bool may_have_non_1to1 () const |
| 640 | { return false; } |
| 641 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 642 | void closure (hb_closure_context_t *c) const |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 643 | { |
Behdad Esfahbod | 7514a49 | 2019-02-14 13:16:33 -0800 | [diff] [blame] | 644 | + hb_zip (this+coverage, alternateSet) |
Qunxin Liu | b8a58a0 | 2021-01-10 15:50:04 -0800 | [diff] [blame] | 645 | | hb_filter (c->parent_active_glyphs (), hb_first) |
Behdad Esfahbod | 7514a49 | 2019-02-14 13:16:33 -0800 | [diff] [blame] | 646 | | hb_map (hb_second) |
Behdad Esfahbod | 2376867 | 2019-05-15 21:57:26 -0700 | [diff] [blame] | 647 | | hb_map (hb_add (this)) |
| 648 | | hb_apply ([c] (const AlternateSet &_) { _.closure (c); }) |
Behdad Esfahbod | 7514a49 | 2019-02-14 13:16:33 -0800 | [diff] [blame] | 649 | ; |
Qunxin Liu | b4fc593 | 2020-12-09 10:44:18 -0800 | [diff] [blame] | 650 | |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 651 | } |
| 652 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 653 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
| 654 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 655 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 656 | { |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 657 | if (unlikely (!(this+coverage).collect_coverage (c->input))) return; |
Behdad Esfahbod | 7514a49 | 2019-02-14 13:16:33 -0800 | [diff] [blame] | 658 | + hb_zip (this+coverage, alternateSet) |
| 659 | | hb_map (hb_second) |
Behdad Esfahbod | 2376867 | 2019-05-15 21:57:26 -0700 | [diff] [blame] | 660 | | hb_map (hb_add (this)) |
| 661 | | hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); }) |
Behdad Esfahbod | 7514a49 | 2019-02-14 13:16:33 -0800 | [diff] [blame] | 662 | ; |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 663 | } |
| 664 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 665 | const Coverage &get_coverage () const { return this+coverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 666 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 667 | bool would_apply (hb_would_apply_context_t *c) const |
Behdad Esfahbod | 90b60bd | 2019-03-29 22:12:42 -0700 | [diff] [blame] | 668 | { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; } |
Behdad Esfahbod | 2005fa5 | 2012-11-22 14:38:10 -0500 | [diff] [blame] | 669 | |
Ebrahim Byagowi | d3c1697 | 2020-06-18 08:37:21 +0430 | [diff] [blame] | 670 | unsigned |
Behdad Esfahbod | b2a1acc | 2020-06-18 16:41:31 -0700 | [diff] [blame] | 671 | get_glyph_alternates (hb_codepoint_t gid, |
| 672 | unsigned start_offset, |
| 673 | unsigned *alternate_count /* IN/OUT. May be NULL. */, |
| 674 | hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const |
| 675 | { return (this+alternateSet[(this+coverage).get_coverage (gid)]) |
| 676 | .get_alternates (start_offset, alternate_count, alternate_glyphs); } |
Ebrahim Byagowi | 1348a2c | 2020-06-16 21:05:16 -0400 | [diff] [blame] | 677 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 678 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 679 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 680 | TRACE_APPLY (this); |
Behdad Esfahbod | 52886ca | 2009-04-16 14:19:42 -0400 | [diff] [blame] | 681 | |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 682 | unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 683 | if (likely (index == NOT_COVERED)) return_trace (false); |
Behdad Esfahbod | aa3d7ad | 2009-05-17 23:17:56 -0400 | [diff] [blame] | 684 | |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 685 | return_trace ((this+alternateSet[index]).apply (c)); |
Behdad Esfahbod | 52886ca | 2009-04-16 14:19:42 -0400 | [diff] [blame] | 686 | } |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 687 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 688 | bool serialize (hb_serialize_context_t *c, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 689 | hb_sorted_array_t<const HBGlyphID16> glyphs, |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 690 | hb_array_t<const unsigned int> alternate_len_list, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 691 | hb_array_t<const HBGlyphID16> alternate_glyphs_list) |
Behdad Esfahbod | 2941683 | 2012-09-03 23:31:14 -0400 | [diff] [blame] | 692 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 693 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | f0a1892 | 2021-07-28 17:36:22 -0600 | [diff] [blame] | 694 | if (unlikely (!c->extend_min (this))) return_trace (false); |
Behdad Esfahbod | 474a120 | 2018-12-21 18:46:51 -0500 | [diff] [blame] | 695 | if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false); |
| 696 | for (unsigned int i = 0; i < glyphs.length; i++) |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 697 | { |
| 698 | unsigned int alternate_len = alternate_len_list[i]; |
Garret Rieger | 5ba46ed | 2021-06-11 13:34:00 -0700 | [diff] [blame] | 699 | if (unlikely (!alternateSet[i] |
| 700 | .serialize_serialize (c, alternate_glyphs_list.sub_array (0, alternate_len)))) |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 701 | return_trace (false); |
| 702 | alternate_glyphs_list += alternate_len; |
| 703 | } |
Garret Rieger | 5ba46ed | 2021-06-11 13:34:00 -0700 | [diff] [blame] | 704 | return_trace (coverage.serialize_serialize (c, glyphs)); |
Behdad Esfahbod | 2941683 | 2012-09-03 23:31:14 -0400 | [diff] [blame] | 705 | } |
| 706 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 707 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 708 | { |
| 709 | TRACE_SUBSET (this); |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 710 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Behdad Esfahbod | dc9222b | 2019-08-28 15:38:46 -0700 | [diff] [blame] | 711 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 712 | |
| 713 | auto *out = c->serializer->start_embed (*this); |
| 714 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
| 715 | out->format = format; |
| 716 | |
| 717 | hb_sorted_vector_t<hb_codepoint_t> new_coverage; |
| 718 | + hb_zip (this+coverage, alternateSet) |
| 719 | | hb_filter (glyphset, hb_first) |
ariza | 188a0a4 | 2020-03-07 11:02:36 -0800 | [diff] [blame] | 720 | | hb_filter (subset_offset_array (c, out->alternateSet, this), hb_second) |
Behdad Esfahbod | dc9222b | 2019-08-28 15:38:46 -0700 | [diff] [blame] | 721 | | hb_map (hb_first) |
| 722 | | hb_map (glyph_map) |
Ebrahim Byagowi | 4990296 | 2019-08-29 15:09:39 +0430 | [diff] [blame] | 723 | | hb_sink (new_coverage) |
Behdad Esfahbod | dc9222b | 2019-08-28 15:38:46 -0700 | [diff] [blame] | 724 | ; |
Garret Rieger | 5ba46ed | 2021-06-11 13:34:00 -0700 | [diff] [blame] | 725 | out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); |
Behdad Esfahbod | dc9222b | 2019-08-28 15:38:46 -0700 | [diff] [blame] | 726 | return_trace (bool (new_coverage)); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 727 | } |
| 728 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 729 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 730 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 731 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 732 | return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this)); |
Behdad Esfahbod | 70de50c | 2009-08-04 00:58:28 -0400 | [diff] [blame] | 733 | } |
| 734 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 735 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 736 | HBUINT16 format; /* Format identifier--format = 1 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 737 | Offset16To<Coverage> |
Behdad Esfahbod | 238c855 | 2009-05-17 00:22:37 -0400 | [diff] [blame] | 738 | coverage; /* Offset to Coverage table--from |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 739 | * beginning of Substitution table */ |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 740 | Array16OfOffset16To<AlternateSet> |
Behdad Esfahbod | c9a7cbe | 2009-05-17 01:22:51 -0400 | [diff] [blame] | 741 | alternateSet; /* Array of AlternateSet tables |
| 742 | * ordered by Coverage Index */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 743 | public: |
Behdad Esfahbod | 0eb9fc6 | 2010-05-10 19:01:17 -0400 | [diff] [blame] | 744 | DEFINE_SIZE_ARRAY (6, alternateSet); |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 745 | }; |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 746 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 747 | struct AlternateSubst |
| 748 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 749 | bool serialize (hb_serialize_context_t *c, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 750 | hb_sorted_array_t<const HBGlyphID16> glyphs, |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 751 | hb_array_t<const unsigned int> alternate_len_list, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 752 | hb_array_t<const HBGlyphID16> alternate_glyphs_list) |
Behdad Esfahbod | 2941683 | 2012-09-03 23:31:14 -0400 | [diff] [blame] | 753 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 754 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 755 | if (unlikely (!c->extend_min (u.format))) return_trace (false); |
Behdad Esfahbod | 2941683 | 2012-09-03 23:31:14 -0400 | [diff] [blame] | 756 | unsigned int format = 1; |
Behdad Esfahbod | b986c6a | 2019-03-29 20:17:46 -0700 | [diff] [blame] | 757 | u.format = format; |
Behdad Esfahbod | 2941683 | 2012-09-03 23:31:14 -0400 | [diff] [blame] | 758 | switch (u.format) { |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 759 | case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 760 | default:return_trace (false); |
Behdad Esfahbod | 2941683 | 2012-09-03 23:31:14 -0400 | [diff] [blame] | 761 | } |
| 762 | } |
| 763 | |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 764 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 765 | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 766 | { |
Behdad Esfahbod | 00f6a8e | 2014-12-12 20:36:49 -0800 | [diff] [blame] | 767 | TRACE_DISPATCH (this, u.format); |
Behdad Esfahbod | f396fbb | 2015-10-09 12:25:55 -0400 | [diff] [blame] | 768 | if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 769 | switch (u.format) { |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 770 | case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 771 | default:return_trace (c->default_return_value ()); |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 772 | } |
| 773 | } |
| 774 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 775 | protected: |
Behdad Esfahbod | 52886ca | 2009-04-16 14:19:42 -0400 | [diff] [blame] | 776 | union { |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 777 | HBUINT16 format; /* Format identifier */ |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 778 | AlternateSubstFormat1 format1; |
Behdad Esfahbod | 52886ca | 2009-04-16 14:19:42 -0400 | [diff] [blame] | 779 | } u; |
| 780 | }; |
Behdad Esfahbod | 52886ca | 2009-04-16 14:19:42 -0400 | [diff] [blame] | 781 | |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 782 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 783 | struct Ligature |
| 784 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 785 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 23681b6 | 2019-08-28 15:30:37 -0700 | [diff] [blame] | 786 | { return hb_all (component, glyphs); } |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 787 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 788 | void closure (hb_closure_context_t *c) const |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 789 | { |
Behdad Esfahbod | 418e9d0 | 2019-03-29 21:57:26 -0700 | [diff] [blame] | 790 | if (!intersects (c->glyphs)) return; |
Behdad Esfahbod | ede1a71 | 2019-01-09 10:45:53 -0800 | [diff] [blame] | 791 | c->output->add (ligGlyph); |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 792 | } |
| 793 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 794 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 795 | { |
Behdad Esfahbod | b8c642c | 2019-08-28 15:06:45 -0700 | [diff] [blame] | 796 | c->input->add_array (component.arrayZ, component.get_length ()); |
Behdad Esfahbod | 8303593 | 2012-12-04 17:08:41 -0500 | [diff] [blame] | 797 | c->output->add (ligGlyph); |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 798 | } |
| 799 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 800 | bool would_apply (hb_would_apply_context_t *c) const |
Behdad Esfahbod | 3660894 | 2012-04-19 22:21:38 -0400 | [diff] [blame] | 801 | { |
Behdad Esfahbod | effc7ce | 2018-09-13 20:21:54 +0200 | [diff] [blame] | 802 | if (c->len != component.lenP1) |
Behdad Esfahbod | 90b60bd | 2019-03-29 22:12:42 -0700 | [diff] [blame] | 803 | return false; |
Behdad Esfahbod | 472f229 | 2012-08-07 22:25:24 -0400 | [diff] [blame] | 804 | |
| 805 | for (unsigned int i = 1; i < c->len; i++) |
| 806 | if (likely (c->glyphs[i] != component[i])) |
Behdad Esfahbod | 90b60bd | 2019-03-29 22:12:42 -0700 | [diff] [blame] | 807 | return false; |
Behdad Esfahbod | 472f229 | 2012-08-07 22:25:24 -0400 | [diff] [blame] | 808 | |
Behdad Esfahbod | 90b60bd | 2019-03-29 22:12:42 -0700 | [diff] [blame] | 809 | return true; |
Behdad Esfahbod | 3660894 | 2012-04-19 22:21:38 -0400 | [diff] [blame] | 810 | } |
| 811 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 812 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 813 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 814 | TRACE_APPLY (this); |
Behdad Esfahbod | effc7ce | 2018-09-13 20:21:54 +0200 | [diff] [blame] | 815 | unsigned int count = component.lenP1; |
Behdad Esfahbod | aae6945 | 2014-06-05 18:54:44 -0400 | [diff] [blame] | 816 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 817 | if (unlikely (!count)) return_trace (false); |
Behdad Esfahbod | 4ab9731 | 2012-01-16 22:05:08 -0500 | [diff] [blame] | 818 | |
Behdad Esfahbod | b5be231 | 2014-06-05 19:00:22 -0400 | [diff] [blame] | 819 | /* Special-case to make it in-place and not consider this |
| 820 | * as a "ligated" substitution. */ |
| 821 | if (unlikely (count == 1)) |
| 822 | { |
| 823 | c->replace_glyph (ligGlyph); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 824 | return_trace (true); |
Behdad Esfahbod | b5be231 | 2014-06-05 19:00:22 -0400 | [diff] [blame] | 825 | } |
| 826 | |
Behdad Esfahbod | c779d82 | 2012-11-23 14:07:24 -0500 | [diff] [blame] | 827 | unsigned int total_component_count = 0; |
Behdad Esfahbod | bb3899a | 2009-05-05 13:25:13 -0400 | [diff] [blame] | 828 | |
Behdad Esfahbod | e714fe6 | 2013-10-17 13:49:51 +0200 | [diff] [blame] | 829 | unsigned int match_length = 0; |
Behdad Esfahbod | 5ba4504 | 2015-11-02 15:43:08 -0800 | [diff] [blame] | 830 | unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; |
Behdad Esfahbod | e714fe6 | 2013-10-17 13:49:51 +0200 | [diff] [blame] | 831 | |
Behdad Esfahbod | 191fa88 | 2012-08-28 22:58:55 -0400 | [diff] [blame] | 832 | if (likely (!match_input (c, count, |
| 833 | &component[1], |
| 834 | match_glyph, |
Behdad Esfahbod | dbdbfe3 | 2017-10-15 12:11:08 +0200 | [diff] [blame] | 835 | nullptr, |
Behdad Esfahbod | e714fe6 | 2013-10-17 13:49:51 +0200 | [diff] [blame] | 836 | &match_length, |
| 837 | match_positions, |
Behdad Esfahbod | 191fa88 | 2012-08-28 22:58:55 -0400 | [diff] [blame] | 838 | &total_component_count))) |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 839 | return_trace (false); |
Behdad Esfahbod | 98370e8 | 2010-10-27 17:39:01 -0400 | [diff] [blame] | 840 | |
Behdad Esfahbod | a177d02 | 2012-08-28 23:18:22 -0400 | [diff] [blame] | 841 | ligate_input (c, |
| 842 | count, |
Behdad Esfahbod | e714fe6 | 2013-10-17 13:49:51 +0200 | [diff] [blame] | 843 | match_positions, |
| 844 | match_length, |
Behdad Esfahbod | 607feb7 | 2013-02-14 07:43:13 -0500 | [diff] [blame] | 845 | ligGlyph, |
Behdad Esfahbod | a177d02 | 2012-08-28 23:18:22 -0400 | [diff] [blame] | 846 | total_component_count); |
Behdad Esfahbod | bb3899a | 2009-05-05 13:25:13 -0400 | [diff] [blame] | 847 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 848 | return_trace (true); |
Behdad Esfahbod | bb3899a | 2009-05-05 13:25:13 -0400 | [diff] [blame] | 849 | } |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 850 | |
Behdad Esfahbod | 2dbdec6 | 2019-05-31 15:38:11 -0700 | [diff] [blame] | 851 | template <typename Iterator, |
| 852 | hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))> |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 853 | bool serialize (hb_serialize_context_t *c, |
Behdad Esfahbod | bc5ef76 | 2019-08-28 14:51:28 -0700 | [diff] [blame] | 854 | hb_codepoint_t ligature, |
Behdad Esfahbod | 2dbdec6 | 2019-05-31 15:38:11 -0700 | [diff] [blame] | 855 | Iterator components /* Starting from second */) |
Behdad Esfahbod | a930c68 | 2012-09-04 18:17:57 -0400 | [diff] [blame] | 856 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 857 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | f0a1892 | 2021-07-28 17:36:22 -0600 | [diff] [blame] | 858 | if (unlikely (!c->extend_min (this))) return_trace (false); |
Behdad Esfahbod | fabd311 | 2012-09-05 22:19:28 -0400 | [diff] [blame] | 859 | ligGlyph = ligature; |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 860 | if (unlikely (!component.serialize (c, components))) return_trace (false); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 861 | return_trace (true); |
Behdad Esfahbod | a930c68 | 2012-09-04 18:17:57 -0400 | [diff] [blame] | 862 | } |
| 863 | |
Behdad Esfahbod | bc5ef76 | 2019-08-28 14:51:28 -0700 | [diff] [blame] | 864 | bool subset (hb_subset_context_t *c) const |
| 865 | { |
| 866 | TRACE_SUBSET (this); |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 867 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Behdad Esfahbod | bc5ef76 | 2019-08-28 14:51:28 -0700 | [diff] [blame] | 868 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 869 | |
Behdad Esfahbod | 23681b6 | 2019-08-28 15:30:37 -0700 | [diff] [blame] | 870 | if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false); |
Behdad Esfahbod | bc5ef76 | 2019-08-28 14:51:28 -0700 | [diff] [blame] | 871 | |
| 872 | auto it = |
| 873 | + hb_iter (component) |
| 874 | | hb_map (glyph_map) |
| 875 | ; |
| 876 | |
| 877 | auto *out = c->serializer->start_embed (*this); |
Behdad Esfahbod | dc9222b | 2019-08-28 15:38:46 -0700 | [diff] [blame] | 878 | return_trace (out->serialize (c->serializer, |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 879 | glyph_map[ligGlyph], |
| 880 | it)); |
Behdad Esfahbod | bc5ef76 | 2019-08-28 14:51:28 -0700 | [diff] [blame] | 881 | } |
| 882 | |
Behdad Esfahbod | 70de50c | 2009-08-04 00:58:28 -0400 | [diff] [blame] | 883 | public: |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 884 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 885 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 886 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 887 | return_trace (ligGlyph.sanitize (c) && component.sanitize (c)); |
Behdad Esfahbod | 70de50c | 2009-08-04 00:58:28 -0400 | [diff] [blame] | 888 | } |
| 889 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 890 | protected: |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 891 | HBGlyphID16 ligGlyph; /* GlyphID of ligature to substitute */ |
| 892 | HeadlessArrayOf<HBGlyphID16> |
Behdad Esfahbod | e8cbaaf | 2009-05-18 02:03:58 -0400 | [diff] [blame] | 893 | component; /* Array of component GlyphIDs--start |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 894 | * with the second component--ordered |
| 895 | * in writing direction */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 896 | public: |
Behdad Esfahbod | 0eb9fc6 | 2010-05-10 19:01:17 -0400 | [diff] [blame] | 897 | DEFINE_SIZE_ARRAY (4, component); |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 898 | }; |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 899 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 900 | struct LigatureSet |
| 901 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 902 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 903 | { |
Behdad Esfahbod | 4d28267 | 2019-03-29 22:04:15 -0700 | [diff] [blame] | 904 | return |
| 905 | + hb_iter (ligature) |
Behdad Esfahbod | 2376867 | 2019-05-15 21:57:26 -0700 | [diff] [blame] | 906 | | hb_map (hb_add (this)) |
| 907 | | hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); }) |
Behdad Esfahbod | 4d28267 | 2019-03-29 22:04:15 -0700 | [diff] [blame] | 908 | | hb_any |
| 909 | ; |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 910 | } |
| 911 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 912 | void closure (hb_closure_context_t *c) const |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 913 | { |
Behdad Esfahbod | 4d28267 | 2019-03-29 22:04:15 -0700 | [diff] [blame] | 914 | + hb_iter (ligature) |
Behdad Esfahbod | 2376867 | 2019-05-15 21:57:26 -0700 | [diff] [blame] | 915 | | hb_map (hb_add (this)) |
| 916 | | hb_apply ([c] (const Ligature &_) { _.closure (c); }) |
Behdad Esfahbod | 4d28267 | 2019-03-29 22:04:15 -0700 | [diff] [blame] | 917 | ; |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 918 | } |
| 919 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 920 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 921 | { |
Behdad Esfahbod | 4d28267 | 2019-03-29 22:04:15 -0700 | [diff] [blame] | 922 | + hb_iter (ligature) |
Behdad Esfahbod | 2376867 | 2019-05-15 21:57:26 -0700 | [diff] [blame] | 923 | | hb_map (hb_add (this)) |
| 924 | | hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); }) |
Behdad Esfahbod | 4d28267 | 2019-03-29 22:04:15 -0700 | [diff] [blame] | 925 | ; |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 926 | } |
| 927 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 928 | bool would_apply (hb_would_apply_context_t *c) const |
Behdad Esfahbod | 3660894 | 2012-04-19 22:21:38 -0400 | [diff] [blame] | 929 | { |
Behdad Esfahbod | 688069b | 2019-03-29 22:17:31 -0700 | [diff] [blame] | 930 | return |
| 931 | + hb_iter (ligature) |
Behdad Esfahbod | 2376867 | 2019-05-15 21:57:26 -0700 | [diff] [blame] | 932 | | hb_map (hb_add (this)) |
| 933 | | hb_map ([c] (const Ligature &_) { return _.would_apply (c); }) |
Behdad Esfahbod | 688069b | 2019-03-29 22:17:31 -0700 | [diff] [blame] | 934 | | hb_any |
| 935 | ; |
Behdad Esfahbod | 3660894 | 2012-04-19 22:21:38 -0400 | [diff] [blame] | 936 | } |
| 937 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 938 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 939 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 940 | TRACE_APPLY (this); |
Behdad Esfahbod | c9a7cbe | 2009-05-17 01:22:51 -0400 | [diff] [blame] | 941 | unsigned int num_ligs = ligature.len; |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 942 | for (unsigned int i = 0; i < num_ligs; i++) |
| 943 | { |
Behdad Esfahbod | c9a7cbe | 2009-05-17 01:22:51 -0400 | [diff] [blame] | 944 | const Ligature &lig = this+ligature[i]; |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 945 | if (lig.apply (c)) return_trace (true); |
Behdad Esfahbod | bb3899a | 2009-05-05 13:25:13 -0400 | [diff] [blame] | 946 | } |
| 947 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 948 | return_trace (false); |
Behdad Esfahbod | bb3899a | 2009-05-05 13:25:13 -0400 | [diff] [blame] | 949 | } |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 950 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 951 | bool serialize (hb_serialize_context_t *c, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 952 | hb_array_t<const HBGlyphID16> ligatures, |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 953 | hb_array_t<const unsigned int> component_count_list, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 954 | hb_array_t<const HBGlyphID16> &component_list /* Starting from second for each ligature */) |
Behdad Esfahbod | a930c68 | 2012-09-04 18:17:57 -0400 | [diff] [blame] | 955 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 956 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | f0a1892 | 2021-07-28 17:36:22 -0600 | [diff] [blame] | 957 | if (unlikely (!c->extend_min (this))) return_trace (false); |
Behdad Esfahbod | 474a120 | 2018-12-21 18:46:51 -0500 | [diff] [blame] | 958 | if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false); |
| 959 | for (unsigned int i = 0; i < ligatures.length; i++) |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 960 | { |
Behdad Esfahbod | 41248cc | 2019-05-07 20:54:31 -0700 | [diff] [blame] | 961 | unsigned int component_count = (unsigned) hb_max ((int) component_count_list[i] - 1, 0); |
Garret Rieger | 5ba46ed | 2021-06-11 13:34:00 -0700 | [diff] [blame] | 962 | if (unlikely (!ligature[i].serialize_serialize (c, |
| 963 | ligatures[i], |
| 964 | component_list.sub_array (0, component_count)))) |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 965 | return_trace (false); |
| 966 | component_list += component_count; |
| 967 | } |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 968 | return_trace (true); |
Behdad Esfahbod | a930c68 | 2012-09-04 18:17:57 -0400 | [diff] [blame] | 969 | } |
| 970 | |
Behdad Esfahbod | bc5ef76 | 2019-08-28 14:51:28 -0700 | [diff] [blame] | 971 | bool subset (hb_subset_context_t *c) const |
| 972 | { |
| 973 | TRACE_SUBSET (this); |
| 974 | auto *out = c->serializer->start_embed (*this); |
| 975 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
| 976 | |
| 977 | + hb_iter (ligature) |
ariza | 188a0a4 | 2020-03-07 11:02:36 -0800 | [diff] [blame] | 978 | | hb_filter (subset_offset_array (c, out->ligature, this)) |
Ebrahim Byagowi | 4990296 | 2019-08-29 15:09:39 +0430 | [diff] [blame] | 979 | | hb_drain |
Behdad Esfahbod | bc5ef76 | 2019-08-28 14:51:28 -0700 | [diff] [blame] | 980 | ; |
| 981 | return_trace (bool (out->ligature)); |
| 982 | } |
| 983 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 984 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 985 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 986 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 987 | return_trace (ligature.sanitize (c, this)); |
Behdad Esfahbod | 70de50c | 2009-08-04 00:58:28 -0400 | [diff] [blame] | 988 | } |
| 989 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 990 | protected: |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 991 | Array16OfOffset16To<Ligature> |
Behdad Esfahbod | c9a7cbe | 2009-05-17 01:22:51 -0400 | [diff] [blame] | 992 | ligature; /* Array LigatureSet tables |
| 993 | * ordered by preference */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 994 | public: |
Behdad Esfahbod | 0eb9fc6 | 2010-05-10 19:01:17 -0400 | [diff] [blame] | 995 | DEFINE_SIZE_ARRAY (2, ligature); |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 996 | }; |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 997 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 998 | struct LigatureSubstFormat1 |
| 999 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1000 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1001 | { |
Behdad Esfahbod | bcab098 | 2019-03-29 21:49:18 -0700 | [diff] [blame] | 1002 | return |
| 1003 | + hb_zip (this+coverage, ligatureSet) |
| 1004 | | hb_filter (*glyphs, hb_first) |
| 1005 | | hb_map (hb_second) |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 1006 | | hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_) |
Behdad Esfahbod | bcab098 | 2019-03-29 21:49:18 -0700 | [diff] [blame] | 1007 | { return (this+_).intersects (glyphs); }) |
| 1008 | | hb_any |
| 1009 | ; |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1010 | } |
| 1011 | |
Qunxin Liu | b4fc593 | 2020-12-09 10:44:18 -0800 | [diff] [blame] | 1012 | bool may_have_non_1to1 () const |
| 1013 | { return true; } |
| 1014 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1015 | void closure (hb_closure_context_t *c) const |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 1016 | { |
Behdad Esfahbod | f4cfd6b | 2019-02-14 13:45:52 -0800 | [diff] [blame] | 1017 | + hb_zip (this+coverage, ligatureSet) |
Qunxin Liu | b8a58a0 | 2021-01-10 15:50:04 -0800 | [diff] [blame] | 1018 | | hb_filter (c->parent_active_glyphs (), hb_first) |
Behdad Esfahbod | f4cfd6b | 2019-02-14 13:45:52 -0800 | [diff] [blame] | 1019 | | hb_map (hb_second) |
Behdad Esfahbod | 2376867 | 2019-05-15 21:57:26 -0700 | [diff] [blame] | 1020 | | hb_map (hb_add (this)) |
| 1021 | | hb_apply ([c] (const LigatureSet &_) { _.closure (c); }) |
Behdad Esfahbod | f4cfd6b | 2019-02-14 13:45:52 -0800 | [diff] [blame] | 1022 | ; |
Qunxin Liu | b4fc593 | 2020-12-09 10:44:18 -0800 | [diff] [blame] | 1023 | |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 1024 | } |
| 1025 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 1026 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
| 1027 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1028 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1029 | { |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 1030 | if (unlikely (!(this+coverage).collect_coverage (c->input))) return; |
Behdad Esfahbod | f1dad91 | 2019-03-29 21:17:08 -0700 | [diff] [blame] | 1031 | |
Behdad Esfahbod | f4cfd6b | 2019-02-14 13:45:52 -0800 | [diff] [blame] | 1032 | + hb_zip (this+coverage, ligatureSet) |
| 1033 | | hb_map (hb_second) |
Behdad Esfahbod | 2376867 | 2019-05-15 21:57:26 -0700 | [diff] [blame] | 1034 | | hb_map (hb_add (this)) |
| 1035 | | hb_apply ([c] (const LigatureSet &_) { _.collect_glyphs (c); }) |
Behdad Esfahbod | f4cfd6b | 2019-02-14 13:45:52 -0800 | [diff] [blame] | 1036 | ; |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1037 | } |
| 1038 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 1039 | const Coverage &get_coverage () const { return this+coverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1040 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1041 | bool would_apply (hb_would_apply_context_t *c) const |
Behdad Esfahbod | 3660894 | 2012-04-19 22:21:38 -0400 | [diff] [blame] | 1042 | { |
Behdad Esfahbod | b67881b | 2012-11-24 19:13:55 -0500 | [diff] [blame] | 1043 | unsigned int index = (this+coverage).get_coverage (c->glyphs[0]); |
Behdad Esfahbod | 90b60bd | 2019-03-29 22:12:42 -0700 | [diff] [blame] | 1044 | if (likely (index == NOT_COVERED)) return false; |
Behdad Esfahbod | 2005fa5 | 2012-11-22 14:38:10 -0500 | [diff] [blame] | 1045 | |
| 1046 | const LigatureSet &lig_set = this+ligatureSet[index]; |
Behdad Esfahbod | 90b60bd | 2019-03-29 22:12:42 -0700 | [diff] [blame] | 1047 | return lig_set.would_apply (c); |
Behdad Esfahbod | 3660894 | 2012-04-19 22:21:38 -0400 | [diff] [blame] | 1048 | } |
| 1049 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1050 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1051 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1052 | TRACE_APPLY (this); |
Behdad Esfahbod | a84e71a | 2009-04-16 16:53:40 -0400 | [diff] [blame] | 1053 | |
Ebrahim Byagowi | 0750456 | 2020-02-21 13:05:44 +0330 | [diff] [blame] | 1054 | unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1055 | if (likely (index == NOT_COVERED)) return_trace (false); |
Behdad Esfahbod | aa3d7ad | 2009-05-17 23:17:56 -0400 | [diff] [blame] | 1056 | |
Behdad Esfahbod | c9a7cbe | 2009-05-17 01:22:51 -0400 | [diff] [blame] | 1057 | const LigatureSet &lig_set = this+ligatureSet[index]; |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1058 | return_trace (lig_set.apply (c)); |
Behdad Esfahbod | a84e71a | 2009-04-16 16:53:40 -0400 | [diff] [blame] | 1059 | } |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 1060 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1061 | bool serialize (hb_serialize_context_t *c, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1062 | hb_sorted_array_t<const HBGlyphID16> first_glyphs, |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 1063 | hb_array_t<const unsigned int> ligature_per_first_glyph_count_list, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1064 | hb_array_t<const HBGlyphID16> ligatures_list, |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 1065 | hb_array_t<const unsigned int> component_count_list, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1066 | hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */) |
Behdad Esfahbod | a930c68 | 2012-09-04 18:17:57 -0400 | [diff] [blame] | 1067 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1068 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | f0a1892 | 2021-07-28 17:36:22 -0600 | [diff] [blame] | 1069 | if (unlikely (!c->extend_min (this))) return_trace (false); |
Behdad Esfahbod | 474a120 | 2018-12-21 18:46:51 -0500 | [diff] [blame] | 1070 | if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false); |
| 1071 | for (unsigned int i = 0; i < first_glyphs.length; i++) |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 1072 | { |
| 1073 | unsigned int ligature_count = ligature_per_first_glyph_count_list[i]; |
Garret Rieger | 5ba46ed | 2021-06-11 13:34:00 -0700 | [diff] [blame] | 1074 | if (unlikely (!ligatureSet[i] |
| 1075 | .serialize_serialize (c, |
| 1076 | ligatures_list.sub_array (0, ligature_count), |
| 1077 | component_count_list.sub_array (0, ligature_count), |
| 1078 | component_list))) return_trace (false); |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 1079 | ligatures_list += ligature_count; |
| 1080 | component_count_list += ligature_count; |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 1081 | } |
Garret Rieger | 5ba46ed | 2021-06-11 13:34:00 -0700 | [diff] [blame] | 1082 | return_trace (coverage.serialize_serialize (c, first_glyphs)); |
Behdad Esfahbod | a930c68 | 2012-09-04 18:17:57 -0400 | [diff] [blame] | 1083 | } |
| 1084 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1085 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 1086 | { |
| 1087 | TRACE_SUBSET (this); |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 1088 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Behdad Esfahbod | bc5ef76 | 2019-08-28 14:51:28 -0700 | [diff] [blame] | 1089 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 1090 | |
| 1091 | auto *out = c->serializer->start_embed (*this); |
| 1092 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
| 1093 | out->format = format; |
| 1094 | |
| 1095 | hb_sorted_vector_t<hb_codepoint_t> new_coverage; |
| 1096 | + hb_zip (this+coverage, ligatureSet) |
| 1097 | | hb_filter (glyphset, hb_first) |
ariza | 188a0a4 | 2020-03-07 11:02:36 -0800 | [diff] [blame] | 1098 | | hb_filter (subset_offset_array (c, out->ligatureSet, this), hb_second) |
Behdad Esfahbod | bc5ef76 | 2019-08-28 14:51:28 -0700 | [diff] [blame] | 1099 | | hb_map (hb_first) |
| 1100 | | hb_map (glyph_map) |
Ebrahim Byagowi | 4990296 | 2019-08-29 15:09:39 +0430 | [diff] [blame] | 1101 | | hb_sink (new_coverage) |
Behdad Esfahbod | bc5ef76 | 2019-08-28 14:51:28 -0700 | [diff] [blame] | 1102 | ; |
Garret Rieger | 5ba46ed | 2021-06-11 13:34:00 -0700 | [diff] [blame] | 1103 | out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); |
Behdad Esfahbod | bc5ef76 | 2019-08-28 14:51:28 -0700 | [diff] [blame] | 1104 | return_trace (bool (new_coverage)); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 1105 | } |
| 1106 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1107 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 1108 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1109 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1110 | return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this)); |
Behdad Esfahbod | 70de50c | 2009-08-04 00:58:28 -0400 | [diff] [blame] | 1111 | } |
| 1112 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1113 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1114 | HBUINT16 format; /* Format identifier--format = 1 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 1115 | Offset16To<Coverage> |
Behdad Esfahbod | 238c855 | 2009-05-17 00:22:37 -0400 | [diff] [blame] | 1116 | coverage; /* Offset to Coverage table--from |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 1117 | * beginning of Substitution table */ |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 1118 | Array16OfOffset16To<LigatureSet> |
Behdad Esfahbod | c9a7cbe | 2009-05-17 01:22:51 -0400 | [diff] [blame] | 1119 | ligatureSet; /* Array LigatureSet tables |
| 1120 | * ordered by Coverage Index */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 1121 | public: |
Behdad Esfahbod | 0eb9fc6 | 2010-05-10 19:01:17 -0400 | [diff] [blame] | 1122 | DEFINE_SIZE_ARRAY (6, ligatureSet); |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 1123 | }; |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 1124 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1125 | struct LigatureSubst |
| 1126 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1127 | bool serialize (hb_serialize_context_t *c, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1128 | hb_sorted_array_t<const HBGlyphID16> first_glyphs, |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 1129 | hb_array_t<const unsigned int> ligature_per_first_glyph_count_list, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1130 | hb_array_t<const HBGlyphID16> ligatures_list, |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 1131 | hb_array_t<const unsigned int> component_count_list, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1132 | hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */) |
Behdad Esfahbod | a930c68 | 2012-09-04 18:17:57 -0400 | [diff] [blame] | 1133 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1134 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1135 | if (unlikely (!c->extend_min (u.format))) return_trace (false); |
Behdad Esfahbod | a930c68 | 2012-09-04 18:17:57 -0400 | [diff] [blame] | 1136 | unsigned int format = 1; |
Behdad Esfahbod | b986c6a | 2019-03-29 20:17:46 -0700 | [diff] [blame] | 1137 | u.format = format; |
Behdad Esfahbod | a930c68 | 2012-09-04 18:17:57 -0400 | [diff] [blame] | 1138 | switch (u.format) { |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1139 | case 1: return_trace (u.format1.serialize (c, |
| 1140 | first_glyphs, |
| 1141 | ligature_per_first_glyph_count_list, |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1142 | ligatures_list, |
| 1143 | component_count_list, |
| 1144 | component_list)); |
| 1145 | default:return_trace (false); |
Behdad Esfahbod | a930c68 | 2012-09-04 18:17:57 -0400 | [diff] [blame] | 1146 | } |
| 1147 | } |
| 1148 | |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 1149 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 1150 | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 1151 | { |
Behdad Esfahbod | 00f6a8e | 2014-12-12 20:36:49 -0800 | [diff] [blame] | 1152 | TRACE_DISPATCH (this, u.format); |
Behdad Esfahbod | f396fbb | 2015-10-09 12:25:55 -0400 | [diff] [blame] | 1153 | if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 1154 | switch (u.format) { |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 1155 | case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1156 | default:return_trace (c->default_return_value ()); |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 1157 | } |
| 1158 | } |
| 1159 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1160 | protected: |
Behdad Esfahbod | a84e71a | 2009-04-16 16:53:40 -0400 | [diff] [blame] | 1161 | union { |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1162 | HBUINT16 format; /* Format identifier */ |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 1163 | LigatureSubstFormat1 format1; |
Behdad Esfahbod | a84e71a | 2009-04-16 16:53:40 -0400 | [diff] [blame] | 1164 | } u; |
| 1165 | }; |
Behdad Esfahbod | a84e71a | 2009-04-16 16:53:40 -0400 | [diff] [blame] | 1166 | |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 1167 | |
Behdad Esfahbod | 08f1eed | 2012-11-23 16:51:43 -0500 | [diff] [blame] | 1168 | struct ContextSubst : Context {}; |
Behdad Esfahbod | cdb317b | 2009-05-06 00:12:29 -0400 | [diff] [blame] | 1169 | |
Behdad Esfahbod | 08f1eed | 2012-11-23 16:51:43 -0500 | [diff] [blame] | 1170 | struct ChainContextSubst : ChainContext {}; |
Behdad Esfahbod | 4f27ce7 | 2009-04-16 13:40:13 -0400 | [diff] [blame] | 1171 | |
Behdad Esfahbod | 653eeb2 | 2012-11-23 16:57:36 -0500 | [diff] [blame] | 1172 | struct ExtensionSubst : Extension<ExtensionSubst> |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1173 | { |
Behdad Esfahbod | 9c3747c | 2018-09-03 16:53:03 -0700 | [diff] [blame] | 1174 | typedef struct SubstLookupSubTable SubTable; |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 1175 | bool is_reverse () const; |
Behdad Esfahbod | 4f27ce7 | 2009-04-16 13:40:13 -0400 | [diff] [blame] | 1176 | }; |
Behdad Esfahbod | 4f27ce7 | 2009-04-16 13:40:13 -0400 | [diff] [blame] | 1177 | |
| 1178 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1179 | struct ReverseChainSingleSubstFormat1 |
| 1180 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1181 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1182 | { |
| 1183 | if (!(this+coverage).intersects (glyphs)) |
| 1184 | return false; |
| 1185 | |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 1186 | const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1187 | |
| 1188 | unsigned int count; |
| 1189 | |
| 1190 | count = backtrack.len; |
| 1191 | for (unsigned int i = 0; i < count; i++) |
| 1192 | if (!(this+backtrack[i]).intersects (glyphs)) |
Behdad Esfahbod | bcd3ffc | 2019-05-16 13:22:09 -0700 | [diff] [blame] | 1193 | return false; |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1194 | |
| 1195 | count = lookahead.len; |
| 1196 | for (unsigned int i = 0; i < count; i++) |
| 1197 | if (!(this+lookahead[i]).intersects (glyphs)) |
Behdad Esfahbod | bcd3ffc | 2019-05-16 13:22:09 -0700 | [diff] [blame] | 1198 | return false; |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1199 | |
| 1200 | return true; |
| 1201 | } |
| 1202 | |
Qunxin Liu | b4fc593 | 2020-12-09 10:44:18 -0800 | [diff] [blame] | 1203 | bool may_have_non_1to1 () const |
| 1204 | { return false; } |
| 1205 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1206 | void closure (hb_closure_context_t *c) const |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 1207 | { |
Behdad Esfahbod | 418e9d0 | 2019-03-29 21:57:26 -0700 | [diff] [blame] | 1208 | if (!intersects (c->glyphs)) return; |
| 1209 | |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 1210 | const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1211 | const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); |
Behdad Esfahbod | f1dad91 | 2019-03-29 21:17:08 -0700 | [diff] [blame] | 1212 | |
Behdad Esfahbod | 16cc313 | 2019-02-14 10:40:05 -0800 | [diff] [blame] | 1213 | + hb_zip (this+coverage, substitute) |
Qunxin Liu | b8a58a0 | 2021-01-10 15:50:04 -0800 | [diff] [blame] | 1214 | | hb_filter (c->parent_active_glyphs (), hb_first) |
Behdad Esfahbod | 16cc313 | 2019-02-14 10:40:05 -0800 | [diff] [blame] | 1215 | | hb_map (hb_second) |
Behdad Esfahbod | f8fcfb2 | 2019-02-14 11:03:29 -0800 | [diff] [blame] | 1216 | | hb_sink (c->output) |
Behdad Esfahbod | bb139cb | 2019-02-14 10:51:47 -0800 | [diff] [blame] | 1217 | ; |
Behdad Esfahbod | f94b0aa | 2012-04-23 13:04:38 -0400 | [diff] [blame] | 1218 | } |
| 1219 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 1220 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
| 1221 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1222 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1223 | { |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 1224 | if (unlikely (!(this+coverage).collect_coverage (c->input))) return; |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1225 | |
| 1226 | unsigned int count; |
| 1227 | |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1228 | count = backtrack.len; |
| 1229 | for (unsigned int i = 0; i < count; i++) |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 1230 | if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return; |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1231 | |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 1232 | const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1233 | count = lookahead.len; |
| 1234 | for (unsigned int i = 0; i < count; i++) |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 1235 | if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return; |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1236 | |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1237 | const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1238 | count = substitute.len; |
Behdad Esfahbod | 63f57f4 | 2018-05-08 16:56:11 -0700 | [diff] [blame] | 1239 | c->output->add_array (substitute.arrayZ, substitute.len); |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1240 | } |
| 1241 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 1242 | const Coverage &get_coverage () const { return this+coverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1243 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1244 | bool would_apply (hb_would_apply_context_t *c) const |
Behdad Esfahbod | 90b60bd | 2019-03-29 22:12:42 -0700 | [diff] [blame] | 1245 | { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; } |
Behdad Esfahbod | 2005fa5 | 2012-11-22 14:38:10 -0500 | [diff] [blame] | 1246 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1247 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1248 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1249 | TRACE_APPLY (this); |
Behdad Esfahbod | 5ba4504 | 2015-11-02 15:43:08 -0800 | [diff] [blame] | 1250 | if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL)) |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1251 | return_trace (false); /* No chaining to this type */ |
Behdad Esfahbod | 969afd7 | 2009-05-18 05:47:47 -0400 | [diff] [blame] | 1252 | |
Ebrahim Byagowi | 0750456 | 2020-02-21 13:05:44 +0330 | [diff] [blame] | 1253 | unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1254 | if (likely (index == NOT_COVERED)) return_trace (false); |
Behdad Esfahbod | 969afd7 | 2009-05-18 05:47:47 -0400 | [diff] [blame] | 1255 | |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 1256 | const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1257 | const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); |
Behdad Esfahbod | 969afd7 | 2009-05-18 05:47:47 -0400 | [diff] [blame] | 1258 | |
Behdad Esfahbod | 41ef75f | 2020-06-17 16:29:09 -0700 | [diff] [blame] | 1259 | if (unlikely (index >= substitute.len)) return_trace (false); |
| 1260 | |
| 1261 | unsigned int start_index = 0, end_index = 0; |
Behdad Esfahbod | d7cfb3b | 2010-05-13 14:18:49 -0400 | [diff] [blame] | 1262 | if (match_backtrack (c, |
Behdad Esfahbod | 63f57f4 | 2018-05-08 16:56:11 -0700 | [diff] [blame] | 1263 | backtrack.len, (HBUINT16 *) backtrack.arrayZ, |
Behdad Esfahbod | 40bd7e9 | 2016-05-02 14:47:45 +0200 | [diff] [blame] | 1264 | match_coverage, this, |
| 1265 | &start_index) && |
Behdad Esfahbod | bcd3ffc | 2019-05-16 13:22:09 -0700 | [diff] [blame] | 1266 | match_lookahead (c, |
Behdad Esfahbod | 63f57f4 | 2018-05-08 16:56:11 -0700 | [diff] [blame] | 1267 | lookahead.len, (HBUINT16 *) lookahead.arrayZ, |
Behdad Esfahbod | 40cbefe | 2010-05-10 17:47:22 -0400 | [diff] [blame] | 1268 | match_coverage, this, |
Behdad Esfahbod | 40bd7e9 | 2016-05-02 14:47:45 +0200 | [diff] [blame] | 1269 | 1, &end_index)) |
Behdad Esfahbod | 969afd7 | 2009-05-18 05:47:47 -0400 | [diff] [blame] | 1270 | { |
Behdad Esfahbod | 40bd7e9 | 2016-05-02 14:47:45 +0200 | [diff] [blame] | 1271 | c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index); |
Behdad Esfahbod | 7fbbf86 | 2012-07-30 18:36:42 -0400 | [diff] [blame] | 1272 | c->replace_glyph_inplace (substitute[index]); |
Behdad Esfahbod | 4990186 | 2013-10-17 19:48:51 +0200 | [diff] [blame] | 1273 | /* Note: We DON'T decrease buffer->idx. The main loop does it |
| 1274 | * for us. This is useful for preventing surprises if someone |
| 1275 | * calls us through a Context lookup. */ |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1276 | return_trace (true); |
Behdad Esfahbod | 969afd7 | 2009-05-18 05:47:47 -0400 | [diff] [blame] | 1277 | } |
| 1278 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1279 | return_trace (false); |
Behdad Esfahbod | ca5290f | 2009-05-17 20:48:27 -0400 | [diff] [blame] | 1280 | } |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 1281 | |
Qunxin Liu | 95230e2 | 2021-03-18 17:41:25 -0700 | [diff] [blame] | 1282 | template<typename Iterator, |
| 1283 | hb_requires (hb_is_iterator (Iterator))> |
| 1284 | bool serialize_coverage_offset_array (hb_subset_context_t *c, Iterator it) const |
| 1285 | { |
| 1286 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 1287 | auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> (); |
Qunxin Liu | 95230e2 | 2021-03-18 17:41:25 -0700 | [diff] [blame] | 1288 | |
| 1289 | if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size))) |
| 1290 | return_trace (false); |
| 1291 | |
| 1292 | for (auto& offset : it) { |
| 1293 | auto *o = out->serialize_append (c->serializer); |
| 1294 | if (unlikely (!o) || !o->serialize_subset (c, offset, this)) |
| 1295 | return_trace (false); |
| 1296 | } |
| 1297 | |
| 1298 | return_trace (true); |
| 1299 | } |
| 1300 | |
| 1301 | template<typename Iterator, typename BacktrackIterator, typename LookaheadIterator, |
| 1302 | hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_pair_t)), |
| 1303 | hb_requires (hb_is_iterator (BacktrackIterator)), |
| 1304 | hb_requires (hb_is_iterator (LookaheadIterator))> |
| 1305 | bool serialize (hb_subset_context_t *c, |
| 1306 | Iterator coverage_subst_iter, |
| 1307 | BacktrackIterator backtrack_iter, |
| 1308 | LookaheadIterator lookahead_iter) const |
| 1309 | { |
| 1310 | TRACE_SERIALIZE (this); |
| 1311 | |
| 1312 | auto *out = c->serializer->start_embed (this); |
| 1313 | if (unlikely (!c->serializer->check_success (out))) return_trace (false); |
| 1314 | if (unlikely (!c->serializer->embed (this->format))) return_trace (false); |
| 1315 | if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false); |
| 1316 | |
| 1317 | if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false); |
| 1318 | if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false); |
| 1319 | |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1320 | auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID16>> (); |
Qunxin Liu | 95230e2 | 2021-03-18 17:41:25 -0700 | [diff] [blame] | 1321 | auto substitutes = |
| 1322 | + coverage_subst_iter |
| 1323 | | hb_map (hb_second) |
| 1324 | ; |
| 1325 | |
| 1326 | auto glyphs = |
| 1327 | + coverage_subst_iter |
| 1328 | | hb_map_retains_sorting (hb_first) |
| 1329 | ; |
| 1330 | if (unlikely (! c->serializer->check_success (substitute_out->serialize (c->serializer, substitutes)))) |
| 1331 | return_trace (false); |
| 1332 | |
Garret Rieger | 5ba46ed | 2021-06-11 13:34:00 -0700 | [diff] [blame] | 1333 | if (unlikely (!out->coverage.serialize_serialize (c->serializer, glyphs))) |
Qunxin Liu | 95230e2 | 2021-03-18 17:41:25 -0700 | [diff] [blame] | 1334 | return_trace (false); |
| 1335 | return_trace (true); |
| 1336 | } |
| 1337 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1338 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 1339 | { |
| 1340 | TRACE_SUBSET (this); |
Qunxin Liu | 95230e2 | 2021-03-18 17:41:25 -0700 | [diff] [blame] | 1341 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
| 1342 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 1343 | |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 1344 | const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1345 | const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); |
Qunxin Liu | 95230e2 | 2021-03-18 17:41:25 -0700 | [diff] [blame] | 1346 | |
| 1347 | auto it = |
| 1348 | + hb_zip (this+coverage, substitute) |
| 1349 | | hb_filter (glyphset, hb_first) |
| 1350 | | hb_filter (glyphset, hb_second) |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1351 | | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t |
Qunxin Liu | 95230e2 | 2021-03-18 17:41:25 -0700 | [diff] [blame] | 1352 | { return hb_pair (glyph_map[p.first], glyph_map[p.second]); }) |
| 1353 | ; |
| 1354 | |
| 1355 | return_trace (bool (it) && serialize (c, it, backtrack.iter (), lookahead.iter ())); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 1356 | } |
| 1357 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1358 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 1359 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1360 | TRACE_SANITIZE (this); |
Behdad Esfahbod | 0ab8c86 | 2012-05-11 01:25:34 +0200 | [diff] [blame] | 1361 | if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this))) |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1362 | return_trace (false); |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 1363 | const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack); |
Behdad Esfahbod | d7cfb3b | 2010-05-13 14:18:49 -0400 | [diff] [blame] | 1364 | if (!lookahead.sanitize (c, this)) |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1365 | return_trace (false); |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1366 | const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1367 | return_trace (substitute.sanitize (c)); |
Behdad Esfahbod | 70de50c | 2009-08-04 00:58:28 -0400 | [diff] [blame] | 1368 | } |
| 1369 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1370 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1371 | HBUINT16 format; /* Format identifier--format = 1 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 1372 | Offset16To<Coverage> |
Behdad Esfahbod | 969afd7 | 2009-05-18 05:47:47 -0400 | [diff] [blame] | 1373 | coverage; /* Offset to Coverage table--from |
| 1374 | * beginning of table */ |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 1375 | Array16OfOffset16To<Coverage> |
Behdad Esfahbod | 969afd7 | 2009-05-18 05:47:47 -0400 | [diff] [blame] | 1376 | backtrack; /* Array of coverage tables |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1377 | * in backtracking sequence, in glyph |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 1378 | * sequence order */ |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 1379 | Array16OfOffset16To<Coverage> |
Behdad Esfahbod | 969afd7 | 2009-05-18 05:47:47 -0400 | [diff] [blame] | 1380 | lookaheadX; /* Array of coverage tables |
| 1381 | * in lookahead sequence, in glyph |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 1382 | * sequence order */ |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1383 | Array16Of<HBGlyphID16> |
Behdad Esfahbod | 969afd7 | 2009-05-18 05:47:47 -0400 | [diff] [blame] | 1384 | substituteX; /* Array of substitute |
| 1385 | * GlyphIDs--ordered by Coverage Index */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 1386 | public: |
Behdad Esfahbod | bea34c7 | 2010-05-10 17:28:16 -0400 | [diff] [blame] | 1387 | DEFINE_SIZE_MIN (10); |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 1388 | }; |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 1389 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1390 | struct ReverseChainSingleSubst |
| 1391 | { |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 1392 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 1393 | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1394 | { |
Behdad Esfahbod | 00f6a8e | 2014-12-12 20:36:49 -0800 | [diff] [blame] | 1395 | TRACE_DISPATCH (this, u.format); |
Behdad Esfahbod | f396fbb | 2015-10-09 12:25:55 -0400 | [diff] [blame] | 1396 | if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1397 | switch (u.format) { |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 1398 | case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1399 | default:return_trace (c->default_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1400 | } |
| 1401 | } |
| 1402 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1403 | protected: |
Behdad Esfahbod | ca5290f | 2009-05-17 20:48:27 -0400 | [diff] [blame] | 1404 | union { |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1405 | HBUINT16 format; /* Format identifier */ |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 1406 | ReverseChainSingleSubstFormat1 format1; |
Behdad Esfahbod | ca5290f | 2009-05-17 20:48:27 -0400 | [diff] [blame] | 1407 | } u; |
| 1408 | }; |
Behdad Esfahbod | ca5290f | 2009-05-17 20:48:27 -0400 | [diff] [blame] | 1409 | |
| 1410 | |
| 1411 | |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 1412 | /* |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 1413 | * SubstLookup |
| 1414 | */ |
| 1415 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1416 | struct SubstLookupSubTable |
| 1417 | { |
Behdad Esfahbod | 7b2ef55 | 2018-09-03 17:16:09 -0700 | [diff] [blame] | 1418 | friend struct Lookup; |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 1419 | friend struct SubstLookup; |
| 1420 | |
Behdad Esfahbod | c6035cf | 2012-04-12 13:23:59 -0400 | [diff] [blame] | 1421 | enum Type { |
Behdad Esfahbod | ff05d25 | 2009-05-20 03:53:00 -0400 | [diff] [blame] | 1422 | Single = 1, |
| 1423 | Multiple = 2, |
| 1424 | Alternate = 3, |
| 1425 | Ligature = 4, |
| 1426 | Context = 5, |
| 1427 | ChainContext = 6, |
| 1428 | Extension = 7, |
Behdad Esfahbod | 8f034d5 | 2009-08-18 16:41:59 -0400 | [diff] [blame] | 1429 | ReverseChainSingle = 8 |
Behdad Esfahbod | ff05d25 | 2009-05-20 03:53:00 -0400 | [diff] [blame] | 1430 | }; |
| 1431 | |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 1432 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 1433 | typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1434 | { |
Behdad Esfahbod | 00f6a8e | 2014-12-12 20:36:49 -0800 | [diff] [blame] | 1435 | TRACE_DISPATCH (this, lookup_type); |
Behdad Esfahbod | e8cfdd7 | 2012-11-16 19:07:06 -0800 | [diff] [blame] | 1436 | switch (lookup_type) { |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 1437 | case Single: return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...)); |
| 1438 | case Multiple: return_trace (u.multiple.dispatch (c, hb_forward<Ts> (ds)...)); |
| 1439 | case Alternate: return_trace (u.alternate.dispatch (c, hb_forward<Ts> (ds)...)); |
| 1440 | case Ligature: return_trace (u.ligature.dispatch (c, hb_forward<Ts> (ds)...)); |
| 1441 | case Context: return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...)); |
| 1442 | case ChainContext: return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...)); |
| 1443 | case Extension: return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...)); |
| 1444 | case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, hb_forward<Ts> (ds)...)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1445 | default: return_trace (c->default_return_value ()); |
Behdad Esfahbod | e72b360 | 2012-07-19 14:35:23 -0400 | [diff] [blame] | 1446 | } |
| 1447 | } |
| 1448 | |
ariza | 72cbfb9 | 2020-01-18 16:35:52 -0800 | [diff] [blame] | 1449 | bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const |
| 1450 | { |
| 1451 | hb_intersects_context_t c (glyphs); |
| 1452 | return dispatch (&c, lookup_type); |
| 1453 | } |
| 1454 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1455 | protected: |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 1456 | union { |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 1457 | SingleSubst single; |
| 1458 | MultipleSubst multiple; |
| 1459 | AlternateSubst alternate; |
| 1460 | LigatureSubst ligature; |
Behdad Esfahbod | e72b360 | 2012-07-19 14:35:23 -0400 | [diff] [blame] | 1461 | ContextSubst context; |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 1462 | ChainContextSubst chainContext; |
| 1463 | ExtensionSubst extension; |
| 1464 | ReverseChainSingleSubst reverseChainContextSingle; |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 1465 | } u; |
Behdad Esfahbod | ed07422 | 2010-05-10 18:08:46 -0400 | [diff] [blame] | 1466 | public: |
Behdad Esfahbod | 2cc993e | 2018-12-12 10:07:38 -0500 | [diff] [blame] | 1467 | DEFINE_SIZE_MIN (0); |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 1468 | }; |
| 1469 | |
Behdad Esfahbod | 4f27ce7 | 2009-04-16 13:40:13 -0400 | [diff] [blame] | 1470 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1471 | struct SubstLookup : Lookup |
| 1472 | { |
Behdad Esfahbod | 9c3747c | 2018-09-03 16:53:03 -0700 | [diff] [blame] | 1473 | typedef SubstLookupSubTable SubTable; |
| 1474 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1475 | const SubTable& get_subtable (unsigned int i) const |
Behdad Esfahbod | 9c3747c | 2018-09-03 16:53:03 -0700 | [diff] [blame] | 1476 | { return Lookup::get_subtable<SubTable> (i); } |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 1477 | |
Behdad Esfahbod | a061e47 | 2019-12-10 13:31:50 -0600 | [diff] [blame] | 1478 | static inline bool lookup_type_is_reverse (unsigned int lookup_type) |
Behdad Esfahbod | 9c3747c | 2018-09-03 16:53:03 -0700 | [diff] [blame] | 1479 | { return lookup_type == SubTable::ReverseChainSingle; } |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 1480 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 1481 | bool is_reverse () const |
Behdad Esfahbod | a065f47 | 2010-04-22 20:15:11 -0400 | [diff] [blame] | 1482 | { |
| 1483 | unsigned int type = get_type (); |
Behdad Esfahbod | 9c3747c | 2018-09-03 16:53:03 -0700 | [diff] [blame] | 1484 | if (unlikely (type == SubTable::Extension)) |
Ebrahim Byagowi | 0750456 | 2020-02-21 13:05:44 +0330 | [diff] [blame] | 1485 | return reinterpret_cast<const ExtensionSubst &> (get_subtable (0)).is_reverse (); |
Behdad Esfahbod | a065f47 | 2010-04-22 20:15:11 -0400 | [diff] [blame] | 1486 | return lookup_type_is_reverse (type); |
| 1487 | } |
| 1488 | |
Qunxin Liu | b4fc593 | 2020-12-09 10:44:18 -0800 | [diff] [blame] | 1489 | bool may_have_non_1to1 () const |
| 1490 | { |
| 1491 | hb_have_non_1to1_context_t c; |
| 1492 | return dispatch (&c); |
| 1493 | } |
| 1494 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1495 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | bd047d3 | 2015-02-19 10:47:18 +0300 | [diff] [blame] | 1496 | { |
| 1497 | TRACE_APPLY (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1498 | return_trace (dispatch (c)); |
Behdad Esfahbod | bd047d3 | 2015-02-19 10:47:18 +0300 | [diff] [blame] | 1499 | } |
| 1500 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1501 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1502 | { |
| 1503 | hb_intersects_context_t c (glyphs); |
| 1504 | return dispatch (&c); |
| 1505 | } |
| 1506 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1507 | hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const |
Behdad Esfahbod | 9b34677 | 2012-11-23 17:55:40 -0500 | [diff] [blame] | 1508 | { |
Behdad Esfahbod | ba0ea56 | 2018-06-11 23:24:41 -0400 | [diff] [blame] | 1509 | if (!c->should_visit_lookup (this_index)) |
Behdad Esfahbod | 0772c06 | 2019-01-18 12:53:06 -0500 | [diff] [blame] | 1510 | return hb_closure_context_t::default_return_value (); |
Garret Rieger | 45186b9 | 2018-06-05 17:14:42 -0700 | [diff] [blame] | 1511 | |
| 1512 | c->set_recurse_func (dispatch_closure_recurse_func); |
Behdad Esfahbod | c38bd40 | 2018-07-24 09:43:27 -0700 | [diff] [blame] | 1513 | |
| 1514 | hb_closure_context_t::return_t ret = dispatch (c); |
| 1515 | |
| 1516 | c->flush (); |
| 1517 | |
Behdad Esfahbod | 0772c06 | 2019-01-18 12:53:06 -0500 | [diff] [blame] | 1518 | return ret; |
Behdad Esfahbod | 26514d5 | 2012-11-23 18:13:48 -0500 | [diff] [blame] | 1519 | } |
| 1520 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 1521 | hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const |
| 1522 | { |
| 1523 | if (c->is_lookup_visited (this_index)) |
| 1524 | return hb_closure_lookups_context_t::default_return_value (); |
| 1525 | |
| 1526 | c->set_lookup_visited (this_index); |
| 1527 | if (!intersects (c->glyphs)) |
| 1528 | { |
| 1529 | c->set_lookup_inactive (this_index); |
| 1530 | return hb_closure_lookups_context_t::default_return_value (); |
| 1531 | } |
| 1532 | |
| 1533 | c->set_recurse_func (dispatch_closure_lookups_recurse_func); |
| 1534 | |
| 1535 | hb_closure_lookups_context_t::return_t ret = dispatch (c); |
| 1536 | return ret; |
| 1537 | } |
| 1538 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1539 | hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | 26514d5 | 2012-11-23 18:13:48 -0500 | [diff] [blame] | 1540 | { |
Behdad Esfahbod | 9c5a9ee | 2013-03-09 01:55:04 -0500 | [diff] [blame] | 1541 | c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>); |
Behdad Esfahbod | 89bcfb2 | 2019-01-18 14:59:18 -0500 | [diff] [blame] | 1542 | return dispatch (c); |
Behdad Esfahbod | 9b34677 | 2012-11-23 17:55:40 -0500 | [diff] [blame] | 1543 | } |
| 1544 | |
Behdad Esfahbod | a878c58 | 2012-08-01 21:18:54 -0400 | [diff] [blame] | 1545 | template <typename set_t> |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 1546 | void collect_coverage (set_t *glyphs) const |
Behdad Esfahbod | a878c58 | 2012-08-01 21:18:54 -0400 | [diff] [blame] | 1547 | { |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 1548 | hb_collect_coverage_context_t<set_t> c (glyphs); |
Behdad Esfahbod | 8e36ccf | 2015-02-17 19:15:34 +0300 | [diff] [blame] | 1549 | dispatch (&c); |
Behdad Esfahbod | a878c58 | 2012-08-01 21:18:54 -0400 | [diff] [blame] | 1550 | } |
| 1551 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1552 | bool would_apply (hb_would_apply_context_t *c, |
| 1553 | const hb_ot_layout_lookup_accelerator_t *accel) const |
Behdad Esfahbod | 3660894 | 2012-04-19 22:21:38 -0400 | [diff] [blame] | 1554 | { |
Behdad Esfahbod | 90b60bd | 2019-03-29 22:12:42 -0700 | [diff] [blame] | 1555 | if (unlikely (!c->len)) return false; |
| 1556 | if (!accel->may_have (c->glyphs[0])) return false; |
| 1557 | return dispatch (c); |
Behdad Esfahbod | 3660894 | 2012-04-19 22:21:38 -0400 | [diff] [blame] | 1558 | } |
| 1559 | |
Behdad Esfahbod | a061e47 | 2019-12-10 13:31:50 -0600 | [diff] [blame] | 1560 | static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index); |
Behdad Esfahbod | 29d8644 | 2009-08-04 02:27:37 -0400 | [diff] [blame] | 1561 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1562 | bool serialize_single (hb_serialize_context_t *c, |
| 1563 | uint32_t lookup_props, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1564 | hb_sorted_array_t<const HBGlyphID16> glyphs, |
| 1565 | hb_array_t<const HBGlyphID16> substitutes) |
Behdad Esfahbod | b3b89b6 | 2012-09-04 21:13:17 -0400 | [diff] [blame] | 1566 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1567 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | 9c3747c | 2018-09-03 16:53:03 -0700 | [diff] [blame] | 1568 | if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false); |
Garret Rieger | cc96c4e | 2021-06-14 16:43:23 -0700 | [diff] [blame] | 1569 | if (c->push<SubTable> ()->u.single.serialize (c, hb_zip (glyphs, substitutes))) |
| 1570 | { |
| 1571 | c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ()); |
| 1572 | return_trace (true); |
| 1573 | } |
| 1574 | c->pop_discard (); |
| 1575 | return_trace (false); |
Behdad Esfahbod | b3b89b6 | 2012-09-04 21:13:17 -0400 | [diff] [blame] | 1576 | } |
| 1577 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1578 | bool serialize_multiple (hb_serialize_context_t *c, |
| 1579 | uint32_t lookup_props, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1580 | hb_sorted_array_t<const HBGlyphID16> glyphs, |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 1581 | hb_array_t<const unsigned int> substitute_len_list, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1582 | hb_array_t<const HBGlyphID16> substitute_glyphs_list) |
Behdad Esfahbod | b3b89b6 | 2012-09-04 21:13:17 -0400 | [diff] [blame] | 1583 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1584 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | 9c3747c | 2018-09-03 16:53:03 -0700 | [diff] [blame] | 1585 | if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false); |
Garret Rieger | cc96c4e | 2021-06-14 16:43:23 -0700 | [diff] [blame] | 1586 | if (c->push<SubTable> ()->u.multiple. |
| 1587 | serialize (c, |
| 1588 | glyphs, |
| 1589 | substitute_len_list, |
| 1590 | substitute_glyphs_list)) |
| 1591 | { |
| 1592 | c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ()); |
| 1593 | return_trace (true); |
| 1594 | } |
| 1595 | c->pop_discard (); |
| 1596 | return_trace (false); |
Behdad Esfahbod | b3b89b6 | 2012-09-04 21:13:17 -0400 | [diff] [blame] | 1597 | } |
| 1598 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1599 | bool serialize_alternate (hb_serialize_context_t *c, |
| 1600 | uint32_t lookup_props, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1601 | hb_sorted_array_t<const HBGlyphID16> glyphs, |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 1602 | hb_array_t<const unsigned int> alternate_len_list, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1603 | hb_array_t<const HBGlyphID16> alternate_glyphs_list) |
Behdad Esfahbod | b3b89b6 | 2012-09-04 21:13:17 -0400 | [diff] [blame] | 1604 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1605 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | 9c3747c | 2018-09-03 16:53:03 -0700 | [diff] [blame] | 1606 | if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false); |
Garret Rieger | cc96c4e | 2021-06-14 16:43:23 -0700 | [diff] [blame] | 1607 | |
| 1608 | if (c->push<SubTable> ()->u.alternate. |
| 1609 | serialize (c, |
| 1610 | glyphs, |
| 1611 | alternate_len_list, |
| 1612 | alternate_glyphs_list)) |
| 1613 | { |
| 1614 | c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ()); |
| 1615 | return_trace (true); |
| 1616 | } |
| 1617 | c->pop_discard (); |
| 1618 | return_trace (false); |
Behdad Esfahbod | b3b89b6 | 2012-09-04 21:13:17 -0400 | [diff] [blame] | 1619 | } |
| 1620 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1621 | bool serialize_ligature (hb_serialize_context_t *c, |
| 1622 | uint32_t lookup_props, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1623 | hb_sorted_array_t<const HBGlyphID16> first_glyphs, |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 1624 | hb_array_t<const unsigned int> ligature_per_first_glyph_count_list, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1625 | hb_array_t<const HBGlyphID16> ligatures_list, |
Behdad Esfahbod | f1e95e4 | 2018-12-18 16:49:08 -0500 | [diff] [blame] | 1626 | hb_array_t<const unsigned int> component_count_list, |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1627 | hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */) |
Behdad Esfahbod | b3b89b6 | 2012-09-04 21:13:17 -0400 | [diff] [blame] | 1628 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1629 | TRACE_SERIALIZE (this); |
Behdad Esfahbod | 9c3747c | 2018-09-03 16:53:03 -0700 | [diff] [blame] | 1630 | if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false); |
Garret Rieger | cc96c4e | 2021-06-14 16:43:23 -0700 | [diff] [blame] | 1631 | if (c->push<SubTable> ()->u.ligature. |
| 1632 | serialize (c, |
| 1633 | first_glyphs, |
| 1634 | ligature_per_first_glyph_count_list, |
| 1635 | ligatures_list, |
| 1636 | component_count_list, |
| 1637 | component_list)) |
| 1638 | { |
| 1639 | c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ()); |
| 1640 | return_trace (true); |
| 1641 | } |
| 1642 | c->pop_discard (); |
| 1643 | return_trace (false); |
Behdad Esfahbod | b3b89b6 | 2012-09-04 21:13:17 -0400 | [diff] [blame] | 1644 | } |
| 1645 | |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 1646 | template <typename context_t> |
Behdad Esfahbod | a061e47 | 2019-12-10 13:31:50 -0600 | [diff] [blame] | 1647 | static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); |
Garret Rieger | 73ed59f | 2021-03-17 15:53:10 -0700 | [diff] [blame] | 1648 | |
Qunxin Liu | 0e1c0fa | 2021-01-12 10:17:14 -0800 | [diff] [blame] | 1649 | static inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index); |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 1650 | |
Qunxin Liu | 0e1c0fa | 2021-01-12 10:17:14 -0800 | [diff] [blame] | 1651 | static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index) |
Garret Rieger | 45186b9 | 2018-06-05 17:14:42 -0700 | [diff] [blame] | 1652 | { |
Behdad Esfahbod | ba0ea56 | 2018-06-11 23:24:41 -0400 | [diff] [blame] | 1653 | if (!c->should_visit_lookup (lookup_index)) |
Behdad Esfahbod | 7df3ecf | 2019-05-10 20:43:26 -0700 | [diff] [blame] | 1654 | return hb_empty_t (); |
Behdad Esfahbod | c38bd40 | 2018-07-24 09:43:27 -0700 | [diff] [blame] | 1655 | |
Qunxin Liu | 0e1c0fa | 2021-01-12 10:17:14 -0800 | [diff] [blame] | 1656 | hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index); |
Behdad Esfahbod | c38bd40 | 2018-07-24 09:43:27 -0700 | [diff] [blame] | 1657 | |
Behdad Esfahbod | a9e0bdc | 2018-11-22 21:30:04 -0500 | [diff] [blame] | 1658 | /* While in theory we should flush here, it will cause timeouts because a recursive |
| 1659 | * lookup can keep growing the glyph set. Skip, and outer loop will retry up to |
| 1660 | * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */ |
| 1661 | //c->flush (); |
Behdad Esfahbod | c38bd40 | 2018-07-24 09:43:27 -0700 | [diff] [blame] | 1662 | |
| 1663 | return ret; |
Garret Rieger | 45186b9 | 2018-06-05 17:14:42 -0700 | [diff] [blame] | 1664 | } |
| 1665 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 1666 | HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned lookup_index); |
| 1667 | |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 1668 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 1669 | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 1670 | { return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); } |
Behdad Esfahbod | 9c3747c | 2018-09-03 16:53:03 -0700 | [diff] [blame] | 1671 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1672 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 1673 | { return Lookup::subset<SubTable> (c); } |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 1674 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1675 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | 7b2ef55 | 2018-09-03 17:16:09 -0700 | [diff] [blame] | 1676 | { return Lookup::sanitize<SubTable> (c); } |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 1677 | }; |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 1678 | |
| 1679 | /* |
Ebrahim Byagowi | a02c3ee | 2018-04-12 13:38:19 +0430 | [diff] [blame] | 1680 | * GSUB -- Glyph Substitution |
| 1681 | * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 1682 | */ |
| 1683 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1684 | struct GSUB : GSUBGPOS |
| 1685 | { |
Behdad Esfahbod | ef00654 | 2019-01-22 12:08:57 +0100 | [diff] [blame] | 1686 | static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB; |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 1687 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1688 | const SubstLookup& get_lookup (unsigned int i) const |
Behdad Esfahbod | 858b627 | 2019-12-10 13:18:32 -0600 | [diff] [blame] | 1689 | { return static_cast<const SubstLookup &> (GSUBGPOS::get_lookup (i)); } |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 1690 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1691 | bool subset (hb_subset_context_t *c) const |
Qunxin Liu | e565d1f | 2019-11-01 10:21:36 -0700 | [diff] [blame] | 1692 | { |
Qunxin Liu | 56ca435 | 2021-01-28 15:21:26 -0800 | [diff] [blame] | 1693 | hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features); |
Qunxin Liu | e565d1f | 2019-11-01 10:21:36 -0700 | [diff] [blame] | 1694 | return GSUBGPOS::subset<SubstLookup> (&l); |
| 1695 | } |
Behdad Esfahbod | d1f2990 | 2018-08-31 16:31:00 -0700 | [diff] [blame] | 1696 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1697 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 1698 | { return GSUBGPOS::sanitize<SubstLookup> (c); } |
Behdad Esfahbod | 963413f | 2018-08-26 00:47:55 -0700 | [diff] [blame] | 1699 | |
Behdad Esfahbod | 5671947 | 2020-06-05 12:57:23 -0700 | [diff] [blame] | 1700 | HB_INTERNAL bool is_blocklisted (hb_blob_t *blob, |
Behdad Esfahbod | 574d888 | 2018-11-25 16:51:22 -0500 | [diff] [blame] | 1701 | hb_face_t *face) const; |
| 1702 | |
Qunxin Liu | 973c47f | 2020-06-11 11:27:57 -0700 | [diff] [blame] | 1703 | void closure_lookups (hb_face_t *face, |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 1704 | const hb_set_t *glyphs, |
| 1705 | hb_set_t *lookup_indexes /* IN/OUT */) const |
Qunxin Liu | 973c47f | 2020-06-11 11:27:57 -0700 | [diff] [blame] | 1706 | { GSUBGPOS::closure_lookups<SubstLookup> (face, glyphs, lookup_indexes); } |
| 1707 | |
Behdad Esfahbod | 963413f | 2018-08-26 00:47:55 -0700 | [diff] [blame] | 1708 | typedef GSUBGPOS::accelerator_t<GSUB> accelerator_t; |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 1709 | }; |
Behdad Esfahbod | c43562b | 2009-05-15 18:54:53 -0400 | [diff] [blame] | 1710 | |
| 1711 | |
Behdad Esfahbod | 33b006c | 2018-11-05 23:19:04 -0500 | [diff] [blame] | 1712 | struct GSUB_accelerator_t : GSUB::accelerator_t {}; |
| 1713 | |
| 1714 | |
Behdad Esfahbod | 887c4b4 | 2009-05-17 21:06:08 -0400 | [diff] [blame] | 1715 | /* Out-of-class implementation for methods recursing */ |
Behdad Esfahbod | c43562b | 2009-05-15 18:54:53 -0400 | [diff] [blame] | 1716 | |
Behdad Esfahbod | 7dcf8e1 | 2019-06-26 13:44:10 -0700 | [diff] [blame] | 1717 | #ifndef HB_NO_OT_LAYOUT |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 1718 | /*static*/ inline bool ExtensionSubst::is_reverse () const |
Behdad Esfahbod | a065f47 | 2010-04-22 20:15:11 -0400 | [diff] [blame] | 1719 | { |
Behdad Esfahbod | dd3972a | 2019-12-10 13:21:26 -0600 | [diff] [blame] | 1720 | return SubstLookup::lookup_type_is_reverse (get_type ()); |
Behdad Esfahbod | a065f47 | 2010-04-22 20:15:11 -0400 | [diff] [blame] | 1721 | } |
Behdad Esfahbod | c6fb843 | 2012-11-23 18:04:08 -0500 | [diff] [blame] | 1722 | template <typename context_t> |
Behdad Esfahbod | dd3972a | 2019-12-10 13:21:26 -0600 | [diff] [blame] | 1723 | /*static*/ typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index) |
Behdad Esfahbod | 9b34677 | 2012-11-23 17:55:40 -0500 | [diff] [blame] | 1724 | { |
Behdad Esfahbod | 33b006c | 2018-11-05 23:19:04 -0500 | [diff] [blame] | 1725 | const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index); |
Behdad Esfahbod | 9c5a9ee | 2013-03-09 01:55:04 -0500 | [diff] [blame] | 1726 | return l.dispatch (c); |
Behdad Esfahbod | 9b34677 | 2012-11-23 17:55:40 -0500 | [diff] [blame] | 1727 | } |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 1728 | |
Qunxin Liu | 0e1c0fa | 2021-01-12 10:17:14 -0800 | [diff] [blame] | 1729 | /*static*/ typename hb_closure_context_t::return_t SubstLookup::closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index) |
Qunxin Liu | b8a58a0 | 2021-01-10 15:50:04 -0800 | [diff] [blame] | 1730 | { |
| 1731 | const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index); |
| 1732 | if (l.may_have_non_1to1 ()) |
Qunxin Liu | 0e1c0fa | 2021-01-12 10:17:14 -0800 | [diff] [blame] | 1733 | hb_set_add_range (covered_seq_indices, seq_index, end_index); |
Qunxin Liu | b8a58a0 | 2021-01-10 15:50:04 -0800 | [diff] [blame] | 1734 | return l.dispatch (c); |
| 1735 | } |
| 1736 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 1737 | /*static*/ inline hb_closure_lookups_context_t::return_t SubstLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index) |
| 1738 | { |
| 1739 | const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (this_index); |
| 1740 | return l.closure_lookups (c, this_index); |
| 1741 | } |
| 1742 | |
Behdad Esfahbod | a061e47 | 2019-12-10 13:31:50 -0600 | [diff] [blame] | 1743 | /*static*/ bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index) |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1744 | { |
Behdad Esfahbod | 33b006c | 2018-11-05 23:19:04 -0500 | [diff] [blame] | 1745 | const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index); |
Behdad Esfahbod | 4c4e8f0 | 2012-11-24 01:13:20 -0500 | [diff] [blame] | 1746 | unsigned int saved_lookup_props = c->lookup_props; |
Behdad Esfahbod | 2c8b3b2 | 2015-08-18 14:36:43 +0100 | [diff] [blame] | 1747 | unsigned int saved_lookup_index = c->lookup_index; |
| 1748 | c->set_lookup_index (lookup_index); |
| 1749 | c->set_lookup_props (l.get_props ()); |
Behdad Esfahbod | 1a23221 | 2015-02-19 10:40:23 +0300 | [diff] [blame] | 1750 | bool ret = l.dispatch (c); |
Behdad Esfahbod | 2c8b3b2 | 2015-08-18 14:36:43 +0100 | [diff] [blame] | 1751 | c->set_lookup_index (saved_lookup_index); |
Behdad Esfahbod | 7788993 | 2015-01-28 23:01:12 -0800 | [diff] [blame] | 1752 | c->set_lookup_props (saved_lookup_props); |
Behdad Esfahbod | 4c4e8f0 | 2012-11-24 01:13:20 -0500 | [diff] [blame] | 1753 | return ret; |
Behdad Esfahbod | c43562b | 2009-05-15 18:54:53 -0400 | [diff] [blame] | 1754 | } |
Behdad Esfahbod | 7dcf8e1 | 2019-06-26 13:44:10 -0700 | [diff] [blame] | 1755 | #endif |
| 1756 | |
Behdad Esfahbod | c43562b | 2009-05-15 18:54:53 -0400 | [diff] [blame] | 1757 | |
Behdad Esfahbod | 7d52e66 | 2012-11-16 18:49:54 -0800 | [diff] [blame] | 1758 | } /* namespace OT */ |
Behdad Esfahbod | 7c8e844 | 2012-08-28 17:57:49 -0400 | [diff] [blame] | 1759 | |
Behdad Esfahbod | acdba3f | 2010-07-23 15:11:18 -0400 | [diff] [blame] | 1760 | |
Behdad Esfahbod | 7a750ac | 2011-08-17 14:19:59 +0200 | [diff] [blame] | 1761 | #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */ |