使用 Type1 字体进行文本渲染 | Java
Contents
[
Hide
Show
]渲染文字
为了渲染文本,渲染子系统需要实现 Aspose.Font.Rendering.IGlyphOutlinePainter 接口才能绘制字形。这可以通过以下步骤来实现。
- 创建
DrawText()方法,将指定的文本绘制到 System.Drawing.Bitmap 对象中并将生成的位图保存到磁盘上。这将包括以下步骤:
- 迭代文本字符串中的所有符号。
- 获取每个处理过的符号的字形标识符 - GID。
- 创建类型为 GlyphOutlinePainter 的对象,这是渲染子系统绘制当前字形所需的。
- 创建类型为 Aspose.Font.Renderers.GlyphOutlineRenderer 的对象,并将刚刚创建的类型为 GlyphOutlinePainter 的对象传递给 GlyphOutlineRenderer 的构造函数。此 GlyphOutlineRenderer 对象旨在渲染指定的字形。
- 使用 GlyphOutlineRenderer.RenderGlyph() 方法渲染当前处理的字形。 Aspose.Fonts.Matrix 对象用于指定字形坐标。要渲染的字形通过 GID 参数指定。
此策略的辅助步骤
- 此代码段的 “Y” 轴字形坐标是恒定的。
- 为每个处理过的字形计算 “X” 轴的字形坐标。
- “X” 和 “Y” 坐标都传递到 Aspose.Fonts.Matrix 对象中,GlyphOutlineRenderer 使用该对象来绘制字形。
- 在每个迭代步骤中计算刚处理的字形与前一个字形之间的距离。此距离会影响每个字形的 “X” 坐标。
- 类型为 GlyphOutlinePainter 的对象在 GlyphOutlinePainter 的帮助下不是直接绘制到位图中,而是绘制到传递给 GlyphOutlinePainter 构造函数的 GraphicsPath 对象中,因此我们使用类型为 System.Drawing.Graphics 的对象将 GraphicsPath 绘制到位图中。
- FontWidthToImageWith() 方法计算位图坐标系的字形宽度。
实现如下所示。
1private static final class Type1GlyphOutlinePainter implements IGlyphOutlinePainter {
2 private final GeneralPath path;
3
4 private Type1GlyphOutlinePainter(GeneralPath path) {
5 this.path = path;
6 }
7
8 @Override
9 public void moveTo(MoveTo moveTo) {
10 path.moveTo(moveTo.getX(), moveTo.getY());
11 }
12
13 @Override
14 public void lineTo(LineTo lineTo) {
15 path.lineTo(lineTo.getX(), lineTo.getY());
16 }
17
18 @Override
19 public void curveTo(CurveTo curveTo) {
20 path.curveTo(curveTo.getX1(), curveTo.getY1(), curveTo.getX2(), curveTo.getY2(),
21 curveTo.getX3(), curveTo.getY3());
22 }
23
24 @Override
25 public void closePath() {
26 path.closePath();
27 }
28} 1private static void drawText(String text, IFont font, double fontSize,
2 Paint backgroundBrush, Paint textBrush, String outputFile) throws IOException {
3 GlyphId[] glyphIds = new GlyphId[text.length()];
4 for (int i = 0; i < text.length(); i++) {
5 glyphIds[i] = font.getEncoding().decodeToGid(text.charAt(i));
6 }
7 double dpi = 300;
8 double resolutionCorrection = dpi / 72;
9 BufferedImage outputBitmap = new BufferedImage(960, 720, BufferedImage.TYPE_INT_RGB);
10 Graphics2D graphics = outputBitmap.createGraphics();
11 try {
12 graphics.setPaint(backgroundBrush);
13 graphics.fillRect(0, 0, outputBitmap.getWidth(), outputBitmap.getHeight());
14 graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
15 GlyphId previousGlyphId = null;
16 double glyphXCoordinate = 0;
17 double glyphYCoordinate = fontSize * resolutionCorrection;
18 for (GlyphId glyphId : glyphIds) {
19 if (glyphId == null) {
20 continue;
21 }
22 Glyph glyph = font.getGlyphAccessor().getGlyphById(glyphId);
23 if (glyph == null) {
24 continue;
25 }
26 if (previousGlyphId != null) {
27 double kerning = font.getMetrics().getKerningValue(previousGlyphId, glyphId)
28 / glyph.getSourceResolution() * fontSize * resolutionCorrection;
29 double advance = fontWidthToImageWidth(font.getMetrics().getGlyphWidth(previousGlyphId),
30 glyph.getSourceResolution(), fontSize, dpi);
31 glyphXCoordinate += kerning + advance;
32 }
33 GeneralPath path = new GeneralPath();
34 IGlyphRenderer renderer = new GlyphOutlineRenderer(new Type1GlyphOutlinePainter(path));
35 TransformationMatrix matrix = new TransformationMatrix(new double[] {
36 fontSize * resolutionCorrection, 0, 0, -fontSize * resolutionCorrection,
37 glyphXCoordinate, glyphYCoordinate
38 });
39 renderer.renderGlyph(font, glyphId, matrix);
40 path.setWindingRule(GeneralPath.WIND_NON_ZERO);
41 graphics.setPaint(textBrush);
42 graphics.fill(path);
43 previousGlyphId = glyphId;
44 }
45 } finally {
46 graphics.dispose();
47 }
48 if (!ImageIO.write(outputBitmap, "png", new File(outputFile))) {
49 throw new IOException("No PNG writer is available.");
50 }
51}- 创建实用程序方法以计算字体宽度至图像宽度,如下所示:
1private static double fontWidthToImageWidth(double width, int fontSourceResolution,
2 double fontSize, double dpi) {
3 return width / fontSourceResolution * fontSize * (dpi / 72);
4}调用渲染文本功能
要使用上述实现,可以从基于控制台应用程序的 Main 方法执行以下示例代码。
1String fileName = Paths.get(getDataDir(), "..", "Type1", "courier.pfb").normalize().toString();
2FontDefinition fd = new FontDefinition(FontType.Type1,
3 new FontFileDefinition("pfb", new FileSystemStreamSource(fileName)));
4Type1Font font = (Type1Font) Font.open(fd);
5
6String firstOutput = Paths.get(getOutputDir(), "hello1_type1_out.png").toString();
7String secondOutput = Paths.get(getOutputDir(), "hello2_type1_out.png").toString();
8drawText("Hello world", font, 14, Color.WHITE, Color.BLACK, firstOutput);
9drawText("Hello world", font, 14, Color.YELLOW, Color.RED, secondOutput);