/** * PicFont.java * Not well designed, only for common use. * No copyright. Anyone can use or improve it freely. * * Created by pal 2008-3-25 * 2008-3-28 pal bugfix: drawLine go on looping when fontsize == 16 or 32 * 2008-4-2 pal bugfix: * * The old versions use readUTF/writeUTF to store chars in font-file, changed to writeChar/readChar. * * For Motorola V600, as in.available() is always 0, you should change some code: * loaded = in.available() == buf.length; --> loaded=true; * * 2008-4-2 pal add drawCharImg, which use buffered image to draw font, * that will improve spreed but also take up more memory: _fontSize*_maxBit * * 2008-4-8 pal bugfix: color get from g.getColor() do not has alpha bits, you should set it * yourself. Or you will draw nothing (all transparent) in the real phone. */
import java.io.*; import javax.microedition.lcdui.*;
class PicFont { char[] chars; int _fontSize; int _maxBit; short[] fontMapSmall; int[] fontMapLarge; boolean _fontMapShort; boolean loaded; int[] _fontImgBuf; boolean _useImgFont = true; boolean _useGradualColor = true; // Special effects. You can try other image effects here.
public int fontSize(){
return _fontSize; }
public void setUseImgFont(boolean useImageFont){
_useImgFont = useImageFont; }
public void setUseGradualColor(boolean useGradualColor){
_useGradualColor = useGradualColor; } public void load(InputStream is){ DataInputStream in = null; try{ in = new DataInputStream(is); _fontSize = in.readInt(); int charCount = in.readInt(); chars = new char[charCount]; for (int i = 0; i < charCount; i++) chars[i] = in.readChar();
_fontMapShort = _fontSize <= 16; _maxBit = _fontMapShort ? 16 : 32;
byte[] buf = new byte[charCount * _fontSize * (_fontMapShort ? 2 : 4)];
int bytesReaded = in.read(buf); loaded = bytesReaded == buf.length; if (!loaded) return;
if (_fontMapShort) fontMapSmall = Lib.arrayByteToShort(buf); else fontMapLarge = Lib.arrayByteToInteger(buf);
if (_useImgFont) _fontImgBuf = new int[_fontSize*_fontSize];
} catch (Exception e){
System.out.println("PicFont load failed."); } finally {
try{ in.close(); } catch (Exception e){ e.printStackTrace(); } } }
/** * Find char index in char-map. */ private int getCharMapIndex(char ch){
int idx = -1; for (int i = 0; i < chars.length; i++) if (chars[i] == ch){ idx = i; break; }; return idx > 0 ? idx * _fontSize : idx; }
private void drawLine(Graphics g, int pixelBytes, int x, int y ){
int offsetX = 0; for (int startBit=0, len = 0; startBit < _maxBit; startBit++){
if ((pixelBytes & (1 << startBit)) == 0){
if (len > 0) g.fillRect(x + offsetX, y, len, 1); len = 0; } else {
if (len++ == 0) offsetX = startBit; if (startBit >= _maxBit-1) g.fillRect(x + offsetX, y, len, 1); } } }
private void drawCharLine(Graphics g, int start, int x, int y){
for (int i = start; i < start + _fontSize; i++) drawLine(g, _fontMapShort ? fontMapSmall[i] : fontMapLarge[i], x, y++); }
private void drawCharImg(Graphics g, int start, int x, int y){
int color = g.getColor() | 0xff000000; int line = 0; for (int i = start; i < start + _fontSize; i++){
int pixel = _fontMapShort ? fontMapSmall[i] : fontMapLarge[i]; for (int bit = 0; bit < _fontSize; bit++) _fontImgBuf[line+bit] = (pixel & (1 << (bit))) != 0 ? color : 0;
line += _fontSize; } if (_useGradualColor) FontEffect.gradualEffect(_fontImgBuf, _fontSize, _fontSize, color);
g.drawRGB(_fontImgBuf, 0, _fontSize, x, y, _fontSize, _fontSize, true); }
public void drawChar(Graphics g, char c, int x, int y ){
if (!loaded) return; int start = getCharMapIndex(c);
if (start < 0) return;
try {
if (_useImgFont) drawCharImg(g, start, x, y); else drawCharLine(g, start, x, y); } catch (Exception e){ e.printStackTrace(); } } }
class FontEffect {
private static int gradSingleColor(int r, int bits){
r = (r >> bits) & 0xff; r = r > 5 ? (r-5) : r; return r << bits; }
private static int gradualColor(int color){
int r = gradSingleColor(color, 16); int g = gradSingleColor(color, 8); int b = gradSingleColor(color, 0);
return (color & 0xFF000000) | r | g | b; }
public static void gradualEffect(int[] buf, int width, int height, int color){
int line = 0; int lineColor = color; for (int h = 0; h < height; h++){
for (int w = 0; w < width; w++) buf[line+w] = (buf[line+w] & 0xFF000000) == 0 ? 0 : lineColor; lineColor = gradualColor(lineColor); line += width; } } }
|