MIDP终端模拟之三:MIDP 的自定义字体[3]

[入库:2006年2月23日] [更新:2007年3月24日]

本文简介:


这种方法的不利之处在于不得不在改变剪辑区前记住现存的剪辑区,以使能够返回到  Graphics 创建时的状态。每一次调用绘制方法之前都要存储剪辑区,显著的代价是:每次必须进行 4 次调用并分配 4 个 int。

我们陷入常见的时间-空间的权衡问题中:为节省内存,CustomFont 占用了更多的处理器时间,使用剪辑来取代对每一个字符分配单个图像实例。在内存小的设备上,运行慢总不根本不能运行要强得多。

初始化时,有一项小任务 CustomFont 必须完成,这就是计算字体的基线。在字体渲染中,与字体的高度和宽度一样,字体的基线也是另一个重要的决定因素,因为它定义了一个字体的字符位于一个文本行的哪个位置。如果一个文本行有不同的字体,需要将其基线对齐,以使其出现在同一个水平线上。

我们可以改变 CustomFont.getFont() 来要求调用者指定所选字体的基线,但有一种更好的方法。MIDP 2.0 使我们能够动态检测基线。getRGB() 方法使我们可直接访问一个图像的单个像素,并且一个简单的探试就能确定哪行像素就是基线。

...
// determine background color: assume it's at 0, 0
image.getRGB( row, 0, 1, 0, 0, 1, 1 );
background = row[0];

// here's the heuristic: find the row on the bottom
// half of the image with the most non-background pixels
for ( int y = height/2; y < height; y++ )
{
    total = 0;
    image.getRGB( row, 0, imageWidth, 0, y, imageWidth, 1 );
    for ( int x = 0; x < imageWidth; x++ )
    {
        if ( row[x] != background ) total++;
    }
    if ( total > max ) 
    {
        max = total;
        result = y;
    }
}
...

CustomFont 假定图像中左上角像素为背景颜色。CustomFont 计算图像的下半部分中的每一行的非背景像素,并且判断具有最多前景像素的那一行作为基线。在运行时确定基线,使您在创建自定义字体位图时无需为此事担忧。

动态样式设置

Font.getFont() and CustomFont.getFont() 的签名的第一个参数有所不同:标准的方法采用字体类型,而这里的方法采用的是图像文件的名称;但是二者都接受大小和样式参数。CustomFont 忽略了所要求的字体大小,因为如果对每一个字体大小都在内存中提供一个独立的图像的话,代价太高,并且如果试图在运行时缩放位图,就可能造成最终结果难以辨识。但是,自定义字体类确实试图尊重所要求的样式,途径是采用了一些简单而高效的技术,这些技术改变了它在运行时绘制字符图像的方式。

最简单的是下划线。就是在基线下两个像素的位置,在字符下画一条线。

...
if ( ( style & Font.STYLE_UNDERLINED ) != 0 )
{
    g.drawLine( 
        x, y + baseline + 2, x + width, y + baseline + 2 );
}
...

+加粗只是稍微复杂了一点。为了加粗字符,CustomFont 多绘制了一次字符,在右侧加一列像素。因为背景是透明的,因此两行像素重叠使字符加黑。

...
if ( ( style & Font.STYLE_BOLD ) != 0 )
{
    // draw an additional time, one pixel to the right
    g.drawImage( 
        image, x - width*character + 1, y, anchor );
} 
...

做斜体字时,CustomFont 使用剪辑来将字符的上半部分绘制得向右移动一个像素。效果出人意料地好。

...
if ( ( style & Font.STYLE_ITALIC ) != 0 )
{
    g.setClip( x + 1, y, width, height/2 );
    g.drawImage( 
        image, x - width*character + 1, y, anchor );
    g.setClip( x, y+height/2, width, height/2 );
    g.drawImage( 
        image, x - width*character, y, anchor );
}
...

下面是实际中的样式:

STYLE_PLAIN
STYLE_UNDERLINED
STYLE_BOLD
STYLE_ITALIC

在绘制特定颜色的字符时会稍难一些。当 Graphics 用当前颜色渲染字体时,CustomFont 只能把像素拷贝到整个的字体图像中,因此字符以原始图像的采用的非透明的颜色出现。

MIDP 2.0 提供了一种从 getRGB() 返回的像素创建新图像的方法。您可以复制一个字符的像素,扫描并修改每一个非背景像素的颜色,建立新的图像,并将该图像绘制屏幕上;但这种方法要占用大量的处理器资源而明显地很慢。如果事先知道需要哪种颜色,在创建字体时可以在前景中使用该颜色。MIDTerm 采用是黑色背景,因此整个字体图像含有白色字符,背景则是透明的。

使自定义的字体工作起来

因为 CustomFont 与 MIDP 的 Font 类非常接近于一致,MIDTerm 的 TelnetCanvas 类仅需要很少的改动就可以实现自定义字体的优势。

Using MIDP FontsUsing Custom Font
font = Font.getFont( 
    Font.FACE_MONOSPACE, 
    Font.STYLE_SMALL, 
    Font.SIZE_PLAIN );
font = CustomFont.getFont( 
    "/mono.png", // the font bitmap file
    Font.SIZE_SMALL, // ignored
    Font.STYLE_PLAIN ); // no styling
g.setFont( font );
g.drawChar( (char) b, 
    insetX + x*fontWidth, 
    insetY + y*fontHeight, 
    g.TOP | g.LEFT );
 
font.drawChar( g, (char) b, 
    insetX + x*fontWidth, 
    insetY + y*fontHeight, 
    g.TOP | g.LEFT );

本文关键:MIDP终端模拟之三:MIDP 的自定义字体
  相关方案
Google
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top