Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/source/tools/pdfaudit.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) 2023-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 /* | |
| 24 * PDF auditing tool | |
| 25 */ | |
| 26 | |
| 27 #include "mupdf/fitz.h" | |
| 28 #include "mupdf/pdf.h" | |
| 29 | |
| 30 #include <string.h> | |
| 31 #include <stdlib.h> | |
| 32 #include <stdio.h> | |
| 33 | |
| 34 #define SWITCH(x) switch ((intptr_t)(x)) | |
| 35 #define CASE(x) case ((intptr_t)(x)) | |
| 36 | |
| 37 typedef enum | |
| 38 { | |
| 39 AUDIT_UNKNOWN = 0, | |
| 40 AUDIT_THUMBNAILS, | |
| 41 AUDIT_IMAGES, | |
| 42 AUDIT_BOOKMARKS, | |
| 43 AUDIT_PAGE_OBJECTS, | |
| 44 AUDIT_CONTENT_STREAMS, | |
| 45 AUDIT_FONTS, | |
| 46 AUDIT_STRUCTURE_INFO, | |
| 47 AUDIT_FORMS, | |
| 48 AUDIT_LINK_ANNOTATIONS, | |
| 49 AUDIT_COMMENTS, | |
| 50 AUDIT_3DCONTENT, | |
| 51 AUDIT_NAMED_DESTINATIONS, | |
| 52 //AUDIT_DOCUMENT_OVERHEAD, // FIXME | |
| 53 AUDIT_COLORSPACES, | |
| 54 AUDIT_FORM_XOBJ, | |
| 55 AUDIT_EXTGS, | |
| 56 AUDIT_PIECE_INFORMATION, | |
| 57 AUDIT_EMBEDDED_FILES, | |
| 58 AUDIT_TRAILER, | |
| 59 AUDIT_RESOURCES, | |
| 60 AUDIT_OBJSTM, | |
| 61 AUDIT_METADATA, | |
| 62 AUDIT__MAX | |
| 63 } audit_type_t; | |
| 64 | |
| 65 const char *audit_type[] = | |
| 66 { | |
| 67 "UNKNOWN", | |
| 68 "THUMBNAILS", | |
| 69 "IMAGES", | |
| 70 "BOOKMARKS", | |
| 71 "PAGE OBJECTS", | |
| 72 "CONTENT_STREAMS", | |
| 73 "FONTS", | |
| 74 "STRUCTURE_INFO", | |
| 75 "FORMS", | |
| 76 "LINK_ANNOTATIONS", | |
| 77 "COMMENTS", | |
| 78 "3DCONTENT", | |
| 79 "NAMED_DESTINATIONS", | |
| 80 //"DOCUMENT_OVERHEAD", | |
| 81 "COLORSPACES", | |
| 82 "FORM_XOBJ", | |
| 83 "EXTGS", | |
| 84 "PIECE_INFORMATION", | |
| 85 "EMBEDDED_FILES", | |
| 86 "TRAILER", | |
| 87 "RESOURCES", | |
| 88 "OBJSTM", | |
| 89 "METADATA" | |
| 90 }; | |
| 91 | |
| 92 typedef struct | |
| 93 { | |
| 94 audit_type_t type; | |
| 95 int is_in_objstm; | |
| 96 /* The number of bytes this object will take in the file, not including any actual stream content. */ | |
| 97 size_t textsize; | |
| 98 /* The number of bytes of overhead "1 0 R\nendobj\n" plus "stream\nendstream\n" */ | |
| 99 size_t overhead; | |
| 100 /* Uncompressed stream size */ | |
| 101 size_t len; | |
| 102 /* Compressed stream size (not including 'stream\nendstream\n) */ | |
| 103 size_t stream_len; | |
| 104 } obj_info_t; | |
| 105 | |
| 106 enum | |
| 107 { | |
| 108 OP_w = 0, | |
| 109 OP_j, | |
| 110 OP_J, | |
| 111 OP_M, | |
| 112 OP_d, | |
| 113 OP_ri, | |
| 114 OP_gs_OP, | |
| 115 OP_gs_op, | |
| 116 OP_gs_OPM, | |
| 117 OP_gs_UseBlackPtComp, | |
| 118 OP_i, | |
| 119 OP_gs_begin, | |
| 120 OP_gs_BM, | |
| 121 OP_gs_CA, | |
| 122 OP_gs_ca, | |
| 123 OP_gs_SMask, | |
| 124 OP_gs_end, | |
| 125 OP_q, | |
| 126 OP_cm, | |
| 127 OP_m, | |
| 128 OP_l, | |
| 129 OP_c, | |
| 130 OP_v, | |
| 131 OP_y, | |
| 132 OP_h, | |
| 133 OP_re, | |
| 134 OP_S, | |
| 135 OP_s, | |
| 136 OP_F, | |
| 137 OP_f, | |
| 138 OP_fstar, | |
| 139 OP_B, | |
| 140 OP_Bstar, | |
| 141 OP_b, | |
| 142 OP_bstar, | |
| 143 OP_n, | |
| 144 OP_W, | |
| 145 OP_Wstar, | |
| 146 OP_BT, | |
| 147 OP_ET, | |
| 148 OP_Q, | |
| 149 OP_Tc, | |
| 150 OP_Tw, | |
| 151 OP_Tz, | |
| 152 OP_TL, | |
| 153 OP_Tf, | |
| 154 OP_Tr, | |
| 155 OP_Ts, | |
| 156 OP_Td, | |
| 157 OP_TD, | |
| 158 OP_Tm, | |
| 159 OP_Tstar, | |
| 160 OP_TJ, | |
| 161 OP_Tj, | |
| 162 OP_squote, | |
| 163 OP_dquote, | |
| 164 OP_d0, | |
| 165 OP_d1, | |
| 166 OP_CS, | |
| 167 OP_cs, | |
| 168 OP_SC_pattern, | |
| 169 OP_sc_pattern, | |
| 170 OP_SC_shade, | |
| 171 OP_sc_shade, | |
| 172 OP_SC_color, | |
| 173 OP_sc_color, | |
| 174 OP_G, | |
| 175 OP_g, | |
| 176 OP_RG, | |
| 177 OP_rg, | |
| 178 OP_K, | |
| 179 OP_k, | |
| 180 OP_BI, | |
| 181 OP_sh, | |
| 182 OP_Do_image, | |
| 183 OP_Do_form, | |
| 184 OP_MP, | |
| 185 OP_DP, | |
| 186 OP_BMC, | |
| 187 OP_BDC, | |
| 188 OP_EMC, | |
| 189 OP_BX, | |
| 190 OP_EX, | |
| 191 OP_END | |
| 192 }; | |
| 193 | |
| 194 const char *op_names[] = | |
| 195 { | |
| 196 "w", | |
| 197 "j", | |
| 198 "J", | |
| 199 "M", | |
| 200 "d", | |
| 201 "ri", | |
| 202 "gs_OP", | |
| 203 "gs_op", | |
| 204 "gs_OPM", | |
| 205 "gs_UseBlackPtComp", | |
| 206 "i", | |
| 207 "gs_begin", | |
| 208 "gs_BM", | |
| 209 "gs_CA", | |
| 210 "gs_ca", | |
| 211 "gs_SMask", | |
| 212 "gs_end", | |
| 213 "q", | |
| 214 "cm", | |
| 215 "m", | |
| 216 "l", | |
| 217 "c", | |
| 218 "v", | |
| 219 "y", | |
| 220 "h", | |
| 221 "re", | |
| 222 "S", | |
| 223 "s", | |
| 224 "F", | |
| 225 "f", | |
| 226 "fstar", | |
| 227 "B", | |
| 228 "Bstar", | |
| 229 "b", | |
| 230 "bstar", | |
| 231 "n", | |
| 232 "W", | |
| 233 "Wstar", | |
| 234 "BT", | |
| 235 "ET", | |
| 236 "Q", | |
| 237 "Tc", | |
| 238 "Tw", | |
| 239 "Tz", | |
| 240 "TL", | |
| 241 "Tf", | |
| 242 "Tr", | |
| 243 "Ts", | |
| 244 "Td", | |
| 245 "TD", | |
| 246 "Tm", | |
| 247 "Tstar", | |
| 248 "TJ", | |
| 249 "Tj", | |
| 250 "squote", | |
| 251 "dquote", | |
| 252 "d0", | |
| 253 "d1", | |
| 254 "CS", | |
| 255 "cs", | |
| 256 "SC_pattern", | |
| 257 "sc_pattern", | |
| 258 "SC_shade", | |
| 259 "sc_shade", | |
| 260 "SC_color", | |
| 261 "sc_color", | |
| 262 "G", | |
| 263 "g", | |
| 264 "RG", | |
| 265 "rg", | |
| 266 "K", | |
| 267 "k", | |
| 268 "BI", | |
| 269 "sh", | |
| 270 "Do_image", | |
| 271 "Do_form", | |
| 272 "MP", | |
| 273 "DP", | |
| 274 "BMC", | |
| 275 "BDC", | |
| 276 "EMC", | |
| 277 "BX", | |
| 278 "EX", | |
| 279 }; | |
| 280 | |
| 281 typedef struct | |
| 282 { | |
| 283 size_t len[OP_END]; | |
| 284 } op_usage_t; | |
| 285 | |
| 286 typedef struct | |
| 287 { | |
| 288 pdf_processor super; | |
| 289 pdf_document *doc; | |
| 290 int structparents; | |
| 291 pdf_processor *mine; | |
| 292 pdf_processor *chain; | |
| 293 pdf_filter_options *global_options; | |
| 294 op_usage_t *op_usage; | |
| 295 fz_buffer *buffer; | |
| 296 } pdf_opcount_processor; | |
| 297 | |
| 298 /* general graphics state */ | |
| 299 | |
| 300 static void | |
| 301 pdf_opcount_w(fz_context *ctx, pdf_processor *proc, float linewidth) | |
| 302 { | |
| 303 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 304 size_t z = p->buffer->len; | |
| 305 | |
| 306 if (p->mine->op_w) | |
| 307 p->mine->op_w(ctx, p->mine, linewidth); | |
| 308 | |
| 309 z = p->buffer->len - z; | |
| 310 p->op_usage->len[OP_w] += z; | |
| 311 } | |
| 312 | |
| 313 static void | |
| 314 pdf_opcount_j(fz_context *ctx, pdf_processor *proc, int linejoin) | |
| 315 { | |
| 316 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 317 size_t z = p->buffer->len; | |
| 318 | |
| 319 if (p->mine->op_j) | |
| 320 p->mine->op_j(ctx, p->mine, linejoin); | |
| 321 | |
| 322 z = p->buffer->len - z; | |
| 323 p->op_usage->len[OP_j] += z; | |
| 324 } | |
| 325 | |
| 326 static void | |
| 327 pdf_opcount_J(fz_context *ctx, pdf_processor *proc, int linecap) | |
| 328 { | |
| 329 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 330 size_t z = p->buffer->len; | |
| 331 | |
| 332 if (p->mine->op_J) | |
| 333 p->mine->op_J(ctx, p->mine, linecap); | |
| 334 | |
| 335 z = p->buffer->len - z; | |
| 336 p->op_usage->len[OP_J] += z; | |
| 337 } | |
| 338 | |
| 339 static void | |
| 340 pdf_opcount_M(fz_context *ctx, pdf_processor *proc, float miterlimit) | |
| 341 { | |
| 342 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 343 size_t z = p->buffer->len; | |
| 344 | |
| 345 if (p->mine->op_M) | |
| 346 p->mine->op_M(ctx, p->mine, miterlimit); | |
| 347 | |
| 348 z = p->buffer->len - z; | |
| 349 p->op_usage->len[OP_M] += z; | |
| 350 } | |
| 351 | |
| 352 static void | |
| 353 pdf_opcount_d(fz_context *ctx, pdf_processor *proc, pdf_obj *array, float phase) | |
| 354 { | |
| 355 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 356 size_t z = p->buffer->len; | |
| 357 | |
| 358 if (p->mine->op_d) | |
| 359 p->mine->op_d(ctx, p->mine, array, phase); | |
| 360 | |
| 361 z = p->buffer->len - z; | |
| 362 p->op_usage->len[OP_d] += z; | |
| 363 } | |
| 364 | |
| 365 static void | |
| 366 pdf_opcount_ri(fz_context *ctx, pdf_processor *proc, const char *intent) | |
| 367 { | |
| 368 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 369 size_t z = p->buffer->len; | |
| 370 | |
| 371 if (p->mine->op_ri) | |
| 372 p->mine->op_ri(ctx, p->mine, intent); | |
| 373 | |
| 374 z = p->buffer->len - z; | |
| 375 p->op_usage->len[OP_ri] += z; | |
| 376 } | |
| 377 | |
| 378 static void | |
| 379 pdf_opcount_gs_OP(fz_context *ctx, pdf_processor *proc, int b) | |
| 380 { | |
| 381 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 382 size_t z = p->buffer->len; | |
| 383 | |
| 384 if (p->mine->op_gs_OP) | |
| 385 p->mine->op_gs_OP(ctx, p->mine, b); | |
| 386 | |
| 387 z = p->buffer->len - z; | |
| 388 p->op_usage->len[OP_gs_OP] += z; | |
| 389 } | |
| 390 | |
| 391 static void | |
| 392 pdf_opcount_gs_op(fz_context *ctx, pdf_processor *proc, int b) | |
| 393 { | |
| 394 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 395 size_t z = p->buffer->len; | |
| 396 | |
| 397 if (p->mine->op_gs_op) | |
| 398 p->mine->op_gs_op(ctx, p->mine, b); | |
| 399 | |
| 400 z = p->buffer->len - z; | |
| 401 p->op_usage->len[OP_gs_op] += z; | |
| 402 } | |
| 403 | |
| 404 static void | |
| 405 pdf_opcount_gs_OPM(fz_context *ctx, pdf_processor *proc, int i) | |
| 406 { | |
| 407 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 408 size_t z = p->buffer->len; | |
| 409 | |
| 410 if (p->mine->op_gs_OPM) | |
| 411 p->mine->op_gs_OPM(ctx, p->mine, i); | |
| 412 | |
| 413 z = p->buffer->len - z; | |
| 414 p->op_usage->len[OP_gs_OPM] += z; | |
| 415 } | |
| 416 | |
| 417 static void | |
| 418 pdf_opcount_gs_UseBlackPtComp(fz_context *ctx, pdf_processor *proc, pdf_obj *name) | |
| 419 { | |
| 420 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 421 size_t z = p->buffer->len; | |
| 422 | |
| 423 if (p->mine->op_gs_UseBlackPtComp) | |
| 424 p->mine->op_gs_UseBlackPtComp(ctx, p->mine, name); | |
| 425 | |
| 426 z = p->buffer->len - z; | |
| 427 p->op_usage->len[OP_gs_UseBlackPtComp] += z; | |
| 428 } | |
| 429 | |
| 430 static void | |
| 431 pdf_opcount_i(fz_context *ctx, pdf_processor *proc, float flatness) | |
| 432 { | |
| 433 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 434 size_t z = p->buffer->len; | |
| 435 | |
| 436 if (p->mine->op_i) | |
| 437 p->mine->op_i(ctx, p->mine, flatness); | |
| 438 | |
| 439 z = p->buffer->len - z; | |
| 440 p->op_usage->len[OP_i] += z; | |
| 441 } | |
| 442 | |
| 443 static void | |
| 444 pdf_opcount_gs_begin(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *extgstate) | |
| 445 { | |
| 446 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 447 size_t z = p->buffer->len; | |
| 448 | |
| 449 if (p->mine->op_gs_begin) | |
| 450 p->mine->op_gs_begin(ctx, p->mine, name, extgstate); | |
| 451 | |
| 452 z = p->buffer->len - z; | |
| 453 p->op_usage->len[OP_gs_begin] += z; | |
| 454 } | |
| 455 | |
| 456 static void | |
| 457 pdf_opcount_gs_BM(fz_context *ctx, pdf_processor *proc, const char *blendmode) | |
| 458 { | |
| 459 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 460 size_t z = p->buffer->len; | |
| 461 | |
| 462 if (p->mine->op_gs_BM) | |
| 463 p->mine->op_gs_BM(ctx, p->mine, blendmode); | |
| 464 | |
| 465 z = p->buffer->len - z; | |
| 466 p->op_usage->len[OP_gs_BM] += z; | |
| 467 } | |
| 468 | |
| 469 static void | |
| 470 pdf_opcount_gs_CA(fz_context *ctx, pdf_processor *proc, float alpha) | |
| 471 { | |
| 472 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 473 size_t z = p->buffer->len; | |
| 474 | |
| 475 if (p->mine->op_gs_CA) | |
| 476 p->mine->op_gs_CA(ctx, p->mine, alpha); | |
| 477 | |
| 478 z = p->buffer->len - z; | |
| 479 p->op_usage->len[OP_gs_CA] += z; | |
| 480 } | |
| 481 | |
| 482 static void | |
| 483 pdf_opcount_gs_ca(fz_context *ctx, pdf_processor *proc, float alpha) | |
| 484 { | |
| 485 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 486 size_t z = p->buffer->len; | |
| 487 | |
| 488 if (p->mine->op_gs_ca) | |
| 489 p->mine->op_gs_ca(ctx, p->mine, alpha); | |
| 490 | |
| 491 z = p->buffer->len - z; | |
| 492 p->op_usage->len[OP_gs_ca] += z; | |
| 493 } | |
| 494 | |
| 495 static void | |
| 496 pdf_opcount_gs_SMask(fz_context *ctx, pdf_processor *proc, pdf_obj *smask, fz_colorspace *smask_cs, float *bc, int luminosity, pdf_obj *obj) | |
| 497 { | |
| 498 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 499 size_t z = p->buffer->len; | |
| 500 | |
| 501 if (p->mine->op_gs_SMask) | |
| 502 p->mine->op_gs_SMask(ctx, p->mine, smask, smask_cs, bc, luminosity, obj); | |
| 503 | |
| 504 z = p->buffer->len - z; | |
| 505 p->op_usage->len[OP_gs_SMask] += z; | |
| 506 } | |
| 507 | |
| 508 static void | |
| 509 pdf_opcount_gs_end(fz_context *ctx, pdf_processor *proc) | |
| 510 { | |
| 511 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 512 size_t z = p->buffer->len; | |
| 513 | |
| 514 if (p->mine->op_gs_end) | |
| 515 p->mine->op_gs_end(ctx, p->mine); | |
| 516 | |
| 517 z = p->buffer->len - z; | |
| 518 p->op_usage->len[OP_gs_end] += z; | |
| 519 } | |
| 520 | |
| 521 /* special graphics state */ | |
| 522 | |
| 523 static void | |
| 524 pdf_opcount_q(fz_context *ctx, pdf_processor *proc) | |
| 525 { | |
| 526 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 527 size_t z = p->buffer->len; | |
| 528 | |
| 529 if (p->mine->op_q) | |
| 530 p->mine->op_q(ctx, p->mine); | |
| 531 | |
| 532 z = p->buffer->len - z; | |
| 533 p->op_usage->len[OP_q] += z; | |
| 534 } | |
| 535 | |
| 536 static void | |
| 537 pdf_opcount_cm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f) | |
| 538 { | |
| 539 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 540 size_t z = p->buffer->len; | |
| 541 | |
| 542 if (p->mine->op_cm) | |
| 543 p->mine->op_cm(ctx, p->mine, a, b, c, d, e, f); | |
| 544 | |
| 545 z = p->buffer->len - z; | |
| 546 p->op_usage->len[OP_cm] += z; | |
| 547 } | |
| 548 | |
| 549 /* path construction */ | |
| 550 | |
| 551 static void | |
| 552 pdf_opcount_m(fz_context *ctx, pdf_processor *proc, float x, float y) | |
| 553 { | |
| 554 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 555 size_t z = p->buffer->len; | |
| 556 | |
| 557 if (p->mine->op_m) | |
| 558 p->mine->op_m(ctx, p->mine, x, y); | |
| 559 | |
| 560 z = p->buffer->len - z; | |
| 561 p->op_usage->len[OP_m] += z; | |
| 562 } | |
| 563 | |
| 564 static void | |
| 565 pdf_opcount_l(fz_context *ctx, pdf_processor *proc, float x, float y) | |
| 566 { | |
| 567 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 568 size_t z = p->buffer->len; | |
| 569 | |
| 570 if (p->mine->op_l) | |
| 571 p->mine->op_l(ctx, p->mine, x, y); | |
| 572 | |
| 573 z = p->buffer->len - z; | |
| 574 p->op_usage->len[OP_l] += z; | |
| 575 } | |
| 576 | |
| 577 static void | |
| 578 pdf_opcount_c(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x2, float y2, float x3, float y3) | |
| 579 { | |
| 580 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 581 size_t z = p->buffer->len; | |
| 582 | |
| 583 if (p->mine->op_c) | |
| 584 p->mine->op_c(ctx, p->mine, x1, y1, x2, y2, x3, y3); | |
| 585 | |
| 586 z = p->buffer->len - z; | |
| 587 p->op_usage->len[OP_c] += z; | |
| 588 } | |
| 589 | |
| 590 static void | |
| 591 pdf_opcount_v(fz_context *ctx, pdf_processor *proc, float x2, float y2, float x3, float y3) | |
| 592 { | |
| 593 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 594 size_t z = p->buffer->len; | |
| 595 | |
| 596 if (p->mine->op_v) | |
| 597 p->mine->op_v(ctx, p->mine, x2, y2, x3, y3); | |
| 598 | |
| 599 z = p->buffer->len - z; | |
| 600 p->op_usage->len[OP_v] += z; | |
| 601 } | |
| 602 | |
| 603 static void | |
| 604 pdf_opcount_y(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x3, float y3) | |
| 605 { | |
| 606 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 607 size_t z = p->buffer->len; | |
| 608 | |
| 609 if (p->mine->op_y) | |
| 610 p->mine->op_y(ctx, p->mine, x1, y1, x3, y3); | |
| 611 | |
| 612 z = p->buffer->len - z; | |
| 613 p->op_usage->len[OP_y] += z; | |
| 614 } | |
| 615 | |
| 616 static void | |
| 617 pdf_opcount_h(fz_context *ctx, pdf_processor *proc) | |
| 618 { | |
| 619 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 620 size_t z = p->buffer->len; | |
| 621 | |
| 622 if (p->mine->op_h) | |
| 623 p->mine->op_h(ctx, p->mine); | |
| 624 | |
| 625 z = p->buffer->len - z; | |
| 626 p->op_usage->len[OP_h] += z; | |
| 627 } | |
| 628 | |
| 629 static void | |
| 630 pdf_opcount_re(fz_context *ctx, pdf_processor *proc, float x, float y, float w, float h) | |
| 631 { | |
| 632 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 633 size_t z = p->buffer->len; | |
| 634 | |
| 635 if (p->mine->op_re) | |
| 636 p->mine->op_re(ctx, p->mine, x, y, w, h); | |
| 637 | |
| 638 z = p->buffer->len - z; | |
| 639 p->op_usage->len[OP_re] += z; | |
| 640 } | |
| 641 | |
| 642 /* path painting */ | |
| 643 | |
| 644 static void | |
| 645 pdf_opcount_S(fz_context *ctx, pdf_processor *proc) | |
| 646 { | |
| 647 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 648 size_t z = p->buffer->len; | |
| 649 | |
| 650 if (p->mine->op_S) | |
| 651 p->mine->op_S(ctx, p->mine); | |
| 652 | |
| 653 z = p->buffer->len - z; | |
| 654 p->op_usage->len[OP_S] += z; | |
| 655 } | |
| 656 | |
| 657 static void | |
| 658 pdf_opcount_s(fz_context *ctx, pdf_processor *proc) | |
| 659 { | |
| 660 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 661 size_t z = p->buffer->len; | |
| 662 | |
| 663 if (p->mine->op_s) | |
| 664 p->mine->op_s(ctx, p->mine); | |
| 665 | |
| 666 z = p->buffer->len - z; | |
| 667 p->op_usage->len[OP_s] += z; | |
| 668 } | |
| 669 | |
| 670 static void | |
| 671 pdf_opcount_F(fz_context *ctx, pdf_processor *proc) | |
| 672 { | |
| 673 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 674 size_t z = p->buffer->len; | |
| 675 | |
| 676 if (p->mine->op_F) | |
| 677 p->mine->op_F(ctx, p->mine); | |
| 678 | |
| 679 z = p->buffer->len - z; | |
| 680 p->op_usage->len[OP_F] += z; | |
| 681 } | |
| 682 | |
| 683 static void | |
| 684 pdf_opcount_f(fz_context *ctx, pdf_processor *proc) | |
| 685 { | |
| 686 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 687 size_t z = p->buffer->len; | |
| 688 | |
| 689 if (p->mine->op_f) | |
| 690 p->mine->op_f(ctx, p->mine); | |
| 691 | |
| 692 z = p->buffer->len - z; | |
| 693 p->op_usage->len[OP_f] += z; | |
| 694 } | |
| 695 | |
| 696 static void | |
| 697 pdf_opcount_fstar(fz_context *ctx, pdf_processor *proc) | |
| 698 { | |
| 699 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 700 size_t z = p->buffer->len; | |
| 701 | |
| 702 if (p->mine->op_fstar) | |
| 703 p->mine->op_fstar(ctx, p->mine); | |
| 704 | |
| 705 z = p->buffer->len - z; | |
| 706 p->op_usage->len[OP_fstar] += z; | |
| 707 } | |
| 708 | |
| 709 static void | |
| 710 pdf_opcount_B(fz_context *ctx, pdf_processor *proc) | |
| 711 { | |
| 712 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 713 size_t z = p->buffer->len; | |
| 714 | |
| 715 if (p->mine->op_B) | |
| 716 p->mine->op_B(ctx, p->mine); | |
| 717 | |
| 718 z = p->buffer->len - z; | |
| 719 p->op_usage->len[OP_B] += z; | |
| 720 } | |
| 721 | |
| 722 static void | |
| 723 pdf_opcount_Bstar(fz_context *ctx, pdf_processor *proc) | |
| 724 { | |
| 725 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 726 size_t z = p->buffer->len; | |
| 727 | |
| 728 if (p->mine->op_Bstar) | |
| 729 p->mine->op_Bstar(ctx, p->mine); | |
| 730 | |
| 731 z = p->buffer->len - z; | |
| 732 p->op_usage->len[OP_Bstar] += z; | |
| 733 } | |
| 734 | |
| 735 static void | |
| 736 pdf_opcount_b(fz_context *ctx, pdf_processor *proc) | |
| 737 { | |
| 738 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 739 size_t z = p->buffer->len; | |
| 740 | |
| 741 if (p->mine->op_b) | |
| 742 p->mine->op_b(ctx, p->mine); | |
| 743 | |
| 744 z = p->buffer->len - z; | |
| 745 p->op_usage->len[OP_b] += z; | |
| 746 } | |
| 747 | |
| 748 static void | |
| 749 pdf_opcount_bstar(fz_context *ctx, pdf_processor *proc) | |
| 750 { | |
| 751 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 752 size_t z = p->buffer->len; | |
| 753 | |
| 754 if (p->mine->op_bstar) | |
| 755 p->mine->op_bstar(ctx, p->mine); | |
| 756 | |
| 757 z = p->buffer->len - z; | |
| 758 p->op_usage->len[OP_bstar] += z; | |
| 759 } | |
| 760 | |
| 761 static void | |
| 762 pdf_opcount_n(fz_context *ctx, pdf_processor *proc) | |
| 763 { | |
| 764 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 765 size_t z = p->buffer->len; | |
| 766 | |
| 767 if (p->mine->op_n) | |
| 768 p->mine->op_n(ctx, p->mine); | |
| 769 | |
| 770 z = p->buffer->len - z; | |
| 771 p->op_usage->len[OP_n] += z; | |
| 772 } | |
| 773 | |
| 774 /* clipping paths */ | |
| 775 | |
| 776 static void | |
| 777 pdf_opcount_W(fz_context *ctx, pdf_processor *proc) | |
| 778 { | |
| 779 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 780 size_t z = p->buffer->len; | |
| 781 | |
| 782 if (p->mine->op_W) | |
| 783 p->mine->op_W(ctx, p->mine); | |
| 784 | |
| 785 z = p->buffer->len - z; | |
| 786 p->op_usage->len[OP_W] += z; | |
| 787 } | |
| 788 | |
| 789 static void | |
| 790 pdf_opcount_Wstar(fz_context *ctx, pdf_processor *proc) | |
| 791 { | |
| 792 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 793 size_t z = p->buffer->len; | |
| 794 | |
| 795 if (p->mine->op_Wstar) | |
| 796 p->mine->op_Wstar(ctx, p->mine); | |
| 797 | |
| 798 z = p->buffer->len - z; | |
| 799 p->op_usage->len[OP_Wstar] += z; | |
| 800 } | |
| 801 | |
| 802 /* text objects */ | |
| 803 | |
| 804 static void | |
| 805 pdf_opcount_BT(fz_context *ctx, pdf_processor *proc) | |
| 806 { | |
| 807 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 808 size_t z = p->buffer->len; | |
| 809 | |
| 810 if (p->mine->op_BT) | |
| 811 p->mine->op_BT(ctx, p->mine); | |
| 812 | |
| 813 z = p->buffer->len - z; | |
| 814 p->op_usage->len[OP_BT] += z; | |
| 815 } | |
| 816 | |
| 817 static void | |
| 818 pdf_opcount_ET(fz_context *ctx, pdf_processor *proc) | |
| 819 { | |
| 820 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 821 size_t z = p->buffer->len; | |
| 822 | |
| 823 if (p->mine->op_ET) | |
| 824 p->mine->op_ET(ctx, p->mine); | |
| 825 | |
| 826 z = p->buffer->len - z; | |
| 827 p->op_usage->len[OP_ET] += z; | |
| 828 } | |
| 829 | |
| 830 static void | |
| 831 pdf_opcount_Q(fz_context *ctx, pdf_processor *proc) | |
| 832 { | |
| 833 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 834 size_t z = p->buffer->len; | |
| 835 | |
| 836 if (p->mine->op_Q) | |
| 837 p->mine->op_Q(ctx, p->mine); | |
| 838 | |
| 839 z = p->buffer->len - z; | |
| 840 p->op_usage->len[OP_Q] += z; | |
| 841 } | |
| 842 | |
| 843 /* text state */ | |
| 844 | |
| 845 static void | |
| 846 pdf_opcount_Tc(fz_context *ctx, pdf_processor *proc, float charspace) | |
| 847 { | |
| 848 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 849 size_t z = p->buffer->len; | |
| 850 | |
| 851 if (p->mine->op_Tc) | |
| 852 p->mine->op_Tc(ctx, p->mine, charspace); | |
| 853 | |
| 854 z = p->buffer->len - z; | |
| 855 p->op_usage->len[OP_Tc] += z; | |
| 856 } | |
| 857 | |
| 858 static void | |
| 859 pdf_opcount_Tw(fz_context *ctx, pdf_processor *proc, float wordspace) | |
| 860 { | |
| 861 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 862 size_t z = p->buffer->len; | |
| 863 | |
| 864 if (p->mine->op_Tw) | |
| 865 p->mine->op_Tw(ctx, p->mine, wordspace); | |
| 866 | |
| 867 z = p->buffer->len - z; | |
| 868 p->op_usage->len[OP_Tw] += z; | |
| 869 } | |
| 870 | |
| 871 static void | |
| 872 pdf_opcount_Tz(fz_context *ctx, pdf_processor *proc, float scale) | |
| 873 { | |
| 874 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 875 size_t z = p->buffer->len; | |
| 876 | |
| 877 if (p->mine->op_Tz) | |
| 878 p->mine->op_Tz(ctx, p->mine, scale); | |
| 879 | |
| 880 z = p->buffer->len - z; | |
| 881 p->op_usage->len[OP_Tz] += z; | |
| 882 } | |
| 883 | |
| 884 static void | |
| 885 pdf_opcount_TL(fz_context *ctx, pdf_processor *proc, float leading) | |
| 886 { | |
| 887 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 888 size_t z = p->buffer->len; | |
| 889 | |
| 890 if (p->mine->op_TL) | |
| 891 p->mine->op_TL(ctx, p->mine, leading); | |
| 892 | |
| 893 z = p->buffer->len - z; | |
| 894 p->op_usage->len[OP_TL] += z; | |
| 895 } | |
| 896 | |
| 897 static void | |
| 898 pdf_opcount_Tf(fz_context *ctx, pdf_processor *proc, const char *name, pdf_font_desc *font, float size) | |
| 899 { | |
| 900 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 901 size_t z = p->buffer->len; | |
| 902 | |
| 903 if (p->mine->op_Tf) | |
| 904 p->mine->op_Tf(ctx, p->mine, name, font, size); | |
| 905 | |
| 906 z = p->buffer->len - z; | |
| 907 p->op_usage->len[OP_Tf] += z; | |
| 908 } | |
| 909 | |
| 910 static void | |
| 911 pdf_opcount_Tr(fz_context *ctx, pdf_processor *proc, int render) | |
| 912 { | |
| 913 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 914 size_t z = p->buffer->len; | |
| 915 | |
| 916 if (p->mine->op_Tr) | |
| 917 p->mine->op_Tr(ctx, p->mine, render); | |
| 918 | |
| 919 z = p->buffer->len - z; | |
| 920 p->op_usage->len[OP_Tr] += z; | |
| 921 } | |
| 922 | |
| 923 static void | |
| 924 pdf_opcount_Ts(fz_context *ctx, pdf_processor *proc, float rise) | |
| 925 { | |
| 926 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 927 size_t z = p->buffer->len; | |
| 928 | |
| 929 if (p->mine->op_Ts) | |
| 930 p->mine->op_Ts(ctx, p->mine, rise); | |
| 931 | |
| 932 z = p->buffer->len - z; | |
| 933 p->op_usage->len[OP_Ts] += z; | |
| 934 } | |
| 935 | |
| 936 /* text positioning */ | |
| 937 | |
| 938 static void | |
| 939 pdf_opcount_Td(fz_context *ctx, pdf_processor *proc, float tx, float ty) | |
| 940 { | |
| 941 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 942 size_t z = p->buffer->len; | |
| 943 | |
| 944 if (p->mine->op_Td) | |
| 945 p->mine->op_Td(ctx, p->mine, tx, ty); | |
| 946 | |
| 947 z = p->buffer->len - z; | |
| 948 p->op_usage->len[OP_Td] += z; | |
| 949 } | |
| 950 | |
| 951 static void | |
| 952 pdf_opcount_TD(fz_context *ctx, pdf_processor *proc, float tx, float ty) | |
| 953 { | |
| 954 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 955 size_t z = p->buffer->len; | |
| 956 | |
| 957 if (p->mine->op_TD) | |
| 958 p->mine->op_TD(ctx, p->mine, tx, ty); | |
| 959 | |
| 960 z = p->buffer->len - z; | |
| 961 p->op_usage->len[OP_TD] += z; | |
| 962 } | |
| 963 | |
| 964 static void | |
| 965 pdf_opcount_Tm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f) | |
| 966 { | |
| 967 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 968 size_t z = p->buffer->len; | |
| 969 | |
| 970 if (p->mine->op_Tm) | |
| 971 p->mine->op_Tm(ctx, p->mine, a, b, c, d, e, f); | |
| 972 | |
| 973 z = p->buffer->len - z; | |
| 974 p->op_usage->len[OP_Tm] += z; | |
| 975 } | |
| 976 | |
| 977 static void | |
| 978 pdf_opcount_Tstar(fz_context *ctx, pdf_processor *proc) | |
| 979 { | |
| 980 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 981 size_t z = p->buffer->len; | |
| 982 | |
| 983 if (p->mine->op_Tstar) | |
| 984 p->mine->op_Tstar(ctx, p->mine); | |
| 985 | |
| 986 z = p->buffer->len - z; | |
| 987 p->op_usage->len[OP_Tstar] += z; | |
| 988 } | |
| 989 | |
| 990 /* text showing */ | |
| 991 | |
| 992 static void | |
| 993 pdf_opcount_TJ(fz_context *ctx, pdf_processor *proc, pdf_obj *array) | |
| 994 { | |
| 995 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 996 size_t z = p->buffer->len; | |
| 997 | |
| 998 if (p->mine->op_TJ) | |
| 999 p->mine->op_TJ(ctx, p->mine, array); | |
| 1000 | |
| 1001 z = p->buffer->len - z; | |
| 1002 p->op_usage->len[OP_TJ] += z; | |
| 1003 } | |
| 1004 | |
| 1005 static void | |
| 1006 pdf_opcount_Tj(fz_context *ctx, pdf_processor *proc, char *str, size_t len) | |
| 1007 { | |
| 1008 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1009 size_t z = p->buffer->len; | |
| 1010 | |
| 1011 if (p->mine->op_Tj) | |
| 1012 p->mine->op_Tj(ctx, p->mine, str, len); | |
| 1013 | |
| 1014 z = p->buffer->len - z; | |
| 1015 p->op_usage->len[OP_Tj] += z; | |
| 1016 } | |
| 1017 | |
| 1018 static void | |
| 1019 pdf_opcount_squote(fz_context *ctx, pdf_processor *proc, char *str, size_t len) | |
| 1020 { | |
| 1021 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1022 size_t z = p->buffer->len; | |
| 1023 | |
| 1024 if (p->mine->op_squote) | |
| 1025 p->mine->op_squote(ctx, p->mine, str, len); | |
| 1026 | |
| 1027 z = p->buffer->len - z; | |
| 1028 p->op_usage->len[OP_squote] += z; | |
| 1029 } | |
| 1030 | |
| 1031 static void | |
| 1032 pdf_opcount_dquote(fz_context *ctx, pdf_processor *proc, float aw, float ac, char *str, size_t len) | |
| 1033 { | |
| 1034 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1035 size_t z = p->buffer->len; | |
| 1036 | |
| 1037 if (p->mine->op_dquote) | |
| 1038 p->mine->op_dquote(ctx, p->mine, aw, ac, str, len); | |
| 1039 | |
| 1040 z = p->buffer->len - z; | |
| 1041 p->op_usage->len[OP_dquote] += z; | |
| 1042 } | |
| 1043 | |
| 1044 /* type 3 fonts */ | |
| 1045 | |
| 1046 static void | |
| 1047 pdf_opcount_d0(fz_context *ctx, pdf_processor *proc, float wx, float wy) | |
| 1048 { | |
| 1049 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1050 size_t z = p->buffer->len; | |
| 1051 | |
| 1052 if (p->mine->op_d0) | |
| 1053 p->mine->op_d0(ctx, p->mine, wx, wy); | |
| 1054 | |
| 1055 z = p->buffer->len - z; | |
| 1056 p->op_usage->len[OP_d0] += z; | |
| 1057 } | |
| 1058 | |
| 1059 static void | |
| 1060 pdf_opcount_d1(fz_context *ctx, pdf_processor *proc, float wx, float wy, float llx, float lly, float urx, float ury) | |
| 1061 { | |
| 1062 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1063 size_t z = p->buffer->len; | |
| 1064 | |
| 1065 if (p->mine->op_d1) | |
| 1066 p->mine->op_d1(ctx, p->mine, wx, wy, llx, lly, urx, ury); | |
| 1067 | |
| 1068 z = p->buffer->len - z; | |
| 1069 p->op_usage->len[OP_d1] += z; | |
| 1070 } | |
| 1071 | |
| 1072 /* color */ | |
| 1073 | |
| 1074 static void | |
| 1075 pdf_opcount_CS(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *cs) | |
| 1076 { | |
| 1077 pdf_opcount_processor *p = (pdf_opcount_processor *)proc; | |
| 1078 size_t z = p->buffer->len; | |
| 1079 | |
| 1080 if (p->mine->op_CS) | |
| 1081 p->mine->op_CS(ctx, p->mine, name, cs); | |
| 1082 | |
| 1083 z = p->buffer->len - z; | |
| 1084 p->op_usage->len[OP_CS] += z; | |
| 1085 } | |
| 1086 | |
| 1087 static void | |
| 1088 pdf_opcount_cs(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *cs) | |
| 1089 { | |
| 1090 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1091 size_t z = p->buffer->len; | |
| 1092 | |
| 1093 if (p->mine->op_cs) | |
| 1094 p->mine->op_cs(ctx, p->mine, name, cs); | |
| 1095 | |
| 1096 z = p->buffer->len - z; | |
| 1097 p->op_usage->len[OP_cs] += z; | |
| 1098 } | |
| 1099 | |
| 1100 static void | |
| 1101 pdf_opcount_SC_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color) | |
| 1102 { | |
| 1103 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1104 size_t z = p->buffer->len; | |
| 1105 | |
| 1106 if (p->mine->op_SC_pattern) | |
| 1107 p->mine->op_SC_pattern(ctx, p->mine, name, pat, n, color); | |
| 1108 | |
| 1109 z = p->buffer->len - z; | |
| 1110 p->op_usage->len[OP_SC_pattern] += z; | |
| 1111 } | |
| 1112 | |
| 1113 static void | |
| 1114 pdf_opcount_sc_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color) | |
| 1115 { | |
| 1116 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1117 size_t z = p->buffer->len; | |
| 1118 | |
| 1119 if (p->mine->op_sc_pattern) | |
| 1120 p->mine->op_sc_pattern(ctx, p->mine, name, pat, n, color); | |
| 1121 | |
| 1122 z = p->buffer->len - z; | |
| 1123 p->op_usage->len[OP_sc_pattern] += z; | |
| 1124 } | |
| 1125 | |
| 1126 static void | |
| 1127 pdf_opcount_SC_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade) | |
| 1128 { | |
| 1129 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1130 size_t z = p->buffer->len; | |
| 1131 | |
| 1132 if (p->mine->op_SC_shade) | |
| 1133 p->mine->op_SC_shade(ctx, p->mine, name, shade); | |
| 1134 | |
| 1135 z = p->buffer->len - z; | |
| 1136 p->op_usage->len[OP_SC_shade] += z; | |
| 1137 } | |
| 1138 | |
| 1139 static void | |
| 1140 pdf_opcount_sc_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade) | |
| 1141 { | |
| 1142 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1143 size_t z = p->buffer->len; | |
| 1144 | |
| 1145 if (p->mine->op_sc_shade) | |
| 1146 p->mine->op_sc_shade(ctx, p->mine, name, shade); | |
| 1147 | |
| 1148 z = p->buffer->len - z; | |
| 1149 p->op_usage->len[OP_sc_shade] += z; | |
| 1150 } | |
| 1151 | |
| 1152 static void | |
| 1153 pdf_opcount_SC_color(fz_context *ctx, pdf_processor *proc, int n, float *color) | |
| 1154 { | |
| 1155 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1156 size_t z = p->buffer->len; | |
| 1157 | |
| 1158 if (p->mine->op_SC_color) | |
| 1159 p->mine->op_SC_color(ctx, p->mine, n, color); | |
| 1160 | |
| 1161 z = p->buffer->len - z; | |
| 1162 p->op_usage->len[OP_SC_color] += z; | |
| 1163 } | |
| 1164 | |
| 1165 static void | |
| 1166 pdf_opcount_sc_color(fz_context *ctx, pdf_processor *proc, int n, float *color) | |
| 1167 { | |
| 1168 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1169 size_t z = p->buffer->len; | |
| 1170 | |
| 1171 if (p->mine->op_sc_color) | |
| 1172 p->mine->op_sc_color(ctx, p->mine, n, color); | |
| 1173 | |
| 1174 z = p->buffer->len - z; | |
| 1175 p->op_usage->len[OP_sc_color] += z; | |
| 1176 } | |
| 1177 | |
| 1178 static void | |
| 1179 pdf_opcount_G(fz_context *ctx, pdf_processor *proc, float g) | |
| 1180 { | |
| 1181 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1182 size_t z = p->buffer->len; | |
| 1183 | |
| 1184 if (p->mine->op_G) | |
| 1185 p->mine->op_G(ctx, p->mine, g); | |
| 1186 | |
| 1187 z = p->buffer->len - z; | |
| 1188 p->op_usage->len[OP_G] += z; | |
| 1189 } | |
| 1190 | |
| 1191 static void | |
| 1192 pdf_opcount_g(fz_context *ctx, pdf_processor *proc, float g) | |
| 1193 { | |
| 1194 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1195 size_t z = p->buffer->len; | |
| 1196 | |
| 1197 if (p->mine->op_g) | |
| 1198 p->mine->op_g(ctx, p->mine, g); | |
| 1199 | |
| 1200 z = p->buffer->len - z; | |
| 1201 p->op_usage->len[OP_g] += z; | |
| 1202 } | |
| 1203 | |
| 1204 static void | |
| 1205 pdf_opcount_RG(fz_context *ctx, pdf_processor *proc, float r, float g, float b) | |
| 1206 { | |
| 1207 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1208 size_t z = p->buffer->len; | |
| 1209 | |
| 1210 if (p->mine->op_RG) | |
| 1211 p->mine->op_RG(ctx, p->mine, r, g, b); | |
| 1212 | |
| 1213 z = p->buffer->len - z; | |
| 1214 p->op_usage->len[OP_RG] += z; | |
| 1215 } | |
| 1216 | |
| 1217 static void | |
| 1218 pdf_opcount_rg(fz_context *ctx, pdf_processor *proc, float r, float g, float b) | |
| 1219 { | |
| 1220 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1221 size_t z = p->buffer->len; | |
| 1222 | |
| 1223 if (p->mine->op_rg) | |
| 1224 p->mine->op_rg(ctx, p->mine, r, g, b); | |
| 1225 | |
| 1226 z = p->buffer->len - z; | |
| 1227 p->op_usage->len[OP_rg] += z; | |
| 1228 } | |
| 1229 | |
| 1230 static void | |
| 1231 pdf_opcount_K(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k) | |
| 1232 { | |
| 1233 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1234 size_t z = p->buffer->len; | |
| 1235 | |
| 1236 if (p->mine->op_K) | |
| 1237 p->mine->op_K(ctx, p->mine, c, m, y, k); | |
| 1238 | |
| 1239 z = p->buffer->len - z; | |
| 1240 p->op_usage->len[OP_K] += z; | |
| 1241 } | |
| 1242 | |
| 1243 static void | |
| 1244 pdf_opcount_k(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k) | |
| 1245 { | |
| 1246 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1247 size_t z = p->buffer->len; | |
| 1248 | |
| 1249 if (p->mine->op_k) | |
| 1250 p->mine->op_k(ctx, p->mine, c, m, y, k); | |
| 1251 | |
| 1252 z = p->buffer->len - z; | |
| 1253 p->op_usage->len[OP_k] += z; | |
| 1254 } | |
| 1255 | |
| 1256 /* shadings, images, xobjects */ | |
| 1257 | |
| 1258 static void | |
| 1259 pdf_opcount_BI(fz_context *ctx, pdf_processor *proc, fz_image *image, const char *colorspace) | |
| 1260 { | |
| 1261 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1262 size_t z = p->buffer->len; | |
| 1263 | |
| 1264 if (p->mine->op_BI) | |
| 1265 p->mine->op_BI(ctx, p->mine, image, colorspace); | |
| 1266 | |
| 1267 z = p->buffer->len - z; | |
| 1268 p->op_usage->len[OP_BI] += z; | |
| 1269 } | |
| 1270 | |
| 1271 static void | |
| 1272 pdf_opcount_sh(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade) | |
| 1273 { | |
| 1274 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1275 size_t z = p->buffer->len; | |
| 1276 | |
| 1277 if (p->mine->op_sh) | |
| 1278 p->mine->op_sh(ctx, p->mine, name, shade); | |
| 1279 | |
| 1280 z = p->buffer->len - z; | |
| 1281 p->op_usage->len[OP_sh] += z; | |
| 1282 } | |
| 1283 | |
| 1284 static void | |
| 1285 pdf_opcount_Do_image(fz_context *ctx, pdf_processor *proc, const char *name, fz_image *image) | |
| 1286 { | |
| 1287 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1288 size_t z = p->buffer->len; | |
| 1289 | |
| 1290 if (p->mine->op_Do_image) | |
| 1291 p->mine->op_Do_image(ctx, p->mine, name, image); | |
| 1292 | |
| 1293 z = p->buffer->len - z; | |
| 1294 p->op_usage->len[OP_Do_image] += z; | |
| 1295 } | |
| 1296 | |
| 1297 static void | |
| 1298 pdf_opcount_Do_form(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *xobj) | |
| 1299 { | |
| 1300 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1301 size_t z = p->buffer->len; | |
| 1302 | |
| 1303 if (p->mine->op_Do_form) | |
| 1304 p->mine->op_Do_form(ctx, p->mine, name, xobj); | |
| 1305 | |
| 1306 z = p->buffer->len - z; | |
| 1307 p->op_usage->len[OP_Do_form] += z; | |
| 1308 } | |
| 1309 | |
| 1310 /* marked content */ | |
| 1311 | |
| 1312 static void | |
| 1313 pdf_opcount_MP(fz_context *ctx, pdf_processor *proc, const char *tag) | |
| 1314 { | |
| 1315 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1316 size_t z = p->buffer->len; | |
| 1317 | |
| 1318 if (p->mine->op_MP) | |
| 1319 p->mine->op_MP(ctx, p->mine, tag); | |
| 1320 | |
| 1321 z = p->buffer->len - z; | |
| 1322 p->op_usage->len[OP_MP] += z; | |
| 1323 } | |
| 1324 | |
| 1325 static void | |
| 1326 pdf_opcount_DP(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked) | |
| 1327 { | |
| 1328 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1329 size_t z = p->buffer->len; | |
| 1330 | |
| 1331 if (p->mine->op_DP) | |
| 1332 p->mine->op_DP(ctx, p->mine, tag, raw, cooked); | |
| 1333 | |
| 1334 z = p->buffer->len - z; | |
| 1335 p->op_usage->len[OP_DP] += z; | |
| 1336 } | |
| 1337 | |
| 1338 static void | |
| 1339 pdf_opcount_BMC(fz_context *ctx, pdf_processor *proc, const char *tag) | |
| 1340 { | |
| 1341 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1342 size_t z = p->buffer->len; | |
| 1343 | |
| 1344 if (p->mine->op_BMC) | |
| 1345 p->mine->op_BMC(ctx, p->mine, tag); | |
| 1346 | |
| 1347 z = p->buffer->len - z; | |
| 1348 p->op_usage->len[OP_BMC] += z; | |
| 1349 } | |
| 1350 | |
| 1351 static void | |
| 1352 pdf_opcount_BDC(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked) | |
| 1353 { | |
| 1354 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1355 size_t z = p->buffer->len; | |
| 1356 | |
| 1357 if (p->mine->op_BDC) | |
| 1358 p->mine->op_BDC(ctx, p->mine, tag, raw, cooked); | |
| 1359 | |
| 1360 z = p->buffer->len - z; | |
| 1361 p->op_usage->len[OP_BDC] += z; | |
| 1362 } | |
| 1363 | |
| 1364 static void | |
| 1365 pdf_opcount_EMC(fz_context *ctx, pdf_processor *proc) | |
| 1366 { | |
| 1367 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1368 size_t z = p->buffer->len; | |
| 1369 | |
| 1370 if (p->mine->op_EMC) | |
| 1371 p->mine->op_EMC(ctx, p->mine); | |
| 1372 | |
| 1373 z = p->buffer->len - z; | |
| 1374 p->op_usage->len[OP_EMC] += z; | |
| 1375 } | |
| 1376 | |
| 1377 /* compatibility */ | |
| 1378 | |
| 1379 static void | |
| 1380 pdf_opcount_BX(fz_context *ctx, pdf_processor *proc) | |
| 1381 { | |
| 1382 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1383 size_t z = p->buffer->len; | |
| 1384 | |
| 1385 if (p->mine->op_BX) | |
| 1386 p->mine->op_BX(ctx, p->mine); | |
| 1387 | |
| 1388 z = p->buffer->len - z; | |
| 1389 p->op_usage->len[OP_BX] += z; | |
| 1390 } | |
| 1391 | |
| 1392 static void | |
| 1393 pdf_opcount_EX(fz_context *ctx, pdf_processor *proc) | |
| 1394 { | |
| 1395 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1396 size_t z = p->buffer->len; | |
| 1397 | |
| 1398 if (p->mine->op_EX) | |
| 1399 p->mine->op_EX(ctx, p->mine); | |
| 1400 | |
| 1401 z = p->buffer->len - z; | |
| 1402 p->op_usage->len[OP_EX] += z; | |
| 1403 } | |
| 1404 | |
| 1405 static void | |
| 1406 pdf_opcount_END(fz_context *ctx, pdf_processor *proc) | |
| 1407 { | |
| 1408 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1409 | |
| 1410 if (p->mine->op_END) | |
| 1411 p->mine->op_END(ctx, p->mine); | |
| 1412 } | |
| 1413 | |
| 1414 static void | |
| 1415 pdf_close_opcount_processor(fz_context *ctx, pdf_processor *proc) | |
| 1416 { | |
| 1417 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1418 | |
| 1419 pdf_close_processor(ctx, p->mine); | |
| 1420 pdf_close_processor(ctx, p->chain); | |
| 1421 } | |
| 1422 | |
| 1423 static void | |
| 1424 pdf_drop_opcount_processor(fz_context *ctx, pdf_processor *proc) | |
| 1425 { | |
| 1426 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1427 | |
| 1428 fz_drop_buffer(ctx, p->buffer); | |
| 1429 pdf_drop_processor(ctx, p->mine); | |
| 1430 } | |
| 1431 | |
| 1432 static void | |
| 1433 pdf_opcount_push_resources(fz_context *ctx, pdf_processor *proc, pdf_obj *res) | |
| 1434 { | |
| 1435 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1436 | |
| 1437 pdf_processor_push_resources(ctx, p->mine, res); | |
| 1438 } | |
| 1439 | |
| 1440 static pdf_obj * | |
| 1441 pdf_opcount_pop_resources(fz_context *ctx, pdf_processor *proc) | |
| 1442 { | |
| 1443 pdf_opcount_processor *p = (pdf_opcount_processor*)proc; | |
| 1444 | |
| 1445 return pdf_processor_pop_resources(ctx, p->mine); | |
| 1446 } | |
| 1447 | |
| 1448 pdf_processor * | |
| 1449 pdf_new_opcount_filter( | |
| 1450 fz_context *ctx, | |
| 1451 pdf_document *doc, | |
| 1452 pdf_processor *chain, | |
| 1453 int struct_parents, | |
| 1454 fz_matrix transform, | |
| 1455 pdf_filter_options *global_options, | |
| 1456 void *options_) | |
| 1457 { | |
| 1458 pdf_opcount_processor *proc = pdf_new_processor(ctx, sizeof * proc); | |
| 1459 | |
| 1460 fz_try(ctx) | |
| 1461 { | |
| 1462 proc->buffer = fz_new_buffer(ctx, 1024); | |
| 1463 proc->mine = pdf_new_buffer_processor(ctx, proc->buffer, 0, 0); | |
| 1464 } | |
| 1465 fz_catch(ctx) | |
| 1466 fz_rethrow(ctx); | |
| 1467 | |
| 1468 proc->op_usage = (op_usage_t *)options_; | |
| 1469 | |
| 1470 proc->super.close_processor = pdf_close_opcount_processor; | |
| 1471 proc->super.drop_processor = pdf_drop_opcount_processor; | |
| 1472 | |
| 1473 proc->super.push_resources = pdf_opcount_push_resources; | |
| 1474 proc->super.pop_resources = pdf_opcount_pop_resources; | |
| 1475 | |
| 1476 /* general graphics state */ | |
| 1477 proc->super.op_w = pdf_opcount_w; | |
| 1478 proc->super.op_j = pdf_opcount_j; | |
| 1479 proc->super.op_J = pdf_opcount_J; | |
| 1480 proc->super.op_M = pdf_opcount_M; | |
| 1481 proc->super.op_d = pdf_opcount_d; | |
| 1482 proc->super.op_ri = pdf_opcount_ri; | |
| 1483 proc->super.op_i = pdf_opcount_i; | |
| 1484 proc->super.op_gs_begin = pdf_opcount_gs_begin; | |
| 1485 proc->super.op_gs_end = pdf_opcount_gs_end; | |
| 1486 | |
| 1487 /* transparency graphics state */ | |
| 1488 proc->super.op_gs_BM = pdf_opcount_gs_BM; | |
| 1489 proc->super.op_gs_CA = pdf_opcount_gs_CA; | |
| 1490 proc->super.op_gs_ca = pdf_opcount_gs_ca; | |
| 1491 proc->super.op_gs_SMask = pdf_opcount_gs_SMask; | |
| 1492 | |
| 1493 /* special graphics state */ | |
| 1494 proc->super.op_q = pdf_opcount_q; | |
| 1495 proc->super.op_Q = pdf_opcount_Q; | |
| 1496 proc->super.op_cm = pdf_opcount_cm; | |
| 1497 | |
| 1498 /* path construction */ | |
| 1499 proc->super.op_m = pdf_opcount_m; | |
| 1500 proc->super.op_l = pdf_opcount_l; | |
| 1501 proc->super.op_c = pdf_opcount_c; | |
| 1502 proc->super.op_v = pdf_opcount_v; | |
| 1503 proc->super.op_y = pdf_opcount_y; | |
| 1504 proc->super.op_h = pdf_opcount_h; | |
| 1505 proc->super.op_re = pdf_opcount_re; | |
| 1506 | |
| 1507 /* path painting */ | |
| 1508 proc->super.op_S = pdf_opcount_S; | |
| 1509 proc->super.op_s = pdf_opcount_s; | |
| 1510 proc->super.op_F = pdf_opcount_F; | |
| 1511 proc->super.op_f = pdf_opcount_f; | |
| 1512 proc->super.op_fstar = pdf_opcount_fstar; | |
| 1513 proc->super.op_B = pdf_opcount_B; | |
| 1514 proc->super.op_Bstar = pdf_opcount_Bstar; | |
| 1515 proc->super.op_b = pdf_opcount_b; | |
| 1516 proc->super.op_bstar = pdf_opcount_bstar; | |
| 1517 proc->super.op_n = pdf_opcount_n; | |
| 1518 | |
| 1519 /* clipping paths */ | |
| 1520 proc->super.op_W = pdf_opcount_W; | |
| 1521 proc->super.op_Wstar = pdf_opcount_Wstar; | |
| 1522 | |
| 1523 /* text objects */ | |
| 1524 proc->super.op_BT = pdf_opcount_BT; | |
| 1525 proc->super.op_ET = pdf_opcount_ET; | |
| 1526 | |
| 1527 /* text state */ | |
| 1528 proc->super.op_Tc = pdf_opcount_Tc; | |
| 1529 proc->super.op_Tw = pdf_opcount_Tw; | |
| 1530 proc->super.op_Tz = pdf_opcount_Tz; | |
| 1531 proc->super.op_TL = pdf_opcount_TL; | |
| 1532 proc->super.op_Tf = pdf_opcount_Tf; | |
| 1533 proc->super.op_Tr = pdf_opcount_Tr; | |
| 1534 proc->super.op_Ts = pdf_opcount_Ts; | |
| 1535 | |
| 1536 /* text positioning */ | |
| 1537 proc->super.op_Td = pdf_opcount_Td; | |
| 1538 proc->super.op_TD = pdf_opcount_TD; | |
| 1539 proc->super.op_Tm = pdf_opcount_Tm; | |
| 1540 proc->super.op_Tstar = pdf_opcount_Tstar; | |
| 1541 | |
| 1542 /* text showing */ | |
| 1543 proc->super.op_TJ = pdf_opcount_TJ; | |
| 1544 proc->super.op_Tj = pdf_opcount_Tj; | |
| 1545 proc->super.op_squote = pdf_opcount_squote; | |
| 1546 proc->super.op_dquote = pdf_opcount_dquote; | |
| 1547 | |
| 1548 /* type 3 fonts */ | |
| 1549 proc->super.op_d0 = pdf_opcount_d0; | |
| 1550 proc->super.op_d1 = pdf_opcount_d1; | |
| 1551 | |
| 1552 /* color */ | |
| 1553 proc->super.op_CS = pdf_opcount_CS; | |
| 1554 proc->super.op_cs = pdf_opcount_cs; | |
| 1555 proc->super.op_SC_color = pdf_opcount_SC_color; | |
| 1556 proc->super.op_sc_color = pdf_opcount_sc_color; | |
| 1557 proc->super.op_SC_pattern = pdf_opcount_SC_pattern; | |
| 1558 proc->super.op_sc_pattern = pdf_opcount_sc_pattern; | |
| 1559 proc->super.op_SC_shade = pdf_opcount_SC_shade; | |
| 1560 proc->super.op_sc_shade = pdf_opcount_sc_shade; | |
| 1561 | |
| 1562 proc->super.op_G = pdf_opcount_G; | |
| 1563 proc->super.op_g = pdf_opcount_g; | |
| 1564 proc->super.op_RG = pdf_opcount_RG; | |
| 1565 proc->super.op_rg = pdf_opcount_rg; | |
| 1566 proc->super.op_K = pdf_opcount_K; | |
| 1567 proc->super.op_k = pdf_opcount_k; | |
| 1568 | |
| 1569 /* shadings, images, xobjects */ | |
| 1570 proc->super.op_BI = pdf_opcount_BI; | |
| 1571 proc->super.op_sh = pdf_opcount_sh; | |
| 1572 proc->super.op_Do_image = pdf_opcount_Do_image; | |
| 1573 proc->super.op_Do_form = pdf_opcount_Do_form; | |
| 1574 | |
| 1575 /* marked content */ | |
| 1576 proc->super.op_MP = pdf_opcount_MP; | |
| 1577 proc->super.op_DP = pdf_opcount_DP; | |
| 1578 proc->super.op_BMC = pdf_opcount_BMC; | |
| 1579 proc->super.op_BDC = pdf_opcount_BDC; | |
| 1580 proc->super.op_EMC = pdf_opcount_EMC; | |
| 1581 | |
| 1582 /* compatibility */ | |
| 1583 proc->super.op_BX = pdf_opcount_BX; | |
| 1584 proc->super.op_EX = pdf_opcount_EX; | |
| 1585 | |
| 1586 /* extgstate */ | |
| 1587 proc->super.op_gs_OP = pdf_opcount_gs_OP; | |
| 1588 proc->super.op_gs_op = pdf_opcount_gs_op; | |
| 1589 proc->super.op_gs_OPM = pdf_opcount_gs_OPM; | |
| 1590 proc->super.op_gs_UseBlackPtComp = pdf_opcount_gs_UseBlackPtComp; | |
| 1591 | |
| 1592 proc->super.op_END = pdf_opcount_END; | |
| 1593 | |
| 1594 proc->global_options = global_options; | |
| 1595 proc->chain = chain; | |
| 1596 | |
| 1597 return (pdf_processor*)proc; | |
| 1598 } | |
| 1599 | |
| 1600 static void | |
| 1601 filter_page(fz_context *ctx, pdf_document *doc, op_usage_t *op_usage, int page_num) | |
| 1602 { | |
| 1603 pdf_page *page = pdf_load_page(ctx, doc, page_num); | |
| 1604 pdf_filter_options options = { 0 }; | |
| 1605 pdf_filter_factory list[2] = { 0 }; | |
| 1606 pdf_annot *annot; | |
| 1607 | |
| 1608 options.filters = list; | |
| 1609 options.recurse = 1; | |
| 1610 options.no_update = 1; | |
| 1611 list[0].filter = pdf_new_opcount_filter; | |
| 1612 list[0].options = op_usage; | |
| 1613 | |
| 1614 fz_try(ctx) | |
| 1615 { | |
| 1616 pdf_filter_page_contents(ctx, doc, page, &options); | |
| 1617 | |
| 1618 for (annot = pdf_first_annot(ctx, page); annot != NULL; annot = pdf_next_annot(ctx, annot)) | |
| 1619 pdf_filter_annot_contents(ctx, doc, annot, &options); | |
| 1620 } | |
| 1621 fz_always(ctx) | |
| 1622 fz_drop_page(ctx, &page->super); | |
| 1623 fz_catch(ctx) | |
| 1624 fz_rethrow(ctx); | |
| 1625 } | |
| 1626 | |
| 1627 static void | |
| 1628 filter_page_streams(fz_context *ctx, pdf_document *pdf, op_usage_t *ou) | |
| 1629 { | |
| 1630 int i, n = pdf_count_pages(ctx, pdf); | |
| 1631 | |
| 1632 for (i= 0; i < n; i++) | |
| 1633 { | |
| 1634 filter_page(ctx, pdf, ou, i); | |
| 1635 } | |
| 1636 } | |
| 1637 | |
| 1638 static void | |
| 1639 filter_buffer(fz_context *ctx, obj_info_t *oi, fz_buffer *buf) | |
| 1640 { | |
| 1641 oi->len = buf->len; | |
| 1642 } | |
| 1643 | |
| 1644 static void | |
| 1645 filter_stream(fz_context *ctx, pdf_document *pdf, int i, obj_info_t *oi) | |
| 1646 { | |
| 1647 fz_buffer *buf = pdf_load_stream_number(ctx, pdf, i); | |
| 1648 | |
| 1649 fz_try(ctx) | |
| 1650 filter_buffer(ctx, oi, buf); | |
| 1651 fz_always(ctx) | |
| 1652 fz_drop_buffer(ctx, buf); | |
| 1653 fz_catch(ctx) | |
| 1654 fz_rethrow(ctx); | |
| 1655 } | |
| 1656 | |
| 1657 static void | |
| 1658 filter_obj(fz_context *ctx, obj_info_t *oi, pdf_obj *obj) | |
| 1659 { | |
| 1660 fz_buffer *buf = fz_new_buffer(ctx, 1024); | |
| 1661 fz_output *out = NULL; | |
| 1662 | |
| 1663 fz_var(out); | |
| 1664 | |
| 1665 fz_try(ctx) | |
| 1666 { | |
| 1667 out = fz_new_output_with_buffer(ctx, buf); | |
| 1668 pdf_print_obj(ctx, out, obj, 1, 0); | |
| 1669 fz_close_output(ctx, out); | |
| 1670 } | |
| 1671 fz_always(ctx) | |
| 1672 { | |
| 1673 fz_drop_output(ctx, out); | |
| 1674 if (buf) | |
| 1675 oi->textsize = buf->len; | |
| 1676 fz_drop_buffer(ctx, buf); | |
| 1677 } | |
| 1678 fz_catch(ctx) | |
| 1679 fz_rethrow(ctx); | |
| 1680 } | |
| 1681 | |
| 1682 typedef struct | |
| 1683 { | |
| 1684 int len; | |
| 1685 int max; | |
| 1686 struct { | |
| 1687 pdf_obj *obj; | |
| 1688 int pos; | |
| 1689 int state; | |
| 1690 } *stack; | |
| 1691 } walk_stack_t; | |
| 1692 | |
| 1693 static void | |
| 1694 walk(fz_context *ctx, walk_stack_t *ws, int n, obj_info_t *oi, pdf_obj *obj, audit_type_t type) | |
| 1695 { | |
| 1696 int num = 0; | |
| 1697 do | |
| 1698 { | |
| 1699 if (pdf_is_indirect(ctx, obj)) | |
| 1700 { | |
| 1701 num = pdf_to_num(ctx, obj); | |
| 1702 if (num < 0 || num >= n) | |
| 1703 fz_throw(ctx, FZ_ERROR_GENERIC, "object outside of xref range"); | |
| 1704 if (oi[num].type != AUDIT_UNKNOWN) | |
| 1705 goto visited; | |
| 1706 if (pdf_mark_obj(ctx, obj)) | |
| 1707 { | |
| 1708 /* We've already visited this one! */ | |
| 1709 goto visited; | |
| 1710 } | |
| 1711 } | |
| 1712 /* Push the object onto the stack. */ | |
| 1713 if (ws->len == ws->max) | |
| 1714 { | |
| 1715 int newmax = ws->max * 2; | |
| 1716 if (newmax == 0) | |
| 1717 newmax = 32; | |
| 1718 ws->stack = fz_realloc(ctx, ws->stack, sizeof(ws->stack[0]) * newmax); | |
| 1719 ws->max = newmax; | |
| 1720 } | |
| 1721 | |
| 1722 /* If the object we are about to stack is a dict, then check to see if | |
| 1723 * we should be changing type because of it. */ | |
| 1724 if (pdf_is_dict(ctx, obj)) | |
| 1725 { | |
| 1726 pdf_obj *otype = pdf_dict_get(ctx, obj, PDF_NAME(Type)); | |
| 1727 pdf_obj *subtype = pdf_dict_get(ctx, obj, PDF_NAME(Subtype)); | |
| 1728 | |
| 1729 if (pdf_name_eq(ctx, otype, PDF_NAME(Annot))) | |
| 1730 { | |
| 1731 if (pdf_name_eq(ctx, subtype, PDF_NAME(Link))) | |
| 1732 type = AUDIT_LINK_ANNOTATIONS; | |
| 1733 else if (pdf_name_eq(ctx, subtype, PDF_NAME(Text))) | |
| 1734 type = AUDIT_COMMENTS; | |
| 1735 else if (pdf_name_eq(ctx, subtype, PDF_NAME(FreeText))) | |
| 1736 type = AUDIT_COMMENTS; | |
| 1737 else if (pdf_name_eq(ctx, subtype, PDF_NAME(Popup))) | |
| 1738 type = AUDIT_COMMENTS; | |
| 1739 else if (pdf_name_eq(ctx, subtype, PDF_NAME(3D))) | |
| 1740 type = AUDIT_3DCONTENT; | |
| 1741 else if (pdf_name_eq(ctx, subtype, PDF_NAME(PieceInfo))) | |
| 1742 type = AUDIT_PIECE_INFORMATION; | |
| 1743 } | |
| 1744 else if (pdf_name_eq(ctx, otype, PDF_NAME(Font))) | |
| 1745 type = AUDIT_FONTS; | |
| 1746 else if (pdf_name_eq(ctx, otype, PDF_NAME(FontDescriptor))) | |
| 1747 type = AUDIT_FONTS; | |
| 1748 else if (pdf_name_eq(ctx, otype, PDF_NAME(XObject))) | |
| 1749 { | |
| 1750 if (pdf_name_eq(ctx, subtype, PDF_NAME(Image))) | |
| 1751 type = AUDIT_IMAGES; | |
| 1752 else if (pdf_name_eq(ctx, subtype, PDF_NAME(Form))) | |
| 1753 type = AUDIT_FORM_XOBJ; | |
| 1754 } | |
| 1755 else if (pdf_name_eq(ctx, otype, PDF_NAME(Page))) | |
| 1756 type = AUDIT_PAGE_OBJECTS; | |
| 1757 else if (pdf_name_eq(ctx, otype, PDF_NAME(Pages))) | |
| 1758 type = AUDIT_PAGE_OBJECTS; | |
| 1759 else if (pdf_name_eq(ctx, otype, PDF_NAME(Metadata))) | |
| 1760 type = AUDIT_METADATA; | |
| 1761 } | |
| 1762 ws->stack[ws->len].obj = obj; | |
| 1763 ws->stack[ws->len].pos = 0; | |
| 1764 ws->stack[ws->len].state = type; | |
| 1765 ws->len++; | |
| 1766 | |
| 1767 /* So we have stepped successfully onto obj. */ | |
| 1768 /* Record its type. */ | |
| 1769 if (type != AUDIT_UNKNOWN) | |
| 1770 { | |
| 1771 num = pdf_obj_parent_num(ctx, obj); | |
| 1772 oi[num].type = type; | |
| 1773 } | |
| 1774 | |
| 1775 /* Step onwards to any children. */ | |
| 1776 if (pdf_is_dict(ctx, obj)) | |
| 1777 { | |
| 1778 pdf_obj *key; | |
| 1779 /* We've just stepped onto a dict. */ | |
| 1780 step_next_dict_child: | |
| 1781 if (ws->stack[ws->len-1].pos == pdf_dict_len(ctx, obj)) | |
| 1782 goto pop; | |
| 1783 key = pdf_dict_get_key(ctx, ws->stack[ws->len-1].obj, ws->stack[ws->len-1].pos); | |
| 1784 ws->stack[ws->len-1].pos++; | |
| 1785 | |
| 1786 if (pdf_name_eq(ctx, key, PDF_NAME(Parent))) | |
| 1787 goto step_next_dict_child; | |
| 1788 | |
| 1789 if (pdf_name_eq(ctx, key, PDF_NAME(Thumb))) | |
| 1790 type = AUDIT_THUMBNAILS; | |
| 1791 else if (pdf_name_eq(ctx, key, PDF_NAME(Outlines))) | |
| 1792 type = AUDIT_BOOKMARKS; | |
| 1793 else if (pdf_name_eq(ctx, key, PDF_NAME(Contents))) | |
| 1794 type = AUDIT_CONTENT_STREAMS; | |
| 1795 else if (pdf_name_eq(ctx, key, PDF_NAME(StructTreeRoot))) | |
| 1796 type = AUDIT_STRUCTURE_INFO; | |
| 1797 else if (pdf_name_eq(ctx, key, PDF_NAME(AcroForm))) | |
| 1798 type = AUDIT_FORMS; | |
| 1799 else if (pdf_name_eq(ctx, key, PDF_NAME(ColorSpace))) | |
| 1800 type = AUDIT_COLORSPACES; | |
| 1801 else if (pdf_name_eq(ctx, key, PDF_NAME(CS))) | |
| 1802 type = AUDIT_COLORSPACES; | |
| 1803 else if (pdf_name_eq(ctx, key, PDF_NAME(Dests))) | |
| 1804 type = AUDIT_NAMED_DESTINATIONS; | |
| 1805 else if (pdf_name_eq(ctx, key, PDF_NAME(ExtGState))) | |
| 1806 type = AUDIT_EXTGS; | |
| 1807 else if (pdf_name_eq(ctx, key, PDF_NAME(Resources))) | |
| 1808 type = AUDIT_RESOURCES; | |
| 1809 else if (pdf_name_eq(ctx, key, PDF_NAME(EmbeddedFile))) | |
| 1810 type = AUDIT_EMBEDDED_FILES; | |
| 1811 else if (pdf_name_eq(ctx, key, PDF_NAME(Metadata))) | |
| 1812 type = AUDIT_METADATA; | |
| 1813 | |
| 1814 /* OK. step onto the val. */ | |
| 1815 obj = pdf_dict_get_val(ctx, ws->stack[ws->len-1].obj, ws->stack[ws->len-1].pos-1); | |
| 1816 continue; | |
| 1817 } | |
| 1818 else if (pdf_is_array(ctx, obj)) | |
| 1819 { | |
| 1820 step_next_array_child: | |
| 1821 if (ws->stack[ws->len-1].pos == pdf_array_len(ctx, obj)) | |
| 1822 goto pop; | |
| 1823 | |
| 1824 obj = pdf_array_get(ctx, ws->stack[ws->len-1].obj, ws->stack[ws->len-1].pos); | |
| 1825 ws->stack[ws->len-1].pos++; | |
| 1826 continue; | |
| 1827 } | |
| 1828 | |
| 1829 /* Nothing more to do with this object. Pop back up. */ | |
| 1830 pop: | |
| 1831 if (pdf_is_indirect(ctx, obj)) | |
| 1832 { | |
| 1833 pdf_unmark_obj(ctx, obj); | |
| 1834 } | |
| 1835 ws->len--; | |
| 1836 visited: | |
| 1837 if (ws->len > 0) | |
| 1838 { | |
| 1839 /* We should either have stepped up to a dict or an array. */ | |
| 1840 obj = ws->stack[ws->len-1].obj; | |
| 1841 type = ws->stack[ws->len-1].state; | |
| 1842 num = pdf_obj_parent_num(ctx, obj); | |
| 1843 if (pdf_is_dict(ctx, obj)) | |
| 1844 goto step_next_dict_child; | |
| 1845 else if (pdf_is_array(ctx, obj)) | |
| 1846 goto step_next_array_child; | |
| 1847 else | |
| 1848 assert("Never happens" == NULL); | |
| 1849 } | |
| 1850 } | |
| 1851 while (ws->len > 0); | |
| 1852 } | |
| 1853 | |
| 1854 static void | |
| 1855 classify_by_walking(fz_context *ctx, pdf_document *doc, int n, obj_info_t *oi) | |
| 1856 { | |
| 1857 walk_stack_t ws = { 0 }; | |
| 1858 | |
| 1859 fz_try(ctx) | |
| 1860 walk(ctx, &ws, n, oi, pdf_trailer(ctx, doc), AUDIT_TRAILER); | |
| 1861 fz_always(ctx) | |
| 1862 fz_free(ctx, ws.stack); | |
| 1863 fz_catch(ctx) | |
| 1864 fz_rethrow(ctx); | |
| 1865 } | |
| 1866 | |
| 1867 static void | |
| 1868 output_size(fz_context *ctx, fz_output *out, uint64_t file_size, const char *str, uint64_t size, uint64_t size2) | |
| 1869 { | |
| 1870 fz_write_printf(ctx, out, "<tr align=right><td align=left>%s<td>%,ld<td>%.2f%%<td>%,ld<td>%.2f%%</tr>\n", str, size, 100.0f * size/file_size, size2, 100.0f * size2/file_size); | |
| 1871 } | |
| 1872 | |
| 1873 static void | |
| 1874 filter_file(fz_context *ctx, fz_output *out, const char *filename) | |
| 1875 { | |
| 1876 pdf_document *pdf = NULL; | |
| 1877 int i, n; | |
| 1878 pdf_obj *obj = NULL; | |
| 1879 obj_info_t *oi = NULL; | |
| 1880 op_usage_t ou = { 0 }; | |
| 1881 | |
| 1882 fz_var(pdf); | |
| 1883 fz_var(obj); | |
| 1884 fz_var(i); | |
| 1885 fz_var(oi); | |
| 1886 | |
| 1887 fz_try(ctx) | |
| 1888 { | |
| 1889 pdf = pdf_open_document(ctx, filename); | |
| 1890 | |
| 1891 n = pdf_xref_len(ctx, pdf); | |
| 1892 oi = fz_malloc_array(ctx, n, obj_info_t); | |
| 1893 memset(oi, 0, n * sizeof(obj_info_t)); | |
| 1894 for (i = 1; i < n; i++) | |
| 1895 { | |
| 1896 fz_try(ctx) | |
| 1897 { | |
| 1898 for (; i <n; i++) | |
| 1899 { | |
| 1900 pdf_xref_entry *entry = pdf_cache_object(ctx, pdf, i); | |
| 1901 int is_in_objstm = entry->type == 'o'; | |
| 1902 pdf_obj *type, *subtype; | |
| 1903 char text[128]; | |
| 1904 | |
| 1905 if (entry->obj == NULL) | |
| 1906 continue; | |
| 1907 oi[i].is_in_objstm = is_in_objstm; | |
| 1908 if (!is_in_objstm) | |
| 1909 { | |
| 1910 sprintf(text, "%d 0 obj\nendobj\n", i); | |
| 1911 oi[i].overhead = strlen(text); | |
| 1912 } | |
| 1913 else | |
| 1914 { | |
| 1915 sprintf(text, "%d %zd ", i, (size_t)entry->ofs); | |
| 1916 oi[i].overhead = strlen(text); | |
| 1917 } | |
| 1918 type = pdf_dict_get(ctx, entry->obj, PDF_NAME(Type)); | |
| 1919 SWITCH (type) | |
| 1920 { | |
| 1921 CASE(PDF_NAME(ObjStm)): | |
| 1922 oi[i].type = AUDIT_OBJSTM; | |
| 1923 break; | |
| 1924 | |
| 1925 } | |
| 1926 subtype = pdf_dict_get(ctx, entry->obj, PDF_NAME(Subtype)); | |
| 1927 SWITCH (subtype) | |
| 1928 { | |
| 1929 CASE(PDF_NAME(Image)): | |
| 1930 oi[i].type = AUDIT_IMAGES; | |
| 1931 break; | |
| 1932 } | |
| 1933 | |
| 1934 filter_obj(ctx, &oi[i], entry->obj); | |
| 1935 if (pdf_obj_num_is_stream(ctx, pdf, i)) | |
| 1936 { | |
| 1937 filter_stream(ctx, pdf, i, &oi[i]); | |
| 1938 oi[i].stream_len = pdf_dict_get_int64(ctx, entry->obj, PDF_NAME(Length)); | |
| 1939 } | |
| 1940 pdf_drop_obj(ctx, obj); | |
| 1941 obj = NULL; | |
| 1942 } | |
| 1943 } | |
| 1944 fz_catch(ctx) | |
| 1945 { | |
| 1946 i++; | |
| 1947 /* Swallow error */ | |
| 1948 } | |
| 1949 } | |
| 1950 | |
| 1951 /* Walk the doc structure. */ | |
| 1952 classify_by_walking(ctx, pdf, n, oi); | |
| 1953 | |
| 1954 /* Filter the content streams to establish operator usage */ | |
| 1955 filter_page_streams(ctx, pdf, &ou); | |
| 1956 | |
| 1957 fz_write_printf(ctx, out, "<html><title>PDF Audit: %s</title><body>\n", filename); | |
| 1958 fz_write_printf(ctx, out, "<H1>Input file: %s</H1>\n", filename); | |
| 1959 fz_write_printf(ctx, out, "<p>Total file size: %,zd bytes</p>", pdf->file_size); | |
| 1960 | |
| 1961 fz_write_printf(ctx, out, "<H3>Total file usage</H3>\n"); | |
| 1962 /* Sum the results */ | |
| 1963 { | |
| 1964 struct { | |
| 1965 size_t obj; | |
| 1966 size_t objstm; | |
| 1967 } counts[AUDIT__MAX] = { 0 }; | |
| 1968 size_t total_obj = 0; | |
| 1969 size_t total_objstm = 0; | |
| 1970 size_t overhead = 0; | |
| 1971 size_t objstm_overhead = 0; | |
| 1972 size_t total_stream_uncomp = 0; | |
| 1973 size_t total_stream_comp = 0; | |
| 1974 for (i = 1; i < n; i++) | |
| 1975 { | |
| 1976 size_t z = oi[i].textsize + oi[i].overhead + oi[i].stream_len; | |
| 1977 total_stream_uncomp += oi[i].len; | |
| 1978 total_stream_comp += oi[i].stream_len; | |
| 1979 if (oi[i].is_in_objstm) | |
| 1980 { | |
| 1981 objstm_overhead += oi[i].overhead; | |
| 1982 total_objstm += oi[i].textsize; | |
| 1983 counts[oi[i].type].objstm += z; | |
| 1984 } | |
| 1985 else | |
| 1986 { | |
| 1987 overhead += oi[i].overhead; | |
| 1988 total_obj += oi[i].textsize; | |
| 1989 counts[oi[i].type].obj += z; | |
| 1990 } | |
| 1991 } | |
| 1992 fz_write_printf(ctx, out, "<table border=1><thead><th><th colspan=2>not in objstms<th colspan=2>in objstms</thead>\n"); | |
| 1993 output_size(ctx, out, pdf->file_size, "object text", total_obj, total_objstm); | |
| 1994 output_size(ctx, out, pdf->file_size, "object overhead", overhead, objstm_overhead); | |
| 1995 fz_write_printf(ctx, out, "<thead><th><th colspan=2>uncompressed<th colspan=2>compressed</thead>\n"); | |
| 1996 output_size(ctx, out, pdf->file_size, "streams", total_stream_uncomp, total_stream_comp); | |
| 1997 fz_write_printf(ctx, out, "</table>\n"); | |
| 1998 fz_write_printf(ctx, out, "<p>NOTE: The uncompressed streams percentage figure is misleading," | |
| 1999 " as it is the percentage of the complete file which typically includes compression.</p>\n"); | |
| 2000 fz_write_printf(ctx, out, "<table border=1><thead><th><th colspan=2>not in objstms<th colspan=2>in objstms</thead>\n"); | |
| 2001 fz_write_printf(ctx, out, "<H3>Classified file usage</H3>\n"); | |
| 2002 for (i = 0; i < AUDIT__MAX; i++) | |
| 2003 { | |
| 2004 output_size(ctx, out, pdf->file_size, audit_type[i], counts[i].obj, counts[i].objstm); | |
| 2005 } | |
| 2006 fz_write_printf(ctx, out, "</table>\n"); | |
| 2007 fz_write_printf(ctx, out, "<p>NOTE: The percentages are as percentages of the complete file. This again means that" | |
| 2008 " the percentages in the "in objstms" column are misleading as the objstms are" | |
| 2009 " typically compressed!</p>\n"); | |
| 2010 } | |
| 2011 | |
| 2012 /* List some unknown objects. */ | |
| 2013 { | |
| 2014 int count = 0; | |
| 2015 | |
| 2016 for (i = 1; i < n; i++) | |
| 2017 { | |
| 2018 if (oi[i].type != AUDIT_UNKNOWN || oi[i].textsize == 0) | |
| 2019 continue; | |
| 2020 | |
| 2021 if (count == 0) | |
| 2022 fz_write_printf(ctx, out, "<p>Some objects still unknown: e.g. "); | |
| 2023 fz_write_printf(ctx, out, "%d ", i); | |
| 2024 count++; | |
| 2025 if (count == 10) | |
| 2026 break; | |
| 2027 } | |
| 2028 if (count > 0) | |
| 2029 fz_write_printf(ctx, out, "</p>\n"); | |
| 2030 } | |
| 2031 | |
| 2032 /* Write out the operator usage */ | |
| 2033 fz_write_printf(ctx, out, "<H3>Operator usage within streams</H3>\n"); | |
| 2034 { | |
| 2035 size_t total = 0; | |
| 2036 for (i = 0; i < OP_END; i++) | |
| 2037 total += ou.len[i]; | |
| 2038 fz_write_printf(ctx, out, "<table border=1><thead><th>Op<th>bytes<th></thead>\n"); | |
| 2039 for (i = 0; i < OP_END; i++) | |
| 2040 { | |
| 2041 fz_write_printf(ctx, out, "<tr align=right><td align=left>%s<td>%,zd<td>%.2f%%</tr>\n", op_names[i], ou.len[i], 100.f * ou.len[i] / total); | |
| 2042 } | |
| 2043 fz_write_printf(ctx, out, "</table>\n"); | |
| 2044 fz_write_printf(ctx, out, "<p>NOTE: The percentages are of the operator stream content found.</p>\n"); | |
| 2045 } | |
| 2046 | |
| 2047 } | |
| 2048 fz_always(ctx) | |
| 2049 { | |
| 2050 pdf_drop_obj(ctx, obj); | |
| 2051 pdf_drop_document(ctx, pdf); | |
| 2052 fz_free(ctx, oi); | |
| 2053 } | |
| 2054 fz_catch(ctx) | |
| 2055 fz_rethrow(ctx); | |
| 2056 } | |
| 2057 | |
| 2058 static int usage(void) | |
| 2059 { | |
| 2060 fprintf(stderr, | |
| 2061 "usage: mutool audit [options] input.pdf+\n" | |
| 2062 "\t-o -\toutput file\n" | |
| 2063 ); | |
| 2064 return 1; | |
| 2065 } | |
| 2066 | |
| 2067 int pdfaudit_main(int argc, char **argv) | |
| 2068 { | |
| 2069 char *outfile = "-"; | |
| 2070 int c; | |
| 2071 int errors = 0; | |
| 2072 int append = 0; | |
| 2073 fz_context *ctx; | |
| 2074 fz_output *out = NULL; | |
| 2075 const fz_getopt_long_options longopts[] = | |
| 2076 { | |
| 2077 { NULL, NULL, NULL } | |
| 2078 }; | |
| 2079 | |
| 2080 while ((c = fz_getopt_long(argc, argv, "o:", longopts)) != -1) | |
| 2081 { | |
| 2082 switch (c) | |
| 2083 { | |
| 2084 case 'o': outfile = fz_optpath(fz_optarg); break; | |
| 2085 case 0: | |
| 2086 { | |
| 2087 SWITCH(fz_optlong->opaque) | |
| 2088 { | |
| 2089 // Any future long options go here. | |
| 2090 default: | |
| 2091 case 0: | |
| 2092 assert(!"Never happens"); | |
| 2093 break; | |
| 2094 break; | |
| 2095 } | |
| 2096 } | |
| 2097 default: return usage(); | |
| 2098 } | |
| 2099 } | |
| 2100 | |
| 2101 if (argc - fz_optind < 1) | |
| 2102 return usage(); | |
| 2103 | |
| 2104 ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); | |
| 2105 if (!ctx) | |
| 2106 { | |
| 2107 fprintf(stderr, "cannot initialise context\n"); | |
| 2108 exit(1); | |
| 2109 } | |
| 2110 | |
| 2111 #ifdef _WIN32 | |
| 2112 fz_set_stddbg(ctx, fz_stdods(ctx)); | |
| 2113 #endif | |
| 2114 | |
| 2115 fz_var(out); | |
| 2116 | |
| 2117 fz_try(ctx) | |
| 2118 { | |
| 2119 out = fz_new_output_with_path(ctx, outfile, append); | |
| 2120 while (fz_optind < argc) | |
| 2121 filter_file(ctx, out, argv[fz_optind++]); | |
| 2122 fz_close_output(ctx, out); | |
| 2123 } | |
| 2124 fz_always(ctx) | |
| 2125 fz_drop_output(ctx, out); | |
| 2126 fz_catch(ctx) | |
| 2127 { | |
| 2128 fz_report_error(ctx); | |
| 2129 errors++; | |
| 2130 } | |
| 2131 fz_drop_context(ctx); | |
| 2132 | |
| 2133 return errors != 0; | |
| 2134 } |
