summaryrefslogtreecommitdiff
path: root/pdf/pdf_path.c
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2022-10-13 16:22:47 +0100
committerRobin Watts <Robin.Watts@artifex.com>2022-10-13 16:34:48 +0100
commit7b4a45aa4e582d127d2a99ac29dd7ab9c410e4b6 (patch)
tree5f4e6676dda5acf432fa75189772523f9ac3d327 /pdf/pdf_path.c
parent0b74b65ecc0f36d40b8d04a7fa1fa8b5f9d2b3ff (diff)
downloadghostpdl-7b4a45aa4e582d127d2a99ac29dd7ab9c410e4b6.tar.gz
Bug 705975: Fix hires issue with 'v' operator.
The 'v' operator constructs a path segment with the first control point equal to the current point of the path. The current PDFI code (ApplyStorePath) implements this in a very literal fashion; it asks what the current position of the path is, and then reuses that value. The problem with this is that we set points into the path (using, for example, gs_moveto or gs_lineto) and first transforms the point, then converts it to fixed point for storage. Calling gs_currentpoint therefore retrieves the fixed point value, forms the inverse matrix, and transforms it to get us back to (hopefully) the actual point we were at. Sadly, in this case, this is giving us a point that when set back into the path (using gs_curveto) is retransformed and reconverted to fixed point, giving a value fractionally different to the original one. This means that when the path is stroked, we get a very different tangent vector at the start than we should have done, resulting in different stroking effects. While it would be lovely to hope for a system when 'gs_lineto', 'gs_currentpoint', 'gs_lineto' would end up with the same point in all cases, this is probably unrealistic at such high resolutions given the nature of floating point operations. Accordingly, we opt for the simple fix of making 'ApplyStoredPath' keep track of the currentpoint pre transformation. This solves the problem nicely.
Diffstat (limited to 'pdf/pdf_path.c')
-rw-r--r--pdf/pdf_path.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/pdf/pdf_path.c b/pdf/pdf_path.c
index 56a59b07d..7195713a0 100644
--- a/pdf/pdf_path.c
+++ b/pdf/pdf_path.c
@@ -133,6 +133,7 @@ static int ApplyStoredPath(pdf_context *ctx)
int code = 0;
char *op = NULL;
double *dpts = NULL;
+ double *current;
if (ctx->PathSegments == NULL)
return 0;
@@ -150,6 +151,7 @@ static int ApplyStoredPath(pdf_context *ctx)
op = ctx->PathSegments;
dpts = ctx->PathPts;
+ current = dpts; /* Stop stupid compilers complaining. */
while (op < ctx->PathSegmentsCurrent) {
if (dpts > ctx->PathPtsCurrent) {
@@ -160,10 +162,12 @@ static int ApplyStoredPath(pdf_context *ctx)
switch(*op++) {
case pdfi_moveto_seg:
code = gs_moveto(ctx->pgs, dpts[0], dpts[1]);
+ current = dpts;
dpts+= 2;
break;
case pdfi_lineto_seg:
code = gs_lineto(ctx->pgs, dpts[0], dpts[1]);
+ current = dpts;
dpts+= 2;
break;
case pdfi_re_seg:
@@ -179,25 +183,22 @@ static int ApplyStoredPath(pdf_context *ctx)
}
}
}
+ current = dpts;
dpts+= 4;
break;
case pdfi_v_curveto_seg:
- {
- gs_point pt;
-
- code = gs_currentpoint(ctx->pgs, &pt);
- if (code >= 0) {
- code = gs_curveto(ctx->pgs, pt.x, pt.y, dpts[0], dpts[1], dpts[2], dpts[3]);
- dpts+= 4;
- }
- }
+ code = gs_curveto(ctx->pgs, current[0], current[1], dpts[0], dpts[1], dpts[2], dpts[3]);
+ current = dpts + 2;
+ dpts+= 4;
break;
case pdfi_y_curveto_seg:
code = gs_curveto(ctx->pgs, dpts[0], dpts[1], dpts[2], dpts[3], dpts[2], dpts[3]);
+ current = dpts + 2;
dpts+= 4;
break;
case pdfi_curveto_seg:
code = gs_curveto(ctx->pgs, dpts[0], dpts[1], dpts[2], dpts[3], dpts[4], dpts[5]);
+ current = dpts + 4;
dpts+= 6;
break;
case pdfi_closepath_seg: