From 84332ab81c1b445195f1d9be8bbeae0725c8e758 Mon Sep 17 00:00:00 2001
From: Valerio Virgillito
Date: Tue, 6 Mar 2012 10:58:25 -0800
Subject: Squashed commit of preload-fix into Master

- Requiring all the previously pre-loaded files
- RDGE, Codemirror and gl-matrix are not included via a script tag.

Signed-off-by: Valerio Virgillito <valerio@motorola.com>
---
 js/lib/geom/brush-stroke.js | 482 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 482 insertions(+)
 create mode 100755 js/lib/geom/brush-stroke.js

(limited to 'js/lib/geom/brush-stroke.js')

diff --git a/js/lib/geom/brush-stroke.js b/js/lib/geom/brush-stroke.js
new file mode 100755
index 00000000..9a934928
--- /dev/null
+++ b/js/lib/geom/brush-stroke.js
@@ -0,0 +1,482 @@
+/* <copyright>
+This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
+No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
+(c) Copyright 2011 Motorola Mobility, Inc.  All Rights Reserved.
+</copyright> */
+
+// Todo: This entire class should be converted to a module
+var VecUtils = require("js/helper-classes/3D/vec-utils").VecUtils;
+var GeomObj = require("js/lib/geom/geom-obj").GeomObj;
+
+///////////////////////////////////////////////////////////////////////
+// Class GLBrushStroke
+//      representation a sequence points (polyline) created by brush tool.
+//      Derived from class GLGeomObj
+///////////////////////////////////////////////////////////////////////
+var BrushStroke = function GLBrushStroke() {
+    ///////////////////////////////////////////////////
+    // Instance variables
+    ///////////////////////////////////////////////////
+    this._Points = [];
+    this._BBoxMin = [0, 0, 0];
+    this._BBoxMax = [0, 0, 0];
+    this._dirty = true;
+
+    //whether or not to use the canvas drawing to stroke/fill
+    this._useCanvasDrawing = true;
+
+    //the X and Y location of this subpath's canvas in stage world space of Ninja
+    this._canvasX = 0;
+    this._canvasY = 0;
+
+    //stroke information
+    this._strokeWidth = 0.0;
+    this._strokeColor = [0.4, 0.4, 0.4, 1.0];
+    this._strokeMaterial = null;
+    this._strokeStyle = "Solid";
+
+    //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
+    //smaller value means more samples for the path
+    this._WETNESS_FACTOR = 0.25;
+
+    //prevent extremely long paths that can take a long time to render
+    this._MAX_ALLOWED_SAMPLES = 500;
+
+    //drawing context
+    this._world = null;
+
+    //tool that owns this brushstroke
+    this._drawingTool = null;
+    this._planeMat = null;
+    this._planeMatInv = null;
+    this._planeCenter = null;
+
+    /////////////////////////////////////////////////////////
+    // Property Accessors/Setters
+    /////////////////////////////////////////////////////////
+    this.setWorld = function (world) {
+        this._world = world;
+    };
+
+    this.getWorld = function () {
+        return this._world;
+    };
+
+    this.geomType = function () {
+        return this.GEOM_TYPE_CUBIC_BEZIER;
+    };
+
+    this.setDrawingTool = function (tool) {
+        this._drawingTool = tool;
+    };
+
+    this.getDrawingTool = function () {
+        return this._drawingTool;
+    };
+
+    this.setPlaneMatrix = function(planeMat){
+        this._planeMat = planeMat;
+    };
+
+    this.setPlaneMatrixInverse = function(planeMatInv){
+        this._planeMatInv = planeMatInv;
+    };
+
+    this.setPlaneCenter = function(pc){
+        this._planeCenter = pc;
+    };
+
+    this.getCanvasX = function(){
+        return this._canvasX;
+    };
+
+    this.getCanvasY = function(){
+        return this._canvasY;
+    };
+
+    this.setCanvasX = function(cx){
+        this._canvasX=cx;
+    };
+
+    this.setCanvasY = function(cy){
+        this._canvasY=cy;
+    };
+
+    this.getNumPoints = function () {
+        return this._Points.length;
+    };
+
+    this.getPoint = function (index) {
+        return this._Points[index];
+    };
+
+    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._WETNESS_FACTOR*this._strokeWidth;
+            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._dirty=true;
+            }
+        } else {
+            this._Points.push(pt);
+            this._dirty=true;
+        }
+    };
+    
+    this.insertPoint = function(pt, index){
+        this._Points.splice(index, 0, pt); this._dirty=true;
+    };
+
+    this.isDirty = function(){
+        return this._dirty;
+    };
+
+    this.makeDirty = function(){
+        this._dirty=true;
+    };
+
+    this.getBBoxMin = function () {
+        return this._BBoxMin;
+    };
+
+    this.getBBoxMax = function () {
+        return this._BBoxMax;
+    };
+
+    this.getStrokeWidth = function () {
+        return this._strokeWidth;
+    };
+
+    this.setStrokeWidth = function (w) {
+        this._strokeWidth = w;
+        this._dirty=true;
+    };
+
+    this.getStrokeMaterial = function () {
+        return this._strokeMaterial;
+    };
+
+    this.setStrokeMaterial = function (m) {
+        this._strokeMaterial = m;
+    };
+
+    this.getStrokeColor = function () {
+        return this._strokeColor;
+    };
+
+    this.setStrokeColor = function (c) {
+        this._strokeColor = c;
+    };
+
+    this.getStrokeStyle = function () {
+        return this._strokeStyle;
+    };
+
+    this.setStrokeStyle = function (s) {
+        this._strokeStyle = s;
+    };
+
+    this.setWidth = function () {
+
+    };//NO-OP for now
+
+    this.setHeight = function () {
+
+    };//NO-OP for now
+
+
+    //remove and return anchor at specified index, return null on error
+    this.removePoint = function (index) {
+        var retAnchor = null;
+        if (index < this._Points.length) {
+            retPt = this._Points.splice(index, 1);
+            this._dirty=true;
+        }
+        return retPoint;
+    };
+
+    //remove all the points
+    this.clear = function () {
+        this._Points = [];
+        this._dirty=true;
+    }
+
+    this.translate = function (tx, ty, tz) {
+        for (var i=0;i<this._Points.length;i++){
+            this._Points[i][0]+=tx;
+            this._Points[i][1]+=ty;
+            this._Points[i][2]+=tz;
+        }
+    };
+
+    this.computeMetaGeometry = function() {
+        if (this._dirty) {
+            var numPoints = this._Points.length;
+
+            //**** add samples to the path if needed...linear interpolation for now
+            if (numPoints>1) {
+                var threshold = this._WETNESS_FACTOR*this._strokeWidth;
+                var prevPt = this._Points[0];
+                var prevIndex = 0;
+                for (var i=1;i<numPoints;i++){
+                    var pt = this._Points[i];
+                    var diff = [pt[0]-prevPt[0], pt[1]-prevPt[1]];
+                    var distance = Math.sqrt(diff[0]*diff[0]+diff[1]*diff[1]);
+                    if (distance>threshold){
+                        //insert points along the prev. to current point
+                        var numNewPoints = Math.floor(distance/threshold);
+                        for (var j=0;j<numNewPoints;j++){
+                            var param = (j+1)/(numNewPoints+1);
+                            var newpt = [prevPt[0]+ diff[0]*param, prevPt[1]+ diff[1]*param];
+                            //insert new point before point i
+                            this._Points.splice(i, 0, [newpt[0], newpt[1], 0]);
+                            i++;
+                        }
+                        this._dirty=true;
+                    }
+                    prevPt=pt;
+                    //update numPoints to match the new length
+                    numPoints = this._Points.length;
+
+                    //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;
+                    }
+                }
+            }
+
+            // *** compute the bounding box *********
+            this._BBoxMin = [Infinity, Infinity, Infinity];
+            this._BBoxMax = [-Infinity, -Infinity, -Infinity];
+            numPoints = this._Points.length;
+            if (numPoints === 0) {
+                this._BBoxMin = [0, 0, 0];
+                this._BBoxMax = [0, 0, 0];
+            } else {
+                for (var i=0;i<numPoints;i++){
+                    var pt = this._Points[i];
+                    for (var d = 0; d < 3; d++) {
+                        if (this._BBoxMin[d] > pt[d]) {
+                            this._BBoxMin[d] = pt[d];
+                        }
+                        if (this._BBoxMax[d] < pt[d]) {
+                            this._BBoxMax[d] = pt[d];
+                        }
+                    }//for every dimension d from 0 to 2
+                }
+            }
+             //increase the bbox given the stroke width
+            for (var d = 0; d < 3; d++) {
+                this._BBoxMin[d]-= this._strokeWidth/2;
+                this._BBoxMax[d]+= this._strokeWidth/2;
+            }//for every dimension d from 0 to 2
+        }
+        this._dirty = false;
+    };
+
+    this.buildBuffers = function () {
+        //return; //no need to do anything for now
+    };//buildBuffers()
+
+    //render
+    //  specify how to render the subpath in Canvas2D
+    this.render = function () {
+        // get the world
+        var world = this.getWorld();
+        if (!world)  throw( "null world in brushstroke render" );
+
+         // get the context
+        var ctx = world.get2DContext();
+        if (!ctx)  throw ("null context in brushstroke render")
+
+        var numPoints = this.getNumPoints();
+        if (numPoints === 0) {
+            return; //nothing to do for empty paths
+        }
+
+        ctx.save();
+
+        this.computeMetaGeometry();
+        var bboxMin = this.getBBoxMin();
+        var bboxMax = this.getBBoxMax();
+        var bboxWidth = bboxMax[0] - bboxMin[0];
+        var bboxHeight = bboxMax[1] - bboxMin[1];
+        ctx.clearRect(0, 0, bboxWidth, bboxHeight);
+
+        /*
+        ctx.lineWidth = this._strokeWidth;
+        ctx.strokeStyle = "black";
+        if (this._strokeColor)
+            ctx.strokeStyle = MathUtils.colorToHex( this._strokeColor );
+        ctx.fillStyle = "blue";
+        if (this._fillColor)
+            ctx.fillStyle = MathUtils.colorToHex( this._fillColor );
+        var lineCap = ['butt','round','square'];
+        ctx.lineCap = lineCap[1];
+        ctx.beginPath();
+        var firstPoint = this._Points[0];
+        ctx.moveTo(firstPoint[0]-bboxMin[0], firstPoint[1]-bboxMin[1]);
+        for (var i = 1; i < numPoints; i++) {
+            var pt = this._Points[i];
+            ctx.lineTo(pt[0]-bboxMin[0], pt[1]-bboxMin[1]);
+        }
+        ctx.stroke();
+        */
+
+        /*
+        var isDebug = false;
+        var prevPt = this._Points[0];
+        var prevX = prevPt[0]-bboxMin[0];
+        var prevY = prevPt[1]-bboxMin[1];
+        prevPt = [prevX,prevY];
+        for (var i = 1; i < numPoints; i++) {
+            var pt = this._Points[i];
+            ctx.globalCompositeOperation = 'source-over';
+            var x = pt[0]-bboxMin[0];
+            var y = pt[1]-bboxMin[1];
+            pt = [x,y];
+
+            //vector from prev to current pt
+            var seg = VecUtils.vecSubtract(2, pt, prevPt);
+            var segDir = VecUtils.vecNormalize(2, seg, 1.0);
+
+            var segMidPt = VecUtils.vecInterpolate(2, pt, prevPt, 0.5);
+            var w2 = this._strokeWidth*0.5;
+            var segDirOrtho = [w2*segDir[1], -w2*segDir[0]];
+            
+            //add half the strokewidth to the segMidPt
+            var lgStart = VecUtils.vecAdd(2, segMidPt, segDirOrtho);
+            var lgEnd = VecUtils.vecSubtract(2, segMidPt, segDirOrtho);
+
+            ctx.save();
+            ctx.beginPath();
+
+            if (isDebug) {
+                ctx.strokeStyle="black";
+                ctx.lineWidth = 1;
+
+                ctx.moveTo(lgStart[0], lgStart[1]);
+                ctx.lineTo(lgEnd[0], lgEnd[1]);
+                ctx.stroke();
+            }
+
+            var lg = ctx.createLinearGradient(lgStart[0], lgStart[1], lgEnd[0], lgEnd[1]);
+            lg.addColorStop(1, 'rgba(0,0,0,0.0)');
+            lg.addColorStop(0.5,'rgba(255,0,0,1.0)');
+            lg.addColorStop(0, 'rgba(0,0,0,0.0)');
+            ctx.fillStyle = lg;
+
+            if (isDebug){
+                ctx.strokeStyle="blue";
+                ctx.lineWidth=0.5;
+            }
+            ctx.moveTo(prevX-w2, prevY);
+            ctx.lineTo(prevX+w2, prevY);
+            ctx.lineTo(x+w2, y);
+            ctx.lineTo(x-w2, y);
+            ctx.lineTo(prevX-w2, prevY);
+            ctx.fill();
+            ctx.closePath();
+
+            ctx.restore();
+
+            prevPt = pt;
+            prevX = x;
+            prevY = y;
+        }
+        
+
+        if (isDebug)
+            ctx.stroke();
+
+        if (isDebug){
+            //draw the skeleton of this stroke
+            ctx.lineWidth = 1;
+            ctx.strokeStyle = "black";
+            var pt = this._Points[0];
+            ctx.beginPath();
+            ctx.moveTo(pt[0]-bboxMin[0],pt[1]-bboxMin[1]);
+            for (var i = 1; i < numPoints; i++) {
+                pt = this._Points[i];
+                var x = pt[0]-bboxMin[0];
+                var y = pt[1]-bboxMin[1];
+                ctx.lineTo(x,y);
+            }
+            ctx.stroke();
+        }
+        */
+
+
+        var R2 = this._strokeWidth;
+        var R = R2*0.5;
+        var hardness = 0; //for a pencil, this is always 1 //TODO get hardness parameter from user interface
+        var innerRadius = (hardness*R)-1;
+        if (innerRadius<1)
+            innerRadius=1;
+
+        var r = ctx.createRadialGradient(0,0,innerRadius, 0,0,R);
+        var midColor = "rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+",1)";
+        r.addColorStop(0, midColor);
+        var endColor = "rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+",0.0)";
+        r.addColorStop(1, endColor);
+        ctx.fillStyle = r;
+
+        for (var i = 0; i < numPoints; i++) {
+            var pt = this._Points[i];
+            ctx.globalCompositeOperation = 'source-over';
+            var x = pt[0]-bboxMin[0];
+            var y = pt[1]-bboxMin[1];
+            ctx.save();
+            ctx.translate(x,y);
+            ctx.arc(0, 0, R, 0, 2 * Math.PI, false);
+            ctx.fill();
+            ctx.restore();
+            //ctx.globalCompositeOperation = 'source-in';
+            //ctx.rect(x-R, y-R, R2, R2);
+        }
+
+        ctx.restore();
+    }; //render()
+
+
+    this.export = function() {
+        return "type: " + this.geomType() + "\n";
+    };
+
+    this.import = function( importStr ) {
+
+    }
+
+    this.collidesWithPoint = function (x, y, z) {
+        if (x < this._BBoxMin[0]) return false;
+        if (x > this._BBoxMax[0]) return false;
+        if (y < this._BBoxMin[1]) return false;
+        if (y > this._BBoxMax[1]) return false;
+        if (z < this._BBoxMin[2]) return false;
+        if (z > this._BBoxMax[2]) return false;
+
+        return true;
+    };
+
+    this.collidesWithPoint = function (x, y) {
+        if (x < this._BBoxMin[0]) return false;
+        if (x > this._BBoxMax[0]) return false;
+        if (y < this._BBoxMin[1]) return false;
+        if (y > this._BBoxMax[1]) return false;
+
+        return true;
+    };
+
+}; //function GLSubpath ...class definition
+
+BrushStroke.prototype = new GeomObj();
+
+if (typeof exports === "object") {
+    exports.BrushStroke = BrushStroke;
+}
\ No newline at end of file
-- 
cgit v1.2.3