| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library android_extension; | |
| 6 import 'dart:async'; | |
| 7 | |
| 8 // A VERY simplified DOM. | |
| 9 | |
| 10 class BodyElement { | |
| 11 List _nodes; | |
| 12 get nodes => _nodes; | |
| 13 BodyElement() : _nodes = new List(); | |
| 14 } | |
| 15 | |
| 16 // The OpenGLUI "equivalent" of Window. | |
| 17 | |
| 18 typedef void RequestAnimationFrameCallback(num highResTime); | |
| 19 | |
| 20 class Window { | |
| 21 static int _nextId = 0; | |
| 22 List _callbacks; | |
| 23 List _arguments; | |
| 24 | |
| 25 Window._internal() : _callbacks = [], _arguments = []; | |
| 26 | |
| 27 int _scheduleCallback(callback, [argument]) { | |
| 28 _callbacks.add(callback); | |
| 29 _arguments.add(argument); | |
| 30 return _callbacks.length - 1; | |
| 31 } | |
| 32 | |
| 33 int requestAnimationFrame(RequestAnimationFrameCallback callback) { | |
| 34 return _scheduleCallback(callback, | |
| 35 (new DateTime.now()).millisecondsSinceEpoch); | |
| 36 } | |
| 37 | |
| 38 void cancelAnimationFrame(id) { | |
| 39 _callbacks[id] = null; | |
| 40 _arguments[id] = null; | |
| 41 } | |
| 42 | |
| 43 get animationFrame { | |
| 44 // TODO(gram) | |
| 45 return null; | |
| 46 } | |
| 47 | |
| 48 void _dispatch() { | |
| 49 // We clear out the callbacks map before calling any callbacks, | |
| 50 // as they may schedule new callbacks. | |
| 51 var oldcallbacks = _callbacks; | |
| 52 var oldarguments = _arguments; | |
| 53 _callbacks = []; | |
| 54 _arguments = []; | |
| 55 for (var i = 0; i < oldcallbacks.length; i++) { | |
| 56 if (oldcallbacks[i] != null) { | |
| 57 oldcallbacks[i](oldarguments[i]); | |
| 58 } | |
| 59 } | |
| 60 // We could loop around here to handle any callbacks | |
| 61 // scheduled in processing the prior ones, but then we | |
| 62 // need some other mechanism for trying to get requestAnimationFrame | |
| 63 // callbacks at 60fps. | |
| 64 } | |
| 65 | |
| 66 Map localStorage = {}; // TODO(gram) - Make this persistent. | |
| 67 } | |
| 68 | |
| 69 Window window = new Window._internal(); | |
| 70 | |
| 71 // The OpenGLUI "equivalent" of HtmlDocument. | |
| 72 class Document extends Node { | |
| 73 BodyElement _body; | |
| 74 get body => _body; | |
| 75 Document._internal() : _body = new BodyElement(); | |
| 76 } | |
| 77 | |
| 78 Document document = new Document._internal(); | |
| 79 | |
| 80 // TODO(gram): make private and call from within library context. | |
| 81 update_() { | |
| 82 log("in update"); | |
| 83 window._dispatch(); | |
| 84 } | |
| 85 | |
| 86 // Event handling. This is very kludgy for now, especially the | |
| 87 // bare-bones Stream stuff! | |
| 88 | |
| 89 typedef void EventListener(Event event); | |
| 90 | |
| 91 class EventTarget { | |
| 92 static Map<EventTarget, Map<String, List<EventListener>>> | |
| 93 _listeners = new Map(); | |
| 94 | |
| 95 static get listeners => _listeners; | |
| 96 | |
| 97 bool dispatchEvent(Event event) { | |
| 98 var rtn = false; | |
| 99 if (!_listeners.containsKey(this)) return false; | |
| 100 var listeners = _listeners[this]; | |
| 101 if (!listeners.containsKey(event.type)) return false; | |
| 102 var eventListeners = listeners[event.type]; | |
| 103 for (var eventListener in eventListeners) { | |
| 104 if (eventListener != null) { | |
| 105 eventListener(event); | |
| 106 rtn = true; | |
| 107 } | |
| 108 } | |
| 109 return rtn; | |
| 110 } | |
| 111 | |
| 112 void addListener(String eventType, EventListener handler) { | |
| 113 if (!_listeners.containsKey(this)) { | |
| 114 _listeners[this] = new Map(); | |
| 115 } | |
| 116 var listeners = _listeners[this]; | |
| 117 if (!listeners.containsKey(eventType)) { | |
| 118 listeners[eventType] = new List(); | |
| 119 } | |
| 120 var event_listeners = listeners[eventType]; | |
| 121 for (var i = 0; i < event_listeners.length; i++) { | |
| 122 if (event_listeners[i] == null) { | |
| 123 event_listeners[i] = handler; | |
| 124 return; | |
| 125 } | |
| 126 } | |
| 127 event_listeners.add(handler); | |
| 128 } | |
| 129 | |
| 130 void removeListener(String eventType, EventListener handler) { | |
| 131 if (_listeners.containsKey(this)) { | |
| 132 var listeners = _listeners[this]; | |
| 133 if (listeners.containsKey(eventType)) { | |
| 134 var event_listeners = listeners[eventType]; | |
| 135 for (var i = 0; i < event_listeners.length; i++) { | |
| 136 if (event_listeners[i] == handler) { | |
| 137 event_listeners[i] = null; | |
| 138 break; | |
| 139 } | |
| 140 } | |
| 141 } | |
| 142 } | |
| 143 } | |
| 144 } | |
| 145 | |
| 146 class Event { | |
| 147 final String type; | |
| 148 EventTarget target; | |
| 149 Event(String type) : this.type = type; | |
| 150 preventDefault() {} | |
| 151 stopPropagation() {} | |
| 152 } | |
| 153 | |
| 154 class KeyboardEvent extends Event { | |
| 155 final bool altKey; | |
| 156 final bool ctrlKey; | |
| 157 final bool shiftKey; | |
| 158 final int keyCode; | |
| 159 | |
| 160 KeyboardEvent(String type, int keycode, bool alt, bool ctrl, bool shift) | |
| 161 : super(type), | |
| 162 keyCode = keycode, | |
| 163 altKey = alt, | |
| 164 ctrlKey = ctrl, | |
| 165 shiftKey = shift { | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 class MouseEvent extends Event { | |
| 170 final int screenX, screenY; | |
| 171 final int clientX, clientY; | |
| 172 | |
| 173 MouseEvent(String type, int x, int y) | |
| 174 : super(type), | |
| 175 screenX = x, | |
| 176 screenY = y, | |
| 177 clientX = x, | |
| 178 clientY = y { | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> { | |
| 183 int _pauseCount = 0; | |
| 184 EventTarget _target; | |
| 185 final String _eventType; | |
| 186 var _onData; | |
| 187 | |
| 188 _EventStreamSubscription(this._target, this._eventType, this._onData) { | |
| 189 _tryResume(); | |
| 190 } | |
| 191 | |
| 192 void cancel() { | |
| 193 if (_canceled) { | |
| 194 throw new StateError("Subscription has been canceled."); | |
| 195 } | |
| 196 | |
| 197 _unlisten(); | |
| 198 // Clear out the target to indicate this is complete. | |
| 199 _target = null; | |
| 200 _onData = null; | |
| 201 } | |
| 202 | |
| 203 bool get _canceled => _target == null; | |
| 204 | |
| 205 void onData(void handleData(T event)) { | |
| 206 if (_canceled) { | |
| 207 throw new StateError("Subscription has been canceled."); | |
| 208 } | |
| 209 // Remove current event listener. | |
| 210 _unlisten(); | |
| 211 | |
| 212 _onData = handleData | |
| 213 _tryResume(); | |
| 214 } | |
| 215 | |
| 216 /// Has no effect. | |
| 217 void onError(void handleError(Object error)) {} | |
| 218 | |
| 219 /// Has no effect. | |
| 220 void onDone(void handleDone()) {} | |
| 221 | |
| 222 void pause([Future resumeSignal]) { | |
| 223 if (_canceled) { | |
| 224 throw new StateError("Subscription has been canceled."); | |
| 225 } | |
| 226 ++_pauseCount; | |
| 227 _unlisten(); | |
| 228 | |
| 229 if (resumeSignal != null) { | |
| 230 resumeSignal.whenComplete(resume); | |
| 231 } | |
| 232 } | |
| 233 | |
| 234 bool get _paused => _pauseCount > 0; | |
| 235 | |
| 236 void resume() { | |
| 237 if (_canceled) { | |
| 238 throw new StateError("Subscription has been canceled."); | |
| 239 } | |
| 240 if (!_paused) { | |
| 241 throw new StateError("Subscription is not paused."); | |
| 242 } | |
| 243 --_pauseCount; | |
| 244 _tryResume(); | |
| 245 } | |
| 246 | |
| 247 void _tryResume() { | |
| 248 if (_onData != null && !_paused) { | |
| 249 _target.addListener(_eventType, _onData); | |
| 250 } | |
| 251 } | |
| 252 | |
| 253 void _unlisten() { | |
| 254 if (_onData != null) { | |
| 255 _target.removeListener(_eventType, _onData); | |
| 256 } | |
| 257 } | |
| 258 | |
| 259 Future asFuture([var futureValue]) { | |
| 260 // We just need a future that will never succeed or fail. | |
| 261 Completer completer = new Completer(); | |
| 262 return completer.future; | |
| 263 } | |
| 264 } | |
| 265 | |
| 266 class _EventStream<T extends Event> extends Stream<T> { | |
| 267 final Object _target; | |
| 268 final String _eventType; | |
| 269 | |
| 270 _EventStream(this._target, this._eventType); | |
| 271 | |
| 272 // DOM events are inherently multi-subscribers. | |
| 273 Stream<T> asBroadcastStream() => this; | |
| 274 bool get isBroadcast => true; | |
| 275 | |
| 276 StreamSubscription<T> listen(void onData(T event), | |
| 277 { void onError(Object error), | |
| 278 void onDone(), | |
| 279 bool cancelOnError}) { | |
| 280 | |
| 281 return new _EventStreamSubscription<T>( | |
| 282 this._target, this._eventType, onData); | |
| 283 } | |
| 284 } | |
| 285 | |
| 286 class Node extends EventTarget { | |
| 287 Stream<KeyboardEvent> get onKeyDown => new _EventStream(this, 'keydown'); | |
| 288 Stream<KeyboardEvent> get onKeyUp => new _EventStream(this, 'keyup'); | |
| 289 Stream<MouseEvent> get onMouseDown => new _EventStream(this, 'mousedown'); | |
| 290 Stream<MouseEvent> get onMouseMove => new _EventStream(this, 'mousemove'); | |
| 291 Stream<MouseEvent> get onMouseUp => new _EventStream(this, 'mouseup'); | |
| 292 } | |
| 293 | |
| 294 // TODO(gram): If we support more than one on-screen canvas, we will | |
| 295 // need to filter dispatched mouse and key events by the target Node | |
| 296 // with more granularity; right now we just iterate through DOM nodes | |
| 297 // until we find one that handles the event. | |
| 298 _dispatchEvent(Event event) { | |
| 299 assert(document.body.nodes.length <= 1); | |
| 300 for (var target in document.body.nodes) { | |
| 301 event.target = target; | |
| 302 if (target.dispatchEvent(event)) { | |
| 303 return; | |
| 304 } | |
| 305 } | |
| 306 document.dispatchEvent(event); | |
| 307 } | |
| 308 | |
| 309 _dispatchKeyEvent(String type, int keyCode, bool alt, bool ctrl, bool shift) { | |
| 310 _dispatchEvent(new KeyboardEvent(type, keyCode, alt, ctrl, shift)); | |
| 311 } | |
| 312 | |
| 313 _dispatchMouseEvent(String type, double x, double y) { | |
| 314 _dispatchEvent(new MouseEvent(type, x.toInt(), y.toInt())); | |
| 315 } | |
| 316 | |
| 317 // These next few are called by vmglue.cc. | |
| 318 onKeyDown_(int when, int keyCode, bool alt, bool ctrl, bool shift, int repeat) | |
| 319 => _dispatchKeyEvent('keydown', keyCode, alt, ctrl, shift); | |
| 320 | |
| 321 onKeyUp_(int when, int keyCode, bool alt, bool ctrl, bool shift, int repeat) => | |
| 322 _dispatchKeyEvent('keyup', keyCode, alt, ctrl, shift); | |
| 323 | |
| 324 onMouseDown_(int when, double x, double y) => | |
| 325 _dispatchMouseEvent('mousedown', x, y); | |
| 326 | |
| 327 onMouseMove_(int when, double x, double y) => | |
| 328 _dispatchMouseEvent('mousemove', x, y); | |
| 329 | |
| 330 onMouseUp_(int when, double x, double y) => | |
| 331 _dispatchMouseEvent('mouseup', x, y); | |
| 332 | |
| 333 class CanvasElement extends Node { | |
| 334 int height; | |
| 335 int width; | |
| 336 | |
| 337 CanvasRenderingContext2D _context2d; | |
| 338 WebGLRenderingContext _context3d; | |
| 339 | |
| 340 // For use with drawImage, we want to support a src property | |
| 341 // like ImageElement, which maps to the context handle in native | |
| 342 // code. | |
| 343 get src => "context2d://${_context2d.handle}"; | |
| 344 | |
| 345 CanvasElement({int width, int height}) | |
| 346 : super() { | |
| 347 this.width = (width == null) ? getDeviceScreenWidth() : width; | |
| 348 this.height = (height == null) ? getDeviceScreenHeight() : height; | |
| 349 getContext('2d'); | |
| 350 } | |
| 351 | |
| 352 CanvasRenderingContext getContext(String contextId) { | |
| 353 if (contextId == "2d") { | |
| 354 if (_context2d == null) { | |
| 355 _context2d = new CanvasRenderingContext2D(this, width, height); | |
| 356 } | |
| 357 return _context2d; | |
| 358 } else if (contextId == "webgl" || | |
| 359 contextId == "experimental-webgl") { | |
| 360 if (_context3d == null) { | |
| 361 _context3d = new WebGLRenderingContext(this); | |
| 362 } | |
| 363 return _context3d; | |
| 364 } | |
| 365 } | |
| 366 | |
| 367 String toDataUrl(String type) { | |
| 368 // This needs to take the contents of the underlying | |
| 369 // canvas painted by the 2d context, give that a unique | |
| 370 // URL, and return that. The canvas element should be | |
| 371 // reuable afterwards without destroying the previously | |
| 372 // rendered data associated with this URL. | |
| 373 assert(_context2d != null); | |
| 374 var rtn = src; | |
| 375 _context2d = null; | |
| 376 return rtn; | |
| 377 } | |
| 378 } | |
| 379 | |
| 380 class CanvasRenderingContext { | |
| 381 final CanvasElement canvas; | |
| 382 | |
| 383 CanvasRenderingContext(this.canvas); | |
| 384 } | |
| 385 | |
| 386 class AudioElement { | |
| 387 double volume; | |
| 388 String _src; | |
| 389 get src => _src; | |
| 390 set src(String v) { | |
| 391 _src = v; | |
| 392 _loadSample(v); | |
| 393 } | |
| 394 | |
| 395 AudioElement([this._src]); | |
| 396 void play() { | |
| 397 _playSample(_src); | |
| 398 } | |
| 399 } | |
| 400 | |
| 401 // The simplest way to call native code: top-level functions. | |
| 402 int systemRand() native "SystemRand"; | |
| 403 void systemSrand(int seed) native "SystemSrand"; | |
| 404 void log(String what) native "Log"; | |
| 405 | |
| 406 int getDeviceScreenWidth() native "GetDeviceScreenWidth"; | |
| 407 int getDeviceScreenHeight() native "GetDeviceScreenHeight"; | |
| 408 | |
| 409 // EGL functions. | |
| 410 void glSwapBuffers() native "SwapBuffers"; | |
| 411 | |
| 412 // GL functions. | |
| 413 void glAttachShader(int program, int shader) native "GLAttachShader"; | |
| 414 void glBindBuffer(int target, int buffer) native "GLBindBuffer"; | |
| 415 void glBufferData(int target, List data, int usage) native "GLBufferData"; | |
| 416 void glClearColor(num r, num g, num b, num alpha) native "GLClearColor"; | |
| 417 void glClearDepth(num depth) native "GLClearDepth"; | |
| 418 void glClear(int mask) native "GLClear"; | |
| 419 void glCompileShader(int shader) native "GLCompileShader"; | |
| 420 int glCreateBuffer() native "GLCreateBuffer"; | |
| 421 int glCreateProgram() native "GLCreateProgram"; | |
| 422 int glCreateShader(int shaderType) native "GLCreateShader"; | |
| 423 void glDrawArrays(int mode, int first, int count) native "GLDrawArrays"; | |
| 424 void glEnableVertexAttribArray(int index) native "GLEnableVertexAttribArray"; | |
| 425 int glGetAttribLocation(int program, String name) native "GLGetAttribLocation"; | |
| 426 int glGetError() native "GLGetError"; | |
| 427 int glGetProgramParameter(int program, int param) | |
| 428 native "GLGetProgramParameter"; | |
| 429 int glGetShaderParameter(int shader, int param) native "GLGetShaderParameter"; | |
| 430 int glGetUniformLocation(int program, String name) | |
| 431 native "GLGetUniformLocation"; | |
| 432 void glLinkProgram(int program) native "GLLinkProgram"; | |
| 433 void glShaderSource(int shader, String source) native "GLShaderSource"; | |
| 434 void glUniform1f(int location, double v0) native "GLUniform1f"; | |
| 435 void glUniform2f(int location, double v0, double v1) native "GLUniform2f"; | |
| 436 void glUniform3f(int location, double v0, double v1, double v2) | |
| 437 native "GLUniform3f"; | |
| 438 void glUniform4f(int location, double v0, double v1, double v2, double v3) | |
| 439 native "GLUniform4f"; | |
| 440 void glUniform1i(int location, int v0) native "GLUniform1i"; | |
| 441 void glUniform2i(int location, int v0, int v1) native "GLUniform2i"; | |
| 442 void glUniform3i(int location, int v0, int v1, int v2) native "GLUniform3i"; | |
| 443 void glUniform4i(int location, int v0, int v1, int v2, int v3) | |
| 444 native "GLUniform4i"; | |
| 445 void glUniform1fv(int location, List values) native "GLUniform1fv"; | |
| 446 void glUniform2fv(int location, List values) native "GLUniform2fv"; | |
| 447 void glUniform3fv(int location, List values) native "GLUniform3fv"; | |
| 448 void glUniform4fv(int location, List values) native "GLUniform4fv"; | |
| 449 void glUniform1iv(int location, List values) native "GLUniform1iv"; | |
| 450 void glUniform2iv(int location, List values) native "GLUniform2iv"; | |
| 451 void glUniform3iv(int location, List values) native "GLUniform3iv"; | |
| 452 void glUniform4iv(int location, List values) native "GLUniform4iv"; | |
| 453 void glUseProgram(int program) native "GLUseProgram"; | |
| 454 void glVertexAttribPointer(int index, int size, int type, bool normalized, | |
| 455 int stride, int pointer) native "GLVertexAttribPointer"; | |
| 456 void glViewport(int x, int y, int width, int height) native "GLViewport"; | |
| 457 | |
| 458 int glArrayBuffer() native "GLArrayBuffer"; | |
| 459 int glColorBufferBit() native "GLColorBufferBit"; | |
| 460 int glCompileStatus() native "GLCompileStatus"; | |
| 461 int glDeleteStatus() native "GLDeleteStatus"; | |
| 462 int glDepthBufferBit() native "GLDepthBufferBit"; | |
| 463 int glFloat() native "GLFloat"; | |
| 464 int glFragmentShader() native "GLFragmentShader"; | |
| 465 int glLinkStatus() native "GLLinkStatus"; | |
| 466 int glStaticDraw() native "GLStaticDraw"; | |
| 467 int glTriangleStrip() native "GLTriangleStrip"; | |
| 468 int glTriangles() native "GLTriangles"; | |
| 469 int glTrue() native "GLTrue"; | |
| 470 int glValidateStatus() native "GLValidateStatus"; | |
| 471 int glVertexShader() native "GLVertexShader"; | |
| 472 | |
| 473 String glGetShaderInfoLog(int shader) native "GLGetShaderInfoLog"; | |
| 474 String glGetProgramInfoLog(int program) native "GLGetProgramInfoLog"; | |
| 475 | |
| 476 class WebGLRenderingContext extends CanvasRenderingContext { | |
| 477 WebGLRenderingContext(canvas) : super(canvas); | |
| 478 | |
| 479 static get ARRAY_BUFFER => glArrayBuffer(); | |
| 480 static get COLOR_BUFFER_BIT => glColorBufferBit(); | |
| 481 static get COMPILE_STATUS => glCompileStatus(); | |
| 482 static get DELETE_STATUS => glDeleteStatus(); | |
| 483 static get DEPTH_BUFFER_BIT => glDepthBufferBit(); | |
| 484 static get FLOAT => glFloat(); | |
| 485 static get FRAGMENT_SHADER => glFragmentShader(); | |
| 486 static get LINK_STATUS => glLinkStatus(); | |
| 487 static get STATIC_DRAW => glStaticDraw(); | |
| 488 static get TRUE => glTrue(); | |
| 489 static get TRIANGLE_STRIP => glTriangleStrip(); | |
| 490 static get TRIANGLES => glTriangles(); | |
| 491 static get VALIDATE_STATUS => glValidateStatus(); | |
| 492 static get VERTEX_SHADER => glVertexShader(); | |
| 493 | |
| 494 attachShader(program, shader) => glAttachShader(program, shader); | |
| 495 bindBuffer(target, buffer) => glBindBuffer(target, buffer); | |
| 496 bufferData(target, data, usage) => glBufferData(target, data, usage); | |
| 497 clearColor(r, g, b, alpha) => glClearColor(r, g, b, alpha); | |
| 498 clearDepth(depth) => glClearDepth(depth); | |
| 499 clear(mask) => glClear(mask); | |
| 500 compileShader(shader) => glCompileShader(shader); | |
| 501 createBuffer() => glCreateBuffer(); | |
| 502 createProgram() => glCreateProgram(); | |
| 503 createShader(shaderType) => glCreateShader(shaderType); | |
| 504 drawArrays(mode, first, count) => glDrawArrays(mode, first, count); | |
| 505 enableVertexAttribArray(index) => glEnableVertexAttribArray(index); | |
| 506 getAttribLocation(program, name) => glGetAttribLocation(program, name); | |
| 507 getError() => glGetError(); | |
| 508 getProgramParameter(program, name) { | |
| 509 var rtn = glGetProgramParameter(program, name); | |
| 510 if (name == DELETE_STATUS || | |
| 511 name == LINK_STATUS || | |
| 512 name == VALIDATE_STATUS) { | |
| 513 return (rtn == 0) ? false : true; | |
| 514 } | |
| 515 return rtn; | |
| 516 } | |
| 517 getShaderParameter(shader, name) { | |
| 518 var rtn = glGetShaderParameter(shader, name); | |
| 519 if (name == DELETE_STATUS || name == COMPILE_STATUS) { | |
| 520 return (rtn == 0) ? false : true; | |
| 521 } | |
| 522 return rtn; | |
| 523 } | |
| 524 getUniformLocation(program, name) => glGetUniformLocation(program, name); | |
| 525 linkProgram(program) => glLinkProgram(program); | |
| 526 shaderSource(shader, source) => glShaderSource(shader, source); | |
| 527 uniform1f(location, v0) => glUniform1f(location, v0); | |
| 528 uniform2f(location, v0, v1) => glUniform2f(location, v0, v1); | |
| 529 uniform3f(location, v0, v1, v2) => glUniform3f(location, v0, v1, v2); | |
| 530 uniform4f(location, v0, v1, v2, v3) => glUniform4f(location, v0, v1, v2, v3); | |
| 531 uniform1i(location, v0) => glUniform1i(location, v0); | |
| 532 uniform2i(location, v0, v1) => glUniform2i(location, v0, v1); | |
| 533 uniform3i(location, v0, v1, v2) => glUniform3i(location, v0, v1, v2); | |
| 534 uniform4i(location, v0, v1, v2, v3) => glUniform4i(location, v0, v1, v2, v3); | |
| 535 uniform1fv(location, values) => glUniform1fv(location, values); | |
| 536 uniform2fv(location, values) => glUniform2fv(location, values); | |
| 537 uniform3fv(location, values) => glUniform3fv(location, values); | |
| 538 uniform4fv(location, values) => glUniform4fv(location, values); | |
| 539 uniform1iv(location, values) => glUniform1iv(location, values); | |
| 540 uniform2iv(location, values) => glUniform2iv(location, values); | |
| 541 uniform3iv(location, values) => glUniform3iv(location, values); | |
| 542 uniform4iv(location, values) => glUniform4iv(location, values); | |
| 543 useProgram(program) => glUseProgram(program); | |
| 544 vertexAttribPointer(index, size, type, normalized, stride, pointer) => | |
| 545 glVertexAttribPointer(index, size, type, normalized, stride, pointer); | |
| 546 viewport(x, y, width, height) => glViewport(x, y, width, height); | |
| 547 getShaderInfoLog(shader) => glGetShaderInfoLog(shader); | |
| 548 getProgramInfoLog(program) => glGetProgramInfoLog(program); | |
| 549 | |
| 550 // TODO(vsm): Kill. | |
| 551 noSuchMethod(invocation) { | |
| 552 throw new Exception('Unimplemented ${invocation.memberName}'); | |
| 553 } | |
| 554 } | |
| 555 | |
| 556 //------------------------------------------------------------------ | |
| 557 // Simple audio support. | |
| 558 | |
| 559 void playBackground(String path) native "PlayBackground"; | |
| 560 void stopBackground() native "StopBackground"; | |
| 561 | |
| 562 //------------------------------------------------------------------- | |
| 563 // Set up print(). | |
| 564 | |
| 565 get _printClosure => (s) { | |
| 566 try { | |
| 567 log(s); | |
| 568 } catch (_) { | |
| 569 throw(s); | |
| 570 } | |
| 571 }; | |
| 572 | |
| 573 //------------------------------------------------------------------ | |
| 574 // Temp hack for compat with WebGL. | |
| 575 | |
| 576 class Float32Array extends List<double> { | |
| 577 Float32Array.fromList(List a) { | |
| 578 addAll(a); | |
| 579 } | |
| 580 } | |
| 581 | |
| 582 //------------------------------------------------------------------ | |
| 583 // 2D canvas support | |
| 584 | |
| 585 int _SetWidth(int handle, int width) | |
| 586 native "C2DSetWidth"; | |
| 587 int _SetHeight(int handle, int height) | |
| 588 native "C2DSetHeight"; | |
| 589 | |
| 590 double _SetGlobalAlpha(int handle, double globalAlpha) | |
| 591 native "C2DSetGlobalAlpha"; | |
| 592 void _SetFillStyle(int handle, fs) | |
| 593 native "C2DSetFillStyle"; | |
| 594 String _SetFont(int handle, String font) | |
| 595 native "C2DSetFont"; | |
| 596 void _SetGlobalCompositeOperation(int handle, String op) | |
| 597 native "C2DSetGlobalCompositeOperation"; | |
| 598 _SetLineCap(int handle, String lc) | |
| 599 native "C2DSetLineCap"; | |
| 600 _SetLineJoin(int handle, String lj) | |
| 601 native "C2DSetLineJoin"; | |
| 602 _SetLineWidth(int handle, double w) | |
| 603 native "C2DSetLineWidth"; | |
| 604 _SetMiterLimit(int handle, double limit) | |
| 605 native "C2DSetMiterLimit"; | |
| 606 _SetShadowBlur(int handle, double blur) | |
| 607 native "C2DSetShadowBlur"; | |
| 608 _SetShadowColor(int handle, String color) | |
| 609 native "C2DSetShadowColor"; | |
| 610 _SetShadowOffsetX(int handle, double offset) | |
| 611 native "C2DSetShadowOffsetX"; | |
| 612 _SetShadowOffsetY(int handle, double offset) | |
| 613 native "C2DSetShadowOffsetY"; | |
| 614 void _SetStrokeStyle(int handle, ss) | |
| 615 native "C2DSetStrokeStyle"; | |
| 616 String _SetTextAlign(int handle, String align) | |
| 617 native "C2DSetTextAlign"; | |
| 618 String _SetTextBaseline(int handle, String baseline) | |
| 619 native "C2DSetTextBaseline"; | |
| 620 _GetBackingStorePixelRatio(int handle) | |
| 621 native "C2DGetBackingStorePixelRatio"; | |
| 622 void _SetImageSmoothingEnabled(int handle, bool ise) | |
| 623 native "C2DSetImageSmoothingEnabled"; | |
| 624 void _SetLineDash(int handle, List v) | |
| 625 native "C2DSetLineDash"; | |
| 626 _SetLineDashOffset(int handle, int v) | |
| 627 native "C2DSetLineDashOffset"; | |
| 628 void _Arc(int handle, double x, double y, double radius, | |
| 629 double startAngle, double endAngle, [bool anticlockwise = false]) | |
| 630 native "C2DArc"; | |
| 631 void _ArcTo(int handle, double x1, double y1, | |
| 632 double x2, double y2, double radius) | |
| 633 native "C2DArcTo"; | |
| 634 void _ArcTo2(int handle, double x1, double y1, | |
| 635 double x2, double y2, double radiusX, | |
| 636 double radiusY, double rotation) | |
| 637 native "C2DArcTo2"; | |
| 638 void _BeginPath(int handle) | |
| 639 native "C2DBeginPath"; | |
| 640 void _BezierCurveTo(int handle, double cp1x, double cp1y, | |
| 641 double cp2x, double cp2y, double x, double y) | |
| 642 native "C2DBezierCurveTo"; | |
| 643 void _ClearRect(int handle, double x, double y, double w, double h) | |
| 644 native "C2DClearRect"; | |
| 645 void _Clip(int handle) | |
| 646 native "C2DClip"; | |
| 647 void _ClosePath(int handle) | |
| 648 native "C2DClosePath"; | |
| 649 ImageData _CreateImageDataFromDimensions(int handle, num w, num h) | |
| 650 native "C2DCreateImageDataFromDimensions"; | |
| 651 void _DrawImage(int handle, String src_url, | |
| 652 int sx, int sy, | |
| 653 bool has_src_dimensions, int sw, int sh, | |
| 654 int dx, int dy, | |
| 655 bool has_dst_dimensions, int dw, int dh) | |
| 656 native "C2DDrawImage"; | |
| 657 void _Fill(int handle) | |
| 658 native "C2DFill"; | |
| 659 void _FillRect(int handle, double x, double y, double w, double h) | |
| 660 native "C2DFillRect"; | |
| 661 void _FillText(int handle, String text, double x, double y, double maxWidth) | |
| 662 native "C2DFillText"; | |
| 663 ImageData _GetImageData(num sx, num sy, num sw, num sh) | |
| 664 native "C2DGetImageData"; | |
| 665 void _LineTo(int handle, double x, double y) | |
| 666 native "C2DLineTo"; | |
| 667 double _MeasureText(int handle, String text) | |
| 668 native "C2DMeasureText"; | |
| 669 void _MoveTo(int handle, double x, double y) | |
| 670 native "C2DMoveTo"; | |
| 671 void _PutImageData(int handle, ImageData imagedata, double dx, double dy) | |
| 672 native "C2DPutImageData"; | |
| 673 void _QuadraticCurveTo(int handle, double cpx, double cpy, | |
| 674 double x, double y) | |
| 675 native "C2DQuadraticCurveTo"; | |
| 676 void _Rect(int handle, double x, double y, double w, double h) | |
| 677 native "C2DRect"; | |
| 678 void _Restore(int handle) | |
| 679 native "C2DRestore"; | |
| 680 void _Rotate(int handle, double a) | |
| 681 native "C2DRotate"; | |
| 682 void _Save(int handle) | |
| 683 native "C2DSave"; | |
| 684 void _Scale(int handle, double sx, double sy) | |
| 685 native "C2DScale"; | |
| 686 void _SetTransform(int handle, double m11, double m12, | |
| 687 double m21, double m22, double dx, double dy) | |
| 688 native "C2DSetTransform"; | |
| 689 void _Stroke(int handle) | |
| 690 native "C2DStroke"; | |
| 691 void _StrokeRect(int handle, double x, double y, double w, double h) | |
| 692 native "C2DStrokeRect"; | |
| 693 void _StrokeText(int handle, String text, double x, double y, | |
| 694 double maxWidth) | |
| 695 native "C2DStrokeText"; | |
| 696 void _Transform(int handle, double m11, double m12, | |
| 697 double m21, double m22, double dx, double dy) | |
| 698 native "C2DTransform"; | |
| 699 void _Translate(int handle, double x, double y) | |
| 700 native "C2DTranslate"; | |
| 701 | |
| 702 void _CreateNativeContext(int handle, int width, int height) | |
| 703 native "C2DCreateNativeContext"; | |
| 704 | |
| 705 void _SetFillGradient(int handle, bool isRadial, | |
| 706 double x0, double y0, double r0, | |
| 707 double x1, double y1, double r1, | |
| 708 List<double> positions, List<String> colors) | |
| 709 native "C2DSetFillGradient"; | |
| 710 | |
| 711 void _SetStrokeGradient(int handle, bool isRadial, | |
| 712 double x0, double y0, double r0, | |
| 713 double x1, double y1, double r1, | |
| 714 List<double> positions, List<String> colors) | |
| 715 native "C2DSetStrokeGradient"; | |
| 716 | |
| 717 int _GetImageWidth(String url) | |
| 718 native "C2DGetImageWidth"; | |
| 719 | |
| 720 int _GetImageHeight(String url) | |
| 721 native "C2DGetImageHeight"; | |
| 722 | |
| 723 class CanvasGradient { | |
| 724 num _x0, _y0, _r0 = 0, _x1, _y1, _r1 = 0; | |
| 725 bool _isRadial; | |
| 726 List<double> _colorStopPositions = []; | |
| 727 List<String> _colorStopColors = []; | |
| 728 | |
| 729 void addColorStop(num offset, String color) { | |
| 730 _colorStopPositions.add(offset.toDouble()); | |
| 731 _colorStopColors.add(color); | |
| 732 } | |
| 733 | |
| 734 CanvasGradient.linear(this._x0, this._y0, this._x1, this._y1) | |
| 735 : _isRadial = false; | |
| 736 | |
| 737 CanvasGradient.radial(this._x0, this._y0, this._r0, | |
| 738 this._x1, this._y1, this._r1) | |
| 739 : _isRadial = true; | |
| 740 | |
| 741 void setAsFillStyle(_handle) { | |
| 742 _SetFillGradient(_handle, _isRadial, | |
| 743 _x0.toDouble(), _y0.toDouble(), _r0.toDouble(), | |
| 744 _x1.toDouble(), _y1.toDouble(), _r1.toDouble(), | |
| 745 _colorStopPositions, _colorStopColors); | |
| 746 } | |
| 747 | |
| 748 void setAsStrokeStyle(_handle) { | |
| 749 _SetStrokeGradient(_handle, _isRadial, | |
| 750 _x0.toDouble(), _y0.toDouble(), _r0.toDouble(), | |
| 751 _x1.toDouble(), _y1.toDouble(), _r1.toDouble(), | |
| 752 _colorStopPositions, _colorStopColors); | |
| 753 } | |
| 754 } | |
| 755 | |
| 756 class ImageElement extends Node { | |
| 757 Stream<Event> get onLoad => new _EventStream(this, 'load'); | |
| 758 | |
| 759 String _src; | |
| 760 int _width; | |
| 761 int _height; | |
| 762 | |
| 763 get src => _src; | |
| 764 | |
| 765 set src(String v) { | |
| 766 log("Set ImageElement src to $v"); | |
| 767 _src = v; | |
| 768 } | |
| 769 | |
| 770 // The onLoad handler may be set after the src, so | |
| 771 // we hook into that here... | |
| 772 void addListener(String eventType, EventListener handler) { | |
| 773 super.addListener(eventType, handler); | |
| 774 if (eventType == 'load') { | |
| 775 var e = new Event('load'); | |
| 776 e.target = this; | |
| 777 window._scheduleCallback(handler, e); | |
| 778 } | |
| 779 } | |
| 780 | |
| 781 get width => _width == null ? _width = _GetImageWidth(_src) : _width; | |
| 782 get height => _height == null ? _height = _GetImageHeight(_src) : _height; | |
| 783 set width(int widthp) => _width = widthp; | |
| 784 set height(int heightp) => _height = heightp; | |
| 785 | |
| 786 ImageElement({String srcp, int widthp, int heightp}) | |
| 787 : _src = srcp, | |
| 788 _width = widthp, | |
| 789 _height = heightp { | |
| 790 if (_src != null) { | |
| 791 if (_width == null) _width = _GetImageWidth(_src); | |
| 792 if (_height == null) _height = _GetImageHeight(_src); | |
| 793 } | |
| 794 } | |
| 795 } | |
| 796 | |
| 797 class ImageData { | |
| 798 final Uint8ClampedArray data; | |
| 799 final int height; | |
| 800 final int width; | |
| 801 ImageData(this.height, this.width, this.data); | |
| 802 } | |
| 803 | |
| 804 class TextMetrics { | |
| 805 final num width; | |
| 806 TextMetrics(this.width); | |
| 807 } | |
| 808 | |
| 809 void shutdown() { | |
| 810 CanvasRenderingContext2D.next_handle = 0; | |
| 811 } | |
| 812 | |
| 813 class Rect { | |
| 814 final num top, left, width, height; | |
| 815 const Rect(this.left, this.top, this.width, this.height); | |
| 816 } | |
| 817 | |
| 818 class CanvasRenderingContext2D extends CanvasRenderingContext { | |
| 819 // TODO(gram): We need to support multiple contexts, for cached content | |
| 820 // prerendered to an offscreen buffer. For this we will use handles, with | |
| 821 // handle 0 being the physical display. | |
| 822 static int next_handle = 0; | |
| 823 int _handle = 0; | |
| 824 get handle => _handle; | |
| 825 | |
| 826 int _width, _height; | |
| 827 set width(int w) { _width = SetWidth(_handle, w); } | |
| 828 get width => _width; | |
| 829 set height(int h) { _height = SetHeight(_handle, h); } | |
| 830 get height => _height; | |
| 831 | |
| 832 CanvasRenderingContext2D(canvas, width, height) : super(canvas) { | |
| 833 _width = width; | |
| 834 _height = height; | |
| 835 _CreateNativeContext(_handle = next_handle++, width, height); | |
| 836 } | |
| 837 | |
| 838 double _alpha = 1.0; | |
| 839 set globalAlpha(num a) { | |
| 840 _alpha = _SetGlobalAlpha(_handle, a.toDouble()); | |
| 841 } | |
| 842 get globalAlpha => _alpha; | |
| 843 | |
| 844 // TODO(gram): make sure we support compound assignments like: | |
| 845 // fillStyle = strokeStyle = "red" | |
| 846 var _fillStyle = "#000"; | |
| 847 set fillStyle(fs) { | |
| 848 _fillStyle = fs; | |
| 849 // TODO(gram): Support for CanvasPattern. | |
| 850 if (fs is CanvasGradient) { | |
| 851 fs.setAsFillStyle(_handle); | |
| 852 } else { | |
| 853 _SetFillStyle(_handle, fs); | |
| 854 } | |
| 855 } | |
| 856 get fillStyle => _fillStyle; | |
| 857 | |
| 858 String _font = "10px sans-serif"; | |
| 859 set font(String f) { _font = _SetFont(_handle, f); } | |
| 860 get font => _font; | |
| 861 | |
| 862 String _globalCompositeOperation = "source-over"; | |
| 863 set globalCompositeOperation(String o) => | |
| 864 _SetGlobalCompositeOperation(_handle, _globalCompositeOperation = o); | |
| 865 get globalCompositeOperation => _globalCompositeOperation; | |
| 866 | |
| 867 String _lineCap = "butt"; // "butt", "round", "square" | |
| 868 get lineCap => _lineCap; | |
| 869 set lineCap(String lc) => _SetLineCap(_handle, _lineCap = lc); | |
| 870 | |
| 871 int _lineDashOffset = 0; | |
| 872 get lineDashOffset => _lineDashOffset; | |
| 873 set lineDashOffset(num v) { | |
| 874 _lineDashOffset = v.toInt(); | |
| 875 _SetLineDashOffset(_handle, _lineDashOffset); | |
| 876 } | |
| 877 | |
| 878 String _lineJoin = "miter"; // "round", "bevel", "miter" | |
| 879 get lineJoin => _lineJoin; | |
| 880 set lineJoin(String lj) => _SetLineJoin(_handle, _lineJoin = lj); | |
| 881 | |
| 882 num _lineWidth = 1.0; | |
| 883 get lineWidth => _lineWidth; | |
| 884 set lineWidth(num w) { | |
| 885 _SetLineWidth(_handle, w.toDouble()); | |
| 886 _lineWidth = w; | |
| 887 } | |
| 888 | |
| 889 num _miterLimit = 10.0; // (default 10) | |
| 890 get miterLimit => _miterLimit; | |
| 891 set miterLimit(num limit) { | |
| 892 _SetMiterLimit(_handle, limit.toDouble()); | |
| 893 _miterLimit = limit; | |
| 894 } | |
| 895 | |
| 896 num _shadowBlur; | |
| 897 get shadowBlur => _shadowBlur; | |
| 898 set shadowBlur(num blur) { | |
| 899 _shadowBlur = blur; | |
| 900 _SetShadowBlur(_handle, blur.toDouble()); | |
| 901 } | |
| 902 | |
| 903 String _shadowColor; | |
| 904 get shadowColor => _shadowColor; | |
| 905 set shadowColor(String color) => | |
| 906 _SetShadowColor(_handle, _shadowColor = color); | |
| 907 | |
| 908 num _shadowOffsetX; | |
| 909 get shadowOffsetX => _shadowOffsetX; | |
| 910 set shadowOffsetX(num offset) { | |
| 911 _shadowOffsetX = offset; | |
| 912 _SetShadowOffsetX(_handle, offset.toDouble()); | |
| 913 } | |
| 914 | |
| 915 num _shadowOffsetY; | |
| 916 get shadowOffsetY => _shadowOffsetY; | |
| 917 set shadowOffsetY(num offset) { | |
| 918 _shadowOffsetY = offset; | |
| 919 _SetShadowOffsetY(_handle, offset.toDouble()); | |
| 920 } | |
| 921 | |
| 922 var _strokeStyle = "#000"; | |
| 923 get strokeStyle => _strokeStyle; | |
| 924 set strokeStyle(ss) { | |
| 925 _strokeStyle = ss; | |
| 926 // TODO(gram): Support for CanvasPattern. | |
| 927 if (ss is CanvasGradient) { | |
| 928 ss.setAsStrokeStyle(_handle); | |
| 929 } else { | |
| 930 _SetStrokeStyle(_handle, ss); | |
| 931 } | |
| 932 } | |
| 933 | |
| 934 String _textAlign = "start"; | |
| 935 get textAlign => _textAlign; | |
| 936 set textAlign(String a) { _textAlign = _SetTextAlign(_handle, a); } | |
| 937 | |
| 938 String _textBaseline = "alphabetic"; | |
| 939 get textBaseline => _textBaseline; | |
| 940 set textBaseline(String b) { _textBaseline = _SetTextBaseline(_handle, b); } | |
| 941 | |
| 942 get webkitBackingStorePixelRatio => _GetBackingStorePixelRatio(_handle); | |
| 943 | |
| 944 bool _webkitImageSmoothingEnabled; | |
| 945 get webkitImageSmoothingEnabled => _webkitImageSmoothingEnabled; | |
| 946 set webkitImageSmoothingEnabled(bool v) => | |
| 947 _SetImageSmoothingEnabled(_webkitImageSmoothingEnabled = v); | |
| 948 | |
| 949 get webkitLineDash => lineDash; | |
| 950 set webkitLineDash(List v) => lineDash = v; | |
| 951 | |
| 952 get webkitLineDashOffset => lineDashOffset; | |
| 953 set webkitLineDashOffset(num v) => lineDashOffset = v; | |
| 954 | |
| 955 // Methods | |
| 956 | |
| 957 void arc(num x, num y, num radius, num a1, num a2, bool anticlockwise) { | |
| 958 if (radius < 0) { | |
| 959 // throw IndexSizeError | |
| 960 } else { | |
| 961 _Arc(_handle, x.toDouble(), y.toDouble(), radius.toDouble(), | |
| 962 a1.toDouble(), a2.toDouble(), anticlockwise); | |
| 963 } | |
| 964 } | |
| 965 | |
| 966 // Note - looking at the Dart docs it seems Dart doesn't support | |
| 967 // the second form in the browser. | |
| 968 void arcTo(num x1, num y1, num x2, num y2, | |
| 969 num radiusX, [num radiusY, num rotation]) { | |
| 970 if (radiusY == null) { | |
| 971 _ArcTo(_handle, x1.toDouble(), y1.toDouble(), | |
| 972 x2.toDouble(), y2.toDouble(), radiusX.toDouble()); | |
| 973 } else { | |
| 974 _ArcTo2(_handle, x1.toDouble(), y1.toDouble(), | |
| 975 x2.toDouble(), y2.toDouble(), | |
| 976 radiusX.toDouble(), radiusY.toDouble(), | |
| 977 rotation.toDouble()); | |
| 978 } | |
| 979 } | |
| 980 | |
| 981 void beginPath() => _BeginPath(_handle); | |
| 982 | |
| 983 void bezierCurveTo(num cp1x, num cp1y, num cp2x, num cp2y, | |
| 984 num x, num y) => | |
| 985 _BezierCurveTo(_handle, cp1x.toDouble(), cp1y.toDouble(), | |
| 986 cp2x.toDouble(), cp2y.toDouble(), | |
| 987 x.toDouble(), y.toDouble()); | |
| 988 | |
| 989 void clearRect(num x, num y, num w, num h) => | |
| 990 _ClearRect(_handle, x.toDouble(), y.toDouble(), | |
| 991 w.toDouble(), h.toDouble()); | |
| 992 | |
| 993 void clip() => _Clip(_handle); | |
| 994 | |
| 995 void closePath() => _ClosePath(_handle); | |
| 996 | |
| 997 ImageData createImageData(var imagedata_OR_sw, [num sh = null]) { | |
| 998 if (sh == null) { | |
| 999 throw new Exception('Unimplemented createImageData(imagedata)'); | |
| 1000 } else { | |
| 1001 return _CreateImageDataFromDimensions(_handle, imagedata_OR_sw, sh); | |
| 1002 } | |
| 1003 } | |
| 1004 | |
| 1005 CanvasGradient createLinearGradient(num x0, num y0, num x1, num y1) { | |
| 1006 return new CanvasGradient.linear(x0, y0, x1, y1); | |
| 1007 } | |
| 1008 | |
| 1009 CanvasPattern createPattern(canvas_OR_image, String repetitionType) { | |
| 1010 throw new Exception('Unimplemented createPattern'); | |
| 1011 } | |
| 1012 | |
| 1013 CanvasGradient createRadialGradient(num x0, num y0, num r0, | |
| 1014 num x1, num y1, num r1) { | |
| 1015 return new CanvasGradient.radial(x0, y0, r0, x1, y1, r1); | |
| 1016 } | |
| 1017 | |
| 1018 void _drawImage(element, num x1, num y1, | |
| 1019 [num w1, num h1, num x2, num y2, num w2, num h2]) { | |
| 1020 if (element == null || element.src == null || element.src.length == 0) { | |
| 1021 throw "drawImage called with no valid src"; | |
| 1022 } else { | |
| 1023 log("drawImage ${element.src}"); | |
| 1024 } | |
| 1025 var w = (element.width == null) ? 0 : element.width; | |
| 1026 var h = (element.height == null) ? 0 : element.height; | |
| 1027 if (!?w1) { // drawImage(element, dx, dy) | |
| 1028 _DrawImage(_handle, element.src, 0, 0, false, w, h, | |
| 1029 x1.toInt(), y1.toInt(), false, 0, 0); | |
| 1030 } else if (!?x2) { // drawImage(element, dx, dy, dw, dh) | |
| 1031 _DrawImage(_handle, element.src, 0, 0, false, w, h, | |
| 1032 x1.toInt(), y1.toInt(), true, w1.toInt(), h1.toInt()); | |
| 1033 } else { // drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) | |
| 1034 _DrawImage(_handle, element.src, | |
| 1035 x1.toInt(), y1.toInt(), true, w1.toInt(), h1.toInt(), | |
| 1036 x2.toInt(), y2.toInt(), true, w2.toInt(), h2.toInt()); | |
| 1037 } | |
| 1038 } | |
| 1039 | |
| 1040 void drawImage(source, num destX, num destY) { | |
| 1041 _drawImage(source, destX, destY); | |
| 1042 } | |
| 1043 | |
| 1044 void drawImageScaled(source, | |
| 1045 num destX, num destY, num destWidth, num destHeight) { | |
| 1046 _drawImage(source, destX, destY, destWidth, destHeight); | |
| 1047 } | |
| 1048 | |
| 1049 void drawImageScaledFromSource(source, | |
| 1050 num sourceX, num sourceY, num sourceWidth, num sourceHeight, | |
| 1051 num destX, num destY, num destWidth, num destHeight) { | |
| 1052 _drawImage(source, sourceX, sourceY, sourceWidth, sourceHeight, | |
| 1053 destX, destY, destWidth, destHeight); | |
| 1054 } | |
| 1055 | |
| 1056 void drawImageToRect(source, Rect dest, {Rect sourceRect}) { | |
| 1057 if (sourceRect == null) { | |
| 1058 _drawImage(source, dest.left, dest.top, dest.width, dest.height); | |
| 1059 } else { | |
| 1060 _drawImage(source, | |
| 1061 sourceRect.left, sourceRect.top, sourceRect.width, sourceRect.height, | |
| 1062 dest.left, dest.top, dest.width, dest.height); | |
| 1063 } | |
| 1064 } | |
| 1065 | |
| 1066 void fill() => _Fill(_handle); | |
| 1067 | |
| 1068 void fillRect(num x, num y, num w, num h) => | |
| 1069 _FillRect(_handle, x.toDouble(), y.toDouble(), | |
| 1070 w.toDouble(), h.toDouble()); | |
| 1071 | |
| 1072 void fillText(String text, num x, num y, [num maxWidth = -1]) => | |
| 1073 _FillText(_handle, text, x.toDouble(), y.toDouble(), | |
| 1074 maxWidth.toDouble()); | |
| 1075 | |
| 1076 ImageData getImageData(num sx, num sy, num sw, num sh) => | |
| 1077 _GetImageData(sx, sy, sw, sh); | |
| 1078 | |
| 1079 List<double> _lineDash = null; | |
| 1080 List<num> getLineDash() { | |
| 1081 if (_lineDash == null) return []; | |
| 1082 return _lineDash; // TODO(gram): should we return a copy? | |
| 1083 } | |
| 1084 | |
| 1085 bool isPointInPath(num x, num y) { | |
| 1086 throw new Exception('Unimplemented isPointInPath'); | |
| 1087 } | |
| 1088 | |
| 1089 void lineTo(num x, num y) { | |
| 1090 _LineTo(_handle, x.toDouble(), y.toDouble()); | |
| 1091 } | |
| 1092 | |
| 1093 TextMetrics measureText(String text) { | |
| 1094 double w = _MeasureText(_handle, text); | |
| 1095 return new TextMetrics(w); | |
| 1096 } | |
| 1097 | |
| 1098 void moveTo(num x, num y) => | |
| 1099 _MoveTo(_handle, x.toDouble(), y.toDouble()); | |
| 1100 | |
| 1101 void putImageData(ImageData imagedata, num dx, num dy, | |
| 1102 [num dirtyX, num dirtyY, num dirtyWidth, num dirtyHeight]) { | |
| 1103 if (dirtyX != null || dirtyY != null) { | |
| 1104 throw new Exception('Unimplemented putImageData'); | |
| 1105 } else { | |
| 1106 _PutImageData(_handle, imagedata, dx, dy); | |
| 1107 } | |
| 1108 } | |
| 1109 | |
| 1110 void quadraticCurveTo(num cpx, num cpy, num x, num y) => | |
| 1111 _QuadraticCurveTo(_handle, cpx.toDouble(), cpy.toDouble(), | |
| 1112 x.toDouble(), y.toDouble()); | |
| 1113 | |
| 1114 void rect(num x, num y, num w, num h) => | |
| 1115 _Rect(_handle, x.toDouble(), y.toDouble(), w.toDouble(), h.toDouble()); | |
| 1116 | |
| 1117 void restore() => _Restore(_handle); | |
| 1118 | |
| 1119 void rotate(num angle) => _Rotate(_handle, angle.toDouble()); | |
| 1120 | |
| 1121 void save() => _Save(_handle); | |
| 1122 | |
| 1123 void scale(num x, num y) => _Scale(_handle, x.toDouble(), y.toDouble()); | |
| 1124 | |
| 1125 void setFillColorHsl(int h, num s, num l, [num a = 1]) { | |
| 1126 throw new Exception('Unimplemented setFillColorHsl'); | |
| 1127 } | |
| 1128 | |
| 1129 void setFillColorRgb(int r, int g, int b, [num a = 1]) { | |
| 1130 throw new Exception('Unimplemented setFillColorRgb'); | |
| 1131 } | |
| 1132 | |
| 1133 void setLineDash(List<num> dash) { | |
| 1134 var valid = true; | |
| 1135 var new_dash; | |
| 1136 if (dash.length % 2 == 1) { | |
| 1137 new_dash = new List<double>(2 * dash.length); | |
| 1138 for (int i = 0; i < dash.length; i++) { | |
| 1139 double v = dash[i].toDouble(); | |
| 1140 if (v < 0) { | |
| 1141 valid = false; | |
| 1142 break; | |
| 1143 } | |
| 1144 new_dash[i] = new_dash[i + dash.length] = v; | |
| 1145 } | |
| 1146 } else { | |
| 1147 new_dash = new List<double>(dash.length); | |
| 1148 for (int i = 0; i < dash.length; i++) { | |
| 1149 double v = dash[i].toDouble(); | |
| 1150 if (v < 0) { | |
| 1151 valid = false; | |
| 1152 break; | |
| 1153 } | |
| 1154 new_dash[i] = v; | |
| 1155 } | |
| 1156 } | |
| 1157 if (valid) { | |
| 1158 _SetLineDash(_handle, _lineDash = new_dash); | |
| 1159 } | |
| 1160 } | |
| 1161 | |
| 1162 void setStrokeColorHsl(int h, num s, num l, [num a = 1]) { | |
| 1163 throw new Exception('Unimplemented setStrokeColorHsl'); | |
| 1164 } | |
| 1165 | |
| 1166 void setStrokeColorRgb(int r, int g, int b, [num a = 1]) { | |
| 1167 throw new Exception('Unimplemented setStrokeColorRgb'); | |
| 1168 } | |
| 1169 | |
| 1170 void setTransform(num m11, num m12, num m21, num m22, num dx, num dy) => | |
| 1171 _SetTransform(_handle, m11.toDouble(), m12.toDouble(), | |
| 1172 m21.toDouble(), m22.toDouble(), | |
| 1173 dx.toDouble(), dy.toDouble()); | |
| 1174 | |
| 1175 void stroke() => _Stroke(_handle); | |
| 1176 | |
| 1177 void strokeRect(num x, num y, num w, num h, [num lineWidth]) => | |
| 1178 _StrokeRect(_handle, x.toDouble(), y.toDouble(), | |
| 1179 w.toDouble(), h.toDouble()); | |
| 1180 | |
| 1181 void strokeText(String text, num x, num y, [num maxWidth = -1]) => | |
| 1182 _StrokeText(_handle, text, x.toDouble(), y.toDouble(), | |
| 1183 maxWidth.toDouble()); | |
| 1184 | |
| 1185 void transform(num m11, num m12, num m21, num m22, num dx, num dy) => | |
| 1186 _Transform(_handle, m11.toDouble(), m12.toDouble(), | |
| 1187 m21.toDouble(), m22.toDouble(), | |
| 1188 dx.toDouble(), dy.toDouble()); | |
| 1189 | |
| 1190 void translate(num x, num y) => | |
| 1191 _Translate(_handle, x.toDouble(), y.toDouble()); | |
| 1192 | |
| 1193 ImageData webkitGetImageDataHD(num sx, num sy, num sw, num sh) { | |
| 1194 throw new Exception('Unimplemented webkitGetImageDataHD'); | |
| 1195 } | |
| 1196 | |
| 1197 void webkitPutImageDataHD(ImageData imagedata, num dx, num dy, | |
| 1198 [num dirtyX, num dirtyY, | |
| 1199 num dirtyWidth, num dirtyHeight]) { | |
| 1200 throw new Exception('Unimplemented webkitGetImageDataHD'); | |
| 1201 } | |
| 1202 | |
| 1203 // TODO(vsm): Kill. | |
| 1204 noSuchMethod(invocation) { | |
| 1205 throw new Exception('Unimplemented/unknown ${invocation.memberName}'); | |
| 1206 } | |
| 1207 } | |
| 1208 | |
| 1209 var sfx_extension = 'raw'; | |
| 1210 int _loadSample(String s) native "LoadSample"; | |
| 1211 int _playSample(String s) native "PlaySample"; | |
| OLD | NEW |