context: /**
   * Copyright (c) 2014 James King [metapyziks@gmail.com]
   *
   * This file is part of TorchGame.
   * 
   * TorchGame is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   * 
   * TorchGame is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   * GNU General Public License for more details.
   * 
   * You should have received a copy of the GNU General Public License
   * along with TorchGame. If not, see <http://www.gnu.org/licenses/>.
   */
  
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  
  using OpenTK;
  using OpenTK.Graphics;
  
  using ResourceLib;
  
  namespace TorchGame.Graphics
  {
      public class Font
      {
          private static Font stFontDefault;
          private static Font stFontLarge;
  
          public static Font Default
          {
              get
              {
                  if ( stFontDefault == null )
                      stFontDefault = new Font( "images_gui_fontdefault" );
                  return stFontDefault;
              }
          }
          public static Font Large
          {
              get
              {
                  if ( stFontLarge == null )
                      stFontLarge = new Font( "images_gui_fontlarge" );
                  return stFontLarge;
              }
          }
  
          internal readonly Texture Texture;
  
          public readonly Vector2 CharSize;
  
          public int CharWidth
          {
              get
              {
                  return (int) CharSize.X;
              }
          }
  
          public int CharHeight
          {
              get
              {
                  return (int) CharSize.Y;
              }
          }
          
          public Font( String charMap )
          {
              Texture = Res.Get<Texture>( charMap );
  
              CharSize = new Vector2( Texture.Width / 16, Texture.Height / 16 );
          }
  
          public Vector2 GetCharOffset( Char character )
          {
              int id = (int) character;
  
              return new Vector2( ( id % 16 ) * CharWidth, ( id / 16 ) * CharHeight );
          }
      }
  
      public class Text : Sprite
      {
          private String myText;
          private Font myFont;
          private float myWrapWidth;
  
          public Font Font
          {
              get
              {
                  return myFont;
              }
          }
  
          public String String
          {
              get
              {
                  return myText;
              }
              set
              {
                  myText = value;
                  VertsChanged = true;
              }
          }
  
          public float WrapWidth
          {
              get
              {
                  return myWrapWidth;
              }
              set
              {
                  myWrapWidth = value;
                  VertsChanged = true;
              }
          }
  
          public Text()
              : this( Font.Default )
          {
  
          }
  
          public Text( Font font, float scale = 1.0f )
              : base( font.Texture, scale )
          {
              myText = "";
              myFont = font;
          }
  
          protected override float[] FindVerts()
          {
              String text = myText.ApplyWordWrap( Font.CharWidth * Scale.X, WrapWidth );
  
              int characters = text.Length;
  
              float[,] mat = new float[ , ]
              {
                  { (float) Math.Cos( Rotation ) * Scale.X, -(float) Math.Sin( Rotation ) * Scale.Y },
                  { (float) Math.Sin( Rotation ) * Scale.X,  (float) Math.Cos( Rotation ) * Scale.Y }
              };
  
              int quads = 0;
  
              for ( int i = 0; i < characters; ++i )
                  if ( !char.IsWhiteSpace( text[ i ] ) )
                      ++quads;
  
              float[] verts = new float[ quads * 8 * 4 ];
  
              for ( int i = 0, index = 0, x = 0, y = 0; i < characters; ++i )
                  GetCharVerts( text[ i ], verts, ref index, mat, ref x, ref y );
  
              return verts;
          }
  
          private void GetCharVerts( char character, float[] verts, ref int index, float[ , ] rotationMat, ref int x, ref int y )
          {
              if ( char.IsWhiteSpace( character ) )
              {
                  if ( character == '\t' )
                      x += 4;
                  else if ( character == '\n' )
                  {
                      y += 1;
                      x = 0;
                  }
                  else
                      x += 1;
  
                  return;
              }
  
              Vector2 subMin = myFont.GetCharOffset( character );
  
              Vector2 tMin = Texture.GetCoords( subMin.X, subMin.Y );
              Vector2 tMax = Texture.GetCoords( subMin.X + myFont.CharWidth, subMin.Y + myFont.CharHeight );
              float xMin = tMin.X;
              float yMin = tMin.Y;
              float xMax = tMax.X;
              float yMax = tMax.Y;
  
              float minX = x * myFont.CharWidth;
              float minY = y * myFont.CharHeight;
  
              float[,] pos = new float[ , ]
              {
                  { minX, minY },
  
gt:                 { minX + myFont.CharWidth, minY },