Build, Write and Embed Elements in PDF - Python Sample Code

Sample code to use Apryse SDK's page writing API to generate new pages, embed fonts & images, and copy graphical elements from one page to another. Sample code provided in Python, C++, C#, Java, Node.js (JavaScript), PHP, Ruby and VB.

Learn more about our Server SDK and PDF Editing & Manipulation Library.

1#---------------------------------------------------------------------------------------
2# Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
3# Consult LICENSE.txt regarding license information.
4#---------------------------------------------------------------------------------------
5
6import site
7site.addsitedir("../../../PDFNetC/Lib")
8import sys
9from PDFNetPython import *
10
11sys.path.append("../../LicenseKey/PYTHON")
12from LicenseKey import *
13
14# Relative path to the folder containing the test files.
15input_path = "../../TestFiles/"
16output_path = "../../TestFiles/Output/"
17
18def main():
19 PDFNet.Initialize(LicenseKey)
20
21 doc = PDFDoc()
22
23 # ElementBuilder is used to build new Element objects
24 eb = ElementBuilder()
25 # ElementWriter is used to write Elements to the page
26 writer = ElementWriter()
27
28 # Start a new page ------------------------------------
29 page = doc.PageCreate(Rect(0, 0, 612, 794))
30
31 writer.Begin(page) # begin writing to the page
32
33 # Create an Image that can be reused in the document or on the same page.
34 img = Image.Create(doc.GetSDFDoc(), input_path + "peppers.jpg")
35
36 element = eb.CreateImage(img, Matrix2D(img.GetImageWidth()/2, -145, 20, img.GetImageHeight()/2, 200, 150))
37 writer.WritePlacedElement(element)
38
39 gstate = element.GetGState() # use the same image (just change its matrix)
40 gstate.SetTransform(200, 0, 0, 300, 50, 450)
41 writer.WritePlacedElement(element)
42
43 # use the same image again (just change its matrix)
44 writer.WritePlacedElement(eb.CreateImage(img, 300, 600, 200, -150))
45
46 writer.End() # save changes to the current page
47 doc.PagePushBack(page)
48
49 # Start a new page ------------------------------------
50 # Construct and draw a path object using different styles
51 page = doc.PageCreate(Rect(0, 0, 612, 794))
52
53 writer.Begin(page) # begin writing to this page
54 eb.Reset() # Reset the GState to default
55
56 eb.PathBegin() # start constructing the path
57 eb.MoveTo(306, 396)
58 eb.CurveTo(681, 771, 399.75, 864.75, 306, 771)
59 eb.CurveTo(212.25, 864.75, -69, 771, 306, 396)
60 eb.ClosePath()
61 element = eb.PathEnd() # the path is now finished
62 element.SetPathFill(True) # the path should be filled
63
64 # Set the path color space and color
65 gstate = element.GetGState()
66 gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK())
67 gstate.SetFillColor(ColorPt(1, 0, 0, 0)) # cyan
68 gstate.SetTransform(0.5, 0, 0, 0.5, -20, 300)
69 writer.WritePlacedElement(element)
70
71 # Draw the same path using a different stroke color
72 element.SetPathStroke(True) # this path is should be filled and stroked
73 gstate.SetFillColor(ColorPt(0, 0, 1, 0)) # yellow
74 gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB())
75 gstate.SetStrokeColor(ColorPt(1, 0, 0)) # red
76 gstate.SetTransform(0.5, 0, 0, 0.5, 280, 300)
77 gstate.SetLineWidth(20)
78 writer.WritePlacedElement(element)
79
80 # Draw the same path with a given dash pattern
81 element.SetPathFill(False) # this path should be only stroked
82
83 gstate.SetStrokeColor(ColorPt(0,0,1)) # blue
84 gstate.SetTransform(0.5, 0, 0, 0.5, 280, 0)
85 dash_pattern = VectorDouble()
86 dash_pattern.append(30)
87 gstate.SetDashPattern(dash_pattern, 0)
88 writer.WritePlacedElement(element)
89
90 # Use the path as a clipping path
91 writer.WriteElement(eb.CreateGroupBegin()) # Save the graphics state
92 # Start constructing the new path (the old path was lost when we created
93 # a new Element using CreateGroupBegin()).
94 eb.PathBegin()
95 eb.MoveTo(306, 396)
96 eb.CurveTo(681, 771, 399.75, 864.75, 306, 771)
97 eb.CurveTo(212.25, 864.75, -69, 771, 306, 396)
98 eb.ClosePath()
99 element = eb.PathEnd() # path is now constructed
100 element.SetPathClip(True) # this path is a clipping path
101 element.SetPathStroke(True) # this path should be filled and stroked
102 gstate = element.GetGState()
103 gstate.SetTransform(0.5, 0, 0, 0.5, -20, 0)
104
105 writer.WriteElement(element)
106
107 writer.WriteElement(eb.CreateImage(img, 100, 300, 400, 600))
108
109 writer.WriteElement(eb.CreateGroupEnd()) # Restore the graphics state
110
111 writer.End() # save changes to the current page
112 doc.PagePushBack(page)
113
114 # Start a new page ------------------------------------
115 page = doc.PageCreate(Rect(0, 0, 612, 794))
116
117 writer.Begin(page) # begin writing to this page
118 eb.Reset() # Reset the GState to default
119
120 # Begin writing a block of text
121 element = eb.CreateTextBegin(Font.Create(doc.GetSDFDoc(), Font.e_times_roman), 12)
122 writer.WriteElement(element)
123
124 element = eb.CreateTextRun("Hello World!")
125 element.SetTextMatrix(10, 0, 0, 10, 0, 600)
126 element.GetGState().SetLeading(15) # Set the spacing between lines
127 writer.WriteElement(element)
128
129 writer.WriteElement(eb.CreateTextNewLine()) # New line
130
131 element = eb.CreateTextRun("Hello World!")
132 gstate = element.GetGState()
133 gstate.SetTextRenderMode(GState.e_stroke_text)
134 gstate.SetCharSpacing(-1.25)
135 gstate.SetWordSpacing(-1.25)
136 writer.WriteElement(element)
137
138 writer.WriteElement(eb.CreateTextNewLine()) # New line
139
140 element = eb.CreateTextRun("Hello World!")
141 gstate = element.GetGState()
142 gstate.SetCharSpacing(0)
143 gstate.SetWordSpacing(0)
144 gstate.SetLineWidth(3)
145 gstate.SetTextRenderMode(GState.e_fill_stroke_text)
146 gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB())
147 gstate.SetStrokeColor(ColorPt(1, 0, 0)) # red
148 gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK())
149 gstate.SetFillColor(ColorPt(1, 0, 0, 0)) # cyan
150 writer.WriteElement(element)
151
152 writer.WriteElement(eb.CreateTextNewLine()) # New line
153
154 # Set text as a clipping path to the image.
155 element = eb.CreateTextRun("Hello World!")
156 gstate = element.GetGState()
157 gstate.SetTextRenderMode(GState.e_clip_text)
158 writer.WriteElement(element)
159
160 # Finish the block of text
161 writer.WriteElement(eb.CreateTextEnd())
162
163 # Draw an image that will be clipped by the above text
164 writer.WriteElement(eb.CreateImage(img, 10, 100, 1300, 720))
165
166 writer.End() # save changes to the current page
167 doc.PagePushBack(page)
168
169 # Start a new page ------------------------------------
170 #
171 # The example illustrates how to embed the external font in a PDF document.
172 # The example also shows how ElementReader can be used to copy and modify
173 # Elements between pages.
174
175 reader = ElementReader()
176
177 # Start reading Elements from the last page. We will copy all Elements to
178 # a new page but will modify the font associated with text.
179 reader.Begin(doc.GetPage(doc.GetPageCount()))
180
181 page = doc.PageCreate(Rect(0, 0, 1300, 794))
182
183 writer.Begin(page) # begin writing to this page
184 eb.Reset() # Reset the GState to default
185
186 # Embed an external font in the document.
187 font = Font.CreateTrueTypeFont(doc.GetSDFDoc(), (input_path + "font.ttf"))
188
189 element = reader.Next()
190 while element != None: # Read page contents
191 if element.GetType() == Element.e_text:
192 element.GetGState().SetFont(font, 12)
193 writer.WriteElement(element)
194 element = reader.Next()
195
196 reader.End()
197 writer.End() # save changes to the current page
198 doc.PagePushBack(page)
199
200 # Start a new page ------------------------------------
201 #
202 # The example illustrates how to embed the external font in a PDF document.
203 # The example also shows how ElementReader can be used to copy and modify
204 # Elements between pages.
205
206 # Start reading Elements from the last page. We will copy all Elements to
207 # a new page but will modify the font associated with text.
208 reader.Begin(doc.GetPage(doc.GetPageCount()))
209
210 page = doc.PageCreate(Rect(0, 0, 1300, 794))
211
212 writer.Begin(page) # begin writing to this page
213 eb.Reset() # Reset the GState to default
214
215 # Embed an external font in the document.
216 font2 = Font.CreateType1Font(doc.GetSDFDoc(), (input_path + "Misc-Fixed.pfa"))
217
218 element = reader.Next()
219 while element != None:
220 if element.GetType() == Element.e_text:
221 element.GetGState().SetFont(font2, 12)
222 writer.WriteElement(element)
223 element = reader.Next()
224
225 reader.End()
226 writer.End() # save changes to the current page
227 doc.PagePushBack(page)
228
229 # Start a new page ------------------------------------
230 page = doc.PageCreate()
231 writer.Begin(page) # begin writing to this page
232 eb.Reset() # Reset the GState to default
233
234 # Begin writing a block of text
235 element = eb.CreateTextBegin(Font.Create(doc.GetSDFDoc(), Font.e_times_roman), 12)
236 element.SetTextMatrix(1.5, 0, 0, 1.5, 50, 600)
237 element.GetGState().SetLeading(15) # Set the spacing between lines
238 writer.WriteElement(element)
239
240 para = ("A PDF text object consists of operators that can show "
241 "text strings, move the text position, and set text state and certain "
242 "other parameters. In addition, there are three parameters that are "
243 "defined only within a text object and do not persist from one text "
244 "object to the next: Tm, the text matrix, Tlm, the text line matrix, "
245 "Trm, the text rendering matrix, actually just an intermediate result "
246 "that combines the effects of text state parameters, the text matrix "
247 "(Tm), and the current transformation matrix")
248
249 para_end = len(para)
250 text_run = 0
251
252 para_width = 300 # paragraph width is 300 units
253 cur_width = 0
254
255 while text_run < para_end:
256 text_run_end = para.find(' ', text_run)
257 if text_run_end < 0:
258 text_run_end = para_end - 1
259
260 text = para[text_run:text_run_end+1]
261 element = eb.CreateTextRun(text)
262 if cur_width + element.GetTextLength() < para_width:
263 writer.WriteElement(element)
264 cur_width = cur_width + element.GetTextLength()
265 else:
266 writer.WriteElement(eb.CreateTextNewLine()) # new line
267 element = eb.CreateTextRun(text)
268 cur_width = element.GetTextLength()
269 writer.WriteElement(element)
270 text_run = text_run_end + 1
271
272 # -----------------------------------------------------------------------
273 # The following code snippet illustrates how to adjust spacing between
274 # characters (text runs).
275 element = eb.CreateTextNewLine()
276 writer.WriteElement(element) # Skip 2 lines
277 writer.WriteElement(element)
278
279 writer.WriteElement(eb.CreateTextRun("An example of space adjustments between inter-characters:"))
280 writer.WriteElement(eb.CreateTextNewLine())
281
282 # Write string "AWAY" without space adjustments between characters.
283 element = eb.CreateTextRun("AWAY")
284 writer.WriteElement(element)
285
286 writer.WriteElement(eb.CreateTextNewLine())
287
288 # Write string "AWAY" with space adjustments between characters.
289 element = eb.CreateTextRun("A")
290 writer.WriteElement(element)
291
292 element = eb.CreateTextRun("W")
293 element.SetPosAdjustment(140)
294 writer.WriteElement(element)
295
296 element = eb.CreateTextRun("A")
297 element.SetPosAdjustment(140)
298 writer.WriteElement(element)
299
300 element = eb.CreateTextRun("Y again")
301 element.SetPosAdjustment(115)
302 writer.WriteElement(element)
303
304 # Draw the same strings using direct content output...
305 writer.Flush() # flush pending Element writing operations.
306
307 # You can also write page content directly to the content stream using
308 # ElementWriter.WriteString(...) and ElementWriter.WriteBuffer(...) methods.
309 # Note that if you are planning to use these functions you need to be familiar
310 # with PDF page content operators (see Appendix A in PDF Reference Manual).
311 # Because it is easy to make mistakes during direct output we recommend that
312 # you use ElementBuilder and Element interface instead.
313
314 writer.WriteString("T* T* ") # Skip 2 lines
315 writer.WriteString("(Direct output to PDF page content stream:) Tj T* ")
316 writer.WriteString("(AWAY) Tj T* ")
317 writer.WriteString("[(A)140(W)140(A)115(Y again)] TJ ")
318
319 # Finish the block of text
320 writer.WriteElement(eb.CreateTextEnd())
321
322 writer.End() # save changes to the current page
323 doc.PagePushBack(page)
324
325 # Start a new page ------------------------------------
326
327 # Image Masks
328 #
329 # In the opaque imaging model, images mark all areas they occupy on the page as
330 # if with opaque paint. All portions of the image, whether black, white, gray,
331 # or color, completely obscure any marks that may previously have existed in the
332 # same place on the page.
333 # In the graphic arts industry and page layout applications, however, it is common
334 # to crop or 'mask out' the background of an image and then place the masked image
335 # on a different background, allowing the existing background to show through the
336 # masked areas. This sample illustrates how to use image masks.
337
338 page = doc.PageCreate()
339 writer.Begin(page) # begin writing to the page
340
341 # Create the Image Mask
342 imgf = MappedFile(input_path + "imagemask.dat")
343 mask_read = FilterReader(imgf)
344
345 device_gray = ColorSpace.CreateDeviceGray()
346 mask = Image.Create(doc.GetSDFDoc(), mask_read, 64, 64, 1, device_gray, Image.e_ascii_hex)
347
348 mask.GetSDFObj().PutBool("ImageMask", True)
349
350 element = eb.CreateRect(0, 0, 612, 794)
351 element.SetPathStroke(False)
352 element.SetPathFill(True)
353 element.GetGState().SetFillColorSpace(device_gray)
354 element.GetGState().SetFillColor(ColorPt(0.8))
355 writer.WritePlacedElement(element)
356
357 element = eb.CreateImage(mask, Matrix2D(200, 0, 0, -200, 40, 680))
358 element.GetGState().SetFillColor(ColorPt(0.1))
359 writer.WritePlacedElement(element)
360
361 element.GetGState().SetFillColorSpace(ColorSpace.CreateDeviceRGB())
362 element.GetGState().SetFillColor(ColorPt(1, 0, 0))
363 element = eb.CreateImage(mask, Matrix2D(200, 0, 0, -200, 320, 680))
364 writer.WritePlacedElement(element)
365
366 element.GetGState().SetFillColor(ColorPt(0, 1, 0))
367 element = eb.CreateImage(mask, Matrix2D(200, 0, 0, -200, 40, 380))
368 writer.WritePlacedElement(element)
369
370 # This sample illustrates Explicit Masking.
371 img = Image.Create(doc.GetSDFDoc(), (input_path + "peppers.jpg"))
372
373 # mask is the explicit mask for the primary (base) image
374 img.SetMask(mask)
375
376 element = eb.CreateImage(img, Matrix2D(200, 0, 0, -200, 320, 380))
377 writer.WritePlacedElement(element)
378
379 writer.End() # save changes to the current page
380 doc.PagePushBack(page)
381
382 # Transparency sample ----------------------------------
383
384 # Start a new page -------------------------------------
385 page = doc.PageCreate()
386 writer.Begin(page) # begin writing to this page
387 eb.Reset() # Reset the GState to default
388
389 # Write some transparent text at the bottom of the page.
390 element = eb.CreateTextBegin(Font.Create(doc.GetSDFDoc(), Font.e_times_roman), 100)
391
392 # Set the text knockout attribute. Text knockout must be set outside of
393 # the text group.
394 gstate = element.GetGState()
395 gstate.SetTextKnockout(False)
396 gstate.SetBlendMode(GState.e_bl_difference)
397 writer.WriteElement(element)
398
399 element = eb.CreateTextRun("Transparency")
400 element.SetTextMatrix(1, 0, 0, 1, 30, 30)
401 gstate = element.GetGState()
402 gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK())
403 gstate.SetFillColor(ColorPt(1, 0, 0, 0))
404
405 gstate.SetFillOpacity(0.5)
406 writer.WriteElement(element)
407
408 # Write the same text on top the old; shifted by 3 points
409 element.SetTextMatrix(1, 0, 0, 1, 33, 33)
410 gstate.SetFillColor(ColorPt(0, 1, 0, 0))
411 gstate.SetFillOpacity(0.5)
412
413 writer.WriteElement(element)
414 writer.WriteElement(eb.CreateTextEnd())
415
416 # Draw three overlapping transparent circles.
417 eb.PathBegin() # start constructing the path
418 eb.MoveTo(459.223, 505.646)
419 eb.CurveTo(459.223, 415.841, 389.85, 343.04, 304.273, 343.04)
420 eb.CurveTo(218.697, 343.04, 149.324, 415.841, 149.324, 505.646)
421 eb.CurveTo(149.324, 595.45, 218.697, 668.25, 304.273, 668.25)
422 eb.CurveTo(389.85, 668.25, 459.223, 595.45, 459.223, 505.646)
423 element = eb.PathEnd()
424 element.SetPathFill(True)
425
426 gstate = element.GetGState()
427 gstate.SetFillColorSpace(ColorSpace.CreateDeviceRGB())
428 gstate.SetFillColor(ColorPt(0, 0, 1)) # Blue Circle
429
430 gstate.SetBlendMode(GState.e_bl_normal)
431 gstate.SetFillOpacity(0.5)
432 writer.WriteElement(element)
433
434 # Translate relative to the Blue Circle
435 gstate.SetTransform(1, 0, 0, 1, 113, -185)
436 gstate.SetFillColor(ColorPt(0, 1, 0)) # Green Circle
437 gstate.SetFillOpacity(0.5)
438 writer.WriteElement(element)
439
440 # Translate relative to the Green Circle
441 gstate.SetTransform(1, 0, 0, 1, -220, 0)
442 gstate.SetFillColor(ColorPt(1, 0, 0)) # Red Circle
443 gstate.SetFillOpacity(0.5)
444 writer.WriteElement(element)
445
446 writer.End() # save changes to the current page
447 doc.PagePushBack(page)
448
449 # End page ------------------------------------
450
451 doc.Save((output_path + "element_builder.pdf"), SDFDoc.e_remove_unused)
452 doc.Close()
453 PDFNet.Terminate()
454 print("Done. Result saved in element_builder.pdf...")
455
456if __name__ == '__main__':
457 main()

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales