Home | History | Annotate | Download | only in render
      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