<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
<font-metrics>
<font-name>Courier</font-name>
+ <full-name>Courier</full-name>
+ <family-name>Courier</family-name>
<class-name>Courier</class-name>
<encoding>StandardEncoding</encoding>
<cap-height>562</cap-height>
<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
<font-metrics>
<font-name>Courier-Bold</font-name>
+ <full-name>Courier Bold</full-name>
+ <family-name>Courier</family-name>
<class-name>CourierBold</class-name>
<encoding>StandardEncoding</encoding>
<cap-height>562</cap-height>
<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
<font-metrics>
<font-name>Courier-BoldOblique</font-name>
+ <full-name>Courier Bold Oblique</full-name>
+ <family-name>Courier</family-name>
<class-name>CourierBoldOblique</class-name>
<encoding>StandardEncoding</encoding>
<cap-height>562</cap-height>
<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
<font-metrics>
<font-name>Courier-Oblique</font-name>
+ <full-name>Courier Oblique</full-name>
+ <family-name>Courier</family-name>
<class-name>CourierOblique</class-name>
<encoding>StandardEncoding</encoding>
<cap-height>562</cap-height>
<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
<font-metrics>
<font-name>Helvetica</font-name>
+ <full-name>Helvetica</full-name>
+ <family-name>Helvetica</family-name>
<class-name>Helvetica</class-name>
<encoding>StandardEncoding</encoding>
<cap-height>718</cap-height>
<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
<font-metrics>
<font-name>Helvetica-Bold</font-name>
+ <full-name>Helvetica Bold</full-name>
+ <family-name>Helvetica</family-name>
<class-name>HelveticaBold</class-name>
<encoding>StandardEncoding</encoding>
<cap-height>718</cap-height>
<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
<font-metrics>
<font-name>Helvetica-BoldOblique</font-name>
+ <full-name>Helvetica Bold Oblique</full-name>
+ <family-name>Helvetica</family-name>
<class-name>HelveticaBoldOblique</class-name>
<encoding>StandardEncoding</encoding>
<cap-height>718</cap-height>
<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
<font-metrics>
<font-name>Helvetica-Oblique</font-name>
+ <full-name>Helvetica Oblique</full-name>
+ <family-name>Helvetica</family-name>
<class-name>HelveticaOblique</class-name>
<encoding>StandardEncoding</encoding>
<cap-height>718</cap-height>
<!-- $Id$ -->
<font-metrics>
<font-name>Symbol</font-name>
+ <full-name>Symbol</full-name>
+ <family-name>Symbol</family-name>
<class-name>Symbol</class-name>
<encoding>SymbolEncoding</encoding>
<cap-height>1010</cap-height>
<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
<font-metrics>
<font-name>Times-Bold</font-name>
+ <full-name>Times Bold</full-name>
+ <family-name>Times</family-name>
<class-name>TimesBold</class-name>
<encoding>StandardEncoding</encoding>
<cap-height>676</cap-height>
<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
<font-metrics>
<font-name>Times-BoldItalic</font-name>
+ <full-name>Times Bold Italic</full-name>
+ <family-name>Times</family-name>
<class-name>TimesBoldItalic</class-name>
<encoding>StandardEncoding</encoding>
<cap-height>669</cap-height>
<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
<font-metrics>
<font-name>Times-Italic</font-name>
+ <full-name>Times Italic</full-name>
+ <family-name>Times</family-name>
<class-name>TimesItalic</class-name>
<encoding>StandardEncoding</encoding>
<cap-height>653</cap-height>
<!-- JKT: these metrics in XML were kindly produced by Fotis Jannidis -->
<font-metrics>
<font-name>Times-Roman</font-name>
+ <full-name>Times Roman</full-name>
+ <family-name>Times</family-name>
<class-name>TimesRoman</class-name>
<encoding>StandardEncoding</encoding>
<cap-height>662</cap-height>
<!-- $Id$ -->
<font-metrics>
<font-name>ZapfDingbats</font-name>
+ <full-name>ITC Zapf Dingbats</full-name>
+ <family-name>ZapfDingbats</family-name>
<class-name>ZapfDingbats</class-name>
<encoding>ZapfDingbatsEncoding</encoding>
<cap-height>820</cap-height>
public class <xsl:value-of select="class-name"/> extends Typeface {
private final static String fontName = "<xsl:value-of select="font-name"/>";
+ private final static String fullName = "<xsl:value-of select="full-name"/>";
+ private final static String familyName = "<xsl:value-of select="family-name"/>";
private final static String encoding = <xsl:choose><xsl:when test="$encoding != $native-encoding">"<xsl:value-of select="$encoding"/>"</xsl:when><xsl:otherwise>null</xsl:otherwise></xsl:choose>;
private final static int capHeight = <xsl:value-of select="cap-height"/>;
private final static int xHeight = <xsl:value-of select="x-height"/>;
return fontName;
}
+ public String getEmbedFontName() {
+ return getFontName();
+ }
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public String getFamilyName() {
+ return familyName;
+ }
+
public FontType getFontType() {
return FontType.TYPE1;
}
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
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;
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;
}
/**
* @see FontUtil#stripWhiteSpace(String)
*/
public String getStrippedFontName() {
- return FontUtil.stripWhiteSpace(fontName);
+ return FontUtil.stripWhiteSpace(getFontName());
}
/**
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;
}
/* ---- 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
package org.apache.fop.fonts;
-import java.util.BitSet;
import java.util.Map;
import org.apache.commons.logging.Log;
*/
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";
* 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);
}
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.)
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.
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.
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)) {
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.
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);
}
}
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;
+ }
+
}
}
// ---- 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}
*/
package org.apache.fop.fonts;
//Java
+import java.text.DecimalFormat;
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";
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);
}
return namePrefix + FontUtil.stripWhiteSpace(super.getFontName());
}
- /**
- * {@inheritDoc}
- */
- public String getCidBaseFont() {
+ /** {@inheritDoc} */
+ public String getEmbedFontName() {
if (isEmbeddable()) {
return getPrefixedFontName();
} else {
return encoding;
}
- /**
- * {@inheritDoc}
- */
- public String getFontName() {
- if (isEmbeddable()) {
- return getPrefixedFontName();
- } else {
- return super.getFontName();
- }
- }
-
/**
* {@inheritDoc}
*/
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
} 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);
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;
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.
);
}
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;
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
/** 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
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;
}
/**
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;
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 = "";
* @return String The PostScript name
*/
public String getPostScriptName() {
+ return postScriptName;
+ /*
if ("Regular".equals(subFamilyName) || "Roman".equals(subFamilyName)) {
return familyName;
} else {
return familyName + "," + subFamilyName;
}
+ */
}
/**
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
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;
fullName = txt;
break;
case 6:
- fontName = txt;
+ postScriptName = txt;
break;
}
if (!notice.equals("")
&& !fullName.equals("")
- && !fontName.equals("")
+ && !postScriptName.equals("")
&& !familyName.equals("")
&& !subFamilyName.equals("")) {
break;
notice = "";
fullName = "";
familyName = "";
- fontName = "";
+ postScriptName = "";
subFamilyName = "";
}
* 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);
multiFont.setResolver(this.resolver);\r
returnFont = multiFont;\r
\r
- returnFont.setFontName(ttf.getFamilyName());\r
+ returnFont.setFontName(ttf.getPostScriptName());\r
+ returnFont.setFullName(ttf.getFullName());\r
+ returnFont.setFamilyName(ttf.getFamilyName());\r
returnFont.setFontSubFamilyName(ttf.getSubFamilyName());\r
//multiFont.setTTCName(ttcName)\r
returnFont.setCapHeight(ttf.getCapHeight());\r
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;
/**
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();
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));
case 1:
return "Expert";
case 2:
- return "ExpertSubset";
+ if ("Symbol".equals(getPostscriptName())) {
+ return "Symbol";
+ } else {
+ return "ExpertSubset";
+ }
case 128:
return "Shift-JIS (Japanese)";
default:
pfm.load(in);\r
singleFont = new SingleByteFont();\r
singleFont.setFontType(FontType.TYPE1);\r
+ singleFont.setEncoding(pfm.getCharSetName() + "Encoding");\r
singleFont.setResolver(this.resolver);\r
returnFont = singleFont;\r
returnFont.setFontName(pfm.getPostscriptName());\r
+ String fullName = pfm.getPostscriptName();\r
+ fullName = fullName.replace('-', ' '); //Hack! Try to emulate full name\r
+ returnFont.setFullName(fullName); //should be afm.getFullName()!!\r
+ //TODO not accurate: we need FullName from the AFM file but we don't have an AFM parser\r
+ returnFont.setFamilyName(pfm.getWindowsName()); //should be afm.getFamilyName()!!\r
returnFont.setCapHeight(pfm.getCapHeight());\r
returnFont.setXHeight(pfm.getXHeight());\r
returnFont.setAscender(pfm.getLowerCaseAscent());\r
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;
if (desc.getFontType() == FontType.TYPE0) {
// CID Font
- descriptor = new PDFCIDFontDescriptor(desc.getFontName(),
+ descriptor = new PDFCIDFontDescriptor(desc.getEmbedFontName(),
desc.getFontBBox(),
desc.getCapHeight(),
desc.getFlags(),
desc.getStemV(), null);
} else {
// Create normal FontDescriptor
- descriptor = new PDFFontDescriptor(desc.getFontName(),
+ descriptor = new PDFFontDescriptor(desc.getEmbedFontName(),
desc.getAscender(),
desc.getDescender(),
desc.getCapHeight(),
} catch (IOException ioe) {
log.error(
"Failed to write CIDSet [" + cidFont + "] "
- + cidFont.getFontName(), ioe);
+ + cidFont.getEmbedFontName(), ioe);
}
}
} catch (IOException ioe) {
log.error(
"Failed to embed font [" + desc + "] "
- + desc.getFontName(), ioe);
+ + desc.getEmbedFontName(), ioe);
return (PDFStream) null;
}
}
desc = (FontDescriptor)font;
}
addFont(doc.getFactory().makeFont(
- f, font.getFontName(), font.getEncoding(), font, desc));
+ f, font.getEmbedFontName(), font.getEncoding(), font, desc));
}
}
}
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.
* <p/>
*/
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();
}
/**
}
/**
- * Indicates if the font has kering information.
+ * Indicates if the font has kerning information.
* @return True, if kerning is available.
*/
public boolean hasKerningInfo() {
/**
* 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;
}
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);
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);
}
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);
}
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;
}
}
- /**
- * {@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}
*/
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
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;
}
}
<changes>
<release version="FOP Trunk">
+ <action context="Code" dev="JM" type="fix">
+ Made the way TrueType fonts are embedded in PDF compliant to the
+ specification so viewers correctly identify subset fonts.
+ </action>
+ <action context="Code" dev="JM" type="fix">
+ Fixed font-autodetection so fonts with uppercase extensions are
+ detected, too.
+ </action>
+ <action context="Code" dev="JM" type="update">
+ 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.
+ </action>
<action context="Code" dev="JM" type="fix">
Fixed regression: transparent-page-background was not recognized for PNG output.
</action>