On Wed, Jan 5, 2011 at 8:12 AM, <span dir="ltr"><<a href="mailto:carol.szabo@nokia.com">carol.szabo@nokia.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div>
<div dir="ltr" align="left"><span><font face="Arial" color="#0000ff" size="2">Please see my in-line comments
below:</font></span></div><br>
<blockquote style="padding-left:5px;margin-left:5px;border-left:#0000ff 2px solid;margin-right:0px">
<div dir="ltr" align="left" lang="en-us">
<hr>Version 1:</div><div class="gmail_quote"><blockquote class="gmail_quote" style="padding-left:1ex;margin:0pt 0pt 0pt 0.8ex;border-left:rgb(204,204,204) 1px solid"><div bgcolor="#ffffff" text="#000000"><div dir="ltr" align="left">
<span><span lang="EN">
<p>4.8.11.1.13 Drawing model</p>
<p><font face="Arial" color="#0000ff" size="2"></font> </p>
<p>When a shape or image is painted, user agents must follow these steps, in
the order given (or act as if they do):</p>
<p>1. Render the shape or image onto an infinite transparent black bitmap,
creating image M1, as described in the previous sections except that for the
purpose of this step every pixel of the image will be considered to be fully
opaque white and the current fillStyle will be considered to be solid fully
opaque white and the strokeStyle will be considered fullyOpaque white as
well <br></p></span></span></div></div></blockquote>
<blockquote class="gmail_quote" style="padding-left:1ex;margin:0pt 0pt 0pt 0.8ex;border-left:rgb(204,204,204) 1px solid">
<div bgcolor="#ffffff" text="#000000">
<div dir="ltr" align="left"><span><span lang="EN">
<p>2. When shadows are drawn, render the shadow from image M1, using a fully
opaque white shadow color as described in the shadows section, creating
image M2. </p></span></span></div></div></blockquote>
<blockquote class="gmail_quote" style="padding-left:1ex;margin:0pt 0pt 0pt 0.8ex;border-left:rgb(204,204,204) 1px solid">
<div bgcolor="#ffffff" text="#000000">
<div dir="ltr" align="left"><span><span lang="EN">
<p>3. Let C1 be a region obtained by intersecting the canvas's cliping
region with the set of pixels in the canvas that correspond to pixels in M1
(by having the same coordinates) that are not fully transparent.</p>
<p>4. Let C2 be a region obtained by intersecting the canvas's cliping
region with the set of pixels in the canvas that correspond to pixels in M2
(by having the same coordinates) that are not fully
transparent.</p></span></span></div></div></blockquote>
<blockquote class="gmail_quote" style="padding-left:1ex;margin:0pt 0pt 0pt 0.8ex;border-left:rgb(204,204,204) 1px solid">
<div bgcolor="#ffffff" text="#000000">
<div dir="ltr" align="left"><span><span lang="EN">
<p>5. Render the shape or image onto an infinite transparent black bitmap,
creating image A, as described in the previous sections. For shapes, the
current fill, stroke, and line styles must be honored, and the stroke must
itself also be subjected to the current transformation matrix.</p>
<p>6. When shadows are drawn, render the shadow from image A, using the
current shadow styles, creating image B.</p>
<p>7. When shadows are drawn, multiply the alpha component of every pixel in
B by globalAlpha.</p>
<p>8. When shadows are drawn, composite B with the current canvas bitmap,
cliping results to region C2 defined above, using the current composition
operator.</p>
<p>9. Multiply the alpha component of every pixel in A by globalAlpha.</p>
<p>10. Composite A with the current canvas bitmap, cliping results to region
C1 defined above, using the current composition operator.
</p></span></span></div></div></blockquote><font face="Arial" color="#0000ff" size="2"></font>
<div><font face="Arial" color="#0000ff" size="2"></font><br>Making a binary
fully-transparent/not-fully-transparent per-pixel decision to create regions
C1 and C2 seems like it can't be right in the presence of
antialiasing.<br><br>Suppose we have a path filled with black and operator
"copy". Any pixel on the edge of that path that gets any nonzero coverage
value from antialiasing will end up solid black with this proposal. That's
going to look very ugly. We'll want a solution where any canvas pixel which
has a very small amount of coverage by the path will be mostly unchanged in
the final result.<br><span><font face="Arial" color="#0000ff" size="2"> </font></span></div>
<div><span>
<div dir="ltr" align="left"><span><font face="Arial" color="#0000ff" size="2">I do not understand why pixels touched by antialiasing
are going to be solid black.</font></span></div></span></div></div></blockquote></div></blockquote><div>Yes, I made a mistake. The actual result will be mostly-transparent black, but that is equally unacceptable.<br><br>
In step 1, every pixel which is very slightly covered by the path will be filled with mostly-transparent white.<br>In step 3, all such pixels will be added to C1.<br>In step 5, those pixels will be set to mostly-transparent black in image A.<br>
In step 10, for those pixels we'll composite mostly-transparent black onto the canvas with operator "copy", setting the canvas pixels to mostly-transparent black.<br><br>The core problem is steps 3 and 4. Making a binary decision for each pixel whether it's "in" or "out" of the shape simply can't work well when coverage-based antialiasing is being used.<br>
<br>If you generalize C1 and C2 to be alpha masks, or rephrase the approach so that it permits such generalization, then this could work. But you have to be careful about how you use partial alpha values in step 10.<br><br>
</div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div><blockquote style="padding-left: 5px; margin-left: 5px; border-left: 2px solid rgb(0, 0, 255); margin-right: 0px;">
<div class="gmail_quote"><div><span>
<div dir="ltr" align="left"><span><font face="Arial" color="#0000ff" size="2">The way I understand antialiasing (and maybe I am wrong),
pixels that are partly touched retained partly their old color and
transparency and get parly the new color and transparency. More
precisely the resulting transparency and color components an average of
the color component being painted and the previous color component weighted by
the coverage fraction of the pixel. Hence partially covered pixels are
partially transparent, thus the background behind the canvas should shine
through and the partially covered pixels won't be entirely black unless
that background is black as well.</font></span></div></span></div></div></blockquote></div></blockquote><div><br>That's right, but your proposal interacts with this process.<br><br></div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div><blockquote style="padding-left: 5px; margin-left: 5px; border-left: 2px solid rgb(0, 0, 255); margin-right: 0px;"><div class="gmail_quote"><div><span><div dir="ltr" align="left"><span><font face="Arial" color="#0000ff" size="2">I agree with you though that there are
cases when inappropriately using globalCompositeOperation can yield ugly and
perhaps surprising results, such as in the case you described if the
canvas is completely red before the operation and it is put on a page that has
green background, thus the shape will acquire an unexpected slightly
green rim between black and red.</font></span></div></span></div></div></blockquote></div></blockquote><div><br>Yes, it's easy to produce ugliness. With great power comes great responsibility :-).<br></div><div><br>
</div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div><blockquote style="padding-left: 5px; margin-left: 5px; border-left: 2px solid rgb(0, 0, 255); margin-right: 0px;">
<div class="gmail_quote"><div><span> </span><br></div>
<blockquote class="gmail_quote" style="padding-left:1ex;margin:0pt 0pt 0pt 0.8ex;border-left:rgb(204,204,204) 1px solid">
<div bgcolor="#ffffff" text="#000000">
<div dir="ltr" align="left">Version 2:<span><span lang="EN">
<p><font face="Arial" color="#0000ff" size="2"></font> </p>
<p>4.8.11.1.13 Drawing model</p>
<p><font face="Arial" color="#0000ff" size="2"></font> </p>
<p>When a shape or image is painted, user agents must follow these steps, in
the order given (or act as if they do):</p>
<p>1. Render the shape or image onto an infinite transparent black bitmap,
creating image A, as described in the previous sections. For shapes, the
current fill, stroke, and line styles must be honored, and the stroke must
itself also be subjected to the current transformation matrix.</p>
<p>2. When shadows are drawn, render the shadow from image A, using the
current shadow styles, creating image B.</p>
<p>3. When shadows are drawn, multiply the alpha component of every pixel in
B by globalAlpha.</p>
<p>4. When shadows are drawn, composite, using the current composition
operator, B with the current canvas bitmap, cliping results to the cliping
region of the canvas and to the pixels that would have taken the shadow's
color if the composition operator would have been source-over and the shadow
would have been fully opaque and the globalAlpha would have been 1.</p>
<p>5. Multiply the alpha component of every pixel in A by globalAlpha.</p>
<p>6. Composite, using the current composition operator, A with the current
canvas bitmap, cliping results to the cliping region of the canvas and to
the pixels that would have taken the shape's or image's pixel color if the
composition operator would have been source-over and the image would have
been fully opaque, the fillStyle and strokeStyle would have been a solid
fully opaque color, and the globalAlpha would have been
1</p></span></span></div></div></blockquote><font face="Arial" color="#0000ff" size="2"></font>
<div><font face="Arial" color="#0000ff" size="2"></font><br>Again, this needs to be
modified to take into account the possibility that some pixels are partially
covered.<span><font face="Arial" color="#0000ff" size="2"> </font></span></div>
<div><span><font face="Arial" color="#0000ff" size="2"></font></span> </div>
<div><span><font face="Arial" color="#0000ff" size="2">Again, as above, Porter-Duff does not allow for partially applying
the composition operator. For every pair of source and target pixels, the
operator is applied.</font></span></div></div></blockquote></div></blockquote><div><br>Right. In practice implementations go beyond Porter-Duff to take some kind of "mask alpha" into account to support coverage-based antialiasing.<br>
</div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div><blockquote style="padding-left: 5px; margin-left: 5px; border-left: 2px solid rgb(0, 0, 255); margin-right: 0px;">
<div class="gmail_quote"><span><font face="Arial" color="#0000ff" size="2">I
myself have no particular quarel with the current spec language other than the
fact that it looses shadows and that it is very expensive to implement with
graphics primitives that I know of, due to the need to alocate large
intermediary images to be composited later, rather then drawing directly on
the target bitmap using an appropriate pen and compositor.</font></span></div></blockquote></div></blockquote><div><br>This depends on what your underlying implementation can do and what the workload is. In practice usage of operators other than "over" is quite rare. Copying one canvas to another is probably the main use. You can optimize the case where the source fills the destination clip region --- in those cases, which I think are most cases in practice, of course it doesn't matter whether the operation is bounded by the source shape or not.<br>
<br></div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div><blockquote style="padding-left: 5px; margin-left: 5px; border-left: 2px solid rgb(0, 0, 255); margin-right: 0px;">
Given that Microsoft have indicated they're happy with the
current spec, and are presumably implementing it, I think we should get their
explicit approval before we change the spec here. I'm still happy with either
the current spec or your proposed change (after the issues have been
addressed).<br><div><span><font face="Arial" color="#0000ff" size="2"> </font></span></div>
<div><span><font face="Arial" color="#0000ff" size="2">My
understanding from some older thread was that Microsoft favored the approach
where only pixels covered by the shape are composited, but that information
may be outdated.</font></span></div></blockquote></div></blockquote><br></div>Yes, they seem to have changed their minds.<br clear="all"><br>Rob<br>-- <br>"Now the Bereans were of more noble character than the
Thessalonians, for they received the message with great eagerness and
examined the Scriptures every day to see if what Paul said was true." [Acts 17:11]<br>