如何使用PDFBox绘制彩色表情符号?
用PDFBox绘制彩色表情符号的解决方案
你当前的代码通过showText绘制表情符号时,只会渲染字形的单色轮廓——因为PDFBox默认文本绘制不处理字体中的COLR/CPAL彩色表(seguiemj.ttf属于这类彩色字体)。要实现彩色效果,有两种可行方案:
方案一:利用PDFBox的彩色字体渲染支持(需2.0.27+版本)
PDFBox从2.0.27版本开始支持带有COLR/CPAL表的彩色字体,需要启用彩色渲染选项并使用showGlyphs方法替代showText。
修改后的代码示例:
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.font.PDType0Font; import org.apache.pdfbox.pdmodel.font.PDVectorFont; import java.io.File; import java.io.IOException; import java.util.List; public class ColoredEmojiPDF { public static void main(String[] args) throws IOException { try (PDDocument doc = new PDDocument()) { PDPage page = new PDPage(); doc.addPage(page); // 加载Segoe UI Emoji字体 PDType0Font emojiFont = PDType0Font.load(doc, new File("C:/Windows/Fonts/seguiemj.ttf")); // 验证字体是否支持COLR彩色表 if (!(emojiFont.getDescendantFont() instanceof PDVectorFont vectorFont) || !vectorFont.hasCOLRTable()) { System.err.println("该字体不支持彩色COLR表"); return; } try (PDPageContentStream cs = new PDPageContentStream(doc, page)) { float fontSize = 24; float x = 100; float y = 700; cs.beginText(); cs.setFont(emojiFont, fontSize); cs.newLineAtOffset(x, y); // 将表情文本转换为字形ID列表 String emojiText = "🎯💡📢✅"; List<Integer> glyphIds = emojiFont.encode(emojiText); // 启用彩色渲染绘制字形 cs.showGlyphs(glyphIds, emojiFont, fontSize, true); cs.endText(); } doc.save("colored_emoji.pdf"); } } }
注意事项:
- 必须使用PDFBox 2.0.27或更高版本,旧版本无此功能
- 确保字体路径正确,非Windows系统可替换为对应彩色Emoji字体(如Noto Color Emoji)
方案二:将Emoji渲染为图像后插入PDF
如果无法升级PDFBox版本,可通过Java AWT将Emoji渲染为图像,再插入PDF文档:
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; public class EmojiImagePDF { public static void main(String[] args) throws IOException { try (PDDocument doc = new PDDocument()) { PDPage page = new PDPage(); doc.addPage(page); String emojiText = "🎯💡📢✅"; float fontSize = 24; float startX = 100; float startY = 700; float spacing = 30; // 表情间的间距 // 加载系统彩色Emoji字体 Font emojiFont = new Font("Segoe UI Emoji", Font.PLAIN, (int) fontSize); try (PDPageContentStream cs = new PDPageContentStream(doc, page)) { float currentX = startX; for (char c : emojiText.toCharArray()) { // 创建图像并绘制单个Emoji BufferedImage image = new BufferedImage((int) fontSize, (int) fontSize, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = image.createGraphics(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setFont(emojiFont); g2d.drawString(String.valueOf(c), 0, fontSize - 2); // 调整基线位置保证显示完整 g2d.dispose(); // 将图像插入PDF PDImageXObject pdImage = PDImageXObject.createFromByteArray(doc, imageToBytes(image), "emoji"); cs.drawImage(pdImage, currentX, startY - fontSize, fontSize, fontSize); currentX += spacing; } } doc.save("colored_emoji_image.pdf"); } } // 将BufferedImage转为字节数组 private static byte[] imageToBytes(BufferedImage image) throws IOException { java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(); javax.imageio.ImageIO.write(image, "PNG", baos); return baos.toByteArray(); } }
这种方法依赖系统的字体渲染能力,生成的是图像格式的Emoji,无需依赖PDFBox的高版本特性。
内容的提问来源于stack exchange,提问作者bai yuan
相关产品推荐
相关产品推荐

