[ https://issues.apache.org/jira/browse/PDFBOX-1296?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13675800#comment-13675800 ]
Tilman Hausherr commented on PDFBOX-1296: ----------------------------------------- Sigh... Its now a year later and nothing has happened. Anyway, here's an updated the fix for the current trunk, which I checked out with svn yesterday. The changes are in canDisplayUpTo() and in the parts with //TH in drawString(). /** * * Font.canDisplayUpTo() is buggy: * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6623219 * http://stackoverflow.com/questions/1754697/displaying-chinese-text-in-an-applet * * @param font * @param s * @return -1 when all is good * * This method returns an offset into the String s which is the first * character this Font cannot display without using the missing glyph code. * If the Font can display all characters, -1 is returned. */ int canDisplayUpTo(Font font, String s) { if (!font.canDisplay(' ') || !font.canDisplay('a') || !font.canDisplay('A')) { return 0; //TH font.canDisplay does not always tell the truth } int len = s.length(); int index = 0; while (index < len) { int codePoint = s.codePointAt(index); if (!font.canDisplay(codePoint)) { return index; } index += Character.charCount(codePoint); } return -1; } /** * {@inheritDoc} */ public void drawString(String string, int[] codePoints, Graphics g, float fontSize, AffineTransform at, float x, float y) throws IOException { Font awtFont = getawtFont(); FontRenderContext frc = new FontRenderContext(new AffineTransform(), true, true); GlyphVector glyphs = null; boolean useCodepoints = codePoints != null && isType0Font(); PDFont descendantFont = useCodepoints ? ((PDType0Font) this).getDescendantFont() : null; // symbolic fonts may trigger the same fontmanager.so/dll error as described below if (useCodepoints && !descendantFont.getFontDescriptor().isSymbolic()) { PDCIDFontType2Font cid2Font = null; if (descendantFont instanceof PDCIDFontType2Font) { cid2Font = (PDCIDFontType2Font) descendantFont; } if ((cid2Font != null && cid2Font.hasCIDToGIDMap()) || isFontSubstituted) { // we still have to use the string if a CIDToGIDMap is used glyphs = awtFont.createGlyphVector(frc, string); } else { glyphs = awtFont.createGlyphVector(frc, codePoints); } } else { // mdavis - fix fontmanager.so/dll on sun.font.FileFont.getGlyphImage // for font with bad cmaps? // Type1 fonts are not affected as they don't have cmaps //TH /* if (!isType1Font() && awtFont.canDisplayUpTo(string) != -1) { LOG.warn("Changing font on <" + string + "> from <" + awtFont.getName() + "> to the default font"); awtFont = Font.decode(null).deriveFont(1f); } */ //TH if (!isType1Font() && canDisplayUpTo(awtFont, string) != -1) { Font awtFontOld = awtFont; String name = null; String style; String defText = ""; if (awtFont.getName().indexOf('+') > 0) { name = awtFont.getName().substring(awtFont.getName().indexOf('+') + 1); } else if (awtFont.getName().startsWith("DejaVu") || awtFont.getName().startsWith("Liberation")) { if (awtFont.getName().startsWith("DejaVu Sans")) { name = "Lucida Sans"; } else if (awtFont.getName().startsWith("Liberation Serif")) { name = "Times New Roman"; } else if (awtFont.getName().startsWith("Liberation Sans")) { name = "Arial"; } else if (awtFont.getName().startsWith("Liberation Mono")) { name = "Courier New"; } else { name = "Lucida Sans"; } } if (name == null) { awtFont = Font.decode(null).deriveFont(1f); defText = " (default font)"; } else { switch (awtFont.getStyle()) { case Font.BOLD: style = "BOLD"; break; case Font.ITALIC: style = "ITALIC"; break; case Font.PLAIN: style = "PLAIN"; break; default: if (awtFont.getStyle() == (Font.BOLD | Font.ITALIC)) { style = "BOLDITALIC"; } else { style = "PLAIN"; } } if (awtFont.getName().endsWith("Bold")) { style = "BOLD"; } else if (awtFont.getName().endsWith("Bold Italic")) { style = "BOLDITALIC"; } else if (awtFont.getName().endsWith("Italic")) { style = "ITALIC"; } awtFont = Font.decode(name + "-" + style + "-" + Integer.toString(awtFont.getSize())); } LOG.warn("Changing font on <" + string + "> from <" + awtFontOld + "> to <" + awtFont + ">" + defText); } glyphs = awtFont.createGlyphVector(frc, string); if (isType1Font()) { glyphs = remapGlyphs(glyphs, string); } } Graphics2D g2d = (Graphics2D) g; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); writeFont(g2d, at, x, y, glyphs); } However the real problem is deeper. One of my test files (confidential, thus not attached) is PDF/A, the font is included in the PDF itself, so my fallfack solution shouldn't be used at all. > Warnung: Changing font on < > from <AMAKEA+TimesNewRoman> to the default font > ----------------------------------------------------------------------------- > > Key: PDFBOX-1296 > URL: https://issues.apache.org/jira/browse/PDFBOX-1296 > Project: PDFBox > Issue Type: Bug > Components: PDModel > Affects Versions: 1.6.0 > Environment: XP, JDK 1.7 > Reporter: Tilman Hausherr > Attachments: outside-in-01.png, outside-in.pdf, shortcuts-01.png, > shortcuts.pdf > > > Pdfbox does not produce the correct fonts in the PNG file created with the > following code and I get a lot of warnings: > PDDocument document = null; > try > { > document = PDDocument.load(pdfFile); > List pages = document.getDocumentCatalog().getAllPages(); > int p = 0; > for (Object pobj : pages) > { > PDPage page = (PDPage) pobj; > ++p; > BufferedImage bim = page.convertToImage(); > // Test with output in memory, to see the size > ByteArrayOutputStream memout = new > ByteArrayOutputStream(); > boolean memoutok = ImageIO.write(bim, "png", memout); > if (!memoutok) > System.err.println ("mem write failed for " + p); > memout.reset(); > memout.close(); > // Test with output to png file > String fname = String.format("%s-%02d.png", prefix, p); > boolean foutok = ImageIO.write(bim, "png", new > File(fname)); > if (!foutok) > System.err.println ("file write failed for " + p); > .... > Apr 26, 2012 2:41:11 PM org.apache.pdfbox.util.PDFStreamEngine processOperator > Information: unsupported/disabled operation: i > Apr 26, 2012 2:41:12 PM org.apache.pdfbox.util.PDFStreamEngine processOperator > Information: unsupported/disabled operation: ri > Apr 26, 2012 2:41:12 PM org.apache.pdfbox.pdmodel.font.PDSimpleFont drawString > Warnung: Changing font on < > from <AMAKEA+TimesNewRoman> to the default font > Apr 26, 2012 2:41:13 PM org.apache.pdfbox.pdmodel.font.PDSimpleFont drawString > Warnung: Changing font on < > from <AMAKEA+TimesNewRoman> to the default font > Apr 26, 2012 2:41:13 PM org.apache.pdfbox.pdmodel.font.PDSimpleFont drawString > Warnung: Changing font on <O> from <AMAKME+Arial,Bold> to the default font > Apr 26, 2012 2:41:13 PM org.apache.pdfbox.pdmodel.font.PDSimpleFont drawString -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira