KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > ext > awt > g2d > GraphicContext


1 /*
2
3    Copyright 2001,2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.ext.awt.g2d;
19
20 import java.awt.AlphaComposite JavaDoc;
21 import java.awt.BasicStroke JavaDoc;
22 import java.awt.Color JavaDoc;
23 import java.awt.Composite JavaDoc;
24 import java.awt.Font JavaDoc;
25 import java.awt.Paint JavaDoc;
26 import java.awt.Rectangle JavaDoc;
27 import java.awt.RenderingHints JavaDoc;
28 import java.awt.Shape JavaDoc;
29 import java.awt.Stroke JavaDoc;
30 import java.awt.font.FontRenderContext JavaDoc;
31 import java.awt.geom.AffineTransform JavaDoc;
32 import java.awt.geom.Area JavaDoc;
33 import java.awt.geom.GeneralPath JavaDoc;
34 import java.awt.geom.NoninvertibleTransformException JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.Vector JavaDoc;
37
38 /**
39  * Handles the attributes in a graphic context:<br>
40  * + Composite <br>
41  * + Font <br>
42  * + Paint <br>
43  * + Stroke <br>
44  * + Clip <br>
45  * + RenderingHints <br>
46  * + AffineTransform <br>
47  *
48  * @author <a HREF="mailto:cjolif@ilog.fr">Christophe Jolif</a>
49  * @author <a HREF="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
50  * @version $Id: GraphicContext.java,v 1.10 2005/04/02 14:26:09 deweese Exp $
51  */

52 public class GraphicContext implements Cloneable JavaDoc{
53     /**
54      * Default Transform to be used for creating FontRenderContext.
55      */

56     protected AffineTransform JavaDoc defaultTransform = new AffineTransform JavaDoc();
57
58     /**
59      * Current AffineTransform. This is the concatenation
60      * of the original AffineTransform (i.e., last setTransform
61      * invocation) and the following transform invocations,
62      * as captured by originalTransform and the transformStack.
63      */

64     protected AffineTransform JavaDoc transform = new AffineTransform JavaDoc();
65
66     /**
67      * Transform stack
68      */

69     protected Vector JavaDoc transformStack = new Vector JavaDoc();
70
71     /**
72      * Defines whether the transform stack is valide or not.
73      * This is for use by the class clients. The client should
74      * validate the stack every time it starts using it. The
75      * stack becomes invalid when a new transform is set.
76      * @see #invalidateTransformStack()
77      * @see #isTransformStackValid
78      * @see #setTransform
79      */

80     protected boolean transformStackValid = true;
81
82     /**
83      * Current Paint
84      */

85     protected Paint JavaDoc paint = Color.black;
86
87     /**
88      * Current Stroke
89      */

90     protected Stroke JavaDoc stroke = new BasicStroke JavaDoc();
91
92     /**
93      * Current Composite
94      */

95     protected Composite JavaDoc composite = AlphaComposite.SrcOver;
96
97     /**
98      * Current clip
99      */

100     protected Shape JavaDoc clip = null;
101
102     /**
103      * Current set of RenderingHints
104      */

105     protected RenderingHints JavaDoc hints = new RenderingHints JavaDoc(null);
106
107     /**
108      * Current Font
109      */

110     protected Font JavaDoc font = new Font JavaDoc("sanserif", Font.PLAIN, 12);
111
112     /**
113      * Current background color.
114      */

115     protected Color JavaDoc background = new Color JavaDoc(0, 0, 0, 0);
116
117     /**
118      * Current foreground color
119      */

120     protected Color JavaDoc foreground = Color.black;
121
122     /**
123      * Default constructor
124      */

125     public GraphicContext() {
126         // to workaround a JDK bug
127
hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_DEFAULT);
128     }
129
130     /**
131      * @param defaultDeviceTransform Default affine transform applied to map the user space to the
132      * user space.
133      */

134     public GraphicContext(AffineTransform JavaDoc defaultDeviceTransform) {
135         this();
136         defaultTransform = new AffineTransform JavaDoc(defaultDeviceTransform);
137         transform = new AffineTransform JavaDoc(defaultTransform);
138         if (!defaultTransform.isIdentity())
139             transformStack.addElement(TransformStackElement.createGeneralTransformElement(defaultTransform));
140     }
141
142     /**
143      * @return a deep copy of this context
144      */

145     public Object JavaDoc clone(){
146         GraphicContext copyGc = new GraphicContext(defaultTransform);
147
148         //
149
// Now, copy each GC element in turn
150
//
151

152         // Default transform
153
/* Set in constructor */
154
155         // Transform
156
copyGc.transform = new AffineTransform JavaDoc(this.transform);
157
158         // Transform stack
159
copyGc.transformStack = new Vector JavaDoc();
160         for(int i=0; i<this.transformStack.size(); i++){
161             TransformStackElement stackElement =
162                 (TransformStackElement)this.transformStack.elementAt(i);
163             copyGc.transformStack.addElement(stackElement.clone());
164         }
165
166         // Transform stack validity
167
copyGc.transformStackValid = this.transformStackValid;
168
169         // Paint (immutable by requirement)
170
copyGc.paint = this.paint;
171
172         // Stroke (immutable by requirement)
173
copyGc.stroke = this.stroke;
174
175         // Composite (immutable by requirement)
176
copyGc.composite = this.composite;
177
178         // Clip
179
if(clip != null)
180             copyGc.clip = new GeneralPath JavaDoc(clip);
181         else
182             copyGc.clip = null;
183
184         // RenderingHints
185
copyGc.hints = (RenderingHints JavaDoc)this.hints.clone();
186
187         // Font (immutable)
188
copyGc.font = this.font;
189
190         // Background, Foreground (immutable)
191
copyGc.background = this.background;
192         copyGc.foreground = this.foreground;
193
194         return copyGc;
195     }
196
197     /**
198      * Gets this graphics context's current color.
199      * @return this graphics context's current color.
200      * @see java.awt.Color
201      * @see java.awt.Graphics#setColor
202      */

203     public Color JavaDoc getColor(){
204         return foreground;
205     }
206
207     /**
208      * Sets this graphics context's current color to the specified
209      * color. All subsequent graphics operations using this graphics
210      * context use this specified color.
211      * @param c the new rendering color.
212      * @see java.awt.Color
213      * @see java.awt.Graphics#getColor
214      */

215     public void setColor(Color JavaDoc c){
216         if(c == null)
217             return;
218
219         if(paint != c)
220             setPaint(c);
221     }
222
223     /**
224      * Gets the current font.
225      * @return this graphics context's current font.
226      * @see java.awt.Font
227      * @see java.awt.Graphics#setFont
228      */

229     public Font JavaDoc getFont(){
230         return font;
231     }
232
233     /**
234      * Sets this graphics context's font to the specified font.
235      * All subsequent text operations using this graphics context
236      * use this font.
237      * @param font the font.
238      * @see java.awt.Graphics#getFont
239      */

240     public void setFont(Font JavaDoc font){
241         if(font != null)
242             this.font = font;
243     }
244
245     /**
246      * Returns the bounding rectangle of the current clipping area.
247      * This method refers to the user clip, which is independent of the
248      * clipping associated with device bounds and window visibility.
249      * If no clip has previously been set, or if the clip has been
250      * cleared using <code>setClip(null)</code>, this method returns
251      * <code>null</code>.
252      * The coordinates in the rectangle are relative to the coordinate
253      * system origin of this graphics context.
254      * @return the bounding rectangle of the current clipping area,
255      * or <code>null</code> if no clip is set.
256      * @see java.awt.Graphics#getClip
257      * @see java.awt.Graphics#clipRect
258      * @see java.awt.Graphics#setClip(int, int, int, int)
259      * @see java.awt.Graphics#setClip(Shape)
260      * @since JDK1.1
261      */

262     public Rectangle JavaDoc getClipBounds(){
263         Shape JavaDoc c = getClip();
264         if(c==null)
265             return null;
266         else
267             return c.getBounds();
268     }
269
270
271     /**
272      * Intersects the current clip with the specified rectangle.
273      * The resulting clipping area is the intersection of the current
274      * clipping area and the specified rectangle. If there is no
275      * current clipping area, either because the clip has never been
276      * set, or the clip has been cleared using <code>setClip(null)</code>,
277      * the specified rectangle becomes the new clip.
278      * This method sets the user clip, which is independent of the
279      * clipping associated with device bounds and window visibility.
280      * This method can only be used to make the current clip smaller.
281      * To set the current clip larger, use any of the setClip methods.
282      * Rendering operations have no effect outside of the clipping area.
283      * @param x the x coordinate of the rectangle to intersect the clip with
284      * @param y the y coordinate of the rectangle to intersect the clip with
285      * @param width the width of the rectangle to intersect the clip with
286      * @param height the height of the rectangle to intersect the clip with
287      * @see #setClip(int, int, int, int)
288      * @see #setClip(Shape)
289      */

290     public void clipRect(int x, int y, int width, int height){
291         clip(new Rectangle JavaDoc(x, y, width, height));
292     }
293
294
295     /**
296      * Sets the current clip to the rectangle specified by the given
297      * coordinates. This method sets the user clip, which is
298      * independent of the clipping associated with device bounds
299      * and window visibility.
300      * Rendering operations have no effect outside of the clipping area.
301      * @param x the <i>x</i> coordinate of the new clip rectangle.
302      * @param y the <i>y</i> coordinate of the new clip rectangle.
303      * @param width the width of the new clip rectangle.
304      * @param height the height of the new clip rectangle.
305      * @see java.awt.Graphics#clipRect
306      * @see java.awt.Graphics#setClip(Shape)
307      * @since JDK1.1
308      */

309     public void setClip(int x, int y, int width, int height){
310         setClip(new Rectangle JavaDoc(x, y, width, height));
311     }
312
313
314     /**
315      * Gets the current clipping area.
316      * This method returns the user clip, which is independent of the
317      * clipping associated with device bounds and window visibility.
318      * If no clip has previously been set, or if the clip has been
319      * cleared using <code>setClip(null)</code>, this method returns
320      * <code>null</code>.
321      * @return a <code>Shape</code> object representing the
322      * current clipping area, or <code>null</code> if
323      * no clip is set.
324      * @see java.awt.Graphics#getClipBounds
325      * @see java.awt.Graphics#clipRect
326      * @see java.awt.Graphics#setClip(int, int, int, int)
327      * @see java.awt.Graphics#setClip(Shape)
328      * @since JDK1.1
329      */

330     public Shape JavaDoc getClip(){
331         try{
332             return transform.createInverse().createTransformedShape(clip);
333         }catch(NoninvertibleTransformException JavaDoc e){
334             return null;
335         }
336     }
337
338
339     /**
340      * Sets the current clipping area to an arbitrary clip shape.
341      * Not all objects that implement the <code>Shape</code>
342      * interface can be used to set the clip. The only
343      * <code>Shape</code> objects that are guaranteed to be
344      * supported are <code>Shape</code> objects that are
345      * obtained via the <code>getClip</code> method and via
346      * <code>Rectangle</code> objects. This method sets the
347      * user clip, which is independent of the clipping associated
348      * with device bounds and window visibility.
349      * @param clip the <code>Shape</code> to use to set the clip
350      * @see java.awt.Graphics#getClip()
351      * @see java.awt.Graphics#clipRect
352      * @see java.awt.Graphics#setClip(int, int, int, int)
353      * @since JDK1.1
354      */

355     public void setClip(Shape JavaDoc clip) {
356         if (clip != null)
357             this.clip = transform.createTransformedShape(clip);
358         else
359             this.clip = null;
360     }
361
362     /**
363      * Sets the <code>Composite</code> for the <code>Graphics2D</code> context.
364      * The <code>Composite</code> is used in all drawing methods such as
365      * <code>drawImage</code>, <code>drawString</code>, <code>draw</code>,
366      * and <code>fill</code>. It specifies how new pixels are to be combined
367      * with the existing pixels on the graphics device during the rendering
368      * process.
369      * <p>If this <code>Graphics2D</code> context is drawing to a
370      * <code>Component</code> on the display screen and the
371      * <code>Composite</code> is a custom object rather than an
372      * instance of the <code>AlphaComposite</code> class, and if
373      * there is a security manager, its <code>checkPermission</code>
374      * method is called with an <code>AWTPermission("readDisplayPixels")</code>
375      * permission.
376      * @throws SecurityException
377      * if a custom <code>Composite</code> object is being
378      * used to render to the screen and a security manager
379      * is set and its <code>checkPermission</code> method
380      * does not allow the operation.
381      * @param comp the <code>Composite</code> object to be used for rendering
382      * @see java.awt.Graphics#setXORMode
383      * @see java.awt.Graphics#setPaintMode
384      * @see java.awt.AlphaComposite
385      */

386     public void setComposite(Composite JavaDoc comp){
387         this.composite = comp;
388     }
389
390
391     /**
392      * Sets the <code>Paint</code> attribute for the
393      * <code>Graphics2D</code> context. Calling this method
394      * with a <code>null</code> <code>Paint</code> object does
395      * not have any effect on the current <code>Paint</code> attribute
396      * of this <code>Graphics2D</code>.
397      * @param paint the <code>Paint</code> object to be used to generate
398      * color during the rendering process, or <code>null</code>
399      * @see java.awt.Graphics#setColor
400      * @see java.awt.GradientPaint
401      * @see java.awt.TexturePaint
402      */

403     public void setPaint( Paint JavaDoc paint ){
404         if(paint == null)
405             return;
406
407         this.paint = paint;
408         if(paint instanceof Color JavaDoc)
409             foreground = (Color JavaDoc)paint;
410     }
411
412
413     /**
414      * Sets the <code>Stroke</code> for the <code>Graphics2D</code> context.
415      * @param s the <code>Stroke</code> object to be used to stroke a
416      * <code>Shape</code> during the rendering process
417      * @see BasicStroke
418      */

419     public void setStroke(Stroke JavaDoc s){
420         stroke = s;
421     }
422
423     /**
424      * Sets the value of a single preference for the rendering algorithms.
425      * Hint categories include controls for rendering quality and overall
426      * time/quality trade-off in the rendering process. Refer to the
427      * <code>RenderingHints</code> class for definitions of some common
428      * keys and values.
429      * @param hintKey the key of the hint to be set.
430      * @param hintValue the value indicating preferences for the specified
431      * hint category.
432      * @see RenderingHints
433      */

434     public void setRenderingHint(RenderingHints.Key JavaDoc hintKey, Object JavaDoc hintValue){
435         hints.put(hintKey, hintValue);
436     }
437
438
439     /**
440      * Returns the value of a single preference for the rendering algorithms.
441      * Hint categories include controls for rendering quality and overall
442      * time/quality trade-off in the rendering process. Refer to the
443      * <code>RenderingHints</code> class for definitions of some common
444      * keys and values.
445      * @param hintKey the key corresponding to the hint to get.
446      * @return an object representing the value for the specified hint key.
447      * Some of the keys and their associated values are defined in the
448      * <code>RenderingHints</code> class.
449      * @see RenderingHints
450      */

451     public Object JavaDoc getRenderingHint(RenderingHints.Key JavaDoc hintKey){
452         return hints.get(hintKey);
453     }
454
455
456     /**
457      * Replaces the values of all preferences for the rendering
458      * algorithms with the specified <code>hints</code>.
459      * The existing values for all rendering hints are discarded and
460      * the new set of known hints and values are initialized from the
461      * specified {@link Map} object.
462      * Hint categories include controls for rendering quality and
463      * overall time/quality trade-off in the rendering process.
464      * Refer to the <code>RenderingHints</code> class for definitions of
465      * some common keys and values.
466      * @param hints the rendering hints to be set
467      * @see RenderingHints
468      */

469     public void setRenderingHints(Map JavaDoc hints){
470         this.hints = new RenderingHints JavaDoc(hints);
471     }
472
473
474     /**
475      * Sets the values of an arbitrary number of preferences for the
476      * rendering algorithms.
477      * Only values for the rendering hints that are present in the
478      * specified <code>Map</code> object are modified.
479      * All other preferences not present in the specified
480      * object are left unmodified.
481      * Hint categories include controls for rendering quality and
482      * overall time/quality trade-off in the rendering process.
483      * Refer to the <code>RenderingHints</code> class for definitions of
484      * some common keys and values.
485      * @param hints the rendering hints to be set
486      * @see RenderingHints
487      */

488     public void addRenderingHints(Map JavaDoc hints){
489         this.hints.putAll(hints);
490     }
491
492
493     /**
494      * Gets the preferences for the rendering algorithms. Hint categories
495      * include controls for rendering quality and overall time/quality
496      * trade-off in the rendering process.
497      * Returns all of the hint key/value pairs that were ever specified in
498      * one operation. Refer to the
499      * <code>RenderingHints</code> class for definitions of some common
500      * keys and values.
501      * @return a reference to an instance of <code>RenderingHints</code>
502      * that contains the current preferences.
503      * @see RenderingHints
504      */

505     public RenderingHints JavaDoc getRenderingHints(){
506         return hints;
507     }
508
509     /**
510      * Translates the origin of the graphics context to the point
511      * (<i>x</i>,&nbsp;<i>y</i>) in the current coordinate system.
512      * Modifies this graphics context so that its new origin corresponds
513      * to the point (<i>x</i>,&nbsp;<i>y</i>) in this graphics context's
514      * original coordinate system. All coordinates used in subsequent
515      * rendering operations on this graphics context will be relative
516      * to this new origin.
517      * @param x the <i>x</i> coordinate.
518      * @param y the <i>y</i> coordinate.
519      */

520     public void translate(int x, int y){
521         if(x!=0 || y!=0){
522             transform.translate(x, y);
523             transformStack.addElement(TransformStackElement.createTranslateElement(x, y));
524         }
525     }
526
527
528     /**
529      * Concatenates the current
530      * <code>Graphics2D</code> <code>Transform</code>
531      * with a translation transform.
532      * Subsequent rendering is translated by the specified
533      * distance relative to the previous position.
534      * This is equivalent to calling transform(T), where T is an
535      * <code>AffineTransform</code> represented by the following matrix:
536      * <pre>
537      * [ 1 0 tx ]
538      * [ 0 1 ty ]
539      * [ 0 0 1 ]
540      * </pre>
541      * @param tx the distance to translate along the x-axis
542      * @param ty the distance to translate along the y-axis
543      */

544     public void translate(double tx, double ty){
545         transform.translate(tx, ty);
546         transformStack.addElement(TransformStackElement.createTranslateElement(tx, ty));
547     }
548
549     /**
550      * Concatenates the current <code>Graphics2D</code>
551      * <code>Transform</code> with a rotation transform.
552      * Subsequent rendering is rotated by the specified radians relative
553      * to the previous origin.
554      * This is equivalent to calling <code>transform(R)</code>, where R is an
555      * <code>AffineTransform</code> represented by the following matrix:
556      * <pre>
557      * [ cos(theta) -sin(theta) 0 ]
558      * [ sin(theta) cos(theta) 0 ]
559      * [ 0 0 1 ]
560      * </pre>
561      * Rotating with a positive angle theta rotates points on the positive
562      * x axis toward the positive y axis.
563      * @param theta the angle of rotation in radians
564      */

565     public void rotate(double theta){
566         transform.rotate(theta);
567         transformStack.addElement(TransformStackElement.createRotateElement(theta));
568     }
569
570     /**
571      * Concatenates the current <code>Graphics2D</code>
572      * <code>Transform</code> with a translated rotation
573      * transform. Subsequent rendering is transformed by a transform
574      * which is constructed by translating to the specified location,
575      * rotating by the specified radians, and translating back by the same
576      * amount as the original translation. This is equivalent to the
577      * following sequence of calls:
578      * <pre>
579      * translate(x, y);
580      * rotate(theta);
581      * translate(-x, -y);
582      * </pre>
583      * Rotating with a positive angle theta rotates points on the positive
584      * x axis toward the positive y axis.
585      * @param theta the angle of rotation in radians
586      * @param x x coordinate of the origin of the rotation
587      * @param y y coordinate of the origin of the rotation
588      */

589     public void rotate(double theta, double x, double y){
590         transform.rotate(theta, x, y);
591         transformStack.addElement(TransformStackElement.createTranslateElement(x, y));
592         transformStack.addElement(TransformStackElement.createRotateElement(theta));
593         transformStack.addElement(TransformStackElement.createTranslateElement(-x, -y));
594     }
595
596     /**
597      * Concatenates the current <code>Graphics2D</code>
598      * <code>Transform</code> with a scaling transformation
599      * Subsequent rendering is resized according to the specified scaling
600      * factors relative to the previous scaling.
601      * This is equivalent to calling <code>transform(S)</code>, where S is an
602      * <code>AffineTransform</code> represented by the following matrix:
603      * <pre>
604      * [ sx 0 0 ]
605      * [ 0 sy 0 ]
606      * [ 0 0 1 ]
607      * </pre>
608      * @param sx the amount by which X coordinates in subsequent
609      * rendering operations are multiplied relative to previous
610      * rendering operations.
611      * @param sy the amount by which Y coordinates in subsequent
612      * rendering operations are multiplied relative to previous
613      * rendering operations.
614      */

615     public void scale(double sx, double sy){
616         transform.scale(sx, sy);
617         transformStack.addElement(TransformStackElement.createScaleElement(sx, sy));
618     }
619
620     /**
621      * Concatenates the current <code>Graphics2D</code>
622      * <code>Transform</code> with a shearing transform.
623      * Subsequent renderings are sheared by the specified
624      * multiplier relative to the previous position.
625      * This is equivalent to calling <code>transform(SH)</code>, where SH
626      * is an <code>AffineTransform</code> represented by the following
627      * matrix:
628      * <pre>
629      * [ 1 shx 0 ]
630      * [ shy 1 0 ]
631      * [ 0 0 1 ]
632      * </pre>
633      * @param shx the multiplier by which coordinates are shifted in
634      * the positive X axis direction as a function of their Y coordinate
635      * @param shy the multiplier by which coordinates are shifted in
636      * the positive Y axis direction as a function of their X coordinate
637      */

638     public void shear(double shx, double shy){
639         transform.shear(shx, shy);
640         transformStack.addElement(TransformStackElement.createShearElement(shx, shy));
641     }
642
643     /**
644      * Composes an <code>AffineTransform</code> object with the
645      * <code>Transform</code> in this <code>Graphics2D</code> according
646      * to the rule last-specified-first-applied. If the current
647      * <code>Transform</code> is Cx, the result of composition
648      * with Tx is a new <code>Transform</code> Cx'. Cx' becomes the
649      * current <code>Transform</code> for this <code>Graphics2D</code>.
650      * Transforming a point p by the updated <code>Transform</code> Cx' is
651      * equivalent to first transforming p by Tx and then transforming
652      * the result by the original <code>Transform</code> Cx. In other
653      * words, Cx'(p) = Cx(Tx(p)). A copy of the Tx is made, if necessary,
654      * so further modifications to Tx do not affect rendering.
655      * @param Tx the <code>AffineTransform</code> object to be composed with
656      * the current <code>Transform</code>
657      * @see #setTransform
658      * @see AffineTransform
659      */

660     public void transform(AffineTransform JavaDoc Tx){
661         transform.concatenate(Tx);
662         transformStack.addElement(TransformStackElement.createGeneralTransformElement(Tx));
663     }
664
665     /**
666      * Sets the <code>Transform</code> in the <code>Graphics2D</code>
667      * context.
668      * @param Tx the <code>AffineTransform</code> object to be used in the
669      * rendering process
670      * @see #transform
671      * @see AffineTransform
672      */

673     public void setTransform(AffineTransform JavaDoc Tx){
674         transform = new AffineTransform JavaDoc(Tx);
675         invalidateTransformStack();
676         if(!Tx.isIdentity())
677             transformStack.addElement(TransformStackElement.createGeneralTransformElement(Tx));
678     }
679
680     /**
681      * Marks the GraphicContext's isNewTransformStack to false
682      * as a memento that the current transform stack was read and
683      * has not been reset. Only the setTransform method can
684      * override this memento.
685      */

686     public void validateTransformStack(){
687         transformStackValid = true;
688     }
689
690     /**
691      * Checks the status of the transform stack
692      */

693     public boolean isTransformStackValid(){
694         return transformStackValid;
695     }
696
697     /**
698      * @return array containing the successive transforms that
699      * were concatenated with the original one.
700      */

701     public TransformStackElement[] getTransformStack(){
702         TransformStackElement stack[] = new TransformStackElement[transformStack.size()];
703         transformStack.copyInto(stack);
704         return stack;
705     }
706
707     /**
708      * Marks the GraphicContext's isNewTransformStack to true
709      * as a memento that the current transform stack was reset
710      * since it was last read. Only validateTransformStack
711      * can override this memento
712      */

713     protected void invalidateTransformStack(){
714         transformStack.removeAllElements();
715         transformStackValid = false;
716     }
717
718     /**
719      * Returns a copy of the current <code>Transform</code> in the
720      * <code>Graphics2D</code> context.
721      * @return the current <code>AffineTransform</code> in the
722      * <code>Graphics2D</code> context.
723      * @see #transform
724      * @see #setTransform
725      */

726     public AffineTransform JavaDoc getTransform(){
727         return new AffineTransform JavaDoc(transform);
728     }
729
730     /**
731      * Returns the current <code>Paint</code> of the
732      * <code>Graphics2D</code> context.
733      * @return the current <code>Graphics2D</code> <code>Paint</code>,
734      * which defines a color or pattern.
735      * @see #setPaint
736      * @see java.awt.Graphics#setColor
737      */

738     public Paint JavaDoc getPaint(){
739         return paint;
740     }
741
742
743     /**
744      * Returns the current <code>Composite</code> in the
745      * <code>Graphics2D</code> context.
746      * @return the current <code>Graphics2D</code> <code>Composite</code>,
747      * which defines a compositing style.
748      * @see #setComposite
749      */

750     public Composite JavaDoc getComposite(){
751         return composite;
752     }
753
754     /**
755      * Sets the background color for the <code>Graphics2D</code> context.
756      * The background color is used for clearing a region.
757      * When a <code>Graphics2D</code> is constructed for a
758      * <code>Component</code>, the background color is
759      * inherited from the <code>Component</code>. Setting the background color
760      * in the <code>Graphics2D</code> context only affects the subsequent
761      * <code>clearRect</code> calls and not the background color of the
762      * <code>Component</code>. To change the background
763      * of the <code>Component</code>, use appropriate methods of
764      * the <code>Component</code>.
765      * @param color the background color that isused in
766      * subsequent calls to <code>clearRect</code>
767      * @see #getBackground
768      * @see java.awt.Graphics#clearRect
769      */

770     public void setBackground(Color JavaDoc color){
771         if(color == null)
772             return;
773
774         background = color;
775     }
776
777
778     /**
779      * Returns the background color used for clearing a region.
780      * @return the current <code>Graphics2D</code> <code>Color</code>,
781      * which defines the background color.
782      * @see #setBackground
783      */

784     public Color JavaDoc getBackground(){
785         return background;
786     }
787
788     /**
789      * Returns the current <code>Stroke</code> in the
790      * <code>Graphics2D</code> context.
791      * @return the current <code>Graphics2D</code> <code>Stroke</code>,
792      * which defines the line style.
793      * @see #setStroke
794      */

795     public Stroke JavaDoc getStroke(){
796         return stroke;
797     }
798
799
800     /**
801      * Intersects the current <code>Clip</code> with the interior of the
802      * specified <code>Shape</code> and sets the <code>Clip</code> to the
803      * resulting intersection. The specified <code>Shape</code> is
804      * transformed with the current <code>Graphics2D</code>
805      * <code>Transform</code> before being intersected with the current
806      * <code>Clip</code>. This method is used to make the current
807      * <code>Clip</code> smaller.
808      * To make the <code>Clip</code> larger, use <code>setClip</code>.
809      * The <i>user clip</i> modified by this method is independent of the
810      * clipping associated with device bounds and visibility. If no clip has
811      * previously been set, or if the clip has been cleared using
812      * {@link java.awt.Graphics#setClip(Shape) setClip} with a
813      * <code>null</code> argument, the specified <code>Shape</code> becomes
814      * the new user clip.
815      * @param s the <code>Shape</code> to be intersected with the current
816      * <code>Clip</code>. If <code>s</code> is <code>null</code>,
817      * this method clears the current <code>Clip</code>.
818      */

819     public void clip(Shape JavaDoc s){
820         if (s != null)
821             s = transform.createTransformedShape(s);
822
823         if (clip != null) {
824             Area JavaDoc newClip = new Area JavaDoc(clip);
825             newClip.intersect(new Area JavaDoc(s));
826             clip = new GeneralPath JavaDoc(newClip);
827         } else {
828             clip = s;
829         }
830     }
831
832     /**
833      * Get the rendering context of the <code>Font</code> within this
834      * <code>Graphics2D</code> context.
835      * The {@link FontRenderContext}
836      * encapsulates application hints such as anti-aliasing and
837      * fractional metrics, as well as target device specific information
838      * such as dots-per-inch. This information should be provided by the
839      * application when using objects that perform typographical
840      * formatting, such as <code>Font</code> and
841      * <code>TextLayout</code>. This information should also be provided
842      * by applications that perform their own layout and need accurate
843      * measurements of various characteristics of glyphs such as advance
844      * and line height when various rendering hints have been applied to
845      * the text rendering.
846      *
847      * @return a reference to an instance of FontRenderContext.
848      * @see java.awt.font.FontRenderContext
849      * @see java.awt.Font#createGlyphVector
850      * @see java.awt.font.TextLayout
851      * @since JDK1.2
852      */

853     public FontRenderContext JavaDoc getFontRenderContext(){
854         //
855
// Find if antialiasing should be used.
856
//
857
Object JavaDoc antialiasingHint = hints.get(RenderingHints.KEY_TEXT_ANTIALIASING);
858         boolean isAntialiased = true;
859         if(antialiasingHint != RenderingHints.VALUE_TEXT_ANTIALIAS_ON &&
860            antialiasingHint != RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT){
861
862             // If antialias was not turned off, then use the general rendering
863
// hint.
864
if(antialiasingHint != RenderingHints.VALUE_TEXT_ANTIALIAS_OFF){
865                 antialiasingHint = hints.get(RenderingHints.KEY_ANTIALIASING);
866
867                 // Test general hint
868
if(antialiasingHint != RenderingHints.VALUE_ANTIALIAS_ON &&
869                    antialiasingHint != RenderingHints.VALUE_ANTIALIAS_DEFAULT){
870                     // Antialiasing was not requested. However, if it was not turned
871
// off explicitly, use it.
872
if(antialiasingHint == RenderingHints.VALUE_ANTIALIAS_OFF)
873                         isAntialiased = false;
874                 }
875             }
876             else
877                 isAntialiased = false;
878
879         }
880
881         //
882
// Find out whether fractional metrics should be used.
883
//
884
boolean useFractionalMetrics = true;
885         if(hints.get(RenderingHints.KEY_FRACTIONALMETRICS)
886            == RenderingHints.VALUE_FRACTIONALMETRICS_OFF)
887             useFractionalMetrics = false;
888
889         FontRenderContext JavaDoc frc = new FontRenderContext JavaDoc(defaultTransform,
890                                                       isAntialiased,
891                                                       useFractionalMetrics);
892         return frc;
893     }
894 }
895
Popular Tags