From aa40256e384c13ba197cce9f1e833f3c5a11a8d4 Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Thu, 31 May 2012 18:31:04 -0700 Subject: runtime version of the brush stroke (similar to the pen paths, this seems to not work unless we run it through the debugger) --- assets/canvas-runtime.js | 201 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 1 deletion(-) diff --git a/assets/canvas-runtime.js b/assets/canvas-runtime.js index 3ed7ed0f..dab1c444 100644 --- a/assets/canvas-runtime.js +++ b/assets/canvas-runtime.js @@ -382,6 +382,12 @@ NinjaCvsRt.GLRuntime = Object.create(Object.prototype, { obj = Object.create(NinjaCvsRt.RuntimeSubPath, {_materials: { value:[], writable:true}}); obj.importJSON (jObj ); break; + + case 6: //brushstroke (created by brush tool) + obj = Object.create(NinjaCvsRt.RuntimeBrushStroke, {_materials: { value:[], writable:true}}); + obj.importJSON (jObj ); + break; + default: throw new Error( "Attempting to load unrecognized object type: " + type ); break; @@ -524,6 +530,7 @@ NinjaCvsRt.RuntimeGeomObj = Object.create(Object.prototype, { GEOM_TYPE_LINE: { value: 3, writable: false }, GEOM_TYPE_PATH: { value: 4, writable: false }, GEOM_TYPE_CUBIC_BEZIER: { value: 5, writable: false }, + GEOM_TYPE_BRUSH_STROKE: { value: 6, writable: false }, GEOM_TYPE_UNDEFINED: { value: -1, writable: false }, /////////////////////////////////////////////////////////////////////// @@ -2006,8 +2013,200 @@ NinjaCvsRt.RuntimeSubPath = Object.create(NinjaCvsRt.RuntimeGeomObj, { ctx.restore(); } } -});// ************************************************************************** +}); + +// ************************************************************************** // END runtime for the pen tool path // ************************************************************************** +// *************************************************************************** +// runtime for brush tool brush stroke +// *************************************************************************** + +NinjaCvsRt.RuntimeBrushStroke = Object.create(NinjaCvsRt.RuntimeGeomObj, { + // array of brush stroke points + _LocalPoints: { value: null, writable: true }, + _OrigLocalPoints: {value: null, writable: true}, + + _strokeWidth: {value: 0, writable: true}, + _strokeColor: {value: null, writable: true}, + _strokeWidth: {value: 0, writable: true}, + _strokeColor: {value: 0, writable: true}, + _strokeHardness: {value: 0, writable: true}, + _strokeUseCalligraphic : {value: 0, writable: true}, + _strokeAngle : {value: 0, writable: true}, + + //stroke smoothing properties + _strokeDoSmoothing: {value: 0, writable: true}, + _strokeAmountSmoothing : {value: 0, writable: true}, + + geomType: { + value: function () { + return this.GEOM_TYPE_BRUSH_STROKE; + } + }, + + _copyCoordinates3D: { + value: function(srcCoord, destCoord){ + var i=0; + var numPoints = srcCoord.length; + for (i=0;i1) { + this._copyCoordinates3D(this._OrigLocalPoints, this._LocalPoints); + //iterations of Laplacian smoothing (setting the points to the average of their neighbors) + var numLaplacianIterations = this._strokeAmountSmoothing; + for (var n=0;n + + //stroke appearance properties + this._strokeWidth = jo.strokeWidth; + this._strokeColor = jo.strokeColor; + this._strokeHardness = jo.strokeHardness; + this._strokeUseCalligraphic = jo.strokeUseCalligraphic; + this._strokeAngle = jo.strokeAngle; + + //stroke smoothing properties + this._strokeDoSmoothing = jo.strokeDoSmoothing; + this._strokeAmountSmoothing = jo.strokeAmountSmoothing; + + this._doSmoothing(); //after smoothing, the stroke is ready to be rendered + } + }, + + render: { + value: function() { + // get the world + var world = this.getWorld(); + if (!world) { + throw( "null world in brush stroke render" ); + return; + } + + // get the context + var ctx = world.get2DContext(); + if (!ctx) { + throw( "null world in brush stroke render" ); + return; + } + + ctx.save(); + + //**** BEGIN RENDER CODE BLOCK **** + var points = this._LocalPoints; + var numPoints = points.length; + var tempP, p; + if (this._strokeUseCalligraphic) { + //build the stamp for the brush stroke + var t=0; + var numTraces = this._strokeWidth; + var halfNumTraces = numTraces*0.5; + var opaqueRegionHalfWidth = 0.5*this._strokeHardness*numTraces*0.01; //the 0.01 is to convert the strokeHardness from [0,100] to [0,1] + var maxTransparentRegionHalfWidth = halfNumTraces-opaqueRegionHalfWidth; + + //build an angled (calligraphic) brush stamp + var deltaDisplacement = [Math.cos(this._strokeAngle),Math.sin(this._strokeAngle)]; + deltaDisplacement = VecUtils.vecNormalize(2, deltaDisplacement, 1); + var startPos = [-halfNumTraces*deltaDisplacement[0],-halfNumTraces*deltaDisplacement[1]]; + + var brushStamp = []; + for (t=0;t0) { + var transparencyFactor = distFromOpaqueRegion/maxTransparentRegionHalfWidth; + alphaVal = 1.0 - transparencyFactor;//(transparencyFactor*transparencyFactor);//the square term produces nonlinearly varying alpha values + alphaVal *= 0.5; //factor that accounts for lineWidth == 2 + } + ctx.save(); + if (t === (numTraces-1) || t === 0){ + ctx.lineWidth = 1; + } else { + ctx.lineWidth=2; + } + ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")"; + ctx.translate(disp[0],disp[1]); + ctx.beginPath(); + p = points[0]; + ctx.moveTo(p[0],p[1]); + for (var i=0;i