From: Jeremias Maerki Date: Thu, 8 Nov 2007 15:13:24 +0000 (+0000) Subject: Improved font auto-detection and handling of AWT-supplied fonts in order to achieve... X-Git-Tag: fop-0_95beta~303 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=11aa26d46621bd6e74143124868eb22906514677;p=xmlgraphics-fop.git Improved font auto-detection and handling of AWT-supplied fonts in order to achieve better results when using multiple output formats. Whenever possible, the font names appearing in the operating system can also be used in XSL-FO. Better distinction between Font Family Name ("Arial"), Full Font Name ("Arial Bold") and PostScript Name ("Arial-BoldMT"). This allows a better generation of FontTriplets. The same is done for AWT fonts where I have switch from font-family detection to enumerating all java.awt.Font instances so I can extract Family Name, Full Name and PostScript Name. FontInfoFinder and AWT's FontSetup are synchronized as well as possible at this time. Register "extra-bold" (weight 800) and "light" (weight 200) in triplets when detected. Tweaked FontInfo.fontLookup() for better fallback behaviour. This approach is rapidly nearing its flexibility limits. We should rethink the FontTriplet structure. Fixed font-autodetection so fonts with uppercase extensions are detected, too. Made the way TrueType fonts are embedded in PDF compliant to the specification so viewers correctly identify subset fonts. The name prefix in MultiByteFont was incorrect. Support the detection of the special Type 1 Symbol font. Symbol used to be detected with "ExpertSubsetEncoding" instead of "SymbolEncoding". Type1FontLoader tries to construct a "full name" from the PostScript name. This is a temporary hack until we have a PFB or PFA parser. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@593189 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/codegen/fonts/Courier.xml b/src/codegen/fonts/Courier.xml index 89c7314db..be977e22e 100644 --- a/src/codegen/fonts/Courier.xml +++ b/src/codegen/fonts/Courier.xml @@ -18,6 +18,8 @@ Courier + Courier + Courier Courier StandardEncoding 562 diff --git a/src/codegen/fonts/CourierBold.xml b/src/codegen/fonts/CourierBold.xml index 92a777a50..fa8bed196 100644 --- a/src/codegen/fonts/CourierBold.xml +++ b/src/codegen/fonts/CourierBold.xml @@ -18,6 +18,8 @@ Courier-Bold + Courier Bold + Courier CourierBold StandardEncoding 562 diff --git a/src/codegen/fonts/CourierBoldOblique.xml b/src/codegen/fonts/CourierBoldOblique.xml index 914fdab84..5bd26092e 100644 --- a/src/codegen/fonts/CourierBoldOblique.xml +++ b/src/codegen/fonts/CourierBoldOblique.xml @@ -18,6 +18,8 @@ Courier-BoldOblique + Courier Bold Oblique + Courier CourierBoldOblique StandardEncoding 562 diff --git a/src/codegen/fonts/CourierOblique.xml b/src/codegen/fonts/CourierOblique.xml index 3b043c17c..2dc300645 100644 --- a/src/codegen/fonts/CourierOblique.xml +++ b/src/codegen/fonts/CourierOblique.xml @@ -18,6 +18,8 @@ Courier-Oblique + Courier Oblique + Courier CourierOblique StandardEncoding 562 diff --git a/src/codegen/fonts/Helvetica.xml b/src/codegen/fonts/Helvetica.xml index d63eb5a11..38ae23055 100644 --- a/src/codegen/fonts/Helvetica.xml +++ b/src/codegen/fonts/Helvetica.xml @@ -18,6 +18,8 @@ Helvetica + Helvetica + Helvetica Helvetica StandardEncoding 718 diff --git a/src/codegen/fonts/HelveticaBold.xml b/src/codegen/fonts/HelveticaBold.xml index c417937b4..2620a128e 100644 --- a/src/codegen/fonts/HelveticaBold.xml +++ b/src/codegen/fonts/HelveticaBold.xml @@ -18,6 +18,8 @@ Helvetica-Bold + Helvetica Bold + Helvetica HelveticaBold StandardEncoding 718 diff --git a/src/codegen/fonts/HelveticaBoldOblique.xml b/src/codegen/fonts/HelveticaBoldOblique.xml index 087b225e4..c11e0ba18 100644 --- a/src/codegen/fonts/HelveticaBoldOblique.xml +++ b/src/codegen/fonts/HelveticaBoldOblique.xml @@ -18,6 +18,8 @@ Helvetica-BoldOblique + Helvetica Bold Oblique + Helvetica HelveticaBoldOblique StandardEncoding 718 diff --git a/src/codegen/fonts/HelveticaOblique.xml b/src/codegen/fonts/HelveticaOblique.xml index d913b6d51..7f651a5d9 100644 --- a/src/codegen/fonts/HelveticaOblique.xml +++ b/src/codegen/fonts/HelveticaOblique.xml @@ -18,6 +18,8 @@ Helvetica-Oblique + Helvetica Oblique + Helvetica HelveticaOblique StandardEncoding 718 diff --git a/src/codegen/fonts/Symbol.xml b/src/codegen/fonts/Symbol.xml index 241d4d2c6..90685eb5b 100644 --- a/src/codegen/fonts/Symbol.xml +++ b/src/codegen/fonts/Symbol.xml @@ -17,6 +17,8 @@ Symbol + Symbol + Symbol Symbol SymbolEncoding 1010 diff --git a/src/codegen/fonts/TimesBold.xml b/src/codegen/fonts/TimesBold.xml index 12bb17580..20d50fdd8 100644 --- a/src/codegen/fonts/TimesBold.xml +++ b/src/codegen/fonts/TimesBold.xml @@ -18,6 +18,8 @@ Times-Bold + Times Bold + Times TimesBold StandardEncoding 676 diff --git a/src/codegen/fonts/TimesBoldItalic.xml b/src/codegen/fonts/TimesBoldItalic.xml index 540e891e1..d1b70872a 100644 --- a/src/codegen/fonts/TimesBoldItalic.xml +++ b/src/codegen/fonts/TimesBoldItalic.xml @@ -18,6 +18,8 @@ Times-BoldItalic + Times Bold Italic + Times TimesBoldItalic StandardEncoding 669 diff --git a/src/codegen/fonts/TimesItalic.xml b/src/codegen/fonts/TimesItalic.xml index 4868aed05..514aaa6dd 100644 --- a/src/codegen/fonts/TimesItalic.xml +++ b/src/codegen/fonts/TimesItalic.xml @@ -18,6 +18,8 @@ Times-Italic + Times Italic + Times TimesItalic StandardEncoding 653 diff --git a/src/codegen/fonts/TimesRoman.xml b/src/codegen/fonts/TimesRoman.xml index 1f21290de..9ddadfddd 100644 --- a/src/codegen/fonts/TimesRoman.xml +++ b/src/codegen/fonts/TimesRoman.xml @@ -18,6 +18,8 @@ Times-Roman + Times Roman + Times TimesRoman StandardEncoding 662 diff --git a/src/codegen/fonts/ZapfDingbats.xml b/src/codegen/fonts/ZapfDingbats.xml index 0420908a0..f6ed76d25 100644 --- a/src/codegen/fonts/ZapfDingbats.xml +++ b/src/codegen/fonts/ZapfDingbats.xml @@ -17,6 +17,8 @@ ZapfDingbats + ITC Zapf Dingbats + ZapfDingbats ZapfDingbats ZapfDingbatsEncoding 820 diff --git a/src/codegen/fonts/font-file.xsl b/src/codegen/fonts/font-file.xsl index 94dfa7b4c..316d8a784 100644 --- a/src/codegen/fonts/font-file.xsl +++ b/src/codegen/fonts/font-file.xsl @@ -45,6 +45,8 @@ import org.apache.fop.fonts.CodePointMapping; public class extends Typeface { private final static String fontName = ""; + private final static String fullName = ""; + private final static String familyName = ""; private final static String encoding = ""null; private final static int capHeight = ; private final static int xHeight = ; @@ -88,6 +90,18 @@ public class extends Typeface { return fontName; } + public String getEmbedFontName() { + return getFontName(); + } + + public String getFullName() { + return fullName; + } + + public String getFamilyName() { + return familyName; + } + public FontType getFontType() { return FontType.TYPE1; } diff --git a/src/java/org/apache/fop/fonts/CIDFont.java b/src/java/org/apache/fop/fonts/CIDFont.java index f31d00bb9..69f9704ff 100644 --- a/src/java/org/apache/fop/fonts/CIDFont.java +++ b/src/java/org/apache/fop/fonts/CIDFont.java @@ -47,12 +47,6 @@ public abstract class CIDFont extends CustomFont { public int width[] = null; // ---- Required ---- - /** - * Returns the name of the base font. - * @return the name of the base font - */ - public abstract String getCidBaseFont(); - /** * Returns the type of the CID font. * @return the type of the CID font diff --git a/src/java/org/apache/fop/fonts/CustomFont.java b/src/java/org/apache/fop/fonts/CustomFont.java index 916597746..8e2bb918e 100644 --- a/src/java/org/apache/fop/fonts/CustomFont.java +++ b/src/java/org/apache/fop/fonts/CustomFont.java @@ -31,6 +31,8 @@ public abstract class CustomFont extends Typeface implements FontDescriptor, MutableFont { private String fontName = null; + private String fullName = null; + private String familyName = null; private String fontSubName = null; private String embedFileName = null; private String embedResourceName = null; @@ -53,19 +55,27 @@ public abstract class CustomFont extends Typeface private boolean useKerning = true; - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getFontName() { return fontName; } + /** {@inheritDoc} */ + public String getEmbedFontName() { + return getFontName(); + } + + /** {@inheritDoc} */ + public String getFullName() { + return fullName; + } + /** * Return the font family. * @return the font family */ - public String getFontFamily() { - return fontName; + public String getFamilyName() { + return familyName; } /** @@ -74,7 +84,7 @@ public abstract class CustomFont extends Typeface * @see FontUtil#stripWhiteSpace(String) */ public String getStrippedFontName() { - return FontUtil.stripWhiteSpace(fontName); + return FontUtil.stripWhiteSpace(getFontName()); } /** @@ -103,7 +113,10 @@ public abstract class CustomFont extends Typeface Source result = null; if (resolver != null && embedFileName != null) { result = resolver.resolve(embedFileName); - if(result == null) throw new IOException("Unable to resolve Source '" + embedFileName + "' for embedded font"); + if (result == null) { + throw new IOException("Unable to resolve Source '" + + embedFileName + "' for embedded font"); + } } return result; } @@ -256,13 +269,21 @@ public abstract class CustomFont extends Typeface /* ---- MutableFont interface ---- */ - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void setFontName(String name) { this.fontName = name; } + /** {@inheritDoc} */ + public void setFullName(String name) { + this.fullName = name; + } + + /** {@inheritDoc} */ + public void setFamilyName(String name) { + this.familyName = name; + } + /** * Sets the font's subfamily name. * @param subFamilyName the subfamily name of the font diff --git a/src/java/org/apache/fop/fonts/Font.java b/src/java/org/apache/fop/fonts/Font.java index b8e7fa9c8..96aaf80d2 100644 --- a/src/java/org/apache/fop/fonts/Font.java +++ b/src/java/org/apache/fop/fonts/Font.java @@ -19,7 +19,6 @@ package org.apache.fop.fonts; -import java.util.BitSet; import java.util.Map; import org.apache.commons.logging.Log; @@ -31,12 +30,18 @@ import org.apache.commons.logging.LogFactory; */ public class Font { + /** Extra Bold font weight */ + public static final int WEIGHT_EXTRA_BOLD = 800; + /** Bold font weight */ public static final int WEIGHT_BOLD = 700; - + /** Normal font weight */ public static final int WEIGHT_NORMAL = 400; + /** Light font weight */ + public static final int WEIGHT_LIGHT = 200; + /** Normal font style */ public static final String STYLE_NORMAL = "normal"; diff --git a/src/java/org/apache/fop/fonts/FontInfo.java b/src/java/org/apache/fop/fonts/FontInfo.java index 6cea08afd..83bd123eb 100644 --- a/src/java/org/apache/fop/fonts/FontInfo.java +++ b/src/java/org/apache/fop/fonts/FontInfo.java @@ -102,6 +102,9 @@ public class FontInfo { * add the given family, style and weight as a lookup for the font * with the given name */ + if (log.isDebugEnabled()) { + log.debug("Registering: " + triplet + " under " + name); + } this.triplets.put(triplet, name); } @@ -135,55 +138,94 @@ public class FontInfo { if (log.isTraceEnabled()) { log.trace("Font lookup: " + family + " " + style + " " + weight); } - FontTriplet startKey = createFontKey(family, style, weight); + FontTriplet startKey = createFontKey(family, style, weight); FontTriplet key = startKey; // first try given parameters String f = getInternalFontKey(key); if (f == null) { - // then adjust weight, favouring normal or bold - key = findAdjustWeight(family, style, weight); - f = getInternalFontKey(key); + key = doAdjustedLookup(family, style, weight, startKey, substFont); + } - if (!substFont && f == null) { - return null; - } - - // only if the font may be substituted - // fallback 1: try the same font-family and weight with default style - if (f == null) { - key = createFontKey(family, Font.STYLE_NORMAL, weight); - f = getInternalFontKey(key); - } - - // fallback 2: try the same font-family with default style and weight - if (f == null) { - key = createFontKey(family, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); - f = getInternalFontKey(key); + if (key != null) { + if (key != startKey) { + notifyFontReplacement(startKey, key); } - - // fallback 3: try any family with orig style/weight - if (f == null) { - key = createFontKey("any", style, weight); - f = getInternalFontKey(key); + return key; + } else { + return null; + } + } + + private FontTriplet doAdjustedLookup(String family, String style, + int weight, FontTriplet startKey, boolean substFont) { + FontTriplet key; + String f; + if (!family.equals(startKey.getName())) { + key = createFontKey(family, style, weight); + f = getInternalFontKey(key); + if (f != null) { + return key; } + } + + // adjust weight, favouring normal or bold + key = findAdjustWeight(family, style, weight); + f = getInternalFontKey(key); - // last resort: use default - if (f == null) { - key = Font.DEFAULT_FONT; + if (!substFont && f == null) { + return null; + } + + // only if the font may be substituted + // fallback 1: try the same font-family and weight with default style + if (f == null && style != Font.STYLE_NORMAL) { + key = createFontKey(family, Font.STYLE_NORMAL, weight); + f = getInternalFontKey(key); + } + + if (f == null && weight != Font.WEIGHT_NORMAL) { + int diffWeight = (Font.WEIGHT_NORMAL - weight) / 100; + int direction = diffWeight > 0 ? 1 : -1; + int tryWeight = weight; + while (tryWeight != Font.WEIGHT_NORMAL) { + tryWeight += 100 * direction; + key = createFontKey(family, style, weight); f = getInternalFontKey(key); + if (f == null) { + key = createFontKey(family, Font.STYLE_NORMAL, weight); + f = getInternalFontKey(key); + } + if (f != null) { + break; + } } } + + // fallback 2: try the same font-family with default style and weight + /* obsolete: replaced by the loop above + if (f == null) { + key = createFontKey(family, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + f = getInternalFontKey(key); + }*/ + + // fallback 3: try any family with orig style/weight + if (f == null) { + return doAdjustedLookup("any", style, weight, startKey, false); + } + + // last resort: use default + if (f == null) { + key = Font.DEFAULT_FONT; + f = getInternalFontKey(key); + } if (f != null) { - if (key != startKey) { - notifyFontReplacement(startKey, key); - } return key; } else { return null; } } - + /** * Tells this class that the font with the given internal name has been used. * @param internalName the internal font name (F1, F2 etc.) diff --git a/src/java/org/apache/fop/fonts/FontMetrics.java b/src/java/org/apache/fop/fonts/FontMetrics.java index 1a1bd04e4..2c4ada0ae 100644 --- a/src/java/org/apache/fop/fonts/FontMetrics.java +++ b/src/java/org/apache/fop/fonts/FontMetrics.java @@ -28,11 +28,28 @@ import java.util.Map; public interface FontMetrics { /** - * Returns the font name. + * Returns the "PostScript" font name (Example: "Helvetica-BoldOblique"). * @return the font name */ String getFontName(); + /** + * Returns the font's full name (Example: "Helvetica Bold Oblique"). + * @return the font's full name + */ + String getFullName(); + + /** + * Returns the font's family name (Example: "Helvetica"). + * @return the font's family name + */ + String getFamilyName(); + + /** + * Returns the font name for font embedding (may include a prefix, Example: "1E28bcArialMT"). + * @return the name for font embedding + */ + String getEmbedFontName(); /** * Returns the type of the font. diff --git a/src/java/org/apache/fop/fonts/FontReader.java b/src/java/org/apache/fop/fonts/FontReader.java index ccc0c80ba..f276ae995 100644 --- a/src/java/org/apache/fop/fonts/FontReader.java +++ b/src/java/org/apache/fop/fonts/FontReader.java @@ -20,23 +20,20 @@ package org.apache.fop.fonts; //Java +import java.io.IOException; import java.util.List; import java.util.Map; -import java.io.IOException; import javax.xml.parsers.SAXParserFactory; -//SAX -import org.xml.sax.XMLReader; -import org.xml.sax.SAXException; -import org.xml.sax.Locator; -import org.xml.sax.Attributes; -import org.xml.sax.helpers.DefaultHandler; - -//FOP import org.apache.fop.apps.FOPException; import org.apache.fop.fonts.apps.TTFReader; +import org.xml.sax.Attributes; import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; /** * Class for reading a metric.xml file and creating a font object. @@ -229,6 +226,10 @@ public class FontReader extends DefaultHandler { String content = text.toString().trim(); if ("font-name".equals(localName)) { returnFont.setFontName(content); + } else if ("full-name".equals(localName)) { + multiFont.setFullName(content); + } else if ("family-name".equals(localName)) { + multiFont.setFamilyName(content); } else if ("ttc-name".equals(localName) && isCID) { multiFont.setTTCName(content); } else if ("encoding".equals(localName)) { diff --git a/src/java/org/apache/fop/fonts/FontSetup.java b/src/java/org/apache/fop/fonts/FontSetup.java index 0e9501f25..8734856f6 100644 --- a/src/java/org/apache/fop/fonts/FontSetup.java +++ b/src/java/org/apache/fop/fonts/FontSetup.java @@ -20,31 +20,28 @@ package org.apache.fop.fonts; // FOP (base 14 fonts) +import java.util.List; + +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.fonts.base14.Courier; +import org.apache.fop.fonts.base14.CourierBold; +import org.apache.fop.fonts.base14.CourierBoldOblique; +import org.apache.fop.fonts.base14.CourierOblique; import org.apache.fop.fonts.base14.Helvetica; import org.apache.fop.fonts.base14.HelveticaBold; -import org.apache.fop.fonts.base14.HelveticaOblique; import org.apache.fop.fonts.base14.HelveticaBoldOblique; -import org.apache.fop.fonts.base14.TimesRoman; +import org.apache.fop.fonts.base14.HelveticaOblique; +import org.apache.fop.fonts.base14.Symbol; import org.apache.fop.fonts.base14.TimesBold; -import org.apache.fop.fonts.base14.TimesItalic; import org.apache.fop.fonts.base14.TimesBoldItalic; -import org.apache.fop.fonts.base14.Courier; -import org.apache.fop.fonts.base14.CourierBold; -import org.apache.fop.fonts.base14.CourierOblique; -import org.apache.fop.fonts.base14.CourierBoldOblique; -import org.apache.fop.fonts.base14.Symbol; +import org.apache.fop.fonts.base14.TimesItalic; +import org.apache.fop.fonts.base14.TimesRoman; import org.apache.fop.fonts.base14.ZapfDingbats; -// commons logging -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -// Java -import java.util.List; - -import javax.xml.transform.Source; -import javax.xml.transform.stream.StreamSource; - /** * Default fonts for FOP application; currently this uses PDF's fonts * by default. @@ -232,9 +229,6 @@ public class FontSetup { for (int c = 0; c < triplets.size(); c++) { FontTriplet triplet = (FontTriplet) triplets.get(c); - if (log.isDebugEnabled()) { - log.debug("Registering: " + triplet + " under " + internalName); - } fontInfo.addFontProperties(internalName, triplet); } } diff --git a/src/java/org/apache/fop/fonts/FontUtil.java b/src/java/org/apache/fop/fonts/FontUtil.java index 7ca2a0371..b9e891c9c 100644 --- a/src/java/org/apache/fop/fonts/FontUtil.java +++ b/src/java/org/apache/fop/fonts/FontUtil.java @@ -76,5 +76,59 @@ public class FontUtil { return sb.toString(); } + /** font constituent names which identify a font as being of "italic" style */ + private static final String[] ITALIC_WORDS = {"italic", "oblique"}; + + /** font constituent names which identify a font as being of "light" weight */ + private static final String[] LIGHT_WORDS = {"light"}; + /** font constituent names which identify a font as being of "bold" weight */ + private static final String[] BOLD_WORDS = {"bold"}; + /** font constituent names which identify a font as being of "bold" weight */ + private static final String[] EXTRA_BOLD_WORDS = {"extrabold", "black", + "heavy", "ultra", "super"}; + + /** + * Guesses the font style of a font using its name. + * @param fontName the font name + * @return "normal" or "italic" + */ + public static String guessStyle(String fontName) { + for (int i = 0; i < ITALIC_WORDS.length; i++) { + if (fontName.indexOf(ITALIC_WORDS[i]) != -1) { + return Font.STYLE_ITALIC; + } + } + return Font.STYLE_NORMAL; + } + + /** + * Guesses the font weight of a font using its name. + * @param fontName the font name + * @return an integer between 100 and 900 + */ + public static int guessWeight(String fontName) { + // weight + int weight = Font.WEIGHT_NORMAL; + for (int i = 0; i < BOLD_WORDS.length; i++) { + if (fontName.indexOf(BOLD_WORDS[i]) != -1) { + weight = Font.WEIGHT_BOLD; + break; + } + } + for (int i = 0; i < EXTRA_BOLD_WORDS.length; i++) { + if (fontName.indexOf(EXTRA_BOLD_WORDS[i]) != -1) { + weight = Font.WEIGHT_EXTRA_BOLD; + break; + } + } + for (int i = 0; i < LIGHT_WORDS.length; i++) { + if (fontName.indexOf(LIGHT_WORDS[i]) != -1) { + weight = Font.WEIGHT_LIGHT; + break; + } + } + return weight; + } + } diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java index cc8989b7d..45917aeef 100644 --- a/src/java/org/apache/fop/fonts/LazyFont.java +++ b/src/java/org/apache/fop/fonts/LazyFont.java @@ -189,14 +189,30 @@ public class LazyFont extends Typeface implements FontDescriptor { } // ---- FontMetrics interface ---- - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getFontName() { load(true); return realFont.getFontName(); } + /** {@inheritDoc} */ + public String getEmbedFontName() { + load(true); + return realFont.getEmbedFontName(); + } + + /** {@inheritDoc} */ + public String getFullName() { + load(true); + return realFont.getFullName(); + } + + /** {@inheritDoc} */ + public String getFamilyName() { + load(true); + return realFont.getFamilyName(); + } + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fonts/MultiByteFont.java b/src/java/org/apache/fop/fonts/MultiByteFont.java index dcd3bdfa0..e40c40985 100644 --- a/src/java/org/apache/fop/fonts/MultiByteFont.java +++ b/src/java/org/apache/fop/fonts/MultiByteFont.java @@ -20,6 +20,7 @@ package org.apache.fop.fonts; //Java +import java.text.DecimalFormat; import java.util.Map; /** @@ -27,8 +28,8 @@ import java.util.Map; */ public class MultiByteFont extends CIDFont { - private static int uniqueCounter = 1; - + private static int uniqueCounter = -1; + private static final DecimalFormat COUNTER_FORMAT = new DecimalFormat("00000"); private String ttcName = null; private String encoding = "Identity-H"; @@ -54,14 +55,24 @@ public class MultiByteFont extends CIDFont { usedGlyphs.put(new Integer(2), new Integer(2)); usedGlyphsIndex.put(new Integer(2), new Integer(2)); usedGlyphsCount++; - + // Create a quasiunique prefix for fontname - int cnt = 0; synchronized (this.getClass()) { - cnt = uniqueCounter++; + uniqueCounter++; + if (uniqueCounter > 99999 || uniqueCounter < 0) { + uniqueCounter = 0; //We need maximum 5 character then we start again + } } - int ctm = (int)(System.currentTimeMillis() & 0xffff); - namePrefix = new String(cnt + "E" + Integer.toHexString(ctm)); + String cntString = COUNTER_FORMAT.format(uniqueCounter); + + //Subset prefix as described in chapter 5.5.3 of PDF 1.4 + StringBuffer sb = new StringBuffer("E"); + for (int i = 0, c = cntString.length(); i < c; i++) { + //translate numbers to uppercase characters + sb.append((char)(cntString.charAt(i) + (65 - 48))); + } + sb.append("+"); + namePrefix = sb.toString(); setFontType(FontType.TYPE0); } @@ -113,10 +124,8 @@ public class MultiByteFont extends CIDFont { return namePrefix + FontUtil.stripWhiteSpace(super.getFontName()); } - /** - * {@inheritDoc} - */ - public String getCidBaseFont() { + /** {@inheritDoc} */ + public String getEmbedFontName() { if (isEmbeddable()) { return getPrefixedFontName(); } else { @@ -138,17 +147,6 @@ public class MultiByteFont extends CIDFont { return encoding; } - /** - * {@inheritDoc} - */ - public String getFontName() { - if (isEmbeddable()) { - return getPrefixedFontName(); - } else { - return super.getFontName(); - } - } - /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fonts/MutableFont.java b/src/java/org/apache/fop/fonts/MutableFont.java index 3a53d7432..657239dcf 100644 --- a/src/java/org/apache/fop/fonts/MutableFont.java +++ b/src/java/org/apache/fop/fonts/MutableFont.java @@ -28,11 +28,24 @@ import java.util.Map; public interface MutableFont { /** - * Sets the font name. + * Sets the "PostScript" font name (Example: "Helvetica-BoldOblique"). * @param name font name */ void setFontName(String name); + /** + * Sets the font's full name (usually the one that the operating system displays). Example: + * "Helvetica Bold Oblique". + * @param name font' full name + */ + void setFullName(String name); + + /** + * Sets the font's family name (Example: "Helvetica"). + * @param name the font's family name + */ + void setFamilyName(String name); + /** * Sets the path to the embeddable font file. * @param path URI to the file diff --git a/src/java/org/apache/fop/fonts/apps/TTFReader.java b/src/java/org/apache/fop/fonts/apps/TTFReader.java index 4d5cc3942..f7eeb89d7 100644 --- a/src/java/org/apache/fop/fonts/apps/TTFReader.java +++ b/src/java/org/apache/fop/fonts/apps/TTFReader.java @@ -266,6 +266,16 @@ public class TTFReader extends AbstractFontReader { } else { el.appendChild(doc.createTextNode(s)); } + if (ttf.getFullName() != null) { + el = doc.createElement("full-name"); + root.appendChild(el); + el.appendChild(doc.createTextNode(ttf.getFullName())); + } + if (ttf.getFamilyName() != null) { + el = doc.createElement("family-name"); + root.appendChild(el); + el.appendChild(doc.createTextNode(ttf.getFamilyName())); + } el = doc.createElement("embed"); root.appendChild(el); diff --git a/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java index 381572a25..c35faf65d 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java @@ -22,15 +22,15 @@ package org.apache.fop.fonts.autodetect; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; -import java.net.URL; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.apache.commons.io.DirectoryWalker; +import org.apache.commons.io.IOCase; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.IOFileFilter; -import org.apache.commons.io.filefilter.SuffixFileFilter; +import org.apache.commons.io.filefilter.WildcardFileFilter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -78,7 +78,7 @@ public class FontFileFinder extends DirectoryWalker implements FontFinder { protected static IOFileFilter getFileFilter() { return FileFilterUtils.andFileFilter( FileFilterUtils.fileFileFilter(), - new SuffixFileFilter(new String[] {".ttf", ".otf", ".pfb"}) + new WildcardFileFilter(new String[] {"*.ttf", "*.otf", "*.pfb"}, IOCase.INSENSITIVE) //TODO Add *.ttc when support for it has been added to the auto-detection mech. ); } diff --git a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java index bb7e00505..4876a6f1d 100644 --- a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java +++ b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java @@ -19,11 +19,9 @@ package org.apache.fop.fonts.autodetect; -import java.io.File; import java.io.IOException; -import java.net.MalformedURLException; -import java.util.Collection; import java.net.URL; +import java.util.Collection; import java.util.List; import org.apache.commons.logging.Log; @@ -36,6 +34,7 @@ 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 @@ -45,12 +44,6 @@ public class FontInfoFinder { /** logging instance */ private Log log = LogFactory.getLog(FontInfoFinder.class); - /** font constituent names which identify a font as being of "italic" style */ - private static final String[] ITALIC_WORDS = {"italic", "oblique"}; - - /** font constituent names which identify a font as being of "bold" weight */ - private static final String[] BOLD_WORDS = {"bold", "black", "heavy", "ultra", "super"}; - /** * Attempts to determine FontTriplets from a given CustomFont. * It seems to be fairly accurate but will probably require some tweaking over time @@ -67,32 +60,31 @@ public class FontInfoFinder { searchName += subName.toLowerCase(); } + String style = guessStyle(customFont, searchName); + int weight = FontUtil.guessWeight(searchName); + + //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 + String fullName = customFont.getFullName(); + triplets.add(new FontTriplet(fullName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL)); + if (!fullName.equals(strippedName)) { + triplets.add(new FontTriplet(strippedName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL)); + } + String familyName = customFont.getFamilyName(); + if (!fullName.equals(familyName)) { + triplets.add(new FontTriplet(familyName, style, weight)); + } + } + + private String guessStyle(CustomFont customFont, String fontName) { // style String style = Font.STYLE_NORMAL; if (customFont.getItalicAngle() > 0) { style = Font.STYLE_ITALIC; } else { - for (int i = 0; i < ITALIC_WORDS.length; i++) { - if (searchName.indexOf(ITALIC_WORDS[i]) != -1) { - style = Font.STYLE_ITALIC; - break; - } - } - } - - // weight - int weight = Font.WEIGHT_NORMAL; - for (int i = 0; i < BOLD_WORDS.length; i++) { - if (searchName.indexOf(BOLD_WORDS[i]) != -1) { - weight = Font.WEIGHT_BOLD; - break; - } - } - triplets.add(new FontTriplet(strippedName, style, weight)); - String familyName = customFont.getFontFamily(); - if (!strippedName.equals(familyName)) { - triplets.add(new FontTriplet(familyName, style, weight)); + style = FontUtil.guessStyle(fontName); } + return style; } /** diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFile.java b/src/java/org/apache/fop/fonts/truetype/TTFFile.java index 4142b0444..b40202b7f 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFile.java @@ -21,8 +21,8 @@ package org.apache.fop.fonts.truetype; import java.io.IOException; import java.util.Iterator; -import java.util.Map; import java.util.List; +import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -74,7 +74,7 @@ public class TTFFile { protected TTFMtxEntry[] mtxTab; // Contains glyph data private int[] mtxEncoded = null; - private String fontName = ""; + private String postScriptName = ""; private String fullName = ""; private String notice = ""; private String familyName = ""; @@ -550,11 +550,14 @@ public class TTFFile { * @return String The PostScript name */ public String getPostScriptName() { + return postScriptName; + /* if ("Regular".equals(subFamilyName) || "Roman".equals(subFamilyName)) { return familyName; } else { return familyName + "," + subFamilyName; } + */ } /** @@ -573,6 +576,14 @@ public class TTFFile { return subFamilyName; } + /** + * Returns the full name of the font. + * @return String The full name + */ + public String getFullName() { + return fullName; + } + /** * Returns the name of the character set used. * @return String The caracter set @@ -1111,10 +1122,12 @@ public class TTFFile { in.seekSet(j + in.readTTFUShort()); String txt = in.readTTFString(l); - log.debug(platformID + " " - + encodingID + " " - + languageID + " " - + k + " " + txt); + if (log.isDebugEnabled()) { + log.debug(platformID + " " + + encodingID + " " + + languageID + " " + + k + " " + txt); + } switch (k) { case 0: notice = txt; @@ -1129,12 +1142,12 @@ public class TTFFile { fullName = txt; break; case 6: - fontName = txt; + postScriptName = txt; break; } if (!notice.equals("") && !fullName.equals("") - && !fontName.equals("") + && !postScriptName.equals("") && !familyName.equals("") && !subFamilyName.equals("")) { break; @@ -1440,7 +1453,7 @@ public class TTFFile { notice = ""; fullName = ""; familyName = ""; - fontName = ""; + postScriptName = ""; subFamilyName = ""; } @@ -1470,7 +1483,7 @@ public class TTFFile { * Dumps a few informational values to System.out. */ public void printStuff() { - System.out.println("Font name: " + fontName); + System.out.println("Font name: " + postScriptName); System.out.println("Full name: " + fullName); System.out.println("Family name: " + familyName); System.out.println("Subfamily name: " + subFamilyName); diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java index a7de26b75..b179bd8fe 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java @@ -66,7 +66,9 @@ public class TTFFontLoader extends FontLoader { multiFont.setResolver(this.resolver); returnFont = multiFont; - returnFont.setFontName(ttf.getFamilyName()); + returnFont.setFontName(ttf.getPostScriptName()); + returnFont.setFullName(ttf.getFullName()); + returnFont.setFamilyName(ttf.getFamilyName()); returnFont.setFontSubFamilyName(ttf.getSubFamilyName()); //multiFont.setTTCName(ttcName) returnFont.setCapHeight(ttf.getCapHeight()); diff --git a/src/java/org/apache/fop/fonts/type1/PFMFile.java b/src/java/org/apache/fop/fonts/type1/PFMFile.java index 8818f1a73..490e9da90 100644 --- a/src/java/org/apache/fop/fonts/type1/PFMFile.java +++ b/src/java/org/apache/fop/fonts/type1/PFMFile.java @@ -28,9 +28,6 @@ import java.util.Map; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - - -// FOP import org.apache.fop.fonts.Glyphs; /** @@ -190,8 +187,8 @@ public class PFMFile { int i = inStream.readShort(); - if (log.isDebugEnabled()) { - log.debug(i + " kerning pairs"); + if (log.isTraceEnabled()) { + log.trace(i + " kerning pairs"); } while (i > 0) { int g1 = (int)inStream.readByte(); @@ -204,11 +201,11 @@ public class PFMFile { adj = -(0x10000 - adj); } - if (log.isDebugEnabled()) { - log.debug("Char no: (" + g1 + ", " + g2 + ") kern: " + adj); + if (log.isTraceEnabled()) { + log.trace("Char no: (" + g1 + ", " + g2 + ") kern: " + adj); final String glyph1 = Glyphs.TEX8R_GLYPH_NAMES[g1]; final String glyph2 = Glyphs.TEX8R_GLYPH_NAMES[g2]; - log.debug("glyphs: " + glyph1 + ", " + glyph2); + log.trace("glyphs: " + glyph1 + ", " + glyph2); } Map adjTab = (Map)kerningTab.get(new Integer(g1)); @@ -306,7 +303,11 @@ public class PFMFile { case 1: return "Expert"; case 2: - return "ExpertSubset"; + if ("Symbol".equals(getPostscriptName())) { + return "Symbol"; + } else { + return "ExpertSubset"; + } case 128: return "Shift-JIS (Japanese)"; default: diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java index 56d1b4cfb..a8f8b7613 100644 --- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java +++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java @@ -55,9 +55,15 @@ public class Type1FontLoader extends FontLoader { pfm.load(in); singleFont = new SingleByteFont(); singleFont.setFontType(FontType.TYPE1); + singleFont.setEncoding(pfm.getCharSetName() + "Encoding"); singleFont.setResolver(this.resolver); returnFont = singleFont; returnFont.setFontName(pfm.getPostscriptName()); + String fullName = pfm.getPostscriptName(); + fullName = fullName.replace('-', ' '); //Hack! Try to emulate full name + returnFont.setFullName(fullName); //should be afm.getFullName()!! + //TODO not accurate: we need FullName from the AFM file but we don't have an AFM parser + returnFont.setFamilyName(pfm.getWindowsName()); //should be afm.getFamilyName()!! returnFont.setCapHeight(pfm.getCapHeight()); returnFont.setXHeight(pfm.getXHeight()); returnFont.setAscender(pfm.getLowerCaseAscent()); diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index f2fe97139..e1546baed 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -26,29 +26,27 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; +import java.util.ArrayList; import java.util.BitSet; import java.util.Iterator; import java.util.List; import java.util.Map; + import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; -import java.util.ArrayList; -// Apache libs import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - -// FOP import org.apache.fop.fonts.CIDFont; import org.apache.fop.fonts.CustomFont; -import org.apache.fop.fonts.Typeface; import org.apache.fop.fonts.FontDescriptor; import org.apache.fop.fonts.FontMetrics; import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.LazyFont; import org.apache.fop.fonts.MultiByteFont; +import org.apache.fop.fonts.Typeface; import org.apache.fop.fonts.truetype.FontFileReader; import org.apache.fop.fonts.truetype.TTFSubSetFile; import org.apache.fop.fonts.type1.PFBData; @@ -1270,7 +1268,7 @@ public class PDFFactory { if (desc.getFontType() == FontType.TYPE0) { // CID Font - descriptor = new PDFCIDFontDescriptor(desc.getFontName(), + descriptor = new PDFCIDFontDescriptor(desc.getEmbedFontName(), desc.getFontBBox(), desc.getCapHeight(), desc.getFlags(), @@ -1278,7 +1276,7 @@ public class PDFFactory { desc.getStemV(), null); } else { // Create normal FontDescriptor - descriptor = new PDFFontDescriptor(desc.getFontName(), + descriptor = new PDFFontDescriptor(desc.getEmbedFontName(), desc.getAscender(), desc.getDescender(), desc.getCapHeight(), @@ -1333,7 +1331,7 @@ public class PDFFactory { } catch (IOException ioe) { log.error( "Failed to write CIDSet [" + cidFont + "] " - + cidFont.getFontName(), ioe); + + cidFont.getEmbedFontName(), ioe); } } @@ -1422,7 +1420,7 @@ public class PDFFactory { } catch (IOException ioe) { log.error( "Failed to embed font [" + desc + "] " - + desc.getFontName(), ioe); + + desc.getEmbedFontName(), ioe); return (PDFStream) null; } } diff --git a/src/java/org/apache/fop/pdf/PDFResources.java b/src/java/org/apache/fop/pdf/PDFResources.java index d9420946a..66ccdc78b 100644 --- a/src/java/org/apache/fop/pdf/PDFResources.java +++ b/src/java/org/apache/fop/pdf/PDFResources.java @@ -110,7 +110,7 @@ public class PDFResources extends PDFObject { desc = (FontDescriptor)font; } addFont(doc.getFactory().makeFont( - f, font.getFontName(), font.getEncoding(), font, desc)); + f, font.getEmbedFontName(), font.getEncoding(), font, desc)); } } } diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFont.java b/src/java/org/apache/fop/render/afp/fonts/AFPFont.java index cca5e4d74..104ba84b1 100644 --- a/src/java/org/apache/fop/render/afp/fonts/AFPFont.java +++ b/src/java/org/apache/fop/render/afp/fonts/AFPFont.java @@ -19,35 +19,48 @@ package org.apache.fop.render.afp.fonts; import java.util.Map; + import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.Typeface; /** - * All implemenations of AFP fonts should extend this base class, + * All implementations of AFP fonts should extend this base class, * the object implements the FontMetrics information. *

*/ public abstract class AFPFont extends Typeface { /** The font name */ - protected String _name; + protected String name; /** * Constructor for the base font requires the name. * @param name the name of the font */ public AFPFont(String name) { - - _name = name; + this.name = name; } - /** - * @return the name of the font. - */ + /** {@inheritDoc} */ public String getFontName() { - return _name; + return this.name; + } + + /** {@inheritDoc} */ + public String getEmbedFontName() { + return this.name; + } + + /** {@inheritDoc} */ + public String getFullName() { + return getFontName(); + } + + /** {@inheritDoc} */ + public String getFamilyName() { + return getFamilyName(); } /** @@ -59,7 +72,7 @@ public abstract class AFPFont extends Typeface { } /** - * Indicates if the font has kering information. + * Indicates if the font has kerning information. * @return True, if kerning is available. */ public boolean hasKerningInfo() { @@ -84,7 +97,7 @@ public abstract class AFPFont extends Typeface { /** * Determines whether this font contains a particular character/glyph. * @param c character to check - * @return True if the character is supported, Falso otherwise + * @return True if the character is supported, False otherwise */ public boolean hasChar(char c) { return true; diff --git a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java index 879f35769..8aee59b26 100644 --- a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java +++ b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java @@ -92,13 +92,13 @@ public class RasterFont extends AFPFont { } if (csm != null) { _characterSets.put(size + "mpt", csm); - String msg = "No " + (size / 1000) + "pt font " + _name + String msg = "No " + (size / 1000) + "pt font " + getFontName() + " found, substituted with " + pointsize + "pt font"; log.warn(msg); } } if (csm == null) { - String msg = "No font found for font " + _name + String msg = "No font found for font " + getFontName() + " with point size " + pointsize; log.error(msg); throw new FontRuntimeException(msg); @@ -117,7 +117,7 @@ public class RasterFont extends AFPFont { CharacterSet csm = (CharacterSet) i.next(); return csm.getFirstChar(); } else { - String msg = "getFirstChar() - No character set found for font:" + _name; + String msg = "getFirstChar() - No character set found for font:" + getFontName(); log.error(msg); throw new FontRuntimeException(msg); } @@ -134,7 +134,7 @@ public class RasterFont extends AFPFont { CharacterSet csm = (CharacterSet) i.next(); return csm.getLastChar(); } else { - String msg = "getLastChar() - No character set found for font:" + _name; + String msg = "getLastChar() - No character set found for font:" + getFontName(); log.error(msg); throw new FontRuntimeException(msg); } diff --git a/src/java/org/apache/fop/render/java2d/FontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/FontMetricsMapper.java index 67476b46a..f5f92f741 100644 --- a/src/java/org/apache/fop/render/java2d/FontMetricsMapper.java +++ b/src/java/org/apache/fop/render/java2d/FontMetricsMapper.java @@ -23,7 +23,6 @@ package org.apache.fop.render.java2d; import java.awt.Graphics2D; import java.util.Map; -// FOP import org.apache.fop.fonts.FontMetrics; import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.Typeface; @@ -72,13 +71,26 @@ public class FontMetricsMapper extends Typeface implements FontMetrics { } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public String getFontName() { return family; } + /** {@inheritDoc} */ + public String getEmbedFontName() { + return getFontName(); + } + + /** {@inheritDoc} */ + public String getFullName() { + return getFontName(); + } + + /** {@inheritDoc} */ + public String getFamilyName() { + return getFontName(); + } + /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/render/java2d/FontSetup.java b/src/java/org/apache/fop/render/java2d/FontSetup.java index e1dffd0e7..df6e4a0de 100644 --- a/src/java/org/apache/fop/render/java2d/FontSetup.java +++ b/src/java/org/apache/fop/render/java2d/FontSetup.java @@ -20,16 +20,16 @@ package org.apache.fop.render.java2d; // FOP +import java.awt.Graphics2D; +import java.awt.GraphicsEnvironment; +import java.util.Set; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; - -// Java -import java.awt.Graphics2D; -import java.awt.GraphicsEnvironment; -import java.util.Set; +import org.apache.fop.fonts.FontUtil; /** * Sets up the Java2D/AWT fonts. It is similar to @@ -214,54 +214,57 @@ public class FontSetup { int startNumber) { int num = startNumber; GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); - String[] allFontFamilies = env.getAvailableFontFamilyNames(); - for (int i = 0; i < allFontFamilies.length; i++) { - String family = allFontFamilies[i]; - if (HARDCODED_FONT_NAMES.contains(family)) { + + java.awt.Font[] fonts = env.getAllFonts(); + for (int i = 0; i < fonts.length; i++) { + java.awt.Font f = fonts[i]; + if (HARDCODED_FONT_NAMES.contains(f.getFontName())) { continue; //skip } - - if (log.isDebugEnabled()) { - log.debug("Registering: " + family); - } - //Java does not give info about what variants of a font is actually supported, so - //we simply register all the basic variants. If we use GraphicsEnvironment.getAllFonts() - //we don't get reliable info whether a font is italic or bold or both. - int fontStyle; - fontStyle = java.awt.Font.PLAIN; - registerFontTriplet(fontInfo, family, fontStyle, "F" + num, graphics); - num++; + String searchName = FontUtil.stripWhiteSpace(f.getFontName()).toLowerCase(); + String guessedStyle = FontUtil.guessStyle(searchName); + int guessedWeight = FontUtil.guessWeight(searchName); - fontStyle = java.awt.Font.ITALIC; - registerFontTriplet(fontInfo, family, fontStyle, "F" + num, graphics); num++; + String fontKey = "F" + num; + int style = convertToAWTFontStyle(guessedStyle, guessedWeight); + addFontMetricsMapper(fontInfo, f.getFontName(), fontKey, graphics, style); + + //Register appropriate font triplets matching the font. Two different strategies: + //Example: "Arial Bold", normal, normal + addFontTriplet(fontInfo, f.getFontName(), + Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, fontKey); + if (!f.getFontName().equals(f.getFamily())) { + //Example: "Arial", bold, normal + addFontTriplet(fontInfo, f.getFamily(), + guessedStyle, guessedWeight, fontKey); + } + } - fontStyle = java.awt.Font.BOLD; - registerFontTriplet(fontInfo, family, fontStyle, "F" + num, graphics); - num++; + } - fontStyle = java.awt.Font.BOLD | java.awt.Font.ITALIC; - registerFontTriplet(fontInfo, family, fontStyle, "F" + num, graphics); - num++; - } + private static void addFontTriplet(FontInfo fontInfo, String fontName, String fontStyle, + int fontWeight, String fontKey) { + FontTriplet triplet = FontInfo.createFontKey(fontName, fontStyle, fontWeight); + fontInfo.addFontProperties(fontKey, triplet); } - private static void registerFontTriplet(FontInfo fontInfo, String family, int fontStyle, - String fontKey, Graphics2D graphics) { - FontMetricsMapper metric = new FontMetricsMapper(family, fontStyle, graphics); + private static void addFontMetricsMapper(FontInfo fontInfo, String family, String fontKey, + Graphics2D graphics, int style) { + FontMetricsMapper metric = new FontMetricsMapper(family, style, graphics); fontInfo.addMetrics(fontKey, metric); - - int weight = Font.WEIGHT_NORMAL; - if ((fontStyle & java.awt.Font.BOLD) != 0) { - weight = Font.WEIGHT_BOLD; + } + + private static int convertToAWTFontStyle(String fontStyle, int fontWeight) { + int style = java.awt.Font.PLAIN; + if (fontWeight >= Font.WEIGHT_BOLD) { + style |= java.awt.Font.BOLD; } - String style = "normal"; - if ((fontStyle & java.awt.Font.ITALIC) != 0) { - style = "italic"; + if (!"normal".equals(fontStyle)) { + style |= java.awt.Font.ITALIC; } - FontTriplet triplet = FontInfo.createFontKey(family, style, weight); - fontInfo.addFontProperties(fontKey, triplet); + return style; } } diff --git a/status.xml b/status.xml index ec3b80a3e..c11a43074 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,20 @@ + + Made the way TrueType fonts are embedded in PDF compliant to the + specification so viewers correctly identify subset fonts. + + + Fixed font-autodetection so fonts with uppercase extensions are + detected, too. + + + Improved font auto-detection and handling of AWT-supplied fonts in order + to achieve better results when using multiple output formats. Whenever + possible, the font names appearing in the operating system can also + be used in XSL-FO. + Fixed regression: transparent-page-background was not recognized for PNG output.