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