CharacterWidthEstimator.java 7.11 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.fontengine.font.Font
 *  com.adobe.fontengine.font.FontData
 *  com.adobe.fontengine.font.FontLoadingException
 *  com.adobe.fontengine.font.InvalidFontException
 *  com.adobe.fontengine.font.PDFFontDescription
 *  com.adobe.fontengine.font.UnsupportedFontException
 *  com.adobe.internal.pdftoolkit.core.exceptions.PDFIOException
 *  com.adobe.internal.pdftoolkit.core.exceptions.PDFInvalidDocumentException
 *  com.adobe.internal.pdftoolkit.core.exceptions.PDFRuntimeException
 *  com.adobe.internal.pdftoolkit.core.exceptions.PDFSecurityException
 */
package com.adobe.internal.pdftoolkit.pdf.content.processor;

import com.adobe.fontengine.font.Font;
import com.adobe.fontengine.font.FontData;
import com.adobe.fontengine.font.FontLoadingException;
import com.adobe.fontengine.font.InvalidFontException;
import com.adobe.fontengine.font.PDFFontDescription;
import com.adobe.fontengine.font.UnsupportedFontException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFIOException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFInvalidDocumentException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFRuntimeException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFSecurityException;
import com.adobe.internal.pdftoolkit.pdf.content.processor.CosineDistanceComputer;
import com.adobe.internal.pdftoolkit.pdf.content.processor.FontWidthStore;
import com.adobe.internal.pdftoolkit.pdf.content.processor.PDFSimpleFontData;
import com.adobe.internal.pdftoolkit.pdf.content.processor.SimpleFontDataCache;
import com.adobe.internal.pdftoolkit.pdf.graphics.font.PDFFontSimple;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

class CharacterWidthEstimator {
    private SimpleFontDataCache simpleFontDataCache;
    private static ArrayList<FontWidthStore> base14FontswidthStore;
    private static final String[] SERIALIZED_FONT_WIDTHS;

    CharacterWidthEstimator(SimpleFontDataCache simpleFontDataCache) {
        this.simpleFontDataCache = simpleFontDataCache;
    }

    double getCharacterWidth(int charcode, PDFFontSimple font) throws InvalidFontException, UnsupportedFontException, FontLoadingException, PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        return this.getClosestFontWidthStoreWidth(font, charcode);
    }

    private double getRatio(FontWidthStore actualFont, FontWidthStore closest) {
        double sum = 0.0;
        int count = 0;
        Iterator<Integer> i$ = actualFont.getUnicodes().iterator();
        while (i$.hasNext()) {
            int ch = i$.next();
            double baseWidth = actualFont.getWidth(ch) / 1000.0;
            double refWidth = closest.getWidth(ch) / 1000.0;
            if (baseWidth <= 0.0 || refWidth <= 0.0) continue;
            ++count;
            sum += baseWidth / refWidth;
        }
        return sum / (double)count;
    }

    private double getClosestFontWidthStoreWidth(PDFFontSimple font, int charCode) throws InvalidFontException, UnsupportedFontException, FontLoadingException, PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        FontWidthStore fws = this.getFontWidthStore(font);
        if (fws == null || fws.getUnicodes().size() <= 0) {
            return -1.0;
        }
        double maxDistance = Double.NEGATIVE_INFINITY;
        FontWidthStore closest = null;
        CosineDistanceComputer dis = new CosineDistanceComputer();
        for (FontWidthStore f : base14FontswidthStore) {
            double dist = dis.getDistance(fws, f);
            if (dist <= maxDistance) continue;
            maxDistance = dist;
            closest = f;
        }
        if (closest == null) {
            return 0.0;
        }
        return closest.getWidth(charCode) * this.getRatio(fws, closest);
    }

    private FontWidthStore getFontWidthStore(PDFFontSimple simpleFont) throws InvalidFontException, UnsupportedFontException, FontLoadingException, PDFInvalidDocumentException, PDFIOException, PDFSecurityException {
        FontWidthStore fws = null;
        PDFSimpleFontData simpleFontData = null;
        if (this.simpleFontDataCache.isEnabled() && (fws = (simpleFontData = this.simpleFontDataCache.getPDFSimpleFontData(simpleFont)).getFontWidthStore()) != null) {
            return fws;
        }
        FontData fData = simpleFont.getAFEFontData();
        Font afeFont = simpleFont.getAFEFont();
        if (fData == null || afeFont == null) {
            return null;
        }
        PDFFontDescription desc = afeFont.getPDFFontDescription();
        HashMap<Integer, Double> widthMap = new HashMap<Integer, Double>();
        for (int i = 32; i <= 127; ++i) {
            long gid = fData.getGlyphForChar(i);
            if (gid <= 0) continue;
            double width = desc.getAdvance((int)gid);
            double unitesPerEmX = fData.getUnitsPerEmX();
            if (unitesPerEmX != 0.0) {
                width = width * 1000.0 / unitesPerEmX;
            }
            widthMap.put(i, width);
        }
        fws = new FontWidthStore(simpleFont.getAFEFont(), widthMap);
        if (this.simpleFontDataCache.isEnabled()) {
            simpleFontData.setFontWidthStore(fws);
        }
        return fws;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    static {
        SERIALIZED_FONT_WIDTHS = new String[]{"base14fontwidths/courierRegular", "base14fontwidths/courierBoldOblique", "base14fontwidths/courierBold", "base14fontwidths/courierOblique", "base14fontwidths/helveticaRegular", "base14fontwidths/helveticaBold", "base14fontwidths/helveticaBoldOblique", "base14fontwidths/helveticaOblique", "base14fontwidths/symbol", "base14fontwidths/timesBold", "base14fontwidths/timesBoldItalic", "base14fontwidths/timesItalic", "base14fontwidths/timesRegular", "base14fontwidths/zapfDingbats"};
        base14FontswidthStore = new ArrayList();
        try {
            for (String fname : SERIALIZED_FONT_WIDTHS) {
                InputStream fontWidthStream = null;
                ObjectInputStream ois = null;
                try {
                    fontWidthStream = CharacterWidthEstimator.class.getResourceAsStream(fname);
                    ois = new ObjectInputStream(fontWidthStream);
                    FontWidthStore widthStore = (FontWidthStore)ois.readObject();
                    ois.close();
                    base14FontswidthStore.add(widthStore);
                }
                finally {
                    if (ois != null) {
                        ois.close();
                    }
                    if (fontWidthStream != null) {
                        fontWidthStream.close();
                    }
                }
            }
        }
        catch (IOException e) {
            throw new PDFRuntimeException("Bad configuration - unable to load width map for Base14 fonts.");
        }
        catch (ClassNotFoundException e) {
            throw new PDFRuntimeException("Bad configuration - unable to load width map for Base14 fonts.", (Throwable)e);
        }
    }
}