aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xjs/components/tools-properties/brush-properties.reel/brush-properties.html23
-rwxr-xr-xjs/components/tools-properties/brush-properties.reel/brush-properties.js8
-rwxr-xr-xjs/lib/geom/brush-stroke.js147
-rw-r--r--js/tools/BrushTool.js18
4 files changed, 129 insertions, 67 deletions
diff --git a/js/components/tools-properties/brush-properties.reel/brush-properties.html b/js/components/tools-properties/brush-properties.reel/brush-properties.html
index 6d4852e6..d96bd1ba 100755
--- a/js/components/tools-properties/brush-properties.reel/brush-properties.html
+++ b/js/components/tools-properties/brush-properties.reel/brush-properties.html
@@ -37,6 +37,19 @@
37 } 37 }
38 }, 38 },
39 39
40 "strokeAngleHT": {
41 "module": "js/components/hottextunit.reel",
42 "name": "HotTextUnit",
43 "properties": {
44 "element": {"#": "strokeAngle"},
45 "minValue": -90,
46 "maxValue": 90,
47 "value": 0,
48 "decimalPlace": 10,
49 "acceptableUnits" : ["px", "pt"]
50 }
51 },
52
40 "owner": { 53 "owner": {
41 "module": "js/components/tools-properties/brush-properties.reel", 54 "module": "js/components/tools-properties/brush-properties.reel",
42 "name": "BrushProperties", 55 "name": "BrushProperties",
@@ -44,7 +57,9 @@
44 "element": {"#": "brushProperties"}, 57 "element": {"#": "brushProperties"},
45 "_strokeSize": {"@": "strokeSizeHT"}, 58 "_strokeSize": {"@": "strokeSizeHT"},
46 "_strokeHardness": {"@": "strokeHardnessHT"}, 59 "_strokeHardness": {"@": "strokeHardnessHT"},
47 "_doSmoothing": {"@": "doSmoothing"} 60 "_doSmoothing": {"#": "doSmoothing"},
61 "_useCalligraphic":{"#": "useCalligraphic"},
62 "_strokeAngle": {"@": "strokeAngleHT"}
48 } 63 }
49 } 64 }
50 } 65 }
@@ -59,7 +74,11 @@
59 <div id="strokeSize" class="label"></div> 74 <div id="strokeSize" class="label"></div>
60 <label class="label"> Hardness:</label> 75 <label class="label"> Hardness:</label>
61 <div id="strokeHardness" class="label"></div> 76 <div id="strokeHardness" class="label"></div>
62 <label class="label subOption optionLabel"><input id="doSmoothing" type="checkbox" name="doSmoothingControl" class="checkBoxAlign"/>Smoothing</label> 77 <label class="label"><input id="doSmoothing" type="checkbox" name="doSmoothingControl" class="checkBoxAlign"/>Smoothing</label>
78 <label class="label"><input id="useCalligraphic" type="checkbox" name="useCalligraphicControl" class="checkBoxAlign"/>Calligraphic</label>
79 <label class="label"> Angle:</label>
80 <div id="strokeAngle" class="label"></div>
81
63 </div> 82 </div>
64 </div> 83 </div>
65 </body> 84 </body>
diff --git a/js/components/tools-properties/brush-properties.reel/brush-properties.js b/js/components/tools-properties/brush-properties.reel/brush-properties.js
index 0ce685b5..e6faa0f0 100755
--- a/js/components/tools-properties/brush-properties.reel/brush-properties.js
+++ b/js/components/tools-properties/brush-properties.reel/brush-properties.js
@@ -16,6 +16,12 @@ exports.BrushProperties = Montage.create(ToolProperties, {
16 get: function() { return this._strokeHardness; } 16 get: function() { return this._strokeHardness; }
17 }, 17 },
18 doSmoothing:{ 18 doSmoothing:{
19 get: function() {return this._doSmoothing; } 19 get: function() {return this._doSmoothing.checked; }
20 },
21 useCalligraphic: {
22 get: function() {return this._useCalligraphic.checked;}
23 },
24 strokeAngle: {
25 get: function() {return this._strokeAngle;}
20 } 26 }
21}); 27});
diff --git a/js/lib/geom/brush-stroke.js b/js/lib/geom/brush-stroke.js
index 3e64e730..a92657a4 100755
--- a/js/lib/geom/brush-stroke.js
+++ b/js/lib/geom/brush-stroke.js
@@ -37,6 +37,8 @@ var BrushStroke = function GLBrushStroke() {
37 this._strokeMaterial = null; 37 this._strokeMaterial = null;
38 this._strokeStyle = "Solid"; 38 this._strokeStyle = "Solid";
39 this._strokeDoSmoothing = false; 39 this._strokeDoSmoothing = false;
40 this._strokeUseCalligraphic = false;
41 this._strokeAngle = 0;
40 42
41 //the wetness of the brush (currently this is multiplied to the square of the stroke width, but todo should be changed to not depend on stroke width entirely 43 //the wetness of the brush (currently this is multiplied to the square of the stroke width, but todo should be changed to not depend on stroke width entirely
42 //smaller value means more samples for the path 44 //smaller value means more samples for the path
@@ -117,7 +119,7 @@ var BrushStroke = function GLBrushStroke() {
117 //add the point only if it is some epsilon away from the previous point 119 //add the point only if it is some epsilon away from the previous point
118 var numPoints = this._Points.length; 120 var numPoints = this._Points.length;
119 if (numPoints>0) { 121 if (numPoints>0) {
120 var threshold = 1;//this._WETNESS_FACTOR*this._strokeWidth; 122 var threshold = 2;//this._WETNESS_FACTOR*this._strokeWidth;
121 var prevPt = this._Points[numPoints-1]; 123 var prevPt = this._Points[numPoints-1];
122 var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]]; 124 var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]];
123 var diffPtMag = Math.sqrt(diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]); 125 var diffPtMag = Math.sqrt(diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]);
@@ -188,6 +190,14 @@ var BrushStroke = function GLBrushStroke() {
188 this._strokeDoSmoothing = s; 190 this._strokeDoSmoothing = s;
189 } 191 }
190 192
193 this.setStrokeUseCalligraphic = function(c){
194 this._strokeUseCalligraphic = c;
195 }
196
197 this.setStrokeAngle = function(a){
198 this._strokeAngle = a;
199 }
200
191 this.getStrokeStyle = function () { 201 this.getStrokeStyle = function () {
192 return this._strokeStyle; 202 return this._strokeStyle;
193 }; 203 };
@@ -266,6 +276,8 @@ var BrushStroke = function GLBrushStroke() {
266 } 276 }
267 } 277 }
268 } 278 }
279 //todo 4-point subdivision iterations over continuous regions of 'long' segments
280 // look at http://www.gvu.gatech.edu/~jarek/Split&Tweak/ for formula
269 //**** add samples to the long sections of the path --- Catmull-Rom spline interpolation 281 //**** add samples to the long sections of the path --- Catmull-Rom spline interpolation
270 if (this._strokeDoSmoothing && numPoints>1) { 282 if (this._strokeDoSmoothing && numPoints>1) {
271 var numInsertedPoints = 0; 283 var numInsertedPoints = 0;
@@ -496,75 +508,84 @@ var BrushStroke = function GLBrushStroke() {
496 } 508 }
497 */ 509 */
498 510
499 /*
500 //build the stamp for the brush stroke
501 //todo get this directly from the UI
502 var t=0;
503 var numTraces = this._strokeWidth;
504 var halfNumTraces = numTraces/2;
505 var startPos = [-this._strokeWidth/2,0];
506 var brushStamp = [];
507
508 //build an angled (calligraphic) brush stamp
509 var deltaDisplacement = [1,1];//[this._strokeWidth/numTraces, 0]; //a horizontal line brush
510 for (t=0;t<numTraces;t++){
511 var brushPt = [startPos[0]+t*deltaDisplacement[0], startPos[1]+t*deltaDisplacement[1]];
512 brushStamp.push(brushPt);
513 }
514 511
515 for (t=0;t<numTraces;t++){ 512 if (this._strokeUseCalligraphic) {
516 var disp = [brushStamp[t][0], brushStamp[t][1]]; 513 //build the stamp for the brush stroke
517 //ctx.globalCompositeOperation = 'source-over'; 514 var t=0;
518 var distFromMiddle = Math.abs(halfNumTraces-t); 515 var numTraces = this._strokeWidth;
519 var alphaVal = 1.0 - (100-this._strokeHardness)*(distFromMiddle/halfNumTraces)/100; 516 var halfNumTraces = numTraces/2;
520 alphaVal = 0.2; 517 var opaqueRegionHalfWidth = 0.5*this._strokeHardness*numTraces*0.01;
521 ctx.save(); 518 var maxTransparentRegionHalfWidth = halfNumTraces-opaqueRegionHalfWidth;
522 ctx.lineWidth=this._strokeWidth/10;//todo figure out the correct formula for the line width 519 var startPos = [-this._strokeWidth/2,0];
523 if (ctx.lineWidth<2) 520 var brushStamp = [];
524 ctx.lineWidth=2;
525 if (t===numTraces-1){
526 ctx.lineWidth = 1;
527 }
528 ctx.lineJoin="bevel";
529 ctx.lineCap="butt";
530 //if (t<numTraces/2)
531 ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")";
532 //else
533 // ctx.strokeStyle="rgba("+parseInt(255*this._secondStrokeColor[0])+","+parseInt(255*this._secondStrokeColor[1])+","+parseInt(255*this._secondStrokeColor[2])+","+alphaVal+")";
534 ctx.translate(disp[0],disp[1]);
535 ctx.beginPath();
536 ctx.moveTo(this._Points[0][0]-bboxMin[0], this._Points[0][1]-bboxMin[1]);
537 for (var i=0;i<numPoints;i++){
538 ctx.lineTo(this._Points[i][0]-bboxMin[0], this._Points[i][1]-bboxMin[1]);
539 }
540 ctx.stroke();
541 ctx.restore();
542 }
543 */
544 521
522 //build an angled (calligraphic) brush stamp
523 var deltaDisplacement = [Math.cos(this._strokeAngle),Math.sin(this._strokeAngle)];
524 deltaDisplacement = VecUtils.vecNormalize(2, deltaDisplacement, 1);
545 525
546 var minStrokeWidth = (this._strokeHardness*this._strokeWidth)/100; //the hardness is the percentage of the stroke width that's fully opaque 526 for (t=0;t<numTraces;t++){
547 var numlayers = 1 + (this._strokeWidth-minStrokeWidth)/2; 527 var brushPt = [startPos[0]+t*deltaDisplacement[0], startPos[1]+t*deltaDisplacement[1]];
548 var alphaVal = 1.0/(numlayers); 528 brushStamp.push(brushPt);
549 ctx.lineCap = "round";
550 ctx.lineJoin="round";
551 ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")";
552 ctx.globalCompositeOperation = 'lighter'; //we wish to add up the colors
553 ctx.globalAlpha = this._strokeColor[3];
554 for (var l=0;l<numlayers;l++){
555 ctx.beginPath();
556 ctx.moveTo(this._Points[0][0]-bboxMin[0], this._Points[0][1]-bboxMin[1]);
557 if (numPoints===1){
558 ctx.lineTo(this._Points[0][0]-bboxMin[0], this._Points[0][1]-bboxMin[1]+0.01);
559 } 529 }
560 for (var i=1;i<numPoints;i++){ 530
561 ctx.lineTo(this._Points[i][0]-bboxMin[0], this._Points[i][1]-bboxMin[1]); 531 for (t=0;t<numTraces;t++){
532 var disp = [brushStamp[t][0], brushStamp[t][1]];
533 //ctx.globalCompositeOperation = 'source-over';
534 var alphaVal = 1.0;
535 var distFromOpaqueRegion = Math.abs(t-halfNumTraces) - opaqueRegionHalfWidth;
536 if (distFromOpaqueRegion>0) {
537 alphaVal = 1.0 - distFromOpaqueRegion/maxTransparentRegionHalfWidth;
538 }
539