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