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