-
Notifications
You must be signed in to change notification settings - Fork 30
Description
Greetings, and thank you for sharing Pixie!
I am not sure if this is to be expected or not (or even whether cairo shows similar behavior), although there are inconsistencies within pixie's behavior at minimum. Here is a 4x2 grid showcasing the behavior. Each cell is essentially filled with two white triangles, and sometimes a gap is visible between them even though their shared edge is specified from the same points. In case it is not obvious which cells due to monitor dpi or brightness:
|--------|-----------|-----------|--------|
| no gap | light gap | light gap | no gap |
|--------|-----------|-----------|--------|
| gap | light gap | light gap | gap |
|--------|-----------|-----------|--------|
For the top row, cw, and ccw refers to whether a triangle's path was specified in a clockwise or counter-clockwise manner. Each top row example is a single filled path.
For the second row, each example left to right:
- Two paths separately filled (one for each triangle).
- The same two paths added to another path which is filled.
- The triangles defined in a single SVG string which is filled.
- Each triangle filled from a separate SVG string.
Vertical and horizontal fills don't seem to exhibit this behavior, only diagonals.
The code which produced this image:
import pixie
var
image = newImage(800, 400)
cwcw, cwccw, ccwcw, ccwccw, p1, p2, p = newPath()
font = readFont("Hack-Regular.ttf")
font.size = 18
image.fill("black")
#[ ROW 1 ]#
# cw, cw: no gap visible
cwcw.moveTo(0.0, 0.0)
cwcw.lineTo(200.0, 0.0)
cwcw.lineTo(200.0, 200.0)
cwcw.lineTo(0.0, 0.0)
cwcw.moveTo(200.0, 200.0)
cwcw.lineTo(0.0, 200.0)
cwcw.lineTo(0.0, 0.0)
cwcw.lineTo(200.0, 200.0)
image.fillPath(cwcw, "white")
image.fillText(font.typeset("cw, cw", vec2(200, 100), hAlign = CenterAlign, vAlign = MiddleAlign), translate(vec2(0, 100)))
# cw, ccw: light gap visible
cwccw.moveTo(0.0, 0.0)
cwccw.lineTo(200.0, 200.0)
cwccw.lineTo(0.0, 200.0)
cwccw.lineTo(0.0, 0.0)
cwccw.moveTo(200.0, 200.0)
cwccw.lineTo(200.0, 0.0)
cwccw.lineTo(0.0, 0.0)
cwccw.lineTo(200.0, 200.0)
image.fillPath(cwccw, "white", translate(vec2(200, 0)))
image.fillText(font.typeset("cw, ccw", vec2(200, 100), hAlign = CenterAlign, vAlign = MiddleAlign), translate(vec2(200, 100)))
# ccw, cw: light gap visible
ccwcw.moveTo(0.0, 0.0)
ccwcw.lineTo(0.0, 200.0)
ccwcw.lineTo(200.0, 200.0)
ccwcw.lineTo(0.0, 0.0)
ccwcw.moveTo(200.0, 200.0)
ccwcw.lineTo(0.0, 0.0)
ccwcw.lineTo(200.0, 0.0)
ccwcw.lineTo(200.0, 200.0)
image.fillPath(ccwcw, "white", translate(vec2(400, 0)))
image.fillText(font.typeset("ccw, cw", vec2(200, 100), hAlign = CenterAlign, vAlign = MiddleAlign), translate(vec2(400, 100)))
# ccw, ccw: no gap visible
ccwccw.moveTo(0.0, 0.0)
ccwccw.lineTo(0.0, 200.0)
ccwccw.lineTo(200.0, 200.0)
ccwccw.lineTo(0.0, 0.0)
ccwccw.moveTo(200.0, 200.0)
ccwccw.lineTo(200.0, 0.0)
ccwccw.lineTo(0.0, 0.0)
ccwccw.lineTo(200.0, 200.0)
image.fillPath(ccwccw, "white", translate(vec2(600, 0)))
image.fillText(font.typeset("ccw, ccw", vec2(200, 100), hAlign = CenterAlign, vAlign = MiddleAlign), translate(vec2(600, 100)))
#[ ROW 2 ]#
# p1, p2
# clear gap visible
p1.moveTo(0.0, 0.0)
p1.lineTo(0.0, 200.0)
p1.lineTo(200.0, 200.0)
p1.lineTo(0.0, 0.0)
p2.moveTo(200.0, 200.0)
p2.lineTo(0.0, 0.0)
p2.lineTo(200.0, 0.0)
p2.lineTo(200.0, 200.0)
image.fillPath(p1, "white", translate(vec2(0, 200)))
image.fillPath(p2, "white", translate(vec2(0, 200)))
image.fillText(font.typeset("p1, p2", vec2(200, 100), hAlign = CenterAlign, vAlign = MiddleAlign), translate(vec2(0, 300)))
# p
# light gap visible
p.addPath(p1)
p.addPath(p2)
image.fillPath(p, "white", translate(vec2(200, 200)))
image.fillText(font.typeset("p", vec2(200, 100), hAlign = CenterAlign, vAlign = MiddleAlign), translate(vec2(200, 300)))
# 1 SVG string
# light gap visible
image.fillPath(
"""
M 0.0 0.0
L 200.0 200.0
L 0.0 200.0
L 0.0 0.0
M 200.0 200.0
L 200.0 0.0
L 0.0 0.0
L 200.0 200.0
""", "white", translate(vec2(400, 200)))
image.fillText(font.typeset("1 SVG string", vec2(200, 100), hAlign = CenterAlign, vAlign = MiddleAlign), translate(vec2(400, 300)))
# 2 SVG string
# clear gap visible
image.fillPath(
"""
M 0 0
L 200 200
L 0 200
L 0 0
""", "white", translate(vec2(600, 200)))
image.fillPath(
"""
M 200 200
L 200 0
L 0 0
L 200 200
""", "white", translate(vec2(600, 200)))
image.fillText(font.typeset("2 SVG string", vec2(200, 100), hAlign = CenterAlign, vAlign = MiddleAlign), translate(vec2(600, 300)))
image.writeFile("fillIssue.png")
In an image full of filled paths, this behavior makes it look as though strokes were applied when they were not. For example:
If you look closely, there are a few spots in the above image where 'strokes' seem to be missing. These are areas where shared edges are closely vertical or horizontal.
I assume this has everything to do with AA of fills. Thanks for taking a look.

