1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "core/fpdfapi/font/cfx_cttgsubtable.h" 8 9 #include <utility> 10 11 #include "core/fxge/fx_freetype.h" 12 #include "third_party/base/ptr_util.h" 13 #include "third_party/base/stl_util.h" 14 15 CFX_CTTGSUBTable::CFX_CTTGSUBTable() : m_bFeautureMapLoad(false) {} 16 17 CFX_CTTGSUBTable::~CFX_CTTGSUBTable() {} 18 19 bool CFX_CTTGSUBTable::LoadGSUBTable(FT_Bytes gsub) { 20 if ((gsub[0] << 24u | gsub[1] << 16u | gsub[2] << 8u | gsub[3]) != 0x00010000) 21 return false; 22 23 return Parse(&gsub[gsub[4] << 8 | gsub[5]], &gsub[gsub[6] << 8 | gsub[7]], 24 &gsub[gsub[8] << 8 | gsub[9]]); 25 } 26 27 bool CFX_CTTGSUBTable::GetVerticalGlyph(uint32_t glyphnum, 28 uint32_t* vglyphnum) { 29 uint32_t tag[] = { 30 (uint8_t)'v' << 24 | (uint8_t)'r' << 16 | (uint8_t)'t' << 8 | 31 (uint8_t)'2', 32 (uint8_t)'v' << 24 | (uint8_t)'e' << 16 | (uint8_t)'r' << 8 | 33 (uint8_t)'t', 34 }; 35 if (!m_bFeautureMapLoad) { 36 for (const TScriptRecord& script : ScriptList) { 37 for (const auto& record : script.LangSysRecords) { 38 for (const auto& index : record.FeatureIndices) { 39 if (FeatureList[index].FeatureTag == tag[0] || 40 FeatureList[index].FeatureTag == tag[1]) { 41 m_featureSet.insert(index); 42 } 43 } 44 } 45 } 46 if (m_featureSet.empty()) { 47 int i = 0; 48 for (const TFeatureRecord& feature : FeatureList) { 49 if (feature.FeatureTag == tag[0] || feature.FeatureTag == tag[1]) 50 m_featureSet.insert(i); 51 ++i; 52 } 53 } 54 m_bFeautureMapLoad = true; 55 } 56 for (const auto& item : m_featureSet) { 57 if (GetVerticalGlyphSub(glyphnum, vglyphnum, &FeatureList[item])) { 58 return true; 59 } 60 } 61 return false; 62 } 63 64 bool CFX_CTTGSUBTable::GetVerticalGlyphSub(uint32_t glyphnum, 65 uint32_t* vglyphnum, 66 TFeatureRecord* Feature) { 67 for (int index : Feature->LookupListIndices) { 68 if (!pdfium::IndexInBounds(LookupList, index)) 69 continue; 70 if (LookupList[index].LookupType == 1 && 71 GetVerticalGlyphSub2(glyphnum, vglyphnum, &LookupList[index])) { 72 return true; 73 } 74 } 75 return false; 76 } 77 78 bool CFX_CTTGSUBTable::GetVerticalGlyphSub2(uint32_t glyphnum, 79 uint32_t* vglyphnum, 80 TLookup* Lookup) { 81 for (const auto& subTable : Lookup->SubTables) { 82 switch (subTable->SubstFormat) { 83 case 1: { 84 auto* tbl1 = static_cast<TSubTable1*>(subTable.get()); 85 if (GetCoverageIndex(tbl1->Coverage.get(), glyphnum) >= 0) { 86 *vglyphnum = glyphnum + tbl1->DeltaGlyphID; 87 return true; 88 } 89 break; 90 } 91 case 2: { 92 auto* tbl2 = static_cast<TSubTable2*>(subTable.get()); 93 int index = GetCoverageIndex(tbl2->Coverage.get(), glyphnum); 94 if (pdfium::IndexInBounds(tbl2->Substitutes, index)) { 95 *vglyphnum = tbl2->Substitutes[index]; 96 return true; 97 } 98 break; 99 } 100 } 101 } 102 return false; 103 } 104 105 int CFX_CTTGSUBTable::GetCoverageIndex(TCoverageFormatBase* Coverage, 106 uint32_t g) const { 107 if (!Coverage) 108 return -1; 109 110 switch (Coverage->CoverageFormat) { 111 case 1: { 112 int i = 0; 113 TCoverageFormat1* c1 = static_cast<TCoverageFormat1*>(Coverage); 114 for (const auto& glyph : c1->GlyphArray) { 115 if (static_cast<uint32_t>(glyph) == g) 116 return i; 117 ++i; 118 } 119 return -1; 120 } 121 case 2: { 122 TCoverageFormat2* c2 = static_cast<TCoverageFormat2*>(Coverage); 123 for (const auto& rangeRec : c2->RangeRecords) { 124 uint32_t s = rangeRec.Start; 125 uint32_t e = rangeRec.End; 126 uint32_t si = rangeRec.StartCoverageIndex; 127 if (s <= g && g <= e) 128 return si + g - s; 129 } 130 return -1; 131 } 132 } 133 return -1; 134 } 135 136 uint8_t CFX_CTTGSUBTable::GetUInt8(FT_Bytes& p) const { 137 uint8_t ret = p[0]; 138 p += 1; 139 return ret; 140 } 141 142 int16_t CFX_CTTGSUBTable::GetInt16(FT_Bytes& p) const { 143 uint16_t ret = p[0] << 8 | p[1]; 144 p += 2; 145 return *(int16_t*)&ret; 146 } 147 148 uint16_t CFX_CTTGSUBTable::GetUInt16(FT_Bytes& p) const { 149 uint16_t ret = p[0] << 8 | p[1]; 150 p += 2; 151 return ret; 152 } 153 154 int32_t CFX_CTTGSUBTable::GetInt32(FT_Bytes& p) const { 155 uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 156 p += 4; 157 return *(int32_t*)&ret; 158 } 159 160 uint32_t CFX_CTTGSUBTable::GetUInt32(FT_Bytes& p) const { 161 uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 162 p += 4; 163 return ret; 164 } 165 166 bool CFX_CTTGSUBTable::Parse(FT_Bytes scriptlist, 167 FT_Bytes featurelist, 168 FT_Bytes lookuplist) { 169 ParseScriptList(scriptlist); 170 ParseFeatureList(featurelist); 171 ParseLookupList(lookuplist); 172 return true; 173 } 174 175 void CFX_CTTGSUBTable::ParseScriptList(FT_Bytes raw) { 176 FT_Bytes sp = raw; 177 ScriptList = std::vector<TScriptRecord>(GetUInt16(sp)); 178 for (auto& scriptRec : ScriptList) { 179 scriptRec.ScriptTag = GetUInt32(sp); 180 ParseScript(&raw[GetUInt16(sp)], &scriptRec); 181 } 182 } 183 184 void CFX_CTTGSUBTable::ParseScript(FT_Bytes raw, TScriptRecord* rec) { 185 FT_Bytes sp = raw; 186 rec->DefaultLangSys = GetUInt16(sp); 187 rec->LangSysRecords = std::vector<TLangSysRecord>(GetUInt16(sp)); 188 for (auto& sysRecord : rec->LangSysRecords) { 189 sysRecord.LangSysTag = GetUInt32(sp); 190 ParseLangSys(&raw[GetUInt16(sp)], &sysRecord); 191 } 192 } 193 194 void CFX_CTTGSUBTable::ParseLangSys(FT_Bytes raw, TLangSysRecord* rec) { 195 FT_Bytes sp = raw; 196 rec->LookupOrder = GetUInt16(sp); 197 rec->ReqFeatureIndex = GetUInt16(sp); 198 rec->FeatureIndices = std::vector<uint16_t>(GetUInt16(sp)); 199 for (auto& element : rec->FeatureIndices) 200 element = GetUInt16(sp); 201 } 202 203 void CFX_CTTGSUBTable::ParseFeatureList(FT_Bytes raw) { 204 FT_Bytes sp = raw; 205 FeatureList = std::vector<TFeatureRecord>(GetUInt16(sp)); 206 for (auto& featureRec : FeatureList) { 207 featureRec.FeatureTag = GetUInt32(sp); 208 ParseFeature(&raw[GetUInt16(sp)], &featureRec); 209 } 210 } 211 212 void CFX_CTTGSUBTable::ParseFeature(FT_Bytes raw, TFeatureRecord* rec) { 213 FT_Bytes sp = raw; 214 rec->FeatureParams = GetUInt16(sp); 215 rec->LookupListIndices = std::vector<uint16_t>(GetUInt16(sp)); 216 for (auto& listIndex : rec->LookupListIndices) 217 listIndex = GetUInt16(sp); 218 } 219 220 void CFX_CTTGSUBTable::ParseLookupList(FT_Bytes raw) { 221 FT_Bytes sp = raw; 222 LookupList = std::vector<TLookup>(GetUInt16(sp)); 223 for (auto& lookup : LookupList) 224 ParseLookup(&raw[GetUInt16(sp)], &lookup); 225 } 226 227 void CFX_CTTGSUBTable::ParseLookup(FT_Bytes raw, TLookup* rec) { 228 FT_Bytes sp = raw; 229 rec->LookupType = GetUInt16(sp); 230 rec->LookupFlag = GetUInt16(sp); 231 rec->SubTables = std::vector<std::unique_ptr<TSubTableBase>>(GetUInt16(sp)); 232 if (rec->LookupType != 1) 233 return; 234 235 for (auto& subTable : rec->SubTables) 236 ParseSingleSubst(&raw[GetUInt16(sp)], &subTable); 237 } 238 239 std::unique_ptr<CFX_CTTGSUBTable::TCoverageFormatBase> 240 CFX_CTTGSUBTable::ParseCoverage(FT_Bytes raw) { 241 FT_Bytes sp = raw; 242 uint16_t format = GetUInt16(sp); 243 if (format == 1) { 244 auto rec = pdfium::MakeUnique<TCoverageFormat1>(); 245 ParseCoverageFormat1(raw, rec.get()); 246 return std::move(rec); 247 } 248 if (format == 2) { 249 auto rec = pdfium::MakeUnique<TCoverageFormat2>(); 250 ParseCoverageFormat2(raw, rec.get()); 251 return std::move(rec); 252 } 253 return nullptr; 254 } 255 256 void CFX_CTTGSUBTable::ParseCoverageFormat1(FT_Bytes raw, 257 TCoverageFormat1* rec) { 258 FT_Bytes sp = raw; 259 (void)GetUInt16(sp); 260 rec->GlyphArray = std::vector<uint16_t>(GetUInt16(sp)); 261 for (auto& glyph : rec->GlyphArray) 262 glyph = GetUInt16(sp); 263 } 264 265 void CFX_CTTGSUBTable::ParseCoverageFormat2(FT_Bytes raw, 266 TCoverageFormat2* rec) { 267 FT_Bytes sp = raw; 268 (void)GetUInt16(sp); 269 rec->RangeRecords = std::vector<TRangeRecord>(GetUInt16(sp)); 270 for (auto& rangeRec : rec->RangeRecords) { 271 rangeRec.Start = GetUInt16(sp); 272 rangeRec.End = GetUInt16(sp); 273 rangeRec.StartCoverageIndex = GetUInt16(sp); 274 } 275 } 276 277 void CFX_CTTGSUBTable::ParseSingleSubst(FT_Bytes raw, 278 std::unique_ptr<TSubTableBase>* rec) { 279 FT_Bytes sp = raw; 280 uint16_t Format = GetUInt16(sp); 281 switch (Format) { 282 case 1: 283 *rec = pdfium::MakeUnique<TSubTable1>(); 284 ParseSingleSubstFormat1(raw, static_cast<TSubTable1*>(rec->get())); 285 break; 286 case 2: 287 *rec = pdfium::MakeUnique<TSubTable2>(); 288 ParseSingleSubstFormat2(raw, static_cast<TSubTable2*>(rec->get())); 289 break; 290 } 291 } 292 293 void CFX_CTTGSUBTable::ParseSingleSubstFormat1(FT_Bytes raw, TSubTable1* rec) { 294 FT_Bytes sp = raw; 295 GetUInt16(sp); 296 uint16_t offset = GetUInt16(sp); 297 rec->Coverage = ParseCoverage(&raw[offset]); 298 rec->DeltaGlyphID = GetInt16(sp); 299 } 300 301 void CFX_CTTGSUBTable::ParseSingleSubstFormat2(FT_Bytes raw, TSubTable2* rec) { 302 FT_Bytes sp = raw; 303 (void)GetUInt16(sp); 304 uint16_t offset = GetUInt16(sp); 305 rec->Coverage = ParseCoverage(&raw[offset]); 306 rec->Substitutes = std::vector<uint16_t>(GetUInt16(sp)); 307 for (auto& substitute : rec->Substitutes) 308 substitute = GetUInt16(sp); 309 } 310 311 CFX_CTTGSUBTable::TLangSysRecord::TLangSysRecord() 312 : LangSysTag(0), LookupOrder(0), ReqFeatureIndex(0) {} 313 314 CFX_CTTGSUBTable::TLangSysRecord::~TLangSysRecord() {} 315 316 CFX_CTTGSUBTable::TScriptRecord::TScriptRecord() 317 : ScriptTag(0), DefaultLangSys(0) {} 318 319 CFX_CTTGSUBTable::TScriptRecord::~TScriptRecord() {} 320 321 CFX_CTTGSUBTable::TFeatureRecord::TFeatureRecord() 322 : FeatureTag(0), FeatureParams(0) {} 323 324 CFX_CTTGSUBTable::TFeatureRecord::~TFeatureRecord() {} 325 326 CFX_CTTGSUBTable::TRangeRecord::TRangeRecord() 327 : Start(0), End(0), StartCoverageIndex(0) {} 328 329 CFX_CTTGSUBTable::TCoverageFormat1::TCoverageFormat1() { 330 CoverageFormat = 1; 331 } 332 333 CFX_CTTGSUBTable::TCoverageFormat1::~TCoverageFormat1() {} 334 335 CFX_CTTGSUBTable::TCoverageFormat2::TCoverageFormat2() { 336 CoverageFormat = 2; 337 } 338 339 CFX_CTTGSUBTable::TCoverageFormat2::~TCoverageFormat2() {} 340 341 CFX_CTTGSUBTable::TSubTableBase::TSubTableBase() {} 342 343 CFX_CTTGSUBTable::TSubTableBase::~TSubTableBase() {} 344 345 CFX_CTTGSUBTable::TSubTable1::TSubTable1() { 346 SubstFormat = 1; 347 } 348 349 CFX_CTTGSUBTable::TSubTable1::~TSubTable1() {} 350 351 CFX_CTTGSUBTable::TSubTable2::TSubTable2() { 352 SubstFormat = 2; 353 } 354 355 CFX_CTTGSUBTable::TSubTable2::~TSubTable2() {} 356 357 CFX_CTTGSUBTable::TLookup::TLookup() : LookupType(0), LookupFlag(0) {} 358 359 CFX_CTTGSUBTable::TLookup::~TLookup() {} 360