Monday, October 25, 2010

Custom Font in J2ME

I have seen many posts where people asking help for creating custom font in j2me so i though to share an example for the people. The idea is to use self created custom font as an image and when required drawing of a string draw particular part of the image through clipping. Of course that particular part of the image will match the string we wish to draw. This way you can control the height and width of the image which j2me doesn't provide you. I have created an image in photo shop to be used as font.



import javax.microedition.lcdui.*;

public class CustomFont {

private Image image;
private int[] widthMap;
private int[] positionMap;
private String characterMap;
public int height;
private int length;

public CustomFont() {
if (initialize()) {
this.height = 12;
length = characterMap.length();
this.positionMap = new int[length];
short xPos = 0;
int width = 0;
for (int i = 0; i < length; i++) {
width = this.widthMap[i];
this.positionMap[i] = xPos;
xPos += width;
}
} else {
System.out.println("Could not initialize Custom Font");
}
}

public boolean initialize() {

try {
this.image = Image.createImage("/custom font.png");
this.characterMap = "@©®?$&_+-'\"(),./\\:;!<>0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz%*|[]= ";
this.widthMap = new int[]{12, 10, 10, 6, 6, 8, 8, 6, 4, 2, 4, 4,
4, 2, 2, 4, 4, 2, 2, 2, 6, 6, 6, 4, 6, 6, 6, 6, 6, 6, 6, 6, 8, 7, 8, 8, 7, 6, 8, 8, 2, 6, 8, 7, 8, 8, 8, 7, 8, 8, 7, 8,
8, 8, 12, 8, 8, 8, 6, 6, 5, 6, 6, 5, 6, 6, 2, 3, 6, 2, 10, 6, 6, 6, 6, 4, 6, 4, 6, 6, 10, 6, 6, 6, 10, 6, 2, 3, 3, 7, 3
};
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}

public void drawString(String str, int x, int y, Graphics graphics) {

int[] previousWidthMap;
int[] previousPositionsMap;
int[] indeces = null;

length = str.length();
indeces = new int[length];
for (int i = length - 1; i >= 0; i--) {
char inputCharacter = str.charAt(i);
indeces[i] = indexOf(inputCharacter);
}

previousPositionsMap = new int[indeces.length];
previousWidthMap = new int[indeces.length];

for (int i = 0; i < indeces.length; i++) {
int index = indeces[i];
if (index == -1) {
// ignore, this is a character which is not available in the
// character-map
} else {

previousPositionsMap[i] = positionMap[index];
previousWidthMap[i] = widthMap[index];
}
}
int clipX = graphics.getClipX();
int clipY = graphics.getClipY();
int clipWidth = graphics.getClipWidth();
int clipHeight = graphics.getClipHeight();
for (int i = 0; i < previousWidthMap.length; i++) {
int characterWidth = previousWidthMap[i];
graphics.clipRect(x, y, characterWidth, this.height);
int imageX = x - previousPositionsMap[i];
int imageY = y;
graphics.drawImage(this.image, imageX, imageY, Graphics.TOP | Graphics.LEFT);
x += characterWidth;

graphics.setClip(clipX, clipY, clipWidth, clipHeight);
}

}

public int stringWidth(String str) {
length = str.length();
int width = 0;
for (int i = length - 1; i
>= 0; i--) {
char inputCharacter = str.charAt(i);
int charactorMapIndex = this.characterMap.indexOf(inputCharacter);
if (charactorMapIndex == -1) {
charactorMapIndex = this.characterMap.indexOf("?");
}

width = width + this.widthMap[charactorMapIndex];
}

return width;
}

public int getHeight() {
return height;
}

private int indexOf(char inputCharacter) {
return characterMap.indexOf(inputCharacter);
}
}