/*
* ShareNav - Copyright (c) 2008 Kai Krueger apmon at users dot sourceforge dot net
* See file COPYING
*/
package net.sharenav.midlet.graphics;
import java.io.IOException;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import net.sharenav.midlet.util.ImageTools;
import net.sharenav.util.Logger;
import de.enough.polish.util.Locale;
public class LcdNumericFont {
private final static Logger logger = Logger.getInstance(
LcdNumericFont.class, Logger.DEBUG);
private final static byte SEGMENT_BOTTOM_LEFT = 1;
private final static byte SEGMENT_TOP_LEFT = 2;
private final static byte SEGMENT_TOP = 4;
private final static byte SEGMENT_TOP_RIGHT = 8;
private final static byte SEGMENT_BOTTOM_RIGHT = 16;
private final static byte SEGMENT_BOTTOM = 32;
private final static byte SEGMENT_MIDDLE = 64;
/** Original sized image of vertical bar */
private Image vert_bar_orig;
/** Original sized image of horizontal bar */
private Image horiz_bar_orig;
/** Image of vertical bar scaled to the current font size */
private Image vert_bar;
/** Image of horizontal bar scaled to the current font size */
private Image horiz_bar;
/** Image of vertical bar scaled to previous size for faster switching */
private Image vert_bar_cache;
/** Image of horizontal bar scaled to previous size for faster switching */
private Image horiz_bar_cache;
/** Current font size */
private int fontSize = 48;
/** Font size corresponding to the cached images */
private int fontSize_cache = -1;
public LcdNumericFont() {
try {
vert_bar_orig = Image.createImage("/LCD_vert.png");
horiz_bar_orig = Image.createImage("/LCD_horiz.png");
vert_bar = vert_bar_orig;
horiz_bar = horiz_bar_orig;
} catch (IOException ioe) {
logger.exception(Locale.get("lcdnumericfont.CouldNotLoadLCDFontSegments")
/*Could not load the LCD font segments*/, ioe);
}
}
/** Sets the font size.
* @param size Font size in
*/
public void setFontSize(int size) {
if (fontSize == size) {
return;
}
if (size == fontSize_cache) {
int tmpSize = fontSize;
fontSize = fontSize_cache;
fontSize_cache = tmpSize;
Image tmpImage = vert_bar;
vert_bar = vert_bar_cache;
vert_bar_cache = tmpImage;
tmpImage = horiz_bar;
horiz_bar = horiz_bar_cache;
horiz_bar_cache = tmpImage;
} else {
fontSize_cache = fontSize;
vert_bar_cache = vert_bar;
horiz_bar_cache = horiz_bar;
fontSize = size;
vert_bar = ImageTools.scaleImage(vert_bar_orig, 12 * size / 48, (size >> 1));
horiz_bar = ImageTools.scaleImage(horiz_bar_orig, (size >> 1), 12 * size / 48);
}
}
/**
* Draw an integer to the graphics canvas in the LCD font
* @param g Graphics context for drawing
* @param i integer to draw
* @param x x-coordinate of the bottom right corner
* @param y y-coordinate of the bottom right corner
*/
public void drawInt(Graphics g, int i, int x, int y) {
drawInt(g, i, 0, x, y);
}
/**
* Draw an integer to the graphics canvas in the LCD font
* @param g Graphics context for drawing
* @param i integer to draw
* @param minDigit left fill with 0 up to minDigit digits
* @param x x-coordinate of the bottom right corner
* @param y y-coordinate of the bottom right corner
*/
public void drawInt(Graphics g, int i, int minDigit, int x, int y) {
boolean negative = (i < 0);
int digitPos = 0;
if (negative) {
i *= -1;
}
int digit = i % 10;
drawDigit(g, (byte) digit, x, y);
digitPos++;
i /= 10;
while ((i > 0) || (digitPos < minDigit)) {
digit = i % 10;
drawDigit(g, (byte) digit, x - digitPos * fontSize, y);
digitPos++;
i /= 10;
}
if (negative) {
drawDigit(g, (byte) -1, x - digitPos * fontSize, y);
}
}
/**
* Draw a floating point number to the graphics canvas in the LCD font
* @param g Graphics context for drawing
* @param f number to draw
* @param decimalPlaces number of decimal places to show
* @param x x-coordinate of the bottom right corner
* @param y y-coordinate of the bottom right corner
*/
public void drawFloat(Graphics g, float f, int decimalPlaces, int x, int y) {
logger.info("Drawing float " + f);
int multi = 1;
for (int i = 0; i < decimalPlaces; i++) {
multi *= 10;
}
int frac = ((int) (f * multi)) % multi;
drawInt(g, (frac < 0) ? -1 * frac : frac, decimalPlaces, x, y);
g.fillRect(x - (fontSize * decimalPlaces + (fontSize >> 3)), y
- (fontSize >> 3), (fontSize >> 3), (fontSize >> 3));
drawInt(g, (int) f, x - (fontSize * decimalPlaces + (fontSize >> 2)), y);
}
/**
* Draw a dash for every decimal place to indicate that the number is
* invalid / not available.
* @param g Graphics context for drawing
* @param decimalPlaces number of decimal places to show
* @param x x-coordinate of the bottom right corner
* @param y y-coordinate of the bottom right corner
*/
public void drawInvalid(Graphics g, int decimalPlaces, int x, int y) {
for (int i = 0; i < decimalPlaces; i++) {
drawDigit(g, (byte) -1, x, y);
x -= fontSize;
}
}
/**
* Draw one digit to the graphics canvas in the LCD font
* @param g Graphics context for drawing
* @param digit Digit to draw, -1 (dash) to 9
* @param x x-coordinate of the bottom right corner
* @param y y-coordinate of the bottom right corner
*/
private void drawDigit(Graphics g, byte digit, int x, int y) {
switch (digit) {
case -1: {
drawSegment(g, (SEGMENT_MIDDLE), x, y);
break;
}
case 0: {
drawSegment(g, (byte) (SEGMENT_BOTTOM | SEGMENT_TOP
| SEGMENT_BOTTOM_LEFT | SEGMENT_BOTTOM_RIGHT
| SEGMENT_TOP_LEFT | SEGMENT_TOP_RIGHT), x, y);
break;
}
case 1: {
drawSegment(g, (byte) (SEGMENT_BOTTOM_RIGHT | SEGMENT_TOP_RIGHT),
x, y);
break;
}
case 2: {
drawSegment(g, (byte) (SEGMENT_BOTTOM | SEGMENT_TOP | SEGMENT_MIDDLE
| SEGMENT_BOTTOM_LEFT | SEGMENT_TOP_RIGHT), x, y);
break;
}
case 3: {
drawSegment(g, (byte) (SEGMENT_BOTTOM | SEGMENT_TOP | SEGMENT_MIDDLE
| SEGMENT_BOTTOM_RIGHT | SEGMENT_TOP_RIGHT), x, y);
break;
}
case 4: {
drawSegment(g, (byte) (SEGMENT_BOTTOM_RIGHT | SEGMENT_TOP_LEFT
| SEGMENT_TOP_RIGHT | SEGMENT_MIDDLE), x, y);
break;
}
case 5: {
drawSegment(g, (byte) (SEGMENT_BOTTOM | SEGMENT_TOP | SEGMENT_MIDDLE
| SEGMENT_BOTTOM_RIGHT | SEGMENT_TOP_LEFT), x, y);
break;
}
case 6: {
drawSegment(g, (byte) (SEGMENT_BOTTOM | SEGMENT_TOP
| SEGMENT_MIDDLE | SEGMENT_BOTTOM_LEFT
| SEGMENT_BOTTOM_RIGHT | SEGMENT_TOP_LEFT), x, y);
break;
}
case 7: {
drawSegment(g,
(byte) (SEGMENT_TOP | SEGMENT_BOTTOM_RIGHT | SEGMENT_TOP_RIGHT),
x, y);
break;
}
case 8: {
drawSegment(g, (byte) (SEGMENT_BOTTOM | SEGMENT_TOP | SEGMENT_MIDDLE
| SEGMENT_BOTTOM_LEFT | SEGMENT_BOTTOM_RIGHT
| SEGMENT_TOP_LEFT | SEGMENT_TOP_RIGHT), x, y);
break;
}
case 9: {
drawSegment(g, (byte) (SEGMENT_TOP | SEGMENT_MIDDLE | SEGMENT_BOTTOM_RIGHT
| SEGMENT_TOP_LEFT | SEGMENT_TOP_RIGHT), x, y);
break;
}
}
}
/**
* Draw the segments of a number to the graphics canvas in the LCD font
* @param g Graphics context for drawing
* @param segments Bit field specifying the digits to draw
* @param x x-coordinate of the bottom right corner
* @param y y-coordinate of the bottom right corner
*/
private void drawSegment(Graphics g, byte segments, int x, int y) {
if ((segments & SEGMENT_BOTTOM_RIGHT) != 0) {
g.drawImage(vert_bar, x, y, Graphics.BOTTOM | Graphics.RIGHT);
}
if ((segments & SEGMENT_TOP_RIGHT) != 0) {
g.drawImage(vert_bar, x, y - (int) (fontSize * 0.62),
Graphics.BOTTOM | Graphics.RIGHT);
}
if ((segments & SEGMENT_BOTTOM) != 0) {
g.drawImage(horiz_bar, x - (fontSize >> 2), y + (fontSize >> 3),
Graphics.BOTTOM | Graphics.RIGHT);
}
if ((segments & SEGMENT_MIDDLE) != 0) {
g.drawImage(horiz_bar, x - (fontSize >> 2), y
- (int) (fontSize * 0.4375), Graphics.BOTTOM
| Graphics.RIGHT);
}
if ((segments & SEGMENT_TOP) != 0) {
g.drawImage(horiz_bar, x - (fontSize >> 2), y - fontSize,
Graphics.BOTTOM | Graphics.RIGHT);
}
if ((segments & SEGMENT_BOTTOM_LEFT) != 0) {
g.drawImage(vert_bar, x - ((3 * fontSize) >> 2), y, Graphics.BOTTOM
| Graphics.RIGHT);
}
if ((segments & SEGMENT_TOP_LEFT) != 0) {
g
.drawImage(vert_bar, x - ((3 * fontSize) >> 2), y
- (int) (fontSize * 0.62), Graphics.BOTTOM
| Graphics.RIGHT);
}
}
}