diff options
Diffstat (limited to 'dom/canvas/test/reftest')
-rw-r--r-- | dom/canvas/test/reftest/colors/_generated_reftest.list | 176 | ||||
-rw-r--r-- | dom/canvas/test/reftest/colors/color_canvas.html | 461 | ||||
-rw-r--r-- | dom/canvas/test/reftest/colors/generate_color_canvas_reftests.py | 427 | ||||
-rw-r--r-- | dom/canvas/test/reftest/filters/reftest.list | 4 | ||||
-rw-r--r-- | dom/canvas/test/reftest/reftest.list | 12 |
5 files changed, 1068 insertions, 12 deletions
diff --git a/dom/canvas/test/reftest/colors/_generated_reftest.list b/dom/canvas/test/reftest/colors/_generated_reftest.list new file mode 100644 index 0000000000..29761e3df8 --- /dev/null +++ b/dom/canvas/test/reftest/colors/_generated_reftest.list @@ -0,0 +1,176 @@ +### Generated, do not edit. ### + ### Generated, do not edit. ### + ### Generated, do not edit. ### + +# Generated by `./generate_color_canvas_reftests.py --write`. +# - + +defaults pref(webgl.colorspaces.prototype,true) + +### Generated, do not edit. ### +# - + +# Ensure not white-screening: +!= color_canvas.html?= about:blank +# Ensure differing results with different args: +!= color_canvas.html?e_color=color(srgb,1,0,0) color_canvas.html?e_color=color(srgb,0,1,0) + +### Generated, do not edit. ### +# - +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000) +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200) + ### Generated, do not edit. ### +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000) +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000) + ### Generated, do not edit. ### +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200) +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502) + ### Generated, do not edit. ### +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000) +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000) + ### Generated, do not edit. ### +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502) +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000) + ### Generated, do not edit. ### +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000) +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200) + ### Generated, do not edit. ### +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000) +skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000) +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000) + ### Generated, do not edit. ### +skip-if(cocoaWidget) fails-if(!Android) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000) +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200) +skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200) + ### Generated, do not edit. ### +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200) +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502) +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000) + ### Generated, do not edit. ### +skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000) +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000) +skip-if(cocoaWidget) fails-if(!Android) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000) + ### Generated, do not edit. ### +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000) +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502) +skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502) + ### Generated, do not edit. ### +skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000) +skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000) + ### Generated, do not edit. ### + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502) + == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000) diff --git a/dom/canvas/test/reftest/colors/color_canvas.html b/dom/canvas/test/reftest/colors/color_canvas.html new file mode 100644 index 0000000000..7abbc86255 --- /dev/null +++ b/dom/canvas/test/reftest/colors/color_canvas.html @@ -0,0 +1,461 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset=utf-8> + <title>color_canvas.html</title> + </head> + <!-- +# color_canvas.html + +* Default is a 100x100 'css' canvas-equivalent div, filled with 50% srgb red. + +* We default to showing the settings pane when loaded without a query string. + This way, someone naively opens this in a browser, they can immediately see + all available options. + +* The 'Publish' button updates the url, and so causes the settings pane to + hide. + +* Clicking on the canvas toggles the settings pane for further editing. + --> + <body> + <form id=e_settings><fieldset><legend>Settings</legend> + Width: <input id=e_width type=text value=100> + <br> + Height: <input id=e_height type=text value=100> + <br> + <fieldset><legend>Canvas Context</legend> + Type: <select id=e_context> + <option value=css selected>css</option> + <option value=2d>2d</option> + <option value=webgl>webgl</option> + </select> + <br> + Options: <input id=e_options type=text value={}> + <br> + Colorspace: <input id=e_cspace type=text placeholder=srgb> + <br> + WebGL Format: <input id=e_webgl_format type=text placeholder=RGBA8> + </fieldset> + <br> + Color: <input id=e_color type=text value='color(srgb 0 0.5 0)'> + <br> + <input id=e_publish type=button value=Publish> + <input type=checkbox id=e_publish_omit_defaults checked><label for=e_publish_omit_defaults>Omit defaults</label> + <hr> + </fieldset></form> + <div id=e_canvas_list><canvas></canvas></div> + <script> +'use strict'; + +// - + +function walk_nodes_depth_first(e, fn) { + if (fn(e) === false) return; // Don't stop on `true`, or `undefined`! + for (const c of e.childNodes) { + walk_nodes_depth_first(c, fn); + } +} + +// - + +// Click the canvas to toggle the settings pane. +e_canvas_list.addEventListener('click', () => { + // Toggle display:none to hide/unhide. + e_settings.hidden = !e_settings.hidden; +}); + +// Hide settings initially if there's a query string in the url. +if (window.location.search.startsWith('?')) { + e_settings.hidden = true; +} + +// - + +// Imply .name from .id, because `new FormData` collects based on names. +walk_nodes_depth_first(e_settings, e => { + if (e.id) { + e.name = e.id; + e._default_value = e.value; + } +}); + +// - + +const URL_PARAMS = new URLSearchParams(window.location.search); +URL_PARAMS.forEach((v,k) => { + const e = window[k]; + if (!e) { + if (k) { + console.warn(`Unrecognized setting: ${k} = ${v}`); + } + return; + } + v = decode_url_v(k,v); + e.value = v; +}); + +// - + +globalThis.ASSERT = (() => { + function toPrettyString(arg) { + if (!arg) return ''+arg; + + if (arg.call) { + let s = arg.toString(); + const RE_TRIVIAL_LAMBDA = /\( *\) *=> *(.*)/; + const m = RE_TRIVIAL_LAMBDA.exec(s); + if (m) { + s = '`' + m[1] + '`'; + } + return s; + } + if (arg.constructor == Array) { + return `[${[].join.call(arg, ', ')}]`; + } + return JSON.stringify(arg); + } + + /// new AssertArg(): Construct a wrapper for args to assert functions. + function AssertArg(dict) { + this.label = Object.keys(dict)[0]; + + this.set = function(arg) { + this.arg = arg; + this.value = (arg && arg.call) ? arg.call() : arg; + this.value = toPrettyString(this.value); + }; + this.set(dict[this.label]); + + this.toString = function() { + let ret = `${this.label} ${toPrettyString(this.arg)}`; + if (this.arg.call) { + ret += ` (${this.value})`; + } + return ret; + } + } + + const eq = (a,b) => a == b; + const neq = (a,b) => a != b; + + const CMP_BY_NAME = { + '==': eq, + '!=': neq, + }; + + function IS(cmp, was, expected, _console) { + _console = _console || console; + + _console.assert(was.call, '`was.call` not defined.'); + was = new AssertArg({was}); + expected = new AssertArg({expected}); + + const fn_cmp = CMP_BY_NAME[cmp] || cmp; + + _console.assert(fn_cmp(was.value, expected.value), `${toPrettyString(was.arg)} => ${was.value} not ${cmp} ${expected}`); + if (was.value != expected.value) { + } else if (globalThis.ASSERT && globalThis.ASSERT.verbose) { + const maybe_cmp_str = (cmp == '==') ? '' : ` ${was.value} ${cmp}`; + _console.log(`${toPrettyString(was.arg)} => ${maybe_cmp_str}${expected}`); + } + } + + // - + + const MOCK_CONSOLE = { + _asserts: [], + assert: function(expr, ...args) { + if (!expr) { + this._asserts.push(args); + } + }, + log: function(...args) { + // Don't record. + }, + }; + + // - + // Test `==` + + IS('==', () => 1, 1, MOCK_CONSOLE); + console.assert(MOCK_CONSOLE._asserts.length == 0, MOCK_CONSOLE._asserts); + MOCK_CONSOLE._asserts = []; + + IS('==', () => 2, 2, MOCK_CONSOLE); + console.assert(MOCK_CONSOLE._asserts.length == 0, MOCK_CONSOLE._asserts); + MOCK_CONSOLE._asserts = []; + + IS('==', () => 5, () => 3, MOCK_CONSOLE); + console.assert(MOCK_CONSOLE._asserts.length == 1, MOCK_CONSOLE._asserts); + MOCK_CONSOLE._asserts = []; + + IS('==', () => [1,2], () => [1,2], MOCK_CONSOLE); + console.assert(MOCK_CONSOLE._asserts.length == 0, MOCK_CONSOLE._asserts); + MOCK_CONSOLE._asserts = []; + + // - + // Test `!=` + + IS('!=', () => [1,2,5], () => [1,2,3], MOCK_CONSOLE); + console.assert(MOCK_CONSOLE._asserts.length == 0, MOCK_CONSOLE._asserts); + MOCK_CONSOLE._asserts = []; + + // - + + const ret = { + verbose: false, + IS, + }; + ret.EQ = (was,expected) => ret.IS('==', was, expected); + ret.NEQ = (was,expected) => ret.IS('!=', was, expected); + ret.EEQ = (was,expected) => ret.IS('===', was, expected); + ret.NEEQ = (was,expected) => ret.IS('!==', was, expected); + ret.TRUE = was => ret.EQ(was, true); + ret.FALSE = was => ret.EQ(was, false); + ret.NULL = was => ret.EEQ(was, null); + return ret; +})(); + +// - + +function parse_css_rgb(str) { + // rgb (R ,G ,B /A ) + const m = /rgba?\(([^,]+),([^,]+),([^/)]+)(?: *\/([^)]+))?\)/.exec(str); + if (!m) throw str; + const rgba = m.slice(1,1+4).map((s,i) => { + if (s === undefined && i == 3) { + s = '1'; // Alpha defaults to 1. + } + s = s.trim(); + let v = parseFloat(s); + if (s.endsWith('%')) { + v /= 100; + } else { + if (i < 3) { // r,g,b but not a! + v /= 255; + } + } + return v; + }); + return rgba; +} +ASSERT.EQ(() => parse_css_rgb('rgb(255,255,255)'), [1,1,1,1]); +ASSERT.EQ(() => parse_css_rgb('rgba(255,255,255)'), [1,1,1,1]); +ASSERT.EQ(() => parse_css_rgb('rgb(255,255,255)'), [1,1,1,1]); +ASSERT.EQ(() => parse_css_rgb('rgba(255,255,255)'), [1,1,1,1]); +ASSERT.EQ(() => parse_css_rgb('rgb(20,40,60)'), () => [20/255, 40/255, 60/255, 1]); +ASSERT.EQ(() => parse_css_rgb('rgb(20,40,60 / 0.5)'), () => [20/255, 40/255, 60/255, 0.5]); +ASSERT.EQ(() => parse_css_rgb('rgb(20,40,60 / 0)'), () => [20/255, 40/255, 60/255, 0]); + +// - + +function parse_css_color(str) { + // color ( srgb R G B /A ) + const m = /color\( *([^ ]+) +([^ ]+) +([^ ]+) +([^/)]+)(?:\/([^)]+))?\)/.exec(str); + if (!m) { + return ['srgb', ...parse_css_rgb(str)]; + } + + const cspace = m[1].trim(); + let has_extreme_colors = false; + const rgba = m.slice(2, 2+4).map((s,i) => { + if (s === undefined && i == 3) { + s = '1'; // Alpha defaults to 1. + } + s = s.trim(); + let v = parseFloat(s); + if (s.endsWith('%')) { + v /= 100; + } + if (v < 0 || v > 1) { + has_extreme_colors = true; + } + return v; + }); + if (has_extreme_colors) { + console.warn(`parse_css_color('${str}') has colors outside [0.0,1.0]: ${JSON.stringify(rgba)}`); + } + return [cspace, ...rgba]; +} +ASSERT.EQ(() => parse_css_color('rgb(255,255,255)'), ['srgb',1,1,1,1]); +ASSERT.EQ(() => parse_css_color('rgb(20,40,60 / 0.5)'), () => ['srgb', 20/255, 40/255, 60/255, 0.5]); +ASSERT.EQ(() => parse_css_color('color(srgb 1 0 1 /0.3)'), ['srgb',1,0,1,0.3]); +ASSERT.EQ(() => parse_css_color('color(display-p3 1 0% 100%/ 30%)'), ['display-p3',1,0,1,0.3]); + +// - + +class CssColor { + constructor(cspace, r,g,b,a=1) { + this.cspace = cspace; + this.rgba = [this.r, this.g, this.b, this.a] = [r,g,b,a]; + this.rgb = this.rgba.slice(0,3); + this.tuple = [this.cspace, ...this.rgba]; + } + + toString() { + return `color(${this.cspace} ${this.rgb.join(' ')} / ${this.a})`; + } +}; +CssColor.parse = function(str) { + return new CssColor(...parse_css_color(str)); +} + +{ + let STR; + // Test round-trip. + STR = 'color(display-p3 1 0 1 / 0.3)'; + ASSERT.EQ(() => CssColor.parse(STR).toString(), STR); + + // Test round-trip normalization + ASSERT.EQ(() => CssColor.parse('color( display-p3 1 0 1/30% )').toString(), 'color(display-p3 1 0 1 / 0.3)'); +} + +// - + +function redraw() { + while (e_canvas_list.firstChild) { + e_canvas_list.removeChild(e_canvas_list.firstChild); + } + + const c = make_canvas(e_color.value.trim()); + c.style.border = '4px solid black'; + e_canvas_list.appendChild(c); +} + +function fill_canvas_rect(context /*: CanvasRenderingContext | WebGLRenderingContext*/, css_color, rect=null) { + rect = rect || {left: 0, top: 0, w: context.canvas.width, h: context.canvas.height}; + + const is_c2d = ('fillRect' in context); + if (is_c2d) { + const c2d = context; + c2d.fillStyle = css_color; + c2d.fillRect(rect.left, rect.top, rect.w, rect.h); + return; + } + + const is_webgl = ('drawArrays' in context); + if (is_webgl) { + const gl = context; + console.assert(context.canvas.width == gl.drawingBufferWidth, context.canvas.width, '!=', gl.drawingBufferWidth); + console.assert(context.canvas.height == gl.drawingBufferHeight, context.canvas.height, '!=', gl.drawingBufferHeight); + + gl.enable(gl.SCISSOR_TEST); + gl.disable(gl.DEPTH_TEST); + const bottom = rect.top + rect.h; // in y-down c2d coords + gl.scissor(rect.left, context.canvas.height - bottom, rect.w, rect.h); + + const canvas_cspace = context.drawingBufferColorSpace || 'srgb'; + if (css_color.cspace != canvas_cspace) { + console.warn(`Ignoring mismatched color vs webgl canvas cspace: ${css_color.cspace} vs ${canvas_cspace}`); + } + gl.clearColor(...css_color.rgba); + gl.clear(gl.COLOR_BUFFER_BIT); + return; + } + + console.error('Unhandled context kind:', context); +} + +window.e_canvas = null; + +function make_canvas(css_color) { + css_color = CssColor.parse(css_color); + + // `e_width` and e_friends are elements (by id) that we added to the raw HTML above. + // `e_width` is an old shorthand for `window.e_width || document.getElementById('e_width')`. + const W = parseInt(e_width.value); + const H = parseInt(e_height.value); + if (e_context.value == 'css') { + e_canvas = document.createElement('div'); + e_canvas.style.width = `${W}px`; + e_canvas.style.height = `${H}px`; + e_canvas.style.backgroundColor = css_color; + return e_canvas; + } + e_canvas = document.createElement('canvas'); + e_canvas.width = W; + e_canvas.height = H; + + let requested_options = JSON.parse(e_options.value); + requested_options.colorSpace = e_cspace.value || undefined; + + const context = e_canvas.getContext(e_context.value, requested_options); + if (requested_options.colorSpace) { + if (!context.drawingBufferColorSpace) { + console.warn(`${context.constructor.name}.drawingBufferColorSpace not supported by browser.`); + } else { + context.drawingBufferColorSpace = requested_options.colorSpace; + } + } + + if (e_webgl_format.value) { + if (!context.drawingBufferStorage) { + console.warn(`${context.constructor.name}.drawingBufferStorage not supported by browser.`); + } else { + context.drawingBufferStorage(W, H, context[e_webgl_format.value]); + } + } + + let actual_options; + if (!context.getContextAttributes) { + console.warn(`${canvas.constructor.name}.getContextAttributes not supported by browser.`); + actual_options = requested_options; + } else { + actual_options = context.getContextAttributes(); + } + + // - + + fill_canvas_rect(context, css_color); + + return e_canvas; +} + +e_settings.addEventListener('change', async () => { + redraw(); + const e_updated = document.createElement('i'); + e_updated.textContent = '(Updated!)'; + document.body.appendChild(e_updated); + await new Promise(go => setTimeout(go, 1000)); + document.body.removeChild(e_updated); +}); +redraw(); + +// - + +function encode_url_v(k,v) { + if (k == 'e_color') { + v = v.replaceAll(' ', ','); + } + console.assert(!v.includes(' '), v); + return v +} +function decode_url_v(k,v) { + console.assert(!v.includes(' '), v); + if (k == 'e_color') { + v = v.replaceAll(',', ' '); + } + return v +} +ASSERT.EQ(() => decode_url_v('e_color', encode_url_v('e_color', 'color(srgb 1 0 0)')), 'color(srgb 1 0 0)') + +e_publish.addEventListener('click', () => { + const fd = new FormData(e_settings); + let settings = []; + for (let [k,v] of fd) { + const e = window[k]; + if (e_publish_omit_defaults.checked && v == e._default_value) continue; + + v = encode_url_v(k,v); + settings.push(`${k}=${v}`); + } + settings = settings.join('&'); + if (!settings) { + settings = '='; // Empty key-value pair is 'publish with default settings' + } + window.location.search = '?' + settings; +}); + </script> + </body> +</html> diff --git a/dom/canvas/test/reftest/colors/generate_color_canvas_reftests.py b/dom/canvas/test/reftest/colors/generate_color_canvas_reftests.py new file mode 100644 index 0000000000..8c1e5f3788 --- /dev/null +++ b/dom/canvas/test/reftest/colors/generate_color_canvas_reftests.py @@ -0,0 +1,427 @@ +#! python3 + +# Typecheck: +# `pip -m mypy generate_color_canvas_reftests.py` +# +# Run: +# `./generate_color_canvas_reftests.py [--write]` + +import functools +import json +import math +import pathlib +import re +import sys +from typing import Iterable, NamedTuple, TypeVar + +ARGS = sys.argv[1:] +DEST = pathlib.Path(__file__).parent / "_generated_reftest.list" + +COL_DELIM = " " +COL_ALIGNMENT = 4 + +# - + +T = TypeVar("T") +U = TypeVar("U") + +# - + + +# crossCombine([{a:false},{a:5}], [{},{b:5}]) +# [{a:false}, {a:true}, {a:false,b:5}, {a:true,b:5}] +def cross_combine(*args_tup: list[dict]) -> list[dict]: + args = list(args_tup) + for i, a in enumerate(args): + assert type(a) == list, f"Arg{i} is {type(a)}, expected {list}." + + def cross_combine2(listA, listB): + listC = [] + for a in listA: + for b in listB: + c = dict() + c.update(a) + c.update(b) + listC.append(c) + return listC + + res: list[dict] = [dict()] + while True: + try: + next = args.pop(0) + except IndexError: + break + res = cross_combine2(res, next) + return res + + +# keyed_alternatives('count', [1,2,3]) -> [{count: 1}, {count: 2}, {count: 3}] +def keyed_alternatives(key: T, vals: Iterable[U]) -> list[dict[T, U]]: + """ + res = [] + for v in vals: + d = dict() + d[key] = v + res.append(d) + return res + """ + # return [dict([[key,v]]) for v in vals] + return [{key: v} for v in vals] + + +# - + + +def eprint(*args, **kwargs): + sys.stdout.flush() + print(*args, file=sys.stderr, **kwargs) + sys.stderr.flush() + + +# - + +# color_canvas.html?e_width=100&e_height=100&e_context=css&e_options={}&e_cspace=&e_webgl_format=&e_color=rgb(127,0,0) + +CSPACE_LIST = ["srgb", "display-p3"] +CANVAS_CSPACES = keyed_alternatives("e_cspace", CSPACE_LIST) + +RGB_LIST = [ + "0.000 0.000 0.000", + "0.200 0.200 0.200", # 0.2*255 = 51 + "0.200 0.000 0.000", + "0.000 0.200 0.000", + "0.000 0.000 0.200", + "0.502 0.502 0.502", # 0.502*255 = 128.01 + "0.502 0.000 0.000", + "0.000 0.502 0.000", + "0.000 0.000 0.502", + "1.000 1.000 1.000", + #'1.000 0.000 0.000', # These will hit gamut clipping on most displays. + #'0.000 1.000 0.000', + #'0.000 0.000 1.000', +] + +WEBGL_COLORS = keyed_alternatives("e_color", [f"color(srgb {rgb})" for rgb in RGB_LIST]) + +C2D_COLORS = [] +for cspace in CSPACE_LIST: + C2D_COLORS += keyed_alternatives( + "e_color", [f"color({cspace} {rgb})" for rgb in RGB_LIST] + ) + +# - + +WEBGL_FORMATS = keyed_alternatives( + "e_webgl_format", + [ + "RGBA8", + # Bug 1883748: (webgl.drawingbufferStorage) + #'SRGB8_ALPHA8', + #'RGBA16F', + ], +) +WEBGL = cross_combine( + [{"e_context": "webgl"}], WEBGL_FORMATS, CANVAS_CSPACES, WEBGL_COLORS +) + +# - + +C2D_OPTIONS_COMBOS = cross_combine( + keyed_alternatives("willReadFrequently", ["true", "false"]), # E.g. D2D vs Skia + # keyed_alternatives('alpha', ['true','false']) +) +C2D_OPTIONS = [ + json.dumps(config, separators=(",", ":")) for config in C2D_OPTIONS_COMBOS +] + +C2D = cross_combine( + [{"e_context": "2d"}], + keyed_alternatives("e_options", C2D_OPTIONS), + CANVAS_CSPACES, + C2D_COLORS, +) + +# - + +COMBOS: list[dict[str, str]] = cross_combine(WEBGL + C2D) + +eprint(f"{len(COMBOS)} combinations...") + +# - + +Config = dict[str, str] + + +class CssColor(NamedTuple): + cspace: str + rgb: str + + def rgb_vals(self) -> tuple[float, float, float]: + (r, g, b) = [float(z) for z in self.rgb.split(" ")] + return (r, g, b) + + def is_same_color(x, y) -> bool: + if x == y: + return True + (r, g, b) = x.rgb_vals() + if x.rgb == y.rgb and r == g and g == b: + return True + return False + + +class Reftest(NamedTuple): + notes: list[str] + op: str + test_config: Config + ref_config: Config + + +def make_ref_config(color: CssColor) -> Config: + return { + "e_context": "css", + "e_color": f"color({color.cspace} {color.rgb})", + } + + +class ColorReftest(NamedTuple): + notes: list[str] + test_config: Config + ref_color: CssColor + + def to_reftest(self): + ref_config = make_ref_config(self.ref_color) + return Reftest(self.notes.copy(), "==", self.test_config.copy(), ref_config) + + +class Expectation(NamedTuple): + notes: list[str] + test_config: Config + color: CssColor + + +def parse_css_color(s: str) -> CssColor: + m = re.match("color[(]([^)]+)[)]", s) + assert m, s + (cspace, rgb) = m.group(1).split(" ", 1) + return CssColor(cspace, rgb) + + +def correct_color_from_test_config(test_config: Config) -> CssColor: + canvas_cspace = test_config["e_cspace"] + if not canvas_cspace: + canvas_cspace = "srgb" + + correct_color = parse_css_color(test_config["e_color"]) + if test_config["e_context"] == "webgl": + # Webgl ignores the color's cspace, because webgl has no concept of + # source colorspace for clears/draws to the backbuffer. + # This (correct) behavior is as if the color's cspace were overwritten by the + # cspace of the canvas. (so expect that) + correct_color = CssColor(canvas_cspace, correct_color.rgb) + + return correct_color + + +# ------------------------------------- +# ------------------------------------- +# ------------------------------------- +# Choose (multiple?) reference configs given a test config. + + +def reftests_from_config(test_config: Config) -> Iterable[ColorReftest]: + correct_color = correct_color_from_test_config(test_config) + + if test_config["e_context"] == "2d": + # Canvas2d generally has the same behavior as css, so expect all passing. + yield ColorReftest([], test_config, correct_color) + return + + assert test_config["e_context"] == "webgl", test_config["e_context"] + + # - + + def reftests_from_expected_color( + notes: list[str], expected_color: CssColor + ) -> Iterable[ColorReftest]: + # If expecting failure, generate two tests, both expecting failure: + # 1. expected-fail test == correct_color + # 2. expected-pass test == (incorrect) expected_color + # If we fix an error, we'll see one unexpected-pass and one unexpected-fail. + # If we get a new wrong answer, we'll see one unexpected-fail. + + if not expected_color.is_same_color(correct_color): + yield ColorReftest(notes + ["fails"], test_config, correct_color) + yield ColorReftest(notes, test_config, expected_color) + else: + yield ColorReftest(notes, test_config, correct_color) + + # - + # On Mac, (with the pref) we do tag the IOSurface with the right cspace. + # On other platforms, Webgl always outputs in the display color profile + # right now. This is the same as "srgb". + + expected_color_srgb = CssColor("srgb", correct_color.rgb) + # Mac + yield from reftests_from_expected_color(["skip-if(!cocoaWidget)"], correct_color) + # Win, Lin, Android + yield from reftests_from_expected_color( + ["skip-if(cocoaWidget) "], expected_color_srgb + ) + + +# - + + +def amended_notes_from_reftest(reftest: ColorReftest) -> list[str]: + notes = reftest.notes[:] + + ref_rgb_vals = reftest.ref_color.rgb_vals() + is_green_only = ref_rgb_vals == (0, ref_rgb_vals[1], 0) + if ( + "fails" in reftest.notes + and reftest.test_config["e_context"] == "webgl" + and reftest.test_config["e_cspace"] == "display-p3" + and is_green_only + ): + # Android's display bitdepth rounds srgb green and p3 green to the same thing. + notes[notes.index("fails")] = "fails-if(!Android)" + + return notes + + +# ------------------------------------- +# ------------------------------------- +# ------------------------------------- +# Ok, back to implementation. + + +def encode_url_v(k, v): + if k == "e_color": + # reftest harness can't deal with spaces in urls, and 'color(srgb%201%200%200)' is hard to read. + v = v.replace(" ", ",") + + assert " " not in v, (k, v) + return v + + +# Cool: +assert encode_url_v("e_color", "color(srgb 0 0 0)") == "color(srgb,0,0,0)" +# Unfortunate, but tolerable: +assert encode_url_v("e_color", "color(srgb 0 0 0)") == "color(srgb,,,0,,,0,,,0)" + +# - + + +def url_from_config(kvs: Config) -> str: + parts = [f"{k}={encode_url_v(k,v)}" for k, v in kvs.items()] + url = "color_canvas.html?" + "&".join(parts) + return url + + +# - + +color_reftests: list[ColorReftest] = [] +for c in COMBOS: + color_reftests += reftests_from_config(c) +color_reftests = [ + ColorReftest(amended_notes_from_reftest(r), r.test_config, r.ref_color) + for r in color_reftests +] +reftests = [r.to_reftest() for r in color_reftests] + +# - + +HEADINGS = ["# annotations", "op", "test", "reference"] +table: list[list[str]] = [HEADINGS] +table = [ + [ + " ".join(r.notes), + r.op, + url_from_config(r.test_config), + url_from_config(r.ref_config), + ] + for r in reftests +] + +# - + + +def round_to(a, b: int) -> int: + return int(math.ceil(a / b) * b) + + +def aligned_lines_from_table( + rows: list[list[str]], col_delim=" ", col_alignment=4 +) -> Iterable[str]: + max_col_len = functools.reduce( + lambda accum, input: [max(r, len(c)) for r, c in zip(accum, input)], + rows, + [0 for _ in rows[0]], + ) + max_col_len = [round_to(x, col_alignment) for x in max_col_len] + + for i, row in enumerate(rows): + parts = [s + (" " * (col_len - len(s))) for s, col_len in zip(row, max_col_len)] + line = col_delim.join(parts) + yield line + + +# - + +GENERATED_FILE_LINE = "### Generated, do not edit. ###" + +lines = list(aligned_lines_from_table(table, COL_DELIM, COL_ALIGNMENT)) +WARN_EVERY_N_LINES = 5 +i = WARN_EVERY_N_LINES - 1 +while i < len(lines): + lines.insert(i, " " + GENERATED_FILE_LINE) + i += WARN_EVERY_N_LINES + +# - + +GENERATED_BY_ARGS = [f"./{pathlib.Path(__file__).name}"] + ARGS + +REFTEST_LIST_PREAMBLE = f"""\ +{GENERATED_FILE_LINE} + {GENERATED_FILE_LINE} + {GENERATED_FILE_LINE} + +# Generated by `{' '.join(GENERATED_BY_ARGS)}`. +# - + +defaults pref(webgl.colorspaces.prototype,true) + +{GENERATED_FILE_LINE} +# - + +# Ensure not white-screening: +!= {url_from_config({})+'='} about:blank +# Ensure differing results with different args: +!= {url_from_config({'e_color':'color(srgb 1 0 0)'})} {url_from_config({'e_color':'color(srgb 0 1 0)'})} + +{GENERATED_FILE_LINE} +# - +""" + +lines.insert(0, REFTEST_LIST_PREAMBLE) +lines.append("") + +# - + +for line in lines: + print(line) + +if "--write" not in ARGS: + eprint("Use --write to write. Exiting...") + sys.exit(0) + +# - + +eprint("Concatenating...") +file_str = "\n".join([line.rstrip() for line in lines]) + +eprint(f"Writing to {DEST}...") +DEST.write_bytes(file_str.encode()) +eprint("Done!") + +sys.exit(0) diff --git a/dom/canvas/test/reftest/filters/reftest.list b/dom/canvas/test/reftest/filters/reftest.list index cf851e2a3b..e4f21db6ce 100644 --- a/dom/canvas/test/reftest/filters/reftest.list +++ b/dom/canvas/test/reftest/filters/reftest.list @@ -1,7 +1,7 @@ == default-color.html ref.html == drop-shadow.html ref.html == drop-shadow-transformed.html ref.html -fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||azureSkia,0-1,0-1500) == global-alpha.html global-alpha-ref.html +fuzzy(0-1,0-1500) == global-alpha.html global-alpha-ref.html == global-composite-operation.html global-composite-operation-ref.html == liveness.html ref.html == liveness-document-open.html data:text/html,PASS @@ -20,7 +20,7 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||azureSkia,0-1,0-1500) == gl == units-off-screen.html ref.html fuzzy(0-2,0-700) == fillText-with-filter-opacity-1.html fillText-with-filter-opacity-1-ref.html fuzzy(0-1,0-302) == fillText-with-filter-opacity-2.html fillText-with-filter-opacity-2-ref.html -fuzzy(0-1,0-600) fuzzy-if(d2d&&!swgl,0-36,0-15) == strokeText-with-filter-grayscale-1.html strokeText-with-filter-grayscale-1-ref.html +fuzzy(0-1,0-600) fuzzy-if(winWidget&&!swgl,0-36,0-15) == strokeText-with-filter-grayscale-1.html strokeText-with-filter-grayscale-1-ref.html fuzzy(0-1,0-600) == strokeText-with-filter-grayscale-2.html strokeText-with-filter-grayscale-2-ref.html != fillText-with-shadow-1.html fillText-without-shadow-1-ref.html != fillText-with-shadow-2.html fillText-without-shadow-2-ref.html diff --git a/dom/canvas/test/reftest/reftest.list b/dom/canvas/test/reftest/reftest.list index 0eef0b3daf..26f373b32c 100644 --- a/dom/canvas/test/reftest/reftest.list +++ b/dom/canvas/test/reftest/reftest.list @@ -1,4 +1,5 @@ # Canvas Filter Reftests +include colors/_generated_reftest.list include filters/reftest.list include color_quads.list @@ -26,15 +27,6 @@ skip-if(Android) == webgl-resize-test.html wrapper.html?green.png # Check that captureStream() displays in a local video element skip-if(Android) == webgl-capturestream-test.html?preserve wrapper.html?green.png -# Some of the failure conditions are a little weird. I'm (jgilbert) setting these based on -# failures encountered when running on Try, and then targetting the Try config by -# differences in the `sandbox` contents. That is, I'm labeling based on symptoms rather -# than cause. -# WinXP R: winWidget && layersGPUAccelerated && !d3d11 -# Win7+ R: winWidget && layersGPUAccelerated && d3d11 -# Win7+ Ru: winWidget && !layersGPUAccelerated && d3d11 -# (Note that we have to remove spaces when used below) - # IMPORTANT: Expected outcomes are evaluated left-to-right, and they replace eachother. # That means that if an unconditional status (`fuzzy()`) is to the right of another status # (such as fails-if), it will overwrite the old status. @@ -233,7 +225,7 @@ fuzzy(0-1,0-150) == clip-multiple-move-2.html clip-multiple-move-2-ref.html == stroketext-shadow.html stroketext-shadow-ref.html # focus rings -fuzzy(0-1,0-2) skip-if(cocoaWidget||winWidget||gtkWidget) needs-focus == drawFocusIfNeeded.html drawFocusIfNeeded-ref.html +fuzzy(0-1,0-2) skip-if(cocoaWidget||gtkWidget||winWidget) needs-focus == drawFocusIfNeeded.html drawFocusIfNeeded-ref.html # Check that captureStream() displays in a local video element == capturestream.html wrapper.html?green.png |