All,
The PdfGraphics2D.drawString() method wasn't simulating bold, italic or
bold-italic when a bold, italic or bold-italic specific version of the
font was not found.
The PdfGraphics2D.drawGlyphVector() method will produce the proper
output, but it consumes a lot of memory and produces really large pdf
files.
The following PdfGraphics2D.drawString() method will simulate bold,
italic or bold-italic when needed, and it contains the code I submitted
earlier for horizontally scaled fonts.
Note:
On my machine the font.getFontName() and font.getName() values would be
different when the java virtual machine was using a bold, italic or
bold-italic version of a font, and the values were the same when it was
simulating bold, italic, and bold-italic.
I would prefer if there was some way of determining if itext doesn't
have a bold, italic or bold-italic version of the font, and use that
information to trigger the code to simulate a bold, italic, or
bold-italic font.
/**
* @see Graphics2D#drawString(String, float, float)
*/
public void drawString(String s, float x, float y) {
if (s.length() == 0)
return;
setFillPaint();
if (onlyShapes) {
drawGlyphVector(this.font.layoutGlyphVector(getFontRenderContext(),
s.toCharArray(), 0, s.length(),
java.awt.Font.LAYOUT_LEFT_TO_RIGHT), x, y);
// Use the following line to compile in JDK 1.3
//
drawGlyphVector(this.font.createGlyphVector(getFontRenderContext(), s),
x, y);
}
else {
boolean restoreTextRenderingMode = false;
AffineTransform at = getTransform();
AffineTransform at2 = getTransform();
at2.translate(x, y);
at2.concatenate(font.getTransform());
setTransform(at2);
AffineTransform inverse = this.normalizeMatrix();
AffineTransform flipper = AffineTransform.getScaleInstance(1,-1);
inverse.concatenate(flipper);
double[] mx = new double[6];
inverse.getMatrix(mx);
cb.beginText();
cb.setFontAndSize(baseFont, fontSize);
// Check if we need to simulate an italic font.
// When there are different fonts for italic, bold, italic bold
// the font.getName() will be different from the font.getFontName()
// value. When they are the same value then we are normally dealing
// with a single font that has been made into an italic or bold
// font.
if (font.isItalic() && font.getFontName().equals(font.getName())) {
float angle = baseFont.getFontDescriptor(baseFont.ITALICANGLE,
1000);
float angle2 = font.getItalicAngle();
// We don't have an italic version of this font so we need
// to set the font angle ourselves to produce an italic font.
if (angle2 == 0) {
// The JavaVM didn't have an angle setting for making
// the font an italic font so use a default of
// italic angle of 15 degrees.
angle2 = 15.0f;
} else {
// This sign of the angle for Java and PDF seams
// seams to be reversed.
angle2 = -angle2;
}
if (angle == 0) {
mx[2] = angle2 / 100.0f;
}
}
cb.setTextMatrix((float)mx[0], (float)mx[1], (float)mx[2],
(float)mx[3], (float)mx[4], (float)mx[5]);
// Set the horizontal scaling to match the Java font if needed.
Float hscale = (Float)
font.getAttributes().get(TextAttribute.WIDTH);
hscale = (hscale == null) ? TextAttribute.WIDTH_REGULAR : hscale;
cb.setHorizontalScaling(100.0f / hscale);
// Get the weight of the font so we can detect fonts with a weight
// that makes them bold, but the Font.isBold() value is false.
Float weight = (Float)
font.getAttributes().get(TextAttribute.WEIGHT);
if (weight == null) {
weight = (font.isBold()) ? TextAttribute.WEIGHT_BOLD
: TextAttribute.WEIGHT_REGULAR;
}
// Check if we need to simulate a bold font.
if ((font.isBold() || weight >= TextAttribute.WEIGHT_SEMIBOLD)
&& (font.getFontName().equals(font.getName()))) {
// Simulate a bold font.
float strokeWidth = font.getSize2D()
* (weight - TextAttribute.WEIGHT_REGULAR)
/ 30f;
if (strokeWidth != 1) {
cb.setTextRenderingMode(PdfContentByte.
TEXT_RENDER_MODE_FILL_STROKE);
cb.setLineWidth(strokeWidth);
cb.setColorStroke(getColor());
restoreTextRenderingMode = true;
}
}
double width = 0;
if (font.getSize2D() > 0) {
float scale = 1000 / font.getSize2D();
width = font.deriveFont(
AffineTransform.getScaleInstance(scale, scale))
.getStringBounds(s, getFontRenderContext()).getWidth()
/ scale;
}
if (s.length() > 1) {
float adv = ((float)width - baseFont.getWidthPoint(s,
fontSize))
/ (s.length() - 1);
cb.setCharacterSpacing(adv);
}
cb.showText(s);
if (s.length() > 1) {
cb.setCharacterSpacing(0);
}
// Restore the original TextRenderingMode if needed.
if (restoreTextRenderingMode) {
cb.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL);
}
cb.endText();
setTransform(at);
if(underline)
{
// These two are supposed to be taken from the .AFM file
//int UnderlinePosition = -100;
int UnderlineThickness = 50;
//
double d = asPoints((double)UnderlineThickness, (int)fontSize);
setStroke(new BasicStroke((float)d));
y = (float)((double)(y) +
asPoints((double)(UnderlineThickness), (int)fontSize));
Line2D line = new Line2D.Double((double)x, (double)y,
(double)(width+x), (double)y);
draw(line);
}
}
}
--
John Hellerud
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
iText-questions mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/itext-questions
Buy the iText book: http://itext.ugent.be/itext-in-action/