Where people come together to learn, code, and play. Custom-built HTTP server, site generator, and website from scratch using no external libraries. Goal is to be as minimalistic and fun as possible. http://projectdivar.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
SigPlace/readers/fonts/Font.java

199 lines
7.9 KiB

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();
}
}