/*! * Canvas * Copyright (c) 2010 LearnBoost * MIT Licensed */ /** * Module dependencies. */ var canvas = require('../build/default/canvas') , colors = require('./colors') , Canvas = canvas.Canvas , Context2d = canvas.CanvasRenderingContext2d , CanvasGradient = canvas.CanvasGradient , cairoVersion = canvas.cairoVersion , PNGStream = require('./pngstream'); /** * Export `Canvas` as the module. */ var Canvas = exports = module.exports = Canvas; /** * Library version. */ exports.version = '0.0.1'; /** * Cairo version. */ exports.cairoVersion = cairoVersion; /** * Cache color string RGBA values. */ var cache = {}; /** * Parse the given color `str`. * * Current supports: * * - #nnn * - #nnnnnn * - rgb(r,g,b) * - rgba(r,g,b,a) * - color * * Examples * * - #fff * - #FFF * - #FFFFFF * - rgb(255,255,5) * - rgba(255,255,5,.8) * - rgba(255,255,5,0.8) * - white * - red * * @param {String} str * @return {Array} * @api public */ var parseColor = exports.parseColor = function(str){ if (cache[str]) return cache[str]; str = colors[str] || String(str); // RGBA if (0 == str.indexOf('rgba')) { var captures = /rgba\((\d{1,3}) *, *(\d{1,3}) *, *(\d{1,3}) *, *(\d+\.\d+|\.\d+|\d+) *\)/.exec(str); if (!captures) return; return cache[str] = [ parseInt(captures[1], 10) , parseInt(captures[2], 10) , parseInt(captures[3], 10) , parseFloat(captures[4], 10) ]; // RGB } else if (0 == str.indexOf('rgb')) { var captures = /rgb\((\d{1,3}) *, *(\d{1,3}) *, *(\d{1,3}) *\)/.exec(str); if (!captures) return; return cache[str] = [ parseInt(captures[1], 10) , parseInt(captures[2], 10) , parseInt(captures[3], 10) , 1 ]; // #RRGGBB } else if ('#' == str.charAt(0) && str.length > 4) { var captures = /#(\w{2})(\w{2})(\w{2})/.exec(str); if (!captures) return; return cache[str] = [ parseInt(captures[1], 16) , parseInt(captures[2], 16) , parseInt(captures[3], 16) , 1 ]; // #RGB } else if ('#' == str.charAt(0)) { var captures = /#(\w)(\w)(\w)/.exec(str); if (!captures) return; return cache[str] = [ parseInt(captures[1] + captures[1], 16) , parseInt(captures[2] + captures[2], 16) , parseInt(captures[3] + captures[3], 16) , 1 ]; } }; /** * Get a context object. * * @param {String} contextId * @return {Context2d} * @api public */ Canvas.prototype.getContext = function(contextId){ if ('2d' == contextId) { var ctx = new Context2d(this); this.context = ctx; ctx.canvas = this; return ctx; } }; /** * Create a `PNGStream` for `this` canvas. * * @return {PNGStream} * @api public */ Canvas.prototype.createPNGStream = function(){ return new PNGStream(this); }; /** * Add `color` stop at the given `offset`. * * @param {Number} offset * @param {String} color * @api public */ CanvasGradient.prototype.addColorStop = function(offset, color){ var rgba; if (rgba = parseColor(color)) { this.addColorStopRGBA( offset , rgba[0] , rgba[1] , rgba[2] , rgba[3]); } }; /** * Create a linear gradient at the given point `(x0, y0)` and `(x1, y1)`. * * @param {Number} x0 * @param {Number} y0 * @param {Number} x1 * @param {Number} y1 * @return {CanvasGradient} * @api public */ Context2d.prototype.createLinearGradient = function(x0, y0, x1, y1){ return new CanvasGradient(x0, y0, x1, y1); }; /** * Create a radial gradient at the given point `(x0, y0)` and `(x1, y1)` * and radius `r0` and `r1`. * * @param {Number} x0 * @param {Number} y0 * @param {Number} r0 * @param {Number} x1 * @param {Number} y1 * @param {Number} r1 * @return {CanvasGradient} * @api public */ Context2d.prototype.createRadialGradient = function(x0, y0, r0, x1, y1, r1){ return new CanvasGradient(x0, y0, r0, x1, y1, r1); }; /** * Reset transform matrix to identity, then apply the given args. * * @param {...} * @api public */ Context2d.prototype.setTransform = function(){ this.resetTransform(); this.transform.apply(this, arguments); }; /** * Set the fill style with the given css color string. * * @see exports.parseColor() * @api public */ Context2d.prototype.__defineSetter__('fillStyle', function(val){ if (val instanceof CanvasGradient) { this.setFillPattern(val); } else if ('string' == typeof val) { var rgba; if (rgba = parseColor(val)) { this.lastFillStyle = rgba; this.setFillRGBA( rgba[0] , rgba[1] , rgba[2] , rgba[3]); } } }); /** * Get the current fill style string. * * @api public */ Context2d.prototype.__defineGetter__('fillStyle', function(){ var rgba = this.lastFillStyle; return 'rgba(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ',' + rgba[3] + ')'; }); /** * Set the stroke style with the given css color string. * * @see exports.parseColor() * @api public */ Context2d.prototype.__defineSetter__('strokeStyle', function(val){ if (val instanceof CanvasGradient) { this.setStrokePattern(val); } else if ('string' == typeof val) { var rgba; if (rgba = parseColor(val)) { this.lastStrokeStyle = rgba; this.setStrokeRGBA( rgba[0] , rgba[1] , rgba[2] , rgba[3]); } } }); /** * Get the current stroke style string. * * @api public */ Context2d.prototype.__defineGetter__('strokeStyle', function(){ var rgba = this.lastStrokeStyle; return 'rgba(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ',' + rgba[3] + ')'; }); /** * Set the shadow color with the given css color string. * * @see exports.parseColor() * @api public */ Context2d.prototype.__defineSetter__('shadowColor', function(val){ if ('string' == typeof val) { var rgba; if (rgba = parseColor(val)) { this.lastShadowColor = rgba; this.setShadowRGBA( rgba[0] , rgba[1] , rgba[2] , rgba[3]); } } }); /** * Get the current shadow color string. * * @api public */ Context2d.prototype.__defineGetter__('shadowColor', function(){ var rgba = this.lastShadowColor; return 'rgba(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ',' + rgba[3] + ')'; });