diff options
Diffstat (limited to 'excanvas.js')
-rw-r--r-- | excanvas.js | 131 |
1 files changed, 66 insertions, 65 deletions
diff --git a/excanvas.js b/excanvas.js index c40d6f7..70a8f25 100644 --- a/excanvas.js +++ b/excanvas.js @@ -49,6 +49,8 @@ if (!document.createElement('canvas').getContext) { var Z = 10; var Z2 = Z / 2; + var IE_VERSION = +navigator.userAgent.match(/MSIE ([\d.]+)?/)[1]; + /** * This funtion is assigned to the <canvas> elements as element.getContext(). * @this {HTMLElement} @@ -88,17 +90,15 @@ if (!document.createElement('canvas').getContext) { return String(s).replace(/&/g, '&').replace(/"/g, '"'); } - function addNamespacesAndStylesheet(doc) { - // create xmlns - if (!doc.namespaces['g_vml_']) { - doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml', - '#default#VML'); - - } - if (!doc.namespaces['g_o_']) { - doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office', - '#default#VML'); + function addNamespace(doc, prefix, urn) { + if (!doc.namespaces[prefix]) { + doc.namespaces.add(prefix, urn, '#default#VML'); } + } + + function addNamespacesAndStylesheet(doc) { + addNamespace(doc, 'g_vml_', 'urn:schemas-microsoft-com:vml'); + addNamespace(doc, 'g_o_', 'urn:schemas-microsoft-com:office:office'); // Setup default CSS. Only add one style sheet per document if (!doc.styleSheets['ex_canvas_']) { @@ -115,13 +115,11 @@ if (!document.createElement('canvas').getContext) { var G_vmlCanvasManager_ = { init: function(opt_doc) { - if (/MSIE/.test(navigator.userAgent) && !window.opera) { - var doc = opt_doc || document; - // Create a dummy element so that IE will allow canvas elements to be - // recognized. - doc.createElement('canvas'); - doc.attachEvent('onreadystatechange', bind(this.init_, this, doc)); - } + var doc = opt_doc || document; + // Create a dummy element so that IE will allow canvas elements to be + // recognized. + doc.createElement('canvas'); + doc.attachEvent('onreadystatechange', bind(this.init_, this, doc)); }, init_: function(doc) { @@ -398,9 +396,7 @@ if (!document.createElement('canvas').getContext) { var end = styleString.indexOf(')', start + 1); var parts = styleString.substring(start + 1, end).split(','); // add alpha if needed - if (parts.length == 4 && styleString.substr(3, 1) == 'a') { - alpha = Number(parts[3]); - } else { + if (parts.length != 4 || styleString.charAt(3) != 'a') { parts[3] = 1; } return parts; @@ -415,7 +411,7 @@ if (!document.createElement('canvas').getContext) { } function hslToRgb(parts){ - var r, g, b; + var r, g, b, h, s, l; h = parseFloat(parts[0]) / 360 % 360; if (h < 0) h++; @@ -452,7 +448,13 @@ if (!document.createElement('canvas').getContext) { return m1; } + var processStyleCache = {}; + function processStyle(styleString) { + if (styleString in processStyleCache) { + return processStyleCache[styleString]; + } + var str, alpha = 1; styleString = String(styleString); @@ -465,11 +467,11 @@ if (!document.createElement('canvas').getContext) { if (parts[i].indexOf('%') != -1) { n = Math.floor(percent(parts[i]) * 255); } else { - n = Number(parts[i]); + n = +parts[i]; } str += decToHex[clamp(n, 0, 255)]; } - alpha = parts[3]; + alpha = +parts[3]; } else if (/^hsl/.test(styleString)) { var parts = getRgbHslContent(styleString); str = hslToRgb(parts); @@ -477,7 +479,7 @@ if (!document.createElement('canvas').getContext) { } else { str = colorData[styleString] || styleString; } - return {color: str, alpha: alpha}; + return processStyleCache[styleString] = {color: str, alpha: alpha}; } var DEFAULT_STYLE = { @@ -550,25 +552,22 @@ if (!document.createElement('canvas').getContext) { style.size + 'px ' + style.family; } + var lineCapMap = { + 'butt': 'flat', + 'round': 'round' + }; + function processLineCap(lineCap) { - switch (lineCap) { - case 'butt': - return 'flat'; - case 'round': - return 'round'; - case 'square': - default: - return 'square'; - } + return lineCapMap[lineCap] || 'square'; } /** * This class implements CanvasRenderingContext2D interface as described by * the WHATWG. - * @param {HTMLElement} surfaceElement The element that the 2D context should + * @param {HTMLElement} canvasElement The element that the 2D context should * be associated with */ - function CanvasRenderingContext2D_(surfaceElement) { + function CanvasRenderingContext2D_(canvasElement) { this.m_ = createMatrixIdentity(); this.mStack_ = []; @@ -587,14 +586,19 @@ if (!document.createElement('canvas').getContext) { this.font = '10px sans-serif'; this.textAlign = 'left'; this.textBaseline = 'alphabetic'; - this.canvas = surfaceElement; + this.canvas = canvasElement; + + var cssText = 'width:' + canvasElement.clientWidth + 'px;height:' + + canvasElement.clientHeight + 'px;overflow:hidden;position:absolute'; + var el = canvasElement.ownerDocument.createElement('div'); + el.style.cssText = cssText; + canvasElement.appendChild(el); - var el = surfaceElement.ownerDocument.createElement('div'); - el.style.width = surfaceElement.clientWidth + 'px'; - el.style.height = surfaceElement.clientHeight + 'px'; - el.style.overflow = 'hidden'; - el.style.position = 'absolute'; - surfaceElement.appendChild(el); + var overlayEl = el.cloneNode(false); + // Use a non transparent background. + overlayEl.style.backgroundColor = 'red'; + overlayEl.style.filter = 'alpha(opacity=0)'; + canvasElement.appendChild(overlayEl); this.element_ = el; this.arcScaleX_ = 1; @@ -618,14 +622,14 @@ if (!document.createElement('canvas').getContext) { }; contextPrototype.moveTo = function(aX, aY) { - var p = this.getCoords_(aX, aY); + var p = getCoords(this, aX, aY); this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y}); this.currentX_ = p.x; this.currentY_ = p.y; }; contextPrototype.lineTo = function(aX, aY) { - var p = this.getCoords_(aX, aY); + var p = getCoords(this, aX, aY); this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y}); this.currentX_ = p.x; @@ -635,9 +639,9 @@ if (!document.createElement('canvas').getContext) { contextPrototype.bezierCurveTo = function(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) { - var p = this.getCoords_(aX, aY); - var cp1 = this.getCoords_(aCP1x, aCP1y); - var cp2 = this.getCoords_(aCP2x, aCP2y); + var p = getCoords(this, aX, aY); + var cp1 = getCoords(this, aCP1x, aCP1y); + var cp2 = getCoords(this, aCP2x, aCP2y); bezierCurveTo(this, cp1, cp2, p); }; @@ -660,8 +664,8 @@ if (!document.createElement('canvas').getContext) { // the following is lifted almost directly from // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes - var cp = this.getCoords_(aCPx, aCPy); - var p = this.getCoords_(aX, aY); + var cp = getCoords(this, aCPx, aCPy); + var p = getCoords(this, aX, aY); var cp1 = { x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_), @@ -692,9 +696,9 @@ if (!document.createElement('canvas').getContext) { // that can be represented in binary } - var p = this.getCoords_(aX, aY); - var pStart = this.getCoords_(xStart, yStart); - var pEnd = this.getCoords_(xEnd, yEnd); + var p = getCoords(this, aX, aY); + var pStart = getCoords(this, xStart, yStart); + var pEnd = getCoords(this, xEnd, yEnd); this.currentPath_.push({type: arcType, x: p.x, @@ -808,7 +812,7 @@ if (!document.createElement('canvas').getContext) { throw Error('Invalid number of arguments'); } - var d = this.getCoords_(dx, dy); + var d = getCoords(this, dx, dy); var w2 = sw / 2; var h2 = sh / 2; @@ -844,9 +848,9 @@ if (!document.createElement('canvas').getContext) { // Bounding box calculation (need to minimize displayed area so that // filters don't waste time on unused pixels. var max = d; - var c2 = this.getCoords_(dx + dw, dy); - var c3 = this.getCoords_(dx, dy + dh); - var c4 = this.getCoords_(dx + dw, dy + dh); + var c2 = getCoords(this, dx + dw, dy); + var c3 = getCoords(this, dx, dy + dh); + var c4 = getCoords(this, dx + dw, dy + dh); max.x = m.max(max.x, c2.x, c3.x, c4.x); max.y = m.max(max.y, c2.y, c3.y, c4.y); @@ -1015,8 +1019,8 @@ if (!document.createElement('canvas').getContext) { var y0 = fillStyle.y0_ / arcScaleY; var x1 = fillStyle.x1_ / arcScaleX; var y1 = fillStyle.y1_ / arcScaleY; - var p0 = ctx.getCoords_(x0, y0); - var p1 = ctx.getCoords_(x1, y1); + var p0 = getCoords(ctx, x0, y0); + var p1 = getCoords(ctx, x1, y1); var dx = p1.x - p0.x; var dy = p1.y - p0.y; angle = Math.atan2(dx, dy) * 180 / Math.PI; @@ -1032,7 +1036,7 @@ if (!document.createElement('canvas').getContext) { angle = 0; } } else { - var p0 = ctx.getCoords_(fillStyle.x0_, fillStyle.y0_); + var p0 = getCoords(ctx, fillStyle.x0_, fillStyle.y0_); focus = { x: (p0.x - min.x) / width, y: (p0.y - min.y) / height @@ -1105,11 +1109,8 @@ if (!document.createElement('canvas').getContext) { this.currentPath_.push({type: 'close'}); }; - /** - * @private - */ - contextPrototype.getCoords_ = function(aX, aY) { - var m = this.m_; + function getCoords(ctx, aX, aY) { + var m = ctx.m_; return { x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2, y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2 @@ -1270,7 +1271,7 @@ if (!document.createElement('canvas').getContext) { break; } - var d = this.getCoords_(x + offset.x, y + offset.y); + var d = getCoords(this, x + offset.x, y + offset.y); lineStr.push('<g_vml_:line from="', -left ,' 0" to="', right ,' 0.05" ', ' coordsize="100 100" coordorigin="0 0"', |