initial commit taken from gitlab.lrz.de

This commit is contained in:
privatereese
2018-08-24 18:09:42 +02:00
parent ae54ed4c48
commit fc05486403
28494 changed files with 2159823 additions and 0 deletions

158
node_modules/art/parsers/svg/colors.js generated vendored Normal file
View File

@@ -0,0 +1,158 @@
var SVGParser = require('./core');
var parseColor = SVGParser.prototype.parseColor,
namedColors = {
// Colors already in the Color class are commented out
aliceblue: '#f0f8ff',
antiquewhite: '#faebd7',
// aqua: '#00ffff',
aquamarine: '#7fffd4',
azure: '#f0ffff',
beige: '#f5f5dc',
bisque: '#ffe4c4',
// black: '#000000',
blanchedalmond: '#ffebcd',
// blue: '#0000ff',
blueviolet: '#8a2be2',
brown: '#a52a2a',
burlywood: '#deb887',
cadetblue: '#5f9ea0',
chartreuse: '#7fff00',
chocolate: '#d2691e',
coral: '#ff7f50',
cornflowerblue: '#6495ed',
cornsilk: '#fff8dc',
crimson: '#dc143c',
cyan: '#00ffff',
darkblue: '#00008b',
darkcyan: '#008b8b',
darkgoldenrod: '#b8860b',
darkgray: '#a9a9a9',
darkgreen: '#006400',
darkgrey: '#a9a9a9',
darkkhaki: '#bdb76b',
darkmagenta: '#8b008b',
darkolivegreen: '#556b2f',
darkorange: '#ff8c00',
darkorchid: '#9932cc',
darkred: '#8b0000',
darksalmon: '#e9967a',
darkseagreen: '#8fbc8f',
darkslateblue: '#483d8b',
darkslategray: '#2f4f4f',
darkslategrey: '#2f4f4f',
darkturquoise: '#00ced1',
darkviolet: '#9400d3',
deeppink: '#ff1493',
deepskyblue: '#00bfff',
dimgray: '#696969',
dimgrey: '#696969',
dodgerblue: '#1e90ff',
firebrick: '#b22222',
floralwhite: '#fffaf0',
forestgreen: '#228b22',
// fuchsia: '#ff00ff',
gainsboro: '#dcdcdc',
ghostwhite: '#f8f8ff',
gold: '#ffd700',
goldenrod: '#daa520',
// gray: '#808080',
// green: '#008000',
greenyellow: '#adff2f',
grey: '#808080',
honeydew: '#f0fff0',
hotpink: '#ff69b4',
indianred: '#cd5c5c',
indigo: '#4b0082',
ivory: '#fffff0',
khaki: '#f0e68c',
lavender: '#e6e6fa',
lavenderblush: '#fff0f5',
lawngreen: '#7cfc00',
lemonchiffon: '#fffacd',
lightblue: '#add8e6',
lightcoral: '#f08080',
lightcyan: '#e0ffff',
lightgoldenrodyellow: '#fafad2',
lightgray: '#d3d3d3',
lightgreen: '#90ee90',
lightgrey: '#d3d3d3',
lightpink: '#ffb6c1',
lightsalmon: '#ffa07a',
lightseagreen: '#20b2aa',
lightskyblue: '#87cefa',
lightslategray: '#778899',
lightslategrey: '#778899',
lightsteelblue: '#b0c4de',
lightyellow: '#ffffe0',
// lime: '#00ff00',
limegreen: '#32cd32',
linen: '#faf0e6',
magenta: '#ff00ff',
// maroon: '#800000',
mediumaquamarine: '#66cdaa',
mediumblue: '#0000cd',
mediumorchid: '#ba55d3',
mediumpurple: '#9370db',
mediumseagreen: '#3cb371',
mediumslateblue: '#7b68ee',
mediumspringgreen: '#00fa9a',
mediumturquoise: '#48d1cc',
mediumvioletred: '#c71585',
midnightblue: '#191970',
mintcream: '#f5fffa',
mistyrose: '#ffe4e1',
moccasin: '#ffe4b5',
navajowhite: '#ffdead',
// navy: '#000080',
oldlace: '#fdf5e6',
// olive: '#808000',
olivedrab: '#6b8e23',
// orange: '#ffa500',
orangered: '#ff4500',
orchid: '#da70d6',
palegoldenrod: '#eee8aa',
palegreen: '#98fb98',
paleturquoise: '#afeeee',
palevioletred: '#db7093',
papayawhip: '#ffefd5',
peachpuff: '#ffdab9',
peru: '#cd853f',
pink: '#ffc0cb',
plum: '#dda0dd',
powderblue: '#b0e0e6',
// purple: '#800080',
// red: '#ff0000',
rosybrown: '#bc8f8f',
royalblue: '#4169e1',
saddlebrown: '#8b4513',
salmon: '#fa8072',
sandybrown: '#f4a460',
seagreen: '#2e8b57',
seashell: '#fff5ee',
sienna: '#a0522d',
// silver: '#c0c0c0',
skyblue: '#87ceeb',
slateblue: '#6a5acd',
slategray: '#708090',
slategrey: '#708090',
snow: '#fffafa',
springgreen: '#00ff7f',
steelblue: '#4682b4',
tan: '#d2b48c',
// teal: '#008080',
thistle: '#d8bfd8',
tomato: '#ff6347',
turquoise: '#40e0d0',
violet: '#ee82ee',
wheat: '#f5deb3',
// white: '#ffffff',
whitesmoke: '#f5f5f5',
// yellow: '#ffff00',
yellowgreen: '#9acd32'
};
SVGParser.prototype.parseColor = function(value, opacity, styles){
if (value == 'currentColor') value = styles.color;
return parseColor.call(this, namedColors[value] || value, opacity, styles);
};

417
node_modules/art/parsers/svg/core.js generated vendored Normal file
View File

@@ -0,0 +1,417 @@
var Class = require('../../core/class');
var Color = require('../../core/color');
var Mode = require('../../modes/current');
var Rectangle = require('../../shapes/rectangle');
// Regular Expressions
var matchURL = /^\s*url\(["'\s]*([^\)]*?)["'\s]*\)/,
requiredNumber = '(?:\\s+|\\s*,\\s*)([^\\s,\\)]+)';
number = '(?:' + requiredNumber + ')?',
matchViewBox = new RegExp('^\\s*([^\\s,]+)' + requiredNumber + requiredNumber + requiredNumber),
matchUnit = /^\s*([\+\-\d\.]+(?:e\d+)?)(|px|em|ex|in|pt|pc|mm|cm|%)\s*$/i;
// Environment Settings
var dpi = 72, emToEx = 0.5;
var styleSheet = function(){},
defaultStyles = {
'viewportWidth': 500,
'viewportHeight': 500,
'font-family': 'Arial',
'font-size': 12,
'color': 'black',
'fill': 'black'
},
nonInheritedStyles = {
'stop-color': 'black',
'stop-opacity': 1,
'clip-path': null,
'filter': null,
'mask': null,
'opacity': 1,
'cursor': null
};
// Visitor
var SVGParser = Class({
initialize: function(mode){
this.MODE = mode;
},
// TODO Fix this silly API
parseAsSurface: function(element, styles){
return this.parse(element, styles, true);
},
parse: function(element, styles, asSurface){
if (typeof element == 'string') element = this.parseXML(element);
if (!styles)
styles = this.findStyles(element);
else
for (var style in defaultStyles)
if (!(style in styles))
styles[style] = defaultStyles[style];
if (element.documentElement || asSurface){
element = element.documentElement || element;
var canvas = new this.MODE.Surface(
this.parseLength(element.getAttribute('width') || '100%', styles, 'x'),
this.parseLength(element.getAttribute('height') || '100%', styles, 'y')
);
if (element.getAttribute('viewBox'))
canvas.grab(this.parse(element, styles));
else
this.container(element, this.parseStyles(element, styles), canvas);
return canvas;
}
if (element.nodeType != 1 || element.getAttribute('requiredExtensions') || element.getAttribute('systemLanguage') != null) return null;
styles = this.parseStyles(element, styles);
var parseFunction = this[element.nodeName + 'Element'];
return parseFunction ? parseFunction.call(this, element, styles) : null;
},
parseXML: window.DOMParser ? function(text){
return new DOMParser().parseFromString(text, 'text/xml');
} : function(text){
try {
var xml;
try { xml = new ActiveXObject('MSXML2.DOMDocument'); }
catch (e){ xml = new ActiveXObject('Microsoft.XMLDOM'); }
xml.resolveExternals = false;
xml.validateOnParse = false;
xml.async = false;
xml.preserveWhiteSpace = true;
xml.loadXML(text);
return xml;
} catch (e){
return null;
}
},
parseStyles: function(element, styles){
styleSheet.prototype = styles;
var newSheet = new styleSheet();
for (var key in nonInheritedStyles) newSheet[key] = nonInheritedStyles[key];
this.applyStyles(element, newSheet);
if (newSheet.hasOwnProperty('font-size')){
var newFontSize = this.parseLength(newSheet['font-size'], styles, 'font');
if (newFontSize != null) newSheet['font-size'] = newFontSize;
}
if (newSheet.hasOwnProperty('text-decoration')){
newSheet['text-decoration-color'] = newSheet.color;
}
return newSheet;
},
findStyles: function(element){
if (!element || element.nodeType != 1) return defaultStyles;
var styles = this.findStyles(element.parentNode);
return this.parseStyles(element, styles);
},
applyStyles: function(element, target){
var attributes = element.attributes;
for (var i = 0, l = attributes.length; i < l; i++){
var attribute = attributes[i],
name = attribute.nodeName,
value = attribute.nodeValue;
if (value != 'inherit'){
target[name] = value;
if (name == 'fill') target['fill_document'] = element.ownerDocument;
}
}
return target;
},
findById: function(document, id){
// if (document.getElementById) return document.getElementById(id); Not reliable
if (this.cacheDocument != document){
this.ids = {};
this.lastSweep = null;
this.cacheDocument = document;
}
var ids = this.ids;
if (ids[id] != null) return ids[id];
var root = document.documentElement, node = this.lastSweep || root;
treewalker: while (node){
if (node.nodeType == 1){
var newID = node.getAttribute('id') || node.getAttribute('xml:id');
if (newID && ids[newID] == null) ids[newID] = node;
if (newID == id){
this.lastSweep = node;
return node;
}
}
if (node.firstChild){
node = node.firstChild;
} else {
while (!node.nextSibling){
node = node.parentNode;
if (!node || node == root) break treewalker;
}
node = node.nextSibling;
}
}
return null;
},
findByURL: function(document, url, callback){
callback.call(this, url && url[0] == '#' ? this.findById(document, url.substr(1)) : null);
},
resolveURL: function(url){
return url;
},
parseLength: function(value, styles, dimension){
var match = matchUnit.exec(value);
if (!match) return null;
var result = parseFloat(match[1]);
switch(match[2]){
case '': case 'px': return result;
case 'em': return result * styles['font-size'];
case 'ex': return result * styles['font-size'] * emToEx;
case 'in': return result * dpi;
case 'pt': return result * dpi / 72;
case 'pc': return result * dpi / 6;
case 'mm': return result * dpi / 25.4;
case 'cm': return result * dpi / 2.54;
case '%':
var w = styles.viewportWidth, h = styles.viewportHeight;
if (dimension == 'font') return result * styles['font-size'] / 100;
if (dimension == 'x') return result * w / 100;
if (dimension == 'y') return result * h / 100;
return result * Math.sqrt(w * w + h * h) / Math.sqrt(2) / 100;
}
},
parseColor: function(value, opacity, styles){
if (value == 'currentColor') value = styles.color;
try {
var color = new Color(value);
} catch (x){
// Ignore unparsable colors, TODO: log
return null;
}
color.alpha = opacity == null ? 1 : +opacity;
return color;
},
getLengthAttribute: function(element, styles, attr, dimension){
return this.parseLength(element.getAttribute(attr) || 0, styles, dimension);
},
container: function(element, styles, container){
if (container.width != null) styles.viewportWidth = container.width;
if (container.height != null) styles.viewportHeight = container.height;
this.filter(styles, container);
this.describe(element, styles, container);
var node = element.firstChild;
while (node){
var art = this.parse(node, styles);
if (art) container.grab(art);
node = node.nextSibling;
}
return container;
},
shape: function(element, styles, target, x, y){
this.transform(element, target);
target.transform(1, 0, 0, 1, x, y);
this.fill(styles, target, x, y);
this.stroke(styles, target);
this.filter(styles, target);
if (styles.visibility == 'hidden') target.hide();
this.describe(element, styles, target);
return target;
},
fill: function(styles, target, x, y){
if (!styles.fill || styles.fill == 'none') return;
var match;
if (match = matchURL.exec(styles.fill)){
this.findByURL(styles.fill_document, match[1], function(fill){
var fillFunction = fill && this[fill.nodeName + 'Fill'];
if (fillFunction) fillFunction.call(this, fill, this.findStyles(fill), target, x, y);
});
} else {
target.fill(this.parseColor(styles.fill, styles['fill-opacity'], styles));
}
},
stroke: function(styles, target){
if (!styles.stroke || styles.stroke == 'none' || matchURL.test(styles.stroke)) return; // Advanced stroke colors are not supported, TODO: log
var color = this.parseColor(styles.stroke, styles['stroke-opacity'], styles),
width = this.parseLength(styles['stroke-width'], styles),
cap = styles['stroke-linecap'] || 'butt',
join = styles['stroke-linejoin'] || 'miter';
target.stroke(color, width == null ? 1 : width, cap, join);
},
filter: function(styles, target){
if (styles.opacity != 1 && target.blend) target.blend(styles.opacity);
if (styles.display == 'none') target.hide();
},
describe: function(element, styles, target){
var node = element.firstChild, title = '';
if (element.nodeName != 'svg')
while (node){
if (node.nodeName == 'title') title += node.firstChild && node.firstChild.nodeValue;
node = node.nextSibling;
}
if (styles.cursor || title) target.indicate(styles.cursor, title);
},
transform: function(element, target){
var transform = element.getAttribute('transform'), match;
var matchTransform = new RegExp('([a-z]+)\\s*\\(\\s*([^\\s,\\)]+)' + number + number + number + number + number + '\\s*\\)', 'gi');
while(match = transform && matchTransform.exec(transform)){
switch(match[1]){
case 'matrix':
target.transform(match[2], match[3], match[4], match[5], match[6], match[7]);
break;
case 'translate':
target.transform(1, 0, 0, 1, match[2], match[3]);
break;
case 'scale':
target.transform(match[2], 0, 0, match[3] || match[2]);
break;
case 'rotate':
var rad = match[2] * Math.PI / 180, cos = Math.cos(rad), sin = Math.sin(rad);
target.transform(1, 0, 0, 1, match[3], match[4])
.transform(cos, sin, -sin, cos)
.transform(1, 0, 0, 1, -match[3], -match[4]);
break;
case 'skewX':
target.transform(1, 0, Math.tan(match[2] * Math.PI / 180), 1);
break;
case 'skewY':
target.transform(1, Math.tan(match[2] * Math.PI / 180), 0, 1);
break;
}
}
},
svgElement: function(element, styles){
var viewbox = element.getAttribute('viewBox'),
match = matchViewBox.exec(viewbox),
x = this.getLengthAttribute(element, styles, 'x', 'x'),
y = this.getLengthAttribute(element, styles, 'y', 'y'),
width = this.getLengthAttribute(element, styles, 'width', 'x'),
height = this.getLengthAttribute(element, styles, 'height', 'y'),
group = match ? new this.MODE.Group(+match[3], +match[4]) : new this.MODE.Group(width || null, height || null);
if (width && height) group.resizeTo(width, height); // TODO: Aspect ratio
if (match) group.transform(1, 0, 0, 1, -match[1], -match[2]);
this.container(element, styles, group);
group.move(x, y);
return group;
},
gElement: function(element, styles){
var group = new this.MODE.Group();
this.transform(element, group);
this.container(element, styles, group);
return group;
},
useElement: function(element, styles){
var placeholder = new this.MODE.Group(),
x = this.getLengthAttribute(element, styles, 'x', 'x'),
y = this.getLengthAttribute(element, styles, 'y', 'y'),
width = this.getLengthAttribute(element, styles, 'width', 'x'),
height = this.getLengthAttribute(element, styles, 'height', 'y');
this.transform(element, placeholder);
placeholder.transform(1, 0, 0, 1, x, y);
this.findByURL(element.ownerDocument, element.getAttribute('xlink:href') || element.getAttribute('href'), function(target){
if (!target || target.nodeType != 1) return;
var parseFunction = target.nodeName == 'symbol' ? this.svgElement : this[target.nodeName + 'Element'];
if (!parseFunction) return;
styles = this.parseStyles(element, this.parseStyles(target, styles));
var symbol = parseFunction.call(this, target, styles);
if (!symbol) return;
if (width && height) symbol.resizeTo(width, height); // TODO: Aspect ratio, maybe resize the placeholder instead
placeholder.grab(symbol);
});
return placeholder;
},
switchElement: function(element, styles){
var node = element.firstChild;
while (node){
var art = this.parse(node, styles);
if (art) return art;
node = node.nextSibling;
}
return null;
},
aElement: function(element, styles){
// For now treat it like a group
return this.gElement(element, styles);
},
pathElement: function(element, styles){
var shape = new this.MODE.Shape(element.getAttribute('d') || null);
this.shape(element, styles, shape);
return shape;
},
imageElement: function(element, styles){
var href = this.resolveURL(element.getAttribute('xlink:href') || element.getAttribute('href')),
width = this.getLengthAttribute(element, styles, 'width', 'x'),
height = this.getLengthAttribute(element, styles, 'height', 'y'),
x = this.getLengthAttribute(element, styles, 'x', 'x'),
y = this.getLengthAttribute(element, styles, 'y', 'y'),
clipPath = element.getAttribute('clip-path'),
image,
match;
if (clipPath && (match = matchURL.exec(clipPath)) && match[1][0] == '#'){
var clip = this.findById(element.ownerDocument, match[1].substr(1));
if (clip){
image = this.switchElement(clip, styles);
if (image){
if (typeof image.fillImage == 'function'){
image.fillImage(href, width, height);
if (image.stroke) image.stroke(0);
} else {
image = null;
}
}
}
}
if (!image){
//image = new Image(href, width, height); TODO
image = new Rectangle(width, height).fillImage(href, width, height);
}
this.filter(styles, image);
if (styles.visibility == 'hidden') target.hide();
this.describe(element, styles, image);
this.transform(element, image);
image.transform(1, 0, 0, 1, x, y);
return image;
}
});
SVGParser.parse = function(element, styles){
return new SVGParser(Mode).parse(element, styles);
};
SVGParser.implement = function(obj){
for (var key in obj)
this.prototype[key] = obj[key];
};
module.exports = SVGParser;

73
node_modules/art/parsers/svg/externals.js generated vendored Normal file
View File

@@ -0,0 +1,73 @@
var SVGParser = require('./core');
var Mode = require('../../modes/current');
var urlSuffix = '', baseUrl, urlAliases = {},
urlParts = /^((?:\w+:)?(?:\/\/[^\/?#]*)?)(\.\.?$|(?:[^?#\/]*\/)*)(.*)/,
endSlash = /\/$/;
function resolvePath(path, base){
var parts = String(path).match(urlParts);
if (!parts || parts[1]) return path;
if (!base || path.charAt(0) !== '.') base = '';
base = String(base).match(urlParts);
var directory = parts[2];
if (directory.charAt(0) != '/'){
directory = (base[2] || '') + directory;
var result = [], paths = directory.replace(endSlash, '').split('/');
for (var i = 0, l = paths.length; i < l; i++){
var dir = paths[i];
if (dir === '..' && result.length > 0 && result[result.length - 1] != '..') result.pop();
else if (dir !== '.') result.push(dir);
};
directory = result.join('/') + '/';
}
return base[1] + directory + parts[3];
}
SVGParser.prototype.findByURL = function(document, url, callback){
if (!url){
callback.call(this, null);
return;
}
if (url.charAt(0) == '#'){
callback.call(this, this.findById(document, url.substr(1)));
return;
}
url = this.resolveURL(url);
var self = this, i = url.indexOf('#'), id = i > -1 ? url.substr(i + 1) : null;
if (i > -1) url = url.substr(0, i);
this.pendingRequests = (this.pendingRequests || 0) + 1;
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){
if (xhr.status == 200){
var resolve = self.resolveURL,
doc = /*xhr.responseXML ||*/ self.parseXML(xhr.responseText);
self.resolveURL = function(newurl){
return resolvePath(newurl, url);
}
callback.call(self, !doc ? null : id ? self.findById(doc, id) : doc.documentElement);
self.resolveURL = resolve;
} else {
callback.call(self, null);
}
if (--self.pendingRequests == 0 && self.oncomplete) self.oncomplete();
}
};
xhr.send(null);
};
SVGParser.prototype.load = function(url, styles, callback){
if (typeof styles == 'function'){ callback = styles; styles = null; }
var parser = this, result = null;
parser.oncomplete = function(){ callback(result); };
parser.findByURL(null, url, function(doc){ result = parser.parse(doc.ownerDocument, styles); });
};
SVGParser.load = function(url, styles, callback){
new SVGParser(Mode).load(url, styles, callback);
};

203
node_modules/art/parsers/svg/fonts.js generated vendored Normal file
View File

@@ -0,0 +1,203 @@
var Class = require('../../core/class');
var Path = require('../../core/path');
var SVGParser = require('./core');
var Font = require('../../shapes/font');
var parse = SVGParser.prototype.parse;
var matchFontURL = /url\(['"\s]*([^\)]*?)['"\s]*\)\s+format\(['"]?svg['"]?\)/i;
var trimFontFamily = /^['"\s]+|['"\s]+$|,.*$/g;
var fillFaceAttributes = function(element, face){
var attributes = element.attributes;
for (var i = 0, l = attributes.length; i < l; i++){
var attribute = attributes[i];
if (!(attribute.nodeName in face)){
face[attribute.nodeName] = attribute.nodeValue;
}
}
};
SVGParser.implement({
parse: function(element, styles){
if (element.documentElement && element != this.fontDocument){
this.fontDocument = element;
this.findFonts(element);
}
return parse.apply(this, arguments);
},
findFonts: function(document){
var fonts = this.fonts || (this.fonts = {});
var root = document.documentElement, node = root;
treewalker: while (node){
if (node.nodeType == 1 && node.nodeName == 'font-face'){
this.fontFace(node);
}
if (node.firstChild){
node = node.firstChild;
} else {
while (!node.nextSibling){
node = node.parentNode;
if (!node || node == root) break treewalker;
}
node = node.nextSibling;
}
}
if (this.findCSS){
var rules = this.findCSS(document).cssRules;
for (var i = 0, l = rules.length; i < l; i++){
var rule = rules[i];
if (rule.fontFace){
var url = matchFontURL.exec(rule.style.src);
if (url) this.fontURL(document, url[1], rule.style);
}
}
}
},
fontFace: function(element){
var face = {};
fillFaceAttributes(element, face);
if (element.parentNode.nodeName == 'font') this.font(element.parentNode, face);
var node = element.firstChild;
while (node){
if (node.nodeName == 'font-face-src'){
node = node.firstChild;
continue;
}
if (node.nodeName == 'font-face-uri'){
var url = node.getAttribute('xlink:href');
this.fontURL(element.ownerDocument, url, face);
}
node = node.nextSibling;
}
},
fontURL: function(document, url, face){
if (!face['font-family']) return;
var pendingFonts = this.pendingFonts || (this.pendingFonts = {});
var family = face['font-family'].replace(trimFontFamily, '');
var callbacks = pendingFonts[family] = [];
this.findByURL(document, url, function(font){
delete pendingFonts[family];
if (font){
var f = this.font(font, face);
for (var i = 0, l = callbacks.length; i < l; i++)
callbacks[i].call(this, f);
}
});
},
findFont: function(styles, callback){
var family = styles['font-family'].replace(trimFontFamily, '');
var callbacks = this.pendingFonts && this.pendingFonts[family];
if (callbacks){
callbacks.push(callback);
} else if (this.fonts){
callback.call(this, this.fonts[family]);
} else {
callback.call(this, null);
}
},
font: function(element, face){
var glyphs = {}, font = { face: face, glyphs: glyphs };
var w = element.getAttribute('horiz-adv-x');
if (w) font.w = parseInt(w, 10);
var node = element.firstChild;
while (node){
switch(node.nodeName){
case 'font-face':
fillFaceAttributes(node, face);
break;
case 'missing-glyph':
case 'glyph':
var glyph = {},
code = node.nodeName == 'missing-glyph' ? 'missing' : node.getAttribute('unicode'),
w = node.getAttribute('horiz-adv-x'),
d = node.getAttribute('d');
if (!code) break;
if (w) glyph.w = parseInt(w, 10);
if (d){
// Flip path
var path = new FlippedVMLPathAtNormalPrecision(d);
glyph.d = path.toVML().substr(1);
}
glyphs[code] = glyph;
break;
// TODO: Kerning
}
node = node.nextSibling;
}
var units = face['units-per-em'];
if (isNaN(units)) face['units-per-em'] = units = 1000;
if (face.ascent == null) face.ascent = face.descent == null ? 0.8 * units : units - face.descent;
if (face.descent == null) face.descent = face.ascent - units;
var family = face['font-family'];
if (!family) return;
face['font-family'] = family = family.replace(trimFontFamily, '');
var fonts = this.fonts || (this.fonts = {});
if (face.ascent) face.ascent = +face.ascent;
if (face.descent) face.descent = +face.descent;
fonts[family] = font;
if (this.MODE.Font)
this.MODE.Font.register(font);
else
Font.register(font);
return font;
}
});
var round = Math.round;
var FlippedVMLPathAtNormalPrecision = Class(Path, {
initialize: function(path){
this.reset();
if (path){
this.push(path);
}
},
onReset: function(){
this.path = [];
},
onMove: function(sx, sy, x, y){
this.path.push('m', round(x), -round(y));
},
onLine: function(sx, sy, x, y){
this.path.push('l', round(x), -round(y));
},
onBezierCurve: function(sx, sy, p1x, p1y, p2x, p2y, x, y){
this.path.push('c',
round(p1x), -round(p1y),
round(p2x), -round(p2y),
round(x), -round(y)
);
},
onClose: function(){
this.path.push('x');
},
toVML: function(){
return this.path.join(' ');
}
});

5
node_modules/art/parsers/svg/markers.js generated vendored Normal file
View File

@@ -0,0 +1,5 @@
var SVGParser = require('./core');
SVGParser.prototype.markerElement = function(){
// TODO
};

150
node_modules/art/parsers/svg/paints.js generated vendored Normal file
View File

@@ -0,0 +1,150 @@
var SVGParser = require('./core');
SVGParser.implement({
findLinkedAttributes: function(element, callback){
var self = this;
var cb = function(result){
var attributes = element.attributes;
for (var i = 0, l = attributes.length; i < l; i++){
var attribute = attributes[i];
result[attribute.nodeName] = attribute.nodeValue;
}
if (element.childNodes.length > 0) result.container = element;
callback.call(self, result);
};
var href = element.getAttribute('xlink:href') || element.getAttribute('href');
if (!href){ cb.call(this, {}); return; }
this.findByURL(element.ownerDocument, href, function(parent){
if (!parent) cb.call(this, {});
else this.findLinkedAttributes(parent, function(parentResult){
cb.call(this, parentResult);
});
});
},
getBBox: function(graphic){
var path = graphic.getPath && graphic.getPath();
return path ? path.measure() : graphic;
},
parseBBLength: function(value, bbox, dimension){
value = /%/.test(value) ? parseFloat(value) / 100 : parseFloat(value);
if (dimension == 'x') return (bbox.left || 0) + (bbox.width || 0) * value;
if (dimension == 'y') return (bbox.top || 0) + (bbox.height || 0) * value;
},
getGradientStops: function(element, styles){
var stops = null, node = element.firstChild;
while (node){
if (node.nodeName == 'stop'){
var stopStyles = this.parseStyles(node, styles);
var color = this.parseColor(stopStyles['stop-color'] || 'black', stopStyles['stop-opacity'], stopStyles),
offset = node.getAttribute('offset');
if (color && offset){
offset = /%/.test(offset) ? parseFloat(offset) / 100 : parseFloat(offset);
if (offset < 0) offset = 0;
if (offset > 1) offset = 1;
if (!stops) stops = {};
stops[offset.toFixed(4)] = color;
}
}
node = node.nextSibling;
}
return stops;
},
radialGradientFill: function(element, styles, target, x, y){
this.findLinkedAttributes(element, function(attrs){
if (!attrs.container) return;
var stops = this.getGradientStops(attrs.container, styles);
if (!stops) return;
// TODO: Transform
var cx = attrs.cx || '50%',
cy = attrs.cy || '50%',
rx = attrs.r || '50%', ry,
fx = attrs.fx || cx,
fy = attrs.fy || cy;
if (attrs['gradientUnits'] == 'userSpaceOnUse'){
cx = this.parseLength(cx, styles, 'x') - x;
cy = this.parseLength(cy, styles, 'y') - y;
rx = ry = this.parseLength(rx, styles);
fx = this.parseLength(fx, styles, 'x') - x;
fy = this.parseLength(fy, styles, 'y') - y;
} else {
var bb = this.getBBox(target);
cx = this.parseBBLength(cx, bb, 'x');
cy = this.parseBBLength(cy, bb, 'y');
rx = this.parseBBLength(rx, bb, 'x');
ry = rx * (bb.height / bb.width);
fx = this.parseBBLength(fx, bb, 'x');
fy = this.parseBBLength(fy, bb, 'y');
}
target.fillRadial(stops, fx, fy, rx, ry, cx, cy);
});
},
linearGradientFill: function(element, styles, target, x, y){
this.findLinkedAttributes(element, function(attrs){
if (!attrs.container) return;
var stops = this.getGradientStops(attrs.container, styles);
if (!stops) return;
var x1 = attrs.x1 || 0,
y1 = attrs.y1 || 0,
x2 = attrs.x2 || '100%',
y2 = attrs.y2 || 0;
// TODO: Transform
if (attrs['gradientUnits'] == 'userSpaceOnUse'){
x1 = this.parseLength(x1, styles, 'x') - x;
y1 = this.parseLength(y1, styles, 'y') - y;
x2 = this.parseLength(x2, styles, 'x') - x;
y2 = this.parseLength(y2, styles, 'y') - y;
} else {
x1 = /%/.test(x1) ? parseFloat(x1) / 100 : parseFloat(x1);
y1 = /%/.test(y1) ? parseFloat(y1) / 100 : parseFloat(y1);
x2 = /%/.test(x2) ? parseFloat(x2) / 100 : parseFloat(x2);
y2 = /%/.test(y2) ? parseFloat(y2) / 100 : parseFloat(y2);
// If both points are close to the opposite edges, use rotation angle instead
var closeToEdge =
(x1 > -0.01 && x1 < 0.01 && x2 > 0.99 && x2 < 1.01) ||
(x1 > 0.99 && x1 < 1.01 && x2 > -0.01 && x2 < 0.01) ||
(y1 > -0.01 && y1 < 0.01 && y2 > 0.99 && y2 < 1.01) ||
(y1 > 0.99 && y1 < 1.01 && y2 > -0.01 && y2 < 0.01);
if (closeToEdge){
var angle = Math.atan2(y1 - y2, x2 - x1) * 180 / Math.PI;
target.fillLinear(stops, angle);
return;
}
// TODO: Always use rotation angle, but offset stops instead to adjust
// TODO2: Never use rotation angle because measuring is deprecated
var bb = this.getBBox(target);
x1 = this.parseBBLength(x1, bb, 'x');
y1 = this.parseBBLength(y1, bb, 'y');
x2 = this.parseBBLength(x2, bb, 'x');
y2 = this.parseBBLength(y2, bb, 'y');
}
target.fillLinear(stops, x1, y1, x2, y2);
});
},
patternFill: function(element, styles, target, x, y){
// TODO: If the pattern is an image, fillImage
}
});

94
node_modules/art/parsers/svg/shapes.js generated vendored Normal file
View File

@@ -0,0 +1,94 @@
var SVGParser = require('./core');
var Rectangle = require('../../shapes/rectangle');
var Ellipse = require('../../shapes/ellipse');
SVGParser.implement({
rectElement: function(element, styles){
var x = this.getLengthAttribute(element, styles, 'x', 'x'),
y = this.getLengthAttribute(element, styles, 'y', 'y'),
w = +this.getLengthAttribute(element, styles, 'width', 'x'),
h = +this.getLengthAttribute(element, styles, 'height', 'y'),
rx = this.getLengthAttribute(element, styles, 'rx', 'x'),
ry = this.getLengthAttribute(element, styles, 'ry', 'y'),
shape;
if (!w || !h) return null;
if (rx > w / 2) rx = w / 2;
if (ry > h / 2) ry = h / 2;
if (rx && ry && rx != ry){
shape = new this.MODE.Shape(
new this.MODE.Path()
.move(0, ry)
.arc(rx, -ry)
.line(w - rx - rx, 0)
.arc(rx, ry)
.line(0, h - ry - ry)
.arc(-rx, ry)
.line(-w + rx + rx, 0)
.arc(-rx, -ry)
.line(0, -h + ry + ry)
);
} else {
shape = new Rectangle(w, h, rx || ry);
}
this.shape(element, styles, shape, x, y);
return shape;
},
circleElement: function(element, styles){
var x = this.getLengthAttribute(element, styles, 'cx', 'x'),
y = this.getLengthAttribute(element, styles, 'cy', 'y'),
r = this.getLengthAttribute(element, styles, 'r'),
shape = new Ellipse(r * 2, r * 2);
if (r == 0) return null;
this.shape(element, styles, shape, x - r, y - r);
return shape;
},
ellipseElement: function(element, styles){
var x = this.getLengthAttribute(element, styles, 'cx', 'x'),
y = this.getLengthAttribute(element, styles, 'cy', 'y'),
rx = this.getLengthAttribute(element, styles, 'rx', 'x'),
ry = this.getLengthAttribute(element, styles, 'ry', 'y'),
shape = ry != 0 ? new Ellipse(rx * 2, ry * 2) : new this.MODE.Shape();
if (rx == 0 || ry == 0) return null;
this.shape(element, styles, shape, x - rx, y - ry);
return shape;
},
lineElement: function(element, styles){
var x1 = this.getLengthAttribute(element, styles, 'x1', 'x'),
y1 = this.getLengthAttribute(element, styles, 'y1', 'y'),
x2 = this.getLengthAttribute(element, styles, 'x2', 'x'),
y2 = this.getLengthAttribute(element, styles, 'y2', 'y'),
shape = new this.MODE.Shape(new this.MODE.Path().moveTo(x1, y1).lineTo(x2, y2));
if (x1 == x2 && y1 == y2) return null;
this.shape(element, styles, shape);
return shape;
},
parsePolypath: function(points){
if (!points) return new this.MODE.Path();
var pointMatcher = /([\-+]?(?:[\d\.]e[\-+]?|[^\s\-+,a-z])+)[\s\,]+([\-+]?(?:[\d\.]e[\-+]?|[^\s\-+,a-z])+)/ig,
first = true;
return new this.MODE.Path(points.replace(pointMatcher, function(match){
if (first){ first = false; return 'M' + match; }
return 'L' + match;
}));
},
polygonElement: function(element, styles){
var path = this.parsePolypath(element.getAttribute('points')),
shape = new this.MODE.Shape(path.close());
this.shape(element, styles, shape);
return shape;
},
polylineElement: function(element, styles){
var path = this.parsePolypath(element.getAttribute('points')),
shape = new this.MODE.Shape(path);
this.shape(element, styles, shape);
return shape;
}
});

32
node_modules/art/parsers/svg/styles.js generated vendored Normal file
View File

@@ -0,0 +1,32 @@
var SVGParser = require('./core');
var Slick = require('../../lib/slick/Source/slick').Slick;
var SheetCascade = require('../../lib/Sheet.Cascade').SheetCascade;
var applyStyles = SVGParser.prototype.applyStyles;
SVGParser.implement({
applyStyles: function(element, target){
this.findCSS(element.ownerDocument).applyStyle(element, target);
for (var key in target)
if (target.hasOwnProperty(key) && target[key] == 'inherit')
delete target[key];
if (target.hasOwnProperty('fill')) target['fill_document'] = element.ownerDocument;
applyStyles.call(this, element, target);
},
findCSS: function(document){
if (this.cssDocument != document){
this.cssDocument = document;
var css = this.css = new SheetCascade();
var sheets = Slick.search(document, 'style');
for (var i = 0, l = sheets.length; i < l; i++){
css.addSheet(sheets[i]);
}
return css;
} else {
return this.css;
}
}
});

219
node_modules/art/parsers/svg/text.js generated vendored Normal file
View File

@@ -0,0 +1,219 @@
var SVGParser = require('./core');
var Font = require('../../shapes/font');
function fontStyles(styles){
var font = {}, isFontStyle = /^(font|text-d|kerning|letter|word)[^\_]*$/;
for (var style in styles)
if (isFontStyle.test(style))
font[style] = styles[style] + (style == 'font-size' ? 'px' : '');
// Iffy
font['font-weight'] = (font['font-weight'] > 500 || font['font-weight'] == 'bold' || font['font-weight'] == 'bolder') ? 'bold' : 'normal';
font['font-style'] = font['font-style'] == 'oblique' || font['font-style'] == 'italic' ? 'italic' : 'normal';
return font;
};
function progressRow(row, element, styles){
var nx = element.getAttribute('x'),
ny = element.getAttribute('y'),
dx = element.getAttribute('dx'),
dy = element.getAttribute('dy');
var newRow = (nx != null && nx != '') || (ny != null && ny != '');
if (newRow){
adjustRow(row);
row = [];
row.anchor = styles['text-anchor'];
row.x = row.y = 0;
}
if (dx) row.x += this.parseLength(dx.split(/[\s\,]+/)[0], styles, 'x');
if (dy) row.y += this.parseLength(dy.split(/[\s\,]+/)[0], styles, 'y');
if (nx != null && nx != '') row.x = this.parseLength(nx.split(/[\s\,]+/)[0], styles, 'x');
if (ny != null && ny != '') row.y = this.parseLength(ny.split(/[\s\,]+/)[0], styles, 'y');
if (newRow) row.ix = row.x;
return row;
};
function adjustRow(row){
var adjustment = row.anchor == 'end' ? (row.ix - row.x) : row.anchor == 'middle' ? (row.ix - row.x) / 2 : 0;
if (adjustment)
for (var i = 0, l = row.length; i < l; i++)
row[i].transform(1,0,0,1,adjustment,0);
}
SVGParser.implement({
textElement: function(element, styles){
var group = new this.MODE.Group();
this.transform(element, group);
this.filter(styles, group);
var row = [];
row.ix = row.x = row.y = 0;
row.anchor = styles['text-anchor'];
this.tspanText(element, styles, row, group, adjustRow);
return group;
},
tspanText: function(element, styles, row, target, continuation){
row = progressRow.call(this, row, element, styles);
var node = element.firstChild;
var self = this;
var next = function(row){
if (node.nodeType == 3){
var text = self.textContent(node, styles);
node = node.nextSibling;
self.createText(text, styles, row, target, null, function(shape){
if (shape){
if (shape.width) row.x += shape.width + (shape.left || 0); // TODO: Adjust for rotated text
row.push(shape);
}
if (node) next(row); else continuation(row);
});
} else {
var parseFn = self[node.nodeName + 'Text'];
var current = node;
node = node.nextSibling;
if (parseFn) return parseFn.call(self, current, self.parseStyles(current, styles), row, target, node ? next : continuation);
if (node) next(row); else continuation(row);
}
};
if (node) next(row); else continuation(row);
},
aText: function(){
return this.tspanText.apply(this, arguments);
},
textPathText: function(element, styles, row, target, continuation){
this.findByURL(element.ownerDocument, element.getAttribute('xlink:href') || element.getAttribute('href'), function(path){
if (!path || !(path = path.getAttribute('d'))) return;
var text = this.elementTextContent(element, styles);
this.createText(text, styles, null, target, path, function(){
continuation(row);
});
});
},
trefText: function(element, styles, row, target, continuation){
row = progressRow.call(this, row, element, styles);
this.findByURL(element.ownerDocument, element.getAttribute('xlink:href') || element.getAttribute('href'), function(ref){
if (!ref) return continuation(row);
var text = this.elementTextContent(ref, styles);
this.createText(text, styles, row, target, null, function(shape){
if (shape){
if (shape.width) row.x += shape.width + (shape.left || 0); // TODO: Adjust for rotated text
row.push(shape);
}
continuation(row);
});
});
},
createText: function(text, styles, row, target, path, continuation){
var fontstyle = fontStyles(styles);
var create = function(font){
if (font){
var face = font.face;
fontstyle = {
fontFamily: font.face['font-family'],
fontSize: fontstyle['font-size']
};
if (face['font-weight'] > 500) fontstyle.fontWeight = face['font-weight'];
if (face['font-stretch'] == 'oblique' || face['font-style'] == 'oblique' || face['font-style'] == 'italic') fontstyle.fontStyle = 'italic';
};
var Text = font ? (this.MODE.Font || Font) : this.MODE.Text;
if (row){
var pad = row.pad || '';
row.pad = (/[\s\xA0]*$/).exec(text)[0];
if (row.length == 0) text = text.replace(/^\s+/, '');
text = pad + text.replace(/\s+$/, '');
} else {
text = text.replace(/^\s+|\s+$/g, '');
}
if (text == ''){
if (row && row.length == 0) row.pad = '';
continuation();
return;
}
var x = path ? 0 : row.x, y = path ? 0 : row.y - this.getBaseline(styles);
var shape = new Text(text, fontstyle, 'start', path);
shape.transform(1, 0, 0, 1, x, y);
this.fill(styles, shape, x, y);
this.stroke(styles, shape);
this.filter(styles, shape);
shape.inject(target);
continuation(shape);
}
if (this.findFont)
this.findFont(fontstyle, create);
else
create.call(this);
},
elementTextContent: function(element, styles){
var node = element.firstChild, text = '';
treewalker: while (node){
if (node.nodeType == 3){
text += this.textContent(node, styles);
}
if (node.firstChild){
node = node.firstChild;
} else {
while (!node.nextSibling){
node = node.parentNode;
if (!node || node == element) break treewalker;
}
node = node.nextSibling;
}
}
return text;
},
textContent: function(node, styles){
var value = node.nodeValue;
if (styles['xml:space'] == 'preserve'){
value = value.replace(/\t|\r?\n/g, ' ');
} else {
value = value.replace(/\r?\n/g, '').replace(/\s+/g, ' ');
}
return value; //.replace(/^\s+|\s+$/g, '');
},
getBaseline: function(styles){
var metrics = this.getTextMetrics(styles),
shift = styles['baseline-shift'];
if (shift == 'baseline') shift = '0';
else if (shift== 'sub') shift = '-0.5em';
else if (shift == 'super') shift = '0.5em';
shift = this.parseLength(shift, styles, 'font');
return metrics.em + metrics.descent + shift;
},
getTextMetrics: function(styles){
var fontFamily = styles['font-family'],
weight = styles['font-weight'],
style = styles['font-style'],
size = styles['font-size'],
font = this.fonts && this.fonts[fontFamily.replace(/^['"\s]+|['"\s]+$/, '')];
if (font) return { em: size, descent: -(1- font.face.ascent / font.face['units-per-em']) * size };
// TODO: Use cross-platform hack to get native font descent
return { em: size, ascent: 0.85 * size, descent: -0.15 * size }; // Good guess for web safe fonts
}
});