[ 
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

Reply via email to