Stage class
The Stage is the drawing area wher all display objects are rendered to. Place a Canvas element to your HTML and use the Stage to wrap all the rendering functions to this Canvas element.
Example:
HTML: <canvas id="stage" width="800" height="600"></canvas> Dart: var stage = new Stage(querySelector("#stage"));
class Stage extends DisplayObjectContainer {
 static bool autoHiDpi = _autoHiDpi;
 static bool get isMobile => _isMobile;
 static num get devicePixelRatio => _devicePixelRatio;
 CanvasElement _canvas;
 RenderContext _renderContext;
 int _sourceWidth = 0;
 int _sourceHeight = 0;
 int _frameRate = 30;
 int _canvasWidth = -1;
 int _canvasHeight = -1;
 Rectangle _contentRectangle = new Rectangle.zero();
 Matrix _clientTransformation = new Matrix.fromIdentity();
 Matrix _stageTransformation = new Matrix.fromIdentity();
 RenderLoop _renderLoop = null;
 Juggler _juggler = new Juggler();
 InteractiveObject _focus = null;
 RenderState _renderState = null;
 String _stageRenderMode = StageRenderMode.AUTO;
 String _stageScaleMode = StageScaleMode.SHOW_ALL;
 String _stageAlign = StageAlign.NONE;
 String _mouseCursor = MouseCursor.ARROW;
 Point _mousePosition = new Point.zero();
 InteractiveObject _mouseTarget = null;
 Map<int, _Touch> _touches = new Map<int, _Touch>();
 List<_MouseButton> _mouseButtons = [
   new _MouseButton(MouseEvent.MOUSE_DOWN, MouseEvent.MOUSE_UP, MouseEvent.CLICK, MouseEvent.DOUBLE_CLICK),
   new _MouseButton(MouseEvent.MIDDLE_MOUSE_DOWN, MouseEvent.MIDDLE_MOUSE_UP, MouseEvent.MIDDLE_CLICK, MouseEvent.MIDDLE_CLICK),
   new _MouseButton(MouseEvent.RIGHT_MOUSE_DOWN, MouseEvent.RIGHT_MOUSE_UP, MouseEvent.RIGHT_CLICK, MouseEvent.RIGHT_CLICK)];
 //-------------------------------------------------------------------------------------------------
 static const EventStreamProvider<Event> resizeEvent = const EventStreamProvider<Event>(Event.RESIZE);
 EventStream<Event> get onResize => Stage.resizeEvent.forTarget(this);
 //-------------------------------------------------------------------------------------------------
 Stage(CanvasElement canvas, {int width, int height,
   bool webGL: false, int frameRate: 30, int color: Color.White}) {
   if (canvas is! CanvasElement) {
     throw new ArgumentError("The canvas argument is not a CanvasElement");
   }
   _canvas = canvas;
   if (canvas.tabIndex == -1) canvas.tabIndex = 0;
   if (canvas.style.outline == "") canvas.style.outline = "none";
   _sourceWidth = _ensureInt((width != null) ? width : canvas.width);
   _sourceHeight = _ensureInt((width != null) ? height : canvas.height);
   _frameRate = _ensureInt((frameRate != null) ? frameRate : 30);
   _renderContext = webGL && gl.RenderingContext.supported
       ? new RenderContextWebGL(canvas, color)
       : new RenderContextCanvas(canvas, color);
   _renderState = new RenderState(_renderContext);
   _updateCanvasSize();
   print("StageXL render engine : ${_renderContext.renderEngine}");
   canvas.onKeyDown.listen(_onKeyEvent);
   canvas.onKeyUp.listen(_onKeyEvent);
   canvas.onKeyPress.listen(_onKeyEvent);
   canvas.onMouseDown.listen(_onMouseEvent);
   canvas.onMouseUp.listen(_onMouseEvent);
   canvas.onMouseMove.listen(_onMouseEvent);
   canvas.onMouseOut.listen(_onMouseEvent);
   canvas.onContextMenu.listen(_onMouseEvent);
   canvas.onMouseWheel.listen(_onMouseWheelEvent);
   Mouse._onMouseCursorChanged.listen(_onMouseCursorChanged);
   Multitouch._onInputModeChanged.listen(_onMultitouchInputModeChanged);
   _onMultitouchInputModeChanged(null);
 }
 //-------------------------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------------------------
 /**
  * Gets the original source width of the Stage as defined in the constructor.
  */
 int get sourceWidth => _sourceWidth;
 /**
  * Gets the original source height of the Stage as defined in the constructor.
  */
 int get sourceHeight => _sourceHeight;
 /**
  * Gets the current width of the Stage in pixels on the screen.
  */
 int get stageWidth => _canvasWidth;
 /**
  * Gets the current height of the Stage in pixels on the screen.
  */
 int get stageHeight => _canvasHeight;
 /**
  * Gets the available content area on the stage. The value of this rectangle
  * changes with the scaleMode and the alignment of the stage, as well as the size
  * of the underlying Canvas element.
  */
 Rectangle get contentRectangle => _contentRectangle.clone();
 /**
  * Gets the underlying render engine used to draw the pixels to the screen.
  * The returned string is defined in [RenderEngine] and is either "WebGL"
  * or "Canvas2D".
  */
 String get renderEngine => _renderContext.renderEngine;
 /**
  * Gets the [RenderLoop] where this Stage was added to, or
  * NULL in case this Stage is not added to a [RenderLoop].
  */
 RenderLoop get renderLoop => _renderLoop;
 /**
  * Gets the [Juggler] of this Stage. The Juggler is driven by the
  * [RenderLoop] where this Stage is added to. If this Stage is not
  * added to a RenderLoop, the [Juggler] will not advance in time.
  */
 Juggler get juggler => _juggler;
 /**
  * Gets the last known mouse position in Stage coordinates.
  */
 Point get mousePosition => _mousePosition;
 /**
  * Gets and sets the default frame rate for MovieClips. This value has no
  * impact on the frame rate of the Stage itself.
  */
 int get frameRate => _frameRate;
 set frameRate(int value) {
   _frameRate = value;
 }
 /**
  * Gets and sets the [InteractiveObject] (a DisplayObject which can
  * receive user input like mouse, touch or keyboard).
  */
 InteractiveObject get focus => _focus;
 set focus(InteractiveObject value) {
   _focus = value;
 }
 /**
  * Gets and sets the render mode of this Stage. You can choose between
  * three different modes defined in [StageRenderMode].
  */
 String get renderMode => _stageRenderMode;
 set renderMode(String value) {
   _stageRenderMode = value;
 }
 /**
  * Gets and sets the scale mode of this Stage. You can choose between
  * four dfferent modes defined in [StageScaleMode].
  */
 String get scaleMode => _stageScaleMode;
 set scaleMode(String value) {
   _stageScaleMode = value;
   _updateCanvasSize();
 }
 /**
  * Gets and sets the alignment of this Stage inside of the Canvas element.
  * You can choose between nine different align modes defined in [StageAlign].
  */
 String get align => _stageAlign;
 set align(String value) {
   _stageAlign = value;
   _updateCanvasSize();
 }
 /**
  * Calling this method will cause an [RenderEvent] to be fired right before
  * the next frame will be rendered by the render loop. To receive the render
  * event attach a listener to [DisplayObject.onRender].
  */
 invalidate() {
   if (_renderLoop != null) {
     _renderLoop.invalidate();
   }
 }
 //-------------------------------------------------------------------------------------------------
 _throwStageException() {
   throw new UnsupportedError("Error #2071: The Stage class does not implement this property or method.");
 }
 set x(num value) { _throwStageException(); }
 set y(num value) { _throwStageException(); }
 set pivotX(num value) { _throwStageException(); }
 set pivotY(num value) { _throwStageException(); }
 set scaleX(num value) { _throwStageException(); }
 set scaleY(num value) { _throwStageException(); }
 set skewX(num value) { _throwStageException(); }
 set skewY(num value) { _throwStageException(); }
 set rotation(num value) { _throwStageException(); }
 set alpha(num value) { _throwStageException(); }
 set width(num value) { _throwStageException(); }
 set height(num value) { _throwStageException(); }
 //-------------------------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------------------------
 /**
  * This method is called by the [RenderLoop] where this Stage is added to.
  * If this Stage is not added to a [RenderLoop] you could call this method
  * on your own and therefore get full control of the rendering of this Stage.
  */
 materialize(num currentTime, num deltaTime) {
   if (_stageRenderMode == StageRenderMode.AUTO || _stageRenderMode == StageRenderMode.ONCE) {
     _updateCanvasSize();
     _renderState.reset(_stageTransformation, currentTime, deltaTime);
     render(_renderState);
     _renderState.flush();
     if (_stageRenderMode == StageRenderMode.ONCE)
       _stageRenderMode = StageRenderMode.STOP;
   }
 }
 //-------------------------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------------------------
 _updateCanvasSize() {
   var client = _canvas.getBoundingClientRect();
   var clientLeft = _canvas.clientLeft + client.left;
   var clientTop = _canvas.clientTop + client.top;
   var clientWidth = _canvas.clientWidth;
   var clientHeight = _canvas.clientHeight;
   var sourceWidth = _sourceWidth;
   var sourceHeight = _sourceHeight;
   if (clientWidth is! num) throw "dart2js_hint";
   if (clientHeight is! num) throw "dart2js_hint";
   if (sourceWidth is! num) throw "dart2js_hint";
   if (sourceHeight is! num) throw "dart2js_hint";
   if (clientWidth == 0 || clientHeight == 0) return;
   //----------------------------
   var scaleX = 1.0;
   var scaleY = 1.0;
   var pivotX = 0.0;
   var pivotY = 0.0;
   var ratioWidth = clientWidth / sourceWidth;
   var ratioHeight = clientHeight / sourceHeight;
   switch(_stageScaleMode) {
     case StageScaleMode.EXACT_FIT:
       scaleX = ratioWidth;
       scaleY = ratioHeight;
       break;
     case StageScaleMode.NO_BORDER:
       scaleX = scaleY = (ratioWidth > ratioHeight) ? ratioWidth : ratioHeight;
       break;
     case StageScaleMode.NO_SCALE:
       scaleX = scaleY = 1.0;
       break;
     case StageScaleMode.SHOW_ALL:
       scaleX = scaleY = (ratioWidth < ratioHeight) ? ratioWidth : ratioHeight;
       break;
   }
   switch(_stageAlign) {
     case StageAlign.TOP_RIGHT:
     case StageAlign.RIGHT:
     case StageAlign.BOTTOM_RIGHT:
       pivotX = (clientWidth - sourceWidth * scaleX);
       break;
     case StageAlign.TOP:
     case StageAlign.NONE:
     case StageAlign.BOTTOM:
       pivotX = (clientWidth - sourceWidth * scaleX) / 2;
       break;
   }
   switch(_stageAlign) {
     case StageAlign.BOTTOM_LEFT:
     case StageAlign.BOTTOM:
     case StageAlign.BOTTOM_RIGHT:
       pivotY = (clientHeight - sourceHeight * scaleY);
       break;
     case StageAlign.LEFT:
     case StageAlign.NONE:
     case StageAlign.RIGHT:
       pivotY = (clientHeight - sourceHeight * scaleY) / 2;
       break;
   }
   //----------------------------
   var contentRectangle = _contentRectangle;
   contentRectangle.x = - pivotX / scaleX;
   contentRectangle.y = - pivotY / scaleY;
   contentRectangle.width = clientWidth / scaleX;
   contentRectangle.height = clientHeight / scaleY;
   var pixelRatio = (Stage.autoHiDpi ? _devicePixelRatio : 1.0) / _backingStorePixelRatio;
   // stage to canvas coordinate transformation
   _stageTransformation.setTo(scaleX, 0.0, 0.0, scaleY, pivotX, pivotY);
   _stageTransformation.scale(pixelRatio, pixelRatio);
   // client to stage coordinate transformation
   _clientTransformation.setTo(1.0, 0.0, 0.0, 1.0, - clientLeft - pivotX, - clientTop - pivotY);
   _clientTransformation.scale(1.0 / scaleX, 1.0 / scaleY);
   if (_canvasWidth != clientWidth || _canvasHeight != clientHeight) {
     _canvasWidth = clientWidth;
     _canvasHeight = clientHeight;
     _canvas.width = (_canvasWidth * pixelRatio).round();
     _canvas.height = (_canvasHeight * pixelRatio).round();
     // update hi-dpi canvas style size if client size has changed
     if (_canvas.clientWidth != clientWidth || _canvas.clientHeight != clientHeight) {
       _canvas.style.width = "${clientWidth}px";
       _canvas.style.height = "${clientHeight}px";
     }
     dispatchEvent(new Event(Event.RESIZE));
   }
 }
 //-------------------------------------------------------------------------------------------------
 _onMouseCursorChanged(String action) {
   _canvas.style.cursor = Mouse._getCssStyle(_mouseCursor);
 }
 //-------------------------------------------------------------------------------------------------
 _onMouseEvent(html.MouseEvent event) {
   event.preventDefault();
   var time = new DateTime.now().millisecondsSinceEpoch;
   var button = event.button;
   InteractiveObject target = null;
   Point stagePoint = _clientTransformation._transformHtmlPoint(event.client);
   Point localPoint = null;
   if (button < 0 || button > 2) return;
   if (event.type == "mousemove" && _mousePosition.equals(stagePoint)) return;
   _MouseButton mouseButton = _mouseButtons[button];
   _mousePosition = stagePoint;
   if (Mouse._dragSprite != null) {
     Mouse._dragSprite._updateDrag();
   }
   if (event.type != "mouseout") {
     target = hitTestInput(stagePoint.x, stagePoint.y) as InteractiveObject;
   }
   //-----------------------------------------------------------------
   var mouseCursor = MouseCursor.ARROW;
   if (target is Sprite && (target as Sprite).useHandCursor) {
     mouseCursor = MouseCursor.BUTTON;
   }
   if (target is SimpleButton && (target as SimpleButton).useHandCursor) {
     mouseCursor = MouseCursor.BUTTON;
   }
   if (target is TextField && (target as TextField).type == TextFieldType.INPUT) {
     mouseCursor = MouseCursor.IBEAM;
   }
   if (_mouseCursor != mouseCursor) {
     _mouseCursor = mouseCursor;
     _canvas.style.cursor = Mouse._getCssStyle(mouseCursor);
   }
   //-----------------------------------------------------------------
   if (_mouseTarget != target) {
     DisplayObject oldTarget = _mouseTarget;
     DisplayObject newTarget = target;
     List oldTargetList = [];
     List newTargetList = [];
     int commonCount = 0;
     for(DisplayObject p = oldTarget; p != null; p = p.parent) {
       oldTargetList.add(p);
     }
     for(DisplayObject p = newTarget; p != null; p = p.parent) {
       newTargetList.add(p);
     }
     for(;;commonCount++) {
       if (commonCount == oldTargetList.length) break;
       if (commonCount == newTargetList.length) break;
       var ot = oldTargetList[oldTargetList.length - commonCount - 1];
       var nt = newTargetList[newTargetList.length - commonCount - 1];
       if (ot != nt) break;
     }
     if (oldTarget != null) {
       oldTarget.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OUT, true)
           .._localPoint = oldTarget.globalToLocal(stagePoint)
           .._stagePoint = stagePoint
           .._buttonDown = mouseButton.buttonDown);
     }
     for(int i = 0; i < oldTargetList.length - commonCount; i++) {
       DisplayObject target = oldTargetList[i];
       target.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OUT, false)
           .._localPoint = target.globalToLocal(stagePoint)
           .._stagePoint = stagePoint
           .._buttonDown = mouseButton.buttonDown);
     }
     for(int i = newTargetList.length - commonCount - 1; i >= 0; i--) {
       DisplayObject target = newTargetList[i];
       target.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OVER, false)
           .._localPoint = target.globalToLocal(stagePoint)
           .._stagePoint = stagePoint
           .._buttonDown = mouseButton.buttonDown);
     }
     if (newTarget != null) {
       newTarget.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OVER, true)
           .._localPoint = newTarget.globalToLocal(stagePoint)
           .._stagePoint = stagePoint
           .._buttonDown = mouseButton.buttonDown);
     }
     _mouseTarget = newTarget;
   }
   //-----------------------------------------------------------------
   String mouseEventType = null;
   bool isClick = false;
   bool isDoubleClick = false;
   if (event.type == "mousedown") {
     _canvas.focus();
     mouseEventType = mouseButton.mouseDownEventType;
     if (target != mouseButton.target || time > mouseButton.clickTime + 500) {
       mouseButton.clickCount = 0;
     }
     mouseButton.buttonDown = true;
     mouseButton.target = target;
     mouseButton.clickTime = time;
     mouseButton.clickCount++;
   }
   if (event.type == "mouseup") {
     mouseEventType = mouseButton.mouseUpEventType;
     mouseButton.buttonDown = false;
     isClick = (mouseButton.target == target);
     isDoubleClick = isClick
         && mouseButton.clickCount.isEven
         && (time < mouseButton.clickTime + 500);
   }
   if (event.type == "mousemove") {
     mouseEventType = MouseEvent.MOUSE_MOVE;
   }
   if (event.type == "contextmenu") {
     mouseEventType = MouseEvent.CONTEXT_MENU;
   }
   //-----------------------------------------------------------------
   if (mouseEventType != null && target != null) {
     localPoint = target.globalToLocal(stagePoint);
     target.dispatchEvent(new MouseEvent(mouseEventType, true)
         .._localPoint = localPoint
         .._stagePoint = stagePoint
         .._buttonDown = mouseButton.buttonDown
         .._clickCount = mouseButton.clickCount);
     if (isClick) {
       if (isDoubleClick && target.doubleClickEnabled) {
         target.dispatchEvent(new MouseEvent(mouseButton.mouseDoubleClickEventType, true)
             .._localPoint = localPoint
             .._stagePoint = stagePoint
             .._buttonDown = mouseButton.buttonDown);
       } else {
         target.dispatchEvent(new MouseEvent(mouseButton.mouseClickEventType, true)
             .._localPoint = localPoint
             .._stagePoint = stagePoint
             .._buttonDown = mouseButton.buttonDown);
       }
     }
   }
 }
 //-------------------------------------------------------------------------------------------------
 _onMouseWheelEvent(html.WheelEvent event) {
   var stagePoint = _clientTransformation._transformHtmlPoint(event.client);
   var target = hitTestInput(stagePoint.x, stagePoint.y) as InteractiveObject;
   if (target != null) {
     var mouseEvent = new MouseEvent(MouseEvent.MOUSE_WHEEL, true)
         .._localPoint = target.globalToLocal(stagePoint)
         .._stagePoint = stagePoint
         .._deltaX = event.deltaX
         .._deltaY = event.deltaY;
     target.dispatchEvent(mouseEvent);
     if (mouseEvent.stopsPropagation) event.preventDefault();
   }
 }
 //-------------------------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------------------------
 List<StreamSubscription<html.TouchEvent>> _touchEventSubscriptions = [];
 _onMultitouchInputModeChanged(String inputMode) {
   _touchEventSubscriptions.forEach((s) => s.cancel());
   if (Multitouch.inputMode == MultitouchInputMode.TOUCH_POINT) {
     _touchEventSubscriptions = [
       _canvas.onTouchStart.listen(_onTouchEvent),
       _canvas.onTouchEnd.listen(_onTouchEvent),
       _canvas.onTouchMove.listen(_onTouchEvent),
       _canvas.onTouchEnter.listen(_onTouchEvent),
       _canvas.onTouchLeave.listen(_onTouchEvent),
       _canvas.onTouchCancel.listen(_onTouchEvent)
     ];
   }
 }
 //-------------------------------------------------------------------------------------------------
 _onTouchEvent(html.TouchEvent event) {
   event.preventDefault();
   for(var changedTouch in event.changedTouches) {
     var identifier = changedTouch.identifier;
     var stagePoint = _clientTransformation._transformHtmlPoint(changedTouch.client);
     var target = hitTestInput(stagePoint.x, stagePoint.y) as InteractiveObject;
     var touch = _touches.containsKey(identifier) ? _touches[identifier] : new _Touch(target, _touches.length == 0);
     //-----------------------------------------------------------------
     if (touch.target != null && touch.target != target) {
       touch.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OUT, true)
         .._localPoint = (touch.target.stage != null)
             ? touch.target.globalToLocal(stagePoint) : new Point.zero()
         .._stagePoint = stagePoint
         .._touchPointID = touch.touchPointID
         .._isPrimaryTouchPoint = touch.primaryTouchPoint);
       touch.target = null;
     }
     if (target != null && target != touch.target) {
       target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OVER, true)
         .._localPoint = target.globalToLocal(stagePoint)
         .._stagePoint = stagePoint
         .._touchPointID = touch.touchPointID
         .._isPrimaryTouchPoint = touch.primaryTouchPoint);
       touch.target = target;
     }
     //-----------------------------------------------------------------
     String touchEventType = null;
     if (event.type == "touchstart") {
       _canvas.focus();
       _touches[identifier] = touch;
       touchEventType = TouchEvent.TOUCH_BEGIN;
     }
     if (event.type == "touchend") {
       _touches.remove(identifier);
       touchEventType = TouchEvent.TOUCH_END;
     }
     if (event.type == "touchcancel") {
       _touches.remove(identifier);
       touchEventType = TouchEvent.TOUCH_CANCEL;
     }
     if (event.type == "touchmove") {
       touchEventType = TouchEvent.TOUCH_MOVE;
     }
     if (touchEventType != null && target != null) {
       target.dispatchEvent(new TouchEvent(touchEventType, true)
         .._localPoint = target.globalToLocal(stagePoint)
         .._stagePoint = stagePoint
         .._touchPointID = touch.touchPointID
         .._isPrimaryTouchPoint = touch.primaryTouchPoint);
     }
   }
 }
 //-------------------------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------------------------
 _onKeyEvent(html.KeyboardEvent event) {
   if (event.keyCode == 8) event.preventDefault();
   if (_focus == null) return;
   if (event.type == "keypress") {
     var charCode = event.charCode;
     var keyCode = event.keyCode;
     if (keyCode == 13) charCode = 13;
     if (charCode == 0) return;
     _focus.dispatchEvent(new TextEvent(TextEvent.TEXT_INPUT, true)
         .._text = new String.fromCharCodes([charCode]));
   } else {
     var keyLocation = KeyLocation.STANDARD;
     var keyboardEventType = "";
     if (event.type == "keyup") keyboardEventType = KeyboardEvent.KEY_UP;
     if (event.type == "keydown") keyboardEventType = KeyboardEvent.KEY_DOWN;
     if (event.keyLocation == html.KeyLocation.LEFT) keyLocation = KeyLocation.LEFT;
     if (event.keyLocation == html.KeyLocation.RIGHT) keyLocation = KeyLocation.RIGHT;
     if (event.keyLocation == html.KeyLocation.NUMPAD) keyLocation = KeyLocation.NUM_PAD;
     if (event.keyLocation == html.KeyLocation.JOYSTICK) keyLocation = KeyLocation.D_PAD;
     if (event.keyLocation == html.KeyLocation.MOBILE) keyLocation = KeyLocation.D_PAD;
     var keyboardEvent = new KeyboardEvent(keyboardEventType, true)
         .._altKey = event.altKey
         .._ctrlKey = event.ctrlKey
         .._shiftKey = event.shiftKey
         .._charCode = event.charCode
         .._keyCode = event.keyCode
         .._keyLocation = keyLocation;
     _focus.dispatchEvent(keyboardEvent);
     if (keyboardEvent.stopsPropagation) event.preventDefault();
   }
 }
}
Extends
EventDispatcher > DisplayObject > InteractiveObject > DisplayObjectContainer > Stage
Static Properties
const EventStreamProvider<Event> resizeEvent #
static const EventStreamProvider<Event> resizeEvent = const EventStreamProvider<Event>(Event.RESIZE)
Constructors
new Stage(CanvasElement canvas, {int width, int height, bool webGL: false, int frameRate: 30, int color: Color.White}) #
Creates a new Object instance.
Object instances have no meaningful state, and are only useful through their identity. An Object instance is equal to itself only.
Stage(CanvasElement canvas, {int width, int height,
 bool webGL: false, int frameRate: 30, int color: Color.White}) {
 if (canvas is! CanvasElement) {
   throw new ArgumentError("The canvas argument is not a CanvasElement");
 }
 _canvas = canvas;
 if (canvas.tabIndex == -1) canvas.tabIndex = 0;
 if (canvas.style.outline == "") canvas.style.outline = "none";
 _sourceWidth = _ensureInt((width != null) ? width : canvas.width);
 _sourceHeight = _ensureInt((width != null) ? height : canvas.height);
 _frameRate = _ensureInt((frameRate != null) ? frameRate : 30);
 _renderContext = webGL && gl.RenderingContext.supported
     ? new RenderContextWebGL(canvas, color)
     : new RenderContextCanvas(canvas, color);
 _renderState = new RenderState(_renderContext);
 _updateCanvasSize();
 print("StageXL render engine : ${_renderContext.renderEngine}");
 canvas.onKeyDown.listen(_onKeyEvent);
 canvas.onKeyUp.listen(_onKeyEvent);
 canvas.onKeyPress.listen(_onKeyEvent);
 canvas.onMouseDown.listen(_onMouseEvent);
 canvas.onMouseUp.listen(_onMouseEvent);
 canvas.onMouseMove.listen(_onMouseEvent);
 canvas.onMouseOut.listen(_onMouseEvent);
 canvas.onContextMenu.listen(_onMouseEvent);
 canvas.onMouseWheel.listen(_onMouseWheelEvent);
 Mouse._onMouseCursorChanged.listen(_onMouseCursorChanged);
 Multitouch._onInputModeChanged.listen(_onMultitouchInputModeChanged);
 _onMultitouchInputModeChanged(null);
}
Properties
String align #
Gets and sets the alignment of this Stage inside of the Canvas element. You can choose between nine different align modes defined in StageAlign.
String get align => _stageAlign;
set align(String value) {
 _stageAlign = value;
 _updateCanvasSize();
}
String compositeOperation #
String get compositeOperation => _compositeOperation;
set compositeOperation(String value) {
 _compositeOperation = value;
}
final Rectangle contentRectangle #
Gets the available content area on the stage. The value of this rectangle changes with the scaleMode and the alignment of the stage, as well as the size of the underlying Canvas element.
Rectangle get contentRectangle => _contentRectangle.clone();
List<BitmapFilter> filters #
List<BitmapFilter> get filters {
 if (_filters == null) _filters = new List<BitmapFilter>();
 return _filters;
}
set filters(List<BitmapFilter> value) {
 _filters = value;
}
InteractiveObject focus #
Gets and sets the InteractiveObject (a DisplayObject which can receive user input like mouse, touch or keyboard).
InteractiveObject get focus => _focus;
set focus(InteractiveObject value) {
 _focus = value;
}
int frameRate #
Gets and sets the default frame rate for MovieClips. This value has no impact on the frame rate of the Stage itself.
int get frameRate => _frameRate;
set frameRate(int value) {
 _frameRate = value;
}
num get height #
num get height => getBoundsTransformed(this.transformationMatrix).height;
final Juggler juggler #
Gets the Juggler of this Stage. The Juggler is driven by the RenderLoop where this Stage is added to. If this Stage is not added to a RenderLoop, the Juggler will not advance in time.
Juggler get juggler => _juggler;
Mask mask #
Mask get mask => _mask;
set mask(Mask value) {
 _mask = value;
}
bool mouseChildren #
bool get mouseChildren => _mouseChildren;
void set mouseChildren(bool value) { _mouseChildren = value; }
final Point mousePosition #
Gets the last known mouse position in Stage coordinates.
Point get mousePosition => _mousePosition;
final num mouseX #
num get mouseX {
 var mp = this.mousePosition;
 return (mp != null) ? mp.x : 0.0;
}
final num mouseY #
num get mouseY {
 var mp = this.mousePosition;
 return (mp != null) ? mp.y : 0.0;
}
String name #
String get name => _name;
set name(String value) {
 _name = value;
}
final int numChildren #
int get numChildren => _children.length;
bool off #
bool get off => _off;
set off(bool value) {
 if (value is bool) _off = value;
}
final EventStream<Event> onAdded #
EventStream<Event> get onAdded => DisplayObject.addedEvent.forTarget(this);
final EventStream<Event> onAddedToStage #
EventStream<Event> get onAddedToStage => DisplayObject.addedToStageEvent.forTarget(this);
final EventStream<EnterFrameEvent> onEnterFrame #
EventStream<EnterFrameEvent> get onEnterFrame => DisplayObject.enterFrameEvent.forTarget(this);
final EventStream<ExitFrameEvent> onExitFrame #
EventStream<ExitFrameEvent> get onExitFrame => DisplayObject.exitFrameEvent.forTarget(this);
final EventStream<KeyboardEvent> onKeyDown #
EventStream<KeyboardEvent> get onKeyDown => InteractiveObject.keyDownEvent.forTarget(this);
final EventStream<KeyboardEvent> onKeyUp #
EventStream<KeyboardEvent> get onKeyUp => InteractiveObject.keyUpEvent.forTarget(this);
final EventStream<MouseEvent> onMouseClick #
EventStream<MouseEvent> get onMouseClick => InteractiveObject.mouseClickEvent.forTarget(this);
final EventStream<MouseEvent> onMouseContextMenu #
EventStream<MouseEvent> get onMouseContextMenu => InteractiveObject.mouseContextMenu.forTarget(this);
final EventStream<MouseEvent> onMouseDoubleClick #
EventStream<MouseEvent> get onMouseDoubleClick => InteractiveObject.mouseDoubleClickEvent.forTarget(this);
final EventStream<MouseEvent> onMouseDown #
EventStream<MouseEvent> get onMouseDown => InteractiveObject.mouseDownEvent.forTarget(this);
final EventStream<MouseEvent> onMouseMiddleClick #
EventStream<MouseEvent> get onMouseMiddleClick => InteractiveObject.mouseMiddleClickEvent.forTarget(this);
final EventStream<MouseEvent> onMouseMiddleDown #
EventStream<MouseEvent> get onMouseMiddleDown => InteractiveObject.mouseMiddleDownEvent.forTarget(this);
final EventStream<MouseEvent> onMouseMiddleUp #
EventStream<MouseEvent> get onMouseMiddleUp => InteractiveObject.mouseMiddleUpEvent.forTarget(this);
final EventStream<MouseEvent> onMouseMove #
EventStream<MouseEvent> get onMouseMove => InteractiveObject.mouseMoveEvent.forTarget(this);
final EventStream<MouseEvent> onMouseOut #
EventStream<MouseEvent> get onMouseOut => InteractiveObject.mouseOutEvent.forTarget(this);
final EventStream<MouseEvent> onMouseOver #
EventStream<MouseEvent> get onMouseOver => InteractiveObject.mouseOverEvent.forTarget(this);
final EventStream<MouseEvent> onMouseRightClick #
EventStream<MouseEvent> get onMouseRightClick => InteractiveObject.mouseRightClickEvent.forTarget(this);
final EventStream<MouseEvent> onMouseRightDown #
EventStream<MouseEvent> get onMouseRightDown => InteractiveObject.mouseRightDownEvent.forTarget(this);
final EventStream<MouseEvent> onMouseRightUp #
EventStream<MouseEvent> get onMouseRightUp => InteractiveObject.mouseRightUpEvent.forTarget(this);
final EventStream<MouseEvent> onMouseRollOut #
EventStream<MouseEvent> get onMouseRollOut => InteractiveObject.mouseRollOutEvent.forTarget(this);
final EventStream<MouseEvent> onMouseRollOver #
EventStream<MouseEvent> get onMouseRollOver => InteractiveObject.mouseRollOverEvent.forTarget(this);
final EventStream<MouseEvent> onMouseUp #
EventStream<MouseEvent> get onMouseUp => InteractiveObject.mouseUpEvent.forTarget(this);
final EventStream<MouseEvent> onMouseWheel #
EventStream<MouseEvent> get onMouseWheel => InteractiveObject.mouseWheelEvent.forTarget(this);
final EventStream<Event> onRemoved #
EventStream<Event> get onRemoved => DisplayObject.removedEvent.forTarget(this);
final EventStream<Event> onRemovedFromStage #
EventStream<Event> get onRemovedFromStage => DisplayObject.removedFromStageEvent.forTarget(this);
final EventStream<RenderEvent> onRender #
EventStream<RenderEvent> get onRender => DisplayObject.renderEvent.forTarget(this);
final EventStream<Event> onResize #
EventStream<Event> get onResize => Stage.resizeEvent.forTarget(this);
final EventStream<TextEvent> onTextInput #
EventStream<TextEvent> get onTextInput => InteractiveObject.textInputEvent.forTarget(this);
final EventStream<TouchEvent> onTouchBegin #
EventStream<TouchEvent> get onTouchBegin => InteractiveObject.touchBeginEvent.forTarget(this);
final EventStream<TouchEvent> onTouchCancel #
EventStream<TouchEvent> get onTouchCancel => InteractiveObject.touchCancelEvent.forTarget(this);
final EventStream<TouchEvent> onTouchEnd #
EventStream<TouchEvent> get onTouchEnd => InteractiveObject.touchEndEvent.forTarget(this);
final EventStream<TouchEvent> onTouchMove #
EventStream<TouchEvent> get onTouchMove => InteractiveObject.touchMoveEvent.forTarget(this);
final EventStream<TouchEvent> onTouchOut #
EventStream<TouchEvent> get onTouchOut => InteractiveObject.touchOutEvent.forTarget(this);
final EventStream<TouchEvent> onTouchOver #
EventStream<TouchEvent> get onTouchOver => InteractiveObject.touchOverEvent.forTarget(this);
final DisplayObjectContainer parent #
DisplayObjectContainer get parent => _parent;
final String renderEngine #
Gets the underlying render engine used to draw the pixels to the screen. The returned string is defined in RenderEngine and is either "WebGL" or "Canvas2D".
String get renderEngine => _renderContext.renderEngine;
final RenderLoop renderLoop #
Gets the RenderLoop where this Stage was added to, or NULL in case this Stage is not added to a RenderLoop.
RenderLoop get renderLoop => _renderLoop;
String renderMode #
Gets and sets the render mode of this Stage. You can choose between three different modes defined in StageRenderMode.
String get renderMode => _stageRenderMode;
set renderMode(String value) {
 _stageRenderMode = value;
}
final DisplayObject root #
DisplayObject get root {
 DisplayObject currentObject = this;
 while (currentObject._parent != null)
   currentObject = currentObject._parent;
 return currentObject;
}
String scaleMode #
Gets and sets the scale mode of this Stage. You can choose between four dfferent modes defined in StageScaleMode.
String get scaleMode => _stageScaleMode;
set scaleMode(String value) {
 _stageScaleMode = value;
 _updateCanvasSize();
}
Shadow shadow #
Shadow get shadow => _shadow;
set shadow(Shadow value) {
 _shadow = value;
}
final int sourceHeight #
Gets the original source height of the Stage as defined in the constructor.
int get sourceHeight => _sourceHeight;
final int sourceWidth #
Gets the original source width of the Stage as defined in the constructor.
int get sourceWidth => _sourceWidth;
final Stage stage #
Stage get stage {
 DisplayObject root = this.root;
 return (root is Stage) ? root : null;
}
final int stageHeight #
Gets the current height of the Stage in pixels on the screen.
int get stageHeight => _canvasHeight;
final int stageWidth #
Gets the current width of the Stage in pixels on the screen.
int get stageWidth => _canvasWidth;
bool tabChildren #
bool get tabChildren => _tabChildren;
void set tabChildren(bool value) { _tabChildren = value; }
final Matrix transformationMatrix #
Matrix get transformationMatrix {
 /*
 _transformationMatrix.identity();
 _transformationMatrix.translate(-_pivotX, -_pivotY);
 _transformationMatrix.scale(_scaleX, _scaleY);
 _transformationMatrix.rotate(_rotation);
 _transformationMatrix.translate(_x, _y);
 */
 if (_transformationMatrixRefresh) {
   _transformationMatrixRefresh = false;
   num skewXrotation =  _skewX + _rotation;
   num skewYrotation =  _skewY + _rotation;
   num scaleX = _scaleX;
   num scaleY = _scaleY;
   num pivotX = _pivotX;
   num pivotY = _pivotY;
   // ToDo: https://bugzilla.mozilla.org/show_bug.cgi?id=661452
   if (scaleX > -0.0001 && scaleX < 0.0001) scaleX = (scaleX >= 0) ? 0.0001 : -0.0001;
   if (scaleY > -0.0001 && scaleY < 0.0001) scaleY = (scaleY >= 0) ? 0.0001 : -0.0001;
   if (skewXrotation == 0.0 && skewYrotation == 0.0) {
     _transformationMatrix.setTo(scaleX, 0.0, 0.0, scaleY, _x - pivotX * scaleX, _y - pivotY * scaleY);
   } else {
     num a, b, c, d;
     num cosX = cos(skewXrotation);
     num sinX = sin(skewXrotation);
     if (skewXrotation == skewYrotation) {
       a =   scaleX * cosX;
       b =   scaleX * sinX;
       c = - scaleY * sinX;
       d =   scaleY * cosX;
     } else {
       a =   scaleX * cos(skewYrotation);
       b =   scaleX * sin(skewYrotation);
       c = - scaleY * sinX;
       d =   scaleY * cosX;
     }
     num tx =  _x - (pivotX * a + pivotY * c);
     num ty =  _y - (pivotX * b + pivotY * d);
     _transformationMatrix.setTo(a, b, c, d, tx, ty);
   }
 }
 return _transformationMatrix;
}
var userData #
Gets or sets user-defined data associated with the display object.
dynamic userData = null
bool visible #
bool get visible => _visible;
set visible(bool value) {
 if (value is bool) _visible = value;
}
num get width #
num get width => getBoundsTransformed(this.transformationMatrix).width;
Methods
void addChild(DisplayObject child) #
void addChild(DisplayObject child) {
 addChildAt(child, _children.length);
}
void addChildAt(DisplayObject child, int index) #
void addChildAt(DisplayObject child, int index) {
 if (index < 0 || index > _children.length) {
   throw new ArgumentError("Error #2006: The supplied index is out of bounds.");
 }
 if (child == this) {
   throw new ArgumentError("Error #2024: An object cannot be added as a child of itself.");
 }
 if (child.parent == this) {
   _children.remove(child);
   if (index > _children.length) index -= 1;
   _children.insert(index, child);
 } else {
   child.removeFromParent();
   for(var ancestor = this; ancestor != null; ancestor = ancestor.parent) {
     if (ancestor == child) {
       throw new ArgumentError("Error #2150: An object cannot be added as "
           "a child to one of it's children (or children's children, etc.).");
     }
   }
   _children.insert(index, child);
   child._parent = this;
   child.dispatchEvent(new Event(Event.ADDED, true));
   if (this.stage != null) {
     _dispatchEventDescendants(child, new Event(Event.ADDED_TO_STAGE));
   }
 }
}
StreamSubscription<Event> addEventListener(String eventType, EventListener eventListener, {bool useCapture: false, int priority: 0}) #
StreamSubscription<Event> addEventListener(String eventType, EventListener eventListener, {
 bool useCapture: false, int priority: 0 }) {
 return this.on(eventType)._subscribe(eventListener, useCapture, priority);
}
void addTo(DisplayObjectContainer parent) #
void addTo(DisplayObjectContainer parent) {
 parent.addChild(this);
}
void applyCache(int x, int y, int width, int height, {bool debugBorder: false}) #
void applyCache(int x, int y, int width, int height, {bool debugBorder: false}) {
 var pixelRatio = Stage.autoHiDpi ? _devicePixelRatio : 1.0;
 if (_cacheTexture == null) {
   _cacheTexture = new RenderTexture(width, height, true, Color.Transparent, pixelRatio);
 } else {
   _cacheTexture.resize(width, height);
 }
 _cacheRectangle = new Rectangle(x, y, width, height);
 _cacheDebugBorder = debugBorder;
 refreshCache();
}
bool contains(DisplayObject child) #
bool contains(DisplayObject child) {
 while(child != null) {
   if (child == this) return true;
   child = child.parent;
 }
 return false;
}
void dispatchEvent(Event event) #
void dispatchEvent(Event event) {
 List<DisplayObject> ancestors = null;
 if (event.captures || event.bubbles) {
   for(DisplayObject ancestor = parent; ancestor != null; ancestor = ancestor.parent) {
     if(ancestor._hasPropagationEventListeners(event)) {
       if (ancestors == null) ancestors = [];
       ancestors.add(ancestor);
     }
   }
 }
 if (ancestors != null && event.captures) {
   for(int i = ancestors.length - 1 ; i >= 0; i--) {
     ancestors[i]._dispatchEventInternal(event, this, EventPhase.CAPTURING_PHASE);
     if (event.stopsPropagation) return;
   }
 }
 _dispatchEventInternal(event, this, EventPhase.AT_TARGET);
 if (event.stopsPropagation) return;
 if (ancestors != null && event.bubbles) {
   for(int i = 0; i < ancestors.length; i++) {
     ancestors[i]._dispatchEventInternal(event, this, EventPhase.BUBBLING_PHASE);
     if (event.stopsPropagation) return;
   }
 }
}
Rectangle getBounds(DisplayObject targetSpace) #
Rectangle getBounds(DisplayObject targetSpace) {
 Rectangle returnRectangle = new Rectangle.zero();
 Matrix matrix = (targetSpace == null) ? transformationMatrix : transformationMatrixTo(targetSpace);
 return (matrix != null) ? getBoundsTransformed(matrix, returnRectangle) : returnRectangle;
}
Rectangle getBoundsTransformed(Matrix matrix, [Rectangle returnRectangle]) #
Rectangle getBoundsTransformed(Matrix matrix, [Rectangle returnRectangle]) {
 if (returnRectangle == null) {
   returnRectangle = new Rectangle.zero();
 }
 if (_children.length == 0) {
   return super.getBoundsTransformed(matrix, returnRectangle);
 }
 num left = double.INFINITY;
 num top = double.INFINITY;
 num right = double.NEGATIVE_INFINITY;
 num bottom = double.NEGATIVE_INFINITY;
 int childrenLength = _children.length;
 for (int i = 0; i < _children.length; i++) {
   DisplayObject child = _children[i];
   _tmpMatrix.copyFromAndConcat(child.transformationMatrix, matrix);
   Rectangle rectangle = child.getBoundsTransformed(_tmpMatrix, returnRectangle);
   if (rectangle.left < left) left = rectangle.left;
   if (rectangle.top < top ) top = rectangle.top;
   if (rectangle.right > right) right = rectangle.right;
   if (rectangle.bottom > bottom) bottom = rectangle.bottom;
 }
 returnRectangle.x = left;
 returnRectangle.y = top;
 returnRectangle.width = right - left;
 returnRectangle.height = bottom - top;
 return returnRectangle;
}
dynamic getChildAt(int index) #
dynamic getChildAt(int index) {
 if (index < 0 || index >= _children.length) {
   throw new ArgumentError("Error #2006: The supplied index is out of bounds.");
 }
 return _children[index];
}
dynamic getChildByName(String name) #
dynamic getChildByName(String name) {
 for(int i = 0; i < _children.length; i++) {
   DisplayObject child = _children[i];
   if (child.name == name) return child;
 }
 return null;
}
int getChildIndex(DisplayObject child) #
int getChildIndex(DisplayObject child) {
 return _children.indexOf(child);
}
Point globalToLocal(Point globalPoint) #
Point globalToLocal(Point globalPoint) {
 _tmpMatrix.identity();
 for(var current = this; current != null; current = current._parent) {
   _tmpMatrix.concat(current.transformationMatrix);
 }
 _tmpMatrix.invert();
 return _tmpMatrix.transformPoint(globalPoint);
}
bool hasEventListener(String eventType) #
bool hasEventListener(String eventType) {
 var eventStreams = _eventStreams;
 if (eventStreams == null) return false;
 var eventStream = eventStreams[eventType];
 if (eventStream == null) return false;
 return eventStream.hasSubscriptions;
}
DisplayObject hitTestInput(num localX, num localY) #
DisplayObject hitTestInput(num localX, num localY) {
 localX = localX.toDouble();
 localY = localY.toDouble();
 DisplayObject hit = null;
 for (int i = _children.length - 1; i >= 0; i--) {
   var child = _children[i];
   var mask = child.mask;
   var matrix = child.transformationMatrix;
   if (child.visible && child.off == false) {
     num deltaX = localX - matrix.tx;
     num deltaY = localY - matrix.ty;
     num childX = (matrix.d * deltaX - matrix.c * deltaY) / matrix.det;
     num childY = (matrix.a * deltaY - matrix.b * deltaX) / matrix.det;
     num maskX = 0.0;
     num maskY = 0.0;
     if (mask != null) {
       if (mask.targetSpace == null) {
         maskX = childX;
         maskY = childY;
       } else if (identical(mask.targetSpace, child)) {
         maskX = childX;
         maskY = childY;
       } else if (identical(mask.targetSpace, this)) {
         maskX = localX;
         maskY = localY;
       } else {
         matrix = this.transformationMatrixTo(mask.targetSpace);
         matrix = (matrix != null) ? matrix : _identityMatrix;
         maskX = localX * matrix.a + localY * matrix.c + matrix.tx;
         maskY = localX * matrix.b + localY * matrix.d + matrix.ty;
       }
       if (mask.hitTest(maskX, maskY) == false) continue;
     }
     var displayObject = child.hitTestInput(childX, childY);
     if (displayObject == null) continue;
     if (displayObject is InteractiveObject && displayObject.mouseEnabled) {
       return _mouseChildren ? displayObject : this;
     }
     hit = this;
   }
 }
 return hit;
}
bool hitTestObject(DisplayObject other) #
bool hitTestObject(DisplayObject other) {
 var stage1 = this.stage;
 var stage2 = other.stage;
 if (stage1 == null || stage2 == null || stage1 != stage2) return false;
 var rect1 = this.getBounds(stage1);
 var rect2 = other.getBounds(stage2);
 return rect1.intersects(rect2);
}
bool hitTestPoint(num x, num y, [bool shapeFlag = false]) #
bool hitTestPoint(num x, num y, [bool shapeFlag = false]) {
 var stage = this.stage;
 if (stage == null) return false;
 if (shapeFlag) {
   var matrix = stage.transformationMatrixTo(this);
   if (matrix == null) return false;
   var stagePoint = new Point(x, y);
   var localPoint = matrix.transformPoint(stagePoint);
   return this.hitTestInput(localPoint.x, localPoint.y) != null;
 } else {
   var rect = this.getBounds(stage);
   return rect.contains(x, y);
 }
}
dynamic invalidate() #
Calling this method will cause an RenderEvent to be fired right before the next frame will be rendered by the render loop. To receive the render event attach a listener to DisplayObject.onRender.
invalidate() {
 if (_renderLoop != null) {
   _renderLoop.invalidate();
 }
}
Point localToGlobal(Point localPoint) #
Point localToGlobal(Point localPoint) {
 _tmpMatrix.identity();
 for(var current = this; current != null; current = current._parent) {
   _tmpMatrix.concat(current.transformationMatrix);
 }
 return _tmpMatrix.transformPoint(localPoint);
}
dynamic materialize(num currentTime, num deltaTime) #
This method is called by the RenderLoop where this Stage is added to. If this Stage is not added to a RenderLoop you could call this method on your own and therefore get full control of the rendering of this Stage.
materialize(num currentTime, num deltaTime) {
 if (_stageRenderMode == StageRenderMode.AUTO || _stageRenderMode == StageRenderMode.ONCE) {
   _updateCanvasSize();
   _renderState.reset(_stageTransformation, currentTime, deltaTime);
   render(_renderState);
   _renderState.flush();
   if (_stageRenderMode == StageRenderMode.ONCE)
     _stageRenderMode = StageRenderMode.STOP;
 }
}
EventStream<Event> on(String eventType) #
EventStream<Event> on(String eventType) {
 var eventStreams = _eventStreams;
 if (eventStreams == null) {
   eventStreams = new Map<String, EventStream>();
   _eventStreams = eventStreams;
 }
 var eventStream = eventStreams[eventType];
 if (eventStream == null) {
   eventStream = new EventStream._internal(this, eventType);
   eventStreams[eventType] = eventStream;
 }
 return eventStream;
}
void refreshCache() #
void refreshCache() {
 if (_cacheTexture == null) return;
 var x = _cacheRectangle.x;
 var y = _cacheRectangle.y;
 var width = _cacheRectangle.width;
 var height = _cacheRectangle.height;
 var canvas = _cacheTexture.canvas;
 var matrix = _cacheTexture.quad.drawMatrix..translate(-x, -y);
 var renderContext = new RenderContextCanvas(canvas, Color.Transparent);
 var renderState = new RenderState(renderContext, matrix);
 renderContext.clear();
 render(renderState);
 if (_filters != null) {
   var cacheBitmapData = new BitmapData.fromRenderTextureQuad(_cacheTexture.quad);
   var bounds = this.getBoundsTransformed(_identityMatrix)..offset(-x, -y);
   for(var filter in _filters) {
     var filterOverlap = filter.overlap;
     var filterBounds = bounds.clone();
     filterBounds.offset(filterOverlap.x, filterOverlap.y);
     filterBounds.inflate(filterOverlap.width, filterOverlap.height);
     filter.apply(cacheBitmapData, filterBounds.align());
   }
 }
 if (_cacheDebugBorder) {
   canvas.context2D
       ..setTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)
       ..lineWidth = 1
       ..lineJoin = "miter"
       ..lineCap = "butt"
       ..strokeStyle = "#FF00FF"
       ..strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
 }
 _cacheTexture.update();
}
void removeCache() #
void removeCache() {
 if (_cacheTexture != null) {
   _cacheTexture.dispose();
   _cacheTexture = null;
 }
}
void removeChild(DisplayObject child) #
void removeChild(DisplayObject child) {
 int childIndex = _children.indexOf(child);
 if (childIndex == -1) {
   throw new ArgumentError(
       "Error #2025: The supplied DisplayObject must be a child of the caller.");
 }
 removeChildAt(childIndex);
}
void removeChildAt(int index) #
void removeChildAt(int index) {
 if (index < 0 || index >= _children.length) {
   throw new ArgumentError("Error #2006: The supplied index is out of bounds.");
 }
 DisplayObject child = _children[index];
 child.dispatchEvent(new Event(Event.REMOVED, true));
 if (this.stage != null) {
   _dispatchEventDescendants(child, new Event(Event.REMOVED_FROM_STAGE));
 }
 child._parent = null;
 _children.removeAt(index);
}
void removeChildren([int beginIndex = 0, int endIndex = 0x7fffffff]) #
void removeChildren([int beginIndex = 0, int endIndex = 0x7fffffff]) {
 var length = _children.length;
 if (length == 0) return;
 if (endIndex == 0x7fffffff) {
   endIndex = length - 1;
 }
 if (beginIndex < 0 || endIndex < 0 || beginIndex >= length || endIndex >= length) {
   throw new ArgumentError("Error #2006: The supplied index is out of bounds.");
 }
 for(int i = beginIndex; i <= endIndex; i++) {
   if (beginIndex >= _children.length) break;
   removeChildAt(beginIndex);
 }
}
void removeEventListener(String eventType, EventListener eventListener, {bool useCapture: false}) #
void removeEventListener(String eventType, EventListener eventListener, {
 bool useCapture: false }) {
 this.on(eventType)._unsubscribe(eventListener, useCapture);
}
void removeEventListeners(String eventType) #
void removeEventListeners(String eventType) {
 this.on(eventType).cancelSubscriptions();
}
void removeFromParent() #
void removeFromParent() {
 if (_parent != null)
   _parent.removeChild(this);
}
void render(RenderState renderState) #
void render(RenderState renderState) {
 for(int i = 0; i < _children.length; i++) {
   DisplayObject child = _children[i];
   if (child.visible && child.off == false) {
     renderState.renderDisplayObject(child);
   }
 }
}
void setChildIndex(DisplayObject child, int index) #
void setChildIndex(DisplayObject child, int index) {
 if (index < 0 || index >= _children.length) {
   throw new ArgumentError("Error #2006: The supplied index is out of bounds.");
 }
 int oldIndex = getChildIndex(child);
 if (oldIndex == -1) {
   throw new ArgumentError("Error #2025: The supplied DisplayObject must be a child of the caller.");
 }
 _children.removeAt(oldIndex);
 _children.insert(index, child);
}
void setTransform(num x, num y, [num scaleX, num scaleY, num rotation, num skewX, num skewY, num pivotX, num pivotY]) #
void setTransform(num x, num y, [num scaleX, num scaleY, num rotation, num skewX, num skewY, num pivotX, num pivotY]) {
 if (x is num) _x = x;
 if (y is num) _y = y;
 if (scaleX is num) _scaleX = scaleX;
 if (scaleY is num) _scaleY = scaleY;
 if (rotation is num) _rotation = rotation;
 if (skewX is num) _skewX = skewX;
 if (skewY is num) _skewY = skewY;
 if (pivotX is num) _pivotX = pivotX;
 if (pivotY is num) _pivotY = pivotY;
 _transformationMatrixRefresh = true;
}
void sortChildren(Function compareFunction) #
void sortChildren(Function compareFunction) {
 _children.sort(compareFunction);
}
void swapChildren(DisplayObject child1, DisplayObject child2) #
void swapChildren(DisplayObject child1, DisplayObject child2) {
 int index1 = getChildIndex(child1);
 int index2 = getChildIndex(child2);
 if (index1 == -1 || index2 == -1) {
   throw new ArgumentError("Error #2025: The supplied DisplayObject must be a child of the caller.");
 }
 swapChildrenAt(index1, index2);
}
void swapChildrenAt(int index1, int index2) #
void swapChildrenAt(int index1, int index2) {
 DisplayObject child1 = getChildAt(index1);
 DisplayObject child2 = getChildAt(index2);
 _children[index1] = child2;
 _children[index2] = child1;
}
Matrix transformationMatrixTo(DisplayObject targetSpace) #
Matrix transformationMatrixTo(DisplayObject targetSpace) {
 if (targetSpace == _parent) {
   return this.transformationMatrix.clone();
 }
 if (targetSpace != null && targetSpace._parent == this) {
   return targetSpace.transformationMatrix.cloneInvert();
 }
 //------------------------------------------------
 Matrix resultMatrix = new Matrix.fromIdentity();
 DisplayObject resultObject = this;
 while(resultObject != targetSpace && resultObject._parent != null) {
   resultMatrix.concat(resultObject.transformationMatrix);
   resultObject = resultObject._parent;
 }
 if (targetSpace == null && resultObject != null) {
   resultMatrix.concat(resultObject.transformationMatrix);
   resultObject = null;
 }
 if (resultObject == targetSpace)
   return resultMatrix;
 //------------------------------------------------
 Matrix targetMatrix = new Matrix.fromIdentity();
 DisplayObject targetObject = targetSpace;
 while(targetObject != this && targetObject._parent != null) {
   targetMatrix.concat(targetObject.transformationMatrix);
   targetObject = targetObject._parent;
 }
 targetMatrix.invert();
 if (targetObject == this) {
   return targetMatrix;
 }
 if (targetObject != resultObject) {
   return null;
 }
 resultMatrix.concat(targetMatrix);
 return resultMatrix;
}