GLText.java
Go to the documentation of this file.
00001 // This is a OpenGL ES 1.0 dynamic font rendering system. It loads actual font
00002 // files, generates a font map (texture) from them, and allows rendering of
00003 // text strings.
00004 //
00005 // NOTE: the rendering portions of this class uses a sprite batcher in order
00006 // provide decent speed rendering. Also, rendering assumes a BOTTOM-LEFT
00007 // origin, and the (x,y) positions are relative to that, as well as the
00008 // bottom-left of the string to render.
00009 
00010 package uk.co.blogspot.fractiousg.texample;
00011 
00012 import android.content.res.AssetManager;
00013 import android.graphics.Bitmap;
00014 import android.graphics.Canvas;
00015 import android.graphics.Paint;
00016 import android.graphics.Typeface;
00017 import android.opengl.GLUtils;
00018 import android.util.Log;
00019 
00020 import javax.microedition.khronos.opengles.GL10;
00021 
00022 public class GLText {
00023 
00024    //--Constants--//
00025    public final static int CHAR_START = 32;           // First Character (ASCII Code)
00026    public final static int CHAR_END = 126;            // Last Character (ASCII Code)
00027    public final static int CHAR_CNT = ( ( ( CHAR_END - CHAR_START ) + 1 ) + 1 );  // Character Count (Including Character to use for Unknown)
00028 
00029    public final static int CHAR_NONE = 32;            // Character to Use for Unknown (ASCII Code)
00030    public final static int CHAR_UNKNOWN = ( CHAR_CNT - 1 );  // Index of the Unknown Character
00031 
00032    public final static int FONT_SIZE_MIN = 6;         // Minumum Font Size (Pixels)
00033    public final static int FONT_SIZE_MAX = 180;       // Maximum Font Size (Pixels)
00034 
00035    public final static int CHAR_BATCH_SIZE = 100;     // Number of Characters to Render Per Batch
00036 
00037    //--Members--//
00038    GL10 gl;                                           // GL10 Instance
00039    AssetManager assets;                               // Asset Manager
00040    SpriteBatch batch;                                 // Batch Renderer
00041 
00042    int fontPadX, fontPadY;                            // Font Padding (Pixels; On Each Side, ie. Doubled on Both X+Y Axis)
00043 
00044    float fontHeight;                                  // Font Height (Actual; Pixels)
00045    float fontAscent;                                  // Font Ascent (Above Baseline; Pixels)
00046    float fontDescent;                                 // Font Descent (Below Baseline; Pixels)
00047 
00048    int textureId;                                     // Font Texture ID [NOTE: Public for Testing Purposes Only!]
00049    int textureSize;                                   // Texture Size for Font (Square) [NOTE: Public for Testing Purposes Only!]
00050    TextureRegion textureRgn;                          // Full Texture Region
00051 
00052    float charWidthMax;                                // Character Width (Maximum; Pixels)
00053    float charHeight;                                  // Character Height (Maximum; Pixels)
00054    final float[] charWidths;                          // Width of Each Character (Actual; Pixels)
00055    TextureRegion[] charRgn;                           // Region of Each Character (Texture Coordinates)
00056    int cellWidth, cellHeight;                         // Character Cell Width/Height
00057    int rowCnt, colCnt;                                // Number of Rows/Columns
00058 
00059    float scaleX, scaleY;                              // Font Scale (X,Y Axis)
00060    float spaceX;                                      // Additional (X,Y Axis) Spacing (Unscaled)
00061 
00062 
00063    //--Constructor--//
00064    // D: save GL instance + asset manager, create arrays, and initialize the members
00065    // A: gl - OpenGL ES 10 Instance
00066    public GLText(GL10 gl, AssetManager assets) {
00067       this.gl = gl;                                   // Save the GL10 Instance
00068       this.assets = assets;                           // Save the Asset Manager Instance
00069 
00070       batch = new SpriteBatch( gl, CHAR_BATCH_SIZE );  // Create Sprite Batch (with Defined Size)
00071 
00072       charWidths = new float[CHAR_CNT];               // Create the Array of Character Widths
00073       charRgn = new TextureRegion[CHAR_CNT];          // Create the Array of Character Regions
00074 
00075       // initialize remaining members
00076       fontPadX = 0;
00077       fontPadY = 0;
00078 
00079       fontHeight = 0.0f;
00080       fontAscent = 0.0f;
00081       fontDescent = 0.0f;
00082 
00083       textureId = -1;
00084       textureSize = 0;
00085 
00086       charWidthMax = 0;
00087       charHeight = 0;
00088 
00089       cellWidth = 0;
00090       cellHeight = 0;
00091       rowCnt = 0;
00092       colCnt = 0;
00093 
00094       scaleX = 1.0f;                                  // Default Scale = 1 (Unscaled)
00095       scaleY = 1.0f;                                  // Default Scale = 1 (Unscaled)
00096       spaceX = 0.0f;
00097    }
00098 
00099   public boolean load(String file, int size, int padX, int padY) {
00100     Typeface tf = Typeface.createFromAsset( assets, file );  // Create the Typeface from Font File
00101     return load(tf, size, padX, padY);
00102   }
00103 
00104    //--Load Font--//
00105    // description
00106    //    this will load the specified font file, create a texture for the defined
00107    //    character range, and setup all required values used to render with it.
00108    // arguments:
00109    //    file - Filename of the font (.ttf, .otf) to use. In 'Assets' folder.
00110    //    size - Requested pixel size of font (height)
00111    //    padX, padY - Extra padding per character (X+Y Axis); to prevent overlapping characters.
00112    public boolean load(Typeface tf, int size, int padX, int padY) {
00113 
00114       // setup requested values
00115       fontPadX = padX;                                // Set Requested X Axis Padding
00116       fontPadY = padY;                                // Set Requested Y Axis Padding
00117 
00118       // setup paint instance for drawing
00119       Paint paint = new Paint();                      // Create Android Paint Instance
00120       paint.setAntiAlias( true );                     // Enable Anti Alias
00121       paint.setTextSize( size );                      // Set Text Size
00122       paint.setColor( 0xffffffff );                   // Set ARGB (White, Opaque)
00123       paint.setTypeface( tf );                        // Set Typeface
00124 
00125       // get font metrics
00126       Paint.FontMetrics fm = paint.getFontMetrics();  // Get Font Metrics
00127       fontHeight = (float)Math.ceil( Math.abs( fm.bottom ) + Math.abs( fm.top ) );  // Calculate Font Height
00128       fontAscent = (float)Math.ceil( Math.abs( fm.ascent ) );  // Save Font Ascent
00129       fontDescent = (float)Math.ceil( Math.abs( fm.descent ) );  // Save Font Descent
00130 
00131       // determine the width of each character (including unknown character)
00132       // also determine the maximum character width
00133       char[] s = new char[2];                         // Create Character Array
00134       charWidthMax = charHeight = 0;                  // Reset Character Width/Height Maximums
00135       float[] w = new float[2];                       // Working Width Value
00136       int cnt = 0;                                    // Array Counter
00137       for ( char c = CHAR_START; c <= CHAR_END; c++ )  {  // FOR Each Character
00138          s[0] = c;                                    // Set Character
00139          paint.getTextWidths( s, 0, 1, w );           // Get Character Bounds
00140          charWidths[cnt] = w[0];                      // Get Width
00141          if ( charWidths[cnt] > charWidthMax )        // IF Width Larger Than Max Width
00142             charWidthMax = charWidths[cnt];           // Save New Max Width
00143          cnt++;                                       // Advance Array Counter
00144       }
00145       s[0] = CHAR_NONE;                               // Set Unknown Character
00146       paint.getTextWidths( s, 0, 1, w );              // Get Character Bounds
00147       charWidths[cnt] = w[0];                         // Get Width
00148       if ( charWidths[cnt] > charWidthMax )           // IF Width Larger Than Max Width
00149          charWidthMax = charWidths[cnt];              // Save New Max Width
00150       cnt++;                                          // Advance Array Counter
00151 
00152       // set character height to font height
00153       charHeight = fontHeight;                        // Set Character Height
00154 
00155       // find the maximum size, validate, and setup cell sizes
00156       cellWidth = (int)charWidthMax + ( 2 * fontPadX );  // Set Cell Width
00157       cellHeight = (int)charHeight + ( 2 * fontPadY );  // Set Cell Height
00158       int maxSize = cellWidth > cellHeight ? cellWidth : cellHeight;  // Save Max Size (Width/Height)
00159       if ( maxSize < FONT_SIZE_MIN || maxSize > FONT_SIZE_MAX )  // IF Maximum Size Outside Valid Bounds
00160          return false;                                // Return Error
00161 
00162       // set texture size based on max font size (width or height)
00163       // NOTE: these values are fixed, based on the defined characters. when
00164       // changing start/end characters (CHAR_START/CHAR_END) this will need adjustment too!
00165       if ( maxSize <= 24 )                            // IF Max Size is 18 or Less
00166          textureSize = 256;                           // Set 256 Texture Size
00167       else if ( maxSize <= 40 )                       // ELSE IF Max Size is 40 or Less
00168          textureSize = 512;                           // Set 512 Texture Size
00169       else if ( maxSize <= 80 )                       // ELSE IF Max Size is 80 or Less
00170          textureSize = 1024;                          // Set 1024 Texture Size
00171       else                                            // ELSE IF Max Size is Larger Than 80 (and Less than FONT_SIZE_MAX)
00172          textureSize = 2048;                          // Set 2048 Texture Size
00173 
00174       // create an empty bitmap (alpha only)
00175       Bitmap bitmap = Bitmap.createBitmap( textureSize, textureSize, Bitmap.Config.ALPHA_8 );  // Create Bitmap
00176       Canvas canvas = new Canvas( bitmap );           // Create Canvas for Rendering to Bitmap
00177       bitmap.eraseColor( 0x00000000 );                // Set Transparent Background (ARGB)
00178 
00179       // calculate rows/columns
00180       // NOTE: while not required for anything, these may be useful to have :)
00181       colCnt = textureSize / cellWidth;               // Calculate Number of Columns
00182       rowCnt = (int)Math.ceil( (float)CHAR_CNT / (float)colCnt );  // Calculate Number of Rows
00183 
00184       // render each of the characters to the canvas (ie. build the font map)
00185       float x = fontPadX;                             // Set Start Position (X)
00186       float y = ( cellHeight - 1 ) - fontDescent - fontPadY;  // Set Start Position (Y)
00187       for ( char c = CHAR_START; c <= CHAR_END; c++ )  {  // FOR Each Character
00188          s[0] = c;                                    // Set Character to Draw
00189          canvas.drawText( s, 0, 1, x, y, paint );     // Draw Character
00190          x += cellWidth;                              // Move to Next Character
00191          if ( ( x + cellWidth - fontPadX ) > textureSize )  {  // IF End of Line Reached
00192             x = fontPadX;                             // Set X for New Row
00193             y += cellHeight;                          // Move Down a Row
00194          }
00195       }
00196       s[0] = CHAR_NONE;                               // Set Character to Use for NONE
00197       canvas.drawText( s, 0, 1, x, y, paint );        // Draw Character
00198 
00199       // generate a new texture
00200       int[] textureIds = new int[1];                  // Array to Get Texture Id
00201       gl.glGenTextures( 1, textureIds, 0 );           // Generate New Texture
00202       Log.i("text handle", "" + textureIds[0]);
00203       textureId = textureIds[0];                      // Save Texture Id
00204 
00205       // setup filters for texture
00206       gl.glBindTexture( GL10.GL_TEXTURE_2D, textureId );  // Bind Texture
00207       gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST );  // Set Minification Filter
00208       gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR );  // Set Magnification Filter
00209       gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE );  // Set U Wrapping
00210       gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE );  // Set V Wrapping
00211 
00212       // load the generated bitmap onto the texture
00213       GLUtils.texImage2D( GL10.GL_TEXTURE_2D, 0, bitmap, 0 );  // Load Bitmap to Texture
00214       gl.glBindTexture( GL10.GL_TEXTURE_2D, 0 );      // Unbind Texture
00215 
00216       // release the bitmap
00217       bitmap.recycle();                               // Release the Bitmap
00218 
00219       // setup the array of character texture regions
00220       x = 0;                                          // Initialize X
00221       y = 0;                                          // Initialize Y
00222       for ( int c = 0; c < CHAR_CNT; c++ )  {         // FOR Each Character (On Texture)
00223          charRgn[c] = new TextureRegion( textureSize, textureSize, x, y, cellWidth-1, cellHeight-1 );  // Create Region for Character
00224          x += cellWidth;                              // Move to Next Char (Cell)
00225          if ( x + cellWidth > textureSize )  {
00226             x = 0;                                    // Reset X Position to Start
00227             y += cellHeight;                          // Move to Next Row (Cell)
00228          }
00229       }
00230 
00231       // create full texture region
00232       textureRgn = new TextureRegion( textureSize, textureSize, 0, 0, textureSize, textureSize );  // Create Full Texture Region
00233 
00234       // return success
00235       return true;                                    // Return Success
00236    }
00237 
00238    //--Begin/End Text Drawing--//
00239    // D: call these methods before/after (respectively all draw() calls using a text instance
00240    //    NOTE: color is set on a per-batch basis, and fonts should be 8-bit alpha only!!!
00241    // A: red, green, blue - RGB values for font (default = 1.0)
00242    //    alpha - optional alpha value for font (default = 1.0)
00243    // R: [none]
00244    public void begin()  {
00245       begin( 1.0f, 1.0f, 1.0f, 1.0f );                // Begin with White Opaque
00246    }
00247    public void begin(float alpha)  {
00248       begin( 1.0f, 1.0f, 1.0f, alpha );               // Begin with White (Explicit Alpha)
00249    }
00250    public void begin(float red, float green, float blue, float alpha)  {
00251       gl.glColor4f( red, green, blue, alpha );        // Set Color+Alpha
00252       gl.glBindTexture( GL10.GL_TEXTURE_2D, textureId );  // Bind the Texture
00253       batch.beginBatch();                             // Begin Batch
00254    }
00255    public void end()  {
00256       batch.endBatch();                               // End Batch
00257       gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);  // Bind the Texture
00258       gl.glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );         // Restore Default Color/Alpha
00259    }
00260 
00261    //--Draw Text--//
00262    // D: draw text at the specified x,y position
00263    // A: text - the string to draw
00264    //    x, y - the x,y position to draw text at (bottom left of text; including descent)
00265    // R: [none]
00266    public void draw(String text, float x, float y)  {
00267       float chrHeight = cellHeight * scaleY;          // Calculate Scaled Character Height
00268       float chrWidth = cellWidth * scaleX;            // Calculate Scaled Character Width
00269       int len = text.length();                        // Get String Length
00270       x += ( chrWidth / 2.0f ) - ( fontPadX * scaleX );  // Adjust Start X
00271       y += ( chrHeight / 2.0f ) - ( fontPadY * scaleY );  // Adjust Start Y
00272       for ( int i = 0; i < len; i++ )  {              // FOR Each Character in String
00273          int c = (int)text.charAt( i ) - CHAR_START;  // Calculate Character Index (Offset by First Char in Font)
00274          if ( c < 0 || c >= CHAR_CNT )                // IF Character Not In Font
00275             c = CHAR_UNKNOWN;                         // Set to Unknown Character Index
00276          batch.drawSprite( x, y, chrWidth, chrHeight, charRgn[c] );  // Draw the Character
00277          x += ( charWidths[c] + spaceX ) * scaleX;    // Advance X Position by Scaled Character Width
00278       }
00279    }
00280 
00281    //--Draw Text Centered--//
00282    // D: draw text CENTERED at the specified x,y position
00283    // A: text - the string to draw
00284    //    x, y - the x,y position to draw text at (bottom left of text)
00285    // R: the total width of the text that was drawn
00286    public float drawC(String text, float x, float y)  {
00287       float len = getLength( text );                  // Get Text Length
00288       draw( text, x - ( len / 2.0f ), y - ( getCharHeight() / 2.0f ) );  // Draw Text Centered
00289       return len;                                     // Return Length
00290    }
00291    public float drawCX(String text, float x, float y)  {
00292       float len = getLength( text );                  // Get Text Length
00293       draw( text, x - ( len / 2.0f ), y );            // Draw Text Centered (X-Axis Only)
00294       return len;                                     // Return Length
00295    }
00296    public void drawCY(String text, float x, float y)  {
00297       draw( text, x, y - ( getCharHeight() / 2.0f ) );  // Draw Text Centered (Y-Axis Only)
00298    }
00299 
00300    //--Set Scale--//
00301    // D: set the scaling to use for the font
00302    // A: scale - uniform scale for both x and y axis scaling
00303    //    sx, sy - separate x and y axis scaling factors
00304    // R: [none]
00305    public void setScale(float scale)  {
00306       scaleX = scaleY = scale;                        // Set Uniform Scale
00307    }
00308    public void setScale(float sx, float sy)  {
00309       scaleX = sx;                                    // Set X Scale
00310       scaleY = sy;                                    // Set Y Scale
00311    }
00312 
00313    //--Get Scale--//
00314    // D: get the current scaling used for the font
00315    // A: [none]
00316    // R: the x/y scale currently used for scale
00317    public float getScaleX()  {
00318       return scaleX;                                  // Return X Scale
00319    }
00320    public float getScaleY()  {
00321       return scaleY;                                  // Return Y Scale
00322    }
00323 
00324    //--Set Space--//
00325    // D: set the spacing (unscaled; ie. pixel size) to use for the font
00326    // A: space - space for x axis spacing
00327    // R: [none]
00328    public void setSpace(float space)  {
00329       spaceX = space;                                 // Set Space
00330    }
00331 
00332    //--Get Space--//
00333    // D: get the current spacing used for the font
00334    // A: [none]
00335    // R: the x/y space currently used for scale
00336    public float getSpace()  {
00337       return spaceX;                                  // Return X Space
00338    }
00339 
00340    //--Get Length of a String--//
00341    // D: return the length of the specified string if rendered using current settings
00342    // A: text - the string to get length for
00343    // R: the length of the specified string (pixels)
00344    public float getLength(String text) {
00345       float len = 0.0f;                               // Working Length
00346       int strLen = text.length();                     // Get String Length (Characters)
00347       for ( int i = 0; i < strLen; i++ )  {           // For Each Character in String (Except Last
00348          int c = (int)text.charAt( i ) - CHAR_START;  // Calculate Character Index (Offset by First Char in Font)
00349          len += ( charWidths[c] * scaleX );           // Add Scaled Character Width to Total Length
00350       }
00351       len += ( strLen > 1 ? ( ( strLen - 1 ) * spaceX ) * scaleX : 0 );  // Add Space Length
00352       return len;                                     // Return Total Length
00353    }
00354 
00355    //--Get Width/Height of Character--//
00356    // D: return the scaled width/height of a character, or max character width
00357    //    NOTE: since all characters are the same height, no character index is required!
00358    //    NOTE: excludes spacing!!
00359    // A: chr - the character to get width for
00360    // R: the requested character size (scaled)
00361    public float getCharWidth(char chr)  {
00362       int c = chr - CHAR_START;                       // Calculate Character Index (Offset by First Char in Font)
00363       return ( charWidths[c] * scaleX );              // Return Scaled Character Width
00364    }
00365    public float getCharWidthMax()  {
00366       return ( charWidthMax * scaleX );               // Return Scaled Max Character Width
00367    }
00368    public float getCharHeight() {
00369       return ( charHeight * scaleY );                 // Return Scaled Character Height
00370    }
00371 
00372    //--Get Font Metrics--//
00373    // D: return the specified (scaled) font metric
00374    // A: [none]
00375    // R: the requested font metric (scaled)
00376    public float getAscent()  {
00377       return ( fontAscent * scaleY );                 // Return Font Ascent
00378    }
00379    public float getDescent()  {
00380       return ( fontDescent * scaleY );                // Return Font Descent
00381    }
00382    public float getHeight()  {
00383       return ( fontHeight * scaleY );                 // Return Font Height (Actual)
00384    }
00385 }


android_core
Author(s): Damon Kohler
autogenerated on Thu Jun 6 2019 21:20:07