package org.apache.fop.render.java2d;
// FOP
+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.FontTriplet;
// Java
import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.util.Set;
/**
- * Sets up the AWT fonts. It is similar to
- * org.apache.fop.render.pdf.FontSetup.
+ * Sets up the Java2D/AWT fonts. It is similar to
+ * org.apache.fop.render.fonts.FontSetup.
* Assigns the font (with metrics) to internal names like "F1" and
* assigns family-style-weight triplets to the fonts.
*/
public class FontSetup {
+ /** logging instance */
+ protected static Log log = LogFactory.getLog(FontSetup.class);
+
+ private static final int LAST_PREDEFINED_FONT_NUMBER = 14;
+ private static final Set HARDCODED_FONT_NAMES;
+
+ static {
+ HARDCODED_FONT_NAMES = new java.util.HashSet();
+ HARDCODED_FONT_NAMES.add("any");
+ HARDCODED_FONT_NAMES.add("sans-serif");
+ HARDCODED_FONT_NAMES.add("serif");
+ HARDCODED_FONT_NAMES.add("monospace");
+
+ HARDCODED_FONT_NAMES.add("Helvetica");
+ HARDCODED_FONT_NAMES.add("Times");
+ HARDCODED_FONT_NAMES.add("Courier");
+ HARDCODED_FONT_NAMES.add("Symbol");
+ HARDCODED_FONT_NAMES.add("ZapfDingbats");
+ HARDCODED_FONT_NAMES.add("Times Roman");
+ HARDCODED_FONT_NAMES.add("Times-Roman");
+ HARDCODED_FONT_NAMES.add("Computer-Modern-Typewriter");
+ }
+
/**
* Sets up the font info object.
*
fontInfo.addFontProperties("F8", "Times Roman", "italic", Font.BOLD);
fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter",
"normal", Font.NORMAL);
+
+ configureInstalledAWTFonts(fontInfo, graphics, LAST_PREDEFINED_FONT_NUMBER + 1);
+ }
+
+ private static void configureInstalledAWTFonts(FontInfo fontInfo, Graphics2D graphics,
+ 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)) {
+ 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++;
+
+ fontStyle = java.awt.Font.ITALIC;
+ registerFontTriplet(fontInfo, family, fontStyle, "F" + num, graphics);
+ num++;
+
+ 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 registerFontTriplet(FontInfo fontInfo, String family, int fontStyle,
+ String fontKey, Graphics2D graphics) {
+ FontMetricsMapper metric = new FontMetricsMapper(family, fontStyle, graphics);
+ fontInfo.addMetrics(fontKey, metric);
+
+ int weight = Font.NORMAL;
+ if ((fontStyle & java.awt.Font.BOLD) != 0) {
+ weight = Font.BOLD;
+ }
+ String style = "normal";
+ if ((fontStyle & java.awt.Font.ITALIC) != 0) {
+ style = "italic";
+ }
+ FontTriplet triplet = FontInfo.createFontKey(family, style, weight);
+ fontInfo.addFontProperties(fontKey, triplet);
+ }
+
}
private int[] width = null;
/**
- * The typical height of a small cap latter
+ * The typical height of a small cap latter (often derived from "x", value in mpt)
*/
private int xHeight = 0;
-
+
+ /**
+ * The highest point of the font above the baseline (usually derived from "d", value in mpt)
+ */
+ private int ascender = 0;
+
+ /**
+ * The lowest point of the font under the baseline (usually derived from "p", value in mpt)
+ */
+ private int descender = 0;
+
/**
* Buffered font.
* f1 is bufferd for metric measurements during layout.
*/
public int getAscender(String family, int style, int size) {
setFont(family, style, size);
- // return (int)(FONT_FACTOR * fmt.getAscent());
+ return ascender * 1000;
// workaround for sun bug on FontMetrics.getAscent()
// http://developer.java.sun.com/developer/bugParade/bugs/4399887.html
*
* xxxxx@xxxxx 2001-05-15
*/
+ /* I don't think this is right.
int realAscent = fmt.getAscent()
- (fmt.getDescent() + fmt.getLeading());
return FONT_FACTOR * realAscent;
+ */
}
*/
public int getDescender(String family, int style, int size) {
setFont(family, style, size);
- return (-1 * FONT_FACTOR * fmt.getDescent());
+ return descender * 1000;
}
/**
*/
public int getXHeight(String family, int style, int size) {
setFont(family, style, size);
- return (int)(FONT_FACTOR * xHeight);
+ return xHeight * 1000;
}
/**
*/
private boolean setFont(String family, int style, int size) {
boolean changed = false;
- Rectangle2D rect;
- TextLayout layout;
//TODO this seems bad. It rounds font sizes down to the next integer value (=pt)
int s = (int)(size / 1000f);
+ //int s = size;
if (f1 == null) {
f1 = new Font(family, style, s);
// else the font is unchanged from last time
}
if (changed) {
- layout = new TextLayout("m", f1, graphics.getFontRenderContext());
+ //x-Height
+ TextLayout layout = new TextLayout("x", f1, graphics.getFontRenderContext());
+ Rectangle2D rect = layout.getBounds();
+ xHeight = (int)Math.round(-rect.getY() * 1000);
+
+ //PostScript-compatible ascent
+ layout = new TextLayout("d", f1, graphics.getFontRenderContext());
+ rect = layout.getBounds();
+ ascender = (int)Math.round(-rect.getY() * 1000);
+
+ //PostScript-compatible descent
+ layout = new TextLayout("p", f1, graphics.getFontRenderContext());
rect = layout.getBounds();
- xHeight = (int)rect.getHeight();
+ descender = (int)Math.round((rect.getY() + rect.getHeight()) * -1000);
+
+ //Alternative way to get metrics but the ascender is again wrong for our purposes
+ //lineMetrics = f1.getLineMetrics("", graphics.getFontRenderContext());
}
// save the family and style for later comparison
this.family = family;