Package org.apache.fop.fonts.autodetect

Source Code of org.apache.fop.fonts.autodetect.FontInfoFinder

/*
* 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: FontInfoFinder.java 629131 2008-02-19 15:47:48Z jeremias $ */

package org.apache.fop.fonts.autodetect;

import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.fonts.CachedFontInfo;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.EmbedFontInfo;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontCache;
import org.apache.fop.fonts.FontLoader;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.FontUtil;

/**
* Attempts to determine correct FontInfo
*/
public class FontInfoFinder {
   
    /** logging instance */
    private Log log = LogFactory.getLog(FontInfoFinder.class);

    /**
     * Attempts to determine FontTriplets from a given CustomFont.
     * It seems to be fairly accurate but will probably require some tweaking over time
     *
     * @param customFont CustomFont
     * @param triplet Collection that will take the generated triplets
     */
    private void generateTripletsFromFont(CustomFont customFont, Collection triplets) {
        if (log.isTraceEnabled()) {
            log.trace("Font: " + customFont.getFullName()
                    + ", family: " + customFont.getFamilyNames()
                    + ", PS: " + customFont.getFontName()
                    + ", EmbedName: " + customFont.getEmbedFontName());
        }

        // default style and weight triplet vales (fallback)
        String strippedName = stripQuotes(customFont.getStrippedFontName());
        //String subName = customFont.getFontSubName();
        String fullName = stripQuotes(customFont.getFullName());
        String searchName = fullName.toLowerCase();

        String style = guessStyle(customFont, searchName);
        int weight; //= customFont.getWeight();
        int guessedWeight = FontUtil.guessWeight(searchName);
        //We always take the guessed weight for now since it yield much better results.
        //OpenType's OS/2 usWeightClass value proves to be unreliable.
        weight = guessedWeight;

        //Full Name usually includes style/weight info so don't use these traits
        //If we still want to use these traits, we have to make FontInfo.fontLookup() smarter
        triplets.add(new FontTriplet(fullName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, 0));
        if (!fullName.equals(strippedName)) {
            triplets.add(new FontTriplet(strippedName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, 0));
        }
        Set familyNames = customFont.getFamilyNames();
        Iterator iter = familyNames.iterator();
        while (iter.hasNext()) {
            String familyName = stripQuotes((String)iter.next());
            if (!fullName.equals(familyName)) {
                /* Heuristic:
                 *   The more similar the family name to the full font name,
                 *   the higher the priority of its triplet.
                 * (Lower values indicate higher priorities.) */
                int priority = fullName.startsWith(familyName)
                    ? fullName.length() - familyName.length()
                    : fullName.length();
                triplets.add(new FontTriplet(familyName, style, weight, priority));
            }
        }
    }
   
    private final Pattern quotePattern = Pattern.compile("'");
   
    private String stripQuotes(String name) {
        return quotePattern.matcher(name).replaceAll("");
    }

    private String guessStyle(CustomFont customFont, String fontName) {
        // style
        String style = Font.STYLE_NORMAL;
        if (customFont.getItalicAngle() > 0) {
            style = Font.STYLE_ITALIC; 
        } else {
            style = FontUtil.guessStyle(fontName);
        }
        return style;
    }
   
    /**
     * Attempts to determine FontInfo from a given custom font
     * @param fontUrl the font URL
     * @param customFont the custom font
     * @param fontCache font cache (may be null)
     * @return
     */
    private EmbedFontInfo fontInfoFromCustomFont(
            URL fontUrl, CustomFont customFont, FontCache fontCache) {
        List fontTripletList = new java.util.ArrayList();
        generateTripletsFromFont(customFont, fontTripletList);
        String embedUrl;
        embedUrl = fontUrl.toExternalForm();
        EmbedFontInfo fontInfo = new EmbedFontInfo(null, customFont.isKerningEnabled(),
                fontTripletList, embedUrl);
        if (fontCache != null) {
            fontCache.addFont(fontInfo);
        }
        return fontInfo;
    }
       
    /**
     * Attempts to determine EmbedFontInfo from a given font file.
     *
     * @param fontUrl font URL. Assumed to be local.
     * @param resolver font resolver used to resolve font
     * @param fontCache font cache (may be null)
     * @return newly created embed font info
     */
    public EmbedFontInfo find(URL fontUrl, FontResolver resolver, FontCache fontCache) {
        String embedUrl = null;
        embedUrl = fontUrl.toExternalForm();
       
        long fileLastModified = -1;
        if (fontCache != null) {
            try {
                URLConnection conn = fontUrl.openConnection();
                try {
                    fileLastModified = conn.getLastModified();
                } finally {
                    //An InputStream is created even if it's not accessed, but we need to close it.
                    IOUtils.closeQuietly(conn.getInputStream());
                }
            } catch (IOException e) {
                // Should never happen, because URL must be local
                log.debug("IOError: " + e.getMessage());
                fileLastModified = 0;
            }
            // firstly try and fetch it from cache before loading/parsing the font file
            if (fontCache.containsFont(embedUrl)) {
                CachedFontInfo fontInfo = fontCache.getFont(embedUrl);
                if (fontInfo.lastModified() == fileLastModified) {
                    return fontInfo;
                } else {
                    // out of date cache item
                    fontCache.removeFont(embedUrl);
                }
            // is this a previously failed parsed font?
            } else if (fontCache.isFailedFont(embedUrl, fileLastModified)) {
                if (log.isDebugEnabled()) {
                    log.debug("Skipping font file that failed to load previously: " + embedUrl);
                }
                return null;
            }
        }
       
        // try to determine triplet information from font file
        CustomFont customFont = null;
        try {
            customFont = FontLoader.loadFont(fontUrl, resolver);
        } catch (Exception e) {
            //TODO Too verbose (it's an error but we don't care if some fonts can't be loaded)
            if (log.isErrorEnabled()) {
                log.error("Unable to load font file: " + embedUrl + ". Reason: " + e.getMessage());
            }
            if (fontCache != null) {
                fontCache.registerFailedFont(embedUrl, fileLastModified);
            }
            return null;
        }
        return fontInfoFromCustomFont(fontUrl, customFont, fontCache);    
    }
}
TOP

Related Classes of org.apache.fop.fonts.autodetect.FontInfoFinder

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.