diff --git a/public/svg-edit/editor/images/svg_edit_icons.svg b/public/svg-edit/editor/images/svg_edit_icons.svg index 4f8f75e2..030635cd 100644 --- a/public/svg-edit/editor/images/svg_edit_icons.svg +++ b/public/svg-edit/editor/images/svg_edit_icons.svg @@ -1,4 +1,4 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/svg-edit/editor/locale/locale.js b/public/svg-edit/editor/locale/locale.js index a5297ec5..7d8c1166 100644 --- a/public/svg-edit/editor/locale/locale.js +++ b/public/svg-edit/editor/locale/locale.js @@ -6,10 +6,9 @@ * Copyright(c) 2009 Narendra Sisodya * */ -var put_locale = function(svgCanvas, given_param){ +var put_locale = function(svgCanvas, given_param, good_langs){ var lang_param; - // TODO: Make this array be based on entries in svg-editor.html - var good_langs = ['ar','cs','de','en','es','fa','fr','fy','hi','ja','nl','ro','ru','sk','zh-TW']; + if(given_param) { lang_param = given_param; } else { @@ -28,7 +27,7 @@ var put_locale = function(svgCanvas, given_param){ if($.inArray(lang_param, good_langs) == -1) { lang_param = "en"; } - + // don't bother on first run if language is English if(lang_param.indexOf("en") == 0) return; } diff --git a/public/svg-edit/editor/svg-editor.css b/public/svg-edit/editor/svg-editor.css index b02d14bd..0d946bc8 100644 --- a/public/svg-edit/editor/svg-editor.css +++ b/public/svg-edit/editor/svg-editor.css @@ -1,4 +1,4 @@ -body { +body { background: #E8E8E8; } @@ -681,11 +681,12 @@ span.zoom_tool { text-align: right; } -#svg_source_editor { +#svg_source_editor, #svg_foreign_editor{ display: none; } -#svg_source_editor #svg_source_overlay { +#svg_source_editor #svg_source_overlay, +#svg_foreign_editor #svg_foreign_overlay { position: absolute; top: 0px; right: 0px; @@ -696,7 +697,8 @@ span.zoom_tool { z-index: 5; } -#svg_source_editor #svg_source_container { +#svg_source_editor #svg_source_container, +#svg_foreign_editor #svg_foreign_container { position: absolute; top: 30px; left: 30px; @@ -778,7 +780,8 @@ span.zoom_tool { display: block; } -#svg_source_editor #svg_source_textarea { +#svg_source_editor #svg_source_textarea, +#svg_foreign_editor #svg_foreign_textarea { position: relative; width: 95%; top: 5px; @@ -787,7 +790,8 @@ span.zoom_tool { font-size: 12px; } -#svg_source_editor #tool_source_back { +#svg_source_editor #tool_source_back, +#svg_foreign_editor #tool_foreign_back { text-align: left; padding-left: 20px; } @@ -810,7 +814,7 @@ span.zoom_tool { text-align: left; } -#svg_source_editor button, #svg_docprops button { +#svg_source_editor button, #svg_foreign_editor button, #svg_docprops button { padding: 5px 5px 7px 28px; margin: 5px 20px 0 0; } @@ -845,6 +849,8 @@ span.zoom_tool { button#tool_source_save, button#tool_source_cancel, +button#tool_foreign_save, +button#tool_foreign_cancel, button#tool_docprops_save, button#tool_docprops_cancel { border:1px solid #dedede; @@ -963,4 +969,4 @@ button#tool_docprops_cancel { -webkit-border-radius: 0px; } -foreignObject { line-height:1.0; } \ No newline at end of file +foreignObject { line-height:1.0; } \ No newline at end of file diff --git a/public/svg-edit/editor/svg-editor.html b/public/svg-edit/editor/svg-editor.html index 891172b9..3b65501a 100644 --- a/public/svg-edit/editor/svg-editor.html +++ b/public/svg-edit/editor/svg-editor.html @@ -330,6 +330,22 @@ script type="text/javascript" src="locale/locale.min.js"> + +
+
+ + + +
+
+
@@ -365,6 +381,7 @@ script type="text/javascript" src="locale/locale.min.js">
+
@@ -452,6 +469,19 @@ script type="text/javascript" src="locale/locale.min.js">
+
+
+
+
+ + +
+
+ +
+
+
+
diff --git a/public/svg-edit/editor/svg-editor.js b/public/svg-edit/editor/svg-editor.js index 884dd97a..c13eb49e 100644 --- a/public/svg-edit/editor/svg-editor.js +++ b/public/svg-edit/editor/svg-editor.js @@ -165,6 +165,7 @@ function svg_edit_setup() { var selectedElement = null; var multiselected = false; var editingsource = false; + var editingforeign = false; var docprops = false; var fillPaint = new $.jGraduate.Paint({solidColor: "FF0000"}); // solid red @@ -705,7 +706,7 @@ function svg_edit_setup() { var is_node = currentMode == 'pathedit'; //elem ? (elem.id && elem.id.indexOf('pathpointgrip') == 0) : false; $('#selected_panel, #multiselected_panel, #g_panel, #rect_panel, #circle_panel,\ - #ellipse_panel, #line_panel, #text_panel, #image_panel').hide(); + #ellipse_panel, #line_panel, #text_panel, #image_panel, #foreignObject_panel').hide(); if (elem != null) { var elname = elem.nodeName; var angle = svgCanvas.getRotationAngle(elem); @@ -771,6 +772,7 @@ function svg_edit_setup() { circle: ['cx','cy','r'], ellipse: ['cx','cy','rx','ry'], line: ['x1','y1','x2','y2'], + foreignObject: [], text: [] }; @@ -807,6 +809,12 @@ function svg_edit_setup() { $('#text').focus().select(); } } // text + else if (el_name == 'foreignObject') { + $('#foreignObject_panel').css("display", "inline"); + $('#foreign_font_size').val(elem.getAttribute("font-size")); + $('#foreign_width').val(elem.getAttribute("width")); + $('#foreign_height').val(elem.getAttribute("height")); + } //foreignObject else if(el_name == 'image') { var xlinkNS="http://www.w3.org/1999/xlink"; var href = elem.getAttributeNS(xlinkNS, "href"); @@ -1294,7 +1302,12 @@ function svg_edit_setup() { toolButtonClick('#tool_text'); svgCanvas.setMode('text'); }; - + + var clickForeign = function(){ + toolButtonClick('#tool_foreign'); + svgCanvas.setMode('foreign'); + }; + var clickPath = function(){ toolButtonClick('#tool_path'); svgCanvas.setMode('path'); @@ -1499,10 +1512,21 @@ function svg_edit_setup() { var str = svgCanvas.getSvgString(); $('#svg_source_textarea').val(str); $('#svg_source_editor').fadeIn(); - properlySourceSizeTextArea(); + properlySourceSizeTextArea('source'); $('#svg_source_textarea').focus(); }; + var showForeignEditor = function(elt){ + if (!elt || editingforeign) return; + editingforeign = true; + elt.removeAttribute('fill'); + var str = svgCanvas.getForeignString(elt); + $('#svg_foreign_textarea').val(str); + $('#svg_foreign_editor').fadeIn(); + properlySourceSizeTextArea('foreign'); + $('#svg_foreign_textarea').focus(); + }; + $('#svg_docprops_container').draggable({cancel:'button,fieldset'}); var showDocProperties = function(){ @@ -1538,18 +1562,40 @@ function svg_edit_setup() { $('#svg_docprops').fadeIn(); }; - var properlySourceSizeTextArea = function(){ + var properlySourceSizeTextArea = function(str){ // TODO: remove magic numbers here and get values from CSS - var height = $('#svg_source_container').height() - 80; - $('#svg_source_textarea').css('height', height); + var height = $('#svg_'+str+'_container').height() - 80; + $('#svg_'+str+'_textarea').css('height', height); }; - + + var saveForeignEditor = function(elt){ + if (!editingforeign) return; + + var saveChanges = function() { + svgCanvas.clearSelection(); + hideSourceEditor('foreign'); + zoomImage(); + populateLayers(); + setTitle(svgCanvas.getImageTitle()); + } + + if (!svgCanvas.setForeignString($('#svg_foreign_textarea').val(), elt)) { + $.confirm(uiStrings.QerrorsRevertToSource, function(ok) { + if(!ok) return false; + saveChanges(); + }); + } else { + saveChanges(); + } + setSelectMode(); + } + var saveSourceEditor = function(){ if (!editingsource) return; var saveChanges = function() { svgCanvas.clearSelection(); - hideSourceEditor(); + hideSourceEditor('source'); zoomImage(); populateLayers(); setTitle(svgCanvas.getImageTitle()); @@ -1776,18 +1822,28 @@ function svg_edit_setup() { setFlyoutPositions(); } - var cancelOverlays = function() { + var cancelOverlays = function(elt) { $('#dialog_box').hide(); - if (!editingsource && !docprops) return; + if (!editingsource && !editingforeign && !docprops) return; if (editingsource) { var oldString = svgCanvas.getSvgString(); if (oldString != $('#svg_source_textarea').val()) { $.confirm(uiStrings.QignoreSourceChanges, function(ok) { - if(ok) hideSourceEditor(); + if(ok) hideSourceEditor('source'); }); } else { - hideSourceEditor(); + hideSourceEditor('source'); + } + } + else if (editingforeign) { + var oldString = svgCanvas.getForeignString(elt); + if (oldString != $('#svg_foreign_textarea').val()) { + $.confirm(uiStrings.QignoreSourceChanges, function(ok) { + if(ok) hideSourceEditor('foreign'); + }); + } else { + hideSourceEditor('foreign'); } } else if (docprops) { @@ -1796,10 +1852,11 @@ function svg_edit_setup() { }; - var hideSourceEditor = function(){ - $('#svg_source_editor').hide(); + var hideSourceEditor = function(str){ + $('#svg_'+str+'_editor').hide(); editingsource = false; - $('#svg_source_textarea').blur(); + editingforeign = false; + $('#svg_'+str+'_textarea').blur(); }; var hideDocProperties = function(){ @@ -1812,8 +1869,11 @@ function svg_edit_setup() { // TODO: add canvas-centering code in here $(window).resize(function(evt) { - if (!editingsource) return; - properlySourceSizeTextArea(); + if (editingsource) { + properlySourceSizeTextArea('source'); + } else if(editingforeign) { + properlySourceSizeTextArea('foreign'); + } }); $('#url_notice').click(function() { @@ -1949,7 +2009,7 @@ function svg_edit_setup() { var bNoFill = (svgCanvas.getFillColor() == 'none'); var bNoStroke = (svgCanvas.getStrokeColor() == 'none'); var buttonsNeedingStroke = [ '#tool_fhpath', '#tool_line' ]; - var buttonsNeedingFillAndStroke = [ '#tools_rect .tool_button', '#tools_ellipse .tool_button', '#tool_text', '#tool_path']; + var buttonsNeedingFillAndStroke = [ '#tools_rect .tool_button', '#tools_ellipse .tool_button', '#tool_text', '#tool_foreign', '#tool_path', '#tool_edit_foreign']; if (bNoStroke) { for (index in buttonsNeedingStroke) { var button = buttonsNeedingStroke[index]; @@ -2412,13 +2472,19 @@ function svg_edit_setup() { {sel:'#tool_text', fn: clickText, evt: 'click', key: 7}, {sel:'#tool_image', fn: clickImage, evt: 'mouseup', key: 8}, {sel:'#tool_zoom', fn: clickZoom, evt: 'mouseup', key: 9}, + {sel:'#tool_foreign', fn: clickForeign, evt: 'mouseup'}, + {sel:'#tool_edit_foreign', fn: function(){showForeignEditor(selectedElement)}, evt: 'mouseup'}, {sel:'#tool_clear', fn: clickClear, evt: 'mouseup', key: [modKey+'N', true]}, - {sel:'#tool_save', fn: function() { editingsource?saveSourceEditor():clickSave()}, evt: 'mouseup', key: [modKey+'S', true]}, + {sel:'#tool_save', fn: function() { if(editingsource){saveSourceEditor()} + else if(editingforeign){saveForeignEditor(selectedElement)} + else clickSave()}, evt: 'mouseup', key: [modKey+'S', true]}, {sel:'#tool_open', fn: clickOpen, evt: 'mouseup', key: [modKey+'O', true]}, {sel:'#tool_source', fn: showSourceEditor, evt: 'click', key: ['U', true]}, {sel:'#tool_wireframe', fn: clickWireframe, evt: 'click', key: ['F', true]}, {sel:'#tool_source_cancel,#svg_source_overlay,#tool_docprops_cancel', fn: cancelOverlays, evt: 'click', key: ['esc', false, false], hidekey: true}, + {sel:'#tool_foreign_cancel,#svg_source_overlay,#tool_docprops_cancel', fn: function(){cancelOverlays(selectedElement)}, evt: 'click', key: ['esc', false, false], hidekey: true}, {sel:'#tool_source_save', fn: saveSourceEditor, evt: 'click'}, + {sel:'#tool_foreign_save', fn: function(){saveForeignEditor(selectedElement)}, evt: 'click'}, {sel:'#tool_docprops_save', fn: saveDocProperties, evt: 'click'}, {sel:'#tool_docprops', fn: showDocProperties, evt: 'mouseup', key: [modKey+'I', true]}, {sel:'#tool_delete,#tool_delete_multi', fn: deleteSelected, evt: 'click', key: ['del/backspace', true]}, @@ -2718,7 +2784,7 @@ function svg_edit_setup() { updateCanvas(true); }); -// var revnums = "svg-editor.js ($Rev: 1372 $) "; +// var revnums = "svg-editor.js ($Rev: 1377 $) "; // revnums += svgCanvas.getVersion(); // $('#copyright')[0].setAttribute("title", revnums); return svgCanvas; @@ -2756,6 +2822,8 @@ function svg_edit_setup() { 'text':'text.png', 'image':'image.png', 'zoom':'zoom.png', + 'foreign':'foreign.png', + 'edit_foreign':'edit_foreign.png', 'clone':'clone.png', 'delete':'delete.png', @@ -2809,6 +2877,8 @@ function svg_edit_setup() { '#tool_text,#layer_rename':'text', '#tool_image':'image', '#tool_zoom':'zoom', + '#tool_foreign':'foreign', + '#tool_edit_foreign':'edit_foreign', '#tool_clone,#tool_clone_multi,#tool_node_clone':'clone', '#layer_delete,#tool_delete,#tool_delete_multi,#tool_node_delete':'delete', @@ -2833,8 +2903,8 @@ function svg_edit_setup() { '#layer_down':'go_down', '#layerlist td.layervis':'eye', - '#tool_source_save,#tool_docprops_save':'ok', - '#tool_source_cancel,#tool_docprops_cancel':'cancel', + '#tool_source_save,#tool_foreign_save,#tool_docprops_save':'ok', + '#tool_source_cancel,#tool_foreign_cancel,#tool_docprops_cancel':'cancel', '.flyout_arrow_horiz':'arrow_right', '.dropdown button, #main_button .dropdown':'arrow_down', @@ -2907,7 +2977,11 @@ function svg_edit_setup() { // This happens when the page is loaded $(function() { svgCanvas = svg_edit_setup(); - put_locale(svgCanvas); + var good_langs = []; + $('#lang_select option').each(function() { + good_langs.push(this.value); + }); + put_locale(svgCanvas, null, good_langs); try{ json_encode = function(obj){ diff --git a/public/svg-edit/editor/svgcanvas.js b/public/svg-edit/editor/svgcanvas.js index 6bda8ff9..026140db 100644 --- a/public/svg-edit/editor/svgcanvas.js +++ b/public/svg-edit/editor/svgcanvas.js @@ -1,4 +1,4 @@ -/* +/* * svgcanvas.js * * Licensed under the Apache License, Version 2 @@ -99,7 +99,7 @@ var isOpera = !!window.opera, "ellipse": ["class", "clip-path", "clip-rule", "cx", "cy", "fill", "fill-opacity", "fill-rule", "filter", "id", "mask", "opacity", "requiredFeatures", "rx", "ry", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"], "feGaussianBlur": ["class", "id", "requiredFeatures", "stdDeviation"], "filter": ["class", "filterRes", "filterUnits", "height", "id", "primitiveUnits", "requiredFeatures", "width", "x", "xlink:href", "y"], - "foreignObject": ["class", "font-size", "height", "id", "markdown", "opacity", "overflow", "requiredFeatures", "style", "width", "x", "y"], + "foreignObject": ["class", "color", "font-size", "height", "id", "markdown", "opacity", "overflow", "requiredFeatures", "style", "transform", "width", "x", "y"], "g": ["class", "clip-path", "clip-rule", "id", "display", "fill", "fill-opacity", "fill-rule", "filter", "mask", "opacity", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"], "image": ["class", "clip-path", "clip-rule", "filter", "height", "id", "mask", "opacity", "requiredFeatures", "style", "systemLanguage", "transform", "width", "x", "xlink:href", "xlink:title", "y"], "line": ["class", "clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "id", "marker-end", "marker-mid", "marker-start", "mask", "opacity", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform", "x1", "x2", "y1", "y2"], @@ -913,6 +913,7 @@ function BatchCommand(text) { // TODO: declare the variables and set them as null, then move this setup stuff to // an initialization function - probably just use clear() + var canvas = this, svgns = "http://www.w3.org/2000/svg", xlinkns = "http://www.w3.org/1999/xlink", @@ -922,7 +923,7 @@ function BatchCommand(text) { mathns = "http://www.w3.org/1998/Math/MathML", idprefix = "svg_", svgdoc = container.ownerDocument, - svgroot = svgdoc.importNode(Utils.text2xml('' + '' + '' + @@ -938,6 +939,10 @@ function BatchCommand(text) { $(svgroot).appendTo(container); + var nsMap = {}; + nsMap[xlinkns] = 'xlink'; + nsMap[se_ns] = 'se'; + var svgcontent = svgdoc.createElementNS(svgns, "svg"); $(svgcontent).attr({ id: 'svgcontent', @@ -1476,6 +1481,7 @@ function BatchCommand(text) { var svgToString = function(elem, indent) { var out = new Array(); + if (elem) { cleanupElement(elem); var attrs = elem.attributes, @@ -1486,15 +1492,24 @@ function BatchCommand(text) { for (var i=0; i=0; i--) { attr = attrs.item(i); @@ -1520,19 +1535,10 @@ function BatchCommand(text) { } // map various namespaces to our fixed namespace prefixes - // TODO: put this into a map and do a look-up instead of if-else - if (attr.namespaceURI == xlinkns) { - out.push('xlink:'); - } - else if(attr.namespaceURI == 'http://www.w3.org/2000/xmlns/' && attr.localName != 'xmlns') { - out.push('xmlns:'); - } - else if(attr.namespaceURI == xmlns) { - out.push('xml:'); - } - else if(attr.namespaceURI == se_ns) { - out.push('se:'); + if(attr.namespaceURI && nsMap[attr.namespaceURI]) { + out.push(nsMap[attr.namespaceURI]+':'); } + out.push(attr.localName); out.push("=\""); out.push(attrVal); out.push("\""); } @@ -1766,8 +1772,8 @@ function BatchCommand(text) { // if absolute or first segment, we want to remap x, y, x1, y1, x2, y2 // if relative, we want to scalew, scaleh if (type % 2 == 0) { // absolute - var thisx = seg.x ? seg.x : currentpt.x, // for V commands - thisy = seg.y ? seg.y : currentpt.y, // for H commands + var thisx = (seg.x != undefined) ? seg.x : currentpt.x, // for V commands + thisy = (seg.y != undefined) ? seg.y : currentpt.y, // for H commands pt = remap(thisx,thisy), pt1 = remap(seg.x1,seg.y1), pt2 = remap(seg.x2,seg.y2); @@ -1914,7 +1920,7 @@ function BatchCommand(text) { } // if this element had no transforms, we are done - if (tlist.numberOfItems == 0) { + if (!tlist || tlist.numberOfItems == 0) { selected.removeAttribute("transform"); return null; } @@ -2012,8 +2018,7 @@ function BatchCommand(text) { break; } } - } - + } var tx = 0, ty = 0, operation = 0, N = tlist.numberOfItems; @@ -2229,15 +2234,20 @@ function BatchCommand(text) { // temporarily strip off the rotate and save the old center angle = canvas.getRotationAngle(selected); if (angle) { + var a = angle * Math.PI / 180; + if ( Math.abs(a) > (1.0e-10) ) { + var s = Math.sin(a)/(1 - Math.cos(a)); + } else { + // FIXME: This blows up if the angle is exactly 0! + var s = 2/a; + } for (var i = 0; i < tlist.numberOfItems; ++i) { var xform = tlist.getItem(i); if (xform.type == 4) { // extract old center through mystical arts var rm = xform.matrix; - var a = angle * Math.PI / 180; - // FIXME: This blows up if the angle is exactly 0 or 180 degrees! - oldcenter.y = 0.5 * (Math.sin(a)*rm.e + (1-Math.cos(a))*rm.f) / (1 - Math.cos(a)); - oldcenter.x = ((1 - Math.cos(a)) * oldcenter.y - rm.f) / Math.sin(a); + oldcenter.y = (s*rm.e + rm.f)/2; + oldcenter.x = (rm.e - s*rm.f)/2; tlist.removeItem(i); break; } @@ -2734,9 +2744,12 @@ function BatchCommand(text) { if (mouse_target.correspondingUseElement) mouse_target = mouse_target.correspondingUseElement; - // for foreign content, go up until we find the foreignObject - if ($.inArray(mouse_target.namespaceURI, [mathns, htmlns]) != -1) { - while (mouse_target.nodeName != "foreignObject") { + // for foreign content, go up until we find the foreignObject + // WebKit browsers set the mouse target to the svgcanvas div + if ($.inArray(mouse_target.namespaceURI, [mathns, htmlns]) != -1 && + mouse_target.id != "svgcanvas") + { + while (mouse_target.nodeName != "foreignObject") { mouse_target = mouse_target.parentNode; } } @@ -3016,6 +3029,28 @@ function BatchCommand(text) { }); newText.textContent = "text"; break; + case "foreign": + started = true; + var newText = addSvgElementFromJson({ + "element": "foreignObject", + "attr": { + "x": x, + "y": y, + "id": getNextId(), + "font-size": cur_text.font_size, + "width": "24", + "height": "24", + "style": "pointer-events:inherit" + } + }); + var m = svgdoc.createElementNS(mathns, 'math'); + m.setAttribute('xmlns', mathns); + m.setAttributeNS(mathns, 'display', 'inline'); + var mi = svgdoc.createElementNS(mathns, 'mo'); + mi.textContent = "\u03A6"; + m.appendChild(mi); + newText.appendChild(m); + break; case "path": // Fall through case "pathedit": @@ -3234,6 +3269,14 @@ function BatchCommand(text) { 'height': Math.abs(y-start_y*current_zoom) },100); break; + case "foreignObject": + assignAttributes(shape,{ + 'width': 24, + 'height': 24, + 'x': x, + 'y': y + },1000); + break; case "text": assignAttributes(shape,{ 'x': x, @@ -3248,8 +3291,6 @@ function BatchCommand(text) { shape.setAttributeNS(null, "y2", y); if (!window.opera) svgroot.unsuspendRedraw(handle); break; - case "foreignObject": - // fall through case "square": // fall through case "rect": @@ -3457,7 +3498,7 @@ function BatchCommand(text) { var attrs = $(element).attr(["x1", "x2", "y1", "y2"]); keep = (attrs.x1 != attrs.x2 || attrs.y1 != attrs.y2); break; - case "foreignObject": + case "foreign": case "square": case "rect": case "image": @@ -3573,7 +3614,7 @@ function BatchCommand(text) { element = null; var t = evt.target; - + // 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 elements @@ -3599,7 +3640,7 @@ function BatchCommand(text) { cleanupElement(element); if(current_mode == "path") { pathActions.toEditMode(element); - } else if (current_mode == "text" || current_mode == "image") { + } else if (current_mode == "text" || current_mode == "image" || current_mode == "foreign") { // keep us in the tool we were in unless it was a text or image element canvas.addToSelection([element], true); } @@ -5495,6 +5536,19 @@ function BatchCommand(text) { return svgCanvasToString(); }; + // Function: getForeignString(elt) + // Returns the contents of element elt as XML text. + // + // Parameters: + // elt - The foreignObject Element. + // + // Returns: + // The contents of elt as raw XML text. + this.getForeignString = function(elt) { + var s = svgToString(elt, 0); + return s; + }; + // Function: setSvgString // This function sets the current drawing as the input SVG XML. // @@ -5542,6 +5596,20 @@ function BatchCommand(text) { canvas.fixOperaXML(svgcontent, newDoc.documentElement); } + // recalculate dimensions on the top-level children so that unnecessary transforms + // are removed + var deepdive = function(node) { + if (node.nodeType == 1) { + var children = node.children; + var i = children.length; + while (i--) { deepdive(children.item(i)); } + try { + recalculateDimensions(node); + } catch(e) { console.log(e); } + } + } + deepdive(svgcontent); + var content = $(svgcontent); // determine proper size @@ -5592,6 +5660,32 @@ function BatchCommand(text) { return true; }; + // Function: setForeignString(xmlString, elt) + // This function sets the content of element elt to the input XML. + // + // Parameters: + // xmlString - The XML text. + // elt - the parent element to append to + // + // Returns: + // This function returns false if the set was unsuccessful, true otherwise. + this.setForeignString = function(xmlString, elt) { + try { + // convert string into XML document + var newDoc = Utils.text2xml(''+xmlString+''); + // run it through our sanitizer to remove anything we do not support + sanitizeSvg(newDoc.documentElement); + + elt.parentNode.replaceChild(newDoc.documentElement.firstChild, elt); + call("changed", [elt]); + } catch(e) { + console.log(e); + return false; + } + + return true; + }; + // Layer API Functions // Group: Layers @@ -7649,7 +7743,7 @@ function BatchCommand(text) { // Function: getVersion // Returns a string which describes the revision number of SvgCanvas. this.getVersion = function() { - return "svgcanvas.js ($Rev: 1375 $)"; + return "svgcanvas.js ($Rev: 1380 $)"; }; this.setUiStrings = function(strs) {