fz_bbox fz_union_bbox(fz_bbox a, fz_bbox b) { fz_bbox r; if (fz_is_infinite_rect(a)) return a; if (fz_is_infinite_rect(b)) return b; if (fz_is_empty_rect(a)) return b; if (fz_is_empty_rect(b)) return a; r.x0 = MIN(a.x0, b.x0); r.y0 = MIN(a.y0, b.y0); r.x1 = MAX(a.x1, b.x1); r.y1 = MAX(a.y1, b.y1); return r; }
fz_rect fz_intersect_rect(fz_rect a, fz_rect b) { fz_rect r; if (fz_is_infinite_rect(a)) return b; if (fz_is_infinite_rect(b)) return a; if (fz_is_empty_rect(a)) return fz_empty_rect; if (fz_is_empty_rect(b)) return fz_empty_rect; r.x0 = MAX(a.x0, b.x0); r.y0 = MAX(a.y0, b.y0); r.x1 = MIN(a.x1, b.x1); r.y1 = MIN(a.y1, b.y1); return (r.x1 < r.x0 || r.y1 < r.y0) ? fz_empty_rect : r; }
fz_bbox fz_intersect_bbox(fz_bbox a, fz_bbox b) { fz_bbox r; if (fz_is_infinite_rect(a)) return b; if (fz_is_infinite_rect(b)) return a; if (fz_is_empty_rect(a)) return fz_empty_bbox; if (fz_is_empty_rect(b)) return fz_empty_bbox; r.x0 = MAX(a.x0, b.x0); r.y0 = MAX(a.y0, b.y0); r.x1 = MIN(a.x1, b.x1); r.y1 = MIN(a.y1, b.y1); return (r.x1 < r.x0 || r.y1 < r.y0) ? fz_empty_bbox : r; }
fz_bbox fz_union_bbox(fz_bbox a, fz_bbox b) { fz_bbox r; /* Check for empty box before infinite box */ if (fz_is_empty_rect(a)) return b; if (fz_is_empty_rect(b)) return a; if (fz_is_infinite_rect(a)) return a; if (fz_is_infinite_rect(b)) return b; r.x0 = fz_mini(a.x0, b.x0); r.y0 = fz_mini(a.y0, b.y0); r.x1 = fz_maxi(a.x1, b.x1); r.y1 = fz_maxi(a.y1, b.y1); return r; }
fz_bbox fz_intersect_bbox(fz_bbox a, fz_bbox b) { fz_bbox r; /* Check for empty box before infinite box */ if (fz_is_empty_rect(a)) return fz_empty_bbox; if (fz_is_empty_rect(b)) return fz_empty_bbox; if (fz_is_infinite_rect(a)) return b; if (fz_is_infinite_rect(b)) return a; r.x0 = fz_maxi(a.x0, b.x0); r.y0 = fz_maxi(a.y0, b.y0); r.x1 = fz_mini(a.x1, b.x1); r.y1 = fz_mini(a.y1, b.y1); return (r.x1 < r.x0 || r.y1 < r.y0) ? fz_empty_bbox : r; }
fz_rect fz_intersect_rect(fz_rect a, fz_rect b) { fz_rect r; /* Check for empty box before infinite box */ if (fz_is_empty_rect(a)) return fz_empty_rect; if (fz_is_empty_rect(b)) return fz_empty_rect; if (fz_is_infinite_rect(a)) return b; if (fz_is_infinite_rect(b)) return a; r.x0 = fz_max(a.x0, b.x0); r.y0 = fz_max(a.y0, b.y0); r.x1 = fz_min(a.x1, b.x1); r.y1 = fz_min(a.y1, b.y1); return (r.x1 < r.x0 || r.y1 < r.y0) ? fz_empty_rect : r; }
static void fz_draw_clip_path(fz_device *devp, fz_path *path, fz_rect rect, int even_odd, fz_matrix ctm) { fz_draw_device *dev = devp->user; float expansion = fz_matrix_expansion(ctm); float flatness = 0.3f / expansion; fz_bbox bbox; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model; fz_context *ctx = dev->ctx; fz_reset_gel(dev->gel, state->scissor); fz_flatten_fill_path(dev->gel, path, ctm, flatness); fz_sort_gel(dev->gel); state = push_stack(dev); model = state->dest->colorspace; bbox = fz_bound_gel(dev->gel); bbox = fz_intersect_bbox(bbox, state->scissor); bbox = fz_intersect_bbox(bbox, fz_bbox_from_rect(rect)); /* SumatraPDF: try to match rendering with and without display list */ if (fz_is_infinite_rect(rect)) bbox = fz_intersect_bbox(bbox, fz_bbox_from_rect(fz_bound_path(ctx, path, NULL, ctm))); if (fz_is_empty_rect(bbox) || fz_is_rect_gel(dev->gel)) { state[1].scissor = bbox; state[1].mask = NULL; #ifdef DUMP_GROUP_BLENDS dump_spaces(dev->top-1, "Clip (rectangular) begin\n"); #endif return; } fz_try(ctx) { state[1].mask = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); fz_clear_pixmap(dev->ctx, state[1].mask); state[1].dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); fz_clear_pixmap(dev->ctx, state[1].dest); if (state[1].shape) { state[1].shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); fz_clear_pixmap(dev->ctx, state[1].shape); } fz_scan_convert(dev->gel, even_odd, bbox, state[1].mask, NULL); state[1].blendmode |= FZ_BLEND_ISOLATED; state[1].scissor = bbox; #ifdef DUMP_GROUP_BLENDS dump_spaces(dev->top-1, "Clip (non-rectangular) begin\n"); #endif } fz_catch(ctx) { emergency_pop_stack(dev, state); } }
fz_rect fz_transform_rect(fz_matrix m, fz_rect r) { fz_point s, t, u, v; if (fz_is_infinite_rect(r)) return r; s.x = r.x0; s.y = r.y0; t.x = r.x0; t.y = r.y1; u.x = r.x1; u.y = r.y1; v.x = r.x1; v.y = r.y0; s = fz_transform_point(m, s); t = fz_transform_point(m, t); u = fz_transform_point(m, u); v = fz_transform_point(m, v); r.x0 = MIN4(s.x, t.x, u.x, v.x); r.y0 = MIN4(s.y, t.y, u.y, v.y); r.x1 = MAX4(s.x, t.x, u.x, v.x); r.y1 = MAX4(s.y, t.y, u.y, v.y); return r; }
static void fz_draw_clip_stroke_path(fz_device *devp, fz_path *path, fz_rect rect, fz_stroke_state *stroke, fz_matrix ctm) { fz_draw_device *dev = devp->user; float expansion = fz_matrix_expansion(ctm); float flatness = 0.3f / expansion; float linewidth = stroke->linewidth; fz_bbox bbox; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model; fz_context *ctx = dev->ctx; if (linewidth * expansion < 0.1f) linewidth = 1 / expansion; fz_reset_gel(dev->gel, state->scissor); if (stroke->dash_len > 0) fz_flatten_dash_path(dev->gel, path, stroke, ctm, flatness, linewidth); else fz_flatten_stroke_path(dev->gel, path, stroke, ctm, flatness, linewidth); fz_sort_gel(dev->gel); state = push_stack(dev); model = state->dest->colorspace; bbox = fz_bound_gel(dev->gel); bbox = fz_intersect_bbox(bbox, state->scissor); bbox = fz_intersect_bbox(bbox, fz_bbox_from_rect(rect)); /* SumatraPDF: try to match rendering with and without display list */ if (fz_is_infinite_rect(rect)) bbox = fz_intersect_bbox(bbox, fz_bbox_from_rect(fz_bound_path(ctx, path, stroke, ctm))); fz_try(ctx) { state[1].mask = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); fz_clear_pixmap(dev->ctx, state[1].mask); state[1].dest = fz_new_pixmap_with_bbox(dev->ctx, model, bbox); fz_clear_pixmap(dev->ctx, state[1].dest); if (state->shape) { state[1].shape = fz_new_pixmap_with_bbox(dev->ctx, NULL, bbox); fz_clear_pixmap(dev->ctx, state[1].shape); } if (!fz_is_empty_rect(bbox)) fz_scan_convert(dev->gel, 0, bbox, state[1].mask, NULL); state[1].blendmode |= FZ_BLEND_ISOLATED; state[1].scissor = bbox; #ifdef DUMP_GROUP_BLENDS dump_spaces(dev->top-1, "Clip (stroke) begin\n"); #endif } fz_catch(ctx) { emergency_pop_stack(dev, state); } }
fz_bbox fz_translate_bbox(fz_bbox a, int xoff, int yoff) { fz_bbox b; if (fz_is_empty_rect(a)) return a; if (fz_is_infinite_rect(a)) return a; ADD_WITH_SAT(b.x0, a.x0, xoff); ADD_WITH_SAT(b.y0, a.y0, yoff); ADD_WITH_SAT(b.x1, a.x1, xoff); ADD_WITH_SAT(b.y1, a.y1, yoff); return b; }
void fz_reset_gel(fz_gel *gel, fz_bbox clip) { if (fz_is_infinite_rect(clip)) { gel->clip.x0 = gel->clip.y0 = BBOX_MAX; gel->clip.x1 = gel->clip.y1 = BBOX_MIN; } else { gel->clip.x0 = clip.x0 * FZ_AA_HSCALE(gel->ctx); gel->clip.x1 = clip.x1 * FZ_AA_HSCALE(gel->ctx); gel->clip.y0 = clip.y0 * FZ_AA_VSCALE(gel->ctx); gel->clip.y1 = clip.y1 * FZ_AA_VSCALE(gel->ctx); } gel->bbox.x0 = gel->bbox.y0 = BBOX_MAX; gel->bbox.x1 = gel->bbox.y1 = BBOX_MIN; gel->len = 0; }
fz_buffer * fz_new_buffer_from_stext_page(fz_context *ctx, fz_stext_page *text, const fz_rect *sel, int crlf) { fz_buffer *buf; fz_rect hitbox; float x0, y0, x1, y1; int block_num; int need_newline; int i; need_newline = 0; if (fz_is_infinite_rect(sel)) { x0 = y0 = -FLT_MAX; x1 = y1 = FLT_MAX; } else { x0 = sel->x0; y0 = sel->y0; x1 = sel->x1; y1 = sel->y1; } buf = fz_new_buffer(ctx, 256); fz_try(ctx) { for (block_num = 0; block_num < text->len; block_num++) { fz_stext_line *line; fz_stext_block *block; fz_stext_span *span; if (text->blocks[block_num].type != FZ_PAGE_BLOCK_TEXT) continue; block = text->blocks[block_num].u.text; for (line = block->lines; line < block->lines + block->len; line++) { int saw_text = 0; for (span = line->first_span; span; span = span->next) { for (i = 0; i < span->len; i++) { int c; fz_stext_char_bbox(ctx, &hitbox, span, i); c = span->text[i].c; if (c < 32) c = '?'; if (hitbox.x1 >= x0 && hitbox.x0 <= x1 && hitbox.y1 >= y0 && hitbox.y0 <= y1) { saw_text = 1; if (need_newline) { if (crlf) fz_write_buffer_rune(ctx, buf, '\r'); fz_write_buffer_rune(ctx, buf, '\n'); need_newline = 0; } fz_write_buffer_rune(ctx, buf, c); } } } if (saw_text) need_newline = 1; } } } fz_catch(ctx) { fz_drop_buffer(ctx, buf); fz_rethrow(ctx); } return buf; }