ElementBuilder

Sample C# 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. Learn more about our Xamarin SDK and PDF Editing & Manipulation Library.

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

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales