From 7ec9326ce00d08f9d957981f2edff6df26f24a28 Mon Sep 17 00:00:00 2001 From: jinlin <jinlin> Date: 星期四, 26 九月 2024 13:25:02 +0800 Subject: [PATCH] 修改 --- web/public/SVGOrigin/Method-Draw-master/method-draw/src/svgcanvas.js | 1718 +++++++++++++++++++++++++++++----------------------------- 1 files changed, 859 insertions(+), 859 deletions(-) diff --git a/web/public/SVGOrigin/Method-Draw-master/method-draw/src/svgcanvas.js b/web/public/SVGOrigin/Method-Draw-master/method-draw/src/svgcanvas.js index 093f8ae..f0a4d9c 100644 --- a/web/public/SVGOrigin/Method-Draw-master/method-draw/src/svgcanvas.js +++ b/web/public/SVGOrigin/Method-Draw-master/method-draw/src/svgcanvas.js @@ -39,10 +39,10 @@ // This fixes $(...).attr() to work as expected with SVG elements. // Does not currently use *AttributeNS() since we rarely need that. - + // See http://api.jquery.com/attr/ for basic documentation of .attr() - - // Additional functionality: + + // Additional functionality: // - When getting attributes, a string that's a number is return as type number. // - If an array is supplied as first parameter, multiple values are returned // as an object with values for each given attributes @@ -72,7 +72,7 @@ obj[aname] = attr; } return obj; - + } else if(typeof key === "object") { // Setting attributes form object for(var v in key) { @@ -93,7 +93,7 @@ } return this; }; - + }()); // Class: SvgCanvas @@ -117,7 +117,7 @@ var curConfig = { show_outside_canvas: true, selectNew: true, - dimensions: [640, 480] + dimensions: [200, 200] }; // Update config with new one if given @@ -183,8 +183,8 @@ // Function: setIdPrefix // Changes the ID prefix to the given value // -// Parameters: -// p - String with the new prefix +// Parameters: +// p - String with the new prefix canvas.setIdPrefix = function(p) { idprefix = p; }; @@ -238,7 +238,7 @@ // Function: addSvgElementFromJson // Create a new SVG element based on the given object keys/values and add it to the current layer -// The element will be ran through cleanupElement before being returned +// The element will be ran through cleanupElement before being returned // // Parameters: // data - Object with the following keys/values: @@ -342,7 +342,7 @@ var elems = cmd.elements(); canvas.pathActions.clear(); call("changed", elems); - + var cmdType = cmd.type(); var isApply = (eventType == EventTypes.AFTER_APPLY); if (cmdType == MoveElementCommand.type()) { @@ -360,7 +360,7 @@ } else { if (!isApply) restoreRefElems(cmd.elem); } - + if(cmd.elem.tagName === 'use') { setUseData(cmd.elem); } @@ -374,8 +374,8 @@ if (values["stdDeviation"]) { canvas.setBlurOffsets(cmd.elem.parentNode, values["stdDeviation"]); } - - // Remove & Re-add hack for Webkit (issue 775) + + // Remove & Re-add hack for Webkit (issue 775) //if(cmd.elem.tagName === 'use' && svgedit.browser.isWebkit()) { // var elem = cmd.elem; // if(!elem.getAttribute('x') && !elem.getAttribute('y')) { @@ -462,9 +462,9 @@ } } } - + var childs = elem.getElementsByTagName('*'); - + if(childs.length) { for(var i = 0, l = childs.length; i < l; i++) { restoreRefElems(childs[i]); @@ -484,55 +484,55 @@ // Object to contain image data for raster images that were found encodable var encodableImages = {}, - + // String with image URL of last loadable image last_good_img_url = curConfig.imgPath + 'logo.png', - + // Array with current disabled elements (for in-group editing) disabled_elems = [], - + // Object with save options save_options = {round_digits: 5}, - + // Boolean indicating whether or not a draw action has been started started = false, - + // String with an element's initial transform attribute value start_transform = null, - + // String indicating the current editor mode current_mode = "select", - + // String with the current direction in which an element is being resized current_resize_mode = "none", - + // Object with IDs for imported files, to see if one was already added import_ids = {}; // Current text style properties var cur_text = all_properties.text, - + // Current general properties cur_properties = cur_shape, - + // Array with selected elements' Bounding box object // selectedBBoxes = new Array(1), - + // The DOM element that was just selected justSelected = null, - + // DOM element for selection rectangle drawn by the user rubberBox = null, - + // Array of current BBoxes (still needed?) curBBoxes = [], - + // Object to contain all included extensions extensions = {}, - + // Canvas point for the most recent right click lastClickPoint = null, - + // Map of deleted reference elements removedElements = {} @@ -558,14 +558,14 @@ // Function: addExtension // Add an extension to the editor -// +// // Parameters: // name - String with the ID of the extension // ext_func - Function supplied by the extension with its data this.addExtension = function(name, ext_func) { if(!(name in extensions)) { // Provide private vars/funcs here. Is there a better way to do this? - + if($.isFunction(ext_func)) { var ext = ext_func($.extend(canvas.getPrivateMethods(), { svgroot: svgroot, @@ -582,7 +582,7 @@ console.log('Cannot add extension "' + name + '", an extension by that name already exists"'); } }; - + // This method rounds the incoming value to the nearest value based on the current_zoom var round = this.round = function(val) { return parseInt(val*current_zoom)/current_zoom; @@ -590,10 +590,10 @@ // This method sends back an array or a NodeList full of elements that // intersect the multi-select rubber-band-box on the current_layer only. -// -// Since the only browser that supports the SVG DOM getIntersectionList is Opera, +// +// Since the only browser that supports the SVG DOM getIntersectionList is Opera, // we need to provide an implementation here. We brute-force it for now. -// +// // Reference: // Firefox does not implement getIntersectionList(), see https://bugzilla.mozilla.org/show_bug.cgi?id=501421 // Webkit does not implement getIntersectionList(), see https://bugs.webkit.org/show_bug.cgi?id=11274 @@ -601,12 +601,12 @@ if (rubberBox == null) { return null; } var parent = current_group || getCurrentDrawing().getCurrentLayer(); - + if(!curBBoxes.length) { // Cache all bboxes curBBoxes = getVisibleElementsAndBBoxes(parent); } - + var resultList = null; try { resultList = parent.getIntersectionList(rect, null); @@ -614,16 +614,16 @@ if (resultList == null || typeof(resultList.item) != "function") { resultList = []; - + if(!rect) { var rubberBBox = rubberBox.getBBox(); var bb = {}; - + for(var o in rubberBBox) { bb[o] = rubberBBox[o] / current_zoom; } rubberBBox = bb; - + } else { var rubberBBox = rect; } @@ -635,8 +635,8 @@ } } } - // addToSelection expects an array, but it's ok to pass a NodeList - // because using square-bracket notation is allowed: + // addToSelection expects an array, but it's ok to pass a NodeList + // because using square-bracket notation is allowed: // http://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html return resultList; }; @@ -644,34 +644,34 @@ // TODO(codedread): Migrate this into svgutils.js // Function: getStrokedBBox // Get the bounding box for one or more stroked and/or transformed elements -// +// // Parameters: // elems - Array with DOM elements to check -// +// // Returns: // A single bounding box object getStrokedBBox = this.getStrokedBBox = function(elems) { if(!elems) elems = getVisibleElements(); if(!elems.length) return false; - + // Make sure the expected BBox is returned if the element is a group var getCheckedBBox = function(elem) { - + try { // TODO: Fix issue with rotated groups. Currently they work // fine in FF, but not in other browsers (same problem mentioned // in Issue 339 comment #2). - + var bb = svgedit.utilities.getBBox(elem); - + var angle = svgedit.utilities.getRotationAngle(elem); if ((angle && angle % 90) || svgedit.math.hasMatrixTransform(svgedit.transformlist.getTransformList(elem))) { // Accurate way to get BBox of rotated element in Firefox: // Put element in group and get its BBox - + var good_bb = false; - + // Get the BBox from the raw path for these elements var elemNames = ['ellipse','path','line','polyline','polygon']; if(elemNames.indexOf(elem.tagName) >= 0) { @@ -684,10 +684,10 @@ bb = good_bb = canvas.convertToPath(elem, true); } } - + if(!good_bb) { // Must use clone else FF freaks out - var clone = elem.cloneNode(true); + var clone = elem.cloneNode(true); var g = document.createElementNS(svgns, "g"); var parent = elem.parentNode; parent.appendChild(g); @@ -695,17 +695,17 @@ bb = svgedit.utilities.bboxToObj(g.getBBox()); parent.removeChild(g); } - + // Old method: Works by giving the rotated BBox, // this is (unfortunately) what Opera and Safari do // natively when getting the BBox of the parent group // var angle = angle * Math.PI / 180.0; -// var rminx = Number.MAX_VALUE, rminy = Number.MAX_VALUE, +// var rminx = Number.MAX_VALUE, rminy = Number.MAX_VALUE, // rmaxx = Number.MIN_VALUE, rmaxy = Number.MIN_VALUE; // var cx = round(bb.x + bb.width/2), // cy = round(bb.y + bb.height/2); -// var pts = [ [bb.x - cx, bb.y - cy], +// var pts = [ [bb.x - cx, bb.y - cy], // [bb.x + bb.width - cx, bb.y - cy], // [bb.x + bb.width - cx, bb.y + bb.height - cy], // [bb.x - cx, bb.y + bb.height - cy] ]; @@ -717,23 +717,23 @@ // var theta = Math.atan2(y,x) + angle; // x = round(r * Math.cos(theta) + cx); // y = round(r * Math.sin(theta) + cy); -// +// // // now set the bbox for the shape after it's been rotated // if (x < rminx) rminx = x; // if (y < rminy) rminy = y; // if (x > rmaxx) rmaxx = x; // if (y > rmaxy) rmaxy = y; // } -// +// // bb.x = rminx; // bb.y = rminy; // bb.width = rmaxx - rminx; // bb.height = rmaxy - rminy; } return bb; - } catch(e) { + } catch(e) { console.log(elem, e); - } + } }; var full_bb; @@ -742,18 +742,18 @@ if(!this.parentNode) return; full_bb = getCheckedBBox(this); }); - + // This shouldn't ever happen... if(full_bb == null) return null; - + // full_bb doesn't include the stoke, so this does no good! // if(elems.length == 1) return full_bb; - + var max_x = full_bb.x + full_bb.width; var max_y = full_bb.y + full_bb.height; var min_x = full_bb.x; var min_y = full_bb.y; - + // FIXME: same re-creation problem with this function as getCheckedBBox() above var getOffset = function(elem) { var sw = elem.getAttribute("stroke-width"); @@ -773,10 +773,10 @@ bboxes.push(cur_bb); } }); - + full_bb.x = min_x; full_bb.y = min_y; - + $.each(elems, function(i, elem) { var cur_bb = bboxes[i]; // ensure that elem is really an element node @@ -786,7 +786,7 @@ max_y = Math.max(max_y, cur_bb.y + cur_bb.height + offset); } }); - + full_bb.width = max_x - min_x; full_bb.height = max_y - min_y; return full_bb; @@ -830,7 +830,7 @@ // * bbox - The element's BBox as retrieved from getStrokedBBox var getVisibleElementsAndBBoxes = this.getVisibleElementsAndBBoxes = function(parent) { if(!parent) parent = $(svgcontent).children(); // Prevent layers from being included - + var contentElems = []; $(parent).children().each(function(i, elem) { try { @@ -870,7 +870,7 @@ new_el.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.nodeValue); } }); - + // Opera's "d" value needs to be reset for Opera/Win/non-EN // Also needed for webkit (else does not keep curved segments on clone) if(svgedit.browser.isWebkit() && el.nodeName == 'path') { @@ -891,7 +891,7 @@ break; } }); - + if($(el).data('gsvg')) { $(new_el).data('gsvg', new_el.firstChild); } else if($(el).data('symbol')) { @@ -915,7 +915,7 @@ getId = c.getId = function() { return getCurrentDrawing().getId(); }; getNextId = c.getNextId = function() { return getCurrentDrawing().getNextId(); }; - + // Function: call // Run the callback function associated with the given event // @@ -927,14 +927,14 @@ return events[event](this, arg); } }; - + // Function: bind // Attaches a callback function to an event // // Parameters: // event - String indicating the name of the event // f - The callback function to bind to the event - // + // // Return: // The previous event c.bind = function(event, f) { @@ -942,7 +942,7 @@ events[event] = f; return old; }; - + }(canvas)); // Function: canvas.prepareSvg @@ -972,13 +972,13 @@ } // Function: ffClone -// Hack for Firefox bugs where text element features aren't updated or get +// Hack for Firefox bugs where text element features aren't updated or get // messed up. See issue 136 and issue 137. -// This function clones the element and re-selects it -// TODO: Test for this bug on load and add it to "support" object instead of +// This function clones the element and re-selects it +// TODO: Test for this bug on load and add it to "support" object instead of // browser sniffing // -// Parameters: +// Parameters: // elem - The (text) DOM element to clone var ffClone = function(elem) { if(!svgedit.browser.isGecko()) return elem; @@ -1016,7 +1016,7 @@ var bbox = svgedit.utilities.getBBox(elem); var cx = bbox.x+bbox.width/2, cy = bbox.y+bbox.height/2; var tlist = getTransformList(elem); - + // only remove the real rotational transform if present (i.e. at index=0) if (tlist.numberOfItems > 0) { var xform = tlist.getItem(0); @@ -1038,7 +1038,7 @@ else if (tlist.numberOfItems == 0) { elem.removeAttribute("transform"); } - + if (!preventUndo) { // we need to undo it, then redo it so it can be undo-able! :) // TODO: figure out how to make changes to transform list undo-able cross-browser? @@ -1057,7 +1057,7 @@ }; // Function: recalculateAllSelectedDimensions -// Runs recalculateDimensions on the selected elements, +// Runs recalculateDimensions on the selected elements, // adding the changes to a single batch command var recalculateAllSelectedDimensions = this.recalculateAllSelectedDimensions = function() { var text = (current_resize_mode == "none" ? "position" : "size"); @@ -1080,9 +1080,9 @@ }; // this is how we map paths to our preferred relative segment types -var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a', +var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a', 'H', 'h', 'V', 'v', 'S', 's', 'T', 't']; - + // Debug tool to easily see the current matrix in the browser's console var logMatrix = function(m) { console.log([m.a,m.b,m.c,m.d,m.e,m.f]); @@ -1106,7 +1106,7 @@ assignAttributes(selected, changes, 1000, true); } box = svgedit.utilities.getBBox(selected); - + for(var i = 0; i < 2; i++) { var type = i === 0 ? 'fill' : 'stroke'; var attrVal = selected.getAttribute(type); @@ -1114,15 +1114,15 @@ if(m.a < 0 || m.d < 0) { var grad = getRefElem(attrVal); var newgrad = grad.cloneNode(true); - + if(m.a < 0) { //flip x var x1 = newgrad.getAttribute('x1'); var x2 = newgrad.getAttribute('x2'); newgrad.setAttribute('x1', -(x1 - 1)); newgrad.setAttribute('x2', -(x2 - 1)); - } - + } + if(m.d < 0) { //flip y var y1 = newgrad.getAttribute('y1'); @@ -1134,7 +1134,7 @@ findDefs().appendChild(newgrad); selected.setAttribute(type, 'url(#' + newgrad.id + ')'); } - + // Not really working :( // if(selected.tagName === 'path') { // reorientGrads(selected, m); @@ -1146,8 +1146,8 @@ var elName = selected.tagName; if(elName === "g" || elName === "text" || elName === "use") { // if it was a translate, then just update x,y - if (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && - (m.e != 0 || m.f != 0) ) + if (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && + (m.e != 0 || m.f != 0) ) { // [T][M] = [M][T'] // therefore [T'] = [M_inv][T][M] @@ -1165,7 +1165,7 @@ chlist.appendItem(mt); } } - + // now we have a set of changes and an applied reduced transform list // we apply the changes directly to the DOM switch (elName) @@ -1173,7 +1173,7 @@ case "foreignObject": case "rect": case "image": - + // Allow images to be inverted (give them matrix when flipped) if(elName === 'image' && (m.a < 0 || m.d < 0)) { // Convert to matrix @@ -1184,10 +1184,10 @@ chlist.appendItem(mt); } else { var pt1 = remap(changes.x,changes.y); - + changes.width = scalew(changes.width); changes.height = scaleh(changes.height); - + changes.x = pt1.x + Math.min(0,changes.width); changes.y = pt1.y + Math.min(0,changes.height); changes.width = Math.abs(changes.width); @@ -1201,7 +1201,7 @@ changes.cy = c.y; changes.rx = scalew(changes.rx); changes.ry = scaleh(changes.ry); - + changes.rx = Math.abs(changes.rx); changes.ry = Math.abs(changes.ry); finishUp(); @@ -1225,7 +1225,7 @@ changes.y1 = pt1.y; changes.x2 = pt2.x; changes.y2 = pt2.y; - + case "text": var tspan = selected.querySelectorAll('tspan'); var i = tspan.length @@ -1272,7 +1272,7 @@ selected.setAttribute("points", pstr); break; case "path": - + var segList = selected.pathSegList; var len = segList.numberOfItems; changes.d = new Array(len); @@ -1293,7 +1293,7 @@ sweepFlag: seg.sweepFlag }; } - + var len = changes.d.length, firstseg = changes.d[0], currentpt = remap(firstseg.x,firstseg.y); @@ -1330,7 +1330,7 @@ seg.r2 = scaleh(seg.r2); } } // for each segment - + var dstr = ""; var len = changes.d.length; for (var i = 0; i < len; ++i) { @@ -1359,7 +1359,7 @@ dstr += seg.x1 + "," + seg.y1 + " " + seg.x2 + "," + seg.y2 + " " + seg.x + "," + seg.y + " "; break; - case 9: // relative quad (q) + case 9: // relative quad (q) case 8: // absolute quad (Q) dstr += seg.x1 + "," + seg.y1 + " " + seg.x + "," + seg.y + " "; break; @@ -1389,14 +1389,14 @@ // ty - The translation's y value var updateClipPath = function(attr, tx, ty) { var path = getRefElem(attr).firstChild; - + var cp_xform = getTransformList(path); - + var newxlate = svgroot.createSVGTransform(); newxlate.setTranslate(tx, ty); cp_xform.appendItem(newxlate); - + // Update clipPath's dimensions recalculateDimensions(path); } @@ -1407,13 +1407,13 @@ // Parameters: // selected - The DOM element to recalculate // -// Returns: +// Returns: // Undo command object with the resulting change var recalculateDimensions = this.recalculateDimensions = function(selected) { if (selected == null) return null; - + var tlist = getTransformList(selected); - + // remove any unnecessary transforms if (tlist && tlist.numberOfItems > 0) { var k = tlist.numberOfItems; @@ -1438,13 +1438,13 @@ // End here if all it has is a rotation if(tlist.numberOfItems === 1 && getRotationAngle(selected)) return null; } - + // if this element had no transforms, we are done if (!tlist || tlist.numberOfItems == 0) { selected.removeAttribute("transform"); return null; } - + // TODO: Make this work for more than 2 if (tlist) { var k = tlist.numberOfItems; @@ -1463,23 +1463,23 @@ tlist.removeItem(mxs[1][1]); tlist.insertItemBefore(m_new, mxs[1][1]); } - + // combine matrix + translate k = tlist.numberOfItems; if(k >= 2 && tlist.getItem(k-2).type === 1 && tlist.getItem(k-1).type === 2) { var mt = svgroot.createSVGTransform(); - + var m = matrixMultiply( - tlist.getItem(k-2).matrix, + tlist.getItem(k-2).matrix, tlist.getItem(k-1).matrix - ); + ); mt.setMatrix(m); tlist.removeItem(k-2); tlist.removeItem(k-2); tlist.appendItem(mt); } } - + // If it still has a single [M] or [R][M], return null too (prevents BatchCommand from being returned). switch ( selected.tagName ) { // Ignore these elements, as they can absorb the [M] @@ -1496,13 +1496,13 @@ return null; } } - - // Grouped SVG element + + // Grouped SVG element var gsvg = $(selected).data('gsvg'); - - // we know we have some transforms, so set up return variable + + // we know we have some transforms, so set up return variable var batchCmd = new BatchCommand("Transform"); - + // store initial values that will be affected by reducing the transform list var changes = {}, initial = null, attrs = []; switch (selected.tagName) @@ -1544,7 +1544,7 @@ changes["d"] = selected.getAttribute("d"); break; } // switch on element type to get initial values - + if(attrs.length) { changes = $(selected).attr(attrs); $.each(changes, function(attr, val) { @@ -1557,8 +1557,8 @@ y: $(gsvg).attr('y') || 0 }; } - - // if we haven't created an initial array in polygon/polyline/path, then + + // if we haven't created an initial array in polygon/polyline/path, then // make a copy of initial values and include the transform if (initial == null) { initial = $.extend(true, {}, changes); @@ -1568,7 +1568,7 @@ } // save the start transform value too initial["transform"] = start_transform ? start_transform : ""; - + // if it's a regular group, we have special processing to flatten transforms if ((selected.tagName == "g" && !gsvg) || selected.tagName == "a") { var box = svgedit.utilities.getBBox(selected), @@ -1576,8 +1576,8 @@ newcenter = transformPoint(box.x+box.width/2, box.y+box.height/2, transformListToTransform(tlist).matrix), m = svgroot.createSVGMatrix(); - - + + // temporarily strip off the rotate and save the old center var gangle = getRotationAngle(selected); if (gangle) { @@ -1609,17 +1609,17 @@ } // first, if it was a scale then the second-last transform will be it - if (N >= 3 && tlist.getItem(N-2).type == 3 && - tlist.getItem(N-3).type == 2 && tlist.getItem(N-1).type == 2) + if (N >= 3 && tlist.getItem(N-2).type == 3 && + tlist.getItem(N-3).type == 2 && tlist.getItem(N-1).type == 2) { operation = 3; // scale - + // if the children are unrotated, pass the scale down directly // otherwise pass the equivalent matrix() down directly var tm = tlist.getItem(N-3).matrix, sm = tlist.getItem(N-2).matrix, tmn = tlist.getItem(N-1).matrix; - + var children = selected.childNodes; var c = children.length; while (c--) { @@ -1649,7 +1649,7 @@ // childTlist.appendItem(translateOrigin); // } // } - + var angle = getRotationAngle(child); var old_start_transform = start_transform; var childxforms = []; @@ -1664,10 +1664,10 @@ // if not rotated or skewed, push the [T][S][-T] down to the child else { // update the transform list with translate,scale,translate - + // slide the [T][S][-T] from the front to the back // [T][S][-T][M] = [M][T2][S2][-T2] - + // (only bringing [-T] to the right of [M]) // [T][S][-T][M] = [T][S][M][-T2] // [-T2] = [M_inv][-T][M] @@ -1676,7 +1676,7 @@ var t2 = svgroot.createSVGMatrix(); t2.e = -t2n.e; t2.f = -t2n.f; - + // [T][S][-T][M] = [M][T2][S2][-T2] // [S2] = [T2_inv][M_inv][T][S][-T][M][-T2_inv] var s2 = matrixMultiply(t2.inverse(), m.inverse(), tm, sm, tmn, m, t2n.inverse()); @@ -1697,8 +1697,8 @@ // logMatrix(scale.matrix); } // not rotated batchCmd.addSubCommand( recalculateDimensions(child) ); - // TODO: If any <use> have this group as a parent and are - // referencing this child, then we need to impose a reverse + // TODO: If any <use> have this group as a parent and are + // referencing this child, then we need to impose a reverse // scale on it so that when it won't get double-translated // var uses = selected.getElementsByTagNameNS(svgns, "use"); // var href = "#"+child.id; @@ -1728,19 +1728,19 @@ e2t.setMatrix(m); tlist.clear(); tlist.appendItem(e2t); - } - // next, check if the first transform was a translate + } + // next, check if the first transform was a translate // if we had [ T1 ] [ M ] we want to transform this into [ M ] [ T2 ] // therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ] - else if ( (N == 1 || (N > 1 && tlist.getItem(1).type != 3)) && - tlist.getItem(0).type == 2) + else if ( (N == 1 || (N > 1 && tlist.getItem(1).type != 3)) && + tlist.getItem(0).type == 2) { operation = 2; // translate var T_M = transformListToTransform(tlist).matrix; tlist.removeItem(0); var M_inv = transformListToTransform(tlist).matrix.inverse(); var M2 = matrixMultiply( M_inv, T_M ); - + tx = M2.e; ty = M2.f; @@ -1748,13 +1748,13 @@ // we pass the translates down to the individual children var children = selected.childNodes; var c = children.length; - + var clipPaths_done = []; - + while (c--) { var child = children.item(c); if (child.nodeType == 1) { - + // Check if child has clip-path if(child.getAttribute('clip-path')) { // tx, ty @@ -1762,12 +1762,12 @@ if(clipPaths_done.indexOf(attr) === -1) { updateClipPath(attr, tx, ty); clipPaths_done.push(attr); - } + } } var old_start_transform = start_transform; start_transform = child.getAttribute("transform"); - + var childTlist = getTransformList(child); // some children might not have a transform (<metadata>, <defs>, etc) if (childTlist) { @@ -1779,7 +1779,7 @@ childTlist.appendItem(newxlate); } batchCmd.addSubCommand( recalculateDimensions(child) ); - // If any <use> have this group as a parent and are + // If any <use> have this group as a parent and are // referencing this child, then impose a reverse translate on it // so that when it won't get double-translated var uses = selected.getElementsByTagNameNS(svgns, "use"); @@ -1798,9 +1798,9 @@ } } } - + clipPaths_done = []; - + start_transform = old_start_transform; } } @@ -1817,18 +1817,18 @@ var old_start_transform = start_transform; start_transform = child.getAttribute("transform"); var childTlist = getTransformList(child); - + if (!childTlist) continue; - + var em = matrixMultiply(m, transformListToTransform(childTlist).matrix); var e2m = svgroot.createSVGTransform(); e2m.setMatrix(em); childTlist.clear(); childTlist.appendItem(e2m,0); - + batchCmd.addSubCommand( recalculateDimensions(child) ); start_transform = old_start_transform; - + // Convert stroke // TODO: Find out if this should actually happen somewhere else var sw = child.getAttribute("stroke-width"); @@ -1855,9 +1855,9 @@ if (tlist.numberOfItems == 0) { selected.removeAttribute("transform"); } - return null; + return null; } - + // if it was a translate, put back the rotate at the new center if (operation == 2) { if (gangle) { @@ -1865,7 +1865,7 @@ x: oldcenter.x + first_m.e, y: oldcenter.y + first_m.f }; - + var newRot = svgroot.createSVGTransform(); newRot.setRotate(gangle,newcenter.x,newcenter.y); if(tlist.numberOfItems) { @@ -1914,7 +1914,7 @@ } } } - + if (gangle) { if(tlist.numberOfItems) { tlist.insertItemBefore(rnew, 0); @@ -1934,9 +1934,9 @@ // but we still may need to recalculate them (see issue 595). // TODO: Figure out how to get BBox from these elements in case they // have a rotation transform - + if(!box && selected.tagName != 'path') return null; - + var m = svgroot.createSVGMatrix(), // temporarily strip off the rotate and save the old center @@ -1945,7 +1945,7 @@ var oldcenter = {x: box.x+box.width/2, y: box.y+box.height/2}, newcenter = transformPoint(box.x+box.width/2, box.y+box.height/2, transformListToTransform(tlist).matrix); - + var a = angle * Math.PI / 180; if ( Math.abs(a) > (1.0e-10) ) { var s = Math.sin(a)/(1 - Math.cos(a)); @@ -1965,11 +1965,11 @@ } } } - + // 2 = translate, 3 = scale, 4 = rotate, 1 = matrix imposition var operation = 0; var N = tlist.numberOfItems; - + // Check if it has a gradient with userSpaceOnUse, in which case // adjust it by recalculating the matrix transform. // TODO: Make this work in Webkit using svgedit.transformlist.SVGTransformList @@ -1992,14 +1992,14 @@ } } - // first, if it was a scale of a non-skewed element, then the second-last + // first, if it was a scale of a non-skewed element, then the second-last // transform will be the [S] // if we had [M][T][S][T] we want to extract the matrix equivalent of // [T][S][T] and push it down to the element - if (N >= 3 && tlist.getItem(N-2).type == 3 && - tlist.getItem(N-3).type == 2 && tlist.getItem(N-1).type == 2) - - // Removed this so a <use> with a given [T][S][T] would convert to a matrix. + if (N >= 3 && tlist.getItem(N-2).type == 3 && + tlist.getItem(N-3).type == 2 && tlist.getItem(N-1).type == 2) + + // Removed this so a <use> with a given [T][S][T] would convert to a matrix. // Is that bad? // && selected.nodeName != "use" { @@ -2019,12 +2019,12 @@ tlist.appendItem(e2t); // reset the matrix so that the element is not re-mapped m = svgroot.createSVGMatrix(); - } // if we had [R][T][S][-T][M], then this was a rotated matrix-element + } // if we had [R][T][S][-T][M], then this was a rotated matrix-element // if we had [T1][M] we want to transform this into [M][T2] - // therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ] and we can push [T2] + // therefore [ T2 ] = [ M_inv ] [ T1 ] [ M ] and we can push [T2] // down to the element - else if ( (N == 1 || (N > 1 && tlist.getItem(1).type != 3)) && - tlist.getItem(0).type == 2) + else if ( (N == 1 || (N > 1 && tlist.getItem(1).type != 3)) && + tlist.getItem(0).type == 2) { operation = 2; // translate var oldxlate = tlist.getItem(0).matrix, @@ -2069,7 +2069,7 @@ if (angle) { var newRot = svgroot.createSVGTransform(); newRot.setRotate(angle,newcenter.x,newcenter.y); - + if(tlist.numberOfItems) { tlist.insertItemBefore(newRot, 0); } else { @@ -2081,12 +2081,12 @@ } return null; } - + // if it was a translate or resize, we need to remap the element and absorb the xform if (operation == 1 || operation == 2 || operation == 3) { remapElement(selected,changes,m); } // if we are remapping - + // if it was a translate, put back the rotate at the new center if (operation == 2) { if (angle) { @@ -2119,7 +2119,7 @@ var rnew_inv = rnew.matrix.inverse(); var m_inv = m.inverse(); var extrat = matrixMultiply(m_inv, rnew_inv, rold, m); - + remapElement(selected,changes,extrat); if (angle) { if(tlist.numberOfItems) { @@ -2135,9 +2135,9 @@ if (tlist.numberOfItems == 0) { selected.removeAttribute("transform"); } - + batchCmd.addSubCommand(new ChangeElementCommand(selected, initial)); - + return batchCmd; }; @@ -2148,7 +2148,7 @@ // Function: clearSelection // Clears the selection. The 'selected' handler is then called. -// Parameters: +// Parameters: // noCall - Optional boolean that when true does not call the "selected" handler var clearSelection = this.clearSelection = function(noCall) { if (selectedElements[0] != null) { @@ -2177,9 +2177,9 @@ if (elemsToAdd.length == 0) { return; } // find the first null in our selectedElements array var j = 0; - + while (j < selectedElements.length) { - if (selectedElements[j] == null) { + if (selectedElements[j] == null) { break; } ++j; @@ -2192,7 +2192,7 @@ if (!elem || !svgedit.utilities.getBBox(elem)) continue; if(elem.tagName === 'a' && elem.childNodes.length === 1) { - // Make "a" element's child be the selected element + // Make "a" element's child be the selected element elem = elem.firstChild; } @@ -2205,7 +2205,7 @@ // if (j == 0) selectedBBoxes[0] = svgedit.utilities.getBBox(elem); j++; var sel = selectorManager.requestSelector(elem); - + if (selectedElements.length > 1) { sel.showGrips(false); } @@ -2220,12 +2220,12 @@ selectedElements.sort(function(a,b) { if(a && b && a.compareDocumentPosition) { - return 3 - (b.compareDocumentPosition(a) & 6); + return 3 - (b.compareDocumentPosition(a) & 6); } else if(a == null) { return 1; } }); - + // Make sure first elements are not null while(selectedElements[0] == null) selectedElements.shift(0); }; @@ -2285,10 +2285,10 @@ // Function: getMouseTarget // Gets the desired element from a mouse event -// +// // Parameters: // evt - Event object from the mouse event -// +// // Returns: // DOM element we want var getMouseTarget = this.getMouseTarget = function(evt) { @@ -2296,33 +2296,33 @@ return null; } var mouse_target = evt.target; - + // if it was a <use>, Opera and WebKit return the SVGElementInstance if (mouse_target.correspondingUseElement) mouse_target = mouse_target.correspondingUseElement; - + // for foreign content, go up until we find the foreignObject - // WebKit browsers set the mouse target to the svgcanvas div - if ([mathns, htmlns].indexOf(mouse_target.namespaceURI) >= 0 && - mouse_target.id != "svgcanvas") + // WebKit browsers set the mouse target to the svgcanvas div + if ([mathns, htmlns].indexOf(mouse_target.namespaceURI) >= 0 && + mouse_target.id != "svgcanvas") { while (mouse_target.nodeName != "foreignObject") { mouse_target = mouse_target.parentNode; if(!mouse_target) return svgroot; } } - + // Get the desired mouse_target with jQuery selector-fu // If it's root-like, select the root var current_layer = getCurrentDrawing().getCurrentLayer(); if([svgroot, container, svgcontent, current_layer].indexOf(mouse_target) >= 0) { return svgroot; } - + var $target = $(mouse_target); // If it's a selection grip, return the grip parent if($target.closest('#selectorParentGroup').length) { - // While we could instead have just returned mouse_target, + // While we could instead have just returned mouse_target, // this makes it easier to indentify as being a selector grip return selectorManager.selectorParentGroup; } @@ -2330,8 +2330,8 @@ while (mouse_target.parentNode && mouse_target.parentNode !== (current_group || current_layer)) { mouse_target = mouse_target.parentNode; } - -// + +// // // go up until we hit a child of a layer // while (mouse_target.parentNode.parentNode.tagName == 'g') { // mouse_target = mouse_target.parentNode; @@ -2341,7 +2341,7 @@ // if (mouse_target.nodeName.toLowerCase() == "div") { // mouse_target = svgroot; // } - + return mouse_target; }; @@ -2359,7 +2359,7 @@ maxx: null, maxy: null }; - + // - when we are in a create mode, the element is added to the canvas // but the action is not recorded until mousing up // - when we are in select mode, select the element, remember the position @@ -2374,7 +2374,7 @@ var pt = transformPoint( evt.pageX, evt.pageY, root_sctm ), mouse_x = pt.x * current_zoom, mouse_y = pt.y * current_zoom; - + evt.preventDefault(); @@ -2382,15 +2382,15 @@ current_mode = "select"; lastClickPoint = pt; } - + var x = mouse_x / current_zoom, y = mouse_y / current_zoom, mouse_target = getMouseTarget(evt); - + if(mouse_target.tagName === 'a' && mouse_target.childNodes.length === 1) { mouse_target = mouse_target.firstChild; } - + // real_x/y ignores grid-snap value var real_x = r_start_x = start_x = x; var real_y = r_start_y = start_y = y; @@ -2402,9 +2402,9 @@ start_y = snapToGrid(start_y); } - // if it is a selector grip, then it must be a single element selected, + // if it is a selector grip, then it must be a single element selected, // set the mouse_target to that and update the mode to rotate/resize - + if (mouse_target == selectorManager.selectorParentGroup && selectedElements[0] != null) { var grip = evt.target; var griptype = elData(grip, "type"); @@ -2420,7 +2420,7 @@ } mouse_target = selectedElements[0]; } - + start_transform = mouse_target.getAttribute("transform"); var tlist = getTransformList(mouse_target); switch (current_mode) { @@ -2428,11 +2428,11 @@ started = true; current_resize_mode = "none"; if(right_click) started = false; - + if (mouse_target != svgroot) { // if this element is not yet selected, clear selection and select it if (selectedElements.indexOf(mouse_target) == -1) { - // only clear selection if shift is not pressed (otherwise, add + // only clear selection if shift is not pressed (otherwise, add // element to selection) if (!evt.shiftKey) { // No need to do the call here as it will be done on addToSelection @@ -2443,7 +2443,7 @@ pathActions.clear(); } // else if it's a path, go into pathedit mode in mouseup - + if(!right_click) { // insert a dummy transform so if the element(s) are moved it will have // a transform to use for its translate @@ -2466,11 +2466,11 @@ } r_start_x *= current_zoom; r_start_y *= current_zoom; -// console.log('p',[evt.pageX, evt.pageY]); -// console.log('c',[evt.clientX, evt.clientY]); -// console.log('o',[evt.offsetX, evt.offsetY]); +// console.log('p',[evt.pageX, evt.pageY]); +// console.log('c',[evt.clientX, evt.clientY]); +// console.log('o',[evt.offsetX, evt.offsetY]); // console.log('s',[start_x, start_y]); - + assignAttributes(rubberBox, { 'x': r_start_x, 'y': r_start_y, @@ -2480,7 +2480,7 @@ }, 100); } break; - case "zoom": + case "zoom": started = true; if (rubberBox == null) { rubberBox = selectorManager.getRubberBandBox(); @@ -2497,7 +2497,7 @@ started = true; start_x = x; start_y = y; - + // Getting the BBox from the selection box, since we know we // want to orient around it init_bbox = svgedit.utilities.getBBox($('#selectedBox0')[0]); @@ -2509,7 +2509,7 @@ // append three dummy transforms to the tlist so that // we can translate,scale,translate in mousemove var pos = getRotationAngle(mouse_target)?1:0; - + if(hasMatrixTransform(tlist)) { tlist.insertItemBefore(svgroot.createSVGTransform(), pos); tlist.insertItemBefore(svgroot.createSVGTransform(), pos); @@ -2518,7 +2518,7 @@ tlist.appendItem(svgroot.createSVGTransform()); tlist.appendItem(svgroot.createSVGTransform()); tlist.appendItem(svgroot.createSVGTransform()); - + if(svgedit.browser.supportsNonScalingStroke()) { //Handle crash for newer Webkit: https://code.google.com/p/svg-edit/issues/detail?id=904 //Chromium issue: https://code.google.com/p/chromium/issues/detail?id=114625 @@ -2701,27 +2701,27 @@ // This could occur in an extension break; } - + var ext_result = runExtensions("mouseDown", { event: evt, start_x: start_x, start_y: start_y, selectedElements: selectedElements }, true); - + $.each(ext_result, function(i, r) { if(r && r.started) { started = true; } }); if (current_mode) { - document.getElementById("workarea").className = + document.getElementById("workarea").className = (current_mode == "resize") ? evt.target.style.cursor : current_mode } }; - + // in this function we do not record any state changes yet (but we do update // any elements that are still being created, moved or resized on the canvas) var mouseMove = function(evt) { @@ -2743,23 +2743,23 @@ } evt.preventDefault(); - + switch (current_mode) { case "select": // we temporarily use a translate on the element(s) being dragged - // this transform is removed upon mousing up and the element is + // this transform is removed upon mousing up and the element is // relocated to the new location if (selectedElements[0] !== null) { var dx = x - start_x; var dy = y - start_y; - + if(curConfig.gridSnapping){ dx = snapToGrid(dx); dy = snapToGrid(dy); } - - if(evt.shiftKey) { + + if(evt.shiftKey) { var xya = snapToAngle(start_x,start_y,x,y); x=xya.x; y=xya.y; } if (dx != 0 || dy != 0) { @@ -2790,13 +2790,13 @@ } else { tlist.appendItem(xform); } - + // update our internal bbox that we're tracking while dragging selectorManager.requestSelector(selected).resize(); } //duplicate only once - // alt drag = create a clone and save the reference + // alt drag = create a clone and save the reference if(evt.altKey) { //clone doesn't exist yet if (!canvas.addClones) { @@ -2812,14 +2812,14 @@ window.addEventListener("keyup", canvas.removeClones) } } - + call("transition", selectedElements); } - - - + + + } break; case "multiselect": @@ -2839,7 +2839,7 @@ var elemsToRemove = [], elemsToAdd = [], newList = getIntersectionList(), len = selectedElements.length; - + for (var i = 0; i < len; ++i) { var ind = newList.indexOf(selectedElements[i]); if (ind == -1) { @@ -2849,16 +2849,16 @@ newList[ind] = null; } } - + len = newList.length; for (i = 0; i < len; ++i) { if (newList[i]) elemsToAdd.push(newList[i]); } - - if (elemsToRemove.length > 0) + + if (elemsToRemove.length > 0) canvas.removeFromSelection(elemsToRemove); - - if (elemsToAdd.length > 0) + + if (elemsToAdd.length > 0) addToSelection(elemsToAdd); - + break; case "resize": // we track the resize bounding box and translate/scale the selected element @@ -2866,10 +2866,10 @@ // the shape's coordinates var tlist = getTransformList(selected), hasMatrix = hasMatrixTransform(tlist), - box = hasMatrix ? init_bbox : svgedit.utilities.getBBox(selected), + box = hasMatrix ? init_bbox : svgedit.utilities.getBBox(selected), left=box.x, top=box.y, width=box.width, height=box.height, dx=(x-start_x), dy=(y-start_y); - + if(curConfig.gridSnapping){ dx = snapToGrid(dx); dy = snapToGrid(dy); @@ -2893,24 +2893,24 @@ } if(current_resize_mode.indexOf("e")==-1 && current_resize_mode.indexOf("w")==-1) { dx = 0; - } - + } + var ts = null, tx = 0, ty = 0, - sy = height ? (height+dy)/height : 1, + sy = height ? (height+dy)/height : 1, sx = width ? (width+dx)/width : 1; // if we are dragging on the north side, then adjust the scale factor and ty if(current_resize_mode.indexOf("n") >= 0) { sy = height ? (height-dy)/height : 1; ty = height; } - + // if we dragging on the east side, then adjust the scale factor and tx if(current_resize_mode.indexOf("w") >= 0) { sx = width ? (width-dx)/width : 1; tx = width; } - + // update the transform list with translate,scale,translate var translateOrigin = svgroot.createSVGTransform(), scale = svgroot.createSVGTransform(), @@ -2929,7 +2929,7 @@ else sy = sx; } scale.setScale(sx,sy); - + translateBack.setTranslate(left+tx,top+ty); if(hasMatrix) { var diff = angle?1:0; @@ -2944,9 +2944,9 @@ } selectorManager.requestSelector(selected).resize(); - + call("transition", selectedElements); - + break; case "zoom": real_x *= current_zoom; @@ -2956,7 +2956,7 @@ 'y': Math.min(r_start_y*current_zoom, real_y), 'width': Math.abs(real_x - r_start_x*current_zoom), 'height': Math.abs(real_y - r_start_y*current_zoom) - },100); + },100); break; case "text": assignAttributes(shape,{ @@ -2971,10 +2971,10 @@ } var x2 = x; - var y2 = y; + var y2 = y; if(evt.shiftKey) { var xya = snapToAngle(start_x,start_y,x2,y2); x2=xya.x; y2=xya.y; } - + shape.setAttributeNS(null, "x2", x2); shape.setAttributeNS(null, "y2", y2); break; @@ -2998,11 +2998,11 @@ } if (evt.altKey){ w *=2; - h *=2; + h *=2; new_x = start_x - w/2; new_y = start_y - h/2; } - + if(curConfig.gridSnapping){ w = snapToGrid(w); h = snapToGrid(h); @@ -3016,7 +3016,7 @@ 'x': new_x, 'y': new_y },1000); - + break; case "circle": var c = $(shape).attr(["cx", "cy"]); @@ -3042,7 +3042,7 @@ if (evt.shiftKey) { ry = rx cy = (y > start_y) ? start_y + rx : start_y - rx - + } if (evt.altKey) { cx = start_x @@ -3072,7 +3072,7 @@ case "pathedit": x *= current_zoom; y *= current_zoom; - + if(curConfig.gridSnapping){ x = snapToGrid(x); y = snapToGrid(y); @@ -3091,7 +3091,7 @@ var xya = snapToAngle(x1,y1,x,y); x=xya.x; y=xya.y; } - + if(rubberBox && rubberBox.getAttribute('display') !== 'none') { real_x *= current_zoom; real_y *= current_zoom; @@ -3100,10 +3100,10 @@ 'y': Math.min(r_start_y*current_zoom, real_y), 'width': Math.abs(real_x - r_start_x*current_zoom), 'height': Math.abs(real_y - r_start_y*current_zoom) - },100); + },100); } pathActions.mouseMove(evt, x, y); - + break; case "textedit": x *= current_zoom; @@ -3116,13 +3116,13 @@ // 'height': Math.abs(y-start_y) // },100); // } - + textActions.mouseMove(mouse_x, mouse_y); - + break; case "rotate": var box = svgedit.utilities.getBBox(selected), - cx = box.x + box.width/2, + cx = box.x + box.width/2, cy = box.y + box.height/2, m = getMatrix(selected), center = transformPoint(cx,cy,m); @@ -3150,7 +3150,7 @@ default: break; } - + runExtensions("mouseMove", { event: evt, mouse_x: mouse_x, @@ -3159,16 +3159,16 @@ }); }; // mouseMove() - - + + /* mouseover mode var mouseOver = function(evt) { - + if(canvas.spaceKey || evt.button === 1 || current_mode != "select") return; evt.stopPropagation(); mouse_target = getMouseTarget(evt); if (svghover.lastChild) svghover.removeChild(svghover.lastChild); - + if (mouse_target.id == "svgroot") return switch (mouse_target.nodeName) { case "polyline": @@ -3176,7 +3176,7 @@ case "path": case "ellipse": case "rect": - var clone = mouse_target.cloneNode(true); + var clone = mouse_target.cloneNode(true); clone.setAttribute("stroke", "#c00") clone.setAttribute("stroke-width", "1") clone.setAttribute("stroke-opacity", "1") @@ -3184,13 +3184,13 @@ clone.setAttribute("fill", "none") hover_group.appendChild(clone); break; - + default: break; } } */ - + // - in create mode, the element's opacity is set properly, we create an InsertElementCommand // and store it on the Undo stack // - in move/resize mode, the element's attributes which were affected by the move/resize are @@ -3256,7 +3256,7 @@ cur_text.font_family = selected.getAttribute("font-family"); } selectorManager.requestSelector(selected).showGrips(true); - + // This shouldn't be necessary as it was done on mouseDown... // call("selected", [selected]); } @@ -3264,8 +3264,8 @@ recalculateAllSelectedDimensions(); // if it was being dragged/resized - r_start_x = r_start_x; - r_start_y = r_start_y; + r_start_x = r_start_x; + r_start_y = r_start_y; var difference_x = Math.abs(real_x-r_start_x); var difference_y = Math.abs(real_y-r_start_y); @@ -3292,7 +3292,7 @@ } } } // no change in mouse position - + // Remove non-scaling stroke if(svgedit.browser.supportsNonScalingStroke()) { var elem = selectedElements[0]; @@ -3401,7 +3401,7 @@ element = null; // continue to be set to true so that mouseMove happens started = true; - + var res = pathActions.mouseUp(evt, element, mouse_x, mouse_y); element = res.element; keep = res.keep; @@ -3421,7 +3421,7 @@ element = null; current_mode = "select"; var batchCmd = canvas.undoMgr.finishUndoableChange(); - if (!batchCmd.isEmpty()) { + if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); } // perform recalculation to weed out any stray identity transforms that might get stuck @@ -3432,13 +3432,13 @@ // This could occur in an extension break; } - + var ext_result = runExtensions("mouseUp", { event: evt, mouse_x: mouse_x, mouse_y: mouse_y }, true); - + $.each(ext_result, function(i, r) { if(r) { keep = r.keep || keep; @@ -3446,37 +3446,37 @@ started = r.started || started; } }); - + if (!keep && element != null) { getCurrentDrawing().releaseId(getId()); element.parentNode.removeChild(element); element = null; - + var t = evt.target; - - // if this element is in a group, go up until we reach the top-level group + + // if this element is in a group, go up until we reach the top-level group // just below the layer groups // TODO: once we implement links, we also would have to check for <a> elements while (t.parentNode.parentNode.tagName == "g") { t = t.parentNode; } - // if we are not in the middle of creating a path, and we've clicked on some shape, + // if we are not in the middle of creating a path, and we've clicked on some shape, // then go to Select mode. // WebKit returns <div> when the canvas is clicked, Firefox/Opera return <svg> if ( (current_mode != "path" || !drawn_path) && t.parentNode.id != "selectorParentGroup" && - t.id != "svgcanvas" && t.id != "svgroot") + t.id != "svgcanvas" && t.id != "svgroot") { // switch into "select" mode if we've clicked on an element canvas.setMode("select"); selectOnly([t], true); } - + } else if (element != null) { canvas.addedNew = true; - + if(useUnit) svgedit.units.convertAttrs(element); - + var ani_dur = .2, c_ani; if(opac_ani.beginElement && element.getAttribute('opacity') != cur_shape.opacity) { c_ani = $(opac_ani).clone().attr({ @@ -3490,7 +3490,7 @@ } else { ani_dur = 0; } - + // Ideally this would be done on the endEvent of the animation, // but that doesn't seem to be supported in Webkit setTimeout(function() { @@ -3508,14 +3508,14 @@ // we create the insert command that is stored on the stack // undo means to call cmd.unapply(), redo means to call cmd.apply() addCommandToHistory(new InsertElementCommand(element)); - + call("changed",[element]); }, ani_dur * 1000); } - + start_transform = null; }; - + var dblClick = function(evt) { var evt_target = evt.target; var parent = evt_target.parentNode; @@ -3523,16 +3523,16 @@ var tagName = mouse_target.tagName; if(parent === current_group) return; - + if(tagName === 'text' && current_mode !== 'textedit') { var pt = transformPoint( evt.pageX, evt.pageY, root_sctm ); textActions.select(mouse_target, pt.x, pt.y); } - + if((tagName === "g" || tagName === "a") && getRotationAngle(mouse_target)) { - // TODO: Allow method of in-group editing without having to do + // TODO: Allow method of in-group editing without having to do // this (similar to editing rotated paths) - + // Ungroup and regroup pushGroupProperties(mouse_target); mouse_target = selectedElements[0]; @@ -3542,7 +3542,7 @@ if(current_group) { leaveContext(); } - + if((parent.tagName !== 'g' && parent.tagName !== 'a') || parent === getCurrentDrawing().getCurrentLayer() || mouse_target === selectorManager.selectorParentGroup) @@ -3558,12 +3558,12 @@ e.preventDefault(); return false; }; - + // Added mouseup to the container here. // TODO(codedread): Figure out why after the Closure compiler, the window mouseup is ignored. $(container).mousedown(mouseDown).mousemove(mouseMove).click(handleLinkInCanvas).dblclick(dblClick).mouseup(mouseUp); // $(window).mouseup(mouseUp); - + $(container).bind("mousewheel DOMMouseScroll", function(e){ if(!e.shiftKey) return; e.preventDefault(); @@ -3589,14 +3589,14 @@ if (e.detail > 0) { bbox.factor = .5; } else if (e.detail < 0) { - bbox.factor = 2; - } + bbox.factor = 2; + } } - + if(!bbox.factor) return; call("zoomed", bbox); }); - + }()); // Function: preventClickDefault @@ -3621,11 +3621,11 @@ var matrix; var last_x, last_y; var allow_dbl; - + function setCursor(index) { var empty = (textinput.value === ""); $(textinput).focus(); - + if(!arguments.length) { if(empty) { index = 0; @@ -3634,7 +3634,7 @@ index = textinput.selectionEnd; } } - + var charbb; charbb = chardata[index]; if(!empty) { @@ -3650,7 +3650,7 @@ }); cursor = getElem("selectorParentGroup").appendChild(cursor); } - + if(!blinker) { blinker = setInterval(function() { var show = (cursor.getAttribute('display') === 'none'); @@ -3658,11 +3658,11 @@ }, 600); } - - + + var start_pt = ptToScreen(charbb.x, textbb.y); var end_pt = ptToScreen(charbb.x, (textbb.y + textbb.height)); - + assignAttributes(cursor, { x1: start_pt.x, y1: start_pt.y, @@ -3671,20 +3671,20 @@ visibility: 'visible', display: 'inline' }); - + if(selblock) selblock.setAttribute('d', 'M 0 0'); } - + function setSelection(start, end, skipInput) { if(start === end) { setCursor(end); return; } - + if(!skipInput) { textinput.setSelectionRange(start, end); } - + selblock = getElem("text_selectblock"); if (!selblock) { @@ -3698,30 +3698,30 @@ getElem("selectorParentGroup").appendChild(selblock); } - + var startbb = chardata[start]; - + var endbb = chardata[end]; - + cursor.setAttribute('visibility', 'hidden'); - + var tl = ptToScreen(startbb.x, textbb.y), tr = ptToScreen(startbb.x + (endbb.x - startbb.x), textbb.y), bl = ptToScreen(startbb.x, textbb.y + textbb.height), br = ptToScreen(startbb.x + (endbb.x - startbb.x), textbb.y + textbb.height); - - + + var dstr = "M" + tl.x + "," + tl.y + " L" + tr.x + "," + tr.y + " " + br.x + "," + br.y + " " + bl.x + "," + bl.y + "z"; - + assignAttributes(selblock, { d: dstr, 'display': 'inline' }); } - + function getIndexFromPoint(mouse_x, mouse_y) { // Position cursor here var pt = svgroot.createSVGPoint(); @@ -3748,62 +3748,62 @@ } return charpos; } - + function setCursorFromPoint(mouse_x, mouse_y) { setCursor(getIndexFromPoint(mouse_x, mouse_y)); } - + function setEndSelectionFromPoint(x, y, apply) { var i1 = textinput.selectionStart; var i2 = getIndexFromPoint(x, y); - + var start = Math.min(i1, i2); var end = Math.max(i1, i2); setSelection(start, end, !apply); } - + function screenToPt(x_in, y_in) { var out = { x: x_in, y: y_in } - + out.x /= current_zoom; - out.y /= current_zoom; + out.y /= current_zoom; if(matrix) { var pt = transformPoint(out.x, out.y, matrix.inverse()); out.x = pt.x; out.y = pt.y; } - + return out; - } - + } + function ptToScreen(x_in, y_in) { var out = { x: x_in, y: y_in } - + if(matrix) { var pt = transformPoint(out.x, out.y, matrix); out.x = pt.x; out.y = pt.y; } - + out.x *= current_zoom; out.y *= current_zoom; - + return out; } - + function hideCursor() { if(cursor) { cursor.setAttribute('visibility', 'hidden'); } } - + function selectAll(evt) { setSelection(0, curtext.textContent.length); $(this).unbind(evt); @@ -3811,25 +3811,25 @@ function selectWord(evt) { if(!allow_dbl || !curtext) return; - + var ept = transformPoint( evt.pageX, evt.pageY, root_sctm ), mouse_x = ept.x * current_zoom, mouse_y = ept.y * current_zoom; var pt = screenToPt(mouse_x, mouse_y); - + var index = getIndexFromPoint(pt.x, pt.y); var str = curtext.textContent; var first = str.substr(0, index).replace(/[a-z0-9]+$/i, '').length; var m = str.substr(index).match(/^[a-z0-9]+/i); var last = (m?m[0].length:0) + index; setSelection(first, last); - + // Set tripleclick $(evt.target).click(selectAll); setTimeout(function() { $(evt.target).unbind('click', selectAll); }, 300); - + } return { @@ -3843,27 +3843,27 @@ }, mouseDown: function(evt, mouse_target, start_x, start_y) { var pt = screenToPt(start_x, start_y); - + textinput.focus(); setCursorFromPoint(pt.x, pt.y); last_x = start_x; last_y = start_y; - + // TODO: Find way to block native selection }, mouseMove: function(mouse_x, mouse_y) { var pt = screenToPt(mouse_x, mouse_y); setEndSelectionFromPoint(pt.x, pt.y); - }, + }, mouseUp: function(evt, mouse_x, mouse_y) { var pt = screenToPt(mouse_x, mouse_y); - + setEndSelectionFromPoint(pt.x, pt.y, true); - - // TODO: Find a way to make this work: Use transformed BBox instead of evt.target + + // TODO: Find a way to make this work: Use transformed BBox instead of evt.target // if(last_x === mouse_x && last_y === mouse_y // && !svgedit.math.rectsIntersect(transbb, {x: pt.x, y: pt.y, width:0, height:0})) { -// textActions.toSelectMode(true); +// textActions.toSelectMode(true); // } if( @@ -3883,21 +3883,21 @@ allow_dbl = false; current_mode = "textedit"; selectorManager.requestSelector(curtext).showGrips(false); - + // Make selector group accept clicks var sel = selectorManager.requestSelector(curtext).selectorRect; - + textActions.init(); $(curtext).css('cursor', 'text'); - + if(!arguments.length) { setCursor(); } else { var pt = screenToPt(x, y); setCursorFromPoint(pt.x, pt.y); } - + setTimeout(function() { allow_dbl = true; }, 300); @@ -3909,11 +3909,11 @@ if(selblock) $(selblock).attr('display','none'); if(cursor) $(cursor).attr('visibility','hidden'); $(curtext).css('cursor', 'move'); - + if(selectElem) { clearSelection(); $(curtext).css('cursor', 'move'); - + call("selected", [curtext]); addToSelection([curtext], true); } @@ -3921,11 +3921,11 @@ // No content, so delete canvas.deleteSelectedElements(); } - + $(textinput).blur(); - + curtext = false; - + // if(svgedit.browser.supportsEditableText()) { // curtext.removeAttribute('editable'); // } @@ -3946,47 +3946,47 @@ // curtext.select(); // return; // } - + if(!curtext.parentNode) { // Result of the ffClone, need to get correct element curtext = selectedElements[0]; selectorManager.requestSelector(curtext).showGrips(false); } - + var str = curtext.textContent; var len = str.length; - + var xform = curtext.getAttribute('transform'); textbb = svgedit.utilities.getBBox(curtext); - + matrix = xform?getMatrix(curtext):null; chardata = Array(len); textinput.focus(); - + $(curtext).unbind('dblclick', selectWord).dblclick(selectWord); - + if(!len) { var end = {x: textbb.x + (textbb.width/2), width: 0}; } - + for(var i=0; i<len; i++) { var start = curtext.getStartPositionOfChar(i); var end = curtext.getEndPositionOfChar(i); - + if(!svgedit.browser.supportsGoodTextCharPos()) { var offset = canvas.contentW * current_zoom; start.x -= offset; end.x -= offset; - + start.x /= current_zoom; end.x /= current_zoom; } - + // Get a "bbox" equivalent for each character. Uses the // bbox data of the actual text for y, height purposes - + // TODO: Decide if y, width and height are actually necessary chardata[i] = { x: start.x, @@ -3995,7 +3995,7 @@ height: textbb.height }; } - + // Add a last bbox for cursor at end of text chardata.push({ x: end.x, @@ -4010,11 +4010,11 @@ // Group: Path edit functions // Functions relating to editing path elements var pathActions = canvas.pathActions = function() { - + var subpath = false; var current_path; var newPoint, firstCtrl; - + function resetD(p) { p.setAttribute("d", pathActions.convertPath(p)); } @@ -4050,9 +4050,9 @@ } // TODO: Correct this: pathActions.canDeleteNodes = true; - + pathActions.closed_subpath = this.subpathIsClosed(this.selected_pts[0]); - + call("selected", grips); } @@ -4062,7 +4062,7 @@ stretchy = null; this.lastCtrlPoint = [0, 0]; - + // This function converts a polyline (created by the fh_path tool) into // a path element and coverts every three line segments into a single bezier // curve in an attempt to smooth out the free-hand @@ -4071,13 +4071,13 @@ var N = points.numberOfItems; if (N >= 4) { // loop through every 3 points and convert to a cubic bezier curve segment - // - // NOTE: this is cheating, it means that every 3 points has the potential to + // + // NOTE: this is cheating, it means that every 3 points has the potential to // be a corner instead of treating each point in an equal manner. In general, // this technique does not look that good. - // + // // I am open to better ideas! - // + // // Reading: // - http://www.efg2.com/Lab/Graphics/Jean-YvesQueinecBezierCurves.htm // - http://www.codeproject.com/KB/graphics/BezierSpline.aspx?msg=2956963 @@ -4090,7 +4090,7 @@ var ct1 = points.getItem(i); var ct2 = points.getItem(i+1); var end = points.getItem(i+2); - + // if the previous segment had a control point, we want to smooth out // the control points on both sides if (prevCtlPt) { @@ -4103,9 +4103,9 @@ ct1 = newpts[1]; } } - + d.push([ct1.x,ct1.y,ct2.x,ct2.y,end.x,end.y].join(',')); - + curpos = end; prevCtlPt = ct2; } @@ -4137,12 +4137,12 @@ if(current_mode === "path") { mouse_x = start_x; mouse_y = start_y; - + var x = mouse_x/current_zoom, y = mouse_y/current_zoom, stretchy = getElem("path_stretch_line"); - newPoint = [x, y]; - + newPoint = [x, y]; + if(curConfig.gridSnapping){ x = snapToGrid(x); y = snapToGrid(y); @@ -4163,9 +4163,9 @@ stretchy.setAttribute("display", "inline"); this.stretchy = stretchy; - + var keep = null; - + // if pts array is empty, create path element with M at current point if (!drawn_path) { d_attr = "M" + x + "," + y + " "; @@ -4200,15 +4200,15 @@ break; } } - + // get path element that we are in the process of creating var id = getId(); - + // Remove previous path object if previously created svgedit.path.removePath_(id); - + var newpath = getElem(id); - + var len = seglist.numberOfItems; // if we clicked on an existing point, then we are done this path, commit it // (i,i+1) are the x,y that were clicked on @@ -4224,7 +4224,7 @@ var abs_y = seglist.getItem(0).y; var grip_x = svgedit.path.first_grip ? svgedit.path.first_grip[0]/current_zoom : seglist.getItem(0).x; var grip_y = svgedit.path.first_grip ? svgedit.path.first_grip[1]/current_zoom : seglist.getItem(0).y; - + var s_seg = stretchy.pathSegList.getItem(1); if(s_seg.pathSegType === 4) { @@ -4247,7 +4247,7 @@ return keep; } $(stretchy).remove(); - + // this will signal to commit the path element = newpath; drawn_path = null; @@ -4257,7 +4257,7 @@ if(svgedit.path.path.matrix) { remapElement(newpath, {}, svgedit.path.path.matrix.inverse()); } - + var new_d = newpath.getAttribute("d"); var orig_d = $(svgedit.path.path.elem).attr("d"); $(svgedit.path.path.elem).attr("d", orig_d + new_d); @@ -4286,7 +4286,7 @@ var lastx = last.x, lasty = last.y; if(evt.shiftKey) { var xya = snapToAngle(lastx,lasty,x,y); x=xya.x; y=xya.y; } - + // Use the segment defined by stretchy var s_seg = stretchy.pathSegList.getItem(1); if(s_seg.pathSegType === 4) { @@ -4301,12 +4301,12 @@ s_seg.y2 / current_zoom ); } - + drawn_path.pathSegList.appendItem(newseg); - + x *= current_zoom; y *= current_zoom; - + // update everything to the latest point stretchy.setAttribute('d', ['M', x, y, x, y].join(' ')); var pointGrip1 = svgedit.path.addCtrlGrip('1c1'); @@ -4337,20 +4337,20 @@ } return; } - + // TODO: Make sure current_path isn't null at this point if(!svgedit.path.path) return; - + svgedit.path.path.storeD(); - + var id = evt.target.id; if (id.substr(0,14) == "pathpointgrip_") { // Select this point var cur_pt = svgedit.path.path.cur_pt = parseInt(id.substr(14)); svgedit.path.path.dragging = [start_x, start_y]; var seg = svgedit.path.path.segs[cur_pt]; - - // only clear selection if shift is not pressed (otherwise, add + + // only clear selection if shift is not pressed (otherwise, add // node to selection) if (!evt.shiftKey) { if(svgedit.path.path.selected_pts.length <= 1 || !seg.selected) { @@ -4364,7 +4364,7 @@ } } else if(id.indexOf("ctrlpointgrip_") == 0) { svgedit.path.path.dragging = [start_x, start_y]; - + var parts = id.split('_')[1].split('c'); var cur_pt = parts[0]-0; var ctrl_num = parts[1]-0; @@ -4467,7 +4467,7 @@ if(!drawn_path) return; var seglist = drawn_path.pathSegList; var index = seglist.numberOfItems - 1; - var pointGrip1 = svgedit.path.addCtrlGrip('1c1'); + var pointGrip1 = svgedit.path.addCtrlGrip('1c1'); var pointGrip2 = svgedit.path.addCtrlGrip('0c2'); if(newPoint) { @@ -4484,20 +4484,20 @@ var pt_x = newPoint[0]; var pt_y = newPoint[1]; - + // set curve var seg = seglist.getItem(index); var cur_x = mouse_x / current_zoom; var cur_y = mouse_y / current_zoom; var alt_x = (is_linked) ? (pt_x + (pt_x - cur_x)) : current_pointGrip2_x; var alt_y = (is_linked) ? (pt_y + (pt_y - cur_y)) : current_pointGrip2_y; - - + + pointGrip2.setAttribute('cx', alt_x * current_zoom); pointGrip2.setAttribute('cy', alt_y * current_zoom); pointGrip2.setAttribute('display', 'inline'); - - + + var ctrlLine = svgedit.path.getCtrlLine(1); var ctrlLine2 = svgedit.path.getCtrlLine(2); assignAttributes(ctrlLine, { @@ -4507,7 +4507,7 @@ y2: pt_y * current_zoom, display: 'inline' }); - + assignAttributes(ctrlLine2, { x1: alt_x * current_zoom, @@ -4522,11 +4522,11 @@ firstCtrl = [mouse_x, mouse_y]; } else { var last_x, last_y; - + var last = seglist.getItem(index - 1); var last_x = last.x; var last_y = last.y - + if(last.pathSegType === 6) { last_x += (last_x - last.x2); last_y += (last_y - last.y2); @@ -4552,7 +4552,7 @@ if(prev.pathSegType === 6) { var prev_x = this.lastCtrlPoint[0]/current_zoom || prev.x + (prev.x - prev.x2); var prev_y = this.lastCtrlPoint[1]/current_zoom || prev.y + (prev.y - prev.y2); - svgedit.path.replacePathSeg(6, 1, [mouse_x, mouse_y, prev_x * current_zoom, prev_y * current_zoom, lastgripx, lastgripy], stretchy); + svgedit.path.replacePathSeg(6, 1, [mouse_x, mouse_y, prev_x * current_zoom, prev_y * current_zoom, lastgripx, lastgripy], stretchy); } else if(firstCtrl) { svgedit.path.replacePathSeg(6, 1, [mouse_x, mouse_y, firstCtrl[0], firstCtrl[1], mouse_x, mouse_y], stretchy); } else { @@ -4592,7 +4592,7 @@ if(!seg.next && !seg.prev) return; var item = seg.item; var rbb = rubberBox.getBBox(); - + var pt = svgedit.path.getGripPt(seg); var pt_bb = { x: pt.x, @@ -4600,7 +4600,7 @@ width: 0, height: 0 }; - + var sel = svgedit.math.rectsIntersect(rbb, pt_bb); this.select(sel); @@ -4609,7 +4609,7 @@ }); } - }, + }, mouseUp: function(evt, element, mouse_x, mouse_y) { var lastpointgrip = getElem('ctrlpointgrip_1c1'); var firstpointgrip = getElem('ctrlpointgrip_0c2'); @@ -4639,34 +4639,34 @@ element: element } } - + // Edit mode - + if (svgedit.path.path.dragging) { var last_pt = svgedit.path.path.cur_pt; svgedit.path.path.dragging = false; svgedit.path.path.dragctrl = false; svgedit.path.path.update(); - - + + if(hasMoved) { svgedit.path.path.endChanges("Move path point(s)"); - } - + } + if(!evt.shiftKey && !hasMoved) { svgedit.path.path.selectPt(last_pt); - } + } } else if(rubberBox && rubberBox.getAttribute('display') != 'none') { // Done with multi-node-select rubberBox.setAttribute("display", "none"); - + if(rubberBox.getAttribute('width') <= 2 && rubberBox.getAttribute('height') <= 2) { pathActions.toSelectMode(evt.target); } - - // else, move back to select mode + + // else, move back to select mode } else { pathActions.toSelectMode(evt.target); } @@ -4686,12 +4686,12 @@ svgedit.path.path.show(false); current_path = false; clearSelection(); - + if(svgedit.path.path.matrix) { // Rotated, so may need to re-calculate the center svgedit.path.recalcRotatedPath(); } - + if(selPath) { call("selected", [elem]); addToSelection([elem], true); @@ -4715,14 +4715,14 @@ } // going into pathedit mode else { current_path = target; - } + } }, reorient: function() { var elem = selectedElements[0]; if(!elem) return; var angle = getRotationAngle(elem); if(angle == 0) return; - + var batchCmd = new BatchCommand("Reorient path"); var changes = { d: elem.getAttribute('d'), @@ -4731,18 +4731,18 @@ batchCmd.addSubCommand(new ChangeElementCommand(elem, changes)); clearSelection(); this.resetOrientation(elem); - + addCommandToHistory(batchCmd); // Set matrix to null - svgedit.path.getPath_(elem).show(false).matrix = null; + svgedit.path.getPath_(elem).show(false).matrix = null; this.clear(); - + addToSelection([elem], true); call("changed", selectedElements); }, - + clear: function(remove) { current_path = null; if (drawn_path) { @@ -4764,11 +4764,11 @@ tlist.clear(); path.removeAttribute("transform"); var segList = path.pathSegList; - + // Opera/win/non-EN throws an error here. // TODO: Find out why! // Presumed fixed in Opera 10.5, so commented out for now - + // try { var len = segList.numberOfItems; // } catch(err) { @@ -4794,7 +4794,7 @@ }); svgedit.path.replacePathSeg(type, i, pts, path); } - + reorientGrads(path, m); @@ -4814,16 +4814,16 @@ y: seg.item.y, type: seg.type }; - }, + }, linkControlPoints: function(linkPoints) { svgedit.path.setLinkControlPoints(linkPoints); }, clonePathNode: function() { svgedit.path.path.storeD(); - + var sel_pts = svgedit.path.path.selected_pts; var segs = svgedit.path.path.segs; - + var i = sel_pts.length; var nums = []; @@ -4833,7 +4833,7 @@ nums.push(pt + i); nums.push(pt + i + 1); } - + svgedit.path.path.init().addPtsToSelection(nums); svgedit.path.path.endChanges("Clone path node(s)"); @@ -4842,14 +4842,14 @@ var sel_pts = svgedit.path.path.selected_pts; // Only allow one selected node for now if(sel_pts.length !== 1) return; - + var elem = svgedit.path.path.elem; var list = elem.pathSegList; var len = list.numberOfItems; var index = sel_pts[0]; - + var open_pt = null; var start_item = null; @@ -4869,7 +4869,7 @@ return false; } }); - + if(open_pt == null) { // Single path, so close last seg open_pt = svgedit.path.path.segs.length - 1; @@ -4877,10 +4877,10 @@ if(open_pt !== false) { // Close this path - + // Create a line going to the previous "M" var newseg = elem.createSVGPathSegLinetoAbs(start_item.x, start_item.y); - + var closer = elem.createSVGPathSegClosePath(); if(open_pt == svgedit.path.path.segs.length) { list.appendItem(newseg); @@ -4889,30 +4889,30 @@ svgedit.path.insertItemBefore(elem, closer, open_pt); svgedit.path.insertItemBefore(elem, newseg, open_pt); } - + svgedit.path.path.init().selectPt(open_pt+1); return; } - - + + // M 1,1 L 2,2 L 3,3 L 1,1 z // open at 2,2 // M 2,2 L 3,3 L 1,1 - - // M 1,1 L 2,2 L 1,1 z M 4,4 L 5,5 L6,6 L 5,5 z - // M 1,1 L 2,2 L 1,1 z [M 4,4] L 5,5 L(M)6,6 L 5,5 z - + + // M 1,1 L 2,2 L 1,1 z M 4,4 L 5,5 L6,6 L 5,5 z + // M 1,1 L 2,2 L 1,1 z [M 4,4] L 5,5 L(M)6,6 L 5,5 z + var seg = svgedit.path.path.segs[index]; - + if(seg.mate) { list.removeItem(index); // Removes last "L" list.removeItem(index); // Removes the "Z" svgedit.path.path.init().selectPt(index - 1); return; } - + var last_m, z_seg; - + // Find this sub-path's closing point and remove for(var i=0; i<list.numberOfItems; i++) { var item = list.getItem(i); @@ -4931,26 +4931,26 @@ break; } } - + var num = (index - last_m) - 1; - + while(num--) { svgedit.path.insertItemBefore(elem, list.getItem(last_m), z_seg); } - + var pt = list.getItem(last_m); - + // Make this point the new "M" svgedit.path.replacePathSeg(2, last_m, [pt.x, pt.y]); - + var i = index - + svgedit.path.path.init().selectPt(0); }, deletePathNode: function() { if(!pathActions.canDeleteNodes) return; svgedit.path.path.storeD(); - + var sel_pts = svgedit.path.path.selected_pts; var i = sel_pts.length; @@ -4958,12 +4958,12 @@ var pt = sel_pts[i]; svgedit.path.path.deleteSeg(pt); } - + // Cleanup var cleanup = function() { var segList = svgedit.path.path.elem.pathSegList; var len = segList.numberOfItems; - + var remItems = function(pos, count) { while(count--) { segList.removeItem(pos); @@ -4971,7 +4971,7 @@ } if(len <= 1) return true; - + while(len--) { var item = segList.getItem(len); if(item.pathSegType === 1) { @@ -4990,12 +4990,12 @@ } else if(item.pathSegType === 2) { if(len > 0) { var prev_type = segList.getItem(len-1).pathSegType; - // Path has M M + // Path has M M if(prev_type === 2) { remItems(len-1, 1); cleanup(); break; - // Entire path ends with Z M + // Entire path ends with Z M } else if(prev_type === 1 && segList.numberOfItems-1 === len) { remItems(len, 1); cleanup(); @@ -5003,23 +5003,23 @@ } } } - } + } return false; } - + cleanup(); - + // Completely delete a path with 1 or 0 segments if(svgedit.path.path.elem.pathSegList.numberOfItems <= 1) { canvas.setMode("select") canvas.deleteSelectedElements(); return; } - + svgedit.path.path.init(); - + svgedit.path.path.clearSelection(); - + // TODO: Find right way to select point now // path.selectPt(sel_pt); if(window.opera) { // Opera repaints incorrectly @@ -5034,14 +5034,14 @@ moveNode: function(attr, newValue) { var sel_pts = svgedit.path.path.selected_pts; if(!sel_pts.length) return; - + svgedit.path.path.storeD(); - + // Get first selected point var seg = svgedit.path.path.segs[sel_pts[0]]; var diff = {x:0, y:0}; diff[attr] = newValue - seg.item[attr]; - + seg.move(diff.x, diff.y); svgedit.path.path.endChanges("Move path point"); }, @@ -5057,7 +5057,7 @@ if(item.pathSegType === 2) { last_m = item; } - + if(item.pathSegType === 1) { var prev = segList.getItem(i-1); if(prev.x != last_m.x || prev.y != last_m.y) { @@ -5068,7 +5068,7 @@ pathActions.fixEnd(elem); break; } - + } } if(svgedit.browser.isWebkit()) resetD(elem); @@ -5080,7 +5080,7 @@ var curx = 0, cury = 0; var d = ""; var last_m = null; - + for (var i = 0; i < len; ++i) { var seg = segList.getItem(i); // if these properties are not in the segment, set them to zero @@ -5090,10 +5090,10 @@ y1 = seg.y1 || 0, x2 = seg.x2 || 0, y2 = seg.y2 || 0; - + var type = seg.pathSegType; var letter = pathMap[type]['to'+(toRel?'Lower':'Upper')+'Case'](); - + var addToD = function(pnts, more, last) { var str = ''; var more = more?' '+more.join(' '):''; @@ -5103,7 +5103,7 @@ }); d += letter + pnts.join(' ') + more + last; } - + switch (type) { case 1: // z,Z closepath (Z/z) d += "z"; @@ -5143,12 +5143,12 @@ y -= cury; case 5: // relative line (l) case 3: // relative move (m) - // If the last segment was a "z", this must be relative to + // If the last segment was a "z", this must be relative to if(last_m && segList.getItem(i-1).pathSegType === 1 && !toRel) { curx = last_m[0]; cury = last_m[1]; } - + case 19: // relative smooth quad (t) if(toRel) { curx += x; @@ -5160,7 +5160,7 @@ cury = y; } if(type === 3) last_m = [curx, cury]; - + addToD([[x,y]]); break; case 6: // absolute cubic (C) @@ -5181,7 +5181,7 @@ case 8: // absolute quad (Q) x -= curx; x1 -= curx; y -= cury; y1 -= cury; - case 9: // relative quad (q) + case 9: // relative quad (q) if(toRel) { curx += x; cury += y; @@ -5241,23 +5241,23 @@ // Function: removeUnusedDefElems // Looks at DOM elements inside the <defs> to see if they are referred to, // removes them from the DOM if they are not. -// +// // Returns: // The amount of elements that were removed var removeUnusedDefElems = this.removeUnusedDefElems = function() { var defs = svgcontent.getElementsByTagNameNS(svgns, "defs"); if(!defs || !defs.length) return 0; - + // if(!defs.firstChild) return; - + var defelem_uses = [], numRemoved = 0; var attrs = ['fill', 'stroke', 'filter', 'marker-start', 'marker-mid', 'marker-end']; var alen = attrs.length; - + var all_els = svgcontent.getElementsByTagNameNS(svgns, '*'); var all_len = all_els.length; - + for(var i=0; i<all_len; i++) { var el = all_els[i]; for(var j = 0; j < alen; j++) { @@ -5268,14 +5268,14 @@ } } } - + // gradients can refer to other gradients var href = getHref(el); if (href && href.indexOf('#') === 0) { defelem_uses.push(href.substr(1)); } }; - + var defelems = $(defs).find("linearGradient, radialGradient, filter, marker, svg, symbol"); defelem_ids = [], i = defelems.length; @@ -5294,34 +5294,34 @@ } // Function: svgCanvasToString -// Main function to set up the SVG content for output +// Main function to set up the SVG content for output // -// Returns: +// Returns: // String containing the SVG image for output this.svgCanvasToString = function() { // keep calling it until there are none to remove while (removeUnusedDefElems() > 0) {}; - + pathActions.clear(true); - + // Keep SVG-Edit comment on top $.each(svgcontent.childNodes, function(i, node) { if(i && node.nodeType === 8 && node.data.indexOf('Created with') >= 0) { svgcontent.insertBefore(node, svgcontent.firstChild); } }); - + // Move out of in-group editing mode if(current_group) { leaveContext(); selectOnly([current_group]); } - + //hide grid, otherwise shows a black canvas $('#canvasGrid').attr('display', 'none'); - + var naked_svgs = []; - + // Unwrap gsvg if it has no special attributes (only id and style) $(svgcontent).find('g:data(gsvg)').each(function() { var attrs = this.attributes; @@ -5339,25 +5339,25 @@ } }); var output = this.svgToString(svgcontent, 0); - + // Rewrap gsvg if(naked_svgs.length) { $(naked_svgs).each(function() { groupSvgElem(this); }); } - + return output; }; // Function: svgToString // Sub function ran on each SVG element to convert it to a string as desired -// -// Parameters: +// +// Parameters: // elem - The SVG element to convert // indent - Integer with the amount of spaces to indent this tag // -// Returns: +// Returns: // String with the given element as an SVG tag this.svgToString = function(elem, indent) { var out = new Array(), toXml = svgedit.utilities.toXml; @@ -5370,13 +5370,13 @@ attr, i, childs = elem.childNodes; - + for (var i=0; i<indent; i++) out.push(" "); out.push("<"); out.push(elem.nodeName); if(elem.id === 'svgcontent') { // Process root element separately var res = getResolution(); - + var vb = ""; // TODO: Allow this by dividing all values by current baseVal // Note that this also means we should properly deal with this on import @@ -5385,20 +5385,20 @@ // var unit_m = svgedit.units.getTypeMap()[unit]; // res.w = svgedit.units.shortFloat(res.w / unit_m) // res.h = svgedit.units.shortFloat(res.h / unit_m) -// vb = ' viewBox="' + [0, 0, res.w, res.h].join(' ') + '"'; +// vb = ' viewBox="' + [0, 0, res.w, res.h].join(' ') + '"'; // res.w += unit; // res.h += unit; // } - + if(unit !== "px") { res.w = svgedit.units.convertUnit(res.w, unit) + unit; res.h = svgedit.units.convertUnit(res.h, unit) + unit; } - + out.push(' width="' + res.w + '" height="' + res.h + '"' + vb + ' xmlns="'+svgns+'"'); - + var nsuris = {}; - + // Check elements for namespaces, add if found $(elem).find('*').andSelf().each(function() { var el = this; @@ -5410,22 +5410,22 @@ } }); }); - + var i = attrs.length; var attr_names = ['width','height','xmlns','x','y','viewBox','id','overflow']; while (i--) { attr = attrs.item(i); var attrVal = toXml(attr.nodeValue); - + // Namespaces have already been dealt with, so skip if(attr.nodeName.indexOf('xmlns:') === 0) continue; // only serialize attributes we don't use internally - if (attrVal != "" && attr_names.indexOf(attr.localName) == -1) + if (attrVal != "" && attr_names.indexOf(attr.localName) == -1) { if(!attr.namespaceURI || nsMap[attr.namespaceURI]) { - out.push(' '); + out.push(' '); out.push(attr.nodeName); out.push("=\""); out.push(attrVal); out.push("\""); } @@ -5434,7 +5434,7 @@ } else { // Skip empty defs if(elem.nodeName === 'defs' && !elem.firstChild) return; - + var moz_attrs = ['-moz-math-font-style', '_moz-math-font-style']; for (var i=attrs.length-1; i>=0; i--) { attr = attrs.item(i); @@ -5444,25 +5444,25 @@ if (attrVal != "") { if(attrVal.indexOf('pointer-events') === 0) continue; if(attr.localName === "class" && attrVal.indexOf('se_') === 0) continue; - out.push(" "); + out.push(" "); if(attr.localName === 'd') attrVal = pathActions.convertPath(elem, true); if(!isNaN(attrVal)) { attrVal = svgedit.units.shortFloat(attrVal); } else if(unit_re.test(attrVal)) { attrVal = svgedit.units.shortFloat(attrVal) + unit; } - - // Embed images when saving + + // Embed images when saving if(save_options.apply - && elem.nodeName === 'image' + && elem.nodeName === 'image' && attr.localName === 'href' && save_options.images - && save_options.images === 'embed') + && save_options.images === 'embed') { var img = encodableImages[attrVal]; if(img) attrVal = img; } - + // map various namespaces to our fixed namespace prefixes // (the default xmlns attribute itself does not get a prefix) if(!attr.namespaceURI || attr.namespaceURI == svgns || nsMap[attr.namespaceURI]) { @@ -5477,7 +5477,7 @@ out.push(">"); indent++; var bOneLine = false; - + for (var i=0; i<childs.length; i++) { var child = childs.item(i); @@ -5525,7 +5525,7 @@ // Function: embedImage // Converts a given image file to a data URL when possible, then runs a given callback // -// Parameters: +// Parameters: // val - String with the path/URL of the image // callback - Optional function to run when image data is found, supplies the // result (data URL or false) as first parameter. @@ -5567,7 +5567,7 @@ // This function also includes the XML prolog. Clients of the SvgCanvas bind their save // function to the 'saved' event. // -// Returns: +// Returns: // Nothing this.save = function(opts) { // remove the selected outline before serializing @@ -5575,7 +5575,7 @@ // Update save options if provided if(opts) $.extend(save_options, opts); save_options.apply = true; - + // no need for doctype, see http://jwatt.org/svg/authoring/#doctype-declaration var str = this.svgCanvasToString(); if (svgedit.browser.supportsBlobs()) { @@ -5589,15 +5589,15 @@ }; // Function: rasterExport -// Generates a PNG Data URL based on the current image, then calls "exported" +// Generates a PNG Data URL based on the current image, then calls "exported" // with an object including the string and any issues found this.rasterExport = function() { // remove the selected outline before serializing clearSelection(); - - // Check for known CanVG issues + + // Check for known CanVG issues var issues = []; - + // Selector and notice var issue_list = { 'feGaussianBlur': uiStrings.exportNoBlur, @@ -5605,12 +5605,12 @@ '[stroke-dasharray]': uiStrings.exportNoDashArray }; var content = $(svgcontent); - + // Add font/text check if Canvas Text API is not implemented if(!("font" in $('<canvas>')[0].getContext('2d'))) { issue_list['text'] = uiStrings.exportNoText; } - + $.each(issue_list, function(sel, descr) { if(content.find(sel).length) { issues.push(descr); @@ -5634,7 +5634,7 @@ // Function: randomizeIds // This function determines whether to use a nonce in the prefix, when // generating IDs for future documents in SVG-Edit. -// +// // Parameters: // an opional boolean, which, if true, adds a nonce to the prefix. Thus // svgCanvas.randomizeIds() <==> svgCanvas.randomizeIds(true) @@ -5662,11 +5662,11 @@ // // <marker id='se_marker_end_svg_7'/> // <polyline id='svg_7' se:connector='svg_1 svg_6' marker-end='url(#se_marker_end_svg_7)'/> - // + // // Problem #1: if svg_1 gets renamed, we do not update the polyline's se:connector attribute // Problem #2: if the polyline svg_7 gets renamed, we do not update the marker id nor the polyline's marker-end attribute var ref_elems = ["filter", "linearGradient", "pattern", "radialGradient", "symbol", "textPath", "use"]; - + svgedit.utilities.walkTree(g, function(n) { // if it's an element node if (n.nodeType == 1) { @@ -5679,7 +5679,7 @@ } ids[n.id]["elem"] = n; } - + // now search for all attributes on this element that might refer // to other elements $.each(ref_attrs,function(i,attr) { @@ -5697,7 +5697,7 @@ } } }); - + // check xlink:href now var href = svgedit.utilities.getHref(n); // TODO: what if an <image> or <a> element refers to an element internally? @@ -5711,20 +5711,20 @@ } ids[refid]["hrefs"].push(n); } - } + } } }); - + // in ids, we now have a map of ids, elements and attributes, let's re-identify for (var oldid in ids) { if (!oldid) continue; var elem = ids[oldid]["elem"]; if (elem) { var newid = getNextId(); - + // assign element its new id elem.id = newid; - + // remap all url() attributes var attrs = ids[oldid]["attrs"]; var j = attrs.length; @@ -5732,7 +5732,7 @@ var attr = attrs[j]; attr.ownerElement.setAttribute(attr.name, "url(#" + newid + ")"); } - + // remap all href attributes var hreffers = ids[oldid]["hrefs"]; var k = hreffers.length; @@ -5748,11 +5748,11 @@ // Assigns reference data for each use element var setUseData = this.setUseData = function(parent) { var elems = $(parent); - + if(parent.tagName !== 'use') { elems = elems.find('use'); } - + elems.each(function() { var id = getHref(this).substr(1); var ref_elem = getElem(id); @@ -5774,38 +5774,38 @@ return (this.tagName.indexOf('Gradient') >= 0); }); } - + elems.each(function() { var grad = this; if($(grad).attr('gradientUnits') === 'userSpaceOnUse') { // TODO: Support more than one element with this ref by duplicating parent grad var elems = $(svgcontent).find('[fill="url(#' + grad.id + ')"],[stroke="url(#' + grad.id + ')"]'); if(!elems.length) return; - + // get object's bounding box var bb = svgedit.utilities.getBBox(elems[0]); - + // This will occur if the element is inside a <defs> or a <symbol>, // in which we shouldn't need to convert anyway. if(!bb) return; - + if(grad.tagName === 'linearGradient') { var g_coords = $(grad).attr(['x1', 'y1', 'x2', 'y2']); - + // If has transform, convert var tlist = grad.gradientTransform.baseVal; if(tlist && tlist.numberOfItems > 0) { var m = transformListToTransform(tlist).matrix; var pt1 = transformPoint(g_coords.x1, g_coords.y1, m); var pt2 = transformPoint(g_coords.x2, g_coords.y2, m); - + g_coords.x1 = pt1.x; g_coords.y1 = pt1.y; g_coords.x2 = pt2.x; g_coords.y2 = pt2.y; grad.removeAttribute('gradientTransform'); } - + $(grad).attr({ x1: (g_coords.x1 - bb.x) / bb.width, y1: (g_coords.y1 - bb.y) / bb.height, @@ -5814,26 +5814,26 @@ }); grad.removeAttribute('gradientUnits'); } else { - // Note: radialGradient elements cannot be easily converted + // Note: radialGradient elements cannot be easily converted // because userSpaceOnUse will keep circular gradients, while // objectBoundingBox will x/y scale the gradient according to - // its bbox. - + // its bbox. + // For now we'll do nothing, though we should probably have - // the gradient be updated as the element is moved, as + // the gradient be updated as the element is moved, as // inkscape/illustrator do. - + // var g_coords = $(grad).attr(['cx', 'cy', 'r']); -// +// // $(grad).attr({ // cx: (g_coords.cx - bb.x) / bb.width, // cy: (g_coords.cy - bb.y) / bb.height, // r: g_coords.r // }); -// +// // grad.removeAttribute('gradientUnits'); } - + } }); @@ -5846,19 +5846,19 @@ elem = selectedElements[0]; } var $elem = $(elem); - + var batchCmd = new BatchCommand(); - + var ts; - + if($elem.data('gsvg')) { // Use the gsvg as the new group var svg = elem.firstChild; var pt = $(svg).attr(['x', 'y']); - + $(elem.firstChild.firstChild).unwrap(); $(elem).removeData('gsvg'); - + var tlist = getTransformList(elem); var xform = svgroot.createSVGTransform(); xform.setTranslate(pt.x, pt.y); @@ -5867,61 +5867,61 @@ call("selected", [elem]); } else if($elem.data('symbol')) { elem = $elem.data('symbol'); - + ts = $elem.attr('transform'); var pos = $elem.attr(['x','y']); var vb = elem.getAttribute('viewBox'); - + if(vb) { var nums = vb.split(' '); pos.x -= +nums[0]; pos.y -= +nums[1]; } - + // Not ideal, but works ts += " translate(" + (pos.x || 0) + "," + (pos.y || 0) + ")"; - + var prev = $elem.prev(); - + // Remove <use> element batchCmd.addSubCommand(new RemoveElementCommand($elem[0], $elem[0].nextSibling, $elem[0].parentNode)); $elem.remove(); - + // See if other elements reference this symbol var has_more = $(svgcontent).find('use:data(symbol)').length; - + var g = svgdoc.createElementNS(svgns, "g"); var childs = elem.childNodes; - + for(var i = 0; i < childs.length; i++) { g.appendChild(childs[i].cloneNode(true)); } - + // Duplicate the gradients for Gecko, since they weren't included in the <symbol> if(svgedit.browser.isGecko()) { var dupeGrads = $(findDefs()).children('linearGradient,radialGradient,pattern').clone(); $(g).append(dupeGrads); } - + if (ts) { g.setAttribute("transform", ts); } - + var parent = elem.parentNode; - + uniquifyElems(g); - + // Put the dupe gradients back into <defs> (after uniquifying them) if(svgedit.browser.isGecko()) { $(findDefs()).append( $(g).find('linearGradient,radialGradient,pattern') ); } - + // now give the g itself a new id g.id = getNextId(); - + prev.after(g); - + if(parent) { if(!has_more) { // remove symbol/svg element @@ -5931,39 +5931,39 @@ } batchCmd.addSubCommand(new InsertElementCommand(g)); } - + setUseData(g); - + if(svgedit.browser.isGecko()) { convertGradients(findDefs()); } else { convertGradients(g); } - + // recalculate dimensions on the top-level children so that unnecessary transforms // are removed svgedit.utilities.walkTreePost(g, function(n){try{recalculateDimensions(n)}catch(e){console.log(e)}}); - + // Give ID for any visible element missing one $(g).find(visElems).each(function() { if(!this.id) this.id = getNextId(); }); - + selectOnly([g]); - + var cm = pushGroupProperties(g, true); if(cm) { batchCmd.addSubCommand(cm); } addCommandToHistory(batchCmd); - + } else { console.log('Unexpected element to ungroup:', elem); } } -// +// // Function: setSvgString // This function sets the current drawing as the input SVG XML. // @@ -5985,7 +5985,7 @@ var nextSibling = svgcontent.nextSibling; var oldzoom = svgroot.removeChild(svgcontent); batchCmd.addSubCommand(new RemoveElementCommand(oldzoom, nextSibling, svgroot)); - + // set new svg document // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode() if(svgdoc.adoptNode) { @@ -5994,12 +5994,12 @@ else { svgcontent = svgdoc.importNode(newDoc.documentElement, true); } - + svgroot.appendChild(svgcontent); var content = $(svgcontent); - + canvas.current_drawing_ = new svgedit.draw.Drawing(svgcontent, idprefix); - + // retrieve or set the nonce var nonce = getCurrentDrawing().getNonce(); if (nonce) { @@ -6007,7 +6007,7 @@ } else { call("unsetnonce"); } - + // change image href vals if possible content.find('image').each(function() { var image = this; @@ -6026,14 +6026,14 @@ // Add to encodableImages if it loads canvas.embedImage(val); }); - + // Wrap child SVGs in group elements content.find('svg').each(function() { // Skip if it's in a <defs> if($(this).closest('defs').length) return; - + uniquifyElems(this); - + // Check if it already has a gsvg group var pa = this.parentNode; if(pa.childNodes.length === 1 && pa.nodeName === 'g') { @@ -6043,29 +6043,29 @@ groupSvgElem(this); } }); - + // Put all paint elems in defs - + content.find('linearGradient, radialGradient, pattern').appendTo(findDefs()); - + // Set ref element for <use> elements - + // TODO: This should also be done if the object is re-added through "redo" setUseData(content); - + convertGradients(content[0]); - + // recalculate dimensions on the top-level children so that unnecessary transforms // are removed svgedit.utilities.walkTreePost(svgcontent, function(n){try{recalculateDimensions(n)}catch(e){console.log(e)}}); - + var attrs = { id: 'svgcontent', overflow: curConfig.show_outside_canvas?'visible':'hidden' }; - + var percs = false; - + // determine proper size if (content.attr("viewBox")) { var vb = content.attr("viewBox").split(' '); @@ -6077,9 +6077,9 @@ $.each(['width', 'height'], function(i, dim) { // Set to 100 if not given var val = content.attr(dim); - + if(!val) val = '100%'; - + if((val+'').substr(-1) === "%") { // Use user units if percentage given percs = true; @@ -6088,31 +6088,31 @@ } }); } - + // identify layers identifyLayers(); - + // Give ID for any visible layer children missing one content.children().find(visElems).each(function() { if(!this.id) this.id = getNextId(); }); - + // Percentage width/height, so let's base it on visible elements if(percs) { var bb = getStrokedBBox(); attrs.width = bb.width + bb.x; attrs.height = bb.height + bb.y; } - - // Just in case negative numbers are given or + + // Just in case negative numbers are given or // result from the percs calculation if(attrs.width <= 0) attrs.width = 200; if(attrs.height <= 0) attrs.height = 200; - + content.attr(attrs); this.contentW = attrs['width']; this.contentH = attrs['height']; - + $("#canvas_width").val(this.contentW) $("#canvas_height").val(this.contentH) var background = $("#canvas_background") @@ -6131,16 +6131,16 @@ // update root to the correct size var changes = content.attr(["width", "height"]); batchCmd.addSubCommand(new ChangeElementCommand(svgroot, changes)); - + // reset zoom current_zoom = 1; - + // reset transform lists svgedit.transformlist.resetListMap(); clearSelection(); svgedit.path.clearData(); svgroot.appendChild(selectorManager.selectorParentGroup); - + addCommandToHistory(batchCmd); call("changed", [svgcontent]); } catch(e) { @@ -6165,7 +6165,7 @@ opts = { alpha: opac }; opts[refElem.tagName] = refElem; - } + } else if (color.indexOf("#") === 0) { opts = { alpha: opac, @@ -6190,19 +6190,19 @@ // // Returns: // This function returns false if the import was unsuccessful, true otherwise. -// TODO: +// TODO: // * properly handle if namespace is introduced by imported content (must add to svgcontent // and update all prefixes in the imported node) // * properly handle recalculating dimensions, recalculateDimensions() doesn't handle -// arbitrary transform lists, but makes some assumptions about how the transform list +// arbitrary transform lists, but makes some assumptions about how the transform list // was obtained -// * import should happen in top-left of current zoomed viewport +// * import should happen in top-left of current zoomed viewport this.importSvgString = function(xmlString) { try { // Get unique ID var uid = svgedit.utilities.encode64(xmlString.length + xmlString).substr(0,32); - + var useExisting = false; // Look for symbol and make sure symbol exists in image @@ -6211,18 +6211,18 @@ useExisting = true; } } - + var batchCmd = new BatchCommand("Import SVG"); - + if(useExisting) { var symbol = import_ids[uid].symbol; var ts = import_ids[uid].xform; } else { // convert string into XML document var newDoc = svgedit.utilities.text2xml(xmlString); - + this.prepareSvg(newDoc); - + // import new svg document into our document var svg; // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode() @@ -6232,9 +6232,9 @@ else { svg = svgdoc.importNode(newDoc.documentElement, true); } - + uniquifyElems(svg); - + var innerw = convertToNum('width', svg.getAttribute("width")), innerh = convertToNum('height', svg.getAttribute("height")), innervb = svg.getAttribute("viewBox"), @@ -6242,32 +6242,32 @@ vb = innervb ? innervb.split(" ") : [0,0,innerw,innerh]; for (var j = 0; j < 4; ++j) vb[j] = +(vb[j]); - + // TODO: properly handle preserveAspectRatio var canvasw = +svgcontent.getAttribute("width"), canvash = +svgcontent.getAttribute("height"); // imported content should be 1/3 of the canvas on its largest dimension - + if (innerh > innerw) { var ts = "scale(" + (canvash/3)/vb[3] + ")"; } else { var ts = "scale(" + (canvash/3)/vb[2] + ")"; } - + // Hack to make recalculateDimensions understand how to scale ts = "translate(0) " + ts + " translate(0)"; - + var symbol = svgdoc.createElementNS(svgns, "symbol"); var defs = findDefs(); - + if(svgedit.browser.isGecko()) { // Move all gradients into root for Firefox, workaround for this bug: // https://bugzilla.mozilla.org/show_bug.cgi?id=353575 // TODO: Make this properly undo-able. $(svg).find('linearGradient, radialGradient, pattern').appendTo(defs); } - + while (svg.firstChild) { var first = svg.firstChild; symbol.appendChild(first); @@ -6278,31 +6278,31 @@ symbol.setAttribute(attr.nodeName, attr.nodeValue); } symbol.id = getNextId(); - + // Store data import_ids[uid] = { symbol: symbol, xform: ts } - + findDefs().appendChild(symbol); batchCmd.addSubCommand(new InsertElementCommand(symbol)); } - - + + var use_el = svgdoc.createElementNS(svgns, "use"); use_el.id = getNextId(); setHref(use_el, "#" + symbol.id); - + (current_group || getCurrentDrawing().getCurrentLayer()).appendChild(use_el); batchCmd.addSubCommand(new InsertElementCommand(use_el)); clearSelection(); - + use_el.setAttribute("transform", ts); recalculateDimensions(use_el); $(use_el).data('symbol', symbol).data('ref', symbol); addToSelection([use_el]); - + // TODO: Find way to add this in a recalculateDimensions-parsable way // if (vb[0] != 0 || vb[1] != 0) // ts = "translate(" + (-vb[0]) + "," + (-vb[1]) + ") " + ts; @@ -6330,7 +6330,7 @@ }; // Function: createLayer -// Creates a new top-level layer in the drawing with the given name, sets the current layer +// Creates a new top-level layer in the drawing with the given name, sets the current layer // to it, and then clears the selection This function then calls the 'changed' handler. // This is an undoable action. // @@ -6366,7 +6366,7 @@ if(ch.localName == 'title') continue; new_layer.appendChild(copyElem(ch)); } - + clearSelection(); identifyLayers(); @@ -6377,7 +6377,7 @@ }; // Function: deleteCurrentLayer -// Deletes the current layer from the drawing and then clears the selection. This function +// Deletes the current layer from the drawing and then clears the selection. This function // then calls the 'changed' handler. This is an undoable action. this.deleteCurrentLayer = function() { var current_layer = getCurrentDrawing().getCurrentLayer(); @@ -6414,11 +6414,11 @@ }; // Function: renameCurrentLayer -// Renames the current layer. If the layer name is not valid (i.e. unique), then this function +// Renames the current layer. If the layer name is not valid (i.e. unique), then this function // does nothing and returns false, otherwise it returns true. This is an undo-able action. -// +// // Parameters: -// newname - the new name you want to give the current layer. This name must be unique +// newname - the new name you want to give the current layer. This name must be unique // among all layer names. // // Returns: @@ -6437,14 +6437,14 @@ } var oldname = drawing.getLayerName(i); drawing.all_layers[i][0] = svgedit.utilities.toXml(newname); - + // now change the underlying title element contents var len = oldLayer.childNodes.length; for (var i = 0; i < len; ++i) { var child = oldLayer.childNodes.item(i); // found the <title> element, now append all the if (child && child.tagName == "title") { - // wipe out old name + // wipe out old name while (child.firstChild) { child.removeChild(child.firstChild); } child.textContent = newname; @@ -6461,14 +6461,14 @@ }; // Function: setCurrentLayerPosition -// Changes the position of the current layer to the new value. If the new index is not valid, +// Changes the position of the current layer to the new value. If the new index is not valid, // this function does nothing and returns false, otherwise it returns true. This is an // undo-able action. // // Parameters: // newpos - The zero-based index of the new position of the layer. This should be between // 0 and (number of layers - 1) -// +// // Returns: // true if the current layer position was changed, false otherwise. this.setCurrentLayerPosition = function(newpos) { @@ -6479,7 +6479,7 @@ } // some unknown error condition (current_layer not in all_layers) if (oldpos == drawing.getNumLayers()) { return false; } - + if (oldpos != newpos) { // if our new position is below us, we need to insert before the node after newpos var refLayer = null; @@ -6495,19 +6495,19 @@ } svgcontent.insertBefore(drawing.current_layer, refLayer); addCommandToHistory(new MoveElementCommand(drawing.current_layer, oldNextSibling, svgcontent)); - + identifyLayers(); canvas.setCurrentLayer(drawing.getLayerName(newpos)); - + return true; } } - + return false; }; // Function: setLayerVisibility -// Sets the visibility of the layer. If the layer name is not valid, this function return +// Sets the visibility of the layer. If the layer name is not valid, this function return // false, otherwise it returns true. This is an undo-able action. // // Parameters: @@ -6526,17 +6526,17 @@ } else { return false; } - + if (layer == drawing.getCurrentLayer()) { clearSelection(); pathActions.clear(); } -// call("changed", [selected]); +// call("changed", [selected]); return true; }; // Function: moveSelectedToLayer -// Moves the selected elements to layername. If the name is not a valid layer name, then false +// Moves the selected elements to layername. If the name is not a valid layer name, then false // is returned. Otherwise it returns true. This is an undo-able action. // // Parameters: @@ -6555,9 +6555,9 @@ } } if (!layer) return false; - + var batchCmd = new BatchCommand("Move Elements to Layer"); - + // loop for each selected element and move it var selElems = selectedElements; var i = selElems.length; @@ -6570,9 +6570,9 @@ layer.appendChild(elem); batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldLayer)); } - + addCommandToHistory(batchCmd); - + return true; }; @@ -6598,19 +6598,19 @@ prev.appendChild(ch); batchCmd.addSubCommand(new MoveElementCommand(ch, oldNextSibling, drawing.current_layer)); } - + // Remove current layer svgcontent.removeChild(drawing.current_layer); - + if(!skipHistory) { clearSelection(); identifyLayers(); call("changed", [svgcontent]); - + addCommandToHistory(batchCmd); } - + drawing.current_layer = prev; return batchCmd; } @@ -6622,7 +6622,7 @@ while($(svgcontent).children('g').length > 1) { batchCmd.addSubCommand(canvas.mergeLayer(true)); } - + clearSelection(); identifyLayers(); call("changed", [svgcontent]); @@ -6637,7 +6637,7 @@ if(len) { for(var i = 0; i < len; i++) { var elem = disabled_elems[i]; - + var orig = elData(elem, 'orig_opac'); if(orig !== 1) { elem.setAttribute('opacity', orig); @@ -6663,7 +6663,7 @@ // Edit inside this group current_group = elem; - + // Disable other elements $(elem).parentsUntil('#svgcontent').andSelf().siblings().each(function() { var opac = this.getAttribute('opacity') || 1; @@ -6695,7 +6695,7 @@ // create empty first layer canvas.createLayer("Layer 1"); - + // clear the undo stack canvas.undoMgr.resetUndoStack(); @@ -6729,10 +6729,10 @@ var getResolution = this.getResolution = function() { // var vb = svgcontent.getAttribute("viewBox").split(' '); // return {'w':vb[2], 'h':vb[3], 'zoom': current_zoom}; - + var width = svgcontent.getAttribute("width")/current_zoom; var height = svgcontent.getAttribute("height")/current_zoom; - + return { 'w': width, 'h': height, @@ -6789,11 +6789,11 @@ this.setGroupTitle = function(val) { var elem = selectedElements[0]; elem = $(elem).data('gsvg') || elem; - + var ts = $(elem).children('title'); - + var batchCmd = new BatchCommand("Set Label"); - + if(!val.length) { // Remove title element var tsNextSibling = ts.nextSibling; @@ -6829,9 +6829,9 @@ // newtitle - String with the new title this.setDocumentTitle = function(newtitle) { var childs = svgcontent.childNodes, doc_title = false, old_title = ''; - + var batchCmd = new BatchCommand("Change Image Title"); - + for (var i=0; i<childs.length; i++) { if(childs[i].nodeName == 'title') { doc_title = childs[i]; @@ -6842,8 +6842,8 @@ if(!doc_title) { doc_title = svgdoc.createElementNS(svgns, "title"); svgcontent.insertBefore(doc_title, svgcontent.firstChild); - } - + } + if(newtitle.length) { doc_title.textContent = newtitle; } else { @@ -6869,13 +6869,13 @@ // Function: setResolution // Changes the document's dimensions to the given size // -// Parameters: -// x - Number with the width of the new dimensions in user units. +// Parameters: +// x - Number with the width of the new dimensions in user units. // Can also be the string "fit" to indicate "fit to content" -// y - Number with the height of the new dimensions in user units. +// y - Number with the height of the new dimensions in user units. // // Returns: -// Boolean to indicate if resolution change was succesful. +// Boolean to indicate if resolution change was succesful. // It will fail on "fit to content" option with no content to fit to. this.setResolution = function(x, y) { var res = getResolution(); @@ -6885,7 +6885,7 @@ if(x == 'fit') { // Get bounding box var bbox = getStrokedBBox(); - + if(bbox) { batchCmd = new BatchCommand("Fit Canvas to Content"); var visEls = getVisibleElements(); @@ -6895,11 +6895,11 @@ dx.push(bbox.x*-1); dy.push(bbox.y*-1); }); - + var cmd = canvas.moveSelectedElements(dx, dy, true); batchCmd.addSubCommand(cmd); clearSelection(); - + x = Math.round(bbox.width); y = Math.round(bbox.height); } else { @@ -6913,17 +6913,17 @@ x = convertToNum('width', x); y = convertToNum('height', y); - + svgcontent.setAttribute('width', x); svgcontent.setAttribute('height', y); - + this.contentW = x; this.contentH = y; batchCmd.addSubCommand(new ChangeElementCommand(svgcontent, {"width":w, "height":h})); svgcontent.setAttribute("viewBox", [0, 0, x/current_zoom, y/current_zoom].join(' ')); batchCmd.addSubCommand(new ChangeElementCommand(svgcontent, {"viewBox": ["0 0", w, h].join(' ')})); - + addCommandToHistory(batchCmd); background = document.getElementById("canvas_background"); if (background) { @@ -6946,9 +6946,9 @@ // Function: setBBoxZoom // Sets the zoom level on the canvas-side based on the given value -// +// // Parameters: -// val - Bounding box object to zoom to or string indicating zoom option +// val - Bounding box object to zoom to or string indicating zoom option // editor_w - Integer with the editor's workarea box's width // editor_h - Integer with the editor's workarea box's height this.setBBoxZoom = function(val, editor_w, editor_h) { @@ -6957,12 +6957,12 @@ var calcZoom = function(bb) { if(!bb) return false; var w_zoom = Math.round((editor_w / bb.width)*100 * spacer)/100; - var h_zoom = Math.round((editor_h / bb.height)*100 * spacer)/100; + var h_zoom = Math.round((editor_h / bb.height)*100 * spacer)/100; var zoomlevel = Math.min(w_zoom,h_zoom); canvas.setZoom(zoomlevel); return {'zoom': zoomlevel, 'bbox': bb}; } - + if(typeof val == 'object') { bb = val; if(bb.width == 0 || bb.height == 0) { @@ -7025,7 +7025,7 @@ // Parameters: // name - String with the new mode to change to this.setMode = function(name) { - + pathActions.clear(); textActions.clear(); $("#workarea").attr("class", name); @@ -7043,7 +7043,7 @@ // Function: setColor // Change the current stroke/fill color/gradient value -// +// // Parameters: // type - String indicating fill or stroke // val - The value to set the stroke attribute to @@ -7073,7 +7073,7 @@ if (!preventUndo) { changeSelectedAttribute(type, val, elems); call("changed", elems); - } else + } else changeSelectedAttributeNoUndo(type, val, elems); } } @@ -7147,22 +7147,22 @@ if (grad.getAttribute('x1') != og.getAttribute('x1') || grad.getAttribute('y1') != og.getAttribute('y1') || grad.getAttribute('x2') != og.getAttribute('x2') || - grad.getAttribute('y2') != og.getAttribute('y2')) + grad.getAttribute('y2') != og.getAttribute('y2')) { continue; } } else { var grad_attrs = $(grad).attr(rad_attrs); var og_attrs = $(og).attr(rad_attrs); - + var diff = false; $.each(rad_attrs, function(i, attr) { if(grad_attrs[attr] != og_attrs[attr]) diff = true; }); - + if(diff) continue; } - + // else could be a duplicate, iterate through stops var stops = grad.getElementsByTagNameNS(svgns, "stop"); var ostops = og.getElementsByTagNameNS(svgns, "stop"); @@ -7178,7 +7178,7 @@ if (stop.getAttribute('offset') != ostop.getAttribute('offset') || stop.getAttribute('stop-opacity') != ostop.getAttribute('stop-opacity') || - stop.getAttribute('stop-color') != ostop.getAttribute('stop-color')) + stop.getAttribute('stop-color') != ostop.getAttribute('stop-color')) { break; } @@ -7204,28 +7204,28 @@ var y1 = grad.getAttribute('y1') || 0; var x2 = grad.getAttribute('x2') || 1; var y2 = grad.getAttribute('y2') || 0; - + // Convert to USOU points x1 = (bb.width * x1) + bb.x; y1 = (bb.height * y1) + bb.y; x2 = (bb.width * x2) + bb.x; y2 = (bb.height * y2) + bb.y; - + // Transform those points var pt1 = transformPoint(x1, y1, m); var pt2 = transformPoint(x2, y2, m); - + // Convert back to BB points var g_coords = {}; - + g_coords.x1 = (pt1.x - bb.x) / bb.width; g_coords.y1 = (pt1.y - bb.y) / bb.height; g_coords.x2 = (pt2.x - bb.x) / bb.width; g_coords.y2 = (pt2.y - bb.y) / bb.height; - + var newgrad = grad.cloneNode(true); $(newgrad).attr(g_coords); - + newgrad.id = getNextId(); findDefs().appendChild(newgrad); elem.setAttribute(type, 'url(#' + newgrad.id + ')'); @@ -7237,7 +7237,7 @@ // Function: setPaint // Set a color/gradient to a fill/stroke // -// Parameters: +// Parameters: // type - String with "fill" or "stroke" // paint - The jGraduate paint object to apply this.setPaint = function(type, paint) { @@ -7248,13 +7248,13 @@ cur_properties[type + '_paint'] = p; switch ( p.type ) { case "solidColor": - + if (p.solidColor != "none" && p.solidColor != "#none") { this.setColor(type, "#"+p.solidColor) } else { this.setColor(type, "none"); - var selector = (type == "fill") ? "#fill_color rect" : "#stroke_color rect" + var selector = (type == "fill") ? "#fill_color rect" : "#stroke_color rect" document.querySelector(selector).setAttribute('fill', 'none'); } break; @@ -7273,7 +7273,7 @@ // // make a copy // var p = new $.jGraduate.Paint(p); // this.setStrokeOpacity(p.alpha/100); -// +// // // now set the current paint object // cur_properties.stroke_paint = p; // switch ( p.type ) { @@ -7283,17 +7283,17 @@ // case "linearGradient" // case "radialGradient" // canvas.strokeGrad = p[p.type]; -// setGradient(type); +// setGradient(type); // default: // // console.log("none!"); // } // }; -// +// // this.setFillPaint = function(p, addGrad) { // // make a copy // var p = new $.jGraduate.Paint(p); // this.setFillOpacity(p.alpha/100, true); -// +// // // now set the current paint object // cur_properties.fill_paint = p; // if (p.type == "solidColor") { @@ -7301,11 +7301,11 @@ // } // else if(p.type == "linearGradient") { // canvas.fillGrad = p.linearGradient; -// if(addGrad) setGradient(); +// if(addGrad) setGradient(); // } // else if(p.type == "radialGradient") { // canvas.fillGrad = p.radialGradient; -// if(addGrad) setGradient(); +// if(addGrad) setGradient(); // } // else { // // console.log("none!"); @@ -7330,7 +7330,7 @@ return; } cur_properties.stroke_width = val; - + var elems = []; var i = selectedElements.length; while (i--) { @@ -7338,10 +7338,10 @@ if (elem) { if (elem.tagName == "g") svgedit.utilities.walkTree(elem, function(e){if(e.nodeName!="g") elems.push(e);}); - else + else elems.push(elem); } - } + } if (elems.length > 0) { changeSelectedAttribute("stroke-width", val, elems); call("changed", selectedElements); @@ -7363,10 +7363,10 @@ if (elem) { if (elem.tagName == "g") svgedit.utilities.walkTree(elem, function(e){if(e.nodeName!="g") elems.push(e);}); - else + else elems.push(elem); } - } + } if (elems.length > 0) { changeSelectedAttribute(attr, val, elems); call("changed", selectedElements); @@ -7427,7 +7427,7 @@ this.getBlur = function(elem) { var val = 0; // var elem = selectedElements[0]; - + if(elem) { var filter_url = elem.getAttribute('filter'); if(filter_url) { @@ -7444,7 +7444,7 @@ var cur_command = null; var filter = null; var filterHidden = false; - + // Function: setBlurNoUndo // Sets the stdDeviation blur value on the selected element without being undoable // @@ -7473,12 +7473,12 @@ canvas.setBlurOffsets(filter, val); } } - + function finishChange() { var bCmd = canvas.undoMgr.finishUndoableChange(); cur_command.addSubCommand(bCmd); addCommandToHistory(cur_command); - cur_command = null; + cur_command = null; filter = null; } @@ -7509,7 +7509,7 @@ } } - // Function: setBlur + // Function: setBlur // Adds/updates the blur filter to the selected element // // Parameters: @@ -7520,16 +7520,16 @@ finishChange(); return; } - + // Looks for associated blur, creates one if not found var elem = selectedElements[0]; var elem_id = elem.id; filter = getElem(elem_id + '_blur'); - + val -= 0; - + var batchCmd = new BatchCommand(); - + // Blur found! if(filter) { if(val === 0) { @@ -7543,33 +7543,33 @@ "stdDeviation": val } }); - + filter = addSvgElementFromJson({ "element": "filter", "attr": { "id": elem_id + '_blur' } }); - + filter.appendChild(newblur); findDefs().appendChild(filter); - + batchCmd.addSubCommand(new InsertElementCommand(filter)); } var changes = {filter: elem.getAttribute('filter')}; - + if(val === 0) { elem.removeAttribute("filter"); batchCmd.addSubCommand(new ChangeElementCommand(elem, changes)); return; } else { changeSelectedAttribute("filter", 'url(#' + elem_id + '_blur)'); - + batchCmd.addSubCommand(new ChangeElementCommand(elem, changes)); - + canvas.setBlurOffsets(filter, val); } - + cur_command = batchCmd; canvas.undoMgr.beginUndoableChange("stdDeviation", [filter?filter.firstChild:null]); if(complete) { @@ -7710,18 +7710,18 @@ // Function: setImageURL // Sets the new image URL for the selected image element. Updates its size if // a new URL is given -// +// // Parameters: // val - String with the image URL/path this.setImageURL = function(val) { var elem = selectedElements[0]; if(!elem) return; - + var attrs = $(elem).attr(['width', 'height']); var setsize = (!attrs.width || !attrs.height); var cur_href = getHref(elem); - + // Do nothing if no URL change or size change if(cur_href !== val) { setsize = true; @@ -7737,14 +7737,14 @@ if(setsize) { $(new Image()).load(function() { var changes = $(elem).attr(['width', 'height']); - + $(elem).attr({ width: this.width, height: this.height }); - + selectorManager.requestSelector(elem).resize(); - + batchCmd.addSubCommand(new ChangeElementCommand(elem, changes)); addCommandToHistory(batchCmd); call("changed", [elem]); @@ -7756,7 +7756,7 @@ // Function: setLinkURL // Sets the new link URL for the selected anchor element. -// +// // Parameters: // val - String with the link URL/path this.setLinkURL = function(val) { @@ -7771,11 +7771,11 @@ return; } } - + var cur_href = getHref(elem); - + if(cur_href === val) return; - + var batchCmd = new BatchCommand("Change Link URL"); setHref(elem, val); @@ -7789,14 +7789,14 @@ // Function elementAreSame // Checks if all the selected Elements are the same type -// +// // Parameters: // None this.elementsAreSame = function(elements) { if (!elements.length || elements[0] == null) return null else { - var isSameElement = function(el) { + var isSameElement = function(el) { if (el && selectedElements[0]) return (el.nodeName == selectedElements[0].nodeName); else return null; @@ -7808,7 +7808,7 @@ // Function: setRectRadius // Sets the rx & ry values to the selected rect element to change its corner radius -// +// // Parameters: // val - The new radius this.setRectRadius = function(val) { @@ -7830,7 +7830,7 @@ // Wraps the selected element(s) in an anchor element or converts group to one this.makeHyperlink = function(url) { canvas.groupSelectedElements('a', url); - + // TODO: If element is a single "g", convert to "a" // if(selectedElements.length > 1 && selectedElements[1]) { @@ -7844,7 +7844,7 @@ // Group: Element manipulation // Function: setSegType -// Sets the new segment type to the selected segment(s). +// Sets the new segment type to the selected segment(s). // // Parameters: // new_type - Integer with the new segment type @@ -7857,7 +7857,7 @@ // Function: convertToPath // Convert selected element to a path, or get the BBox of an element-as-path // -// Parameters: +// Parameters: // elem - The DOM element to be converted // getBBox - Boolean on whether or not to only return the path's BBox // @@ -7872,11 +7872,11 @@ }); return; } - + if(!getBBox) { var batchCmd = new BatchCommand("Convert element to Path"); } - + var attrs = getBBox?{}:{ "fill": cur_shape.fill, "fill-opacity": cur_shape.fill_opacity, @@ -7889,7 +7889,7 @@ "opacity": cur_shape.opacity, "visibility":"hidden" }; - + // any attribute on the element not covered by the above // TODO: make this list global so that we can properly maintain it // TODO: what about @transform, @clip-rule, @fill-rule, etc? @@ -7898,17 +7898,17 @@ attrs[this] = elem.getAttribute(this); } }); - + var path = addSvgElementFromJson({ "element": "path", "attr": attrs }); - + var eltrans = elem.getAttribute("transform"); if(eltrans) { path.setAttribute("transform",eltrans); } - + var id = elem.id; var parent = elem.parentNode; if(elem.nextSibling) { @@ -7916,9 +7916,9 @@ } else { parent.appendChild(path); } - + var d = ''; - + var joinSegs = function(segs) { $.each(segs, function(j, seg) { var l = seg[0], pts = seg[1]; @@ -7940,7 +7940,7 @@ if(elem.tagName == 'circle') { rx = ry = $(elem).attr('r'); } - + joinSegs([ ['M',[(cx-rx),(cy)]], ['C',[(cx-rx),(cy-ry/num), (cx-rx/num),(cy-ry), (cx),(cy-ry)]], @@ -7997,14 +7997,14 @@ path.parentNode.removeChild(path); break; } - + if(d) { path.setAttribute('d',d); } - + if(!getBBox) { // Replace the current element with the converted one - + // Reorient if it has a matrix if(eltrans) { var tlist = getTransformList(path); @@ -8012,7 +8012,7 @@ pathActions.resetOrientation(path); } } - + var nextSibling = elem.nextSibling; batchCmd.addSubCommand(new RemoveElementCommand(elem, nextSibling, parent)); batchCmd.addSubCommand(new InsertElementCommand(path)); @@ -8022,9 +8022,9 @@ path.setAttribute('id', id); path.removeAttribute("visibility"); addToSelection([path], true); - + addCommandToHistory(batchCmd); - + } else { // Get the correct BBox of the new path, then discard it pathActions.resetOrientation(path); @@ -8042,8 +8042,8 @@ // Function: changeSelectedAttributeNoUndo // This function makes the changes to the elements. It does not add the change -// to the history stack. -// +// to the history stack. +// // Parameters: // attr - String with the attribute name // newValue - String or number with the new attribute value @@ -8099,7 +8099,7 @@ },0); } // if this element was rotated, and we changed the position of this element - // we need to update the rotational transform attribute + // we need to update the rotational transform attribute var angle = getRotationAngle(elem); if (angle != 0 && attr != "transform") { var tlist = getTransformList(elem); @@ -8130,7 +8130,7 @@ // If you want to change all selectedElements, ignore the elems argument. // If you want to change only a subset of selectedElements, then send the // subset to this function in the elems argument. -// +// // Parameters: // attr - String with the attribute name // newValue - String or number with the new attribute value @@ -8143,13 +8143,13 @@ changeSelectedAttributeNoUndo(attr, val, elems); var batchCmd = canvas.undoMgr.finishUndoableChange(); - if (!batchCmd.isEmpty()) { + if (!batchCmd.isEmpty()) { addCommandToHistory(batchCmd); } }; // Function: deleteSelectedElements -// Removes all selected elements from the DOM and adds the change to the +// Removes all selected elements from the DOM and adds the change to the // history stack this.deleteSelectedElements = function() { var batchCmd = new BatchCommand("Delete Elements"); @@ -8161,19 +8161,19 @@ var parent = selected.parentNode; var t = selected; - + // this will unselect the element and remove the selectedOutline selectorManager.releaseSelector(t); - + // Remove the path if present. svgedit.path.removePath_(t.id); - + // Get the parent if it's a single-child anchor if(parent.tagName === 'a' && parent.childNodes.length === 1) { t = parent; parent = parent.parentNode; } - + var nextSibling = t.nextSibling; var elem = parent.removeChild(t); selectedCopy.push(selected); //for the copy @@ -8186,7 +8186,7 @@ }; // Function: cutSelectedElements -// Removes all selected elements from the DOM and adds the change to the +// Removes all selected elements from the DOM and adds the change to the // history stack. Remembers removed elements on the clipboard // TODO: Combine similar code with deleteSelectedElements @@ -8216,7 +8216,7 @@ if (!batchCmd.isEmpty()) addCommandToHistory(batchCmd); call("changed", selectedCopy); clearSelection(); - + canvas.clipBoard = selectedCopy; }; @@ -8230,10 +8230,10 @@ var cb = canvas.clipBoard; var len = cb.length; if(!len) return; - + var pasted = []; var batchCmd = new BatchCommand('Paste elements'); - + // Move elements to lastClickPoint while (len--) { @@ -8249,9 +8249,9 @@ } svgCanvas.clearSelection(); setTimeout(function(){selectOnly(pasted)},100); - - + + addCommandToHistory(batchCmd); call("changed", pasted); } @@ -8259,12 +8259,12 @@ // Function: groupSelectedElements // Wraps all the selected elements in a group (g) element -// Parameters: +// Parameters: // type - type of element to group into, defaults to <g> this.groupSelectedElements = function(type) { if(!type) type = 'g'; var cmd_str = ''; - + switch ( type ) { case "a": cmd_str = "Make hyperlink"; @@ -8278,9 +8278,9 @@ cmd_str = "Group Elements"; break; } - + var batchCmd = new BatchCommand(cmd_str); - + // create and insert the group element var g = addSvgElementFromJson({ "element": type, @@ -8292,24 +8292,24 @@ setHref(g, url); } batchCmd.addSubCommand(new InsertElementCommand(g)); - + // now move all children into the group var i = selectedElements.length; while (i--) { var elem = selectedElements[i]; if (elem == null) continue; - + if (elem.parentNode.tagName === 'a' && elem.parentNode.childNodes.length === 1) { elem = elem.parentNode; } - + var oldNextSibling = elem.nextSibling; var oldParent = elem.parentNode; g.appendChild(elem); - batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent)); + batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent)); } if (!batchCmd.isEmpty()) addCommandToHistory(batchCmd); - + // update selection selectOnly([g], true); }; @@ -8326,27 +8326,27 @@ var glist = getTransformList(g); var m = transformListToTransform(glist).matrix; - + var batchCmd = new BatchCommand("Push group properties"); // TODO: get all fill/stroke properties from the group that we are about to destroy - // "fill", "fill-opacity", "fill-rule", "stroke", "stroke-dasharray", "stroke-dashoffset", - // "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", + // "fill", "fill-opacity", "fill-rule", "stroke", "stroke-dasharray", "stroke-dashoffset", + // "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", // "stroke-width" // and then for each child, if they do not have the attribute (or the value is 'inherit') // then set the child's attribute - + var i = 0; var gangle = getRotationAngle(g); - + var gattrs = $(g).attr(['filter', 'opacity']); var gfilter, gblur; - + for(var i = 0; i < len; i++) { var elem = children[i]; - + if(elem.nodeType !== 1) continue; - + if(gattrs.opacity !== null && gattrs.opacity !== 1) { var c_opac = elem.getAttribute('opacity') || 1; var new_opac = Math.round((elem.getAttribute('opacity') || 1) * gattrs.opacity * 100)/100; @@ -8363,7 +8363,7 @@ } else if(cblur === 0) { cblur = gblur; } - + // If child has no current filter, get group's filter or clone it. if(!orig_cblur) { // Set group's filter to use first child's ID @@ -8379,28 +8379,28 @@ } // Change this in future for different filters - var suffix = (gfilter.firstChild.tagName === 'feGaussianBlur')?'blur':'filter'; + var suffix = (gfilter.firstChild.tagName === 'feGaussianBlur')?'blur':'filter'; gfilter.id = elem.id + '_' + suffix; changeSelectedAttribute('filter', 'url(#' + gfilter.id + ')', [elem]); - - // Update blur value + + // Update blur value if(cblur) { changeSelectedAttribute('stdDeviation', cblur, [gfilter.firstChild]); canvas.setBlurOffsets(gfilter, cblur); } } - + var chtlist = getTransformList(elem); // Don't process gradient transforms if(~elem.tagName.indexOf('Gradient')) chtlist = null; - + // Hopefully not a problem to add this. Necessary for elements like <desc/> if(!chtlist) continue; - + // Apparently <defs> can get get a transformlist, but we don't want it to have one! if(elem.tagName === 'defs') continue; - + if (glist.numberOfItems) { // TODO: if the group's transform is just a rotate, we can always transfer the // rotate() down to the children (collapsing consecutive rotates and factoring @@ -8408,43 +8408,43 @@ if (gangle && glist.numberOfItems == 1) { // [Rg] [Rc] [Mc] // we want [Tr] [Rc2] [Mc] where: - // - [Rc2] is at the child's current center but has the + // - [Rc2] is at the child's current center but has the // sum of the group and child's rotation angles - // - [Tr] is the equivalent translation that this child + // - [Tr] is the equivalent translation that this child // undergoes if the group wasn't there - + // [Tr] = [Rg] [Rc] [Rc2_inv] - + // get group's rotation matrix (Rg) var rgm = glist.getItem(0).matrix; - + // get child's rotation matrix (Rc) var rcm = svgroot.createSVGMatrix(); var cangle = getRotationAngle(elem); if (cangle) { rcm = chtlist.getItem(0).matrix; } - + // get child's old center of rotation var cbox = svgedit.utilities.getBBox(elem); var ceqm = transformListToTransform(chtlist).matrix; var coldc = transformPoint(cbox.x+cbox.width/2, cbox.y+cbox.height/2,ceqm); - + // sum group and child's angles var sangle = gangle + cangle; - + // get child's rotation at the old center (Rc2_inv) var r2 = svgroot.createSVGTransform(); r2.setRotate(sangle, coldc.x, coldc.y); - + // calculate equivalent translate var trm = matrixMultiply(rgm, rcm, r2.matrix.inverse()); - + // set up tlist if (cangle) { chtlist.removeItem(0); } - + if (sangle) { if(chtlist.numberOfItems) { chtlist.insertItemBefore(r2, 0); @@ -8464,9 +8464,9 @@ } } else { // more complicated than just a rotate - + // transfer the group's transform down to each child and then - // call recalculateDimensions() + // call recalculateDimensions() var oldxform = elem.getAttribute("transform"); var changes = {}; changes["transform"] = oldxform ? oldxform : ""; @@ -8486,16 +8486,16 @@ } } - + // remove transform and make it undo-able if (xform) { var changes = {}; changes["transform"] = xform; g.setAttribute("transform", ""); - g.removeAttribute("transform"); + g.removeAttribute("transform"); batchCmd.addSubCommand(new ChangeElementCommand(g, changes)); } - + if (undoable && !batchCmd.isEmpty()) { return batchCmd; } @@ -8523,25 +8523,25 @@ if(parents_a.length) { g = parents_a[0]; } - + // Look for parent "a" if (g.tagName === "g" || g.tagName === "a") { - + var batchCmd = new BatchCommand("Ungroup Elements"); var cmd = pushGroupProperties(g, true); if(cmd) batchCmd.addSubCommand(cmd); - + var parent = g.parentNode; var anchor = g.nextSibling; var children = new Array(g.childNodes.length); - + var i = 0; - + while (g.firstChild) { var elem = g.firstChild; var oldNextSibling = elem.nextSibling; var oldParent = elem.parentNode; - + // Remove child title elements if(elem.tagName === 'title') { var nextSibling = elem.nextSibling; @@ -8549,21 +8549,21 @@ oldParent.removeChild(elem); continue; } - + children[i++] = elem = parent.insertBefore(elem, anchor); batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent)); } - // remove the group from the selection + // remove the group from the selection clearSelection(); - + // delete the group element (but make undo-able) var gNextSibling = g.nextSibling; g = parent.removeChild(g); batchCmd.addSubCommand(new RemoveElementCommand(g, gNextSibling, parent)); if (!batchCmd.isEmpty()) addCommandToHistory(batchCmd); - + // update selection addToSelection(children); } @@ -8591,7 +8591,7 @@ }; // Function: moveToBottomSelectedElement -// Repositions the selected element to the top in the DOM to appear under +// Repositions the selected element to the top in the DOM to appear under // other elements this.moveToBottomSelectedElement = function() { var selected = selectedElements.filter(Boolean).reverse(); @@ -8624,7 +8624,7 @@ // Moves the select element up or down the stack, based on the visibly // intersecting elements // -// Parameters: +// Parameters: // dir - String that's either 'Up' or 'Down' this.moveUpDownSelected = function(dir) { var selected = selectedElements.filter(Boolean); @@ -8648,7 +8648,7 @@ return false; }); if(!closest) return; - + var t = selected; var oldParent = t.parentNode; var oldNextSibling = t.nextSibling; @@ -8664,7 +8664,7 @@ }; // Function: moveSelectedElements -// Moves selected elements on the X/Y axis +// Moves selected elements on the X/Y axis // // Parameters: // dx - Float with the distance to move on the x-axis @@ -8688,14 +8688,14 @@ if (selected != null) { // if (i==0) // selectedBBoxes[0] = svgedit.utilities.getBBox(selected); - + // var b = {}; // for(var j in selectedBBoxes[i]) b[j] = selectedBBoxes[i][j]; // selectedBBoxes[i] = b; - + var xform = svgroot.createSVGTransform(); var tlist = getTransformList(selected); - + // dx and dy could be arrays if (dx.constructor == Array) { // if (i==0) { @@ -8716,12 +8716,12 @@ } else { tlist.appendItem(xform); } - + var cmd = recalculateDimensions(selected); if (cmd) { batchCmd.addSubCommand(cmd); } - + selectorManager.requestSelector(selected).resize(); } } @@ -8734,7 +8734,7 @@ }; // Function: cloneSelectedElements -// Create deep DOM copies (clones) of all selected elements and move them slightly +// Create deep DOM copies (clones) of all selected elements and move them slightly // from their originals this.cloneSelectedElements = function(x,y, drag) { var batchCmd = new BatchCommand("Clone Elements"); @@ -8753,7 +8753,7 @@ clones = [] while (i--) { // clone each element and replace it within copiedElements - var elem = copiedElements[i] + var elem = copiedElements[i] var clone = copyElem(copiedElements[i]); var parent = (current_group || getCurrentDrawing().getCurrentLayer()) if (drag) { @@ -8769,7 +8769,7 @@ clones.push(clone) batchCmd.addSubCommand(new InsertElementCommand(clone)); } - + if (!batchCmd.isEmpty()) { addToSelection(copiedElements.reverse()); // Need to reverse for correct selection-adding if (!drag) this.moveSelectedElements(x,y,false); @@ -8783,7 +8783,7 @@ // // Parameters: // type - String with single character indicating the alignment type -// relative_to - String that must be one of the following: +// relative_to - String that must be one of the following: // "selected", "largest", "smallest", "page" this.alignSelectedElements = function(type, relative_to) { var bboxes = [], angles = []; @@ -8795,7 +8795,7 @@ if (selectedElements[i] == null) break; var elem = selectedElements[i]; bboxes[i] = getStrokedBBox([elem]); - + // now bbox is axis-aligned and handles rotation switch (relative_to) { case 'smallest': @@ -8874,13 +8874,13 @@ this.contentH = getResolution().h; // Function: updateCanvas -// Updates the editor canvas width/height/position after a zoom has occurred +// Updates the editor canvas width/height/position after a zoom has occurred // // Parameters: // w - Float with the new width // h - Float with the new height // -// Returns: +// Returns: // Object with the following values: // * x - The canvas' new x coordinate // * y - The canvas' new y coordinate @@ -8904,7 +8904,7 @@ 'y': y, "viewBox" : "0 0 " + this.contentW + " " + this.contentH }); - + assignAttributes(bg, { width: svgcontent.getAttribute('width'), height: svgcontent.getAttribute('height'), @@ -8919,9 +8919,9 @@ 'height': '100%' }); } - + selectorManager.selectorParentGroup.setAttribute("transform","translate(" + x + "," + y + ")"); - + return {x:x, y:y, old_x:old_x, old_y:old_y, d_x:x - old_x, d_y:y - old_y}; } @@ -8976,12 +8976,12 @@ num = 0; } else if(num < 0) { num = all_elems.length-1; - } + } elem = all_elems[num]; break; - } + } } - } + } selectOnly([elem], true); call("selected", selectedElements); } @@ -8989,7 +8989,7 @@ this.clear(); -// DEPRECATED: getPrivateMethods +// DEPRECATED: getPrivateMethods // Since all methods are/should be public somehow, this function should be removed // Being able to access private methods publicly seems wrong somehow, -- Gitblit v1.9.1