14d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Copyright 2016 PDFium Authors. All rights reserved.
24d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Use of this source code is governed by a BSD-style license that can be
34d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// found in the LICENSE file.
44d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
54d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
64d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
74d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/edit/cpdf_pagecontentgenerator.h"
84d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann#include <tuple>
1033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann#include <utility>
1133357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann
1233357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann#include "core/fpdfapi/font/cpdf_font.h"
134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/page/cpdf_docpagedata.h"
144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/page/cpdf_image.h"
154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/page/cpdf_imageobject.h"
164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/page/cpdf_page.h"
1733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann#include "core/fpdfapi/page/cpdf_path.h"
1833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann#include "core/fpdfapi/page/cpdf_pathobject.h"
1933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann#include "core/fpdfapi/page/cpdf_textobject.h"
20d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fpdfapi/parser/cpdf_array.h"
214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/cpdf_dictionary.h"
224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/cpdf_document.h"
234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/cpdf_name.h"
2433357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann#include "core/fpdfapi/parser/cpdf_number.h"
254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/cpdf_reference.h"
264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/cpdf_stream.h"
274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/fpdf_parser_decode.h"
284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannnamespace {
304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
31d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannstd::ostream& operator<<(std::ostream& ar, const CFX_Matrix& matrix) {
324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  ar << matrix.a << " " << matrix.b << " " << matrix.c << " " << matrix.d << " "
334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann     << matrix.e << " " << matrix.f;
344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return ar;
354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
37d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannbool GetColor(const CPDF_Color* pColor, float* rgb) {
3833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  int intRGB[3];
3933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  if (!pColor ||
4033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann      pColor->GetColorSpace() != CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB) ||
41d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      !pColor->GetRGB(&intRGB[0], &intRGB[1], &intRGB[2])) {
4233357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    return false;
4333357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  }
4433357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  rgb[0] = intRGB[0] / 255.0f;
4533357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  rgb[1] = intRGB[1] / 255.0f;
4633357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  rgb[2] = intRGB[2] / 255.0f;
4733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  return true;
4833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann}
4933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann
504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}  // namespace
514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
52d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_PageContentGenerator::CPDF_PageContentGenerator(
53d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    CPDF_PageObjectHolder* pObjHolder)
54d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    : m_pObjHolder(pObjHolder), m_pDocument(pObjHolder->m_pDocument.Get()) {
55d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  for (const auto& pObj : *pObjHolder->GetPageObjectList()) {
564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (pObj)
57d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_pageObjects.emplace_back(pObj.get());
584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. MoltmannCPDF_PageContentGenerator::~CPDF_PageContentGenerator() {}
624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid CPDF_PageContentGenerator::GenerateContent() {
64d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ASSERT(m_pObjHolder->IsPage());
65d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
66d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CPDF_Document* pDoc = m_pDocument.Get();
67d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  std::ostringstream buf;
684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
69d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // Set the default graphic state values
70d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  buf << "q\n";
71d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!m_pObjHolder->GetLastCTM().IsIdentity())
72d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    buf << m_pObjHolder->GetLastCTM().GetInverse() << " cm\n";
73d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ProcessDefaultGraphics(&buf);
74d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
75d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // Process the page objects
76d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!ProcessPageObjects(&buf))
77d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return;
78d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
79d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // Return graphics to original state
80d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  buf << "Q\n";
81d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
82d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  // Add buffer to a stream in page's 'Contents'
83d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CPDF_Dictionary* pPageDict = m_pObjHolder->m_pFormDict.Get();
84d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CPDF_Object* pContent =
85d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pPageDict ? pPageDict->GetObjectFor("Contents") : nullptr;
86d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CPDF_Stream* pStream = pDoc->NewIndirect<CPDF_Stream>();
87d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  pStream->SetData(&buf);
88d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (pContent) {
89d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    CPDF_Array* pArray = ToArray(pContent);
90d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (pArray) {
91d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pArray->AddNew<CPDF_Reference>(pDoc, pStream->GetObjNum());
92d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return;
93d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
94d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    CPDF_Reference* pReference = ToReference(pContent);
95d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (!pReference) {
96d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pPageDict->SetNewFor<CPDF_Reference>("Contents", m_pDocument.Get(),
97d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                           pStream->GetObjNum());
98d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return;
99d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
100d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    CPDF_Object* pDirectObj = pReference->GetDirect();
101d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (!pDirectObj) {
102d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pPageDict->SetNewFor<CPDF_Reference>("Contents", m_pDocument.Get(),
103d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                           pStream->GetObjNum());
104d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return;
105d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
106d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    CPDF_Array* pObjArray = pDirectObj->AsArray();
107d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (pObjArray) {
108d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pObjArray->AddNew<CPDF_Reference>(pDoc, pStream->GetObjNum());
109d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return;
110d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
111d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (pDirectObj->IsStream()) {
112d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      CPDF_Array* pContentArray = pDoc->NewIndirect<CPDF_Array>();
113d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pContentArray->AddNew<CPDF_Reference>(pDoc, pDirectObj->GetObjNum());
114d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pContentArray->AddNew<CPDF_Reference>(pDoc, pStream->GetObjNum());
115d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pPageDict->SetNewFor<CPDF_Reference>("Contents", pDoc,
116d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                           pContentArray->GetObjNum());
117d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return;
118d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
119d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
120d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  pPageDict->SetNewFor<CPDF_Reference>("Contents", m_pDocument.Get(),
1214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                       pStream->GetObjNum());
1224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
1234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
124d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannByteString CPDF_PageContentGenerator::RealizeResource(
1254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    uint32_t dwResourceObjNum,
126d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    const ByteString& bsType) {
1274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  ASSERT(dwResourceObjNum);
128d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!m_pObjHolder->m_pResources) {
129d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    m_pObjHolder->m_pResources = m_pDocument->NewIndirect<CPDF_Dictionary>();
130d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    m_pObjHolder->m_pFormDict->SetNewFor<CPDF_Reference>(
131d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        "Resources", m_pDocument.Get(),
132d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        m_pObjHolder->m_pResources->GetObjNum());
1334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
134d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CPDF_Dictionary* pResList = m_pObjHolder->m_pResources->GetDictFor(bsType);
1354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!pResList)
136d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pResList = m_pObjHolder->m_pResources->SetNewFor<CPDF_Dictionary>(bsType);
1374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
138d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ByteString name;
1394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int idnum = 1;
1404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  while (1) {
141d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    name = ByteString::Format("FX%c%d", bsType[0], idnum);
142d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (!pResList->KeyExist(name))
1434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      break;
144d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
1454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    idnum++;
1464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
147d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  pResList->SetNewFor<CPDF_Reference>(name, m_pDocument.Get(),
148d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                      dwResourceObjNum);
1494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return name;
1504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
1514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
152d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannbool CPDF_PageContentGenerator::ProcessPageObjects(std::ostringstream* buf) {
153d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  bool bDirty = false;
154d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  for (auto& pPageObj : m_pageObjects) {
155d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (m_pObjHolder->IsPage() && !pPageObj->IsDirty())
156d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      continue;
157d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
158d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    bDirty = true;
159d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (CPDF_ImageObject* pImageObject = pPageObj->AsImage())
160d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      ProcessImage(buf, pImageObject);
161d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    else if (CPDF_PathObject* pPathObj = pPageObj->AsPath())
162d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      ProcessPath(buf, pPathObj);
163d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    else if (CPDF_TextObject* pTextObj = pPageObj->AsText())
164d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      ProcessText(buf, pTextObj);
165d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pPageObj->SetDirty(false);
166d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
167d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return bDirty;
168d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
169d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
170d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid CPDF_PageContentGenerator::ProcessImage(std::ostringstream* buf,
1714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                             CPDF_ImageObject* pImageObj) {
1724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if ((pImageObj->matrix().a == 0 && pImageObj->matrix().b == 0) ||
1734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      (pImageObj->matrix().c == 0 && pImageObj->matrix().d == 0)) {
1744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return;
1754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
1764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *buf << "q " << pImageObj->matrix() << " cm ";
1774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
178d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  RetainPtr<CPDF_Image> pImage = pImageObj->GetImage();
1794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (pImage->IsInline())
1804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return;
1814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CPDF_Stream* pStream = pImage->GetStream();
1834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!pStream)
1844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return;
1854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  bool bWasInline = pStream->IsInline();
1874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (bWasInline)
1884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    pImage->ConvertStreamToIndirectObject();
1894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t dwObjNum = pStream->GetObjNum();
191d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ByteString name = RealizeResource(dwObjNum, "XObject");
1924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (bWasInline)
193d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pImageObj->SetImage(m_pDocument->GetPageData()->GetImage(dwObjNum));
1944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *buf << "/" << PDF_NameEncode(name) << " Do Q\n";
1964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
19733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann
19833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// Processing path with operators from Tables 4.9 and 4.10 of PDF spec 1.7:
19933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// "re" appends a rectangle (here, used only if the whole path is a rectangle)
20033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// "m" moves current point to the given coordinates
20133357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// "l" creates a line from current point to the new point
20233357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// "c" adds a Bezier curve from current to last point, using the two other
20333357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// points as the Bezier control points
20433357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// Note: "l", "c" change the current point
20533357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// "h" closes the subpath (appends a line from current to starting point)
20633357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// Path painting operators: "S", "n", "B", "f", "B*", "f*", depending on
20733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// the filling mode and whether we want stroking the path or not.
20833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// "Q" restores the graphics state imposed by the ProcessGraphics method.
209d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid CPDF_PageContentGenerator::ProcessPath(std::ostringstream* buf,
21033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann                                            CPDF_PathObject* pPathObj) {
21133357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  ProcessGraphics(buf, pPathObj);
212d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
213d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  *buf << pPathObj->m_Matrix << " cm ";
214d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
21533357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  auto& pPoints = pPathObj->m_Path.GetPoints();
21633357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  if (pPathObj->m_Path.IsRect()) {
21733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    CFX_PointF diff = pPoints[2].m_Point - pPoints[0].m_Point;
21833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    *buf << pPoints[0].m_Point.x << " " << pPoints[0].m_Point.y << " " << diff.x
21933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann         << " " << diff.y << " re";
22033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  } else {
22133357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    for (size_t i = 0; i < pPoints.size(); i++) {
22233357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann      if (i > 0)
22333357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann        *buf << " ";
22433357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann      *buf << pPoints[i].m_Point.x << " " << pPoints[i].m_Point.y;
22533357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann      FXPT_TYPE pointType = pPoints[i].m_Type;
22633357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann      if (pointType == FXPT_TYPE::MoveTo) {
22733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann        *buf << " m";
22833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann      } else if (pointType == FXPT_TYPE::LineTo) {
22933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann        *buf << " l";
23033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann      } else if (pointType == FXPT_TYPE::BezierTo) {
23133357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann        if (i + 2 >= pPoints.size() ||
23233357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann            !pPoints[i].IsTypeAndOpen(FXPT_TYPE::BezierTo) ||
23333357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann            !pPoints[i + 1].IsTypeAndOpen(FXPT_TYPE::BezierTo) ||
23433357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann            pPoints[i + 2].m_Type != FXPT_TYPE::BezierTo) {
23533357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann          // If format is not supported, close the path and paint
23633357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann          *buf << " h";
23733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann          break;
23833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann        }
23933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann        *buf << " " << pPoints[i + 1].m_Point.x << " "
24033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann             << pPoints[i + 1].m_Point.y << " " << pPoints[i + 2].m_Point.x
24133357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann             << " " << pPoints[i + 2].m_Point.y << " c";
24233357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann        i += 2;
24333357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann      }
24433357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann      if (pPoints[i].m_CloseFigure)
24533357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann        *buf << " h";
24633357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    }
24733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  }
24833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  if (pPathObj->m_FillType == 0)
24933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    *buf << (pPathObj->m_bStroke ? " S" : " n");
25033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  else if (pPathObj->m_FillType == FXFILL_WINDING)
25133357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    *buf << (pPathObj->m_bStroke ? " B" : " f");
25233357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  else if (pPathObj->m_FillType == FXFILL_ALTERNATE)
25333357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    *buf << (pPathObj->m_bStroke ? " B*" : " f*");
25433357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  *buf << " Q\n";
25533357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann}
25633357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann
25733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// This method supports color operators rg and RGB from Table 4.24 of PDF spec
25833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// 1.7. A color will not be set if the colorspace is not DefaultRGB or the RGB
25933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// values cannot be obtained. The method also adds an external graphics
26033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// dictionary, as described in Section 4.3.4.
26133357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// "rg" sets the fill color, "RG" sets the stroke color (using DefaultRGB)
26233357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// "w" sets the stroke line width.
26333357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// "ca" sets the fill alpha, "CA" sets the stroke alpha.
26433357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// "q" saves the graphics state, so that the settings can later be reversed
265d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid CPDF_PageContentGenerator::ProcessGraphics(std::ostringstream* buf,
26633357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann                                                CPDF_PageObject* pPageObj) {
26733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  *buf << "q ";
268d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  float fillColor[3];
26933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  if (GetColor(pPageObj->m_ColorState.GetFillColor(), fillColor)) {
27033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    *buf << fillColor[0] << " " << fillColor[1] << " " << fillColor[2]
27133357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann         << " rg ";
27233357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  }
273d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  float strokeColor[3];
27433357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  if (GetColor(pPageObj->m_ColorState.GetStrokeColor(), strokeColor)) {
27533357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    *buf << strokeColor[0] << " " << strokeColor[1] << " " << strokeColor[2]
27633357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann         << " RG ";
27733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  }
278d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  float lineWidth = pPageObj->m_GraphState.GetLineWidth();
27933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  if (lineWidth != 1.0f)
28033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    *buf << lineWidth << " w ";
281d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CFX_GraphStateData::LineCap lineCap = pPageObj->m_GraphState.GetLineCap();
282d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (lineCap != CFX_GraphStateData::LineCapButt)
283d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    *buf << static_cast<int>(lineCap) << " J ";
284d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  CFX_GraphStateData::LineJoin lineJoin = pPageObj->m_GraphState.GetLineJoin();
285d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (lineJoin != CFX_GraphStateData::LineJoinMiter)
286d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    *buf << static_cast<int>(lineJoin) << " j ";
28733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann
28833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  GraphicsData graphD;
28933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  graphD.fillAlpha = pPageObj->m_GeneralState.GetFillAlpha();
29033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  graphD.strokeAlpha = pPageObj->m_GeneralState.GetStrokeAlpha();
291d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  graphD.blendType = pPageObj->m_GeneralState.GetBlendType();
292d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (graphD.fillAlpha == 1.0f && graphD.strokeAlpha == 1.0f &&
293d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      (graphD.blendType == FXDIB_BLEND_UNSUPPORTED ||
294d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       graphD.blendType == FXDIB_BLEND_NORMAL)) {
29533357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    return;
296d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
29733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann
298d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ByteString name;
299d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  auto it = m_pObjHolder->m_GraphicsMap.find(graphD);
300d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (it != m_pObjHolder->m_GraphicsMap.end()) {
30133357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    name = it->second;
30233357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  } else {
30333357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    auto gsDict = pdfium::MakeUnique<CPDF_Dictionary>();
304d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (graphD.fillAlpha != 1.0f)
305d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      gsDict->SetNewFor<CPDF_Number>("ca", graphD.fillAlpha);
306d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
307d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (graphD.strokeAlpha != 1.0f)
308d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      gsDict->SetNewFor<CPDF_Number>("CA", graphD.strokeAlpha);
309d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
310d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (graphD.blendType != FXDIB_BLEND_UNSUPPORTED &&
311d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        graphD.blendType != FXDIB_BLEND_NORMAL) {
312d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      gsDict->SetNewFor<CPDF_Name>("BM",
313d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                   pPageObj->m_GeneralState.GetBlendMode());
314d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
31533357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(gsDict));
31633357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    uint32_t dwObjNum = pDict->GetObjNum();
31733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    name = RealizeResource(dwObjNum, "ExtGState");
318d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    m_pObjHolder->m_GraphicsMap[graphD] = name;
31933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  }
32033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  *buf << "/" << PDF_NameEncode(name) << " gs ";
32133357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann}
32233357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann
323d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid CPDF_PageContentGenerator::ProcessDefaultGraphics(
324d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    std::ostringstream* buf) {
325d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  *buf << "0 0 0 RG 0 0 0 rg 1 w "
326d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       << static_cast<int>(CFX_GraphStateData::LineCapButt) << " J "
327d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann       << static_cast<int>(CFX_GraphStateData::LineJoinMiter) << " j\n";
328d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  GraphicsData defaultGraphics;
329d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  defaultGraphics.fillAlpha = 1.0f;
330d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  defaultGraphics.strokeAlpha = 1.0f;
331d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  defaultGraphics.blendType = FXDIB_BLEND_NORMAL;
332d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  auto it = m_pObjHolder->m_GraphicsMap.find(defaultGraphics);
333d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ByteString name;
334d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (it != m_pObjHolder->m_GraphicsMap.end()) {
335d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    name = it->second;
336d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  } else {
337d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    auto gsDict = pdfium::MakeUnique<CPDF_Dictionary>();
338d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    gsDict->SetNewFor<CPDF_Number>("ca", defaultGraphics.fillAlpha);
339d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    gsDict->SetNewFor<CPDF_Number>("CA", defaultGraphics.strokeAlpha);
340d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    gsDict->SetNewFor<CPDF_Name>("BM", "Normal");
341d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(gsDict));
342d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    uint32_t dwObjNum = pDict->GetObjNum();
343d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    name = RealizeResource(dwObjNum, "ExtGState");
344d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    m_pObjHolder->m_GraphicsMap[defaultGraphics] = name;
345d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
346d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  *buf << "/" << PDF_NameEncode(name).c_str() << " gs ";
347d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
348d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
34933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// This method adds text to the buffer, BT begins the text object, ET ends it.
35033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// Tm sets the text matrix (allows positioning and transforming text).
35133357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// Tf sets the font name (from Font in Resources) and font size.
35233357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann// Tj sets the actual text, <####...> is used when specifying charcodes.
353d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid CPDF_PageContentGenerator::ProcessText(std::ostringstream* buf,
35433357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann                                            CPDF_TextObject* pTextObj) {
355d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ProcessGraphics(buf, pTextObj);
35633357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  *buf << "BT " << pTextObj->GetTextMatrix() << " Tm ";
35733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  CPDF_Font* pFont = pTextObj->GetFont();
35833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  if (!pFont)
359d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pFont = CPDF_Font::GetStockFont(m_pDocument.Get(), "Helvetica");
36033357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  FontData fontD;
361d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (pFont->IsType1Font())
362d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    fontD.type = "Type1";
363d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  else if (pFont->IsTrueTypeFont())
364d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    fontD.type = "TrueType";
365d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  else if (pFont->IsCIDFont())
366d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    fontD.type = "Type0";
367d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  else
368d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return;
36933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  fontD.baseFont = pFont->GetBaseFont();
370d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  auto it = m_pObjHolder->m_FontsMap.find(fontD);
371d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ByteString dictName;
372d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (it != m_pObjHolder->m_FontsMap.end()) {
37333357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    dictName = it->second;
37433357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  } else {
375d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    uint32_t dwObjNum = pFont->GetFontDict()->GetObjNum();
376d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (!dwObjNum) {
377d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      // In this case we assume it must be a standard font
378d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      auto fontDict = pdfium::MakeUnique<CPDF_Dictionary>();
379d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      fontDict->SetNewFor<CPDF_Name>("Type", "Font");
380d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      fontDict->SetNewFor<CPDF_Name>("Subtype", fontD.type);
381d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      fontDict->SetNewFor<CPDF_Name>("BaseFont", fontD.baseFont);
382d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(fontDict));
383d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      dwObjNum = pDict->GetObjNum();
384d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
38533357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann    dictName = RealizeResource(dwObjNum, "Font");
386d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    m_pObjHolder->m_FontsMap[fontD] = dictName;
38733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  }
38833357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  *buf << "/" << PDF_NameEncode(dictName) << " " << pTextObj->GetFontSize()
38933357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann       << " Tf ";
390d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ByteString text;
391d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  for (uint32_t charcode : pTextObj->GetCharCodes()) {
392d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (charcode != CPDF_Font::kInvalidCharCode)
393d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pFont->AppendChar(&text, charcode);
39433357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann  }
395d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  *buf << PDF_EncodeString(text, true) << " Tj ET";
396d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  *buf << " Q\n";
39733357cad1fd1321a2b38d2963e2585f27ce980a2Philip P. Moltmann}
398