1
2 package org.freehep.graphics2d;
3
4 import java.awt.AlphaComposite;
5 import java.awt.BasicStroke;
6 import java.awt.Color;
7 import java.awt.Composite;
8 import java.awt.Font;
9 import java.awt.FontMetrics;
10 import java.awt.Graphics;
11 import java.awt.Graphics2D;
12 import java.awt.GraphicsConfiguration;
13 import java.awt.Image;
14 import java.awt.Paint;
15 import java.awt.Polygon;
16 import java.awt.Rectangle;
17 import java.awt.RenderingHints;
18 import java.awt.Shape;
19 import java.awt.Stroke;
20 import java.awt.Transparency;
21 import java.awt.font.FontRenderContext;
22 import java.awt.font.GlyphVector;
23 import java.awt.geom.AffineTransform;
24 import java.awt.geom.Rectangle2D;
25 import java.awt.image.BufferedImage;
26 import java.awt.image.BufferedImageOp;
27 import java.awt.image.ImageObserver;
28 import java.awt.image.RenderedImage;
29 import java.awt.image.renderable.RenderableImage;
30 import java.awt.print.PrinterGraphics;
31 import java.lang.reflect.InvocationTargetException;
32 import java.lang.reflect.Method;
33 import java.text.AttributedCharacterIterator;
34 import java.util.HashMap;
35 import java.util.Map;
36
37 import org.freehep.graphics2d.font.FontEncoder;
38
39
40
41
42
43
44 public class PixelGraphics2D extends AbstractVectorGraphics {
45
46 public final static RenderingHints.Key KEY_SYMBOL_BLIT = new SymbolBlitKey();
47
48 public final static Object VALUE_SYMBOL_BLIT_ON = Boolean.TRUE;
49
50 public final static Object VALUE_SYMBOL_BLIT_OFF = Boolean.FALSE;
51
52 static class SymbolBlitKey extends RenderingHints.Key {
53 public SymbolBlitKey() {
54 super(94025);
55 }
56
57 public boolean isCompatibleValue(Object o) {
58 if (o.equals(VALUE_SYMBOL_BLIT_ON))
59 return true;
60 if (o.equals(VALUE_SYMBOL_BLIT_OFF))
61 return true;
62 return false;
63 }
64
65 public String toString() {
66 return "Symbol Blitting enable key";
67 }
68 }
69
70
71 protected Graphics2D hostGraphics;
72
73 protected double lineWidth;
74
75 protected int resolution;
76
77
78 protected GenericTagHandler tagHandler;
79
80
81 private static final int MAX_BLIT_SIZE = 32;
82
83 private static Map
84
85 private WebColor webColor;
86
87
88 private static boolean displayX11;
89
90 private static boolean displayLocal;
91
92 static {
93 symbols = new HashMap();
94
95 displayX11 = false;
96 displayLocal = false;
97 try {
98 Class clazz = Class.forName("sun.awt.X11GraphicsEnvironment");
99 displayX11 = true;
100 Method method = clazz.getMethod("isDisplayLocal", null);
101 Boolean result = (Boolean) method.invoke(null, null);
102 displayLocal = result.booleanValue();
103 } catch (ClassNotFoundException e) {
104
105 displayLocal = true;
106 } catch (IllegalAccessException e) {
107
108 } catch (NoSuchMethodException e) {
109
110 } catch (InvocationTargetException e) {
111
112 } catch (ClassCastException e) {
113
114 } catch (SecurityException e) {
115
116 }
117 }
118
119 public PixelGraphics2D(Graphics graphics) {
120 this();
121 setHostGraphics(graphics);
122 }
123
124
125
126 protected PixelGraphics2D(PixelGraphics2D graphics) {
127 super(graphics);
128 setHostGraphics(graphics.hostGraphics.create());
129 }
130
131
132
133
134
135 protected PixelGraphics2D() {
136 super();
137 }
138
139 protected void setHostGraphics(Graphics graphics) {
140 hostGraphics = (Graphics2D) graphics;
141 resolution = (graphics instanceof PrinterGraphics) ? 0 : 1;
142 tagHandler = new GenericTagHandler(hostGraphics);
143
144 super.setBackground(hostGraphics.getBackground());
145 super.setColor(hostGraphics.getColor());
146 super.setPaint(hostGraphics.getPaint());
147 super.setFont(hostGraphics.getFont());
148
149 Stroke s = hostGraphics.getStroke();
150 if (s instanceof BasicStroke) {
151 lineWidth = ((BasicStroke) s).getLineWidth();
152 }
153 webColor = WebColor.create(getColor());
154 setRenderingHint(KEY_SYMBOL_BLIT, VALUE_SYMBOL_BLIT_ON);
155 }
156
157 public void startExport() {
158 }
159
160 public void endExport() {
161 }
162
163 public void printComment(String comment) {
164 }
165
166 public Graphics create(double x, double y, double width, double height) {
167 PixelGraphics2D graphics = new PixelGraphics2D(this);
168 graphics.translate(x, y);
169 graphics.clipRect(0, 0, width, height);
170 return graphics;
171 }
172
173
174
175
176
177
178
179 public void clearRect(int x, int y, int width, int height) {
180 hostGraphics.clearRect(x, y, width, height);
181 }
182
183 public void clipRect(int x, int y, int width, int height) {
184 hostGraphics.clipRect(x, y, width, height);
185 }
186
187 public void copyArea(int x, int y, int width, int height, int dx, int dy) {
188 hostGraphics.copyArea(x, y, width, height, dx, dy);
189 }
190
191 public Graphics create() {
192 return new PixelGraphics2D(this);
193 }
194
195 public void dispose() {
196 hostGraphics.dispose();
197 }
198
199 public void drawArc(int x, int y, int width, int height, int startAngle,
200 int arcAngle) {
201 hostGraphics.drawArc(x, y, width, height, startAngle, arcAngle);
202 }
203
204 public boolean drawImage(Image img, int x, int y, Color bgcolor,
205 ImageObserver observer) {
206 return hostGraphics.drawImage(img, x, y, getPrintColor(bgcolor),
207 observer);
208 }
209
210 public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
211 return hostGraphics.drawImage(img, x, y, observer);
212 }
213
214 public boolean drawImage(Image img, int x, int y, int width, int height,
215 Color bgcolor, ImageObserver observer) {
216 return hostGraphics.drawImage(img, x, y, width, height,
217 getPrintColor(bgcolor), observer);
218 }
219
220 public boolean drawImage(Image img, int x, int y, int width, int height,
221 ImageObserver observer) {
222 return hostGraphics.drawImage(img, x, y, width, height, observer);
223 }
224
225 public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
226 int sx1, int sy1, int sx2, int sy2, Color bgcolor,
227 ImageObserver observer) {
228 return hostGraphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2,
229 sy2, getPrintColor(bgcolor), observer);
230 }
231
232 public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
233 int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
234 return hostGraphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2,
235 sy2, observer);
236 }
237
238 public void drawLine(int x1, int y1, int x2, int y2) {
239 hostGraphics.drawLine(x1, y1, x2, y2);
240 }
241
242 public void drawOval(int x, int y, int width, int height) {
243 hostGraphics.drawOval(x, y, width, height);
244 }
245
246 public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
247 hostGraphics.drawPolygon(xPoints, yPoints, nPoints);
248 }
249
250 public void drawPolygon(Polygon p) {
251 hostGraphics.drawPolygon(p);
252 }
253
254 public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
255 hostGraphics.drawPolyline(xPoints, yPoints, nPoints);
256 }
257
258 public void drawRect(int x, int y, int width, int height) {
259 hostGraphics.drawRect(x, y, width, height);
260 }
261
262 public void drawString(String str, int x, int y) {
263 str = FontEncoder.getEncodedString(str, getFont().getName());
264 hostGraphics.drawString(str, x, y);
265 }
266
267 public void fillArc(int x, int y, int width, int height, int startAngle,
268 int arcAngle) {
269 hostGraphics.fillArc(x, y, width, height, startAngle, arcAngle);
270 }
271
272 public void fillOval(int x, int y, int width, int height) {
273 hostGraphics.fillOval(x, y, width, height);
274 }
275
276 public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
277 hostGraphics.fillPolygon(xPoints, yPoints, nPoints);
278 }
279
280 public void fillPolygon(Polygon p) {
281 hostGraphics.fillPolygon(p);
282 }
283
284 public void fillRect(int x, int y, int width, int height) {
285 hostGraphics.fillRect(x, y, width, height);
286 }
287
288 public void drawSymbol(double x, double y, double size, int symbol) {
289 if (size <= 0)
290 return;
291
292 int intSize = (int) Math.ceil(size);
293 if ((intSize > MAX_BLIT_SIZE)
294 || (lineWidth != 1.0)
295 || !isDisplayLocal()
296 || (getRenderingHint(RenderingHints.KEY_ANTIALIASING) == RenderingHints.VALUE_ANTIALIAS_ON)
297 || (getRenderingHint(KEY_SYMBOL_BLIT) == VALUE_SYMBOL_BLIT_OFF)) {
298 super.drawSymbol(x, y, size, symbol);
299 return;
300 }
301
302 blitSymbol(x, y, intSize, symbol, false);
303 }
304
305 public void fillSymbol(double x, double y, double size, int symbol) {
306 if (size <= 0)
307 return;
308
309 int intSize = (int) Math.ceil(size);
310 if ((intSize > MAX_BLIT_SIZE)
311 || (lineWidth != 1.0)
312 || !isDisplayLocal()
313 || (getRenderingHint(RenderingHints.KEY_ANTIALIASING) == RenderingHints.VALUE_ANTIALIAS_ON)
314 || (getRenderingHint(KEY_SYMBOL_BLIT) == VALUE_SYMBOL_BLIT_OFF)) {
315 super.fillSymbol(x, y, size, symbol);
316 return;
317 }
318
319 blitSymbol(x, y, intSize, symbol, true);
320 }
321
322
323 public void fillAndDrawSymbol(double x, double y, double size, int symbol,
324 Color fillColor) {
325 Color color = getColor();
326 setColor(fillColor);
327 super.fillSymbol(x, y, size, symbol);
328 setColor(color);
329 super.drawSymbol(x, y, size, symbol);
330 }
331
332 private void blitSymbol(double x, double y, int size, int symbol,
333 boolean fill) {
334 Image[][][] images = (Image[][][]) symbols.get(webColor);
335 if (images == null) {
336 images = new Image[2][NUMBER_OF_SYMBOLS][MAX_BLIT_SIZE];
337 symbols.put(webColor, images);
338 }
339
340 Image image = images[fill ? 1 : 0][symbol][size - 1];
341 int imageSize = size + 1;
342 double imageSize2 = imageSize / 2.0;
343 if (image == null) {
344 image = getDeviceConfiguration().createCompatibleImage(
345 imageSize + 1, imageSize + 1, Transparency.BITMASK);
346 VectorGraphics imageGraphics = VectorGraphics.create(image
347 .getGraphics());
348 Composite composite = imageGraphics.getComposite();
349 imageGraphics.setComposite(AlphaComposite.Clear);
350 imageGraphics.fillRect(0, 0, size, size);
351 imageGraphics.setComposite(composite);
352 imageGraphics.setColor(getColor());
353 if (fill) {
354 fillSymbol(imageGraphics, imageSize2, imageSize2, size, symbol);
355 } else {
356 drawSymbol(imageGraphics, imageSize2, imageSize2, size, symbol);
357 }
358 images[fill ? 1 : 0][symbol][size - 1] = image;
359 }
360 drawImage(image, (int) (x - imageSize2), (int) (y - imageSize2), null);
361 }
362
363 public void setLineWidth(double width) {
364 super.setLineWidth(width);
365 lineWidth = width;
366 }
367
368 public Shape getClip() {
369 return hostGraphics.getClip();
370 }
371
372 public Rectangle getClipBounds() {
373 return hostGraphics.getClipBounds();
374 }
375
376 public Rectangle getClipBounds(Rectangle r) {
377 return hostGraphics.getClipBounds(r);
378 }
379
380 public FontMetrics getFontMetrics(Font f) {
381 return hostGraphics.getFontMetrics(f);
382 }
383
384 public void setClip(int x, int y, int width, int height) {
385 hostGraphics.setClip(x, y, width, height);
386 }
387
388 public void setClip(Shape clip) {
389 hostGraphics.setClip(clip);
390 }
391
392 public void setFont(Font font) {
393 if (font == null) return;
394
395 super.setFont(font);
396 if (font.getName().equals("Symbol")
397 || font.getName().equals("ZapfDingbats")) {
398 Font newFont = new Font("Serif", font.getSize(), font.getStyle());
399 font = newFont.deriveFont(font.getSize2D());
400 }
401 hostGraphics.setFont(font);
402 }
403
404 public void setColor(Color color) {
405 if (color == null) return;
406
407 if (color.equals(getColor()))
408 return;
409
410 super.setColor(color);
411 hostGraphics.setColor(getPrintColor(color));
412 webColor = WebColor.create(color);
413 }
414
415 public void setPaint(Paint paint) {
416 if (paint == null) return;
417
418 if (paint.equals(getPaint()))
419 return;
420
421 if (paint instanceof Color) {
422 setColor((Color) paint);
423 } else {
424 super.setPaint(paint);
425 hostGraphics.setPaint(paint);
426 }
427 }
428
429 public void setPaintMode() {
430 hostGraphics.setPaintMode();
431 }
432
433 public void setXORMode(Color c1) {
434 hostGraphics.setXORMode(getPrintColor(c1));
435 }
436
437 public void translate(int x, int y) {
438 hostGraphics.translate(x, y);
439 }
440
441
442
443
444
445
446
447 public void addRenderingHints(Map hints) {
448 hostGraphics.addRenderingHints(hints);
449 }
450
451 public void clip(Shape clip) {
452 hostGraphics.clip(clip);
453 }
454
455 public void draw(Shape s) {
456 hostGraphics.draw(s);
457 }
458
459 public void drawGlyphVector(GlyphVector g, float x, float y) {
460 hostGraphics.drawGlyphVector(g, x, y);
461 }
462
463 public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) {
464 hostGraphics.drawImage(img, op, x, y);
465 }
466
467 public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {
468 return hostGraphics.drawImage(img, xform, obs);
469 }
470
471 public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
472 hostGraphics.drawRenderableImage(img, xform);
473 }
474
475 public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
476 hostGraphics.drawRenderedImage(img, xform);
477 }
478
479 public void drawString(AttributedCharacterIterator iterator, float x,
480 float y) {
481 hostGraphics.drawString(iterator, x, y);
482 }
483
484 public void drawString(AttributedCharacterIterator iterator, int x, int y) {
485 hostGraphics.drawString(iterator, x, y);
486 }
487
488 public void drawString(String str, float x, float y) {
489 str = FontEncoder.getEncodedString(str, getFont().getName());
490 hostGraphics.drawString(str, x, y);
491 }
492
493 public void fill(Shape s) {
494 hostGraphics.fill(s);
495 }
496
497 public Composite getComposite() {
498 return hostGraphics.getComposite();
499 }
500
501 public GraphicsConfiguration getDeviceConfiguration() {
502 return hostGraphics.getDeviceConfiguration();
503 }
504
505 public FontRenderContext getFontRenderContext() {
506 return hostGraphics.getFontRenderContext();
507 }
508
509 public Object getRenderingHint(RenderingHints.Key hintKey) {
510 return hostGraphics.getRenderingHint(hintKey);
511 }
512
513 public RenderingHints getRenderingHints() {
514 return hostGraphics.getRenderingHints();
515 }
516
517 public Stroke getStroke() {
518 return hostGraphics.getStroke();
519 }
520
521 public AffineTransform getTransform() {
522 return hostGraphics.getTransform();
523 }
524
525 public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
526 return hostGraphics.hit(rect, s, onStroke);
527 }
528
529 public void rotate(double theta) {
530 hostGraphics.rotate(theta);
531 }
532
533 public void rotate(double theta, double x, double y) {
534 hostGraphics.rotate(theta, x, y);
535 }
536
537 public void scale(double sx, double sy) {
538 hostGraphics.scale(sx, sy);
539 }
540
541 public void setBackground(Color color) {
542 super.setBackground(color);
543 hostGraphics.setBackground(getPrintColor(color));
544 }
545
546 public void setComposite(Composite comp) {
547 hostGraphics.setComposite(comp);
548 }
549
550 public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue) {
551 hostGraphics.setRenderingHint(hintKey, hintValue);
552 }
553
554 public void setRenderingHints(Map hints) {
555 hostGraphics.setRenderingHints(hints);
556 }
557
558 public void setStroke(Stroke s) {
559 hostGraphics.setStroke(s);
560 }
561
562 public void setTransform(AffineTransform Tx) {
563 hostGraphics.setTransform(Tx);
564 }
565
566 public void shear(double shx, double shy) {
567 hostGraphics.shear(shx, shy);
568 }
569
570 public void transform(AffineTransform Tx) {
571 hostGraphics.transform(Tx);
572 }
573
574 public void translate(double tx, double ty) {
575 hostGraphics.translate(tx, ty);
576 }
577
578
579
580
581
582
583
584 public void clearRect(double x, double y, double width, double height) {
585 clearRect((int) x, (int) y, (int) width, (int) height);
586 }
587
588 public void clipRect(double x, double y, double width, double height) {
589 clipRect((int) x, (int) y, (int) width, (int) height);
590 }
591
592 public void drawString(String str, double x, double y) {
593 drawString(str, (int) Math.round(x), (int) Math.round(y));
594 }
595
596 public void setClip(double x, double y, double width, double height) {
597 setClip(new Rectangle2D.Double(x, y, width, height));
598 }
599
600 public String toString() {
601 return "PixelGraphics2D[" + hostGraphics.toString() + "]";
602 }
603
604 public static boolean isDisplayX11() {
605 return displayX11;
606 }
607
608 public static boolean isDisplayLocal() {
609 return displayLocal;
610 }
611
612
613
614
615
616 protected Shape createShape(double[] xPoints, double[] yPoints,
617 int nPoints, boolean close) {
618 return new ArrayPath(xPoints, yPoints, nPoints, close, resolution);
619 }
620
621
622
623
624
625
626
627
628
629
630
631
632
633 }