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