diff options
Diffstat (limited to 'xps/xpspath.c')
-rw-r--r-- | xps/xpspath.c | 288 |
1 files changed, 136 insertions, 152 deletions
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); } |