offered by Java.
</p>
<p>
- Additionally, there's one setting that controls how borders are painted.
+ Additionally, there are certain settings that control who the renderer handles various elements.
</p>
<source><![CDATA[<renderer mime="application/vnd.hp-PCL">
<rendering>quality</rendering>
+ <text-rendering>bitmap</text-rendering>
</renderer>]]></source>
<p>
The default value for the "rendering" setting is "speed" which causes borders
value to "quality" as indicated above. This will cause the borders to be painted
as bitmaps.
</p>
+ <p>
+ The default value for the "text-rendering" setting is "auto" which paints the
+ base fonts using PCL fonts. Non-base fonts are painted as bitmaps through Java2D.
+ If the mix of painting methods results in unwelcome output, you can set this
+ to "bitmap" which causes all text to be rendered as bitmaps.
+ </p>
</section>
</section>
</body>
<section id="pcl-configuration">
<title>Configuration</title>
<p>
- The PCL renderer configuration currently allows one setting:
+ The PCL renderer configuration currently allows the following settings:
</p>
<source><![CDATA[<renderer mime="application/vnd.hp-PCL">
<rendering>quality</rendering>
+ <text-rendering>bitmap</text-rendering>
</renderer>]]></source>
<p>
The default value for the "rendering" setting is "speed" which causes borders
value to "quality" as indicated above. This will cause the borders to be painted
as bitmaps.
</p>
+ <p>
+ The default value for the "text-rendering" setting is "auto" which paints the
+ base fonts using PCL fonts. Non-base fonts are painted as bitmaps through Java2D.
+ If the mix of painting methods results in unwelcome output, you can set this
+ to "bitmap" which causes all text to be rendered as bitmaps.
+ </p>
<p>
You can control the output resolution for the PCL using the "target resolution"
setting on the FOUserAgent. The actual value will be rounded up to the next
FontType getFontType();
+ /**
+ * Returns the maximum ascent of the font described by this
+ * FontMetrics object. Note: This is not the same as getAscender().
+ * @param size font size
+ * @return ascent in milliponts
+ */
+ int getMaxAscent(int size);
+
/**
* Returns the ascent of the font described by this
- * FontMetrics object.
+ * FontMetrics object. It returns the nominal ascent within the em box.
* @param size font size
* @return ascent in milliponts
*/
return realFont.getFontName();
}
+ /**
+ * @see org.apache.fop.fonts.FontMetrics#getMaxAscent(int)
+ */
+ public int getMaxAscent(int size) {
+ load(true);
+ return realFont.getMaxAscent(size);
+ }
+
/**
* @see org.apache.fop.fonts.FontMetrics#getAscender(int)
*/
return false;
}
+ /** @see org.apache.fop.fonts.FontMetrics#getMaxAscent(int) */
+ public int getMaxAscent(int size) {
+ return getAscender(size);
+ }
+
}
return FontType.OTHER;
}
+ /**
+ * @see org.apache.fop.fonts.FontMetrics#getMaxAscent(int)
+ */
+ public int getMaxAscent(int size) {
+ return metric.getMaxAscent(family, style, size);
+ }
+
/**
* @see org.apache.fop.fonts.FontMetrics#getAscender(int)
*/
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.FontMetrics;
+import java.awt.font.LineMetrics;
+import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
+import java.util.Map;
/**
* This is a FontMetrics to be used for AWT rendering.
*/
private FontMetrics fmt = null;
+ /** A LineMetrics to access high-resolution metrics information. */
+ private LineMetrics lineMetrics;
+
/**
* Temp graphics object needed to get the font metrics
*/
this.graphics = graphics;
}
+ /**
+ * Determines the font's maximum ascent of the Font described by the current
+ * FontMetrics object
+ * @param family font family (java name) to use
+ * @param style font style (java def.) to use
+ * @param size font size
+ * @return ascent in milliponts
+ */
+ public int getMaxAscent(String family, int style, int size) {
+ setFont(family, style, size);
+ return Math.round(lineMetrics.getAscent() * FONT_FACTOR);
+ }
+
/**
* Determines the font ascent of the Font described by this
* FontMetrics object
return width;
}
+ private Font getBaseFont(String family, int style, float size) {
+ Map atts = new java.util.HashMap();
+ atts.put(TextAttribute.FAMILY, family);
+ if ((style & Font.BOLD) != 0) {
+ atts.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
+ }
+ if ((style & Font.ITALIC) != 0) {
+ atts.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
+ }
+ atts.put(TextAttribute.SIZE, new Float(size)); //size in pt
+ return new Font(atts);
+ }
+
/**
* Checks whether the font for which values are
* requested is the one used immediately before or
*/
private boolean setFont(String family, int style, int size) {
boolean changed = false;
- //TODO this seems bad. It rounds font sizes down to the next integer value (=pt)
- int s = (int)(size / 1000f);
- //int s = size;
+ float s = size / 1000f;
if (f1 == null) {
- f1 = new Font(family, style, s);
+ f1 = getBaseFont(family, style, s);
fmt = graphics.getFontMetrics(f1);
changed = true;
} else {
if ((this.style != style) || !this.family.equals(family)
|| this.size != s) {
if (family.equals(this.family)) {
- f1 = f1.deriveFont(style, (float)s);
+ f1 = f1.deriveFont(style, s);
} else {
- f1 = new Font(family, style, s);
+ f1 = getBaseFont(family, style, s);
}
fmt = graphics.getFontMetrics(f1);
changed = true;
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());
+ lineMetrics = f1.getLineMetrics("", graphics.getFontRenderContext());
}
// save the family and style for later comparison
this.family = family;
*/
private boolean qualityBeforeSpeed = false;
+ /**
+ * Controls whether all text should be painted as text. This is a fallback setting in case
+ * the mixture of native and bitmapped text does not provide the necessary quality.
+ */
+ private boolean allTextAsBitmaps = false;
+
/**
* Create the PCL renderer
*/
"Valid values for 'rendering' are 'quality' and 'speed'. Value found: "
+ rendering);
}
+ String textRendering = cfg.getChild("text-rendering").getValue(null);
+ if ("bitmap".equalsIgnoreCase(textRendering)) {
+ this.allTextAsBitmaps = true;
+ } else if ("auto".equalsIgnoreCase(textRendering)) {
+ this.allTextAsBitmaps = false;
+ } else if (textRendering != null) {
+ throw new ConfigurationException(
+ "Valid values for 'text-rendering' are 'auto' and 'bitmap'. Value found: "
+ + textRendering);
+ }
}
/**
* Sets the current font (NOTE: Hard-coded font mappings ATM!)
* @param name the font name (internal F* names for now)
* @param size the font size
+ * @param text the text to be rendered (used to determine if there are non-printable chars)
* @return true if the font can be mapped to PCL
* @throws IOException if an I/O problem occurs
*/
- public boolean setFont(String name, float size) throws IOException {
+ public boolean setFont(String name, float size, String text) throws IOException {
+ byte[] encoded = text.getBytes("ISO-8859-1");
+ for (int i = 0, c = encoded.length; i < c; i++) {
+ if (encoded[i] == 0x3F && text.charAt(i) != '?') {
+ return false;
+ }
+ }
int fontcode = 0;
if (name.length() > 1 && name.charAt(0) == 'F') {
try {
log.error(e);
}
}
+ //Note "(ON" selects ISO 8859-1 symbol set as used by PCLGenerator
String formattedSize = gen.formatDouble2(size / 1000);
switch (fontcode) {
case 1: // F1 = Helvetica
break;
case 13: // F13 = Symbol
- gen.writeCommand("(19M");
- gen.writeCommand("(s1p" + formattedSize + "v0s0b16686T");
+ return false;
+ //gen.writeCommand("(19M");
+ //gen.writeCommand("(s1p" + formattedSize + "v0s0b16686T");
// ECMA Latin 1 Symbol Set in Times Roman???
// gen.writeCommand("(9U");
// gen.writeCommand("(s1p" + formattedSize + "v0s0b25093T");
- break;
+ //break;
case 14: // F14 = Zapf Dingbats
- gen.writeCommand("(14L");
- gen.writeCommand("(s1p" + formattedSize + "v0s0b45101T");
- break;
+ return false;
+ //gen.writeCommand("(14L");
+ //gen.writeCommand("(s1p" + formattedSize + "v0s0b45101T");
+ //break;
default:
//gen.writeCommand("(0N");
//gen.writeCommand("(s" + formattedSize + "V");
try {
final Color col = (Color)text.getTrait(Trait.COLOR);
- boolean pclFont = setFont(fontname, fontsize);
+ boolean pclFont = allTextAsBitmaps
+ ? false
+ : setFont(fontname, fontsize, text.getText());
if (pclFont) {
//this.currentFill = col;
if (col != null) {
//for cursive fonts, so the text isn't clipped
int extraWidth = font.getFontSize() / 3;
+ final FontMetricsMapper mapper = (FontMetricsMapper)fontInfo.getMetricsFor(
+ font.getFontName());
+ int maxAscent = mapper.getMaxAscent(font.getFontSize()) / 1000;
+ final int additionalBPD = maxAscent - baseline;
Graphics2DAdapter g2a = getGraphics2DAdapter();
final Rectangle paintRect = new Rectangle(
- rx, currentBPPosition + text.getOffset(),
- text.getIPD() + extraWidth, text.getBPD());
+ rx, currentBPPosition + text.getOffset() - additionalBPD,
+ text.getIPD() + extraWidth, text.getBPD() + additionalBPD);
RendererContext rc = createRendererContext(paintRect.x, paintRect.y,
paintRect.width, paintRect.height, null);
Map atts = new java.util.HashMap();
Graphics2DImagePainter painter = new Graphics2DImagePainter() {
public void paint(Graphics2D g2d, Rectangle2D area) {
- FontMetricsMapper mapper = (FontMetricsMapper)fontInfo.getMetricsFor(
- font.getFontName());
g2d.setFont(mapper.getFont(font.getFontSize()));
- g2d.translate(0, baseline);
+ g2d.translate(0, baseline + additionalBPD);
g2d.scale(1000, 1000);
g2d.setColor(col);
Java2DRenderer.renderText(text, g2d, font);