diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2011-04-01 14:51:57 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2011-04-01 14:51:57 +0200 |
commit | 706c332d78120675f26164c93f59f8f16b3a885e (patch) | |
tree | 9ebffb1d1b8ef6582597cc6965f4e4634174f2e2 | |
parent | 324d663baa86f9355f7a336b60f706ce31d4f9ca (diff) | |
download | mupdf-706c332d78120675f26164c93f59f8f16b3a885e.tar.xz |
xps: Repeat enough tiles to cover the shape being filled.
-rw-r--r-- | xps/muxps.h | 10 | ||||
-rw-r--r-- | xps/xpscommon.c | 6 | ||||
-rw-r--r-- | xps/xpsglyphs.c | 6 | ||||
-rw-r--r-- | xps/xpsgradient.c | 161 | ||||
-rw-r--r-- | xps/xpsimage.c | 5 | ||||
-rw-r--r-- | xps/xpsopacity.c | 29 | ||||
-rw-r--r-- | xps/xpspath.c | 14 | ||||
-rw-r--r-- | xps/xpstile.c | 39 | ||||
-rw-r--r-- | xps/xpsvisual.c | 6 |
9 files changed, 58 insertions, 218 deletions
diff --git a/xps/muxps.h b/xps/muxps.h index f135b875..9154316b 100644 --- a/xps/muxps.h +++ b/xps/muxps.h @@ -189,12 +189,12 @@ void xps_parse_canvas(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resou void xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); void xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); void xps_parse_solid_color_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); -void xps_parse_image_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); -void xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); +void xps_parse_image_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xps_item *node); +void xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xps_item *node); void xps_parse_linear_gradient_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); void xps_parse_radial_gradient_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); -void xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *root, void(*func)(xps_context*, fz_matrix, char*, xps_resource*, xps_item*, void*), void *user); +void xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xps_item *root, void(*func)(xps_context*, fz_matrix, char*, xps_resource*, xps_item*, void*), void *user); void xps_parse_matrix_transform(xps_context *ctx, xps_item *root, fz_matrix *matrix); void xps_parse_render_transform(xps_context *ctx, char *text, fz_matrix *matrix); @@ -205,12 +205,10 @@ void xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xps_item *roo void xps_begin_opacity(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, char *opacity_att, xps_item *opacity_mask_tag); void xps_end_opacity(xps_context *ctx, char *base_uri, xps_resource *dict, char *opacity_att, xps_item *opacity_mask_tag); -void xps_parse_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); +void xps_parse_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xps_item *node); void xps_parse_element(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node); -void xps_fill(xps_context *ctx, fz_matrix ctm); void xps_clip(xps_context *ctx, fz_matrix ctm); -void xps_bounds_in_user_space(xps_context *ctx, fz_rect *user); int xps_element_has_transparency(xps_context *ctx, char *base_uri, xps_item *node); int xps_resource_dictionary_has_transparency(xps_context *ctx, char *base_uri, xps_item *node); diff --git a/xps/xpscommon.c b/xps/xpscommon.c index d338ffaa..3213f3e9 100644 --- a/xps/xpscommon.c +++ b/xps/xpscommon.c @@ -2,13 +2,13 @@ #include "muxps.h" void -xps_parse_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *node) +xps_parse_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xps_item *node) { /* SolidColorBrushes are handled in a special case and will never show up here */ if (!strcmp(xps_tag(node), "ImageBrush")) - xps_parse_image_brush(ctx, ctm, base_uri, dict, node); + xps_parse_image_brush(ctx, ctm, area, base_uri, dict, node); else if (!strcmp(xps_tag(node), "VisualBrush")) - xps_parse_visual_brush(ctx, ctm, base_uri, dict, node); + xps_parse_visual_brush(ctx, ctm, area, base_uri, dict, node); else if (!strcmp(xps_tag(node), "LinearGradientBrush")) xps_parse_linear_gradient_brush(ctx, ctm, base_uri, dict, node); else if (!strcmp(xps_tag(node), "RadialGradientBrush")) diff --git a/xps/xpsglyphs.c b/xps/xpsglyphs.c index 372cf222..05b12ed3 100644 --- a/xps/xpsglyphs.c +++ b/xps/xpsglyphs.c @@ -328,6 +328,8 @@ xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, int is_sideways = 0; int bidi_level = 0; + fz_rect area; + /* * Extract attributes and extended attributes. */ @@ -498,11 +500,13 @@ xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, atof(origin_x_att), atof(origin_y_att), is_sideways, bidi_level, indices_att, unicode_att, 1); + area = fz_boundtext(ctx->text, ctm); + ctx->dev->cliptext(ctx->dev->user, ctx->text, ctm, 0); fz_freetext(ctx->text); ctx->text = nil; - xps_parse_brush(ctx, ctm, fill_uri, dict, fill_tag); + xps_parse_brush(ctx, ctm, area, fill_uri, dict, fill_tag); ctx->dev->popclip(ctx->dev->user); } diff --git a/xps/xpsgradient.c b/xps/xpsgradient.c index c1b45e93..340528bb 100644 --- a/xps/xpsgradient.c +++ b/xps/xpsgradient.c @@ -301,15 +301,11 @@ xps_draw_radial_gradient(xps_context *ctx, fz_matrix ctm, struct stop *stops, int count, xps_item *root, int spread) { - fz_rect bbox; float x0, y0, r0; float x1, y1, r1; float xrad = 1; float yrad = 1; float invscale; - float dx, dy; - int i; - int done; char *center_att = xps_att(root, "Center"); char *origin_att = xps_att(root, "GradientOrigin"); @@ -335,99 +331,7 @@ xps_draw_radial_gradient(xps_context *ctx, fz_matrix ctm, r0 = 0.0; r1 = xrad; - dx = x1 - x0; - dy = y1 - y0; - xps_draw_one_radial_gradient(ctx, ctm, stops, count, 1, x0, y0, r0, x1, y1, r1); - -#if 0 - xps_bounds_in_user_space(ctx, &bbox); - - if (spread == SPREAD_PAD) - { - if (!point_inside_circle(x0, y0, x1, y1, r1)) - { - float in[1]; - float out[4]; - float fary[10]; - void *vary[1]; - - /* PDF shadings with extend doesn't work the same way as XPS - * gradients when the radial shading is a cone. In this case - * we fill the background ourselves. - */ - in[0] = 1.0; - out[0] = 1.0; - out[1] = 0.0; - out[2] = 0.0; - out[3] = 0.0; - if (ctx->opacity_only) - gs_function_evaluate(func, in, out); - else - gs_function_evaluate(func, in, out + 1); - - xps_set_color(ctx, ctx->srgb, out); - - gs_moveto(ctx->pgs, bbox.p.x, bbox.p.y); - gs_lineto(ctx->pgs, bbox.q.x, bbox.p.y); - gs_lineto(ctx->pgs, bbox.q.x, bbox.q.y); - gs_lineto(ctx->pgs, bbox.p.x, bbox.q.y); - gs_closepath(ctx->pgs); - gs_fill(ctx->pgs); - - /* We also have to reverse the direction so the bigger circle - * comes first or the graphical results do not match. We also - * have to reverse the direction of the function to compensate. - */ - -// reverse = xps_reverse_function(ctx, func, fary, vary); -// xps_draw_one_radial_gradient(ctx, reverse, 1, x1, y1, r1, x0, y0, r0); - xps_draw_one_radial_gradient(ctx, ctm, stops, count, - 1, x1, y1, r1, x0, y0, r0); - } - else - { - xps_draw_one_radial_gradient(ctx, ctm, stops, count, - 1, x0, y0, r0, x1, y1, r1); - } - } - else - { - for (i = 0; i < 2; i++) - { - /* Draw current circle */ - - if (!point_inside_circle(x0, y0, x1, y1, r1)) - printf("xps: we should reverse gradient here too\n"); - - if (spread == SPREAD_REFLECT && (i & 1)) - xps_draw_one_radial_gradient(ctx, ctm, stops, count, - 0, x1, y1, r1, x0, y0, r0); - else - xps_draw_one_radial_gradient(ctx, ctm, stops, count, - 0, x0, y0, r0, x1, y1, r1); - - /* Check if circle encompassed the entire bounding box (break loop if we do) */ - done = 1; - if (!point_inside_circle(bbox.x0, bbox.y0, x1, y1, r1)) done = 0; - if (!point_inside_circle(bbox.x0, bbox.y1, x1, y1, r1)) done = 0; - if (!point_inside_circle(bbox.x1, bbox.y1, x1, y1, r1)) done = 0; - if (!point_inside_circle(bbox.x1, bbox.y0, x1, y1, r1)) done = 0; - if (done) - break; - - /* Prepare next circle */ - - r0 = r1; - r1 += xrad; - - x0 += dx; - y0 += dy; - x1 += dx; - y1 += dy; - } - } -#endif } /* @@ -440,77 +344,20 @@ xps_draw_linear_gradient(xps_context *ctx, fz_matrix ctm, struct stop *stops, int count, xps_item *root, int spread) { - fz_rect bbox; float x0, y0, x1, y1; - float dx, dy; - int i; char *start_point_att = xps_att(root, "StartPoint"); char *end_point_att = xps_att(root, "EndPoint"); - x0 = 0; - y0 = 0; - x1 = 0; - y1 = 1; + x0 = y0 = 0; + x1 = y1 = 1; if (start_point_att) sscanf(start_point_att, "%g,%g", &x0, &y0); if (end_point_att) sscanf(end_point_att, "%g,%g", &x1, &y1); - dx = x1 - x0; - dy = y1 - y0; - xps_draw_one_linear_gradient(ctx, ctm, stops, count, 1, x0, y0, x1, y1); - -#if 0 - xps_bounds_in_user_space(ctx, &bbox); - - if (spread == SPREAD_PAD) - { - xps_draw_one_linear_gradient(ctx, ctm, stops, count, 1, x0, y0, x1, y1); - } - else - { - float len; - float a, b; - float dist[4]; - float d0, d1; - int i0, i1; - - len = sqrt(dx * dx + dy * dy); - a = dx / len; - b = dy / len; - - dist[0] = a * (bbox.x0 - x0) + b * (bbox.y0 - y0); - dist[1] = a * (bbox.x0 - x0) + b * (bbox.y1 - y0); - dist[2] = a * (bbox.x1 - x0) + b * (bbox.y1 - y0); - dist[3] = a * (bbox.x1 - x0) + b * (bbox.y0 - y0); - - d0 = dist[0]; - d1 = dist[0]; - for (i = 1; i < 4; i++) - { - if (dist[i] < d0) d0 = dist[i]; - if (dist[i] > d1) d1 = dist[i]; - } - - i0 = floor(d0 / len); - i1 = ceil(d1 / len); - - for (i = i0; i < i1; i++) - { - if (spread == SPREAD_REFLECT && (i & 1)) - xps_draw_one_linear_gradient(ctx, ctm, stops, count, 0, - x1 + dx * i, y1 + dy * i, - x0 + dx * i, y0 + dy * i); - else - xps_draw_one_linear_gradient(ctx, ctm, stops, count, 0, - x0 + dx * i, y0 + dy * i, - x1 + dx * i, y1 + dy * i); - } - } -#endif } /* @@ -539,8 +386,6 @@ xps_parse_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_matrix transform; int spread_method; - fz_rect bbox; - opacity_att = xps_att(root, "Opacity"); interpolation_att = xps_att(root, "ColorInterpolationMode"); spread_att = xps_att(root, "SpreadMethod"); @@ -591,8 +436,6 @@ xps_parse_gradient_brush(xps_context *ctx, fz_matrix ctm, return; } - xps_bounds_in_user_space(ctx, &bbox); - xps_begin_opacity(ctx, ctm, base_uri, dict, opacity_att, NULL); draw(ctx, ctm, stop_list, stop_count, root, spread_method); diff --git a/xps/xpsimage.c b/xps/xpsimage.c index 8fc2f7a1..102051cb 100644 --- a/xps/xpsimage.c +++ b/xps/xpsimage.c @@ -105,7 +105,8 @@ xps_find_image_brush_source_part(xps_context *ctx, char *base_uri, xps_item *roo } void -xps_parse_image_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *root) +xps_parse_image_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, + char *base_uri, xps_resource *dict, xps_item *root) { xps_part *part; xps_image *image; @@ -123,7 +124,7 @@ xps_parse_image_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resou return; } - xps_parse_tiling_brush(ctx, ctm, base_uri, dict, root, xps_paint_image_brush, image); + xps_parse_tiling_brush(ctx, ctm, area, base_uri, dict, root, xps_paint_image_brush, image); xps_free_image(ctx, image); xps_free_part(ctx, part); diff --git a/xps/xpsopacity.c b/xps/xpsopacity.c index 51a356e3..db7bc400 100644 --- a/xps/xpsopacity.c +++ b/xps/xpsopacity.c @@ -2,31 +2,10 @@ #include "muxps.h" void -xps_bounds_in_user_space(xps_context *ctx, fz_rect *ubox) -{ - *ubox = fz_infiniterect; // *evil grin* -#if 0 - gx_clip_path *clip_path; - fz_rect dbox; - int code; - - code = gx_effective_clip_path(ctx->pgs, &clip_path); - if (code < 0) - fz_warn("gx_effective_clip_path failed"); - - dbox.p.x = fixed2float(clip_path->outer_box.p.x); - dbox.p.y = fixed2float(clip_path->outer_box.p.y); - dbox.q.x = fixed2float(clip_path->outer_box.q.x); - dbox.q.y = fixed2float(clip_path->outer_box.q.y); - gs_bbox_transform_inverse(&dbox, &ctm_only(ctx->pgs), ubox); -#endif -} - -void xps_begin_opacity(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, char *opacity_att, xps_item *opacity_mask_tag) { - fz_rect bbox; + fz_rect area; float opacity; if (!opacity_att && !opacity_mask_tag) @@ -52,7 +31,7 @@ xps_begin_opacity(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource opacity_mask_tag = NULL; } - xps_bounds_in_user_space(ctx, &bbox); + area = fz_infiniterect; /* FIXME */ if (ctx->opacity_top + 1 < nelem(ctx->opacity)) { @@ -62,8 +41,8 @@ xps_begin_opacity(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource if (opacity_mask_tag) { - ctx->dev->beginmask(ctx->dev->user, bbox, 0, NULL, NULL); - xps_parse_brush(ctx, ctm, base_uri, dict, opacity_mask_tag); + ctx->dev->beginmask(ctx->dev->user, area, 0, NULL, NULL); + xps_parse_brush(ctx, ctm, area, base_uri, dict, opacity_mask_tag); ctx->dev->endmask(ctx->dev->user); } } diff --git a/xps/xpspath.c b/xps/xpspath.c index dd0d2ef3..14de9147 100644 --- a/xps/xpspath.c +++ b/xps/xpspath.c @@ -815,6 +815,7 @@ xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *di fz_matrix transform; float samples[32]; fz_colorspace *colorspace; + fz_rect area; ctx->fill_rule = 0; @@ -966,10 +967,10 @@ xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *di if (data_tag) xps_parse_path_geometry(ctx, dict, data_tag, 0); - xps_clip(ctx, ctm); - - xps_parse_brush(ctx, ctm, fill_uri, dict, fill_tag); + area = fz_boundpath(ctx->path, NULL, ctm); + xps_clip(ctx, ctm); + xps_parse_brush(ctx, ctm, area, fill_uri, dict, fill_tag); ctx->dev->popclip(ctx->dev->user); } @@ -997,11 +998,10 @@ xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *di if (data_tag) xps_parse_path_geometry(ctx, dict, data_tag, 1); - ctx->fill_rule = 1; /* over-ride fill rule when converting outline to stroked */ - xps_clipstroke(ctx, ctm, &stroke); - - xps_parse_brush(ctx, ctm, stroke_uri, dict, stroke_tag); + area = fz_boundpath(ctx->path, &stroke, ctm); + xps_clipstroke(ctx, ctm, &stroke); + xps_parse_brush(ctx, ctm, area, stroke_uri, dict, stroke_tag); ctx->dev->popclip(ctx->dev->user); } diff --git a/xps/xpstile.c b/xps/xpstile.c index baa274e6..59cf2f09 100644 --- a/xps/xpstile.c +++ b/xps/xpstile.c @@ -63,7 +63,7 @@ xps_paint_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect viewbox, int til } void -xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, +xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xps_item *root, void (*func)(xps_context*, fz_matrix, char*, xps_resource*, xps_item*, void*), void *user) { @@ -83,7 +83,8 @@ xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_matrix transform; fz_rect viewbox; fz_rect viewport; - float scalex, scaley; + float xstep, ystep; + float xscale, yscale; int tile_mode; opacity_att = xps_att(root, "Opacity"); @@ -130,8 +131,11 @@ xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, if (fabs(viewbox.x1 - viewbox.x0) < 0.01) return; if (fabs(viewbox.y1 - viewbox.y0) < 0.01) return; - scalex = (viewport.x1 - viewport.x0) / (viewbox.x1 - viewbox.x0); - scaley = (viewport.y1 - viewport.y0) / (viewbox.y1 - viewbox.y0); + xstep = viewbox.x1 - viewbox.x0; + ystep = viewbox.y1 - viewbox.y0; + + xscale = (viewport.x1 - viewport.x0) / xstep; + yscale = (viewport.y1 - viewport.y0) / ystep; tile_mode = TILE_NONE; if (tile_mode_att) @@ -148,26 +152,35 @@ xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, tile_mode = TILE_FLIP_X_Y; } + if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y) + xstep *= 2; + if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y) + ystep *= 2; + xps_begin_opacity(ctx, ctm, base_uri, dict, opacity_att, NULL); ctm = fz_concat(transform, ctm); ctm = fz_concat(fz_translate(viewport.x0, viewport.y0), ctm); - ctm = fz_concat(fz_scale(scalex, scaley), ctm); + ctm = fz_concat(fz_scale(xscale, yscale), ctm); ctm = fz_concat(fz_translate(-viewbox.x0, -viewbox.y0), ctm); - if (tile_mode != TILE_NONE) + if (tile_mode != TILE_NONE && !fz_isinfiniterect(area)) { - float w = viewbox.x1 - viewbox.x0; - float h = viewbox.y1 - viewbox.y0; - fz_matrix ttm; + fz_matrix invctm = fz_invertmatrix(ctm); + fz_rect bbox = fz_transformrect(invctm, area); + int x0 = floorf(bbox.x0 / xstep); + int y0 = floorf(bbox.y0 / ystep); + int x1 = ceilf(bbox.x1 / xstep); + int y1 = ceilf(bbox.y1 / ystep); int x, y; - /* TODO: loop in visible area */ - for (y = 0; y < 2; y++) + printf("repeating tile %d x %d times\n", x1-x0, y1-y0); + + for (y = y0; y < y1; y++) { - for (x = 0; x < 2; x++) + for (x = x0; x < x1; x++) { - ttm = fz_concat(fz_translate(w*x, h*y), ctm); + fz_matrix ttm = fz_concat(fz_translate(xstep * x, ystep * y), ctm); xps_paint_tiling_brush(ctx, ttm, viewbox, tile_mode, &c); } } diff --git a/xps/xpsvisual.c b/xps/xpsvisual.c index 82d37691..ad633708 100644 --- a/xps/xpsvisual.c +++ b/xps/xpsvisual.c @@ -11,7 +11,8 @@ xps_paint_visual_brush(xps_context *ctx, fz_matrix ctm, } void -xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xps_item *root) +xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, + char *base_uri, xps_resource *dict, xps_item *root) { xps_item *node; @@ -32,6 +33,7 @@ xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_reso if (visual_tag) { - xps_parse_tiling_brush(ctx, ctm, visual_uri, dict, root, xps_paint_visual_brush, visual_tag); + xps_parse_tiling_brush(ctx, ctm, area, + visual_uri, dict, root, xps_paint_visual_brush, visual_tag); } } |