使用 Apache POI HSLFSlide.draw 时默认的日语字体是什么? [英] What is the default Japanese font when using Apache POI HSLFSlide.draw?
问题描述
我正在使用 Apache POI 将 pptx 幻灯片转换为图像.在 pptx 幻灯片中,我的系统中没有使用 GE Inspira 字体的日语文本(注释掉 ge.registerFont(font) 以模拟它).生成的图像以默认字体(参见此处的图像)显示日语文本.那是什么字体,这个默认字体集在哪里?
I am using Apache POI to convert pptx slide to image. In the pptx slide, I have Japanese text in GE Inspira font that is not available in my system (comment out ge.registerFont(font) to simulate that). The generated image shows the Japanese text in a default font (see image here). What font is that and where is this default font set?
当我注册字体时,日语文本显示为框(请参阅此处的图片)一>.这是因为 GE Inspira 字体不支持日文字符.有没有办法强制 POI 使用日语文本的默认字体?
When I register the font, the Japanese text appears as boxes (see image here). This is because GE Inspira font does not support Japanese characters. Is there a way to force POI to use the default font for Japanese text?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFTextBox;
import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
import org.apache.poi.xslf.usermodel.XSLFTextRun;
public class UnicodePPT {
public static void main(String[] args) throws Exception {
// create a sample pptx
XMLSlideShow ss = new XMLSlideShow();
Dimension pgsize = ss.getPageSize();
XSLFSlide slide = ss.createSlide();
XSLFTextBox tb = slide.createTextBox();
// tb.setShapeType(XSLFShapeType.HEART);
int shapeSize = 150;
tb.setAnchor(new Rectangle((int)(pgsize.getWidth() / 2 - shapeSize / 2), (int)(pgsize.getHeight()
/ 2
- shapeSize
/ 2), shapeSize, shapeSize));
tb.setLineWidth(2);
tb.setLineColor(Color.BLACK);
XSLFTextParagraph par = tb.addNewTextParagraph();
tb.setVerticalAlignment(VerticalAlignment.DISTRIBUTED);
par.setTextAlign(TextAlign.CENTER);
XSLFTextRun run = par.addNewTextRun();
run.setText("ゴミ箱");
run.setFontFamily("GE Inspira");
run.setFontSize(12.0);
// set the font
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
InputStream is = new FileInputStream("src/test/resources/GEInspRg.TTF");
Font font = Font.createFont(Font.TRUETYPE_FONT, is);
is.close();
ge.registerFont(font);
// render it
double zoom = 2; // magnify it by 2
AffineTransform at = new AffineTransform();
at.setToScale(zoom, zoom);
BufferedImage img = new BufferedImage((int)Math.ceil(pgsize.width * zoom),
(int)Math.ceil(pgsize.height * zoom), BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = img.createGraphics();
graphics.setTransform(at);
graphics.setPaint(Color.white);
graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
slide.draw(graphics);
FileOutputStream fos = new FileOutputStream("src/test/resources/unicodeppt.png");
javax.imageio.ImageIO.write(img, "png", fos);
fos.close();
}
}
推荐答案
正如评论中提到的,Inspira GE 字体不是 unicode 字体,因此需要回退.如果没有指定特定的后备字体,字体.将使用 SANS_SERIF.对于像 SANS_SERIF 这样的逻辑字体,有 java 内部 fallback 配置.不幸的是,自动添加的 Lucida 字体不支持中文(简体)、中文(繁体)、日语和韩语.
As mentioned in the comments, the Inspira GE font is not an unicode font, therefore a fallback is needed. If no specific fallback font is specified, Font.SANS_SERIF will be used. For the logical fonts like SANS_SERIF there is java internal fallback configuration. Unfortunately the automatically added Lucida fonts do not support Chinese (Simplified), Chinese (Traditional), Japanese, and Korean.
所以你应该提供一个 unicode 字体,例如Mona、Map
的形式,其中 key
是原始字体系列,value
是替换字体.您还可以指定 "*"
作为键,以捕获所有字体.除了 FONT_FALLBACK
之外,还有一个 FONT_MAP
提示来映射所有的出现,即不仅是丢失的字形.
So you should provide a unicode font, e.g. Mona, Code2000 and Arial Unicode MS are a good picks - wikipedia has also good collection.
The mapping is provided as POI-specific rendering hint in the form of Map<String,String>
, where the key
is original font family and value
the substitution font. You can also specify "*"
as a key, to catch-all fonts. Beside the FONT_FALLBACK
, there's also a FONT_MAP
hint to map all the occurrences, i.e. not only the missing glyphs.
这将在 POI 3.16-beta2(预计到 2017 年 2 月)中可用,或者您暂时使用 trunk - 另一种选择是提供您自己的 DrawTextParagraph 通过自定义DrawFactory
This will be available in POI 3.16-beta2 (ETA February 2017) or you temporarily use the trunk - another option is to provide your own DrawTextParagraph via a customized DrawFactory
要了解您的字体是否能够呈现您的字符/glpyhs,您需要在 Windows 字符映射工具 或其他一些字体工具,例如 FontForge 并检查 unicode block 中是否有字形.
To find out, if your font is capable of rendering your chars/glpyhs, you need to open it in the Windows character map tool or some other font tool like FontForge and check if there's a glyph at the unicode block.
@Test
public void unicodeRendering() throws Exception {
// create a sample pptx
XMLSlideShow ss = createSamplePPT();
Dimension pgsize = ss.getPageSize();
// set the font
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
for (String s : new String[]{"GEInspRg.ttf","mona.ttf"}) {
Font font = Font.createFont(Font.TRUETYPE_FONT, new File(s));
ge.registerFont(font);
}
Map<String,String> fallbackMap = new HashMap<String,String>();
fallbackMap.put("GE Inspira", "Mona");
// render it
double zoom = 2; // magnify it by 2
AffineTransform at = new AffineTransform();
at.setToScale(zoom, zoom);
BufferedImage img = new BufferedImage((int)Math.ceil(pgsize.width * zoom),
(int)Math.ceil(pgsize.height * zoom), BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = img.createGraphics();
graphics.setRenderingHint(Drawable.FONT_FALLBACK, fallbackMap);
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
graphics.setTransform(at);
graphics.setPaint(Color.white);
graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
ss.getSlides().get(0).draw(graphics);
javax.imageio.ImageIO.write(img, "png", new File("unicodeppt.png"));
ss.close();
}
private XMLSlideShow createSamplePPT() {
XMLSlideShow ss = new XMLSlideShow();
Dimension pgsize = ss.getPageSize();
XSLFSlide slide = ss.createSlide();
XSLFTextBox tb = slide.createTextBox();
// tb.setShapeType(XSLFShapeType.HEART);
int shapeSize = 150;
tb.setAnchor(new Rectangle((int)(pgsize.getWidth() / 2 - shapeSize / 2),
(int)(pgsize.getHeight() / 2 - shapeSize / 2), shapeSize, shapeSize));
tb.setLineWidth(2);
tb.setLineColor(Color.BLACK);
XSLFTextParagraph par = tb.addNewTextParagraph();
tb.setVerticalAlignment(VerticalAlignment.DISTRIBUTED);
par.setTextAlign(TextAlign.CENTER);
XSLFTextRun run = par.addNewTextRun();
run.setText("unicode ->\u30B4\u30DF\u7BB1<-");
run.setFontFamily("GE Inspira");
run.setFontSize(12.0);
return ss;
}
这篇关于使用 Apache POI HSLFSlide.draw 时默认的日语字体是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!