From bad5beec2992f5d48a7afd0b05ad5fe0b8721081 Mon Sep 17 00:00:00 2001 From: Jacques Distler Date: Fri, 5 Feb 2010 23:17:34 -0600 Subject: [PATCH] Sync with SVG-edit --- public/svg-edit/editor/locale/lang.hi.js | 2 +- public/svg-edit/editor/locale/lang.zh-TW.js | 10 +- public/svg-edit/editor/svg-editor.js | 78 ++++++++- public/svg-edit/editor/svgcanvas.js | 166 +++++++++++++++++--- public/svg-edit/extensions/ext-arrows.js | 48 +++--- public/svg-edit/extensions/ext-connector.js | 51 +++++- public/svg-edit/extras/tojson.py | 52 ++++++ public/svg-edit/extras/topo.py | 39 +++++ 8 files changed, 386 insertions(+), 60 deletions(-) create mode 100644 public/svg-edit/extras/tojson.py create mode 100644 public/svg-edit/extras/topo.py diff --git a/public/svg-edit/editor/locale/lang.hi.js b/public/svg-edit/editor/locale/lang.hi.js index 44709568..d6dde786 100644 --- a/public/svg-edit/editor/locale/lang.hi.js +++ b/public/svg-edit/editor/locale/lang.hi.js @@ -127,7 +127,7 @@ {"id": "tool_zoom", "title": "ज़ूम उपकरण"}, {"id": "zoom", "title": "बदलें स्तर ज़ूम"}, {"id": "zoomLabel", "textContent": "जूम:"}, -{"id": "sidepanel_handle", "textContent": "परतें", "title": "दायें/बाएं घसीट कर आकार बदलें"}, +{"id": "sidepanel_handle","textContent":"प र तें","title":"दायें/बाएं घसीट कर आकार बदलें"}, { "js_strings": { "QerrorsRevertToSource": "आपके एस.वी.जी. स्रोत में त्रुटियों थी.\nक्या आप मूल एस.वी.जी स्रोत पर वापिस जाना चाहते हैं?", diff --git a/public/svg-edit/editor/locale/lang.zh-TW.js b/public/svg-edit/editor/locale/lang.zh-TW.js index a0c1a81e..209d1d4f 100644 --- a/public/svg-edit/editor/locale/lang.zh-TW.js +++ b/public/svg-edit/editor/locale/lang.zh-TW.js @@ -87,12 +87,12 @@ {"id":"tool_aligntop","title":"頂端對齊"}, {"id":"tool_bold","title":"粗體"}, {"id":"tool_circle","title":"圓"}, -{"id":"tool_clear","title":"清空圖像"}, +{"id":"tool_clear","textContent":"清空圖像"}, {"id":"tool_clone","title":"複製"}, {"id":"tool_clone_multi","title":"複製所選元素"}, {"id":"tool_delete","title":"刪除"}, {"id":"tool_delete_multi","title":"刪除所選元素"}, -{"id":"tool_docprops","title":"文件屬性"}, +{"id":"tool_docprops","textContent":"文件屬性"}, {"id":"tool_docprops_cancel","textContent":"取消"}, {"id":"tool_docprops_save","textContent":"保存"}, {"id":"tool_ellipse","title":"橢圓"}, @@ -108,12 +108,12 @@ {"id":"tool_node_clone","title":"增加節點"}, {"id":"tool_node_delete","title":"刪除節點"}, {"id":"tool_node_link","title":"將控制點連起來"}, -{"id":"tool_open","title":"打開圖像"}, +{"id":"tool_open","textContent":"打開圖像"}, {"id":"tool_path","title":"路徑工具"}, {"id":"tool_rect","title":"矩形"}, {"id":"tool_redo","title":"復原"}, {"id":"tool_reorient","title":"調整路徑"}, -{"id":"tool_save","title":"保存圖像"}, +{"id":"tool_save","textContent":"保存圖像"}, {"id":"tool_select","title":"選擇工具"}, {"id":"tool_source","title":"編輯SVG原始碼"}, {"id":"tool_source_cancel","textContent":"取消"}, @@ -125,8 +125,6 @@ {"id":"tool_ungroup","title":"取消群組"}, {"id":"tool_wireframe","title":"框線模式(只瀏覽線條)"}, {"id":"tool_zoom","title":"縮放工具"}, -{"id":"tools_ellipse_show","title":"橢圓/圓工具"}, -{"id":"tools_rect_show","title":"矩形/方形工具"}, {"id":"zoom","title":"更改縮放級別"}, {"id":"zoomLabel","textContent":"調整頁面大小:"}, {"id":"sidepanel_handle","textContent":"圖層","title":"拖拉以改變側邊面板的大小"}, diff --git a/public/svg-edit/editor/svg-editor.js b/public/svg-edit/editor/svg-editor.js index bb026e14..28aec112 100644 --- a/public/svg-edit/editor/svg-editor.js +++ b/public/svg-edit/editor/svg-editor.js @@ -179,7 +179,6 @@ function svg_edit_setup() { // https://bugzilla.mozilla.org/show_bug.cgi?id=308590 var saveHandler = function(window,svg) { window.opener.postMessage(svg, window.location.protocol + '//' + window.location.host); -// window.open("data:image/svg+xml;base64," + Utils.encode64(svg)); }; // called when we've selected a different element @@ -383,12 +382,23 @@ function svg_edit_setup() { } var extAdded = function(window, ext) { - if("buttons" in ext) { + + var cb_called = false; + + var runCallback = function() { + if(ext.callback && !cb_called) { + cb_called = true; + ext.callback(); + } + } + + if(ext.buttons) { var fallback_obj = {}, placement_obj = {}, svgicons = ext.svgicons; var holders = {}; + // Add buttons given by extension $.each(ext.buttons, function(i, btn) { @@ -515,10 +525,70 @@ function svg_edit_setup() { setIconSize('m'); setIconSize(old); } + runCallback(); } }); } + if(ext.context_tools) { + $.each(ext.context_tools, function(i, tool) { + // Add select tool + var cont_id = tool.container_id?(' id="' + tool.container_id + '"'):""; + + var panel = $('#' + tool.panel); + + if(!panel.length) { + panel = $('
', {id: tool.panel}).appendTo("#tools_top"); + } + + // TODO: Allow support for other types, or adding to existing tool + switch (tool.type) { + case 'select': + var html = '' + + '"; + // Creates the tool, hides & adds it, returns the select element + var sel = $(html).appendTo(panel).find('select'); + + $.each(tool.events, function(evt, func) { + $(sel).bind(evt, func); + }); + break; + + case 'input': + var html = '' + + '' + + tool.label + ':' + + '' + + // Creates the tool, hides & adds it, returns the select element + + // Add to given tool.panel + var inp = $(html).appendTo(panel).find('input'); + + if(tool.spindata) { + inp.SpinButton(tool.spindata); + } + + if(tool.events) { + $.each(tool.events, function(evt, func) { + $(sel).bind(evt, func); + }); + } + break; + + default: + break; + } + }); + } + + runCallback(); }; var getPaint = function(color, opac) { @@ -1865,7 +1935,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' ]; + var buttonsNeedingFillAndStroke = [ '#tools_rect .tool_button', '#tools_ellipse .tool_button', '#tool_text', '#tool_path']; if (bNoStroke) { for (index in buttonsNeedingStroke) { var button = buttonsNeedingStroke[index]; @@ -2634,7 +2704,7 @@ function svg_edit_setup() { updateCanvas(true); }); -// var revnums = "svg-editor.js ($Rev: 1342 $) "; +// var revnums = "svg-editor.js ($Rev: 1347 $) "; // revnums += svgCanvas.getVersion(); // $('#copyright')[0].setAttribute("title", revnums); return svgCanvas; diff --git a/public/svg-edit/editor/svgcanvas.js b/public/svg-edit/editor/svgcanvas.js index cc3bc0a9..4d74659a 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 @@ -984,27 +984,6 @@ function BatchCommand(text) { return result; } - this.addExtension = function(name, ext_func) { - if(!(name in extensions)) { - // Provide constants here (or should these be accessed through getSomething()? - var ext = ext_func({ - content: svgcontent, - root: svgroot, - call: call, - getNextId: getNextId, - getElem: getElem, - addSvgElementFromJson: addSvgElementFromJson, - selectorManager: selectorManager, - findDefs: findDefs, - recalculateDimensions: recalculateDimensions - }); - extensions[name] = ext; - call("extension_added", ext); - } else { - 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 = function(val){ return parseInt(val*current_zoom)/current_zoom; @@ -2322,6 +2301,51 @@ function BatchCommand(text) { return (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && m.e == 0 && m.f == 0); } + // expects three points to be sent, each point must have an x,y field + // returns an array of two points that are the smoothed + this.smoothControlPoints = function(ct1, ct2, pt) { + // each point must not be the origin + var x1 = ct1.x - pt.x, + y1 = ct1.y - pt.y, + x2 = ct2.x - pt.x, + y2 = ct2.y - pt.y; + + if ( (x1 != 0 || y1 != 0) && (x2 != 0 || y2 != 0) ) { + var anglea = Math.atan2(y1,x1), + angleb = Math.atan2(y2,x2), + r1 = Math.sqrt(x1*x1+y1*y1), + r2 = Math.sqrt(x2*x2+y2*y2), + nct1 = svgroot.createSVGPoint(), + nct2 = svgroot.createSVGPoint(); + if (anglea < 0) { anglea += 2*Math.PI; } + if (angleb < 0) { angleb += 2*Math.PI; } + + var angleBetween = Math.abs(anglea - angleb), + angleDiff = Math.abs(Math.PI - angleBetween)/2; + + var new_anglea, new_angleb; + if (anglea - angleb > 0) { + new_anglea = angleBetween < Math.PI ? (anglea + angleDiff) : (anglea - angleDiff); + new_angleb = angleBetween < Math.PI ? (angleb - angleDiff) : (angleb + angleDiff); + } + else { + new_anglea = angleBetween < Math.PI ? (anglea - angleDiff) : (anglea + angleDiff); + new_angleb = angleBetween < Math.PI ? (angleb + angleDiff) : (angleb - angleDiff); + } + + // rotate the points + nct1.x = r1 * Math.cos(new_anglea) + pt.x; + nct1.y = r1 * Math.sin(new_anglea) + pt.y; + nct2.x = r2 * Math.cos(new_angleb) + pt.x; + nct2.y = r2 * Math.sin(new_angleb) + pt.y; + + return [nct1, nct2]; + } + return undefined; + }; + var smoothControlPoints = this.smoothControlPoints; + + // matrixMultiply() is provided because WebKit didn't implement multiply() correctly // on the SVGMatrix interface. See https://bugs.webkit.org/show_bug.cgi?id=16062 // This function tries to return a SVGMatrix that is the multiplication m1*m2. @@ -3521,6 +3545,18 @@ function BatchCommand(text) { 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 + // 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 + // - http://www.ian-ko.com/ET_GeoWizards/UserGuide/smooth.htm + // - http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/bezier-der.html var curpos = points.getItem(0), prevCtlPt = null; var d = []; d.push(["M",curpos.x,",",curpos.y," C"].join("")); @@ -3532,7 +3568,14 @@ function BatchCommand(text) { // if the previous segment had a control point, we want to smooth out // the control points on both sides if (prevCtlPt) { - // TODO: fancy processing here :) + var newpts = smoothControlPoints( prevCtlPt, ct1, curpos ); + if (newpts && newpts.length == 2) { + var prevArr = d[d.length-1].split(','); + prevArr[2] = newpts[0].x; + prevArr[3] = newpts[0].y; + d[d.length-1] = prevArr.join(','); + ct1 = newpts[1]; + } } d.push([ct1.x,ct1.y,ct2.x,ct2.y,end.x,end.y].join(',')); @@ -6549,6 +6592,9 @@ function BatchCommand(text) { // selector if the element is in that array if ($.inArray(elem, selectedElements) != -1) { setTimeout(function() { + // Due to element replacement, this element may no longer + // be part of the DOM + if(!elem.parentNode) return; selectorManager.requestSelector(elem).resize(); },0); } @@ -7391,7 +7437,7 @@ function BatchCommand(text) { // Function: getVersion // Returns a string which describes the revision number of SvgCanvas. this.getVersion = function() { - return "svgcanvas.js ($Rev: 1341 $)"; + return "svgcanvas.js ($Rev: 1349 $)"; }; this.setUiStrings = function(strs) { @@ -7426,6 +7472,78 @@ function BatchCommand(text) { // return svgdoc.getElementById(id); } + // Being able to access private methods publicly seems wrong somehow, + // but currently appears to be the best way to allow testing and provide + // access to them to plugins. + this.getPrivateMethods = function() { + return { + addCommandToHistory: addCommandToHistory, + addGradient: addGradient, + addSvgElementFromJson: addSvgElementFromJson, + assignAttributes: assignAttributes, + BatchCommand: BatchCommand, + call: call, + ChangeElementCommand: ChangeElementCommand, + cleanupElement: cleanupElement, + copyElem: copyElem, + ffClone: ffClone, + findDefs: findDefs, + findDuplicateGradient: findDuplicateGradient, + fromXml: fromXml, + getElem: getElem, + getId: getId, + getIntersectionList: getIntersectionList, + getNextId: getNextId, + getPathBBox: getPathBBox, + getUrlFromAttr: getUrlFromAttr, + hasMatrixTransform: hasMatrixTransform, + identifyLayers: identifyLayers, + InsertElementCommand: InsertElementCommand, + isIdentity: isIdentity, + logMatrix: logMatrix, + matrixMultiply: matrixMultiply, + MoveElementCommand: MoveElementCommand, + preventClickDefault: preventClickDefault, + recalculateAllSelectedDimensions: recalculateAllSelectedDimensions, + recalculateDimensions: recalculateDimensions, + remapElement: remapElement, + RemoveElementCommand: RemoveElementCommand, + removeUnusedGrads: removeUnusedGrads, + resetUndoStack: resetUndoStack, + round: round, + runExtensions: runExtensions, + sanitizeSvg: sanitizeSvg, + Selector: Selector, + SelectorManager: SelectorManager, + shortFloat: shortFloat, + svgCanvasToString: svgCanvasToString, + SVGEditTransformList: SVGEditTransformList, + svgToString: svgToString, + toString: toString, + toXml: toXml, + transformBox: transformBox, + transformListToTransform: transformListToTransform, + transformPoint: transformPoint, + transformToObj: transformToObj, + walkTree: walkTree + } + } + + this.addExtension = function(name, ext_func) { + if(!(name in extensions)) { + // Provide private vars/funcs here. Is there a better way to do this? + var ext = ext_func($.extend(canvas.getPrivateMethods(), { + svgroot: svgroot, + svgcontent: svgcontent, + selectorManager: selectorManager + })); + extensions[name] = ext; + call("extension_added", ext); + } else { + console.log('Cannot add extension "' + name + '", an extension by that name already exists"'); + } + }; + // Test support for features/bugs (function() { // segList functions (for FF1.5 and 2.0) diff --git a/public/svg-edit/extensions/ext-arrows.js b/public/svg-edit/extensions/ext-arrows.js index 4b935074..8d3c6f48 100644 --- a/public/svg-edit/extensions/ext-arrows.js +++ b/public/svg-edit/extensions/ext-arrows.js @@ -9,8 +9,7 @@ $(function() { svgCanvas.addExtension("Arrows", function(S) { - var svgcontent = S.content, - getElem = S.getElem, + var svgcontent = S.svgcontent, addElem = S.addSvgElementFromJson, selElems; @@ -64,7 +63,7 @@ $(function() { function addMarker(id, type) { // TODO: Make marker (or use?) per arrow type, since refX can be different - var marker = getElem(id); + var marker = S.getElem(id); var pathdata = { se_arrow_fw: {d:"m0,0l10,5l-10,5l5,-5l-5,-5z", refx:8}, @@ -104,7 +103,8 @@ $(function() { marker.setAttribute('refX', data.refx); } - function setArrow(type) { + function setArrow() { + var type = this.value; resetMarker(); if(type == "none") { @@ -114,7 +114,6 @@ $(function() { var fw_id = "se_arrow_fw"; var bk_id = "se_arrow_bk"; - // Set marker on element var id = fw_id; if(type == "mid_bk") { @@ -134,24 +133,29 @@ $(function() { S.call("changed", selElems); } - // Init code - (function() { - var conn_tools = $('
\ -
"').hide().appendTo("#tools_top"); - $('#arrow_list').change(function() { - setArrow(this.value); - }); - }()); - return { name: "Arrows", + context_tools: [{ + type: "select", + panel: "arrow_panel", + title: "Select arrow type", + id: "arrow_list", + options: { + none: "No arrow", + end: "---->", + start: "<----", + both: "<--->", + mid: "-->--", + mid_bk: "--<--" + }, + defval: "none", + events: { + change: setArrow + } + }], + callback: function() { + $('#arrow_panel').hide(); + }, addLangData: function(lang) { return { data: lang_list[lang] @@ -180,4 +184,4 @@ $(function() { } }; }); -}); \ No newline at end of file +}); diff --git a/public/svg-edit/extensions/ext-connector.js b/public/svg-edit/extensions/ext-connector.js index 3f4de067..a0e050e7 100644 --- a/public/svg-edit/extensions/ext-connector.js +++ b/public/svg-edit/extensions/ext-connector.js @@ -9,8 +9,8 @@ $(function() { svgCanvas.addExtension("Connector", function(S) { - var svgcontent = S.content, - svgroot = S.root, + var svgcontent = S.svgcontent, + svgroot = S.svgroot, getNextId = S.getNextId, getElem = S.getElem, addElem = S.addSvgElementFromJson, @@ -104,14 +104,29 @@ $(function() { svgCanvas.removeFromSelection($(conn_sel).toArray()); } + // Loop through selected elements while(i--) { var elem = all_els[i]; if(!elem) continue; + + // Element was deleted, so delete connector + var was_deleted = !elem.parentNode; + + // Skip connector if($(elem).data('c_start')) continue; + + // Loop through connectors to see if one is connected to the element connectors.each(function() { var start = $(this).data("c_start"); var end = $(this).data("c_end"); + + // Connector found for this element if(start == elem.id || end == elem.id) { + + if(was_deleted) { + $(this).remove(); + return; + } var bb = svgCanvas.getStrokedBBox([elem]); connections.push({ elem: elem, @@ -138,8 +153,8 @@ $(function() { var line = conn.connector; var elem = conn.elem; - var pre = conn.is_start?'start':'end'; var sw = line.getAttribute('stroke-width'); + var pre = conn.is_start?'start':'end'; // Update bbox for this element var bb = svgCanvas.getStrokedBBox([elem]); @@ -458,6 +473,7 @@ $(function() { se_ns = svgCanvas.getEditorNS(true); cur_line.setAttributeNS(se_ns, "se:connector", conn_str); cur_line.setAttribute('class', conn_sel.substr(1)); + cur_line.setAttribute('opacity', 1); svgCanvas.addToSelection([cur_line]); svgCanvas.moveToBottomSelectedElement(); selManager.requestSelector(cur_line).showGrips(false); @@ -507,11 +523,40 @@ $(function() { elem.getAttribute("marker-end") )) { var start = elem.getAttribute("marker-start"); + var mid = elem.getAttribute("marker-mid"); var end = elem.getAttribute("marker-end"); cur_line = elem; $(elem) .data("start_off", !!start) .data("end_off", !!end); + + if(elem.tagName == "line" && mid) { + // Convert to polyline to accept mid-arrow + + var x1 = elem.getAttribute('x1')-0; + var x2 = elem.getAttribute('x2')-0; + var y1 = elem.getAttribute('y1')-0; + var y2 = elem.getAttribute('y2')-0; + var id = elem.id; + + var mid_pt = (' '+((x1+x2)/2)+','+((y1+y2)/2) + ' '); + var pline = addElem({ + "element": "polyline", + "attr": { + "points": (x1+','+y1+ mid_pt +x2+','+y2), + "stroke": elem.getAttribute('stroke'), + "stroke-width": elem.getAttribute('stroke-width'), + "marker-mid": mid, + "fill": "none", + "opacity": elem.getAttribute('opacity') || 1 + } + }); + $(elem).after(pline).remove(); + svgCanvas.clearSelection(); + pline.id = id; + svgCanvas.addToSelection([pline]); + } + } updateConnectors(); }, diff --git a/public/svg-edit/extras/tojson.py b/public/svg-edit/extras/tojson.py new file mode 100644 index 00000000..5feea1d1 --- /dev/null +++ b/public/svg-edit/extras/tojson.py @@ -0,0 +1,52 @@ +import sys, json, codecs +infile = codecs.open(sys.argv[1], "r", "utf-8") +outfile = codecs.open(sys.argv[1][:-3], "w", "utf-8") +indata = infile.readlines() +look = False +out = "[\n" +js = [] +jss = "" + +def readfrompos(pos): + global out + global js + + if (indata[pos].startswith("#, -x-svg-edit-title")) or (indata[pos].startswith("#, -x-svg-edit-textContent")): + out += '{' + out += '"id": ' + out += " ".join(indata[pos+1].split()[1:]) + ", " + out += '"' + line[15:].strip() + '": ' + out += " ".join(indata[pos+2].split()[1:]) + out += '}' + elif (indata[pos].startswith("#, -x-svg-edit-both")): + out += '{' + out += '"id": ' + out += " ".join(indata[pos+1].split()[1:]) + ", " + out += '"textContent": ' + out += '"' + " ".join(indata[pos+2].split()[1:]).split('|')[1] + ', ' + out += '"title": ' + out += " ".join(indata[pos+2].split()[1:]).split('|')[0] + '"' + out += '}' + elif (indata[pos].startswith("#, -x-svg-edit-js_strings")): + js.append((" ".join(indata[pos+1].split()[1:]), " ".join(indata[pos+2].split()[1:]))) + +for pos, line in enumerate(indata): + if (not look) and (line.startswith('# ---')): + look = True + marker = pos + elif (look) and (line.startswith('#, -x-svg-edit')): + readfrompos(pos) + +js.sort() + +for j in js: + jss += " %s: %s,\n" % (j[0], j[1]) + +out += '{\n "js_strings": {\n' +out += str(jss) +out += ' "": ""\n }' +out += "\n}" +out += "\n]" +out = out.replace('}{', '},\n{') + +outfile.write(out) \ No newline at end of file diff --git a/public/svg-edit/extras/topo.py b/public/svg-edit/extras/topo.py new file mode 100644 index 00000000..592cbee8 --- /dev/null +++ b/public/svg-edit/extras/topo.py @@ -0,0 +1,39 @@ +import sys, json, codecs +infile = json.load(codecs.open(sys.argv[1], "r", "utf-8")) +outfile = codecs.open(sys.argv[1] + ".po", "w", "utf-8") +out = [] + +out.append("""# LANGUAGE FILE FOR SVG-EDIT, AUTOGENERATED BY TOPO.PY + +msgid "" +msgstr "" +"Content-Type: text/plain; charset=utf-8\\n" +"Content-Transfer-Encoding: 8bit\\n" + +# --- + +""") + +def printstr(flag, i, s): + out.append('\n') + if flag == '-x-svg-edit-both': + out.append("# Enter the title first, then the contents, seperated by a pipe char (|)\n") + out.append("#, " + flag + '\n') + out.append("msgid \"" + i + "\"" + '\n') + out.append("msgstr \"" + s.replace('\n', '\\n') + "\"" + '\n') + +for line in infile: + if line.has_key('title') and line.has_key('textContent'): + printstr('-x-svg-edit-both', line['id'], "|".join(((line['title'], line['textContent'])))) + elif line.has_key('title'): + printstr('-x-svg-edit-title', line['id'], line['title']) + elif line.has_key('textContent'): + printstr('-x-svg-edit-textContent', line['id'], line['textContent']) + elif line.has_key('js_strings'): + for i, s in line['js_strings'].items(): + printstr('-x-svg-edit-js_strings', i, s) + else: + pass # The line wasn't really a string + +outfile.writelines(out) +outfile.close() \ No newline at end of file