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