1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "../../../include/fpdfapi/fpdf_page.h" 8 #include "../../../include/fpdfapi/fpdf_module.h" 9 #include "pageint.h" 10 #include <limits.h> 11 class CPDF_PSEngine; 12 typedef enum {PSOP_ADD, PSOP_SUB, PSOP_MUL, PSOP_DIV, PSOP_IDIV, PSOP_MOD, 13 PSOP_NEG, PSOP_ABS, PSOP_CEILING, PSOP_FLOOR, PSOP_ROUND, PSOP_TRUNCATE, 14 PSOP_SQRT, PSOP_SIN, PSOP_COS, PSOP_ATAN, PSOP_EXP, PSOP_LN, PSOP_LOG, 15 PSOP_CVI, PSOP_CVR, PSOP_EQ, PSOP_NE, PSOP_GT, PSOP_GE, PSOP_LT, PSOP_LE, 16 PSOP_AND, PSOP_OR, PSOP_XOR, PSOP_NOT, PSOP_BITSHIFT, PSOP_TRUE, PSOP_FALSE, 17 PSOP_IF, PSOP_IFELSE, PSOP_POP, PSOP_EXCH, PSOP_DUP, PSOP_COPY, 18 PSOP_INDEX, PSOP_ROLL, PSOP_PROC, PSOP_CONST 19 } PDF_PSOP; 20 class CPDF_PSProc : public CFX_Object 21 { 22 public: 23 ~CPDF_PSProc(); 24 FX_BOOL Parse(CPDF_SimpleParser& parser); 25 FX_BOOL Execute(CPDF_PSEngine* pEngine); 26 CFX_PtrArray m_Operators; 27 }; 28 #define PSENGINE_STACKSIZE 100 29 class CPDF_PSEngine : public CFX_Object 30 { 31 public: 32 CPDF_PSEngine(); 33 ~CPDF_PSEngine(); 34 FX_BOOL Parse(const FX_CHAR* string, int size); 35 FX_BOOL Execute() 36 { 37 return m_MainProc.Execute(this); 38 } 39 FX_BOOL DoOperator(PDF_PSOP op); 40 void Reset() 41 { 42 m_StackCount = 0; 43 } 44 void Push(FX_FLOAT value); 45 void Push(int value) 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 }; 59 CPDF_PSProc::~CPDF_PSProc() 60 { 61 int size = m_Operators.GetSize(); 62 for (int i = 0; i < size; i ++) { 63 if (m_Operators[i] == (FX_LPVOID)PSOP_PROC) { 64 delete (CPDF_PSProc*)m_Operators[i + 1]; 65 i ++; 66 } else if (m_Operators[i] == (FX_LPVOID)PSOP_CONST) { 67 FX_Free((FX_FLOAT*)m_Operators[i + 1]); 68 i ++; 69 } 70 } 71 } 72 #pragma optimize( "", off ) 73 FX_BOOL CPDF_PSProc::Execute(CPDF_PSEngine* pEngine) 74 { 75 int size = m_Operators.GetSize(); 76 for (int i = 0; i < size; i ++) { 77 PDF_PSOP op = (PDF_PSOP)(FX_UINTPTR)m_Operators[i]; 78 if (op == PSOP_PROC) { 79 i ++; 80 } else if (op == PSOP_CONST) { 81 pEngine->Push(*(FX_FLOAT*)m_Operators[i + 1]); 82 i ++; 83 } else if (op == PSOP_IF) { 84 if (i < 2 || m_Operators[i - 2] != (FX_LPVOID)PSOP_PROC) { 85 return FALSE; 86 } 87 if ((int)pEngine->Pop()) { 88 ((CPDF_PSProc*)m_Operators[i - 1])->Execute(pEngine); 89 } 90 } else if (op == PSOP_IFELSE) { 91 if (i < 4 || m_Operators[i - 2] != (FX_LPVOID)PSOP_PROC || 92 m_Operators[i - 4] != (FX_LPVOID)PSOP_PROC) { 93 return FALSE; 94 } 95 if ((int)pEngine->Pop()) { 96 ((CPDF_PSProc*)m_Operators[i - 3])->Execute(pEngine); 97 } else { 98 ((CPDF_PSProc*)m_Operators[i - 1])->Execute(pEngine); 99 } 100 } else { 101 pEngine->DoOperator(op); 102 } 103 } 104 return TRUE; 105 } 106 #pragma optimize( "", on ) 107 CPDF_PSEngine::CPDF_PSEngine() 108 { 109 m_StackCount = 0; 110 } 111 CPDF_PSEngine::~CPDF_PSEngine() 112 { 113 } 114 void CPDF_PSEngine::Push(FX_FLOAT v) 115 { 116 if (m_StackCount == 100) { 117 return; 118 } 119 m_Stack[m_StackCount++] = v; 120 } 121 FX_FLOAT CPDF_PSEngine::Pop() 122 { 123 if (m_StackCount == 0) { 124 return 0; 125 } 126 return m_Stack[--m_StackCount]; 127 } 128 const struct _PDF_PSOpName { 129 const FX_CHAR* name; 130 PDF_PSOP op; 131 } _PDF_PSOpNames[] = { 132 {"add", PSOP_ADD}, {"sub", PSOP_SUB}, {"mul", PSOP_MUL}, {"div", PSOP_DIV}, 133 {"idiv", PSOP_IDIV}, {"mod", PSOP_MOD}, {"neg", PSOP_NEG}, {"abs", PSOP_ABS}, 134 {"ceiling", PSOP_CEILING}, {"floor", PSOP_FLOOR}, {"round", PSOP_ROUND}, 135 {"truncate", PSOP_TRUNCATE}, {"sqrt", PSOP_SQRT}, {"sin", PSOP_SIN}, 136 {"cos", PSOP_COS}, {"atan", PSOP_ATAN}, {"exp", PSOP_EXP}, {"ln", PSOP_LN}, 137 {"log", PSOP_LOG}, {"cvi", PSOP_CVI}, {"cvr", PSOP_CVR}, {"eq", PSOP_EQ}, 138 {"ne", PSOP_NE}, {"gt", PSOP_GT}, {"ge", PSOP_GE}, {"lt", PSOP_LT}, 139 {"le", PSOP_LE}, {"and", PSOP_AND}, {"or", PSOP_OR}, {"xor", PSOP_XOR}, 140 {"not", PSOP_NOT}, {"bitshift", PSOP_BITSHIFT}, {"true", PSOP_TRUE}, 141 {"false", PSOP_FALSE}, {"if", PSOP_IF}, {"ifelse", PSOP_IFELSE}, 142 {"pop", PSOP_POP}, {"exch", PSOP_EXCH}, {"dup", PSOP_DUP}, 143 {"copy", PSOP_COPY}, {"index", PSOP_INDEX}, {"roll", PSOP_ROLL}, 144 {NULL, PSOP_PROC} 145 }; 146 FX_BOOL CPDF_PSEngine::Parse(const FX_CHAR* string, int size) 147 { 148 CPDF_SimpleParser parser((FX_LPBYTE)string, size); 149 CFX_ByteStringC word = parser.GetWord(); 150 if (word != FX_BSTRC("{")) { 151 return FALSE; 152 } 153 return m_MainProc.Parse(parser); 154 } 155 FX_BOOL CPDF_PSProc::Parse(CPDF_SimpleParser& parser) 156 { 157 while (1) { 158 CFX_ByteStringC word = parser.GetWord(); 159 if (word.IsEmpty()) { 160 return FALSE; 161 } 162 if (word == FX_BSTRC("}")) { 163 return TRUE; 164 } 165 if (word == FX_BSTRC("{")) { 166 CPDF_PSProc* pProc = FX_NEW CPDF_PSProc; 167 m_Operators.Add((FX_LPVOID)PSOP_PROC); 168 m_Operators.Add(pProc); 169 if (!pProc->Parse(parser)) { 170 return FALSE; 171 } 172 } else { 173 int i = 0; 174 while (_PDF_PSOpNames[i].name) { 175 if (word == CFX_ByteStringC(_PDF_PSOpNames[i].name)) { 176 m_Operators.Add((FX_LPVOID)_PDF_PSOpNames[i].op); 177 break; 178 } 179 i ++; 180 } 181 if (_PDF_PSOpNames[i].name == NULL) { 182 FX_FLOAT* pd = FX_Alloc(FX_FLOAT, 1); 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 > PSENGINE_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_StackCount - 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_StackCount - 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_FLOAT 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) const; 448 SampleEncodeInfo* m_pEncodeInfo; 449 SampleDecodeInfo* m_pDecodeInfo; 450 FX_DWORD m_nBitsPerSample, m_SampleMax; 451 CPDF_StreamAcc* m_pSampleStream; 452 }; 453 CPDF_SampledFunc::CPDF_SampledFunc() 454 { 455 m_pSampleStream = NULL; 456 m_pEncodeInfo = NULL; 457 m_pDecodeInfo = NULL; 458 } 459 CPDF_SampledFunc::~CPDF_SampledFunc() 460 { 461 if (m_pSampleStream) { 462 delete m_pSampleStream; 463 } 464 if (m_pEncodeInfo) { 465 FX_Free(m_pEncodeInfo); 466 } 467 if (m_pDecodeInfo) { 468 FX_Free(m_pDecodeInfo); 469 } 470 } 471 FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj) 472 { 473 if (pObj->GetType() != PDFOBJ_STREAM) { 474 return FALSE; 475 } 476 CPDF_Stream* pStream = (CPDF_Stream*)pObj; 477 CPDF_Dictionary* pDict = pStream->GetDict(); 478 CPDF_Array* pSize = pDict->GetArray(FX_BSTRC("Size")); 479 CPDF_Array* pEncode = pDict->GetArray(FX_BSTRC("Encode")); 480 CPDF_Array* pDecode = pDict->GetArray(FX_BSTRC("Decode")); 481 m_nBitsPerSample = pDict->GetInteger(FX_BSTRC("BitsPerSample")); 482 m_SampleMax = 0xffffffff >> (32 - m_nBitsPerSample); 483 m_pSampleStream = FX_NEW CPDF_StreamAcc; 484 m_pSampleStream->LoadAllData(pStream, FALSE); 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->GetInteger(i); 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_pDomains[i * 2 + 1], 547 m_pEncodeInfo[i].encode_min, m_pEncodeInfo[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_nBitsPerSample, 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) const; 585 CPDF_PSEngine m_PS; 586 }; 587 FX_BOOL CPDF_PSFunc::v_Init(CPDF_Object* pObj) 588 { 589 CPDF_Stream* pStream = (CPDF_Stream*)pObj; 590 CPDF_StreamAcc acc; 591 acc.LoadAllData(pStream, FALSE); 592 return m_PS.Parse((const FX_CHAR*)acc.GetData(), acc.GetSize()); 593 } 594 FX_BOOL CPDF_PSFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const 595 { 596 CPDF_PSEngine& PS = (CPDF_PSEngine&)m_PS; 597 PS.Reset(); 598 int i; 599 for (i = 0; i < m_nInputs; i ++) { 600 PS.Push(inputs[i]); 601 } 602 PS.Execute(); 603 if (PS.GetStackSize() < m_nOutputs) { 604 return FALSE; 605 } 606 for (i = 0; i < m_nOutputs; i ++) { 607 results[m_nOutputs - i - 1] = PS.Pop(); 608 } 609 return TRUE; 610 } 611 class CPDF_ExpIntFunc : public CPDF_Function 612 { 613 public: 614 CPDF_ExpIntFunc(); 615 virtual ~CPDF_ExpIntFunc(); 616 virtual FX_BOOL v_Init(CPDF_Object* pObj); 617 virtual FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const; 618 FX_FLOAT m_Exponent; 619 FX_FLOAT* m_pBeginValues; 620 FX_FLOAT* m_pEndValues; 621 int m_nOrigOutputs; 622 }; 623 CPDF_ExpIntFunc::CPDF_ExpIntFunc() 624 { 625 m_pBeginValues = NULL; 626 m_pEndValues = NULL; 627 } 628 CPDF_ExpIntFunc::~CPDF_ExpIntFunc() 629 { 630 if (m_pBeginValues) { 631 FX_Free(m_pBeginValues); 632 } 633 if (m_pEndValues) { 634 FX_Free(m_pEndValues); 635 } 636 } 637 FX_BOOL CPDF_ExpIntFunc::v_Init(CPDF_Object* pObj) 638 { 639 CPDF_Dictionary* pDict = pObj->GetDict(); 640 if (pDict == NULL) { 641 return FALSE; 642 } 643 CPDF_Array* pArray0 = pDict->GetArray(FX_BSTRC("C0")); 644 if (m_nOutputs == 0) { 645 m_nOutputs = 1; 646 if (pArray0) { 647 m_nOutputs = pArray0->GetCount(); 648 } 649 } 650 CPDF_Array* pArray1 = pDict->GetArray(FX_BSTRC("C1")); 651 m_pBeginValues = FX_Alloc(FX_FLOAT, m_nOutputs * 2); 652 m_pEndValues = FX_Alloc(FX_FLOAT, m_nOutputs * 2); 653 for (int i = 0; i < m_nOutputs; i ++) { 654 m_pBeginValues[i] = pArray0 ? pArray0->GetFloat(i) : 0.0f; 655 m_pEndValues[i] = pArray1 ? pArray1->GetFloat(i) : 1.0f; 656 } 657 m_Exponent = pDict->GetFloat(FX_BSTRC("N")); 658 m_nOrigOutputs = m_nOutputs; 659 if (m_nOutputs && m_nInputs > INT_MAX / m_nOutputs) { 660 return FALSE; 661 } 662 m_nOutputs *= m_nInputs; 663 return TRUE; 664 } 665 FX_BOOL CPDF_ExpIntFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const 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)FXSYS_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) const; 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 FXSYS_memset32(m_pSubFunctions, 0, sizeof(CPDF_Function*)*m_nSubs); 725 m_nOutputs = 0; 726 int i; 727 for (i = 0; i < m_nSubs; i ++) { 728 CPDF_Object* pSub = pArray->GetElementValue(i); 729 if (pSub == pObj) { 730 return FALSE; 731 } 732 m_pSubFunctions[i] = CPDF_Function::Load(pSub); 733 if (m_pSubFunctions[i] == NULL) { 734 return FALSE; 735 } 736 if (m_pSubFunctions[i]->CountOutputs() > m_nOutputs) { 737 m_nOutputs = m_pSubFunctions[i]->CountOutputs(); 738 } 739 } 740 m_pBounds = FX_Alloc(FX_FLOAT, m_nSubs + 1); 741 m_pBounds[0] = m_pDomains[0]; 742 pArray = pDict->GetArray(FX_BSTRC("Bounds")); 743 if (pArray == NULL) { 744 return FALSE; 745 } 746 for (i = 0; i < m_nSubs - 1; i ++) { 747 m_pBounds[i + 1] = pArray->GetFloat(i); 748 } 749 m_pBounds[m_nSubs] = m_pDomains[1]; 750 m_pEncode = FX_Alloc(FX_FLOAT, m_nSubs * 2); 751 pArray = pDict->GetArray(FX_BSTRC("Encode")); 752 if (pArray == NULL) { 753 return FALSE; 754 } 755 for (i = 0; i < m_nSubs * 2; i ++) { 756 m_pEncode[i] = pArray->GetFloat(i); 757 } 758 return TRUE; 759 } 760 FX_BOOL CPDF_StitchFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* outputs) const 761 { 762 FX_FLOAT input = inputs[0]; 763 int i; 764 for (i = 0; i < m_nSubs - 1; i ++) 765 if (input < m_pBounds[i + 1]) { 766 break; 767 } 768 if (m_pSubFunctions[i] == NULL) { 769 return FALSE; 770 } 771 input = PDF_Interpolate(input, m_pBounds[i], m_pBounds[i + 1], m_pEncode[i * 2], m_pEncode[i * 2 + 1]); 772 int nresults; 773 m_pSubFunctions[i]->Call(&input, m_nInputs, outputs, nresults); 774 return TRUE; 775 } 776 CPDF_Function* CPDF_Function::Load(CPDF_Object* pFuncObj) 777 { 778 if (pFuncObj == NULL) { 779 return NULL; 780 } 781 CPDF_Function* pFunc = NULL; 782 int type; 783 if (pFuncObj->GetType() == PDFOBJ_STREAM) { 784 type = ((CPDF_Stream*)pFuncObj)->GetDict()->GetInteger(FX_BSTRC("FunctionType")); 785 } else if (pFuncObj->GetType() == PDFOBJ_DICTIONARY) { 786 type = ((CPDF_Dictionary*)pFuncObj)->GetInteger(FX_BSTRC("FunctionType")); 787 } else { 788 return NULL; 789 } 790 if (type == 0) { 791 pFunc = FX_NEW CPDF_SampledFunc; 792 } else if (type == 2) { 793 pFunc = FX_NEW CPDF_ExpIntFunc; 794 } else if (type == 3) { 795 pFunc = FX_NEW CPDF_StitchFunc; 796 } else if (type == 4) { 797 pFunc = FX_NEW CPDF_PSFunc; 798 } else { 799 return NULL; 800 } 801 if (!pFunc->Init(pFuncObj)) { 802 delete pFunc; 803 return NULL; 804 } 805 return pFunc; 806 } 807 CPDF_Function::CPDF_Function() 808 { 809 m_pDomains = NULL; 810 m_pRanges = NULL; 811 } 812 CPDF_Function::~CPDF_Function() 813 { 814 if (m_pDomains) { 815 FX_Free(m_pDomains); 816 m_pDomains = NULL; 817 } 818 if (m_pRanges) { 819 FX_Free(m_pRanges); 820 m_pRanges = NULL; 821 } 822 } 823 FX_BOOL CPDF_Function::Init(CPDF_Object* pObj) 824 { 825 CPDF_Dictionary* pDict; 826 if (pObj->GetType() == PDFOBJ_STREAM) { 827 pDict = ((CPDF_Stream*)pObj)->GetDict(); 828 } else { 829 pDict = (CPDF_Dictionary*)pObj; 830 } 831 CPDF_Array* pDomains = pDict->GetArray(FX_BSTRC("Domain")); 832 if (pDomains == NULL) { 833 return FALSE; 834 } 835 m_nInputs = pDomains->GetCount() / 2; 836 if (m_nInputs == 0) { 837 return FALSE; 838 } 839 m_pDomains = FX_Alloc(FX_FLOAT, m_nInputs * 2); 840 for (int i = 0; i < m_nInputs * 2; i ++) { 841 m_pDomains[i] = pDomains->GetFloat(i); 842 } 843 CPDF_Array* pRanges = pDict->GetArray(FX_BSTRC("Range")); 844 m_nOutputs = 0; 845 if (pRanges) { 846 m_nOutputs = pRanges->GetCount() / 2; 847 m_pRanges = FX_Alloc(FX_FLOAT, m_nOutputs * 2); 848 for (int i = 0; i < m_nOutputs * 2; i ++) { 849 m_pRanges[i] = pRanges->GetFloat(i); 850 } 851 } 852 FX_DWORD old_outputs = m_nOutputs; 853 FX_BOOL ret = v_Init(pObj); 854 if (m_pRanges && m_nOutputs > (int)old_outputs) { 855 m_pRanges = FX_Realloc(FX_FLOAT, m_pRanges, m_nOutputs * 2); 856 if (m_pRanges) { 857 FXSYS_memset32(m_pRanges + (old_outputs * 2), 0, sizeof(FX_FLOAT) * (m_nOutputs - old_outputs) * 2); 858 } 859 } 860 return ret; 861 } 862 FX_BOOL CPDF_Function::Call(FX_FLOAT* inputs, int ninputs, FX_FLOAT* results, int& nresults) const 863 { 864 if (m_nInputs != ninputs) { 865 return FALSE; 866 } 867 nresults = m_nOutputs; 868 for (int i = 0; i < m_nInputs; i ++) { 869 if (inputs[i] < m_pDomains[i * 2]) { 870 inputs[i] = m_pDomains[i * 2]; 871 } else if (inputs[i] > m_pDomains[i * 2 + 1]) { 872 inputs[i] = m_pDomains[i * 2] + 1; 873 } 874 } 875 v_Call(inputs, results); 876 if (m_pRanges) { 877 for (int i = 0; i < m_nOutputs; i ++) { 878 if (results[i] < m_pRanges[i * 2]) { 879 results[i] = m_pRanges[i * 2]; 880 } else if (results[i] > m_pRanges[i * 2 + 1]) { 881 results[i] = m_pRanges[i * 2 + 1]; 882 } 883 } 884 } 885 return TRUE; 886 } 887