PHP Classes

File: web/bundles/extjs/src/draw/engine/Vml.js

Recommend this page to a friend!
  Classes of william amed   Raptor 2   web/bundles/extjs/src/draw/engine/Vml.js   Download  
File: web/bundles/extjs/src/draw/engine/Vml.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Raptor 2
Framework that takes routes from annotations
Author: By
Last change:
Date: 8 years ago
Size: 30,170 bytes
 

Contents

Class file image Download
/* This file is part of Ext JS 4.2 Copyright (c) 2011-2013 Sencha Inc Contact: http://www.sencha.com/contact GNU General Public License Usage This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html. If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact. Build date: 2013-05-16 14:36:50 (f9be68accb407158ba2b1be2c226a6ce1f649314) */ /** * Provides specific methods to draw with VML. */ Ext.define('Ext.draw.engine.Vml', { /* Begin Definitions */ extend: 'Ext.draw.Surface', requires: ['Ext.draw.Draw', 'Ext.draw.Color', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.Element'], /* End Definitions */ engine: 'Vml', map: {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"}, bitesRe: /([clmz]),?([^clmz]*)/gi, valRe: /-?[^,\s\-]+/g, fillUrlRe: /^url\(\s*['"]?([^\)]+?)['"]?\s*\)$/i, pathlike: /^(path|rect)$/, NonVmlPathRe: /[ahqstv]/ig, // Non-VML Pathing ops partialPathRe: /[clmz]/g, fontFamilyRe: /^['"]+|['"]+$/g, baseVmlCls: Ext.baseCSSPrefix + 'vml-base', vmlGroupCls: Ext.baseCSSPrefix + 'vml-group', spriteCls: Ext.baseCSSPrefix + 'vml-sprite', measureSpanCls: Ext.baseCSSPrefix + 'vml-measure-span', zoom: 21600, coordsize: 1000, coordorigin: '0 0', zIndexShift: 0, // VML uses CSS z-index and therefore doesn't need sprites to be kept in zIndex order orderSpritesByZIndex: false, // @private // Convert an SVG standard path into a VML path path2vml: function (path) { var me = this, nonVML = me.NonVmlPathRe, map = me.map, val = me.valRe, zoom = me.zoom, bites = me.bitesRe, command = Ext.Function.bind(Ext.draw.Draw.pathToAbsolute, Ext.draw.Draw), res, pa, p, r, i, ii, j, jj; if (String(path).match(nonVML)) { command = Ext.Function.bind(Ext.draw.Draw.path2curve, Ext.draw.Draw); } else if (!String(path).match(me.partialPathRe)) { res = String(path).replace(bites, function (all, command, args) { var vals = [], isMove = command.toLowerCase() == "m", res = map[command]; args.replace(val, function (value) { if (isMove && vals.length === 2) { res += vals + map[command == "m" ? "l" : "L"]; vals = []; } vals.push(Math.round(value * zoom)); }); return res + vals; }); return res; } pa = command(path); res = []; for (i = 0, ii = pa.length; i < ii; i++) { p = pa[i]; r = pa[i][0].toLowerCase(); if (r == "z") { r = "x"; } for (j = 1, jj = p.length; j < jj; j++) { r += Math.round(p[j] * me.zoom) + (j != jj - 1 ? "," : ""); } res.push(r); } return res.join(" "); }, // @private - set of attributes which need to be translated from the sprite API to the native browser API translateAttrs: { radius: "r", radiusX: "rx", radiusY: "ry", lineWidth: "stroke-width", fillOpacity: "fill-opacity", strokeOpacity: "stroke-opacity", strokeLinejoin: "stroke-linejoin" }, // @private - Minimun set of defaults for different types of sprites. minDefaults: { circle: { fill: "none", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, ellipse: { cx: 0, cy: 0, rx: 0, ry: 0, fill: "none", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, rect: { x: 0, y: 0, width: 0, height: 0, rx: 0, ry: 0, fill: "none", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, text: { x: 0, y: 0, "text-anchor": "start", font: '10px "Arial"', fill: "#000", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, path: { d: "M0,0", fill: "none", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, image: { x: 0, y: 0, width: 0, height: 0, preserveAspectRatio: "none", opacity: null } }, // private onMouseEnter: function (e) { this.fireEvent("mouseenter", e); }, // private onMouseLeave: function (e) { this.fireEvent("mouseleave", e); }, // @private - Normalize a delegated single event from the main container to each sprite and sprite group processEvent: function (name, e) { var target = e.getTarget(), surface = this.surface, sprite; this.fireEvent(name, e); sprite = this.items.get(target.id); if (sprite) { sprite.fireEvent(name, sprite, e); } }, // Create the VML element/elements and append them to the DOM createSpriteElement: function (sprite) { var me = this, attr = sprite.attr, type = sprite.type, zoom = me.zoom, vml = sprite.vml || (sprite.vml = {}), round = Math.round, el = (type === 'image') ? me.createNode('image') : me.createNode('shape'), path, skew, textPath; el.coordsize = zoom + ' ' + zoom; el.coordorigin = attr.coordorigin || "0 0"; Ext.get(el).addCls(me.spriteCls); if (type == "text") { vml.path = path = me.createNode("path"); path.textpathok = true; vml.textpath = textPath = me.createNode("textpath"); textPath.on = true; el.appendChild(textPath); el.appendChild(path); } el.id = sprite.id; sprite.el = Ext.get(el); sprite.el.setStyle('zIndex', -me.zIndexShift); me.el.appendChild(el); if (type !== 'image') { skew = me.createNode("skew"); skew.on = true; el.appendChild(skew); sprite.skew = skew; } sprite.matrix = new Ext.draw.Matrix(); sprite.bbox = { plain: null, transform: null }; this.applyAttrs(sprite); this.applyTransformations(sprite); sprite.fireEvent("render", sprite); return sprite.el; }, getBBoxText: function (sprite) { var vml = sprite.vml; return { x: vml.X + (vml.bbx || 0) - vml.W / 2, y: vml.Y - vml.H / 2, width: vml.W, height: vml.H }; }, applyAttrs: function (sprite) { var me = this, vml = sprite.vml, group = sprite.group, spriteAttr = sprite.attr, el = sprite.el, dom = el.dom, style, name, groups, i, ln, scrubbedAttrs, font, key, cx, cy, rx, ry; if (group) { groups = [].concat(group); ln = groups.length; for (i = 0; i < ln; i++) { group = groups[i]; me.getGroup(group).add(sprite); } delete sprite.group; } scrubbedAttrs = me.scrubAttrs(sprite) || {}; if (sprite.zIndexDirty) { me.setZIndex(sprite); } // Apply minimum default attributes Ext.applyIf(scrubbedAttrs, me.minDefaults[sprite.type]); if (sprite.type == 'image') { Ext.apply(sprite.attr, { x: scrubbedAttrs.x, y: scrubbedAttrs.y, width: scrubbedAttrs.width, height: scrubbedAttrs.height }); el.setStyle({ width: scrubbedAttrs.width + 'px', height: scrubbedAttrs.height + 'px' }); dom.src = scrubbedAttrs.src; } if (dom.href) { dom.href = scrubbedAttrs.href; } if (dom.title) { dom.title = scrubbedAttrs.title; } if (dom.target) { dom.target = scrubbedAttrs.target; } if (dom.cursor) { dom.cursor = scrubbedAttrs.cursor; } // Change visibility if (sprite.dirtyHidden) { (scrubbedAttrs.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite); sprite.dirtyHidden = false; } // Update path if (sprite.dirtyPath) { if (sprite.type == "circle" || sprite.type == "ellipse") { cx = scrubbedAttrs.x; cy = scrubbedAttrs.y; rx = scrubbedAttrs.rx || scrubbedAttrs.r || 0; ry = scrubbedAttrs.ry || scrubbedAttrs.r || 0; dom.path = Ext.String.format("ar{0},{1},{2},{3},{4},{1},{4},{1}", Math.round((cx - rx) * me.zoom), Math.round((cy - ry) * me.zoom), Math.round((cx + rx) * me.zoom), Math.round((cy + ry) * me.zoom), Math.round(cx * me.zoom)); sprite.dirtyPath = false; } else if (sprite.type !== "text" && sprite.type !== 'image') { sprite.attr.path = scrubbedAttrs.path = me.setPaths(sprite, scrubbedAttrs) || scrubbedAttrs.path; dom.path = me.path2vml(scrubbedAttrs.path); sprite.dirtyPath = false; } } // Apply clipping if ("clip-rect" in scrubbedAttrs) { me.setClip(sprite, scrubbedAttrs); } // Handle text (special handling required) if (sprite.type == "text") { me.setTextAttributes(sprite, scrubbedAttrs); } // Handle fill and opacity if (scrubbedAttrs.opacity || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) { me.setFill(sprite, scrubbedAttrs); } // Handle stroke (all fills require a stroke element) if (scrubbedAttrs.stroke || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) { me.setStroke(sprite, scrubbedAttrs); } //set styles style = spriteAttr.style; if (style) { el.setStyle(style); } sprite.dirty = false; }, setZIndex: function (sprite) { var me = this, zIndex = sprite.attr.zIndex, shift = me.zIndexShift, items, iLen, item, i; if (zIndex < shift) { // This means bad thing happened. // The algorithm below will guarantee O(n) time. items = me.items.items; iLen = items.length; for (i = 0; i < iLen; i++) { if ((zIndex = items[i].attr.zIndex) && zIndex < shift) { // zIndex is no longer useful this case shift = zIndex; } } me.zIndexShift = shift; for (i = 0; i < iLen; i++) { item = items[i]; if (item.el) { item.el.setStyle('zIndex', item.attr.zIndex - shift); } item.zIndexDirty = false; } } else if (sprite.el) { sprite.el.setStyle('zIndex', zIndex - shift); sprite.zIndexDirty = false; } }, // Normalize all virtualized types into paths. setPaths: function (sprite, params) { var spriteAttr = sprite.attr, thickness = sprite.attr['stroke-width'] || 1; // Clear bbox cache sprite.bbox.plain = null; sprite.bbox.transform = null; if (sprite.type == 'circle') { spriteAttr.rx = spriteAttr.ry = params.r; return Ext.draw.Draw.ellipsePath(sprite); } else if (sprite.type == 'ellipse') { spriteAttr.rx = params.rx; spriteAttr.ry = params.ry; return Ext.draw.Draw.ellipsePath(sprite); } else if (sprite.type == 'rect') { spriteAttr.rx = spriteAttr.ry = params.r; return Ext.draw.Draw.rectPath(sprite); } else if (sprite.type == 'path' && spriteAttr.path) { return Ext.draw.Draw.pathToAbsolute(spriteAttr.path); } return false; }, setFill: function (sprite, params) { var me = this, el = sprite.el.dom, fillEl = el.fill, newfill = false, opacity, gradient, fillUrl, rotation, angle; if (!fillEl) { // NOT an expando (but it sure looks like one)... fillEl = el.fill = me.createNode("fill"); newfill = true; } if (Ext.isArray(params.fill)) { params.fill = params.fill[0]; } if (params.fill == "none") { fillEl.on = false; } else { if (typeof params.opacity == "number") { fillEl.opacity = params.opacity; } if (typeof params["fill-opacity"] == "number") { fillEl.opacity = params["fill-opacity"]; } fillEl.on = true; if (typeof params.fill == "string") { fillUrl = params.fill.match(me.fillUrlRe); if (fillUrl) { fillUrl = fillUrl[1]; // If the URL matches one of the registered gradients, render that gradient if (fillUrl.charAt(0) == "#") { gradient = me.gradientsColl.getByKey(fillUrl.substring(1)); } if (gradient) { // VML angle is offset and inverted from standard, and must be adjusted to match rotation transform rotation = params.rotation; angle = -(gradient.angle + 270 + (rotation ? rotation.degrees : 0)) % 360; // IE will flip the angle at 0 degrees... if (angle === 0) { angle = 180; } fillEl.angle = angle; fillEl.type = "gradient"; fillEl.method = "sigma"; if (fillEl.colors) { fillEl.colors.value = gradient.colors; } else { fillEl.colors = gradient.colors; } } // Otherwise treat it as an image else { fillEl.src = fillUrl; fillEl.type = "tile"; } } else { fillEl.color = Ext.draw.Color.toHex(params.fill); fillEl.src = ""; fillEl.type = "solid"; } } } if (newfill) { el.appendChild(fillEl); } }, setStroke: function (sprite, params) { var me = this, el = sprite.el.dom, strokeEl = sprite.strokeEl, newStroke = false, width, opacity; if (!strokeEl) { strokeEl = sprite.strokeEl = me.createNode("stroke"); newStroke = true; } if (Ext.isArray(params.stroke)) { params.stroke = params.stroke[0]; } if (!params.stroke || params.stroke == "none" || params.stroke == 0 || params["stroke-width"] == 0) { strokeEl.on = false; } else { strokeEl.on = true; if (params.stroke && !params.stroke.match(me.fillUrlRe)) { // VML does NOT support a gradient stroke :( strokeEl.color = Ext.draw.Color.toHex(params.stroke); } strokeEl.dashstyle = params["stroke-dasharray"] ? "dash" : "solid"; strokeEl.joinstyle = params["stroke-linejoin"]; strokeEl.endcap = params["stroke-linecap"] || "round"; strokeEl.miterlimit = params["stroke-miterlimit"] || 8; width = parseFloat(params["stroke-width"] || 1) * 0.75; opacity = params["stroke-opacity"] || 1; // VML Does not support stroke widths under 1, so we're going to fiddle with stroke-opacity instead. if (Ext.isNumber(width) && width < 1) { strokeEl.weight = 1; strokeEl.opacity = opacity * width; } else { strokeEl.weight = width; strokeEl.opacity = opacity; } } if (newStroke) { el.appendChild(strokeEl); } }, setClip: function (sprite, params) { var me = this, el = sprite.el, clipEl = sprite.clipEl, rect = String(params["clip-rect"]).split(me.separatorRe); if (!clipEl) { clipEl = sprite.clipEl = me.el.insertFirst(Ext.getDoc().dom.createElement("div")); clipEl.addCls(Ext.baseCSSPrefix + 'vml-sprite'); } if (rect.length == 4) { rect[2] = +rect[2] + (+rect[0]); rect[3] = +rect[3] + (+rect[1]); clipEl.setStyle("clip", Ext.String.format("rect({1}px {2}px {3}px {0}px)", rect[0], rect[1], rect[2], rect[3])); clipEl.setSize(me.el.width, me.el.height); } else { clipEl.setStyle("clip", ""); } }, setTextAttributes: function (sprite, params) { var me = this, vml = sprite.vml, textStyle = vml.textpath.style, spanCacheStyle = me.span.style, zoom = me.zoom, round = Math.round, fontObj = { fontSize: "font-size", fontWeight: "font-weight", fontStyle: "font-style" }, fontProp, paramProp; if (sprite.dirtyFont) { if (params.font) { textStyle.font = spanCacheStyle.font = params.font; } if (params["font-family"]) { textStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(me.fontFamilyRe, "") + '"'; spanCacheStyle.fontFamily = params["font-family"]; } for (fontProp in fontObj) { paramProp = params[fontObj[fontProp]]; if (paramProp) { textStyle[fontProp] = spanCacheStyle[fontProp] = paramProp; } } me.setText(sprite, params.text); if (vml.textpath.string) { me.span.innerHTML = String(vml.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br/>"); } vml.W = me.span.offsetWidth; vml.H = me.span.offsetHeight + 2; // TODO handle baseline differences and offset in VML Textpath // text-anchor emulation if (params["text-anchor"] == "middle") { textStyle["v-text-align"] = "center"; } else if (params["text-anchor"] == "end") { textStyle["v-text-align"] = "right"; vml.bbx = -Math.round(vml.W / 2); } else { textStyle["v-text-align"] = "left"; vml.bbx = Math.round(vml.W / 2); } } vml.X = params.x; vml.Y = params.y; vml.path.v = Ext.String.format("m{0},{1}l{2},{1}", Math.round(vml.X * zoom), Math.round(vml.Y * zoom), Math.round(vml.X * zoom) + 1); // Clear bbox cache sprite.bbox.plain = null; sprite.bbox.transform = null; sprite.dirtyFont = false; }, setText: function (sprite, text) { sprite.vml.textpath.string = Ext.htmlDecode(text); }, hide: function () { this.el.hide(); }, show: function () { this.el.show(); }, hidePrim: function (sprite) { sprite.el.addCls(Ext.baseCSSPrefix + 'hide-visibility'); }, showPrim: function (sprite) { sprite.el.removeCls(Ext.baseCSSPrefix + 'hide-visibility'); }, setSize: function (width, height) { var me = this; width = width || me.width; height = height || me.height; me.width = width; me.height = height; if (me.el) { // Size outer div if (width != undefined) { me.el.setWidth(width); } if (height != undefined) { me.el.setHeight(height); } } me.callParent(arguments); }, /** * @private Using the current viewBox property and the surface's width and height, calculate the * appropriate viewBoxShift that will be applied as a persistent transform to all sprites. */ applyViewBox: function () { var me = this, viewBox = me.viewBox, width = me.width, height = me.height, items, iLen, i; me.callParent(); if (viewBox && (width || height)) { items = me.items.items; iLen = items.length; for (i = 0; i < iLen; i++) { me.applyTransformations(items[i]); } } }, onAdd: function (item) { this.callParent(arguments); if (this.el) { this.renderItem(item); } }, onRemove: function (sprite) { if (sprite.el) { sprite.el.remove(); delete sprite.el; } this.callParent(arguments); }, render: function (container) { var me = this, doc = Ext.getDoc().dom, el; // VML Node factory method (createNode) if (!me.createNode) { try { if (!doc.namespaces.rvml) { doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml"); } me.createNode = function (tagName) { return doc.createElement("<rvml:" + tagName + ' class="rvml">'); }; } catch (e) { me.createNode = function (tagName) { return doc.createElement("<" + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">'); }; } } if (!me.el) { el = doc.createElement("div"); me.el = Ext.get(el); me.el.addCls(me.baseVmlCls); // Measuring span (offscrren) me.span = doc.createElement("span"); Ext.get(me.span).addCls(me.measureSpanCls); el.appendChild(me.span); me.el.setSize(me.width || 0, me.height || 0); container.appendChild(el); me.el.on({ scope: me, mouseup: me.onMouseUp, mousedown: me.onMouseDown, mouseover: me.onMouseOver, mouseout: me.onMouseOut, mousemove: me.onMouseMove, mouseenter: me.onMouseEnter, mouseleave: me.onMouseLeave, click: me.onClick, dblclick: me.onDblClick }); } me.renderAll(); }, renderAll: function () { this.items.each(this.renderItem, this); }, redraw: function (sprite) { sprite.dirty = true; this.renderItem(sprite); }, renderItem: function (sprite) { // Does the surface element exist? if (!this.el) { return; } // Create sprite element if necessary if (!sprite.el) { this.createSpriteElement(sprite); } if (sprite.dirty) { this.applyAttrs(sprite); if (sprite.dirtyTransform) { this.applyTransformations(sprite); } } }, rotationCompensation: function (deg, dx, dy) { var matrix = new Ext.draw.Matrix(); matrix.rotate(-deg, 0.5, 0.5); return { x: matrix.x(dx, dy), y: matrix.y(dx, dy) }; }, transform: function (sprite, matrixOnly) { var me = this, bbox = me.getBBox(sprite, true), cx = bbox.x + bbox.width * 0.5, cy = bbox.y + bbox.height * 0.5, matrix = new Ext.draw.Matrix(), transforms = sprite.transformations, transformsLength = transforms.length, i = 0, deltaDegrees = 0, deltaScaleX = 1, deltaScaleY = 1, flip = "", el = sprite.el, dom = el.dom, domStyle = dom.style, zoom = me.zoom, skew = sprite.skew, shift = me.viewBoxShift, deltaX, deltaY, transform, type, compensate, y, fill, newAngle, zoomScaleX, zoomScaleY, newOrigin, offset; for (; i < transformsLength; i++) { transform = transforms[i]; type = transform.type; if (type == "translate") { matrix.translate(transform.x, transform.y); } else if (type == "rotate") { matrix.rotate(transform.degrees, transform.x, transform.y); deltaDegrees += transform.degrees; } else if (type == "scale") { matrix.scale(transform.x, transform.y, transform.centerX, transform.centerY); deltaScaleX *= transform.x; deltaScaleY *= transform.y; } } sprite.matrix = matrix.clone(); if (matrixOnly) { return; } if (shift) { matrix.prepend(shift.scale, 0, 0, shift.scale, shift.dx * shift.scale, shift.dy * shift.scale); } // Hide element while we transform if (sprite.type != "image" && skew) { skew.origin = "0,0"; // matrix transform via VML skew skew.matrix = matrix.toString(); // skew.offset = '32767,1' OK // skew.offset = '32768,1' Crash // M$, R U kidding?? offset = matrix.offset(); if (offset[0] > 32767) { offset[0] = 32767; } else if (offset[0] < -32768) { offset[0] = -32768; } if (offset[1] > 32767) { offset[1] = 32767; } else if (offset[1] < -32768) { offset[1] = -32768; } skew.offset = offset; } else { domStyle.filter = matrix.toFilter(); domStyle.left = Math.min( matrix.x(bbox.x, bbox.y), matrix.x(bbox.x + bbox.width, bbox.y), matrix.x(bbox.x, bbox.y + bbox.height), matrix.x(bbox.x + bbox.width, bbox.y + bbox.height)) + 'px'; domStyle.top = Math.min( matrix.y(bbox.x, bbox.y), matrix.y(bbox.x + bbox.width, bbox.y), matrix.y(bbox.x, bbox.y + bbox.height), matrix.y(bbox.x + bbox.width, bbox.y + bbox.height)) + 'px'; } }, createItem: function (config) { return Ext.create('Ext.draw.Sprite', config); }, getRegion: function () { return this.el.getRegion(); }, addCls: function (sprite, className) { if (sprite && sprite.el) { sprite.el.addCls(className); } }, removeCls: function (sprite, className) { if (sprite && sprite.el) { sprite.el.removeCls(className); } }, /** * Adds a definition to this Surface for a linear gradient. We convert the gradient definition * to its corresponding VML attributes and store it for later use by individual sprites. * @param {Object} gradient */ addGradient: function (gradient) { var gradients = this.gradientsColl || (this.gradientsColl = Ext.create('Ext.util.MixedCollection')), colors = [], stops = Ext.create('Ext.util.MixedCollection'), keys, items, iLen, key, item, i; // Build colors string stops.addAll(gradient.stops); stops.sortByKey("ASC", function (a, b) { a = parseInt(a, 10); b = parseInt(b, 10); return a > b ? 1 : (a < b ? -1 : 0); }); keys = stops.keys; items = stops.items; iLen = keys.length; for (i = 0; i < iLen; i++) { key = keys[i]; item = items[i]; colors.push(key + '% ' + item.color); } gradients.add(gradient.id, { colors: colors.join(","), angle: gradient.angle }); }, destroy: function () { var me = this; me.callParent(arguments); if (me.el) { me.el.remove(); } delete me.el; } });