static void push_clip_stack_accumulate(fz_device *dev, const fz_rect *rect, int accumulate) { if (accumulate <= 1) { dev->scissor_accumulator = *rect; if (dev->container_len == dev->container_cap) { int newmax = dev->container_cap * 2; if (newmax == 0) newmax = 4; dev->container = fz_resize_array(dev->ctx, dev->container, newmax, sizeof(*dev->container)); dev->container_cap = newmax; } if (dev->container_len > 0) dev->container[dev->container_len].scissor = dev->container[dev->container_len-1].scissor; else dev->container[dev->container_len].scissor = fz_infinite_rect; fz_intersect_rect(&dev->container[dev->container_len].scissor, rect); dev->container[dev->container_len].flags = fz_device_container_stack_is_clip_text; dev->container[dev->container_len].user = 0; dev->container_len++; } else { if (dev->container_len <= 0) return; fz_union_rect(&dev->scissor_accumulator, rect); fz_intersect_rect(&dev->container[dev->container_len-1].scissor, &dev->scissor_accumulator); } }
static void fz_list_clip_image_mask(fz_device *dev, fz_image *image, fz_rect *rect, fz_matrix ctm) { fz_display_node *node; node = fz_new_display_node(dev->ctx, FZ_CMD_CLIP_IMAGE_MASK, ctm, NULL, NULL, 0); node->rect = fz_transform_rect(ctm, fz_unit_rect); if (rect) node->rect = fz_intersect_rect(node->rect, *rect); node->item.image = fz_keep_image(dev->ctx, image); fz_append_display_node(dev->user, node); }
static void fz_list_clip_image_mask(void *user, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) { fz_display_node *node; node = fz_new_display_node(FZ_CMD_CLIP_IMAGE_MASK, ctm, NULL, NULL, 0); node->rect = fz_transform_rect(ctm, fz_unit_rect); if (rect != NULL) node->rect = fz_intersect_rect(node->rect, *rect); node->item.image = fz_keep_pixmap(image); fz_append_display_node(user, node); }
static void fz_list_clip_path(void *user, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) { fz_display_node *node; node = fz_new_display_node(FZ_CMD_CLIP_PATH, ctm, NULL, NULL, 0); node->rect = fz_bound_path(path, NULL, ctm); if (rect != NULL) node->rect = fz_intersect_rect(node->rect, *rect); node->item.path = fz_clone_path(path); node->flag = even_odd; fz_append_display_node(user, node); }
static void fz_list_clip_stroke_path(void *user, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm) { fz_display_node *node; node = fz_new_display_node(FZ_CMD_CLIP_STROKE_PATH, ctm, NULL, NULL, 0); node->rect = fz_bound_path(path, stroke, ctm); if (rect != NULL) node->rect = fz_intersect_rect(node->rect, *rect); node->item.path = fz_clone_path(path); node->stroke = fz_clone_stroke_state(stroke); fz_append_display_node(user, node); }
static void fz_bbox_add_rect(fz_device *dev, fz_rect rect, int clip) { fz_bbox_data *data = dev->user; if (0 < data->top && data->top <= STACK_SIZE) rect = fz_intersect_rect(rect, data->stack[data->top-1]); if (!clip && data->top <= STACK_SIZE && !data->ignore) *data->result = fz_union_bbox(*data->result, fz_bbox_covering_rect(rect)); if (clip && ++data->top <= STACK_SIZE) data->stack[data->top-1] = rect; }
static void fz_bbox_add_rect(fz_device *dev, const fz_rect *rect, int clip) { fz_bbox_data *data = dev->user; fz_rect r = *rect; if (0 < data->top && data->top <= STACK_SIZE) fz_intersect_rect(&r, &data->stack[data->top-1]); if (!clip && data->top <= STACK_SIZE && !data->ignore) fz_union_rect(data->result, &r); if (clip && ++data->top <= STACK_SIZE) data->stack[data->top-1] = r; }
fz_rect * fz_bound_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_rect *s) { fz_matrix local_ctm; fz_rect rect; fz_concat(&local_ctm, &shade->matrix, ctm); *s = shade->bbox; if (shade->type != FZ_LINEAR && shade->type != FZ_RADIAL) { fz_bound_mesh(ctx, shade, &rect); fz_intersect_rect(s, &rect); } return fz_transform_rect(s, &local_ctm); }
static float calc_bbox_overlap(const fz_rect *bbox1, const fz_rect *bbox2) { float area1, area2, area3; fz_rect intersect = *bbox1; fz_intersect_rect(&intersect, bbox2); if (fz_is_empty_rect(&intersect)) return 0; area1 = (bbox1->x1 - bbox1->x0) * (bbox1->y1 - bbox1->y0); area2 = (bbox2->x1 - bbox2->x0) * (bbox2->y1 - bbox2->y0); area3 = (intersect.x1 - intersect.x0) * (intersect.y1 - intersect.y0); return area3 / fz_max(area1, area2); }
static void svg_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha) { svg_device *sdev = (svg_device*)dev; fz_output *out = sdev->out; fz_rect rect; fz_irect bbox; fz_pixmap *pix; fz_buffer *buf = NULL; fz_var(buf); if (dev->container_len == 0) return; fz_round_rect(&bbox, fz_intersect_rect(fz_bound_shade(ctx, shade, ctm, &rect), &dev->container[dev->container_len-1].scissor)); if (fz_is_empty_irect(&bbox)) return; pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox); fz_clear_pixmap(ctx, pix); fz_try(ctx) { fz_paint_shade(ctx, shade, ctm, pix, &bbox); buf = fz_new_buffer_from_pixmap_as_png(ctx, pix); if (alpha != 1.0f) fz_printf(ctx, out, "<g opacity=\"%g\">", alpha); fz_printf(ctx, out, "<image x=\"%dpx\" y=\"%dpx\" width=\"%dpx\" height=\"%dpx\" xlink:href=\"data:image/png;base64,", pix->x, pix->y, pix->w, pix->h); send_data_base64(ctx, out, buf); fz_printf(ctx, out, "\"/>\n"); if (alpha != 1.0f) fz_printf(ctx, out, "</g>"); } fz_always(ctx) { fz_drop_buffer(ctx, buf); fz_drop_pixmap(ctx, pix); } fz_catch(ctx) { fz_rethrow(ctx); } }
static void fz_bbox_add_rect(fz_context *ctx, fz_device *dev, const fz_rect *rect, int clip) { fz_bbox_device *bdev = (fz_bbox_device*)dev; fz_rect r = *rect; if (0 < bdev->top && bdev->top <= STACK_SIZE) { fz_intersect_rect(&r, &bdev->stack[bdev->top-1]); } if (!clip && bdev->top <= STACK_SIZE && !bdev->ignore) { fz_union_rect(bdev->result, &r); } if (clip && ++bdev->top <= STACK_SIZE) { bdev->stack[bdev->top-1] = r; } }
static void fz_list_clip_stroke_path(fz_device *dev, fz_path *path, const fz_rect *rect, fz_stroke_state *stroke, const fz_matrix *ctm) { fz_display_node *node; fz_context *ctx = dev->ctx; node = fz_new_display_node(ctx, FZ_CMD_CLIP_STROKE_PATH, ctm, NULL, NULL, 0); fz_try(ctx) { fz_bound_path(dev->ctx, path, stroke, ctm, &node->rect); if (rect) fz_intersect_rect(&node->rect, rect); node->item.path = fz_clone_path(dev->ctx, path); node->stroke = fz_keep_stroke_state(dev->ctx, stroke); } fz_catch(ctx) { fz_free_display_node(ctx, node); fz_rethrow(ctx); } fz_append_display_node(dev->user, node); }
static void fz_list_clip_path(fz_device *dev, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) { fz_display_node *node; fz_context *ctx = dev->ctx; node = fz_new_display_node(ctx, FZ_CMD_CLIP_PATH, ctm, NULL, NULL, 0); fz_try(ctx) { node->rect = fz_bound_path(dev->ctx, path, NULL, ctm); if (rect) node->rect = fz_intersect_rect(node->rect, *rect); node->item.path = fz_clone_path(dev->ctx, path); node->flag = even_odd; } fz_catch(ctx) { fz_free_display_node(ctx, node); fz_rethrow(ctx); } fz_append_display_node(dev->user, node); }
fz_rect * fz_bound_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_rect *s) { fz_matrix local_ctm; struct bound_mesh_data bmd; fz_concat(&local_ctm, &shade->matrix, ctm); *s = shade->bbox; fz_transform_rect(s, &local_ctm); if (shade->type == FZ_LINEAR) return s; if (shade->type == FZ_RADIAL) return s; bmd.rect = fz_empty_rect; bmd.first = 1; fz_process_mesh(ctx, shade, &local_ctm, &bound_tri, &bmd); fz_intersect_rect(s, &bmd.rect); return s; }
static void push_clip_stack(fz_device *dev, const fz_rect *rect, int flags) { if (dev->container_len == dev->container_cap) { int newmax = dev->container_cap * 2; if (newmax == 0) newmax = 4; dev->container = fz_resize_array(dev->ctx, dev->container, newmax, sizeof(*dev->container)); dev->container_cap = newmax; } if (dev->container_len == 0) dev->container[0].scissor = *rect; else { dev->container[dev->container_len].scissor = dev->container[dev->container_len-1].scissor; fz_intersect_rect(&dev->container[dev->container_len].scissor, rect); } dev->container[dev->container_len].flags = flags; dev->container[dev->container_len].user = 0; dev->container_len++; }
pdf_page * pdf_load_page_by_obj(pdf_document *doc, int number, pdf_obj *pageref) { fz_context *ctx = doc->ctx; pdf_page *page; pdf_annot *annot; pdf_obj *pageobj, *obj; fz_rect mediabox, cropbox, realbox; float userunit; fz_matrix mat; /* SumatraPDF: allow replacing potentially slow pdf_lookup_page_obj */ pageobj = pdf_resolve_indirect(pageref); page = fz_malloc_struct(ctx, pdf_page); page->resources = NULL; page->contents = NULL; page->transparency = 0; page->links = NULL; page->annots = NULL; page->annot_tailp = &page->annots; page->deleted_annots = NULL; page->tmp_annots = NULL; page->me = pdf_keep_obj(pageobj); page->incomplete = 0; obj = pdf_dict_gets(pageobj, "UserUnit"); if (pdf_is_real(obj)) userunit = pdf_to_real(obj); else userunit = 1; pdf_to_rect(ctx, pdf_lookup_inherited_page_item(doc, pageobj, "MediaBox"), &mediabox); if (fz_is_empty_rect(&mediabox)) { fz_warn(ctx, "cannot find page size for page %d", number + 1); mediabox.x0 = 0; mediabox.y0 = 0; mediabox.x1 = 612; mediabox.y1 = 792; } pdf_to_rect(ctx, pdf_lookup_inherited_page_item(doc, pageobj, "CropBox"), &cropbox); if (!fz_is_empty_rect(&cropbox)) fz_intersect_rect(&mediabox, &cropbox); page->mediabox.x0 = fz_min(mediabox.x0, mediabox.x1) * userunit; page->mediabox.y0 = fz_min(mediabox.y0, mediabox.y1) * userunit; page->mediabox.x1 = fz_max(mediabox.x0, mediabox.x1) * userunit; page->mediabox.y1 = fz_max(mediabox.y0, mediabox.y1) * userunit; if (page->mediabox.x1 - page->mediabox.x0 < 1 || page->mediabox.y1 - page->mediabox.y0 < 1) { fz_warn(ctx, "invalid page size in page %d", number + 1); page->mediabox = fz_unit_rect; } page->rotate = pdf_to_int(pdf_lookup_inherited_page_item(doc, pageobj, "Rotate")); /* Snap page->rotate to 0, 90, 180 or 270 */ if (page->rotate < 0) page->rotate = 360 - ((-page->rotate) % 360); if (page->rotate >= 360) page->rotate = page->rotate % 360; page->rotate = 90*((page->rotate + 45)/90); if (page->rotate > 360) page->rotate = 0; fz_pre_rotate(fz_scale(&page->ctm, 1, -1), -page->rotate); realbox = page->mediabox; fz_transform_rect(&realbox, &page->ctm); fz_pre_scale(fz_translate(&mat, -realbox.x0, -realbox.y0), userunit, userunit); fz_concat(&page->ctm, &page->ctm, &mat); fz_try(ctx) { obj = pdf_dict_gets(pageobj, "Annots"); if (obj) { page->links = pdf_load_link_annots(doc, obj, &page->ctm); pdf_load_annots(doc, page, obj); } } fz_catch(ctx) { if (fz_caught(ctx) != FZ_ERROR_TRYLATER) /* SumatraPDF: ignore annotations in case of unexpected errors */ fz_warn(ctx, "unexpectedly failed to load page annotations"); page->incomplete |= PDF_PAGE_INCOMPLETE_ANNOTS; } page->duration = pdf_to_real(pdf_dict_gets(pageobj, "Dur")); obj = pdf_dict_gets(pageobj, "Trans"); page->transition_present = (obj != NULL); if (obj) { pdf_load_transition(doc, page, obj); } // TODO: inherit page->resources = pdf_lookup_inherited_page_item(doc, pageobj, "Resources"); if (page->resources) pdf_keep_obj(page->resources); obj = pdf_dict_gets(pageobj, "Contents"); fz_try(ctx) { page->contents = pdf_keep_obj(obj); if (pdf_resources_use_blending(doc, page->resources)) page->transparency = 1; /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=2107 */ else if (!strcmp(pdf_to_name(pdf_dict_getp(pageobj, "Group/S")), "Transparency")) page->transparency = 1; for (annot = page->annots; annot && !page->transparency; annot = annot->next) if (annot->ap && pdf_resources_use_blending(doc, annot->ap->resources)) page->transparency = 1; } fz_catch(ctx) { if (fz_caught(ctx) != FZ_ERROR_TRYLATER) { pdf_free_page(doc, page); fz_rethrow_message(ctx, "cannot load page %d contents (%d 0 R)", number + 1, pdf_to_num(pageref)); } page->incomplete |= PDF_PAGE_INCOMPLETE_CONTENTS; } return page; }
static void fz_append_display_node(fz_display_list *list, fz_display_node *node) { switch (node->cmd) { case FZ_CMD_CLIP_PATH: case FZ_CMD_CLIP_STROKE_PATH: case FZ_CMD_CLIP_IMAGE_MASK: list->stack[list->top].update = &node->rect; list->stack[list->top].rect = fz_empty_rect; list->top++; break; case FZ_CMD_CLIP_TEXT: case FZ_CMD_CLIP_STROKE_TEXT: list->stack[list->top].update = NULL; list->stack[list->top].rect = fz_empty_rect; list->top++; break; case FZ_CMD_BEGIN_TILE: list->tiled++; if (list->top > 0) { list->stack[list->top-1].rect = fz_infinite_rect; } break; case FZ_CMD_END_TILE: list->tiled--; break; case FZ_CMD_END_GROUP: break; case FZ_CMD_POP_CLIP: if (list->top > 0) { fz_rect *update; list->top--; update = list->stack[list->top].update; if (list->tiled == 0) { if (update != NULL) { *update = fz_intersect_rect(*update, list->stack[list->top].rect); node->rect = *update; } else { node->rect = list->stack[list->top].rect; } } else { node->rect = fz_infinite_rect; } } /*@fallthrough@*/ default: if ((list->top > 0) && (list->tiled == 0)) { list->stack[list->top-1].rect = fz_union_rect(list->stack[list->top-1].rect, node->rect); } break; } if (!list->first) { list->first = node; list->last = node; } else { list->last->next = node; list->last = node; } }
static void fz_append_display_node(fz_display_list *list, fz_display_node *node) { switch (node->cmd) { case FZ_CMD_CLIP_PATH: case FZ_CMD_CLIP_STROKE_PATH: case FZ_CMD_CLIP_IMAGE_MASK: if (list->top < STACK_SIZE) { list->stack[list->top].update = &node->rect; list->stack[list->top].rect = fz_empty_rect; } list->top++; break; case FZ_CMD_CLIP_TEXT: /* don't reset the clip rect for accumulated text */ if (node->flag == 2) break; /* fallthrough */ case FZ_CMD_END_MASK: case FZ_CMD_CLIP_STROKE_TEXT: if (list->top < STACK_SIZE) { list->stack[list->top].update = NULL; list->stack[list->top].rect = fz_empty_rect; } list->top++; break; case FZ_CMD_BEGIN_TILE: list->tiled++; if (list->top > 0 && list->top <= STACK_SIZE) { list->stack[list->top-1].rect = fz_infinite_rect; } break; case FZ_CMD_END_TILE: list->tiled--; break; case FZ_CMD_END_GROUP: break; case FZ_CMD_POP_CLIP: if (list->top > STACK_SIZE) { list->top--; node->rect = fz_infinite_rect; } else if (list->top > 0) { fz_rect *update; list->top--; update = list->stack[list->top].update; if (list->tiled == 0) { if (update) { fz_intersect_rect(update, &list->stack[list->top].rect); node->rect = *update; } else node->rect = list->stack[list->top].rect; } else node->rect = fz_infinite_rect; } /* fallthrough */ default: if (list->top > 0 && list->tiled == 0 && list->top <= STACK_SIZE) fz_union_rect(&list->stack[list->top-1].rect, &node->rect); break; } if (!list->first) { list->first = node; list->last = node; } else { list->last->next = node; list->last = node; } list->len++; }
static int _pdf_doc_load(struct _pdf_doc *self, mume_stream_t *stm) { fz_error error; fz_stream *fzstm; fz_rect *mbox; fz_obj *page_obj, *box_obj; int i, c; _pdf_doc_clear(self); fzstm = fz_new_stream(stm, _pdf_stream_read, _pdf_stream_close); mume_stream_reference(stm); fzstm->seek = _pdf_stream_seek; error = pdf_open_xref_with_stream(&self->xref, fzstm, NULL); fz_close(fzstm); if (error) { mume_error(("Read xref failed\n", error)); return 0; } assert(!pdf_needs_password(self->xref)); /* Load meta information. */ error = pdf_load_page_tree(self->xref); if (error) { mume_error(("Cannot load page tree\n")); return 0; } c = pdf_count_pages(self->xref); self->glyph_cache = fz_new_glyph_cache(); self->pages = calloc_abort(c, sizeof(pdf_page*)); self->disps = calloc_abort(c, sizeof(fz_display_list*)); self->media_boxes = malloc_abort(c * sizeof(fz_rect)); self->page_rotates = malloc_abort(c * sizeof(int)); /* Extract each pages' media box and rotation. */ for (i = 0; i < c; ++i) { mbox = self->media_boxes + i; page_obj = self->xref->page_objs[i]; if (!page_obj) { *mbox = fz_empty_rect; continue; } box_obj = fz_dict_gets(page_obj, "MediaBox"); *mbox = pdf_to_rect(box_obj); if (fz_is_empty_rect(*mbox)) { fz_warn("Cannot find page bounds, guessing page bounds."); mbox->x1 = 612; mbox->y1 = 792; } box_obj = fz_dict_gets(page_obj, "CropBox"); if (fz_is_array(box_obj)) *mbox = fz_intersect_rect(*mbox, pdf_to_rect(box_obj)); self->page_rotates[i] = fz_to_int( fz_dict_gets(page_obj, "Rotate")); if (self->page_rotates[i] % 90) self->page_rotates[i] = 0; } return 1; }
void fz_run_display_list(fz_display_list *list, fz_device *dev, const fz_matrix *top_ctm, const fz_rect *scissor, fz_cookie *cookie) { fz_display_node *node; fz_matrix ctm; int clipped = 0; int tiled = 0; int progress = 0; fz_context *ctx = dev->ctx; if (!scissor) scissor = &fz_infinite_rect; if (cookie) { cookie->progress_max = list->len; cookie->progress = 0; } for (node = list->first; node; node = node->next) { int empty; fz_rect node_rect = node->rect; fz_transform_rect(&node_rect, top_ctm); /* Check the cookie for aborting */ if (cookie) { if (cookie->abort) break; cookie->progress = progress++; } /* cull objects to draw using a quick visibility test */ if (tiled || node->cmd == FZ_CMD_BEGIN_TILE || node->cmd == FZ_CMD_END_TILE || node->cmd == FZ_CMD_BEGIN_PAGE || node->cmd == FZ_CMD_END_PAGE) { empty = 0; } else { fz_rect rect = node_rect; fz_intersect_rect(&rect, scissor); empty = fz_is_empty_rect(&rect); } if (clipped || empty) { switch (node->cmd) { case FZ_CMD_CLIP_PATH: case FZ_CMD_CLIP_STROKE_PATH: case FZ_CMD_CLIP_STROKE_TEXT: case FZ_CMD_CLIP_IMAGE_MASK: case FZ_CMD_BEGIN_MASK: case FZ_CMD_BEGIN_GROUP: clipped++; continue; case FZ_CMD_CLIP_TEXT: /* Accumulated text has no extra pops */ if (node->flag != 2) clipped++; continue; case FZ_CMD_POP_CLIP: case FZ_CMD_END_GROUP: if (!clipped) goto visible; clipped--; continue; case FZ_CMD_END_MASK: if (!clipped) goto visible; continue; default: continue; } } visible: fz_concat(&ctm, &node->ctm, top_ctm); fz_try(ctx) { switch (node->cmd) { case FZ_CMD_BEGIN_PAGE: fz_begin_page(dev, &node_rect, &ctm); break; case FZ_CMD_END_PAGE: fz_end_page(dev); break; case FZ_CMD_FILL_PATH: fz_fill_path(dev, node->item.path, node->flag, &ctm, node->colorspace, node->color, node->alpha); break; case FZ_CMD_STROKE_PATH: fz_stroke_path(dev, node->item.path, node->stroke, &ctm, node->colorspace, node->color, node->alpha); break; case FZ_CMD_CLIP_PATH: fz_clip_path(dev, node->item.path, &node_rect, node->flag, &ctm); break; case FZ_CMD_CLIP_STROKE_PATH: fz_clip_stroke_path(dev, node->item.path, &node_rect, node->stroke, &ctm); break; case FZ_CMD_FILL_TEXT: fz_fill_text(dev, node->item.text, &ctm, node->colorspace, node->color, node->alpha); break; case FZ_CMD_STROKE_TEXT: fz_stroke_text(dev, node->item.text, node->stroke, &ctm, node->colorspace, node->color, node->alpha); break; case FZ_CMD_CLIP_TEXT: fz_clip_text(dev, node->item.text, &ctm, node->flag); break; case FZ_CMD_CLIP_STROKE_TEXT: fz_clip_stroke_text(dev, node->item.text, node->stroke, &ctm); break; case FZ_CMD_IGNORE_TEXT: fz_ignore_text(dev, node->item.text, &ctm); break; case FZ_CMD_FILL_SHADE: if ((dev->hints & FZ_IGNORE_SHADE) == 0) fz_fill_shade(dev, node->item.shade, &ctm, node->alpha); break; case FZ_CMD_FILL_IMAGE: if ((dev->hints & FZ_IGNORE_IMAGE) == 0) fz_fill_image(dev, node->item.image, &ctm, node->alpha); break; case FZ_CMD_FILL_IMAGE_MASK: if ((dev->hints & FZ_IGNORE_IMAGE) == 0) fz_fill_image_mask(dev, node->item.image, &ctm, node->colorspace, node->color, node->alpha); break; case FZ_CMD_CLIP_IMAGE_MASK: if ((dev->hints & FZ_IGNORE_IMAGE) == 0) fz_clip_image_mask(dev, node->item.image, &node_rect, &ctm); break; case FZ_CMD_POP_CLIP: fz_pop_clip(dev); break; case FZ_CMD_BEGIN_MASK: fz_begin_mask(dev, &node_rect, node->flag, node->colorspace, node->color); break; case FZ_CMD_END_MASK: fz_end_mask(dev); break; case FZ_CMD_BEGIN_GROUP: fz_begin_group(dev, &node_rect, (node->flag & ISOLATED) != 0, (node->flag & KNOCKOUT) != 0, node->item.blendmode, node->alpha); break; case FZ_CMD_END_GROUP: fz_end_group(dev); break; case FZ_CMD_BEGIN_TILE: { int cached; fz_rect tile_rect; tiled++; tile_rect.x0 = node->color[2]; tile_rect.y0 = node->color[3]; tile_rect.x1 = node->color[4]; tile_rect.y1 = node->color[5]; cached = fz_begin_tile_id(dev, &node->rect, &tile_rect, node->color[0], node->color[1], &ctm, node->flag); if (cached) node = skip_to_end_tile(node, &progress); break; } case FZ_CMD_END_TILE: tiled--; fz_end_tile(dev); break; /* SumatraPDF: support transfer functions */ case FZ_CMD_APPLY_TRANSFER_FUNCTION: fz_apply_transfer_function(dev, node->item.tr, node->flag); break; } } fz_catch(ctx) { /* Swallow the error */ if (cookie) cookie->errors++; fz_warn(ctx, "Ignoring error during interpretation"); } } }