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