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_psengine_unittest.cpp
Go to the documentation of this file.
1// Copyright 2017 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/page/cpdf_psengine.h"
6
7#include <iterator>
8#include <limits>
9
10#include "testing/gtest/include/gtest/gtest.h"
11
12namespace {
13
14float DoOperator0(CPDF_PSEngine* engine, PDF_PSOP op) {
15 EXPECT_EQ(0u, engine->GetStackSize());
16 engine->DoOperator(op);
17 float ret = engine->Pop();
18 EXPECT_EQ(0u, engine->GetStackSize());
19 return ret;
20}
21
22float DoOperator1(CPDF_PSEngine* engine, float v1, PDF_PSOP op) {
23 EXPECT_EQ(0u, engine->GetStackSize());
24 engine->Push(v1);
25 engine->DoOperator(op);
26 float ret = engine->Pop();
27 EXPECT_EQ(0u, engine->GetStackSize());
28 return ret;
29}
30
31float DoOperator2(CPDF_PSEngine* engine, float v1, float v2, PDF_PSOP op) {
32 EXPECT_EQ(0u, engine->GetStackSize());
33 engine->Push(v1);
34 engine->Push(v2);
35 engine->DoOperator(op);
36 float ret = engine->Pop();
37 EXPECT_EQ(0u, engine->GetStackSize());
38 return ret;
39}
40
41} // namespace
42
44 static const struct {
45 const char* name;
46 PDF_PSOP op;
47 } kTestData[] = {
48 {"add", PSOP_ADD}, {"sub", PSOP_SUB},
49 {"mul", PSOP_MUL}, {"div", PSOP_DIV},
50 {"idiv", PSOP_IDIV}, {"mod", PSOP_MOD},
51 {"neg", PSOP_NEG}, {"abs", PSOP_ABS},
52 {"ceiling", PSOP_CEILING}, {"floor", PSOP_FLOOR},
53 {"round", PSOP_ROUND}, {"truncate", PSOP_TRUNCATE},
54 {"sqrt", PSOP_SQRT}, {"sin", PSOP_SIN},
55 {"cos", PSOP_COS}, {"atan", PSOP_ATAN},
56 {"exp", PSOP_EXP}, {"ln", PSOP_LN},
57 {"log", PSOP_LOG}, {"cvi", PSOP_CVI},
58 {"cvr", PSOP_CVR}, {"eq", PSOP_EQ},
59 {"ne", PSOP_NE}, {"gt", PSOP_GT},
60 {"ge", PSOP_GE}, {"lt", PSOP_LT},
61 {"le", PSOP_LE}, {"and", PSOP_AND},
62 {"or", PSOP_OR}, {"xor", PSOP_XOR},
63 {"not", PSOP_NOT}, {"bitshift", PSOP_BITSHIFT},
64 {"true", PSOP_TRUE}, {"false", PSOP_FALSE},
65 {"if", PSOP_IF}, {"ifelse", PSOP_IFELSE},
66 {"pop", PSOP_POP}, {"exch", PSOP_EXCH},
67 {"dup", PSOP_DUP}, {"copy", PSOP_COPY},
68 {"index", PSOP_INDEX}, {"roll", PSOP_ROLL},
69 {"55", PSOP_CONST}, {"123.4", PSOP_CONST},
70 {"-5", PSOP_CONST}, {"invalid", PSOP_CONST},
71 };
72
73 CPDF_PSProc proc;
74 EXPECT_EQ(0U, proc.num_operators());
75 for (size_t i = 0; i < std::size(kTestData); ++i) {
76 ByteStringView word(kTestData[i].name);
78 ASSERT_EQ(i + 1, proc.num_operators());
79 const std::unique_ptr<CPDF_PSOP>& new_psop = proc.last_operator();
80 ASSERT_TRUE(new_psop);
81 PDF_PSOP new_op = new_psop->GetOp();
82 EXPECT_EQ(kTestData[i].op, new_op);
83 if (new_op == PSOP_CONST) {
84 float fv = new_psop->GetFloatValue();
85 if (word == "invalid")
86 EXPECT_FLOAT_EQ(0, fv);
87 else
88 EXPECT_EQ(word, ByteString::FormatFloat(fv));
89 }
90 }
91}
92
94 CPDF_PSEngine engine;
95
96 EXPECT_FLOAT_EQ(300.0f, DoOperator2(&engine, 100, 200, PSOP_ADD));
97 EXPECT_FLOAT_EQ(-50.0f, DoOperator2(&engine, 100, 150, PSOP_SUB));
98 EXPECT_FLOAT_EQ(600.0f, DoOperator2(&engine, 5, 120, PSOP_MUL));
99 EXPECT_FLOAT_EQ(1.5f, DoOperator2(&engine, 15, 10, PSOP_DIV));
100 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 15, 10, PSOP_IDIV));
101 EXPECT_FLOAT_EQ(5.0f, DoOperator2(&engine, 15, 10, PSOP_MOD));
102 EXPECT_FLOAT_EQ(5.0f, DoOperator1(&engine, -5, PSOP_NEG));
103 EXPECT_FLOAT_EQ(5.0f, DoOperator1(&engine, -5, PSOP_ABS));
104}
105
107 CPDF_PSEngine engine;
108
109 // Integer divide by zero is defined as resulting in 0.
110 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 100, 0.0, PSOP_IDIV));
111 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 100, 0.0, PSOP_MOD));
112
113 // floating divide by zero is defined as resulting in 0.
114 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 100, 0.0, PSOP_DIV));
115}
116
118 CPDF_PSEngine engine;
119
120 // Smallest positive float value.
121 float min_float = std::numeric_limits<float>::min();
122 // Largest positive float value.
123 float max_float = std::numeric_limits<float>::max();
124 EXPECT_FLOAT_EQ(1.0f, DoOperator1(&engine, min_float, PSOP_CEILING));
125 EXPECT_FLOAT_EQ(max_float, DoOperator1(&engine, max_float, PSOP_CEILING));
126 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, -min_float, PSOP_CEILING));
127 EXPECT_FLOAT_EQ(-max_float, DoOperator1(&engine, -max_float, PSOP_CEILING));
128 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, -0.9f, PSOP_CEILING));
129 EXPECT_FLOAT_EQ(1.0f, DoOperator1(&engine, 0.0000000001f, PSOP_CEILING));
130 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0f, PSOP_CEILING));
131 EXPECT_FLOAT_EQ(3.0f, DoOperator1(&engine, 2.3f, PSOP_CEILING));
132 EXPECT_FLOAT_EQ(4.0f, DoOperator1(&engine, 3.8f, PSOP_CEILING));
133 EXPECT_FLOAT_EQ(6.0f, DoOperator1(&engine, 5.5f, PSOP_CEILING));
134 EXPECT_FLOAT_EQ(-2.0f, DoOperator1(&engine, -2.3f, PSOP_CEILING));
135 EXPECT_FLOAT_EQ(-3.0f, DoOperator1(&engine, -3.8f, PSOP_CEILING));
136 EXPECT_FLOAT_EQ(-5.0f, DoOperator1(&engine, -5.5f, PSOP_CEILING));
137}
138
140 CPDF_PSEngine engine;
141
142 // Smallest positive float value.
143 float min_float = std::numeric_limits<float>::min();
144 // Largest positive float value.
145 float max_float = std::numeric_limits<float>::max();
146 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, min_float, PSOP_FLOOR));
147 EXPECT_FLOAT_EQ(max_float, DoOperator1(&engine, max_float, PSOP_FLOOR));
148 EXPECT_FLOAT_EQ(-1.0f, DoOperator1(&engine, -min_float, PSOP_FLOOR));
149 EXPECT_FLOAT_EQ(-max_float, DoOperator1(&engine, -max_float, PSOP_FLOOR));
150 EXPECT_FLOAT_EQ(5.0f, DoOperator1(&engine, 5.9f, PSOP_FLOOR));
151 EXPECT_FLOAT_EQ(-4.0f, DoOperator1(&engine, -4.0000000001f, PSOP_FLOOR));
152 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0f, PSOP_FLOOR));
153 EXPECT_FLOAT_EQ(-1.0f, DoOperator1(&engine, -0.9f, PSOP_FLOOR));
154 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0000000001f, PSOP_FLOOR));
155 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0f, PSOP_FLOOR));
156 EXPECT_FLOAT_EQ(2.0f, DoOperator1(&engine, 2.3f, PSOP_FLOOR));
157 EXPECT_FLOAT_EQ(3.0f, DoOperator1(&engine, 3.8f, PSOP_FLOOR));
158 EXPECT_FLOAT_EQ(5.0f, DoOperator1(&engine, 5.5f, PSOP_FLOOR));
159 EXPECT_FLOAT_EQ(-3.0f, DoOperator1(&engine, -2.3f, PSOP_FLOOR));
160 EXPECT_FLOAT_EQ(-4.0f, DoOperator1(&engine, -3.8f, PSOP_FLOOR));
161 EXPECT_FLOAT_EQ(-6.0f, DoOperator1(&engine, -5.5f, PSOP_FLOOR));
162}
163
165 CPDF_PSEngine engine;
166
167 EXPECT_FLOAT_EQ(6.0f, DoOperator1(&engine, 5.9f, PSOP_ROUND));
168 EXPECT_FLOAT_EQ(-4.0f, DoOperator1(&engine, -4.0000000001f, PSOP_ROUND));
169 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0f, PSOP_ROUND));
170 EXPECT_FLOAT_EQ(-1.0f, DoOperator1(&engine, -0.9f, PSOP_ROUND));
171 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0000000001f, PSOP_ROUND));
172 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0f, PSOP_ROUND));
173 // Smallest positive float value.
174 float min_float = std::numeric_limits<float>::min();
175 // Largest positive float value.
176 float max_float = std::numeric_limits<float>::max();
177 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, min_float, PSOP_ROUND));
178 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, -min_float, PSOP_ROUND));
179 EXPECT_FLOAT_EQ(max_float, DoOperator1(&engine, max_float, PSOP_ROUND));
180 EXPECT_FLOAT_EQ(-max_float, DoOperator1(&engine, -max_float, PSOP_ROUND));
181 EXPECT_FLOAT_EQ(2.0f, DoOperator1(&engine, 2.3f, PSOP_ROUND));
182 EXPECT_FLOAT_EQ(4.0f, DoOperator1(&engine, 3.8f, PSOP_ROUND));
183 EXPECT_FLOAT_EQ(6.0f, DoOperator1(&engine, 5.5f, PSOP_ROUND));
184 EXPECT_FLOAT_EQ(-2.0f, DoOperator1(&engine, -2.3f, PSOP_ROUND));
185 EXPECT_FLOAT_EQ(-4.0f, DoOperator1(&engine, -3.8f, PSOP_ROUND));
186 EXPECT_FLOAT_EQ(-5.0f, DoOperator1(&engine, -5.5f, PSOP_ROUND));
187}
188
190 CPDF_PSEngine engine;
191
192 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, -0.9f, PSOP_TRUNCATE));
193 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0000000001f, PSOP_TRUNCATE));
194 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0f, PSOP_TRUNCATE));
195 // Smallest positive float value.
196 float min_float = std::numeric_limits<float>::min();
197 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, min_float, PSOP_TRUNCATE));
198 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, -min_float, PSOP_TRUNCATE));
199 EXPECT_FLOAT_EQ(2.0f, DoOperator1(&engine, 2.3f, PSOP_TRUNCATE));
200 EXPECT_FLOAT_EQ(3.0f, DoOperator1(&engine, 3.8f, PSOP_TRUNCATE));
201 EXPECT_FLOAT_EQ(5.0f, DoOperator1(&engine, 5.5f, PSOP_TRUNCATE));
202 EXPECT_FLOAT_EQ(-2.0f, DoOperator1(&engine, -2.3f, PSOP_TRUNCATE));
203 EXPECT_FLOAT_EQ(-3.0f, DoOperator1(&engine, -3.8f, PSOP_TRUNCATE));
204 EXPECT_FLOAT_EQ(-5.0f, DoOperator1(&engine, -5.5f, PSOP_TRUNCATE));
205
206 // Truncate does not behave according to the PostScript Language Reference for
207 // values beyond the range of integers. This seems to match Acrobat's
208 // behavior. See https://crbug.com/pdfium/1314.
209 float max_int = static_cast<float>(std::numeric_limits<int>::max());
210 EXPECT_FLOAT_EQ(-max_int,
211 DoOperator1(&engine, max_int * -1.5f, PSOP_TRUNCATE));
212}
213
215 CPDF_PSEngine engine;
216
217 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 0.0f, 0.0f, PSOP_EQ));
218 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 0.0f, 1.0f, PSOP_EQ));
219 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 255.0f, 1.0f, PSOP_EQ));
220 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, -1.0f, 0.0f, PSOP_EQ));
221
222 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 0.0f, 0.0f, PSOP_NE));
223 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 0.0f, 1.0f, PSOP_NE));
224 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 255.0f, 1.0f, PSOP_NE));
225 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, -1.0f, 0.0f, PSOP_NE));
226
227 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 0.0f, 0.0f, PSOP_GT));
228 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 0.0f, 1.0f, PSOP_GT));
229 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 255.0f, 1.0f, PSOP_GT));
230 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, -1.0f, 0.0f, PSOP_GT));
231
232 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 0.0f, 0.0f, PSOP_GE));
233 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 0.0f, 1.0f, PSOP_GE));
234 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 255.0f, 1.0f, PSOP_GE));
235 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, -1.0f, 0.0f, PSOP_GE));
236
237 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 0.0f, 0.0f, PSOP_LT));
238 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 0.0f, 1.0f, PSOP_LT));
239 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 255.0f, 1.0f, PSOP_LT));
240 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, -1.0f, 0.0f, PSOP_LT));
241
242 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 0.0f, 0.0f, PSOP_LE));
243 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 0.0f, 1.0f, PSOP_LE));
244 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 255.0f, 1.0f, PSOP_LE));
245 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, -1.0f, 0.0f, PSOP_LE));
246}
247
249 CPDF_PSEngine engine;
250
251 EXPECT_FLOAT_EQ(1.0f, DoOperator0(&engine, PSOP_TRUE));
252 EXPECT_FLOAT_EQ(0.0f, DoOperator0(&engine, PSOP_FALSE));
253
254 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 0.0f, 0.0f, PSOP_AND));
255 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 0.0f, 1.0f, PSOP_AND));
256 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 1.0f, 0.0f, PSOP_AND));
257 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 1.0f, 1.0f, PSOP_AND));
258
259 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 0.0f, 0.0f, PSOP_OR));
260 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 0.0f, 1.0f, PSOP_OR));
261 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 1.0f, 0.0f, PSOP_OR));
262 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 1.0f, 1.0f, PSOP_OR));
263
264 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 0.0f, 0.0f, PSOP_XOR));
265 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 0.0f, 1.0f, PSOP_XOR));
266 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 1.0f, 0.0f, PSOP_XOR));
267 EXPECT_FLOAT_EQ(0.0f, DoOperator2(&engine, 1.0f, 1.0f, PSOP_XOR));
268
269 EXPECT_FLOAT_EQ(1.0f, DoOperator1(&engine, 0.0f, PSOP_NOT));
270 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 1.0f, PSOP_NOT));
271}
272
274 CPDF_PSEngine engine;
275
276 EXPECT_FLOAT_EQ(1.4142135f, DoOperator1(&engine, 2.0f, PSOP_SQRT));
277 EXPECT_FLOAT_EQ(0.8660254f, DoOperator1(&engine, 60.0f, PSOP_SIN));
278 EXPECT_FLOAT_EQ(0.5f, DoOperator1(&engine, 60.0f, PSOP_COS));
279 EXPECT_FLOAT_EQ(45.0f, DoOperator2(&engine, 1.0f, 1.0f, PSOP_ATAN));
280 EXPECT_FLOAT_EQ(1000.0f, DoOperator2(&engine, 10.0f, 3.0f, PSOP_EXP));
281 EXPECT_FLOAT_EQ(3.0f, DoOperator1(&engine, 1000.0f, PSOP_LOG));
282 EXPECT_FLOAT_EQ(2.302585f, DoOperator1(&engine, 10.0f, PSOP_LN));
283}
bool DoOperator(PDF_PSOP op)
uint32_t GetStackSize() const
void Push(float value)
void AddOperatorForTesting(ByteStringView word)
static ByteString FormatFloat(float f)
PDF_PSOP
@ PSOP_COS
@ PSOP_FLOOR
@ PSOP_LT
@ PSOP_LOG
@ PSOP_DIV
@ PSOP_DUP
@ PSOP_GE
@ PSOP_NEG
@ PSOP_LN
@ PSOP_OR
@ PSOP_EQ
@ PSOP_MOD
@ PSOP_IDIV
@ PSOP_ATAN
@ PSOP_CVR
@ PSOP_SUB
@ PSOP_EXP
@ PSOP_ADD
@ PSOP_ROUND
@ PSOP_CONST
@ PSOP_IF
@ PSOP_NE
@ PSOP_FALSE
@ PSOP_TRUE
@ PSOP_MUL
@ PSOP_ROLL
@ PSOP_AND
@ PSOP_GT
@ PSOP_CEILING
@ PSOP_POP
@ PSOP_EXCH
@ PSOP_BITSHIFT
@ PSOP_SQRT
@ PSOP_COPY
@ PSOP_IFELSE
@ PSOP_NOT
@ PSOP_ABS
@ PSOP_CVI
@ PSOP_SIN
@ PSOP_TRUNCATE
@ PSOP_XOR
@ PSOP_LE
@ PSOP_INDEX
TEST(CPDF_PSProc, AddOperator)
TEST(CPDF_PSEngine, Basic)