Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/source/pdf/pdf-shade-recolor.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 | aa33339d6b8a |
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 | |
| 30 typedef struct | |
| 31 { | |
| 32 void *opaque; | |
| 33 pdf_recolor_vertex *recolor; | |
| 34 fz_colorspace *dst_cs; | |
| 35 fz_colorspace *src_cs; | |
| 36 int funcs; | |
| 37 } recolor_details; | |
| 38 | |
| 39 #define FUNSEGS 64 /* size of sampled mesh for function-based shadings */ | |
| 40 #define FUNBPS 8 /* Bits per sample in output functions */ | |
| 41 | |
| 42 static void | |
| 43 fz_recolor_shade_type1(fz_context *ctx, pdf_obj *shade, pdf_function **func, recolor_details *rd) | |
| 44 { | |
| 45 float x0 = 0; | |
| 46 float y0 = 0; | |
| 47 float x1 = 1; | |
| 48 float y1 = 1; | |
| 49 float in[FZ_MAX_COLORS] = { 0 }; | |
| 50 float out[(FUNSEGS+1)*(FUNSEGS+1)*FZ_MAX_COLORS]; | |
| 51 float *p; | |
| 52 float fv[2]; | |
| 53 int xx, yy; | |
| 54 pdf_obj *obj; | |
| 55 int n_in = rd->src_cs->n; | |
| 56 int n_out = rd->dst_cs->n; | |
| 57 pdf_obj *fun_obj = NULL; | |
| 58 float range[FZ_MAX_COLORS]; | |
| 59 int i; | |
| 60 pdf_document *doc = pdf_get_bound_document(ctx, shade); | |
| 61 pdf_obj *ref = NULL; | |
| 62 fz_buffer *buf = NULL; | |
| 63 fz_output *output = NULL; | |
| 64 | |
| 65 obj = pdf_dict_get(ctx, shade, PDF_NAME(Domain)); | |
| 66 if (obj) | |
| 67 { | |
| 68 x0 = pdf_array_get_real(ctx, obj, 0); | |
| 69 x1 = pdf_array_get_real(ctx, obj, 1); | |
| 70 y0 = pdf_array_get_real(ctx, obj, 2); | |
| 71 y1 = pdf_array_get_real(ctx, obj, 3); | |
| 72 } | |
| 73 | |
| 74 if (rd->funcs != 1 && rd->funcs != n_in) | |
| 75 { | |
| 76 fz_throw(ctx, FZ_ERROR_SYNTAX, "Unexpected function-arity."); | |
| 77 } | |
| 78 | |
| 79 /* Sample the function, rewriting it. */ | |
| 80 for (i = 0; i < n_out; i++) | |
| 81 { | |
| 82 range[2 * i] = FLT_MAX; | |
| 83 range[2 * i + 1] = -FLT_MAX; | |
| 84 } | |
| 85 p = out; | |
| 86 for (yy = 0; yy <= FUNSEGS; yy++) | |
| 87 { | |
| 88 fv[1] = y0 + (y1 - y0) * yy / FUNSEGS; | |
| 89 | |
| 90 for (xx = 0; xx <= FUNSEGS; xx++) | |
| 91 { | |
| 92 fv[0] = x0 + (x1 - x0) * xx / FUNSEGS; | |
| 93 | |
| 94 if (rd->funcs == 1) | |
| 95 pdf_eval_function(ctx, func[0], fv, 2, in, n_in); | |
| 96 else | |
| 97 { | |
| 98 int zz; | |
| 99 for (zz = 0; zz < n_in; zz++) | |
| 100 pdf_eval_function(ctx, func[zz], fv, 2, &in[zz], 1); | |
| 101 } | |
| 102 | |
| 103 rd->recolor(ctx, rd->opaque, rd->dst_cs, p, rd->src_cs, in); | |
| 104 | |
| 105 for (i = 0; i < n_out; i++) | |
| 106 { | |
| 107 if (range[2 * i] > p[i]) | |
| 108 range[2 * i] = p[i]; | |
| 109 if (range[2 * i + 1] < p[i]) | |
| 110 range[2 * i + 1] = p[i]; | |
| 111 } | |
| 112 p += n_out; | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 /* Now write the function out again. */ | |
| 117 fun_obj = pdf_new_dict(ctx, doc, 3); | |
| 118 pdf_dict_put_int(ctx, fun_obj, PDF_NAME(FunctionType), 0); | |
| 119 | |
| 120 /* Domain */ | |
| 121 obj = pdf_dict_put_array(ctx, fun_obj, PDF_NAME(Domain), 4); | |
| 122 pdf_array_push_real(ctx, obj, x0); | |
| 123 pdf_array_push_real(ctx, obj, x1); | |
| 124 pdf_array_push_real(ctx, obj, y0); | |
| 125 pdf_array_push_real(ctx, obj, y1); | |
| 126 | |
| 127 /* Range */ | |
| 128 obj = pdf_dict_put_array(ctx, fun_obj, PDF_NAME(Range), 4); | |
| 129 for (i = 0; i < 2*n_out; i++) | |
| 130 pdf_array_push_real(ctx, obj, range[i]); | |
| 131 | |
| 132 /* Size */ | |
| 133 obj = pdf_dict_put_array(ctx, fun_obj, PDF_NAME(Size), 2); | |
| 134 pdf_array_push_int(ctx, obj, FUNSEGS+1); | |
| 135 pdf_array_push_int(ctx, obj, FUNSEGS+1); | |
| 136 | |
| 137 /* BitsPerSample */ | |
| 138 pdf_dict_put_int(ctx, fun_obj, PDF_NAME(BitsPerSample), FUNBPS); | |
| 139 | |
| 140 buf = fz_new_buffer(ctx, 1); | |
| 141 output = fz_new_output_with_buffer(ctx, buf); | |
| 142 | |
| 143 p = out; | |
| 144 for (yy = 0; yy <= FUNSEGS; yy++) | |
| 145 { | |
| 146 for (xx = 0; xx <= FUNSEGS; xx++) | |
| 147 { | |
| 148 for (i = 0; i < n_out; i++) | |
| 149 { | |
| 150 float v = p[i]; | |
| 151 float d = range[2 * i + 1] - range[2 * i]; | |
| 152 int iv; | |
| 153 | |
| 154 v -= range[2 * i]; | |
| 155 if (d != 0) | |
| 156 v = v * ((1<<FUNBPS)-1) / d; | |
| 157 iv = (int)(v + 0.5f); | |
| 158 fz_write_bits(ctx, output, iv, FUNBPS); | |
| 159 } | |
| 160 p += n_out; | |
| 161 } | |
| 162 } | |
| 163 fz_write_bits_sync(ctx, output); | |
| 164 fz_close_output(ctx, output); | |
| 165 fz_drop_output(ctx, output); | |
| 166 | |
| 167 ref = pdf_add_object(ctx, doc, fun_obj); | |
| 168 pdf_update_stream(ctx, doc, ref, buf, 0); | |
| 169 fz_drop_buffer(ctx, buf); | |
| 170 pdf_dict_put(ctx, shade, PDF_NAME(Function), ref); | |
| 171 } | |
| 172 | |
| 173 static void | |
| 174 fz_recolor_shade_function(fz_context *ctx, pdf_obj *shade, float *samples, int stride, recolor_details *rd) | |
| 175 { | |
| 176 int i; | |
| 177 int n_in = fz_colorspace_n(ctx, rd->src_cs); | |
| 178 int n_out = fz_colorspace_n(ctx, rd->dst_cs); | |
| 179 float localp[256*FZ_MAX_COLORS]; | |
| 180 float *q = localp; | |
| 181 float p[FZ_MAX_COLORS]; | |
| 182 pdf_obj *fun_obj = NULL; | |
| 183 pdf_document *doc = pdf_get_bound_document(ctx, shade); | |
| 184 pdf_obj *obj; | |
| 185 float t0 = 0; | |
| 186 float t1 = 1; | |
| 187 float range[FZ_MAX_COLORS]; | |
| 188 pdf_obj *ref = NULL; | |
| 189 fz_buffer *buf = NULL; | |
| 190 fz_output *output = NULL; | |
| 191 int t; | |
| 192 | |
| 193 obj = pdf_dict_get(ctx, shade, PDF_NAME(Domain)); | |
| 194 if (obj) | |
| 195 { | |
| 196 t0 = pdf_array_get_real(ctx, obj, 0); | |
| 197 t1 = pdf_array_get_real(ctx, obj, 1); | |
| 198 } | |
| 199 | |
| 200 for (i = 0; i < n_out; i++) | |
| 201 { | |
| 202 range[2 * i] = FLT_MAX; | |
| 203 range[2 * i + 1] = -FLT_MAX; | |
| 204 } | |
| 205 for (t = 0; t < 256; t++) | |
| 206 { | |
| 207 for (i = 0; i < n_in; i++) | |
| 208 p[i] = samples[t*stride+i]; | |
| 209 | |
| 210 rd->recolor(ctx, rd->opaque, rd->dst_cs, q, rd->src_cs, p); | |
| 211 | |
| 212 for (i = 0; i < n_out; i++) | |
| 213 { | |
| 214 if (range[2 * i] > q[i]) | |
| 215 range[2 * i] = q[i]; | |
| 216 if (range[2 * i + 1] < q[i]) | |
| 217 range[2 * i + 1] = q[i]; | |
| 218 } | |
| 219 q += n_out; | |
| 220 } | |
| 221 | |
| 222 fz_var(ref); | |
| 223 fz_var(output); | |
| 224 | |
| 225 /* Now write the function out again. */ | |
| 226 fun_obj = pdf_new_dict(ctx, doc, 3); | |
| 227 fz_try(ctx) | |
| 228 { | |
| 229 pdf_dict_put_int(ctx, fun_obj, PDF_NAME(FunctionType), 0); | |
| 230 | |
| 231 /* Domain */ | |
| 232 obj = pdf_dict_put_array(ctx, fun_obj, PDF_NAME(Domain), 2); | |
| 233 pdf_array_push_real(ctx, obj, t0); | |
| 234 pdf_array_push_real(ctx, obj, t1); | |
| 235 | |
| 236 /* Range */ | |
| 237 obj = pdf_dict_put_array(ctx, fun_obj, PDF_NAME(Range), 2 * n_out); | |
| 238 for (i = 0; i < 2 * n_out; i++) | |
| 239 pdf_array_push_real(ctx, obj, range[i]); | |
| 240 | |
| 241 obj = pdf_dict_put_array(ctx, fun_obj, PDF_NAME(Size), 1); | |
| 242 pdf_array_push_int(ctx, obj, 256); | |
| 243 | |
| 244 pdf_dict_put_int(ctx, fun_obj, PDF_NAME(BitsPerSample), FUNBPS); | |
| 245 | |
| 246 buf = fz_new_buffer(ctx, 1); | |
| 247 output = fz_new_output_with_buffer(ctx, buf); | |
| 248 | |
| 249 q = localp; | |
| 250 for (t = 0; t < 256; t++) | |
| 251 { | |
| 252 for (i = 0; i < n_out; i++) | |
| 253 { | |
| 254 float v = q[i]; | |
| 255 float d = range[2 * i + 1] - range[2 * i]; | |
| 256 int iv; | |
| 257 | |
| 258 v -= range[2 * i]; | |
| 259 if (d != 0) | |
| 260 v = v * ((1<<FUNBPS)-1) / d; | |
| 261 iv = (int)(v + 0.5f); | |
| 262 fz_write_bits(ctx, output, iv, FUNBPS); | |
| 263 } | |
| 264 q += n_out; | |
| 265 } | |
| 266 fz_write_bits_sync(ctx, output); | |
| 267 fz_close_output(ctx, output); | |
| 268 | |
| 269 ref = pdf_add_object(ctx, doc, fun_obj); | |
| 270 pdf_update_stream(ctx, doc, ref, buf, 0); | |
| 271 pdf_dict_put(ctx, shade, PDF_NAME(Function), ref); | |
| 272 } | |
| 273 fz_always(ctx) | |
| 274 { | |
| 275 fz_drop_output(ctx, output); | |
| 276 fz_drop_buffer(ctx, buf); | |
| 277 pdf_drop_obj(ctx, fun_obj); | |
| 278 pdf_drop_obj(ctx, ref); | |
| 279 } | |
| 280 fz_catch(ctx) | |
| 281 fz_rethrow(ctx); | |
| 282 } | |
| 283 | |
| 284 static inline float read_sample(fz_context *ctx, fz_stream *stream, int bits, float min, float max) | |
| 285 { | |
| 286 /* we use pow(2,x) because (1<<x) would overflow the math on 32-bit samples */ | |
| 287 float bitscale = 1 / (powf(2, bits) - 1); | |
| 288 return min + fz_read_bits(ctx, stream, bits) * (max - min) * bitscale; | |
| 289 } | |
| 290 | |
| 291 static inline void write_sample(fz_context *ctx, fz_output *out, int bits, float min, float max, float val) | |
| 292 { | |
| 293 /* we use pow(2,x) because (1<<x) would overflow the math on 32-bit samples */ | |
| 294 float bitscale = (powf(2, bits) - 1); | |
| 295 if (val < min) | |
| 296 val = min; | |
| 297 else if (val > max) | |
| 298 val = max; | |
| 299 val -= min; | |
| 300 if (max != min) | |
| 301 val /= (max - min); | |
| 302 /* Now 0 <= val <= 1 */ | |
| 303 fz_write_bits(ctx, out, (int)(val * bitscale), bits); | |
| 304 } | |
| 305 | |
| 306 typedef struct | |
| 307 { | |
| 308 float *p; | |
| 309 int len; | |
| 310 int max; | |
| 311 int pos; | |
| 312 } float_queue; | |
| 313 | |
| 314 static void | |
| 315 float_queue_push(fz_context *ctx, float_queue *p, float f) | |
| 316 { | |
| 317 if (p->len == p->max) | |
| 318 { | |
| 319 int new_max = p->max * 2; | |
| 320 if (new_max == 0) | |
| 321 new_max = 32; | |
| 322 p->p = fz_realloc(ctx, p->p, sizeof(float) * new_max); | |
| 323 p->max = new_max; | |
| 324 } | |
| 325 p->p[p->len++] = f; | |
| 326 } | |
| 327 | |
| 328 static float | |
| 329 float_queue_pop(fz_context *ctx, float_queue *p) | |
| 330 { | |
| 331 return p->p[p->pos++]; | |
| 332 } | |
| 333 | |
| 334 static void | |
| 335 float_queue_drop(fz_context *ctx, float_queue *p) | |
| 336 { | |
| 337 fz_free(ctx, p->p); | |
| 338 } | |
| 339 | |
| 340 static void | |
| 341 read_decode(fz_context *ctx, pdf_obj *shade, int n_in, float *c_min, float *c_max, int n_out, float *d_min, float *d_max) | |
| 342 { | |
| 343 int i; | |
| 344 pdf_obj *obj = pdf_dict_get(ctx, shade, PDF_NAME(Decode)); | |
| 345 | |
| 346 for (i = 0; i < n_in; i++) | |
| 347 { | |
| 348 c_min[i] = pdf_array_get_int(ctx, obj, 2 * i + 4); | |
| 349 c_max[i] = pdf_array_get_int(ctx, obj, 2 * i + 5); | |
| 350 } | |
| 351 for (i = 0; i < n_out; i++) | |
| 352 { | |
| 353 d_min[i] = FLT_MAX; | |
| 354 d_max[i] = -FLT_MAX; | |
| 355 } | |
| 356 } | |
| 357 | |
| 358 static void | |
| 359 rewrite_decode(fz_context *ctx, pdf_obj *shade, int n_out, float *d_min, float *d_max) | |
| 360 { | |
| 361 int i; | |
| 362 pdf_obj *obj = pdf_keep_obj(ctx, pdf_dict_get(ctx, shade, PDF_NAME(Decode))); | |
| 363 pdf_obj *obj2; | |
| 364 | |
| 365 fz_try(ctx) | |
| 366 { | |
| 367 obj2 = pdf_dict_put_array(ctx, shade, PDF_NAME(Decode), 4); | |
| 368 | |
| 369 for (i = 0; i < 4; i++) | |
| 370 { | |
| 371 pdf_array_push(ctx, obj2, pdf_array_get(ctx, obj, i)); | |
| 372 } | |
| 373 for (i = 0; i < n_out; i++) | |
| 374 { | |
| 375 pdf_array_push_real(ctx, obj2, d_min[i]); | |
| 376 pdf_array_push_real(ctx, obj2, d_max[i]); | |
| 377 } | |
| 378 } | |
| 379 fz_always(ctx) | |
| 380 pdf_drop_obj(ctx, obj); | |
| 381 fz_catch(ctx) | |
| 382 fz_rethrow(ctx); | |
| 383 } | |
| 384 | |
| 385 static void | |
| 386 fz_recolor_shade_type4(fz_context *ctx, pdf_obj *shade, recolor_details *rd) | |
| 387 { | |
| 388 fz_stream *stream; | |
| 389 int i, n_in = rd->src_cs->n; | |
| 390 int n_out = rd->dst_cs->n; | |
| 391 int bpflag = pdf_dict_get_int(ctx, shade, PDF_NAME(BitsPerFlag)); | |
| 392 int bpcoord = pdf_dict_get_int(ctx, shade, PDF_NAME(BitsPerCoordinate)); | |
| 393 int bpcomp = pdf_dict_get_int(ctx, shade, PDF_NAME(BitsPerComponent)); | |
| 394 pdf_document *doc = pdf_get_bound_document(ctx, shade); | |
| 395 float c[FZ_MAX_COLORS]; | |
| 396 float d[FZ_MAX_COLORS]; | |
| 397 float c_min[FZ_MAX_COLORS]; | |
| 398 float c_max[FZ_MAX_COLORS]; | |
| 399 float d_min[FZ_MAX_COLORS]; | |
| 400 float d_max[FZ_MAX_COLORS]; | |
| 401 fz_buffer *outbuf = NULL; | |
| 402 fz_output *out = NULL; | |
| 403 float_queue fq = { 0 }; | |
| 404 | |
| 405 fz_var(outbuf); | |
| 406 fz_var(out); | |
| 407 fz_var(stream); | |
| 408 | |
| 409 read_decode(ctx, shade, n_in, c_min, c_max, n_out, d_min, d_max); | |
| 410 | |
| 411 stream = pdf_open_stream(ctx, shade); | |
| 412 fz_try(ctx) | |
| 413 { | |
| 414 while (!fz_is_eof_bits(ctx, stream)) | |
| 415 { | |
| 416 /* flag */ (void)fz_read_bits(ctx, stream, bpflag); | |
| 417 /* x_bits */ (void)fz_read_bits(ctx, stream, bpcoord); | |
| 418 /* y_bits */ (void)fz_read_bits(ctx, stream, bpcoord); | |
| 419 for (i = 0; i < n_in; i++) | |
| 420 c[i] = read_sample(ctx, stream, bpcomp, c_min[i], c_max[i]); | |
| 421 | |
| 422 rd->recolor(ctx, rd->opaque, rd->dst_cs, d, rd->src_cs, c); | |
| 423 | |
| 424 for (i = 0; i < n_out; i++) | |
| 425 { | |
| 426 if (d[i] < d_min[i]) | |
| 427 d_min[i] = d[i]; | |
| 428 if (d[i] > d_max[i]) | |
| 429 d_max[i] = d[i]; | |
| 430 float_queue_push(ctx, &fq, d[i]); | |
| 431 } | |
| 432 } | |
| 433 fz_drop_stream(ctx, stream); | |
| 434 stream = NULL; | |
| 435 | |
| 436 rewrite_decode(ctx, shade, n_out, d_min, d_max); | |
| 437 | |
| 438 stream = pdf_open_stream(ctx, shade); | |
| 439 outbuf = fz_new_buffer(ctx, 1); | |
| 440 out = fz_new_output_with_buffer(ctx, outbuf); | |
| 441 while (!fz_is_eof_bits(ctx, stream)) | |
| 442 { | |
| 443 unsigned int flag = fz_read_bits(ctx, stream, bpflag); | |
| 444 unsigned int x_bits = fz_read_bits(ctx, stream, bpcoord); | |
| 445 unsigned int y_bits = fz_read_bits(ctx, stream, bpcoord); | |
| 446 for (i = 0; i < n_in; i++) | |
| 447 (void)fz_read_bits(ctx, stream, bpcomp); | |
| 448 | |
| 449 fz_write_bits(ctx, out, flag, bpflag); | |
| 450 fz_write_bits(ctx, out, x_bits, bpcoord); | |
| 451 fz_write_bits(ctx, out, y_bits, bpcoord); | |
| 452 | |
| 453 for (i = 0; i < n_out; i++) | |
| 454 { | |
| 455 float f = float_queue_pop(ctx, &fq); | |
| 456 write_sample(ctx, out, 8, d_min[i], d_max[i], f); | |
| 457 } | |
| 458 } | |
| 459 fz_write_bits_sync(ctx, out); | |
| 460 fz_close_output(ctx, out); | |
| 461 | |
| 462 pdf_dict_put_int(ctx, shade, PDF_NAME(BitsPerComponent), 8); | |
| 463 | |
| 464 pdf_update_stream(ctx, doc, shade, outbuf, 0); | |
| 465 } | |
| 466 fz_always(ctx) | |
| 467 { | |
| 468 float_queue_drop(ctx, &fq); | |
| 469 fz_drop_stream(ctx, stream); | |
| 470 fz_drop_output(ctx, out); | |
| 471 fz_drop_buffer(ctx, outbuf); | |
| 472 } | |
| 473 fz_catch(ctx) | |
| 474 { | |
| 475 fz_rethrow(ctx); | |
| 476 } | |
| 477 } | |
| 478 | |
| 479 static void | |
| 480 fz_recolor_shade_type5(fz_context *ctx, pdf_obj *shade, recolor_details *rd) | |
| 481 { | |
| 482 fz_stream *stream; | |
| 483 int i, k, n_in = rd->src_cs->n; | |
| 484 int n_out = rd->dst_cs->n; | |
| 485 int bpcoord = pdf_dict_get_int(ctx, shade, PDF_NAME(BitsPerCoordinate)); | |
| 486 int bpcomp = pdf_dict_get_int(ctx, shade, PDF_NAME(BitsPerComponent)); | |
| 487 int vprow = pdf_dict_get_int(ctx, shade, PDF_NAME(VerticesPerRow)); | |
| 488 pdf_document *doc = pdf_get_bound_document(ctx, shade); | |
| 489 float c[FZ_MAX_COLORS]; | |
| 490 float d[FZ_MAX_COLORS]; | |
| 491 float c_min[FZ_MAX_COLORS]; | |
| 492 float c_max[FZ_MAX_COLORS]; | |
| 493 float d_min[FZ_MAX_COLORS]; | |
| 494 float d_max[FZ_MAX_COLORS]; | |
| 495 fz_buffer *outbuf = NULL; | |
| 496 fz_output *out = NULL; | |
| 497 float_queue fq = { 0 }; | |
| 498 | |
| 499 fz_var(outbuf); | |
| 500 fz_var(out); | |
| 501 fz_var(stream); | |
| 502 | |
| 503 read_decode(ctx, shade, n_in, c_min, c_max, n_out, d_min, d_max); | |
| 504 | |
| 505 stream = pdf_open_stream(ctx, shade); | |
| 506 fz_try(ctx) | |
| 507 { | |
| 508 while (!fz_is_eof_bits(ctx, stream)) | |
| 509 { | |
| 510 for (i = 0; i < vprow; i++) | |
| 511 { | |
| 512 /* x_bits */ (void)fz_read_bits(ctx, stream, bpcoord); | |
| 513 /* y_bits */ (void)fz_read_bits(ctx, stream, bpcoord); | |
| 514 for (k = 0; k < n_in; k++) | |
| 515 c[k] = read_sample(ctx, stream, bpcomp, c_min[k], c_max[k]); | |
| 516 | |
| 517 rd->recolor(ctx, rd->opaque, rd->dst_cs, d, rd->src_cs, c); | |
| 518 | |
| 519 for (k = 0; k < n_out; k++) | |
| 520 { | |
| 521 if (d[k] < d_min[k]) | |
| 522 d_min[k] = d[k]; | |
| 523 if (d[k] > d_max[k]) | |
| 524 d_max[k] = d[k]; | |
| 525 float_queue_push(ctx, &fq, d[k]); | |
| 526 } | |
| 527 } | |
| 528 } | |
| 529 fz_drop_stream(ctx, stream); | |
| 530 stream = NULL; | |
| 531 | |
| 532 rewrite_decode(ctx, shade, n_out, d_min, d_max); | |
| 533 | |
| 534 stream = pdf_open_stream(ctx, shade); | |
| 535 outbuf = fz_new_buffer(ctx, 1); | |
| 536 out = fz_new_output_with_buffer(ctx, outbuf); | |
| 537 while (!fz_is_eof_bits(ctx, stream)) | |
| 538 { | |
| 539 for (i = 0; i < vprow; i++) | |
| 540 { | |
| 541 unsigned int x_bits = fz_read_bits(ctx, stream, bpcoord); | |
| 542 unsigned int y_bits = fz_read_bits(ctx, stream, bpcoord); | |
| 543 for (k = 0; k < n_in; k++) | |
| 544 (void)fz_read_bits(ctx, stream, bpcomp); | |
| 545 | |
| 546 fz_write_bits(ctx, out, x_bits, bpcoord); | |
| 547 fz_write_bits(ctx, out, y_bits, bpcoord); | |
| 548 for (k = 0; k < n_out; k++) | |
| 549 { | |
| 550 float f = float_queue_pop(ctx, &fq); | |
| 551 write_sample(ctx, out, 8, d_min[k], d_max[k], f); | |
| 552 } | |
| 553 } | |
| 554 } | |
| 555 fz_write_bits_sync(ctx, out); | |
| 556 fz_close_output(ctx, out); | |
| 557 | |
| 558 pdf_dict_put_int(ctx, shade, PDF_NAME(BitsPerComponent), 8); | |
| 559 | |
| 560 pdf_update_stream(ctx, doc, shade, outbuf, 0); | |
| 561 } | |
| 562 fz_always(ctx) | |
| 563 { | |
| 564 float_queue_drop(ctx, &fq); | |
| 565 fz_drop_stream(ctx, stream); | |
| 566 fz_drop_output(ctx, out); | |
| 567 fz_drop_buffer(ctx, outbuf); | |
| 568 } | |
| 569 fz_catch(ctx) | |
| 570 { | |
| 571 fz_rethrow(ctx); | |
| 572 } | |
| 573 } | |
| 574 | |
| 575 static void | |
| 576 fz_recolor_shade_type6(fz_context *ctx, pdf_obj *shade, recolor_details *rd) | |
| 577 { | |
| 578 fz_stream *stream; | |
| 579 int i, k, n_in = rd->src_cs->n; | |
| 580 int n_out = rd->dst_cs->n; | |
| 581 int bpflag = pdf_dict_get_int(ctx, shade, PDF_NAME(BitsPerFlag)); | |
| 582 int bpcoord = pdf_dict_get_int(ctx, shade, PDF_NAME(BitsPerCoordinate)); | |
| 583 int bpcomp = pdf_dict_get_int(ctx, shade, PDF_NAME(BitsPerComponent)); | |
| 584 pdf_document *doc = pdf_get_bound_document(ctx, shade); | |
| 585 float c[FZ_MAX_COLORS]; | |
| 586 float d[FZ_MAX_COLORS]; | |
| 587 float c_min[FZ_MAX_COLORS]; | |
| 588 float c_max[FZ_MAX_COLORS]; | |
| 589 float d_min[FZ_MAX_COLORS]; | |
| 590 float d_max[FZ_MAX_COLORS]; | |
| 591 fz_buffer *outbuf = NULL; | |
| 592 fz_output *out = NULL; | |
| 593 float_queue fq = { 0 }; | |
| 594 | |
| 595 fz_var(outbuf); | |
| 596 fz_var(out); | |
| 597 fz_var(stream); | |
| 598 | |
| 599 read_decode(ctx, shade, n_in, c_min, c_max, n_out, d_min, d_max); | |
| 600 | |
| 601 stream = pdf_open_stream(ctx, shade); | |
| 602 fz_try(ctx) | |
| 603 { | |
| 604 while (!fz_is_eof_bits(ctx, stream)) | |
| 605 { | |
| 606 int startcolor; | |
| 607 int startpt; | |
| 608 | |
| 609 int flag = fz_read_bits(ctx, stream, bpflag); | |
| 610 | |
| 611 if (flag == 0) | |
| 612 { | |
| 613 startpt = 0; | |
| 614 startcolor = 0; | |
| 615 } | |
| 616 else | |
| 617 { | |
| 618 startpt = 4; | |
| 619 startcolor = 2; | |
| 620 } | |
| 621 | |
| 622 for (i = startpt; i < 12; i++) | |
| 623 { | |
| 624 unsigned int x_bits = fz_read_bits(ctx, stream, bpcoord); | |
| 625 unsigned int y_bits = fz_read_bits(ctx, stream, bpcoord); | |
| 626 fz_write_bits(ctx, out, x_bits, bpcoord); | |
| 627 fz_write_bits(ctx, out, y_bits, bpcoord); | |
| 628 } | |
| 629 | |
| 630 for (i = startcolor; i < 4; i++) | |
| 631 { | |
| 632 for (k = 0; k < n_in; k++) | |
| 633 c[k] = read_sample(ctx, stream, bpcomp, c_min[k], c_max[k]); | |
| 634 | |
| 635 rd->recolor(ctx, rd->opaque, rd->dst_cs, d, rd->src_cs, c); | |
| 636 | |
| 637 for (k = 0; k < n_out; k++) | |
| 638 { | |
| 639 if (d[k] < d_min[k]) | |
| 640 d_min[k] = d[k]; | |
| 641 if (d[k] > d_max[k]) | |
| 642 d_max[k] = d[k]; | |
| 643 float_queue_push(ctx, &fq, d[k]); | |
| 644 } | |
| 645 } | |
| 646 } | |
| 647 fz_drop_stream(ctx, stream); | |
| 648 stream = NULL; | |
| 649 | |
| 650 rewrite_decode(ctx, shade, n_out, d_min, d_max); | |
| 651 | |
| 652 stream = pdf_open_stream(ctx, shade); | |
| 653 outbuf = fz_new_buffer(ctx, 1); | |
| 654 out = fz_new_output_with_buffer(ctx, outbuf); | |
| 655 while (!fz_is_eof_bits(ctx, stream)) | |
| 656 { | |
| 657 int startcolor; | |
| 658 int startpt; | |
| 659 | |
| 660 int flag = fz_read_bits(ctx, stream, bpflag); | |
| 661 | |
| 662 fz_write_bits(ctx, out, flag, bpflag); | |
| 663 | |
| 664 if (flag == 0) | |
| 665 { | |
| 666 startpt = 0; | |
| 667 startcolor = 0; | |
| 668 } | |
| 669 else | |
| 670 { | |
| 671 startpt = 4; | |
| 672 startcolor = 2; | |
| 673 } | |
| 674 | |
| 675 for (i = startpt; i < 12; i++) | |
| 676 { | |
| 677 unsigned int x_bits = fz_read_bits(ctx, stream, bpcoord); | |
| 678 unsigned int y_bits = fz_read_bits(ctx, stream, bpcoord); | |
| 679 fz_write_bits(ctx, out, x_bits, bpcoord); | |
| 680 fz_write_bits(ctx, out, y_bits, bpcoord); | |
| 681 } | |
| 682 | |
| 683 for (i = startcolor; i < 4; i++) | |
| 684 { | |
| 685 for (k = 0; k < n_in; k++) | |
| 686 (void)fz_read_bits(ctx, stream, bpcomp); | |
| 687 | |
| 688 for (k = 0; k < n_out; k++) | |
| 689 { | |
| 690 float f = float_queue_pop(ctx, &fq); | |
| 691 write_sample(ctx, out, 8, d_min[k], d_max[k], f); | |
| 692 } | |
| 693 } | |
| 694 } | |
| 695 fz_write_bits_sync(ctx, out); | |
| 696 fz_close_output(ctx, out); | |
| 697 | |
| 698 pdf_dict_put_int(ctx, shade, PDF_NAME(BitsPerComponent), 8); | |
| 699 | |
| 700 pdf_update_stream(ctx, doc, shade, outbuf, 0); | |
| 701 } | |
| 702 fz_always(ctx) | |
| 703 { | |
| 704 float_queue_drop(ctx, &fq); | |
| 705 fz_drop_stream(ctx, stream); | |
| 706 fz_drop_output(ctx, out); | |
| 707 fz_drop_buffer(ctx, outbuf); | |
| 708 } | |
| 709 fz_catch(ctx) | |
| 710 { | |
| 711 fz_rethrow(ctx); | |
| 712 } | |
| 713 } | |
| 714 | |
| 715 static void | |
| 716 fz_recolor_shade_type7(fz_context *ctx, pdf_obj *shade, recolor_details *rd) | |
| 717 { | |
| 718 fz_stream *stream; | |
| 719 int i, k, n_in = rd->src_cs->n; | |
| 720 int n_out = rd->dst_cs->n; | |
| 721 int bpflag = pdf_dict_get_int(ctx, shade, PDF_NAME(BitsPerFlag)); | |
| 722 int bpcoord = pdf_dict_get_int(ctx, shade, PDF_NAME(BitsPerCoordinate)); | |
| 723 int bpcomp = pdf_dict_get_int(ctx, shade, PDF_NAME(BitsPerComponent)); | |
| 724 pdf_document *doc = pdf_get_bound_document(ctx, shade); | |
| 725 float c[FZ_MAX_COLORS]; | |
| 726 float d[FZ_MAX_COLORS]; | |
| 727 float c_min[FZ_MAX_COLORS]; | |
| 728 float c_max[FZ_MAX_COLORS]; | |
| 729 float d_min[FZ_MAX_COLORS]; | |
| 730 float d_max[FZ_MAX_COLORS]; | |
| 731 fz_buffer *outbuf = NULL; | |
| 732 fz_output *out = NULL; | |
| 733 float_queue fq = { 0 }; | |
| 734 | |
| 735 fz_var(outbuf); | |
| 736 fz_var(out); | |
| 737 fz_var(stream); | |
| 738 | |
| 739 read_decode(ctx, shade, n_in, c_min, c_max, n_out, d_min, d_max); | |
| 740 | |
| 741 stream = pdf_open_stream(ctx, shade); | |
| 742 fz_try(ctx) | |
| 743 { | |
| 744 while (!fz_is_eof_bits(ctx, stream)) | |
| 745 { | |
| 746 int startcolor; | |
| 747 int startpt; | |
| 748 | |
| 749 int flag = fz_read_bits(ctx, stream, bpflag); | |
| 750 | |
| 751 if (flag == 0) | |
| 752 { | |
| 753 startpt = 0; | |
| 754 startcolor = 0; | |
| 755 } | |
| 756 else | |
| 757 { | |
| 758 startpt = 4; | |
| 759 startcolor = 2; | |
| 760 } | |
| 761 | |
| 762 for (i = startpt; i < 16; i++) | |
| 763 { | |
| 764 /* x_bits */ (void)fz_read_bits(ctx, stream, bpcoord); | |
| 765 /* y_bits */ (void)fz_read_bits(ctx, stream, bpcoord); | |
| 766 } | |
| 767 | |
| 768 for (i = startcolor; i < 4; i++) | |
| 769 { | |
| 770 for (k = 0; k < n_in; k++) | |
| 771 c[k] = read_sample(ctx, stream, bpcomp, c_min[k], c_max[k]); | |
| 772 | |
| 773 rd->recolor(ctx, rd->opaque, rd->dst_cs, d, rd->src_cs, c); | |
| 774 | |
| 775 for (k = 0; k < n_out; k++) | |
| 776 { | |
| 777 if (d[k] < d_min[k]) | |
| 778 d_min[k] = d[k]; | |
| 779 if (d[k] > d_max[k]) | |
| 780 d_max[k] = d[k]; | |
| 781 float_queue_push(ctx, &fq, d[k]); | |
| 782 } | |
| 783 } | |
| 784 } | |
| 785 fz_drop_stream(ctx, stream); | |
| 786 stream = NULL; | |
| 787 | |
| 788 rewrite_decode(ctx, shade, n_out, d_min, d_max); | |
| 789 | |
| 790 stream = pdf_open_stream(ctx, shade); | |
| 791 outbuf = fz_new_buffer(ctx, 1); | |
| 792 out = fz_new_output_with_buffer(ctx, outbuf); | |
| 793 while (!fz_is_eof_bits(ctx, stream)) | |
| 794 { | |
| 795 int startcolor; | |
| 796 int startpt; | |
| 797 | |
| 798 int flag = fz_read_bits(ctx, stream, bpflag); | |
| 799 | |
| 800 fz_write_bits(ctx, out, flag, bpflag); | |
| 801 | |
| 802 if (flag == 0) | |
| 803 { | |
| 804 startpt = 0; | |
| 805 startcolor = 0; | |
| 806 } | |
| 807 else | |
| 808 { | |
| 809 startpt = 4; | |
| 810 startcolor = 2; | |
| 811 } | |
| 812 | |
| 813 for (i = startpt; i < 16; i++) | |
| 814 { | |
| 815 unsigned int x_bits = fz_read_bits(ctx, stream, bpcoord); | |
| 816 unsigned int y_bits = fz_read_bits(ctx, stream, bpcoord); | |
| 817 fz_write_bits(ctx, out, x_bits, bpcoord); | |
| 818 fz_write_bits(ctx, out, y_bits, bpcoord); | |
| 819 } | |
| 820 | |
| 821 for (i = startcolor; i < 4; i++) | |
| 822 { | |
| 823 for (k = 0; k < n_in; k++) | |
| 824 (void)fz_read_bits(ctx, stream, bpcomp); | |
| 825 | |
| 826 for (k = 0; k < n_out; k++) | |
| 827 { | |
| 828 float f = float_queue_pop(ctx, &fq); | |
| 829 write_sample(ctx, out, 8, d_min[k], d_max[k], f); | |
| 830 } | |
| 831 } | |
| 832 | |
| 833 } | |
| 834 fz_write_bits_sync(ctx, out); | |
| 835 fz_close_output(ctx, out); | |
| 836 | |
| 837 pdf_dict_put_int(ctx, shade, PDF_NAME(BitsPerComponent), 8); | |
| 838 | |
| 839 pdf_update_stream(ctx, doc, shade, outbuf, 0); | |
| 840 } | |
| 841 fz_always(ctx) | |
| 842 { | |
| 843 float_queue_drop(ctx, &fq); | |
| 844 fz_drop_stream(ctx, stream); | |
| 845 fz_drop_output(ctx, out); | |
| 846 fz_drop_buffer(ctx, outbuf); | |
| 847 } | |
| 848 fz_catch(ctx) | |
| 849 { | |
| 850 fz_rethrow(ctx); | |
| 851 } | |
| 852 } | |
| 853 | |
| 854 pdf_obj * | |
| 855 pdf_new_colorspace(fz_context *ctx, fz_colorspace *cs) | |
| 856 { | |
| 857 switch (fz_colorspace_type(ctx, cs)) | |
| 858 { | |
| 859 case FZ_COLORSPACE_GRAY: | |
| 860 return PDF_NAME(DeviceGray); | |
| 861 case FZ_COLORSPACE_RGB: | |
| 862 return PDF_NAME(DeviceRGB); | |
| 863 case FZ_COLORSPACE_CMYK: | |
| 864 return PDF_NAME(DeviceCMYK); | |
| 865 default: | |
| 866 fz_throw(ctx, FZ_ERROR_ARGUMENT, "Unimplemented colorspace"); | |
| 867 } | |
| 868 } | |
| 869 | |
| 870 pdf_obj * | |
| 871 pdf_recolor_shade(fz_context *ctx, pdf_obj *shade, pdf_shade_recolorer *reshade, void *opaque) | |
| 872 { | |
| 873 recolor_details rd; | |
| 874 fz_colorspace *src_cs; | |
| 875 pdf_obj *background, *new_bg = NULL; | |
| 876 pdf_obj *function; | |
| 877 pdf_obj *rewritten = NULL; | |
| 878 pdf_obj *obj; | |
| 879 int type, i; | |
| 880 pdf_function *func[FZ_MAX_COLORS] = { NULL }; | |
| 881 float d0, d1; | |
| 882 float samples[256*(FZ_MAX_COLORS + 1)]; | |
| 883 pdf_document *doc = pdf_get_bound_document(ctx, shade); | |
| 884 | |
| 885 src_cs = pdf_load_colorspace(ctx, pdf_dict_get(ctx, shade, PDF_NAME(ColorSpace))); | |
| 886 | |
| 887 fz_var(rewritten); | |
| 888 | |
| 889 rd.funcs = 0; | |
| 890 | |
| 891 fz_try(ctx) | |
| 892 { | |
| 893 rd.recolor = reshade(ctx, opaque, src_cs, &rd.dst_cs); | |
| 894 if (rd.recolor == NULL) | |
| 895 break; | |
| 896 | |
| 897 rd.src_cs = src_cs; | |
| 898 rd.opaque = opaque; | |
| 899 | |
| 900 rewritten = pdf_deep_copy_obj(ctx, shade); | |
| 901 | |
| 902 type = pdf_dict_get_int(ctx, shade, PDF_NAME(ShadingType)); | |
| 903 | |
| 904 pdf_dict_put_drop(ctx, rewritten, PDF_NAME(ColorSpace), pdf_new_colorspace(ctx, rd.dst_cs)); | |
| 905 | |
| 906 background = pdf_dict_get(ctx, shade, PDF_NAME(Background)); | |
| 907 if (background) | |
| 908 { | |
| 909 int n = pdf_array_len(ctx, background); | |
| 910 float bg[FZ_MAX_COLORS]; | |
| 911 float nbg[FZ_MAX_COLORS]; | |
| 912 | |
| 913 if (n > FZ_MAX_COLORS) | |
| 914 fz_throw(ctx, FZ_ERROR_SYNTAX, "Too many background components"); | |
| 915 if (n != src_cs->n) | |
| 916 fz_throw(ctx, FZ_ERROR_SYNTAX, "Wrong background dimension"); | |
| 917 | |
| 918 for (i = 0; i < n; i++) | |
| 919 bg[i] = pdf_array_get_real(ctx, background, i); | |
| 920 | |
| 921 rd.recolor(ctx, rd.opaque, rd.dst_cs, nbg, src_cs, bg); | |
| 922 | |
| 923 new_bg = pdf_dict_put_array(ctx, rewritten, PDF_NAME(Background), rd.dst_cs->n); | |
| 924 for (i = 0; i < n; i++) | |
| 925 pdf_array_put_real(ctx, new_bg, i, bg[i]); | |
| 926 pdf_dict_put(ctx, rewritten, PDF_NAME(Background), new_bg); | |
| 927 } | |
| 928 | |
| 929 d0 = 0; | |
| 930 d1 = 1; | |
| 931 obj = pdf_dict_get(ctx, shade, PDF_NAME(Domain)); | |
| 932 if (obj) | |
| 933 { | |
| 934 d0 = pdf_array_get_real(ctx, obj, 0); | |
| 935 d1 = pdf_array_get_real(ctx, obj, 1); | |
| 936 } | |
| 937 | |
| 938 function = pdf_dict_get(ctx, shade, PDF_NAME(Function)); | |
| 939 if (pdf_is_dict(ctx, function)) | |
| 940 { | |
| 941 rd.funcs = 1; | |
| 942 func[0] = pdf_load_function(ctx, function, type == 1 ? 2 : 1, src_cs->n); | |
| 943 if (!func[0]) | |
| 944 fz_throw(ctx, FZ_ERROR_SYNTAX, "cannot load shading function (%d 0 R)", pdf_to_num(ctx, obj)); | |
| 945 | |
| 946 if (type != 1) | |
| 947 pdf_sample_shade_function(ctx, samples, src_cs->n, 1, func, d0, d1); | |
| 948 } | |
| 949 else if (pdf_is_array(ctx, function)) | |
| 950 { | |
| 951 int in; | |
| 952 | |
| 953 rd.funcs = pdf_array_len(ctx, function); | |
| 954 | |
| 955 if (rd.funcs != 1 && rd.funcs != src_cs->n) | |
| 956 fz_throw(ctx, FZ_ERROR_SYNTAX, "incorrect number of shading functions"); | |
| 957 if (rd.funcs > FZ_MAX_COLORS) | |
| 958 fz_throw(ctx, FZ_ERROR_SYNTAX, "too many shading functions"); | |
| 959 if (type == 1) | |
| 960 in = 2; | |
| 961 else | |
| 962 in = 1; | |
| 963 | |
| 964 for (i = 0; i < rd.funcs; i++) | |
| 965 { | |
| 966 func[i] = pdf_load_function(ctx, pdf_array_get(ctx, function, i), in, 1); | |
| 967 if (!func[i]) | |
| 968 fz_throw(ctx, FZ_ERROR_SYNTAX, "cannot load shading function (%d 0 R)", pdf_to_num(ctx, obj)); | |
| 969 } | |
| 970 | |
| 971 if (type != 1) | |
| 972 pdf_sample_shade_function(ctx, samples, src_cs->n, rd.funcs, func, d0, d1); | |
| 973 } | |
| 974 else if (type < 4) | |
| 975 { | |
| 976 /* Functions are compulsory for types 1,2,3 */ | |
| 977 fz_throw(ctx, FZ_ERROR_SYNTAX, "cannot load shading function (%d 0 R)", pdf_to_num(ctx, obj)); | |
| 978 } | |
| 979 | |
| 980 /* For function based shadings, we rewrite the 2d function. */ | |
| 981 if (type == 1) | |
| 982 { | |
| 983 fz_recolor_shade_type1(ctx, rewritten, func, &rd); | |
| 984 break; | |
| 985 } | |
| 986 | |
| 987 /* For all other function based shadings, we just rewrite the 1d function. */ | |
| 988 if (rd.funcs) | |
| 989 { | |
| 990 fz_recolor_shade_function(ctx, rewritten, samples, src_cs->n+1, &rd); | |
| 991 break; | |
| 992 } | |
| 993 | |
| 994 /* From here on in, we're changing the mesh, which means altering a stream. | |
| 995 * We'll need to be an indirect for that to work. */ | |
| 996 obj = pdf_add_object(ctx, doc, rewritten); | |
| 997 pdf_drop_obj(ctx, rewritten); | |
| 998 rewritten = obj; | |
| 999 | |
| 1000 switch (type) | |
| 1001 { | |
| 1002 case FZ_FUNCTION_BASED: | |
| 1003 /* Can never reach here. */ | |
| 1004 break; | |
| 1005 case FZ_LINEAR: | |
| 1006 case FZ_RADIAL: | |
| 1007 fz_throw(ctx, FZ_ERROR_SYNTAX, "Linear/Radial shadings must use functions"); | |
| 1008 break; | |
| 1009 case FZ_MESH_TYPE4: | |
| 1010 fz_recolor_shade_type4(ctx, rewritten, &rd); | |
| 1011 break; | |
| 1012 case FZ_MESH_TYPE5: | |
| 1013 fz_recolor_shade_type5(ctx, rewritten, &rd); | |
| 1014 break; | |
| 1015 case FZ_MESH_TYPE6: | |
| 1016 fz_recolor_shade_type6(ctx, rewritten, &rd); | |
| 1017 break; | |
| 1018 case FZ_MESH_TYPE7: | |
| 1019 fz_recolor_shade_type7(ctx, rewritten, &rd); | |
| 1020 break; | |
| 1021 default: | |
| 1022 fz_throw(ctx, FZ_ERROR_SYNTAX, "Unexpected mesh type %d\n", type); | |
| 1023 } | |
| 1024 } | |
| 1025 fz_always(ctx) | |
| 1026 { | |
| 1027 for (i = 0; i < rd.funcs; i++) | |
| 1028 pdf_drop_function(ctx, func[i]); | |
| 1029 fz_drop_colorspace(ctx, src_cs); | |
| 1030 } | |
| 1031 fz_catch(ctx) | |
| 1032 { | |
| 1033 pdf_drop_obj(ctx, rewritten); | |
| 1034 fz_rethrow(ctx); | |
| 1035 } | |
| 1036 | |
| 1037 return rewritten ? rewritten : shade; | |
| 1038 } |
