| // Copyright 2016 PDFium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| |
| #include "core/fpdfapi/render/cpdf_docrenderdata.h" |
| |
| #include <memory> |
| |
| #include "core/fpdfapi/font/cpdf_type3font.h" |
| #include "core/fpdfapi/page/cpdf_function.h" |
| #include "core/fpdfapi/parser/cpdf_array.h" |
| #include "core/fpdfapi/parser/cpdf_document.h" |
| #include "core/fpdfapi/render/cpdf_dibsource.h" |
| #include "core/fpdfapi/render/cpdf_transferfunc.h" |
| #include "core/fpdfapi/render/cpdf_type3cache.h" |
| |
| namespace { |
| |
| const int kMaxOutputs = 16; |
| |
| } // namespace |
| |
| CPDF_DocRenderData::CPDF_DocRenderData(CPDF_Document* pPDFDoc) |
| : m_pPDFDoc(pPDFDoc) {} |
| |
| CPDF_DocRenderData::~CPDF_DocRenderData() { |
| Clear(true); |
| } |
| |
| void CPDF_DocRenderData::Clear(bool bRelease) { |
| for (auto it = m_Type3FaceMap.begin(); it != m_Type3FaceMap.end();) { |
| auto curr_it = it++; |
| if (bRelease || curr_it->second->HasOneRef()) { |
| m_Type3FaceMap.erase(curr_it); |
| } |
| } |
| |
| for (auto it = m_TransferFuncMap.begin(); it != m_TransferFuncMap.end();) { |
| auto curr_it = it++; |
| if (bRelease || curr_it->second->HasOneRef()) |
| m_TransferFuncMap.erase(curr_it); |
| } |
| } |
| |
| CFX_RetainPtr<CPDF_Type3Cache> CPDF_DocRenderData::GetCachedType3( |
| CPDF_Type3Font* pFont) { |
| auto it = m_Type3FaceMap.find(pFont); |
| if (it != m_Type3FaceMap.end()) |
| return it->second; |
| |
| auto pCache = pdfium::MakeRetain<CPDF_Type3Cache>(pFont); |
| m_Type3FaceMap[pFont] = pCache; |
| return pCache; |
| } |
| |
| void CPDF_DocRenderData::MaybePurgeCachedType3(CPDF_Type3Font* pFont) { |
| auto it = m_Type3FaceMap.find(pFont); |
| if (it != m_Type3FaceMap.end() && it->second->HasOneRef()) |
| m_Type3FaceMap.erase(it); |
| } |
| |
| CFX_RetainPtr<CPDF_TransferFunc> CPDF_DocRenderData::GetTransferFunc( |
| CPDF_Object* pObj) { |
| if (!pObj) |
| return nullptr; |
| |
| auto it = m_TransferFuncMap.find(pObj); |
| if (it != m_TransferFuncMap.end()) |
| return it->second; |
| |
| std::unique_ptr<CPDF_Function> pFuncs[3]; |
| bool bUniTransfer = true; |
| bool bIdentity = true; |
| if (CPDF_Array* pArray = pObj->AsArray()) { |
| bUniTransfer = false; |
| if (pArray->GetCount() < 3) |
| return nullptr; |
| |
| for (uint32_t i = 0; i < 3; ++i) { |
| pFuncs[2 - i] = CPDF_Function::Load(pArray->GetDirectObjectAt(i)); |
| if (!pFuncs[2 - i]) |
| return nullptr; |
| } |
| } else { |
| pFuncs[0] = CPDF_Function::Load(pObj); |
| if (!pFuncs[0]) |
| return nullptr; |
| } |
| auto pTransfer = pdfium::MakeRetain<CPDF_TransferFunc>(m_pPDFDoc.Get()); |
| m_TransferFuncMap[pObj] = pTransfer; |
| |
| float input; |
| int noutput; |
| float output[kMaxOutputs]; |
| memset(output, 0, sizeof(output)); |
| for (int v = 0; v < 256; ++v) { |
| input = (float)v / 255.0f; |
| if (bUniTransfer) { |
| if (pFuncs[0] && pFuncs[0]->CountOutputs() <= kMaxOutputs) |
| pFuncs[0]->Call(&input, 1, output, &noutput); |
| int o = FXSYS_round(output[0] * 255); |
| if (o != v) |
| bIdentity = false; |
| for (int i = 0; i < 3; ++i) |
| pTransfer->m_Samples[i * 256 + v] = o; |
| continue; |
| } |
| for (int i = 0; i < 3; ++i) { |
| if (!pFuncs[i] || pFuncs[i]->CountOutputs() > kMaxOutputs) { |
| pTransfer->m_Samples[i * 256 + v] = v; |
| continue; |
| } |
| pFuncs[i]->Call(&input, 1, output, &noutput); |
| int o = FXSYS_round(output[0] * 255); |
| if (o != v) |
| bIdentity = false; |
| pTransfer->m_Samples[i * 256 + v] = o; |
| } |
| } |
| |
| pTransfer->m_bIdentity = bIdentity; |
| return pTransfer; |
| } |
| |
| void CPDF_DocRenderData::MaybePurgeTransferFunc(CPDF_Object* pObj) { |
| auto it = m_TransferFuncMap.find(pObj); |
| if (it != m_TransferFuncMap.end() && it->second->HasOneRef()) |
| m_TransferFuncMap.erase(it); |
| } |