summaryrefslogtreecommitdiff
path: root/core/fpdfapi
diff options
context:
space:
mode:
Diffstat (limited to 'core/fpdfapi')
-rw-r--r--core/fpdfapi/page/cpdf_psengine.cpp127
-rw-r--r--core/fpdfapi/page/cpdf_psengine.h30
-rw-r--r--core/fpdfapi/page/cpdf_psengine_unittest.cpp56
3 files changed, 149 insertions, 64 deletions
diff --git a/core/fpdfapi/page/cpdf_psengine.cpp b/core/fpdfapi/page/cpdf_psengine.cpp
index d879ead9c1..9dfa9989f0 100644
--- a/core/fpdfapi/page/cpdf_psengine.cpp
+++ b/core/fpdfapi/page/cpdf_psengine.cpp
@@ -46,39 +46,32 @@ const PDF_PSOpName kPsOpNames[] = {
} // namespace
-class CPDF_PSOP {
- public:
- explicit CPDF_PSOP(PDF_PSOP op) : m_op(op), m_value(0) {
- ASSERT(m_op != PSOP_CONST);
- ASSERT(m_op != PSOP_PROC);
- }
- explicit CPDF_PSOP(float value) : m_op(PSOP_CONST), m_value(value) {}
- CPDF_PSOP()
- : m_op(PSOP_PROC),
- m_value(0),
- m_proc(pdfium::MakeUnique<CPDF_PSProc>()) {}
-
- float GetFloatValue() const {
- if (m_op == PSOP_CONST)
- return m_value;
-
- NOTREACHED();
- return 0;
- }
- CPDF_PSProc* GetProc() const {
- if (m_op == PSOP_PROC)
- return m_proc.get();
- NOTREACHED();
- return nullptr;
- }
+CPDF_PSOP::CPDF_PSOP()
+ : m_op(PSOP_PROC), m_value(0), m_proc(pdfium::MakeUnique<CPDF_PSProc>()) {}
- PDF_PSOP GetOp() const { return m_op; }
+CPDF_PSOP::CPDF_PSOP(PDF_PSOP op) : m_op(op), m_value(0) {
+ ASSERT(m_op != PSOP_CONST);
+ ASSERT(m_op != PSOP_PROC);
+}
- private:
- const PDF_PSOP m_op;
- const float m_value;
- std::unique_ptr<CPDF_PSProc> m_proc;
-};
+CPDF_PSOP::CPDF_PSOP(float value) : m_op(PSOP_CONST), m_value(value) {}
+
+CPDF_PSOP::~CPDF_PSOP() {}
+
+float CPDF_PSOP::GetFloatValue() const {
+ if (m_op == PSOP_CONST)
+ return m_value;
+
+ NOTREACHED();
+ return 0;
+}
+
+CPDF_PSProc* CPDF_PSOP::GetProc() const {
+ if (m_op == PSOP_PROC)
+ return m_proc.get();
+ NOTREACHED();
+ return nullptr;
+}
bool CPDF_PSEngine::Execute() {
return m_MainProc.Execute(this);
@@ -87,6 +80,29 @@ bool CPDF_PSEngine::Execute() {
CPDF_PSProc::CPDF_PSProc() {}
CPDF_PSProc::~CPDF_PSProc() {}
+bool CPDF_PSProc::Parse(CPDF_SimpleParser* parser, int depth) {
+ if (depth > kMaxDepth)
+ return false;
+
+ while (1) {
+ ByteStringView word = parser->GetWord();
+ if (word.IsEmpty())
+ return false;
+
+ if (word == "}")
+ return true;
+
+ if (word == "{") {
+ m_Operators.push_back(pdfium::MakeUnique<CPDF_PSOP>());
+ if (!m_Operators.back()->GetProc()->Parse(parser, depth + 1))
+ return false;
+ continue;
+ }
+
+ AddOperator(word);
+ }
+}
+
bool CPDF_PSProc::Execute(CPDF_PSEngine* pEngine) {
for (size_t i = 0; i < m_Operators.size(); ++i) {
const PDF_PSOP op = m_Operators[i]->GetOp();
@@ -118,6 +134,23 @@ bool CPDF_PSProc::Execute(CPDF_PSEngine* pEngine) {
return true;
}
+void CPDF_PSProc::AddOperatorForTesting(const ByteStringView& word) {
+ AddOperator(word);
+}
+
+void CPDF_PSProc::AddOperator(const ByteStringView& word) {
+ std::unique_ptr<CPDF_PSOP> op;
+ for (const PDF_PSOpName& op_name : kPsOpNames) {
+ if (word == ByteStringView(op_name.name)) {
+ op = pdfium::MakeUnique<CPDF_PSOP>(op_name.op);
+ break;
+ }
+ }
+ if (!op)
+ op = pdfium::MakeUnique<CPDF_PSOP>(FX_atof(word));
+ m_Operators.push_back(std::move(op));
+}
+
CPDF_PSEngine::CPDF_PSEngine() : m_StackCount(0) {}
CPDF_PSEngine::~CPDF_PSEngine() {}
@@ -141,38 +174,6 @@ bool CPDF_PSEngine::Parse(const char* str, int size) {
return word == "{" ? m_MainProc.Parse(&parser, 0) : false;
}
-bool CPDF_PSProc::Parse(CPDF_SimpleParser* parser, int depth) {
- if (depth > kMaxDepth)
- return false;
-
- while (1) {
- ByteStringView word = parser->GetWord();
- if (word.IsEmpty())
- return false;
-
- if (word == "}")
- return true;
-
- if (word == "{") {
- m_Operators.push_back(pdfium::MakeUnique<CPDF_PSOP>());
- if (!m_Operators.back()->GetProc()->Parse(parser, depth + 1))
- return false;
- continue;
- }
-
- std::unique_ptr<CPDF_PSOP> op;
- for (const PDF_PSOpName& op_name : kPsOpNames) {
- if (word == ByteStringView(op_name.name)) {
- op = pdfium::MakeUnique<CPDF_PSOP>(op_name.op);
- break;
- }
- }
- if (!op)
- op = pdfium::MakeUnique<CPDF_PSOP>(FX_atof(word));
- m_Operators.push_back(std::move(op));
- }
-}
-
bool CPDF_PSEngine::DoOperator(PDF_PSOP op) {
int i1;
int i2;
diff --git a/core/fpdfapi/page/cpdf_psengine.h b/core/fpdfapi/page/cpdf_psengine.h
index 0d5eadd78e..63d91d0757 100644
--- a/core/fpdfapi/page/cpdf_psengine.h
+++ b/core/fpdfapi/page/cpdf_psengine.h
@@ -10,10 +10,11 @@
#include <memory>
#include <vector>
+#include "core/fxcrt/fx_string.h"
#include "core/fxcrt/fx_system.h"
class CPDF_PSEngine;
-class CPDF_PSOP;
+class CPDF_PSProc;
class CPDF_SimpleParser;
enum PDF_PSOP : uint8_t {
@@ -63,6 +64,23 @@ enum PDF_PSOP : uint8_t {
PSOP_CONST
};
+class CPDF_PSOP {
+ public:
+ CPDF_PSOP();
+ explicit CPDF_PSOP(PDF_PSOP op);
+ explicit CPDF_PSOP(float value);
+ ~CPDF_PSOP();
+
+ float GetFloatValue() const;
+ CPDF_PSProc* GetProc() const;
+ PDF_PSOP GetOp() const { return m_op; }
+
+ private:
+ const PDF_PSOP m_op;
+ const float m_value;
+ std::unique_ptr<CPDF_PSProc> m_proc;
+};
+
class CPDF_PSProc {
public:
CPDF_PSProc();
@@ -71,8 +89,18 @@ class CPDF_PSProc {
bool Parse(CPDF_SimpleParser* parser, int depth);
bool Execute(CPDF_PSEngine* pEngine);
+ // These methods are exposed for testing.
+ void AddOperatorForTesting(const ByteStringView& word);
+ size_t num_operators() const { return m_Operators.size(); }
+ const std::unique_ptr<CPDF_PSOP>& last_operator() {
+ return m_Operators.back();
+ }
+
private:
static const int kMaxDepth = 128;
+
+ void AddOperator(const ByteStringView& word);
+
std::vector<std::unique_ptr<CPDF_PSOP>> m_Operators;
};
diff --git a/core/fpdfapi/page/cpdf_psengine_unittest.cpp b/core/fpdfapi/page/cpdf_psengine_unittest.cpp
new file mode 100644
index 0000000000..f966c3aced
--- /dev/null
+++ b/core/fpdfapi/page/cpdf_psengine_unittest.cpp
@@ -0,0 +1,56 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fpdfapi/page/cpdf_psengine.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(CPDF_PSProc, AddOperator) {
+ static const struct {
+ const char* name;
+ PDF_PSOP op;
+ } kTestData[] = {
+ {"add", PSOP_ADD}, {"sub", PSOP_SUB},
+ {"mul", PSOP_MUL}, {"div", PSOP_DIV},
+ {"idiv", PSOP_IDIV}, {"mod", PSOP_MOD},
+ {"neg", PSOP_NEG}, {"abs", PSOP_ABS},
+ {"ceiling", PSOP_CEILING}, {"floor", PSOP_FLOOR},
+ {"round", PSOP_ROUND}, {"truncate", PSOP_TRUNCATE},
+ {"sqrt", PSOP_SQRT}, {"sin", PSOP_SIN},
+ {"cos", PSOP_COS}, {"atan", PSOP_ATAN},
+ {"exp", PSOP_EXP}, {"ln", PSOP_LN},
+ {"log", PSOP_LOG}, {"cvi", PSOP_CVI},
+ {"cvr", PSOP_CVR}, {"eq", PSOP_EQ},
+ {"ne", PSOP_NE}, {"gt", PSOP_GT},
+ {"ge", PSOP_GE}, {"lt", PSOP_LT},
+ {"le", PSOP_LE}, {"and", PSOP_AND},
+ {"or", PSOP_OR}, {"xor", PSOP_XOR},
+ {"not", PSOP_NOT}, {"bitshift", PSOP_BITSHIFT},
+ {"true", PSOP_TRUE}, {"false", PSOP_FALSE},
+ {"if", PSOP_IF}, {"ifelse", PSOP_IFELSE},
+ {"pop", PSOP_POP}, {"exch", PSOP_EXCH},
+ {"dup", PSOP_DUP}, {"copy", PSOP_COPY},
+ {"index", PSOP_INDEX}, {"roll", PSOP_ROLL},
+ {"55", PSOP_CONST}, {"123.4", PSOP_CONST},
+ {"-5", PSOP_CONST}, {"invalid", PSOP_CONST},
+ };
+
+ CPDF_PSProc proc;
+ EXPECT_EQ(0U, proc.num_operators());
+ for (size_t i = 0; i < FX_ArraySize(kTestData); ++i) {
+ ByteStringView word(kTestData[i].name);
+ proc.AddOperatorForTesting(word);
+ ASSERT_EQ(i + 1, proc.num_operators());
+ const std::unique_ptr<CPDF_PSOP>& new_psop = proc.last_operator();
+ ASSERT_TRUE(new_psop);
+ PDF_PSOP new_op = new_psop->GetOp();
+ EXPECT_EQ(kTestData[i].op, new_op);
+ if (new_op == PSOP_CONST) {
+ float fv = new_psop->GetFloatValue();
+ if (word == "invalid")
+ EXPECT_FLOAT_EQ(0, fv);
+ else
+ EXPECT_EQ(word, ByteString::FormatFloat(fv));
+ }
+ }
+}