• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The PDFium Authors
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 <stdint.h>
10 
11 #include <algorithm>
12 #include <array>
13 #include <memory>
14 #include <utility>
15 
16 #include "core/fpdfapi/font/cpdf_type3font.h"
17 #include "core/fpdfapi/page/cpdf_dib.h"
18 #include "core/fpdfapi/page/cpdf_function.h"
19 #include "core/fpdfapi/page/cpdf_transferfunc.h"
20 #include "core/fpdfapi/parser/cpdf_array.h"
21 #include "core/fpdfapi/parser/cpdf_document.h"
22 #include "core/fpdfapi/render/cpdf_type3cache.h"
23 #include "core/fxcrt/fixed_uninit_data_vector.h"
24 
25 #if BUILDFLAG(IS_WIN)
26 #include "core/fxge/win32/cfx_psfonttracker.h"
27 #endif
28 
29 namespace {
30 
31 const int kMaxOutputs = 16;
32 
33 }  // namespace
34 
35 // static
FromDocument(const CPDF_Document * pDoc)36 CPDF_DocRenderData* CPDF_DocRenderData::FromDocument(
37     const CPDF_Document* pDoc) {
38   return static_cast<CPDF_DocRenderData*>(pDoc->GetRenderData());
39 }
40 
41 CPDF_DocRenderData::CPDF_DocRenderData() = default;
42 
43 CPDF_DocRenderData::~CPDF_DocRenderData() = default;
44 
GetCachedType3(CPDF_Type3Font * pFont)45 RetainPtr<CPDF_Type3Cache> CPDF_DocRenderData::GetCachedType3(
46     CPDF_Type3Font* pFont) {
47   auto it = m_Type3FaceMap.find(pFont);
48   if (it != m_Type3FaceMap.end() && it->second)
49     return pdfium::WrapRetain(it->second.Get());
50 
51   auto pCache = pdfium::MakeRetain<CPDF_Type3Cache>(pFont);
52   m_Type3FaceMap[pFont].Reset(pCache.Get());
53   return pCache;
54 }
55 
GetTransferFunc(RetainPtr<const CPDF_Object> pObj)56 RetainPtr<CPDF_TransferFunc> CPDF_DocRenderData::GetTransferFunc(
57     RetainPtr<const CPDF_Object> pObj) {
58   if (!pObj)
59     return nullptr;
60 
61   auto it = m_TransferFuncMap.find(pObj);
62   if (it != m_TransferFuncMap.end() && it->second)
63     return pdfium::WrapRetain(it->second.Get());
64 
65   auto pFunc = CreateTransferFunc(pObj);
66   m_TransferFuncMap[pObj].Reset(pFunc.Get());
67   return pFunc;
68 }
69 
70 #if BUILDFLAG(IS_WIN)
GetPSFontTracker()71 CFX_PSFontTracker* CPDF_DocRenderData::GetPSFontTracker() {
72   if (!m_PSFontTracker)
73     m_PSFontTracker = std::make_unique<CFX_PSFontTracker>();
74   return m_PSFontTracker.get();
75 }
76 #endif
77 
CreateTransferFunc(RetainPtr<const CPDF_Object> pObj) const78 RetainPtr<CPDF_TransferFunc> CPDF_DocRenderData::CreateTransferFunc(
79     RetainPtr<const CPDF_Object> pObj) const {
80   std::unique_ptr<CPDF_Function> pFuncs[3];
81   const CPDF_Array* pArray = pObj->AsArray();
82   if (pArray) {
83     if (pArray->size() < 3)
84       return nullptr;
85 
86     for (uint32_t i = 0; i < 3; ++i) {
87       pFuncs[2 - i] = CPDF_Function::Load(pArray->GetDirectObjectAt(i));
88       if (!pFuncs[2 - i])
89         return nullptr;
90     }
91   } else {
92     pFuncs[0] = CPDF_Function::Load(pObj);
93     if (!pFuncs[0])
94       return nullptr;
95   }
96 
97   float output[kMaxOutputs];
98   std::fill(std::begin(output), std::end(output), 0.0f);
99 
100   bool bIdentity = true;
101   FixedUninitDataVector<uint8_t> samples_r(
102       CPDF_TransferFunc::kChannelSampleSize);
103   FixedUninitDataVector<uint8_t> samples_g(
104       CPDF_TransferFunc::kChannelSampleSize);
105   FixedUninitDataVector<uint8_t> samples_b(
106       CPDF_TransferFunc::kChannelSampleSize);
107   std::array<pdfium::span<uint8_t>, 3> samples = {samples_r.writable_span(),
108                                                   samples_g.writable_span(),
109                                                   samples_b.writable_span()};
110   if (pArray) {
111     for (size_t v = 0; v < CPDF_TransferFunc::kChannelSampleSize; ++v) {
112       float input = static_cast<float>(v) / 255.0f;
113       for (int i = 0; i < 3; ++i) {
114         if (pFuncs[i]->CountOutputs() > kMaxOutputs) {
115           samples[i][v] = v;
116           continue;
117         }
118         pFuncs[i]->Call(pdfium::make_span(&input, 1), output);
119         size_t o = FXSYS_roundf(output[0] * 255);
120         if (o != v)
121           bIdentity = false;
122         samples[i][v] = o;
123       }
124     }
125   } else {
126     for (size_t v = 0; v < CPDF_TransferFunc::kChannelSampleSize; ++v) {
127       float input = static_cast<float>(v) / 255.0f;
128       if (pFuncs[0]->CountOutputs() <= kMaxOutputs)
129         pFuncs[0]->Call(pdfium::make_span(&input, 1), output);
130       size_t o = FXSYS_roundf(output[0] * 255);
131       if (o != v)
132         bIdentity = false;
133       for (auto& channel : samples)
134         channel[v] = o;
135     }
136   }
137 
138   return pdfium::MakeRetain<CPDF_TransferFunc>(bIdentity, std::move(samples_r),
139                                                std::move(samples_g),
140                                                std::move(samples_b));
141 }
142