Jens Nöckel's Homepage

Computer notes home

Table of contents

Copying PDF selections from Preview to Keynote (iWork) under Lepoard

The crop you sow and the crop you reap

If you want to copy snippets of a PDF document into Apple's Keynote presentation software (or any other iWork application, for that matter - i.e., Pages and Numbers), there is a new problem that "cropped" up with the upgrade to Leopard: a rectangle selected and copied within Peview doesn't get pasted into Keynote in its cropped form. The pasted PDF content in Keynote looks as if you never cropped anything at all.

The reason is explained by Martin Costabel, and until Apple fixes this you'll have to put up with some inconvenience to work around the problem. As of Leopard 10.5.5, this problem hasn't been resolved yet.

On this page you can download a fix for this cropping issue. I packaged it in different flavors, so you should look through the following notes to see which solution you like best. My initial solution is an Applescript that requires an additional piece of software (ghostscript). In response to a suggestion by Ken Drake at KeynoteUser.com, I'm also posting a second version of that Applescript which does not require any additonal software. If you don't know what ghostscript is, just skip to the second version. Finally, you may prefer the even easier-to-install Application bundle.

Ghostscript required

The script can be downloaded as
clipPDF-gs-1.0.zip
Here are the steps to make this work painlessly:

If the PDF fix is successful, the script remains completely silent so as not to interfere with the workflow. I emphasize this so you don't get suspicious if nothing seems to happen after activating the menu item. If there is a problem (e.g., if there was no PDF on the clipboard), the script should tell you so with an Alert box.

If there is an error converting the PDF, the most likely reason is that gs hasn't been found. Make sure you set up the PATH as mentioned above. Alternatively, you can edit the python script to hard-wire the path to ghostscript. This is done by adding the path to the variable gsBin. Another potential cause of errors is an outdated version of ghostscript - use version 8.61 or above.

The python script is shown below:
#!/usr/bin/python
import os,sys,tempfile
from AppKit import *
from Foundation import *

rr=64
gsBin = "gs"
board=NSPasteboard.generalPasteboard()
result = board.dataForType_(NSPDFPboardType)
if result:
        tmpdir = tempfile.mkdtemp("","clipPDF","/tmp")
        inname=tmpdir+"/infile.pdf"
        outname=tmpdir+"/outfile.pdf"
        result.writeToFile_atomically_(inname,1)
#
#       ghostscript (gs) is used to rewrite the PDF file. You may have to hard-code the path in gsBin:
#
        rr=os.spawnlp(os.P_WAIT,gsBin,gsBin,"-sDEVICE=pdfwrite", "-sOutputFile="+outname, "-q", "-dbatch", "-dNOPAUSE", inname, "-c", "quit")
        if rr==0:
                content=NSData.dataWithContentsOfFile_(outname)
                board.declareTypes_owner_([NSPDFPboardType], None)
                board.setData_forType_(content, NSPDFPboardType)
                os.remove(outname)
        os.remove(inname)
        os.rmdir(tmpdir)
sys.exit(rr)

If you want to make modifications to the script, you can find it by selecting Show Contents from the contextual Finder menu of the clipPDF bundle. You can then edit Contents/Resources/Scripts/clipPDF.

No ghostscript required

For users who don't want to install ghostscript, here is another version of the script that requires no addional software at all. It does the job just fine, if all you care about is pasting into Keynote. With ghostscript, you get more peace of mind that you have a standards-compliant PDF on the clipboard, but it may not be worth the additional installation effort if you have no other use for gs.

The script below simply performs a search for "/ArtBox [...]" and deletes that entry from the PDF file.

The script can be downloaded as
clipPDF-noGS-1.1.zip

The installation instructions are simpler than above:

As with the other version: If the PDF fix is successful, the script remains completely silent so as not to interfere with the workflow. I emphasize this so you don't get suspicious if nothing seems to happen after activating the menu item. If there is a problem (e.g., if there was no PDF on the clipboard), the script should tell you so with an Alert box.

The Python code is shown here:
#!/usr/bin/python
#
#   clipPDF version 1.1
#
import os,sys,tempfile,re
from AppKit import *
from Foundation import *

rr=64
ruleT = re.compile(r"(\s*\/ArtBox\s*\[.*?\]\s*)", re.DOTALL)
board=NSPasteboard.generalPasteboard()
result = board.dataForType_(NSPDFPboardType)
if result:
        tmpdir = tempfile.mkdtemp("","clipPDF","/tmp")
        inname=tmpdir+"/infile.pdf"
        outname=tmpdir+"/outfile.pdf"
        result.writeToFile_atomically_(inname,1)
        #
        #   Writing to a file and re-opening seems to be the easiest
        #   way to avoid type conversion problems for the PDF binary file.
        #   If I wanted to avoid this, I'd have to additionally
        #   import PyObjCTools.Conversion, so the net timing is equal.
        #
        try:
                resultFile=open(inname,"r")
                result2 = resultFile.read()
                resultFile.close()
        except:
                rr=74
        else:
                content = ruleT.sub(" ",result2)
                try:
                        resultFile=open(outname,"w")
                        resultFile.write(content)
                        resultFile.close()
                except:
                        rr=74
                else:
                        content=NSData.dataWithContentsOfFile_(outname)
                        board.declareTypes_owner_([NSPDFPboardType], None)
                        board.setData_forType_(content, NSPDFPboardType)
                        os.remove(outname)
                        rr=0
        os.remove(inname)
        os.rmdir(tmpdir)
sys.exit(rr)

Windowless Application, no ghostscript

For some people it may be inconvenient to access clipPDF via the AppleScript menu. That's basically a matter of taste, but in case you prefer having the same functionality running as an Application that you can keep on the Dock, here is the solution:
clipPDFservant.zip
This does exactly the same as clipPDF, but there is zero installation required. I'd recommend dragging the clipPDFservant Application to a folder such as Applications or Utilities.

When you have a PDF clipping on the clipboard, launch clipPDFservant. It will do its job and stay open. Next time you want to use it, click on its icon in the Dock and it will do its job again. The Application has no window, but you launch and quit it the way you would for any other Application.

One thing that this version doesn't do yet is to re-execute the clipPDF script when it's selected by Command-Tab while already running. You actually have to click on its icon to stir it into action.

For reference, here is a thread on the Apple discussion forum where these modifications took shape.

Revisions

clipPDFservant-1.0
Initial version (04-13-2008). Same as clipPDF-1.1, but run as an Application.
clipPDF-1.1
Current version (04-11-2008). This revised version stays silent even when the PDF on the clipboard required no fixing (e.g. if you copied from LaTeXiT).
clipPDF-1.0
Initial version of clipPDF (04-05-2008).

noeckel@uoregon.edu
Last modified: Tue Sep 16 21:38:47 PDT 2008