1 // Copyright 2014 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 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/fpdfapi/fpdf_page/pageint.h"
8
9 #include <limits.h>
10
11 #include <algorithm>
12 #include <memory>
13 #include <utility>
14 #include <vector>
15
16 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
17 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
18 #include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h"
19 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
20 #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
21 #include "core/fxcrt/include/fx_safe_types.h"
22 #include "third_party/base/numerics/safe_conversions_impl.h"
23
24 namespace {
25
26 enum PDF_PSOP {
27 PSOP_ADD,
28 PSOP_SUB,
29 PSOP_MUL,
30 PSOP_DIV,
31 PSOP_IDIV,
32 PSOP_MOD,
33 PSOP_NEG,
34 PSOP_ABS,
35 PSOP_CEILING,
36 PSOP_FLOOR,
37 PSOP_ROUND,
38 PSOP_TRUNCATE,
39 PSOP_SQRT,
40 PSOP_SIN,
41 PSOP_COS,
42 PSOP_ATAN,
43 PSOP_EXP,
44 PSOP_LN,
45 PSOP_LOG,
46 PSOP_CVI,
47 PSOP_CVR,
48 PSOP_EQ,
49 PSOP_NE,
50 PSOP_GT,
51 PSOP_GE,
52 PSOP_LT,
53 PSOP_LE,
54 PSOP_AND,
55 PSOP_OR,
56 PSOP_XOR,
57 PSOP_NOT,
58 PSOP_BITSHIFT,
59 PSOP_TRUE,
60 PSOP_FALSE,
61 PSOP_IF,
62 PSOP_IFELSE,
63 PSOP_POP,
64 PSOP_EXCH,
65 PSOP_DUP,
66 PSOP_COPY,
67 PSOP_INDEX,
68 PSOP_ROLL,
69 PSOP_PROC,
70 PSOP_CONST
71 };
72
73 class CPDF_PSEngine;
74 class CPDF_PSProc;
75
76 class CPDF_PSOP {
77 public:
CPDF_PSOP(PDF_PSOP op)78 explicit CPDF_PSOP(PDF_PSOP op) : m_op(op), m_value(0) {
79 ASSERT(m_op != PSOP_CONST);
80 ASSERT(m_op != PSOP_PROC);
81 }
CPDF_PSOP(FX_FLOAT value)82 explicit CPDF_PSOP(FX_FLOAT value) : m_op(PSOP_CONST), m_value(value) {}
CPDF_PSOP(std::unique_ptr<CPDF_PSProc> proc)83 explicit CPDF_PSOP(std::unique_ptr<CPDF_PSProc> proc)
84 : m_op(PSOP_PROC), m_value(0), m_proc(std::move(proc)) {}
85
GetFloatValue() const86 FX_FLOAT GetFloatValue() const {
87 if (m_op == PSOP_CONST)
88 return m_value;
89
90 ASSERT(false);
91 return 0;
92 }
GetProc() const93 CPDF_PSProc* GetProc() const {
94 if (m_op == PSOP_PROC)
95 return m_proc.get();
96 ASSERT(false);
97 return nullptr;
98 }
99
GetOp() const100 PDF_PSOP GetOp() const { return m_op; }
101
102 private:
103 const PDF_PSOP m_op;
104 const FX_FLOAT m_value;
105 std::unique_ptr<CPDF_PSProc> m_proc;
106 };
107
108 class CPDF_PSProc {
109 public:
CPDF_PSProc()110 CPDF_PSProc() {}
~CPDF_PSProc()111 ~CPDF_PSProc() {}
112
113 FX_BOOL Parse(CPDF_SimpleParser* parser);
114 FX_BOOL Execute(CPDF_PSEngine* pEngine);
115
116 private:
117 std::vector<std::unique_ptr<CPDF_PSOP>> m_Operators;
118 };
119
120 const uint32_t PSENGINE_STACKSIZE = 100;
121
122 class CPDF_PSEngine {
123 public:
124 CPDF_PSEngine();
125 ~CPDF_PSEngine();
126
127 FX_BOOL Parse(const FX_CHAR* str, int size);
Execute()128 FX_BOOL Execute() { return m_MainProc.Execute(this); }
129 FX_BOOL DoOperator(PDF_PSOP op);
Reset()130 void Reset() { m_StackCount = 0; }
131 void Push(FX_FLOAT value);
Push(int value)132 void Push(int value) { Push((FX_FLOAT)value); }
133 FX_FLOAT Pop();
GetStackSize() const134 uint32_t GetStackSize() const { return m_StackCount; }
135
136 private:
137 FX_FLOAT m_Stack[PSENGINE_STACKSIZE];
138 uint32_t m_StackCount;
139 CPDF_PSProc m_MainProc;
140 };
141
Execute(CPDF_PSEngine * pEngine)142 FX_BOOL CPDF_PSProc::Execute(CPDF_PSEngine* pEngine) {
143 for (size_t i = 0; i < m_Operators.size(); ++i) {
144 const PDF_PSOP op = m_Operators[i]->GetOp();
145 if (op == PSOP_PROC)
146 continue;
147
148 if (op == PSOP_CONST) {
149 pEngine->Push(m_Operators[i]->GetFloatValue());
150 continue;
151 }
152
153 if (op == PSOP_IF) {
154 if (i == 0 || m_Operators[i - 1]->GetOp() != PSOP_PROC)
155 return FALSE;
156
157 if (static_cast<int>(pEngine->Pop()))
158 m_Operators[i - 1]->GetProc()->Execute(pEngine);
159 } else if (op == PSOP_IFELSE) {
160 if (i < 2 || m_Operators[i - 1]->GetOp() != PSOP_PROC ||
161 m_Operators[i - 2]->GetOp() != PSOP_PROC) {
162 return FALSE;
163 }
164 size_t offset = static_cast<int>(pEngine->Pop()) ? 2 : 1;
165 m_Operators[i - offset]->GetProc()->Execute(pEngine);
166 } else {
167 pEngine->DoOperator(op);
168 }
169 }
170 return TRUE;
171 }
172
CPDF_PSEngine()173 CPDF_PSEngine::CPDF_PSEngine() {
174 m_StackCount = 0;
175 }
~CPDF_PSEngine()176 CPDF_PSEngine::~CPDF_PSEngine() {}
Push(FX_FLOAT v)177 void CPDF_PSEngine::Push(FX_FLOAT v) {
178 if (m_StackCount == PSENGINE_STACKSIZE) {
179 return;
180 }
181 m_Stack[m_StackCount++] = v;
182 }
Pop()183 FX_FLOAT CPDF_PSEngine::Pop() {
184 if (m_StackCount == 0) {
185 return 0;
186 }
187 return m_Stack[--m_StackCount];
188 }
189 const struct PDF_PSOpName {
190 const FX_CHAR* name;
191 PDF_PSOP op;
192 } PDF_PSOpNames[] = {{"add", PSOP_ADD}, {"sub", PSOP_SUB},
193 {"mul", PSOP_MUL}, {"div", PSOP_DIV},
194 {"idiv", PSOP_IDIV}, {"mod", PSOP_MOD},
195 {"neg", PSOP_NEG}, {"abs", PSOP_ABS},
196 {"ceiling", PSOP_CEILING}, {"floor", PSOP_FLOOR},
197 {"round", PSOP_ROUND}, {"truncate", PSOP_TRUNCATE},
198 {"sqrt", PSOP_SQRT}, {"sin", PSOP_SIN},
199 {"cos", PSOP_COS}, {"atan", PSOP_ATAN},
200 {"exp", PSOP_EXP}, {"ln", PSOP_LN},
201 {"log", PSOP_LOG}, {"cvi", PSOP_CVI},
202 {"cvr", PSOP_CVR}, {"eq", PSOP_EQ},
203 {"ne", PSOP_NE}, {"gt", PSOP_GT},
204 {"ge", PSOP_GE}, {"lt", PSOP_LT},
205 {"le", PSOP_LE}, {"and", PSOP_AND},
206 {"or", PSOP_OR}, {"xor", PSOP_XOR},
207 {"not", PSOP_NOT}, {"bitshift", PSOP_BITSHIFT},
208 {"true", PSOP_TRUE}, {"false", PSOP_FALSE},
209 {"if", PSOP_IF}, {"ifelse", PSOP_IFELSE},
210 {"pop", PSOP_POP}, {"exch", PSOP_EXCH},
211 {"dup", PSOP_DUP}, {"copy", PSOP_COPY},
212 {"index", PSOP_INDEX}, {"roll", PSOP_ROLL}};
213
Parse(const FX_CHAR * str,int size)214 FX_BOOL CPDF_PSEngine::Parse(const FX_CHAR* str, int size) {
215 CPDF_SimpleParser parser((uint8_t*)str, size);
216 CFX_ByteStringC word = parser.GetWord();
217 if (word != "{") {
218 return FALSE;
219 }
220 return m_MainProc.Parse(&parser);
221 }
Parse(CPDF_SimpleParser * parser)222 FX_BOOL CPDF_PSProc::Parse(CPDF_SimpleParser* parser) {
223 while (1) {
224 CFX_ByteStringC word = parser->GetWord();
225 if (word.IsEmpty()) {
226 return FALSE;
227 }
228 if (word == "}") {
229 return TRUE;
230 }
231 if (word == "{") {
232 std::unique_ptr<CPDF_PSProc> proc(new CPDF_PSProc);
233 std::unique_ptr<CPDF_PSOP> op(new CPDF_PSOP(std::move(proc)));
234 m_Operators.push_back(std::move(op));
235 if (!m_Operators.back()->GetProc()->Parse(parser)) {
236 return FALSE;
237 }
238 } else {
239 bool found = false;
240 for (const PDF_PSOpName& op_name : PDF_PSOpNames) {
241 if (word == CFX_ByteStringC(op_name.name)) {
242 std::unique_ptr<CPDF_PSOP> op(new CPDF_PSOP(op_name.op));
243 m_Operators.push_back(std::move(op));
244 found = true;
245 break;
246 }
247 }
248 if (!found) {
249 std::unique_ptr<CPDF_PSOP> op(new CPDF_PSOP(FX_atof(word)));
250 m_Operators.push_back(std::move(op));
251 }
252 }
253 }
254 }
255
DoOperator(PDF_PSOP op)256 FX_BOOL CPDF_PSEngine::DoOperator(PDF_PSOP op) {
257 int i1, i2;
258 FX_FLOAT d1, d2;
259 switch (op) {
260 case PSOP_ADD:
261 d1 = Pop();
262 d2 = Pop();
263 Push(d1 + d2);
264 break;
265 case PSOP_SUB:
266 d2 = Pop();
267 d1 = Pop();
268 Push(d1 - d2);
269 break;
270 case PSOP_MUL:
271 d1 = Pop();
272 d2 = Pop();
273 Push(d1 * d2);
274 break;
275 case PSOP_DIV:
276 d2 = Pop();
277 d1 = Pop();
278 Push(d1 / d2);
279 break;
280 case PSOP_IDIV:
281 i2 = (int)Pop();
282 i1 = (int)Pop();
283 Push(i1 / i2);
284 break;
285 case PSOP_MOD:
286 i2 = (int)Pop();
287 i1 = (int)Pop();
288 Push(i1 % i2);
289 break;
290 case PSOP_NEG:
291 d1 = Pop();
292 Push(-d1);
293 break;
294 case PSOP_ABS:
295 d1 = Pop();
296 Push((FX_FLOAT)FXSYS_fabs(d1));
297 break;
298 case PSOP_CEILING:
299 d1 = Pop();
300 Push((FX_FLOAT)FXSYS_ceil(d1));
301 break;
302 case PSOP_FLOOR:
303 d1 = Pop();
304 Push((FX_FLOAT)FXSYS_floor(d1));
305 break;
306 case PSOP_ROUND:
307 d1 = Pop();
308 Push(FXSYS_round(d1));
309 break;
310 case PSOP_TRUNCATE:
311 i1 = (int)Pop();
312 Push(i1);
313 break;
314 case PSOP_SQRT:
315 d1 = Pop();
316 Push((FX_FLOAT)FXSYS_sqrt(d1));
317 break;
318 case PSOP_SIN:
319 d1 = Pop();
320 Push((FX_FLOAT)FXSYS_sin(d1 * FX_PI / 180.0f));
321 break;
322 case PSOP_COS:
323 d1 = Pop();
324 Push((FX_FLOAT)FXSYS_cos(d1 * FX_PI / 180.0f));
325 break;
326 case PSOP_ATAN:
327 d2 = Pop();
328 d1 = Pop();
329 d1 = (FX_FLOAT)(FXSYS_atan2(d1, d2) * 180.0 / FX_PI);
330 if (d1 < 0) {
331 d1 += 360;
332 }
333 Push(d1);
334 break;
335 case PSOP_EXP:
336 d2 = Pop();
337 d1 = Pop();
338 Push((FX_FLOAT)FXSYS_pow(d1, d2));
339 break;
340 case PSOP_LN:
341 d1 = Pop();
342 Push((FX_FLOAT)FXSYS_log(d1));
343 break;
344 case PSOP_LOG:
345 d1 = Pop();
346 Push((FX_FLOAT)FXSYS_log10(d1));
347 break;
348 case PSOP_CVI:
349 i1 = (int)Pop();
350 Push(i1);
351 break;
352 case PSOP_CVR:
353 break;
354 case PSOP_EQ:
355 d2 = Pop();
356 d1 = Pop();
357 Push((int)(d1 == d2));
358 break;
359 case PSOP_NE:
360 d2 = Pop();
361 d1 = Pop();
362 Push((int)(d1 != d2));
363 break;
364 case PSOP_GT:
365 d2 = Pop();
366 d1 = Pop();
367 Push((int)(d1 > d2));
368 break;
369 case PSOP_GE:
370 d2 = Pop();
371 d1 = Pop();
372 Push((int)(d1 >= d2));
373 break;
374 case PSOP_LT:
375 d2 = Pop();
376 d1 = Pop();
377 Push((int)(d1 < d2));
378 break;
379 case PSOP_LE:
380 d2 = Pop();
381 d1 = Pop();
382 Push((int)(d1 <= d2));
383 break;
384 case PSOP_AND:
385 i1 = (int)Pop();
386 i2 = (int)Pop();
387 Push(i1 & i2);
388 break;
389 case PSOP_OR:
390 i1 = (int)Pop();
391 i2 = (int)Pop();
392 Push(i1 | i2);
393 break;
394 case PSOP_XOR:
395 i1 = (int)Pop();
396 i2 = (int)Pop();
397 Push(i1 ^ i2);
398 break;
399 case PSOP_NOT:
400 i1 = (int)Pop();
401 Push((int)!i1);
402 break;
403 case PSOP_BITSHIFT: {
404 int shift = (int)Pop();
405 int i = (int)Pop();
406 if (shift > 0) {
407 Push(i << shift);
408 } else {
409 Push(i >> -shift);
410 }
411 break;
412 }
413 case PSOP_TRUE:
414 Push(1);
415 break;
416 case PSOP_FALSE:
417 Push(0);
418 break;
419 case PSOP_POP:
420 Pop();
421 break;
422 case PSOP_EXCH:
423 d2 = Pop();
424 d1 = Pop();
425 Push(d2);
426 Push(d1);
427 break;
428 case PSOP_DUP:
429 d1 = Pop();
430 Push(d1);
431 Push(d1);
432 break;
433 case PSOP_COPY: {
434 int n = static_cast<int>(Pop());
435 if (n < 0 || m_StackCount + n > PSENGINE_STACKSIZE ||
436 n > static_cast<int>(m_StackCount))
437 break;
438 for (int i = 0; i < n; i++)
439 m_Stack[m_StackCount + i] = m_Stack[m_StackCount + i - n];
440 m_StackCount += n;
441 break;
442 }
443 case PSOP_INDEX: {
444 int n = static_cast<int>(Pop());
445 if (n < 0 || n >= static_cast<int>(m_StackCount))
446 break;
447 Push(m_Stack[m_StackCount - n - 1]);
448 break;
449 }
450 case PSOP_ROLL: {
451 int j = static_cast<int>(Pop());
452 int n = static_cast<int>(Pop());
453 if (m_StackCount == 0)
454 break;
455 if (n < 0 || n > static_cast<int>(m_StackCount))
456 break;
457 if (j < 0) {
458 for (int i = 0; i < -j; i++) {
459 FX_FLOAT first = m_Stack[m_StackCount - n];
460 for (int ii = 0; ii < n - 1; ii++)
461 m_Stack[m_StackCount - n + ii] = m_Stack[m_StackCount - n + ii + 1];
462 m_Stack[m_StackCount - 1] = first;
463 }
464 } else {
465 for (int i = 0; i < j; i++) {
466 FX_FLOAT last = m_Stack[m_StackCount - 1];
467 int ii;
468 for (ii = 0; ii < n - 1; ii++)
469 m_Stack[m_StackCount - ii - 1] = m_Stack[m_StackCount - ii - 2];
470 m_Stack[m_StackCount - ii - 1] = last;
471 }
472 }
473 break;
474 }
475 default:
476 break;
477 }
478 return TRUE;
479 }
480
481 // See PDF Reference 1.7, page 170, table 3.36.
IsValidBitsPerSample(uint32_t x)482 bool IsValidBitsPerSample(uint32_t x) {
483 switch (x) {
484 case 1:
485 case 2:
486 case 4:
487 case 8:
488 case 12:
489 case 16:
490 case 24:
491 case 32:
492 return true;
493 default:
494 return false;
495 }
496 }
497
498 // See PDF Reference 1.7, page 170.
PDF_Interpolate(FX_FLOAT x,FX_FLOAT xmin,FX_FLOAT xmax,FX_FLOAT ymin,FX_FLOAT ymax)499 FX_FLOAT PDF_Interpolate(FX_FLOAT x,
500 FX_FLOAT xmin,
501 FX_FLOAT xmax,
502 FX_FLOAT ymin,
503 FX_FLOAT ymax) {
504 FX_FLOAT divisor = xmax - xmin;
505 return ymin + (divisor ? (x - xmin) * (ymax - ymin) / divisor : 0);
506 }
507
508 class CPDF_PSFunc : public CPDF_Function {
509 public:
CPDF_PSFunc()510 CPDF_PSFunc() : CPDF_Function(Type::kType4PostScript) {}
~CPDF_PSFunc()511 ~CPDF_PSFunc() override {}
512
513 // CPDF_Function
514 FX_BOOL v_Init(CPDF_Object* pObj) override;
515 FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override;
516
517 private:
518 CPDF_PSEngine m_PS;
519 };
520
v_Init(CPDF_Object * pObj)521 FX_BOOL CPDF_PSFunc::v_Init(CPDF_Object* pObj) {
522 CPDF_StreamAcc acc;
523 acc.LoadAllData(pObj->AsStream(), FALSE);
524 return m_PS.Parse(reinterpret_cast<const FX_CHAR*>(acc.GetData()),
525 acc.GetSize());
526 }
527
v_Call(FX_FLOAT * inputs,FX_FLOAT * results) const528 FX_BOOL CPDF_PSFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const {
529 CPDF_PSEngine& PS = const_cast<CPDF_PSEngine&>(m_PS);
530 PS.Reset();
531 for (uint32_t i = 0; i < m_nInputs; i++)
532 PS.Push(inputs[i]);
533 PS.Execute();
534 if (PS.GetStackSize() < m_nOutputs)
535 return FALSE;
536 for (uint32_t i = 0; i < m_nOutputs; i++)
537 results[m_nOutputs - i - 1] = PS.Pop();
538 return TRUE;
539 }
540
541 } // namespace
542
CPDF_SampledFunc()543 CPDF_SampledFunc::CPDF_SampledFunc() : CPDF_Function(Type::kType0Sampled) {}
544
~CPDF_SampledFunc()545 CPDF_SampledFunc::~CPDF_SampledFunc() {}
546
v_Init(CPDF_Object * pObj)547 FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj) {
548 CPDF_Stream* pStream = pObj->AsStream();
549 if (!pStream)
550 return false;
551
552 CPDF_Dictionary* pDict = pStream->GetDict();
553 CPDF_Array* pSize = pDict->GetArrayBy("Size");
554 CPDF_Array* pEncode = pDict->GetArrayBy("Encode");
555 CPDF_Array* pDecode = pDict->GetArrayBy("Decode");
556 m_nBitsPerSample = pDict->GetIntegerBy("BitsPerSample");
557 if (!IsValidBitsPerSample(m_nBitsPerSample))
558 return FALSE;
559
560 m_SampleMax = 0xffffffff >> (32 - m_nBitsPerSample);
561 m_pSampleStream.reset(new CPDF_StreamAcc);
562 m_pSampleStream->LoadAllData(pStream, FALSE);
563 FX_SAFE_UINT32 nTotalSampleBits = 1;
564 m_EncodeInfo.resize(m_nInputs);
565 for (uint32_t i = 0; i < m_nInputs; i++) {
566 m_EncodeInfo[i].sizes = pSize ? pSize->GetIntegerAt(i) : 0;
567 if (!pSize && i == 0)
568 m_EncodeInfo[i].sizes = pDict->GetIntegerBy("Size");
569 nTotalSampleBits *= m_EncodeInfo[i].sizes;
570 if (pEncode) {
571 m_EncodeInfo[i].encode_min = pEncode->GetFloatAt(i * 2);
572 m_EncodeInfo[i].encode_max = pEncode->GetFloatAt(i * 2 + 1);
573 } else {
574 m_EncodeInfo[i].encode_min = 0;
575 m_EncodeInfo[i].encode_max =
576 m_EncodeInfo[i].sizes == 1 ? 1 : (FX_FLOAT)m_EncodeInfo[i].sizes - 1;
577 }
578 }
579 nTotalSampleBits *= m_nBitsPerSample;
580 nTotalSampleBits *= m_nOutputs;
581 FX_SAFE_UINT32 nTotalSampleBytes = nTotalSampleBits;
582 nTotalSampleBytes += 7;
583 nTotalSampleBytes /= 8;
584 if (!nTotalSampleBytes.IsValid() || nTotalSampleBytes.ValueOrDie() == 0 ||
585 nTotalSampleBytes.ValueOrDie() > m_pSampleStream->GetSize()) {
586 return FALSE;
587 }
588 m_DecodeInfo.resize(m_nOutputs);
589 for (uint32_t i = 0; i < m_nOutputs; i++) {
590 if (pDecode) {
591 m_DecodeInfo[i].decode_min = pDecode->GetFloatAt(2 * i);
592 m_DecodeInfo[i].decode_max = pDecode->GetFloatAt(2 * i + 1);
593 } else {
594 m_DecodeInfo[i].decode_min = m_pRanges[i * 2];
595 m_DecodeInfo[i].decode_max = m_pRanges[i * 2 + 1];
596 }
597 }
598 return TRUE;
599 }
600
v_Call(FX_FLOAT * inputs,FX_FLOAT * results) const601 FX_BOOL CPDF_SampledFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const {
602 int pos = 0;
603 CFX_FixedBufGrow<FX_FLOAT, 16> encoded_input_buf(m_nInputs);
604 FX_FLOAT* encoded_input = encoded_input_buf;
605 CFX_FixedBufGrow<uint32_t, 32> int_buf(m_nInputs * 2);
606 uint32_t* index = int_buf;
607 uint32_t* blocksize = index + m_nInputs;
608 for (uint32_t i = 0; i < m_nInputs; i++) {
609 if (i == 0)
610 blocksize[i] = 1;
611 else
612 blocksize[i] = blocksize[i - 1] * m_EncodeInfo[i - 1].sizes;
613 encoded_input[i] =
614 PDF_Interpolate(inputs[i], m_pDomains[i * 2], m_pDomains[i * 2 + 1],
615 m_EncodeInfo[i].encode_min, m_EncodeInfo[i].encode_max);
616 index[i] = std::min((uint32_t)std::max(0.f, encoded_input[i]),
617 m_EncodeInfo[i].sizes - 1);
618 pos += index[i] * blocksize[i];
619 }
620 FX_SAFE_INT32 bits_to_output = m_nOutputs;
621 bits_to_output *= m_nBitsPerSample;
622 if (!bits_to_output.IsValid())
623 return FALSE;
624
625 FX_SAFE_INT32 bitpos = pos;
626 bitpos *= bits_to_output.ValueOrDie();
627 if (!bitpos.IsValid())
628 return FALSE;
629
630 FX_SAFE_INT32 range_check = bitpos;
631 range_check += bits_to_output.ValueOrDie();
632 if (!range_check.IsValid())
633 return FALSE;
634
635 const uint8_t* pSampleData = m_pSampleStream->GetData();
636 if (!pSampleData)
637 return FALSE;
638
639 for (uint32_t j = 0; j < m_nOutputs; j++) {
640 uint32_t sample =
641 GetBits32(pSampleData, bitpos.ValueOrDie() + j * m_nBitsPerSample,
642 m_nBitsPerSample);
643 FX_FLOAT encoded = (FX_FLOAT)sample;
644 for (uint32_t i = 0; i < m_nInputs; i++) {
645 if (index[i] == m_EncodeInfo[i].sizes - 1) {
646 if (index[i] == 0)
647 encoded = encoded_input[i] * (FX_FLOAT)sample;
648 } else {
649 FX_SAFE_INT32 bitpos2 = blocksize[i];
650 bitpos2 += pos;
651 bitpos2 *= m_nOutputs;
652 bitpos2 += j;
653 bitpos2 *= m_nBitsPerSample;
654 if (!bitpos2.IsValid())
655 return FALSE;
656 uint32_t sample1 =
657 GetBits32(pSampleData, bitpos2.ValueOrDie(), m_nBitsPerSample);
658 encoded += (encoded_input[i] - index[i]) *
659 ((FX_FLOAT)sample1 - (FX_FLOAT)sample);
660 }
661 }
662 results[j] =
663 PDF_Interpolate(encoded, 0, (FX_FLOAT)m_SampleMax,
664 m_DecodeInfo[j].decode_min, m_DecodeInfo[j].decode_max);
665 }
666 return TRUE;
667 }
668
CPDF_ExpIntFunc()669 CPDF_ExpIntFunc::CPDF_ExpIntFunc()
670 : CPDF_Function(Type::kType2ExpotentialInterpolation),
671 m_pBeginValues(nullptr),
672 m_pEndValues(nullptr) {}
673
~CPDF_ExpIntFunc()674 CPDF_ExpIntFunc::~CPDF_ExpIntFunc() {
675 FX_Free(m_pBeginValues);
676 FX_Free(m_pEndValues);
677 }
v_Init(CPDF_Object * pObj)678 FX_BOOL CPDF_ExpIntFunc::v_Init(CPDF_Object* pObj) {
679 CPDF_Dictionary* pDict = pObj->GetDict();
680 if (!pDict) {
681 return FALSE;
682 }
683 CPDF_Array* pArray0 = pDict->GetArrayBy("C0");
684 if (m_nOutputs == 0) {
685 m_nOutputs = 1;
686 if (pArray0) {
687 m_nOutputs = pArray0->GetCount();
688 }
689 }
690 CPDF_Array* pArray1 = pDict->GetArrayBy("C1");
691 m_pBeginValues = FX_Alloc2D(FX_FLOAT, m_nOutputs, 2);
692 m_pEndValues = FX_Alloc2D(FX_FLOAT, m_nOutputs, 2);
693 for (uint32_t i = 0; i < m_nOutputs; i++) {
694 m_pBeginValues[i] = pArray0 ? pArray0->GetFloatAt(i) : 0.0f;
695 m_pEndValues[i] = pArray1 ? pArray1->GetFloatAt(i) : 1.0f;
696 }
697 m_Exponent = pDict->GetFloatBy("N");
698 m_nOrigOutputs = m_nOutputs;
699 if (m_nOutputs && m_nInputs > INT_MAX / m_nOutputs) {
700 return FALSE;
701 }
702 m_nOutputs *= m_nInputs;
703 return TRUE;
704 }
v_Call(FX_FLOAT * inputs,FX_FLOAT * results) const705 FX_BOOL CPDF_ExpIntFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const {
706 for (uint32_t i = 0; i < m_nInputs; i++)
707 for (uint32_t j = 0; j < m_nOrigOutputs; j++) {
708 results[i * m_nOrigOutputs + j] =
709 m_pBeginValues[j] +
710 (FX_FLOAT)FXSYS_pow(inputs[i], m_Exponent) *
711 (m_pEndValues[j] - m_pBeginValues[j]);
712 }
713 return TRUE;
714 }
715
CPDF_StitchFunc()716 CPDF_StitchFunc::CPDF_StitchFunc()
717 : CPDF_Function(Type::kType3Stitching),
718 m_pBounds(nullptr),
719 m_pEncode(nullptr) {}
720
~CPDF_StitchFunc()721 CPDF_StitchFunc::~CPDF_StitchFunc() {
722 FX_Free(m_pBounds);
723 FX_Free(m_pEncode);
724 }
725
v_Init(CPDF_Object * pObj)726 FX_BOOL CPDF_StitchFunc::v_Init(CPDF_Object* pObj) {
727 CPDF_Dictionary* pDict = pObj->GetDict();
728 if (!pDict) {
729 return FALSE;
730 }
731 if (m_nInputs != kRequiredNumInputs) {
732 return FALSE;
733 }
734 CPDF_Array* pArray = pDict->GetArrayBy("Functions");
735 if (!pArray) {
736 return FALSE;
737 }
738 uint32_t nSubs = pArray->GetCount();
739 if (nSubs == 0)
740 return FALSE;
741 m_nOutputs = 0;
742 for (uint32_t i = 0; i < nSubs; i++) {
743 CPDF_Object* pSub = pArray->GetDirectObjectAt(i);
744 if (pSub == pObj)
745 return FALSE;
746 std::unique_ptr<CPDF_Function> pFunc(CPDF_Function::Load(pSub));
747 if (!pFunc)
748 return FALSE;
749 // Check that the input dimensionality is 1, and that all output
750 // dimensionalities are the same.
751 if (pFunc->CountInputs() != kRequiredNumInputs)
752 return FALSE;
753 if (pFunc->CountOutputs() != m_nOutputs) {
754 if (m_nOutputs)
755 return FALSE;
756
757 m_nOutputs = pFunc->CountOutputs();
758 }
759
760 m_pSubFunctions.push_back(std::move(pFunc));
761 }
762 m_pBounds = FX_Alloc(FX_FLOAT, nSubs + 1);
763 m_pBounds[0] = m_pDomains[0];
764 pArray = pDict->GetArrayBy("Bounds");
765 if (!pArray)
766 return FALSE;
767 for (uint32_t i = 0; i < nSubs - 1; i++)
768 m_pBounds[i + 1] = pArray->GetFloatAt(i);
769 m_pBounds[nSubs] = m_pDomains[1];
770 m_pEncode = FX_Alloc2D(FX_FLOAT, nSubs, 2);
771 pArray = pDict->GetArrayBy("Encode");
772 if (!pArray)
773 return FALSE;
774
775 for (uint32_t i = 0; i < nSubs * 2; i++)
776 m_pEncode[i] = pArray->GetFloatAt(i);
777 return TRUE;
778 }
779
v_Call(FX_FLOAT * inputs,FX_FLOAT * outputs) const780 FX_BOOL CPDF_StitchFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* outputs) const {
781 FX_FLOAT input = inputs[0];
782 size_t i;
783 for (i = 0; i < m_pSubFunctions.size() - 1; i++) {
784 if (input < m_pBounds[i + 1])
785 break;
786 }
787 input = PDF_Interpolate(input, m_pBounds[i], m_pBounds[i + 1],
788 m_pEncode[i * 2], m_pEncode[i * 2 + 1]);
789 int nresults;
790 m_pSubFunctions[i]->Call(&input, kRequiredNumInputs, outputs, nresults);
791 return TRUE;
792 }
793
794 // static
Load(CPDF_Object * pFuncObj)795 std::unique_ptr<CPDF_Function> CPDF_Function::Load(CPDF_Object* pFuncObj) {
796 std::unique_ptr<CPDF_Function> pFunc;
797 if (!pFuncObj)
798 return pFunc;
799
800 int iType = -1;
801 if (CPDF_Stream* pStream = pFuncObj->AsStream())
802 iType = pStream->GetDict()->GetIntegerBy("FunctionType");
803 else if (CPDF_Dictionary* pDict = pFuncObj->AsDictionary())
804 iType = pDict->GetIntegerBy("FunctionType");
805
806 Type type = IntegerToFunctionType(iType);
807 if (type == Type::kType0Sampled)
808 pFunc.reset(new CPDF_SampledFunc());
809 else if (type == Type::kType2ExpotentialInterpolation)
810 pFunc.reset(new CPDF_ExpIntFunc());
811 else if (type == Type::kType3Stitching)
812 pFunc.reset(new CPDF_StitchFunc());
813 else if (type == Type::kType4PostScript)
814 pFunc.reset(new CPDF_PSFunc());
815
816 if (!pFunc || !pFunc->Init(pFuncObj))
817 return std::unique_ptr<CPDF_Function>();
818 return pFunc;
819 }
820
821 // static
IntegerToFunctionType(int iType)822 CPDF_Function::Type CPDF_Function::IntegerToFunctionType(int iType) {
823 switch (iType) {
824 case 0:
825 case 2:
826 case 3:
827 case 4:
828 return static_cast<Type>(iType);
829 default:
830 return Type::kTypeInvalid;
831 }
832 }
833
CPDF_Function(Type type)834 CPDF_Function::CPDF_Function(Type type)
835 : m_pDomains(nullptr), m_pRanges(nullptr), m_Type(type) {}
836
~CPDF_Function()837 CPDF_Function::~CPDF_Function() {
838 FX_Free(m_pDomains);
839 FX_Free(m_pRanges);
840 }
841
Init(CPDF_Object * pObj)842 FX_BOOL CPDF_Function::Init(CPDF_Object* pObj) {
843 CPDF_Stream* pStream = pObj->AsStream();
844 CPDF_Dictionary* pDict = pStream ? pStream->GetDict() : pObj->AsDictionary();
845
846 CPDF_Array* pDomains = pDict->GetArrayBy("Domain");
847 if (!pDomains)
848 return FALSE;
849
850 m_nInputs = pDomains->GetCount() / 2;
851 if (m_nInputs == 0)
852 return FALSE;
853
854 m_pDomains = FX_Alloc2D(FX_FLOAT, m_nInputs, 2);
855 for (uint32_t i = 0; i < m_nInputs * 2; i++) {
856 m_pDomains[i] = pDomains->GetFloatAt(i);
857 }
858 CPDF_Array* pRanges = pDict->GetArrayBy("Range");
859 m_nOutputs = 0;
860 if (pRanges) {
861 m_nOutputs = pRanges->GetCount() / 2;
862 m_pRanges = FX_Alloc2D(FX_FLOAT, m_nOutputs, 2);
863 for (uint32_t i = 0; i < m_nOutputs * 2; i++)
864 m_pRanges[i] = pRanges->GetFloatAt(i);
865 }
866 uint32_t old_outputs = m_nOutputs;
867 if (!v_Init(pObj))
868 return FALSE;
869 if (m_pRanges && m_nOutputs > old_outputs) {
870 m_pRanges = FX_Realloc(FX_FLOAT, m_pRanges, m_nOutputs * 2);
871 if (m_pRanges) {
872 FXSYS_memset(m_pRanges + (old_outputs * 2), 0,
873 sizeof(FX_FLOAT) * (m_nOutputs - old_outputs) * 2);
874 }
875 }
876 return TRUE;
877 }
878
Call(FX_FLOAT * inputs,uint32_t ninputs,FX_FLOAT * results,int & nresults) const879 FX_BOOL CPDF_Function::Call(FX_FLOAT* inputs,
880 uint32_t ninputs,
881 FX_FLOAT* results,
882 int& nresults) const {
883 if (m_nInputs != ninputs) {
884 return FALSE;
885 }
886 nresults = m_nOutputs;
887 for (uint32_t i = 0; i < m_nInputs; i++) {
888 if (inputs[i] < m_pDomains[i * 2])
889 inputs[i] = m_pDomains[i * 2];
890 else if (inputs[i] > m_pDomains[i * 2 + 1])
891 inputs[i] = m_pDomains[i * 2] + 1;
892 }
893 v_Call(inputs, results);
894 if (m_pRanges) {
895 for (uint32_t i = 0; i < m_nOutputs; i++) {
896 if (results[i] < m_pRanges[i * 2])
897 results[i] = m_pRanges[i * 2];
898 else if (results[i] > m_pRanges[i * 2 + 1])
899 results[i] = m_pRanges[i * 2 + 1];
900 }
901 }
902 return TRUE;
903 }
904
ToSampledFunc() const905 const CPDF_SampledFunc* CPDF_Function::ToSampledFunc() const {
906 return m_Type == Type::kType0Sampled
907 ? static_cast<const CPDF_SampledFunc*>(this)
908 : nullptr;
909 }
910
ToExpIntFunc() const911 const CPDF_ExpIntFunc* CPDF_Function::ToExpIntFunc() const {
912 return m_Type == Type::kType2ExpotentialInterpolation
913 ? static_cast<const CPDF_ExpIntFunc*>(this)
914 : nullptr;
915 }
916
ToStitchFunc() const917 const CPDF_StitchFunc* CPDF_Function::ToStitchFunc() const {
918 return m_Type == Type::kType3Stitching
919 ? static_cast<const CPDF_StitchFunc*>(this)
920 : nullptr;
921 }
922