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