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
Java to Build, Write, Embed Elements in PDF Pages | Apryse documentation