Chromium Code Reviews| 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 const struct PDF_PSOpName { | |
|
Tom Sepez
2016/10/13 16:21:30
nit: as long as we're moving this, can we split th
Lei Zhang
2016/10/13 22:48:19
Done.
| |
| 27 const FX_CHAR* name; | |
| 28 PDF_PSOP op; | |
| 29 } PDF_PSOpNames[] = {{"add", PSOP_ADD}, {"sub", PSOP_SUB}, | |
| 30 {"mul", PSOP_MUL}, {"div", PSOP_DIV}, | |
| 31 {"idiv", PSOP_IDIV}, {"mod", PSOP_MOD}, | |
| 32 {"neg", PSOP_NEG}, {"abs", PSOP_ABS}, | |
| 33 {"ceiling", PSOP_CEILING}, {"floor", PSOP_FLOOR}, | |
| 34 {"round", PSOP_ROUND}, {"truncate", PSOP_TRUNCATE}, | |
| 35 {"sqrt", PSOP_SQRT}, {"sin", PSOP_SIN}, | |
| 36 {"cos", PSOP_COS}, {"atan", PSOP_ATAN}, | |
| 37 {"exp", PSOP_EXP}, {"ln", PSOP_LN}, | |
| 38 {"log", PSOP_LOG}, {"cvi", PSOP_CVI}, | |
| 39 {"cvr", PSOP_CVR}, {"eq", PSOP_EQ}, | |
| 40 {"ne", PSOP_NE}, {"gt", PSOP_GT}, | |
| 41 {"ge", PSOP_GE}, {"lt", PSOP_LT}, | |
| 42 {"le", PSOP_LE}, {"and", PSOP_AND}, | |
| 43 {"or", PSOP_OR}, {"xor", PSOP_XOR}, | |
| 44 {"not", PSOP_NOT}, {"bitshift", PSOP_BITSHIFT}, | |
| 45 {"true", PSOP_TRUE}, {"false", PSOP_FALSE}, | |
| 46 {"if", PSOP_IF}, {"ifelse", PSOP_IFELSE}, | |
| 47 {"pop", PSOP_POP}, {"exch", PSOP_EXCH}, | |
| 48 {"dup", PSOP_DUP}, {"copy", PSOP_COPY}, | |
| 49 {"index", PSOP_INDEX}, {"roll", PSOP_ROLL}}; | |
| 50 | |
| 51 // See PDF Reference 1.7, page 170, table 3.36. | |
| 52 bool IsValidBitsPerSample(uint32_t x) { | |
| 53 switch (x) { | |
| 54 case 1: | |
| 55 case 2: | |
| 56 case 4: | |
| 57 case 8: | |
| 58 case 12: | |
| 59 case 16: | |
| 60 case 24: | |
| 61 case 32: | |
| 62 return true; | |
| 63 default: | |
| 64 return false; | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 // See PDF Reference 1.7, page 170. | |
| 69 FX_FLOAT PDF_Interpolate(FX_FLOAT x, | |
| 70 FX_FLOAT xmin, | |
| 71 FX_FLOAT xmax, | |
| 72 FX_FLOAT ymin, | |
| 73 FX_FLOAT ymax) { | |
| 74 FX_FLOAT divisor = xmax - xmin; | |
| 75 return ymin + (divisor ? (x - xmin) * (ymax - ymin) / divisor : 0); | |
| 76 } | |
| 77 | |
| 78 class CPDF_PSFunc : public CPDF_Function { | |
| 79 public: | |
| 80 CPDF_PSFunc() : CPDF_Function(Type::kType4PostScript) {} | |
| 81 ~CPDF_PSFunc() override {} | |
| 82 | |
| 83 // CPDF_Function | |
| 84 FX_BOOL v_Init(CPDF_Object* pObj) override; | |
| 85 FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override; | |
| 86 | |
| 87 private: | |
| 88 CPDF_PSEngine m_PS; | |
| 89 }; | |
| 90 | |
| 91 FX_BOOL CPDF_PSFunc::v_Init(CPDF_Object* pObj) { | |
| 92 CPDF_StreamAcc acc; | |
| 93 acc.LoadAllData(pObj->AsStream(), FALSE); | |
| 94 return m_PS.Parse(reinterpret_cast<const FX_CHAR*>(acc.GetData()), | |
| 95 acc.GetSize()); | |
| 96 } | |
| 97 | |
| 98 FX_BOOL CPDF_PSFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const { | |
| 99 CPDF_PSEngine& PS = const_cast<CPDF_PSEngine&>(m_PS); | |
| 100 PS.Reset(); | |
| 101 for (uint32_t i = 0; i < m_nInputs; i++) | |
| 102 PS.Push(inputs[i]); | |
| 103 PS.Execute(); | |
| 104 if (PS.GetStackSize() < m_nOutputs) | |
| 105 return FALSE; | |
| 106 for (uint32_t i = 0; i < m_nOutputs; i++) | |
| 107 results[m_nOutputs - i - 1] = PS.Pop(); | |
| 108 return TRUE; | |
| 109 } | |
| 110 | |
| 111 } // namespace | |
| 112 | |
| 24 class CPDF_PSOP { | 113 class CPDF_PSOP { |
| 25 public: | 114 public: |
| 26 explicit CPDF_PSOP(PDF_PSOP op) : m_op(op), m_value(0) { | 115 explicit CPDF_PSOP(PDF_PSOP op) : m_op(op), m_value(0) { |
| 27 ASSERT(m_op != PSOP_CONST); | 116 ASSERT(m_op != PSOP_CONST); |
| 28 ASSERT(m_op != PSOP_PROC); | 117 ASSERT(m_op != PSOP_PROC); |
| 29 } | 118 } |
| 30 explicit CPDF_PSOP(FX_FLOAT value) : m_op(PSOP_CONST), m_value(value) {} | 119 explicit CPDF_PSOP(FX_FLOAT value) : m_op(PSOP_CONST), m_value(value) {} |
| 31 explicit CPDF_PSOP(std::unique_ptr<CPDF_PSProc> proc) | 120 explicit CPDF_PSOP(std::unique_ptr<CPDF_PSProc> proc) |
| 32 : m_op(PSOP_PROC), m_value(0), m_proc(std::move(proc)) {} | 121 : m_op(PSOP_PROC), m_value(0), m_proc(std::move(proc)) {} |
| 33 | 122 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 100 return; | 189 return; |
| 101 } | 190 } |
| 102 m_Stack[m_StackCount++] = v; | 191 m_Stack[m_StackCount++] = v; |
| 103 } | 192 } |
| 104 FX_FLOAT CPDF_PSEngine::Pop() { | 193 FX_FLOAT CPDF_PSEngine::Pop() { |
| 105 if (m_StackCount == 0) { | 194 if (m_StackCount == 0) { |
| 106 return 0; | 195 return 0; |
| 107 } | 196 } |
| 108 return m_Stack[--m_StackCount]; | 197 return m_Stack[--m_StackCount]; |
| 109 } | 198 } |
| 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) { | 199 FX_BOOL CPDF_PSEngine::Parse(const FX_CHAR* str, int size) { |
| 136 CPDF_SimpleParser parser((uint8_t*)str, size); | 200 CPDF_SimpleParser parser((uint8_t*)str, size); |
| 137 CFX_ByteStringC word = parser.GetWord(); | 201 CFX_ByteStringC word = parser.GetWord(); |
| 138 if (word != "{") { | 202 if (word != "{") { |
| 139 return FALSE; | 203 return FALSE; |
| 140 } | 204 } |
| 141 return m_MainProc.Parse(&parser, 0); | 205 return m_MainProc.Parse(&parser, 0); |
| 142 } | 206 } |
| 143 | 207 |
| 144 FX_BOOL CPDF_PSProc::Parse(CPDF_SimpleParser* parser, int depth) { | 208 FX_BOOL CPDF_PSProc::Parse(CPDF_SimpleParser* parser, int depth) { |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 389 } | 453 } |
| 390 case PSOP_ROLL: { | 454 case PSOP_ROLL: { |
| 391 int j = static_cast<int>(Pop()); | 455 int j = static_cast<int>(Pop()); |
| 392 int n = static_cast<int>(Pop()); | 456 int n = static_cast<int>(Pop()); |
| 393 if (j == 0 || n == 0 || m_StackCount == 0) | 457 if (j == 0 || n == 0 || m_StackCount == 0) |
| 394 break; | 458 break; |
| 395 if (n < 0 || n > static_cast<int>(m_StackCount)) | 459 if (n < 0 || n > static_cast<int>(m_StackCount)) |
| 396 break; | 460 break; |
| 397 | 461 |
| 398 j %= n; | 462 j %= n; |
| 399 if (j < 0) { | 463 if (j > 0) |
| 400 for (int i = 0; i < -j; i++) { | 464 j -= n; |
| 401 FX_FLOAT first = m_Stack[m_StackCount - n]; | 465 auto begin_it = std::begin(m_Stack) + m_StackCount - n; |
| 402 for (int ii = 0; ii < n - 1; ii++) | 466 auto end_it = begin_it + n; |
|
Tom Sepez
2016/10/13 16:21:30
Maybe it's easier to compute end_it first as
st
Lei Zhang
2016/10/13 22:48:19
I was trying to keep the arguments to std::rotate(
| |
| 403 m_Stack[m_StackCount - n + ii] = m_Stack[m_StackCount - n + ii + 1]; | 467 auto middle_it = begin_it - j; |
|
Tom Sepez
2016/10/13 16:21:30
I'm confused. Middle comes before begin?
Lei Zhang
2016/10/13 22:48:19
|j| is always negative here. I had it as an additi
| |
| 404 m_Stack[m_StackCount - 1] = first; | 468 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; | 469 break; |
| 416 } | 470 } |
| 417 default: | 471 default: |
| 418 break; | 472 break; |
| 419 } | 473 } |
| 420 return TRUE; | 474 return TRUE; |
| 421 } | 475 } |
| 422 | 476 |
| 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) {} | 477 CPDF_SampledFunc::CPDF_SampledFunc() : CPDF_Function(Type::kType0Sampled) {} |
| 484 | 478 |
| 485 CPDF_SampledFunc::~CPDF_SampledFunc() {} | 479 CPDF_SampledFunc::~CPDF_SampledFunc() {} |
| 486 | 480 |
| 487 FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj) { | 481 FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj) { |
| 488 CPDF_Stream* pStream = pObj->AsStream(); | 482 CPDF_Stream* pStream = pObj->AsStream(); |
| 489 if (!pStream) | 483 if (!pStream) |
| 490 return false; | 484 return false; |
| 491 | 485 |
| 492 CPDF_Dictionary* pDict = pStream->GetDict(); | 486 CPDF_Dictionary* pDict = pStream->GetDict(); |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 852 return m_Type == Type::kType2ExpotentialInterpolation | 846 return m_Type == Type::kType2ExpotentialInterpolation |
| 853 ? static_cast<const CPDF_ExpIntFunc*>(this) | 847 ? static_cast<const CPDF_ExpIntFunc*>(this) |
| 854 : nullptr; | 848 : nullptr; |
| 855 } | 849 } |
| 856 | 850 |
| 857 const CPDF_StitchFunc* CPDF_Function::ToStitchFunc() const { | 851 const CPDF_StitchFunc* CPDF_Function::ToStitchFunc() const { |
| 858 return m_Type == Type::kType3Stitching | 852 return m_Type == Type::kType3Stitching |
| 859 ? static_cast<const CPDF_StitchFunc*>(this) | 853 ? static_cast<const CPDF_StitchFunc*>(this) |
| 860 : nullptr; | 854 : nullptr; |
| 861 } | 855 } |
| OLD | NEW |