001: /**
002: * Copyright (c) 2003-2005, www.pdfbox.org
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are met:
007: *
008: * 1. Redistributions of source code must retain the above copyright notice,
009: * this list of conditions and the following disclaimer.
010: * 2. Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: * 3. Neither the name of pdfbox; nor the names of its
014: * contributors may be used to endorse or promote products derived from this
015: * software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
021: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: *
028: * http://www.pdfbox.org
029: *
030: */package org.pdfbox.pdfviewer;
031:
032: import java.awt.Color;
033: import java.awt.Dimension;
034: import java.awt.Graphics;
035: import java.awt.Graphics2D;
036: import java.awt.RenderingHints;
037:
038: import java.awt.geom.GeneralPath;
039:
040: import java.io.IOException;
041: import java.util.ArrayList;
042: import java.util.List;
043: import java.util.Map;
044:
045: import org.pdfbox.pdmodel.PDPage;
046: import org.pdfbox.pdmodel.PDResources;
047:
048: import org.pdfbox.pdmodel.common.PDRectangle;
049: import org.pdfbox.pdmodel.font.PDFont;
050: import org.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
051: import org.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
052: import org.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
053:
054: import org.pdfbox.util.PDFStreamEngine;
055: import org.pdfbox.util.ResourceLoader;
056: import org.pdfbox.util.TextPosition;
057:
058: /**
059: * This will paint a page in a PDF document to a graphics context.
060: *
061: * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
062: * @version $Revision: 1.19 $
063: */
064: public class PageDrawer extends PDFStreamEngine {
065:
066: private Graphics2D graphics;
067: private Dimension pageSize;
068: private PDPage page;
069:
070: private List lineSubPaths = new ArrayList();
071: private GeneralPath linePath = new GeneralPath();
072: private Color strokingColor = Color.BLACK;
073: private Color nonStrokingColor = Color.BLACK;
074:
075: /**
076: * Default constructor, loads properties from file.
077: *
078: * @throws IOException If there is an error loading properties from the file.
079: */
080: public PageDrawer() throws IOException {
081: super (ResourceLoader
082: .loadProperties("Resources/PageDrawer.properties"));
083: }
084:
085: /**
086: * This will draw the page to the requested context.
087: *
088: * @param g The graphics context to draw onto.
089: * @param p The page to draw.
090: * @param pageDimension The size of the page to draw.
091: *
092: * @throws IOException If there is an IO error while drawing the page.
093: */
094: public void drawPage(Graphics g, PDPage p, Dimension pageDimension)
095: throws IOException {
096: graphics = (Graphics2D) g;
097: page = p;
098: pageSize = pageDimension;
099:
100: graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
101: RenderingHints.VALUE_ANTIALIAS_ON);
102: PDResources resources = page.findResources();
103: processStream(page, resources, page.getContents().getStream());
104: List annotations = page.getAnnotations();
105: for (int i = 0; i < annotations.size(); i++) {
106: PDAnnotation annot = (PDAnnotation) annotations.get(i);
107: PDRectangle rect = annot.getRectangle();
108: String appearanceName = annot.getAppearanceStream();
109: PDAppearanceDictionary appearDictionary = annot
110: .getAppearance();
111: if (appearDictionary != null) {
112: if (appearanceName == null) {
113: appearanceName = "default";
114: }
115: Map appearanceMap = appearDictionary
116: .getNormalAppearance();
117: PDAppearanceStream appearance = (PDAppearanceStream) appearanceMap
118: .get(appearanceName);
119: if (appearance != null) {
120: g.translate((int) rect.getLowerLeftX(), (int) -rect
121: .getLowerLeftY());
122: //g.translate( 20, -20 );
123: processSubStream(page, appearance.getResources(),
124: appearance.getStream());
125: g.translate((int) -rect.getLowerLeftX(),
126: (int) +rect.getLowerLeftY());
127: }
128: }
129: }
130: // Transformations should be done in order
131: // 1 - Translate
132: // 2 - Rotate
133: // 3 - Scale
134: // Refer to PDFReference p176 (or 188 in xpdf)
135: //AffineTransform transform = graphics.getTransform();
136: //transform.setToTranslate( 0, page.findMediaBox().getHeight()/2 );
137: //transform.setToRotation((double)p.getRotation());
138: //transform.setTransform( 1, 0, 0, 1, 0, 0 );
139: //transform.setToScale( 1, 1 );
140:
141: //AffineTransform rotation = graphics.getTransform();
142: //rotation.rotate( (page.findRotation() * Math.PI) / 180d );
143: //graphics.setTransform( rotation );
144: }
145:
146: /**
147: * You should override this method if you want to perform an action when a
148: * string is being shown.
149: *
150: * @param text The string to display.
151: */
152: protected void showCharacter(TextPosition text) {
153: //should use colorspaces for the font color but for now assume that
154: //the font color is black
155: try {
156: graphics.setColor(Color.black);
157: PDFont font = text.getFont();
158: font.drawString(text.getCharacter(), graphics, text
159: .getFontSize(), text.getXScale(), text.getYScale(),
160: text.getX(), text.getY());
161: } catch (IOException io) {
162: io.printStackTrace();
163: }
164: }
165:
166: /**
167: * Get the graphics that we are currently drawing on.
168: *
169: * @return The graphics we are drawing on.
170: */
171: public Graphics2D getGraphics() {
172: return graphics;
173: }
174:
175: /**
176: * Get the page that is currently being drawn.
177: *
178: * @return The page that is being drawn.
179: */
180: public PDPage getPage() {
181: return page;
182: }
183:
184: /**
185: * Get the size of the page that is currently being drawn.
186: *
187: * @return The size of the page that is being drawn.
188: */
189: public Dimension getPageSize() {
190: return pageSize;
191: }
192:
193: /**
194: * Fix the y coordinate based on page rotation.
195: *
196: * @param x The x coordinate.
197: * @param y The y coordinate.
198: * @return The updated y coordinate.
199: */
200: public double fixY(double x, double y) {
201: double retval = y;
202: int rotation = page.findRotation();
203: if (rotation == 0) {
204: retval = pageSize.getHeight() - y;
205: } else if (rotation == 90) {
206: retval = y;
207: }
208: return retval;
209: }
210:
211: /**
212: * Get the current line path to be drawn.
213: *
214: * @return The current line path to be drawn.
215: */
216: public GeneralPath getLinePath() {
217: return linePath;
218: }
219:
220: /**
221: * Set the line path to draw.
222: *
223: * @param newLinePath Set the line path to draw.
224: */
225: public void setLinePath(GeneralPath newLinePath) {
226: linePath = newLinePath;
227: }
228:
229: /**
230: * Get the current list of line paths to be drawn.
231: *
232: * @return The current list of line paths to be drawn.
233: */
234: public List getLineSubPaths() {
235: return lineSubPaths;
236: }
237:
238: /**
239: * Set the list of line paths to draw.
240: *
241: * @param newLineSubPaths Set the list of line paths to draw.
242: */
243: public void setLineSubPaths(List newLineSubPaths) {
244: lineSubPaths = newLineSubPaths;
245: }
246:
247: /**
248: * Get the non stroking color.
249: *
250: * @return The non stroking color.
251: */
252: public Color getNonStrokingColor() {
253: return nonStrokingColor;
254: }
255:
256: /**
257: * Set the non stroking color.
258: *
259: * @param newNonStrokingColor The non stroking color.
260: */
261: public void setNonStrokingColor(Color newNonStrokingColor) {
262: nonStrokingColor = newNonStrokingColor;
263: }
264:
265: /**
266: * Get the stroking color.
267: *
268: * @return The stroking color.
269: */
270: public Color getStrokingColor() {
271: return strokingColor;
272: }
273:
274: /**
275: * Set the stroking color.
276: *
277: * @param newStrokingColor The stroking color.
278: */
279: public void setStrokingColor(Color newStrokingColor) {
280: strokingColor = newStrokingColor;
281: }
282: }
|