sketchily 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +39 -0
- data/Rakefile +40 -0
- data/app/helpers/sketchily.rb~ +10 -0
- data/app/helpers/sketchily_helper.rb +10 -0
- data/app/views/sketchily/_embed.html.erb +28 -0
- data/app/views/sketchily/_embed.html.erb~ +28 -0
- data/app/views/sketchily/_embed.js.erb +50 -0
- data/app/views/sketchily/_embed.js.erb~ +50 -0
- data/app/views/sketchily/_sketchily.html.erb +23 -0
- data/app/views/sketchily/_sketchily.html.erb~ +23 -0
- data/app/views/sketchily/_sketchily_tag.html.erb +21 -0
- data/app/views/sketchily/_sketchily_tag.html.erb~ +21 -0
- data/app/views/sketchily/_svg_edit_tag.html.erb~ +51 -0
- data/app/views/sketchily/svg_edit_tag_.html~ +35 -0
- data/lib/sketchily.rb +15 -0
- data/lib/sketchily.rb~ +16 -0
- data/lib/sketchily/engine.rb +4 -0
- data/lib/sketchily/sketchily.rb +28 -0
- data/lib/sketchily/sketchily_show.rb~ +13 -0
- data/lib/sketchily/sketchily_tag.rb +15 -0
- data/lib/sketchily/svg_edit_tag.rb~ +9 -0
- data/lib/sketchily/version.rb +3 -0
- data/lib/sketchily/version.rb~ +3 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +59 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/lib/sketchily_spec.rb +0 -0
- data/spec/spec_helper.rb +11 -0
- data/vendor/assets/svg-edit-2.6/browser-not-supported.html +27 -0
- data/vendor/assets/svg-edit-2.6/browser.js +180 -0
- data/vendor/assets/svg-edit-2.6/canvg/canvg.js +2620 -0
- data/vendor/assets/svg-edit-2.6/canvg/rgbcolor.js +287 -0
- data/vendor/assets/svg-edit-2.6/contextmenu.js +67 -0
- data/vendor/assets/svg-edit-2.6/contextmenu/jquery.contextMenu.js +203 -0
- data/vendor/assets/svg-edit-2.6/draw.js +528 -0
- data/vendor/assets/svg-edit-2.6/embedapi.html +56 -0
- data/vendor/assets/svg-edit-2.6/embedapi.js +173 -0
- data/vendor/assets/svg-edit-2.6/extensions/closepath_icons.svg +41 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-arrows.js +298 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-closepath.js +92 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-connector.js +587 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-eyedropper.js +109 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-foreignobject.js +277 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-grid.js +184 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-helloworld.js +78 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-imagelib.js +453 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-imagelib.xml +14 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-markers.js +572 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-server_moinsave.js +56 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-server_opensave.js +180 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-shapes.js +387 -0
- data/vendor/assets/svg-edit-2.6/extensions/ext-shapes.xml +10 -0
- data/vendor/assets/svg-edit-2.6/extensions/eyedropper-icon.xml +34 -0
- data/vendor/assets/svg-edit-2.6/extensions/eyedropper.png +0 -0
- data/vendor/assets/svg-edit-2.6/extensions/fileopen.php +31 -0
- data/vendor/assets/svg-edit-2.6/extensions/filesave.php +44 -0
- data/vendor/assets/svg-edit-2.6/extensions/foreignobject-icons.xml +96 -0
- data/vendor/assets/svg-edit-2.6/extensions/grid-icon.xml +30 -0
- data/vendor/assets/svg-edit-2.6/extensions/helloworld-icon.xml +21 -0
- data/vendor/assets/svg-edit-2.6/extensions/imagelib/index.html +64 -0
- data/vendor/assets/svg-edit-2.6/extensions/imagelib/smiley.svg +12 -0
- data/vendor/assets/svg-edit-2.6/extensions/markers-icons.xml +115 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/animal.json +21 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/arrow.json +28 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/dialog_balloon.json +9 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/electronics.json +20 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/flowchart.json +25 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/game.json +13 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/math.json +9 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/misc.json +37 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/music.json +21 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/object.json +19 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/raphael.txt +12 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/raphael_1.json +67 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/raphael_2.json +64 -0
- data/vendor/assets/svg-edit-2.6/extensions/shapelib/symbol.json +28 -0
- data/vendor/assets/svg-edit-2.6/history.js +601 -0
- data/vendor/assets/svg-edit-2.6/images/README.txt +61 -0
- data/vendor/assets/svg-edit-2.6/images/align-bottom.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/align-bottom.svg +277 -0
- data/vendor/assets/svg-edit-2.6/images/align-center.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/align-center.svg +252 -0
- data/vendor/assets/svg-edit-2.6/images/align-left.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/align-left.svg +235 -0
- data/vendor/assets/svg-edit-2.6/images/align-middle.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/align-middle.svg +250 -0
- data/vendor/assets/svg-edit-2.6/images/align-right.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/align-right.svg +233 -0
- data/vendor/assets/svg-edit-2.6/images/align-top.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/align-top.svg +233 -0
- data/vendor/assets/svg-edit-2.6/images/bold.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/cancel.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/circle.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/clear.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/clone.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/conn.svg +29 -0
- data/vendor/assets/svg-edit-2.6/images/copy.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/cut.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/delete.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/document-properties.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/dropdown.gif +0 -0
- data/vendor/assets/svg-edit-2.6/images/ellipse.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/eye.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/fhpath.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/flyouth.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/flyup.gif +0 -0
- data/vendor/assets/svg-edit-2.6/images/freehand-circle.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/freehand-square.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/go-down.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/go-up.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/image.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/italic.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/line.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/link_controls.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/logo.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/logo.svg +32 -0
- data/vendor/assets/svg-edit-2.6/images/move_bottom.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/move_top.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/node_clone.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/node_delete.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/none.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/open.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/paste.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/path.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/polygon.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/polygon.svg +219 -0
- data/vendor/assets/svg-edit-2.6/images/rect.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/redo.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/reorient.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/rotate.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/save.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/select.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/select_node.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/sep.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/shape_group.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/shape_ungroup.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/source.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/spinbtn_updn_big.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/square.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/svg_edit_icons.svg +1034 -0
- data/vendor/assets/svg-edit-2.6/images/svg_edit_icons.svgz +0 -0
- data/vendor/assets/svg-edit-2.6/images/text.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/text.svg +157 -0
- data/vendor/assets/svg-edit-2.6/images/to_path.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/undo.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/view-refresh.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/wave.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/wireframe.png +0 -0
- data/vendor/assets/svg-edit-2.6/images/zoom.png +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/LICENSE +202 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/README +3 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/css/jPicker.css +1 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/css/jgraduate.css +351 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/images/AlphaBar.png +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/images/Bars.png +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/images/Maps.png +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/images/NoColor.png +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/images/bar-opacity.png +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/images/map-opacity.png +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/images/mappoint.gif +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/images/mappoint_c.png +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/images/mappoint_f.png +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/images/picker.gif +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/images/preview-opacity.png +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/images/rangearrows.gif +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/images/rangearrows2.gif +0 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/jpicker.js +2091 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/jpicker.min.js +1 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/jquery.jgraduate.js +1175 -0
- data/vendor/assets/svg-edit-2.6/jgraduate/jquery.jgraduate.min.js +37 -0
- data/vendor/assets/svg-edit-2.6/jquery-ui/jquery-ui-1.8.17.custom.min.js +54 -0
- data/vendor/assets/svg-edit-2.6/jquery-ui/jquery-ui-1.8.custom.min.js +84 -0
- data/vendor/assets/svg-edit-2.6/jquery.js +4 -0
- data/vendor/assets/svg-edit-2.6/jquerybbq/jquery.bbq.min.js +18 -0
- data/vendor/assets/svg-edit-2.6/js-hotkeys/README.md +45 -0
- data/vendor/assets/svg-edit-2.6/js-hotkeys/jquery.hotkeys.min.js +15 -0
- data/vendor/assets/svg-edit-2.6/locale/README.txt +17 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.af.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.ar.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.az.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.be.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.bg.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.ca.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.cs.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.cy.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.da.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.de.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.el.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.en.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.es.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.et.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.fa.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.fi.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.fr.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.fy.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.ga.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.gl.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.he.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.hi.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.hr.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.hu.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.hy.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.id.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.is.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.it.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.ja.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.ko.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.lt.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.lv.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.mk.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.ms.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.mt.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.nl.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.no.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.pl.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.pt-BR.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.pt-PT.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.ro.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.ru.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.sk.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.sl.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.sq.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.sr.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.sv.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.sw.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.test.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.th.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.tl.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.tr.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.uk.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.vi.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.yi.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.zh-CN.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.zh-HK.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/lang.zh-TW.js +234 -0
- data/vendor/assets/svg-edit-2.6/locale/locale.js +320 -0
- data/vendor/assets/svg-edit-2.6/math.js +246 -0
- data/vendor/assets/svg-edit-2.6/path.js +980 -0
- data/vendor/assets/svg-edit-2.6/sanitize.js +273 -0
- data/vendor/assets/svg-edit-2.6/select.js +532 -0
- data/vendor/assets/svg-edit-2.6/spinbtn/JQuerySpinBtn.css +41 -0
- data/vendor/assets/svg-edit-2.6/spinbtn/JQuerySpinBtn.js +266 -0
- data/vendor/assets/svg-edit-2.6/spinbtn/JQuerySpinBtn.min.js +7 -0
- data/vendor/assets/svg-edit-2.6/spinbtn/spinbtn_updn.png +0 -0
- data/vendor/assets/svg-edit-2.6/svg-editor.css +1495 -0
- data/vendor/assets/svg-edit-2.6/svg-editor.css~ +1500 -0
- data/vendor/assets/svg-edit-2.6/svg-editor.html +788 -0
- data/vendor/assets/svg-edit-2.6/svg-editor.html~ +788 -0
- data/vendor/assets/svg-edit-2.6/svg-editor.js +4969 -0
- data/vendor/assets/svg-edit-2.6/svg-editor.manifest +121 -0
- data/vendor/assets/svg-edit-2.6/svgcanvas.js +8775 -0
- data/vendor/assets/svg-edit-2.6/svgedit.compiled.js +465 -0
- data/vendor/assets/svg-edit-2.6/svgicons/jquery.svgicons.js +486 -0
- data/vendor/assets/svg-edit-2.6/svgtransformlist.js +291 -0
- data/vendor/assets/svg-edit-2.6/svgutils.js +651 -0
- data/vendor/assets/svg-edit-2.6/touch.js +30 -0
- data/vendor/assets/svg-edit-2.6/units.js +281 -0
- metadata +407 -0
@@ -0,0 +1,291 @@
|
|
1
|
+
/**
|
2
|
+
* SVGTransformList
|
3
|
+
*
|
4
|
+
* Licensed under the MIT License
|
5
|
+
*
|
6
|
+
* Copyright(c) 2010 Alexis Deveria
|
7
|
+
* Copyright(c) 2010 Jeff Schiller
|
8
|
+
*/
|
9
|
+
|
10
|
+
// Dependencies:
|
11
|
+
// 1) browser.js
|
12
|
+
|
13
|
+
var svgedit = svgedit || {};
|
14
|
+
|
15
|
+
(function() {
|
16
|
+
|
17
|
+
if (!svgedit.transformlist) {
|
18
|
+
svgedit.transformlist = {};
|
19
|
+
}
|
20
|
+
|
21
|
+
var svgroot = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
22
|
+
|
23
|
+
// Helper function.
|
24
|
+
function transformToString(xform) {
|
25
|
+
var m = xform.matrix,
|
26
|
+
text = "";
|
27
|
+
switch(xform.type) {
|
28
|
+
case 1: // MATRIX
|
29
|
+
text = "matrix(" + [m.a,m.b,m.c,m.d,m.e,m.f].join(",") + ")";
|
30
|
+
break;
|
31
|
+
case 2: // TRANSLATE
|
32
|
+
text = "translate(" + m.e + "," + m.f + ")";
|
33
|
+
break;
|
34
|
+
case 3: // SCALE
|
35
|
+
if (m.a == m.d) text = "scale(" + m.a + ")";
|
36
|
+
else text = "scale(" + m.a + "," + m.d + ")";
|
37
|
+
break;
|
38
|
+
case 4: // ROTATE
|
39
|
+
var cx = 0, cy = 0;
|
40
|
+
// this prevents divide by zero
|
41
|
+
if (xform.angle != 0) {
|
42
|
+
var K = 1 - m.a;
|
43
|
+
cy = ( K * m.f + m.b*m.e ) / ( K*K + m.b*m.b );
|
44
|
+
cx = ( m.e - m.b * cy ) / K;
|
45
|
+
}
|
46
|
+
text = "rotate(" + xform.angle + " " + cx + "," + cy + ")";
|
47
|
+
break;
|
48
|
+
}
|
49
|
+
return text;
|
50
|
+
};
|
51
|
+
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Map of SVGTransformList objects.
|
55
|
+
*/
|
56
|
+
var listMap_ = {};
|
57
|
+
|
58
|
+
|
59
|
+
// **************************************************************************************
|
60
|
+
// SVGTransformList implementation for Webkit
|
61
|
+
// These methods do not currently raise any exceptions.
|
62
|
+
// These methods also do not check that transforms are being inserted. This is basically
|
63
|
+
// implementing as much of SVGTransformList that we need to get the job done.
|
64
|
+
//
|
65
|
+
// interface SVGEditTransformList {
|
66
|
+
// attribute unsigned long numberOfItems;
|
67
|
+
// void clear ( )
|
68
|
+
// SVGTransform initialize ( in SVGTransform newItem )
|
69
|
+
// SVGTransform getItem ( in unsigned long index ) (DOES NOT THROW DOMException, INDEX_SIZE_ERR)
|
70
|
+
// SVGTransform insertItemBefore ( in SVGTransform newItem, in unsigned long index ) (DOES NOT THROW DOMException, INDEX_SIZE_ERR)
|
71
|
+
// SVGTransform replaceItem ( in SVGTransform newItem, in unsigned long index ) (DOES NOT THROW DOMException, INDEX_SIZE_ERR)
|
72
|
+
// SVGTransform removeItem ( in unsigned long index ) (DOES NOT THROW DOMException, INDEX_SIZE_ERR)
|
73
|
+
// SVGTransform appendItem ( in SVGTransform newItem )
|
74
|
+
// NOT IMPLEMENTED: SVGTransform createSVGTransformFromMatrix ( in SVGMatrix matrix );
|
75
|
+
// NOT IMPLEMENTED: SVGTransform consolidate ( );
|
76
|
+
// }
|
77
|
+
// **************************************************************************************
|
78
|
+
svgedit.transformlist.SVGTransformList = function(elem) {
|
79
|
+
this._elem = elem || null;
|
80
|
+
this._xforms = [];
|
81
|
+
// TODO: how do we capture the undo-ability in the changed transform list?
|
82
|
+
this._update = function() {
|
83
|
+
var tstr = "";
|
84
|
+
var concatMatrix = svgroot.createSVGMatrix();
|
85
|
+
for (var i = 0; i < this.numberOfItems; ++i) {
|
86
|
+
var xform = this._list.getItem(i);
|
87
|
+
tstr += transformToString(xform) + " ";
|
88
|
+
}
|
89
|
+
this._elem.setAttribute("transform", tstr);
|
90
|
+
};
|
91
|
+
this._list = this;
|
92
|
+
this._init = function() {
|
93
|
+
// Transform attribute parser
|
94
|
+
var str = this._elem.getAttribute("transform");
|
95
|
+
if(!str) return;
|
96
|
+
|
97
|
+
// TODO: Add skew support in future
|
98
|
+
var re = /\s*((scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/;
|
99
|
+
var arr = [];
|
100
|
+
var m = true;
|
101
|
+
while(m) {
|
102
|
+
m = str.match(re);
|
103
|
+
str = str.replace(re,'');
|
104
|
+
if(m && m[1]) {
|
105
|
+
var x = m[1];
|
106
|
+
var bits = x.split(/\s*\(/);
|
107
|
+
var name = bits[0];
|
108
|
+
var val_bits = bits[1].match(/\s*(.*?)\s*\)/);
|
109
|
+
val_bits[1] = val_bits[1].replace(/(\d)-/g, "$1 -");
|
110
|
+
var val_arr = val_bits[1].split(/[, ]+/);
|
111
|
+
var letters = 'abcdef'.split('');
|
112
|
+
var mtx = svgroot.createSVGMatrix();
|
113
|
+
$.each(val_arr, function(i, item) {
|
114
|
+
val_arr[i] = parseFloat(item);
|
115
|
+
if(name == 'matrix') {
|
116
|
+
mtx[letters[i]] = val_arr[i];
|
117
|
+
}
|
118
|
+
});
|
119
|
+
var xform = svgroot.createSVGTransform();
|
120
|
+
var fname = 'set' + name.charAt(0).toUpperCase() + name.slice(1);
|
121
|
+
var values = name=='matrix'?[mtx]:val_arr;
|
122
|
+
|
123
|
+
if (name == 'scale' && values.length == 1) {
|
124
|
+
values.push(values[0]);
|
125
|
+
} else if (name == 'translate' && values.length == 1) {
|
126
|
+
values.push(0);
|
127
|
+
} else if (name == 'rotate' && values.length == 1) {
|
128
|
+
values.push(0);
|
129
|
+
values.push(0);
|
130
|
+
}
|
131
|
+
xform[fname].apply(xform, values);
|
132
|
+
this._list.appendItem(xform);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
};
|
136
|
+
this._removeFromOtherLists = function(item) {
|
137
|
+
if (item) {
|
138
|
+
// Check if this transform is already in a transformlist, and
|
139
|
+
// remove it if so.
|
140
|
+
var found = false;
|
141
|
+
for (var id in listMap_) {
|
142
|
+
var tl = listMap_[id];
|
143
|
+
for (var i = 0, len = tl._xforms.length; i < len; ++i) {
|
144
|
+
if(tl._xforms[i] == item) {
|
145
|
+
found = true;
|
146
|
+
tl.removeItem(i);
|
147
|
+
break;
|
148
|
+
}
|
149
|
+
}
|
150
|
+
if (found) {
|
151
|
+
break;
|
152
|
+
}
|
153
|
+
}
|
154
|
+
}
|
155
|
+
};
|
156
|
+
|
157
|
+
this.numberOfItems = 0;
|
158
|
+
this.clear = function() {
|
159
|
+
this.numberOfItems = 0;
|
160
|
+
this._xforms = [];
|
161
|
+
};
|
162
|
+
|
163
|
+
this.initialize = function(newItem) {
|
164
|
+
this.numberOfItems = 1;
|
165
|
+
this._removeFromOtherLists(newItem);
|
166
|
+
this._xforms = [newItem];
|
167
|
+
};
|
168
|
+
|
169
|
+
this.getItem = function(index) {
|
170
|
+
if (index < this.numberOfItems && index >= 0) {
|
171
|
+
return this._xforms[index];
|
172
|
+
}
|
173
|
+
throw {code: 1}; // DOMException with code=INDEX_SIZE_ERR
|
174
|
+
};
|
175
|
+
|
176
|
+
this.insertItemBefore = function(newItem, index) {
|
177
|
+
var retValue = null;
|
178
|
+
if (index >= 0) {
|
179
|
+
if (index < this.numberOfItems) {
|
180
|
+
this._removeFromOtherLists(newItem);
|
181
|
+
var newxforms = new Array(this.numberOfItems + 1);
|
182
|
+
// TODO: use array copying and slicing
|
183
|
+
for ( var i = 0; i < index; ++i) {
|
184
|
+
newxforms[i] = this._xforms[i];
|
185
|
+
}
|
186
|
+
newxforms[i] = newItem;
|
187
|
+
for ( var j = i+1; i < this.numberOfItems; ++j, ++i) {
|
188
|
+
newxforms[j] = this._xforms[i];
|
189
|
+
}
|
190
|
+
this.numberOfItems++;
|
191
|
+
this._xforms = newxforms;
|
192
|
+
retValue = newItem;
|
193
|
+
this._list._update();
|
194
|
+
}
|
195
|
+
else {
|
196
|
+
retValue = this._list.appendItem(newItem);
|
197
|
+
}
|
198
|
+
}
|
199
|
+
return retValue;
|
200
|
+
};
|
201
|
+
|
202
|
+
this.replaceItem = function(newItem, index) {
|
203
|
+
var retValue = null;
|
204
|
+
if (index < this.numberOfItems && index >= 0) {
|
205
|
+
this._removeFromOtherLists(newItem);
|
206
|
+
this._xforms[index] = newItem;
|
207
|
+
retValue = newItem;
|
208
|
+
this._list._update();
|
209
|
+
}
|
210
|
+
return retValue;
|
211
|
+
};
|
212
|
+
|
213
|
+
this.removeItem = function(index) {
|
214
|
+
if (index < this.numberOfItems && index >= 0) {
|
215
|
+
var retValue = this._xforms[index];
|
216
|
+
var newxforms = new Array(this.numberOfItems - 1);
|
217
|
+
for (var i = 0; i < index; ++i) {
|
218
|
+
newxforms[i] = this._xforms[i];
|
219
|
+
}
|
220
|
+
for (var j = i; j < this.numberOfItems-1; ++j, ++i) {
|
221
|
+
newxforms[j] = this._xforms[i+1];
|
222
|
+
}
|
223
|
+
this.numberOfItems--;
|
224
|
+
this._xforms = newxforms;
|
225
|
+
this._list._update();
|
226
|
+
return retValue;
|
227
|
+
} else {
|
228
|
+
throw {code: 1}; // DOMException with code=INDEX_SIZE_ERR
|
229
|
+
}
|
230
|
+
};
|
231
|
+
|
232
|
+
this.appendItem = function(newItem) {
|
233
|
+
this._removeFromOtherLists(newItem);
|
234
|
+
this._xforms.push(newItem);
|
235
|
+
this.numberOfItems++;
|
236
|
+
this._list._update();
|
237
|
+
return newItem;
|
238
|
+
};
|
239
|
+
};
|
240
|
+
|
241
|
+
|
242
|
+
svgedit.transformlist.resetListMap = function() {
|
243
|
+
listMap_ = {};
|
244
|
+
};
|
245
|
+
|
246
|
+
/**
|
247
|
+
* Removes transforms of the given element from the map.
|
248
|
+
* Parameters:
|
249
|
+
* elem - a DOM Element
|
250
|
+
*/
|
251
|
+
svgedit.transformlist.removeElementFromListMap = function(elem) {
|
252
|
+
if (elem.id && listMap_[elem.id]) {
|
253
|
+
delete listMap_[elem.id];
|
254
|
+
}
|
255
|
+
};
|
256
|
+
|
257
|
+
// Function: getTransformList
|
258
|
+
// Returns an object that behaves like a SVGTransformList for the given DOM element
|
259
|
+
//
|
260
|
+
// Parameters:
|
261
|
+
// elem - DOM element to get a transformlist from
|
262
|
+
svgedit.transformlist.getTransformList = function(elem) {
|
263
|
+
if (!svgedit.browser.supportsNativeTransformLists()) {
|
264
|
+
var id = elem.id;
|
265
|
+
if(!id) {
|
266
|
+
// Get unique ID for temporary element
|
267
|
+
id = 'temp';
|
268
|
+
}
|
269
|
+
var t = listMap_[id];
|
270
|
+
if (!t || id == 'temp') {
|
271
|
+
listMap_[id] = new svgedit.transformlist.SVGTransformList(elem);
|
272
|
+
listMap_[id]._init();
|
273
|
+
t = listMap_[id];
|
274
|
+
}
|
275
|
+
return t;
|
276
|
+
}
|
277
|
+
else if (elem.transform) {
|
278
|
+
return elem.transform.baseVal;
|
279
|
+
}
|
280
|
+
else if (elem.gradientTransform) {
|
281
|
+
return elem.gradientTransform.baseVal;
|
282
|
+
}
|
283
|
+
else if (elem.patternTransform) {
|
284
|
+
return elem.patternTransform.baseVal;
|
285
|
+
}
|
286
|
+
|
287
|
+
return null;
|
288
|
+
};
|
289
|
+
|
290
|
+
|
291
|
+
})();
|
@@ -0,0 +1,651 @@
|
|
1
|
+
/**
|
2
|
+
* Package: svgedit.utilities
|
3
|
+
*
|
4
|
+
* Licensed under the MIT License
|
5
|
+
*
|
6
|
+
* Copyright(c) 2010 Alexis Deveria
|
7
|
+
* Copyright(c) 2010 Jeff Schiller
|
8
|
+
*/
|
9
|
+
|
10
|
+
// Dependencies:
|
11
|
+
// 1) jQuery
|
12
|
+
// 2) browser.js
|
13
|
+
// 3) svgtransformlist.js
|
14
|
+
|
15
|
+
var svgedit = svgedit || {};
|
16
|
+
|
17
|
+
(function() {
|
18
|
+
|
19
|
+
if (!svgedit.utilities) {
|
20
|
+
svgedit.utilities = {};
|
21
|
+
}
|
22
|
+
|
23
|
+
// Constants
|
24
|
+
|
25
|
+
// String used to encode base64.
|
26
|
+
var KEYSTR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
27
|
+
var SVGNS = 'http://www.w3.org/2000/svg';
|
28
|
+
var XLINKNS = 'http://www.w3.org/1999/xlink';
|
29
|
+
var XMLNS = "http://www.w3.org/XML/1998/namespace";
|
30
|
+
|
31
|
+
// Much faster than running getBBox() every time
|
32
|
+
var visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use';
|
33
|
+
var visElems_arr = visElems.split(',');
|
34
|
+
//var hidElems = 'clipPath,defs,desc,feGaussianBlur,filter,linearGradient,marker,mask,metadata,pattern,radialGradient,stop,switch,symbol,title,textPath';
|
35
|
+
|
36
|
+
var editorContext_ = null;
|
37
|
+
var domdoc_ = null;
|
38
|
+
var domcontainer_ = null;
|
39
|
+
var svgroot_ = null;
|
40
|
+
|
41
|
+
svgedit.utilities.init = function(editorContext) {
|
42
|
+
editorContext_ = editorContext;
|
43
|
+
domdoc_ = editorContext.getDOMDocument();
|
44
|
+
domcontainer_ = editorContext.getDOMContainer();
|
45
|
+
svgroot_ = editorContext.getSVGRoot();
|
46
|
+
};
|
47
|
+
|
48
|
+
// Function: svgedit.utilities.toXml
|
49
|
+
// Converts characters in a string to XML-friendly entities.
|
50
|
+
//
|
51
|
+
// Example: "&" becomes "&"
|
52
|
+
//
|
53
|
+
// Parameters:
|
54
|
+
// str - The string to be converted
|
55
|
+
//
|
56
|
+
// Returns:
|
57
|
+
// The converted string
|
58
|
+
svgedit.utilities.toXml = function(str) {
|
59
|
+
return $('<p/>').text(str).html();
|
60
|
+
};
|
61
|
+
|
62
|
+
// Function: svgedit.utilities.fromXml
|
63
|
+
// Converts XML entities in a string to single characters.
|
64
|
+
// Example: "&" becomes "&"
|
65
|
+
//
|
66
|
+
// Parameters:
|
67
|
+
// str - The string to be converted
|
68
|
+
//
|
69
|
+
// Returns:
|
70
|
+
// The converted string
|
71
|
+
svgedit.utilities.fromXml = function(str) {
|
72
|
+
return $('<p/>').html(str).text();
|
73
|
+
};
|
74
|
+
|
75
|
+
// This code was written by Tyler Akins and has been placed in the
|
76
|
+
// public domain. It would be nice if you left this header intact.
|
77
|
+
// Base64 code from Tyler Akins -- http://rumkin.com
|
78
|
+
|
79
|
+
// schiller: Removed string concatenation in favour of Array.join() optimization,
|
80
|
+
// also precalculate the size of the array needed.
|
81
|
+
|
82
|
+
// Function: svgedit.utilities.encode64
|
83
|
+
// Converts a string to base64
|
84
|
+
svgedit.utilities.encode64 = function(input) {
|
85
|
+
// base64 strings are 4/3 larger than the original string
|
86
|
+
// input = svgedit.utilities.encodeUTF8(input); // convert non-ASCII characters
|
87
|
+
input = svgedit.utilities.convertToXMLReferences(input);
|
88
|
+
if(window.btoa) return window.btoa(input); // Use native if available
|
89
|
+
var output = new Array( Math.floor( (input.length + 2) / 3 ) * 4 );
|
90
|
+
var chr1, chr2, chr3;
|
91
|
+
var enc1, enc2, enc3, enc4;
|
92
|
+
var i = 0, p = 0;
|
93
|
+
|
94
|
+
do {
|
95
|
+
chr1 = input.charCodeAt(i++);
|
96
|
+
chr2 = input.charCodeAt(i++);
|
97
|
+
chr3 = input.charCodeAt(i++);
|
98
|
+
|
99
|
+
enc1 = chr1 >> 2;
|
100
|
+
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
101
|
+
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
102
|
+
enc4 = chr3 & 63;
|
103
|
+
|
104
|
+
if (isNaN(chr2)) {
|
105
|
+
enc3 = enc4 = 64;
|
106
|
+
} else if (isNaN(chr3)) {
|
107
|
+
enc4 = 64;
|
108
|
+
}
|
109
|
+
|
110
|
+
output[p++] = KEYSTR.charAt(enc1);
|
111
|
+
output[p++] = KEYSTR.charAt(enc2);
|
112
|
+
output[p++] = KEYSTR.charAt(enc3);
|
113
|
+
output[p++] = KEYSTR.charAt(enc4);
|
114
|
+
} while (i < input.length);
|
115
|
+
|
116
|
+
return output.join('');
|
117
|
+
};
|
118
|
+
|
119
|
+
// Function: svgedit.utilities.decode64
|
120
|
+
// Converts a string from base64
|
121
|
+
svgedit.utilities.decode64 = function(input) {
|
122
|
+
if(window.atob) return window.atob(input);
|
123
|
+
var output = "";
|
124
|
+
var chr1, chr2, chr3 = "";
|
125
|
+
var enc1, enc2, enc3, enc4 = "";
|
126
|
+
var i = 0;
|
127
|
+
|
128
|
+
// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
|
129
|
+
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
130
|
+
|
131
|
+
do {
|
132
|
+
enc1 = KEYSTR.indexOf(input.charAt(i++));
|
133
|
+
enc2 = KEYSTR.indexOf(input.charAt(i++));
|
134
|
+
enc3 = KEYSTR.indexOf(input.charAt(i++));
|
135
|
+
enc4 = KEYSTR.indexOf(input.charAt(i++));
|
136
|
+
|
137
|
+
chr1 = (enc1 << 2) | (enc2 >> 4);
|
138
|
+
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
139
|
+
chr3 = ((enc3 & 3) << 6) | enc4;
|
140
|
+
|
141
|
+
output = output + String.fromCharCode(chr1);
|
142
|
+
|
143
|
+
if (enc3 != 64) {
|
144
|
+
output = output + String.fromCharCode(chr2);
|
145
|
+
}
|
146
|
+
if (enc4 != 64) {
|
147
|
+
output = output + String.fromCharCode(chr3);
|
148
|
+
}
|
149
|
+
|
150
|
+
chr1 = chr2 = chr3 = "";
|
151
|
+
enc1 = enc2 = enc3 = enc4 = "";
|
152
|
+
|
153
|
+
} while (i < input.length);
|
154
|
+
return unescape(output);
|
155
|
+
};
|
156
|
+
|
157
|
+
// Currently not being used, so commented out for now
|
158
|
+
// based on http://phpjs.org/functions/utf8_encode:577
|
159
|
+
// codedread:does not seem to work with webkit-based browsers on OSX
|
160
|
+
// "encodeUTF8": function(input) {
|
161
|
+
// //return unescape(encodeURIComponent(input)); //may or may not work
|
162
|
+
// var output = '';
|
163
|
+
// for (var n = 0; n < input.length; n++){
|
164
|
+
// var c = input.charCodeAt(n);
|
165
|
+
// if (c < 128) {
|
166
|
+
// output += input[n];
|
167
|
+
// }
|
168
|
+
// else if (c > 127) {
|
169
|
+
// if (c < 2048){
|
170
|
+
// output += String.fromCharCode((c >> 6) | 192);
|
171
|
+
// }
|
172
|
+
// else {
|
173
|
+
// output += String.fromCharCode((c >> 12) | 224) + String.fromCharCode((c >> 6) & 63 | 128);
|
174
|
+
// }
|
175
|
+
// output += String.fromCharCode((c & 63) | 128);
|
176
|
+
// }
|
177
|
+
// }
|
178
|
+
// return output;
|
179
|
+
// },
|
180
|
+
|
181
|
+
// Function: svgedit.utilities.convertToXMLReferences
|
182
|
+
// Converts a string to use XML references
|
183
|
+
svgedit.utilities.convertToXMLReferences = function(input) {
|
184
|
+
var output = '';
|
185
|
+
for (var n = 0; n < input.length; n++){
|
186
|
+
var c = input.charCodeAt(n);
|
187
|
+
if (c < 128) {
|
188
|
+
output += input[n];
|
189
|
+
} else if(c > 127) {
|
190
|
+
output += ("&#" + c + ";");
|
191
|
+
}
|
192
|
+
}
|
193
|
+
return output;
|
194
|
+
};
|
195
|
+
|
196
|
+
// Function: svgedit.utilities.text2xml
|
197
|
+
// Cross-browser compatible method of converting a string to an XML tree
|
198
|
+
// found this function here: http://groups.google.com/group/jquery-dev/browse_thread/thread/c6d11387c580a77f
|
199
|
+
svgedit.utilities.text2xml = function(sXML) {
|
200
|
+
if(sXML.indexOf('<svg:svg') >= 0) {
|
201
|
+
sXML = sXML.replace(/<(\/?)svg:/g, '<$1').replace('xmlns:svg', 'xmlns');
|
202
|
+
}
|
203
|
+
|
204
|
+
var out;
|
205
|
+
try{
|
206
|
+
var dXML = (window.DOMParser)?new DOMParser():new ActiveXObject("Microsoft.XMLDOM");
|
207
|
+
dXML.async = false;
|
208
|
+
} catch(e){
|
209
|
+
throw new Error("XML Parser could not be instantiated");
|
210
|
+
};
|
211
|
+
try{
|
212
|
+
if(dXML.loadXML) out = (dXML.loadXML(sXML))?dXML:false;
|
213
|
+
else out = dXML.parseFromString(sXML, "text/xml");
|
214
|
+
}
|
215
|
+
catch(e){ throw new Error("Error parsing XML string"); };
|
216
|
+
return out;
|
217
|
+
};
|
218
|
+
|
219
|
+
// Function: svgedit.utilities.bboxToObj
|
220
|
+
// Converts a SVGRect into an object.
|
221
|
+
//
|
222
|
+
// Parameters:
|
223
|
+
// bbox - a SVGRect
|
224
|
+
//
|
225
|
+
// Returns:
|
226
|
+
// An object with properties names x, y, width, height.
|
227
|
+
svgedit.utilities.bboxToObj = function(bbox) {
|
228
|
+
return {
|
229
|
+
x: bbox.x,
|
230
|
+
y: bbox.y,
|
231
|
+
width: bbox.width,
|
232
|
+
height: bbox.height
|
233
|
+
}
|
234
|
+
};
|
235
|
+
|
236
|
+
// Function: svgedit.utilities.walkTree
|
237
|
+
// Walks the tree and executes the callback on each element in a top-down fashion
|
238
|
+
//
|
239
|
+
// Parameters:
|
240
|
+
// elem - DOM element to traverse
|
241
|
+
// cbFn - Callback function to run on each element
|
242
|
+
svgedit.utilities.walkTree = function(elem, cbFn){
|
243
|
+
if (elem && elem.nodeType == 1) {
|
244
|
+
cbFn(elem);
|
245
|
+
var i = elem.childNodes.length;
|
246
|
+
while (i--) {
|
247
|
+
svgedit.utilities.walkTree(elem.childNodes.item(i), cbFn);
|
248
|
+
}
|
249
|
+
}
|
250
|
+
};
|
251
|
+
|
252
|
+
// Function: svgedit.utilities.walkTreePost
|
253
|
+
// Walks the tree and executes the callback on each element in a depth-first fashion
|
254
|
+
// TODO: FIXME: Shouldn't this be calling walkTreePost?
|
255
|
+
//
|
256
|
+
// Parameters:
|
257
|
+
// elem - DOM element to traverse
|
258
|
+
// cbFn - Callback function to run on each element
|
259
|
+
svgedit.utilities.walkTreePost = function(elem, cbFn) {
|
260
|
+
if (elem && elem.nodeType == 1) {
|
261
|
+
var i = elem.childNodes.length;
|
262
|
+
while (i--) {
|
263
|
+
svgedit.utilities.walkTree(elem.childNodes.item(i), cbFn);
|
264
|
+
}
|
265
|
+
cbFn(elem);
|
266
|
+
}
|
267
|
+
};
|
268
|
+
|
269
|
+
// Function: svgedit.utilities.getUrlFromAttr
|
270
|
+
// Extracts the URL from the url(...) syntax of some attributes.
|
271
|
+
// Three variants:
|
272
|
+
// * <circle fill="url(someFile.svg#foo)" />
|
273
|
+
// * <circle fill="url('someFile.svg#foo')" />
|
274
|
+
// * <circle fill='url("someFile.svg#foo")' />
|
275
|
+
//
|
276
|
+
// Parameters:
|
277
|
+
// attrVal - The attribute value as a string
|
278
|
+
//
|
279
|
+
// Returns:
|
280
|
+
// String with just the URL, like someFile.svg#foo
|
281
|
+
svgedit.utilities.getUrlFromAttr = function(attrVal) {
|
282
|
+
if (attrVal) {
|
283
|
+
// url("#somegrad")
|
284
|
+
if (attrVal.indexOf('url("') === 0) {
|
285
|
+
return attrVal.substring(5,attrVal.indexOf('"',6));
|
286
|
+
}
|
287
|
+
// url('#somegrad')
|
288
|
+
else if (attrVal.indexOf("url('") === 0) {
|
289
|
+
return attrVal.substring(5,attrVal.indexOf("'",6));
|
290
|
+
}
|
291
|
+
else if (attrVal.indexOf("url(") === 0) {
|
292
|
+
return attrVal.substring(4,attrVal.indexOf(')'));
|
293
|
+
}
|
294
|
+
}
|
295
|
+
return null;
|
296
|
+
};
|
297
|
+
|
298
|
+
// Function: svgedit.utilities.getHref
|
299
|
+
// Returns the given element's xlink:href value
|
300
|
+
svgedit.utilities.getHref = function(elem) {
|
301
|
+
return elem.getAttributeNS(XLINKNS, "href");
|
302
|
+
}
|
303
|
+
|
304
|
+
// Function: svgedit.utilities.setHref
|
305
|
+
// Sets the given element's xlink:href value
|
306
|
+
svgedit.utilities.setHref = function(elem, val) {
|
307
|
+
elem.setAttributeNS(XLINKNS, "xlink:href", val);
|
308
|
+
}
|
309
|
+
|
310
|
+
// Function: findDefs
|
311
|
+
// Parameters:
|
312
|
+
// svgElement - The <svg> element.
|
313
|
+
//
|
314
|
+
// Returns:
|
315
|
+
// The document's <defs> element, create it first if necessary
|
316
|
+
svgedit.utilities.findDefs = function(svgElement) {
|
317
|
+
var svgElement = editorContext_.getSVGContent().documentElement;
|
318
|
+
var defs = svgElement.getElementsByTagNameNS(SVGNS, "defs");
|
319
|
+
if (defs.length > 0) {
|
320
|
+
defs = defs[0];
|
321
|
+
}
|
322
|
+
else {
|
323
|
+
// first child is a comment, so call nextSibling
|
324
|
+
defs = svgElement.insertBefore( svgElement.ownerDocument.createElementNS(SVGNS, "defs" ), svgElement.firstChild.nextSibling);
|
325
|
+
}
|
326
|
+
return defs;
|
327
|
+
};
|
328
|
+
|
329
|
+
// TODO(codedread): Consider moving the next to functions to bbox.js
|
330
|
+
|
331
|
+
// Function: svgedit.utilities.getPathBBox
|
332
|
+
// Get correct BBox for a path in Webkit
|
333
|
+
// Converted from code found here:
|
334
|
+
// http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
|
335
|
+
//
|
336
|
+
// Parameters:
|
337
|
+
// path - The path DOM element to get the BBox for
|
338
|
+
//
|
339
|
+
// Returns:
|
340
|
+
// A BBox-like object
|
341
|
+
svgedit.utilities.getPathBBox = function(path) {
|
342
|
+
var seglist = path.pathSegList;
|
343
|
+
var tot = seglist.numberOfItems;
|
344
|
+
|
345
|
+
var bounds = [[], []];
|
346
|
+
var start = seglist.getItem(0);
|
347
|
+
var P0 = [start.x, start.y];
|
348
|
+
|
349
|
+
for(var i=0; i < tot; i++) {
|
350
|
+
var seg = seglist.getItem(i);
|
351
|
+
|
352
|
+
if(typeof seg.x == 'undefined') continue;
|
353
|
+
|
354
|
+
// Add actual points to limits
|
355
|
+
bounds[0].push(P0[0]);
|
356
|
+
bounds[1].push(P0[1]);
|
357
|
+
|
358
|
+
if(seg.x1) {
|
359
|
+
var P1 = [seg.x1, seg.y1],
|
360
|
+
P2 = [seg.x2, seg.y2],
|
361
|
+
P3 = [seg.x, seg.y];
|
362
|
+
|
363
|
+
for(var j=0; j < 2; j++) {
|
364
|
+
|
365
|
+
var calc = function(t) {
|
366
|
+
return Math.pow(1-t,3) * P0[j]
|
367
|
+
+ 3 * Math.pow(1-t,2) * t * P1[j]
|
368
|
+
+ 3 * (1-t) * Math.pow(t,2) * P2[j]
|
369
|
+
+ Math.pow(t,3) * P3[j];
|
370
|
+
};
|
371
|
+
|
372
|
+
var b = 6 * P0[j] - 12 * P1[j] + 6 * P2[j];
|
373
|
+
var a = -3 * P0[j] + 9 * P1[j] - 9 * P2[j] + 3 * P3[j];
|
374
|
+
var c = 3 * P1[j] - 3 * P0[j];
|
375
|
+
|
376
|
+
if(a == 0) {
|
377
|
+
if(b == 0) {
|
378
|
+
continue;
|
379
|
+
}
|
380
|
+
var t = -c / b;
|
381
|
+
if(0 < t && t < 1) {
|
382
|
+
bounds[j].push(calc(t));
|
383
|
+
}
|
384
|
+
continue;
|
385
|
+
}
|
386
|
+
|
387
|
+
var b2ac = Math.pow(b,2) - 4 * c * a;
|
388
|
+
if(b2ac < 0) continue;
|
389
|
+
var t1 = (-b + Math.sqrt(b2ac))/(2 * a);
|
390
|
+
if(0 < t1 && t1 < 1) bounds[j].push(calc(t1));
|
391
|
+
var t2 = (-b - Math.sqrt(b2ac))/(2 * a);
|
392
|
+
if(0 < t2 && t2 < 1) bounds[j].push(calc(t2));
|
393
|
+
}
|
394
|
+
P0 = P3;
|
395
|
+
} else {
|
396
|
+
bounds[0].push(seg.x);
|
397
|
+
bounds[1].push(seg.y);
|
398
|
+
}
|
399
|
+
}
|
400
|
+
|
401
|
+
var x = Math.min.apply(null, bounds[0]);
|
402
|
+
var w = Math.max.apply(null, bounds[0]) - x;
|
403
|
+
var y = Math.min.apply(null, bounds[1]);
|
404
|
+
var h = Math.max.apply(null, bounds[1]) - y;
|
405
|
+
return {
|
406
|
+
'x': x,
|
407
|
+
'y': y,
|
408
|
+
'width': w,
|
409
|
+
'height': h
|
410
|
+
};
|
411
|
+
};
|
412
|
+
|
413
|
+
// Function: groupBBFix
|
414
|
+
// Get the given/selected element's bounding box object, checking for
|
415
|
+
// horizontal/vertical lines (see issue 717)
|
416
|
+
// Note that performance is currently terrible, so some way to improve would
|
417
|
+
// be great.
|
418
|
+
//
|
419
|
+
// Parameters:
|
420
|
+
// selected - Container or <use> DOM element
|
421
|
+
function groupBBFix(selected) {
|
422
|
+
if(svgedit.browser.supportsHVLineContainerBBox()) {
|
423
|
+
try { return selected.getBBox();} catch(e){}
|
424
|
+
}
|
425
|
+
var ref = $.data(selected, 'ref');
|
426
|
+
var matched = null;
|
427
|
+
|
428
|
+
if(ref) {
|
429
|
+
var copy = $(ref).children().clone().attr('visibility', 'hidden');
|
430
|
+
$(svgroot_).append(copy);
|
431
|
+
matched = copy.filter('line, path');
|
432
|
+
} else {
|
433
|
+
matched = $(selected).find('line, path');
|
434
|
+
}
|
435
|
+
|
436
|
+
var issue = false;
|
437
|
+
if(matched.length) {
|
438
|
+
matched.each(function() {
|
439
|
+
var bb = this.getBBox();
|
440
|
+
if(!bb.width || !bb.height) {
|
441
|
+
issue = true;
|
442
|
+
}
|
443
|
+
});
|
444
|
+
if(issue) {
|
445
|
+
var elems = ref ? copy : $(selected).children();
|
446
|
+
ret = getStrokedBBox(elems);
|
447
|
+
} else {
|
448
|
+
ret = selected.getBBox();
|
449
|
+
}
|
450
|
+
} else {
|
451
|
+
ret = selected.getBBox();
|
452
|
+
}
|
453
|
+
if(ref) {
|
454
|
+
copy.remove();
|
455
|
+
}
|
456
|
+
return ret;
|
457
|
+
}
|
458
|
+
|
459
|
+
// Function: svgedit.utilities.getBBox
|
460
|
+
// Get the given/selected element's bounding box object, convert it to be more
|
461
|
+
// usable when necessary
|
462
|
+
//
|
463
|
+
// Parameters:
|
464
|
+
// elem - Optional DOM element to get the BBox for
|
465
|
+
svgedit.utilities.getBBox = function(elem) {
|
466
|
+
var selected = elem || editorContext_.geSelectedElements()[0];
|
467
|
+
if (elem.nodeType != 1) return null;
|
468
|
+
var ret = null;
|
469
|
+
var elname = selected.nodeName;
|
470
|
+
|
471
|
+
switch ( elname ) {
|
472
|
+
case 'text':
|
473
|
+
if(selected.textContent === '') {
|
474
|
+
selected.textContent = 'a'; // Some character needed for the selector to use.
|
475
|
+
ret = selected.getBBox();
|
476
|
+
selected.textContent = '';
|
477
|
+
} else {
|
478
|
+
try { ret = selected.getBBox();} catch(e){}
|
479
|
+
}
|
480
|
+
break;
|
481
|
+
case 'path':
|
482
|
+
if(!svgedit.browser.supportsPathBBox()) {
|
483
|
+
ret = svgedit.utilities.getPathBBox(selected);
|
484
|
+
} else {
|
485
|
+
try { ret = selected.getBBox();} catch(e){}
|
486
|
+
}
|
487
|
+
break;
|
488
|
+
case 'g':
|
489
|
+
case 'a':
|
490
|
+
ret = groupBBFix(selected);
|
491
|
+
break;
|
492
|
+
default:
|
493
|
+
|
494
|
+
if(elname === 'use') {
|
495
|
+
ret = groupBBFix(selected, true);
|
496
|
+
}
|
497
|
+
|
498
|
+
if(elname === 'use') {
|
499
|
+
if(!ret) ret = selected.getBBox();
|
500
|
+
// This is resolved in later versions of webkit, perhaps we should
|
501
|
+
// have a featured detection for correct 'use' behavior?
|
502
|
+
// ——————————
|
503
|
+
//if(!svgedit.browser.isWebkit()) {
|
504
|
+
var bb = {};
|
505
|
+
bb.width = ret.width;
|
506
|
+
bb.height = ret.height;
|
507
|
+
bb.x = ret.x + parseFloat(selected.getAttribute('x')||0);
|
508
|
+
bb.y = ret.y + parseFloat(selected.getAttribute('y')||0);
|
509
|
+
ret = bb;
|
510
|
+
//}
|
511
|
+
} else if(~visElems_arr.indexOf(elname)) {
|
512
|
+
try { ret = selected.getBBox();}
|
513
|
+
catch(e) {
|
514
|
+
// Check if element is child of a foreignObject
|
515
|
+
var fo = $(selected).closest("foreignObject");
|
516
|
+
if(fo.length) {
|
517
|
+
try {
|
518
|
+
ret = fo[0].getBBox();
|
519
|
+
} catch(e) {
|
520
|
+
ret = null;
|
521
|
+
}
|
522
|
+
} else {
|
523
|
+
ret = null;
|
524
|
+
}
|
525
|
+
}
|
526
|
+
}
|
527
|
+
}
|
528
|
+
|
529
|
+
if(ret) {
|
530
|
+
ret = svgedit.utilities.bboxToObj(ret);
|
531
|
+
}
|
532
|
+
|
533
|
+
// get the bounding box from the DOM (which is in that element's coordinate system)
|
534
|
+
return ret;
|
535
|
+
};
|
536
|
+
|
537
|
+
// Function: svgedit.utilities.getRotationAngle
|
538
|
+
// Get the rotation angle of the given/selected DOM element
|
539
|
+
//
|
540
|
+
// Parameters:
|
541
|
+
// elem - Optional DOM element to get the angle for
|
542
|
+
// to_rad - Boolean that when true returns the value in radians rather than degrees
|
543
|
+
//
|
544
|
+
// Returns:
|
545
|
+
// Float with the angle in degrees or radians
|
546
|
+
svgedit.utilities.getRotationAngle = function(elem, to_rad) {
|
547
|
+
var selected = elem || editorContext_.getSelectedElements()[0];
|
548
|
+
// find the rotation transform (if any) and set it
|
549
|
+
var tlist = svgedit.transformlist.getTransformList(selected);
|
550
|
+
if(!tlist) return 0; // <svg> elements have no tlist
|
551
|
+
var N = tlist.numberOfItems;
|
552
|
+
for (var i = 0; i < N; ++i) {
|
553
|
+
var xform = tlist.getItem(i);
|
554
|
+
if (xform.type == 4) {
|
555
|
+
return to_rad ? xform.angle * Math.PI / 180.0 : xform.angle;
|
556
|
+
}
|
557
|
+
}
|
558
|
+
return 0.0;
|
559
|
+
};
|
560
|
+
|
561
|
+
// Function: getElem
|
562
|
+
// Get a DOM element by ID within the SVG root element.
|
563
|
+
//
|
564
|
+
// Parameters:
|
565
|
+
// id - String with the element's new ID
|
566
|
+
if (svgedit.browser.supportsSelectors()) {
|
567
|
+
svgedit.utilities.getElem = function(id) {
|
568
|
+
// querySelector lookup
|
569
|
+
return svgroot_.querySelector('#'+id);
|
570
|
+
};
|
571
|
+
} else if (svgedit.browser.supportsXpath()) {
|
572
|
+
svgedit.utilities.getElem = function(id) {
|
573
|
+
// xpath lookup
|
574
|
+
return domdoc_.evaluate(
|
575
|
+
'svg:svg[@id="svgroot"]//svg:*[@id="'+id+'"]',
|
576
|
+
domcontainer_,
|
577
|
+
function() { return "http://www.w3.org/2000/svg"; },
|
578
|
+
9,
|
579
|
+
null).singleNodeValue;
|
580
|
+
};
|
581
|
+
} else {
|
582
|
+
svgedit.utilities.getElem = function(id) {
|
583
|
+
// jQuery lookup: twice as slow as xpath in FF
|
584
|
+
return $(svgroot_).find('[id=' + id + ']')[0];
|
585
|
+
};
|
586
|
+
}
|
587
|
+
|
588
|
+
// Function: assignAttributes
|
589
|
+
// Assigns multiple attributes to an element.
|
590
|
+
//
|
591
|
+
// Parameters:
|
592
|
+
// node - DOM element to apply new attribute values to
|
593
|
+
// attrs - Object with attribute keys/values
|
594
|
+
// suspendLength - Optional integer of milliseconds to suspend redraw
|
595
|
+
// unitCheck - Boolean to indicate the need to use svgedit.units.setUnitAttr
|
596
|
+
svgedit.utilities.assignAttributes = function(node, attrs, suspendLength, unitCheck) {
|
597
|
+
if(!suspendLength) suspendLength = 0;
|
598
|
+
// Opera has a problem with suspendRedraw() apparently
|
599
|
+
var handle = null;
|
600
|
+
if (!svgedit.browser.isOpera()) svgroot_.suspendRedraw(suspendLength);
|
601
|
+
|
602
|
+
for (var i in attrs) {
|
603
|
+
var ns = (i.substr(0,4) === "xml:" ? XMLNS :
|
604
|
+
i.substr(0,6) === "xlink:" ? XLINKNS : null);
|
605
|
+
|
606
|
+
if(ns) {
|
607
|
+
node.setAttributeNS(ns, i, attrs[i]);
|
608
|
+
} else if(!unitCheck) {
|
609
|
+
node.setAttribute(i, attrs[i]);
|
610
|
+
} else {
|
611
|
+
svgedit.units.setUnitAttr(node, i, attrs[i]);
|
612
|
+
}
|
613
|
+
|
614
|
+
}
|
615
|
+
|
616
|
+
if (!svgedit.browser.isOpera()) svgroot_.unsuspendRedraw(handle);
|
617
|
+
};
|
618
|
+
|
619
|
+
// Function: cleanupElement
|
620
|
+
// Remove unneeded (default) attributes, makes resulting SVG smaller
|
621
|
+
//
|
622
|
+
// Parameters:
|
623
|
+
// element - DOM element to clean up
|
624
|
+
svgedit.utilities.cleanupElement = function(element) {
|
625
|
+
var handle = svgroot_.suspendRedraw(60);
|
626
|
+
var defaults = {
|
627
|
+
'fill-opacity':1,
|
628
|
+
'stop-opacity':1,
|
629
|
+
'opacity':1,
|
630
|
+
'stroke':'none',
|
631
|
+
'stroke-dasharray':'none',
|
632
|
+
'stroke-linejoin':'miter',
|
633
|
+
'stroke-linecap':'butt',
|
634
|
+
'stroke-opacity':1,
|
635
|
+
'stroke-width':1,
|
636
|
+
'rx':0,
|
637
|
+
'ry':0
|
638
|
+
}
|
639
|
+
|
640
|
+
for(var attr in defaults) {
|
641
|
+
var val = defaults[attr];
|
642
|
+
if(element.getAttribute(attr) == val) {
|
643
|
+
element.removeAttribute(attr);
|
644
|
+
}
|
645
|
+
}
|
646
|
+
|
647
|
+
svgroot_.unsuspendRedraw(handle);
|
648
|
+
};
|
649
|
+
|
650
|
+
|
651
|
+
})();
|