<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=us-ascii">
<META content="MSHTML 6.00.2900.3698" name=GENERATOR></HEAD>
<BODY>
<DIV dir=ltr align=left><SPAN class=118300323-03012011><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 class=OutlookMessageHeader lang=en-us dir=ltr align=left>
  <HR tabIndex=-1>
  <FONT face=Tahoma size=2><B>From:</B> rocallahan@gmail.com 
  [mailto:rocallahan@gmail.com] <B>On Behalf Of </B>ext Robert 
  O'Callahan<BR><B>Sent:</B> Monday, January 03, 2011 5:56 PM<BR><B>To:</B> 
  Szabo Carol (Nokia-MS/Boston)<BR><B>Cc:</B> chuck@jumis.com; 
  whatwg@whatwg.org<BR><B>Subject:</B> Re: [whatwg] Fwd: RE: Inconsistent 
  behaviour of globalCompositeOperation property<BR></FONT><BR></DIV>
  <DIV></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>HTML5 - Canvas.</P>
    <P>I have read this thread (from and of July 2010) and I happen to agree 
    that the Safari/Chromium implementation is more intuitive, and likely less 
    expensive to implement, therefore I offer these 2 proposals for changing the 
    spec's Drawing model section to match what I perceive to be the preference 
    of most people in that discussion.</P>
    <P>Of note: According to the current Drawing model, an opaque shape's shadow 
    would be erased as part of step 6 when drawn with source-in composite Mode 
    if globalAlpha is 1, which is probably not the intended behavior.</P>
    <P>Version 1:</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 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 class=118300323-03012011><FONT face=Arial 
  color=#0000ff size=2> </FONT></SPAN></DIV>
  <DIV><SPAN class=118300323-03012011>
  <DIV dir=ltr align=left><SPAN class=118300323-03012011><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>
  <DIV dir=ltr align=left><SPAN class=118300323-03012011><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. 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>
  <DIV dir=ltr align=left><SPAN class=118300323-03012011><FONT face=Arial 
  color=#0000ff size=2>I still believe that this behavior as ugly as it may be 
  in some cases, is still preferable to not being able to do shadows when using 
  the copy operation (as results from the standard's current language), is more 
  intuitive and less resource intensive (to me the less resource intensive is 
  the most important part).</FONT></SPAN></DIV> </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 class=118300323-03012011><FONT face=Arial color=#0000ff 
  size=2> </FONT></SPAN></DIV>
  <DIV><SPAN class=118300323-03012011><FONT face=Arial color=#0000ff 
  size=2></FONT></SPAN> </DIV>
  <DIV><SPAN class=118300323-03012011><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. The only question is what are the source pixels to be 
  paired with the target. The current language of the standard</FONT> <FONT 
  face=Arial color=#0000ff size=2>provides one or even two 
  (in case of shadows) source pixel(s) for every target pixel inside 
  the cliping region. This is expensive and leads to non-intuitive behaviors 
  such as loss shadows with some operations.</FONT></SPAN></DIV>
  <DIV><SPAN class=118300323-03012011><FONT face=Arial color=#0000ff size=2>My 
  proposal is to apply the composition operator only to pixels covered by the 
  source inside the cliping region, of course. The question is the definition of 
  covered. I chose for that the pixels that would be changed by a plain solid 
  brush/pen in the graphics system. The hope is that the whole trick with 2 
  infinite canvases in reality will be just a way of explaining how the result 
  should look like and that drawing a shape and compositing an image shall be 
  done using simple graphics primitives in-place avoiding the need for extra 
  memory and calculation.</FONT></SPAN></DIV>
  <DIV><SPAN class=118300323-03012011><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>
  <DIV><SPAN class=118300323-03012011><FONT face=Arial color=#0000ff size=2>If 
  the current spec is to survive, then I suggest instead of steps 3 
  to 6 of the drawing model, to say:</FONT></SPAN></DIV>
  <DIV><SPAN class=118300323-03012011><FONT face=Arial color=#0000ff 
  size=2></FONT></SPAN> </DIV>
  <DIV><SPAN class=118300323-03012011><FONT face=Arial color=#0000ff size=2>3. 
  </FONT></SPAN><SPAN class=118300323-03012011><A 
  href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#when-shadows-are-drawn">When 
  shadows are drawn</A>, composite <VAR title="">A over B in A</VAR>. 
  </SPAN></DIV>
  <DIV><SPAN class=118300323-03012011><FONT face=Arial color=#0000ff 
  size=2></FONT></SPAN> </DIV>
  <DIV><SPAN class=118300323-03012011>4. Multiply the alpha component of every 
  pixel in <VAR title="">A</VAR> by <CODE title=dom-context-2d-globalAlpha><A 
  href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-globalalpha">globalAlpha</A></CODE>.</SPAN></DIV>
  <DIV><SPAN class=118300323-03012011><FONT face=Arial color=#0000ff 
  size=2></FONT></SPAN> </DIV>
  <DIV><SPAN class=118300323-03012011>5. Composite <VAR title="">A</VAR> within 
  the <A 
  href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#clipping-region">clipping 
  region</A> over the current canvas bitmap using the current composition 
  operator. </DIV></SPAN>
  <BLOCKQUOTE class=gmail_quote 
  style="PADDING-LEFT: 1ex; MARGIN: 0pt 0pt 0pt 0.8ex; BORDER-LEFT: rgb(204,204,204) 1px solid"><FONT 
    face=Arial color=#0000ff size=2></FONT></BLOCKQUOTE></DIV>
  <DIV><FONT face=Arial color=#0000ff size=2></FONT><FONT face=Arial 
  color=#0000ff size=2></FONT><FONT face=Arial color=#0000ff 
  size=2></FONT><BR>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><SPAN class=118300323-03012011><FONT face=Arial color=#0000ff 
  size=2> </FONT></SPAN></DIV>
  <DIV><SPAN class=118300323-03012011><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>
  <DIV><SPAN class=118300323-03012011></SPAN><SPAN 
  class=118300323-03012011><FONT face=Arial color=#0000ff 
  size=2> </FONT></SPAN></DIV>
  <DIV><SPAN class=118300323-03012011><FONT face=Arial color=#0000ff size=2>In 
  any case, I wish that this aspect of the spec is firmed up so that 
  implementations can be aligned.</FONT></SPAN></DIV>
  <DIV><SPAN class=118300323-03012011><FONT face=Arial color=#0000ff 
  size=2></FONT></SPAN> </DIV>
  <DIV><SPAN class=118300323-03012011><FONT face=Arial color=#0000ff 
  size=2>Thanks for the review,</FONT></SPAN></DIV>
  <DIV><SPAN class=118300323-03012011><FONT face=Arial color=#0000ff 
  size=2></FONT></SPAN> </DIV>
  <DIV><SPAN class=118300323-03012011><FONT face=Arial color=#0000ff 
  size=2>Carol</FONT></SPAN></DIV>
  <DIV> </DIV></BLOCKQUOTE></BODY></HTML>