1 // Copyright 2017 PDFium Authors. All rights reserved.
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 <limits>
6
7 #include "core/fpdfapi/page/cpdf_psengine.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9
10 namespace {
11
DoOperator1(CPDF_PSEngine * engine,float v1,PDF_PSOP op)12 float DoOperator1(CPDF_PSEngine* engine, float v1, PDF_PSOP op) {
13 EXPECT_EQ(0u, engine->GetStackSize());
14 engine->Push(v1);
15 engine->DoOperator(op);
16 float ret = engine->Pop();
17 EXPECT_EQ(0u, engine->GetStackSize());
18 return ret;
19 }
20
DoOperator2(CPDF_PSEngine * engine,float v1,float v2,PDF_PSOP op)21 float DoOperator2(CPDF_PSEngine* engine, float v1, float v2, PDF_PSOP op) {
22 EXPECT_EQ(0u, engine->GetStackSize());
23 engine->Push(v1);
24 engine->Push(v2);
25 engine->DoOperator(op);
26 float ret = engine->Pop();
27 EXPECT_EQ(0u, engine->GetStackSize());
28 return ret;
29 }
30
31 } // namespace
32
TEST(CPDF_PSProc,AddOperator)33 TEST(CPDF_PSProc, AddOperator) {
34 static const struct {
35 const char* name;
36 PDF_PSOP op;
37 } kTestData[] = {
38 {"add", PSOP_ADD}, {"sub", PSOP_SUB},
39 {"mul", PSOP_MUL}, {"div", PSOP_DIV},
40 {"idiv", PSOP_IDIV}, {"mod", PSOP_MOD},
41 {"neg", PSOP_NEG}, {"abs", PSOP_ABS},
42 {"ceiling", PSOP_CEILING}, {"floor", PSOP_FLOOR},
43 {"round", PSOP_ROUND}, {"truncate", PSOP_TRUNCATE},
44 {"sqrt", PSOP_SQRT}, {"sin", PSOP_SIN},
45 {"cos", PSOP_COS}, {"atan", PSOP_ATAN},
46 {"exp", PSOP_EXP}, {"ln", PSOP_LN},
47 {"log", PSOP_LOG}, {"cvi", PSOP_CVI},
48 {"cvr", PSOP_CVR}, {"eq", PSOP_EQ},
49 {"ne", PSOP_NE}, {"gt", PSOP_GT},
50 {"ge", PSOP_GE}, {"lt", PSOP_LT},
51 {"le", PSOP_LE}, {"and", PSOP_AND},
52 {"or", PSOP_OR}, {"xor", PSOP_XOR},
53 {"not", PSOP_NOT}, {"bitshift", PSOP_BITSHIFT},
54 {"true", PSOP_TRUE}, {"false", PSOP_FALSE},
55 {"if", PSOP_IF}, {"ifelse", PSOP_IFELSE},
56 {"pop", PSOP_POP}, {"exch", PSOP_EXCH},
57 {"dup", PSOP_DUP}, {"copy", PSOP_COPY},
58 {"index", PSOP_INDEX}, {"roll", PSOP_ROLL},
59 {"55", PSOP_CONST}, {"123.4", PSOP_CONST},
60 {"-5", PSOP_CONST}, {"invalid", PSOP_CONST},
61 };
62
63 CPDF_PSProc proc;
64 EXPECT_EQ(0U, proc.num_operators());
65 for (size_t i = 0; i < FX_ArraySize(kTestData); ++i) {
66 ByteStringView word(kTestData[i].name);
67 proc.AddOperatorForTesting(word);
68 ASSERT_EQ(i + 1, proc.num_operators());
69 const std::unique_ptr<CPDF_PSOP>& new_psop = proc.last_operator();
70 ASSERT_TRUE(new_psop);
71 PDF_PSOP new_op = new_psop->GetOp();
72 EXPECT_EQ(kTestData[i].op, new_op);
73 if (new_op == PSOP_CONST) {
74 float fv = new_psop->GetFloatValue();
75 if (word == "invalid")
76 EXPECT_FLOAT_EQ(0, fv);
77 else
78 EXPECT_EQ(word, ByteString::FormatFloat(fv));
79 }
80 }
81 }
82
TEST(CPDF_PSEngine,Basic)83 TEST(CPDF_PSEngine, Basic) {
84 CPDF_PSEngine engine;
85
86 EXPECT_FLOAT_EQ(300.0f, DoOperator2(&engine, 100, 200, PSOP_ADD));
87 EXPECT_FLOAT_EQ(-50.0f, DoOperator2(&engine, 100, 150, PSOP_SUB));
88 EXPECT_FLOAT_EQ(600.0f, DoOperator2(&engine, 5, 120, PSOP_MUL));
89 EXPECT_FLOAT_EQ(1.5f, DoOperator2(&engine, 15, 10, PSOP_DIV));
90 EXPECT_FLOAT_EQ(1.0f, DoOperator2(&engine, 15, 10, PSOP_IDIV));
91 EXPECT_FLOAT_EQ(5.0f, DoOperator2(&engine, 15, 10, PSOP_MOD));
92 EXPECT_FLOAT_EQ(5.0f, DoOperator1(&engine, -5, PSOP_NEG));
93 EXPECT_FLOAT_EQ(5.0f, DoOperator1(&engine, -5, PSOP_ABS));
94 }
95
TEST(CPDF_PSEngine,Ceiling)96 TEST(CPDF_PSEngine, Ceiling) {
97 CPDF_PSEngine engine;
98
99 // Smallest positive float value.
100 float min_float = std::numeric_limits<float>::min();
101 // Largest positive float value.
102 float max_float = std::numeric_limits<float>::max();
103 EXPECT_FLOAT_EQ(1.0f, DoOperator1(&engine, min_float, PSOP_CEILING));
104 EXPECT_FLOAT_EQ(max_float, DoOperator1(&engine, max_float, PSOP_CEILING));
105 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, -min_float, PSOP_CEILING));
106 EXPECT_FLOAT_EQ(-max_float, DoOperator1(&engine, -max_float, PSOP_CEILING));
107 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, -0.9f, PSOP_CEILING));
108 EXPECT_FLOAT_EQ(1.0f, DoOperator1(&engine, 0.0000000001f, PSOP_CEILING));
109 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0f, PSOP_CEILING));
110 EXPECT_FLOAT_EQ(3.0f, DoOperator1(&engine, 2.3f, PSOP_CEILING));
111 EXPECT_FLOAT_EQ(4.0f, DoOperator1(&engine, 3.8f, PSOP_CEILING));
112 EXPECT_FLOAT_EQ(6.0f, DoOperator1(&engine, 5.5f, PSOP_CEILING));
113 EXPECT_FLOAT_EQ(-2.0f, DoOperator1(&engine, -2.3f, PSOP_CEILING));
114 EXPECT_FLOAT_EQ(-3.0f, DoOperator1(&engine, -3.8f, PSOP_CEILING));
115 EXPECT_FLOAT_EQ(-5.0f, DoOperator1(&engine, -5.5f, PSOP_CEILING));
116 }
117
TEST(CPDF_PSEngine,Floor)118 TEST(CPDF_PSEngine, Floor) {
119 CPDF_PSEngine engine;
120
121 // Smallest positive float value.
122 float min_float = std::numeric_limits<float>::min();
123 // Largest positive float value.
124 float max_float = std::numeric_limits<float>::max();
125 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, min_float, PSOP_FLOOR));
126 EXPECT_FLOAT_EQ(max_float, DoOperator1(&engine, max_float, PSOP_FLOOR));
127 EXPECT_FLOAT_EQ(-1.0f, DoOperator1(&engine, -min_float, PSOP_FLOOR));
128 EXPECT_FLOAT_EQ(-max_float, DoOperator1(&engine, -max_float, PSOP_FLOOR));
129 EXPECT_FLOAT_EQ(5.0f, DoOperator1(&engine, 5.9f, PSOP_FLOOR));
130 EXPECT_FLOAT_EQ(-4.0f, DoOperator1(&engine, -4.0000000001f, PSOP_FLOOR));
131 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0f, PSOP_FLOOR));
132 EXPECT_FLOAT_EQ(-1.0f, DoOperator1(&engine, -0.9f, PSOP_FLOOR));
133 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0000000001f, PSOP_FLOOR));
134 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0f, PSOP_FLOOR));
135 EXPECT_FLOAT_EQ(2.0f, DoOperator1(&engine, 2.3f, PSOP_FLOOR));
136 EXPECT_FLOAT_EQ(3.0f, DoOperator1(&engine, 3.8f, PSOP_FLOOR));
137 EXPECT_FLOAT_EQ(5.0f, DoOperator1(&engine, 5.5f, PSOP_FLOOR));
138 EXPECT_FLOAT_EQ(-3.0f, DoOperator1(&engine, -2.3f, PSOP_FLOOR));
139 EXPECT_FLOAT_EQ(-4.0f, DoOperator1(&engine, -3.8f, PSOP_FLOOR));
140 EXPECT_FLOAT_EQ(-6.0f, DoOperator1(&engine, -5.5f, PSOP_FLOOR));
141 }
142
TEST(CPDF_PSEngine,Round)143 TEST(CPDF_PSEngine, Round) {
144 CPDF_PSEngine engine;
145
146 EXPECT_FLOAT_EQ(6.0f, DoOperator1(&engine, 5.9f, PSOP_ROUND));
147 EXPECT_FLOAT_EQ(-4.0f, DoOperator1(&engine, -4.0000000001f, PSOP_ROUND));
148 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0f, PSOP_ROUND));
149 EXPECT_FLOAT_EQ(-1.0f, DoOperator1(&engine, -0.9f, PSOP_ROUND));
150 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0000000001f, PSOP_ROUND));
151 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0f, PSOP_ROUND));
152 // Smallest positive float value.
153 float min_float = std::numeric_limits<float>::min();
154 // Largest positive float value.
155 float max_float = std::numeric_limits<float>::max();
156 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, min_float, PSOP_ROUND));
157 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, -min_float, PSOP_ROUND));
158 EXPECT_FLOAT_EQ(max_float, DoOperator1(&engine, max_float, PSOP_ROUND));
159 EXPECT_FLOAT_EQ(-max_float, DoOperator1(&engine, -max_float, PSOP_ROUND));
160 EXPECT_FLOAT_EQ(2.0f, DoOperator1(&engine, 2.3f, PSOP_ROUND));
161 EXPECT_FLOAT_EQ(4.0f, DoOperator1(&engine, 3.8f, PSOP_ROUND));
162 EXPECT_FLOAT_EQ(6.0f, DoOperator1(&engine, 5.5f, PSOP_ROUND));
163 EXPECT_FLOAT_EQ(-2.0f, DoOperator1(&engine, -2.3f, PSOP_ROUND));
164 EXPECT_FLOAT_EQ(-4.0f, DoOperator1(&engine, -3.8f, PSOP_ROUND));
165 EXPECT_FLOAT_EQ(-5.0f, DoOperator1(&engine, -5.5f, PSOP_ROUND));
166 }
167
TEST(CPDF_PSEngine,Truncate)168 TEST(CPDF_PSEngine, Truncate) {
169 CPDF_PSEngine engine;
170
171 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, -0.9f, PSOP_TRUNCATE));
172 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0000000001f, PSOP_TRUNCATE));
173 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, 0.0f, PSOP_TRUNCATE));
174 // Smallest positive float value.
175 float min_float = std::numeric_limits<float>::min();
176 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, min_float, PSOP_TRUNCATE));
177 EXPECT_FLOAT_EQ(0.0f, DoOperator1(&engine, -min_float, PSOP_TRUNCATE));
178 EXPECT_FLOAT_EQ(2.0f, DoOperator1(&engine, 2.3f, PSOP_TRUNCATE));
179 EXPECT_FLOAT_EQ(3.0f, DoOperator1(&engine, 3.8f, PSOP_TRUNCATE));
180 EXPECT_FLOAT_EQ(5.0f, DoOperator1(&engine, 5.5f, PSOP_TRUNCATE));
181 EXPECT_FLOAT_EQ(-2.0f, DoOperator1(&engine, -2.3f, PSOP_TRUNCATE));
182 EXPECT_FLOAT_EQ(-3.0f, DoOperator1(&engine, -3.8f, PSOP_TRUNCATE));
183 EXPECT_FLOAT_EQ(-5.0f, DoOperator1(&engine, -5.5f, PSOP_TRUNCATE));
184
185 // Truncate does not behave according to the PostScript Language Reference for
186 // values beyond the range of integers. This seems to match Acrobat's
187 // behavior. See https://crbug.com/1314.
188 float max_int = std::numeric_limits<int>::max();
189 EXPECT_FLOAT_EQ(-max_int,
190 DoOperator1(&engine, max_int * 2.0f, PSOP_TRUNCATE));
191 EXPECT_FLOAT_EQ(-max_int,
192 DoOperator1(&engine, max_int * -1.5f, PSOP_TRUNCATE));
193 }
194