diff --git a/public/svg-edit/editor/browser.js b/public/svg-edit/editor/browser.js index 48809fe7..57f5598f 100644 --- a/public/svg-edit/editor/browser.js +++ b/public/svg-edit/editor/browser.js @@ -85,6 +85,17 @@ var supportsTextCharPos_ = (function() { return retValue; })(); +var supportsPathBBox_ = (function() { + var svgcontent = document.createElementNS(svgns, 'svg'); + document.documentElement.appendChild(svgcontent); + var path = document.createElementNS(svgns, 'path'); + path.setAttribute('d','M0,0 C0,0 10,10 10,0'); + svgcontent.appendChild(path); + var bbox = path.getBBox(); + document.documentElement.removeChild(svgcontent); + return (bbox.height > 4 && bbox.height < 5); +})(); + var supportsEditableText_ = (function() { // TODO: Find better way to check support for this return isOpera_; @@ -129,6 +140,7 @@ svgedit.browser.supportsXpath = function() { return supportsXpath_; } svgedit.browser.supportsPathReplaceItem = function() { return supportsPathReplaceItem_; } svgedit.browser.supportsPathInsertItemBefore = function() { return supportsPathInsertItemBefore_; } +svgedit.browser.supportsPathBBox = function() { return supportsPathBBox_; } svgedit.browser.supportsTextCharPos = function() { return supportsTextCharPos_; } svgedit.browser.supportsEditableText = function() { return supportsEditableText_; } svgedit.browser.supportsGoodDecimals = function() { return supportsGoodDecimals_; } diff --git a/public/svg-edit/editor/draw.js b/public/svg-edit/editor/draw.js index 2ea8df86..f3152633 100644 --- a/public/svg-edit/editor/draw.js +++ b/public/svg-edit/editor/draw.js @@ -23,6 +23,13 @@ var svg_ns = "http://www.w3.org/2000/svg"; var se_ns = "http://svg-edit.googlecode.com"; var xmlns_ns = "http://www.w3.org/2000/xmlns/"; +var RandomizeModes = { + LET_DOCUMENT_DECIDE: 0, + ALWAYS_RANDOMIZE: 1, + NEVER_RANDOMIZE: 2 +}; +var randomize_ids = RandomizeModes.LET_DOCUMENT_DECIDE; + /** * This class encapsulates the concept of a layer in the drawing * @param name {String} Layer name @@ -42,6 +49,23 @@ svgedit.draw.Layer.prototype.getGroup = function() { }; +// Called to ensure that drawings will or will not have randomized ids. +// The current_drawing will have its nonce set if it doesn't already. +// +// Params: +// enableRandomization - flag indicating if documents should have randomized ids +svgedit.draw.randomizeIds = function(enableRandomization, current_drawing) { + randomize_ids = enableRandomization == false ? + RandomizeModes.NEVER_RANDOMIZE : + RandomizeModes.ALWAYS_RANDOMIZE; + + if (randomize_ids == RandomizeModes.ALWAYS_RANDOMIZE && !current_drawing.getNonce()) { + current_drawing.setNonce(Math.floor(Math.random() * 100001)); + } else if (randomize_ids == RandomizeModes.NEVER_RANDOMIZE && current_drawing.getNonce()) { + current_drawing.clearNonce(); + } +}; + /** * This class encapsulates the concept of a SVG-edit drawing * @@ -100,7 +124,15 @@ svgedit.draw.Drawing = function(svgElem, opt_idPrefix) { * The nonce to use to uniquely identify elements across drawings. * @type {!String} */ - this.nonce_ = this.svgElem_.getAttributeNS(se_ns, 'nonce') || ""; + this.nonce_ = ""; + var n = this.svgElem_.getAttributeNS(se_ns, 'nonce'); + // If already set in the DOM, use the nonce throughout the document + // else, if randomizeIds(true) has been called, create and set the nonce. + if (!!n && randomize_ids != RandomizeModes.NEVER_RANDOMIZE) { + this.nonce_ = n; + } else if (randomize_ids == RandomizeModes.ALWAYS_RANDOMIZE) { + this.setNonce(Math.floor(Math.random() * 100001)); + } }; svgedit.draw.Drawing.prototype.getElem_ = function(id) { @@ -121,10 +153,16 @@ svgedit.draw.Drawing.prototype.getNonce = function() { return this.nonce_; }; -svgedit.draw.Drawing.prototype.setNonce = function(nonce) { - this.nonce_ = nonce; +svgedit.draw.Drawing.prototype.setNonce = function(n) { this.svgElem_.setAttributeNS(xmlns_ns, 'xmlns:se', se_ns); - this.svgElem_.setAttributeNS(se_ns, 'se:nonce', nonce); + this.svgElem_.setAttributeNS(se_ns, 'se:nonce', n); + this.nonce_ = n; +}; + +svgedit.draw.Drawing.prototype.clearNonce = function() { + // We deliberately leave any se:nonce attributes alone, + // we just don't use it to randomize ids. + this.nonce_ = ""; }; /** diff --git a/public/svg-edit/editor/extensions/ext-arrows.js b/public/svg-edit/editor/extensions/ext-arrows.js index ebc3930c..4bb5cd25 100644 --- a/public/svg-edit/editor/extensions/ext-arrows.js +++ b/public/svg-edit/editor/extensions/ext-arrows.js @@ -15,8 +15,8 @@ svgEditor.addExtension("Arrows", function(S) { randomize_ids = S.randomize_ids, selElems; - svgCanvas.bind('setarrownonce', setArrowNonce); - svgCanvas.bind('unsetsetarrownonce', unsetArrowNonce); + svgCanvas.bind('setnonce', setArrowNonce); + svgCanvas.bind('unsetnonce', unsetArrowNonce); var lang_list = { "en":[ diff --git a/public/svg-edit/editor/history.js b/public/svg-edit/editor/history.js index 98eb5a36..d5edda2e 100644 --- a/public/svg-edit/editor/history.js +++ b/public/svg-edit/editor/history.js @@ -36,13 +36,23 @@ var removedElements = {}; * An interface that all command objects must implement. * * interface svgedit.history.HistoryCommand { - * void apply(); - * void unapply(); + * void apply(svgedit.history.HistoryEventHandler); + * void unapply(svgedit.history.HistoryEventHandler); * Element[] elements(); * String getText(); * * static String type(); * } + * + * Interface: svgedit.history.HistoryEventHandler + * An interface for objects that will handle history events. + * + * interface svgedit.history.HistoryEventHandler { + * void handleHistoryEvent(eventType, command); + * } + * + * eventType is a string conforming to one of the HistoryEvent types. + * command is an object fulfilling the HistoryCommand interface. */ // Class: svgedit.history.MoveElementCommand @@ -213,8 +223,12 @@ svgedit.history.RemoveElementCommand.prototype.unapply = function(handler) { } svgedit.transformlist.removeElementFromListMap(this.elem); + if(this.nextSibling == null) { + console.log('Error: reference element was lost'); + } this.parent.insertBefore(this.elem, this.nextSibling); + if (handler) { handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this); } @@ -443,18 +457,6 @@ svgedit.history.BatchCommand.prototype.isEmpty = function() { }; -/** - * Interface: svgedit.history.HistoryEventHandler - * An interface for objects that will handle history events. - * - * interface svgedit.history.HistoryEventHandler { - * void handleHistoryEvent(eventType, command); - * } - * - * eventType is a string conforming to one of the HistoryEvent types (see above). - * command is an object fulfilling the HistoryCommand interface (see above). - */ - // Class: svgedit.history.UndoManager // Parameters: // historyEventHandler - an object that conforms to the HistoryEventHandler interface diff --git a/public/svg-edit/editor/svg-editor.css b/public/svg-edit/editor/svg-editor.css index dc5f2fc2..81498fe8 100644 --- a/public/svg-edit/editor/svg-editor.css +++ b/public/svg-edit/editor/svg-editor.css @@ -532,7 +532,7 @@ position: absolute; top: 77px; left: 40px; - right: -2px; + right: 0; line-height: 22px; overflow: auto; border: 1px solid #777; diff --git a/public/svg-edit/editor/svg-editor.js b/public/svg-edit/editor/svg-editor.js index 0889a374..f6eea4fb 100644 --- a/public/svg-edit/editor/svg-editor.js +++ b/public/svg-edit/editor/svg-editor.js @@ -1535,8 +1535,8 @@ } if(unit) { - x = svgCanvas.convertUnit(x); - y = svgCanvas.convertUnit(y); + x = svgedit.units.convertUnit(x); + y = svgedit.units.convertUnit(y); } $('#selected_x').val(x || 0); @@ -1560,8 +1560,8 @@ if(point) { var seg_type = $('#seg_type'); if(unit) { - point.x = svgCanvas.convertUnit(point.x); - point.y = svgCanvas.convertUnit(point.y); + point.x = svgedit.units.convertUnit(point.x); + point.y = svgedit.units.convertUnit(point.y); } $('#path_node_x').val(point.x); $('#path_node_y').val(point.y); @@ -1622,7 +1622,7 @@ var attrVal = elem.getAttribute(item); if(curConfig.baseUnit !== 'px' && elem[item]) { var bv = elem[item].baseVal.value; - attrVal = svgCanvas.convertUnit(bv); + attrVal = svgedit.units.convertUnit(bv); } $('#' + el_name + '_' + item).val(attrVal || 0); @@ -2734,8 +2734,8 @@ // update resolution option with actual resolution var res = svgCanvas.getResolution(); if(curConfig.baseUnit !== "px") { - res.w = svgCanvas.convertUnit(res.w) + curConfig.baseUnit; - res.h = svgCanvas.convertUnit(res.h) + curConfig.baseUnit; + res.w = svgedit.units.convertUnit(res.w) + curConfig.baseUnit; + res.h = svgedit.units.convertUnit(res.h) + curConfig.baseUnit; } $('#canvas_width').val(res.w); @@ -4583,7 +4583,7 @@ updateCanvas(true); // }); - // var revnums = "svg-editor.js ($Rev: 1956 $) "; + // var revnums = "svg-editor.js ($Rev: 1973 $) "; // revnums += svgCanvas.getVersion(); // $('#copyright')[0].setAttribute("title", revnums); @@ -4721,6 +4721,13 @@ }); }; + Editor.disableUI = function(featList) { +// $(function() { +// $('#tool_wireframe, #tool_image, #main_button, #tool_source, #sidepanels').remove(); +// $('#tools_top').css('left', 5); +// }); + }; + Editor.loadFromURL = function(url, opts) { if(!opts) opts = {}; diff --git a/public/svg-edit/editor/svgcanvas.js b/public/svg-edit/editor/svgcanvas.js index 3ca83a52..6059a408 100644 --- a/public/svg-edit/editor/svgcanvas.js +++ b/public/svg-edit/editor/svgcanvas.js @@ -151,17 +151,29 @@ container.appendChild(svgroot); // The actual element that represents the final output SVG element var svgcontent = svgdoc.createElementNS(svgns, "svg"); -$(svgcontent).attr({ - id: 'svgcontent', - width: dimensions[0], - height: dimensions[1], - x: dimensions[0], - y: dimensions[1], - overflow: curConfig.show_outside_canvas ? 'visible' : 'hidden', - xmlns: svgns, - "xmlns:se": se_ns, - "xmlns:xlink": xlinkns -}).appendTo(svgroot); +// This function resets the svgcontent element while keeping it in the DOM. +var clearSvgContentElement = canvas.clearSvgContentElement = function() { + while (svgcontent.firstChild) { svgcontent.removeChild(svgcontent.firstChild); } + + // TODO: Clear out all other attributes first? + $(svgcontent).attr({ + id: 'svgcontent', + width: dimensions[0], + height: dimensions[1], + x: dimensions[0], + y: dimensions[1], + overflow: curConfig.show_outside_canvas ? 'visible' : 'hidden', + xmlns: svgns, + "xmlns:se": se_ns, + "xmlns:xlink": xlinkns + }).appendTo(svgroot); + + // TODO: make this string optional and set by the client + var comment = svgdoc.createComment(" Created with SVG-edit - http://svg-edit.googlecode.com/ "); + // Lead to invalid content with Instiki's Sanitizer + // svgcontent.appendChild(comment); +}; +clearSvgContentElement(); // Prefix string for element IDs var idprefix = "svg_"; @@ -177,27 +189,15 @@ canvas.setIdPrefix = function(p) { // Current svgedit.draw.Drawing object // @type {svgedit.draw.Drawing} -var current_drawing = new svgedit.draw.Drawing(svgcontent, idprefix); +canvas.current_drawing_ = new svgedit.draw.Drawing(svgcontent, idprefix); // Function: getCurrentDrawing // Returns the current Drawing. // @return {svgedit.draw.Drawing} var getCurrentDrawing = canvas.getCurrentDrawing = function() { - return current_drawing; + return canvas.current_drawing_; }; -// nonce to uniquify id's -var nonce = Math.floor(Math.random() * 100001); - -// Boolean to indicate whether or not IDs given to elements should be random -var randomize_ids = false; - -// Set nonce if randomize_ids = true -// TODO: Remove this? Given randomize_ids is set to false above, it seems useless. -if (randomize_ids) { - getCurrentDrawing().setNonce(nonce); -} - // Float displaying the current zoom level (1 = 100%, .5 = 50%, etc) var current_zoom = 1; @@ -386,7 +386,8 @@ svgedit.units.init({ getBaseUnit: function() { return curConfig.baseUnit; }, getElement: getElem, getHeight: function() { return svgcontent.getAttribute("height")/current_zoom; }, - getWidth: function() { return svgcontent.getAttribute("width")/current_zoom; } + getWidth: function() { return svgcontent.getAttribute("width")/current_zoom; }, + getRoundDigits: function() { return save_options.round_digits; } }); // import from units.js var convertToNum = canvas.convertToNum = svgedit.units.convertToNum; @@ -426,7 +427,7 @@ canvas.undoMgr = new svgedit.history.UndoManager({ call("changed", elems); var cmdType = cmd.type(); - var isApply = eventType == EventTypes.AFTER_APPLY; + var isApply = (eventType == EventTypes.AFTER_APPLY); if (cmdType == MoveElementCommand.type()) { var parent = isApply ? cmd.newParent : cmd.oldParent; if (parent == svgcontent) { @@ -442,6 +443,10 @@ canvas.undoMgr = new svgedit.history.UndoManager({ } else { if (!isApply) restoreRefElems(cmd.elem); } + + if(cmd.elem.tagName === 'use') { + setUseData(cmd.elem); + } } else if (cmdType == ChangeElementCommand.type()) { // if we are changing layer names, re-identify all layers if (cmd.elem.tagName == "title" && cmd.elem.parentNode.parentNode == svgcontent) { @@ -524,14 +529,17 @@ var restoreRefElems = function(elem) { } } } + + var childs = elem.getElementsByTagName('*'); + + if(childs.length) { + for(var i = 0, l = childs.length; i < l; i++) { + restoreRefElems(childs[i]); + } + } }; (function() { - // TODO: make this string optional and set by the client - var comment = svgdoc.createComment(" Created with SVG-edit - http://svg-edit.googlecode.com/ "); - // Lead to invalid content with Instiki's Sanitizer - // svgcontent.appendChild(comment); - // TODO For Issue 208: this is a start on a thumbnail // var svgthumb = svgdoc.createElementNS(svgns, "use"); // svgthumb.setAttribute('width', '100'); @@ -628,7 +636,7 @@ this.addExtension = function(name, ext_func) { var ext = ext_func($.extend(canvas.getPrivateMethods(), { svgroot: svgroot, svgcontent: svgcontent, - nonce: nonce, + nonce: getCurrentDrawing().getNonce(), selectorManager: selectorManager })); } else { @@ -640,32 +648,6 @@ this.addExtension = function(name, ext_func) { console.log('Cannot add extension "' + name + '", an extension by that name already exists"'); } }; - - -// Function: shortFloat -// Rounds a given value to a float with number of digits defined in save_options -// -// Parameters: -// val - The value as a String, Number or Array of two numbers to be rounded -// -// Returns: -// If a string/number was given, returns a Float. If an array, return a string -// with comma-seperated floats -var shortFloat = function(val) { - var digits = save_options.round_digits; - if(!isNaN(val)) { - // Note that + converts to Number - return +((+val).toFixed(digits)); - } else if($.isArray(val)) { - return shortFloat(val[0]) + ',' + shortFloat(val[1]); - } else { - return parseFloat(val).toFixed(digits) - 0; - } -} - -this.convertUnit = function(val, unit) { - return shortFloat(svgedit.units.convertUnit(val, unit)); -}; // This method rounds the incoming value to the nearest value based on the current_zoom var round = this.round = function(val) { @@ -1547,6 +1529,23 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) { } } + // 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] + case 'line': + case 'polyline': + case 'polygon': + case 'path': + break; + default: + if( + (tlist.numberOfItems === 1 && tlist.getItem(0).type === 1) + || (tlist.numberOfItems === 2 && tlist.getItem(0).type === 1 && tlist.getItem(0).type === 4) + ) { + return null; + } + } + // Grouped SVG element var gsvg = $(selected).data('gsvg'); @@ -2184,6 +2183,7 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) { if (tlist.numberOfItems == 0) { selected.removeAttribute("transform"); } + batchCmd.addSubCommand(new ChangeElementCommand(selected, initial)); return batchCmd; @@ -5832,9 +5832,9 @@ var pathActions = canvas.pathActions = function() { var addToD = function(pnts, more, last) { var str = ''; var more = more?' '+more.join(' '):''; - var last = last?' '+shortFloat(last):''; + var last = last?' '+svgedit.units.shortFloat(last):''; $.each(pnts, function(i, pnt) { - pnts[i] = shortFloat(pnt); + pnts[i] = svgedit.units.shortFloat(pnt); }); d += letter + pnts.join(' ') + more + last; } @@ -5984,6 +5984,8 @@ 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']; @@ -5996,7 +5998,9 @@ var removeUnusedDefElems = this.removeUnusedDefElems = function() { var el = all_els[i]; for(var j = 0; j < alen; j++) { var ref = getUrlFromAttr(el.getAttribute(attrs[j])); - if(ref) defelem_uses.push(ref.substr(1)); + if(ref) { + defelem_uses.push(ref.substr(1)); + } } // gradients can refer to other gradients @@ -6019,16 +6023,7 @@ var removeUnusedDefElems = this.removeUnusedDefElems = function() { numRemoved++; } } - - // Remove defs if empty - var i = defs.length; - while (i--) { - var def = defs[i]; - if(!def.getElementsByTagNameNS(svgns,'*').length) { - def.parentNode.removeChild(def); - } - } - + return numRemoved; } @@ -6119,16 +6114,16 @@ this.svgToString = function(elem, indent) { // if(curConfig.baseUnit !== "px") { // var unit = curConfig.baseUnit; // var unit_m = svgedit.units.getTypeMap()[unit]; -// res.w = shortFloat(res.w / unit_m) -// res.h = shortFloat(res.h / unit_m) +// 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(' ') + '"'; // res.w += unit; // res.h += unit; // } if(unit !== "px") { - res.w = this.convertUnit(res.w, unit) + unit; - res.h = this.convertUnit(res.h, unit) + unit; + 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+'"'); @@ -6168,6 +6163,9 @@ this.svgToString = function(elem, indent) { } } } 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); @@ -6180,9 +6178,9 @@ this.svgToString = function(elem, indent) { out.push(" "); if(attr.localName === 'd') attrVal = pathActions.convertPath(elem, true); if(!isNaN(attrVal)) { - attrVal = shortFloat(attrVal); + attrVal = svgedit.units.shortFloat(attrVal); } else if(unit_re.test(attrVal)) { - attrVal = shortFloat(attrVal) + unit; + attrVal = svgedit.units.shortFloat(attrVal) + unit; } // Embed images when saving @@ -6350,9 +6348,9 @@ this.getSvgString = function() { return this.svgCanvasToString(); }; -//function randomizeIds -// This function determines whether to add a nonce to the prefix, when -// generating IDs in SVG-Edit +// 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 @@ -6363,17 +6361,11 @@ this.getSvgString = function() { // this.randomizeIds = function() { if (arguments.length > 0 && arguments[0] == false) { - randomize_ids = false; - if (extensions["Arrows"]) call("unsetarrownonce") ; + svgedit.draw.randomizeIds(false, getCurrentDrawing()); } else { - randomize_ids = true; - var drawing = getCurrentDrawing(); - if (!drawing.getSvgElem().getAttributeNS(se_ns, 'nonce')) { - drawing.setNonce(nonce); - if (extensions["Arrows"]) call("setarrownonce", nonce); - } + svgedit.draw.randomizeIds(true, getCurrentDrawing()); } -} +}; // Function: uniquifyElems // Ensure each element has a unique ID @@ -6472,9 +6464,16 @@ var uniquifyElems = this.uniquifyElems = function(g) { // Function setUseData // Assigns reference data for each use element var setUseData = this.setUseData = function(parent) { - $(parent).find('use').each(function() { + 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); + if(!ref_elem) return; $(this).data('ref', ref_elem); if(ref_elem.tagName == 'symbol' || ref_elem.tagName == 'svg') { $(this).data('symbol', ref_elem); @@ -6669,8 +6668,11 @@ var convertToGroup = this.convertToGroup = function(elem) { selectOnly([g]); - batchCmd.addSubCommand(pushGroupProperties(g, true)); -// + var cm = pushGroupProperties(g, true); + if(cm) { + batchCmd.addSubCommand(cm); + } + addCommandToHistory(batchCmd); } else { @@ -6706,19 +6708,16 @@ this.setSvgString = function(xmlString) { var content = $(svgcontent); - current_drawing = new svgedit.draw.Drawing(svgcontent, idprefix); + canvas.current_drawing_ = new svgedit.draw.Drawing(svgcontent, idprefix); // retrieve or set the nonce - n = svgcontent.getAttributeNS(se_ns, 'nonce'); - if (n) { - randomize_ids = true; - nonce = n; - if (extensions["Arrows"]) call("setarrownonce", n) ; - } else if (randomize_ids) { - current_drawing.setNonce(nonce); - if (extensions["Arrows"]) call("setarrownonce", nonce) ; + var nonce = getCurrentDrawing().getNonce(); + if (nonce) { + call("setnonce", nonce); + } else { + call("unsetnonce"); } - + // change image href vals if possible content.find('image').each(function() { var image = this; @@ -7042,10 +7041,10 @@ this.cloneLayer = function(name) { // 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 = current_drawing.getCurrentLayer(); + var current_layer = getCurrentDrawing().getCurrentLayer(); var nextSibling = current_layer.nextSibling; var parent = current_layer.parentNode; - current_layer = current_drawing.deleteCurrentLayer(); + current_layer = getCurrentDrawing().deleteCurrentLayer(); if (current_layer) { var batchCmd = new BatchCommand("Delete Layer"); // store in our Undo History @@ -7086,18 +7085,19 @@ this.setCurrentLayer = function(name) { // Returns: // true if the rename succeeded, false otherwise. this.renameCurrentLayer = function(newname) { - if (current_drawing.current_layer) { - var oldLayer = current_drawing.current_layer; + var drawing = getCurrentDrawing(); + if (drawing.current_layer) { + var oldLayer = drawing.current_layer; // setCurrentLayer will return false if the name doesn't already exist // this means we are free to rename our oldLayer if (!canvas.setCurrentLayer(newname)) { var batchCmd = new BatchCommand("Rename Layer"); // find the index of the layer - for (var i = 0; i < current_drawing.getNumLayers(); ++i) { - if (current_drawing.all_layers[i][1] == oldLayer) break; + for (var i = 0; i < drawing.getNumLayers(); ++i) { + if (drawing.all_layers[i][1] == oldLayer) break; } - var oldname = current_drawing.getLayerName(i); - current_drawing.all_layers[i][0] = svgedit.utilities.toXml(newname); + 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; @@ -7116,7 +7116,7 @@ this.renameCurrentLayer = function(newname) { } } } - current_drawing.current_layer = oldLayer; + drawing.current_layer = oldLayer; } return false; }; @@ -7133,31 +7133,32 @@ this.renameCurrentLayer = function(newname) { // Returns: // true if the current layer position was changed, false otherwise. this.setCurrentLayerPosition = function(newpos) { - if (current_drawing.current_layer && newpos >= 0 && newpos < current_drawing.getNumLayers()) { - for (var oldpos = 0; oldpos < current_drawing.getNumLayers(); ++oldpos) { - if (current_drawing.all_layers[oldpos][1] == current_drawing.current_layer) break; + var drawing = getCurrentDrawing(); + if (drawing.current_layer && newpos >= 0 && newpos < drawing.getNumLayers()) { + for (var oldpos = 0; oldpos < drawing.getNumLayers(); ++oldpos) { + if (drawing.all_layers[oldpos][1] == drawing.current_layer) break; } // some unknown error condition (current_layer not in all_layers) - if (oldpos == current_drawing.getNumLayers()) { return false; } + 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; - var oldNextSibling = current_drawing.current_layer.nextSibling; + var oldNextSibling = drawing.current_layer.nextSibling; if (newpos > oldpos ) { - if (newpos < current_drawing.getNumLayers()-1) { - refLayer = current_drawing.all_layers[newpos+1][1]; + if (newpos < drawing.getNumLayers()-1) { + refLayer = drawing.all_layers[newpos+1][1]; } } // if our new position is above us, we need to insert before the node at newpos else { - refLayer = current_drawing.all_layers[newpos][1]; + refLayer = drawing.all_layers[newpos][1]; } - svgcontent.insertBefore(current_drawing.current_layer, refLayer); - addCommandToHistory(new MoveElementCommand(current_drawing.current_layer, oldNextSibling, svgcontent)); + svgcontent.insertBefore(drawing.current_layer, refLayer); + addCommandToHistory(new MoveElementCommand(drawing.current_layer, oldNextSibling, svgcontent)); identifyLayers(); - canvas.setCurrentLayer(current_drawing.getLayerName(newpos)); + canvas.setCurrentLayer(drawing.getLayerName(newpos)); return true; } @@ -7207,9 +7208,10 @@ this.setLayerVisibility = function(layername, bVisible) { this.moveSelectedToLayer = function(layername) { // find the layer var layer = null; - for (var i = 0; i < current_drawing.getNumLayers(); ++i) { - if (current_drawing.getLayerName(i) == layername) { - layer = current_drawing.all_layers[i][1]; + var drawing = getCurrentDrawing(); + for (var i = 0; i < drawing.getNumLayers(); ++i) { + if (drawing.getLayerName(i) == layername) { + layer = drawing.all_layers[i][1]; break; } } @@ -7237,28 +7239,29 @@ this.moveSelectedToLayer = function(layername) { this.mergeLayer = function(skipHistory) { var batchCmd = new BatchCommand("Merge Layer"); - var prev = $(current_drawing.current_layer).prev()[0]; + var drawing = getCurrentDrawing(); + var prev = $(drawing.current_layer).prev()[0]; if(!prev) return; - var childs = current_drawing.current_layer.childNodes; + var childs = drawing.current_layer.childNodes; var len = childs.length; - var layerNextSibling = current_drawing.current_layer.nextSibling; - batchCmd.addSubCommand(new RemoveElementCommand(current_drawing.current_layer, layerNextSibling, svgcontent)); + var layerNextSibling = drawing.current_layer.nextSibling; + batchCmd.addSubCommand(new RemoveElementCommand(drawing.current_layer, layerNextSibling, svgcontent)); - while(current_drawing.current_layer.firstChild) { - var ch = current_drawing.current_layer.firstChild; + while(drawing.current_layer.firstChild) { + var ch = drawing.current_layer.firstChild; if(ch.localName == 'title') { var chNextSibling = ch.nextSibling; - batchCmd.addSubCommand(new RemoveElementCommand(ch, chNextSibling, current_drawing.current_layer)); - current_drawing.current_layer.removeChild(ch); + batchCmd.addSubCommand(new RemoveElementCommand(ch, chNextSibling, drawing.current_layer)); + drawing.current_layer.removeChild(ch); continue; } var oldNextSibling = ch.nextSibling; prev.appendChild(ch); - batchCmd.addSubCommand(new MoveElementCommand(ch, oldNextSibling, current_drawing.current_layer)); + batchCmd.addSubCommand(new MoveElementCommand(ch, oldNextSibling, drawing.current_layer)); } // Remove current layer - svgcontent.removeChild(current_drawing.current_layer); + svgcontent.removeChild(drawing.current_layer); if(!skipHistory) { clearSelection(); @@ -7269,13 +7272,14 @@ this.mergeLayer = function(skipHistory) { addCommandToHistory(batchCmd); } - current_drawing.current_layer = prev; + drawing.current_layer = prev; return batchCmd; } this.mergeAllLayers = function() { var batchCmd = new BatchCommand("Merge all Layers"); - current_drawing.current_layer = current_drawing.all_layers[current_drawing.getNumLayers()-1][1]; + var drawing = getCurrentDrawing(); + drawing.current_layer = drawing.all_layers[drawing.getNumLayers()-1][1]; while($(svgcontent).children('g').length > 1) { batchCmd.addSubCommand(canvas.mergeLayer(true)); } @@ -7342,29 +7346,26 @@ var setContext = this.setContext = function(elem) { this.clear = function() { pathActions.clear(); - // clear the svgcontent node - var nodes = svgcontent.childNodes; - var len = svgcontent.childNodes.length; - var i = 0; clearSelection(); - for(var rep = 0; rep < len; rep++){ - if (nodes[i].nodeType == 1) { // element node - svgcontent.removeChild(nodes[i]); - } else { - i++; - } - } + + // clear the svgcontent node + canvas.clearSvgContentElement(); + + // create new document + canvas.current_drawing_ = new svgedit.draw.Drawing(svgcontent); + // create empty first layer - current_drawing.all_layers = []; - canvas.createLayer("Layer 1"); // clear the undo stack canvas.undoMgr.resetUndoStack(); + // reset the selector manager selectorManager.initGroup(); + // reset the rubber band box rubberBox = selectorManager.getRubberBandBox(); + call("cleared"); }; @@ -7407,7 +7408,7 @@ this.getZoom = function(){return current_zoom;}; // Function: getVersion // Returns a string which describes the revision number of SvgCanvas. this.getVersion = function() { - return "svgcanvas.js ($Rev: 1961 $)"; + return "svgcanvas.js ($Rev: 1972 $)"; }; // Function: setUiStrings @@ -8730,8 +8731,8 @@ var changeSelectedAttributeNoUndo = function(attr, newValue, elems) { selectedBBoxes[i] = getBBox(elem); // Use the Firefox ffClone hack for text elements with gradients or // where other text attributes are changed. - if(elem.nodeName == 'text') { - if((newValue+'').indexOf('url') == 0 || ['font-size','font-family','x','y'].indexOf(attr) >= 0 && elem.textContent) { + if(svgedit.browser.isGecko() && elem.nodeName === 'text' && /rotate/.test(elem.getAttribute('transform'))) { + if((newValue+'').indexOf('url') === 0 || ['font-size','font-family','x','y'].indexOf(attr) >= 0 && elem.textContent) { elem = ffClone(elem); } } @@ -9015,6 +9016,8 @@ var pushGroupProperties = this.pushGroupProperties = function(g, undoable) { 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; @@ -9149,7 +9152,8 @@ var pushGroupProperties = this.pushGroupProperties = function(g, undoable) { newxform.setMatrix(gm); chtlist.appendItem(newxform); } - batchCmd.addSubCommand(recalculateDimensions(elem)); + var cmd = recalculateDimensions(elem); + if(cmd) batchCmd.addSubCommand(cmd); } } @@ -9670,7 +9674,6 @@ this.getPrivateMethods = function() { round: round, runExtensions: runExtensions, sanitizeSvg: sanitizeSvg, - shortFloat: shortFloat, SVGEditTransformList: svgedit.transformlist.SVGTransformList, toString: toString, transformBox: svgedit.math.transformBox, diff --git a/public/svg-edit/editor/svgutils.js b/public/svg-edit/editor/svgutils.js index b56119b8..3dbf0f9d 100644 --- a/public/svg-edit/editor/svgutils.js +++ b/public/svg-edit/editor/svgutils.js @@ -186,7 +186,7 @@ svgedit.utilities.convertToXMLReferences = function(input) { return output; }; -// Function: text2xml +// Function: svgedit.utilities.text2xml // Cross-browser compatible method of converting a string to an XML tree // found this function here: http://groups.google.com/group/jquery-dev/browse_thread/thread/c6d11387c580a77f svgedit.utilities.text2xml = function(sXML) { @@ -209,7 +209,7 @@ svgedit.utilities.text2xml = function(sXML) { return out; }; -// Function: bboxToObj +// Function: svgedit.utilities.bboxToObj // Converts a SVGRect into an object. // // Parameters: @@ -226,7 +226,7 @@ svgedit.utilities.bboxToObj = function(bbox) { } }; -// Function: walkTree +// Function: svgedit.utilities.walkTree // Walks the tree and executes the callback on each element in a top-down fashion // // Parameters: @@ -242,7 +242,7 @@ svgedit.utilities.walkTree = function(elem, cbFn){ } }; -// Function: walkTreePost +// Function: svgedit.utilities.walkTreePost // Walks the tree and executes the callback on each element in a depth-first fashion // TODO: FIXME: Shouldn't this be calling walkTreePost? // @@ -418,7 +418,7 @@ svgedit.utilities.getBBox = function(elem) { selected.textContent = 'a'; // Some character needed for the selector to use. ret = selected.getBBox(); selected.textContent = ''; - } else if(elname === 'path' && svgedit.browser.isWebkit()) { + } else if(elname === 'path' && !svgedit.browser.supportsPathBBox()) { ret = svgedit.utilities.getPathBBox(selected); } else if(elname === 'use' && !svgedit.browser.isWebkit() || elname === 'foreignObject') { ret = selected.getBBox(); diff --git a/public/svg-edit/editor/units.js b/public/svg-edit/editor/units.js index 237489ae..8be858cb 100644 --- a/public/svg-edit/editor/units.js +++ b/public/svg-edit/editor/units.js @@ -51,6 +51,7 @@ var typeMap_ = {px: 1}; * function getElement() - returns an element in the container given an id * function getHeight() - returns the container's height * function getWidth() - returns the container's width + * function getRoundDigits() - returns the number of digits number should be rounded to */ /** @@ -95,6 +96,26 @@ svgedit.units.getTypeMap = function() { return typeMap_; }; +// Function: svgedit.units.shortFloat +// Rounds a given value to a float with number of digits defined in save_options +// +// Parameters: +// val - The value as a String, Number or Array of two numbers to be rounded +// +// Returns: +// If a string/number was given, returns a Float. If an array, return a string +// with comma-seperated floats +svgedit.units.shortFloat = function(val) { + var digits = elementContainer_.getRoundDigits(); + if(!isNaN(val)) { + // Note that + converts to Number + return +((+val).toFixed(digits)); + } else if($.isArray(val)) { + return svgedit.units.shortFloat(val[0]) + ',' + svgedit.units.shortFloat(val[1]); + } + return parseFloat(val).toFixed(digits) - 0; +}; + // Function: svgedit.units.convertUnit // Converts the number to given unit or baseUnit svgedit.units.convertUnit = function(val, unit) { @@ -102,7 +123,7 @@ svgedit.units.convertUnit = function(val, unit) { // baseVal.convertToSpecifiedUnits(unitNumMap[unit]); // var val = baseVal.valueInSpecifiedUnits; // baseVal.convertToSpecifiedUnits(1); - return val / typeMap_[unit]; + return svgedit.unit.shortFloat(val / typeMap_[unit]); }; // Function: svgedit.units.setUnitAttr @@ -249,7 +270,9 @@ svgedit.units.isValidUnit = function(attr, val) { result = (elem == null); } catch(e) {} return result; - } else valid = true; + } else { + valid = true; + } return valid; };