private CFFFont parseFont()

in fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java [550:713]


    private CFFFont parseFont(DataInput input, String name, byte[] topDictIndex) throws IOException
    {
        // top dict
        DataInputByteArray topDictInput = new DataInputByteArray(topDictIndex);
        DictData topDict = readDictData(topDictInput);

        // we don't support synthetic fonts
        DictData.Entry syntheticBaseEntry = topDict.getEntry("SyntheticBase");
        if (syntheticBaseEntry != null)
        {
            throw new IOException("Synthetic Fonts are not supported");
        }

        // determine if this is a Type 1-equivalent font or a CIDFont
        CFFFont font;
        CFFCIDFont cffCIDFont = parseROS(topDict);
        // determine if this is a Type 1-equivalent font or a CIDFont
        boolean isCIDFont = cffCIDFont != null;
        if (cffCIDFont != null)
        {
            font = cffCIDFont;
        }
        else
        {
            font = new CFFType1Font();
        }

        // name
        debugFontName = name;
        font.setName(name);

        // top dict
        font.addValueToTopDict("version", getString(topDict, "version"));
        font.addValueToTopDict("Notice", getString(topDict, "Notice"));
        font.addValueToTopDict("Copyright", getString(topDict, "Copyright"));
        font.addValueToTopDict("FullName", getString(topDict, "FullName"));
        font.addValueToTopDict("FamilyName", getString(topDict, "FamilyName"));
        font.addValueToTopDict("Weight", getString(topDict, "Weight"));
        font.addValueToTopDict("isFixedPitch", topDict.getBoolean("isFixedPitch", false));
        font.addValueToTopDict("ItalicAngle", topDict.getNumber("ItalicAngle", 0));
        font.addValueToTopDict("UnderlinePosition", topDict.getNumber("UnderlinePosition", -100));
        font.addValueToTopDict("UnderlineThickness", topDict.getNumber("UnderlineThickness", 50));
        font.addValueToTopDict("PaintType", topDict.getNumber("PaintType", 0));
        font.addValueToTopDict("CharstringType", topDict.getNumber("CharstringType", 2));
        font.addValueToTopDict("FontMatrix", topDict.getArray("FontMatrix", List.of(
                                                      0.001, 0.0, 0.0, 0.001,
                                                      0.0, 0.0)));
        font.addValueToTopDict("UniqueID", topDict.getNumber("UniqueID", null));
        font.addValueToTopDict("FontBBox", topDict.getArray("FontBBox",
                                                    List.of(0, 0, 0, 0)));
        font.addValueToTopDict("StrokeWidth", topDict.getNumber("StrokeWidth", 0));
        font.addValueToTopDict("XUID", topDict.getArray("XUID", null));

        // charstrings index
        DictData.Entry charStringsEntry = topDict.getEntry("CharStrings");
        if (charStringsEntry == null || !charStringsEntry.hasOperands())
        {
            throw new IOException("CharStrings is missing or empty");
        }
        int charStringsOffset = charStringsEntry.getNumber(0).intValue();
        input.setPosition(charStringsOffset);
        byte[][] charStringsIndex = readIndexData(input);
        
        // charset
        DictData.Entry charsetEntry = topDict.getEntry("charset");
        CFFCharset charset;
        if (charsetEntry != null && charsetEntry.hasOperands())
        {
            int charsetId = charsetEntry.getNumber(0).intValue();
            if (!isCIDFont && charsetId == 0)
            {
                charset = CFFISOAdobeCharset.getInstance();
            }
            else if (!isCIDFont && charsetId == 1)
            {
                charset = CFFExpertCharset.getInstance();
            }
            else if (!isCIDFont && charsetId == 2)
            {
                charset = CFFExpertSubsetCharset.getInstance();
            }
            else if (charStringsIndex.length > 0)
            {
                input.setPosition(charsetId);
                charset = readCharset(input, charStringsIndex.length, isCIDFont);
            }
            // that should not happen
            else
            {
                LOG.debug("Couldn't read CharStrings index - returning empty charset instead");
                charset = new EmptyCharsetType1();
            }            
        }
        else
        {
            if (isCIDFont)
            {
                // a CID font with no charset does not default to any predefined charset
                charset = new EmptyCharsetCID(charStringsIndex.length);
            }
            else
            {
                charset = CFFISOAdobeCharset.getInstance();
            }
        }
        font.setCharset(charset);

        // charstrings dict
        font.charStrings = charStringsIndex;

        // format-specific dictionaries
        if (isCIDFont)
        {

            // CharStrings index could be null if the index data couldn't be read
            int numEntries = 0;
            if (charStringsIndex.length == 0)
            {
                LOG.debug("Couldn't read CharStrings index - parsing CIDFontDicts with number of char strings set to 0");
            }
            else
            {
                numEntries = charStringsIndex.length;
            }

            parseCIDFontDicts(input, topDict, (CFFCIDFont) font, numEntries);

            List<Map<String, Object>> fontDicts = ((CFFCIDFont) font).getFontDicts();
            List<Number> privMatrix = null;
            if (!fontDicts.isEmpty())
            {
                privMatrix = (List<Number>) fontDicts.get(0).getOrDefault("FontMatrix", null);
            }
            // some malformed fonts have FontMatrix in their Font DICT, seePDFBOX-2495
            List<Number> matrix = topDict.getArray("FontMatrix", null);
            if (matrix == null)
            {
                if (privMatrix != null)
                {
                    font.addValueToTopDict("FontMatrix", privMatrix);
                }
                else
                {
                    // default
                    font.addValueToTopDict("FontMatrix", topDict.getArray("FontMatrix",
                            List.of(0.001, 0.0, 0.0, 0.001, 0.0, 0.0)));
                }
            }
            else if (privMatrix != null)
            {
                // we have to multiply the font matrix from the top directory with the font matrix
                // from the private directory. This should be done for synthetic fonts only but in
                // case of PDFBOX-3579 it's needed as well to get the right scaling
                concatenateMatrix(matrix, privMatrix);
            }

        }
        else
        {
            parseType1Dicts(input, topDict, (CFFType1Font) font, charset);
        }

        return font;
    }