[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 // Memory Leaks patch from http://explorercanvas.googlecode.com/svn/trunk/ 2 // svn : r73 3 // ------------------------------------------------------------------ 4 // Copyright 2006 Google Inc. 5 // 6 // Licensed under the Apache License, Version 2.0 (the "License"); 7 // you may not use this file except in compliance with the License. 8 // You may obtain a copy of the License at 9 // 10 // http://www.apache.org/licenses/LICENSE-2.0 11 // 12 // Unless required by applicable law or agreed to in writing, software 13 // distributed under the License is distributed on an "AS IS" BASIS, 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 18 19 // Known Issues: 20 // 21 // * Patterns only support repeat. 22 // * Radial gradient are not implemented. The VML version of these look very 23 // different from the canvas one. 24 // * Clipping paths are not implemented. 25 // * Coordsize. The width and height attribute have higher priority than the 26 // width and height style values which isn't correct. 27 // * Painting mode isn't implemented. 28 // * Canvas width/height should is using content-box by default. IE in 29 // Quirks mode will draw the canvas using border-box. Either change your 30 // doctype to HTML5 31 // (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype) 32 // or use Box Sizing Behavior from WebFX 33 // (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html) 34 // * Non uniform scaling does not correctly scale strokes. 35 // * Optimize. There is always room for speed improvements. 36 37 // Only add this code if we do not already have a canvas implementation 38 if (!document.createElement('canvas').getContext) { 39 40 (function() { 41 42 // alias some functions to make (compiled) code shorter 43 var m = Math; 44 var mr = m.round; 45 var ms = m.sin; 46 var mc = m.cos; 47 var abs = m.abs; 48 var sqrt = m.sqrt; 49 50 // this is used for sub pixel precision 51 var Z = 10; 52 var Z2 = Z / 2; 53 54 var IE_VERSION = +navigator.userAgent.match(/MSIE ([\d.]+)?/)[1]; 55 56 /** 57 * This funtion is assigned to the <canvas> elements as element.getContext(). 58 * @this {HTMLElement} 59 * @return {CanvasRenderingContext2D_} 60 */ 61 function getContext() { 62 return this.context_ || 63 (this.context_ = new CanvasRenderingContext2D_(this)); 64 } 65 66 var slice = Array.prototype.slice; 67 68 /** 69 * Binds a function to an object. The returned function will always use the 70 * passed in {@code obj} as {@code this}. 71 * 72 * Example: 73 * 74 * g = bind(f, obj, a, b) 75 * g(c, d) // will do f.call(obj, a, b, c, d) 76 * 77 * @param {Function} f The function to bind the object to 78 * @param {Object} obj The object that should act as this when the function 79 * is called 80 * @param {*} var_args Rest arguments that will be used as the initial 81 * arguments when the function is called 82 * @return {Function} A new function that has bound this 83 */ 84 function bind(f, obj, var_args) { 85 var a = slice.call(arguments, 2); 86 return function() { 87 return f.apply(obj, a.concat(slice.call(arguments))); 88 }; 89 } 90 91 function encodeHtmlAttribute(s) { 92 return String(s).replace(/&/g, '&').replace(/"/g, '"'); 93 } 94 95 function addNamespace(doc, prefix, urn) { 96 if (!doc.namespaces[prefix]) { 97 doc.namespaces.add(prefix, urn, '#default#VML'); 98 } 99 } 100 101 function addNamespacesAndStylesheet(doc) { 102 addNamespace(doc, 'g_vml_', 'urn:schemas-microsoft-com:vml'); 103 addNamespace(doc, 'g_o_', 'urn:schemas-microsoft-com:office:office'); 104 105 // Setup default CSS. Only add one style sheet per document 106 if (!doc.styleSheets['ex_canvas_']) { 107 var ss = doc.createStyleSheet(); 108 ss.owningElement.id = 'ex_canvas_'; 109 ss.cssText = 'canvas{display:inline-block;overflow:hidden;' + 110 // default size is 300x150 in Gecko and Opera 111 'text-align:left;width:300px;height:150px}'; 112 } 113 } 114 115 // Add namespaces and stylesheet at startup. 116 addNamespacesAndStylesheet(document); 117 118 var G_vmlCanvasManager_ = { 119 init: function(opt_doc) { 120 var doc = opt_doc || document; 121 // Create a dummy element so that IE will allow canvas elements to be 122 // recognized. 123 doc.createElement('canvas'); 124 doc.attachEvent('onreadystatechange', bind(this.init_, this, doc)); 125 }, 126 127 init_: function(doc) { 128 // find all canvas elements 129 var els = doc.getElementsByTagName('canvas'); 130 for (var i = 0; i < els.length; i++) { 131 this.initElement(els[i]); 132 } 133 }, 134 135 /** 136 * Public initializes a canvas element so that it can be used as canvas 137 * element from now on. This is called automatically before the page is 138 * loaded but if you are creating elements using createElement you need to 139 * make sure this is called on the element. 140 * @param {HTMLElement} el The canvas element to initialize. 141 * @return {HTMLElement} the element that was created. 142 */ 143 initElement: function(el) { 144 if (!el.getContext) { 145 el.getContext = getContext; 146 147 // Add namespaces and stylesheet to document of the element. 148 addNamespacesAndStylesheet(el.ownerDocument); 149 150 // Remove fallback content. There is no way to hide text nodes so we 151 // just remove all childNodes. We could hide all elements and remove 152 // text nodes but who really cares about the fallback content. 153 el.innerHTML = ''; 154 155 // do not use inline function because that will leak memory 156 el.attachEvent('onpropertychange', onPropertyChange); 157 el.attachEvent('onresize', onResize); 158 159 var attrs = el.attributes; 160 if (attrs.width && attrs.width.specified) { 161 // TODO: use runtimeStyle and coordsize 162 // el.getContext().setWidth_(attrs.width.nodeValue); 163 el.style.width = attrs.width.nodeValue + 'px'; 164 } else { 165 el.width = el.clientWidth; 166 } 167 if (attrs.height && attrs.height.specified) { 168 // TODO: use runtimeStyle and coordsize 169 // el.getContext().setHeight_(attrs.height.nodeValue); 170 el.style.height = attrs.height.nodeValue + 'px'; 171 } else { 172 el.height = el.clientHeight; 173 } 174 //el.getContext().setCoordsize_() 175 } 176 return el; 177 }, 178 179 // Memory Leaks patch : see http://code.google.com/p/explorercanvas/issues/detail?id=82 180 uninitElement: function(el){ 181 if (el.getContext) { 182 var ctx = el.getContext(); 183 delete ctx.element_; 184 delete ctx.canvas; 185 el.innerHTML = ""; 186 //el.outerHTML = ""; 187 el.context_ = null; 188 el.getContext = null; 189 el.detachEvent("onpropertychange", onPropertyChange); 190 el.detachEvent("onresize", onResize); 191 } 192 } 193 }; 194 195 function onPropertyChange(e) { 196 var el = e.srcElement; 197 198 switch (e.propertyName) { 199 case 'width': 200 el.getContext().clearRect(); 201 el.style.width = el.attributes.width.nodeValue + 'px'; 202 // In IE8 this does not trigger onresize. 203 el.firstChild.style.width = el.clientWidth + 'px'; 204 break; 205 case 'height': 206 el.getContext().clearRect(); 207 el.style.height = el.attributes.height.nodeValue + 'px'; 208 el.firstChild.style.height = el.clientHeight + 'px'; 209 break; 210 } 211 } 212 213 function onResize(e) { 214 var el = e.srcElement; 215 if (el.firstChild) { 216 el.firstChild.style.width = el.clientWidth + 'px'; 217 el.firstChild.style.height = el.clientHeight + 'px'; 218 } 219 } 220 221 G_vmlCanvasManager_.init(); 222 223 // precompute "00" to "FF" 224 var decToHex = []; 225 for (var i = 0; i < 16; i++) { 226 for (var j = 0; j < 16; j++) { 227 decToHex[i * 16 + j] = i.toString(16) + j.toString(16); 228 } 229 } 230 231 function createMatrixIdentity() { 232 return [ 233 [1, 0, 0], 234 [0, 1, 0], 235 [0, 0, 1] 236 ]; 237 } 238 239 function matrixMultiply(m1, m2) { 240 var result = createMatrixIdentity(); 241 242 for (var x = 0; x < 3; x++) { 243 for (var y = 0; y < 3; y++) { 244 var sum = 0; 245 246 for (var z = 0; z < 3; z++) { 247 sum += m1[x][z] * m2[z][y]; 248 } 249 250 result[x][y] = sum; 251 } 252 } 253 return result; 254 } 255 256 function copyState(o1, o2) { 257 o2.fillStyle = o1.fillStyle; 258 o2.lineCap = o1.lineCap; 259 o2.lineJoin = o1.lineJoin; 260 o2.lineWidth = o1.lineWidth; 261 o2.miterLimit = o1.miterLimit; 262 o2.shadowBlur = o1.shadowBlur; 263 o2.shadowColor = o1.shadowColor; 264 o2.shadowOffsetX = o1.shadowOffsetX; 265 o2.shadowOffsetY = o1.shadowOffsetY; 266 o2.strokeStyle = o1.strokeStyle; 267 o2.globalAlpha = o1.globalAlpha; 268 o2.font = o1.font; 269 o2.textAlign = o1.textAlign; 270 o2.textBaseline = o1.textBaseline; 271 o2.arcScaleX_ = o1.arcScaleX_; 272 o2.arcScaleY_ = o1.arcScaleY_; 273 o2.lineScale_ = o1.lineScale_; 274 } 275 276 var colorData = { 277 aliceblue: '#F0F8FF', 278 antiquewhite: '#FAEBD7', 279 aquamarine: '#7FFFD4', 280 azure: '#F0FFFF', 281 beige: '#F5F5DC', 282 bisque: '#FFE4C4', 283 black: '#000000', 284 blanchedalmond: '#FFEBCD', 285 blueviolet: '#8A2BE2', 286 brown: '#A52A2A', 287 burlywood: '#DEB887', 288 cadetblue: '#5F9EA0', 289 chartreuse: '#7FFF00', 290 chocolate: '#D2691E', 291 coral: '#FF7F50', 292 cornflowerblue: '#6495ED', 293 cornsilk: '#FFF8DC', 294 crimson: '#DC143C', 295 cyan: '#00FFFF', 296 darkblue: '#00008B', 297 darkcyan: '#008B8B', 298 darkgoldenrod: '#B8860B', 299 darkgray: '#A9A9A9', 300 darkgreen: '#006400', 301 darkgrey: '#A9A9A9', 302 darkkhaki: '#BDB76B', 303 darkmagenta: '#8B008B', 304 darkolivegreen: '#556B2F', 305 darkorange: '#FF8C00', 306 darkorchid: '#9932CC', 307 darkred: '#8B0000', 308 darksalmon: '#E9967A', 309 darkseagreen: '#8FBC8F', 310 darkslateblue: '#483D8B', 311 darkslategray: '#2F4F4F', 312 darkslategrey: '#2F4F4F', 313 darkturquoise: '#00CED1', 314 darkviolet: '#9400D3', 315 deeppink: '#FF1493', 316 deepskyblue: '#00BFFF', 317 dimgray: '#696969', 318 dimgrey: '#696969', 319 dodgerblue: '#1E90FF', 320 firebrick: '#B22222', 321 floralwhite: '#FFFAF0', 322 forestgreen: '#228B22', 323 gainsboro: '#DCDCDC', 324 ghostwhite: '#F8F8FF', 325 gold: '#FFD700', 326 goldenrod: '#DAA520', 327 grey: '#808080', 328 greenyellow: '#ADFF2F', 329 honeydew: '#F0FFF0', 330 hotpink: '#FF69B4', 331 indianred: '#CD5C5C', 332 indigo: '#4B0082', 333 ivory: '#FFFFF0', 334 khaki: '#F0E68C', 335 lavender: '#E6E6FA', 336 lavenderblush: '#FFF0F5', 337 lawngreen: '#7CFC00', 338 lemonchiffon: '#FFFACD', 339 lightblue: '#ADD8E6', 340 lightcoral: '#F08080', 341 lightcyan: '#E0FFFF', 342 lightgoldenrodyellow: '#FAFAD2', 343 lightgreen: '#90EE90', 344 lightgrey: '#D3D3D3', 345 lightpink: '#FFB6C1', 346 lightsalmon: '#FFA07A', 347 lightseagreen: '#20B2AA', 348 lightskyblue: '#87CEFA', 349 lightslategray: '#778899', 350 lightslategrey: '#778899', 351 lightsteelblue: '#B0C4DE', 352 lightyellow: '#FFFFE0', 353 limegreen: '#32CD32', 354 linen: '#FAF0E6', 355 magenta: '#FF00FF', 356 mediumaquamarine: '#66CDAA', 357 mediumblue: '#0000CD', 358 mediumorchid: '#BA55D3', 359 mediumpurple: '#9370DB', 360 mediumseagreen: '#3CB371', 361 mediumslateblue: '#7B68EE', 362 mediumspringgreen: '#00FA9A', 363 mediumturquoise: '#48D1CC', 364 mediumvioletred: '#C71585', 365 midnightblue: '#191970', 366 mintcream: '#F5FFFA', 367 mistyrose: '#FFE4E1', 368 moccasin: '#FFE4B5', 369 navajowhite: '#FFDEAD', 370 oldlace: '#FDF5E6', 371 olivedrab: '#6B8E23', 372 orange: '#FFA500', 373 orangered: '#FF4500', 374 orchid: '#DA70D6', 375 palegoldenrod: '#EEE8AA', 376 palegreen: '#98FB98', 377 paleturquoise: '#AFEEEE', 378 palevioletred: '#DB7093', 379 papayawhip: '#FFEFD5', 380 peachpuff: '#FFDAB9', 381 peru: '#CD853F', 382 pink: '#FFC0CB', 383 plum: '#DDA0DD', 384 powderblue: '#B0E0E6', 385 rosybrown: '#BC8F8F', 386 royalblue: '#4169E1', 387 saddlebrown: '#8B4513', 388 salmon: '#FA8072', 389 sandybrown: '#F4A460', 390 seagreen: '#2E8B57', 391 seashell: '#FFF5EE', 392 sienna: '#A0522D', 393 skyblue: '#87CEEB', 394 slateblue: '#6A5ACD', 395 slategray: '#708090', 396 slategrey: '#708090', 397 snow: '#FFFAFA', 398 springgreen: '#00FF7F', 399 steelblue: '#4682B4', 400 tan: '#D2B48C', 401 thistle: '#D8BFD8', 402 tomato: '#FF6347', 403 turquoise: '#40E0D0', 404 violet: '#EE82EE', 405 wheat: '#F5DEB3', 406 whitesmoke: '#F5F5F5', 407 yellowgreen: '#9ACD32' 408 }; 409 410 411 function getRgbHslContent(styleString) { 412 var start = styleString.indexOf('(', 3); 413 var end = styleString.indexOf(')', start + 1); 414 var parts = styleString.substring(start + 1, end).split(','); 415 // add alpha if needed 416 if (parts.length != 4 || styleString.charAt(3) != 'a') { 417 parts[3] = 1; 418 } 419 return parts; 420 } 421 422 function percent(s) { 423 return parseFloat(s) / 100; 424 } 425 426 function clamp(v, min, max) { 427 return Math.min(max, Math.max(min, v)); 428 } 429 430 function hslToRgb(parts){ 431 var r, g, b, h, s, l; 432 h = parseFloat(parts[0]) / 360 % 360; 433 if (h < 0) 434 h++; 435 s = clamp(percent(parts[1]), 0, 1); 436 l = clamp(percent(parts[2]), 0, 1); 437 if (s == 0) { 438 r = g = b = l; // achromatic 439 } else { 440 var q = l < 0.5 ? l * (1 + s) : l + s - l * s; 441 var p = 2 * l - q; 442 r = hueToRgb(p, q, h + 1 / 3); 443 g = hueToRgb(p, q, h); 444 b = hueToRgb(p, q, h - 1 / 3); 445 } 446 447 return '#' + decToHex[Math.floor(r * 255)] + 448 decToHex[Math.floor(g * 255)] + 449 decToHex[Math.floor(b * 255)]; 450 } 451 452 function hueToRgb(m1, m2, h) { 453 if (h < 0) 454 h++; 455 if (h > 1) 456 h--; 457 458 if (6 * h < 1) 459 return m1 + (m2 - m1) * 6 * h; 460 else if (2 * h < 1) 461 return m2; 462 else if (3 * h < 2) 463 return m1 + (m2 - m1) * (2 / 3 - h) * 6; 464 else 465 return m1; 466 } 467 468 var processStyleCache = {}; 469 470 function processStyle(styleString) { 471 if (styleString in processStyleCache) { 472 return processStyleCache[styleString]; 473 } 474 475 var str, alpha = 1; 476 477 styleString = String(styleString); 478 if (styleString.charAt(0) == '#') { 479 str = styleString; 480 } else if (/^rgb/.test(styleString)) { 481 var parts = getRgbHslContent(styleString); 482 var str = '#', n; 483 for (var i = 0; i < 3; i++) { 484 if (parts[i].indexOf('%') != -1) { 485 n = Math.floor(percent(parts[i]) * 255); 486 } else { 487 n = +parts[i]; 488 } 489 str += decToHex[clamp(n, 0, 255)]; 490 } 491 alpha = +parts[3]; 492 } else if (/^hsl/.test(styleString)) { 493 var parts = getRgbHslContent(styleString); 494 str = hslToRgb(parts); 495 alpha = parts[3]; 496 } else { 497 str = colorData[styleString] || styleString; 498 } 499 return processStyleCache[styleString] = {color: str, alpha: alpha}; 500 } 501 502 var DEFAULT_STYLE = { 503 style: 'normal', 504 variant: 'normal', 505 weight: 'normal', 506 size: 10, 507 family: 'sans-serif' 508 }; 509 510 // Internal text style cache 511 var fontStyleCache = {}; 512 513 function processFontStyle(styleString) { 514 if (fontStyleCache[styleString]) { 515 return fontStyleCache[styleString]; 516 } 517 518 var el = document.createElement('div'); 519 var style = el.style; 520 try { 521 style.font = styleString; 522 } catch (ex) { 523 // Ignore failures to set to invalid font. 524 } 525 526 return fontStyleCache[styleString] = { 527 style: style.fontStyle || DEFAULT_STYLE.style, 528 variant: style.fontVariant || DEFAULT_STYLE.variant, 529 weight: style.fontWeight || DEFAULT_STYLE.weight, 530 size: style.fontSize || DEFAULT_STYLE.size, 531 family: style.fontFamily || DEFAULT_STYLE.family 532 }; 533 } 534 535 function getComputedStyle(style, element) { 536 var computedStyle = {}; 537 538 for (var p in style) { 539 computedStyle[p] = style[p]; 540 } 541 542 // Compute the size 543 var canvasFontSize = parseFloat(element.currentStyle.fontSize), 544 fontSize = parseFloat(style.size); 545 546 if (typeof style.size == 'number') { 547 computedStyle.size = style.size; 548 } else if (style.size.indexOf('px') != -1) { 549 computedStyle.size = fontSize; 550 } else if (style.size.indexOf('em') != -1) { 551 computedStyle.size = canvasFontSize * fontSize; 552 } else if(style.size.indexOf('%') != -1) { 553 computedStyle.size = (canvasFontSize / 100) * fontSize; 554 } else if (style.size.indexOf('pt') != -1) { 555 computedStyle.size = fontSize / .75; 556 } else { 557 computedStyle.size = canvasFontSize; 558 } 559 560 // Different scaling between normal text and VML text. This was found using 561 // trial and error to get the same size as non VML text. 562 computedStyle.size *= 0.981; 563 564 // Fix for VML handling of bare font family names. Add a '' around font family names. 565 computedStyle.family = "'" + computedStyle.family.replace(/(\'|\")/g,'').replace(/\s*,\s*/g, "', '") + "'"; 566 567 return computedStyle; 568 } 569 570 function buildStyle(style) { 571 return style.style + ' ' + style.variant + ' ' + style.weight + ' ' + 572 style.size + 'px ' + style.family; 573 } 574 575 var lineCapMap = { 576 'butt': 'flat', 577 'round': 'round' 578 }; 579 580 function processLineCap(lineCap) { 581 return lineCapMap[lineCap] || 'square'; 582 } 583 584 /** 585 * This class implements CanvasRenderingContext2D interface as described by 586 * the WHATWG. 587 * @param {HTMLElement} canvasElement The element that the 2D context should 588 * be associated with 589 */ 590 function CanvasRenderingContext2D_(canvasElement) { 591 this.m_ = createMatrixIdentity(); 592 593 this.mStack_ = []; 594 this.aStack_ = []; 595 this.currentPath_ = []; 596 597 // Canvas context properties 598 this.strokeStyle = '#000'; 599 this.fillStyle = '#000'; 600 601 this.lineWidth = 1; 602 this.lineJoin = 'miter'; 603 this.lineCap = 'butt'; 604 this.miterLimit = Z * 1; 605 this.globalAlpha = 1; 606 this.font = '10px sans-serif'; 607 this.textAlign = 'left'; 608 this.textBaseline = 'alphabetic'; 609 this.canvas = canvasElement; 610 611 var cssText = 'width:' + canvasElement.clientWidth + 'px;height:' + 612 canvasElement.clientHeight + 'px;overflow:hidden;position:absolute'; 613 var el = canvasElement.ownerDocument.createElement('div'); 614 el.style.cssText = cssText; 615 canvasElement.appendChild(el); 616 617 var overlayEl = el.cloneNode(false); 618 // Use a non transparent background. 619 overlayEl.style.backgroundColor = 'red'; 620 overlayEl.style.filter = 'alpha(opacity=0)'; 621 canvasElement.appendChild(overlayEl); 622 623 this.element_ = el; 624 this.arcScaleX_ = 1; 625 this.arcScaleY_ = 1; 626 this.lineScale_ = 1; 627 } 628 629 var contextPrototype = CanvasRenderingContext2D_.prototype; 630 contextPrototype.clearRect = function() { 631 if (this.textMeasureEl_) { 632 this.textMeasureEl_.removeNode(true); 633 this.textMeasureEl_ = null; 634 } 635 this.element_.innerHTML = ''; 636 }; 637 638 contextPrototype.beginPath = function() { 639 // TODO: Branch current matrix so that save/restore has no effect 640 // as per safari docs. 641 this.currentPath_ = []; 642 }; 643 644 contextPrototype.moveTo = function(aX, aY) { 645 var p = getCoords(this, aX, aY); 646 this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y}); 647 this.currentX_ = p.x; 648 this.currentY_ = p.y; 649 }; 650 651 contextPrototype.lineTo = function(aX, aY) { 652 var p = getCoords(this, aX, aY); 653 this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y}); 654 655 this.currentX_ = p.x; 656 this.currentY_ = p.y; 657 }; 658 659 contextPrototype.bezierCurveTo = function(aCP1x, aCP1y, 660 aCP2x, aCP2y, 661 aX, aY) { 662 var p = getCoords(this, aX, aY); 663 var cp1 = getCoords(this, aCP1x, aCP1y); 664 var cp2 = getCoords(this, aCP2x, aCP2y); 665 bezierCurveTo(this, cp1, cp2, p); 666 }; 667 668 // Helper function that takes the already fixed cordinates. 669 function bezierCurveTo(self, cp1, cp2, p) { 670 self.currentPath_.push({ 671 type: 'bezierCurveTo', 672 cp1x: cp1.x, 673 cp1y: cp1.y, 674 cp2x: cp2.x, 675 cp2y: cp2.y, 676 x: p.x, 677 y: p.y 678 }); 679 self.currentX_ = p.x; 680 self.currentY_ = p.y; 681 } 682 683 contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) { 684 // the following is lifted almost directly from 685 // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes 686 687 var cp = getCoords(this, aCPx, aCPy); 688 var p = getCoords(this, aX, aY); 689 690 var cp1 = { 691 x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_), 692 y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_) 693 }; 694 var cp2 = { 695 x: cp1.x + (p.x - this.currentX_) / 3.0, 696 y: cp1.y + (p.y - this.currentY_) / 3.0 697 }; 698 699 bezierCurveTo(this, cp1, cp2, p); 700 }; 701 702 contextPrototype.arc = function(aX, aY, aRadius, 703 aStartAngle, aEndAngle, aClockwise) { 704 aRadius *= Z; 705 var arcType = aClockwise ? 'at' : 'wa'; 706 707 var xStart = aX + mc(aStartAngle) * aRadius - Z2; 708 var yStart = aY + ms(aStartAngle) * aRadius - Z2; 709 710 var xEnd = aX + mc(aEndAngle) * aRadius - Z2; 711 var yEnd = aY + ms(aEndAngle) * aRadius - Z2; 712 713 // IE won't render arches drawn counter clockwise if xStart == xEnd. 714 if (xStart == xEnd && !aClockwise) { 715 xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something 716 // that can be represented in binary 717 } 718 719 var p = getCoords(this, aX, aY); 720 var pStart = getCoords(this, xStart, yStart); 721 var pEnd = getCoords(this, xEnd, yEnd); 722 723 this.currentPath_.push({type: arcType, 724 x: p.x, 725 y: p.y, 726 radius: aRadius, 727 xStart: pStart.x, 728 yStart: pStart.y, 729 xEnd: pEnd.x, 730 yEnd: pEnd.y}); 731 732 }; 733 734 contextPrototype.rect = function(aX, aY, aWidth, aHeight) { 735 this.moveTo(aX, aY); 736 this.lineTo(aX + aWidth, aY); 737 this.lineTo(aX + aWidth, aY + aHeight); 738 this.lineTo(aX, aY + aHeight); 739 this.closePath(); 740 }; 741 742 contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) { 743 var oldPath = this.currentPath_; 744 this.beginPath(); 745 746 this.moveTo(aX, aY); 747 this.lineTo(aX + aWidth, aY); 748 this.lineTo(aX + aWidth, aY + aHeight); 749 this.lineTo(aX, aY + aHeight); 750 this.closePath(); 751 this.stroke(); 752 753 this.currentPath_ = oldPath; 754 }; 755 756 contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) { 757 var oldPath = this.currentPath_; 758 this.beginPath(); 759 760 this.moveTo(aX, aY); 761 this.lineTo(aX + aWidth, aY); 762 this.lineTo(aX + aWidth, aY + aHeight); 763 this.lineTo(aX, aY + aHeight); 764 this.closePath(); 765 this.fill(); 766 767 this.currentPath_ = oldPath; 768 }; 769 770 contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) { 771 var gradient = new CanvasGradient_('gradient'); 772 gradient.x0_ = aX0; 773 gradient.y0_ = aY0; 774 gradient.x1_ = aX1; 775 gradient.y1_ = aY1; 776 return gradient; 777 }; 778 779 contextPrototype.createRadialGradient = function(aX0, aY0, aR0, 780 aX1, aY1, aR1) { 781 var gradient = new CanvasGradient_('gradientradial'); 782 gradient.x0_ = aX0; 783 gradient.y0_ = aY0; 784 gradient.r0_ = aR0; 785 gradient.x1_ = aX1; 786 gradient.y1_ = aY1; 787 gradient.r1_ = aR1; 788 return gradient; 789 }; 790 791 contextPrototype.drawImage = function(image, var_args) { 792 var dx, dy, dw, dh, sx, sy, sw, sh; 793 794 // to find the original width we overide the width and height 795 var oldRuntimeWidth = image.runtimeStyle.width; 796 var oldRuntimeHeight = image.runtimeStyle.height; 797 image.runtimeStyle.width = 'auto'; 798 image.runtimeStyle.height = 'auto'; 799 800 // get the original size 801 var w = image.width; 802 var h = image.height; 803 804 // and remove overides 805 image.runtimeStyle.width = oldRuntimeWidth; 806 image.runtimeStyle.height = oldRuntimeHeight; 807 808 if (arguments.length == 3) { 809 dx = arguments[1]; 810 dy = arguments[2]; 811 sx = sy = 0; 812 sw = dw = w; 813 sh = dh = h; 814 } else if (arguments.length == 5) { 815 dx = arguments[1]; 816 dy = arguments[2]; 817 dw = arguments[3]; 818 dh = arguments[4]; 819 sx = sy = 0; 820 sw = w; 821 sh = h; 822 } else if (arguments.length == 9) { 823 sx = arguments[1]; 824 sy = arguments[2]; 825 sw = arguments[3]; 826 sh = arguments[4]; 827 dx = arguments[5]; 828 dy = arguments[6]; 829 dw = arguments[7]; 830 dh = arguments[8]; 831 } else { 832 throw Error('Invalid number of arguments'); 833 } 834 835 var d = getCoords(this, dx, dy); 836 837 var w2 = sw / 2; 838 var h2 = sh / 2; 839 840 var vmlStr = []; 841 842 var W = 10; 843 var H = 10; 844 845 // For some reason that I've now forgotten, using divs didn't work 846 vmlStr.push(' <g_vml_:group', 847 ' coordsize="', Z * W, ',', Z * H, '"', 848 ' coordorigin="0,0"' , 849 ' style="width:', W, 'px;height:', H, 'px;position:absolute;'); 850 851 // If filters are necessary (rotation exists), create them 852 // filters are bog-slow, so only create them if abbsolutely necessary 853 // The following check doesn't account for skews (which don't exist 854 // in the canvas spec (yet) anyway. 855 856 if (this.m_[0][0] != 1 || this.m_[0][1] || 857 this.m_[1][1] != 1 || this.m_[1][0]) { 858 var filter = []; 859 860 // Note the 12/21 reversal 861 filter.push('M11=', this.m_[0][0], ',', 862 'M12=', this.m_[1][0], ',', 863 'M21=', this.m_[0][1], ',', 864 'M22=', this.m_[1][1], ',', 865 'Dx=', mr(d.x / Z), ',', 866 'Dy=', mr(d.y / Z), ''); 867 868 // Bounding box calculation (need to minimize displayed area so that 869 // filters don't waste time on unused pixels. 870 var max = d; 871 var c2 = getCoords(this, dx + dw, dy); 872 var c3 = getCoords(this, dx, dy + dh); 873 var c4 = getCoords(this, dx + dw, dy + dh); 874 875 max.x = m.max(max.x, c2.x, c3.x, c4.x); 876 max.y = m.max(max.y, c2.y, c3.y, c4.y); 877 878 vmlStr.push('padding:0 ', mr(max.x / Z), 'px ', mr(max.y / Z), 879 'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(', 880 filter.join(''), ", sizingmethod='clip');"); 881 882 } else { 883 vmlStr.push('top:', mr(d.y / Z), 'px;left:', mr(d.x / Z), 'px;'); 884 } 885 886 vmlStr.push(' ">' , 887 '<g_vml_:image src="', image.src, '"', 888 ' style="width:', Z * dw, 'px;', 889 ' height:', Z * dh, 'px"', 890 ' cropleft="', sx / w, '"', 891 ' croptop="', sy / h, '"', 892 ' cropright="', (w - sx - sw) / w, '"', 893 ' cropbottom="', (h - sy - sh) / h, '"', 894 ' />', 895 '</g_vml_:group>'); 896 897 this.element_.insertAdjacentHTML('BeforeEnd', vmlStr.join('')); 898 }; 899 900 contextPrototype.stroke = function(aFill) { 901 var lineStr = []; 902 var lineOpen = false; 903 904 var W = 10; 905 var H = 10; 906 907 lineStr.push('<g_vml_:shape', 908 ' filled="', !!aFill, '"', 909 ' style="position:absolute;width:', W, 'px;height:', H, 'px;"', 910 ' coordorigin="0,0"', 911 ' coordsize="', Z * W, ',', Z * H, '"', 912 ' stroked="', !aFill, '"', 913 ' path="'); 914 915 var newSeq = false; 916 var min = {x: null, y: null}; 917 var max = {x: null, y: null}; 918 919 for (var i = 0; i < this.currentPath_.length; i++) { 920 var p = this.currentPath_[i]; 921 var c; 922 923 switch (p.type) { 924 case 'moveTo': 925 c = p; 926 lineStr.push(' m ', mr(p.x), ',', mr(p.y)); 927 break; 928 case 'lineTo': 929 lineStr.push(' l ', mr(p.x), ',', mr(p.y)); 930 break; 931 case 'close': 932 lineStr.push(' x '); 933 p = null; 934 break; 935 case 'bezierCurveTo': 936 lineStr.push(' c ', 937 mr(p.cp1x), ',', mr(p.cp1y), ',', 938 mr(p.cp2x), ',', mr(p.cp2y), ',', 939 mr(p.x), ',', mr(p.y)); 940 break; 941 case 'at': 942 case 'wa': 943 lineStr.push(' ', p.type, ' ', 944 mr(p.x - this.arcScaleX_ * p.radius), ',', 945 mr(p.y - this.arcScaleY_ * p.radius), ' ', 946 mr(p.x + this.arcScaleX_ * p.radius), ',', 947 mr(p.y + this.arcScaleY_ * p.radius), ' ', 948 mr(p.xStart), ',', mr(p.yStart), ' ', 949 mr(p.xEnd), ',', mr(p.yEnd)); 950 break; 951 } 952 953 954 // TODO: Following is broken for curves due to 955 // move to proper paths. 956 957 // Figure out dimensions so we can do gradient fills 958 // properly 959 if (p) { 960 if (min.x == null || p.x < min.x) { 961 min.x = p.x; 962 } 963 if (max.x == null || p.x > max.x) { 964 max.x = p.x; 965 } 966 if (min.y == null || p.y < min.y) { 967 min.y = p.y; 968 } 969 if (max.y == null || p.y > max.y) { 970 max.y = p.y; 971 } 972 } 973 } 974 lineStr.push(' ">'); 975 976 if (!aFill) { 977 appendStroke(this, lineStr); 978 } else { 979 appendFill(this, lineStr, min, max); 980 } 981 982 lineStr.push('</g_vml_:shape>'); 983 984 this.element_.insertAdjacentHTML('beforeEnd', lineStr.join('')); 985 }; 986 987 function appendStroke(ctx, lineStr) { 988 var a = processStyle(ctx.strokeStyle); 989 var color = a.color; 990 var opacity = a.alpha * ctx.globalAlpha; 991 var lineWidth = ctx.lineScale_ * ctx.lineWidth; 992 993 // VML cannot correctly render a line if the width is less than 1px. 994 // In that case, we dilute the color to make the line look thinner. 995 if (lineWidth < 1) { 996 opacity *= lineWidth; 997 } 998 999 lineStr.push( 1000 '<g_vml_:stroke', 1001 ' opacity="', opacity, '"', 1002 ' joinstyle="', ctx.lineJoin, '"', 1003 ' miterlimit="', ctx.miterLimit, '"', 1004 ' endcap="', processLineCap(ctx.lineCap), '"', 1005 ' weight="', lineWidth, 'px"', 1006 ' color="', color, '" />' 1007 ); 1008 } 1009 1010 function appendFill(ctx, lineStr, min, max) { 1011 var fillStyle = ctx.fillStyle; 1012 var arcScaleX = ctx.arcScaleX_; 1013 var arcScaleY = ctx.arcScaleY_; 1014 var width = max.x - min.x; 1015 var height = max.y - min.y; 1016 if (fillStyle instanceof CanvasGradient_) { 1017 // TODO: Gradients transformed with the transformation matrix. 1018 var angle = 0; 1019 var focus = {x: 0, y: 0}; 1020 1021 // additional offset 1022 var shift = 0; 1023 // scale factor for offset 1024 var expansion = 1; 1025 1026 if (fillStyle.type_ == 'gradient') { 1027 var x0 = fillStyle.x0_ / arcScaleX; 1028 var y0 = fillStyle.y0_ / arcScaleY; 1029 var x1 = fillStyle.x1_ / arcScaleX; 1030 var y1 = fillStyle.y1_ / arcScaleY; 1031 var p0 = getCoords(ctx, x0, y0); 1032 var p1 = getCoords(ctx, x1, y1); 1033 var dx = p1.x - p0.x; 1034 var dy = p1.y - p0.y; 1035 angle = Math.atan2(dx, dy) * 180 / Math.PI; 1036 1037 // The angle should be a non-negative number. 1038 if (angle < 0) { 1039 angle += 360; 1040 } 1041 1042 // Very small angles produce an unexpected result because they are 1043 // converted to a scientific notation string. 1044 if (angle < 1e-6) { 1045 angle = 0; 1046 } 1047 } else { 1048 var p0 = getCoords(ctx, fillStyle.x0_, fillStyle.y0_); 1049 focus = { 1050 x: (p0.x - min.x) / width, 1051 y: (p0.y - min.y) / height 1052 }; 1053 1054 width /= arcScaleX * Z; 1055 height /= arcScaleY * Z; 1056 var dimension = m.max(width, height); 1057 shift = 2 * fillStyle.r0_ / dimension; 1058 expansion = 2 * fillStyle.r1_ / dimension - shift; 1059 } 1060 1061 // We need to sort the color stops in ascending order by offset, 1062 // otherwise IE won't interpret it correctly. 1063 var stops = fillStyle.colors_; 1064 stops.sort(function(cs1, cs2) { 1065 return cs1.offset - cs2.offset; 1066 }); 1067 1068 var length = stops.length; 1069 var color1 = stops[0].color; 1070 var color2 = stops[length - 1].color; 1071 var opacity1 = stops[0].alpha * ctx.globalAlpha; 1072 var opacity2 = stops[length - 1].alpha * ctx.globalAlpha; 1073 1074 var colors = []; 1075 for (var i = 0; i < length; i++) { 1076 var stop = stops[i]; 1077 colors.push(stop.offset * expansion + shift + ' ' + stop.color); 1078 } 1079 1080 // When colors attribute is used, the meanings of opacity and o:opacity2 1081 // are reversed. 1082 lineStr.push('<g_vml_:fill type="', fillStyle.type_, '"', 1083 ' method="none" focus="100%"', 1084 ' color="', color1, '"', 1085 ' color2="', color2, '"', 1086 ' colors="', colors.join(','), '"', 1087 ' opacity="', opacity2, '"', 1088 ' g_o_:opacity2="', opacity1, '"', 1089 ' angle="', angle, '"', 1090 ' focusposition="', focus.x, ',', focus.y, '" />'); 1091 } else if (fillStyle instanceof CanvasPattern_) { 1092 if (width && height) { 1093 var deltaLeft = -min.x; 1094 var deltaTop = -min.y; 1095 lineStr.push('<g_vml_:fill', 1096 ' position="', 1097 deltaLeft / width * arcScaleX * arcScaleX, ',', 1098 deltaTop / height * arcScaleY * arcScaleY, '"', 1099 ' type="tile"', 1100 // TODO: Figure out the correct size to fit the scale. 1101 //' size="', w, 'px ', h, 'px"', 1102 ' src="', fillStyle.src_, '" />'); 1103 } 1104 } else { 1105 var a = processStyle(ctx.fillStyle); 1106 var color = a.color; 1107 var opacity = a.alpha * ctx.globalAlpha; 1108 lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity, 1109 '" />'); 1110 } 1111 } 1112 1113 contextPrototype.fill = function() { 1114 this.stroke(true); 1115 }; 1116 1117 contextPrototype.closePath = function() { 1118 this.currentPath_.push({type: 'close'}); 1119 }; 1120 1121 function getCoords(ctx, aX, aY) { 1122 var m = ctx.m_; 1123 return { 1124 x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2, 1125 y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2 1126 }; 1127 }; 1128 1129 contextPrototype.save = function() { 1130 var o = {}; 1131 copyState(this, o); 1132 this.aStack_.push(o); 1133 this.mStack_.push(this.m_); 1134 this.m_ = matrixMultiply(createMatrixIdentity(), this.m_); 1135 }; 1136 1137 contextPrototype.restore = function() { 1138 if (this.aStack_.length) { 1139 copyState(this.aStack_.pop(), this); 1140 this.m_ = this.mStack_.pop(); 1141 } 1142 }; 1143 1144 function matrixIsFinite(m) { 1145 return isFinite(m[0][0]) && isFinite(m[0][1]) && 1146 isFinite(m[1][0]) && isFinite(m[1][1]) && 1147 isFinite(m[2][0]) && isFinite(m[2][1]); 1148 } 1149 1150 function setM(ctx, m, updateLineScale) { 1151 if (!matrixIsFinite(m)) { 1152 return; 1153 } 1154 ctx.m_ = m; 1155 1156 if (updateLineScale) { 1157 // Get the line scale. 1158 // Determinant of this.m_ means how much the area is enlarged by the 1159 // transformation. So its square root can be used as a scale factor 1160 // for width. 1161 var det = m[0][0] * m[1][1] - m[0][1] * m[1][0]; 1162 ctx.lineScale_ = sqrt(abs(det)); 1163 } 1164 } 1165 1166 contextPrototype.translate = function(aX, aY) { 1167 var m1 = [ 1168 [1, 0, 0], 1169 [0, 1, 0], 1170 [aX, aY, 1] 1171 ]; 1172 1173 setM(this, matrixMultiply(m1, this.m_), false); 1174 }; 1175 1176 contextPrototype.rotate = function(aRot) { 1177 var c = mc(aRot); 1178 var s = ms(aRot); 1179 1180 var m1 = [ 1181 [c, s, 0], 1182 [-s, c, 0], 1183 [0, 0, 1] 1184 ]; 1185 1186 setM(this, matrixMultiply(m1, this.m_), false); 1187 }; 1188 1189 contextPrototype.scale = function(aX, aY) { 1190 this.arcScaleX_ *= aX; 1191 this.arcScaleY_ *= aY; 1192 var m1 = [ 1193 [aX, 0, 0], 1194 [0, aY, 0], 1195 [0, 0, 1] 1196 ]; 1197 1198 setM(this, matrixMultiply(m1, this.m_), true); 1199 }; 1200 1201 contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) { 1202 var m1 = [ 1203 [m11, m12, 0], 1204 [m21, m22, 0], 1205 [dx, dy, 1] 1206 ]; 1207 1208 setM(this, matrixMultiply(m1, this.m_), true); 1209 }; 1210 1211 contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) { 1212 var m = [ 1213 [m11, m12, 0], 1214 [m21, m22, 0], 1215 [dx, dy, 1] 1216 ]; 1217 1218 setM(this, m, true); 1219 }; 1220 1221 /** 1222 * The text drawing function. 1223 * The maxWidth argument isn't taken in account, since no browser supports 1224 * it yet. 1225 */ 1226 contextPrototype.drawText_ = function(text, x, y, maxWidth, stroke) { 1227 var m = this.m_, 1228 delta = 1000, 1229 left = 0, 1230 right = delta, 1231 offset = {x: 0, y: 0}, 1232 lineStr = []; 1233 1234 var fontStyle = getComputedStyle(processFontStyle(this.font), this.element_); 1235 1236 var fontStyleString = buildStyle(fontStyle); 1237 1238 var elementStyle = this.element_.currentStyle; 1239 var textAlign = this.textAlign.toLowerCase(); 1240 switch (textAlign) { 1241 case 'left': 1242 case 'center': 1243 case 'right': 1244 break; 1245 case 'end': 1246 textAlign = elementStyle.direction == 'ltr' ? 'right' : 'left'; 1247 break; 1248 case 'start': 1249 textAlign = elementStyle.direction == 'rtl' ? 'right' : 'left'; 1250 break; 1251 default: 1252 textAlign = 'left'; 1253 } 1254 1255 // 1.75 is an arbitrary number, as there is no info about the text baseline 1256 switch (this.textBaseline) { 1257 case 'hanging': 1258 case 'top': 1259 offset.y = fontStyle.size / 1.75; 1260 break; 1261 case 'middle': 1262 break; 1263 default: 1264 case null: 1265 case 'alphabetic': 1266 case 'ideographic': 1267 case 'bottom': 1268 offset.y = -fontStyle.size / 2.25; 1269 break; 1270 } 1271 1272 switch(textAlign) { 1273 case 'right': 1274 left = delta; 1275 right = 0.05; 1276 break; 1277 case 'center': 1278 left = right = delta / 2; 1279 break; 1280 } 1281 1282 var d = getCoords(this, x + offset.x, y + offset.y); 1283 1284 lineStr.push('<g_vml_:line from="', -left ,' 0" to="', right ,' 0.05" ', 1285 ' coordsize="100 100" coordorigin="0 0"', 1286 ' filled="', !stroke, '" stroked="', !!stroke, 1287 '" style="position:absolute;width:1px;height:1px;">'); 1288 1289 if (stroke) { 1290 appendStroke(this, lineStr); 1291 } else { 1292 // TODO: Fix the min and max params. 1293 appendFill(this, lineStr, {x: -left, y: 0}, 1294 {x: right, y: fontStyle.size}); 1295 } 1296 1297 var skewM = m[0][0].toFixed(3) + ',' + m[1][0].toFixed(3) + ',' + 1298 m[0][1].toFixed(3) + ',' + m[1][1].toFixed(3) + ',0,0'; 1299 1300 var skewOffset = mr(d.x / Z + 1 - m[0][0]) + ',' + mr(d.y / Z - 2 * m[1][0]); 1301 1302 1303 lineStr.push('<g_vml_:skew on="t" matrix="', skewM ,'" ', 1304 ' offset="', skewOffset, '" origin="', left ,' 0" />', 1305 '<g_vml_:path textpathok="true" />', 1306 '<g_vml_:textpath on="true" string="', 1307 encodeHtmlAttribute(text), 1308 '" style="v-text-align:', textAlign, 1309 ';font:', encodeHtmlAttribute(fontStyleString), 1310 '" /></g_vml_:line>'); 1311 1312 this.element_.insertAdjacentHTML('beforeEnd', lineStr.join('')); 1313 }; 1314 1315 contextPrototype.fillText = function(text, x, y, maxWidth) { 1316 this.drawText_(text, x, y, maxWidth, false); 1317 }; 1318 1319 contextPrototype.strokeText = function(text, x, y, maxWidth) { 1320 this.drawText_(text, x, y, maxWidth, true); 1321 }; 1322 1323 contextPrototype.measureText = function(text) { 1324 if (!this.textMeasureEl_) { 1325 var s = '<span style="position:absolute;' + 1326 'top:-20000px;left:0;padding:0;margin:0;border:none;' + 1327 'white-space:pre;"></span>'; 1328 this.element_.insertAdjacentHTML('beforeEnd', s); 1329 this.textMeasureEl_ = this.element_.lastChild; 1330 } 1331 var doc = this.element_.ownerDocument; 1332 this.textMeasureEl_.innerHTML = ''; 1333 this.textMeasureEl_.style.font = this.font; 1334 // Don't use innerHTML or innerText because they allow markup/whitespace. 1335 this.textMeasureEl_.appendChild(doc.createTextNode(text)); 1336 return {width: this.textMeasureEl_.offsetWidth}; 1337 }; 1338 1339 /******** STUBS ********/ 1340 contextPrototype.clip = function() { 1341 // TODO: Implement 1342 }; 1343 1344 contextPrototype.arcTo = function() { 1345 // TODO: Implement 1346 }; 1347 1348 contextPrototype.createPattern = function(image, repetition) { 1349 return new CanvasPattern_(image, repetition); 1350 }; 1351 1352 // Gradient / Pattern Stubs 1353 function CanvasGradient_(aType) { 1354 this.type_ = aType; 1355 this.x0_ = 0; 1356 this.y0_ = 0; 1357 this.r0_ = 0; 1358 this.x1_ = 0; 1359 this.y1_ = 0; 1360 this.r1_ = 0; 1361 this.colors_ = []; 1362 } 1363 1364 CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) { 1365 aColor = processStyle(aColor); 1366 this.colors_.push({offset: aOffset, 1367 color: aColor.color, 1368 alpha: aColor.alpha}); 1369 }; 1370 1371 function CanvasPattern_(image, repetition) { 1372 assertImageIsValid(image); 1373 switch (repetition) { 1374 case 'repeat': 1375 case null: 1376 case '': 1377 this.repetition_ = 'repeat'; 1378 break; 1379 case 'repeat-x': 1380 case 'repeat-y': 1381 case 'no-repeat': 1382 this.repetition_ = repetition; 1383 break; 1384 default: 1385 throwException('SYNTAX_ERR'); 1386 } 1387 1388 this.src_ = image.src; 1389 this.width_ = image.width; 1390 this.height_ = image.height; 1391 } 1392 1393 function throwException(s) { 1394 throw new DOMException_(s); 1395 } 1396 1397 function assertImageIsValid(img) { 1398 if (!img || img.nodeType != 1 || img.tagName != 'IMG') { 1399 throwException('TYPE_MISMATCH_ERR'); 1400 } 1401 if (img.readyState != 'complete') { 1402 throwException('INVALID_STATE_ERR'); 1403 } 1404 } 1405 1406 function DOMException_(s) { 1407 this.code = this[s]; 1408 this.message = s +': DOM Exception ' + this.code; 1409 } 1410 var p = DOMException_.prototype = new Error; 1411 p.INDEX_SIZE_ERR = 1; 1412 p.DOMSTRING_SIZE_ERR = 2; 1413 p.HIERARCHY_REQUEST_ERR = 3; 1414 p.WRONG_DOCUMENT_ERR = 4; 1415 p.INVALID_CHARACTER_ERR = 5; 1416 p.NO_DATA_ALLOWED_ERR = 6; 1417 p.NO_MODIFICATION_ALLOWED_ERR = 7; 1418 p.NOT_FOUND_ERR = 8; 1419 p.NOT_SUPPORTED_ERR = 9; 1420 p.INUSE_ATTRIBUTE_ERR = 10; 1421 p.INVALID_STATE_ERR = 11; 1422 p.SYNTAX_ERR = 12; 1423 p.INVALID_MODIFICATION_ERR = 13; 1424 p.NAMESPACE_ERR = 14; 1425 p.INVALID_ACCESS_ERR = 15; 1426 p.VALIDATION_ERR = 16; 1427 p.TYPE_MISMATCH_ERR = 17; 1428 1429 // set up externs 1430 G_vmlCanvasManager = G_vmlCanvasManager_; 1431 CanvasRenderingContext2D = CanvasRenderingContext2D_; 1432 CanvasGradient = CanvasGradient_; 1433 CanvasPattern = CanvasPattern_; 1434 DOMException = DOMException_; 1435 G_vmlCanvasManager._version = 888; 1436 })(); 1437 1438 } // if
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |