_display: defaultDisplay,
_fill: defaultFill,
_fontFamily: defaultFontFamily,
_fontSize: defaultFontSize,
_fontStyle: defaultFontStyle,
_fontWeight: defaultFontWeight,
_opacity: defaultOpacity,
_stroke: defaultStroke,
_strokeLinecap: defaultStrokeLinecap,
_strokeLinejoin: defaultStrokeLinejoin,
_strokeWidth: defaultStrokeWidth,
_textAnchor: defaultTextAnchor
});
}
function popDefault () {
let t = defaultStack.pop ();
defaultAlignmentBaseline = t._alignmentBaseline;
defaultDisplay = t._display;
defaultFill = t._fill;
defaultFontFamily = t._fontFamily;
defaultFontSize = t._fontSize;
defaultFontStyle = t._fontStyle;
defaultFontWeight = t._fontWeight;
defaultOpacity = t._opacity;
defaultStroke = t._stroke;
defaultStrokeLinecap = t._strokeLinecap;
defaultStrokeLinejoin = t._strokeLinejoin;
defaultStrokeWidth = t._strokeWidth;
defaultTextAnchor = t._textAnchor;
}
function setDefaultAlignmentBaseline (alignmentBaseline) {
defaultAlignmentBaseline = alignmentBaseline;
}
function setDefaultDisplay (display) {
defaultDisplay = display;
}
function setDefaultFill (fill) {
defaultFill = fill;
}
function setDefaultFontFamily (fontFamily) {
defaultFontFamily = fontFamily;
}
function setDefaultFontSize (fontSize) {
defaultFontSize = fontSize;
}
function setDefaultFontStyle (fontStyle) {
defaultFontStyle = fontStyle;
}
function setDefaultFontWeight (fontWeight) {
defaultFontWeight = fontWeight;
}
function setDefaultOpacity (opacity) {
defaultOpacity = opacity;
}
function setDefaultStroke (stroke) {
defaultStroke = stroke;
}
function setDefaultStrokeLinecap (strokeLinecap) {
defaultStrokeLinecap = strokeLinecap;
}
function setDefaultStrokeLinejoin (strokeLinejoin) {
defaultStrokeLinejoin = strokeLinejoin;
}
function setDefaultStrokeWidth (strokeWidth) {
defaultStrokeWidth = strokeWidth;
}
function setDefaultTextAnchor (textAnchor) {
defaultTextAnchor = textAnchor;
}
function setAlignmentBaseline (o, alignmentBaseline) {
if (alignmentBaseline !== null) {
nsSetAttr (o, null, "alignment-baseline", alignmentBaseline);
}
return o;
}
function setDisplay (o, display) {
if (display !== null) {
nsSetAttr (o, null, "display", display);
}
return o;
}
function setFill (o, fill) {
if (fill !== null) {
nsSetAttr (o, null, "fill", fill);
}
return o;
}
function setFontFamily (o, fontFamily) {
if (fontFamily !== null) {
nsSetAttr (o, null, "font-family", fontFamily);
}
return o;
}
function setFontSize (o, fontSize) {
if (!isNaN (fontSize)) {
nsSetAttr (o, null, "font-size", fontSize);
}
return o;
}
function setFontStyle (o, fontStyle) {
if (fontStyle !== null) {
nsSetAttr (o, null, "font-style", fontStyle);
}
return o;
}
function setFontWeight (o, fontWeight) {
if (fontWeight !== null) {
nsSetAttr (o, null, "font-weight", fontWeight);
}
return o;
}
function setOpacity (o, opacity) {
if (!isNaN (opacity)) {
nsSetAttr (o, null, "opacity", opacity);
}
return o;
}
function setStroke (o, stroke) {
if (stroke !== null) {
nsSetAttr (o, null, "stroke", stroke);
}
return o;
}
function setStrokeLinecap (o, strokeLinecap) {
if (strokeLinecap !== null) {
nsSetAttr (o, null, "stroke-linecap", strokeLinecap);
}
return o;
}
function setStrokeLinejoin (o, strokeLinejoin) {
if (strokeLinejoin !== null) {
nsSetAttr (o, null, "stroke-linejoin", strokeLinejoin);
}
return o;
}
function setStrokeWidth (o, strokeWidth) {
if (!isNaN (strokeWidth)) {
nsSetAttr (o, null, "stroke-width", strokeWidth);
}
return o;
}
function setTextAnchor (o, textAnchor) {
if (textAnchor !== null) {
nsSetAttr (o, null, "text-anchor", textAnchor);
}
return o;
}
function createArc (cx, cy, rx, ry, ta, tb, tc, closed) {
return (
setStrokeWidth (
setStroke (
setFill (
moveArc (nsCreateNode (SVGNS, "path"), cx, cy, rx, ry, ta, tb, tc, closed),
defaultFill),
defaultStroke),
defaultStrokeWidth)
);
}
function moveArc (o, cx, cy, rx, ry, ta, tb, tc, closed) {
if (tb < ta) {
let t = ta;
ta = tb;
tb = t;
}
tb = min2 (tb - ta, TWOPI) + ta;
let xa = cos (ta) * rx;
let ya = sin (ta) * ry;
let xb = cos (tb) * rx;
let yb = sin (tb) * ry;
if (tc) {
let c = cos (tc);
let s = sin (tc);
let t;
t = c * xa - s * ya;
ya = s * xa + c * ya;
xa = t;
t = c * xb - s * yb;
yb = s * xb + c * yb;
xb = t;
}
let a = ["M",cx + xa, cy + ya,
"A", rx, ry, deg (tc), tb - ta <= PI ? 0 : 1, 1, cx + xb, cy + yb];
if (closed) {
a.push ("L", cx, cy, "Z");
}
return nsSetAttr (o, null, "d", a.join (" "));
}
function createCircle (cx, cy, r) {
return (
setStrokeWidth (
setStroke (
setFill (
moveCircle (nsCreateNode (SVGNS, "circle"), cx, cy, r),
defaultFill),
defaultStroke),
defaultStrokeWidth)
);
}
function moveCircle (o, cx, cy, r) {
return nsSetAttr (o, null, "cx", cx, "cy", cy, "r", r);
}
function createDefs () {
return nsCreateNode (SVGNS, "defs");
}
function createEllipse (cx, cy, rx, ry) {
return (
setStrokeWidth (
setStroke (
setFill (
moveCircle (nsCreateNode (SVGNS, "ellipse"), cx, cy, rx, ry),
defaultFill),
defaultStroke),
defaultStrokeWidth)
);
}
function moveEllipse (o, cx, cy, rx, ry) {
return nsSetAttr (o, null, "cx", cx, "cy", cy, "rx", rx, "ry", ry);
}
function createG () {
return nsCreateNode (SVGNS, "g");
}
function createLine (x1, y1, x2, y2) {
return (
setStrokeWidth (
setStrokeLinejoin (
setStrokeLinecap (
setStroke (
moveLine (nsCreateNode (SVGNS, "line"), x1, y1, x2, y2),
defaultStroke),
defaultStrokeLinecap),
defaultStrokeLinejoin),
defaultStrokeWidth)
);
}
function moveLine (o, x1, y1, x2, y2) {
return nsSetAttr (o, null, "x1", x1, "y1", y1, "x2", x2, "y2", y2);
}
function createPath (d) {
return (
setStrokeWidth (
setStrokeLinejoin (
setStrokeLinecap (
setStroke (
setFill (
movePath (nsCreateNode (SVGNS, "path"), d),
defaultFill),
defaultStroke),
defaultStrokeLinecap),
defaultStrokeLinejoin),
defaultStrokeWidth)
);
}
function movePath (o, d) {
return nsSetAttr (o, null, "d", d);
}
function createPolygon (points) {
return (
setStrokeWidth (
setStroke (
setFill (
movePolygon (nsCreateNode (SVGNS, "polygon"), points),
defaultFill),
defaultStroke),
defaultStrokeWidth)
);
}
function movePolygon (o, points) {
return nsSetAttr (o, null, "points", points);
}
function createPolyline (points) {
return (
setStrokeWidth (
setStrokeLinejoin (
setStrokeLinecap (
setStroke (
movePolyline (nsCreateNode (SVGNS, "polyline"), points),
defaultStroke),
defaultStrokeLinecap),
defaultStrokeLinejoin),
defaultStrokeWidth)
);
}
function movePolyline (o, points) {
return nsSetAttr (o, null, "points", points);
}
function createRadialGradient (elementId, a) {
let gradientElement = nsSetAttr (nsCreateNode (SVGNS, "radialGradient"), null,
"id", elementId);
for (let i = 0, l = a.length; i < l; i += 2) {
appendNode (gradientElement,
nsSetAttr (nsCreateNode (SVGNS, "stop"), null,
"offset", a[i],
"stop-color", a[i + 1]));
}
return gradientElement;
}
function createRect (x, y, width, height) {
return (
setStrokeWidth (
setStroke (
setFill (
moveRect (nsCreateNode (SVGNS, "rect"), x, y, width, height),
defaultFill),
defaultStroke),
defaultStrokeWidth)
);
}
function createRoundRect (x, y, width, height, rx, ry) {
return (
setStrokeWidth (
setStroke (
setFill (
moveRoundRect (nsCreateNode (SVGNS, "rect"), x, y, width, height, rx, ry),
defaultFill),
defaultStroke),
defaultStrokeWidth)
);
}
function moveRect (o, x, y, width, height) {
return nsSetAttr (o, null, "x", x, "y", y, "width", width, "height", height);
}
function moveRoundRect (o, x, y, width, height, rx, ry) {
return nsSetAttr (o, null, "x", x, "y", y, "width", width, "height", height, "rx", rx, "ry", ry);
}
function createText (x, y, text) {
return (
setFontWeight (
setFontStyle (
setFontSize (
setFontFamily (
setFill (
setAlignmentBaseline (
appendNode (moveText (nsCreateNode (SVGNS, "text"), x, y), text),
defaultAlignmentBaseline),
defaultFill),
defaultFontFamily),
defaultFontSize),
defaultFontStyle),
defaultFontWeight)
);
}
function moveText (o, x, y) {
return nsSetAttr (o, null, "x", x, "y", y);
}
function setText (o, text) {
o.firstChild.nodeValue = text;
return o;
}
const COLOR_NAMES = {
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",
darkkhaki: "#BDB76B",
darkmagenta: "#8B008B",
darkolivegreen: "#556B2F",
darkorange: "#FF8C00",
darkorchid: "#9932CC",
darkred: "#8B0000",
darksalmon: "#E9967A",
darkseagreen: "#8FBC8F",
darkslateblue: "#483D8B",
darkslategray: "#2F4F4F",
darkturquoise: "#00CED1",
darkviolet: "#9400D3",
deeppink: "#FF1493",
deepskyblue: "#00BFFF",
dimgray: "#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",
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",
lightgreen: "#90EE90",
lightgrey: "#D3D3D3",
lightpink: "#FFB6C1",
lightsalmon: "#FFA07A",
lightseagreen: "#20B2AA",
lightskyblue: "#87CEFA",
lightslategray: "#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",
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"
};
function RGBtoColor (rgb) {
let r = max2 (0, min2 (255, floor (rgb[0] * 255 + 0.5)));
let g = max2 (0, min2 (255, floor (rgb[1] * 255 + 0.5)));
let b = max2 (0, min2 (255, floor (rgb[2] * 255 + 0.5)));
let a = rgb.length == 3 ? 1 : max2 (0, min2 (1, rgb[3]));
return (a == 1 ?
"rgb(" + r + "," + g + "," + b + ")" :
"rgba(" + r + "," + g + "," + b + "," + a + ")");
}
function colorToRGB (color) {
if (COLOR_NAMES[color]) {
color = COLOR_NAMES[color];
}
if (color[0] == "#") {
if (color.length == 3) {
let t = parseInt (color.substring (1, 4), 16);
return [(t >> 8) / 15, (t >> 4 & 15) / 15, (t & 15) / 15];
} else if (color.length == 7) {
let t = parseInt (color.substring (1, 7), 16);
return [(t >> 16) / 255, (t >> 8 & 255) / 255, (t & 255) / 255];
}
} else if (color.substring (4) == "rgb(") {
let i = 4;
let j = color.indexOf (",", i);
if (i <= j) {
let r = max2 (0, min2 (1, parseInt (color.substring (i, j), 10) / 255));
i = j + 1;
j = color.indexOf (",", i);
if (i <= j) {
let g = max2 (0, min2 (1, parseInt (color.substring (i, j), 10) / 255));
i = j + 1;
j = color.indexOf (")", i);
if (i <= j) {
let b = max2 (0, min2 (1, parseInt (color.substring (i, j), 10) / 255));
return [r, g, b];
}
}
}
} else if (color.substring (5) == "rgba(") {
let i = 5;
let j = color.indexOf (",", i);
if (i <= j) {
let r = max2 (0, min2 (1, parseInt (color.substring (i, j), 10) / 255));
i = j + 1;
j = color.indexOf (",", i);
if (i <= j) {
let g = max2 (0, min2 (1, parseInt (color.substring (i, j), 10) / 255));
i = j + 1;
j = color.indexOf (",", i);
if (i <= j) {
let b = max2 (0, min2 (1, parseInt (color.substring (i, j), 10) / 255));
i = j + 1;
j = color.indexOf (")", i);
if (i <= j) {
let a = max2 (0, min2 (1, parseFloat (color.substring (i, j))));
return a == 1 ? [r, g, b] : [r, g, b, a];
}
}
}
}
}
return [0, 0, 0];
}
function vAngle (a, b) {
let ax = a[0], ay = a[1];
let bx = b[0], by = b[1];
return acos ((ax * bx + ay * by) / (hypot2 (ax, ay) * hypot2 (bx, by)));
}
function vAngleA (a, b, c) {
let ax = a[0], ay = a[1];
let bx = b[0], by = b[1];
let cx = c[0], cy = c[1];
bx -= ax;
by -= ay;
cx -= ax;
cy -= ay;
return acos ((bx * cx + by * cy) / (hypot2 (bx, by) * hypot2 (cx, cy)));
}
function vAreaOfTriangle (a, b, c) {
let ax = a[0], ay = a[1];
let bx = b[0], by = b[1];
let cx = c[0], cy = c[1];
bx -= ax;
by -= ay;
cx -= ax;
cy -= ay;
return 0.5 * abs (bx * cy - cx * by);
}
function vAzimuth (a) {
return atan2 (a[1], a[0]);
}
function vBisect (a, b) {
a[0] = (a[0] + b[0]) * 0.5;
a[1] = (a[1] + b[1]) * 0.5;
return a;
}
function vLetBisect (o, a, b) {
o[0] = (a[0] + b[0]) * 0.5;
o[1] = (a[1] + b[1]) * 0.5;
return o;
}