From 3257c12220c411cc9db564e6bf02baba4c1bc061 Mon Sep 17 00:00:00 2001 From: caryclark Date: Mon, 16 Nov 2015 13:36:08 -0800 Subject: runs some sample animations side by side in canvas and svg TBR=fmalita@chromium.org Review URL: https://codereview.chromium.org/1342523002 --- experimental/docs/animationCommon.js | 314 +++++ experimental/docs/backend.js | 44 + experimental/docs/canvasBackend.js | 167 +++ experimental/docs/exampleSlides.js | 564 +++++++++ experimental/docs/interpolatorFunctions.js | 84 ++ experimental/docs/jsonbaseddoc.htm | 41 + experimental/docs/svgBackend.js | 246 ++++ experimental/docs/svgbaseddoc.htm | 1712 ++++++++++++++++++++++++++++ experimental/docs/utilities.js | 24 + 9 files changed, 3196 insertions(+) create mode 100644 experimental/docs/animationCommon.js create mode 100644 experimental/docs/backend.js create mode 100644 experimental/docs/canvasBackend.js create mode 100644 experimental/docs/exampleSlides.js create mode 100644 experimental/docs/interpolatorFunctions.js create mode 100644 experimental/docs/jsonbaseddoc.htm create mode 100644 experimental/docs/svgBackend.js create mode 100644 experimental/docs/svgbaseddoc.htm create mode 100644 experimental/docs/utilities.js (limited to 'experimental/docs') diff --git a/experimental/docs/animationCommon.js b/experimental/docs/animationCommon.js new file mode 100644 index 0000000000..1733ec2032 --- /dev/null +++ b/experimental/docs/animationCommon.js @@ -0,0 +1,314 @@ +var animationState = {}; +animationState.reset = function (engine) { + if ('string' === typeof engine) { + this.defaultEngine = engine; + } + this.defaults = {}; + this.displayList = []; + this.displayDict = {}; + this.start = null; + this.time = 0; + this.timeline = []; + this.timelineIndex = 0; + this.requestID = null; + this.paused = false; + this.displayEngine = 'undefined' === typeof engine ? this.defaultEngine : engine; +} + +function addActions(frame, timeline) { + var keyframe = keyframes[frame]; + var len = keyframe.length; + for (var i = 0; i < len; ++i) { + var action = keyframe[i]; + loopOver(action, timeline); + } +} + +function animateList(now) { + if (animationState.paused) { + return; + } + if (animationState.start == null) { + animationState.start = now - animationState.time; + } + animationState.time = now - animationState.start; + var stillAnimating = false; + for (var index = animationState.timelineIndex; index < animationState.timeline.length; ++index) { + var animation = animationState.timeline[index]; + if (animation.time > animationState.time) { + stillAnimating = true; + break; + } + if (animation.time + animation.duration < animationState.time) { + if (animation.finalized) { + continue; + } + animation.finalized = true; + } + stillAnimating = true; + var actions = animation.actions; + for (var aIndex = 0; aIndex < actions.length; ++aIndex) { + var action = actions[aIndex]; + var hasDraw = 'draw' in action; + var hasRef = 'ref' in action; + var displayIndex; + if (hasDraw) { + var ref = hasRef ? action.ref : "anonymous_" + index + "_" + aIndex; + assert('string' == typeof(ref)); + if (ref in animationState.displayDict) { + displayIndex = animationState.displayDict[ref]; + } else { + assert('string' == typeof(action.draw)); + var draw = (new Function("return " + action.draw))(); + assert('object' == typeof(draw)); + var paint; + if ('paint' in action) { + assert('string' == typeof(action.paint)); + paint = (new Function("return " + action.paint))(); + assert('object' == typeof(paint) && !isArray(paint)); + } else { + paint = animationState.defaults.paint; + } + displayIndex = animationState.displayList.length; + animationState.displayList.push( { "ref":ref, "draw":draw, "paint":paint, + "drawSpec":action.draw, "paintSpec":action.paint, + "drawCopied":false, "paintCopied":false, + "drawDirty":true, "paintDirty":true, "once":false } ); + animationState.displayDict[ref] = displayIndex; + } + } else if (hasRef) { + assert('string' == typeof(action.ref)); + displayIndex = animationState.displayDict[action.ref]; + } else { + assert(actions.length == 1); + for (var prop in action) { + if ('paint' == prop) { + assert('string' == typeof(action[prop])); + var obj = (new Function("return " + action[prop]))(); + assert('object' == typeof(obj) && !isArray(obj)); + animationState.defaults[prop] = obj; + } else { + animationState.defaults[prop] = action[prop]; + } + } + continue; + } + var targetSpec = 'target' in action ? action.target : animationState.defaults.target; + assert(targetSpec); + assert('string' == typeof(targetSpec)); + assert(displayIndex < animationState.displayList.length); + var display = animationState.displayList[displayIndex]; + var modDraw = targetSpec.startsWith('draw'); + assert(modDraw || targetSpec.startsWith('paint')); + var modType = modDraw ? "draw" : "paint"; + var copied = modDraw ? display.drawCopied : action.paintCopied; + if (!copied) { + var copy; + if (!modDraw || display.drawSpec.startsWith("text")) { + copy = {}; + var original = modDraw ? display.draw : display.paint; + for (var p in original) { + copy[p] = original[p]; + } + } else if (display.drawSpec.startsWith("paths")) { + copy = []; + for (var i = 0; i < display.draw.length; ++i) { + var curves = display.draw[i]; + var curve = Object.keys(curves)[0]; + copy[i] = {}; + copy[i][curve] = curves[curve].slice(0); // clone the array of curves + } + } else { + assert(display.drawSpec.startsWith("pictures")); + copy = []; + for (var i = 0; i < display.draw.length; ++i) { + var entry = display.draw[i]; + copy[i] = { "draw":entry.draw, "paint":entry.paint }; + } + } + display[modType] = copy; + display[modType + "Copied"] = true; + } + var targetField, targetObject, fieldOffset; + if (targetSpec.endsWith("]")) { + fieldOffset = targetSpec.lastIndexOf("["); + assert(fieldOffset >= 0); + targetField = targetSpec.substring(fieldOffset + 1, targetSpec.length - 1); + var arrayIndex = +targetField; + if (!isNaN(arrayIndex) && targetField.length > 0) { + targetField = arrayIndex; + } + + } else { + fieldOffset = targetSpec.lastIndexOf("."); + if (fieldOffset >= 0) { + targetField = targetSpec.substring(fieldOffset + 1, targetSpec.length); + } else { + targetObject = display; + targetField = targetSpec; + } + } + if (fieldOffset >= 0) { + var sub = targetSpec.substring(0, fieldOffset); + targetObject = (new Function('display', "return display." + sub))(display); + } + assert(null != targetObject[targetField]); + if (!('start' in action) || action.start < animation.time) { + for (var p in animationState.defaults) { + if ('draw' == p || 'paint' == p || 'ref' == p) { + continue; + } + assert('range' == p || 'target' == p || 'formula' == p || 'params' == p); + if (!(p in action)) { + action[p] = animationState.defaults[p]; + } + } + if ('number' == typeof(action.formula)) { + targetObject[targetField] = action.formula; + action.once = true; + } + action.start = animation.time; + } + if (action.once) { + continue; + } + var value = Math.min(1, (animationState.time - animation.time) / animation.duration); + var scaled = action.range[0] + (action.range[1] - action.range[0]) * value; + if ('params' in action) { + if (!('func' in action)) { + if (isArray(action.params)) { + action.funcParams = []; + var len = action.params.length; + for (var i = 0; i < len; ++i) { + action.funcParams[i] = 'target' == action.params[i] + ? targetObject[targetField] + : (new Function("return " + action.params[i]))(); + } + } else { + action.funcParams = 'target' == action.params + ? targetObject[targetField] + : (new Function("return " + action.params))(); + } + assert('formula' in action && 'string' == typeof(action.formula)); + // evaluate inline function to get value + action.func = new Function('value', 'params', "return " + action.formula); + } + scaled = action.func(scaled, action.funcParams); + } + if (targetObject[targetField] != scaled) { + if (modDraw) { + display.drawDirty = true; + } else { + display.paintDirty = true; + } + targetObject[targetField] = scaled; + } + } + } + displayBackend(animationState.displayEngine, animationState.displayList); + + if (stillAnimating) { + animationState.requestID = requestAnimationFrame(animateList); + } +} + +function flattenPaint(paint) { + if (!paint.paint) { + return; + } + var parent = paints[paint.paint]; + flattenPaint(parent); + for (var prop in parent) { + if (!(prop in paint)) { + paint[prop] = parent[prop]; + } + } + paint.paint = null; +} + +function init(engine, keyframe) { + animationState.reset(engine); + setupPaint(); + setupBackend(animationState.displayEngine); + keyframeInit(keyframe); +} + +function keyframeInit(frame) { + animationState.reset(); + addActions("_default", animationState.timeline); + addActions(frame, animationState.timeline); + for (var index = 0; index < animationState.timeline.length; ++index) { + animationState.timeline[index].position = index; + } + animationState.timeline.sort(function(a, b) { + if (a.time == b.time) { + return a.position - b.position; + } + return a.time - b.time; + }); + keyframeBackendInit(animationState.displayEngine, animationState.displayList, + keyframes[frame][0]); + animationState.requestID = requestAnimationFrame(animateList); +} + +function loopAddProp(action, propName) { + var funcStr = ""; + var prop = action[propName]; + if ('draw' != propName && isArray(prop)) { + funcStr += '['; + for (var index = 0; index < prop.length; ++index) { + funcStr += loopAddProp(prop, index); + if (index + 1 < prop.length) { + funcStr += ", "; + } + } + funcStr += ']'; + return funcStr; + } + assert("object" != typeof(prop)); + var useString = "string" == typeof(prop) && isAlpha(prop.charCodeAt(0)); + if (useString) { + funcStr += "'"; + } + funcStr += prop; + if (useString) { + funcStr += "'"; + } + return funcStr; +} + +function loopOver(rec, timeline) { + var funcStr = ""; + if (rec.for) { + funcStr += "for (" + rec.for[0] + "; " + rec.for[1] + "; " + rec.for[2] + ") {\n"; + } + funcStr += " var time = " + ('time' in rec ? rec.time : 0) + ";\n"; + funcStr += " var duration = " + ('duration' in rec ? rec.duration : 0) + ";\n"; + funcStr += " var actions = [];\n"; + var len = rec.actions.length; + for (var i = 0; i < len; ++i) { + funcStr += " var action" + i + " = {\n"; + var action = rec.actions[i]; + for (var p in action) { + funcStr += " '" + p + "':"; + funcStr += loopAddProp(action, p); + funcStr += ",\n"; + } + funcStr = funcStr.substring(0, funcStr.length - 2); + funcStr += "\n };\n"; + funcStr += " actions.push(action" + i + ");\n"; + } + funcStr += " timeline.push( { 'time':time, 'duration':duration, 'actions':actions," + + "'finalized':false } );\n"; + if (rec.for) { + funcStr += "}\n"; + } + var func = new Function('rec', 'timeline', funcStr); + func(rec, timeline); +} + +function setupPaint() { + for (var prop in paints) { + flattenPaint(paints[prop]); + } +} diff --git a/experimental/docs/backend.js b/experimental/docs/backend.js new file mode 100644 index 0000000000..efb8e52ef0 --- /dev/null +++ b/experimental/docs/backend.js @@ -0,0 +1,44 @@ +function displayBackend(displayEngine, displayList) { + switch (displayEngine) { + case 'all': + displayCanvas(displayList); + displaySvg(displayList); + break; + case 'Canvas': + displayCanvas(displayList); + break; + case 'SVG': + displaySvg(displayList); + break; + default: + assert(0); + } +} + +function keyframeBackendInit(displayEngine, displayList, first) { + switch (displayEngine) { + case 'all': + case 'Canvas': + keyframeCanvasInit(displayList, first); + break; + case 'SVG': + break; + default: + assert(0); + } +} + +function setupBackend(displayEngine) { + switch (displayEngine) { + case 'all': + case 'Canvas': + setupCanvas(); + setupSvg(); + break; + case 'SVG': + setupSvg(); + break; + default: + assert(0); + } +} diff --git a/experimental/docs/canvasBackend.js b/experimental/docs/canvasBackend.js new file mode 100644 index 0000000000..0574813f22 --- /dev/null +++ b/experimental/docs/canvasBackend.js @@ -0,0 +1,167 @@ +var canvas; +var ctx; +var canvasGradients = {}; + +function canvas_rbga(color) { + var a = canvas_opacity(color); + var r = (color >> 16) & 0xFF; + var g = (color >> 8) & 0xFF; + var b = (color >> 0) & 0xFF; + return "rgba(" + r + "," + g + "," + b + "," + a + ")"; +} + +function canvas_opacity(color) { + var a = (color >> 24) & 0xFF; + return a / 255.; +} + +function displayCanvas(displayList) { + if (displayList.clear) { + ctx.clearRect(0, 0, canvas.width, canvas.height); + } + for (var index = 0; index < displayList.length; ++index) { + drawToCanvas(displayList[index]); + } +} + +function drawToCanvas(action) { + ctx.save(); + var paint = paintToCanvas(action.paint); + var draw = action.draw; + if ('string' == typeof(draw)) { + draw = (new Function("return " + draw))(); + } + if (isArray(draw)) { + assert(draw.length > 0); + var picture = 'draw' in draw[0]; + if (picture) { + for (var index = 0; index < draw.length; ++index) { + drawToCanvas(draw[index]); + } + return; + } + ctx.beginPath(); + for (var index = 0; index < draw.length; ++index) { + for (var prop in draw[index]) { + var v = draw[index][prop]; + switch (prop) { + case 'arcTo': + ctx.arcTo(v[0], v[1], v[2], v[3], v[4]); + break; + case 'close': + ctx.closePath(); + break; + case 'cubic': + ctx.moveTo(v[0], v[1]); + ctx.bezierCurveTo(v[2], v[3], v[4], v[5], v[6], v[7]); + break; + case 'line': + ctx.moveTo(v[0], v[1]); + ctx.lineTo(v[2], v[3]); + break; + case 'quad': + ctx.moveTo(v[0], v[1]); + ctx.quadraticCurveTo(v[2], v[3], v[4], v[5]); + break; + default: + assert(0); + } + } + } + if ('fill' == paint.style) { + ctx.fill(); + } else { + assert('stroke' == paint.style); + ctx.stroke(); + } + } else { + assert('string' in draw); + if ('fill' == paint.style) { + ctx.fillText(draw.string, draw.x, draw.y); + } else { + assert('stroke' == paint.style); + ctx.strokeText(draw.string, draw.x, draw.y); + } + } + ctx.restore(); +} + +function keyframeCanvasInit(displayList, first) { + if ('canvas' in first && 'clear' == first.canvas) { + displayList.clear = true; + } +} + +function paintToCanvas(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 (!canvasGradients[gradName]) { + var g = window[gradient[0]][gradient[1]]; + var grad = ctx.createRadialGradient(g.cx, g.cy, 0, g.cx, g.cy, g.r); + var stopLen = g.stops.length; + for (var index = 0; index < stopLen; ++index) { + var stop = g.stops[index]; + var color = canvas_rbga(stop.color); + grad.addColorStop(index, color); + } + canvasGradients[gradName] = grad; + } + color = canvasGradients[gradName]; + if (!inPicture) { + ctx.globalAlpha = canvas_opacity(paint.color); + } + } else { + color = canvas_rbga(paint.color); + } + if ('fill' == paint.style) { + ctx.fillStyle = color; + } else if ('stroke' == paint.style) { + ctx.strokeStyle = color; + } else { + ctx.globalAlpha = canvas_opacity(paint.color); + } + if ('strokeWidth' in paint) { + ctx.lineWidth = paint.strokeWidth; + } + if ('typeface' in paint) { + var typeface = typefaces[paint.typeface]; + var font = typeface.style; + if ('textSize' in paint) { + font += " " + paint.textSize; + } + if ('family' in typeface) { + font += " " + typeface.family; + } + ctx.font = font; + if ('textAlign' in paint) { + ctx.textAlign = paint.textAlign; + } + if ('textBaseline' in paint) { + ctx.textBaseline = paint.textBaseline; + } + } + return paint; +} + +function setupCanvas() { + canvas = document.getElementById("canvas"); + ctx = canvas ? canvas.getContext("2d") : null; + assert(ctx); + var resScale = window.devicePixelRatio ? window.devicePixelRatio : 1; + var unscaledWidth = canvas.width; + var unscaledHeight = canvas.height; + canvas.width = unscaledWidth * resScale; + canvas.height = unscaledHeight * resScale; + canvas.style.width = unscaledWidth + 'px'; + canvas.style.height = unscaledHeight + 'px'; + if (resScale != 1) { + ctx.scale(resScale, resScale); + } +} diff --git a/experimental/docs/exampleSlides.js b/experimental/docs/exampleSlides.js new file mode 100644 index 0000000000..d1a10b6985 --- /dev/null +++ b/experimental/docs/exampleSlides.js @@ -0,0 +1,564 @@ +var circle = { + "center":{ "x":200, "y":200 }, + "radius":100 +} + +var gradients = { + "grad1": { "cx":200, "cy":200, "r":300, + "stops": [ + { "offset":0, "color": argb(76,0,0,255) }, + { "offset":1, "color": argb( 0,0,0,255) } + ] + }, + "grad2": { "cx":200, "cy":200, "r":300, + "stops": [ + { "offset":0, "color": argb(76,0,255,0) }, + { "offset":1, "color": argb( 0,0,255,0) } + ] + }, + "grad3": { "cx":200, "cy":200, "r":300, + "stops": [ + { "offset":0, "color": argb(76,255,0,0) }, + { "offset":1, "color": argb( 0,255,0,0) } + ] + }, + "grad4": { "cx":200, "cy":200, "r":300, + "stops": [ + { "offset":0, "color": argb(76,192,63,192) }, + { "offset":1, "color": argb( 0,192,63,192) } + ] + }, + "grad5": { "cx":200, "cy":200, "r":300, + "stops": [ + { "offset":0, "color": argb(76,127,127,0) }, + { "offset":1, "color": argb( 0,127,127,0) } + ] + }, + "grad6": { "cx":200, "cy":200, "r":300, + "stops": [ + { "offset":0, "color": argb(76,127,0,127) }, + { "offset":1, "color": argb( 0,127,0,127) } + ] + }, + "grad7": { "cx":200, "cy":200, "r":300, + "stops": [ + { "offset":0, "color": argb(76,0,127,127) }, + { "offset":1, "color": argb( 0,0,127,127) } + ] + }, + "grad8": { "cx":200, "cy":200, "r":300, + "stops": [ + { "offset":0, "color": argb(76,63,192,63) }, + { "offset":1, "color": argb( 0,63,192,63) } + ] + } +}; + +var paths = { + "cubicSegment1": [ + { "cubic": [ 200,200, 200,200, 200,200, 200,200 ] } + ], + "cubicSegment2": [ + { "cubic": [ 200,200, 250,200, 300,200, 300,100 ] } + ], + "curveSegment1": [ + { "cubic": [ 200,200, 250,200, 300,150, 300,100 ] } + ], + "curveSegment2": [ + { "cubic": [ 200,200, 250,200, 300,150, 200,100 ] } + ], + "curveSegment3": [ + { "cubic": [ 200,200, 350,200, 250,-150, 170,300 ] } + ], + "diagSegment": [ + { "line": [ 200,200, 100,100 ] } + ], + "horzSegment": [ + { "line": [ 200,200, 341.4,200 ] } + ], + "lineSegment": [ + { "line": [ 200,200, 200 + circle.radius * Math.cos(-22.5 * Math.PI / 180), + 200 + circle.radius * Math.sin(-22.5 * Math.PI / 180) ] } + ], + "span1": [ + { "quad": [ 200,200, 300,300, 200,300 ] } + ], + "span2": [ + { "cubic": [ 200,200, 100,300, 100,400, 200,300 ] } + ], + "span3": [ + { "cubic": [ 200,200, 300,100, 100,400, 300,200 ] } + ], + "span4": [ + { "quad": [ 200,200, 300,300, 400,300 ] } + ], + "span5": [ + { "quad": [ 200,200, 280,320, 200,400 ] } + ], + "span6": [ + { "quad": [ 200,200, 60,340, 100,400 ] } + ], + "vertSegment": [ + { "line": [ 200,200, 200,341.4 ] } + ], + "wedge1": [ + { "line": [ 200,200, 500,500 ] }, + { "arcTo": [ 375.74,624.36, 200,624.26, 424.26 ] }, + { "close": null } + ], + "wedge2": [ + { "line": [ 200,200, 200,624.26 ] }, + { "arcTo": [ 24.265,624.26, -100,500, 424.26 ] }, + { "close": null } + ], + "wedge3": [ + { "line": [ 200,200, 500,-100 ] }, + { "arcTo": [ 1138.22,537.70, 240,622.5, 424.26 ] }, + { "close": null } + ], + "wedge4": [ + { "line": [ 200,200, 500,500 ] }, + { "arcTo": [ 530.79,438.42, 579.47,389.74, 424.26 ] }, + { "close": null } + ], + "wedge5": [ + { "line": [ 200,200, 389.74,579.47 ] }, + { "arcTo": [ 284.94,563.441, 200,500, 424.26 ] }, + { "close": null } + ], + "wedge6": [ + { "line": [ 200,200, 10.26,579.47 ] }, + { "arcTo": [ -51.318,548.68, -100,500, 424.26 ] }, + { "close": null } + ], + "wedgeXY1": [ + { "line": [ 200,200, 500,-100 ] }, + { "arcTo": [ 624.26,24.265, 624.26,200, 424.26 ] }, + { "close": null } + ], + "wedgeXY2": [ + { "line": [ 200,200, 200,-175.74 ] }, + { "arcTo": [ 364.83,-196.61, 500,-100, 424.26 ] }, + { "close": null } + ], + "wedgeXY3": [ + { "line": [ 200,200, -100,-100 ] }, + { "arcTo": [ 35.170,-196.61, 200,-175.74, 424.26 ] }, + { "close": null } + ], + "wedgeXY4": [ + { "line": [ 200,200, -175.74,200 ] }, + { "arcTo": [ -196.61,35.170, -100,-100, 424.26 ] }, + { "close": null } + ], + "wedgeXY5": [ + { "line": [ 200,200, -100,500 ] }, + { "arcTo": [ -196.61,364.83, -175.74,200, 424.26 ] }, + { "close": null } + ], + "wedgeXY6": [ + { "line": [ 200,200, -100,500 ] }, + { "arcTo": [ 75.735,500, 200,624.26, 424.26 ] }, + { "close": null } + ], + "wedgeXY7": [ + { "line": [ 200,200, 200,624.26 ] }, + { "arcTo": [ 324.26,500, 500,500, 424.26 ] }, + { "close": null } + ], + "wedgeXY8": [ + { "line": [ 200,200, 500,500 ] }, + { "arcTo": [ 500,324.26, 624.26,200, 424.26 ] }, + { "close": null } + ], + "xaxis": [ + { "line": [ 100,200, 300,200 ] } + ], + "yaxis": [ + { "line": [ 200,100, 200,300 ] } + ] +}; + +var text = { + "curve1d1": { + "string":"Some curves initially occupy", "x":400, "y":200 + }, + "curve1d2": { + "string":"one-dimensional sectors, then diverge.", "x":400, "y":240 + }, + "curveMultiple1": { + "string":"A curve span may cover more", "x":400, "y":200 + }, + "curveMultiple2": { + "string":"than one sector.", "x":400, "y":240 + }, + "line1DDest1": { + "string":"Some lines occupy one-dimensional", "x":400, "y":200 + }, + "line1DDest2": { + "string":"sectors.", "x":400, "y":240 + }, + "lineSingle": { + "string":"Line spans are contained by a single sector.", "x":400, "y":200 + }, + "sector1": { + "string":"A sector is a wedge of a circle", "x":400, "y":200 + }, + "sector2": { + "string":"containing a range of points.", "x":400, "y":240 + }, + "sectorXY1": { + "string":"X > 0 Y < 0 -Y < X", "x":500, "y":460 + }, + "sectorXY2": { + "string":"X > 0 Y < 0 -Y > X", "x":500, "y":460 + }, + "sectorXY3": { + "string":"X < 0 Y < 0 Y < X", "x":500, "y":460 + }, + "sectorXY4": { + "string":"X < 0 Y < 0 Y > X", "x":500, "y":460 + }, + "sectorXY5": { + "string":"X < 0 Y > 0 -Y > X", "x":500, "y":460 + }, + "sectorXY6": { + "string":"X < 0 Y > 0 -Y < X", "x":500, "y":460 + }, + "sectorXY7": { + "string":"X > 0 Y > 0 Y > X", "x":500, "y":460 + }, + "sectorXY8": { + "string":"X > 0 Y > 0 Y < X", "x":500, "y":460 + }, + "sectorXY9": { + "string":"X > 0 Y == 0", "x":500, "y":460 + }, + "sectorXY10": { + "string":"Y > 0 0 == X", "x":500, "y":460 + }, + "sectorXY11": { + "string":"X < 0 Y == X", "x":500, "y":460 + }, + "sectorXYA": { + "string":"X > 0 Y > 0 Y < X", "x":500, "y":310 + }, + "sectorXYB": { + "string":"X < 0 Y > 0 -Y < X", "x":500, "y":360 + }, + "sectorXYC": { + "string":"X < 0 Y < 0 Y < X", "x":500, "y":410 + }, + "spanWedge": { + "string":"All spans are contained by a wedge", "x":400, "y":200 + }, + "trivialWedge1": { + "string":"Wedges that don't overlap can be", "x":400, "y":200 + }, + "trivialWedge2": { + "string":"easily sorted.", "x":400, "y":240 + }, + "xaxis1": { + "string":"-X", "x":100, "y":220 + }, + "xaxis2": { + "string":"+X", "x":300, "y":220 + }, + "yaxis1": { + "string":"-Y", "x":205, "y":100 + }, + "yaxis2": { + "string":"+Y", "x":205, "y":300 + } +}; + +var typefaces = { + "description": { "style":"normal", "family":"Helvetica,Arial" } +}; + +var paints = { + "axisStroke": { "style":"stroke", "color":rgb(191,191,191) }, + "axisTextDesc": { "paint":"textBase", "color":rgb(191,191,191) }, + "axisTextRight": { "paint":"axisTextDesc", "textAlign":"right" }, + "axisTextTop": { "paint":"axisTextDesc", "textBaseline":"hanging" }, + "diagSegment": { "style":"stroke", "color":rgb(127,63,127), "strokeWidth":2 }, + "gradient1": { "style":"fill", "gradient":"gradients.grad1", "color":alpha(255) }, + "gradient2": { "paint":"gradient1", "gradient":"gradients.grad2" }, + "gradient3": { "paint":"gradient1", "gradient":"gradients.grad3" }, + "gradient4": { "paint":"gradient1", "gradient":"gradients.grad4" }, + "gradient5": { "paint":"gradient1", "gradient":"gradients.grad5" }, + "gradient6": { "paint":"gradient1", "gradient":"gradients.grad6" }, + "gradient7": { "paint":"gradient1", "gradient":"gradients.grad7" }, + "gradient8": { "paint":"gradient1", "gradient":"gradients.grad8" }, + "horzSegment": { "paint":"diagSegment", "color":rgb(192,92,31) }, + "picture": { "color":alpha(255) }, + "sectorADesc": { "paint":"textBase", "color":rgb(0,0,255) }, + "sectorBDesc": { "paint":"textBase", "color":rgb(0,127,0) }, + "sectorCDesc": { "paint":"textBase", "color":rgb(255,0,0) }, + "sectorXY1": { "paint":"textBase", "color":rgb(192,63,192) }, + "sectorXY2": { "paint":"textBase", "color":rgb(127,127,0) }, + "sectorXY3": { "paint":"textBase", "color":rgb(255,0,0) }, + "sectorXY4": { "paint":"textBase", "color":rgb(127,0,127) }, + "sectorXY5": { "paint":"textBase", "color":rgb(0,127,127) }, + "sectorXY6": { "paint":"textBase", "color":rgb(0,127,0) }, + "sectorXY7": { "paint":"textBase", "color":rgb(63,192,63) }, + "sectorXY8": { "paint":"textBase", "color":rgb(0,0,255) }, + "sectorXY9": { "paint":"textBase", "color":rgb(192,92,31) }, + "sectorXY10": { "paint":"textBase", "color":rgb(31,92,192) }, + "sectorXY11": { "paint":"textBase", "color":rgb(127,63,127) }, + + "stroke": { "style":"stroke", "color":rgb(0,0,0) }, + "textBase": { "style":"fill", "color":rgb(0,0,0), "typeface":"description", + "textSize":"1.3rem" }, + "vertSegment": { "paint":"diagSegment", "color":rgb(31,92,192) }, +}; + +var pictures = { + "curve1DDestText": [ + { "draw":"text.curve1d1", "paint":"paints.textBase" }, + { "draw":"text.curve1d2", "paint":"paints.textBase" } + ], + "curveMultipleText": [ + { "draw":"text.curveMultiple1", "paint":"paints.textBase" }, + { "draw":"text.curveMultiple2", "paint":"paints.textBase" } + ], + "line1DDestText": [ + { "draw":"text.line1DDest1", "paint":"paints.textBase" }, + { "draw":"text.line1DDest2", "paint":"paints.textBase" } + ], + "sectorXYA": [ + { "draw":"text.sectorXYA", "paint":"paints.sectorADesc" }, + { "draw":"paths.wedgeXY8", "paint":"paints.gradient1" } + ], + "sectorXYB": [ + { "draw":"text.sectorXYB", "paint":"paints.sectorBDesc" }, + { "draw":"paths.wedgeXY6", "paint":"paints.gradient2" } + ], + "sectorXYC": [ + { "draw":"text.sectorXYC", "paint":"paints.sectorCDesc" }, + { "draw":"paths.wedgeXY3", "paint":"paints.gradient3" } + ], + "sectorText": [ + { "draw":"text.sector1", "paint":"paints.textBase" }, + { "draw":"text.sector2", "paint":"paints.textBase" } + ], + "trivialWedgeSpans": [ + { "draw":"paths.span4", "paint":"paints.stroke" }, + { "draw":"paths.wedge4", "paint":"paints.gradient4" }, + { "draw":"paths.span5", "paint":"paints.stroke" }, + { "draw":"paths.wedge5", "paint":"paints.gradient5" }, + { "draw":"paths.span6", "paint":"paints.stroke" }, + { "draw":"paths.wedge6", "paint":"paints.gradient6" } + ], + "trivialWedgeText": [ + { "draw":"text.trivialWedge1", "paint":"paints.textBase" }, + { "draw":"text.trivialWedge2", "paint":"paints.textBase" } + ], + "xaxis": [ + { "draw":"paths.xaxis", "paint":"paints.axisStroke" }, + { "draw":"text.xaxis1", "paint":"paints.axisTextDesc" }, + { "draw":"text.xaxis2", "paint":"paints.axisTextRight" } + ], + "yaxis": [ + { "draw":"paths.yaxis", "paint":"paints.axisStroke" }, + { "draw":"text.yaxis1", "paint":"paints.axisTextTop" }, + { "draw":"text.yaxis2", "paint":"paints.axisTextDesc" } + ], + "axes": [ + { "draw":"pictures.xaxis", "paint":"paints.picture" }, + { "draw":"pictures.yaxis", "paint":"paints.picture" } + ] +}; + +var gradientLookup = [ + 0, 4, 5, 3, 6, 7, 2, 8, 1 +]; + +var keyframes = { + "_default": [ + { "actions": [ + { "range":[0,255], "paint":"paints.picture", "target":"paint.color", + "params":"target", "formula":"alpha(value, params)" } + ]} + ], + "keyframe1": [ + { "time": 0, "duration":1000, "canvas":"clear", "actions": [ + { "draw":"text.spanWedge", "paint":"paints.textBase" } + ]}, + { "time":1000, "duration":1000, "actions": [ + { "ref":"span1", "draw":"paths.span1", "paint":"paints.stroke" } + ]}, + { "time":1500, "duration":1500, "actions": [ + { "ref":"wedge1", "draw":"paths.wedge1", "paint":"paints.gradient1" } + ]}, + { "time":3500, "duration": 500, "actions": [ + { "ref":"span1", "range":[255,0] }, + { "ref":"wedge1", "range":[255,0] } + ]}, + { "time":4000, "duration":1000, "actions": [ + { "ref":"span2", "draw":"paths.span2", "paint":"paints.stroke" } + ]}, + { "time":4500, "duration":1500, "actions": [ + { "ref":"wedge2", "draw":"paths.wedge2", "paint":"paints.gradient2" } + ]}, + { "time":6500, "duration": 500, "actions": [ + { "ref":"span2", "range":[255,0] }, + { "ref":"wedge2", "range":[255,0] } + ]}, + { "time":7000, "duration":1000, "actions": [ + { "draw":"paths.span3", "paint":"paints.stroke" } + ]}, + { "time":7500, "duration":1500, "actions": [ + { "draw":"paths.wedge3", "paint":"paints.gradient3" } + ]} + ], + "keyframe2": [ + { "time": 0, "duration":1000, "canvas":"clear", "actions": [ + { "draw":"pictures.trivialWedgeText", "paint":"paints.picture" } + ]}, + { "time":2000, "duration":1500, "actions": [ + { "draw":"pictures.trivialWedgeSpans", "paint":"paints.picture" } + ]} + ], + "keyframe3": [ + { "time": 0, "duration":1000, "canvas":"clear", "actions": [ + { "draw":"pictures.sectorText" }, + { "draw":"pictures.xaxis" } + ]}, + { "time": 500, "duration":1000, "actions": [ + { "draw":"pictures.yaxis" } + ]}, + { "time":2000, "duration":1500, "actions": [ + { "draw":"pictures.sectorXYA" } + ]}, + { "time":3000, "duration":1500, "actions": [ + { "draw":"pictures.sectorXYB" } + ]}, + { "time":4000, "duration":1500, "actions": [ + { "draw":"pictures.sectorXYC" } + ]} + ], + "keyframe4": [ + { "time": 0, "duration":1000, "canvas":"clear", "actions": [ + { "draw":"text.lineSingle", "paint":"paints.textBase" }, + { "draw":"pictures.axes" } + ]}, + { "time":1000, "duration":1000, "actions": [ + { "ref":"line", "draw":"paths.lineSegment", "paint":"paints.stroke" } + ]}, + { "time":1850, "duration":1000, "actions": [ + { "ref":"sectorXY1", "draw":"text.sectorXY1", "paint":"paints.sectorXY1" }, + { "ref":"sectorXY1", "target":"draw.y", "formula":260 }, + { "ref":"wedgeXY1", "draw":"paths.wedgeXY1", "paint":"paints.gradient4" } + ]}, + { "time":3000, "duration":4000, "actions": [ + { "ref":"line", "target":"draw[0].line[2]", + "range":[-22.5 * Math.PI / 180, (-22.5 - 360) * Math.PI / 180], "params":"circle", + "formula":"params.center.x + params.radius * Math.cos(value)" + }, + { "ref":"line", "target":"draw[0].line[3]", + "range":[-22.5 * Math.PI / 180, (-22.5 - 360) * Math.PI / 180], "params":"circle", + "formula":"params.center.y + params.radius * Math.sin(value)" + } + ]}, + { "for":["i=2", "i<=8", "++i"], "time":"2250 + 500 * i", "duration":100, "actions": [ + { "ref":"'sectorXY' + i", "draw":"'text.sectorXY' + i", + "paint":"'paints.sectorXY' + i" }, + { "ref":"'sectorXY' + i", "target":"draw.y", "formula":260 }, + { "ref":"'wedgeXY' + i", "draw":"'paths.wedgeXY' + i", + "paint":"'paints.gradient' + gradientLookup[i]" }, + { "ref":"'sectorXY' + (i - 1)", "range":[255,0] }, + { "ref":"'wedgeXY' + (i - 1)", "range":[255,0] } + ]}, + { "time":2250 + 500 * 9, "duration":100, "actions": [ + { "ref":"sectorXY1" }, + { "ref":"wedgeXY1" }, + { "ref":"sectorXY8", "range":[255,0] }, + { "ref":"wedgeXY8", "range":[255,0] } + ]} + ], + "keyframe5": [ + { "time": 0, "duration":1000, "canvas":"clear", "actions": [ + { "draw":"pictures.curveMultipleText" }, + { "draw":"pictures.axes" } + ]}, + { "time":1000, "duration":1000, "actions": [ + { "ref":"curve", "draw":"paths.curveSegment1", "paint":"paints.stroke" } + ]}, + { "time":2000, "duration":1000, "actions": [ + { "draw":"text.sectorXY1", "paint":"paints.sectorXY1", + "target":"draw.y", "formula":260 + 1 * 25}, + { "draw":"paths.wedgeXY1", "paint":"paints.gradient4" } + ]}, + { "time":3000, "duration":1000, "actions": [ + { "ref":"curve", "range":[0,1], "target":"draw", + "params":["paths.curveSegment1","paths.curveSegment2"], + "formula":"interp_paths(value, params)" + } + ]}, + { "time":4000, "duration":1000, "actions": [ + { "draw":"text.sectorXY2", "paint":"paints.sectorXY2", + "target":"draw.y", "formula":260 + 2 * 25}, + { "draw":"paths.wedgeXY2", "paint":"paints.gradient5" } + ]}, + { "time":5000, "duration":1000, "actions": [ + { "ref":"curve", "range":[0,1], "target":"draw", + "params":["paths.curveSegment2","paths.curveSegment3"], + "formula":"interp_paths(value, params)" + } + ]}, + { "for":["i=3", "i<=6", "++i"], "time":"6000", "actions": [ + { "ref":"'text' + i", "draw":"'text.sectorXY' + i", "paint":"'paints.sectorXY' + i", + "target":"draw.y", "formula":"260 + i * 25" }, + ]}, + { "for":["i=3", "i<=6", "++i"], "time":"6000", "duration":1000, "actions": [ + { "ref":"'text' + i" }, + ]}, + { "time":6000, "duration":1000, "actions": [ + { "draw":"paths.wedgeXY3", "paint":"paints.gradient3" }, + { "draw":"paths.wedgeXY4", "paint":"paints.gradient6" }, + { "draw":"paths.wedgeXY5", "paint":"paints.gradient7" }, + { "draw":"paths.wedgeXY6", "paint":"paints.gradient2" }, + ]} + ], + "keyframe6": [ + { "time": 0, "duration":1000, "canvas":"clear", "actions": [ + { "draw":"pictures.line1DDestText" }, + { "draw":"pictures.axes" } + ]}, + { "time":2000, "duration":1000, "actions": [ + { "ref":"xy9", "draw":"text.sectorXY9", "paint":"paints.sectorXY9" }, + { "ref":"xy9", "target":"draw.y", "formula":260 + 25}, + { "draw":"paths.horzSegment", "paint":"paints.horzSegment" } + ]}, + { "time":3000, "duration":1000, "actions": [ + { "ref":"xy10", "draw":"text.sectorXY10", "paint":"paints.sectorXY10" }, + { "ref":"xy10", "target":"draw.y", "formula":260 + 50 }, + { "draw":"paths.vertSegment", "paint":"paints.vertSegment" } + ]}, + { "time":4000, "duration":1000, "actions": [ + { "ref":"xy11", "draw":"text.sectorXY11", "paint":"paints.sectorXY11" }, + { "ref":"xy11", "target":"draw.y", "formula":260 + 75 }, + { "draw":"paths.diagSegment", "paint":"paints.diagSegment" } + ]} + ], + "keyframe7": [ + { "time": 0, "duration":1000, "canvas":"clear", "actions": [ + { "draw":"pictures.curve1DDestText" }, + { "draw":"pictures.axes" } + ]}, + { "time":2000, "duration":1000, "actions": [ + { "ref":"cubic", "draw":"paths.cubicSegment1", "paint":"paints.stroke" }, + { "ref":"cubic", "range":[0,1], "target":"draw", + "params":"paths.cubicSegment2", "formula":"path_partial(value, params)" }, + { "ref":"xy9", "draw":"text.sectorXY9", "paint":"paints.sectorXY9" }, + { "ref":"xy9", "target":"draw.y", "formula":260 + 25}, + { "draw":"paths.horzSegment", "paint":"paints.horzSegment" } + ]}, + { "time":3000, "duration":1000, "actions": [ + { "ref":"xy1", "draw":"text.sectorXY1", "paint":"paints.sectorXY1" }, + { "ref":"xy1", "target":"draw.y", "formula":260 + 60}, + { "draw":"paths.wedgeXY1", "paint":"paints.gradient4" } + ]}, + ] +}; diff --git a/experimental/docs/interpolatorFunctions.js b/experimental/docs/interpolatorFunctions.js new file mode 100644 index 0000000000..d51969ff11 --- /dev/null +++ b/experimental/docs/interpolatorFunctions.js @@ -0,0 +1,84 @@ +function interp(A, B, t) { + return A + (B - A) * t; +} + +function interp_cubic_coords(x1, x2, x3, x4, t) +{ + var ab = interp(x1, x2, t); + var bc = interp(x2, x3, t); + var cd = interp(x3, x4, t); + var abc = interp(ab, bc, t); + var bcd = interp(bc, cd, t); + var abcd = interp(abc, bcd, t); + return abcd; +} + +// FIXME : only works for path with single cubic +function path_partial(value, path) { + assert(isArray(path)); + var out = []; + for (var cIndex = 0; cIndex < path.length; ++cIndex) { + out[cIndex] = {}; + var curveKey = Object.keys(path[cIndex])[0]; + var curve = path[cIndex][curveKey]; + var outArray; + switch (curveKey) { + case "cubic": + var x1 = curve[0], y1 = curve[1], x2 = curve[2], y2 = curve[3]; + var x3 = curve[4], y3 = curve[5], x4 = curve[6], y4 = curve[7]; + var t1 = 0, t2 = value; + var ax = interp_cubic_coords(x1, x2, x3, x4, t1); + var ay = interp_cubic_coords(y1, y2, y3, y4, t1); + var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3); + var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3); + var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3); + var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3); + var dx = interp_cubic_coords(x1, x2, x3, x4, t2); + var dy = interp_cubic_coords(y1, y2, y3, y4, t2); + var mx = ex * 27 - ax * 8 - dx; + var my = ey * 27 - ay * 8 - dy; + var nx = fx * 27 - ax - dx * 8; + var ny = fy * 27 - ay - dy * 8; + var bx = (mx * 2 - nx) / 18; + var by = (my * 2 - ny) / 18; + var cx = (nx * 2 - mx) / 18; + var cy = (ny * 2 - my) / 18; + outArray = [ + ax, ay, bx, by, cx, cy, dx, dy + ]; + break; + default: + assert(0); // unimplemented + } + out[cIndex][curveKey] = outArray; + } + return out; +} + +function interp_paths(value, paths) { + assert(isArray(paths)); + assert(paths.length == 2); + var curves0 = paths[0]; + assert(isArray(curves0)); + var curves1 = paths[1]; + assert(isArray(curves1)); + assert(curves0.length == curves1.length); + var out = []; + for (var cIndex = 0; cIndex < curves0.length; ++cIndex) { + out[cIndex] = {}; + var curve0Key = Object.keys(curves0[cIndex])[0]; + var curve1Key = Object.keys(curves1[cIndex])[0]; + assert(curve0Key == curve1Key); + var curve0 = curves0[cIndex][curve0Key]; + var curve1 = curves1[cIndex][curve1Key]; + assert(isArray(curve0)); + assert(isArray(curve1)); + assert(curve0.length == curve1.length); + var outArray = []; + for (var i = 0; i < curve1.length; ++i) { + outArray[i] = curve0[i] + (curve1[i] - curve0[i]) * value; + } + out[cIndex][curve0Key] = outArray; + } + return out; +} diff --git a/experimental/docs/jsonbaseddoc.htm b/experimental/docs/jsonbaseddoc.htm new file mode 100644 index 0000000000..bceabaebc6 --- /dev/null +++ b/experimental/docs/jsonbaseddoc.htm @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + 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); +} diff --git a/experimental/docs/svgbaseddoc.htm b/experimental/docs/svgbaseddoc.htm new file mode 100644 index 0000000000..c96edcc4f6 --- /dev/null +++ b/experimental/docs/svgbaseddoc.htm @@ -0,0 +1,1712 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +All spans are contained by a wedge. + + + + + + + + + + +Wedges that don't overlap can be + + +easily sorted. + + + + + + + + + + + +A sector is a wedge of a circle + + +containing a range of points. + + + + -X + +X + + + + -Y + +Y + + +X > 0>  Y > 0    Y < X + +X < 0   Y > 0   -Y < X + +X < 0   Y < 0    Y < X + + + + + + +Line spans are contained by a single sector. + + +X > 0   Y < 0   -Y < X + +X > 0   Y < 0   -Y > X + +X < 0   Y < 0    Y < X + +X < 0   Y < 0    Y > X + +X < 0   Y > 0   -Y < X + +X < 0   Y > 0   -Y < X + +X > 0   Y > 0    Y > X + +X > 0   Y > 0    Y < X + + + + + + + + + +A curve span may cover more + + +than one sector. + + + + + + + + +Some lines occupy one-dimensional + + +sectors. + + +X > 0   Y == 0 + +Y > 0   0 == X + +X < 0   Y == X + + + + + + +Some curves initially occupy + + +one-dimensional sectors, then diverge. + + + + + + +Each sector is assigned a number. + + +Each span has a bit set for one or more sectors. + + +Span sets allow rough sorting without angle computation. + + + + + + + + + + + + + +
+ + + +
+ + + + + \ No newline at end of file diff --git a/experimental/docs/utilities.js b/experimental/docs/utilities.js new file mode 100644 index 0000000000..e3261c604e --- /dev/null +++ b/experimental/docs/utilities.js @@ -0,0 +1,24 @@ +function alpha(value, color) { + return value << 24 | (color & 0x00FFFFFF); +} + +function argb(a, r, g, b) { + return a << 24 | r << 16 | g << 8 | b; +} + +function assert(condition) { + if (!condition) debugger; +} + +function isAlpha(code) { + return (code > 64 && code < 91) // upper alpha (A-Z) + || (code > 96 && code < 123); // lower alpha (a-z) +} + +function isArray(a) { + return a.constructor === Array; +} + +function rgb(r, g, b) { + return 0xFF << 24 | r << 16 | g << 8 | b; +} -- cgit v1.2.3