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 |