/* * Copyright (c) Joshua John Lawrence 2012, all rights reserved. * * This file is hardly complete for a graphics library, but overkill for the * task this demo performs. I've written it in the style I would use in a real * product, expecting it to grow with reuse and needing it to be maintainable. */ /* * A color value with alpha defaulting to fully opaque. Immutable. * * All arguments should be numeric. If they have fractional parts, they will * be truncated. */ function Color( red, green, blue, alpha ) { red = Math.floor( red ); green = Math.floor( green ); blue = Math.floor( blue ); if( alpha === undefined ) { alpha = 255; } alpha = Math.floor( alpha ); this.getRed = function() { return red; }; this.getGreen = function() { return green; }; this.getBlue = function() { return blue; }; this.getAlpha = function() { return alpha; }; } Color.BLACK = new Color( 0, 0, 0 ); /* * A simple wrapper around a 2d canvas context, to allow easy pixel manipulation. */ function PixelCanvas( context ) { /* * Set the pixel at position p to the color. * * v should be a Vector whose ordinates will be truncated, and color a Color. */ this.drawPixel = function( v, color ) { var x = Math.floor( v.getX() ); var y = Math.floor( v.getY() ); var offset = 4 * ( y * this.getWidth() + x ); imageData.data[ offset + 0 ] = color.getRed(); imageData.data[ offset + 1 ] = color.getGreen(); imageData.data[ offset + 2 ] = color.getBlue(); imageData.data[ offset + 3 ] = color.getAlpha(); }; /* * Redraw the canvas the next time the browser updates the screen. */ this.paint = function() { context.putImageData( imageData, 0, 0 ); }; /* * The width of this canvas. */ this.getWidth = function() { return context.canvas.width; }; /* * The height of this canvas. */ this.getHeight = function() { return context.canvas.height; }; // After getWidth and getHeight are defined. var imageData = context.getImageData( 0, 0, this.getWidth(), this.getHeight() ); } /* * To transform between world and screen co-ordinates. All arguments are Vectors. Immutable. * * Screen left and screen right cannot be equal. Likewise screen top and screen bottom. */ function Transform( worldBottomLeft, worldTopRight, screenBottomLeft, screenTopRight ) { var scaleX = ( worldTopRight.getX() - worldBottomLeft.getX() ) / ( screenTopRight.getX() - screenBottomLeft.getX() ); var scaleY = ( worldTopRight.getY() - worldBottomLeft.getY() ) / ( screenTopRight.getY() - screenBottomLeft.getY() ); var m = new Matrix( scaleX, 0, 0, scaleY ); var offset = new Vector( worldBottomLeft.getX() - scaleX * screenBottomLeft.getX(), worldBottomLeft.getY() - scaleY * screenBottomLeft.getY() ); /* * Takes a Vector in screen co-ordinates, returns a Vector in world co-ordinates. */ this.screenToWorld = function( v ) { return m.times( v ).plus( offset ); }; }