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_OT_CFF1_TABLE_HH 28*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_CFF1_TABLE_HH 29*2d1272b8SAndroid Build Coastguard Worker 30*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-cff-common.hh" 31*2d1272b8SAndroid Build Coastguard Worker #include "hb-subset-cff-common.hh" 32*2d1272b8SAndroid Build Coastguard Worker #include "hb-draw.hh" 33*2d1272b8SAndroid Build Coastguard Worker #include "hb-paint.hh" 34*2d1272b8SAndroid Build Coastguard Worker 35*2d1272b8SAndroid Build Coastguard Worker #define HB_STRING_ARRAY_NAME cff1_std_strings 36*2d1272b8SAndroid Build Coastguard Worker #define HB_STRING_ARRAY_LIST "hb-ot-cff1-std-str.hh" 37*2d1272b8SAndroid Build Coastguard Worker #include "hb-string-array.hh" 38*2d1272b8SAndroid Build Coastguard Worker #undef HB_STRING_ARRAY_LIST 39*2d1272b8SAndroid Build Coastguard Worker #undef HB_STRING_ARRAY_NAME 40*2d1272b8SAndroid Build Coastguard Worker 41*2d1272b8SAndroid Build Coastguard Worker namespace CFF { 42*2d1272b8SAndroid Build Coastguard Worker 43*2d1272b8SAndroid Build Coastguard Worker /* 44*2d1272b8SAndroid Build Coastguard Worker * CFF -- Compact Font Format (CFF) 45*2d1272b8SAndroid Build Coastguard Worker * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf 46*2d1272b8SAndroid Build Coastguard Worker */ 47*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_TAG_CFF1 HB_TAG('C','F','F',' ') 48*2d1272b8SAndroid Build Coastguard Worker 49*2d1272b8SAndroid Build Coastguard Worker #define CFF_UNDEF_SID CFF_UNDEF_CODE 50*2d1272b8SAndroid Build Coastguard Worker 51*2d1272b8SAndroid Build Coastguard Worker enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 }; 52*2d1272b8SAndroid Build Coastguard Worker enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 }; 53*2d1272b8SAndroid Build Coastguard Worker 54*2d1272b8SAndroid Build Coastguard Worker typedef CFF1Index CFF1CharStrings; 55*2d1272b8SAndroid Build Coastguard Worker typedef Subrs<HBUINT16> CFF1Subrs; 56*2d1272b8SAndroid Build Coastguard Worker 57*2d1272b8SAndroid Build Coastguard Worker struct CFF1FDSelect : FDSelect {}; 58*2d1272b8SAndroid Build Coastguard Worker 59*2d1272b8SAndroid Build Coastguard Worker /* Encoding */ 60*2d1272b8SAndroid Build Coastguard Worker struct Encoding0 { sanitizeCFF::Encoding061*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 62*2d1272b8SAndroid Build Coastguard Worker { 63*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 64*2d1272b8SAndroid Build Coastguard Worker return_trace (codes.sanitize (c)); 65*2d1272b8SAndroid Build Coastguard Worker } 66*2d1272b8SAndroid Build Coastguard Worker get_codeCFF::Encoding067*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t get_code (hb_codepoint_t glyph) const 68*2d1272b8SAndroid Build Coastguard Worker { 69*2d1272b8SAndroid Build Coastguard Worker assert (glyph > 0); 70*2d1272b8SAndroid Build Coastguard Worker glyph--; 71*2d1272b8SAndroid Build Coastguard Worker if (glyph < nCodes ()) 72*2d1272b8SAndroid Build Coastguard Worker { 73*2d1272b8SAndroid Build Coastguard Worker return (hb_codepoint_t)codes[glyph]; 74*2d1272b8SAndroid Build Coastguard Worker } 75*2d1272b8SAndroid Build Coastguard Worker else 76*2d1272b8SAndroid Build Coastguard Worker return CFF_UNDEF_CODE; 77*2d1272b8SAndroid Build Coastguard Worker } 78*2d1272b8SAndroid Build Coastguard Worker nCodesCFF::Encoding079*2d1272b8SAndroid Build Coastguard Worker HBUINT8 &nCodes () { return codes.len; } nCodesCFF::Encoding080*2d1272b8SAndroid Build Coastguard Worker HBUINT8 nCodes () const { return codes.len; } 81*2d1272b8SAndroid Build Coastguard Worker 82*2d1272b8SAndroid Build Coastguard Worker ArrayOf<HBUINT8, HBUINT8> codes; 83*2d1272b8SAndroid Build Coastguard Worker 84*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_ARRAY_SIZED (1, codes); 85*2d1272b8SAndroid Build Coastguard Worker }; 86*2d1272b8SAndroid Build Coastguard Worker 87*2d1272b8SAndroid Build Coastguard Worker struct Encoding1_Range { sanitizeCFF::Encoding1_Range88*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 89*2d1272b8SAndroid Build Coastguard Worker { 90*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 91*2d1272b8SAndroid Build Coastguard Worker return_trace (c->check_struct (this)); 92*2d1272b8SAndroid Build Coastguard Worker } 93*2d1272b8SAndroid Build Coastguard Worker 94*2d1272b8SAndroid Build Coastguard Worker HBUINT8 first; 95*2d1272b8SAndroid Build Coastguard Worker HBUINT8 nLeft; 96*2d1272b8SAndroid Build Coastguard Worker 97*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (2); 98*2d1272b8SAndroid Build Coastguard Worker }; 99*2d1272b8SAndroid Build Coastguard Worker 100*2d1272b8SAndroid Build Coastguard Worker struct Encoding1 { sanitizeCFF::Encoding1101*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 102*2d1272b8SAndroid Build Coastguard Worker { 103*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 104*2d1272b8SAndroid Build Coastguard Worker return_trace (ranges.sanitize (c)); 105*2d1272b8SAndroid Build Coastguard Worker } 106*2d1272b8SAndroid Build Coastguard Worker get_codeCFF::Encoding1107*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t get_code (hb_codepoint_t glyph) const 108*2d1272b8SAndroid Build Coastguard Worker { 109*2d1272b8SAndroid Build Coastguard Worker /* TODO: Add cache like get_sid. */ 110*2d1272b8SAndroid Build Coastguard Worker assert (glyph > 0); 111*2d1272b8SAndroid Build Coastguard Worker glyph--; 112*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < nRanges (); i++) 113*2d1272b8SAndroid Build Coastguard Worker { 114*2d1272b8SAndroid Build Coastguard Worker if (glyph <= ranges[i].nLeft) 115*2d1272b8SAndroid Build Coastguard Worker { 116*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph; 117*2d1272b8SAndroid Build Coastguard Worker return (likely (code < 0x100) ? code: CFF_UNDEF_CODE); 118*2d1272b8SAndroid Build Coastguard Worker } 119*2d1272b8SAndroid Build Coastguard Worker glyph -= (ranges[i].nLeft + 1); 120*2d1272b8SAndroid Build Coastguard Worker } 121*2d1272b8SAndroid Build Coastguard Worker return CFF_UNDEF_CODE; 122*2d1272b8SAndroid Build Coastguard Worker } 123*2d1272b8SAndroid Build Coastguard Worker nRangesCFF::Encoding1124*2d1272b8SAndroid Build Coastguard Worker HBUINT8 &nRanges () { return ranges.len; } nRangesCFF::Encoding1125*2d1272b8SAndroid Build Coastguard Worker HBUINT8 nRanges () const { return ranges.len; } 126*2d1272b8SAndroid Build Coastguard Worker 127*2d1272b8SAndroid Build Coastguard Worker ArrayOf<Encoding1_Range, HBUINT8> ranges; 128*2d1272b8SAndroid Build Coastguard Worker 129*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_ARRAY_SIZED (1, ranges); 130*2d1272b8SAndroid Build Coastguard Worker }; 131*2d1272b8SAndroid Build Coastguard Worker 132*2d1272b8SAndroid Build Coastguard Worker struct SuppEncoding { sanitizeCFF::SuppEncoding133*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 134*2d1272b8SAndroid Build Coastguard Worker { 135*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 136*2d1272b8SAndroid Build Coastguard Worker return_trace (c->check_struct (this)); 137*2d1272b8SAndroid Build Coastguard Worker } 138*2d1272b8SAndroid Build Coastguard Worker 139*2d1272b8SAndroid Build Coastguard Worker HBUINT8 code; 140*2d1272b8SAndroid Build Coastguard Worker HBUINT16 glyph; 141*2d1272b8SAndroid Build Coastguard Worker 142*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (3); 143*2d1272b8SAndroid Build Coastguard Worker }; 144*2d1272b8SAndroid Build Coastguard Worker 145*2d1272b8SAndroid Build Coastguard Worker struct CFF1SuppEncData { sanitizeCFF::CFF1SuppEncData146*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 147*2d1272b8SAndroid Build Coastguard Worker { 148*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 149*2d1272b8SAndroid Build Coastguard Worker return_trace (supps.sanitize (c)); 150*2d1272b8SAndroid Build Coastguard Worker } 151*2d1272b8SAndroid Build Coastguard Worker get_codesCFF::CFF1SuppEncData152*2d1272b8SAndroid Build Coastguard Worker void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const 153*2d1272b8SAndroid Build Coastguard Worker { 154*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < nSups (); i++) 155*2d1272b8SAndroid Build Coastguard Worker if (sid == supps[i].glyph) 156*2d1272b8SAndroid Build Coastguard Worker codes.push (supps[i].code); 157*2d1272b8SAndroid Build Coastguard Worker } 158*2d1272b8SAndroid Build Coastguard Worker nSupsCFF::CFF1SuppEncData159*2d1272b8SAndroid Build Coastguard Worker HBUINT8 &nSups () { return supps.len; } nSupsCFF::CFF1SuppEncData160*2d1272b8SAndroid Build Coastguard Worker HBUINT8 nSups () const { return supps.len; } 161*2d1272b8SAndroid Build Coastguard Worker 162*2d1272b8SAndroid Build Coastguard Worker ArrayOf<SuppEncoding, HBUINT8> supps; 163*2d1272b8SAndroid Build Coastguard Worker 164*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_ARRAY_SIZED (1, supps); 165*2d1272b8SAndroid Build Coastguard Worker }; 166*2d1272b8SAndroid Build Coastguard Worker 167*2d1272b8SAndroid Build Coastguard Worker struct Encoding 168*2d1272b8SAndroid Build Coastguard Worker { 169*2d1272b8SAndroid Build Coastguard Worker /* serialize a fullset Encoding */ serializeCFF::Encoding170*2d1272b8SAndroid Build Coastguard Worker bool serialize (hb_serialize_context_t *c, const Encoding &src) 171*2d1272b8SAndroid Build Coastguard Worker { 172*2d1272b8SAndroid Build Coastguard Worker TRACE_SERIALIZE (this); 173*2d1272b8SAndroid Build Coastguard Worker return_trace (c->embed (src)); 174*2d1272b8SAndroid Build Coastguard Worker } 175*2d1272b8SAndroid Build Coastguard Worker 176*2d1272b8SAndroid Build Coastguard Worker /* serialize a subset Encoding */ serializeCFF::Encoding177*2d1272b8SAndroid Build Coastguard Worker bool serialize (hb_serialize_context_t *c, 178*2d1272b8SAndroid Build Coastguard Worker uint8_t format, 179*2d1272b8SAndroid Build Coastguard Worker unsigned int enc_count, 180*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<code_pair_t>& code_ranges, 181*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<code_pair_t>& supp_codes) 182*2d1272b8SAndroid Build Coastguard Worker { 183*2d1272b8SAndroid Build Coastguard Worker TRACE_SERIALIZE (this); 184*2d1272b8SAndroid Build Coastguard Worker Encoding *dest = c->extend_min (this); 185*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!dest)) return_trace (false); 186*2d1272b8SAndroid Build Coastguard Worker dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0); 187*2d1272b8SAndroid Build Coastguard Worker switch (format) { 188*2d1272b8SAndroid Build Coastguard Worker case 0: 189*2d1272b8SAndroid Build Coastguard Worker { 190*2d1272b8SAndroid Build Coastguard Worker Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count); 191*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!fmt0)) return_trace (false); 192*2d1272b8SAndroid Build Coastguard Worker fmt0->nCodes () = enc_count; 193*2d1272b8SAndroid Build Coastguard Worker unsigned int glyph = 0; 194*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < code_ranges.length; i++) 195*2d1272b8SAndroid Build Coastguard Worker { 196*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t code = code_ranges[i].code; 197*2d1272b8SAndroid Build Coastguard Worker for (int left = (int)code_ranges[i].glyph; left >= 0; left--) 198*2d1272b8SAndroid Build Coastguard Worker fmt0->codes[glyph++] = code++; 199*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!((glyph <= 0x100) && (code <= 0x100)))) 200*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 201*2d1272b8SAndroid Build Coastguard Worker } 202*2d1272b8SAndroid Build Coastguard Worker } 203*2d1272b8SAndroid Build Coastguard Worker break; 204*2d1272b8SAndroid Build Coastguard Worker 205*2d1272b8SAndroid Build Coastguard Worker case 1: 206*2d1272b8SAndroid Build Coastguard Worker { 207*2d1272b8SAndroid Build Coastguard Worker Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length); 208*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!fmt1)) return_trace (false); 209*2d1272b8SAndroid Build Coastguard Worker fmt1->nRanges () = code_ranges.length; 210*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < code_ranges.length; i++) 211*2d1272b8SAndroid Build Coastguard Worker { 212*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF)))) 213*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 214*2d1272b8SAndroid Build Coastguard Worker fmt1->ranges[i].first = code_ranges[i].code; 215*2d1272b8SAndroid Build Coastguard Worker fmt1->ranges[i].nLeft = code_ranges[i].glyph; 216*2d1272b8SAndroid Build Coastguard Worker } 217*2d1272b8SAndroid Build Coastguard Worker } 218*2d1272b8SAndroid Build Coastguard Worker break; 219*2d1272b8SAndroid Build Coastguard Worker 220*2d1272b8SAndroid Build Coastguard Worker } 221*2d1272b8SAndroid Build Coastguard Worker 222*2d1272b8SAndroid Build Coastguard Worker if (supp_codes.length) 223*2d1272b8SAndroid Build Coastguard Worker { 224*2d1272b8SAndroid Build Coastguard Worker CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length); 225*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!suppData)) return_trace (false); 226*2d1272b8SAndroid Build Coastguard Worker suppData->nSups () = supp_codes.length; 227*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < supp_codes.length; i++) 228*2d1272b8SAndroid Build Coastguard Worker { 229*2d1272b8SAndroid Build Coastguard Worker suppData->supps[i].code = supp_codes[i].code; 230*2d1272b8SAndroid Build Coastguard Worker suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */ 231*2d1272b8SAndroid Build Coastguard Worker } 232*2d1272b8SAndroid Build Coastguard Worker } 233*2d1272b8SAndroid Build Coastguard Worker 234*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 235*2d1272b8SAndroid Build Coastguard Worker } 236*2d1272b8SAndroid Build Coastguard Worker get_sizeCFF::Encoding237*2d1272b8SAndroid Build Coastguard Worker unsigned int get_size () const 238*2d1272b8SAndroid Build Coastguard Worker { 239*2d1272b8SAndroid Build Coastguard Worker unsigned int size = min_size; 240*2d1272b8SAndroid Build Coastguard Worker switch (table_format ()) 241*2d1272b8SAndroid Build Coastguard Worker { 242*2d1272b8SAndroid Build Coastguard Worker case 0: hb_barrier (); size += u.format0.get_size (); break; 243*2d1272b8SAndroid Build Coastguard Worker case 1: hb_barrier (); size += u.format1.get_size (); break; 244*2d1272b8SAndroid Build Coastguard Worker } 245*2d1272b8SAndroid Build Coastguard Worker if (has_supplement ()) 246*2d1272b8SAndroid Build Coastguard Worker size += suppEncData ().get_size (); 247*2d1272b8SAndroid Build Coastguard Worker return size; 248*2d1272b8SAndroid Build Coastguard Worker } 249*2d1272b8SAndroid Build Coastguard Worker get_codeCFF::Encoding250*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t get_code (hb_codepoint_t glyph) const 251*2d1272b8SAndroid Build Coastguard Worker { 252*2d1272b8SAndroid Build Coastguard Worker switch (table_format ()) 253*2d1272b8SAndroid Build Coastguard Worker { 254*2d1272b8SAndroid Build Coastguard Worker case 0: hb_barrier (); return u.format0.get_code (glyph); 255*2d1272b8SAndroid Build Coastguard Worker case 1: hb_barrier (); return u.format1.get_code (glyph); 256*2d1272b8SAndroid Build Coastguard Worker default:return 0; 257*2d1272b8SAndroid Build Coastguard Worker } 258*2d1272b8SAndroid Build Coastguard Worker } 259*2d1272b8SAndroid Build Coastguard Worker table_formatCFF::Encoding260*2d1272b8SAndroid Build Coastguard Worker uint8_t table_format () const { return format & 0x7F; } has_supplementCFF::Encoding261*2d1272b8SAndroid Build Coastguard Worker bool has_supplement () const { return format & 0x80; } 262*2d1272b8SAndroid Build Coastguard Worker get_supplement_codesCFF::Encoding263*2d1272b8SAndroid Build Coastguard Worker void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const 264*2d1272b8SAndroid Build Coastguard Worker { 265*2d1272b8SAndroid Build Coastguard Worker codes.resize (0); 266*2d1272b8SAndroid Build Coastguard Worker if (has_supplement ()) 267*2d1272b8SAndroid Build Coastguard Worker suppEncData().get_codes (sid, codes); 268*2d1272b8SAndroid Build Coastguard Worker } 269*2d1272b8SAndroid Build Coastguard Worker sanitizeCFF::Encoding270*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 271*2d1272b8SAndroid Build Coastguard Worker { 272*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 273*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!c->check_struct (this))) 274*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 275*2d1272b8SAndroid Build Coastguard Worker hb_barrier (); 276*2d1272b8SAndroid Build Coastguard Worker 277*2d1272b8SAndroid Build Coastguard Worker switch (table_format ()) 278*2d1272b8SAndroid Build Coastguard Worker { 279*2d1272b8SAndroid Build Coastguard Worker case 0: hb_barrier (); if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break; 280*2d1272b8SAndroid Build Coastguard Worker case 1: hb_barrier (); if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break; 281*2d1272b8SAndroid Build Coastguard Worker default:return_trace (false); 282*2d1272b8SAndroid Build Coastguard Worker } 283*2d1272b8SAndroid Build Coastguard Worker return_trace (likely (!has_supplement () || suppEncData ().sanitize (c))); 284*2d1272b8SAndroid Build Coastguard Worker } 285*2d1272b8SAndroid Build Coastguard Worker 286*2d1272b8SAndroid Build Coastguard Worker protected: suppEncDataCFF::Encoding287*2d1272b8SAndroid Build Coastguard Worker const CFF1SuppEncData &suppEncData () const 288*2d1272b8SAndroid Build Coastguard Worker { 289*2d1272b8SAndroid Build Coastguard Worker switch (table_format ()) 290*2d1272b8SAndroid Build Coastguard Worker { 291*2d1272b8SAndroid Build Coastguard Worker case 0: hb_barrier (); return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]); 292*2d1272b8SAndroid Build Coastguard Worker case 1: hb_barrier (); return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]); 293*2d1272b8SAndroid Build Coastguard Worker default:return Null (CFF1SuppEncData); 294*2d1272b8SAndroid Build Coastguard Worker } 295*2d1272b8SAndroid Build Coastguard Worker } 296*2d1272b8SAndroid Build Coastguard Worker 297*2d1272b8SAndroid Build Coastguard Worker public: 298*2d1272b8SAndroid Build Coastguard Worker HBUINT8 format; 299*2d1272b8SAndroid Build Coastguard Worker union { 300*2d1272b8SAndroid Build Coastguard Worker Encoding0 format0; 301*2d1272b8SAndroid Build Coastguard Worker Encoding1 format1; 302*2d1272b8SAndroid Build Coastguard Worker } u; 303*2d1272b8SAndroid Build Coastguard Worker /* CFF1SuppEncData suppEncData; */ 304*2d1272b8SAndroid Build Coastguard Worker 305*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_MIN (1); 306*2d1272b8SAndroid Build Coastguard Worker }; 307*2d1272b8SAndroid Build Coastguard Worker 308*2d1272b8SAndroid Build Coastguard Worker /* Charset */ 309*2d1272b8SAndroid Build Coastguard Worker struct Charset0 310*2d1272b8SAndroid Build Coastguard Worker { sanitizeCFF::Charset0311*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const 312*2d1272b8SAndroid Build Coastguard Worker { 313*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 314*2d1272b8SAndroid Build Coastguard Worker if (num_charset_entries) *num_charset_entries = num_glyphs; 315*2d1272b8SAndroid Build Coastguard Worker return_trace (sids.sanitize (c, num_glyphs - 1)); 316*2d1272b8SAndroid Build Coastguard Worker } 317*2d1272b8SAndroid Build Coastguard Worker get_sidCFF::Charset0318*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const 319*2d1272b8SAndroid Build Coastguard Worker { 320*2d1272b8SAndroid Build Coastguard Worker if (unlikely (glyph >= num_glyphs)) return 0; 321*2d1272b8SAndroid Build Coastguard Worker if (unlikely (glyph == 0)) 322*2d1272b8SAndroid Build Coastguard Worker return 0; 323*2d1272b8SAndroid Build Coastguard Worker else 324*2d1272b8SAndroid Build Coastguard Worker return sids[glyph - 1]; 325*2d1272b8SAndroid Build Coastguard Worker } 326*2d1272b8SAndroid Build Coastguard Worker collect_glyph_to_sid_mapCFF::Charset0327*2d1272b8SAndroid Build Coastguard Worker void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const 328*2d1272b8SAndroid Build Coastguard Worker { 329*2d1272b8SAndroid Build Coastguard Worker mapping->resize (num_glyphs, false); 330*2d1272b8SAndroid Build Coastguard Worker for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++) 331*2d1272b8SAndroid Build Coastguard Worker mapping->arrayZ[gid] = {sids[gid - 1], gid}; 332*2d1272b8SAndroid Build Coastguard Worker } 333*2d1272b8SAndroid Build Coastguard Worker get_glyphCFF::Charset0334*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 335*2d1272b8SAndroid Build Coastguard Worker { 336*2d1272b8SAndroid Build Coastguard Worker if (sid == 0) 337*2d1272b8SAndroid Build Coastguard Worker return 0; 338*2d1272b8SAndroid Build Coastguard Worker 339*2d1272b8SAndroid Build Coastguard Worker for (unsigned int glyph = 1; glyph < num_glyphs; glyph++) 340*2d1272b8SAndroid Build Coastguard Worker { 341*2d1272b8SAndroid Build Coastguard Worker if (sids[glyph-1] == sid) 342*2d1272b8SAndroid Build Coastguard Worker return glyph; 343*2d1272b8SAndroid Build Coastguard Worker } 344*2d1272b8SAndroid Build Coastguard Worker return 0; 345*2d1272b8SAndroid Build Coastguard Worker } 346*2d1272b8SAndroid Build Coastguard Worker get_sizeCFF::Charset0347*2d1272b8SAndroid Build Coastguard Worker static unsigned int get_size (unsigned int num_glyphs) 348*2d1272b8SAndroid Build Coastguard Worker { 349*2d1272b8SAndroid Build Coastguard Worker assert (num_glyphs > 0); 350*2d1272b8SAndroid Build Coastguard Worker return UnsizedArrayOf<HBUINT16>::get_size (num_glyphs - 1); 351*2d1272b8SAndroid Build Coastguard Worker } 352*2d1272b8SAndroid Build Coastguard Worker 353*2d1272b8SAndroid Build Coastguard Worker UnsizedArrayOf<HBUINT16> sids; 354*2d1272b8SAndroid Build Coastguard Worker 355*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_ARRAY(0, sids); 356*2d1272b8SAndroid Build Coastguard Worker }; 357*2d1272b8SAndroid Build Coastguard Worker 358*2d1272b8SAndroid Build Coastguard Worker template <typename TYPE> 359*2d1272b8SAndroid Build Coastguard Worker struct Charset_Range { sanitizeCFF::Charset_Range360*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 361*2d1272b8SAndroid Build Coastguard Worker { 362*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 363*2d1272b8SAndroid Build Coastguard Worker return_trace (c->check_struct (this)); 364*2d1272b8SAndroid Build Coastguard Worker } 365*2d1272b8SAndroid Build Coastguard Worker 366*2d1272b8SAndroid Build Coastguard Worker HBUINT16 first; 367*2d1272b8SAndroid Build Coastguard Worker TYPE nLeft; 368*2d1272b8SAndroid Build Coastguard Worker 369*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size); 370*2d1272b8SAndroid Build Coastguard Worker }; 371*2d1272b8SAndroid Build Coastguard Worker 372*2d1272b8SAndroid Build Coastguard Worker template <typename TYPE> 373*2d1272b8SAndroid Build Coastguard Worker struct Charset1_2 { sanitizeCFF::Charset1_2374*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const 375*2d1272b8SAndroid Build Coastguard Worker { 376*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 377*2d1272b8SAndroid Build Coastguard Worker num_glyphs--; 378*2d1272b8SAndroid Build Coastguard Worker unsigned i; 379*2d1272b8SAndroid Build Coastguard Worker for (i = 0; num_glyphs > 0; i++) 380*2d1272b8SAndroid Build Coastguard Worker { 381*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!(ranges[i].sanitize (c) && 382*2d1272b8SAndroid Build Coastguard Worker hb_barrier () && 383*2d1272b8SAndroid Build Coastguard Worker (num_glyphs >= ranges[i].nLeft + 1)))) 384*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 385*2d1272b8SAndroid Build Coastguard Worker num_glyphs -= (ranges[i].nLeft + 1); 386*2d1272b8SAndroid Build Coastguard Worker } 387*2d1272b8SAndroid Build Coastguard Worker if (num_charset_entries) 388*2d1272b8SAndroid Build Coastguard Worker *num_charset_entries = i; 389*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 390*2d1272b8SAndroid Build Coastguard Worker } 391*2d1272b8SAndroid Build Coastguard Worker get_sidCFF::Charset1_2392*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs, 393*2d1272b8SAndroid Build Coastguard Worker code_pair_t *cache = nullptr) const 394*2d1272b8SAndroid Build Coastguard Worker { 395*2d1272b8SAndroid Build Coastguard Worker if (unlikely (glyph >= num_glyphs)) return 0; 396*2d1272b8SAndroid Build Coastguard Worker unsigned i; 397*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t start_glyph; 398*2d1272b8SAndroid Build Coastguard Worker if (cache && likely (cache->glyph <= glyph)) 399*2d1272b8SAndroid Build Coastguard Worker { 400*2d1272b8SAndroid Build Coastguard Worker i = cache->code; 401*2d1272b8SAndroid Build Coastguard Worker start_glyph = cache->glyph; 402*2d1272b8SAndroid Build Coastguard Worker } 403*2d1272b8SAndroid Build Coastguard Worker else 404*2d1272b8SAndroid Build Coastguard Worker { 405*2d1272b8SAndroid Build Coastguard Worker if (unlikely (glyph == 0)) return 0; 406*2d1272b8SAndroid Build Coastguard Worker i = 0; 407*2d1272b8SAndroid Build Coastguard Worker start_glyph = 1; 408*2d1272b8SAndroid Build Coastguard Worker } 409*2d1272b8SAndroid Build Coastguard Worker glyph -= start_glyph; 410*2d1272b8SAndroid Build Coastguard Worker for (;; i++) 411*2d1272b8SAndroid Build Coastguard Worker { 412*2d1272b8SAndroid Build Coastguard Worker unsigned count = ranges[i].nLeft; 413*2d1272b8SAndroid Build Coastguard Worker if (glyph <= count) 414*2d1272b8SAndroid Build Coastguard Worker { 415*2d1272b8SAndroid Build Coastguard Worker if (cache) 416*2d1272b8SAndroid Build Coastguard Worker *cache = {i, start_glyph}; 417*2d1272b8SAndroid Build Coastguard Worker return ranges[i].first + glyph; 418*2d1272b8SAndroid Build Coastguard Worker } 419*2d1272b8SAndroid Build Coastguard Worker count++; 420*2d1272b8SAndroid Build Coastguard Worker start_glyph += count; 421*2d1272b8SAndroid Build Coastguard Worker glyph -= count; 422*2d1272b8SAndroid Build Coastguard Worker } 423*2d1272b8SAndroid Build Coastguard Worker 424*2d1272b8SAndroid Build Coastguard Worker return 0; 425*2d1272b8SAndroid Build Coastguard Worker } 426*2d1272b8SAndroid Build Coastguard Worker collect_glyph_to_sid_mapCFF::Charset1_2427*2d1272b8SAndroid Build Coastguard Worker void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const 428*2d1272b8SAndroid Build Coastguard Worker { 429*2d1272b8SAndroid Build Coastguard Worker mapping->resize (num_glyphs, false); 430*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t gid = 1; 431*2d1272b8SAndroid Build Coastguard Worker if (gid >= num_glyphs) 432*2d1272b8SAndroid Build Coastguard Worker return; 433*2d1272b8SAndroid Build Coastguard Worker for (unsigned i = 0;; i++) 434*2d1272b8SAndroid Build Coastguard Worker { 435*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t sid = ranges[i].first; 436*2d1272b8SAndroid Build Coastguard Worker unsigned count = ranges[i].nLeft + 1; 437*2d1272b8SAndroid Build Coastguard Worker unsigned last = gid + count; 438*2d1272b8SAndroid Build Coastguard Worker for (unsigned j = 0; j < count; j++) 439*2d1272b8SAndroid Build Coastguard Worker mapping->arrayZ[gid++] = {sid++, last - 1}; 440*2d1272b8SAndroid Build Coastguard Worker 441*2d1272b8SAndroid Build Coastguard Worker if (gid >= num_glyphs) 442*2d1272b8SAndroid Build Coastguard Worker break; 443*2d1272b8SAndroid Build Coastguard Worker } 444*2d1272b8SAndroid Build Coastguard Worker } 445*2d1272b8SAndroid Build Coastguard Worker get_glyphCFF::Charset1_2446*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 447*2d1272b8SAndroid Build Coastguard Worker { 448*2d1272b8SAndroid Build Coastguard Worker if (sid == 0) return 0; 449*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph = 1; 450*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0;; i++) 451*2d1272b8SAndroid Build Coastguard Worker { 452*2d1272b8SAndroid Build Coastguard Worker if (glyph >= num_glyphs) 453*2d1272b8SAndroid Build Coastguard Worker return 0; 454*2d1272b8SAndroid Build Coastguard Worker if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft)) 455*2d1272b8SAndroid Build Coastguard Worker return glyph + (sid - ranges[i].first); 456*2d1272b8SAndroid Build Coastguard Worker glyph += (ranges[i].nLeft + 1); 457*2d1272b8SAndroid Build Coastguard Worker } 458*2d1272b8SAndroid Build Coastguard Worker 459*2d1272b8SAndroid Build Coastguard Worker return 0; 460*2d1272b8SAndroid Build Coastguard Worker } 461*2d1272b8SAndroid Build Coastguard Worker get_sizeCFF::Charset1_2462*2d1272b8SAndroid Build Coastguard Worker unsigned int get_size (unsigned int num_glyphs) const 463*2d1272b8SAndroid Build Coastguard Worker { 464*2d1272b8SAndroid Build Coastguard Worker int glyph = (int) num_glyphs; 465*2d1272b8SAndroid Build Coastguard Worker unsigned num_ranges = 0; 466*2d1272b8SAndroid Build Coastguard Worker 467*2d1272b8SAndroid Build Coastguard Worker assert (glyph > 0); 468*2d1272b8SAndroid Build Coastguard Worker glyph--; 469*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; glyph > 0; i++) 470*2d1272b8SAndroid Build Coastguard Worker { 471*2d1272b8SAndroid Build Coastguard Worker glyph -= (ranges[i].nLeft + 1); 472*2d1272b8SAndroid Build Coastguard Worker num_ranges++; 473*2d1272b8SAndroid Build Coastguard Worker } 474*2d1272b8SAndroid Build Coastguard Worker 475*2d1272b8SAndroid Build Coastguard Worker return get_size_for_ranges (num_ranges); 476*2d1272b8SAndroid Build Coastguard Worker } 477*2d1272b8SAndroid Build Coastguard Worker get_size_for_rangesCFF::Charset1_2478*2d1272b8SAndroid Build Coastguard Worker static unsigned int get_size_for_ranges (unsigned int num_ranges) 479*2d1272b8SAndroid Build Coastguard Worker { 480*2d1272b8SAndroid Build Coastguard Worker return UnsizedArrayOf<Charset_Range<TYPE> >::get_size (num_ranges); 481*2d1272b8SAndroid Build Coastguard Worker } 482*2d1272b8SAndroid Build Coastguard Worker 483*2d1272b8SAndroid Build Coastguard Worker UnsizedArrayOf<Charset_Range<TYPE>> ranges; 484*2d1272b8SAndroid Build Coastguard Worker 485*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_ARRAY (0, ranges); 486*2d1272b8SAndroid Build Coastguard Worker }; 487*2d1272b8SAndroid Build Coastguard Worker 488*2d1272b8SAndroid Build Coastguard Worker typedef Charset1_2<HBUINT8> Charset1; 489*2d1272b8SAndroid Build Coastguard Worker typedef Charset1_2<HBUINT16> Charset2; 490*2d1272b8SAndroid Build Coastguard Worker typedef Charset_Range<HBUINT8> Charset1_Range; 491*2d1272b8SAndroid Build Coastguard Worker typedef Charset_Range<HBUINT16> Charset2_Range; 492*2d1272b8SAndroid Build Coastguard Worker 493*2d1272b8SAndroid Build Coastguard Worker struct Charset 494*2d1272b8SAndroid Build Coastguard Worker { 495*2d1272b8SAndroid Build Coastguard Worker /* serialize a fullset Charset */ serializeCFF::Charset496*2d1272b8SAndroid Build Coastguard Worker bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs) 497*2d1272b8SAndroid Build Coastguard Worker { 498*2d1272b8SAndroid Build Coastguard Worker TRACE_SERIALIZE (this); 499*2d1272b8SAndroid Build Coastguard Worker return_trace (c->embed ((const char *) &src, src.get_size (num_glyphs))); 500*2d1272b8SAndroid Build Coastguard Worker } 501*2d1272b8SAndroid Build Coastguard Worker 502*2d1272b8SAndroid Build Coastguard Worker /* serialize a subset Charset */ serializeCFF::Charset503*2d1272b8SAndroid Build Coastguard Worker bool serialize (hb_serialize_context_t *c, 504*2d1272b8SAndroid Build Coastguard Worker uint8_t format, 505*2d1272b8SAndroid Build Coastguard Worker unsigned int num_glyphs, 506*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<code_pair_t>& sid_ranges) 507*2d1272b8SAndroid Build Coastguard Worker { 508*2d1272b8SAndroid Build Coastguard Worker TRACE_SERIALIZE (this); 509*2d1272b8SAndroid Build Coastguard Worker Charset *dest = c->extend_min (this); 510*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!dest)) return_trace (false); 511*2d1272b8SAndroid Build Coastguard Worker dest->format = format; 512*2d1272b8SAndroid Build Coastguard Worker switch (format) 513*2d1272b8SAndroid Build Coastguard Worker { 514*2d1272b8SAndroid Build Coastguard Worker case 0: 515*2d1272b8SAndroid Build Coastguard Worker { 516*2d1272b8SAndroid Build Coastguard Worker Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::get_size (num_glyphs), false); 517*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!fmt0)) return_trace (false); 518*2d1272b8SAndroid Build Coastguard Worker unsigned int glyph = 0; 519*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < sid_ranges.length; i++) 520*2d1272b8SAndroid Build Coastguard Worker { 521*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t sid = sid_ranges.arrayZ[i].code; 522*2d1272b8SAndroid Build Coastguard Worker for (int left = (int)sid_ranges.arrayZ[i].glyph; left >= 0; left--) 523*2d1272b8SAndroid Build Coastguard Worker fmt0->sids[glyph++] = sid++; 524*2d1272b8SAndroid Build Coastguard Worker } 525*2d1272b8SAndroid Build Coastguard Worker } 526*2d1272b8SAndroid Build Coastguard Worker break; 527*2d1272b8SAndroid Build Coastguard Worker 528*2d1272b8SAndroid Build Coastguard Worker case 1: 529*2d1272b8SAndroid Build Coastguard Worker { 530*2d1272b8SAndroid Build Coastguard Worker Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::get_size_for_ranges (sid_ranges.length), false); 531*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!fmt1)) return_trace (false); 532*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t all_glyphs = 0; 533*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < sid_ranges.length; i++) 534*2d1272b8SAndroid Build Coastguard Worker { 535*2d1272b8SAndroid Build Coastguard Worker auto &_ = sid_ranges.arrayZ[i]; 536*2d1272b8SAndroid Build Coastguard Worker all_glyphs |= _.glyph; 537*2d1272b8SAndroid Build Coastguard Worker fmt1->ranges[i].first = _.code; 538*2d1272b8SAndroid Build Coastguard Worker fmt1->ranges[i].nLeft = _.glyph; 539*2d1272b8SAndroid Build Coastguard Worker } 540*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!(all_glyphs <= 0xFF))) 541*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 542*2d1272b8SAndroid Build Coastguard Worker } 543*2d1272b8SAndroid Build Coastguard Worker break; 544*2d1272b8SAndroid Build Coastguard Worker 545*2d1272b8SAndroid Build Coastguard Worker case 2: 546*2d1272b8SAndroid Build Coastguard Worker { 547*2d1272b8SAndroid Build Coastguard Worker Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::get_size_for_ranges (sid_ranges.length), false); 548*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!fmt2)) return_trace (false); 549*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t all_glyphs = 0; 550*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < sid_ranges.length; i++) 551*2d1272b8SAndroid Build Coastguard Worker { 552*2d1272b8SAndroid Build Coastguard Worker auto &_ = sid_ranges.arrayZ[i]; 553*2d1272b8SAndroid Build Coastguard Worker all_glyphs |= _.glyph; 554*2d1272b8SAndroid Build Coastguard Worker fmt2->ranges[i].first = _.code; 555*2d1272b8SAndroid Build Coastguard Worker fmt2->ranges[i].nLeft = _.glyph; 556*2d1272b8SAndroid Build Coastguard Worker } 557*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!(all_glyphs <= 0xFFFF))) 558*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 559*2d1272b8SAndroid Build Coastguard Worker } 560*2d1272b8SAndroid Build Coastguard Worker break; 561*2d1272b8SAndroid Build Coastguard Worker 562*2d1272b8SAndroid Build Coastguard Worker } 563*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 564*2d1272b8SAndroid Build Coastguard Worker } 565*2d1272b8SAndroid Build Coastguard Worker get_sizeCFF::Charset566*2d1272b8SAndroid Build Coastguard Worker unsigned int get_size (unsigned int num_glyphs) const 567*2d1272b8SAndroid Build Coastguard Worker { 568*2d1272b8SAndroid Build Coastguard Worker switch (format) 569*2d1272b8SAndroid Build Coastguard Worker { 570*2d1272b8SAndroid Build Coastguard Worker case 0: hb_barrier (); return min_size + u.format0.get_size (num_glyphs); 571*2d1272b8SAndroid Build Coastguard Worker case 1: hb_barrier (); return min_size + u.format1.get_size (num_glyphs); 572*2d1272b8SAndroid Build Coastguard Worker case 2: hb_barrier (); return min_size + u.format2.get_size (num_glyphs); 573*2d1272b8SAndroid Build Coastguard Worker default:return 0; 574*2d1272b8SAndroid Build Coastguard Worker } 575*2d1272b8SAndroid Build Coastguard Worker } 576*2d1272b8SAndroid Build Coastguard Worker get_sidCFF::Charset577*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs, 578*2d1272b8SAndroid Build Coastguard Worker code_pair_t *cache = nullptr) const 579*2d1272b8SAndroid Build Coastguard Worker { 580*2d1272b8SAndroid Build Coastguard Worker switch (format) 581*2d1272b8SAndroid Build Coastguard Worker { 582*2d1272b8SAndroid Build Coastguard Worker case 0: hb_barrier (); return u.format0.get_sid (glyph, num_glyphs); 583*2d1272b8SAndroid Build Coastguard Worker case 1: hb_barrier (); return u.format1.get_sid (glyph, num_glyphs, cache); 584*2d1272b8SAndroid Build Coastguard Worker case 2: hb_barrier (); return u.format2.get_sid (glyph, num_glyphs, cache); 585*2d1272b8SAndroid Build Coastguard Worker default:return 0; 586*2d1272b8SAndroid Build Coastguard Worker } 587*2d1272b8SAndroid Build Coastguard Worker } 588*2d1272b8SAndroid Build Coastguard Worker collect_glyph_to_sid_mapCFF::Charset589*2d1272b8SAndroid Build Coastguard Worker void collect_glyph_to_sid_map (glyph_to_sid_map_t *mapping, unsigned int num_glyphs) const 590*2d1272b8SAndroid Build Coastguard Worker { 591*2d1272b8SAndroid Build Coastguard Worker switch (format) 592*2d1272b8SAndroid Build Coastguard Worker { 593*2d1272b8SAndroid Build Coastguard Worker case 0: hb_barrier (); u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return; 594*2d1272b8SAndroid Build Coastguard Worker case 1: hb_barrier (); u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return; 595*2d1272b8SAndroid Build Coastguard Worker case 2: hb_barrier (); u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return; 596*2d1272b8SAndroid Build Coastguard Worker default:return; 597*2d1272b8SAndroid Build Coastguard Worker } 598*2d1272b8SAndroid Build Coastguard Worker } 599*2d1272b8SAndroid Build Coastguard Worker get_glyphCFF::Charset600*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const 601*2d1272b8SAndroid Build Coastguard Worker { 602*2d1272b8SAndroid Build Coastguard Worker switch (format) 603*2d1272b8SAndroid Build Coastguard Worker { 604*2d1272b8SAndroid Build Coastguard Worker case 0: hb_barrier (); return u.format0.get_glyph (sid, num_glyphs); 605*2d1272b8SAndroid Build Coastguard Worker case 1: hb_barrier (); return u.format1.get_glyph (sid, num_glyphs); 606*2d1272b8SAndroid Build Coastguard Worker case 2: hb_barrier (); return u.format2.get_glyph (sid, num_glyphs); 607*2d1272b8SAndroid Build Coastguard Worker default:return 0; 608*2d1272b8SAndroid Build Coastguard Worker } 609*2d1272b8SAndroid Build Coastguard Worker } 610*2d1272b8SAndroid Build Coastguard Worker sanitizeCFF::Charset611*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c, unsigned *num_charset_entries) const 612*2d1272b8SAndroid Build Coastguard Worker { 613*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 614*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!c->check_struct (this))) 615*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 616*2d1272b8SAndroid Build Coastguard Worker hb_barrier (); 617*2d1272b8SAndroid Build Coastguard Worker 618*2d1272b8SAndroid Build Coastguard Worker switch (format) 619*2d1272b8SAndroid Build Coastguard Worker { 620*2d1272b8SAndroid Build Coastguard Worker case 0: hb_barrier (); return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries)); 621*2d1272b8SAndroid Build Coastguard Worker case 1: hb_barrier (); return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries)); 622*2d1272b8SAndroid Build Coastguard Worker case 2: hb_barrier (); return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries)); 623*2d1272b8SAndroid Build Coastguard Worker default:return_trace (false); 624*2d1272b8SAndroid Build Coastguard Worker } 625*2d1272b8SAndroid Build Coastguard Worker } 626*2d1272b8SAndroid Build Coastguard Worker 627*2d1272b8SAndroid Build Coastguard Worker HBUINT8 format; 628*2d1272b8SAndroid Build Coastguard Worker union { 629*2d1272b8SAndroid Build Coastguard Worker Charset0 format0; 630*2d1272b8SAndroid Build Coastguard Worker Charset1 format1; 631*2d1272b8SAndroid Build Coastguard Worker Charset2 format2; 632*2d1272b8SAndroid Build Coastguard Worker } u; 633*2d1272b8SAndroid Build Coastguard Worker 634*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_MIN (1); 635*2d1272b8SAndroid Build Coastguard Worker }; 636*2d1272b8SAndroid Build Coastguard Worker 637*2d1272b8SAndroid Build Coastguard Worker struct CFF1StringIndex : CFF1Index 638*2d1272b8SAndroid Build Coastguard Worker { serializeCFF::CFF1StringIndex639*2d1272b8SAndroid Build Coastguard Worker bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings, 640*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<unsigned> &sidmap) 641*2d1272b8SAndroid Build Coastguard Worker { 642*2d1272b8SAndroid Build Coastguard Worker TRACE_SERIALIZE (this); 643*2d1272b8SAndroid Build Coastguard Worker if (unlikely ((strings.count == 0) || (sidmap.length == 0))) 644*2d1272b8SAndroid Build Coastguard Worker { 645*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!c->extend_min (this->count))) 646*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 647*2d1272b8SAndroid Build Coastguard Worker count = 0; 648*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 649*2d1272b8SAndroid Build Coastguard Worker } 650*2d1272b8SAndroid Build Coastguard Worker 651*2d1272b8SAndroid Build Coastguard Worker if (unlikely (sidmap.in_error ())) return_trace (false); 652*2d1272b8SAndroid Build Coastguard Worker 653*2d1272b8SAndroid Build Coastguard Worker // Save this in a vector since serialize() iterates it twice. 654*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<hb_ubytes_t> bytesArray (+ hb_iter (sidmap) 655*2d1272b8SAndroid Build Coastguard Worker | hb_map (strings)); 656*2d1272b8SAndroid Build Coastguard Worker 657*2d1272b8SAndroid Build Coastguard Worker if (unlikely (bytesArray.in_error ())) return_trace (false); 658*2d1272b8SAndroid Build Coastguard Worker 659*2d1272b8SAndroid Build Coastguard Worker bool result = CFF1Index::serialize (c, bytesArray); 660*2d1272b8SAndroid Build Coastguard Worker return_trace (result); 661*2d1272b8SAndroid Build Coastguard Worker } 662*2d1272b8SAndroid Build Coastguard Worker }; 663*2d1272b8SAndroid Build Coastguard Worker 664*2d1272b8SAndroid Build Coastguard Worker struct cff1_top_dict_interp_env_t : num_interp_env_t 665*2d1272b8SAndroid Build Coastguard Worker { cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t666*2d1272b8SAndroid Build Coastguard Worker cff1_top_dict_interp_env_t () 667*2d1272b8SAndroid Build Coastguard Worker : num_interp_env_t(), prev_offset(0), last_offset(0) {} cff1_top_dict_interp_env_tCFF::cff1_top_dict_interp_env_t668*2d1272b8SAndroid Build Coastguard Worker cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes) 669*2d1272b8SAndroid Build Coastguard Worker : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {} 670*2d1272b8SAndroid Build Coastguard Worker 671*2d1272b8SAndroid Build Coastguard Worker unsigned int prev_offset; 672*2d1272b8SAndroid Build Coastguard Worker unsigned int last_offset; 673*2d1272b8SAndroid Build Coastguard Worker }; 674*2d1272b8SAndroid Build Coastguard Worker 675*2d1272b8SAndroid Build Coastguard Worker struct name_dict_values_t 676*2d1272b8SAndroid Build Coastguard Worker { 677*2d1272b8SAndroid Build Coastguard Worker enum name_dict_val_index_t 678*2d1272b8SAndroid Build Coastguard Worker { 679*2d1272b8SAndroid Build Coastguard Worker version, 680*2d1272b8SAndroid Build Coastguard Worker notice, 681*2d1272b8SAndroid Build Coastguard Worker copyright, 682*2d1272b8SAndroid Build Coastguard Worker fullName, 683*2d1272b8SAndroid Build Coastguard Worker familyName, 684*2d1272b8SAndroid Build Coastguard Worker weight, 685*2d1272b8SAndroid Build Coastguard Worker postscript, 686*2d1272b8SAndroid Build Coastguard Worker fontName, 687*2d1272b8SAndroid Build Coastguard Worker baseFontName, 688*2d1272b8SAndroid Build Coastguard Worker registry, 689*2d1272b8SAndroid Build Coastguard Worker ordering, 690*2d1272b8SAndroid Build Coastguard Worker 691*2d1272b8SAndroid Build Coastguard Worker ValCount 692*2d1272b8SAndroid Build Coastguard Worker }; 693*2d1272b8SAndroid Build Coastguard Worker initCFF::name_dict_values_t694*2d1272b8SAndroid Build Coastguard Worker void init () 695*2d1272b8SAndroid Build Coastguard Worker { 696*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < ValCount; i++) 697*2d1272b8SAndroid Build Coastguard Worker values[i] = CFF_UNDEF_SID; 698*2d1272b8SAndroid Build Coastguard Worker } 699*2d1272b8SAndroid Build Coastguard Worker operator []CFF::name_dict_values_t700*2d1272b8SAndroid Build Coastguard Worker unsigned int& operator[] (unsigned int i) 701*2d1272b8SAndroid Build Coastguard Worker { assert (i < ValCount); return values[i]; } 702*2d1272b8SAndroid Build Coastguard Worker operator []CFF::name_dict_values_t703*2d1272b8SAndroid Build Coastguard Worker unsigned int operator[] (unsigned int i) const 704*2d1272b8SAndroid Build Coastguard Worker { assert (i < ValCount); return values[i]; } 705*2d1272b8SAndroid Build Coastguard Worker name_op_to_indexCFF::name_dict_values_t706*2d1272b8SAndroid Build Coastguard Worker static enum name_dict_val_index_t name_op_to_index (op_code_t op) 707*2d1272b8SAndroid Build Coastguard Worker { 708*2d1272b8SAndroid Build Coastguard Worker switch (op) { 709*2d1272b8SAndroid Build Coastguard Worker default: // can't happen - just make some compiler happy 710*2d1272b8SAndroid Build Coastguard Worker case OpCode_version: 711*2d1272b8SAndroid Build Coastguard Worker return version; 712*2d1272b8SAndroid Build Coastguard Worker case OpCode_Notice: 713*2d1272b8SAndroid Build Coastguard Worker return notice; 714*2d1272b8SAndroid Build Coastguard Worker case OpCode_Copyright: 715*2d1272b8SAndroid Build Coastguard Worker return copyright; 716*2d1272b8SAndroid Build Coastguard Worker case OpCode_FullName: 717*2d1272b8SAndroid Build Coastguard Worker return fullName; 718*2d1272b8SAndroid Build Coastguard Worker case OpCode_FamilyName: 719*2d1272b8SAndroid Build Coastguard Worker return familyName; 720*2d1272b8SAndroid Build Coastguard Worker case OpCode_Weight: 721*2d1272b8SAndroid Build Coastguard Worker return weight; 722*2d1272b8SAndroid Build Coastguard Worker case OpCode_PostScript: 723*2d1272b8SAndroid Build Coastguard Worker return postscript; 724*2d1272b8SAndroid Build Coastguard Worker case OpCode_FontName: 725*2d1272b8SAndroid Build Coastguard Worker return fontName; 726*2d1272b8SAndroid Build Coastguard Worker case OpCode_BaseFontName: 727*2d1272b8SAndroid Build Coastguard Worker return baseFontName; 728*2d1272b8SAndroid Build Coastguard Worker } 729*2d1272b8SAndroid Build Coastguard Worker } 730*2d1272b8SAndroid Build Coastguard Worker 731*2d1272b8SAndroid Build Coastguard Worker unsigned int values[ValCount]; 732*2d1272b8SAndroid Build Coastguard Worker }; 733*2d1272b8SAndroid Build Coastguard Worker 734*2d1272b8SAndroid Build Coastguard Worker struct cff1_top_dict_val_t : op_str_t 735*2d1272b8SAndroid Build Coastguard Worker { 736*2d1272b8SAndroid Build Coastguard Worker unsigned int last_arg_offset; 737*2d1272b8SAndroid Build Coastguard Worker }; 738*2d1272b8SAndroid Build Coastguard Worker 739*2d1272b8SAndroid Build Coastguard Worker struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t> 740*2d1272b8SAndroid Build Coastguard Worker { initCFF::cff1_top_dict_values_t741*2d1272b8SAndroid Build Coastguard Worker void init () 742*2d1272b8SAndroid Build Coastguard Worker { 743*2d1272b8SAndroid Build Coastguard Worker top_dict_values_t<cff1_top_dict_val_t>::init (); 744*2d1272b8SAndroid Build Coastguard Worker 745*2d1272b8SAndroid Build Coastguard Worker nameSIDs.init (); 746*2d1272b8SAndroid Build Coastguard Worker ros_supplement = 0; 747*2d1272b8SAndroid Build Coastguard Worker cidCount = 8720; 748*2d1272b8SAndroid Build Coastguard Worker EncodingOffset = 0; 749*2d1272b8SAndroid Build Coastguard Worker CharsetOffset = 0; 750*2d1272b8SAndroid Build Coastguard Worker FDSelectOffset = 0; 751*2d1272b8SAndroid Build Coastguard Worker privateDictInfo.init (); 752*2d1272b8SAndroid Build Coastguard Worker } finiCFF::cff1_top_dict_values_t753*2d1272b8SAndroid Build Coastguard Worker void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); } 754*2d1272b8SAndroid Build Coastguard Worker is_CIDCFF::cff1_top_dict_values_t755*2d1272b8SAndroid Build Coastguard Worker bool is_CID () const 756*2d1272b8SAndroid Build Coastguard Worker { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; } 757*2d1272b8SAndroid Build Coastguard Worker 758*2d1272b8SAndroid Build Coastguard Worker name_dict_values_t nameSIDs; 759*2d1272b8SAndroid Build Coastguard Worker unsigned int ros_supplement_offset; 760*2d1272b8SAndroid Build Coastguard Worker unsigned int ros_supplement; 761*2d1272b8SAndroid Build Coastguard Worker unsigned int cidCount; 762*2d1272b8SAndroid Build Coastguard Worker 763*2d1272b8SAndroid Build Coastguard Worker int EncodingOffset; 764*2d1272b8SAndroid Build Coastguard Worker int CharsetOffset; 765*2d1272b8SAndroid Build Coastguard Worker int FDSelectOffset; 766*2d1272b8SAndroid Build Coastguard Worker table_info_t privateDictInfo; 767*2d1272b8SAndroid Build Coastguard Worker }; 768*2d1272b8SAndroid Build Coastguard Worker 769*2d1272b8SAndroid Build Coastguard Worker struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t> 770*2d1272b8SAndroid Build Coastguard Worker { process_opCFF::cff1_top_dict_opset_t771*2d1272b8SAndroid Build Coastguard Worker static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval) 772*2d1272b8SAndroid Build Coastguard Worker { 773*2d1272b8SAndroid Build Coastguard Worker cff1_top_dict_val_t val; 774*2d1272b8SAndroid Build Coastguard Worker val.last_arg_offset = (env.last_offset-1) - dictval.opStart; /* offset to the last argument */ 775*2d1272b8SAndroid Build Coastguard Worker 776*2d1272b8SAndroid Build Coastguard Worker switch (op) { 777*2d1272b8SAndroid Build Coastguard Worker case OpCode_version: 778*2d1272b8SAndroid Build Coastguard Worker case OpCode_Notice: 779*2d1272b8SAndroid Build Coastguard Worker case OpCode_Copyright: 780*2d1272b8SAndroid Build Coastguard Worker case OpCode_FullName: 781*2d1272b8SAndroid Build Coastguard Worker case OpCode_FontName: 782*2d1272b8SAndroid Build Coastguard Worker case OpCode_FamilyName: 783*2d1272b8SAndroid Build Coastguard Worker case OpCode_Weight: 784*2d1272b8SAndroid Build Coastguard Worker case OpCode_PostScript: 785*2d1272b8SAndroid Build Coastguard Worker case OpCode_BaseFontName: 786*2d1272b8SAndroid Build Coastguard Worker dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint (); 787*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 788*2d1272b8SAndroid Build Coastguard Worker break; 789*2d1272b8SAndroid Build Coastguard Worker case OpCode_isFixedPitch: 790*2d1272b8SAndroid Build Coastguard Worker case OpCode_ItalicAngle: 791*2d1272b8SAndroid Build Coastguard Worker case OpCode_UnderlinePosition: 792*2d1272b8SAndroid Build Coastguard Worker case OpCode_UnderlineThickness: 793*2d1272b8SAndroid Build Coastguard Worker case OpCode_PaintType: 794*2d1272b8SAndroid Build Coastguard Worker case OpCode_CharstringType: 795*2d1272b8SAndroid Build Coastguard Worker case OpCode_UniqueID: 796*2d1272b8SAndroid Build Coastguard Worker case OpCode_StrokeWidth: 797*2d1272b8SAndroid Build Coastguard Worker case OpCode_SyntheticBase: 798*2d1272b8SAndroid Build Coastguard Worker case OpCode_CIDFontVersion: 799*2d1272b8SAndroid Build Coastguard Worker case OpCode_CIDFontRevision: 800*2d1272b8SAndroid Build Coastguard Worker case OpCode_CIDFontType: 801*2d1272b8SAndroid Build Coastguard Worker case OpCode_UIDBase: 802*2d1272b8SAndroid Build Coastguard Worker case OpCode_FontBBox: 803*2d1272b8SAndroid Build Coastguard Worker case OpCode_XUID: 804*2d1272b8SAndroid Build Coastguard Worker case OpCode_BaseFontBlend: 805*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 806*2d1272b8SAndroid Build Coastguard Worker break; 807*2d1272b8SAndroid Build Coastguard Worker 808*2d1272b8SAndroid Build Coastguard Worker case OpCode_CIDCount: 809*2d1272b8SAndroid Build Coastguard Worker dictval.cidCount = env.argStack.pop_uint (); 810*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 811*2d1272b8SAndroid Build Coastguard Worker break; 812*2d1272b8SAndroid Build Coastguard Worker 813*2d1272b8SAndroid Build Coastguard Worker case OpCode_ROS: 814*2d1272b8SAndroid Build Coastguard Worker dictval.ros_supplement = env.argStack.pop_uint (); 815*2d1272b8SAndroid Build Coastguard Worker dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint (); 816*2d1272b8SAndroid Build Coastguard Worker dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint (); 817*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 818*2d1272b8SAndroid Build Coastguard Worker break; 819*2d1272b8SAndroid Build Coastguard Worker 820*2d1272b8SAndroid Build Coastguard Worker case OpCode_Encoding: 821*2d1272b8SAndroid Build Coastguard Worker dictval.EncodingOffset = env.argStack.pop_int (); 822*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 823*2d1272b8SAndroid Build Coastguard Worker if (unlikely (dictval.EncodingOffset == 0)) return; 824*2d1272b8SAndroid Build Coastguard Worker break; 825*2d1272b8SAndroid Build Coastguard Worker 826*2d1272b8SAndroid Build Coastguard Worker case OpCode_charset: 827*2d1272b8SAndroid Build Coastguard Worker dictval.CharsetOffset = env.argStack.pop_int (); 828*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 829*2d1272b8SAndroid Build Coastguard Worker if (unlikely (dictval.CharsetOffset == 0)) return; 830*2d1272b8SAndroid Build Coastguard Worker break; 831*2d1272b8SAndroid Build Coastguard Worker 832*2d1272b8SAndroid Build Coastguard Worker case OpCode_FDSelect: 833*2d1272b8SAndroid Build Coastguard Worker dictval.FDSelectOffset = env.argStack.pop_int (); 834*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 835*2d1272b8SAndroid Build Coastguard Worker break; 836*2d1272b8SAndroid Build Coastguard Worker 837*2d1272b8SAndroid Build Coastguard Worker case OpCode_Private: 838*2d1272b8SAndroid Build Coastguard Worker dictval.privateDictInfo.offset = env.argStack.pop_int (); 839*2d1272b8SAndroid Build Coastguard Worker dictval.privateDictInfo.size = env.argStack.pop_uint (); 840*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 841*2d1272b8SAndroid Build Coastguard Worker break; 842*2d1272b8SAndroid Build Coastguard Worker 843*2d1272b8SAndroid Build Coastguard Worker default: 844*2d1272b8SAndroid Build Coastguard Worker env.last_offset = env.str_ref.get_offset (); 845*2d1272b8SAndroid Build Coastguard Worker top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval); 846*2d1272b8SAndroid Build Coastguard Worker /* Record this operand below if stack is empty, otherwise done */ 847*2d1272b8SAndroid Build Coastguard Worker if (!env.argStack.is_empty ()) return; 848*2d1272b8SAndroid Build Coastguard Worker break; 849*2d1272b8SAndroid Build Coastguard Worker } 850*2d1272b8SAndroid Build Coastguard Worker 851*2d1272b8SAndroid Build Coastguard Worker if (unlikely (env.in_error ())) return; 852*2d1272b8SAndroid Build Coastguard Worker 853*2d1272b8SAndroid Build Coastguard Worker dictval.add_op (op, env.str_ref, val); 854*2d1272b8SAndroid Build Coastguard Worker } 855*2d1272b8SAndroid Build Coastguard Worker }; 856*2d1272b8SAndroid Build Coastguard Worker 857*2d1272b8SAndroid Build Coastguard Worker struct cff1_font_dict_values_t : dict_values_t<op_str_t> 858*2d1272b8SAndroid Build Coastguard Worker { initCFF::cff1_font_dict_values_t859*2d1272b8SAndroid Build Coastguard Worker void init () 860*2d1272b8SAndroid Build Coastguard Worker { 861*2d1272b8SAndroid Build Coastguard Worker dict_values_t<op_str_t>::init (); 862*2d1272b8SAndroid Build Coastguard Worker privateDictInfo.init (); 863*2d1272b8SAndroid Build Coastguard Worker fontName = CFF_UNDEF_SID; 864*2d1272b8SAndroid Build Coastguard Worker } finiCFF::cff1_font_dict_values_t865*2d1272b8SAndroid Build Coastguard Worker void fini () { dict_values_t<op_str_t>::fini (); } 866*2d1272b8SAndroid Build Coastguard Worker 867*2d1272b8SAndroid Build Coastguard Worker table_info_t privateDictInfo; 868*2d1272b8SAndroid Build Coastguard Worker unsigned int fontName; 869*2d1272b8SAndroid Build Coastguard Worker }; 870*2d1272b8SAndroid Build Coastguard Worker 871*2d1272b8SAndroid Build Coastguard Worker struct cff1_font_dict_opset_t : dict_opset_t 872*2d1272b8SAndroid Build Coastguard Worker { process_opCFF::cff1_font_dict_opset_t873*2d1272b8SAndroid Build Coastguard Worker static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval) 874*2d1272b8SAndroid Build Coastguard Worker { 875*2d1272b8SAndroid Build Coastguard Worker switch (op) { 876*2d1272b8SAndroid Build Coastguard Worker case OpCode_FontName: 877*2d1272b8SAndroid Build Coastguard Worker dictval.fontName = env.argStack.pop_uint (); 878*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 879*2d1272b8SAndroid Build Coastguard Worker break; 880*2d1272b8SAndroid Build Coastguard Worker case OpCode_FontMatrix: 881*2d1272b8SAndroid Build Coastguard Worker case OpCode_PaintType: 882*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 883*2d1272b8SAndroid Build Coastguard Worker break; 884*2d1272b8SAndroid Build Coastguard Worker case OpCode_Private: 885*2d1272b8SAndroid Build Coastguard Worker dictval.privateDictInfo.offset = env.argStack.pop_uint (); 886*2d1272b8SAndroid Build Coastguard Worker dictval.privateDictInfo.size = env.argStack.pop_uint (); 887*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 888*2d1272b8SAndroid Build Coastguard Worker break; 889*2d1272b8SAndroid Build Coastguard Worker 890*2d1272b8SAndroid Build Coastguard Worker default: 891*2d1272b8SAndroid Build Coastguard Worker dict_opset_t::process_op (op, env); 892*2d1272b8SAndroid Build Coastguard Worker if (!env.argStack.is_empty ()) return; 893*2d1272b8SAndroid Build Coastguard Worker break; 894*2d1272b8SAndroid Build Coastguard Worker } 895*2d1272b8SAndroid Build Coastguard Worker 896*2d1272b8SAndroid Build Coastguard Worker if (unlikely (env.in_error ())) return; 897*2d1272b8SAndroid Build Coastguard Worker 898*2d1272b8SAndroid Build Coastguard Worker dictval.add_op (op, env.str_ref); 899*2d1272b8SAndroid Build Coastguard Worker } 900*2d1272b8SAndroid Build Coastguard Worker }; 901*2d1272b8SAndroid Build Coastguard Worker 902*2d1272b8SAndroid Build Coastguard Worker template <typename VAL> 903*2d1272b8SAndroid Build Coastguard Worker struct cff1_private_dict_values_base_t : dict_values_t<VAL> 904*2d1272b8SAndroid Build Coastguard Worker { initCFF::cff1_private_dict_values_base_t905*2d1272b8SAndroid Build Coastguard Worker void init () 906*2d1272b8SAndroid Build Coastguard Worker { 907*2d1272b8SAndroid Build Coastguard Worker dict_values_t<VAL>::init (); 908*2d1272b8SAndroid Build Coastguard Worker subrsOffset = 0; 909*2d1272b8SAndroid Build Coastguard Worker localSubrs = &Null (CFF1Subrs); 910*2d1272b8SAndroid Build Coastguard Worker } finiCFF::cff1_private_dict_values_base_t911*2d1272b8SAndroid Build Coastguard Worker void fini () { dict_values_t<VAL>::fini (); } 912*2d1272b8SAndroid Build Coastguard Worker 913*2d1272b8SAndroid Build Coastguard Worker int subrsOffset; 914*2d1272b8SAndroid Build Coastguard Worker const CFF1Subrs *localSubrs; 915*2d1272b8SAndroid Build Coastguard Worker }; 916*2d1272b8SAndroid Build Coastguard Worker 917*2d1272b8SAndroid Build Coastguard Worker typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t; 918*2d1272b8SAndroid Build Coastguard Worker typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t; 919*2d1272b8SAndroid Build Coastguard Worker 920*2d1272b8SAndroid Build Coastguard Worker struct cff1_private_dict_opset_t : dict_opset_t 921*2d1272b8SAndroid Build Coastguard Worker { process_opCFF::cff1_private_dict_opset_t922*2d1272b8SAndroid Build Coastguard Worker static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval) 923*2d1272b8SAndroid Build Coastguard Worker { 924*2d1272b8SAndroid Build Coastguard Worker num_dict_val_t val; 925*2d1272b8SAndroid Build Coastguard Worker val.init (); 926*2d1272b8SAndroid Build Coastguard Worker 927*2d1272b8SAndroid Build Coastguard Worker switch (op) { 928*2d1272b8SAndroid Build Coastguard Worker case OpCode_BlueValues: 929*2d1272b8SAndroid Build Coastguard Worker case OpCode_OtherBlues: 930*2d1272b8SAndroid Build Coastguard Worker case OpCode_FamilyBlues: 931*2d1272b8SAndroid Build Coastguard Worker case OpCode_FamilyOtherBlues: 932*2d1272b8SAndroid Build Coastguard Worker case OpCode_StemSnapH: 933*2d1272b8SAndroid Build Coastguard Worker case OpCode_StemSnapV: 934*2d1272b8SAndroid Build Coastguard Worker case OpCode_StdHW: 935*2d1272b8SAndroid Build Coastguard Worker case OpCode_StdVW: 936*2d1272b8SAndroid Build Coastguard Worker case OpCode_BlueScale: 937*2d1272b8SAndroid Build Coastguard Worker case OpCode_BlueShift: 938*2d1272b8SAndroid Build Coastguard Worker case OpCode_BlueFuzz: 939*2d1272b8SAndroid Build Coastguard Worker case OpCode_ForceBold: 940*2d1272b8SAndroid Build Coastguard Worker case OpCode_LanguageGroup: 941*2d1272b8SAndroid Build Coastguard Worker case OpCode_ExpansionFactor: 942*2d1272b8SAndroid Build Coastguard Worker case OpCode_initialRandomSeed: 943*2d1272b8SAndroid Build Coastguard Worker case OpCode_defaultWidthX: 944*2d1272b8SAndroid Build Coastguard Worker case OpCode_nominalWidthX: 945*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 946*2d1272b8SAndroid Build Coastguard Worker break; 947*2d1272b8SAndroid Build Coastguard Worker case OpCode_Subrs: 948*2d1272b8SAndroid Build Coastguard Worker dictval.subrsOffset = env.argStack.pop_int (); 949*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 950*2d1272b8SAndroid Build Coastguard Worker break; 951*2d1272b8SAndroid Build Coastguard Worker 952*2d1272b8SAndroid Build Coastguard Worker default: 953*2d1272b8SAndroid Build Coastguard Worker dict_opset_t::process_op (op, env); 954*2d1272b8SAndroid Build Coastguard Worker if (!env.argStack.is_empty ()) return; 955*2d1272b8SAndroid Build Coastguard Worker break; 956*2d1272b8SAndroid Build Coastguard Worker } 957*2d1272b8SAndroid Build Coastguard Worker 958*2d1272b8SAndroid Build Coastguard Worker if (unlikely (env.in_error ())) return; 959*2d1272b8SAndroid Build Coastguard Worker 960*2d1272b8SAndroid Build Coastguard Worker dictval.add_op (op, env.str_ref, val); 961*2d1272b8SAndroid Build Coastguard Worker } 962*2d1272b8SAndroid Build Coastguard Worker }; 963*2d1272b8SAndroid Build Coastguard Worker 964*2d1272b8SAndroid Build Coastguard Worker struct cff1_private_dict_opset_subset_t : dict_opset_t 965*2d1272b8SAndroid Build Coastguard Worker { process_opCFF::cff1_private_dict_opset_subset_t966*2d1272b8SAndroid Build Coastguard Worker static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval) 967*2d1272b8SAndroid Build Coastguard Worker { 968*2d1272b8SAndroid Build Coastguard Worker switch (op) { 969*2d1272b8SAndroid Build Coastguard Worker case OpCode_BlueValues: 970*2d1272b8SAndroid Build Coastguard Worker case OpCode_OtherBlues: 971*2d1272b8SAndroid Build Coastguard Worker case OpCode_FamilyBlues: 972*2d1272b8SAndroid Build Coastguard Worker case OpCode_FamilyOtherBlues: 973*2d1272b8SAndroid Build Coastguard Worker case OpCode_StemSnapH: 974*2d1272b8SAndroid Build Coastguard Worker case OpCode_StemSnapV: 975*2d1272b8SAndroid Build Coastguard Worker case OpCode_StdHW: 976*2d1272b8SAndroid Build Coastguard Worker case OpCode_StdVW: 977*2d1272b8SAndroid Build Coastguard Worker case OpCode_BlueScale: 978*2d1272b8SAndroid Build Coastguard Worker case OpCode_BlueShift: 979*2d1272b8SAndroid Build Coastguard Worker case OpCode_BlueFuzz: 980*2d1272b8SAndroid Build Coastguard Worker case OpCode_ForceBold: 981*2d1272b8SAndroid Build Coastguard Worker case OpCode_LanguageGroup: 982*2d1272b8SAndroid Build Coastguard Worker case OpCode_ExpansionFactor: 983*2d1272b8SAndroid Build Coastguard Worker case OpCode_initialRandomSeed: 984*2d1272b8SAndroid Build Coastguard Worker case OpCode_defaultWidthX: 985*2d1272b8SAndroid Build Coastguard Worker case OpCode_nominalWidthX: 986*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 987*2d1272b8SAndroid Build Coastguard Worker break; 988*2d1272b8SAndroid Build Coastguard Worker 989*2d1272b8SAndroid Build Coastguard Worker case OpCode_Subrs: 990*2d1272b8SAndroid Build Coastguard Worker dictval.subrsOffset = env.argStack.pop_int (); 991*2d1272b8SAndroid Build Coastguard Worker env.clear_args (); 992*2d1272b8SAndroid Build Coastguard Worker break; 993*2d1272b8SAndroid Build Coastguard Worker 994*2d1272b8SAndroid Build Coastguard Worker default: 995*2d1272b8SAndroid Build Coastguard Worker dict_opset_t::process_op (op, env); 996*2d1272b8SAndroid Build Coastguard Worker if (!env.argStack.is_empty ()) return; 997*2d1272b8SAndroid Build Coastguard Worker break; 998*2d1272b8SAndroid Build Coastguard Worker } 999*2d1272b8SAndroid Build Coastguard Worker 1000*2d1272b8SAndroid Build Coastguard Worker if (unlikely (env.in_error ())) return; 1001*2d1272b8SAndroid Build Coastguard Worker 1002*2d1272b8SAndroid Build Coastguard Worker dictval.add_op (op, env.str_ref); 1003*2d1272b8SAndroid Build Coastguard Worker } 1004*2d1272b8SAndroid Build Coastguard Worker }; 1005*2d1272b8SAndroid Build Coastguard Worker 1006*2d1272b8SAndroid Build Coastguard Worker typedef dict_interpreter_t<cff1_top_dict_opset_t, cff1_top_dict_values_t, cff1_top_dict_interp_env_t> cff1_top_dict_interpreter_t; 1007*2d1272b8SAndroid Build Coastguard Worker typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t; 1008*2d1272b8SAndroid Build Coastguard Worker 1009*2d1272b8SAndroid Build Coastguard Worker typedef CFF1Index CFF1NameIndex; 1010*2d1272b8SAndroid Build Coastguard Worker typedef CFF1Index CFF1TopDictIndex; 1011*2d1272b8SAndroid Build Coastguard Worker 1012*2d1272b8SAndroid Build Coastguard Worker struct cff1_font_dict_values_mod_t 1013*2d1272b8SAndroid Build Coastguard Worker { cff1_font_dict_values_mod_tCFF::cff1_font_dict_values_mod_t1014*2d1272b8SAndroid Build Coastguard Worker cff1_font_dict_values_mod_t() { init (); } 1015*2d1272b8SAndroid Build Coastguard Worker initCFF::cff1_font_dict_values_mod_t1016*2d1272b8SAndroid Build Coastguard Worker void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); } 1017*2d1272b8SAndroid Build Coastguard Worker initCFF::cff1_font_dict_values_mod_t1018*2d1272b8SAndroid Build Coastguard Worker void init (const cff1_font_dict_values_t *base_, 1019*2d1272b8SAndroid Build Coastguard Worker unsigned int fontName_) 1020*2d1272b8SAndroid Build Coastguard Worker { 1021*2d1272b8SAndroid Build Coastguard Worker base = base_; 1022*2d1272b8SAndroid Build Coastguard Worker fontName = fontName_; 1023*2d1272b8SAndroid Build Coastguard Worker privateDictInfo.init (); 1024*2d1272b8SAndroid Build Coastguard Worker } 1025*2d1272b8SAndroid Build Coastguard Worker get_countCFF::cff1_font_dict_values_mod_t1026*2d1272b8SAndroid Build Coastguard Worker unsigned get_count () const { return base->get_count (); } 1027*2d1272b8SAndroid Build Coastguard Worker operator []CFF::cff1_font_dict_values_mod_t1028*2d1272b8SAndroid Build Coastguard Worker const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; } 1029*2d1272b8SAndroid Build Coastguard Worker 1030*2d1272b8SAndroid Build Coastguard Worker const cff1_font_dict_values_t *base; 1031*2d1272b8SAndroid Build Coastguard Worker table_info_t privateDictInfo; 1032*2d1272b8SAndroid Build Coastguard Worker unsigned int fontName; 1033*2d1272b8SAndroid Build Coastguard Worker }; 1034*2d1272b8SAndroid Build Coastguard Worker 1035*2d1272b8SAndroid Build Coastguard Worker struct CFF1FDArray : FDArray<HBUINT16> 1036*2d1272b8SAndroid Build Coastguard Worker { 1037*2d1272b8SAndroid Build Coastguard Worker /* FDArray::serialize() requires this partial specialization to compile */ 1038*2d1272b8SAndroid Build Coastguard Worker template <typename ITER, typename OP_SERIALIZER> serializeCFF::CFF1FDArray1039*2d1272b8SAndroid Build Coastguard Worker bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr) 1040*2d1272b8SAndroid Build Coastguard Worker { return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); } 1041*2d1272b8SAndroid Build Coastguard Worker }; 1042*2d1272b8SAndroid Build Coastguard Worker 1043*2d1272b8SAndroid Build Coastguard Worker } /* namespace CFF */ 1044*2d1272b8SAndroid Build Coastguard Worker 1045*2d1272b8SAndroid Build Coastguard Worker namespace OT { 1046*2d1272b8SAndroid Build Coastguard Worker 1047*2d1272b8SAndroid Build Coastguard Worker using namespace CFF; 1048*2d1272b8SAndroid Build Coastguard Worker 1049*2d1272b8SAndroid Build Coastguard Worker struct cff1 1050*2d1272b8SAndroid Build Coastguard Worker { 1051*2d1272b8SAndroid Build Coastguard Worker static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF1; 1052*2d1272b8SAndroid Build Coastguard Worker sanitizeOT::cff11053*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c) const 1054*2d1272b8SAndroid Build Coastguard Worker { 1055*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 1056*2d1272b8SAndroid Build Coastguard Worker return_trace (c->check_struct (this) && 1057*2d1272b8SAndroid Build Coastguard Worker hb_barrier () && 1058*2d1272b8SAndroid Build Coastguard Worker likely (version.major == 1)); 1059*2d1272b8SAndroid Build Coastguard Worker } 1060*2d1272b8SAndroid Build Coastguard Worker 1061*2d1272b8SAndroid Build Coastguard Worker template <typename PRIVOPSET, typename PRIVDICTVAL> 1062*2d1272b8SAndroid Build Coastguard Worker struct accelerator_templ_t 1063*2d1272b8SAndroid Build Coastguard Worker { 1064*2d1272b8SAndroid Build Coastguard Worker static constexpr hb_tag_t tableTag = cff1::tableTag; 1065*2d1272b8SAndroid Build Coastguard Worker accelerator_templ_tOT::cff1::accelerator_templ_t1066*2d1272b8SAndroid Build Coastguard Worker accelerator_templ_t (hb_face_t *face) 1067*2d1272b8SAndroid Build Coastguard Worker { 1068*2d1272b8SAndroid Build Coastguard Worker if (!face) return; 1069*2d1272b8SAndroid Build Coastguard Worker 1070*2d1272b8SAndroid Build Coastguard Worker topDict.init (); 1071*2d1272b8SAndroid Build Coastguard Worker fontDicts.init (); 1072*2d1272b8SAndroid Build Coastguard Worker privateDicts.init (); 1073*2d1272b8SAndroid Build Coastguard Worker 1074*2d1272b8SAndroid Build Coastguard Worker this->blob = sc.reference_table<cff1> (face); 1075*2d1272b8SAndroid Build Coastguard Worker 1076*2d1272b8SAndroid Build Coastguard Worker /* setup for run-time santization */ 1077*2d1272b8SAndroid Build Coastguard Worker sc.init (this->blob); 1078*2d1272b8SAndroid Build Coastguard Worker sc.start_processing (); 1079*2d1272b8SAndroid Build Coastguard Worker 1080*2d1272b8SAndroid Build Coastguard Worker const OT::cff1 *cff = this->blob->template as<OT::cff1> (); 1081*2d1272b8SAndroid Build Coastguard Worker 1082*2d1272b8SAndroid Build Coastguard Worker if (cff == &Null (OT::cff1)) 1083*2d1272b8SAndroid Build Coastguard Worker goto fail; 1084*2d1272b8SAndroid Build Coastguard Worker 1085*2d1272b8SAndroid Build Coastguard Worker nameIndex = &cff->nameIndex (cff); 1086*2d1272b8SAndroid Build Coastguard Worker if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc)) 1087*2d1272b8SAndroid Build Coastguard Worker goto fail; 1088*2d1272b8SAndroid Build Coastguard Worker hb_barrier (); 1089*2d1272b8SAndroid Build Coastguard Worker 1090*2d1272b8SAndroid Build Coastguard Worker topDictIndex = &StructAtOffsetOrNull<CFF1TopDictIndex> (nameIndex, nameIndex->get_size (), sc); 1091*2d1272b8SAndroid Build Coastguard Worker if (topDictIndex == &Null (CFF1TopDictIndex) || (topDictIndex->count == 0)) 1092*2d1272b8SAndroid Build Coastguard Worker goto fail; 1093*2d1272b8SAndroid Build Coastguard Worker hb_barrier (); 1094*2d1272b8SAndroid Build Coastguard Worker 1095*2d1272b8SAndroid Build Coastguard Worker { /* parse top dict */ 1096*2d1272b8SAndroid Build Coastguard Worker const hb_ubytes_t topDictStr = (*topDictIndex)[0]; 1097*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!topDictStr.sanitize (&sc))) goto fail; 1098*2d1272b8SAndroid Build Coastguard Worker hb_barrier (); 1099*2d1272b8SAndroid Build Coastguard Worker cff1_top_dict_interp_env_t env (topDictStr); 1100*2d1272b8SAndroid Build Coastguard Worker cff1_top_dict_interpreter_t top_interp (env); 1101*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!top_interp.interpret (topDict))) goto fail; 1102*2d1272b8SAndroid Build Coastguard Worker } 1103*2d1272b8SAndroid Build Coastguard Worker 1104*2d1272b8SAndroid Build Coastguard Worker if (is_predef_charset ()) 1105*2d1272b8SAndroid Build Coastguard Worker charset = &Null (Charset); 1106*2d1272b8SAndroid Build Coastguard Worker else 1107*2d1272b8SAndroid Build Coastguard Worker { 1108*2d1272b8SAndroid Build Coastguard Worker charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset, sc, &num_charset_entries); 1109*2d1272b8SAndroid Build Coastguard Worker if (unlikely (charset == &Null (Charset))) goto fail; 1110*2d1272b8SAndroid Build Coastguard Worker } 1111*2d1272b8SAndroid Build Coastguard Worker 1112*2d1272b8SAndroid Build Coastguard Worker fdCount = 1; 1113*2d1272b8SAndroid Build Coastguard Worker if (is_CID ()) 1114*2d1272b8SAndroid Build Coastguard Worker { 1115*2d1272b8SAndroid Build Coastguard Worker fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset, sc); 1116*2d1272b8SAndroid Build Coastguard Worker fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset, sc, fdArray->count); 1117*2d1272b8SAndroid Build Coastguard Worker if (unlikely (fdArray == &Null (CFF1FDArray) || 1118*2d1272b8SAndroid Build Coastguard Worker fdSelect == &Null (CFF1FDSelect))) 1119*2d1272b8SAndroid Build Coastguard Worker goto fail; 1120*2d1272b8SAndroid Build Coastguard Worker 1121*2d1272b8SAndroid Build Coastguard Worker fdCount = fdArray->count; 1122*2d1272b8SAndroid Build Coastguard Worker } 1123*2d1272b8SAndroid Build Coastguard Worker else 1124*2d1272b8SAndroid Build Coastguard Worker { 1125*2d1272b8SAndroid Build Coastguard Worker fdArray = &Null (CFF1FDArray); 1126*2d1272b8SAndroid Build Coastguard Worker fdSelect = &Null (CFF1FDSelect); 1127*2d1272b8SAndroid Build Coastguard Worker } 1128*2d1272b8SAndroid Build Coastguard Worker 1129*2d1272b8SAndroid Build Coastguard Worker encoding = &Null (Encoding); 1130*2d1272b8SAndroid Build Coastguard Worker if (is_CID ()) 1131*2d1272b8SAndroid Build Coastguard Worker { 1132*2d1272b8SAndroid Build Coastguard Worker if (unlikely (charset == &Null (Charset))) goto fail; 1133*2d1272b8SAndroid Build Coastguard Worker } 1134*2d1272b8SAndroid Build Coastguard Worker else 1135*2d1272b8SAndroid Build Coastguard Worker { 1136*2d1272b8SAndroid Build Coastguard Worker if (!is_predef_encoding ()) 1137*2d1272b8SAndroid Build Coastguard Worker { 1138*2d1272b8SAndroid Build Coastguard Worker encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset, sc); 1139*2d1272b8SAndroid Build Coastguard Worker if (unlikely (encoding == &Null (Encoding))) goto fail; 1140*2d1272b8SAndroid Build Coastguard Worker } 1141*2d1272b8SAndroid Build Coastguard Worker } 1142*2d1272b8SAndroid Build Coastguard Worker 1143*2d1272b8SAndroid Build Coastguard Worker stringIndex = &StructAtOffsetOrNull<CFF1StringIndex> (topDictIndex, topDictIndex->get_size (), sc); 1144*2d1272b8SAndroid Build Coastguard Worker if (stringIndex == &Null (CFF1StringIndex)) 1145*2d1272b8SAndroid Build Coastguard Worker goto fail; 1146*2d1272b8SAndroid Build Coastguard Worker 1147*2d1272b8SAndroid Build Coastguard Worker globalSubrs = &StructAtOffsetOrNull<CFF1Subrs> (stringIndex, stringIndex->get_size (), sc); 1148*2d1272b8SAndroid Build Coastguard Worker charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset, sc); 1149*2d1272b8SAndroid Build Coastguard Worker if (charStrings == &Null (CFF1CharStrings)) 1150*2d1272b8SAndroid Build Coastguard Worker goto fail; 1151*2d1272b8SAndroid Build Coastguard Worker 1152*2d1272b8SAndroid Build Coastguard Worker num_glyphs = charStrings->count; 1153*2d1272b8SAndroid Build Coastguard Worker if (num_glyphs != sc.get_num_glyphs ()) 1154*2d1272b8SAndroid Build Coastguard Worker goto fail; 1155*2d1272b8SAndroid Build Coastguard Worker 1156*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!privateDicts.resize (fdCount))) 1157*2d1272b8SAndroid Build Coastguard Worker goto fail; 1158*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < fdCount; i++) 1159*2d1272b8SAndroid Build Coastguard Worker privateDicts[i].init (); 1160*2d1272b8SAndroid Build Coastguard Worker 1161*2d1272b8SAndroid Build Coastguard Worker // parse CID font dicts and gather private dicts 1162*2d1272b8SAndroid Build Coastguard Worker if (is_CID ()) 1163*2d1272b8SAndroid Build Coastguard Worker { 1164*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < fdCount; i++) 1165*2d1272b8SAndroid Build Coastguard Worker { 1166*2d1272b8SAndroid Build Coastguard Worker hb_ubytes_t fontDictStr = (*fdArray)[i]; 1167*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!fontDictStr.sanitize (&sc))) goto fail; 1168*2d1272b8SAndroid Build Coastguard Worker hb_barrier (); 1169*2d1272b8SAndroid Build Coastguard Worker cff1_font_dict_values_t *font; 1170*2d1272b8SAndroid Build Coastguard Worker cff1_top_dict_interp_env_t env (fontDictStr); 1171*2d1272b8SAndroid Build Coastguard Worker cff1_font_dict_interpreter_t font_interp (env); 1172*2d1272b8SAndroid Build Coastguard Worker font = fontDicts.push (); 1173*2d1272b8SAndroid Build Coastguard Worker if (unlikely (fontDicts.in_error ())) goto fail; 1174*2d1272b8SAndroid Build Coastguard Worker 1175*2d1272b8SAndroid Build Coastguard Worker font->init (); 1176*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!font_interp.interpret (*font))) goto fail; 1177*2d1272b8SAndroid Build Coastguard Worker PRIVDICTVAL *priv = &privateDicts[i]; 1178*2d1272b8SAndroid Build Coastguard Worker const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); 1179*2d1272b8SAndroid Build Coastguard Worker if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; 1180*2d1272b8SAndroid Build Coastguard Worker num_interp_env_t env2 (privDictStr); 1181*2d1272b8SAndroid Build Coastguard Worker dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2); 1182*2d1272b8SAndroid Build Coastguard Worker priv->init (); 1183*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!priv_interp.interpret (*priv))) goto fail; 1184*2d1272b8SAndroid Build Coastguard Worker 1185*2d1272b8SAndroid Build Coastguard Worker priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset, sc); 1186*2d1272b8SAndroid Build Coastguard Worker } 1187*2d1272b8SAndroid Build Coastguard Worker } 1188*2d1272b8SAndroid Build Coastguard Worker else /* non-CID */ 1189*2d1272b8SAndroid Build Coastguard Worker { 1190*2d1272b8SAndroid Build Coastguard Worker cff1_top_dict_values_t *font = &topDict; 1191*2d1272b8SAndroid Build Coastguard Worker PRIVDICTVAL *priv = &privateDicts[0]; 1192*2d1272b8SAndroid Build Coastguard Worker 1193*2d1272b8SAndroid Build Coastguard Worker const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size); 1194*2d1272b8SAndroid Build Coastguard Worker if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail; 1195*2d1272b8SAndroid Build Coastguard Worker num_interp_env_t env (privDictStr); 1196*2d1272b8SAndroid Build Coastguard Worker dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env); 1197*2d1272b8SAndroid Build Coastguard Worker priv->init (); 1198*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!priv_interp.interpret (*priv))) goto fail; 1199*2d1272b8SAndroid Build Coastguard Worker 1200*2d1272b8SAndroid Build Coastguard Worker priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset, sc); 1201*2d1272b8SAndroid Build Coastguard Worker hb_barrier (); 1202*2d1272b8SAndroid Build Coastguard Worker } 1203*2d1272b8SAndroid Build Coastguard Worker 1204*2d1272b8SAndroid Build Coastguard Worker return; 1205*2d1272b8SAndroid Build Coastguard Worker 1206*2d1272b8SAndroid Build Coastguard Worker fail: 1207*2d1272b8SAndroid Build Coastguard Worker _fini (); 1208*2d1272b8SAndroid Build Coastguard Worker } ~accelerator_templ_tOT::cff1::accelerator_templ_t1209*2d1272b8SAndroid Build Coastguard Worker ~accelerator_templ_t () { _fini (); } _finiOT::cff1::accelerator_templ_t1210*2d1272b8SAndroid Build Coastguard Worker void _fini () 1211*2d1272b8SAndroid Build Coastguard Worker { 1212*2d1272b8SAndroid Build Coastguard Worker sc.end_processing (); 1213*2d1272b8SAndroid Build Coastguard Worker topDict.fini (); 1214*2d1272b8SAndroid Build Coastguard Worker fontDicts.fini (); 1215*2d1272b8SAndroid Build Coastguard Worker privateDicts.fini (); 1216*2d1272b8SAndroid Build Coastguard Worker hb_blob_destroy (blob); 1217*2d1272b8SAndroid Build Coastguard Worker blob = nullptr; 1218*2d1272b8SAndroid Build Coastguard Worker } 1219*2d1272b8SAndroid Build Coastguard Worker get_blobOT::cff1::accelerator_templ_t1220*2d1272b8SAndroid Build Coastguard Worker hb_blob_t *get_blob () const { return blob; } 1221*2d1272b8SAndroid Build Coastguard Worker is_validOT::cff1::accelerator_templ_t1222*2d1272b8SAndroid Build Coastguard Worker bool is_valid () const { return blob; } is_CIDOT::cff1::accelerator_templ_t1223*2d1272b8SAndroid Build Coastguard Worker bool is_CID () const { return topDict.is_CID (); } 1224*2d1272b8SAndroid Build Coastguard Worker is_predef_charsetOT::cff1::accelerator_templ_t1225*2d1272b8SAndroid Build Coastguard Worker bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; } 1226*2d1272b8SAndroid Build Coastguard Worker std_code_to_glyphOT::cff1::accelerator_templ_t1227*2d1272b8SAndroid Build Coastguard Worker unsigned int std_code_to_glyph (hb_codepoint_t code) const 1228*2d1272b8SAndroid Build Coastguard Worker { 1229*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t sid = lookup_standard_encoding_for_sid (code); 1230*2d1272b8SAndroid Build Coastguard Worker if (unlikely (sid == CFF_UNDEF_SID)) 1231*2d1272b8SAndroid Build Coastguard Worker return 0; 1232*2d1272b8SAndroid Build Coastguard Worker 1233*2d1272b8SAndroid Build Coastguard Worker if (charset != &Null (Charset)) 1234*2d1272b8SAndroid Build Coastguard Worker return charset->get_glyph (sid, num_glyphs); 1235*2d1272b8SAndroid Build Coastguard Worker else if ((topDict.CharsetOffset == ISOAdobeCharset) 1236*2d1272b8SAndroid Build Coastguard Worker && (code <= 228 /*zcaron*/)) return sid; 1237*2d1272b8SAndroid Build Coastguard Worker return 0; 1238*2d1272b8SAndroid Build Coastguard Worker } 1239*2d1272b8SAndroid Build Coastguard Worker is_predef_encodingOT::cff1::accelerator_templ_t1240*2d1272b8SAndroid Build Coastguard Worker bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; } 1241*2d1272b8SAndroid Build Coastguard Worker glyph_to_codeOT::cff1::accelerator_templ_t1242*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph_to_code (hb_codepoint_t glyph, 1243*2d1272b8SAndroid Build Coastguard Worker code_pair_t *glyph_to_sid_cache = nullptr) const 1244*2d1272b8SAndroid Build Coastguard Worker { 1245*2d1272b8SAndroid Build Coastguard Worker if (encoding != &Null (Encoding)) 1246*2d1272b8SAndroid Build Coastguard Worker return encoding->get_code (glyph); 1247*2d1272b8SAndroid Build Coastguard Worker else 1248*2d1272b8SAndroid Build Coastguard Worker { 1249*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t sid = glyph_to_sid (glyph, glyph_to_sid_cache); 1250*2d1272b8SAndroid Build Coastguard Worker if (sid == 0) return 0; 1251*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t code = 0; 1252*2d1272b8SAndroid Build Coastguard Worker switch (topDict.EncodingOffset) 1253*2d1272b8SAndroid Build Coastguard Worker { 1254*2d1272b8SAndroid Build Coastguard Worker case StandardEncoding: 1255*2d1272b8SAndroid Build Coastguard Worker code = lookup_standard_encoding_for_code (sid); 1256*2d1272b8SAndroid Build Coastguard Worker break; 1257*2d1272b8SAndroid Build Coastguard Worker case ExpertEncoding: 1258*2d1272b8SAndroid Build Coastguard Worker code = lookup_expert_encoding_for_code (sid); 1259*2d1272b8SAndroid Build Coastguard Worker break; 1260*2d1272b8SAndroid Build Coastguard Worker default: 1261*2d1272b8SAndroid Build Coastguard Worker break; 1262*2d1272b8SAndroid Build Coastguard Worker } 1263*2d1272b8SAndroid Build Coastguard Worker return code; 1264*2d1272b8SAndroid Build Coastguard Worker } 1265*2d1272b8SAndroid Build Coastguard Worker } 1266*2d1272b8SAndroid Build Coastguard Worker create_glyph_to_sid_mapOT::cff1::accelerator_templ_t1267*2d1272b8SAndroid Build Coastguard Worker glyph_to_sid_map_t *create_glyph_to_sid_map () const 1268*2d1272b8SAndroid Build Coastguard Worker { 1269*2d1272b8SAndroid Build Coastguard Worker if (charset != &Null (Charset)) 1270*2d1272b8SAndroid Build Coastguard Worker { 1271*2d1272b8SAndroid Build Coastguard Worker auto *mapping = (glyph_to_sid_map_t *) hb_malloc (sizeof (glyph_to_sid_map_t)); 1272*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!mapping)) return nullptr; 1273*2d1272b8SAndroid Build Coastguard Worker mapping = new (mapping) glyph_to_sid_map_t (); 1274*2d1272b8SAndroid Build Coastguard Worker mapping->push (code_pair_t {0, 1}); 1275*2d1272b8SAndroid Build Coastguard Worker charset->collect_glyph_to_sid_map (mapping, num_glyphs); 1276*2d1272b8SAndroid Build Coastguard Worker return mapping; 1277*2d1272b8SAndroid Build Coastguard Worker } 1278*2d1272b8SAndroid Build Coastguard Worker else 1279*2d1272b8SAndroid Build Coastguard Worker return nullptr; 1280*2d1272b8SAndroid Build Coastguard Worker } 1281*2d1272b8SAndroid Build Coastguard Worker glyph_to_sidOT::cff1::accelerator_templ_t1282*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph, 1283*2d1272b8SAndroid Build Coastguard Worker code_pair_t *cache = nullptr) const 1284*2d1272b8SAndroid Build Coastguard Worker { 1285*2d1272b8SAndroid Build Coastguard Worker if (charset != &Null (Charset)) 1286*2d1272b8SAndroid Build Coastguard Worker return charset->get_sid (glyph, num_glyphs, cache); 1287*2d1272b8SAndroid Build Coastguard Worker else 1288*2d1272b8SAndroid Build Coastguard Worker { 1289*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t sid = 0; 1290*2d1272b8SAndroid Build Coastguard Worker switch (topDict.CharsetOffset) 1291*2d1272b8SAndroid Build Coastguard Worker { 1292*2d1272b8SAndroid Build Coastguard Worker case ISOAdobeCharset: 1293*2d1272b8SAndroid Build Coastguard Worker if (glyph <= 228 /*zcaron*/) sid = glyph; 1294*2d1272b8SAndroid Build Coastguard Worker break; 1295*2d1272b8SAndroid Build Coastguard Worker case ExpertCharset: 1296*2d1272b8SAndroid Build Coastguard Worker sid = lookup_expert_charset_for_sid (glyph); 1297*2d1272b8SAndroid Build Coastguard Worker break; 1298*2d1272b8SAndroid Build Coastguard Worker case ExpertSubsetCharset: 1299*2d1272b8SAndroid Build Coastguard Worker sid = lookup_expert_subset_charset_for_sid (glyph); 1300*2d1272b8SAndroid Build Coastguard Worker break; 1301*2d1272b8SAndroid Build Coastguard Worker default: 1302*2d1272b8SAndroid Build Coastguard Worker break; 1303*2d1272b8SAndroid Build Coastguard Worker } 1304*2d1272b8SAndroid Build Coastguard Worker return sid; 1305*2d1272b8SAndroid Build Coastguard Worker } 1306*2d1272b8SAndroid Build Coastguard Worker } 1307*2d1272b8SAndroid Build Coastguard Worker sid_to_glyphOT::cff1::accelerator_templ_t1308*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const 1309*2d1272b8SAndroid Build Coastguard Worker { 1310*2d1272b8SAndroid Build Coastguard Worker if (charset != &Null (Charset)) 1311*2d1272b8SAndroid Build Coastguard Worker return charset->get_glyph (sid, num_glyphs); 1312*2d1272b8SAndroid Build Coastguard Worker else 1313*2d1272b8SAndroid Build Coastguard Worker { 1314*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph = 0; 1315*2d1272b8SAndroid Build Coastguard Worker switch (topDict.CharsetOffset) 1316*2d1272b8SAndroid Build Coastguard Worker { 1317*2d1272b8SAndroid Build Coastguard Worker case ISOAdobeCharset: 1318*2d1272b8SAndroid Build Coastguard Worker if (sid <= 228 /*zcaron*/) glyph = sid; 1319*2d1272b8SAndroid Build Coastguard Worker break; 1320*2d1272b8SAndroid Build Coastguard Worker case ExpertCharset: 1321*2d1272b8SAndroid Build Coastguard Worker glyph = lookup_expert_charset_for_glyph (sid); 1322*2d1272b8SAndroid Build Coastguard Worker break; 1323*2d1272b8SAndroid Build Coastguard Worker case ExpertSubsetCharset: 1324*2d1272b8SAndroid Build Coastguard Worker glyph = lookup_expert_subset_charset_for_glyph (sid); 1325*2d1272b8SAndroid Build Coastguard Worker break; 1326*2d1272b8SAndroid Build Coastguard Worker default: 1327*2d1272b8SAndroid Build Coastguard Worker break; 1328*2d1272b8SAndroid Build Coastguard Worker } 1329*2d1272b8SAndroid Build Coastguard Worker return glyph; 1330*2d1272b8SAndroid Build Coastguard Worker } 1331*2d1272b8SAndroid Build Coastguard Worker } 1332*2d1272b8SAndroid Build Coastguard Worker 1333*2d1272b8SAndroid Build Coastguard Worker protected: 1334*2d1272b8SAndroid Build Coastguard Worker hb_sanitize_context_t sc; 1335*2d1272b8SAndroid Build Coastguard Worker 1336*2d1272b8SAndroid Build Coastguard Worker public: 1337*2d1272b8SAndroid Build Coastguard Worker hb_blob_t *blob = nullptr; 1338*2d1272b8SAndroid Build Coastguard Worker const Encoding *encoding = nullptr; 1339*2d1272b8SAndroid Build Coastguard Worker const Charset *charset = nullptr; 1340*2d1272b8SAndroid Build Coastguard Worker const CFF1NameIndex *nameIndex = nullptr; 1341*2d1272b8SAndroid Build Coastguard Worker const CFF1TopDictIndex *topDictIndex = nullptr; 1342*2d1272b8SAndroid Build Coastguard Worker const CFF1StringIndex *stringIndex = nullptr; 1343*2d1272b8SAndroid Build Coastguard Worker const CFF1Subrs *globalSubrs = nullptr; 1344*2d1272b8SAndroid Build Coastguard Worker const CFF1CharStrings *charStrings = nullptr; 1345*2d1272b8SAndroid Build Coastguard Worker const CFF1FDArray *fdArray = nullptr; 1346*2d1272b8SAndroid Build Coastguard Worker const CFF1FDSelect *fdSelect = nullptr; 1347*2d1272b8SAndroid Build Coastguard Worker unsigned int fdCount = 0; 1348*2d1272b8SAndroid Build Coastguard Worker 1349*2d1272b8SAndroid Build Coastguard Worker cff1_top_dict_values_t topDict; 1350*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<cff1_font_dict_values_t> 1351*2d1272b8SAndroid Build Coastguard Worker fontDicts; 1352*2d1272b8SAndroid Build Coastguard Worker hb_vector_t<PRIVDICTVAL> privateDicts; 1353*2d1272b8SAndroid Build Coastguard Worker 1354*2d1272b8SAndroid Build Coastguard Worker unsigned int num_glyphs = 0; 1355*2d1272b8SAndroid Build Coastguard Worker unsigned int num_charset_entries = 0; 1356*2d1272b8SAndroid Build Coastguard Worker }; 1357*2d1272b8SAndroid Build Coastguard Worker 1358*2d1272b8SAndroid Build Coastguard Worker struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> 1359*2d1272b8SAndroid Build Coastguard Worker { accelerator_tOT::cff1::accelerator_t1360*2d1272b8SAndroid Build Coastguard Worker accelerator_t (hb_face_t *face) : SUPER (face) 1361*2d1272b8SAndroid Build Coastguard Worker { 1362*2d1272b8SAndroid Build Coastguard Worker glyph_names.set_relaxed (nullptr); 1363*2d1272b8SAndroid Build Coastguard Worker 1364*2d1272b8SAndroid Build Coastguard Worker if (!is_valid ()) return; 1365*2d1272b8SAndroid Build Coastguard Worker if (is_CID ()) return; 1366*2d1272b8SAndroid Build Coastguard Worker } ~accelerator_tOT::cff1::accelerator_t1367*2d1272b8SAndroid Build Coastguard Worker ~accelerator_t () 1368*2d1272b8SAndroid Build Coastguard Worker { 1369*2d1272b8SAndroid Build Coastguard Worker hb_sorted_vector_t<gname_t> *names = glyph_names.get_relaxed (); 1370*2d1272b8SAndroid Build Coastguard Worker if (names) 1371*2d1272b8SAndroid Build Coastguard Worker { 1372*2d1272b8SAndroid Build Coastguard Worker names->fini (); 1373*2d1272b8SAndroid Build Coastguard Worker hb_free (names); 1374*2d1272b8SAndroid Build Coastguard Worker } 1375*2d1272b8SAndroid Build Coastguard Worker } 1376*2d1272b8SAndroid Build Coastguard Worker get_glyph_nameOT::cff1::accelerator_t1377*2d1272b8SAndroid Build Coastguard Worker bool get_glyph_name (hb_codepoint_t glyph, 1378*2d1272b8SAndroid Build Coastguard Worker char *buf, unsigned int buf_len) const 1379*2d1272b8SAndroid Build Coastguard Worker { 1380*2d1272b8SAndroid Build Coastguard Worker if (unlikely (glyph >= num_glyphs)) return false; 1381*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!is_valid ())) return false; 1382*2d1272b8SAndroid Build Coastguard Worker if (is_CID()) return false; 1383*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!buf_len)) return true; 1384*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t sid = glyph_to_sid (glyph); 1385*2d1272b8SAndroid Build Coastguard Worker const char *str; 1386*2d1272b8SAndroid Build Coastguard Worker size_t str_len; 1387*2d1272b8SAndroid Build Coastguard Worker if (sid < cff1_std_strings_length) 1388*2d1272b8SAndroid Build Coastguard Worker { 1389*2d1272b8SAndroid Build Coastguard Worker hb_bytes_t byte_str = cff1_std_strings (sid); 1390*2d1272b8SAndroid Build Coastguard Worker str = byte_str.arrayZ; 1391*2d1272b8SAndroid Build Coastguard Worker str_len = byte_str.length; 1392*2d1272b8SAndroid Build Coastguard Worker } 1393*2d1272b8SAndroid Build Coastguard Worker else 1394*2d1272b8SAndroid Build Coastguard Worker { 1395*2d1272b8SAndroid Build Coastguard Worker hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length]; 1396*2d1272b8SAndroid Build Coastguard Worker str = (const char *)ubyte_str.arrayZ; 1397*2d1272b8SAndroid Build Coastguard Worker str_len = ubyte_str.length; 1398*2d1272b8SAndroid Build Coastguard Worker } 1399*2d1272b8SAndroid Build Coastguard Worker if (!str_len) return false; 1400*2d1272b8SAndroid Build Coastguard Worker unsigned int len = hb_min (buf_len - 1, str_len); 1401*2d1272b8SAndroid Build Coastguard Worker strncpy (buf, (const char*)str, len); 1402*2d1272b8SAndroid Build Coastguard Worker buf[len] = '\0'; 1403*2d1272b8SAndroid Build Coastguard Worker return true; 1404*2d1272b8SAndroid Build Coastguard Worker } 1405*2d1272b8SAndroid Build Coastguard Worker get_glyph_from_nameOT::cff1::accelerator_t1406*2d1272b8SAndroid Build Coastguard Worker bool get_glyph_from_name (const char *name, int len, 1407*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t *glyph) const 1408*2d1272b8SAndroid Build Coastguard Worker { 1409*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!is_valid ())) return false; 1410*2d1272b8SAndroid Build Coastguard Worker if (is_CID()) return false; 1411*2d1272b8SAndroid Build Coastguard Worker if (len < 0) len = strlen (name); 1412*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!len)) return false; 1413*2d1272b8SAndroid Build Coastguard Worker 1414*2d1272b8SAndroid Build Coastguard Worker retry: 1415*2d1272b8SAndroid Build Coastguard Worker hb_sorted_vector_t<gname_t> *names = glyph_names.get_acquire (); 1416*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!names)) 1417*2d1272b8SAndroid Build Coastguard Worker { 1418*2d1272b8SAndroid Build Coastguard Worker names = (hb_sorted_vector_t<gname_t> *) hb_calloc (1, sizeof (hb_sorted_vector_t<gname_t>)); 1419*2d1272b8SAndroid Build Coastguard Worker if (likely (names)) 1420*2d1272b8SAndroid Build Coastguard Worker { 1421*2d1272b8SAndroid Build Coastguard Worker names->init (); 1422*2d1272b8SAndroid Build Coastguard Worker /* TODO */ 1423*2d1272b8SAndroid Build Coastguard Worker 1424*2d1272b8SAndroid Build Coastguard Worker /* fill glyph names */ 1425*2d1272b8SAndroid Build Coastguard Worker code_pair_t glyph_to_sid_cache {0, HB_CODEPOINT_INVALID}; 1426*2d1272b8SAndroid Build Coastguard Worker for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++) 1427*2d1272b8SAndroid Build Coastguard Worker { 1428*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t sid = glyph_to_sid (gid, &glyph_to_sid_cache); 1429*2d1272b8SAndroid Build Coastguard Worker gname_t gname; 1430*2d1272b8SAndroid Build Coastguard Worker gname.sid = sid; 1431*2d1272b8SAndroid Build Coastguard Worker if (sid < cff1_std_strings_length) 1432*2d1272b8SAndroid Build Coastguard Worker gname.name = cff1_std_strings (sid); 1433*2d1272b8SAndroid Build Coastguard Worker else 1434*2d1272b8SAndroid Build Coastguard Worker { 1435*2d1272b8SAndroid Build Coastguard Worker hb_ubytes_t ustr = (*stringIndex)[sid - cff1_std_strings_length]; 1436*2d1272b8SAndroid Build Coastguard Worker gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length); 1437*2d1272b8SAndroid Build Coastguard Worker } 1438*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!gname.name.arrayZ)) 1439*2d1272b8SAndroid Build Coastguard Worker gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */ 1440*2d1272b8SAndroid Build Coastguard Worker names->push (gname); 1441*2d1272b8SAndroid Build Coastguard Worker } 1442*2d1272b8SAndroid Build Coastguard Worker names->qsort (); 1443*2d1272b8SAndroid Build Coastguard Worker } 1444*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!glyph_names.cmpexch (nullptr, names))) 1445*2d1272b8SAndroid Build Coastguard Worker { 1446*2d1272b8SAndroid Build Coastguard Worker if (names) 1447*2d1272b8SAndroid Build Coastguard Worker { 1448*2d1272b8SAndroid Build Coastguard Worker names->fini (); 1449*2d1272b8SAndroid Build Coastguard Worker hb_free (names); 1450*2d1272b8SAndroid Build Coastguard Worker } 1451*2d1272b8SAndroid Build Coastguard Worker goto retry; 1452*2d1272b8SAndroid Build Coastguard Worker } 1453*2d1272b8SAndroid Build Coastguard Worker } 1454*2d1272b8SAndroid Build Coastguard Worker 1455*2d1272b8SAndroid Build Coastguard Worker gname_t key = { hb_bytes_t (name, len), 0 }; 1456*2d1272b8SAndroid Build Coastguard Worker const gname_t *gname = names ? names->bsearch (key) : nullptr; 1457*2d1272b8SAndroid Build Coastguard Worker if (!gname) return false; 1458*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t gid = sid_to_glyph (gname->sid); 1459*2d1272b8SAndroid Build Coastguard Worker if (!gid && gname->sid) return false; 1460*2d1272b8SAndroid Build Coastguard Worker *glyph = gid; 1461*2d1272b8SAndroid Build Coastguard Worker return true; 1462*2d1272b8SAndroid Build Coastguard Worker } 1463*2d1272b8SAndroid Build Coastguard Worker 1464*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const; 1465*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const; 1466*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const; 1467*2d1272b8SAndroid Build Coastguard Worker 1468*2d1272b8SAndroid Build Coastguard Worker private: 1469*2d1272b8SAndroid Build Coastguard Worker struct gname_t 1470*2d1272b8SAndroid Build Coastguard Worker { 1471*2d1272b8SAndroid Build Coastguard Worker hb_bytes_t name; 1472*2d1272b8SAndroid Build Coastguard Worker uint16_t sid; 1473*2d1272b8SAndroid Build Coastguard Worker cmpOT::cff1::accelerator_t::gname_t1474*2d1272b8SAndroid Build Coastguard Worker static int cmp (const void *a_, const void *b_) 1475*2d1272b8SAndroid Build Coastguard Worker { 1476*2d1272b8SAndroid Build Coastguard Worker const gname_t *a = (const gname_t *)a_; 1477*2d1272b8SAndroid Build Coastguard Worker const gname_t *b = (const gname_t *)b_; 1478*2d1272b8SAndroid Build Coastguard Worker unsigned minlen = hb_min (a->name.length, b->name.length); 1479*2d1272b8SAndroid Build Coastguard Worker int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen); 1480*2d1272b8SAndroid Build Coastguard Worker if (ret) return ret; 1481*2d1272b8SAndroid Build Coastguard Worker return a->name.length - b->name.length; 1482*2d1272b8SAndroid Build Coastguard Worker } 1483*2d1272b8SAndroid Build Coastguard Worker cmpOT::cff1::accelerator_t::gname_t1484*2d1272b8SAndroid Build Coastguard Worker int cmp (const gname_t &a) const { return cmp (&a, this); } 1485*2d1272b8SAndroid Build Coastguard Worker }; 1486*2d1272b8SAndroid Build Coastguard Worker 1487*2d1272b8SAndroid Build Coastguard Worker mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names; 1488*2d1272b8SAndroid Build Coastguard Worker 1489*2d1272b8SAndroid Build Coastguard Worker typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER; 1490*2d1272b8SAndroid Build Coastguard Worker }; 1491*2d1272b8SAndroid Build Coastguard Worker 1492*2d1272b8SAndroid Build Coastguard Worker struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> 1493*2d1272b8SAndroid Build Coastguard Worker { accelerator_subset_tOT::cff1::accelerator_subset_t1494*2d1272b8SAndroid Build Coastguard Worker accelerator_subset_t (hb_face_t *face) : SUPER (face) {} ~accelerator_subset_tOT::cff1::accelerator_subset_t1495*2d1272b8SAndroid Build Coastguard Worker ~accelerator_subset_t () 1496*2d1272b8SAndroid Build Coastguard Worker { 1497*2d1272b8SAndroid Build Coastguard Worker if (cff_accelerator) 1498*2d1272b8SAndroid Build Coastguard Worker cff_subset_accelerator_t::destroy (cff_accelerator); 1499*2d1272b8SAndroid Build Coastguard Worker } 1500*2d1272b8SAndroid Build Coastguard Worker 1501*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL bool subset (hb_subset_context_t *c) const; 1502*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL bool serialize (hb_serialize_context_t *c, 1503*2d1272b8SAndroid Build Coastguard Worker struct cff1_subset_plan &plan) const; 1504*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const; 1505*2d1272b8SAndroid Build Coastguard Worker 1506*2d1272b8SAndroid Build Coastguard Worker mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr; 1507*2d1272b8SAndroid Build Coastguard Worker 1508*2d1272b8SAndroid Build Coastguard Worker typedef accelerator_templ_t<cff1_private_dict_opset_subset_t, cff1_private_dict_values_subset_t> SUPER; 1509*2d1272b8SAndroid Build Coastguard Worker }; 1510*2d1272b8SAndroid Build Coastguard Worker 1511*2d1272b8SAndroid Build Coastguard Worker protected: 1512*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid); 1513*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid); 1514*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph); 1515*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph); 1516*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid); 1517*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid); 1518*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code); 1519*2d1272b8SAndroid Build Coastguard Worker 1520*2d1272b8SAndroid Build Coastguard Worker public: 1521*2d1272b8SAndroid Build Coastguard Worker FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */ 1522*2d1272b8SAndroid Build Coastguard Worker NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */ 1523*2d1272b8SAndroid Build Coastguard Worker HBUINT8 offSize; /* offset size (unused?) */ 1524*2d1272b8SAndroid Build Coastguard Worker 1525*2d1272b8SAndroid Build Coastguard Worker public: 1526*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (4); 1527*2d1272b8SAndroid Build Coastguard Worker }; 1528*2d1272b8SAndroid Build Coastguard Worker 1529*2d1272b8SAndroid Build Coastguard Worker struct cff1_accelerator_t : cff1::accelerator_t { cff1_accelerator_tOT::cff1_accelerator_t1530*2d1272b8SAndroid Build Coastguard Worker cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {} 1531*2d1272b8SAndroid Build Coastguard Worker }; 1532*2d1272b8SAndroid Build Coastguard Worker 1533*2d1272b8SAndroid Build Coastguard Worker struct cff1_subset_accelerator_t : cff1::accelerator_subset_t { cff1_subset_accelerator_tOT::cff1_subset_accelerator_t1534*2d1272b8SAndroid Build Coastguard Worker cff1_subset_accelerator_t (hb_face_t *face) : cff1::accelerator_subset_t (face) {} 1535*2d1272b8SAndroid Build Coastguard Worker }; 1536*2d1272b8SAndroid Build Coastguard Worker 1537*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */ 1538*2d1272b8SAndroid Build Coastguard Worker 1539*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_OT_CFF1_TABLE_HH */ 1540