From 7126689b3e3df4a39321a54639320f283b260273 Mon Sep 17 00:00:00 2001 From: Robert Bamler Date: Thu, 10 May 2012 22:58:39 +0200 Subject: [PATCH 1/3] Proof-of-concept for auto-trimming of page margins This implementation follows the second approach outlined in #issuecomment-5596872 (see issue #20 on github.com/Borisvl/ Pdf4Eclipse). Auto-trimming can be turned on and of with the boolean field PDFPageView.autoTrimOn, which, for now, is just a static constant. Things that remain to do: - I'm not sure if this implementation is memory efficient. Maybe we could do with copying the image one less time. - Coordinate transformation for forward/backward search and for annotations. - Correct handling of the "fit page to screen" and "fit page width to screen width" zoom actions. - Frontend to turn auto-trimming on and off (toggle button). --- .../vonloesch/pdf4eclipse/PDFPageViewer.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/PDFPageViewer.java b/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/PDFPageViewer.java index f6b5c18..a192fda 100644 --- a/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/PDFPageViewer.java +++ b/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/PDFPageViewer.java @@ -16,6 +16,7 @@ import java.awt.geom.Rectangle2D.Double; import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferInt; import java.awt.image.DirectColorModel; import java.awt.image.IndexColorModel; import java.awt.image.WritableRaster; @@ -53,6 +54,8 @@ * */ public class PDFPageViewer extends Canvas implements PaintListener, IPreferenceChangeListener{ + private static final boolean autoTrimOn = true; + /** The image of the rendered PDF page being displayed */ private Image currentImage; @@ -306,6 +309,9 @@ public void showPage(IPDFPage page) { if (sz.x == 0 || sz.y == 0) return; currentImage = page.getImage(newH, newW); + if (autoTrimOn) { + trimCurrentImage(); + } newW = currentImage.getWidth(null); newH = currentImage.getHeight(null); @@ -329,6 +335,78 @@ public void showPage(IPDFPage page) { } } + private void trimCurrentImage() { + if (currentImage==null) + return; + + int origw = currentImage.getWidth(null); + int origh = currentImage.getHeight(null); + if (origw<1 || origh<1) + return; + + BufferedImage img = new BufferedImage(origw, origh, BufferedImage.TYPE_INT_ARGB); + img.getGraphics().drawImage(currentImage, 0, 0, origw, origh, 0, 0, origw, origh, null); + + int[] srcbuf = ((DataBufferInt) img.getRaster().getDataBuffer()).getData(); + + // detect upper margin + int trimy1 = origh; + int referenceColor = srcbuf[0]; + for (int i=0; i!=srcbuf.length; i++) { + if (srcbuf[i] != referenceColor) { + trimy1 = i/origw; + break; + } + } + + // detect lower margin + int trimy2 = 0; + referenceColor = srcbuf[srcbuf.length-1]; + for (int i=srcbuf.length-1; i!=trimy1*origw-1; i--) { + if (srcbuf[i] != referenceColor) { + trimy2 = i/origw + 1; + break; + } + } + + // detect left margin + int trimx1 = 0; + referenceColor = srcbuf[0]; + int offset = trimy1*origw; + int end = trimy2*origw; + trimx1loop: + while (trimx1 != origw) { + for (int i=offset+trimx1; i Date: Sun, 13 May 2012 19:05:49 +0200 Subject: [PATCH 2/3] Automatically trim page margins (issue #20) Finish implementation of auto-trimming of page margins. Detailed list of changes compared to previous commit: - Add front end (toolbar button). - Fix coordinate transformations for annotations and for synctex forward/backward search. - Fix behaviour of the "fit page to screen" and "fit page width to screen width" commands when auto-trimming is activated. --- .../OSGI-INF/l10n/bundle.properties | 2 + de.vonloesch.pdf4eclipse/icons/autotrim.png | Bin 0 -> 585 bytes de.vonloesch.pdf4eclipse/plugin.xml | 33 +++++++++ .../vonloesch/pdf4eclipse/PDFPageViewer.java | 42 +++++++++-- .../pdf4eclipse/editors/PDFEditor.java | 7 +- .../handlers/ToggleAutoTrimHandler.java | 65 ++++++++++++++++++ 6 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 de.vonloesch.pdf4eclipse/icons/autotrim.png create mode 100644 de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/editors/handlers/ToggleAutoTrimHandler.java diff --git a/de.vonloesch.pdf4eclipse/OSGI-INF/l10n/bundle.properties b/de.vonloesch.pdf4eclipse/OSGI-INF/l10n/bundle.properties index 9f7b588..5019032 100644 --- a/de.vonloesch.pdf4eclipse/OSGI-INF/l10n/bundle.properties +++ b/de.vonloesch.pdf4eclipse/OSGI-INF/l10n/bundle.properties @@ -8,9 +8,11 @@ command.description.0 = Set the zoom level command.name.0 = Zoom commandParameter.name = zoomlevel command.name.1 = Toggle highlight +command.name.2 = Toggle auto-trimming command.tooltip = Zoom out command.tooltip.0 = Fit page to window command.tooltip.1 = Fit page to window width command.tooltip.2 = Zoom in command.tooltip.3 = Toggle link highlighting +command.tooltip.4 = Trim Page Margins context.name = PDF viewer \ No newline at end of file diff --git a/de.vonloesch.pdf4eclipse/icons/autotrim.png b/de.vonloesch.pdf4eclipse/icons/autotrim.png new file mode 100644 index 0000000000000000000000000000000000000000..720a56fd6c20c72eb4174567037b5733dd4742e4 GIT binary patch literal 585 zcmV-P0=E5$P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iye> z5CsJFp0afS00GHKL_t(I%cYY)XcJK!$3K@`APz^HOCTv3{6mE^It4S8f(UX&f?Yc0 zz?%do!9|j(xhX-=#UO&EH`&SEyH0{}5(g)R6avynmY$rwGah1}gGoJW(+Gay@%a7T z@B96IAMf`NLJ(gqRb4-tJLxPz4DD=o9cVHg&2h~k68tCRSm%Gnq`tnlXUXH>E-*JK z*l}HP(ly4r-_B-{s?{pRViD6c$>;MN^m<}Z*N0iX!AN49R3vY}>~7{h0zm5b*X<2jf*2ZFiSM7>4xw15EQ4 zilWRE$mMcezNWLdyiBFv2SrgRl`gTd@r-Ww9X-bp)6jDq(dj&8G#a6wJ;(J_>X&LV znM9UlWLcgmF#6P>P$-a2rvZ>!s`}UTt!-@`YyWwz77zD<2Xe#ntd^?&@y_R0R-}t( zVC@PlU6uG6g1%Y@5bUP4Noeah64eo79{l5I-5`0eCcEa(0qBpx7^o1 zevk4|EU55#AENIPckX@Q@qLXT5Yzuc+)_(bx&3gG5xoDXF*gtMneiCk^eo;a4>>;p XNX+ + + + + + + + + + + @@ -190,6 +211,18 @@ + + + + + + diff --git a/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/PDFPageViewer.java b/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/PDFPageViewer.java index a192fda..b2d72ce 100644 --- a/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/PDFPageViewer.java +++ b/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/PDFPageViewer.java @@ -7,6 +7,7 @@ * * Contributors: * Boris von Loesch - initial API and implementation + * Robert Bamler - auto-trimming of page margins ******************************************************************************/ package de.vonloesch.pdf4eclipse; @@ -40,6 +41,7 @@ import org.eclipse.swt.widgets.Display; import de.vonloesch.pdf4eclipse.editors.PDFEditor; +import de.vonloesch.pdf4eclipse.editors.handlers.ToggleAutoTrimHandler; import de.vonloesch.pdf4eclipse.editors.handlers.ToggleLinkHighlightHandler; import de.vonloesch.pdf4eclipse.model.IPDFLinkAnnotation; import de.vonloesch.pdf4eclipse.model.IPDFPage; @@ -54,8 +56,6 @@ * */ public class PDFPageViewer extends Canvas implements PaintListener, IPreferenceChangeListener{ - private static final boolean autoTrimOn = true; - /** The image of the rendered PDF page being displayed */ private Image currentImage; @@ -75,6 +75,11 @@ public class PDFPageViewer extends Canvas implements PaintListener, IPreferenceC private float zoomFactor; + private boolean autoTrimOn = true; + private Point trimOffset = new Point(0, 0); + private float horizontalTrimFactor = 1.0f; + private float verticalTrimFactor = 1.0f; + //private org.eclipse.swt.graphics.Image swtImage; /** @@ -181,6 +186,7 @@ public void run() { prefs.addPreferenceChangeListener(this); highlightLinks = prefs.getBoolean(ToggleLinkHighlightHandler.PREF_LINKHIGHTLIGHT_ID, true); + autoTrimOn = prefs.getBoolean(ToggleAutoTrimHandler.PREF_AUTOTRIM_ID, false); } @@ -403,6 +409,12 @@ private void trimCurrentImage() { trimy1 = Math.max(0, trimy1-margin); trimy2 = Math.min(origh, trimy2+margin); + // remember trim margins + trimOffset .x = trimx1; + trimOffset.y = trimy1; + horizontalTrimFactor = 1.0f * (trimx2-trimx1) / origw; + verticalTrimFactor = 1.0f * (trimy2-trimy1) / origh; + // crop image currentImage = img.getSubimage(trimx1, trimy1, trimx2-trimx1, trimy2-trimy1); } @@ -412,11 +424,14 @@ private Rectangle getRectangle(Rectangle2D r) { } public Rectangle2D convertPDF2ImageCoord(Rectangle2D r) { - return currentPage.pdf2ImageCoordinates(r); + Rectangle2D coord = currentPage.pdf2ImageCoordinates(r); + coord.setRect(coord.getX()-trimOffset.x, coord.getY()-trimOffset.y, coord.getWidth(), coord.getHeight()); + return coord; } public Rectangle2D convertImage2PDFCoord(Rectangle2D r) { - return currentPage.image2PdfCoordinates(r); + java.awt.Rectangle coord = new java.awt.Rectangle((int)r.getX()+trimOffset.x, (int)r.getY()+trimOffset.y, (int)r.getWidth(), (int)r.getHeight()); + return currentPage.image2PdfCoordinates(coord); } /** @@ -501,6 +516,15 @@ public void preferenceChange(PreferenceChangeEvent event) { if (ToggleLinkHighlightHandler.PREF_LINKHIGHTLIGHT_ID.equals(event.getKey())) { highlightLinks = Boolean.parseBoolean((String)(event.getNewValue())); redraw(); + } else if (ToggleAutoTrimHandler.PREF_AUTOTRIM_ID.equals(event.getKey())) { + autoTrimOn = Boolean.parseBoolean((String)(event.getNewValue())); + if (!autoTrimOn) { + trimOffset.x = 0; + trimOffset.y = 0; + horizontalTrimFactor = 1.0f; + verticalTrimFactor = 1.0f; + } + showPage(currentPage); } } @@ -523,4 +547,14 @@ public void dispose() { IEclipsePreferences prefs = (new InstanceScope()).getNode(de.vonloesch.pdf4eclipse.Activator.PLUGIN_ID); prefs.removePreferenceChangeListener(this); } + + + public float getHorizontalTrimFactor() { + return horizontalTrimFactor; + } + + + public float getVerticalTrimFactor() { + return verticalTrimFactor; + } } \ No newline at end of file diff --git a/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/editors/PDFEditor.java b/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/editors/PDFEditor.java index 12e3459..b0dc1bc 100644 --- a/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/editors/PDFEditor.java +++ b/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/editors/PDFEditor.java @@ -8,6 +8,7 @@ * Contributors: * Boris von Loesch - initial API and implementation * MeisterYeti - pseudo-continuous scrolling and zooming by mouse wheel + * Robert Bamler - auto-trimming of page margins ******************************************************************************/ package de.vonloesch.pdf4eclipse.editors; @@ -742,12 +743,12 @@ private void updateStatusLine() { public void fitHorizontal() { int w = sc.getClientArea().width; - pv.setZoomFactor((1.0f*w)/pv.getPage().getWidth()); + pv.setZoomFactor((1.0f/pv.getHorizontalTrimFactor()*w)/pv.getPage().getWidth()); } public void fit() { - float w = 1.f * sc.getClientArea().width; - float h = 1.f * sc.getClientArea().height; + float w = 1.f/pv.getHorizontalTrimFactor() * sc.getClientArea().width; + float h = 1.f/pv.getVerticalTrimFactor() * sc.getClientArea().height; float pw = pv.getPage().getWidth(); float ph = pv.getPage().getHeight(); if (w/pw < h/ph) pv.setZoomFactor(w/pw); diff --git a/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/editors/handlers/ToggleAutoTrimHandler.java b/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/editors/handlers/ToggleAutoTrimHandler.java new file mode 100644 index 0000000..cb91746 --- /dev/null +++ b/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/editors/handlers/ToggleAutoTrimHandler.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2011 Boris von Loesch. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Boris von Loesch - initial API and implementation + * Robert Bamler - auto-trimming of page margins + ******************************************************************************/ +package de.vonloesch.pdf4eclipse.editors.handlers; + +import java.util.Map; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.State; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.commands.IElementUpdater; +import org.eclipse.ui.handlers.RegistryToggleState; +import org.eclipse.ui.menus.UIElement; +import org.osgi.service.prefs.BackingStoreException; + +public class ToggleAutoTrimHandler extends AbstractHandler implements IElementUpdater{ + + public final static String PREF_AUTOTRIM_ID = "de.vonloesch.pdf4eclipse.preferences.autoTrim"; + + private final static String COMMAND_ID = "PDFViewer.command.ToggleAutoTrim"; + private final static String STATE_ID = RegistryToggleState.STATE_ID; + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + Command command = event.getCommand(); + State state = command.getState(STATE_ID); + state.setValue(!(Boolean) state.getValue()); + + ICommandService service = + (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); + service.refreshElements(command.getId(), null); + IEclipsePreferences prefs = (new InstanceScope()).getNode(de.vonloesch.pdf4eclipse.Activator.PLUGIN_ID); + prefs.putBoolean(PREF_AUTOTRIM_ID, ((Boolean) state.getValue()).booleanValue()); + try { + prefs.flush(); + } catch (BackingStoreException e) { + //Do nothing + } + return null; + } + + @Override + public void updateElement(UIElement element, Map parameters) { + ICommandService service = + (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); + Command command = service.getCommand(COMMAND_ID); + State state = command.getState(STATE_ID); + element.setChecked(((Boolean) state.getValue()).booleanValue()); + } + +} From 52128f4393b55a219ac701ff042cbc80f8070011 Mon Sep 17 00:00:00 2001 From: Robert Bamler Date: Sun, 13 May 2012 19:17:11 +0200 Subject: [PATCH 3/3] Fix rounding of scaled page size With the previous implementation, fitting the page width to the screen width sometimes resulted in a page width that was actually one pixel *larger* than the screen width. This was due the use of Math.round(). This commit should fix this issue by always rounding _down_ the would-be floating point page dimensions to the integer page dimensions. --- .../src/de/vonloesch/pdf4eclipse/PDFPageViewer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/PDFPageViewer.java b/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/PDFPageViewer.java index b2d72ce..263bbac 100644 --- a/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/PDFPageViewer.java +++ b/de.vonloesch.pdf4eclipse/src/de/vonloesch/pdf4eclipse/PDFPageViewer.java @@ -308,8 +308,9 @@ public void showPage(IPDFPage page) { highlight = null; boolean resize = false; - int newW = Math.round(zoomFactor*page.getWidth()); - int newH = Math.round(zoomFactor*page.getHeight()); + // always round _down_ so that the fit-to-screen commands work properly + int newW = (int) (zoomFactor*page.getWidth()); + int newH = (int) (zoomFactor*page.getHeight()); Point sz = getSize();