• 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/pageint.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     CPDF_CountedObject<CPDF_Type3Cache>* cache = curr_it->second;
36     if (bRelease || cache->use_count() < 2) {
37       delete cache->get();
38       delete cache;
39       m_Type3FaceMap.erase(curr_it);
40     }
41   }
42 
43   for (auto it = m_TransferFuncMap.begin(); it != m_TransferFuncMap.end();) {
44     auto curr_it = it++;
45     CPDF_CountedObject<CPDF_TransferFunc>* value = curr_it->second;
46     if (bRelease || value->use_count() < 2) {
47       delete value->get();
48       delete value;
49       m_TransferFuncMap.erase(curr_it);
50     }
51   }
52 }
53 
GetCachedType3(CPDF_Type3Font * pFont)54 CPDF_Type3Cache* CPDF_DocRenderData::GetCachedType3(CPDF_Type3Font* pFont) {
55   CPDF_CountedObject<CPDF_Type3Cache>* pCache;
56   auto it = m_Type3FaceMap.find(pFont);
57   if (it == m_Type3FaceMap.end()) {
58     pCache = new CPDF_CountedObject<CPDF_Type3Cache>(
59         pdfium::MakeUnique<CPDF_Type3Cache>(pFont));
60     m_Type3FaceMap[pFont] = pCache;
61   } else {
62     pCache = it->second;
63   }
64   return pCache->AddRef();
65 }
66 
ReleaseCachedType3(CPDF_Type3Font * pFont)67 void CPDF_DocRenderData::ReleaseCachedType3(CPDF_Type3Font* pFont) {
68   auto it = m_Type3FaceMap.find(pFont);
69   if (it != m_Type3FaceMap.end()) {
70     it->second->RemoveRef();
71     if (it->second->use_count() < 2) {
72       delete it->second->get();
73       delete it->second;
74       m_Type3FaceMap.erase(it);
75     }
76   }
77 }
78 
GetTransferFunc(CPDF_Object * pObj)79 CPDF_TransferFunc* CPDF_DocRenderData::GetTransferFunc(CPDF_Object* pObj) {
80   if (!pObj)
81     return nullptr;
82 
83   auto it = m_TransferFuncMap.find(pObj);
84   if (it != m_TransferFuncMap.end()) {
85     CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter = it->second;
86     return pTransferCounter->AddRef();
87   }
88 
89   std::unique_ptr<CPDF_Function> pFuncs[3];
90   bool bUniTransfer = true;
91   bool bIdentity = true;
92   if (CPDF_Array* pArray = pObj->AsArray()) {
93     bUniTransfer = false;
94     if (pArray->GetCount() < 3)
95       return nullptr;
96 
97     for (uint32_t i = 0; i < 3; ++i) {
98       pFuncs[2 - i] = CPDF_Function::Load(pArray->GetDirectObjectAt(i));
99       if (!pFuncs[2 - i])
100         return nullptr;
101     }
102   } else {
103     pFuncs[0] = CPDF_Function::Load(pObj);
104     if (!pFuncs[0])
105       return nullptr;
106   }
107   CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter =
108       new CPDF_CountedObject<CPDF_TransferFunc>(
109           pdfium::MakeUnique<CPDF_TransferFunc>(m_pPDFDoc));
110   CPDF_TransferFunc* pTransfer = pTransferCounter->get();
111   m_TransferFuncMap[pObj] = pTransferCounter;
112   FX_FLOAT output[kMaxOutputs];
113   FXSYS_memset(output, 0, sizeof(output));
114   FX_FLOAT input;
115   int noutput;
116   for (int v = 0; v < 256; ++v) {
117     input = (FX_FLOAT)v / 255.0f;
118     if (bUniTransfer) {
119       if (pFuncs[0] && pFuncs[0]->CountOutputs() <= kMaxOutputs)
120         pFuncs[0]->Call(&input, 1, output, noutput);
121       int o = FXSYS_round(output[0] * 255);
122       if (o != v)
123         bIdentity = false;
124       for (int i = 0; i < 3; ++i)
125         pTransfer->m_Samples[i * 256 + v] = o;
126       continue;
127     }
128     for (int i = 0; i < 3; ++i) {
129       if (!pFuncs[i] || pFuncs[i]->CountOutputs() > kMaxOutputs) {
130         pTransfer->m_Samples[i * 256 + v] = v;
131         continue;
132       }
133       pFuncs[i]->Call(&input, 1, output, noutput);
134       int o = FXSYS_round(output[0] * 255);
135       if (o != v)
136         bIdentity = false;
137       pTransfer->m_Samples[i * 256 + v] = o;
138     }
139   }
140 
141   pTransfer->m_bIdentity = bIdentity;
142   return pTransferCounter->AddRef();
143 }
144 
ReleaseTransferFunc(CPDF_Object * pObj)145 void CPDF_DocRenderData::ReleaseTransferFunc(CPDF_Object* pObj) {
146   auto it = m_TransferFuncMap.find(pObj);
147   if (it != m_TransferFuncMap.end()) {
148     it->second->RemoveRef();
149     if (it->second->use_count() < 2) {
150       delete it->second->get();
151       delete it->second;
152       m_TransferFuncMap.erase(it);
153     }
154   }
155 }
156