package net.sf.openrocket.gui.print.visitor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfWriter;
import net.sf.openrocket.gui.print.FinMarkingGuide;
import net.sf.openrocket.gui.print.ITextHelper;
import net.sf.openrocket.rocketcomponent.Rocket;
import java.awt.*;
import java.awt.image.BufferedImage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A strategy for drawing a fin marking guide. As currently implemented, each body tube with a finset will have
* a marking guide. If a tube has multiple fin sets, they are combined onto one marking guide. Launch lugs are supported
* as well.
*/
public class FinMarkingGuideStrategy {
/**
* The logger.
*/
private static final Logger log = LoggerFactory.getLogger(FinMarkingGuideStrategy.class);
/**
* The iText document.
*/
protected Document document;
/**
* The direct iText writer.
*/
protected PdfWriter writer;
/**
* Constructor.
*
* @param doc The iText document
* @param theWriter The direct iText writer
*/
public FinMarkingGuideStrategy(Document doc, PdfWriter theWriter) {
document = doc;
writer = theWriter;
}
/**
* Recurse through the given rocket component.
*
* @param root the root component; all children will be visited recursively
*/
public void writeToDocument(final Rocket root) {
render(root);
}
/**
* The core behavior of this strategy.
*
* @param rocket the rocket to render all
*/
private void render(final Rocket rocket) {
try {
FinMarkingGuide pfs = new FinMarkingGuide(rocket);
java.awt.Dimension size = pfs.getSize();
final Dimension pageSize = getPageSize();
if (fitsOnOnePage(pageSize, size.getWidth(), size.getHeight())) {
printOnOnePage(pfs);
} else {
BufferedImage image = (BufferedImage) pfs.createImage();
ITextHelper.renderImageAcrossPages(new Rectangle(pageSize.getWidth(), pageSize.getHeight()),
document, writer, image);
}
} catch (DocumentException e) {
log.error("Could not render the fin marking guide.", e);
}
}
/**
* Determine if the image will fit on the given page.
*
* @param pageSize the page size
* @param wImage the width of the thing to be printed
* @param hImage the height of the thing to be printed
* @return true if the thing to be printed will fit on a single page
*/
private boolean fitsOnOnePage(Dimension pageSize, double wImage, double hImage) {
double wPage = pageSize.getWidth();
double hPage = pageSize.getHeight();
int wRatio = (int) Math.ceil(wImage / wPage);
int hRatio = (int) Math.ceil(hImage / hPage);
return wRatio <= 1.0d && hRatio <= 1.0d;
}
/**
* Print the transition.
*
* @param theMarkingGuide the fin marking guide
*/
private void printOnOnePage(final FinMarkingGuide theMarkingGuide) {
Dimension d = getPageSize();
PdfContentByte cb = writer.getDirectContent();
Graphics2D g2 = cb.createGraphics(d.width, d.height);
theMarkingGuide.print(g2);
g2.dispose();
document.newPage();
}
/**
* Get the dimensions of the paper page.
*
* @return an internal Dimension
*/
protected Dimension getPageSize() {
return new Dimension(document.getPageSize().getWidth(),
document.getPageSize().getHeight());
}
/**
* Convenience class to model a dimension.
*/
class Dimension {
/**
* Width, in points.
*/
public float width;
/**
* Height, in points.
*/
public float height;
/**
* Constructor.
*
* @param w width
* @param h height
*/
public Dimension(float w, float h) {
width = w;
height = h;
}
/**
* Get the width.
*
* @return the width
*/
public float getWidth() {
return width;
}
/**
* Get the height.
*
* @return the height
*/
public float getHeight() {
return height;
}
}
}