1
2 package org.freehep.graphicsio;
3
4 import java.awt.AlphaComposite;
5 import java.awt.BasicStroke;
6 import java.awt.Color;
7 import java.awt.Component;
8 import java.awt.Composite;
9 import java.awt.Dimension;
10 import java.awt.Font;
11 import java.awt.FontMetrics;
12 import java.awt.GradientPaint;
13 import java.awt.GraphicsConfiguration;
14 import java.awt.Image;
15 import java.awt.MediaTracker;
16 import java.awt.Paint;
17 import java.awt.Panel;
18 import java.awt.Rectangle;
19 import java.awt.RenderingHints;
20 import java.awt.Shape;
21 import java.awt.Stroke;
22 import java.awt.TexturePaint;
23 import java.awt.Toolkit;
24 import java.awt.font.FontRenderContext;
25 import java.awt.font.GlyphVector;
26 import java.awt.font.TextLayout;
27 import java.awt.geom.AffineTransform;
28 import java.awt.geom.Area;
29 import java.awt.geom.GeneralPath;
30 import java.awt.geom.NoninvertibleTransformException;
31 import java.awt.geom.Rectangle2D;
32 import java.awt.image.BufferedImage;
33 import java.awt.image.BufferedImageOp;
34 import java.awt.image.CropImageFilter;
35 import java.awt.image.FilteredImageSource;
36 import java.awt.image.ImageFilter;
37 import java.awt.image.ImageObserver;
38 import java.awt.image.RenderedImage;
39 import java.awt.image.renderable.RenderContext;
40 import java.awt.image.renderable.RenderableImage;
41 import java.io.IOException;
42 import java.text.AttributedCharacterIterator;
43 import java.util.Arrays;
44 import java.util.Map;
45
46 import org.freehep.graphics2d.font.FontEncoder;
47 import org.freehep.graphics2d.font.FontUtilities;
48 import org.freehep.util.images.ImageUtilities;
49
50
51
52
53
54
55
56
57
58
59 public abstract class AbstractVectorGraphicsIO extends VectorGraphicsIO {
60
61 private static final String rootKey = AbstractVectorGraphicsIO.class
62 .getName();
63
64 public static final String EMIT_WARNINGS = rootKey + ".EMIT_WARNINGS";
65
66 public static final String TEXT_AS_SHAPES = rootKey + "." + FontConstants.TEXT_AS_SHAPES;
67
68 public static final String EMIT_ERRORS = rootKey + ".EMIT_ERRORS";
69
70 public static final String CLIP = rootKey+".CLIP";
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 private Dimension size;
86
87 private Component component;
88
89 private boolean doRestoreOnDispose;
90
91 private Rectangle deviceClip;
92
93
94
95
96 private Area userClip;
97
98 private AffineTransform currentTransform;
99
100
101 private AffineTransform oldTransform = new AffineTransform();
102
103 private Composite currentComposite;
104
105 private Stroke currentStroke;
106
107 private RenderingHints hints;
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131 protected AbstractVectorGraphicsIO(Dimension size,
132 boolean doRestoreOnDispose) {
133 super();
134
135 this.size = size;
136 this.component = null;
137 this.doRestoreOnDispose = doRestoreOnDispose;
138
139 deviceClip = (size != null ? new Rectangle(0, 0, size.width,
140 size.height) : null);
141 userClip = null;
142 currentTransform = new AffineTransform();
143 currentComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
144 currentStroke = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE,
145 BasicStroke.JOIN_MITER, 10.0f, null, 0.0f);
146
147 super.setColor(Color.BLACK);
148 super.setBackground(Color.BLACK);
149 super.setFont(new Font("Dialog", Font.PLAIN, 12));
150
151
152 hints = new RenderingHints(null);
153 }
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 protected AbstractVectorGraphicsIO(Component component,
175 boolean doRestoreOnDispose) {
176 super();
177
178 this.size = component.getSize();
179 this.component = component;
180 this.doRestoreOnDispose = doRestoreOnDispose;
181
182 deviceClip = (size != null ? new Rectangle(0, 0, size.width,
183 size.height) : null);
184 userClip = null;
185 GraphicsConfiguration gc = component.getGraphicsConfiguration();
186 currentTransform = (gc != null) ? gc.getDefaultTransform()
187 : new AffineTransform();
188 currentComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
189 currentStroke = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE,
190 BasicStroke.JOIN_MITER, 10.0f, null, 0.0f);
191
192 super.setFont(component.getFont());
193 super.setBackground(component.getBackground());
194 super.setColor(component.getForeground());
195
196
197 hints = new RenderingHints(null);
198 }
199
200
201
202
203
204
205
206
207 protected AbstractVectorGraphicsIO(AbstractVectorGraphicsIO graphics,
208 boolean doRestoreOnDispose) {
209 super(graphics);
210 this.doRestoreOnDispose = doRestoreOnDispose;
211
212 size = new Dimension(graphics.size);
213 component = graphics.component;
214
215 deviceClip = new Rectangle(graphics.deviceClip);
216 userClip = (graphics.userClip != null) ? new Area(graphics.userClip)
217 : null;
218 currentTransform = new AffineTransform(graphics.currentTransform);
219 currentComposite = graphics.currentComposite;
220 currentStroke = graphics.currentStroke;
221 hints = graphics.hints;
222 }
223
224
225
226
227
228
229 public Dimension getSize() {
230 return size;
231 }
232
233 public Component getComponent() {
234 return component;
235 }
236
237
238
239
240
241
242
243 public void startExport() {
244 try {
245 writeHeader();
246
247
248 if (!(this instanceof MultiPageDocument)) {
249 writeGraphicsState();
250 writeBackground();
251 }
252 } catch (IOException e) {
253 handleException(e);
254 }
255 }
256
257 public void endExport() {
258 try {
259 dispose();
260 writeTrailer();
261 closeStream();
262 } catch (IOException e) {
263 handleException(e);
264 }
265 }
266
267
268
269
270 public abstract void writeHeader() throws IOException;
271
272
273
274
275 public void writeGraphicsState() throws IOException {
276 writePaint(getPrintColor(getColor()));
277
278 writeSetTransform(getTransform());
279
280
281
282 setClip(getClip());
283
284
285
286
287
288
289
290 }
291
292 public abstract void writeBackground() throws IOException;
293
294
295
296
297 public abstract void writeTrailer() throws IOException;
298
299
300
301
302 public abstract void closeStream() throws IOException;
303
304 public void printComment(String comment) {
305 try {
306 writeComment(comment);
307 } catch (IOException e) {
308 handleException(e);
309 }
310 }
311
312
313
314
315
316
317 public abstract void writeComment(String comment) throws IOException;
318
319
320 protected void resetClip(Rectangle clip) {
321 deviceClip = clip;
322 userClip = null;
323 }
324
325
326
327
328
329
330
331
332
333
334 public void dispose() {
335 try {
336
337
338
339 if (doRestoreOnDispose) {
340 writeGraphicsRestore();
341 doRestoreOnDispose = false;
342 }
343 } catch (IOException e) {
344 handleException(e);
345 }
346 }
347
348
349
350
351
352
353 protected abstract void writeGraphicsSave() throws IOException;
354
355
356
357
358
359 protected abstract void writeGraphicsRestore() throws IOException;
360
361
362
363
364
365
366
367
368 public boolean drawImage(Image image, int x, int y, ImageObserver observer) {
369 int imageWidth = image.getWidth(observer);
370 int imageHeight = image.getHeight(observer);
371 return drawImage(image, x, y, x + imageWidth, y + imageHeight, 0, 0,
372 imageWidth, imageHeight, null, observer);
373 }
374
375 public boolean drawImage(Image image, int x, int y, int width, int height,
376 ImageObserver observer) {
377 int imageWidth = image.getWidth(observer);
378 int imageHeight = image.getHeight(observer);
379 return drawImage(image, x, y, x + width, y + height, 0, 0, imageWidth,
380 imageHeight, null, observer);
381 }
382
383 public boolean drawImage(Image image, int x, int y, int width, int height,
384 Color bgColor, ImageObserver observer) {
385 int imageWidth = image.getWidth(observer);
386 int imageHeight = image.getHeight(observer);
387 return drawImage(image, x, y, x + width, y + height, 0, 0, imageWidth,
388 imageHeight, bgColor, observer);
389 }
390
391 public boolean drawImage(Image image, int x, int y, Color bgColor,
392 ImageObserver observer) {
393 int imageWidth = image.getWidth(observer);
394 int imageHeight = image.getHeight(observer);
395 return drawImage(image, x, y, x + imageWidth, y + imageHeight, 0, 0,
396 imageWidth, imageHeight, bgColor, observer);
397 }
398
399 public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
400 int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
401 return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null,
402 observer);
403 }
404
405 public boolean drawImage(Image image, AffineTransform xform,
406 ImageObserver observer) {
407 drawRenderedImage(ImageUtilities.createRenderedImage(image, observer,
408 null), xform);
409 return true;
410 }
411
412 public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) {
413 drawImage(op.filter(img, null), x, y, null);
414 }
415
416
417 public void drawRenderableImage(RenderableImage image, AffineTransform xform) {
418 drawRenderedImage(image.createRendering(new RenderContext(
419 new AffineTransform(), getRenderingHints())), xform);
420 }
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438 public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
439 int sx1, int sy1, int sx2, int sy2, Color bgColor,
440 ImageObserver observer) {
441 try {
442 int srcX = Math.min(sx1, sx2);
443 int srcY = Math.min(sy1, sy2);
444 int srcWidth = Math.abs(sx2 - sx1);
445 int srcHeight = Math.abs(sy2 - sy1);
446 int width = Math.abs(dx2 - dx1);
447 int height = Math.abs(dy2 - dy1);
448
449 if ((srcX != 0) || (srcY != 0)
450 || (srcWidth != image.getWidth(observer))
451 || (srcHeight != image.getHeight(observer))) {
452
453 ImageFilter crop = new CropImageFilter(srcX, srcY, srcWidth,
454 srcHeight);
455 image = Toolkit.getDefaultToolkit().createImage(
456 new FilteredImageSource(image.getSource(), crop));
457 MediaTracker mediaTracker = new MediaTracker(new Panel());
458 mediaTracker.addImage(image, 0);
459 try {
460 mediaTracker.waitForAll();
461 } catch (InterruptedException e) {
462 handleException(e);
463 }
464 }
465
466 boolean flipHorizontal = (dx2 < dx1) ^ (sx2 < sx1);
467
468
469
470 boolean flipVertical = (dy2 < dy1) ^ (sy2 < sy1);
471
472
473
474 double tx = (flipHorizontal) ? (double) dx2 : (double) dx1;
475 double ty = (flipVertical) ? (double) dy2 : (double) dy1;
476
477 double sx = (double) width / srcWidth;
478 sx = flipHorizontal ? -1 * sx : sx;
479 double sy = (double) height / srcHeight;
480 sy = flipVertical ? -1 * sy : sy;
481
482 writeImage(ImageUtilities.createRenderedImage(image, observer,
483 bgColor), new AffineTransform(sx, 0, 0, sy, tx, ty),
484 bgColor);
485 return true;
486 } catch (IOException e) {
487 handleException(e);
488 return false;
489 }
490 }
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523 public void drawRenderedImage(RenderedImage image, AffineTransform xform) {
524 try {
525 writeImage(image, xform, null);
526 } catch (Exception e) {
527 handleException(e);
528 }
529 }
530
531 protected abstract void writeImage(RenderedImage image,
532 AffineTransform xform, Color bkg) throws IOException;
533
534
535
536
537
538
539
540
541
542 public void clearRect(double x, double y, double width, double height) {
543 Paint temp = getPaint();
544 setPaint(getBackground());
545 fillRect(x, y, width, height);
546 setPaint(temp);
547 }
548
549
550
551
552
553
554
555
556
557
558 public void drawString(String string, double x, double y) {
559
560 if (string == null || string.equals("")) {
561 return;
562 }
563
564
565 if (isProperty(TEXT_AS_SHAPES)) {
566
567 Font font = getFont();
568
569
570
571 String fontName = font.getName();
572 if (fontName.equals("Symbol") || fontName.equals("ZapfDingbats")) {
573 string = FontEncoder.getEncodedString(string, fontName);
574
575 font = new Font("Serif", font.getStyle(), font.getSize());
576 }
577
578
579 GlyphVector gv = font.createGlyphVector(getFontRenderContext(), string);
580
581
582 drawGlyphVector(gv, (float) x, (float) y);
583 } else {
584
585 try {
586 writeString(string, x, y);
587 } catch (IOException e) {
588 handleException(e);
589 }
590 }
591 }
592
593 protected abstract void writeString(String string, double x, double y)
594 throws IOException;
595
596
597
598
599
600
601
602
603 public void drawGlyphVector(GlyphVector g, float x, float y) {
604 fill(g.getOutline(x, y));
605 }
606
607 public void drawString(AttributedCharacterIterator iterator, float x,
608 float y) {
609
610
611
612
613 if (isProperty(TEXT_AS_SHAPES)) {
614
615 TextLayout tl = new TextLayout(iterator, getFontRenderContext());
616 tl.draw(this, x, y);
617 } else {
618
619 Font font = getFont();
620
621
622
623
624 Map
625
626
627
628
629 StringBuffer sb = new StringBuffer();
630
631 for (char c = iterator.first();
632 c != AttributedCharacterIterator.DONE;
633 c = iterator.next()) {
634
635
636 if (attributes.equals(iterator.getAttributes())) {
637 sb.append(c);
638
639 } else {
640
641 if (sb.length() > 0) {
642
643 drawString(sb.toString(), x, y);
644
645
646
647 TextLayout tl = new TextLayout(
648 sb.toString(),
649 attributes,
650 getFontRenderContext());
651
652
653 x = x + Math.max(
654 tl.getAdvance(),
655 (float)tl.getBounds().getWidth());
656 }
657
658
659 sb = new StringBuffer();
660 sb.append(c);
661
662
663 attributes = iterator.getAttributes();
664 setFont(new Font(attributes));
665 }
666 }
667
668
669 if (sb.length() > 0) {
670 drawString(sb.toString(), x, y);
671 }
672
673
674 setFont(font);
675 }
676 }
677
678
679
680
681
682
683
684
685
686
687
688 public AffineTransform getTransform() {
689 return new AffineTransform(currentTransform);
690 }
691
692
693
694
695
696
697 public void setTransform(AffineTransform transform) {
698
699 oldTransform.setTransform(currentTransform);
700 currentTransform.setTransform(transform);
701 try {
702 writeSetTransform(transform);
703 } catch (IOException e) {
704 handleException(e);
705 }
706 }
707
708
709
710
711
712
713 public void transform(AffineTransform transform) {
714 currentTransform.concatenate(transform);
715 try {
716 writeTransform(transform);
717 } catch (IOException e) {
718 handleException(e);
719 }
720 }
721
722
723
724
725
726
727
728 public void translate(double x, double y) {
729 currentTransform.translate(x, y);
730 try {
731 writeTransform(new AffineTransform(1, 0, 0, 1, x, y));
732 } catch (IOException e) {
733 handleException(e);
734 }
735 }
736
737
738
739
740
741
742
743
744 public void rotate(double theta) {
745 currentTransform.rotate(theta);
746 try {
747 writeTransform(new AffineTransform(Math.cos(theta),
748 Math.sin(theta), -Math.sin(theta), Math.cos(theta), 0, 0));
749 } catch (IOException e) {
750 handleException(e);
751 }
752 }
753
754
755
756
757
758
759
760 public void scale(double sx, double sy) {
761 currentTransform.scale(sx, sy);
762 try {
763 writeTransform(new AffineTransform(sx, 0, 0, sy, 0, 0));
764 } catch (IOException e) {
765 handleException(e);
766 }
767 }
768
769
770
771
772
773
774
775 public void shear(double shx, double shy) {
776 currentTransform.shear(shx, shy);
777 try {
778 writeTransform(new AffineTransform(1, shy, shx, 1, 0, 0));
779 } catch (IOException e) {
780 handleException(e);
781 }
782 }
783
784
785
786
787
788
789
790
791
792
793 protected abstract void writeTransform(AffineTransform transform)
794 throws IOException;
795
796
797
798
799
800
801
802
803 protected void writeSetTransform(AffineTransform transform) throws IOException {
804 try {
805 AffineTransform deltaTransform = new AffineTransform(transform);
806 deltaTransform.concatenate(oldTransform.createInverse());
807 writeTransform(deltaTransform);
808 } catch (NoninvertibleTransformException e) {
809
810 System.err.println("Warning: (ignored) Could not invert matrix: "+oldTransform);
811 }
812 }
813
814
815
816
817
818
819
820
821
822
823
824
825 public Shape getClip() {
826 return (userClip != null) ? new Area(untransformShape(userClip)) : null;
827 }
828
829
830
831
832
833
834 public Rectangle getClipBounds() {
835 Shape clip = getClip();
836 return (clip != null) ? getClip().getBounds() : null;
837 }
838
839
840
841
842
843
844 public Rectangle getClipBounds(Rectangle r) {
845 Rectangle bounds = getClipBounds();
846 if (bounds != null)
847 r.setBounds(bounds);
848 return r;
849 }
850
851
852
853
854
855
856
857
858
859 public void clipRect(int x, int y, int width, int height) {
860 clip(new Rectangle(x, y, width, height));
861 }
862
863
864
865
866
867
868
869
870
871 public void clipRect(double x, double y, double width, double height) {
872 clip(new Rectangle2D.Double(x, y, width, height));
873 }
874
875
876
877
878
879
880
881
882
883 public void setClip(int x, int y, int width, int height) {
884 setClip(new Rectangle(x, y, width, height));
885 }
886
887
888
889
890
891
892
893
894
895 public void setClip(double x, double y, double width, double height) {
896 setClip(new Rectangle2D.Double(x, y, width, height));
897 }
898
899
900
901
902
903
904 public void setClip(Shape s) {
905
906 Shape ts = transformShape(s);
907 userClip = (ts != null) ? new Area(ts) : null;
908
909 try {
910 writeSetClip(s);
911 } catch (IOException e) {
912 handleException(e);
913 }
914 }
915
916
917
918
919
920
921
922 public void clip(Shape s) {
923 Shape ts = transformShape(s);
924 if (userClip != null) {
925 if (ts != null) {
926 userClip.intersect(new Area(ts));
927 } else {
928 userClip = null;
929 }
930 } else {
931 userClip = (ts != null) ? new Area(ts) : null;
932 }
933
934 try {
935 writeClip(s);
936 } catch (IOException e) {
937 handleException(e);
938 }
939 }
940
941
942
943
944
945
946 protected abstract void writeClip(Shape shape) throws IOException;
947
948
949
950
951
952
953 protected abstract void writeSetClip(Shape shape) throws IOException;
954
955
956
957
958
959
960
961
962
963
964
965
966 public Stroke getStroke() {
967 return currentStroke;
968 }
969
970
971
972
973
974
975
976 public void setStroke(Stroke stroke) {
977 if (stroke.equals(currentStroke)) {
978 return;
979 }
980 try {
981 writeStroke(stroke);
982 } catch (IOException e) {
983 handleException(e);
984 }
985 currentStroke = stroke;
986 }
987
988
989
990
991
992
993 protected void writeStroke(Stroke stroke) throws IOException {
994 if (stroke instanceof BasicStroke) {
995 BasicStroke ns = (BasicStroke) stroke;
996
997
998
999 int currentCap = -1, currentJoin = -1;
1000 float currentWidth = -1, currentLimit = -1, currentDashPhase = -1;
1001 float[] currentDashArray = null;
1002 if ((currentStroke != null)
1003 && (currentStroke instanceof BasicStroke)) {
1004 BasicStroke cs = (BasicStroke) currentStroke;
1005 currentCap = cs.getEndCap();
1006 currentJoin = cs.getLineJoin();
1007 currentWidth = cs.getLineWidth();
1008 currentLimit = cs.getMiterLimit();
1009 currentDashArray = cs.getDashArray();
1010 currentDashPhase = cs.getDashPhase();
1011 }
1012
1013
1014 float width = ns.getLineWidth();
1015 if (currentWidth != width) {
1016 writeWidth(width);
1017 }
1018
1019
1020 int cap = ns.getEndCap();
1021 if (currentCap != cap) {
1022 writeCap(cap);
1023 }
1024
1025
1026 int join = ns.getLineJoin();
1027 if (currentJoin != join) {
1028 writeJoin(join);
1029 }
1030
1031
1032 float limit = ns.getMiterLimit();
1033 if ((currentLimit != limit) && (limit >= 1.0f)) {
1034 writeMiterLimit(limit);
1035 }
1036
1037
1038 if(!Arrays.equals(currentDashArray, ns.getDashArray()) ||
1039 (currentDashPhase != ns.getDashPhase())) {
1040
1041
1042 if (ns.getDashArray() != null) {
1043 writeDash(ns.getDashArray(), ns.getDashPhase());
1044 } else {
1045 writeDash(new float[0], ns.getDashPhase());
1046 }
1047 }
1048 }
1049 }
1050
1051
1052
1053
1054
1055
1056 protected void writeWidth(float width) throws IOException {
1057 writeWarning(getClass() + ": writeWidth() not implemented.");
1058 }
1059
1060
1061
1062
1063
1064
1065 protected void writeCap(int cap) throws IOException {
1066 writeWarning(getClass() + ": writeCap() not implemented.");
1067 }
1068
1069
1070
1071
1072
1073
1074 protected void writeJoin(int join) throws IOException {
1075 writeWarning(getClass() + ": writeJoin() not implemented.");
1076 }
1077
1078
1079
1080
1081
1082
1083 protected void writeMiterLimit(float limit) throws IOException {
1084 writeWarning(getClass() + ": writeMiterLimit() not implemented.");
1085 }
1086
1087
1088
1089
1090
1091
1092
1093 protected void writeDash(float[] dash, float phase) throws IOException {
1094
1095 double[] dd = new double[dash.length];
1096 for (int i = 0; i < dash.length; i++) {
1097 dd[i] = dash[i];
1098 }
1099 writeDash(dd, (double)phase);
1100 }
1101
1102
1103
1104
1105
1106
1107
1108
1109 protected void writeDash(double[] dash, double phase) throws IOException {
1110 writeWarning(getClass() + ": writeDash() not implemented.");
1111 }
1112
1113
1114 public void setColor(Color color) {
1115 if (color == null) return;
1116
1117 if (color.equals(getColor()))
1118 return;
1119
1120 try {
1121 super.setColor(color);
1122 writePaint(getPrintColor(color));
1123 } catch (IOException e) {
1124 handleException(e);
1125 }
1126 }
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136 public void setPaint(Paint paint) {
1137 if (paint == null) return;
1138
1139 if (paint.equals(getPaint()))
1140 return;
1141
1142 try {
1143 if (paint instanceof Color) {
1144 setColor((Color) paint);
1145 } else if (paint instanceof GradientPaint) {
1146 super.setPaint(paint);
1147 writePaint((GradientPaint) paint);
1148 } else if (paint instanceof TexturePaint) {
1149 super.setPaint(paint);
1150 writePaint((TexturePaint) paint);
1151 } else {
1152 super.setPaint(paint);
1153 writePaint(paint);
1154 }
1155 } catch (IOException e) {
1156 handleException(e);
1157 }
1158 }
1159
1160
1161
1162
1163
1164
1165 protected abstract void writePaint(Color color) throws IOException;
1166
1167
1168
1169
1170
1171
1172 protected abstract void writePaint(GradientPaint paint) throws IOException;
1173
1174
1175
1176
1177
1178
1179 protected abstract void writePaint(TexturePaint paint) throws IOException;
1180
1181
1182
1183
1184
1185
1186 protected abstract void writePaint(Paint paint) throws IOException;
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196 public FontRenderContext getFontRenderContext() {
1197
1198
1199 return new FontRenderContext(new AffineTransform(1, 0, 0, 1, 0, 0),
1200 true, true);
1201 }
1202
1203
1204
1205
1206
1207
1208
1209
1210 public FontMetrics getFontMetrics(Font font) {
1211 return Toolkit.getDefaultToolkit().getFontMetrics(font);
1212 }
1213
1214
1215
1216
1217
1218
1219
1220 public RenderingHints getRenderingHints() {
1221 return (RenderingHints) hints.clone();
1222 }
1223
1224
1225
1226
1227
1228
1229 public void addRenderingHints(Map hints) {
1230 hints.putAll(hints);
1231 }
1232
1233
1234
1235
1236
1237
1238 public void setRenderingHints(Map hints) {
1239 hints.clear();
1240 hints.putAll(hints);
1241 }
1242
1243
1244
1245
1246
1247
1248
1249 public Object getRenderingHint(RenderingHints.Key key) {
1250 return hints.get(key);
1251 }
1252
1253
1254
1255
1256
1257
1258
1259 public void setRenderingHint(RenderingHints.Key key, Object hint) {
1260
1261 if ((key == null) || (hint == null))
1262 return;
1263 hints.put(key, hint);
1264 }
1265
1266
1267
1268
1269
1270
1271 public void setFont(Font font) {
1272 if (font == null) return;
1273
1274
1275 super.setFont(font);
1276
1277
1278 try {
1279 writeFont(font);
1280 } catch (IOException e) {
1281 handleException(e);
1282 }
1283 }
1284
1285
1286
1287
1288
1289
1290 protected abstract void writeFont(Font font) throws IOException;
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302 public Composite getComposite() {
1303 return currentComposite;
1304 }
1305
1306
1307
1308
1309
1310
1311 public void setComposite(Composite composite) {
1312 currentComposite = composite;
1313 }
1314
1315
1316
1317
1318
1319
1320
1321 protected void handleException(Exception exception) {
1322 if (exception instanceof UnsupportedOperationException) {
1323 writeWarning(exception);
1324 } else {
1325 writeError(exception);
1326 }
1327 }
1328
1329
1330
1331
1332
1333
1334 protected void writeWarning(Exception exception) {
1335 writeWarning(exception.getMessage());
1336 }
1337
1338
1339
1340
1341
1342
1343 protected void writeWarning(String warning) {
1344 if (isProperty(EMIT_WARNINGS)) {
1345 System.err.println(warning);
1346 }
1347 }
1348
1349
1350
1351
1352
1353
1354 protected void writeError(Exception exception) {
1355 throw new RuntimeException(exception);
1356
1357
1358
1359
1360
1361 }
1362
1363 protected Shape createShape(double[] xPoints, double[] yPoints,
1364 int nPoints, boolean close) {
1365 GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
1366 if (nPoints > 0) {
1367 path.moveTo((float) xPoints[0], (float) yPoints[0]);
1368 for (int i = 1; i < nPoints; i++) {
1369 path.lineTo((float) xPoints[i], (float) yPoints[i]);
1370 }
1371 if (close)
1372 path.closePath();
1373 }
1374 return path;
1375 }
1376
1377 private Shape transformShape(AffineTransform at, Shape s) {
1378 if (s == null)
1379 return null;
1380 return at.createTransformedShape(s);
1381 }
1382
1383 private Shape transformShape(Shape s) {
1384 return transformShape(getTransform(), s);
1385 }
1386
1387 private Shape untransformShape(Shape s) {
1388 if (s == null)
1389 return null;
1390 try {
1391 return transformShape(getTransform().createInverse(), s);
1392 } catch (NoninvertibleTransformException e) {
1393 return null;
1394 }
1395 }
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406 protected void overLine(String text, Font font, float x, float y) {
1407 TextLayout layout = new TextLayout(text, font, getFontRenderContext());
1408 float width = Math.max(
1409 layout.getAdvance(),
1410 (float) layout.getBounds().getWidth());
1411
1412 GeneralPath path = new GeneralPath();
1413 path.moveTo(x, y + (float) layout.getBounds().getY() - layout.getAscent());
1414 path.lineTo(x + width, y + (float) layout.getBounds().getY() - layout.getAscent() - layout.getAscent());
1415 draw(path);
1416 }
1417 }