aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPushkar Joshi2012-06-06 15:01:10 -0700
committerPushkar Joshi2012-06-06 15:01:10 -0700
commit2dca8a0aa69981bc2a81c4a68f9061aef861f0ea (patch)
tree8ebc5a87d3b90569f4ac2688ac2a6d8c3c8713d0
parentcf3087b78d771ef89b0d5557430fd594f71cf063 (diff)
downloadninja-2dca8a0aa69981bc2a81c4a68f9061aef861f0ea.tar.gz
enable gradients for brush stroke (in authoring as well as runtime)
-rw-r--r--assets/canvas-runtime.js62
-rwxr-xr-xjs/lib/geom/brush-stroke.js1406
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 ///////////////////////////////////////////////////////// 70BrushStroke.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/////////////////////////////////////////////////////////
75BrushStroke.prototype.setCanvas = function(c) {
76 this._canvas = c;
77};
78
79BrushStroke.prototype.setWorld = function (world) {
80 this._world = world;
81};
82
83BrushStroke.prototype.getWorld = function () {
84 return this._world;
85};
86
87BrushStroke.prototype.geomType = function () {
88 return this.GEOM_TYPE_BRUSH_STROKE;
89};
90
91BrushStroke.prototype.setDrawingTool = function (tool) {
92 this._drawingTool = tool;
93};
94
95BrushStroke.prototype.getDrawingTool = function () {
96 return this._drawingTool;
97};
98
99BrushStroke.prototype.setPlaneMatrix = function(planeMat){
100 this._planeMat = planeMat;
101};
102
103BrushStroke.prototype.setPlaneMatrixInverse = function(planeMatInv){
104 this._planeMatInv = planeMatInv;
105};
106
107BrushStroke.prototype.setPlaneCenter = function(pc){
108 this._planeCenter = pc;
109};
110
111BrushStroke.prototype.setDragPlane = function(p){
112 this._dragPlane = p;
113};
114
115BrushStroke.prototype.getNumPoints = function () {
116 if (this._LocalPoints.length)
117 return this._LocalPoints.length;
118 else
119 return this._Points.length;
120};
121
122BrushStroke.prototype.getPoint = function (index) {
123 return this._Points[index].slice(0);
124};
125
126BrushStroke.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) { 146BrushStroke.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 () { 152BrushStroke.prototype.isDirty = function(){
81 return this._world; 153 return this._isDirty;
82 }; 154};
83 155
84 this.geomType = function () { 156BrushStroke.prototype.makeDirty = function(){
85 return this.GEOM_TYPE_BRUSH_STROKE; 157 this._isDirty=true;
86 }; 158};
87 159
88 this.setDrawingTool = function (tool) { 160BrushStroke.prototype.getStageWorldCenter = function() {
89 this._drawingTool = tool; 161 return this._stageWorldCenter;
90 }; 162};
91