Home | History | Annotate | Download | only in page
      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.
     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.
     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:
     84   CPDF_PSFunc() : CPDF_Function(Type::kType4PostScript) {}
     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 
     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 
    102 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:
    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   }
    123   explicit CPDF_PSOP(FX_FLOAT value) : m_op(PSOP_CONST), m_value(value) {}
    124   explicit CPDF_PSOP(std::unique_ptr<CPDF_PSProc> proc)
    125       : m_op(PSOP_PROC), m_value(0), m_proc(std::move(proc)) {}
    126 
    127   FX_FLOAT GetFloatValue() const {
    128     if (m_op == PSOP_CONST)
    129       return m_value;
    130 
    131     ASSERT(false);
    132     return 0;
    133   }
    134   CPDF_PSProc* GetProc() const {
    135     if (m_op == PSOP_PROC)
    136       return m_proc.get();
    137     ASSERT(false);
    138     return nullptr;
    139   }
    140 
    141   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 
    149 bool CPDF_PSEngine::Execute() {
    150   return m_MainProc.Execute(this);
    151 }
    152 
    153 CPDF_PSProc::CPDF_PSProc() {}
    154 CPDF_PSProc::~CPDF_PSProc() {}
    155 
    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 
    187 CPDF_PSEngine::CPDF_PSEngine() {
    188   m_StackCount = 0;
    189 }
    190 CPDF_PSEngine::~CPDF_PSEngine() {}
    191 void CPDF_PSEngine::Push(FX_FLOAT v) {
    192   if (m_StackCount == PSENGINE_STACKSIZE) {
    193     return;
    194   }
    195   m_Stack[m_StackCount++] = v;
    196 }
    197 FX_FLOAT CPDF_PSEngine::Pop() {
    198   if (m_StackCount == 0) {
    199     return 0;
    200   }
    201   return m_Stack[--m_StackCount];
    202 }
    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 
    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 
    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 
    484 CPDF_SampledFunc::CPDF_SampledFunc() : CPDF_Function(Type::kType0Sampled) {}
    485 
    486 CPDF_SampledFunc::~CPDF_SampledFunc() {}
    487 
    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 
    542 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 
    609 CPDF_ExpIntFunc::CPDF_ExpIntFunc()
    610     : CPDF_Function(Type::kType2ExpotentialInterpolation),
    611       m_pBeginValues(nullptr),
    612       m_pEndValues(nullptr) {}
    613 
    614 CPDF_ExpIntFunc::~CPDF_ExpIntFunc() {
    615   FX_Free(m_pBeginValues);
    616   FX_Free(m_pEndValues);
    617 }
    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 }
    645 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 
    656 CPDF_StitchFunc::CPDF_StitchFunc()
    657     : CPDF_Function(Type::kType3Stitching),
    658       m_pBounds(nullptr),
    659       m_pEncode(nullptr) {}
    660 
    661 CPDF_StitchFunc::~CPDF_StitchFunc() {
    662   FX_Free(m_pBounds);
    663   FX_Free(m_pEncode);
    664 }
    665 
    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 
    720 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
    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
    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 
    775 CPDF_Function::CPDF_Function(Type type)
    776     : m_pDomains(nullptr), m_pRanges(nullptr), m_Type(type) {}
    777 
    778 CPDF_Function::~CPDF_Function() {
    779   FX_Free(m_pDomains);
    780   FX_Free(m_pRanges);
    781 }
    782 
    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 
    820 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 
    846 const CPDF_SampledFunc* CPDF_Function::ToSampledFunc() const {
    847   return m_Type == Type::kType0Sampled
    848              ? static_cast<const CPDF_SampledFunc*>(this)
    849              : nullptr;
    850 }
    851 
    852 const CPDF_ExpIntFunc* CPDF_Function::ToExpIntFunc() const {
    853   return m_Type == Type::kType2ExpotentialInterpolation
    854              ? static_cast<const CPDF_ExpIntFunc*>(this)
    855              : nullptr;
    856 }
    857 
    858 const CPDF_StitchFunc* CPDF_Function::ToStitchFunc() const {
    859   return m_Type == Type::kType3Stitching
    860              ? static_cast<const CPDF_StitchFunc*>(this)
    861              : nullptr;
    862 }
    863