summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--platform/java/example/PageCanvas.java122
-rw-r--r--platform/java/example/Viewer.java507
-rw-r--r--platform/java/src/com/artifex/mupdf/fitz/Document.java4
3 files changed, 320 insertions, 313 deletions
diff --git a/platform/java/example/PageCanvas.java b/platform/java/example/PageCanvas.java
deleted file mode 100644
index b6471f3d..00000000
--- a/platform/java/example/PageCanvas.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package example;
-
-import com.artifex.mupdf.fitz.*;
-import java.awt.*;
-import java.awt.image.*;
-
-public class PageCanvas extends java.awt.Canvas
-{
- protected Page page;
- protected BufferedImage image;
-
- protected float mScale = 1.0f;
- private float mRetinaScale = 1.0f;
-
- private static boolean mShowAnnots = false;
-
- public static BufferedImage imageFromPixmap(Pixmap pixmap) {
- int w = pixmap.getWidth();
- int h = pixmap.getHeight();
- BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
- image.setRGB(0, 0, w, h, pixmap.getPixels(), 0, w);
- return image;
- }
-
- public static BufferedImage imageFromPageWithDevice(Page page, Matrix ctm) {
- // make a blank pixmap
- Rect bbox = page.getBounds();
- bbox.transform(ctm);
- Pixmap pixmap = new Pixmap(ColorSpace.DeviceBGR, bbox, true);
- pixmap.clear(255);
-
- // make a device
- DrawDevice dev = new DrawDevice(pixmap);
-
- // run page contents (without annotations)
- page.runPageContents(dev, ctm, new Cookie());
-
- // run annotations
- if (mShowAnnots)
- {
- Annotation annotations[] = page.getAnnotations();
- if (annotations != null && annotations.length>0)
- {
- for (Annotation annot : annotations) {
- annot.run(dev, ctm, new Cookie());
- }
- }
- }
-
- dev.destroy();
-
- BufferedImage image = imageFromPixmap(pixmap);
- pixmap.destroy();
-
- return image;
- }
-
- public static BufferedImage imageFromPage(Page page, Matrix ctm) {
- Pixmap pixmap = page.toPixmap(ctm, ColorSpace.DeviceBGR, true);
- BufferedImage image = imageFromPixmap(pixmap);
- pixmap.destroy();
- return image;
- }
-
- public PageCanvas(Page page_, float nativeScale) {
- mRetinaScale = nativeScale;
- mScale = mRetinaScale;
- this.page = page_;
- run();
- }
-
- private void run()
- {
- Matrix ctm = new Matrix();
- ctm.scale(mScale);
- image = imageFromPageWithDevice(page, ctm);
- repaint();
- }
-
- public Dimension getPreferredSize() {
- return new Dimension(image.getWidth(), image.getHeight());
- }
-
- public Dimension getMinimumSize() {
- return getPreferredSize();
- }
-
- public Dimension getMaximumSize() {
- return getPreferredSize();
- }
-
- public void zoomIn() {
- if (mScale < 10) {
- mScale += 0.25f;
- run();
- }
- }
-
- public void zoomOut() {
- if (mScale > 0.25f) {
- mScale -= 0.25f;
- run();
- }
- }
-
- public void toggleAnnots() {
- mShowAnnots = !mShowAnnots;
- run();
- }
-
- public void paint(Graphics g)
- {
- float scale = 1.0f;
- scale = 1/mRetinaScale;
-
- final Graphics2D g2d = (Graphics2D)g.create(0, 0, image.getWidth(), image.getHeight());
- g2d.scale(scale, scale);
- g2d.drawImage(image, 0, 0, null);
- g2d.dispose();
- }
-
-}
diff --git a/platform/java/example/Viewer.java b/platform/java/example/Viewer.java
index abd13067..f5a1ad2b 100644
--- a/platform/java/example/Viewer.java
+++ b/platform/java/example/Viewer.java
@@ -2,112 +2,253 @@ package example;
import com.artifex.mupdf.fitz.*;
-import java.io.File;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
-import java.awt.Frame;
-import java.awt.Label;
-import java.awt.Button;
-import java.awt.Panel;
-import java.awt.BorderLayout;
-import java.awt.FlowLayout;
-import java.awt.event.ActionListener;
-import java.awt.event.WindowListener;
-import java.awt.event.WindowEvent;
-import java.awt.event.ActionEvent;
-import java.awt.GraphicsEnvironment;
-import java.awt.GraphicsDevice;
-import java.awt.Toolkit;
-
-import javax.swing.JFileChooser;
-import javax.swing.filechooser.FileFilter;
-import javax.swing.JOptionPane;
+import java.io.File;
+import java.io.FilenameFilter;
import java.lang.reflect.Field;
+import java.util.Vector;
-public class Viewer extends Frame implements WindowListener, ActionListener
+public class Viewer extends Frame implements WindowListener, ActionListener, ItemListener
{
protected Document doc;
- protected Panel toolbar;
- protected PageCanvas pageCanvas;
+
+ protected ScrollPane pageScroll;
+ protected Panel pageHolder;
+ protected ImageCanvas pageCanvas;
+
+ protected Button firstButton, prevButton, nextButton, lastButton;
+ protected TextField pageField;
protected Label pageLabel;
- protected Button firstButton, prevButton, nextButton, lastButton, zoomInButton, zoomOutButton, fontIncButton, fontDecButton, toggleAnnotsButton;
+ protected Button zoomInButton, zoomOutButton;
+ protected Choice zoomChoice;
+ protected Button fontIncButton, fontDecButton;
+ protected Label fontSizeLabel;
+
+ protected List outlineList;
+ protected Vector flatOutline;
+
protected int pageCount;
- protected int pageNumber;
- protected int layoutWidth;
- protected int layoutHeight;
- protected int layoutEm;
+ protected int pageNumber = 0;
+ protected int zoomLevel = 5;
+ protected int layoutWidth = 450;
+ protected int layoutHeight = 600;
+ protected int layoutEm = 12;
+ protected float pixelScale;
+
+ protected static final int zoomList[] = {
+ 18, 24, 36, 54, 72, 96, 120, 144, 180, 216, 288
+ };
+
+ protected static BufferedImage imageFromPixmap(Pixmap pixmap) {
+ int w = pixmap.getWidth();
+ int h = pixmap.getHeight();
+ BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
+ image.setRGB(0, 0, w, h, pixmap.getPixels(), 0, w);
+ return image;
+ }
- private float retinaScale;
+ protected static BufferedImage imageFromPage(Page page, Matrix ctm) {
+ Rect bbox = page.getBounds().transform(ctm);
+ Pixmap pixmap = new Pixmap(ColorSpace.DeviceBGR, bbox, true);
+ pixmap.clear(255);
- public Viewer(Document doc_) {
- super("MuPDF");
+ DrawDevice dev = new DrawDevice(pixmap);
+ page.run(dev, ctm, null);
+ dev.close();
+ dev.destroy();
+
+ BufferedImage image = imageFromPixmap(pixmap);
+ pixmap.destroy();
+ return image;
+ }
+
+ protected static void messageBox(Frame owner, String title, String message) {
+ final Dialog box = new Dialog(owner, title, true);
+ box.add(new Label(message), BorderLayout.CENTER);
+ Panel buttonPane = new Panel(new FlowLayout());
+ Button okayButton = new Button("Okay");
+ okayButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent event) {
+ box.setVisible(false);
+ }
+ });
+ buttonPane.add(okayButton);
+ box.add(buttonPane, BorderLayout.SOUTH);
+ box.pack();
+ box.setVisible(true);
+ box.dispose();
+ }
+
+ protected class ImageCanvas extends Canvas
+ {
+ protected BufferedImage image;
+
+ public void setImage(BufferedImage image_) {
+ image = image_;
+ repaint();
+ }
- retinaScale = getRetinaScale();
+ public Dimension getPreferredSize() {
+ return new Dimension(image.getWidth(), image.getHeight());
+ }
+
+ public void paint(Graphics g) {
+ float imageScale = 1 / pixelScale;
+ final Graphics2D g2d = (Graphics2D)g.create(0, 0, image.getWidth(), image.getHeight());
+ g2d.scale(imageScale, imageScale);
+ g2d.drawImage(image, 0, 0, null);
+ g2d.dispose();
+ }
+ public Dimension getMinimumSize() { return getPreferredSize(); }
+ public Dimension getMaximumSize() { return getPreferredSize(); }
+ public void update(Graphics g) { paint(g); }
+ }
+
+ public Viewer(Document doc_) {
this.doc = doc_;
+ pixelScale = getRetinaScale();
+ setTitle("MuPDF: " + doc.getMetaData(Document.META_INFO_TITLE));
+ doc.layout(layoutWidth, layoutHeight, layoutEm);
pageCount = doc.countPages();
- pageNumber = 0;
- layoutWidth = 1200;
- layoutHeight = 800;
- layoutEm = 12;
+ Panel rightPanel = new Panel(new BorderLayout());
+ {
+ Panel toolpane = new Panel(new GridBagLayout());
+ {
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.WEST;
- setSize(layoutWidth, layoutHeight + 100);
- setTitle("MuPDF: " + doc.getMetaData(Document.META_INFO_TITLE));
+ Panel toolbar = new Panel(new FlowLayout(FlowLayout.LEFT));
+ {
+ firstButton = new Button("|<");
+ firstButton.addActionListener(this);
+ prevButton = new Button("<");
+ prevButton.addActionListener(this);
+ nextButton = new Button(">");
+ nextButton.addActionListener(this);
+ lastButton = new Button(">|");
+ lastButton.addActionListener(this);
+ pageField = new TextField(4);
+ pageField.addActionListener(this);
+ pageLabel = new Label("/ " + pageCount);
+
+ toolbar.add(firstButton);
+ toolbar.add(prevButton);
+ toolbar.add(pageField);
+ toolbar.add(pageLabel);
+ toolbar.add(nextButton);
+ toolbar.add(lastButton);
+ }
+ c.gridy = 0;
+ toolpane.add(toolbar, c);
- toolbar = new Panel();
- toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));
- firstButton = new Button("|<");
- firstButton.addActionListener(this);
- prevButton = new Button("<");
- prevButton.addActionListener(this);
- nextButton = new Button(">");
- nextButton.addActionListener(this);
- lastButton = new Button(">|");
- lastButton.addActionListener(this);
- zoomInButton = new Button("+");
- zoomInButton.addActionListener(this);
- zoomOutButton = new Button("-");
- zoomOutButton.addActionListener(this);
-
- toggleAnnotsButton = new Button("toggle annots");
- toggleAnnotsButton.addActionListener(this);
-
- if (doc.isReflowable()) {
- fontIncButton = new Button("FONT");
- fontIncButton.addActionListener(this);
- fontDecButton = new Button("font");
- fontDecButton.addActionListener(this);
- }
+ toolbar = new Panel(new FlowLayout(FlowLayout.LEFT));
+ {
+ zoomOutButton = new Button("Zoom-");
+ zoomOutButton.addActionListener(this);
+ zoomInButton = new Button("Zoom+");
+ zoomInButton.addActionListener(this);
+
+ zoomChoice = new Choice();
+ for (int i = 0; i < zoomList.length; ++i)
+ zoomChoice.add(String.valueOf(zoomList[i]));
+ zoomChoice.select(zoomLevel);
+ zoomChoice.addItemListener(this);
+
+ toolbar.add(zoomOutButton);
+ toolbar.add(zoomChoice);
+ toolbar.add(zoomInButton);
+ }
+ c.gridy += 1;
+ toolpane.add(toolbar, c);
+
+ if (doc.isReflowable()) {
+ toolbar = new Panel(new FlowLayout(FlowLayout.LEFT));
+ {
+ fontDecButton = new Button("Font-");
+ fontDecButton.addActionListener(this);
+ fontIncButton = new Button("Font+");
+ fontIncButton.addActionListener(this);
+ fontSizeLabel = new Label(String.valueOf(layoutEm));
+
+ toolbar.add(fontDecButton);
+ toolbar.add(fontSizeLabel);
+ toolbar.add(fontIncButton);
+ }
+ c.gridy += 1;
+ toolpane.add(toolbar, c);
+ }
+ }
+ rightPanel.add(toolpane, BorderLayout.NORTH);
- pageLabel = new Label();
-
- toolbar.add(firstButton);
- toolbar.add(prevButton);
- toolbar.add(nextButton);
- toolbar.add(lastButton);
- toolbar.add(zoomInButton);
- toolbar.add(zoomOutButton);
- toolbar.add(toggleAnnotsButton);
- if (doc.isReflowable()) {
- toolbar.add(fontIncButton);
- toolbar.add(fontDecButton);
+ outlineList = new List();
+ outlineList.addItemListener(this);
+ rightPanel.add(outlineList, BorderLayout.CENTER);
}
- toolbar.add(pageLabel);
+ this.add(rightPanel, BorderLayout.EAST);
- add(toolbar, BorderLayout.NORTH);
+ pageScroll = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
+ {
+ pageHolder = new Panel(new GridBagLayout());
+ {
+ pageHolder.setBackground(Color.gray);
+ pageCanvas = new ImageCanvas();
+ pageHolder.add(pageCanvas);
+ }
+ pageScroll.add(pageHolder);
+ }
+ this.add(pageScroll, BorderLayout.CENTER);
addWindowListener(this);
- stuff();
+ updateOutline();
+ updatePageCanvas();
+
+ pack();
+ }
+
+ protected void addOutline(Outline[] outline, String indent) {
+ for (int i = 0; i < outline.length; ++i) {
+ Outline node = outline[i];
+ if (node.title != null) {
+ flatOutline.add(node);
+ outlineList.add(indent + node.title);
+ }
+ if (node.down != null)
+ addOutline(node.down, indent + " ");
+ }
+ }
+
+ protected void updateOutline() {
+ Outline[] outline = doc.loadOutline();
+ outlineList.removeAll();
+ if (outline != null) {
+ flatOutline = new Vector();
+ addOutline(outline, "");
+ outlineList.setVisible(true);
+ } else {
+ outlineList.setVisible(false);
+ }
}
- public void stuff() {
- pageLabel.setText("Page " + (pageNumber + 1) + " / " + pageCount);
- if (pageCanvas != null)
- remove(pageCanvas);
- pageCanvas = new PageCanvas(doc.loadPage(pageNumber), retinaScale);
- add(pageCanvas, BorderLayout.CENTER);
+ protected void updatePageCanvas() {
+ pageField.setText(String.valueOf(pageNumber + 1));
+
+ Matrix ctm = new Matrix().scale(zoomList[zoomLevel] / 72.0f * pixelScale);
+ BufferedImage image = imageFromPage(doc.loadPage(pageNumber), ctm);
+ pageCanvas.setImage(image);
+
+ Dimension size = pageHolder.getPreferredSize();
+ size.width += 40;
+ size.height += 40;
+ pageScroll.setPreferredSize(size);
+ pageCanvas.invalidate();
validate();
}
@@ -115,6 +256,7 @@ public class Viewer extends Frame implements WindowListener, ActionListener
Object source = event.getSource();
int oldPageNumber = pageNumber;
int oldLayoutEm = layoutEm;
+ int oldZoomLevel = zoomLevel;
if (source == firstButton)
pageNumber = 0;
@@ -133,36 +275,78 @@ public class Viewer extends Frame implements WindowListener, ActionListener
if (pageNumber >= pageCount)
pageNumber = pageCount - 1;
}
- if (doc.isReflowable() && source == fontIncButton) {
- layoutEm = layoutEm + 1;
+
+ if (source == pageField) {
+ pageNumber = Integer.parseInt(pageField.getText()) - 1;
+ if (pageNumber < 0)
+ pageNumber = 0;
+ if (pageNumber >= pageCount)
+ pageNumber = pageCount - 1;
+ pageField.setText(String.valueOf(pageNumber));
}
- if (doc.isReflowable() && source == fontDecButton) {
- layoutEm = layoutEm - 1;
+
+ if (source == fontIncButton && doc.isReflowable()) {
+ layoutEm += 1;
+ if (layoutEm > 36)
+ layoutEm = 36;
+ fontSizeLabel.setText(String.valueOf(layoutEm));
}
- if (source == zoomInButton) {
- pageCanvas.zoomIn();
+ if (source == fontDecButton && doc.isReflowable()) {
+ layoutEm -= 1;
+ if (layoutEm < 6)
+ layoutEm = 6;
+ fontSizeLabel.setText(String.valueOf(layoutEm));
}
if (source == zoomOutButton) {
- pageCanvas.zoomOut();
+ zoomLevel -= 1;
+ if (zoomLevel < 0)
+ zoomLevel = 0;
+ zoomChoice.select(zoomLevel);
}
- if (layoutEm != oldLayoutEm)
- doc.layout(layoutWidth, layoutHeight, layoutEm);
+ if (source == zoomInButton) {
+ zoomLevel += 1;
+ if (zoomLevel >= zoomList.length)
+ zoomLevel = zoomList.length - 1;
+ zoomChoice.select(zoomLevel);
+ }
- if (source == toggleAnnotsButton) {
- pageCanvas.toggleAnnots();
+ if (layoutEm != oldLayoutEm) {
+ float oldPos = (pageNumber + 0.5f) / (float)pageCount;
+ doc.layout(layoutWidth, layoutHeight, layoutEm);
+ updateOutline();
+ pageCount = doc.countPages();
+ pageLabel.setText("/ " + pageCount);
+ pageNumber = (int)(oldPos * pageCount);
}
- if (pageNumber != oldPageNumber || layoutEm != oldLayoutEm)
- stuff();
+ if (zoomLevel != oldZoomLevel || pageNumber != oldPageNumber || layoutEm != oldLayoutEm)
+ updatePageCanvas();
}
- public void windowClosing(WindowEvent event) {
- System.exit(0);
+ public void itemStateChanged(ItemEvent event) {
+ Object source = event.getSource();
+ if (source == zoomChoice) {
+ int oldZoomLevel = zoomLevel;
+ zoomLevel = zoomChoice.getSelectedIndex();
+ if (zoomLevel != oldZoomLevel)
+ updatePageCanvas();
+ }
+ if (source == outlineList) {
+ int i = outlineList.getSelectedIndex();
+ Outline node = (Outline)flatOutline.elementAt(i);
+ if (node.page >= 0) {
+ if (node.page != pageNumber) {
+ pageNumber = node.page;
+ updatePageCanvas();
+ }
+ }
+ }
}
+ public void windowClosing(WindowEvent event) { System.exit(0); }
public void windowActivated(WindowEvent event) { }
public void windowDeactivated(WindowEvent event) { }
public void windowIconified(WindowEvent event) { }
@@ -170,108 +354,50 @@ public class Viewer extends Frame implements WindowListener, ActionListener
public void windowOpened(WindowEvent event) { }
public void windowClosed(WindowEvent event) { }
- public static void main(String[] args)
- {
- JFileChooser fileChooser = new JFileChooser();
- fileChooser.setDialogTitle("Choose a file to open");
- fileChooser.setFileFilter(new FileFilter()
- {
- public String getDescription()
- {
- return "Supported files (*.pdf, *,xps, *.jpg, *.jpeg, *.png, *.epub, *.cbz, *.cbr, *.epub)";
- }
-
- public boolean accept(File f)
- {
- if (f.isDirectory())
- return true;
-
- String filename = f.getName().toLowerCase();
- if (filename.endsWith(".pdf"))
- return true;
- if (filename.endsWith(".xps"))
- return true;
- if (filename.endsWith(".jpg"))
- return true;
- if (filename.endsWith(".jpeg"))
- return true;
- if (filename.endsWith(".png"))
- return true;
- if (filename.endsWith(".epub"))
- return true;
- if (filename.endsWith(".cbz"))
- return true;
- if (filename.endsWith(".cbr"))
- return true;
- if (filename.endsWith(".epub"))
- return true;
-
- return false;
- }
- });
-
- while (true)
- {
- try
- {
- // get a file to open
- int result = fileChooser.showOpenDialog(null);
- if (result == JFileChooser.APPROVE_OPTION)
- {
- // user selects a file
- File selectedFile = fileChooser.getSelectedFile();
- if (selectedFile != null)
- {
- Document doc = new Document(selectedFile.getAbsolutePath());
- if (doc != null)
- {
- Viewer app = new Viewer(doc);
- if (app != null)
- {
- app.setVisible(true);
- return;
- }
- else
- {
- infoBox("Cannot create Viewer for "+selectedFile.getAbsolutePath(),"Error");
- }
- }
- else
- {
- infoBox("Cannot open "+selectedFile.getAbsolutePath(),"Error");
- }
- }
- else
- {
- infoBox("Selected file not found.","Error");
- }
+ public static void main(String[] args) {
+ File selectedFile;
+
+ if (args.length <= 0) {
+ FileDialog fileDialog = new FileDialog((Frame)null, "MuPDF Open File", FileDialog.LOAD);
+ fileDialog.setDirectory(System.getProperty("user.dir"));
+ fileDialog.setFilenameFilter(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ if (name.endsWith(".pdf")) return true;
+ if (name.endsWith(".xps")) return true;
+ if (name.endsWith(".oxps")) return true;
+ if (name.endsWith(".cbt")) return true;
+ if (name.endsWith(".cbz")) return true;
+ if (name.endsWith(".epub")) return true;
+ if (name.endsWith(".fb2")) return true;
+ if (name.endsWith(".xhtml")) return true;
+ return false;
}
- else
- {
- infoBox("File selection cancelled.","Error");
- return;
- }
-
- }
- catch (Exception e)
- {
- infoBox("Exception: "+e.getMessage(),"Error");
- }
+ });
+ fileDialog.setVisible(true);
+ if (fileDialog.getFile() == null)
+ System.exit(0);
+ selectedFile = new File(fileDialog.getDirectory(), fileDialog.getFile());
+ fileDialog.dispose();
+ } else {
+ selectedFile = new File(args[0]);
}
- }
- private static void infoBox(String infoMessage, String titleBar)
- {
- JOptionPane.showMessageDialog(null, infoMessage, "InfoBox: " + titleBar, JOptionPane.INFORMATION_MESSAGE);
+ try {
+ Document doc = new Document(selectedFile.getAbsolutePath());
+ Viewer app = new Viewer(doc);
+ app.setVisible(true);
+ return;
+ } catch (Exception e) {
+ messageBox(null, "MuPDF Error", "Cannot open \"" + selectedFile + "\": " + e.getMessage() + ".");
+ System.exit(1);
+ }
}
- public float getRetinaScale()
- {
+ public float getRetinaScale() {
// first try Oracle's VM (we should also test for 1.7.0_40 or higher)
final String vendor = System.getProperty("java.vm.vendor");
boolean isOracle = vendor != null && vendor.toLowerCase().contains("Oracle".toLowerCase());
- if (isOracle)
- {
+ if (isOracle) {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
final GraphicsDevice device = env.getDefaultScreenDevice();
try {
@@ -297,5 +423,4 @@ public class Viewer extends Frame implements WindowListener, ActionListener
return 1.0f;
}
-
}
diff --git a/platform/java/src/com/artifex/mupdf/fitz/Document.java b/platform/java/src/com/artifex/mupdf/fitz/Document.java
index d619f4a2..29cad4db 100644
--- a/platform/java/src/com/artifex/mupdf/fitz/Document.java
+++ b/platform/java/src/com/artifex/mupdf/fitz/Document.java
@@ -53,6 +53,10 @@ public class Document
public native PDFDocument toPDFDocument();
+ public boolean isPDF() {
+ return toPDFDocument() != null;
+ }
+
public String makeProof (String currentPath, String printProfile, String displayProfile, int resolution)
{
String proofFile = proofNative( currentPath, printProfile, displayProfile, resolution);