ttgsubtable.cpp revision 5ae9d0c6fd838a2967cca72aa5751b51dadc2769
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/ttgsubtable.h" 8 9#include "core/fxge/fx_freetype.h" 10#include "third_party/base/ptr_util.h" 11#include "third_party/base/stl_util.h" 12 13CFX_GlyphMap::CFX_GlyphMap() {} 14 15CFX_GlyphMap::~CFX_GlyphMap() {} 16 17extern "C" { 18static int _CompareInt(const void* p1, const void* p2) { 19 return (*(uint32_t*)p1) - (*(uint32_t*)p2); 20} 21}; 22 23struct _IntPair { 24 int32_t key; 25 int32_t value; 26}; 27 28void CFX_GlyphMap::SetAt(int key, int value) { 29 uint32_t count = m_Buffer.GetSize() / sizeof(_IntPair); 30 _IntPair* buf = (_IntPair*)m_Buffer.GetBuffer(); 31 _IntPair pair = {key, value}; 32 if (count == 0 || key > buf[count - 1].key) { 33 m_Buffer.AppendBlock(&pair, sizeof(_IntPair)); 34 return; 35 } 36 int low = 0, high = count - 1; 37 while (low <= high) { 38 int mid = (low + high) / 2; 39 if (buf[mid].key < key) { 40 low = mid + 1; 41 } else if (buf[mid].key > key) { 42 high = mid - 1; 43 } else { 44 buf[mid].value = value; 45 return; 46 } 47 } 48 m_Buffer.InsertBlock(low * sizeof(_IntPair), &pair, sizeof(_IntPair)); 49} 50 51bool CFX_GlyphMap::Lookup(int key, int& value) { 52 void* pResult = FXSYS_bsearch(&key, m_Buffer.GetBuffer(), 53 m_Buffer.GetSize() / sizeof(_IntPair), 54 sizeof(_IntPair), _CompareInt); 55 if (!pResult) { 56 return false; 57 } 58 value = ((uint32_t*)pResult)[1]; 59 return true; 60} 61 62CFX_CTTGSUBTable::CFX_CTTGSUBTable() 63 : m_bFeautureMapLoad(false), loaded(false) {} 64 65CFX_CTTGSUBTable::CFX_CTTGSUBTable(FT_Bytes gsub) 66 : m_bFeautureMapLoad(false), loaded(false) { 67 LoadGSUBTable(gsub); 68} 69 70CFX_CTTGSUBTable::~CFX_CTTGSUBTable() {} 71 72bool CFX_CTTGSUBTable::IsOk() const { 73 return loaded; 74} 75 76bool CFX_CTTGSUBTable::LoadGSUBTable(FT_Bytes gsub) { 77 header.Version = gsub[0] << 24 | gsub[1] << 16 | gsub[2] << 8 | gsub[3]; 78 if (header.Version != 0x00010000) { 79 return false; 80 } 81 header.ScriptList = gsub[4] << 8 | gsub[5]; 82 header.FeatureList = gsub[6] << 8 | gsub[7]; 83 header.LookupList = gsub[8] << 8 | gsub[9]; 84 return Parse(&gsub[header.ScriptList], &gsub[header.FeatureList], 85 &gsub[header.LookupList]); 86} 87 88bool CFX_CTTGSUBTable::GetVerticalGlyph(uint32_t glyphnum, 89 uint32_t* vglyphnum) { 90 uint32_t tag[] = { 91 (uint8_t)'v' << 24 | (uint8_t)'r' << 16 | (uint8_t)'t' << 8 | 92 (uint8_t)'2', 93 (uint8_t)'v' << 24 | (uint8_t)'e' << 16 | (uint8_t)'r' << 8 | 94 (uint8_t)'t', 95 }; 96 if (!m_bFeautureMapLoad) { 97 for (const auto& script : ScriptList.ScriptRecords) { 98 for (const auto& record : script.Script.LangSysRecords) { 99 for (const auto& index : record.LangSys.FeatureIndices) { 100 if (FeatureList.FeatureRecords[index].FeatureTag == tag[0] || 101 FeatureList.FeatureRecords[index].FeatureTag == tag[1]) { 102 m_featureSet.insert(index); 103 } 104 } 105 } 106 } 107 if (m_featureSet.empty()) { 108 int i = 0; 109 for (const auto& feature : FeatureList.FeatureRecords) { 110 if (feature.FeatureTag == tag[0] || feature.FeatureTag == tag[1]) 111 m_featureSet.insert(i); 112 ++i; 113 } 114 } 115 m_bFeautureMapLoad = true; 116 } 117 for (const auto& item : m_featureSet) { 118 if (GetVerticalGlyphSub(glyphnum, vglyphnum, 119 &FeatureList.FeatureRecords[item].Feature)) { 120 return true; 121 } 122 } 123 return false; 124} 125 126bool CFX_CTTGSUBTable::GetVerticalGlyphSub(uint32_t glyphnum, 127 uint32_t* vglyphnum, 128 TFeature* Feature) { 129 for (int index : Feature->LookupListIndices) { 130 if (index < 0 || index >= pdfium::CollectionSize<int>(LookupList.Lookups)) 131 continue; 132 133 if (LookupList.Lookups[index].LookupType == 1 && 134 GetVerticalGlyphSub2(glyphnum, vglyphnum, &LookupList.Lookups[index])) { 135 return true; 136 } 137 } 138 return false; 139} 140 141bool CFX_CTTGSUBTable::GetVerticalGlyphSub2(uint32_t glyphnum, 142 uint32_t* vglyphnum, 143 TLookup* Lookup) { 144 for (const auto& subTable : Lookup->SubTables) { 145 switch (subTable->SubstFormat) { 146 case 1: { 147 auto tbl1 = static_cast<TSingleSubstFormat1*>(subTable.get()); 148 if (GetCoverageIndex(tbl1->Coverage.get(), glyphnum) >= 0) { 149 *vglyphnum = glyphnum + tbl1->DeltaGlyphID; 150 return true; 151 } 152 break; 153 } 154 case 2: { 155 auto tbl2 = static_cast<TSingleSubstFormat2*>(subTable.get()); 156 int index = GetCoverageIndex(tbl2->Coverage.get(), glyphnum); 157 if (index >= 0 && 158 index < pdfium::CollectionSize<int>(tbl2->Substitutes)) { 159 *vglyphnum = tbl2->Substitutes[index]; 160 return true; 161 } 162 break; 163 } 164 } 165 } 166 return false; 167} 168 169int CFX_CTTGSUBTable::GetCoverageIndex(TCoverageFormatBase* Coverage, 170 uint32_t g) const { 171 if (!Coverage) 172 return -1; 173 174 switch (Coverage->CoverageFormat) { 175 case 1: { 176 int i = 0; 177 TCoverageFormat1* c1 = (TCoverageFormat1*)Coverage; 178 for (const auto& glyph : c1->GlyphArray) { 179 if (static_cast<uint32_t>(glyph) == g) 180 return i; 181 ++i; 182 } 183 return -1; 184 } 185 case 2: { 186 TCoverageFormat2* c2 = (TCoverageFormat2*)Coverage; 187 for (const auto& rangeRec : c2->RangeRecords) { 188 uint32_t s = rangeRec.Start; 189 uint32_t e = rangeRec.End; 190 uint32_t si = rangeRec.StartCoverageIndex; 191 if (s <= g && g <= e) 192 return si + g - s; 193 } 194 return -1; 195 } 196 } 197 return -1; 198} 199 200uint8_t CFX_CTTGSUBTable::GetUInt8(FT_Bytes& p) const { 201 uint8_t ret = p[0]; 202 p += 1; 203 return ret; 204} 205 206int16_t CFX_CTTGSUBTable::GetInt16(FT_Bytes& p) const { 207 uint16_t ret = p[0] << 8 | p[1]; 208 p += 2; 209 return *(int16_t*)&ret; 210} 211 212uint16_t CFX_CTTGSUBTable::GetUInt16(FT_Bytes& p) const { 213 uint16_t ret = p[0] << 8 | p[1]; 214 p += 2; 215 return ret; 216} 217 218int32_t CFX_CTTGSUBTable::GetInt32(FT_Bytes& p) const { 219 uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 220 p += 4; 221 return *(int32_t*)&ret; 222} 223 224uint32_t CFX_CTTGSUBTable::GetUInt32(FT_Bytes& p) const { 225 uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 226 p += 4; 227 return ret; 228} 229 230bool CFX_CTTGSUBTable::Parse(FT_Bytes scriptlist, 231 FT_Bytes featurelist, 232 FT_Bytes lookuplist) { 233 ParseScriptList(scriptlist, &ScriptList); 234 ParseFeatureList(featurelist, &FeatureList); 235 ParseLookupList(lookuplist, &LookupList); 236 return true; 237} 238 239void CFX_CTTGSUBTable::ParseScriptList(FT_Bytes raw, TScriptList* rec) { 240 FT_Bytes sp = raw; 241 rec->ScriptRecords = std::vector<TScriptRecord>(GetUInt16(sp)); 242 for (auto& scriptRec : rec->ScriptRecords) { 243 scriptRec.ScriptTag = GetUInt32(sp); 244 ParseScript(&raw[GetUInt16(sp)], &scriptRec.Script); 245 } 246} 247 248void CFX_CTTGSUBTable::ParseScript(FT_Bytes raw, TScript* rec) { 249 FT_Bytes sp = raw; 250 rec->DefaultLangSys = GetUInt16(sp); 251 rec->LangSysRecords = std::vector<TLangSysRecord>(GetUInt16(sp)); 252 for (auto& sysRecord : rec->LangSysRecords) { 253 sysRecord.LangSysTag = GetUInt32(sp); 254 ParseLangSys(&raw[GetUInt16(sp)], &sysRecord.LangSys); 255 } 256} 257 258void CFX_CTTGSUBTable::ParseLangSys(FT_Bytes raw, TLangSys* rec) { 259 FT_Bytes sp = raw; 260 rec->LookupOrder = GetUInt16(sp); 261 rec->ReqFeatureIndex = GetUInt16(sp); 262 rec->FeatureIndices = std::vector<uint16_t>(GetUInt16(sp)); 263 for (auto& element : rec->FeatureIndices) 264 element = GetUInt16(sp); 265} 266 267void CFX_CTTGSUBTable::ParseFeatureList(FT_Bytes raw, TFeatureList* rec) { 268 FT_Bytes sp = raw; 269 rec->FeatureRecords = std::vector<TFeatureRecord>(GetUInt16(sp)); 270 for (auto& featureRec : rec->FeatureRecords) { 271 featureRec.FeatureTag = GetUInt32(sp); 272 ParseFeature(&raw[GetUInt16(sp)], &featureRec.Feature); 273 } 274} 275 276void CFX_CTTGSUBTable::ParseFeature(FT_Bytes raw, TFeature* rec) { 277 FT_Bytes sp = raw; 278 rec->FeatureParams = GetUInt16(sp); 279 rec->LookupListIndices = std::vector<uint16_t>(GetUInt16(sp)); 280 for (auto& listIndex : rec->LookupListIndices) 281 listIndex = GetUInt16(sp); 282} 283 284void CFX_CTTGSUBTable::ParseLookupList(FT_Bytes raw, TLookupList* rec) { 285 FT_Bytes sp = raw; 286 rec->Lookups = std::vector<TLookup>(GetUInt16(sp)); 287 for (auto& lookup : rec->Lookups) 288 ParseLookup(&raw[GetUInt16(sp)], &lookup); 289} 290 291void CFX_CTTGSUBTable::ParseLookup(FT_Bytes raw, TLookup* rec) { 292 FT_Bytes sp = raw; 293 rec->LookupType = GetUInt16(sp); 294 rec->LookupFlag = GetUInt16(sp); 295 rec->SubTables = std::vector<std::unique_ptr<TSubTableBase>>(GetUInt16(sp)); 296 if (rec->LookupType != 1) 297 return; 298 299 for (auto& subTable : rec->SubTables) 300 ParseSingleSubst(&raw[GetUInt16(sp)], &subTable); 301} 302 303CFX_CTTGSUBTable::TCoverageFormatBase* CFX_CTTGSUBTable::ParseCoverage( 304 FT_Bytes raw) { 305 FT_Bytes sp = raw; 306 uint16_t format = GetUInt16(sp); 307 TCoverageFormatBase* rec = nullptr; 308 if (format == 1) { 309 rec = new TCoverageFormat1(); 310 ParseCoverageFormat1(raw, static_cast<TCoverageFormat1*>(rec)); 311 } else if (format == 2) { 312 rec = new TCoverageFormat2(); 313 ParseCoverageFormat2(raw, static_cast<TCoverageFormat2*>(rec)); 314 } 315 return rec; 316} 317 318void CFX_CTTGSUBTable::ParseCoverageFormat1(FT_Bytes raw, 319 TCoverageFormat1* rec) { 320 FT_Bytes sp = raw; 321 (void)GetUInt16(sp); 322 rec->GlyphArray = std::vector<uint16_t>(GetUInt16(sp)); 323 for (auto& glyph : rec->GlyphArray) 324 glyph = GetUInt16(sp); 325} 326 327void CFX_CTTGSUBTable::ParseCoverageFormat2(FT_Bytes raw, 328 TCoverageFormat2* rec) { 329 FT_Bytes sp = raw; 330 (void)GetUInt16(sp); 331 rec->RangeRecords = std::vector<TRangeRecord>(GetUInt16(sp)); 332 for (auto& rangeRec : rec->RangeRecords) { 333 rangeRec.Start = GetUInt16(sp); 334 rangeRec.End = GetUInt16(sp); 335 rangeRec.StartCoverageIndex = GetUInt16(sp); 336 } 337} 338 339void CFX_CTTGSUBTable::ParseSingleSubst(FT_Bytes raw, 340 std::unique_ptr<TSubTableBase>* rec) { 341 FT_Bytes sp = raw; 342 uint16_t Format = GetUInt16(sp); 343 switch (Format) { 344 case 1: 345 *rec = pdfium::MakeUnique<TSingleSubstFormat1>(); 346 ParseSingleSubstFormat1(raw, 347 static_cast<TSingleSubstFormat1*>(rec->get())); 348 break; 349 case 2: 350 *rec = pdfium::MakeUnique<TSingleSubstFormat2>(); 351 ParseSingleSubstFormat2(raw, 352 static_cast<TSingleSubstFormat2*>(rec->get())); 353 break; 354 } 355} 356 357void CFX_CTTGSUBTable::ParseSingleSubstFormat1(FT_Bytes raw, 358 TSingleSubstFormat1* rec) { 359 FT_Bytes sp = raw; 360 GetUInt16(sp); 361 uint16_t offset = GetUInt16(sp); 362 rec->Coverage.reset(ParseCoverage(&raw[offset])); 363 rec->DeltaGlyphID = GetInt16(sp); 364} 365 366void CFX_CTTGSUBTable::ParseSingleSubstFormat2(FT_Bytes raw, 367 TSingleSubstFormat2* rec) { 368 FT_Bytes sp = raw; 369 (void)GetUInt16(sp); 370 uint16_t offset = GetUInt16(sp); 371 rec->Coverage.reset(ParseCoverage(&raw[offset])); 372 rec->Substitutes = std::vector<uint16_t>(GetUInt16(sp)); 373 for (auto& substitute : rec->Substitutes) 374 substitute = GetUInt16(sp); 375} 376 377CFX_CTTGSUBTable::TCoverageFormat1::TCoverageFormat1() 378 : TCoverageFormatBase(1) {} 379 380CFX_CTTGSUBTable::TCoverageFormat1::~TCoverageFormat1() {} 381 382CFX_CTTGSUBTable::TRangeRecord::TRangeRecord() 383 : Start(0), End(0), StartCoverageIndex(0) {} 384 385CFX_CTTGSUBTable::TCoverageFormat2::TCoverageFormat2() 386 : TCoverageFormatBase(2) {} 387 388CFX_CTTGSUBTable::TCoverageFormat2::~TCoverageFormat2() {} 389 390CFX_CTTGSUBTable::TSingleSubstFormat1::TSingleSubstFormat1() 391 : TSubTableBase(1), DeltaGlyphID(0) {} 392 393CFX_CTTGSUBTable::TSingleSubstFormat1::~TSingleSubstFormat1() {} 394 395CFX_CTTGSUBTable::TSingleSubstFormat2::TSingleSubstFormat2() 396 : TSubTableBase(2) {} 397 398CFX_CTTGSUBTable::TSingleSubstFormat2::~TSingleSubstFormat2() {} 399 400CFX_CTTGSUBTable::TLookup::TLookup() : LookupType(0), LookupFlag(0) {} 401 402CFX_CTTGSUBTable::TLookup::~TLookup() {} 403 404CFX_CTTGSUBTable::TScript::TScript() : DefaultLangSys(0) {} 405 406CFX_CTTGSUBTable::TScript::~TScript() {} 407 408CFX_CTTGSUBTable::TScriptList::TScriptList() {} 409 410CFX_CTTGSUBTable::TScriptList::~TScriptList() {} 411 412CFX_CTTGSUBTable::TFeature::TFeature() : FeatureParams(0) {} 413 414CFX_CTTGSUBTable::TFeature::~TFeature() {} 415 416CFX_CTTGSUBTable::TFeatureList::TFeatureList() {} 417 418CFX_CTTGSUBTable::TFeatureList::~TFeatureList() {} 419 420CFX_CTTGSUBTable::TLookupList::TLookupList() {} 421 422CFX_CTTGSUBTable::TLookupList::~TLookupList() {} 423 424CFX_CTTGSUBTable::TLangSys::TLangSys() : LookupOrder(0), ReqFeatureIndex(0) {} 425 426CFX_CTTGSUBTable::TLangSys::~TLangSys() {} 427