首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2ME

MIDP 自訂字體實作:從位圖字體產生到 CustomFont 類完整設計

     編輯:J2ME

為什麼需要自訂字體?

MIDP 內建字體僅支援「等寬/比例、三號字、粗/斜/底線」組合,且各裝置渲染差異大。遊戲、終端機模擬器等需求:

  • 絕對等寬、像素級對齊
  • 極小字體 (6~8px) 仍清晰可讀
  • 跨裝置外觀一致

位圖字體 是最佳解:每個字元對應一小塊像素圖,繪製即 drawRegion() 複製像素塊,速度快、體積小 (PNG 壓縮後常 < 1KB)。

一、字體圖集製作流程

  1. 選擇等寬字體 (如 Anonymous 6pt,免費商用)。
  2. 建立畫布:高 = 字高 (如 12px),寬 = 字寬 × 字元數 (ASCII 128 字元 → 10px × 128 = 1280px)。
  3. 將字元按 ASCII 碼序 (0~127) 依次繪入畫布,不可見控制碼 (0~31) 留白。
  4. 設定背景透明 (MIDP 2.0 支援 PNG 透明)。
  5. 匯出 PNG-8,檔名如 font.png 放入 /res/。

二、CustomFont 核心類設計

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

三、在 Canvas 中使用

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,避免重複載入。
  • 裁剪透明像素:製作圖集時裁掉全透明列/行,縮小圖集尺寸。
  • 避免頻繁 new String:遊戲迴圈中改用 char[] 或 StringBuilder 組裝後再繪製。

結語

自訂位圖字體讓 MIDP 應用擁有「像素級掌控力」:無論裝置廠商如何實作內建字體,你的遊戲 UI、終端機模擬器、聊天氣泡都能保持一致外觀。核心只需一張 PNG + 輕量 CustomFont 類,即可在 100KB JAR 額度內實現專業級文字渲染。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved