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 |