CSS20FontSelector.java 5.64 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.agl.util.ULocale
 */
package com.adobe.fontengine.inlineformatting.css20;

import com.adobe.agl.util.ULocale;
import com.adobe.fontengine.font.Font;
import com.adobe.fontengine.font.FontData;
import com.adobe.fontengine.font.FontException;
import com.adobe.fontengine.font.FontImpl;
import com.adobe.fontengine.inlineformatting.AttributedRun;
import com.adobe.fontengine.inlineformatting.ElementAttribute;
import com.adobe.fontengine.inlineformatting.FallbackFontSet;
import com.adobe.fontengine.inlineformatting.FontStyle;
import com.adobe.fontengine.inlineformatting.FormattingException;
import com.adobe.fontengine.inlineformatting.NoSuitableFontException;
import com.adobe.fontengine.inlineformatting.TypographicCase;
import com.adobe.fontengine.inlineformatting.css20.CSS20Attribute;
import com.adobe.fontengine.inlineformatting.css20.CSS20FontDatabase;
import com.adobe.fontengine.inlineformatting.css20.CSS20FontSet;
import com.adobe.fontengine.inlineformatting.infontformatting.InFontFormatter;
import java.util.Iterator;
import java.util.List;

public final class CSS20FontSelector {
    private final CSS20FontDatabase fontDB;

    public CSS20FontSelector(CSS20FontSet fontSet) {
        this.fontDB = (CSS20FontDatabase)fontSet;
    }

    public int format(AttributedRun run, int start, int limit) throws FormattingException {
        Font lastFontUsed = null;
        FontData lastFontDataUsed = null;
        while (start < limit) {
            int count;
            CSS20Attribute attributes = (CSS20Attribute)run.getElementStyle(start, ElementAttribute.CSS20Attribute);
            SelectedFont selectedFont = null;
            try {
                selectedFont = this.selectFont(attributes, run, start, limit, lastFontUsed, lastFontDataUsed);
            }
            catch (FontException e) {
                throw new FormattingException("Font problem found during formatting", e, start, limit);
            }
            int n = count = selectedFont.count == 0 ? 1 : selectedFont.count;
            if (selectedFont.font == null) {
                throw new NoSuitableFontException("Unable to select font for character U+" + Integer.toHexString(run.elementAt(start)) + " '" + (char)run.elementAt(start) + "'", start, start + count);
            }
            lastFontUsed = selectedFont.font;
            lastFontDataUsed = selectedFont.fontData;
            run.setElementStyle(start, start + count, ElementAttribute.font, selectedFont.font);
            run.setElementStyle(start, start + count, ElementAttribute.pointSize, new Double(attributes.getPointSize()));
            CSS20Attribute.CSSStyleValue v = attributes.getStyle();
            run.setElementStyle(start, start + count, ElementAttribute.fontStyle, v == CSS20Attribute.CSSStyleValue.ITALIC ? FontStyle.ITALIC : (v == CSS20Attribute.CSSStyleValue.OBLIQUE ? FontStyle.OBLIQUE : FontStyle.NORMAL));
            run.setElementStyle(start, start + count, ElementAttribute.typographicCase, attributes.getVariant() == CSS20Attribute.CSSVariantValue.SMALL_CAPS ? TypographicCase.SMALLCAPS : TypographicCase.TEXT);
            start += count;
        }
        return limit;
    }

    private SelectedFont selectFont(CSS20Attribute attributes, AttributedRun run, int start, int limit, Font lastFontUsed, FontData lastFontDataUsed) throws FontException {
        int count;
        List fontFamilyList = attributes.getFamilyNamesList();
        this.fontDB.replaceGenericFontFamily(fontFamilyList);
        for (int i = 0; i < fontFamilyList.size(); ++i) {
            String familyName = (String)fontFamilyList.get(i);
            Font[] proposedFonts = this.fontDB.findFont(familyName, attributes);
            if (proposedFonts == null) continue;
            for (int j = 0; j < proposedFonts.length; ++j) {
                try {
                    FontData fontData = proposedFonts[j] == lastFontUsed ? lastFontDataUsed : ((FontImpl)proposedFonts[j]).getFontData();
                    count = InFontFormatter.canRenderWithFont(fontData, run, start, limit);
                    if (count == 0) continue;
                    return new SelectedFont(proposedFonts[j], count, fontData);
                }
                catch (FontException e) {
                    e.initFont(proposedFonts[j]);
                    throw e;
                }
            }
        }
        ULocale locale = (ULocale)run.getElementStyle(start, ElementAttribute.locale);
        FallbackFontSet ffs = this.fontDB.getFallbackFontSet();
        Iterator it = ffs.getFallbackFonts(locale);
        while (it.hasNext()) {
            Font proposedFont = (Font)it.next();
            FontData proposedFontData = proposedFont == lastFontUsed ? lastFontDataUsed : ((FontImpl)proposedFont).getFontData();
            try {
                count = InFontFormatter.canRenderWithFont(proposedFontData, run, start, limit);
            }
            catch (FontException e) {
                e.initFont(proposedFont);
                throw e;
            }
            if (count != 0) {
                return new SelectedFont(proposedFont, count, proposedFontData);
            }
            if (it.hasNext()) continue;
            return new SelectedFont(proposedFont, InFontFormatter.canRenderWithNotdef(run, start, limit), proposedFontData);
        }
        return new SelectedFont(null, 0, null);
    }

    private static final class SelectedFont {
        final Font font;
        final int count;
        final FontData fontData;

        public SelectedFont(Font font, int count, FontData fontData) {
            this.font = font;
            this.count = count;
            this.fontData = fontData;
        }
    }

}