• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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 #include "core/fpdfapi/render/cpdf_docrenderdata.h"
6 
7 #include <iterator>
8 #include <memory>
9 #include <utility>
10 
11 #include "core/fpdfapi/page/cpdf_transferfunc.h"
12 #include "core/fpdfapi/parser/cpdf_array.h"
13 #include "core/fpdfapi/parser/cpdf_dictionary.h"
14 #include "core/fpdfapi/parser/cpdf_number.h"
15 #include "core/fpdfapi/parser/cpdf_stream.h"
16 #include "core/fxcrt/data_vector.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 
19 namespace {
20 
21 constexpr uint8_t kExpectedType0FunctionSamples[] = {
22     0,   3,   6,   9,   13,  16,  19,  22,  25,  28,  31,  34,  37,  40,  43,
23     46,  49,  52,  55,  58,  60,  63,  66,  68,  71,  74,  76,  79,  81,  84,
24     86,  88,  90,  93,  95,  97,  99,  101, 103, 105, 106, 108, 110, 111, 113,
25     114, 115, 117, 118, 119, 120, 121, 122, 123, 124, 125, 125, 126, 126, 127,
26     127, 127, 127, 127, 127, 127, 127, 127, 127, 126, 126, 125, 125, 124, 123,
27     123, 122, 121, 120, 119, 117, 116, 115, 113, 112, 110, 109, 107, 105, 104,
28     102, 100, 98,  96,  94,  92,  89,  87,  85,  82,  80,  77,  75,  72,  70,
29     67,  64,  62,  59,  56,  53,  50,  48,  45,  42,  39,  36,  33,  30,  27,
30     23,  20,  17,  14,  11,  8,   5,   2,   254, 251, 248, 245, 242, 239, 236,
31     233, 229, 226, 223, 220, 217, 214, 211, 208, 206, 203, 200, 197, 194, 192,
32     189, 186, 184, 181, 179, 176, 174, 171, 169, 167, 164, 162, 160, 158, 156,
33     154, 152, 151, 149, 147, 146, 144, 143, 141, 140, 139, 137, 136, 135, 134,
34     133, 133, 132, 131, 131, 130, 130, 129, 129, 129, 129, 129, 129, 129, 129,
35     129, 129, 130, 130, 131, 131, 132, 133, 134, 135, 136, 137, 138, 139, 141,
36     142, 143, 145, 146, 148, 150, 151, 153, 155, 157, 159, 161, 163, 166, 168,
37     170, 172, 175, 177, 180, 182, 185, 188, 190, 193, 196, 198, 201, 204, 207,
38     210, 213, 216, 219, 222, 225, 228, 231, 234, 237, 240, 243, 247, 250, 253,
39     0};
40 
41 constexpr uint8_t kExpectedType2FunctionSamples[] = {
42     26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
43     25, 25, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
44     24, 24, 24, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
45     23, 23, 23, 23, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
46     22, 22, 22, 22, 22, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
47     21, 21, 21, 21, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
48     20, 20, 20, 20, 20, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
49     19, 19, 19, 19, 19, 19, 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
50     18, 18, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
51     17, 17, 17, 17, 17, 17, 17, 17, 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
52     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15,
53     15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14,
54     14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13,
55     13, 13, 13, 13, 13, 13, 13, 13, 13};
56 
57 constexpr uint8_t kExpectedType4FunctionSamples[] = {
58     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
59     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
60     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
61     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
62     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
63     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
64     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
65     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
66     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26,
67     26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
68     26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
69     26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
70     26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
71     26, 26, 26, 26, 26, 26, 26, 26, 26};
72 
CreateType0FunctionStream()73 RetainPtr<CPDF_Stream> CreateType0FunctionStream() {
74   auto func_dict = pdfium::MakeRetain<CPDF_Dictionary>();
75   func_dict->SetNewFor<CPDF_Number>("FunctionType", 0);
76   func_dict->SetNewFor<CPDF_Number>("BitsPerSample", 8);
77 
78   auto domain_array = func_dict->SetNewFor<CPDF_Array>("Domain");
79   domain_array->AppendNew<CPDF_Number>(0);
80   domain_array->AppendNew<CPDF_Number>(1);
81 
82   auto range_array = func_dict->SetNewFor<CPDF_Array>("Range");
83   range_array->AppendNew<CPDF_Number>(0);
84   range_array->AppendNew<CPDF_Number>(0.5f);
85 
86   auto size_array = func_dict->SetNewFor<CPDF_Array>("Size");
87   size_array->AppendNew<CPDF_Number>(4);
88 
89   static constexpr uint8_t kContents[] = "1234";
90   return pdfium::MakeRetain<CPDF_Stream>(
91       DataVector<uint8_t>(std::begin(kContents), std::end(kContents)),
92       std::move(func_dict));
93 }
94 
CreateType2FunctionDict()95 RetainPtr<CPDF_Dictionary> CreateType2FunctionDict() {
96   auto func_dict = pdfium::MakeRetain<CPDF_Dictionary>();
97   func_dict->SetNewFor<CPDF_Number>("FunctionType", 2);
98   func_dict->SetNewFor<CPDF_Number>("N", 1);
99 
100   auto domain_array = func_dict->SetNewFor<CPDF_Array>("Domain");
101   domain_array->AppendNew<CPDF_Number>(0);
102   domain_array->AppendNew<CPDF_Number>(1);
103 
104   auto c0_array = func_dict->SetNewFor<CPDF_Array>("C0");
105   c0_array->AppendNew<CPDF_Number>(0.1f);
106   c0_array->AppendNew<CPDF_Number>(0.2f);
107   c0_array->AppendNew<CPDF_Number>(0.8f);
108 
109   auto c1_array = func_dict->SetNewFor<CPDF_Array>("C1");
110   c1_array->AppendNew<CPDF_Number>(0.05f);
111   c1_array->AppendNew<CPDF_Number>(0.01f);
112   c1_array->AppendNew<CPDF_Number>(0.4f);
113 
114   return func_dict;
115 }
116 
CreateType4FunctionStream()117 RetainPtr<CPDF_Stream> CreateType4FunctionStream() {
118   auto func_dict = pdfium::MakeRetain<CPDF_Dictionary>();
119   func_dict->SetNewFor<CPDF_Number>("FunctionType", 4);
120 
121   auto domain_array = func_dict->SetNewFor<CPDF_Array>("Domain");
122   domain_array->AppendNew<CPDF_Number>(0);
123   domain_array->AppendNew<CPDF_Number>(1);
124 
125   auto range_array = func_dict->SetNewFor<CPDF_Array>("Range");
126   range_array->AppendNew<CPDF_Number>(-1);
127   range_array->AppendNew<CPDF_Number>(1);
128 
129   static constexpr uint8_t kContents[] = "{ 360 mul sin 2 div }";
130   return pdfium::MakeRetain<CPDF_Stream>(
131       DataVector<uint8_t>(std::begin(kContents), std::end(kContents)),
132       std::move(func_dict));
133 }
134 
CreateBadType4FunctionStream()135 RetainPtr<CPDF_Stream> CreateBadType4FunctionStream() {
136   auto func_dict = pdfium::MakeRetain<CPDF_Dictionary>();
137   func_dict->SetNewFor<CPDF_Number>("FunctionType", 4);
138 
139   auto domain_array = func_dict->SetNewFor<CPDF_Array>("Domain");
140   domain_array->AppendNew<CPDF_Number>(0);
141   domain_array->AppendNew<CPDF_Number>(1);
142 
143   auto range_array = func_dict->SetNewFor<CPDF_Array>("Range");
144   range_array->AppendNew<CPDF_Number>(-1);
145   range_array->AppendNew<CPDF_Number>(1);
146 
147   static constexpr uint8_t kContents[] = "garbage";
148   return pdfium::MakeRetain<CPDF_Stream>(
149       DataVector<uint8_t>(std::begin(kContents), std::end(kContents)),
150       std::move(func_dict));
151 }
152 
153 class TestDocRenderData : public CPDF_DocRenderData {
154  public:
155   TestDocRenderData() = default;
156 
CreateTransferFuncForTesting(RetainPtr<const CPDF_Object> pObj) const157   RetainPtr<CPDF_TransferFunc> CreateTransferFuncForTesting(
158       RetainPtr<const CPDF_Object> pObj) const {
159     return CreateTransferFunc(std::move(pObj));
160   }
161 };
162 
TEST(CPDF_DocRenderDataTest,TransferFunctionOne)163 TEST(CPDF_DocRenderDataTest, TransferFunctionOne) {
164   RetainPtr<CPDF_Dictionary> func_dict = CreateType2FunctionDict();
165 
166   TestDocRenderData render_data;
167   auto func = render_data.CreateTransferFuncForTesting(func_dict);
168   ASSERT_TRUE(func);
169   EXPECT_FALSE(func->GetIdentity());
170 
171   auto r_samples = func->GetSamplesR();
172   auto g_samples = func->GetSamplesG();
173   auto b_samples = func->GetSamplesB();
174   ASSERT_EQ(std::size(kExpectedType2FunctionSamples), r_samples.size());
175   ASSERT_EQ(std::size(kExpectedType2FunctionSamples), g_samples.size());
176   ASSERT_EQ(std::size(kExpectedType2FunctionSamples), b_samples.size());
177 
178   for (size_t i = 0; i < std::size(kExpectedType2FunctionSamples); ++i) {
179     EXPECT_EQ(kExpectedType2FunctionSamples[i], r_samples[i]);
180     EXPECT_EQ(kExpectedType2FunctionSamples[i], g_samples[i]);
181     EXPECT_EQ(kExpectedType2FunctionSamples[i], b_samples[i]);
182   }
183 
184   EXPECT_EQ(0x000d0d0du, func->TranslateColor(0x00ffffff));
185   EXPECT_EQ(0x000d1a1au, func->TranslateColor(0x00ff0000));
186   EXPECT_EQ(0x001a0d1au, func->TranslateColor(0x0000ff00));
187   EXPECT_EQ(0x001a1a0du, func->TranslateColor(0x000000ff));
188   EXPECT_EQ(0x000f0f0fu, func->TranslateColor(0x00cccccc));
189   EXPECT_EQ(0x00191715u, func->TranslateColor(0x00123456));
190   EXPECT_EQ(0x000d0d0du, func->TranslateColor(0xffffffff));
191   EXPECT_EQ(0x001a1a1au, func->TranslateColor(0xff000000));
192   EXPECT_EQ(0x000d0d0du, func->TranslateColor(0xccffffff));
193   EXPECT_EQ(0x001a1a1au, func->TranslateColor(0x99000000));
194 }
195 
TEST(CPDF_DocRenderDataTest,TransferFunctionArray)196 TEST(CPDF_DocRenderDataTest, TransferFunctionArray) {
197   auto func_array = pdfium::MakeRetain<CPDF_Array>();
198   func_array->Append(CreateType0FunctionStream());
199   func_array->Append(CreateType2FunctionDict());
200   func_array->Append(CreateType4FunctionStream());
201 
202   TestDocRenderData render_data;
203   auto func = render_data.CreateTransferFuncForTesting(func_array);
204   ASSERT_TRUE(func);
205   EXPECT_FALSE(func->GetIdentity());
206 
207   auto r_samples = func->GetSamplesR();
208   auto g_samples = func->GetSamplesG();
209   auto b_samples = func->GetSamplesB();
210   ASSERT_EQ(std::size(kExpectedType0FunctionSamples), r_samples.size());
211   ASSERT_EQ(std::size(kExpectedType2FunctionSamples), g_samples.size());
212   ASSERT_EQ(std::size(kExpectedType4FunctionSamples), b_samples.size());
213 
214   for (size_t i = 0; i < std::size(kExpectedType2FunctionSamples); ++i) {
215     EXPECT_EQ(kExpectedType0FunctionSamples[i], r_samples[i]);
216     EXPECT_EQ(kExpectedType2FunctionSamples[i], g_samples[i]);
217     EXPECT_EQ(kExpectedType4FunctionSamples[i], b_samples[i]);
218   }
219 
220   EXPECT_EQ(0x001a0d00u, func->TranslateColor(0x00ffffff));
221   EXPECT_EQ(0x001a1a00u, func->TranslateColor(0x00ff0000));
222   EXPECT_EQ(0x00190d00u, func->TranslateColor(0x0000ff00));
223   EXPECT_EQ(0x00191a00u, func->TranslateColor(0x000000ff));
224   EXPECT_EQ(0x001a0f87u, func->TranslateColor(0x00cccccc));
225   EXPECT_EQ(0x0019176du, func->TranslateColor(0x00123456));
226   EXPECT_EQ(0x001a0d00u, func->TranslateColor(0xffffffff));
227   EXPECT_EQ(0x00191a00u, func->TranslateColor(0xff000000));
228   EXPECT_EQ(0x001a0d00u, func->TranslateColor(0xccffffff));
229   EXPECT_EQ(0x00191a00u, func->TranslateColor(0x99000000));
230 }
231 
TEST(CPDF_DocRenderDataTest,BadTransferFunctions)232 TEST(CPDF_DocRenderDataTest, BadTransferFunctions) {
233   {
234     auto func_stream = CreateBadType4FunctionStream();
235 
236     TestDocRenderData render_data;
237     auto func = render_data.CreateTransferFuncForTesting(func_stream);
238     EXPECT_FALSE(func);
239   }
240 
241   {
242     auto func_array = pdfium::MakeRetain<CPDF_Array>();
243 
244     TestDocRenderData render_data;
245     auto func = render_data.CreateTransferFuncForTesting(func_array);
246     EXPECT_FALSE(func);
247   }
248 
249   {
250     auto func_array = pdfium::MakeRetain<CPDF_Array>();
251     func_array->Append(CreateType0FunctionStream());
252     func_array->Append(CreateType2FunctionDict());
253     func_array->Append(CreateBadType4FunctionStream());
254 
255     TestDocRenderData render_data;
256     auto func = render_data.CreateTransferFuncForTesting(func_array);
257     EXPECT_FALSE(func);
258   }
259 }
260 
261 }  // namespace
262