diff options
-rw-r--r-- | assets/canvas-runtime.js | 62 | ||||
-rwxr-xr-x | js/lib/geom/brush-stroke.js | 1406 |
2 files changed, 790 insertions, 678 deletions
diff --git a/assets/canvas-runtime.js b/assets/canvas-runtime.js index 524cdfeb..76332bcb 100644 --- a/assets/canvas-runtime.js +++ b/assets/canvas-runtime.js | |||
@@ -2137,15 +2137,59 @@ NinjaCvsRt.RuntimeBrushStroke = Object.create(NinjaCvsRt.RuntimeGeomObj, { | |||
2137 | } | 2137 | } |
2138 | }, | 2138 | }, |
2139 | 2139 | ||
2140 | //buildColor returns the fillStyle or strokeStyle for the Canvas 2D context | ||
2141 | buildColor: { | ||
2142 | value: function(ctx, //the 2D rendering context (for creating gradients if necessary) | ||
2143 | ipColor, //color string, also encodes whether there's a gradient and of what type | ||
2144 | w, //width of the region of color | ||
2145 | h, //height of the region of color | ||
2146 | lw) //linewidth (i.e. stroke width/size) | ||
2147 | { | ||
2148 | if (ipColor.gradientMode){ | ||
2149 | var position, gradient, cs, inset; //vars used in gradient calculations | ||
2150 | inset = Math.ceil( lw ) - 0.5; | ||
2151 | |||
2152 | if(ipColor.gradientMode === "radial") { | ||
2153 | var ww = w - 2*lw, hh = h - 2*lw; | ||
2154 | gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2, h/2, Math.max(ww, hh)/2); | ||
2155 | } else { | ||
2156 | gradient = ctx.createLinearGradient(inset, h/2, w-inset, h/2); | ||
2157 | } | ||
2158 | var colors = ipColor.color; | ||
2159 | |||
2160 | var len = colors.length; | ||
2161 | for(n=0; n<len; n++) { | ||
2162 | position = colors[n].position/100; | ||
2163 | cs = colors[n].value; | ||
2164 | gradient.addColorStop(position, "rgba(" + cs.r + "," + cs.g + "," + cs.b + "," + cs.a + ")"); | ||
2165 | } | ||
2166 | return gradient; | ||
2167 | } else { | ||
2168 | var c = "rgba(" + 255*ipColor[0] + "," + 255*ipColor[1] + "," + 255*ipColor[2] + "," + ipColor[3] + ")"; | ||
2169 | return c; | ||
2170 | } | ||
2171 | } | ||
2172 | }, | ||
2173 | |||
2140 | render: { | 2174 | render: { |
2141 | value: function() { | 2175 | value: function() { |
2176 | //vars for gradient code | ||
2177 | var w,h; | ||
2178 | |||
2142 | // get the world | 2179 | // get the world |
2143 | var world = this.getWorld(); | 2180 | var world = this.getWorld(); |
2144 | if (!world) { | 2181 | if (!world) { |
2145 | throw( "null world in brush stroke render" ); | 2182 | throw( "null world in brush stroke render" ); |
2146 | return; | 2183 | return; |
2147 | } | 2184 | } else { |
2148 | 2185 | ||
2186 | if (this._strokeColor.gradientMode){ | ||
2187 | useBuildColor = true; | ||
2188 | } | ||
2189 | //vars used for the gradient computation in buildColor | ||
2190 | w = world.getViewportWidth(); | ||
2191 | h = world.getViewportHeight(); | ||
2192 | } | ||
2149 | // get the context | 2193 | // get the context |
2150 | var ctx = world.get2DContext(); | 2194 | var ctx = world.get2DContext(); |
2151 | if (!ctx) { | 2195 | if (!ctx) { |
@@ -2169,7 +2213,7 @@ NinjaCvsRt.RuntimeBrushStroke = Object.create(NinjaCvsRt.RuntimeGeomObj, { | |||
2169 | 2213 | ||
2170 | //build an angled (calligraphic) brush stamp | 2214 | //build an angled (calligraphic) brush stamp |
2171 | var deltaDisplacement = [Math.cos(this._strokeAngle),Math.sin(this._strokeAngle)]; | 2215 | var deltaDisplacement = [Math.cos(this._strokeAngle),Math.sin(this._strokeAngle)]; |
2172 | deltaDisplacement = VecUtils.vecNormalize(2, deltaDisplacement, 1); | 2216 | deltaDisplacement = this.vecNormalize(2, deltaDisplacement, 1); |
2173 | var startPos = [-halfNumTraces*deltaDisplacement[0],-halfNumTraces*deltaDisplacement[1]]; | 2217 | var startPos = [-halfNumTraces*deltaDisplacement[0],-halfNumTraces*deltaDisplacement[1]]; |
2174 | 2218 | ||
2175 | var brushStamp = []; | 2219 | var brushStamp = []; |
@@ -2198,7 +2242,11 @@ NinjaCvsRt.RuntimeBrushStroke = Object.create(NinjaCvsRt.RuntimeGeomObj, { | |||
2198 | } else { | 2242 | } else { |
2199 | ctx.lineWidth=2; | 2243 | ctx.lineWidth=2; |
2200 | } | 2244 | } |
2201 | ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")"; | 2245 | if (!useBuildColor){ |
2246 | ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")"; | ||
2247 | } else { | ||
2248 | ctx.strokeStyle = this.buildColor(ctx, this._strokeColor, w, h, this._strokeWidth, alphaVal); | ||
2249 | } | ||
2202 | ctx.translate(disp[0],disp[1]); | 2250 | ctx.translate(disp[0],disp[1]); |
2203 | ctx.beginPath(); | 2251 | ctx.beginPath(); |
2204 | p = points[0]; | 2252 | p = points[0]; |
@@ -2218,7 +2266,13 @@ NinjaCvsRt.RuntimeBrushStroke = Object.create(NinjaCvsRt.RuntimeGeomObj, { | |||
2218 | var minStrokeWidth = (this._strokeHardness*this._strokeWidth)/100; //the hardness is the percentage of the stroke width that's fully opaque | 2266 | var minStrokeWidth = (this._strokeHardness*this._strokeWidth)/100; //the hardness is the percentage of the stroke width that's fully opaque |
2219 | var numlayers = 1 + Math.ceil((this._strokeWidth-minStrokeWidth)*0.5); | 2267 | var numlayers = 1 + Math.ceil((this._strokeWidth-minStrokeWidth)*0.5); |
2220 | var alphaVal = 1.0/(numlayers); //this way the alpha at the first path will be 1 | 2268 | var alphaVal = 1.0/(numlayers); //this way the alpha at the first path will be 1 |
2221 | ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")"; | 2269 | |
2270 | if (!useBuildColor){ | ||
2271 | ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")"; | ||
2272 | } else { | ||
2273 | ctx.strokeStyle = this.buildColor(ctx, this._strokeColor, w,h, this._strokeWidth, alphaVal); | ||
2274 | } | ||
2275 | |||
2222 | for (var l=0;l<numlayers;l++){ | 2276 | for (var l=0;l<numlayers;l++){ |
2223 | ctx.beginPath(); | 2277 | ctx.beginPath(); |
2224 | p = points[0]; | 2278 | p = points[0]; |
diff --git a/js/lib/geom/brush-stroke.js b/js/lib/geom/brush-stroke.js index 09a7023c..b2e56149 100755 --- a/js/lib/geom/brush-stroke.js +++ b/js/lib/geom/brush-stroke.js | |||
@@ -65,777 +65,835 @@ var BrushStroke = function GLBrushStroke() { | |||
65 | this._planeMatInv = null; | 65 | this._planeMatInv = null; |
66 | this._planeCenter = null; | 66 | this._planeCenter = null; |
67 | this._dragPlane = null; | 67 | this._dragPlane = null; |
68 | }; //BrushStroke class defition | ||
68 | 69 | ||
69 | ///////////////////////////////////////////////////////// | 70 | BrushStroke.prototype = Object.create(GeomObj, {}); |
70 | // Property Accessors/Setters | 71 | |
71 | ///////////////////////////////////////////////////////// | 72 | ///////////////////////////////////////////////////////// |
72 | this.setCanvas = function(c) { | 73 | // Property Accessors/Setters |
73 | this._canvas = c; | 74 | ///////////////////////////////////////////////////////// |
75 | BrushStroke.prototype.setCanvas = function(c) { | ||
76 | this._canvas = c; | ||
77 | }; | ||
78 | |||
79 | BrushStroke.prototype.setWorld = function (world) { | ||
80 | this._world = world; | ||
81 | }; | ||
82 | |||
83 | BrushStroke.prototype.getWorld = function () { | ||
84 | return this._world; | ||
85 | }; | ||
86 | |||
87 | BrushStroke.prototype.geomType = function () { | ||
88 | return this.GEOM_TYPE_BRUSH_STROKE; | ||
89 | }; | ||
90 | |||
91 | BrushStroke.prototype.setDrawingTool = function (tool) { | ||
92 | this._drawingTool = tool; | ||
93 | }; | ||
94 | |||
95 | BrushStroke.prototype.getDrawingTool = function () { | ||
96 | return this._drawingTool; | ||
97 | }; | ||
98 | |||
99 | BrushStroke.prototype.setPlaneMatrix = function(planeMat){ | ||
100 | this._planeMat = planeMat; | ||
101 | }; | ||
102 | |||
103 | BrushStroke.prototype.setPlaneMatrixInverse = function(planeMatInv){ | ||
104 | this._planeMatInv = planeMatInv; | ||
105 | }; | ||
106 | |||
107 | BrushStroke.prototype.setPlaneCenter = function(pc){ | ||
108 | this._planeCenter = pc; | ||
109 | }; | ||
110 | |||
111 | BrushStroke.prototype.setDragPlane = function(p){ | ||
112 | this._dragPlane = p; | ||
113 | }; | ||
114 | |||
115 | BrushStroke.prototype.getNumPoints = function () { | ||
116 | if (this._LocalPoints.length) | ||
117 | return this._LocalPoints.length; | ||
118 | else | ||
119 | return this._Points.length; | ||
120 | }; | ||
121 | |||
122 | BrushStroke.prototype.getPoint = function (index) { | ||
123 | return this._Points[index].slice(0); | ||
124 | }; | ||
125 | |||
126 | BrushStroke.prototype.addPoint = function (pt) { | ||
127 | //add the point only if it is some epsilon away from the previous point | ||
128 | var numPoints = this._Points.length; | ||
129 | if (numPoints>0) { | ||
130 | var threshold = this._MIN_SAMPLE_DISTANCE_THRESHOLD; | ||
131 | var prevPt = this._Points[numPoints-1]; | ||
132 | var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]]; | ||
133 | var diffPtMag = Math.sqrt(diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]); | ||
134 | if (diffPtMag>threshold){ | ||
135 | this._Points.push(pt); | ||
136 | this._isDirty=true; | ||
137 | this._isInit = false; | ||
138 | } | ||
139 | } else { | ||
140 | this._Points.push(pt); | ||
141 | this._isDirty=true; | ||
142 | this._isInit = false; | ||
74 | } | 143 | } |
144 | }; | ||
75 | 145 | ||
76 | this.setWorld = function (world) { | 146 | BrushStroke.prototype.insertPoint = function(pt, index){ |
77 | this._world = world; | 147 | this._Points.splice(index, 0, pt); |
78 | }; | 148 | this._isDirty=true; |
149 | this._isInit = false; | ||
150 | }; | ||
79 | 151 | ||
80 | this.getWorld = function () { | 152 | BrushStroke.prototype.isDirty = function(){ |
81 | return this._world; | 153 | return this._isDirty; |
82 | }; | 154 | }; |
83 | 155 | ||
84 | this.geomType = function () { | 156 | BrushStroke.prototype.makeDirty = function(){ |
85 | return this.GEOM_TYPE_BRUSH_STROKE; | 157 | this._isDirty=true; |
86 | }; | 158 | }; |
87 | 159 | ||
88 | this.setDrawingTool = function (tool) { | 160 | BrushStroke.prototype.getStageWorldCenter = function() { |
89 | this._drawingTool = tool; | 161 | return this._stageWorldCenter; |
90 | }; | 162 | }; |
91 | 163 | ||
92 | this.getDrawingTool = function () { | 164 | BrushStroke.prototype.getBBoxMin = function () { |
93 | return this._drawingTool; | 165 | return this._BBoxMin; |
94 | }; |