/** @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]); Float fontTextAttributeWidth = (Float) font.getAttributes().get(TextAttribute.WIDTH); fontTextAttributeWidth = (fontTextAttributeWidth == null) ? TextAttribute.WIDTH_REGULAR : fontTextAttributeWidth; if (!TextAttribute.WIDTH_REGULAR.equals(fontTextAttributeWidth)) cb.setHorizontalScaling(100.0f / fontTextAttributeWidth.floatValue()); // Check if we need to simulate a bold font. // Do nothing if the BaseFont is already bold. This test is not foolproof but it will work // most of the times. if (baseFont.getPostscriptFontName().toLowerCase().indexOf("bold") < 0) { // 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; } if ((font.isBold() || (weight.floatValue() >= TextAttribute.WEIGHT_SEMIBOLD.floatValue())) && (font.getFontName().equals(font.getName()))) { // Simulate a bold font. float strokeWidth = font.getSize2D() * (weight.floatValue() - TextAttribute.WEIGHT_REGULAR.floatValue()) / 30f; if (strokeWidth != 1) { if (realPaint instanceof Color) { cb.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE); cb.setLineWidth(strokeWidth); Color color = (Color) realPaint; int alpha = color.getAlpha(); if (alpha != currentStrokeGState) { currentStrokeGState = alpha; PdfGState gs = strokeGState[alpha]; if (gs == null) { gs = new PdfGState(); gs.setStrokeOpacity(alpha / 255f); strokeGState[alpha] = gs; } cb.setGState(gs); } cb.setColorStroke(color); restoreTextRenderingMode = true; } } } } double width = 0; if (font.getSize2D() > 0) { float scale = 1000 / font.getSize2D(); Font derivedFont = font.deriveFont(AffineTransform.getScaleInstance(scale, scale)); width = derivedFont.getStringBounds(s, getFontRenderContext()).getWidth(); if (derivedFont.isTransformed()) width /= scale; } // if the hyperlink flag is set add an action to the text Object url = getRenderingHint(HyperLinkKey.KEY_INSTANCE); if (url != null && !url.equals(HyperLinkKey.VALUE_HYPERLINKKEY_OFF)) { float scale = 1000 / font.getSize2D(); Font derivedFont = font.deriveFont(AffineTransform.getScaleInstance(scale, scale)); double height = derivedFont.getStringBounds(s, getFontRenderContext()).getHeight(); if (derivedFont.isTransformed()) height /= scale; double leftX = cb.getXTLM(); double leftY = cb.getYTLM(); PdfAction action = new PdfAction(url.toString()); cb.setAction( action, (float) leftX, (float) leftY, (float) (leftX + width), (float) (leftY + height)); } 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); } if (!TextAttribute.WIDTH_REGULAR.equals(fontTextAttributeWidth)) cb.setHorizontalScaling(100); // 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(UnderlineThickness, (int) fontSize); Stroke savedStroke = originalStroke; setStroke(new BasicStroke((float) d)); y = (float) (y + asPoints(UnderlineThickness, (int) fontSize)); Line2D line = new Line2D.Double(x, y, width + x, y); draw(line); setStroke(savedStroke); } } }
private boolean drawImage( Image img, Image mask, AffineTransform xform, Color bgColor, ImageObserver obs) { if (xform == null) xform = new AffineTransform(); else xform = new AffineTransform(xform); xform.translate(0, img.getHeight(obs)); xform.scale(img.getWidth(obs), img.getHeight(obs)); AffineTransform inverse = this.normalizeMatrix(); AffineTransform flipper = AffineTransform.getScaleInstance(1, -1); inverse.concatenate(xform); inverse.concatenate(flipper); double[] mx = new double[6]; inverse.getMatrix(mx); if (currentFillGState != 255) { PdfGState gs = fillGState[255]; if (gs == null) { gs = new PdfGState(); gs.setFillOpacity(1); fillGState[255] = gs; } cb.setGState(gs); } try { com.lowagie.text.Image image = null; if (!convertImagesToJPEG) { image = com.lowagie.text.Image.getInstance(img, bgColor); } else { BufferedImage scaled = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB); Graphics2D g3 = scaled.createGraphics(); g3.drawImage(img, 0, 0, img.getWidth(null), img.getHeight(null), null); g3.dispose(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageWriteParam iwparam = new JPEGImageWriteParam(Locale.getDefault()); iwparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); iwparam.setCompressionQuality(jpegQuality); // Set here your compression rate ImageWriter iw = (ImageWriter) ImageIO.getImageWritersByFormatName("jpg").next(); ImageOutputStream ios = ImageIO.createImageOutputStream(baos); iw.setOutput(ios); iw.write(null, new IIOImage(scaled, null, null), iwparam); iw.dispose(); ios.close(); scaled.flush(); scaled = null; image = com.lowagie.text.Image.getInstance(baos.toByteArray()); } if (mask != null) { com.lowagie.text.Image msk = com.lowagie.text.Image.getInstance(mask, null, true); msk.makeMask(); msk.setInverted(true); image.setImageMask(msk); } cb.addImage( image, (float) mx[0], (float) mx[1], (float) mx[2], (float) mx[3], (float) mx[4], (float) mx[5]); Object url = getRenderingHint(HyperLinkKey.KEY_INSTANCE); if (url != null && !url.equals(HyperLinkKey.VALUE_HYPERLINKKEY_OFF)) { PdfAction action = new PdfAction(url.toString()); cb.setAction( action, (float) mx[4], (float) mx[5], (float) (mx[0] + mx[4]), (float) (mx[3] + mx[5])); } } catch (Exception ex) { throw new IllegalArgumentException(); } if (currentFillGState != 255) { PdfGState gs = fillGState[currentFillGState]; cb.setGState(gs); } return true; }
private void setPaint(boolean invert, double xoffset, double yoffset, boolean fill) { if (paint instanceof Color) { Color color = (Color) paint; int alpha = color.getAlpha(); if (fill) { if (alpha != currentFillGState) { currentFillGState = alpha; PdfGState gs = fillGState[alpha]; if (gs == null) { gs = new PdfGState(); gs.setFillOpacity(alpha / 255f); fillGState[alpha] = gs; } cb.setGState(gs); } cb.setColorFill(color); } else { if (alpha != currentStrokeGState) { currentStrokeGState = alpha; PdfGState gs = strokeGState[alpha]; if (gs == null) { gs = new PdfGState(); gs.setStrokeOpacity(alpha / 255f); strokeGState[alpha] = gs; } cb.setGState(gs); } cb.setColorStroke(color); } } else if (paint instanceof GradientPaint) { GradientPaint gp = (GradientPaint) paint; Point2D p1 = gp.getPoint1(); transform.transform(p1, p1); Point2D p2 = gp.getPoint2(); transform.transform(p2, p2); Color c1 = gp.getColor1(); Color c2 = gp.getColor2(); PdfShading shading = PdfShading.simpleAxial( cb.getPdfWriter(), (float) p1.getX(), normalizeY((float) p1.getY()), (float) p2.getX(), normalizeY((float) p2.getY()), c1, c2); PdfShadingPattern pat = new PdfShadingPattern(shading); if (fill) cb.setShadingFill(pat); else cb.setShadingStroke(pat); } else if (paint instanceof TexturePaint) { try { TexturePaint tp = (TexturePaint) paint; BufferedImage img = tp.getImage(); Rectangle2D rect = tp.getAnchorRect(); com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(img, null); PdfPatternPainter pattern = cb.createPattern(image.getWidth(), image.getHeight()); AffineTransform inverse = this.normalizeMatrix(); inverse.translate(rect.getX(), rect.getY()); inverse.scale(rect.getWidth() / image.getWidth(), -rect.getHeight() / image.getHeight()); double[] mx = new double[6]; inverse.getMatrix(mx); pattern.setPatternMatrix( (float) mx[0], (float) mx[1], (float) mx[2], (float) mx[3], (float) mx[4], (float) mx[5]); image.setAbsolutePosition(0, 0); pattern.addImage(image); if (fill) cb.setPatternFill(pattern); else cb.setPatternStroke(pattern); } catch (Exception ex) { if (fill) cb.setColorFill(Color.gray); else cb.setColorStroke(Color.gray); } } else { try { BufferedImage img = null; int type = BufferedImage.TYPE_4BYTE_ABGR; if (paint.getTransparency() == Transparency.OPAQUE) { type = BufferedImage.TYPE_3BYTE_BGR; } img = new BufferedImage((int) width, (int) height, type); Graphics2D g = (Graphics2D) img.getGraphics(); g.transform(transform); AffineTransform inv = transform.createInverse(); Shape fillRect = new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight()); fillRect = inv.createTransformedShape(fillRect); g.setPaint(paint); g.fill(fillRect); if (invert) { AffineTransform tx = new AffineTransform(); tx.scale(1, -1); tx.translate(-xoffset, -yoffset); g.drawImage(img, tx, null); } g.dispose(); g = null; com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(img, null); PdfPatternPainter pattern = cb.createPattern(width, height); image.setAbsolutePosition(0, 0); pattern.addImage(image); if (fill) cb.setPatternFill(pattern); else cb.setPatternStroke(pattern); } catch (Exception ex) { if (fill) cb.setColorFill(Color.gray); else cb.setColorStroke(Color.gray); } } }
private boolean drawImage( Image img, Image mask, AffineTransform xform, Color bgColor, ImageObserver obs) { if (xform == null) return true; xform.translate(0, img.getHeight(obs)); xform.scale(img.getWidth(obs), img.getHeight(obs)); AffineTransform inverse = this.normalizeMatrix(); AffineTransform flipper = AffineTransform.getScaleInstance(1, -1); inverse.concatenate(xform); inverse.concatenate(flipper); double[] mx = new double[6]; inverse.getMatrix(mx); if (currentFillGState != 255) { PdfGState gs = fillGState[255]; if (gs == null) { gs = new PdfGState(); gs.setFillOpacity(1); fillGState[255] = gs; } cb.setGState(gs); } try { com.lowagie.text.Image image = null; // ssteward: cut out com.sun.image.codec.jpeg code if (true || !convertImagesToJPEG) { image = com.lowagie.text.Image.getInstance(img, bgColor); convertImagesToJPEG = false; // ssteward } else { /* ssteward BufferedImage scaled = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB); Graphics2D g3 = scaled.createGraphics(); g3.drawImage(img, 0, 0, img.getWidth(null), img.getHeight(null), null); g3.dispose(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); com.sun.image.codec.jpeg.JPEGImageEncoder encoder = com.sun.image.codec.jpeg.JPEGCodec.createJPEGEncoder(baos); com.sun.image.codec.jpeg.JPEGEncodeParam param = com.sun.image.codec.jpeg.JPEGCodec.getDefaultJPEGEncodeParam(scaled); param.setQuality(jpegQuality, true); encoder.encode(scaled, param); scaled.flush(); scaled = null; image = com.lowagie.text.Image.getInstance(baos.toByteArray()); */ } if (mask != null) { com.lowagie.text.Image msk = com.lowagie.text.Image.getInstance(mask, null, true); msk.makeMask(); msk.setInvertMask(true); image.setImageMask(msk); } cb.addImage( image, (float) mx[0], (float) mx[1], (float) mx[2], (float) mx[3], (float) mx[4], (float) mx[5]); } catch (Exception ex) { throw new IllegalArgumentException(); } if (currentFillGState != 255) { PdfGState gs = fillGState[currentFillGState]; cb.setGState(gs); } return true; }