MIDP 內建字體僅支援「等寬/比例、三號字、粗/斜/底線」組合,且各裝置渲染差異大。遊戲、終端機模擬器等需求:
位圖字體 是最佳解:每個字元對應一小塊像素圖,繪製即 drawRegion() 複製像素塊,速度快、體積小 (PNG 壓縮後常 < 1KB)。
font.png 放入 /res/。package com.example.ui;
import javax.microedition.lcdui.*;
import java.io.*;
public final class CustomFont {
private Image fontImage; // 字體圖集
private int charW, charH; // 單字元寬高
private int cols; // 每行字元數 (圖集寬 / charW)
/** 工廠方法:從資源載入 */
public static CustomFont load(String resPath, int charW, int charH) throws IOException {
InputStream is = CustomFont.class.getResourceAsStream(resPath);
if (is == null) throw new IOException("Font not found: " + resPath);
Image img = Image.createImage(is);
is.close();
return new CustomFont(img, charW, charH);
}
private CustomFont(Image img, int cw, int ch) {
fontImage = img;
charW = cw; charH = ch;
cols = img.getWidth() / cw;
}
/** 繪製單一字元 */
public void drawChar(Graphics g, char c, int x, int y, int anchor) {
int idx = c; // 僅支援 ASCII 0~127
if (idx < 0 || idx >= cols * (fontImage.getHeight() / charH)) return;
int sx = (idx % cols) * charW;
int sy = (idx / cols) * charH;
g.drawRegion(fontImage, sx, sy, charW, charH, Sprite.TRANS_NONE, x, y, anchor);
}
/** 繪製字串 (支援換行 \n) */
public void drawString(Graphics g, String str, int x, int y, int anchor) {
int cx = x, cy = y;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c == '\n') { cx = x; cy += charH; continue; }
drawChar(g, c, cx, cy, anchor);
cx += charW;
}
}
/** 字串像素寬度 */
public int stringWidth(String str) {
int max = 0, cur = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == '\n') { max = Math.max(max, cur); cur = 0; }
else cur += charW;
}
return Math.max(max, cur);
}
public int getHeight() { return charH; }
public int charWidth(char c) { return charW; }
}
public class DemoCanvas extends Canvas {
CustomFont font;
public DemoCanvas() {
try { font = CustomFont.load("/res/font.png", 10, 12); }
catch (IOException e) { e.printStackTrace(); }
}
protected void paint(Graphics g) {
g.setColor(0xFFFFFF); g.fillRect(0,0,getWidth(),getHeight());
if (font != null) {
font.drawString(g, "Hello MIDP\nCustom Font!", 10, 10, Graphics.TOP|Graphics.LEFT);
}
}
}
| 需求 | 實作方向 |
|---|---|
| 支援 Unicode / 中文 | 改用「字元碼 → 圖集座標」映射表 (Hashtable/IntMap),圖集只放實際用到的字元 |
| 多種字號/粗細 | 建立多個 CustomFont 實例,或單圖集多區塊 (如 12px/16px 疊放) |
| 抗鋸齒/次像素渲染 | 位圖字體無法做;若必須,改用向量字體 (FreeType 移植) 或預先產生多倍圖再縮放 |
| 文字排版 (對齊、縮排、行距) | 在 drawString 內累算寬度、處理 anchor、行距參數 |
fontImage,避免重複載入。char[] 或 StringBuilder 組裝後再繪製。自訂位圖字體讓 MIDP 應用擁有「像素級掌控力」:無論裝置廠商如何實作內建字體,你的遊戲 UI、終端機模擬器、聊天氣泡都能保持一致外觀。核心只需一張 PNG + 輕量 CustomFont 類,即可在 100KB JAR 額度內實現專業級文字渲染。