Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/source/pdf/pdf-op-buffer.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 typedef struct resources_stack | |
| 27 { | |
| 28 struct resources_stack *next; | |
| 29 pdf_obj *res; | |
| 30 } resources_stack; | |
| 31 | |
| 32 typedef struct | |
| 33 { | |
| 34 pdf_processor super; | |
| 35 fz_output *out; | |
| 36 int ahxencode; | |
| 37 int extgstate; | |
| 38 int newlines; | |
| 39 int balance; | |
| 40 pdf_obj *res; | |
| 41 pdf_obj *last_res; | |
| 42 resources_stack *rstack; | |
| 43 int sep; | |
| 44 } pdf_output_processor; | |
| 45 | |
| 46 /* general graphics state */ | |
| 47 | |
| 48 static void | |
| 49 post_op(fz_context *ctx, pdf_output_processor *proc) | |
| 50 { | |
| 51 if (proc->newlines) | |
| 52 proc->sep = '\n'; | |
| 53 else | |
| 54 proc->sep = 1; | |
| 55 } | |
| 56 | |
| 57 static inline void separate(fz_context *ctx, pdf_output_processor *proc) | |
| 58 { | |
| 59 if (!proc->sep) | |
| 60 return; | |
| 61 | |
| 62 if (proc->sep == '\n') | |
| 63 fz_write_byte(ctx, proc->out, '\n'); | |
| 64 else | |
| 65 fz_write_byte(ctx, proc->out, ' '); | |
| 66 } | |
| 67 | |
| 68 static void | |
| 69 pdf_out_w(fz_context *ctx, pdf_processor *proc_, float linewidth) | |
| 70 { | |
| 71 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 72 | |
| 73 if (proc->extgstate != 0) | |
| 74 return; | |
| 75 | |
| 76 separate(ctx, proc); | |
| 77 fz_write_printf(ctx, proc->out, "%g w", linewidth); | |
| 78 post_op(ctx, proc); | |
| 79 } | |
| 80 | |
| 81 static void | |
| 82 pdf_out_j(fz_context *ctx, pdf_processor *proc_, int linejoin) | |
| 83 { | |
| 84 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 85 | |
| 86 if (proc->extgstate != 0) | |
| 87 return; | |
| 88 | |
| 89 separate(ctx, proc); | |
| 90 fz_write_printf(ctx, proc->out, "%d j", linejoin); | |
| 91 post_op(ctx, proc); | |
| 92 } | |
| 93 | |
| 94 static void | |
| 95 pdf_out_J(fz_context *ctx, pdf_processor *proc_, int linecap) | |
| 96 { | |
| 97 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 98 | |
| 99 if (proc->extgstate != 0) | |
| 100 return; | |
| 101 | |
| 102 separate(ctx, proc); | |
| 103 fz_write_printf(ctx, proc->out, "%d J", linecap); | |
| 104 post_op(ctx, proc); | |
| 105 } | |
| 106 | |
| 107 static void | |
| 108 pdf_out_M(fz_context *ctx, pdf_processor *proc_, float a) | |
| 109 { | |
| 110 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 111 | |
| 112 if (proc->extgstate != 0) | |
| 113 return; | |
| 114 | |
| 115 separate(ctx, proc); | |
| 116 fz_write_printf(ctx, proc->out, "%g M", a); | |
| 117 post_op(ctx, proc); | |
| 118 } | |
| 119 | |
| 120 static void | |
| 121 pdf_out_d(fz_context *ctx, pdf_processor *proc_, pdf_obj *array, float phase) | |
| 122 { | |
| 123 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 124 int ahx = proc->ahxencode; | |
| 125 | |
| 126 if (proc->extgstate != 0) | |
| 127 return; | |
| 128 | |
| 129 pdf_print_encrypted_obj(ctx, proc->out, array, 1, ahx, NULL, 0, 0, &proc->sep); | |
| 130 separate(ctx, proc); | |
| 131 fz_write_printf(ctx, proc->out, "%g d", phase); | |
| 132 post_op(ctx, proc); | |
| 133 } | |
| 134 | |
| 135 static void | |
| 136 pdf_out_ri(fz_context *ctx, pdf_processor *proc_, const char *intent) | |
| 137 { | |
| 138 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 139 | |
| 140 if (proc->extgstate != 0) | |
| 141 return; | |
| 142 | |
| 143 separate(ctx, proc); | |
| 144 fz_write_printf(ctx, proc->out, "%n ri", intent); | |
| 145 post_op(ctx, proc); | |
| 146 } | |
| 147 | |
| 148 static void | |
| 149 pdf_out_i(fz_context *ctx, pdf_processor *proc_, float flatness) | |
| 150 { | |
| 151 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 152 | |
| 153 if (proc->extgstate != 0) | |
| 154 return; | |
| 155 | |
| 156 separate(ctx, proc); | |
| 157 fz_write_printf(ctx, proc->out, "%g i", flatness); | |
| 158 post_op(ctx, proc); | |
| 159 } | |
| 160 | |
| 161 static void | |
| 162 pdf_out_gs_begin(fz_context *ctx, pdf_processor *proc_, const char *name, pdf_obj *extgstate) | |
| 163 { | |
| 164 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 165 | |
| 166 proc->extgstate = 1; | |
| 167 | |
| 168 fz_write_printf(ctx, proc->out, "%n gs", name); | |
| 169 post_op(ctx, proc); | |
| 170 } | |
| 171 | |
| 172 static void | |
| 173 pdf_out_gs_end(fz_context *ctx, pdf_processor *proc) | |
| 174 { | |
| 175 ((pdf_output_processor*)proc)->extgstate = 0; | |
| 176 } | |
| 177 | |
| 178 /* special graphics state */ | |
| 179 | |
| 180 static void | |
| 181 pdf_out_q(fz_context *ctx, pdf_processor *proc_) | |
| 182 { | |
| 183 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 184 | |
| 185 proc->balance++; | |
| 186 | |
| 187 separate(ctx, proc); | |
| 188 fz_write_string(ctx, proc->out, "q"); | |
| 189 post_op(ctx, proc); | |
| 190 } | |
| 191 | |
| 192 static void | |
| 193 pdf_out_Q(fz_context *ctx, pdf_processor *proc_) | |
| 194 { | |
| 195 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 196 | |
| 197 proc->balance--; | |
| 198 if (proc->balance < 0) | |
| 199 fz_warn(ctx, "gstate underflow (too many Q operators)"); | |
| 200 | |
| 201 separate(ctx, proc); | |
| 202 fz_write_string(ctx, proc->out, "Q"); | |
| 203 post_op(ctx, proc); | |
| 204 } | |
| 205 | |
| 206 static void | |
| 207 pdf_out_cm(fz_context *ctx, pdf_processor *proc_, float a, float b, float c, float d, float e, float f) | |
| 208 { | |
| 209 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 210 | |
| 211 separate(ctx, proc); | |
| 212 fz_write_printf(ctx, proc->out, "%g %g %g %g %g %g cm", a, b, c, d, e, f); | |
| 213 post_op(ctx, proc); | |
| 214 } | |
| 215 | |
| 216 /* path construction */ | |
| 217 | |
| 218 static void | |
| 219 pdf_out_m(fz_context *ctx, pdf_processor *proc_, float x, float y) | |
| 220 { | |
| 221 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 222 | |
| 223 separate(ctx, proc); | |
| 224 fz_write_printf(ctx, proc->out, "%g %g m", x, y); | |
| 225 post_op(ctx, proc); | |
| 226 } | |
| 227 | |
| 228 static void | |
| 229 pdf_out_l(fz_context *ctx, pdf_processor *proc_, float x, float y) | |
| 230 { | |
| 231 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 232 | |
| 233 separate(ctx, proc); | |
| 234 fz_write_printf(ctx, proc->out, "%g %g l", x, y); | |
| 235 post_op(ctx, proc); | |
| 236 } | |
| 237 | |
| 238 static void | |
| 239 pdf_out_c(fz_context *ctx, pdf_processor *proc_, float x1, float y1, float x2, float y2, float x3, float y3) | |
| 240 { | |
| 241 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 242 | |
| 243 separate(ctx, proc); | |
| 244 fz_write_printf(ctx, proc->out, "%g %g %g %g %g %g c", x1, y1, x2, y2, x3, y3); | |
| 245 post_op(ctx, proc); | |
| 246 } | |
| 247 | |
| 248 static void | |
| 249 pdf_out_v(fz_context *ctx, pdf_processor *proc_, float x2, float y2, float x3, float y3) | |
| 250 { | |
| 251 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 252 | |
| 253 separate(ctx, proc); | |
| 254 fz_write_printf(ctx, proc->out, "%g %g %g %g v", x2, y2, x3, y3); | |
| 255 post_op(ctx, proc); | |
| 256 } | |
| 257 | |
| 258 static void | |
| 259 pdf_out_y(fz_context *ctx, pdf_processor *proc_, float x1, float y1, float x3, float y3) | |
| 260 { | |
| 261 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 262 | |
| 263 separate(ctx, proc); | |
| 264 fz_write_printf(ctx, proc->out, "%g %g %g %g y", x1, y1, x3, y3); | |
| 265 post_op(ctx, proc); | |
| 266 } | |
| 267 | |
| 268 static void | |
| 269 pdf_out_h(fz_context *ctx, pdf_processor *proc_) | |
| 270 { | |
| 271 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 272 | |
| 273 separate(ctx, proc); | |
| 274 fz_write_string(ctx, proc->out, "h"); | |
| 275 post_op(ctx, proc); | |
| 276 } | |
| 277 | |
| 278 static void | |
| 279 pdf_out_re(fz_context *ctx, pdf_processor *proc_, float x, float y, float w, float h) | |
| 280 { | |
| 281 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 282 | |
| 283 separate(ctx, proc); | |
| 284 fz_write_printf(ctx, proc->out, "%g %g %g %g re", x, y, w, h); | |
| 285 post_op(ctx, proc); | |
| 286 } | |
| 287 | |
| 288 /* path painting */ | |
| 289 | |
| 290 static void | |
| 291 pdf_out_S(fz_context *ctx, pdf_processor *proc_) | |
| 292 { | |
| 293 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 294 | |
| 295 separate(ctx, proc); | |
| 296 fz_write_string(ctx, proc->out, "S"); | |
| 297 post_op(ctx, proc); | |
| 298 } | |
| 299 | |
| 300 static void | |
| 301 pdf_out_s(fz_context *ctx, pdf_processor *proc_) | |
| 302 { | |
| 303 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 304 | |
| 305 separate(ctx, proc); | |
| 306 fz_write_string(ctx, proc->out, "s"); | |
| 307 post_op(ctx, proc); | |
| 308 } | |
| 309 | |
| 310 static void | |
| 311 pdf_out_F(fz_context *ctx, pdf_processor *proc_) | |
| 312 { | |
| 313 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 314 | |
| 315 separate(ctx, proc); | |
| 316 fz_write_string(ctx, proc->out, "F"); | |
| 317 post_op(ctx, proc); | |
| 318 } | |
| 319 | |
| 320 static void | |
| 321 pdf_out_f(fz_context *ctx, pdf_processor *proc_) | |
| 322 { | |
| 323 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 324 | |
| 325 separate(ctx, proc); | |
| 326 fz_write_string(ctx, proc->out, "f"); | |
| 327 post_op(ctx, proc); | |
| 328 } | |
| 329 | |
| 330 static void | |
| 331 pdf_out_fstar(fz_context *ctx, pdf_processor *proc_) | |
| 332 { | |
| 333 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 334 | |
| 335 separate(ctx, proc); | |
| 336 fz_write_string(ctx, proc->out, "f*"); | |
| 337 post_op(ctx, proc); | |
| 338 } | |
| 339 | |
| 340 static void | |
| 341 pdf_out_B(fz_context *ctx, pdf_processor *proc_) | |
| 342 { | |
| 343 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 344 | |
| 345 separate(ctx, proc); | |
| 346 fz_write_string(ctx, proc->out, "B"); | |
| 347 post_op(ctx, proc); | |
| 348 } | |
| 349 | |
| 350 static void | |
| 351 pdf_out_Bstar(fz_context *ctx, pdf_processor *proc_) | |
| 352 { | |
| 353 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 354 | |
| 355 separate(ctx, proc); | |
| 356 fz_write_string(ctx, proc->out, "B*"); | |
| 357 post_op(ctx, proc); | |
| 358 } | |
| 359 | |
| 360 static void | |
| 361 pdf_out_b(fz_context *ctx, pdf_processor *proc_) | |
| 362 { | |
| 363 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 364 | |
| 365 separate(ctx, proc); | |
| 366 fz_write_string(ctx, proc->out, "b"); | |
| 367 post_op(ctx, proc); | |
| 368 } | |
| 369 | |
| 370 static void | |
| 371 pdf_out_bstar(fz_context *ctx, pdf_processor *proc_) | |
| 372 { | |
| 373 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 374 | |
| 375 separate(ctx, proc); | |
| 376 fz_write_string(ctx, proc->out, "b*"); | |
| 377 post_op(ctx, proc); | |
| 378 } | |
| 379 | |
| 380 static void | |
| 381 pdf_out_n(fz_context *ctx, pdf_processor *proc_) | |
| 382 { | |
| 383 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 384 | |
| 385 separate(ctx, proc); | |
| 386 fz_write_string(ctx, proc->out, "n"); | |
| 387 post_op(ctx, proc); | |
| 388 } | |
| 389 | |
| 390 /* clipping paths */ | |
| 391 | |
| 392 static void | |
| 393 pdf_out_W(fz_context *ctx, pdf_processor *proc_) | |
| 394 { | |
| 395 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 396 | |
| 397 separate(ctx, proc); | |
| 398 fz_write_string(ctx, proc->out, "W"); | |
| 399 post_op(ctx, proc); | |
| 400 } | |
| 401 | |
| 402 static void | |
| 403 pdf_out_Wstar(fz_context *ctx, pdf_processor *proc_) | |
| 404 { | |
| 405 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 406 | |
| 407 separate(ctx, proc); | |
| 408 fz_write_string(ctx, proc->out, "W*"); | |
| 409 post_op(ctx, proc); | |
| 410 } | |
| 411 | |
| 412 /* text objects */ | |
| 413 | |
| 414 static void | |
| 415 pdf_out_BT(fz_context *ctx, pdf_processor *proc_) | |
| 416 { | |
| 417 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 418 | |
| 419 separate(ctx, proc); | |
| 420 fz_write_string(ctx, proc->out, "BT"); | |
| 421 post_op(ctx, proc); | |
| 422 } | |
| 423 | |
| 424 static void | |
| 425 pdf_out_ET(fz_context *ctx, pdf_processor *proc_) | |
| 426 { | |
| 427 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 428 | |
| 429 separate(ctx, proc); | |
| 430 fz_write_string(ctx, proc->out, "ET"); | |
| 431 post_op(ctx, proc); | |
| 432 } | |
| 433 | |
| 434 /* text state */ | |
| 435 | |
| 436 static void | |
| 437 pdf_out_Tc(fz_context *ctx, pdf_processor *proc_, float charspace) | |
| 438 { | |
| 439 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 440 | |
| 441 separate(ctx, proc); | |
| 442 fz_write_printf(ctx, proc->out, "%g Tc", charspace); | |
| 443 post_op(ctx, proc); | |
| 444 } | |
| 445 | |
| 446 static void | |
| 447 pdf_out_Tw(fz_context *ctx, pdf_processor *proc_, float wordspace) | |
| 448 { | |
| 449 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 450 | |
| 451 separate(ctx, proc); | |
| 452 fz_write_printf(ctx, proc->out, "%g Tw", wordspace); | |
| 453 post_op(ctx, proc); | |
| 454 } | |
| 455 | |
| 456 static void | |
| 457 pdf_out_Tz(fz_context *ctx, pdf_processor *proc_, float scale) | |
| 458 { | |
| 459 /* scale is exactly as read from the file. */ | |
| 460 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 461 | |
| 462 separate(ctx, proc); | |
| 463 fz_write_printf(ctx, proc->out, "%g Tz", scale); | |
| 464 post_op(ctx, proc); | |
| 465 } | |
| 466 | |
| 467 static void | |
| 468 pdf_out_TL(fz_context *ctx, pdf_processor *proc_, float leading) | |
| 469 { | |
| 470 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 471 | |
| 472 separate(ctx, proc); | |
| 473 fz_write_printf(ctx, proc->out, "%g TL", leading); | |
| 474 post_op(ctx, proc); | |
| 475 } | |
| 476 | |
| 477 static void | |
| 478 pdf_out_Tf(fz_context *ctx, pdf_processor *proc_, const char *name, pdf_font_desc *font, float size) | |
| 479 { | |
| 480 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 481 | |
| 482 if (proc->extgstate != 0) | |
| 483 return; | |
| 484 | |
| 485 fz_write_printf(ctx, proc->out, "%n %g Tf", name, size); | |
| 486 post_op(ctx, proc); | |
| 487 } | |
| 488 | |
| 489 static void | |
| 490 pdf_out_Tr(fz_context *ctx, pdf_processor *proc_, int render) | |
| 491 { | |
| 492 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 493 | |
| 494 separate(ctx, proc); | |
| 495 fz_write_printf(ctx, proc->out, "%d Tr", render); | |
| 496 post_op(ctx, proc); | |
| 497 } | |
| 498 | |
| 499 static void | |
| 500 pdf_out_Ts(fz_context *ctx, pdf_processor *proc_, float rise) | |
| 501 { | |
| 502 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 503 | |
| 504 separate(ctx, proc); | |
| 505 fz_write_printf(ctx, proc->out, "%g Ts", rise); | |
| 506 post_op(ctx, proc); | |
| 507 } | |
| 508 | |
| 509 /* text positioning */ | |
| 510 | |
| 511 static void | |
| 512 pdf_out_Td(fz_context *ctx, pdf_processor *proc_, float tx, float ty) | |
| 513 { | |
| 514 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 515 | |
| 516 separate(ctx, proc); | |
| 517 fz_write_printf(ctx, proc->out, "%g %g Td", tx, ty); | |
| 518 post_op(ctx, proc); | |
| 519 } | |
| 520 | |
| 521 static void | |
| 522 pdf_out_TD(fz_context *ctx, pdf_processor *proc_, float tx, float ty) | |
| 523 { | |
| 524 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 525 | |
| 526 separate(ctx, proc); | |
| 527 fz_write_printf(ctx, proc->out, "%g %g TD", tx, ty); | |
| 528 post_op(ctx, proc); | |
| 529 } | |
| 530 | |
| 531 static void | |
| 532 pdf_out_Tm(fz_context *ctx, pdf_processor *proc_, float a, float b, float c, float d, float e, float f) | |
| 533 { | |
| 534 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 535 | |
| 536 separate(ctx, proc); | |
| 537 fz_write_printf(ctx, proc->out, "%g %g %g %g %g %g Tm", a, b, c, d, e, f); | |
| 538 post_op(ctx, proc); | |
| 539 } | |
| 540 | |
| 541 static void | |
| 542 pdf_out_Tstar(fz_context *ctx, pdf_processor *proc_) | |
| 543 { | |
| 544 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 545 | |
| 546 separate(ctx, proc); | |
| 547 fz_write_string(ctx, proc->out, "T*"); | |
| 548 post_op(ctx, proc); | |
| 549 } | |
| 550 | |
| 551 /* text showing */ | |
| 552 | |
| 553 static void | |
| 554 fz_write_pdf_string(fz_context *ctx, fz_output *out, const unsigned char *str, size_t len) | |
| 555 { | |
| 556 size_t i; | |
| 557 | |
| 558 for (i = 0; i < len; ++i) | |
| 559 if (str[i] < 32 || str[i] >= 127) | |
| 560 break; | |
| 561 | |
| 562 if (i < len) | |
| 563 { | |
| 564 fz_write_byte(ctx, out, '<'); | |
| 565 for (i = 0; i < len; ++i) | |
| 566 { | |
| 567 unsigned char c = str[i]; | |
| 568 fz_write_byte(ctx, out, "0123456789abcdef"[(c>>4)&15]); | |
| 569 fz_write_byte(ctx, out, "0123456789abcdef"[(c)&15]); | |
| 570 } | |
| 571 fz_write_byte(ctx, out, '>'); | |
| 572 } | |
| 573 else | |
| 574 { | |
| 575 fz_write_byte(ctx, out, '('); | |
| 576 for (i = 0; i < len; ++i) | |
| 577 { | |
| 578 unsigned char c = str[i]; | |
| 579 if (c == '(' || c == ')' || c == '\\') | |
| 580 fz_write_byte(ctx, out, '\\'); | |
| 581 fz_write_byte(ctx, out, c); | |
| 582 } | |
| 583 fz_write_byte(ctx, out, ')'); | |
| 584 } | |
| 585 } | |
| 586 | |
| 587 static void | |
| 588 pdf_out_TJ(fz_context *ctx, pdf_processor *proc_, pdf_obj *array) | |
| 589 { | |
| 590 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 591 int ahx = proc->ahxencode; | |
| 592 | |
| 593 pdf_print_encrypted_obj(ctx, proc->out, array, 1, ahx, NULL, 0, 0, &proc->sep); | |
| 594 separate(ctx, proc); | |
| 595 fz_write_string(ctx, proc->out, "TJ"); | |
| 596 post_op(ctx, proc); | |
| 597 } | |
| 598 | |
| 599 static void | |
| 600 pdf_out_Tj(fz_context *ctx, pdf_processor *proc_, char *str, size_t len) | |
| 601 { | |
| 602 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 603 | |
| 604 separate(ctx, proc); | |
| 605 fz_write_pdf_string(ctx, proc->out, (const unsigned char *)str, len); | |
| 606 fz_write_string(ctx, proc->out, "Tj"); | |
| 607 post_op(ctx, proc); | |
| 608 } | |
| 609 | |
| 610 static void | |
| 611 pdf_out_squote(fz_context *ctx, pdf_processor *proc_, char *str, size_t len) | |
| 612 { | |
| 613 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 614 | |
| 615 separate(ctx, proc); | |
| 616 fz_write_pdf_string(ctx, proc->out, (const unsigned char *)str, len); | |
| 617 fz_write_string(ctx, proc->out, "'"); | |
| 618 post_op(ctx, proc); | |
| 619 } | |
| 620 | |
| 621 static void | |
| 622 pdf_out_dquote(fz_context *ctx, pdf_processor *proc_, float aw, float ac, char *str, size_t len) | |
| 623 { | |
| 624 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 625 | |
| 626 separate(ctx, proc); | |
| 627 fz_write_printf(ctx, proc->out, "%g %g ", aw, ac); | |
| 628 fz_write_pdf_string(ctx, proc->out, (const unsigned char *)str, len); | |
| 629 fz_write_string(ctx, proc->out, "\""); | |
| 630 post_op(ctx, proc); | |
| 631 } | |
| 632 | |
| 633 /* type 3 fonts */ | |
| 634 | |
| 635 static void | |
| 636 pdf_out_d0(fz_context *ctx, pdf_processor *proc_, float wx, float wy) | |
| 637 { | |
| 638 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 639 | |
| 640 separate(ctx, proc); | |
| 641 fz_write_printf(ctx, proc->out, "%g %g d0", wx, wy); | |
| 642 post_op(ctx, proc); | |
| 643 } | |
| 644 | |
| 645 static void | |
| 646 pdf_out_d1(fz_context *ctx, pdf_processor *proc_, float wx, float wy, float llx, float lly, float urx, float ury) | |
| 647 { | |
| 648 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 649 | |
| 650 separate(ctx, proc); | |
| 651 fz_write_printf(ctx, proc->out, "%g %g %g %g %g %g d1", wx, wy, llx, lly, urx, ury); | |
| 652 post_op(ctx, proc); | |
| 653 } | |
| 654 | |
| 655 /* color */ | |
| 656 | |
| 657 static void | |
| 658 pdf_out_CS(fz_context *ctx, pdf_processor *proc_, const char *name, fz_colorspace *cs) | |
| 659 { | |
| 660 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 661 | |
| 662 separate(ctx, proc); | |
| 663 fz_write_printf(ctx, proc->out, "%n CS", name); | |
| 664 post_op(ctx, proc); | |
| 665 } | |
| 666 | |
| 667 static void | |
| 668 pdf_out_cs(fz_context *ctx, pdf_processor *proc_, const char *name, fz_colorspace *cs) | |
| 669 { | |
| 670 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 671 | |
| 672 separate(ctx, proc); | |
| 673 fz_write_printf(ctx, proc->out, "%n cs", name); | |
| 674 post_op(ctx, proc); | |
| 675 } | |
| 676 | |
| 677 static void | |
| 678 pdf_out_SC_pattern(fz_context *ctx, pdf_processor *proc_, const char *name, pdf_pattern *pat, int n, float *color) | |
| 679 { | |
| 680 int i; | |
| 681 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 682 | |
| 683 separate(ctx, proc); | |
| 684 for (i = 0; i < n; ++i) | |
| 685 fz_write_printf(ctx, proc->out, "%g ", color[i]); | |
| 686 fz_write_printf(ctx, proc->out, "%n SCN", name); | |
| 687 post_op(ctx, proc); | |
| 688 } | |
| 689 | |
| 690 static void | |
| 691 pdf_out_sc_pattern(fz_context *ctx, pdf_processor *proc_, const char *name, pdf_pattern *pat, int n, float *color) | |
| 692 { | |
| 693 int i; | |
| 694 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 695 | |
| 696 separate(ctx, proc); | |
| 697 for (i = 0; i < n; ++i) | |
| 698 fz_write_printf(ctx, proc->out, "%g ", color[i]); | |
| 699 fz_write_printf(ctx, proc->out, "%n scn", name); | |
| 700 post_op(ctx, proc); | |
| 701 } | |
| 702 | |
| 703 static void | |
| 704 pdf_out_SC_shade(fz_context *ctx, pdf_processor *proc_, const char *name, fz_shade *shade) | |
| 705 { | |
| 706 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 707 | |
| 708 separate(ctx, proc); | |
| 709 fz_write_printf(ctx, proc->out, "%n SCN", name); | |
| 710 post_op(ctx, proc); | |
| 711 } | |
| 712 | |
| 713 static void | |
| 714 pdf_out_sc_shade(fz_context *ctx, pdf_processor *proc_, const char *name, fz_shade *shade) | |
| 715 { | |
| 716 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 717 | |
| 718 separate(ctx, proc); | |
| 719 fz_write_printf(ctx, proc->out, "%n scn", name); | |
| 720 post_op(ctx, proc); | |
| 721 } | |
| 722 | |
| 723 static void | |
| 724 pdf_out_SC_color(fz_context *ctx, pdf_processor *proc_, int n, float *color) | |
| 725 { | |
| 726 int i; | |
| 727 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 728 | |
| 729 separate(ctx, proc); | |
| 730 for (i = 0; i < n; ++i) | |
| 731 fz_write_printf(ctx, proc->out, "%g ", color[i]); | |
| 732 fz_write_string(ctx, proc->out, "SCN"); | |
| 733 post_op(ctx, proc); | |
| 734 } | |
| 735 | |
| 736 static void | |
| 737 pdf_out_sc_color(fz_context *ctx, pdf_processor *proc_, int n, float *color) | |
| 738 { | |
| 739 int i; | |
| 740 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 741 | |
| 742 separate(ctx, proc); | |
| 743 for (i = 0; i < n; ++i) | |
| 744 fz_write_printf(ctx, proc->out, "%g ", color[i]); | |
| 745 fz_write_string(ctx, proc->out, "scn"); | |
| 746 post_op(ctx, proc); | |
| 747 } | |
| 748 | |
| 749 static void | |
| 750 pdf_out_G(fz_context *ctx, pdf_processor *proc_, float g) | |
| 751 { | |
| 752 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 753 | |
| 754 separate(ctx, proc); | |
| 755 fz_write_printf(ctx, proc->out, "%g G", g); | |
| 756 post_op(ctx, proc); | |
| 757 } | |
| 758 | |
| 759 static void | |
| 760 pdf_out_g(fz_context *ctx, pdf_processor *proc_, float g) | |
| 761 { | |
| 762 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 763 | |
| 764 separate(ctx, proc); | |
| 765 fz_write_printf(ctx, proc->out, "%g g", g); | |
| 766 post_op(ctx, proc); | |
| 767 } | |
| 768 | |
| 769 static void | |
| 770 pdf_out_RG(fz_context *ctx, pdf_processor *proc_, float r, float g, float b) | |
| 771 { | |
| 772 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 773 | |
| 774 separate(ctx, proc); | |
| 775 fz_write_printf(ctx, proc->out, "%g %g %g RG", r, g, b); | |
| 776 post_op(ctx, proc); | |
| 777 } | |
| 778 | |
| 779 static void | |
| 780 pdf_out_rg(fz_context *ctx, pdf_processor *proc_, float r, float g, float b) | |
| 781 { | |
| 782 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 783 | |
| 784 separate(ctx, proc); | |
| 785 fz_write_printf(ctx, proc->out, "%g %g %g rg", r, g, b); | |
| 786 post_op(ctx, proc); | |
| 787 } | |
| 788 | |
| 789 static void | |
| 790 pdf_out_K(fz_context *ctx, pdf_processor *proc_, float c, float m, float y, float k) | |
| 791 { | |
| 792 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 793 | |
| 794 separate(ctx, proc); | |
| 795 fz_write_printf(ctx, proc->out, "%g %g %g %g K", c, m, y, k); | |
| 796 post_op(ctx, proc); | |
| 797 } | |
| 798 | |
| 799 static void | |
| 800 pdf_out_k(fz_context *ctx, pdf_processor *proc_, float c, float m, float y, float k) | |
| 801 { | |
| 802 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 803 | |
| 804 separate(ctx, proc); | |
| 805 fz_write_printf(ctx, proc->out, "%g %g %g %g k", c, m, y, k); | |
| 806 post_op(ctx, proc); | |
| 807 } | |
| 808 | |
| 809 /* shadings, images, xobjects */ | |
| 810 | |
| 811 static void | |
| 812 pdf_out_BI(fz_context *ctx, pdf_processor *proc_, fz_image *img, const char *colorspace) | |
| 813 { | |
| 814 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 815 fz_output *out = proc->out; | |
| 816 int ahx = proc->ahxencode; | |
| 817 fz_compressed_buffer *cbuf; | |
| 818 fz_buffer *buf = NULL; | |
| 819 int i, w, h, bpc; | |
| 820 unsigned char *data; | |
| 821 size_t len; | |
| 822 fz_pixmap *pix = NULL; | |
| 823 fz_colorspace *cs; | |
| 824 int type; | |
| 825 | |
| 826 if (img == NULL) | |
| 827 return; | |
| 828 cbuf = fz_compressed_image_buffer(ctx, img); | |
| 829 if (cbuf == NULL) | |
| 830 { | |
| 831 pix = fz_get_pixmap_from_image(ctx, img, NULL, NULL, &w, &h); | |
| 832 bpc = 8; | |
| 833 cs = pix->colorspace; | |
| 834 type = FZ_IMAGE_RAW; | |
| 835 } | |
| 836 else | |
| 837 { | |
| 838 buf = cbuf->buffer; | |
| 839 if (buf == NULL) | |
| 840 return; | |
| 841 w = img->w; | |
| 842 h = img->h; | |
| 843 bpc = img->bpc; | |
| 844 cs = img->colorspace; | |
| 845 type = cbuf->params.type; | |
| 846 } | |
| 847 | |
| 848 fz_try(ctx) | |
| 849 { | |
| 850 separate(ctx, proc); | |
| 851 fz_write_string(ctx, out, "BI "); | |
| 852 fz_write_printf(ctx, out, "/W %d", w); | |
| 853 fz_write_printf(ctx, out, "/H %d", h); | |
| 854 fz_write_printf(ctx, out, "/BPC %d", bpc); | |
| 855 if (img->imagemask) | |
| 856 fz_write_string(ctx, out, "/IM true"); | |
| 857 else if (cs == fz_device_gray(ctx)) | |
| 858 fz_write_string(ctx, out, "/CS/G"); | |
| 859 else if (cs == fz_device_rgb(ctx)) | |
| 860 fz_write_string(ctx, out, "/CS/RGB"); | |
| 861 else if (cs == fz_device_cmyk(ctx)) | |
| 862 fz_write_string(ctx, out, "/CS/CMYK"); | |
| 863 else if (cs) | |
| 864 fz_write_printf(ctx, out, "/CS%n", colorspace); | |
| 865 else | |
| 866 fz_throw(ctx, FZ_ERROR_ARGUMENT, "BI operator can only show ImageMask, Gray, RGB, or CMYK images"); | |
| 867 if (img->interpolate) | |
| 868 fz_write_string(ctx, out, "/I true"); | |
| 869 fz_write_string(ctx, out, "/D["); | |
| 870 for (i = 0; i < img->n * 2; ++i) | |
| 871 { | |
| 872 if (i > 0) | |
| 873 fz_write_byte(ctx, out, ' '); | |
| 874 fz_write_printf(ctx, out, "%g", img->decode[i]); | |
| 875 } | |
| 876 fz_write_string(ctx, out, "]"); | |
| 877 proc->sep = 0; | |
| 878 | |
| 879 switch (type) | |
| 880 { | |
| 881 default: | |
| 882 fz_throw(ctx, FZ_ERROR_ARGUMENT, "unknown compressed buffer type"); | |
| 883 break; | |
| 884 | |
| 885 case FZ_IMAGE_JPEG: | |
| 886 fz_write_string(ctx, out, ahx ? "/F[/AHx/DCT]" : "/F/DCT"); | |
| 887 proc->sep = !ahx; | |
| 888 if (cbuf->params.u.jpeg.color_transform >= 0) | |
| 889 { | |
| 890 fz_write_printf(ctx, out, "/DP<</ColorTransform %d>>", cbuf->params.u.jpeg.color_transform); | |
| 891 proc->sep = 0; | |
| 892 } | |
| 893 if (cbuf->params.u.jpeg.invert_cmyk && img->n == 4) | |
| 894 { | |
| 895 fz_write_string(ctx, out, "/D[1 0 1 0 1 0 1 0]"); | |
| 896 proc->sep = 0; | |
| 897 } | |
| 898 break; | |
| 899 | |
| 900 case FZ_IMAGE_FAX: | |
| 901 fz_write_string(ctx, out, ahx ? "/F[/AHx/CCF]/DP[null<<" : "/F/CCF/DP<<"); | |
| 902 fz_write_printf(ctx, out, "/K %d", cbuf->params.u.fax.k); | |
| 903 if (cbuf->params.u.fax.columns != 1728) | |
| 904 fz_write_printf(ctx, out, "/Columns %d", cbuf->params.u.fax.columns); | |
| 905 if (cbuf->params.u.fax.rows > 0) | |
| 906 fz_write_printf(ctx, out, "/Rows %d", cbuf->params.u.fax.rows); | |
| 907 if (cbuf->params.u.fax.end_of_line) | |
| 908 fz_write_string(ctx, out, "/EndOfLine true"); | |
| 909 if (cbuf->params.u.fax.encoded_byte_align) | |
| 910 fz_write_string(ctx, out, "/EncodedByteAlign true"); | |
| 911 if (!cbuf->params.u.fax.end_of_block) | |
| 912 fz_write_string(ctx, out, "/EndOfBlock false"); | |
| 913 if (cbuf->params.u.fax.black_is_1) | |
| 914 fz_write_string(ctx, out, "/BlackIs1 true"); | |
| 915 if (cbuf->params.u.fax.damaged_rows_before_error > 0) | |
| 916 fz_write_printf(ctx, out, "/DamagedRowsBeforeError %d", | |
| 917 cbuf->params.u.fax.damaged_rows_before_error); | |
| 918 fz_write_string(ctx, out, ahx ? ">>]" : ">>"); | |
| 919 proc->sep = 0; | |
| 920 break; | |
| 921 | |
| 922 case FZ_IMAGE_RAW: | |
| 923 if (ahx) | |
| 924 { | |
| 925 fz_write_string(ctx, out, "/F/AHx"); | |
| 926 proc->sep = 1; | |
| 927 } | |
| 928 break; | |
| 929 | |
| 930 case FZ_IMAGE_RLD: | |
| 931 fz_write_string(ctx, out, ahx ? "/F[/AHx/RL]" : "/F/RL"); | |
| 932 proc->sep = !ahx; | |
| 933 break; | |
| 934 | |
| 935 case FZ_IMAGE_FLATE: | |
| 936 fz_write_string(ctx, out, ahx ? "/F[/AHx/Fl]" : "/F/Fl"); | |
| 937 proc->sep = !ahx; | |
| 938 if (cbuf->params.u.flate.predictor > 1) | |
| 939 { | |
| 940 fz_write_string(ctx, out, ahx ? "/DP[null<<" : "/DP<<"); | |
| 941 fz_write_printf(ctx, out, "/Predictor %d", cbuf->params.u.flate.predictor); | |
| 942 if (cbuf->params.u.flate.columns != 1) | |
| 943 fz_write_printf(ctx, out, "/Columns %d", cbuf->params.u.flate.columns); | |
| 944 if (cbuf->params.u.flate.colors != 1) | |
| 945 fz_write_printf(ctx, out, "/Colors %d", cbuf->params.u.flate.colors); | |
| 946 if (cbuf->params.u.flate.bpc != 8) | |
| 947 fz_write_printf(ctx, out, "/BitsPerComponent %d", cbuf->params.u.flate.bpc); | |
| 948 fz_write_string(ctx, out, ahx ? ">>]" : ">>"); | |
| 949 proc->sep = 0; | |
| 950 } | |
| 951 break; | |
| 952 | |
| 953 case FZ_IMAGE_LZW: | |
| 954 fz_write_string(ctx, out, ahx ? "/F[/AHx/LZW]" : "/F/LZW"); | |
| 955 proc->sep = !ahx; | |
| 956 if (cbuf->params.u.lzw.predictor > 1) | |
| 957 { | |
| 958 fz_write_string(ctx, out, ahx ? "/DP[null<<" : "/DP<<"); | |
| 959 fz_write_printf(ctx, out, "/Predictor %d", cbuf->params.u.lzw.predictor); | |
| 960 if (cbuf->params.u.lzw.columns != 1) | |
| 961 fz_write_printf(ctx, out, "/Columns %d", cbuf->params.u.lzw.columns); | |
| 962 if (cbuf->params.u.lzw.colors != 1) | |
| 963 fz_write_printf(ctx, out, "/Colors %d", cbuf->params.u.lzw.colors); | |
| 964 if (cbuf->params.u.lzw.bpc != 8) | |
| 965 fz_write_printf(ctx, out, "/BitsPerComponent %d", cbuf->params.u.lzw.bpc); | |
| 966 if (cbuf->params.u.lzw.early_change != 1) | |
| 967 fz_write_printf(ctx, out, "/EarlyChange %d", cbuf->params.u.lzw.early_change); | |
| 968 fz_write_string(ctx, out, ahx ? ">>]" : ">>"); | |
| 969 proc->sep = 0; | |
| 970 } | |
| 971 break; | |
| 972 | |
| 973 case FZ_IMAGE_BROTLI: | |
| 974 fz_write_string(ctx, out, ahx ? "/F[/AHx/Br]\n" : "/F/Br\n"); | |
| 975 if (cbuf->params.u.brotli.predictor > 1) | |
| 976 { | |
| 977 fz_write_string(ctx, out, ahx ? "/DP[null<<\n" : "/DP<<\n"); | |
| 978 fz_write_printf(ctx, out, "/Predictor %d\n", cbuf->params.u.brotli.predictor); | |
| 979 if (cbuf->params.u.brotli.columns != 1) | |
| 980 fz_write_printf(ctx, out, "/Columns %d\n", cbuf->params.u.brotli.columns); | |
| 981 if (cbuf->params.u.brotli.colors != 1) | |
| 982 fz_write_printf(ctx, out, "/Colors %d\n", cbuf->params.u.brotli.colors); | |
| 983 if (cbuf->params.u.brotli.bpc != 8) | |
| 984 fz_write_printf(ctx, out, "/BitsPerComponent %d\n", cbuf->params.u.brotli.bpc); | |
| 985 fz_write_string(ctx, out, ahx ? ">>]\n" : ">>\n"); | |
| 986 } | |
| 987 break; | |
| 988 } | |
| 989 | |
| 990 separate(ctx, proc); | |
| 991 fz_write_string(ctx, out, "ID "); | |
| 992 if (buf) | |
| 993 len = fz_buffer_storage(ctx, buf, &data); | |
| 994 else | |
| 995 { | |
| 996 data = pix->samples; | |
| 997 len = ((size_t)w) * h * pix->n; | |
| 998 } | |
| 999 if (ahx) | |
| 1000 { | |
| 1001 size_t z; | |
| 1002 for (z = 0; z < len; ++z) | |
| 1003 { | |
| 1004 int c = data[z]; | |
| 1005 fz_write_byte(ctx, out, "0123456789abcdef"[(c >> 4) & 0xf]); | |
| 1006 fz_write_byte(ctx, out, "0123456789abcdef"[c & 0xf]); | |
| 1007 if ((z & 31) == 31) | |
| 1008 fz_write_byte(ctx, out, '\n'); | |
| 1009 } | |
| 1010 fz_write_byte(ctx, out, '>'); | |
| 1011 } | |
| 1012 else | |
| 1013 { | |
| 1014 fz_write_data(ctx, out, data, len); | |
| 1015 } | |
| 1016 fz_write_string(ctx, out, " EI"); | |
| 1017 proc->sep = 1; | |
| 1018 } | |
| 1019 fz_always(ctx) | |
| 1020 fz_drop_pixmap(ctx, pix); | |
| 1021 fz_catch(ctx) | |
| 1022 fz_rethrow(ctx); | |
| 1023 } | |
| 1024 | |
| 1025 static void | |
| 1026 pdf_out_sh(fz_context *ctx, pdf_processor *proc_, const char *name, fz_shade *shade) | |
| 1027 { | |
| 1028 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 1029 | |
| 1030 separate(ctx, proc); | |
| 1031 fz_write_printf(ctx, proc->out, "%n sh", name); | |
| 1032 post_op(ctx, proc); | |
| 1033 } | |
| 1034 | |
| 1035 static void | |
| 1036 pdf_out_Do_image(fz_context *ctx, pdf_processor *proc_, const char *name, fz_image *image) | |
| 1037 { | |
| 1038 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 1039 | |
| 1040 separate(ctx, proc); | |
| 1041 fz_write_printf(ctx, proc->out, "%n Do", name); | |
| 1042 post_op(ctx, proc); | |
| 1043 } | |
| 1044 | |
| 1045 static void | |
| 1046 pdf_out_Do_form(fz_context *ctx, pdf_processor *proc_, const char *name, pdf_obj *xobj) | |
| 1047 { | |
| 1048 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 1049 | |
| 1050 separate(ctx, proc); | |
| 1051 fz_write_printf(ctx, proc->out, "%n Do", name); | |
| 1052 post_op(ctx, proc); | |
| 1053 } | |
| 1054 | |
| 1055 /* marked content */ | |
| 1056 | |
| 1057 static void | |
| 1058 pdf_out_MP(fz_context *ctx, pdf_processor *proc_, const char *tag) | |
| 1059 { | |
| 1060 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 1061 | |
| 1062 separate(ctx, proc); | |
| 1063 fz_write_printf(ctx, proc->out, "%n MP", tag); | |
| 1064 post_op(ctx, proc); | |
| 1065 } | |
| 1066 | |
| 1067 static void | |
| 1068 pdf_out_DP(fz_context *ctx, pdf_processor *proc_, const char *tag, pdf_obj *raw, pdf_obj *cooked) | |
| 1069 { | |
| 1070 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 1071 int ahx = proc->ahxencode; | |
| 1072 | |
| 1073 separate(ctx, proc); | |
| 1074 fz_write_printf(ctx, proc->out, "%n", tag); | |
| 1075 proc->sep = 1; | |
| 1076 pdf_print_encrypted_obj(ctx, proc->out, raw, 1, ahx, NULL, 0, 0, &proc->sep); | |
| 1077 separate(ctx, proc); | |
| 1078 fz_write_string(ctx, proc->out, "DP"); | |
| 1079 post_op(ctx, proc); | |
| 1080 } | |
| 1081 | |
| 1082 static void | |
| 1083 pdf_out_BMC(fz_context *ctx, pdf_processor *proc_, const char *tag) | |
| 1084 { | |
| 1085 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 1086 | |
| 1087 separate(ctx, proc); | |
| 1088 fz_write_printf(ctx, proc->out, "%n BMC", tag); | |
| 1089 post_op(ctx, proc); | |
| 1090 } | |
| 1091 | |
| 1092 static void | |
| 1093 pdf_out_BDC(fz_context *ctx, pdf_processor *proc_, const char *tag, pdf_obj *raw, pdf_obj *cooked) | |
| 1094 { | |
| 1095 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 1096 int ahx = proc->ahxencode; | |
| 1097 | |
| 1098 separate(ctx, proc); | |
| 1099 fz_write_printf(ctx, proc->out, "%n", tag); | |
| 1100 proc->sep = 1; | |
| 1101 pdf_print_encrypted_obj(ctx, proc->out, raw, 1, ahx, NULL, 0, 0, &proc->sep); | |
| 1102 separate(ctx, proc); | |
| 1103 fz_write_string(ctx, proc->out, "BDC"); | |
| 1104 post_op(ctx, proc); | |
| 1105 } | |
| 1106 | |
| 1107 static void | |
| 1108 pdf_out_EMC(fz_context *ctx, pdf_processor *proc_) | |
| 1109 { | |
| 1110 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 1111 | |
| 1112 separate(ctx, proc); | |
| 1113 fz_write_string(ctx, proc->out, "EMC"); | |
| 1114 post_op(ctx, proc); | |
| 1115 } | |
| 1116 | |
| 1117 /* compatibility */ | |
| 1118 | |
| 1119 static void | |
| 1120 pdf_out_BX(fz_context *ctx, pdf_processor *proc_) | |
| 1121 { | |
| 1122 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 1123 | |
| 1124 separate(ctx, proc); | |
| 1125 fz_write_string(ctx, proc->out, "BX"); | |
| 1126 post_op(ctx, proc); | |
| 1127 } | |
| 1128 | |
| 1129 static void | |
| 1130 pdf_out_EX(fz_context *ctx, pdf_processor *proc_) | |
| 1131 { | |
| 1132 pdf_output_processor *proc = (pdf_output_processor *)proc_; | |
| 1133 | |
| 1134 separate(ctx, proc); | |
| 1135 fz_write_string(ctx, proc->out, "EX"); | |
| 1136 post_op(ctx, proc); | |
| 1137 } | |
| 1138 | |
| 1139 static void | |
| 1140 pdf_close_output_processor(fz_context *ctx, pdf_processor *proc_) | |
| 1141 { | |
| 1142 pdf_output_processor *proc = (pdf_output_processor*)proc_; | |
| 1143 fz_output *out = proc->out; | |
| 1144 | |
| 1145 /* Add missing 'Q' operators to get back to zero. */ | |
| 1146 /* We can't prepend missing 'q' operators to guarantee we don't underflow. */ | |
| 1147 while (proc->balance > 0) | |
| 1148 { | |
| 1149 proc->balance--; | |
| 1150 separate(ctx, proc); | |
| 1151 fz_write_byte(ctx, out, 'Q'); | |
| 1152 post_op(ctx, proc); | |
| 1153 } | |
| 1154 | |
| 1155 fz_close_output(ctx, out); | |
| 1156 } | |
| 1157 | |
| 1158 static void | |
| 1159 pdf_drop_output_processor(fz_context *ctx, pdf_processor *proc) | |
| 1160 { | |
| 1161 pdf_output_processor *p = (pdf_output_processor *)proc; | |
| 1162 | |
| 1163 fz_drop_output(ctx, p->out); | |
| 1164 } | |
| 1165 | |
| 1166 static void | |
| 1167 pdf_reset_output_processor(fz_context *ctx, pdf_processor *proc) | |
| 1168 { | |
| 1169 pdf_output_processor *p = (pdf_output_processor *)proc; | |
| 1170 | |
| 1171 fz_reset_output(ctx, p->out); | |
| 1172 } | |
| 1173 | |
| 1174 static void | |
| 1175 pdf_out_push_resources(fz_context *ctx, pdf_processor *proc, pdf_obj *res) | |
| 1176 { | |
| 1177 pdf_output_processor *p = (pdf_output_processor *)proc; | |
| 1178 resources_stack *stk = fz_malloc_struct(ctx, resources_stack); | |
| 1179 | |
| 1180 stk->next = p->rstack; | |
| 1181 p->rstack = stk; | |
| 1182 stk->res = pdf_keep_obj(ctx, res); | |
| 1183 } | |
| 1184 | |
| 1185 static pdf_obj * | |
| 1186 pdf_out_pop_resources(fz_context *ctx, pdf_processor *proc) | |
| 1187 { | |
| 1188 pdf_output_processor *p = (pdf_output_processor *)proc; | |
| 1189 resources_stack *stk = p->rstack; | |
| 1190 pdf_obj *res = stk->res; | |
| 1191 | |
| 1192 p->rstack = stk->next; | |
| 1193 fz_free(ctx, stk); | |
| 1194 | |
| 1195 return res; | |
| 1196 } | |
| 1197 | |
| 1198 pdf_processor * | |
| 1199 pdf_new_output_processor(fz_context *ctx, fz_output *out, int ahxencode, int newlines) | |
| 1200 { | |
| 1201 pdf_output_processor *proc = pdf_new_processor(ctx, sizeof *proc); | |
| 1202 | |
| 1203 proc->super.close_processor = pdf_close_output_processor; | |
| 1204 proc->super.drop_processor = pdf_drop_output_processor; | |
| 1205 proc->super.reset_processor = pdf_reset_output_processor; | |
| 1206 | |
| 1207 proc->super.push_resources = pdf_out_push_resources; | |
| 1208 proc->super.pop_resources = pdf_out_pop_resources; | |
| 1209 | |
| 1210 /* general graphics state */ | |
| 1211 proc->super.op_w = pdf_out_w; | |
| 1212 proc->super.op_j = pdf_out_j; | |
| 1213 proc->super.op_J = pdf_out_J; | |
| 1214 proc->super.op_M = pdf_out_M; | |
| 1215 proc->super.op_d = pdf_out_d; | |
| 1216 proc->super.op_ri = pdf_out_ri; | |
| 1217 proc->super.op_i = pdf_out_i; | |
| 1218 proc->super.op_gs_begin = pdf_out_gs_begin; | |
| 1219 proc->super.op_gs_end = pdf_out_gs_end; | |
| 1220 | |
| 1221 /* transparency graphics state */ | |
| 1222 proc->super.op_gs_BM = NULL; | |
| 1223 proc->super.op_gs_CA = NULL; | |
| 1224 proc->super.op_gs_ca = NULL; | |
| 1225 proc->super.op_gs_SMask = NULL; | |
| 1226 | |
| 1227 /* special graphics state */ | |
| 1228 proc->super.op_q = pdf_out_q; | |
| 1229 proc->super.op_Q = pdf_out_Q; | |
| 1230 proc->super.op_cm = pdf_out_cm; | |
| 1231 | |
| 1232 /* path construction */ | |
| 1233 proc->super.op_m = pdf_out_m; | |
| 1234 proc->super.op_l = pdf_out_l; | |
| 1235 proc->super.op_c = pdf_out_c; | |
| 1236 proc->super.op_v = pdf_out_v; | |
| 1237 proc->super.op_y = pdf_out_y; | |
| 1238 proc->super.op_h = pdf_out_h; | |
| 1239 proc->super.op_re = pdf_out_re; | |
| 1240 | |
| 1241 /* path painting */ | |
| 1242 proc->super.op_S = pdf_out_S; | |
| 1243 proc->super.op_s = pdf_out_s; | |
| 1244 proc->super.op_F = pdf_out_F; | |
| 1245 proc->super.op_f = pdf_out_f; | |
| 1246 proc->super.op_fstar = pdf_out_fstar; | |
| 1247 proc->super.op_B = pdf_out_B; | |
| 1248 proc->super.op_Bstar = pdf_out_Bstar; | |
| 1249 proc->super.op_b = pdf_out_b; | |
| 1250 proc->super.op_bstar = pdf_out_bstar; | |
| 1251 proc->super.op_n = pdf_out_n; | |
| 1252 | |
| 1253 /* clipping paths */ | |
| 1254 proc->super.op_W = pdf_out_W; | |
| 1255 proc->super.op_Wstar = pdf_out_Wstar; | |
| 1256 | |
| 1257 /* text objects */ | |
| 1258 proc->super.op_BT = pdf_out_BT; | |
| 1259 proc->super.op_ET = pdf_out_ET; | |
| 1260 | |
| 1261 /* text state */ | |
| 1262 proc->super.op_Tc = pdf_out_Tc; | |
| 1263 proc->super.op_Tw = pdf_out_Tw; | |
| 1264 proc->super.op_Tz = pdf_out_Tz; | |
| 1265 proc->super.op_TL = pdf_out_TL; | |
| 1266 proc->super.op_Tf = pdf_out_Tf; | |
| 1267 proc->super.op_Tr = pdf_out_Tr; | |
| 1268 proc->super.op_Ts = pdf_out_Ts; | |
| 1269 | |
| 1270 /* text positioning */ | |
| 1271 proc->super.op_Td = pdf_out_Td; | |
| 1272 proc->super.op_TD = pdf_out_TD; | |
| 1273 proc->super.op_Tm = pdf_out_Tm; | |
| 1274 proc->super.op_Tstar = pdf_out_Tstar; | |
| 1275 | |
| 1276 /* text showing */ | |
| 1277 proc->super.op_TJ = pdf_out_TJ; | |
| 1278 proc->super.op_Tj = pdf_out_Tj; | |
| 1279 proc->super.op_squote = pdf_out_squote; | |
| 1280 proc->super.op_dquote = pdf_out_dquote; | |
| 1281 | |
| 1282 /* type 3 fonts */ | |
| 1283 proc->super.op_d0 = pdf_out_d0; | |
| 1284 proc->super.op_d1 = pdf_out_d1; | |
| 1285 | |
| 1286 /* color */ | |
| 1287 proc->super.op_CS = pdf_out_CS; | |
| 1288 proc->super.op_cs = pdf_out_cs; | |
| 1289 proc->super.op_SC_color = pdf_out_SC_color; | |
| 1290 proc->super.op_sc_color = pdf_out_sc_color; | |
| 1291 proc->super.op_SC_pattern = pdf_out_SC_pattern; | |
| 1292 proc->super.op_sc_pattern = pdf_out_sc_pattern; | |
| 1293 proc->super.op_SC_shade = pdf_out_SC_shade; | |
| 1294 proc->super.op_sc_shade = pdf_out_sc_shade; | |
| 1295 | |
| 1296 proc->super.op_G = pdf_out_G; | |
| 1297 proc->super.op_g = pdf_out_g; | |
| 1298 proc->super.op_RG = pdf_out_RG; | |
| 1299 proc->super.op_rg = pdf_out_rg; | |
| 1300 proc->super.op_K = pdf_out_K; | |
| 1301 proc->super.op_k = pdf_out_k; | |
| 1302 | |
| 1303 /* shadings, images, xobjects */ | |
| 1304 proc->super.op_BI = pdf_out_BI; | |
| 1305 proc->super.op_sh = pdf_out_sh; | |
| 1306 proc->super.op_Do_image = pdf_out_Do_image; | |
| 1307 proc->super.op_Do_form = pdf_out_Do_form; | |
| 1308 | |
| 1309 /* marked content */ | |
| 1310 proc->super.op_MP = pdf_out_MP; | |
| 1311 proc->super.op_DP = pdf_out_DP; | |
| 1312 proc->super.op_BMC = pdf_out_BMC; | |
| 1313 proc->super.op_BDC = pdf_out_BDC; | |
| 1314 proc->super.op_EMC = pdf_out_EMC; | |
| 1315 | |
| 1316 /* compatibility */ | |
| 1317 proc->super.op_BX = pdf_out_BX; | |
| 1318 proc->super.op_EX = pdf_out_EX; | |
| 1319 | |
| 1320 /* extgstate */ | |
| 1321 proc->super.op_gs_OP = NULL; | |
| 1322 proc->super.op_gs_op = NULL; | |
| 1323 proc->super.op_gs_OPM = NULL; | |
| 1324 proc->super.op_gs_UseBlackPtComp = NULL; | |
| 1325 | |
| 1326 proc->out = out; | |
| 1327 proc->ahxencode = ahxencode; | |
| 1328 proc->newlines = newlines; | |
| 1329 | |
| 1330 proc->super.requirements = PDF_PROCESSOR_REQUIRES_DECODED_IMAGES; | |
| 1331 | |
| 1332 proc->balance = 0; | |
| 1333 | |
| 1334 return (pdf_processor*)proc; | |
| 1335 } | |
| 1336 | |
| 1337 pdf_processor * | |
| 1338 pdf_new_buffer_processor(fz_context *ctx, fz_buffer *buffer, int ahxencode, int newlines) | |
| 1339 { | |
| 1340 pdf_processor *proc = NULL; | |
| 1341 fz_output *out = fz_new_output_with_buffer(ctx, buffer); | |
| 1342 fz_try(ctx) | |
| 1343 { | |
| 1344 proc = pdf_new_output_processor(ctx, out, ahxencode, newlines); | |
| 1345 } | |
| 1346 fz_catch(ctx) | |
| 1347 { | |
| 1348 fz_drop_output(ctx, out); | |
| 1349 fz_rethrow(ctx); | |
| 1350 } | |
| 1351 return proc; | |
| 1352 } | |
| 1353 | |
| 1354 /* Simplified processor that only counts matching q/Q pairs. */ | |
| 1355 | |
| 1356 typedef struct | |
| 1357 { | |
| 1358 pdf_processor super; | |
| 1359 int *balance; | |
| 1360 int *min_q; | |
| 1361 int *min_op_q; | |
| 1362 int first; | |
| 1363 int ending; | |
| 1364 } pdf_balance_processor; | |
| 1365 | |
| 1366 static void | |
| 1367 pdf_balance_q(fz_context *ctx, pdf_processor *proc_) | |
| 1368 { | |
| 1369 pdf_balance_processor *proc = (pdf_balance_processor*)proc_; | |
| 1370 (*proc->balance)++; | |
| 1371 } | |
| 1372 | |
| 1373 static void | |
| 1374 pdf_balance_Q(fz_context *ctx, pdf_processor *proc_) | |
| 1375 { | |
| 1376 pdf_balance_processor *proc = (pdf_balance_processor*)proc_; | |
| 1377 | |
| 1378 if (proc->ending) | |
| 1379 return; | |
| 1380 | |
| 1381 (*proc->balance)--; | |
| 1382 if (*proc->balance < *proc->min_q) | |
| 1383 *proc->min_q = *proc->balance; | |
| 1384 } | |
| 1385 | |
| 1386 static void | |
| 1387 pdf_balance_void(fz_context *ctx, pdf_processor *proc_) | |
| 1388 { | |
| 1389 pdf_balance_processor *proc = (pdf_balance_processor*)proc_; | |
| 1390 if (*proc->balance < *proc->min_op_q) | |
| 1391 *proc->min_op_q = *proc->balance; | |
| 1392 } | |
| 1393 | |
| 1394 #define BALANCE { pdf_balance_void(ctx, p); } | |
| 1395 | |
| 1396 static void pdf_balance_string(fz_context *ctx, pdf_processor *p, const char *x) BALANCE | |
| 1397 static void pdf_balance_int(fz_context *ctx, pdf_processor *p, int x) BALANCE | |
| 1398 static void pdf_balance_float(fz_context *ctx, pdf_processor *p, float x) BALANCE | |
| 1399 static void pdf_balance_float2(fz_context *ctx, pdf_processor *p, float x, float y) BALANCE | |
| 1400 static void pdf_balance_float3(fz_context *ctx, pdf_processor *p, float x, float y, float z) BALANCE | |
| 1401 static void pdf_balance_float4(fz_context *ctx, pdf_processor *p, float x, float y, float z, float w) BALANCE | |
| 1402 static void pdf_balance_float6(fz_context *ctx, pdf_processor *p, float a, float b, float c, float d, float e, float f) BALANCE | |
| 1403 | |
| 1404 static void pdf_balance_d(fz_context *ctx, pdf_processor *p, pdf_obj *array, float phase) BALANCE | |
| 1405 static void pdf_balance_gs_begin(fz_context *ctx, pdf_processor *p, const char *name, pdf_obj *extgstate) BALANCE | |
| 1406 static void pdf_balance_Tf(fz_context *ctx, pdf_processor *p, const char *name, pdf_font_desc *font, float size) BALANCE | |
| 1407 static void pdf_balance_TJ(fz_context *ctx, pdf_processor *p, pdf_obj *array) BALANCE | |
| 1408 static void pdf_balance_Tj(fz_context *ctx, pdf_processor *p, char *str, size_t len) BALANCE | |
| 1409 static void pdf_balance_squote(fz_context *ctx, pdf_processor *p, char *str, size_t len) BALANCE | |
| 1410 static void pdf_balance_dquote(fz_context *ctx, pdf_processor *p, float aw, float ac, char *str, size_t len) BALANCE | |
| 1411 static void pdf_balance_cs(fz_context *ctx, pdf_processor *p, const char *name, fz_colorspace *cs) BALANCE | |
| 1412 static void pdf_balance_sc_pattern(fz_context *ctx, pdf_processor *p, const char *name, pdf_pattern *pat, int n, float *color) BALANCE | |
| 1413 static void pdf_balance_sc_shade(fz_context *ctx, pdf_processor *p, const char *name, fz_shade *shade) BALANCE | |
| 1414 static void pdf_balance_sc_color(fz_context *ctx, pdf_processor *p, int n, float *color) BALANCE | |
| 1415 static void pdf_balance_BDC(fz_context *ctx, pdf_processor *p, const char *tag, pdf_obj *raw, pdf_obj *cooked) BALANCE | |
| 1416 static void pdf_balance_BI(fz_context *ctx, pdf_processor *p, fz_image *img, const char *colorspace) BALANCE | |
| 1417 static void pdf_balance_sh(fz_context *ctx, pdf_processor *p, const char *name, fz_shade *shade) BALANCE | |
| 1418 static void pdf_balance_Do_image(fz_context *ctx, pdf_processor *p, const char *name, fz_image *image) BALANCE | |
| 1419 static void pdf_balance_Do_form(fz_context *ctx, pdf_processor *p, const char *name, pdf_obj *xobj) BALANCE | |
| 1420 | |
| 1421 static void pdf_balance_EOD(fz_context *ctx, pdf_processor *p) | |
| 1422 { | |
| 1423 pdf_balance_processor *proc = (pdf_balance_processor *)p; | |
| 1424 | |
| 1425 proc->ending = 1; | |
| 1426 } | |
| 1427 | |
| 1428 static pdf_processor * | |
| 1429 pdf_new_balance_processor(fz_context *ctx, int *balance, int *min_q, int *min_op_q) | |
| 1430 { | |
| 1431 pdf_balance_processor *proc = pdf_new_processor(ctx, sizeof *proc); | |
| 1432 | |
| 1433 proc->super.op_q = pdf_balance_q; | |
| 1434 proc->super.op_Q = pdf_balance_Q; | |
| 1435 | |
| 1436 /* general graphics state */ | |
| 1437 proc->super.op_w = pdf_balance_float; | |
| 1438 proc->super.op_j = pdf_balance_int; | |
| 1439 proc->super.op_J = pdf_balance_int; | |
| 1440 proc->super.op_M = pdf_balance_float; | |
| 1441 proc->super.op_d = pdf_balance_d; | |
| 1442 proc->super.op_ri = pdf_balance_string; | |
| 1443 proc->super.op_i = pdf_balance_float; | |
| 1444 proc->super.op_gs_begin = pdf_balance_gs_begin; | |
| 1445 | |
| 1446 /* special graphics state */ | |
| 1447 proc->super.op_cm = pdf_balance_float6; | |
| 1448 | |
| 1449 /* path construction */ | |
| 1450 proc->super.op_m = pdf_balance_float2; | |
| 1451 proc->super.op_l = pdf_balance_float2; | |
| 1452 proc->super.op_c = pdf_balance_float6; | |
| 1453 proc->super.op_v = pdf_balance_float4; | |
| 1454 proc->super.op_y = pdf_balance_float4; | |
| 1455 proc->super.op_h = pdf_balance_void; | |
| 1456 proc->super.op_re = pdf_balance_float4; | |
| 1457 | |
| 1458 /* path painting */ | |
| 1459 proc->super.op_S = pdf_balance_void; | |
| 1460 proc->super.op_s = pdf_balance_void; | |
| 1461 proc->super.op_F = pdf_balance_void; | |
| 1462 proc->super.op_f = pdf_balance_void; | |
| 1463 proc->super.op_fstar = pdf_balance_void; | |
| 1464 proc->super.op_B = pdf_balance_void; | |
| 1465 proc->super.op_Bstar = pdf_balance_void; | |
| 1466 proc->super.op_b = pdf_balance_void; | |
| 1467 proc->super.op_bstar = pdf_balance_void; | |
| 1468 proc->super.op_n = pdf_balance_void; | |
| 1469 | |
| 1470 /* clipping paths */ | |
| 1471 proc->super.op_W = pdf_balance_void; | |
| 1472 proc->super.op_Wstar = pdf_balance_void; | |
| 1473 | |
| 1474 /* text objects */ | |
| 1475 proc->super.op_BT = pdf_balance_void; | |
| 1476 proc->super.op_ET = pdf_balance_void; | |
| 1477 | |
| 1478 /* text state */ | |
| 1479 proc->super.op_Tc = pdf_balance_float; | |
| 1480 proc->super.op_Tw = pdf_balance_float; | |
| 1481 proc->super.op_Tz = pdf_balance_float; | |
| 1482 proc->super.op_TL = pdf_balance_float; | |
| 1483 proc->super.op_Tf = pdf_balance_Tf; | |
| 1484 proc->super.op_Tr = pdf_balance_int; | |
| 1485 proc->super.op_Ts = pdf_balance_float; | |
| 1486 | |
| 1487 /* text positioning */ | |
| 1488 proc->super.op_Td = pdf_balance_float2; | |
| 1489 proc->super.op_TD = pdf_balance_float2; | |
| 1490 proc->super.op_Tm = pdf_balance_float6; | |
| 1491 proc->super.op_Tstar = pdf_balance_void; | |
| 1492 | |
| 1493 /* text showing */ | |
| 1494 proc->super.op_TJ = pdf_balance_TJ; | |
| 1495 proc->super.op_Tj = pdf_balance_Tj; | |
| 1496 proc->super.op_squote = pdf_balance_squote; | |
| 1497 proc->super.op_dquote = pdf_balance_dquote; | |
| 1498 | |
| 1499 /* type 3 fonts */ | |
| 1500 proc->super.op_d0 = pdf_balance_float2; | |
| 1501 proc->super.op_d1 = pdf_balance_float6; | |
| 1502 | |
| 1503 /* color */ | |
| 1504 proc->super.op_CS = pdf_balance_cs; | |
| 1505 proc->super.op_cs = pdf_balance_cs; | |
| 1506 proc->super.op_SC_color = pdf_balance_sc_color; | |
| 1507 proc->super.op_sc_color = pdf_balance_sc_color; | |
| 1508 proc->super.op_SC_pattern = pdf_balance_sc_pattern; | |
| 1509 proc->super.op_sc_pattern = pdf_balance_sc_pattern; | |
| 1510 proc->super.op_SC_shade = pdf_balance_sc_shade; | |
| 1511 proc->super.op_sc_shade = pdf_balance_sc_shade; | |
| 1512 | |
| 1513 proc->super.op_G = pdf_balance_float; | |
| 1514 proc->super.op_g = pdf_balance_float; | |
| 1515 proc->super.op_RG = pdf_balance_float3; | |
| 1516 proc->super.op_rg = pdf_balance_float3; | |
| 1517 proc->super.op_K = pdf_balance_float4; | |
| 1518 proc->super.op_k = pdf_balance_float4; | |
| 1519 | |
| 1520 /* shadings, images, xobjects */ | |
| 1521 proc->super.op_BI = pdf_balance_BI; | |
| 1522 proc->super.op_sh = pdf_balance_sh; | |
| 1523 proc->super.op_Do_image = pdf_balance_Do_image; | |
| 1524 proc->super.op_Do_form = pdf_balance_Do_form; | |
| 1525 | |
| 1526 /* marked content */ | |
| 1527 proc->super.op_MP = pdf_balance_string; | |
| 1528 proc->super.op_DP = pdf_balance_BDC; | |
| 1529 proc->super.op_BMC = pdf_balance_string; | |
| 1530 proc->super.op_BDC = pdf_balance_BDC; | |
| 1531 proc->super.op_EMC = pdf_balance_void; | |
| 1532 | |
| 1533 /* compatibility */ | |
| 1534 proc->super.op_BX = pdf_balance_void; | |
| 1535 proc->super.op_EX = pdf_balance_void; | |
| 1536 | |
| 1537 proc->super.op_EOD = pdf_balance_EOD; | |
| 1538 | |
| 1539 proc->balance = balance; | |
| 1540 proc->min_q = min_q; | |
| 1541 proc->min_op_q = min_op_q; | |
| 1542 | |
| 1543 return (pdf_processor*)proc; | |
| 1544 } | |
| 1545 | |
| 1546 void | |
| 1547 pdf_count_q_balance(fz_context *ctx, pdf_document *doc, pdf_obj *res, pdf_obj *stm, int *prepend, int *append) | |
| 1548 { | |
| 1549 pdf_processor *proc; | |
| 1550 | |
| 1551 int end_q = 0; | |
| 1552 int min_q = 0; | |
| 1553 int min_op_q = 1; | |
| 1554 | |
| 1555 proc = pdf_new_balance_processor(ctx, &end_q, &min_q, &min_op_q); | |
| 1556 fz_try(ctx) | |
| 1557 { | |
| 1558 pdf_process_raw_contents(ctx, proc, doc, res, stm, NULL); | |
| 1559 pdf_close_processor(ctx, proc); | |
| 1560 } | |
| 1561 fz_always(ctx) | |
| 1562 pdf_drop_processor(ctx, proc); | |
| 1563 fz_catch(ctx) | |
| 1564 fz_rethrow(ctx); | |
| 1565 | |
| 1566 /* normally zero, but in bad files there could be more Q than q */ | |
| 1567 *prepend = -min_q; | |
| 1568 | |
| 1569 /* how many Q are missing at the end */ | |
| 1570 *append = end_q - min_q; | |
| 1571 | |
| 1572 /* if there are unguarded operators we must add one level of q/Q around everything */ | |
| 1573 if (min_op_q == min_q) | |
| 1574 { | |
| 1575 *prepend += 1; | |
| 1576 *append += 1; | |
| 1577 } | |
| 1578 } |
