package controlP5; /** * controlP5 is a processing gui library. * * 2006-2015 by Andreas Schlegel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA * * @author Andreas Schlegel (http://www.sojamo.de) * @modified ##date## * @version ##version## * */ import java.lang.reflect.Constructor; import java.util.Arrays; import processing.core.PApplet; import processing.core.PFont; import processing.core.PImage; public class BitFont extends PFont { static public final String standard58base64 = "AakACQBgACAEAgQGBggGAgMDBAYDBAIGBQMFBQUFBQUFBQICBAUEBQgFBQUFBQUFBQIFBQQGBQUFBQUFBAUGCAUGBQMFAwYGAwQEBAQEBAQEAgQEAgYEBAQEAwQEBAQGBAQEBAIEBQKgUgghIaUAAIiRMeiZZwwAAANgjjnvmRRKESVzzDGXoqQUvYURQCCAQCCSCAAAAAgAAABEqECleCVFkRAAiLSUWEgoJQAAiSOllEJIKVRiSymllCRFSSlCEVIAQQBBQAARAAAAEAAAACQpgeALJASiIwAQSQipE1BKRS+QSEohhRBSqES1UkopSIqSkkIiFAGwEZOwSaplZGx2VVXVSQIAgeIgSETy4RCSCEnoEONAgJCkd0I6p73QiKilk46RpCQZQoQIAFBVVVOVVFVVVUKqqiqKCACCDyKpiIoAICQJ9FAiCUE8ElUphRRCSqESUUohJSRJSUpECBEAoCrqoiqZqqqqiFRVUiIJAADKI5UQASEgSAoJpSRSCgECUlJKKYSUSiWilEJKSRKRlIgQJABAVVVEVVJVVVUhqaqqQhIACBQixEIBQFBg9AwyRhhDBEIIpGPOCyZl0kXJBJOMGMImEW9owAcbMQmrpKpKxjJiopQdFQAAAAAAAABAAAAAAAAAAIAAAOAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAQIAAAEAQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgAAAgCAAAAAgAA"; static public final String standard56base64 = "AeYACQBgACAEAgQGBggHAgMDBgYDBQIFBgMGBgYGBgYGBgIDBAYEBggGBgYGBgYGBgIGBgUIBgYGBgYGBgYGCAYGBgMFAwYHAwUFBQUFAwUFAgMFAggFBQUFBAQEBQUIBQUFBAMEBQKgUgghRwoBAIAcOQ7yOZ/jAADAAXAe5/k+JwqKQlDkPM7jfFGUFEXfwghAQAAICIQUAgAAAAABAAAAQAkVqBSvJFJUEQCQaFHEBBEURQAAiDiiKIqCIIqCkjAWRVEURUQUJUURFCEFIBAAAgEBhAAAAABAAAAAAEikBIIvkFAQOQQAJBIEKU8ARVGiLyCRKAqiIAiioCJUTVEURQERRUmKgkQoAsAd40zcSambY447u5SSUnoSAYBAcRBMRNWHh4iEMAn0II4HBBAk6XuC6HmyL2gISVX0RI9DREoSQRAhAgBIKaW0lFIpKaWUIiSlpJRQhAAg+CCSFBFBACAiEdAHRUgEgfiIqIqiIAqCKAoqQlAWBVEBEZGSpBBCiAAAUgrpJaU0SkoppRBJKckkIxEAAJRHKkIEEACESEKERBERRUEAAVKiKIqCIIqKkhAURUGUREREJEVEECQAgJRSCkkplZJSSilIUkpKKUgEAAKFCHGhAIBAwdHnII5DOA4iIAiB6HGeL3CinOgFRU7gRA7hEDYR8QUJ+MEd40xcSqmkZI6LEWdsknsSAQAAAAAAAAAgAAAAAAAAAACAAACAAwAAAAAAAAAAAAAAQAAAAAAAAAADAwAAAAAABBAAAICAAAAAAIAAJQAAAAAAAAAABAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAACAAAgIAAAAAAYAAA="; static public final String grixelbase64 = "AnoADABgACAFAgQICAoIAgQEBgYDBQIKCQMICAgICAcICAIDBQYFBwkICAgIBwcICAYHCAcJCAgICAgICAgICggICAQKBAQHBAcHBwcHBQcHAgUHBAoHBwcHBgcGBwcKBwcHBQIFCAJAJeIjkENBAAAAQHzk4wPz5/Pz8QEAAB4ePj8+Pz6fX9AHCgoECvL58fnx+QsKiigo6C8CIAEIIAAAARwgEAoEAAAAAAAABAAAAAAAICIAAZVIUiERBQEAAIAIWlAQSkAQKCgIICCEhAQFBQUFAgFBBCgoMGwoKCgoKAghKCiioCCgEIAKQIAAAAQIgAAgEAAAAAAAABAAAAAAAICIsAUEfwlCRBCkEAAAIUhAQCQBAaCgIEAAAcoUFBQQFAgEBBGgoECpoqCgoKAAhKCgiEREQIIAAgAAAgAQIAACgEAAAAAAAABAAAAAAAAAIrIBEIgkgBBBEEEAAIIgAQGJ/ARAgoKS+AioVFBQQFAgEBBEgEICmZKCgoKCAhCCgiKioIAIBAgA4Pl4fJ7n+YRC8c7H8/F5ni8UiigU+okIAEAg4gOBA0HfhwcEguTDEwL0g/DxAwFAoFJ/PwFBv1/eHwH6CASKCgoKCvJBCAqKCAEBISAgAAAoFAqFQigUikREoVAoFISEUCgiSQgSQgAAgQgSAlEEEQQACAhSANAfUBAhCAiIj2BKBQUFBAUCQUEEKCQQKCzoJ+gHCCEoKCIKBIIAgQAAvlAg9AuhUOgREYVCoVBgEEKhiBghhIgAAAB/SITEEKQQABAgSAFAIEBBhCAgQABByBMUFBAUCAQFEaGgQKCgoICgECCEIJGIRBAEAggCAIRCgVAghEKhSEQUCoVCAUYIhSJihAgiAgAAiCQJFUMQAAgggCAFBIEEBRGCghACAkBAUFBQUCAQFESEggKBgoICkoKCEIIoIgpCCAhACAAQCoVCoRAKhUIRUSgUCgUhISSJSBISiAgAQCDiE4gTQQAgUAB89OcD4uND8PFJAAAEfkE/Pj++gF/Q5wn6BQryCfAJ8kHwQXAnCOEvACIAgM/j8XiCLxQKWUQhz8cXeDgPw52Q7yciAAAAAAIAANgAQAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAgAPg4AcAAAAAACAACAAAAAABEAAAAAAAACAAawAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4ABgAAAAABEAAAAAAAAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; protected int characters; protected int[] charWidth = new int[ 255 ]; protected int charHeight; protected int[][] chars; protected int lineHeight = 10; protected int kerning = 0; protected int wh; protected PImage texture; public static int defaultChar = 32; public BitFont( byte[] theBytes ) { super( ); texture = decodeBitFont( theBytes ); make( ); size = lineHeight; glyphs = new Glyph[ 256 ]; ascii = new int[ 128 ]; Arrays.fill( ascii , -1 ); lazy = false; ascent = 4; descent = 4; glyphCount = 128; for ( int i = 0 ; i < 128 ; i++ ) { // unfortunately the PFont.Glyph constructor in // the android source code is for whatever // reason protected and not public like in the // java application source, therefore the // bitfont will only be used in the java // application mode until changes to the // processing core code have been made. see // issue // http://code.google.com/p/processing/issues/detail?id=1293 try { Constructor< PFont.Glyph >[] constructors = ( Constructor< PFont.Glyph >[] ) PFont.Glyph.class.getDeclaredConstructors( ); Constructor< PFont.Glyph > constructor = ( Constructor< PFont.Glyph > ) PFont.Glyph.class.getDeclaredConstructors( )[ 0 ]; constructor.setAccessible( true ); for ( Constructor< PFont.Glyph > c : constructors ) { c.setAccessible( true ); if ( c.getParameterTypes( ).length == 1 ) { glyphs[ i ] = c.newInstance( this ); break; } } } catch ( Exception e ) { System.out.println( e ); } // as soon as the constructor is public, the // line below will replace the hack above // glyphs[i] = new Glyph(); glyphs[ i ].value = i; if ( glyphs[ i ].value < 128 ) { ascii[ glyphs[ i ].value ] = i; } glyphs[ i ].index = i; int id = i - 32; if ( id >= 0 ) { glyphs[ i ].image = new PImage( charWidth[ id ] , 9 , ALPHA ); for ( int n = 0 ; n < chars[ id ].length ; n++ ) { glyphs[ i ].image.pixels[ n ] = ( chars[ id ][ n ] == 1 ) ? 0xffffffff : 0x00000000; } glyphs[ i ].height = 9; glyphs[ i ].width = charWidth[ id ]; glyphs[ i ].index = i; glyphs[ i ].value = i; glyphs[ i ].setWidth = charWidth[ id ]; glyphs[ i ].topExtent = 4; glyphs[ i ].leftExtent = 0; } else { glyphs[ i ].image = new PImage( 1 , 1 ); } } } public Glyph getGlyph( char c ) { int n = ( int ) c; /* if c is out of the BitFont-glyph bounds, return * the defaultChar glyph (the space char by * default). */ n = ( n >= 128 ) ? defaultChar : n; return glyphs[ n ]; } PImage decodeBitFont( byte[] bytes ) { PImage tex; // read width int w = CP.byteArrayToInt( new byte[] { bytes[ 0 ] , bytes[ 1 ] } ); // read height int h = CP.byteArrayToInt( new byte[] { bytes[ 2 ] , bytes[ 3 ] } ); // read size of chars int s = CP.byteArrayToInt( new byte[] { bytes[ 4 ] , bytes[ 5 ] } ); // read first ascii char int c = CP.byteArrayToInt( new byte[] { bytes[ 6 ] , bytes[ 7 ] } ); tex = new PImage( w , h , PApplet.ALPHA ); // read bytes and write pixels into image int off = 8 + s; for ( int i = off ; i < bytes.length ; i++ ) { for ( int j = 0 ; j < 8 ; j++ ) { tex.pixels[ ( i - off ) * 8 + j ] = CP.getBit( bytes[ i ] , j ) == 1 ? 0xff000000 : 0xffffffff; } } int cnt = 0 , n = 0 , i = 0; // add character seperators on top of the texture for ( i = 0 ; i < s ; i++ ) { while ( ++cnt != bytes[ i + 8 ] ) { } n += cnt; tex.pixels[ n ] = 0xffff0000; cnt = 0; } return tex; } int getHeight( ) { return texture.height; } BitFont make( ) { charHeight = texture.height; lineHeight = charHeight; int currWidth = 0; for ( int i = 0 ; i < texture.width ; i++ ) { currWidth++; if ( texture.pixels[ i ] == 0xffff0000 ) { charWidth[ characters++ ] = currWidth; currWidth = 0; } } chars = new int[ characters ][]; int indent = 0; for ( int i = 0 ; i < characters ; i++ ) { chars[ i ] = new int[ charWidth[ i ] * charHeight ]; for ( int u = 0 ; u < charWidth[ i ] * charHeight ; u++ ) { chars[ i ][ u ] = texture.pixels[ indent + ( u / charWidth[ i ] ) * texture.width + ( u % charWidth[ i ] ) ] == 0xff000000 ? 1 : 0; } indent += charWidth[ i ]; } return this; } }