diff options
Diffstat (limited to 'xps')
-rw-r--r-- | xps/muxps.h | 16 | ||||
-rw-r--r-- | xps/xpsglyphs.c | 53 | ||||
-rw-r--r-- | xps/xpspage.c | 9 | ||||
-rw-r--r-- | xps/xpspath.c | 288 | ||||
-rw-r--r-- | xps/xpstile.c | 15 | ||||
-rw-r--r-- | xps/xpszip.c | 2 |
6 files changed, 167 insertions, 216 deletions
diff --git a/xps/muxps.h b/xps/muxps.h index 9154316b..0bb03584 100644 --- a/xps/muxps.h +++ b/xps/muxps.h @@ -199,8 +199,8 @@ void xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char 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); void xps_parse_rectangle(xps_context *ctx, char *text, fz_rect *rect); -void xps_parse_abbreviated_geometry(xps_context *ctx, char *geom); -void xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xps_item *root, int stroking); +fz_path *xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule); +fz_path *xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xps_item *root, int stroking, int *fill_rule); 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); @@ -208,7 +208,7 @@ void xps_end_opacity(xps_context *ctx, char *base_uri, xps_resource *dict, char 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_clip(xps_context *ctx, fz_matrix ctm); +void xps_clip(xps_context *ctx, fz_matrix ctm, xps_resource *dict, char *clip_att, xps_item *clip_tag); 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); @@ -248,20 +248,10 @@ struct xps_context_s xps_hash_table *font_table; xps_hash_table *colorspace_table; - /* The fill_rule is set by path parsing. - * It is used by clip/fill functions. - * 1=nonzero, 0=evenodd - */ - int fill_rule; - /* Opacity attribute stack */ float opacity[64]; int opacity_top; - /* Current path being accumulated */ - fz_path *path; - fz_text *text; /* ... or text, for clipping brushes */ - /* Current color */ fz_colorspace *colorspace; float color[8]; diff --git a/xps/xpsglyphs.c b/xps/xpsglyphs.c index 05b12ed3..f857542c 100644 --- a/xps/xpsglyphs.c +++ b/xps/xpsglyphs.c @@ -171,12 +171,13 @@ xps_parse_glyph_metrics(char *s, float *advance, float *uofs, float *vofs) * Parse unicode and indices strings and encode glyphs. * Calculate metrics for positioning. */ -static void +static fz_text * xps_parse_glyphs_imp(xps_context *ctx, fz_matrix ctm, fz_font *font, float size, float originx, float originy, int is_sideways, int bidi_level, - char *indices, char *unicode, int is_charpath) + char *indices, char *unicode) { xps_glyph_metrics mtx; + fz_text *text; fz_matrix tm; float e, f; float x = originx; @@ -186,10 +187,7 @@ xps_parse_glyphs_imp(xps_context *ctx, fz_matrix ctm, fz_font *font, float size, int un = 0; if (!unicode && !indices) - { fz_warn("glyphs element with neither characters nor indices"); - return; - } if (us) { @@ -203,7 +201,7 @@ xps_parse_glyphs_imp(xps_context *ctx, fz_matrix ctm, fz_font *font, float size, else tm = fz_scale(size, -size); - ctx->text = fz_newtext(font, tm, is_sideways); + text = fz_newtext(font, tm, is_sideways); while ((us && un > 0) || (is && *is)) { @@ -277,11 +275,13 @@ xps_parse_glyphs_imp(xps_context *ctx, fz_matrix ctm, fz_font *font, float size, f = y - v_offset; } - fz_addtext(ctx->text, glyph_index, char_code, e, f); + fz_addtext(text, glyph_index, char_code, e, f); x += advance * 0.01 * size; } } + + return text; } void @@ -328,6 +328,7 @@ xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, int is_sideways = 0; int bidi_level = 0; + fz_text *text; fz_rect area; /* @@ -445,17 +446,16 @@ xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, } if (clip_att || clip_tag) - { - ctx->path = fz_newpath(); - if (clip_att) - xps_parse_abbreviated_geometry(ctx, clip_att); - if (clip_tag) - xps_parse_path_geometry(ctx, dict, clip_tag, 0); - xps_clip(ctx, ctm); - } + xps_clip(ctx, ctm, dict, clip_att, clip_tag); font_size = atof(font_size_att); + text = xps_parse_glyphs_imp(ctx, ctm, font, font_size, + atof(origin_x_att), atof(origin_y_att), + is_sideways, bidi_level, indices_att, unicode_att); + + area = fz_boundtext(text, ctm); + xps_begin_opacity(ctx, ctm, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); /* @@ -479,15 +479,8 @@ xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, samples[0] = atof(fill_opacity_att); xps_set_color(ctx, colorspace, samples); - xps_parse_glyphs_imp(ctx, ctm, font, font_size, - atof(origin_x_att), atof(origin_y_att), - is_sideways, bidi_level, - indices_att, unicode_att, 0); - - ctx->dev->filltext(ctx->dev->user, ctx->text, ctm, + ctx->dev->filltext(ctx->dev->user, text, ctm, ctx->colorspace, ctx->color, ctx->alpha); - fz_freetext(ctx->text); - ctx->text = nil; } /* @@ -496,23 +489,15 @@ xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, if (fill_tag) { - xps_parse_glyphs_imp(ctx, ctm, font, font_size, - 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; - + ctx->dev->cliptext(ctx->dev->user, text, ctm, 0); xps_parse_brush(ctx, ctm, area, fill_uri, dict, fill_tag); - ctx->dev->popclip(ctx->dev->user); } xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); + fz_freetext(text); + if (clip_att || clip_tag) ctx->dev->popclip(ctx->dev->user); } diff --git a/xps/xpspage.c b/xps/xpspage.c index 39731ef2..0188eb62 100644 --- a/xps/xpspage.c +++ b/xps/xpspage.c @@ -60,14 +60,7 @@ xps_parse_canvas(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource * ctm = fz_concat(transform, ctm); if (clip_att || clip_tag) - { - ctx->path = fz_newpath(); - if (clip_att) - xps_parse_abbreviated_geometry(ctx, clip_att); - if (clip_tag) - xps_parse_path_geometry(ctx, dict, clip_tag, 0); - xps_clip(ctx, ctm); - } + xps_clip(ctx, ctm, dict, clip_att, clip_tag); xps_begin_opacity(ctx, ctm, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); diff --git a/xps/xpspath.c b/xps/xpspath.c index 14de9147..d5063a87 100644 --- a/xps/xpspath.c +++ b/xps/xpspath.c @@ -36,37 +36,19 @@ fz_currentpoint(fz_path *path) } void -xps_clip(xps_context *ctx, fz_matrix ctm) +xps_clip(xps_context *ctx, fz_matrix ctm, xps_resource *dict, char *clip_att, xps_item *clip_tag) { - ctx->dev->clippath(ctx->dev->user, ctx->path, ctx->fill_rule == 0, ctm); - fz_freepath(ctx->path); - ctx->path = NULL; -} - -void -xps_fill(xps_context *ctx, fz_matrix ctm) -{ - ctx->dev->fillpath(ctx->dev->user, ctx->path, ctx->fill_rule == 0, ctm, - ctx->colorspace, ctx->color, ctx->alpha); - fz_freepath(ctx->path); - ctx->path = NULL; -} + fz_path *path; + int fill_rule = 0; -static void -xps_stroke(xps_context *ctx, fz_matrix ctm, fz_strokestate *stroke) -{ - ctx->dev->strokepath(ctx->dev->user, ctx->path, stroke, ctm, - ctx->colorspace, ctx->color, ctx->alpha); - fz_freepath(ctx->path); - ctx->path = NULL; -} - -static void -xps_clipstroke(xps_context *ctx, fz_matrix ctm, fz_strokestate *stroke) -{ - ctx->dev->clipstrokepath(ctx->dev->user, ctx->path, stroke, ctm); - fz_freepath(ctx->path); - ctx->path = NULL; + if (clip_att) + path = xps_parse_abbreviated_geometry(ctx, clip_att, &fill_rule); + else if (clip_tag) + path = xps_parse_path_geometry(ctx, dict, clip_tag, 0, &fill_rule); + else + path = fz_newpath(); + ctx->dev->clippath(ctx->dev->user, path, fill_rule, ctm); + fz_freepath(path); } /* Draw an arc segment transformed by the matrix, we approximate with straight @@ -75,7 +57,7 @@ xps_clipstroke(xps_context *ctx, fz_matrix ctm, fz_strokestate *stroke) * without transforming the line width. */ static inline void -xps_draw_arc_segment(xps_context *ctx, fz_matrix mtx, float th0, float th1, int iscw) +xps_draw_arc_segment(fz_path *path, fz_matrix mtx, float th0, float th1, int iscw) { float t, d; fz_point p; @@ -90,18 +72,18 @@ xps_draw_arc_segment(xps_context *ctx, fz_matrix mtx, float th0, float th1, int p.x = cos(th0); p.y = sin(th0); p = fz_transformpoint(mtx, p); - fz_lineto(ctx->path, p.x, p.y); + fz_lineto(path, p.x, p.y); for (t = th0; t < th1; t += d) { p.x = cos(t); p.y = sin(t); p = fz_transformpoint(mtx, p); - fz_lineto(ctx->path, p.x, p.y); + fz_lineto(path, p.x, p.y); } p.x = cos(th1); p.y = sin(th1); p = fz_transformpoint(mtx, p); - fz_lineto(ctx->path, p.x, p.y); + fz_lineto(path, p.x, p.y); } else { @@ -109,18 +91,18 @@ xps_draw_arc_segment(xps_context *ctx, fz_matrix mtx, float th0, float th1, int p.x = cos(th0); p.y = sin(th0); p = fz_transformpoint(mtx, p); - fz_lineto(ctx->path, p.x, p.y); + fz_lineto(path, p.x, p.y); for (t = th0; t > th1; t -= d) { p.x = cos(t); p.y = sin(t); p = fz_transformpoint(mtx, p); - fz_lineto(ctx->path, p.x, p.y); + fz_lineto(path, p.x, p.y); } p.x = cos(th1); p.y = sin(th1); p = fz_transformpoint(mtx, p); - fz_lineto(ctx->path, p.x, p.y); + fz_lineto(path, p.x, p.y); } } @@ -141,7 +123,7 @@ angle_between(const fz_point u, const fz_point v) } static void -xps_draw_arc(xps_context *ctx, +xps_draw_arc(fz_path *path, float size_x, float size_y, float rotation_angle, int is_large_arc, int is_clockwise, float point_x, float point_y) @@ -157,7 +139,7 @@ xps_draw_arc(xps_context *ctx, double sign; double th1, dth; - pt = fz_currentpoint(ctx->path); + pt = fz_currentpoint(path); x1 = pt.x; y1 = pt.y; x2 = point_x; @@ -181,7 +163,7 @@ xps_draw_arc(xps_context *ctx, ry = fabsf(ry); if (rx < 0.001 || ry < 0.001) { - fz_lineto(ctx->path, x2, y2); + fz_lineto(path, x2, y2); return; } @@ -241,9 +223,9 @@ xps_draw_arc(xps_context *ctx, mtx = fz_concat(fz_translate(cx, cy), mtx); mtx = fz_concat(fz_rotate(rotation_angle), mtx); mtx = fz_concat(fz_scale(rx, ry), mtx); - xps_draw_arc_segment(ctx, mtx, th1, th1 + dth, is_clockwise); + xps_draw_arc_segment(path, mtx, th1, th1 + dth, is_clockwise); - fz_lineto(ctx->path, point_x, point_y); + fz_lineto(path, point_x, point_y); } /* @@ -252,9 +234,10 @@ xps_draw_arc(xps_context *ctx, * build up a path. */ -void -xps_parse_abbreviated_geometry(xps_context *ctx, char *geom) +fz_path * +xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) { + fz_path *path; char **args; char **pargs; char *s = geom; @@ -265,6 +248,8 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom) float smooth_x, smooth_y; /* saved cubic bezier control point for smooth curves */ int reset_smooth; + path = fz_newpath(); + args = fz_calloc(strlen(geom) + 1, sizeof(char*)); pargs = args; @@ -317,49 +302,49 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom) switch (cmd) { case 'F': - ctx->fill_rule = atoi(args[i]); + *fill_rule = atoi(args[i]); i ++; break; case 'M': - fz_moveto(ctx->path, atof(args[i]), atof(args[i+1])); + fz_moveto(path, atof(args[i]), atof(args[i+1])); i += 2; break; case 'm': - pt = fz_currentpoint(ctx->path); - fz_moveto(ctx->path, pt.x + atof(args[i]), pt.y + atof(args[i+1])); + pt = fz_currentpoint(path); + fz_moveto(path, pt.x + atof(args[i]), pt.y + atof(args[i+1])); i += 2; break; case 'L': - fz_lineto(ctx->path, atof(args[i]), atof(args[i+1])); + fz_lineto(path, atof(args[i]), atof(args[i+1])); i += 2; break; case 'l': - pt = fz_currentpoint(ctx->path); - fz_lineto(ctx->path, pt.x + atof(args[i]), pt.y + atof(args[i+1])); + pt = fz_currentpoint(path); + fz_lineto(path, pt.x + atof(args[i]), pt.y + atof(args[i+1])); i += 2; break; case 'H': - pt = fz_currentpoint(ctx->path); - fz_lineto(ctx->path, atof(args[i]), pt.y); + pt = fz_currentpoint(path); + fz_lineto(path, atof(args[i]), pt.y); i += 1; break; case 'h': - pt = fz_currentpoint(ctx->path); - fz_lineto(ctx->path, pt.x + atof(args[i]), pt.y); + pt = fz_currentpoint(path); + fz_lineto(path, pt.x + atof(args[i]), pt.y); i += 1; break; case 'V': - pt = fz_currentpoint(ctx->path); - fz_lineto(ctx->path, pt.x, atof(args[i])); + pt = fz_currentpoint(path); + fz_lineto(path, pt.x, atof(args[i])); i += 1; break; case 'v': - pt = fz_currentpoint(ctx->path); - fz_lineto(ctx->path, pt.x, pt.y + atof(args[i])); + pt = fz_currentpoint(path); + fz_lineto(path, pt.x, pt.y + atof(args[i])); i += 1; break; @@ -370,7 +355,7 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom) y2 = atof(args[i+3]); x3 = atof(args[i+4]); y3 = atof(args[i+5]); - fz_curveto(ctx->path, x1, y1, x2, y2, x3, y3); + fz_curveto(path, x1, y1, x2, y2, x3, y3); i += 6; reset_smooth = 0; smooth_x = x3 - x2; @@ -378,14 +363,14 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom) break; case 'c': - pt = fz_currentpoint(ctx->path); + pt = fz_currentpoint(path); x1 = atof(args[i+0]) + pt.x; y1 = atof(args[i+1]) + pt.y; x2 = atof(args[i+2]) + pt.x; y2 = atof(args[i+3]) + pt.y; x3 = atof(args[i+4]) + pt.x; y3 = atof(args[i+5]) + pt.y; - fz_curveto(ctx->path, x1, y1, x2, y2, x3, y3); + fz_curveto(path, x1, y1, x2, y2, x3, y3); i += 6; reset_smooth = 0; smooth_x = x3 - x2; @@ -393,12 +378,12 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom) break; case 'S': - pt = fz_currentpoint(ctx->path); + pt = fz_currentpoint(path); x1 = atof(args[i+0]); y1 = atof(args[i+1]); x2 = atof(args[i+2]); y2 = atof(args[i+3]); - fz_curveto(ctx->path, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); + fz_curveto(path, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); i += 4; reset_smooth = 0; smooth_x = x2 - x1; @@ -406,12 +391,12 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom) break; case 's': - pt = fz_currentpoint(ctx->path); + pt = fz_currentpoint(path); x1 = atof(args[i+0]) + pt.x; y1 = atof(args[i+1]) + pt.y; x2 = atof(args[i+2]) + pt.x; y2 = atof(args[i+3]) + pt.y; - fz_curveto(ctx->path, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); + fz_curveto(path, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); i += 4; reset_smooth = 0; smooth_x = x2 - x1; @@ -419,49 +404,49 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom) break; case 'Q': - pt = fz_currentpoint(ctx->path); + pt = fz_currentpoint(path); x1 = atof(args[i+0]); y1 = atof(args[i+1]); x2 = atof(args[i+2]); y2 = atof(args[i+3]); - fz_curveto(ctx->path, - (pt.x + 2 * x1) / 3, (pt.y + 2 * y1) / 3, - (x2 + 2 * x1) / 3, (y2 + 2 * y1) / 3, - x2, y2); + fz_curveto(path, + (pt.x + 2 * x1) / 3, (pt.y + 2 * y1) / 3, + (x2 + 2 * x1) / 3, (y2 + 2 * y1) / 3, + x2, y2); i += 4; break; case 'q': - pt = fz_currentpoint(ctx->path); + pt = fz_currentpoint(path); x1 = atof(args[i+0]) + pt.x; y1 = atof(args[i+1]) + pt.y; x2 = atof(args[i+2]) + pt.x; y2 = atof(args[i+3]) + pt.y; - fz_curveto(ctx->path, - (pt.x + 2 * x1) / 3, (pt.y + 2 * y1) / 3, - (x2 + 2 * x1) / 3, (y2 + 2 * y1) / 3, - x2, y2); + fz_curveto(path, + (pt.x + 2 * x1) / 3, (pt.y + 2 * y1) / 3, + (x2 + 2 * x1) / 3, (y2 + 2 * y1) / 3, + x2, y2); i += 4; break; case 'A': - xps_draw_arc(ctx, - atof(args[i+0]), atof(args[i+1]), atof(args[i+2]), - atoi(args[i+3]), atoi(args[i+4]), - atof(args[i+5]), atof(args[i+6])); + xps_draw_arc(path, + atof(args[i+0]), atof(args[i+1]), atof(args[i+2]), + atoi(args[i+3]), atoi(args[i+4]), + atof(args[i+5]), atof(args[i+6])); i += 7; break; case 'a': - pt = fz_currentpoint(ctx->path); - xps_draw_arc(ctx, - atof(args[i+0]), atof(args[i+1]), atof(args[i+2]), - atoi(args[i+3]), atoi(args[i+4]), - atof(args[i+5]) + pt.x, atof(args[i+6]) + pt.y); + pt = fz_currentpoint(path); + xps_draw_arc(path, + atof(args[i+0]), atof(args[i+1]), atof(args[i+2]), + atoi(args[i+3]), atoi(args[i+4]), + atof(args[i+5]) + pt.x, atof(args[i+6]) + pt.y); i += 7; break; case 'Z': case 'z': - fz_closepath(ctx->path); + fz_closepath(path); break; default: @@ -473,10 +458,11 @@ xps_parse_abbreviated_geometry(xps_context *ctx, char *geom) } fz_free(args); + return path; } static void -xps_parse_arc_segment(xps_context *ctx, xps_item *root, int stroking, int *skipped_stroke) +xps_parse_arc_segment(fz_path *path, xps_item *root, int stroking, int *skipped_stroke) { /* ArcSegment pretty much follows the SVG algorithm for converting an * arc in endpoint representation to an arc in centerpoint @@ -516,15 +502,15 @@ xps_parse_arc_segment(xps_context *ctx, xps_item *root, int stroking, int *skipp if (stroking && !is_stroked) { - fz_moveto(ctx->path, point_x, point_y); + fz_moveto(path, point_x, point_y); return; } - xps_draw_arc(ctx, size_x, size_y, rotation_angle, is_large_arc, is_clockwise, point_x, point_y); + xps_draw_arc(path, size_x, size_y, rotation_angle, is_large_arc, is_clockwise, point_x, point_y); } static void -xps_parse_poly_quadratic_bezier_segment(xps_context *ctx, xps_item *root, int stroking, int *skipped_stroke) +xps_parse_poly_quadratic_bezier_segment(fz_path *path, xps_item *root, int stroking, int *skipped_stroke) { char *points_att = xps_att(root, "Points"); char *is_stroked_att = xps_att(root, "IsStroked"); @@ -558,12 +544,12 @@ xps_parse_poly_quadratic_bezier_segment(xps_context *ctx, xps_item *root, int st { if (stroking && !is_stroked) { - fz_moveto(ctx->path, x[1], y[1]); + fz_moveto(path, x[1], y[1]); } else { - pt = fz_currentpoint(ctx->path); - fz_curveto(ctx->path, + pt = fz_currentpoint(path); + fz_curveto(path, (pt.x + 2 * x[0]) / 3, (pt.y + 2 * y[0]) / 3, (x[1] + 2 * x[0]) / 3, (y[1] + 2 * y[0]) / 3, x[1], y[1]); @@ -574,7 +560,7 @@ xps_parse_poly_quadratic_bezier_segment(xps_context *ctx, xps_item *root, int st } static void -xps_parse_poly_bezier_segment(xps_context *ctx, xps_item *root, int stroking, int *skipped_stroke) +xps_parse_poly_bezier_segment(fz_path *path, xps_item *root, int stroking, int *skipped_stroke) { char *points_att = xps_att(root, "Points"); char *is_stroked_att = xps_att(root, "IsStroked"); @@ -606,16 +592,16 @@ xps_parse_poly_bezier_segment(xps_context *ctx, xps_item *root, int stroking, in if (n == 3) { if (stroking && !is_stroked) - fz_moveto(ctx->path, x[2], y[2]); + fz_moveto(path, x[2], y[2]); else - fz_curveto(ctx->path, x[0], y[0], x[1], y[1], x[2], y[2]); + fz_curveto(path, x[0], y[0], x[1], y[1], x[2], y[2]); n = 0; } } } static void -xps_parse_poly_line_segment(xps_context *ctx, xps_item *root, int stroking, int *skipped_stroke) +xps_parse_poly_line_segment(fz_path *path, xps_item *root, int stroking, int *skipped_stroke) { char *points_att = xps_att(root, "Points"); char *is_stroked_att = xps_att(root, "IsStroked"); @@ -641,15 +627,15 @@ xps_parse_poly_line_segment(xps_context *ctx, xps_item *root, int stroking, int while (*s == ' ') s++; sscanf(s, "%g,%g", &x, &y); if (stroking && !is_stroked) - fz_moveto(ctx->path, x, y); + fz_moveto(path, x, y); else - fz_lineto(ctx->path, x, y); + fz_lineto(path, x, y); while (*s != ' ' && *s != 0) s++; } } static void -xps_parse_path_figure(xps_context *ctx, xps_item *root, int stroking) +xps_parse_path_figure(fz_path *path, xps_item *root, int stroking) { xps_item *node; @@ -678,31 +664,31 @@ xps_parse_path_figure(xps_context *ctx, xps_item *root, int stroking) if (!stroking && !is_filled) /* not filled, when filling */ return; - fz_moveto(ctx->path, start_x, start_y); + fz_moveto(path, start_x, start_y); for (node = xps_down(root); node; node = xps_next(node)) { if (!strcmp(xps_tag(node), "ArcSegment")) - xps_parse_arc_segment(ctx, node, stroking, &skipped_stroke); + xps_parse_arc_segment(path, node, stroking, &skipped_stroke); if (!strcmp(xps_tag(node), "PolyBezierSegment")) - xps_parse_poly_bezier_segment(ctx, node, stroking, &skipped_stroke); + xps_parse_poly_bezier_segment(path, node, stroking, &skipped_stroke); if (!strcmp(xps_tag(node), "PolyLineSegment")) - xps_parse_poly_line_segment(ctx, node, stroking, &skipped_stroke); + xps_parse_poly_line_segment(path, node, stroking, &skipped_stroke); if (!strcmp(xps_tag(node), "PolyQuadraticBezierSegment")) - xps_parse_poly_quadratic_bezier_segment(ctx, node, stroking, &skipped_stroke); + xps_parse_poly_quadratic_bezier_segment(path, node, stroking, &skipped_stroke); } if (is_closed) { if (stroking && skipped_stroke) - fz_lineto(ctx->path, start_x, start_y); /* we've skipped using fz_moveto... */ + fz_lineto(path, start_x, start_y); /* we've skipped using fz_moveto... */ else - fz_closepath(ctx->path); /* no skipped segments, safe to closepath properly */ + fz_closepath(path); /* no skipped segments, safe to closepath properly */ } } -void -xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xps_item *root, int stroking) +fz_path * +xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xps_item *root, int stroking, int *fill_rule) { xps_item *node; @@ -714,6 +700,7 @@ xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xps_item *root, in xps_item *figures_tag = NULL; /* only used by resource */ fz_matrix transform; + fz_path *path; figures_att = xps_att(root, "Figures"); fill_rule_att = xps_att(root, "FillRule"); @@ -731,9 +718,9 @@ xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xps_item *root, in if (fill_rule_att) { if (!strcmp(fill_rule_att, "NonZero")) - ctx->fill_rule = 1; + *fill_rule = 1; if (!strcmp(fill_rule_att, "EvenOdd")) - ctx->fill_rule = 0; + *fill_rule = 0; } transform = fz_identity; @@ -743,18 +730,23 @@ xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xps_item *root, in xps_parse_matrix_transform(ctx, transform_tag, &transform); if (figures_att) - xps_parse_abbreviated_geometry(ctx, figures_att); + path = xps_parse_abbreviated_geometry(ctx, figures_att, fill_rule); + else + path = fz_newpath(); + if (figures_tag) - xps_parse_path_figure(ctx, figures_tag, stroking); + xps_parse_path_figure(path, figures_tag, stroking); for (node = xps_down(root); node; node = xps_next(node)) { if (!strcmp(xps_tag(node), "PathFigure")) - xps_parse_path_figure(ctx, node, stroking); + xps_parse_path_figure(path, node, stroking); } if (transform_att || transform_tag) - fz_transformpath(ctx->path, transform); + fz_transformpath(path, transform); + + return path; } static int @@ -815,9 +807,9 @@ 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_path *path; fz_rect area; - - ctx->fill_rule = 0; + int fill_rule; /* * Extract attributes and extended attributes. @@ -871,6 +863,9 @@ xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *di * Act on the information we have gathered: */ + if (!data_att && !data_tag) + return; + if (fill_tag && !strcmp(xps_tag(fill_tag), "SolidColorBrush")) { fill_opacity_att = xps_att(fill_tag, "Opacity"); @@ -932,14 +927,18 @@ xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *di ctm = fz_concat(transform, ctm); if (clip_att || clip_tag) - { - ctx->path = fz_newpath(); - if (clip_att) - xps_parse_abbreviated_geometry(ctx, clip_att); - if (clip_tag) - xps_parse_path_geometry(ctx, dict, clip_tag, 0); - xps_clip(ctx, ctm); - } + xps_clip(ctx, ctm, dict, clip_att, clip_tag); + + fill_rule = 0; + if (data_att) + path = xps_parse_abbreviated_geometry(ctx, data_att, &fill_rule); + else if (data_tag) + path = xps_parse_path_geometry(ctx, dict, data_tag, 0, &fill_rule); + + if (stroke_att || stroke_tag) + area = fz_boundpath(path, &stroke, ctm); + else + area = fz_boundpath(path, NULL, ctm); xps_begin_opacity(ctx, ctm, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); @@ -950,26 +949,15 @@ xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *di samples[0] = atof(fill_opacity_att); xps_set_color(ctx, colorspace, samples); - ctx->path = fz_newpath(); - if (data_att) - xps_parse_abbreviated_geometry(ctx, data_att); - if (data_tag) - xps_parse_path_geometry(ctx, dict, data_tag, 0); - - xps_fill(ctx, ctm); + ctx->dev->fillpath(ctx->dev->user, path, fill_rule == 0, ctm, + ctx->colorspace, ctx->color, ctx->alpha); } if (fill_tag) { - ctx->path = fz_newpath(); - if (data_att) - xps_parse_abbreviated_geometry(ctx, data_att); - if (data_tag) - xps_parse_path_geometry(ctx, dict, data_tag, 0); + area = fz_boundpath(path, NULL, ctm); - area = fz_boundpath(ctx->path, NULL, ctm); - - xps_clip(ctx, ctm); + ctx->dev->clippath(ctx->dev->user, path, fill_rule == 0, ctm); xps_parse_brush(ctx, ctm, area, fill_uri, dict, fill_tag); ctx->dev->popclip(ctx->dev->user); } @@ -981,32 +969,28 @@ xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *di samples[0] = atof(stroke_opacity_att); xps_set_color(ctx, colorspace, samples); - ctx->path = fz_newpath(); - if (data_att) - xps_parse_abbreviated_geometry(ctx, data_att); - if (data_tag) - xps_parse_path_geometry(ctx, dict, data_tag, 1); - - xps_stroke(ctx, ctm, &stroke); + ctx->dev->strokepath(ctx->dev->user, path, &stroke, ctm, + ctx->colorspace, ctx->color, ctx->alpha); } if (stroke_tag) { - ctx->path = fz_newpath(); + path = fz_newpath(); if (data_att) - xps_parse_abbreviated_geometry(ctx, data_att); + xps_parse_abbreviated_geometry(ctx, data_att, &fill_rule); if (data_tag) - xps_parse_path_geometry(ctx, dict, data_tag, 1); + xps_parse_path_geometry(ctx, dict, data_tag, 1, &fill_rule); - area = fz_boundpath(ctx->path, &stroke, ctm); - - xps_clipstroke(ctx, ctm, &stroke); + ctx->dev->clipstrokepath(ctx->dev->user, path, &stroke, ctm); xps_parse_brush(ctx, ctm, area, stroke_uri, dict, stroke_tag); ctx->dev->popclip(ctx->dev->user); } xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); + fz_freepath(path); + path = NULL; + if (clip_att || clip_tag) ctx->dev->popclip(ctx->dev->user); } diff --git a/xps/xpstile.c b/xps/xpstile.c index 59cf2f09..dedb0a3d 100644 --- a/xps/xpstile.c +++ b/xps/xpstile.c @@ -20,13 +20,14 @@ struct closure static void xps_paint_tiling_brush_clipped(xps_context *ctx, fz_matrix ctm, fz_rect viewbox, struct closure *c) { - ctx->path = fz_newpath(); - fz_moveto(ctx->path, viewbox.x0, viewbox.y0); - fz_lineto(ctx->path, viewbox.x0, viewbox.y1); - fz_lineto(ctx->path, viewbox.x1, viewbox.y1); - fz_lineto(ctx->path, viewbox.x1, viewbox.y0); - fz_closepath(ctx->path); - xps_clip(ctx, ctm); + fz_path *path = fz_newpath(); + fz_moveto(path, viewbox.x0, viewbox.y0); + fz_lineto(path, viewbox.x0, viewbox.y1); + fz_lineto(path, viewbox.x1, viewbox.y1); + fz_lineto(path, viewbox.x1, viewbox.y0); + fz_closepath(path); + + ctx->dev->clippath(ctx->dev->user, path, 0, ctm); c->func(ctx, ctm, c->base_uri, c->dict, c->root, c->user); diff --git a/xps/xpszip.c b/xps/xpszip.c index 069c83ea..0646b89f 100644 --- a/xps/xpszip.c +++ b/xps/xpszip.c @@ -498,8 +498,6 @@ xps_new_context(void) ctx->start_part = NULL; - ctx->fill_rule = 0; - return ctx; } |