📄 pdfviewport.java
字号:
// $Id: PDFViewport.java,v 1.57 2007/05/21 15:02:19 mike Exp $package org.faceless.pdf2.viewer;import java.awt.*;import java.awt.image.*;import java.awt.event.*;import java.awt.geom.*;import java.awt.print.*;import java.io.*;import java.util.*;import javax.print.*;import javax.swing.*;import javax.swing.border.*;import java.awt.event.MouseEvent;import org.faceless.pdf2.*;import org.faceless.pdf2.Event;/** * <p> * This class represents the "viewport" or "porthole" through which you see * the underlying {@link PDF} object. When you scroll a {@link PDFScrollPane}, what * moves is the viewport, like peering through a camera's viewfinder. Moving the * viewfinder upwards brings new things into view at the top of the picture and * loses things that were at the bottom. * <p></p> * Since 2.7.1 this class may be extended - the {@link #annotateComponent} method * can be overridden to add graphics operations to the page. * </p> * * @see PDFScrollPane * @since 2.5 */public class PDFViewport extends JPanel implements MouseMotionListener, MouseListener, KeyListener{ private PDF pdf; // The PDF... private PDFParser parser; // it's Parser... private PagePainter[] painters; // and it's PagePainters. private BufferedImage pageImage; // The section of page we're drawing private BufferedImage fullImage; // The full page. May not be used private boolean updateImage; // Whether we need to redraw private float dpi; // The DPI private float x1, y1, x2, y2; // Scope of the viewport (points). 0,0 is top left private int pagenum; // The current pagenumber, starts at 0 private float pagewidth, pageheight; // Width/Height of the page (points) private float pageleft, pagebottom; // Offset to the left/bottom of the page (points) private final Collection observers; // List of viewport observers private PageWorker task; // The SwingWorker that redraws the page. private RenderingHints hints; private EventHandler eventhandler; // The handler for mouse/keyboard events private final Map annotationmap; // Map containing a map of shapes -> annotations // If the number of pixels required to render the image is less // than this value, the entire PDF is rendered. Above this size, // only sections of the page are rendered and the Viewport may // have to be redrawn if the viewport is scrolled. // private static final int MAXPIXELS = 2250000; // 1500x1500 // The native DPI of the viewport. 72 may not always be right but that's // what we've chosen. // private static final float SCREENDPI = 72f; // The ColorModel used to draw the PDF. // * ColorModel.getRGBDefault() works on everything but Java 1.4 on OS X. // * PDFParser.RGB only works on Java 1.4 on OS X // private static final ColorModel colormodel = ColorModel.getRGBdefault(); protected PDFViewport() { super(); setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); setBackground(Color.GRAY); setDoubleBuffered(true); observers = new ArrayList(); pagenum = -1; dpi = SCREENDPI; annotationmap = new HashMap(); setEventHandler(new DefaultEventHandler()); } /** * Return true if the zoom level is above the threshold we've chosen to * display the full image. If this method returns false, only a portion * of the page should be rendered. */ private boolean isFullImageOK() { return pagewidth*pageheight*dpi/SCREENDPI <= MAXPIXELS; } /** * Shortcut for min <= val <= max */ private static final float minmax(double min, double val, double max) { if (min>max) throw new IllegalArgumentException("min>max"); return (float)(val < min ? min : val > max ? max : val); } /** * Returns the width of the visible part of the view in points. */ final float getVisibleWidth() { return getWidth() * SCREENDPI / dpi; } /** * Returns the height of the visible part of the view in points. */ final float getVisibleHeight() { return getHeight() * SCREENDPI / dpi; } /** * Returns the maximum distance that can be scrolled along the X-axis. * @return the maximum scroll distance for X */ public final double getMaxScrollX() { return Math.max(pagewidth - getVisibleWidth(), 0); } /** * Returns the maximum distance that can be scrolled along the Y-axis. * * @return the maximum scroll distance for Y */ public final double getMaxScrollY() { return Math.max(pageheight - getVisibleHeight(), 0); } /** * Set the {@link RenderingHints} to be used when rendering this PDF * @param hints the RenderingHints to use - may be null * @since 2.7.7 */ public void setRenderingHints(RenderingHints hints) { this.hints = hints; } /** * Sets the Viewports's {@link PDF} object, which can be <code>null</code>. * Calling this method resets the pagenumber, X and Y co-ordinates to 0, and the * DPI to 72. * * @param pdf the PDF pdf to display in this viewport * @see PDF */ public final void setDocument(PDF pdf) { pageImage = fullImage = null; this.pdf = pdf; if (pdf == null) { parser = null; painters = null; } else { parser = new PDFParser(this.pdf); painters = new PagePainter[parser.getNumberOfPages()]; for (int i=0;i<painters.length;i++) { painters[i] = parser.getPagePainter(i); painters[i].setRenderingHints(hints); } // Run the open action. If one doesn't exist, create one that // moves to the top-left of the first page. // PDFAction action = pdf.getAction(Event.OPEN); if (action==null) { PDFPage page = pdf.getPage(0); action = PDFAction.goTo(page, 0, page.getHeight(), 1); } runAction(action); } } /** * Select the page of the PDF to display in this Viewport. Calling this * method resets the X and Y co-ordinates to 0 but leaves the DPI unchanged. * * @param pagenumber the page number, between 0 and {@link PDF#getNumberOfPages}-1 * @see #setDocument */ public void setPageNumber(int pagenumber) { setPageNumber(pagenumber, 0, 0, 0); } /** * Display the specified page at the specified X and Y co-ordinates and DPI. * * @param pagenumber the page number, between 0 and {@link PDF#getNumberOfPages}-1 * @param x the X co-ordinate of the top-left hand corner of the viewport, in points. NaN means "don't change" * @param y the Y co-ordinate of the top-left hand corner of the viewport, in points. NaN means "don't change" * @param dpi how many dots per inch to view the page at (the zoom level). A value of * 72 renders in 1 point per pixel, whereas a value of zero or NaN means keep the current zoom level. * @throws NullPointerException if no document has been set * @throws IllegalArgumentException if the DPI is <= 0 */ public void setPageNumber(int pagenumber, double x, double y, double dpi) { if (pdf==null) throw new NullPointerException("Document is null"); if (dpi==dpi && dpi<0) throw new IllegalArgumentException("DPI must be > 0");// System.out.println("setPageNumber("+pagenumber+", "+x+", "+y+", "+dpi+")"); if (pagenumber!=pagenum) { if (eventhandler!=null && pagenum!=-1) { PDFPage oldpage = pdf.getPage(pagenum); eventhandler.pageHidden(new PDFNavigationEvent(this, oldpage)); removePageAnnotations(oldpage); } // Set "pagewidth" and "pageheight", the size of the page in points // Note if the CropBox is specified we use that, in which case pageleft // and pagebottom may be non-zero. // PDFPage page = pdf.getPage(pagenumber); float[] mbox = page.getBox("MediaBox"); float[] cbox = page.getBox("CropBox"); if (cbox == null) cbox = mbox; pageleft = cbox[0]; pagebottom = cbox[1]; pagewidth = cbox[2] - cbox[0]; pageheight = cbox[3] - cbox[1]; this.pagenum = pagenumber; page.flush(); updateImage = true; if (eventhandler!=null) { storePageAnnotations(page); eventhandler.pageDisplayed(new PDFNavigationEvent(this, page)); } } if (dpi==dpi && dpi!=0 && dpi!=this.dpi) { this.dpi = (float)dpi; updateImage = true; } // Set the view position and notify our observers that we've changed. // Allow for NaN for X or Y - means keep same position // if ((x==x && x!=x1) || (y==y && y!=y1) || updateImage) { setViewPosition(x, y); updateImage = true; } if (updateImage) { for (Iterator i = observers.iterator();i.hasNext();) { ((ViewportObserver)i.next()).viewportChanged(x1, y1); } } } /** * Sets the view co-ordinates that appear in the upper left hand corner * of the viewport. * * @param x the X co-ordinate of the top-left hand corner of the viewport, in points * @param y the Y co-ordinate of the top-left hand corner of the viewport, in points * @throws NullPointerException if no document has been set */ public void setViewPosition(double x, double y) { if (pdf==null) throw new NullPointerException("Document is null");// System.out.print("setViewPosition("+x+", "+y+")"); // Set 'x1" and "y1" to 0 if the full page is displayed, otherwise // set the section of the page to display // if (x==x) { x1 = getVisibleWidth() < pagewidth ? minmax(0, x, getMaxScrollX()) : 0; x2 = Math.min(x1+getVisibleWidth(), pagewidth); } if (y==y) { y1 = getVisibleHeight() < pageheight ? minmax(0, y, getMaxScrollY()) : 0; // TODO? y2 = Math.min(y1+getVisibleHeight(), pageheight); } if (x2-x1!=0 && y2-y1!=0) { // If values aren't insane: // Adjust coordinates by crop offsets //// System.out.println(" page="+x1+" "+y1+" "+x2+" "+y2+" ph="+pageheight); if (task == null) { task = new PageWorker(pagenum, x1, y1, x2, y2, dpi, pageheight); task.start(); } else { if ((task.x1!=x1 || task.y1!=y1 || task.x2!=x2 || task.y2!=y2 || task.dpi!=dpi || task.pagenum!=pagenum) && !task.isInterrupted()) { task.interrupt(); } } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -