All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jpedal.fonts.TrueType Maven / Gradle / Ivy

/*
 * ===========================================
 * Java Pdf Extraction Decoding Access Library
 * ===========================================
 *
 * Project Info:  http://www.idrsolutions.com
 * Help section for developers at http://www.idrsolutions.com/support/
 *
 * (C) Copyright 1997-2017 IDRsolutions and Contributors.
 *
 * This file is part of JPedal/JPDF2HTML5
 *
     This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


 *
 * ---------------
 * TrueType.java
 * ---------------
 */
package org.jpedal.fonts;

import java.awt.Rectangle;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.jpedal.exception.PdfFontException;
import org.jpedal.external.ExternalHandlers;
import org.jpedal.fonts.glyph.PdfJavaGlyphs;
import org.jpedal.fonts.objects.FontData;
import org.jpedal.fonts.tt.TTGlyphs;
import org.jpedal.io.ObjectStore;
import org.jpedal.io.PdfObjectReader;
import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.utils.LogWriter;
import org.jpedal.utils.repositories.FastByteArrayOutputStream;

/**
 * handles truetype specifics
 */
public class TrueType extends PdfFont {

    private boolean subfontAlreadyLoaded;
    private Map fontsLoaded;

    private Rectangle BBox;

    public TrueType() {
        fontsLoaded = new HashMap();

        init(null);

    }

    private void readFontData(final byte[] fontDataAsArray, final FontData fontData) {

        if (subfontAlreadyLoaded) {
            glyphs = fontsLoaded.get(substituteFont + '_' + glyphs.getBaseFontName() + ' ' + fontDataAsArray.length);

            fontTypes = glyphs.getType();
        } else {

            if ((!isCIDFont) && (fontDataAsArray != null)) {
                fontsLoaded.put(substituteFont + '_' + glyphs.getBaseFontName() + ' ' + fontDataAsArray.length, glyphs);
            }

            fontTypes = glyphs.readEmbeddedFont(TTstreamisCID, fontDataAsArray, fontData);
        }
        //does not see to be accurate on all PDFs tested
        //this.FontBBox=glyphs.getFontBoundingBox();

    }

    /**
     * allows us to substitute a font to use for display
     *
     * @throws PdfFontException
     */
    protected void substituteFontUsed(final String substituteFontFile) throws PdfFontException {

        InputStream from = null;

        //process the font data
        try {

            //try in jar first
            from = loader.getResourceAsStream("org/jpedal/res/fonts/" + substituteFontFile);

            //try as straight file
            if (from == null) {
                from = new FileInputStream(substituteFontFile);
            }

        } catch (final Exception e) {
            LogWriter.writeLog("Exception " + e + " reading " + substituteFontFile + " Check cid  jar installed");
        }

        if (from == null) {
            throw new PdfFontException("Unable to load font " + substituteFontFile);
        }

        try {

            //create streams
            final FastByteArrayOutputStream to = new FastByteArrayOutputStream();

            //write
            final byte[] buffer = new byte[65535];
            int bytes_read;
            while ((bytes_read = from.read(buffer)) != -1) {
                to.write(buffer, 0, bytes_read);
            }

            from.close();

            final FontData fontData = null; //new FontData(to.toByteArray());

            readFontData(to.toByteArray(), fontData);

            glyphs.setEncodingToUse(hasEncoding, this.getFontEncoding(false), isCIDFont);

            isFontEmbedded = true;

        } catch (final Exception e) {
            LogWriter.writeLog("Exception " + e + " reading " + substituteFontFile + " Check cid  jar installed");

            if (ExternalHandlers.throwMissingCIDError && e.getMessage() != null && e.getMessage().contains("kochi")) {
                throw new Error(e);
            }
        }

    }

    /**
     * get handles onto Reader so we can access the file
     */
    public TrueType(final PdfObjectReader current_pdf_file, final String substituteFont) {

        glyphs = new TTGlyphs();

        init(current_pdf_file);
        this.substituteFont = substituteFont;

    }

    /**
     * read in a font and its details from the pdf file
     */
    @Override
    public void createFont(final PdfObject pdfObject, final String fontID, final boolean renderPage, final ObjectStore objectStore, final Map substitutedFonts) throws Exception {

        fontTypes = StandardFonts.TRUETYPE;

        this.fontsLoaded = substitutedFonts;

        //generic setup
        init(fontID, renderPage);
        
        /*
         * get FontDescriptor object - if present contains metrics on glyphs
         */
        final PdfObject pdfFontDescriptor = pdfObject.getDictionary(PdfDictionary.FontDescriptor);

        setBoundsAndMatrix(pdfFontDescriptor);

        setName(pdfObject);
        setEncoding(pdfObject, pdfFontDescriptor);

        if (renderPage) {

            if (pdfFontDescriptor != null && substituteFont == null) {

                byte[] stream = null;
                PdfObject FontFile2 = pdfFontDescriptor.getDictionary(PdfDictionary.FontFile2);

                //allow for wrong types used (Acrobat does not care so neither do we)
                if (FontFile2 == null) {
                    FontFile2 = pdfFontDescriptor.getDictionary(PdfDictionary.FontFile);

                    if (FontFile2 == null) {
                        FontFile2 = pdfFontDescriptor.getDictionary(PdfDictionary.FontFile3);
                    }
                }

                if (FontFile2 != null) {
                    stream = currentPdfFile.readStream(FontFile2, true, true, false, false, false, FontFile2.getCacheName(currentPdfFile.getObjectReader()));
                }

                if (stream != null) {
                    readEmbeddedFont(stream, null, hasEncoding);
                }
            }

            if (!isFontEmbedded && substituteFont != null) {

                subfontAlreadyLoaded = !isCIDFont && fontsLoaded.containsKey(substituteFont + '_' + glyphs.getBaseFontName());

                final File fontFile;
                FontData fontData = null;
                int objSize = 0;
                
                /*
                 * see if we cache or read
                 */
                if (!subfontAlreadyLoaded) {
                    fontFile = new File(substituteFont);

                    objSize = (int) fontFile.length();
                }

                if (FontData.maxSizeAllowedInMemory >= 0 && objSize > FontData.maxSizeAllowedInMemory) {

                    if (!subfontAlreadyLoaded) {
                        fontData = new FontData(substituteFont);
                    }

                    readEmbeddedFont(null, fontData, false);
                } else if (subfontAlreadyLoaded) {
                    readEmbeddedFont(null, null, false);
                } else {

                    //read details
                    final BufferedInputStream from;

                    InputStream jarFile = null;
                    try {
                        if (substituteFont.startsWith("jar:") || substituteFont.startsWith("http:")) {
                            jarFile = loader.getResourceAsStream(substituteFont);
                        } else {
                            jarFile = loader.getResourceAsStream("file:///" + substituteFont);
                        }

                    } catch (final Exception e) {
                        LogWriter.writeLog("1.Unable to open " + substituteFont + ' ' + e);
                    } catch (final Error err) {
                        LogWriter.writeLog("1.Unable to open " + substituteFont + ' ' + err);
                    }

                    if (jarFile == null) {
                        from = new BufferedInputStream(new FileInputStream(substituteFont));
                    } else {
                        from = new BufferedInputStream(jarFile);
                    }

                    //create streams
                    final FastByteArrayOutputStream to = new FastByteArrayOutputStream();

                    //write
                    final byte[] buffer = new byte[65535];
                    int bytes_read;
                    while ((bytes_read = from.read(buffer)) != -1) {
                        to.write(buffer, 0, bytes_read);
                    }

                    from.close();

                    readEmbeddedFont(to.toByteArray(), null, false);
                }

                isFontSubstituted = true;

            }
        }

        readWidths(pdfObject, true);

        //make sure a font set
        if (renderPage) {
            setFont(glyphs.fontName, 1);
        }

    }

    /**
     * read truetype font data and also install font onto System
     * so we can use
     */
    protected final void readEmbeddedFont(final byte[] fontDataAsArray, final FontData fontDataAsObject, final boolean hasEncoding) {

        //process the font data
        try {

            readFontData(fontDataAsArray, fontDataAsObject);

            isFontEmbedded = true;

            glyphs.setFontEmbedded(true);

            glyphs.setEncodingToUse(hasEncoding, this.getFontEncoding(false), TTstreamisCID);

        } catch (final Exception e) {

            isFontEmbedded = false;

            LogWriter.writeLog("Exception " + e + " processing TrueType font");

        }
    }

    /**
     * get bounding box to highlight
     *
     * @return
     */
    @Override
    public Rectangle getBoundingBox() {

//        if(BBox==null){
        if (isFontEmbedded && !isFontSubstituted) {
            BBox = new Rectangle((int) FontBBox[0], (int) FontBBox[1], (int) (FontBBox[2] - FontBBox[0]), (int) (FontBBox[3] - FontBBox[1]));
        } else {
            BBox = super.getBoundingBox();
        }
//        }

        return BBox;
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy