2018-07-23 11:12:06 +00:00
|
|
|
import attributes from './attributes'
|
|
|
|
import * as hooklib from 'hooks'
|
|
|
|
import hooks from './hooks'
|
|
|
|
|
|
|
|
function svg (pattern)
|
|
|
|
{
|
|
|
|
this.body = '';
|
|
|
|
this.style = '';
|
|
|
|
this.script = '';
|
|
|
|
this.header = '';
|
|
|
|
this.footer = '';
|
|
|
|
this.defs = '';
|
|
|
|
this.pattern = pattern; // Needed to expose pattern to hooks
|
|
|
|
this.prefix = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>';
|
|
|
|
this.attributes = new attributes();
|
|
|
|
this.attributes.add("xmlns", "http://www.w3.org/2000/svg");
|
|
|
|
this.attributes.add("xmlns:svg", "http://www.w3.org/2000/svg");
|
|
|
|
this.attributes.add("xmlns:xlink", "http://www.w3.org/1999/xlink");
|
|
|
|
this.hooks = hooks.all;
|
|
|
|
for(let k in hooklib) this[k] = hooklib[k];
|
|
|
|
for(let k in this.hooks) this.hook(k, this[k]);
|
|
|
|
|
|
|
|
return this;
|
2018-07-14 16:04:39 +00:00
|
|
|
|
2018-07-18 11:45:46 +00:00
|
|
|
/** Method to attach preRenderSvg hooks on */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.preRenderSvg = function() {};
|
2018-07-18 07:39:29 +00:00
|
|
|
|
2018-07-18 11:45:46 +00:00
|
|
|
/** Method to attach postRenderSvg hooks on */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.postRenderSvg = function() {};
|
|
|
|
|
|
|
|
/** Method to attach insertText hooks on */
|
|
|
|
this.prototype.insertText = function() {};
|
2018-07-17 14:16:17 +00:00
|
|
|
|
2018-07-14 16:04:39 +00:00
|
|
|
/** Renders a draft object as SVG */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.render = function (pattern)
|
|
|
|
{
|
2018-07-18 11:45:46 +00:00
|
|
|
this.preRenderSvg();
|
2018-07-18 07:39:29 +00:00
|
|
|
this.svg = this.prefix;
|
|
|
|
this.svg += this.renderComments(this.header);
|
|
|
|
this.svg += this.renderSvgTag(pattern);
|
|
|
|
this.svg += this.renderStyle();
|
|
|
|
this.svg += this.renderScript();
|
|
|
|
this.svg += this.renderDefs();
|
|
|
|
this.svg += this.openGroup('draftContainer');
|
2018-07-14 16:04:39 +00:00
|
|
|
for (let partId in pattern.parts) {
|
|
|
|
let part = pattern.parts[partId];
|
|
|
|
if (part.render) {
|
2018-07-18 07:39:29 +00:00
|
|
|
this.svg += this.openGroup(part.id, part.attributes);
|
|
|
|
this.svg += this.renderPart(part);
|
|
|
|
this.svg += this.closeGroup();
|
2018-07-14 16:04:39 +00:00
|
|
|
}
|
|
|
|
}
|
2018-07-18 07:39:29 +00:00
|
|
|
this.svg += this.closeGroup();
|
|
|
|
this.svg += this.nl()+'</svg>';
|
|
|
|
this.svg += this.renderComments(this.footer);
|
2018-07-18 11:45:46 +00:00
|
|
|
this.postRenderSvg();
|
2018-07-18 07:39:29 +00:00
|
|
|
return this.svg;
|
2018-07-14 16:04:39 +00:00
|
|
|
}
|
|
|
|
|
2018-07-15 11:00:48 +00:00
|
|
|
/** Returns SVG code for the opening SVG tag */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.renderSvgTag = funtion (pattern)
|
|
|
|
{
|
2018-07-15 11:00:48 +00:00
|
|
|
let svg = '<svg';
|
|
|
|
this.indent();
|
|
|
|
svg += this.nl()+this.attributes.render();
|
|
|
|
this.outdent();
|
|
|
|
svg += this.nl()+'>'+this.nl();
|
|
|
|
|
|
|
|
return svg;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns SVG code for the style block */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.renderStyle = function ()
|
|
|
|
{
|
2018-07-17 14:16:17 +00:00
|
|
|
let svg = '<style type="text/css"> <![CDATA[ ';
|
2018-07-15 11:00:48 +00:00
|
|
|
this.indent();
|
|
|
|
svg += this.nl()+this.style;
|
|
|
|
this.outdent();
|
2018-07-18 14:48:49 +00:00
|
|
|
svg += this.nl()+']]>'+this.nl()+'</style>'+this.nl();
|
2018-07-15 11:00:48 +00:00
|
|
|
return svg;
|
|
|
|
}
|
|
|
|
|
2018-07-16 13:42:26 +00:00
|
|
|
/** Returns SVG code for the script block */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.renderScript = function ()
|
|
|
|
{
|
2018-07-16 13:42:26 +00:00
|
|
|
let svg = '<script type="text/javascript"> <![CDATA[';
|
|
|
|
this.indent();
|
|
|
|
svg += this.nl()+this.script;
|
|
|
|
this.outdent();
|
2018-07-18 14:48:49 +00:00
|
|
|
svg += this.nl()+']]>'+this.nl()+'</script>'+this.nl();
|
2018-07-16 13:42:26 +00:00
|
|
|
|
|
|
|
return svg;
|
|
|
|
}
|
|
|
|
|
2018-07-15 11:00:48 +00:00
|
|
|
/** Returns SVG code for the defs block */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.renderDefs = function ()
|
|
|
|
{
|
2018-07-15 11:00:48 +00:00
|
|
|
let svg = '<defs id="defs">';
|
|
|
|
this.indent();
|
|
|
|
svg += this.nl()+this.defs;
|
|
|
|
this.outdent();
|
|
|
|
svg += this.nl()+'</defs>'+this.nl();
|
|
|
|
|
|
|
|
return svg;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns SVG code for a comment block */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.renderComments = function (comments)
|
|
|
|
{
|
2018-07-15 11:00:48 +00:00
|
|
|
return this.nl()+this.nl()+'<!--'+this.nl()+comments+this.nl()+'-->';
|
|
|
|
}
|
|
|
|
|
2018-07-14 16:04:39 +00:00
|
|
|
/** Returns SVG code for a Part object */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.renderPart = function (part)
|
|
|
|
{
|
2018-07-14 16:04:39 +00:00
|
|
|
let svg = '';
|
2018-07-16 13:42:26 +00:00
|
|
|
for (let key in part.paths) {
|
|
|
|
let path = part.paths[key];
|
2018-07-14 16:04:39 +00:00
|
|
|
if(path.render) svg += this.renderPath(path);
|
|
|
|
}
|
2018-07-22 18:22:51 +02:00
|
|
|
for (let key in part.points) {
|
|
|
|
if(part.points[key].attributes.get('data-text')) {
|
|
|
|
svg += this.renderPoint(part.points[key]);
|
|
|
|
}
|
|
|
|
}
|
2018-07-16 13:42:26 +00:00
|
|
|
for (let key in part.snippets) {
|
|
|
|
let snippet = part.snippets[key];
|
|
|
|
svg += this.renderSnippet(snippet);
|
|
|
|
}
|
2018-07-22 18:22:51 +02:00
|
|
|
|
|
|
|
return svg;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns SVG code for a Point object */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.renderPoint = function (point)
|
2018-07-22 18:22:51 +02:00
|
|
|
{
|
|
|
|
let svg = ''
|
|
|
|
if(point.attributes.get('data-text')) svg += this.renderText(point);
|
2018-07-14 16:04:39 +00:00
|
|
|
|
|
|
|
return svg;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns SVG code for a Path object */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.renderPath = function (path)
|
2018-07-21 18:53:03 +02:00
|
|
|
{
|
|
|
|
if(!path.attributes.get('id')) path.attributes.add('id', this.getUid());
|
2018-07-15 08:36:19 +00:00
|
|
|
path.attributes.add('d', path.asPathstring());
|
2018-07-21 18:53:03 +02:00
|
|
|
|
|
|
|
return `${this.nl()}<path ${path.attributes.render()} />${this.renderPathText(path)}`;
|
|
|
|
}
|
|
|
|
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.renderPathText = function (path)
|
2018-07-21 18:53:03 +02:00
|
|
|
{
|
|
|
|
let text = path.attributes.get('data-text');
|
|
|
|
if(!text) return false;
|
|
|
|
let attributes = path.attributes.renderIfPrefixIs('data-text-');
|
|
|
|
let svg = this.nl()+'<text>';
|
|
|
|
this.indent();
|
|
|
|
svg += `<textPath xlink:href="#${path.attributes.get('id')}" startOffset="50%"><tspan ${attributes}>${text}</tspan></textPath>`;
|
|
|
|
this.outdent();
|
|
|
|
svg += this.nl()+'</text>';
|
|
|
|
|
|
|
|
return svg;
|
2018-07-14 16:04:39 +00:00
|
|
|
}
|
|
|
|
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.renderText = function (point)
|
2018-07-22 18:22:51 +02:00
|
|
|
{
|
|
|
|
let text = point.attributes.get('data-text');
|
|
|
|
if(!text) return false;
|
|
|
|
|
|
|
|
point.attributes.add('data-text-x', point.x);
|
|
|
|
point.attributes.add('data-text-y', point.y);
|
|
|
|
let attributes = point.attributes.renderIfPrefixIs('data-text-');
|
|
|
|
let svg = `${this.nl()}<text ${point.attributes.renderIfPrefixIs('data-text-')}>`;
|
|
|
|
this.indent();
|
|
|
|
svg += `<tspan>${text}</tspan>`;
|
|
|
|
this.outdent();
|
|
|
|
svg += this.nl()+'</text>';
|
|
|
|
|
|
|
|
return svg;
|
|
|
|
}
|
|
|
|
|
2018-07-16 13:42:26 +00:00
|
|
|
/** Returns SVG code for a snippet */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.renderSnippet = function (snippet)
|
2018-07-22 18:22:51 +02:00
|
|
|
{
|
2018-07-16 13:42:26 +00:00
|
|
|
let svg = this.nl();
|
|
|
|
svg += `<use x="${snippet.anchor.x}" y="${snippet.anchor.y}" `
|
|
|
|
svg += `xlink:href="#${snippet.def}" ${snippet.attributes.render()}>`;
|
|
|
|
if(snippet.description) {
|
|
|
|
svg += `<title>${snippet.description}</title>`;
|
|
|
|
}
|
|
|
|
svg += '</use>';
|
|
|
|
|
|
|
|
return svg;
|
|
|
|
}
|
|
|
|
|
2018-07-14 16:04:39 +00:00
|
|
|
/** Returns SVG code to open a group */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.openGroup = function (id)
|
|
|
|
{
|
2018-07-14 16:04:39 +00:00
|
|
|
let svg = this.nl()+this.nl();
|
|
|
|
svg += `<!-- Start of group #${id} -->`;
|
|
|
|
svg += this.nl();
|
|
|
|
svg += `<g id="${id}">`;
|
|
|
|
this.indent();
|
|
|
|
this.openGroups.push(id);
|
|
|
|
|
|
|
|
return svg;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns SVG code to close a group */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.closeGroup = function ()
|
|
|
|
{
|
2018-07-14 16:04:39 +00:00
|
|
|
this.outdent();
|
|
|
|
|
|
|
|
return `${this.nl()}</g>${this.nl()}<!-- end of group #${this.openGroups.pop()} -->`;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns a linebreak + identation */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.nl = function ()
|
|
|
|
{
|
2018-07-15 11:00:48 +00:00
|
|
|
return "\n"+this.tab();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns indentation */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.tab = function ()
|
|
|
|
{
|
2018-07-15 11:00:48 +00:00
|
|
|
let space = '';
|
|
|
|
for (let i = 0; i < this.tabs; i++) {
|
|
|
|
space += ' ';
|
|
|
|
}
|
|
|
|
|
|
|
|
return space;
|
2018-07-14 16:04:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Increases indentation by 1 */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.indent = function ()
|
|
|
|
{
|
2018-07-14 16:04:39 +00:00
|
|
|
this.tabs += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Decreases indentation by 1 */
|
2018-07-23 11:12:06 +00:00
|
|
|
this.prototype.outdent = function ()
|
|
|
|
{
|
2018-07-14 16:04:39 +00:00
|
|
|
this.tabs -= 1;
|
|
|
|
}
|
|
|
|
|
2018-07-23 11:12:06 +00:00
|
|
|
/** Returns an unused ID */
|
|
|
|
this.prototype.getUid = function ()
|
|
|
|
{
|
2018-07-14 16:04:39 +00:00
|
|
|
this.freeId += 1;
|
|
|
|
|
2018-07-16 15:20:50 +00:00
|
|
|
return ''+this.freeId;
|
2018-07-23 11:12:06 +00:00
|
|
|
}
|
2018-07-14 16:04:39 +00:00
|
|
|
}
|
2018-07-23 11:12:06 +00:00
|
|
|
|
|
|
|
export default svg;
|