summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2011-04-01 14:51:57 +0200
committerTor Andersson <tor.andersson@artifex.com>2011-04-01 14:51:57 +0200
commit706c332d78120675f26164c93f59f8f16b3a885e (patch)
tree9ebffb1d1b8ef6582597cc6965f4e4634174f2e2
parent324d663baa86f9355f7a336b60f706ce31d4f9ca (diff)
downloadmupdf-706c332d78120675f26164c93f59f8f16b3a885e.tar.xz
xps: Repeat enough tiles to cover the shape being filled.
-rw-r--r--xps/muxps.h10
-rw-r--r--xps/xpscommon.c6
-rw-r--r--xps/xpsglyphs.c6
-rw-r--r--xps/xpsgradient.c161
-rw-r--r--xps/xpsimage.c5
-rw-r--r--xps/xpsopacity.c29
-rw-r--r--xps/xpspath.c14
-rw-r--r--xps/xpstile.c39
-rw-r--r--xps/xpsvisual.c6
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);
}
}