|
| 1 | +%%% Canvas2D API |
| 2 | + |
| 3 | +%%% Specification: http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas/ |
| 4 | +%%% Firefox WebIDL: https://github.com/mozilla/gecko-dev/blob/inbound/dom/webidl/CanvasRenderingContext2D.webidl |
| 5 | +%%% Blink WebIDL: https://github.com/mirrors/blink/tree/master/Source/core/html/canvas |
| 6 | + |
| 7 | +%%% ########################################################################### |
| 8 | + |
| 9 | +%const% VARIANCE_MAX := 10 |
| 10 | +%const% VARIANCE_TEMPLATE := "try { %s } catch (e) { }" |
| 11 | +%const% MAX_REPEAT_POWER := 4 |
| 12 | + |
| 13 | +%%% ########################################################################### |
| 14 | + |
| 15 | +%section% := value |
| 16 | + |
| 17 | +Canvas2DContextAttributeOptions := |
| 18 | +alpha:+common:bool+ |
| 19 | +willReadFrequently:+common:bool+ |
| 20 | + |
| 21 | +Canvas2DContextAttributes := |
| 22 | +{ +Canvas2DContextAttributeOptions+ } |
| 23 | +{ %repeat%(+Canvas2DContextAttributeOptions+, ", ") } |
| 24 | + |
| 25 | +canvasWindingRule := |
| 26 | +nonzero |
| 27 | +evenodd |
| 28 | + |
| 29 | +globalCompositeOperation := |
| 30 | +source-atop |
| 31 | +source-in |
| 32 | +source-out |
| 33 | +source-over |
| 34 | +destination-atop |
| 35 | +destination-in |
| 36 | +destination-out |
| 37 | +destination-over |
| 38 | +lighter |
| 39 | +copy |
| 40 | +exclusion |
| 41 | + |
| 42 | +lineJoin := |
| 43 | +butt |
| 44 | +round |
| 45 | +square |
| 46 | + |
| 47 | +lineCap := |
| 48 | +round |
| 49 | +bevel |
| 50 | +miter |
| 51 | + |
| 52 | +textAlign := |
| 53 | +start |
| 54 | +end |
| 55 | +left |
| 56 | +right |
| 57 | +center |
| 58 | + |
| 59 | +textBaseline := |
| 60 | +top |
| 61 | +hanging |
| 62 | +middle |
| 63 | +alphabetic |
| 64 | +ideographic |
| 65 | +bottom |
| 66 | + |
| 67 | +dash_array_values := |
| 68 | +0 |
| 69 | +1 |
| 70 | + |
| 71 | +createPattern_params := |
| 72 | +repeat |
| 73 | +repeat-x |
| 74 | +repeat-y |
| 75 | +no-repeat |
| 76 | + |
| 77 | +hitRegionOptionValues := |
| 78 | +id:"!hitRegion!" |
| 79 | +control: null |
| 80 | + |
| 81 | +hitRegionOptions := |
| 82 | +{ +hitRegionOptionValues+ } |
| 83 | +{ %repeat%(+hitRegionOptionValues+, ", ") } |
| 84 | + |
| 85 | +canvasAttributes := |
| 86 | +!context!.canvas.width=+common:number+; |
| 87 | +!context!.canvas.height=+common:number+; |
| 88 | +!context!.canvas.mozOpaque=+common:bool+; |
| 89 | + |
| 90 | +contextAttributes := |
| 91 | +!context!.globalAlpha=+common:number+; |
| 92 | +!context!.globalCompositeOperation="+globalCompositeOperation+"; |
| 93 | +!context!.strokeStyle="+common:color+"; |
| 94 | +!context!.fillStyle="+common:color+"; |
| 95 | +!context!.shadowOffsetX=+common:number+; |
| 96 | +!context!.shadowOffsetY=+common:number+; |
| 97 | +!context!.shadowBlur="+common:number+"; |
| 98 | +!context!.shadowColor="+common:color+"; |
| 99 | +!context!.lineWidth="+common:number+"; |
| 100 | +!context!.lineCap="+lineCap+"; |
| 101 | +!context!.lineJoin="+lineJoin+"; |
| 102 | +!context!.lineDashOffset=+common:number+; |
| 103 | +!context!.miterLimit=+common:number+; |
| 104 | +!context!.font="+common:font+"; |
| 105 | +!context!.textAlign="+textAlign+"; |
| 106 | +!context!.textBaseline="+textBaseline+"; |
| 107 | + |
| 108 | +Gecko_contextAttributes := |
| 109 | +!context!.mozImageSmoothingEnabled=+common:bool+; |
| 110 | +!context!.mozDashOffset=+common:number+; |
| 111 | +!context!.mozFillRule="+canvasWindingRule+"; |
| 112 | +!context!.mozDash=!dash_array!; |
| 113 | +!context!.mozCurrentTransform=!currentTransform_array!; |
| 114 | +!context!.mozCurrentTransformInverse=!currentTransformInverse_array!; |
| 115 | + |
| 116 | +WebKit_contextAttributes := |
| 117 | +!context!.webkitImageSmoothingEnabled=+common:bool+; |
| 118 | + |
| 119 | +textMetricReadAttributes := |
| 120 | +!textMetrics!.fontBoundingBoxAscent |
| 121 | +!textMetrics!.fontBoundingBoxDescent |
| 122 | +!textMetrics!.actualBoundingBoxAscent |
| 123 | +!textMetrics!.actualBoundingBoxDescent |
| 124 | +!textMetrics!.emHeightAscent |
| 125 | +!textMetrics!.emHeightDescent |
| 126 | +!textMetrics!.hangingBaseline |
| 127 | +!textMetrics!.alphabeticBaseline |
| 128 | +!textMetrics!.ideographicBaseline |
| 129 | + |
| 130 | +contextMethods := |
| 131 | +!context!.save(); |
| 132 | +!context!.restore(); |
| 133 | +!context!.scale(+common:number+, +common:number+); |
| 134 | +!context!.rotate(+common:number+); |
| 135 | +!context!.translate(+common:number+, +common:number+); |
| 136 | +!context!.transform(+common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+); |
| 137 | +!context!.setTransform(+common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+); |
| 138 | +!context!.clearRect(+common:number+, +common:number+, +common:number+, +common:number+); |
| 139 | +!context!.fillRect(+common:number+, +common:number+, +common:number+, +common:number+); |
| 140 | +!context!.strokeRect(+common:number+, +common:number+, +common:number+, +common:number+); |
| 141 | +!context!.beginPath(); |
| 142 | +!context!.stroke(); |
| 143 | +!context!.stroke(!path2D!); |
| 144 | +!context!.fill("+canvasWindingRule+"); |
| 145 | +!context!.fill(!path2D!, "+canvasWindingRule+"); |
| 146 | +!context!.clip("+canvasWindingRule+"); |
| 147 | +!context!.clip(!path2D!, "+canvasWindingRule+"); |
| 148 | +!context!.isPointInPath(+common:number+, +common:number+, "+canvasWindingRule+"); |
| 149 | +!context!.isPointInPath(!path2D!, +common:number+, +common:number+, "+canvasWindingRule+"); |
| 150 | +!context!.isPointInStroke(+common:number+, +common:number+); |
| 151 | +!context!.isPointInStroke(!path2D!, +common:number+, +common:number+); |
| 152 | +!context!.fillText("+common:text+", +common:number+, +common:number+); |
| 153 | +!context!.strokeText("+common:text+", +common:number+, +common:number+); |
| 154 | +!context!.strokeText("+common:text+", +common:number+, +common:number+, +common:number+); |
| 155 | +!context!.measureText("+common:text+"); |
| 156 | +!context!.closePath(); |
| 157 | +!context!.moveTo(+common:number+, +common:number+); |
| 158 | +!context!.lineTo(+common:number+, +common:number+); |
| 159 | +!context!.quadraticCurveTo(+common:number+, +common:number+, +common:number+, +common:number+); |
| 160 | +!context!.bezierCurveTo(+common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+); |
| 161 | +!context!.rect(+common:number+, +common:number+, +common:number+, +common:number+); |
| 162 | +!context!.arcTo(+common:number+, +common:number+, +common:number+, +common:number+, +common:number+); |
| 163 | +!context!.arc(+common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:bool+); |
| 164 | +!context!.setLineDash(!dash_array!); |
| 165 | +!context!.getLineDash(); |
| 166 | +!context!.addHitRegion(!hitRegion!); |
| 167 | +!context!.removeHitRegion(!hitRegion!.id); |
| 168 | +!context!.drawFocusIfNeeded(document.documentElement); |
| 169 | +!context!.drawCustomFocusRing(document.documentElement); |
| 170 | +!canvasGradient!.addColorStop(+common:decimal_number+, "+common:color+"); |
| 171 | +!context!.drawImage(!imageElement!, +common:number+, +common:number+); |
| 172 | +!context!.drawImage(!imageElement!, +common:number+, +common:number+, +common:number+, +common:number+); |
| 173 | +!context!.drawImage(!imageElement!, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+); |
| 174 | +!context!.putImageData(!imageData!, +common:number+, +common:number+); |
| 175 | +!context!.putImageData(!imageData!, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+); |
| 176 | +!context!.canvas.toDataURL("+common:mime_type+"); |
| 177 | +!context!.canvas.toBlob(function(b){n=document.createElement("img"),u=URL.createObjectURL(b);n.onload=function(){URL.revokeObjectURL(u);};n.src=u;document.body.appendChild(n);}, "+common:mime_type+", +common:number+); |
| 178 | + |
| 179 | +Gecko_contextMethods := |
| 180 | +!context!.canvas.mozGetAsFile("+common:text+", "+common:mime_type+"); |
| 181 | + |
| 182 | +Blink_contextMethods := |
| 183 | +!context!.setAlpha(+common:number+); |
| 184 | +!context!.setCompositeOperation("+globalCompositeOperation+"); |
| 185 | +!context!.setLineWidth(+common:number+); |
| 186 | +!context!.setLineCap("+lineCap+"); |
| 187 | +!context!.setLineJoin("+lineJoin+"); |
| 188 | +!context!.setMiterLine(+common:number+); |
| 189 | +!context!.setStrokeColor("+common:color+", +common:number+); |
| 190 | +!context!.setStrokeColor(+common:number+, +common:number+); |
| 191 | +!context!.setStrokeColor(+common:number+, +common:number+, +common:number+, +common:number+); |
| 192 | +!context!.setStrokeColor(+common:number+, +common:number+, +common:number+, +common:number+, +common:number+); |
| 193 | +!context!.setFillColor("+common:color+", +common:number+); |
| 194 | +!context!.setFillColor(+common:number+, +common:number+); |
| 195 | +!context!.setFillColor(+common:number+, +common:number+, +common:number+, +common:number+); |
| 196 | +!context!.setFillColor(+common:number+, +common:number+, +common:number+, +common:number+, +common:number+); |
| 197 | +!context!.clearShadow(); |
| 198 | +!context!.setShadow(+common:number+, +common:number+, +common:number+, "+common:color+", +common:number+); |
| 199 | +!context!.setShadow(+common:number+, +common:number+, +common:number+, +common:number+, +common:number+); |
| 200 | +!context!.setShadow(+common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+); |
| 201 | +!context!.setShadow(+common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+); |
| 202 | +!context!.webkitGetImageDataHD(+common:number+, +common:number+, +common:number+, +common:number+); |
| 203 | +!context!.webkitPutImageDataHD(); |
| 204 | +!context!.getContextAttributes(); |
| 205 | + |
| 206 | +Canvas2D := |
| 207 | ++canvasAttributes+ |
| 208 | ++contextAttributes+ |
| 209 | ++contextMethods+ |
| 210 | ++Gecko_contextAttributes+ |
| 211 | ++Gecko_contextMethods+ |
| 212 | ++textMetricReadAttributes+; |
| 213 | +%%%+WebKit_contextAttributes+ |
| 214 | +%%%+Blink_contextMethods+ |
| 215 | + |
| 216 | +wrapper := |
| 217 | +try { +Canvas2D+ } catch(e) {} |
| 218 | + |
| 219 | +%%% ########################################################################### |
| 220 | + |
| 221 | +%section% := variable |
| 222 | + |
| 223 | +context := |
| 224 | +canvas=document.createElement("canvas"); (document.body || document.documentElement).appendChild(canvas); @context@=canvas.getContext('2d'); |
| 225 | +canvas=document.createElement("canvas"); (document.body || document.documentElement).appendChild(canvas); @context@=canvas.getContext('2d', +Canvas2DContextAttributes+); |
| 226 | + |
| 227 | +imageElement := |
| 228 | +x=document.createElement("img"); x.src="file://%uri%(images)"; @imageElement@=x; |
| 229 | + |
| 230 | +dash_array := |
| 231 | +%%% Prevent static values in the grammar by using undefiend.js library functions. |
| 232 | +x=new Array(%range%(0-32)); for(var i=0; i<x.length; i++) { x[i]=Random.pick([0,1]); }; @dash_array@=x; |
| 233 | + |
| 234 | +currentTransform_array := |
| 235 | +x=new Array(6); for(var i=0; i<x.length; i++){ x[i]=i*+common:number+; }; @currentTransform_array@=x; |
| 236 | + |
| 237 | +currentTransformInverse_array := |
| 238 | +x=new Array(6); for(var i=0; i<x.length; i++) { x[i]=i*+common:number+; }; @currentTransformInverse_array@=x; |
| 239 | + |
| 240 | +canvasGradient := |
| 241 | +@canvasGradient@=!context!.createRadialGradient(+common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+); |
| 242 | + |
| 243 | +canvasPattern := |
| 244 | +@canvasPattern@=!context!.createPattern(!context!.canvas, +createPattern_params+); |
| 245 | + |
| 246 | +imageData := |
| 247 | +@imageData@=!context!.getImageData(+common:number+, +common:number+, +common:number+, +common:number+); |
| 248 | +@imageData@=!context!.createImageData(!imageData!); |
| 249 | +@imageData@=!context!.createImageData(+common:number+, +common:number+); |
| 250 | + |
| 251 | +textMetrics := |
| 252 | +@textMetrics@=!context!.measureText("+common:text+"); |
| 253 | + |
| 254 | +path2D := |
| 255 | +%%%% Todo: http://www.w3.org/TR/SVGTiny12/paths.html#PathDataBNF |
| 256 | +@path2D@=new Path2D("M100,0L200,0L200,100L100,100z"); |
| 257 | + |
| 258 | +hitRegion := |
| 259 | +@hitRegion@=+hitRegionOptions+; |
| 260 | + |
| 261 | +linearGradient := |
| 262 | +@linearGradient@=!context!.createLinearGradient(+common:number+, +common:number+, +common:number+, +common:number+); |
| 263 | +@linearGradient@=!context!.createLinearGradient(+common:number+, +common:number+, +common:number+, +common:number+, +common:number+, +common:number+); |
| 264 | + |
| 265 | +%%% ########################################################################### |
| 266 | + |
| 267 | +%section% := variance |
| 268 | + |
| 269 | +main := |
| 270 | ++Canvas2D+ |
| 271 | +%%%setInterval(function(){\n %repeat%(+wrapper+, "\n ")\n}, 0); |
| 272 | + |