function RasterizedAlphabet(alphabet, font, target_width) {
      //variable prototypes
      this.lookup = []; //a map of letter to index
      this.rasters = []; //a list of rasters
      this.dimensions = []; //a list of dimensions

      //function prototypes
      this.draw = RasterizedAlphabet_draw;

      //construct
      var default_size = 60; // size of square to assume as the default width
      var safety_pad = 20; // pixels to pad around so we don't miss the edges
      // create a canvas to do our rasterizing on
      var canvas = document.createElement("canvas");
      // assume the default font would fit in a canvas of 100 by 100
      canvas.width = default_size + 2 * safety_pad;
      canvas.height = default_size + 2 * safety_pad;
      // check for canvas support before attempting anything
      if (!canvas.getContext) throw "NO_CANVAS_SUPPORT";
      var ctx = canvas.getContext('2d');
      // check for html5 text drawing support
      if (!supports_text(ctx)) throw "NO_CANVAS_TEXT_SUPPORT";
      // calculate the middle
      var middle = Math.round(canvas.width / 2);
      // calculate the baseline
      var baseline = Math.round(canvas.height - safety_pad);
      // list of widths
      var widths = [];
      var count = 0;
      var letters = [];
      //now measure each letter in the alphabet
      for (var i = 0; i < alphabet.get_size(); ++i) {
        if (alphabet.is_ambig(i)) continue; //skip ambigs as they're never rendered
        var letter = alphabet.get_letter(i);
        letters.push(letter);
        var pos = count++;
        this.lookup[letter] = pos;
        //clear the canvas
        canvas.width = canvas.width;
        // get the context and prepare to draw our width test
        var ctx = canvas.getContext('2d');
        ctx.font = font;
        ctx.fillStyle = alphabet.get_colour(i);
        ctx.textAlign = "center";
        ctx.translate(middle, baseline);
        // draw the test text
        ctx.fillText(letter, 0, 0);
        //measure
        var size = RasterizedAlphabet_measure(ctx, canvas.width, canvas.height);
        if (size.width == 0) throw "INVISIBLE_LETTER"; //maybe the fill was white on white?
        widths.push(size.width);
        this.dimensions[pos] = size;
      }
      //sort the widths
      widths.sort(function(a,b) {return a - b;});
      //drop 10% of the items off each end
      var tenpercent = Math.floor(widths.length / 10);
      for (var i = 0; i < tenpercent; ++i) {
        widths.pop();
        widths.shift();
      }
      //calculate average width
      var avg_width = 0;
      for (var i = 0; i < widths.length; ++i) avg_width += widths[i];
      avg_width /= widths.length;
      // calculate scales
      for (var i = 0; i < this.dimensions.length; ++i) {
        var size = this.dimensions[i];
        // calculate scale
        var scale = target_width / Math.max(avg_width, size.width);
        // estimate scaled height
        var target_height = size.height * scale;
        // create an approprately sized canvas
        var raster = document.createElement("canvas");
        raster.width = target_width; // if it goes over the edge too bad...
        raster.height = target_height + safety_pad * 2;
        // calculate the middle
        middle = Math.round(raster.width / 2);
        // calculate the baseline
        baseline = Math.round(raster.height - safety_pad);
        // get the context and prepare to draw the rasterized text
        ctx = raster.getContext('2d');
        ctx.font = font;
        ctx.fillStyle = alphabet.get_colour(i);
        ctx.textAlign = "center";
        ctx.translate(middle, baseline);
        ctx.save();
        ctx.scale(scale, scale);
        // draw the rasterized text
        ctx.fillText(letters[i], 0, 0);
        ctx.restore();
        this.rasters[i] = raster;
        this.dimensions[i] = RasterizedAlphabet_measure(ctx, raster.width, raster.height);
      }
    }
// 8) Paint on to another canvas at the desired height (but only scaling width to fit if larger).
8) Paint on to another canvas at the desired height (but only scaling width to fit if larger).
8 ) Paint on to another canvas at the desired height ( but only scaling width to fit if larger ) .
function RasterizedAlphabet(alphabet, font, target_width) {
      this.lookup = []; 
      this.rasters = []; 
      this.dimensions = []; 
      this.draw = RasterizedAlphabet_draw;
      var default_size = 60; 
      var safety_pad = 20; 
      var canvas = document.createElement("canvas");
      canvas.width = default_size + 2 * safety_pad;
      canvas.height = default_size + 2 * safety_pad;
      if (!canvas.getContext) throw "NO_CANVAS_SUPPORT";
      var ctx = canvas.getContext('2d');
      if (!supports_text(ctx)) throw "NO_CANVAS_TEXT_SUPPORT";
      var middle = Math.round(canvas.width / 2);
      var baseline = Math.round(canvas.height - safety_pad);
      var widths = [];
      var count = 0;
      var letters = [];
      for (var i = 0; i < alphabet.get_size(); ++i) {
        if (alphabet.is_ambig(i)) continue; 
        var letter = alphabet.get_letter(i);
        letters.push(letter);
        var pos = count++;
        this.lookup[letter] = pos;
        canvas.width = canvas.width;
        var ctx = canvas.getContext('2d');
        ctx.font = font;
        ctx.fillStyle = alphabet.get_colour(i);
        ctx.textAlign = "center";
        ctx.translate(middle, baseline);
        ctx.fillText(letter, 0, 0);
        var size = RasterizedAlphabet_measure(ctx, canvas.width, canvas.height);
        if (size.width == 0) throw "INVISIBLE_LETTER"; 
        widths.push(size.width);
        this.dimensions[pos] = size;
      }
      widths.sort(function(a,b) {return a - b;});
      var tenpercent = Math.floor(widths.length / 10);
      for (var i = 0; i < tenpercent; ++i) {
        widths.pop();
        widths.shift();
      }
      var avg_width = 0;
      for (var i = 0; i < widths.length; ++i) avg_width += widths[i];
      avg_width /= widths.length;
      for (var i = 0; i < this.dimensions.length; ++i) {
        var size = this.dimensions[i];
        var scale = target_width / Math.max(avg_width, size.width);
        var target_height = size.height * scale;
        var raster = document.createElement("canvas");
        raster.width = target_width; 
        raster.height = target_height + safety_pad * 2;
        middle = Math.round(raster.width / 2);
        baseline = Math.round(raster.height - safety_pad);
        ctx = raster.getContext('2d');
        ctx.font = font;
        ctx.fillStyle = alphabet.get_colour(i);
        ctx.textAlign = "center";
        ctx.translate(middle, baseline);
        ctx.save();
        ctx.scale(scale, scale);
        ctx.fillText(letters[i], 0, 0);
        ctx.restore();
        this.rasters[i] = raster;
        this.dimensions[i] = RasterizedAlphabet_measure(ctx, raster.width, raster.height);
      }
    }
function RasterizedAlphabet ( alphabet , font , target_width ) { this . lookup = [ ] ; this . rasters = [ ] ; this . dimensions = [ ] ; this . draw = RasterizedAlphabet_draw ; var default_size = 60 ; var safety_pad = 20 ; var canvas = document . createElement ( "canvas" ) ; canvas . width = default_size + 2 * safety_pad ; canvas . height = default_size + 2 * safety_pad ; if ( ! canvas . getContext ) throw "NO_CANVAS_SUPPORT" ; var ctx = canvas . getContext ( '2d' ) ; if ( ! supports_text ( ctx ) ) throw "NO_CANVAS_TEXT_SUPPORT" ; var middle = Math . round ( canvas . width / 2 ) ; var baseline = Math . round ( canvas . height - safety_pad ) ; var widths = [ ] ; var count = 0 ; var letters = [ ] ; for ( var i = 0 ; i < alphabet . get_size ( ) ; ++ i ) { if ( alphabet . is_ambig ( i ) ) continue ; var letter = alphabet . get_letter ( i ) ; letters . push ( letter ) ; var pos = count ++ ; this . lookup [ letter ] = pos ; canvas . width = canvas . width ; var ctx = canvas . getContext ( '2d' ) ; ctx . font = font ; ctx . fillStyle = alphabet . get_colour ( i ) ; ctx . textAlign = "center" ; ctx . translate ( middle , baseline ) ; ctx . fillText ( letter , 0 , 0 ) ; var size = RasterizedAlphabet_measure ( ctx , canvas . width , canvas . height ) ; if ( size . width == 0 ) throw "INVISIBLE_LETTER" ; widths . push ( size . width ) ; this . dimensions [ pos ] = size ; } widths . sort ( function ( a , b ) { return a - b ; } ) ; var tenpercent = Math . floor ( widths . length / 10 ) ; for ( var i = 0 ; i < tenpercent ; ++ i ) { widths . pop ( ) ; widths . shift ( ) ; } var avg_width = 0 ; for ( var i = 0 ; i < widths . length ; ++ i ) avg_width += widths [ i ] ; avg_width /= widths . length ; for ( var i = 0 ; i < this . dimensions . length ; ++ i ) { var size = this . dimensions [ i ] ; var scale = target_width / Math . max ( avg_width , size . width ) ; var target_height = size . height * scale ; var raster = document . createElement ( "canvas" ) ; raster . width = target_width ; raster . height = target_height + safety_pad * 2 ; middle = Math . round ( raster . width / 2 ) ; baseline = Math . round ( raster . height - safety_pad ) ; ctx = raster . getContext ( '2d' ) ; ctx . font = font ; ctx . fillStyle = alphabet . get_colour ( i ) ; ctx . textAlign = "center" ; ctx . translate ( middle , baseline ) ; ctx . save ( ) ; ctx . scale ( scale , scale ) ; ctx . fillText ( letters [ i ] , 0 , 0 ) ; ctx . restore ( ) ; this . rasters [ i ] = raster ; this . dimensions [ i ] = RasterizedAlphabet_measure ( ctx , raster . width , raster . height ) ; } }
8) Paint on to another canvas at the desired height (but only scaling width to fit if larger).
8 ) Paint on to another canvas at the desired height ( but only scaling width to fit if larger ) .
//variable prototypes //a map of letter to index //a list of rasters //a list of dimensions //function prototypes //construct // size of square to assume as the default width // pixels to pad around so we don't miss the edges // create a canvas to do our rasterizing on // assume the default font would fit in a canvas of 100 by 100 // check for canvas support before attempting anything // check for html5 text drawing support // calculate the middle // calculate the baseline // list of widths //now measure each letter in the alphabet //skip ambigs as they're never rendered //clear the canvas // get the context and prepare to draw our width test // draw the test text //measure //maybe the fill was white on white? //sort the widths //drop 10% of the items off each end //calculate average width // calculate scales // calculate scale // estimate scaled height // create an approprately sized canvas // if it goes over the edge too bad... // calculate the middle // calculate the baseline // get the context and prepare to draw the rasterized text // draw the rasterized text