• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fpdfapi/render/cpdf_docrenderdata.h"
8 
9 #include <memory>
10 
11 #include "core/fpdfapi/font/cpdf_type3font.h"
12 #include "core/fpdfapi/page/cpdf_function.h"
13 #include "core/fpdfapi/parser/cpdf_array.h"
14 #include "core/fpdfapi/parser/cpdf_document.h"
15 #include "core/fpdfapi/render/cpdf_dibsource.h"
16 #include "core/fpdfapi/render/cpdf_transferfunc.h"
17 #include "core/fpdfapi/render/cpdf_type3cache.h"
18 
19 namespace {
20 
21 const int kMaxOutputs = 16;
22 
23 }  // namespace
24 
CPDF_DocRenderData(CPDF_Document * pPDFDoc)25 CPDF_DocRenderData::CPDF_DocRenderData(CPDF_Document* pPDFDoc)
26     : m_pPDFDoc(pPDFDoc) {}
27 
~CPDF_DocRenderData()28 CPDF_DocRenderData::~CPDF_DocRenderData() {
29   Clear(true);
30 }
31 
Clear(bool bRelease)32 void CPDF_DocRenderData::Clear(bool bRelease) {
33   for (auto it = m_Type3FaceMap.begin(); it != m_Type3FaceMap.end();) {
34     auto curr_it = it++;
35     if (bRelease || curr_it->second->HasOneRef()) {
36       m_Type3FaceMap.erase(curr_it);
37     }
38   }
39 
40   for (auto it = m_TransferFuncMap.begin(); it != m_TransferFuncMap.end();) {
41     auto curr_it = it++;
42     if (bRelease || curr_it->second->HasOneRef())
43       m_TransferFuncMap.erase(curr_it);
44   }
45 }
46 
GetCachedType3(CPDF_Type3Font * pFont)47 RetainPtr<CPDF_Type3Cache> CPDF_DocRenderData::GetCachedType3(
48     CPDF_Type3Font* pFont) {
49   auto it = m_Type3FaceMap.find(pFont);
50   if (it != m_Type3FaceMap.end())
51     return it->second;
52 
53   auto pCache = pdfium::MakeRetain<CPDF_Type3Cache>(pFont);
54   m_Type3FaceMap[pFont] = pCache;
55   return pCache;
56 }
57 
MaybePurgeCachedType3(CPDF_Type3Font * pFont)58 void CPDF_DocRenderData::MaybePurgeCachedType3(CPDF_Type3Font* pFont) {
59   auto it = m_Type3FaceMap.find(pFont);
60   if (it != m_Type3FaceMap.end() && it->second->HasOneRef())
61     m_Type3FaceMap.erase(it);
62 }
63 
GetTransferFunc(CPDF_Object * pObj)64 RetainPtr<CPDF_TransferFunc> CPDF_DocRenderData::GetTransferFunc(
65     CPDF_Object* pObj) {
66   if (!pObj)
67     return nullptr;
68 
69   auto it = m_TransferFuncMap.find(pObj);
70   if (it != m_TransferFuncMap.end())
71     return it->second;
72 
73   std::unique_ptr<CPDF_Function> pFuncs[3];
74   bool bUniTransfer = true;
75   bool bIdentity = true;
76   if (CPDF_Array* pArray = pObj->AsArray()) {
77     bUniTransfer = false;
78     if (pArray->GetCount() < 3)
79       return nullptr;
80 
81     for (uint32_t i = 0; i < 3; ++i) {
82       pFuncs[2 - i] = CPDF_Function::Load(pArray->GetDirectObjectAt(i));
83       if (!pFuncs[2 - i])
84         return nullptr;
85     }
86   } else {
87     pFuncs[0] = CPDF_Function::Load(pObj);
88     if (!pFuncs[0])
89       return nullptr;
90   }
91   auto pTransfer = pdfium::MakeRetain<CPDF_TransferFunc>(m_pPDFDoc.Get());
92   m_TransferFuncMap[pObj] = pTransfer;
93 
94   float input;
95   int noutput;
96   float output[kMaxOutputs];
97   memset(output, 0, sizeof(output));
98   for (int v = 0; v < 256; ++v) {
99     input = (float)v / 255.0f;
100     if (bUniTransfer) {
101       if (pFuncs[0] && pFuncs[0]->CountOutputs() <= kMaxOutputs)
102         pFuncs[0]->Call(&input, 1, output, &noutput);
103       int o = FXSYS_round(output[0] * 255);
104       if (o != v)
105         bIdentity = false;
106       for (int i = 0; i < 3; ++i)
107         pTransfer->GetSamples()[i * 256 + v] = o;
108       continue;
109     }
110     for (int i = 0; i < 3; ++i) {
111       if (!pFuncs[i] || pFuncs[i]->CountOutputs() > kMaxOutputs) {
112         pTransfer->GetSamples()[i * 256 + v] = v;
113         continue;
114       }
115       pFuncs[i]->Call(&input, 1, output, &noutput);
116       int o = FXSYS_round(output[0] * 255);
117       if (o != v)
118         bIdentity = false;
119       pTransfer->GetSamples()[i * 256 + v] = o;
120     }
121   }
122 
123   pTransfer->SetIdentity(bIdentity);
124   return pTransfer;
125 }
126 
MaybePurgeTransferFunc(CPDF_Object * pObj)127 void CPDF_DocRenderData::MaybePurgeTransferFunc(CPDF_Object* pObj) {
128   auto it = m_TransferFuncMap.find(pObj);
129   if (it != m_TransferFuncMap.end() && it->second->HasOneRef())
130     m_TransferFuncMap.erase(it);
131 }
132