I have more carefully checked svg, cairo, qt, and xwin results today, and
most of my conclusions are different than they were before (sigh).
Furthermore, I have made some fundamental changes (revision 11579) in
how our qt device driver deals with fills having complex
(self-intersecting) boundaries. The first such change was a bug fix
for qtwidgets (drawConvexPolygon should never be used for non-simple
polygons so I replaced that call with a call to the completely general
drawPolygon). The other change was to move from the default
Qt::OddEvenFill fill rule to the Qt::WindingFill fill rule. The former
appears to have _many_ bugs for complex boundaries. The latter also
has bugs, but far fewer than the former.
Finally, I changed (revision 11580) -dev xwin to use the (nonzero)
WindingRule fill rule rather than the default EvenOddRule fill rule.
In general, I now get example 27 fill consistency between all svg,
cairo, qt, and xwin devices except for -dev svgqt. For that device
alone, revision 11579 changed nothing. If you use "less" to look at
the svg file you generate with -dev svgqt, it is clear the evenodd
fill rule is being used rather than the requested nonzero fill rule.
Ignoring the requested fill rule and using the default instead must be
a svg file bug in my version of the Qt4 libraries (4.6.3 from Debian
Squeeze). Others with access to newer versions of Qt4 may not get
this inconsistent result.
Once the above drawConvexPolygon bug was fixed but previous to
adopting the Qt::WindingFill fill rule, all qt fill results looked
identical for the pngqt, epsqt, and svgqt devices. But pngqt results
are just a bitmap so the default Qt::OddEvenFill fill rule must have
been implemented within Qt4 itself to create that bitmap. In
contrast, epsqt fill results are rendered by gv and svgqt results are
rendered using the librsvg library (used, e.g., by "display" or "eog).
Furthermore, before I changed the fill rule for -dev xwin its even-odd
result was also bad, but consistent with the others listed here. The
consistency of these really bad even-odd results means, I think, that
the X fill implementation is being used by all drivers other than the
bitmapped ones (e.g., pngqt), and for those bitmapped ones, I suspect
they must have copied their (bad even-odd fill) code from X.
That conclusion is further supported after the change from
Qt::OddEvenFill to Qt::WindingFill for the qt devices and EvenOddRule
to WindingRule for -dev xwin since now you have consistent results for
the qt devices (other than svgqt for the reason discussed above), -dev
svg, _and_ all the cairo devices, and the xwin device even though some
of those rendered results are not correct. For all those devices,
page 14 of example 27, for example, gives consistently wrong results
with asymmetric fill results for a symmetrical boundary.
In sum, as a work-around to a universally bad implementation of the
even-odd fill rule (probably in X) and in individual libraries for
bitmapped results, we should, for now, continue to specify the
non-zero fill rule (as I have just done for the qt devices and xwin
device). Example 27 reveals that that fill rule also has a
universally bad implemention, but the bugs are not nearly as severe as
in the even-odd fill rule case.
N.B. all these comments are specific to X-based platforms such as
Linux. It would be a very interesting experiment to run example 27 on
non-X platforms such as Windows for all our many different qt and
cairo devices. Of course, in that case as well, a distinction must be
made between results for bitmapped file devices (where the fill must
be internally implemented by either Qt4 or pango/cairo) and
non-bitmapped file or interactive devices where the fill is ultimately
implemented by the platform's displaying facility that has the same
role as X.
Finally, because of these fill issues for polygons with
self-intersecting boundaries we should probably want to implement our
own even-odd _and_ non-zero filling rules by, e.g., partitioning
(using the appropriate fill rule) a fill of a self-intersecting
polygon into fills of simpler polygons that do not self-intersect. If
you google for <partition complex polygon>,
is the top result. That master's thesis (University of South Alabama,
2003) is low enough level so even I can understand large parts of it.
He even includes his code for implementing
such partitions. However, that code has no licensing terms and is
partially copied from others at that faculty (presumably with personal
permission for him to do so). That means anyone who copies that code
would be in violation of Subramaniam's copyright as well as the
copyright of others at that faculty. Thus, we should completely
ignore his code and instead use Subramaniam's _ideas_ which he has very
clearly expressed in the body of the thesis as a pseudo-algorithm for
I think this would be a really interesting project for anyone who
would like to see better-looking fill results for example 27.
Unfortunately, I don't have time to pursue this myself for the
forseeable future, but I hope someone else here is inspired to look
Alan W. Irwin
Astronomical research affiliation with Department of Physics and Astronomy,
University of Victoria (astrowww.phys.uvic.ca).
Programming affiliations with the FreeEOS equation-of-state implementation
for stellar interiors (freeeos.sf.net); PLplot scientific plotting software
package (plplot.org); the libLASi project (unifont.org/lasi); the Loads of
Linux Links project (loll.sf.net); and the Linux Brochure Project