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