[gs-cvs] rev 7021 - trunk/gs/src
leonardo at ghostscript.com
leonardo at ghostscript.com
Mon Sep 4 05:50:37 PDT 2006
Author: leonardo
Date: 2006-09-04 05:50:36 -0700 (Mon, 04 Sep 2006)
New Revision: 7021
Modified:
trunk/gs/src/gxpath.c
trunk/gs/src/gxpath.h
trunk/gs/src/gxpcopy.c
trunk/gs/src/gxpdash.c
trunk/gs/src/gxstroke.c
trunk/gs/src/gzpath.h
trunk/gs/src/lib.mak
Log:
Fix (stroking) : Zero lengh dashes have been missed, part 1.
DETAILS :
Bug 688838 "stroking: A zero length dash missed".
Bug 687720 "Zero length lines must not stroke" (recently reopened).
This patch defines a new path element type dash_segment,
and uses it for internal needs of the stroking algorithm.
The old code skipped zero length dashes with a non-round cap.
It appears incompatible to Adobe CPSI.
The new code renders zero length dashes with any cap type,
if the path is not degenerate.
The new type of path segment works for storing the path tangent
at the dash start point. The tangent can't represent with a small line segment
(as it tried in old hacks) due to insufficient precision of 'fixed'.
In subpath_expand_dashes the branch "within epsilon of the end
of the dash element" have been changed for a better Adobe compatibility
with looking ahead for a zero length dash pattern.
When a zero length dash fall to a path corner,
the old code choosen the direction of the next segment (after the corner).
The new code (as Adobe compatibile) chooses the direction of the last segment
(before the corner).
In the old code of gx_stroke_path_only_aux we don't understand the branch
"if (pgs_lp->dot_length != 0) break;"
It look contradicting to the comment above it.
Leaving it as it is, but the condition has been changed to
(pgs_lp->dot_length != 0 && pseg->type != s_dash)
to comply with the new logic. Likely dot_length is now a rudiment.
The old code arbitrary applied a horizontal stroke adjustment for
zero length dashes. The new code uses the direction of the path tangent.
Due to that some dashes got ununiform shapes, and we improved
the stroke adjustment against undiserable regression with PixelisAd.pdf.
The new code adjusts horizontal and vertical strokes,
each stroke by both directions X and Y, if the dash length
is greater than 1 pixel, and the dash is isolated.
Otherwise the transversal adjustment applies only.
The old code did not render zero length subpathes
when .setdotlength was called with a non-zero argument.
It happens since Revision 4173.
The new code restores the correct behavior, which is important
for the PCL interpreter.
An unfixed problem :
When a dash pattern is very short,
the last dash of a segment appears ununiform due
to accumulating a significant rounding error.
This problem to be fixed separately in order to
simplify the regression analyzis.
Note that this patch doesn't provide an HP LazerJet compatibility,
which orients zero length dashes at path corner differently than Adobe.
Also HP LazerJet doesn't paint zero length pathes with round caps as PLRM3 specifies.
EXPECTED DIFFERENCES :
normal 300 dpi :
"H:\AuxFiles\CompareFiles\013-13.ps"
"H:\AuxFiles\CompareFiles\014-05.ps"
"H:\AuxFiles\CompareFiles\015-05.ps"
"H:\AuxFiles\CompareFiles\027-09.ps"
"H:\AuxFiles\CompareFiles\083-13.ps"
"H:\AuxFiles\CompareFiles\205-13.ps"
"H:\AuxFiles\CompareFiles\a.pdf"
"H:\AuxFiles\CompareFiles\Bug687660a.ps"
"H:\AuxFiles\CompareFiles\file2.pdf"
"H:\AuxFiles\CompareFiles\motor.pdf"
"H:\AuxFiles\CompareFiles\test.pdf"
"H:\AuxFiles\CompareFiles\type3xshow.eps"
normal 72 dpi :
"H:\AuxFiles\CompareFiles\012-05.ps"
"H:\AuxFiles\CompareFiles\014-05.ps"
"H:\AuxFiles\CompareFiles\014-13.ps"
"H:\AuxFiles\CompareFiles\015-05.ps"
"H:\AuxFiles\CompareFiles\034-10.ps"
"H:\AuxFiles\CompareFiles\083-13.ps"
"H:\AuxFiles\CompareFiles\169-05.ps"
"H:\AuxFiles\CompareFiles\205-05.ps"
"H:\AuxFiles\CompareFiles\222-05.ps"
"H:\AuxFiles\CompareFiles\250-01.ps"
"H:\AuxFiles\CompareFiles\298-05.ps"
"H:\AuxFiles\CompareFiles\307-01.ps"
"H:\AuxFiles\CompareFiles\321-05.ps"
"H:\AuxFiles\CompareFiles\bugsample.pdf"
"H:\AuxFiles\CompareFiles\file2.pdf"
"H:\AuxFiles\CompareFiles\PixelisAd.pdf"
"H:\AuxFiles\CompareFiles\test.pdf"
pdfwrite 300 dpi :
"H:\AuxFiles\CompareFiles\012-13.ps"
"H:\AuxFiles\CompareFiles\013-13.ps"
"H:\AuxFiles\CompareFiles\014-13.ps"
"H:\AuxFiles\CompareFiles\027-09.ps"
"H:\AuxFiles\CompareFiles\034-10.ps"
"H:\AuxFiles\CompareFiles\083-13.ps"
"H:\AuxFiles\CompareFiles\298-05.ps"
"H:\AuxFiles\CompareFiles\316-07.ps"
"H:\AuxFiles\CompareFiles\321-05.ps"
"H:\AuxFiles\CompareFiles\a.pdf"
"H:\AuxFiles\CompareFiles\Bug687660a.ps"
"H:\AuxFiles\CompareFiles\file2.pdf"
"H:\AuxFiles\CompareFiles\motor.pdf"
"H:\AuxFiles\CompareFiles\test.pdf"
"H:\AuxFiles\CompareFiles\type3xshow.eps"
pdfwrite 72 dpi :
"H:\AuxFiles\CompareFiles\012-05.ps"
"H:\AuxFiles\CompareFiles\015-05.ps"
"H:\AuxFiles\CompareFiles\083-13.ps"
"H:\AuxFiles\CompareFiles\169-05.ps"
"H:\AuxFiles\CompareFiles\222-05.ps"
"H:\AuxFiles\CompareFiles\250-01.ps"
"H:\AuxFiles\CompareFiles\307-01.ps"
"H:\AuxFiles\CompareFiles\316-07.ps"
"H:\AuxFiles\CompareFiles\bugsample.pdf"
"H:\AuxFiles\CompareFiles\file2.pdf"
"H:\AuxFiles\CompareFiles\PixelisAd.pdf"
Modified: trunk/gs/src/gxpath.c
===================================================================
--- trunk/gs/src/gxpath.c 2006-09-04 11:40:17 UTC (rev 7020)
+++ trunk/gs/src/gxpath.c 2006-09-04 12:50:36 UTC (rev 7021)
@@ -50,6 +50,7 @@
private_st_path_segments();
private_st_segment();
private_st_line();
+private_st_dash();
private_st_line_close();
private_st_curve();
private_st_subpath();
@@ -642,6 +643,28 @@
return code;
}
+/* Add a dash to the current path (lineto with a small length). */
+/* Only for internal use of the stroking algorithm. */
+int
+gx_path_add_dash_notes(gx_path * ppath, fixed x, fixed y, fixed dx, fixed dy, segment_notes notes)
+{
+ subpath *psub;
+ dash_segment *lp;
+
+ if (ppath->bbox_set)
+ check_in_bbox(ppath, x, y);
+ path_open();
+ path_alloc_segment(lp, dash_segment, &st_dash, s_dash, notes,
+ "gx_dash_add_dash");
+ path_alloc_link(lp);
+ path_set_point(lp, x, y);
+ lp->tangent.x = dx;
+ lp->tangent.y = dy;
+ path_update_draw(ppath);
+ trace_segment("[P]", (segment *) lp);
+ return 0;
+}
+
/* Add a rectangle to the current path. */
/* This is a special case of adding a closed polygon. */
int
@@ -991,6 +1014,12 @@
case s_line:
dprintf3("%s: %1.4f %1.4f lineto\n", out, px, py);
break;
+ case s_dash:{
+ const dash_segment *const pd = (const dash_segment *)pseg;
+
+ dprintf5("%s: %1.4f %1.4f %1.4f %1.4f dash\n", out, pd->pt.x, pd->pt.y, pd->tangent.x, pd->tangent.y);
+ break;
+ }
case s_line_close:{
const line_close_segment *const plc =
(const line_close_segment *)pseg;
Modified: trunk/gs/src/gxpath.h
===================================================================
--- trunk/gs/src/gxpath.h 2006-09-04 11:40:17 UTC (rev 7020)
+++ trunk/gs/src/gxpath.h 2006-09-04 12:50:36 UTC (rev 7021)
@@ -137,6 +137,7 @@
gx_path_add_point(gx_path *, fixed, fixed),
gx_path_add_relative_point(gx_path *, fixed, fixed),
gx_path_add_line_notes(gx_path *, fixed, fixed, segment_notes),
+ gx_path_add_dash_notes(gx_path * ppath, fixed x, fixed y, fixed dx, fixed dy, segment_notes notes),
gx_path_add_lines_notes(gx_path *, const gs_fixed_point *, int, segment_notes),
gx_path_add_rectangle(gx_path *, fixed, fixed, fixed, fixed),
gx_path_add_char_path(gx_path *, gx_path *, gs_char_path_mode),
Modified: trunk/gs/src/gxpcopy.c
===================================================================
--- trunk/gs/src/gxpcopy.c 2006-09-04 11:40:17 UTC (rev 7020)
+++ trunk/gs/src/gxpcopy.c 2006-09-04 12:50:36 UTC (rev 7021)
@@ -181,6 +181,14 @@
pseg->pt.x, pseg->pt.y, pseg->notes);
vd_lineto(pseg->pt.x, pseg->pt.y);
break;
+ case s_dash:
+ {
+ const dash_segment *pd = (const dash_segment *)pseg;
+
+ code = gx_path_add_dash_notes(ppath,
+ pd->pt.x, pd->pt.y, pd->tangent.x, pd->tangent.y, pseg->notes);
+ break;
+ }
case s_line_close:
code = gx_path_close_subpath(ppath);
vd_closepath;
Modified: trunk/gs/src/gxpdash.c
===================================================================
--- trunk/gs/src/gxpdash.c 2006-09-04 11:40:17 UTC (rev 7020)
+++ trunk/gs/src/gxpdash.c 2006-09-04 12:50:36 UTC (rev 7021)
@@ -18,6 +18,7 @@
#include "gsmatrix.h" /* for gscoord.h */
#include "gscoord.h"
#include "gxfixed.h"
+#include "gxarith.h"
#include "gsline.h"
#include "gzline.h"
#include "gzpath.h"
@@ -112,13 +113,20 @@
left = length;
while (left > elt_length) { /* We are using up the line segment. */
double fraction = elt_length / length;
- fixed nx = x + (fixed) (dx * fraction);
- fixed ny = y + (fixed) (dy * fraction);
+ fixed fx = (fixed) (dx * fraction);
+ fixed fy = (fixed) (dy * fraction);
+ fixed nx = x + fx;
+ fixed ny = y + fy;
if (ink_on) {
- if (drawing >= 0)
- code = gx_path_add_line_notes(ppath, nx, ny,
+ if (drawing >= 0) {
+ if (left >= elt_length && any_abs(fx) + any_abs(fy) < fixed_half)
+ code = gx_path_add_dash_notes(ppath, nx, ny, udx, udy,
+ notes & pseg->notes);
+ else
+ code = gx_path_add_line_notes(ppath, nx, ny,
notes & pseg->notes);
+ }
notes |= sn_not_first;
} else {
if (drawing > 0) /* done */
@@ -140,32 +148,57 @@
/* Handle the last dash of a segment. */
on:if (ink_on) {
if (drawing >= 0) {
- code =
- (pseg->type == s_line_close && drawing > 0 ?
- gx_path_close_subpath_notes(ppath,
- notes & pseg->notes) :
- gx_path_add_line_notes(ppath, sx, sy,
- notes & pseg->notes));
+ if (pseg->type == s_line_close && drawing > 0)
+ code = gx_path_close_subpath_notes(ppath,
+ notes & pseg->notes);
+ else if (any_abs(sx - x) + any_abs(sy - y) < fixed_half)
+ code = gx_path_add_dash_notes(ppath, sx, sy, udx, udy,
+ notes & pseg->notes);
+ else
+ code = gx_path_add_line_notes(ppath, sx, sy,
+ notes & pseg->notes);
notes |= sn_not_first;
}
} else {
code = gx_path_add_point(ppath, sx, sy);
notes &= ~sn_not_first;
if (elt_length < fixed2float(fixed_epsilon) &&
- (pseg->next == 0 || pseg->next->type == s_start)
- ) { /*
+ (pseg->next == 0 || pseg->next->type == s_start || elt_length == 0)) {
+ /*
* Ink is off, but we're within epsilon of the end
- * of the dash element, and at the end of the
- * subpath. "Stretch" a little so we get a dot.
+ * of the dash element.
+ * "Stretch" a little so we get a dot.
+ * Also if the next dash pattern is zero length,
+ * use the last segment orientation.
*/
+ double elt_length1;
+
if (code < 0)
return code;
- elt_length = 0;
- ink_on = true;
if (++index == count)
index = 0;
- elt_length = pattern[index] * scale;
- goto on;
+ elt_length1 = pattern[index] * scale;
+ if (pseg->next == 0 || pseg->next->type == s_start) {
+ elt_length = elt_length1;
+ left = 0;
+ ink_on = true;
+ goto on;
+ }
+ /* Looking ahead one dash pattern element.
+ If it is zero length, apply to the current segment
+ (at its end). */
+ if (elt_length1 == 0) {
+ left = 0;
+ code = gx_path_add_dash_notes(ppath, sx, sy, udx, udy,
+ notes & pseg->notes);
+ if (++index == count)
+ index = 0;
+ elt_length = pattern[index] * scale;
+ ink_on = false;
+ } else if (--index == 0) {
+ /* Revert lookahead. */
+ index = count - 1;
+ }
}
if (drawing > 0) /* done */
return code;
Modified: trunk/gs/src/gxstroke.c
===================================================================
--- trunk/gs/src/gxstroke.c 2006-09-04 11:40:17 UTC (rev 7020)
+++ trunk/gs/src/gxstroke.c 2006-09-04 12:50:36 UTC (rev 7021)
@@ -114,6 +114,7 @@
goto not_exact;
break;
case s_line:
+ case s_dash:
case s_line_close:
if (!(pseg->pt.x == prev.x || pseg->pt.y == prev.y))
goto not_exact;
@@ -207,7 +208,7 @@
/* Other forward declarations */
private bool width_is_thin(pl_ptr);
-private void adjust_stroke(pl_ptr, const gs_imager_state *, bool);
+private void adjust_stroke(pl_ptr, const gs_imager_state *, bool, bool);
private int line_join_points(const gx_line_params * pgs_lp,
pl_ptr plp, pl_ptr nplp,
gs_fixed_point * join_points,
@@ -533,42 +534,56 @@
fixed y = pseg->pt.y;
bool is_closed = ((const subpath *)pseg)->is_closed;
partial_line pl, pl_prev, pl_first;
+ bool zero_length = true;
while ((pseg = pseg->next) != 0 &&
pseg->type != s_start
) {
/* Compute the width parameters in device space. */
/* We work with unscaled values, for speed. */
- fixed sx = pseg->pt.x, udx = sx - x;
- fixed sy = pseg->pt.y, udy = sy - y;
+ fixed sx, udx, sy, udy;
+ bool is_dash_segment = false;
+ d1:if (pseg->type != s_dash) {
+ sx = pseg->pt.x;
+ sy = pseg->pt.y;
+ udx = sx - x;
+ udy = sy - y;
+ } else {
+ dash_segment *pd = (dash_segment *)pseg;
+
+ sx = pd->pt.x;
+ sy = pd->pt.y;
+ udx = pd->tangent.x;
+ udy = pd->tangent.y;
+ is_dash_segment = true;
+ }
+ zero_length &= ((udx | udy) == 0);
+
pl.o.p.x = x, pl.o.p.y = y;
d:pl.e.p.x = sx, pl.e.p.y = sy;
- if (!(udx | udy)) { /* degenerate */
+ if (!(udx | udy) || pseg->type == s_dash) { /* degenerate or short */
/*
* If this is the first segment of the subpath,
* check the entire subpath for degeneracy.
* Otherwise, ignore the degenerate segment.
*/
- if (index != 0)
+ if (index != 0 && pseg->type != s_dash)
continue;
/* Check for a degenerate subpath. */
while ((pseg = pseg->next) != 0 &&
pseg->type != s_start
) {
+ if (is_dash_segment)
+ break;
+ if (pseg->type == s_dash)
+ goto d1;
sx = pseg->pt.x, udx = sx - x;
sy = pseg->pt.y, udy = sy - y;
if (udx | udy)
goto d;
}
- /*
- * The entire subpath is degenerate, but it includes
- * more than one point. If the dot length is non-zero,
- * draw the caps, otherwise do nothing.
- */
- if (pgs_lp->dot_length != 0)
- break;
- if (pgs_lp->cap != gs_cap_round) {
+ if (pgs_lp->dot_length == 0 && pgs_lp->cap != gs_cap_round && !is_dash_segment) {
/* From PLRM, stroke operator :
If a subpath is degenerate (consists of a single-point closed path
or of two or more points at the same coordinates),
@@ -576,25 +591,27 @@
break;
}
/*
- * Orient the dot according to the previous segment if
+ * If the subpath is a dash, take the orientation from the dash segmnent.
+ * Otherwise orient the dot according to the previous segment if
* any, or else the next segment if any, or else
* according to the specified dot orientation.
*/
{
const segment *end = psub->prev;
- if (end != 0 && (end->pt.x != x || end->pt.y != y))
- sx = end->pt.x, sy = end->pt.y;
+ if (is_dash_segment) {
+ /* Nothing. */
+ } else if (end != 0 && (end->pt.x != x || end->pt.y != y))
+ sx = end->pt.x, sy = end->pt.y, udx = sx - x, udy = sy - y;
else if (pseg != 0 &&
(pseg->pt.x != x || pseg->pt.y != y)
)
- sx = pseg->pt.x, sy = pseg->pt.y;
+ sx = pseg->pt.x, sy = pseg->pt.y, udx = sx - x, udy = sy - y;
}
/*
* Compute the properly oriented dot length, and then
* draw the dot like a very short line.
*/
- udx = sx - x, udy = sy - y;
if ((udx | udy) == 0) {
if (is_fzero(pgs_lp->dot_orientation.xy)) {
/* Portrait orientation, dot length = X */
@@ -604,32 +621,35 @@
udy = fixed_1;
}
}
- {
+ if (sx == x && sy == y && (pseg == NULL || pseg->type == s_start)) {
double scale = device_dot_length /
- hypot((double)udx, (double)udy);
-
+ hypot((double)udx, (double)udy);
+ fixed udx1, udy1;
/*
* If we're using butt caps, make sure the "line" is
- * long enough to show up.
+ * long enough to show up.
+ * Don't apply this with always_thin, becase
+ * draw thin line always rounds the length up.
*/
- if (pgs_lp->cap == gs_cap_butt) {
+ if (!always_thin && pgs_lp->cap == gs_cap_butt) {
fixed dmax = max(any_abs(udx), any_abs(udy));
if (dmax * scale < fixed_1)
scale = (float)fixed_1 / dmax;
}
- udx = (fixed) (udx * scale);
- udy = (fixed) (udy * scale);
- if ((udx | udy) == 0)
- udy = fixed_epsilon;
- sx = x + udx;
- sy = y + udy;
+ udx1 = (fixed) (udx * scale);
+ udy1 = (fixed) (udy * scale);
+ sx = x + udx1;
+ sy = y + udy1;
}
/*
* Back up 1 segment to keep the bookkeeping straight.
*/
pseg = (pseg != 0 ? pseg->prev : psub->last);
- goto d;
+ if (!is_dash_segment)
+ goto d;
+ pl.e.p.x = sx;
+ pl.e.p.y = sy;
}
if (always_thin) {
pl.e.cdelta.x = pl.e.cdelta.y = 0;
@@ -692,7 +712,10 @@
pl.thin = width_is_thin(&pl);
}
if (!pl.thin) {
- adjust_stroke(&pl, pis, false);
+ adjust_stroke(&pl, pis, false,
+ (pseg->prev == 0 || pseg->prev->type == s_start) &&
+ (pseg->next == 0 || pseg->next->type == s_start) &&
+ (zero_length || !is_closed));
compute_caps(&pl);
}
}
@@ -731,7 +754,7 @@
/* For some reason, the Borland compiler requires the cast */
/* in the following statement. */
pl_ptr lptr =
- (!is_closed || join == gs_join_none ?
+ (!is_closed || join == gs_join_none || zero_length ?
(pl_ptr) 0 : (pl_ptr) & pl_first);
code = (*line_proc) (to_path, index - 1, &pl_prev, lptr, pdevc,
@@ -820,11 +843,9 @@
}
}
-/* Adjust the endpoints and width of a stroke segment */
-/* to achieve more uniform rendering. */
-/* Only o.p, e.p, e.cdelta, and width have been set. */
+/* Adjust the endpoints and width of a stroke segment along a specified axis */
private void
-adjust_stroke(pl_ptr plp, const gs_imager_state * pis, bool thin)
+adjust_stroke_transversal(pl_ptr plp, const gs_imager_state * pis, bool thin, bool horiz)
{
fixed *pw;
fixed *pov;
@@ -832,9 +853,7 @@
fixed w, w2;
fixed adj2;
- if (!pis->stroke_adjust && plp->width.x != 0 && plp->width.y != 0)
- return; /* don't adjust */
- if (any_abs(plp->width.x) < any_abs(plp->width.y)) {
+ if (horiz) {
/* More horizontal stroke */
pw = &plp->width.y, pov = &plp->o.p.y, pev = &plp->e.p.y;
adj2 = STROKE_ADJUSTMENT(thin, pis, y) << 1;
@@ -873,6 +892,73 @@
}
}
+void adjust_stroke_longitude(pl_ptr plp, const gs_imager_state * pis, bool thin, bool horiz)
+{
+
+ fixed *pow = (horiz ? &plp->o.p.y : &plp->o.p.x);
+ fixed *pew = (horiz ? &plp->e.p.y : &plp->e.p.x);
+
+ /* Only adjust the endpoints if the line is horizontal or vertical.
+ Debugged with pdfwrite->ppmraw 72dpi file2.pdf */
+ if (*pow == *pew) {
+ fixed *pov = (horiz ? &plp->o.p.x : &plp->o.p.y);
+ fixed *pev = (horiz ? &plp->e.p.x : &plp->e.p.y);
+ fixed length = any_abs(*pov - *pev);
+ fixed length_r, length_r_2;
+ fixed mv = (*pov + *pev) / 2, mv_r;
+ fixed adj2 = (horiz ? STROKE_ADJUSTMENT(thin, pis, x)
+ : STROKE_ADJUSTMENT(thin, pis, y)) << 1;
+
+ if (length > fixed_1) /* comparefiles/file2.pdf */
+ return;
+ if (pis->line_params.cap == gs_cap_butt) {
+ length_r = fixed_rounded(length);
+ if (length_r < fixed_1)
+ length_r = fixed_1;
+ length_r_2 = length_r / 2;
+ } else {
+ /* Account width for proper placing cap centers. */
+ fixed width = any_abs(horiz ? plp->width.y : plp->width.x);
+
+ length_r = fixed_rounded(length + width * 2 + adj2);
+ length_r_2 = fixed_rounded(length) / 2;
+ }
+ if (length_r & fixed_1)
+ mv_r = fixed_floor(mv) + fixed_half;
+ else
+ mv_r = fixed_floor(mv);
+ if (*pov < *pev) {
+ *pov = mv_r - length_r_2;
+ *pev = mv_r + length_r_2;
+ } else {
+ *pov = mv_r + length_r_2;
+ *pev = mv_r - length_r_2;
+ }
+ }
+}
+
+/* Adjust the endpoints and width of a stroke segment */
+/* to achieve more uniform rendering. */
+/* Only o.p, e.p, e.cdelta, and width have been set. */
+private void
+adjust_stroke(pl_ptr plp, const gs_imager_state * pis, bool thin, bool adjust_longitude)
+{
+ bool horiz;
+
+ if (!pis->stroke_adjust && plp->width.x != 0 && plp->width.y != 0)
+ return; /* don't adjust */
+ horiz = (any_abs(plp->width.x) <= any_abs(plp->width.y));
+ adjust_stroke_transversal(plp, pis, thin, horiz);
+ if (adjust_longitude)
+ adjust_stroke_longitude(plp, pis, thin, horiz);
+ /* fixme :
+ The best value for adjust_longitude is whether
+ the dash is isolated and doesn't cover entire segment.
+ The current data structure can't pass this info.
+ Therefore we restrict adjust_stroke_longitude with 1 pixel length.
+ */
+}
+
/* Compute the intersection of two lines. This is a messy algorithm */
/* that somehow ought to be useful in more places than just here.... */
/* If the lines are (nearly) parallel, return -1 without setting *pi; */
@@ -1059,7 +1145,7 @@
/* We didn't set up the endpoint parameters before, */
/* because the line was thin. Do it now. */
set_thin_widths(plp);
- adjust_stroke(plp, pis, true);
+ adjust_stroke(plp, pis, true, first == 0 && nplp == 0);
compute_caps(plp);
}
/* Create an initial cap if desired. */
Modified: trunk/gs/src/gzpath.h
===================================================================
--- trunk/gs/src/gzpath.h 2006-09-04 11:40:17 UTC (rev 7020)
+++ trunk/gs/src/gzpath.h 2006-09-04 12:50:36 UTC (rev 7021)
@@ -36,7 +36,8 @@
s_start,
s_line,
s_line_close,
- s_curve
+ s_curve,
+ s_dash /* only for internal use of the stroking algorithm */
} segment_type;
/* Define the common structure for all segments. */
@@ -77,6 +78,16 @@
gs_private_st_suffix_add0(st_line, line_segment, "line",\
line_enum_ptrs, line_reloc_ptrs, st_segment)
+/* Dash segments (only for internal use of the stroking algorithm). */
+typedef struct {
+ segment_common
+ gs_fixed_point tangent;
+} dash_segment;
+
+#define private_st_dash() /* in gxpath.c */\
+ gs_private_st_suffix_add0(st_dash, dash_segment, "dash",\
+ dash_enum_ptrs, dash_reloc_ptrs, st_segment)
+
/* Line_close segments are for the lines appended by closepath. */
/* They point back to the subpath being closed. */
typedef struct {
Modified: trunk/gs/src/lib.mak
===================================================================
--- trunk/gs/src/lib.mak 2006-09-04 11:40:17 UTC (rev 7020)
+++ trunk/gs/src/lib.mak 2006-09-04 12:50:36 UTC (rev 7021)
@@ -693,7 +693,7 @@
$(GLOBJ)gxpdash.$(OBJ) : $(GLSRC)gxpdash.c $(GX) $(math__h)\
$(gscoord_h) $(gsline_h) $(gsmatrix_h)\
- $(gxfixed_h) $(gzline_h) $(gzpath_h)
+ $(gxfixed_h) $(gxarith_h) $(gzline_h) $(gzpath_h)
$(GLCC) $(GLO_)gxpdash.$(OBJ) $(C_) $(GLSRC)gxpdash.c
$(GLOBJ)gxpflat.$(OBJ) : $(GLSRC)gxpflat.c $(GX)\
More information about the gs-cvs
mailing list