Package org.apache.fop.fonts

Source Code of org.apache.fop.fonts.FontInfoConfigurator

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: FontInfoConfigurator.java 821058 2009-10-02 15:31:14Z jeremias $ */

package org.apache.fop.fonts;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.apps.FOPException;
import org.apache.fop.fonts.autodetect.FontFileFinder;
import org.apache.fop.fonts.autodetect.FontInfoFinder;
import org.apache.fop.util.LogUtil;

/**
* An abstract FontInfo configurator
*/
public class FontInfoConfigurator {
    /** logger instance */
    protected static Log log = LogFactory.getLog(FontInfoConfigurator.class);

    private Configuration cfg;
    private FontManager fontManager;
    private FontResolver fontResolver;
    private FontEventListener listener;
    private boolean strict;

    /**
     * Main constructor
     * @param cfg the configuration object
     * @param fontManager the font manager
     * @param fontResolver the font resolver
     * @param listener the font event listener
     * @param strict true if an Exception should be thrown if an error is found.
     */
    public FontInfoConfigurator(Configuration cfg, FontManager fontManager,
            FontResolver fontResolver, FontEventListener listener, boolean strict) {
        this.cfg = cfg;
        this.fontManager = fontManager;
        this.fontResolver = fontResolver;
        this.listener = listener;
        this.strict = strict;
    }

    /**
     * Initializes font info settings from the user configuration
     * @param fontInfoList a font info list
     * @throws FOPException if an exception occurs while processing the configuration
     */
    public void configure(List/*<EmbedFontInfo>*/ fontInfoList) throws FOPException {
        Configuration fonts = cfg.getChild("fonts", false);
        if (fonts != null) {
            long start = 0;
            if (log.isDebugEnabled()) {
                log.debug("Starting font configuration...");
                start = System.currentTimeMillis();
            }

            FontAdder fontAdder = new FontAdder(fontManager, fontResolver, listener);

            // native o/s search (autodetect) configuration
            boolean autodetectFonts = (fonts.getChild("auto-detect", false) != null);
            if (autodetectFonts) {
                FontDetector fontDetector = new FontDetector(fontManager, fontAdder, strict);
                fontDetector.detect(fontInfoList);
            }

            // Add configured directories to FontInfo
            addDirectories(fonts, fontAdder, fontInfoList);

            // Add configured fonts to FontInfo
            FontCache fontCache = fontManager.getFontCache();
            addFonts(fonts, fontCache, fontInfoList);

            // Update referenced fonts (fonts which are not to be embedded)
            fontManager.updateReferencedFonts(fontInfoList);

            // Renderer-specific referenced fonts
            Configuration referencedFontsCfg = fonts.getChild("referenced-fonts", false);
            if (referencedFontsCfg != null) {
                FontTriplet.Matcher matcher = FontManagerConfigurator.createFontsMatcher(
                        referencedFontsCfg, strict);
                fontManager.updateReferencedFonts(fontInfoList, matcher);
            }

            // Update font cache if it has changed
            if (fontCache != null && fontCache.hasChanged()) {
                fontCache.save();
            }

            if (log.isDebugEnabled()) {
                log.debug("Finished font configuration in "
                        + (System.currentTimeMillis() - start) + "ms");
            }
        }
    }

    private void addDirectories(Configuration fontsCfg,
            FontAdder fontAdder, List/*<URL>*/ fontInfoList) throws FOPException {
        // directory (multiple font) configuration
        Configuration[] directories = fontsCfg.getChildren("directory");
        for (int i = 0; i < directories.length; i++) {
            boolean recursive = directories[i].getAttributeAsBoolean("recursive", false);
            String directory = null;
            try {
                directory = directories[i].getValue();
            } catch (ConfigurationException e) {
                LogUtil.handleException(log, e, strict);
                continue;
            }
            if (directory == null) {
                LogUtil.handleException(log,
                        new FOPException("directory defined without value"), strict);
                continue;
            }

            // add fonts found in directory
            FontFileFinder fontFileFinder = new FontFileFinder(recursive ? -1 : 1);
            List/*<URL>*/ fontURLList;
            try {
                fontURLList = fontFileFinder.find(directory);
                fontAdder.add(fontURLList, fontInfoList);
            } catch (IOException e) {
                LogUtil.handleException(log, e, strict);
            }
        }
    }

    /**
     * Populates the font info list from the fonts configuration
     * @param fontsCfg a fonts configuration
     * @param fontCache a font cache
     * @param fontInfoList a font info list
     * @throws FOPException if an exception occurs while processing the configuration
     */
    protected void addFonts(Configuration fontsCfg, FontCache fontCache,
            List/*<EmbedFontInfo>*/ fontInfoList) throws FOPException {
        // font file (singular) configuration
        Configuration[] font = fontsCfg.getChildren("font");
        for (int i = 0; i < font.length; i++) {
            EmbedFontInfo embedFontInfo = getFontInfo(
                    font[i], fontCache);
            if (embedFontInfo != null) {
                fontInfoList.add(embedFontInfo);
            }
        }
    }

    private static void closeSource(Source src) {
        if (src instanceof StreamSource) {
            StreamSource streamSource = (StreamSource)src;
            IOUtils.closeQuietly(streamSource.getInputStream());
            IOUtils.closeQuietly(streamSource.getReader());
        }
    }

    /**
     * Returns a font info from a font node Configuration definition
     *
     * @param fontCfg Configuration object (font node)
     * @param fontCache the font cache (or null if it is disabled)
     * @return the embedded font info
     * @throws FOPException if something's wrong with the config data
     */
    protected EmbedFontInfo getFontInfo(
            Configuration fontCfg, FontCache fontCache)
                    throws FOPException {
        String metricsUrl = fontCfg.getAttribute("metrics-url", null);
        String embedUrl = fontCfg.getAttribute("embed-url", null);
        String subFont = fontCfg.getAttribute("sub-font", null);

        if (metricsUrl == null && embedUrl == null) {
            LogUtil.handleError(log,
                    "Font configuration without metric-url or embed-url attribute",
                    strict);
            return null;
        }
        if (strict) {
            //This section just checks early whether the URIs can be resolved
            //Stream are immediately closed again since they will never be used anyway
            if (embedUrl != null) {
                Source source = fontResolver.resolve(embedUrl);
                closeSource(source);
                if (source == null) {
                    LogUtil.handleError(log,
                            "Failed to resolve font with embed-url '" + embedUrl + "'", strict);
                    return null;
                }
            }
            if (metricsUrl != null) {
                Source source = fontResolver.resolve(metricsUrl);
                closeSource(source);
                if (source == null) {
                    LogUtil.handleError(log,
                            "Failed to resolve font with metric-url '" + metricsUrl + "'", strict);
                    return null;
                }
            }
        }

        Configuration[] tripletCfg = fontCfg.getChildren("font-triplet");

        // no font triplet info
        if (tripletCfg.length == 0) {
            LogUtil.handleError(log, "font without font-triplet", strict);

            File fontFile = FontCache.getFileFromUrls(new String[] {embedUrl, metricsUrl});
            URL fontUrl;
            try {
                fontUrl = fontFile.toURI().toURL();
            } catch (MalformedURLException e) {
                // Should never happen
                log.debug("Malformed Url: " + e.getMessage());
                return null;
            }
            if (fontFile != null) {
                FontInfoFinder finder = new FontInfoFinder();
                finder.setEventListener(listener);
                EmbedFontInfo[] infos = finder.find(fontUrl, fontResolver, fontCache);
                return infos[0]; //When subFont is set, only one font is returned
            } else {
                return null;
            }
        }

        List/*<FontTriplet>*/ tripletList = new java.util.ArrayList/*<FontTriplet>*/();
        for (int j = 0; j < tripletCfg.length; j++) {
            FontTriplet fontTriplet = getFontTriplet(tripletCfg[j]);
            tripletList.add(fontTriplet);
        }

        boolean useKerning = fontCfg.getAttributeAsBoolean("kerning", true);
        EncodingMode encodingMode = EncodingMode.valueOf(
                fontCfg.getAttribute("encoding-mode", EncodingMode.AUTO.getName()));
        EmbedFontInfo embedFontInfo
                = new EmbedFontInfo(metricsUrl, useKerning, tripletList, embedUrl, subFont);
        embedFontInfo.setEncodingMode(encodingMode);
        if (fontCache != null) {
            if (!fontCache.containsFont(embedFontInfo)) {
                fontCache.addFont(embedFontInfo);
            }
        }

        if (log.isDebugEnabled()) {
            String embedFile = embedFontInfo.getEmbedFile();
            log.debug("Adding font " + (embedFile != null ? embedFile + ", " : "")
                    + "metric file " + embedFontInfo.getMetricsFile());
            for (int j = 0; j < tripletList.size(); ++j) {
                FontTriplet triplet = (FontTriplet) tripletList.get(j);
                log.debug("  Font triplet "
                        + triplet.getName() + ", "
                        + triplet.getStyle() + ", "
                        + triplet.getWeight());
            }
        }
        return embedFontInfo;
    }

    /**
     * Creates a new FontTriplet given a triple Configuration
     *
     * @param tripletCfg a triplet configuration
     * @return a font triplet font key
     * @throws FOPException thrown if a FOP exception occurs
     */
    private FontTriplet getFontTriplet(Configuration tripletCfg) throws FOPException {
        try {
            String name = tripletCfg.getAttribute("name");
            if (name == null) {
                LogUtil.handleError(log, "font-triplet without name", strict);
                return null;
            }

            String weightStr = tripletCfg.getAttribute("weight");
            if (weightStr == null) {
                LogUtil.handleError(log, "font-triplet without weight", strict);
                return null;
            }
            int weight = FontUtil.parseCSS2FontWeight(FontUtil.stripWhiteSpace(weightStr));

            String style = tripletCfg.getAttribute("style");
            if (style == null) {
                LogUtil.handleError(log, "font-triplet without style", strict);
                return null;
            } else {
                style = FontUtil.stripWhiteSpace(style);
            }
            return FontInfo.createFontKey(name, style, weight);
        } catch (ConfigurationException e) {
            LogUtil.handleException(log, e, strict);
        }
        return null;
    }

}
TOP

Related Classes of org.apache.fop.fonts.FontInfoConfigurator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.