1
2 package org.freehep.graphicsio.pdf;
3
4 import java.awt.BasicStroke;
5 import java.awt.Color;
6 import java.awt.Component;
7 import java.awt.Dimension;
8 import java.awt.Font;
9 import java.awt.GradientPaint;
10 import java.awt.Graphics;
11 import java.awt.GraphicsConfiguration;
12 import java.awt.Insets;
13 import java.awt.Paint;
14 import java.awt.Rectangle;
15 import java.awt.Shape;
16 import java.awt.Stroke;
17 import java.awt.TexturePaint;
18 import java.awt.font.LineMetrics;
19 import java.awt.geom.AffineTransform;
20 import java.awt.geom.Rectangle2D;
21 import java.awt.image.BufferedImage;
22 import java.awt.image.RenderedImage;
23 import java.io.BufferedOutputStream;
24 import java.io.File;
25 import java.io.FileNotFoundException;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.OutputStream;
29 import java.util.ArrayList;
30 import java.util.Calendar;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Properties;
36
37 import org.freehep.graphics2d.TagString;
38 import org.freehep.graphics2d.font.FontUtilities;
39 import org.freehep.graphics2d.font.Lookup;
40 import org.freehep.graphicsio.AbstractVectorGraphicsIO;
41 import org.freehep.graphicsio.FontConstants;
42 import org.freehep.graphicsio.ImageConstants;
43 import org.freehep.graphicsio.ImageGraphics2D;
44 import org.freehep.graphicsio.InfoConstants;
45 import org.freehep.graphicsio.MultiPageDocument;
46 import org.freehep.graphicsio.PageConstants;
47 import org.freehep.util.UserProperties;
48
49
50
51
52
53
54
55
56
57
58
59
60
61 public class PDFGraphics2D extends AbstractVectorGraphicsIO implements
62 MultiPageDocument, FontUtilities.ShowString {
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 private static final String rootKey = PDFGraphics2D.class.getName();
79
80 public static final String VERSION6 = "Acrobat Reader 6.x";
81
82 public static final String VERSION5 = "Acrobat Reader 5.x";
83
84 public static final String VERSION4 = "Acrobat Reader 4.x";
85
86 public static final String TRANSPARENT = rootKey + "."
87 + PageConstants.TRANSPARENT;
88
89 public static final String BACKGROUND = rootKey + "."
90 + PageConstants.BACKGROUND;
91
92 public static final String BACKGROUND_COLOR = rootKey + "."
93 + PageConstants.BACKGROUND_COLOR;
94
95 public static final String PAGE_SIZE = rootKey + "."
96 + PageConstants.PAGE_SIZE;
97
98 public static final String PAGE_MARGINS = rootKey + "."
99 + PageConstants.PAGE_MARGINS;
100
101 public static final String ORIENTATION = rootKey + "."
102 + PageConstants.ORIENTATION;
103
104 public static final String FIT_TO_PAGE = rootKey + "."
105 + PageConstants.FIT_TO_PAGE;
106
107 public static final String EMBED_FONTS = rootKey + "."
108 + FontConstants.EMBED_FONTS;
109
110 public static final String EMBED_FONTS_AS = rootKey + "."
111 + FontConstants.EMBED_FONTS_AS;
112
113 public static final String THUMBNAILS = rootKey + ".Thumbnails";
114
115 public static final String THUMBNAIL_SIZE = rootKey + ".ThumbnailSize";
116
117 public static final String COMPRESS = rootKey + ".Compress";
118
119 public static final String VERSION = rootKey + ".Version";
120
121 public static final String WRITE_IMAGES_AS = rootKey + "."
122 + ImageConstants.WRITE_IMAGES_AS;
123
124 public static final String AUTHOR = rootKey + "." + InfoConstants.AUTHOR;
125
126 public static final String TITLE = rootKey + "." + InfoConstants.TITLE;
127
128 public static final String SUBJECT = rootKey + "." + InfoConstants.SUBJECT;
129
130 public static final String KEYWORDS = rootKey + "."
131 + InfoConstants.KEYWORDS;
132
133 private static final UserProperties defaultProperties = new UserProperties();
134 static {
135 defaultProperties.setProperty(TRANSPARENT, true);
136 defaultProperties.setProperty(BACKGROUND, false);
137 defaultProperties.setProperty(BACKGROUND_COLOR, Color.GRAY);
138
139 defaultProperties.setProperty(VERSION, VERSION5);
140 defaultProperties.setProperty(COMPRESS, false);
141 defaultProperties.setProperty(PAGE_SIZE, PageConstants.INTERNATIONAL);
142 defaultProperties.setProperty(PAGE_MARGINS, PageConstants
143 .getMargins(PageConstants.SMALL));
144 defaultProperties.setProperty(ORIENTATION, PageConstants.PORTRAIT);
145 defaultProperties.setProperty(FIT_TO_PAGE, true);
146 defaultProperties.setProperty(EMBED_FONTS, false);
147 defaultProperties.setProperty(EMBED_FONTS_AS,
148 FontConstants.EMBED_FONTS_TYPE3);
149 defaultProperties.setProperty(THUMBNAILS, defaultProperties
150 .getProperty(VERSION).equals(VERSION4));
151 defaultProperties.setProperty(THUMBNAIL_SIZE, new Dimension(128, 128));
152 defaultProperties.setProperty(WRITE_IMAGES_AS, ImageConstants.SMALLEST);
153
154 defaultProperties.setProperty(AUTHOR, "");
155 defaultProperties.setProperty(TITLE, "");
156 defaultProperties.setProperty(SUBJECT, "");
157 defaultProperties.setProperty(KEYWORDS, "");
158
159 defaultProperties.setProperty(CLIP, true);
160 defaultProperties.setProperty(TEXT_AS_SHAPES, true);
161 }
162
163 public static Properties getDefaultProperties() {
164 return defaultProperties;
165 }
166
167 public static void setDefaultProperties(Properties newProperties) {
168 defaultProperties.setProperties(newProperties);
169 }
170
171 public static final String version = "$Revision: 10516 $";
172
173 private static final String PDF_VERSION = "1.4";
174
175 private static final String[] COMPRESS_FILTERS = { ImageConstants.ENCODING_FLATE, ImageConstants.ENCODING_ASCII85};
176
177 private static final String[] NO_FILTERS = {};
178
179 private static final double FONTSIZE_CORRECTION = 1.0;
180
181
182
183
184
185
186
187
188
189
190
191
192 private OutputStream ros;
193
194 private PDFWriter os;
195
196 private PDFStream pageStream;
197
198
199 private PDFFontTable fontTable;
200
201 private PDFImageDelayQueue delayImageQueue;
202
203
204
205 private PDFPaintDelayQueue delayPaintQueue;
206
207
208
209
210 private int currentPage;
211
212 private boolean multiPage;
213
214 private TagString[] headerText;
215
216 private int headerUnderline;
217
218 private Font headerFont;
219
220 private TagString[] footerText;
221
222 private int footerUnderline;
223
224 private Font footerFont;
225
226 private List titles;
227
228
229 int alphaIndex;
230
231 Map extGStates;
232
233
234
235
236
237
238
239 public PDFGraphics2D(File file, Dimension size)
240 throws FileNotFoundException {
241 this(new FileOutputStream(file), size);
242 }
243
244 public PDFGraphics2D(File file, Component component)
245 throws FileNotFoundException {
246 this(new FileOutputStream(file), component);
247 }
248
249 public PDFGraphics2D(OutputStream ros, Dimension size) {
250 super(size, false);
251 init(ros);
252 }
253
254 public PDFGraphics2D(OutputStream ros, Component component) {
255 super(component, false);
256 init(ros);
257 }
258
259 private void init(OutputStream ros) {
260 this.ros = new BufferedOutputStream(ros);
261
262 currentPage = 0;
263 multiPage = false;
264 titles = new ArrayList();
265 initProperties(defaultProperties);
266 }
267
268
269 protected PDFGraphics2D(PDFGraphics2D graphics, boolean doRestoreOnDispose) {
270 super(graphics, doRestoreOnDispose);
271
272 this.os = graphics.os;
273 this.pageStream = graphics.pageStream;
274
275 this.delayImageQueue = graphics.delayImageQueue;
276 this.delayPaintQueue = graphics.delayPaintQueue;
277 this.fontTable = graphics.fontTable;
278
279 this.currentPage = graphics.currentPage;
280 this.multiPage = graphics.multiPage;
281 this.titles = graphics.titles;
282
283 this.alphaIndex = graphics.alphaIndex;
284 this.extGStates = graphics.extGStates;
285 }
286
287
288
289
290
291
292 public void setMultiPage(boolean multiPage) {
293 this.multiPage = multiPage;
294 }
295
296 public boolean isMultiPage() {
297 return multiPage;
298 }
299
300
301
302
303
304
305
306 public static void setClipEnabled(boolean enabled) {
307 defaultProperties.setProperty(CLIP, enabled);
308 }
309
310
311
312
313
314
315
316
317
318
319
320
321 public void writeHeader() throws IOException {
322 os = new PDFWriter(new BufferedOutputStream(ros), PDF_VERSION);
323
324 delayImageQueue = new PDFImageDelayQueue(os);
325 delayPaintQueue = new PDFPaintDelayQueue(os, delayImageQueue);
326
327 fontTable = new PDFFontTable(os);
328
329 String producer = getClass().getName();
330 if (!isDeviceIndependent()) {
331 producer += " " + version.substring(1, version.length() - 1);
332 }
333
334 PDFDocInfo info = os.openDocInfo("DocInfo");
335 info.setTitle(getProperty(TITLE));
336 info.setAuthor(getProperty(AUTHOR));
337 info.setSubject(getProperty(SUBJECT));
338 info.setKeywords(getProperty(KEYWORDS));
339
340 info.setCreator(getCreator());
341 info.setProducer(producer);
342 if (!isDeviceIndependent()) {
343 Calendar now = Calendar.getInstance();
344 info.setCreationDate(now);
345 info.setModificationDate(now);
346 }
347 info.setTrapped("False");
348 os.close(info);
349
350
351 PDFCatalog catalog = os.openCatalog("Catalog", "RootPage");
352 catalog.setOutlines("Outlines");
353 catalog.setPageMode("UseOutlines");
354 catalog.setViewerPreferences("Preferences");
355 catalog.setOpenAction(new Object[] { os.ref("Page1"), os.name("Fit") });
356 os.close(catalog);
357
358
359 PDFViewerPreferences prefs = os.openViewerPreferences("Preferences");
360 prefs.setFitWindow(true);
361 prefs.setCenterWindow(false);
362 os.close(prefs);
363
364
365 alphaIndex = 1;
366 extGStates = new HashMap();
367
368
369
370 if (!isMultiPage())
371 openPage(getSize(), null, getComponent());
372 }
373
374 public void writeBackground() {
375 if (isProperty(TRANSPARENT)) {
376 setBackground(null);
377 } else if (isProperty(BACKGROUND)) {
378 setBackground(getPropertyColor(BACKGROUND_COLOR));
379 clearRect(0.0, 0.0, getSize().width, getSize().height);
380 } else {
381 setBackground(getComponent() != null ? getComponent()
382 .getBackground() : Color.WHITE);
383 clearRect(0.0, 0.0, getSize().width, getSize().height);
384 }
385 }
386
387 public void writeTrailer() throws IOException {
388 if (!isMultiPage())
389 closePage();
390
391
392 PDFPageTree pages = os.openPageTree("RootPage", null);
393 for (int i = 1; i <= currentPage; i++) {
394 pages.addPage("Page" + i);
395 }
396 Dimension pageSize = PageConstants.getSize(getProperty(PAGE_SIZE),
397 getProperty(ORIENTATION));
398 pages.setMediaBox(0, 0, pageSize.getWidth(), pageSize.getHeight());
399 pages.setResources("Resources");
400 os.close(pages);
401
402
403 os.object("PageProcSet", new Object[] { os.name("PDF"),
404 os.name("Text"), os.name("ImageC") });
405
406
407 int nFonts = fontTable.addFontDictionary();
408
409
410 int nXObjects = delayImageQueue.addXObjects();
411
412
413 int nPatterns = delayPaintQueue.addPatterns();
414
415
416 if (extGStates.size() > 0) {
417 PDFDictionary extGState = os.openDictionary("ExtGState");
418
419 for (Iterator i = extGStates.keySet().iterator(); i.hasNext();) {
420 Float alpha = (Float) i.next();
421 String alphaName = (String) extGStates.get(alpha);
422 PDFDictionary alphaDictionary = extGState
423 .openDictionary(alphaName);
424 alphaDictionary.entry("ca", alpha.floatValue());
425 alphaDictionary.entry("CA", alpha.floatValue());
426 alphaDictionary.entry("BM", os.name("Normal"));
427 alphaDictionary.entry("AIS", false);
428 extGState.close(alphaDictionary);
429 }
430 os.close(extGState);
431 }
432
433
434 PDFDictionary resources = os.openDictionary("Resources");
435 resources.entry("ProcSet", os.ref("PageProcSet"));
436 if (nFonts > 0)
437 resources.entry("Font", os.ref("FontList"));
438 if (nXObjects > 0)
439 resources.entry("XObject", os.ref("XObjects"));
440 if (nPatterns > 0)
441 resources.entry("Pattern", os.ref("Pattern"));
442 if (extGStates.size() > 0)
443 resources.entry("ExtGState", os.ref("ExtGState"));
444 os.close(resources);
445
446
447 PDFOutlineList outlines = os.openOutlineList("Outlines", "Outline1",
448 "Outline" + currentPage);
449 os.close(outlines);
450
451 for (int i = 1; i <= currentPage; i++) {
452 String prev = i > 1 ? "Outline" + (i - 1) : null;
453 String next = i < currentPage ? "Outline" + (i + 1) : null;
454 PDFOutline outline = os.openOutline("Outline" + i, (String) titles
455 .get(i - 1), "Outlines", prev, next);
456 outline
457 .setDest(new Object[] { os.ref("Page" + i), os.name("Fit") });
458 os.close(outline);
459 }
460
461
462 processDelayed();
463 }
464
465 public void closeStream() throws IOException {
466 os.close();
467 }
468
469 private void processDelayed() throws IOException {
470 delayImageQueue.processAll();
471 delayPaintQueue.processAll();
472 fontTable.embedAll(getFontRenderContext(), isProperty(EMBED_FONTS),
473 getProperty(EMBED_FONTS_AS));
474 }
475
476
477 public void openPage(Component component) throws IOException {
478 openPage(component.getSize(), component.getName(), component);
479 }
480
481 public void openPage(Dimension size, String title) throws IOException {
482 openPage(size, title, null);
483 }
484
485 private void openPage(Dimension size, String title, Component component)
486 throws IOException {
487 if (size == null)
488 size = component.getSize();
489
490 resetClip(new Rectangle(0, 0, size.width, size.height));
491
492 if (pageStream != null) {
493 writeWarning("Page " + currentPage + " already open. "
494 + "Call closePage() before starting a new one.");
495 return;
496 }
497
498 BufferedImage thumbnail = null;
499
500 if ((component != null) && isProperty(PDFGraphics2D.THUMBNAILS)) {
501 thumbnail = ImageGraphics2D.generateThumbnail(component,
502 getPropertyDimension(PDFGraphics2D.THUMBNAIL_SIZE));
503 }
504
505 currentPage++;
506
507 if (title == null)
508 title = "Page " + currentPage + " (untitled)";
509 titles.add(title);
510
511 PDFPage page = os.openPage("Page" + currentPage, "RootPage");
512 page.setContents("PageContents" + currentPage);
513
514 if (thumbnail != null)
515 page.setThumb("Thumb" + currentPage);
516
517 os.close(page);
518
519 if (thumbnail != null) {
520 PDFStream thumbnailStream = os.openStream("Thumb" + currentPage);
521 thumbnailStream.image(thumbnail, Color.black, ImageConstants.ZLIB);
522 os.close(thumbnailStream);
523 }
524
525 pageStream = os.openStream("PageContents" + currentPage,
526 isProperty(COMPRESS) ? COMPRESS_FILTERS : NO_FILTERS);
527
528
529
530
531 AffineTransform pageTrafo = new AffineTransform();
532 pageTrafo.scale(1, -1);
533 Dimension pageSize = PageConstants.getSize(getProperty(PAGE_SIZE),
534 getProperty(ORIENTATION));
535 Insets margins = PageConstants.getMargins(
536 getPropertyInsets(PAGE_MARGINS), getProperty(ORIENTATION));
537 pageTrafo
538 .translate(margins.left, -(pageSize.getHeight() - margins.top));
539
540
541 writeHeadline(pageTrafo);
542 writeFootline(pageTrafo);
543
544
545 double scaleFactor = Math.min(getWidth() / size.width, getHeight()
546 / size.height);
547 if ((scaleFactor < 1) || isProperty(FIT_TO_PAGE)) {
548 pageTrafo.scale(scaleFactor, scaleFactor);
549 } else {
550 scaleFactor = 1;
551 }
552
553
554 double dx = (getWidth() - size.width * scaleFactor) / 2 / scaleFactor;
555 double dy = (getHeight() - size.height * scaleFactor) / 2 / scaleFactor;
556 pageTrafo.translate(dx, dy);
557
558 writeTransform(pageTrafo);
559
560
561 writeGraphicsSave();
562
563 clipRect(0, 0, size.width, size.height);
564
565
566 writeGraphicsSave();
567
568 delayPaintQueue.setPageMatrix(pageTrafo);
569
570 writeGraphicsState();
571 writeBackground();
572 }
573
574 public void closePage() throws IOException {
575 if (pageStream == null) {
576 writeWarning("Page " + currentPage + " already closed. "
577 + "Call openPage() to start a new one.");
578 return;
579 }
580 writeGraphicsRestore();
581 writeGraphicsRestore();
582 os.close(pageStream);
583 pageStream = null;
584
585 processDelayed();
586
587 }
588
589 public void setHeader(Font font, TagString left, TagString center,
590 TagString right, int underlineThickness) {
591 this.headerFont = font;
592 this.headerText = new TagString[3];
593 this.headerText[0] = left;
594 this.headerText[1] = center;
595 this.headerText[2] = right;
596 this.headerUnderline = underlineThickness;
597 }
598
599 public void setFooter(Font font, TagString left, TagString center,
600 TagString right, int underlineThickness) {
601 this.footerFont = font;
602 this.footerText = new TagString[3];
603 this.footerText[0] = left;
604 this.footerText[1] = center;
605 this.footerText[2] = right;
606 this.footerUnderline = underlineThickness;
607 }
608
609 private void writeHeadline(AffineTransform pageTrafo) throws IOException {
610 if (headerText != null) {
611 LineMetrics metrics = headerFont.getLineMetrics("mM",
612 getFontRenderContext());
613 writeLine(pageTrafo, headerFont, headerText, -metrics.getLeading()
614 - headerFont.getSize2D() / 2, TEXT_BOTTOM, -headerFont
615 .getSize2D() / 2, headerUnderline);
616
617 }
618 }
619
620 private void writeFootline(AffineTransform pageTrafo) throws IOException {
621 if (footerText != null) {
622 LineMetrics metrics = footerFont.getLineMetrics("mM",
623 getFontRenderContext());
624 double y = getHeight() + footerFont.getSize2D() / 2;
625 writeLine(pageTrafo, footerFont, footerText, y
626 + metrics.getLeading(), TEXT_TOP, y, footerUnderline);
627 }
628 }
629
630 private void writeLine(AffineTransform trafo, Font font, TagString[] text,
631 double ty, int yAlign, double ly, int underline) throws IOException {
632 writeGraphicsSave();
633 setColor(Color.black);
634 setFont(font);
635 writeTransform(trafo);
636 if (text[0] != null)
637 drawString(text[0], 0, ty, TEXT_LEFT, yAlign);
638 if (text[1] != null)
639 drawString(text[1], getWidth() / 2, ty, TEXT_CENTER, yAlign);
640 if (text[2] != null)
641 drawString(text[2], getWidth(), ty, TEXT_RIGHT, yAlign);
642 if (underline >= 0) {
643 setLineWidth((double) underline);
644 drawLine(0, ly, getWidth(), ly);
645 }
646 writeGraphicsRestore();
647 }
648
649
650
651
652
653
654
655 public Graphics create() {
656 try {
657 writeGraphicsSave();
658 } catch (IOException e) {
659 handleException(e);
660 }
661 return new PDFGraphics2D(this, true);
662 }
663
664 public Graphics create(double x, double y, double width, double height) {
665 try {
666 writeGraphicsSave();
667 } catch (IOException e) {
668 handleException(e);
669 }
670 PDFGraphics2D graphics = new PDFGraphics2D(this, true);
671 graphics.translate(x, y);
672 graphics.clipRect(0, 0, width, height);
673 return graphics;
674 }
675
676 protected void writeGraphicsSave() throws IOException {
677 pageStream.save();
678 }
679
680 protected void writeGraphicsRestore() throws IOException {
681 pageStream.restore();
682 }
683
684
685
686
687
688
689
690 public void draw(Shape s) {
691 try {
692 if (getStroke() instanceof BasicStroke) {
693
694 pageStream.drawPath(s);
695 pageStream.stroke();
696 } else {
697
698 pageStream.drawPath(getStroke().createStrokedShape(s));
699 pageStream.fill();
700 }
701 } catch (IOException e) {
702 handleException(e);
703 }
704 }
705
706 public void fill(Shape s) {
707 try {
708 boolean eofill = pageStream.drawPath(s);
709 if (eofill) {
710 pageStream.fillEvenOdd();
711 } else {
712 pageStream.fill();
713 }
714 } catch (IOException e) {
715 handleException(e);
716 }
717 }
718
719
720 public void copyArea(int x, int y, int width, int height, int dx, int dy) {
721 writeWarning(getClass()
722 + ": copyArea(int, int, int, int, int, int) not implemented.");
723 }
724
725 protected void writeImage(RenderedImage image, AffineTransform xform,
726 Color bkg) throws IOException {
727 PDFName ref = delayImageQueue.delayImage(image, bkg,
728 getProperty(WRITE_IMAGES_AS));
729
730 AffineTransform imageTransform = new AffineTransform(image.getWidth(),
731 0.0, 0.0, -image.getHeight(), 0.0, image.getHeight());
732 xform.concatenate(imageTransform);
733
734 writeGraphicsSave();
735 pageStream.matrix(xform);
736 pageStream.xObject(ref);
737 writeGraphicsRestore();
738 }
739
740
741 protected void writeString(String str, double x, double y)
742 throws IOException {
743
744 writeGraphicsSave();
745
746
747 AffineTransform at = new AffineTransform(1, 0, 0, 1, x, y);
748
749 at.concatenate(getFont().getTransform());
750
751 at.scale(1, -1);
752
753
754 writeTransform(at);
755
756 pageStream.beginText();
757 pageStream.text(0, 0);
758 showCharacterCodes(str);
759 pageStream.endText();
760
761
762 writeGraphicsRestore();
763 }
764
765
766
767
768
769
770
771 protected void writeTransform(AffineTransform t) throws IOException {
772 pageStream.matrix(t);
773 }
774
775
776
777
778
779
780 protected void writeSetClip(Shape s) throws IOException {
781
782 try {
783 AffineTransform at = getTransform();
784 Stroke stroke = getStroke();
785
786 writeGraphicsRestore();
787 writeGraphicsSave();
788
789 writeStroke(stroke);
790 writeTransform(at);
791 } catch (IOException e) {
792 handleException(e);
793 }
794
795
796 writeClip(s);
797 }
798
799 protected void writeClip(Shape s) throws IOException {
800 if (s == null || !isProperty(CLIP)) {
801 return;
802 }
803
804 if (s instanceof Rectangle2D) {
805 pageStream.move(((Rectangle2D) s).getMinX(), ((Rectangle2D) s)
806 .getMinY());
807 pageStream.line(((Rectangle2D) s).getMaxX(), ((Rectangle2D) s)
808 .getMinY());
809 pageStream.line(((Rectangle2D) s).getMaxX(), ((Rectangle2D) s)
810 .getMaxY());
811 pageStream.line(((Rectangle2D) s).getMinX(), ((Rectangle2D) s)
812 .getMaxY());
813 pageStream.closePath();
814 pageStream.clip();
815 pageStream.endPath();
816 } else {
817 boolean eoclip = pageStream.drawPath(s);
818 if (eoclip) {
819 pageStream.clipEvenOdd();
820 } else {
821 pageStream.clip();
822 }
823
824 pageStream.endPath();
825 }
826 }
827
828
829
830
831
832
833
834 protected void writeWidth(float width) throws IOException {
835 pageStream.width(width);
836 }
837
838 protected void writeCap(int cap) throws IOException {
839 switch (cap) {
840 default:
841 case BasicStroke.CAP_BUTT:
842 pageStream.cap(0);
843 break;
844 case BasicStroke.CAP_ROUND:
845 pageStream.cap(1);
846 break;
847 case BasicStroke.CAP_SQUARE:
848 pageStream.cap(2);
849 break;
850 }
851 }
852
853 protected void writeJoin(int join) throws IOException {
854 switch (join) {
855 default:
856 case BasicStroke.JOIN_MITER:
857 pageStream.join(0);
858 break;
859 case BasicStroke.JOIN_ROUND:
860 pageStream.join(1);
861 break;
862 case BasicStroke.JOIN_BEVEL:
863 pageStream.join(2);
864 break;
865 }
866 }
867
868 protected void writeMiterLimit(float limit) throws IOException {
869 pageStream.mitterLimit(limit);
870 }
871
872 protected void writeDash(float[] dash, float phase) throws IOException {
873 pageStream.dash(dash, phase);
874 }
875
876
877 public void setPaintMode() {
878 writeWarning(getClass() + ": setPaintMode() not implemented.");
879 }
880
881 public void setXORMode(Color c1) {
882 writeWarning(getClass() + ": setXORMode(Color) not implemented.");
883 }
884
885 protected void writePaint(Color c) throws IOException {
886 float[] cc = c.getRGBComponents(null);
887
888 Float alpha = new Float(cc[3]);
889 String alphaName = (String) extGStates.get(alpha);
890 if (alphaName == null) {
891 alphaName = "Alpha" + alphaIndex;
892 alphaIndex++;
893 extGStates.put(alpha, alphaName);
894 }
895 pageStream.state(os.name(alphaName));
896 pageStream.colorSpace(cc[0], cc[1], cc[2]);
897 pageStream.colorSpaceStroke(cc[0], cc[1], cc[2]);
898 }
899
900 protected void writePaint(GradientPaint c) throws IOException {
901 writePaint((Paint) c);
902 }
903
904 protected void writePaint(TexturePaint c) throws IOException {
905 writePaint((Paint) c);
906 }
907
908 protected void writePaint(Paint paint) throws IOException {
909 pageStream.colorSpace(os.name("Pattern"));
910 pageStream.colorSpaceStroke(os.name("Pattern"));
911 PDFName shadingName = delayPaintQueue.delayPaint(paint, getTransform(),
912 getProperty(WRITE_IMAGES_AS));
913 pageStream.colorSpace(null, shadingName);
914 pageStream.colorSpaceStroke(new double[] {}, shadingName);
915 }
916
917 protected void setNonStrokeColor(Color c) throws IOException {
918 float[] cc = c.getRGBColorComponents(null);
919 pageStream.colorSpace(cc[0], cc[1], cc[2]);
920 }
921
922 protected void setStrokeColor(Color c) throws IOException {
923 float[] cc = c.getRGBColorComponents(null);
924 pageStream.colorSpaceStroke(cc[0], cc[1], cc[2]);
925 }
926
927
928 protected void writeFont(Font font) throws IOException {
929
930 }
931
932
933
934
935
936
937 public GraphicsConfiguration getDeviceConfiguration() {
938 writeWarning(getClass() + ": getDeviceConfiguration() not implemented.");
939 return null;
940 }
941
942 public void writeComment(String comment) throws IOException {
943
944
945 }
946
947 public String toString() {
948 return "PDFGraphics2D";
949 }
950
951
952
953
954
955
956 public void showString(Font font, String str) throws IOException {
957 String fontRef = fontTable.fontReference(font, isProperty(EMBED_FONTS),
958 getProperty(EMBED_FONTS_AS));
959 pageStream.font(os.name(fontRef), font.getSize() * FONTSIZE_CORRECTION);
960 pageStream.show(str);
961 }
962
963
964
965
966
967
968
969
970 private void showCharacterCodes(String str) throws IOException {
971 FontUtilities.showString(getFont(), str, Lookup.getInstance().getTable(
972 "PDFLatin"), this);
973 }
974
975 private double getWidth() {
976 Dimension pageSize = PageConstants.getSize(getProperty(PAGE_SIZE),
977 getProperty(ORIENTATION));
978 Insets margins = PageConstants.getMargins(
979 getPropertyInsets(PAGE_MARGINS), getProperty(ORIENTATION));
980 return pageSize.getWidth() - margins.left - margins.right;
981 }
982
983 private double getHeight() {
984 Dimension pageSize = PageConstants.getSize(getProperty(PAGE_SIZE),
985 getProperty(ORIENTATION));
986 Insets margins = PageConstants.getMargins(
987 getPropertyInsets(PAGE_MARGINS), getProperty(ORIENTATION));
988 return pageSize.getHeight() - margins.top - margins.bottom;
989 }
990
991 }