Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 1 | /* |
Behdad Esfahbod | 0ab8c86 | 2012-05-11 01:25:34 +0200 | [diff] [blame] | 2 | * Copyright © 2011,2012 Google, Inc. |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 3 | * |
| 4 | * This is part of HarfBuzz, a text shaping library. |
| 5 | * |
| 6 | * Permission is hereby granted, without written agreement and without |
| 7 | * license or royalty fees, to use, copy, modify, and distribute this |
| 8 | * software and its documentation for any purpose, provided that the |
| 9 | * above copyright notice and the following two paragraphs appear in |
| 10 | * all copies of this software. |
| 11 | * |
| 12 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
| 13 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
| 14 | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
| 15 | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| 16 | * DAMAGE. |
| 17 | * |
| 18 | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
| 19 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| 20 | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
| 21 | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
| 22 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| 23 | * |
Rod Sheeter | 0e088a6 | 2018-02-14 21:11:45 -0800 | [diff] [blame] | 24 | * Google Author(s): Behdad Esfahbod, Roderick Sheeter |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 25 | */ |
| 26 | |
| 27 | #ifndef HB_OT_HMTX_TABLE_HH |
| 28 | #define HB_OT_HMTX_TABLE_HH |
| 29 | |
Behdad Esfahbod | c77ae40 | 2018-08-25 22:36:36 -0700 | [diff] [blame] | 30 | #include "hb-open-type.hh" |
Behdad Esfahbod | eab4feb | 2017-11-14 20:16:45 -0800 | [diff] [blame] | 31 | #include "hb-ot-hhea-table.hh" |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 32 | #include "hb-ot-os2-table.hh" |
| 33 | #include "hb-ot-var-hvar-table.hh" |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 34 | |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 35 | /* |
Ebrahim Byagowi | a02c3ee | 2018-04-12 13:38:19 +0430 | [diff] [blame] | 36 | * hmtx -- Horizontal Metrics |
| 37 | * https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx |
| 38 | * vmtx -- Vertical Metrics |
| 39 | * https://docs.microsoft.com/en-us/typography/opentype/spec/vmtx |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 40 | */ |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 41 | #define HB_OT_TAG_hmtx HB_TAG('h','m','t','x') |
Behdad Esfahbod | d41b809 | 2014-09-25 13:04:08 +0300 | [diff] [blame] | 42 | #define HB_OT_TAG_vmtx HB_TAG('v','m','t','x') |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 43 | |
| 44 | |
Ebrahim Byagowi | a02c3ee | 2018-04-12 13:38:19 +0430 | [diff] [blame] | 45 | namespace OT { |
| 46 | |
| 47 | |
Behdad Esfahbod | d41b809 | 2014-09-25 13:04:08 +0300 | [diff] [blame] | 48 | struct LongMetric |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 49 | { |
Behdad Esfahbod | 082b79f | 2016-03-01 16:41:26 +0900 | [diff] [blame] | 50 | UFWORD advance; /* Advance width/height. */ |
Behdad Esfahbod | 8dc6296 | 2018-10-15 01:09:05 -0700 | [diff] [blame] | 51 | FWORD sb; /* Leading (left/top) side bearing. */ |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 52 | public: |
| 53 | DEFINE_SIZE_STATIC (4); |
| 54 | }; |
| 55 | |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 56 | template <typename T, typename H> |
Behdad Esfahbod | a11d9a0 | 2017-01-22 20:09:47 -0800 | [diff] [blame] | 57 | struct hmtxvmtx |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 58 | { |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 59 | bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const |
Behdad Esfahbod | de2118e | 2015-02-17 17:27:44 +0300 | [diff] [blame] | 60 | { |
Behdad Esfahbod | be218c6 | 2012-11-23 15:32:14 -0500 | [diff] [blame] | 61 | TRACE_SANITIZE (this); |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 62 | /* We don't check for anything specific here. The users of the |
| 63 | * struct do all the hard work... */ |
Behdad Esfahbod | b471590 | 2015-09-29 14:57:02 +0100 | [diff] [blame] | 64 | return_trace (true); |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 65 | } |
| 66 | |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 67 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 68 | bool subset_update_header (hb_subset_plan_t *plan, |
Garret Rieger | 03e88ea | 2019-01-28 16:15:06 -0800 | [diff] [blame] | 69 | unsigned int num_hmetrics) const |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 70 | { |
Ebrahim Byagowi | 11aa046 | 2018-11-15 23:10:56 +0330 | [diff] [blame] | 71 | hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (plan->source, H::tableTag); |
| 72 | hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob); |
Garret Rieger | 0775bc0 | 2018-02-14 16:37:35 -0800 | [diff] [blame] | 73 | hb_blob_destroy (src_blob); |
| 74 | |
Rod Sheeter | e158739 | 2018-02-14 19:22:37 -0800 | [diff] [blame] | 75 | if (unlikely (!dest_blob)) { |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 76 | return false; |
| 77 | } |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 78 | |
Rod Sheeter | 1efecd9 | 2018-02-14 18:42:29 -0800 | [diff] [blame] | 79 | unsigned int length; |
Rod Sheeter | 0e088a6 | 2018-02-14 21:11:45 -0800 | [diff] [blame] | 80 | H *table = (H *) hb_blob_get_data (dest_blob, &length); |
Behdad Esfahbod | b986c6a | 2019-03-29 20:17:46 -0700 | [diff] [blame] | 81 | table->numberOfLongMetrics = num_hmetrics; |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 82 | |
Garret Rieger | 251cc97 | 2018-05-30 12:23:51 -0700 | [diff] [blame] | 83 | bool result = plan->add_table (H::tableTag, dest_blob); |
Garret Rieger | 0775bc0 | 2018-02-14 16:37:35 -0800 | [diff] [blame] | 84 | hb_blob_destroy (dest_blob); |
| 85 | |
| 86 | return result; |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 87 | } |
| 88 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 89 | bool subset (hb_subset_plan_t *plan) const |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 90 | { |
| 91 | typename T::accelerator_t _mtx; |
Rod Sheeter | 0e088a6 | 2018-02-14 21:11:45 -0800 | [diff] [blame] | 92 | _mtx.init (plan->source); |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 93 | |
| 94 | /* All the trailing glyphs with the same advance can use one LongMetric |
| 95 | * and just keep LSB */ |
Garret Rieger | 03e88ea | 2019-01-28 16:15:06 -0800 | [diff] [blame] | 96 | unsigned int num_output_glyphs = plan->num_output_glyphs (); |
| 97 | unsigned int num_advances = _mtx.num_advances_for_subset (plan); |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 98 | |
| 99 | /* alloc the new table */ |
| 100 | size_t dest_sz = num_advances * 4 |
Garret Rieger | 03e88ea | 2019-01-28 16:15:06 -0800 | [diff] [blame] | 101 | + (num_output_glyphs - num_advances) * 2; |
Garret Rieger | 4665aaa | 2018-02-23 15:36:14 -0800 | [diff] [blame] | 102 | void *dest = (void *) malloc (dest_sz); |
Rod Sheeter | e158739 | 2018-02-14 19:22:37 -0800 | [diff] [blame] | 103 | if (unlikely (!dest)) |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 104 | { |
| 105 | return false; |
| 106 | } |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 107 | DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in src has %d advances, %d lsbs", HB_UNTAG(T::tableTag), _mtx.num_advances, _mtx.num_metrics - _mtx.num_advances); |
Garret Rieger | 03e88ea | 2019-01-28 16:15:06 -0800 | [diff] [blame] | 108 | DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", |
| 109 | HB_UNTAG(T::tableTag), num_advances, num_output_glyphs - num_advances, (unsigned int) dest_sz); |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 110 | |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 111 | // Copy everything over |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 112 | char * dest_pos = (char *) dest; |
Garret Rieger | 1a94804 | 2018-03-19 18:39:22 -0700 | [diff] [blame] | 113 | |
| 114 | bool failed = false; |
Garret Rieger | 03e88ea | 2019-01-28 16:15:06 -0800 | [diff] [blame] | 115 | for (unsigned int i = 0; i < num_output_glyphs; i++) |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 116 | { |
Garret Rieger | 03e88ea | 2019-01-28 16:15:06 -0800 | [diff] [blame] | 117 | unsigned int side_bearing = 0; |
| 118 | unsigned int advance = 0; |
| 119 | hb_codepoint_t old_gid; |
| 120 | if (plan->old_gid_for_new_gid (i, &old_gid)) |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 121 | { |
Garret Rieger | 03e88ea | 2019-01-28 16:15:06 -0800 | [diff] [blame] | 122 | // Glyph is not an empty glyph so copy advance and side bearing |
| 123 | // from the input font. |
| 124 | side_bearing = _mtx.get_side_bearing (old_gid); |
| 125 | advance = _mtx.get_advance (old_gid); |
| 126 | } |
| 127 | |
| 128 | bool has_advance = i < num_advances; |
| 129 | if (has_advance) |
| 130 | { |
Behdad Esfahbod | b986c6a | 2019-03-29 20:17:46 -0700 | [diff] [blame] | 131 | ((LongMetric *) dest_pos)->advance = advance; |
| 132 | ((LongMetric *) dest_pos)->sb = side_bearing; |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 133 | } |
| 134 | else |
| 135 | { |
Behdad Esfahbod | b986c6a | 2019-03-29 20:17:46 -0700 | [diff] [blame] | 136 | *((FWORD *) dest_pos) = side_bearing; |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 137 | } |
Garret Rieger | 03e88ea | 2019-01-28 16:15:06 -0800 | [diff] [blame] | 138 | dest_pos += (has_advance ? 4 : 2); |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 139 | } |
Rod Sheeter | 0e088a6 | 2018-02-14 21:11:45 -0800 | [diff] [blame] | 140 | _mtx.fini (); |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 141 | |
| 142 | // Amend header num hmetrics |
Garret Rieger | 1a94804 | 2018-03-19 18:39:22 -0700 | [diff] [blame] | 143 | if (failed || unlikely (!subset_update_header (plan, num_advances))) |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 144 | { |
Rod Sheeter | 0e088a6 | 2018-02-14 21:11:45 -0800 | [diff] [blame] | 145 | free (dest); |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 146 | return false; |
| 147 | } |
| 148 | |
| 149 | hb_blob_t *result = hb_blob_create ((const char *)dest, |
| 150 | dest_sz, |
| 151 | HB_MEMORY_MODE_READONLY, |
Garret Rieger | 4665aaa | 2018-02-23 15:36:14 -0800 | [diff] [blame] | 152 | dest, |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 153 | free); |
Garret Rieger | 251cc97 | 2018-05-30 12:23:51 -0700 | [diff] [blame] | 154 | bool success = plan->add_table (T::tableTag, result); |
Garret Rieger | 4665aaa | 2018-02-23 15:36:14 -0800 | [diff] [blame] | 155 | hb_blob_destroy (result); |
| 156 | return success; |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 157 | } |
| 158 | |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 159 | struct accelerator_t |
| 160 | { |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 161 | friend struct hmtxvmtx; |
| 162 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 163 | void init (hb_face_t *face, |
Garret Rieger | 03e88ea | 2019-01-28 16:15:06 -0800 | [diff] [blame] | 164 | unsigned int default_advance_ = 0) |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 165 | { |
Behdad Esfahbod | 96f1f52 | 2018-02-12 18:48:51 -0800 | [diff] [blame] | 166 | default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face); |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 167 | |
| 168 | bool got_font_extents = false; |
Ebrahim Byagowi | f7cfe99 | 2018-12-08 13:40:44 +0330 | [diff] [blame] | 169 | if (T::os2Tag != HB_TAG_NONE && face->table.OS2->is_typo_metrics ()) |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 170 | { |
Ebrahim Byagowi | f7cfe99 | 2018-12-08 13:40:44 +0330 | [diff] [blame] | 171 | ascender = abs (face->table.OS2->sTypoAscender); |
| 172 | descender = -abs (face->table.OS2->sTypoDescender); |
| 173 | line_gap = face->table.OS2->sTypoLineGap; |
| 174 | got_font_extents = (ascender | descender) != 0; |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 175 | } |
| 176 | |
Behdad Esfahbod | 9583e00 | 2018-07-22 22:40:32 -0700 | [diff] [blame] | 177 | hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table<H> (face); |
Behdad Esfahbod | eba1c16 | 2018-05-08 02:47:42 -0700 | [diff] [blame] | 178 | const H *_hea_table = _hea_blob->as<H> (); |
Behdad Esfahbod | a7f1595 | 2017-11-14 20:02:24 -0800 | [diff] [blame] | 179 | num_advances = _hea_table->numberOfLongMetrics; |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 180 | if (!got_font_extents) |
| 181 | { |
Behdad Esfahbod | 401cdf0 | 2018-10-23 17:00:49 -0700 | [diff] [blame] | 182 | ascender = abs (_hea_table->ascender); |
| 183 | descender = -abs (_hea_table->descender); |
Behdad Esfahbod | a7f1595 | 2017-11-14 20:02:24 -0800 | [diff] [blame] | 184 | line_gap = _hea_table->lineGap; |
| 185 | got_font_extents = (ascender | descender) != 0; |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 186 | } |
| 187 | hb_blob_destroy (_hea_blob); |
| 188 | |
Behdad Esfahbod | a7f1595 | 2017-11-14 20:02:24 -0800 | [diff] [blame] | 189 | has_font_extents = got_font_extents; |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 190 | |
Behdad Esfahbod | bb9abb4 | 2018-11-11 00:39:52 -0500 | [diff] [blame] | 191 | table = hb_sanitize_context_t().reference_table<hmtxvmtx> (face, T::tableTag); |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 192 | |
| 193 | /* Cap num_metrics() and num_advances() based on table length. */ |
Behdad Esfahbod | bb9abb4 | 2018-11-11 00:39:52 -0500 | [diff] [blame] | 194 | unsigned int len = table.get_length (); |
Behdad Esfahbod | a7f1595 | 2017-11-14 20:02:24 -0800 | [diff] [blame] | 195 | if (unlikely (num_advances * 4 > len)) |
| 196 | num_advances = len / 4; |
| 197 | num_metrics = num_advances + (len - 4 * num_advances) / 2; |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 198 | |
| 199 | /* We MUST set num_metrics to zero if num_advances is zero. |
| 200 | * Our get_advance() depends on that. */ |
Behdad Esfahbod | a7f1595 | 2017-11-14 20:02:24 -0800 | [diff] [blame] | 201 | if (unlikely (!num_advances)) |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 202 | { |
Behdad Esfahbod | a7f1595 | 2017-11-14 20:02:24 -0800 | [diff] [blame] | 203 | num_metrics = num_advances = 0; |
Behdad Esfahbod | da6aa3b | 2018-11-11 11:40:57 -0500 | [diff] [blame] | 204 | table.destroy (); |
Behdad Esfahbod | bb9abb4 | 2018-11-11 00:39:52 -0500 | [diff] [blame] | 205 | table = hb_blob_get_empty (); |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 206 | } |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 207 | |
Behdad Esfahbod | bb9abb4 | 2018-11-11 00:39:52 -0500 | [diff] [blame] | 208 | var_table = hb_sanitize_context_t().reference_table<HVARVVAR> (face, T::variationsTag); |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 209 | } |
| 210 | |
Ebrahim Byagowi | e412008 | 2018-12-17 21:31:01 +0330 | [diff] [blame] | 211 | void fini () |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 212 | { |
Behdad Esfahbod | da6aa3b | 2018-11-11 11:40:57 -0500 | [diff] [blame] | 213 | table.destroy (); |
| 214 | var_table.destroy (); |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 215 | } |
| 216 | |
Behdad Esfahbod | 8dc6296 | 2018-10-15 01:09:05 -0700 | [diff] [blame] | 217 | /* TODO Add variations version. */ |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 218 | unsigned int get_side_bearing (hb_codepoint_t glyph) const |
Behdad Esfahbod | 8dc6296 | 2018-10-15 01:09:05 -0700 | [diff] [blame] | 219 | { |
| 220 | if (glyph < num_advances) |
| 221 | return table->longMetricZ[glyph].sb; |
| 222 | |
Behdad Esfahbod | e012502 | 2018-10-31 18:14:00 -0700 | [diff] [blame] | 223 | if (unlikely (glyph >= num_metrics)) |
Behdad Esfahbod | 8dc6296 | 2018-10-15 01:09:05 -0700 | [diff] [blame] | 224 | return 0; |
| 225 | |
| 226 | const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances]; |
| 227 | return bearings[glyph - num_advances]; |
| 228 | } |
| 229 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 230 | unsigned int get_advance (hb_codepoint_t glyph) const |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 231 | { |
Behdad Esfahbod | a7f1595 | 2017-11-14 20:02:24 -0800 | [diff] [blame] | 232 | if (unlikely (glyph >= num_metrics)) |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 233 | { |
Behdad Esfahbod | 8dc6296 | 2018-10-15 01:09:05 -0700 | [diff] [blame] | 234 | /* If num_metrics is zero, it means we don't have the metrics table |
| 235 | * for this direction: return default advance. Otherwise, it means that the |
| 236 | * glyph index is out of bound: return zero. */ |
| 237 | if (num_metrics) |
| 238 | return 0; |
| 239 | else |
| 240 | return default_advance; |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 241 | } |
| 242 | |
Behdad Esfahbod | dff2c45 | 2018-09-10 23:29:26 +0200 | [diff] [blame] | 243 | return table->longMetricZ[MIN (glyph, (uint32_t) num_advances - 1)].advance; |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 244 | } |
| 245 | |
Ebrahim Byagowi | b2ebaa9 | 2018-12-16 22:38:10 +0330 | [diff] [blame] | 246 | unsigned int get_advance (hb_codepoint_t glyph, |
| 247 | hb_font_t *font) const |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 248 | { |
Rod Sheeter | 0758cbc | 2018-02-15 11:29:01 -0800 | [diff] [blame] | 249 | unsigned int advance = get_advance (glyph); |
Ebrahim Byagowi | 11aa046 | 2018-11-15 23:10:56 +0330 | [diff] [blame] | 250 | if (likely (glyph < num_metrics)) |
Rod Sheeter | 0758cbc | 2018-02-15 11:29:01 -0800 | [diff] [blame] | 251 | { |
Behdad Esfahbod | 8dc6296 | 2018-10-15 01:09:05 -0700 | [diff] [blame] | 252 | advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?! |
Rod Sheeter | 0758cbc | 2018-02-15 11:29:01 -0800 | [diff] [blame] | 253 | } |
Garret Rieger | 64cf53d | 2018-03-02 17:33:49 -0800 | [diff] [blame] | 254 | return advance; |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 255 | } |
| 256 | |
Garret Rieger | 03e88ea | 2019-01-28 16:15:06 -0800 | [diff] [blame] | 257 | unsigned int num_advances_for_subset (const hb_subset_plan_t *plan) const |
| 258 | { |
| 259 | unsigned int num_advances = plan->num_output_glyphs (); |
| 260 | unsigned int last_advance = _advance_for_new_gid (plan, |
| 261 | num_advances - 1); |
| 262 | while (num_advances > 1 && |
| 263 | last_advance == _advance_for_new_gid (plan, |
| 264 | num_advances - 2)) |
| 265 | { |
| 266 | num_advances--; |
| 267 | } |
| 268 | |
| 269 | return num_advances; |
| 270 | } |
| 271 | |
| 272 | private: |
| 273 | unsigned int _advance_for_new_gid (const hb_subset_plan_t *plan, |
| 274 | hb_codepoint_t new_gid) const |
| 275 | { |
| 276 | hb_codepoint_t old_gid; |
| 277 | if (!plan->old_gid_for_new_gid (new_gid, &old_gid)) |
| 278 | return 0; |
| 279 | |
| 280 | return get_advance (old_gid); |
| 281 | } |
| 282 | |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 283 | public: |
| 284 | bool has_font_extents; |
Behdad Esfahbod | 48d16c2 | 2018-11-14 09:56:30 -0500 | [diff] [blame] | 285 | int ascender; |
| 286 | int descender; |
| 287 | int line_gap; |
Behdad Esfahbod | a7f1595 | 2017-11-14 20:02:24 -0800 | [diff] [blame] | 288 | |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 289 | protected: |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 290 | unsigned int num_metrics; |
| 291 | unsigned int num_advances; |
| 292 | unsigned int default_advance; |
Behdad Esfahbod | a7f1595 | 2017-11-14 20:02:24 -0800 | [diff] [blame] | 293 | |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 294 | private: |
Behdad Esfahbod | bb9abb4 | 2018-11-11 00:39:52 -0500 | [diff] [blame] | 295 | hb_blob_ptr_t<hmtxvmtx> table; |
| 296 | hb_blob_ptr_t<HVARVVAR> var_table; |
Behdad Esfahbod | a85d7ea | 2017-11-14 20:00:34 -0800 | [diff] [blame] | 297 | }; |
| 298 | |
| 299 | protected: |
Behdad Esfahbod | dff2c45 | 2018-09-10 23:29:26 +0200 | [diff] [blame] | 300 | UnsizedArrayOf<LongMetric>longMetricZ;/* Paired advance width and leading |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 301 | * bearing values for each glyph. The |
| 302 | * value numOfHMetrics comes from |
| 303 | * the 'hhea' table. If the font is |
| 304 | * monospaced, only one entry need |
| 305 | * be in the array, but that entry is |
| 306 | * required. The last entry applies to |
| 307 | * all subsequent glyphs. */ |
Behdad Esfahbod | dff2c45 | 2018-09-10 23:29:26 +0200 | [diff] [blame] | 308 | /*UnsizedArrayOf<FWORD> leadingBearingX;*//* Here the advance is assumed |
Behdad Esfahbod | d41b809 | 2014-09-25 13:04:08 +0300 | [diff] [blame] | 309 | * to be the same as the advance |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 310 | * for the last entry above. The |
| 311 | * number of entries in this array is |
| 312 | * derived from numGlyphs (from 'maxp' |
Behdad Esfahbod | d41b809 | 2014-09-25 13:04:08 +0300 | [diff] [blame] | 313 | * table) minus numberOfLongMetrics. |
| 314 | * This generally is used with a run |
| 315 | * of monospaced glyphs (e.g., Kanji |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 316 | * fonts or Courier fonts). Only one |
| 317 | * run is allowed and it must be at |
| 318 | * the end. This allows a monospaced |
Behdad Esfahbod | d41b809 | 2014-09-25 13:04:08 +0300 | [diff] [blame] | 319 | * font to vary the side bearing |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 320 | * values for each glyph. */ |
| 321 | public: |
Behdad Esfahbod | dff2c45 | 2018-09-10 23:29:26 +0200 | [diff] [blame] | 322 | DEFINE_SIZE_ARRAY (0, longMetricZ); |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 323 | }; |
| 324 | |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 325 | struct hmtx : hmtxvmtx<hmtx, hhea> { |
Behdad Esfahbod | ef00654 | 2019-01-22 12:08:57 +0100 | [diff] [blame] | 326 | static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx; |
| 327 | static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR; |
| 328 | static constexpr hb_tag_t os2Tag = HB_OT_TAG_OS2; |
Behdad Esfahbod | d41b809 | 2014-09-25 13:04:08 +0300 | [diff] [blame] | 329 | }; |
Rod Sheeter | fa87770 | 2018-02-14 14:16:25 -0800 | [diff] [blame] | 330 | struct vmtx : hmtxvmtx<vmtx, vhea> { |
Behdad Esfahbod | ef00654 | 2019-01-22 12:08:57 +0100 | [diff] [blame] | 331 | static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx; |
| 332 | static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR; |
| 333 | static constexpr hb_tag_t os2Tag = HB_TAG_NONE; |
Behdad Esfahbod | d41b809 | 2014-09-25 13:04:08 +0300 | [diff] [blame] | 334 | }; |
Behdad Esfahbod | 7c8e844 | 2012-08-28 17:57:49 -0400 | [diff] [blame] | 335 | |
Behdad Esfahbod | 3a0b3a2 | 2018-08-26 15:11:24 -0700 | [diff] [blame] | 336 | struct hmtx_accelerator_t : hmtx::accelerator_t {}; |
| 337 | struct vmtx_accelerator_t : vmtx::accelerator_t {}; |
| 338 | |
Behdad Esfahbod | 7d52e66 | 2012-11-16 18:49:54 -0800 | [diff] [blame] | 339 | } /* namespace OT */ |
Behdad Esfahbod | 7c8e844 | 2012-08-28 17:57:49 -0400 | [diff] [blame] | 340 | |
| 341 | |
Behdad Esfahbod | 24bcdbc | 2011-08-24 19:13:15 +0200 | [diff] [blame] | 342 | #endif /* HB_OT_HMTX_TABLE_HH */ |