Converts all paths in an SVG file to all-absolute / all-relative coordinates, and prints the result to stdout.
Origin: https://github.com/johan/kilobyte-svg-challenge/blob/master/tools/
Converts all paths in an SVG file to all-absolute / all-relative coordinates, and prints the result to stdout.
Origin: https://github.com/johan/kilobyte-svg-challenge/blob/master/tools/
#! /usr/bin/env phantomjs | |
var webpage = require('webpage') | |
, URL; | |
; | |
if (phantom.args.length < 1 || phantom.args.length > 1) { | |
console.log('Usage: svg2abs source.svg'); | |
phantom.exit(); | |
} | |
else { | |
URL = phantom.args[0]; | |
load(URL, absolutize); | |
} | |
function load(url, fn) { | |
var page = webpage.create(); | |
page.onConsoleMessage = function(msg) { | |
console.log(msg); | |
}; | |
page.open(url, function (status) { | |
if (status !== 'success') | |
console.log('Unable to load ' + url); | |
else | |
fn(page); | |
}); | |
} | |
function absolutize(page) { | |
page.onConsoleMessage = function(msg) { | |
console.log(msg); | |
phantom.exit(); | |
}; | |
page.evaluate(onSVG); | |
} | |
function onSVG() { | |
var svg = document.documentElement | |
, all = [].slice.call(document.querySelectorAll('path'), 0); | |
all.forEach(convertToAbsolute); | |
console.log((new XMLSerializer).serializeToString(svg)); | |
// from: http://stackoverflow.com/a/9677915/1130377 | |
function convertToAbsolute(path) { | |
function set(type) { | |
var args = [].slice.call(arguments, 1); | |
segs.replaceItem(path['createSVGPathSeg' + type].apply(path, args), i); | |
} | |
var x0, y0, x1, y1, x2, y2, segs = path.pathSegList; | |
for (var x = 0, y = 0, i = 0, len = segs.numberOfItems; i < len; i++) { | |
var seg = segs.getItem(i) | |
, c = seg.pathSegTypeAsLetter; | |
if (/[MLHVCSQTA]/.test(c)) { | |
if ('x' in seg) x = seg.x; | |
if ('y' in seg) y = seg.y; | |
} | |
else { | |
if ('x1' in seg) x1 = seg.x1 + x; | |
if ('x2' in seg) x2 = seg.x2 + x; | |
if ('y1' in seg) y1 = seg.y1 + y; | |
if ('y2' in seg) y2 = seg.y2 + y; | |
if ('x' in seg) x += seg.x; | |
if ('y' in seg) y += seg.y; | |
switch (c) { | |
case 'm': set('MovetoAbs',x,y); break; | |
case 'l': set('LinetoAbs',x,y); break; | |
case 'h': set('LinetoHorizontalAbs',x); break; | |
case 'v': set('LinetoVerticalAbs',y); break; | |
case 'c': set('CurvetoCubicAbs',x,y,x1,y1,x2,y2); break; | |
case 's': set('CurvetoCubicSmoothAbs',x,y,x2,y2); break; | |
case 'q': set('CurvetoQuadraticAbs',x,y,x1,y1); break; | |
case 't': set('CurvetoQuadraticSmoothAbs',x,y); break; | |
case 'a': set('ArcAbs',x,y,seg.r1,seg.r2,seg.angle, | |
seg.largeArcFlag,seg.sweepFlag); break; | |
case 'z': case 'Z': x = x0; y = y0; break; | |
} | |
} | |
// store the start of a subpath | |
if (c == 'M' || c == 'm') { | |
x0 = x; | |
y0 = y; | |
} | |
} | |
path.setAttribute('d', path.getAttribute('d').replace(/z/g, 'Z')); | |
} | |
} |
#! /usr/bin/env phantomjs | |
// -*- js2 -*- | |
var webpage = require('webpage') | |
, URL; | |
; | |
if (phantom.args.length < 1 || phantom.args.length > 1) { | |
console.log('Usage: svg2rel source.svg'); | |
phantom.exit(); | |
} | |
else { | |
URL = phantom.args[0]; | |
load(URL, onload); | |
} | |
function load(url, fn) { | |
var page = webpage.create(); | |
page.onConsoleMessage = function(msg) { | |
console.log(msg); | |
}; | |
page.open(url, function (status) { | |
if (status !== 'success') | |
console.log('Unable to load ' + url); | |
else | |
fn(page); | |
}); | |
} | |
function onload(page) { | |
page.onConsoleMessage = function(msg) { | |
console.log(msg); | |
phantom.exit(); | |
}; | |
page.evaluate(onSVG); | |
} | |
function onSVG() { | |
var svg = document.documentElement | |
, all = [].slice.call(document.querySelectorAll('path'), 0); | |
all.forEach(convertToRelative); | |
console.log((new XMLSerializer).serializeToString(svg)); | |
// based on http://stackoverflow.com/a/9677915/1130377 | |
function convertToRelative(path) { | |
function set(type) { | |
var args = [].slice.call(arguments, 1) | |
, rcmd = 'createSVGPathSeg'+ type +'Rel' | |
, rseg = path[rcmd].apply(path, args); | |
segs.replaceItem(rseg, i); | |
} | |
var dx, dy, x0, y0, x1, y1, x2, y2, segs = path.pathSegList; | |
for (var x = 0, y = 0, i = 0, len = segs.numberOfItems; i < len; i++) { | |
var seg = segs.getItem(i) | |
, c = seg.pathSegTypeAsLetter; | |
if (/[MLHVCSQTAZz]/.test(c)) { | |
if ('x1' in seg) x1 = seg.x1 - x; | |
if ('x2' in seg) x2 = seg.x2 - x; | |
if ('y1' in seg) y1 = seg.y1 - y; | |
if ('y2' in seg) y2 = seg.y2 - y; | |
if ('x' in seg) dx = -x + (x = seg.x); | |
if ('y' in seg) dy = -y + (y = seg.y); | |
switch (c) { | |
case 'M': set('Moveto',dx,dy); break; | |
case 'L': set('Lineto',dx,dy); break; | |
case 'H': set('LinetoHorizontal',dx); break; | |
case 'V': set('LinetoVertical',dy); break; | |
case 'C': set('CurvetoCubic',dx,dy,x1,y1,x2,y2); break; | |
case 'S': set('CurvetoCubicSmooth',dx,dy,x2,y2); break; | |
case 'Q': set('CurvetoQuadratic',dx,dy,x1,y1); break; | |
case 'T': set('CurvetoQuadraticSmooth',dx,dy); break; | |
case 'A': set('Arc',dx,dy,seg.r1,seg.r2,seg.angle, | |
seg.largeArcFlag,seg.sweepFlag); break; | |
case 'Z': case 'z': x = x0; y = y0; break; | |
} | |
} | |
else { | |
if ('x' in seg) x += seg.x; | |
if ('y' in seg) y += seg.y; | |
} | |
// store the start of a subpath | |
if (c == 'M' || c == 'm') { | |
x0 = x; | |
y0 = y; | |
} | |
} | |
path.setAttribute('d', path.getAttribute('d').replace(/Z/g, 'z')); | |
} | |
} |