| 1 | #include "mupdf/fitz.h" | 
|---|
| 2 | #include "mupdf/pdf.h" | 
|---|
| 3 |  | 
|---|
| 4 | #include <string.h> | 
|---|
| 5 | #include <math.h> | 
|---|
| 6 |  | 
|---|
| 7 | #define TILE | 
|---|
| 8 |  | 
|---|
| 9 | /* | 
|---|
| 10 | * Emit graphics calls to device. | 
|---|
| 11 | */ | 
|---|
| 12 |  | 
|---|
| 13 | typedef struct pdf_material_s pdf_material; | 
|---|
| 14 | typedef struct pdf_run_processor_s pdf_run_processor; | 
|---|
| 15 |  | 
|---|
| 16 | static void pdf_run_xobject(fz_context *ctx, pdf_run_processor *proc, pdf_obj *xobj, pdf_obj *page_resources, fz_matrix transform, int is_smask); | 
|---|
| 17 |  | 
|---|
| 18 | enum | 
|---|
| 19 | { | 
|---|
| 20 | PDF_FILL, | 
|---|
| 21 | PDF_STROKE, | 
|---|
| 22 | }; | 
|---|
| 23 |  | 
|---|
| 24 | enum | 
|---|
| 25 | { | 
|---|
| 26 | PDF_MAT_NONE, | 
|---|
| 27 | PDF_MAT_COLOR, | 
|---|
| 28 | PDF_MAT_PATTERN, | 
|---|
| 29 | PDF_MAT_SHADE, | 
|---|
| 30 | }; | 
|---|
| 31 |  | 
|---|
| 32 | struct pdf_material_s | 
|---|
| 33 | { | 
|---|
| 34 | int kind; | 
|---|
| 35 | fz_colorspace *colorspace; | 
|---|
| 36 | pdf_pattern *pattern; | 
|---|
| 37 | fz_shade *shade; | 
|---|
| 38 | int gstate_num; | 
|---|
| 39 | fz_color_params color_params; | 
|---|
| 40 | float alpha; | 
|---|
| 41 | float v[FZ_MAX_COLORS]; | 
|---|
| 42 | }; | 
|---|
| 43 |  | 
|---|
| 44 | struct pdf_gstate_s | 
|---|
| 45 | { | 
|---|
| 46 | fz_matrix ctm; | 
|---|
| 47 | int clip_depth; | 
|---|
| 48 |  | 
|---|
| 49 | /* path stroking */ | 
|---|
| 50 | fz_stroke_state *stroke_state; | 
|---|
| 51 |  | 
|---|
| 52 | /* materials */ | 
|---|
| 53 | pdf_material stroke; | 
|---|
| 54 | pdf_material fill; | 
|---|
| 55 |  | 
|---|
| 56 | /* text state */ | 
|---|
| 57 | pdf_text_state text; | 
|---|
| 58 |  | 
|---|
| 59 | /* transparency */ | 
|---|
| 60 | int blendmode; | 
|---|
| 61 | pdf_obj *softmask; | 
|---|
| 62 | pdf_obj *softmask_resources; | 
|---|
| 63 | fz_matrix softmask_ctm; | 
|---|
| 64 | float softmask_bc[FZ_MAX_COLORS]; | 
|---|
| 65 | int luminosity; | 
|---|
| 66 | }; | 
|---|
| 67 |  | 
|---|
| 68 | struct pdf_run_processor_s | 
|---|
| 69 | { | 
|---|
| 70 | pdf_processor super; | 
|---|
| 71 | fz_device *dev; | 
|---|
| 72 | fz_cookie *cookie; | 
|---|
| 73 |  | 
|---|
| 74 | fz_default_colorspaces *default_cs; | 
|---|
| 75 |  | 
|---|
| 76 | /* path object state */ | 
|---|
| 77 | fz_path *path; | 
|---|
| 78 | int clip; | 
|---|
| 79 | int clip_even_odd; | 
|---|
| 80 |  | 
|---|
| 81 | /* text object state */ | 
|---|
| 82 | pdf_text_object_state tos; | 
|---|
| 83 |  | 
|---|
| 84 | /* graphics state */ | 
|---|
| 85 | pdf_gstate *gstate; | 
|---|
| 86 | int gcap; | 
|---|
| 87 | int gtop; | 
|---|
| 88 | int gbot; | 
|---|
| 89 | int gparent; | 
|---|
| 90 | }; | 
|---|
| 91 |  | 
|---|
| 92 | typedef struct softmask_save_s softmask_save; | 
|---|
| 93 |  | 
|---|
| 94 | struct softmask_save_s | 
|---|
| 95 | { | 
|---|
| 96 | pdf_obj *softmask; | 
|---|
| 97 | pdf_obj *page_resources; | 
|---|
| 98 | fz_matrix ctm; | 
|---|
| 99 | }; | 
|---|
| 100 |  | 
|---|
| 101 | static pdf_gstate * | 
|---|
| 102 | begin_softmask(fz_context *ctx, pdf_run_processor *pr, softmask_save *save) | 
|---|
| 103 | { | 
|---|
| 104 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 105 | pdf_obj *softmask = gstate->softmask; | 
|---|
| 106 | fz_rect mask_bbox; | 
|---|
| 107 | fz_matrix tos_save[2], save_ctm; | 
|---|
| 108 | fz_matrix mask_matrix; | 
|---|
| 109 | fz_colorspace *mask_colorspace; | 
|---|
| 110 | int saved_blendmode; | 
|---|
| 111 |  | 
|---|
| 112 | save->softmask = softmask; | 
|---|
| 113 | if (softmask == NULL) | 
|---|
| 114 | return gstate; | 
|---|
| 115 | save->page_resources = gstate->softmask_resources; | 
|---|
| 116 | save->ctm = gstate->softmask_ctm; | 
|---|
| 117 | save_ctm = gstate->ctm; | 
|---|
| 118 |  | 
|---|
| 119 | mask_bbox = pdf_xobject_bbox(ctx, softmask); | 
|---|
| 120 | mask_matrix = pdf_xobject_matrix(ctx, softmask); | 
|---|
| 121 |  | 
|---|
| 122 | pdf_tos_save(ctx, &pr->tos, tos_save); | 
|---|
| 123 |  | 
|---|
| 124 | if (gstate->luminosity) | 
|---|
| 125 | mask_bbox = fz_infinite_rect; | 
|---|
| 126 | else | 
|---|
| 127 | { | 
|---|
| 128 | mask_bbox = fz_transform_rect(mask_bbox, mask_matrix); | 
|---|
| 129 | mask_bbox = fz_transform_rect(mask_bbox, gstate->softmask_ctm); | 
|---|
| 130 | } | 
|---|
| 131 | gstate->softmask = NULL; | 
|---|
| 132 | gstate->softmask_resources = NULL; | 
|---|
| 133 | gstate->ctm = gstate->softmask_ctm; | 
|---|
| 134 |  | 
|---|
| 135 | saved_blendmode = gstate->blendmode; | 
|---|
| 136 |  | 
|---|
| 137 | mask_colorspace = pdf_xobject_colorspace(ctx, softmask); | 
|---|
| 138 | if (gstate->luminosity && !mask_colorspace) | 
|---|
| 139 | mask_colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx)); | 
|---|
| 140 |  | 
|---|
| 141 | fz_try(ctx) | 
|---|
| 142 | { | 
|---|
| 143 | fz_begin_mask(ctx, pr->dev, mask_bbox, gstate->luminosity, mask_colorspace, gstate->softmask_bc, gstate->fill.color_params); | 
|---|
| 144 | gstate->blendmode = 0; | 
|---|
| 145 | pdf_run_xobject(ctx, pr, softmask, save->page_resources, fz_identity, 1); | 
|---|
| 146 | gstate = pr->gstate + pr->gtop; | 
|---|
| 147 | gstate->blendmode = saved_blendmode; | 
|---|
| 148 | fz_end_mask(ctx, pr->dev); | 
|---|
| 149 | } | 
|---|
| 150 | fz_always(ctx) | 
|---|
| 151 | fz_drop_colorspace(ctx, mask_colorspace); | 
|---|
| 152 | fz_catch(ctx) | 
|---|
| 153 | fz_rethrow(ctx); | 
|---|
| 154 |  | 
|---|
| 155 | pdf_tos_restore(ctx, &pr->tos, tos_save); | 
|---|
| 156 |  | 
|---|
| 157 | gstate = pr->gstate + pr->gtop; | 
|---|
| 158 | gstate->ctm = save_ctm; | 
|---|
| 159 |  | 
|---|
| 160 | return gstate; | 
|---|
| 161 | } | 
|---|
| 162 |  | 
|---|
| 163 | static void | 
|---|
| 164 | end_softmask(fz_context *ctx, pdf_run_processor *pr, softmask_save *save) | 
|---|
| 165 | { | 
|---|
| 166 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 167 |  | 
|---|
| 168 | if (save->softmask == NULL) | 
|---|
| 169 | return; | 
|---|
| 170 |  | 
|---|
| 171 | gstate->softmask = save->softmask; | 
|---|
| 172 | gstate->softmask_resources = save->page_resources; | 
|---|
| 173 | gstate->softmask_ctm = save->ctm; | 
|---|
| 174 | save->softmask = NULL; | 
|---|
| 175 | save->page_resources = NULL; | 
|---|
| 176 |  | 
|---|
| 177 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 178 | } | 
|---|
| 179 |  | 
|---|
| 180 | static pdf_gstate * | 
|---|
| 181 | pdf_begin_group(fz_context *ctx, pdf_run_processor *pr, fz_rect bbox, softmask_save *softmask) | 
|---|
| 182 | { | 
|---|
| 183 | pdf_gstate *gstate = begin_softmask(ctx, pr, softmask); | 
|---|
| 184 |  | 
|---|
| 185 | if (gstate->blendmode) | 
|---|
| 186 | fz_begin_group(ctx, pr->dev, bbox, NULL, 0, 0, gstate->blendmode, 1); | 
|---|
| 187 |  | 
|---|
| 188 | return pr->gstate + pr->gtop; | 
|---|
| 189 | } | 
|---|
| 190 |  | 
|---|
| 191 | static void | 
|---|
| 192 | pdf_end_group(fz_context *ctx, pdf_run_processor *pr, softmask_save *softmask) | 
|---|
| 193 | { | 
|---|
| 194 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 195 |  | 
|---|
| 196 | if (gstate->blendmode) | 
|---|
| 197 | fz_end_group(ctx, pr->dev); | 
|---|
| 198 |  | 
|---|
| 199 | end_softmask(ctx, pr, softmask); | 
|---|
| 200 | } | 
|---|
| 201 |  | 
|---|
| 202 | static void | 
|---|
| 203 | pdf_show_shade(fz_context *ctx, pdf_run_processor *pr, fz_shade *shd) | 
|---|
| 204 | { | 
|---|
| 205 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 206 | fz_rect bbox; | 
|---|
| 207 | softmask_save softmask = { NULL }; | 
|---|
| 208 |  | 
|---|
| 209 | if (pr->super.hidden) | 
|---|
| 210 | return; | 
|---|
| 211 |  | 
|---|
| 212 | bbox = fz_bound_shade(ctx, shd, gstate->ctm); | 
|---|
| 213 |  | 
|---|
| 214 | gstate = pdf_begin_group(ctx, pr, bbox, &softmask); | 
|---|
| 215 |  | 
|---|
| 216 | /* FIXME: The gstate->ctm in the next line may be wrong; maybe | 
|---|
| 217 | * it should be the parent gstates ctm? */ | 
|---|
| 218 | fz_fill_shade(ctx, pr->dev, shd, gstate->ctm, gstate->fill.alpha, gstate->fill.color_params); | 
|---|
| 219 |  | 
|---|
| 220 | pdf_end_group(ctx, pr, &softmask); | 
|---|
| 221 | } | 
|---|
| 222 |  | 
|---|
| 223 | static pdf_material * | 
|---|
| 224 | pdf_keep_material(fz_context *ctx, pdf_material *mat) | 
|---|
| 225 | { | 
|---|
| 226 | if (mat->colorspace) | 
|---|
| 227 | fz_keep_colorspace(ctx, mat->colorspace); | 
|---|
| 228 | if (mat->pattern) | 
|---|
| 229 | pdf_keep_pattern(ctx, mat->pattern); | 
|---|
| 230 | if (mat->shade) | 
|---|
| 231 | fz_keep_shade(ctx, mat->shade); | 
|---|
| 232 | return mat; | 
|---|
| 233 | } | 
|---|
| 234 |  | 
|---|
| 235 | static pdf_material * | 
|---|
| 236 | pdf_drop_material(fz_context *ctx, pdf_material *mat) | 
|---|
| 237 | { | 
|---|
| 238 | fz_drop_colorspace(ctx, mat->colorspace); | 
|---|
| 239 | pdf_drop_pattern(ctx, mat->pattern); | 
|---|
| 240 | fz_drop_shade(ctx, mat->shade); | 
|---|
| 241 | return mat; | 
|---|
| 242 | } | 
|---|
| 243 |  | 
|---|
| 244 | static void | 
|---|
| 245 | pdf_copy_pattern_gstate(fz_context *ctx, pdf_gstate *dst, const pdf_gstate *src) | 
|---|
| 246 | { | 
|---|
| 247 | dst->ctm = src->ctm; | 
|---|
| 248 |  | 
|---|
| 249 | pdf_drop_font(ctx, dst->text.font); | 
|---|
| 250 | dst->text.font = pdf_keep_font(ctx, src->text.font); | 
|---|
| 251 |  | 
|---|
| 252 | pdf_drop_obj(ctx, dst->softmask); | 
|---|
| 253 | dst->softmask = pdf_keep_obj(ctx, src->softmask); | 
|---|
| 254 |  | 
|---|
| 255 | fz_drop_stroke_state(ctx, dst->stroke_state); | 
|---|
| 256 | dst->stroke_state = fz_keep_stroke_state(ctx, src->stroke_state); | 
|---|
| 257 | } | 
|---|
| 258 |  | 
|---|
| 259 | static void | 
|---|
| 260 | pdf_unset_pattern(fz_context *ctx, pdf_run_processor *pr, int what) | 
|---|
| 261 | { | 
|---|
| 262 | pdf_gstate *gs = pr->gstate + pr->gtop; | 
|---|
| 263 | pdf_material *mat; | 
|---|
| 264 | mat = what == PDF_FILL ? &gs->fill : &gs->stroke; | 
|---|
| 265 | if (mat->kind == PDF_MAT_PATTERN) | 
|---|
| 266 | { | 
|---|
| 267 | pdf_drop_pattern(ctx, mat->pattern); | 
|---|
| 268 | mat->pattern = NULL; | 
|---|
| 269 | mat->kind = PDF_MAT_COLOR; | 
|---|
| 270 | } | 
|---|
| 271 | } | 
|---|
| 272 |  | 
|---|
| 273 | static void | 
|---|
| 274 | pdf_keep_gstate(fz_context *ctx, pdf_gstate *gs) | 
|---|
| 275 | { | 
|---|
| 276 | pdf_keep_material(ctx, &gs->stroke); | 
|---|
| 277 | pdf_keep_material(ctx, &gs->fill); | 
|---|
| 278 | if (gs->text.font) | 
|---|
| 279 | pdf_keep_font(ctx, gs->text.font); | 
|---|
| 280 | if (gs->softmask) | 
|---|
| 281 | pdf_keep_obj(ctx, gs->softmask); | 
|---|
| 282 | if (gs->softmask_resources) | 
|---|
| 283 | pdf_keep_obj(ctx, gs->softmask_resources); | 
|---|
| 284 | fz_keep_stroke_state(ctx, gs->stroke_state); | 
|---|
| 285 | } | 
|---|
| 286 |  | 
|---|
| 287 | static void | 
|---|
| 288 | pdf_drop_gstate(fz_context *ctx, pdf_gstate *gs) | 
|---|
| 289 | { | 
|---|
| 290 | pdf_drop_material(ctx, &gs->stroke); | 
|---|
| 291 | pdf_drop_material(ctx, &gs->fill); | 
|---|
| 292 | pdf_drop_font(ctx, gs->text.font); | 
|---|
| 293 | pdf_drop_obj(ctx, gs->softmask); | 
|---|
| 294 | pdf_drop_obj(ctx, gs->softmask_resources); | 
|---|
| 295 | fz_drop_stroke_state(ctx, gs->stroke_state); | 
|---|
| 296 | } | 
|---|
| 297 |  | 
|---|
| 298 | static void | 
|---|
| 299 | pdf_gsave(fz_context *ctx, pdf_run_processor *pr) | 
|---|
| 300 | { | 
|---|
| 301 | if (pr->gtop == pr->gcap-1) | 
|---|
| 302 | { | 
|---|
| 303 | pr->gstate = fz_realloc_array(ctx, pr->gstate, pr->gcap*2, pdf_gstate); | 
|---|
| 304 | pr->gcap *= 2; | 
|---|
| 305 | } | 
|---|
| 306 |  | 
|---|
| 307 | memcpy(&pr->gstate[pr->gtop + 1], &pr->gstate[pr->gtop], sizeof(pdf_gstate)); | 
|---|
| 308 |  | 
|---|
| 309 | pr->gtop++; | 
|---|
| 310 | pdf_keep_gstate(ctx, &pr->gstate[pr->gtop]); | 
|---|
| 311 | } | 
|---|
| 312 |  | 
|---|
| 313 | static void | 
|---|
| 314 | pdf_grestore(fz_context *ctx, pdf_run_processor *pr) | 
|---|
| 315 | { | 
|---|
| 316 | pdf_gstate *gs = pr->gstate + pr->gtop; | 
|---|
| 317 | int clip_depth = gs->clip_depth; | 
|---|
| 318 |  | 
|---|
| 319 | if (pr->gtop <= pr->gbot) | 
|---|
| 320 | { | 
|---|
| 321 | fz_warn(ctx, "gstate underflow in content stream"); | 
|---|
| 322 | return; | 
|---|
| 323 | } | 
|---|
| 324 |  | 
|---|
| 325 | pdf_drop_gstate(ctx, gs); | 
|---|
| 326 | pr->gtop --; | 
|---|
| 327 |  | 
|---|
| 328 | gs = pr->gstate + pr->gtop; | 
|---|
| 329 | while (clip_depth > gs->clip_depth) | 
|---|
| 330 | { | 
|---|
| 331 | fz_try(ctx) | 
|---|
| 332 | { | 
|---|
| 333 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 334 | } | 
|---|
| 335 | fz_catch(ctx) | 
|---|
| 336 | { | 
|---|
| 337 | /* Silently swallow the problem - restores must | 
|---|
| 338 | * never throw! */ | 
|---|
| 339 | } | 
|---|
| 340 | clip_depth--; | 
|---|
| 341 | } | 
|---|
| 342 | } | 
|---|
| 343 |  | 
|---|
| 344 | static pdf_gstate * | 
|---|
| 345 | pdf_show_pattern(fz_context *ctx, pdf_run_processor *pr, pdf_pattern *pat, int pat_gstate_num, fz_rect area, int what) | 
|---|
| 346 | { | 
|---|
| 347 | pdf_gstate *gstate; | 
|---|
| 348 | pdf_gstate *pat_gstate; | 
|---|
| 349 | int gparent_save; | 
|---|
| 350 | fz_matrix ptm, invptm, gparent_save_ctm; | 
|---|
| 351 | int x0, y0, x1, y1; | 
|---|
| 352 | float fx0, fy0, fx1, fy1; | 
|---|
| 353 | fz_rect local_area; | 
|---|
| 354 | int id; | 
|---|
| 355 |  | 
|---|
| 356 | pdf_gsave(ctx, pr); | 
|---|
| 357 | gstate = pr->gstate + pr->gtop; | 
|---|
| 358 | pat_gstate = pr->gstate + pat_gstate_num; | 
|---|
| 359 |  | 
|---|
| 360 | /* Patterns are run with the gstate of the parent */ | 
|---|
| 361 | pdf_copy_pattern_gstate(ctx, gstate, pat_gstate); | 
|---|
| 362 |  | 
|---|
| 363 | if (pat->ismask) | 
|---|
| 364 | { | 
|---|
| 365 | pdf_unset_pattern(ctx, pr, PDF_FILL); | 
|---|
| 366 | pdf_unset_pattern(ctx, pr, PDF_STROKE); | 
|---|
| 367 | if (what == PDF_FILL) | 
|---|
| 368 | { | 
|---|
| 369 | pdf_drop_material(ctx, &gstate->stroke); | 
|---|
| 370 | pdf_keep_material(ctx, &gstate->fill); | 
|---|
| 371 | gstate->stroke = gstate->fill; | 
|---|
| 372 | } | 
|---|
| 373 | if (what == PDF_STROKE) | 
|---|
| 374 | { | 
|---|
| 375 | pdf_drop_material(ctx, &gstate->fill); | 
|---|
| 376 | pdf_keep_material(ctx, &gstate->stroke); | 
|---|
| 377 | gstate->fill = gstate->stroke; | 
|---|
| 378 | } | 
|---|
| 379 | id = 0; /* don't cache uncolored patterns, since we colorize them when drawing */ | 
|---|
| 380 | } | 
|---|
| 381 | else | 
|---|
| 382 | { | 
|---|
| 383 | // TODO: unset only the current fill/stroke or both? | 
|---|
| 384 | pdf_unset_pattern(ctx, pr, what); | 
|---|
| 385 | id = pat->id; | 
|---|
| 386 | } | 
|---|
| 387 |  | 
|---|
| 388 | /* don't apply soft masks to objects in the pattern as well */ | 
|---|
| 389 | if (gstate->softmask) | 
|---|
| 390 | { | 
|---|
| 391 | pdf_drop_obj(ctx, gstate->softmask); | 
|---|
| 392 | gstate->softmask = NULL; | 
|---|
| 393 | } | 
|---|
| 394 |  | 
|---|
| 395 | ptm = fz_concat(pat->matrix, pat_gstate->ctm); | 
|---|
| 396 | invptm = fz_invert_matrix(ptm); | 
|---|
| 397 |  | 
|---|
| 398 | /* The parent_ctm is amended with our pattern matrix */ | 
|---|
| 399 | gparent_save = pr->gparent; | 
|---|
| 400 | pr->gparent = pr->gtop-1; | 
|---|
| 401 | gparent_save_ctm = pr->gstate[pr->gparent].ctm; | 
|---|
| 402 | pr->gstate[pr->gparent].ctm = ptm; | 
|---|
| 403 |  | 
|---|
| 404 | /* patterns are painted using the parent_ctm. area = bbox of | 
|---|
| 405 | * shape to be filled in device space. Map it back to pattern | 
|---|
| 406 | * space. */ | 
|---|
| 407 | local_area = fz_transform_rect(area, invptm); | 
|---|
| 408 |  | 
|---|
| 409 | fx0 = (local_area.x0 - pat->bbox.x0) / pat->xstep; | 
|---|
| 410 | fy0 = (local_area.y0 - pat->bbox.y0) / pat->ystep; | 
|---|
| 411 | fx1 = (local_area.x1 - pat->bbox.x0) / pat->xstep; | 
|---|
| 412 | fy1 = (local_area.y1 - pat->bbox.y0) / pat->ystep; | 
|---|
| 413 | if (fx0 > fx1) | 
|---|
| 414 | { | 
|---|
| 415 | float t = fx0; fx0 = fx1; fx1 = t; | 
|---|
| 416 | } | 
|---|
| 417 | if (fy0 > fy1) | 
|---|
| 418 | { | 
|---|
| 419 | float t = fy0; fy0 = fy1; fy1 = t; | 
|---|
| 420 | } | 
|---|
| 421 |  | 
|---|
| 422 | #ifdef TILE | 
|---|
| 423 | /* We have tried various formulations in the past, but this one is | 
|---|
| 424 | * best we've found; only use it as a tile if a whole repeat is | 
|---|
| 425 | * required in at least one direction. Note, that this allows for | 
|---|
| 426 | * 'sections' of 4 tiles to be show, but all non-overlapping. */ | 
|---|
| 427 | if (fx1-fx0 > 1 || fy1-fy0 > 1) | 
|---|
| 428 | #else | 
|---|
| 429 | if (0) | 
|---|
| 430 | #endif | 
|---|
| 431 | { | 
|---|
| 432 | int cached = fz_begin_tile_id(ctx, pr->dev, local_area, pat->bbox, pat->xstep, pat->ystep, ptm, id); | 
|---|
| 433 | if (!cached) | 
|---|
| 434 | { | 
|---|
| 435 | gstate->ctm = ptm; | 
|---|
| 436 | pdf_gsave(ctx, pr); | 
|---|
| 437 | pdf_process_contents(ctx, (pdf_processor*)pr, pat->document, pat->resources, pat->contents, NULL); | 
|---|
| 438 | pdf_grestore(ctx, pr); | 
|---|
| 439 | } | 
|---|
| 440 | fz_end_tile(ctx, pr->dev); | 
|---|
| 441 | } | 
|---|
| 442 | else | 
|---|
| 443 | { | 
|---|
| 444 | int x, y; | 
|---|
| 445 |  | 
|---|
| 446 | /* When calculating the number of tiles required, we adjust by | 
|---|
| 447 | * a small amount to allow for rounding errors. By choosing | 
|---|
| 448 | * this amount to be smaller than 1/256, we guarantee we won't | 
|---|
| 449 | * cause problems that will be visible even under our most | 
|---|
| 450 | * extreme antialiasing. */ | 
|---|
| 451 | x0 = floorf(fx0 + 0.001f); | 
|---|
| 452 | y0 = floorf(fy0 + 0.001f); | 
|---|
| 453 | x1 = ceilf(fx1 - 0.001f); | 
|---|
| 454 | y1 = ceilf(fy1 - 0.001f); | 
|---|
| 455 | /* The above adjustments cause problems for sufficiently | 
|---|
| 456 | * large values for xstep/ystep which may be used if the | 
|---|
| 457 | * pattern is expected to be rendered exactly once. */ | 
|---|
| 458 | if (fx1 > fx0 && x1 == x0) | 
|---|
| 459 | x1 = x0 + 1; | 
|---|
| 460 | if (fy1 > fy0 && y1 == y0) | 
|---|
| 461 | y1 = y0 + 1; | 
|---|
| 462 |  | 
|---|
| 463 | for (y = y0; y < y1; y++) | 
|---|
| 464 | { | 
|---|
| 465 | for (x = x0; x < x1; x++) | 
|---|
| 466 | { | 
|---|
| 467 | gstate->ctm = fz_pre_translate(ptm, x * pat->xstep, y * pat->ystep); | 
|---|
| 468 | pdf_gsave(ctx, pr); | 
|---|
| 469 | pdf_process_contents(ctx, (pdf_processor*)pr, pat->document, pat->resources, pat->contents, NULL); | 
|---|
| 470 | pdf_grestore(ctx, pr); | 
|---|
| 471 | } | 
|---|
| 472 | } | 
|---|
| 473 | } | 
|---|
| 474 |  | 
|---|
| 475 | pr->gstate[pr->gparent].ctm = gparent_save_ctm; | 
|---|
| 476 | pr->gparent = gparent_save; | 
|---|
| 477 |  | 
|---|
| 478 | pdf_grestore(ctx, pr); | 
|---|
| 479 |  | 
|---|
| 480 | return pr->gstate + pr->gtop; | 
|---|
| 481 | } | 
|---|
| 482 |  | 
|---|
| 483 | static void | 
|---|
| 484 | pdf_show_image_imp(fz_context *ctx, pdf_run_processor *pr, fz_image *image, fz_matrix image_ctm, fz_rect bbox) | 
|---|
| 485 | { | 
|---|
| 486 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 487 |  | 
|---|
| 488 | if (image->colorspace) | 
|---|
| 489 | { | 
|---|
| 490 | fz_fill_image(ctx, pr->dev, image, image_ctm, gstate->fill.alpha, gstate->fill.color_params); | 
|---|
| 491 | } | 
|---|
| 492 | else if (gstate->fill.kind == PDF_MAT_COLOR) | 
|---|
| 493 | { | 
|---|
| 494 | fz_fill_image_mask(ctx, pr->dev, image, image_ctm, gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha, gstate->fill.color_params); | 
|---|
| 495 | } | 
|---|
| 496 | else if (gstate->fill.kind == PDF_MAT_PATTERN && gstate->fill.pattern) | 
|---|
| 497 | { | 
|---|
| 498 | fz_clip_image_mask(ctx, pr->dev, image, image_ctm, bbox); | 
|---|
| 499 | gstate = pdf_show_pattern(ctx, pr, gstate->fill.pattern, gstate->fill.gstate_num, bbox, PDF_FILL); | 
|---|
| 500 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 501 | } | 
|---|
| 502 | else if (gstate->fill.kind == PDF_MAT_SHADE && gstate->fill.shade) | 
|---|
| 503 | { | 
|---|
| 504 | fz_clip_image_mask(ctx, pr->dev, image, image_ctm, bbox); | 
|---|
| 505 | fz_fill_shade(ctx, pr->dev, gstate->fill.shade, pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha, gstate->fill.color_params); | 
|---|
| 506 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 507 | } | 
|---|
| 508 | } | 
|---|
| 509 |  | 
|---|
| 510 | static void | 
|---|
| 511 | pdf_show_image(fz_context *ctx, pdf_run_processor *pr, fz_image *image) | 
|---|
| 512 | { | 
|---|
| 513 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 514 | fz_matrix image_ctm; | 
|---|
| 515 | fz_rect bbox; | 
|---|
| 516 |  | 
|---|
| 517 | if (pr->super.hidden) | 
|---|
| 518 | return; | 
|---|
| 519 |  | 
|---|
| 520 | /* PDF has images bottom-up, so flip them right side up here */ | 
|---|
| 521 | image_ctm = fz_pre_scale(fz_pre_translate(gstate->ctm, 0, 1), 1, -1); | 
|---|
| 522 |  | 
|---|
| 523 | bbox = fz_transform_rect(fz_unit_rect, image_ctm); | 
|---|
| 524 |  | 
|---|
| 525 | if (image->mask && gstate->blendmode) | 
|---|
| 526 | { | 
|---|
| 527 | /* apply blend group even though we skip the soft mask */ | 
|---|
| 528 | fz_begin_group(ctx, pr->dev, bbox, NULL, 0, 0, gstate->blendmode, 1); | 
|---|
| 529 | fz_clip_image_mask(ctx, pr->dev, image->mask, image_ctm, bbox); | 
|---|
| 530 | pdf_show_image_imp(ctx, pr, image, image_ctm, bbox); | 
|---|
| 531 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 532 | fz_end_group(ctx, pr->dev); | 
|---|
| 533 | } | 
|---|
| 534 | else if (image->mask) | 
|---|
| 535 | { | 
|---|
| 536 | fz_clip_image_mask(ctx, pr->dev, image->mask, image_ctm, bbox); | 
|---|
| 537 | pdf_show_image_imp(ctx, pr, image, image_ctm, bbox); | 
|---|
| 538 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 539 | } | 
|---|
| 540 | else | 
|---|
| 541 | { | 
|---|
| 542 | softmask_save softmask = { NULL }; | 
|---|
| 543 | gstate = pdf_begin_group(ctx, pr, bbox, &softmask); | 
|---|
| 544 | pdf_show_image_imp(ctx, pr, image, image_ctm, bbox); | 
|---|
| 545 | pdf_end_group(ctx, pr, &softmask); | 
|---|
| 546 | } | 
|---|
| 547 | } | 
|---|
| 548 |  | 
|---|
| 549 | static void | 
|---|
| 550 | pdf_show_path(fz_context *ctx, pdf_run_processor *pr, int doclose, int dofill, int dostroke, int even_odd) | 
|---|
| 551 | { | 
|---|
| 552 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 553 | fz_path *path; | 
|---|
| 554 | fz_rect bbox; | 
|---|
| 555 | softmask_save softmask = { NULL }; | 
|---|
| 556 | int knockout_group = 0; | 
|---|
| 557 |  | 
|---|
| 558 | if (dostroke) { | 
|---|
| 559 | if (pr->dev->flags & (FZ_DEVFLAG_STROKECOLOR_UNDEFINED | FZ_DEVFLAG_LINEJOIN_UNDEFINED | FZ_DEVFLAG_LINEWIDTH_UNDEFINED)) | 
|---|
| 560 | pr->dev->flags |= FZ_DEVFLAG_UNCACHEABLE; | 
|---|
| 561 | else if (gstate->stroke_state->dash_len != 0 && pr->dev->flags & (FZ_DEVFLAG_STARTCAP_UNDEFINED | FZ_DEVFLAG_DASHCAP_UNDEFINED | FZ_DEVFLAG_ENDCAP_UNDEFINED)) | 
|---|
| 562 | pr->dev->flags |= FZ_DEVFLAG_UNCACHEABLE; | 
|---|
| 563 | else if (gstate->stroke_state->linejoin == FZ_LINEJOIN_MITER && (pr->dev->flags & FZ_DEVFLAG_MITERLIMIT_UNDEFINED)) | 
|---|
| 564 | pr->dev->flags |= FZ_DEVFLAG_UNCACHEABLE; | 
|---|
| 565 | } | 
|---|
| 566 | if (dofill) { | 
|---|
| 567 | if (pr->dev->flags & FZ_DEVFLAG_FILLCOLOR_UNDEFINED) | 
|---|
| 568 | pr->dev->flags |= FZ_DEVFLAG_UNCACHEABLE; | 
|---|
| 569 | } | 
|---|
| 570 |  | 
|---|
| 571 | path = pr->path; | 
|---|
| 572 | pr->path = fz_new_path(ctx); | 
|---|
| 573 |  | 
|---|
| 574 | fz_try(ctx) | 
|---|
| 575 | { | 
|---|
| 576 | if (doclose) | 
|---|
| 577 | fz_closepath(ctx, path); | 
|---|
| 578 |  | 
|---|
| 579 | bbox = fz_bound_path(ctx, path, (dostroke ? gstate->stroke_state : NULL), gstate->ctm); | 
|---|
| 580 |  | 
|---|
| 581 | if (pr->super.hidden) | 
|---|
| 582 | dostroke = dofill = 0; | 
|---|
| 583 |  | 
|---|
| 584 | if (dofill || dostroke) | 
|---|
| 585 | gstate = pdf_begin_group(ctx, pr, bbox, &softmask); | 
|---|
| 586 |  | 
|---|
| 587 | if (dofill && dostroke) | 
|---|
| 588 | { | 
|---|
| 589 | /* We may need to push a knockout group */ | 
|---|
| 590 | if (gstate->stroke.alpha == 0) | 
|---|
| 591 | { | 
|---|
| 592 | /* No need for group, as stroke won't do anything */ | 
|---|
| 593 | } | 
|---|
| 594 | else if (gstate->stroke.alpha == 1.0f && gstate->blendmode == FZ_BLEND_NORMAL) | 
|---|
| 595 | { | 
|---|
| 596 | /* No need for group, as stroke won't show up */ | 
|---|
| 597 | } | 
|---|
| 598 | else | 
|---|
| 599 | { | 
|---|
| 600 | knockout_group = 1; | 
|---|
| 601 | fz_begin_group(ctx, pr->dev, bbox, NULL, 0, 1, FZ_BLEND_NORMAL, 1); | 
|---|
| 602 | } | 
|---|
| 603 | } | 
|---|
| 604 |  | 
|---|
| 605 | if (dofill) | 
|---|
| 606 | { | 
|---|
| 607 | switch (gstate->fill.kind) | 
|---|
| 608 | { | 
|---|
| 609 | case PDF_MAT_NONE: | 
|---|
| 610 | break; | 
|---|
| 611 | case PDF_MAT_COLOR: | 
|---|
| 612 | fz_fill_path(ctx, pr->dev, path, even_odd, gstate->ctm, | 
|---|
| 613 | gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha, gstate->fill.color_params); | 
|---|
| 614 | break; | 
|---|
| 615 | case PDF_MAT_PATTERN: | 
|---|
| 616 | if (gstate->fill.pattern) | 
|---|
| 617 | { | 
|---|
| 618 | fz_clip_path(ctx, pr->dev, path, even_odd, gstate->ctm, bbox); | 
|---|
| 619 | gstate = pdf_show_pattern(ctx, pr, gstate->fill.pattern, gstate->fill.gstate_num, bbox, PDF_FILL); | 
|---|
| 620 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 621 | } | 
|---|
| 622 | break; | 
|---|
| 623 | case PDF_MAT_SHADE: | 
|---|
| 624 | if (gstate->fill.shade) | 
|---|
| 625 | { | 
|---|
| 626 | fz_clip_path(ctx, pr->dev, path, even_odd, gstate->ctm, bbox); | 
|---|
| 627 | /* The cluster and page 2 of patterns.pdf shows that fz_fill_shade should NOT be called with gstate->ctm. */ | 
|---|
| 628 | fz_fill_shade(ctx, pr->dev, gstate->fill.shade, pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha, gstate->fill.color_params); | 
|---|
| 629 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 630 | } | 
|---|
| 631 | break; | 
|---|
| 632 | } | 
|---|
| 633 | } | 
|---|
| 634 |  | 
|---|
| 635 | if (dostroke) | 
|---|
| 636 | { | 
|---|
| 637 | switch (gstate->stroke.kind) | 
|---|
| 638 | { | 
|---|
| 639 | case PDF_MAT_NONE: | 
|---|
| 640 | break; | 
|---|
| 641 | case PDF_MAT_COLOR: | 
|---|
| 642 | fz_stroke_path(ctx, pr->dev, path, gstate->stroke_state, gstate->ctm, | 
|---|
| 643 | gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha, gstate->stroke.color_params); | 
|---|
| 644 | break; | 
|---|
| 645 | case PDF_MAT_PATTERN: | 
|---|
| 646 | if (gstate->stroke.pattern) | 
|---|
| 647 | { | 
|---|
| 648 | fz_clip_stroke_path(ctx, pr->dev, path, gstate->stroke_state, gstate->ctm, bbox); | 
|---|
| 649 | gstate = pdf_show_pattern(ctx, pr, gstate->stroke.pattern, gstate->stroke.gstate_num, bbox, PDF_STROKE); | 
|---|
| 650 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 651 | } | 
|---|
| 652 | break; | 
|---|
| 653 | case PDF_MAT_SHADE: | 
|---|
| 654 | if (gstate->stroke.shade) | 
|---|
| 655 | { | 
|---|
| 656 | fz_clip_stroke_path(ctx, pr->dev, path, gstate->stroke_state, gstate->ctm, bbox); | 
|---|
| 657 | fz_fill_shade(ctx, pr->dev, gstate->stroke.shade, pr->gstate[gstate->stroke.gstate_num].ctm, gstate->stroke.alpha, gstate->stroke.color_params); | 
|---|
| 658 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 659 | } | 
|---|
| 660 | break; | 
|---|
| 661 | } | 
|---|
| 662 | } | 
|---|
| 663 |  | 
|---|
| 664 | if (knockout_group) | 
|---|
| 665 | fz_end_group(ctx, pr->dev); | 
|---|
| 666 |  | 
|---|
| 667 | if (dofill || dostroke) | 
|---|
| 668 | pdf_end_group(ctx, pr, &softmask); | 
|---|
| 669 |  | 
|---|
| 670 | if (pr->clip) | 
|---|
| 671 | { | 
|---|
| 672 | gstate->clip_depth++; | 
|---|
| 673 | fz_clip_path(ctx, pr->dev, path, pr->clip_even_odd, gstate->ctm, bbox); | 
|---|
| 674 | pr->clip = 0; | 
|---|
| 675 | } | 
|---|
| 676 | } | 
|---|
| 677 | fz_always(ctx) | 
|---|
| 678 | { | 
|---|
| 679 | fz_drop_path(ctx, path); | 
|---|
| 680 | } | 
|---|
| 681 | fz_catch(ctx) | 
|---|
| 682 | { | 
|---|
| 683 | fz_rethrow(ctx); | 
|---|
| 684 | } | 
|---|
| 685 | } | 
|---|
| 686 |  | 
|---|
| 687 | /* | 
|---|
| 688 | * Assemble and emit text | 
|---|
| 689 | */ | 
|---|
| 690 |  | 
|---|
| 691 | static pdf_gstate * | 
|---|
| 692 | pdf_flush_text(fz_context *ctx, pdf_run_processor *pr) | 
|---|
| 693 | { | 
|---|
| 694 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 695 | fz_text *text; | 
|---|
| 696 | int dofill; | 
|---|
| 697 | int dostroke; | 
|---|
| 698 | int doclip; | 
|---|
| 699 | int doinvisible; | 
|---|
| 700 | softmask_save softmask = { NULL }; | 
|---|
| 701 | int knockout_group = 0; | 
|---|
| 702 |  | 
|---|
| 703 | text = pdf_tos_get_text(ctx, &pr->tos); | 
|---|
| 704 | if (!text) | 
|---|
| 705 | return gstate; | 
|---|
| 706 |  | 
|---|
| 707 | dofill = dostroke = doclip = doinvisible = 0; | 
|---|
| 708 | switch (pr->tos.text_mode) | 
|---|
| 709 | { | 
|---|
| 710 | case 0: dofill = 1; break; | 
|---|
| 711 | case 1: dostroke = 1; break; | 
|---|
| 712 | case 2: dofill = dostroke = 1; break; | 
|---|
| 713 | case 3: doinvisible = 1; break; | 
|---|
| 714 | case 4: dofill = doclip = 1; break; | 
|---|
| 715 | case 5: dostroke = doclip = 1; break; | 
|---|
| 716 | case 6: dofill = dostroke = doclip = 1; break; | 
|---|
| 717 | case 7: doclip = 1; break; | 
|---|
| 718 | } | 
|---|
| 719 |  | 
|---|
| 720 | if (pr->super.hidden) | 
|---|
| 721 | dostroke = dofill = 0; | 
|---|
| 722 |  | 
|---|
| 723 | fz_try(ctx) | 
|---|
| 724 | { | 
|---|
| 725 | fz_rect tb = fz_transform_rect(pr->tos.text_bbox, gstate->ctm); | 
|---|
| 726 | if (dostroke) | 
|---|
| 727 | tb = fz_adjust_rect_for_stroke(ctx, tb, gstate->stroke_state, gstate->ctm); | 
|---|
| 728 |  | 
|---|
| 729 | /* Don't bother sending a text group with nothing in it */ | 
|---|
| 730 | if (!text->head) | 
|---|
| 731 | break; | 
|---|
| 732 |  | 
|---|
| 733 | if (dofill || dostroke) | 
|---|
| 734 | gstate = pdf_begin_group(ctx, pr, tb, &softmask); | 
|---|
| 735 |  | 
|---|
| 736 | if (dofill && dostroke) | 
|---|
| 737 | { | 
|---|
| 738 | /* We may need to push a knockout group */ | 
|---|
| 739 | if (gstate->stroke.alpha == 0) | 
|---|
| 740 | { | 
|---|
| 741 | /* No need for group, as stroke won't do anything */ | 
|---|
| 742 | } | 
|---|
| 743 | else if (gstate->stroke.alpha == 1.0f && gstate->blendmode == FZ_BLEND_NORMAL) | 
|---|
| 744 | { | 
|---|
| 745 | /* No need for group, as stroke won't show up */ | 
|---|
| 746 | } | 
|---|
| 747 | else | 
|---|
| 748 | { | 
|---|
| 749 | knockout_group = 1; | 
|---|
| 750 | fz_begin_group(ctx, pr->dev, tb, NULL, 0, 1, FZ_BLEND_NORMAL, 1); | 
|---|
| 751 | } | 
|---|
| 752 | } | 
|---|
| 753 |  | 
|---|
| 754 | if (doinvisible) | 
|---|
| 755 | fz_ignore_text(ctx, pr->dev, text, gstate->ctm); | 
|---|
| 756 |  | 
|---|
| 757 | if (dofill) | 
|---|
| 758 | { | 
|---|
| 759 | switch (gstate->fill.kind) | 
|---|
| 760 | { | 
|---|
| 761 | case PDF_MAT_NONE: | 
|---|
| 762 | break; | 
|---|
| 763 | case PDF_MAT_COLOR: | 
|---|
| 764 | fz_fill_text(ctx, pr->dev, text, gstate->ctm, | 
|---|
| 765 | gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha, gstate->fill.color_params); | 
|---|
| 766 | break; | 
|---|
| 767 | case PDF_MAT_PATTERN: | 
|---|
| 768 | if (gstate->fill.pattern) | 
|---|
| 769 | { | 
|---|
| 770 | fz_clip_text(ctx, pr->dev, text, gstate->ctm, tb); | 
|---|
| 771 | gstate = pdf_show_pattern(ctx, pr, gstate->fill.pattern, gstate->fill.gstate_num, tb, PDF_FILL); | 
|---|
| 772 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 773 | } | 
|---|
| 774 | break; | 
|---|
| 775 | case PDF_MAT_SHADE: | 
|---|
| 776 | if (gstate->fill.shade) | 
|---|
| 777 | { | 
|---|
| 778 | fz_clip_text(ctx, pr->dev, text, gstate->ctm, tb); | 
|---|
| 779 | /* Page 2 of patterns.pdf shows that fz_fill_shade should NOT be called with gstate->ctm */ | 
|---|
| 780 | fz_fill_shade(ctx, pr->dev, gstate->fill.shade, pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha, gstate->fill.color_params); | 
|---|
| 781 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 782 | } | 
|---|
| 783 | break; | 
|---|
| 784 | } | 
|---|
| 785 | } | 
|---|
| 786 |  | 
|---|
| 787 | if (dostroke) | 
|---|
| 788 | { | 
|---|
| 789 | switch (gstate->stroke.kind) | 
|---|
| 790 | { | 
|---|
| 791 | case PDF_MAT_NONE: | 
|---|
| 792 | break; | 
|---|
| 793 | case PDF_MAT_COLOR: | 
|---|
| 794 | fz_stroke_text(ctx, pr->dev, text, gstate->stroke_state, gstate->ctm, | 
|---|
| 795 | gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha, gstate->stroke.color_params); | 
|---|
| 796 | break; | 
|---|
| 797 | case PDF_MAT_PATTERN: | 
|---|
| 798 | if (gstate->stroke.pattern) | 
|---|
| 799 | { | 
|---|
| 800 | fz_clip_stroke_text(ctx, pr->dev, text, gstate->stroke_state, gstate->ctm, tb); | 
|---|
| 801 | gstate = pdf_show_pattern(ctx, pr, gstate->stroke.pattern, gstate->stroke.gstate_num, tb, PDF_STROKE); | 
|---|
| 802 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 803 | } | 
|---|
| 804 | break; | 
|---|
| 805 | case PDF_MAT_SHADE: | 
|---|
| 806 | if (gstate->stroke.shade) | 
|---|
| 807 | { | 
|---|
| 808 | fz_clip_stroke_text(ctx, pr->dev, text, gstate->stroke_state, gstate->ctm, tb); | 
|---|
| 809 | fz_fill_shade(ctx, pr->dev, gstate->stroke.shade, pr->gstate[gstate->stroke.gstate_num].ctm, gstate->stroke.alpha, gstate->stroke.color_params); | 
|---|
| 810 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 811 | } | 
|---|
| 812 | break; | 
|---|
| 813 | } | 
|---|
| 814 | } | 
|---|
| 815 |  | 
|---|
| 816 | if (knockout_group) | 
|---|
| 817 | fz_end_group(ctx, pr->dev); | 
|---|
| 818 |  | 
|---|
| 819 | if (dofill || dostroke) | 
|---|
| 820 | pdf_end_group(ctx, pr, &softmask); | 
|---|
| 821 |  | 
|---|
| 822 | if (doclip) | 
|---|
| 823 | { | 
|---|
| 824 | gstate->clip_depth++; | 
|---|
| 825 | fz_clip_text(ctx, pr->dev, text, gstate->ctm, tb); | 
|---|
| 826 | } | 
|---|
| 827 | } | 
|---|
| 828 | fz_always(ctx) | 
|---|
| 829 | { | 
|---|
| 830 | fz_drop_text(ctx, text); | 
|---|
| 831 | } | 
|---|
| 832 | fz_catch(ctx) | 
|---|
| 833 | { | 
|---|
| 834 | fz_rethrow(ctx); | 
|---|
| 835 | } | 
|---|
| 836 |  | 
|---|
| 837 | return pr->gstate + pr->gtop; | 
|---|
| 838 | } | 
|---|
| 839 |  | 
|---|
| 840 | static void | 
|---|
| 841 | pdf_show_char(fz_context *ctx, pdf_run_processor *pr, int cid) | 
|---|
| 842 | { | 
|---|
| 843 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 844 | pdf_font_desc *fontdesc = gstate->text.font; | 
|---|
| 845 | fz_matrix trm; | 
|---|
| 846 | int gid; | 
|---|
| 847 | int ucsbuf[8]; | 
|---|
| 848 | int ucslen; | 
|---|
| 849 | int i; | 
|---|
| 850 | int render_direct; | 
|---|
| 851 |  | 
|---|
| 852 | gid = pdf_tos_make_trm(ctx, &pr->tos, &gstate->text, fontdesc, cid, &trm); | 
|---|
| 853 |  | 
|---|
| 854 | /* If we are uncachable, then render direct. */ | 
|---|
| 855 | render_direct = !fz_glyph_cacheable(ctx, fontdesc->font, gid); | 
|---|
| 856 |  | 
|---|
| 857 | /* flush buffered text if rendermode has changed */ | 
|---|
| 858 | if (!pr->tos.text || gstate->text.render != pr->tos.text_mode || render_direct) | 
|---|
| 859 | { | 
|---|
| 860 | gstate = pdf_flush_text(ctx, pr); | 
|---|
| 861 | pdf_tos_reset(ctx, &pr->tos, gstate->text.render); | 
|---|
| 862 | } | 
|---|
| 863 |  | 
|---|
| 864 | if (render_direct) | 
|---|
| 865 | { | 
|---|
| 866 | /* Render the glyph stream direct here (only happens for | 
|---|
| 867 | * type3 glyphs that seem to inherit current graphics | 
|---|
| 868 | * attributes, or type 3 glyphs within type3 glyphs). */ | 
|---|
| 869 | fz_matrix composed = fz_concat(trm, gstate->ctm); | 
|---|
| 870 | fz_render_t3_glyph_direct(ctx, pr->dev, fontdesc->font, gid, composed, gstate, pr->default_cs); | 
|---|
| 871 | /* Render text invisibly so that it can still be extracted. */ | 
|---|
| 872 | pr->tos.text_mode = 3; | 
|---|
| 873 | } | 
|---|
| 874 |  | 
|---|
| 875 | ucslen = 0; | 
|---|
| 876 | if (fontdesc->to_unicode) | 
|---|
| 877 | ucslen = pdf_lookup_cmap_full(fontdesc->to_unicode, cid, ucsbuf); | 
|---|
| 878 | if (ucslen == 0 && (size_t)cid < fontdesc->cid_to_ucs_len) | 
|---|
| 879 | { | 
|---|
| 880 | ucsbuf[0] = fontdesc->cid_to_ucs[cid]; | 
|---|
| 881 | ucslen = 1; | 
|---|
| 882 | } | 
|---|
| 883 | if (ucslen == 0 || (ucslen == 1 && ucsbuf[0] == 0)) | 
|---|
| 884 | { | 
|---|
| 885 | ucsbuf[0] = FZ_REPLACEMENT_CHARACTER; | 
|---|
| 886 | ucslen = 1; | 
|---|
| 887 | } | 
|---|
| 888 |  | 
|---|
| 889 | /* add glyph to textobject */ | 
|---|
| 890 | fz_show_glyph(ctx, pr->tos.text, fontdesc->font, trm, gid, ucsbuf[0], fontdesc->wmode, 0, FZ_BIDI_NEUTRAL, FZ_LANG_UNSET); | 
|---|
| 891 |  | 
|---|
| 892 | /* add filler glyphs for one-to-many unicode mapping */ | 
|---|
| 893 | for (i = 1; i < ucslen; i++) | 
|---|
| 894 | fz_show_glyph(ctx, pr->tos.text, fontdesc->font, trm, -1, ucsbuf[i], fontdesc->wmode, 0, FZ_BIDI_NEUTRAL, FZ_LANG_UNSET); | 
|---|
| 895 |  | 
|---|
| 896 | pdf_tos_move_after_char(ctx, &pr->tos); | 
|---|
| 897 | } | 
|---|
| 898 |  | 
|---|
| 899 | static void | 
|---|
| 900 | pdf_show_space(fz_context *ctx, pdf_run_processor *pr, float tadj) | 
|---|
| 901 | { | 
|---|
| 902 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 903 | pdf_font_desc *fontdesc = gstate->text.font; | 
|---|
| 904 |  | 
|---|
| 905 | if (fontdesc->wmode == 0) | 
|---|
| 906 | pr->tos.tm = fz_pre_translate(pr->tos.tm, tadj * gstate->text.scale, 0); | 
|---|
| 907 | else | 
|---|
| 908 | pr->tos.tm = fz_pre_translate(pr->tos.tm, 0, tadj); | 
|---|
| 909 | } | 
|---|
| 910 |  | 
|---|
| 911 | static void | 
|---|
| 912 | show_string(fz_context *ctx, pdf_run_processor *pr, unsigned char *buf, int len) | 
|---|
| 913 | { | 
|---|
| 914 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 915 | pdf_font_desc *fontdesc = gstate->text.font; | 
|---|
| 916 | unsigned char *end = buf + len; | 
|---|
| 917 | unsigned int cpt; | 
|---|
| 918 | int cid; | 
|---|
| 919 |  | 
|---|
| 920 | while (buf < end) | 
|---|
| 921 | { | 
|---|
| 922 | int w = pdf_decode_cmap(fontdesc->encoding, buf, end, &cpt); | 
|---|
| 923 | buf += w; | 
|---|
| 924 |  | 
|---|
| 925 | cid = pdf_lookup_cmap(fontdesc->encoding, cpt); | 
|---|
| 926 | if (cid >= 0) | 
|---|
| 927 | pdf_show_char(ctx, pr, cid); | 
|---|
| 928 | else | 
|---|
| 929 | fz_warn(ctx, "cannot encode character"); | 
|---|
| 930 | if (cpt == 32 && w == 1) | 
|---|
| 931 | pdf_show_space(ctx, pr, gstate->text.word_space); | 
|---|
| 932 | } | 
|---|
| 933 | } | 
|---|
| 934 |  | 
|---|
| 935 | static void | 
|---|
| 936 | pdf_show_string(fz_context *ctx, pdf_run_processor *pr, unsigned char *buf, int len) | 
|---|
| 937 | { | 
|---|
| 938 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 939 | pdf_font_desc *fontdesc = gstate->text.font; | 
|---|
| 940 |  | 
|---|
| 941 | if (!fontdesc) | 
|---|
| 942 | { | 
|---|
| 943 | fz_warn(ctx, "cannot draw text since font and size not set"); | 
|---|
| 944 | return; | 
|---|
| 945 | } | 
|---|
| 946 |  | 
|---|
| 947 | show_string(ctx, pr, buf, len); | 
|---|
| 948 | } | 
|---|
| 949 |  | 
|---|
| 950 | static void | 
|---|
| 951 | pdf_show_text(fz_context *ctx, pdf_run_processor *pr, pdf_obj *text) | 
|---|
| 952 | { | 
|---|
| 953 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 954 | pdf_font_desc *fontdesc = gstate->text.font; | 
|---|
| 955 | int i; | 
|---|
| 956 |  | 
|---|
| 957 | if (!fontdesc) | 
|---|
| 958 | { | 
|---|
| 959 | fz_warn(ctx, "cannot draw text since font and size not set"); | 
|---|
| 960 | return; | 
|---|
| 961 | } | 
|---|
| 962 |  | 
|---|
| 963 | if (pdf_is_array(ctx, text)) | 
|---|
| 964 | { | 
|---|
| 965 | int n = pdf_array_len(ctx, text); | 
|---|
| 966 | for (i = 0; i < n; i++) | 
|---|
| 967 | { | 
|---|
| 968 | pdf_obj *item = pdf_array_get(ctx, text, i); | 
|---|
| 969 | if (pdf_is_string(ctx, item)) | 
|---|
| 970 | show_string(ctx, pr, (unsigned char *)pdf_to_str_buf(ctx, item), pdf_to_str_len(ctx, item)); | 
|---|
| 971 | else | 
|---|
| 972 | pdf_show_space(ctx, pr, - pdf_to_real(ctx, item) * gstate->text.size * 0.001f); | 
|---|
| 973 | } | 
|---|
| 974 | } | 
|---|
| 975 | else if (pdf_is_string(ctx, text)) | 
|---|
| 976 | { | 
|---|
| 977 | pdf_show_string(ctx, pr, (unsigned char *)pdf_to_str_buf(ctx, text), pdf_to_str_len(ctx, text)); | 
|---|
| 978 | } | 
|---|
| 979 | } | 
|---|
| 980 |  | 
|---|
| 981 | /* | 
|---|
| 982 | * Interpreter and graphics state stack. | 
|---|
| 983 | */ | 
|---|
| 984 |  | 
|---|
| 985 | static void | 
|---|
| 986 | pdf_init_gstate(fz_context *ctx, pdf_gstate *gs, fz_matrix ctm) | 
|---|
| 987 | { | 
|---|
| 988 | gs->ctm = ctm; | 
|---|
| 989 | gs->clip_depth = 0; | 
|---|
| 990 |  | 
|---|
| 991 | gs->stroke_state = fz_new_stroke_state(ctx); | 
|---|
| 992 |  | 
|---|
| 993 | gs->stroke.kind = PDF_MAT_COLOR; | 
|---|
| 994 | gs->stroke.colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx)); | 
|---|
| 995 | gs->stroke.v[0] = 0; | 
|---|
| 996 | gs->stroke.pattern = NULL; | 
|---|
| 997 | gs->stroke.shade = NULL; | 
|---|
| 998 | gs->stroke.alpha = 1; | 
|---|
| 999 | gs->stroke.gstate_num = -1; | 
|---|
| 1000 |  | 
|---|
| 1001 | gs->fill.kind = PDF_MAT_COLOR; | 
|---|
| 1002 | gs->fill.colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx)); | 
|---|
| 1003 | gs->fill.v[0] = 0; | 
|---|
| 1004 | gs->fill.pattern = NULL; | 
|---|
| 1005 | gs->fill.shade = NULL; | 
|---|
| 1006 | gs->fill.alpha = 1; | 
|---|
| 1007 | gs->fill.gstate_num = -1; | 
|---|
| 1008 |  | 
|---|
| 1009 | gs->text.char_space = 0; | 
|---|
| 1010 | gs->text.word_space = 0; | 
|---|
| 1011 | gs->text.scale = 1; | 
|---|
| 1012 | gs->text.leading = 0; | 
|---|
| 1013 | gs->text.font = NULL; | 
|---|
| 1014 | gs->text.size = -1; | 
|---|
| 1015 | gs->text.render = 0; | 
|---|
| 1016 | gs->text.rise = 0; | 
|---|
| 1017 |  | 
|---|
| 1018 | gs->blendmode = 0; | 
|---|
| 1019 | gs->softmask = NULL; | 
|---|
| 1020 | gs->softmask_resources = NULL; | 
|---|
| 1021 | gs->softmask_ctm = fz_identity; | 
|---|
| 1022 | gs->luminosity = 0; | 
|---|
| 1023 |  | 
|---|
| 1024 | gs->fill.color_params = fz_default_color_params; | 
|---|
| 1025 | gs->stroke.color_params = fz_default_color_params; | 
|---|
| 1026 | } | 
|---|
| 1027 |  | 
|---|
| 1028 | static void | 
|---|
| 1029 | pdf_copy_gstate(fz_context *ctx, pdf_gstate *dst, pdf_gstate *src) | 
|---|
| 1030 | { | 
|---|
| 1031 | pdf_drop_gstate(ctx, dst); | 
|---|
| 1032 | *dst = *src; | 
|---|
| 1033 | pdf_keep_gstate(ctx, dst); | 
|---|
| 1034 | } | 
|---|
| 1035 |  | 
|---|
| 1036 | /* | 
|---|
| 1037 | * Material state | 
|---|
| 1038 | */ | 
|---|
| 1039 |  | 
|---|
| 1040 | static void | 
|---|
| 1041 | pdf_set_colorspace(fz_context *ctx, pdf_run_processor *pr, int what, fz_colorspace *colorspace) | 
|---|
| 1042 | { | 
|---|
| 1043 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 1044 | pdf_material *mat; | 
|---|
| 1045 | int n = fz_colorspace_n(ctx, colorspace); | 
|---|
| 1046 |  | 
|---|
| 1047 | gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1048 |  | 
|---|
| 1049 | mat = what == PDF_FILL ? &gstate->fill : &gstate->stroke; | 
|---|
| 1050 |  | 
|---|
| 1051 | fz_drop_colorspace(ctx, mat->colorspace); | 
|---|
| 1052 |  | 
|---|
| 1053 | mat->kind = PDF_MAT_COLOR; | 
|---|
| 1054 | mat->colorspace = fz_keep_colorspace(ctx, colorspace); | 
|---|
| 1055 |  | 
|---|
| 1056 | mat->v[0] = 0; | 
|---|
| 1057 | mat->v[1] = 0; | 
|---|
| 1058 | mat->v[2] = 0; | 
|---|
| 1059 | mat->v[3] = 1; | 
|---|
| 1060 |  | 
|---|
| 1061 | if (pdf_is_tint_colorspace(ctx, colorspace)) | 
|---|
| 1062 | { | 
|---|
| 1063 | int i; | 
|---|
| 1064 | for (i = 0; i < n; i++) | 
|---|
| 1065 | mat->v[i] = 1.0f; | 
|---|
| 1066 | } | 
|---|
| 1067 | } | 
|---|
| 1068 |  | 
|---|
| 1069 | static void | 
|---|
| 1070 | pdf_set_color(fz_context *ctx, pdf_run_processor *pr, int what, float *v) | 
|---|
| 1071 | { | 
|---|
| 1072 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 1073 | pdf_material *mat; | 
|---|
| 1074 |  | 
|---|
| 1075 | gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1076 |  | 
|---|
| 1077 | mat = what == PDF_FILL ? &gstate->fill : &gstate->stroke; | 
|---|
| 1078 |  | 
|---|
| 1079 | switch (mat->kind) | 
|---|
| 1080 | { | 
|---|
| 1081 | case PDF_MAT_PATTERN: | 
|---|
| 1082 | case PDF_MAT_COLOR: | 
|---|
| 1083 | fz_clamp_color(ctx, mat->colorspace, v, mat->v); | 
|---|
| 1084 | break; | 
|---|
| 1085 | default: | 
|---|
| 1086 | fz_warn(ctx, "color incompatible with material"); | 
|---|
| 1087 | } | 
|---|
| 1088 |  | 
|---|
| 1089 | mat->gstate_num = pr->gparent; | 
|---|
| 1090 | } | 
|---|
| 1091 |  | 
|---|
| 1092 | static void | 
|---|
| 1093 | pdf_set_shade(fz_context *ctx, pdf_run_processor *pr, int what, fz_shade *shade) | 
|---|
| 1094 | { | 
|---|
| 1095 | pdf_gstate *gs; | 
|---|
| 1096 | pdf_material *mat; | 
|---|
| 1097 |  | 
|---|
| 1098 | gs = pdf_flush_text(ctx, pr); | 
|---|
| 1099 |  | 
|---|
| 1100 | mat = what == PDF_FILL ? &gs->fill : &gs->stroke; | 
|---|
| 1101 |  | 
|---|
| 1102 | fz_drop_shade(ctx, mat->shade); | 
|---|
| 1103 |  | 
|---|
| 1104 | mat->kind = PDF_MAT_SHADE; | 
|---|
| 1105 | mat->shade = fz_keep_shade(ctx, shade); | 
|---|
| 1106 |  | 
|---|
| 1107 | mat->gstate_num = pr->gparent; | 
|---|
| 1108 | } | 
|---|
| 1109 |  | 
|---|
| 1110 | static void | 
|---|
| 1111 | pdf_set_pattern(fz_context *ctx, pdf_run_processor *pr, int what, pdf_pattern *pat, float *v) | 
|---|
| 1112 | { | 
|---|
| 1113 | pdf_gstate *gs; | 
|---|
| 1114 | pdf_material *mat; | 
|---|
| 1115 |  | 
|---|
| 1116 | gs = pdf_flush_text(ctx, pr); | 
|---|
| 1117 |  | 
|---|
| 1118 | mat = what == PDF_FILL ? &gs->fill : &gs->stroke; | 
|---|
| 1119 |  | 
|---|
| 1120 | pdf_drop_pattern(ctx, mat->pattern); | 
|---|
| 1121 | mat->pattern = NULL; | 
|---|
| 1122 |  | 
|---|
| 1123 | mat->kind = PDF_MAT_PATTERN; | 
|---|
| 1124 | if (pat) | 
|---|
| 1125 | mat->pattern = pdf_keep_pattern(ctx, pat); | 
|---|
| 1126 |  | 
|---|
| 1127 | if (v) | 
|---|
| 1128 | pdf_set_color(ctx, pr, what, v); | 
|---|
| 1129 |  | 
|---|
| 1130 | mat->gstate_num = pr->gparent; | 
|---|
| 1131 | } | 
|---|
| 1132 |  | 
|---|
| 1133 | static void | 
|---|
| 1134 | pdf_run_xobject(fz_context *ctx, pdf_run_processor *proc, pdf_obj *xobj, pdf_obj *page_resources, fz_matrix transform, int is_smask) | 
|---|
| 1135 | { | 
|---|
| 1136 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1137 | pdf_gstate *gstate = NULL; | 
|---|
| 1138 | int oldtop = 0; | 
|---|
| 1139 | int oldbot = -1; | 
|---|
| 1140 | softmask_save softmask = { NULL }; | 
|---|
| 1141 | int gparent_save; | 
|---|
| 1142 | fz_matrix gparent_save_ctm; | 
|---|
| 1143 | pdf_obj *resources; | 
|---|
| 1144 | fz_rect xobj_bbox; | 
|---|
| 1145 | fz_matrix xobj_matrix; | 
|---|
| 1146 | int transparency = 0; | 
|---|
| 1147 | pdf_document *doc; | 
|---|
| 1148 | fz_colorspace *cs = NULL; | 
|---|
| 1149 | fz_default_colorspaces *save_default_cs = NULL; | 
|---|
| 1150 | fz_default_colorspaces *xobj_default_cs = NULL; | 
|---|
| 1151 |  | 
|---|
| 1152 | /* Avoid infinite recursion */ | 
|---|
| 1153 | if (xobj == NULL || pdf_mark_obj(ctx, xobj)) | 
|---|
| 1154 | return; | 
|---|
| 1155 |  | 
|---|
| 1156 | fz_var(cs); | 
|---|
| 1157 | fz_var(xobj_default_cs); | 
|---|
| 1158 |  | 
|---|
| 1159 | gparent_save = pr->gparent; | 
|---|
| 1160 | pr->gparent = pr->gtop; | 
|---|
| 1161 | oldtop = pr->gtop; | 
|---|
| 1162 |  | 
|---|
| 1163 | save_default_cs = pr->default_cs; | 
|---|
| 1164 |  | 
|---|
| 1165 | fz_try(ctx) | 
|---|
| 1166 | { | 
|---|
| 1167 | pdf_gsave(ctx, pr); | 
|---|
| 1168 |  | 
|---|
| 1169 | gstate = pr->gstate + pr->gtop; | 
|---|
| 1170 |  | 
|---|
| 1171 | xobj_bbox = pdf_xobject_bbox(ctx, xobj); | 
|---|
| 1172 | xobj_matrix = pdf_xobject_matrix(ctx, xobj); | 
|---|
| 1173 | transparency = pdf_xobject_transparency(ctx, xobj); | 
|---|
| 1174 |  | 
|---|
| 1175 | /* apply xobject's transform matrix */ | 
|---|
| 1176 | transform = fz_concat(xobj_matrix, transform); | 
|---|
| 1177 | gstate->ctm = fz_concat(transform, gstate->ctm); | 
|---|
| 1178 |  | 
|---|
| 1179 | /* The gparent is updated with the modified ctm */ | 
|---|
| 1180 | gparent_save_ctm = pr->gstate[pr->gparent].ctm; | 
|---|
| 1181 | pr->gstate[pr->gparent].ctm = gstate->ctm; | 
|---|
| 1182 |  | 
|---|
| 1183 | /* apply soft mask, create transparency group and reset state */ | 
|---|
| 1184 | if (transparency) | 
|---|
| 1185 | { | 
|---|
| 1186 | int isolated = pdf_xobject_isolated(ctx, xobj); | 
|---|
| 1187 |  | 
|---|
| 1188 | fz_rect bbox = fz_transform_rect(xobj_bbox, gstate->ctm); | 
|---|
| 1189 |  | 
|---|
| 1190 | gstate = begin_softmask(ctx, pr, &softmask); | 
|---|
| 1191 |  | 
|---|
| 1192 | if (isolated) | 
|---|
| 1193 | cs = pdf_xobject_colorspace(ctx, xobj); | 
|---|
| 1194 | fz_begin_group(ctx, pr->dev, bbox, | 
|---|
| 1195 | cs, | 
|---|
| 1196 | (is_smask ? 1 : isolated), | 
|---|
| 1197 | pdf_xobject_knockout(ctx, xobj), | 
|---|
| 1198 | gstate->blendmode, gstate->fill.alpha); | 
|---|
| 1199 |  | 
|---|
| 1200 | gstate->blendmode = 0; | 
|---|
| 1201 | gstate->stroke.alpha = 1; | 
|---|
| 1202 | gstate->fill.alpha = 1; | 
|---|
| 1203 | } | 
|---|
| 1204 |  | 
|---|
| 1205 | pdf_gsave(ctx, pr); /* Save here so the clippath doesn't persist */ | 
|---|
| 1206 |  | 
|---|
| 1207 | /* clip to the bounds */ | 
|---|
| 1208 | fz_moveto(ctx, pr->path, xobj_bbox.x0, xobj_bbox.y0); | 
|---|
| 1209 | fz_lineto(ctx, pr->path, xobj_bbox.x1, xobj_bbox.y0); | 
|---|
| 1210 | fz_lineto(ctx, pr->path, xobj_bbox.x1, xobj_bbox.y1); | 
|---|
| 1211 | fz_lineto(ctx, pr->path, xobj_bbox.x0, xobj_bbox.y1); | 
|---|
| 1212 | fz_closepath(ctx, pr->path); | 
|---|
| 1213 | pr->clip = 1; | 
|---|
| 1214 | pdf_show_path(ctx, pr, 0, 0, 0, 0); | 
|---|
| 1215 |  | 
|---|
| 1216 | /* run contents */ | 
|---|
| 1217 |  | 
|---|
| 1218 | resources = pdf_xobject_resources(ctx, xobj); | 
|---|
| 1219 | if (!resources) | 
|---|
| 1220 | resources = page_resources; | 
|---|
| 1221 |  | 
|---|
| 1222 | fz_try(ctx) | 
|---|
| 1223 | xobj_default_cs = pdf_update_default_colorspaces(ctx, pr->default_cs, resources); | 
|---|
| 1224 | fz_catch(ctx) | 
|---|
| 1225 | { | 
|---|
| 1226 | if (fz_caught(ctx) != FZ_ERROR_TRYLATER) | 
|---|
| 1227 | fz_rethrow(ctx); | 
|---|
| 1228 | if (pr->cookie) | 
|---|
| 1229 | pr->cookie->incomplete = 1; | 
|---|
| 1230 | } | 
|---|
| 1231 | if (xobj_default_cs != save_default_cs) | 
|---|
| 1232 | { | 
|---|
| 1233 | fz_set_default_colorspaces(ctx, pr->dev, xobj_default_cs); | 
|---|
| 1234 | pr->default_cs = xobj_default_cs; | 
|---|
| 1235 | } | 
|---|
| 1236 |  | 
|---|
| 1237 | doc = pdf_get_bound_document(ctx, xobj); | 
|---|
| 1238 |  | 
|---|
| 1239 | oldbot = pr->gbot; | 
|---|
| 1240 | pr->gbot = pr->gtop; | 
|---|
| 1241 |  | 
|---|
| 1242 | pdf_process_contents(ctx, (pdf_processor*)pr, doc, resources, xobj, pr->cookie); | 
|---|
| 1243 |  | 
|---|
| 1244 | /* Undo any gstate mismatches due to the pdf_process_contents call */ | 
|---|
| 1245 | if (oldbot != -1) | 
|---|
| 1246 | { | 
|---|
| 1247 | while (pr->gtop > pr->gbot) | 
|---|
| 1248 | { | 
|---|
| 1249 | pdf_grestore(ctx, pr); | 
|---|
| 1250 | } | 
|---|
| 1251 | pr->gbot = oldbot; | 
|---|
| 1252 | } | 
|---|
| 1253 |  | 
|---|
| 1254 | pdf_grestore(ctx, pr); /* Remove the state we pushed for the clippath */ | 
|---|
| 1255 |  | 
|---|
| 1256 | /* wrap up transparency stacks */ | 
|---|
| 1257 | if (transparency) | 
|---|
| 1258 | { | 
|---|
| 1259 | fz_end_group(ctx, pr->dev); | 
|---|
| 1260 | end_softmask(ctx, pr, &softmask); | 
|---|
| 1261 | } | 
|---|
| 1262 |  | 
|---|
| 1263 | pr->gstate[pr->gparent].ctm = gparent_save_ctm; | 
|---|
| 1264 | pr->gparent = gparent_save; | 
|---|
| 1265 |  | 
|---|
| 1266 | while (oldtop < pr->gtop) | 
|---|
| 1267 | pdf_grestore(ctx, pr); | 
|---|
| 1268 |  | 
|---|
| 1269 | if (xobj_default_cs != save_default_cs) | 
|---|
| 1270 | { | 
|---|
| 1271 | fz_set_default_colorspaces(ctx, pr->dev, save_default_cs); | 
|---|
| 1272 | } | 
|---|
| 1273 | } | 
|---|
| 1274 | fz_always(ctx) | 
|---|
| 1275 | { | 
|---|
| 1276 | pr->default_cs = save_default_cs; | 
|---|
| 1277 | fz_drop_default_colorspaces(ctx, xobj_default_cs); | 
|---|
| 1278 | fz_drop_colorspace(ctx, cs); | 
|---|
| 1279 | pdf_unmark_obj(ctx, xobj); | 
|---|
| 1280 | } | 
|---|
| 1281 | fz_catch(ctx) | 
|---|
| 1282 | { | 
|---|
| 1283 | pdf_drop_obj(ctx, softmask.softmask); | 
|---|
| 1284 | pdf_drop_obj(ctx, softmask.page_resources); | 
|---|
| 1285 | /* Note: Any SYNTAX errors should have been swallowed | 
|---|
| 1286 | * by pdf_process_contents, but in case any escape from other | 
|---|
| 1287 | * functions, recast the error type here to be safe. */ | 
|---|
| 1288 | if (fz_caught(ctx) == FZ_ERROR_SYNTAX) | 
|---|
| 1289 | fz_throw(ctx, FZ_ERROR_GENERIC, "syntax error in xobject"); | 
|---|
| 1290 | fz_rethrow(ctx); | 
|---|
| 1291 | } | 
|---|
| 1292 | } | 
|---|
| 1293 |  | 
|---|
| 1294 | /* general graphics state */ | 
|---|
| 1295 |  | 
|---|
| 1296 | static void pdf_run_w(fz_context *ctx, pdf_processor *proc, float linewidth) | 
|---|
| 1297 | { | 
|---|
| 1298 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1299 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1300 |  | 
|---|
| 1301 | pr->dev->flags &= ~FZ_DEVFLAG_LINEWIDTH_UNDEFINED; | 
|---|
| 1302 | gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state); | 
|---|
| 1303 | gstate->stroke_state->linewidth = linewidth; | 
|---|
| 1304 | } | 
|---|
| 1305 |  | 
|---|
| 1306 | static void pdf_run_j(fz_context *ctx, pdf_processor *proc, int linejoin) | 
|---|
| 1307 | { | 
|---|
| 1308 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1309 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1310 |  | 
|---|
| 1311 | pr->dev->flags &= ~FZ_DEVFLAG_LINEJOIN_UNDEFINED; | 
|---|
| 1312 | gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state); | 
|---|
| 1313 | gstate->stroke_state->linejoin = linejoin; | 
|---|
| 1314 | } | 
|---|
| 1315 |  | 
|---|
| 1316 | static void pdf_run_J(fz_context *ctx, pdf_processor *proc, int linecap) | 
|---|
| 1317 | { | 
|---|
| 1318 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1319 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1320 |  | 
|---|
| 1321 | pr->dev->flags &= ~(FZ_DEVFLAG_STARTCAP_UNDEFINED | FZ_DEVFLAG_DASHCAP_UNDEFINED | FZ_DEVFLAG_ENDCAP_UNDEFINED); | 
|---|
| 1322 | gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state); | 
|---|
| 1323 | gstate->stroke_state->start_cap = linecap; | 
|---|
| 1324 | gstate->stroke_state->dash_cap = linecap; | 
|---|
| 1325 | gstate->stroke_state->end_cap = linecap; | 
|---|
| 1326 | } | 
|---|
| 1327 |  | 
|---|
| 1328 | static void pdf_run_M(fz_context *ctx, pdf_processor *proc, float miterlimit) | 
|---|
| 1329 | { | 
|---|
| 1330 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1331 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1332 |  | 
|---|
| 1333 | pr->dev->flags &= ~FZ_DEVFLAG_MITERLIMIT_UNDEFINED; | 
|---|
| 1334 | gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state); | 
|---|
| 1335 | gstate->stroke_state->miterlimit = miterlimit; | 
|---|
| 1336 | } | 
|---|
| 1337 |  | 
|---|
| 1338 | static void pdf_run_d(fz_context *ctx, pdf_processor *proc, pdf_obj *array, float phase) | 
|---|
| 1339 | { | 
|---|
| 1340 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1341 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1342 | int len, i; | 
|---|
| 1343 |  | 
|---|
| 1344 | len = pdf_array_len(ctx, array); | 
|---|
| 1345 | gstate->stroke_state = fz_unshare_stroke_state_with_dash_len(ctx, gstate->stroke_state, len); | 
|---|
| 1346 | gstate->stroke_state->dash_len = len; | 
|---|
| 1347 | for (i = 0; i < len; i++) | 
|---|
| 1348 | gstate->stroke_state->dash_list[i] = pdf_array_get_real(ctx, array, i); | 
|---|
| 1349 | gstate->stroke_state->dash_phase = phase; | 
|---|
| 1350 | } | 
|---|
| 1351 |  | 
|---|
| 1352 | static void pdf_run_ri(fz_context *ctx, pdf_processor *proc, const char *intent) | 
|---|
| 1353 | { | 
|---|
| 1354 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1355 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1356 | gstate->fill.color_params.ri = fz_lookup_rendering_intent(intent); | 
|---|
| 1357 | gstate->stroke.color_params.ri = gstate->fill.color_params.ri; | 
|---|
| 1358 | } | 
|---|
| 1359 |  | 
|---|
| 1360 | static void pdf_run_gs_OP(fz_context *ctx, pdf_processor *proc, int b) | 
|---|
| 1361 | { | 
|---|
| 1362 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1363 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1364 | gstate->stroke.color_params.op = b; | 
|---|
| 1365 | gstate->fill.color_params.op = b; | 
|---|
| 1366 | } | 
|---|
| 1367 |  | 
|---|
| 1368 | static void pdf_run_gs_op(fz_context *ctx, pdf_processor *proc, int b) | 
|---|
| 1369 | { | 
|---|
| 1370 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1371 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1372 | gstate->fill.color_params.op = b; | 
|---|
| 1373 | } | 
|---|
| 1374 |  | 
|---|
| 1375 | static void pdf_run_gs_OPM(fz_context *ctx, pdf_processor *proc, int i) | 
|---|
| 1376 | { | 
|---|
| 1377 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1378 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1379 | gstate->stroke.color_params.opm = i; | 
|---|
| 1380 | gstate->fill.color_params.opm = i; | 
|---|
| 1381 | } | 
|---|
| 1382 |  | 
|---|
| 1383 | static void pdf_run_gs_UseBlackPtComp(fz_context *ctx, pdf_processor *proc, pdf_obj *obj) | 
|---|
| 1384 | { | 
|---|
| 1385 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1386 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1387 | int on = pdf_name_eq(ctx, obj, PDF_NAME(ON)); | 
|---|
| 1388 | /* The spec says that "ON" means on, "OFF" means "Off", and | 
|---|
| 1389 | * "Default" or anything else means "Meh, do what you want." */ | 
|---|
| 1390 | gstate->stroke.color_params.bp = on; | 
|---|
| 1391 | gstate->fill.color_params.bp = on; | 
|---|
| 1392 | } | 
|---|
| 1393 |  | 
|---|
| 1394 | static void pdf_run_i(fz_context *ctx, pdf_processor *proc, float flatness) | 
|---|
| 1395 | { | 
|---|
| 1396 | } | 
|---|
| 1397 |  | 
|---|
| 1398 | static void pdf_run_gs_begin(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *extgstate) | 
|---|
| 1399 | { | 
|---|
| 1400 | } | 
|---|
| 1401 |  | 
|---|
| 1402 | static void pdf_run_gs_end(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1403 | { | 
|---|
| 1404 | } | 
|---|
| 1405 |  | 
|---|
| 1406 | /* transparency graphics state */ | 
|---|
| 1407 |  | 
|---|
| 1408 | static void pdf_run_gs_BM(fz_context *ctx, pdf_processor *proc, const char *blendmode) | 
|---|
| 1409 | { | 
|---|
| 1410 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1411 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1412 | gstate->blendmode = fz_lookup_blendmode(blendmode); | 
|---|
| 1413 | } | 
|---|
| 1414 |  | 
|---|
| 1415 | static void pdf_run_gs_CA(fz_context *ctx, pdf_processor *proc, float alpha) | 
|---|
| 1416 | { | 
|---|
| 1417 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1418 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1419 | gstate->stroke.alpha = fz_clamp(alpha, 0, 1); | 
|---|
| 1420 | } | 
|---|
| 1421 |  | 
|---|
| 1422 | static void pdf_run_gs_ca(fz_context *ctx, pdf_processor *proc, float alpha) | 
|---|
| 1423 | { | 
|---|
| 1424 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1425 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1426 | gstate->fill.alpha = fz_clamp(alpha, 0, 1); | 
|---|
| 1427 | } | 
|---|
| 1428 |  | 
|---|
| 1429 | static void pdf_run_gs_SMask(fz_context *ctx, pdf_processor *proc, pdf_obj *smask, pdf_obj *page_resources, float *bc, int luminosity) | 
|---|
| 1430 | { | 
|---|
| 1431 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1432 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1433 | int i; | 
|---|
| 1434 |  | 
|---|
| 1435 | if (gstate->softmask) | 
|---|
| 1436 | { | 
|---|
| 1437 | pdf_drop_obj(ctx, gstate->softmask); | 
|---|
| 1438 | gstate->softmask = NULL; | 
|---|
| 1439 | pdf_drop_obj(ctx, gstate->softmask_resources); | 
|---|
| 1440 | gstate->softmask_resources = NULL; | 
|---|
| 1441 | } | 
|---|
| 1442 |  | 
|---|
| 1443 | if (smask) | 
|---|
| 1444 | { | 
|---|
| 1445 | fz_colorspace *cs = pdf_xobject_colorspace(ctx, smask); | 
|---|
| 1446 | int cs_n = 1; | 
|---|
| 1447 | if (cs) | 
|---|
| 1448 | cs_n = fz_colorspace_n(ctx, cs); | 
|---|
| 1449 | gstate->softmask_ctm = gstate->ctm; | 
|---|
| 1450 | gstate->softmask = pdf_keep_obj(ctx, smask); | 
|---|
| 1451 | gstate->softmask_resources = pdf_keep_obj(ctx, page_resources); | 
|---|
| 1452 | for (i = 0; i < cs_n; ++i) | 
|---|
| 1453 | gstate->softmask_bc[i] = bc[i]; | 
|---|
| 1454 | gstate->luminosity = luminosity; | 
|---|
| 1455 | fz_drop_colorspace(ctx, cs); | 
|---|
| 1456 | } | 
|---|
| 1457 | } | 
|---|
| 1458 |  | 
|---|
| 1459 | /* special graphics state */ | 
|---|
| 1460 |  | 
|---|
| 1461 | static void pdf_run_q(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1462 | { | 
|---|
| 1463 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1464 | pdf_gsave(ctx, pr); | 
|---|
| 1465 | } | 
|---|
| 1466 |  | 
|---|
| 1467 | static void pdf_run_Q(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1468 | { | 
|---|
| 1469 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1470 | pdf_grestore(ctx, pr); | 
|---|
| 1471 | } | 
|---|
| 1472 |  | 
|---|
| 1473 | static void pdf_run_cm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f) | 
|---|
| 1474 | { | 
|---|
| 1475 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1476 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); | 
|---|
| 1477 | fz_matrix m; | 
|---|
| 1478 |  | 
|---|
| 1479 | m.a = a; | 
|---|
| 1480 | m.b = b; | 
|---|
| 1481 | m.c = c; | 
|---|
| 1482 | m.d = d; | 
|---|
| 1483 | m.e = e; | 
|---|
| 1484 | m.f = f; | 
|---|
| 1485 | gstate->ctm = fz_concat(m, gstate->ctm); | 
|---|
| 1486 | } | 
|---|
| 1487 |  | 
|---|
| 1488 | /* path construction */ | 
|---|
| 1489 |  | 
|---|
| 1490 | static void pdf_run_m(fz_context *ctx, pdf_processor *proc, float x, float y) | 
|---|
| 1491 | { | 
|---|
| 1492 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1493 | fz_moveto(ctx, pr->path, x, y); | 
|---|
| 1494 | } | 
|---|
| 1495 |  | 
|---|
| 1496 | static void pdf_run_l(fz_context *ctx, pdf_processor *proc, float x, float y) | 
|---|
| 1497 | { | 
|---|
| 1498 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1499 | fz_lineto(ctx, pr->path, x, y); | 
|---|
| 1500 | } | 
|---|
| 1501 | static void pdf_run_c(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x2, float y2, float x3, float y3) | 
|---|
| 1502 | { | 
|---|
| 1503 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1504 | fz_curveto(ctx, pr->path, x1, y1, x2, y2, x3, y3); | 
|---|
| 1505 | } | 
|---|
| 1506 |  | 
|---|
| 1507 | static void pdf_run_v(fz_context *ctx, pdf_processor *proc, float x2, float y2, float x3, float y3) | 
|---|
| 1508 | { | 
|---|
| 1509 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1510 | fz_curvetov(ctx, pr->path, x2, y2, x3, y3); | 
|---|
| 1511 | } | 
|---|
| 1512 |  | 
|---|
| 1513 | static void pdf_run_y(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x3, float y3) | 
|---|
| 1514 | { | 
|---|
| 1515 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1516 | fz_curvetoy(ctx, pr->path, x1, y1, x3, y3); | 
|---|
| 1517 | } | 
|---|
| 1518 |  | 
|---|
| 1519 | static void pdf_run_h(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1520 | { | 
|---|
| 1521 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1522 | fz_closepath(ctx, pr->path); | 
|---|
| 1523 | } | 
|---|
| 1524 |  | 
|---|
| 1525 | static void pdf_run_re(fz_context *ctx, pdf_processor *proc, float x, float y, float w, float h) | 
|---|
| 1526 | { | 
|---|
| 1527 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1528 | fz_rectto(ctx, pr->path, x, y, x+w, y+h); | 
|---|
| 1529 | } | 
|---|
| 1530 |  | 
|---|
| 1531 | /* path painting */ | 
|---|
| 1532 |  | 
|---|
| 1533 | static void pdf_run_S(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1534 | { | 
|---|
| 1535 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1536 | pdf_show_path(ctx, pr, 0, 0, 1, 0); | 
|---|
| 1537 | } | 
|---|
| 1538 |  | 
|---|
| 1539 | static void pdf_run_s(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1540 | { | 
|---|
| 1541 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1542 | pdf_show_path(ctx, pr, 1, 0, 1, 0); | 
|---|
| 1543 | } | 
|---|
| 1544 |  | 
|---|
| 1545 | static void pdf_run_F(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1546 | { | 
|---|
| 1547 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1548 | pdf_show_path(ctx, pr, 0, 1, 0, 0); | 
|---|
| 1549 | } | 
|---|
| 1550 |  | 
|---|
| 1551 | static void pdf_run_f(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1552 | { | 
|---|
| 1553 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1554 | pdf_show_path(ctx, pr, 0, 1, 0, 0); | 
|---|
| 1555 | } | 
|---|
| 1556 |  | 
|---|
| 1557 | static void pdf_run_fstar(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1558 | { | 
|---|
| 1559 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1560 | pdf_show_path(ctx, pr, 0, 1, 0, 1); | 
|---|
| 1561 | } | 
|---|
| 1562 |  | 
|---|
| 1563 | static void pdf_run_B(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1564 | { | 
|---|
| 1565 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1566 | pdf_show_path(ctx, pr, 0, 1, 1, 0); | 
|---|
| 1567 | } | 
|---|
| 1568 |  | 
|---|
| 1569 | static void pdf_run_Bstar(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1570 | { | 
|---|
| 1571 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1572 | pdf_show_path(ctx, pr, 0, 1, 1, 1); | 
|---|
| 1573 | } | 
|---|
| 1574 |  | 
|---|
| 1575 | static void pdf_run_b(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1576 | { | 
|---|
| 1577 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1578 | pdf_show_path(ctx, pr, 1, 1, 1, 0); | 
|---|
| 1579 | } | 
|---|
| 1580 |  | 
|---|
| 1581 | static void pdf_run_bstar(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1582 | { | 
|---|
| 1583 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1584 | pdf_show_path(ctx, pr, 1, 1, 1, 1); | 
|---|
| 1585 | } | 
|---|
| 1586 |  | 
|---|
| 1587 | static void pdf_run_n(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1588 | { | 
|---|
| 1589 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1590 | pdf_show_path(ctx, pr, 0, 0, 0, 0); | 
|---|
| 1591 | } | 
|---|
| 1592 |  | 
|---|
| 1593 | /* clipping paths */ | 
|---|
| 1594 |  | 
|---|
| 1595 | static void pdf_run_W(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1596 | { | 
|---|
| 1597 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1598 | pr->clip = 1; | 
|---|
| 1599 | pr->clip_even_odd = 0; | 
|---|
| 1600 | } | 
|---|
| 1601 |  | 
|---|
| 1602 | static void pdf_run_Wstar(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1603 | { | 
|---|
| 1604 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1605 | pr->clip = 1; | 
|---|
| 1606 | pr->clip_even_odd = 1; | 
|---|
| 1607 | } | 
|---|
| 1608 |  | 
|---|
| 1609 | /* text objects */ | 
|---|
| 1610 |  | 
|---|
| 1611 | static void pdf_run_BT(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1612 | { | 
|---|
| 1613 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1614 | pr->tos.tm = fz_identity; | 
|---|
| 1615 | pr->tos.tlm = fz_identity; | 
|---|
| 1616 | } | 
|---|
| 1617 |  | 
|---|
| 1618 | static void pdf_run_ET(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1619 | { | 
|---|
| 1620 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1621 | pdf_flush_text(ctx, pr); | 
|---|
| 1622 | } | 
|---|
| 1623 |  | 
|---|
| 1624 | /* text state */ | 
|---|
| 1625 |  | 
|---|
| 1626 | static void pdf_run_Tc(fz_context *ctx, pdf_processor *proc, float charspace) | 
|---|
| 1627 | { | 
|---|
| 1628 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1629 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 1630 | gstate->text.char_space = charspace; | 
|---|
| 1631 | } | 
|---|
| 1632 |  | 
|---|
| 1633 | static void pdf_run_Tw(fz_context *ctx, pdf_processor *proc, float wordspace) | 
|---|
| 1634 | { | 
|---|
| 1635 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1636 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 1637 | gstate->text.word_space = wordspace; | 
|---|
| 1638 | } | 
|---|
| 1639 |  | 
|---|
| 1640 | static void pdf_run_Tz(fz_context *ctx, pdf_processor *proc, float scale) | 
|---|
| 1641 | { | 
|---|
| 1642 | /* scale is as written in the file. It is 100 times smaller in | 
|---|
| 1643 | * the gstate. */ | 
|---|
| 1644 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1645 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 1646 | gstate->text.scale = scale / 100; | 
|---|
| 1647 | } | 
|---|
| 1648 |  | 
|---|
| 1649 | static void pdf_run_TL(fz_context *ctx, pdf_processor *proc, float leading) | 
|---|
| 1650 | { | 
|---|
| 1651 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1652 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 1653 | gstate->text.leading = leading; | 
|---|
| 1654 | } | 
|---|
| 1655 |  | 
|---|
| 1656 | static void pdf_run_Tf(fz_context *ctx, pdf_processor *proc, const char *name, pdf_font_desc *font, float size) | 
|---|
| 1657 | { | 
|---|
| 1658 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1659 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 1660 | pdf_drop_font(ctx, gstate->text.font); | 
|---|
| 1661 | gstate->text.font = pdf_keep_font(ctx, font); | 
|---|
| 1662 | gstate->text.size = size; | 
|---|
| 1663 | } | 
|---|
| 1664 |  | 
|---|
| 1665 | static void pdf_run_Tr(fz_context *ctx, pdf_processor *proc, int render) | 
|---|
| 1666 | { | 
|---|
| 1667 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1668 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 1669 | gstate->text.render = render; | 
|---|
| 1670 | } | 
|---|
| 1671 |  | 
|---|
| 1672 | static void pdf_run_Ts(fz_context *ctx, pdf_processor *proc, float rise) | 
|---|
| 1673 | { | 
|---|
| 1674 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1675 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 1676 | gstate->text.rise = rise; | 
|---|
| 1677 | } | 
|---|
| 1678 |  | 
|---|
| 1679 | /* text positioning */ | 
|---|
| 1680 |  | 
|---|
| 1681 | static void pdf_run_Td(fz_context *ctx, pdf_processor *proc, float tx, float ty) | 
|---|
| 1682 | { | 
|---|
| 1683 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1684 | pdf_tos_translate(&pr->tos, tx, ty); | 
|---|
| 1685 | } | 
|---|
| 1686 |  | 
|---|
| 1687 | static void pdf_run_TD(fz_context *ctx, pdf_processor *proc, float tx, float ty) | 
|---|
| 1688 | { | 
|---|
| 1689 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1690 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 1691 | gstate->text.leading = -ty; | 
|---|
| 1692 | pdf_tos_translate(&pr->tos, tx, ty); | 
|---|
| 1693 | } | 
|---|
| 1694 |  | 
|---|
| 1695 | static void pdf_run_Tm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f) | 
|---|
| 1696 | { | 
|---|
| 1697 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1698 | pdf_tos_set_matrix(&pr->tos, a, b, c, d, e, f); | 
|---|
| 1699 | } | 
|---|
| 1700 |  | 
|---|
| 1701 | static void pdf_run_Tstar(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1702 | { | 
|---|
| 1703 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1704 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 1705 | pdf_tos_newline(&pr->tos, gstate->text.leading); | 
|---|
| 1706 | } | 
|---|
| 1707 |  | 
|---|
| 1708 | /* text showing */ | 
|---|
| 1709 |  | 
|---|
| 1710 | static void pdf_run_TJ(fz_context *ctx, pdf_processor *proc, pdf_obj *obj) | 
|---|
| 1711 | { | 
|---|
| 1712 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1713 | pdf_show_text(ctx, pr, obj); | 
|---|
| 1714 | } | 
|---|
| 1715 |  | 
|---|
| 1716 | static void pdf_run_Tj(fz_context *ctx, pdf_processor *proc, char *string, int string_len) | 
|---|
| 1717 | { | 
|---|
| 1718 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1719 | pdf_show_string(ctx, pr, (unsigned char *)string, string_len); | 
|---|
| 1720 | } | 
|---|
| 1721 |  | 
|---|
| 1722 | static void pdf_run_squote(fz_context *ctx, pdf_processor *proc, char *string, int string_len) | 
|---|
| 1723 | { | 
|---|
| 1724 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1725 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 1726 | pdf_tos_newline(&pr->tos, gstate->text.leading); | 
|---|
| 1727 | pdf_show_string(ctx, pr, (unsigned char*)string, string_len); | 
|---|
| 1728 | } | 
|---|
| 1729 |  | 
|---|
| 1730 | static void pdf_run_dquote(fz_context *ctx, pdf_processor *proc, float aw, float ac, char *string, int string_len) | 
|---|
| 1731 | { | 
|---|
| 1732 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1733 | pdf_gstate *gstate = pr->gstate + pr->gtop; | 
|---|
| 1734 | gstate->text.word_space = aw; | 
|---|
| 1735 | gstate->text.char_space = ac; | 
|---|
| 1736 | pdf_tos_newline(&pr->tos, gstate->text.leading); | 
|---|
| 1737 | pdf_show_string(ctx, pr, (unsigned char*)string, string_len); | 
|---|
| 1738 | } | 
|---|
| 1739 |  | 
|---|
| 1740 | /* type 3 fonts */ | 
|---|
| 1741 |  | 
|---|
| 1742 | static void pdf_run_d0(fz_context *ctx, pdf_processor *proc, float wx, float wy) | 
|---|
| 1743 | { | 
|---|
| 1744 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1745 | pr->dev->flags |= FZ_DEVFLAG_COLOR; | 
|---|
| 1746 | } | 
|---|
| 1747 |  | 
|---|
| 1748 | static void pdf_run_d1(fz_context *ctx, pdf_processor *proc, float wx, float wy, float llx, float lly, float urx, float ury) | 
|---|
| 1749 | { | 
|---|
| 1750 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1751 | pr->dev->flags |= FZ_DEVFLAG_MASK | FZ_DEVFLAG_BBOX_DEFINED; | 
|---|
| 1752 | pr->dev->flags &= ~(FZ_DEVFLAG_FILLCOLOR_UNDEFINED | | 
|---|
| 1753 | FZ_DEVFLAG_STROKECOLOR_UNDEFINED | | 
|---|
| 1754 | FZ_DEVFLAG_STARTCAP_UNDEFINED | | 
|---|
| 1755 | FZ_DEVFLAG_DASHCAP_UNDEFINED | | 
|---|
| 1756 | FZ_DEVFLAG_ENDCAP_UNDEFINED | | 
|---|
| 1757 | FZ_DEVFLAG_LINEJOIN_UNDEFINED | | 
|---|
| 1758 | FZ_DEVFLAG_MITERLIMIT_UNDEFINED | | 
|---|
| 1759 | FZ_DEVFLAG_LINEWIDTH_UNDEFINED); | 
|---|
| 1760 | pr->dev->d1_rect.x0 = fz_min(llx, urx); | 
|---|
| 1761 | pr->dev->d1_rect.y0 = fz_min(lly, ury); | 
|---|
| 1762 | pr->dev->d1_rect.x1 = fz_max(llx, urx); | 
|---|
| 1763 | pr->dev->d1_rect.y1 = fz_max(lly, ury); | 
|---|
| 1764 | } | 
|---|
| 1765 |  | 
|---|
| 1766 | /* color */ | 
|---|
| 1767 |  | 
|---|
| 1768 | static void pdf_run_CS(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *colorspace) | 
|---|
| 1769 | { | 
|---|
| 1770 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1771 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; | 
|---|
| 1772 | if (!strcmp(name, "Pattern")) | 
|---|
| 1773 | pdf_set_pattern(ctx, pr, PDF_STROKE, NULL, NULL); | 
|---|
| 1774 | else | 
|---|
| 1775 | pdf_set_colorspace(ctx, pr, PDF_STROKE, colorspace); | 
|---|
| 1776 | } | 
|---|
| 1777 |  | 
|---|
| 1778 | static void pdf_run_cs(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *colorspace) | 
|---|
| 1779 | { | 
|---|
| 1780 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1781 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; | 
|---|
| 1782 | if (!strcmp(name, "Pattern")) | 
|---|
| 1783 | pdf_set_pattern(ctx, pr, PDF_FILL, NULL, NULL); | 
|---|
| 1784 | else | 
|---|
| 1785 | pdf_set_colorspace(ctx, pr, PDF_FILL, colorspace); | 
|---|
| 1786 | } | 
|---|
| 1787 |  | 
|---|
| 1788 | static void pdf_run_SC_color(fz_context *ctx, pdf_processor *proc, int n, float *color) | 
|---|
| 1789 | { | 
|---|
| 1790 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1791 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; | 
|---|
| 1792 | pdf_set_color(ctx, pr, PDF_STROKE, color); | 
|---|
| 1793 | } | 
|---|
| 1794 |  | 
|---|
| 1795 | static void pdf_run_sc_color(fz_context *ctx, pdf_processor *proc, int n, float *color) | 
|---|
| 1796 | { | 
|---|
| 1797 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1798 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; | 
|---|
| 1799 | pdf_set_color(ctx, pr, PDF_FILL, color); | 
|---|
| 1800 | } | 
|---|
| 1801 |  | 
|---|
| 1802 | static void pdf_run_SC_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color) | 
|---|
| 1803 | { | 
|---|
| 1804 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1805 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; | 
|---|
| 1806 | pdf_set_pattern(ctx, pr, PDF_STROKE, pat, color); | 
|---|
| 1807 | } | 
|---|
| 1808 |  | 
|---|
| 1809 | static void pdf_run_sc_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color) | 
|---|
| 1810 | { | 
|---|
| 1811 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1812 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; | 
|---|
| 1813 | pdf_set_pattern(ctx, pr, PDF_FILL, pat, color); | 
|---|
| 1814 | } | 
|---|
| 1815 |  | 
|---|
| 1816 | static void pdf_run_SC_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade) | 
|---|
| 1817 | { | 
|---|
| 1818 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1819 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; | 
|---|
| 1820 | pdf_set_shade(ctx, pr, PDF_STROKE, shade); | 
|---|
| 1821 | } | 
|---|
| 1822 |  | 
|---|
| 1823 | static void pdf_run_sc_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade) | 
|---|
| 1824 | { | 
|---|
| 1825 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1826 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; | 
|---|
| 1827 | pdf_set_shade(ctx, pr, PDF_FILL, shade); | 
|---|
| 1828 | } | 
|---|
| 1829 |  | 
|---|
| 1830 | static void pdf_run_G(fz_context *ctx, pdf_processor *proc, float g) | 
|---|
| 1831 | { | 
|---|
| 1832 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1833 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; | 
|---|
| 1834 | pdf_set_colorspace(ctx, pr, PDF_STROKE, fz_device_gray(ctx)); | 
|---|
| 1835 | pdf_set_color(ctx, pr, PDF_STROKE, &g); | 
|---|
| 1836 | } | 
|---|
| 1837 |  | 
|---|
| 1838 | static void pdf_run_g(fz_context *ctx, pdf_processor *proc, float g) | 
|---|
| 1839 | { | 
|---|
| 1840 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1841 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; | 
|---|
| 1842 | pdf_set_colorspace(ctx, pr, PDF_FILL, fz_device_gray(ctx)); | 
|---|
| 1843 | pdf_set_color(ctx, pr, PDF_FILL, &g); | 
|---|
| 1844 | } | 
|---|
| 1845 |  | 
|---|
| 1846 | static void pdf_run_K(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k) | 
|---|
| 1847 | { | 
|---|
| 1848 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1849 | float color[4] = {c, m, y, k}; | 
|---|
| 1850 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; | 
|---|
| 1851 | pdf_set_colorspace(ctx, pr, PDF_STROKE, fz_device_cmyk(ctx)); | 
|---|
| 1852 | pdf_set_color(ctx, pr, PDF_STROKE, color); | 
|---|
| 1853 | } | 
|---|
| 1854 |  | 
|---|
| 1855 | static void pdf_run_k(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k) | 
|---|
| 1856 | { | 
|---|
| 1857 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1858 | float color[4] = {c, m, y, k}; | 
|---|
| 1859 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; | 
|---|
| 1860 | pdf_set_colorspace(ctx, pr, PDF_FILL, fz_device_cmyk(ctx)); | 
|---|
| 1861 | pdf_set_color(ctx, pr, PDF_FILL, color); | 
|---|
| 1862 | } | 
|---|
| 1863 |  | 
|---|
| 1864 | static void pdf_run_RG(fz_context *ctx, pdf_processor *proc, float r, float g, float b) | 
|---|
| 1865 | { | 
|---|
| 1866 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1867 | float color[3] = {r, g, b}; | 
|---|
| 1868 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; | 
|---|
| 1869 | pdf_set_colorspace(ctx, pr, PDF_STROKE, fz_device_rgb(ctx)); | 
|---|
| 1870 | pdf_set_color(ctx, pr, PDF_STROKE, color); | 
|---|
| 1871 | } | 
|---|
| 1872 |  | 
|---|
| 1873 | static void pdf_run_rg(fz_context *ctx, pdf_processor *proc, float r, float g, float b) | 
|---|
| 1874 | { | 
|---|
| 1875 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1876 | float color[3] = {r, g, b}; | 
|---|
| 1877 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; | 
|---|
| 1878 | pdf_set_colorspace(ctx, pr, PDF_FILL, fz_device_rgb(ctx)); | 
|---|
| 1879 | pdf_set_color(ctx, pr, PDF_FILL, color); | 
|---|
| 1880 | } | 
|---|
| 1881 |  | 
|---|
| 1882 | /* shadings, images, xobjects */ | 
|---|
| 1883 |  | 
|---|
| 1884 | static void pdf_run_BI(fz_context *ctx, pdf_processor *proc, fz_image *image, const char *colorspace) | 
|---|
| 1885 | { | 
|---|
| 1886 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1887 | pdf_show_image(ctx, pr, image); | 
|---|
| 1888 | } | 
|---|
| 1889 |  | 
|---|
| 1890 | static void pdf_run_sh(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade) | 
|---|
| 1891 | { | 
|---|
| 1892 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1893 | pdf_show_shade(ctx, pr, shade); | 
|---|
| 1894 | } | 
|---|
| 1895 |  | 
|---|
| 1896 | static void pdf_run_Do_image(fz_context *ctx, pdf_processor *proc, const char *name, fz_image *image) | 
|---|
| 1897 | { | 
|---|
| 1898 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1899 | pdf_show_image(ctx, pr, image); | 
|---|
| 1900 | } | 
|---|
| 1901 |  | 
|---|
| 1902 | static void pdf_run_Do_form(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *xobj, pdf_obj *page_resources) | 
|---|
| 1903 | { | 
|---|
| 1904 | pdf_run_xobject(ctx, (pdf_run_processor*)proc, xobj, page_resources, fz_identity, 0); | 
|---|
| 1905 | } | 
|---|
| 1906 |  | 
|---|
| 1907 | /* marked content */ | 
|---|
| 1908 |  | 
|---|
| 1909 | static void pdf_run_BMC(fz_context *ctx, pdf_processor *proc, const char *tag) | 
|---|
| 1910 | { | 
|---|
| 1911 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1912 |  | 
|---|
| 1913 | if (!tag) | 
|---|
| 1914 | tag = "Untitled"; | 
|---|
| 1915 |  | 
|---|
| 1916 | fz_begin_layer(ctx, pr->dev, tag); | 
|---|
| 1917 | } | 
|---|
| 1918 |  | 
|---|
| 1919 | static void pdf_run_BDC(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked) | 
|---|
| 1920 | { | 
|---|
| 1921 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1922 | const char *str; | 
|---|
| 1923 |  | 
|---|
| 1924 | if (!tag) | 
|---|
| 1925 | tag = "Untitled"; | 
|---|
| 1926 |  | 
|---|
| 1927 | str = pdf_dict_get_text_string(ctx, cooked, PDF_NAME(Name)); | 
|---|
| 1928 | if (strlen(str) == 0) | 
|---|
| 1929 | str = tag; | 
|---|
| 1930 |  | 
|---|
| 1931 | fz_begin_layer(ctx, pr->dev, str); | 
|---|
| 1932 | } | 
|---|
| 1933 |  | 
|---|
| 1934 | static void pdf_run_EMC(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1935 | { | 
|---|
| 1936 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1937 |  | 
|---|
| 1938 | fz_end_layer(ctx, pr->dev); | 
|---|
| 1939 | } | 
|---|
| 1940 |  | 
|---|
| 1941 | static void pdf_run_MP(fz_context *ctx, pdf_processor *proc, const char *tag) | 
|---|
| 1942 | { | 
|---|
| 1943 | pdf_run_BMC(ctx, proc, tag); | 
|---|
| 1944 | pdf_run_EMC(ctx, proc); | 
|---|
| 1945 | } | 
|---|
| 1946 |  | 
|---|
| 1947 | static void pdf_run_DP(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked) | 
|---|
| 1948 | { | 
|---|
| 1949 | pdf_run_BDC(ctx, proc, tag, raw, cooked); | 
|---|
| 1950 | pdf_run_EMC(ctx, proc); | 
|---|
| 1951 | } | 
|---|
| 1952 |  | 
|---|
| 1953 | /* compatibility */ | 
|---|
| 1954 |  | 
|---|
| 1955 | static void pdf_run_BX(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1956 | { | 
|---|
| 1957 | } | 
|---|
| 1958 |  | 
|---|
| 1959 | static void pdf_run_EX(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1960 | { | 
|---|
| 1961 | } | 
|---|
| 1962 |  | 
|---|
| 1963 | static void pdf_run_END(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1964 | { | 
|---|
| 1965 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1966 | pdf_flush_text(ctx, pr); | 
|---|
| 1967 | } | 
|---|
| 1968 |  | 
|---|
| 1969 | static void | 
|---|
| 1970 | pdf_close_run_processor(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1971 | { | 
|---|
| 1972 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1973 |  | 
|---|
| 1974 | while (pr->gtop) | 
|---|
| 1975 | pdf_grestore(ctx, pr); | 
|---|
| 1976 |  | 
|---|
| 1977 | while (pr->gstate[0].clip_depth) | 
|---|
| 1978 | { | 
|---|
| 1979 | fz_pop_clip(ctx, pr->dev); | 
|---|
| 1980 | pr->gstate[0].clip_depth--; | 
|---|
| 1981 | } | 
|---|
| 1982 | } | 
|---|
| 1983 |  | 
|---|
| 1984 | static void | 
|---|
| 1985 | pdf_drop_run_processor(fz_context *ctx, pdf_processor *proc) | 
|---|
| 1986 | { | 
|---|
| 1987 | pdf_run_processor *pr = (pdf_run_processor *)proc; | 
|---|
| 1988 |  | 
|---|
| 1989 | while (pr->gtop >= 0) | 
|---|
| 1990 | { | 
|---|
| 1991 | pdf_drop_gstate(ctx, &pr->gstate[pr->gtop]); | 
|---|
| 1992 | pr->gtop--; | 
|---|
| 1993 | } | 
|---|
| 1994 |  | 
|---|
| 1995 | fz_drop_path(ctx, pr->path); | 
|---|
| 1996 | fz_drop_text(ctx, pr->tos.text); | 
|---|
| 1997 |  | 
|---|
| 1998 | fz_drop_default_colorspaces(ctx, pr->default_cs); | 
|---|
| 1999 |  | 
|---|
| 2000 | fz_free(ctx, pr->gstate); | 
|---|
| 2001 | } | 
|---|
| 2002 |  | 
|---|
| 2003 | /* | 
|---|
| 2004 | Create a new "run" processor. This maps | 
|---|
| 2005 | from PDF operators to fz_device level calls. | 
|---|
| 2006 |  | 
|---|
| 2007 | dev: The device to which the resulting device calls are to be | 
|---|
| 2008 | sent. | 
|---|
| 2009 |  | 
|---|
| 2010 | ctm: The initial transformation matrix to use. | 
|---|
| 2011 |  | 
|---|
| 2012 | usage: A NULL terminated string that describes the 'usage' of | 
|---|
| 2013 | this interpretation. Typically 'View', though 'Print' is also | 
|---|
| 2014 | defined within the PDF reference manual, and others are possible. | 
|---|
| 2015 |  | 
|---|
| 2016 | gstate: The initial graphics state. | 
|---|
| 2017 | */ | 
|---|
| 2018 | pdf_processor * | 
|---|
| 2019 | pdf_new_run_processor(fz_context *ctx, fz_device *dev, fz_matrix ctm, const char *usage, pdf_gstate *gstate, fz_default_colorspaces *default_cs, fz_cookie *cookie) | 
|---|
| 2020 | { | 
|---|
| 2021 | pdf_run_processor *proc = pdf_new_processor(ctx, sizeof *proc); | 
|---|
| 2022 | { | 
|---|
| 2023 | proc->super.usage = usage; | 
|---|
| 2024 |  | 
|---|
| 2025 | proc->super.close_processor = pdf_close_run_processor; | 
|---|
| 2026 | proc->super.drop_processor = pdf_drop_run_processor; | 
|---|
| 2027 |  | 
|---|
| 2028 | /* general graphics state */ | 
|---|
| 2029 | proc->super.op_w = pdf_run_w; | 
|---|
| 2030 | proc->super.op_j = pdf_run_j; | 
|---|
| 2031 | proc->super.op_J = pdf_run_J; | 
|---|
| 2032 | proc->super.op_M = pdf_run_M; | 
|---|
| 2033 | proc->super.op_d = pdf_run_d; | 
|---|
| 2034 | proc->super.op_ri = pdf_run_ri; | 
|---|
| 2035 | proc->super.op_i = pdf_run_i; | 
|---|
| 2036 | proc->super.op_gs_begin = pdf_run_gs_begin; | 
|---|
| 2037 | proc->super.op_gs_end = pdf_run_gs_end; | 
|---|
| 2038 |  | 
|---|
| 2039 | /* transparency graphics state */ | 
|---|
| 2040 | proc->super.op_gs_BM = pdf_run_gs_BM; | 
|---|
| 2041 | proc->super.op_gs_CA = pdf_run_gs_CA; | 
|---|
| 2042 | proc->super.op_gs_ca = pdf_run_gs_ca; | 
|---|
| 2043 | proc->super.op_gs_SMask = pdf_run_gs_SMask; | 
|---|
| 2044 |  | 
|---|
| 2045 | /* special graphics state */ | 
|---|
| 2046 | proc->super.op_q = pdf_run_q; | 
|---|
| 2047 | proc->super.op_Q = pdf_run_Q; | 
|---|
| 2048 | proc->super.op_cm = pdf_run_cm; | 
|---|
| 2049 |  | 
|---|
| 2050 | /* path construction */ | 
|---|
| 2051 | proc->super.op_m = pdf_run_m; | 
|---|
| 2052 | proc->super.op_l = pdf_run_l; | 
|---|
| 2053 | proc->super.op_c = pdf_run_c; | 
|---|
| 2054 | proc->super.op_v = pdf_run_v; | 
|---|
| 2055 | proc->super.op_y = pdf_run_y; | 
|---|
| 2056 | proc->super.op_h = pdf_run_h; | 
|---|
| 2057 | proc->super.op_re = pdf_run_re; | 
|---|
| 2058 |  | 
|---|
| 2059 | /* path painting */ | 
|---|
| 2060 | proc->super.op_S = pdf_run_S; | 
|---|
| 2061 | proc->super.op_s = pdf_run_s; | 
|---|
| 2062 | proc->super.op_F = pdf_run_F; | 
|---|
| 2063 | proc->super.op_f = pdf_run_f; | 
|---|
| 2064 | proc->super.op_fstar = pdf_run_fstar; | 
|---|
| 2065 | proc->super.op_B = pdf_run_B; | 
|---|
| 2066 | proc->super.op_Bstar = pdf_run_Bstar; | 
|---|
| 2067 | proc->super.op_b = pdf_run_b; | 
|---|
| 2068 | proc->super.op_bstar = pdf_run_bstar; | 
|---|
| 2069 | proc->super.op_n = pdf_run_n; | 
|---|
| 2070 |  | 
|---|
| 2071 | /* clipping paths */ | 
|---|
| 2072 | proc->super.op_W = pdf_run_W; | 
|---|
| 2073 | proc->super.op_Wstar = pdf_run_Wstar; | 
|---|
| 2074 |  | 
|---|
| 2075 | /* text objects */ | 
|---|
| 2076 | proc->super.op_BT = pdf_run_BT; | 
|---|
| 2077 | proc->super.op_ET = pdf_run_ET; | 
|---|
| 2078 |  | 
|---|
| 2079 | /* text state */ | 
|---|
| 2080 | proc->super.op_Tc = pdf_run_Tc; | 
|---|
| 2081 | proc->super.op_Tw = pdf_run_Tw; | 
|---|
| 2082 | proc->super.op_Tz = pdf_run_Tz; | 
|---|
| 2083 | proc->super.op_TL = pdf_run_TL; | 
|---|
| 2084 | proc->super.op_Tf = pdf_run_Tf; | 
|---|
| 2085 | proc->super.op_Tr = pdf_run_Tr; | 
|---|
| 2086 | proc->super.op_Ts = pdf_run_Ts; | 
|---|
| 2087 |  | 
|---|
| 2088 | /* text positioning */ | 
|---|
| 2089 | proc->super.op_Td = pdf_run_Td; | 
|---|
| 2090 | proc->super.op_TD = pdf_run_TD; | 
|---|
| 2091 | proc->super.op_Tm = pdf_run_Tm; | 
|---|
| 2092 | proc->super.op_Tstar = pdf_run_Tstar; | 
|---|
| 2093 |  | 
|---|
| 2094 | /* text showing */ | 
|---|
| 2095 | proc->super.op_TJ = pdf_run_TJ; | 
|---|
| 2096 | proc->super.op_Tj = pdf_run_Tj; | 
|---|
| 2097 | proc->super.op_squote = pdf_run_squote; | 
|---|
| 2098 | proc->super.op_dquote = pdf_run_dquote; | 
|---|
| 2099 |  | 
|---|
| 2100 | /* type 3 fonts */ | 
|---|
| 2101 | proc->super.op_d0 = pdf_run_d0; | 
|---|
| 2102 | proc->super.op_d1 = pdf_run_d1; | 
|---|
| 2103 |  | 
|---|
| 2104 | /* color */ | 
|---|
| 2105 | proc->super.op_CS = pdf_run_CS; | 
|---|
| 2106 | proc->super.op_cs = pdf_run_cs; | 
|---|
| 2107 | proc->super.op_SC_color = pdf_run_SC_color; | 
|---|
| 2108 | proc->super.op_sc_color = pdf_run_sc_color; | 
|---|
| 2109 | proc->super.op_SC_pattern = pdf_run_SC_pattern; | 
|---|
| 2110 | proc->super.op_sc_pattern = pdf_run_sc_pattern; | 
|---|
| 2111 | proc->super.op_SC_shade = pdf_run_SC_shade; | 
|---|
| 2112 | proc->super.op_sc_shade = pdf_run_sc_shade; | 
|---|
| 2113 |  | 
|---|
| 2114 | proc->super.op_G = pdf_run_G; | 
|---|
| 2115 | proc->super.op_g = pdf_run_g; | 
|---|
| 2116 | proc->super.op_RG = pdf_run_RG; | 
|---|
| 2117 | proc->super.op_rg = pdf_run_rg; | 
|---|
| 2118 | proc->super.op_K = pdf_run_K; | 
|---|
| 2119 | proc->super.op_k = pdf_run_k; | 
|---|
| 2120 |  | 
|---|
| 2121 | /* shadings, images, xobjects */ | 
|---|
| 2122 | proc->super.op_sh = pdf_run_sh; | 
|---|
| 2123 | if (dev->fill_image || dev->fill_image_mask || dev->clip_image_mask) | 
|---|
| 2124 | { | 
|---|
| 2125 | proc->super.op_BI = pdf_run_BI; | 
|---|
| 2126 | proc->super.op_Do_image = pdf_run_Do_image; | 
|---|
| 2127 | } | 
|---|
| 2128 | proc->super.op_Do_form = pdf_run_Do_form; | 
|---|
| 2129 |  | 
|---|
| 2130 | /* marked content */ | 
|---|
| 2131 | proc->super.op_MP = pdf_run_MP; | 
|---|
| 2132 | proc->super.op_DP = pdf_run_DP; | 
|---|
| 2133 | proc->super.op_BMC = pdf_run_BMC; | 
|---|
| 2134 | proc->super.op_BDC = pdf_run_BDC; | 
|---|
| 2135 | proc->super.op_EMC = pdf_run_EMC; | 
|---|
| 2136 |  | 
|---|
| 2137 | /* compatibility */ | 
|---|
| 2138 | proc->super.op_BX = pdf_run_BX; | 
|---|
| 2139 | proc->super.op_EX = pdf_run_EX; | 
|---|
| 2140 |  | 
|---|
| 2141 | /* extgstate */ | 
|---|
| 2142 | proc->super.op_gs_OP = pdf_run_gs_OP; | 
|---|
| 2143 | proc->super.op_gs_op = pdf_run_gs_op; | 
|---|
| 2144 | proc->super.op_gs_OPM = pdf_run_gs_OPM; | 
|---|
| 2145 | proc->super.op_gs_UseBlackPtComp = pdf_run_gs_UseBlackPtComp; | 
|---|
| 2146 |  | 
|---|
| 2147 | proc->super.op_END = pdf_run_END; | 
|---|
| 2148 | } | 
|---|
| 2149 |  | 
|---|
| 2150 | proc->dev = dev; | 
|---|
| 2151 | proc->cookie = cookie; | 
|---|
| 2152 |  | 
|---|
| 2153 | proc->default_cs = fz_keep_default_colorspaces(ctx, default_cs); | 
|---|
| 2154 |  | 
|---|
| 2155 | proc->path = NULL; | 
|---|
| 2156 | proc->clip = 0; | 
|---|
| 2157 | proc->clip_even_odd = 0; | 
|---|
| 2158 |  | 
|---|
| 2159 | proc->tos.text = NULL; | 
|---|
| 2160 | proc->tos.tlm = fz_identity; | 
|---|
| 2161 | proc->tos.tm = fz_identity; | 
|---|
| 2162 | proc->tos.text_mode = 0; | 
|---|
| 2163 |  | 
|---|
| 2164 | proc->gtop = -1; | 
|---|
| 2165 |  | 
|---|
| 2166 | fz_try(ctx) | 
|---|
| 2167 | { | 
|---|
| 2168 | proc->path = fz_new_path(ctx); | 
|---|
| 2169 |  | 
|---|
| 2170 | proc->gcap = 64; | 
|---|
| 2171 | proc->gstate = fz_calloc(ctx, proc->gcap, sizeof(pdf_gstate)); | 
|---|
| 2172 |  | 
|---|
| 2173 | proc->gtop = 0; | 
|---|
| 2174 | pdf_init_gstate(ctx, &proc->gstate[0], ctm); | 
|---|
| 2175 |  | 
|---|
| 2176 | if (gstate) | 
|---|
| 2177 | { | 
|---|
| 2178 | pdf_copy_gstate(ctx, &proc->gstate[0], gstate); | 
|---|
| 2179 | proc->gstate[0].clip_depth = 0; | 
|---|
| 2180 | proc->gstate[0].ctm = ctm; | 
|---|
| 2181 | } | 
|---|
| 2182 | } | 
|---|
| 2183 | fz_catch(ctx) | 
|---|
| 2184 | { | 
|---|
| 2185 | pdf_drop_run_processor(ctx, (pdf_processor *) proc); | 
|---|
| 2186 | fz_free(ctx, proc); | 
|---|
| 2187 | fz_rethrow(ctx); | 
|---|
| 2188 | } | 
|---|
| 2189 |  | 
|---|
| 2190 | /* We need to save an extra level to allow for level 0 to be the parent gstate level. */ | 
|---|
| 2191 | pdf_gsave(ctx, proc); | 
|---|
| 2192 |  | 
|---|
| 2193 | return (pdf_processor*)proc; | 
|---|
| 2194 | } | 
|---|
| 2195 |  | 
|---|