Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/source/pdf/pdf-function.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 // Copyright (C) 2004-2025 Artifex Software, Inc. | |
| 2 // | |
| 3 // This file is part of MuPDF. | |
| 4 // | |
| 5 // MuPDF is free software: you can redistribute it and/or modify it under the | |
| 6 // terms of the GNU Affero General Public License as published by the Free | |
| 7 // Software Foundation, either version 3 of the License, or (at your option) | |
| 8 // any later version. | |
| 9 // | |
| 10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY | |
| 11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
| 12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more | |
| 13 // details. | |
| 14 // | |
| 15 // You should have received a copy of the GNU Affero General Public License | |
| 16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> | |
| 17 // | |
| 18 // Alternative licensing terms are available from the licensor. | |
| 19 // For commercial licensing, see <https://www.artifex.com/> or contact | |
| 20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, | |
| 21 // CA 94129, USA, for further information. | |
| 22 | |
| 23 #include "mupdf/fitz.h" | |
| 24 #include "mupdf/pdf.h" | |
| 25 | |
| 26 #include <string.h> | |
| 27 #include <math.h> | |
| 28 #include <float.h> | |
| 29 #include <limits.h> | |
| 30 | |
| 31 static pdf_function *pdf_load_function_imp(fz_context *ctx, pdf_obj *dict, int in, int out, pdf_cycle_list *cycle); | |
| 32 | |
| 33 #define DIV_BY_ZERO(a, b, min, max) (((a) < 0) ^ ((b) < 0) ? (min) : (max)) | |
| 34 | |
| 35 enum | |
| 36 { | |
| 37 MAX_N = FZ_MAX_COLORS, | |
| 38 MAX_M = FZ_MAX_COLORS | |
| 39 }; | |
| 40 | |
| 41 enum | |
| 42 { | |
| 43 SAMPLE = 0, | |
| 44 EXPONENTIAL = 2, | |
| 45 STITCHING = 3, | |
| 46 POSTSCRIPT = 4 | |
| 47 }; | |
| 48 | |
| 49 typedef struct | |
| 50 { | |
| 51 int type; | |
| 52 union | |
| 53 { | |
| 54 int b; /* boolean (stack only) */ | |
| 55 int i; /* integer (stack and code) */ | |
| 56 float f; /* real (stack and code) */ | |
| 57 int op; /* operator (code only) */ | |
| 58 int block; /* if/ifelse block pointer (code only) */ | |
| 59 } u; | |
| 60 } psobj; | |
| 61 | |
| 62 struct pdf_function | |
| 63 { | |
| 64 fz_function super; | |
| 65 | |
| 66 float domain[MAX_M][2]; /* even index : min value, odd index : max value */ | |
| 67 float range[MAX_N][2]; /* even index : min value, odd index : max value */ | |
| 68 int has_range; | |
| 69 }; | |
| 70 | |
| 71 typedef struct | |
| 72 { | |
| 73 pdf_function super; | |
| 74 | |
| 75 unsigned short bps; | |
| 76 int size[MAX_M]; | |
| 77 float encode[MAX_M][2]; | |
| 78 float decode[MAX_N][2]; | |
| 79 float *samples; | |
| 80 } pdf_function_sa; | |
| 81 | |
| 82 typedef struct | |
| 83 { | |
| 84 pdf_function super; | |
| 85 | |
| 86 float n; | |
| 87 float c0[MAX_N]; | |
| 88 float c1[MAX_N]; | |
| 89 } pdf_function_e; | |
| 90 | |
| 91 typedef struct | |
| 92 { | |
| 93 pdf_function super; | |
| 94 | |
| 95 int k; | |
| 96 pdf_function **funcs; /* k */ | |
| 97 float *bounds; /* k - 1 */ | |
| 98 float *encode; /* k * 2 */ | |
| 99 } pdf_function_st; | |
| 100 | |
| 101 typedef struct | |
| 102 { | |
| 103 pdf_function super; | |
| 104 | |
| 105 psobj *code; | |
| 106 int cap; | |
| 107 } pdf_function_p; | |
| 108 | |
| 109 pdf_function * | |
| 110 pdf_keep_function(fz_context *ctx, pdf_function *func) | |
| 111 { | |
| 112 return (pdf_function *)fz_keep_function(ctx, &func->super); | |
| 113 } | |
| 114 | |
| 115 void | |
| 116 pdf_drop_function(fz_context *ctx, pdf_function *func) | |
| 117 { | |
| 118 fz_drop_function(ctx, &func->super); | |
| 119 } | |
| 120 | |
| 121 size_t | |
| 122 pdf_function_size(fz_context *ctx, pdf_function *func) | |
| 123 { | |
| 124 return fz_function_size(ctx, &func->super); | |
| 125 } | |
| 126 | |
| 127 static inline float lerp(float x, float xmin, float xmax, float ymin, float ymax) | |
| 128 { | |
| 129 if (xmin == xmax) | |
| 130 return ymin; | |
| 131 if (ymin == ymax) | |
| 132 return ymin; | |
| 133 return ymin + (x - xmin) * (ymax - ymin) / (xmax - xmin); | |
| 134 } | |
| 135 | |
| 136 /* | |
| 137 * PostScript calculator | |
| 138 */ | |
| 139 | |
| 140 enum { PS_BOOL, PS_INT, PS_REAL, PS_OPERATOR, PS_BLOCK }; | |
| 141 | |
| 142 enum | |
| 143 { | |
| 144 PS_OP_ABS, PS_OP_ADD, PS_OP_AND, PS_OP_ATAN, PS_OP_BITSHIFT, | |
| 145 PS_OP_CEILING, PS_OP_COPY, PS_OP_COS, PS_OP_CVI, PS_OP_CVR, | |
| 146 PS_OP_DIV, PS_OP_DUP, PS_OP_EQ, PS_OP_EXCH, PS_OP_EXP, | |
| 147 PS_OP_FALSE, PS_OP_FLOOR, PS_OP_GE, PS_OP_GT, PS_OP_IDIV, PS_OP_IF, | |
| 148 PS_OP_IFELSE, PS_OP_INDEX, PS_OP_LE, PS_OP_LN, PS_OP_LOG, PS_OP_LT, | |
| 149 PS_OP_MOD, PS_OP_MUL, PS_OP_NE, PS_OP_NEG, PS_OP_NOT, PS_OP_OR, | |
| 150 PS_OP_POP, PS_OP_RETURN, PS_OP_ROLL, PS_OP_ROUND, PS_OP_SIN, | |
| 151 PS_OP_SQRT, PS_OP_SUB, PS_OP_TRUE, PS_OP_TRUNCATE, PS_OP_XOR | |
| 152 }; | |
| 153 | |
| 154 static char *ps_op_names[] = | |
| 155 { | |
| 156 "abs", "add", "and", "atan", "bitshift", "ceiling", "copy", | |
| 157 "cos", "cvi", "cvr", "div", "dup", "eq", "exch", "exp", | |
| 158 "false", "floor", "ge", "gt", "idiv", "if", "ifelse", "index", "le", "ln", | |
| 159 "log", "lt", "mod", "mul", "ne", "neg", "not", "or", "pop", "return", | |
| 160 "roll", "round", "sin", "sqrt", "sub", "true", "truncate", "xor" | |
| 161 }; | |
| 162 | |
| 163 typedef struct | |
| 164 { | |
| 165 psobj stack[100]; | |
| 166 int sp; | |
| 167 } ps_stack; | |
| 168 | |
| 169 static void | |
| 170 ps_init_stack(ps_stack *st) | |
| 171 { | |
| 172 memset(st->stack, 0, sizeof(st->stack)); | |
| 173 st->sp = 0; | |
| 174 } | |
| 175 | |
| 176 static inline int ps_overflow(ps_stack *st, int n) | |
| 177 { | |
| 178 return n < 0 || st->sp + n >= (int)nelem(st->stack); | |
| 179 } | |
| 180 | |
| 181 static inline int ps_underflow(ps_stack *st, int n) | |
| 182 { | |
| 183 return n < 0 || n > st->sp; | |
| 184 } | |
| 185 | |
| 186 static inline int ps_is_type(ps_stack *st, int t) | |
| 187 { | |
| 188 return !ps_underflow(st, 1) && st->stack[st->sp - 1].type == t; | |
| 189 } | |
| 190 | |
| 191 static inline int ps_is_type2(ps_stack *st, int t) | |
| 192 { | |
| 193 return !ps_underflow(st, 2) && st->stack[st->sp - 1].type == t && st->stack[st->sp - 2].type == t; | |
| 194 } | |
| 195 | |
| 196 static void | |
| 197 ps_push_bool(ps_stack *st, int b) | |
| 198 { | |
| 199 if (!ps_overflow(st, 1)) | |
| 200 { | |
| 201 st->stack[st->sp].type = PS_BOOL; | |
| 202 st->stack[st->sp].u.b = b; | |
| 203 st->sp++; | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 static void | |
| 208 ps_push_int(ps_stack *st, int n) | |
| 209 { | |
| 210 if (!ps_overflow(st, 1)) | |
| 211 { | |
| 212 st->stack[st->sp].type = PS_INT; | |
| 213 st->stack[st->sp].u.i = n; | |
| 214 st->sp++; | |
| 215 } | |
| 216 } | |
| 217 | |
| 218 static void | |
| 219 ps_push_real(ps_stack *st, float n) | |
| 220 { | |
| 221 if (!ps_overflow(st, 1)) | |
| 222 { | |
| 223 st->stack[st->sp].type = PS_REAL; | |
| 224 if (isnan(n)) | |
| 225 { | |
| 226 /* Push 1.0, as it's a small known value that won't | |
| 227 * cause a divide by 0. Same reason as in fz_atof. */ | |
| 228 n = 1.0f; | |
| 229 } | |
| 230 st->stack[st->sp].u.f = fz_clamp(n, -FLT_MAX, FLT_MAX); | |
| 231 st->sp++; | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 static int | |
| 236 ps_pop_bool(ps_stack *st) | |
| 237 { | |
| 238 if (!ps_underflow(st, 1)) | |
| 239 { | |
| 240 if (ps_is_type(st, PS_BOOL)) | |
| 241 return st->stack[--st->sp].u.b; | |
| 242 } | |
| 243 return 0; | |
| 244 } | |
| 245 | |
| 246 static int | |
| 247 ps_pop_int(ps_stack *st) | |
| 248 { | |
| 249 if (!ps_underflow(st, 1)) | |
| 250 { | |
| 251 if (ps_is_type(st, PS_INT)) | |
| 252 return st->stack[--st->sp].u.i; | |
| 253 if (ps_is_type(st, PS_REAL)) | |
| 254 return st->stack[--st->sp].u.f; | |
| 255 } | |
| 256 return 0; | |
| 257 } | |
| 258 | |
| 259 static float | |
| 260 ps_pop_real(ps_stack *st) | |
| 261 { | |
| 262 if (!ps_underflow(st, 1)) | |
| 263 { | |
| 264 if (ps_is_type(st, PS_INT)) | |
| 265 return st->stack[--st->sp].u.i; | |
| 266 if (ps_is_type(st, PS_REAL)) | |
| 267 return st->stack[--st->sp].u.f; | |
| 268 } | |
| 269 return 0; | |
| 270 } | |
| 271 | |
| 272 static void | |
| 273 ps_copy(ps_stack *st, int n) | |
| 274 { | |
| 275 if (!ps_underflow(st, n) && !ps_overflow(st, n)) | |
| 276 { | |
| 277 memcpy(st->stack + st->sp, st->stack + st->sp - n, n * sizeof(psobj)); | |
| 278 st->sp += n; | |
| 279 } | |
| 280 } | |
| 281 | |
| 282 static void | |
| 283 ps_roll(ps_stack *st, int n, int j) | |
| 284 { | |
| 285 psobj tmp; | |
| 286 int i; | |
| 287 | |
| 288 if (ps_underflow(st, n) || j == 0 || n == 0) | |
| 289 return; | |
| 290 | |
| 291 if (j >= 0) | |
| 292 { | |
| 293 j %= n; | |
| 294 } | |
| 295 else | |
| 296 { | |
| 297 j = -j % n; | |
| 298 if (j != 0) | |
| 299 j = n - j; | |
| 300 } | |
| 301 | |
| 302 if (j*2 > n) | |
| 303 { | |
| 304 for (i = j; i < n; i++) | |
| 305 { | |
| 306 tmp = st->stack[st->sp - n]; | |
| 307 memmove(st->stack + st->sp - n, st->stack + st->sp - n + 1, (n-1) * sizeof(psobj)); | |
| 308 st->stack[st->sp - 1] = tmp; | |
| 309 } | |
| 310 } | |
| 311 else | |
| 312 { | |
| 313 for (i = 0; i < j; i++) | |
| 314 { | |
| 315 tmp = st->stack[st->sp - 1]; | |
| 316 memmove(st->stack + st->sp - n + 1, st->stack + st->sp - n, (n-1) * sizeof(psobj)); | |
| 317 st->stack[st->sp - n] = tmp; | |
| 318 } | |
| 319 } | |
| 320 } | |
| 321 | |
| 322 static void | |
| 323 ps_index(ps_stack *st, int n) | |
| 324 { | |
| 325 if (!ps_overflow(st, 1) && !ps_underflow(st, n + 1)) | |
| 326 { | |
| 327 st->stack[st->sp] = st->stack[st->sp - n - 1]; | |
| 328 st->sp++; | |
| 329 } | |
| 330 } | |
| 331 | |
| 332 static void | |
| 333 ps_run(fz_context *ctx, psobj *code, ps_stack *st, int pc) | |
| 334 { | |
| 335 int i1, i2; | |
| 336 float r1, r2; | |
| 337 int b1, b2; | |
| 338 | |
| 339 while (1) | |
| 340 { | |
| 341 switch (code[pc].type) | |
| 342 { | |
| 343 case PS_INT: | |
| 344 ps_push_int(st, code[pc++].u.i); | |
| 345 break; | |
| 346 | |
| 347 case PS_REAL: | |
| 348 ps_push_real(st, code[pc++].u.f); | |
| 349 break; | |
| 350 | |
| 351 case PS_OPERATOR: | |
| 352 switch (code[pc++].u.op) | |
| 353 { | |
| 354 case PS_OP_ABS: | |
| 355 if (ps_is_type(st, PS_INT)) | |
| 356 ps_push_int(st, fz_absi(ps_pop_int(st))); | |
| 357 else | |
| 358 ps_push_real(st, fz_abs(ps_pop_real(st))); | |
| 359 break; | |
| 360 | |
| 361 case PS_OP_ADD: | |
| 362 if (ps_is_type2(st, PS_INT)) { | |
| 363 i2 = ps_pop_int(st); | |
| 364 i1 = ps_pop_int(st); | |
| 365 ps_push_int(st, i1 + i2); | |
| 366 } | |
| 367 else { | |
| 368 r2 = ps_pop_real(st); | |
| 369 r1 = ps_pop_real(st); | |
| 370 ps_push_real(st, r1 + r2); | |
| 371 } | |
| 372 break; | |
| 373 | |
| 374 case PS_OP_AND: | |
| 375 if (ps_is_type2(st, PS_INT)) { | |
| 376 i2 = ps_pop_int(st); | |
| 377 i1 = ps_pop_int(st); | |
| 378 ps_push_int(st, i1 & i2); | |
| 379 } | |
| 380 else { | |
| 381 b2 = ps_pop_bool(st); | |
| 382 b1 = ps_pop_bool(st); | |
| 383 ps_push_bool(st, b1 && b2); | |
| 384 } | |
| 385 break; | |
| 386 | |
| 387 case PS_OP_ATAN: | |
| 388 r2 = ps_pop_real(st); | |
| 389 r1 = ps_pop_real(st); | |
| 390 r1 = atan2f(r1, r2) * FZ_RADIAN; | |
| 391 if (r1 < 0) | |
| 392 r1 += 360; | |
| 393 ps_push_real(st, r1); | |
| 394 break; | |
| 395 | |
| 396 case PS_OP_BITSHIFT: | |
| 397 i2 = ps_pop_int(st); | |
| 398 i1 = ps_pop_int(st); | |
| 399 if (i2 > 0 && i2 < 8 * (int)sizeof (i2)) | |
| 400 ps_push_int(st, i1 << i2); | |
| 401 else if (i2 < 0 && i2 > -8 * (int)sizeof (i2)) | |
| 402 ps_push_int(st, (int)((unsigned int)i1 >> -i2)); | |
| 403 else | |
| 404 ps_push_int(st, i1); | |
| 405 break; | |
| 406 | |
| 407 case PS_OP_CEILING: | |
| 408 r1 = ps_pop_real(st); | |
| 409 ps_push_real(st, ceilf(r1)); | |
| 410 break; | |
| 411 | |
| 412 case PS_OP_COPY: | |
| 413 ps_copy(st, ps_pop_int(st)); | |
| 414 break; | |
| 415 | |
| 416 case PS_OP_COS: | |
| 417 r1 = ps_pop_real(st); | |
| 418 ps_push_real(st, cosf(r1/FZ_RADIAN)); | |
| 419 break; | |
| 420 | |
| 421 case PS_OP_CVI: | |
| 422 ps_push_int(st, ps_pop_int(st)); | |
| 423 break; | |
| 424 | |
| 425 case PS_OP_CVR: | |
| 426 ps_push_real(st, ps_pop_real(st)); | |
| 427 break; | |
| 428 | |
| 429 case PS_OP_DIV: | |
| 430 r2 = ps_pop_real(st); | |
| 431 r1 = ps_pop_real(st); | |
| 432 if (fabsf(r2) >= FLT_EPSILON) | |
| 433 ps_push_real(st, r1 / r2); | |
| 434 else | |
| 435 ps_push_real(st, DIV_BY_ZERO(r1, r2, -FLT_MAX, FLT_MAX)); | |
| 436 break; | |
| 437 | |
| 438 case PS_OP_DUP: | |
| 439 ps_copy(st, 1); | |
| 440 break; | |
| 441 | |
| 442 case PS_OP_EQ: | |
| 443 if (ps_is_type2(st, PS_BOOL)) { | |
| 444 b2 = ps_pop_bool(st); | |
| 445 b1 = ps_pop_bool(st); | |
| 446 ps_push_bool(st, b1 == b2); | |
| 447 } | |
| 448 else if (ps_is_type2(st, PS_INT)) { | |
| 449 i2 = ps_pop_int(st); | |
| 450 i1 = ps_pop_int(st); | |
| 451 ps_push_bool(st, i1 == i2); | |
| 452 } | |
| 453 else { | |
| 454 r2 = ps_pop_real(st); | |
| 455 r1 = ps_pop_real(st); | |
| 456 ps_push_bool(st, r1 == r2); | |
| 457 } | |
| 458 break; | |
| 459 | |
| 460 case PS_OP_EXCH: | |
| 461 ps_roll(st, 2, 1); | |
| 462 break; | |
| 463 | |
| 464 case PS_OP_EXP: | |
| 465 r2 = ps_pop_real(st); | |
| 466 r1 = ps_pop_real(st); | |
| 467 ps_push_real(st, powf(r1, r2)); | |
| 468 break; | |
| 469 | |
| 470 case PS_OP_FALSE: | |
| 471 ps_push_bool(st, 0); | |
| 472 break; | |
| 473 | |
| 474 case PS_OP_FLOOR: | |
| 475 r1 = ps_pop_real(st); | |
| 476 ps_push_real(st, floorf(r1)); | |
| 477 break; | |
| 478 | |
| 479 case PS_OP_GE: | |
| 480 if (ps_is_type2(st, PS_INT)) { | |
| 481 i2 = ps_pop_int(st); | |
| 482 i1 = ps_pop_int(st); | |
| 483 ps_push_bool(st, i1 >= i2); | |
| 484 } | |
| 485 else { | |
| 486 r2 = ps_pop_real(st); | |
| 487 r1 = ps_pop_real(st); | |
| 488 ps_push_bool(st, r1 >= r2); | |
| 489 } | |
| 490 break; | |
| 491 | |
| 492 case PS_OP_GT: | |
| 493 if (ps_is_type2(st, PS_INT)) { | |
| 494 i2 = ps_pop_int(st); | |
| 495 i1 = ps_pop_int(st); | |
| 496 ps_push_bool(st, i1 > i2); | |
| 497 } | |
| 498 else { | |
| 499 r2 = ps_pop_real(st); | |
| 500 r1 = ps_pop_real(st); | |
| 501 ps_push_bool(st, r1 > r2); | |
| 502 } | |
| 503 break; | |
| 504 | |
| 505 case PS_OP_IDIV: | |
| 506 i2 = ps_pop_int(st); | |
| 507 i1 = ps_pop_int(st); | |
| 508 if (i2 == 0) { | |
| 509 ps_push_int(st, DIV_BY_ZERO(i1, i2, INT_MIN, INT_MAX)); | |
| 510 } | |
| 511 else if (i1 == INT_MIN && i2 == -1) { | |
| 512 ps_push_int(st, INT_MAX); | |
| 513 } | |
| 514 else { | |
| 515 ps_push_int(st, i1 / i2); | |
| 516 } | |
| 517 break; | |
| 518 | |
| 519 case PS_OP_INDEX: | |
| 520 ps_index(st, ps_pop_int(st)); | |
| 521 break; | |
| 522 | |
| 523 case PS_OP_LE: | |
| 524 if (ps_is_type2(st, PS_INT)) { | |
| 525 i2 = ps_pop_int(st); | |
| 526 i1 = ps_pop_int(st); | |
| 527 ps_push_bool(st, i1 <= i2); | |
| 528 } | |
| 529 else { | |
| 530 r2 = ps_pop_real(st); | |
| 531 r1 = ps_pop_real(st); | |
| 532 ps_push_bool(st, r1 <= r2); | |
| 533 } | |
| 534 break; | |
| 535 | |
| 536 case PS_OP_LN: | |
| 537 r1 = ps_pop_real(st); | |
| 538 /* Bug 692941 - logf as separate statement */ | |
| 539 r2 = logf(r1); | |
| 540 ps_push_real(st, r2); | |
| 541 break; | |
| 542 | |
| 543 case PS_OP_LOG: | |
| 544 r1 = ps_pop_real(st); | |
| 545 ps_push_real(st, log10f(r1)); | |
| 546 break; | |
| 547 | |
| 548 case PS_OP_LT: | |
| 549 if (ps_is_type2(st, PS_INT)) { | |
| 550 i2 = ps_pop_int(st); | |
| 551 i1 = ps_pop_int(st); | |
| 552 ps_push_bool(st, i1 < i2); | |
| 553 } | |
| 554 else { | |
| 555 r2 = ps_pop_real(st); | |
| 556 r1 = ps_pop_real(st); | |
| 557 ps_push_bool(st, r1 < r2); | |
| 558 } | |
| 559 break; | |
| 560 | |
| 561 case PS_OP_MOD: | |
| 562 i2 = ps_pop_int(st); | |
| 563 i1 = ps_pop_int(st); | |
| 564 if (i2 == 0) { | |
| 565 ps_push_int(st, DIV_BY_ZERO(i1, i2, INT_MIN, INT_MAX)); | |
| 566 } | |
| 567 else if (i1 == INT_MIN && i2 == -1) { | |
| 568 ps_push_int(st, 0); | |
| 569 } | |
| 570 else { | |
| 571 ps_push_int(st, i1 % i2); | |
| 572 } | |
| 573 break; | |
| 574 | |
| 575 case PS_OP_MUL: | |
| 576 if (ps_is_type2(st, PS_INT)) { | |
| 577 i2 = ps_pop_int(st); | |
| 578 i1 = ps_pop_int(st); | |
| 579 ps_push_int(st, i1 * i2); | |
| 580 } | |
| 581 else { | |
| 582 r2 = ps_pop_real(st); | |
| 583 r1 = ps_pop_real(st); | |
| 584 ps_push_real(st, r1 * r2); | |
| 585 } | |
| 586 break; | |
| 587 | |
| 588 case PS_OP_NE: | |
| 589 if (ps_is_type2(st, PS_BOOL)) { | |
| 590 b2 = ps_pop_bool(st); | |
| 591 b1 = ps_pop_bool(st); | |
| 592 ps_push_bool(st, b1 != b2); | |
| 593 } | |
| 594 else if (ps_is_type2(st, PS_INT)) { | |
| 595 i2 = ps_pop_int(st); | |
| 596 i1 = ps_pop_int(st); | |
| 597 ps_push_bool(st, i1 != i2); | |
| 598 } | |
| 599 else { | |
| 600 r2 = ps_pop_real(st); | |
| 601 r1 = ps_pop_real(st); | |
| 602 ps_push_bool(st, r1 != r2); | |
| 603 } | |
| 604 break; | |
| 605 | |
| 606 case PS_OP_NEG: | |
| 607 if (ps_is_type(st, PS_INT)) | |
| 608 ps_push_int(st, -ps_pop_int(st)); | |
| 609 else | |
| 610 ps_push_real(st, -ps_pop_real(st)); | |
| 611 break; | |
| 612 | |
| 613 case PS_OP_NOT: | |
| 614 if (ps_is_type(st, PS_BOOL)) | |
| 615 ps_push_bool(st, !ps_pop_bool(st)); | |
| 616 else | |
| 617 ps_push_int(st, ~ps_pop_int(st)); | |
| 618 break; | |
| 619 | |
| 620 case PS_OP_OR: | |
| 621 if (ps_is_type2(st, PS_BOOL)) { | |
| 622 b2 = ps_pop_bool(st); | |
| 623 b1 = ps_pop_bool(st); | |
| 624 ps_push_bool(st, b1 || b2); | |
| 625 } | |
| 626 else { | |
| 627 i2 = ps_pop_int(st); | |
| 628 i1 = ps_pop_int(st); | |
| 629 ps_push_int(st, i1 | i2); | |
| 630 } | |
| 631 break; | |
| 632 | |
| 633 case PS_OP_POP: | |
| 634 if (!ps_underflow(st, 1)) | |
| 635 st->sp--; | |
| 636 break; | |
| 637 | |
| 638 case PS_OP_ROLL: | |
| 639 i2 = ps_pop_int(st); | |
| 640 i1 = ps_pop_int(st); | |
| 641 ps_roll(st, i1, i2); | |
| 642 break; | |
| 643 | |
| 644 case PS_OP_ROUND: | |
| 645 if (!ps_is_type(st, PS_INT)) { | |
| 646 r1 = ps_pop_real(st); | |
| 647 ps_push_real(st, (r1 >= 0) ? floorf(r1 + 0.5f) : ceilf(r1 - 0.5f)); | |
| 648 } | |
| 649 break; | |
| 650 | |
| 651 case PS_OP_SIN: | |
| 652 r1 = ps_pop_real(st); | |
| 653 ps_push_real(st, sinf(r1/FZ_RADIAN)); | |
| 654 break; | |
| 655 | |
| 656 case PS_OP_SQRT: | |
| 657 r1 = ps_pop_real(st); | |
| 658 ps_push_real(st, sqrtf(r1)); | |
| 659 break; | |
| 660 | |
| 661 case PS_OP_SUB: | |
| 662 if (ps_is_type2(st, PS_INT)) { | |
| 663 i2 = ps_pop_int(st); | |
| 664 i1 = ps_pop_int(st); | |
| 665 ps_push_int(st, i1 - i2); | |
| 666 } | |
| 667 else { | |
| 668 r2 = ps_pop_real(st); | |
| 669 r1 = ps_pop_real(st); | |
| 670 ps_push_real(st, r1 - r2); | |
| 671 } | |
| 672 break; | |
| 673 | |
| 674 case PS_OP_TRUE: | |
| 675 ps_push_bool(st, 1); | |
| 676 break; | |
| 677 | |
| 678 case PS_OP_TRUNCATE: | |
| 679 if (!ps_is_type(st, PS_INT)) { | |
| 680 r1 = ps_pop_real(st); | |
| 681 ps_push_real(st, (r1 >= 0) ? floorf(r1) : ceilf(r1)); | |
| 682 } | |
| 683 break; | |
| 684 | |
| 685 case PS_OP_XOR: | |
| 686 if (ps_is_type2(st, PS_BOOL)) { | |
| 687 b2 = ps_pop_bool(st); | |
| 688 b1 = ps_pop_bool(st); | |
| 689 ps_push_bool(st, b1 ^ b2); | |
| 690 } | |
| 691 else { | |
| 692 i2 = ps_pop_int(st); | |
| 693 i1 = ps_pop_int(st); | |
| 694 ps_push_int(st, i1 ^ i2); | |
| 695 } | |
| 696 break; | |
| 697 | |
| 698 case PS_OP_IF: | |
| 699 b1 = ps_pop_bool(st); | |
| 700 if (b1) | |
| 701 ps_run(ctx, code, st, code[pc + 1].u.block); | |
| 702 pc = code[pc + 2].u.block; | |
| 703 break; | |
| 704 | |
| 705 case PS_OP_IFELSE: | |
| 706 b1 = ps_pop_bool(st); | |
| 707 if (b1) | |
| 708 ps_run(ctx, code, st, code[pc + 1].u.block); | |
| 709 else | |
| 710 ps_run(ctx, code, st, code[pc + 0].u.block); | |
| 711 pc = code[pc + 2].u.block; | |
| 712 break; | |
| 713 | |
| 714 case PS_OP_RETURN: | |
| 715 return; | |
| 716 | |
| 717 default: | |
| 718 fz_warn(ctx, "foreign operator in calculator function"); | |
| 719 return; | |
| 720 } | |
| 721 break; | |
| 722 | |
| 723 default: | |
| 724 fz_warn(ctx, "foreign object in calculator function"); | |
| 725 return; | |
| 726 } | |
| 727 } | |
| 728 } | |
| 729 | |
| 730 static void | |
| 731 resize_code(fz_context *ctx, pdf_function_p *func, int newsize) | |
| 732 { | |
| 733 if (newsize >= func->cap) | |
| 734 { | |
| 735 int new_cap = func->cap + 64; | |
| 736 func->code = fz_realloc_array(ctx, func->code, new_cap, psobj); | |
| 737 func->cap = new_cap; | |
| 738 } | |
| 739 } | |
| 740 | |
| 741 static void | |
| 742 parse_code(fz_context *ctx, pdf_function_p *func, fz_stream *stream, int *codeptr, pdf_lexbuf *buf, int depth) | |
| 743 { | |
| 744 pdf_token tok; | |
| 745 int opptr, elseptr, ifptr; | |
| 746 int a, b, mid, cmp; | |
| 747 | |
| 748 if (depth > 100) | |
| 749 fz_throw(ctx, FZ_ERROR_SYNTAX, "too much nesting in calculator function"); | |
| 750 | |
| 751 while (1) | |
| 752 { | |
| 753 tok = pdf_lex(ctx, stream, buf); | |
| 754 | |
| 755 switch (tok) | |
| 756 { | |
| 757 case PDF_TOK_EOF: | |
| 758 fz_throw(ctx, FZ_ERROR_SYNTAX, "truncated calculator function"); | |
| 759 | |
| 760 case PDF_TOK_INT: | |
| 761 resize_code(ctx, func, *codeptr); | |
| 762 func->code[*codeptr].type = PS_INT; | |
| 763 func->code[*codeptr].u.i = buf->i; | |
| 764 ++*codeptr; | |
| 765 break; | |
| 766 | |
| 767 case PDF_TOK_TRUE: | |
| 768 resize_code(ctx, func, *codeptr); | |
| 769 func->code[*codeptr].type = PS_BOOL; | |
| 770 func->code[*codeptr].u.b = 1; | |
| 771 ++*codeptr; | |
| 772 break; | |
| 773 | |
| 774 case PDF_TOK_FALSE: | |
| 775 resize_code(ctx, func, *codeptr); | |
| 776 func->code[*codeptr].type = PS_BOOL; | |
| 777 func->code[*codeptr].u.b = 0; | |
| 778 ++*codeptr; | |
| 779 break; | |
| 780 | |
| 781 case PDF_TOK_REAL: | |
| 782 resize_code(ctx, func, *codeptr); | |
| 783 func->code[*codeptr].type = PS_REAL; | |
| 784 func->code[*codeptr].u.f = buf->f; | |
| 785 ++*codeptr; | |
| 786 break; | |
| 787 | |
| 788 case PDF_TOK_OPEN_BRACE: | |
| 789 opptr = *codeptr; | |
| 790 *codeptr += 4; | |
| 791 | |
| 792 resize_code(ctx, func, *codeptr); | |
| 793 | |
| 794 ifptr = *codeptr; | |
| 795 parse_code(ctx, func, stream, codeptr, buf, depth + 1); | |
| 796 | |
| 797 tok = pdf_lex(ctx, stream, buf); | |
| 798 | |
| 799 if (tok == PDF_TOK_OPEN_BRACE) | |
| 800 { | |
| 801 elseptr = *codeptr; | |
| 802 parse_code(ctx, func, stream, codeptr, buf, depth + 1); | |
| 803 | |
| 804 tok = pdf_lex(ctx, stream, buf); | |
| 805 } | |
| 806 else | |
| 807 { | |
| 808 elseptr = -1; | |
| 809 } | |
| 810 | |
| 811 if (tok != PDF_TOK_KEYWORD) | |
| 812 fz_throw(ctx, FZ_ERROR_SYNTAX, "missing keyword in 'if-else' context"); | |
| 813 | |
| 814 if (!strcmp(buf->scratch, "if")) | |
| 815 { | |
| 816 if (elseptr >= 0) | |
| 817 fz_throw(ctx, FZ_ERROR_SYNTAX, "too many branches for 'if'"); | |
| 818 func->code[opptr].type = PS_OPERATOR; | |
| 819 func->code[opptr].u.op = PS_OP_IF; | |
| 820 func->code[opptr+2].type = PS_BLOCK; | |
| 821 func->code[opptr+2].u.block = ifptr; | |
| 822 func->code[opptr+3].type = PS_BLOCK; | |
| 823 func->code[opptr+3].u.block = *codeptr; | |
| 824 } | |
| 825 else if (!strcmp(buf->scratch, "ifelse")) | |
| 826 { | |
| 827 if (elseptr < 0) | |
| 828 fz_throw(ctx, FZ_ERROR_SYNTAX, "not enough branches for 'ifelse'"); | |
| 829 func->code[opptr].type = PS_OPERATOR; | |
| 830 func->code[opptr].u.op = PS_OP_IFELSE; | |
| 831 func->code[opptr+1].type = PS_BLOCK; | |
| 832 func->code[opptr+1].u.block = elseptr; | |
| 833 func->code[opptr+2].type = PS_BLOCK; | |
| 834 func->code[opptr+2].u.block = ifptr; | |
| 835 func->code[opptr+3].type = PS_BLOCK; | |
| 836 func->code[opptr+3].u.block = *codeptr; | |
| 837 } | |
| 838 else | |
| 839 { | |
| 840 fz_throw(ctx, FZ_ERROR_SYNTAX, "unknown keyword in 'if-else' context: '%s'", buf->scratch); | |
| 841 } | |
| 842 break; | |
| 843 | |
| 844 case PDF_TOK_CLOSE_BRACE: | |
| 845 resize_code(ctx, func, *codeptr); | |
| 846 func->code[*codeptr].type = PS_OPERATOR; | |
| 847 func->code[*codeptr].u.op = PS_OP_RETURN; | |
| 848 ++*codeptr; | |
| 849 return; | |
| 850 | |
| 851 case PDF_TOK_KEYWORD: | |
| 852 cmp = -1; | |
| 853 a = -1; | |
| 854 b = nelem(ps_op_names); | |
| 855 while (b - a > 1) | |
| 856 { | |
| 857 mid = (a + b) / 2; | |
| 858 cmp = strcmp(buf->scratch, ps_op_names[mid]); | |
| 859 if (cmp > 0) | |
| 860 a = mid; | |
| 861 else if (cmp < 0) | |
| 862 b = mid; | |
| 863 else | |
| 864 a = b = mid; | |
| 865 } | |
| 866 if (cmp != 0) | |
| 867 fz_throw(ctx, FZ_ERROR_SYNTAX, "unknown operator: '%s'", buf->scratch); | |
| 868 if (a == PS_OP_IFELSE) | |
| 869 fz_throw(ctx, FZ_ERROR_SYNTAX, "illegally positioned ifelse operator in function"); | |
| 870 if (a == PS_OP_IF) | |
| 871 fz_throw(ctx, FZ_ERROR_SYNTAX, "illegally positioned if operator in function"); | |
| 872 | |
| 873 resize_code(ctx, func, *codeptr); | |
| 874 func->code[*codeptr].type = PS_OPERATOR; | |
| 875 func->code[*codeptr].u.op = a; | |
| 876 ++*codeptr; | |
| 877 break; | |
| 878 | |
| 879 default: | |
| 880 fz_throw(ctx, FZ_ERROR_SYNTAX, "calculator function syntax error"); | |
| 881 } | |
| 882 } | |
| 883 } | |
| 884 | |
| 885 static void | |
| 886 load_postscript_func(fz_context *ctx, pdf_function *func_, pdf_obj *dict) | |
| 887 { | |
| 888 pdf_function_p *func = (pdf_function_p *)func_; | |
| 889 fz_stream *stream = NULL; | |
| 890 int codeptr; | |
| 891 pdf_lexbuf buf; | |
| 892 pdf_token tok; | |
| 893 | |
| 894 pdf_lexbuf_init(ctx, &buf, PDF_LEXBUF_SMALL); | |
| 895 | |
| 896 fz_var(stream); | |
| 897 | |
| 898 fz_try(ctx) | |
| 899 { | |
| 900 stream = pdf_open_stream(ctx, dict); | |
| 901 | |
| 902 tok = pdf_lex(ctx, stream, &buf); | |
| 903 if (tok != PDF_TOK_OPEN_BRACE) | |
| 904 { | |
| 905 fz_throw(ctx, FZ_ERROR_SYNTAX, "stream is not a calculator function"); | |
| 906 } | |
| 907 | |
| 908 func->code = NULL; | |
| 909 func->cap = 0; | |
| 910 | |
| 911 codeptr = 0; | |
| 912 parse_code(ctx, func, stream, &codeptr, &buf, 0); | |
| 913 } | |
| 914 fz_always(ctx) | |
| 915 { | |
| 916 fz_drop_stream(ctx, stream); | |
| 917 pdf_lexbuf_fin(ctx, &buf); | |
| 918 } | |
| 919 fz_catch(ctx) | |
| 920 { | |
| 921 fz_rethrow(ctx); | |
| 922 } | |
| 923 | |
| 924 func->super.super.size += func->cap * sizeof(psobj); | |
| 925 } | |
| 926 | |
| 927 static void | |
| 928 eval_postscript_func(fz_context *ctx, fz_function *func_, const float *in, float *out) | |
| 929 { | |
| 930 pdf_function_p *func = (pdf_function_p *)func_; | |
| 931 ps_stack st; | |
| 932 float x; | |
| 933 int i; | |
| 934 | |
| 935 ps_init_stack(&st); | |
| 936 | |
| 937 for (i = 0; i < func->super.super.m; i++) | |
| 938 { | |
| 939 x = fz_clamp(in[i], func->super.domain[i][0], func->super.domain[i][1]); | |
| 940 ps_push_real(&st, x); | |
| 941 } | |
| 942 | |
| 943 ps_run(ctx, func->code, &st, 0); | |
| 944 | |
| 945 for (i = func->super.super.n - 1; i >= 0; i--) | |
| 946 { | |
| 947 x = ps_pop_real(&st); | |
| 948 out[i] = fz_clamp(x, func->super.range[i][0], func->super.range[i][1]); | |
| 949 } | |
| 950 } | |
| 951 | |
| 952 /* | |
| 953 * Sample function | |
| 954 */ | |
| 955 | |
| 956 #define MAX_SAMPLE_FUNCTION_SIZE (100 << 20) | |
| 957 | |
| 958 static void | |
| 959 load_sample_func(fz_context *ctx, pdf_function *func_, pdf_obj *dict) | |
| 960 { | |
| 961 pdf_function_sa *func = (pdf_function_sa *)func_; | |
| 962 fz_stream *stream; | |
| 963 pdf_obj *obj; | |
| 964 int samplecount; | |
| 965 int bps; | |
| 966 int i; | |
| 967 | |
| 968 func->samples = NULL; | |
| 969 | |
| 970 obj = pdf_dict_get(ctx, dict, PDF_NAME(Size)); | |
| 971 if (pdf_array_len(ctx, obj) < func->super.super.m) | |
| 972 fz_throw(ctx, FZ_ERROR_SYNTAX, "too few sample function dimension sizes"); | |
| 973 if (pdf_array_len(ctx, obj) > func->super.super.m) | |
| 974 fz_warn(ctx, "too many sample function dimension sizes"); | |
| 975 for (i = 0; i < func->super.super.m; i++) | |
| 976 { | |
| 977 func->size[i] = pdf_array_get_int(ctx, obj, i); | |
| 978 if (func->size[i] <= 0) | |
| 979 { | |
| 980 fz_warn(ctx, "non-positive sample function dimension size"); | |
| 981 func->size[i] = 1; | |
| 982 } | |
| 983 } | |
| 984 | |
| 985 func->bps = bps = pdf_dict_get_int(ctx, dict, PDF_NAME(BitsPerSample)); | |
| 986 | |
| 987 for (i = 0; i < func->super.super.m; i++) | |
| 988 { | |
| 989 func->encode[i][0] = 0; | |
| 990 func->encode[i][1] = func->size[i] - 1; | |
| 991 } | |
| 992 obj = pdf_dict_get(ctx, dict, PDF_NAME(Encode)); | |
| 993 if (pdf_is_array(ctx, obj)) | |
| 994 { | |
| 995 int ranges = fz_mini(func->super.super.m, pdf_array_len(ctx, obj) / 2); | |
| 996 if (ranges != func->super.super.m) | |
| 997 fz_warn(ctx, "wrong number of sample function input mappings"); | |
| 998 | |
| 999 for (i = 0; i < ranges; i++) | |
| 1000 { | |
| 1001 func->encode[i][0] = pdf_array_get_real(ctx, obj, i * 2 + 0); | |
| 1002 func->encode[i][1] = pdf_array_get_real(ctx, obj, i * 2 + 1); | |
| 1003 } | |
| 1004 } | |
| 1005 | |
| 1006 for (i = 0; i < func->super.super.n; i++) | |
| 1007 { | |
| 1008 func->decode[i][0] = func->super.range[i][0]; | |
| 1009 func->decode[i][1] = func->super.range[i][1]; | |
| 1010 } | |
| 1011 | |
| 1012 obj = pdf_dict_get(ctx, dict, PDF_NAME(Decode)); | |
| 1013 if (pdf_is_array(ctx, obj)) | |
| 1014 { | |
| 1015 int ranges = fz_mini(func->super.super.n, pdf_array_len(ctx, obj) / 2); | |
| 1016 if (ranges != func->super.super.n) | |
| 1017 fz_warn(ctx, "wrong number of sample function output mappings"); | |
| 1018 | |
| 1019 for (i = 0; i < ranges; i++) | |
| 1020 { | |
| 1021 func->decode[i][0] = pdf_array_get_real(ctx, obj, i * 2 + 0); | |
| 1022 func->decode[i][1] = pdf_array_get_real(ctx, obj, i * 2 + 1); | |
| 1023 } | |
| 1024 } | |
| 1025 | |
| 1026 for (i = 0, samplecount = func->super.super.n; i < func->super.super.m; i++) | |
| 1027 { | |
| 1028 if (samplecount > MAX_SAMPLE_FUNCTION_SIZE / func->size[i]) | |
| 1029 fz_throw(ctx, FZ_ERROR_SYNTAX, "sample function too large"); | |
| 1030 samplecount *= func->size[i]; | |
| 1031 } | |
| 1032 | |
| 1033 if (samplecount > MAX_SAMPLE_FUNCTION_SIZE) | |
| 1034 fz_throw(ctx, FZ_ERROR_SYNTAX, "sample function too large"); | |
| 1035 | |
| 1036 func->samples = Memento_label(fz_malloc_array(ctx, samplecount, float), "function_samples"); | |
| 1037 func->super.super.size += samplecount * sizeof(float); | |
| 1038 | |
| 1039 stream = pdf_open_stream(ctx, dict); | |
| 1040 | |
| 1041 fz_try(ctx) | |
| 1042 { | |
| 1043 /* read samples */ | |
| 1044 for (i = 0; i < samplecount; i++) | |
| 1045 { | |
| 1046 float s; | |
| 1047 | |
| 1048 if (fz_is_eof_bits(ctx, stream)) | |
| 1049 fz_throw(ctx, FZ_ERROR_SYNTAX, "truncated sample function stream"); | |
| 1050 | |
| 1051 switch (bps) | |
| 1052 { | |
| 1053 case 1: s = fz_read_bits(ctx, stream, 1); break; | |
| 1054 case 2: s = fz_read_bits(ctx, stream, 2) / 3.0f; break; | |
| 1055 case 4: s = fz_read_bits(ctx, stream, 4) / 15.0f; break; | |
| 1056 case 8: s = fz_read_byte(ctx, stream) / 255.0f; break; | |
| 1057 case 12: s = fz_read_bits(ctx, stream, 12) / 4095.0f; break; | |
| 1058 case 16: s = fz_read_uint16(ctx, stream) / 65535.0f; break; | |
| 1059 case 24: s = fz_read_uint24(ctx, stream) / 16777215.0f; break; | |
| 1060 case 32: s = fz_read_uint32(ctx, stream) / 4294967295.0f; break; | |
| 1061 default: fz_throw(ctx, FZ_ERROR_SYNTAX, "sample stream bit depth %d unsupported", bps); | |
| 1062 } | |
| 1063 | |
| 1064 func->samples[i] = s; | |
| 1065 } | |
| 1066 } | |
| 1067 fz_always(ctx) | |
| 1068 { | |
| 1069 fz_drop_stream(ctx, stream); | |
| 1070 } | |
| 1071 fz_catch(ctx) | |
| 1072 { | |
| 1073 fz_rethrow(ctx); | |
| 1074 } | |
| 1075 } | |
| 1076 | |
| 1077 static float | |
| 1078 interpolate_sample(pdf_function_sa *func, int *scale, int *e0, int *e1, float *efrac, int dim, int idx) | |
| 1079 { | |
| 1080 float a, b; | |
| 1081 int idx0, idx1; | |
| 1082 | |
| 1083 idx0 = e0[dim] * scale[dim] + idx; | |
| 1084 idx1 = e1[dim] * scale[dim] + idx; | |
| 1085 | |
| 1086 if (dim == 0) | |
| 1087 { | |
| 1088 a = func->samples[idx0]; | |
| 1089 b = func->samples[idx1]; | |
| 1090 } | |
| 1091 else | |
| 1092 { | |
| 1093 a = interpolate_sample(func, scale, e0, e1, efrac, dim - 1, idx0); | |
| 1094 b = interpolate_sample(func, scale, e0, e1, efrac, dim - 1, idx1); | |
| 1095 } | |
| 1096 | |
| 1097 return a + (b - a) * efrac[dim]; | |
| 1098 } | |
| 1099 | |
| 1100 static void | |
| 1101 eval_sample_func(fz_context *ctx, fz_function *func_, const float *in, float *out) | |
| 1102 { | |
| 1103 pdf_function_sa *func = (pdf_function_sa *)func_; | |
| 1104 int e0[MAX_M], e1[MAX_M], scale[MAX_M]; | |
| 1105 float efrac[MAX_M]; | |
| 1106 float x; | |
| 1107 int i; | |
| 1108 | |
| 1109 /* encode input coordinates */ | |
| 1110 for (i = 0; i < func->super.super.m; i++) | |
| 1111 { | |
| 1112 x = fz_clamp(in[i], func->super.domain[i][0], func->super.domain[i][1]); | |
| 1113 x = lerp(x, func->super.domain[i][0], func->super.domain[i][1], | |
| 1114 func->encode[i][0], func->encode[i][1]); | |
| 1115 x = fz_clamp(x, 0, func->size[i] - 1); | |
| 1116 e0[i] = floorf(x); | |
| 1117 e1[i] = ceilf(x); | |
| 1118 efrac[i] = x - e0[i]; | |
| 1119 } | |
| 1120 | |
| 1121 scale[0] = func->super.super.n; | |
| 1122 for (i = 1; i < func->super.super.m; i++) | |
| 1123 scale[i] = scale[i - 1] * func->size[i-1]; | |
| 1124 | |
| 1125 for (i = 0; i < func->super.super.n; i++) | |
| 1126 { | |
| 1127 if (func->super.super.m == 1) | |
| 1128 { | |
| 1129 float a = func->samples[e0[0] * func->super.super.n + i]; | |
| 1130 float b = func->samples[e1[0] * func->super.super.n + i]; | |
| 1131 | |
| 1132 float ab = a + (b - a) * efrac[0]; | |
| 1133 | |
| 1134 out[i] = lerp(ab, 0, 1, func->decode[i][0], func->decode[i][1]); | |
| 1135 out[i] = fz_clamp(out[i], func->super.range[i][0], func->super.range[i][1]); | |
| 1136 } | |
| 1137 | |
| 1138 else if (func->super.super.m == 2) | |
| 1139 { | |
| 1140 int s0 = func->super.super.n; | |
| 1141 int s1 = s0 * func->size[0]; | |
| 1142 | |
| 1143 float a = func->samples[e0[0] * s0 + e0[1] * s1 + i]; | |
| 1144 float b = func->samples[e1[0] * s0 + e0[1] * s1 + i]; | |
| 1145 float c = func->samples[e0[0] * s0 + e1[1] * s1 + i]; | |
| 1146 float d = func->samples[e1[0] * s0 + e1[1] * s1 + i]; | |
| 1147 | |
| 1148 float ab = a + (b - a) * efrac[0]; | |
| 1149 float cd = c + (d - c) * efrac[0]; | |
| 1150 float abcd = ab + (cd - ab) * efrac[1]; | |
| 1151 | |
| 1152 out[i] = lerp(abcd, 0, 1, func->decode[i][0], func->decode[i][1]); | |
| 1153 out[i] = fz_clamp(out[i], func->super.range[i][0], func->super.range[i][1]); | |
| 1154 } | |
| 1155 | |
| 1156 else | |
| 1157 { | |
| 1158 x = interpolate_sample(func, scale, e0, e1, efrac, func->super.super.m - 1, i); | |
| 1159 out[i] = lerp(x, 0, 1, func->decode[i][0], func->decode[i][1]); | |
| 1160 out[i] = fz_clamp(out[i], func->super.range[i][0], func->super.range[i][1]); | |
| 1161 } | |
| 1162 } | |
| 1163 } | |
| 1164 | |
| 1165 /* | |
| 1166 * Exponential function | |
| 1167 */ | |
| 1168 | |
| 1169 static void | |
| 1170 load_exponential_func(fz_context *ctx, pdf_function *func_, pdf_obj *dict) | |
| 1171 { | |
| 1172 pdf_function_e *func = (pdf_function_e *)func_; | |
| 1173 pdf_obj *obj; | |
| 1174 int i; | |
| 1175 | |
| 1176 if (func->super.super.m > 1) | |
| 1177 fz_warn(ctx, "exponential functions have at most one input"); | |
| 1178 func->super.super.m = 1; | |
| 1179 | |
| 1180 func->n = pdf_dict_get_real(ctx, dict, PDF_NAME(N)); | |
| 1181 | |
| 1182 /* See exponential functions (PDF 1.7 section 3.9.2) */ | |
| 1183 if (func->n != (int) func->n) | |
| 1184 { | |
| 1185 /* If N is non-integer, input values may never be negative */ | |
| 1186 for (i = 0; i < func->super.super.m; i++) | |
| 1187 if (func->super.domain[i][0] < 0 || func->super.domain[i][1] < 0) | |
| 1188 fz_warn(ctx, "exponential function input domain includes illegal negative input values"); | |
| 1189 } | |
| 1190 else if (func->n < 0) | |
| 1191 { | |
| 1192 /* if N is negative, input values may never be zero */ | |
| 1193 for (i = 0; i < func->super.super.m; i++) | |
| 1194 if (func->super.domain[i][0] == 0 || func->super.domain[i][1] == 0 || | |
| 1195 (func->super.domain[i][0] < 0 && func->super.domain[i][1] > 0)) | |
| 1196 fz_warn(ctx, "exponential function input domain includes illegal input value zero"); | |
| 1197 } | |
| 1198 | |
| 1199 for (i = 0; i < func->super.super.n; i++) | |
| 1200 { | |
| 1201 func->c0[i] = 0; | |
| 1202 func->c1[i] = 1; | |
| 1203 } | |
| 1204 | |
| 1205 obj = pdf_dict_get(ctx, dict, PDF_NAME(C0)); | |
| 1206 if (pdf_is_array(ctx, obj)) | |
| 1207 { | |
| 1208 int ranges = fz_mini(func->super.super.n, pdf_array_len(ctx, obj)); | |
| 1209 if (ranges != func->super.super.n) | |
| 1210 fz_warn(ctx, "wrong number of C0 constants for exponential function"); | |
| 1211 | |
| 1212 for (i = 0; i < ranges; i++) | |
| 1213 func->c0[i] = pdf_array_get_real(ctx, obj, i); | |
| 1214 } | |
| 1215 | |
| 1216 obj = pdf_dict_get(ctx, dict, PDF_NAME(C1)); | |
| 1217 if (pdf_is_array(ctx, obj)) | |
| 1218 { | |
| 1219 int ranges = fz_mini(func->super.super.n, pdf_array_len(ctx, obj)); | |
| 1220 if (ranges != func->super.super.n) | |
| 1221 fz_warn(ctx, "wrong number of C1 constants for exponential function"); | |
| 1222 | |
| 1223 for (i = 0; i < ranges; i++) | |
| 1224 func->c1[i] = pdf_array_get_real(ctx, obj, i); | |
| 1225 } | |
| 1226 } | |
| 1227 | |
| 1228 static void | |
| 1229 eval_exponential_func(fz_context *ctx, fz_function *func_, const float *in, float *out) | |
| 1230 { | |
| 1231 pdf_function_e *func = (pdf_function_e *)func_; | |
| 1232 float x = *in; | |
| 1233 float tmp; | |
| 1234 int i; | |
| 1235 | |
| 1236 x = fz_clamp(x, func->super.domain[0][0], func->super.domain[0][1]); | |
| 1237 | |
| 1238 /* Default output is zero, which is suitable for violated constraints */ | |
| 1239 if ((func->n != (int)func->n && x < 0) || (func->n < 0 && x == 0)) | |
| 1240 { | |
| 1241 for (i = 0; i < func->super.super.n; i++) | |
| 1242 out[i] = 0; | |
| 1243 return; | |
| 1244 } | |
| 1245 | |
| 1246 tmp = powf(x, func->n); | |
| 1247 for (i = 0; i < func->super.super.n; i++) | |
| 1248 { | |
| 1249 out[i] = func->c0[i] + tmp * (func->c1[i] - func->c0[i]); | |
| 1250 if (func->super.has_range) | |
| 1251 out[i] = fz_clamp(out[i], func->super.range[i][0], func->super.range[i][1]); | |
| 1252 } | |
| 1253 } | |
| 1254 | |
| 1255 /* | |
| 1256 * Stitching function | |
| 1257 */ | |
| 1258 | |
| 1259 static void | |
| 1260 load_stitching_func(fz_context *ctx, pdf_function *func_, pdf_obj *dict, pdf_cycle_list *cycle_up) | |
| 1261 { | |
| 1262 pdf_function_st *func = (pdf_function_st *)func_; | |
| 1263 pdf_function **funcs; | |
| 1264 pdf_obj *obj; | |
| 1265 pdf_obj *sub; | |
| 1266 int k; | |
| 1267 int i; | |
| 1268 | |
| 1269 func->k = 0; | |
| 1270 | |
| 1271 if (func->super.super.m > 1) | |
| 1272 fz_warn(ctx, "stitching functions have at most one input"); | |
| 1273 func->super.super.m = 1; | |
| 1274 | |
| 1275 obj = pdf_dict_get(ctx, dict, PDF_NAME(Functions)); | |
| 1276 if (!pdf_is_array(ctx, obj)) | |
| 1277 fz_throw(ctx, FZ_ERROR_SYNTAX, "stitching function has no input functions"); | |
| 1278 | |
| 1279 k = pdf_array_len(ctx, obj); | |
| 1280 | |
| 1281 func->funcs = Memento_label(fz_malloc_array(ctx, k, pdf_function*), "stitch_fns"); | |
| 1282 func->bounds = Memento_label(fz_malloc_array(ctx, k - 1, float), "stitch_bounds"); | |
| 1283 func->encode = Memento_label(fz_malloc_array(ctx, k * 2, float), "stitch_encode"); | |
| 1284 funcs = func->funcs; | |
| 1285 | |
| 1286 for (i = 0; i < k; i++) | |
| 1287 { | |
| 1288 sub = pdf_array_get(ctx, obj, i); | |
| 1289 funcs[i] = pdf_load_function_imp(ctx, sub, 1, func->super.super.n, cycle_up); | |
| 1290 | |
| 1291 func->super.super.size += pdf_function_size(ctx, funcs[i]); | |
| 1292 func->k ++; | |
| 1293 | |
| 1294 if (funcs[i]->super.m != func->super.super.m) | |
| 1295 fz_warn(ctx, "wrong number of inputs for sub function %d", i); | |
| 1296 if (funcs[i]->super.n != func->super.super.n) | |
| 1297 fz_warn(ctx, "wrong number of outputs for sub function %d", i); | |
| 1298 } | |
| 1299 | |
| 1300 obj = pdf_dict_get(ctx, dict, PDF_NAME(Bounds)); | |
| 1301 if (!pdf_is_array(ctx, obj)) | |
| 1302 fz_throw(ctx, FZ_ERROR_SYNTAX, "stitching function has no bounds"); | |
| 1303 { | |
| 1304 if (pdf_array_len(ctx, obj) < k - 1) | |
| 1305 fz_throw(ctx, FZ_ERROR_SYNTAX, "too few subfunction boundaries"); | |
| 1306 if (pdf_array_len(ctx, obj) > k) | |
| 1307 fz_warn(ctx, "too many subfunction boundaries"); | |
| 1308 | |
| 1309 for (i = 0; i < k - 1; i++) | |
| 1310 { | |
| 1311 func->bounds[i] = pdf_array_get_real(ctx, obj, i); | |
| 1312 if (i && func->bounds[i - 1] > func->bounds[i]) | |
| 1313 fz_throw(ctx, FZ_ERROR_SYNTAX, "subfunction %d boundary out of range", i); | |
| 1314 } | |
| 1315 | |
| 1316 if (k > 1 && (func->super.domain[0][0] > func->bounds[0] || | |
| 1317 func->super.domain[0][1] < func->bounds[k - 2])) | |
| 1318 fz_warn(ctx, "subfunction boundaries outside of input mapping"); | |
| 1319 } | |
| 1320 | |
| 1321 for (i = 0; i < k; i++) | |
| 1322 { | |
| 1323 func->encode[i * 2 + 0] = 0; | |
| 1324 func->encode[i * 2 + 1] = 0; | |
| 1325 } | |
| 1326 | |
| 1327 obj = pdf_dict_get(ctx, dict, PDF_NAME(Encode)); | |
| 1328 if (pdf_is_array(ctx, obj)) | |
| 1329 { | |
| 1330 int ranges = fz_mini(k, pdf_array_len(ctx, obj) / 2); | |
| 1331 if (ranges != k) | |
| 1332 fz_warn(ctx, "wrong number of stitching function input mappings"); | |
| 1333 | |
| 1334 for (i = 0; i < ranges; i++) | |
| 1335 { | |
| 1336 func->encode[i * 2 + 0] = pdf_array_get_real(ctx, obj, i * 2 + 0); | |
| 1337 func->encode[i * 2 + 1] = pdf_array_get_real(ctx, obj, i * 2 + 1); | |
| 1338 } | |
| 1339 } | |
| 1340 } | |
| 1341 | |
| 1342 static void | |
| 1343 eval_stitching_func(fz_context *ctx, fz_function *func_, const float *inp, float *out) | |
| 1344 { | |
| 1345 pdf_function_st *func = (pdf_function_st *)func_; | |
| 1346 float low, high; | |
| 1347 int k = func->k; | |
| 1348 float *bounds = func->bounds; | |
| 1349 int i; | |
| 1350 float in = fz_clamp(*inp, func->super.domain[0][0], func->super.domain[0][1]); | |
| 1351 | |
| 1352 for (i = 0; i < k - 1; i++) | |
| 1353 { | |
| 1354 if (in < bounds[i]) | |
| 1355 break; | |
| 1356 } | |
| 1357 | |
| 1358 if (i == 0 && k == 1) | |
| 1359 { | |
| 1360 low = func->super.domain[0][0]; | |
| 1361 high = func->super.domain[0][1]; | |
| 1362 } | |
| 1363 else if (i == 0) | |
| 1364 { | |
| 1365 low = func->super.domain[0][0]; | |
| 1366 high = bounds[0]; | |
| 1367 } | |
| 1368 else if (i == k - 1) | |
| 1369 { | |
| 1370 low = bounds[k - 2]; | |
| 1371 high = func->super.domain[0][1]; | |
| 1372 } | |
| 1373 else | |
| 1374 { | |
| 1375 low = bounds[i - 1]; | |
| 1376 high = bounds[i]; | |
| 1377 } | |
| 1378 | |
| 1379 in = lerp(in, low, high, func->encode[i * 2 + 0], func->encode[i * 2 + 1]); | |
| 1380 | |
| 1381 pdf_eval_function(ctx, func->funcs[i], &in, 1, out, func->super.super.n); | |
| 1382 } | |
| 1383 | |
| 1384 /* | |
| 1385 * Common | |
| 1386 */ | |
| 1387 | |
| 1388 static void | |
| 1389 pdf_drop_function_sa(fz_context *ctx, fz_storable *func_) | |
| 1390 { | |
| 1391 pdf_function_sa *func = (pdf_function_sa *)func_; | |
| 1392 | |
| 1393 fz_free(ctx, func->samples); | |
| 1394 fz_free(ctx, func); | |
| 1395 } | |
| 1396 | |
| 1397 static void | |
| 1398 pdf_drop_function_e(fz_context *ctx, fz_storable *func) | |
| 1399 { | |
| 1400 fz_free(ctx, func); | |
| 1401 } | |
| 1402 | |
| 1403 static void | |
| 1404 pdf_drop_function_st(fz_context *ctx, fz_storable *func_) | |
| 1405 { | |
| 1406 pdf_function_st *func = (pdf_function_st *)func_; | |
| 1407 int i; | |
| 1408 | |
| 1409 for (i = 0; i < func->k; i++) | |
| 1410 pdf_drop_function(ctx, func->funcs[i]); | |
| 1411 fz_free(ctx, func->funcs); | |
| 1412 fz_free(ctx, func->bounds); | |
| 1413 fz_free(ctx, func->encode); | |
| 1414 fz_free(ctx, func); | |
| 1415 } | |
| 1416 | |
| 1417 static void | |
| 1418 pdf_drop_function_p(fz_context *ctx, fz_storable *func_) | |
| 1419 { | |
| 1420 pdf_function_p *func = (pdf_function_p *)func_; | |
| 1421 | |
| 1422 fz_free(ctx, func->code); | |
| 1423 fz_free(ctx, func); | |
| 1424 } | |
| 1425 | |
| 1426 void | |
| 1427 pdf_eval_function(fz_context *ctx, pdf_function *func, const float *in, int inlen, float *out, int outlen) | |
| 1428 { | |
| 1429 fz_eval_function(ctx, &func->super, in, inlen, out, outlen); | |
| 1430 } | |
| 1431 | |
| 1432 static pdf_function * | |
| 1433 pdf_load_function_imp(fz_context *ctx, pdf_obj *dict, int in, int out, pdf_cycle_list *cycle_up) | |
| 1434 { | |
| 1435 pdf_cycle_list cycle; | |
| 1436 pdf_function *func; | |
| 1437 pdf_obj *obj; | |
| 1438 int i; | |
| 1439 int type; | |
| 1440 fz_store_drop_fn *drop; | |
| 1441 | |
| 1442 if (pdf_cycle(ctx, &cycle, cycle_up, dict)) | |
| 1443 fz_throw(ctx, FZ_ERROR_SYNTAX, "recursive function"); | |
| 1444 | |
| 1445 type = pdf_dict_get_int(ctx, dict, PDF_NAME(FunctionType)); | |
| 1446 | |
| 1447 switch (type) | |
| 1448 { | |
| 1449 case SAMPLE: | |
| 1450 drop = pdf_drop_function_sa; | |
| 1451 break; | |
| 1452 | |
| 1453 case EXPONENTIAL: | |
| 1454 drop = pdf_drop_function_e; | |
| 1455 break; | |
| 1456 | |
| 1457 case STITCHING: | |
| 1458 drop = pdf_drop_function_st; | |
| 1459 break; | |
| 1460 | |
| 1461 case POSTSCRIPT: | |
| 1462 drop = pdf_drop_function_p; | |
| 1463 break; | |
| 1464 | |
| 1465 default: | |
| 1466 fz_throw(ctx, FZ_ERROR_SYNTAX, "unknown function type (%d 0 R)", pdf_to_num(ctx, dict)); | |
| 1467 } | |
| 1468 | |
| 1469 if ((func = pdf_find_item(ctx, drop, dict)) != NULL) | |
| 1470 return func; | |
| 1471 | |
| 1472 switch (type) | |
| 1473 { | |
| 1474 case SAMPLE: | |
| 1475 func = &fz_new_derived_function(ctx, pdf_function_sa, sizeof(pdf_function_sa), 1, 1, eval_sample_func, pdf_drop_function_sa)->super; | |
| 1476 break; | |
| 1477 | |
| 1478 case EXPONENTIAL: | |
| 1479 func = &fz_new_derived_function(ctx, pdf_function_e, sizeof(pdf_function_e), 1, 1, eval_exponential_func, pdf_drop_function_e)->super; | |
| 1480 break; | |
| 1481 | |
| 1482 case STITCHING: | |
| 1483 func = &fz_new_derived_function(ctx, pdf_function_st, sizeof(pdf_function_st), 1, 1, eval_stitching_func, pdf_drop_function_st)->super; | |
| 1484 break; | |
| 1485 | |
| 1486 case POSTSCRIPT: | |
| 1487 func = &fz_new_derived_function(ctx, pdf_function_p, sizeof(pdf_function_p), 1, 1, eval_postscript_func, pdf_drop_function_p)->super; | |
| 1488 break; | |
| 1489 } | |
| 1490 | |
| 1491 /* required for all */ | |
| 1492 obj = pdf_dict_get(ctx, dict, PDF_NAME(Domain)); | |
| 1493 func->super.m = fz_clampi(pdf_array_len(ctx, obj) / 2, 1, MAX_M); | |
| 1494 for (i = 0; i < func->super.m; i++) | |
| 1495 { | |
| 1496 func->domain[i][0] = pdf_array_get_real(ctx, obj, i * 2 + 0); | |
| 1497 func->domain[i][1] = pdf_array_get_real(ctx, obj, i * 2 + 1); | |
| 1498 } | |
| 1499 | |
| 1500 /* required for type0 and type4, optional otherwise */ | |
| 1501 obj = pdf_dict_get(ctx, dict, PDF_NAME(Range)); | |
| 1502 if (pdf_is_array(ctx, obj)) | |
| 1503 { | |
| 1504 func->has_range = 1; | |
| 1505 func->super.n = fz_clampi(pdf_array_len(ctx, obj) / 2, 1, MAX_N); | |
| 1506 for (i = 0; i < func->super.n; i++) | |
| 1507 { | |
| 1508 func->range[i][0] = pdf_array_get_real(ctx, obj, i * 2 + 0); | |
| 1509 func->range[i][1] = pdf_array_get_real(ctx, obj, i * 2 + 1); | |
| 1510 } | |
| 1511 } | |
| 1512 else | |
| 1513 { | |
| 1514 func->has_range = 0; | |
| 1515 func->super.n = out; | |
| 1516 } | |
| 1517 | |
| 1518 if (func->super.m != in) | |
| 1519 fz_warn(ctx, "wrong number of function inputs"); | |
| 1520 if (func->super.n != out) | |
| 1521 fz_warn(ctx, "wrong number of function outputs"); | |
| 1522 | |
| 1523 fz_try(ctx) | |
| 1524 { | |
| 1525 switch (type) | |
| 1526 { | |
| 1527 case SAMPLE: | |
| 1528 load_sample_func(ctx, func, dict); | |
| 1529 break; | |
| 1530 | |
| 1531 case EXPONENTIAL: | |
| 1532 load_exponential_func(ctx, func, dict); | |
| 1533 break; | |
| 1534 | |
| 1535 case STITCHING: | |
| 1536 load_stitching_func(ctx, func, dict, &cycle); | |
| 1537 break; | |
| 1538 | |
| 1539 case POSTSCRIPT: | |
| 1540 load_postscript_func(ctx, func, dict); | |
| 1541 break; | |
| 1542 | |
| 1543 default: | |
| 1544 fz_throw(ctx, FZ_ERROR_SYNTAX, "unknown function type (%d 0 R)", pdf_to_num(ctx, dict)); | |
| 1545 } | |
| 1546 | |
| 1547 pdf_store_item(ctx, dict, func, func->super.size); | |
| 1548 } | |
| 1549 fz_catch(ctx) | |
| 1550 { | |
| 1551 pdf_drop_function(ctx, func); | |
| 1552 fz_rethrow(ctx); | |
| 1553 } | |
| 1554 | |
| 1555 return func; | |
| 1556 } | |
| 1557 | |
| 1558 pdf_function * | |
| 1559 pdf_load_function(fz_context *ctx, pdf_obj *dict, int in, int out) | |
| 1560 { | |
| 1561 return pdf_load_function_imp(ctx, dict, in, out, NULL); | |
| 1562 } |
