Browse Source

Improved accuracy of font size selection. The font size is not rounded down to the next integer point value anymore. (Java2D renderers profit from that one, too)

PCL Renderer:
Found a use case for that Java2D ascent value (which I call MaxAscent). It is used for painting text as bitmaps and to make sure the image the text is painted on is big enough if the font ascends beyond the em box. For non-Java2D fonts, MaxAscent is the same as ascent.
Added a check that lets text painting fall back to bitmaps if there are characters that are not in the ISO-8859-1 encoding. This also enables Symbol and ZapfDingbats fonts.
A "text-rendering" setting allows to disable PCL text painting in case the mix of PCL and bitmap text painting should result in unwelcome output. Note: the bitmap rendering is relatively slow (many small bitmaps). In the end we might end up rendering using a BitmapRenderer and only wrapping the whole thing in PCL (much like the Windows PCL drivers do). This would be faster than creating many small bitmaps.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@410672 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-0_93
Jeremias Maerki 18 years ago
parent
commit
e189115a92

+ 8
- 1
src/documentation/content/xdocs/trunk/configuration.xml View File

@@ -253,10 +253,11 @@
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
@@ -265,6 +266,12 @@
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>

+ 8
- 1
src/documentation/content/xdocs/trunk/output.xml View File

@@ -369,10 +369,11 @@ out = proc.getOutputStream();]]></source>
<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
@@ -381,6 +382,12 @@ out = proc.getOutputStream();]]></source>
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

+ 9
- 1
src/java/org/apache/fop/fonts/FontMetrics.java View File

@@ -40,9 +40,17 @@ public interface FontMetrics {
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
*/

+ 8
- 0
src/java/org/apache/fop/fonts/LazyFont.java View File

@@ -176,6 +176,14 @@ public class LazyFont extends Typeface implements FontDescriptor {
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)
*/

+ 5
- 0
src/java/org/apache/fop/fonts/Typeface.java View File

@@ -54,5 +54,10 @@ public abstract class Typeface implements FontMetrics {
return false;
}

/** @see org.apache.fop.fonts.FontMetrics#getMaxAscent(int) */
public int getMaxAscent(int size) {
return getAscender(size);
}
}


+ 7
- 0
src/java/org/apache/fop/render/java2d/FontMetricsMapper.java View File

@@ -85,6 +85,13 @@ public class FontMetricsMapper extends Typeface implements FontMetrics {
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)
*/

+ 37
- 7
src/java/org/apache/fop/render/java2d/Java2DFontMetrics.java View File

@@ -23,7 +23,10 @@ import java.awt.Font;
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.
@@ -97,6 +100,9 @@ public class Java2DFontMetrics {
*/
private FontMetrics fmt = null;

/** A LineMetrics to access high-resolution metrics information. */
private LineMetrics lineMetrics;
/**
* Temp graphics object needed to get the font metrics
*/
@@ -111,6 +117,19 @@ public class Java2DFontMetrics {
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
@@ -233,6 +252,19 @@ public class Java2DFontMetrics {
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
@@ -244,21 +276,19 @@ public class Java2DFontMetrics {
*/
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;
@@ -282,7 +312,7 @@ public class Java2DFontMetrics {
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;

+ 43
- 13
src/sandbox/org/apache/fop/render/pcl/PCLRenderer.java View File

@@ -127,6 +127,12 @@ public class PCLRenderer extends PrintRenderer {
*/
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
*/
@@ -148,6 +154,16 @@ public class PCLRenderer extends PrintRenderer {
"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);
}
}

/**
@@ -202,10 +218,17 @@ public class PCLRenderer extends PrintRenderer {
* 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 {
@@ -214,6 +237,7 @@ public class PCLRenderer extends PrintRenderer {
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
@@ -288,17 +312,19 @@ public class PCLRenderer extends PrintRenderer {
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");
@@ -554,7 +580,9 @@ public class PCLRenderer extends PrintRenderer {

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) {
@@ -577,11 +605,15 @@ public class PCLRenderer extends PrintRenderer {
//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();
@@ -592,10 +624,8 @@ public class PCLRenderer extends PrintRenderer {
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);

Loading…
Cancel
Save