1*2d1272b8SAndroid Build Coastguard Worker /* 2*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2018 Adobe Inc. 3*2d1272b8SAndroid Build Coastguard Worker * 4*2d1272b8SAndroid Build Coastguard Worker * This is part of HarfBuzz, a text shaping library. 5*2d1272b8SAndroid Build Coastguard Worker * 6*2d1272b8SAndroid Build Coastguard Worker * Permission is hereby granted, without written agreement and without 7*2d1272b8SAndroid Build Coastguard Worker * license or royalty fees, to use, copy, modify, and distribute this 8*2d1272b8SAndroid Build Coastguard Worker * software and its documentation for any purpose, provided that the 9*2d1272b8SAndroid Build Coastguard Worker * above copyright notice and the following two paragraphs appear in 10*2d1272b8SAndroid Build Coastguard Worker * all copies of this software. 11*2d1272b8SAndroid Build Coastguard Worker * 12*2d1272b8SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13*2d1272b8SAndroid Build Coastguard Worker * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14*2d1272b8SAndroid Build Coastguard Worker * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15*2d1272b8SAndroid Build Coastguard Worker * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16*2d1272b8SAndroid Build Coastguard Worker * DAMAGE. 17*2d1272b8SAndroid Build Coastguard Worker * 18*2d1272b8SAndroid Build Coastguard Worker * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19*2d1272b8SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20*2d1272b8SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21*2d1272b8SAndroid Build Coastguard Worker * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22*2d1272b8SAndroid Build Coastguard Worker * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23*2d1272b8SAndroid Build Coastguard Worker * 24*2d1272b8SAndroid Build Coastguard Worker * Adobe Author(s): Michiharu Ariza 25*2d1272b8SAndroid Build Coastguard Worker */ 26*2d1272b8SAndroid Build Coastguard Worker 27*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_SUBSET_CFF_COMMON_HH 28*2d1272b8SAndroid Build Coastguard Worker #define HB_SUBSET_CFF_COMMON_HH 29*2d1272b8SAndroid Build Coastguard Worker 30*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh" 31*2d1272b8SAndroid Build Coastguard Worker 32*2d1272b8SAndroid Build Coastguard Worker #include "hb-subset-plan.hh" 33*2d1272b8SAndroid Build Coastguard Worker #include "hb-cff-interp-cs-common.hh" 34*2d1272b8SAndroid Build Coastguard Worker 35*2d1272b8SAndroid Build Coastguard Worker namespace CFF { 36*2d1272b8SAndroid Build Coastguard Worker 37*2d1272b8SAndroid Build Coastguard Worker /* Used for writing a temporary charstring */ 38*2d1272b8SAndroid Build Coastguard Worker struct str_encoder_t 39*2d1272b8SAndroid Build Coastguard Worker { str_encoder_tCFF::str_encoder_t40*2d1272b8SAndroid Build Coastguard Worker str_encoder_t (str_buff_t &buff_) 41*2d1272b8SAndroid Build Coastguard Worker : buff (buff_) {} 42*2d1272b8SAndroid Build Coastguard Worker resetCFF::str_encoder_t43*2d1272b8SAndroid Build Coastguard Worker void reset () { buff.reset (); } 44*2d1272b8SAndroid Build Coastguard Worker encode_byteCFF::str_encoder_t45*2d1272b8SAndroid Build Coastguard Worker void encode_byte (unsigned char b) 46*2d1272b8SAndroid Build Coastguard Worker { 47*2d1272b8SAndroid Build Coastguard Worker if (likely ((signed) buff.length < buff.allocated)) 48*2d1272b8SAndroid Build Coastguard Worker buff.arrayZ[buff.length++] = b; 49*2d1272b8SAndroid Build Coastguard Worker else 50*2d1272b8SAndroid Build Coastguard Worker buff.push (b); 51*2d1272b8SAndroid Build Coastguard Worker } 52*2d1272b8SAndroid Build Coastguard Worker encode_intCFF::str_encoder_t53*2d1272b8SAndroid Build Coastguard Worker void encode_int (int v) 54*2d1272b8SAndroid Build Coastguard Worker { 55*2d1272b8SAndroid Build Coastguard Worker if ((-1131 <= v) && (v <= 1131)) 56*2d1272b8SAndroid Build Coastguard Worker { 57*2d1272b8SAndroid Build Coastguard Worker if ((-107 <= v) && (v <= 107)) 58*2d1272b8SAndroid Build Coastguard Worker encode_byte (v + 139); 59*2d1272b8SAndroid Build Coastguard Worker else if (v > 0) 60*2d1272b8SAndroid Build Coastguard Worker { 61*2d1272b8SAndroid Build Coastguard Worker v -= 108; 62*2d1272b8SAndroid Build Coastguard Worker encode_byte ((v >> 8) + OpCode_TwoBytePosInt0); 63*2d1272b8SAndroid Build Coastguard Worker encode_byte (v & 0xFF); 64*2d1272b8SAndroid Build Coastguard Worker } 65*2d1272b8SAndroid Build Coastguard Worker else 66*2d1272b8SAndroid Build Coastguard Worker { 67*2d1272b8SAndroid Build Coastguard Worker v = -v - 108; 68*2d1272b8SAndroid Build Coastguard Worker encode_byte ((v >> 8) + OpCode_TwoByteNegInt0); 69*2d1272b8SAndroid Build Coastguard Worker encode_byte (v & 0xFF); 70*2d1272b8SAndroid Build Coastguard Worker } 71*2d1272b8SAndroid Build Coastguard Worker } 72*2d1272b8SAndroid Build Coastguard Worker else 73*2d1272b8SAndroid Build Coastguard Worker { 74*2d1272b8SAndroid Build Coastguard Worker if (unlikely (v < -32768)) 75*2d1272b8SAndroid Build Coastguard Worker v = -32768; 76*2d1272b8SAndroid Build Coastguard Worker else if (unlikely (v > 32767)) 77*2d1272b8SAndroid Build Coastguard Worker v = 32767; 78*2d1272b8SAndroid Build Coastguard Worker encode_byte (OpCode_shortint); 79*2d1272b8SAndroid Build Coastguard Worker encode_byte ((v >> 8) & 0xFF); 80*2d1272b8SAndroid Build Coastguard Worker encode_byte (v & 0xFF); 81*2d1272b8SAndroid Build Coastguard Worker } 82*2d1272b8SAndroid Build Coastguard Worker } 83*2d1272b8SAndroid Build Coastguard Worker 84*2d1272b8SAndroid Build Coastguard Worker // Encode number for CharString encode_num_csCFF::str_encoder_t85*2d1272b8SAndroid Build Coastguard Worker void encode_num_cs (const number_t& n) 86*2d1272b8SAndroid Build Coastguard Worker { 87*2d1272b8SAndroid Build Coastguard Worker if (n.in_int_range ()) 88*2d1272b8SAndroid Build Coastguard Worker { 89*2d1272b8SAndroid Build Coastguard Worker encode_int (n.to_int ()); 90*2d1272b8SAndroid Build Coastguard Worker } 91*2d1272b8SAndroid Build Coastguard Worker else 92*2d1272b8SAndroid Build Coastguard Worker { 93*2d1272b8SAndroid Build Coastguard Worker int32_t v = n.to_fixed (); 94*2d1272b8SAndroid Build Coastguard Worker encode_byte (OpCode_fixedcs); 95*2d1272b8SAndroid Build Coastguard Worker encode_byte ((v >> 24) & 0xFF); 96*2d1272b8SAndroid Build Coastguard Worker encode_byte ((v >> 16) & 0xFF); 97*2d1272b8SAndroid Build Coastguard Worker encode_byte ((v >> 8) & 0xFF); 98*2d1272b8SAndroid Build Coastguard Worker encode_byte (v & 0xFF); 99*2d1272b8SAndroid Build Coastguard Worker } 100*2d1272b8SAndroid Build Coastguard Worker } 101*2d1272b8SAndroid Build Coastguard Worker 102*2d1272b8SAndroid Build Coastguard Worker // Encode number for TopDict / Private encode_num_tpCFF::str_encoder_t103*2d1272b8SAndroid Build Coastguard Worker void encode_num_tp (const number_t& n) 104*2d1272b8SAndroid Build Coastguard Worker { 105*2d1272b8SAndroid Build Coastguard Worker if (n.in_int_range ()) 106*2d1272b8SAndroid Build Coastguard Worker { 107*2d1272b8SAndroid Build Coastguard Worker // TODO longint 108*2d1272b8SAndroid Build Coastguard Worker encode_int (n.to_int ()); 109*2d1272b8SAndroid Build Coastguard Worker } 110*2d1272b8SAndroid Build Coastguard Worker else 111*2d1272b8SAndroid Build Coastguard Worker { 112*2d1272b8SAndroid Build Coastguard Worker // Sigh. BCD 113*2d1272b8SAndroid Build Coastguard Worker // https://learn.microsoft.com/en-us/typography/opentype/spec/cff2#table-5-nibble-definitions 114*2d1272b8SAndroid Build Coastguard Worker double v = n.to_real (); 115*2d1272b8SAndroid Build Coastguard Worker encode_byte (OpCode_BCD); 116*2d1272b8SAndroid Build Coastguard Worker 117*2d1272b8SAndroid Build Coastguard Worker // Based on: 118*2d1272b8SAndroid Build Coastguard Worker // https://github.com/fonttools/fonttools/blob/0738c41dfbcbc213ab9263f486ef0cccc6eb5ce5/Lib/fontTools/misc/psCharStrings.py#L267-L316 119*2d1272b8SAndroid Build Coastguard Worker 120*2d1272b8SAndroid Build Coastguard Worker char buf[16]; 121*2d1272b8SAndroid Build Coastguard Worker /* FontTools has the following comment: 122*2d1272b8SAndroid Build Coastguard Worker * 123*2d1272b8SAndroid Build Coastguard Worker * # Note: 14 decimal digits seems to be the limitation for CFF real numbers 124*2d1272b8SAndroid Build Coastguard Worker * # in macOS. However, we use 8 here to match the implementation of AFDKO. 125*2d1272b8SAndroid Build Coastguard Worker * 126*2d1272b8SAndroid Build Coastguard Worker * We use 8 here to match FontTools X-). 127*2d1272b8SAndroid Build Coastguard Worker */ 128*2d1272b8SAndroid Build Coastguard Worker 129*2d1272b8SAndroid Build Coastguard Worker hb_locale_t clocale HB_UNUSED; 130*2d1272b8SAndroid Build Coastguard Worker hb_locale_t oldlocale HB_UNUSED; 131*2d1272b8SAndroid Build Coastguard Worker oldlocale = hb_uselocale (clocale = newlocale (LC_ALL_MASK, "C", NULL)); 132*2d1272b8SAndroid Build Coastguard Worker snprintf (buf, sizeof (buf), "%.8G", v); 133*2d1272b8SAndroid Build Coastguard Worker (void) hb_uselocale (((void) freelocale (clocale), oldlocale)); 134*2d1272b8SAndroid Build Coastguard Worker 135*2d1272b8SAndroid Build Coastguard Worker char *s = buf; 136*2d1272b8SAndroid Build Coastguard Worker size_t len; 137*2d1272b8SAndroid Build Coastguard Worker char *comma = strchr (s, ','); 138*2d1272b8SAndroid Build Coastguard Worker if (comma) // Comma for some European locales in case no uselocale available. 139*2d1272b8SAndroid Build Coastguard Worker *comma = '.'; 140*2d1272b8SAndroid Build Coastguard Worker if (s[0] == '0' && s[1] == '.') 141*2d1272b8SAndroid Build Coastguard Worker s++; 142*2d1272b8SAndroid Build Coastguard Worker else if (s[0] == '-' && s[1] == '0' && s[2] == '.') 143*2d1272b8SAndroid Build Coastguard Worker { 144*2d1272b8SAndroid Build Coastguard Worker s[1] = '-'; 145*2d1272b8SAndroid Build Coastguard Worker s++; 146*2d1272b8SAndroid Build Coastguard Worker } 147*2d1272b8SAndroid Build Coastguard Worker else if ((len = strlen (s)) > 3 && !strcmp (s + len - 3, "000")) 148*2d1272b8SAndroid Build Coastguard Worker { 149*2d1272b8SAndroid Build Coastguard Worker unsigned exponent = len - 3; 150*2d1272b8SAndroid Build Coastguard Worker char *s2 = s + exponent - 1; 151*2d1272b8SAndroid Build Coastguard Worker while (*s2 == '0' && exponent > 1) 152*2d1272b8SAndroid Build Coastguard Worker { 153*2d1272b8SAndroid Build Coastguard Worker s2--; 154*2d1272b8SAndroid Build Coastguard Worker exponent++; 155*2d1272b8SAndroid Build Coastguard Worker } 156*2d1272b8SAndroid Build Coastguard Worker snprintf (s2 + 1, sizeof (buf) - (s2 + 1 - buf), "E%u", exponent); 157*2d1272b8SAndroid Build Coastguard Worker } 158*2d1272b8SAndroid Build Coastguard Worker else 159*2d1272b8SAndroid Build Coastguard Worker { 160*2d1272b8SAndroid Build Coastguard Worker char *dot = strchr (s, '.'); 161*2d1272b8SAndroid Build Coastguard Worker char *e = strchr (s, 'E'); 162*2d1272b8SAndroid Build Coastguard Worker if (dot && e) 163*2d1272b8SAndroid Build Coastguard Worker { 164*2d1272b8SAndroid Build Coastguard Worker memmove (dot, dot + 1, e - (dot + 1)); 165*2d1272b8SAndroid Build Coastguard Worker int exponent = atoi (e + 1); 166*2d1272b8SAndroid Build Coastguard Worker int new_exponent = exponent - (e - (dot + 1)); 167*2d1272b8SAndroid Build Coastguard Worker if (new_exponent == 1) 168*2d1272b8SAndroid Build Coastguard Worker { 169*2d1272b8SAndroid Build Coastguard Worker e[-1] = '0'; 170*2d1272b8SAndroid Build Coastguard Worker e[0] = '\0'; 171*2d1272b8SAndroid Build Coastguard Worker } 172*2d1272b8SAndroid Build Coastguard Worker else 173*2d1272b8SAndroid Build Coastguard Worker snprintf (e - 1, sizeof (buf) - (e - 1 - buf), "E%d", new_exponent); 174*2d1272b8SAndroid Build Coastguard Worker } 175*2d1272b8SAndroid Build Coastguard Worker } 176*2d1272b8SAndroid Build Coastguard Worker if ((s[0] == '.' && s[1] == '0') || (s[0] == '-' && s[1] == '.' && s[2] == '0')) 177*2d1272b8SAndroid Build Coastguard Worker { 178*2d1272b8SAndroid Build Coastguard Worker int sign = s[0] == '-'; 179*2d1272b8SAndroid Build Coastguard Worker char *s2 = s + sign + 1; 180*2d1272b8SAndroid Build Coastguard Worker while (*s2 == '0') 181*2d1272b8SAndroid Build Coastguard Worker s2++; 182*2d1272b8SAndroid Build Coastguard Worker len = strlen (s2); 183*2d1272b8SAndroid Build Coastguard Worker memmove (s + sign, s2, len); 184*2d1272b8SAndroid Build Coastguard Worker snprintf (s + sign + len, sizeof (buf) - (s + sign + len - buf), "E-%u", (unsigned) (strlen (s + sign) - 1)); 185*2d1272b8SAndroid Build Coastguard Worker } 186*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<char> nibbles; 187*2d1272b8SAndroid Build Coastguard Worker while (*s) 188*2d1272b8SAndroid Build Coastguard Worker { 189*2d1272b8SAndroid Build Coastguard Worker char c = s[0]; 190*2d1272b8SAndroid Build Coastguard Worker s++; 191*2d1272b8SAndroid Build Coastguard Worker 192*2d1272b8SAndroid Build Coastguard Worker switch (c) 193*2d1272b8SAndroid Build Coastguard Worker { 194*2d1272b8SAndroid Build Coastguard Worker case 'E': 195*2d1272b8SAndroid Build Coastguard Worker { 196*2d1272b8SAndroid Build Coastguard Worker char c2 = *s; 197*2d1272b8SAndroid Build Coastguard Worker if (c2 == '-') 198*2d1272b8SAndroid Build Coastguard Worker { 199*2d1272b8SAndroid Build Coastguard Worker s++; 200*2d1272b8SAndroid Build Coastguard Worker nibbles.push (0x0C); // E- 201*2d1272b8SAndroid Build Coastguard Worker } else { 202*2d1272b8SAndroid Build Coastguard Worker if (c2 == '+') 203*2d1272b8SAndroid Build Coastguard Worker s++; 204*2d1272b8SAndroid Build Coastguard Worker nibbles.push (0x0B); // E 205*2d1272b8SAndroid Build Coastguard Worker } 206*2d1272b8SAndroid Build Coastguard Worker if (*s == '0') 207*2d1272b8SAndroid Build Coastguard Worker s++; 208*2d1272b8SAndroid Build Coastguard Worker continue; 209*2d1272b8SAndroid Build Coastguard Worker } 210*2d1272b8SAndroid Build Coastguard Worker 211*2d1272b8SAndroid Build Coastguard Worker case '.': 212*2d1272b8SAndroid Build Coastguard Worker nibbles.push (0x0A); // . 213*2d1272b8SAndroid Build Coastguard Worker continue; 214*2d1272b8SAndroid Build Coastguard Worker 215*2d1272b8SAndroid Build Coastguard Worker case '-': 216*2d1272b8SAndroid Build Coastguard Worker nibbles.push (0x0E); // - 217*2d1272b8SAndroid Build Coastguard Worker continue; 218*2d1272b8SAndroid Build Coastguard Worker } 219*2d1272b8SAndroid Build Coastguard Worker 220*2d1272b8SAndroid Build Coastguard Worker nibbles.push (c - '0'); 221*2d1272b8SAndroid Build Coastguard Worker } 222*2d1272b8SAndroid Build Coastguard Worker nibbles.push (0x0F); 223*2d1272b8SAndroid Build Coastguard Worker if (nibbles.length % 2) 224*2d1272b8SAndroid Build Coastguard Worker nibbles.push (0x0F); 225*2d1272b8SAndroid Build Coastguard Worker 226*2d1272b8SAndroid Build Coastguard Worker unsigned count = nibbles.length; 227*2d1272b8SAndroid Build Coastguard Worker for (unsigned i = 0; i < count; i += 2) 228*2d1272b8SAndroid Build Coastguard Worker encode_byte ((nibbles[i] << 4) | nibbles[i+1]); 229*2d1272b8SAndroid Build Coastguard Worker } 230*2d1272b8SAndroid Build Coastguard Worker } 231*2d1272b8SAndroid Build Coastguard Worker encode_opCFF::str_encoder_t232*2d1272b8SAndroid Build Coastguard Worker void encode_op (op_code_t op) 233*2d1272b8SAndroid Build Coastguard Worker { 234*2d1272b8SAndroid Build Coastguard Worker if (Is_OpCode_ESC (op)) 235*2d1272b8SAndroid Build Coastguard Worker { 236*2d1272b8SAndroid Build Coastguard Worker encode_byte (OpCode_escape); 237*2d1272b8SAndroid Build Coastguard Worker encode_byte (Unmake_OpCode_ESC (op)); 238*2d1272b8SAndroid Build Coastguard Worker } 239*2d1272b8SAndroid Build Coastguard Worker else 240*2d1272b8SAndroid Build Coastguard Worker encode_byte (op); 241*2d1272b8SAndroid Build Coastguard Worker } 242*2d1272b8SAndroid Build Coastguard Worker copy_strCFF::str_encoder_t243*2d1272b8SAndroid Build Coastguard Worker void copy_str (const unsigned char *str, unsigned length) 244*2d1272b8SAndroid Build Coastguard Worker { 245*2d1272b8SAndroid Build Coastguard Worker assert ((signed) (buff.length + length) <= buff.allocated); 246*2d1272b8SAndroid Build Coastguard Worker hb_memcpy (buff.arrayZ + buff.length, str, length); 247*2d1272b8SAndroid Build Coastguard Worker buff.length += length; 248*2d1272b8SAndroid Build Coastguard Worker } 249*2d1272b8SAndroid Build Coastguard Worker in_errorCFF::str_encoder_t250*2d1272b8SAndroid Build Coastguard Worker bool in_error () const { return buff.in_error (); } 251*2d1272b8SAndroid Build Coastguard Worker 252*2d1272b8SAndroid Build Coastguard Worker protected: 253*2d1272b8SAndroid Build Coastguard Worker 254*2d1272b8SAndroid Build Coastguard Worker str_buff_t &buff; 255*2d1272b8SAndroid Build Coastguard Worker }; 256*2d1272b8SAndroid Build Coastguard Worker 257*2d1272b8SAndroid Build Coastguard Worker struct cff_sub_table_info_t { cff_sub_table_info_tCFF::cff_sub_table_info_t258*2d1272b8SAndroid Build Coastguard Worker cff_sub_table_info_t () 259*2d1272b8SAndroid Build Coastguard Worker : fd_array_link (0), 260*2d1272b8SAndroid Build Coastguard Worker char_strings_link (0) 261*2d1272b8SAndroid Build Coastguard Worker { 262*2d1272b8SAndroid Build Coastguard Worker fd_select.init (); 263*2d1272b8SAndroid Build Coastguard Worker } 264*2d1272b8SAndroid Build Coastguard Worker 265*2d1272b8SAndroid Build Coastguard Worker table_info_t fd_select; 266*2d1272b8SAndroid Build Coastguard Worker objidx_t fd_array_link; 267*2d1272b8SAndroid Build Coastguard Worker objidx_t char_strings_link; 268*2d1272b8SAndroid Build Coastguard Worker }; 269*2d1272b8SAndroid Build Coastguard Worker 270*2d1272b8SAndroid Build Coastguard Worker template <typename OPSTR=op_str_t> 271*2d1272b8SAndroid Build Coastguard Worker struct cff_top_dict_op_serializer_t : op_serializer_t 272*2d1272b8SAndroid Build Coastguard Worker { serializeCFF::cff_top_dict_op_serializer_t273*2d1272b8SAndroid Build Coastguard Worker bool serialize (hb_serialize_context_t *c, 274*2d1272b8SAndroid Build Coastguard Worker const OPSTR &opstr, 275*2d1272b8SAndroid Build Coastguard Worker const cff_sub_table_info_t &info) const 276*2d1272b8SAndroid Build Coastguard Worker { 277*2d1272b8SAndroid Build Coastguard Worker TRACE_SERIALIZE (this); 278*2d1272b8SAndroid Build Coastguard Worker 279*2d1272b8SAndroid Build Coastguard Worker switch (opstr.op) 280*2d1272b8SAndroid Build Coastguard Worker { 281*2d1272b8SAndroid Build Coastguard Worker case OpCode_CharStrings: 282*2d1272b8SAndroid Build Coastguard Worker return_trace (FontDict::serialize_link4_op(c, opstr.op, info.char_strings_link, whence_t::Absolute)); 283*2d1272b8SAndroid Build Coastguard Worker 284*2d1272b8SAndroid Build Coastguard Worker case OpCode_FDArray: 285*2d1272b8SAndroid Build Coastguard Worker return_trace (FontDict::serialize_link4_op(c, opstr.op, info.fd_array_link, whence_t::Absolute)); 286*2d1272b8SAndroid Build Coastguard Worker 287*2d1272b8SAndroid Build Coastguard Worker case OpCode_FDSelect: 288*2d1272b8SAndroid Build Coastguard Worker return_trace (FontDict::serialize_link4_op(c, opstr.op, info.fd_select.link, whence_t::Absolute)); 289*2d1272b8SAndroid Build Coastguard Worker 290*2d1272b8SAndroid Build Coastguard Worker default: 291*2d1272b8SAndroid Build Coastguard Worker return_trace (copy_opstr (c, opstr)); 292*2d1272b8SAndroid Build Coastguard Worker } 293*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 294*2d1272b8SAndroid Build Coastguard Worker } 295*2d1272b8SAndroid Build Coastguard Worker }; 296*2d1272b8SAndroid Build Coastguard Worker 297*2d1272b8SAndroid Build Coastguard Worker struct cff_font_dict_op_serializer_t : op_serializer_t 298*2d1272b8SAndroid Build Coastguard Worker { serializeCFF::cff_font_dict_op_serializer_t299*2d1272b8SAndroid Build Coastguard Worker bool serialize (hb_serialize_context_t *c, 300*2d1272b8SAndroid Build Coastguard Worker const op_str_t &opstr, 301*2d1272b8SAndroid Build Coastguard Worker const table_info_t &privateDictInfo) const 302*2d1272b8SAndroid Build Coastguard Worker { 303*2d1272b8SAndroid Build Coastguard Worker TRACE_SERIALIZE (this); 304*2d1272b8SAndroid Build Coastguard Worker 305*2d1272b8SAndroid Build Coastguard Worker if (opstr.op == OpCode_Private) 306*2d1272b8SAndroid Build Coastguard Worker { 307*2d1272b8SAndroid Build Coastguard Worker /* serialize the private dict size & offset as 2-byte & 4-byte integers */ 308*2d1272b8SAndroid Build Coastguard Worker return_trace (UnsizedByteStr::serialize_int2 (c, privateDictInfo.size) && 309*2d1272b8SAndroid Build Coastguard Worker Dict::serialize_link4_op (c, opstr.op, privateDictInfo.link, whence_t::Absolute)); 310*2d1272b8SAndroid Build Coastguard Worker } 311*2d1272b8SAndroid Build Coastguard Worker else 312*2d1272b8SAndroid Build Coastguard Worker { 313*2d1272b8SAndroid Build Coastguard Worker unsigned char *d = c->allocate_size<unsigned char> (opstr.length); 314*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!d)) return_trace (false); 315*2d1272b8SAndroid Build Coastguard Worker /* Faster than hb_memcpy for small strings. */ 316*2d1272b8SAndroid Build Coastguard Worker for (unsigned i = 0; i < opstr.length; i++) 317*2d1272b8SAndroid Build Coastguard Worker d[i] = opstr.ptr[i]; 318*2d1272b8SAndroid Build Coastguard Worker //hb_memcpy (d, opstr.ptr, opstr.length); 319*2d1272b8SAndroid Build Coastguard Worker } 320*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 321*2d1272b8SAndroid Build Coastguard Worker } 322*2d1272b8SAndroid Build Coastguard Worker }; 323*2d1272b8SAndroid Build Coastguard Worker 324*2d1272b8SAndroid Build Coastguard Worker struct flatten_param_t 325*2d1272b8SAndroid Build Coastguard Worker { 326*2d1272b8SAndroid Build Coastguard Worker str_buff_t &flatStr; 327*2d1272b8SAndroid Build Coastguard Worker bool drop_hints; 328*2d1272b8SAndroid Build Coastguard Worker const hb_subset_plan_t *plan; 329*2d1272b8SAndroid Build Coastguard Worker }; 330*2d1272b8SAndroid Build Coastguard Worker 331*2d1272b8SAndroid Build Coastguard Worker template <typename ACC, typename ENV, typename OPSET, op_code_t endchar_op=OpCode_Invalid> 332*2d1272b8SAndroid Build Coastguard Worker struct subr_flattener_t 333*2d1272b8SAndroid Build Coastguard Worker { subr_flattener_tCFF::subr_flattener_t334*2d1272b8SAndroid Build Coastguard Worker subr_flattener_t (const ACC &acc_, 335*2d1272b8SAndroid Build Coastguard Worker const hb_subset_plan_t *plan_) 336*2d1272b8SAndroid Build Coastguard Worker : acc (acc_), plan (plan_) {} 337*2d1272b8SAndroid Build Coastguard Worker flattenCFF::subr_flattener_t338*2d1272b8SAndroid Build Coastguard Worker bool flatten (str_buff_vec_t &flat_charstrings) 339*2d1272b8SAndroid Build Coastguard Worker { 340*2d1272b8SAndroid Build Coastguard Worker unsigned count = plan->num_output_glyphs (); 341*2d1272b8SAndroid Build Coastguard Worker if (!flat_charstrings.resize_exact (count)) 342*2d1272b8SAndroid Build Coastguard Worker return false; 343*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < count; i++) 344*2d1272b8SAndroid Build Coastguard Worker { 345*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph; 346*2d1272b8SAndroid Build Coastguard Worker if (!plan->old_gid_for_new_gid (i, &glyph)) 347*2d1272b8SAndroid Build Coastguard Worker { 348*2d1272b8SAndroid Build Coastguard Worker /* add an endchar only charstring for a missing glyph if CFF1 */ 349*2d1272b8SAndroid Build Coastguard Worker if (endchar_op != OpCode_Invalid) flat_charstrings[i].push (endchar_op); 350*2d1272b8SAndroid Build Coastguard Worker continue; 351*2d1272b8SAndroid Build Coastguard Worker } 352*2d1272b8SAndroid Build Coastguard Worker const hb_ubytes_t str = (*acc.charStrings)[glyph]; 353*2d1272b8SAndroid Build Coastguard Worker unsigned int fd = acc.fdSelect->get_fd (glyph); 354*2d1272b8SAndroid Build Coastguard Worker if (unlikely (fd >= acc.fdCount)) 355*2d1272b8SAndroid Build Coastguard Worker return false; 356*2d1272b8SAndroid Build Coastguard Worker 357*2d1272b8SAndroid Build Coastguard Worker 358*2d1272b8SAndroid Build Coastguard Worker ENV env (str, acc, fd, 359*2d1272b8SAndroid Build Coastguard Worker plan->normalized_coords.arrayZ, plan->normalized_coords.length); 360*2d1272b8SAndroid Build Coastguard Worker cs_interpreter_t<ENV, OPSET, flatten_param_t> interp (env); 361*2d1272b8SAndroid Build Coastguard Worker flatten_param_t param = { 362*2d1272b8SAndroid Build Coastguard Worker flat_charstrings.arrayZ[i], 363*2d1272b8SAndroid Build Coastguard Worker (bool) (plan->flags & HB_SUBSET_FLAGS_NO_HINTING), 364*2d1272b8SAndroid Build Coastguard Worker plan 365*2d1272b8SAndroid Build Coastguard Worker }; 366*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!interp.interpret (param))) 367*2d1272b8SAndroid Build Coastguard Worker return false; 368*2d1272b8SAndroid Build Coastguard Worker } 369*2d1272b8SAndroid Build Coastguard Worker return true; 370*2d1272b8SAndroid Build Coastguard Worker } 371*2d1272b8SAndroid Build Coastguard Worker 372*2d1272b8SAndroid Build Coastguard Worker const ACC &acc; 373*2d1272b8SAndroid Build Coastguard Worker const hb_subset_plan_t *plan; 374*2d1272b8SAndroid Build Coastguard Worker }; 375*2d1272b8SAndroid Build Coastguard Worker 376*2d1272b8SAndroid Build Coastguard Worker struct subr_closures_t 377*2d1272b8SAndroid Build Coastguard Worker { subr_closures_tCFF::subr_closures_t378*2d1272b8SAndroid Build Coastguard Worker subr_closures_t (unsigned int fd_count) : global_closure (), local_closures () 379*2d1272b8SAndroid Build Coastguard Worker { 380*2d1272b8SAndroid Build Coastguard Worker local_closures.resize_exact (fd_count); 381*2d1272b8SAndroid Build Coastguard Worker } 382*2d1272b8SAndroid Build Coastguard Worker resetCFF::subr_closures_t383*2d1272b8SAndroid Build Coastguard Worker void reset () 384*2d1272b8SAndroid Build Coastguard Worker { 385*2d1272b8SAndroid Build Coastguard Worker global_closure.clear(); 386*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < local_closures.length; i++) 387*2d1272b8SAndroid Build Coastguard Worker local_closures[i].clear(); 388*2d1272b8SAndroid Build Coastguard Worker } 389*2d1272b8SAndroid Build Coastguard Worker in_errorCFF::subr_closures_t390*2d1272b8SAndroid Build Coastguard Worker bool in_error () const { return local_closures.in_error (); } 391*2d1272b8SAndroid Build Coastguard Worker hb_set_t global_closure; 392*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<hb_set_t> local_closures; 393*2d1272b8SAndroid Build Coastguard Worker }; 394*2d1272b8SAndroid Build Coastguard Worker 395*2d1272b8SAndroid Build Coastguard Worker struct parsed_cs_op_t : op_str_t 396*2d1272b8SAndroid Build Coastguard Worker { parsed_cs_op_tCFF::parsed_cs_op_t397*2d1272b8SAndroid Build Coastguard Worker parsed_cs_op_t (unsigned int subr_num_ = 0) : 398*2d1272b8SAndroid Build Coastguard Worker subr_num (subr_num_) {} 399*2d1272b8SAndroid Build Coastguard Worker is_hintingCFF::parsed_cs_op_t400*2d1272b8SAndroid Build Coastguard Worker bool is_hinting () const { return hinting_flag; } set_hintingCFF::parsed_cs_op_t401*2d1272b8SAndroid Build Coastguard Worker void set_hinting () { hinting_flag = true; } 402*2d1272b8SAndroid Build Coastguard Worker 403*2d1272b8SAndroid Build Coastguard Worker /* The layout of this struct is designed to fit within the 404*2d1272b8SAndroid Build Coastguard Worker * padding of op_str_t! */ 405*2d1272b8SAndroid Build Coastguard Worker 406*2d1272b8SAndroid Build Coastguard Worker protected: 407*2d1272b8SAndroid Build Coastguard Worker bool hinting_flag = false; 408*2d1272b8SAndroid Build Coastguard Worker 409*2d1272b8SAndroid Build Coastguard Worker public: 410*2d1272b8SAndroid Build Coastguard Worker uint16_t subr_num; 411*2d1272b8SAndroid Build Coastguard Worker }; 412*2d1272b8SAndroid Build Coastguard Worker 413*2d1272b8SAndroid Build Coastguard Worker struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t> 414*2d1272b8SAndroid Build Coastguard Worker { parsed_cs_str_tCFF::parsed_cs_str_t415*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_t () : 416*2d1272b8SAndroid Build Coastguard Worker parsed (false), 417*2d1272b8SAndroid Build Coastguard Worker hint_dropped (false), 418*2d1272b8SAndroid Build Coastguard Worker has_prefix_ (false), 419*2d1272b8SAndroid Build Coastguard Worker has_calls_ (false) 420*2d1272b8SAndroid Build Coastguard Worker { 421*2d1272b8SAndroid Build Coastguard Worker SUPER::init (); 422*2d1272b8SAndroid Build Coastguard Worker } 423*2d1272b8SAndroid Build Coastguard Worker add_opCFF::parsed_cs_str_t424*2d1272b8SAndroid Build Coastguard Worker void add_op (op_code_t op, const byte_str_ref_t& str_ref) 425*2d1272b8SAndroid Build Coastguard Worker { 426*2d1272b8SAndroid Build Coastguard Worker if (!is_parsed ()) 427*2d1272b8SAndroid Build Coastguard Worker SUPER::add_op (op, str_ref); 428*2d1272b8SAndroid Build Coastguard Worker } 429*2d1272b8SAndroid Build Coastguard Worker add_call_opCFF::parsed_cs_str_t430*2d1272b8SAndroid Build Coastguard Worker void add_call_op (op_code_t op, const byte_str_ref_t& str_ref, unsigned int subr_num) 431*2d1272b8SAndroid Build Coastguard Worker { 432*2d1272b8SAndroid Build Coastguard Worker if (!is_parsed ()) 433*2d1272b8SAndroid Build Coastguard Worker { 434*2d1272b8SAndroid Build Coastguard Worker has_calls_ = true; 435*2d1272b8SAndroid Build Coastguard Worker 436*2d1272b8SAndroid Build Coastguard Worker /* Pop the subroutine number. */ 437*2d1272b8SAndroid Build Coastguard Worker values.pop (); 438*2d1272b8SAndroid Build Coastguard Worker 439*2d1272b8SAndroid Build Coastguard Worker SUPER::add_op (op, str_ref, {subr_num}); 440*2d1272b8SAndroid Build Coastguard Worker } 441*2d1272b8SAndroid Build Coastguard Worker } 442*2d1272b8SAndroid Build Coastguard Worker set_prefixCFF::parsed_cs_str_t443*2d1272b8SAndroid Build Coastguard Worker void set_prefix (const number_t &num, op_code_t op = OpCode_Invalid) 444*2d1272b8SAndroid Build Coastguard Worker { 445*2d1272b8SAndroid Build Coastguard Worker has_prefix_ = true; 446*2d1272b8SAndroid Build Coastguard Worker prefix_op_ = op; 447*2d1272b8SAndroid Build Coastguard Worker prefix_num_ = num; 448*2d1272b8SAndroid Build Coastguard Worker } 449*2d1272b8SAndroid Build Coastguard Worker at_endCFF::parsed_cs_str_t450*2d1272b8SAndroid Build Coastguard Worker bool at_end (unsigned int pos) const 451*2d1272b8SAndroid Build Coastguard Worker { 452*2d1272b8SAndroid Build Coastguard Worker return ((pos + 1 >= values.length) /* CFF2 */ 453*2d1272b8SAndroid Build Coastguard Worker || (values[pos + 1].op == OpCode_return)); 454*2d1272b8SAndroid Build Coastguard Worker } 455*2d1272b8SAndroid Build Coastguard Worker is_parsedCFF::parsed_cs_str_t456*2d1272b8SAndroid Build Coastguard Worker bool is_parsed () const { return parsed; } set_parsedCFF::parsed_cs_str_t457*2d1272b8SAndroid Build Coastguard Worker void set_parsed () { parsed = true; } 458*2d1272b8SAndroid Build Coastguard Worker is_hint_droppedCFF::parsed_cs_str_t459*2d1272b8SAndroid Build Coastguard Worker bool is_hint_dropped () const { return hint_dropped; } set_hint_droppedCFF::parsed_cs_str_t460*2d1272b8SAndroid Build Coastguard Worker void set_hint_dropped () { hint_dropped = true; } 461*2d1272b8SAndroid Build Coastguard Worker is_vsindex_droppedCFF::parsed_cs_str_t462*2d1272b8SAndroid Build Coastguard Worker bool is_vsindex_dropped () const { return vsindex_dropped; } set_vsindex_droppedCFF::parsed_cs_str_t463*2d1272b8SAndroid Build Coastguard Worker void set_vsindex_dropped () { vsindex_dropped = true; } 464*2d1272b8SAndroid Build Coastguard Worker has_prefixCFF::parsed_cs_str_t465*2d1272b8SAndroid Build Coastguard Worker bool has_prefix () const { return has_prefix_; } prefix_opCFF::parsed_cs_str_t466*2d1272b8SAndroid Build Coastguard Worker op_code_t prefix_op () const { return prefix_op_; } prefix_numCFF::parsed_cs_str_t467*2d1272b8SAndroid Build Coastguard Worker const number_t &prefix_num () const { return prefix_num_; } 468*2d1272b8SAndroid Build Coastguard Worker has_callsCFF::parsed_cs_str_t469*2d1272b8SAndroid Build Coastguard Worker bool has_calls () const { return has_calls_; } 470*2d1272b8SAndroid Build Coastguard Worker compactCFF::parsed_cs_str_t471*2d1272b8SAndroid Build Coastguard Worker void compact () 472*2d1272b8SAndroid Build Coastguard Worker { 473*2d1272b8SAndroid Build Coastguard Worker unsigned count = values.length; 474*2d1272b8SAndroid Build Coastguard Worker if (!count) return; 475*2d1272b8SAndroid Build Coastguard Worker auto &opstr = values.arrayZ; 476*2d1272b8SAndroid Build Coastguard Worker unsigned j = 0; 477*2d1272b8SAndroid Build Coastguard Worker for (unsigned i = 1; i < count; i++) 478*2d1272b8SAndroid Build Coastguard Worker { 479*2d1272b8SAndroid Build Coastguard Worker /* See if we can combine op j and op i. */ 480*2d1272b8SAndroid Build Coastguard Worker bool combine = 481*2d1272b8SAndroid Build Coastguard Worker (opstr[j].op != OpCode_callsubr && opstr[j].op != OpCode_callgsubr) && 482*2d1272b8SAndroid Build Coastguard Worker (opstr[i].op != OpCode_callsubr && opstr[i].op != OpCode_callgsubr) && 483*2d1272b8SAndroid Build Coastguard Worker (opstr[j].is_hinting () == opstr[i].is_hinting ()) && 484*2d1272b8SAndroid Build Coastguard Worker (opstr[j].ptr + opstr[j].length == opstr[i].ptr) && 485*2d1272b8SAndroid Build Coastguard Worker (opstr[j].length + opstr[i].length <= 255); 486*2d1272b8SAndroid Build Coastguard Worker 487*2d1272b8SAndroid Build Coastguard Worker if (combine) 488*2d1272b8SAndroid Build Coastguard Worker { 489*2d1272b8SAndroid Build Coastguard Worker opstr[j].length += opstr[i].length; 490*2d1272b8SAndroid Build Coastguard Worker opstr[j].op = OpCode_Invalid; 491*2d1272b8SAndroid Build Coastguard Worker } 492*2d1272b8SAndroid Build Coastguard Worker else 493*2d1272b8SAndroid Build Coastguard Worker { 494*2d1272b8SAndroid Build Coastguard Worker opstr[++j] = opstr[i]; 495*2d1272b8SAndroid Build Coastguard Worker } 496*2d1272b8SAndroid Build Coastguard Worker } 497*2d1272b8SAndroid Build Coastguard Worker values.shrink (j + 1); 498*2d1272b8SAndroid Build Coastguard Worker } 499*2d1272b8SAndroid Build Coastguard Worker 500*2d1272b8SAndroid Build Coastguard Worker protected: 501*2d1272b8SAndroid Build Coastguard Worker bool parsed : 1; 502*2d1272b8SAndroid Build Coastguard Worker bool hint_dropped : 1; 503*2d1272b8SAndroid Build Coastguard Worker bool vsindex_dropped : 1; 504*2d1272b8SAndroid Build Coastguard Worker bool has_prefix_ : 1; 505*2d1272b8SAndroid Build Coastguard Worker bool has_calls_ : 1; 506*2d1272b8SAndroid Build Coastguard Worker op_code_t prefix_op_; 507*2d1272b8SAndroid Build Coastguard Worker number_t prefix_num_; 508*2d1272b8SAndroid Build Coastguard Worker 509*2d1272b8SAndroid Build Coastguard Worker private: 510*2d1272b8SAndroid Build Coastguard Worker typedef parsed_values_t<parsed_cs_op_t> SUPER; 511*2d1272b8SAndroid Build Coastguard Worker }; 512*2d1272b8SAndroid Build Coastguard Worker 513*2d1272b8SAndroid Build Coastguard Worker struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t> 514*2d1272b8SAndroid Build Coastguard Worker { 515*2d1272b8SAndroid Build Coastguard Worker private: 516*2d1272b8SAndroid Build Coastguard Worker typedef hb_vector_t<parsed_cs_str_t> SUPER; 517*2d1272b8SAndroid Build Coastguard Worker }; 518*2d1272b8SAndroid Build Coastguard Worker 519*2d1272b8SAndroid Build Coastguard Worker struct cff_subset_accelerator_t 520*2d1272b8SAndroid Build Coastguard Worker { createCFF::cff_subset_accelerator_t521*2d1272b8SAndroid Build Coastguard Worker static cff_subset_accelerator_t* create ( 522*2d1272b8SAndroid Build Coastguard Worker hb_blob_t* original_blob, 523*2d1272b8SAndroid Build Coastguard Worker const parsed_cs_str_vec_t& parsed_charstrings, 524*2d1272b8SAndroid Build Coastguard Worker const parsed_cs_str_vec_t& parsed_global_subrs, 525*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs) { 526*2d1272b8SAndroid Build Coastguard Worker cff_subset_accelerator_t* accel = 527*2d1272b8SAndroid Build Coastguard Worker (cff_subset_accelerator_t*) hb_malloc (sizeof(cff_subset_accelerator_t)); 528*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!accel)) return nullptr; 529*2d1272b8SAndroid Build Coastguard Worker new (accel) cff_subset_accelerator_t (original_blob, 530*2d1272b8SAndroid Build Coastguard Worker parsed_charstrings, 531*2d1272b8SAndroid Build Coastguard Worker parsed_global_subrs, 532*2d1272b8SAndroid Build Coastguard Worker parsed_local_subrs); 533*2d1272b8SAndroid Build Coastguard Worker return accel; 534*2d1272b8SAndroid Build Coastguard Worker } 535*2d1272b8SAndroid Build Coastguard Worker destroyCFF::cff_subset_accelerator_t536*2d1272b8SAndroid Build Coastguard Worker static void destroy (void* value) { 537*2d1272b8SAndroid Build Coastguard Worker if (!value) return; 538*2d1272b8SAndroid Build Coastguard Worker 539*2d1272b8SAndroid Build Coastguard Worker cff_subset_accelerator_t* accel = (cff_subset_accelerator_t*) value; 540*2d1272b8SAndroid Build Coastguard Worker accel->~cff_subset_accelerator_t (); 541*2d1272b8SAndroid Build Coastguard Worker hb_free (accel); 542*2d1272b8SAndroid Build Coastguard Worker } 543*2d1272b8SAndroid Build Coastguard Worker cff_subset_accelerator_tCFF::cff_subset_accelerator_t544*2d1272b8SAndroid Build Coastguard Worker cff_subset_accelerator_t( 545*2d1272b8SAndroid Build Coastguard Worker hb_blob_t* original_blob_, 546*2d1272b8SAndroid Build Coastguard Worker const parsed_cs_str_vec_t& parsed_charstrings_, 547*2d1272b8SAndroid Build Coastguard Worker const parsed_cs_str_vec_t& parsed_global_subrs_, 548*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<parsed_cs_str_vec_t>& parsed_local_subrs_) 549*2d1272b8SAndroid Build Coastguard Worker { 550*2d1272b8SAndroid Build Coastguard Worker parsed_charstrings = parsed_charstrings_; 551*2d1272b8SAndroid Build Coastguard Worker parsed_global_subrs = parsed_global_subrs_; 552*2d1272b8SAndroid Build Coastguard Worker parsed_local_subrs = parsed_local_subrs_; 553*2d1272b8SAndroid Build Coastguard Worker 554*2d1272b8SAndroid Build Coastguard Worker // the parsed charstrings point to memory in the original CFF table so we must hold a reference 555*2d1272b8SAndroid Build Coastguard Worker // to it to keep the memory valid. 556*2d1272b8SAndroid Build Coastguard Worker original_blob = hb_blob_reference (original_blob_); 557*2d1272b8SAndroid Build Coastguard Worker } 558*2d1272b8SAndroid Build Coastguard Worker ~cff_subset_accelerator_tCFF::cff_subset_accelerator_t559*2d1272b8SAndroid Build Coastguard Worker ~cff_subset_accelerator_t() 560*2d1272b8SAndroid Build Coastguard Worker { 561*2d1272b8SAndroid Build Coastguard Worker hb_blob_destroy (original_blob); 562*2d1272b8SAndroid Build Coastguard Worker auto *mapping = glyph_to_sid_map.get_relaxed (); 563*2d1272b8SAndroid Build Coastguard Worker if (mapping) 564*2d1272b8SAndroid Build Coastguard Worker { 565*2d1272b8SAndroid Build Coastguard Worker mapping->~glyph_to_sid_map_t (); 566*2d1272b8SAndroid Build Coastguard Worker hb_free (mapping); 567*2d1272b8SAndroid Build Coastguard Worker } 568*2d1272b8SAndroid Build Coastguard Worker } 569*2d1272b8SAndroid Build Coastguard Worker 570*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_vec_t parsed_charstrings; 571*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_vec_t parsed_global_subrs; 572*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs; 573*2d1272b8SAndroid Build Coastguard Worker mutable hb_atomic_ptr_t<glyph_to_sid_map_t> glyph_to_sid_map; 574*2d1272b8SAndroid Build Coastguard Worker 575*2d1272b8SAndroid Build Coastguard Worker private: 576*2d1272b8SAndroid Build Coastguard Worker hb_blob_t* original_blob; 577*2d1272b8SAndroid Build Coastguard Worker }; 578*2d1272b8SAndroid Build Coastguard Worker 579*2d1272b8SAndroid Build Coastguard Worker struct subr_subset_param_t 580*2d1272b8SAndroid Build Coastguard Worker { subr_subset_param_tCFF::subr_subset_param_t581*2d1272b8SAndroid Build Coastguard Worker subr_subset_param_t (parsed_cs_str_t *parsed_charstring_, 582*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_vec_t *parsed_global_subrs_, 583*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_vec_t *parsed_local_subrs_, 584*2d1272b8SAndroid Build Coastguard Worker hb_set_t *global_closure_, 585*2d1272b8SAndroid Build Coastguard Worker hb_set_t *local_closure_, 586*2d1272b8SAndroid Build Coastguard Worker bool drop_hints_) : 587*2d1272b8SAndroid Build Coastguard Worker current_parsed_str (parsed_charstring_), 588*2d1272b8SAndroid Build Coastguard Worker parsed_charstring (parsed_charstring_), 589*2d1272b8SAndroid Build Coastguard Worker parsed_global_subrs (parsed_global_subrs_), 590*2d1272b8SAndroid Build Coastguard Worker parsed_local_subrs (parsed_local_subrs_), 591*2d1272b8SAndroid Build Coastguard Worker global_closure (global_closure_), 592*2d1272b8SAndroid Build Coastguard Worker local_closure (local_closure_), 593*2d1272b8SAndroid Build Coastguard Worker drop_hints (drop_hints_) {} 594*2d1272b8SAndroid Build Coastguard Worker get_parsed_str_for_contextCFF::subr_subset_param_t595*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_t *get_parsed_str_for_context (call_context_t &context) 596*2d1272b8SAndroid Build Coastguard Worker { 597*2d1272b8SAndroid Build Coastguard Worker switch (context.type) 598*2d1272b8SAndroid Build Coastguard Worker { 599*2d1272b8SAndroid Build Coastguard Worker case CSType_CharString: 600*2d1272b8SAndroid Build Coastguard Worker return parsed_charstring; 601*2d1272b8SAndroid Build Coastguard Worker 602*2d1272b8SAndroid Build Coastguard Worker case CSType_LocalSubr: 603*2d1272b8SAndroid Build Coastguard Worker if (likely (context.subr_num < parsed_local_subrs->length)) 604*2d1272b8SAndroid Build Coastguard Worker return &(*parsed_local_subrs)[context.subr_num]; 605*2d1272b8SAndroid Build Coastguard Worker break; 606*2d1272b8SAndroid Build Coastguard Worker 607*2d1272b8SAndroid Build Coastguard Worker case CSType_GlobalSubr: 608*2d1272b8SAndroid Build Coastguard Worker if (likely (context.subr_num < parsed_global_subrs->length)) 609*2d1272b8SAndroid Build Coastguard Worker return &(*parsed_global_subrs)[context.subr_num]; 610*2d1272b8SAndroid Build Coastguard Worker break; 611*2d1272b8SAndroid Build Coastguard Worker } 612*2d1272b8SAndroid Build Coastguard Worker return nullptr; 613*2d1272b8SAndroid Build Coastguard Worker } 614*2d1272b8SAndroid Build Coastguard Worker 615*2d1272b8SAndroid Build Coastguard Worker template <typename ENV> set_current_strCFF::subr_subset_param_t616*2d1272b8SAndroid Build Coastguard Worker void set_current_str (ENV &env, bool calling) 617*2d1272b8SAndroid Build Coastguard Worker { 618*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_t *parsed_str = get_parsed_str_for_context (env.context); 619*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!parsed_str)) 620*2d1272b8SAndroid Build Coastguard Worker { 621*2d1272b8SAndroid Build Coastguard Worker env.set_error (); 622*2d1272b8SAndroid Build Coastguard Worker return; 623*2d1272b8SAndroid Build Coastguard Worker } 624*2d1272b8SAndroid Build Coastguard Worker /* If the called subroutine is parsed partially but not completely yet, 625*2d1272b8SAndroid Build Coastguard Worker * it must be because we are calling it recursively. 626*2d1272b8SAndroid Build Coastguard Worker * Handle it as an error. */ 627*2d1272b8SAndroid Build Coastguard Worker if (unlikely (calling && !parsed_str->is_parsed () && (parsed_str->values.length > 0))) 628*2d1272b8SAndroid Build Coastguard Worker env.set_error (); 629*2d1272b8SAndroid Build Coastguard Worker else 630*2d1272b8SAndroid Build Coastguard Worker { 631*2d1272b8SAndroid Build Coastguard Worker if (!parsed_str->is_parsed ()) 632*2d1272b8SAndroid Build Coastguard Worker parsed_str->alloc (env.str_ref.total_size ()); 633*2d1272b8SAndroid Build Coastguard Worker current_parsed_str = parsed_str; 634*2d1272b8SAndroid Build Coastguard Worker } 635*2d1272b8SAndroid Build Coastguard Worker } 636*2d1272b8SAndroid Build Coastguard Worker 637*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_t *current_parsed_str; 638*2d1272b8SAndroid Build Coastguard Worker 639*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_t *parsed_charstring; 640*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_vec_t *parsed_global_subrs; 641*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_vec_t *parsed_local_subrs; 642*2d1272b8SAndroid Build Coastguard Worker hb_set_t *global_closure; 643*2d1272b8SAndroid Build Coastguard Worker hb_set_t *local_closure; 644*2d1272b8SAndroid Build Coastguard Worker bool drop_hints; 645*2d1272b8SAndroid Build Coastguard Worker }; 646*2d1272b8SAndroid Build Coastguard Worker 647*2d1272b8SAndroid Build Coastguard Worker struct subr_remap_t : hb_inc_bimap_t 648*2d1272b8SAndroid Build Coastguard Worker { createCFF::subr_remap_t649*2d1272b8SAndroid Build Coastguard Worker void create (const hb_set_t *closure) 650*2d1272b8SAndroid Build Coastguard Worker { 651*2d1272b8SAndroid Build Coastguard Worker /* create a remapping of subroutine numbers from old to new. 652*2d1272b8SAndroid Build Coastguard Worker * no optimization based on usage counts. fonttools doesn't appear doing that either. 653*2d1272b8SAndroid Build Coastguard Worker */ 654*2d1272b8SAndroid Build Coastguard Worker 655*2d1272b8SAndroid Build Coastguard Worker alloc (closure->get_population ()); 656*2d1272b8SAndroid Build Coastguard Worker for (auto old_num : *closure) 657*2d1272b8SAndroid Build Coastguard Worker add (old_num); 658*2d1272b8SAndroid Build Coastguard Worker 659*2d1272b8SAndroid Build Coastguard Worker if (get_population () < 1240) 660*2d1272b8SAndroid Build Coastguard Worker bias = 107; 661*2d1272b8SAndroid Build Coastguard Worker else if (get_population () < 33900) 662*2d1272b8SAndroid Build Coastguard Worker bias = 1131; 663*2d1272b8SAndroid Build Coastguard Worker else 664*2d1272b8SAndroid Build Coastguard Worker bias = 32768; 665*2d1272b8SAndroid Build Coastguard Worker } 666*2d1272b8SAndroid Build Coastguard Worker biased_numCFF::subr_remap_t667*2d1272b8SAndroid Build Coastguard Worker int biased_num (unsigned int old_num) const 668*2d1272b8SAndroid Build Coastguard Worker { 669*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t new_num = get (old_num); 670*2d1272b8SAndroid Build Coastguard Worker return (int)new_num - bias; 671*2d1272b8SAndroid Build Coastguard Worker } 672*2d1272b8SAndroid Build Coastguard Worker 673*2d1272b8SAndroid Build Coastguard Worker protected: 674*2d1272b8SAndroid Build Coastguard Worker int bias; 675*2d1272b8SAndroid Build Coastguard Worker }; 676*2d1272b8SAndroid Build Coastguard Worker 677*2d1272b8SAndroid Build Coastguard Worker struct subr_remaps_t 678*2d1272b8SAndroid Build Coastguard Worker { subr_remaps_tCFF::subr_remaps_t679*2d1272b8SAndroid Build Coastguard Worker subr_remaps_t (unsigned int fdCount) 680*2d1272b8SAndroid Build Coastguard Worker { 681*2d1272b8SAndroid Build Coastguard Worker local_remaps.resize (fdCount); 682*2d1272b8SAndroid Build Coastguard Worker } 683*2d1272b8SAndroid Build Coastguard Worker in_errorCFF::subr_remaps_t684*2d1272b8SAndroid Build Coastguard Worker bool in_error() 685*2d1272b8SAndroid Build Coastguard Worker { 686*2d1272b8SAndroid Build Coastguard Worker return local_remaps.in_error (); 687*2d1272b8SAndroid Build Coastguard Worker } 688*2d1272b8SAndroid Build Coastguard Worker createCFF::subr_remaps_t689*2d1272b8SAndroid Build Coastguard Worker void create (subr_closures_t& closures) 690*2d1272b8SAndroid Build Coastguard Worker { 691*2d1272b8SAndroid Build Coastguard Worker global_remap.create (&closures.global_closure); 692*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < local_remaps.length; i++) 693*2d1272b8SAndroid Build Coastguard Worker local_remaps.arrayZ[i].create (&closures.local_closures[i]); 694*2d1272b8SAndroid Build Coastguard Worker } 695*2d1272b8SAndroid Build Coastguard Worker 696*2d1272b8SAndroid Build Coastguard Worker subr_remap_t global_remap; 697*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<subr_remap_t> local_remaps; 698*2d1272b8SAndroid Build Coastguard Worker }; 699*2d1272b8SAndroid Build Coastguard Worker 700*2d1272b8SAndroid Build Coastguard Worker template <typename SUBSETTER, typename SUBRS, typename ACC, typename ENV, typename OPSET, op_code_t endchar_op=OpCode_Invalid> 701*2d1272b8SAndroid Build Coastguard Worker struct subr_subsetter_t 702*2d1272b8SAndroid Build Coastguard Worker { subr_subsetter_tCFF::subr_subsetter_t703*2d1272b8SAndroid Build Coastguard Worker subr_subsetter_t (ACC &acc_, const hb_subset_plan_t *plan_) 704*2d1272b8SAndroid Build Coastguard Worker : acc (acc_), plan (plan_), closures(acc_.fdCount), 705*2d1272b8SAndroid Build Coastguard Worker remaps(acc_.fdCount) 706*2d1272b8SAndroid Build Coastguard Worker {} 707*2d1272b8SAndroid Build Coastguard Worker 708*2d1272b8SAndroid Build Coastguard Worker /* Subroutine subsetting with --no-desubroutinize runs in phases: 709*2d1272b8SAndroid Build Coastguard Worker * 710*2d1272b8SAndroid Build Coastguard Worker * 1. execute charstrings/subroutines to determine subroutine closures 711*2d1272b8SAndroid Build Coastguard Worker * 2. parse out all operators and numbers 712*2d1272b8SAndroid Build Coastguard Worker * 3. mark hint operators and operands for removal if --no-hinting 713*2d1272b8SAndroid Build Coastguard Worker * 4. re-encode all charstrings and subroutines with new subroutine numbers 714*2d1272b8SAndroid Build Coastguard Worker * 715*2d1272b8SAndroid Build Coastguard Worker * Phases #1 and #2 are done at the same time in collect_subrs (). 716*2d1272b8SAndroid Build Coastguard Worker * Phase #3 walks charstrings/subroutines forward then backward (hence parsing required), 717*2d1272b8SAndroid Build Coastguard Worker * because we can't tell if a number belongs to a hint op until we see the first moveto. 718*2d1272b8SAndroid Build Coastguard Worker * 719*2d1272b8SAndroid Build Coastguard Worker * Assumption: a callsubr/callgsubr operator must immediately follow a (biased) subroutine number 720*2d1272b8SAndroid Build Coastguard Worker * within the same charstring/subroutine, e.g., not split across a charstring and a subroutine. 721*2d1272b8SAndroid Build Coastguard Worker */ subsetCFF::subr_subsetter_t722*2d1272b8SAndroid Build Coastguard Worker bool subset (void) 723*2d1272b8SAndroid Build Coastguard Worker { 724*2d1272b8SAndroid Build Coastguard Worker unsigned fd_count = acc.fdCount; 725*2d1272b8SAndroid Build Coastguard Worker const cff_subset_accelerator_t* cff_accelerator = nullptr; 726*2d1272b8SAndroid Build Coastguard Worker if (acc.cff_accelerator) { 727*2d1272b8SAndroid Build Coastguard Worker cff_accelerator = acc.cff_accelerator; 728*2d1272b8SAndroid Build Coastguard Worker fd_count = cff_accelerator->parsed_local_subrs.length; 729*2d1272b8SAndroid Build Coastguard Worker } 730*2d1272b8SAndroid Build Coastguard Worker 731*2d1272b8SAndroid Build Coastguard Worker if (cff_accelerator) { 732*2d1272b8SAndroid Build Coastguard Worker // If we are not dropping hinting then charstrings are not modified so we can 733*2d1272b8SAndroid Build Coastguard Worker // just use a reference to the cached copies. 734*2d1272b8SAndroid Build Coastguard Worker cached_charstrings.resize_exact (plan->num_output_glyphs ()); 735*2d1272b8SAndroid Build Coastguard Worker parsed_global_subrs = &cff_accelerator->parsed_global_subrs; 736*2d1272b8SAndroid Build Coastguard Worker parsed_local_subrs = &cff_accelerator->parsed_local_subrs; 737*2d1272b8SAndroid Build Coastguard Worker } else { 738*2d1272b8SAndroid Build Coastguard Worker parsed_charstrings.resize_exact (plan->num_output_glyphs ()); 739*2d1272b8SAndroid Build Coastguard Worker parsed_global_subrs_storage.resize_exact (acc.globalSubrs->count); 740*2d1272b8SAndroid Build Coastguard Worker 741*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!parsed_local_subrs_storage.resize (fd_count))) return false; 742*2d1272b8SAndroid Build Coastguard Worker 743*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < acc.fdCount; i++) 744*2d1272b8SAndroid Build Coastguard Worker { 745*2d1272b8SAndroid Build Coastguard Worker unsigned count = acc.privateDicts[i].localSubrs->count; 746*2d1272b8SAndroid Build Coastguard Worker parsed_local_subrs_storage[i].resize (count); 747*2d1272b8SAndroid Build Coastguard Worker if (unlikely (parsed_local_subrs_storage[i].in_error ())) return false; 748*2d1272b8SAndroid Build Coastguard Worker } 749*2d1272b8SAndroid Build Coastguard Worker 750*2d1272b8SAndroid Build Coastguard Worker parsed_global_subrs = &parsed_global_subrs_storage; 751*2d1272b8SAndroid Build Coastguard Worker parsed_local_subrs = &parsed_local_subrs_storage; 752*2d1272b8SAndroid Build Coastguard Worker } 753*2d1272b8SAndroid Build Coastguard Worker 754*2d1272b8SAndroid Build Coastguard Worker if (unlikely (remaps.in_error() 755*2d1272b8SAndroid Build Coastguard Worker || cached_charstrings.in_error () 756*2d1272b8SAndroid Build Coastguard Worker || parsed_charstrings.in_error () 757*2d1272b8SAndroid Build Coastguard Worker || parsed_global_subrs->in_error () 758*2d1272b8SAndroid Build Coastguard Worker || closures.in_error ())) { 759*2d1272b8SAndroid Build Coastguard Worker return false; 760*2d1272b8SAndroid Build Coastguard Worker } 761*2d1272b8SAndroid Build Coastguard Worker 762*2d1272b8SAndroid Build Coastguard Worker /* phase 1 & 2 */ 763*2d1272b8SAndroid Build Coastguard Worker for (auto _ : plan->new_to_old_gid_list) 764*2d1272b8SAndroid Build Coastguard Worker { 765*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t new_glyph = _.first; 766*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t old_glyph = _.second; 767*2d1272b8SAndroid Build Coastguard Worker 768*2d1272b8SAndroid Build Coastguard Worker const hb_ubytes_t str = (*acc.charStrings)[old_glyph]; 769*2d1272b8SAndroid Build Coastguard Worker unsigned int fd = acc.fdSelect->get_fd (old_glyph); 770*2d1272b8SAndroid Build Coastguard Worker if (unlikely (fd >= acc.fdCount)) 771*2d1272b8SAndroid Build Coastguard Worker return false; 772*2d1272b8SAndroid Build Coastguard Worker 773*2d1272b8SAndroid Build Coastguard Worker if (cff_accelerator) 774*2d1272b8SAndroid Build Coastguard Worker { 775*2d1272b8SAndroid Build Coastguard Worker // parsed string already exists in accelerator, copy it and move 776*2d1272b8SAndroid Build Coastguard Worker // on. 777*2d1272b8SAndroid Build Coastguard Worker if (cached_charstrings) 778*2d1272b8SAndroid Build Coastguard Worker cached_charstrings[new_glyph] = &cff_accelerator->parsed_charstrings[old_glyph]; 779*2d1272b8SAndroid Build Coastguard Worker else 780*2d1272b8SAndroid Build Coastguard Worker parsed_charstrings[new_glyph] = cff_accelerator->parsed_charstrings[old_glyph]; 781*2d1272b8SAndroid Build Coastguard Worker 782*2d1272b8SAndroid Build Coastguard Worker continue; 783*2d1272b8SAndroid Build Coastguard Worker } 784*2d1272b8SAndroid Build Coastguard Worker 785*2d1272b8SAndroid Build Coastguard Worker ENV env (str, acc, fd); 786*2d1272b8SAndroid Build Coastguard Worker cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp (env); 787*2d1272b8SAndroid Build Coastguard Worker 788*2d1272b8SAndroid Build Coastguard Worker parsed_charstrings[new_glyph].alloc (str.length); 789*2d1272b8SAndroid Build Coastguard Worker subr_subset_param_t param (&parsed_charstrings[new_glyph], 790*2d1272b8SAndroid Build Coastguard Worker &parsed_global_subrs_storage, 791*2d1272b8SAndroid Build Coastguard Worker &parsed_local_subrs_storage[fd], 792*2d1272b8SAndroid Build Coastguard Worker &closures.global_closure, 793*2d1272b8SAndroid Build Coastguard Worker &closures.local_closures[fd], 794*2d1272b8SAndroid Build Coastguard Worker plan->flags & HB_SUBSET_FLAGS_NO_HINTING); 795*2d1272b8SAndroid Build Coastguard Worker 796*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!interp.interpret (param))) 797*2d1272b8SAndroid Build Coastguard Worker return false; 798*2d1272b8SAndroid Build Coastguard Worker 799*2d1272b8SAndroid Build Coastguard Worker /* complete parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */ 800*2d1272b8SAndroid Build Coastguard Worker SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[new_glyph]); 801*2d1272b8SAndroid Build Coastguard Worker 802*2d1272b8SAndroid Build Coastguard Worker /* mark hint ops and arguments for drop */ 803*2d1272b8SAndroid Build Coastguard Worker if ((plan->flags & HB_SUBSET_FLAGS_NO_HINTING) || plan->inprogress_accelerator) 804*2d1272b8SAndroid Build Coastguard Worker { 805*2d1272b8SAndroid Build Coastguard Worker subr_subset_param_t param (&parsed_charstrings[new_glyph], 806*2d1272b8SAndroid Build Coastguard Worker &parsed_global_subrs_storage, 807*2d1272b8SAndroid Build Coastguard Worker &parsed_local_subrs_storage[fd], 808*2d1272b8SAndroid Build Coastguard Worker &closures.global_closure, 809*2d1272b8SAndroid Build Coastguard Worker &closures.local_closures[fd], 810*2d1272b8SAndroid Build Coastguard Worker plan->flags & HB_SUBSET_FLAGS_NO_HINTING); 811*2d1272b8SAndroid Build Coastguard Worker 812*2d1272b8SAndroid Build Coastguard Worker drop_hints_param_t drop; 813*2d1272b8SAndroid Build Coastguard Worker if (drop_hints_in_str (parsed_charstrings[new_glyph], param, drop)) 814*2d1272b8SAndroid Build Coastguard Worker { 815*2d1272b8SAndroid Build Coastguard Worker parsed_charstrings[new_glyph].set_hint_dropped (); 816*2d1272b8SAndroid Build Coastguard Worker if (drop.vsindex_dropped) 817*2d1272b8SAndroid Build Coastguard Worker parsed_charstrings[new_glyph].set_vsindex_dropped (); 818*2d1272b8SAndroid Build Coastguard Worker } 819*2d1272b8SAndroid Build Coastguard Worker } 820*2d1272b8SAndroid Build Coastguard Worker 821*2d1272b8SAndroid Build Coastguard Worker /* Doing this here one by one instead of compacting all at the end 822*2d1272b8SAndroid Build Coastguard Worker * has massive peak-memory saving. 823*2d1272b8SAndroid Build Coastguard Worker * 824*2d1272b8SAndroid Build Coastguard Worker * The compacting both saves memory and makes further operations 825*2d1272b8SAndroid Build Coastguard Worker * faster. 826*2d1272b8SAndroid Build Coastguard Worker */ 827*2d1272b8SAndroid Build Coastguard Worker parsed_charstrings[new_glyph].compact (); 828*2d1272b8SAndroid Build Coastguard Worker } 829*2d1272b8SAndroid Build Coastguard Worker 830*2d1272b8SAndroid Build Coastguard Worker /* Since parsed strings were loaded from accelerator, we still need 831*2d1272b8SAndroid Build Coastguard Worker * to compute the subroutine closures which would have normally happened during 832*2d1272b8SAndroid Build Coastguard Worker * parsing. 833*2d1272b8SAndroid Build Coastguard Worker * 834*2d1272b8SAndroid Build Coastguard Worker * Or if we are dropping hinting, redo closure to get actually used subrs. 835*2d1272b8SAndroid Build Coastguard Worker */ 836*2d1272b8SAndroid Build Coastguard Worker if ((cff_accelerator || 837*2d1272b8SAndroid Build Coastguard Worker (!cff_accelerator && plan->flags & HB_SUBSET_FLAGS_NO_HINTING)) && 838*2d1272b8SAndroid Build Coastguard Worker !closure_subroutines(*parsed_global_subrs, 839*2d1272b8SAndroid Build Coastguard Worker *parsed_local_subrs)) 840*2d1272b8SAndroid Build Coastguard Worker return false; 841*2d1272b8SAndroid Build Coastguard Worker 842*2d1272b8SAndroid Build Coastguard Worker remaps.create (closures); 843*2d1272b8SAndroid Build Coastguard Worker 844*2d1272b8SAndroid Build Coastguard Worker populate_subset_accelerator (); 845*2d1272b8SAndroid Build Coastguard Worker return true; 846*2d1272b8SAndroid Build Coastguard Worker } 847*2d1272b8SAndroid Build Coastguard Worker encode_charstringsCFF::subr_subsetter_t848*2d1272b8SAndroid Build Coastguard Worker bool encode_charstrings (str_buff_vec_t &buffArray, bool encode_prefix = true) const 849*2d1272b8SAndroid Build Coastguard Worker { 850*2d1272b8SAndroid Build Coastguard Worker unsigned num_glyphs = plan->num_output_glyphs (); 851*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!buffArray.resize_exact (num_glyphs))) 852*2d1272b8SAndroid Build Coastguard Worker return false; 853*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t last = 0; 854*2d1272b8SAndroid Build Coastguard Worker for (auto _ : plan->new_to_old_gid_list) 855*2d1272b8SAndroid Build Coastguard Worker { 856*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t gid = _.first; 857*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t old_glyph = _.second; 858*2d1272b8SAndroid Build Coastguard Worker 859*2d1272b8SAndroid Build Coastguard Worker if (endchar_op != OpCode_Invalid) 860*2d1272b8SAndroid Build Coastguard Worker for (; last < gid; last++) 861*2d1272b8SAndroid Build Coastguard Worker { 862*2d1272b8SAndroid Build Coastguard Worker // Hack to point vector to static string. 863*2d1272b8SAndroid Build Coastguard Worker auto &b = buffArray.arrayZ[last]; 864*2d1272b8SAndroid Build Coastguard Worker b.length = 1; 865*2d1272b8SAndroid Build Coastguard Worker b.arrayZ = const_cast<unsigned char *>(endchar_str); 866*2d1272b8SAndroid Build Coastguard Worker } 867*2d1272b8SAndroid Build Coastguard Worker 868*2d1272b8SAndroid Build Coastguard Worker last++; // Skip over gid 869*2d1272b8SAndroid Build Coastguard Worker unsigned int fd = acc.fdSelect->get_fd (old_glyph); 870*2d1272b8SAndroid Build Coastguard Worker if (unlikely (fd >= acc.fdCount)) 871*2d1272b8SAndroid Build Coastguard Worker return false; 872*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!encode_str (get_parsed_charstring (gid), fd, buffArray.arrayZ[gid], encode_prefix))) 873*2d1272b8SAndroid Build Coastguard Worker return false; 874*2d1272b8SAndroid Build Coastguard Worker } 875*2d1272b8SAndroid Build Coastguard Worker if (endchar_op != OpCode_Invalid) 876*2d1272b8SAndroid Build Coastguard Worker for (; last < num_glyphs; last++) 877*2d1272b8SAndroid Build Coastguard Worker { 878*2d1272b8SAndroid Build Coastguard Worker // Hack to point vector to static string. 879*2d1272b8SAndroid Build Coastguard Worker auto &b = buffArray.arrayZ[last]; 880*2d1272b8SAndroid Build Coastguard Worker b.length = 1; 881*2d1272b8SAndroid Build Coastguard Worker b.arrayZ = const_cast<unsigned char *>(endchar_str); 882*2d1272b8SAndroid Build Coastguard Worker } 883*2d1272b8SAndroid Build Coastguard Worker 884*2d1272b8SAndroid Build Coastguard Worker return true; 885*2d1272b8SAndroid Build Coastguard Worker } 886*2d1272b8SAndroid Build Coastguard Worker encode_subrsCFF::subr_subsetter_t887*2d1272b8SAndroid Build Coastguard Worker bool encode_subrs (const parsed_cs_str_vec_t &subrs, const subr_remap_t& remap, unsigned int fd, str_buff_vec_t &buffArray) const 888*2d1272b8SAndroid Build Coastguard Worker { 889*2d1272b8SAndroid Build Coastguard Worker unsigned int count = remap.get_population (); 890*2d1272b8SAndroid Build Coastguard Worker 891*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!buffArray.resize_exact (count))) 892*2d1272b8SAndroid Build Coastguard Worker return false; 893*2d1272b8SAndroid Build Coastguard Worker for (unsigned int new_num = 0; new_num < count; new_num++) 894*2d1272b8SAndroid Build Coastguard Worker { 895*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t old_num = remap.backward (new_num); 896*2d1272b8SAndroid Build Coastguard Worker assert (old_num != CFF_UNDEF_CODE); 897*2d1272b8SAndroid Build Coastguard Worker 898*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num]))) 899*2d1272b8SAndroid Build Coastguard Worker return false; 900*2d1272b8SAndroid Build Coastguard Worker } 901*2d1272b8SAndroid Build Coastguard Worker return true; 902*2d1272b8SAndroid Build Coastguard Worker } 903*2d1272b8SAndroid Build Coastguard Worker encode_globalsubrsCFF::subr_subsetter_t904*2d1272b8SAndroid Build Coastguard Worker bool encode_globalsubrs (str_buff_vec_t &buffArray) 905*2d1272b8SAndroid Build Coastguard Worker { 906*2d1272b8SAndroid Build Coastguard Worker return encode_subrs (*parsed_global_subrs, remaps.global_remap, 0, buffArray); 907*2d1272b8SAndroid Build Coastguard Worker } 908*2d1272b8SAndroid Build Coastguard Worker encode_localsubrsCFF::subr_subsetter_t909*2d1272b8SAndroid Build Coastguard Worker bool encode_localsubrs (unsigned int fd, str_buff_vec_t &buffArray) const 910*2d1272b8SAndroid Build Coastguard Worker { 911*2d1272b8SAndroid Build Coastguard Worker return encode_subrs ((*parsed_local_subrs)[fd], remaps.local_remaps[fd], fd, buffArray); 912*2d1272b8SAndroid Build Coastguard Worker } 913*2d1272b8SAndroid Build Coastguard Worker 914*2d1272b8SAndroid Build Coastguard Worker protected: 915*2d1272b8SAndroid Build Coastguard Worker struct drop_hints_param_t 916*2d1272b8SAndroid Build Coastguard Worker { drop_hints_param_tCFF::subr_subsetter_t::drop_hints_param_t917*2d1272b8SAndroid Build Coastguard Worker drop_hints_param_t () 918*2d1272b8SAndroid Build Coastguard Worker : seen_moveto (false), 919*2d1272b8SAndroid Build Coastguard Worker ends_in_hint (false), 920*2d1272b8SAndroid Build Coastguard Worker all_dropped (false), 921*2d1272b8SAndroid Build Coastguard Worker vsindex_dropped (false) {} 922*2d1272b8SAndroid Build Coastguard Worker 923*2d1272b8SAndroid Build Coastguard Worker bool seen_moveto; 924*2d1272b8SAndroid Build Coastguard Worker bool ends_in_hint; 925*2d1272b8SAndroid Build Coastguard Worker bool all_dropped; 926*2d1272b8SAndroid Build Coastguard Worker bool vsindex_dropped; 927*2d1272b8SAndroid Build Coastguard Worker }; 928*2d1272b8SAndroid Build Coastguard Worker drop_hints_in_subrCFF::subr_subsetter_t929*2d1272b8SAndroid Build Coastguard Worker bool drop_hints_in_subr (parsed_cs_str_t &str, unsigned int pos, 930*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_vec_t &subrs, unsigned int subr_num, 931*2d1272b8SAndroid Build Coastguard Worker const subr_subset_param_t ¶m, drop_hints_param_t &drop) 932*2d1272b8SAndroid Build Coastguard Worker { 933*2d1272b8SAndroid Build Coastguard Worker drop.ends_in_hint = false; 934*2d1272b8SAndroid Build Coastguard Worker bool has_hint = drop_hints_in_str (subrs[subr_num], param, drop); 935*2d1272b8SAndroid Build Coastguard Worker 936*2d1272b8SAndroid Build Coastguard Worker /* if this subr ends with a stem hint (i.e., not a number; potential argument for moveto), 937*2d1272b8SAndroid Build Coastguard Worker * then this entire subroutine must be a hint. drop its call. */ 938*2d1272b8SAndroid Build Coastguard Worker if (drop.ends_in_hint) 939*2d1272b8SAndroid Build Coastguard Worker { 940*2d1272b8SAndroid Build Coastguard Worker str.values[pos].set_hinting (); 941*2d1272b8SAndroid Build Coastguard Worker /* if this subr call is at the end of the parent subr, propagate the flag 942*2d1272b8SAndroid Build Coastguard Worker * otherwise reset the flag */ 943*2d1272b8SAndroid Build Coastguard Worker if (!str.at_end (pos)) 944*2d1272b8SAndroid Build Coastguard Worker drop.ends_in_hint = false; 945*2d1272b8SAndroid Build Coastguard Worker } 946*2d1272b8SAndroid Build Coastguard Worker else if (drop.all_dropped) 947*2d1272b8SAndroid Build Coastguard Worker { 948*2d1272b8SAndroid Build Coastguard Worker str.values[pos].set_hinting (); 949*2d1272b8SAndroid Build Coastguard Worker } 950*2d1272b8SAndroid Build Coastguard Worker 951*2d1272b8SAndroid Build Coastguard Worker return has_hint; 952*2d1272b8SAndroid Build Coastguard Worker } 953*2d1272b8SAndroid Build Coastguard Worker 954*2d1272b8SAndroid Build Coastguard Worker /* returns true if it sees a hint op before the first moveto */ drop_hints_in_strCFF::subr_subsetter_t955*2d1272b8SAndroid Build Coastguard Worker bool drop_hints_in_str (parsed_cs_str_t &str, const subr_subset_param_t ¶m, drop_hints_param_t &drop) 956*2d1272b8SAndroid Build Coastguard Worker { 957*2d1272b8SAndroid Build Coastguard Worker bool seen_hint = false; 958*2d1272b8SAndroid Build Coastguard Worker 959*2d1272b8SAndroid Build Coastguard Worker unsigned count = str.values.length; 960*2d1272b8SAndroid Build Coastguard Worker auto *values = str.values.arrayZ; 961*2d1272b8SAndroid Build Coastguard Worker for (unsigned int pos = 0; pos < count; pos++) 962*2d1272b8SAndroid Build Coastguard Worker { 963*2d1272b8SAndroid Build Coastguard Worker bool has_hint = false; 964*2d1272b8SAndroid Build Coastguard Worker switch (values[pos].op) 965*2d1272b8SAndroid Build Coastguard Worker { 966*2d1272b8SAndroid Build Coastguard Worker case OpCode_callsubr: 967*2d1272b8SAndroid Build Coastguard Worker has_hint = drop_hints_in_subr (str, pos, 968*2d1272b8SAndroid Build Coastguard Worker *param.parsed_local_subrs, values[pos].subr_num, 969*2d1272b8SAndroid Build Coastguard Worker param, drop); 970*2d1272b8SAndroid Build Coastguard Worker break; 971*2d1272b8SAndroid Build Coastguard Worker 972*2d1272b8SAndroid Build Coastguard Worker case OpCode_callgsubr: 973*2d1272b8SAndroid Build Coastguard Worker has_hint = drop_hints_in_subr (str, pos, 974*2d1272b8SAndroid Build Coastguard Worker *param.parsed_global_subrs, values[pos].subr_num, 975*2d1272b8SAndroid Build Coastguard Worker param, drop); 976*2d1272b8SAndroid Build Coastguard Worker break; 977*2d1272b8SAndroid Build Coastguard Worker 978*2d1272b8SAndroid Build Coastguard Worker case OpCode_rmoveto: 979*2d1272b8SAndroid Build Coastguard Worker case OpCode_hmoveto: 980*2d1272b8SAndroid Build Coastguard Worker case OpCode_vmoveto: 981*2d1272b8SAndroid Build Coastguard Worker drop.seen_moveto = true; 982*2d1272b8SAndroid Build Coastguard Worker break; 983*2d1272b8SAndroid Build Coastguard Worker 984*2d1272b8SAndroid Build Coastguard Worker case OpCode_hintmask: 985*2d1272b8SAndroid Build Coastguard Worker case OpCode_cntrmask: 986*2d1272b8SAndroid Build Coastguard Worker if (drop.seen_moveto) 987*2d1272b8SAndroid Build Coastguard Worker { 988*2d1272b8SAndroid Build Coastguard Worker values[pos].set_hinting (); 989*2d1272b8SAndroid Build Coastguard Worker break; 990*2d1272b8SAndroid Build Coastguard Worker } 991*2d1272b8SAndroid Build Coastguard Worker HB_FALLTHROUGH; 992*2d1272b8SAndroid Build Coastguard Worker 993*2d1272b8SAndroid Build Coastguard Worker case OpCode_hstemhm: 994*2d1272b8SAndroid Build Coastguard Worker case OpCode_vstemhm: 995*2d1272b8SAndroid Build Coastguard Worker case OpCode_hstem: 996*2d1272b8SAndroid Build Coastguard Worker case OpCode_vstem: 997*2d1272b8SAndroid Build Coastguard Worker has_hint = true; 998*2d1272b8SAndroid Build Coastguard Worker values[pos].set_hinting (); 999*2d1272b8SAndroid Build Coastguard Worker if (str.at_end (pos)) 1000*2d1272b8SAndroid Build Coastguard Worker drop.ends_in_hint = true; 1001*2d1272b8SAndroid Build Coastguard Worker break; 1002*2d1272b8SAndroid Build Coastguard Worker 1003*2d1272b8SAndroid Build Coastguard Worker case OpCode_dotsection: 1004*2d1272b8SAndroid Build Coastguard Worker values[pos].set_hinting (); 1005*2d1272b8SAndroid Build Coastguard Worker break; 1006*2d1272b8SAndroid Build Coastguard Worker 1007*2d1272b8SAndroid Build Coastguard Worker default: 1008*2d1272b8SAndroid Build Coastguard Worker /* NONE */ 1009*2d1272b8SAndroid Build Coastguard Worker break; 1010*2d1272b8SAndroid Build Coastguard Worker } 1011*2d1272b8SAndroid Build Coastguard Worker if (has_hint) 1012*2d1272b8SAndroid Build Coastguard Worker { 1013*2d1272b8SAndroid Build Coastguard Worker for (int i = pos - 1; i >= 0; i--) 1014*2d1272b8SAndroid Build Coastguard Worker { 1015*2d1272b8SAndroid Build Coastguard Worker parsed_cs_op_t &csop = values[(unsigned)i]; 1016*2d1272b8SAndroid Build Coastguard Worker if (csop.is_hinting ()) 1017*2d1272b8SAndroid Build Coastguard Worker break; 1018*2d1272b8SAndroid Build Coastguard Worker csop.set_hinting (); 1019*2d1272b8SAndroid Build Coastguard Worker if (csop.op == OpCode_vsindexcs) 1020*2d1272b8SAndroid Build Coastguard Worker drop.vsindex_dropped = true; 1021*2d1272b8SAndroid Build Coastguard Worker } 1022*2d1272b8SAndroid Build Coastguard Worker seen_hint |= has_hint; 1023*2d1272b8SAndroid Build Coastguard Worker } 1024*2d1272b8SAndroid Build Coastguard Worker } 1025*2d1272b8SAndroid Build Coastguard Worker 1026*2d1272b8SAndroid Build Coastguard Worker /* Raise all_dropped flag if all operators except return are dropped from a subr. 1027*2d1272b8SAndroid Build Coastguard Worker * It may happen even after seeing the first moveto if a subr contains 1028*2d1272b8SAndroid Build Coastguard Worker * only (usually one) hintmask operator, then calls to this subr can be dropped. 1029*2d1272b8SAndroid Build Coastguard Worker */ 1030*2d1272b8SAndroid Build Coastguard Worker drop.all_dropped = true; 1031*2d1272b8SAndroid Build Coastguard Worker for (unsigned int pos = 0; pos < count; pos++) 1032*2d1272b8SAndroid Build Coastguard Worker { 1033*2d1272b8SAndroid Build Coastguard Worker parsed_cs_op_t &csop = values[pos]; 1034*2d1272b8SAndroid Build Coastguard Worker if (csop.op == OpCode_return) 1035*2d1272b8SAndroid Build Coastguard Worker break; 1036*2d1272b8SAndroid Build Coastguard Worker if (!csop.is_hinting ()) 1037*2d1272b8SAndroid Build Coastguard Worker { 1038*2d1272b8SAndroid Build Coastguard Worker drop.all_dropped = false; 1039*2d1272b8SAndroid Build Coastguard Worker break; 1040*2d1272b8SAndroid Build Coastguard Worker } 1041*2d1272b8SAndroid Build Coastguard Worker } 1042*2d1272b8SAndroid Build Coastguard Worker 1043*2d1272b8SAndroid Build Coastguard Worker return seen_hint; 1044*2d1272b8SAndroid Build Coastguard Worker } 1045*2d1272b8SAndroid Build Coastguard Worker closure_subroutinesCFF::subr_subsetter_t1046*2d1272b8SAndroid Build Coastguard Worker bool closure_subroutines (const parsed_cs_str_vec_t& global_subrs, 1047*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<parsed_cs_str_vec_t>& local_subrs) 1048*2d1272b8SAndroid Build Coastguard Worker { 1049*2d1272b8SAndroid Build Coastguard Worker closures.reset (); 1050*2d1272b8SAndroid Build Coastguard Worker for (auto _ : plan->new_to_old_gid_list) 1051*2d1272b8SAndroid Build Coastguard Worker { 1052*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t new_glyph = _.first; 1053*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t old_glyph = _.second; 1054*2d1272b8SAndroid Build Coastguard Worker unsigned int fd = acc.fdSelect->get_fd (old_glyph); 1055*2d1272b8SAndroid Build Coastguard Worker if (unlikely (fd >= acc.fdCount)) 1056*2d1272b8SAndroid Build Coastguard Worker return false; 1057*2d1272b8SAndroid Build Coastguard Worker 1058*2d1272b8SAndroid Build Coastguard Worker // Note: const cast is safe here because the collect_subr_refs_in_str only performs a 1059*2d1272b8SAndroid Build Coastguard Worker // closure and does not modify any of the charstrings. 1060*2d1272b8SAndroid Build Coastguard Worker subr_subset_param_t param (const_cast<parsed_cs_str_t*> (&get_parsed_charstring (new_glyph)), 1061*2d1272b8SAndroid Build Coastguard Worker const_cast<parsed_cs_str_vec_t*> (&global_subrs), 1062*2d1272b8SAndroid Build Coastguard Worker const_cast<parsed_cs_str_vec_t*> (&local_subrs[fd]), 1063*2d1272b8SAndroid Build Coastguard Worker &closures.global_closure, 1064*2d1272b8SAndroid Build Coastguard Worker &closures.local_closures[fd], 1065*2d1272b8SAndroid Build Coastguard Worker plan->flags & HB_SUBSET_FLAGS_NO_HINTING); 1066*2d1272b8SAndroid Build Coastguard Worker collect_subr_refs_in_str (get_parsed_charstring (new_glyph), param); 1067*2d1272b8SAndroid Build Coastguard Worker } 1068*2d1272b8SAndroid Build Coastguard Worker 1069*2d1272b8SAndroid Build Coastguard Worker return true; 1070*2d1272b8SAndroid Build Coastguard Worker } 1071*2d1272b8SAndroid Build Coastguard Worker collect_subr_refs_in_subrCFF::subr_subsetter_t1072*2d1272b8SAndroid Build Coastguard Worker void collect_subr_refs_in_subr (unsigned int subr_num, parsed_cs_str_vec_t &subrs, 1073*2d1272b8SAndroid Build Coastguard Worker hb_set_t *closure, 1074*2d1272b8SAndroid Build Coastguard Worker const subr_subset_param_t ¶m) 1075*2d1272b8SAndroid Build Coastguard Worker { 1076*2d1272b8SAndroid Build Coastguard Worker if (closure->has (subr_num)) 1077*2d1272b8SAndroid Build Coastguard Worker return; 1078*2d1272b8SAndroid Build Coastguard Worker closure->add (subr_num); 1079*2d1272b8SAndroid Build Coastguard Worker collect_subr_refs_in_str (subrs[subr_num], param); 1080*2d1272b8SAndroid Build Coastguard Worker } 1081*2d1272b8SAndroid Build Coastguard Worker collect_subr_refs_in_strCFF::subr_subsetter_t1082*2d1272b8SAndroid Build Coastguard Worker void collect_subr_refs_in_str (const parsed_cs_str_t &str, 1083*2d1272b8SAndroid Build Coastguard Worker const subr_subset_param_t ¶m) 1084*2d1272b8SAndroid Build Coastguard Worker { 1085*2d1272b8SAndroid Build Coastguard Worker if (!str.has_calls ()) 1086*2d1272b8SAndroid Build Coastguard Worker return; 1087*2d1272b8SAndroid Build Coastguard Worker 1088*2d1272b8SAndroid Build Coastguard Worker for (auto &opstr : str.values) 1089*2d1272b8SAndroid Build Coastguard Worker { 1090*2d1272b8SAndroid Build Coastguard Worker if (!param.drop_hints || !opstr.is_hinting ()) 1091*2d1272b8SAndroid Build Coastguard Worker { 1092*2d1272b8SAndroid Build Coastguard Worker switch (opstr.op) 1093*2d1272b8SAndroid Build Coastguard Worker { 1094*2d1272b8SAndroid Build Coastguard Worker case OpCode_callsubr: 1095*2d1272b8SAndroid Build Coastguard Worker collect_subr_refs_in_subr (opstr.subr_num, *param.parsed_local_subrs, 1096*2d1272b8SAndroid Build Coastguard Worker param.local_closure, param); 1097*2d1272b8SAndroid Build Coastguard Worker break; 1098*2d1272b8SAndroid Build Coastguard Worker 1099*2d1272b8SAndroid Build Coastguard Worker case OpCode_callgsubr: 1100*2d1272b8SAndroid Build Coastguard Worker collect_subr_refs_in_subr (opstr.subr_num, *param.parsed_global_subrs, 1101*2d1272b8SAndroid Build Coastguard Worker param.global_closure, param); 1102*2d1272b8SAndroid Build Coastguard Worker break; 1103*2d1272b8SAndroid Build Coastguard Worker 1104*2d1272b8SAndroid Build Coastguard Worker default: break; 1105*2d1272b8SAndroid Build Coastguard Worker } 1106*2d1272b8SAndroid Build Coastguard Worker } 1107*2d1272b8SAndroid Build Coastguard Worker } 1108*2d1272b8SAndroid Build Coastguard Worker } 1109*2d1272b8SAndroid Build Coastguard Worker encode_strCFF::subr_subsetter_t1110*2d1272b8SAndroid Build Coastguard Worker bool encode_str (const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff, bool encode_prefix = true) const 1111*2d1272b8SAndroid Build Coastguard Worker { 1112*2d1272b8SAndroid Build Coastguard Worker str_encoder_t encoder (buff); 1113*2d1272b8SAndroid Build Coastguard Worker encoder.reset (); 1114*2d1272b8SAndroid Build Coastguard Worker bool hinting = !(plan->flags & HB_SUBSET_FLAGS_NO_HINTING); 1115*2d1272b8SAndroid Build Coastguard Worker /* if a prefix (CFF1 width or CFF2 vsindex) has been removed along with hints, 1116*2d1272b8SAndroid Build Coastguard Worker * re-insert it at the beginning of charstreing */ 1117*2d1272b8SAndroid Build Coastguard Worker if (encode_prefix && str.has_prefix () && !hinting && str.is_hint_dropped ()) 1118*2d1272b8SAndroid Build Coastguard Worker { 1119*2d1272b8SAndroid Build Coastguard Worker encoder.encode_num_cs (str.prefix_num ()); 1120*2d1272b8SAndroid Build Coastguard Worker if (str.prefix_op () != OpCode_Invalid) 1121*2d1272b8SAndroid Build Coastguard Worker encoder.encode_op (str.prefix_op ()); 1122*2d1272b8SAndroid Build Coastguard Worker } 1123*2d1272b8SAndroid Build Coastguard Worker 1124*2d1272b8SAndroid Build Coastguard Worker unsigned size = 0; 1125*2d1272b8SAndroid Build Coastguard Worker for (auto &opstr : str.values) 1126*2d1272b8SAndroid Build Coastguard Worker { 1127*2d1272b8SAndroid Build Coastguard Worker size += opstr.length; 1128*2d1272b8SAndroid Build Coastguard Worker if (opstr.op == OpCode_callsubr || opstr.op == OpCode_callgsubr) 1129*2d1272b8SAndroid Build Coastguard Worker size += 3; 1130*2d1272b8SAndroid Build Coastguard Worker } 1131*2d1272b8SAndroid Build Coastguard Worker if (!buff.alloc (buff.length + size, true)) 1132*2d1272b8SAndroid Build Coastguard Worker return false; 1133*2d1272b8SAndroid Build Coastguard Worker 1134*2d1272b8SAndroid Build Coastguard Worker for (auto &opstr : str.values) 1135*2d1272b8SAndroid Build Coastguard Worker { 1136*2d1272b8SAndroid Build Coastguard Worker if (hinting || !opstr.is_hinting ()) 1137*2d1272b8SAndroid Build Coastguard Worker { 1138*2d1272b8SAndroid Build Coastguard Worker switch (opstr.op) 1139*2d1272b8SAndroid Build Coastguard Worker { 1140*2d1272b8SAndroid Build Coastguard Worker case OpCode_callsubr: 1141*2d1272b8SAndroid Build Coastguard Worker encoder.encode_int (remaps.local_remaps[fd].biased_num (opstr.subr_num)); 1142*2d1272b8SAndroid Build Coastguard Worker encoder.copy_str (opstr.ptr, opstr.length); 1143*2d1272b8SAndroid Build Coastguard Worker break; 1144*2d1272b8SAndroid Build Coastguard Worker 1145*2d1272b8SAndroid Build Coastguard Worker case OpCode_callgsubr: 1146*2d1272b8SAndroid Build Coastguard Worker encoder.encode_int (remaps.global_remap.biased_num (opstr.subr_num)); 1147*2d1272b8SAndroid Build Coastguard Worker encoder.copy_str (opstr.ptr, opstr.length); 1148*2d1272b8SAndroid Build Coastguard Worker break; 1149*2d1272b8SAndroid Build Coastguard Worker 1150*2d1272b8SAndroid Build Coastguard Worker default: 1151*2d1272b8SAndroid Build Coastguard Worker encoder.copy_str (opstr.ptr, opstr.length); 1152*2d1272b8SAndroid Build Coastguard Worker break; 1153*2d1272b8SAndroid Build Coastguard Worker } 1154*2d1272b8SAndroid Build Coastguard Worker } 1155*2d1272b8SAndroid Build Coastguard Worker } 1156*2d1272b8SAndroid Build Coastguard Worker return !encoder.in_error (); 1157*2d1272b8SAndroid Build Coastguard Worker } 1158*2d1272b8SAndroid Build Coastguard Worker compact_parsed_subrsCFF::subr_subsetter_t1159*2d1272b8SAndroid Build Coastguard Worker void compact_parsed_subrs () const 1160*2d1272b8SAndroid Build Coastguard Worker { 1161*2d1272b8SAndroid Build Coastguard Worker for (auto &cs : parsed_global_subrs_storage) 1162*2d1272b8SAndroid Build Coastguard Worker cs.compact (); 1163*2d1272b8SAndroid Build Coastguard Worker for (auto &vec : parsed_local_subrs_storage) 1164*2d1272b8SAndroid Build Coastguard Worker for (auto &cs : vec) 1165*2d1272b8SAndroid Build Coastguard Worker cs.compact (); 1166*2d1272b8SAndroid Build Coastguard Worker } 1167*2d1272b8SAndroid Build Coastguard Worker populate_subset_acceleratorCFF::subr_subsetter_t1168*2d1272b8SAndroid Build Coastguard Worker void populate_subset_accelerator () const 1169*2d1272b8SAndroid Build Coastguard Worker { 1170*2d1272b8SAndroid Build Coastguard Worker if (!plan->inprogress_accelerator) return; 1171*2d1272b8SAndroid Build Coastguard Worker 1172*2d1272b8SAndroid Build Coastguard Worker compact_parsed_subrs (); 1173*2d1272b8SAndroid Build Coastguard Worker 1174*2d1272b8SAndroid Build Coastguard Worker acc.cff_accelerator = 1175*2d1272b8SAndroid Build Coastguard Worker cff_subset_accelerator_t::create(acc.blob, 1176*2d1272b8SAndroid Build Coastguard Worker parsed_charstrings, 1177*2d1272b8SAndroid Build Coastguard Worker parsed_global_subrs_storage, 1178*2d1272b8SAndroid Build Coastguard Worker parsed_local_subrs_storage); 1179*2d1272b8SAndroid Build Coastguard Worker } 1180*2d1272b8SAndroid Build Coastguard Worker get_parsed_charstringCFF::subr_subsetter_t1181*2d1272b8SAndroid Build Coastguard Worker const parsed_cs_str_t& get_parsed_charstring (unsigned i) const 1182*2d1272b8SAndroid Build Coastguard Worker { 1183*2d1272b8SAndroid Build Coastguard Worker if (cached_charstrings) return *(cached_charstrings[i]); 1184*2d1272b8SAndroid Build Coastguard Worker return parsed_charstrings[i]; 1185*2d1272b8SAndroid Build Coastguard Worker } 1186*2d1272b8SAndroid Build Coastguard Worker 1187*2d1272b8SAndroid Build Coastguard Worker protected: 1188*2d1272b8SAndroid Build Coastguard Worker const ACC &acc; 1189*2d1272b8SAndroid Build Coastguard Worker const hb_subset_plan_t *plan; 1190*2d1272b8SAndroid Build Coastguard Worker 1191*2d1272b8SAndroid Build Coastguard Worker subr_closures_t closures; 1192*2d1272b8SAndroid Build Coastguard Worker 1193*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<const parsed_cs_str_t*> cached_charstrings; 1194*2d1272b8SAndroid Build Coastguard Worker const parsed_cs_str_vec_t* parsed_global_subrs; 1195*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<parsed_cs_str_vec_t>* parsed_local_subrs; 1196*2d1272b8SAndroid Build Coastguard Worker 1197*2d1272b8SAndroid Build Coastguard Worker subr_remaps_t remaps; 1198*2d1272b8SAndroid Build Coastguard Worker 1199*2d1272b8SAndroid Build Coastguard Worker private: 1200*2d1272b8SAndroid Build Coastguard Worker 1201*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_vec_t parsed_charstrings; 1202*2d1272b8SAndroid Build Coastguard Worker parsed_cs_str_vec_t parsed_global_subrs_storage; 1203*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<parsed_cs_str_vec_t> parsed_local_subrs_storage; 1204*2d1272b8SAndroid Build Coastguard Worker typedef typename SUBRS::count_type subr_count_type; 1205*2d1272b8SAndroid Build Coastguard Worker }; 1206*2d1272b8SAndroid Build Coastguard Worker 1207*2d1272b8SAndroid Build Coastguard Worker } /* namespace CFF */ 1208*2d1272b8SAndroid Build Coastguard Worker 1209*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL bool 1210*2d1272b8SAndroid Build Coastguard Worker hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan, 1211*2d1272b8SAndroid Build Coastguard Worker unsigned int fdCount, 1212*2d1272b8SAndroid Build Coastguard Worker const CFF::FDSelect &src, /* IN */ 1213*2d1272b8SAndroid Build Coastguard Worker unsigned int &subset_fd_count /* OUT */, 1214*2d1272b8SAndroid Build Coastguard Worker unsigned int &subset_fdselect_size /* OUT */, 1215*2d1272b8SAndroid Build Coastguard Worker unsigned int &subset_fdselect_format /* OUT */, 1216*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<CFF::code_pair_t> &fdselect_ranges /* OUT */, 1217*2d1272b8SAndroid Build Coastguard Worker hb_inc_bimap_t &fdmap /* OUT */); 1218*2d1272b8SAndroid Build Coastguard Worker 1219*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL bool 1220*2d1272b8SAndroid Build Coastguard Worker hb_serialize_cff_fdselect (hb_serialize_context_t *c, 1221*2d1272b8SAndroid Build Coastguard Worker unsigned int num_glyphs, 1222*2d1272b8SAndroid Build Coastguard Worker const CFF::FDSelect &src, 1223*2d1272b8SAndroid Build Coastguard Worker unsigned int fd_count, 1224*2d1272b8SAndroid Build Coastguard Worker unsigned int fdselect_format, 1225*2d1272b8SAndroid Build Coastguard Worker unsigned int size, 1226*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<CFF::code_pair_t> &fdselect_ranges); 1227*2d1272b8SAndroid Build Coastguard Worker 1228*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_SUBSET_CFF_COMMON_HH */ 1229