diff options
Diffstat (limited to 'assets/canvas-runtime.js')
-rw-r--r-- | assets/canvas-runtime.js | 493 |
1 files changed, 493 insertions, 0 deletions
diff --git a/assets/canvas-runtime.js b/assets/canvas-runtime.js index afb9563e..753161aa 100644 --- a/assets/canvas-runtime.js +++ b/assets/canvas-runtime.js | |||
@@ -382,6 +382,16 @@ NinjaCvsRt.GLRuntime = Object.create(Object.prototype, { | |||
382 | obj.importJSON( jObj ); | 382 | obj.importJSON( jObj ); |
383 | break; | 383 | break; |
384 | 384 | ||
385 | case 5: //subpath (created by pen tool) | ||
386 | obj = Object.create(NinjaCvsRt.RuntimeSubPath, {_materials: { value:[], writable:true}}); | ||
387 | obj.importJSON (jObj ); | ||
388 | break; | ||
389 | |||
390 | case 6: //brushstroke (created by brush tool) | ||
391 | obj = Object.create(NinjaCvsRt.RuntimeBrushStroke, {_materials: { value:[], writable:true}}); | ||
392 | obj.importJSON (jObj ); | ||
393 | break; | ||
394 | |||
385 | default: | 395 | default: |
386 | throw new Error( "Attempting to load unrecognized object type: " + type ); | 396 | throw new Error( "Attempting to load unrecognized object type: " + type ); |
387 | break; | 397 | break; |
@@ -524,6 +534,7 @@ NinjaCvsRt.RuntimeGeomObj = Object.create(Object.prototype, { | |||
524 | GEOM_TYPE_LINE: { value: 3, writable: false }, | 534 | GEOM_TYPE_LINE: { value: 3, writable: false }, |
525 | GEOM_TYPE_PATH: { value: 4, writable: false }, | 535 | GEOM_TYPE_PATH: { value: 4, writable: false }, |
526 | GEOM_TYPE_CUBIC_BEZIER: { value: 5, writable: false }, | 536 | GEOM_TYPE_CUBIC_BEZIER: { value: 5, writable: false }, |
537 | GEOM_TYPE_BRUSH_STROKE: { value: 6, writable: false }, | ||
527 | GEOM_TYPE_UNDEFINED: { value: -1, writable: false }, | 538 | GEOM_TYPE_UNDEFINED: { value: -1, writable: false }, |
528 | 539 | ||
529 | /////////////////////////////////////////////////////////////////////// | 540 | /////////////////////////////////////////////////////////////////////// |
@@ -2144,3 +2155,485 @@ NinjaCvsRt.RuntimePlasmaMaterial = Object.create(NinjaCvsRt.RuntimeMaterial, { | |||
2144 | }); | 2155 | }); |
2145 | 2156 | ||
2146 | 2157 | ||
2158 | |||
2159 | // ************************************************************************** | ||
2160 | // Runtime for the pen tool path | ||
2161 | // ************************************************************************** | ||
2162 | NinjaCvsRt.AnchorPoint = Object.create(Object.prototype, { | ||
2163 | ///////////////////////////////////////// | ||
2164 | // Instance variables | ||
2165 | ///////////////////////////////////////// | ||
2166 | _x: {value: 0.0, writable: true}, | ||
2167 | _y: {value: 0.0, writable: true}, | ||
2168 | _z: {value: 0.0, writable: true}, | ||
2169 | |||
2170 | _prevX: {value: 0.0, writable: true}, | ||
2171 | _prevY: {value: 0.0, writable: true}, | ||
2172 | _prevZ: {value: 0.0, writable: true}, | ||
2173 | |||
2174 | _nextX: {value: 0.0, writable: true}, | ||
2175 | _nextY: {value: 0.0, writable: true}, | ||
2176 | _nextZ: {value: 0.0, writable: true}, | ||
2177 | |||
2178 | // *********** setters ************ | ||
2179 | setPos: { | ||
2180 | value: function(x,y,z){ | ||
2181 | this._x = x; | ||
2182 | this._y = y; | ||
2183 | this._z = z; | ||
2184 | } | ||
2185 | }, | ||
2186 | |||
2187 | setPrevPos: { | ||
2188 | value: function (x, y, z) { | ||
2189 | this._prevX = x; | ||
2190 | this._prevY = y; | ||
2191 | this._prevZ = z; | ||
2192 | } | ||
2193 | }, | ||
2194 | |||
2195 | setNextPos: { | ||
2196 | value: function (x, y, z) { | ||
2197 | this._nextX = x; | ||
2198 | this._nextY = y; | ||
2199 | this._nextZ = z; | ||
2200 | } | ||
2201 | }, | ||
2202 | |||
2203 | // *************** getters ****************** | ||
2204 | // (add as needed) | ||
2205 | getPosX: { | ||
2206 | value: function () { | ||
2207 | return this._x; | ||
2208 | } | ||
2209 | }, | ||
2210 | |||
2211 | getPosY: { | ||
2212 | value: function () { | ||
2213 | return this._y; | ||
2214 | } | ||
2215 | }, | ||
2216 | |||
2217 | getPosZ: { | ||
2218 | value: function () { | ||
2219 | return this._z; | ||
2220 | } | ||
2221 | }, | ||
2222 | |||
2223 | getPrevX: { | ||
2224 | value: function () { | ||
2225 | return this._prevX; | ||
2226 | } | ||
2227 | }, | ||
2228 | |||
2229 | getPrevY: { | ||
2230 | value: function () { | ||
2231 | return this._prevY; | ||
2232 | } | ||
2233 | }, | ||
2234 | |||
2235 | getPrevZ: { | ||
2236 | value: function () { | ||
2237 | return this._prevZ; | ||
2238 | } | ||
2239 | }, | ||
2240 | |||
2241 | getNextX: { | ||
2242 | value: function () { | ||
2243 | return this._nextX; | ||
2244 | } | ||
2245 | }, | ||
2246 | |||
2247 | getNextY: { | ||
2248 | value: function () { | ||
2249 | return this._nextY; | ||
2250 | } | ||
2251 | }, | ||
2252 | |||
2253 | getNextZ: { | ||
2254 | value: function () { | ||
2255 | return this._nextZ; | ||
2256 | } | ||
2257 | } | ||
2258 | }); | ||
2259 | |||
2260 | NinjaCvsRt.RuntimeSubPath = Object.create(NinjaCvsRt.RuntimeGeomObj, { | ||
2261 | // array of anchor points | ||
2262 | _Anchors: { value: null, writable: true }, | ||
2263 | |||
2264 | //path properties | ||
2265 | _isClosed: {value: false, writable: true}, | ||
2266 | _strokeWidth: {value: 0, writable: true}, | ||
2267 | _strokeColor: {value: null, writable: true}, | ||
2268 | _fillColor: {value: null, writable: true}, | ||
2269 | |||
2270 | geomType: { | ||
2271 | value: function () { | ||
2272 | return this.GEOM_TYPE_CUBIC_BEZIER; | ||
2273 | } | ||
2274 | }, | ||
2275 | |||
2276 | importJSON: { | ||
2277 | value: function(jo) { | ||
2278 | if (this.geomType()!== jo.geomType){ | ||
2279 | return; | ||
2280 | } | ||
2281 | //the geometry for this object | ||
2282 | this._Anchors = []; | ||
2283 | var i=0; | ||
2284 | for (i=0;i<jo.anchors.length;i++){ | ||
2285 | var newAnchor = Object.create(NinjaCvsRt.AnchorPoint); | ||
2286 | var ipAnchor = jo.anchors[i]; | ||
2287 | newAnchor.setPos(ipAnchor._x, ipAnchor._y, ipAnchor._z); | ||
2288 | newAnchor.setPrevPos(ipAnchor._prevX, ipAnchor._prevY, ipAnchor._prevZ); | ||
2289 | newAnchor.setNextPos(ipAnchor._nextX, ipAnchor._nextY, ipAnchor._nextZ); | ||
2290 | this._Anchors.push(newAnchor); | ||
2291 | } | ||
2292 | this._isClosed = jo.isClosed; | ||
2293 | |||
2294 | //stroke appearance properties | ||
2295 | this._strokeWidth = jo.strokeWidth; | ||
2296 | this._strokeColor = jo.strokeColor; | ||
2297 | this._fillColor = jo.fillColor; | ||
2298 | } | ||
2299 | }, | ||
2300 | |||
2301 | //buildColor returns the fillStyle or strokeStyle for the Canvas 2D context | ||
2302 | buildColor: { | ||
2303 | value: function(ctx, //the 2D rendering context (for creating gradients if necessary) | ||
2304 | ipColor, //color string, also encodes whether there's a gradient and of what type | ||
2305 | w, //width of the region of color | ||
2306 | h, //height of the region of color | ||
2307 | lw) //linewidth (i.e. stroke width/size) | ||
2308 | { | ||
2309 | if (ipColor.gradientMode){ | ||
2310 | var position, gradient, cs, inset; //vars used in gradient calculations | ||
2311 | inset = Math.ceil( lw ) - 0.5; | ||
2312 | |||
2313 | if(ipColor.gradientMode === "radial") { | ||
2314 | var ww = w - 2*lw, hh = h - 2*lw; | ||
2315 | gradient = ctx.createRadialGradient(w/2, h/2, 0, w/2, h/2, Math.max(ww, hh)/2); | ||
2316 | } else { | ||
2317 | gradient = ctx.createLinearGradient(inset, h/2, w-inset, h/2); | ||
2318 | } | ||
2319 | var colors = ipColor.color; | ||
2320 | |||
2321 | var len = colors.length; | ||
2322 | for(n=0; n<len; n++) { | ||
2323 | position = colors[n].position/100; | ||
2324 | cs = colors[n].value; | ||
2325 | gradient.addColorStop(position, "rgba(" + cs.r + "," + cs.g + "," + cs.b + "," + cs.a + ")"); | ||
2326 | } | ||
2327 | return gradient; | ||
2328 | } else { | ||
2329 | var c = "rgba(" + 255*ipColor[0] + "," + 255*ipColor[1] + "," + 255*ipColor[2] + "," + ipColor[3] + ")"; | ||
2330 | return c; | ||
2331 | } | ||
2332 | } | ||
2333 | }, | ||
2334 | |||
2335 | render: { | ||
2336 | value: function() { | ||
2337 | // get the world | ||
2338 | var world = this.getWorld(); | ||
2339 | if (!world) { | ||
2340 | throw( "null world in subpath render" ); | ||
2341 | return; | ||
2342 | } | ||
2343 | |||
2344 | // get the context | ||
2345 | var ctx = world.get2DContext(); | ||
2346 | if (!ctx) { | ||
2347 | throw( "null world in subpath render" ); | ||
2348 | return; | ||
2349 | } | ||
2350 | |||
2351 | //vars used for the gradient computation in buildColor | ||
2352 | var w = world.getViewportWidth(), h = world.getViewportHeight(); | ||
2353 | |||
2354 | ctx.save(); | ||
2355 | ctx.lineWidth = this._strokeWidth; | ||
2356 | ctx.strokeStyle = "black"; | ||
2357 | if (this._strokeColor) { | ||
2358 | ctx.strokeStyle = this.buildColor(ctx, this._strokeColor, w,h, this._strokeWidth); | ||
2359 | } | ||
2360 | |||
2361 | ctx.fillStyle = "white"; | ||
2362 | if (this._fillColor){ | ||
2363 | ctx.fillStyle = this.buildColor(ctx, this._fillColor, w,h, this._strokeWidth); | ||
2364 | } | ||
2365 | var lineCap = ['butt','round','square']; | ||
2366 | ctx.lineCap = lineCap[1]; | ||
2367 | var lineJoin = ['round','bevel','miter']; | ||
2368 | ctx.lineJoin = lineJoin[0]; | ||
2369 | |||
2370 |