package readers.fonts ;
import java.awt.image.BufferedImage ;
import java.io.IOException ;
import java.nio.file.Files ;
import java.nio.file.Path ;
import java.nio.file.Paths ;
import java.nio.file.StandardOpenOption ;
import java.util.List ;
import java.awt.Color ;
public class Font {
Glyph [ ] data = new Glyph [ 10 ] ;
final static int TRANSPARENT = new Color ( 0 , 0 , 0 , 0 ) . getRGB ( ) ;
final public static Font FONT_DDR_DIFF = LoadFont ( "ddr_diff" ) ;
final public static Font FONT_DDR_EXCOMBO = LoadFont ( "ddr_excombo" ) ;
final public static Font FONT_DDR_NOTECOUNT = LoadFont ( "ddr_noteCount" ) ;
final public static Font FONT_DDR_SCORE = LoadFont ( "ddr_score" ) ;
final public static Font FONT_ITG_DIFF = LoadFont ( "itg_diff" ) ;
final public static Font FONT_ITG_EX = LoadFont ( "itg_ex" ) ;
final public static Font FONT_ITG_NOTECOUNT = LoadFont ( "itg_noteCount" ) ;
final public static Font FONT_ITG_PCT = LoadFont ( "itg_pct" ) ;
final public static Font FONT_LOVELIVE_NOTECOUNT = LoadFont ( "lovelive_noteCount" ) ;
final public static Font FONT_LOVELIVE_PCT = LoadFont ( "lovelive_pct" ) ;
final public static Font FONT_LOVELIVE_SCORE = LoadFont ( "lovelive_score" ) ;
final public static Font FONT_POPN_COMBO = LoadFont ( "popn_combo" ) ;
final public static Font FONT_POPN_NOTECOUNT = LoadFont ( "popn_noteCount" ) ;
final public static Font FONT_POPN_SCORE = LoadFont ( "popn_score" ) ;
final public static Font FONT_SDVX_EXSCORE = LoadFont ( "sdvx_EXScore" ) ;
final public static Font FONT_SDVX_LITTLESCORE = LoadFont ( "sdvx_littleScore" ) ;
final public static Font FONT_SDVX_NOTECOUNT = LoadFont ( "sdvx_noteCount" ) ;
final public static Font FONT_SDVX_BIGSCORE = LoadFont ( "sdvx_largeScore" ) ;
public static Font LoadFont ( String fontName ) {
Path f = Paths . get ( "readers" , "fonts" , fontName ) ;
if ( Files . exists ( f ) ) {
Font font = new Font ( ) ;
try {
List < String > data = Files . readAllLines ( f ) ;
for ( int i = 0 ; i < data . size ( ) ; i + = 3 ) {
Glyph g = new Glyph ( ) ;
g . width = Integer . parseInt ( data . get ( i ) ) ;
g . height = Integer . parseInt ( data . get ( i + 1 ) ) ;
String dataArr = data . get ( i + 2 ) ;
g . data = new boolean [ dataArr . length ( ) ] ;
for ( int j = 0 ; j < dataArr . length ( ) ; j + + ) {
g . data [ j ] = ( dataArr . charAt ( j ) ) = = '1' ? true : false ;
}
if ( g . width = = 0 | | g . height = = 0 ) {
System . out . println ( " WARNING! Font " + fontName + " does not have glyph data for " + ( i / 3 ) + "!" ) ;
}
font . data [ i / 3 ] = g ;
}
} catch ( IOException e ) {
e . printStackTrace ( ) ;
}
return font ;
} else {
try {
Files . createFile ( f ) ;
} catch ( IOException e ) {
e . printStackTrace ( ) ;
}
}
return new Font ( ) ;
}
public static void TrainFont ( String fontName , String expectedGlyphs , BufferedImage data ) {
Path f = Paths . get ( "readers" , "fonts" , fontName ) ;
Font font = LoadFont ( fontName ) ;
int startX = - 1 ;
int endX = - 1 ;
outer :
for ( int x = 0 ; x < data . getWidth ( ) ; x + + ) {
for ( int y = 0 ; y < data . getHeight ( ) ; y + + ) {
if ( data . getRGB ( x , y ) ! = TRANSPARENT ) {
if ( startX = = - 1 ) {
startX = x ;
}
continue outer ;
}
}
//If we got to here it means we found transparent on everything.
if ( startX ! = - 1 ) {
endX = x ;
//Create a Glyph out of this.
Glyph g = new Glyph ( ) ;
g . width = endX - startX ;
g . height = data . getHeight ( ) ;
int [ ] arr = data . getRGB ( startX , 0 , g . width , g . height , null , 0 , g . width ) ;
//Find the min and max Y.
int startY = g . height ;
int endY = 0 ;
for ( int X = 0 ; X < g . width ; X + + ) {
for ( int Y = 0 ; Y < g . height ; Y + + ) {
if ( arr [ Y * g . width + X ] ! = TRANSPARENT & & Y < startY ) {
startY = Y ;
}
if ( arr [ Y * g . width + X ] ! = TRANSPARENT & & Y > endY ) {
endY = Y ;
}
}
}
g . height = endY - startY ;
g . data = new boolean [ g . width * g . height ] ;
for ( int X = 0 ; X < g . width ; X + + ) {
for ( int Y = 0 ; Y < g . height ; Y + + ) {
g . data [ Y * g . width + X ] = arr [ ( Y + startY ) * g . width + X ] ! = TRANSPARENT ;
}
}
int index = expectedGlyphs . charAt ( 0 ) - '0' ;
if ( index > = 0 & & index < font . data . length ) {
font . data [ index ] = g ;
System . out . println ( "Glyph for number " + index + " has been saved." ) ;
} else {
System . out . println ( "Skip unrecognized glyph: " + expectedGlyphs . charAt ( 0 ) ) ;
}
expectedGlyphs = expectedGlyphs . substring ( 1 ) ;
startX = - 1 ;
endX = - 1 ;
}
}
saveFont ( font , fontName ) ;
}
private static void saveFont ( Font f , String name ) {
StringBuilder sb = new StringBuilder ( ) ;
for ( int i = 0 ; i < f . data . length ; i + + ) {
Glyph g = f . data [ i ] ;
if ( g = = null ) {
g = new Glyph ( ) ;
}
sb
. append ( g . width )
. append ( '\n' )
. append ( g . height )
. append ( '\n' ) ;
for ( int j = 0 ; j < g . data . length ; j + + ) {
sb . append ( g . data [ j ] ? "1" : "0" ) ;
}
sb . append ( '\n' ) ;
}
try {
Files . write ( Paths . get ( "readers" , "fonts" , name ) , sb . toString ( ) . getBytes ( ) , StandardOpenOption . TRUNCATE_EXISTING ) ;
} catch ( IOException e ) {
e . printStackTrace ( ) ;
}
}
public String convertGlyphs ( List < Glyph > glyphs ) {
return convertGlyphs ( glyphs , false ) ;
}
public String convertGlyphs ( List < Glyph > glyphs , boolean debug ) {
StringBuilder sb = new StringBuilder ( ) ;
for ( int i = 0 ; i < glyphs . size ( ) ; i + + ) {
int bestScore = Integer . MIN_VALUE ;
int bestGlyph = 0 ;
for ( int j = 0 ; j < data . length ; j + + ) {
Glyph g_a = glyphs . get ( i ) ;
Glyph g_b = data [ j ] ;
int score = 0 ;
for ( int x = 0 ; x < g_b . width ; x + + ) {
for ( int y = 0 ; y < g_b . height ; y + + ) {
boolean found = false ;
//We can be up to 1 pixel off and still be valid.
inner :
for ( int xx = - 1 ; xx < = 1 ; xx + + ) {
for ( int yy = - 1 ; yy < = 1 ; yy + + ) {
int a_x = x + xx ;
int a_y = y + yy ;
if ( a_x > = 0 & & a_x < g_a . width & & a_y > = 0 & & a_y < g_a . height ) {
int a_index = a_y * g_a . width + a_x ;
if ( g_a . data [ a_index ] = = g_b . data [ y * g_b . width + x ] ) {
found = true ;
break inner ;
}
}
}
}
if ( found ) {
score + + ;
} else {
score - = 2 ;
}
}
}
if ( score > bestScore ) {
bestScore = score ;
bestGlyph = j ;
if ( debug ) {
System . out . println ( "Glyph " + j + " has a score of " + bestScore + "." ) ;
}
}
}
sb . append ( bestGlyph ) ;
}
return sb . toString ( ) ;
}
}