From 169b30187bf5798a6106b5ab16288c9d86861f8b Mon Sep 17 00:00:00 2001 From: Nicolas Pena Date: Fri, 26 May 2017 14:38:03 -0400 Subject: Use proper file names in core/fpdfapi/font MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL splits up font_int.h into files by classes. It also renames the unittests to match the class being tested. Finally, it renames the ttgsubtable files to match the class name. Change-Id: I6187caa9e82d12b9a66e955113fe327d52042ae0 Reviewed-on: https://pdfium-review.googlesource.com/6090 Reviewed-by: Tom Sepez Commit-Queue: Nicolás Peña --- BUILD.gn | 25 +- core/fpdfapi/cmaps/CNS1/cmaps_cns1.cpp | 2 +- core/fpdfapi/cmaps/GB1/cmaps_gb1.cpp | 2 +- core/fpdfapi/cmaps/Japan1/cmaps_japan1.cpp | 2 +- core/fpdfapi/cmaps/Korea1/cmaps_korea1.cpp | 2 +- core/fpdfapi/cmaps/fpdf_cmaps.cpp | 2 +- core/fpdfapi/font/cfx_cttgsubtable.cpp | 379 ++++++++++++ core/fpdfapi/font/cfx_cttgsubtable.h | 298 +++++++++ core/fpdfapi/font/cfx_stockfontarray.cpp | 35 ++ core/fpdfapi/font/cfx_stockfontarray.h | 27 + core/fpdfapi/font/cpdf_cid2unicodemap.cpp | 42 ++ core/fpdfapi/font/cpdf_cid2unicodemap.h | 29 + core/fpdfapi/font/cpdf_cidfont.cpp | 10 +- core/fpdfapi/font/cpdf_cmap.cpp | 488 +++++++++++++++ core/fpdfapi/font/cpdf_cmap.h | 87 +++ core/fpdfapi/font/cpdf_cmapmanager.cpp | 59 ++ core/fpdfapi/font/cpdf_cmapmanager.h | 36 ++ core/fpdfapi/font/cpdf_cmapparser.cpp | 204 ++++++ core/fpdfapi/font/cpdf_cmapparser.h | 52 ++ core/fpdfapi/font/cpdf_cmapparser_unittest.cpp | 71 +++ core/fpdfapi/font/cpdf_font.cpp | 25 +- core/fpdfapi/font/cpdf_font.h | 4 + core/fpdfapi/font/cpdf_fontglobals.cpp | 39 ++ core/fpdfapi/font/cpdf_fontglobals.h | 45 ++ core/fpdfapi/font/cpdf_simplefont.cpp | 1 - core/fpdfapi/font/cpdf_tounicodemap.cpp | 233 +++++++ core/fpdfapi/font/cpdf_tounicodemap.h | 42 ++ core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp | 31 + core/fpdfapi/font/cpdf_truetypefont.cpp | 1 - core/fpdfapi/font/cpdf_type1font.cpp | 1 - core/fpdfapi/font/font_int.h | 229 ------- core/fpdfapi/font/fpdf_font.cpp | 314 ---------- core/fpdfapi/font/fpdf_font_cid.cpp | 750 ----------------------- core/fpdfapi/font/fpdf_font_cid_unittest.cpp | 70 --- core/fpdfapi/font/fpdf_font_unittest.cpp | 30 - core/fpdfapi/font/ttgsubtable.cpp | 379 ------------ core/fpdfapi/font/ttgsubtable.h | 298 --------- core/fpdfapi/page/cpdf_docpagedata.cpp | 1 - core/fpdfapi/page/cpdf_pagemodule.h | 2 +- testing/libfuzzer/pdf_cmap_fuzzer.cc | 2 +- 40 files changed, 2256 insertions(+), 2093 deletions(-) create mode 100644 core/fpdfapi/font/cfx_cttgsubtable.cpp create mode 100644 core/fpdfapi/font/cfx_cttgsubtable.h create mode 100644 core/fpdfapi/font/cfx_stockfontarray.cpp create mode 100644 core/fpdfapi/font/cfx_stockfontarray.h create mode 100644 core/fpdfapi/font/cpdf_cid2unicodemap.cpp create mode 100644 core/fpdfapi/font/cpdf_cid2unicodemap.h create mode 100644 core/fpdfapi/font/cpdf_cmap.cpp create mode 100644 core/fpdfapi/font/cpdf_cmap.h create mode 100644 core/fpdfapi/font/cpdf_cmapmanager.cpp create mode 100644 core/fpdfapi/font/cpdf_cmapmanager.h create mode 100644 core/fpdfapi/font/cpdf_cmapparser.cpp create mode 100644 core/fpdfapi/font/cpdf_cmapparser.h create mode 100644 core/fpdfapi/font/cpdf_cmapparser_unittest.cpp create mode 100644 core/fpdfapi/font/cpdf_fontglobals.cpp create mode 100644 core/fpdfapi/font/cpdf_fontglobals.h create mode 100644 core/fpdfapi/font/cpdf_tounicodemap.cpp create mode 100644 core/fpdfapi/font/cpdf_tounicodemap.h create mode 100644 core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp delete mode 100644 core/fpdfapi/font/font_int.h delete mode 100644 core/fpdfapi/font/fpdf_font.cpp delete mode 100644 core/fpdfapi/font/fpdf_font_cid.cpp delete mode 100644 core/fpdfapi/font/fpdf_font_cid_unittest.cpp delete mode 100644 core/fpdfapi/font/fpdf_font_unittest.cpp delete mode 100644 core/fpdfapi/font/ttgsubtable.cpp delete mode 100644 core/fpdfapi/font/ttgsubtable.h diff --git a/BUILD.gn b/BUILD.gn index 98189a09f5..9ecd20d6cb 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -445,14 +445,30 @@ static_library("fpdfapi") { "core/fpdfapi/edit/cpdf_flateencoder.h", "core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp", "core/fpdfapi/edit/cpdf_pagecontentgenerator.h", + "core/fpdfapi/font/cfx_cttgsubtable.cpp", + "core/fpdfapi/font/cfx_cttgsubtable.h", + "core/fpdfapi/font/cfx_stockfontarray.cpp", + "core/fpdfapi/font/cfx_stockfontarray.h", + "core/fpdfapi/font/cpdf_cid2unicodemap.cpp", + "core/fpdfapi/font/cpdf_cid2unicodemap.h", "core/fpdfapi/font/cpdf_cidfont.cpp", "core/fpdfapi/font/cpdf_cidfont.h", + "core/fpdfapi/font/cpdf_cmap.cpp", + "core/fpdfapi/font/cpdf_cmap.h", + "core/fpdfapi/font/cpdf_cmapmanager.cpp", + "core/fpdfapi/font/cpdf_cmapmanager.h", + "core/fpdfapi/font/cpdf_cmapparser.cpp", + "core/fpdfapi/font/cpdf_cmapparser.h", "core/fpdfapi/font/cpdf_font.cpp", "core/fpdfapi/font/cpdf_font.h", "core/fpdfapi/font/cpdf_fontencoding.cpp", "core/fpdfapi/font/cpdf_fontencoding.h", + "core/fpdfapi/font/cpdf_fontglobals.cpp", + "core/fpdfapi/font/cpdf_fontglobals.h", "core/fpdfapi/font/cpdf_simplefont.cpp", "core/fpdfapi/font/cpdf_simplefont.h", + "core/fpdfapi/font/cpdf_tounicodemap.cpp", + "core/fpdfapi/font/cpdf_tounicodemap.h", "core/fpdfapi/font/cpdf_truetypefont.cpp", "core/fpdfapi/font/cpdf_truetypefont.h", "core/fpdfapi/font/cpdf_type1font.cpp", @@ -461,11 +477,6 @@ static_library("fpdfapi") { "core/fpdfapi/font/cpdf_type3char.h", "core/fpdfapi/font/cpdf_type3font.cpp", "core/fpdfapi/font/cpdf_type3font.h", - "core/fpdfapi/font/font_int.h", - "core/fpdfapi/font/fpdf_font.cpp", - "core/fpdfapi/font/fpdf_font_cid.cpp", - "core/fpdfapi/font/ttgsubtable.cpp", - "core/fpdfapi/font/ttgsubtable.h", "core/fpdfapi/page/cpdf_allstates.cpp", "core/fpdfapi/page/cpdf_allstates.h", "core/fpdfapi/page/cpdf_clippath.cpp", @@ -1866,8 +1877,8 @@ test("pdfium_unittests") { sources = [ "core/fdrm/crypto/fx_crypt_unittest.cpp", "core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp", - "core/fpdfapi/font/fpdf_font_cid_unittest.cpp", - "core/fpdfapi/font/fpdf_font_unittest.cpp", + "core/fpdfapi/font/cpdf_cmapparser_unittest.cpp", + "core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp", "core/fpdfapi/page/cpdf_devicecs_unittest.cpp", "core/fpdfapi/page/cpdf_streamcontentparser_unittest.cpp", "core/fpdfapi/page/cpdf_streamparser_unittest.cpp", diff --git a/core/fpdfapi/cmaps/CNS1/cmaps_cns1.cpp b/core/fpdfapi/cmaps/CNS1/cmaps_cns1.cpp index a1bbefc1ab..dc8a21776d 100644 --- a/core/fpdfapi/cmaps/CNS1/cmaps_cns1.cpp +++ b/core/fpdfapi/cmaps/CNS1/cmaps_cns1.cpp @@ -8,7 +8,7 @@ #include "core/fpdfapi/cmaps/cmap_int.h" #include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_fontglobals.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" #include "core/fxcrt/fx_basic.h" diff --git a/core/fpdfapi/cmaps/GB1/cmaps_gb1.cpp b/core/fpdfapi/cmaps/GB1/cmaps_gb1.cpp index 9d15271e7e..1591da1eca 100644 --- a/core/fpdfapi/cmaps/GB1/cmaps_gb1.cpp +++ b/core/fpdfapi/cmaps/GB1/cmaps_gb1.cpp @@ -8,7 +8,7 @@ #include "core/fpdfapi/cmaps/cmap_int.h" #include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_fontglobals.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" #include "core/fxcrt/fx_basic.h" diff --git a/core/fpdfapi/cmaps/Japan1/cmaps_japan1.cpp b/core/fpdfapi/cmaps/Japan1/cmaps_japan1.cpp index bdf65595ad..8fd4fcb7c4 100644 --- a/core/fpdfapi/cmaps/Japan1/cmaps_japan1.cpp +++ b/core/fpdfapi/cmaps/Japan1/cmaps_japan1.cpp @@ -8,7 +8,7 @@ #include "core/fpdfapi/cmaps/cmap_int.h" #include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_fontglobals.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" #include "core/fxcrt/fx_basic.h" diff --git a/core/fpdfapi/cmaps/Korea1/cmaps_korea1.cpp b/core/fpdfapi/cmaps/Korea1/cmaps_korea1.cpp index 5e88b3ba17..8e9784e5de 100644 --- a/core/fpdfapi/cmaps/Korea1/cmaps_korea1.cpp +++ b/core/fpdfapi/cmaps/Korea1/cmaps_korea1.cpp @@ -8,7 +8,7 @@ #include "core/fpdfapi/cmaps/cmap_int.h" #include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_fontglobals.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" #include "core/fxcrt/fx_basic.h" diff --git a/core/fpdfapi/cmaps/fpdf_cmaps.cpp b/core/fpdfapi/cmaps/fpdf_cmaps.cpp index 13aec268ae..80ebbdef70 100644 --- a/core/fpdfapi/cmaps/fpdf_cmaps.cpp +++ b/core/fpdfapi/cmaps/fpdf_cmaps.cpp @@ -7,7 +7,7 @@ #include "core/fpdfapi/cmaps/cmap_int.h" #include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_fontglobals.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" extern "C" { 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 + +#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(subTable.get()); + if (GetCoverageIndex(tbl1->Coverage.get(), glyphnum) >= 0) { + *vglyphnum = glyphnum + tbl1->DeltaGlyphID; + return true; + } + break; + } + case 2: { + auto* tbl2 = static_cast(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(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(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(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(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(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(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(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>(GetUInt16(sp)); + if (rec->LookupType != 1) + return; + + for (auto& subTable : rec->SubTables) + ParseSingleSubst(&raw[GetUInt16(sp)], &subTable); +} + +std::unique_ptr +CFX_CTTGSUBTable::ParseCoverage(FT_Bytes raw) { + FT_Bytes sp = raw; + uint16_t format = GetUInt16(sp); + if (format == 1) { + auto rec = pdfium::MakeUnique(); + ParseCoverageFormat1(raw, rec.get()); + return std::move(rec); + } + if (format == 2) { + auto rec = pdfium::MakeUnique(); + 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(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(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* rec) { + FT_Bytes sp = raw; + uint16_t Format = GetUInt16(sp); + switch (Format) { + case 1: + *rec = pdfium::MakeUnique(); + ParseSingleSubstFormat1(raw, + static_cast(rec->get())); + break; + case 2: + *rec = pdfium::MakeUnique(); + ParseSingleSubstFormat2(raw, + static_cast(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(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() {} diff --git a/core/fpdfapi/font/cfx_cttgsubtable.h b/core/fpdfapi/font/cfx_cttgsubtable.h new file mode 100644 index 0000000000..aac3f86c07 --- /dev/null +++ b/core/fpdfapi/font/cfx_cttgsubtable.h @@ -0,0 +1,298 @@ +// 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 + +#ifndef CORE_FPDFAPI_FONT_CFX_CTTGSUBTABLE_H_ +#define CORE_FPDFAPI_FONT_CFX_CTTGSUBTABLE_H_ + +#include + +#include +#include +#include + +#include "core/fxcrt/fx_basic.h" +#include "core/fxge/fx_font.h" +#include "core/fxge/fx_freetype.h" + +class CFX_CTTGSUBTable { + public: + CFX_CTTGSUBTable(); + explicit CFX_CTTGSUBTable(FT_Bytes gsub); + virtual ~CFX_CTTGSUBTable(); + + bool IsOk() const; + bool LoadGSUBTable(FT_Bytes gsub); + bool GetVerticalGlyph(uint32_t glyphnum, uint32_t* vglyphnum); + + private: + struct tt_gsub_header { + uint32_t Version; + uint16_t ScriptList; + uint16_t FeatureList; + uint16_t LookupList; + }; + + struct TLangSys { + TLangSys(); + ~TLangSys(); + + uint16_t LookupOrder; + uint16_t ReqFeatureIndex; + std::vector FeatureIndices; + + private: + TLangSys(const TLangSys&) = delete; + TLangSys& operator=(const TLangSys&) = delete; + }; + + struct TLangSysRecord { + TLangSysRecord() : LangSysTag(0) {} + + uint32_t LangSysTag; + TLangSys LangSys; + + private: + TLangSysRecord(const TLangSysRecord&) = delete; + TLangSysRecord& operator=(const TLangSysRecord&) = delete; + }; + + struct TScript { + TScript(); + ~TScript(); + + uint16_t DefaultLangSys; + std::vector LangSysRecords; + + private: + TScript(const TScript&) = delete; + TScript& operator=(const TScript&) = delete; + }; + + struct TScriptRecord { + TScriptRecord() : ScriptTag(0) {} + + uint32_t ScriptTag; + TScript Script; + + private: + TScriptRecord(const TScriptRecord&) = delete; + TScriptRecord& operator=(const TScriptRecord&) = delete; + }; + + struct TScriptList { + TScriptList(); + ~TScriptList(); + + std::vector ScriptRecords; + + private: + TScriptList(const TScriptList&) = delete; + TScriptList& operator=(const TScriptList&) = delete; + }; + + struct TFeature { + TFeature(); + ~TFeature(); + + uint16_t FeatureParams; + std::vector LookupListIndices; + + private: + TFeature(const TFeature&) = delete; + TFeature& operator=(const TFeature&) = delete; + }; + + struct TFeatureRecord { + TFeatureRecord() : FeatureTag(0) {} + + uint32_t FeatureTag; + TFeature Feature; + + private: + TFeatureRecord(const TFeatureRecord&) = delete; + TFeatureRecord& operator=(const TFeatureRecord&) = delete; + }; + + struct TFeatureList { + TFeatureList(); + ~TFeatureList(); + + std::vector FeatureRecords; + + private: + TFeatureList(const TFeatureList&) = delete; + TFeatureList& operator=(const TFeatureList&) = delete; + }; + + enum TLookupFlag { + LOOKUPFLAG_RightToLeft = 0x0001, + LOOKUPFLAG_IgnoreBaseGlyphs = 0x0002, + LOOKUPFLAG_IgnoreLigatures = 0x0004, + LOOKUPFLAG_IgnoreMarks = 0x0008, + LOOKUPFLAG_Reserved = 0x00F0, + LOOKUPFLAG_MarkAttachmentType = 0xFF00, + }; + + struct TCoverageFormatBase { + TCoverageFormatBase() : CoverageFormat(0) {} + explicit TCoverageFormatBase(uint16_t format) : CoverageFormat(format) {} + virtual ~TCoverageFormatBase() {} + + uint16_t CoverageFormat; + + private: + TCoverageFormatBase(const TCoverageFormatBase&); + TCoverageFormatBase& operator=(const TCoverageFormatBase&); + }; + + struct TCoverageFormat1 : public TCoverageFormatBase { + TCoverageFormat1(); + ~TCoverageFormat1() override; + + std::vector GlyphArray; + + private: + TCoverageFormat1(const TCoverageFormat1&) = delete; + TCoverageFormat1& operator=(const TCoverageFormat1&) = delete; + }; + + struct TRangeRecord { + TRangeRecord(); + + friend bool operator>(const TRangeRecord& r1, const TRangeRecord& r2) { + return r1.Start > r2.Start; + } + + uint16_t Start; + uint16_t End; + uint16_t StartCoverageIndex; + + private: + TRangeRecord(const TRangeRecord&) = delete; + }; + + struct TCoverageFormat2 : public TCoverageFormatBase { + TCoverageFormat2(); + ~TCoverageFormat2() override; + + std::vector RangeRecords; + + private: + TCoverageFormat2(const TCoverageFormat2&) = delete; + TCoverageFormat2& operator=(const TCoverageFormat2&) = delete; + }; + + struct TDevice { + TDevice() : StartSize(0), EndSize(0), DeltaFormat(0) {} + + uint16_t StartSize; + uint16_t EndSize; + uint16_t DeltaFormat; + + private: + TDevice(const TDevice&) = delete; + TDevice& operator=(const TDevice&) = delete; + }; + + struct TSubTableBase { + TSubTableBase() : SubstFormat(0) {} + explicit TSubTableBase(uint16_t format) : SubstFormat(format) {} + virtual ~TSubTableBase() {} + + uint16_t SubstFormat; + + private: + TSubTableBase(const TSubTableBase&) = delete; + TSubTableBase& operator=(const TSubTableBase&) = delete; + }; + + struct TSingleSubstFormat1 : public TSubTableBase { + TSingleSubstFormat1(); + ~TSingleSubstFormat1() override; + + std::unique_ptr Coverage; + int16_t DeltaGlyphID; + + private: + TSingleSubstFormat1(const TSingleSubstFormat1&) = delete; + TSingleSubstFormat1& operator=(const TSingleSubstFormat1&) = delete; + }; + + struct TSingleSubstFormat2 : public TSubTableBase { + TSingleSubstFormat2(); + ~TSingleSubstFormat2() override; + + std::unique_ptr Coverage; + std::vector Substitutes; + + private: + TSingleSubstFormat2(const TSingleSubstFormat2&) = delete; + TSingleSubstFormat2& operator=(const TSingleSubstFormat2&) = delete; + }; + + struct TLookup { + TLookup(); + ~TLookup(); + + uint16_t LookupType; + uint16_t LookupFlag; + std::vector> SubTables; + + private: + TLookup(const TLookup&) = delete; + TLookup& operator=(const TLookup&) = delete; + }; + + struct TLookupList { + TLookupList(); + ~TLookupList(); + + std::vector Lookups; + + private: + TLookupList(const TLookupList&) = delete; + TLookupList& operator=(const TLookupList&) = delete; + }; + + bool Parse(FT_Bytes scriptlist, FT_Bytes featurelist, FT_Bytes lookuplist); + void ParseScriptList(FT_Bytes raw, TScriptList* rec); + void ParseScript(FT_Bytes raw, TScript* rec); + void ParseLangSys(FT_Bytes raw, TLangSys* rec); + void ParseFeatureList(FT_Bytes raw, TFeatureList* rec); + void ParseFeature(FT_Bytes raw, TFeature* rec); + void ParseLookupList(FT_Bytes raw, TLookupList* rec); + void ParseLookup(FT_Bytes raw, TLookup* rec); + std::unique_ptr ParseCoverage(FT_Bytes raw); + void ParseCoverageFormat1(FT_Bytes raw, TCoverageFormat1* rec); + void ParseCoverageFormat2(FT_Bytes raw, TCoverageFormat2* rec); + void ParseSingleSubst(FT_Bytes raw, std::unique_ptr* rec); + void ParseSingleSubstFormat1(FT_Bytes raw, TSingleSubstFormat1* rec); + void ParseSingleSubstFormat2(FT_Bytes raw, TSingleSubstFormat2* rec); + + bool GetVerticalGlyphSub(uint32_t glyphnum, + uint32_t* vglyphnum, + TFeature* Feature); + bool GetVerticalGlyphSub2(uint32_t glyphnum, + uint32_t* vglyphnum, + TLookup* Lookup); + int GetCoverageIndex(TCoverageFormatBase* Coverage, uint32_t g) const; + + uint8_t GetUInt8(FT_Bytes& p) const; + int16_t GetInt16(FT_Bytes& p) const; + uint16_t GetUInt16(FT_Bytes& p) const; + int32_t GetInt32(FT_Bytes& p) const; + uint32_t GetUInt32(FT_Bytes& p) const; + + std::set m_featureSet; + bool m_bFeautureMapLoad; + bool loaded; + tt_gsub_header header; + TScriptList ScriptList; + TFeatureList FeatureList; + TLookupList LookupList; +}; + +#endif // CORE_FPDFAPI_FONT_CFX_CTTGSUBTABLE_H_ diff --git a/core/fpdfapi/font/cfx_stockfontarray.cpp b/core/fpdfapi/font/cfx_stockfontarray.cpp new file mode 100644 index 0000000000..0808471c82 --- /dev/null +++ b/core/fpdfapi/font/cfx_stockfontarray.cpp @@ -0,0 +1,35 @@ +// Copyright 2017 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_stockfontarray.h" + +#include +#include + +#include "core/fxcrt/fx_memory.h" + +CFX_StockFontArray::CFX_StockFontArray() {} + +CFX_StockFontArray::~CFX_StockFontArray() { + for (size_t i = 0; i < FX_ArraySize(m_StockFonts); ++i) { + if (m_StockFonts[i]) + delete m_StockFonts[i]->GetFontDict(); + } +} + +CPDF_Font* CFX_StockFontArray::GetFont(uint32_t index) const { + if (index >= FX_ArraySize(m_StockFonts)) + return nullptr; + return m_StockFonts[index].get(); +} + +CPDF_Font* CFX_StockFontArray::SetFont(uint32_t index, + std::unique_ptr pFont) { + CPDF_Font* result = pFont.get(); + if (index < FX_ArraySize(m_StockFonts)) + m_StockFonts[index] = std::move(pFont); + return result; +} diff --git a/core/fpdfapi/font/cfx_stockfontarray.h b/core/fpdfapi/font/cfx_stockfontarray.h new file mode 100644 index 0000000000..50a13c167f --- /dev/null +++ b/core/fpdfapi/font/cfx_stockfontarray.h @@ -0,0 +1,27 @@ +// Copyright 2017 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 + +#ifndef CORE_FPDFAPI_FONT_CFX_STOCKFONTARRAY_H_ +#define CORE_FPDFAPI_FONT_CFX_STOCKFONTARRAY_H_ + +#include + +#include "core/fpdfapi/font/cpdf_font.h" + +class CFX_StockFontArray { + public: + CFX_StockFontArray(); + ~CFX_StockFontArray(); + + // Takes ownership of |pFont|, returns unowned pointer to it. + CPDF_Font* SetFont(uint32_t index, std::unique_ptr pFont); + CPDF_Font* GetFont(uint32_t index) const; + + private: + std::unique_ptr m_StockFonts[14]; +}; + +#endif // CORE_FPDFAPI_FONT_CFX_STOCKFONTARRAY_H_ diff --git a/core/fpdfapi/font/cpdf_cid2unicodemap.cpp b/core/fpdfapi/font/cpdf_cid2unicodemap.cpp new file mode 100644 index 0000000000..cb378aa9d6 --- /dev/null +++ b/core/fpdfapi/font/cpdf_cid2unicodemap.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 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/cpdf_cid2unicodemap.h" + +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fpdfapi/font/cpdf_cmapmanager.h" +#include "core/fpdfapi/page/cpdf_pagemodule.h" + +CPDF_CID2UnicodeMap::CPDF_CID2UnicodeMap() { + m_EmbeddedCount = 0; +} + +CPDF_CID2UnicodeMap::~CPDF_CID2UnicodeMap() {} + +bool CPDF_CID2UnicodeMap::IsLoaded() { + return m_EmbeddedCount != 0; +} + +wchar_t CPDF_CID2UnicodeMap::UnicodeFromCID(uint16_t CID) { + if (m_Charset == CIDSET_UNICODE) { + return CID; + } + if (CID < m_EmbeddedCount) { + return m_pEmbeddedMap[CID]; + } + return 0; +} + +void CPDF_CID2UnicodeMap::Load(CPDF_CMapManager* pMgr, + CIDSet charset, + bool bPromptCJK) { + m_Charset = charset; + + CPDF_FontGlobals* pFontGlobals = + CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals(); + m_pEmbeddedMap = pFontGlobals->m_EmbeddedToUnicodes[charset].m_pMap; + m_EmbeddedCount = pFontGlobals->m_EmbeddedToUnicodes[charset].m_Count; +} diff --git a/core/fpdfapi/font/cpdf_cid2unicodemap.h b/core/fpdfapi/font/cpdf_cid2unicodemap.h new file mode 100644 index 0000000000..2c3fe5b7aa --- /dev/null +++ b/core/fpdfapi/font/cpdf_cid2unicodemap.h @@ -0,0 +1,29 @@ +// Copyright 2017 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 + +#ifndef CORE_FPDFAPI_FONT_CPDF_CID2UNICODEMAP_H_ +#define CORE_FPDFAPI_FONT_CPDF_CID2UNICODEMAP_H_ + +#include "core/fpdfapi/font/cpdf_cidfont.h" + +class CPDF_CMapManager; + +class CPDF_CID2UnicodeMap { + public: + CPDF_CID2UnicodeMap(); + ~CPDF_CID2UnicodeMap(); + + bool IsLoaded(); + void Load(CPDF_CMapManager* pMgr, CIDSet charset, bool bPromptCJK); + wchar_t UnicodeFromCID(uint16_t CID); + + private: + CIDSet m_Charset; + const uint16_t* m_pEmbeddedMap; + uint32_t m_EmbeddedCount; +}; + +#endif // CORE_FPDFAPI_FONT_CPDF_CID2UNICODEMAP_H_ diff --git a/core/fpdfapi/font/cpdf_cidfont.cpp b/core/fpdfapi/font/cpdf_cidfont.cpp index c41f8046f7..8cb59de739 100644 --- a/core/fpdfapi/font/cpdf_cidfont.cpp +++ b/core/fpdfapi/font/cpdf_cidfont.cpp @@ -12,9 +12,11 @@ #include "core/fpdfapi/cmaps/cmap_int.h" #include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fpdfapi/font/cfx_cttgsubtable.h" +#include "core/fpdfapi/font/cpdf_cid2unicodemap.h" +#include "core/fpdfapi/font/cpdf_cmap.h" +#include "core/fpdfapi/font/cpdf_cmapparser.h" #include "core/fpdfapi/font/cpdf_fontencoding.h" -#include "core/fpdfapi/font/font_int.h" -#include "core/fpdfapi/font/ttgsubtable.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" @@ -377,8 +379,8 @@ bool CPDF_CIDFont::Load() { if (m_Charset == CIDSET_UNKNOWN) { CPDF_Dictionary* pCIDInfo = pCIDFontDict->GetDictFor("CIDSystemInfo"); if (pCIDInfo) { - m_Charset = - CharsetFromOrdering(pCIDInfo->GetStringFor("Ordering").AsStringC()); + m_Charset = CPDF_CMapParser::CharsetFromOrdering( + pCIDInfo->GetStringFor("Ordering").AsStringC()); } } if (m_Charset != CIDSET_UNKNOWN) { diff --git a/core/fpdfapi/font/cpdf_cmap.cpp b/core/fpdfapi/font/cpdf_cmap.cpp new file mode 100644 index 0000000000..55f5ccc5c5 --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmap.cpp @@ -0,0 +1,488 @@ +// Copyright 2017 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/cpdf_cmap.h" + +#include +#include +#include + +#include "core/fpdfapi/cmaps/cmap_int.h" +#include "core/fpdfapi/font/cpdf_cmapmanager.h" +#include "core/fpdfapi/font/cpdf_cmapparser.h" +#include "core/fpdfapi/parser/cpdf_simple_parser.h" + +namespace { + +struct ByteRange { + uint8_t m_First; + uint8_t m_Last; // Inclusive. +}; + +struct PredefinedCMap { + const char* m_pName; + CIDSet m_Charset; + CIDCoding m_Coding; + CPDF_CMap::CodingScheme m_CodingScheme; + uint8_t m_LeadingSegCount; + ByteRange m_LeadingSegs[2]; +}; + +const PredefinedCMap g_PredefinedCMaps[] = { + {"GB-EUC", + CIDSET_GB1, + CIDCODING_GB, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfe}}}, + {"GBpc-EUC", + CIDSET_GB1, + CIDCODING_GB, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfc}}}, + {"GBK-EUC", + CIDSET_GB1, + CIDCODING_GB, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x81, 0xfe}}}, + {"GBKp-EUC", + CIDSET_GB1, + CIDCODING_GB, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x81, 0xfe}}}, + {"GBK2K-EUC", + CIDSET_GB1, + CIDCODING_GB, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x81, 0xfe}}}, + {"GBK2K", + CIDSET_GB1, + CIDCODING_GB, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x81, 0xfe}}}, + {"UniGB-UCS2", CIDSET_GB1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, + {"UniGB-UTF16", CIDSET_GB1, CIDCODING_UTF16, CPDF_CMap::TwoBytes, 0, {}}, + {"B5pc", + CIDSET_CNS1, + CIDCODING_BIG5, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfc}}}, + {"HKscs-B5", + CIDSET_CNS1, + CIDCODING_BIG5, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x88, 0xfe}}}, + {"ETen-B5", + CIDSET_CNS1, + CIDCODING_BIG5, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfe}}}, + {"ETenms-B5", + CIDSET_CNS1, + CIDCODING_BIG5, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfe}}}, + {"UniCNS-UCS2", CIDSET_CNS1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, + {"UniCNS-UTF16", CIDSET_CNS1, CIDCODING_UTF16, CPDF_CMap::TwoBytes, 0, {}}, + {"83pv-RKSJ", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x81, 0x9f}, {0xe0, 0xfc}}}, + {"90ms-RKSJ", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x81, 0x9f}, {0xe0, 0xfc}}}, + {"90msp-RKSJ", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x81, 0x9f}, {0xe0, 0xfc}}}, + {"90pv-RKSJ", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x81, 0x9f}, {0xe0, 0xfc}}}, + {"Add-RKSJ", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x81, 0x9f}, {0xe0, 0xfc}}}, + {"EUC", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x8e, 0x8e}, {0xa1, 0xfe}}}, + {"H", CIDSET_JAPAN1, CIDCODING_JIS, CPDF_CMap::TwoBytes, 1, {{0x21, 0x7e}}}, + {"V", CIDSET_JAPAN1, CIDCODING_JIS, CPDF_CMap::TwoBytes, 1, {{0x21, 0x7e}}}, + {"Ext-RKSJ", + CIDSET_JAPAN1, + CIDCODING_JIS, + CPDF_CMap::MixedTwoBytes, + 2, + {{0x81, 0x9f}, {0xe0, 0xfc}}}, + {"UniJIS-UCS2", CIDSET_JAPAN1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, + {"UniJIS-UCS2-HW", + CIDSET_JAPAN1, + CIDCODING_UCS2, + CPDF_CMap::TwoBytes, + 0, + {}}, + {"UniJIS-UTF16", + CIDSET_JAPAN1, + CIDCODING_UTF16, + CPDF_CMap::TwoBytes, + 0, + {}}, + {"KSC-EUC", + CIDSET_KOREA1, + CIDCODING_KOREA, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfe}}}, + {"KSCms-UHC", + CIDSET_KOREA1, + CIDCODING_KOREA, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x81, 0xfe}}}, + {"KSCms-UHC-HW", + CIDSET_KOREA1, + CIDCODING_KOREA, + CPDF_CMap::MixedTwoBytes, + 1, + {{0x81, 0xfe}}}, + {"KSCpc-EUC", + CIDSET_KOREA1, + CIDCODING_KOREA, + CPDF_CMap::MixedTwoBytes, + 1, + {{0xa1, 0xfd}}}, + {"UniKS-UCS2", CIDSET_KOREA1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, + {"UniKS-UTF16", CIDSET_KOREA1, CIDCODING_UTF16, CPDF_CMap::TwoBytes, 0, {}}, +}; + +int CheckFourByteCodeRange(uint8_t* codes, + int size, + const std::vector& ranges) { + int iSeg = pdfium::CollectionSize(ranges) - 1; + while (iSeg >= 0) { + if (ranges[iSeg].m_CharSize < size) { + --iSeg; + continue; + } + int iChar = 0; + while (iChar < size) { + if (codes[iChar] < ranges[iSeg].m_Lower[iChar] || + codes[iChar] > ranges[iSeg].m_Upper[iChar]) { + break; + } + ++iChar; + } + if (iChar == ranges[iSeg].m_CharSize) + return 2; + if (iChar) + return (size == ranges[iSeg].m_CharSize) ? 2 : 1; + iSeg--; + } + return 0; +} + +int GetFourByteCharSizeImpl(uint32_t charcode, + const std::vector& ranges) { + if (ranges.empty()) + return 1; + + uint8_t codes[4]; + codes[0] = codes[1] = 0x00; + codes[2] = (uint8_t)(charcode >> 8 & 0xFF); + codes[3] = (uint8_t)charcode; + int offset = 0; + int size = 4; + for (int i = 0; i < 4; ++i) { + int iSeg = pdfium::CollectionSize(ranges) - 1; + while (iSeg >= 0) { + if (ranges[iSeg].m_CharSize < size) { + --iSeg; + continue; + } + int iChar = 0; + while (iChar < size) { + if (codes[offset + iChar] < ranges[iSeg].m_Lower[iChar] || + codes[offset + iChar] > ranges[iSeg].m_Upper[iChar]) { + break; + } + ++iChar; + } + if (iChar == ranges[iSeg].m_CharSize) + return size; + --iSeg; + } + --size; + ++offset; + } + return 1; +} + +} // namespace + +CPDF_CMap::CPDF_CMap() + : m_bLoaded(false), + m_bVertical(false), + m_Charset(CIDSET_UNKNOWN), + m_CodingScheme(TwoBytes), + m_Coding(CIDCODING_UNKNOWN), + m_pEmbedMap(nullptr) {} + +CPDF_CMap::~CPDF_CMap() {} + +void CPDF_CMap::LoadPredefined(CPDF_CMapManager* pMgr, + const CFX_ByteString& bsName, + bool bPromptCJK) { + m_PredefinedCMap = bsName; + if (m_PredefinedCMap == "Identity-H" || m_PredefinedCMap == "Identity-V") { + m_Coding = CIDCODING_CID; + m_bVertical = bsName[9] == 'V'; + m_bLoaded = true; + return; + } + CFX_ByteString cmapid = m_PredefinedCMap; + m_bVertical = cmapid.Right(1) == "V"; + if (cmapid.GetLength() > 2) { + cmapid = cmapid.Left(cmapid.GetLength() - 2); + } + const PredefinedCMap* map = nullptr; + for (size_t i = 0; i < FX_ArraySize(g_PredefinedCMaps); ++i) { + if (cmapid == CFX_ByteStringC(g_PredefinedCMaps[i].m_pName)) { + map = &g_PredefinedCMaps[i]; + break; + } + } + if (!map) + return; + + m_Charset = map->m_Charset; + m_Coding = map->m_Coding; + m_CodingScheme = map->m_CodingScheme; + if (m_CodingScheme == MixedTwoBytes) { + m_MixedTwoByteLeadingBytes = std::vector(256); + for (uint32_t i = 0; i < map->m_LeadingSegCount; ++i) { + const ByteRange& seg = map->m_LeadingSegs[i]; + for (int b = seg.m_First; b <= seg.m_Last; ++b) + m_MixedTwoByteLeadingBytes[b] = true; + } + } + FPDFAPI_FindEmbeddedCMap(bsName, m_Charset, m_Coding, m_pEmbedMap); + if (!m_pEmbedMap) + return; + + m_bLoaded = true; +} + +void CPDF_CMap::LoadEmbedded(const uint8_t* pData, uint32_t size) { + m_DirectCharcodeToCIDTable = std::vector(65536); + CPDF_CMapParser parser(this); + CPDF_SimpleParser syntax(pData, size); + while (1) { + CFX_ByteStringC word = syntax.GetWord(); + if (word.IsEmpty()) { + break; + } + parser.ParseWord(word); + } + if (m_CodingScheme == MixedFourBytes && parser.HasAdditionalMappings()) { + m_AdditionalCharcodeToCIDMappings = parser.TakeAdditionalMappings(); + std::sort( + m_AdditionalCharcodeToCIDMappings.begin(), + m_AdditionalCharcodeToCIDMappings.end(), + [](const CPDF_CMap::CIDRange& arg1, const CPDF_CMap::CIDRange& arg2) { + return arg1.m_EndCode < arg2.m_EndCode; + }); + } +} + +uint16_t CPDF_CMap::CIDFromCharCode(uint32_t charcode) const { + if (m_Coding == CIDCODING_CID) + return static_cast(charcode); + + if (m_pEmbedMap) + return FPDFAPI_CIDFromCharCode(m_pEmbedMap, charcode); + + if (m_DirectCharcodeToCIDTable.empty()) + return static_cast(charcode); + + if (charcode < 0x10000) + return m_DirectCharcodeToCIDTable[charcode]; + + auto it = std::lower_bound(m_AdditionalCharcodeToCIDMappings.begin(), + m_AdditionalCharcodeToCIDMappings.end(), charcode, + [](const CPDF_CMap::CIDRange& arg, uint32_t val) { + return arg.m_EndCode < val; + }); + if (it == m_AdditionalCharcodeToCIDMappings.end() || + it->m_StartCode > charcode) { + return 0; + } + return it->m_StartCID + charcode - it->m_StartCode; +} + +uint32_t CPDF_CMap::GetNextChar(const char* pString, + int nStrLen, + int& offset) const { + auto* pBytes = reinterpret_cast(pString); + switch (m_CodingScheme) { + case OneByte: { + return pBytes[offset++]; + } + case TwoBytes: { + uint8_t byte1 = pBytes[offset++]; + return 256 * byte1 + pBytes[offset++]; + } + case MixedTwoBytes: { + uint8_t byte1 = pBytes[offset++]; + if (!m_MixedTwoByteLeadingBytes[byte1]) + return byte1; + return 256 * byte1 + pBytes[offset++]; + } + case MixedFourBytes: { + uint8_t codes[4]; + int char_size = 1; + codes[0] = pBytes[offset++]; + while (1) { + int ret = CheckFourByteCodeRange(codes, char_size, + m_MixedFourByteLeadingRanges); + if (ret == 0) + return 0; + if (ret == 2) { + uint32_t charcode = 0; + for (int i = 0; i < char_size; i++) + charcode = (charcode << 8) + codes[i]; + return charcode; + } + if (char_size == 4 || offset == nStrLen) + return 0; + codes[char_size++] = pBytes[offset++]; + } + break; + } + } + return 0; +} + +int CPDF_CMap::GetCharSize(uint32_t charcode) const { + switch (m_CodingScheme) { + case OneByte: + return 1; + case TwoBytes: + return 2; + case MixedTwoBytes: + if (charcode < 0x100) + return 1; + return 2; + case MixedFourBytes: + if (charcode < 0x100) + return 1; + if (charcode < 0x10000) + return 2; + if (charcode < 0x1000000) + return 3; + return 4; + } + return 1; +} + +int CPDF_CMap::CountChar(const char* pString, int size) const { + switch (m_CodingScheme) { + case OneByte: + return size; + case TwoBytes: + return (size + 1) / 2; + case MixedTwoBytes: { + int count = 0; + for (int i = 0; i < size; i++) { + count++; + if (m_MixedTwoByteLeadingBytes[reinterpret_cast( + pString)[i]]) { + i++; + } + } + return count; + } + case MixedFourBytes: { + int count = 0, offset = 0; + while (offset < size) { + GetNextChar(pString, size, offset); + count++; + } + return count; + } + } + return size; +} + +int CPDF_CMap::AppendChar(char* str, uint32_t charcode) const { + switch (m_CodingScheme) { + case OneByte: + str[0] = (uint8_t)charcode; + return 1; + case TwoBytes: + str[0] = (uint8_t)(charcode / 256); + str[1] = (uint8_t)(charcode % 256); + return 2; + case MixedTwoBytes: + if (charcode < 0x100 && !m_MixedTwoByteLeadingBytes[(uint8_t)charcode]) { + str[0] = (uint8_t)charcode; + return 1; + } + str[0] = (uint8_t)(charcode >> 8); + str[1] = (uint8_t)charcode; + return 2; + case MixedFourBytes: + if (charcode < 0x100) { + int iSize = + GetFourByteCharSizeImpl(charcode, m_MixedFourByteLeadingRanges); + if (iSize == 0) + iSize = 1; + str[iSize - 1] = (uint8_t)charcode; + if (iSize > 1) + memset(str, 0, iSize - 1); + return iSize; + } + if (charcode < 0x10000) { + str[0] = (uint8_t)(charcode >> 8); + str[1] = (uint8_t)charcode; + return 2; + } + if (charcode < 0x1000000) { + str[0] = (uint8_t)(charcode >> 16); + str[1] = (uint8_t)(charcode >> 8); + str[2] = (uint8_t)charcode; + return 3; + } + str[0] = (uint8_t)(charcode >> 24); + str[1] = (uint8_t)(charcode >> 16); + str[2] = (uint8_t)(charcode >> 8); + str[3] = (uint8_t)charcode; + return 4; + } + return 0; +} diff --git a/core/fpdfapi/font/cpdf_cmap.h b/core/fpdfapi/font/cpdf_cmap.h new file mode 100644 index 0000000000..ab495efbfc --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmap.h @@ -0,0 +1,87 @@ +// Copyright 2017 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 + +#ifndef CORE_FPDFAPI_FONT_CPDF_CMAP_H_ +#define CORE_FPDFAPI_FONT_CPDF_CMAP_H_ + +#include + +#include "core/fpdfapi/font/cpdf_cidfont.h" +#include "core/fxcrt/cfx_retain_ptr.h" +#include "core/fxcrt/fx_basic.h" + +class CPDF_CMapManager; +struct FXCMAP_CMap; + +enum CIDCoding : uint8_t { + CIDCODING_UNKNOWN = 0, + CIDCODING_GB, + CIDCODING_BIG5, + CIDCODING_JIS, + CIDCODING_KOREA, + CIDCODING_UCS2, + CIDCODING_CID, + CIDCODING_UTF16, +}; + +class CPDF_CMap : public CFX_Retainable { + public: + enum CodingScheme : uint8_t { + OneByte, + TwoBytes, + MixedTwoBytes, + MixedFourBytes + }; + + struct CodeRange { + int m_CharSize; + uint8_t m_Lower[4]; + uint8_t m_Upper[4]; + }; + + struct CIDRange { + uint32_t m_StartCode; + uint32_t m_EndCode; + uint16_t m_StartCID; + }; + + template + friend CFX_RetainPtr pdfium::MakeRetain(Args&&... args); + + void LoadPredefined(CPDF_CMapManager* pMgr, + const CFX_ByteString& name, + bool bPromptCJK); + void LoadEmbedded(const uint8_t* pData, uint32_t dwSize); + + bool IsLoaded() const { return m_bLoaded; } + bool IsVertWriting() const { return m_bVertical; } + uint16_t CIDFromCharCode(uint32_t charcode) const; + int GetCharSize(uint32_t charcode) const; + uint32_t GetNextChar(const char* pString, int nStrLen, int& offset) const; + int CountChar(const char* pString, int size) const; + int AppendChar(char* str, uint32_t charcode) const; + + private: + friend class CPDF_CMapParser; + friend class CPDF_CIDFont; + + CPDF_CMap(); + ~CPDF_CMap() override; + + CFX_ByteString m_PredefinedCMap; + bool m_bLoaded; + bool m_bVertical; + CIDSet m_Charset; + CodingScheme m_CodingScheme; + int m_Coding; + std::vector m_MixedTwoByteLeadingBytes; + std::vector m_MixedFourByteLeadingRanges; + std::vector m_DirectCharcodeToCIDTable; + std::vector m_AdditionalCharcodeToCIDMappings; + const FXCMAP_CMap* m_pEmbedMap; +}; + +#endif // CORE_FPDFAPI_FONT_CPDF_CMAP_H_ diff --git a/core/fpdfapi/font/cpdf_cmapmanager.cpp b/core/fpdfapi/font/cpdf_cmapmanager.cpp new file mode 100644 index 0000000000..040af5556a --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmapmanager.cpp @@ -0,0 +1,59 @@ +// Copyright 2017 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/cpdf_cmapmanager.h" + +#include + +#include "core/fpdfapi/font/cpdf_cid2unicodemap.h" +#include "core/fpdfapi/font/cpdf_cmap.h" +#include "third_party/base/stl_util.h" + +CPDF_CMapManager::CPDF_CMapManager() {} + +CPDF_CMapManager::~CPDF_CMapManager() {} + +CFX_RetainPtr CPDF_CMapManager::GetPredefinedCMap( + const CFX_ByteString& name, + bool bPromptCJK) { + auto it = m_CMaps.find(name); + if (it != m_CMaps.end()) + return it->second; + + CFX_RetainPtr pCMap = LoadPredefinedCMap(name, bPromptCJK); + if (!name.IsEmpty()) + m_CMaps[name] = pCMap; + + return pCMap; +} + +CFX_RetainPtr CPDF_CMapManager::LoadPredefinedCMap( + const CFX_ByteString& name, + bool bPromptCJK) { + const char* pname = name.c_str(); + if (*pname == '/') + pname++; + + auto pCMap = pdfium::MakeRetain(); + pCMap->LoadPredefined(this, pname, bPromptCJK); + return pCMap; +} + +CPDF_CID2UnicodeMap* CPDF_CMapManager::GetCID2UnicodeMap(CIDSet charset, + bool bPromptCJK) { + if (!m_CID2UnicodeMaps[charset]) + m_CID2UnicodeMaps[charset] = LoadCID2UnicodeMap(charset, bPromptCJK); + + return m_CID2UnicodeMaps[charset].get(); +} + +std::unique_ptr CPDF_CMapManager::LoadCID2UnicodeMap( + CIDSet charset, + bool bPromptCJK) { + auto pMap = pdfium::MakeUnique(); + pMap->Load(this, charset, bPromptCJK); + return pMap; +} diff --git a/core/fpdfapi/font/cpdf_cmapmanager.h b/core/fpdfapi/font/cpdf_cmapmanager.h new file mode 100644 index 0000000000..1bc1c6f839 --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmapmanager.h @@ -0,0 +1,36 @@ +// Copyright 2017 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 + +#ifndef CORE_FPDFAPI_FONT_CPDF_CMAPMANAGER_H_ +#define CORE_FPDFAPI_FONT_CPDF_CMAPMANAGER_H_ + +#include +#include + +#include "core/fpdfapi/font/cpdf_cidfont.h" +#include "core/fxcrt/cfx_bytestring.h" +#include "core/fxcrt/cfx_retain_ptr.h" + +class CPDF_CMapManager { + public: + CPDF_CMapManager(); + ~CPDF_CMapManager(); + + CFX_RetainPtr GetPredefinedCMap(const CFX_ByteString& name, + bool bPromptCJK); + CPDF_CID2UnicodeMap* GetCID2UnicodeMap(CIDSet charset, bool bPromptCJK); + + private: + CFX_RetainPtr LoadPredefinedCMap(const CFX_ByteString& name, + bool bPromptCJK); + std::unique_ptr LoadCID2UnicodeMap(CIDSet charset, + bool bPromptCJK); + + std::map> m_CMaps; + std::unique_ptr m_CID2UnicodeMaps[6]; +}; + +#endif // CORE_FPDFAPI_FONT_CPDF_CMAPMANAGER_H_ diff --git a/core/fpdfapi/font/cpdf_cmapparser.cpp b/core/fpdfapi/font/cpdf_cmapparser.cpp new file mode 100644 index 0000000000..0f9bca6018 --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmapparser.cpp @@ -0,0 +1,204 @@ +// 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/cpdf_cmapparser.h" + +#include + +#include "core/fpdfapi/cmaps/cmap_int.h" +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fpdfapi/page/cpdf_pagemodule.h" +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_simple_parser.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxge/fx_freetype.h" +#include "third_party/base/logging.h" +#include "third_party/base/stl_util.h" + +namespace { + +const char* const g_CharsetNames[CIDSET_NUM_SETS] = {nullptr, "GB1", "CNS1", + "Japan1", "Korea1", "UCS"}; + +CIDSet CIDSetFromSizeT(size_t index) { + if (index >= CIDSET_NUM_SETS) { + NOTREACHED(); + return CIDSET_UNKNOWN; + } + return static_cast(index); +} + +CFX_ByteStringC CMap_GetString(const CFX_ByteStringC& word) { + if (word.GetLength() <= 2) + return CFX_ByteStringC(); + return CFX_ByteStringC(&word[1], word.GetLength() - 2); +} + +} // namespace + +CPDF_CMapParser::CPDF_CMapParser(CPDF_CMap* pCMap) + : m_pCMap(pCMap), m_Status(0), m_CodeSeq(0) {} + +CPDF_CMapParser::~CPDF_CMapParser() {} + +void CPDF_CMapParser::ParseWord(const CFX_ByteStringC& word) { + if (word.IsEmpty()) { + return; + } + if (word == "begincidchar") { + m_Status = 1; + m_CodeSeq = 0; + } else if (word == "begincidrange") { + m_Status = 2; + m_CodeSeq = 0; + } else if (word == "endcidrange" || word == "endcidchar") { + m_Status = 0; + } else if (word == "/WMode") { + m_Status = 6; + } else if (word == "/Registry") { + m_Status = 3; + } else if (word == "/Ordering") { + m_Status = 4; + } else if (word == "/Supplement") { + m_Status = 5; + } else if (word == "begincodespacerange") { + m_Status = 7; + m_CodeSeq = 0; + } else if (word == "usecmap") { + } else if (m_Status == 1 || m_Status == 2) { + m_CodePoints[m_CodeSeq] = CMap_GetCode(word); + m_CodeSeq++; + uint32_t StartCode, EndCode; + uint16_t StartCID; + if (m_Status == 1) { + if (m_CodeSeq < 2) { + return; + } + EndCode = StartCode = m_CodePoints[0]; + StartCID = (uint16_t)m_CodePoints[1]; + } else { + if (m_CodeSeq < 3) { + return; + } + StartCode = m_CodePoints[0]; + EndCode = m_CodePoints[1]; + StartCID = (uint16_t)m_CodePoints[2]; + } + if (EndCode < 0x10000) { + for (uint32_t code = StartCode; code <= EndCode; code++) { + m_pCMap->m_DirectCharcodeToCIDTable[code] = + static_cast(StartCID + code - StartCode); + } + } else { + m_AdditionalCharcodeToCIDMappings.push_back( + {StartCode, EndCode, StartCID}); + } + m_CodeSeq = 0; + } else if (m_Status == 3) { + m_Status = 0; + } else if (m_Status == 4) { + m_pCMap->m_Charset = CharsetFromOrdering(CMap_GetString(word)); + m_Status = 0; + } else if (m_Status == 5) { + m_Status = 0; + } else if (m_Status == 6) { + m_pCMap->m_bVertical = CMap_GetCode(word) != 0; + m_Status = 0; + } else if (m_Status == 7) { + if (word == "endcodespacerange") { + uint32_t nSegs = pdfium::CollectionSize(m_CodeRanges); + if (nSegs > 1) { + m_pCMap->m_CodingScheme = CPDF_CMap::MixedFourBytes; + m_pCMap->m_MixedFourByteLeadingRanges = m_CodeRanges; + } else if (nSegs == 1) { + m_pCMap->m_CodingScheme = (m_CodeRanges[0].m_CharSize == 2) + ? CPDF_CMap::TwoBytes + : CPDF_CMap::OneByte; + } + m_Status = 0; + } else { + if (word.GetLength() == 0 || word.GetAt(0) != '<') { + return; + } + if (m_CodeSeq % 2) { + CPDF_CMap::CodeRange range; + if (CMap_GetCodeRange(range, m_LastWord.AsStringC(), word)) + m_CodeRanges.push_back(range); + } + m_CodeSeq++; + } + } + m_LastWord = word; +} + +// Static. +uint32_t CPDF_CMapParser::CMap_GetCode(const CFX_ByteStringC& word) { + pdfium::base::CheckedNumeric num = 0; + if (word.GetAt(0) == '<') { + for (int i = 1; i < word.GetLength() && std::isxdigit(word.GetAt(i)); ++i) { + num = num * 16 + FXSYS_HexCharToInt(word.GetAt(i)); + if (!num.IsValid()) + return 0; + } + return num.ValueOrDie(); + } + + for (int i = 0; i < word.GetLength() && std::isdigit(word.GetAt(i)); ++i) { + num = + num * 10 + FXSYS_DecimalCharToInt(static_cast(word.GetAt(i))); + if (!num.IsValid()) + return 0; + } + return num.ValueOrDie(); +} + +// Static. +bool CPDF_CMapParser::CMap_GetCodeRange(CPDF_CMap::CodeRange& range, + const CFX_ByteStringC& first, + const CFX_ByteStringC& second) { + if (first.GetLength() == 0 || first.GetAt(0) != '<') + return false; + + int i; + for (i = 1; i < first.GetLength(); ++i) { + if (first.GetAt(i) == '>') { + break; + } + } + range.m_CharSize = (i - 1) / 2; + if (range.m_CharSize > 4) + return false; + + for (i = 0; i < range.m_CharSize; ++i) { + uint8_t digit1 = first.GetAt(i * 2 + 1); + uint8_t digit2 = first.GetAt(i * 2 + 2); + range.m_Lower[i] = + FXSYS_HexCharToInt(digit1) * 16 + FXSYS_HexCharToInt(digit2); + } + + uint32_t size = second.GetLength(); + for (i = 0; i < range.m_CharSize; ++i) { + uint8_t digit1 = ((uint32_t)i * 2 + 1 < size) + ? second.GetAt((FX_STRSIZE)i * 2 + 1) + : '0'; + uint8_t digit2 = ((uint32_t)i * 2 + 2 < size) + ? second.GetAt((FX_STRSIZE)i * 2 + 2) + : '0'; + range.m_Upper[i] = + FXSYS_HexCharToInt(digit1) * 16 + FXSYS_HexCharToInt(digit2); + } + return true; +} + +// static +CIDSet CPDF_CMapParser::CharsetFromOrdering(const CFX_ByteStringC& ordering) { + for (size_t charset = 1; charset < FX_ArraySize(g_CharsetNames); ++charset) { + if (ordering == g_CharsetNames[charset]) + return CIDSetFromSizeT(charset); + } + return CIDSET_UNKNOWN; +} diff --git a/core/fpdfapi/font/cpdf_cmapparser.h b/core/fpdfapi/font/cpdf_cmapparser.h new file mode 100644 index 0000000000..184ef75043 --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmapparser.h @@ -0,0 +1,52 @@ +// Copyright 2017 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 + +#ifndef CORE_FPDFAPI_FONT_CPDF_CMAPPARSER_H_ +#define CORE_FPDFAPI_FONT_CPDF_CMAPPARSER_H_ + +#include +#include +#include + +#include "core/fpdfapi/font/cpdf_cidfont.h" +#include "core/fpdfapi/font/cpdf_cmap.h" +#include "core/fxcrt/cfx_unowned_ptr.h" +#include "core/fxcrt/fx_basic.h" + +class CPDF_CMapParser { + public: + explicit CPDF_CMapParser(CPDF_CMap* pMap); + ~CPDF_CMapParser(); + + void ParseWord(const CFX_ByteStringC& str); + bool HasAdditionalMappings() const { + return !m_AdditionalCharcodeToCIDMappings.empty(); + } + std::vector TakeAdditionalMappings() { + return std::move(m_AdditionalCharcodeToCIDMappings); + } + + static CIDSet CharsetFromOrdering(const CFX_ByteStringC& ordering); + + private: + friend class cpdf_cmapparser_CMap_GetCode_Test; + friend class cpdf_cmapparser_CMap_GetCodeRange_Test; + + static uint32_t CMap_GetCode(const CFX_ByteStringC& word); + static bool CMap_GetCodeRange(CPDF_CMap::CodeRange& range, + const CFX_ByteStringC& first, + const CFX_ByteStringC& second); + + CFX_UnownedPtr const m_pCMap; + int m_Status; + int m_CodeSeq; + uint32_t m_CodePoints[4]; + std::vector m_CodeRanges; + std::vector m_AdditionalCharcodeToCIDMappings; + CFX_ByteString m_LastWord; +}; + +#endif // CORE_FPDFAPI_FONT_CPDF_CMAPPARSER_H_ diff --git a/core/fpdfapi/font/cpdf_cmapparser_unittest.cpp b/core/fpdfapi/font/cpdf_cmapparser_unittest.cpp new file mode 100644 index 0000000000..0d55aa274d --- /dev/null +++ b/core/fpdfapi/font/cpdf_cmapparser_unittest.cpp @@ -0,0 +1,71 @@ +// Copyright 2015 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. + +#include "core/fpdfapi/font/cpdf_cmapparser.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +bool uint_ranges_equal(uint8_t* a, uint8_t* b, size_t count) { + for (size_t i = 0; i < count; ++i) { + if (a[i] != b[i]) + return false; + } + return true; +} + +} // namespace + +TEST(cpdf_cmapparser, CMap_GetCode) { + EXPECT_EQ(0u, CPDF_CMapParser::CMap_GetCode("")); + EXPECT_EQ(0u, CPDF_CMapParser::CMap_GetCode("<")); + EXPECT_EQ(194u, CPDF_CMapParser::CMap_GetCode("", "")); + EXPECT_EQ(5, range.m_CharSize); + + EXPECT_TRUE( + CPDF_CMapParser::CMap_GetCodeRange(range, "<12345678>", "<87654321>")); + EXPECT_EQ(4, range.m_CharSize); + { + uint8_t lower[4] = {18, 52, 86, 120}; + uint8_t upper[4] = {135, 101, 67, 33}; + EXPECT_TRUE(uint_ranges_equal(lower, range.m_Lower, range.m_CharSize)); + EXPECT_TRUE(uint_ranges_equal(upper, range.m_Upper, range.m_CharSize)); + } + + // Hex characters + EXPECT_TRUE(CPDF_CMapParser::CMap_GetCodeRange(range, "", "")); + EXPECT_EQ(1, range.m_CharSize); + EXPECT_EQ(161, range.m_Lower[0]); + EXPECT_EQ(243, range.m_Upper[0]); + + // The second string should return 0's if it is shorter + EXPECT_TRUE(CPDF_CMapParser::CMap_GetCodeRange(range, "", "")); + EXPECT_EQ(1, range.m_CharSize); + EXPECT_EQ(161, range.m_Lower[0]); + EXPECT_EQ(0, range.m_Upper[0]); +} diff --git a/core/fpdfapi/font/cpdf_font.cpp b/core/fpdfapi/font/cpdf_font.cpp index 1a7fb60b0b..1faa4ec4be 100644 --- a/core/fpdfapi/font/cpdf_font.cpp +++ b/core/fpdfapi/font/cpdf_font.cpp @@ -15,7 +15,6 @@ #include "core/fpdfapi/font/cpdf_truetypefont.h" #include "core/fpdfapi/font/cpdf_type1font.h" #include "core/fpdfapi/font/cpdf_type3font.h" -#include "core/fpdfapi/font/font_int.h" #include "core/fpdfapi/page/cpdf_docpagedata.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" #include "core/fpdfapi/parser/cpdf_array.h" @@ -477,3 +476,27 @@ CFX_Font* CPDF_Font::GetFontFallback(int position) { return nullptr; return m_FontFallbacks[position].get(); } + +// static +int CPDF_Font::TT2PDF(int m, FXFT_Face face) { + int upm = FXFT_Get_Face_UnitsPerEM(face); + if (upm == 0) + return m; + return pdfium::base::checked_cast( + (static_cast(m) * 1000 + upm / 2) / upm); +} + +// static +bool CPDF_Font::FT_UseTTCharmap(FXFT_Face face, + int platform_id, + int encoding_id) { + auto** pCharMap = FXFT_Get_Face_Charmaps(face); + for (int i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) { + if (FXFT_Get_Charmap_PlatformID(pCharMap[i]) == platform_id && + FXFT_Get_Charmap_EncodingID(pCharMap[i]) == encoding_id) { + FXFT_Set_Charmap(face, pCharMap[i]); + return true; + } + } + return false; +} diff --git a/core/fpdfapi/font/cpdf_font.h b/core/fpdfapi/font/cpdf_font.h index c8e65e26a5..1fef77b322 100644 --- a/core/fpdfapi/font/cpdf_font.h +++ b/core/fpdfapi/font/cpdf_font.h @@ -10,6 +10,7 @@ #include #include +#include "core/fpdfapi/font/cpdf_tounicodemap.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" #include "core/fxcrt/cfx_unowned_ptr.h" #include "core/fxcrt/fx_string.h" @@ -87,6 +88,9 @@ class CPDF_Font { protected: CPDF_Font(); + static int TT2PDF(int m, FXFT_Face face); + static bool FT_UseTTCharmap(FXFT_Face face, int platform_id, int encoding_id); + virtual bool Load() = 0; void LoadUnicodeMap() const; // logically const only. diff --git a/core/fpdfapi/font/cpdf_fontglobals.cpp b/core/fpdfapi/font/cpdf_fontglobals.cpp new file mode 100644 index 0000000000..ddf87b1c09 --- /dev/null +++ b/core/fpdfapi/font/cpdf_fontglobals.cpp @@ -0,0 +1,39 @@ +// Copyright 2017 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/cpdf_fontglobals.h" + +#include + +#include "core/fpdfapi/parser/cpdf_document.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +CPDF_FontGlobals::CPDF_FontGlobals() { + memset(m_EmbeddedCharsets, 0, sizeof(m_EmbeddedCharsets)); + memset(m_EmbeddedToUnicodes, 0, sizeof(m_EmbeddedToUnicodes)); +} + +CPDF_FontGlobals::~CPDF_FontGlobals() {} + +CPDF_Font* CPDF_FontGlobals::Find(CPDF_Document* pDoc, uint32_t index) { + auto it = m_StockMap.find(pDoc); + if (it == m_StockMap.end()) + return nullptr; + return it->second ? it->second->GetFont(index) : nullptr; +} + +CPDF_Font* CPDF_FontGlobals::Set(CPDF_Document* pDoc, + uint32_t index, + std::unique_ptr pFont) { + if (!pdfium::ContainsKey(m_StockMap, pDoc)) + m_StockMap[pDoc] = pdfium::MakeUnique(); + return m_StockMap[pDoc]->SetFont(index, std::move(pFont)); +} + +void CPDF_FontGlobals::Clear(CPDF_Document* pDoc) { + m_StockMap.erase(pDoc); +} diff --git a/core/fpdfapi/font/cpdf_fontglobals.h b/core/fpdfapi/font/cpdf_fontglobals.h new file mode 100644 index 0000000000..b930aa2905 --- /dev/null +++ b/core/fpdfapi/font/cpdf_fontglobals.h @@ -0,0 +1,45 @@ +// Copyright 2017 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 + +#ifndef CORE_FPDFAPI_FONT_CPDF_FONTGLOBALS_H_ +#define CORE_FPDFAPI_FONT_CPDF_FONTGLOBALS_H_ + +#include +#include + +#include "core/fpdfapi/cmaps/cmap_int.h" +#include "core/fpdfapi/font/cfx_stockfontarray.h" +#include "core/fpdfapi/font/cpdf_cmapmanager.h" +#include "core/fxcrt/fx_basic.h" + +class CPDF_FontGlobals { + public: + CPDF_FontGlobals(); + ~CPDF_FontGlobals(); + + void Clear(CPDF_Document* pDoc); + CPDF_Font* Find(CPDF_Document* pDoc, uint32_t index); + + // Takes ownership of |pFont|, returns unowned pointer to it. + CPDF_Font* Set(CPDF_Document* key, + uint32_t index, + std::unique_ptr pFont); + + CPDF_CMapManager m_CMapManager; + struct { + CFX_UnownedPtr m_pMapList; + uint32_t m_Count; + } m_EmbeddedCharsets[CIDSET_NUM_SETS]; + struct { + const uint16_t* m_pMap; + uint32_t m_Count; + } m_EmbeddedToUnicodes[CIDSET_NUM_SETS]; + + private: + std::map> m_StockMap; +}; + +#endif // CORE_FPDFAPI_FONT_CPDF_FONTGLOBALS_H_ diff --git a/core/fpdfapi/font/cpdf_simplefont.cpp b/core/fpdfapi/font/cpdf_simplefont.cpp index cb8f00a98a..ebf2cb65c7 100644 --- a/core/fpdfapi/font/cpdf_simplefont.cpp +++ b/core/fpdfapi/font/cpdf_simplefont.cpp @@ -6,7 +6,6 @@ #include "core/fpdfapi/font/cpdf_simplefont.h" -#include "core/fpdfapi/font/font_int.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fxge/fx_freetype.h" diff --git a/core/fpdfapi/font/cpdf_tounicodemap.cpp b/core/fpdfapi/font/cpdf_tounicodemap.cpp new file mode 100644 index 0000000000..8989f0be37 --- /dev/null +++ b/core/fpdfapi/font/cpdf_tounicodemap.cpp @@ -0,0 +1,233 @@ +// Copyright 2017 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/cpdf_tounicodemap.h" + +#include "core/fpdfapi/cpdf_modulemgr.h" +#include "core/fpdfapi/font/cpdf_cid2unicodemap.h" +#include "core/fpdfapi/page/cpdf_pagemodule.h" +#include "core/fpdfapi/parser/cpdf_simple_parser.h" +#include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/fx_safe_types.h" +#include "third_party/base/numerics/safe_conversions.h" + +CFX_WideString CPDF_ToUnicodeMap::Lookup(uint32_t charcode) const { + auto it = m_Map.find(charcode); + if (it != m_Map.end()) { + uint32_t value = it->second; + wchar_t unicode = (wchar_t)(value & 0xffff); + if (unicode != 0xffff) { + return unicode; + } + const wchar_t* buf = m_MultiCharBuf.GetBuffer(); + uint32_t buf_len = m_MultiCharBuf.GetLength(); + if (!buf || buf_len == 0) { + return CFX_WideString(); + } + uint32_t index = value >> 16; + if (index >= buf_len) { + return CFX_WideString(); + } + uint32_t len = buf[index]; + if (index + len < index || index + len >= buf_len) { + return CFX_WideString(); + } + return CFX_WideString(buf + index + 1, len); + } + if (m_pBaseMap) { + return m_pBaseMap->UnicodeFromCID((uint16_t)charcode); + } + return CFX_WideString(); +} + +uint32_t CPDF_ToUnicodeMap::ReverseLookup(wchar_t unicode) const { + for (const auto& pair : m_Map) { + if (pair.second == static_cast(unicode)) + return pair.first; + } + return 0; +} + +// Static. +uint32_t CPDF_ToUnicodeMap::StringToCode(const CFX_ByteStringC& str) { + int len = str.GetLength(); + if (len == 0) + return 0; + + uint32_t result = 0; + if (str[0] == '<') { + for (int i = 1; i < len && std::isxdigit(str[i]); ++i) + result = result * 16 + FXSYS_HexCharToInt(str.CharAt(i)); + return result; + } + + for (int i = 0; i < len && std::isdigit(str[i]); ++i) + result = result * 10 + FXSYS_DecimalCharToInt(str.CharAt(i)); + + return result; +} + +static CFX_WideString StringDataAdd(CFX_WideString str) { + CFX_WideString ret; + int len = str.GetLength(); + wchar_t value = 1; + for (int i = len - 1; i >= 0; --i) { + wchar_t ch = str[i] + value; + if (ch < str[i]) { + ret.Insert(0, 0); + } else { + ret.Insert(0, ch); + value = 0; + } + } + if (value) { + ret.Insert(0, value); + } + return ret; +} + +// Static. +CFX_WideString CPDF_ToUnicodeMap::StringToWideString( + const CFX_ByteStringC& str) { + int len = str.GetLength(); + if (len == 0) + return CFX_WideString(); + + CFX_WideString result; + if (str[0] == '<') { + int byte_pos = 0; + wchar_t ch = 0; + for (int i = 1; i < len && std::isxdigit(str[i]); ++i) { + ch = ch * 16 + FXSYS_HexCharToInt(str[i]); + byte_pos++; + if (byte_pos == 4) { + result += ch; + byte_pos = 0; + ch = 0; + } + } + return result; + } + return result; +} + +CPDF_ToUnicodeMap::CPDF_ToUnicodeMap() : m_pBaseMap(nullptr) {} + +CPDF_ToUnicodeMap::~CPDF_ToUnicodeMap() {} + +uint32_t CPDF_ToUnicodeMap::GetUnicode() { + FX_SAFE_UINT32 uni = m_MultiCharBuf.GetLength(); + uni = uni * 0x10000 + 0xffff; + return uni.ValueOrDefault(0); +} + +void CPDF_ToUnicodeMap::Load(CPDF_Stream* pStream) { + CIDSet cid_set = CIDSET_UNKNOWN; + auto pAcc = pdfium::MakeRetain(pStream); + pAcc->LoadAllData(false); + CPDF_SimpleParser parser(pAcc->GetData(), pAcc->GetSize()); + while (1) { + CFX_ByteStringC word = parser.GetWord(); + if (word.IsEmpty()) { + break; + } + if (word == "beginbfchar") { + while (1) { + word = parser.GetWord(); + if (word.IsEmpty() || word == "endbfchar") { + break; + } + uint32_t srccode = StringToCode(word); + word = parser.GetWord(); + CFX_WideString destcode = StringToWideString(word); + int len = destcode.GetLength(); + if (len == 0) { + continue; + } + if (len == 1) { + m_Map[srccode] = destcode.GetAt(0); + } else { + m_Map[srccode] = GetUnicode(); + m_MultiCharBuf.AppendChar(destcode.GetLength()); + m_MultiCharBuf << destcode; + } + } + } else if (word == "beginbfrange") { + while (1) { + CFX_ByteString low, high; + low = parser.GetWord(); + if (low.IsEmpty() || low == "endbfrange") { + break; + } + high = parser.GetWord(); + uint32_t lowcode = StringToCode(low.AsStringC()); + uint32_t highcode = + (lowcode & 0xffffff00) | (StringToCode(high.AsStringC()) & 0xff); + if (highcode == (uint32_t)-1) { + break; + } + CFX_ByteString start(parser.GetWord()); + if (start == "[") { + for (uint32_t code = lowcode; code <= highcode; code++) { + CFX_ByteString dest(parser.GetWord()); + CFX_WideString destcode = StringToWideString(dest.AsStringC()); + int len = destcode.GetLength(); + if (len == 0) { + continue; + } + if (len == 1) { + m_Map[code] = destcode.GetAt(0); + } else { + m_Map[code] = GetUnicode(); + m_MultiCharBuf.AppendChar(destcode.GetLength()); + m_MultiCharBuf << destcode; + } + } + parser.GetWord(); + } else { + CFX_WideString destcode = StringToWideString(start.AsStringC()); + int len = destcode.GetLength(); + uint32_t value = 0; + if (len == 1) { + value = StringToCode(start.AsStringC()); + for (uint32_t code = lowcode; code <= highcode; code++) { + m_Map[code] = value++; + } + } else { + for (uint32_t code = lowcode; code <= highcode; code++) { + CFX_WideString retcode; + if (code == lowcode) { + retcode = destcode; + } else { + retcode = StringDataAdd(destcode); + } + m_Map[code] = GetUnicode(); + m_MultiCharBuf.AppendChar(retcode.GetLength()); + m_MultiCharBuf << retcode; + destcode = retcode; + } + } + } + } + } else if (word == "/Adobe-Korea1-UCS2") { + cid_set = CIDSET_KOREA1; + } else if (word == "/Adobe-Japan1-UCS2") { + cid_set = CIDSET_JAPAN1; + } else if (word == "/Adobe-CNS1-UCS2") { + cid_set = CIDSET_CNS1; + } else if (word == "/Adobe-GB1-UCS2") { + cid_set = CIDSET_GB1; + } + } + if (cid_set) { + m_pBaseMap = CPDF_ModuleMgr::Get() + ->GetPageModule() + ->GetFontGlobals() + ->m_CMapManager.GetCID2UnicodeMap(cid_set, false); + } else { + m_pBaseMap = nullptr; + } +} diff --git a/core/fpdfapi/font/cpdf_tounicodemap.h b/core/fpdfapi/font/cpdf_tounicodemap.h new file mode 100644 index 0000000000..83db6e3030 --- /dev/null +++ b/core/fpdfapi/font/cpdf_tounicodemap.h @@ -0,0 +1,42 @@ +// Copyright 2017 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 + +#ifndef CORE_FPDFAPI_FONT_CPDF_TOUNICODEMAP_H_ +#define CORE_FPDFAPI_FONT_CPDF_TOUNICODEMAP_H_ + +#include + +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fxcrt/cfx_unowned_ptr.h" +#include "core/fxcrt/fx_basic.h" + +class CPDF_CID2UnicodeMap; + +class CPDF_ToUnicodeMap { + public: + CPDF_ToUnicodeMap(); + ~CPDF_ToUnicodeMap(); + + void Load(CPDF_Stream* pStream); + + CFX_WideString Lookup(uint32_t charcode) const; + uint32_t ReverseLookup(wchar_t unicode) const; + + private: + friend class cpdf_tounicodemap_StringToCode_Test; + friend class cpdf_tounicodemap_StringToWideString_Test; + + static uint32_t StringToCode(const CFX_ByteStringC& str); + static CFX_WideString StringToWideString(const CFX_ByteStringC& str); + + uint32_t GetUnicode(); + + std::map m_Map; + CFX_UnownedPtr m_pBaseMap; + CFX_WideTextBuf m_MultiCharBuf; +}; + +#endif // CORE_FPDFAPI_FONT_CPDF_TOUNICODEMAP_H_ diff --git a/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp new file mode 100644 index 0000000000..299f4d9b1e --- /dev/null +++ b/core/fpdfapi/font/cpdf_tounicodemap_unittest.cpp @@ -0,0 +1,31 @@ +// Copyright 2015 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. + +#include "core/fpdfapi/font/cpdf_tounicodemap.h" + +#include "testing/gtest/include/gtest/gtest.h" + +TEST(cpdf_tounicodemap, StringToCode) { + EXPECT_EQ(0u, CPDF_ToUnicodeMap::StringToCode("")); + EXPECT_EQ(194u, CPDF_ToUnicodeMap::StringToCode(" -#include -#include -#include - -#include "core/fpdfapi/font/cpdf_cidfont.h" -#include "core/fxcrt/cfx_retain_ptr.h" -#include "core/fxcrt/cfx_unowned_ptr.h" -#include "core/fxcrt/fx_basic.h" - -class CPDF_CID2UnicodeMap; -class CPDF_CMapManager; -class CPDF_Font; -class CPDF_Stream; -struct FXCMAP_CMap; - -using FXFT_Library = void*; - -int TT2PDF(int m, FXFT_Face face); -bool FT_UseTTCharmap(FXFT_Face face, int platform_id, int encoding_id); -CIDSet CharsetFromOrdering(const CFX_ByteStringC& ordering); - -class CFX_StockFontArray { - public: - CFX_StockFontArray(); - ~CFX_StockFontArray(); - - // Takes ownership of |pFont|, returns unowned pointer to it. - CPDF_Font* SetFont(uint32_t index, std::unique_ptr pFont); - CPDF_Font* GetFont(uint32_t index) const; - - private: - std::unique_ptr m_StockFonts[14]; -}; - -enum CIDCoding : uint8_t { - CIDCODING_UNKNOWN = 0, - CIDCODING_GB, - CIDCODING_BIG5, - CIDCODING_JIS, - CIDCODING_KOREA, - CIDCODING_UCS2, - CIDCODING_CID, - CIDCODING_UTF16, -}; - -class CPDF_CMap : public CFX_Retainable { - public: - enum CodingScheme : uint8_t { - OneByte, - TwoBytes, - MixedTwoBytes, - MixedFourBytes - }; - - struct CodeRange { - int m_CharSize; - uint8_t m_Lower[4]; - uint8_t m_Upper[4]; - }; - - struct CIDRange { - uint32_t m_StartCode; - uint32_t m_EndCode; - uint16_t m_StartCID; - }; - - template - friend CFX_RetainPtr pdfium::MakeRetain(Args&&... args); - - void LoadPredefined(CPDF_CMapManager* pMgr, - const CFX_ByteString& name, - bool bPromptCJK); - void LoadEmbedded(const uint8_t* pData, uint32_t dwSize); - - bool IsLoaded() const { return m_bLoaded; } - bool IsVertWriting() const { return m_bVertical; } - uint16_t CIDFromCharCode(uint32_t charcode) const; - int GetCharSize(uint32_t charcode) const; - uint32_t GetNextChar(const char* pString, int nStrLen, int& offset) const; - int CountChar(const char* pString, int size) const; - int AppendChar(char* str, uint32_t charcode) const; - - private: - friend class CPDF_CMapParser; - friend class CPDF_CIDFont; - - CPDF_CMap(); - ~CPDF_CMap() override; - - CFX_ByteString m_PredefinedCMap; - bool m_bLoaded; - bool m_bVertical; - CIDSet m_Charset; - CodingScheme m_CodingScheme; - int m_Coding; - std::vector m_MixedTwoByteLeadingBytes; - std::vector m_MixedFourByteLeadingRanges; - std::vector m_DirectCharcodeToCIDTable; - std::vector m_AdditionalCharcodeToCIDMappings; - const FXCMAP_CMap* m_pEmbedMap; -}; - -class CPDF_CMapManager { - public: - CPDF_CMapManager(); - ~CPDF_CMapManager(); - - CFX_RetainPtr GetPredefinedCMap(const CFX_ByteString& name, - bool bPromptCJK); - CPDF_CID2UnicodeMap* GetCID2UnicodeMap(CIDSet charset, bool bPromptCJK); - - private: - CFX_RetainPtr LoadPredefinedCMap(const CFX_ByteString& name, - bool bPromptCJK); - std::unique_ptr LoadCID2UnicodeMap(CIDSet charset, - bool bPromptCJK); - - std::map> m_CMaps; - std::unique_ptr m_CID2UnicodeMaps[6]; -}; - -class CPDF_CMapParser { - public: - explicit CPDF_CMapParser(CPDF_CMap* pMap); - ~CPDF_CMapParser(); - - void ParseWord(const CFX_ByteStringC& str); - bool HasAdditionalMappings() const { - return !m_AdditionalCharcodeToCIDMappings.empty(); - } - std::vector TakeAdditionalMappings() { - return std::move(m_AdditionalCharcodeToCIDMappings); - } - - private: - friend class fpdf_font_cid_CMap_GetCode_Test; - friend class fpdf_font_cid_CMap_GetCodeRange_Test; - - static uint32_t CMap_GetCode(const CFX_ByteStringC& word); - static bool CMap_GetCodeRange(CPDF_CMap::CodeRange& range, - const CFX_ByteStringC& first, - const CFX_ByteStringC& second); - - CFX_UnownedPtr const m_pCMap; - int m_Status; - int m_CodeSeq; - uint32_t m_CodePoints[4]; - std::vector m_CodeRanges; - std::vector m_AdditionalCharcodeToCIDMappings; - CFX_ByteString m_LastWord; -}; - -class CPDF_CID2UnicodeMap { - public: - CPDF_CID2UnicodeMap(); - ~CPDF_CID2UnicodeMap(); - - bool IsLoaded(); - void Load(CPDF_CMapManager* pMgr, CIDSet charset, bool bPromptCJK); - wchar_t UnicodeFromCID(uint16_t CID); - - private: - CIDSet m_Charset; - const uint16_t* m_pEmbeddedMap; - uint32_t m_EmbeddedCount; -}; - -class CPDF_ToUnicodeMap { - public: - CPDF_ToUnicodeMap(); - ~CPDF_ToUnicodeMap(); - - void Load(CPDF_Stream* pStream); - - CFX_WideString Lookup(uint32_t charcode) const; - uint32_t ReverseLookup(wchar_t unicode) const; - - private: - friend class fpdf_font_StringToCode_Test; - friend class fpdf_font_StringToWideString_Test; - - static uint32_t StringToCode(const CFX_ByteStringC& str); - static CFX_WideString StringToWideString(const CFX_ByteStringC& str); - - uint32_t GetUnicode(); - - std::map m_Map; - CFX_UnownedPtr m_pBaseMap; - CFX_WideTextBuf m_MultiCharBuf; -}; - -class CPDF_FontGlobals { - public: - CPDF_FontGlobals(); - ~CPDF_FontGlobals(); - - void Clear(CPDF_Document* pDoc); - CPDF_Font* Find(CPDF_Document* pDoc, uint32_t index); - - // Takes ownership of |pFont|, returns unowned pointer to it. - CPDF_Font* Set(CPDF_Document* key, - uint32_t index, - std::unique_ptr pFont); - - CPDF_CMapManager m_CMapManager; - struct { - CFX_UnownedPtr m_pMapList; - uint32_t m_Count; - } m_EmbeddedCharsets[CIDSET_NUM_SETS]; - struct { - const uint16_t* m_pMap; - uint32_t m_Count; - } m_EmbeddedToUnicodes[CIDSET_NUM_SETS]; - - private: - std::map> m_StockMap; -}; - -#endif // CORE_FPDFAPI_FONT_FONT_INT_H_ diff --git a/core/fpdfapi/font/fpdf_font.cpp b/core/fpdfapi/font/fpdf_font.cpp deleted file mode 100644 index ebdad49da7..0000000000 --- a/core/fpdfapi/font/fpdf_font.cpp +++ /dev/null @@ -1,314 +0,0 @@ -// 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/font_int.h" - -#include -#include - -#include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/page/cpdf_form.h" -#include "core/fpdfapi/page/cpdf_pagemodule.h" -#include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfapi/parser/cpdf_document.h" -#include "core/fpdfapi/parser/cpdf_name.h" -#include "core/fpdfapi/parser/cpdf_number.h" -#include "core/fpdfapi/parser/cpdf_simple_parser.h" -#include "core/fpdfapi/parser/cpdf_stream_acc.h" -#include "core/fxcrt/fx_extension.h" -#include "core/fxcrt/fx_safe_types.h" -#include "core/fxge/fx_freetype.h" -#include "third_party/base/numerics/safe_conversions.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" - -int TT2PDF(int m, FXFT_Face face) { - int upm = FXFT_Get_Face_UnitsPerEM(face); - if (upm == 0) - return m; - return pdfium::base::checked_cast( - (static_cast(m) * 1000 + upm / 2) / upm); -} - -bool FT_UseTTCharmap(FXFT_Face face, int platform_id, int encoding_id) { - auto** pCharMap = FXFT_Get_Face_Charmaps(face); - for (int i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) { - if (FXFT_Get_Charmap_PlatformID(pCharMap[i]) == platform_id && - FXFT_Get_Charmap_EncodingID(pCharMap[i]) == encoding_id) { - FXFT_Set_Charmap(face, pCharMap[i]); - return true; - } - } - return false; -} - -CFX_StockFontArray::CFX_StockFontArray() {} - -CFX_StockFontArray::~CFX_StockFontArray() { - for (size_t i = 0; i < FX_ArraySize(m_StockFonts); ++i) { - if (m_StockFonts[i]) - delete m_StockFonts[i]->GetFontDict(); - } -} - -CPDF_Font* CFX_StockFontArray::GetFont(uint32_t index) const { - if (index >= FX_ArraySize(m_StockFonts)) - return nullptr; - return m_StockFonts[index].get(); -} - -CPDF_Font* CFX_StockFontArray::SetFont(uint32_t index, - std::unique_ptr pFont) { - CPDF_Font* result = pFont.get(); - if (index < FX_ArraySize(m_StockFonts)) - m_StockFonts[index] = std::move(pFont); - return result; -} - -CPDF_FontGlobals::CPDF_FontGlobals() { - memset(m_EmbeddedCharsets, 0, sizeof(m_EmbeddedCharsets)); - memset(m_EmbeddedToUnicodes, 0, sizeof(m_EmbeddedToUnicodes)); -} - -CPDF_FontGlobals::~CPDF_FontGlobals() {} - -CPDF_Font* CPDF_FontGlobals::Find(CPDF_Document* pDoc, uint32_t index) { - auto it = m_StockMap.find(pDoc); - if (it == m_StockMap.end()) - return nullptr; - return it->second ? it->second->GetFont(index) : nullptr; -} - -CPDF_Font* CPDF_FontGlobals::Set(CPDF_Document* pDoc, - uint32_t index, - std::unique_ptr pFont) { - if (!pdfium::ContainsKey(m_StockMap, pDoc)) - m_StockMap[pDoc] = pdfium::MakeUnique(); - return m_StockMap[pDoc]->SetFont(index, std::move(pFont)); -} - -void CPDF_FontGlobals::Clear(CPDF_Document* pDoc) { - m_StockMap.erase(pDoc); -} - -CFX_WideString CPDF_ToUnicodeMap::Lookup(uint32_t charcode) const { - auto it = m_Map.find(charcode); - if (it != m_Map.end()) { - uint32_t value = it->second; - wchar_t unicode = (wchar_t)(value & 0xffff); - if (unicode != 0xffff) { - return unicode; - } - const wchar_t* buf = m_MultiCharBuf.GetBuffer(); - uint32_t buf_len = m_MultiCharBuf.GetLength(); - if (!buf || buf_len == 0) { - return CFX_WideString(); - } - uint32_t index = value >> 16; - if (index >= buf_len) { - return CFX_WideString(); - } - uint32_t len = buf[index]; - if (index + len < index || index + len >= buf_len) { - return CFX_WideString(); - } - return CFX_WideString(buf + index + 1, len); - } - if (m_pBaseMap) { - return m_pBaseMap->UnicodeFromCID((uint16_t)charcode); - } - return CFX_WideString(); -} - -uint32_t CPDF_ToUnicodeMap::ReverseLookup(wchar_t unicode) const { - for (const auto& pair : m_Map) { - if (pair.second == static_cast(unicode)) - return pair.first; - } - return 0; -} - -// Static. -uint32_t CPDF_ToUnicodeMap::StringToCode(const CFX_ByteStringC& str) { - int len = str.GetLength(); - if (len == 0) - return 0; - - uint32_t result = 0; - if (str[0] == '<') { - for (int i = 1; i < len && std::isxdigit(str[i]); ++i) - result = result * 16 + FXSYS_HexCharToInt(str.CharAt(i)); - return result; - } - - for (int i = 0; i < len && std::isdigit(str[i]); ++i) - result = result * 10 + FXSYS_DecimalCharToInt(str.CharAt(i)); - - return result; -} - -static CFX_WideString StringDataAdd(CFX_WideString str) { - CFX_WideString ret; - int len = str.GetLength(); - wchar_t value = 1; - for (int i = len - 1; i >= 0; --i) { - wchar_t ch = str[i] + value; - if (ch < str[i]) { - ret.Insert(0, 0); - } else { - ret.Insert(0, ch); - value = 0; - } - } - if (value) { - ret.Insert(0, value); - } - return ret; -} - -// Static. -CFX_WideString CPDF_ToUnicodeMap::StringToWideString( - const CFX_ByteStringC& str) { - int len = str.GetLength(); - if (len == 0) - return CFX_WideString(); - - CFX_WideString result; - if (str[0] == '<') { - int byte_pos = 0; - wchar_t ch = 0; - for (int i = 1; i < len && std::isxdigit(str[i]); ++i) { - ch = ch * 16 + FXSYS_HexCharToInt(str[i]); - byte_pos++; - if (byte_pos == 4) { - result += ch; - byte_pos = 0; - ch = 0; - } - } - return result; - } - return result; -} - -CPDF_ToUnicodeMap::CPDF_ToUnicodeMap() : m_pBaseMap(nullptr) {} - -CPDF_ToUnicodeMap::~CPDF_ToUnicodeMap() {} - -uint32_t CPDF_ToUnicodeMap::GetUnicode() { - FX_SAFE_UINT32 uni = m_MultiCharBuf.GetLength(); - uni = uni * 0x10000 + 0xffff; - return uni.ValueOrDefault(0); -} - -void CPDF_ToUnicodeMap::Load(CPDF_Stream* pStream) { - CIDSet cid_set = CIDSET_UNKNOWN; - auto pAcc = pdfium::MakeRetain(pStream); - pAcc->LoadAllData(false); - CPDF_SimpleParser parser(pAcc->GetData(), pAcc->GetSize()); - while (1) { - CFX_ByteStringC word = parser.GetWord(); - if (word.IsEmpty()) { - break; - } - if (word == "beginbfchar") { - while (1) { - word = parser.GetWord(); - if (word.IsEmpty() || word == "endbfchar") { - break; - } - uint32_t srccode = StringToCode(word); - word = parser.GetWord(); - CFX_WideString destcode = StringToWideString(word); - int len = destcode.GetLength(); - if (len == 0) { - continue; - } - if (len == 1) { - m_Map[srccode] = destcode.GetAt(0); - } else { - m_Map[srccode] = GetUnicode(); - m_MultiCharBuf.AppendChar(destcode.GetLength()); - m_MultiCharBuf << destcode; - } - } - } else if (word == "beginbfrange") { - while (1) { - CFX_ByteString low, high; - low = parser.GetWord(); - if (low.IsEmpty() || low == "endbfrange") { - break; - } - high = parser.GetWord(); - uint32_t lowcode = StringToCode(low.AsStringC()); - uint32_t highcode = - (lowcode & 0xffffff00) | (StringToCode(high.AsStringC()) & 0xff); - if (highcode == (uint32_t)-1) { - break; - } - CFX_ByteString start(parser.GetWord()); - if (start == "[") { - for (uint32_t code = lowcode; code <= highcode; code++) { - CFX_ByteString dest(parser.GetWord()); - CFX_WideString destcode = StringToWideString(dest.AsStringC()); - int len = destcode.GetLength(); - if (len == 0) { - continue; - } - if (len == 1) { - m_Map[code] = destcode.GetAt(0); - } else { - m_Map[code] = GetUnicode(); - m_MultiCharBuf.AppendChar(destcode.GetLength()); - m_MultiCharBuf << destcode; - } - } - parser.GetWord(); - } else { - CFX_WideString destcode = StringToWideString(start.AsStringC()); - int len = destcode.GetLength(); - uint32_t value = 0; - if (len == 1) { - value = StringToCode(start.AsStringC()); - for (uint32_t code = lowcode; code <= highcode; code++) { - m_Map[code] = value++; - } - } else { - for (uint32_t code = lowcode; code <= highcode; code++) { - CFX_WideString retcode; - if (code == lowcode) { - retcode = destcode; - } else { - retcode = StringDataAdd(destcode); - } - m_Map[code] = GetUnicode(); - m_MultiCharBuf.AppendChar(retcode.GetLength()); - m_MultiCharBuf << retcode; - destcode = retcode; - } - } - } - } - } else if (word == "/Adobe-Korea1-UCS2") { - cid_set = CIDSET_KOREA1; - } else if (word == "/Adobe-Japan1-UCS2") { - cid_set = CIDSET_JAPAN1; - } else if (word == "/Adobe-CNS1-UCS2") { - cid_set = CIDSET_CNS1; - } else if (word == "/Adobe-GB1-UCS2") { - cid_set = CIDSET_GB1; - } - } - if (cid_set) { - m_pBaseMap = CPDF_ModuleMgr::Get() - ->GetPageModule() - ->GetFontGlobals() - ->m_CMapManager.GetCID2UnicodeMap(cid_set, false); - } else { - m_pBaseMap = nullptr; - } -} diff --git a/core/fpdfapi/font/fpdf_font_cid.cpp b/core/fpdfapi/font/fpdf_font_cid.cpp deleted file mode 100644 index dd37551b2d..0000000000 --- a/core/fpdfapi/font/fpdf_font_cid.cpp +++ /dev/null @@ -1,750 +0,0 @@ -// 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/font_int.h" - -#include -#include -#include - -#include "core/fpdfapi/cmaps/cmap_int.h" -#include "core/fpdfapi/cpdf_modulemgr.h" -#include "core/fpdfapi/font/ttgsubtable.h" -#include "core/fpdfapi/page/cpdf_pagemodule.h" -#include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfapi/parser/cpdf_simple_parser.h" -#include "core/fxcrt/fx_extension.h" -#include "core/fxge/fx_freetype.h" -#include "third_party/base/logging.h" -#include "third_party/base/stl_util.h" - -namespace { - -const char* const g_CharsetNames[CIDSET_NUM_SETS] = {nullptr, "GB1", "CNS1", - "Japan1", "Korea1", "UCS"}; -struct ByteRange { - uint8_t m_First; - uint8_t m_Last; // Inclusive. -}; - -struct PredefinedCMap { - const char* m_pName; - CIDSet m_Charset; - CIDCoding m_Coding; - CPDF_CMap::CodingScheme m_CodingScheme; - uint8_t m_LeadingSegCount; - ByteRange m_LeadingSegs[2]; -}; - -const PredefinedCMap g_PredefinedCMaps[] = { - {"GB-EUC", - CIDSET_GB1, - CIDCODING_GB, - CPDF_CMap::MixedTwoBytes, - 1, - {{0xa1, 0xfe}}}, - {"GBpc-EUC", - CIDSET_GB1, - CIDCODING_GB, - CPDF_CMap::MixedTwoBytes, - 1, - {{0xa1, 0xfc}}}, - {"GBK-EUC", - CIDSET_GB1, - CIDCODING_GB, - CPDF_CMap::MixedTwoBytes, - 1, - {{0x81, 0xfe}}}, - {"GBKp-EUC", - CIDSET_GB1, - CIDCODING_GB, - CPDF_CMap::MixedTwoBytes, - 1, - {{0x81, 0xfe}}}, - {"GBK2K-EUC", - CIDSET_GB1, - CIDCODING_GB, - CPDF_CMap::MixedTwoBytes, - 1, - {{0x81, 0xfe}}}, - {"GBK2K", - CIDSET_GB1, - CIDCODING_GB, - CPDF_CMap::MixedTwoBytes, - 1, - {{0x81, 0xfe}}}, - {"UniGB-UCS2", CIDSET_GB1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, - {"UniGB-UTF16", CIDSET_GB1, CIDCODING_UTF16, CPDF_CMap::TwoBytes, 0, {}}, - {"B5pc", - CIDSET_CNS1, - CIDCODING_BIG5, - CPDF_CMap::MixedTwoBytes, - 1, - {{0xa1, 0xfc}}}, - {"HKscs-B5", - CIDSET_CNS1, - CIDCODING_BIG5, - CPDF_CMap::MixedTwoBytes, - 1, - {{0x88, 0xfe}}}, - {"ETen-B5", - CIDSET_CNS1, - CIDCODING_BIG5, - CPDF_CMap::MixedTwoBytes, - 1, - {{0xa1, 0xfe}}}, - {"ETenms-B5", - CIDSET_CNS1, - CIDCODING_BIG5, - CPDF_CMap::MixedTwoBytes, - 1, - {{0xa1, 0xfe}}}, - {"UniCNS-UCS2", CIDSET_CNS1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, - {"UniCNS-UTF16", CIDSET_CNS1, CIDCODING_UTF16, CPDF_CMap::TwoBytes, 0, {}}, - {"83pv-RKSJ", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {{0x81, 0x9f}, {0xe0, 0xfc}}}, - {"90ms-RKSJ", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {{0x81, 0x9f}, {0xe0, 0xfc}}}, - {"90msp-RKSJ", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {{0x81, 0x9f}, {0xe0, 0xfc}}}, - {"90pv-RKSJ", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {{0x81, 0x9f}, {0xe0, 0xfc}}}, - {"Add-RKSJ", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {{0x81, 0x9f}, {0xe0, 0xfc}}}, - {"EUC", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {{0x8e, 0x8e}, {0xa1, 0xfe}}}, - {"H", CIDSET_JAPAN1, CIDCODING_JIS, CPDF_CMap::TwoBytes, 1, {{0x21, 0x7e}}}, - {"V", CIDSET_JAPAN1, CIDCODING_JIS, CPDF_CMap::TwoBytes, 1, {{0x21, 0x7e}}}, - {"Ext-RKSJ", - CIDSET_JAPAN1, - CIDCODING_JIS, - CPDF_CMap::MixedTwoBytes, - 2, - {{0x81, 0x9f}, {0xe0, 0xfc}}}, - {"UniJIS-UCS2", CIDSET_JAPAN1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, - {"UniJIS-UCS2-HW", - CIDSET_JAPAN1, - CIDCODING_UCS2, - CPDF_CMap::TwoBytes, - 0, - {}}, - {"UniJIS-UTF16", - CIDSET_JAPAN1, - CIDCODING_UTF16, - CPDF_CMap::TwoBytes, - 0, - {}}, - {"KSC-EUC", - CIDSET_KOREA1, - CIDCODING_KOREA, - CPDF_CMap::MixedTwoBytes, - 1, - {{0xa1, 0xfe}}}, - {"KSCms-UHC", - CIDSET_KOREA1, - CIDCODING_KOREA, - CPDF_CMap::MixedTwoBytes, - 1, - {{0x81, 0xfe}}}, - {"KSCms-UHC-HW", - CIDSET_KOREA1, - CIDCODING_KOREA, - CPDF_CMap::MixedTwoBytes, - 1, - {{0x81, 0xfe}}}, - {"KSCpc-EUC", - CIDSET_KOREA1, - CIDCODING_KOREA, - CPDF_CMap::MixedTwoBytes, - 1, - {{0xa1, 0xfd}}}, - {"UniKS-UCS2", CIDSET_KOREA1, CIDCODING_UCS2, CPDF_CMap::TwoBytes, 0, {}}, - {"UniKS-UTF16", CIDSET_KOREA1, CIDCODING_UTF16, CPDF_CMap::TwoBytes, 0, {}}, -}; - -CIDSet CIDSetFromSizeT(size_t index) { - if (index >= CIDSET_NUM_SETS) { - NOTREACHED(); - return CIDSET_UNKNOWN; - } - return static_cast(index); -} - -CFX_ByteStringC CMap_GetString(const CFX_ByteStringC& word) { - if (word.GetLength() <= 2) - return CFX_ByteStringC(); - return CFX_ByteStringC(&word[1], word.GetLength() - 2); -} - -int CheckFourByteCodeRange(uint8_t* codes, - int size, - const std::vector& ranges) { - int iSeg = pdfium::CollectionSize(ranges) - 1; - while (iSeg >= 0) { - if (ranges[iSeg].m_CharSize < size) { - --iSeg; - continue; - } - int iChar = 0; - while (iChar < size) { - if (codes[iChar] < ranges[iSeg].m_Lower[iChar] || - codes[iChar] > ranges[iSeg].m_Upper[iChar]) { - break; - } - ++iChar; - } - if (iChar == ranges[iSeg].m_CharSize) - return 2; - if (iChar) - return (size == ranges[iSeg].m_CharSize) ? 2 : 1; - iSeg--; - } - return 0; -} - -int GetFourByteCharSizeImpl(uint32_t charcode, - const std::vector& ranges) { - if (ranges.empty()) - return 1; - - uint8_t codes[4]; - codes[0] = codes[1] = 0x00; - codes[2] = (uint8_t)(charcode >> 8 & 0xFF); - codes[3] = (uint8_t)charcode; - int offset = 0; - int size = 4; - for (int i = 0; i < 4; ++i) { - int iSeg = pdfium::CollectionSize(ranges) - 1; - while (iSeg >= 0) { - if (ranges[iSeg].m_CharSize < size) { - --iSeg; - continue; - } - int iChar = 0; - while (iChar < size) { - if (codes[offset + iChar] < ranges[iSeg].m_Lower[iChar] || - codes[offset + iChar] > ranges[iSeg].m_Upper[iChar]) { - break; - } - ++iChar; - } - if (iChar == ranges[iSeg].m_CharSize) - return size; - --iSeg; - } - --size; - ++offset; - } - return 1; -} - -} // namespace - -CPDF_CMapManager::CPDF_CMapManager() {} - -CPDF_CMapManager::~CPDF_CMapManager() {} - -CFX_RetainPtr CPDF_CMapManager::GetPredefinedCMap( - const CFX_ByteString& name, - bool bPromptCJK) { - auto it = m_CMaps.find(name); - if (it != m_CMaps.end()) - return it->second; - - CFX_RetainPtr pCMap = LoadPredefinedCMap(name, bPromptCJK); - if (!name.IsEmpty()) - m_CMaps[name] = pCMap; - - return pCMap; -} - -CFX_RetainPtr CPDF_CMapManager::LoadPredefinedCMap( - const CFX_ByteString& name, - bool bPromptCJK) { - const char* pname = name.c_str(); - if (*pname == '/') - pname++; - - auto pCMap = pdfium::MakeRetain(); - pCMap->LoadPredefined(this, pname, bPromptCJK); - return pCMap; -} - -CPDF_CID2UnicodeMap* CPDF_CMapManager::GetCID2UnicodeMap(CIDSet charset, - bool bPromptCJK) { - if (!m_CID2UnicodeMaps[charset]) - m_CID2UnicodeMaps[charset] = LoadCID2UnicodeMap(charset, bPromptCJK); - - return m_CID2UnicodeMaps[charset].get(); -} - -std::unique_ptr CPDF_CMapManager::LoadCID2UnicodeMap( - CIDSet charset, - bool bPromptCJK) { - auto pMap = pdfium::MakeUnique(); - pMap->Load(this, charset, bPromptCJK); - return pMap; -} - -CPDF_CMapParser::CPDF_CMapParser(CPDF_CMap* pCMap) - : m_pCMap(pCMap), m_Status(0), m_CodeSeq(0) {} - -CPDF_CMapParser::~CPDF_CMapParser() {} - -void CPDF_CMapParser::ParseWord(const CFX_ByteStringC& word) { - if (word.IsEmpty()) { - return; - } - if (word == "begincidchar") { - m_Status = 1; - m_CodeSeq = 0; - } else if (word == "begincidrange") { - m_Status = 2; - m_CodeSeq = 0; - } else if (word == "endcidrange" || word == "endcidchar") { - m_Status = 0; - } else if (word == "/WMode") { - m_Status = 6; - } else if (word == "/Registry") { - m_Status = 3; - } else if (word == "/Ordering") { - m_Status = 4; - } else if (word == "/Supplement") { - m_Status = 5; - } else if (word == "begincodespacerange") { - m_Status = 7; - m_CodeSeq = 0; - } else if (word == "usecmap") { - } else if (m_Status == 1 || m_Status == 2) { - m_CodePoints[m_CodeSeq] = CMap_GetCode(word); - m_CodeSeq++; - uint32_t StartCode, EndCode; - uint16_t StartCID; - if (m_Status == 1) { - if (m_CodeSeq < 2) { - return; - } - EndCode = StartCode = m_CodePoints[0]; - StartCID = (uint16_t)m_CodePoints[1]; - } else { - if (m_CodeSeq < 3) { - return; - } - StartCode = m_CodePoints[0]; - EndCode = m_CodePoints[1]; - StartCID = (uint16_t)m_CodePoints[2]; - } - if (EndCode < 0x10000) { - for (uint32_t code = StartCode; code <= EndCode; code++) { - m_pCMap->m_DirectCharcodeToCIDTable[code] = - static_cast(StartCID + code - StartCode); - } - } else { - m_AdditionalCharcodeToCIDMappings.push_back( - {StartCode, EndCode, StartCID}); - } - m_CodeSeq = 0; - } else if (m_Status == 3) { - m_Status = 0; - } else if (m_Status == 4) { - m_pCMap->m_Charset = CharsetFromOrdering(CMap_GetString(word)); - m_Status = 0; - } else if (m_Status == 5) { - m_Status = 0; - } else if (m_Status == 6) { - m_pCMap->m_bVertical = CMap_GetCode(word) != 0; - m_Status = 0; - } else if (m_Status == 7) { - if (word == "endcodespacerange") { - uint32_t nSegs = pdfium::CollectionSize(m_CodeRanges); - if (nSegs > 1) { - m_pCMap->m_CodingScheme = CPDF_CMap::MixedFourBytes; - m_pCMap->m_MixedFourByteLeadingRanges = m_CodeRanges; - } else if (nSegs == 1) { - m_pCMap->m_CodingScheme = (m_CodeRanges[0].m_CharSize == 2) - ? CPDF_CMap::TwoBytes - : CPDF_CMap::OneByte; - } - m_Status = 0; - } else { - if (word.GetLength() == 0 || word.GetAt(0) != '<') { - return; - } - if (m_CodeSeq % 2) { - CPDF_CMap::CodeRange range; - if (CMap_GetCodeRange(range, m_LastWord.AsStringC(), word)) - m_CodeRanges.push_back(range); - } - m_CodeSeq++; - } - } - m_LastWord = word; -} - -// Static. -uint32_t CPDF_CMapParser::CMap_GetCode(const CFX_ByteStringC& word) { - pdfium::base::CheckedNumeric num = 0; - if (word.GetAt(0) == '<') { - for (int i = 1; i < word.GetLength() && std::isxdigit(word.GetAt(i)); ++i) { - num = num * 16 + FXSYS_HexCharToInt(word.GetAt(i)); - if (!num.IsValid()) - return 0; - } - return num.ValueOrDie(); - } - - for (int i = 0; i < word.GetLength() && std::isdigit(word.GetAt(i)); ++i) { - num = - num * 10 + FXSYS_DecimalCharToInt(static_cast(word.GetAt(i))); - if (!num.IsValid()) - return 0; - } - return num.ValueOrDie(); -} - -// Static. -bool CPDF_CMapParser::CMap_GetCodeRange(CPDF_CMap::CodeRange& range, - const CFX_ByteStringC& first, - const CFX_ByteStringC& second) { - if (first.GetLength() == 0 || first.GetAt(0) != '<') - return false; - - int i; - for (i = 1; i < first.GetLength(); ++i) { - if (first.GetAt(i) == '>') { - break; - } - } - range.m_CharSize = (i - 1) / 2; - if (range.m_CharSize > 4) - return false; - - for (i = 0; i < range.m_CharSize; ++i) { - uint8_t digit1 = first.GetAt(i * 2 + 1); - uint8_t digit2 = first.GetAt(i * 2 + 2); - range.m_Lower[i] = - FXSYS_HexCharToInt(digit1) * 16 + FXSYS_HexCharToInt(digit2); - } - - uint32_t size = second.GetLength(); - for (i = 0; i < range.m_CharSize; ++i) { - uint8_t digit1 = ((uint32_t)i * 2 + 1 < size) - ? second.GetAt((FX_STRSIZE)i * 2 + 1) - : '0'; - uint8_t digit2 = ((uint32_t)i * 2 + 2 < size) - ? second.GetAt((FX_STRSIZE)i * 2 + 2) - : '0'; - range.m_Upper[i] = - FXSYS_HexCharToInt(digit1) * 16 + FXSYS_HexCharToInt(digit2); - } - return true; -} - -CPDF_CMap::CPDF_CMap() - : m_bLoaded(false), - m_bVertical(false), - m_Charset(CIDSET_UNKNOWN), - m_CodingScheme(TwoBytes), - m_Coding(CIDCODING_UNKNOWN), - m_pEmbedMap(nullptr) {} - -CPDF_CMap::~CPDF_CMap() {} - -void CPDF_CMap::LoadPredefined(CPDF_CMapManager* pMgr, - const CFX_ByteString& bsName, - bool bPromptCJK) { - m_PredefinedCMap = bsName; - if (m_PredefinedCMap == "Identity-H" || m_PredefinedCMap == "Identity-V") { - m_Coding = CIDCODING_CID; - m_bVertical = bsName[9] == 'V'; - m_bLoaded = true; - return; - } - CFX_ByteString cmapid = m_PredefinedCMap; - m_bVertical = cmapid.Right(1) == "V"; - if (cmapid.GetLength() > 2) { - cmapid = cmapid.Left(cmapid.GetLength() - 2); - } - const PredefinedCMap* map = nullptr; - for (size_t i = 0; i < FX_ArraySize(g_PredefinedCMaps); ++i) { - if (cmapid == CFX_ByteStringC(g_PredefinedCMaps[i].m_pName)) { - map = &g_PredefinedCMaps[i]; - break; - } - } - if (!map) - return; - - m_Charset = map->m_Charset; - m_Coding = map->m_Coding; - m_CodingScheme = map->m_CodingScheme; - if (m_CodingScheme == MixedTwoBytes) { - m_MixedTwoByteLeadingBytes = std::vector(256); - for (uint32_t i = 0; i < map->m_LeadingSegCount; ++i) { - const ByteRange& seg = map->m_LeadingSegs[i]; - for (int b = seg.m_First; b <= seg.m_Last; ++b) - m_MixedTwoByteLeadingBytes[b] = true; - } - } - FPDFAPI_FindEmbeddedCMap(bsName, m_Charset, m_Coding, m_pEmbedMap); - if (!m_pEmbedMap) - return; - - m_bLoaded = true; -} - -void CPDF_CMap::LoadEmbedded(const uint8_t* pData, uint32_t size) { - m_DirectCharcodeToCIDTable = std::vector(65536); - CPDF_CMapParser parser(this); - CPDF_SimpleParser syntax(pData, size); - while (1) { - CFX_ByteStringC word = syntax.GetWord(); - if (word.IsEmpty()) { - break; - } - parser.ParseWord(word); - } - if (m_CodingScheme == MixedFourBytes && parser.HasAdditionalMappings()) { - m_AdditionalCharcodeToCIDMappings = parser.TakeAdditionalMappings(); - std::sort( - m_AdditionalCharcodeToCIDMappings.begin(), - m_AdditionalCharcodeToCIDMappings.end(), - [](const CPDF_CMap::CIDRange& arg1, const CPDF_CMap::CIDRange& arg2) { - return arg1.m_EndCode < arg2.m_EndCode; - }); - } -} - -uint16_t CPDF_CMap::CIDFromCharCode(uint32_t charcode) const { - if (m_Coding == CIDCODING_CID) - return static_cast(charcode); - - if (m_pEmbedMap) - return FPDFAPI_CIDFromCharCode(m_pEmbedMap, charcode); - - if (m_DirectCharcodeToCIDTable.empty()) - return static_cast(charcode); - - if (charcode < 0x10000) - return m_DirectCharcodeToCIDTable[charcode]; - - auto it = std::lower_bound(m_AdditionalCharcodeToCIDMappings.begin(), - m_AdditionalCharcodeToCIDMappings.end(), charcode, - [](const CPDF_CMap::CIDRange& arg, uint32_t val) { - return arg.m_EndCode < val; - }); - if (it == m_AdditionalCharcodeToCIDMappings.end() || - it->m_StartCode > charcode) { - return 0; - } - return it->m_StartCID + charcode - it->m_StartCode; -} - -uint32_t CPDF_CMap::GetNextChar(const char* pString, - int nStrLen, - int& offset) const { - auto* pBytes = reinterpret_cast(pString); - switch (m_CodingScheme) { - case OneByte: { - return pBytes[offset++]; - } - case TwoBytes: { - uint8_t byte1 = pBytes[offset++]; - return 256 * byte1 + pBytes[offset++]; - } - case MixedTwoBytes: { - uint8_t byte1 = pBytes[offset++]; - if (!m_MixedTwoByteLeadingBytes[byte1]) - return byte1; - return 256 * byte1 + pBytes[offset++]; - } - case MixedFourBytes: { - uint8_t codes[4]; - int char_size = 1; - codes[0] = pBytes[offset++]; - while (1) { - int ret = CheckFourByteCodeRange(codes, char_size, - m_MixedFourByteLeadingRanges); - if (ret == 0) - return 0; - if (ret == 2) { - uint32_t charcode = 0; - for (int i = 0; i < char_size; i++) - charcode = (charcode << 8) + codes[i]; - return charcode; - } - if (char_size == 4 || offset == nStrLen) - return 0; - codes[char_size++] = pBytes[offset++]; - } - break; - } - } - return 0; -} - -int CPDF_CMap::GetCharSize(uint32_t charcode) const { - switch (m_CodingScheme) { - case OneByte: - return 1; - case TwoBytes: - return 2; - case MixedTwoBytes: - if (charcode < 0x100) - return 1; - return 2; - case MixedFourBytes: - if (charcode < 0x100) - return 1; - if (charcode < 0x10000) - return 2; - if (charcode < 0x1000000) - return 3; - return 4; - } - return 1; -} - -int CPDF_CMap::CountChar(const char* pString, int size) const { - switch (m_CodingScheme) { - case OneByte: - return size; - case TwoBytes: - return (size + 1) / 2; - case MixedTwoBytes: { - int count = 0; - for (int i = 0; i < size; i++) { - count++; - if (m_MixedTwoByteLeadingBytes[reinterpret_cast( - pString)[i]]) { - i++; - } - } - return count; - } - case MixedFourBytes: { - int count = 0, offset = 0; - while (offset < size) { - GetNextChar(pString, size, offset); - count++; - } - return count; - } - } - return size; -} - -int CPDF_CMap::AppendChar(char* str, uint32_t charcode) const { - switch (m_CodingScheme) { - case OneByte: - str[0] = (uint8_t)charcode; - return 1; - case TwoBytes: - str[0] = (uint8_t)(charcode / 256); - str[1] = (uint8_t)(charcode % 256); - return 2; - case MixedTwoBytes: - if (charcode < 0x100 && !m_MixedTwoByteLeadingBytes[(uint8_t)charcode]) { - str[0] = (uint8_t)charcode; - return 1; - } - str[0] = (uint8_t)(charcode >> 8); - str[1] = (uint8_t)charcode; - return 2; - case MixedFourBytes: - if (charcode < 0x100) { - int iSize = - GetFourByteCharSizeImpl(charcode, m_MixedFourByteLeadingRanges); - if (iSize == 0) - iSize = 1; - str[iSize - 1] = (uint8_t)charcode; - if (iSize > 1) - memset(str, 0, iSize - 1); - return iSize; - } - if (charcode < 0x10000) { - str[0] = (uint8_t)(charcode >> 8); - str[1] = (uint8_t)charcode; - return 2; - } - if (charcode < 0x1000000) { - str[0] = (uint8_t)(charcode >> 16); - str[1] = (uint8_t)(charcode >> 8); - str[2] = (uint8_t)charcode; - return 3; - } - str[0] = (uint8_t)(charcode >> 24); - str[1] = (uint8_t)(charcode >> 16); - str[2] = (uint8_t)(charcode >> 8); - str[3] = (uint8_t)charcode; - return 4; - } - return 0; -} - -CPDF_CID2UnicodeMap::CPDF_CID2UnicodeMap() { - m_EmbeddedCount = 0; -} - -CPDF_CID2UnicodeMap::~CPDF_CID2UnicodeMap() {} - -bool CPDF_CID2UnicodeMap::IsLoaded() { - return m_EmbeddedCount != 0; -} - -wchar_t CPDF_CID2UnicodeMap::UnicodeFromCID(uint16_t CID) { - if (m_Charset == CIDSET_UNICODE) { - return CID; - } - if (CID < m_EmbeddedCount) { - return m_pEmbeddedMap[CID]; - } - return 0; -} - -void CPDF_CID2UnicodeMap::Load(CPDF_CMapManager* pMgr, - CIDSet charset, - bool bPromptCJK) { - m_Charset = charset; - - CPDF_FontGlobals* pFontGlobals = - CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals(); - m_pEmbeddedMap = pFontGlobals->m_EmbeddedToUnicodes[charset].m_pMap; - m_EmbeddedCount = pFontGlobals->m_EmbeddedToUnicodes[charset].m_Count; -} - -CIDSet CharsetFromOrdering(const CFX_ByteStringC& ordering) { - for (size_t charset = 1; charset < FX_ArraySize(g_CharsetNames); ++charset) { - if (ordering == g_CharsetNames[charset]) - return CIDSetFromSizeT(charset); - } - return CIDSET_UNKNOWN; -} diff --git a/core/fpdfapi/font/fpdf_font_cid_unittest.cpp b/core/fpdfapi/font/fpdf_font_cid_unittest.cpp deleted file mode 100644 index 813a3a9d9b..0000000000 --- a/core/fpdfapi/font/fpdf_font_cid_unittest.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2015 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. - -#include "core/fpdfapi/font/font_int.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -bool uint_ranges_equal(uint8_t* a, uint8_t* b, size_t count) { - for (size_t i = 0; i < count; ++i) { - if (a[i] != b[i]) - return false; - } - return true; -} - -} // namespace - -TEST(fpdf_font_cid, CMap_GetCode) { - EXPECT_EQ(0u, CPDF_CMapParser::CMap_GetCode("")); - EXPECT_EQ(0u, CPDF_CMapParser::CMap_GetCode("<")); - EXPECT_EQ(194u, CPDF_CMapParser::CMap_GetCode("", "")); - EXPECT_EQ(5, range.m_CharSize); - - EXPECT_TRUE( - CPDF_CMapParser::CMap_GetCodeRange(range, "<12345678>", "<87654321>")); - EXPECT_EQ(4, range.m_CharSize); - { - uint8_t lower[4] = {18, 52, 86, 120}; - uint8_t upper[4] = {135, 101, 67, 33}; - EXPECT_TRUE(uint_ranges_equal(lower, range.m_Lower, range.m_CharSize)); - EXPECT_TRUE(uint_ranges_equal(upper, range.m_Upper, range.m_CharSize)); - } - - // Hex characters - EXPECT_TRUE(CPDF_CMapParser::CMap_GetCodeRange(range, "", "")); - EXPECT_EQ(1, range.m_CharSize); - EXPECT_EQ(161, range.m_Lower[0]); - EXPECT_EQ(243, range.m_Upper[0]); - - // The second string should return 0's if it is shorter - EXPECT_TRUE(CPDF_CMapParser::CMap_GetCodeRange(range, "", "")); - EXPECT_EQ(1, range.m_CharSize); - EXPECT_EQ(161, range.m_Lower[0]); - EXPECT_EQ(0, range.m_Upper[0]); -} diff --git a/core/fpdfapi/font/fpdf_font_unittest.cpp b/core/fpdfapi/font/fpdf_font_unittest.cpp deleted file mode 100644 index 977ae8a3bb..0000000000 --- a/core/fpdfapi/font/fpdf_font_unittest.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2015 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. - -#include "core/fpdfapi/font/font_int.h" -#include "testing/gtest/include/gtest/gtest.h" - -TEST(fpdf_font, StringToCode) { - EXPECT_EQ(0u, CPDF_ToUnicodeMap::StringToCode("")); - EXPECT_EQ(194u, CPDF_ToUnicodeMap::StringToCode(" - -#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(subTable.get()); - if (GetCoverageIndex(tbl1->Coverage.get(), glyphnum) >= 0) { - *vglyphnum = glyphnum + tbl1->DeltaGlyphID; - return true; - } - break; - } - case 2: { - auto* tbl2 = static_cast(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(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(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(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(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(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(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(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>(GetUInt16(sp)); - if (rec->LookupType != 1) - return; - - for (auto& subTable : rec->SubTables) - ParseSingleSubst(&raw[GetUInt16(sp)], &subTable); -} - -std::unique_ptr -CFX_CTTGSUBTable::ParseCoverage(FT_Bytes raw) { - FT_Bytes sp = raw; - uint16_t format = GetUInt16(sp); - if (format == 1) { - auto rec = pdfium::MakeUnique(); - ParseCoverageFormat1(raw, rec.get()); - return std::move(rec); - } - if (format == 2) { - auto rec = pdfium::MakeUnique(); - 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(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(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* rec) { - FT_Bytes sp = raw; - uint16_t Format = GetUInt16(sp); - switch (Format) { - case 1: - *rec = pdfium::MakeUnique(); - ParseSingleSubstFormat1(raw, - static_cast(rec->get())); - break; - case 2: - *rec = pdfium::MakeUnique(); - ParseSingleSubstFormat2(raw, - static_cast(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(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() {} diff --git a/core/fpdfapi/font/ttgsubtable.h b/core/fpdfapi/font/ttgsubtable.h deleted file mode 100644 index c3bff43957..0000000000 --- a/core/fpdfapi/font/ttgsubtable.h +++ /dev/null @@ -1,298 +0,0 @@ -// 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 - -#ifndef CORE_FPDFAPI_FONT_TTGSUBTABLE_H_ -#define CORE_FPDFAPI_FONT_TTGSUBTABLE_H_ - -#include - -#include -#include -#include - -#include "core/fxcrt/fx_basic.h" -#include "core/fxge/fx_font.h" -#include "core/fxge/fx_freetype.h" - -class CFX_CTTGSUBTable { - public: - CFX_CTTGSUBTable(); - explicit CFX_CTTGSUBTable(FT_Bytes gsub); - virtual ~CFX_CTTGSUBTable(); - - bool IsOk() const; - bool LoadGSUBTable(FT_Bytes gsub); - bool GetVerticalGlyph(uint32_t glyphnum, uint32_t* vglyphnum); - - private: - struct tt_gsub_header { - uint32_t Version; - uint16_t ScriptList; - uint16_t FeatureList; - uint16_t LookupList; - }; - - struct TLangSys { - TLangSys(); - ~TLangSys(); - - uint16_t LookupOrder; - uint16_t ReqFeatureIndex; - std::vector FeatureIndices; - - private: - TLangSys(const TLangSys&) = delete; - TLangSys& operator=(const TLangSys&) = delete; - }; - - struct TLangSysRecord { - TLangSysRecord() : LangSysTag(0) {} - - uint32_t LangSysTag; - TLangSys LangSys; - - private: - TLangSysRecord(const TLangSysRecord&) = delete; - TLangSysRecord& operator=(const TLangSysRecord&) = delete; - }; - - struct TScript { - TScript(); - ~TScript(); - - uint16_t DefaultLangSys; - std::vector LangSysRecords; - - private: - TScript(const TScript&) = delete; - TScript& operator=(const TScript&) = delete; - }; - - struct TScriptRecord { - TScriptRecord() : ScriptTag(0) {} - - uint32_t ScriptTag; - TScript Script; - - private: - TScriptRecord(const TScriptRecord&) = delete; - TScriptRecord& operator=(const TScriptRecord&) = delete; - }; - - struct TScriptList { - TScriptList(); - ~TScriptList(); - - std::vector ScriptRecords; - - private: - TScriptList(const TScriptList&) = delete; - TScriptList& operator=(const TScriptList&) = delete; - }; - - struct TFeature { - TFeature(); - ~TFeature(); - - uint16_t FeatureParams; - std::vector LookupListIndices; - - private: - TFeature(const TFeature&) = delete; - TFeature& operator=(const TFeature&) = delete; - }; - - struct TFeatureRecord { - TFeatureRecord() : FeatureTag(0) {} - - uint32_t FeatureTag; - TFeature Feature; - - private: - TFeatureRecord(const TFeatureRecord&) = delete; - TFeatureRecord& operator=(const TFeatureRecord&) = delete; - }; - - struct TFeatureList { - TFeatureList(); - ~TFeatureList(); - - std::vector FeatureRecords; - - private: - TFeatureList(const TFeatureList&) = delete; - TFeatureList& operator=(const TFeatureList&) = delete; - }; - - enum TLookupFlag { - LOOKUPFLAG_RightToLeft = 0x0001, - LOOKUPFLAG_IgnoreBaseGlyphs = 0x0002, - LOOKUPFLAG_IgnoreLigatures = 0x0004, - LOOKUPFLAG_IgnoreMarks = 0x0008, - LOOKUPFLAG_Reserved = 0x00F0, - LOOKUPFLAG_MarkAttachmentType = 0xFF00, - }; - - struct TCoverageFormatBase { - TCoverageFormatBase() : CoverageFormat(0) {} - explicit TCoverageFormatBase(uint16_t format) : CoverageFormat(format) {} - virtual ~TCoverageFormatBase() {} - - uint16_t CoverageFormat; - - private: - TCoverageFormatBase(const TCoverageFormatBase&); - TCoverageFormatBase& operator=(const TCoverageFormatBase&); - }; - - struct TCoverageFormat1 : public TCoverageFormatBase { - TCoverageFormat1(); - ~TCoverageFormat1() override; - - std::vector GlyphArray; - - private: - TCoverageFormat1(const TCoverageFormat1&) = delete; - TCoverageFormat1& operator=(const TCoverageFormat1&) = delete; - }; - - struct TRangeRecord { - TRangeRecord(); - - friend bool operator>(const TRangeRecord& r1, const TRangeRecord& r2) { - return r1.Start > r2.Start; - } - - uint16_t Start; - uint16_t End; - uint16_t StartCoverageIndex; - - private: - TRangeRecord(const TRangeRecord&) = delete; - }; - - struct TCoverageFormat2 : public TCoverageFormatBase { - TCoverageFormat2(); - ~TCoverageFormat2() override; - - std::vector RangeRecords; - - private: - TCoverageFormat2(const TCoverageFormat2&) = delete; - TCoverageFormat2& operator=(const TCoverageFormat2&) = delete; - }; - - struct TDevice { - TDevice() : StartSize(0), EndSize(0), DeltaFormat(0) {} - - uint16_t StartSize; - uint16_t EndSize; - uint16_t DeltaFormat; - - private: - TDevice(const TDevice&) = delete; - TDevice& operator=(const TDevice&) = delete; - }; - - struct TSubTableBase { - TSubTableBase() : SubstFormat(0) {} - explicit TSubTableBase(uint16_t format) : SubstFormat(format) {} - virtual ~TSubTableBase() {} - - uint16_t SubstFormat; - - private: - TSubTableBase(const TSubTableBase&) = delete; - TSubTableBase& operator=(const TSubTableBase&) = delete; - }; - - struct TSingleSubstFormat1 : public TSubTableBase { - TSingleSubstFormat1(); - ~TSingleSubstFormat1() override; - - std::unique_ptr Coverage; - int16_t DeltaGlyphID; - - private: - TSingleSubstFormat1(const TSingleSubstFormat1&) = delete; - TSingleSubstFormat1& operator=(const TSingleSubstFormat1&) = delete; - }; - - struct TSingleSubstFormat2 : public TSubTableBase { - TSingleSubstFormat2(); - ~TSingleSubstFormat2() override; - - std::unique_ptr Coverage; - std::vector Substitutes; - - private: - TSingleSubstFormat2(const TSingleSubstFormat2&) = delete; - TSingleSubstFormat2& operator=(const TSingleSubstFormat2&) = delete; - }; - - struct TLookup { - TLookup(); - ~TLookup(); - - uint16_t LookupType; - uint16_t LookupFlag; - std::vector> SubTables; - - private: - TLookup(const TLookup&) = delete; - TLookup& operator=(const TLookup&) = delete; - }; - - struct TLookupList { - TLookupList(); - ~TLookupList(); - - std::vector Lookups; - - private: - TLookupList(const TLookupList&) = delete; - TLookupList& operator=(const TLookupList&) = delete; - }; - - bool Parse(FT_Bytes scriptlist, FT_Bytes featurelist, FT_Bytes lookuplist); - void ParseScriptList(FT_Bytes raw, TScriptList* rec); - void ParseScript(FT_Bytes raw, TScript* rec); - void ParseLangSys(FT_Bytes raw, TLangSys* rec); - void ParseFeatureList(FT_Bytes raw, TFeatureList* rec); - void ParseFeature(FT_Bytes raw, TFeature* rec); - void ParseLookupList(FT_Bytes raw, TLookupList* rec); - void ParseLookup(FT_Bytes raw, TLookup* rec); - std::unique_ptr ParseCoverage(FT_Bytes raw); - void ParseCoverageFormat1(FT_Bytes raw, TCoverageFormat1* rec); - void ParseCoverageFormat2(FT_Bytes raw, TCoverageFormat2* rec); - void ParseSingleSubst(FT_Bytes raw, std::unique_ptr* rec); - void ParseSingleSubstFormat1(FT_Bytes raw, TSingleSubstFormat1* rec); - void ParseSingleSubstFormat2(FT_Bytes raw, TSingleSubstFormat2* rec); - - bool GetVerticalGlyphSub(uint32_t glyphnum, - uint32_t* vglyphnum, - TFeature* Feature); - bool GetVerticalGlyphSub2(uint32_t glyphnum, - uint32_t* vglyphnum, - TLookup* Lookup); - int GetCoverageIndex(TCoverageFormatBase* Coverage, uint32_t g) const; - - uint8_t GetUInt8(FT_Bytes& p) const; - int16_t GetInt16(FT_Bytes& p) const; - uint16_t GetUInt16(FT_Bytes& p) const; - int32_t GetInt32(FT_Bytes& p) const; - uint32_t GetUInt32(FT_Bytes& p) const; - - std::set m_featureSet; - bool m_bFeautureMapLoad; - bool loaded; - tt_gsub_header header; - TScriptList ScriptList; - TFeatureList FeatureList; - TLookupList LookupList; -}; - -#endif // CORE_FPDFAPI_FONT_TTGSUBTABLE_H_ diff --git a/core/fpdfapi/page/cpdf_docpagedata.cpp b/core/fpdfapi/page/cpdf_docpagedata.cpp index d8b89b318b..4438006ab3 100644 --- a/core/fpdfapi/page/cpdf_docpagedata.cpp +++ b/core/fpdfapi/page/cpdf_docpagedata.cpp @@ -14,7 +14,6 @@ #include "core/fdrm/crypto/fx_crypt.h" #include "core/fpdfapi/cpdf_modulemgr.h" #include "core/fpdfapi/font/cpdf_type1font.h" -#include "core/fpdfapi/font/font_int.h" #include "core/fpdfapi/page/cpdf_iccprofile.h" #include "core/fpdfapi/page/cpdf_image.h" #include "core/fpdfapi/page/cpdf_pagemodule.h" diff --git a/core/fpdfapi/page/cpdf_pagemodule.h b/core/fpdfapi/page/cpdf_pagemodule.h index 49d2769f88..720ee85464 100644 --- a/core/fpdfapi/page/cpdf_pagemodule.h +++ b/core/fpdfapi/page/cpdf_pagemodule.h @@ -7,7 +7,7 @@ #ifndef CORE_FPDFAPI_PAGE_CPDF_PAGEMODULE_H_ #define CORE_FPDFAPI_PAGE_CPDF_PAGEMODULE_H_ -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_fontglobals.h" #include "core/fpdfapi/page/cpdf_colorspace.h" #include "core/fpdfapi/page/cpdf_devicecs.h" #include "core/fpdfapi/page/cpdf_patterncs.h" diff --git a/testing/libfuzzer/pdf_cmap_fuzzer.cc b/testing/libfuzzer/pdf_cmap_fuzzer.cc index ef0f684212..b0e41d511c 100644 --- a/testing/libfuzzer/pdf_cmap_fuzzer.cc +++ b/testing/libfuzzer/pdf_cmap_fuzzer.cc @@ -4,7 +4,7 @@ #include -#include "core/fpdfapi/font/font_int.h" +#include "core/fpdfapi/font/cpdf_cmap.h" #include "third_party/base/ptr_util.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { -- cgit v1.2.3