aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/docs/svgBackend.js
diff options
context:
space:
mode:
Diffstat (limited to 'experimental/docs/svgBackend.js')
-rw-r--r--experimental/docs/svgBackend.js246
1 files changed, 246 insertions, 0 deletions
diff --git a/experimental/docs/svgBackend.js b/experimental/docs/svgBackend.js
new file mode 100644
index 0000000000..b5907f0340
--- /dev/null
+++ b/experimental/docs/svgBackend.js
@@ -0,0 +1,246 @@
+var svgCache;
+var svgDefs;
+var svgGradients;
+var svgNS = "http://www.w3.org/2000/svg";
+var svgRoot;
+
+function displaySvg(displayList) {
+ for (var index = 0; index < displayList.length; ++index) {
+ drawToSvg(displayList[index]);
+ }
+}
+
+function drawToSvg(display) {
+ assert('string' == typeof(display.ref));
+ var cache;
+ if (display.ref in svgCache) {
+ cache = svgCache[display.ref];
+ if (display.drawDirty) {
+ switch (cache.spec) {
+ case "paths":
+ svgSetPathData(cache.element, display.draw);
+ break;
+ case "pictures":
+ svgSetPictureData(cache.element, display.draw);
+ break;
+ case "text":
+ svgCreateText(cache.element, display.draw);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ } else {
+ cache = {};
+ cache.action = display;
+ cache.spec = display.drawSpec;
+ var dot = cache.spec.indexOf(".");
+ if (dot > 0) {
+ cache.spec = cache.spec.substring(0, dot);
+ }
+ switch (cache.spec) {
+ case "paths":
+ cache.element = svgCreatePath(display.ref, display.draw);
+ break;
+ case "pictures":
+ cache.element = svgCreatePicture(display.ref, display.draw);
+ break;
+ case "text":
+ cache.element = svgCreateText(display.ref, display.draw);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ display.drawDirty = false;
+ if (display.paintDirty) {
+ svgSetPaintData(cache.element, display.paint);
+ var opacity = svg_opacity(display.paint.color);
+ cache.element.setAttribute("fill-opacity", opacity);
+ cache.element.setAttribute("stroke-opacity", opacity);
+ display.paintDirty = false;
+ }
+ assert('object' == typeof(cache));
+ if (!(display.ref in svgCache)) {
+ svgRoot.appendChild(cache.element);
+ svgCache[display.ref] = cache;
+ }
+}
+
+function setupSvg() {
+ svgCache = { "paths":{}, "pictures":{}, "text":{} };
+ svgDefs = document.createElementNS(svgNS, "defs");
+ svgGradients = {};
+ svgRoot = document.getElementById("svg");
+ while (svgRoot.lastChild) {
+ svgRoot.removeChild(svgRoot.lastChild);
+ }
+ svgRoot.appendChild(svgDefs);
+}
+
+function svg_rbg(color) {
+ return "rgb(" + ((color >> 16) & 0xFF)
+ + "," + ((color >> 8) & 0xFF)
+ + "," + ((color >> 0) & 0xFF) + ")";
+}
+
+function svg_opacity(color) {
+ return ((color >> 24) & 0xFF) / 255.0;
+}
+
+function svgCreatePath(key, path) {
+ var svgPath = document.createElementNS(svgNS, "path");
+ svgPath.setAttribute("id", key);
+ svgSetPathData(svgPath, path);
+ return svgPath;
+}
+
+function svgCreatePicture(key, picture) {
+ var svgPicture = document.createElementNS(svgNS, "g");
+ svgPicture.setAttribute("id", key);
+ svgSetPictureData(svgPicture, picture);
+ return svgPicture;
+}
+
+function svgCreateRadialGradient(key) {
+ var g = gradients[key];
+ var e = document.createElementNS(svgNS, "radialGradient");
+ e.setAttribute("id", key);
+ e.setAttribute("cx", g.cx);
+ e.setAttribute("cy", g.cy);
+ e.setAttribute("r", g.r);
+ e.setAttribute("gradientUnits", "userSpaceOnUse");
+ var stopLen = g.stops.length;
+ for (var index = 0; index < stopLen; ++index) {
+ var stop = g.stops[index];
+ var color = svg_rbg(stop.color);
+ var s = document.createElementNS(svgNS, 'stop');
+ s.setAttribute("offset", stop.offset);
+ var style = "stop-color:" + svg_rbg(stop.color) + "; stop-opacity:"
+ + svg_opacity(stop.color);
+ s.setAttribute("style", style);
+ e.appendChild(s);
+ }
+ svgGradients[key] = e;
+ svgDefs.appendChild(e);
+}
+
+function svgCreateText(key, text) {
+ var svgText = document.createElementNS(svgNS, "text");
+ svgText.setAttribute("id", key);
+ var textNode = document.createTextNode(text.string);
+ svgText.appendChild(textNode);
+ svgSetTextData(svgText, text);
+ return svgText;
+}
+
+function svgSetPathData(svgPath, path) {
+ var dString = "";
+ for (var cIndex = 0; cIndex < path.length; ++cIndex) {
+ var curveKey = Object.keys(path[cIndex])[0];
+ var v = path[cIndex][curveKey];
+ switch (curveKey) {
+ case 'arcTo':
+ var clockwise = 1; // to do; work in general case
+ dString += " A" + v[4] + "," + v[4] + " 0 0," + clockwise + " "
+ + v[2] + "," + v[3];
+ break;
+ case 'close':
+ dString += " z";
+ break;
+ case 'cubic':
+ dString += " M" + v[0] + "," + v[1];
+ dString += " C" + v[2] + "," + v[3]
+ + " " + v[4] + "," + v[5]
+ + " " + v[6] + "," + v[7];
+ break;
+ case 'line':
+ dString += " M" + v[0] + "," + v[1];
+ dString += " L" + v[2] + "," + v[3];
+ break;
+ case 'quad':
+ dString += " M" + v[0] + "," + v[1];
+ dString += " Q" + v[2] + "," + v[3]
+ + " " + v[4] + "," + v[5];
+ break;
+ default:
+ assert(0);
+ }
+ }
+ svgPath.setAttribute("d", dString);
+}
+
+function svgSetPaintData(svgElement, paint) {
+ var color;
+ var inPicture = 'string' == typeof(paint);
+ if (inPicture) {
+ paint = (new Function("return " + paint))();
+ assert('object' == typeof(paint) && !isArray(paint));
+ }
+ if ('gradient' in paint) {
+ var gradient = paint.gradient.split('.');
+ var gradName = gradient[1];
+ if (!svgGradients[gradName]) {
+ svgCreateRadialGradient(gradName);
+ }
+ color = "url(#" + gradName + ")";
+ } else {
+ color = svg_rbg(paint.color);
+ }
+ svgElement.setAttribute("fill", 'fill' == paint.style ? color : "none");
+ if ('stroke' == paint.style) {
+ svgElement.setAttribute("stroke", color);
+ }
+ if ('strokeWidth' in paint) {
+ svgElement.setAttribute("stroke-width", paint.strokeWidth);
+ }
+ if ('typeface' in paint) {
+ var typeface = typefaces[paint.typeface];
+ var font = typeface.style;
+ if ('textSize' in paint) {
+ svgElement.setAttribute("font-size", paint.textSize);
+ }
+ if ('family' in typeface) {
+ svgElement.setAttribute("font-family", typeface.family);
+ }
+ if ('textAlign' in paint) {
+ svgElement.setAttribute("text-anchor", paint.textAlign == "right" ? "end" : assert(0));
+ }
+ if ('textBaseline' in paint) {
+ svgElement.setAttribute("alignment-baseline", paint.textBaseline);
+ }
+ }
+}
+
+function svgSetPictureData(svgPicture, picture) {
+ while (svgPicture.lastChild) {
+ svgPicture.removeChild(svgPicture.lastChild);
+ }
+ for (var index = 0; index < picture.length; ++index) {
+ var entry = picture[index];
+ var drawObj = (new Function("return " + entry.draw))();
+ var drawSpec = entry.draw.split('.');
+ var svgElement;
+ switch (drawSpec[0]) {
+ case 'paths':
+ svgElement = svgCreatePath(drawSpec[1], drawObj);
+ break;
+ case 'pictures':
+ svgElement = svgCreatePicture(drawSpec[1], drawObj);
+ break;
+ case 'text':
+ svgElement = svgCreateText(drawSpec[1], drawObj);
+ break;
+ default:
+ assert(0);
+ }
+ var paintObj = (new Function("return " + entry.paint))();
+ svgSetPaintData(svgElement, paintObj);
+ svgPicture.appendChild(svgElement);
+ }
+}
+
+function svgSetTextData(svgElement, text) {
+ svgElement.setAttribute('x', text.x);
+ svgElement.setAttribute('y', text.y);
+}