Fix for #687750 Attempt to share (local) segments of path
Raph Levien <[email protected]> Wed, 20 Oct 2004 17:44:41 -0700
| Newsgroups | gmane.comp.printing.ghostscript.patches |
|---|---|
| Message-ID | <[email protected]> |
Reviewers,
I believe I tracked down the shared path bug. It's basically a
question of the preconditions for using the "local_segments"
optimization not being met.
As a refresher, "local_segments" is an optimization by which the
path_segments field of a path is allocated as part of the path, rather
than through a separate allocation, a savings of exactly one
allocation per path. I am absolutely not convinced that this
optimization is worth the extra code complexity.
Separately, the "shared" optimization allows multiple paths to
reference the same subpaths. Unlike the local_segments optimization,
this is worthwhile, because it enables copying semantics with O(1)
time complexity. Lifetime management and copy-on-write semantics are
all handled in the usual way with refcounting.
These two optimizations cannot both be used at the same time. For
a single path_segments structure to be shared between two paths, it must
be allocated on the heap rather than contained in one of the path's
allocations. Thus, many of the functions which implement sharing have
the precondition that the source path does not use the local_segments
optimization.
That assumption is valid most of the time for cpath use, but there is
one case for which it fails: when adding paths generated internally by
the stroking logic to the clip path. This can happen when stroking using
a shading (as a pattern color space).
The proposed fix simply initializes the path internal to the clip
path list to a null path, then copies the source path over using
gx_path_assign_preserve(). This function, unlike the
gx_path_init_contained_shared() previously used, implements correct
copying semantics whether the source path uses the local_segments
optimization or not. It is worth noting that the old cpath code (prior
to implementing high-level intersected clip paths) used this function
to copy paths over from ppath_orig; see line 556 on gxcpath.c version
1.8.
Verified on test files from bugs #687401, #687612, and #687750.
Raph
Index: src/gxcpath.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxcpath.c,v
retrieving revision 1.12
diff -C2 -r1.12 gxcpath.c
*** src/gxcpath.c 4 Aug 2004 19:36:12 -0000 1.12
--- src/gxcpath.c 21 Oct 2004 00:25:05 -0000
***************
*** 363,368 ****
return code;
code = gx_cpath_to_path(pcpath, &pcplist->path);
! } else
! code = gx_path_init_contained_shared(&pcplist->path, ppfrom, mem, cname);
if (code < 0)
return code;
--- 363,370 ----
return code;
code = gx_cpath_to_path(pcpath, &pcplist->path);
! } else {
! gx_path_init_local(&pcplist->path, mem);
! code = gx_path_assign_preserve(&pcplist->path, ppfrom);
! }
if (code < 0)
return code;