create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / gui / print / visitor / FinMarkingGuideStrategy.java
1 package net.sf.openrocket.gui.print.visitor;
2
3 import com.itextpdf.text.Document;
4 import com.itextpdf.text.DocumentException;
5 import com.itextpdf.text.Rectangle;
6 import com.itextpdf.text.pdf.PdfContentByte;
7 import com.itextpdf.text.pdf.PdfWriter;
8 import net.sf.openrocket.gui.print.FinMarkingGuide;
9 import net.sf.openrocket.gui.print.ITextHelper;
10 import net.sf.openrocket.logging.LogHelper;
11 import net.sf.openrocket.rocketcomponent.Rocket;
12 import net.sf.openrocket.startup.Application;
13
14 import java.awt.*;
15 import java.awt.image.BufferedImage;
16
17 /**
18  * A strategy for drawing a fin marking guide. As currently implemented, each body tube with a finset will have
19  * a marking guide.  If a tube has multiple fin sets, they are combined onto one marking guide.  Launch lugs are supported
20  * as well.
21  */
22 public class FinMarkingGuideStrategy {
23
24     /**
25      * The logger.
26      */
27     private static final LogHelper log = Application.getLogger();
28
29     /**
30      * The iText document.
31      */
32     protected Document document;
33
34     /**
35      * The direct iText writer.
36      */
37     protected PdfWriter writer;
38
39     /**
40      * Constructor.
41      *
42      * @param doc              The iText document
43      * @param theWriter        The direct iText writer
44      */
45     public FinMarkingGuideStrategy(Document doc, PdfWriter theWriter) {
46         document = doc;
47         writer = theWriter;
48     }
49
50     /**
51      * Recurse through the given rocket component.
52      *
53      * @param root the root component; all children will be visited recursively
54      */
55     public void writeToDocument(final Rocket root) {
56         render(root);
57     }
58
59
60     /**
61      * The core behavior of this strategy.
62      *
63      * @param rocket the rocket to render all
64      */
65     private void render(final Rocket rocket) {
66         try {
67             FinMarkingGuide pfs = new FinMarkingGuide(rocket);
68
69             java.awt.Dimension size = pfs.getSize();
70             final Dimension pageSize = getPageSize();
71             if (fitsOnOnePage(pageSize, size.getWidth(), size.getHeight())) {
72                 printOnOnePage(pfs);
73             } else {
74                 BufferedImage image = (BufferedImage) pfs.createImage();
75                 ITextHelper.renderImageAcrossPages(new Rectangle(pageSize.getWidth(), pageSize.getHeight()),
76                         document, writer, image);
77             }
78         } catch (DocumentException e) {
79             log.error("Could not render the fin marking guide.", e);
80         }
81     }
82
83     /**
84      * Determine if the image will fit on the given page.
85      *
86      * @param pageSize the page size
87      * @param wImage   the width of the thing to be printed
88      * @param hImage   the height of the thing to be printed
89      * @return true if the thing to be printed will fit on a single page
90      */
91     private boolean fitsOnOnePage(Dimension pageSize, double wImage, double hImage) {
92         double wPage = pageSize.getWidth();
93         double hPage = pageSize.getHeight();
94
95         int wRatio = (int) Math.ceil(wImage / wPage);
96         int hRatio = (int) Math.ceil(hImage / hPage);
97
98         return wRatio <= 1.0d && hRatio <= 1.0d;
99     }
100
101     /**
102      * Print the transition.
103      *
104      * @param theMarkingGuide the fin marking guide
105      */
106     private void printOnOnePage(final FinMarkingGuide theMarkingGuide) {
107         Dimension d = getPageSize();
108         PdfContentByte cb = writer.getDirectContent();
109         Graphics2D g2 = cb.createGraphics(d.width, d.height);
110         theMarkingGuide.print(g2);
111         g2.dispose();
112         document.newPage();
113     }
114
115     /**
116      * Get the dimensions of the paper page.
117      *
118      * @return an internal Dimension
119      */
120     protected Dimension getPageSize() {
121         return new Dimension(document.getPageSize().getWidth(),
122                 document.getPageSize().getHeight());
123     }
124
125     /**
126      * Convenience class to model a dimension.
127      */
128     class Dimension {
129         /**
130          * Width, in points.
131          */
132         public float width;
133         /**
134          * Height, in points.
135          */
136         public float height;
137
138         /**
139          * Constructor.
140          *
141          * @param w width
142          * @param h height
143          */
144         public Dimension(float w, float h) {
145             width = w;
146             height = h;
147         }
148
149         /**
150          * Get the width.
151          *
152          * @return the width
153          */
154         public float getWidth() {
155             return width;
156         }
157
158         /**
159          * Get the height.
160          *
161          * @return the height
162          */
163         public float getHeight() {
164             return height;
165         }
166     }
167 }