📄 pdfgraphics2d.java
字号:
/*
* $Id: PdfGraphics2D.java 2780 2007-05-24 09:19:25Z blowagie $
*
* Copyright 2002 by Jim Moore <jim@scolamoore.com>.
*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the License.
*
* The Original Code is 'iText, a free JAVA-PDF library'.
*
* The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
* the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
* All Rights Reserved.
* Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
* are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
*
* Contributor(s): all the names of the contributors are added in the source code
* where applicable.
*
* Alternatively, the contents of this file may be used under the terms of the
* LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
* provisions of LGPL are applicable instead of those above. If you wish to
* allow use of your version of this file only under the terms of the LGPL
* License and not to allow others to use your version of this file under
* the MPL, indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by the LGPL.
* If you do not delete the provisions above, a recipient may use your version
* of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MPL as stated above or under the terms of the GNU
* Library General Public License as published by the Free Software Foundation;
* either version 2 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
* details.
*
* If you didn't download this code from the following link, you should check if
* you aren't using an obsolete version:
* http://www.lowagie.com/iText/
*/
package com.lowagie.text.pdf;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Paint;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.TexturePaint;
import java.awt.Transparency;
import java.awt.RenderingHints.Key;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.font.TextAttribute;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import java.awt.image.renderable.RenderableImage;
import java.io.ByteArrayOutputStream;
import java.text.AttributedCharacterIterator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import com.lowagie.text.pdf.internal.PolylineShape;
public class PdfGraphics2D extends Graphics2D {
private static final int FILL = 1;
private static final int STROKE = 2;
private static final int CLIP = 3;
private BasicStroke strokeOne = new BasicStroke(1);
private static final AffineTransform IDENTITY = new AffineTransform();
private Font font;
private BaseFont baseFont;
private float fontSize;
private AffineTransform transform;
private Paint paint;
private Color background;
private float width;
private float height;
private Area clip;
private RenderingHints rhints = new RenderingHints(null);
private Stroke stroke;
private Stroke originalStroke;
private PdfContentByte cb;
/** Storage for BaseFont objects created. */
private HashMap baseFonts;
private boolean disposeCalled = false;
private FontMapper fontMapper;
private ArrayList kids;
private boolean kid = false;
private Graphics2D dg2 = new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB).createGraphics();
private boolean onlyShapes = false;
private Stroke oldStroke;
private Paint paintFill;
private Paint paintStroke;
private MediaTracker mediaTracker;
// Added by Jurij Bilas
protected boolean underline; // indicates if the font style is underlined
protected PdfGState fillGState[] = new PdfGState[256];
protected PdfGState strokeGState[] = new PdfGState[256];
protected int currentFillGState = 255;
protected int currentStrokeGState = 255;
public static final int AFM_DIVISOR = 1000; // used to calculate coordinates
private boolean convertImagesToJPEG = false;
private float jpegQuality = .95f;
// Added by Alexej Suchov
private float alpha;
// Added by Alexej Suchov
private Composite composite;
// Added by Alexej Suchov
private Paint realPaint;
private PdfGraphics2D() {
dg2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
}
/**
* Constructor for PDFGraphics2D.
*
*/
PdfGraphics2D(PdfContentByte cb, float width, float height, FontMapper fontMapper, boolean onlyShapes, boolean convertImagesToJPEG, float quality) {
super();
dg2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
try {
Class.forName("com.sun.image.codec.jpeg.JPEGCodec");
}
catch (Throwable t) {
convertImagesToJPEG = false;
}
this.convertImagesToJPEG = convertImagesToJPEG;
this.jpegQuality = quality;
this.onlyShapes = onlyShapes;
this.transform = new AffineTransform();
this.baseFonts = new HashMap();
if (!onlyShapes) {
this.fontMapper = fontMapper;
if (this.fontMapper == null)
this.fontMapper = new DefaultFontMapper();
}
paint = Color.black;
background = Color.white;
setFont(new Font("sanserif", Font.PLAIN, 12));
this.cb = cb;
cb.saveState();
this.width = width;
this.height = height;
clip = new Area(new Rectangle2D.Float(0, 0, width, height));
clip(clip);
originalStroke = stroke = oldStroke = strokeOne;
setStrokeDiff(stroke, null);
cb.saveState();
}
/**
* @see Graphics2D#draw(Shape)
*/
public void draw(Shape s) {
followPath(s, STROKE);
}
/**
* @see Graphics2D#drawImage(Image, AffineTransform, ImageObserver)
*/
public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {
return drawImage(img, null, xform, null, obs);
}
/**
* @see Graphics2D#drawImage(BufferedImage, BufferedImageOp, int, int)
*/
public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) {
BufferedImage result = img;
if (op != null) {
result = op.createCompatibleDestImage(img, img.getColorModel());
result = op.filter(img, result);
}
drawImage(result, x, y, null);
}
/**
* @see Graphics2D#drawRenderedImage(RenderedImage, AffineTransform)
*/
public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
BufferedImage image = null;
if (img instanceof BufferedImage) {
image = (BufferedImage)img;
} else {
ColorModel cm = img.getColorModel();
int width = img.getWidth();
int height = img.getHeight();
WritableRaster raster = cm.createCompatibleWritableRaster(width, height);
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
Hashtable properties = new Hashtable();
String[] keys = img.getPropertyNames();
if (keys!=null) {
for (int i = 0; i < keys.length; i++) {
properties.put(keys[i], img.getProperty(keys[i]));
}
}
BufferedImage result = new BufferedImage(cm, raster, isAlphaPremultiplied, properties);
img.copyData(raster);
image=result;
}
drawImage(image, xform, null);
}
/**
* @see Graphics2D#drawRenderableImage(RenderableImage, AffineTransform)
*/
public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
drawRenderedImage(img.createDefaultRendering(), xform);
}
/**
* @see Graphics#drawString(String, int, int)
*/
public void drawString(String s, int x, int y) {
drawString(s, (float)x, (float)y);
}
/**
* Calculates position and/or stroke thickness depending on the font size
* @param d value to be converted
* @param i font size
* @return position and/or stroke thickness depending on the font size
*/
public static double asPoints(double d, int i) {
return (d * (double)i) / (double)AFM_DIVISOR;
}
/**
* This routine goes through the attributes and sets the font
* before calling the actual string drawing routine
* @param iter
*/
protected void doAttributes(AttributedCharacterIterator iter) {
underline = false;
Set set = iter.getAttributes().keySet();
for(Iterator iterator = set.iterator(); iterator.hasNext();) {
AttributedCharacterIterator.Attribute attribute = (AttributedCharacterIterator.Attribute)iterator.next();
if (!(attribute instanceof TextAttribute))
continue;
TextAttribute textattribute = (TextAttribute)attribute;
if(textattribute.equals(TextAttribute.FONT)) {
Font font = (Font)iter.getAttributes().get(textattribute);
setFont(font);
}
else if(textattribute.equals(TextAttribute.UNDERLINE)) {
if(iter.getAttributes().get(textattribute) == TextAttribute.UNDERLINE_ON)
underline = true;
}
else if(textattribute.equals(TextAttribute.SIZE)) {
Object obj = iter.getAttributes().get(textattribute);
if(obj instanceof Integer) {
int i = ((Integer)obj).intValue();
setFont(getFont().deriveFont(getFont().getStyle(), i));
}
else if(obj instanceof Float) {
float f = ((Float)obj).floatValue();
setFont(getFont().deriveFont(getFont().getStyle(), f));
}
}
else if(textattribute.equals(TextAttribute.FOREGROUND)) {
setColor((Color) iter.getAttributes().get(textattribute));
}
else if(textattribute.equals(TextAttribute.FAMILY)) {
Font font = getFont();
Map fontAttributes = font.getAttributes();
fontAttributes.put(TextAttribute.FAMILY, iter.getAttributes().get(textattribute));
setFont(font.deriveFont(fontAttributes));
}
else if(textattribute.equals(TextAttribute.POSTURE)) {
Font font = getFont();
Map fontAttributes = font.getAttributes();
fontAttributes.put(TextAttribute.POSTURE, iter.getAttributes().get(textattribute));
setFont(font.deriveFont(fontAttributes));
}
else if(textattribute.equals(TextAttribute.WEIGHT)) {
Font font = getFont();
Map fontAttributes = font.getAttributes();
fontAttributes.put(TextAttribute.WEIGHT, iter.getAttributes().get(textattribute));
setFont(font.deriveFont(fontAttributes));
}
}
}
/**
* @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 {
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);
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());
double width = 0;
if (font.getSize2D() > 0) {
float scale = 1000 / font.getSize2D();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -