From 594c64f744862b993bcad12e05217f3d43e7d547 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 30 Jan 2013 13:54:39 +0100 Subject: Introduce fz_irect where the old fz_bbox was useful. Inside the renderer we often deal with integer sized areas, for pixmaps and scissoring regions. Use a new fz_irect type in these places. --- apps/mudraw.c | 5 ++- apps/pdfapp.c | 21 +++++---- doc/example.c | 5 ++- doc/multi-threaded.c | 2 +- draw/draw_affine.c | 13 +++--- draw/draw_blend.c | 4 +- draw/draw_device.c | 108 +++++++++++++++++++++++----------------------- draw/draw_edge.c | 20 ++++----- draw/draw_glyph.c | 6 +-- draw/draw_mesh.c | 6 +-- draw/draw_paint.c | 16 +++---- draw/draw_scale.c | 4 +- draw/draw_simple_scale.c | 4 +- fitz/base_geometry.c | 110 ++++++++++++++++++++++++++++++++++++++--------- fitz/fitz-internal.h | 28 ++++++------ fitz/fitz.h | 34 +++++++++++---- fitz/res_font.c | 16 +++---- fitz/res_pixmap.c | 29 ++++++------- 18 files changed, 256 insertions(+), 175 deletions(-) diff --git a/apps/mudraw.c b/apps/mudraw.c index 84c02682..cf9864ec 100644 --- a/apps/mudraw.c +++ b/apps/mudraw.c @@ -402,7 +402,8 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) { float zoom; fz_matrix ctm; - fz_rect bounds, tbounds, ibounds; + fz_rect bounds, tbounds; + fz_irect ibounds; fz_pixmap *pix = NULL; int w, h; @@ -477,7 +478,7 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) dev = fz_new_draw_device(ctx, pix); if (list) - fz_run_display_list(list, dev, ctm, ibounds, &cookie); + fz_run_display_list(list, dev, ctm, tbounds, &cookie); else fz_run_page(doc, page, dev, ctm, &cookie); fz_free_device(dev); diff --git a/apps/pdfapp.c b/apps/pdfapp.c index 167c118d..1d2a2fa2 100644 --- a/apps/pdfapp.c +++ b/apps/pdfapp.c @@ -100,7 +100,7 @@ void pdfapp_init(fz_context *ctx, pdfapp_t *app) void pdfapp_invert(pdfapp_t *app, fz_rect rect) { - fz_invert_pixmap_rect(app->image, rect); + fz_invert_pixmap_rect(app->image, fz_round_rect(rect)); } static void event_cb(fz_doc_event *event, void *data) @@ -566,14 +566,15 @@ static void pdfapp_updatepage(pdfapp_t *app) while ((annot = fz_poll_changed_annot(idoc, app->page)) != NULL) { - fz_rect bbox = fz_transform_rect(ctm, fz_bound_annot(app->doc, annot)); + fz_rect bounds = fz_transform_rect(ctm, fz_bound_annot(app->doc, annot)); + fz_irect bbox = fz_round_rect(bounds); fz_clear_pixmap_rect_with_value(app->ctx, app->image, 255, bbox); idev = fz_new_draw_device_with_bbox(app->ctx, app->image, bbox); if (app->page_list) - fz_run_display_list(app->page_list, idev, ctm, bbox, NULL); + fz_run_display_list(app->page_list, idev, ctm, bounds, NULL); if (app->annotations_list) - fz_run_display_list(app->annotations_list, idev, ctm, bbox, NULL); + fz_run_display_list(app->annotations_list, idev, ctm, bounds, NULL); fz_free_device(idev); } @@ -589,7 +590,8 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai fz_device *tdev; fz_colorspace *colorspace; fz_matrix ctm; - fz_rect bbox; + fz_rect bounds; + fz_irect bbox; fz_cookie cookie = { 0 }; if (!app->nowaitcursor) @@ -646,7 +648,8 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai wintitle(app, buf); ctm = pdfapp_viewctm(app); - bbox = fz_transform_rect(ctm, app->page_bbox); + bounds = fz_transform_rect(ctm, app->page_bbox); + bbox = fz_round_rect(bounds); /* Draw */ if (app->image) @@ -662,9 +665,9 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai { idev = fz_new_draw_device(app->ctx, app->image); if (app->page_list) - fz_run_display_list(app->page_list, idev, ctm, bbox, &cookie); + fz_run_display_list(app->page_list, idev, ctm, bounds, &cookie); if (app->annotations_list) - fz_run_display_list(app->annotations_list, idev, ctm, bbox, &cookie); + fz_run_display_list(app->annotations_list, idev, ctm, bounds, &cookie); fz_free_device(idev); } if (app->invert) @@ -1336,7 +1339,7 @@ void pdfapp_onkey(pdfapp_t *app, int c) void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int state) { fz_context *ctx = app->ctx; - fz_rect rect = fz_pixmap_bbox(app->ctx, app->image); + fz_irect rect = fz_pixmap_bbox(app->ctx, app->image); fz_link *link; fz_matrix ctm; fz_point p; diff --git a/doc/example.c b/doc/example.c index b834e3ff..d1e4798f 100644 --- a/doc/example.c +++ b/doc/example.c @@ -41,8 +41,8 @@ render(char *filename, int pagenumber, int zoom, int rotation) // Take the page bounds and transform them by the same matrix that // we will use to render the page. - fz_rect bbox = fz_bound_page(doc, page); - bbox = fz_transform_rect(transform, rect); + fz_rect bounds = fz_bound_page(doc, page); + bounds = fz_transform_rect(transform, rect); // Create a blank pixmap to hold the result of rendering. The // pixmap bounds used here are the same as the transformed page @@ -50,6 +50,7 @@ render(char *filename, int pagenumber, int zoom, int rotation) // space has the origin at the top left corner and the x axis // extends to the right and the y axis extends down. + fz_irect bbox = fz_round_rect(bounds); fz_pixmap *pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb, bbox); fz_clear_pixmap_with_value(ctx, pix, 0xff); diff --git a/doc/multi-threaded.c b/doc/multi-threaded.c index b54beb81..af4bab97 100644 --- a/doc/multi-threaded.c +++ b/doc/multi-threaded.c @@ -201,7 +201,7 @@ int main(int argc, char **argv) // Create a white pixmap using the correct dimensions. - fz_pixmap *pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb, bbox); + fz_pixmap *pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb, fz_round_rect(bbox)); fz_clear_pixmap_with_value(ctx, pix, 0xff); // Populate the data structure to be sent to the diff --git a/draw/draw_affine.c b/draw/draw_affine.c index 347346b9..a824c874 100644 --- a/draw/draw_affine.c +++ b/draw/draw_affine.c @@ -597,14 +597,14 @@ fz_gridfit_matrix(fz_matrix *m) /* Draw an image with an affine transform on destination */ static void -fz_paint_image_imp(fz_pixmap *dst, fz_rect scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, byte *color, int alpha) +fz_paint_image_imp(fz_pixmap *dst, fz_irect scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, byte *color, int alpha) { byte *dp, *sp, *hp; int u, v, fa, fb, fc, fd; int x, y, w, h; int sw, sh, n, hw; fz_matrix inv; - fz_rect bbox; + fz_irect bbox; int dolerp; void (*paintfn)(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color, byte *hp); @@ -629,9 +629,8 @@ fz_paint_image_imp(fz_pixmap *dst, fz_rect scissor, fz_pixmap *shape, fz_pixmap dolerp = 0; } - bbox = fz_transform_rect(ctm, fz_unit_rect); - bbox = fz_intersect_rect(bbox, scissor); - bbox = fz_rect_covering_rect(bbox); + bbox = fz_rect_covering_rect(fz_transform_rect(ctm, fz_unit_rect)); + bbox = fz_intersect_irect(bbox, scissor); x = bbox.x0; if (shape && shape->x > x) @@ -731,14 +730,14 @@ fz_paint_image_imp(fz_pixmap *dst, fz_rect scissor, fz_pixmap *shape, fz_pixmap } void -fz_paint_image_with_color(fz_pixmap *dst, fz_rect scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, byte *color) +fz_paint_image_with_color(fz_pixmap *dst, fz_irect scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, byte *color) { assert(img->n == 1); fz_paint_image_imp(dst, scissor, shape, img, ctm, color, 255); } void -fz_paint_image(fz_pixmap *dst, fz_rect scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, int alpha) +fz_paint_image(fz_pixmap *dst, fz_irect scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, int alpha) { assert(dst->n == img->n || (dst->n == 4 && img->n == 2)); fz_paint_image_imp(dst, scissor, shape, img, ctm, NULL, alpha); diff --git a/draw/draw_blend.c b/draw/draw_blend.c index 3e5dd932..27888cfe 100644 --- a/draw/draw_blend.c +++ b/draw/draw_blend.c @@ -574,7 +574,7 @@ void fz_blend_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, int blendmode, int isolated, fz_pixmap *shape) { unsigned char *sp, *dp; - fz_rect bbox; + fz_irect bbox; int x, y, w, h, n; /* TODO: fix this hack! */ @@ -590,7 +590,7 @@ fz_blend_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, int blendmode, int is } bbox = fz_pixmap_bbox_no_ctx(dst); - bbox = fz_intersect_rect(bbox, fz_pixmap_bbox_no_ctx(src)); + bbox = fz_intersect_irect(bbox, fz_pixmap_bbox_no_ctx(src)); x = bbox.x0; y = bbox.y0; diff --git a/draw/draw_device.c b/draw/draw_device.c index 196e9bdb..0e2697e4 100644 --- a/draw/draw_device.c +++ b/draw/draw_device.c @@ -22,7 +22,7 @@ enum { typedef struct fz_draw_state_s fz_draw_state; struct fz_draw_state_s { - fz_rect scissor; + fz_irect scissor; fz_pixmap *dest; fz_pixmap *mask; fz_pixmap *shape; @@ -31,7 +31,7 @@ struct fz_draw_state_s { float alpha; fz_matrix ctm; float xstep, ystep; - fz_rect area; + fz_irect area; }; struct fz_draw_device_s @@ -127,7 +127,7 @@ static fz_draw_state * fz_knockout_begin(fz_draw_device *dev) { fz_context *ctx = dev->ctx; - fz_rect bbox; + fz_irect bbox; fz_pixmap *dest, *shape; fz_draw_state *state = &dev->stack[dev->top]; int isolated = state->blendmode & FZ_BLEND_ISOLATED; @@ -138,7 +138,7 @@ fz_knockout_begin(fz_draw_device *dev) state = push_stack(dev); bbox = fz_pixmap_bbox(dev->ctx, state->dest); - bbox = fz_intersect_rect(bbox, state->scissor); + bbox = fz_intersect_irect(bbox, state->scissor); dest = fz_new_pixmap_with_bbox(dev->ctx, state->dest->colorspace, bbox); if (isolated) @@ -246,7 +246,7 @@ fz_draw_fill_path(fz_device *devp, fz_path *path, int even_odd, fz_matrix ctm, float flatness = 0.3f / expansion; unsigned char colorbv[FZ_MAX_COLORS + 1]; float colorfv[FZ_MAX_COLORS]; - fz_rect bbox; + fz_irect bbox; int i; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model = state->dest->colorspace; @@ -259,7 +259,7 @@ fz_draw_fill_path(fz_device *devp, fz_path *path, int even_odd, fz_matrix ctm, fz_sort_gel(dev->gel); bbox = fz_bound_gel(dev->gel); - bbox = fz_intersect_rect(bbox, state->scissor); + bbox = fz_intersect_irect(bbox, state->scissor); if (fz_is_empty_rect(bbox)) return; @@ -297,7 +297,7 @@ fz_draw_stroke_path(fz_device *devp, fz_path *path, fz_stroke_state *stroke, fz_ float linewidth = stroke->linewidth; unsigned char colorbv[FZ_MAX_COLORS + 1]; float colorfv[FZ_MAX_COLORS]; - fz_rect bbox; + fz_irect bbox; int i; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model = state->dest->colorspace; @@ -316,7 +316,7 @@ fz_draw_stroke_path(fz_device *devp, fz_path *path, fz_stroke_state *stroke, fz_ fz_sort_gel(dev->gel); bbox = fz_bound_gel(dev->gel); - bbox = fz_intersect_rect(bbox, state->scissor); + bbox = fz_intersect_irect(bbox, state->scissor); if (fz_is_empty_rect(bbox)) return; @@ -353,7 +353,7 @@ fz_draw_clip_path(fz_device *devp, fz_path *path, fz_rect rect, int even_odd, fz fz_draw_device *dev = devp->user; float expansion = fz_matrix_expansion(ctm); float flatness = 0.3f / expansion; - fz_rect bbox; + fz_irect bbox; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model; fz_context *ctx = dev->ctx; @@ -366,8 +366,8 @@ fz_draw_clip_path(fz_device *devp, fz_path *path, fz_rect rect, int even_odd, fz model = state->dest->colorspace; bbox = fz_bound_gel(dev->gel); - bbox = fz_intersect_rect(bbox, state->scissor); - bbox = fz_intersect_rect(bbox, fz_rect_covering_rect(rect)); + bbox = fz_intersect_irect(bbox, state->scissor); + bbox = fz_intersect_irect(bbox, fz_rect_covering_rect(rect)); if (fz_is_empty_rect(bbox) || fz_is_rect_gel(dev->gel)) { @@ -412,7 +412,7 @@ fz_draw_clip_stroke_path(fz_device *devp, fz_path *path, fz_rect rect, fz_stroke float expansion = fz_matrix_expansion(ctm); float flatness = 0.3f / expansion; float linewidth = stroke->linewidth; - fz_rect bbox; + fz_irect bbox; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model; fz_context *ctx = dev->ctx; @@ -431,8 +431,8 @@ fz_draw_clip_stroke_path(fz_device *devp, fz_path *path, fz_rect rect, fz_stroke model = state->dest->colorspace; bbox = fz_bound_gel(dev->gel); - bbox = fz_intersect_rect(bbox, state->scissor); - bbox = fz_intersect_rect(bbox, fz_rect_covering_rect(rect)); + bbox = fz_intersect_irect(bbox, state->scissor); + bbox = fz_intersect_irect(bbox, fz_rect_covering_rect(rect)); fz_try(ctx) { @@ -463,15 +463,15 @@ fz_draw_clip_stroke_path(fz_device *devp, fz_path *path, fz_rect rect, fz_stroke static void draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_pixmap *msk, - int xorig, int yorig, fz_rect scissor) + int xorig, int yorig, fz_irect scissor) { unsigned char *dp, *mp; - fz_rect bbox; + fz_irect bbox; int x, y, w, h; bbox = fz_pixmap_bbox_no_ctx(msk); - bbox = fz_translate_rect(bbox, xorig, yorig); - bbox = fz_intersect_rect(bbox, scissor); /* scissor < dst */ + bbox = fz_translate_irect(bbox, xorig, yorig); + bbox = fz_intersect_irect(bbox, scissor); /* scissor < dst */ x = bbox.x0; y = bbox.y0; w = bbox.x1 - bbox.x0; @@ -506,7 +506,7 @@ fz_draw_fill_text(fz_device *devp, fz_text *text, fz_matrix ctm, int i, x, y, gid; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model = state->dest->colorspace; - fz_rect scissor = state->scissor; + fz_irect scissor = state->scissor; if (state->blendmode & FZ_BLEND_KNOCKOUT) state = fz_knockout_begin(dev); @@ -585,7 +585,7 @@ fz_draw_stroke_text(fz_device *devp, fz_text *text, fz_stroke_state *stroke, fz_ int i, x, y, gid; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model = state->dest->colorspace; - fz_rect scissor = state->scissor; + fz_irect scissor = state->scissor; if (state->blendmode & FZ_BLEND_KNOCKOUT) state = fz_knockout_begin(dev); @@ -648,7 +648,7 @@ fz_draw_clip_text(fz_device *devp, fz_text *text, fz_matrix ctm, int accumulate) { fz_draw_device *dev = devp->user; fz_context *ctx = dev->ctx; - fz_rect bbox; + fz_irect bbox; fz_pixmap *mask, *dest, *shape; fz_matrix tm, trm, trunc_trm; fz_pixmap *glyph; @@ -667,7 +667,7 @@ fz_draw_clip_text(fz_device *devp, fz_text *text, fz_matrix ctm, int accumulate) { /* make the mask the exact size needed */ bbox = fz_rect_covering_rect(fz_bound_text(dev->ctx, text, ctm)); - bbox = fz_intersect_rect(bbox, state->scissor); + bbox = fz_intersect_irect(bbox, state->scissor); } else { @@ -782,7 +782,7 @@ fz_draw_clip_stroke_text(fz_device *devp, fz_text *text, fz_stroke_state *stroke { fz_draw_device *dev = devp->user; fz_context *ctx = dev->ctx; - fz_rect bbox; + fz_irect bbox; fz_pixmap *mask, *dest, *shape; fz_matrix tm, trm, trunc_trm; fz_pixmap *glyph; @@ -792,7 +792,7 @@ fz_draw_clip_stroke_text(fz_device *devp, fz_text *text, fz_stroke_state *stroke /* make the mask the exact size needed */ bbox = fz_rect_covering_rect(fz_bound_text(dev->ctx, text, ctm)); - bbox = fz_intersect_rect(bbox, state->scissor); + bbox = fz_intersect_irect(bbox, state->scissor); fz_try(ctx) { @@ -893,7 +893,7 @@ fz_draw_fill_shade(fz_device *devp, fz_shade *shade, fz_matrix ctm, float alpha) { fz_draw_device *dev = devp->user; fz_rect bounds; - fz_rect bbox, scissor; + fz_irect bbox, scissor; fz_pixmap *dest, *shape; float colorfv[FZ_MAX_COLORS]; unsigned char colorbv[FZ_MAX_COLORS + 1]; @@ -902,7 +902,7 @@ fz_draw_fill_shade(fz_device *devp, fz_shade *shade, fz_matrix ctm, float alpha) bounds = fz_bound_shade(dev->ctx, shade, ctm); scissor = state->scissor; - bbox = fz_intersect_rect(fz_rect_covering_rect(bounds), scissor); + bbox = fz_intersect_irect(fz_rect_covering_rect(bounds), scissor); if (fz_is_empty_rect(bbox)) return; @@ -982,7 +982,7 @@ fz_draw_fill_shade(fz_device *devp, fz_shade *shade, fz_matrix ctm, float alpha) } static fz_pixmap * -fz_transform_pixmap(fz_draw_device *dev, fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int dy, int gridfit, fz_rect *clip) +fz_transform_pixmap(fz_draw_device *dev, fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int dy, int gridfit, fz_irect *clip) { fz_pixmap *scaled; fz_context *ctx = dev->ctx; @@ -1007,7 +1007,7 @@ fz_transform_pixmap(fz_draw_device *dev, fz_pixmap *image, fz_matrix *ctm, int x { /* Other orthogonal flip/rotation cases */ fz_matrix m = *ctm; - fz_rect rclip; + fz_irect rclip; if (gridfit) fz_gridfit_matrix(&m); if (clip) @@ -1050,9 +1050,9 @@ fz_draw_fill_image(fz_device *devp, fz_image *image, fz_matrix ctm, float alpha) fz_context *ctx = dev->ctx; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model = state->dest->colorspace; - fz_rect clip = fz_pixmap_bbox(ctx, state->dest); + fz_irect clip = fz_pixmap_bbox(ctx, state->dest); - clip = fz_intersect_rect(clip, state->scissor); + clip = fz_intersect_irect(clip, state->scissor); fz_var(scaled); @@ -1154,9 +1154,9 @@ fz_draw_fill_image_mask(fz_device *devp, fz_image *image, fz_matrix ctm, fz_context *ctx = dev->ctx; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model = state->dest->colorspace; - fz_rect clip = fz_pixmap_bbox(ctx, state->dest); + fz_irect clip = fz_pixmap_bbox(ctx, state->dest); - clip = fz_intersect_rect(clip, state->scissor); + clip = fz_intersect_irect(clip, state->scissor); if (image->w == 0 || image->h == 0) return; @@ -1215,7 +1215,7 @@ fz_draw_clip_image_mask(fz_device *devp, fz_image *image, fz_rect rect, fz_matri { fz_draw_device *dev = devp->user; fz_context *ctx = dev->ctx; - fz_rect bbox; + fz_irect bbox; fz_pixmap *mask = NULL; fz_pixmap *dest = NULL; fz_pixmap *shape = NULL; @@ -1225,9 +1225,9 @@ fz_draw_clip_image_mask(fz_device *devp, fz_image *image, fz_rect rect, fz_matri int dx, dy; fz_draw_state *state = push_stack(dev); fz_colorspace *model = state->dest->colorspace; - fz_rect clip = fz_pixmap_bbox(ctx, state->dest); + fz_irect clip = fz_pixmap_bbox(ctx, state->dest); - clip = fz_intersect_rect(clip, state->scissor); + clip = fz_intersect_irect(clip, state->scissor); fz_var(mask); fz_var(dest); @@ -1240,7 +1240,7 @@ fz_draw_clip_image_mask(fz_device *devp, fz_image *image, fz_rect rect, fz_matri #ifdef DUMP_GROUP_BLENDS dump_spaces(dev->top-1, "Clip (image mask) (empty) begin\n"); #endif - state[1].scissor = fz_empty_rect; + state[1].scissor = fz_empty_irect; state[1].mask = NULL; return; } @@ -1250,8 +1250,8 @@ fz_draw_clip_image_mask(fz_device *devp, fz_image *image, fz_rect rect, fz_matri #endif bbox = fz_rect_covering_rect(fz_transform_rect(ctm, fz_unit_rect)); - bbox = fz_intersect_rect(bbox, state->scissor); - bbox = fz_intersect_rect(bbox, fz_rect_covering_rect(rect)); + bbox = fz_intersect_irect(bbox, state->scissor); + bbox = fz_intersect_irect(bbox, fz_rect_covering_rect(rect)); dx = sqrtf(ctm.a * ctm.a + ctm.b * ctm.b); dy = sqrtf(ctm.c * ctm.c + ctm.d * ctm.d); @@ -1360,13 +1360,13 @@ fz_draw_begin_mask(fz_device *devp, fz_rect rect, int luminosity, fz_colorspace { fz_draw_device *dev = devp->user; fz_pixmap *dest; - fz_rect bbox; + fz_irect bbox; fz_draw_state *state = push_stack(dev); fz_pixmap *shape = state->shape; fz_context *ctx = dev->ctx; bbox = fz_rect_covering_rect(rect); - bbox = fz_intersect_rect(bbox, state->scissor); + bbox = fz_intersect_irect(bbox, state->scissor); fz_try(ctx) { @@ -1416,7 +1416,7 @@ fz_draw_end_mask(fz_device *devp) { fz_draw_device *dev = devp->user; fz_pixmap *temp, *dest; - fz_rect bbox; + fz_irect bbox; int luminosity; fz_context *ctx = dev->ctx; fz_draw_state *state; @@ -1468,7 +1468,7 @@ static void fz_draw_begin_group(fz_device *devp, fz_rect rect, int isolated, int knockout, int blendmode, float alpha) { fz_draw_device *dev = devp->user; - fz_rect bbox; + fz_irect bbox; fz_pixmap *dest, *shape; fz_context *ctx = dev->ctx; fz_draw_state *state = &dev->stack[dev->top]; @@ -1479,7 +1479,7 @@ fz_draw_begin_group(fz_device *devp, fz_rect rect, int isolated, int knockout, i state = push_stack(dev); bbox = fz_rect_covering_rect(rect); - bbox = fz_intersect_rect(bbox, state->scissor); + bbox = fz_intersect_irect(bbox, state->scissor); fz_try(ctx) { @@ -1591,7 +1591,7 @@ fz_draw_begin_tile(fz_device *devp, fz_rect area, fz_rect view, float xstep, flo fz_draw_device *dev = devp->user; fz_pixmap *dest = NULL; fz_pixmap *shape; - fz_rect bbox; + fz_irect bbox; fz_context *ctx = dev->ctx; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model = state->dest->colorspace; @@ -1624,7 +1624,7 @@ fz_draw_begin_tile(fz_device *devp, fz_rect area, fz_rect view, float xstep, flo state[1].blendmode |= FZ_BLEND_ISOLATED; state[1].xstep = xstep; state[1].ystep = ystep; - state[1].area = area; + state[1].area = fz_rect_covering_rect(area); state[1].ctm = ctm; #ifdef DUMP_GROUP_BLENDS dump_spaces(dev->top-1, "Tile begin\n"); @@ -1645,8 +1645,8 @@ fz_draw_end_tile(fz_device *devp) fz_draw_device *dev = devp->user; float xstep, ystep; fz_matrix ttm, ctm, shapectm; - fz_rect area, scissor; - fz_rect scissor_box; + fz_irect area, scissor; + fz_rect scissor_tmp; int x0, y0, x1, y1, x, y; fz_context *ctx = dev->ctx; fz_draw_state *state; @@ -1665,13 +1665,11 @@ fz_draw_end_tile(fz_device *devp) /* Fudge the scissor bbox a little to allow for inaccuracies in the * matrix inversion. */ - scissor_box = fz_expand_rect(state[0].scissor, 1); - scissor.x0 = (float)scissor_box.x0; - scissor.y0 = (float)scissor_box.y0; - scissor.x1 = (float)scissor_box.x1; - scissor.y1 = (float)scissor_box.y1; - scissor = fz_transform_rect(fz_invert_matrix(ctm), scissor); - area = fz_intersect_rect(area, scissor); + scissor_tmp = fz_rect_from_irect(state[0].scissor); + scissor_tmp = fz_expand_rect(scissor_tmp, 1); + scissor_tmp = fz_transform_rect(fz_invert_matrix(ctm), scissor_tmp); + scissor = fz_rect_covering_rect(scissor_tmp); + area = fz_intersect_irect(area, scissor); x0 = floorf(area.x0 / xstep); y0 = floorf(area.y0 / ystep); @@ -1831,7 +1829,7 @@ fz_new_draw_device(fz_context *ctx, fz_pixmap *dest) } fz_device * -fz_new_draw_device_with_bbox(fz_context *ctx, fz_pixmap *dest, fz_rect clip) +fz_new_draw_device_with_bbox(fz_context *ctx, fz_pixmap *dest, fz_irect clip) { fz_device *dev = fz_new_draw_device(ctx, dest); fz_draw_device *ddev = dev->user; diff --git a/draw/draw_edge.c b/draw/draw_edge.c index df59ba14..c5438ffe 100644 --- a/draw/draw_edge.c +++ b/draw/draw_edge.c @@ -203,7 +203,7 @@ fz_new_gel(fz_context *ctx) } void -fz_reset_gel(fz_gel *gel, fz_rect clip) +fz_reset_gel(fz_gel *gel, fz_irect clip) { fz_aa_context *ctxaa = gel->ctx->aa; @@ -235,13 +235,13 @@ fz_free_gel(fz_gel *gel) fz_free(gel->ctx, gel); } -fz_rect +fz_irect fz_bound_gel(fz_gel *gel) { - fz_rect bbox; + fz_irect bbox; fz_aa_context *ctxaa = gel->ctx->aa; if (gel->len == 0) - return fz_empty_rect; + return fz_empty_irect; bbox.x0 = fz_idiv(gel->bbox.x0, fz_aa_hscale); bbox.y0 = fz_idiv(gel->bbox.y0, fz_aa_vscale); bbox.x1 = fz_idiv(gel->bbox.x1, fz_aa_hscale) + 1; @@ -666,7 +666,7 @@ static inline void blit_aa(fz_pixmap *dst, int x, int y, } static void -fz_scan_convert_aa(fz_gel *gel, int eofill, fz_rect clip, +fz_scan_convert_aa(fz_gel *gel, int eofill, fz_irect clip, fz_pixmap *dst, unsigned char *color) { unsigned char *alphas; @@ -851,7 +851,7 @@ clip_ended: */ static inline void blit_sharp(int x0, int x1, int y, - fz_rect clip, fz_pixmap *dst, unsigned char *color) + fz_irect clip, fz_pixmap *dst, unsigned char *color) { unsigned char *dp; x0 = fz_clampi(x0, dst->x, dst->x + dst->w); @@ -867,7 +867,7 @@ static inline void blit_sharp(int x0, int x1, int y, } static inline void non_zero_winding_sharp(fz_gel *gel, int y, - fz_rect clip, fz_pixmap *dst, unsigned char *color) + fz_irect clip, fz_pixmap *dst, unsigned char *color) { int winding = 0; int x = 0; @@ -883,7 +883,7 @@ static inline void non_zero_winding_sharp(fz_gel *gel, int y, } static inline void even_odd_sharp(fz_gel *gel, int y, - fz_rect clip, fz_pixmap *dst, unsigned char *color) + fz_irect clip, fz_pixmap *dst, unsigned char *color) { int even = 0; int x = 0; @@ -899,7 +899,7 @@ static inline void even_odd_sharp(fz_gel *gel, int y, } static void -fz_scan_convert_sharp(fz_gel *gel, int eofill, fz_rect clip, +fz_scan_convert_sharp(fz_gel *gel, int eofill, fz_irect clip, fz_pixmap *dst, unsigned char *color) { int e = 0; @@ -955,7 +955,7 @@ fz_scan_convert_sharp(fz_gel *gel, int eofill, fz_rect clip, } void -fz_scan_convert(fz_gel *gel, int eofill, fz_rect clip, +fz_scan_convert(fz_gel *gel, int eofill, fz_irect clip, fz_pixmap *dst, unsigned char *color) { fz_aa_context *ctxaa = gel->ctx->aa; diff --git a/draw/draw_glyph.c b/draw/draw_glyph.c index 40c71241..93caf478 100644 --- a/draw/draw_glyph.c +++ b/draw/draw_glyph.c @@ -95,7 +95,7 @@ fz_keep_glyph_cache(fz_context *ctx) } fz_pixmap * -fz_render_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *stroke, fz_rect scissor) +fz_render_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *stroke, fz_irect scissor) { if (font->ft_face) { @@ -116,7 +116,7 @@ fz_render_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, This must not be inserted into the cache. */ fz_pixmap * -fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm, fz_colorspace *model, fz_rect scissor) +fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm, fz_colorspace *model, fz_irect scissor) { fz_glyph_cache *cache; fz_glyph_key key; @@ -126,7 +126,7 @@ fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm, fz_color if (size <= MAX_GLYPH_SIZE) { - scissor = fz_infinite_rect; + scissor = fz_infinite_irect; do_cache = 1; } else diff --git a/draw/draw_mesh.c b/draw/draw_mesh.c index 98669e17..bbd3dc02 100644 --- a/draw/draw_mesh.c +++ b/draw/draw_mesh.c @@ -213,7 +213,7 @@ static inline void step_edge(int *ael, int *del, int n) } static void -fz_paint_triangle(fz_pixmap *pix, float *av, float *bv, float *cv, int n, fz_rect bbox) +fz_paint_triangle(fz_pixmap *pix, float *av, float *bv, float *cv, int n, fz_irect bbox) { float poly[MAXV][MAXN]; float temp[MAXV][MAXN]; @@ -307,7 +307,7 @@ struct paint_tri_data fz_context *ctx; fz_shade *shade; fz_pixmap *dest; - fz_rect bbox; + fz_irect bbox; }; static void @@ -349,7 +349,7 @@ do_paint_tri(void *arg, fz_vertex *av, fz_vertex *bv, fz_vertex *cv) } void -fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_rect bbox) +fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_irect bbox) { unsigned char clut[256][FZ_MAX_COLORS]; fz_pixmap *temp = NULL; diff --git a/draw/draw_paint.c b/draw/draw_paint.c index 2f6ef368..de0f1d34 100644 --- a/draw/draw_paint.c +++ b/draw/draw_paint.c @@ -375,15 +375,15 @@ fz_paint_span(byte * restrict dp, byte * restrict sp, int n, int w, int alpha) */ void -fz_paint_pixmap_with_bbox(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_rect bbox) +fz_paint_pixmap_with_bbox(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_irect bbox) { unsigned char *sp, *dp; int x, y, w, h, n; assert(dst->n == src->n); - bbox = fz_intersect_rect(bbox, fz_pixmap_bbox_no_ctx(dst)); - bbox = fz_intersect_rect(bbox, fz_pixmap_bbox_no_ctx(src)); + bbox = fz_intersect_irect(bbox, fz_pixmap_bbox_no_ctx(dst)); + bbox = fz_intersect_irect(bbox, fz_pixmap_bbox_no_ctx(src)); x = bbox.x0; y = bbox.y0; @@ -408,13 +408,13 @@ void fz_paint_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha) { unsigned char *sp, *dp; - fz_rect bbox; + fz_irect bbox; int x, y, w, h, n; assert(dst->n == src->n); bbox = fz_pixmap_bbox_no_ctx(dst); - bbox = fz_intersect_rect(bbox, fz_pixmap_bbox_no_ctx(src)); + bbox = fz_intersect_irect(bbox, fz_pixmap_bbox_no_ctx(src)); x = bbox.x0; y = bbox.y0; @@ -439,15 +439,15 @@ void fz_paint_pixmap_with_mask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk) { unsigned char *sp, *dp, *mp; - fz_rect bbox; + fz_irect bbox; int x, y, w, h, n; assert(dst->n == src->n); assert(msk->n == 1); bbox = fz_pixmap_bbox_no_ctx(dst); - bbox = fz_intersect_rect(bbox, fz_pixmap_bbox_no_ctx(src)); - bbox = fz_intersect_rect(bbox, fz_pixmap_bbox_no_ctx(msk)); + bbox = fz_intersect_irect(bbox, fz_pixmap_bbox_no_ctx(src)); + bbox = fz_intersect_irect(bbox, fz_pixmap_bbox_no_ctx(msk)); x = bbox.x0; y = bbox.y0; diff --git a/draw/draw_scale.c b/draw/draw_scale.c index a2439216..8cb99166 100644 --- a/draw/draw_scale.c +++ b/draw/draw_scale.c @@ -1238,13 +1238,13 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in #endif /* SINGLE_PIXEL_SPECIALS */ fz_pixmap * -fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_rect *clip) +fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_irect *clip) { return fz_scale_pixmap_cached(ctx, src, x, y, w, h, clip, NULL, NULL); } fz_pixmap * -fz_scale_pixmap_cached(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_rect *clip, fz_scale_cache *cache_x, fz_scale_cache *cache_y) +fz_scale_pixmap_cached(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_irect *clip, fz_scale_cache *cache_x, fz_scale_cache *cache_y) { fz_scale_filter *filter = &fz_scale_filter_simple; fz_weights *contrib_rows = NULL; diff --git a/draw/draw_simple_scale.c b/draw/draw_simple_scale.c index d2b69cf9..60914e52 100644 --- a/draw/draw_simple_scale.c +++ b/draw/draw_simple_scale.c @@ -1214,13 +1214,13 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in #endif /* SINGLE_PIXEL_SPECIALS */ fz_pixmap * -fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_rect *clip) +fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_irect *clip) { return fz_scale_pixmap_cached(ctx, src, x, y, w, h, clip, NULL, NULL); } fz_pixmap * -fz_scale_pixmap_cached(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_rect *clip, fz_scale_cache *cache_x, fz_scale_cache *cache_y) +fz_scale_pixmap_cached(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_irect *clip, fz_scale_cache *cache_x, fz_scale_cache *cache_y) { fz_scale_filter *filter = &fz_scale_filter_simple; fz_weights *contrib_rows = NULL; diff --git a/fitz/base_geometry.c b/fitz/base_geometry.c index 1486279f..317c8df1 100644 --- a/fitz/base_geometry.c +++ b/fitz/base_geometry.c @@ -3,6 +3,24 @@ #define MAX4(a,b,c,d) fz_max(fz_max(a,b), fz_max(c,d)) #define MIN4(a,b,c,d) fz_min(fz_min(a,b), fz_min(c,d)) +/* A useful macro to add with overflow detection and clamping. + + We want to do "b = a + x", but to allow for overflow. Consider the + top bits, and the cases in which overflow occurs: + + overflow a x b ~a^x a^b (~a^x)&(a^b) + no 0 0 0 1 0 0 + yes 0 0 1 1 1 1 + no 0 1 0 0 0 0 + no 0 1 1 0 1 0 + no 1 0 0 0 1 0 + no 1 0 1 0 0 0 + yes 1 1 0 1 1 1 + no 1 1 1 1 0 0 +*/ +#define ADD_WITH_SAT(b,a,x) \ + ((b) = (a) + (x), (b) = (((~(a)^(x))&((a)^(b))) < 0 ? ((x) < 0 ? INT_MIN : INT_MAX) : (b))) + /* Matrices, points and affine transformations */ const fz_matrix fz_identity = { 1, 0, 0, 1, 0, 0 }; @@ -170,36 +188,57 @@ const fz_rect fz_infinite_rect = { 1, 1, -1, -1 }; const fz_rect fz_empty_rect = { 0, 0, 0, 0 }; const fz_rect fz_unit_rect = { 0, 0, 1, 1 }; -fz_rect -fz_rect_covering_rect(fz_rect f) +const fz_irect fz_infinite_irect = { 1, 1, -1, -1 }; +const fz_irect fz_empty_irect = { 0, 0, 0, 0 }; +const fz_irect fz_unit_irect = { 0, 0, 1, 1 }; + +fz_irect +fz_rect_covering_rect(fz_rect a) { - f.x0 = floorf(f.x0); - f.y0 = floorf(f.y0); - f.x1 = ceilf(f.x1); - f.y1 = ceilf(f.y1); + fz_irect b; + + a.x0 = floorf(a.x0); + a.y0 = floorf(a.y0); + a.x1 = ceilf(a.x1); + a.y1 = ceilf(a.y1); /* check for integer overflow */ - f.x0 = fz_clamp(f.x0, MIN_SAFE_INT, MAX_SAFE_INT); - f.y0 = fz_clamp(f.y0, MIN_SAFE_INT, MAX_SAFE_INT); - f.x1 = fz_clamp(f.x1, MIN_SAFE_INT, MAX_SAFE_INT); - f.y1 = fz_clamp(f.y1, MIN_SAFE_INT, MAX_SAFE_INT); - return f; + b.x0 = fz_clamp(a.x0, MIN_SAFE_INT, MAX_SAFE_INT); + b.y0 = fz_clamp(a.y0, MIN_SAFE_INT, MAX_SAFE_INT); + b.x1 = fz_clamp(a.x1, MIN_SAFE_INT, MAX_SAFE_INT); + b.y1 = fz_clamp(a.y1, MIN_SAFE_INT, MAX_SAFE_INT); + + return b; } fz_rect -fz_round_rect(fz_rect f) +fz_rect_from_irect(fz_irect a) { - f.x0 = floorf(f.x0 + 0.001); - f.y0 = floorf(f.y0 + 0.001); - f.x1 = ceilf(f.x1 - 0.001); - f.y1 = ceilf(f.y1 - 0.001); + fz_rect b; + b.x0 = a.x0; + b.y0 = a.y0; + b.x1 = a.x1; + b.y1 = a.y1; + return b; +} + +fz_irect +fz_round_rect(fz_rect a) +{ + fz_irect b; + + a.x0 = floorf(a.x0 + 0.001); + a.y0 = floorf(a.y0 + 0.001); + a.x1 = ceilf(a.x1 - 0.001); + a.y1 = ceilf(a.y1 - 0.001); /* check for integer overflow */ - f.x0 = fz_clamp(f.x0, MIN_SAFE_INT, MAX_SAFE_INT); - f.y0 = fz_clamp(f.y0, MIN_SAFE_INT, MAX_SAFE_INT); - f.x1 = fz_clamp(f.x1, MIN_SAFE_INT, MAX_SAFE_INT); - f.y1 = fz_clamp(f.y1, MIN_SAFE_INT, MAX_SAFE_INT); - return f; + b.x0 = fz_clamp(a.x0, MIN_SAFE_INT, MAX_SAFE_INT); + b.y0 = fz_clamp(a.y0, MIN_SAFE_INT, MAX_SAFE_INT); + b.x1 = fz_clamp(a.x1, MIN_SAFE_INT, MAX_SAFE_INT); + b.y1 = fz_clamp(a.y1, MIN_SAFE_INT, MAX_SAFE_INT); + + return b; } fz_rect @@ -218,6 +257,22 @@ fz_intersect_rect(fz_rect a, fz_rect b) return (r.x1 < r.x0 || r.y1 < r.y0) ? fz_empty_rect : r; } +fz_irect +fz_intersect_irect(fz_irect a, fz_irect b) +{ + fz_irect r; + /* Check for empty box before infinite box */ + if (fz_is_empty_rect(a)) return fz_empty_irect; + if (fz_is_empty_rect(b)) return fz_empty_irect; + 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_irect : r; +} + fz_rect fz_union_rect(fz_rect a, fz_rect b) { @@ -270,6 +325,19 @@ fz_translate_rect(fz_rect a, float xoff, float yoff) return b; } +fz_irect +fz_translate_irect(fz_irect a, int xoff, int yoff) +{ + fz_irect 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; +} + fz_rect fz_expand_rect(fz_rect a, float expand) { diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index e7e7ca3b..518ed8c2 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -872,22 +872,22 @@ struct fz_pixmap_s void fz_free_pixmap_imp(fz_context *ctx, fz_storable *pix); -void fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, fz_rect r); +void fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, fz_irect r); void fz_premultiply_pixmap(fz_context *ctx, fz_pixmap *pix); fz_pixmap *fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray, int luminosity); unsigned int fz_pixmap_size(fz_context *ctx, fz_pixmap *pix); -fz_pixmap *fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_rect *clip); +fz_pixmap *fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_irect *clip); typedef struct fz_scale_cache_s fz_scale_cache; fz_scale_cache *fz_new_scale_cache(fz_context *ctx); void fz_free_scale_cache(fz_context *ctx, fz_scale_cache *cache); -fz_pixmap *fz_scale_pixmap_cached(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_rect *clip, fz_scale_cache *cache_x, fz_scale_cache *cache_y); +fz_pixmap *fz_scale_pixmap_cached(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_irect *clip, fz_scale_cache *cache_x, fz_scale_cache *cache_y); void fz_subsample_pixmap(fz_context *ctx, fz_pixmap *tile, int factor); -fz_rect fz_pixmap_bbox_no_ctx(fz_pixmap *src); +fz_irect fz_pixmap_bbox_no_ctx(fz_pixmap *src); typedef struct fz_compression_params_s fz_compression_params; @@ -1187,10 +1187,10 @@ void fz_purge_glyph_cache(fz_context *ctx); fz_path *fz_outline_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm); fz_path *fz_outline_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix ctm); fz_pixmap *fz_render_ft_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm, int aa); -fz_pixmap *fz_render_t3_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm, fz_colorspace *model, fz_rect scissor); +fz_pixmap *fz_render_t3_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm, fz_colorspace *model, fz_irect scissor); fz_pixmap *fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *state); -fz_pixmap *fz_render_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz_colorspace *model, fz_rect scissor); -fz_pixmap *fz_render_stroked_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz_matrix, fz_stroke_state *stroke, fz_rect scissor); +fz_pixmap *fz_render_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz_colorspace *model, fz_irect scissor); +fz_pixmap *fz_render_stroked_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz_matrix, fz_stroke_state *stroke, fz_irect scissor); void fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, fz_matrix trm, void *gstate, int nestedDepth); void fz_prepare_t3_glyph(fz_context *ctx, fz_font *font, int gid, int nestedDepth); @@ -1300,7 +1300,7 @@ void fz_drop_shade(fz_context *ctx, fz_shade *shade); void fz_free_shade_imp(fz_context *ctx, fz_storable *shade); fz_rect fz_bound_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm); -void fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_rect bbox); +void fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_irect bbox); /* * Handy routine for processing mesh based shades @@ -1339,13 +1339,13 @@ typedef struct fz_gel_s fz_gel; fz_gel *fz_new_gel(fz_context *ctx); void fz_insert_gel(fz_gel *gel, float x0, float y0, float x1, float y1); -void fz_reset_gel(fz_gel *gel, fz_rect clip); +void fz_reset_gel(fz_gel *gel, fz_irect clip); void fz_sort_gel(fz_gel *gel); -fz_rect fz_bound_gel(fz_gel *gel); +fz_irect fz_bound_gel(fz_gel *gel); void fz_free_gel(fz_gel *gel); int fz_is_rect_gel(fz_gel *gel); -void fz_scan_convert(fz_gel *gel, int eofill, fz_rect clip, fz_pixmap *pix, unsigned char *colorbv); +void fz_scan_convert(fz_gel *gel, int eofill, fz_irect clip, fz_pixmap *pix, unsigned char *colorbv); void fz_flatten_fill_path(fz_gel *gel, fz_path *path, fz_matrix ctm, float flatness); void fz_flatten_stroke_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, float flatness, float linewidth); @@ -1458,12 +1458,12 @@ void fz_paint_solid_color(unsigned char * restrict dp, int n, int w, unsigned ch void fz_paint_span(unsigned char * restrict dp, unsigned char * restrict sp, int n, int w, int alpha); void fz_paint_span_with_color(unsigned char * restrict dp, unsigned char * restrict mp, int n, int w, unsigned char *color); -void fz_paint_image(fz_pixmap *dst, fz_rect scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, int alpha); -void fz_paint_image_with_color(fz_pixmap *dst, fz_rect scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, unsigned char *colorbv); +void fz_paint_image(fz_pixmap *dst, fz_irect scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, int alpha); +void fz_paint_image_with_color(fz_pixmap *dst, fz_irect scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, unsigned char *colorbv); void fz_paint_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha); void fz_paint_pixmap_with_mask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk); -void fz_paint_pixmap_with_bbox(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_rect bbox); +void fz_paint_pixmap_with_bbox(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_irect bbox); void fz_blend_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, int blendmode, int isolated, fz_pixmap *shape); void fz_blend_pixel(unsigned char dp[3], unsigned char bp[3], unsigned char sp[3], int blendmode); diff --git a/fitz/fitz.h b/fitz/fitz.h index 7243c341..0e025e44 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -747,6 +747,18 @@ struct fz_rect_s float x1, y1; }; +/* + fz_irect is a rectangle using integers instead of floats. + + It's used in the draw device and for pixmap dimensions. +*/ +typedef struct fz_irect_s fz_irect; +struct fz_irect_s +{ + int x0, y0; + int x1, y1; +}; + /* A rectangle with sides of length one. @@ -761,6 +773,7 @@ extern const fz_rect fz_unit_rect; Both the top left and bottom right corner are at (0, 0). */ extern const fz_rect fz_empty_rect; +extern const fz_irect fz_empty_irect; /* An infinite rectangle with negative area. @@ -769,6 +782,7 @@ extern const fz_rect fz_empty_rect; at (-1, -1). */ extern const fz_rect fz_infinite_rect; +extern const fz_irect fz_infinite_irect; /* fz_is_empty_rect: Check if rectangle is empty. @@ -912,6 +926,7 @@ float fz_matrix_expansion(fz_matrix m); /* sumatrapdf */ Does not throw exceptions. */ fz_rect fz_intersect_rect(fz_rect a, fz_rect b); +fz_irect fz_intersect_irect(fz_irect a, fz_irect b); /* fz_union_rect: Compute union of two rectangles. @@ -938,7 +953,7 @@ fz_rect fz_union_rect(fz_rect a, fz_rect b); Does not throw exceptions. */ -fz_rect fz_rect_covering_rect(fz_rect rect); +fz_irect fz_rect_covering_rect(fz_rect rect); /* fz_round_rect: Round rectangle coordinates. @@ -956,7 +971,9 @@ fz_rect fz_rect_covering_rect(fz_rect rect); Does not throw exceptions. */ -fz_rect fz_round_rect(fz_rect rect); +fz_irect fz_round_rect(fz_rect rect); + +fz_rect fz_rect_from_irect(fz_irect rect); /* fz_expand_rect: Expand a bbox by a given amount in all directions. @@ -973,6 +990,7 @@ fz_rect fz_expand_rect(fz_rect b, float expand); Does not throw exceptions. */ fz_rect fz_translate_rect(fz_rect a, float xoff, float yoff); +fz_irect fz_translate_irect(fz_irect a, int xoff, int yoff); /* fz_transform_point: Apply a transformation to a point. @@ -1245,7 +1263,7 @@ typedef struct fz_pixmap_s fz_pixmap; /* fz_pixmap_bbox: Return the bounding box for a pixmap. */ -fz_rect fz_pixmap_bbox(fz_context *ctx, fz_pixmap *pix); +fz_irect fz_pixmap_bbox(fz_context *ctx, fz_pixmap *pix); /* fz_pixmap_width: Return the width of the pixmap in pixels. @@ -1289,7 +1307,7 @@ fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *cs, int w, int h); Returns a pointer to the new pixmap. Throws exception on failure to allocate. */ -fz_pixmap *fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, fz_rect bbox); +fz_pixmap *fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, fz_irect bbox); /* fz_new_pixmap_with_data: Create a new pixmap, with it's origin at @@ -1328,7 +1346,7 @@ fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, i Returns a pointer to the new pixmap. Throws exception on failure to allocate. */ -fz_pixmap *fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_rect rect, unsigned char *samples); +fz_pixmap *fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_irect rect, unsigned char *samples); /* fz_keep_pixmap: Take a reference to a pixmap. @@ -1396,7 +1414,7 @@ void fz_clear_pixmap_with_value(fz_context *ctx, fz_pixmap *pix, int value); Does not throw exceptions. */ -void fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *pix, int value, fz_rect r); +void fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *pix, int value, fz_irect r); /* fz_clear_pixmap_with_value: Sets all components (including alpha) of @@ -1423,7 +1441,7 @@ void fz_invert_pixmap(fz_context *ctx, fz_pixmap *pix); Does not throw exceptions. */ -void fz_invert_pixmap_rect(fz_pixmap *image, fz_rect rect); +void fz_invert_pixmap_rect(fz_pixmap *image, fz_irect rect); /* fz_gamma_pixmap: Apply gamma correction to a pixmap. All components @@ -1624,7 +1642,7 @@ fz_device *fz_new_draw_device(fz_context *ctx, fz_pixmap *dest); clip: Bounding box to restrict any marking operations of the draw device. */ -fz_device *fz_new_draw_device_with_bbox(fz_context *ctx, fz_pixmap *dest, fz_rect clip); +fz_device *fz_new_draw_device_with_bbox(fz_context *ctx, fz_pixmap *dest, fz_irect clip); /* Text extraction device: Used for searching, format conversion etc. diff --git a/fitz/res_font.c b/fitz/res_font.c index 1b07d060..56481962 100644 --- a/fitz/res_font.c +++ b/fitz/res_font.c @@ -887,11 +887,12 @@ fz_bound_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) } fz_pixmap * -fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_colorspace *model, fz_rect scissor) +fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_colorspace *model, fz_irect scissor) { fz_display_list *list; fz_matrix ctm; - fz_rect bbox; + fz_rect bounds; + fz_irect bbox; fz_device *dev; fz_pixmap *glyph; fz_pixmap *result; @@ -920,13 +921,10 @@ fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_co model = NULL; /* Treat as masked */ } - bbox = fz_bound_glyph(ctx, font, gid, trm); - bbox.x0 -= 1; - bbox.y0 -= 1; - bbox.x1 += 1; - bbox.y1 += 1; - - bbox = fz_intersect_rect(bbox, scissor); + bounds = fz_bound_glyph(ctx, font, gid, trm); + bounds = fz_expand_rect(bounds, 1); + bbox = fz_rect_covering_rect(bounds); + bbox = fz_intersect_irect(bbox, scissor); glyph = fz_new_pixmap_with_bbox(ctx, model ? model : fz_device_gray, bbox); fz_clear_pixmap(ctx, glyph); diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c index eb5d58ef..60e615ec 100644 --- a/fitz/res_pixmap.c +++ b/fitz/res_pixmap.c @@ -83,9 +83,8 @@ fz_new_pixmap(fz_context *ctx, fz_colorspace *colorspace, int w, int h) } fz_pixmap * -fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, fz_rect rf) +fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, fz_irect r) { - fz_rect r = fz_round_rect(rf); fz_pixmap *pixmap = fz_new_pixmap(ctx, colorspace, r.x1 - r.x0, r.y1 - r.y0); pixmap->x = r.x0; pixmap->y = r.y0; @@ -93,19 +92,18 @@ fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, fz_rect rf) } fz_pixmap * -fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_rect rf, unsigned char *samples) +fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_irect r, unsigned char *samples) { - fz_rect r = fz_round_rect(rf); fz_pixmap *pixmap = fz_new_pixmap_with_data(ctx, colorspace, r.x1 - r.x0, r.y1 - r.y0, samples); pixmap->x = r.x0; pixmap->y = r.y0; return pixmap; } -fz_rect +fz_irect fz_pixmap_bbox(fz_context *ctx, fz_pixmap *pix) { - fz_rect bbox; + fz_irect bbox; bbox.x0 = pix->x; bbox.y0 = pix->y; bbox.x1 = pix->x + pix->w; @@ -113,10 +111,10 @@ fz_pixmap_bbox(fz_context *ctx, fz_pixmap *pix) return bbox; } -fz_rect +fz_irect fz_pixmap_bbox_no_ctx(fz_pixmap *pix) { - fz_rect bbox; + fz_irect bbox; bbox.x0 = pix->x; bbox.y0 = pix->y; bbox.x1 = pix->x + pix->w; @@ -166,15 +164,14 @@ fz_clear_pixmap_with_value(fz_context *ctx, fz_pixmap *pix, int value) } void -fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, fz_rect r) +fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, fz_irect r) { const unsigned char *srcp; unsigned char *destp; int x, y, w, destspan, srcspan; - r = fz_round_rect(r); - r = fz_intersect_rect(r, fz_pixmap_bbox(ctx, dest)); - r = fz_intersect_rect(r, fz_pixmap_bbox(ctx, src)); + r = fz_intersect_irect(r, fz_pixmap_bbox(ctx, dest)); + r = fz_intersect_irect(r, fz_pixmap_bbox(ctx, src)); w = r.x1 - r.x0; y = r.y1 - r.y0; if (w <= 0 || y <= 0) @@ -267,13 +264,12 @@ fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, fz_rect r) } void -fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *dest, int value, fz_rect r) +fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *dest, int value, fz_irect r) { unsigned char *destp; int x, y, w, k, destspan; - r = fz_round_rect(r); - r = fz_intersect_rect(r, fz_pixmap_bbox(ctx, dest)); + r = fz_intersect_irect(r, fz_pixmap_bbox(ctx, dest)); w = r.x1 - r.x0; y = r.y1 - r.y0; if (w <= 0 || y <= 0) @@ -384,13 +380,12 @@ fz_invert_pixmap(fz_context *ctx, fz_pixmap *pix) } } -void fz_invert_pixmap_rect(fz_pixmap *image, fz_rect r) +void fz_invert_pixmap_rect(fz_pixmap *image, fz_irect r) { unsigned char *p; int x0, x1, y0, y1; int x, y, n; - r = fz_round_rect(r); x0 = fz_clampi(r.x0 - image->x, 0, image->w - 1); x1 = fz_clampi(r.x1 - image->x, 0, image->w - 1); y0 = fz_clampi(r.y0 - image->y, 0, image->h - 1); -- cgit v1.2.3