Skip to content
Commits on Source (6)
......@@ -13,7 +13,7 @@ Binary Downloads
----------------
You can download binary versions for releases currently under development or older
releases from out [Download Page](http://pdfbox.apache.org/download.cgi).
releases from our [Download Page](http://pdfbox.apache.org/download.cgi).
Build
-----
......
Release Notes -- Apache PDFBox -- Version 2.0.13
Release Notes -- Apache PDFBox -- Version 2.0.16
Introduction
------------
The Apache PDFBox library is an open source Java tool for working with PDF documents.
This is an incremental bugfix release based on the earlier 2.0.12 release. It contains
This is an incremental bugfix release based on the earlier 2.0.15 release. It contains
a couple of fixes and small improvements.
For more details on these changes and all the other fixes and improvements
......@@ -14,58 +14,54 @@ PDFBox issue tracker at https://issues.apache.org/jira/browse/PDFBOX.
Bug
[PDFBOX-3646] - Annotations parsed from XFDF containing ampersand characters are not properly imported
[PDFBOX-4163] - Java 11 compile error
[PDFBOX-4326] - PDF with JPEG2000 image can't be rendered
[PDFBOX-4327] - NullPointerException in PDFStreamEngine.processSoftMask() when running ExtractImages
[PDFBOX-4330] - NumberFormatException in CFFParser.readRealNumber()
[PDFBOX-4331] - Make jdk9 profile activation automatic
[PDFBOX-4333] - ClassCastException when loading PDF
[PDFBOX-4336] - "CMap is invalid" exception thrown
[PDFBOX-4338] - ArrayIndexOutOfBoundsException in COSParser
[PDFBOX-4339] - NullPointerException in COSParser
[PDFBOX-4343] - Prevent calling addSignature twice
[PDFBOX-4345] - FDFAnnotation.richContentsToString does not evaluate text nodes which have siblings in the XML
[PDFBOX-4347] - ArrayIndexOutOfBoundsException in PDFXrefStreamParser
[PDFBOX-4348] - ClassCastException in COSParser
[PDFBOX-4349] - ClassCastException in COSParser
[PDFBOX-4350] - IllegalArgumentException in PDFObjectStreamParser
[PDFBOX-4351] - IndexOutOfBoundsException when reading from InputStreamSource
[PDFBOX-4352] - NullPointerException in COSParser
[PDFBOX-4353] - NullPointerException in PDFXrefStreamParser
[PDFBOX-4354] - NumberFormatException in COSParser
[PDFBOX-4355] - PDFTextStripperByArea dies on Chinese/Japanese files
[PDFBOX-4357] - IllegalArgumentException "root cannot be null"
[PDFBOX-4359] - Bad sizing of signature field inside rotated page
[PDFBOX-4360] - ArrayIndexOutOfBoundsException in ASCIIHexFilter
[PDFBOX-4361] - ArrayIndexOutOfBoundsException in COSParser
[PDFBOX-4364] - example AddValidationInformation fails with scratchfile error
[PDFBOX-4365] - PDFDebugger: JComboBox does not take generic parameters in Java 1.6
[PDFBOX-4366] - NullPointerException in PDButton.updateByValue() when appearance missing
[PDFBOX-4367] - Error expected floating point number actual='18-5'
[PDFBOX-4369] - unsupported ExtractText -force option still appears in online 2.0 docs
[PDFBOX-4372] - Stack overflow around PDFStreamEngine.processStream
[PDFBOX-4374] - Switch from log4j to slf4j
[PDFBOX-4377] - Verify CRL in AddValidation example
[PDFBOX-4381] - Revocation CRL check should be done at signing time in AddValidation example
[PDFBOX-4383] - PDFMergerUtility seems to leave source file open
[PDFBOX-4384] - PDF/A Document Validation out of memory
[PDFBOX-3819] - TrueType glyphs not displayed in rendering on Windows 10
[PDFBOX-4017] - Symbol font glyphs not found on Windows 10 fall creators update
[PDFBOX-4155] - Password Security with Unicode needs SASLprep
[PDFBOX-4489] - Memory issue on org.apache.fontbox.ttf.GlyphSubstitutionTable.readLangSysTable(GlyphSubstitutionTable.java:147)
[PDFBOX-4513] - FDFAnnotationStamp fails to parse some appearance streams
[PDFBOX-4517] - Unable to decrypt PDF with String and Stream filter to identity
[PDFBOX-4518] - NegativeArraySizeException thrown when converting PDF to Image
[PDFBOX-4520] - PDFBox PDFToImage shows black bars on scanned text
[PDFBOX-4521] - Missing Info value from file trailer: org.apache.pdfbox.cos.COSName cannot be cast to org.apache.pdfbox.cos.COSDictionary
[PDFBOX-4525] - PDF completely blow up the RAM on RedHat
[PDFBOX-4526] - Optional Content Membership Dictionaries (OCMD) not supported
[PDFBOX-4535] - java.lang.ClassCastException in PDImageXObject.getMask()
[PDFBOX-4540] - COSWriter sometimes retrieves wrong ObjectKey
[PDFBOX-4543] - PDLineDashPattern fails as float[] is converted to List<float[]> instead of List<Float>
[PDFBOX-4549] - No Unicode mapping
[PDFBOX-4550] - Poor performance with corrupt ToUnicode stream
[PDFBOX-4551] - Prevent printing from CL applications when not authorized
[PDFBOX-4553] - Break of backward compatibility from 2.0.14 to 2.0.15
[PDFBOX-4571] - IllegalArgumentException: illegal line join value
New Feature
[PDFBOX-4563] - Port Appearance Handler from 3.0 back to 2.0
Sub-task
[PDFBOX-4564] - Port interface and base handler
[PDFBOX-4573] - Add dummy call to create appearance to annotations
[PDFBOX-4574] - Port individual appearance handlers
[PDFBOX-4575] - Add appearance generation to annotation example code
[PDFBOX-4576] - Update PageDrawer to match appearance handling in trunk
Improvement
[PDFBOX-4335] - Overlay should implement Closeable
[PDFBOX-4363] - [Patch] Add a common interface PDShadingPaint for all shading paints
[PDFBOX-4371] - Improve ExtractText utility so that it can extract rotated text automatically
[PDFBOX-4375] - Change visibility of Overlay#loadPDF to protected
[PDFBOX-4458] - Subclasses of OperatorProcessor dont use constants
[PDFBOX-4509] - Font appears twice in resources of field widget
[PDFBOX-4510] - Don't write identity matrix in form XObjects of field widgets appearance stream
[PDFBOX-4519] - Reduce artefacts in shadings
[PDFBOX-4522] - Resources cache should be passed to type 3 fonts
[PDFBOX-4529] - ImageToPDF as Command Line
[PDFBOX-4539] - Cache CharsetDecoder
[PDFBOX-4544] - COSWriter.doWriteHeader(COSDocument) should use the document specified as parameter
[PDFBOX-4562] - Remove the usage of COSDocument.getCatalog
[PDFBOX-4578] - Overhaul StreamValidationProcess
Test
Wish
[PDFBOX-4373] - Add additional unit tests
Task
[PDFBOX-4358] - Prevent stack overflow in COSDictionary.toString()
[PDFBOX-4362] - Create simple text extraction example
[PDFBOX-4515] - Support for Add Text Callout Annotation tool.
Release Contents
......
......@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-parent</artifactId>
<version>2.0.13</version>
<version>2.0.16</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
......
libpdfbox2-java (2.0.16-1) unstable; urgency=medium
* New upstream version 2.0.16.
* Switch to debhelper-compat = 12.
* Declare compliance with Debian Policy 4.4.0.
-- Markus Koschany <apo@debian.org> Fri, 19 Jul 2019 02:14:14 +0200
libpdfbox2-java (2.0.13-2) unstable; urgency=medium
* Team upload.
......
......@@ -5,7 +5,7 @@ Maintainer: Debian Java Maintainers <pkg-java-maintainers@lists.alioth.debian.or
Uploaders:
Markus Koschany <apo@debian.org>
Build-Depends:
debhelper (>= 11),
debhelper-compat (= 12),
default-jdk,
javahelper,
junit4,
......@@ -18,7 +18,7 @@ Build-Depends:
libmaven-javadoc-plugin-java,
libpdfbox2-java,
maven-debian-helper
Standards-Version: 4.3.0
Standards-Version: 4.4.0
Vcs-Git: https://salsa.debian.org/java-team/libpdfbox2-java.git
Vcs-Browser: https://salsa.debian.org/java-team/libpdfbox2-java
Homepage: http://pdfbox.apache.org
......
......@@ -4,7 +4,7 @@ Upstream-Contact: The Apache Software Foundation
Source: https://pdfbox.apache.org/downloads.html
Files: *
Copyright: 2010-2017, The Apache Software Foundation
Copyright: 2010-2019, The Apache Software Foundation
2010, Atos Worldline SAS
License: Apache-2.0
......@@ -43,7 +43,7 @@ Copyright: 2012 Red Hat, Inc
License: Liberation-Fonts-License
Files: debian/*
Copyright: 2017-2018, Markus Koschany <apo@debian.org>
Copyright: 2017-2019, Markus Koschany <apo@debian.org>
License: Apache-2.0
License: Apache-2.0
......
......@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-parent</artifactId>
<version>2.0.13</version>
<version>2.0.16</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
......
......@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-parent</artifactId>
<version>2.0.13</version>
<version>2.0.16</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
......
......@@ -110,6 +110,7 @@ import org.apache.pdfbox.filter.FilterFactory;
import org.apache.pdfbox.io.IOUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDPageLabels;
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
import org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceCMYK;
......@@ -124,6 +125,7 @@ import org.apache.pdfbox.printing.PDFPageable;
* @author Ben Litchfield
* @author Khyrul Bashar
*/
@SuppressWarnings({"serial","squid:MaximumInheritanceDepth"})
public class PDFDebugger extends JFrame
{
private static final Set<COSName> SPECIALCOLORSPACES =
......@@ -224,8 +226,10 @@ public class PDFDebugger extends JFrame
}
});
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
jScrollPane1.setBorder(new BevelBorder(BevelBorder.RAISED));
jScrollPane1.setPreferredSize(new Dimension(300, 500));
jScrollPane1.setPreferredSize(new Dimension(screenSize.width / 8, 500));
jSplitPane1.setDividerLocation(screenSize.width / 8);
tree.addTreeSelectionListener(new TreeSelectionListener()
{
@Override
......@@ -239,8 +243,8 @@ public class PDFDebugger extends JFrame
jSplitPane1.setRightComponent(jScrollPane2);
jSplitPane1.setDividerSize(3);
jScrollPane2.setPreferredSize(new Dimension(300, 500));
jScrollPane2.setPreferredSize(new Dimension(screenSize.width / 8 * 7, 500));
jScrollPane2.setViewportView(jTextPane1);
jSplitPane1.setLeftComponent(jScrollPane1);
......@@ -265,8 +269,7 @@ public class PDFDebugger extends JFrame
menuBar.add(createViewMenu());
setJMenuBar(menuBar);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds((screenSize.width-700)/2, (screenSize.height-600)/2, 700, 600);
setBounds(screenSize.width / 4, screenSize.height / 4, screenSize.width / 2, screenSize.height / 2);
// drag and drop to open files
setTransferHandler(new TransferHandler()
......@@ -1122,6 +1125,12 @@ public class PDFDebugger extends JFrame
{
return;
}
AccessPermission ap = document.getCurrentAccessPermission();
if (!ap.canPrint())
{
JOptionPane.showMessageDialog(this, "You do not have permission to print");
return;
}
try
{
......@@ -1180,17 +1189,6 @@ public class PDFDebugger extends JFrame
*/
public static void main(String[] args) throws Exception
{
try
{
// force KCMS (faster than LCMS) if available
Class.forName("sun.java2d.cmm.kcms.KcmsServiceProvider");
System.setProperty("sun.java2d.cmm", "sun.java2d.cmm.kcms.KcmsServiceProvider");
}
catch (ClassNotFoundException e)
{
// do nothing. Happens with JDK7 (which has KCMS) and with JDK10 (which hasn't)
}
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
if (System.getProperty("apple.laf.useScreenMenuBar") == null)
{
......
......@@ -35,11 +35,11 @@ import javax.swing.JTable;
*/
class FlagBitsPaneView
{
final private JPanel panel;
final private String flagHeader;
final private String flagValue;
final private Object[][] tableData;
final private String[] columnNames;
private final JPanel panel;
private final String flagHeader;
private final String flagValue;
private final Object[][] tableData;
private final String[] columnNames;
/**
* Constructor
......
......@@ -21,22 +21,24 @@ import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Iterator;
import java.util.Map;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.TableCellRenderer;
import org.apache.pdfbox.debugger.ui.HighResolutionImageIcon;
/**
* @author Khyrul Bashar
......@@ -47,6 +49,9 @@ class FontEncodingView
{
private JPanel panel;
private static final AffineTransform DEFAULT_TRANSFORM = GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().getDefaultConfiguration().getDefaultTransform();
/**
* Constructor.
* @param tableData Object[][] instance as table data.
......@@ -151,13 +156,20 @@ class FontEncodingView
}
Rectangle cellRect = jTable.getCellRect(row, col, false);
BufferedImage bim = renderGlyph(path, bounds2D, cellRect);
return new JLabel(new ImageIcon(bim));
return new JLabel(new HighResolutionImageIcon(
bim,
(int) Math.ceil(bim.getWidth() / DEFAULT_TRANSFORM.getScaleX()),
(int) Math.ceil(bim.getHeight() / DEFAULT_TRANSFORM.getScaleY())),
SwingConstants.CENTER);
}
if (o instanceof BufferedImage)
{
Rectangle cellRect = jTable.getCellRect(row, col, false);
BufferedImage glyphImage = (BufferedImage) o;
BufferedImage cellImage = new BufferedImage((int) cellRect.getWidth(), (int) cellRect.getHeight(), BufferedImage.TYPE_INT_RGB);
BufferedImage cellImage = new BufferedImage(
(int) (cellRect.getWidth() * DEFAULT_TRANSFORM.getScaleX()),
(int) (cellRect.getHeight() * DEFAULT_TRANSFORM.getScaleY()),
BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) cellImage.getGraphics();
g.setBackground(Color.white);
g.clearRect(0, 0, cellImage.getWidth(), cellImage.getHeight());
......@@ -165,17 +177,20 @@ class FontEncodingView
double scale = 1 / (glyphImage.getHeight() / cellRect.getHeight());
// horizontal center
g.translate((cellRect.getWidth() - glyphImage.getWidth() * scale) / 2, 0);
g.translate((cellRect.getWidth() - glyphImage.getWidth() * scale) / 2 * DEFAULT_TRANSFORM.getScaleX(), 0);
// scale from the glyph to the cell
g.scale(scale, scale);
g.scale(scale * DEFAULT_TRANSFORM.getScaleX(), scale * DEFAULT_TRANSFORM.getScaleY());
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(glyphImage, 0, 0, null);
g.dispose();
return new JLabel(new ImageIcon(cellImage));
return new JLabel(new HighResolutionImageIcon(
cellImage,
(int) Math.ceil(cellImage.getWidth() / DEFAULT_TRANSFORM.getScaleX()),
(int) Math.ceil(cellImage.getHeight() / DEFAULT_TRANSFORM.getScaleY())));
}
if (o != null)
{
......@@ -193,7 +208,10 @@ class FontEncodingView
private BufferedImage renderGlyph(GeneralPath path, Rectangle2D bounds2D, Rectangle cellRect)
{
BufferedImage bim = new BufferedImage((int) cellRect.getWidth(), (int) cellRect.getHeight(), BufferedImage.TYPE_INT_RGB);
BufferedImage bim = new BufferedImage(
(int) (cellRect.getWidth() * DEFAULT_TRANSFORM.getScaleX()),
(int) (cellRect.getHeight() * DEFAULT_TRANSFORM.getScaleY()),
BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) bim.getGraphics();
g.setBackground(Color.white);
g.clearRect(0, 0, bim.getWidth(), bim.getHeight());
......@@ -205,10 +223,10 @@ class FontEncodingView
g.translate(0, -bim.getHeight());
// horizontal center
g.translate((cellRect.getWidth() - bounds2D.getWidth() * scale) / 2, 0);
g.translate((cellRect.getWidth() - bounds2D.getWidth() * scale) / 2 * DEFAULT_TRANSFORM.getScaleX(), 0);
// scale from the glyph to the cell
g.scale(scale, scale);
g.scale(scale * DEFAULT_TRANSFORM.getScaleX(), scale * DEFAULT_TRANSFORM.getScaleY());
// Adjust for negative y min bound
g.translate(0, -yBounds[0]);
......
......@@ -16,14 +16,14 @@
package org.apache.pdfbox.debugger.fontencodingpane;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.swing.JPanel;
import org.apache.fontbox.util.BoundingBox;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
......@@ -96,26 +96,47 @@ class Type3Font extends FontPane
maxY = Math.max(maxY, glyphBBox.getUpperRightY());
}
fontBBox = new PDRectangle((float) minX, (float) minY, (float) (maxX - minX), (float) (maxY - minY));
if (fontBBox.getWidth() <= 0 || fontBBox.getHeight() <= 0)
{
// less reliable, but good as a fallback solution for PDF.js issue 10717
BoundingBox boundingBox = font.getBoundingBox();
fontBBox = new PDRectangle(boundingBox.getLowerLeftX(),
boundingBox.getLowerLeftY(),
boundingBox.getWidth(),
boundingBox.getHeight());
}
}
private Object[][] getGlyphs(PDType3Font font) throws IOException
{
boolean isEmpty = fontBBox.toGeneralPath().getBounds2D().isEmpty();
Object[][] glyphs = new Object[256][4];
// map needed to lessen memory footprint for files with duplicates
// e.g. PDF.js issue 10717
Map<String, BufferedImage> map = new HashMap<String, BufferedImage>();
for (int index = 0; index <= 255; index++)
{
glyphs[index][0] = index;
if (font.getEncoding().contains(index))
{
glyphs[index][1] = font.getEncoding().getName(index);
String name = font.getEncoding().getName(index);
glyphs[index][1] = name;
glyphs[index][2] = font.toUnicode(index);
if (fontBBox.toGeneralPath().getBounds2D().isEmpty())
if (isEmpty)
{
glyphs[index][3] = NO_GLYPH;
}
else if (map.containsKey(name))
{
glyphs[index][3] = map.get(name);
}
else
{
glyphs[index][3] = renderType3Glyph(font, index);
BufferedImage image = renderType3Glyph(font, index);
map.put(name, image);
glyphs[index][3] = image;
}
totalAvailableGlyph++;
}
......@@ -142,26 +163,24 @@ class Type3Font extends FontPane
}
PDPage page = new PDPage(new PDRectangle(fontBBox.getWidth() * scale, fontBBox.getHeight() * scale));
page.setResources(resources);
PDPageContentStream cs = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, false);
try
{
PDPageContentStream cs = new PDPageContentStream(doc, page);
cs.transform(Matrix.getTranslateInstance(-fontBBox.getLowerLeftX(), -fontBBox.getLowerLeftY()));
try
{
AffineTransform at = font.getFontMatrix().createAffineTransform();
if (!at.isIdentity())
{
at.invert();
cs.transform(new Matrix(at));
}
}
catch (NoninvertibleTransformException ex)
{
// "shouldn't happen"
}
// any changes here must be done carefully and each file must be tested again
// just inverting didn't work with
// https://www.treasury.gov/ofac/downloads/sdnlist.pdf (has rotated matrix)
// also PDFBOX-4228-type3.pdf (identity matrix)
// Root/Pages/Kids/[0]/Resources/XObject/X1/Resources/XObject/X3/Resources/Font/F10
// PDFBOX-1794-vattenfall.pdf (scale 0.001)
float scalingFactorX = font.getFontMatrix().getScalingFactorX();
float scalingFactorY = font.getFontMatrix().getScalingFactorY();
float translateX = scalingFactorX > 0 ? -fontBBox.getLowerLeftX() : fontBBox.getUpperRightX();
float translateY = scalingFactorY > 0 ? -fontBBox.getLowerLeftY() : fontBBox.getUpperRightY();
cs.transform(Matrix.getTranslateInstance(translateX * scale, translateY * scale));
cs.beginText();
cs.setFont(font, scale);
//TODO support type3 font encoding in PDType3Font.encode
cs.setFont(font, scale / Math.min(Math.abs(scalingFactorX), Math.abs(scalingFactorY)));
// can't use showText() because there's no guarantee we have the unicode
cs.appendRawCommands(String.format("<%02X> Tj\n", index).getBytes(Charsets.ISO_8859_1));
cs.endText();
cs.close();
......
......@@ -40,6 +40,7 @@ import javax.swing.JPanel;
* HexPane shows the byte in a Grid table where every row has 16 bytes. It only draws bytes those are
* only visible at a given time.
*/
@SuppressWarnings("squid:S1948")
class HexPane extends JPanel implements KeyListener, MouseListener, MouseMotionListener, HexModelChangeListener
{
private final HexModel model;
......@@ -170,15 +171,15 @@ class HexPane extends JPanel implements KeyListener, MouseListener, MouseMotionL
*/
private int getIndexForPoint(Point point)
{
if (point.x <= 20 || point.x >= (16 * HexView.CHAR_WIDTH)+20 )
if (point.x <= 20 || point.x >= (16 * HexView.CHAR_WIDTH) + 20)
{
return -1;
}
int y = point.y;
int lineNumber = (y+ (HexView.CHAR_HEIGHT -(y % HexView.CHAR_HEIGHT)))/ HexView.CHAR_HEIGHT;
int lineNumber = (y + (HexView.CHAR_HEIGHT - (y % HexView.CHAR_HEIGHT))) / HexView.CHAR_HEIGHT;
int x = point.x - 20;
int elementNumber = (x / HexView.CHAR_WIDTH);
return (lineNumber-1) * 16 + elementNumber;
int elementNumber = x / HexView.CHAR_WIDTH;
return (lineNumber - 1) * 16 + elementNumber;
}
/**
......@@ -306,7 +307,7 @@ class HexPane extends JPanel implements KeyListener, MouseListener, MouseMotionL
@Override
public void keyReleased(KeyEvent keyEvent)
{
// do nothing
}
@Override
......@@ -324,36 +325,37 @@ class HexPane extends JPanel implements KeyListener, MouseListener, MouseMotionL
@Override
public void mousePressed(MouseEvent mouseEvent)
{
// do nothing
}
@Override
public void mouseReleased(MouseEvent mouseEvent)
{
// do nothing
}
@Override
public void mouseEntered(MouseEvent mouseEvent)
{
// do nothing
}
@Override
public void mouseExited(MouseEvent mouseEvent)
{
// do nothing
}
@Override
public void mouseDragged(MouseEvent mouseEvent)
{
// do nothing
}
@Override
public void mouseMoved(MouseEvent mouseEvent)
{
// do nothing
}
private static boolean isHexChar(char c)
......
......@@ -29,7 +29,9 @@ import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
......@@ -37,6 +39,8 @@ import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.debugger.ui.ImageUtil;
import org.apache.pdfbox.debugger.ui.RotationMenu;
......@@ -47,7 +51,15 @@ import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.debugger.PDFDebugger;
import org.apache.pdfbox.debugger.ui.HighResolutionImageIcon;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.interactive.action.PDAction;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionGoTo;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionURI;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDDestination;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDNamedDestination;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageDestination;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
......@@ -59,6 +71,7 @@ import org.apache.pdfbox.pdmodel.interactive.form.PDField;
*/
public class PagePane implements ActionListener, AncestorListener, MouseMotionListener, MouseListener
{
private static final Log LOG = LogFactory.getLog(PagePane.class);
private JPanel panel;
private int pageIndex = -1;
private final PDDocument document;
......@@ -83,20 +96,81 @@ public class PagePane implements ActionListener, AncestorListener, MouseMotionLi
}
private void initRectMap()
{
try
{
collectFieldLocations();
collectLinkLocations();
}
catch (IOException ex)
{
LOG.error(ex.getMessage(), ex);
}
}
private void collectLinkLocations() throws IOException
{
for (PDAnnotation annotation : page.getAnnotations())
{
if (annotation instanceof PDAnnotationLink)
{
PDAnnotationLink linkAnnotation = (PDAnnotationLink) annotation;
PDAction action = linkAnnotation.getAction();
if (action instanceof PDActionURI)
{
PDActionURI uriAction = (PDActionURI) action;
rectMap.put(annotation.getRectangle(), "URI: " + uriAction.getURI());
continue;
}
PDDestination destination;
if (action instanceof PDActionGoTo)
{
PDActionGoTo goToAction = (PDActionGoTo) action;
destination = goToAction.getDestination();
}
else
{
destination = linkAnnotation.getDestination();
}
if (destination instanceof PDNamedDestination)
{
destination = document.getDocumentCatalog().
findNamedDestinationPage((PDNamedDestination) destination);
}
if (destination instanceof PDPageDestination)
{
PDPageDestination pageDestination = (PDPageDestination) destination;
int pageNum = pageDestination.retrievePageNumber();
if (pageNum != -1)
{
rectMap.put(annotation.getRectangle(), "Page destination: " + (pageNum + 1));
}
}
}
}
}
private void collectFieldLocations() throws IOException
{
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
if (acroForm == null)
{
return;
}
Set<COSDictionary> dictionarySet = new HashSet<COSDictionary>();
for (PDAnnotation annotation : page.getAnnotations())
{
dictionarySet.add(annotation.getCOSObject());
}
for (PDField field : acroForm.getFieldTree())
{
String fullyQualifiedName = field.getFullyQualifiedName();
for (PDAnnotationWidget widget : field.getWidgets())
{
if (page.equals(widget.getPage()))
// check if the annotation widget is on this page
// (checking widget.getPage() also works, but it is sometimes null)
if (dictionarySet.contains(widget.getCOSObject()))
{
rectMap.put(widget.getRectangle(), fullyQualifiedName);
rectMap.put(widget.getRectangle(), "Field name: " + field.getFullyQualifiedName());
}
}
}
......@@ -196,11 +270,13 @@ public class PagePane implements ActionListener, AncestorListener, MouseMotionLi
@Override
public void ancestorMoved(AncestorEvent ancestorEvent)
{
// do nothing
}
@Override
public void mouseDragged(MouseEvent e)
{
// do nothing
}
/**
......@@ -218,7 +294,8 @@ public class PagePane implements ActionListener, AncestorListener, MouseMotionLi
float zoomScale = zoomMenu.getPageZoomScale();
float x = e.getX() / zoomScale * (float) defaultTransform.getScaleX();
float y = e.getY() / zoomScale * (float) defaultTransform.getScaleY();
int x1, y1;
int x1;
int y1;
switch ((RotationMenu.getRotationDegrees() + page.getRotation()) % 360)
{
case 90:
......@@ -246,7 +323,7 @@ public class PagePane implements ActionListener, AncestorListener, MouseMotionLi
{
if (entry.getKey().contains(x1, y1))
{
text += ", field: " + rectMap.get(entry.getKey());
text += ", " + rectMap.get(entry.getKey());
break;
}
}
......@@ -257,21 +334,25 @@ public class PagePane implements ActionListener, AncestorListener, MouseMotionLi
@Override
public void mouseClicked(MouseEvent e)
{
// do nothing
}
@Override
public void mousePressed(MouseEvent e)
{
// do nothing
}
@Override
public void mouseReleased(MouseEvent e)
{
// do nothing
}
@Override
public void mouseEntered(MouseEvent e)
{
// do nothing
}
@Override
......
......@@ -24,19 +24,29 @@ import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import org.apache.pdfbox.contentstream.operator.OperatorName;
/**
* @author Khyrul Bashar
*/
final class OperatorMarker
{
public static final String BEGIN_TEXT_OBJECT = "BT";
public static final String END_TEXT_OBJECT = "ET";
public static final String SAVE_GRAPHICS_STATE = "q";
public static final String RESTORE_GRAPHICS_STATE = "Q";
public static final String CONCAT = "cm";
public static final String INLINE_IMAGE_BEGIN = "BI";
public static final String IMAGE_DATA = "ID";
public static final String INLINE_IMAGE_END = "EI";
@Deprecated
public static final String BEGIN_TEXT_OBJECT = OperatorName.BEGIN_TEXT;
@Deprecated
public static final String END_TEXT_OBJECT = OperatorName.END_TEXT;
@Deprecated
public static final String SAVE_GRAPHICS_STATE = OperatorName.SAVE;
@Deprecated
public static final String RESTORE_GRAPHICS_STATE = OperatorName.RESTORE;
@Deprecated
public static final String CONCAT = OperatorName.CONCAT;
@Deprecated
public static final String INLINE_IMAGE_BEGIN = OperatorName.BEGIN_INLINE_IMAGE;
@Deprecated
public static final String IMAGE_DATA = OperatorName.BEGIN_INLINE_IMAGE_DATA;
@Deprecated
public static final String INLINE_IMAGE_END = OperatorName.END_INLINE_IMAGE;
private static final Map<String, Style> operatorStyleMap;
......@@ -64,14 +74,14 @@ final class OperatorMarker
Map<String, Style> styleMap = new HashMap<String, Style>();
styleMap.put(BEGIN_TEXT_OBJECT, textObjectStyle);
styleMap.put(END_TEXT_OBJECT, textObjectStyle);
styleMap.put(SAVE_GRAPHICS_STATE, graphicsStyle);
styleMap.put(RESTORE_GRAPHICS_STATE, graphicsStyle);
styleMap.put(CONCAT, concatStyle);
styleMap.put(INLINE_IMAGE_BEGIN, inlineImage);
styleMap.put(IMAGE_DATA, imageData);
styleMap.put(INLINE_IMAGE_END, inlineImage);
styleMap.put(OperatorName.BEGIN_TEXT, textObjectStyle);
styleMap.put(OperatorName.END_TEXT, textObjectStyle);
styleMap.put(OperatorName.SAVE, graphicsStyle);
styleMap.put(OperatorName.RESTORE, graphicsStyle);
styleMap.put(OperatorName.CONCAT, concatStyle);
styleMap.put(OperatorName.BEGIN_INLINE_IMAGE, inlineImage);
styleMap.put(OperatorName.BEGIN_INLINE_IMAGE_DATA, imageData);
styleMap.put(OperatorName.END_INLINE_IMAGE, inlineImage);
operatorStyleMap = styleMap;
}
......
......@@ -44,6 +44,7 @@ import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
import org.apache.pdfbox.contentstream.operator.Operator;
import org.apache.pdfbox.contentstream.operator.OperatorName;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSBoolean;
......@@ -67,16 +68,26 @@ import org.apache.pdfbox.util.Charsets;
*/
public class StreamPane implements ActionListener
{
public static final String BEGIN_TEXT_OBJECT = "BT";
public static final String END_TEXT_OBJECT = "ET";
public static final String SAVE_GRAPHICS_STATE = "q";
public static final String RESTORE_GRAPHICS_STATE = "Q";
public static final String INLINE_IMAGE_BEGIN = "BI";
public static final String IMAGE_DATA = "ID";
public static final String INLINE_IMAGE_END = "EI";
public static final String BEGIN_MARKED_CONTENT1 = "BMC";
public static final String BEGIN_MARKED_CONTENT2 = "BDC";
public static final String END_MARKED_CONTENT = "EMC";
@Deprecated
public static final String BEGIN_TEXT_OBJECT = OperatorName.BEGIN_TEXT;
@Deprecated
public static final String END_TEXT_OBJECT = OperatorName.END_TEXT;
@Deprecated
public static final String SAVE_GRAPHICS_STATE = OperatorName.SAVE;
@Deprecated
public static final String RESTORE_GRAPHICS_STATE = OperatorName.RESTORE;
@Deprecated
public static final String INLINE_IMAGE_BEGIN = OperatorName.BEGIN_INLINE_IMAGE;
@Deprecated
public static final String IMAGE_DATA = OperatorName.BEGIN_INLINE_IMAGE_DATA;
@Deprecated
public static final String INLINE_IMAGE_END = OperatorName.END_INLINE_IMAGE;
@Deprecated
public static final String BEGIN_MARKED_CONTENT1 = OperatorName.BEGIN_MARKED_CONTENT;
@Deprecated
public static final String BEGIN_MARKED_CONTENT2 = OperatorName.BEGIN_MARKED_CONTENT_SEQ;
@Deprecated
public static final String END_MARKED_CONTENT = OperatorName.END_MARKED_CONTENT;
private static final StyleContext CONTEXT = StyleContext.getDefaultStyleContext();
private static final Style OPERATOR_STYLE = CONTEXT.addStyle("operator", null);
......@@ -178,7 +189,7 @@ public class StreamPane implements ActionListener
@Override
public void actionPerformed(ActionEvent actionEvent)
{
if (actionEvent.getActionCommand().equals("comboBoxChanged"))
if ("comboBoxChanged".equals(actionEvent.getActionCommand()))
{
JComboBox comboBox = (JComboBox) actionEvent.getSource();
String currentFilter = (String) comboBox.getSelectedItem();
......@@ -453,17 +464,17 @@ public class StreamPane implements ActionListener
{
Operator op = (Operator) obj;
if (op.getName().equals(END_TEXT_OBJECT)
|| op.getName().equals(RESTORE_GRAPHICS_STATE)
|| op.getName().equals(END_MARKED_CONTENT))
if (op.getName().equals(OperatorName.END_TEXT)
|| op.getName().equals(OperatorName.RESTORE)
|| op.getName().equals(OperatorName.END_MARKED_CONTENT))
{
indent--;
}
writeIndent(docu);
if (op.getName().equals(INLINE_IMAGE_BEGIN))
if (op.getName().equals(OperatorName.BEGIN_INLINE_IMAGE))
{
docu.insertString(docu.getLength(), INLINE_IMAGE_BEGIN + "\n", OPERATOR_STYLE);
docu.insertString(docu.getLength(), OperatorName.BEGIN_INLINE_IMAGE + "\n", OPERATOR_STYLE);
COSDictionary dic = op.getImageParameters();
for (COSName key : dic.keySet())
{
......@@ -473,10 +484,10 @@ public class StreamPane implements ActionListener
docu.insertString(docu.getLength(), "\n", null);
}
String imageString = new String(op.getImageData(), Charsets.ISO_8859_1);
docu.insertString(docu.getLength(), IMAGE_DATA + "\n", INLINE_IMAGE_STYLE);
docu.insertString(docu.getLength(), OperatorName.BEGIN_INLINE_IMAGE_DATA + "\n", INLINE_IMAGE_STYLE);
docu.insertString(docu.getLength(), imageString, null);
docu.insertString(docu.getLength(), "\n", null);
docu.insertString(docu.getLength(), INLINE_IMAGE_END + "\n", OPERATOR_STYLE);
docu.insertString(docu.getLength(), OperatorName.END_INLINE_IMAGE + "\n", OPERATOR_STYLE);
}
else
{
......@@ -484,10 +495,10 @@ public class StreamPane implements ActionListener
docu.insertString(docu.getLength(), operator + "\n", OPERATOR_STYLE);
// nested opening operators
if (op.getName().equals(BEGIN_TEXT_OBJECT) ||
op.getName().equals(SAVE_GRAPHICS_STATE) ||
op.getName().equals(BEGIN_MARKED_CONTENT1) ||
op.getName().equals(BEGIN_MARKED_CONTENT2))
if (op.getName().equals(OperatorName.BEGIN_TEXT) ||
op.getName().equals(OperatorName.SAVE) ||
op.getName().equals(OperatorName.BEGIN_MARKED_CONTENT) ||
op.getName().equals(OperatorName.BEGIN_MARKED_CONTENT_SEQ))
{
indent++;
}
......
......@@ -89,6 +89,7 @@ class StreamTextView implements MouseMotionListener, AncestorListener
@Override
public void mouseDragged(MouseEvent mouseEvent)
{
// do nothing
}
@Override
......@@ -126,5 +127,6 @@ class StreamTextView implements MouseMotionListener, AncestorListener
@Override
public void ancestorMoved(AncestorEvent ancestorEvent)
{
// do nothing
}
}
......@@ -77,9 +77,9 @@ final class KToolTip extends ColorToolTip
// Instead, the "ISO Coated v2 300% (basICColor)" is used, which
// is an open alternative to the "ISO Coated v2 300% (ECI)" profile.
String name = "org/apache/pdfbox/resources/icc/ISOcoated_v2_300_bas.icc";
String name = "/org/apache/pdfbox/resources/icc/ISOcoated_v2_300_bas.icc";
URL url = PDDeviceCMYK.class.getClassLoader().getResource(name);
URL url = PDDeviceCMYK.class.getResource(name);
if (url == null)
{
throw new IOException("Error loading resource: " + name);
......
......@@ -50,7 +50,7 @@ import javax.swing.KeyStroke;
* package</a>.
*
*/
@SuppressWarnings("serial")
@SuppressWarnings({"serial","squid:MaximumInheritanceDepth"})
public class ErrorDialog extends JDialog
{
private static final List<String> FILTERS = Arrays.asList(
......@@ -167,7 +167,7 @@ public class ErrorDialog extends JDialog
{
if (details == null)
{
details = createDetailedMessage(error);
details = createDetailedMessage();
StringBuilder buffer = new StringBuilder();
stacktrace.setText(generateStackTrace(error, buffer).toString());
stacktrace.setCaretPosition(0);
......@@ -247,14 +247,13 @@ public class ErrorDialog extends JDialog
/**
* Creates a non-editable widget to display the detailed stack trace.
*/
JScrollPane createDetailedMessage(Throwable t)
JScrollPane createDetailedMessage()
{
stacktrace = new JTextPane();
stacktrace.setEditable(false);
JScrollPane pane = new JScrollPane(stacktrace,
return new JScrollPane(stacktrace,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
return pane;
}
/**
......