• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.10.1/pyobjc-45/pyobjc/pyobjc-framework-Quartz-2.5.1/Examples/Programming with Quartz/ConfidentialStamper/
1"""
2Add a watermark to all pages in a PDF document
3"""
4import sys, math, os
5
6from Quartz import *
7from Foundation import *
8
9def usage(name):
10    print >>sys.stderr, "Usage %s [inputfile]"%(name,)
11
12
13class MyPDFData (object):
14    pdfDoc = None
15    mediaRect = None
16
17# This is a simple function to create a CFURLRef from
18# a path to a file. The path can be relative to the
19# current directory or an absolute path.
20def createURL(path):
21    return CFURLCreateFromFileSystemRepresentation(None, path,
22                            len(path), False)
23
24# For the supplied URL and media box, create a PDF context
25# that creates a PDF file at that URL and uses supplied rect
26# as its document media box.
27def myCreatePDFContext(url, mediaBox):
28    dict = {}
29    dict[kCGPDFContextCreator] = "PDF Stamper Application"
30
31    pdfContext = CGPDFContextCreateWithURL(url, mediaBox, dict)
32    return pdfContext
33
34# For a URL corresponding to an existing PDF document on disk,
35# create a CGPDFDocumentRef and obtain the media box of the first
36# page.
37def myCreatePDFSourceDocument(url):
38    myPDFData = MyPDFData()
39    myPDFData.pdfDoc = CGPDFDocumentCreateWithURL(url)
40    if myPDFData.pdfDoc is not None:
41        # NOTE: the original code uses CGPDFDocumentGetMediaBox, but that
42        # API is deprecated and doesn't work in Leopard.
43        page = CGPDFDocumentGetPage(myPDFData.pdfDoc, 1)
44        myPDFData.mediaRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox)
45
46        # Make the media rect origin at 0,0.
47        myPDFData.mediaRect.origin.x = myPDFData.mediaRect.origin.y = 0.0
48
49    return myPDFData
50
51# Draw the source PDF document into the context and then draw the stamp PDF document
52# on top of it. When drawing the stamp on top, place it along the diagonal from the lower
53# left corner to the upper right corner and center its media rect to the center of that
54# diagonal.
55def StampWithPDFDocument(context,
56                        sourcePDFDoc,
57                        stampFileDoc, stampMediaRect):
58    numPages = CGPDFDocumentGetNumberOfPages(sourcePDFDoc)
59
60    # Loop over document pages and stamp each one appropriately.
61    for i in range(1, numPages+1):
62        # Use the page rectangle of each page from the source to compute
63        # the destination media box for each page and the location of
64        # the stamp.
65
66        # NOTE: the original code uses CGPDFDocumentGetMediaBox, but that
67        # API is deprecated and doesn't work in Leopard.
68        page = CGPDFDocumentGetPage(sourcePDFDoc, i)
69        pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox)
70
71        CGContextBeginPage(context, pageRect)
72        CGContextSaveGState(context)
73        # Clip to the media box of the page.
74        CGContextClipToRect(context, pageRect)
75        # First draw the content of the source document.
76        CGContextDrawPDFDocument(context, pageRect, sourcePDFDoc, i)
77        # Translate to center of destination rect, that is the center of
78        # the media box of content to draw on top of.
79        CGContextTranslateCTM(context,
80            pageRect.size.width/2, pageRect.size.height/2)
81        # Compute angle of the diagonal across the destination page.
82        angle = math.atan(pageRect.size.height/pageRect.size.width)
83        # Rotate by an amount so that drawn content goes along a diagonal
84        # axis across the page.
85        CGContextRotateCTM(context, angle)
86        # Move the origin so that the media box of the PDF to stamp
87        # is centered around center point of destination.
88        CGContextTranslateCTM(context,
89            -stampMediaRect.size.width/2,
90            -stampMediaRect.size.height/2)
91        # Now draw the document to stamp with on top of original content.
92        CGContextDrawPDFDocument(context, stampMediaRect,
93            stampFileDoc, 1)
94        CGContextRestoreGState(context)
95        CGContextEndPage(context)
96
97# From an input PDF document and a PDF document whose contents you
98# want to draw on top of the other, create a new PDF document
99# containing all the pages of the input document with the first page
100# of the "stamping" overlayed.
101def createStampedFileWithFile(inURL, stampURL, outURL):
102    sourceFileData = myCreatePDFSourceDocument(inURL)
103    if sourceFileData.pdfDoc is None:
104        print >>sys.stderr, "Can't create PDFDocumentRef for source input file!"
105        return
106
107    stampFileData = myCreatePDFSourceDocument(stampURL)
108    if stampFileData.pdfDoc is None:
109        CGPDFDocumentRelease(sourceFileData.pdfDoc);
110        print >>sys.stderr, "Can't create PDFDocumentRef for file to stamp with!"
111        return
112
113    pdfContext = myCreatePDFContext(outURL, sourceFileData.mediaRect)
114    if pdfContext is None:
115        print >>sys.stderr, "Can't create PDFContext for output file!"
116        return
117
118    StampWithPDFDocument(pdfContext, sourceFileData.pdfDoc,
119            stampFileData.pdfDoc, stampFileData.mediaRect)
120
121def main(args = None):
122    if args is None:
123        args = sys.argv
124
125    suffix = ".watermarked.pdf";
126    stampFileName = os.path.join(
127            os.path.dirname(__file__), "confidential.pdf")
128
129    if len(args) != 2:
130        usage(args[0])
131        return 1
132
133    inputFileName = args[1];
134    outputFileName = os.path.splitext(inputFileName)[0] + suffix
135
136    inURL = createURL(inputFileName);
137    if inURL is None:
138        print >>sys.stderr, "Couldn't create URL for input file!"
139        return 1
140
141    outURL = createURL(outputFileName)
142    if outURL is None:
143        print >>sys.stderr, "Couldn't create URL for output file!"
144        return 1
145
146    stampURL = createURL(stampFileName)
147    if stampURL is None:
148        print >>sys.stderr, "Couldn't create URL for stamping file!"
149        return 1
150
151    createStampedFileWithFile(inURL, stampURL, outURL)
152    return 0
153
154if __name__ == "__main__":
155    sys.exit(main())
156