[whatwg] A question about the drawimage() canvas function

Ian Hickson ian at hixie.ch
Tue Aug 6 13:17:38 PDT 2013


On Fri, 1 Mar 2013, Kang-Hao (Kenny) Lu wrote:
> (13/02/06 14:45), 王铁套 wrote:
> >
> > This is about the drawimage() canvas function in html5. What should 
> > the following code ouput? [...]
> >
> > <style> canvas { display:none } </style>
> > <script>
> >  window.onload = function() {
> >    var r = document.getElementById('r');
> >    var ctx = document.getElementsByTagName('canvas')[0].getContext('2d');
> >    var passed = false;
> >    var message = "";
> >    try {
> >      ctx.drawImage((new Image()), 0, 0, 150, 150);
> >      message = "No exception thrown"
> >    } catch (e) {
> >      passed = e.code === e.INDEX_SIZE_ERR;
> >      if (!passed)
> >        message = "Got exception code " + e.code +
> >                  " expected 1 (INDEX_SIZE_ERR)"
> >    }
> >    r.textContent = passed ? "PASS" : "FAIL";
> >    if (message) { r.textContent += " (" + message + ")" }
> >  }
> > </script>
> > <p id="r">FAIL (Script did not run.)</p>
> > <canvas></canvas>
> 
> The spec currently says
> 
>   # 1. If the image argument is an HTMLImageElement object that is not
>   #    fully decodable, or if the image argument is an HTMLVideoElement
>   #    object whose readyState attribute is either HAVE_NOTHING or
>   #    HAVE_METADATA, then return bad and abort these steps.
> 
> An <img> without @src isn't fully decodable by definition and therefore
> no exception should be thrown.
> 
> However, I worry that WebKit would not be willing to change this to to
> reflect the spec as I think this behavior has been existing for a long
> time (correct me if I am wrong here). Firefox has a bug for this[1] but
> I can't find one in WebKit yet.
> 
> Also, the rationale[2] that made this change[3] in 2009 had
> 
>   # I expect authors to just draw a video on a canvas when they see
>   # fit, test locally or on a stable network, see that it works fine.
>   # Then the script will stop working completely for some users because
>   # of the uncaught exception when the script tries to drawImage() a
>   # video that's not ready yet.
>   #
>   # Moreover, Opera has lazy loading of images (only loading images
>   # that are rendered or have some event handlers or were created with
>   # new Image() etc), so we'd probably want to just load the image when
>   # the script tries  to draw it instead of throwing.
> 
> which seems like a very uncommon situation in contemporary usage pattern 
> of <canvas> (starting drawImage() calls after all images are fully 
> loaded) and so I think this rationale shouldn't trump the benefits of 
> raising exceptions when Web developers make typos in @src or something. 
> Again, my main worry is that no WebKit people joined that discussion at 
> that time ....
> 
> [1] https://bugzilla.mozilla.org/show_bug.cgi?id=691186
> [2] http://lists.w3.org/Archives/Public/public-html/2009Aug/0299
> [3] http://html5.org/tools/web-apps-tracker?from=3684&to=3685

On Fri, 1 Mar 2013, Glenn Maynard wrote [edited for terseness]:
> 
> To be specific, testing Chrome 24, Firefox 19, and IE9 on 
> https://zewt.org/~glenn/test-drawimage-exception.html :
> 
> In Chrome:
> - drawImage(img, dx, dy) before the image is downloaded does nothing
> - drawImage(img, dx, dy, dw, dh) before the image is downloaded does nothing
> - drawImage(img, dx, dy) after the image fails to download does nothing
> - drawImage(img, dx, dy, dw, dh) after the image fails to download throws
>
> In Firefox and IE:
> - drawImage(img, dx, dy) before the image is downloaded does nothing
> - drawImage(img, dx, dy, dw, dh) before the image is downloaded does nothing
> - drawImage(img, dx, dy) after the image fails to download throws
> - drawImage(img, dx, dy, dw, dh) after the image fails to download throws
>
> It looks like the pattern is to not throw an exception for drawing 
> before the image finishes loading, but to throw an exception if the 
> image fetch did complete, but failed.  Chrome in the 3rd case above 
> seems like the exception.
>
> I imagine one of the Chrome cases is a bug, since it doesn't make sense 
> that the three-argument and five-argument versions have different 
> behavior. (I really hope that's just a bug, and not weird web-compat.)  
> I think the spec should also reflect what browsers are converging on: 
> throw an exception if the image is in the "broken" state, but not in 
> "unavailable" or "partially available".

Done.


On Fri, 1 Mar 2013, Rik Cabanier wrote:
> On Fri, Mar 1, 2013 at 2:40 PM, Glenn Maynard <glenn at zewt.org> wrote:
> > On Fri, Mar 1, 2013 at 4:24 PM, Rik Cabanier <cabanier at gmail.com> 
> > wrote:
> >>
> >> I think original step 2 should be updated to *CanvasImageSource* 
> >> instead of HTMLImageElement. This is certainly how webkit implemented 
> >> it.
> >
> > That sounds fine too, as long as you mean in addition to the above and 
> > not instead of.
> >
> > (If you mean instead of, I disagree.  As far as throwing or not 
> > throwing based on the broken or loading state question, it seems like 
> > WebKit should change to match FF and IE, since those two already 
> > agree, and WebKit also agrees with one of the two drawImage overloads 
> > tested.)
>
> Sorry about being unclear. Yes, I meant in addition of.
> So:
> - add your suggested step 1
> - change HTMLImageElement from original step 2 to CanvasImageSource

I don't understand this suggestion.

Can you show a test that demonstrates how this would differ from what the 
spec says now?


On Sat, 2 Mar 2013, Robert O'Callahan wrote:
>
> I actually just wrote a patch to implement the spec behavior in Firefox.
> 
> I think changing behavior from "throw" to "not throw" shouldn't have any 
> compatibility concerns. I also think that "not throw" is better here 
> than throwing; it's simpler to not distinguish "finished downloading but 
> decoding failed" from "download in progress (but very slow perhaps)".
> 
> In fact I question why the spec has us throw for zero-sized canvas 
> source. It would seem to me to be simpler/better to just not draw and 
> not throw in that case also.

On Sun, 3 Mar 2013, Robert O'Callahan wrote:
> 
> It would be really simple if we never throw and just paint nothing when 
> we don't have a valid image or the source has no pixels. Changing cases 
> from throwing to not throwing is very unlikely to cause compatibility 
> risk. Why not just do it?

Well, we have interop, and throwing when there are errors helps authors 
find bugs quicker.


On Fri, 22 Mar 2013, Rik Cabanier wrote:
> 
> Kenny found a couple of instances where changing this in webkit will break
> the application:
> - https://github.com/Animatron/player/pull/70
> - https://github.com/aduros/flambe/issues/55
> - http://groups.google.com/group/melonjs/msg/571b36150fd2760b

All these cases are interesting, because they all show cases where it's 
not clear that the code was correct in the first place (note comments 
like "why you'd want to use empty image?").

But in any case, why would this break WebKit? WebKit already does throw 
when the canvas is width=0:

   http://software.hixie.ch/utilities/js/live-dom-viewer/saved/2430

In fact we seem to have more interop on this than the earlier thing -- 
Chrome and Firefox even fire the exception the spec says to fire.

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'


More information about the whatwg mailing list