blob: ec2f8892fde1201f683a92fdfa09cf348605cdc1 [file] [log] [blame]
Garret Riegera2965f22018-01-31 14:53:09 -08001/*
Behdad Esfahbodbfa87162018-02-10 13:37:28 -06002 * Copyright © 2018 Google, Inc.
Garret Riegera2965f22018-01-31 14:53:09 -08003 *
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 Sheeterd463e9f2018-02-14 15:04:15 -080024 * Google Author(s): Garret Rieger, Rod Sheeter, Behdad Esfahbod
Garret Riegera2965f22018-01-31 14:53:09 -080025 */
26
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070027#include "hb.hh"
28#include "hb-open-type.hh"
Rod Sheeter0859a002018-02-07 15:59:36 -080029
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070030#include "hb-subset.hh"
Garret Riegera2965f22018-01-31 14:53:09 -080031
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070032#include "hb-open-file.hh"
Rod Sheeter0859a002018-02-07 15:59:36 -080033#include "hb-ot-cmap-table.hh"
Garret Rieger6a45e5d2018-02-06 16:04:09 -080034#include "hb-ot-glyf-table.hh"
Garret Riegerfe428622018-02-21 14:18:49 -080035#include "hb-ot-hdmx-table.hh"
Garret Rieger83e1ef92018-02-12 11:22:32 -080036#include "hb-ot-head-table.hh"
Rod Sheeterfa877702018-02-14 14:16:25 -080037#include "hb-ot-hhea-table.hh"
38#include "hb-ot-hmtx-table.hh"
Garret Rieger83e1ef92018-02-12 11:22:32 -080039#include "hb-ot-maxp-table.hh"
Garret Rieger24904382018-02-12 17:31:01 -080040#include "hb-ot-os2-table.hh"
Garret Riegerdd107692018-03-06 18:33:39 -080041#include "hb-ot-post-table.hh"
Michiharu Arizafdbfa182018-08-16 00:13:09 -070042#include "hb-ot-cff1-table.hh"
Michiharu Ariza3a61c3e2018-07-18 14:17:52 -070043#include "hb-ot-cff2-table.hh"
Michiharu Arizaf212c052018-09-20 09:45:43 -070044#include "hb-ot-vorg-table.hh"
Qunxin Liu408c1da2019-03-29 10:34:32 -070045#include "hb-ot-name-table.hh"
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070046#include "hb-ot-layout-gsub-table.hh"
47#include "hb-ot-layout-gpos-table.hh"
Garret Rieger6a45e5d2018-02-06 16:04:09 -080048
Behdad Esfahbod2da0d872018-02-07 12:44:35 -050049
Behdad Esfahbod19e800c2019-04-15 12:07:00 -040050HB_UNUSED static inline unsigned int
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070051_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
Behdad Esfahbod19e800c2019-04-15 12:07:00 -040052 unsigned int table_len);
53static inline unsigned int
54_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
55 unsigned int table_len)
Garret Riegera2965f22018-01-31 14:53:09 -080056{
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070057 unsigned int src_glyphs = plan->source->get_num_glyphs ();
Garret Rieger05e99c82019-01-28 17:05:04 -080058 unsigned int dst_glyphs = plan->glyphset ()->get_population ();
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070059
Behdad Esfahbod5f17dbc2018-09-07 10:24:22 -040060 if (unlikely (!src_glyphs))
61 return 512 + table_len;
62
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070063 return 512 + (unsigned int) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
Garret Riegera2965f22018-01-31 14:53:09 -080064}
65
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070066template<typename TableType>
67static bool
68_subset2 (hb_subset_plan_t *plan)
Garret Riegera2965f22018-01-31 14:53:09 -080069{
Qunxin Liu209491f2019-05-29 14:03:17 -070070 bool result = false;
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070071 hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
72 const TableType *table = source_blob->as<TableType> ();
Garret Riegera2965f22018-01-31 14:53:09 -080073
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070074 hb_tag_t tag = TableType::tableTag;
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070075 if (source_blob->data)
76 {
Behdad Esfahbod3a4e5dd2018-10-29 18:05:25 -070077 hb_vector_t<char> buf;
Behdad Esfahbod521262b2019-05-07 11:08:08 -070078 /* TODO Not all tables are glyph-related. 'name' table size for example should not be
79 * affected by number of glyphs. Accommodate that. */
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070080 unsigned int buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +033081 DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070082 if (unlikely (!buf.alloc (buf_size)))
83 {
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +033084 DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
Ebrahim Byagowi28aba782019-08-23 16:47:15 +043085 hb_blob_destroy (source_blob);
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070086 return false;
87 }
88 retry:
Behdad Esfahbod861bc752018-11-29 14:34:44 -050089 hb_serialize_context_t serializer ((void *) buf, buf_size);
Behdad Esfahbod2e675cc2019-04-01 16:45:50 -070090 serializer.start_serialize<TableType> ();
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070091 hb_subset_context_t c (plan, &serializer);
Behdad Esfahbod6977a952019-04-27 10:05:25 -070092 bool needed = table->subset (&c);
Behdad Esfahbodfe05e482019-03-30 15:06:25 -070093 if (serializer.ran_out_of_room)
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070094 {
95 buf_size += (buf_size >> 1) + 32;
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +033096 DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (tag), buf_size);
Behdad Esfahboda1e5e072018-09-05 16:24:28 -070097 if (unlikely (!buf.alloc (buf_size)))
98 {
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +033099 DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size);
Ebrahim Byagowi28aba782019-08-23 16:47:15 +0430100 hb_blob_destroy (source_blob);
Behdad Esfahboda1e5e072018-09-05 16:24:28 -0700101 return false;
102 }
103 goto retry;
104 }
Qunxin Liu19afd252019-04-24 14:02:29 -0700105 serializer.end_serialize ();
Behdad Esfahbod2b051e72019-04-27 10:01:11 -0700106
Behdad Esfahbod6977a952019-04-27 10:05:25 -0700107 result = !serializer.in_error ();
Behdad Esfahbod2b051e72019-04-27 10:01:11 -0700108
Behdad Esfahboda1e5e072018-09-05 16:24:28 -0700109 if (result)
110 {
Behdad Esfahbod6977a952019-04-27 10:05:25 -0700111 if (needed)
112 {
113 hb_blob_t *dest_blob = serializer.copy_blob ();
114 DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
115 result = c.plan->add_table (tag, dest_blob);
116 hb_blob_destroy (dest_blob);
117 }
118 else
119 {
120 DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
121 }
Behdad Esfahboda1e5e072018-09-05 16:24:28 -0700122 }
123 }
124 else
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330125 DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
Behdad Esfahboda1e5e072018-09-05 16:24:28 -0700126
127 hb_blob_destroy (source_blob);
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330128 DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
Behdad Esfahboda1e5e072018-09-05 16:24:28 -0700129 return result;
Garret Riegera2965f22018-01-31 14:53:09 -0800130}
131
Rod Sheeter0859a002018-02-07 15:59:36 -0800132template<typename TableType>
Rod Sheeter3ed70e52018-02-14 15:24:49 -0800133static bool
Rod Sheeterfa877702018-02-14 14:16:25 -0800134_subset (hb_subset_plan_t *plan)
Rod Sheeter0859a002018-02-07 15:59:36 -0800135{
Behdad Esfahboded7b2e52018-08-01 23:59:09 -0700136 hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
Behdad Esfahbodeba1c162018-05-08 02:47:42 -0700137 const TableType *table = source_blob->as<TableType> ();
Rod Sheeter13193a92018-02-07 16:09:52 -0800138
Garret Rieger07851aa2018-03-26 20:56:56 -0600139 hb_tag_t tag = TableType::tableTag;
Garret Riegerec302ad2018-02-22 11:57:35 -0800140 hb_bool_t result = false;
Behdad Esfahbodb912fbe2018-08-06 06:30:12 -0700141 if (source_blob->data)
Behdad Esfahbodd237ce72018-08-29 18:13:07 -0700142 result = table->subset (plan);
143 else
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330144 DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
Garret Riegerec302ad2018-02-22 11:57:35 -0800145
146 hb_blob_destroy (source_blob);
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330147 DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
Garret Riegerec302ad2018-02-22 11:57:35 -0800148 return result;
Rod Sheeter0859a002018-02-07 15:59:36 -0800149}
Garret Riegera2965f22018-01-31 14:53:09 -0800150
Behdad Esfahbod6804b612018-02-07 13:47:35 -0500151
Behdad Esfahboda981d792018-02-10 15:17:28 -0600152static bool
Garret Riegeraac7d962018-02-08 18:18:16 -0800153_subset_table (hb_subset_plan_t *plan,
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330154 hb_tag_t tag)
Garret Riegeraac7d962018-02-08 18:18:16 -0800155{
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330156 DEBUG_MSG(SUBSET, nullptr, "begin subset %c%c%c%c", HB_UNTAG (tag));
Rod Sheeterfa877702018-02-14 14:16:25 -0800157 bool result = true;
Garret Riegeraac7d962018-02-08 18:18:16 -0800158 switch (tag) {
159 case HB_OT_TAG_glyf:
rsheeter02d4d4f2019-05-08 14:43:18 -0700160 result = _subset2<const OT::glyf> (plan);
Rod Sheeterfa877702018-02-14 14:16:25 -0800161 break;
Garret Riegeraa4aa232018-02-21 17:43:32 -0800162 case HB_OT_TAG_hdmx:
Garret Riegerd5decf92019-05-07 15:47:38 -0700163 result = _subset2<const OT::hdmx> (plan);
Garret Riegeraa4aa232018-02-21 17:43:32 -0800164 break;
Qunxin Liu408c1da2019-03-29 10:34:32 -0700165 case HB_OT_TAG_name:
Qunxin Liu19afd252019-04-24 14:02:29 -0700166 result = _subset2<const OT::name> (plan);
Qunxin Liu408c1da2019-03-29 10:34:32 -0700167 break;
Garret Rieger1582eab2018-02-09 12:52:08 -0800168 case HB_OT_TAG_head:
Rod Sheeter9bd6d252018-02-23 13:05:58 -0800169 // TODO that won't work well if there is no glyf
170 DEBUG_MSG(SUBSET, nullptr, "skip head, handled by glyf");
Rod Sheeterfa877702018-02-14 14:16:25 -0800171 result = true;
172 break;
173 case HB_OT_TAG_hhea:
Rod Sheeter9bd6d252018-02-23 13:05:58 -0800174 DEBUG_MSG(SUBSET, nullptr, "skip hhea handled by hmtx");
Garret Rieger1582eab2018-02-09 12:52:08 -0800175 return true;
Rod Sheeterfa877702018-02-14 14:16:25 -0800176 case HB_OT_TAG_hmtx:
Qunxin Liu209491f2019-05-29 14:03:17 -0700177 result = _subset2<const OT::hmtx> (plan);
Rod Sheeterfa877702018-02-14 14:16:25 -0800178 break;
Garret Rieger0e8f9432018-03-06 13:08:20 -0800179 case HB_OT_TAG_vhea:
Garret Rieger91867cd2018-03-07 10:17:06 -0800180 DEBUG_MSG(SUBSET, nullptr, "skip vhea handled by vmtx");
Garret Rieger0e8f9432018-03-06 13:08:20 -0800181 return true;
Garret Rieger64cf53d2018-03-02 17:33:49 -0800182 case HB_OT_TAG_vmtx:
Qunxin Liu209491f2019-05-29 14:03:17 -0700183 result = _subset2<const OT::vmtx> (plan);
Garret Rieger64cf53d2018-03-02 17:33:49 -0800184 break;
Garret Rieger83e1ef92018-02-12 11:22:32 -0800185 case HB_OT_TAG_maxp:
Qunxin Liudb938472019-06-04 10:30:53 -0700186 result = _subset2<const OT::maxp> (plan);
Garret Riegerdf6d7802018-02-12 17:56:17 -0800187 break;
Garret Riegeraac7d962018-02-08 18:18:16 -0800188 case HB_OT_TAG_loca:
Rod Sheeter9bd6d252018-02-23 13:05:58 -0800189 DEBUG_MSG(SUBSET, nullptr, "skip loca handled by glyf");
Garret Riegeraac7d962018-02-08 18:18:16 -0800190 return true;
191 case HB_OT_TAG_cmap:
Qunxin Liu37572882019-06-25 13:17:30 -0700192 result = _subset2<const OT::cmap> (plan);
Rod Sheeter9275bd02018-02-09 17:33:34 -0800193 break;
Khaled Hosny2c68f342018-11-02 23:06:00 +0200194 case HB_OT_TAG_OS2:
Garret Riegerf9b1ae72019-06-05 17:40:59 -0700195 result = _subset2<const OT::OS2> (plan);
Garret Rieger24904382018-02-12 17:31:01 -0800196 break;
Garret Riegerdd107692018-03-06 18:33:39 -0800197 case HB_OT_TAG_post:
Qunxin Liu93d592e2019-06-05 16:51:31 -0700198 result = _subset2<const OT::post> (plan);
Garret Riegerdd107692018-03-06 18:33:39 -0800199 break;
Behdad Esfahbod5ea8ad52019-05-10 23:36:42 -0700200
201#ifndef HB_NO_SUBSET_CFF
Michiharu Arizae67bb3f2018-08-16 00:25:57 -0700202 case HB_OT_TAG_cff1:
203 result = _subset<const OT::cff1> (plan);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700204 break;
Michiharu Ariza3a61c3e2018-07-18 14:17:52 -0700205 case HB_OT_TAG_cff2:
206 result = _subset<const OT::cff2> (plan);
207 break;
Michiharu Arizaf212c052018-09-20 09:45:43 -0700208 case HB_OT_TAG_VORG:
Qunxin Liu9bd8d662019-06-12 11:02:48 -0700209 result = _subset2<const OT::VORG> (plan);
Michiharu Arizaf212c052018-09-20 09:45:43 -0700210 break;
Behdad Esfahbod5ea8ad52019-05-10 23:36:42 -0700211#endif
Behdad Esfahbod47e538a2019-04-12 22:50:22 -0400212
Behdad Esfahbod227d85e2019-05-10 23:15:58 -0700213#ifndef HB_NO_SUBSET_LAYOUT
Behdad Esfahbod42a10122018-12-13 19:39:59 -0500214 case HB_OT_TAG_GDEF:
215 result = _subset2<const OT::GDEF> (plan);
216 break;
Behdad Esfahboda1e5e072018-09-05 16:24:28 -0700217 case HB_OT_TAG_GSUB:
218 result = _subset2<const OT::GSUB> (plan);
219 break;
220 case HB_OT_TAG_GPOS:
221 result = _subset2<const OT::GPOS> (plan);
222 break;
Behdad Esfahbod47e538a2019-04-12 22:50:22 -0400223#endif
Behdad Esfahboda1e5e072018-09-05 16:24:28 -0700224
Garret Riegeraac7d962018-02-08 18:18:16 -0800225 default:
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330226 hb_blob_t *source_table = hb_face_reference_table (plan->source, tag);
Garret Rieger66b0a392018-02-23 15:41:52 -0800227 if (likely (source_table))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330228 result = plan->add_table (tag, source_table);
Rod Sheeterfa877702018-02-14 14:16:25 -0800229 else
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330230 result = false;
Garret Rieger66b0a392018-02-23 15:41:52 -0800231 hb_blob_destroy (source_table);
Rod Sheeter9275bd02018-02-09 17:33:34 -0800232 break;
Garret Rieger83e1ef92018-02-12 11:22:32 -0800233 }
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330234 DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG (tag), result ? "ok" : "FAILED");
Rod Sheeter2d026522018-02-21 09:42:46 -0800235 return result;
Garret Riegeraac7d962018-02-08 18:18:16 -0800236}
237
Rod Sheeter692f86e2018-02-12 11:29:23 -0800238static bool
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330239_should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
Rod Sheeter692f86e2018-02-12 11:29:23 -0800240{
Garret Rieger3be0ffe2019-05-16 11:29:15 -0700241 if (plan->drop_tables->has (tag))
242 return true;
243
Garret Rieger39b2f692018-03-08 16:30:36 -0800244 switch (tag) {
245 case HB_TAG ('c', 'v', 'a', 'r'): /* hint table, fallthrough */
246 case HB_TAG ('c', 'v', 't', ' '): /* hint table, fallthrough */
247 case HB_TAG ('f', 'p', 'g', 'm'): /* hint table, fallthrough */
248 case HB_TAG ('p', 'r', 'e', 'p'): /* hint table, fallthrough */
249 case HB_TAG ('h', 'd', 'm', 'x'): /* hint table, fallthrough */
250 case HB_TAG ('V', 'D', 'M', 'X'): /* hint table, fallthrough */
251 return plan->drop_hints;
Behdad Esfahbod47e538a2019-04-12 22:50:22 -0400252
Garret Rieger0ff36182019-05-17 15:30:01 -0700253#ifdef HB_NO_SUBSET_LAYOUT
Garret Riegera5673da2018-06-07 14:23:03 -0700254 // Drop Layout Tables if requested.
Behdad Esfahbod57610312018-12-12 21:21:26 -0500255 case HB_OT_TAG_GDEF:
256 case HB_OT_TAG_GPOS:
257 case HB_OT_TAG_GSUB:
Garret Riegerff7fc6d2019-05-22 17:36:16 -0700258 case HB_TAG ('m', 'o', 'r', 'x'):
259 case HB_TAG ('m', 'o', 'r', 't'):
260 case HB_TAG ('k', 'e', 'r', 'x'):
261 case HB_TAG ('k', 'e', 'r', 'n'):
Behdad Esfahbod47e538a2019-04-12 22:50:22 -0400262 return true;
263#endif
Behdad Esfahbod47e538a2019-04-12 22:50:22 -0400264
Garret Rieger39b2f692018-03-08 16:30:36 -0800265 default:
266 return false;
Garret Rieger24904382018-02-12 17:31:01 -0800267 }
Rod Sheeter692f86e2018-02-12 11:29:23 -0800268}
269
Garret Riegera2965f22018-01-31 14:53:09 -0800270/**
271 * hb_subset:
Behdad Esfahbod7fd0b612018-02-07 16:44:52 -0600272 * @source: font face data to be subset.
Garret Riegera2965f22018-01-31 14:53:09 -0800273 * @input: input to use for the subsetting.
Garret Riegera2965f22018-01-31 14:53:09 -0800274 *
Behdad Esfahbodf39166f2018-08-29 18:09:55 -0700275 * Subsets a font according to provided input.
Garret Riegera2965f22018-01-31 14:53:09 -0800276 **/
Behdad Esfahbodaf028122018-02-07 13:07:46 -0500277hb_face_t *
278hb_subset (hb_face_t *source,
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330279 hb_subset_input_t *input)
Garret Riegera2965f22018-01-31 14:53:09 -0800280{
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330281 if (unlikely (!input || !source)) return hb_face_get_empty ();
Garret Riegera2965f22018-01-31 14:53:09 -0800282
Behdad Esfahbodf39166f2018-08-29 18:09:55 -0700283 hb_subset_plan_t *plan = hb_subset_plan_create (source, input);
Garret Rieger31ec3c22018-02-06 15:37:34 -0800284
Garret Riegeraac7d962018-02-08 18:18:16 -0800285 hb_tag_t table_tags[32];
286 unsigned int offset = 0, count;
Rod Sheeter13193a92018-02-07 16:09:52 -0800287 bool success = true;
Ebrahim Byagowi41d6e952019-09-02 01:41:48 +0430288 hb_set_t tags_set;
Garret Riegeraac7d962018-02-08 18:18:16 -0800289 do {
290 count = ARRAY_LENGTH (table_tags);
291 hb_face_get_table_tags (source, offset, &count, table_tags);
292 for (unsigned int i = 0; i < count; i++)
293 {
294 hb_tag_t tag = table_tags[i];
Ebrahim Byagowi41d6e952019-09-02 01:41:48 +0430295 if (_should_drop_table (plan, tag) && !tags_set.has (tag))
Rod Sheeter692f86e2018-02-12 11:29:23 -0800296 {
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330297 DEBUG_MSG(SUBSET, nullptr, "drop %c%c%c%c", HB_UNTAG (tag));
298 continue;
Rod Sheeter692f86e2018-02-12 11:29:23 -0800299 }
Ebrahim Byagowi41d6e952019-09-02 01:41:48 +0430300 tags_set.add (tag);
Rod Sheeterfa877702018-02-14 14:16:25 -0800301 success = success && _subset_table (plan, tag);
Garret Riegeraac7d962018-02-08 18:18:16 -0800302 }
Garret Rieger1c337272018-03-27 10:42:19 -0700303 offset += count;
Behdad Esfahbodd237ce72018-08-29 18:13:07 -0700304 } while (success && count == ARRAY_LENGTH (table_tags));
Rod Sheeter13193a92018-02-07 16:09:52 -0800305
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330306 hb_face_t *result = success ? hb_face_reference (plan->dest) : hb_face_get_empty ();
Garret Rieger5df080b2018-02-12 10:15:59 -0800307 hb_subset_plan_destroy (plan);
Rod Sheeterfa877702018-02-14 14:16:25 -0800308 return result;
Garret Riegera2965f22018-01-31 14:53:09 -0800309}