Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [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 | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [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 | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [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 | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 27 | */ |
| 28 | |
Behdad Esfahbod | 7a750ac | 2011-08-17 14:19:59 +0200 | [diff] [blame] | 29 | #ifndef HB_OT_LAYOUT_GPOS_TABLE_HH |
| 30 | #define HB_OT_LAYOUT_GPOS_TABLE_HH |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 31 | |
Behdad Esfahbod | c77ae40 | 2018-08-25 22:36:36 -0700 | [diff] [blame] | 32 | #include "hb-ot-layout-gsubgpos.hh" |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [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 | |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 37 | struct MarkArray; |
| 38 | static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage, |
| 39 | const MarkArray &mark_array, |
| 40 | const hb_set_t &glyphset, |
| 41 | hb_map_t* klass_mapping /* INOUT */); |
Behdad Esfahbod | 94a23aa | 2010-05-05 01:13:09 -0400 | [diff] [blame] | 42 | |
Behdad Esfahbod | b65c060 | 2011-07-28 16:48:43 -0400 | [diff] [blame] | 43 | /* buffer **position** var allocations */ |
Behdad Esfahbod | 686567b | 2016-02-11 15:25:28 +0700 | [diff] [blame] | 44 | #define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */ |
| 45 | #define attach_type() var.u8[2] /* attachment type */ |
| 46 | /* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */ |
| 47 | |
| 48 | enum attach_type_t { |
| 49 | ATTACH_TYPE_NONE = 0X00, |
| 50 | |
| 51 | /* Each attachment should be either a mark or a cursive; can't be both. */ |
| 52 | ATTACH_TYPE_MARK = 0X01, |
| 53 | ATTACH_TYPE_CURSIVE = 0X02, |
| 54 | }; |
Behdad Esfahbod | 194d456 | 2010-10-27 23:09:10 -0400 | [diff] [blame] | 55 | |
| 56 | |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 57 | /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */ |
| 58 | |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 59 | typedef HBUINT16 Value; |
Behdad Esfahbod | c91facd | 2009-08-26 18:53:43 -0400 | [diff] [blame] | 60 | |
Behdad Esfahbod | 1d66cdc | 2018-11-10 19:54:08 -0500 | [diff] [blame] | 61 | typedef UnsizedArrayOf<Value> ValueRecord; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 62 | |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 63 | struct ValueFormat : HBUINT16 |
Behdad Esfahbod | fca6a0d | 2009-05-21 04:49:04 -0400 | [diff] [blame] | 64 | { |
Behdad Esfahbod | c6035cf | 2012-04-12 13:23:59 -0400 | [diff] [blame] | 65 | enum Flags { |
Behdad Esfahbod | 7627100 | 2014-07-11 14:54:42 -0400 | [diff] [blame] | 66 | xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */ |
| 67 | yPlacement = 0x0002u, /* Includes vertical adjustment for placement */ |
| 68 | xAdvance = 0x0004u, /* Includes horizontal adjustment for advance */ |
| 69 | yAdvance = 0x0008u, /* Includes vertical adjustment for advance */ |
| 70 | xPlaDevice = 0x0010u, /* Includes horizontal Device table for placement */ |
| 71 | yPlaDevice = 0x0020u, /* Includes vertical Device table for placement */ |
| 72 | xAdvDevice = 0x0040u, /* Includes horizontal Device table for advance */ |
| 73 | yAdvDevice = 0x0080u, /* Includes vertical Device table for advance */ |
| 74 | ignored = 0x0F00u, /* Was used in TrueType Open for MM fonts */ |
| 75 | reserved = 0xF000u, /* For future use */ |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 76 | |
Behdad Esfahbod | 7627100 | 2014-07-11 14:54:42 -0400 | [diff] [blame] | 77 | devices = 0x00F0u /* Mask for having any Device table */ |
Behdad Esfahbod | fca6a0d | 2009-05-21 04:49:04 -0400 | [diff] [blame] | 78 | }; |
| 79 | |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 80 | /* All fields are options. Only those available advance the value pointer. */ |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 81 | #if 0 |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 82 | HBINT16 xPlacement; /* Horizontal adjustment for |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 83 | * placement--in design units */ |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 84 | HBINT16 yPlacement; /* Vertical adjustment for |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 85 | * placement--in design units */ |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 86 | HBINT16 xAdvance; /* Horizontal adjustment for |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 87 | * advance--in design units (only used |
| 88 | * for horizontal writing) */ |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 89 | HBINT16 yAdvance; /* Vertical adjustment for advance--in |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 90 | * design units (only used for vertical |
| 91 | * writing) */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 92 | Offset16To<Device> xPlaDevice; /* Offset to Device table for |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 93 | * horizontal placement--measured from |
| 94 | * beginning of PosTable (may be NULL) */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 95 | Offset16To<Device> yPlaDevice; /* Offset to Device table for vertical |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 96 | * placement--measured from beginning |
| 97 | * of PosTable (may be NULL) */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 98 | Offset16To<Device> xAdvDevice; /* Offset to Device table for |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 99 | * horizontal advance--measured from |
| 100 | * beginning of PosTable (may be NULL) */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 101 | Offset16To<Device> yAdvDevice; /* Offset to Device table for vertical |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 102 | * advance--measured from beginning of |
| 103 | * PosTable (may be NULL) */ |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 104 | #endif |
| 105 | |
Garret Rieger | 5df7c66 | 2021-04-22 16:45:14 -0700 | [diff] [blame] | 106 | IntType& operator = (uint16_t i) { v = i; return *this; } |
| 107 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 108 | unsigned int get_len () const { return hb_popcount ((unsigned int) *this); } |
| 109 | unsigned int get_size () const { return get_len () * Value::static_size; } |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 110 | |
Ebrahim Byagowi | 0558413 | 2019-10-01 13:49:55 +0330 | [diff] [blame] | 111 | bool apply_value (hb_ot_apply_context_t *c, |
| 112 | const void *base, |
| 113 | const Value *values, |
| 114 | hb_glyph_position_t &glyph_pos) const |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 115 | { |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 116 | bool ret = false; |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 117 | unsigned int format = *this; |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 118 | if (!format) return ret; |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 119 | |
Behdad Esfahbod | 151d93d | 2016-09-09 17:03:11 -0700 | [diff] [blame] | 120 | hb_font_t *font = c->font; |
Behdad Esfahbod | 385f78b | 2018-11-07 17:19:21 -0500 | [diff] [blame] | 121 | bool horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction); |
Behdad Esfahbod | 151d93d | 2016-09-09 17:03:11 -0700 | [diff] [blame] | 122 | |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 123 | if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret)); |
| 124 | if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret)); |
Behdad Esfahbod | 3b0bb85 | 2011-05-20 15:59:59 -0400 | [diff] [blame] | 125 | if (format & xAdvance) { |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 126 | if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret)); |
Konstantin Ritt | 0832259 | 2014-01-22 20:31:30 +0200 | [diff] [blame] | 127 | values++; |
Behdad Esfahbod | 3b0bb85 | 2011-05-20 15:59:59 -0400 | [diff] [blame] | 128 | } |
Behdad Esfahbod | cc2086d | 2011-05-19 19:19:50 -0400 | [diff] [blame] | 129 | /* y_advance values grow downward but font-space grows upward, hence negation */ |
Behdad Esfahbod | 3b0bb85 | 2011-05-20 15:59:59 -0400 | [diff] [blame] | 130 | if (format & yAdvance) { |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 131 | if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret)); |
Konstantin Ritt | 0832259 | 2014-01-22 20:31:30 +0200 | [diff] [blame] | 132 | values++; |
Behdad Esfahbod | 3b0bb85 | 2011-05-20 15:59:59 -0400 | [diff] [blame] | 133 | } |
Behdad Esfahbod | 056c7ec | 2009-05-18 19:47:52 -0400 | [diff] [blame] | 134 | |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 135 | if (!has_device ()) return ret; |
Behdad Esfahbod | a8d960b | 2010-04-29 14:31:56 -0400 | [diff] [blame] | 136 | |
Behdad Esfahbod | ca28670 | 2016-03-01 19:29:36 +0900 | [diff] [blame] | 137 | bool use_x_device = font->x_ppem || font->num_coords; |
| 138 | bool use_y_device = font->y_ppem || font->num_coords; |
Behdad Esfahbod | a8d960b | 2010-04-29 14:31:56 -0400 | [diff] [blame] | 139 | |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 140 | if (!use_x_device && !use_y_device) return ret; |
Behdad Esfahbod | a8d960b | 2010-04-29 14:31:56 -0400 | [diff] [blame] | 141 | |
Behdad Esfahbod | cf3de4d | 2016-09-10 00:22:24 -0700 | [diff] [blame] | 142 | const VariationStore &store = c->var_store; |
Behdad Esfahbod | 151d93d | 2016-09-09 17:03:11 -0700 | [diff] [blame] | 143 | |
Behdad Esfahbod | 0090dc0 | 2009-07-30 16:28:45 -0400 | [diff] [blame] | 144 | /* pixel -> fractional pixel */ |
| 145 | if (format & xPlaDevice) { |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 146 | if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store); |
Konstantin Ritt | 0832259 | 2014-01-22 20:31:30 +0200 | [diff] [blame] | 147 | values++; |
Behdad Esfahbod | 0090dc0 | 2009-07-30 16:28:45 -0400 | [diff] [blame] | 148 | } |
| 149 | if (format & yPlaDevice) { |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 150 | if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store); |
Konstantin Ritt | 0832259 | 2014-01-22 20:31:30 +0200 | [diff] [blame] | 151 | values++; |
Behdad Esfahbod | 0090dc0 | 2009-07-30 16:28:45 -0400 | [diff] [blame] | 152 | } |
| 153 | if (format & xAdvDevice) { |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 154 | if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store); |
Konstantin Ritt | 0832259 | 2014-01-22 20:31:30 +0200 | [diff] [blame] | 155 | values++; |
Behdad Esfahbod | 0090dc0 | 2009-07-30 16:28:45 -0400 | [diff] [blame] | 156 | } |
| 157 | if (format & yAdvDevice) { |
Behdad Esfahbod | cc2086d | 2011-05-19 19:19:50 -0400 | [diff] [blame] | 158 | /* y_advance values grow downward but font-space grows upward, hence negation */ |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 159 | if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store); |
Konstantin Ritt | 0832259 | 2014-01-22 20:31:30 +0200 | [diff] [blame] | 160 | values++; |
Behdad Esfahbod | 056c7ec | 2009-05-18 19:47:52 -0400 | [diff] [blame] | 161 | } |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 162 | return ret; |
Behdad Esfahbod | 056c7ec | 2009-05-18 19:47:52 -0400 | [diff] [blame] | 163 | } |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 164 | |
Garret Rieger | 2f50283 | 2021-04-23 15:21:30 -0700 | [diff] [blame] | 165 | unsigned int get_effective_format (const Value *values) const |
| 166 | { |
| 167 | unsigned int format = *this; |
Garret Rieger | e25efb3 | 2021-04-23 19:09:37 -0700 | [diff] [blame] | 168 | for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) { |
| 169 | if (format & flag) should_drop (*values++, (Flags) flag, &format); |
| 170 | } |
| 171 | |
Garret Rieger | 2f50283 | 2021-04-23 15:21:30 -0700 | [diff] [blame] | 172 | return format; |
| 173 | } |
| 174 | |
| 175 | template<typename Iterator, |
| 176 | hb_requires (hb_is_iterator (Iterator))> |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 177 | unsigned int get_effective_format (Iterator it) const { |
Garret Rieger | 2f50283 | 2021-04-23 15:21:30 -0700 | [diff] [blame] | 178 | unsigned int new_format = 0; |
| 179 | |
| 180 | for (const hb_array_t<const Value>& values : it) |
| 181 | new_format = new_format | get_effective_format (&values); |
| 182 | |
| 183 | return new_format; |
| 184 | } |
| 185 | |
| 186 | void copy_values (hb_serialize_context_t *c, |
| 187 | unsigned int new_format, |
| 188 | const void *base, |
| 189 | const Value *values, |
| 190 | const hb_map_t *layout_variation_idx_map) const |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 191 | { |
| 192 | unsigned int format = *this; |
| 193 | if (!format) return; |
| 194 | |
Garret Rieger | 2f50283 | 2021-04-23 15:21:30 -0700 | [diff] [blame] | 195 | if (format & xPlacement) copy_value (c, new_format, xPlacement, *values++); |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 196 | if (format & yPlacement) copy_value (c, new_format, yPlacement, *values++); |
| 197 | if (format & xAdvance) copy_value (c, new_format, xAdvance, *values++); |
| 198 | if (format & yAdvance) copy_value (c, new_format, yAdvance, *values++); |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 199 | |
Qunxin Liu | d7c012a | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 200 | if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map); |
| 201 | if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map); |
| 202 | if (format & xAdvDevice) copy_device (c, base, values++, layout_variation_idx_map); |
| 203 | if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map); |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 204 | } |
| 205 | |
Garret Rieger | 2f50283 | 2021-04-23 15:21:30 -0700 | [diff] [blame] | 206 | void copy_value (hb_serialize_context_t *c, |
| 207 | unsigned int new_format, |
| 208 | Flags flag, |
| 209 | Value value) const |
| 210 | { |
| 211 | // Filter by new format. |
| 212 | if (!(new_format & flag)) return; |
| 213 | c->copy (value); |
| 214 | } |
| 215 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 216 | void collect_variation_indices (hb_collect_variation_indices_context_t *c, |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 217 | const void *base, |
| 218 | const hb_array_t<const Value>& values) const |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 219 | { |
| 220 | unsigned format = *this; |
| 221 | unsigned i = 0; |
| 222 | if (format & xPlacement) i++; |
| 223 | if (format & yPlacement) i++; |
| 224 | if (format & xAdvance) i++; |
| 225 | if (format & yAdvance) i++; |
| 226 | if (format & xPlaDevice) |
| 227 | { |
| 228 | (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices); |
| 229 | i++; |
| 230 | } |
| 231 | |
| 232 | if (format & ValueFormat::yPlaDevice) |
| 233 | { |
| 234 | (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices); |
| 235 | i++; |
| 236 | } |
| 237 | |
| 238 | if (format & ValueFormat::xAdvDevice) |
| 239 | { |
| 240 | |
| 241 | (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices); |
| 242 | i++; |
| 243 | } |
| 244 | |
| 245 | if (format & ValueFormat::yAdvDevice) |
| 246 | { |
| 247 | |
| 248 | (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices); |
| 249 | i++; |
| 250 | } |
| 251 | } |
| 252 | |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 253 | private: |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 254 | bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 255 | { |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 256 | unsigned int format = *this; |
| 257 | |
| 258 | if (format & xPlacement) values++; |
| 259 | if (format & yPlacement) values++; |
| 260 | if (format & xAdvance) values++; |
| 261 | if (format & yAdvance) values++; |
| 262 | |
Behdad Esfahbod | d7cfb3b | 2010-05-13 14:18:49 -0400 | [diff] [blame] | 263 | if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false; |
| 264 | if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false; |
| 265 | if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false; |
| 266 | if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false; |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 267 | |
| 268 | return true; |
| 269 | } |
| 270 | |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 271 | static inline Offset16To<Device>& get_device (Value* value) |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 272 | { |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 273 | return *static_cast<Offset16To<Device> *> (value); |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 274 | } |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 275 | static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr) |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 276 | { |
| 277 | if (worked) *worked |= bool (*value); |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 278 | return *static_cast<const Offset16To<Device> *> (value); |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 279 | } |
| 280 | |
Qunxin Liu | d7c012a | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 281 | bool copy_device (hb_serialize_context_t *c, const void *base, |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 282 | const Value *src_value, const hb_map_t *layout_variation_idx_map) const |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 283 | { |
| 284 | Value *dst_value = c->copy (*src_value); |
| 285 | |
| 286 | if (!dst_value) return false; |
| 287 | if (*dst_value == 0) return true; |
| 288 | |
| 289 | *dst_value = 0; |
| 290 | c->push (); |
Qunxin Liu | d7c012a | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 291 | if ((base + get_device (src_value)).copy (c, layout_variation_idx_map)) |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 292 | { |
ariza | 188a0a4 | 2020-03-07 11:02:36 -0800 | [diff] [blame] | 293 | c->add_link (*dst_value, c->pop_pack ()); |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 294 | return true; |
| 295 | } |
| 296 | else |
| 297 | { |
| 298 | c->pop_discard (); |
| 299 | return false; |
| 300 | } |
| 301 | } |
| 302 | |
Behdad Esfahbod | a061e47 | 2019-12-10 13:31:50 -0600 | [diff] [blame] | 303 | static inline const HBINT16& get_short (const Value* value, bool *worked=nullptr) |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 304 | { |
Behdad Esfahbod | b9a51f5 | 2018-12-21 15:05:00 -0500 | [diff] [blame] | 305 | if (worked) *worked |= bool (*value); |
Behdad Esfahbod | b84ceb2 | 2019-12-10 13:02:48 -0600 | [diff] [blame] | 306 | return *reinterpret_cast<const HBINT16 *> (value); |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 307 | } |
Behdad Esfahbod | c2ddfd2 | 2010-05-06 13:06:15 -0400 | [diff] [blame] | 308 | |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 309 | public: |
| 310 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 311 | bool has_device () const |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 312 | { |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 313 | unsigned int format = *this; |
| 314 | return (format & devices) != 0; |
| 315 | } |
| 316 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 317 | bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 318 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 319 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 320 | return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values))); |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 321 | } |
| 322 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 323 | bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 324 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 325 | TRACE_SANITIZE (this); |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 326 | unsigned int len = get_len (); |
| 327 | |
Behdad Esfahbod | e014405 | 2018-11-12 14:23:31 -0500 | [diff] [blame] | 328 | if (!c->check_range (values, count, get_size ())) return_trace (false); |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 329 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 330 | if (!has_device ()) return_trace (true); |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 331 | |
| 332 | for (unsigned int i = 0; i < count; i++) { |
Behdad Esfahbod | d7cfb3b | 2010-05-13 14:18:49 -0400 | [diff] [blame] | 333 | if (!sanitize_value_devices (c, base, values)) |
Ebrahim Byagowi | 11aa046 | 2018-11-15 23:10:56 +0330 | [diff] [blame] | 334 | return_trace (false); |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 335 | values += len; |
| 336 | } |
| 337 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 338 | return_trace (true); |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 339 | } |
| 340 | |
Behdad Esfahbod | 278a91f | 2010-04-22 13:59:39 -0400 | [diff] [blame] | 341 | /* Just sanitize referenced Device tables. Doesn't check the values themselves. */ |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 342 | bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 343 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 344 | TRACE_SANITIZE (this); |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 345 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 346 | if (!has_device ()) return_trace (true); |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 347 | |
| 348 | for (unsigned int i = 0; i < count; i++) { |
Behdad Esfahbod | d7cfb3b | 2010-05-13 14:18:49 -0400 | [diff] [blame] | 349 | if (!sanitize_value_devices (c, base, values)) |
Ebrahim Byagowi | 11aa046 | 2018-11-15 23:10:56 +0330 | [diff] [blame] | 350 | return_trace (false); |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 351 | values += stride; |
| 352 | } |
| 353 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 354 | return_trace (true); |
Behdad Esfahbod | 673a4ef | 2010-04-21 02:02:57 -0400 | [diff] [blame] | 355 | } |
Garret Rieger | 2f50283 | 2021-04-23 15:21:30 -0700 | [diff] [blame] | 356 | |
| 357 | private: |
| 358 | |
| 359 | void should_drop (Value value, Flags flag, unsigned int* format) const |
| 360 | { |
| 361 | if (value) return; |
| 362 | *format = *format & ~flag; |
| 363 | } |
| 364 | |
Behdad Esfahbod | 056c7ec | 2009-05-18 19:47:52 -0400 | [diff] [blame] | 365 | }; |
Behdad Esfahbod | 056c7ec | 2009-05-18 19:47:52 -0400 | [diff] [blame] | 366 | |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 367 | template<typename Iterator, typename SrcLookup> |
Behdad Esfahbod | dd3972a | 2019-12-10 13:21:26 -0600 | [diff] [blame] | 368 | static void SinglePos_serialize (hb_serialize_context_t *c, |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 369 | const SrcLookup *src, |
Behdad Esfahbod | dd3972a | 2019-12-10 13:21:26 -0600 | [diff] [blame] | 370 | Iterator it, |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 371 | const hb_map_t *layout_variation_idx_map); |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 372 | |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 373 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 374 | struct AnchorFormat1 |
| 375 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 376 | void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, |
| 377 | float *x, float *y) const |
Behdad Esfahbod | b24ecba | 2009-05-19 22:16:04 -0400 | [diff] [blame] | 378 | { |
Behdad Esfahbod | 49cb878 | 2016-09-09 16:27:03 -0700 | [diff] [blame] | 379 | hb_font_t *font = c->font; |
Behdad Esfahbod | 188ee6e | 2018-01-10 05:13:47 +0100 | [diff] [blame] | 380 | *x = font->em_fscale_x (xCoordinate); |
| 381 | *y = font->em_fscale_y (yCoordinate); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 382 | } |
| 383 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 384 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 385 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 386 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 387 | return_trace (c->check_struct (this)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 388 | } |
Ebrahim Byagowi | 0558413 | 2019-10-01 13:49:55 +0330 | [diff] [blame] | 389 | |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 390 | AnchorFormat1* copy (hb_serialize_context_t *c) const |
| 391 | { |
| 392 | TRACE_SERIALIZE (this); |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 393 | AnchorFormat1* out = c->embed<AnchorFormat1> (this); |
Qunxin Liu | 553ffaf | 2021-04-07 17:15:32 -0700 | [diff] [blame] | 394 | if (!out) return_trace (out); |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 395 | out->format = 1; |
| 396 | return_trace (out); |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 397 | } |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 398 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 399 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 400 | HBUINT16 format; /* Format identifier--format = 1 */ |
Behdad Esfahbod | e347fb9 | 2018-02-26 01:08:00 -0800 | [diff] [blame] | 401 | FWORD xCoordinate; /* Horizontal value--in design units */ |
| 402 | FWORD yCoordinate; /* Vertical value--in design units */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 403 | public: |
| 404 | DEFINE_SIZE_STATIC (6); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 405 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 406 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 407 | struct AnchorFormat2 |
| 408 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 409 | void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id, |
| 410 | float *x, float *y) const |
Behdad Esfahbod | b24ecba | 2009-05-19 22:16:04 -0400 | [diff] [blame] | 411 | { |
Behdad Esfahbod | 49cb878 | 2016-09-09 16:27:03 -0700 | [diff] [blame] | 412 | hb_font_t *font = c->font; |
Behdad Esfahbod | c8f529a | 2019-06-19 19:33:15 -0700 | [diff] [blame] | 413 | |
| 414 | #ifdef HB_NO_HINTING |
| 415 | *x = font->em_fscale_x (xCoordinate); |
| 416 | *y = font->em_fscale_y (yCoordinate); |
| 417 | return; |
| 418 | #endif |
| 419 | |
Behdad Esfahbod | 49cb878 | 2016-09-09 16:27:03 -0700 | [diff] [blame] | 420 | unsigned int x_ppem = font->x_ppem; |
| 421 | unsigned int y_ppem = font->y_ppem; |
Ebrahim Byagowi | eaf6494 | 2018-04-23 18:39:40 +0430 | [diff] [blame] | 422 | hb_position_t cx = 0, cy = 0; |
Behdad Esfahbod | 385f78b | 2018-11-07 17:19:21 -0500 | [diff] [blame] | 423 | bool ret; |
Behdad Esfahbod | 6f729b4 | 2010-04-29 03:59:06 -0400 | [diff] [blame] | 424 | |
Behdad Esfahbod | 49cb878 | 2016-09-09 16:27:03 -0700 | [diff] [blame] | 425 | ret = (x_ppem || y_ppem) && |
Behdad Esfahbod | 385f78b | 2018-11-07 17:19:21 -0500 | [diff] [blame] | 426 | font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy); |
Behdad Esfahbod | 188ee6e | 2018-01-10 05:13:47 +0100 | [diff] [blame] | 427 | *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate); |
| 428 | *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 429 | } |
| 430 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 431 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 432 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 433 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 434 | return_trace (c->check_struct (this)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 435 | } |
| 436 | |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 437 | AnchorFormat2* copy (hb_serialize_context_t *c) const |
| 438 | { |
| 439 | TRACE_SERIALIZE (this); |
| 440 | return_trace (c->embed<AnchorFormat2> (this)); |
| 441 | } |
| 442 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 443 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 444 | HBUINT16 format; /* Format identifier--format = 2 */ |
Behdad Esfahbod | e347fb9 | 2018-02-26 01:08:00 -0800 | [diff] [blame] | 445 | FWORD xCoordinate; /* Horizontal value--in design units */ |
| 446 | FWORD yCoordinate; /* Vertical value--in design units */ |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 447 | HBUINT16 anchorPoint; /* Index to glyph contour point */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 448 | public: |
| 449 | DEFINE_SIZE_STATIC (8); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 450 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 451 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 452 | struct AnchorFormat3 |
| 453 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 454 | void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED, |
| 455 | float *x, float *y) const |
Behdad Esfahbod | b24ecba | 2009-05-19 22:16:04 -0400 | [diff] [blame] | 456 | { |
Behdad Esfahbod | 49cb878 | 2016-09-09 16:27:03 -0700 | [diff] [blame] | 457 | hb_font_t *font = c->font; |
Behdad Esfahbod | 188ee6e | 2018-01-10 05:13:47 +0100 | [diff] [blame] | 458 | *x = font->em_fscale_x (xCoordinate); |
| 459 | *y = font->em_fscale_y (yCoordinate); |
Behdad Esfahbod | c18ec2b | 2009-05-21 04:54:01 -0400 | [diff] [blame] | 460 | |
Behdad Esfahbod | 49cb878 | 2016-09-09 16:27:03 -0700 | [diff] [blame] | 461 | if (font->x_ppem || font->num_coords) |
Behdad Esfahbod | 151d93d | 2016-09-09 17:03:11 -0700 | [diff] [blame] | 462 | *x += (this+xDeviceTable).get_x_delta (font, c->var_store); |
Behdad Esfahbod | 49cb878 | 2016-09-09 16:27:03 -0700 | [diff] [blame] | 463 | if (font->y_ppem || font->num_coords) |
Behdad Esfahbod | 1124d2e | 2016-09-09 22:48:27 -0700 | [diff] [blame] | 464 | *y += (this+yDeviceTable).get_y_delta (font, c->var_store); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 465 | } |
| 466 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 467 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 468 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 469 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 470 | return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 471 | } |
| 472 | |
Qunxin Liu | d7c012a | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 473 | AnchorFormat3* copy (hb_serialize_context_t *c, |
| 474 | const hb_map_t *layout_variation_idx_map) const |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 475 | { |
| 476 | TRACE_SERIALIZE (this); |
Qunxin Liu | d7c012a | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 477 | if (!layout_variation_idx_map) return_trace (nullptr); |
| 478 | |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 479 | auto *out = c->embed<AnchorFormat3> (this); |
| 480 | if (unlikely (!out)) return_trace (nullptr); |
| 481 | |
Qunxin Liu | d7c012a | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 482 | out->xDeviceTable.serialize_copy (c, xDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map); |
| 483 | out->yDeviceTable.serialize_copy (c, yDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map); |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 484 | return_trace (out); |
| 485 | } |
| 486 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 487 | void collect_variation_indices (hb_collect_variation_indices_context_t *c) const |
| 488 | { |
| 489 | (this+xDeviceTable).collect_variation_indices (c->layout_variation_indices); |
| 490 | (this+yDeviceTable).collect_variation_indices (c->layout_variation_indices); |
| 491 | } |
| 492 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 493 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 494 | HBUINT16 format; /* Format identifier--format = 3 */ |
Behdad Esfahbod | e347fb9 | 2018-02-26 01:08:00 -0800 | [diff] [blame] | 495 | FWORD xCoordinate; /* Horizontal value--in design units */ |
| 496 | FWORD yCoordinate; /* Vertical value--in design units */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 497 | Offset16To<Device> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 498 | xDeviceTable; /* Offset to Device table for X |
| 499 | * coordinate-- from beginning of |
| 500 | * Anchor table (may be NULL) */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 501 | Offset16To<Device> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 502 | yDeviceTable; /* Offset to Device table for Y |
| 503 | * coordinate-- from beginning of |
| 504 | * Anchor table (may be NULL) */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 505 | public: |
| 506 | DEFINE_SIZE_STATIC (10); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 507 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 508 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 509 | struct Anchor |
| 510 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 511 | void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id, |
| 512 | float *x, float *y) const |
Behdad Esfahbod | b24ecba | 2009-05-19 22:16:04 -0400 | [diff] [blame] | 513 | { |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 514 | *x = *y = 0; |
| 515 | switch (u.format) { |
Behdad Esfahbod | 49cb878 | 2016-09-09 16:27:03 -0700 | [diff] [blame] | 516 | case 1: u.format1.get_anchor (c, glyph_id, x, y); return; |
| 517 | case 2: u.format2.get_anchor (c, glyph_id, x, y); return; |
| 518 | case 3: u.format3.get_anchor (c, glyph_id, x, y); return; |
Behdad Esfahbod | 7cdd6ab | 2018-01-10 04:33:08 +0100 | [diff] [blame] | 519 | default: return; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 520 | } |
| 521 | } |
| 522 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 523 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 524 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 525 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 526 | if (!u.format.sanitize (c)) return_trace (false); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 527 | switch (u.format) { |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 528 | case 1: return_trace (u.format1.sanitize (c)); |
| 529 | case 2: return_trace (u.format2.sanitize (c)); |
| 530 | case 3: return_trace (u.format3.sanitize (c)); |
| 531 | default:return_trace (true); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 532 | } |
| 533 | } |
| 534 | |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 535 | bool subset (hb_subset_context_t *c) const |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 536 | { |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 537 | TRACE_SUBSET (this); |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 538 | switch (u.format) { |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 539 | case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer)))); |
Garret Rieger | 92757f6 | 2021-04-22 15:18:35 -0700 | [diff] [blame] | 540 | case 2: |
Garret Rieger | 46d4a5e | 2021-07-29 15:07:13 -0700 | [diff] [blame] | 541 | if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING) |
Garret Rieger | 92757f6 | 2021-04-22 15:18:35 -0700 | [diff] [blame] | 542 | { |
| 543 | // AnchorFormat 2 just containins extra hinting information, so |
| 544 | // if hints are being dropped convert to format 1. |
| 545 | return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer)))); |
| 546 | } |
| 547 | return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer)))); |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 548 | case 3: return_trace (bool (reinterpret_cast<Anchor *> (u.format3.copy (c->serializer, |
Garret Rieger | 92757f6 | 2021-04-22 15:18:35 -0700 | [diff] [blame] | 549 | c->plan->layout_variation_idx_map)))); |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 550 | default:return_trace (false); |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 551 | } |
| 552 | } |
| 553 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 554 | void collect_variation_indices (hb_collect_variation_indices_context_t *c) const |
| 555 | { |
| 556 | switch (u.format) { |
| 557 | case 1: case 2: |
| 558 | return; |
| 559 | case 3: |
| 560 | u.format3.collect_variation_indices (c); |
| 561 | return; |
| 562 | default: return; |
| 563 | } |
| 564 | } |
| 565 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 566 | protected: |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 567 | union { |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 568 | HBUINT16 format; /* Format identifier */ |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 569 | AnchorFormat1 format1; |
| 570 | AnchorFormat2 format2; |
| 571 | AnchorFormat3 format3; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 572 | } u; |
Behdad Esfahbod | ed07422 | 2010-05-10 18:08:46 -0400 | [diff] [blame] | 573 | public: |
Behdad Esfahbod | 596e471 | 2010-05-10 18:47:48 -0400 | [diff] [blame] | 574 | DEFINE_SIZE_UNION (2, format); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 575 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 576 | |
| 577 | |
Behdad Esfahbod | cb71a2f | 2009-08-14 18:14:03 -0400 | [diff] [blame] | 578 | struct AnchorMatrix |
| 579 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 580 | const Anchor& get_anchor (unsigned int row, unsigned int col, |
| 581 | unsigned int cols, bool *found) const |
| 582 | { |
Behdad Esfahbod | e95e031 | 2013-01-08 16:15:46 -0600 | [diff] [blame] | 583 | *found = false; |
Ebrahim Byagowi | 2dda6dd | 2020-04-20 14:12:45 +0430 | [diff] [blame] | 584 | if (unlikely (row >= rows || col >= cols)) return Null (Anchor); |
Behdad Esfahbod | 093c520 | 2014-12-12 21:07:53 -0800 | [diff] [blame] | 585 | *found = !matrixZ[row * cols + col].is_null (); |
| 586 | return this+matrixZ[row * cols + col]; |
Behdad Esfahbod | cb71a2f | 2009-08-14 18:14:03 -0400 | [diff] [blame] | 587 | } |
| 588 | |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 589 | template <typename Iterator, |
| 590 | hb_requires (hb_is_iterator (Iterator))> |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 591 | void collect_variation_indices (hb_collect_variation_indices_context_t *c, |
| 592 | Iterator index_iter) const |
| 593 | { |
| 594 | for (unsigned i : index_iter) |
| 595 | (this+matrixZ[i]).collect_variation_indices (c); |
| 596 | } |
| 597 | |
| 598 | template <typename Iterator, |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 599 | hb_requires (hb_is_iterator (Iterator))> |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 600 | bool subset (hb_subset_context_t *c, |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 601 | unsigned num_rows, |
| 602 | Iterator index_iter) const |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 603 | { |
| 604 | TRACE_SUBSET (this); |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 605 | |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 606 | auto *out = c->serializer->start_embed (this); |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 607 | |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 608 | if (!index_iter) return_trace (false); |
| 609 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
| 610 | |
| 611 | out->rows = num_rows; |
| 612 | for (const unsigned i : index_iter) |
| 613 | { |
| 614 | auto *offset = c->serializer->embed (matrixZ[i]); |
| 615 | if (!offset) return_trace (false); |
| 616 | offset->serialize_subset (c, matrixZ[i], this); |
| 617 | } |
| 618 | |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 619 | return_trace (true); |
| 620 | } |
| 621 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 622 | bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 623 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 624 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 625 | if (!c->check_struct (this)) return_trace (false); |
Behdad Esfahbod | bddeb2b | 2018-07-10 14:12:37 +0200 | [diff] [blame] | 626 | if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false); |
Behdad Esfahbod | cb71a2f | 2009-08-14 18:14:03 -0400 | [diff] [blame] | 627 | unsigned int count = rows * cols; |
Behdad Esfahbod | dff2c45 | 2018-09-10 23:29:26 +0200 | [diff] [blame] | 628 | if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false); |
Behdad Esfahbod | cb71a2f | 2009-08-14 18:14:03 -0400 | [diff] [blame] | 629 | for (unsigned int i = 0; i < count; i++) |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 630 | if (!matrixZ[i].sanitize (c, this)) return_trace (false); |
| 631 | return_trace (true); |
Behdad Esfahbod | cb71a2f | 2009-08-14 18:14:03 -0400 | [diff] [blame] | 632 | } |
| 633 | |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 634 | HBUINT16 rows; /* Number of rows */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 635 | UnsizedArrayOf<Offset16To<Anchor>> |
Behdad Esfahbod | dff2c45 | 2018-09-10 23:29:26 +0200 | [diff] [blame] | 636 | matrixZ; /* Matrix of offsets to Anchor tables-- |
Behdad Esfahbod | cb71a2f | 2009-08-14 18:14:03 -0400 | [diff] [blame] | 637 | * from beginning of AnchorMatrix table */ |
Behdad Esfahbod | 569da92 | 2010-05-10 16:38:32 -0400 | [diff] [blame] | 638 | public: |
Behdad Esfahbod | 093c520 | 2014-12-12 21:07:53 -0800 | [diff] [blame] | 639 | DEFINE_SIZE_ARRAY (2, matrixZ); |
Behdad Esfahbod | cb71a2f | 2009-08-14 18:14:03 -0400 | [diff] [blame] | 640 | }; |
Behdad Esfahbod | cb71a2f | 2009-08-14 18:14:03 -0400 | [diff] [blame] | 641 | |
| 642 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 643 | struct MarkRecord |
| 644 | { |
Behdad Esfahbod | 377bfc5 | 2009-05-21 04:58:24 -0400 | [diff] [blame] | 645 | friend struct MarkArray; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 646 | |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 647 | unsigned get_class () const { return (unsigned) klass; } |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 648 | bool sanitize (hb_sanitize_context_t *c, const void *base) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 649 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 650 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 651 | return_trace (c->check_struct (this) && markAnchor.sanitize (c, base)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 652 | } |
| 653 | |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 654 | MarkRecord *subset (hb_subset_context_t *c, |
| 655 | const void *src_base, |
| 656 | const hb_map_t *klass_mapping) const |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 657 | { |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 658 | TRACE_SUBSET (this); |
| 659 | auto *out = c->serializer->embed (this); |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 660 | if (unlikely (!out)) return_trace (nullptr); |
Ebrahim Byagowi | 07acd1a | 2020-03-08 23:39:24 +0330 | [diff] [blame] | 661 | |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 662 | out->klass = klass_mapping->get (klass); |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 663 | out->markAnchor.serialize_subset (c, markAnchor, src_base); |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 664 | return_trace (out); |
| 665 | } |
| 666 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 667 | void collect_variation_indices (hb_collect_variation_indices_context_t *c, |
| 668 | const void *src_base) const |
| 669 | { |
| 670 | (src_base+markAnchor).collect_variation_indices (c); |
| 671 | } |
| 672 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 673 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 674 | HBUINT16 klass; /* Class defined for this mark */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 675 | Offset16To<Anchor> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 676 | markAnchor; /* Offset to Anchor table--from |
| 677 | * beginning of MarkArray table */ |
Behdad Esfahbod | 569da92 | 2010-05-10 16:38:32 -0400 | [diff] [blame] | 678 | public: |
| 679 | DEFINE_SIZE_STATIC (4); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 680 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 681 | |
Behdad Esfahbod | 5639e25 | 2021-03-31 16:04:43 -0600 | [diff] [blame] | 682 | struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */ |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 683 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 684 | bool apply (hb_ot_apply_context_t *c, |
| 685 | unsigned int mark_index, unsigned int glyph_index, |
| 686 | const AnchorMatrix &anchors, unsigned int class_count, |
| 687 | unsigned int glyph_pos) const |
Behdad Esfahbod | b41f210 | 2009-08-14 19:33:24 -0400 | [diff] [blame] | 688 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 689 | TRACE_APPLY (this); |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 690 | hb_buffer_t *buffer = c->buffer; |
Behdad Esfahbod | 5639e25 | 2021-03-31 16:04:43 -0600 | [diff] [blame] | 691 | const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index); |
Behdad Esfahbod | b41f210 | 2009-08-14 19:33:24 -0400 | [diff] [blame] | 692 | unsigned int mark_class = record.klass; |
| 693 | |
| 694 | const Anchor& mark_anchor = this + record.markAnchor; |
Behdad Esfahbod | e95e031 | 2013-01-08 16:15:46 -0600 | [diff] [blame] | 695 | bool found; |
| 696 | const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found); |
| 697 | /* If this subtable doesn't have an anchor for this base and this class, |
| 698 | * return false such that the subsequent subtables have a chance at it. */ |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 699 | if (unlikely (!found)) return_trace (false); |
Behdad Esfahbod | b41f210 | 2009-08-14 19:33:24 -0400 | [diff] [blame] | 700 | |
Behdad Esfahbod | 188ee6e | 2018-01-10 05:13:47 +0100 | [diff] [blame] | 701 | float mark_x, mark_y, base_x, base_y; |
Behdad Esfahbod | b41f210 | 2009-08-14 19:33:24 -0400 | [diff] [blame] | 702 | |
Behdad Esfahbod | b65aa1c | 2017-08-10 20:32:02 -0700 | [diff] [blame] | 703 | buffer->unsafe_to_break (glyph_pos, buffer->idx); |
Behdad Esfahbod | 49cb878 | 2016-09-09 16:27:03 -0700 | [diff] [blame] | 704 | mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y); |
| 705 | glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y); |
Behdad Esfahbod | b41f210 | 2009-08-14 19:33:24 -0400 | [diff] [blame] | 706 | |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 707 | hb_glyph_position_t &o = buffer->cur_pos(); |
Behdad Esfahbod | dfc5780 | 2019-05-07 23:26:09 -0700 | [diff] [blame] | 708 | o.x_offset = roundf (base_x - mark_x); |
| 709 | o.y_offset = roundf (base_y - mark_y); |
Behdad Esfahbod | 686567b | 2016-02-11 15:25:28 +0700 | [diff] [blame] | 710 | o.attach_type() = ATTACH_TYPE_MARK; |
Behdad Esfahbod | 0f6278d | 2016-02-11 14:49:10 +0700 | [diff] [blame] | 711 | o.attach_chain() = (int) glyph_pos - (int) buffer->idx; |
Behdad Esfahbod | 550bd14 | 2015-11-04 22:58:58 -0800 | [diff] [blame] | 712 | buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; |
Behdad Esfahbod | b41f210 | 2009-08-14 19:33:24 -0400 | [diff] [blame] | 713 | |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 714 | buffer->idx++; |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 715 | return_trace (true); |
Behdad Esfahbod | b41f210 | 2009-08-14 19:33:24 -0400 | [diff] [blame] | 716 | } |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 717 | |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 718 | template <typename Iterator, |
| 719 | hb_requires (hb_is_iterator (Iterator))> |
| 720 | bool subset (hb_subset_context_t *c, |
| 721 | Iterator coverage, |
| 722 | const hb_map_t *klass_mapping) const |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 723 | { |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 724 | TRACE_SUBSET (this); |
| 725 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
| 726 | |
| 727 | auto* out = c->serializer->start_embed (this); |
| 728 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
| 729 | |
| 730 | auto mark_iter = |
| 731 | + hb_zip (coverage, this->iter ()) |
| 732 | | hb_filter (glyphset, hb_first) |
| 733 | | hb_map (hb_second) |
| 734 | ; |
| 735 | |
| 736 | unsigned new_length = 0; |
| 737 | for (const auto& mark_record : mark_iter) { |
| 738 | if (unlikely (!mark_record.subset (c, this, klass_mapping))) |
| 739 | return_trace (false); |
| 740 | new_length++; |
| 741 | } |
| 742 | |
| 743 | if (unlikely (!c->serializer->check_assign (out->len, new_length, |
| 744 | HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) |
| 745 | return_trace (false); |
| 746 | |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 747 | return_trace (true); |
| 748 | } |
| 749 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 750 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 751 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 752 | TRACE_SANITIZE (this); |
Behdad Esfahbod | 5639e25 | 2021-03-31 16:04:43 -0600 | [diff] [blame] | 753 | return_trace (Array16Of<MarkRecord>::sanitize (c, this)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 754 | } |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 755 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 756 | |
| 757 | |
| 758 | /* Lookups */ |
| 759 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 760 | struct SinglePosFormat1 |
| 761 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 762 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 763 | { return (this+coverage).intersects (glyphs); } |
| 764 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 765 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 766 | void collect_variation_indices (hb_collect_variation_indices_context_t *c) const |
| 767 | { |
| 768 | if (!valueFormat.has_device ()) return; |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 769 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 770 | auto it = |
| 771 | + hb_iter (this+coverage) |
| 772 | | hb_filter (c->glyph_set) |
| 773 | ; |
| 774 | |
| 775 | if (!it) return; |
| 776 | valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ())); |
| 777 | } |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 778 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 779 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 780 | { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; } |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 781 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 782 | const Coverage &get_coverage () const { return this+coverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 783 | |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 784 | ValueFormat get_value_format () const { return valueFormat; } |
| 785 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 786 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | b24ecba | 2009-05-19 22:16:04 -0400 | [diff] [blame] | 787 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 788 | TRACE_APPLY (this); |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 789 | hb_buffer_t *buffer = c->buffer; |
| 790 | unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 791 | if (likely (index == NOT_COVERED)) return_trace (false); |
Behdad Esfahbod | 056c7ec | 2009-05-18 19:47:52 -0400 | [diff] [blame] | 792 | |
Behdad Esfahbod | 151d93d | 2016-09-09 17:03:11 -0700 | [diff] [blame] | 793 | valueFormat.apply_value (c, this, values, buffer->cur_pos()); |
Behdad Esfahbod | f53d434 | 2009-05-30 22:17:32 -0400 | [diff] [blame] | 794 | |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 795 | buffer->idx++; |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 796 | return_trace (true); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 797 | } |
| 798 | |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 799 | template<typename Iterator, |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 800 | typename SrcLookup, |
| 801 | hb_requires (hb_is_iterator (Iterator))> |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 802 | void serialize (hb_serialize_context_t *c, |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 803 | const SrcLookup *src, |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 804 | Iterator it, |
Garret Rieger | 2f50283 | 2021-04-23 15:21:30 -0700 | [diff] [blame] | 805 | ValueFormat newFormat, |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 806 | const hb_map_t *layout_variation_idx_map) |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 807 | { |
Behdad Esfahbod | f0a1892 | 2021-07-28 17:36:22 -0600 | [diff] [blame] | 808 | if (unlikely (!c->extend_min (this))) return; |
Garret Rieger | 5df7c66 | 2021-04-22 16:45:14 -0700 | [diff] [blame] | 809 | if (unlikely (!c->check_assign (valueFormat, |
Garret Rieger | 2f50283 | 2021-04-23 15:21:30 -0700 | [diff] [blame] | 810 | newFormat, |
Garret Rieger | 5df7c66 | 2021-04-22 16:45:14 -0700 | [diff] [blame] | 811 | HB_SERIALIZE_ERROR_INT_OVERFLOW))) return; |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 812 | |
Garret Rieger | 5df7c66 | 2021-04-22 16:45:14 -0700 | [diff] [blame] | 813 | for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second)) |
| 814 | { |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 815 | src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); |
Garret Rieger | 5df7c66 | 2021-04-22 16:45:14 -0700 | [diff] [blame] | 816 | // Only serialize the first entry in the iterator, the rest are assumed to |
| 817 | // be the same. |
| 818 | break; |
| 819 | } |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 820 | |
| 821 | auto glyphs = |
| 822 | + it |
| 823 | | hb_map_retains_sorting (hb_first) |
| 824 | ; |
| 825 | |
Garret Rieger | 8443cc8 | 2021-06-11 13:40:39 -0700 | [diff] [blame] | 826 | coverage.serialize_serialize (c, glyphs); |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 827 | } |
| 828 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 829 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 830 | { |
| 831 | TRACE_SUBSET (this); |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 832 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 833 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 834 | |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 835 | auto it = |
| 836 | + hb_iter (this+coverage) |
| 837 | | hb_filter (glyphset) |
Behdad Esfahbod | 3c81246 | 2019-09-01 19:25:50 -0500 | [diff] [blame] | 838 | | hb_map_retains_sorting (glyph_map) |
| 839 | | hb_zip (hb_repeat (values.as_array (valueFormat.get_len ()))) |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 840 | ; |
| 841 | |
| 842 | bool ret = bool (it); |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 843 | SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map); |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 844 | return_trace (ret); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 845 | } |
| 846 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 847 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 848 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 849 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 850 | return_trace (c->check_struct (this) && |
| 851 | coverage.sanitize (c, this) && |
| 852 | valueFormat.sanitize_value (c, this, values)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 853 | } |
| 854 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 855 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 856 | HBUINT16 format; /* Format identifier--format = 1 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 857 | Offset16To<Coverage> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 858 | coverage; /* Offset to Coverage table--from |
| 859 | * beginning of subtable */ |
Behdad Esfahbod | 056c7ec | 2009-05-18 19:47:52 -0400 | [diff] [blame] | 860 | ValueFormat valueFormat; /* Defines the types of data in the |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 861 | * ValueRecord */ |
| 862 | ValueRecord values; /* Defines positioning |
| 863 | * value(s)--applied to all glyphs in |
| 864 | * the Coverage table */ |
Behdad Esfahbod | 569da92 | 2010-05-10 16:38:32 -0400 | [diff] [blame] | 865 | public: |
Behdad Esfahbod | 0eb9fc6 | 2010-05-10 19:01:17 -0400 | [diff] [blame] | 866 | DEFINE_SIZE_ARRAY (6, values); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 867 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 868 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 869 | struct SinglePosFormat2 |
| 870 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 871 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 872 | { return (this+coverage).intersects (glyphs); } |
| 873 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 874 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 875 | void collect_variation_indices (hb_collect_variation_indices_context_t *c) const |
| 876 | { |
| 877 | if (!valueFormat.has_device ()) return; |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 878 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 879 | auto it = |
| 880 | + hb_zip (this+coverage, hb_range ((unsigned) valueCount)) |
| 881 | | hb_filter (c->glyph_set, hb_first) |
| 882 | ; |
| 883 | |
| 884 | if (!it) return; |
| 885 | |
| 886 | unsigned sub_length = valueFormat.get_len (); |
| 887 | const hb_array_t<const Value> values_array = values.as_array (valueCount * sub_length); |
| 888 | |
| 889 | for (unsigned i : + it |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 890 | | hb_map (hb_second)) |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 891 | valueFormat.collect_variation_indices (c, this, values_array.sub_array (i * sub_length, sub_length)); |
| 892 | |
| 893 | } |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 894 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 895 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 896 | { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; } |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 897 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 898 | const Coverage &get_coverage () const { return this+coverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 899 | |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 900 | ValueFormat get_value_format () const { return valueFormat; } |
| 901 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 902 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | b24ecba | 2009-05-19 22:16:04 -0400 | [diff] [blame] | 903 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 904 | TRACE_APPLY (this); |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 905 | hb_buffer_t *buffer = c->buffer; |
| 906 | unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 907 | if (likely (index == NOT_COVERED)) return_trace (false); |
Behdad Esfahbod | 056c7ec | 2009-05-18 19:47:52 -0400 | [diff] [blame] | 908 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 909 | if (likely (index >= valueCount)) return_trace (false); |
Behdad Esfahbod | 056c7ec | 2009-05-18 19:47:52 -0400 | [diff] [blame] | 910 | |
Behdad Esfahbod | 151d93d | 2016-09-09 17:03:11 -0700 | [diff] [blame] | 911 | valueFormat.apply_value (c, this, |
Behdad Esfahbod | 4b8487d | 2010-03-16 03:46:17 -0400 | [diff] [blame] | 912 | &values[index * valueFormat.get_len ()], |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 913 | buffer->cur_pos()); |
Behdad Esfahbod | f53d434 | 2009-05-30 22:17:32 -0400 | [diff] [blame] | 914 | |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 915 | buffer->idx++; |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 916 | return_trace (true); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 917 | } |
| 918 | |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 919 | template<typename Iterator, |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 920 | typename SrcLookup, |
| 921 | hb_requires (hb_is_iterator (Iterator))> |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 922 | void serialize (hb_serialize_context_t *c, |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 923 | const SrcLookup *src, |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 924 | Iterator it, |
Garret Rieger | 2f50283 | 2021-04-23 15:21:30 -0700 | [diff] [blame] | 925 | ValueFormat newFormat, |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 926 | const hb_map_t *layout_variation_idx_map) |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 927 | { |
Behdad Esfahbod | f0a1892 | 2021-07-28 17:36:22 -0600 | [diff] [blame] | 928 | auto out = c->extend_min (this); |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 929 | if (unlikely (!out)) return; |
Garret Rieger | 2f50283 | 2021-04-23 15:21:30 -0700 | [diff] [blame] | 930 | if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return; |
Garret Rieger | b14475d | 2021-03-18 10:51:26 -0700 | [diff] [blame] | 931 | if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return; |
Ebrahim Byagowi | a0b4ac4 | 2019-08-24 17:57:14 +0430 | [diff] [blame] | 932 | |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 933 | + it |
| 934 | | hb_map (hb_second) |
| 935 | | hb_apply ([&] (hb_array_t<const Value> _) |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 936 | { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); }) |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 937 | ; |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 938 | |
| 939 | auto glyphs = |
| 940 | + it |
| 941 | | hb_map_retains_sorting (hb_first) |
| 942 | ; |
Ebrahim Byagowi | a0b4ac4 | 2019-08-24 17:57:14 +0430 | [diff] [blame] | 943 | |
Garret Rieger | 8443cc8 | 2021-06-11 13:40:39 -0700 | [diff] [blame] | 944 | coverage.serialize_serialize (c, glyphs); |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 945 | } |
| 946 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 947 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 948 | { |
| 949 | TRACE_SUBSET (this); |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 950 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 951 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 952 | |
| 953 | unsigned sub_length = valueFormat.get_len (); |
Behdad Esfahbod | e0e0c8c | 2019-08-29 14:58:16 -0700 | [diff] [blame] | 954 | auto values_array = values.as_array (valueCount * sub_length); |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 955 | |
| 956 | auto it = |
| 957 | + hb_zip (this+coverage, hb_range ((unsigned) valueCount)) |
| 958 | | hb_filter (glyphset, hb_first) |
| 959 | | hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _) |
Ebrahim Byagowi | a0b4ac4 | 2019-08-24 17:57:14 +0430 | [diff] [blame] | 960 | { |
Behdad Esfahbod | e0e0c8c | 2019-08-29 14:58:16 -0700 | [diff] [blame] | 961 | return hb_pair (glyph_map[_.first], |
| 962 | values_array.sub_array (_.second * sub_length, |
| 963 | sub_length)); |
Ebrahim Byagowi | a0b4ac4 | 2019-08-24 17:57:14 +0430 | [diff] [blame] | 964 | }) |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 965 | ; |
| 966 | |
| 967 | bool ret = bool (it); |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 968 | SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map); |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 969 | return_trace (ret); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 970 | } |
| 971 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 972 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 973 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 974 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 975 | return_trace (c->check_struct (this) && |
| 976 | coverage.sanitize (c, this) && |
| 977 | valueFormat.sanitize_values (c, this, values, valueCount)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 978 | } |
| 979 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 980 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 981 | HBUINT16 format; /* Format identifier--format = 2 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 982 | Offset16To<Coverage> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 983 | coverage; /* Offset to Coverage table--from |
| 984 | * beginning of subtable */ |
Behdad Esfahbod | 056c7ec | 2009-05-18 19:47:52 -0400 | [diff] [blame] | 985 | ValueFormat valueFormat; /* Defines the types of data in the |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 986 | * ValueRecord */ |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 987 | HBUINT16 valueCount; /* Number of ValueRecords */ |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 988 | ValueRecord values; /* Array of ValueRecords--positioning |
| 989 | * values applied to glyphs */ |
Behdad Esfahbod | 569da92 | 2010-05-10 16:38:32 -0400 | [diff] [blame] | 990 | public: |
Behdad Esfahbod | 0eb9fc6 | 2010-05-10 19:01:17 -0400 | [diff] [blame] | 991 | DEFINE_SIZE_ARRAY (8, values); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 992 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 993 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 994 | struct SinglePos |
| 995 | { |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 996 | template<typename Iterator, |
| 997 | hb_requires (hb_is_iterator (Iterator))> |
| 998 | unsigned get_format (Iterator glyph_val_iter_pairs) |
| 999 | { |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 1000 | hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs); |
| 1001 | |
Ebrahim Byagowi | 68d39ea | 2019-09-24 13:52:46 +0330 | [diff] [blame] | 1002 | for (const auto iter : glyph_val_iter_pairs) |
| 1003 | for (const auto _ : hb_zip (iter.second, first_val_iter)) |
Ebrahim Byagowi | 6e42a41 | 2019-09-21 16:25:54 +0430 | [diff] [blame] | 1004 | if (_.first != _.second) |
Ebrahim Byagowi | c1a585f | 2019-09-21 23:30:52 +0430 | [diff] [blame] | 1005 | return 2; |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 1006 | |
Ebrahim Byagowi | c1a585f | 2019-09-21 23:30:52 +0430 | [diff] [blame] | 1007 | return 1; |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 1008 | } |
| 1009 | |
| 1010 | |
| 1011 | template<typename Iterator, |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1012 | typename SrcLookup, |
| 1013 | hb_requires (hb_is_iterator (Iterator))> |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 1014 | void serialize (hb_serialize_context_t *c, |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1015 | const SrcLookup* src, |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 1016 | Iterator glyph_val_iter_pairs, |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 1017 | const hb_map_t *layout_variation_idx_map) |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 1018 | { |
| 1019 | if (unlikely (!c->extend_min (u.format))) return; |
| 1020 | unsigned format = 2; |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1021 | ValueFormat new_format = src->get_value_format (); |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 1022 | |
Garret Rieger | 2f50283 | 2021-04-23 15:21:30 -0700 | [diff] [blame] | 1023 | if (glyph_val_iter_pairs) |
| 1024 | { |
| 1025 | format = get_format (glyph_val_iter_pairs); |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1026 | new_format = src->get_value_format ().get_effective_format (+ glyph_val_iter_pairs | hb_map (hb_second)); |
Garret Rieger | 2f50283 | 2021-04-23 15:21:30 -0700 | [diff] [blame] | 1027 | } |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 1028 | |
| 1029 | u.format = format; |
| 1030 | switch (u.format) { |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1031 | case 1: u.format1.serialize (c, |
Garret Rieger | 2f50283 | 2021-04-23 15:21:30 -0700 | [diff] [blame] | 1032 | src, |
| 1033 | glyph_val_iter_pairs, |
| 1034 | new_format, |
| 1035 | layout_variation_idx_map); |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1036 | return; |
| 1037 | case 2: u.format2.serialize (c, |
| 1038 | src, |
| 1039 | glyph_val_iter_pairs, |
| 1040 | new_format, |
| 1041 | layout_variation_idx_map); |
| 1042 | return; |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 1043 | default:return; |
| 1044 | } |
| 1045 | } |
| 1046 | |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 1047 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 1048 | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1049 | { |
Behdad Esfahbod | 00f6a8e | 2014-12-12 20:36:49 -0800 | [diff] [blame] | 1050 | TRACE_DISPATCH (this, u.format); |
Behdad Esfahbod | f396fbb | 2015-10-09 12:25:55 -0400 | [diff] [blame] | 1051 | if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1052 | switch (u.format) { |
Behdad Esfahbod | 6d555ce | 2021-11-02 00:18:22 -0600 | [diff] [blame] | 1053 | case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); |
| 1054 | case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1055 | default:return_trace (c->default_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1056 | } |
| 1057 | } |
| 1058 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1059 | protected: |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1060 | union { |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1061 | HBUINT16 format; /* Format identifier */ |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 1062 | SinglePosFormat1 format1; |
| 1063 | SinglePosFormat2 format2; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1064 | } u; |
| 1065 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1066 | |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1067 | template<typename Iterator, typename SrcLookup> |
Behdad Esfahbod | dd3972a | 2019-12-10 13:21:26 -0600 | [diff] [blame] | 1068 | static void |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 1069 | SinglePos_serialize (hb_serialize_context_t *c, |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1070 | const SrcLookup *src, |
Ebrahim Byagowi | a0b4ac4 | 2019-08-24 17:57:14 +0430 | [diff] [blame] | 1071 | Iterator it, |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 1072 | const hb_map_t *layout_variation_idx_map) |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1073 | { c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_map); } |
Qunxin Liu | 321d558 | 2019-07-02 16:30:57 -0700 | [diff] [blame] | 1074 | |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1075 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1076 | struct PairValueRecord |
| 1077 | { |
Behdad Esfahbod | 70c9bfd | 2010-05-11 00:23:50 -0400 | [diff] [blame] | 1078 | friend struct PairSet; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1079 | |
Behdad Esfahbod | 39afe60 | 2019-12-10 12:04:44 -0600 | [diff] [blame] | 1080 | int cmp (hb_codepoint_t k) const |
| 1081 | { return secondGlyph.cmp (k); } |
| 1082 | |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1083 | struct context_t |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 1084 | { |
Ebrahim Byagowi | 07acd1a | 2020-03-08 23:39:24 +0330 | [diff] [blame] | 1085 | const void *base; |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 1086 | const ValueFormat *valueFormats; |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1087 | const ValueFormat *newFormats; |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 1088 | unsigned len1; /* valueFormats[0].get_len() */ |
| 1089 | const hb_map_t *glyph_map; |
Qunxin Liu | d7c012a | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1090 | const hb_map_t *layout_variation_idx_map; |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 1091 | }; |
| 1092 | |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1093 | bool subset (hb_subset_context_t *c, |
| 1094 | context_t *closure) const |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1095 | { |
| 1096 | TRACE_SERIALIZE (this); |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1097 | auto *s = c->serializer; |
| 1098 | auto *out = s->start_embed (*this); |
| 1099 | if (unlikely (!s->extend_min (out))) return_trace (false); |
Behdad Esfahbod | 39afe60 | 2019-12-10 12:04:44 -0600 | [diff] [blame] | 1100 | |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 1101 | out->secondGlyph = (*closure->glyph_map)[secondGlyph]; |
| 1102 | |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1103 | closure->valueFormats[0].copy_values (s, |
| 1104 | closure->newFormats[0], |
| 1105 | closure->base, &values[0], |
| 1106 | closure->layout_variation_idx_map); |
| 1107 | closure->valueFormats[1].copy_values (s, |
| 1108 | closure->newFormats[1], |
| 1109 | closure->base, |
| 1110 | &values[closure->len1], |
| 1111 | closure->layout_variation_idx_map); |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 1112 | |
| 1113 | return_trace (true); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1114 | } |
| 1115 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1116 | void collect_variation_indices (hb_collect_variation_indices_context_t *c, |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 1117 | const ValueFormat *valueFormats, |
| 1118 | const void *base) const |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1119 | { |
| 1120 | unsigned record1_len = valueFormats[0].get_len (); |
| 1121 | unsigned record2_len = valueFormats[1].get_len (); |
| 1122 | const hb_array_t<const Value> values_array = values.as_array (record1_len + record2_len); |
| 1123 | |
| 1124 | if (valueFormats[0].has_device ()) |
| 1125 | valueFormats[0].collect_variation_indices (c, base, values_array.sub_array (0, record1_len)); |
| 1126 | |
| 1127 | if (valueFormats[1].has_device ()) |
| 1128 | valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len)); |
| 1129 | } |
| 1130 | |
Garret Rieger | d356d0f | 2021-04-23 17:41:09 -0700 | [diff] [blame] | 1131 | bool intersects (const hb_set_t& glyphset) const |
| 1132 | { |
| 1133 | return glyphset.has(secondGlyph); |
| 1134 | } |
| 1135 | |
| 1136 | const Value* get_values_1 () const |
| 1137 | { |
| 1138 | return &values[0]; |
| 1139 | } |
| 1140 | |
| 1141 | const Value* get_values_2 (ValueFormat format1) const |
| 1142 | { |
| 1143 | return &values[format1.get_len ()]; |
| 1144 | } |
| 1145 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1146 | protected: |
Behdad Esfahbod | c852b86 | 2021-09-19 16:30:12 -0400 | [diff] [blame] | 1147 | HBGlyphID16 secondGlyph; /* GlyphID of second glyph in the |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1148 | * pair--first glyph is listed in the |
| 1149 | * Coverage table */ |
| 1150 | ValueRecord values; /* Positioning data for the first glyph |
| 1151 | * followed by for second glyph */ |
Behdad Esfahbod | 569da92 | 2010-05-10 16:38:32 -0400 | [diff] [blame] | 1152 | public: |
Behdad Esfahbod | 0eb9fc6 | 2010-05-10 19:01:17 -0400 | [diff] [blame] | 1153 | DEFINE_SIZE_ARRAY (2, values); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1154 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1155 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1156 | struct PairSet |
| 1157 | { |
Behdad Esfahbod | b24ecba | 2009-05-19 22:16:04 -0400 | [diff] [blame] | 1158 | friend struct PairPosFormat1; |
| 1159 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1160 | bool intersects (const hb_set_t *glyphs, |
Behdad Esfahbod | 9d8c720 | 2019-03-29 21:59:28 -0700 | [diff] [blame] | 1161 | const ValueFormat *valueFormats) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1162 | { |
Behdad Esfahbod | fb05908 | 2018-11-30 20:45:40 -0500 | [diff] [blame] | 1163 | unsigned int len1 = valueFormats[0].get_len (); |
| 1164 | unsigned int len2 = valueFormats[1].get_len (); |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1165 | unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2); |
| 1166 | |
Behdad Esfahbod | dff2c45 | 2018-09-10 23:29:26 +0200 | [diff] [blame] | 1167 | const PairValueRecord *record = &firstPairValueRecord; |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1168 | unsigned int count = len; |
| 1169 | for (unsigned int i = 0; i < count; i++) |
| 1170 | { |
| 1171 | if (glyphs->has (record->secondGlyph)) |
Ebrahim Byagowi | 11aa046 | 2018-11-15 23:10:56 +0330 | [diff] [blame] | 1172 | return true; |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1173 | record = &StructAtOffset<const PairValueRecord> (record, record_size); |
| 1174 | } |
| 1175 | return false; |
| 1176 | } |
| 1177 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1178 | void collect_glyphs (hb_collect_glyphs_context_t *c, |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 1179 | const ValueFormat *valueFormats) const |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 1180 | { |
Behdad Esfahbod | fb05908 | 2018-11-30 20:45:40 -0500 | [diff] [blame] | 1181 | unsigned int len1 = valueFormats[0].get_len (); |
| 1182 | unsigned int len2 = valueFormats[1].get_len (); |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1183 | unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2); |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 1184 | |
Behdad Esfahbod | dff2c45 | 2018-09-10 23:29:26 +0200 | [diff] [blame] | 1185 | const PairValueRecord *record = &firstPairValueRecord; |
Behdad Esfahbod | 81f27df | 2017-12-16 06:12:06 -0800 | [diff] [blame] | 1186 | c->input->add_array (&record->secondGlyph, len, record_size); |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 1187 | } |
| 1188 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1189 | void collect_variation_indices (hb_collect_variation_indices_context_t *c, |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 1190 | const ValueFormat *valueFormats) const |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1191 | { |
| 1192 | unsigned len1 = valueFormats[0].get_len (); |
| 1193 | unsigned len2 = valueFormats[1].get_len (); |
| 1194 | unsigned record_size = HBUINT16::static_size * (1 + len1 + len2); |
| 1195 | |
| 1196 | const PairValueRecord *record = &firstPairValueRecord; |
| 1197 | unsigned count = len; |
| 1198 | for (unsigned i = 0; i < count; i++) |
| 1199 | { |
| 1200 | if (c->glyph_set->has (record->secondGlyph)) |
| 1201 | { record->collect_variation_indices (c, valueFormats, this); } |
| 1202 | |
| 1203 | record = &StructAtOffset<const PairValueRecord> (record, record_size); |
| 1204 | } |
| 1205 | } |
| 1206 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1207 | bool apply (hb_ot_apply_context_t *c, |
Behdad Esfahbod | 39afe60 | 2019-12-10 12:04:44 -0600 | [diff] [blame] | 1208 | const ValueFormat *valueFormats, |
| 1209 | unsigned int pos) const |
Behdad Esfahbod | 70c9bfd | 2010-05-11 00:23:50 -0400 | [diff] [blame] | 1210 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1211 | TRACE_APPLY (this); |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 1212 | hb_buffer_t *buffer = c->buffer; |
Behdad Esfahbod | fb05908 | 2018-11-30 20:45:40 -0500 | [diff] [blame] | 1213 | unsigned int len1 = valueFormats[0].get_len (); |
| 1214 | unsigned int len2 = valueFormats[1].get_len (); |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1215 | unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2); |
Behdad Esfahbod | 70c9bfd | 2010-05-11 00:23:50 -0400 | [diff] [blame] | 1216 | |
Behdad Esfahbod | 39afe60 | 2019-12-10 12:04:44 -0600 | [diff] [blame] | 1217 | const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint, |
| 1218 | &firstPairValueRecord, |
| 1219 | len, |
| 1220 | record_size); |
| 1221 | if (record) |
Behdad Esfahbod | 70c9bfd | 2010-05-11 00:23:50 -0400 | [diff] [blame] | 1222 | { |
Nico Weber | 96299d7 | 2021-10-12 10:42:43 -0400 | [diff] [blame] | 1223 | bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); |
| 1224 | bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); |
| 1225 | if (applied_first || applied_second) |
Behdad Esfahbod | 39afe60 | 2019-12-10 12:04:44 -0600 | [diff] [blame] | 1226 | buffer->unsafe_to_break (buffer->idx, pos + 1); |
| 1227 | if (len2) |
| 1228 | pos++; |
| 1229 | buffer->idx = pos; |
| 1230 | return_trace (true); |
Behdad Esfahbod | 70c9bfd | 2010-05-11 00:23:50 -0400 | [diff] [blame] | 1231 | } |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1232 | return_trace (false); |
Behdad Esfahbod | 70c9bfd | 2010-05-11 00:23:50 -0400 | [diff] [blame] | 1233 | } |
| 1234 | |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1235 | bool subset (hb_subset_context_t *c, |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1236 | const ValueFormat valueFormats[2], |
| 1237 | const ValueFormat newFormats[2]) const |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1238 | { |
| 1239 | TRACE_SUBSET (this); |
| 1240 | auto snap = c->serializer->snapshot (); |
| 1241 | |
| 1242 | auto *out = c->serializer->start_embed (*this); |
| 1243 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
| 1244 | out->len = 0; |
| 1245 | |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 1246 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1247 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 1248 | |
Qunxin Liu | defe9b6 | 2019-10-25 10:07:26 -0700 | [diff] [blame] | 1249 | unsigned len1 = valueFormats[0].get_len (); |
| 1250 | unsigned len2 = valueFormats[1].get_len (); |
| 1251 | unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1252 | |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1253 | PairValueRecord::context_t context = |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 1254 | { |
| 1255 | this, |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 1256 | valueFormats, |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1257 | newFormats, |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 1258 | len1, |
Qunxin Liu | d7c012a | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1259 | &glyph_map, |
| 1260 | c->plan->layout_variation_idx_map |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 1261 | }; |
| 1262 | |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1263 | const PairValueRecord *record = &firstPairValueRecord; |
| 1264 | unsigned count = len, num = 0; |
| 1265 | for (unsigned i = 0; i < count; i++) |
| 1266 | { |
ariza | 1ab3924 | 2020-01-22 11:20:56 -0800 | [diff] [blame] | 1267 | if (glyphset.has (record->secondGlyph) |
Garret Rieger | badb8e4 | 2021-04-23 16:32:56 -0700 | [diff] [blame] | 1268 | && record->subset (c, &context)) num++; |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1269 | record = &StructAtOffset<const PairValueRecord> (record, record_size); |
| 1270 | } |
| 1271 | |
| 1272 | out->len = num; |
| 1273 | if (!num) c->serializer->revert (snap); |
| 1274 | return_trace (num); |
| 1275 | } |
| 1276 | |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1277 | struct sanitize_closure_t |
| 1278 | { |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 1279 | const ValueFormat *valueFormats; |
Behdad Esfahbod | fb05908 | 2018-11-30 20:45:40 -0500 | [diff] [blame] | 1280 | unsigned int len1; /* valueFormats[0].get_len() */ |
Behdad Esfahbod | 70c9bfd | 2010-05-11 00:23:50 -0400 | [diff] [blame] | 1281 | unsigned int stride; /* 1 + len1 + len2 */ |
| 1282 | }; |
| 1283 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1284 | bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 1285 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1286 | TRACE_SANITIZE (this); |
Behdad Esfahbod | d7cfb3b | 2010-05-13 14:18:49 -0400 | [diff] [blame] | 1287 | if (!(c->check_struct (this) |
Behdad Esfahbod | e014405 | 2018-11-12 14:23:31 -0500 | [diff] [blame] | 1288 | && c->check_range (&firstPairValueRecord, |
| 1289 | len, |
| 1290 | HBUINT16::static_size, |
| 1291 | closure->stride))) return_trace (false); |
Behdad Esfahbod | 70c9bfd | 2010-05-11 00:23:50 -0400 | [diff] [blame] | 1292 | |
| 1293 | unsigned int count = len; |
Behdad Esfahbod | dff2c45 | 2018-09-10 23:29:26 +0200 | [diff] [blame] | 1294 | const PairValueRecord *record = &firstPairValueRecord; |
ariza | 1ab3924 | 2020-01-22 11:20:56 -0800 | [diff] [blame] | 1295 | return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) && |
| 1296 | closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 1297 | } |
| 1298 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1299 | protected: |
Behdad Esfahbod | dff2c45 | 2018-09-10 23:29:26 +0200 | [diff] [blame] | 1300 | HBUINT16 len; /* Number of PairValueRecords */ |
| 1301 | PairValueRecord firstPairValueRecord; |
| 1302 | /* Array of PairValueRecords--ordered |
| 1303 | * by GlyphID of the second glyph */ |
Behdad Esfahbod | 569da92 | 2010-05-10 16:38:32 -0400 | [diff] [blame] | 1304 | public: |
Behdad Esfahbod | dff2c45 | 2018-09-10 23:29:26 +0200 | [diff] [blame] | 1305 | DEFINE_SIZE_MIN (2); |
Behdad Esfahbod | b24ecba | 2009-05-19 22:16:04 -0400 | [diff] [blame] | 1306 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1307 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1308 | struct PairPosFormat1 |
| 1309 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1310 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1311 | { |
Behdad Esfahbod | f5ef8a7 | 2019-03-29 21:57:17 -0700 | [diff] [blame] | 1312 | return |
| 1313 | + hb_zip (this+coverage, pairSet) |
| 1314 | | hb_filter (*glyphs, hb_first) |
| 1315 | | hb_map (hb_second) |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 1316 | | hb_map ([glyphs, this] (const Offset16To<PairSet> &_) |
Behdad Esfahbod | f5ef8a7 | 2019-03-29 21:57:17 -0700 | [diff] [blame] | 1317 | { return (this+_).intersects (glyphs, valueFormat); }) |
| 1318 | | hb_any |
| 1319 | ; |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1320 | } |
| 1321 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 1322 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1323 | void collect_variation_indices (hb_collect_variation_indices_context_t *c) const |
| 1324 | { |
| 1325 | if ((!valueFormat[0].has_device ()) && (!valueFormat[1].has_device ())) return; |
| 1326 | |
| 1327 | auto it = |
| 1328 | + hb_zip (this+coverage, pairSet) |
| 1329 | | hb_filter (c->glyph_set, hb_first) |
| 1330 | | hb_map (hb_second) |
| 1331 | ; |
| 1332 | |
| 1333 | if (!it) return; |
| 1334 | + it |
| 1335 | | hb_map (hb_add (this)) |
| 1336 | | hb_apply ([&] (const PairSet& _) { _.collect_variation_indices (c, valueFormat); }) |
| 1337 | ; |
| 1338 | } |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 1339 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1340 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 1341 | { |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 1342 | if (unlikely (!(this+coverage).collect_coverage (c->input))) return; |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 1343 | unsigned int count = pairSet.len; |
| 1344 | for (unsigned int i = 0; i < count; i++) |
Volker H. Simonis | ad27388 | 2016-12-14 18:56:17 +0100 | [diff] [blame] | 1345 | (this+pairSet[i]).collect_glyphs (c, valueFormat); |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 1346 | } |
| 1347 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 1348 | const Coverage &get_coverage () const { return this+coverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1349 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1350 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | b24ecba | 2009-05-19 22:16:04 -0400 | [diff] [blame] | 1351 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1352 | TRACE_APPLY (this); |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 1353 | hb_buffer_t *buffer = c->buffer; |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 1354 | unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1355 | if (likely (index == NOT_COVERED)) return_trace (false); |
Behdad Esfahbod | b24ecba | 2009-05-19 22:16:04 -0400 | [diff] [blame] | 1356 | |
Behdad Esfahbod | fd03449 | 2018-01-17 16:46:51 -0800 | [diff] [blame] | 1357 | hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; |
Behdad Esfahbod | b051be5 | 2015-01-29 13:40:39 +0100 | [diff] [blame] | 1358 | skippy_iter.reset (buffer->idx, 1); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1359 | if (!skippy_iter.next ()) return_trace (false); |
Behdad Esfahbod | b24ecba | 2009-05-19 22:16:04 -0400 | [diff] [blame] | 1360 | |
Volker H. Simonis | ad27388 | 2016-12-14 18:56:17 +0100 | [diff] [blame] | 1361 | return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx)); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1362 | } |
| 1363 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1364 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 1365 | { |
| 1366 | TRACE_SUBSET (this); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1367 | |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 1368 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1369 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 1370 | |
| 1371 | auto *out = c->serializer->start_embed (*this); |
| 1372 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
| 1373 | out->format = format; |
| 1374 | out->valueFormat[0] = valueFormat[0]; |
| 1375 | out->valueFormat[1] = valueFormat[1]; |
Garret Rieger | 46d4a5e | 2021-07-29 15:07:13 -0700 | [diff] [blame] | 1376 | if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING) |
Garret Rieger | d356d0f | 2021-04-23 17:41:09 -0700 | [diff] [blame] | 1377 | { |
| 1378 | hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset); |
| 1379 | out->valueFormat[0] = newFormats.first; |
| 1380 | out->valueFormat[1] = newFormats.second; |
| 1381 | } |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1382 | |
| 1383 | hb_sorted_vector_t<hb_codepoint_t> new_coverage; |
| 1384 | |
| 1385 | + hb_zip (this+coverage, pairSet) |
| 1386 | | hb_filter (glyphset, hb_first) |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 1387 | | hb_filter ([this, c, out] (const Offset16To<PairSet>& _) |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1388 | { |
Garret Rieger | c2cc566 | 2021-09-22 14:15:55 -0700 | [diff] [blame] | 1389 | auto snap = c->serializer->snapshot (); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1390 | auto *o = out->pairSet.serialize_append (c->serializer); |
| 1391 | if (unlikely (!o)) return false; |
Garret Rieger | d356d0f | 2021-04-23 17:41:09 -0700 | [diff] [blame] | 1392 | bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1393 | if (!ret) |
| 1394 | { |
| 1395 | out->pairSet.pop (); |
| 1396 | c->serializer->revert (snap); |
| 1397 | } |
| 1398 | return ret; |
| 1399 | }, |
| 1400 | hb_second) |
| 1401 | | hb_map (hb_first) |
| 1402 | | hb_map (glyph_map) |
| 1403 | | hb_sink (new_coverage) |
| 1404 | ; |
| 1405 | |
Garret Rieger | 8443cc8 | 2021-06-11 13:40:39 -0700 | [diff] [blame] | 1406 | out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1407 | |
| 1408 | return_trace (bool (new_coverage)); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 1409 | } |
| 1410 | |
Garret Rieger | d356d0f | 2021-04-23 17:41:09 -0700 | [diff] [blame] | 1411 | |
| 1412 | hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const |
| 1413 | { |
| 1414 | unsigned len1 = valueFormat[0].get_len (); |
| 1415 | unsigned len2 = valueFormat[1].get_len (); |
| 1416 | unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2); |
| 1417 | |
| 1418 | unsigned format1 = 0; |
| 1419 | unsigned format2 = 0; |
| 1420 | for (const Offset16To<PairSet>& _ : |
| 1421 | + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second)) |
| 1422 | { |
| 1423 | const PairSet& set = (this + _); |
| 1424 | const PairValueRecord *record = &set.firstPairValueRecord; |
| 1425 | |
| 1426 | for (unsigned i = 0; i < set.len; i++) |
| 1427 | { |
| 1428 | if (record->intersects (glyphset)) |
| 1429 | { |
| 1430 | format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ()); |
| 1431 | format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0])); |
| 1432 | } |
| 1433 | record = &StructAtOffset<const PairValueRecord> (record, record_size); |
| 1434 | } |
| 1435 | } |
| 1436 | |
| 1437 | return hb_pair (format1, format2); |
| 1438 | } |
| 1439 | |
| 1440 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1441 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 1442 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1443 | TRACE_SANITIZE (this); |
Behdad Esfahbod | eba8b4f | 2010-03-29 00:04:12 -0400 | [diff] [blame] | 1444 | |
Behdad Esfahbod | f966649 | 2015-10-13 00:30:50 -0400 | [diff] [blame] | 1445 | if (!c->check_struct (this)) return_trace (false); |
| 1446 | |
Behdad Esfahbod | fb05908 | 2018-11-30 20:45:40 -0500 | [diff] [blame] | 1447 | unsigned int len1 = valueFormat[0].get_len (); |
| 1448 | unsigned int len2 = valueFormat[1].get_len (); |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1449 | PairSet::sanitize_closure_t closure = |
| 1450 | { |
Volker H. Simonis | ad27388 | 2016-12-14 18:56:17 +0100 | [diff] [blame] | 1451 | valueFormat, |
Behdad Esfahbod | 70c9bfd | 2010-05-11 00:23:50 -0400 | [diff] [blame] | 1452 | len1, |
| 1453 | 1 + len1 + len2 |
| 1454 | }; |
Behdad Esfahbod | eba8b4f | 2010-03-29 00:04:12 -0400 | [diff] [blame] | 1455 | |
Behdad Esfahbod | f966649 | 2015-10-13 00:30:50 -0400 | [diff] [blame] | 1456 | return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 1457 | } |
| 1458 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1459 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1460 | HBUINT16 format; /* Format identifier--format = 1 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 1461 | Offset16To<Coverage> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1462 | coverage; /* Offset to Coverage table--from |
| 1463 | * beginning of subtable */ |
Behdad Esfahbod | fb05908 | 2018-11-30 20:45:40 -0500 | [diff] [blame] | 1464 | ValueFormat valueFormat[2]; /* [0] Defines the types of data in |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1465 | * ValueRecord1--for the first glyph |
| 1466 | * in the pair--may be zero (0) */ |
Behdad Esfahbod | fb05908 | 2018-11-30 20:45:40 -0500 | [diff] [blame] | 1467 | /* [1] Defines the types of data in |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1468 | * ValueRecord2--for the second glyph |
| 1469 | * in the pair--may be zero (0) */ |
Behdad Esfahbod | 6c4e049 | 2021-03-31 15:31:32 -0600 | [diff] [blame] | 1470 | Array16OfOffset16To<PairSet> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1471 | pairSet; /* Array of PairSet tables |
| 1472 | * ordered by Coverage Index */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 1473 | public: |
Behdad Esfahbod | 0eb9fc6 | 2010-05-10 19:01:17 -0400 | [diff] [blame] | 1474 | DEFINE_SIZE_ARRAY (10, pairSet); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1475 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1476 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1477 | struct PairPosFormat2 |
| 1478 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1479 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1480 | { |
| 1481 | return (this+coverage).intersects (glyphs) && |
| 1482 | (this+classDef2).intersects (glyphs); |
| 1483 | } |
| 1484 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 1485 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1486 | void collect_variation_indices (hb_collect_variation_indices_context_t *c) const |
| 1487 | { |
Qunxin Liu | 84dbfac | 2021-04-15 16:52:11 -0700 | [diff] [blame] | 1488 | if (!intersects (c->glyph_set)) return; |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1489 | if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return; |
| 1490 | |
Qunxin Liu | 84dbfac | 2021-04-15 16:52:11 -0700 | [diff] [blame] | 1491 | hb_set_t klass1_glyphs, klass2_glyphs; |
| 1492 | if (!(this+classDef1).collect_coverage (&klass1_glyphs)) return; |
| 1493 | if (!(this+classDef2).collect_coverage (&klass2_glyphs)) return; |
| 1494 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1495 | hb_set_t class1_set, class2_set; |
Garret Rieger | bb54e10 | 2021-03-16 13:19:26 -0700 | [diff] [blame] | 1496 | for (const unsigned cp : + c->glyph_set->iter () | hb_filter (this + coverage)) |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1497 | { |
Qunxin Liu | 84dbfac | 2021-04-15 16:52:11 -0700 | [diff] [blame] | 1498 | if (!klass1_glyphs.has (cp)) class1_set.add (0); |
| 1499 | else |
| 1500 | { |
| 1501 | unsigned klass1 = (this+classDef1).get (cp); |
| 1502 | class1_set.add (klass1); |
| 1503 | } |
| 1504 | } |
| 1505 | |
| 1506 | class2_set.add (0); |
| 1507 | for (const unsigned cp : + c->glyph_set->iter () | hb_filter (klass2_glyphs)) |
| 1508 | { |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1509 | unsigned klass2 = (this+classDef2).get (cp); |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1510 | class2_set.add (klass2); |
| 1511 | } |
| 1512 | |
Garret Rieger | 190b7a9 | 2020-10-08 14:44:54 -0700 | [diff] [blame] | 1513 | if (class1_set.is_empty () |
| 1514 | || class2_set.is_empty () |
| 1515 | || (class2_set.get_population() == 1 && class2_set.has(0))) |
| 1516 | return; |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 1517 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1518 | unsigned len1 = valueFormat1.get_len (); |
| 1519 | unsigned len2 = valueFormat2.get_len (); |
| 1520 | const hb_array_t<const Value> values_array = values.as_array ((unsigned)class1Count * (unsigned) class2Count * (len1 + len2)); |
| 1521 | for (const unsigned class1_idx : class1_set.iter ()) |
| 1522 | { |
| 1523 | for (const unsigned class2_idx : class2_set.iter ()) |
| 1524 | { |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 1525 | unsigned start_offset = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); |
| 1526 | if (valueFormat1.has_device ()) |
| 1527 | valueFormat1.collect_variation_indices (c, this, values_array.sub_array (start_offset, len1)); |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 1528 | |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 1529 | if (valueFormat2.has_device ()) |
| 1530 | valueFormat2.collect_variation_indices (c, this, values_array.sub_array (start_offset+len1, len2)); |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1531 | } |
| 1532 | } |
| 1533 | } |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 1534 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1535 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 1536 | { |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 1537 | if (unlikely (!(this+coverage).collect_coverage (c->input))) return; |
| 1538 | if (unlikely (!(this+classDef2).collect_coverage (c->input))) return; |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 1539 | } |
| 1540 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 1541 | const Coverage &get_coverage () const { return this+coverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1542 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1543 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 70632ad | 2009-05-19 22:30:09 -0400 | [diff] [blame] | 1544 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1545 | TRACE_APPLY (this); |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 1546 | hb_buffer_t *buffer = c->buffer; |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 1547 | unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1548 | if (likely (index == NOT_COVERED)) return_trace (false); |
Behdad Esfahbod | 70632ad | 2009-05-19 22:30:09 -0400 | [diff] [blame] | 1549 | |
Behdad Esfahbod | fd03449 | 2018-01-17 16:46:51 -0800 | [diff] [blame] | 1550 | hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; |
Behdad Esfahbod | b051be5 | 2015-01-29 13:40:39 +0100 | [diff] [blame] | 1551 | skippy_iter.reset (buffer->idx, 1); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1552 | if (!skippy_iter.next ()) return_trace (false); |
Behdad Esfahbod | 70632ad | 2009-05-19 22:30:09 -0400 | [diff] [blame] | 1553 | |
| 1554 | unsigned int len1 = valueFormat1.get_len (); |
| 1555 | unsigned int len2 = valueFormat2.get_len (); |
| 1556 | unsigned int record_len = len1 + len2; |
| 1557 | |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 1558 | unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint); |
| 1559 | unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1560 | if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false); |
Behdad Esfahbod | 70632ad | 2009-05-19 22:30:09 -0400 | [diff] [blame] | 1561 | |
Behdad Esfahbod | 4b8487d | 2010-03-16 03:46:17 -0400 | [diff] [blame] | 1562 | const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; |
Nico Weber | 96299d7 | 2021-10-12 10:42:43 -0400 | [diff] [blame] | 1563 | bool applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos()); |
| 1564 | bool applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); |
| 1565 | if (applied_first || applied_second) |
Behdad Esfahbod | 6ee6cd9 | 2018-11-07 15:40:55 -0500 | [diff] [blame] | 1566 | buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1); |
Behdad Esfahbod | 70632ad | 2009-05-19 22:30:09 -0400 | [diff] [blame] | 1567 | |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 1568 | buffer->idx = skippy_iter.idx; |
Behdad Esfahbod | 70632ad | 2009-05-19 22:30:09 -0400 | [diff] [blame] | 1569 | if (len2) |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 1570 | buffer->idx++; |
Behdad Esfahbod | 70632ad | 2009-05-19 22:30:09 -0400 | [diff] [blame] | 1571 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1572 | return_trace (true); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1573 | } |
| 1574 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1575 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 1576 | { |
| 1577 | TRACE_SUBSET (this); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1578 | auto *out = c->serializer->start_embed (*this); |
| 1579 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
| 1580 | out->format = format; |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1581 | |
| 1582 | hb_map_t klass1_map; |
Qunxin Liu | 84dbfac | 2021-04-15 16:52:11 -0700 | [diff] [blame] | 1583 | out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, true, &(this + coverage)); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1584 | out->class1Count = klass1_map.get_population (); |
| 1585 | |
| 1586 | hb_map_t klass2_map; |
Qunxin Liu | 84dbfac | 2021-04-15 16:52:11 -0700 | [diff] [blame] | 1587 | out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, true, false); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1588 | out->class2Count = klass2_map.get_population (); |
| 1589 | |
Michiharu Ariza | c828d7b | 2020-01-15 15:32:44 -0800 | [diff] [blame] | 1590 | unsigned len1 = valueFormat1.get_len (); |
| 1591 | unsigned len2 = valueFormat2.get_len (); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1592 | |
Garret Rieger | f9fbe48 | 2021-04-23 17:06:06 -0700 | [diff] [blame] | 1593 | hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2); |
Garret Rieger | 46d4a5e | 2021-07-29 15:07:13 -0700 | [diff] [blame] | 1594 | if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING) |
Garret Rieger | f9fbe48 | 2021-04-23 17:06:06 -0700 | [diff] [blame] | 1595 | newFormats = compute_effective_value_formats (klass1_map, klass2_map); |
| 1596 | |
| 1597 | out->valueFormat1 = newFormats.first; |
| 1598 | out->valueFormat2 = newFormats.second; |
| 1599 | |
| 1600 | for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map)) |
| 1601 | { |
| 1602 | for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map)) |
| 1603 | { |
| 1604 | unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); |
| 1605 | valueFormat1.copy_values (c->serializer, newFormats.first, this, &values[idx], c->plan->layout_variation_idx_map); |
| 1606 | valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map); |
| 1607 | } |
| 1608 | } |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1609 | |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 1610 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1611 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 1612 | |
| 1613 | auto it = |
| 1614 | + hb_iter (this+coverage) |
| 1615 | | hb_filter (glyphset) |
| 1616 | | hb_map_retains_sorting (glyph_map) |
| 1617 | ; |
| 1618 | |
Garret Rieger | 8443cc8 | 2021-06-11 13:40:39 -0700 | [diff] [blame] | 1619 | out->coverage.serialize_serialize (c->serializer, it); |
Qunxin Liu | 1f0a9d9 | 2019-09-17 11:10:08 -0700 | [diff] [blame] | 1620 | return_trace (out->class1Count && out->class2Count && bool (it)); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 1621 | } |
| 1622 | |
Garret Rieger | f9fbe48 | 2021-04-23 17:06:06 -0700 | [diff] [blame] | 1623 | |
| 1624 | hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map, |
| 1625 | const hb_map_t& klass2_map) const |
| 1626 | { |
| 1627 | unsigned len1 = valueFormat1.get_len (); |
| 1628 | unsigned len2 = valueFormat2.get_len (); |
| 1629 | |
| 1630 | unsigned format1 = 0; |
| 1631 | unsigned format2 = 0; |
| 1632 | |
| 1633 | for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map)) |
| 1634 | { |
| 1635 | for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map)) |
| 1636 | { |
| 1637 | unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); |
| 1638 | format1 = format1 | valueFormat1.get_effective_format (&values[idx]); |
| 1639 | format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]); |
| 1640 | } |
| 1641 | } |
| 1642 | |
| 1643 | return hb_pair (format1, format2); |
| 1644 | } |
| 1645 | |
| 1646 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1647 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 1648 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1649 | TRACE_SANITIZE (this); |
Behdad Esfahbod | d7cfb3b | 2010-05-13 14:18:49 -0400 | [diff] [blame] | 1650 | if (!(c->check_struct (this) |
| 1651 | && coverage.sanitize (c, this) |
| 1652 | && classDef1.sanitize (c, this) |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1653 | && classDef2.sanitize (c, this))) return_trace (false); |
Behdad Esfahbod | 815a73e | 2009-08-14 17:31:16 -0400 | [diff] [blame] | 1654 | |
Behdad Esfahbod | eba8b4f | 2010-03-29 00:04:12 -0400 | [diff] [blame] | 1655 | unsigned int len1 = valueFormat1.get_len (); |
| 1656 | unsigned int len2 = valueFormat2.get_len (); |
| 1657 | unsigned int stride = len1 + len2; |
Behdad Esfahbod | 4b8487d | 2010-03-16 03:46:17 -0400 | [diff] [blame] | 1658 | unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size (); |
Behdad Esfahbod | eba8b4f | 2010-03-29 00:04:12 -0400 | [diff] [blame] | 1659 | unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count; |
Behdad Esfahbod | e014405 | 2018-11-12 14:23:31 -0500 | [diff] [blame] | 1660 | return_trace (c->check_range ((const void *) values, |
| 1661 | count, |
| 1662 | record_size) && |
Behdad Esfahbod | fb05908 | 2018-11-30 20:45:40 -0500 | [diff] [blame] | 1663 | valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) && |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1664 | valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 1665 | } |
Behdad Esfahbod | 70632ad | 2009-05-19 22:30:09 -0400 | [diff] [blame] | 1666 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1667 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1668 | HBUINT16 format; /* Format identifier--format = 2 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 1669 | Offset16To<Coverage> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1670 | coverage; /* Offset to Coverage table--from |
| 1671 | * beginning of subtable */ |
Behdad Esfahbod | 056c7ec | 2009-05-18 19:47:52 -0400 | [diff] [blame] | 1672 | ValueFormat valueFormat1; /* ValueRecord definition--for the |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1673 | * first glyph of the pair--may be zero |
| 1674 | * (0) */ |
Behdad Esfahbod | 056c7ec | 2009-05-18 19:47:52 -0400 | [diff] [blame] | 1675 | ValueFormat valueFormat2; /* ValueRecord definition--for the |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1676 | * second glyph of the pair--may be |
| 1677 | * zero (0) */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 1678 | Offset16To<ClassDef> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1679 | classDef1; /* Offset to ClassDef table--from |
| 1680 | * beginning of PairPos subtable--for |
| 1681 | * the first glyph of the pair */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 1682 | Offset16To<ClassDef> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1683 | classDef2; /* Offset to ClassDef table--from |
| 1684 | * beginning of PairPos subtable--for |
| 1685 | * the second glyph of the pair */ |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1686 | HBUINT16 class1Count; /* Number of classes in ClassDef1 |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1687 | * table--includes Class0 */ |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1688 | HBUINT16 class2Count; /* Number of classes in ClassDef2 |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1689 | * table--includes Class0 */ |
| 1690 | ValueRecord values; /* Matrix of value pairs: |
| 1691 | * class1-major, class2-minor, |
| 1692 | * Each entry has value1 and value2 */ |
Behdad Esfahbod | 569da92 | 2010-05-10 16:38:32 -0400 | [diff] [blame] | 1693 | public: |
Behdad Esfahbod | 0eb9fc6 | 2010-05-10 19:01:17 -0400 | [diff] [blame] | 1694 | DEFINE_SIZE_ARRAY (16, values); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1695 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1696 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1697 | struct PairPos |
| 1698 | { |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 1699 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 1700 | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1701 | { |
Behdad Esfahbod | 00f6a8e | 2014-12-12 20:36:49 -0800 | [diff] [blame] | 1702 | TRACE_DISPATCH (this, u.format); |
Behdad Esfahbod | f396fbb | 2015-10-09 12:25:55 -0400 | [diff] [blame] | 1703 | if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1704 | switch (u.format) { |
Behdad Esfahbod | 6d555ce | 2021-11-02 00:18:22 -0600 | [diff] [blame] | 1705 | case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); |
| 1706 | case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1707 | default:return_trace (c->default_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1708 | } |
| 1709 | } |
| 1710 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1711 | protected: |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1712 | union { |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1713 | HBUINT16 format; /* Format identifier */ |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 1714 | PairPosFormat1 format1; |
| 1715 | PairPosFormat2 format2; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1716 | } u; |
| 1717 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1718 | |
| 1719 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1720 | struct EntryExitRecord |
| 1721 | { |
Behdad Esfahbod | 569da92 | 2010-05-10 16:38:32 -0400 | [diff] [blame] | 1722 | friend struct CursivePosFormat1; |
| 1723 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1724 | bool sanitize (hb_sanitize_context_t *c, const void *base) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 1725 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1726 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1727 | return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 1728 | } |
| 1729 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1730 | void collect_variation_indices (hb_collect_variation_indices_context_t *c, |
| 1731 | const void *src_base) const |
| 1732 | { |
| 1733 | (src_base+entryAnchor).collect_variation_indices (c); |
| 1734 | (src_base+exitAnchor).collect_variation_indices (c); |
| 1735 | } |
| 1736 | |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 1737 | EntryExitRecord* subset (hb_subset_context_t *c, |
| 1738 | const void *src_base) const |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 1739 | { |
| 1740 | TRACE_SERIALIZE (this); |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 1741 | auto *out = c->serializer->embed (this); |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 1742 | if (unlikely (!out)) return_trace (nullptr); |
| 1743 | |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 1744 | out->entryAnchor.serialize_subset (c, entryAnchor, src_base); |
| 1745 | out->exitAnchor.serialize_subset (c, exitAnchor, src_base); |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 1746 | return_trace (out); |
| 1747 | } |
| 1748 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1749 | protected: |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 1750 | Offset16To<Anchor> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1751 | entryAnchor; /* Offset to EntryAnchor table--from |
| 1752 | * beginning of CursivePos |
| 1753 | * subtable--may be NULL */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 1754 | Offset16To<Anchor> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1755 | exitAnchor; /* Offset to ExitAnchor table--from |
| 1756 | * beginning of CursivePos |
| 1757 | * subtable--may be NULL */ |
Behdad Esfahbod | 569da92 | 2010-05-10 16:38:32 -0400 | [diff] [blame] | 1758 | public: |
| 1759 | DEFINE_SIZE_STATIC (4); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1760 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1761 | |
Behdad Esfahbod | 6578575 | 2015-08-25 20:24:59 +0100 | [diff] [blame] | 1762 | static void |
| 1763 | reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent); |
| 1764 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1765 | struct CursivePosFormat1 |
| 1766 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1767 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 1768 | { return (this+coverage).intersects (glyphs); } |
| 1769 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 1770 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
| 1771 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1772 | void collect_variation_indices (hb_collect_variation_indices_context_t *c) const |
| 1773 | { |
| 1774 | + hb_zip (this+coverage, entryExitRecord) |
| 1775 | | hb_filter (c->glyph_set, hb_first) |
| 1776 | | hb_map (hb_second) |
| 1777 | | hb_apply ([&] (const EntryExitRecord& record) { record.collect_variation_indices (c, this); }) |
| 1778 | ; |
| 1779 | } |
| 1780 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1781 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 1782 | { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; } |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 1783 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 1784 | const Coverage &get_coverage () const { return this+coverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1785 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1786 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | d18fd8e | 2009-05-19 23:25:41 -0400 | [diff] [blame] | 1787 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1788 | TRACE_APPLY (this); |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 1789 | hb_buffer_t *buffer = c->buffer; |
Behdad Esfahbod | 0f7e6b2 | 2009-05-20 04:16:35 -0400 | [diff] [blame] | 1790 | |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 1791 | const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)]; |
Behdad Esfahbod | bf8469b | 2018-10-11 20:45:00 -0400 | [diff] [blame] | 1792 | if (!this_record.entryAnchor) return_trace (false); |
Behdad Esfahbod | d18fd8e | 2009-05-19 23:25:41 -0400 | [diff] [blame] | 1793 | |
Behdad Esfahbod | fd03449 | 2018-01-17 16:46:51 -0800 | [diff] [blame] | 1794 | hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; |
Behdad Esfahbod | b051be5 | 2015-01-29 13:40:39 +0100 | [diff] [blame] | 1795 | skippy_iter.reset (buffer->idx, 1); |
Behdad Esfahbod | bf8469b | 2018-10-11 20:45:00 -0400 | [diff] [blame] | 1796 | if (!skippy_iter.prev ()) return_trace (false); |
Behdad Esfahbod | d18fd8e | 2009-05-19 23:25:41 -0400 | [diff] [blame] | 1797 | |
Behdad Esfahbod | bf8469b | 2018-10-11 20:45:00 -0400 | [diff] [blame] | 1798 | const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)]; |
| 1799 | if (!prev_record.exitAnchor) return_trace (false); |
Behdad Esfahbod | af5d02a | 2010-10-27 11:54:26 -0400 | [diff] [blame] | 1800 | |
Behdad Esfahbod | bf8469b | 2018-10-11 20:45:00 -0400 | [diff] [blame] | 1801 | unsigned int i = skippy_iter.idx; |
| 1802 | unsigned int j = buffer->idx; |
Behdad Esfahbod | af5d02a | 2010-10-27 11:54:26 -0400 | [diff] [blame] | 1803 | |
Behdad Esfahbod | 882ebda | 2017-08-10 20:23:17 -0700 | [diff] [blame] | 1804 | buffer->unsafe_to_break (i, j); |
Behdad Esfahbod | 188ee6e | 2018-01-10 05:13:47 +0100 | [diff] [blame] | 1805 | float entry_x, entry_y, exit_x, exit_y; |
Behdad Esfahbod | bf8469b | 2018-10-11 20:45:00 -0400 | [diff] [blame] | 1806 | (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y); |
| 1807 | (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y); |
Behdad Esfahbod | cc83ae1 | 2009-05-27 00:17:37 -0400 | [diff] [blame] | 1808 | |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 1809 | hb_glyph_position_t *pos = buffer->pos; |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 1810 | |
| 1811 | hb_position_t d; |
| 1812 | /* Main-direction adjustment */ |
| 1813 | switch (c->direction) { |
| 1814 | case HB_DIRECTION_LTR: |
Behdad Esfahbod | dfc5780 | 2019-05-07 23:26:09 -0700 | [diff] [blame] | 1815 | pos[i].x_advance = roundf (exit_x) + pos[i].x_offset; |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 1816 | |
Behdad Esfahbod | dfc5780 | 2019-05-07 23:26:09 -0700 | [diff] [blame] | 1817 | d = roundf (entry_x) + pos[j].x_offset; |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 1818 | pos[j].x_advance -= d; |
| 1819 | pos[j].x_offset -= d; |
| 1820 | break; |
| 1821 | case HB_DIRECTION_RTL: |
Behdad Esfahbod | dfc5780 | 2019-05-07 23:26:09 -0700 | [diff] [blame] | 1822 | d = roundf (exit_x) + pos[i].x_offset; |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 1823 | pos[i].x_advance -= d; |
| 1824 | pos[i].x_offset -= d; |
| 1825 | |
Behdad Esfahbod | dfc5780 | 2019-05-07 23:26:09 -0700 | [diff] [blame] | 1826 | pos[j].x_advance = roundf (entry_x) + pos[j].x_offset; |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 1827 | break; |
| 1828 | case HB_DIRECTION_TTB: |
Behdad Esfahbod | dfc5780 | 2019-05-07 23:26:09 -0700 | [diff] [blame] | 1829 | pos[i].y_advance = roundf (exit_y) + pos[i].y_offset; |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 1830 | |
Behdad Esfahbod | dfc5780 | 2019-05-07 23:26:09 -0700 | [diff] [blame] | 1831 | d = roundf (entry_y) + pos[j].y_offset; |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 1832 | pos[j].y_advance -= d; |
| 1833 | pos[j].y_offset -= d; |
| 1834 | break; |
| 1835 | case HB_DIRECTION_BTT: |
Behdad Esfahbod | dfc5780 | 2019-05-07 23:26:09 -0700 | [diff] [blame] | 1836 | d = roundf (exit_y) + pos[i].y_offset; |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 1837 | pos[i].y_advance -= d; |
| 1838 | pos[i].y_offset -= d; |
| 1839 | |
Behdad Esfahbod | dfc5780 | 2019-05-07 23:26:09 -0700 | [diff] [blame] | 1840 | pos[j].y_advance = roundf (entry_y); |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 1841 | break; |
| 1842 | case HB_DIRECTION_INVALID: |
| 1843 | default: |
| 1844 | break; |
Behdad Esfahbod | d18fd8e | 2009-05-19 23:25:41 -0400 | [diff] [blame] | 1845 | } |
| 1846 | |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 1847 | /* Cross-direction adjustment */ |
Behdad Esfahbod | 58f2a73 | 2015-08-25 18:55:34 +0100 | [diff] [blame] | 1848 | |
| 1849 | /* We attach child to parent (think graph theory and rooted trees whereas |
| 1850 | * the root stays on baseline and each node aligns itself against its |
| 1851 | * parent. |
| 1852 | * |
| 1853 | * Optimize things for the case of RightToLeft, as that's most common in |
Behdad Esfahbod | bf8469b | 2018-10-11 20:45:00 -0400 | [diff] [blame] | 1854 | * Arabic. */ |
Behdad Esfahbod | 58f2a73 | 2015-08-25 18:55:34 +0100 | [diff] [blame] | 1855 | unsigned int child = i; |
| 1856 | unsigned int parent = j; |
| 1857 | hb_position_t x_offset = entry_x - exit_x; |
| 1858 | hb_position_t y_offset = entry_y - exit_y; |
| 1859 | if (!(c->lookup_props & LookupFlag::RightToLeft)) |
| 1860 | { |
| 1861 | unsigned int k = child; |
| 1862 | child = parent; |
| 1863 | parent = k; |
| 1864 | x_offset = -x_offset; |
| 1865 | y_offset = -y_offset; |
Behdad Esfahbod | d18fd8e | 2009-05-19 23:25:41 -0400 | [diff] [blame] | 1866 | } |
| 1867 | |
Behdad Esfahbod | 6578575 | 2015-08-25 20:24:59 +0100 | [diff] [blame] | 1868 | /* If child was already connected to someone else, walk through its old |
| 1869 | * chain and reverse the link direction, such that the whole tree of its |
| 1870 | * previous connection now attaches to new parent. Watch out for case |
| 1871 | * where new parent is on the path from old chain... |
| 1872 | */ |
| 1873 | reverse_cursive_minor_offset (pos, child, c->direction, parent); |
| 1874 | |
Behdad Esfahbod | 686567b | 2016-02-11 15:25:28 +0700 | [diff] [blame] | 1875 | pos[child].attach_type() = ATTACH_TYPE_CURSIVE; |
| 1876 | pos[child].attach_chain() = (int) parent - (int) child; |
Behdad Esfahbod | cbc3a76 | 2016-02-11 16:48:13 +0700 | [diff] [blame] | 1877 | buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; |
Behdad Esfahbod | 58f2a73 | 2015-08-25 18:55:34 +0100 | [diff] [blame] | 1878 | if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) |
| 1879 | pos[child].y_offset = y_offset; |
| 1880 | else |
| 1881 | pos[child].x_offset = x_offset; |
| 1882 | |
Behdad Esfahbod | bb48bf5 | 2021-07-08 10:53:45 -0600 | [diff] [blame] | 1883 | /* If parent was attached to child, separate them. |
Behdad Esfahbod | 9ef9ac3 | 2020-06-17 17:41:15 -0700 | [diff] [blame] | 1884 | * https://github.com/harfbuzz/harfbuzz/issues/2469 |
| 1885 | */ |
| 1886 | if (unlikely (pos[parent].attach_chain() == -pos[child].attach_chain())) |
| 1887 | pos[parent].attach_chain() = 0; |
| 1888 | |
Behdad Esfahbod | bf8469b | 2018-10-11 20:45:00 -0400 | [diff] [blame] | 1889 | buffer->idx++; |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1890 | return_trace (true); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1891 | } |
| 1892 | |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 1893 | template <typename Iterator, |
| 1894 | hb_requires (hb_is_iterator (Iterator))> |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 1895 | void serialize (hb_subset_context_t *c, |
Qunxin Liu | d7c012a | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 1896 | Iterator it, |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 1897 | const void *src_base) |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 1898 | { |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 1899 | if (unlikely (!c->serializer->extend_min ((*this)))) return; |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 1900 | this->format = 1; |
| 1901 | this->entryExitRecord.len = it.len (); |
| 1902 | |
| 1903 | for (const EntryExitRecord& entry_record : + it |
| 1904 | | hb_map (hb_second)) |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 1905 | entry_record.subset (c, src_base); |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 1906 | |
| 1907 | auto glyphs = |
| 1908 | + it |
| 1909 | | hb_map_retains_sorting (hb_first) |
| 1910 | ; |
| 1911 | |
Garret Rieger | 8443cc8 | 2021-06-11 13:40:39 -0700 | [diff] [blame] | 1912 | coverage.serialize_serialize (c->serializer, glyphs); |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 1913 | } |
| 1914 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1915 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 1916 | { |
| 1917 | TRACE_SUBSET (this); |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 1918 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 1919 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 1920 | |
| 1921 | auto *out = c->serializer->start_embed (*this); |
| 1922 | if (unlikely (!out)) return_trace (false); |
| 1923 | |
| 1924 | auto it = |
| 1925 | + hb_zip (this+coverage, entryExitRecord) |
| 1926 | | hb_filter (glyphset, hb_first) |
| 1927 | | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&> |
Ebrahim Byagowi | 0558413 | 2019-10-01 13:49:55 +0330 | [diff] [blame] | 1928 | { return hb_pair (glyph_map[p.first], p.second);}) |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 1929 | ; |
| 1930 | |
| 1931 | bool ret = bool (it); |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 1932 | out->serialize (c, it, this); |
Qunxin Liu | b0c3eb0 | 2019-09-18 16:11:44 -0700 | [diff] [blame] | 1933 | return_trace (ret); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 1934 | } |
| 1935 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 1936 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 1937 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 1938 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1939 | return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 1940 | } |
| 1941 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1942 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1943 | HBUINT16 format; /* Format identifier--format = 1 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 1944 | Offset16To<Coverage> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1945 | coverage; /* Offset to Coverage table--from |
| 1946 | * beginning of subtable */ |
Behdad Esfahbod | 5639e25 | 2021-03-31 16:04:43 -0600 | [diff] [blame] | 1947 | Array16Of<EntryExitRecord> |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1948 | entryExitRecord; /* Array of EntryExit records--in |
| 1949 | * Coverage Index order */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 1950 | public: |
Behdad Esfahbod | 0eb9fc6 | 2010-05-10 19:01:17 -0400 | [diff] [blame] | 1951 | DEFINE_SIZE_ARRAY (6, entryExitRecord); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1952 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1953 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 1954 | struct CursivePos |
| 1955 | { |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 1956 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 1957 | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1958 | { |
Behdad Esfahbod | 00f6a8e | 2014-12-12 20:36:49 -0800 | [diff] [blame] | 1959 | TRACE_DISPATCH (this, u.format); |
Behdad Esfahbod | f396fbb | 2015-10-09 12:25:55 -0400 | [diff] [blame] | 1960 | if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1961 | switch (u.format) { |
Behdad Esfahbod | 6d555ce | 2021-11-02 00:18:22 -0600 | [diff] [blame] | 1962 | case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 1963 | default:return_trace (c->default_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 1964 | } |
| 1965 | } |
| 1966 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 1967 | protected: |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1968 | union { |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 1969 | HBUINT16 format; /* Format identifier */ |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 1970 | CursivePosFormat1 format1; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1971 | } u; |
| 1972 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1973 | |
| 1974 | |
Behdad Esfahbod | cb71a2f | 2009-08-14 18:14:03 -0400 | [diff] [blame] | 1975 | typedef AnchorMatrix BaseArray; /* base-major-- |
| 1976 | * in order of BaseCoverage Index--, |
| 1977 | * mark-minor-- |
Behdad Esfahbod | fb3b5cc | 2009-05-21 04:47:05 -0400 | [diff] [blame] | 1978 | * ordered by class--zero-based. */ |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 1979 | |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 1980 | static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage, |
| 1981 | const MarkArray &mark_array, |
| 1982 | const hb_set_t &glyphset, |
| 1983 | hb_map_t* klass_mapping /* INOUT */) |
| 1984 | { |
| 1985 | hb_set_t orig_classes; |
| 1986 | |
| 1987 | + hb_zip (mark_coverage, mark_array) |
| 1988 | | hb_filter (glyphset, hb_first) |
| 1989 | | hb_map (hb_second) |
| 1990 | | hb_map (&MarkRecord::get_class) |
| 1991 | | hb_sink (orig_classes) |
| 1992 | ; |
| 1993 | |
| 1994 | unsigned idx = 0; |
| 1995 | for (auto klass : orig_classes.iter ()) |
| 1996 | { |
| 1997 | if (klass_mapping->has (klass)) continue; |
| 1998 | klass_mapping->set (klass, idx); |
| 1999 | idx++; |
| 2000 | } |
| 2001 | } |
| 2002 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 2003 | struct MarkBasePosFormat1 |
| 2004 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2005 | bool intersects (const hb_set_t *glyphs) const |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 2006 | { |
| 2007 | return (this+markCoverage).intersects (glyphs) && |
| 2008 | (this+baseCoverage).intersects (glyphs); |
| 2009 | } |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 2010 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 2011 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
| 2012 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 2013 | void collect_variation_indices (hb_collect_variation_indices_context_t *c) const |
| 2014 | { |
| 2015 | + hb_zip (this+markCoverage, this+markArray) |
| 2016 | | hb_filter (c->glyph_set, hb_first) |
| 2017 | | hb_map (hb_second) |
| 2018 | | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); }) |
| 2019 | ; |
| 2020 | |
| 2021 | hb_map_t klass_mapping; |
| 2022 | Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping); |
| 2023 | |
| 2024 | unsigned basecount = (this+baseArray).rows; |
| 2025 | auto base_iter = |
| 2026 | + hb_zip (this+baseCoverage, hb_range (basecount)) |
| 2027 | | hb_filter (c->glyph_set, hb_first) |
| 2028 | | hb_map (hb_second) |
| 2029 | ; |
| 2030 | |
| 2031 | hb_sorted_vector_t<unsigned> base_indexes; |
| 2032 | for (const unsigned row : base_iter) |
| 2033 | { |
| 2034 | + hb_range ((unsigned) classCount) |
| 2035 | | hb_filter (klass_mapping) |
| 2036 | | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; }) |
| 2037 | | hb_sink (base_indexes) |
| 2038 | ; |
| 2039 | } |
| 2040 | (this+baseArray).collect_variation_indices (c, base_indexes.iter ()); |
| 2041 | } |
| 2042 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2043 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 2044 | { |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 2045 | if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return; |
| 2046 | if (unlikely (!(this+baseCoverage).collect_coverage (c->input))) return; |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 2047 | } |
| 2048 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 2049 | const Coverage &get_coverage () const { return this+markCoverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2050 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2051 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 2052 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 2053 | TRACE_APPLY (this); |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 2054 | hb_buffer_t *buffer = c->buffer; |
| 2055 | unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2056 | if (likely (mark_index == NOT_COVERED)) return_trace (false); |
Behdad Esfahbod | 357ccde | 2009-05-21 06:32:01 -0400 | [diff] [blame] | 2057 | |
Behdad Esfahbod | 6ab9202 | 2016-02-11 16:57:52 +0700 | [diff] [blame] | 2058 | /* Now we search backwards for a non-mark glyph */ |
Behdad Esfahbod | fd03449 | 2018-01-17 16:46:51 -0800 | [diff] [blame] | 2059 | hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; |
Behdad Esfahbod | b051be5 | 2015-01-29 13:40:39 +0100 | [diff] [blame] | 2060 | skippy_iter.reset (buffer->idx, 1); |
Behdad Esfahbod | c074ebc | 2013-02-13 11:22:42 -0500 | [diff] [blame] | 2061 | skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); |
Behdad Esfahbod | 7b84c53 | 2012-06-08 22:04:23 -0400 | [diff] [blame] | 2062 | do { |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2063 | if (!skippy_iter.prev ()) return_trace (false); |
Behdad Esfahbod | 9b5af3e | 2018-02-10 21:50:26 -0600 | [diff] [blame] | 2064 | /* We only want to attach to the first of a MultipleSubst sequence. |
| 2065 | * https://github.com/harfbuzz/harfbuzz/issues/740 |
Behdad Esfahbod | d3c0980 | 2018-06-30 15:59:25 +0430 | [diff] [blame] | 2066 | * Reject others... |
| 2067 | * ...but stop if we find a mark in the MultipleSubst sequence: |
| 2068 | * https://github.com/harfbuzz/harfbuzz/issues/1020 */ |
Behdad Esfahbod | 5d98de1 | 2017-10-03 13:46:25 +0200 | [diff] [blame] | 2069 | if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) || |
Behdad Esfahbod | 9b5af3e | 2018-02-10 21:50:26 -0600 | [diff] [blame] | 2070 | 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) || |
| 2071 | (skippy_iter.idx == 0 || |
Behdad Esfahbod | d3c0980 | 2018-06-30 15:59:25 +0430 | [diff] [blame] | 2072 | _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) || |
Behdad Esfahbod | 9b5af3e | 2018-02-10 21:50:26 -0600 | [diff] [blame] | 2073 | _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) != |
Behdad Esfahbod | 1c50a88 | 2018-02-18 15:57:09 -0800 | [diff] [blame] | 2074 | _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) || |
| 2075 | _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) != |
| 2076 | _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1 |
| 2077 | )) |
Behdad Esfahbod | 5d98de1 | 2017-10-03 13:46:25 +0200 | [diff] [blame] | 2078 | break; |
Behdad Esfahbod | 7b84c53 | 2012-06-08 22:04:23 -0400 | [diff] [blame] | 2079 | skippy_iter.reject (); |
Bruce Mitchener | 8d1e479 | 2018-10-18 22:18:42 +0700 | [diff] [blame] | 2080 | } while (true); |
Behdad Esfahbod | 0532ed1 | 2009-08-12 15:40:04 -0400 | [diff] [blame] | 2081 | |
Behdad Esfahbod | 101303d | 2013-10-18 00:42:39 +0200 | [diff] [blame] | 2082 | /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */ |
Behdad Esfahbod | 6ab9202 | 2016-02-11 16:57:52 +0700 | [diff] [blame] | 2083 | //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); } |
Behdad Esfahbod | 357ccde | 2009-05-21 06:32:01 -0400 | [diff] [blame] | 2084 | |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 2085 | unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2086 | if (base_index == NOT_COVERED) return_trace (false); |
Behdad Esfahbod | 357ccde | 2009-05-21 06:32:01 -0400 | [diff] [blame] | 2087 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2088 | return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx)); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2089 | } |
| 2090 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2091 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 2092 | { |
| 2093 | TRACE_SUBSET (this); |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 2094 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 2095 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 2096 | |
| 2097 | auto *out = c->serializer->start_embed (*this); |
| 2098 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
| 2099 | out->format = format; |
| 2100 | |
| 2101 | hb_map_t klass_mapping; |
| 2102 | Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping); |
Ebrahim Byagowi | 07acd1a | 2020-03-08 23:39:24 +0330 | [diff] [blame] | 2103 | |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 2104 | if (!klass_mapping.get_population ()) return_trace (false); |
| 2105 | out->classCount = klass_mapping.get_population (); |
| 2106 | |
| 2107 | auto mark_iter = |
| 2108 | + hb_zip (this+markCoverage, this+markArray) |
| 2109 | | hb_filter (glyphset, hb_first) |
| 2110 | ; |
| 2111 | |
| 2112 | hb_sorted_vector_t<hb_codepoint_t> new_coverage; |
| 2113 | + mark_iter |
| 2114 | | hb_map (hb_first) |
| 2115 | | hb_map (glyph_map) |
| 2116 | | hb_sink (new_coverage) |
| 2117 | ; |
| 2118 | |
Garret Rieger | 8443cc8 | 2021-06-11 13:40:39 -0700 | [diff] [blame] | 2119 | if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ())) |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 2120 | return_trace (false); |
| 2121 | |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 2122 | out->markArray.serialize_subset (c, markArray, this, |
| 2123 | (this+markCoverage).iter (), |
| 2124 | &klass_mapping); |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 2125 | |
| 2126 | unsigned basecount = (this+baseArray).rows; |
| 2127 | auto base_iter = |
| 2128 | + hb_zip (this+baseCoverage, hb_range (basecount)) |
| 2129 | | hb_filter (glyphset, hb_first) |
| 2130 | ; |
| 2131 | |
| 2132 | new_coverage.reset (); |
| 2133 | + base_iter |
| 2134 | | hb_map (hb_first) |
| 2135 | | hb_map (glyph_map) |
| 2136 | | hb_sink (new_coverage) |
| 2137 | ; |
| 2138 | |
Garret Rieger | 8443cc8 | 2021-06-11 13:40:39 -0700 | [diff] [blame] | 2139 | if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ())) |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 2140 | return_trace (false); |
| 2141 | |
| 2142 | hb_sorted_vector_t<unsigned> base_indexes; |
| 2143 | for (const unsigned row : + base_iter |
| 2144 | | hb_map (hb_second)) |
| 2145 | { |
| 2146 | + hb_range ((unsigned) classCount) |
| 2147 | | hb_filter (klass_mapping) |
| 2148 | | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; }) |
| 2149 | | hb_sink (base_indexes) |
| 2150 | ; |
| 2151 | } |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 2152 | |
| 2153 | out->baseArray.serialize_subset (c, baseArray, this, |
| 2154 | base_iter.len (), |
| 2155 | base_indexes.iter ()); |
Qunxin Liu | 82afc75 | 2020-02-04 13:24:37 -0800 | [diff] [blame] | 2156 | |
| 2157 | return_trace (true); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 2158 | } |
| 2159 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2160 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 2161 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 2162 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2163 | return_trace (c->check_struct (this) && |
| 2164 | markCoverage.sanitize (c, this) && |
| 2165 | baseCoverage.sanitize (c, this) && |
| 2166 | markArray.sanitize (c, this) && |
| 2167 | baseArray.sanitize (c, this, (unsigned int) classCount)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 2168 | } |
| 2169 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 2170 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 2171 | HBUINT16 format; /* Format identifier--format = 1 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 2172 | Offset16To<Coverage> |
Behdad Esfahbod | fb3b5cc | 2009-05-21 04:47:05 -0400 | [diff] [blame] | 2173 | markCoverage; /* Offset to MarkCoverage table--from |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2174 | * beginning of MarkBasePos subtable */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 2175 | Offset16To<Coverage> |
Behdad Esfahbod | fb3b5cc | 2009-05-21 04:47:05 -0400 | [diff] [blame] | 2176 | baseCoverage; /* Offset to BaseCoverage table--from |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2177 | * beginning of MarkBasePos subtable */ |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 2178 | HBUINT16 classCount; /* Number of classes defined for marks */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 2179 | Offset16To<MarkArray> |
Behdad Esfahbod | fb3b5cc | 2009-05-21 04:47:05 -0400 | [diff] [blame] | 2180 | markArray; /* Offset to MarkArray table--from |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2181 | * beginning of MarkBasePos subtable */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 2182 | Offset16To<BaseArray> |
Behdad Esfahbod | fb3b5cc | 2009-05-21 04:47:05 -0400 | [diff] [blame] | 2183 | baseArray; /* Offset to BaseArray table--from |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2184 | * beginning of MarkBasePos subtable */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 2185 | public: |
| 2186 | DEFINE_SIZE_STATIC (12); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2187 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2188 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 2189 | struct MarkBasePos |
| 2190 | { |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 2191 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 2192 | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2193 | { |
Behdad Esfahbod | 00f6a8e | 2014-12-12 20:36:49 -0800 | [diff] [blame] | 2194 | TRACE_DISPATCH (this, u.format); |
Behdad Esfahbod | f396fbb | 2015-10-09 12:25:55 -0400 | [diff] [blame] | 2195 | if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2196 | switch (u.format) { |
Behdad Esfahbod | 6d555ce | 2021-11-02 00:18:22 -0600 | [diff] [blame] | 2197 | case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2198 | default:return_trace (c->default_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2199 | } |
| 2200 | } |
| 2201 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 2202 | protected: |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2203 | union { |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 2204 | HBUINT16 format; /* Format identifier */ |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 2205 | MarkBasePosFormat1 format1; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2206 | } u; |
| 2207 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2208 | |
| 2209 | |
Behdad Esfahbod | cb71a2f | 2009-08-14 18:14:03 -0400 | [diff] [blame] | 2210 | typedef AnchorMatrix LigatureAttach; /* component-major-- |
| 2211 | * in order of writing direction--, |
| 2212 | * mark-minor-- |
Behdad Esfahbod | 9b006bc | 2009-05-22 18:29:45 -0400 | [diff] [blame] | 2213 | * ordered by class--zero-based. */ |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2214 | |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2215 | /* Array of LigatureAttach tables ordered by LigatureCoverage Index */ |
Behdad Esfahbod | 5efe360 | 2021-03-31 15:33:22 -0600 | [diff] [blame] | 2216 | struct LigatureArray : List16OfOffset16To<LigatureAttach> |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2217 | { |
| 2218 | template <typename Iterator, |
| 2219 | hb_requires (hb_is_iterator (Iterator))> |
Garret Rieger | 093909b | 2020-10-05 13:14:53 -0700 | [diff] [blame] | 2220 | bool subset (hb_subset_context_t *c, |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 2221 | Iterator coverage, |
Garret Rieger | 093909b | 2020-10-05 13:14:53 -0700 | [diff] [blame] | 2222 | unsigned class_count, |
| 2223 | const hb_map_t *klass_mapping) const |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2224 | { |
Garret Rieger | 093909b | 2020-10-05 13:14:53 -0700 | [diff] [blame] | 2225 | TRACE_SUBSET (this); |
| 2226 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Garret Rieger | 147e93b | 2020-10-01 16:44:16 -0700 | [diff] [blame] | 2227 | |
Garret Rieger | 093909b | 2020-10-05 13:14:53 -0700 | [diff] [blame] | 2228 | auto *out = c->serializer->start_embed (this); |
| 2229 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2230 | |
Behdad Esfahbod | 103ed7d | 2021-02-19 16:48:30 -0700 | [diff] [blame] | 2231 | for (const auto _ : + hb_zip (coverage, *this) |
| 2232 | | hb_filter (glyphset, hb_first)) |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2233 | { |
Garret Rieger | 093909b | 2020-10-05 13:14:53 -0700 | [diff] [blame] | 2234 | auto *matrix = out->serialize_append (c->serializer); |
| 2235 | if (unlikely (!matrix)) return_trace (false); |
| 2236 | |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 2237 | const LigatureAttach& src = (this + _.second); |
| 2238 | auto indexes = |
| 2239 | + hb_range (src.rows * class_count) |
| 2240 | | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); }) |
| 2241 | ; |
Garret Rieger | 093909b | 2020-10-05 13:14:53 -0700 | [diff] [blame] | 2242 | matrix->serialize_subset (c, |
Behdad Esfahbod | 103ed7d | 2021-02-19 16:48:30 -0700 | [diff] [blame] | 2243 | _.second, |
Garret Rieger | 093909b | 2020-10-05 13:14:53 -0700 | [diff] [blame] | 2244 | this, |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 2245 | src.rows, |
| 2246 | indexes); |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2247 | } |
| 2248 | return_trace (this->len); |
| 2249 | } |
| 2250 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2251 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 2252 | struct MarkLigPosFormat1 |
| 2253 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2254 | bool intersects (const hb_set_t *glyphs) const |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 2255 | { |
| 2256 | return (this+markCoverage).intersects (glyphs) && |
| 2257 | (this+ligatureCoverage).intersects (glyphs); |
| 2258 | } |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 2259 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 2260 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
| 2261 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 2262 | void collect_variation_indices (hb_collect_variation_indices_context_t *c) const |
| 2263 | { |
| 2264 | + hb_zip (this+markCoverage, this+markArray) |
| 2265 | | hb_filter (c->glyph_set, hb_first) |
| 2266 | | hb_map (hb_second) |
| 2267 | | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); }) |
| 2268 | ; |
| 2269 | |
| 2270 | hb_map_t klass_mapping; |
| 2271 | Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping); |
| 2272 | |
| 2273 | unsigned ligcount = (this+ligatureArray).len; |
| 2274 | auto lig_iter = |
| 2275 | + hb_zip (this+ligatureCoverage, hb_range (ligcount)) |
| 2276 | | hb_filter (c->glyph_set, hb_first) |
| 2277 | | hb_map (hb_second) |
| 2278 | ; |
| 2279 | |
| 2280 | const LigatureArray& lig_array = this+ligatureArray; |
| 2281 | for (const unsigned i : lig_iter) |
| 2282 | { |
| 2283 | hb_sorted_vector_t<unsigned> lig_indexes; |
| 2284 | unsigned row_count = lig_array[i].rows; |
| 2285 | for (unsigned row : + hb_range (row_count)) |
| 2286 | { |
Ebrahim Byagowi | 5a7cc7f | 2020-07-29 08:33:32 +0430 | [diff] [blame] | 2287 | + hb_range ((unsigned) classCount) |
| 2288 | | hb_filter (klass_mapping) |
| 2289 | | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; }) |
| 2290 | | hb_sink (lig_indexes) |
| 2291 | ; |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 2292 | } |
| 2293 | |
| 2294 | lig_array[i].collect_variation_indices (c, lig_indexes.iter ()); |
| 2295 | } |
| 2296 | } |
| 2297 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2298 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 2299 | { |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 2300 | if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return; |
| 2301 | if (unlikely (!(this+ligatureCoverage).collect_coverage (c->input))) return; |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 2302 | } |
| 2303 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 2304 | const Coverage &get_coverage () const { return this+markCoverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2305 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2306 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 2307 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 2308 | TRACE_APPLY (this); |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 2309 | hb_buffer_t *buffer = c->buffer; |
| 2310 | unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2311 | if (likely (mark_index == NOT_COVERED)) return_trace (false); |
Behdad Esfahbod | 9b006bc | 2009-05-22 18:29:45 -0400 | [diff] [blame] | 2312 | |
Behdad Esfahbod | 6ab9202 | 2016-02-11 16:57:52 +0700 | [diff] [blame] | 2313 | /* Now we search backwards for a non-mark glyph */ |
Behdad Esfahbod | fd03449 | 2018-01-17 16:46:51 -0800 | [diff] [blame] | 2314 | hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; |
Behdad Esfahbod | b051be5 | 2015-01-29 13:40:39 +0100 | [diff] [blame] | 2315 | skippy_iter.reset (buffer->idx, 1); |
Behdad Esfahbod | c074ebc | 2013-02-13 11:22:42 -0500 | [diff] [blame] | 2316 | skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2317 | if (!skippy_iter.prev ()) return_trace (false); |
Behdad Esfahbod | 0532ed1 | 2009-08-12 15:40:04 -0400 | [diff] [blame] | 2318 | |
Behdad Esfahbod | 101303d | 2013-10-18 00:42:39 +0200 | [diff] [blame] | 2319 | /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */ |
Behdad Esfahbod | 6ab9202 | 2016-02-11 16:57:52 +0700 | [diff] [blame] | 2320 | //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); } |
Behdad Esfahbod | 9b006bc | 2009-05-22 18:29:45 -0400 | [diff] [blame] | 2321 | |
Behdad Esfahbod | 4ab9731 | 2012-01-16 22:05:08 -0500 | [diff] [blame] | 2322 | unsigned int j = skippy_iter.idx; |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 2323 | unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2324 | if (lig_index == NOT_COVERED) return_trace (false); |
Behdad Esfahbod | 9b006bc | 2009-05-22 18:29:45 -0400 | [diff] [blame] | 2325 | |
Behdad Esfahbod | 9b006bc | 2009-05-22 18:29:45 -0400 | [diff] [blame] | 2326 | const LigatureArray& lig_array = this+ligatureArray; |
Behdad Esfahbod | 3564ee5 | 2009-08-14 18:32:56 -0400 | [diff] [blame] | 2327 | const LigatureAttach& lig_attach = lig_array[lig_index]; |
Behdad Esfahbod | cb71a2f | 2009-08-14 18:14:03 -0400 | [diff] [blame] | 2328 | |
| 2329 | /* Find component to attach to */ |
Behdad Esfahbod | b2b18ef | 2009-08-14 19:37:18 -0400 | [diff] [blame] | 2330 | unsigned int comp_count = lig_attach.rows; |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2331 | if (unlikely (!comp_count)) return_trace (false); |
Behdad Esfahbod | acea183 | 2012-05-11 02:33:11 +0200 | [diff] [blame] | 2332 | |
Behdad Esfahbod | 9b006bc | 2009-05-22 18:29:45 -0400 | [diff] [blame] | 2333 | /* We must now check whether the ligature ID of the current mark glyph |
| 2334 | * is identical to the ligature ID of the found ligature. If yes, we |
| 2335 | * can directly use the component index. If not, we attach the mark |
| 2336 | * glyph to the last component of the ligature. */ |
Behdad Esfahbod | 0aef425 | 2012-07-30 00:55:15 -0400 | [diff] [blame] | 2337 | unsigned int comp_index; |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 2338 | unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]); |
| 2339 | unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur()); |
| 2340 | unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); |
Behdad Esfahbod | 0aef425 | 2012-07-30 00:55:15 -0400 | [diff] [blame] | 2341 | if (lig_id && lig_id == mark_id && mark_comp > 0) |
Behdad Esfahbod | 41248cc | 2019-05-07 20:54:31 -0700 | [diff] [blame] | 2342 | comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1; |
Behdad Esfahbod | 9b006bc | 2009-05-22 18:29:45 -0400 | [diff] [blame] | 2343 | else |
Behdad Esfahbod | b2b18ef | 2009-08-14 19:37:18 -0400 | [diff] [blame] | 2344 | comp_index = comp_count - 1; |
Behdad Esfahbod | 9b006bc | 2009-05-22 18:29:45 -0400 | [diff] [blame] | 2345 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2346 | return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j)); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2347 | } |
| 2348 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2349 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 2350 | { |
| 2351 | TRACE_SUBSET (this); |
Garret Rieger | 093909b | 2020-10-05 13:14:53 -0700 | [diff] [blame] | 2352 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2353 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 2354 | |
| 2355 | auto *out = c->serializer->start_embed (*this); |
| 2356 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
| 2357 | out->format = format; |
| 2358 | |
| 2359 | hb_map_t klass_mapping; |
| 2360 | Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping); |
Garret Rieger | 147e93b | 2020-10-01 16:44:16 -0700 | [diff] [blame] | 2361 | |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2362 | if (!klass_mapping.get_population ()) return_trace (false); |
| 2363 | out->classCount = klass_mapping.get_population (); |
| 2364 | |
| 2365 | auto mark_iter = |
| 2366 | + hb_zip (this+markCoverage, this+markArray) |
| 2367 | | hb_filter (glyphset, hb_first) |
| 2368 | ; |
| 2369 | |
Garret Rieger | 093909b | 2020-10-05 13:14:53 -0700 | [diff] [blame] | 2370 | auto new_mark_coverage = |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2371 | + mark_iter |
Garret Rieger | 093909b | 2020-10-05 13:14:53 -0700 | [diff] [blame] | 2372 | | hb_map_retains_sorting (hb_first) |
| 2373 | | hb_map_retains_sorting (glyph_map) |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2374 | ; |
| 2375 | |
Garret Rieger | 8443cc8 | 2021-06-11 13:40:39 -0700 | [diff] [blame] | 2376 | if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage)) |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2377 | return_trace (false); |
| 2378 | |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 2379 | out->markArray.serialize_subset (c, markArray, this, |
| 2380 | (this+markCoverage).iter (), |
| 2381 | &klass_mapping); |
Garret Rieger | 147e93b | 2020-10-01 16:44:16 -0700 | [diff] [blame] | 2382 | |
Garret Rieger | 093909b | 2020-10-05 13:14:53 -0700 | [diff] [blame] | 2383 | auto new_ligature_coverage = |
| 2384 | + hb_iter (this + ligatureCoverage) |
| 2385 | | hb_filter (glyphset) |
| 2386 | | hb_map_retains_sorting (glyph_map) |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2387 | ; |
| 2388 | |
Garret Rieger | 8443cc8 | 2021-06-11 13:40:39 -0700 | [diff] [blame] | 2389 | if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage)) |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2390 | return_trace (false); |
| 2391 | |
Garret Rieger | 093909b | 2020-10-05 13:14:53 -0700 | [diff] [blame] | 2392 | out->ligatureArray.serialize_subset (c, ligatureArray, this, |
| 2393 | hb_iter (this+ligatureCoverage), classCount, &klass_mapping); |
Qunxin Liu | 3a0b05f | 2020-02-06 15:08:26 -0800 | [diff] [blame] | 2394 | |
| 2395 | return_trace (true); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 2396 | } |
| 2397 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2398 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 2399 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 2400 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2401 | return_trace (c->check_struct (this) && |
| 2402 | markCoverage.sanitize (c, this) && |
| 2403 | ligatureCoverage.sanitize (c, this) && |
| 2404 | markArray.sanitize (c, this) && |
| 2405 | ligatureArray.sanitize (c, this, (unsigned int) classCount)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 2406 | } |
| 2407 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 2408 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 2409 | HBUINT16 format; /* Format identifier--format = 1 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 2410 | Offset16To<Coverage> |
Behdad Esfahbod | 9b006bc | 2009-05-22 18:29:45 -0400 | [diff] [blame] | 2411 | markCoverage; /* Offset to Mark Coverage table--from |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2412 | * beginning of MarkLigPos subtable */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 2413 | Offset16To<Coverage> |
Behdad Esfahbod | 9b006bc | 2009-05-22 18:29:45 -0400 | [diff] [blame] | 2414 | ligatureCoverage; /* Offset to Ligature Coverage |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2415 | * table--from beginning of MarkLigPos |
| 2416 | * subtable */ |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 2417 | HBUINT16 classCount; /* Number of defined mark classes */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 2418 | Offset16To<MarkArray> |
Behdad Esfahbod | 9b006bc | 2009-05-22 18:29:45 -0400 | [diff] [blame] | 2419 | markArray; /* Offset to MarkArray table--from |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2420 | * beginning of MarkLigPos subtable */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 2421 | Offset16To<LigatureArray> |
Behdad Esfahbod | 9b006bc | 2009-05-22 18:29:45 -0400 | [diff] [blame] | 2422 | ligatureArray; /* Offset to LigatureArray table--from |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2423 | * beginning of MarkLigPos subtable */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 2424 | public: |
| 2425 | DEFINE_SIZE_STATIC (12); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2426 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2427 | |
Garret Rieger | 093909b | 2020-10-05 13:14:53 -0700 | [diff] [blame] | 2428 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 2429 | struct MarkLigPos |
| 2430 | { |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 2431 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 2432 | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2433 | { |
Behdad Esfahbod | 00f6a8e | 2014-12-12 20:36:49 -0800 | [diff] [blame] | 2434 | TRACE_DISPATCH (this, u.format); |
Behdad Esfahbod | f396fbb | 2015-10-09 12:25:55 -0400 | [diff] [blame] | 2435 | if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2436 | switch (u.format) { |
Behdad Esfahbod | 6d555ce | 2021-11-02 00:18:22 -0600 | [diff] [blame] | 2437 | case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2438 | default:return_trace (c->default_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2439 | } |
| 2440 | } |
| 2441 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 2442 | protected: |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2443 | union { |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 2444 | HBUINT16 format; /* Format identifier */ |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 2445 | MarkLigPosFormat1 format1; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2446 | } u; |
| 2447 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2448 | |
| 2449 | |
Behdad Esfahbod | cb71a2f | 2009-08-14 18:14:03 -0400 | [diff] [blame] | 2450 | typedef AnchorMatrix Mark2Array; /* mark2-major-- |
| 2451 | * in order of Mark2Coverage Index--, |
| 2452 | * mark1-minor-- |
| 2453 | * ordered by class--zero-based. */ |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2454 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 2455 | struct MarkMarkPosFormat1 |
| 2456 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2457 | bool intersects (const hb_set_t *glyphs) const |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 2458 | { |
| 2459 | return (this+mark1Coverage).intersects (glyphs) && |
| 2460 | (this+mark2Coverage).intersects (glyphs); |
| 2461 | } |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 2462 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 2463 | void closure_lookups (hb_closure_lookups_context_t *c) const {} |
| 2464 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 2465 | void collect_variation_indices (hb_collect_variation_indices_context_t *c) const |
| 2466 | { |
| 2467 | + hb_zip (this+mark1Coverage, this+mark1Array) |
| 2468 | | hb_filter (c->glyph_set, hb_first) |
| 2469 | | hb_map (hb_second) |
| 2470 | | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); }) |
| 2471 | ; |
| 2472 | |
| 2473 | hb_map_t klass_mapping; |
| 2474 | Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping); |
| 2475 | |
| 2476 | unsigned mark2_count = (this+mark2Array).rows; |
| 2477 | auto mark2_iter = |
| 2478 | + hb_zip (this+mark2Coverage, hb_range (mark2_count)) |
| 2479 | | hb_filter (c->glyph_set, hb_first) |
| 2480 | | hb_map (hb_second) |
| 2481 | ; |
| 2482 | |
| 2483 | hb_sorted_vector_t<unsigned> mark2_indexes; |
| 2484 | for (const unsigned row : mark2_iter) |
| 2485 | { |
| 2486 | + hb_range ((unsigned) classCount) |
| 2487 | | hb_filter (klass_mapping) |
| 2488 | | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; }) |
| 2489 | | hb_sink (mark2_indexes) |
| 2490 | ; |
| 2491 | } |
| 2492 | (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ()); |
| 2493 | } |
| 2494 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2495 | void collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 2496 | { |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 2497 | if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return; |
| 2498 | if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return; |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 2499 | } |
| 2500 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 2501 | const Coverage &get_coverage () const { return this+mark1Coverage; } |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2502 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2503 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 2504 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 2505 | TRACE_APPLY (this); |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 2506 | hb_buffer_t *buffer = c->buffer; |
| 2507 | unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2508 | if (likely (mark1_index == NOT_COVERED)) return_trace (false); |
Behdad Esfahbod | fe550f4 | 2009-05-21 08:27:07 -0400 | [diff] [blame] | 2509 | |
| 2510 | /* now we search backwards for a suitable mark glyph until a non-mark glyph */ |
Behdad Esfahbod | fd03449 | 2018-01-17 16:46:51 -0800 | [diff] [blame] | 2511 | hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input; |
Behdad Esfahbod | b051be5 | 2015-01-29 13:40:39 +0100 | [diff] [blame] | 2512 | skippy_iter.reset (buffer->idx, 1); |
Behdad Esfahbod | c074ebc | 2013-02-13 11:22:42 -0500 | [diff] [blame] | 2513 | skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2514 | if (!skippy_iter.prev ()) return_trace (false); |
Behdad Esfahbod | 0532ed1 | 2009-08-12 15:40:04 -0400 | [diff] [blame] | 2515 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2516 | if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) { return_trace (false); } |
Behdad Esfahbod | 80ea5bd | 2009-05-26 17:58:37 -0400 | [diff] [blame] | 2517 | |
Behdad Esfahbod | 4ab9731 | 2012-01-16 22:05:08 -0500 | [diff] [blame] | 2518 | unsigned int j = skippy_iter.idx; |
| 2519 | |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 2520 | unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur()); |
| 2521 | unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]); |
| 2522 | unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur()); |
| 2523 | unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]); |
Behdad Esfahbod | fe550f4 | 2009-05-21 08:27:07 -0400 | [diff] [blame] | 2524 | |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 2525 | if (likely (id1 == id2)) |
| 2526 | { |
Behdad Esfahbod | 5d874d5 | 2012-07-28 21:05:25 -0400 | [diff] [blame] | 2527 | if (id1 == 0) /* Marks belonging to the same base. */ |
| 2528 | goto good; |
| 2529 | else if (comp1 == comp2) /* Marks belonging to the same ligature component. */ |
Ebrahim Byagowi | 11aa046 | 2018-11-15 23:10:56 +0330 | [diff] [blame] | 2530 | goto good; |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 2531 | } |
| 2532 | else |
| 2533 | { |
Behdad Esfahbod | 5d874d5 | 2012-07-28 21:05:25 -0400 | [diff] [blame] | 2534 | /* If ligature ids don't match, it may be the case that one of the marks |
| 2535 | * itself is a ligature. In which case match. */ |
| 2536 | if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2)) |
| 2537 | goto good; |
| 2538 | } |
| 2539 | |
| 2540 | /* Didn't match. */ |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2541 | return_trace (false); |
Behdad Esfahbod | 5d874d5 | 2012-07-28 21:05:25 -0400 | [diff] [blame] | 2542 | |
| 2543 | good: |
Behdad Esfahbod | ac8cd51 | 2013-10-18 19:33:09 +0200 | [diff] [blame] | 2544 | unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2545 | if (mark2_index == NOT_COVERED) return_trace (false); |
Behdad Esfahbod | fe550f4 | 2009-05-21 08:27:07 -0400 | [diff] [blame] | 2546 | |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2547 | return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j)); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2548 | } |
| 2549 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2550 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 2551 | { |
| 2552 | TRACE_SUBSET (this); |
Garret Rieger | e583505 | 2020-09-29 11:05:08 -0700 | [diff] [blame] | 2553 | const hb_set_t &glyphset = *c->plan->glyphset_gsub (); |
Qunxin Liu | eb7849a | 2020-02-05 15:29:03 -0800 | [diff] [blame] | 2554 | const hb_map_t &glyph_map = *c->plan->glyph_map; |
| 2555 | |
| 2556 | auto *out = c->serializer->start_embed (*this); |
| 2557 | if (unlikely (!c->serializer->extend_min (out))) return_trace (false); |
| 2558 | out->format = format; |
| 2559 | |
| 2560 | hb_map_t klass_mapping; |
| 2561 | Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping); |
Ebrahim Byagowi | 07acd1a | 2020-03-08 23:39:24 +0330 | [diff] [blame] | 2562 | |
Qunxin Liu | eb7849a | 2020-02-05 15:29:03 -0800 | [diff] [blame] | 2563 | if (!klass_mapping.get_population ()) return_trace (false); |
| 2564 | out->classCount = klass_mapping.get_population (); |
| 2565 | |
| 2566 | auto mark1_iter = |
| 2567 | + hb_zip (this+mark1Coverage, this+mark1Array) |
| 2568 | | hb_filter (glyphset, hb_first) |
| 2569 | ; |
| 2570 | |
| 2571 | hb_sorted_vector_t<hb_codepoint_t> new_coverage; |
| 2572 | + mark1_iter |
| 2573 | | hb_map (hb_first) |
| 2574 | | hb_map (glyph_map) |
| 2575 | | hb_sink (new_coverage) |
| 2576 | ; |
| 2577 | |
Garret Rieger | 8443cc8 | 2021-06-11 13:40:39 -0700 | [diff] [blame] | 2578 | if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ())) |
Qunxin Liu | eb7849a | 2020-02-05 15:29:03 -0800 | [diff] [blame] | 2579 | return_trace (false); |
| 2580 | |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 2581 | out->mark1Array.serialize_subset (c, mark1Array, this, |
| 2582 | (this+mark1Coverage).iter (), |
| 2583 | &klass_mapping); |
Ebrahim Byagowi | d0e2add | 2020-07-18 22:14:52 +0430 | [diff] [blame] | 2584 | |
Qunxin Liu | eb7849a | 2020-02-05 15:29:03 -0800 | [diff] [blame] | 2585 | unsigned mark2count = (this+mark2Array).rows; |
| 2586 | auto mark2_iter = |
| 2587 | + hb_zip (this+mark2Coverage, hb_range (mark2count)) |
| 2588 | | hb_filter (glyphset, hb_first) |
| 2589 | ; |
| 2590 | |
| 2591 | new_coverage.reset (); |
| 2592 | + mark2_iter |
| 2593 | | hb_map (hb_first) |
| 2594 | | hb_map (glyph_map) |
| 2595 | | hb_sink (new_coverage) |
| 2596 | ; |
| 2597 | |
Garret Rieger | 8443cc8 | 2021-06-11 13:40:39 -0700 | [diff] [blame] | 2598 | if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ())) |
Qunxin Liu | eb7849a | 2020-02-05 15:29:03 -0800 | [diff] [blame] | 2599 | return_trace (false); |
| 2600 | |
| 2601 | hb_sorted_vector_t<unsigned> mark2_indexes; |
| 2602 | for (const unsigned row : + mark2_iter |
| 2603 | | hb_map (hb_second)) |
| 2604 | { |
| 2605 | + hb_range ((unsigned) classCount) |
| 2606 | | hb_filter (klass_mapping) |
| 2607 | | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; }) |
| 2608 | | hb_sink (mark2_indexes) |
| 2609 | ; |
| 2610 | } |
Garret Rieger | 6f98a8e | 2021-04-02 14:37:10 -0700 | [diff] [blame] | 2611 | |
| 2612 | out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ()); |
Qunxin Liu | eb7849a | 2020-02-05 15:29:03 -0800 | [diff] [blame] | 2613 | |
| 2614 | return_trace (true); |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 2615 | } |
| 2616 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2617 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 2618 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 2619 | TRACE_SANITIZE (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2620 | return_trace (c->check_struct (this) && |
| 2621 | mark1Coverage.sanitize (c, this) && |
| 2622 | mark2Coverage.sanitize (c, this) && |
| 2623 | mark1Array.sanitize (c, this) && |
| 2624 | mark2Array.sanitize (c, this, (unsigned int) classCount)); |
Behdad Esfahbod | 42b778f | 2009-08-04 13:30:49 -0400 | [diff] [blame] | 2625 | } |
| 2626 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 2627 | protected: |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 2628 | HBUINT16 format; /* Format identifier--format = 1 */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 2629 | Offset16To<Coverage> |
Behdad Esfahbod | fe550f4 | 2009-05-21 08:27:07 -0400 | [diff] [blame] | 2630 | mark1Coverage; /* Offset to Combining Mark1 Coverage |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2631 | * table--from beginning of MarkMarkPos |
| 2632 | * subtable */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 2633 | Offset16To<Coverage> |
Behdad Esfahbod | fe550f4 | 2009-05-21 08:27:07 -0400 | [diff] [blame] | 2634 | mark2Coverage; /* Offset to Combining Mark2 Coverage |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2635 | * table--from beginning of MarkMarkPos |
| 2636 | * subtable */ |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 2637 | HBUINT16 classCount; /* Number of defined mark classes */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 2638 | Offset16To<MarkArray> |
Behdad Esfahbod | fe550f4 | 2009-05-21 08:27:07 -0400 | [diff] [blame] | 2639 | mark1Array; /* Offset to Mark1Array table--from |
| 2640 | * beginning of MarkMarkPos subtable */ |
Behdad Esfahbod | ad28f97 | 2021-03-31 12:49:14 -0600 | [diff] [blame] | 2641 | Offset16To<Mark2Array> |
Behdad Esfahbod | fe550f4 | 2009-05-21 08:27:07 -0400 | [diff] [blame] | 2642 | mark2Array; /* Offset to Mark2Array table--from |
| 2643 | * beginning of MarkMarkPos subtable */ |
Behdad Esfahbod | b365123 | 2010-05-10 16:57:29 -0400 | [diff] [blame] | 2644 | public: |
| 2645 | DEFINE_SIZE_STATIC (12); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2646 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2647 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 2648 | struct MarkMarkPos |
| 2649 | { |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 2650 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 2651 | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2652 | { |
Behdad Esfahbod | 00f6a8e | 2014-12-12 20:36:49 -0800 | [diff] [blame] | 2653 | TRACE_DISPATCH (this, u.format); |
Behdad Esfahbod | f396fbb | 2015-10-09 12:25:55 -0400 | [diff] [blame] | 2654 | if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2655 | switch (u.format) { |
Behdad Esfahbod | 6d555ce | 2021-11-02 00:18:22 -0600 | [diff] [blame] | 2656 | case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2657 | default:return_trace (c->default_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2658 | } |
| 2659 | } |
| 2660 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 2661 | protected: |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2662 | union { |
Behdad Esfahbod | 6b19178 | 2018-01-10 03:07:30 +0100 | [diff] [blame] | 2663 | HBUINT16 format; /* Format identifier */ |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 2664 | MarkMarkPosFormat1 format1; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2665 | } u; |
| 2666 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2667 | |
| 2668 | |
Behdad Esfahbod | 08f1eed | 2012-11-23 16:51:43 -0500 | [diff] [blame] | 2669 | struct ContextPos : Context {}; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2670 | |
Behdad Esfahbod | 08f1eed | 2012-11-23 16:51:43 -0500 | [diff] [blame] | 2671 | struct ChainContextPos : ChainContext {}; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2672 | |
Behdad Esfahbod | 653eeb2 | 2012-11-23 16:57:36 -0500 | [diff] [blame] | 2673 | struct ExtensionPos : Extension<ExtensionPos> |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 2674 | { |
Behdad Esfahbod | 9c3747c | 2018-09-03 16:53:03 -0700 | [diff] [blame] | 2675 | typedef struct PosLookupSubTable SubTable; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2676 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2677 | |
| 2678 | |
Behdad Esfahbod | d468f9a | 2009-05-21 22:31:33 -0400 | [diff] [blame] | 2679 | |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2680 | /* |
| 2681 | * PosLookup |
| 2682 | */ |
| 2683 | |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2684 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 2685 | struct PosLookupSubTable |
| 2686 | { |
Behdad Esfahbod | 7b2ef55 | 2018-09-03 17:16:09 -0700 | [diff] [blame] | 2687 | friend struct Lookup; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2688 | friend struct PosLookup; |
| 2689 | |
Behdad Esfahbod | c6035cf | 2012-04-12 13:23:59 -0400 | [diff] [blame] | 2690 | enum Type { |
Behdad Esfahbod | ff05d25 | 2009-05-20 03:53:00 -0400 | [diff] [blame] | 2691 | Single = 1, |
| 2692 | Pair = 2, |
| 2693 | Cursive = 3, |
| 2694 | MarkBase = 4, |
| 2695 | MarkLig = 5, |
| 2696 | MarkMark = 6, |
| 2697 | Context = 7, |
| 2698 | ChainContext = 8, |
Behdad Esfahbod | 8f034d5 | 2009-08-18 16:41:59 -0400 | [diff] [blame] | 2699 | Extension = 9 |
Behdad Esfahbod | ff05d25 | 2009-05-20 03:53:00 -0400 | [diff] [blame] | 2700 | }; |
| 2701 | |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 2702 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 2703 | typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const |
Behdad Esfahbod | faf0f20 | 2012-06-09 03:02:36 -0400 | [diff] [blame] | 2704 | { |
Behdad Esfahbod | 00f6a8e | 2014-12-12 20:36:49 -0800 | [diff] [blame] | 2705 | TRACE_DISPATCH (this, lookup_type); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2706 | switch (lookup_type) { |
Behdad Esfahbod | 6d555ce | 2021-11-02 00:18:22 -0600 | [diff] [blame] | 2707 | case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...)); |
| 2708 | case Pair: return_trace (u.pair.dispatch (c, std::forward<Ts> (ds)...)); |
| 2709 | case Cursive: return_trace (u.cursive.dispatch (c, std::forward<Ts> (ds)...)); |
| 2710 | case MarkBase: return_trace (u.markBase.dispatch (c, std::forward<Ts> (ds)...)); |
| 2711 | case MarkLig: return_trace (u.markLig.dispatch (c, std::forward<Ts> (ds)...)); |
| 2712 | case MarkMark: return_trace (u.markMark.dispatch (c, std::forward<Ts> (ds)...)); |
| 2713 | case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...)); |
| 2714 | case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...)); |
| 2715 | case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...)); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2716 | default: return_trace (c->default_return_value ()); |
Behdad Esfahbod | 0b99429 | 2012-07-28 17:31:01 -0400 | [diff] [blame] | 2717 | } |
Behdad Esfahbod | faf0f20 | 2012-06-09 03:02:36 -0400 | [diff] [blame] | 2718 | } |
| 2719 | |
ariza | 72cbfb9 | 2020-01-18 16:35:52 -0800 | [diff] [blame] | 2720 | bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const |
| 2721 | { |
| 2722 | hb_intersects_context_t c (glyphs); |
| 2723 | return dispatch (&c, lookup_type); |
| 2724 | } |
| 2725 | |
Behdad Esfahbod | ec8d249 | 2012-07-24 15:40:37 -0400 | [diff] [blame] | 2726 | protected: |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2727 | union { |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 2728 | SinglePos single; |
| 2729 | PairPos pair; |
| 2730 | CursivePos cursive; |
| 2731 | MarkBasePos markBase; |
| 2732 | MarkLigPos markLig; |
| 2733 | MarkMarkPos markMark; |
Behdad Esfahbod | e72b360 | 2012-07-19 14:35:23 -0400 | [diff] [blame] | 2734 | ContextPos context; |
Behdad Esfahbod | dacebca | 2010-05-10 19:45:41 -0400 | [diff] [blame] | 2735 | ChainContextPos chainContext; |
| 2736 | ExtensionPos extension; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2737 | } u; |
Behdad Esfahbod | ed07422 | 2010-05-10 18:08:46 -0400 | [diff] [blame] | 2738 | public: |
Behdad Esfahbod | 2cc993e | 2018-12-12 10:07:38 -0500 | [diff] [blame] | 2739 | DEFINE_SIZE_MIN (0); |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2740 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2741 | |
| 2742 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 2743 | struct PosLookup : Lookup |
| 2744 | { |
Behdad Esfahbod | 9c3747c | 2018-09-03 16:53:03 -0700 | [diff] [blame] | 2745 | typedef struct PosLookupSubTable SubTable; |
| 2746 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2747 | const SubTable& get_subtable (unsigned int i) const |
Behdad Esfahbod | 9c3747c | 2018-09-03 16:53:03 -0700 | [diff] [blame] | 2748 | { return Lookup::get_subtable<SubTable> (i); } |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2749 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 2750 | bool is_reverse () const |
Behdad Esfahbod | e015b8f | 2013-05-03 17:34:29 -0400 | [diff] [blame] | 2751 | { |
| 2752 | return false; |
| 2753 | } |
| 2754 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2755 | bool apply (hb_ot_apply_context_t *c) const |
Behdad Esfahbod | bd047d3 | 2015-02-19 10:47:18 +0300 | [diff] [blame] | 2756 | { |
| 2757 | TRACE_APPLY (this); |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 2758 | return_trace (dispatch (c)); |
Behdad Esfahbod | bd047d3 | 2015-02-19 10:47:18 +0300 | [diff] [blame] | 2759 | } |
| 2760 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2761 | bool intersects (const hb_set_t *glyphs) const |
Behdad Esfahbod | 7c9cfa2 | 2018-09-02 19:47:50 -0700 | [diff] [blame] | 2762 | { |
| 2763 | hb_intersects_context_t c (glyphs); |
| 2764 | return dispatch (&c); |
| 2765 | } |
| 2766 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2767 | hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const |
Behdad Esfahbod | 89bcfb2 | 2019-01-18 14:59:18 -0500 | [diff] [blame] | 2768 | { return dispatch (c); } |
Behdad Esfahbod | cdd756b | 2012-11-24 01:38:41 -0500 | [diff] [blame] | 2769 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 2770 | hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const |
| 2771 | { |
| 2772 | if (c->is_lookup_visited (this_index)) |
| 2773 | return hb_closure_lookups_context_t::default_return_value (); |
| 2774 | |
| 2775 | c->set_lookup_visited (this_index); |
| 2776 | if (!intersects (c->glyphs)) |
| 2777 | { |
| 2778 | c->set_lookup_inactive (this_index); |
| 2779 | return hb_closure_lookups_context_t::default_return_value (); |
| 2780 | } |
| 2781 | c->set_recurse_func (dispatch_closure_lookups_recurse_func); |
| 2782 | |
| 2783 | hb_closure_lookups_context_t::return_t ret = dispatch (c); |
| 2784 | return ret; |
| 2785 | } |
| 2786 | |
Behdad Esfahbod | a878c58 | 2012-08-01 21:18:54 -0400 | [diff] [blame] | 2787 | template <typename set_t> |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 2788 | void collect_coverage (set_t *glyphs) const |
Behdad Esfahbod | a878c58 | 2012-08-01 21:18:54 -0400 | [diff] [blame] | 2789 | { |
Behdad Esfahbod | 5cf53c0 | 2020-04-23 10:55:41 -0700 | [diff] [blame] | 2790 | hb_collect_coverage_context_t<set_t> c (glyphs); |
Behdad Esfahbod | 8e36ccf | 2015-02-17 19:15:34 +0300 | [diff] [blame] | 2791 | dispatch (&c); |
Behdad Esfahbod | a878c58 | 2012-08-01 21:18:54 -0400 | [diff] [blame] | 2792 | } |
| 2793 | |
Behdad Esfahbod | a061e47 | 2019-12-10 13:31:50 -0600 | [diff] [blame] | 2794 | static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index); |
Behdad Esfahbod | ec35a72 | 2012-11-22 16:05:59 -0500 | [diff] [blame] | 2795 | |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 2796 | template <typename context_t> |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2797 | static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index); |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 2798 | |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 2799 | HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index); |
| 2800 | |
Behdad Esfahbod | 36bb24f | 2019-05-05 10:14:17 -0700 | [diff] [blame] | 2801 | template <typename context_t, typename ...Ts> |
Behdad Esfahbod | 83e3eab | 2019-05-07 20:58:43 -0700 | [diff] [blame] | 2802 | typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const |
Behdad Esfahbod | 6d555ce | 2021-11-02 00:18:22 -0600 | [diff] [blame] | 2803 | { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); } |
Behdad Esfahbod | ee5464d | 2013-03-09 01:59:30 -0500 | [diff] [blame] | 2804 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2805 | bool subset (hb_subset_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 2806 | { return Lookup::subset<SubTable> (c); } |
| 2807 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2808 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | 7b2ef55 | 2018-09-03 17:16:09 -0700 | [diff] [blame] | 2809 | { return Lookup::sanitize<SubTable> (c); } |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2810 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2811 | |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2812 | /* |
Ebrahim Byagowi | a02c3ee | 2018-04-12 13:38:19 +0430 | [diff] [blame] | 2813 | * GPOS -- Glyph Positioning |
| 2814 | * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2815 | */ |
| 2816 | |
Behdad Esfahbod | 4c44d83 | 2009-05-19 23:42:30 -0400 | [diff] [blame] | 2817 | struct GPOS : GSUBGPOS |
| 2818 | { |
Behdad Esfahbod | ef00654 | 2019-01-22 12:08:57 +0100 | [diff] [blame] | 2819 | static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2820 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2821 | const PosLookup& get_lookup (unsigned int i) const |
Behdad Esfahbod | 858b627 | 2019-12-10 13:18:32 -0600 | [diff] [blame] | 2822 | { return static_cast<const PosLookup &> (GSUBGPOS::get_lookup (i)); } |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2823 | |
Behdad Esfahbod | 05bd1b6 | 2012-07-30 19:30:01 -0400 | [diff] [blame] | 2824 | static inline void position_start (hb_font_t *font, hb_buffer_t *buffer); |
Behdad Esfahbod | 7d8d58a | 2016-02-11 16:34:28 +0700 | [diff] [blame] | 2825 | static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer); |
| 2826 | static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer); |
Behdad Esfahbod | 1e7c1fc | 2010-10-27 22:48:31 -0400 | [diff] [blame] | 2827 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2828 | bool subset (hb_subset_context_t *c) const |
Qunxin Liu | e565d1f | 2019-11-01 10:21:36 -0700 | [diff] [blame] | 2829 | { |
Qunxin Liu | 56ca435 | 2021-01-28 15:21:26 -0800 | [diff] [blame] | 2830 | hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features); |
Qunxin Liu | e565d1f | 2019-11-01 10:21:36 -0700 | [diff] [blame] | 2831 | return GSUBGPOS::subset<PosLookup> (&l); |
| 2832 | } |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 2833 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 2834 | bool sanitize (hb_sanitize_context_t *c) const |
Behdad Esfahbod | 339d360 | 2018-09-03 17:33:34 -0700 | [diff] [blame] | 2835 | { return GSUBGPOS::sanitize<PosLookup> (c); } |
Behdad Esfahbod | 963413f | 2018-08-26 00:47:55 -0700 | [diff] [blame] | 2836 | |
Behdad Esfahbod | 5671947 | 2020-06-05 12:57:23 -0700 | [diff] [blame] | 2837 | HB_INTERNAL bool is_blocklisted (hb_blob_t *blob, |
Behdad Esfahbod | 574d888 | 2018-11-25 16:51:22 -0500 | [diff] [blame] | 2838 | hb_face_t *face) const; |
| 2839 | |
Qunxin Liu | 8200e48 | 2020-02-26 13:11:42 -0800 | [diff] [blame] | 2840 | void collect_variation_indices (hb_collect_variation_indices_context_t *c) const |
| 2841 | { |
| 2842 | for (unsigned i = 0; i < GSUBGPOS::get_lookup_count (); i++) |
| 2843 | { |
| 2844 | if (!c->gpos_lookups->has (i)) continue; |
| 2845 | const PosLookup &l = get_lookup (i); |
| 2846 | l.dispatch (c); |
| 2847 | } |
| 2848 | } |
| 2849 | |
Qunxin Liu | 973c47f | 2020-06-11 11:27:57 -0700 | [diff] [blame] | 2850 | void closure_lookups (hb_face_t *face, |
| 2851 | const hb_set_t *glyphs, |
| 2852 | hb_set_t *lookup_indexes /* IN/OUT */) const |
| 2853 | { GSUBGPOS::closure_lookups<PosLookup> (face, glyphs, lookup_indexes); } |
| 2854 | |
Behdad Esfahbod | 963413f | 2018-08-26 00:47:55 -0700 | [diff] [blame] | 2855 | typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2856 | }; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2857 | |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 2858 | |
| 2859 | static void |
Behdad Esfahbod | 6578575 | 2015-08-25 20:24:59 +0100 | [diff] [blame] | 2860 | reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent) |
| 2861 | { |
Behdad Esfahbod | 686567b | 2016-02-11 15:25:28 +0700 | [diff] [blame] | 2862 | int chain = pos[i].attach_chain(), type = pos[i].attach_type(); |
| 2863 | if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE))) |
Behdad Esfahbod | 6578575 | 2015-08-25 20:24:59 +0100 | [diff] [blame] | 2864 | return; |
| 2865 | |
Behdad Esfahbod | 686567b | 2016-02-11 15:25:28 +0700 | [diff] [blame] | 2866 | pos[i].attach_chain() = 0; |
Behdad Esfahbod | 6578575 | 2015-08-25 20:24:59 +0100 | [diff] [blame] | 2867 | |
Behdad Esfahbod | 686567b | 2016-02-11 15:25:28 +0700 | [diff] [blame] | 2868 | unsigned int j = (int) i + chain; |
Behdad Esfahbod | 806ad8d | 2016-02-11 14:53:11 +0700 | [diff] [blame] | 2869 | |
Behdad Esfahbod | 6578575 | 2015-08-25 20:24:59 +0100 | [diff] [blame] | 2870 | /* Stop if we see new parent in the chain. */ |
| 2871 | if (j == new_parent) |
| 2872 | return; |
| 2873 | |
| 2874 | reverse_cursive_minor_offset (pos, j, direction, new_parent); |
| 2875 | |
| 2876 | if (HB_DIRECTION_IS_HORIZONTAL (direction)) |
| 2877 | pos[j].y_offset = -pos[i].y_offset; |
| 2878 | else |
| 2879 | pos[j].x_offset = -pos[i].x_offset; |
| 2880 | |
Behdad Esfahbod | 686567b | 2016-02-11 15:25:28 +0700 | [diff] [blame] | 2881 | pos[j].attach_chain() = -chain; |
| 2882 | pos[j].attach_type() = type; |
Behdad Esfahbod | 6578575 | 2015-08-25 20:24:59 +0100 | [diff] [blame] | 2883 | } |
| 2884 | static void |
Behdad Esfahbod | 36f38ea | 2018-10-16 16:24:03 -0700 | [diff] [blame] | 2885 | propagate_attachment_offsets (hb_glyph_position_t *pos, |
| 2886 | unsigned int len, |
| 2887 | unsigned int i, |
| 2888 | hb_direction_t direction) |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 2889 | { |
Behdad Esfahbod | cbc3a76 | 2016-02-11 16:48:13 +0700 | [diff] [blame] | 2890 | /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate |
| 2891 | * offset of glyph they are attached to. */ |
Behdad Esfahbod | 686567b | 2016-02-11 15:25:28 +0700 | [diff] [blame] | 2892 | int chain = pos[i].attach_chain(), type = pos[i].attach_type(); |
Behdad Esfahbod | cbc3a76 | 2016-02-11 16:48:13 +0700 | [diff] [blame] | 2893 | if (likely (!chain)) |
Behdad Esfahbod | df5d5c6 | 2012-08-23 09:33:30 -0400 | [diff] [blame] | 2894 | return; |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 2895 | |
Behdad Esfahbod | 686567b | 2016-02-11 15:25:28 +0700 | [diff] [blame] | 2896 | pos[i].attach_chain() = 0; |
| 2897 | |
Behdad Esfahbod | 36f38ea | 2018-10-16 16:24:03 -0700 | [diff] [blame] | 2898 | unsigned int j = (int) i + chain; |
| 2899 | |
| 2900 | if (unlikely (j >= len)) |
| 2901 | return; |
| 2902 | |
| 2903 | propagate_attachment_offsets (pos, len, j, direction); |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 2904 | |
Behdad Esfahbod | cbc3a76 | 2016-02-11 16:48:13 +0700 | [diff] [blame] | 2905 | assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE)); |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 2906 | |
Behdad Esfahbod | cbc3a76 | 2016-02-11 16:48:13 +0700 | [diff] [blame] | 2907 | if (type & ATTACH_TYPE_CURSIVE) |
| 2908 | { |
| 2909 | if (HB_DIRECTION_IS_HORIZONTAL (direction)) |
| 2910 | pos[i].y_offset += pos[j].y_offset; |
| 2911 | else |
| 2912 | pos[i].x_offset += pos[j].x_offset; |
| 2913 | } |
| 2914 | else /*if (type & ATTACH_TYPE_MARK)*/ |
| 2915 | { |
Behdad Esfahbod | df5d5c6 | 2012-08-23 09:33:30 -0400 | [diff] [blame] | 2916 | pos[i].x_offset += pos[j].x_offset; |
Behdad Esfahbod | cbc3a76 | 2016-02-11 16:48:13 +0700 | [diff] [blame] | 2917 | pos[i].y_offset += pos[j].y_offset; |
Behdad Esfahbod | ebd7431 | 2016-02-24 15:53:40 +0900 | [diff] [blame] | 2918 | |
| 2919 | assert (j < i); |
| 2920 | if (HB_DIRECTION_IS_FORWARD (direction)) |
| 2921 | for (unsigned int k = j; k < i; k++) { |
| 2922 | pos[i].x_offset -= pos[k].x_advance; |
| 2923 | pos[i].y_offset -= pos[k].y_advance; |
| 2924 | } |
| 2925 | else |
| 2926 | for (unsigned int k = j + 1; k < i + 1; k++) { |
| 2927 | pos[i].x_offset += pos[k].x_advance; |
| 2928 | pos[i].y_offset += pos[k].y_advance; |
| 2929 | } |
Behdad Esfahbod | cbc3a76 | 2016-02-11 16:48:13 +0700 | [diff] [blame] | 2930 | } |
Behdad Esfahbod | 7403e05 | 2011-05-24 21:04:15 -0400 | [diff] [blame] | 2931 | } |
| 2932 | |
Behdad Esfahbod | 1e7c1fc | 2010-10-27 22:48:31 -0400 | [diff] [blame] | 2933 | void |
Behdad Esfahbod | 05bd1b6 | 2012-07-30 19:30:01 -0400 | [diff] [blame] | 2934 | GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) |
Behdad Esfahbod | a9ad3d3 | 2011-07-28 15:42:18 -0400 | [diff] [blame] | 2935 | { |
Behdad Esfahbod | b65c060 | 2011-07-28 16:48:43 -0400 | [diff] [blame] | 2936 | unsigned int count = buffer->len; |
| 2937 | for (unsigned int i = 0; i < count; i++) |
Behdad Esfahbod | 686567b | 2016-02-11 15:25:28 +0700 | [diff] [blame] | 2938 | buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0; |
Behdad Esfahbod | a9ad3d3 | 2011-07-28 15:42:18 -0400 | [diff] [blame] | 2939 | } |
| 2940 | |
| 2941 | void |
Behdad Esfahbod | 39bd07a | 2018-10-26 21:01:11 -0700 | [diff] [blame] | 2942 | GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED) |
Behdad Esfahbod | 7d8d58a | 2016-02-11 16:34:28 +0700 | [diff] [blame] | 2943 | { |
| 2944 | //_hb_buffer_assert_gsubgpos_vars (buffer); |
| 2945 | } |
| 2946 | |
| 2947 | void |
| 2948 | GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) |
Behdad Esfahbod | 1e7c1fc | 2010-10-27 22:48:31 -0400 | [diff] [blame] | 2949 | { |
Behdad Esfahbod | 8f3eebf | 2014-08-02 17:18:46 -0400 | [diff] [blame] | 2950 | _hb_buffer_assert_gsubgpos_vars (buffer); |
| 2951 | |
Ryan Lortie | 70566be | 2011-04-15 18:32:36 -0400 | [diff] [blame] | 2952 | unsigned int len; |
| 2953 | hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len); |
Behdad Esfahbod | 1e7c1fc | 2010-10-27 22:48:31 -0400 | [diff] [blame] | 2954 | hb_direction_t direction = buffer->props.direction; |
| 2955 | |
Behdad Esfahbod | 1e7c1fc | 2010-10-27 22:48:31 -0400 | [diff] [blame] | 2956 | /* Handle attachments */ |
Behdad Esfahbod | 550bd14 | 2015-11-04 22:58:58 -0800 | [diff] [blame] | 2957 | if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT) |
| 2958 | for (unsigned int i = 0; i < len; i++) |
Behdad Esfahbod | 36f38ea | 2018-10-16 16:24:03 -0700 | [diff] [blame] | 2959 | propagate_attachment_offsets (pos, len, i, direction); |
Behdad Esfahbod | 1e7c1fc | 2010-10-27 22:48:31 -0400 | [diff] [blame] | 2960 | } |
| 2961 | |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2962 | |
Behdad Esfahbod | 33b006c | 2018-11-05 23:19:04 -0500 | [diff] [blame] | 2963 | struct GPOS_accelerator_t : GPOS::accelerator_t {}; |
| 2964 | |
| 2965 | |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2966 | /* Out-of-class implementation for methods recursing */ |
| 2967 | |
Behdad Esfahbod | 7dcf8e1 | 2019-06-26 13:44:10 -0700 | [diff] [blame] | 2968 | #ifndef HB_NO_OT_LAYOUT |
Behdad Esfahbod | c6fb843 | 2012-11-23 18:04:08 -0500 | [diff] [blame] | 2969 | template <typename context_t> |
Behdad Esfahbod | dd3972a | 2019-12-10 13:21:26 -0600 | [diff] [blame] | 2970 | /*static*/ typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index) |
Behdad Esfahbod | c6fb843 | 2012-11-23 18:04:08 -0500 | [diff] [blame] | 2971 | { |
Behdad Esfahbod | 33b006c | 2018-11-05 23:19:04 -0500 | [diff] [blame] | 2972 | const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index); |
Behdad Esfahbod | 9c5a9ee | 2013-03-09 01:55:04 -0500 | [diff] [blame] | 2973 | return l.dispatch (c); |
Behdad Esfahbod | c6fb843 | 2012-11-23 18:04:08 -0500 | [diff] [blame] | 2974 | } |
Qunxin Liu | 0b39c48 | 2019-10-22 16:00:43 -0700 | [diff] [blame] | 2975 | |
| 2976 | /*static*/ inline hb_closure_lookups_context_t::return_t PosLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index) |
| 2977 | { |
| 2978 | const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (this_index); |
| 2979 | return l.closure_lookups (c, this_index); |
| 2980 | } |
| 2981 | |
Behdad Esfahbod | a061e47 | 2019-12-10 13:31:50 -0600 | [diff] [blame] | 2982 | /*static*/ bool PosLookup::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] | 2983 | { |
Behdad Esfahbod | 33b006c | 2018-11-05 23:19:04 -0500 | [diff] [blame] | 2984 | const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index); |
Behdad Esfahbod | 4c4e8f0 | 2012-11-24 01:13:20 -0500 | [diff] [blame] | 2985 | unsigned int saved_lookup_props = c->lookup_props; |
Behdad Esfahbod | 2c8b3b2 | 2015-08-18 14:36:43 +0100 | [diff] [blame] | 2986 | unsigned int saved_lookup_index = c->lookup_index; |
| 2987 | c->set_lookup_index (lookup_index); |
| 2988 | c->set_lookup_props (l.get_props ()); |
Behdad Esfahbod | 1a23221 | 2015-02-19 10:40:23 +0300 | [diff] [blame] | 2989 | bool ret = l.dispatch (c); |
Behdad Esfahbod | 2c8b3b2 | 2015-08-18 14:36:43 +0100 | [diff] [blame] | 2990 | c->set_lookup_index (saved_lookup_index); |
Behdad Esfahbod | 7788993 | 2015-01-28 23:01:12 -0800 | [diff] [blame] | 2991 | c->set_lookup_props (saved_lookup_props); |
Behdad Esfahbod | 4c4e8f0 | 2012-11-24 01:13:20 -0500 | [diff] [blame] | 2992 | return ret; |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2993 | } |
Behdad Esfahbod | 7dcf8e1 | 2019-06-26 13:44:10 -0700 | [diff] [blame] | 2994 | #endif |
Behdad Esfahbod | 5e5eb05 | 2009-05-18 17:09:33 -0400 | [diff] [blame] | 2995 | |
| 2996 | |
Behdad Esfahbod | 7d52e66 | 2012-11-16 18:49:54 -0800 | [diff] [blame] | 2997 | } /* namespace OT */ |
Behdad Esfahbod | 7c8e844 | 2012-08-28 17:57:49 -0400 | [diff] [blame] | 2998 | |
Behdad Esfahbod | acdba3f | 2010-07-23 15:11:18 -0400 | [diff] [blame] | 2999 | |
Behdad Esfahbod | 7a750ac | 2011-08-17 14:19:59 +0200 | [diff] [blame] | 3000 | #endif /* HB_OT_LAYOUT_GPOS_TABLE_HH */ |