From fd48d65e1d2208884343bfd5c850be05b9b4948d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Wed, 17 Feb 2021 17:19:59 +0100 Subject: [PATCH] gnujpdf fix number format on certain locales --- lib/gnujpdf.jar | Bin 111442 -> 111525 bytes libsrc/gnujpdf/src/gnu/jpdf/PDFGraphics.java | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gnujpdf.jar b/lib/gnujpdf.jar index bc765e18c765b2d5b1fa22a1db857db3f2e15b99..b3cbe2721564446571e8c3a68ce9559d83c132d2 100644 GIT binary patch literal 111525 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

AXK+xYsvDhIL(ddC%C$r4f@r^V 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 diff --git a/libsrc/gnujpdf/src/gnu/jpdf/PDFGraphics.java b/libsrc/gnujpdf/src/gnu/jpdf/PDFGraphics.java index d5b4d27dd..3073d049c 100644 --- a/libsrc/gnujpdf/src/gnu/jpdf/PDFGraphics.java +++ b/libsrc/gnujpdf/src/gnu/jpdf/PDFGraphics.java @@ -1 +1 @@ -/* * $Id: PDFGraphics.java,v 1.6 2007/09/22 12:58:40 gil1 Exp $ * * $Date: 2007/09/22 12:58:40 $ * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package gnu.jpdf; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Composite; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Frame; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.Image; 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.RenderingHints.Key; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; import java.awt.geom.Area; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; 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.awt.print.PageFormat; import java.io.PrintWriter; import java.io.Serializable; import java.text.DecimalFormat; import java.util.Hashtable; import java.util.Map; import java.util.WeakHashMap; /** * This class is our implementation of AWT's Graphics class. It provides a * Java standard way of rendering into a PDF Document's Page. * * @author Peter T Mount, http://www.retep.org.uk/pdf/ * @author Eric Z. Beard, ericzbeard@hotmail.com * @author Gilbert DeLeeuw, gil1@users.sourceforge.net * @version $Revision: 1.6 $, $Date: 2007/09/22 12:58:40 $ * @see gnu.jpdf.PDFGraphics */ public class PDFGraphics extends Graphics2D implements Serializable { /** * One degree in radians */ private static final double degrees_to_radians = Math.PI/180.0; private static final int FILL = 1; private static final int STROKE = 2; private static final int CLIP = 3; private static final AffineTransform IDENTITY = new AffineTransform(); private static final Stroke DEF_STROKE = new BasicStroke(); /* * NOTE: The original class is the work of Peter T. Mount, who released it * in the uk.org.retep.pdf package. It was modified by Eric Z. Beard as * follows: * The package name was changed to gnu.pdf. * The formatting was changed a little bit. * This used to subclass an abstract class in a different package with * the same name (confusing). Now it's one concrete class. * drawImage() was implemented * It is still licensed under the LGPL. */ // Implementation notes: // // Pages 333-335 of the PDF Reference Manual // // Unless absolutely required, use the moveto, lineto and rectangle // operators to perform those actions. // They contain some extra optimizations // which will reduce the output size by up to half in some cases. // // About fill operators: For correct operation, any fill operation should // start with closeBlock(), which will ensure any previous path is completed, // otherwise you may find the fill will include previous items private static final DecimalFormat df = new DecimalFormat("#.###"); //JPEXS: cache for already used images private static Map usedImages = new WeakHashMap(); private Color background; /** * This is true for any Graphics instance that didn't create the stream. * @see #create */ private boolean child; private Area clip; /** * This holds the current clipRectangle */ protected Rectangle clipRectangle; private Composite composite; private Graphics2D dg2 = new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB).createGraphics(); /** * This is the current font (in Java format) */ private Font font; /** * Part of the optimizer: * When true, we are drawing a path. */ private boolean inStroke; /** * Part of the optimizer: * When true, we are within a Text Block. */ private boolean inText; // true if within a Text Block - see newTextBlock() /** * The stroke line cap code; */ private int lineCap = 0; /** * The stroke line join code */ private int lineJoin = 0; /** * The stroke line width */ private float lineWidth = 1.0f; /** * Part of the optimizer: * The last known moveto/lineto x coordinate * @see #moveto * @see #lineto */ private float lx; // last known moveto/lineto coordinates /** * Part of the optimizer: * The last known moveto/lineto y coordinate * @see #moveto * @see #lineto */ private float ly; // last known moveto/lineto coordinates private float miterLimit = 10.0f; /** * Part of the optimizer: * When true, the font has changed. */ private boolean newFont; // true if the font changes - see newTextBlock() private Stroke originalStroke; // Original transform private AffineTransform oTransform; /** * This is a reference to the PDFPage we are rendering to. */ private PDFPage page; /** * This is the current pen/fill color */ private Paint paint; /** * This is the current font (in PDF format) */ private PDFFont pdffont; /** * Part of the optimizer: * This is written to the stream when the newPath() is called. np then clears * this value. */ private String pre_np; // PDF space transform private AffineTransform pTransform; /** * This is the PrintWriter used to write PDF drawing commands to the Stream */ private PrintWriter pw; /** * RenderingHints */ private RenderingHints rhints = new RenderingHints(null); private Stroke stroke; // Start of Graphics2D properties // Java space transform private AffineTransform transform; /** * This is used to translate coordinates */ protected float trax; /** * This is used to translate coordinates */ protected float tray; /** * Part of the optimizer: * The last x coordinate when rendering text */ private float tx; // the last coordinate for text rendering /** * Part of the optimizer: * The last y coordinate when rendering text */ private float ty; // the last coordinate for text rendering /** * @see Graphics2D#addRenderingHints(Map) */ public void addRenderingHints(Map hints) { rhints.putAll(hints); } /** * This produces an arc by breaking it down into one or more Bezier curves. * It is used internally to implement the drawArc and fillArc methods. * * @param axc X coordinate of arc centre * @param ayc Y coordinate of arc centre * @param width of bounding rectangle * @param height of bounding rectangle * @param ang1 Start angle * @param ang2 End angle * @param clockwise true to draw clockwise, false anti-clockwise */ public void arc(double axc,double ayc, double width,double height, double ang1,double ang2, boolean clockwise) { double adiff; double x0, y0; double x3r, y3r; boolean first = true; // may not need this //if( ar < 0 ) { //ang1 += fixed_180; //ang2 += fixed_180; //ar = - ar; //} double ang1r = (ang1%360.0)*degrees_to_radians; double sin0 = Math.sin(ang1r); double cos0 = Math.cos(ang1r); x0 = axc + width*cos0; y0 = ayc + height*sin0; // NB: !clockwise here as Java Space is inverted to User Space if( !clockwise ) { // Quadrant reduction while ( ang1 < ang2 ) ang2 -= 360.0; while ( (adiff = ang2 - ang1) < -90.0 ) { double w = sin0; sin0 = -cos0; cos0 = w; x3r = axc + width*cos0; y3r = ayc + height*sin0; arc_add(first, width, height, x0, y0, x3r, y3r, (x0 + width*cos0), (y0 + height*sin0) ); x0 = x3r; y0 = y3r; ang1 -= 90.0; first = false; } } else { // Quadrant reduction while ( ang2 < ang1 ) ang2 += 360.0; while ( (adiff = ang2 - ang1) > 90.0 ) { double w = cos0; cos0 = -sin0; sin0 = w; x3r = axc + width*cos0; y3r = ayc + height*sin0; arc_add(first, width, height, x0, y0, x3r, y3r, (x0 + width*cos0), (y0 + height*sin0) ); x0 = x3r; y0 = y3r; ang1 += 90.0; first = false; } } // Compute the intersection of the tangents. // We know that -fixed_90 <= adiff <= fixed_90. double trad = Math.tan(adiff * (degrees_to_radians / 2)); double ang2r = ang2 * degrees_to_radians; double xt = x0 - trad * width*sin0; double yt = y0 + trad * height*cos0; arc_add(first, width, height, x0, y0, (axc + width * Math.cos(ang2r)), (ayc + height * Math.sin(ang2r)), xt, yt); } /** * Used by the arc method to actually add an arc to the path * Important: We write directly to the stream here, because this method * operates in User space, rather than Java space. * @param first true if the first arc * @param w width * @param h height * @param x0 coordinate * @param y0 coordinate * @param x3 coordinate * @param y3 coordinate * @param xt coordinate * @param yt coordinate */ private void arc_add(boolean first, double w,double h, double x0,double y0, double x3,double y3, double xt,double yt) { double dx = xt - x0, dy = yt - y0; double dist = dx*dx + dy*dy; double w2 = w*w, h2=h*h; double r2 = w2+h2; double fw = 0.0, fh = 0.0; if(dist < (r2*1.0e8)) { // JM fw = (w2 != 0.0) ? ((4.0/3.0)/(1+Math.sqrt(1+dist/w2))) : 0.0; fh = (h2 != 0.0) ? ((4.0/3.0)/(1+Math.sqrt(1+dist/h2))) : 0.0; } // The path must have a starting point if(first) moveto(x0,y0); double x = x0+((xt-x0)*fw); double y = y0+((yt-y0)*fh); x0 = x3+((xt-x3)*fw); y0 = y3+((yt-y3)*fh); // Finally the actual curve. curveto(x,y,x0,y0,x3,y3); } /** * This simply draws a White Rectangle to clear the area * @param x coordinate * @param y coordinate * @param w width * @param h height */ public void clearRect(int x,int y,int w,int h) { closeBlock(); pw.print("q 1 1 1 RG ");// save state, set colour to White drawRect(x,y,w,h); closeBlock("B Q"); // close fill & stroke, then restore state } /** * @see Graphics2D#clip(Shape) */ public void clip(Shape s) { if (s == null) { setClip(null); return; } s = transform.createTransformedShape(s); if (clip == null) clip = new Area(s); else clip.intersect(new Area(s)); // followPath(s, CLIP); } /** * This extra method allows PDF users to clip to a Polygon. * *

In theory you could use setClip(), except that java.awt.Graphics * only supports Rectangle with that method, so we will have an extra * method. * @param p Polygon to clip to */ public void clipPolygon(Polygon p) { closeBlock(); // finish off any existing path polygon(p.xpoints,p.ypoints,p.npoints); closeBlock("W"); // clip to current path clipRectangle = p.getBounds(); } /** * Clips to a set of coordinates * @param x coordinate * @param y coordinate * @param w width * @param h height */ public void clipRect(int x,int y,int w,int h) { setClip(x,y,w,h); } /** * All functions should call this to close any existing optimized blocks. */ void closeBlock() { closeBlock("S"); } /** *

This is used by code that use the path in any way other than Stroke * (like Fill, close path & Stroke etc). Usually this is used internally.

* * @param code PDF operators that will close the path */ void closeBlock(String code) { if(inText) { pw.println("ET Q"); // setOrientation(); // fixes Orientation matrix } if(inStroke) { pw.println(code); } inStroke=inText=false; } /** * This is unsupported - how do you do this with Vector graphics? * @param x coordinate * @param y coordinate * @param w width * @param h height * @param dx coordinate * @param dy coordinate */ public void copyArea(int x,int y,int w,int h,int dx,int dy) { // Hmm... Probably need to keep track of everything // that has been drawn so far to get the contents of an area } //============ Line operations ======================= /** *

This returns a child instance of this Graphics object. As with AWT, the * affects of using the parent instance while the child exists, is not * determined.

* *

Once complete, the child should be released with it's dispose() * method which will restore the graphics state to it's parent.

* * @return Graphics object to render onto the page */ public Graphics create() { closeBlock(); PDFGraphics g = createGraphic(page,pw); // The new instance inherits a few items // g.media = new Rectangle(media); g.trax = trax; g.tray = tray; g.clipRectangle = new Rectangle(clipRectangle); return (Graphics) g; } // end create() /** * This method creates a new instance of the class based on the page * and a print writer. * * @param page the page to attach to * @param pw the PrintWriter to attach to. */ protected PDFGraphics createGraphic(PDFPage page, PrintWriter pw) { PDFGraphics g = new PDFGraphics(); g.init(page,pw); return g; } /** * This extension appends a Bezier curve to the path. The curve * extends from the current point to (x2,y2) using the current * point and (x1,y1) as the Bezier control points. *

The new current point is (x2,y2) * * @param x1 Second control point * @param y1 Second control point * @param x2 Destination point * @param y2 Destination point */ public void curveto(double x1,double y1,double x2,double y2) { newPath(); pw.println(cxy(x1,y1)+cxy(x2,y2)+"v"); lx=(float)x2; ly=(float)y2; } /** * This extension appends a Bezier curve to the path. The curve * extends from the current point to (x3,y3) using (x1,y1) and * (x2,y2) as the Bezier control points. *

The new current point is (x3,y3) * * @param x1 First control point * @param y1 First control point * @param x2 Second control point * @param y2 Second control point * @param x3 Destination point * @param y3 Destination point */ public void curveto(double x1,double y1,double x2,double y2,double x3,double y3) { newPath(); pw.println(cxy(x1,y1)+cxy(x2,y2)+cxy(x3,y3)+"c"); lx=(float)x3; ly=(float)y3; } /** * This extension appends a Bezier curve to the path. The curve * extends from the current point to (x2,y2) using the current * point and (x1,y1) as the Bezier control points. *

The new current point is (x2,y2) * * @param x1 Second control point * @param y1 Second control point * @param x2 Destination point * @param y2 Destination point */ public void curveto(int x1,int y1,int x2,int y2) { newPath(); pw.println(cxy(x1,y1)+cxy(x2,y2)+"v"); lx=x2; ly=y2; } /** * This extension appends a Bezier curve to the path. The curve * extends from the current point to (x3,y3) using (x1,y1) and * (x2,y2) as the Bezier control points. *

The new current point is (x3,y3) * * @param x1 First control point * @param y1 First control point * @param x2 Second control point * @param y2 Second control point * @param x3 Destination point * @param y3 Destination point */ public void curveto(int x1,int y1,int x2,int y2,int x3,int y3) { newPath(); pw.println(cxy(x1,y1)+cxy(x2,y2)+cxy(x3,y3)+"c"); lx=x3; ly=y3; } /** * This extension appends a Bezier curve to the path. The curve * extends from the current point to (x2,y2) using (x1,y1) and * the end point as the Bezier control points. *

The new current point is (x2,y2) * * @param x1 Second control point * @param y1 Second control point * @param x2 Destination point * @param y2 Destination point */ public void curveto2(double x1,double y1,double x2,double y2) { newPath(); pw.println(cxy(x1,y1)+cxy(x2,y2)+"y"); lx=(float)x2; ly=(float)y2; } // Arcs are horrible and complex. They are at the end of the // file, because they are the largest. This is because, unlike // Postscript, PDF doesn't have any arc operators, so we must // implement them by converting into one or more Bezier curves // (which is how Postscript does them internally). /** * This extension appends a Bezier curve to the path. The curve * extends from the current point to (x2,y2) using (x1,y1) and * the end point as the Bezier control points. *

The new current point is (x2,y2) * * @param x1 Second control point * @param y1 Second control point * @param x2 Destination point * @param y2 Destination point */ public void curveto2(int x1,int y1,int x2,int y2) { newPath(); pw.println(cxy(x1,y1)+cxy(x2,y2)+"y"); lx=x2; ly=y2; } /** * Converts the Java space dimension into pdf. * @param w width * @param h height * @return String containing the coordinates in PDF space */ private String cwh(double w,double h) { double nw=w,nh=h; // scratch // switch(mediaRot) { // case PageFormat.PORTRAIT: // Portrait //nw = w; nh = -h; // break; // // case PageFormat.LANDSCAPE: // // Landscape // nw = h; // nh = w; // break; // //// case 180: //// // Inverse Portrait //// nw = -w; //// //nh = h; //// break; // // case PageFormat.REVERSE_LANDSCAPE: // // Seascape // nw = -h; // nh = -w; // break; // } return ""+df.format(nw)+" "+df.format(nh)+" "; } /** * Converts the Java space dimension into pdf. * @param w width * @param h height * @return String containing the coordinates in PDF space */ private String cwh(int w,int h) { return cwh((double)w,(double)h); } /** * Converts the Java space coordinates into pdf. * @param x coordinate * @param y coordinate * @return String containing the coordinates in PDF space */ private String cxy(double x, double y) { // double nx = x, ny = y; // scratch // double mh = page.getPageFormat().getHeight(); Point2D ptSrc = new Point2D.Double(x, y); Point2D ptDst = new Point2D.Double(); transform.transform(ptSrc, ptDst); // x += trax; // y += tray; // // nx = x; // ny = mh - y; // // System.out.println("\ncxy(" + ptSrc.getX() + ", " + ptSrc.getY() + ")"); // System.out.println("Old [" + nx + "," + ny + "]"); // System.out.println("Trn [" + ptDst.getX() + ", " + ptDst.getY() + "]"); // // return "" + df.format(nx) + " " + df.format(ny) + " "; return ""+df.format(ptDst.getX())+" "+df.format(ptDst.getY())+" "; } /** * Converts the Java space coordinates into pdf. * @param x coordinate * @param y coordinate * @return String containing the coordinates in PDF space */ private String cxy(int x,int y) { return cxy((double)x,(double)y); } /** *

This releases any resources used by this Graphics object. You must use * this method once finished with it. Leaving it open will leave the PDF * stream in an inconsistent state, and will produce errors.

* *

If this was created with Graphics.create() then the parent instance * can be used again. If not, then this closes the graphics operations for * this page when used with PDFJob.

* *

When using PDFPage, you can create another fresh Graphics instance, * which will draw over this one.

* */ public void dispose() { closeBlock(); if(child) { pw.println("Q"); // restore graphics context } else { pw.close(); // close the stream if were the parent } } // ********************************************* // **** Implementation of java.awt.Graphics **** // ********************************************* //============ Rectangle operations ======================= /** * @see Graphics2D#draw(Shape) */ public void draw(Shape s) { followPath(s, STROKE); } /** *

Not implemented

* *

Draws a 3-D highlighted outline of the specified rectangle. * The edges of the rectangle are highlighted so that they appear * to be beveled and lit from the upper left corner. * The colors used for the highlighting effect are determined based on * the current color. The resulting rectangle covers an area that * is width + 1 pixels wide by height + 1 pixels tall. *

* * @param x an int value * @param y an int value * @param width an int value * @param height an int value * @param raised a boolean value */ public void draw3DRect(int x, int y, int width, int height, boolean raised) { // Not implemented } /** * Draws an arc * @param x coordinate * @param y coordinate * @param w width * @param h height * @param sa Start angle * @param aa End angle */ public void drawArc(int x,int y,int w,int h,int sa,int aa) { w=w>>1; h=h>>1; x+=w; y+=h; arc((double)x,(double)y, (double)w,(double)h, (double)-sa,(double)(-sa-aa), false); } /** *

Not implemented

* * @param data a byte[] value * @param offset an int value * @param length an int value * @param x an int value * @param y an int value */ public void drawBytes(byte[] data, int offset, int length, int x, int y) { } //============ Optimizers ======================= /** * @see Graphics2D#drawGlyphVector(GlyphVector, float, float) */ public void drawGlyphVector(GlyphVector g, float x, float y) { Shape s = g.getOutline(x, y); fill(s); } /** * @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#drawImage(Image, AffineTransform, ImageObserver) */ public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { // return drawImage(img, null, xform, null, obs); return true; } /** *

Draw's an image onto the page, with a backing colour.

* * @param img The java.awt.Image * @param x coordinate on page * @param y coordinate on page * @param bgcolor Background colour * @param obs ImageObserver * @return true if drawn */ public boolean drawImage(Image img,int x,int y,Color bgcolor, ImageObserver obs) { return drawImage(img,x,y,img.getWidth(obs),img.getHeight(obs), bgcolor,obs); } /** * Draw's an image onto the page * @param img The java.awt.Image * @param x coordinate on page * @param y coordinate on page * @param obs ImageObserver * @return true if drawn */ public boolean drawImage(Image img,int x,int y,ImageObserver obs) { return drawImage(img,x,y,img.getWidth(obs),img.getHeight(obs),obs); } /** *

Draw's an image onto the page, with a backing colour.

* * @param img The java.awt.Image * @param x coordinate on page * @param y coordinate on page * @param w Width on page * @param h height on page * @param bgcolor Background colour * @param obs ImageObserver * @return true if drawn */ public boolean drawImage(Image img,int x,int y,int w,int h, Color bgcolor,ImageObserver obs) { closeBlock(); pw.print("q "); // save state Color c = getColor(); // save current colour setColor(bgcolor); // change the colour drawRect(x,y,w,h); closeBlock("B Q"); // fill stroke, restore state paint = c; // restore original colour return drawImage(img,x,y,img.getWidth(obs),img.getHeight(obs),obs); } /** *

Draws an image onto the page.

* *

This method is implemented with ASCIIbase85 encoding and the * zip stream deflater. It results in a stream that is anywhere * from 3 to 10 times as big as the image. This obviously needs some * improvement, but it works well for small images

* * @param img The java.awt.Image * @param x coordinate on page * @param y coordinate on page * @param w Width on page * @param h height on page * @param obs ImageObserver * @return true if drawn */ public boolean drawImage(Image img,int x,int y,int w,int h, ImageObserver obs) { closeBlock(); PDFImage image; if(usedImages.containsKey(img)){ image = usedImages.get(img); }else{ image = new PDFImage(img,obs); // The image needs to be registered in several places page.getPDFDocument().setImageName(image); page.getPDFDocument().add(image); usedImages.put(img, image); } page.addToProcset("/ImageC"); page.addImageResource(image.getName() + " " + image.getSerialID() + " 0 R"); // JM /*page.addResource("/XObject << " + image.getName() + " " + image.getSerialID() + " 0 R >>");*/ // q w 0 0 h x y cm % the coordinate matrix pw.print("q " + w+ " 0 0 " + h+ " " + x + " " + ((int)page.getDimension().getHeight()-y-h) + " cm \n" + image.getName() + " Do\nQ\n"); return false; } /** * Draw's an image onto the page, with scaling *

This is not yet supported. * * @param img The java.awt.Image * @param dx1 coordinate on page * @param dy1 coordinate on page * @param dx2 coordinate on page * @param dy2 coordinate on page * @param sx1 coordinate on image * @param sy1 coordinate on image * @param sx2 coordinate on image * @param sy2 coordinate on image * @param bgcolor Background colour * @param obs ImageObserver * @return true if drawn */ public boolean drawImage(Image img,int dx1,int dy1,int dx2, int dy2,int sx1,int sy1,int sx2,int sy2, Color bgcolor,ImageObserver obs) { return false; } //============ Clipping operations ======================= /** * Draw's an image onto the page, with scaling *

This is not yet supported. * * @param img The java.awt.Image * @param dx1 coordinate on page * @param dy1 coordinate on page * @param dx2 coordinate on page * @param dy2 coordinate on page * @param sx1 coordinate on image * @param sy1 coordinate on image * @param sx2 coordinate on image * @param sy2 coordinate on image * @param obs ImageObserver * @return true if drawn */ public boolean drawImage(Image img,int dx1,int dy1,int dx2, int dy2,int sx1,int sy1,int sx2,int sy2, ImageObserver obs) { // This shouldn't be too bad, just change the coordinate matrix return false; } /** * Draws a line between two coordinates. * * If the first coordinate is the same as the last one drawn * (i.e. a previous drawLine, moveto, etc) it is ignored. * @param x1 coordinate * @param y1 coordinate * @param x2 coordinate * @param y2 coordinate */ public void drawLine(int x1,int y1,int x2,int y2) { moveto(x1,y1); lineto(x2,y2); } //============ Arcs operations ============================== // These are the standard Graphics operators. They use the // arc extension operators to achieve the affect. /** *

Draws an oval

* * @param x coordinate * @param y coordinate * @param w width * @param h height */ public void drawOval(int x,int y,int w,int h) { drawArc(x, y, w, h, 0, 360); } /** * Draws a polygon, linking the first and last coordinates. * @param xp Array of x coordinates * @param yp Array of y coordinates * @param np number of points in polygon */ public void drawPolygon(int[] xp,int[] yp,int np) { polygon(xp,yp,np); closeBlock("s"); // close path and stroke } /** * Draws a polyline. The first and last coordinates are not linked. * @param xp Array of x coordinates * @param yp Array of y coordinates * @param np number of points in polyline */ public void drawPolyline(int[] xp,int[] yp,int np) { polygon(xp,yp,np); // no stroke, as we keep the optimizer in stroke state } /** * We override Graphics.drawRect as it doesn't join the 4 lines. * Also, PDF provides us with a Rectangle operator, so we will use that. * @param x coordinate * @param y coordinate * @param w width * @param h height */ public void drawRect(int x,int y,int w,int h) { newPath(); pw.print(cxy(x,y)+cwh(w,h)+"re "); // rectangle lx=x; // I don't know if this is correct, but lets see if PDF ends ly=y; // the rectangle at it's start. // stroke (optimized) } /** * @see Graphics2D#drawRenderableImage(RenderableImage, AffineTransform) */ public void drawRenderableImage(RenderableImage img, AffineTransform xform) { drawRenderedImage(img.createDefaultRendering(), xform); } /** * @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); } /** * This is not yet implemented * * @param x coordinate * @param y coordinate * @param w width * @param h height * @param aw a-width * @param ah a-height */ public void drawRoundRect(int x,int y,int w,int h,int aw,int ah) { } //============ Oval operations ======================= /** * Draws a string using a AttributedCharacterIterator. *

This is not supported yet, as I have no idea what an * AttributedCharacterIterator is. *

This method is new to the Java2 API. */ public void drawString(java.text.AttributedCharacterIterator aci, float x,float y) { } /** * Draws a string using a AttributedCharacterIterator. *

This is not supported yet, as I have no idea what an * AttributedCharacterIterator is. *

This method is new to the Java2 API. */ public void drawString(java.text.AttributedCharacterIterator aci, int x,int y) { } public void drawString(String s,float x,float y) { newTextBlock(x, y); pw.println(PDFStringHelper.makePDFString(s)+" Tj"); } /** * This draws a string. * * @oaran s String to draw * @param x coordinate * @param y coordinate */ public void drawString(String s,int x,int y) { newTextBlock(x,y); pw.println(PDFStringHelper.makePDFString(s)+" Tj"); } /** * @see Graphics2D#fill(Shape) */ public void fill(Shape s) { followPath(s, FILL); } /** *

Not implemented

* * @param x an int value * @param y an int value * @param width an int value * @param height an int value * @param raised a boolean value */ public void fill3DRect(int x, int y, int width, int height, boolean raised) { // Not implemented } /** * Fills an arc, joining the start and end coordinates * @param x coordinate * @param y coordinate * @param w width * @param h height * @param sa Start angle * @param aa End angle */ public void fillArc(int x,int y,int w,int h,int sa,int aa) { // here we fool the optimizer. We force any open path to be closed, // then draw the arc. Finally, as the optimizer hasn't stroke'd the // path, we close and fill it, and mark the Stroke as closed. // // Note: The lineto to the centre of the object is required, because // the fill only fills the arc. Skipping this includes an extra // chord, which isn't correct. Peter May 31 2000 closeBlock(); drawArc(x,y,w,h,sa,aa); lineto(x+(w>>1),y+(h>>1)); closeBlock("b"); // closepath and fill } //============ Extension operations ============================== // These are extensions, and provide access to PDF Specific // operators. /** *

Draws a filled oval

* * @param x coordinate * @param y coordinate * @param w width * @param h height */ public void fillOval(int x,int y,int w,int h) { fillArc(x, y, w, h, 0, 360); } //============ Polygon operations ======================= /** * Fills a polygon. * @param xp Array of x coordinates * @param yp Array of y coordinates * @param np number of points in polygon */ public void fillPolygon(int[] xp,int[] yp,int np) { closeBlock(); // finish off any previous paths polygon(xp,yp,np); closeBlock("b"); // closepath, fill and stroke } //============ Image operations ======================= /** * Fills a rectangle with the current colour * * @param x coordinate * @param y coordinate * @param w width * @param h height */ public void fillRect(int x,int y,int w,int h) { // end any path & stroke. This ensures the fill is on this // rectangle, and not on any previous graphics closeBlock(); drawRect(x,y,w,h); closeBlock("B"); // rectangle, fill stroke } //============ Round Rectangle operations ======================= /** * This is not yet implemented * * @param x coordinate * @param y coordinate * @param w width * @param h height * @param aw a-width * @param ah a-height */ public void fillRoundRect(int x,int y,int w,int h,int aw,int ah) { } /////////////////////////////////////////////// // // // implementation specific methods // // private void followPath(Shape s, int drawType) { PathIterator points; if (s==null) return; if (drawType==STROKE) { if (!(stroke instanceof BasicStroke)) { s = stroke.createStrokedShape(s); followPath(s, FILL); return; } } // if (drawType==STROKE) { // setStrokeDiff(stroke, oldStroke); // oldStroke = stroke; // setStrokePaint(); // } // else if (drawType==FILL) // setFillPaint(); points = s.getPathIterator(IDENTITY); int segments = 0; float[] coords = new float[6]; while(!points.isDone()) { segments++; int segtype = points.currentSegment(coords); switch(segtype) { case PathIterator.SEG_CLOSE: pw.print("h "); break; case PathIterator.SEG_CUBICTO: curveto(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); break; case PathIterator.SEG_LINETO: lineto(coords[0], coords[1]); break; case PathIterator.SEG_MOVETO: moveto(coords[0], coords[1]); break; case PathIterator.SEG_QUADTO: curveto(coords[0], coords[1], coords[2], coords[3]); break; } points.next(); } switch (drawType) { case FILL: if (segments > 0) { if (points.getWindingRule() == PathIterator.WIND_EVEN_ODD) closeBlock("B*"); else closeBlock("B"); } break; case STROKE: if (segments > 0) closeBlock("S"); break; case CLIP: default: //drawType==CLIP if (segments == 0) drawRect(0, 0, 0, 0); if (points.getWindingRule() == PathIterator.WIND_EVEN_ODD) closeBlock("W*"); else closeBlock("W"); } } /** * @see Graphics2D#getBackground() */ public Color getBackground() { return background; } /** * Returns the Shape of the clipping region * As my JDK docs say, this may break with Java 2D. * @return Shape of the clipping region */ public Shape getClip() { return null; } /** * Returns the Rectangle that fits the current clipping region * @return the Rectangle that fits the current clipping region */ public Rectangle getClipBounds() { return clipRectangle; } //============ Color operations ======================= /** * Returns the current pen Colour * @return the current pen Colour */ public Color getColor() { return (paint instanceof Color) ? (Color) paint : Color.black; } /** * @see Graphics2D#getComposite() */ public Composite getComposite() { return composite; } /** * @see Graphics2D#getDeviceConfiguration() */ public GraphicsConfiguration getDeviceConfiguration() { return dg2.getDeviceConfiguration(); } /** * Return's the current font. * @return the current font. */ public Font getFont() { if(font==null) setFont(new Font("SansSerif",Font.PLAIN,12)); return font; } /** * Returns the FontMetrics for a font. *

This doesn't work correctly. Perhaps having some way of mapping * the base 14 fonts to our own FontMetrics implementation? * @param font The java.awt.Font to return the metrics for * @return FontMetrics for a font */ public FontMetrics getFontMetrics(Font font) { Frame dummy = new Frame(); dummy.addNotify(); Image image = dummy.createImage(100, 100); if (image == null) { System.err.println("getFontMetrics: image is null"); } Graphics graphics = image.getGraphics(); return graphics.getFontMetrics(font); } /** * @see Graphics2D#getFontRenderContext() */ public FontRenderContext getFontRenderContext() { boolean antialias = RenderingHints.VALUE_TEXT_ANTIALIAS_ON.equals(getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING)); boolean fractions = RenderingHints.VALUE_FRACTIONALMETRICS_ON.equals(getRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS)); return new FontRenderContext(new AffineTransform(), antialias, fractions); } /** * Returns the associated PDFPage for this graphic * @return the associated PDFPage for this graphic */ public PDFPage getPage() { return page; } /** * Returns the current pen Colour * @return the current pen Colour */ public Paint getPaint() { return paint; } /** * @param arg0 a key * @return the rendering hint */ public Object getRenderingHint(Key arg0) { return rhints.get(arg0); } /** * @see Graphics2D#getRenderingHints() */ public RenderingHints getRenderingHints() { return rhints; } /** * @see Graphics2D#getStroke() */ public Stroke getStroke() { return originalStroke; } /** * @see Graphics2D#getTransform() */ public AffineTransform getTransform() { return new AffineTransform(oTransform); } /** * Returns the PrintWriter handling the underlying stream * @return the PrintWriter handling the underlying stream */ public PrintWriter getWriter() { return pw; } /** * @see Graphics2D#hit(Rectangle, Shape, boolean) */ public boolean hit(Rectangle rect, Shape s, boolean onStroke) { if (onStroke) { s = stroke.createStrokedShape(s); } s = transform.createTransformedShape(s); Area area = new Area(s); if (clip != null) area.intersect(clip); return area.intersects(rect.x, rect.y, rect.width, rect.height); } /** * This initialises the stream by saving the current graphics state, and * setting up the default line width (for us). * * It also sets up the instance ready for graphic operations and any * optimisations. * *

For child instances, the stream is already open, so this should keep * things happy. */ private void init() { PageFormat pf = page.getPageFormat(); // save graphics state (restored by dispose) if(child) { pw.print("q "); } // now initialise the instance //setColor(Color.black); paint = Color.black; // possible: if parent.color is not black, then force black? // must check to see what AWT does? // Original User Space Transform (identity) oTransform = new AffineTransform(); // Transform from Java Space to PDF Space pTransform = new AffineTransform(); pTransform.translate(0, pf.getHeight()); pTransform.scale(1d, -1d); // Combined Transform User->Java->PDF transform = new AffineTransform(oTransform); transform.concatenate(pTransform); // Set the line width setStroke(DEF_STROKE); } /** * This is called by PDFPage when creating a Graphcis instance. * @param page The PDFPage to draw onto. */ protected void init(PDFPage page) { this.page = page; // We are the parent instance child = false; // Now create a stream to store the graphics in PDFStream stream = new PDFStream(); // To view detail in uncompressed format comment out the next line stream.setDeflate(true); page.getPDFDocument().add(stream); page.add(stream); pw = stream.getWriter(); // initially, we are limited to the page size clipRectangle = page.getImageableArea(); // finally initialise the stream init(); } /** * This method is used internally by create() and by the PDFJob class * @param page PDFPage to draw into * @param pw PrintWriter to use */ protected void init(PDFPage page,PrintWriter pw) { this.page = page; this.pw = pw; // In this case, we didn't create the stream (our parent did) // so child is true (see dispose) child = true; // finally initialise the stream init(); } /** * This adds a line segment to the current path * @param x coordinate * @param y coordinate */ public void lineto(double x,double y) { newPath(); // no optimisation here as it may introduce errors on decimal coordinates. pw.print(cxy(x,y)+"l "); lx=(float)x; ly=(float)y; } /** * This adds a line segment to the current path * @param x coordinate * @param y coordinate */ public void lineto(int x,int y) { newPath(); if(lx!=x && ly!=y) pw.print(cxy(x,y)+"l "); lx=x; ly=y; } /** * This moves the current drawing point. * @param x coordinate * @param y coordinate */ public void moveto(double x,double y) { newPath(); // no optimisation here as it may introduce errors on decimal coordinates. pw.print(cxy(x,y)+"m "); lx=(float)x; ly=(float)y; } /** * This moves the current drawing point. * @param x coordinate * @param y coordinate */ public void moveto(int x,int y) { newPath(); if(lx!=x || ly!=y) pw.print(cxy(x,y)+"m "); lx=x; ly=y; } /** * Functions that draw lines should start by calling this. It starts a * new path unless inStroke is set, in that case it uses the existing path */ void newPath() { if(inText) { closeBlock(); } if(!inStroke) { if(pre_np!=null) { pw.print(pre_np); // this is the prefix set by setOrientation() pre_np = null; } pw.print("n "); } inText=false; inStroke=true; // an unlikely coordinate to fool the moveto() optimizer lx = ly = -9999; } /** *

Functions that draw text should start by calling this. It starts a text * block (accounting for media orientation) unless we are already in a Text * block.

* *

It also handles if the font has been changed since the current text * block was started, so your function will be current.

* * @param x x coordinate in java space * @param y y coordinate in java space */ void newTextBlock(float x,float y) { // close the current path if there is one if(inStroke) { closeBlock(); } // create the text block if one is not current. If we are, the newFont // condition at the end catches font changes if(!inText) { // This ensures that there is a font available getFont(); pw.print("q BT "); tx=ty=0; // produce the text matrix for the media // switch(mediaRot) { // case PageFormat.PORTRAIT: // Portrait // //pw.println("1 0 0 1 0 0 Tm"); // break; // // case PageFormat.LANDSCAPE: // Landscape // pw.println("0 1 -1 0 0 0 Tm"); // rotate // break; // // case 180: // Inverted Portrait // pw.println("1 0 0 -1 0 0 Tm"); // break; // // case PageFormat.REVERSE_LANDSCAPE: // Seascape // pw.println("0 -1 1 0 0 0 Tm"); // rotate // break; // } // move the text cursor by an absolute amount pw.print(txy(x,y)+"Td "); } else { // move the text cursor by a relative amount //int ox=x-tx, oy=ty-y; //pw.print(""+ox+" "+oy+" Td "); //pw.print(cwh(x-tx,y-ty)+"Td "); pw.print(twh(x,y,tx,ty)+"Td "); } // preserve the coordinates for the next time tx = x; ty = y; if(newFont || !inText) pw.print(pdffont.getName()+" "+font.getSize()+" Tf "); // later add colour changes here (if required) inStroke = newFont = false; inText = true; } /** * This is used to add a polygon to the current path. * Used by drawPolygon(), drawPolyline() and fillPolygon() etal * @param xp Array of x coordinates * @param yp Array of y coordinates * @param np number of points in polygon * @see #drawPolygon * @see #drawPolyline * @see #fillPolygon */ public void polygon(int[] xp,int[] yp,int np) { // newPath() not needed here as moveto does it ;-) moveto(xp[0],yp[0]); for(int i=1;iSets the clipping region to that of a Shape. * @param s Shape to clip to. */ public void setClip(Shape s) { Rectangle r = s.getBounds(); setClip(r.x,r.y,r.width,r.height); } /** * Sets the color for drawing * @param c Color to use */ public void setColor(Color c) { setPaint(c); } /** * @see Graphics2D#setComposite(Composite) */ public void setComposite(Composite comp) { this.composite = comp; } /** * This extension sets the line width to the default of 1mm which is what * Java uses when drawing to a PrintJob. */ public void setDefaultLineWidth() { closeBlock(); // draw any path before we change the line width pw.println("1 w"); } /** * This sets the font. * @param f java.awt.Font to set to. */ public void setFont(Font f) { // optimize: Save some space if the font is already the current one. if(font!=f) { font = f; pdffont = page.getFont("/Type1",f.getName(),f.getStyle()); // mark the font as changed newFont = true; } } private void setLineCap(int cap) { int lineCap = 0; switch (cap) { case BasicStroke.JOIN_MITER: lineCap = 0; break; case BasicStroke.JOIN_ROUND: lineCap = 1; break; case BasicStroke.JOIN_BEVEL: lineCap = 2; break; } if (this.lineCap != lineCap) { closeBlock(); // draw any path before we change the line width this.lineCap = lineCap; pw.println(""+lineCap+" J"); } } private void setLineJoin(int join) { int lineJoin = 0; switch (join) { case BasicStroke.JOIN_MITER: lineJoin = 0; break; case BasicStroke.JOIN_ROUND: lineJoin = 1; break; case BasicStroke.JOIN_BEVEL: lineJoin = 2; break; } if (this.lineJoin != lineJoin) { closeBlock(); // draw any path before we change the line width this.lineJoin = lineJoin; pw.println(""+lineJoin+" j"); } } /** * This extension allows the width of the drawn line to be set * @param width Line width in pdf graphic units (points) */ public void setLineWidth(float width) { if (width != this.lineWidth) { closeBlock(); // draw any path before we change the line width this.lineWidth = width; pw.println(""+width+" w"); } } private void setMiterLimit(float limit) { if (limit != this.miterLimit) { closeBlock(); // draw any path before we change the line width this.miterLimit = limit; pw.println(""+limit+" M"); } } /** * Sets the paint for drawing * @param paint Paint to use */ public void setPaint(Paint paint) { this.paint = paint; if (paint instanceof Color) { Color c = (Color) paint; double r = ((double) c.getRed()) / 255.0; double g = ((double) c.getGreen()) / 255.0; double b = ((double) c.getBlue()) / 255.0; closeBlock(); // This ensures any paths are drawn in the previous // colours pw.println("" + r + " " + g + " " + b + " rg " + r + " " + g + " " + b + " RG"); } } /** * Not implemented, as this is not supported in the PDF specification. */ public void setPaintMode() { } /** * Sets a rendering hint * @param arg0 * @param arg1 */ public void setRenderingHint(Key arg0, Object arg1) { if (arg1 != null) { rhints.put(arg0, arg1); } else { rhints.remove(arg0); } } // Add Graphics2D methods. /** * @see Graphics2D#setRenderingHints(Map) */ public void setRenderingHints(Map hints) { rhints.clear(); rhints.putAll(hints); } /** * @see Graphics2D#setStroke(Stroke) */ public void setStroke(Stroke s) { originalStroke = s; this.stroke = transformStroke(s); if (stroke instanceof BasicStroke) { BasicStroke bs = (BasicStroke) stroke; setLineCap(bs.getEndCap()); setLineJoin(bs.getLineJoin()); setLineWidth(bs.getLineWidth()); setMiterLimit(bs.getMiterLimit()); // TODO: Line dash pattern } } /** * @see Graphics2D#setTransform(AffineTransform) */ public void setTransform(AffineTransform t) { // Save copy of original transform. oTransform = t; // Working copy of transform transform = new AffineTransform(t); // Concatenate Java Space to PDF Space transform transform.concatenate(pTransform); this.stroke = transformStroke(originalStroke); } /** * Not implemented, as this is not supported in the PDF specification. * @param c1 Color to xor with */ public void setXORMode(Color c1) { } //============ Text operations ======================= /** * @see Graphics2D#shear(double, double) */ public void shear(double shx, double shy) { transform.shear(shx, shy); } /** * @see Graphics2D#transform(AffineTransform) */ public void transform(AffineTransform tx) { transform.concatenate(tx); this.stroke = transformStroke(originalStroke); } private Stroke transformStroke(Stroke stroke) { if (!(stroke instanceof BasicStroke)) return stroke; BasicStroke st = (BasicStroke)stroke; float scale = (float)Math.sqrt(Math.abs(transform.getDeterminant())); float dash[] = st.getDashArray(); if (dash != null) { for (int k = 0; k < dash.length; ++k) dash[k] *= scale; } return new BasicStroke(st.getLineWidth() * scale, st.getEndCap(), st.getLineJoin(), st.getMiterLimit(), dash, st.getDashPhase() * scale); } /** * @see Graphics2D#translate(double, double) */ public void translate(double tx, double ty) { transform.translate(tx, ty); trax = (float) tx; tray = (float) ty; } /** * @see Graphics#translate(int, int) */ public void translate(int x, int y) { translate((double)x, (double)y); } /** * Converts the Java space coordinates into pdf text space. * @param x coordinate * @param y coordinate * @param tx coordinate * @param ty coordinate * @return String containing the coordinates in PDF text space */ private String twh(float x,float y,float tx,float ty) { float nx=x, ny=y; float ntx=tx, nty=ty; int mh = (int) page.getPageFormat().getHeight(); int sx=1,sy=1; // switch(mediaRot) // { // case PageFormat.PORTRAIT: // Portrait //nx = x; ny = mh - y; nty = mh - ty; // break; // // case PageFormat.LANDSCAPE: // // Landscape // //nx = y; // //ny = x; // //ntx = ty; // //nty = tx; // //sy=-1; // nx = x; // ny = -y; // ntx = tx; // nty = -ty; // //sy=-1; // break; // // case 180: // // Inverse Portrait // // to be completed // nx = mw - x; // //ny = y; // break; // // case PageFormat.REVERSE_LANDSCAPE: // // Seascape // // to be completed // nx = mw - y; // ny = mh - x; // break; // } nx = sx*(nx-ntx); ny = sy*(ny-nty); return ""+df.format(nx)+" "+df.format(ny)+" "; } /** * Converts the Java space coordinates into pdf text space. * @param x coordinate * @param y coordinate * @return String containing the coordinates in PDF text space */ private String txy(float x,float y) { // float nx=x, ny=y; // int mh = (int) page.getPageFormat().getHeight(); Point2D ptSrc = new Point2D.Float(x, y); Point2D ptDst = new Point2D.Float(); transform.transform(ptSrc, ptDst); // // handle any translations // x+=trax; // y+=tray; // // nx = x; // ny = mh - y; // // System.out.println("\ntxy(" + ptSrc.getX() + ", " + ptSrc.getY() + ")"); // System.out.println("Old [" + nx + "," + ny + "]"); // System.out.println("Trn [" + ptDst.getX() + ", " + ptDst.getY() + "]"); // // return ""+df.format(nx)+" "+df.format(ny)+" "; return ""+df.format(ptDst.getX())+" "+df.format(ptDst.getY())+" "; } } // end class PDFGraphics \ No newline at end of file +/* * $Id: PDFGraphics.java,v 1.6 2007/09/22 12:58:40 gil1 Exp $ * * $Date: 2007/09/22 12:58:40 $ * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package gnu.jpdf; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Composite; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Frame; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.Image; 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.RenderingHints.Key; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; import java.awt.geom.Area; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; 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.awt.print.PageFormat; import java.io.PrintWriter; import java.io.Serializable; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Hashtable; import java.util.Locale; import java.util.Map; import java.util.WeakHashMap; /** * This class is our implementation of AWT's Graphics class. It provides a * Java standard way of rendering into a PDF Document's Page. * * @author Peter T Mount, http://www.retep.org.uk/pdf/ * @author Eric Z. Beard, ericzbeard@hotmail.com * @author Gilbert DeLeeuw, gil1@users.sourceforge.net * @version $Revision: 1.6 $, $Date: 2007/09/22 12:58:40 $ * @see gnu.jpdf.PDFGraphics */ public class PDFGraphics extends Graphics2D implements Serializable { /** * One degree in radians */ private static final double degrees_to_radians = Math.PI/180.0; private static final int FILL = 1; private static final int STROKE = 2; private static final int CLIP = 3; private static final AffineTransform IDENTITY = new AffineTransform(); private static final Stroke DEF_STROKE = new BasicStroke(); /* * NOTE: The original class is the work of Peter T. Mount, who released it * in the uk.org.retep.pdf package. It was modified by Eric Z. Beard as * follows: * The package name was changed to gnu.pdf. * The formatting was changed a little bit. * This used to subclass an abstract class in a different package with * the same name (confusing). Now it's one concrete class. * drawImage() was implemented * It is still licensed under the LGPL. */ // Implementation notes: // // Pages 333-335 of the PDF Reference Manual // // Unless absolutely required, use the moveto, lineto and rectangle // operators to perform those actions. // They contain some extra optimizations // which will reduce the output size by up to half in some cases. // // About fill operators: For correct operation, any fill operation should // start with closeBlock(), which will ensure any previous path is completed, // otherwise you may find the fill will include previous items private static final DecimalFormat df = new DecimalFormat("#.###", new DecimalFormatSymbols(Locale.ENGLISH)); //JPEXS: fix "," //JPEXS: cache for already used images private static Map usedImages = new WeakHashMap(); private Color background; /** * This is true for any Graphics instance that didn't create the stream. * @see #create */ private boolean child; private Area clip; /** * This holds the current clipRectangle */ protected Rectangle clipRectangle; private Composite composite; private Graphics2D dg2 = new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB).createGraphics(); /** * This is the current font (in Java format) */ private Font font; /** * Part of the optimizer: * When true, we are drawing a path. */ private boolean inStroke; /** * Part of the optimizer: * When true, we are within a Text Block. */ private boolean inText; // true if within a Text Block - see newTextBlock() /** * The stroke line cap code; */ private int lineCap = 0; /** * The stroke line join code */ private int lineJoin = 0; /** * The stroke line width */ private float lineWidth = 1.0f; /** * Part of the optimizer: * The last known moveto/lineto x coordinate * @see #moveto * @see #lineto */ private float lx; // last known moveto/lineto coordinates /** * Part of the optimizer: * The last known moveto/lineto y coordinate * @see #moveto * @see #lineto */ private float ly; // last known moveto/lineto coordinates private float miterLimit = 10.0f; /** * Part of the optimizer: * When true, the font has changed. */ private boolean newFont; // true if the font changes - see newTextBlock() private Stroke originalStroke; // Original transform private AffineTransform oTransform; /** * This is a reference to the PDFPage we are rendering to. */ private PDFPage page; /** * This is the current pen/fill color */ private Paint paint; /** * This is the current font (in PDF format) */ private PDFFont pdffont; /** * Part of the optimizer: * This is written to the stream when the newPath() is called. np then clears * this value. */ private String pre_np; // PDF space transform private AffineTransform pTransform; /** * This is the PrintWriter used to write PDF drawing commands to the Stream */ private PrintWriter pw; /** * RenderingHints */ private RenderingHints rhints = new RenderingHints(null); private Stroke stroke; // Start of Graphics2D properties // Java space transform private AffineTransform transform; /** * This is used to translate coordinates */ protected float trax; /** * This is used to translate coordinates */ protected float tray; /** * Part of the optimizer: * The last x coordinate when rendering text */ private float tx; // the last coordinate for text rendering /** * Part of the optimizer: * The last y coordinate when rendering text */ private float ty; // the last coordinate for text rendering /** * @see Graphics2D#addRenderingHints(Map) */ public void addRenderingHints(Map hints) { rhints.putAll(hints); } /** * This produces an arc by breaking it down into one or more Bezier curves. * It is used internally to implement the drawArc and fillArc methods. * * @param axc X coordinate of arc centre * @param ayc Y coordinate of arc centre * @param width of bounding rectangle * @param height of bounding rectangle * @param ang1 Start angle * @param ang2 End angle * @param clockwise true to draw clockwise, false anti-clockwise */ public void arc(double axc,double ayc, double width,double height, double ang1,double ang2, boolean clockwise) { double adiff; double x0, y0; double x3r, y3r; boolean first = true; // may not need this //if( ar < 0 ) { //ang1 += fixed_180; //ang2 += fixed_180; //ar = - ar; //} double ang1r = (ang1%360.0)*degrees_to_radians; double sin0 = Math.sin(ang1r); double cos0 = Math.cos(ang1r); x0 = axc + width*cos0; y0 = ayc + height*sin0; // NB: !clockwise here as Java Space is inverted to User Space if( !clockwise ) { // Quadrant reduction while ( ang1 < ang2 ) ang2 -= 360.0; while ( (adiff = ang2 - ang1) < -90.0 ) { double w = sin0; sin0 = -cos0; cos0 = w; x3r = axc + width*cos0; y3r = ayc + height*sin0; arc_add(first, width, height, x0, y0, x3r, y3r, (x0 + width*cos0), (y0 + height*sin0) ); x0 = x3r; y0 = y3r; ang1 -= 90.0; first = false; } } else { // Quadrant reduction while ( ang2 < ang1 ) ang2 += 360.0; while ( (adiff = ang2 - ang1) > 90.0 ) { double w = cos0; cos0 = -sin0; sin0 = w; x3r = axc + width*cos0; y3r = ayc + height*sin0; arc_add(first, width, height, x0, y0, x3r, y3r, (x0 + width*cos0), (y0 + height*sin0) ); x0 = x3r; y0 = y3r; ang1 += 90.0; first = false; } } // Compute the intersection of the tangents. // We know that -fixed_90 <= adiff <= fixed_90. double trad = Math.tan(adiff * (degrees_to_radians / 2)); double ang2r = ang2 * degrees_to_radians; double xt = x0 - trad * width*sin0; double yt = y0 + trad * height*cos0; arc_add(first, width, height, x0, y0, (axc + width * Math.cos(ang2r)), (ayc + height * Math.sin(ang2r)), xt, yt); } /** * Used by the arc method to actually add an arc to the path * Important: We write directly to the stream here, because this method * operates in User space, rather than Java space. * @param first true if the first arc * @param w width * @param h height * @param x0 coordinate * @param y0 coordinate * @param x3 coordinate * @param y3 coordinate * @param xt coordinate * @param yt coordinate */ private void arc_add(boolean first, double w,double h, double x0,double y0, double x3,double y3, double xt,double yt) { double dx = xt - x0, dy = yt - y0; double dist = dx*dx + dy*dy; double w2 = w*w, h2=h*h; double r2 = w2+h2; double fw = 0.0, fh = 0.0; if(dist < (r2*1.0e8)) { // JM fw = (w2 != 0.0) ? ((4.0/3.0)/(1+Math.sqrt(1+dist/w2))) : 0.0; fh = (h2 != 0.0) ? ((4.0/3.0)/(1+Math.sqrt(1+dist/h2))) : 0.0; } // The path must have a starting point if(first) moveto(x0,y0); double x = x0+((xt-x0)*fw); double y = y0+((yt-y0)*fh); x0 = x3+((xt-x3)*fw); y0 = y3+((yt-y3)*fh); // Finally the actual curve. curveto(x,y,x0,y0,x3,y3); } /** * This simply draws a White Rectangle to clear the area * @param x coordinate * @param y coordinate * @param w width * @param h height */ public void clearRect(int x,int y,int w,int h) { closeBlock(); pw.print("q 1 1 1 RG ");// save state, set colour to White drawRect(x,y,w,h); closeBlock("B Q"); // close fill & stroke, then restore state } /** * @see Graphics2D#clip(Shape) */ public void clip(Shape s) { if (s == null) { setClip(null); return; } s = transform.createTransformedShape(s); if (clip == null) clip = new Area(s); else clip.intersect(new Area(s)); // followPath(s, CLIP); } /** * This extra method allows PDF users to clip to a Polygon. * *

In theory you could use setClip(), except that java.awt.Graphics * only supports Rectangle with that method, so we will have an extra * method. * @param p Polygon to clip to */ public void clipPolygon(Polygon p) { closeBlock(); // finish off any existing path polygon(p.xpoints,p.ypoints,p.npoints); closeBlock("W"); // clip to current path clipRectangle = p.getBounds(); } /** * Clips to a set of coordinates * @param x coordinate * @param y coordinate * @param w width * @param h height */ public void clipRect(int x,int y,int w,int h) { setClip(x,y,w,h); } /** * All functions should call this to close any existing optimized blocks. */ void closeBlock() { closeBlock("S"); } /** *

This is used by code that use the path in any way other than Stroke * (like Fill, close path & Stroke etc). Usually this is used internally.

* * @param code PDF operators that will close the path */ void closeBlock(String code) { if(inText) { pw.println("ET Q"); // setOrientation(); // fixes Orientation matrix } if(inStroke) { pw.println(code); } inStroke=inText=false; } /** * This is unsupported - how do you do this with Vector graphics? * @param x coordinate * @param y coordinate * @param w width * @param h height * @param dx coordinate * @param dy coordinate */ public void copyArea(int x,int y,int w,int h,int dx,int dy) { // Hmm... Probably need to keep track of everything // that has been drawn so far to get the contents of an area } //============ Line operations ======================= /** *

This returns a child instance of this Graphics object. As with AWT, the * affects of using the parent instance while the child exists, is not * determined.

* *

Once complete, the child should be released with it's dispose() * method which will restore the graphics state to it's parent.

* * @return Graphics object to render onto the page */ public Graphics create() { closeBlock(); PDFGraphics g = createGraphic(page,pw); // The new instance inherits a few items // g.media = new Rectangle(media); g.trax = trax; g.tray = tray; g.clipRectangle = new Rectangle(clipRectangle); return (Graphics) g; } // end create() /** * This method creates a new instance of the class based on the page * and a print writer. * * @param page the page to attach to * @param pw the PrintWriter to attach to. */ protected PDFGraphics createGraphic(PDFPage page, PrintWriter pw) { PDFGraphics g = new PDFGraphics(); g.init(page,pw); return g; } /** * This extension appends a Bezier curve to the path. The curve * extends from the current point to (x2,y2) using the current * point and (x1,y1) as the Bezier control points. *

The new current point is (x2,y2) * * @param x1 Second control point * @param y1 Second control point * @param x2 Destination point * @param y2 Destination point */ public void curveto(double x1,double y1,double x2,double y2) { newPath(); pw.println(cxy(x1,y1)+cxy(x2,y2)+"v"); lx=(float)x2; ly=(float)y2; } /** * This extension appends a Bezier curve to the path. The curve * extends from the current point to (x3,y3) using (x1,y1) and * (x2,y2) as the Bezier control points. *

The new current point is (x3,y3) * * @param x1 First control point * @param y1 First control point * @param x2 Second control point * @param y2 Second control point * @param x3 Destination point * @param y3 Destination point */ public void curveto(double x1,double y1,double x2,double y2,double x3,double y3) { newPath(); pw.println(cxy(x1,y1)+cxy(x2,y2)+cxy(x3,y3)+"c"); lx=(float)x3; ly=(float)y3; } /** * This extension appends a Bezier curve to the path. The curve * extends from the current point to (x2,y2) using the current * point and (x1,y1) as the Bezier control points. *

The new current point is (x2,y2) * * @param x1 Second control point * @param y1 Second control point * @param x2 Destination point * @param y2 Destination point */ public void curveto(int x1,int y1,int x2,int y2) { newPath(); pw.println(cxy(x1,y1)+cxy(x2,y2)+"v"); lx=x2; ly=y2; } /** * This extension appends a Bezier curve to the path. The curve * extends from the current point to (x3,y3) using (x1,y1) and * (x2,y2) as the Bezier control points. *

The new current point is (x3,y3) * * @param x1 First control point * @param y1 First control point * @param x2 Second control point * @param y2 Second control point * @param x3 Destination point * @param y3 Destination point */ public void curveto(int x1,int y1,int x2,int y2,int x3,int y3) { newPath(); pw.println(cxy(x1,y1)+cxy(x2,y2)+cxy(x3,y3)+"c"); lx=x3; ly=y3; } /** * This extension appends a Bezier curve to the path. The curve * extends from the current point to (x2,y2) using (x1,y1) and * the end point as the Bezier control points. *

The new current point is (x2,y2) * * @param x1 Second control point * @param y1 Second control point * @param x2 Destination point * @param y2 Destination point */ public void curveto2(double x1,double y1,double x2,double y2) { newPath(); pw.println(cxy(x1,y1)+cxy(x2,y2)+"y"); lx=(float)x2; ly=(float)y2; } // Arcs are horrible and complex. They are at the end of the // file, because they are the largest. This is because, unlike // Postscript, PDF doesn't have any arc operators, so we must // implement them by converting into one or more Bezier curves // (which is how Postscript does them internally). /** * This extension appends a Bezier curve to the path. The curve * extends from the current point to (x2,y2) using (x1,y1) and * the end point as the Bezier control points. *

The new current point is (x2,y2) * * @param x1 Second control point * @param y1 Second control point * @param x2 Destination point * @param y2 Destination point */ public void curveto2(int x1,int y1,int x2,int y2) { newPath(); pw.println(cxy(x1,y1)+cxy(x2,y2)+"y"); lx=x2; ly=y2; } /** * Converts the Java space dimension into pdf. * @param w width * @param h height * @return String containing the coordinates in PDF space */ private String cwh(double w,double h) { double nw=w,nh=h; // scratch // switch(mediaRot) { // case PageFormat.PORTRAIT: // Portrait //nw = w; nh = -h; // break; // // case PageFormat.LANDSCAPE: // // Landscape // nw = h; // nh = w; // break; // //// case 180: //// // Inverse Portrait //// nw = -w; //// //nh = h; //// break; // // case PageFormat.REVERSE_LANDSCAPE: // // Seascape // nw = -h; // nh = -w; // break; // } return ""+df.format(nw)+" "+df.format(nh)+" "; } /** * Converts the Java space dimension into pdf. * @param w width * @param h height * @return String containing the coordinates in PDF space */ private String cwh(int w,int h) { return cwh((double)w,(double)h); } /** * Converts the Java space coordinates into pdf. * @param x coordinate * @param y coordinate * @return String containing the coordinates in PDF space */ private String cxy(double x, double y) { // double nx = x, ny = y; // scratch // double mh = page.getPageFormat().getHeight(); Point2D ptSrc = new Point2D.Double(x, y); Point2D ptDst = new Point2D.Double(); transform.transform(ptSrc, ptDst); // x += trax; // y += tray; // // nx = x; // ny = mh - y; // // System.out.println("\ncxy(" + ptSrc.getX() + ", " + ptSrc.getY() + ")"); // System.out.println("Old [" + nx + "," + ny + "]"); // System.out.println("Trn [" + ptDst.getX() + ", " + ptDst.getY() + "]"); // // return "" + df.format(nx) + " " + df.format(ny) + " "; return ""+df.format(ptDst.getX())+" "+df.format(ptDst.getY())+" "; } /** * Converts the Java space coordinates into pdf. * @param x coordinate * @param y coordinate * @return String containing the coordinates in PDF space */ private String cxy(int x,int y) { return cxy((double)x,(double)y); } /** *

This releases any resources used by this Graphics object. You must use * this method once finished with it. Leaving it open will leave the PDF * stream in an inconsistent state, and will produce errors.

* *

If this was created with Graphics.create() then the parent instance * can be used again. If not, then this closes the graphics operations for * this page when used with PDFJob.

* *

When using PDFPage, you can create another fresh Graphics instance, * which will draw over this one.

* */ public void dispose() { closeBlock(); if(child) { pw.println("Q"); // restore graphics context } else { pw.close(); // close the stream if were the parent } } // ********************************************* // **** Implementation of java.awt.Graphics **** // ********************************************* //============ Rectangle operations ======================= /** * @see Graphics2D#draw(Shape) */ public void draw(Shape s) { followPath(s, STROKE); } /** *

Not implemented

* *

Draws a 3-D highlighted outline of the specified rectangle. * The edges of the rectangle are highlighted so that they appear * to be beveled and lit from the upper left corner. * The colors used for the highlighting effect are determined based on * the current color. The resulting rectangle covers an area that * is width + 1 pixels wide by height + 1 pixels tall. *

* * @param x an int value * @param y an int value * @param width an int value * @param height an int value * @param raised a boolean value */ public void draw3DRect(int x, int y, int width, int height, boolean raised) { // Not implemented } /** * Draws an arc * @param x coordinate * @param y coordinate * @param w width * @param h height * @param sa Start angle * @param aa End angle */ public void drawArc(int x,int y,int w,int h,int sa,int aa) { w=w>>1; h=h>>1; x+=w; y+=h; arc((double)x,(double)y, (double)w,(double)h, (double)-sa,(double)(-sa-aa), false); } /** *

Not implemented

* * @param data a byte[] value * @param offset an int value * @param length an int value * @param x an int value * @param y an int value */ public void drawBytes(byte[] data, int offset, int length, int x, int y) { } //============ Optimizers ======================= /** * @see Graphics2D#drawGlyphVector(GlyphVector, float, float) */ public void drawGlyphVector(GlyphVector g, float x, float y) { Shape s = g.getOutline(x, y); fill(s); } /** * @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#drawImage(Image, AffineTransform, ImageObserver) */ public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { // return drawImage(img, null, xform, null, obs); return true; } /** *

Draw's an image onto the page, with a backing colour.

* * @param img The java.awt.Image * @param x coordinate on page * @param y coordinate on page * @param bgcolor Background colour * @param obs ImageObserver * @return true if drawn */ public boolean drawImage(Image img,int x,int y,Color bgcolor, ImageObserver obs) { return drawImage(img,x,y,img.getWidth(obs),img.getHeight(obs), bgcolor,obs); } /** * Draw's an image onto the page * @param img The java.awt.Image * @param x coordinate on page * @param y coordinate on page * @param obs ImageObserver * @return true if drawn */ public boolean drawImage(Image img,int x,int y,ImageObserver obs) { return drawImage(img,x,y,img.getWidth(obs),img.getHeight(obs),obs); } /** *

Draw's an image onto the page, with a backing colour.

* * @param img The java.awt.Image * @param x coordinate on page * @param y coordinate on page * @param w Width on page * @param h height on page * @param bgcolor Background colour * @param obs ImageObserver * @return true if drawn */ public boolean drawImage(Image img,int x,int y,int w,int h, Color bgcolor,ImageObserver obs) { closeBlock(); pw.print("q "); // save state Color c = getColor(); // save current colour setColor(bgcolor); // change the colour drawRect(x,y,w,h); closeBlock("B Q"); // fill stroke, restore state paint = c; // restore original colour return drawImage(img,x,y,img.getWidth(obs),img.getHeight(obs),obs); } /** *

Draws an image onto the page.

* *

This method is implemented with ASCIIbase85 encoding and the * zip stream deflater. It results in a stream that is anywhere * from 3 to 10 times as big as the image. This obviously needs some * improvement, but it works well for small images

* * @param img The java.awt.Image * @param x coordinate on page * @param y coordinate on page * @param w Width on page * @param h height on page * @param obs ImageObserver * @return true if drawn */ public boolean drawImage(Image img,int x,int y,int w,int h, ImageObserver obs) { closeBlock(); PDFImage image; if(usedImages.containsKey(img)){ image = usedImages.get(img); }else{ image = new PDFImage(img,obs); // The image needs to be registered in several places page.getPDFDocument().setImageName(image); page.getPDFDocument().add(image); usedImages.put(img, image); } page.addToProcset("/ImageC"); page.addImageResource(image.getName() + " " + image.getSerialID() + " 0 R"); // JM /*page.addResource("/XObject << " + image.getName() + " " + image.getSerialID() + " 0 R >>");*/ // q w 0 0 h x y cm % the coordinate matrix pw.print("q " + w+ " 0 0 " + h+ " " + x + " " + ((int)page.getDimension().getHeight()-y-h) + " cm \n" + image.getName() + " Do\nQ\n"); return false; } /** * Draw's an image onto the page, with scaling *

This is not yet supported. * * @param img The java.awt.Image * @param dx1 coordinate on page * @param dy1 coordinate on page * @param dx2 coordinate on page * @param dy2 coordinate on page * @param sx1 coordinate on image * @param sy1 coordinate on image * @param sx2 coordinate on image * @param sy2 coordinate on image * @param bgcolor Background colour * @param obs ImageObserver * @return true if drawn */ public boolean drawImage(Image img,int dx1,int dy1,int dx2, int dy2,int sx1,int sy1,int sx2,int sy2, Color bgcolor,ImageObserver obs) { return false; } //============ Clipping operations ======================= /** * Draw's an image onto the page, with scaling *

This is not yet supported. * * @param img The java.awt.Image * @param dx1 coordinate on page * @param dy1 coordinate on page * @param dx2 coordinate on page * @param dy2 coordinate on page * @param sx1 coordinate on image * @param sy1 coordinate on image * @param sx2 coordinate on image * @param sy2 coordinate on image * @param obs ImageObserver * @return true if drawn */ public boolean drawImage(Image img,int dx1,int dy1,int dx2, int dy2,int sx1,int sy1,int sx2,int sy2, ImageObserver obs) { // This shouldn't be too bad, just change the coordinate matrix return false; } /** * Draws a line between two coordinates. * * If the first coordinate is the same as the last one drawn * (i.e. a previous drawLine, moveto, etc) it is ignored. * @param x1 coordinate * @param y1 coordinate * @param x2 coordinate * @param y2 coordinate */ public void drawLine(int x1,int y1,int x2,int y2) { moveto(x1,y1); lineto(x2,y2); } //============ Arcs operations ============================== // These are the standard Graphics operators. They use the // arc extension operators to achieve the affect. /** *

Draws an oval

* * @param x coordinate * @param y coordinate * @param w width * @param h height */ public void drawOval(int x,int y,int w,int h) { drawArc(x, y, w, h, 0, 360); } /** * Draws a polygon, linking the first and last coordinates. * @param xp Array of x coordinates * @param yp Array of y coordinates * @param np number of points in polygon */ public void drawPolygon(int[] xp,int[] yp,int np) { polygon(xp,yp,np); closeBlock("s"); // close path and stroke } /** * Draws a polyline. The first and last coordinates are not linked. * @param xp Array of x coordinates * @param yp Array of y coordinates * @param np number of points in polyline */ public void drawPolyline(int[] xp,int[] yp,int np) { polygon(xp,yp,np); // no stroke, as we keep the optimizer in stroke state } /** * We override Graphics.drawRect as it doesn't join the 4 lines. * Also, PDF provides us with a Rectangle operator, so we will use that. * @param x coordinate * @param y coordinate * @param w width * @param h height */ public void drawRect(int x,int y,int w,int h) { newPath(); pw.print(cxy(x,y)+cwh(w,h)+"re "); // rectangle lx=x; // I don't know if this is correct, but lets see if PDF ends ly=y; // the rectangle at it's start. // stroke (optimized) } /** * @see Graphics2D#drawRenderableImage(RenderableImage, AffineTransform) */ public void drawRenderableImage(RenderableImage img, AffineTransform xform) { drawRenderedImage(img.createDefaultRendering(), xform); } /** * @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); } /** * This is not yet implemented * * @param x coordinate * @param y coordinate * @param w width * @param h height * @param aw a-width * @param ah a-height */ public void drawRoundRect(int x,int y,int w,int h,int aw,int ah) { } //============ Oval operations ======================= /** * Draws a string using a AttributedCharacterIterator. *

This is not supported yet, as I have no idea what an * AttributedCharacterIterator is. *

This method is new to the Java2 API. */ public void drawString(java.text.AttributedCharacterIterator aci, float x,float y) { } /** * Draws a string using a AttributedCharacterIterator. *

This is not supported yet, as I have no idea what an * AttributedCharacterIterator is. *

This method is new to the Java2 API. */ public void drawString(java.text.AttributedCharacterIterator aci, int x,int y) { } public void drawString(String s,float x,float y) { newTextBlock(x, y); pw.println(PDFStringHelper.makePDFString(s)+" Tj"); } /** * This draws a string. * * @oaran s String to draw * @param x coordinate * @param y coordinate */ public void drawString(String s,int x,int y) { newTextBlock(x,y); pw.println(PDFStringHelper.makePDFString(s)+" Tj"); } /** * @see Graphics2D#fill(Shape) */ public void fill(Shape s) { followPath(s, FILL); } /** *

Not implemented

* * @param x an int value * @param y an int value * @param width an int value * @param height an int value * @param raised a boolean value */ public void fill3DRect(int x, int y, int width, int height, boolean raised) { // Not implemented } /** * Fills an arc, joining the start and end coordinates * @param x coordinate * @param y coordinate * @param w width * @param h height * @param sa Start angle * @param aa End angle */ public void fillArc(int x,int y,int w,int h,int sa,int aa) { // here we fool the optimizer. We force any open path to be closed, // then draw the arc. Finally, as the optimizer hasn't stroke'd the // path, we close and fill it, and mark the Stroke as closed. // // Note: The lineto to the centre of the object is required, because // the fill only fills the arc. Skipping this includes an extra // chord, which isn't correct. Peter May 31 2000 closeBlock(); drawArc(x,y,w,h,sa,aa); lineto(x+(w>>1),y+(h>>1)); closeBlock("b"); // closepath and fill } //============ Extension operations ============================== // These are extensions, and provide access to PDF Specific // operators. /** *

Draws a filled oval

* * @param x coordinate * @param y coordinate * @param w width * @param h height */ public void fillOval(int x,int y,int w,int h) { fillArc(x, y, w, h, 0, 360); } //============ Polygon operations ======================= /** * Fills a polygon. * @param xp Array of x coordinates * @param yp Array of y coordinates * @param np number of points in polygon */ public void fillPolygon(int[] xp,int[] yp,int np) { closeBlock(); // finish off any previous paths polygon(xp,yp,np); closeBlock("b"); // closepath, fill and stroke } //============ Image operations ======================= /** * Fills a rectangle with the current colour * * @param x coordinate * @param y coordinate * @param w width * @param h height */ public void fillRect(int x,int y,int w,int h) { // end any path & stroke. This ensures the fill is on this // rectangle, and not on any previous graphics closeBlock(); drawRect(x,y,w,h); closeBlock("B"); // rectangle, fill stroke } //============ Round Rectangle operations ======================= /** * This is not yet implemented * * @param x coordinate * @param y coordinate * @param w width * @param h height * @param aw a-width * @param ah a-height */ public void fillRoundRect(int x,int y,int w,int h,int aw,int ah) { } /////////////////////////////////////////////// // // // implementation specific methods // // private void followPath(Shape s, int drawType) { PathIterator points; if (s==null) return; if (drawType==STROKE) { if (!(stroke instanceof BasicStroke)) { s = stroke.createStrokedShape(s); followPath(s, FILL); return; } } // if (drawType==STROKE) { // setStrokeDiff(stroke, oldStroke); // oldStroke = stroke; // setStrokePaint(); // } // else if (drawType==FILL) // setFillPaint(); points = s.getPathIterator(IDENTITY); int segments = 0; float[] coords = new float[6]; while(!points.isDone()) { segments++; int segtype = points.currentSegment(coords); switch(segtype) { case PathIterator.SEG_CLOSE: pw.print("h "); break; case PathIterator.SEG_CUBICTO: curveto(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); break; case PathIterator.SEG_LINETO: lineto(coords[0], coords[1]); break; case PathIterator.SEG_MOVETO: moveto(coords[0], coords[1]); break; case PathIterator.SEG_QUADTO: curveto(coords[0], coords[1], coords[2], coords[3]); break; } points.next(); } switch (drawType) { case FILL: if (segments > 0) { if (points.getWindingRule() == PathIterator.WIND_EVEN_ODD) closeBlock("B*"); else closeBlock("B"); } break; case STROKE: if (segments > 0) closeBlock("S"); break; case CLIP: default: //drawType==CLIP if (segments == 0) drawRect(0, 0, 0, 0); if (points.getWindingRule() == PathIterator.WIND_EVEN_ODD) closeBlock("W*"); else closeBlock("W"); } } /** * @see Graphics2D#getBackground() */ public Color getBackground() { return background; } /** * Returns the Shape of the clipping region * As my JDK docs say, this may break with Java 2D. * @return Shape of the clipping region */ public Shape getClip() { return null; } /** * Returns the Rectangle that fits the current clipping region * @return the Rectangle that fits the current clipping region */ public Rectangle getClipBounds() { return clipRectangle; } //============ Color operations ======================= /** * Returns the current pen Colour * @return the current pen Colour */ public Color getColor() { return (paint instanceof Color) ? (Color) paint : Color.black; } /** * @see Graphics2D#getComposite() */ public Composite getComposite() { return composite; } /** * @see Graphics2D#getDeviceConfiguration() */ public GraphicsConfiguration getDeviceConfiguration() { return dg2.getDeviceConfiguration(); } /** * Return's the current font. * @return the current font. */ public Font getFont() { if(font==null) setFont(new Font("SansSerif",Font.PLAIN,12)); return font; } /** * Returns the FontMetrics for a font. *

This doesn't work correctly. Perhaps having some way of mapping * the base 14 fonts to our own FontMetrics implementation? * @param font The java.awt.Font to return the metrics for * @return FontMetrics for a font */ public FontMetrics getFontMetrics(Font font) { Frame dummy = new Frame(); dummy.addNotify(); Image image = dummy.createImage(100, 100); if (image == null) { System.err.println("getFontMetrics: image is null"); } Graphics graphics = image.getGraphics(); return graphics.getFontMetrics(font); } /** * @see Graphics2D#getFontRenderContext() */ public FontRenderContext getFontRenderContext() { boolean antialias = RenderingHints.VALUE_TEXT_ANTIALIAS_ON.equals(getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING)); boolean fractions = RenderingHints.VALUE_FRACTIONALMETRICS_ON.equals(getRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS)); return new FontRenderContext(new AffineTransform(), antialias, fractions); } /** * Returns the associated PDFPage for this graphic * @return the associated PDFPage for this graphic */ public PDFPage getPage() { return page; } /** * Returns the current pen Colour * @return the current pen Colour */ public Paint getPaint() { return paint; } /** * @param arg0 a key * @return the rendering hint */ public Object getRenderingHint(Key arg0) { return rhints.get(arg0); } /** * @see Graphics2D#getRenderingHints() */ public RenderingHints getRenderingHints() { return rhints; } /** * @see Graphics2D#getStroke() */ public Stroke getStroke() { return originalStroke; } /** * @see Graphics2D#getTransform() */ public AffineTransform getTransform() { return new AffineTransform(oTransform); } /** * Returns the PrintWriter handling the underlying stream * @return the PrintWriter handling the underlying stream */ public PrintWriter getWriter() { return pw; } /** * @see Graphics2D#hit(Rectangle, Shape, boolean) */ public boolean hit(Rectangle rect, Shape s, boolean onStroke) { if (onStroke) { s = stroke.createStrokedShape(s); } s = transform.createTransformedShape(s); Area area = new Area(s); if (clip != null) area.intersect(clip); return area.intersects(rect.x, rect.y, rect.width, rect.height); } /** * This initialises the stream by saving the current graphics state, and * setting up the default line width (for us). * * It also sets up the instance ready for graphic operations and any * optimisations. * *

For child instances, the stream is already open, so this should keep * things happy. */ private void init() { PageFormat pf = page.getPageFormat(); // save graphics state (restored by dispose) if(child) { pw.print("q "); } // now initialise the instance //setColor(Color.black); paint = Color.black; // possible: if parent.color is not black, then force black? // must check to see what AWT does? // Original User Space Transform (identity) oTransform = new AffineTransform(); // Transform from Java Space to PDF Space pTransform = new AffineTransform(); pTransform.translate(0, pf.getHeight()); pTransform.scale(1d, -1d); // Combined Transform User->Java->PDF transform = new AffineTransform(oTransform); transform.concatenate(pTransform); // Set the line width setStroke(DEF_STROKE); } /** * This is called by PDFPage when creating a Graphcis instance. * @param page The PDFPage to draw onto. */ protected void init(PDFPage page) { this.page = page; // We are the parent instance child = false; // Now create a stream to store the graphics in PDFStream stream = new PDFStream(); // To view detail in uncompressed format comment out the next line stream.setDeflate(true); page.getPDFDocument().add(stream); page.add(stream); pw = stream.getWriter(); // initially, we are limited to the page size clipRectangle = page.getImageableArea(); // finally initialise the stream init(); } /** * This method is used internally by create() and by the PDFJob class * @param page PDFPage to draw into * @param pw PrintWriter to use */ protected void init(PDFPage page,PrintWriter pw) { this.page = page; this.pw = pw; // In this case, we didn't create the stream (our parent did) // so child is true (see dispose) child = true; // finally initialise the stream init(); } /** * This adds a line segment to the current path * @param x coordinate * @param y coordinate */ public void lineto(double x,double y) { newPath(); // no optimisation here as it may introduce errors on decimal coordinates. pw.print(cxy(x,y)+"l "); lx=(float)x; ly=(float)y; } /** * This adds a line segment to the current path * @param x coordinate * @param y coordinate */ public void lineto(int x,int y) { newPath(); if(lx!=x && ly!=y) pw.print(cxy(x,y)+"l "); lx=x; ly=y; } /** * This moves the current drawing point. * @param x coordinate * @param y coordinate */ public void moveto(double x,double y) { newPath(); // no optimisation here as it may introduce errors on decimal coordinates. pw.print(cxy(x,y)+"m "); lx=(float)x; ly=(float)y; } /** * This moves the current drawing point. * @param x coordinate * @param y coordinate */ public void moveto(int x,int y) { newPath(); if(lx!=x || ly!=y) pw.print(cxy(x,y)+"m "); lx=x; ly=y; } /** * Functions that draw lines should start by calling this. It starts a * new path unless inStroke is set, in that case it uses the existing path */ void newPath() { if(inText) { closeBlock(); } if(!inStroke) { if(pre_np!=null) { pw.print(pre_np); // this is the prefix set by setOrientation() pre_np = null; } pw.print("n "); } inText=false; inStroke=true; // an unlikely coordinate to fool the moveto() optimizer lx = ly = -9999; } /** *

Functions that draw text should start by calling this. It starts a text * block (accounting for media orientation) unless we are already in a Text * block.

* *

It also handles if the font has been changed since the current text * block was started, so your function will be current.

* * @param x x coordinate in java space * @param y y coordinate in java space */ void newTextBlock(float x,float y) { // close the current path if there is one if(inStroke) { closeBlock(); } // create the text block if one is not current. If we are, the newFont // condition at the end catches font changes if(!inText) { // This ensures that there is a font available getFont(); pw.print("q BT "); tx=ty=0; // produce the text matrix for the media // switch(mediaRot) { // case PageFormat.PORTRAIT: // Portrait // //pw.println("1 0 0 1 0 0 Tm"); // break; // // case PageFormat.LANDSCAPE: // Landscape // pw.println("0 1 -1 0 0 0 Tm"); // rotate // break; // // case 180: // Inverted Portrait // pw.println("1 0 0 -1 0 0 Tm"); // break; // // case PageFormat.REVERSE_LANDSCAPE: // Seascape // pw.println("0 -1 1 0 0 0 Tm"); // rotate // break; // } // move the text cursor by an absolute amount pw.print(txy(x,y)+"Td "); } else { // move the text cursor by a relative amount //int ox=x-tx, oy=ty-y; //pw.print(""+ox+" "+oy+" Td "); //pw.print(cwh(x-tx,y-ty)+"Td "); pw.print(twh(x,y,tx,ty)+"Td "); } // preserve the coordinates for the next time tx = x; ty = y; if(newFont || !inText) pw.print(pdffont.getName()+" "+font.getSize()+" Tf "); // later add colour changes here (if required) inStroke = newFont = false; inText = true; } /** * This is used to add a polygon to the current path. * Used by drawPolygon(), drawPolyline() and fillPolygon() etal * @param xp Array of x coordinates * @param yp Array of y coordinates * @param np number of points in polygon * @see #drawPolygon * @see #drawPolyline * @see #fillPolygon */ public void polygon(int[] xp,int[] yp,int np) { // newPath() not needed here as moveto does it ;-) moveto(xp[0],yp[0]); for(int i=1;iSets the clipping region to that of a Shape. * @param s Shape to clip to. */ public void setClip(Shape s) { Rectangle r = s.getBounds(); setClip(r.x,r.y,r.width,r.height); } /** * Sets the color for drawing * @param c Color to use */ public void setColor(Color c) { setPaint(c); } /** * @see Graphics2D#setComposite(Composite) */ public void setComposite(Composite comp) { this.composite = comp; } /** * This extension sets the line width to the default of 1mm which is what * Java uses when drawing to a PrintJob. */ public void setDefaultLineWidth() { closeBlock(); // draw any path before we change the line width pw.println("1 w"); } /** * This sets the font. * @param f java.awt.Font to set to. */ public void setFont(Font f) { // optimize: Save some space if the font is already the current one. if(font!=f) { font = f; pdffont = page.getFont("/Type1",f.getName(),f.getStyle()); // mark the font as changed newFont = true; } } private void setLineCap(int cap) { int lineCap = 0; switch (cap) { case BasicStroke.JOIN_MITER: lineCap = 0; break; case BasicStroke.JOIN_ROUND: lineCap = 1; break; case BasicStroke.JOIN_BEVEL: lineCap = 2; break; } if (this.lineCap != lineCap) { closeBlock(); // draw any path before we change the line width this.lineCap = lineCap; pw.println(""+lineCap+" J"); } } private void setLineJoin(int join) { int lineJoin = 0; switch (join) { case BasicStroke.JOIN_MITER: lineJoin = 0; break; case BasicStroke.JOIN_ROUND: lineJoin = 1; break; case BasicStroke.JOIN_BEVEL: lineJoin = 2; break; } if (this.lineJoin != lineJoin) { closeBlock(); // draw any path before we change the line width this.lineJoin = lineJoin; pw.println(""+lineJoin+" j"); } } /** * This extension allows the width of the drawn line to be set * @param width Line width in pdf graphic units (points) */ public void setLineWidth(float width) { if (width != this.lineWidth) { closeBlock(); // draw any path before we change the line width this.lineWidth = width; pw.println(""+width+" w"); } } private void setMiterLimit(float limit) { if (limit != this.miterLimit) { closeBlock(); // draw any path before we change the line width this.miterLimit = limit; pw.println(""+limit+" M"); } } /** * Sets the paint for drawing * @param paint Paint to use */ public void setPaint(Paint paint) { this.paint = paint; if (paint instanceof Color) { Color c = (Color) paint; double r = ((double) c.getRed()) / 255.0; double g = ((double) c.getGreen()) / 255.0; double b = ((double) c.getBlue()) / 255.0; closeBlock(); // This ensures any paths are drawn in the previous // colours pw.println("" + r + " " + g + " " + b + " rg " + r + " " + g + " " + b + " RG"); } } /** * Not implemented, as this is not supported in the PDF specification. */ public void setPaintMode() { } /** * Sets a rendering hint * @param arg0 * @param arg1 */ public void setRenderingHint(Key arg0, Object arg1) { if (arg1 != null) { rhints.put(arg0, arg1); } else { rhints.remove(arg0); } } // Add Graphics2D methods. /** * @see Graphics2D#setRenderingHints(Map) */ public void setRenderingHints(Map hints) { rhints.clear(); rhints.putAll(hints); } /** * @see Graphics2D#setStroke(Stroke) */ public void setStroke(Stroke s) { originalStroke = s; this.stroke = transformStroke(s); if (stroke instanceof BasicStroke) { BasicStroke bs = (BasicStroke) stroke; setLineCap(bs.getEndCap()); setLineJoin(bs.getLineJoin()); setLineWidth(bs.getLineWidth()); setMiterLimit(bs.getMiterLimit()); // TODO: Line dash pattern } } /** * @see Graphics2D#setTransform(AffineTransform) */ public void setTransform(AffineTransform t) { // Save copy of original transform. oTransform = t; // Working copy of transform transform = new AffineTransform(t); // Concatenate Java Space to PDF Space transform transform.concatenate(pTransform); this.stroke = transformStroke(originalStroke); } /** * Not implemented, as this is not supported in the PDF specification. * @param c1 Color to xor with */ public void setXORMode(Color c1) { } //============ Text operations ======================= /** * @see Graphics2D#shear(double, double) */ public void shear(double shx, double shy) { transform.shear(shx, shy); } /** * @see Graphics2D#transform(AffineTransform) */ public void transform(AffineTransform tx) { transform.concatenate(tx); this.stroke = transformStroke(originalStroke); } private Stroke transformStroke(Stroke stroke) { if (!(stroke instanceof BasicStroke)) return stroke; BasicStroke st = (BasicStroke)stroke; float scale = (float)Math.sqrt(Math.abs(transform.getDeterminant())); float dash[] = st.getDashArray(); if (dash != null) { for (int k = 0; k < dash.length; ++k) dash[k] *= scale; } return new BasicStroke(st.getLineWidth() * scale, st.getEndCap(), st.getLineJoin(), st.getMiterLimit(), dash, st.getDashPhase() * scale); } /** * @see Graphics2D#translate(double, double) */ public void translate(double tx, double ty) { transform.translate(tx, ty); trax = (float) tx; tray = (float) ty; } /** * @see Graphics#translate(int, int) */ public void translate(int x, int y) { translate((double)x, (double)y); } /** * Converts the Java space coordinates into pdf text space. * @param x coordinate * @param y coordinate * @param tx coordinate * @param ty coordinate * @return String containing the coordinates in PDF text space */ private String twh(float x,float y,float tx,float ty) { float nx=x, ny=y; float ntx=tx, nty=ty; int mh = (int) page.getPageFormat().getHeight(); int sx=1,sy=1; // switch(mediaRot) // { // case PageFormat.PORTRAIT: // Portrait //nx = x; ny = mh - y; nty = mh - ty; // break; // // case PageFormat.LANDSCAPE: // // Landscape // //nx = y; // //ny = x; // //ntx = ty; // //nty = tx; // //sy=-1; // nx = x; // ny = -y; // ntx = tx; // nty = -ty; // //sy=-1; // break; // // case 180: // // Inverse Portrait // // to be completed // nx = mw - x; // //ny = y; // break; // // case PageFormat.REVERSE_LANDSCAPE: // // Seascape // // to be completed // nx = mw - y; // ny = mh - x; // break; // } nx = sx*(nx-ntx); ny = sy*(ny-nty); return ""+df.format(nx)+" "+df.format(ny)+" "; } /** * Converts the Java space coordinates into pdf text space. * @param x coordinate * @param y coordinate * @return String containing the coordinates in PDF text space */ private String txy(float x,float y) { // float nx=x, ny=y; // int mh = (int) page.getPageFormat().getHeight(); Point2D ptSrc = new Point2D.Float(x, y); Point2D ptDst = new Point2D.Float(); transform.transform(ptSrc, ptDst); // // handle any translations // x+=trax; // y+=tray; // // nx = x; // ny = mh - y; // // System.out.println("\ntxy(" + ptSrc.getX() + ", " + ptSrc.getY() + ")"); // System.out.println("Old [" + nx + "," + ny + "]"); // System.out.println("Trn [" + ptDst.getX() + ", " + ptDst.getY() + "]"); // // return ""+df.format(nx)+" "+df.format(ny)+" "; return ""+df.format(ptDst.getX())+" "+df.format(ptDst.getY())+" "; } } // end class PDFGraphics \ No newline at end of file