
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