ig.module( 'impact.font' ) .requires( 'impact.image' ) .defines(function(){ "use strict"; ig.Font = ig.Image.extend({ widthMap: [], indices: [], firstChar: 32, alpha: 1, letterSpacing: 1, lineSpacing: 0, onload: function( ev ) { this._loadMetrics( this.data ); this.parent( ev ); }, widthForString: function( text ) { // Multiline? if( text.indexOf('\n') !== -1 ) { var lines = text.split( '\n' ); var width = 0; for( var i = 0; i < lines.length; i++ ) { width = Math.max( width, this._widthForLine(lines[i]) ); } return width; } else { return this._widthForLine( text ); } }, _widthForLine: function( text ) { var width = 0; for( var i = 0; i < text.length; i++ ) { width += this.widthMap[text.charCodeAt(i) - this.firstChar] + this.letterSpacing; } return width; }, heightForString: function( text ) { return text.split('\n').length * (this.height + this.lineSpacing); }, draw: function( text, x, y, align ) { if( typeof(text) != 'string' ) { text = text.toString(); } // Multiline? if( text.indexOf('\n') !== -1 ) { var lines = text.split( '\n' ); var lineHeight = this.height + this.lineSpacing; for( var i = 0; i < lines.length; i++ ) { this.draw( lines[i], x, y + i * lineHeight, align ); } return; } if( align == ig.Font.ALIGN.RIGHT || align == ig.Font.ALIGN.CENTER ) { var width = this._widthForLine( text ); x -= align == ig.Font.ALIGN.CENTER ? width/2 : width; } if( this.alpha !== 1 ) { ig.system.context.globalAlpha = this.alpha; } for( var i = 0; i < text.length; i++ ) { var c = text.charCodeAt(i); x += this._drawChar( c - this.firstChar, x, y ); } if( this.alpha !== 1 ) { ig.system.context.globalAlpha = 1; } ig.Image.drawCount += text.length; }, _drawChar: function( c, targetX, targetY ) { if( !this.loaded || c < 0 || c >= this.indices.length ) { return 0; } var scale = ig.system.scale; var charX = this.indices[c] * scale; var charY = 0; var charWidth = this.widthMap[c] * scale; var charHeight = (this.height-2) * scale; ig.system.context.drawImage( this.data, charX, charY, charWidth, charHeight, ig.system.getDrawPos(targetX), ig.system.getDrawPos(targetY), charWidth, charHeight ); return this.widthMap[c] + this.letterSpacing; }, _loadMetrics: function( image ) { // Draw the bottommost line of this font image into an offscreen canvas // and analyze it pixel by pixel. // A run of non-transparent pixels represents a character and its width this.height = image.height-1; this.widthMap = []; this.indices = []; var canvas = ig.$new('canvas'); canvas.width = image.width; canvas.height = image.height; var ctx = canvas.getContext('2d'); ctx.drawImage( image, 0, 0 ); var px = ctx.getImageData(0, image.height-1, image.width, 1); var currentChar = 0; var currentWidth = 0; for( var x = 0; x < image.width; x++ ) { var index = x * 4 + 3; // alpha component of this pixel if( px.data[index] != 0 ) { currentWidth++; } else if( px.data[index] == 0 && currentWidth ) { this.widthMap.push( currentWidth ); this.indices.push( x-currentWidth ); currentChar++; currentWidth = 0; } } this.widthMap.push( currentWidth ); this.indices.push( x-currentWidth ); } }); ig.Font.ALIGN = { LEFT: 0, RIGHT: 1, CENTER: 2 }; });