ElementBuilder

Sample Java 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 Android SDK and PDF Editing & Manipulation Library.

1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6package com.pdftron.android.pdfnetsdksamples.samples;
7
8import com.pdftron.android.pdfnetsdksamples.OutputListener;
9import com.pdftron.android.pdfnetsdksamples.PDFNetSample;
10import com.pdftron.android.pdfnetsdksamples.R;
11import com.pdftron.android.pdfnetsdksamples.util.Utils;
12import com.pdftron.common.Matrix2D;
13import com.pdftron.filters.MappedFile;
14import com.pdftron.pdf.ColorPt;
15import com.pdftron.pdf.ColorSpace;
16import com.pdftron.pdf.Element;
17import com.pdftron.pdf.ElementBuilder;
18import com.pdftron.pdf.ElementReader;
19import com.pdftron.pdf.ElementWriter;
20import com.pdftron.pdf.Font;
21import com.pdftron.pdf.GState;
22import com.pdftron.pdf.Image;
23import com.pdftron.pdf.PDFDoc;
24import com.pdftron.pdf.Page;
25import com.pdftron.pdf.Rect;
26import com.pdftron.sdf.SDFDoc;
27
28import java.io.File;
29import java.io.FileInputStream;
30import java.io.InputStream;
31import java.util.ArrayList;
32
33public class ElementBuilderTest extends PDFNetSample {
34
35 private static OutputListener mOutputListener;
36
37 private static ArrayList<String> mFileList = new ArrayList<>();
38
39 public ElementBuilderTest() {
40 setTitle(R.string.sample_elementbuilder_title);
41 setDescription(R.string.sample_elementbuilder_description);
42 }
43
44 @Override
45 public void run(OutputListener outputListener) {
46 super.run(outputListener);
47 mOutputListener = outputListener;
48 mFileList.clear();
49 printHeader(outputListener);
50
51 InputStream stream = null;
52 try (PDFDoc doc = new PDFDoc()) {
53 ElementBuilder eb = new ElementBuilder(); // ElementBuilder is used to build new
54 // Element objects
55 ElementWriter writer = new ElementWriter(); // ElementWriter is used to write
56 // Elements to the page
57
58 Element element;
59 GState gstate;
60
61 // Start a new page ------------------------------------
62 Page page = doc.pageCreate(new Rect(0, 0, 612, 794));
63
64 writer.begin(page); // begin writing to the page
65
66 // Create an Image that can be reused in the document or on the
67 // same page.
68 Image img = Image.create(doc.getSDFDoc(), (Utils.getAssetTempFile(INPUT_PATH + "peppers.jpg").getAbsolutePath()));
69
70 element = eb.createImage(img, new Matrix2D(img.getImageWidth() / 2, -145, 20, img.getImageHeight() / 2, 200, 150));
71 writer.writePlacedElement(element);
72
73 gstate = element.getGState(); // use the same image (just
74 // change its matrix)
75 gstate.setTransform(200, 0, 0, 300, 50, 450);
76 writer.writePlacedElement(element);
77
78 // use the same image again (just change its matrix).
79 writer.writePlacedElement(eb.createImage(img, 300, 600, 200, -150));
80
81 writer.end(); // save changes to the current page
82 doc.pagePushBack(page);
83
84 // Start a new page ------------------------------------
85 // Construct and draw a path object using different styles
86 page = doc.pageCreate(new Rect(0, 0, 612, 794));
87
88 writer.begin(page); // begin writing to this page
89 eb.reset(); // Reset the GState to default
90
91 eb.pathBegin(); // start constructing the path
92 eb.moveTo(306, 396);
93 eb.curveTo(681, 771, 399.75, 864.75, 306, 771);
94 eb.curveTo(212.25, 864.75, -69, 771, 306, 396);
95 eb.closePath();
96 element = eb.pathEnd(); // the path is now finished
97 element.setPathFill(true); // the path should be filled
98
99 // Set the path color space and color
100 gstate = element.getGState();
101 gstate.setFillColorSpace(ColorSpace.createDeviceCMYK());
102 gstate.setFillColor(new ColorPt(1, 0, 0, 0)); // cyan
103 gstate.setTransform(0.5, 0, 0, 0.5, -20, 300);
104 writer.writePlacedElement(element);
105
106 // Draw the same path using a different stroke color
107 element.setPathStroke(true); // this path is should be
108 // filled and stroked
109 gstate.setFillColor(new ColorPt(0, 0, 1, 0)); // yellow
110 gstate.setStrokeColorSpace(ColorSpace.createDeviceRGB());
111 gstate.setStrokeColor(new ColorPt(1, 0, 0)); // red
112 gstate.setTransform(0.5, 0, 0, 0.5, 280, 300);
113 gstate.setLineWidth(20);
114 writer.writePlacedElement(element);
115
116 // Draw the same path with with a given dash pattern
117 element.setPathFill(false); // this path is should be only
118 // stroked
119 gstate.setStrokeColor(new ColorPt(0, 0, 1)); // blue
120 gstate.setTransform(0.5, 0, 0, 0.5, 280, 0);
121 double[] dash_pattern = {30};
122 gstate.setDashPattern(dash_pattern, 0);
123 writer.writePlacedElement(element);
124
125 // Use the path as a clipping path
126 writer.writeElement(eb.createGroupBegin()); // Save the graphics
127 // state
128 // Start constructing the new path (the old path was lost when
129 // we created
130 // a new Element using CreateGroupBegin()).
131 eb.pathBegin();
132 eb.moveTo(306, 396);
133 eb.curveTo(681, 771, 399.75, 864.75, 306, 771);
134 eb.curveTo(212.25, 864.75, -69, 771, 306, 396);
135 eb.closePath();
136 element = eb.pathEnd(); // path is now constructed
137 element.setPathClip(true); // this path is a clipping path
138 element.setPathStroke(true); // this path should be
139 // filled and stroked
140 gstate = element.getGState();
141 gstate.setTransform(0.5, 0, 0, 0.5, -20, 0);
142
143 writer.writeElement(element);
144
145 writer.writeElement(eb.createImage(img, 100, 300, 400, 600));
146
147 writer.writeElement(eb.createGroupEnd()); // Restore the
148 // graphics state
149
150 writer.end(); // save changes to the current page
151 doc.pagePushBack(page);
152
153 // Start a new page ------------------------------------
154 page = doc.pageCreate(new Rect(0, 0, 612, 794));
155
156 writer.begin(page); // begin writing to this page
157 eb.reset(); // Reset the GState to default
158
159 // Begin writing a block of text
160 element = eb.createTextBegin(Font.create(doc, Font.e_times_roman), 12);
161 writer.writeElement(element);
162
163 element = eb.createTextRun("Hello World!");
164 element.setTextMatrix(10, 0, 0, 10, 0, 600);
165 element.getGState().setLeading(15); // Set the spacing
166 // between lines
167 writer.writeElement(element);
168
169 writer.writeElement(eb.createTextNewLine()); // New line
170
171 element = eb.createTextRun("Hello World!");
172 gstate = element.getGState();
173 gstate.setTextRenderMode(GState.e_stroke_text);
174 gstate.setCharSpacing(-1.25);
175 gstate.setWordSpacing(-1.25);
176 writer.writeElement(element);
177
178 writer.writeElement(eb.createTextNewLine()); // New line
179
180 element = eb.createTextRun("Hello World!");
181 gstate = element.getGState();
182 gstate.setCharSpacing(0);
183 gstate.setWordSpacing(0);
184 gstate.setLineWidth(3);
185 gstate.setTextRenderMode(GState.e_fill_stroke_text);
186 gstate.setStrokeColorSpace(ColorSpace.createDeviceRGB());
187 gstate.setStrokeColor(new ColorPt(1, 0, 0)); // red
188 gstate.setFillColorSpace(ColorSpace.createDeviceCMYK());
189 gstate.setFillColor(new ColorPt(1, 0, 0, 0)); // cyan
190 writer.writeElement(element);
191
192 writer.writeElement(eb.createTextNewLine()); // New line
193
194 // Set text as a clipping path to the image.
195 element = eb.createTextRun("Hello World!");
196 gstate = element.getGState();
197 gstate.setTextRenderMode(GState.e_clip_text);
198 writer.writeElement(element);
199
200 // Finish the block of text
201 writer.writeElement(eb.createTextEnd());
202
203 // Draw an image that will be clipped by the above text
204 writer.writeElement(eb.createImage(img, 10, 100, 1300, 720));
205
206 writer.end(); // save changes to the current page
207 doc.pagePushBack(page);
208
209 // Start a new page ------------------------------------
210 //
211 // The example illustrates how to embed the external font in a
212 // PDF document.
213 // The example also shows how ElementReader can be used to copy
214 // and modify
215 // Elements between pages.
216
217 ElementReader reader = new ElementReader();
218
219 // Start reading Elements from the last page. We will copy all
220 // Elements to
221 // a new page but will modify the font associated with text.
222 reader.begin((doc.getPage(doc.getPageCount())));
223
224 page = doc.pageCreate(new Rect(0, 0, 1300, 794));
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 Font font;
231 File file = Utils.getAssetTempFile(INPUT_PATH + "font.ttf");
232 stream = new FileInputStream(file);
233 font = Font.createTrueTypeFont(doc, stream);
234 //Alternatively, the font can be created from the file path.
235 //font = Font.createTrueTypeFont(doc, (Utils.getAssetTempFile(INPUT_PATH + "font.ttf").getAbsolutePath()));
236
237 while ((element = reader.next()) != null) // Read page
238 // contents
239 {
240 if (element.getType() == Element.e_text) {
241 element.getGState().setFont(font, 12);
242 }
243
244 writer.writeElement(element);
245 }
246
247 reader.end();
248 writer.end(); // save changes to the current page
249
250 doc.pagePushBack(page);
251
252 // Start a new page ------------------------------------
253 //
254 // The example illustrates how to embed the external font in a
255 // PDF document.
256 // The example also shows how ElementReader can be used to copy
257 // and modify
258 // Elements between pages.
259
260 // Start reading Elements from the last page. We will copy all
261 // Elements to
262 // a new page but will modify the font associated with text.
263 reader.begin(((doc.getPage(doc.getPageCount()))));
264
265 page = doc.pageCreate(new Rect(0, 0, 1300, 794));
266
267 writer.begin(page); // begin writing to this page
268 eb.reset(); // Reset the GState to default
269
270 // Embed an external font in the document.
271 Font font2 = Font.createType1Font(doc, (Utils.getAssetTempFile(INPUT_PATH + "Misc-Fixed.pfa").getAbsolutePath()));
272
273 while ((element = reader.next()) != null) // Read page contents
274 {
275 if (element.getType() == Element.e_text) {
276 element.getGState().setFont(font2, 12);
277 }
278
279 writer.writeElement(element);
280 }
281
282 reader.end();
283 writer.end(); // save changes to the current page
284 doc.pagePushBack(page);
285
286 // Start a new page ------------------------------------
287 page = doc.pageCreate();
288 writer.begin(page); // begin writing to this page
289 eb.reset(); // Reset the GState to default
290
291 // Begin writing a block of text
292 element = eb.createTextBegin(Font.create(doc, Font.e_times_roman), 12);
293 element.setTextMatrix(1.5, 0, 0, 1.5, 50, 600);
294 element.getGState().setLeading(15); // Set the spacing between
295 // lines
296 writer.writeElement(element);
297
298 String para = "A PDF text object consists of operators that can show " +
299 "text strings, move the text position, and set text state and certain " +
300 "other parameters. In addition, there are three parameters that are " +
301 "defined only within a text object and do not persist from one text " +
302 "object to the next: Tm, the text matrix, Tlm, the text line matrix, " +
303 "Trm, the text rendering matrix, actually just an intermediate result " +
304 "that combines the effects of text state parameters, the text matrix " +
305 "(Tm), and the current transformation matrix";
306
307 int para_end = para.length();
308 int text_run = 0;
309 int text_run_end;
310
311 double para_width = 300; // paragraph width is 300 units
312 double cur_width = 0;
313
314 while (text_run < para_end) {
315 text_run_end = para.indexOf(' ', text_run);
316 if (text_run_end < 0)
317 text_run_end = para_end - 1;
318
319 String text = para.substring(text_run, text_run_end + 1);
320 element = eb.createTextRun(text);
321 if (cur_width + element.getTextLength() < para_width) {
322 writer.writeElement(element);
323 cur_width += element.getTextLength();
324 } else {
325 writer.writeElement(eb.createTextNewLine()); // New
326 text = para.substring(text_run, text_run_end + 1); // line
327 element = eb.createTextRun(text);
328 cur_width = element.getTextLength();
329 writer.writeElement(element);
330 }
331
332 text_run = text_run_end + 1;
333 }
334
335 // -----------------------------------------------------------------------
336 // The following code snippet illustrates how to adjust
337 // spacing between
338 // characters (text runs).
339 element = eb.createTextNewLine();
340 writer.writeElement(element); // Skip 2 lines
341 writer.writeElement(element);
342
343 writer.writeElement(eb.createTextRun("An example of space adjustments between inter-characters:"));
344 writer.writeElement(eb.createTextNewLine());
345
346 // Write string "AWAY" without space adjustments between
347 // characters.
348 element = eb.createTextRun("AWAY");
349 writer.writeElement(element);
350
351 writer.writeElement(eb.createTextNewLine());
352
353 // Write string "AWAY" with space adjustments between
354 // characters.
355 element = eb.createTextRun("A");
356 writer.writeElement(element);
357
358 element = eb.createTextRun("W");
359 element.setPosAdjustment(140);
360 writer.writeElement(element);
361
362 element = eb.createTextRun("A");
363 element.setPosAdjustment(140);
364 writer.writeElement(element);
365
366 element = eb.createTextRun("Y again");
367 element.setPosAdjustment(115);
368 writer.writeElement(element);
369
370 // Draw the same strings using direct content output...
371 writer.flush(); // flush pending Element writing operations.
372
373 // You can also write page content directly to the content
374 // stream using
375 // ElementWriter.WriteString(...) and
376 // ElementWriter.WriteBuffer(...) methods.
377 // Note that if you are planning to use these functions you need
378 // to be familiar
379 // with PDF page content operators (see Appendix A in PDF
380 // Reference Manual).
381 // Because it is easy to make mistakes during direct output we
382 // recommend that
383 // you use ElementBuilder and Element interface instead.
384
385 writer.writeString("T* T* "); // Skip 2 lines
386 writer.writeString("(Direct output to PDF page content stream:) Tj T* ");
387 writer.writeString("(AWAY) Tj T* ");
388 writer.writeString("[(A)140(W)140(A)115(Y again)] TJ ");
389
390 // Finish the block of text
391 writer.writeElement(eb.createTextEnd());
392
393 writer.end(); // save changes to the current page
394 doc.pagePushBack(page);
395
396 // Start a new page ------------------------------------
397
398 // Image Masks
399 //
400 // In the opaque imaging model, images mark all areas they
401 // occupy on the page as
402 // if with opaque paint. All portions of the image, whether
403 // black, white, gray,
404 // or color, completely obscure any marks that may previously
405 // have existed in the
406 // same place on the page.
407 // In the graphic arts industry and page layout applications,
408 // however, it is common
409 // to crop or 'mask out' the background of an image and then
410 // place the masked image
411 // on a different background, allowing the existing background
412 // to show through the
413 // masked areas. This sample illustrates how to use image masks.
414
415 page = doc.pageCreate();
416 writer.begin(page); // begin writing to the page
417
418 // Create the Image Mask
419 MappedFile imgf=new MappedFile(Utils.getAssetTempFile(INPUT_PATH + "imagemask.dat").getAbsolutePath());
420 com.pdftron.filters.FilterReader mask_read=new com.pdftron.filters.FilterReader(imgf);
421
422 ColorSpace device_gray = ColorSpace.createDeviceGray();
423 Image mask = Image.create(doc, mask_read, 64, 64, 1, device_gray, Image.e_ascii_hex);
424
425 mask.getSDFObj().putBool("ImageMask", true);
426
427 element = eb.createRect(0, 0, 612, 794);
428 element.setPathStroke(false);
429 element.setPathFill(true);
430 element.getGState().setFillColorSpace(device_gray);
431 element.getGState().setFillColor(new ColorPt(0.8,0,0));
432 writer.writePlacedElement(element);
433
434 element = eb.createImage(mask, new Matrix2D(200, 0, 0, -200, 40, 680));
435 element.getGState().setFillColor(new ColorPt(0.1,0,0));
436 writer.writePlacedElement(element);
437
438 element.getGState().setFillColorSpace(ColorSpace.createDeviceRGB());
439 element.getGState().setFillColor(new ColorPt(1, 0, 0));
440 element = eb.createImage(mask, new Matrix2D(200, 0, 0, -200, 320, 680));
441 writer.writePlacedElement(element);
442
443 element.getGState().setFillColor(new ColorPt(0, 1, 0));
444 element = eb.createImage(mask, new Matrix2D(200, 0, 0, -200, 40, 380));
445 writer.writePlacedElement(element);
446
447 {
448 // This sample illustrates Explicit Masking.
449 img = Image.create(doc, (Utils.getAssetTempFile(INPUT_PATH + "peppers.jpg").getAbsolutePath()));
450
451 // mask is the explicit mask for the primary (base) image
452 img.setMask(mask);
453
454 element = eb.createImage(img, new Matrix2D(200, 0, 0, -200, 320, 380));
455 writer.writePlacedElement(element);
456 }
457
458 writer.end(); // save changes to the current page
459 doc.pagePushBack(page);
460
461 // Transparency sample ----------------------------------
462
463 // Start a new page -------------------------------------
464 page = doc.pageCreate();
465 writer.begin(page); // begin writing to this page
466 eb.reset(); // Reset the GState to default
467
468 // Write some transparent text at the bottom of the page.
469 element = eb.createTextBegin(Font.create(doc, Font.e_times_roman), 100);
470
471 // Set the text knockout attribute. Text knockout must be set
472 // outside of
473 // the text group.
474 gstate = element.getGState();
475 gstate.setTextKnockout(false);
476 gstate.setBlendMode(GState.e_bl_difference);
477 writer.writeElement(element);
478
479 element = eb.createTextRun("Transparency");
480 element.setTextMatrix(1, 0, 0, 1, 30, 30);
481 gstate = element.getGState();
482 gstate.setFillColorSpace(ColorSpace.createDeviceCMYK());
483 gstate.setFillColor(new ColorPt(1, 0, 0, 0));
484
485 gstate.setFillOpacity(0.5);
486 writer.writeElement(element);
487
488 // Write the same text on top the old; shifted by 3 points
489 element.setTextMatrix(1, 0, 0, 1, 33, 33);
490 gstate.setFillColor(new ColorPt(0, 1, 0, 0));
491 gstate.setFillOpacity(0.5);
492
493 writer.writeElement(element);
494 writer.writeElement(eb.createTextEnd());
495
496 // Draw three overlapping transparent circles.
497 eb.pathBegin(); // start constructing the path
498 eb.moveTo(459.223, 505.646);
499 eb.curveTo(459.223, 415.841, 389.85, 343.04, 304.273, 343.04);
500 eb.curveTo(218.697, 343.04, 149.324, 415.841, 149.324, 505.646);
501 eb.curveTo(149.324, 595.45, 218.697, 668.25, 304.273, 668.25);
502 eb.curveTo(389.85, 668.25, 459.223, 595.45, 459.223, 505.646);
503 element = eb.pathEnd();
504 element.setPathFill(true);
505
506 gstate = element.getGState();
507 gstate.setFillColorSpace(ColorSpace.createDeviceRGB());
508 gstate.setFillColor(new ColorPt(0, 0, 1)); // Blue
509 // Circle
510
511 gstate.setBlendMode(GState.e_bl_normal);
512 gstate.setFillOpacity(0.5);
513 writer.writeElement(element);
514
515 // Translate relative to the Blue Circle
516 gstate.setTransform(1, 0, 0, 1, 113, -185);
517 gstate.setFillColor(new ColorPt(0, 1, 0)); // Green
518 // Circle
519 gstate.setFillOpacity(0.5);
520 writer.writeElement(element);
521
522 // Translate relative to the Green Circle
523 gstate.setTransform(1, 0, 0, 1, -220, 0);
524 gstate.setFillColor(new ColorPt(1, 0, 0)); // Red
525 // Circle
526 gstate.setFillOpacity(0.5);
527 writer.writeElement(element);
528
529 writer.end(); // save changes to the current page
530 doc.pagePushBack(page);
531
532 // End page ------------------------------------
533
534 doc.save((Utils.createExternalFile("element_builder.pdf", mFileList).getAbsolutePath()), SDFDoc.SaveMode.REMOVE_UNUSED, null);
535 mOutputListener.println("Done. Result saved in element_builder.pdf...");
536 } catch (Exception e) {
537 mOutputListener.printError(e.getStackTrace());
538 } finally {
539 if (stream != null) {
540 try {
541 stream.close();
542 } catch (Exception ignored) {
543 }
544 }
545 }
546
547 for (String file : mFileList) {
548 addToFileList(file);
549 }
550 printFooter(outputListener);
551 }
552
553
554}

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales