| OLD | NEW |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include "core/fpdfapi/page/pageint.h" | 7 #include "core/fpdfapi/page/pageint.h" |
| 8 | 8 |
| 9 #include <limits.h> | 9 #include <limits.h> |
| 10 | 10 |
| 11 #include <algorithm> | 11 #include <algorithm> |
| 12 #include <memory> | 12 #include <memory> |
| 13 #include <utility> | 13 #include <utility> |
| 14 #include <vector> | 14 #include <vector> |
| 15 | 15 |
| 16 #include "core/fpdfapi/page/cpdf_psengine.h" | 16 #include "core/fpdfapi/page/cpdf_psengine.h" |
| 17 #include "core/fpdfapi/parser/cpdf_array.h" | 17 #include "core/fpdfapi/parser/cpdf_array.h" |
| 18 #include "core/fpdfapi/parser/cpdf_dictionary.h" | 18 #include "core/fpdfapi/parser/cpdf_dictionary.h" |
| 19 #include "core/fpdfapi/parser/cpdf_simple_parser.h" | 19 #include "core/fpdfapi/parser/cpdf_simple_parser.h" |
| 20 #include "core/fpdfapi/parser/cpdf_stream.h" | 20 #include "core/fpdfapi/parser/cpdf_stream.h" |
| 21 #include "core/fpdfapi/parser/cpdf_stream_acc.h" | 21 #include "core/fpdfapi/parser/cpdf_stream_acc.h" |
| 22 #include "core/fxcrt/fx_safe_types.h" | 22 #include "core/fxcrt/fx_safe_types.h" |
| 23 | 23 |
| 24 namespace { |
| 25 |
| 26 struct PDF_PSOpName { |
| 27 const FX_CHAR* name; |
| 28 PDF_PSOP op; |
| 29 }; |
| 30 |
| 31 const PDF_PSOpName kPsOpNames[] = { |
| 32 {"add", PSOP_ADD}, {"sub", PSOP_SUB}, |
| 33 {"mul", PSOP_MUL}, {"div", PSOP_DIV}, |
| 34 {"idiv", PSOP_IDIV}, {"mod", PSOP_MOD}, |
| 35 {"neg", PSOP_NEG}, {"abs", PSOP_ABS}, |
| 36 {"ceiling", PSOP_CEILING}, {"floor", PSOP_FLOOR}, |
| 37 {"round", PSOP_ROUND}, {"truncate", PSOP_TRUNCATE}, |
| 38 {"sqrt", PSOP_SQRT}, {"sin", PSOP_SIN}, |
| 39 {"cos", PSOP_COS}, {"atan", PSOP_ATAN}, |
| 40 {"exp", PSOP_EXP}, {"ln", PSOP_LN}, |
| 41 {"log", PSOP_LOG}, {"cvi", PSOP_CVI}, |
| 42 {"cvr", PSOP_CVR}, {"eq", PSOP_EQ}, |
| 43 {"ne", PSOP_NE}, {"gt", PSOP_GT}, |
| 44 {"ge", PSOP_GE}, {"lt", PSOP_LT}, |
| 45 {"le", PSOP_LE}, {"and", PSOP_AND}, |
| 46 {"or", PSOP_OR}, {"xor", PSOP_XOR}, |
| 47 {"not", PSOP_NOT}, {"bitshift", PSOP_BITSHIFT}, |
| 48 {"true", PSOP_TRUE}, {"false", PSOP_FALSE}, |
| 49 {"if", PSOP_IF}, {"ifelse", PSOP_IFELSE}, |
| 50 {"pop", PSOP_POP}, {"exch", PSOP_EXCH}, |
| 51 {"dup", PSOP_DUP}, {"copy", PSOP_COPY}, |
| 52 {"index", PSOP_INDEX}, {"roll", PSOP_ROLL}}; |
| 53 |
| 54 // See PDF Reference 1.7, page 170, table 3.36. |
| 55 bool IsValidBitsPerSample(uint32_t x) { |
| 56 switch (x) { |
| 57 case 1: |
| 58 case 2: |
| 59 case 4: |
| 60 case 8: |
| 61 case 12: |
| 62 case 16: |
| 63 case 24: |
| 64 case 32: |
| 65 return true; |
| 66 default: |
| 67 return false; |
| 68 } |
| 69 } |
| 70 |
| 71 // See PDF Reference 1.7, page 170. |
| 72 FX_FLOAT PDF_Interpolate(FX_FLOAT x, |
| 73 FX_FLOAT xmin, |
| 74 FX_FLOAT xmax, |
| 75 FX_FLOAT ymin, |
| 76 FX_FLOAT ymax) { |
| 77 FX_FLOAT divisor = xmax - xmin; |
| 78 return ymin + (divisor ? (x - xmin) * (ymax - ymin) / divisor : 0); |
| 79 } |
| 80 |
| 81 class CPDF_PSFunc : public CPDF_Function { |
| 82 public: |
| 83 CPDF_PSFunc() : CPDF_Function(Type::kType4PostScript) {} |
| 84 ~CPDF_PSFunc() override {} |
| 85 |
| 86 // CPDF_Function |
| 87 FX_BOOL v_Init(CPDF_Object* pObj) override; |
| 88 FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override; |
| 89 |
| 90 private: |
| 91 CPDF_PSEngine m_PS; |
| 92 }; |
| 93 |
| 94 FX_BOOL CPDF_PSFunc::v_Init(CPDF_Object* pObj) { |
| 95 CPDF_StreamAcc acc; |
| 96 acc.LoadAllData(pObj->AsStream(), FALSE); |
| 97 return m_PS.Parse(reinterpret_cast<const FX_CHAR*>(acc.GetData()), |
| 98 acc.GetSize()); |
| 99 } |
| 100 |
| 101 FX_BOOL CPDF_PSFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const { |
| 102 CPDF_PSEngine& PS = const_cast<CPDF_PSEngine&>(m_PS); |
| 103 PS.Reset(); |
| 104 for (uint32_t i = 0; i < m_nInputs; i++) |
| 105 PS.Push(inputs[i]); |
| 106 PS.Execute(); |
| 107 if (PS.GetStackSize() < m_nOutputs) |
| 108 return FALSE; |
| 109 for (uint32_t i = 0; i < m_nOutputs; i++) |
| 110 results[m_nOutputs - i - 1] = PS.Pop(); |
| 111 return TRUE; |
| 112 } |
| 113 |
| 114 } // namespace |
| 115 |
| 24 class CPDF_PSOP { | 116 class CPDF_PSOP { |
| 25 public: | 117 public: |
| 26 explicit CPDF_PSOP(PDF_PSOP op) : m_op(op), m_value(0) { | 118 explicit CPDF_PSOP(PDF_PSOP op) : m_op(op), m_value(0) { |
| 27 ASSERT(m_op != PSOP_CONST); | 119 ASSERT(m_op != PSOP_CONST); |
| 28 ASSERT(m_op != PSOP_PROC); | 120 ASSERT(m_op != PSOP_PROC); |
| 29 } | 121 } |
| 30 explicit CPDF_PSOP(FX_FLOAT value) : m_op(PSOP_CONST), m_value(value) {} | 122 explicit CPDF_PSOP(FX_FLOAT value) : m_op(PSOP_CONST), m_value(value) {} |
| 31 explicit CPDF_PSOP(std::unique_ptr<CPDF_PSProc> proc) | 123 explicit CPDF_PSOP(std::unique_ptr<CPDF_PSProc> proc) |
| 32 : m_op(PSOP_PROC), m_value(0), m_proc(std::move(proc)) {} | 124 : m_op(PSOP_PROC), m_value(0), m_proc(std::move(proc)) {} |
| 33 | 125 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 return; | 192 return; |
| 101 } | 193 } |
| 102 m_Stack[m_StackCount++] = v; | 194 m_Stack[m_StackCount++] = v; |
| 103 } | 195 } |
| 104 FX_FLOAT CPDF_PSEngine::Pop() { | 196 FX_FLOAT CPDF_PSEngine::Pop() { |
| 105 if (m_StackCount == 0) { | 197 if (m_StackCount == 0) { |
| 106 return 0; | 198 return 0; |
| 107 } | 199 } |
| 108 return m_Stack[--m_StackCount]; | 200 return m_Stack[--m_StackCount]; |
| 109 } | 201 } |
| 110 const struct PDF_PSOpName { | |
| 111 const FX_CHAR* name; | |
| 112 PDF_PSOP op; | |
| 113 } PDF_PSOpNames[] = {{"add", PSOP_ADD}, {"sub", PSOP_SUB}, | |
| 114 {"mul", PSOP_MUL}, {"div", PSOP_DIV}, | |
| 115 {"idiv", PSOP_IDIV}, {"mod", PSOP_MOD}, | |
| 116 {"neg", PSOP_NEG}, {"abs", PSOP_ABS}, | |
| 117 {"ceiling", PSOP_CEILING}, {"floor", PSOP_FLOOR}, | |
| 118 {"round", PSOP_ROUND}, {"truncate", PSOP_TRUNCATE}, | |
| 119 {"sqrt", PSOP_SQRT}, {"sin", PSOP_SIN}, | |
| 120 {"cos", PSOP_COS}, {"atan", PSOP_ATAN}, | |
| 121 {"exp", PSOP_EXP}, {"ln", PSOP_LN}, | |
| 122 {"log", PSOP_LOG}, {"cvi", PSOP_CVI}, | |
| 123 {"cvr", PSOP_CVR}, {"eq", PSOP_EQ}, | |
| 124 {"ne", PSOP_NE}, {"gt", PSOP_GT}, | |
| 125 {"ge", PSOP_GE}, {"lt", PSOP_LT}, | |
| 126 {"le", PSOP_LE}, {"and", PSOP_AND}, | |
| 127 {"or", PSOP_OR}, {"xor", PSOP_XOR}, | |
| 128 {"not", PSOP_NOT}, {"bitshift", PSOP_BITSHIFT}, | |
| 129 {"true", PSOP_TRUE}, {"false", PSOP_FALSE}, | |
| 130 {"if", PSOP_IF}, {"ifelse", PSOP_IFELSE}, | |
| 131 {"pop", PSOP_POP}, {"exch", PSOP_EXCH}, | |
| 132 {"dup", PSOP_DUP}, {"copy", PSOP_COPY}, | |
| 133 {"index", PSOP_INDEX}, {"roll", PSOP_ROLL}}; | |
| 134 | |
| 135 FX_BOOL CPDF_PSEngine::Parse(const FX_CHAR* str, int size) { | 202 FX_BOOL CPDF_PSEngine::Parse(const FX_CHAR* str, int size) { |
| 136 CPDF_SimpleParser parser((uint8_t*)str, size); | 203 CPDF_SimpleParser parser((uint8_t*)str, size); |
| 137 CFX_ByteStringC word = parser.GetWord(); | 204 CFX_ByteStringC word = parser.GetWord(); |
| 138 if (word != "{") { | 205 if (word != "{") { |
| 139 return FALSE; | 206 return FALSE; |
| 140 } | 207 } |
| 141 return m_MainProc.Parse(&parser, 0); | 208 return m_MainProc.Parse(&parser, 0); |
| 142 } | 209 } |
| 143 | 210 |
| 144 FX_BOOL CPDF_PSProc::Parse(CPDF_SimpleParser* parser, int depth) { | 211 FX_BOOL CPDF_PSProc::Parse(CPDF_SimpleParser* parser, int depth) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 155 } | 222 } |
| 156 if (word == "{") { | 223 if (word == "{") { |
| 157 std::unique_ptr<CPDF_PSProc> proc(new CPDF_PSProc); | 224 std::unique_ptr<CPDF_PSProc> proc(new CPDF_PSProc); |
| 158 std::unique_ptr<CPDF_PSOP> op(new CPDF_PSOP(std::move(proc))); | 225 std::unique_ptr<CPDF_PSOP> op(new CPDF_PSOP(std::move(proc))); |
| 159 m_Operators.push_back(std::move(op)); | 226 m_Operators.push_back(std::move(op)); |
| 160 if (!m_Operators.back()->GetProc()->Parse(parser, depth + 1)) { | 227 if (!m_Operators.back()->GetProc()->Parse(parser, depth + 1)) { |
| 161 return FALSE; | 228 return FALSE; |
| 162 } | 229 } |
| 163 } else { | 230 } else { |
| 164 bool found = false; | 231 bool found = false; |
| 165 for (const PDF_PSOpName& op_name : PDF_PSOpNames) { | 232 for (const PDF_PSOpName& op_name : kPsOpNames) { |
| 166 if (word == CFX_ByteStringC(op_name.name)) { | 233 if (word == CFX_ByteStringC(op_name.name)) { |
| 167 std::unique_ptr<CPDF_PSOP> op(new CPDF_PSOP(op_name.op)); | 234 std::unique_ptr<CPDF_PSOP> op(new CPDF_PSOP(op_name.op)); |
| 168 m_Operators.push_back(std::move(op)); | 235 m_Operators.push_back(std::move(op)); |
| 169 found = true; | 236 found = true; |
| 170 break; | 237 break; |
| 171 } | 238 } |
| 172 } | 239 } |
| 173 if (!found) { | 240 if (!found) { |
| 174 std::unique_ptr<CPDF_PSOP> op(new CPDF_PSOP(FX_atof(word))); | 241 std::unique_ptr<CPDF_PSOP> op(new CPDF_PSOP(FX_atof(word))); |
| 175 m_Operators.push_back(std::move(op)); | 242 m_Operators.push_back(std::move(op)); |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 } | 456 } |
| 390 case PSOP_ROLL: { | 457 case PSOP_ROLL: { |
| 391 int j = static_cast<int>(Pop()); | 458 int j = static_cast<int>(Pop()); |
| 392 int n = static_cast<int>(Pop()); | 459 int n = static_cast<int>(Pop()); |
| 393 if (j == 0 || n == 0 || m_StackCount == 0) | 460 if (j == 0 || n == 0 || m_StackCount == 0) |
| 394 break; | 461 break; |
| 395 if (n < 0 || n > static_cast<int>(m_StackCount)) | 462 if (n < 0 || n > static_cast<int>(m_StackCount)) |
| 396 break; | 463 break; |
| 397 | 464 |
| 398 j %= n; | 465 j %= n; |
| 399 if (j < 0) { | 466 if (j > 0) |
| 400 for (int i = 0; i < -j; i++) { | 467 j -= n; |
| 401 FX_FLOAT first = m_Stack[m_StackCount - n]; | 468 auto begin_it = std::begin(m_Stack) + m_StackCount - n; |
| 402 for (int ii = 0; ii < n - 1; ii++) | 469 auto middle_it = begin_it - j; |
| 403 m_Stack[m_StackCount - n + ii] = m_Stack[m_StackCount - n + ii + 1]; | 470 auto end_it = std::begin(m_Stack) + m_StackCount; |
| 404 m_Stack[m_StackCount - 1] = first; | 471 std::rotate(begin_it, middle_it, end_it); |
| 405 } | |
| 406 } else { | |
| 407 for (int i = 0; i < j; i++) { | |
| 408 FX_FLOAT last = m_Stack[m_StackCount - 1]; | |
| 409 int ii; | |
| 410 for (ii = 0; ii < n - 1; ii++) | |
| 411 m_Stack[m_StackCount - ii - 1] = m_Stack[m_StackCount - ii - 2]; | |
| 412 m_Stack[m_StackCount - ii - 1] = last; | |
| 413 } | |
| 414 } | |
| 415 break; | 472 break; |
| 416 } | 473 } |
| 417 default: | 474 default: |
| 418 break; | 475 break; |
| 419 } | 476 } |
| 420 return TRUE; | 477 return TRUE; |
| 421 } | 478 } |
| 422 | 479 |
| 423 // See PDF Reference 1.7, page 170, table 3.36. | |
| 424 bool IsValidBitsPerSample(uint32_t x) { | |
| 425 switch (x) { | |
| 426 case 1: | |
| 427 case 2: | |
| 428 case 4: | |
| 429 case 8: | |
| 430 case 12: | |
| 431 case 16: | |
| 432 case 24: | |
| 433 case 32: | |
| 434 return true; | |
| 435 default: | |
| 436 return false; | |
| 437 } | |
| 438 } | |
| 439 | |
| 440 // See PDF Reference 1.7, page 170. | |
| 441 FX_FLOAT PDF_Interpolate(FX_FLOAT x, | |
| 442 FX_FLOAT xmin, | |
| 443 FX_FLOAT xmax, | |
| 444 FX_FLOAT ymin, | |
| 445 FX_FLOAT ymax) { | |
| 446 FX_FLOAT divisor = xmax - xmin; | |
| 447 return ymin + (divisor ? (x - xmin) * (ymax - ymin) / divisor : 0); | |
| 448 } | |
| 449 | |
| 450 class CPDF_PSFunc : public CPDF_Function { | |
| 451 public: | |
| 452 CPDF_PSFunc() : CPDF_Function(Type::kType4PostScript) {} | |
| 453 ~CPDF_PSFunc() override {} | |
| 454 | |
| 455 // CPDF_Function | |
| 456 FX_BOOL v_Init(CPDF_Object* pObj) override; | |
| 457 FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override; | |
| 458 | |
| 459 private: | |
| 460 CPDF_PSEngine m_PS; | |
| 461 }; | |
| 462 | |
| 463 FX_BOOL CPDF_PSFunc::v_Init(CPDF_Object* pObj) { | |
| 464 CPDF_StreamAcc acc; | |
| 465 acc.LoadAllData(pObj->AsStream(), FALSE); | |
| 466 return m_PS.Parse(reinterpret_cast<const FX_CHAR*>(acc.GetData()), | |
| 467 acc.GetSize()); | |
| 468 } | |
| 469 | |
| 470 FX_BOOL CPDF_PSFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const { | |
| 471 CPDF_PSEngine& PS = const_cast<CPDF_PSEngine&>(m_PS); | |
| 472 PS.Reset(); | |
| 473 for (uint32_t i = 0; i < m_nInputs; i++) | |
| 474 PS.Push(inputs[i]); | |
| 475 PS.Execute(); | |
| 476 if (PS.GetStackSize() < m_nOutputs) | |
| 477 return FALSE; | |
| 478 for (uint32_t i = 0; i < m_nOutputs; i++) | |
| 479 results[m_nOutputs - i - 1] = PS.Pop(); | |
| 480 return TRUE; | |
| 481 } | |
| 482 | |
| 483 CPDF_SampledFunc::CPDF_SampledFunc() : CPDF_Function(Type::kType0Sampled) {} | 480 CPDF_SampledFunc::CPDF_SampledFunc() : CPDF_Function(Type::kType0Sampled) {} |
| 484 | 481 |
| 485 CPDF_SampledFunc::~CPDF_SampledFunc() {} | 482 CPDF_SampledFunc::~CPDF_SampledFunc() {} |
| 486 | 483 |
| 487 FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj) { | 484 FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj) { |
| 488 CPDF_Stream* pStream = pObj->AsStream(); | 485 CPDF_Stream* pStream = pObj->AsStream(); |
| 489 if (!pStream) | 486 if (!pStream) |
| 490 return false; | 487 return false; |
| 491 | 488 |
| 492 CPDF_Dictionary* pDict = pStream->GetDict(); | 489 CPDF_Dictionary* pDict = pStream->GetDict(); |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 return m_Type == Type::kType2ExpotentialInterpolation | 849 return m_Type == Type::kType2ExpotentialInterpolation |
| 853 ? static_cast<const CPDF_ExpIntFunc*>(this) | 850 ? static_cast<const CPDF_ExpIntFunc*>(this) |
| 854 : nullptr; | 851 : nullptr; |
| 855 } | 852 } |
| 856 | 853 |
| 857 const CPDF_StitchFunc* CPDF_Function::ToStitchFunc() const { | 854 const CPDF_StitchFunc* CPDF_Function::ToStitchFunc() const { |
| 858 return m_Type == Type::kType3Stitching | 855 return m_Type == Type::kType3Stitching |
| 859 ? static_cast<const CPDF_StitchFunc*>(this) | 856 ? static_cast<const CPDF_StitchFunc*>(this) |
| 860 : nullptr; | 857 : nullptr; |
| 861 } | 858 } |
| OLD | NEW |