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/

Reply via email to