summaryrefslogtreecommitdiff
path: root/core/fpdfapi/font/cfx_cttgsubtable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/fpdfapi/font/cfx_cttgsubtable.cpp')
-rw-r--r--core/fpdfapi/font/cfx_cttgsubtable.cpp379
1 files changed, 379 insertions, 0 deletions
diff --git a/core/fpdfapi/font/cfx_cttgsubtable.cpp b/core/fpdfapi/font/cfx_cttgsubtable.cpp
new file mode 100644
index 0000000000..902957a436
--- /dev/null
+++ b/core/fpdfapi/font/cfx_cttgsubtable.cpp
@@ -0,0 +1,379 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/font/cfx_cttgsubtable.h"
+
+#include <utility>
+
+#include "core/fxge/fx_freetype.h"
+#include "third_party/base/ptr_util.h"
+#include "third_party/base/stl_util.h"
+
+CFX_CTTGSUBTable::CFX_CTTGSUBTable()
+ : m_bFeautureMapLoad(false), loaded(false) {}
+
+CFX_CTTGSUBTable::CFX_CTTGSUBTable(FT_Bytes gsub)
+ : m_bFeautureMapLoad(false), loaded(false) {
+ LoadGSUBTable(gsub);
+}
+
+CFX_CTTGSUBTable::~CFX_CTTGSUBTable() {}
+
+bool CFX_CTTGSUBTable::IsOk() const {
+ return loaded;
+}
+
+bool CFX_CTTGSUBTable::LoadGSUBTable(FT_Bytes gsub) {
+ header.Version = gsub[0] << 24 | gsub[1] << 16 | gsub[2] << 8 | gsub[3];
+ if (header.Version != 0x00010000) {
+ return false;
+ }
+ header.ScriptList = gsub[4] << 8 | gsub[5];
+ header.FeatureList = gsub[6] << 8 | gsub[7];
+ header.LookupList = gsub[8] << 8 | gsub[9];
+ return Parse(&gsub[header.ScriptList], &gsub[header.FeatureList],
+ &gsub[header.LookupList]);
+}
+
+bool CFX_CTTGSUBTable::GetVerticalGlyph(uint32_t glyphnum,
+ uint32_t* vglyphnum) {
+ uint32_t tag[] = {
+ (uint8_t)'v' << 24 | (uint8_t)'r' << 16 | (uint8_t)'t' << 8 |
+ (uint8_t)'2',
+ (uint8_t)'v' << 24 | (uint8_t)'e' << 16 | (uint8_t)'r' << 8 |
+ (uint8_t)'t',
+ };
+ if (!m_bFeautureMapLoad) {
+ for (const auto& script : ScriptList.ScriptRecords) {
+ for (const auto& record : script.Script.LangSysRecords) {
+ for (const auto& index : record.LangSys.FeatureIndices) {
+ if (FeatureList.FeatureRecords[index].FeatureTag == tag[0] ||
+ FeatureList.FeatureRecords[index].FeatureTag == tag[1]) {
+ m_featureSet.insert(index);
+ }
+ }
+ }
+ }
+ if (m_featureSet.empty()) {
+ int i = 0;
+ for (const auto& feature : FeatureList.FeatureRecords) {
+ if (feature.FeatureTag == tag[0] || feature.FeatureTag == tag[1])
+ m_featureSet.insert(i);
+ ++i;
+ }
+ }
+ m_bFeautureMapLoad = true;
+ }
+ for (const auto& item : m_featureSet) {
+ if (GetVerticalGlyphSub(glyphnum, vglyphnum,
+ &FeatureList.FeatureRecords[item].Feature)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CFX_CTTGSUBTable::GetVerticalGlyphSub(uint32_t glyphnum,
+ uint32_t* vglyphnum,
+ TFeature* Feature) {
+ for (int index : Feature->LookupListIndices) {
+ if (!pdfium::IndexInBounds(LookupList.Lookups, index))
+ continue;
+ if (LookupList.Lookups[index].LookupType == 1 &&
+ GetVerticalGlyphSub2(glyphnum, vglyphnum, &LookupList.Lookups[index])) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CFX_CTTGSUBTable::GetVerticalGlyphSub2(uint32_t glyphnum,
+ uint32_t* vglyphnum,
+ TLookup* Lookup) {
+ for (const auto& subTable : Lookup->SubTables) {
+ switch (subTable->SubstFormat) {
+ case 1: {
+ auto* tbl1 = static_cast<TSingleSubstFormat1*>(subTable.get());
+ if (GetCoverageIndex(tbl1->Coverage.get(), glyphnum) >= 0) {
+ *vglyphnum = glyphnum + tbl1->DeltaGlyphID;
+ return true;
+ }
+ break;
+ }
+ case 2: {
+ auto* tbl2 = static_cast<TSingleSubstFormat2*>(subTable.get());
+ int index = GetCoverageIndex(tbl2->Coverage.get(), glyphnum);
+ if (pdfium::IndexInBounds(tbl2->Substitutes, index)) {
+ *vglyphnum = tbl2->Substitutes[index];
+ return true;
+ }
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+int CFX_CTTGSUBTable::GetCoverageIndex(TCoverageFormatBase* Coverage,
+ uint32_t g) const {
+ if (!Coverage)
+ return -1;
+
+ switch (Coverage->CoverageFormat) {
+ case 1: {
+ int i = 0;
+ TCoverageFormat1* c1 = (TCoverageFormat1*)Coverage;
+ for (const auto& glyph : c1->GlyphArray) {
+ if (static_cast<uint32_t>(glyph) == g)
+ return i;
+ ++i;
+ }
+ return -1;
+ }
+ case 2: {
+ TCoverageFormat2* c2 = (TCoverageFormat2*)Coverage;
+ for (const auto& rangeRec : c2->RangeRecords) {
+ uint32_t s = rangeRec.Start;
+ uint32_t e = rangeRec.End;
+ uint32_t si = rangeRec.StartCoverageIndex;
+ if (s <= g && g <= e)
+ return si + g - s;
+ }
+ return -1;
+ }
+ }
+ return -1;
+}
+
+uint8_t CFX_CTTGSUBTable::GetUInt8(FT_Bytes& p) const {
+ uint8_t ret = p[0];
+ p += 1;
+ return ret;
+}
+
+int16_t CFX_CTTGSUBTable::GetInt16(FT_Bytes& p) const {
+ uint16_t ret = p[0] << 8 | p[1];
+ p += 2;
+ return *(int16_t*)&ret;
+}
+
+uint16_t CFX_CTTGSUBTable::GetUInt16(FT_Bytes& p) const {
+ uint16_t ret = p[0] << 8 | p[1];
+ p += 2;
+ return ret;
+}
+
+int32_t CFX_CTTGSUBTable::GetInt32(FT_Bytes& p) const {
+ uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+ p += 4;
+ return *(int32_t*)&ret;
+}
+
+uint32_t CFX_CTTGSUBTable::GetUInt32(FT_Bytes& p) const {
+ uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+ p += 4;
+ return ret;
+}
+
+bool CFX_CTTGSUBTable::Parse(FT_Bytes scriptlist,
+ FT_Bytes featurelist,
+ FT_Bytes lookuplist) {
+ ParseScriptList(scriptlist, &ScriptList);
+ ParseFeatureList(featurelist, &FeatureList);
+ ParseLookupList(lookuplist, &LookupList);
+ return true;
+}
+
+void CFX_CTTGSUBTable::ParseScriptList(FT_Bytes raw, TScriptList* rec) {
+ FT_Bytes sp = raw;
+ rec->ScriptRecords = std::vector<TScriptRecord>(GetUInt16(sp));
+ for (auto& scriptRec : rec->ScriptRecords) {
+ scriptRec.ScriptTag = GetUInt32(sp);
+ ParseScript(&raw[GetUInt16(sp)], &scriptRec.Script);
+ }
+}
+
+void CFX_CTTGSUBTable::ParseScript(FT_Bytes raw, TScript* rec) {
+ FT_Bytes sp = raw;
+ rec->DefaultLangSys = GetUInt16(sp);
+ rec->LangSysRecords = std::vector<TLangSysRecord>(GetUInt16(sp));
+ for (auto& sysRecord : rec->LangSysRecords) {
+ sysRecord.LangSysTag = GetUInt32(sp);
+ ParseLangSys(&raw[GetUInt16(sp)], &sysRecord.LangSys);
+ }
+}
+
+void CFX_CTTGSUBTable::ParseLangSys(FT_Bytes raw, TLangSys* rec) {
+ FT_Bytes sp = raw;
+ rec->LookupOrder = GetUInt16(sp);
+ rec->ReqFeatureIndex = GetUInt16(sp);
+ rec->FeatureIndices = std::vector<uint16_t>(GetUInt16(sp));
+ for (auto& element : rec->FeatureIndices)
+ element = GetUInt16(sp);
+}
+
+void CFX_CTTGSUBTable::ParseFeatureList(FT_Bytes raw, TFeatureList* rec) {
+ FT_Bytes sp = raw;
+ rec->FeatureRecords = std::vector<TFeatureRecord>(GetUInt16(sp));
+ for (auto& featureRec : rec->FeatureRecords) {
+ featureRec.FeatureTag = GetUInt32(sp);
+ ParseFeature(&raw[GetUInt16(sp)], &featureRec.Feature);
+ }
+}
+
+void CFX_CTTGSUBTable::ParseFeature(FT_Bytes raw, TFeature* rec) {
+ FT_Bytes sp = raw;
+ rec->FeatureParams = GetUInt16(sp);
+ rec->LookupListIndices = std::vector<uint16_t>(GetUInt16(sp));
+ for (auto& listIndex : rec->LookupListIndices)
+ listIndex = GetUInt16(sp);
+}
+
+void CFX_CTTGSUBTable::ParseLookupList(FT_Bytes raw, TLookupList* rec) {
+ FT_Bytes sp = raw;
+ rec->Lookups = std::vector<TLookup>(GetUInt16(sp));
+ for (auto& lookup : rec->Lookups)
+ ParseLookup(&raw[GetUInt16(sp)], &lookup);
+}
+
+void CFX_CTTGSUBTable::ParseLookup(FT_Bytes raw, TLookup* rec) {
+ FT_Bytes sp = raw;
+ rec->LookupType = GetUInt16(sp);
+ rec->LookupFlag = GetUInt16(sp);
+ rec->SubTables = std::vector<std::unique_ptr<TSubTableBase>>(GetUInt16(sp));
+ if (rec->LookupType != 1)
+ return;
+
+ for (auto& subTable : rec->SubTables)
+ ParseSingleSubst(&raw[GetUInt16(sp)], &subTable);
+}
+
+std::unique_ptr<CFX_CTTGSUBTable::TCoverageFormatBase>
+CFX_CTTGSUBTable::ParseCoverage(FT_Bytes raw) {
+ FT_Bytes sp = raw;
+ uint16_t format = GetUInt16(sp);
+ if (format == 1) {
+ auto rec = pdfium::MakeUnique<TCoverageFormat1>();
+ ParseCoverageFormat1(raw, rec.get());
+ return std::move(rec);
+ }
+ if (format == 2) {
+ auto rec = pdfium::MakeUnique<TCoverageFormat2>();
+ ParseCoverageFormat2(raw, rec.get());
+ return std::move(rec);
+ }
+ return nullptr;
+}
+
+void CFX_CTTGSUBTable::ParseCoverageFormat1(FT_Bytes raw,
+ TCoverageFormat1* rec) {
+ FT_Bytes sp = raw;
+ (void)GetUInt16(sp);
+ rec->GlyphArray = std::vector<uint16_t>(GetUInt16(sp));
+ for (auto& glyph : rec->GlyphArray)
+ glyph = GetUInt16(sp);
+}
+
+void CFX_CTTGSUBTable::ParseCoverageFormat2(FT_Bytes raw,
+ TCoverageFormat2* rec) {
+ FT_Bytes sp = raw;
+ (void)GetUInt16(sp);
+ rec->RangeRecords = std::vector<TRangeRecord>(GetUInt16(sp));
+ for (auto& rangeRec : rec->RangeRecords) {
+ rangeRec.Start = GetUInt16(sp);
+ rangeRec.End = GetUInt16(sp);
+ rangeRec.StartCoverageIndex = GetUInt16(sp);
+ }
+}
+
+void CFX_CTTGSUBTable::ParseSingleSubst(FT_Bytes raw,
+ std::unique_ptr<TSubTableBase>* rec) {
+ FT_Bytes sp = raw;
+ uint16_t Format = GetUInt16(sp);
+ switch (Format) {
+ case 1:
+ *rec = pdfium::MakeUnique<TSingleSubstFormat1>();
+ ParseSingleSubstFormat1(raw,
+ static_cast<TSingleSubstFormat1*>(rec->get()));
+ break;
+ case 2:
+ *rec = pdfium::MakeUnique<TSingleSubstFormat2>();
+ ParseSingleSubstFormat2(raw,
+ static_cast<TSingleSubstFormat2*>(rec->get()));
+ break;
+ }
+}
+
+void CFX_CTTGSUBTable::ParseSingleSubstFormat1(FT_Bytes raw,
+ TSingleSubstFormat1* rec) {
+ FT_Bytes sp = raw;
+ GetUInt16(sp);
+ uint16_t offset = GetUInt16(sp);
+ rec->Coverage = ParseCoverage(&raw[offset]);
+ rec->DeltaGlyphID = GetInt16(sp);
+}
+
+void CFX_CTTGSUBTable::ParseSingleSubstFormat2(FT_Bytes raw,
+ TSingleSubstFormat2* rec) {
+ FT_Bytes sp = raw;
+ (void)GetUInt16(sp);
+ uint16_t offset = GetUInt16(sp);
+ rec->Coverage = ParseCoverage(&raw[offset]);
+ rec->Substitutes = std::vector<uint16_t>(GetUInt16(sp));
+ for (auto& substitute : rec->Substitutes)
+ substitute = GetUInt16(sp);
+}
+
+CFX_CTTGSUBTable::TCoverageFormat1::TCoverageFormat1()
+ : TCoverageFormatBase(1) {}
+
+CFX_CTTGSUBTable::TCoverageFormat1::~TCoverageFormat1() {}
+
+CFX_CTTGSUBTable::TRangeRecord::TRangeRecord()
+ : Start(0), End(0), StartCoverageIndex(0) {}
+
+CFX_CTTGSUBTable::TCoverageFormat2::TCoverageFormat2()
+ : TCoverageFormatBase(2) {}
+
+CFX_CTTGSUBTable::TCoverageFormat2::~TCoverageFormat2() {}
+
+CFX_CTTGSUBTable::TSingleSubstFormat1::TSingleSubstFormat1()
+ : TSubTableBase(1), DeltaGlyphID(0) {}
+
+CFX_CTTGSUBTable::TSingleSubstFormat1::~TSingleSubstFormat1() {}
+
+CFX_CTTGSUBTable::TSingleSubstFormat2::TSingleSubstFormat2()
+ : TSubTableBase(2) {}
+
+CFX_CTTGSUBTable::TSingleSubstFormat2::~TSingleSubstFormat2() {}
+
+CFX_CTTGSUBTable::TLookup::TLookup() : LookupType(0), LookupFlag(0) {}
+
+CFX_CTTGSUBTable::TLookup::~TLookup() {}
+
+CFX_CTTGSUBTable::TScript::TScript() : DefaultLangSys(0) {}
+
+CFX_CTTGSUBTable::TScript::~TScript() {}
+
+CFX_CTTGSUBTable::TScriptList::TScriptList() {}
+
+CFX_CTTGSUBTable::TScriptList::~TScriptList() {}
+
+CFX_CTTGSUBTable::TFeature::TFeature() : FeatureParams(0) {}
+
+CFX_CTTGSUBTable::TFeature::~TFeature() {}
+
+CFX_CTTGSUBTable::TFeatureList::TFeatureList() {}
+
+CFX_CTTGSUBTable::TFeatureList::~TFeatureList() {}
+
+CFX_CTTGSUBTable::TLookupList::TLookupList() {}
+
+CFX_CTTGSUBTable::TLookupList::~TLookupList() {}
+
+CFX_CTTGSUBTable::TLangSys::TLangSys() : LookupOrder(0), ReqFeatureIndex(0) {}
+
+CFX_CTTGSUBTable::TLangSys::~TLangSys() {}