GT2/GT2-Android/node_modules/art/modes/svg/text.js

202 lines
5.4 KiB
JavaScript

var Class = require('../../core/class');
var Path = require('./path');
var Base = require('./base');
var Surface = require('./surface');
var DOM = require('./dom');
var createElement = DOM.createElement;
var ua = typeof navigator !== 'undefined' && navigator && navigator.userAgent,
hasBaseline = !(/opera|safari|ie/i).test(ua) || (/chrome/i).test(ua);
var fontAnchors = { left: 'start', center: 'middle', right: 'end' },
fontAnchorOffsets = { middle: '50%', end: '100%' };
module.exports = Class(Base, {
base_initialize: Base.prototype.initialize,
initialize: function(text, font, alignment, path){
this.base_initialize('text');
this.draw.apply(this, arguments);
},
draw: function(text, font, alignment, path){
var element = this.element;
if (font){
if (typeof font == 'string'){
element.style.font = font;
} else {
for (var key in font){
var ckey = key.camelCase ? key.camelCase() : key;
// NOT UNIVERSALLY SUPPORTED OPTIONS
// if (ckey == 'kerning') element.setAttribute('kerning', font[key] ? 'auto' : '0');
// else if (ckey == 'letterSpacing') element.setAttribute('letter-spacing', Number(font[key]) + 'ex');
// else if (ckey == 'rotateGlyphs') element.setAttribute('glyph-orientation-horizontal', font[key] ? '270deg' : '');
// else
element.style[ckey] = font[key];
}
element.style.lineHeight = '0.5em';
}
}
if (alignment) element.setAttribute('text-anchor', this.textAnchor = (fontAnchors[alignment] || alignment));
if (path && typeof path != 'number'){
this._createPaths(new Path(path));
} else if (path === false){
this._ejectPaths();
this.pathElements = null;
}
var paths = this.pathElements, child;
while ((child = element.firstChild)){
element.removeChild(child);
}
// Note: Gecko will (incorrectly) align gradients for each row, while others applies one for the entire element
var lines = String(text).split(/\r?\n/), l = lines.length,
baseline = 'central';
if (paths && l > paths.length) l = paths.length;
if (hasBaseline) element.setAttribute('dominant-baseline', baseline);
DOM.preserveSpace(element);
for (var i = 0; i < l; i++){
var line = lines[i], row, content;
if (paths){
row = createElement('textPath');
DOM.link(row, '#' + paths[i].getAttribute('id'));
row.setAttribute('startOffset', fontAnchorOffsets[this.textAnchor] || 0);
} else {
row = createElement('tspan');
row.setAttribute('x', 0);
row.setAttribute('y', (i * 1.1 + 0.5) + 'em');
}
if (hasBaseline){
row.setAttribute('dominant-baseline', baseline);
content = row;
} else if (paths){
content = createElement('tspan');
content.setAttribute('dy', '0.35em');
row.appendChild(content);
} else {
content = row;
row.setAttribute('y', (i * 1.1 + 0.85) + 'em');
}
DOM.preserveSpace(content);
content.appendChild(DOM.createTextNode(line));
element.appendChild(row);
}
// Measure
// TODO: Move to lazy ES5 left/top/width/height/bottom/right property getters
var bb;
try { bb = element.getBBox(); } catch (x){ }
if (!bb || !bb.width) bb = this._whileInDocument(element.getBBox, element);
this.left = bb.x;
this.top = bb.y;
this.width = bb.width;
this.height = bb.height;
this.right = bb.x + bb.width;
this.bottom = bb.y + bb.height;
return this;
},
// TODO: Unify path injection with gradients and imagefills
base_place: Base.prototype._place,
_place: function(){
if (this.parentNode){
this._injectPaths();
} else {
this._ejectPaths();
}
return this.base_place();
},
_injectPaths: function(){
var paths = this.pathElements;
if (!this.parentNode || !paths) return;
var defs = this.parentNode.defs;
for (var i = 0, l = paths.length; i < l; i++)
defs.appendChild(paths[i]);
},
_ejectPaths: function(){
var paths = this.pathElements;
if (!paths) return;
for (var i = 0, l = paths; i < l; i++){
var path = paths[i];
if (path.parentNode)
path.parentNode.removeChild(paths[i]);
}
},
_createPaths: function(path){
this._ejectPaths();
var id = 'p' + DOM.uniqueID() + '-';
//splitPaths = []; splitPath = ['M', 0, 0];
//path.visit(splitLine, splitCurve, null, splitMove);
//splitPaths.push(splitPath);
var splitPaths = [path.path];
var result = [];
for (var i = 0, l = splitPaths.length; i < l; i++){
var p = createElement('path');
p.setAttribute('d', splitPaths[i].join(' '));
p.setAttribute('id', id + i);
result.push(p);
}
this.pathElements = result;
this._injectPaths();
},
_whileInDocument: function(fn, bind){
// Temporarily inject into the document
var element = this.element,
container = this.parentNode,
parent = element.parentNode,
sibling = element.nextSibling,
body = element.ownerDocument.body,
canvas = new Surface(1, 1).inject(body);
this.inject(canvas);
var result = fn.call(bind);
canvas.eject();
if (container) this.inject(container);
if (parent) parent.insertBefore(element, sibling);
return result;
}
});
/* split each continuous line into individual paths */
/*
var pathSplitter = new CorePath();
pathSplitter.splitPaths = [];
var PathPerRow = Class(CorePath, {
function splitMove(sx, sy, x, y){
if (splitPath.length > 3) splitPaths.push(splitPath);
splitPath = ['M', x, y];
};
function splitLine(sx, sy, x, y){
splitPath.push('L', x, y);
};
function splitCurve(sx, sy, p1x, p1y, p2x, p2y, x, y){
splitPath.push('C', p1x, p1y, p2x, p2y, x, y);
};
});*/