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

com.openhtmltopdf.pdfboxout.fontstore.FallbackFontStore Maven / Gradle / Ivy

Go to download

Openhtmltopdf is a CSS 2.1 renderer written in Java. This artifact supports PDF output with Apache PDF-BOX 2.

The newest version!
package com.openhtmltopdf.pdfboxout.fontstore;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.fontbox.ttf.TrueTypeCollection;
import org.apache.fontbox.ttf.TrueTypeFont;
import org.apache.fontbox.ttf.TrueTypeCollection.TrueTypeFontProcessor;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;

import com.openhtmltopdf.css.constants.IdentValue;
import com.openhtmltopdf.extend.FSCacheEx;
import com.openhtmltopdf.extend.FSCacheValue;
import com.openhtmltopdf.extend.FSSupplier;
import com.openhtmltopdf.layout.SharedContext;
import com.openhtmltopdf.outputdevice.helper.FontResolverHelper;
import com.openhtmltopdf.pdfboxout.PDFontSupplier;
import com.openhtmltopdf.pdfboxout.PdfBoxFontResolver.FontDescription;

public class FallbackFontStore implements Closeable {
    private final List fonts = new ArrayList<>();
    private final List _collectionsToClose = new ArrayList<>();
    private final PDDocument _doc;
    private final FSCacheEx _fontMetricsCache;

    public FallbackFontStore(
            SharedContext sharedContext,
            PDDocument doc,
            FSCacheEx pdfMetricsCache) {
        this._doc = doc;
        this._fontMetricsCache = pdfMetricsCache;
    }

    private int getFontPriority(FontDescription font, String[] families, IdentValue weight, IdentValue desiredStyle, IdentValue variant) {
        String fontFamily = font.getFamily();
        int fontWeight = font.getWeight();
        IdentValue fontStyle = font.getStyle();

        List desiredFamilies = families != null ?
                Arrays.asList(families) : Collections.emptyList();
        int desiredWeight = FontResolverHelper.convertWeightToInt(weight);

        if (fontWeight == desiredWeight &&
            fontStyle == desiredStyle) {
            // Exact match for weight and style.
            return getFamilyPriority(fontFamily, desiredFamilies);
        } else if (Math.abs(fontWeight - desiredWeight) < 200 &&
                   fontStyle == desiredStyle) {
            // Near enough weight match, exact style match.
            return 3 + getFamilyPriority(fontFamily, desiredFamilies);
        } else if (fontStyle == desiredStyle) {
            // No weight match, but style matches.
            return 6 + getFamilyPriority(fontFamily, desiredFamilies);
        } else {
            // Neither weight nor style matches.
            return 9 + getFamilyPriority(fontFamily, desiredFamilies);
        }
    }

    private int getFamilyPriority(String fontFamily, List desiredFamilies) {
        if (!desiredFamilies.isEmpty() &&
            desiredFamilies.get(0).equals(fontFamily)) {
            return 1;
        } else if (desiredFamilies.contains(fontFamily)) {
            return 2;
        } else {
            return 3;
        }
    }

    public List resolveFonts(
            SharedContext ctx, String[] families, float size, IdentValue weight, IdentValue style, IdentValue variant) {

        if (fonts.size() <= 1) {
            // No need to make a copy to sort.
            return fonts;
        }

        List ret = new ArrayList<>(fonts);

        Collections.sort(ret, Comparator.comparing(font -> getFontPriority(font, families, weight, style, variant)));

        return ret;
    }

    public void addFont(
            FSSupplier supplier,
            String fontFamilyNameOverride,
            Integer fontWeightOverride,
            IdentValue fontStyleOverride,
            boolean subset) {

        FontDescription descr = new FontDescription(
                _doc,
                supplier,
                FontUtil.normalizeFontWeight(fontWeightOverride),
                FontUtil.normalizeFontStyle(fontStyleOverride),
                fontFamilyNameOverride,
                false, // isFromFontFace
                subset,
                _fontMetricsCache);

        addFont(subset, descr);
    }

    public void addFont(
            PDFontSupplier supplier,
            String fontFamilyNameOverride,
            Integer fontWeightOverride,
            IdentValue fontStyleOverride,
            boolean subset) {

        FontDescription descr = new FontDescription(
                _doc,
                supplier,
                FontUtil.normalizeFontStyle(fontStyleOverride),
                FontUtil.normalizeFontWeight(fontWeightOverride),
                fontFamilyNameOverride,
                false, // isFromFontFace
                subset,
                _fontMetricsCache);

        addFont(subset, descr);
    }

    /**
     * Add a font with a lazy loaded PDFont
     */
    public void addFontLazy(FSSupplier font, String fontFamilyNameOverride, Integer fontWeightOverride, IdentValue fontStyleOverride, boolean subset) {
        FontDescription descr = new FontDescription(
                _doc,
                font,
                FontUtil.normalizeFontStyle(fontStyleOverride),
                FontUtil.normalizeFontWeight(fontWeightOverride),
                fontFamilyNameOverride,
                false,   // isFromFontFace
                subset,
                _fontMetricsCache);

        addFont(subset, descr);
    }

    private void addFont(boolean subset, FontDescription descr) {
        if (!subset) {
            if (descr.realizeFont()) {
                fonts.add(descr);
            }
        } else {
            fonts.add(descr);
        }
    }

    @Override
    public void close() throws IOException {
        for (TrueTypeCollection collection : _collectionsToClose) {
            FontUtil.tryClose(collection);
        }
        _collectionsToClose.clear();
    }

    /**
     * Add a font using a FontBox TrueTypeFont.
     */
    void addFont(
            TrueTypeFont trueTypeFont,
            String fontFamilyNameOverride,
            Integer fontWeightOverride,
            IdentValue fontStyleOverride,
            boolean subset) throws IOException {

        PDFont font = PDType0Font.load(_doc, trueTypeFont, subset);

        addFontLazy(new PDFontSupplier(font), fontFamilyNameOverride, fontWeightOverride, fontStyleOverride, subset);
    }

    public void addFontCollection(
            TrueTypeCollection collection,
            String fontFamilyNameOverride,
            Integer fontWeightOverride,
            IdentValue fontStyleOverride,
            boolean subset) throws IOException {

        collection.processAllFonts(new TrueTypeFontProcessor() {
            @Override
            public void process(TrueTypeFont ttf) throws IOException {
                addFont(ttf, fontFamilyNameOverride, fontWeightOverride, fontStyleOverride, subset);
            }
        });
        _collectionsToClose.add(collection);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy