diff --git a/public/javascripts/page_helper.js b/public/javascripts/page_helper.js
index e773f99f..d769c4f4 100644
--- a/public/javascripts/page_helper.js
+++ b/public/javascripts/page_helper.js
@@ -87,6 +87,7 @@ function setupSVGedit(path){
} else {
var editor = window.open(path, 'Spoons!');
}
+ editor.focus();
});
}
var t = $('content');
@@ -131,6 +132,9 @@ function setupSVGedit(path){
Event.observe(window, "message", function(event){
if(event.origin !== my_loc) { return;}
t.value = before + event.data + after;
+ t.focus();
+ SVGeditButton.disabled = true;
+ SVGeditButton.value = 'Create SVG graphic';
});
}
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 = '
'
+
+ // 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 cda8bc37..4d74659a 100644
--- a/public/svg-edit/editor/svgcanvas.js
+++ b/public/svg-edit/editor/svgcanvas.js
@@ -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(','));
@@ -5223,9 +5266,8 @@ function BatchCommand(text) {
if(opts) $.extend(save_options, opts);
save_options.apply = true;
- var str = "\n";
// no need for doctype, see http://jwatt.org/svg/authoring/#doctype-declaration
- str += svgCanvasToString();
+ var str = svgCanvasToString();
call("saved", str);
};
@@ -6550,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);
}
@@ -7392,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) {
@@ -7427,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