Improvements in the adapter for Java2D/AWT font metrics. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@406950 13f79535-47bb-0310-9956-ffa450edef68tags/fop-0_93
@@ -19,21 +19,49 @@ | |||
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. | |||
* | |||
@@ -177,7 +205,63 @@ public class FontSetup { | |||
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); | |||
} | |||
} | |||
@@ -56,10 +56,20 @@ public class Java2DFontMetrics { | |||
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. | |||
@@ -111,7 +121,7 @@ public class Java2DFontMetrics { | |||
*/ | |||
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 | |||
@@ -132,9 +142,11 @@ public class Java2DFontMetrics { | |||
* | |||
* xxxxx@xxxxx 2001-05-15 | |||
*/ | |||
/* I don't think this is right. | |||
int realAscent = fmt.getAscent() | |||
- (fmt.getDescent() + fmt.getLeading()); | |||
return FONT_FACTOR * realAscent; | |||
*/ | |||
} | |||
@@ -161,7 +173,7 @@ public class Java2DFontMetrics { | |||
*/ | |||
public int getDescender(String family, int style, int size) { | |||
setFont(family, style, size); | |||
return (-1 * FONT_FACTOR * fmt.getDescent()); | |||
return descender * 1000; | |||
} | |||
/** | |||
@@ -174,7 +186,7 @@ public class Java2DFontMetrics { | |||
*/ | |||
public int getXHeight(String family, int style, int size) { | |||
setFont(family, style, size); | |||
return (int)(FONT_FACTOR * xHeight); | |||
return xHeight * 1000; | |||
} | |||
/** | |||
@@ -232,10 +244,9 @@ public class Java2DFontMetrics { | |||
*/ | |||
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); | |||
@@ -255,9 +266,23 @@ public class Java2DFontMetrics { | |||
// 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; |
@@ -27,6 +27,10 @@ | |||
<changes> | |||
<release version="FOP Trunk"> | |||
<action context="Code" dev="JM" type="add"> | |||
Automatic support for all fonts available to the Java2D subsystem for all | |||
Java2D-descendant renderers (TIFF, PNG, print, AWT). | |||
</action> | |||
<action context="Code" dev="JM" type="fix"> | |||
Bugfix: Improved baseline detection in TTFReader for TrueType fonts. | |||
</action> |