[cairo] Trying to figure out some rasterization problems

David Kastrup dak at gnu.org
Sun Apr 21 08:13:12 PDT 2013

Behdad Esfahbod <behdad at behdad.org> writes:

> Hi David,
> Long time!  Comments below.
> On 13-04-21 09:49 AM, David Kastrup wrote:
>> a) creating a path and filling it (or clipping with it) leads to results
>> that are too thin on a subpixel base.
>> The PostScript/PDF imaging model is pretty clear about clip/fill
>> regions: every pixel that has any part, no matter how small, inside of
>> the path belongs to the region.  So if I am not using strokeadjust, and
>> I am stroking a path, clipping by its outline is not supposed to change
>> any pixel.  And using strokeadjust will only _reduce_ the area covered
>> by a stroke, so again, clipping and stroking should not make a
>> difference as opposed to only stroking.
> You are jumping to conclusions here.  What's strokeadjust?  Cairo doesn't
> implement PostScript/PDF exactly...

Well, libpoppler presumably does something with it...

>> Unfortunately, it _does_ make a difference.  Why do we care?  Because
>> note stems are rectangles with rounded corners.  Not completely circular
>> stroke ends, just rounded corners.  If we care for stroke adjustment
>> (which we do), that means our actual shape needs to be represented as an
>> intersection of a stroke-adjusted rectangle and clipping off the rounded
>> corners.  That clipping apparently removes too much.  An easy solution
>> appears to be to restroke the middle part of the rectangle without any
>> clipping.  Which comes to problem b) which I think Cairo might be
>> responsible for:
> I still have no idea what you are talking about.  Perhaps some images
> would help?

What's wrong with "a rectangle with rounded corners"?  At any rate,
stroke adjustment deals with rasterization on a black&white device: if
you have a thin line, the normal PostScript/PDF way is to color all
pixels black that have any part inside covered by the filled/stroked
region.  For thin lines, this adds up to one line of blackness too much
on each side.  Stroke adjustment checks the total width and reduces it
(starting on the side with the larger overhang) by 1 pixel until it is
not off more than half a pixel.  So 0, 1 or two pixels are culled from
the width, depending on where it lies in the rasterization.

>> Now I can't figure out the strategy used by Cairo for antialiased
>> rendering from the docs and code so far: is it drawing on a higher
>> resolution canvas?  Or is it some heuristic juggling with greyness
>> levels?  If the latter, what are the heuristics?
> The latter.  The "independence" heuristic I'd call it.  Google for
> Porter-Duff.

Ugh.  So it is indeed thickening stuff and I must not draw any feature
more than once.

At any rate: setting a clip area and then drawing a stroke exactly
covering the clip area yields a lighter result than just drawing the
stroke.  That does not seem warranted.  It is conceivable that again an
"independence" heuristic for antialiasing is at work here with its
premise not being met.

David Kastrup

More information about the cairo mailing list