Reputation: 45
I am Persian and j2me do not have good support for persian font.
I will create a native font library that get bitmap font and paint my persian text in desplay. But I have a problem.
In english each letter is a set consist shap and uncode. Like (a , U+0061)
But in persian a char may have several shape. for example letter 'ب' in persian alphabet can be:
آب --when it is separate letter in a word
به --when it is start letter in a word
...
How can I get other form of a letter from font file?
Upvotes: 3
Views: 394
Reputation: 14042
I am a persian developer and I had the same problem in about 4 years ago.You have some way to solve this problem:
1-using custom fonts.
2-reshape your text before display it.
A good article in about first,is "MIDP Terminal Emulation, Part 3: Custom Fonts for MIDP ".But for arabic letters I think that is not simple.
In about second way,say you would to replace any character in your text with correct character.This means when you have:
String str = "به";
If get str characters they will be look like:
{1576,1607} that is like "ب ه" instead of "به".So you would to replace incorrect Unicode with correct Unicode codes(in this case correct characters are: {65169, 65258}).You can use "Arabic Reshapers" even reshapers that designed for android!I saw 2 link for this reshapers:1-github 2-Arabic Android(I'm persian developer and so I do not try them,instead I create classes with the same idea as they have).
With using a good reshaper also you may have problem with character arranging from left to right instead of right to left.(some phones draw characters from left to right and other from right to left).I use below class to detect that ordering is true(from right to left) or not:
public class DetectOrdering{
public static boolean hasTrueOrdering()
{
boolean b = false;
try {
char[] chArr = {65169, 65258};
String str = new String(chArr);
System.out.println(str);
int width = f1.charWidth(chArr[1]) / 2;
int height = f1.getHeight();
image1 = Image.createImage(width, height);
image2 = Image.createImage(width, height);
Graphics g1 = image1.getGraphics();
Graphics g2 = image2.getGraphics();
g1.drawString(str, 0, 0, 0);
g2.drawChar(chArr[1], 0, 0, 0);
int[] im1 = new int[width * height];
int[] im2 = new int[width * height];
image1.getRGB(im1, 0, width, 0, 0, width, height);
image2.getRGB(im2, 0, width, 0, 0, width, height);
if (areEqualIntArrrays(im1, im2)) {
b = true;
} else {
b = false;
}
} catch (Exception e) {
e.printStackTrace();
}
return b;
}
private static boolean areEqualIntArrrays(int[] i1, int[] i2) {
if (i1.length != i2.length) {
return false;
} else {
for (int i = 0; i < i1.length; i++) {
if (i1[i] != i2[i]) {
return false;
}
}
}
return true;
}
}
If DetectOrdering.hasTrueOrdering() returns true,sure that phone draw Arabic characters from right to left and display your String.If returns false it draws from left to right.If phone draws Arabic character from left to right you would to reverse string after reshape it and then you can display it.
Upvotes: 2
Reputation: 4043
You can use one alphabet.png for the direct unicode mappings (those where the persian char does not change because of the neighbor chars). If your characters are monospaced, you may start with below class, as seen at http://smallandadaptive.blogspot.com.br/2008/12/custom-monospaced-font.html:
public class MonospacedFont { private Image image; private char firstChar; private int numChars; private int charWidth; public MonospacedFont(Image image, char firstChar, int numChars) { if (image == null) { throw new IllegalArgumentException("image == null"); } // the first visible Unicode character is '!' (value 33) if (firstChar <= 33) { throw new IllegalArgumentException("firstChar <= 33"); } // there must be at lease one character on the image if (numChars <= 0) { throw new IllegalArgumentException("numChars <= 0"); } this.image = image; this.firstChar = firstChar; this.numChars = numChars; this.charWidth = image.getWidth() / this.numChars; } public void drawString(Graphics g, String text, int x, int y) { // store current Graphics clip area to restore later int clipX = g.getClipX(); int clipY = g.getClipY(); int clipWidth = g.getClipWidth(); int clipHeight = g.getClipHeight(); char[] chars = text.toCharArray(); for (int i = 0; i < chars.length; i++) { int charIndex = chars[i] - this.firstChar; // current char exists on the image if (charIndex >= 0 && charIndex <= this.numChars) { g.setClip(x, y, this.charWidth, this.image.getHeight()); g.drawImage(image, x - (charIndex * this.charWidth), y, Graphics.TOP | Graphics.LEFT); x += this.charWidth; } } // restore initial clip area g.setClip(clipX, clipY, clipWidth, clipHeight); } }
And change it to use a different char_uxxxx.png file for each persian char that changes because of the neighbor chars.
When parsing your string, before painting, you must check which png file is appropriate to use. Hope this is a good place to start.
Upvotes: 1