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

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales