KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jcckit > renderer > GraphicsRenderer


1 /*
2  * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved
3  *
4  * This library is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation; either version 2.1 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details
13  * (http://www.gnu.org/copyleft/lesser.html).
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19 package jcckit.renderer;
20
21 import jcckit.graphic.BasicGraphicalElement;
22 import jcckit.graphic.GraphPoint;
23 import jcckit.graphic.ClippingRectangle;
24 import jcckit.graphic.ClippingShape;
25 import jcckit.graphic.FillAttributes;
26 import jcckit.graphic.FontStyle;
27 import jcckit.graphic.GraphicalComposite;
28 import jcckit.graphic.GraphicalCompositeRenderer;
29 import jcckit.graphic.GraphicAttributes;
30 import jcckit.graphic.LineAttributes;
31 import jcckit.graphic.Oval;
32 import jcckit.graphic.OvalRenderer;
33 import jcckit.graphic.Polygon;
34 import jcckit.graphic.PolygonRenderer;
35 import jcckit.graphic.Rectangle;
36 import jcckit.graphic.RectangleRenderer;
37 import jcckit.graphic.Text;
38 import jcckit.graphic.TextAttributes;
39 import jcckit.graphic.TextRenderer;
40
41 import java.awt.Color JavaDoc;
42 import java.awt.Component JavaDoc;
43 import java.awt.Font JavaDoc;
44 import java.awt.FontMetrics JavaDoc;
45 import java.awt.Graphics JavaDoc;
46 import java.awt.Image JavaDoc;
47 import java.awt.image.ColorModel JavaDoc;
48 import java.awt.image.MemoryImageSource JavaDoc;
49 import java.awt.image.PixelGrabber JavaDoc;
50 import java.util.Stack JavaDoc;
51
52 /**
53  * Renderer who draws the {@link jcckit.graphic.GraphicalElement
54  * GraphicalElements} into a <tt>java.awt.Graphics</tt> context.
55  * <p>
56  * The default color for lines and texts is determined by the
57  * current color of the <tt>Graphics</tt> context when a new
58  * instance of <tt>GraphicsRenderer</tt> is created.
59  * <p>
60  * The default font is <tt>SansSerif-12</tt>.
61  *
62  * @author Franz-Josef Elmer
63  */

64 public class GraphicsRenderer implements GraphicalCompositeRenderer,
65                                          PolygonRenderer, OvalRenderer,
66                                          TextRenderer, RectangleRenderer {
67   private static final String JavaDoc DEFAULT_FONT_NAME = "SansSerif";
68   private static final FontStyle DEFAULT_FONT_STYLE = FontStyle.NORMAL;
69   private static final int DEFAULT_FONT_SIZE = 12;
70
71   /**
72    * Creates a font instance based on the specified text attributes and
73    * font size.
74    * @param attributes Text attributes (font name and style).
75    * @param size Font size in pixel. If 0 {@link #DEFAULT_FONT_SIZE}
76    * will be used.
77    * @return new font instance.
78    */

79   static Font JavaDoc createFont(TextAttributes attributes, int size)
80   {
81     String JavaDoc fontName = attributes.getFontName();
82     if (fontName == null) {
83       fontName = DEFAULT_FONT_NAME;
84     }
85     
86     FontStyle fontStyle = attributes.getFontStyle();
87     if (fontStyle == null) {
88       fontStyle = DEFAULT_FONT_STYLE;
89     }
90     int style = Font.PLAIN;
91     if (fontStyle == FontStyle.BOLD) {
92       style = Font.BOLD;
93     } else if (fontStyle == FontStyle.ITALIC) {
94       style = Font.ITALIC;
95     } else if (fontStyle == FontStyle.BOLD_ITALIC) {
96       style = Font.BOLD + Font.ITALIC;
97     }
98
99     if (size == 0) {
100       size = DEFAULT_FONT_SIZE;
101     }
102     
103     return new Font JavaDoc(fontName, style, size);
104   }
105
106   private final Stack JavaDoc _graphicsStack = new Stack JavaDoc();
107   private Transformation _t;
108   private Component JavaDoc _component;
109   private Graphics JavaDoc _graphics;
110   private Color JavaDoc _defaultColor;
111
112   /**
113    * Initializes this instance.
114    * @param graphics Graphics context into which the
115    * {@link BasicGraphicalElement BaiscGraphicalElements} are painted.
116    * @param component A component needed for creating off-screen images of
117    * rotated texts.
118    * @param transformation Transformation from the device-independent
119    * coordinates into pixel-based Java coordinates.
120    * @return this instance.
121    */

122   public GraphicsRenderer init(Graphics JavaDoc graphics, Component JavaDoc component,
123                                Transformation transformation) {
124     _graphics = graphics;
125     _component = component;
126     _t = transformation;
127     _defaultColor = graphics.getColor(); // the foreground color
128
return this;
129   }
130
131   /**
132    * Starts rendering of the specified composite. Does nothing except if
133    * <tt>composite</tt> has a {@link ClippingShape}. In this case the
134    * current <tt>Graphics</tt> context will be pushed onto a stack.
135    * The new <tt>Graphics</tt> context is a clone of the current one
136    * where the clipping rectangle is determined by the bounding box
137    * of <tt>ClippingShape</tt>.
138    */

139   public void startRendering(GraphicalComposite composite) {
140     ClippingShape shape = composite.getClippingShape();
141     if (shape != null) {
142       _graphicsStack.push(_graphics);
143       _graphics = _graphics.create();
144       ClippingRectangle rect = shape.getBoundingBox();
145       int x = _t.transformX(rect.getMinX());
146       int y = _t.transformY(rect.getMaxY());
147       _graphics.setClip(x, y, _t.transformX(rect.getMaxX()) - x,
148                         _t.transformY(rect.getMinY()) - y);
149     }
150   }
151
152   /**
153    * Finishes rendering of the specified composite. Does nothing except if
154    * <tt>composite</tt> has a {@link ClippingShape}. In this case the
155    * <tt>Graphics</tt> context will be poped from the stack and will replace
156    * the current one.
157    */

158   public void finishRendering(GraphicalComposite composite) {
159     if (composite.getClippingShape() != null) {
160       _graphics = (Graphics JavaDoc) _graphicsStack.pop();
161     }
162   }
163
164   /**
165    * Paints the specified polygon into the current <tt>Graphics</tt> context.
166    */

167   public void render(Polygon polygon) {
168     int numberOfPoints = polygon.getNumberOfPoints();
169     if (numberOfPoints > 0) {
170       Color JavaDoc currentColor = _graphics.getColor();
171       int[] xPoints = new int[numberOfPoints];
172       int[] yPoints = new int[numberOfPoints];
173       for (int i = 0; i < numberOfPoints; i++) {
174         xPoints[i] = _t.transformX(polygon.getPoint(i).getX());
175         yPoints[i] = _t.transformY(polygon.getPoint(i).getY());
176       }
177       Color JavaDoc color = getFillColor(polygon);
178       if (color != null) {
179         _graphics.setColor(color);
180         _graphics.fillPolygon(xPoints, yPoints, numberOfPoints);
181       }
182       color = getLineColor(polygon);
183       if (color != null) {
184         _graphics.setColor(color);
185         if (polygon.isClosed()) {
186           _graphics.drawPolygon(xPoints, yPoints, numberOfPoints);
187         } else {
188           _graphics.drawPolyline(xPoints, yPoints, numberOfPoints);
189         }
190       }
191       _graphics.setColor(currentColor);
192     }
193   }
194
195   /**
196    * Paints the specified rectangle into the current <tt>Graphics</tt> context.
197    */

198   public void render(Rectangle rectangle) {
199     Color JavaDoc currentColor = _graphics.getColor();
200     GraphPoint center = rectangle.getCenter();
201     double width = rectangle.getWidth();
202     double height = rectangle.getHeight();
203     int x = _t.transformX(center.getX() - 0.5 * width);
204     int y = _t.transformY(center.getY() + 0.5 * height);
205     int w = _t.transformX(center.getX() + 0.5 * width) - x;
206     int h = _t.transformY(center.getY() - 0.5 * height) - y;
207
208     Color JavaDoc color = getFillColor(rectangle);
209     if (color != null) {
210       _graphics.setColor(color);
211       _graphics.fillRect(x, y, w, h);
212     }
213     color = getLineColor(rectangle);
214     if (color != null) {
215       _graphics.setColor(color);
216       _graphics.drawRect(x, y, w, h);
217     }
218     _graphics.setColor(currentColor);
219   }
220
221   /**
222    * Paints the specified oval into the current <tt>Graphics</tt> context.
223    */

224   public void render(Oval oval) {
225     Color JavaDoc currentColor = _graphics.getColor();
226     GraphPoint center = oval.getCenter();
227     double width = oval.getWidth();
228     double height = oval.getHeight();
229     int x = _t.transformX(center.getX() - 0.5 * width);
230     int y = _t.transformY(center.getY() + 0.5 * height);
231     int w = _t.transformX(center.getX() + 0.5 * width) - x;
232     int h = _t.transformY(center.getY() - 0.5 * height) - y;
233
234     Color JavaDoc color = getFillColor(oval);
235     if (color != null) {
236       _graphics.setColor(color);
237       _graphics.fillOval(x, y, w, h);
238     }
239     color = getLineColor(oval);
240     if (color != null) {
241       _graphics.setColor(color);
242       _graphics.drawOval(x, y, w, h);
243     }
244     _graphics.setColor(currentColor);
245   }
246
247   private Color JavaDoc getFillColor(BasicGraphicalElement element) {
248     Color JavaDoc result = null;
249     GraphicAttributes ga = element.getGraphicAttributes();
250     if (element.isClosed() && ga instanceof FillAttributes) {
251       result = ((FillAttributes) ga).getFillColor();
252     }
253     return result;
254   }
255
256   private Color JavaDoc getLineColor(BasicGraphicalElement element) {
257     Color JavaDoc result = _defaultColor;
258     GraphicAttributes ga = element.getGraphicAttributes();
259     if (ga instanceof LineAttributes) {
260       LineAttributes la = (LineAttributes) ga;
261       if (la.getLineColor() != null || getFillColor(element) != null) {
262         result = la.getLineColor();
263       }
264     }
265     return result;
266   }
267
268   /**
269    * Paints the specified text into the current <tt>Graphics</tt> context.
270    * <p>
271    * If the font size is zero the default font size will be used.
272    * <p>
273    * If the orientation angle is unequal zero the text will first be painted
274    * into an off-screen image and rotated. Finally, it will be drawn into the
275    * current <tt>Graphics</tt> context. Note, that only integer multiples of
276    * 90 degree rotation are performed. Other orientation angles will be
277    * adjusted to the nearest integer multiple of 90 degree.
278    */

279   public void render(Text text) {
280     final GraphicAttributes ga = text.getGraphicAttributes();
281     if (ga instanceof TextAttributes) {
282       final TextAttributes ta = (TextAttributes) ga;
283       final Color JavaDoc currentColor = _graphics.getColor();
284       final int orientation
285                   = ((int) (ta.getOrientationAngle() / 90 + 4.5)) % 4;
286       Color JavaDoc fontColor = ta.getTextColor();
287       if (fontColor == null) {
288         fontColor = _defaultColor;
289       }
290       _graphics.setColor(fontColor);
291       final Font JavaDoc font = createFont(ta, _t.transformHeight(ta.getFontSize()));
292       _graphics.setFont(font);
293       final String JavaDoc str = text.getText();
294       final FontMetrics JavaDoc metrics = _graphics.getFontMetrics();
295       final int ascent = metrics.getAscent();
296       final int descent = metrics.getDescent();
297       final int height = ascent + descent;
298       final int width = metrics.stringWidth(str);
299       final int xAnchor = ta.getHorizontalAnchor().getFactor();
300       final int yAnchor = ta.getVerticalAnchor().getFactor();
301       final int x = _t.transformX(text.getPosition().getX());
302       final int y = _t.transformY(text.getPosition().getY());
303       if (orientation == 0) {
304         _graphics.drawString(str, x - (width * xAnchor) / 2,
305                              y + (yAnchor * height) / 2 - descent);
306       } else {
307         Image JavaDoc textImage = makeImage(str, font, fontColor, orientation - 2,
308                                     ascent, width, height);
309         int xf = orientation == 2 ? xAnchor : yAnchor;
310         if (orientation != 3) {
311           xf = 2 - xf;
312         }
313         int yf = orientation == 2 ? yAnchor : xAnchor;
314         if (orientation == 1) {
315           yf = 2 - yf;
316         }
317         _graphics.drawImage(textImage, x - (xf * textImage.getWidth(null)) / 2,
318                             y - (yf * textImage.getHeight(null)) / 2, null);
319         textImage.flush();
320       }
321       _graphics.setColor(currentColor);
322     }
323   }
324
325   private Image JavaDoc makeImage(String JavaDoc text, Font JavaDoc font, Color JavaDoc color, int orientation,
326                           int ascent, int width, int height) {
327     int w = orientation == 0 ? width : height;
328     int h = orientation == 0 ? height : width;
329
330     // Draw text in mormal oriention into the buffer
331
Image JavaDoc img = _component.createImage(width, height);
332     Graphics JavaDoc g = img.getGraphics();
333     g.setColor(_component.getForeground());
334     g.setFont(font);
335     g.drawString(text, 0, ascent);
336
337     // Grab pixels from the buffer
338
int[] origPixels = new int[width * height];
339     try {
340       new PixelGrabber JavaDoc(img, 0, 0, width, height,
341                        origPixels, 0, width).grabPixels();
342     } catch (InterruptedException JavaDoc e) {}
343     int background = origPixels[0];
344
345     // Calculate rotation parameters
346
int o2 = orientation * orientation - 1;
347     int index = w * h * ((1 - orientation - o2) / 2) + w * orientation
348                 + (o2 - orientation - 1) / 2;
349     int dx = o2 + w * orientation;
350     int dy = o2 - (w * (h - 1) + 1) * orientation;
351
352     // rotated pixels
353
int[] pixels = new int[origPixels.length];
354     int fc = 0xff000000 | color.getRGB();
355     int lastCol = width - 1;
356     for (int i = 0; i < origPixels.length; i++) {
357       pixels[index] = (origPixels[i] == background) ? 0 : fc;
358       index += (i % width) == lastCol ? dy : dx;
359     }
360
361     // create rotated image
362
return _component.createImage(
363                 new MemoryImageSource JavaDoc(w, h, ColorModel.getRGBdefault(),
364                                       pixels, 0, w));
365   }
366 }
367
Free Books   Free Magazines  
Popular Tags