diff options
Diffstat (limited to 'experimental/docs/svgBackend.js')
-rw-r--r-- | experimental/docs/svgBackend.js | 246 |
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); +} |