xref: /aosp_15_r20/external/pdfium/core/fpdfapi/page/cpdf_psengine_unittest.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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 
12 namespace {
13 
DoOperator0(CPDF_PSEngine * engine,PDF_PSOP op)14 float 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 
DoOperator1(CPDF_PSEngine * engine,float v1,PDF_PSOP op)22 float 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 
DoOperator2(CPDF_PSEngine * engine,float v1,float v2,PDF_PSOP op)31 float 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 
TEST(CPDF_PSProc,AddOperator)43 TEST(CPDF_PSProc, AddOperator) {
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);
77     proc.AddOperatorForTesting(word);
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 
TEST(CPDF_PSEngine,Basic)93 TEST(CPDF_PSEngine, Basic) {
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 
TEST(CPDF_PSEngine,DivByZero)106 TEST(CPDF_PSEngine, DivByZero) {
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 
TEST(CPDF_PSEngine,Ceiling)117 TEST(CPDF_PSEngine, Ceiling) {
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 
TEST(CPDF_PSEngine,Floor)139 TEST(CPDF_PSEngine, Floor) {
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 
TEST(CPDF_PSEngine,Round)164 TEST(CPDF_PSEngine, Round) {
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 
TEST(CPDF_PSEngine,Truncate)189 TEST(CPDF_PSEngine, Truncate) {
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 
TEST(CPDF_PSEngine,Comparisons)214 TEST(CPDF_PSEngine, Comparisons) {
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 
TEST(CPDF_PSEngine,Logic)248 TEST(CPDF_PSEngine, Logic) {
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 
TEST(CPDF_PSEngine,MathFunctions)273 TEST(CPDF_PSEngine, MathFunctions) {
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 }
284