From 57c373259fb22a6c20248ef338dc2766a364ac59 Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Fri, 27 Apr 2012 15:38:17 -0700 Subject: scale the brush stroke according to the input width and height Fixes: 1444 Brush: Unable to scale brushstroke using the Transform handles --- js/lib/geom/brush-stroke.js | 62 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 4 deletions(-) (limited to 'js/lib') diff --git a/js/lib/geom/brush-stroke.js b/js/lib/geom/brush-stroke.js index 1fae0c1d..d5d9a893 100755 --- a/js/lib/geom/brush-stroke.js +++ b/js/lib/geom/brush-stroke.js @@ -264,13 +264,67 @@ var BrushStroke = function GLBrushStroke() { this._strokeStyle = s; }; - this.setWidth = function () { + this.setWidth = function (newW) { + if (newW<1) { + newW=1; //clamp minimum width to 1 + } + + //scale the contents of this subpath to lie within this width + //determine the scale factor by comparing with the old width + var oldWidth = this._BBoxMax[0]-this._BBoxMin[0]; + if (oldWidth<1) { + oldWidth=1; + } + + var scaleX = newW/oldWidth; + if (scaleX===1) { + return; //no need to do anything + } + + //scale the local point positions such that the width of the bbox is the newW + var origX = this._BBoxMin[0]; + var numPoints = this._LocalPoints.length; + for (var i=0;i0) { - alphaVal = 1.0 - distFromOpaqueRegion/maxTransparentRegionHalfWidth; - alphaVal *= 1.0/ctx.lineWidth; //factor that accounts for lineWidth !== 1 + var transparencyFactor = distFromOpaqueRegion/maxTransparentRegionHalfWidth; + alphaVal = 1.0 - transparencyFactor;//(transparencyFactor*transparencyFactor);//the square term produces nonlinearly varying alpha values } ctx.save(); - if (t === (numTraces-1)){ + if (t === (numTraces-1) || t === 0){ ctx.lineWidth = 1; } else { //todo figure out the correct formula for the line width ctx.lineWidth=2; + alphaVal *= 0.5; //factor that accounts for lineWidth == 2 } ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")"; //linearly interpolate between the two stroke colors -- cgit v1.2.3 From b9262c831952e77135b79c2de7c455d5e7ff0589 Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Tue, 1 May 2012 17:00:40 -0700 Subject: undo some previous change that was halving the alpha value of the stroke --- js/lib/geom/brush-stroke.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/lib') diff --git a/js/lib/geom/brush-stroke.js b/js/lib/geom/brush-stroke.js index a1746d95..519e0433 100755 --- a/js/lib/geom/brush-stroke.js +++ b/js/lib/geom/brush-stroke.js @@ -665,6 +665,7 @@ var BrushStroke = function GLBrushStroke() { if (distFromOpaqueRegion>0) { 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){ @@ -672,7 +673,6 @@ var BrushStroke = function GLBrushStroke() { } else { //todo figure out the correct formula for the line width ctx.lineWidth=2; - alphaVal *= 0.5; //factor that accounts for lineWidth == 2 } ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")"; //linearly interpolate between the two stroke colors -- cgit v1.2.3 From de9f718b739ef2b31a161d9dac6e81d614fab853 Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Fri, 11 May 2012 08:55:07 -0700 Subject: code cleanup and starting the subtool functionality --- js/lib/geom/sub-path.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'js/lib') diff --git a/js/lib/geom/sub-path.js b/js/lib/geom/sub-path.js index 56c94df3..24acb2b0 100755 --- a/js/lib/geom/sub-path.js +++ b/js/lib/geom/sub-path.js @@ -166,6 +166,8 @@ var GLSubpath = function GLSubpath() { }; this.setWidth = function (newW) { + var strokeWidth = this._strokeWidth; + var halfStrokeWidth = strokeWidth*0.5; if (newW<1) { newW=1; //clamp minimum width to 1 } @@ -183,7 +185,7 @@ var GLSubpath = function GLSubpath() { } //scale the anchor point positions such that the width of the bbox is the newW - var origX = this._BBoxMin[0]; + var origX = this._BBoxMin[0]; //this should always be zero since we only deal with local coordinates var numAnchors = this._Anchors.length; for (var i=0;i --- js/lib/NJUtils.js | 120 ------------------------------------------------------ 1 file changed, 120 deletions(-) (limited to 'js/lib') diff --git a/js/lib/NJUtils.js b/js/lib/NJUtils.js index 7dd4c9e8..0dec6345 100755 --- a/js/lib/NJUtils.js +++ b/js/lib/NJUtils.js @@ -90,30 +90,6 @@ exports.NJUtils = Montage.create(Component, { } }, - createModel: { - value: function(el) { - el.elementModel = Montage.create(ElementModel).initialize(el); - } - }, - - createModelWithShape: { - value: function(el, selection) { - el.elementModel = Montage.create(ElementModel).initialize(el, true, selection); - } - }, - - createModelWithSelection: { - value: function(el, selection) { - el.elementModel = Montage.create(ElementModel).initialize(el, false, selection); - } - }, - - createModelForComponent: { - value: function(el, selection) { - el.elementModel = Montage.create(ElementModel).initialize(el, false, selection, true); - } - }, - // TODO: Find a better place for this method stylesFromDraw: { value: function(element, width, height, drawData, pos) { @@ -166,102 +142,6 @@ exports.NJUtils = Montage.create(Component, { } }, - ///// Element Model creation for existing elements - ///// TODO: find a different place for this function - makeElementModel: { - value: function(el, selection, controller, isShape) { - var p3d = Montage.create(Properties3D); - - var shapeProps = null; - var pi = controller + "Pi"; - - if(isShape) { - shapeProps = Montage.create(ShapeModel); - } - - if(el.controller) { - - var componentInfo = Montage.getInfoForObject(el.controller); - var componentName = componentInfo.objectName.toLowerCase(); - - controller = "component"; - isShape = false; - - switch(componentName) { - case "feedreader": - selection = "Feed Reader"; - pi = "FeedReaderPi"; - break; - case "map": - selection = "Map"; - pi = "MapPi"; - break; - case "youtubechannel": - selection = "Youtube Channel"; - pi = "YoutubeChannelPi"; - break; - case "picasacarousel": - selection = "Picasa Carousel"; - pi = "PicasaCarouselPi"; - break; - } - } - - el.elementModel = Montage.create(ElementModel, { - type: { value: el.nodeName}, - selection: { value: selection}, - controller: { value: ControllerFactory.getController(controller)}, - pi: { value: pi}, - props3D: { value: p3d}, - shapeModel: { value: shapeProps}, - isShape: { value: isShape} - }); - - - } - }, - - ///// Element Model creation for existing elements based on element type. - ///// TODO: Selection and model should be based on the element type - makeModelFromElement: { - value: function(el) { - var selection = "div", - controller = "block", - isShape = false; - switch(el.nodeName.toLowerCase()) - { - case "div": - break; - case "img": - selection = "image"; - controller = "image"; - break; - case "video": - selection = "video"; - controller = "video"; - break; - case "canvas": - isShape = el.getAttribute("data-RDGE-id"); - if(isShape) { - // TODO - Need more info about the shape - selection = "canvas"; - controller = "shape"; - isShape = true; - } else { - selection = "canvas"; - controller = "canvas"; - } - break; - case "shape": - break; - } - this.makeElementModel(el, selection, controller, isShape); - if(el.elementModel && el.elementModel.props3D) { - el.elementModel.props3D.init(el, (selection === "Stage")); - } - } - }, - ///// Removes all child nodes and returns node ///// Accepts a single node, or an array of dom nodes empty : { -- cgit v1.2.3 From 2dca8a0aa69981bc2a81c4a68f9061aef861f0ea Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Wed, 6 Jun 2012 15:01:10 -0700 Subject: enable gradients for brush stroke (in authoring as well as runtime) --- js/lib/geom/brush-stroke.js | 1406 ++++++++++++++++++++++--------------------- 1 file changed, 732 insertions(+), 674 deletions(-) (limited to 'js/lib') 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() { this._planeMatInv = null; this._planeCenter = null; this._dragPlane = null; +}; //BrushStroke class defition - ///////////////////////////////////////////////////////// - // Property Accessors/Setters - ///////////////////////////////////////////////////////// - this.setCanvas = function(c) { - this._canvas = c; +BrushStroke.prototype = Object.create(GeomObj, {}); + +///////////////////////////////////////////////////////// +// Property Accessors/Setters +///////////////////////////////////////////////////////// +BrushStroke.prototype.setCanvas = function(c) { + this._canvas = c; +}; + +BrushStroke.prototype.setWorld = function (world) { + this._world = world; +}; + +BrushStroke.prototype.getWorld = function () { + return this._world; +}; + +BrushStroke.prototype.geomType = function () { + return this.GEOM_TYPE_BRUSH_STROKE; +}; + +BrushStroke.prototype.setDrawingTool = function (tool) { + this._drawingTool = tool; +}; + +BrushStroke.prototype.getDrawingTool = function () { + return this._drawingTool; +}; + +BrushStroke.prototype.setPlaneMatrix = function(planeMat){ + this._planeMat = planeMat; +}; + +BrushStroke.prototype.setPlaneMatrixInverse = function(planeMatInv){ + this._planeMatInv = planeMatInv; +}; + +BrushStroke.prototype.setPlaneCenter = function(pc){ + this._planeCenter = pc; +}; + +BrushStroke.prototype.setDragPlane = function(p){ + this._dragPlane = p; +}; + +BrushStroke.prototype.getNumPoints = function () { + if (this._LocalPoints.length) + return this._LocalPoints.length; + else + return this._Points.length; +}; + +BrushStroke.prototype.getPoint = function (index) { + return this._Points[index].slice(0); +}; + +BrushStroke.prototype.addPoint = function (pt) { + //add the point only if it is some epsilon away from the previous point + var numPoints = this._Points.length; + if (numPoints>0) { + var threshold = this._MIN_SAMPLE_DISTANCE_THRESHOLD; + var prevPt = this._Points[numPoints-1]; + var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]]; + var diffPtMag = Math.sqrt(diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]); + if (diffPtMag>threshold){ + this._Points.push(pt); + this._isDirty=true; + this._isInit = false; + } + } else { + this._Points.push(pt); + this._isDirty=true; + this._isInit = false; } +}; - this.setWorld = function (world) { - this._world = world; - }; +BrushStroke.prototype.insertPoint = function(pt, index){ + this._Points.splice(index, 0, pt); + this._isDirty=true; + this._isInit = false; +}; - this.getWorld = function () { - return this._world; - }; +BrushStroke.prototype.isDirty = function(){ + return this._isDirty; +}; - this.geomType = function () { - return this.GEOM_TYPE_BRUSH_STROKE; - }; +BrushStroke.prototype.makeDirty = function(){ + this._isDirty=true; +}; - this.setDrawingTool = function (tool) { - this._drawingTool = tool; - }; +BrushStroke.prototype.getStageWorldCenter = function() { + return this._stageWorldCenter; +}; - this.getDrawingTool = function () { - return this._drawingTool; - }; +BrushStroke.prototype.getBBoxMin = function () { + return this._BBoxMin; +}; - this.setPlaneMatrix = function(planeMat){ - this._planeMat = planeMat; - }; +BrushStroke.prototype.getBBoxMax = function () { + return this._BBoxMax; +}; - this.setPlaneMatrixInverse = function(planeMatInv){ - this._planeMatInv = planeMatInv; - }; +BrushStroke.prototype.getStrokeWidth = function () { + return this._strokeWidth; +}; - this.setPlaneCenter = function(pc){ - this._planeCenter = pc; - }; +BrushStroke.prototype.setStrokeWidth = function (w) { + this._strokeWidth = w; + if (this._strokeWidth<1) { + this._strokeWidth = 1; + } + this._isDirty=true; +}; - this.setDragPlane = function(p){ - this._dragPlane = p; - }; +BrushStroke.prototype.getStrokeMaterial = function () { + return this._strokeMaterial; +}; - this.getNumPoints = function () { - if (this._LocalPoints.length) - return this._LocalPoints.length; - else - return this._Points.length; - }; +BrushStroke.prototype.setStrokeMaterial = function (m) { + this._strokeMaterial = m; this._isDirty = true; +}; - this.getPoint = function (index) { - return this._Points[index].slice(0); - }; +BrushStroke.prototype.getStrokeColor = function () { + return this._strokeColor; +}; - this.addPoint = function (pt) { - //add the point only if it is some epsilon away from the previous point - var numPoints = this._Points.length; - if (numPoints>0) { - var threshold = this._MIN_SAMPLE_DISTANCE_THRESHOLD; - var prevPt = this._Points[numPoints-1]; - var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]]; - var diffPtMag = Math.sqrt(diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]); - if (diffPtMag>threshold){ - this._Points.push(pt); - this._isDirty=true; - this._isInit = false; - } - } else { - this._Points.push(pt); - this._isDirty=true; - this._isInit = false; - } - }; - - this.insertPoint = function(pt, index){ - this._Points.splice(index, 0, pt); - this._isDirty=true; - this._isInit = false; - }; +BrushStroke.prototype.setStrokeColor = function (c) { + this._strokeColor = c; this._isDirty = true; +}; - this.isDirty = function(){ - return this._isDirty; - }; +BrushStroke.prototype.setFillColor = function(c){ + return; +}; //NO-OP for now as we have no fill region - this.makeDirty = function(){ - this._isDirty=true; - }; +BrushStroke.prototype.setSecondStrokeColor = function(c){ + this._secondStrokeColor=c; this._isDirty = true; +}; - this.getStageWorldCenter = function() { - return this._stageWorldCenter; - }; +BrushStroke.prototype.setStrokeHardness = function(h){ + if (this._strokeHardness!==h){ + this._strokeHardness=h; + this._isDirty = true; + } +}; +BrushStroke.prototype.getStrokeHardness = function(){ + return this._strokeHardness; +}; + +BrushStroke.prototype.setDoSmoothing = function(s){ + if (this._strokeDoSmoothing!==s) { + this._strokeDoSmoothing = s; + this._isDirty = true; + } +}; - this.getBBoxMin = function () { - return this._BBoxMin; - }; +BrushStroke.prototype.getDoSmoothing = function(){ + return this._strokeDoSmoothing; +}; - this.getBBoxMax = function () { - return this._BBoxMax; - }; +BrushStroke.prototype.setSmoothingAmount = function(a){ + if (this._strokeAmountSmoothing!==a) { + this._strokeAmountSmoothing = a; + this._isDirty = true; + } +}; - this.getStrokeWidth = function () { - return this._strokeWidth; - }; +BrushStroke.prototype.getSmoothingAmount = function(){ + return this._strokeAmountSmoothing; +}; - this.setStrokeWidth = function (w) { - this._strokeWidth = w; - if (this._strokeWidth<1) { - this._strokeWidth = 1; - } - this._isDirty=true; - }; +BrushStroke.prototype.setStrokeUseCalligraphic = function(c){ + if (this._strokeUseCalligraphic!==c){ + this._strokeUseCalligraphic = c; + this._isDirty = true; + } +}; - this.getStrokeMaterial = function () { - return this._strokeMaterial; +BrushStroke.prototype.setStrokeAngle = function(a){ + if (this._strokeAngle!==a){ + this._strokeAngle = a; + this._isDirty = true; }; +}; - this.setStrokeMaterial = function (m) { - this._strokeMaterial = m; this._isDirty = true; - }; +BrushStroke.prototype.getStrokeUseCalligraphic = function(){ + return this._strokeUseCalligraphic; +}; - this.getStrokeColor = function () { - return this._strokeColor; - }; +BrushStroke.prototype.getStrokeAngle = function(){ + return this._strokeAngle; +}; - this.setStrokeColor = function (c) { - this._strokeColor = c; this._isDirty = true; - }; +BrushStroke.prototype.getStrokeStyle = function () { + return this._strokeStyle; +}; - this.setFillColor = function(c){ - return; - }; //NO-OP for now as we have no fill region +BrushStroke.prototype.setStrokeStyle = function (s) { + this._strokeStyle = s; +}; - this.setSecondStrokeColor = function(c){ - this._secondStrokeColor=c; this._isDirty = true; +BrushStroke.prototype.setWidth = function (newW) { + if (newW<1) { + newW=1; //clamp minimum width to 1 } - this.setStrokeHardness = function(h){ - if (this._strokeHardness!==h){ - this._strokeHardness=h; - this._isDirty = true; - } - } - this.getStrokeHardness = function(){ - return this._strokeHardness; + //scale the contents of this subpath to lie within this width + //determine the scale factor by comparing with the old width + var oldWidth = this._BBoxMax[0]-this._BBoxMin[0]; + if (oldWidth<1) { + oldWidth=1; } - this.setDoSmoothing = function(s){ - if (this._strokeDoSmoothing!==s) { - this._strokeDoSmoothing = s; - this._isDirty = true; - } + var scaleX = newW/oldWidth; + if (scaleX===1) { + return; //no need to do anything } - this.getDoSmoothing = function(){ - return this._strokeDoSmoothing; - } + //scale the local point positions such that the width of the bbox is the newW + var origX = this._BBoxMin[0]; + var numPoints = this._LocalPoints.length; + for (var i=0;ithreshold){ + //build the control polygon for the Catmull-Rom spline (prev. 2 points and next 2 points) + var prev = (i===1) ? i-1 : i-2; + var next = (i===numPoints-1) ? i : i+1; + var ctrlPts = [this._Points[prev], this._Points[i-1], this._Points[i], this._Points[next]]; + //insert points along the prev. to current point + var numNewPoints = Math.floor(distance/threshold); + for (var j=0;j this._MAX_ALLOWED_SAMPLES){ + console.log("leaving the resampling because numPoints is greater than limit:"+this._MAX_ALLOWED_SAMPLES); + break; } - this._isDirty = true; - }; + } + this._Points = newSampledPoints.slice(0); + newSampledPoints = []; +}; - this.getWidth = function() { - if (this._isDirty){ - this.update(); - } - return this._BBoxMax[0]-this._BBoxMin[0]; - }; +BrushStroke.prototype.init = function(){ + if (!this._isInit){ + // **** add samples to the _Points in stageworld space **** + this._addSamples(); - this.getHeight = function() { - if (this._isDirty){ - this.update(); - } - return this._BBoxMax[1]-this._BBoxMin[1]; - }; + // **** compute the 2D (canvas space) coord. of the _Points **** + this._buildLocalCoordFromStageWorldCoord(); - //remove all the points - this.clear = function () { - this._Points = []; - this._OrigLocalPoints = []; - this._isDirty=true; - this._isInit = false; - }; + // **** turn off the init. flag **** + this._isInit = true; + this._isDirty= true; + } - this._addSamples = function() { - //**** add samples to the long sections of the path --- Catmull-Rom spline interpolation ***** - // instead of the following, may use 4-point subdivision iterations over continuous regions of 'long' segments - // look at http://www.gvu.gatech.edu/~jarek/Split&Tweak/ for formula - - var numPoints = this._Points.length; - var numInsertedPoints = 0; - var newSampledPoints = []; - var threshold = this._MAX_SAMPLE_DISTANCE_THRESHOLD;//this determines whether a segment between two sample too long - var prevPt = this._Points[0]; - newSampledPoints.push(this._Points[0]); - for (var i=1;ithreshold){ - //build the control polygon for the Catmull-Rom spline (prev. 2 points and next 2 points) - var prev = (i===1) ? i-1 : i-2; - var next = (i===numPoints-1) ? i : i+1; - var ctrlPts = [this._Points[prev], this._Points[i-1], this._Points[i], this._Points[next]]; - //insert points along the prev. to current point - var numNewPoints = Math.floor(distance/threshold); - for (var j=0;j pt[d]) { + bboxMin[d] = pt[d]; } - newSampledPoints.push(pt); - prevPt=pt; - - //end this function if the numPoints has gone above the max. size specified - if (numPoints> this._MAX_ALLOWED_SAMPLES){ - console.log("leaving the resampling because numPoints is greater than limit:"+this._MAX_ALLOWED_SAMPLES); - break; + if (bboxMax[d] < pt[d]) { + bboxMax[d] = pt[d]; } } - this._Points = newSampledPoints.slice(0); - newSampledPoints = []; - }; + } + //save the center of the bbox for later use (while constructing the canvas) + this._stageWorldCenter = VecUtils.vecInterpolate(3, bboxMin, bboxMax, 0.5); + + // ***** center the input stageworld data about the center of the bbox ***** + this._LocalPoints = []; + 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 pt[d]) { - bboxMin[d] = pt[d]; + if (this._BBoxMin[d] > pt[d]) { + this._BBoxMin[d] = pt[d]; } - if (bboxMax[d] < pt[d]) { - bboxMax[d] = pt[d]; + if (this._BBoxMax[d] < pt[d]) { + this._BBoxMax[d] = pt[d]; } - } - } - //save the center of the bbox for later use (while constructing the canvas) - this._stageWorldCenter = VecUtils.vecInterpolate(3, bboxMin, bboxMax, 0.5); - - // ***** center the input stageworld data about the center of the bbox ***** - this._LocalPoints = []; - for (i=0;i