1 /** 2 * The MIT License (MIT) 3 * 4 * Copyright (c) 2016 DeNA Co., Ltd. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 /// <reference path="base.js"/> 26 /// <reference path="object.js"/> 27 /// <reference path="shadow.js"/> 28 /// <reference path="bounding_box.js"/> 29 /// <reference path="color.js"/> 30 /// <reference path="rectangle.js"/> 31 /// <reference path="transform.js"/> 32 /// <reference path="point.js"/> 33 34 /** 35 * An abstract class that renders shapes and objects to an HTMLCanvasElement 36 * object. 37 * @param {HTMLCanvasElement} canvas 38 * @param {number} width 39 * @param {number} height 40 * @constructor 41 */ 42 createjs.Renderer = function(canvas, width, height) { 43 /// <param type="HTMLCanvasElement" name="canvas"/> 44 /// <param type="number" name="width"/> 45 /// <param type="number" name="height"/> 46 /** 47 * The output <canvas> element. 48 * @type {HTMLCanvasElement} 49 * @private 50 */ 51 this.canvas_ = canvas; 52 53 /** 54 * The current width of the output <canvas> element. 55 * @type {number} 56 * @private 57 */ 58 this.width_ = width; 59 60 /** 61 * The current height of the output <canvas> element. 62 * @type {number} 63 * @private 64 */ 65 this.height_ = height; 66 }; 67 68 /** 69 * Whether this renderer applies workarounds for Android browsers. 70 * @type {number} 71 * @private 72 */ 73 createjs.Renderer.prototype.useAndroidWorkarounds_ = -1; 74 75 /** 76 * The ratio of a point in this renderer to one of CSS. 77 * @type {createjs.Point} 78 * @private 79 */ 80 createjs.Renderer.prototype.cssRatio_ = null; 81 82 /** 83 * Composite operations. 84 * @enum {number} 85 */ 86 createjs.Renderer.Composition = { 87 SOURCE_OVER: 0, 88 SOURCE_ATOP: 1, 89 SOURCE_IN: 2, 90 SOURCE_OUT: 3, 91 DESTINATION_OVER: 4, 92 DESTINATION_ATOP: 5, 93 DESTINATION_IN: 6, 94 DESTINATION_OUT: 7, 95 LIGHTER: 8, 96 COPY: 9, 97 XOR: 10, 98 DARKER: 11, 99 MULTIPLY: 12, 100 MASK: 15 101 }; 102 103 /** 104 * Mask methods. 105 * @enum {number} 106 */ 107 createjs.Renderer.Mask = { 108 SCISSOR: 1, 109 COMPOSE: 2, 110 SHOW: 3, 111 HIDE: 4 112 }; 113 114 /** 115 * Color formats used by WebGLTextures. 116 * @enum {number} 117 */ 118 createjs.Renderer.Format = { 119 RGBA8888: 0, 120 RGBA4444: 1 121 }; 122 123 /** 124 * Extensions. 125 * @enum {number} 126 */ 127 createjs.Renderer.Extension = { 128 VIDEO: 1 << 0 129 }; 130 131 /** 132 * Returns the composition ID associated with the specified name. 133 * @param {string} name 134 * @return {number} 135 */ 136 createjs.Renderer.getCompositionKey = function(name) { 137 var KEYS = { 138 'source-over': createjs.Renderer.Composition.SOURCE_OVER, 139 'source-atop': createjs.Renderer.Composition.SOURCE_ATOP, 140 'source-in': createjs.Renderer.Composition.SOURCE_IN, 141 'source-out': createjs.Renderer.Composition.SOURCE_OUT, 142 'destination-over': createjs.Renderer.Composition.DESTINATION_OVER, 143 'destination-atop': createjs.Renderer.Composition.DESTINATION_ATOP, 144 'destination-in': createjs.Renderer.Composition.DESTINATION_IN, 145 'destination-out': createjs.Renderer.Composition.DESTINATION_OUT, 146 'lighter': createjs.Renderer.Composition.LIGHTER, 147 'copy': createjs.Renderer.Composition.COPY, 148 'xor': createjs.Renderer.Composition.XOR, 149 'darker': createjs.Renderer.Composition.DARKER 150 }; 151 return KEYS[name] || createjs.Renderer.Composition.SOURCE_OVER; 152 }; 153 154 /** 155 * Returns the composition name from the specified ID. 156 * @param {number} key 157 * @return {string} 158 */ 159 createjs.Renderer.getCompositionName = function(key) { 160 var NAMES = [ 161 'source-over', 162 'source-atop', 163 'source-in', 164 'source-out', 165 'destination-over', 166 'destination-atop', 167 'destination-in', 168 'destination-out', 169 'lighter', 170 'copy', 171 'xor', 172 'darker', 173 'multiply' 174 ]; 175 return NAMES[key]; 176 }; 177 178 /** 179 * An inner class used by createjs.Renderer objects to clip RenderObject 180 * objects. 181 * @param {createjs.Transform} transform 182 * @param {createjs.BoundingBox} rectangle 183 * @param {createjs.BoundingBox} box 184 * @param {number} method 185 * @param {number} composition 186 * @param {createjs.Renderer.RenderObject} shape 187 * @constructor 188 */ 189 createjs.Renderer.Clip = 190 function(transform, rectangle, box, method, composition, shape) { 191 /// <param type="createjs.Transform" name="transform"/> 192 /// <param type="createjs.BoundingBox" name="rectangle"/> 193 /// <param type="createjs.BoundingBox" name="box"/> 194 /// <param type="number" name="method"/> 195 /// <param type="number" name="composition"/> 196 /// <param type="createjs.Renderer.RenderObject" name="shape"/> 197 /** 198 * An affine transformation applied to a clipping rectangle. 199 * @const {createjs.Transform} 200 * @private 201 */ 202 this.transform_ = transform; 203 204 /** 205 * A clipping rectangle in the local coordinate. 206 * @const {createjs.Rectangle} 207 * @private 208 */ 209 this.rectangle_ = new createjs.Rectangle(rectangle.getLeft(), 210 rectangle.getTop(), 211 rectangle.getWidth(), 212 rectangle.getHeight()); 213 214 /** 215 * A clipping rectangle in the global coordinate. 216 * @const {createjs.BoundingBox} 217 * @private 218 */ 219 this.box_ = createjs.Renderer.Clip.cloneBox(box); 220 221 /** 222 * A method used for applying this clip to a render object. 223 * rectangle. 224 * @const {number} 225 * @private 226 */ 227 this.method_ = method; 228 229 /** 230 * A composition operation used in rendering the clipped image. 231 * @const {number} 232 * @private 233 */ 234 this.composition_ = composition; 235 236 /** 237 * A render object that renders this clip. 238 * @const {createjs.Renderer.RenderObject} 239 * @private 240 */ 241 this.shape_ = 242 (method > createjs.Renderer.Mask.SCISSOR) ? shape : null; 243 }; 244 245 /** 246 * Returns a clone of the specified box. 247 * @param {createjs.BoundingBox} box 248 * @return {createjs.BoundingBox} 249 */ 250 createjs.Renderer.Clip.cloneBox = function(box) { 251 /// <param type="createjs.BoundingBox" name="box"/> 252 /// <returns type="createjs.BoundingBox"/> 253 var clone = new createjs.BoundingBox(); 254 clone.minX = createjs.truncate(box.minX) + 1; 255 clone.minY = createjs.truncate(box.minY); 256 clone.maxX = createjs.truncate(box.maxX); 257 clone.maxY = createjs.truncate(box.maxY); 258 return clone; 259 }; 260 261 /** 262 * Returns the affine transformation. 263 * @return {createjs.Transform} 264 * @const 265 */ 266 createjs.Renderer.Clip.prototype.getTransform = function() { 267 /// <returns type="createjs.Transform"/> 268 return this.transform_; 269 }; 270 271 /** 272 * Returns the clipping rectangle. 273 * @return {createjs.Rectangle} 274 * @const 275 */ 276 createjs.Renderer.Clip.prototype.getRectangle = function() { 277 /// <returns type="createjs.Rectangle"/> 278 return this.rectangle_; 279 }; 280 281 /** 282 * Returns the bounding box. 283 * @return {createjs.BoundingBox} 284 * @const 285 */ 286 createjs.Renderer.Clip.prototype.getBox = function() { 287 /// <returns type="createjs.BoundingBox"/> 288 return this.box_; 289 }; 290 291 /** 292 * Returns the clipping method. 293 * @return {number} 294 * @const 295 */ 296 createjs.Renderer.Clip.prototype.getMethod = function() { 297 /// <returns type="number"/> 298 // Disable this clip when it is invisible to avoid a crash in rendering an 299 // invisible shape. (A tween may set an empty shape to this mask.) 300 if (this.shape_ && !this.shape_.isVisible()) { 301 return 0; 302 } 303 return this.method_; 304 }; 305 306 /** 307 * Returns whether a renderer has to compose this clip to a render object. 308 * @return {boolean} 309 * @const 310 */ 311 createjs.Renderer.Clip.prototype.isCompose = function() { 312 /// <returns type="boolean"/> 313 return this.method_ == createjs.Renderer.Mask.COMPOSE; 314 }; 315 316 /** 317 * Returns whether a renderer should show a render object without applying this 318 * clip. 319 * @return {boolean} 320 * @const 321 */ 322 createjs.Renderer.Clip.prototype.isShow = function() { 323 /// <returns type="boolean"/> 324 return this.method_ == createjs.Renderer.Mask.SHOW; 325 }; 326 327 /** 328 * Returns whether this clip can use its bounding box as a scissor box. 329 * @return {number} 330 * @const 331 */ 332 createjs.Renderer.Clip.prototype.getComposition = function() { 333 /// <returns type="number"/> 334 return this.composition_; 335 }; 336 337 /** 338 * Returns a display object used as a mask. 339 * @return {createjs.Renderer.RenderObject} 340 * @const 341 */ 342 createjs.Renderer.Clip.prototype.getShape = function() { 343 /// <returns type="createjs.Renderer.RenderObject"/> 344 return this.shape_; 345 }; 346 347 /** 348 * An interface used by a renderer object to draw objects registered with the 349 * paintObject() method. 350 * @interface 351 */ 352 createjs.Renderer.RenderObject = function() {}; 353 354 /** 355 * Returns whether this object needs a redraw. 356 * @param {createjs.BoundingBox} box 357 * @return {boolean} 358 */ 359 createjs.Renderer.RenderObject.prototype.isDirtyObject = function(box) { 360 /// <returns type="createjs.BoundingBox"/> 361 }; 362 363 /** 364 * Returns the bounding box of this object in the global coordinate system. 365 * @return {createjs.BoundingBox} 366 */ 367 createjs.Renderer.RenderObject.prototype.getRenderBox = function() { 368 /// <returns type="createjs.BoundingBox"/> 369 }; 370 371 /** 372 * Returns a createjs.Renderer.Clip object associated with this object. 373 * @return {createjs.Renderer.Clip} 374 */ 375 createjs.Renderer.RenderObject.prototype.getClip = function() { 376 /// <returns type="createjs.Renderer.Clip"/> 377 }; 378 379 /** 380 * Starts painting this object. 381 * @param {createjs.Renderer} renderer 382 */ 383 createjs.Renderer.RenderObject.prototype.beginPaintObject = 384 function(renderer) { 385 /// <param type="createjs.Renderer" name="renderer"/> 386 }; 387 388 /** 389 * Paints an object. 390 * @param {createjs.Renderer} renderer 391 */ 392 createjs.Renderer.RenderObject.prototype.paintObject = function(renderer) { 393 /// <param type="createjs.Renderer" name="renderer"/> 394 }; 395 396 /** 397 * Calculates the ratio of a point in this renderer to one of CSS. When this 398 * renderer has its <canvas> element applied CSS transforms, this ratio does not 399 * become (1, 1) to (1, 1). This method retrieves the computed rectangle from a 400 * browser and calculates it. 401 * @private 402 */ 403 createjs.Renderer.prototype.calculateRatio_ = function() { 404 var canvas = this.getCanvas(); 405 var bounds = canvas.getBoundingClientRect(); 406 var zoom = window.getComputedStyle(canvas).zoom; 407 this.cssRatio_ = new createjs.Point( 408 bounds.width * zoom / this.width_, bounds.height * zoom / this.height_); 409 }; 410 411 /** 412 * Synchronizes the width property of this renderer with the specified one. 413 * @param {number} width 414 * @protected 415 * @const 416 */ 417 createjs.Renderer.prototype.setWidth = function(width) { 418 /// <param type="number" name="width"/> 419 this.width_ = width; 420 }; 421 422 /** 423 * Synchronizes the height properties of this renderer with the specified one. 424 * @param {number} height 425 * @protected 426 * @const 427 */ 428 createjs.Renderer.prototype.setHeight = function(height) { 429 /// <param type="number" name="height"/> 430 this.height_ = height; 431 }; 432 433 /** 434 * Resets the HTMLCanvasElement object attached to this renderer. 435 * @protected 436 * @const 437 */ 438 createjs.Renderer.prototype.resetCanvas = function() { 439 if (this.canvas_) { 440 this.canvas_.width = 0; 441 this.canvas_ = null; 442 } 443 }; 444 445 /** 446 * Updates the layout of the HTMLCanvasElement object attached to this renderer. 447 * @param {string} context 448 * @suppress {uselessCode} 449 * @protected 450 * @const 451 */ 452 createjs.Renderer.prototype.updateCanvas = function(context) { 453 /// <param type="string" name="context"/> 454 if (this.useAndroidWorkarounds_ < 0) { 455 this.useAndroidWorkarounds_ = 456 createjs.Config.useAndroidWorkarounds(context); 457 } 458 var canvas = this.getCanvas(); 459 if (this.useAndroidWorkarounds_ == 1) { 460 var display = canvas.style.display; 461 if (display != 'none') { 462 canvas.style.display = 'none'; 463 canvas.offsetHeight; 464 canvas.style.display = display; 465 } 466 } else if (this.useAndroidWorkarounds_) { 467 canvas.width = canvas.width; 468 } 469 }; 470 471 /** 472 * Destroys the resources attached to this renderer. 473 */ 474 createjs.Renderer.prototype.destroy = function() { 475 createjs.notReached(); 476 }; 477 478 /** 479 * Returns the HTMLCanvasElement object attached to this renderer. 480 * @return {HTMLCanvasElement} 481 * @const 482 */ 483 createjs.Renderer.prototype.getCanvas = function() { 484 /// <returns type="HTMLCanvasElement"/> 485 return this.canvas_; 486 }; 487 488 /** 489 * Returns the width. 490 * @return {number} 491 * @const 492 */ 493 createjs.Renderer.prototype.getWidth = function() { 494 /// <returns type="number"/> 495 return this.width_; 496 }; 497 498 /** 499 * Returns the height. 500 * @return {number} 501 * @const 502 */ 503 createjs.Renderer.prototype.getHeight = function() { 504 /// <returns type="number"/> 505 return this.height_; 506 }; 507 508 /** 509 * Returns the ratio of a point in this renderer to one of CSS. 510 * @return {createjs.Point} 511 * @const 512 */ 513 createjs.Renderer.prototype.getCSSRatio = function() { 514 /// <returns type="createjs.Point"/> 515 if (!this.cssRatio_) { 516 this.calculateRatio_(); 517 } 518 return this.cssRatio_; 519 }; 520 521 /** 522 * Sets an affine transformation. 523 * @param {number} a 524 * @param {number} b 525 * @param {number} c 526 * @param {number} d 527 * @param {number} tx 528 * @param {number} ty 529 */ 530 createjs.Renderer.prototype.setTransformation = function(a, b, c, d, tx, ty) { 531 /// <param type="number" name="a"/> 532 /// <param type="number" name="b"/> 533 /// <param type="number" name="c"/> 534 /// <param type="number" name="d"/> 535 /// <param type="number" name="tx"/> 536 /// <param type="number" name="ty"/> 537 createjs.notReached(); 538 }; 539 540 /** 541 * Sets the alpha value. 542 * @param {number} alpha 543 */ 544 createjs.Renderer.prototype.setAlpha = function(alpha) { 545 /// <param type="number" name="alpha"/> 546 createjs.notReached(); 547 }; 548 549 /** 550 * Sets the color matrix. 551 * @param {Array.<number>} matrix 552 */ 553 createjs.Renderer.prototype.setColorMatrix = function(matrix) { 554 /// <param type="Array" elementType="number" name="matrix"/> 555 }; 556 557 /** 558 * Sets the color-composition operation. 559 * @param {number} operation 560 */ 561 createjs.Renderer.prototype.setComposition = function(operation) { 562 /// <param type="number" name="operation"/> 563 createjs.notReached(); 564 }; 565 566 /** 567 * Draws an HTMLCanvasElement object to the specified rectangle. 568 * @param {HTMLCanvasElement} canvas 569 * @param {number} x 570 * @param {number} y 571 * @param {number} width 572 * @param {number} height 573 */ 574 createjs.Renderer.prototype.drawCanvas = function(canvas, x, y, width, height) { 575 /// <param type="HTMLCanvasElement" name="canvas"/> 576 /// <param type="number" name="x"/> 577 /// <param type="number" name="y"/> 578 /// <param type="number" name="width"/> 579 /// <param type="number" name="height"/> 580 createjs.notReached(); 581 }; 582 583 /** 584 * Returns a bit-mask representing the extensions supported by this renderer. 585 * @return {number} 586 */ 587 createjs.Renderer.prototype.getExtensions = function() { 588 /// <returns type="number"/> 589 return createjs.Renderer.Extension.VIDEO; 590 }; 591 592 /** 593 * Draws an HTMLVideoElement object to the specified rectangle. 594 * @param {HTMLVideoElement} video 595 * @param {number} x 596 * @param {number} y 597 * @param {number} width 598 * @param {number} height 599 */ 600 createjs.Renderer.prototype.drawVideo = function(video, x, y, width, height) { 601 /// <param type="HTMLVideoElement" name="video"/> 602 /// <param type="number" name="x"/> 603 /// <param type="number" name="y"/> 604 /// <param type="number" name="width"/> 605 /// <param type="number" name="height"/> 606 createjs.notReached(); 607 }; 608 609 /** 610 * Draws a part of an HTMLImageElement object to the specified rectangle. 611 * @param {HTMLImageElement} image 612 * @param {number} srcX 613 * @param {number} srcY 614 * @param {number} srcWidth 615 * @param {number} srcHeight 616 * @param {number} x 617 * @param {number} y 618 * @param {number} width 619 * @param {number} height 620 */ 621 createjs.Renderer.prototype.drawPartial = 622 function(image, srcX, srcY, srcWidth, srcHeight, x, y, width, height) { 623 /// <param type="HTMLImageElement" name="image"/> 624 /// <param type="number" name="srcX"/> 625 /// <param type="number" name="srcY"/> 626 /// <param type="number" name="srcWidth"/> 627 /// <param type="number" name="srcHeight"/> 628 /// <param type="number" name="x"/> 629 /// <param type="number" name="y"/> 630 /// <param type="number" name="width"/> 631 /// <param type="number" name="height"/> 632 createjs.notReached(); 633 }; 634 635 /** 636 * Adds an object to the rendering queue. 637 * @param {createjs.Renderer.RenderObject} object 638 */ 639 createjs.Renderer.prototype.addObject = function(object) { 640 /// <param type="createjs.Renderer.RenderObject" name="object"/> 641 // This method is used for calculating clipping rectangles, i.e. this method 642 // should not call createjs.notReached(). 643 }; 644 645 /** 646 * Deletes the cache for the specified image. 647 * @param {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} image 648 */ 649 createjs.Renderer.prototype.uncache = function(image) { 650 /// <signature> 651 /// <param type="HTMLImageElement" name="image"/> 652 /// </signature> 653 /// <signature> 654 /// <param type="HTMLCanvasElement" name="canvas"/> 655 /// </signature> 656 /// <signature> 657 /// <param type="HTMLVideoElement" name="video"/> 658 /// </signature> 659 }; 660 661 /** 662 * Starts paints objects. 663 */ 664 createjs.Renderer.prototype.begin = function() { 665 }; 666 667 /** 668 * Paints objects added to this renderer. This method returns true if this 669 * renderer actually draws objects. 670 * @param {number} time 671 */ 672 createjs.Renderer.prototype.paint = function(time) { 673 /// <param type="number" name="time"/> 674 createjs.notReached(); 675 }; 676 677 if (createjs.DEBUG) { 678 /** 679 * Adds a dirty object to another renderer. 680 * @param {createjs.Renderer.RenderObject} object 681 */ 682 createjs.Renderer.prototype.addDirtyObject = function(object) { 683 /// <param type="createjs.Renderer.RenderObject" name="object"/> 684 }; 685 } 686