aboutsummaryrefslogtreecommitdiff
path: root/js/lib/geom/sub-path.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/lib/geom/sub-path.js')
-rwxr-xr-xjs/lib/geom/sub-path.js331
1 files changed, 183 insertions, 148 deletions
diff --git a/js/lib/geom/sub-path.js b/js/lib/geom/sub-path.js
index 4c5fe1eb..f765b715 100755
--- a/js/lib/geom/sub-path.js
+++ b/js/lib/geom/sub-path.js
@@ -68,175 +68,210 @@ var GLSubpath = function GLSubpath() {
68 this._selectedAnchorIndex = -1; 68 this._selectedAnchorIndex = -1;
69 69
70 this._SAMPLING_EPSILON = 0.5; //epsilon used for sampling the curve 70 this._SAMPLING_EPSILON = 0.5; //epsilon used for sampling the curve
71}; //function GLSubpath ...class definition
71 72
72 // (current GeomObj complains if buildBuffers/render is added to GLSubpath prototype) 73GLSubpath.prototype = Object.create(GeomObj, {});
73 //buildBuffers
74 // Build the stroke vertices, normals, textures and colors
75 // Add that array data to the GPU using OpenGL data binding
76 this.buildBuffers = function () {
77 // return; //no need to do anything for now
78 };
79
80 //render
81 // specify how to render the subpath in Canvas2D
82 this.render = function () {
83 // get the world
84 var world = this.getWorld();
85 if (!world) throw( "null world in subpath render" );
86 if (!this._canvas){
87 //set the canvas by querying the world
88 this._canvas = this.getWorld().getCanvas();
89 }
90 // get the context
91 var ctx = world.get2DContext();
92 if (!ctx) throw ("null context in subpath render");
93 74
94 var numAnchors = this.getNumAnchors(); 75//buildBuffers
95 if (numAnchors === 0) { 76GLSubpath.prototype.buildBuffers = function () {
96 return; //nothing to do for empty paths 77 //no need to do anything for now (no WebGL)
97 } 78};
98 this.createSamples(false); //dirty bit checked in this function...will generate a polyline representation
99 79
100 var numPoints = this._Samples.length; 80//buildColor returns the fillStyle or strokeStyle for the Canvas 2D context
101 if (numPoints === 0){ 81GLSubpath.prototype.buildColor = function(ctx, //the 2D rendering context (for creating gradients if necessary)
102 return; //nothing to do for empty paths 82 ipColor, //color string, also encodes whether there's a gradient and of what type
103 } 83 w, //width of the region of color
104 84 h, //height of the region of color
105 //figure the size of the area we will draw into 85 lw) //linewidth (i.e. stroke width/size)
106 var bboxWidth=0, bboxHeight=0; 86{
107 bboxWidth = this._BBoxMax[0] - this._BBoxMin[0]; 87 if (ipColor.gradientMode){
108 bboxHeight = this._BBoxMax[1] - this._BBoxMin[1]; 88 var position, gradient, cs, inset; //vars used in gradient calculations
109 89 inset = Math.ceil( lw ) - 0.5;
110 ctx.save();
111 ctx.clearRect(0, 0, bboxWidth, bboxHeight);
112
113 ctx.lineWidth = this._strokeWidth;
114 ctx.strokeStyle = "black";
115 if (this._strokeColor) {
116 //ctx.strokeStyle = MathUtils.colorToHex( this._strokeColor );
117 var strokeColorStr = "rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+this._strokeColor[3]+")";
118 ctx.strokeStyle = strokeColorStr;
119 }
120 90
121 ctx.fillStyle = "white"; 91 if(ipColor.gradientMode === "radial") {
122 if (this._fillColor){ 92 var ww = w - 2*lw, hh = h - 2*lw;
123 //ctx.fillStyle = MathUtils.colorToHex( this._fillColor ); 93 gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2, h/2, Math.max(ww, hh)/2);
124 var fillColorStr = "rgba("+parseInt(255*this._fillColor[0])+","+parseInt(255*this._fillColor[1])+","+parseInt(255*this._fillColor[2])+","+this._fillColor[3]+")"; 94 } else {
125 ctx.fillStyle = fillColorStr; 95 gradient = ctx.createLinearGradient(inset, h/2, w-inset, h/2);
126 }
127 var lineCap = ['butt','round','square'];
128 ctx.lineCap = lineCap[1];
129 var lineJoin = ['round','bevel','miter'];
130 ctx.lineJoin = lineJoin[0];
131
132 /*
133 commenting this out for now because of Chrome bug where coincident endpoints of bezier curve cause the curve to not be rendered
134 ctx.beginPath();
135 var prevAnchor = this.getAnchor(0);
136 ctx.moveTo(prevAnchor.getPosX()-bboxMin[0],prevAnchor.getPosY()-bboxMin[1]);
137 for (var i = 1; i < numAnchors; i++) {
138 var currAnchor = this.getAnchor(i);
139 ctx.bezierCurveTo(prevAnchor.getNextX()-bboxMin[0],prevAnchor.getNextY()-bboxMin[1], currAnchor.getPrevX()-bboxMin[0], currAnchor.getPrevY()-bboxMin[1], currAnchor.getPosX()-bboxMin[0], currAnchor.getPosY()-bboxMin[1]);
140 prevAnchor = currAnchor;
141 } 96 }
142 if (this._isClosed === true) { 97 var colors = ipColor.color;
143 var currAnchor = this.getAnchor(0); 98
144 ctx.bezierCurveTo(prevAnchor.getNextX()-bboxMin[0],prevAnchor.getNextY()-bboxMin[1], currAnchor.getPrevX()-bboxMin[0], currAnchor.getPrevY()-bboxMin[1], currAnchor.getPosX()-bboxMin[0], currAnchor.getPosY()-bboxMin[1]); 99 var len = colors.length;
145 prevAnchor = currAnchor; 100 for(n=0; n<len; n++) {
146 ctx.fill(); 101 position = colors[n].position/100;
102 cs = colors[n].value;
103 gradient.addColorStop(position, "rgba(" + cs.r + "," + cs.g + "," + cs.b + "," + cs.a + ")");
147 } 104 }
148 */ 105 return gradient;
106 } else {
107 var c = "rgba(" + 255*ipColor[0] + "," + 255*ipColor[1] + "," + 255*ipColor[2] + "," + ipColor[3] + ")";
108 return c;
109 }
110};
111//render
112// specify how to render the subpath in Canvas2D
113GLSubpath.prototype.render = function () {
114 // get the world
115 var world = this.getWorld();
116 if (!world) throw( "null world in subpath render" );
117 if (!this._canvas){
118 //set the canvas by querying the world
119 this._canvas = this.getWorld().getCanvas();
120 }
121 // get the context
122 var ctx = world.get2DContext();
123 if (!ctx) throw ("null context in subpath render");
149 124
125 var numAnchors = this.getNumAnchors();
126 if (numAnchors === 0) {
127 return; //nothing to do for empty paths
128 }
129 this.createSamples(false); //dirty bit checked in this function...will generate a polyline representation
150 130
151 ctx.beginPath(); 131 var numPoints = this._Samples.length;
152 ctx.moveTo(this._Samples[0][0],this._Samples[0][1]); 132 if (numPoints === 0){
153 for (var i=0;i<numPoints;i++){ 133 return; //nothing to do for empty paths
154 ctx.lineTo(this._Samples[i][0],this._Samples[i][1]); 134 }
155 }
156 if (this._isClosed === true) {
157 ctx.lineTo(this._Samples[0][0],this._Samples[0][1]);
158 }
159 ctx.fill();
160 ctx.stroke();
161 ctx.restore();
162 }; //render()
163
164 this.geomType = function () {
165 return this.GEOM_TYPE_CUBIC_BEZIER;
166 };
167
168 this.setWidth = function (newW) {
169 if (newW<1) {
170 newW=1; //clamp minimum width to 1
171 }
172 135
173 //scale the contents of this subpath to lie within this width 136 //figure the size of the area we will draw into
174 //determine the scale factor by comparing with the old width 137 var bboxWidth=0, bboxHeight=0;
175 var oldWidth = this._BBoxMax[0]-this._BBoxMin[0]; 138 bboxWidth = this._BBoxMax[0] - this._BBoxMin[0];
176 if (oldWidth<1) { 139 bboxHeight = this._BBoxMax[1] - this._BBoxMin[1];
177 oldWidth=1;
178 }
179 140
180 var scaleX = newW/oldWidth; 141 ctx.save();
181 if (scaleX===1) { 142 ctx.clearRect(0, 0, bboxWidth, bboxHeight);
182 return; //no need to do anything
183 }
184 143
185 //scale the anchor point positions such that the width of the bbox is the newW 144 ctx.lineWidth = this._strokeWidth;
186 var origX = this._BBoxMin[0]; 145 ctx.strokeStyle = "black";
187 var numAnchors = this._Anchors.length;
188 for (var i=0;i<numAnchors;i++){
189 //compute the distance from the bboxMin
190 var oldW = this._Anchors[i].getPosX() - origX;
191 var prevW = this._Anchors[i].getPrevX() - origX;
192 var nextW = this._Anchors[i].getNextX() - origX;
193
194 this._Anchors[i].setPos(origX + oldW*scaleX,this._Anchors[i].getPosY(),this._Anchors[i].getPosZ());
195 this._Anchors[i].setPrevPos(origX + prevW*scaleX,this._Anchors[i].getPrevY(),this._Anchors[i].getPrevZ());
196 this._Anchors[i].setNextPos(origX + nextW*scaleX,this._Anchors[i].getNextY(),this._Anchors[i].getNextZ());
197 }
198 this.makeDirty();
199 };
200 146
201 this.setHeight = function (newH) { 147 //vars used for the gradient computation in buildColor
202 if (newH<1) { 148 var w = world.getViewportWidth(), h = world.getViewportHeight();
203 newH=1; //clamp minimum width to 1
204 }
205 //scale the contents of this subpath to lie within this height
206 //determine the scale factor by comparing with the old height
207 var oldHeight = this._BBoxMax[1]-this._BBoxMin[1];
208 if (oldHeight<1){
209 oldHeight=1;
210 }
211 149
212 var scaleY = newH/oldHeight; 150 if (this._strokeColor) {
213 if (scaleY===1){ 151 ctx.strokeStyle = this.buildColor(ctx, this._strokeColor, w,h, this._strokeWidth);
214 return; //no need to do anything 152 }
215 }
216 153
217 //scale the anchor point positions such that the height of the bbox is the newH 154 ctx.fillStyle = "white";
218 var origY = this._BBoxMin[1]; 155 if (this._fillColor){
219 var numAnchors = this._Anchors.length; 156 ctx.fillStyle = this.buildColor(ctx, this._fillColor, w, h, this._strokeWidth);
220 for (var i=0;i<numAnchors;i++){ 157 }
221 //compute the distance from the bboxMin 158 var lineCap = ['butt','round','square'];
222 var oldW = this._Anchors[i].getPosY() - origY; 159 ctx.lineCap = lineCap[1];
223 var prevW = this._Anchors[i].getPrevY() - origY; 160 var lineJoin = ['round','bevel','miter'];
224 var nextW = this._Anchors[i].getNextY() - origY; 161 ctx.lineJoin = lineJoin[0];
225 162
226 this._Anchors[i].setPos(this._Anchors[i].getPosX(), origY + oldW*scaleY,this._Anchors[i].getPosZ()); 163
227 this._Anchors[i].setPrevPos(this._Anchors[i].getPrevX(), origY + prevW*scaleY,this._Anchors[i].getPrevZ()); 164 //commenting this out for now because of Chrome bug where coincident endpoints of bezier curve cause the curve to not be rendered
228 this._Anchors[i].setNextPos(this._Anchors[i].getNextX(), origY + nextW*scaleY,this._Anchors[i].getNextZ()); 165 /*
229 } 166 ctx.beginPath();
230 this.makeDirty(); 167 var prevAnchor = this.getAnchor(0);
168 ctx.moveTo(prevAnchor.getPosX(),prevAnchor.getPosY());
169 for (var i = 1; i < numAnchors; i++) {
170 var currAnchor = this.getAnchor(i);
171 ctx.bezierCurveTo(prevAnchor.getNextX(),prevAnchor.getNextY(), currAnchor.getPrevX(), currAnchor.getPrevY(), currAnchor.getPosX(), currAnchor.getPosY());
172 prevAnchor = currAnchor;
173 }
174 if (this._isClosed === true) {