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

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales