From 35292ad2070aa3cabdef4ea23ffaaf38e1a7de3a Mon Sep 17 00:00:00 2001 From: Nicolas Pena Date: Mon, 20 Mar 2017 15:20:58 -0400 Subject: Allow processing fonts with indirect dict MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG=pdfium:667 Change-Id: I6e7620948086f3f620e4cde778a4144570e1bd6d Reviewed-on: https://pdfium-review.googlesource.com/3106 Reviewed-by: dsinclair Commit-Queue: Nicolás Peña --- core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp | 25 +++++++--- .../edit/cpdf_pagecontentgenerator_unittest.cpp | 56 +++++++++++++++++++++- core/fpdfapi/page/cpdf_page.cpp | 4 +- core/fpdfapi/page/cpdf_page.h | 1 + 4 files changed, 77 insertions(+), 9 deletions(-) diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp index 98e96255c6..f7c4630063 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp @@ -243,24 +243,35 @@ void CPDF_PageContentGenerator::ProcessGraphics(CFX_ByteTextBuf* buf, // Tj sets the actual text, <####...> is used when specifying charcodes. void CPDF_PageContentGenerator::ProcessText(CFX_ByteTextBuf* buf, CPDF_TextObject* pTextObj) { - // TODO(npm): Add support for something other than standard type1 fonts. *buf << "BT " << pTextObj->GetTextMatrix() << " Tm "; CPDF_Font* pFont = pTextObj->GetFont(); if (!pFont) pFont = CPDF_Font::GetStockFont(m_pDocument, "Helvetica"); FontData fontD; + if (pFont->IsType1Font()) + fontD.type = "Type1"; + else if (pFont->IsTrueTypeFont()) + fontD.type = "TrueType"; + else if (pFont->IsCIDFont()) + fontD.type = "Type0"; + else + return; fontD.baseFont = pFont->GetBaseFont(); auto it = m_pPage->m_FontsMap.find(fontD); CFX_ByteString dictName; if (it != m_pPage->m_FontsMap.end()) { dictName = it->second; } else { - auto fontDict = pdfium::MakeUnique(); - fontDict->SetNewFor("Type", "Font"); - fontDict->SetNewFor("Subtype", "Type1"); - fontDict->SetNewFor("BaseFont", fontD.baseFont); - CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(fontDict)); - uint32_t dwObjNum = pDict->GetObjNum(); + uint32_t dwObjNum = pFont->GetFontDict()->GetObjNum(); + if (!dwObjNum) { + // In this case we assume it must be a standard font + auto fontDict = pdfium::MakeUnique(); + fontDict->SetNewFor("Type", "Font"); + fontDict->SetNewFor("Subtype", fontD.type); + fontDict->SetNewFor("BaseFont", fontD.baseFont); + CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(fontDict)); + dwObjNum = pDict->GetObjNum(); + } dictName = RealizeResource(dwObjNum, "Font"); m_pPage->m_FontsMap[fontD] = dictName; } diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp index b9510b7803..331cec3813 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp @@ -10,7 +10,9 @@ #include "core/fpdfapi/page/cpdf_pathobject.h" #include "core/fpdfapi/page/cpdf_textobject.h" #include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/cpdf_name.h" #include "core/fpdfapi/parser/cpdf_parser.h" +#include "core/fpdfapi/parser/cpdf_reference.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/base/ptr_util.h" @@ -151,7 +153,8 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessGraphics) { pathString2.Mid(55, pathString2.GetLength() - 83)); } -TEST_F(CPDF_PageContentGeneratorTest, ProcessText) { +TEST_F(CPDF_PageContentGeneratorTest, ProcessStandardText) { + // Checking font whose font dictionary is not yet indirect object. auto pDoc = pdfium::MakeUnique(nullptr); pDoc->CreateNewDoc(); CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0); @@ -176,3 +179,54 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessText) { EXPECT_EQ("Type1", fontDict->GetStringFor("Subtype")); EXPECT_EQ("Times-Roman", fontDict->GetStringFor("BaseFont")); } + +TEST_F(CPDF_PageContentGeneratorTest, ProcessText) { + // Checking font whose font dictionary is already an indirect object. + auto pDoc = pdfium::MakeUnique(nullptr); + pDoc->CreateNewDoc(); + CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0); + auto pTestPage = pdfium::MakeUnique(pDoc.get(), pPageDict, false); + CPDF_PageContentGenerator generator(pTestPage.get()); + + CFX_ByteTextBuf buf; + { + // Set the text object font and text + auto pTextObj = pdfium::MakeUnique(); + CPDF_Dictionary* pDict = pDoc->NewIndirect(); + pDict->SetNewFor("Type", "Font"); + pDict->SetNewFor("Subtype", "TrueType"); + CPDF_Font* pFont = CPDF_Font::GetStockFont(pDoc.get(), "Arial"); + pDict->SetNewFor("BaseFont", pFont->GetBaseFont()); + + CPDF_Dictionary* pDesc = pDoc->NewIndirect(); + pDesc->SetNewFor("Type", "FontDescriptor"); + pDesc->SetNewFor("FontName", pFont->GetBaseFont()); + pDict->SetNewFor("FontDescriptor", pDoc.get(), + pDesc->GetObjNum()); + + CPDF_Font* loadedFont = pDoc->LoadFont(pDict); + pTextObj->m_TextState.SetFont(loadedFont); + pTextObj->m_TextState.SetFontSize(15.5f); + pTextObj->SetText("I am indirect"); + + TestProcessText(&generator, &buf, pTextObj.get()); + } + + CFX_ByteString textString = buf.MakeString(); + EXPECT_LT(63, textString.GetLength()); + EXPECT_EQ("BT 1 0 0 1 0 0 Tm /", textString.Left(19)); + EXPECT_EQ(" 15.5 Tf <4920616D20696E646972656374> Tj ET\n", + textString.Right(44)); + CPDF_Dictionary* fontDict = TestGetResource( + &generator, "Font", textString.Mid(19, textString.GetLength() - 63)); + ASSERT_TRUE(fontDict); + EXPECT_TRUE(fontDict->GetObjNum()); + EXPECT_EQ("Font", fontDict->GetStringFor("Type")); + EXPECT_EQ("TrueType", fontDict->GetStringFor("Subtype")); + EXPECT_EQ("Helvetica", fontDict->GetStringFor("BaseFont")); + CPDF_Dictionary* fontDesc = fontDict->GetDictFor("FontDescriptor"); + ASSERT_TRUE(fontDesc); + EXPECT_TRUE(fontDesc->GetObjNum()); + EXPECT_EQ("FontDescriptor", fontDesc->GetStringFor("Type")); + EXPECT_EQ("Helvetica", fontDesc->GetStringFor("FontName")); +} diff --git a/core/fpdfapi/page/cpdf_page.cpp b/core/fpdfapi/page/cpdf_page.cpp index 46123ab42e..314b8acbaa 100644 --- a/core/fpdfapi/page/cpdf_page.cpp +++ b/core/fpdfapi/page/cpdf_page.cpp @@ -183,5 +183,7 @@ bool GraphicsData::operator<(const GraphicsData& other) const { } bool FontData::operator<(const FontData& other) const { - return baseFont < other.baseFont; + if (baseFont != other.baseFont) + return baseFont < other.baseFont; + return type < other.type; } diff --git a/core/fpdfapi/page/cpdf_page.h b/core/fpdfapi/page/cpdf_page.h index 76587d8c32..076ab3f93b 100644 --- a/core/fpdfapi/page/cpdf_page.h +++ b/core/fpdfapi/page/cpdf_page.h @@ -31,6 +31,7 @@ struct GraphicsData { struct FontData { CFX_ByteString baseFont; + CFX_ByteString type; bool operator<(const FontData& other) const; }; -- cgit v1.2.3