为了使 CustomFont 易于学习和使用,应尽可能地使其具有像标准 MIDP Font 类一样的外观和风格。由于为了使实现者可使用原生代码进行优化,Font 已经被声明为 final,因此不能为其定义子类,但我们能够模拟其公共界面。Font 的每个方法在 CustomFont 中也有,并且只有静态工厂方法 getFont() 具有不同的签名,它采用文件名字来替代惯用的字体类型:
public static CustomFont getFont(
String inName, int inStyle, int inSize );
|
在许多 MIDP 应用程序中,通常通过调用 setFont() 方法来将一种字体传递到 Graphics 对象,然后调用该对象的 drawChars() 和 drawString() 方法来呈现文本。但这里我们不能采用同样的模式。因为 CustomFont 不是 Font 的子类,我们不能将其传递到 Graphics.setFont() 。相反,CustomFont 提供了公共的方法来绘制字符,这些方法模拟 Graphics 类的方法,每一种都用 Graphics 实例作为其第一个参数。
public void drawChar(
Graphics g, char character,
int x, int y, int anchor );
public void drawChars(
Graphics g, char[] data,
int offset, int length,
int x, int y, int anchor );
public void drawString(
Graphics g, String str,
int x, int y, int anchor );
public void drawSubstring(
Graphics g, String str,
int offset, int length,
int x, int y, int anchor );
|
使用 CustomFont 的应用程序需要修改其绘制代码来调用自定义字体类的这些方法,而不是 Graphics 对象的相应方法。
现在让我们看一下字符位图怎样进入屏幕。可考虑两种方法。
显而易见的方法是把源图像分解成为 128 个的图像,一个图像对应一个字符,如下所示:
...
images = new Image[ 128 ];
for ( int i = 0; i < 128; i++ )
{
images[i] = Image.createImage(
image, i*width, 0, width, height, 0 );
}
...
|
从外部资源创建的图像认为是不可变的。因为像素不能改变,运行库能够优化内存分配。使用 createImage() 方法从不可改变的图像创建的图像,也不能够改变。因此,当有 128 个小图像和一个大图像时,可以期望运行库足够职能,能够注意到二者都是不可修改的,并且在内存中只保存位图的一份拷贝。即使这样做,128 个图像实例的纯系统开销也是一个小型设备难于应付的。
另一种方法是只用一个大图像并像 IBM Selectric 打字机的连动球(typeball) 一样使用。作为当时的革新,连动球(typeball)用球面上排列的提升起来的字符取代了用于每个字符的单个连动杆(typebar)。连动球根据每一次按键转动且倾斜,使 Selectric 达到令人惊叹的速度(每秒钟几乎15个字母)。连动球可能早已废弃不用,但我们可以借用它的设计思想来使 MIDTerm 更具有高效率。为了绘制字符,点住图像区域,左右移动图像以便使所需的字符出现在剪辑区内,然后绘制图像。每一个 Graphics 实例始终保持一个剪辑区,并且只有影响剪辑区的命令才真正执行。在这个例子中,可以借助运行库来仅绘制适合于剪辑区的像素。方法如下:
public void drawChar(
Graphics g, char character, int x, int y, int anchor )
{
int clipX = g.getClipX();
int clipY = g.getClipY();
int clipW = g.getClipWidth();
int clipH = g.getClipHeight();
g.setClip( x, y, width, height );
g.drawImage(
image, x - width*character, y, anchor );
g.setClip( clipX, clipY, clipW, clipH );
}
|