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

com.adobe.fontengine.inlineformatting.css20.CSS20FontSelector Maven / Gradle / Ivy

/*
*
*	File: CSS20FontSelector.java
*
*
*	ADOBE CONFIDENTIAL
*	___________________
*
*	Copyright 2004-2005 Adobe Systems Incorporated
*	All Rights Reserved.
*
*	NOTICE: All information contained herein is, and remains the property of
*	Adobe Systems Incorporated and its suppliers, if any. The intellectual
*	and technical concepts contained herein are proprietary to Adobe Systems
*	Incorporated and its suppliers and may be covered by U.S. and Foreign
*	Patents, patents in process, and are protected by trade secret or
*	copyright law. Dissemination of this information or reproduction of this
*	material is strictly forbidden unless prior written permission is obtained
*	from Adobe Systems Incorporated.
*
*/
package com.adobe.fontengine.inlineformatting.css20;


import java.util.Iterator;
import java.util.List;

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.infontformatting.InFontFormatter;

/** The font selection part of {@link com.adobe.fontengine.inlineformatting.PDF16RichTextFormatter}.
 */
final public class CSS20FontSelector
{
    
    final private 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)
        {
            CSS20Attribute attributes = (CSS20Attribute) run.getElementStyle(start, ElementAttribute.CSS20Attribute);
            SelectedFont selectedFont = null;
            try
            {
                selectedFont = selectFont(attributes, run, start, limit, lastFontUsed, lastFontDataUsed);
            } catch (FontException e)
            {
                throw new FormattingException ("Font problem found during formatting", e, start, limit);
            }
            
            // XXX_sgill - just advance by 1?  should we signal an error condition?
            int 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()));
            
            // set the italic, oblique, and small-cap tags
            { 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;
        } // while (start < limit)
        
        return limit;
    }
    
    private SelectedFont selectFont (CSS20Attribute attributes, 
                                       AttributedRun run, int start, int limit,
                                       Font lastFontUsed, FontData lastFontDataUsed)
    throws FontException {
      
      List fontFamilyList = attributes.getFamilyNamesList ();
      fontDB.replaceGenericFontFamily (fontFamilyList);
      
      
      // First - search using the family list
      // These are font names and need to be matched
      for (int i = 0; i < fontFamilyList.size(); i++) {
        String familyName = (String) fontFamilyList.get (i);
        Font[] proposedFonts = fontDB.findFont(familyName, attributes);
        if (proposedFonts != null) {

            // loop over all possible proposed fonts
            for (int j = 0; j < proposedFonts.length; j++) {
              try {
                FontData fontData = ((proposedFonts[j] == lastFontUsed) ? lastFontDataUsed : ((FontImpl) proposedFonts[j]).getFontData ());
                int count = InFontFormatter.canRenderWithFont(fontData, run, start, limit);
                if (count != 0) {
                  return new SelectedFont (proposedFonts[j], count, fontData); }}
              catch (FontException e) {
                e.initFont(proposedFonts[j]);
                throw e; }}}}
      
      // Second, if no font selected, use the locale specific fallback fonts
      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 ());
        int count;
        
        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); }
        else if (! it.hasNext ()) {
          return new SelectedFont (proposedFont, InFontFormatter.canRenderWithNotdef (run, start, limit), proposedFontData); }}
        
      return new SelectedFont (null, 0, null);
    }

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




© 2015 - 2025 Weber Informatics LLC | Privacy Policy