- Linting (ESLint): Stricter rules (or switch to warning)
- Breaking internal API change: `updateGripCursor` moved to be class method of Selector rather than instance method - Breaking internal API change: `subpathIsClosed` moved to be class method of `Path` rather than instance method - Refactoring: Reuse utilities base64 encoder for SVG icons plugin - Docs (JSDoc): Fix return of the `mouseUp` (can also be an object) and `mouseDown` (may also be a boolean) of `pathActions`; other JSDoc additions/improvements
This commit is contained in:
@@ -11,6 +11,15 @@
|
||||
import RGBColor from './rgbcolor.js';
|
||||
import {canvasRGBA} from '../external/stackblur-canvas/dist/stackblur-es.js';
|
||||
|
||||
/**
|
||||
* Whether a value is `null` or `undefined`.
|
||||
* @param {Any} val
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isNullish = (val) => {
|
||||
return val === null || val === undefined;
|
||||
};
|
||||
|
||||
let canvasRGBA_ = canvasRGBA;
|
||||
|
||||
/**
|
||||
@@ -63,7 +72,7 @@ export const setStackBlurCanvasRGBA = (cb) => {
|
||||
*/
|
||||
export const canvg = function (target, s, opts) {
|
||||
// no parameters
|
||||
if (target == null && s == null && opts == null) {
|
||||
if (isNullish(target) && isNullish(s) && isNullish(opts)) {
|
||||
const svgTags = document.querySelectorAll('svg');
|
||||
return Promise.all([...svgTags].map((svgTag) => {
|
||||
const c = document.createElement('canvas');
|
||||
@@ -82,7 +91,7 @@ export const canvg = function (target, s, opts) {
|
||||
}
|
||||
|
||||
// store class on canvas
|
||||
if (target.svg != null) target.svg.stop();
|
||||
if (!isNullish(target.svg)) target.svg.stop();
|
||||
const svg = build(opts || {});
|
||||
// on i.e. 8 for flash canvas, we can't assign the property so check for it
|
||||
if (!(target.childNodes.length === 1 && target.childNodes[0].nodeName === 'OBJECT')) {
|
||||
@@ -113,9 +122,9 @@ function build (opts) {
|
||||
svg.FRAMERATE = 30;
|
||||
svg.MAX_VIRTUAL_PIXELS = 30000;
|
||||
|
||||
svg.log = function (msg) {};
|
||||
svg.log = function (msg) { /* */ };
|
||||
if (svg.opts.log === true && typeof console !== 'undefined') {
|
||||
svg.log = function (msg) { console.log(msg); };
|
||||
svg.log = function (msg) { console.log(msg); }; // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
// globals
|
||||
@@ -139,7 +148,7 @@ function build (opts) {
|
||||
width () { return this.Current().width; },
|
||||
height () { return this.Current().height; },
|
||||
ComputeSize (d) {
|
||||
if (d != null && typeof d === 'number') return d;
|
||||
if (!isNullish(d) && typeof d === 'number') return d;
|
||||
if (d === 'x') return this.width();
|
||||
if (d === 'y') return this.height();
|
||||
return Math.sqrt(
|
||||
@@ -190,13 +199,12 @@ function build (opts) {
|
||||
if (window.DOMParser) {
|
||||
const parser = new DOMParser();
|
||||
return parser.parseFromString(xml, 'text/xml');
|
||||
} else {
|
||||
xml = xml.replace(/<!DOCTYPE svg[^>]*>/, '');
|
||||
const xmlDoc = new window.ActiveXObject('Microsoft.XMLDOM');
|
||||
xmlDoc.async = 'false';
|
||||
xmlDoc.loadXML(xml);
|
||||
return xmlDoc;
|
||||
}
|
||||
xml = xml.replace(/<!DOCTYPE svg[^>]*>/, '');
|
||||
const xmlDoc = new window.ActiveXObject('Microsoft.XMLDOM');
|
||||
xmlDoc.async = 'false';
|
||||
xmlDoc.loadXML(xml);
|
||||
return xmlDoc;
|
||||
};
|
||||
|
||||
// text extensions
|
||||
@@ -226,7 +234,7 @@ function build (opts) {
|
||||
}
|
||||
|
||||
hasValue () {
|
||||
return (this.value != null && this.value !== '');
|
||||
return (!isNullish(this.value) && this.value !== '');
|
||||
}
|
||||
|
||||
// return the numerical value of the property
|
||||
@@ -234,8 +242,8 @@ function build (opts) {
|
||||
if (!this.hasValue()) return 0;
|
||||
|
||||
let n = parseFloat(this.value);
|
||||
if ((this.value + '').match(/%$/)) {
|
||||
n = n / 100.0;
|
||||
if (String(this.value).match(/%$/)) {
|
||||
n /= 100.0;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
@@ -254,7 +262,7 @@ function build (opts) {
|
||||
// augment the current color value with the opacity
|
||||
addOpacity (opacityProp) {
|
||||
let newValue = this.value;
|
||||
if (opacityProp.value != null && opacityProp.value !== '' && typeof this.value === 'string') { // can only add opacity to colors, not patterns
|
||||
if (!isNullish(opacityProp.value) && opacityProp.value !== '' && typeof this.value === 'string') { // can only add opacity to colors, not patterns
|
||||
const color = new RGBColor(this.value);
|
||||
if (color.ok) {
|
||||
newValue = 'rgba(' + color.r + ', ' + color.g + ', ' + color.b + ', ' + opacityProp.numValue() + ')';
|
||||
@@ -280,12 +288,12 @@ function build (opts) {
|
||||
let def = this.getDefinition();
|
||||
|
||||
// gradient
|
||||
if (def != null && def.createGradient) {
|
||||
if (!isNullish(def) && def.createGradient) {
|
||||
return def.createGradient(svg.ctx, e, opacityProp);
|
||||
}
|
||||
|
||||
// pattern
|
||||
if (def != null && def.createPattern) {
|
||||
if (!isNullish(def) && def.createPattern) {
|
||||
if (def.getHrefAttribute().hasValue()) {
|
||||
const pt = def.attribute('patternTransform');
|
||||
def = def.getHrefAttribute().getDefinition();
|
||||
@@ -312,14 +320,13 @@ function build (opts) {
|
||||
}
|
||||
|
||||
getUnits () {
|
||||
const s = this.value + '';
|
||||
return s.replace(/[0-9.-]/g, '');
|
||||
return String(this.value).replace(/[0-9.-]/g, '');
|
||||
}
|
||||
|
||||
// get the length as pixels
|
||||
toPixels (viewPort, processPercent) {
|
||||
if (!this.hasValue()) return 0;
|
||||
const s = this.value + '';
|
||||
const s = String(this.value);
|
||||
if (s.match(/em$/)) return this.numValue() * this.getEM(viewPort);
|
||||
if (s.match(/ex$/)) return this.numValue() * this.getEM(viewPort) / 2.0;
|
||||
if (s.match(/px$/)) return this.numValue();
|
||||
@@ -338,7 +345,7 @@ function build (opts) {
|
||||
// get the time as milliseconds
|
||||
toMilliseconds () {
|
||||
if (!this.hasValue()) return 0;
|
||||
const s = this.value + '';
|
||||
const s = String(this.value);
|
||||
if (s.match(/s$/)) return this.numValue() * 1000;
|
||||
if (s.match(/ms$/)) return this.numValue();
|
||||
return this.numValue();
|
||||
@@ -348,7 +355,7 @@ function build (opts) {
|
||||
// get the angle as radians
|
||||
toRadians () {
|
||||
if (!this.hasValue()) return 0;
|
||||
const s = this.value + '';
|
||||
const s = String(this.value);
|
||||
if (s.match(/deg$/)) return this.numValue() * (Math.PI / 180.0);
|
||||
if (s.match(/grad$/)) return this.numValue() * (Math.PI / 200.0);
|
||||
if (s.match(/rad$/)) return this.numValue();
|
||||
@@ -368,7 +375,7 @@ function build (opts) {
|
||||
Weights: 'normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit',
|
||||
|
||||
CreateFont (fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) {
|
||||
const f = inherit != null ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font);
|
||||
const f = !isNullish(inherit) ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font);
|
||||
return {
|
||||
fontFamily: fontFamily || f.fontFamily,
|
||||
fontSize: fontSize || f.fontSize,
|
||||
@@ -474,7 +481,7 @@ function build (opts) {
|
||||
height () { return this.y2 - this.y1; }
|
||||
|
||||
addPoint (x, y) {
|
||||
if (x != null) {
|
||||
if (!isNullish(x)) {
|
||||
if (isNaN(this.x1) || isNaN(this.x2)) {
|
||||
this.x1 = x;
|
||||
this.x2 = x;
|
||||
@@ -483,7 +490,7 @@ function build (opts) {
|
||||
if (x > this.x2) this.x2 = x;
|
||||
}
|
||||
|
||||
if (y != null) {
|
||||
if (!isNullish(y)) {
|
||||
if (isNaN(this.y1) || isNaN(this.y2)) {
|
||||
this.y1 = y;
|
||||
this.y2 = y;
|
||||
@@ -710,7 +717,7 @@ function build (opts) {
|
||||
else if (meetOrSlice === 'slice') ctx.scale(scaleMax, scaleMax);
|
||||
|
||||
// translate
|
||||
ctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY);
|
||||
ctx.translate(isNullish(minX) ? 0 : -minX, isNullish(minY) ? 0 : -minY);
|
||||
};
|
||||
|
||||
// elements
|
||||
@@ -724,7 +731,7 @@ function build (opts) {
|
||||
this.attributes = {};
|
||||
this.styles = {};
|
||||
this.children = [];
|
||||
if (node != null && node.nodeType === 1) { // ELEMENT_NODE
|
||||
if (!isNullish(node) && node.nodeType === 1) { // ELEMENT_NODE
|
||||
// add children
|
||||
[...node.childNodes].forEach((childNode) => {
|
||||
if (childNode.nodeType === 1) {
|
||||
@@ -749,7 +756,7 @@ function build (opts) {
|
||||
});
|
||||
// add tag styles
|
||||
let styles = svg.Styles[node.nodeName];
|
||||
if (styles != null) {
|
||||
if (!isNullish(styles)) {
|
||||
for (const name in styles) {
|
||||
this.styles[name] = styles[name];
|
||||
}
|
||||
@@ -760,13 +767,13 @@ function build (opts) {
|
||||
const classes = svg.compressSpaces(this.attribute('class').value).split(' ');
|
||||
classes.forEach((clss) => {
|
||||
styles = svg.Styles['.' + clss];
|
||||
if (styles != null) {
|
||||
if (!isNullish(styles)) {
|
||||
for (const name in styles) {
|
||||
this.styles[name] = styles[name];
|
||||
}
|
||||
}
|
||||
styles = svg.Styles[node.nodeName + '.' + clss];
|
||||
if (styles != null) {
|
||||
if (!isNullish(styles)) {
|
||||
for (const name in styles) {
|
||||
this.styles[name] = styles[name];
|
||||
}
|
||||
@@ -777,7 +784,7 @@ function build (opts) {
|
||||
// add id styles
|
||||
if (this.attribute('id').hasValue()) {
|
||||
const styles = svg.Styles['#' + this.attribute('id').value];
|
||||
if (styles != null) {
|
||||
if (!isNullish(styles)) {
|
||||
for (const name in styles) {
|
||||
this.styles[name] = styles[name];
|
||||
}
|
||||
@@ -799,7 +806,7 @@ function build (opts) {
|
||||
|
||||
// add id
|
||||
if (this.attribute('id').hasValue()) {
|
||||
if (svg.Definitions[this.attribute('id').value] == null) {
|
||||
if (isNullish(svg.Definitions[this.attribute('id').value])) {
|
||||
svg.Definitions[this.attribute('id').value] = this;
|
||||
}
|
||||
}
|
||||
@@ -809,7 +816,7 @@ function build (opts) {
|
||||
// get or create attribute
|
||||
attribute (name, createIfNotExists) {
|
||||
let a = this.attributes[name];
|
||||
if (a != null) return a;
|
||||
if (!isNullish(a)) return a;
|
||||
|
||||
if (createIfNotExists === true) { a = new svg.Property(name, ''); this.attributes[name] = a; }
|
||||
return a || svg.EmptyProperty;
|
||||
@@ -827,19 +834,19 @@ function build (opts) {
|
||||
// get or create style, crawls up node tree
|
||||
style (name, createIfNotExists, skipAncestors) {
|
||||
let s = this.styles[name];
|
||||
if (s != null) return s;
|
||||
if (!isNullish(s)) return s;
|
||||
|
||||
const a = this.attribute(name);
|
||||
if (a != null && a.hasValue()) {
|
||||
if (!isNullish(a) && a.hasValue()) {
|
||||
this.styles[name] = a; // move up to me to cache
|
||||
return a;
|
||||
}
|
||||
|
||||
if (skipAncestors !== true) {
|
||||
const p = this.parent;
|
||||
if (p != null) {
|
||||
if (!isNullish(p)) {
|
||||
const ps = p.style(name);
|
||||
if (ps != null && ps.hasValue()) {
|
||||
if (!isNullish(ps) && ps.hasValue()) {
|
||||
return ps;
|
||||
}
|
||||
}
|
||||
@@ -860,10 +867,10 @@ function build (opts) {
|
||||
ctx.save();
|
||||
if (this.attribute('mask').hasValue()) { // mask
|
||||
const mask = this.attribute('mask').getDefinition();
|
||||
if (mask != null) mask.apply(ctx, this);
|
||||
if (!isNullish(mask)) mask.apply(ctx, this);
|
||||
} else if (this.style('filter').hasValue()) { // filter
|
||||
const filter = this.style('filter').getDefinition();
|
||||
if (filter != null) filter.apply(ctx, this);
|
||||
if (!isNullish(filter)) filter.apply(ctx, this);
|
||||
} else {
|
||||
this.setContext(ctx);
|
||||
this.renderChildren(ctx);
|
||||
@@ -903,7 +910,7 @@ function build (opts) {
|
||||
// fill
|
||||
if (this.style('fill').isUrlDefinition()) {
|
||||
const fs = this.style('fill').getFillStyleDefinition(this, this.style('fill-opacity'));
|
||||
if (fs != null) ctx.fillStyle = fs;
|
||||
if (!isNullish(fs)) ctx.fillStyle = fs;
|
||||
} else if (this.style('fill').hasValue()) {
|
||||
const fillStyle = this.style('fill');
|
||||
if (fillStyle.value === 'currentColor') fillStyle.value = this.style('color').value;
|
||||
@@ -918,7 +925,7 @@ function build (opts) {
|
||||
// stroke
|
||||
if (this.style('stroke').isUrlDefinition()) {
|
||||
const fs = this.style('stroke').getFillStyleDefinition(this, this.style('stroke-opacity'));
|
||||
if (fs != null) ctx.strokeStyle = fs;
|
||||
if (!isNullish(fs)) ctx.strokeStyle = fs;
|
||||
} else if (this.style('stroke').hasValue()) {
|
||||
const strokeStyle = this.style('stroke');
|
||||
if (strokeStyle.value === 'currentColor') strokeStyle.value = this.style('color').value;
|
||||
@@ -963,7 +970,8 @@ function build (opts) {
|
||||
this.style('font-variant').value,
|
||||
this.style('font-weight').value,
|
||||
this.style('font-size').hasValue() ? this.style('font-size').toPixels() + 'px' : '',
|
||||
this.style('font-family').value).toString();
|
||||
this.style('font-family').value
|
||||
).toString();
|
||||
}
|
||||
|
||||
// transform
|
||||
@@ -975,7 +983,7 @@ function build (opts) {
|
||||
// clip
|
||||
if (this.style('clip-path', false, true).hasValue()) {
|
||||
const clip = this.style('clip-path', false, true).getDefinition();
|
||||
if (clip != null) clip.apply(ctx);
|
||||
if (!isNullish(clip)) clip.apply(ctx);
|
||||
}
|
||||
|
||||
// opacity
|
||||
@@ -987,7 +995,7 @@ function build (opts) {
|
||||
|
||||
svg.Element.PathElementBase = class extends svg.Element.RenderedElementBase {
|
||||
path (ctx) {
|
||||
if (ctx != null) ctx.beginPath();
|
||||
if (!isNullish(ctx)) ctx.beginPath();
|
||||
return new svg.BoundingBox();
|
||||
}
|
||||
|
||||
@@ -1004,7 +1012,7 @@ function build (opts) {
|
||||
if (ctx.strokeStyle !== '') ctx.stroke();
|
||||
|
||||
const markers = this.getMarkers();
|
||||
if (markers != null) {
|
||||
if (!isNullish(markers)) {
|
||||
if (this.style('marker-start').isUrlDefinition()) {
|
||||
const marker = this.style('marker-start').getDefinition();
|
||||
marker.render(ctx, markers[0][0], markers[0][1]);
|
||||
@@ -1123,7 +1131,7 @@ function build (opts) {
|
||||
if (this.attribute('ry').hasValue() && !this.attribute('rx').hasValue()) rx = ry;
|
||||
rx = Math.min(rx, width / 2.0);
|
||||
ry = Math.min(ry, height / 2.0);
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x + rx, y);
|
||||
ctx.lineTo(x + width - rx, y);
|
||||
@@ -1148,7 +1156,7 @@ function build (opts) {
|
||||
const cy = this.attribute('cy').toPixels('y');
|
||||
const r = this.attribute('r').toPixels();
|
||||
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(cx, cy, r, 0, Math.PI * 2, true);
|
||||
ctx.closePath();
|
||||
@@ -1167,7 +1175,7 @@ function build (opts) {
|
||||
const cx = this.attribute('cx').toPixels('x');
|
||||
const cy = this.attribute('cy').toPixels('y');
|
||||
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(cx, cy - ry);
|
||||
ctx.bezierCurveTo(cx + (KAPPA * rx), cy - ry, cx + rx, cy - (KAPPA * ry), cx + rx, cy);
|
||||
@@ -1186,13 +1194,14 @@ function build (opts) {
|
||||
getPoints () {
|
||||
return [
|
||||
new svg.Point(this.attribute('x1').toPixels('x'), this.attribute('y1').toPixels('y')),
|
||||
new svg.Point(this.attribute('x2').toPixels('x'), this.attribute('y2').toPixels('y'))];
|
||||
new svg.Point(this.attribute('x2').toPixels('x'), this.attribute('y2').toPixels('y'))
|
||||
];
|
||||
}
|
||||
|
||||
path (ctx) {
|
||||
const points = this.getPoints();
|
||||
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(points[0].x, points[0].y);
|
||||
ctx.lineTo(points[1].x, points[1].y);
|
||||
@@ -1218,14 +1227,14 @@ function build (opts) {
|
||||
path (ctx) {
|
||||
const {x, y} = this.points[0];
|
||||
const bb = new svg.BoundingBox(x, y);
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, y);
|
||||
}
|
||||
for (let i = 1; i < this.points.length; i++) {
|
||||
const {x, y} = this.points[i];
|
||||
bb.addPoint(x, y);
|
||||
if (ctx != null) ctx.lineTo(x, y);
|
||||
if (!isNullish(ctx)) ctx.lineTo(x, y);
|
||||
}
|
||||
return bb;
|
||||
}
|
||||
@@ -1244,7 +1253,7 @@ function build (opts) {
|
||||
svg.Element.polygon = class extends svg.Element.polyline {
|
||||
path (ctx) {
|
||||
const bb = super.path(ctx);
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
ctx.lineTo(this.points[0].x, this.points[0].y);
|
||||
ctx.closePath();
|
||||
}
|
||||
@@ -1289,7 +1298,7 @@ function build (opts) {
|
||||
|
||||
isCommandOrEnd () {
|
||||
if (this.isEnd()) return true;
|
||||
return this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null;
|
||||
return !isNullish(this.tokens[this.i + 1].match(/^[A-Za-z]$/));
|
||||
},
|
||||
|
||||
isRelativeCommand () {
|
||||
@@ -1363,10 +1372,10 @@ function build (opts) {
|
||||
|
||||
addMarker (p, from, priorTo) {
|
||||
// if the last angle isn't filled in because we didn't have this point yet ...
|
||||
if (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length - 1] == null) {
|
||||
if (!isNullish(priorTo) && this.angles.length > 0 && isNullish(this.angles[this.angles.length - 1])) {
|
||||
this.angles[this.angles.length - 1] = this.points[this.points.length - 1].angleTo(priorTo);
|
||||
}
|
||||
this.addMarkerAngle(p, from == null ? null : from.angleTo(p));
|
||||
this.addMarkerAngle(p, isNullish(from) ? null : from.angleTo(p));
|
||||
},
|
||||
|
||||
addMarkerAngle (p, a) {
|
||||
@@ -1377,9 +1386,9 @@ function build (opts) {
|
||||
getMarkerPoints () { return this.points; },
|
||||
getMarkerAngles () {
|
||||
for (let i = 0; i < this.angles.length; i++) {
|
||||
if (this.angles[i] == null) {
|
||||
if (isNullish(this.angles[i])) {
|
||||
for (let j = i + 1; j < this.angles.length; j++) {
|
||||
if (this.angles[j] != null) {
|
||||
if (!isNullish(this.angles[j])) {
|
||||
this.angles[i] = this.angles[j];
|
||||
break;
|
||||
}
|
||||
@@ -1396,7 +1405,7 @@ function build (opts) {
|
||||
pp.reset();
|
||||
|
||||
const bb = new svg.BoundingBox();
|
||||
if (ctx != null) ctx.beginPath();
|
||||
if (!isNullish(ctx)) ctx.beginPath();
|
||||
while (!pp.isEnd()) {
|
||||
pp.nextCommand();
|
||||
switch (pp.command) {
|
||||
@@ -1405,13 +1414,13 @@ function build (opts) {
|
||||
const p = pp.getAsCurrentPoint();
|
||||
pp.addMarker(p);
|
||||
bb.addPoint(p.x, p.y);
|
||||
if (ctx != null) ctx.moveTo(p.x, p.y);
|
||||
if (!isNullish(ctx)) ctx.moveTo(p.x, p.y);
|
||||
pp.start = pp.current;
|
||||
while (!pp.isCommandOrEnd()) {
|
||||
const p = pp.getAsCurrentPoint();
|
||||
pp.addMarker(p, pp.start);
|
||||
bb.addPoint(p.x, p.y);
|
||||
if (ctx != null) ctx.lineTo(p.x, p.y);
|
||||
if (!isNullish(ctx)) ctx.lineTo(p.x, p.y);
|
||||
}
|
||||
break;
|
||||
case 'L':
|
||||
@@ -1421,7 +1430,7 @@ function build (opts) {
|
||||
const p = pp.getAsCurrentPoint();
|
||||
pp.addMarker(p, c);
|
||||
bb.addPoint(p.x, p.y);
|
||||
if (ctx != null) ctx.lineTo(p.x, p.y);
|
||||
if (!isNullish(ctx)) ctx.lineTo(p.x, p.y);
|
||||
}
|
||||
break;
|
||||
case 'H':
|
||||
@@ -1431,7 +1440,7 @@ function build (opts) {
|
||||
pp.addMarker(newP, pp.current);
|
||||
pp.current = newP;
|
||||
bb.addPoint(pp.current.x, pp.current.y);
|
||||
if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
|
||||
if (!isNullish(ctx)) ctx.lineTo(pp.current.x, pp.current.y);
|
||||
}
|
||||
break;
|
||||
case 'V':
|
||||
@@ -1441,7 +1450,7 @@ function build (opts) {
|
||||
pp.addMarker(newP, pp.current);
|
||||
pp.current = newP;
|
||||
bb.addPoint(pp.current.x, pp.current.y);
|
||||
if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
|
||||
if (!isNullish(ctx)) ctx.lineTo(pp.current.x, pp.current.y);
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
@@ -1453,7 +1462,7 @@ function build (opts) {
|
||||
const cp = pp.getAsCurrentPoint();
|
||||
pp.addMarker(cp, cntrl, p1);
|
||||
bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (!isNullish(ctx)) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
@@ -1465,7 +1474,7 @@ function build (opts) {
|
||||
const cp = pp.getAsCurrentPoint();
|
||||
pp.addMarker(cp, cntrl, p1);
|
||||
bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (!isNullish(ctx)) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
}
|
||||
break;
|
||||
case 'Q':
|
||||
@@ -1476,7 +1485,7 @@ function build (opts) {
|
||||
const cp = pp.getAsCurrentPoint();
|
||||
pp.addMarker(cp, cntrl, cntrl);
|
||||
bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (!isNullish(ctx)) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
@@ -1488,7 +1497,7 @@ function build (opts) {
|
||||
const cp = pp.getAsCurrentPoint();
|
||||
pp.addMarker(cp, cntrl, cntrl);
|
||||
bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
if (!isNullish(ctx)) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
@@ -1560,7 +1569,7 @@ function build (opts) {
|
||||
pp.addMarkerAngle(cp, ah - dir * Math.PI);
|
||||
|
||||
bb.addPoint(cp.x, cp.y); // TODO: this is too naive, make it better
|
||||
if (ctx != null) {
|
||||
if (!isNullish(ctx)) {
|
||||
const r = rx > ry ? rx : ry;
|
||||
const sx = rx > ry ? 1 : rx / ry;
|
||||
const sy = rx > ry ? ry / rx : 1;
|
||||
@@ -1577,7 +1586,7 @@ function build (opts) {
|
||||
break;
|
||||
case 'Z':
|
||||
case 'z':
|
||||
if (ctx != null) ctx.closePath();
|
||||
if (!isNullish(ctx)) ctx.closePath();
|
||||
pp.current = pp.start;
|
||||
}
|
||||
}
|
||||
@@ -1604,10 +1613,10 @@ function build (opts) {
|
||||
|
||||
// render me using a temporary svg element
|
||||
const tempSvg = new svg.Element.svg();
|
||||
tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);
|
||||
tempSvg.attributes['width'] = new svg.Property('width', width + 'px');
|
||||
tempSvg.attributes['height'] = new svg.Property('height', height + 'px');
|
||||
tempSvg.attributes['transform'] = new svg.Property('transform', this.attribute('patternTransform').value);
|
||||
tempSvg.attributes.viewBox = new svg.Property('viewBox', this.attribute('viewBox').value);
|
||||
tempSvg.attributes.width = new svg.Property('width', width + 'px');
|
||||
tempSvg.attributes.height = new svg.Property('height', height + 'px');
|
||||
tempSvg.attributes.transform = new svg.Property('transform', this.attribute('patternTransform').value);
|
||||
tempSvg.children = this.children;
|
||||
|
||||
const c = document.createElement('canvas');
|
||||
@@ -1641,13 +1650,13 @@ function build (opts) {
|
||||
|
||||
// render me using a temporary svg element
|
||||
const tempSvg = new svg.Element.svg();
|
||||
tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);
|
||||
tempSvg.attributes['refX'] = new svg.Property('refX', this.attribute('refX').value);
|
||||
tempSvg.attributes['refY'] = new svg.Property('refY', this.attribute('refY').value);
|
||||
tempSvg.attributes['width'] = new svg.Property('width', this.attribute('markerWidth').value);
|
||||
tempSvg.attributes['height'] = new svg.Property('height', this.attribute('markerHeight').value);
|
||||
tempSvg.attributes['fill'] = new svg.Property('fill', this.attribute('fill').valueOrDefault('black'));
|
||||
tempSvg.attributes['stroke'] = new svg.Property('stroke', this.attribute('stroke').valueOrDefault('none'));
|
||||
tempSvg.attributes.viewBox = new svg.Property('viewBox', this.attribute('viewBox').value);
|
||||
tempSvg.attributes.refX = new svg.Property('refX', this.attribute('refX').value);
|
||||
tempSvg.attributes.refY = new svg.Property('refY', this.attribute('refY').value);
|
||||
tempSvg.attributes.width = new svg.Property('width', this.attribute('markerWidth').value);
|
||||
tempSvg.attributes.height = new svg.Property('height', this.attribute('markerHeight').value);
|
||||
tempSvg.attributes.fill = new svg.Property('fill', this.attribute('fill').valueOrDefault('black'));
|
||||
tempSvg.attributes.stroke = new svg.Property('stroke', this.attribute('stroke').valueOrDefault('none'));
|
||||
tempSvg.children = this.children;
|
||||
tempSvg.render(ctx);
|
||||
|
||||
@@ -1698,7 +1707,7 @@ function build (opts) {
|
||||
};
|
||||
|
||||
const g = this.getGradient(ctx, element);
|
||||
if (g == null) return addParentOpacity(stopsContainer.stops[stopsContainer.stops.length - 1].color);
|
||||
if (isNullish(g)) return addParentOpacity(stopsContainer.stops[stopsContainer.stops.length - 1].color);
|
||||
stopsContainer.stops.forEach(({offset, color}) => {
|
||||
g.addColorStop(offset, addParentOpacity(color));
|
||||
});
|
||||
@@ -1708,20 +1717,20 @@ function build (opts) {
|
||||
const rootView = svg.ViewPort.viewPorts[0];
|
||||
|
||||
const rect = new svg.Element.rect();
|
||||
rect.attributes['x'] = new svg.Property('x', -svg.MAX_VIRTUAL_PIXELS / 3.0);
|
||||
rect.attributes['y'] = new svg.Property('y', -svg.MAX_VIRTUAL_PIXELS / 3.0);
|
||||
rect.attributes['width'] = new svg.Property('width', svg.MAX_VIRTUAL_PIXELS);
|
||||
rect.attributes['height'] = new svg.Property('height', svg.MAX_VIRTUAL_PIXELS);
|
||||
rect.attributes.x = new svg.Property('x', -svg.MAX_VIRTUAL_PIXELS / 3.0);
|
||||
rect.attributes.y = new svg.Property('y', -svg.MAX_VIRTUAL_PIXELS / 3.0);
|
||||
rect.attributes.width = new svg.Property('width', svg.MAX_VIRTUAL_PIXELS);
|
||||
rect.attributes.height = new svg.Property('height', svg.MAX_VIRTUAL_PIXELS);
|
||||
|
||||
const group = new svg.Element.g();
|
||||
group.attributes['transform'] = new svg.Property('transform', this.attribute('gradientTransform').value);
|
||||
group.attributes.transform = new svg.Property('transform', this.attribute('gradientTransform').value);
|
||||
group.children = [rect];
|
||||
|
||||
const tempSvg = new svg.Element.svg();
|
||||
tempSvg.attributes['x'] = new svg.Property('x', 0);
|
||||
tempSvg.attributes['y'] = new svg.Property('y', 0);
|
||||
tempSvg.attributes['width'] = new svg.Property('width', rootView.width);
|
||||
tempSvg.attributes['height'] = new svg.Property('height', rootView.height);
|
||||
tempSvg.attributes.x = new svg.Property('x', 0);
|
||||
tempSvg.attributes.y = new svg.Property('y', 0);
|
||||
tempSvg.attributes.width = new svg.Property('width', rootView.width);
|
||||
tempSvg.attributes.height = new svg.Property('height', rootView.height);
|
||||
tempSvg.children = [group];
|
||||
|
||||
const c = document.createElement('canvas');
|
||||
@@ -1867,7 +1876,7 @@ function build (opts) {
|
||||
|
||||
update (delta) {
|
||||
// set initial value
|
||||
if (this.initialValue == null) {
|
||||
if (isNullish(this.initialValue)) {
|
||||
this.initialValue = this.getProperty().value;
|
||||
this.initialUnits = this.getProperty().getUnits();
|
||||
}
|
||||
@@ -1949,7 +1958,7 @@ function build (opts) {
|
||||
const r = from.r + (to.r - from.r) * p.progress;
|
||||
const g = from.g + (to.g - from.g) * p.progress;
|
||||
const b = from.b + (to.b - from.b) * p.progress;
|
||||
return 'rgb(' + parseInt(r, 10) + ',' + parseInt(g, 10) + ',' + parseInt(b, 10) + ')';
|
||||
return 'rgb(' + parseInt(r) + ',' + parseInt(g) + ',' + parseInt(b) + ')';
|
||||
}
|
||||
return this.attribute('from').value;
|
||||
}
|
||||
@@ -2048,8 +2057,8 @@ function build (opts) {
|
||||
super.setContext(ctx);
|
||||
|
||||
let textBaseline = this.style('dominant-baseline').toTextBaseline();
|
||||
if (textBaseline == null) textBaseline = this.style('alignment-baseline').toTextBaseline();
|
||||
if (textBaseline != null) ctx.textBaseline = textBaseline;
|
||||
if (isNullish(textBaseline)) textBaseline = this.style('alignment-baseline').toTextBaseline();
|
||||
if (!isNullish(textBaseline)) ctx.textBaseline = textBaseline;
|
||||
}
|
||||
|
||||
getBoundingBox () {
|
||||
@@ -2124,18 +2133,18 @@ function build (opts) {
|
||||
if (i > 0 && text[i - 1] !== ' ' && (i === text.length - 1 || text[i + 1] === ' ')) arabicForm = 'initial';
|
||||
if (typeof font.glyphs[c] !== 'undefined') {
|
||||
glyph = font.glyphs[c][arabicForm];
|
||||
if (glyph == null && font.glyphs[c].type === 'glyph') glyph = font.glyphs[c];
|
||||
if (isNullish(glyph) && font.glyphs[c].type === 'glyph') glyph = font.glyphs[c];
|
||||
}
|
||||
} else {
|
||||
glyph = font.glyphs[c];
|
||||
}
|
||||
if (glyph == null) glyph = font.missingGlyph;
|
||||
if (isNullish(glyph)) glyph = font.missingGlyph;
|
||||
return glyph;
|
||||
}
|
||||
|
||||
renderChildren (ctx) {
|
||||
const customFont = this.parent.style('font-family').getDefinition();
|
||||
if (customFont != null) {
|
||||
if (!isNullish(customFont)) {
|
||||
const fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
|
||||
const fontStyle = this.parent.style('font-style').valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle);
|
||||
let text = this.getText();
|
||||
@@ -2182,7 +2191,7 @@ function build (opts) {
|
||||
|
||||
measureText (ctx) {
|
||||
const customFont = this.parent.style('font-family').getDefinition();
|
||||
if (customFont != null) {
|
||||
if (!isNullish(customFont)) {
|
||||
const fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
|
||||
let measure = 0;
|
||||
let text = this.getText();
|
||||
@@ -2225,7 +2234,8 @@ function build (opts) {
|
||||
svg.Element.tref = class extends svg.Element.TextElementBase {
|
||||
getText () {
|
||||
const element = this.getHrefAttribute().getDefinition();
|
||||
if (element != null) return element.children[0].getText();
|
||||
if (!isNullish(element)) return element.children[0].getText();
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2290,13 +2300,12 @@ function build (opts) {
|
||||
if (svg.opts.useCORS === true) {
|
||||
this.img.crossOrigin = 'Anonymous';
|
||||
}
|
||||
const self = this;
|
||||
this.img.onload = function () {
|
||||
self.loaded = true;
|
||||
this.img.onload = () => {
|
||||
this.loaded = true;
|
||||
};
|
||||
this.img.onerror = function () {
|
||||
this.img.onerror = () => {
|
||||
svg.log('ERROR: image "' + href + '" not found');
|
||||
self.loaded = true;
|
||||
this.loaded = true;
|
||||
};
|
||||
this.img.src = href;
|
||||
} else {
|
||||
@@ -2387,14 +2396,14 @@ function build (opts) {
|
||||
const prop = cssProp.indexOf(':');
|
||||
const name = cssProp.substr(0, prop);
|
||||
const value = cssProp.substr(prop + 1, cssProp.length - prop);
|
||||
if (name != null && value != null) {
|
||||
if (!isNullish(name) && !isNullish(value)) {
|
||||
props[svg.trim(name)] = new svg.Property(svg.trim(name), svg.trim(value));
|
||||
}
|
||||
});
|
||||
svg.Styles[cssClass] = props;
|
||||
if (cssClass === '@font-face') {
|
||||
const fontFamily = props['font-family'].value.replace(/"/g, '');
|
||||
const srcs = props['src'].value.split(',');
|
||||
const srcs = props.src.value.split(',');
|
||||
srcs.forEach((src) => {
|
||||
if (src.includes('format("svg")')) {
|
||||
const urlStart = src.indexOf('url');
|
||||
@@ -2433,31 +2442,31 @@ function build (opts) {
|
||||
|
||||
path (ctx) {
|
||||
const {_el: element} = this;
|
||||
if (element != null) element.path(ctx);
|
||||
if (!isNullish(element)) element.path(ctx);
|
||||
}
|
||||
|
||||
getBoundingBox () {
|
||||
const {_el: element} = this;
|
||||
if (element != null) return element.getBoundingBox();
|
||||
if (!isNullish(element)) return element.getBoundingBox();
|
||||
}
|
||||
|
||||
renderChildren (ctx) {
|
||||
const {_el: element} = this;
|
||||
if (element != null) {
|
||||
if (!isNullish(element)) {
|
||||
let tempSvg = element;
|
||||
if (element.type === 'symbol') {
|
||||
// render me using a temporary svg element in symbol cases (https://www.w3.org/TR/SVG/struct.html#UseElement)
|
||||
tempSvg = new svg.Element.svg();
|
||||
tempSvg.type = 'svg';
|
||||
tempSvg.attributes['viewBox'] = new svg.Property('viewBox', element.attribute('viewBox').value);
|
||||
tempSvg.attributes['preserveAspectRatio'] = new svg.Property('preserveAspectRatio', element.attribute('preserveAspectRatio').value);
|
||||
tempSvg.attributes['overflow'] = new svg.Property('overflow', element.attribute('overflow').value);
|
||||
tempSvg.attributes.viewBox = new svg.Property('viewBox', element.attribute('viewBox').value);
|
||||
tempSvg.attributes.preserveAspectRatio = new svg.Property('preserveAspectRatio', element.attribute('preserveAspectRatio').value);
|
||||
tempSvg.attributes.overflow = new svg.Property('overflow', element.attribute('overflow').value);
|
||||
tempSvg.children = element.children;
|
||||
}
|
||||
if (tempSvg.type === 'svg') {
|
||||
// if symbol or svg, inherit width/height from me
|
||||
if (this.attribute('width').hasValue()) tempSvg.attributes['width'] = new svg.Property('width', this.attribute('width').value);
|
||||
if (this.attribute('height').hasValue()) tempSvg.attributes['height'] = new svg.Property('height', this.attribute('height').value);
|
||||
if (this.attribute('width').hasValue()) tempSvg.attributes.width = new svg.Property('width', this.attribute('width').value);
|
||||
if (this.attribute('height').hasValue()) tempSvg.attributes.height = new svg.Property('height', this.attribute('height').value);
|
||||
}
|
||||
const oldParent = tempSvg.parent;
|
||||
tempSvg.parent = null;
|
||||
@@ -2762,14 +2771,14 @@ function build (opts) {
|
||||
// bind mouse
|
||||
if (svg.opts.ignoreMouse !== true) {
|
||||
ctx.canvas.onclick = function (e) {
|
||||
const args = e != null
|
||||
const args = !isNullish(e)
|
||||
? [e.clientX, e.clientY]
|
||||
: [event.clientX, event.clientY];
|
||||
const {x, y} = mapXY(new svg.Point(...args));
|
||||
svg.Mouse.onclick(x, y);
|
||||
};
|
||||
ctx.canvas.onmousemove = function (e) {
|
||||
const args = e != null
|
||||
const args = !isNullish(e)
|
||||
? [e.clientX, e.clientY]
|
||||
: [event.clientX, event.clientY];
|
||||
const {x, y} = mapXY(new svg.Point(...args));
|
||||
@@ -2812,17 +2821,17 @@ function build (opts) {
|
||||
}
|
||||
svg.ViewPort.SetCurrent(cWidth, cHeight);
|
||||
|
||||
if (svg.opts.offsetX != null) {
|
||||
if (!isNullish(svg.opts.offsetX)) {
|
||||
e.attribute('x', true).value = svg.opts.offsetX;
|
||||
}
|
||||
if (svg.opts.offsetY != null) {
|
||||
if (!isNullish(svg.opts.offsetY)) {
|
||||
e.attribute('y', true).value = svg.opts.offsetY;
|
||||
}
|
||||
if (svg.opts.scaleWidth != null || svg.opts.scaleHeight != null) {
|
||||
if (!isNullish(svg.opts.scaleWidth) || !isNullish(svg.opts.scaleHeight)) {
|
||||
const viewBox = svg.ToNumberArray(e.attribute('viewBox').value);
|
||||
let xRatio = null, yRatio = null;
|
||||
|
||||
if (svg.opts.scaleWidth != null) {
|
||||
if (!isNullish(svg.opts.scaleWidth)) {
|
||||
if (e.attribute('width').hasValue()) {
|
||||
xRatio = e.attribute('width').toPixels('x') / svg.opts.scaleWidth;
|
||||
} else if (!isNaN(viewBox[2])) {
|
||||
@@ -2830,7 +2839,7 @@ function build (opts) {
|
||||
}
|
||||
}
|
||||
|
||||
if (svg.opts.scaleHeight != null) {
|
||||
if (!isNullish(svg.opts.scaleHeight)) {
|
||||
if (e.attribute('height').hasValue()) {
|
||||
yRatio = e.attribute('height').toPixels('y') / svg.opts.scaleHeight;
|
||||
} else if (!isNaN(viewBox[3])) {
|
||||
@@ -2838,8 +2847,8 @@ function build (opts) {
|
||||
}
|
||||
}
|
||||
|
||||
if (xRatio == null) { xRatio = yRatio; }
|
||||
if (yRatio == null) { yRatio = xRatio; }
|
||||
if (isNullish(xRatio)) { xRatio = yRatio; }
|
||||
if (isNullish(yRatio)) { yRatio = xRatio; }
|
||||
|
||||
e.attribute('width', true).value = svg.opts.scaleWidth;
|
||||
e.attribute('height', true).value = svg.opts.scaleHeight;
|
||||
|
||||
@@ -158,9 +158,9 @@ const colorDefs = [
|
||||
example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
|
||||
process (bits) {
|
||||
return [
|
||||
parseInt(bits[1], 10),
|
||||
parseInt(bits[2], 10),
|
||||
parseInt(bits[3], 10)
|
||||
parseInt(bits[1]),
|
||||
parseInt(bits[2]),
|
||||
parseInt(bits[3])
|
||||
];
|
||||
}
|
||||
},
|
||||
@@ -279,8 +279,7 @@ export default class RGBColor {
|
||||
margin: 3px;
|
||||
border: 1px solid black;
|
||||
background: ${listColor.toHex()};
|
||||
color: ${listColor.toHex()};`
|
||||
;
|
||||
color: ${listColor.toHex()};`;
|
||||
exampleDiv.append('test');
|
||||
const listItemValue = ` ${examples[i]} -> ${listColor.toRGB()} -> ${listColor.toHex()}`;
|
||||
listItem.append(exampleDiv, listItemValue);
|
||||
|
||||
Reference in New Issue
Block a user