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

java.util.zip example

So many of you not aware how to use java.util.zip package to compress and uncompress the data. So here are some utility methods for your understanding

public static byte [] zip (byte[] uncompressedData, int off, int len)
{
Deflater compressor = new Deflater();
compressor.setLevel(Deflater.BEST_COMPRESSION);
compressor.setInput(uncompressedData, off, len);
compressor.finish();

ByteArrayOutputStream bos = new ByteArrayOutputStream(len);

byte[] buf = new byte[1024];
while (!compressor.finished())
{
int count = compressor.deflate(buf);
bos.write(buf, 0, count);
}
try
{
bos.close();
}
catch (IOException e)
{
}
return bos.toByteArray();
}

public static byte [] unzip (byte [] compressedData, int off, int len)
{
Inflater decompressor = new Inflater();
decompressor.setInput(compressedData, off, len);

ByteArrayOutputStream bos = null;
bos = new ByteArrayOutputStream(len);

// Decompress the data
byte[] buf = new byte[1024];
while (!decompressor.finished())
{
try
{
int count = decompressor.inflate(buf);
bos.write(buf, 0, count);
}
catch (DataFormatException e)
{
}
}
try
{
bos.close();
}
catch (IOException e)
{
}

return bos.toByteArray();
}

capture stack trace in string

So may of you want to see the complete stack trace in logs. Not happy with Exception.getMessage(). So here is a way to convert the stack trace to string so now you can enjoy the printStackTrace functionality in your logs

/**
* Capture Stack Trace into a String
*/
public static String captureStackTrace(Throwable exception)
{
StringBuffer stackTrace = new StringBuffer();
stackTrace.append("Exception in thread \"");
stackTrace.append(Thread.currentThread());
stackTrace.append("\" ");
stackTrace.append(exception);
stackTrace.append("\n");

StackTraceElement elements[] = exception.getStackTrace();
for (int x = 0; x < elements.length; x++)
{
stackTrace.append(elements[x].toString());
stackTrace.append("\n");
}
return stackTrace.toString();
}

Scaling Image in J2ME

/**
* Creates a new, scaled version of the given image.
*
* @param src: The source image
* @param dstW: The destination (scaled) image width
* @param dstH: The destination (scaled) image height
* @return Image: A new Image object with the given width and height.
*/

public static Image scaleImage (Image src, int dstW, int dstH) {
int srcW = src.getWidth();
int srcH = src.getHeight();

Image tmp = Image.createImage(dstW, srcH);
Graphics g = tmp.getGraphics();

int delta = (srcW << 16) / dstW;
int pos = delta/2;

for (int x = 0; x < dstW; x++) {
g.setClip(x, 0, 1, srcH);
g.drawImage(src, x - (pos >> 16), 0, Graphics.LEFT | Graphics.TOP);
pos += delta;
}

Image dst = Image.createImage(dstW, dstH);
g = dst.getGraphics();

delta = (srcH << 16) / dstH;
pos = delta/2;

for (int y = 0; y < dstH; y++) {
g.setClip(0, y, dstW, 1);
g.drawImage(tmp, 0, y - (pos >> 16), Graphics.LEFT | Graphics.TOP);
pos += delta;
}

return dst;
}


}

StringTokenizer in J2me

So in javame/ j2me StringTokenizer is also not available. I have written some utility methods for this purpose

/**
* stringTokenizer
* Tokenize the string on the basis of parmeter token
* remember empty spaces will not be return as tokens
*
* @param str String
* @param token char
* @return Vector
*/
public static Vector stringTokenizer(String str, char token)
{
/* TOKENIZE THE STRING ON THE BASIS OF THAT CHARACTER*/
Vector temp = new Vector();
str = str.trim();

char[] stringCharacters = str.toCharArray();
int j = 0;
for (int i = 0; i <>
{
if (stringCharacters[i] == token)
{
if (new String(stringCharacters, j, i - j).trim().length() > 0)
{

temp.addElement(new String(stringCharacters, j, i - j));

}
j = i + 1;

}
}
if (j <>
{
temp.addElement(new String(stringCharacters, j,
stringCharacters.length - j));
}
return temp;
}

/***************************************************************************/
/**
* stringTokenizer
* This is overloaded function of stringTokenizer it
* can tokenize on the basis of String also
* Tokenize the string on the basis of parmeter token
* remember empty spaces will not be return as tokens
*
* @param str String
* @param token char
* @return Vector
*/
public static Vector stringTokenizer(String str, String token)
{

Vector temp = new Vector();
int index;
str = str.trim();
index = str.indexOf(token);

while (index != -1)
{
if (str.substring(0, index).trim().length() > 0)
{
temp.addElement(str.substring(0, index));
}
str = str.substring(index + token.length(), str.length());
index = str.indexOf(token);

}
if (index == -1 && str.trim().length() > 0)
{
temp.addElement(str);
}

return temp;
}

/***************************************************************************/
/**
* stringTokenizerWithSpaces
* Tokenize the string on the basis of parmeter token
* here string is trimed from right side so symbol is
* included without spaces
* but empty spaces
* inside string are included as tokens
* This method specially written for the cases
* like "PSO,," Here this method return 3 tokens while
* other 'stringTokenizer(String,char)' will return only one
* @param str String
* @param token char
* @return Vector
*/
public static Vector stringTokenizerWithSpaces(String str, char token)
{
/* TOKENIZE THE STRING ON THE BASIS OF THAT CHARACTER*/
Vector temp = new Vector();
str = str.trim();

char[] stringCharacters = str.toCharArray();
int j = 0;
for (int i = 0; i <>
{
if (stringCharacters[i] == token)
{

if (i > 0)
{
temp.addElement(new String(stringCharacters, j, i - j));
}
j = i + 1;

}
}
/**
* FOR INCLUDING LAST TOKEN
* */
if (j <>
{
temp.addElement(new String(stringCharacters, j,
stringCharacters.length - j));
}
/**
* IF LAST CHARACTER IS TOKEN ITSELF THEN WE LL ADD EMPTY STRING FOR IT
* */
if (stringCharacters[stringCharacters.length - 1] == token)
{
temp.addElement("");
}
return temp;
}

J2ME tips

Here are some tips/ tricks for the very simple problems

Float in CLDC1.0 :
This is the method i wrote years ago when needed to work in CLDC 1.0 with Float. As you might be aware that Float is not supported in CLDC1.0 so it compares the 2 float values given it as String. I have not revised the code so there would be a lot of room to optimize it

public static boolean compareFloats(String str1, String str2)
{
final char DECIMAL = '.';
int decimal = (int) DECIMAL;
str1 = str1.trim();
str2 = str2.trim();
int firstDecimalPosition = str1.indexOf(decimal);
int secondDecimalPosition = str2.indexOf(decimal);

if (firstDecimalPosition == -1)
{
str1 = str1.concat(".0");
firstDecimalPosition = str1.indexOf(decimal);
}
if (secondDecimalPosition == -1)
{
str2 = str2.concat(".0");
secondDecimalPosition = str2.indexOf(decimal);
}

if (str1.substring(0, firstDecimalPosition).equals("0") &&
str2.substring(0, secondDecimalPosition).equals("-0"))
{

return true;
}

if (str1.substring(0, firstDecimalPosition).equals("-0") &&
str2.substring(0, secondDecimalPosition).equals("0"))
{

return false;
}

int firstValue = Integer.parseInt(str1.substring(0,
firstDecimalPosition));
int secondValue = Integer.parseInt(str2.substring(0,
secondDecimalPosition));

if (firstValue > secondValue)
{

return true;
}
else if (firstValue <>
{
return false;

}
else
{
String firstValAfterDec = str1.substring(firstDecimalPosition + 1,
str1.length()).trim();
String secondValAfterDec = str2.substring(secondDecimalPosition + 1,
str2.length()).trim();
int length1 = firstValAfterDec.length();
int length2 = secondValAfterDec.length();
int difference;
if (firstValAfterDec.length() <>
{
difference = length2 - length1;
for (int i = 0; i <>
{
firstValAfterDec = firstValAfterDec + "0";
}
}
if (secondValAfterDec.length() <>
{
difference = length1 - length2;
for (int i = 0; i <>
{
secondValAfterDec = secondValAfterDec + "0";
}
}

firstValue = Integer.parseInt(firstValAfterDec);
secondValue = Integer.parseInt(secondValAfterDec);

if (firstValue > secondValue)
{

return true;
}
else if (firstValue <>
{
return false;

}
else
/** if both value are equal return false*/
{

return false;

}

}

}


equalIqnoreCase in CLDC 1.0:

Again fairly simple

public static boolean equalStrings(String first, String second)
{
first = first.trim().toLowerCase();
second = second.trim().toLowerCase();
return first.equals(second);
}


ASN.1 Continued 2

ASN.1 protocol

So once you have read the tag and the length; the rest is simple. Read the bytes from the stream according to the length. This will be the value of that tag. Now you can interpret that accordingly. For example if you an element version in your stream
  1. First you will read that tag
  2. Then you will read the length ( Length is actually the number of the bytes for the in which value of version is stored)
  3. Then you will read the number of bytes according to the length and this will be value of the your 'version tag'
Thats it from my side on ASN.1 protocol using BER ( basic encoding rule). If you have any questions, queries please do write me in the comments section

Friday, October 22, 2010

ASN.1 Continued

Continuing on the previous post

Reading Length in ASN.1

private int readLength(DataInputStream inputStream)
{
byte[] bytes = readBytes(inputStream, 1);
BitIterator iterator = new BitIterator(bytes);
String mostSignificant = iterator.getBits(1);

String value = iterator.getBits(7);
int length = Integer.parseInt(value, 2);

if (!mostSignificant.equals("0"))
{
bytes = readBytes(inputStream, length);
value = byteArraytoHex(bytes);
length = Integer.parseInt(value, 16);

}

System.out.println("Length of the record " + length);
return length;

}

ASN.1

A few days earlier I have to work on a system using ASN.1 protocol. I did some research to find a solution written in java for BER so that i can test the files encoded through ASN.1; to my surprise the libraries I found further confuse me. I didn't want to blame any one but people have written more complicated things on the subject thus making more confusing for a beginner to understand what the protocol is and how he should write some code to start. So I decided to write a simple piece of code myself.
I am not writing here about the ASN.1 protocol itself; I am writing a piece of code to start decoding a file in ASN.1 protocol using BER. The structure of ASN.1 is like TLV ( which is tag, length, value). You can read more about ASN.1 and BER at wiki.
Reading tag of ASN.1


private String readTag(DataInputStream inputStream)
{

byte[] bytes = readBytes(inputStream, 1);

Of course we can easily read bytes to a byte array, then covert this byte array to hex like

String hexValue = byteArraytoHex(bytes).trim();


If you need help converting byte array to hex please take a look at previous post here
Rest is simple

int tagClass = (bytes[0] & 0xC0) >> 6;

int tagType = (bytes[0] & 0x20) >> 5;
int tag = bytes[0] & 0x1F;
if (tag == 31)
{
StringBuffer buffer = new StringBuffer(byteArraytoHex(bytes).trim());
bytes = readBytes(inputStream, 1);

buffer.append(byteArraytoHex(bytes).trim());
BitIterator iterator = new BitIterator(bytes);
String mostSignificant = iterator.getBits(1);
while (!mostSignificant.equals("0"))
{
bytes = readBytes(inputStream, 1);

buffer.append(byteArraytoHex(bytes).trim());
iterator = new BitIterator(bytes);
mostSignificant = iterator.getBits(1);
}
hexValue = buffer.toString();
}

// System.out.print("Tag Class = ");
// switch (tagClass)
// {
// case 0:
// System.out.print("Universal");
// break;
// case 1:
// System.out.print("Application");
// break;
// case 2:
// System.out.print("Context-Specific");
// break;
// case 3:
// System.out.print("Private");
// break;
// }
//
// System.out.print(" ------ Type = ");
//
// switch (tagType)
// {
// case 0:
// System.out.print("Primitive");
// break;
// case 1:
// System.out.print("Constructed");
// break;
// }
//
// System.out.println(" ------- tage Value = " + tag);

return hexValue;

}



And you might need BitIterator class too; can be found here

Thursday, October 21, 2010

Specific bits from byte

Bit Iteration:
Following code shows how to iterate between bits of a byte array. The original class was taken from somewhere else i have just customized it to get number of desired bits. Please do note that bits are iterated from Most significant bit (MSB)

import java.util.Iterator;

public final class BitIterator implements Iterator
{
private final byte[] array;

private int bitIndex = 0;
private int arrayIndex = 0;

public BitIterator(byte[] array)
{
this.array = array;
}


public boolean hasNext()
{
return (arrayIndex < array.length) && (bitIndex < 8);
}

public Integer next()
{
Integer val = (array[arrayIndex] >> (7 - bitIndex) & 1) == 1 ? 1 : 0;
bitIndex++;
if (bitIndex == 8)
{
bitIndex = 0;
arrayIndex++;
}
return val;
}

public String getBits(int count)
{
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < count; i++)
{
if (hasNext())
{
buffer.append(next());
}
}
return buffer.toString().trim();
}

public void remove()
{
throw new UnsupportedOperationException();
}

}

Byte Array to Hex

Byte Array to Hex:

public static String byteArraytoHex(byte[] bytes)
{
StringBuffer buffer= new StringBuffer();
byte b;
for (int y = 0, x = 0; y < bytes.length; ++y, ++x)
{
b = ((byte) (bytes[y] >> 4));
b = (byte)( b<0?(16+b):b);
buffer.append(Integer.toString((b), 16).toUpperCase());
b = ((byte) (bytes[y] & 0xF));
b=(byte)( b<0?(16+b):b);
buffer.append(Integer.toString((b), 16).toUpperCase());
buffer.append(" ");
}
return buffer.toString();
}