Allow processing fonts with indirect dict

BUG=pdfium:667

Change-Id: I6e7620948086f3f620e4cde778a4144570e1bd6d
Reviewed-on: https://pdfium-review.googlesource.com/3106
Reviewed-by: dsinclair <dsinclair@chromium.org>
Commit-Queue: Nicolás Peña <npm@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index 98e9625..f7c4630 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -243,24 +243,35 @@
 // 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<CPDF_Dictionary>();
-    fontDict->SetNewFor<CPDF_Name>("Type", "Font");
-    fontDict->SetNewFor<CPDF_Name>("Subtype", "Type1");
-    fontDict->SetNewFor<CPDF_Name>("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<CPDF_Dictionary>();
+      fontDict->SetNewFor<CPDF_Name>("Type", "Font");
+      fontDict->SetNewFor<CPDF_Name>("Subtype", fontD.type);
+      fontDict->SetNewFor<CPDF_Name>("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 b9510b7..331cec3 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 @@
             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<CPDF_Document>(nullptr);
   pDoc->CreateNewDoc();
   CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0);
@@ -176,3 +179,54 @@
   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<CPDF_Document>(nullptr);
+  pDoc->CreateNewDoc();
+  CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0);
+  auto pTestPage = pdfium::MakeUnique<CPDF_Page>(pDoc.get(), pPageDict, false);
+  CPDF_PageContentGenerator generator(pTestPage.get());
+
+  CFX_ByteTextBuf buf;
+  {
+    // Set the text object font and text
+    auto pTextObj = pdfium::MakeUnique<CPDF_TextObject>();
+    CPDF_Dictionary* pDict = pDoc->NewIndirect<CPDF_Dictionary>();
+    pDict->SetNewFor<CPDF_Name>("Type", "Font");
+    pDict->SetNewFor<CPDF_Name>("Subtype", "TrueType");
+    CPDF_Font* pFont = CPDF_Font::GetStockFont(pDoc.get(), "Arial");
+    pDict->SetNewFor<CPDF_Name>("BaseFont", pFont->GetBaseFont());
+
+    CPDF_Dictionary* pDesc = pDoc->NewIndirect<CPDF_Dictionary>();
+    pDesc->SetNewFor<CPDF_Name>("Type", "FontDescriptor");
+    pDesc->SetNewFor<CPDF_Name>("FontName", pFont->GetBaseFont());
+    pDict->SetNewFor<CPDF_Reference>("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 46123ab..314b8ac 100644
--- a/core/fpdfapi/page/cpdf_page.cpp
+++ b/core/fpdfapi/page/cpdf_page.cpp
@@ -183,5 +183,7 @@
 }
 
 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 76587d8..076ab3f 100644
--- a/core/fpdfapi/page/cpdf_page.h
+++ b/core/fpdfapi/page/cpdf_page.h
@@ -31,6 +31,7 @@
 
 struct FontData {
   CFX_ByteString baseFont;
+  CFX_ByteString type;
   bool operator<(const FontData& other) const;
 };