diff options
Diffstat (limited to 'core/fpdfapi/render/cpdf_docrenderdata.cpp')
-rw-r--r-- | core/fpdfapi/render/cpdf_docrenderdata.cpp | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/core/fpdfapi/render/cpdf_docrenderdata.cpp b/core/fpdfapi/render/cpdf_docrenderdata.cpp new file mode 100644 index 0000000000..9a1691711b --- /dev/null +++ b/core/fpdfapi/render/cpdf_docrenderdata.cpp @@ -0,0 +1,153 @@ +// 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/pageint.h" +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/render/cpdf_type3cache.h" +#include "core/fpdfapi/render/render_int.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++; + CPDF_CountedObject<CPDF_Type3Cache>* cache = curr_it->second; + if (bRelease || cache->use_count() < 2) { + delete cache->get(); + delete cache; + m_Type3FaceMap.erase(curr_it); + } + } + + for (auto it = m_TransferFuncMap.begin(); it != m_TransferFuncMap.end();) { + auto curr_it = it++; + CPDF_CountedObject<CPDF_TransferFunc>* value = curr_it->second; + if (bRelease || value->use_count() < 2) { + delete value->get(); + delete value; + m_TransferFuncMap.erase(curr_it); + } + } +} + +CPDF_Type3Cache* CPDF_DocRenderData::GetCachedType3(CPDF_Type3Font* pFont) { + CPDF_CountedObject<CPDF_Type3Cache>* pCache; + auto it = m_Type3FaceMap.find(pFont); + if (it == m_Type3FaceMap.end()) { + CPDF_Type3Cache* pType3 = new CPDF_Type3Cache(pFont); + pCache = new CPDF_CountedObject<CPDF_Type3Cache>(pType3); + m_Type3FaceMap[pFont] = pCache; + } else { + pCache = it->second; + } + return pCache->AddRef(); +} + +void CPDF_DocRenderData::ReleaseCachedType3(CPDF_Type3Font* pFont) { + auto it = m_Type3FaceMap.find(pFont); + if (it != m_Type3FaceMap.end()) { + it->second->RemoveRef(); + if (it->second->use_count() < 2) { + delete it->second->get(); + delete it->second; + m_Type3FaceMap.erase(it); + } + } +} + +CPDF_TransferFunc* CPDF_DocRenderData::GetTransferFunc(CPDF_Object* pObj) { + if (!pObj) + return nullptr; + + auto it = m_TransferFuncMap.find(pObj); + if (it != m_TransferFuncMap.end()) { + CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter = it->second; + return pTransferCounter->AddRef(); + } + + 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; + } + CPDF_TransferFunc* pTransfer = new CPDF_TransferFunc(m_pPDFDoc); + CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter = + new CPDF_CountedObject<CPDF_TransferFunc>(pTransfer); + m_TransferFuncMap[pObj] = pTransferCounter; + FX_FLOAT output[kMaxOutputs]; + FXSYS_memset(output, 0, sizeof(output)); + FX_FLOAT input; + int noutput; + for (int v = 0; v < 256; ++v) { + input = (FX_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 pTransferCounter->AddRef(); +} + +void CPDF_DocRenderData::ReleaseTransferFunc(CPDF_Object* pObj) { + auto it = m_TransferFuncMap.find(pObj); + if (it != m_TransferFuncMap.end()) { + it->second->RemoveRef(); + if (it->second->use_count() < 2) { + delete it->second->get(); + delete it->second; + m_TransferFuncMap.erase(it); + } + } +} |