KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > pdf > PdfGraphics2D


1 /*
2  * $Id: PdfGraphics2D.java 2780 2007-05-24 09:19:25Z blowagie $
3  *
4  * Copyright 2002 by Jim Moore <jim@scolamoore.com>.
5  *
6  * The contents of this file are subject to the Mozilla Public License Version 1.1
7  * (the "License"); you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the License.
13  *
14  * The Original Code is 'iText, a free JAVA-PDF library'.
15  *
16  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
17  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
18  * All Rights Reserved.
19  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
20  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
21  *
22  * Contributor(s): all the names of the contributors are added in the source code
23  * where applicable.
24  *
25  * Alternatively, the contents of this file may be used under the terms of the
26  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
27  * provisions of LGPL are applicable instead of those above. If you wish to
28  * allow use of your version of this file only under the terms of the LGPL
29  * License and not to allow others to use your version of this file under
30  * the MPL, indicate your decision by deleting the provisions above and
31  * replace them with the notice and other provisions required by the LGPL.
32  * If you do not delete the provisions above, a recipient may use your version
33  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
34  *
35  * This library is free software; you can redistribute it and/or modify it
36  * under the terms of the MPL as stated above or under the terms of the GNU
37  * Library General Public License as published by the Free Software Foundation;
38  * either version 2 of the License, or any later version.
39  *
40  * This library is distributed in the hope that it will be useful, but WITHOUT
41  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
42  * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
43  * details.
44  *
45  * If you didn't download this code from the following link, you should check if
46  * you aren't using an obsolete version:
47  * http://www.lowagie.com/iText/
48  */

49
50 package com.lowagie.text.pdf;
51
52 import java.awt.AlphaComposite JavaDoc;
53 import java.awt.BasicStroke JavaDoc;
54 import java.awt.Color JavaDoc;
55 import java.awt.Component JavaDoc;
56 import java.awt.Composite JavaDoc;
57 import java.awt.Font JavaDoc;
58 import java.awt.FontMetrics JavaDoc;
59 import java.awt.GradientPaint JavaDoc;
60 import java.awt.Graphics JavaDoc;
61 import java.awt.Graphics2D JavaDoc;
62 import java.awt.GraphicsConfiguration JavaDoc;
63 import java.awt.Image JavaDoc;
64 import java.awt.MediaTracker JavaDoc;
65 import java.awt.Paint JavaDoc;
66 import java.awt.Polygon JavaDoc;
67 import java.awt.Rectangle JavaDoc;
68 import java.awt.RenderingHints JavaDoc;
69 import java.awt.Shape JavaDoc;
70 import java.awt.Stroke JavaDoc;
71 import java.awt.TexturePaint JavaDoc;
72 import java.awt.Transparency JavaDoc;
73 import java.awt.RenderingHints.Key;
74 import java.awt.font.FontRenderContext JavaDoc;
75 import java.awt.font.GlyphVector JavaDoc;
76 import java.awt.font.TextAttribute JavaDoc;
77 import java.awt.geom.AffineTransform JavaDoc;
78 import java.awt.geom.Arc2D JavaDoc;
79 import java.awt.geom.Area JavaDoc;
80 import java.awt.geom.Ellipse2D JavaDoc;
81 import java.awt.geom.Line2D JavaDoc;
82 import java.awt.geom.NoninvertibleTransformException JavaDoc;
83 import java.awt.geom.PathIterator JavaDoc;
84 import java.awt.geom.Point2D JavaDoc;
85 import java.awt.geom.Rectangle2D JavaDoc;
86 import java.awt.geom.RoundRectangle2D JavaDoc;
87 import java.awt.image.BufferedImage JavaDoc;
88 import java.awt.image.BufferedImageOp JavaDoc;
89 import java.awt.image.ColorModel JavaDoc;
90 import java.awt.image.ImageObserver JavaDoc;
91 import java.awt.image.RenderedImage JavaDoc;
92 import java.awt.image.WritableRaster JavaDoc;
93 import java.awt.image.renderable.RenderableImage JavaDoc;
94 import java.io.ByteArrayOutputStream JavaDoc;
95 import java.text.AttributedCharacterIterator JavaDoc;
96 import java.util.ArrayList JavaDoc;
97 import java.util.HashMap JavaDoc;
98 import java.util.Hashtable JavaDoc;
99 import java.util.Iterator JavaDoc;
100 import java.util.Map JavaDoc;
101 import java.util.Set JavaDoc;
102
103 import com.lowagie.text.pdf.internal.PolylineShape;
104
105 public class PdfGraphics2D extends Graphics2D JavaDoc {
106     
107     private static final int FILL = 1;
108     private static final int STROKE = 2;
109     private static final int CLIP = 3;
110     private BasicStroke JavaDoc strokeOne = new BasicStroke JavaDoc(1);
111     
112     private static final AffineTransform JavaDoc IDENTITY = new AffineTransform JavaDoc();
113     
114     private Font JavaDoc font;
115     private BaseFont baseFont;
116     private float fontSize;
117     private AffineTransform JavaDoc transform;
118     private Paint JavaDoc paint;
119     private Color JavaDoc background;
120     private float width;
121     private float height;
122     
123     private Area JavaDoc clip;
124     
125     private RenderingHints JavaDoc rhints = new RenderingHints JavaDoc(null);
126     
127     private Stroke JavaDoc stroke;
128     private Stroke JavaDoc originalStroke;
129     
130     private PdfContentByte cb;
131     
132     /** Storage for BaseFont objects created. */
133     private HashMap JavaDoc baseFonts;
134     
135     private boolean disposeCalled = false;
136     
137     private FontMapper fontMapper;
138     
139     private ArrayList JavaDoc kids;
140     
141     private boolean kid = false;
142     
143     private Graphics2D JavaDoc dg2 = new BufferedImage JavaDoc(2, 2, BufferedImage.TYPE_INT_RGB).createGraphics();
144     
145     private boolean onlyShapes = false;
146     
147     private Stroke JavaDoc oldStroke;
148     private Paint JavaDoc paintFill;
149     private Paint JavaDoc paintStroke;
150     
151     private MediaTracker JavaDoc mediaTracker;
152
153     // Added by Jurij Bilas
154
protected boolean underline; // indicates if the font style is underlined
155

156     protected PdfGState fillGState[] = new PdfGState[256];
157     protected PdfGState strokeGState[] = new PdfGState[256];
158     protected int currentFillGState = 255;
159     protected int currentStrokeGState = 255;
160     
161     public static final int AFM_DIVISOR = 1000; // used to calculate coordinates
162

163     private boolean convertImagesToJPEG = false;
164     private float jpegQuality = .95f;
165
166     // Added by Alexej Suchov
167
private float alpha;
168
169     // Added by Alexej Suchov
170
private Composite JavaDoc composite;
171
172     // Added by Alexej Suchov
173
private Paint JavaDoc realPaint;
174
175     private PdfGraphics2D() {
176         dg2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
177         setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
178     }
179     
180     /**
181      * Constructor for PDFGraphics2D.
182      *
183      */

184     PdfGraphics2D(PdfContentByte cb, float width, float height, FontMapper fontMapper, boolean onlyShapes, boolean convertImagesToJPEG, float quality) {
185         super();
186         dg2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
187         setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
188         try {
189             Class.forName("com.sun.image.codec.jpeg.JPEGCodec");
190         }
191         catch (Throwable JavaDoc t) {
192             convertImagesToJPEG = false;
193         }
194         this.convertImagesToJPEG = convertImagesToJPEG;
195         this.jpegQuality = quality;
196         this.onlyShapes = onlyShapes;
197         this.transform = new AffineTransform JavaDoc();
198         this.baseFonts = new HashMap JavaDoc();
199         if (!onlyShapes) {
200             this.fontMapper = fontMapper;
201             if (this.fontMapper == null)
202                 this.fontMapper = new DefaultFontMapper();
203         }
204         paint = Color.black;
205         background = Color.white;
206         setFont(new Font JavaDoc("sanserif", Font.PLAIN, 12));
207         this.cb = cb;
208         cb.saveState();
209         this.width = width;
210         this.height = height;
211         clip = new Area JavaDoc(new Rectangle2D.Float JavaDoc(0, 0, width, height));
212         clip(clip);
213         originalStroke = stroke = oldStroke = strokeOne;
214         setStrokeDiff(stroke, null);
215         cb.saveState();
216     }
217     
218     /**
219      * @see Graphics2D#draw(Shape)
220      */

221     public void draw(Shape JavaDoc s) {
222         followPath(s, STROKE);
223     }
224     
225     /**
226      * @see Graphics2D#drawImage(Image, AffineTransform, ImageObserver)
227      */

228     public boolean drawImage(Image JavaDoc img, AffineTransform JavaDoc xform, ImageObserver JavaDoc obs) {
229         return drawImage(img, null, xform, null, obs);
230     }
231     
232     /**
233      * @see Graphics2D#drawImage(BufferedImage, BufferedImageOp, int, int)
234      */

235     public void drawImage(BufferedImage JavaDoc img, BufferedImageOp JavaDoc op, int x, int y) {
236         BufferedImage JavaDoc result = img;
237         if (op != null) {
238             result = op.createCompatibleDestImage(img, img.getColorModel());
239             result = op.filter(img, result);
240         }
241         drawImage(result, x, y, null);
242     }
243     
244     /**
245      * @see Graphics2D#drawRenderedImage(RenderedImage, AffineTransform)
246      */

247     public void drawRenderedImage(RenderedImage JavaDoc img, AffineTransform JavaDoc xform) {
248         BufferedImage JavaDoc image = null;
249         if (img instanceof BufferedImage JavaDoc) {
250             image = (BufferedImage JavaDoc)img;
251         } else {
252             ColorModel JavaDoc cm = img.getColorModel();
253             int width = img.getWidth();
254             int height = img.getHeight();
255             WritableRaster JavaDoc raster = cm.createCompatibleWritableRaster(width, height);
256             boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
257             Hashtable JavaDoc properties = new Hashtable JavaDoc();
258             String JavaDoc[] keys = img.getPropertyNames();
259             if (keys!=null) {
260                 for (int i = 0; i < keys.length; i++) {
261                     properties.put(keys[i], img.getProperty(keys[i]));
262                 }
263             }
264             BufferedImage JavaDoc result = new BufferedImage JavaDoc(cm, raster, isAlphaPremultiplied, properties);
265             img.copyData(raster);
266             image=result;
267         }
268         drawImage(image, xform, null);
269     }
270     
271     /**
272      * @see Graphics2D#drawRenderableImage(RenderableImage, AffineTransform)
273      */

274     public void drawRenderableImage(RenderableImage JavaDoc img, AffineTransform JavaDoc xform) {
275         drawRenderedImage(img.createDefaultRendering(), xform);
276     }
277     
278     /**
279      * @see Graphics#drawString(String, int, int)
280      */

281     public void drawString(String JavaDoc s, int x, int y) {
282         drawString(s, (float)x, (float)y);
283     }
284     
285     /**
286      * Calculates position and/or stroke thickness depending on the font size
287      * @param d value to be converted
288      * @param i font size
289      * @return position and/or stroke thickness depending on the font size
290      */

291     public static double asPoints(double d, int i) {
292         return (d * (double)i) / (double)AFM_DIVISOR;
293     }
294     /**
295      * This routine goes through the attributes and sets the font
296      * before calling the actual string drawing routine
297      * @param iter
298      */

299     protected void doAttributes(AttributedCharacterIterator JavaDoc iter) {
300         underline = false;
301         Set JavaDoc set = iter.getAttributes().keySet();
302         for(Iterator JavaDoc iterator = set.iterator(); iterator.hasNext();) {
303             AttributedCharacterIterator.Attribute JavaDoc attribute = (AttributedCharacterIterator.Attribute JavaDoc)iterator.next();
304             if (!(attribute instanceof TextAttribute JavaDoc))
305                 continue;
306             TextAttribute JavaDoc textattribute = (TextAttribute JavaDoc)attribute;
307             if(textattribute.equals(TextAttribute.FONT)) {
308                 Font JavaDoc font = (Font JavaDoc)iter.getAttributes().get(textattribute);
309                 setFont(font);
310             }
311             else if(textattribute.equals(TextAttribute.UNDERLINE)) {
312                 if(iter.getAttributes().get(textattribute) == TextAttribute.UNDERLINE_ON)
313                     underline = true;
314             }
315             else if(textattribute.equals(TextAttribute.SIZE)) {
316                 Object JavaDoc obj = iter.getAttributes().get(textattribute);
317                 if(obj instanceof Integer JavaDoc) {
318                     int i = ((Integer JavaDoc)obj).intValue();
319                     setFont(getFont().deriveFont(getFont().getStyle(), i));
320                 }
321                 else if(obj instanceof Float JavaDoc) {
322                     float f = ((Float JavaDoc)obj).floatValue();
323                     setFont(getFont().deriveFont(getFont().getStyle(), f));
324                 }
325             }
326             else if(textattribute.equals(TextAttribute.FOREGROUND)) {
327                 setColor((Color JavaDoc) iter.getAttributes().get(textattribute));
328             }
329             else if(textattribute.equals(TextAttribute.FAMILY)) {
330               Font JavaDoc font = getFont();
331               Map JavaDoc fontAttributes = font.getAttributes();
332               fontAttributes.put(TextAttribute.FAMILY, iter.getAttributes().get(textattribute));
333               setFont(font.deriveFont(fontAttributes));
334             }
335             else if(textattribute.equals(TextAttribute.POSTURE)) {
336               Font JavaDoc font = getFont();
337               Map JavaDoc fontAttributes = font.getAttributes();
338               fontAttributes.put(TextAttribute.POSTURE, iter.getAttributes().get(textattribute));
339               setFont(font.deriveFont(fontAttributes));
340             }
341             else if(textattribute.equals(TextAttribute.WEIGHT)) {
342               Font JavaDoc font = getFont();
343               Map JavaDoc fontAttributes = font.getAttributes();
344               fontAttributes.put(TextAttribute.WEIGHT, iter.getAttributes().get(textattribute));
345               setFont(font.deriveFont(fontAttributes));
346             }
347         }
348     }
349
350     /**
351      * @see Graphics2D#drawString(String, float, float)
352      */

353     public void drawString(String JavaDoc s, float x, float y) {
354         if (s.length() == 0)
355             return;
356         setFillPaint();
357         if (onlyShapes) {
358             drawGlyphVector(this.font.layoutGlyphVector(getFontRenderContext(), s.toCharArray(), 0, s.length(), java.awt.Font.LAYOUT_LEFT_TO_RIGHT), x, y);
359 // Use the following line to compile in JDK 1.3
360
// drawGlyphVector(this.font.createGlyphVector(getFontRenderContext(), s), x, y);
361
}
362         else {
363             AffineTransform JavaDoc at = getTransform();
364             AffineTransform JavaDoc at2 = getTransform();
365             at2.translate(x, y);
366             at2.concatenate(font.getTransform());
367             setTransform(at2);
368             AffineTransform JavaDoc inverse = this.normalizeMatrix();
369             AffineTransform JavaDoc flipper = AffineTransform.getScaleInstance(1,-1);
370             inverse.concatenate(flipper);
371             double[] mx = new double[6];
372             inverse.getMatrix(mx);
373             cb.beginText();
374             cb.setFontAndSize(baseFont, fontSize);
375             cb.setTextMatrix((float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]);
376             Float JavaDoc fontTextAttributeWidth = (Float JavaDoc)font.getAttributes().get(TextAttribute.WIDTH);
377             fontTextAttributeWidth = (fontTextAttributeWidth == null)
378                                      ? TextAttribute.WIDTH_REGULAR
379                                      : fontTextAttributeWidth;
380             if (!TextAttribute.WIDTH_REGULAR.equals(fontTextAttributeWidth))
381                 cb.setHorizontalScaling(100.0f / fontTextAttributeWidth.floatValue());
382             double width = 0;
383             if (font.getSize2D() > 0) {
384                 float scale = 1000 / font.getSize2D();
385                 width = font.deriveFont(AffineTransform.getScaleInstance(scale, scale)).getStringBounds(s, getFontRenderContext()).getWidth() / scale;
386             }
387             if (s.length() > 1) {
388                 float adv = ((float)width - baseFont.getWidthPoint(s, fontSize)) / (s.length() - 1);
389                 cb.setCharacterSpacing(adv);
390             }
391             cb.showText(s);
392             if (s.length() > 1) {
393                 cb.setCharacterSpacing(0);
394             }
395             if (!TextAttribute.WIDTH_REGULAR.equals(fontTextAttributeWidth))
396                 cb.setHorizontalScaling(100);
397             cb.endText();
398             setTransform(at);
399             if(underline)
400             {
401                 // These two are supposed to be taken from the .AFM file
402
//int UnderlinePosition = -100;
403
int UnderlineThickness = 50;
404                 //
405
double d = asPoints((double)UnderlineThickness, (int)fontSize);
406                 setStroke(new BasicStroke JavaDoc((float)d));
407                 y = (float)((double)(y) + asPoints((double)(UnderlineThickness), (int)fontSize));
408                 Line2D JavaDoc line = new Line2D.Double JavaDoc((double)x, (double)y, (double)(width+x), (double)y);
409                 draw(line);
410             }
411         }
412     }
413
414     /**
415      * @see Graphics#drawString(AttributedCharacterIterator, int, int)
416      */

417     public void drawString(AttributedCharacterIterator JavaDoc iterator, int x, int y) {
418         drawString(iterator, (float)x, (float)y);
419     }
420     
421     /**
422      * @see Graphics2D#drawString(AttributedCharacterIterator, float, float)
423      */

424     public void drawString(AttributedCharacterIterator JavaDoc iter, float x, float y) {
425 /*
426         StringBuffer sb = new StringBuffer();
427         for(char c = iter.first(); c != AttributedCharacterIterator.DONE; c = iter.next()) {
428             sb.append(c);
429         }
430         drawString(sb.toString(),x,y);
431 */

432         StringBuffer JavaDoc stringbuffer = new StringBuffer JavaDoc(iter.getEndIndex());
433         for(char c = iter.first(); c != '\uFFFF'; c = iter.next())
434         {
435             if(iter.getIndex() == iter.getRunStart())
436             {
437                 if(stringbuffer.length() > 0)
438                 {
439                     drawString(stringbuffer.toString(), x, y);
440                     FontMetrics JavaDoc fontmetrics = getFontMetrics();
441                     x = (float)((double)x + fontmetrics.getStringBounds(stringbuffer.toString(), this).getWidth());
442                     stringbuffer.delete(0, stringbuffer.length());
443                 }
444                 doAttributes(iter);
445             }
446             stringbuffer.append(c);
447         }
448         
449         drawString(stringbuffer.toString(), x, y);
450         underline = false;
451     }
452     
453     /**
454      * @see Graphics2D#drawGlyphVector(GlyphVector, float, float)
455      */

456     public void drawGlyphVector(GlyphVector JavaDoc g, float x, float y) {
457         Shape JavaDoc s = g.getOutline(x, y);
458         fill(s);
459     }
460     
461     /**
462      * @see Graphics2D#fill(Shape)
463      */

464     public void fill(Shape JavaDoc s) {
465         followPath(s, FILL);
466     }
467     
468     /**
469      * @see Graphics2D#hit(Rectangle, Shape, boolean)
470      */

471     public boolean hit(Rectangle JavaDoc rect, Shape JavaDoc s, boolean onStroke) {
472         if (onStroke) {
473             s = stroke.createStrokedShape(s);
474         }
475         s = transform.createTransformedShape(s);
476         Area JavaDoc area = new Area JavaDoc(s);
477         if (clip != null)
478             area.intersect(clip);
479         return area.intersects(rect.x, rect.y, rect.width, rect.height);
480     }
481     
482     /**
483      * @see Graphics2D#getDeviceConfiguration()
484      */

485     public GraphicsConfiguration JavaDoc getDeviceConfiguration() {
486         return dg2.getDeviceConfiguration();
487     }
488     
489     /**
490      * Method contributed by Alexej Suchov
491      * @see Graphics2D#setComposite(Composite)
492      */

493     public void setComposite(Composite JavaDoc comp) {
494         
495         if (comp instanceof AlphaComposite JavaDoc) {
496
497             AlphaComposite JavaDoc composite = (AlphaComposite JavaDoc) comp;
498
499             if (composite.getRule() == 3) {
500
501                 alpha = composite.getAlpha();
502                 this.composite = composite;
503
504                 if (realPaint != null && (realPaint instanceof Color JavaDoc)) {
505
506                     Color JavaDoc c = (Color JavaDoc) realPaint;
507                     paint = new Color JavaDoc(c.getRed(), c.getGreen(), c.getBlue(),
508                             (int) ((float) c.getAlpha() * alpha));
509                 }
510                 return;
511             }
512         }
513
514         this.composite = comp;
515         alpha = 1.0F;
516
517     }
518     
519     /**
520      * Method contributed by Alexej Suchov
521      * @see Graphics2D#setPaint(Paint)
522      */

523     public void setPaint(Paint JavaDoc paint) {
524         if (paint == null)
525             return;
526         this.paint = paint;
527         realPaint = paint;
528
529         if ((composite instanceof AlphaComposite JavaDoc) && (paint instanceof Color JavaDoc)) {
530             
531             AlphaComposite JavaDoc co = (AlphaComposite JavaDoc) composite;
532             
533             if (co.getRule() == 3) {
534                 Color JavaDoc c = (Color JavaDoc) paint;
535                 this.paint = new Color JavaDoc(c.getRed(), c.getGreen(), c.getBlue(), (int) ((float) c.getAlpha() * alpha));
536                 realPaint = paint;
537             }
538         }
539
540     }
541
542     private Stroke JavaDoc transformStroke(Stroke JavaDoc stroke) {
543         if (!(stroke instanceof BasicStroke JavaDoc))
544             return stroke;
545         BasicStroke JavaDoc st = (BasicStroke JavaDoc)stroke;
546         float scale = (float)Math.sqrt(Math.abs(transform.getDeterminant()));
547         float dash[] = st.getDashArray();
548         if (dash != null) {
549             for (int k = 0; k < dash.length; ++k)
550                 dash[k] *= scale;
551         }
552         return new BasicStroke JavaDoc(st.getLineWidth() * scale, st.getEndCap(), st.getLineJoin(), st.getMiterLimit(), dash, st.getDashPhase() * scale);
553     }
554     
555     private void setStrokeDiff(Stroke JavaDoc newStroke, Stroke JavaDoc oldStroke) {
556         if (newStroke == oldStroke)
557             return;
558         if (!(newStroke instanceof BasicStroke JavaDoc))
559             return;
560         BasicStroke JavaDoc nStroke = (BasicStroke JavaDoc)newStroke;
561         boolean oldOk = (oldStroke instanceof BasicStroke JavaDoc);
562         BasicStroke JavaDoc oStroke = null;
563         if (oldOk)
564             oStroke = (BasicStroke JavaDoc)oldStroke;
565         if (!oldOk || nStroke.getLineWidth() != oStroke.getLineWidth())
566             cb.setLineWidth(nStroke.getLineWidth());
567         if (!oldOk || nStroke.getEndCap() != oStroke.getEndCap()) {
568             switch (nStroke.getEndCap()) {
569             case BasicStroke.CAP_BUTT:
570                 cb.setLineCap(0);
571                 break;
572             case BasicStroke.CAP_SQUARE:
573                 cb.setLineCap(2);
574                 break;
575             default:
576                 cb.setLineCap(1);
577             }
578         }
579         if (!oldOk || nStroke.getLineJoin() != oStroke.getLineJoin()) {
580             switch (nStroke.getLineJoin()) {
581             case BasicStroke.JOIN_MITER:
582                 cb.setLineJoin(0);
583                 break;
584             case BasicStroke.JOIN_BEVEL:
585                 cb.setLineJoin(2);
586                 break;
587             default:
588                 cb.setLineJoin(1);
589             }
590         }
591         if (!oldOk || nStroke.getMiterLimit() != oStroke.getMiterLimit())
592             cb.setMiterLimit(nStroke.getMiterLimit());
593         boolean makeDash;
594         if (oldOk) {
595             if (nStroke.getDashArray() != null) {
596                 if (nStroke.getDashPhase() != oStroke.getDashPhase()) {
597                     makeDash = true;
598                 }
599                 else if (!java.util.Arrays.equals(nStroke.getDashArray(), oStroke.getDashArray())) {
600                     makeDash = true;
601                 }
602                 else
603                     makeDash = false;
604             }
605             else if (oStroke.getDashArray() != null) {
606                 makeDash = true;
607             }
608             else
609                 makeDash = false;
610         }
611         else {
612             makeDash = true;
613         }
614         if (makeDash) {
615             float dash[] = nStroke.getDashArray();
616             if (dash == null)
617                 cb.setLiteral("[]0 d\n");
618             else {
619                 cb.setLiteral('[');
620                 int lim = dash.length;
621                 for (int k = 0; k < lim; ++k) {
622                     cb.setLiteral(dash[k]);
623                     cb.setLiteral(' ');
624                 }
625                 cb.setLiteral(']');
626                 cb.setLiteral(nStroke.getDashPhase());
627                 cb.setLiteral(" d\n");
628             }
629         }
630     }
631     
632     /**
633      * @see Graphics2D#setStroke(Stroke)
634      */

635     public void setStroke(Stroke JavaDoc s) {
636         originalStroke = s;
637         this.stroke = transformStroke(s);
638     }
639     
640     
641     /**
642      * Sets a rendering hint
643      * @param arg0
644      * @param arg1
645      */

646     public void setRenderingHint(Key arg0, Object JavaDoc arg1) {
647         if (arg1 != null) {
648             rhints.put(arg0, arg1);
649         } else {
650             rhints.remove(arg0);
651         }
652     }
653     
654     /**
655      * @param arg0 a key
656      * @return the rendering hint
657      */

658     public Object JavaDoc getRenderingHint(Key arg0) {
659         return rhints.get(arg0);
660     }
661     
662     /**
663      * @see Graphics2D#setRenderingHints(Map)
664      */

665     public void setRenderingHints(Map JavaDoc hints) {
666         rhints.clear();
667         rhints.putAll(hints);
668     }
669     
670     /**
671      * @see Graphics2D#addRenderingHints(Map)
672      */

673     public void addRenderingHints(Map JavaDoc hints) {
674         rhints.putAll(hints);
675     }
676     
677     /**
678      * @see Graphics2D#getRenderingHints()
679      */

680     public RenderingHints JavaDoc getRenderingHints() {
681         return rhints;
682     }
683     
684     /**
685      * @see Graphics#translate(int, int)
686      */

687     public void translate(int x, int y) {
688         translate((double)x, (double)y);
689     }
690     
691     /**
692      * @see Graphics2D#translate(double, double)
693      */

694     public void translate(double tx, double ty) {
695         transform.translate(tx,ty);
696     }
697     
698     /**
699      * @see Graphics2D#rotate(double)
700      */

701     public void rotate(double theta) {
702         transform.rotate(theta);
703     }
704     
705     /**
706      * @see Graphics2D#rotate(double, double, double)
707      */

708     public void rotate(double theta, double x, double y) {
709         transform.rotate(theta, x, y);
710     }
711     
712     /**
713      * @see Graphics2D#scale(double, double)
714      */

715     public void scale(double sx, double sy) {
716         transform.scale(sx, sy);
717         this.stroke = transformStroke(originalStroke);
718     }
719     
720     /**
721      * @see Graphics2D#shear(double, double)
722      */

723     public void shear(double shx, double shy) {
724         transform.shear(shx, shy);
725     }
726     
727     /**
728      * @see Graphics2D#transform(AffineTransform)
729      */

730     public void transform(AffineTransform JavaDoc tx) {
731         transform.concatenate(tx);
732         this.stroke = transformStroke(originalStroke);
733     }
734     
735     /**
736      * @see Graphics2D#setTransform(AffineTransform)
737      */

738     public void setTransform(AffineTransform JavaDoc t) {
739         transform = new AffineTransform JavaDoc(t);
740         this.stroke = transformStroke(originalStroke);
741     }
742     
743     /**
744      * @see Graphics2D#getTransform()
745      */

746     public AffineTransform JavaDoc getTransform() {
747         return new AffineTransform JavaDoc(transform);
748     }
749     
750     /**
751      * Method contributed by Alexej Suchov
752      * @see Graphics2D#getPaint()
753      */

754     public Paint JavaDoc getPaint() {
755         if (realPaint != null) {
756             return realPaint;
757         } else {
758             return paint;
759         }
760     }
761     
762     /**
763      * @see Graphics2D#getComposite()
764      */

765     public Composite JavaDoc getComposite() {
766         return composite;
767     }
768     
769     /**
770      * @see Graphics2D#setBackground(Color)
771      */

772     public void setBackground(Color JavaDoc color) {
773         background = color;
774     }
775     
776     /**
777      * @see Graphics2D#getBackground()
778      */

779     public Color JavaDoc getBackground() {
780         return background;
781     }
782     
783     /**
784      * @see Graphics2D#getStroke()
785      */

786     public Stroke JavaDoc getStroke() {
787         return originalStroke;
788     }
789     
790     
791     /**
792      * @see Graphics2D#getFontRenderContext()
793      */

794     public FontRenderContext JavaDoc getFontRenderContext() {
795         boolean antialias = RenderingHints.VALUE_TEXT_ANTIALIAS_ON.equals(getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING));
796         boolean fractions = RenderingHints.VALUE_FRACTIONALMETRICS_ON.equals(getRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS));
797         return new FontRenderContext JavaDoc(new AffineTransform JavaDoc(), antialias, fractions);
798     }
799     
800     /**
801      * @see Graphics#create()
802      */

803     public Graphics JavaDoc create() {
804         PdfGraphics2D g2 = new PdfGraphics2D();
805         g2.onlyShapes = this.onlyShapes;
806         g2.transform = new AffineTransform JavaDoc(this.transform);
807         g2.baseFonts = this.baseFonts;
808         g2.fontMapper = this.fontMapper;
809         g2.paint = this.paint;
810         g2.fillGState = this.fillGState;
811         g2.strokeGState = this.strokeGState;
812         g2.background = this.background;
813         g2.mediaTracker = this.mediaTracker;
814         g2.convertImagesToJPEG = this.convertImagesToJPEG;
815         g2.jpegQuality = this.jpegQuality;
816         g2.setFont(this.font);
817         g2.cb = this.cb.getDuplicate();
818         g2.cb.saveState();
819         g2.width = this.width;
820         g2.height = this.height;
821         g2.followPath(new Area JavaDoc(new Rectangle2D.Float JavaDoc(0, 0, width, height)), CLIP);
822         if (this.clip != null)
823             g2.clip = new Area JavaDoc(this.clip);
824         g2.composite = composite;
825         g2.stroke = stroke;
826         g2.originalStroke = originalStroke;
827         g2.strokeOne = (BasicStroke JavaDoc)g2.transformStroke(g2.strokeOne);
828         g2.oldStroke = g2.strokeOne;
829         g2.setStrokeDiff(g2.oldStroke, null);
830         g2.cb.saveState();
831         if (g2.clip != null)
832             g2.followPath(g2.clip, CLIP);
833         g2.kid = true;
834         if (this.kids == null)
835             this.kids = new ArrayList JavaDoc();
836         this.kids.add(new Integer JavaDoc(cb.getInternalBuffer().size()));
837         this.kids.add(g2);
838         return g2;
839     }
840     
841     public PdfContentByte getContent() {
842         return this.cb;
843     }
844     /**
845      * @see Graphics#getColor()
846      */

847     public Color JavaDoc getColor() {
848         if (paint instanceof Color JavaDoc) {
849             return (Color JavaDoc)paint;
850         } else {
851             return Color.black;
852         }
853     }
854     
855     /**
856      * @see Graphics#setColor(Color)
857      */

858     public void setColor(Color JavaDoc color) {
859         setPaint(color);
860     }
861     
862     /**
863      * @see Graphics#setPaintMode()
864      */

865     public void setPaintMode() {}
866     
867     /**
868      * @see Graphics#setXORMode(Color)
869      */

870     public void setXORMode(Color JavaDoc c1) {
871         
872     }
873     
874     /**
875      * @see Graphics#getFont()
876      */

877     public Font JavaDoc getFont() {
878         return font;
879     }
880     
881     /**
882      * @see Graphics#setFont(Font)
883      */

884     /**
885      * Sets the current font.
886      */

887     public void setFont(Font JavaDoc f) {
888         if (f == null)
889             return;
890         if (onlyShapes) {
891             font = f;
892             return;
893         }
894         if (f == font)
895             return;
896         font = f;
897         fontSize = f.getSize2D();
898         baseFont = getCachedBaseFont(f);
899     }
900     
901     private BaseFont getCachedBaseFont(Font JavaDoc f) {
902         synchronized (baseFonts) {
903             BaseFont bf = (BaseFont)baseFonts.get(f.getFontName());
904             if (bf == null) {
905                 bf = fontMapper.awtToPdf(f);
906                 baseFonts.put(f.getFontName(), bf);
907             }
908             return bf;
909         }
910     }
911     
912     /**
913      * @see Graphics#getFontMetrics(Font)
914      */

915     public FontMetrics JavaDoc getFontMetrics(Font JavaDoc f) {
916         return dg2.getFontMetrics(f);
917     }
918     
919     /**
920      * @see Graphics#getClipBounds()
921      */

922     public Rectangle JavaDoc getClipBounds() {
923         if (clip == null)
924             return null;
925         return getClip().getBounds();
926     }
927     
928     /**
929      * @see Graphics#clipRect(int, int, int, int)
930      */

931     public void clipRect(int x, int y, int width, int height) {
932         Rectangle2D JavaDoc rect = new Rectangle2D.Double JavaDoc(x,y,width,height);
933         clip(rect);
934     }
935     
936     /**
937      * @see Graphics#setClip(int, int, int, int)
938      */

939     public void setClip(int x, int y, int width, int height) {
940         Rectangle2D JavaDoc rect = new Rectangle2D.Double JavaDoc(x,y,width,height);
941         setClip(rect);
942     }
943     
944     /**
945      * @see Graphics2D#clip(Shape)
946      */

947     public void clip(Shape JavaDoc s) {
948         if (s == null) {
949             setClip(null);
950             return;
951         }
952         s = transform.createTransformedShape(s);
953         if (clip == null)
954             clip = new Area JavaDoc(s);
955         else
956             clip.intersect(new Area JavaDoc(s));
957         followPath(s, CLIP);
958     }
959     
960     /**
961      * @see Graphics#getClip()
962      */

963     public Shape JavaDoc getClip() {
964         try {
965             return transform.createInverse().createTransformedShape(clip);
966         }
967         catch (NoninvertibleTransformException JavaDoc e) {
968             return null;
969         }
970     }
971     
972     /**
973      * @see Graphics#setClip(Shape)
974      */

975     public void setClip(Shape JavaDoc s) {
976         cb.restoreState();
977         cb.saveState();
978         if (s != null)
979             s = transform.createTransformedShape(s);
980         if (s == null) {
981             clip = null;
982         }
983         else {
984             clip = new Area JavaDoc(s);
985             followPath(s, CLIP);
986         }
987         paintFill = paintStroke = null;
988         currentFillGState = currentStrokeGState = 255;
989         oldStroke = strokeOne;
990     }
991     
992     /**
993      * @see Graphics#copyArea(int, int, int, int, int, int)
994      */

995     public void copyArea(int x, int y, int width, int height, int dx, int dy) {
996         
997     }
998     
999     /**
1000     * @see Graphics#drawLine(int, int, int, int)
1001     */

1002    public void drawLine(int x1, int y1, int x2, int y2) {
1003        Line2D JavaDoc line = new Line2D.Double JavaDoc((double)x1, (double)y1, (double)x2, (double)y2);
1004        draw(line);
1005    }
1006    
1007    /**
1008     * @see Graphics#fillRect(int, int, int, int)
1009     */

1010    public void drawRect(int x, int y, int width, int height) {
1011        draw(new Rectangle JavaDoc(x, y, width, height));
1012    }
1013    
1014    /**
1015     * @see Graphics#fillRect(int, int, int, int)
1016     */

1017    public void fillRect(int x, int y, int width, int height) {
1018        fill(new Rectangle JavaDoc(x,y,width,height));
1019    }
1020    
1021    /**
1022     * @see Graphics#clearRect(int, int, int, int)
1023     */

1024    public void clearRect(int x, int y, int width, int height) {
1025        Paint JavaDoc temp = paint;
1026        setPaint(background);
1027        fillRect(x,y,width,height);
1028        setPaint(temp);
1029    }
1030    
1031    /**
1032     * @see Graphics#drawRoundRect(int, int, int, int, int, int)
1033     */

1034    public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
1035        RoundRectangle2D JavaDoc rect = new RoundRectangle2D.Double JavaDoc(x,y,width,height,arcWidth, arcHeight);
1036        draw(rect);
1037    }
1038    
1039    /**
1040     * @see Graphics#fillRoundRect(int, int, int, int, int, int)
1041     */

1042    public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
1043        RoundRectangle2D JavaDoc rect = new RoundRectangle2D.Double JavaDoc(x,y,width,height,arcWidth, arcHeight);
1044        fill(rect);
1045    }
1046    
1047    /**
1048     * @see Graphics#drawOval(int, int, int, int)
1049     */

1050    public void drawOval(int x, int y, int width, int height) {
1051        Ellipse2D JavaDoc oval = new Ellipse2D.Float JavaDoc((float)x, (float)y, (float)width, (float)height);
1052        draw(oval);
1053    }
1054    
1055    /**
1056     * @see Graphics#fillOval(int, int, int, int)
1057     */

1058    public void fillOval(int x, int y, int width, int height) {
1059        Ellipse2D JavaDoc oval = new Ellipse2D.Float JavaDoc((float)x, (float)y, (float)width, (float)height);
1060        fill(oval);
1061    }
1062    
1063    /**
1064     * @see Graphics#drawArc(int, int, int, int, int, int)
1065     */

1066    public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
1067        Arc2D JavaDoc arc = new Arc2D.Double JavaDoc(x,y,width,height,startAngle, arcAngle, Arc2D.OPEN);
1068        draw(arc);
1069
1070    }
1071    
1072    /**
1073     * @see Graphics#fillArc(int, int, int, int, int, int)
1074     */

1075    public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
1076        Arc2D JavaDoc arc = new Arc2D.Double JavaDoc(x,y,width,height,startAngle, arcAngle, Arc2D.PIE);
1077        fill(arc);
1078    }
1079    
1080    /**
1081     * @see Graphics#drawPolyline(int[], int[], int)
1082     */

1083    public void drawPolyline(int[] x, int[] y, int nPoints) {
1084        PolylineShape polyline = new PolylineShape(x, y, nPoints);
1085        draw(polyline);
1086    }
1087    
1088    /**
1089     * @see Graphics#drawPolygon(int[], int[], int)
1090     */

1091    public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
1092        Polygon JavaDoc poly = new Polygon JavaDoc(xPoints, yPoints, nPoints);
1093        draw(poly);
1094    }
1095    
1096    /**
1097     * @see Graphics#fillPolygon(int[], int[], int)
1098     */

1099    public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
1100        Polygon JavaDoc poly = new Polygon JavaDoc();
1101        for (int i = 0; i < nPoints; i++) {
1102            poly.addPoint(xPoints[i], yPoints[i]);
1103        }
1104        fill(poly);
1105    }
1106    
1107    /**
1108     * @see Graphics#drawImage(Image, int, int, ImageObserver)
1109     */

1110    public boolean drawImage(Image JavaDoc img, int x, int y, ImageObserver JavaDoc observer) {
1111        return drawImage(img, x, y, null, observer);
1112    }
1113    
1114    /**
1115     * @see Graphics#drawImage(Image, int, int, int, int, ImageObserver)
1116     */

1117    public boolean drawImage(Image JavaDoc img, int x, int y, int width, int height, ImageObserver JavaDoc observer) {
1118        return drawImage(img, x, y, width, height, null, observer);
1119    }
1120    
1121    /**
1122     * @see Graphics#drawImage(Image, int, int, Color, ImageObserver)
1123     */

1124    public boolean drawImage(Image JavaDoc img, int x, int y, Color JavaDoc bgcolor, ImageObserver JavaDoc observer) {
1125        waitForImage(img);
1126        return drawImage(img, x, y, img.getWidth(observer), img.getHeight(observer), bgcolor, observer);
1127    }
1128    
1129    /**
1130     * @see Graphics#drawImage(Image, int, int, int, int, Color, ImageObserver)
1131     */

1132    public boolean drawImage(Image JavaDoc img, int x, int y, int width, int height, Color JavaDoc bgcolor, ImageObserver JavaDoc observer) {
1133        waitForImage(img);
1134        double scalex = width/(double)img.getWidth(observer);
1135        double scaley = height/(double)img.getHeight(observer);
1136        AffineTransform JavaDoc tx = AffineTransform.getTranslateInstance(x,y);
1137        tx.scale(scalex,scaley);
1138        return drawImage(img, null, tx, bgcolor, observer);
1139    }
1140    
1141    /**
1142     * @see Graphics#drawImage(Image, int, int, int, int, int, int, int, int, ImageObserver)
1143     */

1144    public boolean drawImage(Image JavaDoc img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver JavaDoc observer) {
1145        return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, observer);
1146    }
1147    
1148    /**
1149     * @see Graphics#drawImage(Image, int, int, int, int, int, int, int, int, Color, ImageObserver)
1150     */

1151    public boolean drawImage(Image JavaDoc img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color JavaDoc bgcolor, ImageObserver JavaDoc observer) {
1152        waitForImage(img);
1153        double dwidth = (double)dx2-dx1;
1154        double dheight = (double)dy2-dy1;
1155        double swidth = (double)sx2-sx1;
1156        double sheight = (double)sy2-sy1;
1157        
1158        //if either width or height is 0, then there is nothing to draw
1159
if (dwidth == 0 || dheight == 0 || swidth == 0 || sheight == 0) return true;
1160        
1161        double scalex = dwidth/swidth;
1162        double scaley = dheight/sheight;
1163        
1164        double transx = sx1*scalex;
1165        double transy = sy1*scaley;
1166        AffineTransform JavaDoc tx = AffineTransform.getTranslateInstance(dx1-transx,dy1-transy);
1167        tx.scale(scalex,scaley);
1168        
1169        BufferedImage JavaDoc mask = new BufferedImage JavaDoc(img.getWidth(observer), img.getHeight(observer), BufferedImage.TYPE_BYTE_BINARY);
1170        Graphics JavaDoc g = mask.getGraphics();
1171        g.fillRect(sx1,sy1, (int)swidth, (int)sheight);
1172        drawImage(img, mask, tx, null, observer);
1173        g.dispose();
1174        return true;
1175    }
1176    
1177    /**
1178     * @see Graphics#dispose()
1179     */

1180    public void dispose() {
1181        if (kid)
1182            return;
1183        if (!disposeCalled) {
1184            disposeCalled = true;
1185            cb.restoreState();
1186            cb.restoreState();
1187            dg2.dispose();
1188            dg2 = null;
1189            if (kids != null) {
1190                ByteBuffer buf = new ByteBuffer();
1191                internalDispose(buf);
1192                ByteBuffer buf2 = cb.getInternalBuffer();
1193                buf2.reset();
1194                buf2.append(buf);
1195            }
1196        }
1197    }
1198    
1199    private void internalDispose(ByteBuffer buf) {
1200        int last = 0;
1201        int pos = 0;
1202        ByteBuffer buf2 = cb.getInternalBuffer();
1203        if (kids != null) {
1204            for (int k = 0; k < kids.size(); k += 2) {
1205                pos = ((Integer JavaDoc)kids.get(k)).intValue();
1206                PdfGraphics2D g2 = (PdfGraphics2D)kids.get(k + 1);
1207                g2.cb.restoreState();
1208                g2.cb.restoreState();
1209                buf.append(buf2.getBuffer(), last, pos - last);
1210                g2.dg2.dispose();
1211                g2.dg2 = null;
1212                g2.internalDispose(buf);
1213                last = pos;
1214            }
1215        }
1216        buf.append(buf2.getBuffer(), last, buf2.size() - last);
1217    }
1218    
1219    ///////////////////////////////////////////////
1220
//
1221
//
1222
// implementation specific methods
1223
//
1224
//
1225

1226    
1227    private void followPath(Shape JavaDoc s, int drawType) {
1228        if (s==null) return;
1229        if (drawType==STROKE) {
1230            if (!(stroke instanceof BasicStroke JavaDoc)) {
1231                s = stroke.createStrokedShape(s);
1232                followPath(s, FILL);
1233                return;
1234            }
1235        }
1236        if (drawType==STROKE) {
1237            setStrokeDiff(stroke, oldStroke);
1238            oldStroke = stroke;
1239            setStrokePaint();
1240        }
1241        else if (drawType==FILL)
1242            setFillPaint();
1243        PathIterator JavaDoc points;
1244        int traces = 0;
1245        if (drawType == CLIP)
1246            points = s.getPathIterator(IDENTITY);
1247        else
1248            points = s.getPathIterator(transform);
1249        float[] coords = new float[6];
1250        while(!points.isDone()) {
1251            ++traces;
1252            int segtype = points.currentSegment(coords);
1253            normalizeY(coords);
1254            switch(segtype) {
1255                case PathIterator.SEG_CLOSE:
1256                    cb.closePath();
1257                    break;
1258
1259                case PathIterator.SEG_CUBICTO:
1260                    cb.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
1261                    break;
1262
1263                case PathIterator.SEG_LINETO:
1264                    cb.lineTo(coords[0], coords[1]);
1265                    break;
1266
1267                case PathIterator.SEG_MOVETO:
1268                    cb.moveTo(coords[0], coords[1]);
1269                    break;
1270
1271                case PathIterator.SEG_QUADTO:
1272                    cb.curveTo(coords[0], coords[1], coords[2], coords[3]);
1273                    break;
1274            }
1275            points.next();
1276        }
1277        switch (drawType) {
1278        case FILL:
1279            if (traces > 0) {
1280                if (points.getWindingRule() == PathIterator.WIND_EVEN_ODD)
1281                    cb.eoFill();
1282                else
1283                    cb.fill();
1284            }
1285            break;
1286        case STROKE:
1287            if (traces > 0)
1288                cb.stroke();
1289            break;
1290        default: //drawType==CLIP
1291
if (traces == 0)
1292                cb.rectangle(0, 0, 0, 0);
1293            if (points.getWindingRule() == PathIterator.WIND_EVEN_ODD)
1294                cb.eoClip();
1295            else
1296                cb.clip();
1297            cb.newPath();
1298        }
1299    }
1300    
1301    private float normalizeY(float y) {
1302        return this.height - y;
1303    }
1304    
1305    private void normalizeY(float[] coords) {
1306        coords[1] = normalizeY(coords[1]);
1307        coords[3] = normalizeY(coords[3]);
1308        coords[5] = normalizeY(coords[5]);
1309    }
1310    
1311    private AffineTransform JavaDoc normalizeMatrix() {
1312        double[] mx = new double[6];
1313        AffineTransform JavaDoc result = AffineTransform.getTranslateInstance(0,0);
1314        result.getMatrix(mx);
1315        mx[3]=-1;
1316        mx[5]=height;
1317        result = new AffineTransform JavaDoc(mx);
1318        result.concatenate(transform);
1319        return result;
1320    }
1321    
1322    private boolean drawImage(Image JavaDoc img, Image JavaDoc mask, AffineTransform JavaDoc xform, Color JavaDoc bgColor, ImageObserver JavaDoc obs) {
1323        if (xform==null) return true;
1324        
1325        xform.translate(0, img.getHeight(obs));
1326        xform.scale(img.getWidth(obs), img.getHeight(obs));
1327        
1328        AffineTransform JavaDoc inverse = this.normalizeMatrix();
1329        AffineTransform JavaDoc flipper = AffineTransform.getScaleInstance(1,-1);
1330        inverse.concatenate(xform);
1331        inverse.concatenate(flipper);
1332        
1333        double[] mx = new double[6];
1334        inverse.getMatrix(mx);
1335        if (currentFillGState != 255) {
1336            PdfGState gs = fillGState[255];
1337            if (gs == null) {
1338                gs = new PdfGState();
1339                gs.setFillOpacity(1);
1340                fillGState[255] = gs;
1341            }
1342            cb.setGState(gs);
1343        }
1344        
1345        try {
1346            com.lowagie.text.Image image = null;
1347            if(!convertImagesToJPEG){
1348                image = com.lowagie.text.Image.getInstance(img, bgColor);
1349            }
1350            else{
1351                BufferedImage JavaDoc scaled = new BufferedImage JavaDoc(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);
1352                Graphics2D JavaDoc g3 = scaled.createGraphics();
1353                g3.drawImage(img, 0, 0, img.getWidth(null), img.getHeight(null), null);
1354                g3.dispose();
1355                
1356                ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
1357                com.sun.image.codec.jpeg.JPEGImageEncoder encoder = com.sun.image.codec.jpeg.JPEGCodec.createJPEGEncoder(baos);
1358                com.sun.image.codec.jpeg.JPEGEncodeParam param = com.sun.image.codec.jpeg.JPEGCodec.getDefaultJPEGEncodeParam(scaled);
1359                param.setQuality(jpegQuality, true);
1360                encoder.encode(scaled, param);
1361                scaled.flush();
1362                scaled = null;
1363                image = com.lowagie.text.Image.getInstance(baos.toByteArray());
1364                
1365            }
1366            if (mask!=null) {
1367                com.lowagie.text.Image msk = com.lowagie.text.Image.getInstance(mask, null, true);
1368                msk.makeMask();
1369                msk.setInverted(true);
1370                image.setImageMask(msk);
1371            }
1372            cb.addImage(image, (float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]);
1373        } catch (Exception JavaDoc ex) {
1374            throw new IllegalArgumentException JavaDoc();
1375        }
1376        if (currentFillGState != 255) {
1377            PdfGState gs = fillGState[currentFillGState];
1378            cb.setGState(gs);
1379        }
1380        return true;
1381    }
1382    
1383    private boolean checkNewPaint(Paint JavaDoc oldPaint) {
1384        if (paint == oldPaint)
1385            return false;
1386        return !((paint instanceof Color JavaDoc) && paint.equals(oldPaint));
1387    }
1388    
1389    private void setFillPaint() {
1390        if (checkNewPaint(paintFill)) {
1391            paintFill = paint;
1392            setPaint(false, 0, 0, true);
1393        }
1394    }
1395    
1396    private void setStrokePaint() {
1397        if (checkNewPaint(paintStroke)) {
1398            paintStroke = paint;
1399            setPaint(false, 0, 0, false);
1400        }
1401    }
1402    
1403    private void setPaint(boolean invert, double xoffset, double yoffset, boolean fill) {
1404        if (paint instanceof Color JavaDoc) {
1405            Color JavaDoc color = (Color JavaDoc)paint;
1406            int alpha = color.getAlpha();
1407            if (fill) {
1408                if (alpha != currentFillGState) {
1409                    currentFillGState = alpha;
1410                    PdfGState gs = fillGState[alpha];
1411                    if (gs == null) {
1412                        gs = new PdfGState();
1413                        gs.setFillOpacity((float)alpha / 255f);
1414                        fillGState[alpha] = gs;
1415                    }
1416                    cb.setGState(gs);
1417                }
1418                cb.setColorFill(color);
1419            }
1420            else {
1421                if (alpha != currentStrokeGState) {
1422                    currentStrokeGState = alpha;
1423                    PdfGState gs = strokeGState[alpha];
1424                    if (gs == null) {
1425                        gs = new PdfGState();
1426                        gs.setStrokeOpacity((float)alpha / 255f);
1427                        strokeGState[alpha] = gs;
1428                    }
1429                    cb.setGState(gs);
1430                }
1431                cb.setColorStroke(color);
1432            }
1433        }
1434        else if (paint instanceof GradientPaint JavaDoc) {
1435            GradientPaint JavaDoc gp = (GradientPaint JavaDoc)paint;
1436            Point2D JavaDoc p1 = gp.getPoint1();
1437            transform.transform(p1, p1);
1438            Point2D JavaDoc p2 = gp.getPoint2();
1439            transform.transform(p2, p2);
1440            Color JavaDoc c1 = gp.getColor1();
1441            Color JavaDoc c2 = gp.getColor2();
1442            PdfShading shading = PdfShading.simpleAxial(cb.getPdfWriter(), (float)p1.getX(), normalizeY((float)p1.getY()), (float)p2.getX(), normalizeY((float)p2.getY()), c1, c2);
1443            PdfShadingPattern pat = new PdfShadingPattern(shading);
1444            if (fill)
1445                cb.setShadingFill(pat);
1446            else
1447                cb.setShadingStroke(pat);
1448        }
1449        else if (paint instanceof TexturePaint JavaDoc) {
1450            try {
1451                TexturePaint JavaDoc tp = (TexturePaint JavaDoc)paint;
1452                BufferedImage JavaDoc img = tp.getImage();
1453                Rectangle2D JavaDoc rect = tp.getAnchorRect();
1454                com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(img, null);
1455                PdfPatternPainter pattern = cb.createPattern(image.getWidth(), image.getHeight());
1456                AffineTransform JavaDoc inverse = this.normalizeMatrix();
1457                inverse.translate(rect.getX(), rect.getY());
1458                inverse.scale(rect.getWidth() / image.getWidth(), -rect.getHeight() / image.getHeight());
1459                double[] mx = new double[6];
1460                inverse.getMatrix(mx);
1461                pattern.setPatternMatrix((float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]) ;
1462                image.setAbsolutePosition(0,0);
1463                pattern.addImage(image);
1464                if (fill)
1465                    cb.setPatternFill(pattern);
1466                else
1467                    cb.setPatternStroke(pattern);
1468            } catch (Exception JavaDoc ex) {
1469                if (fill)
1470                    cb.setColorFill(Color.gray);
1471                else
1472                    cb.setColorStroke(Color.gray);
1473            }
1474        }
1475        else {
1476            try {
1477                BufferedImage JavaDoc img = null;
1478                int type = BufferedImage.TYPE_4BYTE_ABGR;
1479                if (paint.getTransparency() == Transparency.OPAQUE) {
1480                    type = BufferedImage.TYPE_3BYTE_BGR;
1481                }
1482                img = new BufferedImage JavaDoc((int)width, (int)height, type);
1483                Graphics2D JavaDoc g = (Graphics2D JavaDoc)img.getGraphics();
1484                g.transform(transform);
1485                AffineTransform JavaDoc inv = transform.createInverse();
1486                Shape JavaDoc fillRect = new Rectangle2D.Double JavaDoc(0,0,img.getWidth(),img.getHeight());
1487                fillRect = inv.createTransformedShape(fillRect);
1488                g.setPaint(paint);
1489                g.fill(fillRect);
1490                if (invert) {
1491                    AffineTransform JavaDoc tx = new AffineTransform JavaDoc();
1492                    tx.scale(1,-1);
1493                    tx.translate(-xoffset,-yoffset);
1494                    g.drawImage(img,tx,null);
1495                }
1496                g.dispose();
1497                g = null;
1498                com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(img, null);
1499                PdfPatternPainter pattern = cb.createPattern(width, height);
1500                image.setAbsolutePosition(0,0);
1501                pattern.addImage(image);
1502                if (fill)
1503                    cb.setPatternFill(pattern);
1504                else
1505                    cb.setPatternStroke(pattern);
1506            } catch (Exception JavaDoc ex) {
1507                if (fill)
1508                    cb.setColorFill(Color.gray);
1509                else
1510                    cb.setColorStroke(Color.gray);
1511            }
1512        }
1513    }
1514    
1515    private synchronized void waitForImage(java.awt.Image JavaDoc image) {
1516        if (mediaTracker == null)
1517            mediaTracker = new MediaTracker JavaDoc(new PdfGraphics2D.fakeComponent());
1518        mediaTracker.addImage(image, 0);
1519        try {
1520            mediaTracker.waitForID(0);
1521        }
1522        catch (InterruptedException JavaDoc e) {
1523            // empty on purpose
1524
}
1525        mediaTracker.removeImage(image);
1526    }
1527        
1528    static private class fakeComponent extends Component JavaDoc {
1529
1530        private static final long serialVersionUID = 6450197945596086638L;
1531    }
1532}
1533
Popular Tags