Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: core/src/fpdfapi/fpdf_page/fpdf_page_func.cpp

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

Powered by Google App Engine
This is Rietveld 408576698