From 91a9e02bff0397ec9b1f55fdf61cef72eb0d8a0f Mon Sep 17 00:00:00 2001 From: hwc487 Date: Tue, 8 May 2012 15:53:35 -0700 Subject: Radial gradients to match CSS --- js/lib/geom/circle.js | 3 +++ js/lib/geom/rectangle.js | 13 ++----------- js/lib/geom/shape-primitive.js | 27 +++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 11 deletions(-) (limited to 'js/lib/geom') diff --git a/js/lib/geom/circle.js b/js/lib/geom/circle.js index 0f1f49a9..afeed449 100755 --- a/js/lib/geom/circle.js +++ b/js/lib/geom/circle.js @@ -279,6 +279,7 @@ var Circle = function GLCircle() { if (fillPrim) { fillMaterial = this.makeFillMaterial(); + fillMaterial.fitToPrimitive( fillPrim ); this._primArray.push( fillPrim ); this._materialNodeArray.push( fillMaterial.getMaterialNode() ); @@ -286,6 +287,7 @@ var Circle = function GLCircle() { if (strokePrim0) { strokeMaterial0 = this.makeStrokeMaterial(); + strokeMaterial0.fitToPrimitive( strokePrim0 ); this._primArray.push( strokePrim0 ); this._materialNodeArray.push( strokeMaterial0.getMaterialNode() ); @@ -293,6 +295,7 @@ var Circle = function GLCircle() { if (strokePrim1) { strokeMaterial2 = this.makeStrokeMaterial(); + strokeMaterial2.fitToPrimitive( strokePrim1 ); this._primArray.push( strokePrim1 ); this._materialNodeArray.push( strokeMaterial2.getMaterialNode() ); diff --git a/js/lib/geom/rectangle.js b/js/lib/geom/rectangle.js index 490a9a6f..296ed024 100755 --- a/js/lib/geom/rectangle.js +++ b/js/lib/geom/rectangle.js @@ -57,13 +57,10 @@ var Rectangle = function GLRectangle() { this._strokeStyle = strokeStyle; this._matrix = Matrix.I(4); - //this._matrix[12] = xoffset; - //this._matrix[13] = yoffset; } // the overall radius includes the fill and the stroke. separate the two based onthe stroke width // this._fillRad = this._radius - this._strokeWidth; - // var err = 0.05; var err = 0; this._fillWidth = this._width - this._strokeWidth + err; this._fillHeight = this._height - this._strokeWidth + err; @@ -116,18 +113,10 @@ var Rectangle = function GLRectangle() { return this._strokeColor; }; - //this.setStrokeColor = function(c) { - // this._strokeColor = c; - // }; - this.getFillColor = function() { return this._fillColor; }; - //this.setFillColor = function(c) { - // this._fillColor = c.slice(0); - // }; - this.getTLRadius = function() { return this._tlRadius; }; @@ -324,6 +313,7 @@ var Rectangle = function GLRectangle() { // stroke var strokeMaterial = this.makeStrokeMaterial(); var strokePrim = this.createStroke([x,y], 2*xFill, 2*yFill, strokeSize, tlRadius, blRadius, brRadius, trRadius, strokeMaterial); + strokeMaterial.fitToPrimitive( strokePrim ); this._primArray.push( strokePrim ); this._materialNodeArray.push( strokeMaterial.getMaterialNode() ); @@ -337,6 +327,7 @@ var Rectangle = function GLRectangle() { var fillMaterial = this.makeFillMaterial(); //console.log( "fillMaterial: " + fillMaterial.getName() ); var fillPrim = this.createFill([x,y], 2*xFill, 2*yFill, tlRadius, blRadius, brRadius, trRadius, fillMaterial); + fillMaterial.fitToPrimitive( fillPrim ); this._primArray.push( fillPrim ); this._materialNodeArray.push( fillMaterial.getMaterialNode() ); diff --git a/js/lib/geom/shape-primitive.js b/js/lib/geom/shape-primitive.js index 97873d32..9864a8e9 100644 --- a/js/lib/geom/shape-primitive.js +++ b/js/lib/geom/shape-primitive.js @@ -49,6 +49,33 @@ ShapePrimitive.create = function(coords, normals, uvs, indices, primType, ver return prim; }; +ShapePrimitive.getBounds = function( prim ) +{ + var verts = prim.bufferStreams[0]; + var nVerts = verts.length; + var xMin = verts[0], xMax = verts[0], + yMin = verts[1], yMax = verts[1], + zMin = verts[2], zMax = verts[2]; + + for (var index=3; index<verts.length; ) + { + if (verts[index] < xMin) xMin = verts[index]; + else if (verts[index] > xMax) xMax = verts[index]; + + index++; + if (verts[index] < yMin) yMin = verts[index]; + else if (verts[index] > yMax) yMax = verts[index]; + + index++; + if (verts[index] < zMin) zMin = verts[index]; + else if (verts[index] > zMax) zMax = verts[index]; + + index++; + } + + return [xMin, yMin, zMin, xMax, yMax, zMax]; +}; + if (typeof exports === "object") { exports.ShapePrimitive = ShapePrimitive; } \ No newline at end of file -- cgit v1.2.3 From 02e5fbb819f02d26a8a7179cf04021a0f6c6ddf6 Mon Sep 17 00:00:00 2001 From: hwc487 Date: Mon, 14 May 2012 16:41:04 -0700 Subject: base canvas 2d rendering of radial gradient on size of the filled region only --- js/lib/geom/rectangle.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'js/lib/geom') diff --git a/js/lib/geom/rectangle.js b/js/lib/geom/rectangle.js index cf0e7fc8..4415af43 100755 --- a/js/lib/geom/rectangle.js +++ b/js/lib/geom/rectangle.js @@ -537,7 +537,8 @@ exports.Rectangle = Object.create(GeomObj, { if(this._fillColor.gradientMode) { if(this._fillColor.gradientMode === "radial") { - gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2, h/2, Math.max(w, h)/2); + var ww = w - 2*lw, hh = h - 2*lw; + gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2-this._strokeWidth, h/2, Math.max(ww, hh)/2); } else { gradient = ctx.createLinearGradient(inset/2, h/2, w-inset, h/2); } -- cgit v1.2.3 From cb37bee07085690d72e69a82e76cae9166e5f0f1 Mon Sep 17 00:00:00 2001 From: hwc487 Date: Tue, 15 May 2012 16:02:27 -0700 Subject: Gradient matching between WebGL and Canvas2D --- js/lib/geom/circle.js | 119 +++++++++++------------------- js/lib/geom/rectangle.js | 183 ++++++++++++++++++++++++----------------------- 2 files changed, 134 insertions(+), 168 deletions(-) (limited to 'js/lib/geom') diff --git a/js/lib/geom/circle.js b/js/lib/geom/circle.js index b60ad58f..2ca4c1f5 100755 --- a/js/lib/geom/circle.js +++ b/js/lib/geom/circle.js @@ -505,9 +505,9 @@ exports.Circle = Object.create(GeomObj, { if(this._fillColor.gradientMode) { if(this._fillColor.gradientMode === "radial") { gradient = ctx.createRadialGradient(xCtr, yCtr, 0, - xCtr, yCtr, Math.max(this._width, this._height)/2); + xCtr, yCtr, Math.max(this._width, this._height)/2 - lineWidth); } else { - gradient = ctx.createLinearGradient(lineWidth/2, this._height/2, this._width-lineWidth, this._height/2); + gradient = ctx.createLinearGradient(lineWidth, this._height/2, this._width-lineWidth, this._height/2); } colors = this._fillColor.color; @@ -804,79 +804,44 @@ exports.Circle = Object.create(GeomObj, { } }, - /* - this.getNearPoint = function( pt, dir ) { - var world = this.getWorld(); - if (!world) throw( "null world in getNearPoint" ); - - // get a point on the plane of the circle - // the point is in NDC, as is the input parameters - var mat = this.getMatrix(); - var plane = [0,0,1,0]; - plane = MathUtils.transformPlane( plane, mat ); - var projPt = MathUtils.vecIntersectPlane ( pt, dir, plane ); - - // transform the projected point back to the XY plane - //var invMat = mat.inverse(); - var invMat = glmat4.inverse( mat, [] ); - var planePt = MathUtils.transformPoint( projPt, invMat ); - - // get the normalized device coordinates (NDC) for - // the position and radii. - var vpw = world.getViewportWidth(), vph = world.getViewportHeight(); - var xNDC = 2*this._xOffset/vpw, yNDC = -2*this._yOffset/vph, - xRadNDC = this._width/vpw, yRadNDC = this._height/vph; - var projMat = world.makePerspectiveMatrix(); - var z = -world.getViewDistance(); - var planePtNDC = planePt.slice(0); - planePtNDC[2] = z; - planePtNDC = MathUtils.transformHomogeneousPoint( planePtNDC, projMat ); - planePtNDC = MathUtils.applyHomogeneousCoordinate( planePtNDC ); - - // get the gl coordinates - var aspect = world.getAspect(); - var zn = world.getZNear(), zf = world.getZFar(); - var t = zn * Math.tan(world.getFOV() * Math.PI / 360.0), - b = -t, - r = aspect*t, - l = -r; - - var angle = Math.atan2( planePtNDC[1] - yNDC, planePtNDC[0] - xNDC ); - var degrees = angle*180.0/Math.PI; - var objPt = [Math.cos(angle)*xRadNDC + xNDC, Math.sin(angle)*yRadNDC + yNDC, 0]; - - // convert to GL coordinates - objPt[0] = -z*(r-l)/(2.0*zn)*objPt[0]; - objPt[1] = -z*(t-b)/(2.0*zn)*objPt[1]; - - // re-apply the transform - objPt = MathUtils.transformPoint( objPt, mat ); - - return objPt; - }; - */ - recalcTexMapCoords: { - value: function(vrts, uvs) { - var n = vrts.length/3; - var ivrt = 0, iuv = 0; - var uMin = 1.e8, uMax = -1.e8, - vMin = 1.e8, vMax = -1.e8; - - for (var i=0; i<n; i++) { - uvs[iuv] = 0.5*(vrts[ivrt]/this._ovalWidth + 1); - if (uvs[iuv] < uMin) uMin = uvs[iuv]; - if (uvs[iuv] > uMax) uMax = uvs[iuv]; - - iuv++; ivrt++; - uvs[iuv] = 0.5*(vrts[ivrt]/this._ovalHeight + 1); - if (uvs[iuv] < vMin) vMin = uvs[iuv]; - if (uvs[iuv] > vMax) vMax = uvs[iuv]; - iuv++; ivrt += 2; - } - - //console.log( "remap: " + uvs ); - //console.log( "uRange: " + uMin + " => " + uMax ); - //console.log( "vRange: " + vMin + " => " + vMax ); - } - } + recalcTexMapCoords: { + value: function(vrts, uvs) { + var n = vrts.length/3; + if (n === 0) return; + var ivrt = 0, iuv = 0; + var uMin = 1.e8, uMax = -1.e8, + vMin = 1.e8, vMax = -1.e8; + + var i, index = 3; + var xMin = vrts[0], xMax = vrts[0], + yMin = vrts[1], yMax = vrts[1]; + for (i=1; i<n; i++) + { + if (vrts[index] < xMin) xMin = vrts[index]; + else if (vrts[index] > xMax) xMax = vrts[index]; + + if (vrts[index+1] < yMin) yMin = vrts[index+1]; + else if (vrts[index+1] > yMax) yMax = vrts[index+1]; + + index += 3; + } + var ovalWidth = xMax - xMin, + ovalHeight = yMax - yMin; + for (i=0; i<n; i++) { + uvs[iuv] = (vrts[ivrt]-xMin)/ovalWidth; + if (uvs[iuv] < uMin) uMin = uvs[iuv]; + if (uvs[iuv] > uMax) uMax = uvs[iuv]; + + iuv++; ivrt++; + uvs[iuv] = (vrts[ivrt]-yMin)/ovalHeight; + if (uvs[iuv] < vMin) vMin = uvs[iuv]; + if (uvs[iuv] > vMax) vMax = uvs[iuv]; + iuv++; ivrt += 2; + } + + //console.log( "remap" ); + //console.log( "uRange: " + uMin + " => " + uMax ); + //console.log( "vRange: " + vMin + " => " + vMax ); + } + } }); \ No newline at end of file diff --git a/js/lib/geom/rectangle.js b/js/lib/geom/rectangle.js index 4415af43..8fc80c60 100755 --- a/js/lib/geom/rectangle.js +++ b/js/lib/geom/rectangle.js @@ -508,98 +508,99 @@ exports.Rectangle = Object.create(GeomObj, { }, render: { - value: function() { - // get the world - var world = this.getWorld(); - if (!world) throw( "null world in rectangle render" ); - - // get the context - var ctx = world.get2DContext(); - if (!ctx) return; - - // get some dimensions - var lw = this._strokeWidth; - var w = world.getViewportWidth(), - h = world.getViewportHeight(); - - var c, - inset, - gradient, - colors, - len, - n, - position, - cs; - // render the fill - ctx.beginPath(); - if (this._fillColor) { - inset = Math.ceil( lw ) - 0.5; - - if(this._fillColor.gradientMode) { - if(this._fillColor.gradientMode === "radial") { + value: function() { + // get the world + var world = this.getWorld(); + if (!world) throw( "null world in rectangle render" ); + + // get the context + var ctx = world.get2DContext(); + if (!ctx) return; + + // get some dimensions + var lw = this._strokeWidth; + var w = world.getViewportWidth(), + h = world.getViewportHeight(); + + var c, + inset, + gradient, + colors, + len, + n, + position, + cs; + // render the fill + ctx.beginPath(); + if (this._fillColor) { + inset = Math.ceil( lw ) - 0.5; + + if(this._fillColor.gradientMode) { + if(this._fillColor.gradientMode === "radial") { var ww = w - 2*lw, hh = h - 2*lw; - gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2-this._strokeWidth, h/2, Math.max(ww, hh)/2); - } else { - gradient = ctx.createLinearGradient(inset/2, h/2, w-inset, h/2); - } - colors = this._fillColor.color; - - len = colors.length; - - for(n=0; n<len; n++) { - position = colors[n].position/100; - cs = colors[n].value; - gradient.addColorStop(position, "rgba(" + cs.r + "," + cs.g + "," + cs.b + "," + cs.a + ")"); - } - - ctx.fillStyle = gradient; - - } else { - c = "rgba(" + 255*this._fillColor[0] + "," + 255*this._fillColor[1] + "," + 255*this._fillColor[2] + "," + this._fillColor[3] + ")"; - ctx.fillStyle = c; - } - - ctx.lineWidth = lw; - this.renderPath( inset, ctx ); - ctx.fill(); - ctx.closePath(); - } - - // render the stroke - ctx.beginPath(); - if (this._strokeColor) { - inset = Math.ceil( 0.5*lw ) - 0.5; - - if(this._strokeColor.gradientMode) { - if(this._strokeColor.gradientMode === "radial") { - gradient = ctx.createRadialGradient(w/2, h/2, Math.min(h, w)/2-inset, w/2, h/2, Math.max(h, w)/2); - } else { - gradient = ctx.createLinearGradient(0, h/2, w, h/2); - } - colors = this._strokeColor.color; - - len = colors.length; - - for(n=0; n<len; n++) { - position = colors[n].position/100; - cs = colors[n].value; - gradient.addColorStop(position, "rgba(" + cs.r + "," + cs.g + "," + cs.b + "," + cs.a + ")"); - } - - ctx.strokeStyle = gradient; - - } else { - c = "rgba(" + 255*this._strokeColor[0] + "," + 255*this._strokeColor[1] + "," + 255*this._strokeColor[2] + "," + this._strokeColor[3] + ")"; - ctx.strokeStyle = c; - } - - ctx.lineWidth = lw; - this.renderPath( inset, ctx ); - ctx.stroke(); - ctx.closePath(); - } - } - }, + //gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2-this._strokeWidth, h/2, Math.max(ww, hh)/2); + gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2, h/2, Math.max(ww, hh)/2); + } else { + gradient = ctx.createLinearGradient(inset/2, h/2, w-inset, h/2); + } + colors = this._fillColor.color; + + len = colors.length; + + for(n=0; n<len; n++) { + position = colors[n].position/100; + cs = colors[n].value; + gradient.addColorStop(position, "rgba(" + cs.r + "," + cs.g + "," + cs.b + "," + cs.a + ")"); + } + + ctx.fillStyle = gradient; + + } else { + c = "rgba(" + 255*this._fillColor[0] + "," + 255*this._fillColor[1] + "," + 255*this._fillColor[2] + "," + this._fillColor[3] + ")"; + ctx.fillStyle = c; + } + + ctx.lineWidth = lw; + this.renderPath( inset, ctx ); + ctx.fill(); + ctx.closePath(); + } + + // render the stroke + ctx.beginPath(); + if (this._strokeColor) { + inset = Math.ceil( 0.5*lw ) - 0.5; + + if(this._strokeColor.gradientMode) { + if(this._strokeColor.gradientMode === "radial") { + gradient = ctx.createRadialGradient(w/2, h/2, Math.min(h, w)/2-inset, w/2, h/2, Math.max(h, w)/2); + } else { + gradient = ctx.createLinearGradient(0, h/2, w, h/2); + } + colors = this._strokeColor.color; + + len = colors.length; + + for(n=0; n<len; n++) { + position = colors[n].position/100; + cs = colors[n].value; + gradient.addColorStop(position, "rgba(" + cs.r + "," + cs.g + "," + cs.b + "," + cs.a + ")"); + } + + ctx.strokeStyle = gradient; + + } else { + c = "rgba(" + 255*this._strokeColor[0] + "," + 255*this._strokeColor[1] + "," + 255*this._strokeColor[2] + "," + this._strokeColor[3] + ")"; + ctx.strokeStyle = c; + } + + ctx.lineWidth = lw; + this.renderPath( inset, ctx ); + ctx.stroke(); + ctx.closePath(); + } + } + }, createStroke: { value: function(ctr, width, height, strokeWidth, tlRad, blRad, brRad, trRad, material) { -- cgit v1.2.3 From 651341341f894c4d0def267ab3250e77f7d0c276 Mon Sep 17 00:00:00 2001 From: hwc487 Date: Thu, 17 May 2012 16:52:38 -0700 Subject: canvas 2d radial gradient render problem. --- js/lib/geom/rectangle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/lib/geom') diff --git a/js/lib/geom/rectangle.js b/js/lib/geom/rectangle.js index 8fc80c60..711245ae 100755 --- a/js/lib/geom/rectangle.js +++ b/js/lib/geom/rectangle.js @@ -541,7 +541,7 @@ exports.Rectangle = Object.create(GeomObj, { //gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2-this._strokeWidth, h/2, Math.max(ww, hh)/2); gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2, h/2, Math.max(ww, hh)/2); } else { - gradient = ctx.createLinearGradient(inset/2, h/2, w-inset, h/2); + gradient = ctx.createLinearGradient(inset, h/2, w-inset, h/2); } colors = this._fillColor.color; -- cgit v1.2.3 From 6b03f357f45d76733ae7bf5ff52ffe2fb2a84fda Mon Sep 17 00:00:00 2001 From: hwc487 Date: Fri, 18 May 2012 12:35:58 -0700 Subject: Updates for WebGL/Canvas 2D authortime and runtime gradients. --- js/lib/geom/circle.js | 2 +- js/lib/geom/rectangle.js | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'js/lib/geom') diff --git a/js/lib/geom/circle.js b/js/lib/geom/circle.js index 2ca4c1f5..4a369844 100755 --- a/js/lib/geom/circle.js +++ b/js/lib/geom/circle.js @@ -581,7 +581,7 @@ exports.Circle = Object.create(GeomObj, { if (this._strokeColor) { if(this._strokeColor.gradientMode) { if(this._strokeColor.gradientMode === "radial") { - gradient = ctx.createRadialGradient(xCtr, yCtr, Math.min(xScale, yScale), + gradient = ctx.createRadialGradient(xCtr, yCtr, 0, xCtr, yCtr, 0.5*Math.max(this._height, this._width)); } else { gradient = ctx.createLinearGradient(0, this._height/2, this._width, this._height/2); diff --git a/js/lib/geom/rectangle.js b/js/lib/geom/rectangle.js index 711245ae..b85433a0 100755 --- a/js/lib/geom/rectangle.js +++ b/js/lib/geom/rectangle.js @@ -507,7 +507,7 @@ exports.Rectangle = Object.create(GeomObj, { } }, - render: { + render: { value: function() { // get the world var world = this.getWorld(); @@ -538,7 +538,6 @@ exports.Rectangle = Object.create(GeomObj, { if(this._fillColor.gradientMode) { if(this._fillColor.gradientMode === "radial") { var ww = w - 2*lw, hh = h - 2*lw; - //gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2-this._strokeWidth, h/2, Math.max(ww, hh)/2); gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2, h/2, Math.max(ww, hh)/2); } else { gradient = ctx.createLinearGradient(inset, h/2, w-inset, h/2); @@ -572,11 +571,10 @@ exports.Rectangle = Object.create(GeomObj, { inset = Math.ceil( 0.5*lw ) - 0.5; if(this._strokeColor.gradientMode) { - if(this._strokeColor.gradientMode === "radial") { - gradient = ctx.createRadialGradient(w/2, h/2, Math.min(h, w)/2-inset, w/2, h/2, Math.max(h, w)/2); - } else { + if(this._strokeColor.gradientMode === "radial") + gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2, h/2, Math.max(h, w)/2); + else gradient = ctx.createLinearGradient(0, h/2, w, h/2); - } colors = this._strokeColor.color; len = colors.length; -- cgit v1.2.3 From 75a862d305bc4502e22bc5aa65fa271143b8cf6c Mon Sep 17 00:00:00 2001 From: Pushkar Joshi Date: Thu, 31 May 2012 12:18:43 -0700 Subject: move all the subpath functions to its prototype, and first version of the pen path runtime --- js/lib/geom/sub-path.js | 311 ++++++++++++++++++++++++------------------------ 1 file changed, 156 insertions(+), 155 deletions(-) (limited to 'js/lib/geom') diff --git a/js/lib/geom/sub-path.js b/js/lib/geom/sub-path.js index a9034def..db115655 100755 --- a/js/lib/geom/sub-path.js +++ b/js/lib/geom/sub-path.js @@ -68,178 +68,179 @@ var GLSubpath = function GLSubpath() { this._selectedAnchorIndex = -1; this._SAMPLING_EPSILON = 0.5; //epsilon used for sampling the curve +}; //function GLSubpath ...class definition - // (current GeomObj complains if buildBuffers/render is added to GLSubpath prototype) - //buildBuffers - // Build the stroke vertices, normals, textures and colors - // Add that array data to the GPU using OpenGL data binding - this.buildBuffers = function () { - // return; //no need to do anything for now - }; - - //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 subpath render" ); - if (!this._canvas){ - //set the canvas by querying the world - this._canvas = this.getWorld().getCanvas(); - } - // get the context - var ctx = world.get2DContext(); - if (!ctx) throw ("null context in subpath render"); - - var numAnchors = this.getNumAnchors(); - if (numAnchors === 0) { - return; //nothing to do for empty paths - } - this.createSamples(false); //dirty bit checked in this function...will generate a polyline representation +GLSubpath.prototype = Object.create(GeomObj, {}); - var numPoints = this._Samples.length; - if (numPoints === 0){ - return; //nothing to do for empty paths - } - - //figure the size of the area we will draw into - var bboxWidth=0, bboxHeight=0; - bboxWidth = this._BBoxMax[0] - this._BBoxMin[0]; - bboxHeight = this._BBoxMax[1] - this._BBoxMin[1]; - - ctx.save(); - ctx.clearRect(0, 0, bboxWidth, bboxHeight); - - ctx.lineWidth = this._strokeWidth; - ctx.strokeStyle = "black"; - if (this._strokeColor) { - //ctx.strokeStyle = MathUtils.colorToHex( this._strokeColor ); - var strokeColorStr = "rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+this._strokeColor[3]+")"; - ctx.strokeStyle = strokeColorStr; - } +//buildBuffers +GLSubpath.prototype.buildBuffers = function () { + //no need to do anything for now (no WebGL) +}; - ctx.fillStyle = "white"; - if (this._fillColor){ - //ctx.fillStyle = MathUtils.colorToHex( this._fillColor ); - var fillColorStr = "rgba("+parseInt(255*this._fillColor[0])+","+parseInt(255*this._fillColor[1])+","+parseInt(255*this._fillColor[2])+","+this._fillColor[3]+")"; - ctx.fillStyle = fillColorStr; - } - var lineCap = ['butt','round','square']; - ctx.lineCap = lineCap[1]; - var lineJoin = ['round','bevel','miter']; - ctx.lineJoin = lineJoin[0]; - - /* - commenting this out for now because of Chrome bug where coincident endpoints of bezier curve cause the curve to not be rendered - ctx.beginPath(); - var prevAnchor = this.getAnchor(0); - ctx.moveTo(prevAnchor.getPosX()-bboxMin[0],prevAnchor.getPosY()-bboxMin[1]); - for (var i = 1; i < numAnchors; i++) { - var currAnchor = this.getAnchor(i); - 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]); - prevAnchor = currAnchor; - } - if (this._isClosed === true) { - var currAnchor = this.getAnchor(0); - 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]); - prevAnchor = currAnchor; - ctx.fill(); - } - */ +//render +// specify how to render the subpath in Canvas2D +GLSubpath.prototype.render = function () { + // get the world + var world = this.getWorld(); + if (!world) throw( "null world in subpath render" ); + if (!this._canvas){ + //set the canvas by querying the world + this._canvas = this.getWorld().getCanvas(); + } + // get the context + var ctx = world.get2DContext(); + if (!ctx) throw ("null context in subpath render"); + var numAnchors = this.getNumAnchors(); + if (numAnchors === 0) { + return; //nothing to do for empty paths + } + this.createSamples(false); //dirty bit checked in this function...will generate a polyline representation - ctx.beginPath(); - ctx.moveTo(this._Samples[0][0],this._Samples[0][1]); - for (var i=0;i<numPoints;i++){ - ctx.lineTo(this._Samples[i][0],this._Samples[i][1]); - } - if (this._isClosed === true) { - ctx.lineTo(this._Samples[0][0],this._Samples[0][1]); - } - ctx.fill(); - ctx.stroke(); - ctx.restore(); - }; //render() - - this.geomType = function () { - return this.GEOM_TYPE_CUBIC_BEZIER; - }; - - this.setWidth = function (newW) { - var strokeWidth = this._strokeWidth; - var halfStrokeWidth = strokeWidth*0.5; - if (newW<1) { - newW=1; //clamp minimum width to 1 - } + var numPoints = this._Samples.length; + if (numPoints === 0){ + return; //nothing to do for empty paths + } - //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; - } + //figure the size of the area we will draw into + var bboxWidth=0, bboxHeight=0; + bboxWidth = this._BBoxMax[0] - this._BBoxMin[0]; + bboxHeight = this._BBoxMax[1] - this._BBoxMin[1]; - var scaleX = newW/oldWidth; - if (scaleX===1) { - return; //no need to do anything - } + ctx.save(); + ctx.clearRect(0, 0, bboxWidth, bboxHeight); - //scale the anchor point positions such that the width of the bbox is the newW - 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<numAnchors;i++){ - //compute the distance from the bboxMin - var oldW = this._Anchors[i].getPosX() - origX; - var prevW = this._Anchors[i].getPrevX() - origX; - var nextW = this._Anchors[i].getNextX() - origX; - - this._Anchors[i].setPos(origX + oldW*scaleX,this._Anchors[i].getPosY(),this._Anchors[i].getPosZ()); - this._Anchors[i].setPrevPos(origX + prevW*scaleX,this._Anchors[i].getPrevY(),this._Anchors[i].getPrevZ()); - this._Anchors[i].setNextPos(origX + nextW*scaleX,this._Anchors[i].getNextY(),this._Anchors[i].getNextZ()); - } - this.makeDirty(); - this.computeBoundingBox(true, false); - }; + ctx.lineWidth = this._strokeWidth; + ctx.strokeStyle = "black"; + if (this._strokeColor) { + //ctx.strokeStyle = MathUtils.colorToHex( this._strokeColor ); + var strokeColorStr = "rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+this._strokeColor[3]+")"; + ctx.strokeStyle = strokeColorStr; + } - this.setHeight = function (newH) { - if (newH<1) { - newH=1; //clamp minimum width to 1 - } - //scale the contents of this subpath to lie within this height - //determine the scale factor by comparing with the old height - var oldHeight = this._BBoxMax[1]-this._BBoxMin[1]; - if (oldHeight<1){ - oldHeight=1; - } + ctx.fillStyle = "white"; + if (this._fillColor){ + //ctx.fillStyle = MathUtils.colorToHex( this._fillColor ); + var fillColorStr = "rgba("+parseInt(255*this._fillColor[0])+","+parseInt(255*this._fillColor[1])+","+parseInt(255*this._fillColor[2])+","+this._fillColor[3]+")"; + ctx.fillStyle = fillColorStr; + } + var lineCap = ['butt','round','square']; + ctx.lineCap = lineCap[1]; + var lineJoin = ['round','bevel','miter']; + ctx.lineJoin = lineJoin[0]; + + + //commenting this out for now because of Chrome bug where coincident endpoints of bezier curve cause the curve to not be rendered + /* + ctx.beginPath(); + var prevAnchor = this.getAnchor(0); + ctx.moveTo(prevAnchor.getPosX(),prevAnchor.getPosY()); + for (var i = 1; i < numAnchors; i++) { + var currAnchor = this.getAnchor(i); + ctx.bezierCurveTo(prevAnchor.getNextX(),prevAnchor.getNextY(), currAnchor.getPrevX(), currAnchor.getPrevY(), currAnchor.getPosX(), currAnchor.getPosY()); + prevAnchor = currAnchor; + } + if (this._isClosed === true) { + var currAnchor = this.getAnchor(0); + ctx.bezierCurveTo(prevAnchor.getNextX(),prevAnchor.getNextY(), currAnchor.getPrevX(), currAnchor.getPrevY(), currAnchor.getPosX(), currAnchor.getPosY()); + prevAnchor = currAnchor; + } + ctx.fill(); + ctx.stroke(); + */ - var scaleY = newH/oldHeight; - if (scaleY===1){ - return; //no need to do anything - } - //scale the anchor point positions such that the height of the bbox is the newH - var origY = this._BBoxMin[1]; - var numAnchors = this._Anchors.length; - for (var i=0;i<numAnchors;i++){ - //compute the distance from the bboxMin - var oldW = this._Anchors[i].getPosY() - origY; - var prevW = this._Anchors[i].getPrevY() - origY; - var nextW = this._Anchors[i].getNextY() - origY; - - this._Anchors[i].setPos(this._Anchors[i].getPosX(), origY + oldW*scaleY,this._Anchors[i].getPosZ()); - this._Anchors[i].setPrevPos(this._Anchors[i].getPrevX(), origY + prevW*scaleY,this._Anchors[i].getPrevZ()); - this._Anchors[i].setNextPos(this._Anchors[i].getNextX(), origY + nextW*scaleY,this._Anchors[i].getNextZ()); - } - this.makeDirty(); + ctx.beginPath(); + ctx.moveTo(this._Samples[0][0],this._Samples[0][1]); + for (var i=0;i<numPoints;i++){ + ctx.lineTo(this._Samples[i][0],this._Samples[i][1]); } + if (this._isClosed === true) { + ctx.lineTo(this._Samples[0][0],this._Samples[0][1]); + } + ctx.fill(); + ctx.stroke(); -}; //function GLSubpath ...class definition - -GLSubpath.prototype = Object.create(GeomObj, {}); + ctx.restore(); +}; //render() ///////////////////////////////////////////////////////// // Property Accessors/Setters ///////////////////////////////////////////////////////// + + +GLSubpath.prototype.geomType = function () { + return this.GEOM_TYPE_CUBIC_BEZIER; +}; + +GLSubpath.prototype.setWidth = function (newW) { + var strokeWidth = this._strokeWidth; + var halfStrokeWidth = strokeWidth*0.5; + 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 anchor point positions such that the width of the bbox is the newW + 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<numAnchors;i++){ + //compute the distance from the bboxMin + var oldW = this._Anchors[i].getPosX() - origX; + var prevW = this._Anchors[i].getPrevX() - origX; + var nextW = this._Anchors[i].getNextX() - origX; + + this._Anchors[i].setPos(origX + oldW*scaleX,this._Anchors[i].getPosY(),this._Anchors[i].getPosZ()); + this._Anchors[i].setPrevPos(origX + prevW*scaleX,this._Anchors[i].getPrevY(),this._Anchors[i].getPrevZ()); + this._Anchors[i].setNextPos(origX + nextW*scaleX,this._Anchors[i].getNextY(),this._Anchors[i].getNextZ()); + } + this.makeDirty(); + this.computeBoundingBox(true, false); +}; + +GLSubpath.prototype.setHeight = function (newH) { + if (newH<1) { + newH=1; //clamp minimum width to 1 + } + //scale the contents of this subpath to lie within this height + //determine the scale factor by comparing with the old height + var oldHeight = this._BBoxMax[1]-this._BBoxMin[1]; + if (oldHeight<1){ + oldHeight=1; + } + + var scaleY = newH/oldHeight; + if (scaleY===1){ + return; //no need to do anything + } + + //scale the anchor point positions such that the height of the bbox is the newH + var origY = this._BBoxMin[1]; + var numAnchors = this._Anchors.length; + for (var i=0;i<numAnchors;i++){ + //compute the distance from the bboxMin + var oldW = this._Anchors[i].getPosY() - origY; + var prevW = this._Anchors[i].getPrevY() - origY; + var nextW = this._Anchors[i].getNextY() - origY; + + this._Anchors[i].setPos(this._Anchors[i].getPosX(), origY + oldW*scaleY,this._Anchors[i].getPosZ()); + this._Anchors[i].setPrevPos(this._Anchors[i].getPrevX(), origY + prevW*scaleY,this._Anchors[i].getPrevZ()); + this._Anchors[i].setNextPos(this._Anchors[i].getNextX(), origY + nextW*scaleY,this._Anchors[i].getNextZ()); + } + this.makeDirty(); +}; + GLSubpath.prototype.setWorld = function (world) { this._world = world; }; -- cgit v1.2.3