uk.co.spudsoft.birt.emitters.excel.FontManager.java Source code

Java tutorial

Introduction

Here is the source code for uk.co.spudsoft.birt.emitters.excel.FontManager.java

Source

/*************************************************************************************
 * Copyright (c) 2011, 2012, 2013 James Talbut.
 *  jim-emitters@spudsoft.co.uk
 *  
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     James Talbut - Initial implementation.
 ************************************************************************************/

package uk.co.spudsoft.birt.emitters.excel;

import java.util.ArrayList;
import java.util.List;

import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.FontUnderline;
import org.apache.poi.ss.usermodel.Workbook;
import org.eclipse.birt.report.engine.content.IStyle;
import org.eclipse.birt.report.engine.css.engine.CSSEngine;
import org.eclipse.birt.report.engine.css.engine.StyleConstants;
import org.eclipse.birt.report.engine.css.engine.value.ListValue;
import org.eclipse.birt.report.engine.css.engine.value.StringValue;
import org.eclipse.birt.report.engine.css.engine.value.css.CSSConstants;
import org.w3c.dom.css.CSSValue;

/**
 * FontManager is a cache of fonts to enable POI Fonts to be reused based upon their BIRT styles.
 * @author Jim Talbut
 *
 */
public class FontManager {

    /**
     * FontPair maintains the relationship between a BIRT style and a POI font.
     * @author Jim Talbut
     *
     */
    private class FontPair {
        public BirtStyle birtStyle;
        public Font poiFont;

        public FontPair(BirtStyle birtStyle, Font poiFont) {
            this.birtStyle = birtStyle;
            this.poiFont = poiFont;
        }
    }

    private Workbook workbook;
    private StyleManagerUtils smu;
    private List<FontPair> fonts = new ArrayList<FontPair>();
    private Font defaultFont = null;
    private CSSEngine cssEngine;

    /**
     * @param workbook
     * The workbook for which fonts are being tracked.
     * @param smu
     * The StyleManagerUtils instance that will be used in the comparison of styles and manipulation of colours.
     */
    public FontManager(CSSEngine cssEngine, Workbook workbook, StyleManagerUtils smu) {
        this.cssEngine = cssEngine;
        this.workbook = workbook;
        this.smu = smu;
    }

    /**
     * Obtain the CSS Engine known by this font manager.
     */
    CSSEngine getCssEngine() {
        return cssEngine;
    }

    /**
     * Remove quotes surrounding a string.
     * @param family
     * The string that may be surrounded by double quotes.
     * @return
     * family, without any surrounding double quotes.
     */
    private static String cleanupQuotes(CSSValue value) {
        if (value == null) {
            return null;
        }

        if (value instanceof ListValue) {
            ListValue listValue = (ListValue) value;
            if (listValue.getLength() > 0) {
                value = listValue.item(0);
            }
        }

        String stringValue = (value instanceof StringValue ? ((StringValue) value).getStringValue()
                : value.getCssText());
        if ((stringValue == null) || stringValue.isEmpty()) {
            return stringValue;
        }
        if (stringValue.startsWith("\"") && stringValue.endsWith("\"")) {
            String newFamily = stringValue.substring(1, stringValue.length() - 1);
            return newFamily;
        }
        return stringValue;
    }

    static int COMPARE_CSS_PROPERTIES[] = { StyleConstants.STYLE_FONT_FAMILY, StyleConstants.STYLE_FONT_SIZE,
            StyleConstants.STYLE_FONT_WEIGHT, StyleConstants.STYLE_FONT_STYLE, StyleConstants.STYLE_TEXT_UNDERLINE,
            StyleConstants.STYLE_COLOR, };

    /**
     * Test whether two BIRT styles are equivalent, as far as their font definitions are concerned.
     * <br/>
     * Every attribute tested in this method must be used in the construction of the font in createFont.
     * @param style1
     * The first BIRT style to be compared.
     * @param style2
     * The second BIRT style to be compared.
     * @return
     * true if style1 and style2 would produce identical Fonts if passed to createFont.
     */
    public static boolean fontsEquivalent(BirtStyle style1, BirtStyle style2) {
        for (int i = 0; i < COMPARE_CSS_PROPERTIES.length; ++i) {
            int prop = COMPARE_CSS_PROPERTIES[i];
            CSSValue value1 = style1.getProperty(prop);
            CSSValue value2 = style2.getProperty(prop);
            if (!StyleManagerUtils.objectsEqual(value1, value2)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Create a new POI Font based upon a BIRT style.
     * @param birtStyle
     * The BIRT style to base the Font upon.
     * @return
     * The Font whose attributes are described by the BIRT style. 
     */
    private Font createFont(BirtStyle birtStyle) {
        Font font = workbook.createFont();

        // Family
        String fontName = smu
                .poiFontNameFromBirt(cleanupQuotes(birtStyle.getProperty(StyleConstants.STYLE_FONT_FAMILY)));
        if (fontName == null) {
            fontName = "Calibri";
        }
        font.setFontName(fontName);
        // Size
        short fontSize = smu.fontSizeInPoints(cleanupQuotes(birtStyle.getProperty(StyleConstants.STYLE_FONT_SIZE)));
        if (fontSize > 0) {
            font.setFontHeightInPoints(fontSize);
        }
        // Weight
        short fontWeight = smu
                .poiFontWeightFromBirt(cleanupQuotes(birtStyle.getProperty(StyleConstants.STYLE_FONT_WEIGHT)));
        if (fontWeight > 0) {
            font.setBoldweight(fontWeight);
        }
        // Style
        String fontStyle = cleanupQuotes(birtStyle.getProperty(StyleConstants.STYLE_FONT_STYLE));
        if (CSSConstants.CSS_ITALIC_VALUE.equals(fontStyle) || CSSConstants.CSS_OBLIQUE_VALUE.equals(fontStyle)) {
            font.setItalic(true);
        }
        // Underline
        String fontUnderline = cleanupQuotes(birtStyle.getProperty(StyleConstants.STYLE_TEXT_UNDERLINE));
        if (CSSConstants.CSS_UNDERLINE_VALUE.equals(fontUnderline)) {
            font.setUnderline(FontUnderline.SINGLE.getByteValue());
        }
        // Colour
        smu.addColourToFont(workbook, font, cleanupQuotes(birtStyle.getProperty(StyleConstants.STYLE_COLOR)));

        fonts.add(new FontPair(birtStyle, font));
        return font;
    }

    /**
     * <p>
     * Return the default font for the workbook.
     * </p><p>
     * At this stage this is hardcoded to return Calibri 11pt, but it could be changed to either pull a value from POI
     * or to have a parameterised value set from the emitter (via the constructor).
     * @return
     * A Font object representing the default to use when no other options are available.
     */
    private Font getDefaultFont() {
        if (defaultFont == null) {
            defaultFont = workbook.createFont();
            defaultFont.setFontName("Calibri");
            defaultFont.setFontHeightInPoints((short) 11);
        }
        return defaultFont;
    }

    /**
     * Get a Font matching the BIRT style, either from the cache or by creating a new one.
     * @param birtStyle
     * The BIRT style to base the Font upon.
     * @return
     * A Font whose attributes are described by the BIRT style. 
     */
    public Font getFont(BirtStyle birtStyle) {
        if (birtStyle == null) {
            return getDefaultFont();
        }

        if ((birtStyle.getProperty(StyleConstants.STYLE_FONT_FAMILY) == null)
                && (birtStyle.getProperty(StyleConstants.STYLE_FONT_SIZE) == null)
                && (birtStyle.getProperty(StyleConstants.STYLE_FONT_WEIGHT) == null)
                && (birtStyle.getProperty(StyleConstants.STYLE_FONT_STYLE) == null)
                && (birtStyle.getProperty(StyleConstants.STYLE_TEXT_UNDERLINE) == null)
                && (birtStyle.getProperty(StyleConstants.STYLE_COLOR) == null)) {
            return getDefaultFont();
        }

        for (FontPair fontPair : fonts) {
            if (fontsEquivalent(birtStyle, fontPair.birtStyle)) {
                return fontPair.poiFont;
            }
        }

        return createFont(birtStyle);
    }

    private BirtStyle birtStyleFromFont(Font source) {
        for (FontPair fontPair : fonts) {
            if (source.equals(fontPair.poiFont)) {
                return fontPair.birtStyle.clone();
            }
        }

        return new BirtStyle(cssEngine);
    }

    /**
     * Return a POI font created by combining a POI font with a BIRT style, where the BIRT style overrides the values in the POI font.
     * @param source
     * The POI font that represents the base font.
     * @param birtExtraStyle
     * The BIRT style to overlay on top of the POI style.
     * @return
     * A POI font representing the combination of source and birtExtraStyle.
     */
    public Font getFontWithExtraStyle(Font source, IStyle birtExtraStyle) {

        BirtStyle birtStyle = birtStyleFromFont(source);

        for (int i = 0; i < IStyle.NUMBER_OF_STYLE; ++i) {
            CSSValue value = birtExtraStyle.getProperty(i);
            if (value != null) {
                birtStyle.setProperty(i, value);
            }
        }

        Font newFont = getFont(birtStyle);
        return newFont;
    }

}