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 25 CPDF_DocRenderData::CPDF_DocRenderData(CPDF_Document* pPDFDoc) 26 : m_pPDFDoc(pPDFDoc) {} 27 28 CPDF_DocRenderData::~CPDF_DocRenderData() { 29 Clear(true); 30 } 31 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 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 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 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 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