Sample JavaScript 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 Web SDK and PDF Editing & Manipulation Library.
Step 1: Follow get started in your preferred web stack for WebViewer
Step 2: Enable the full API by passing the fullAPI
option into the WebViewer constructor
Step 3: Add the sample code provided in this guide
This full sample is one of many included in the manual download of WebViewer.
1(exports => {
2
3 exports.runElementBuilderTest = () => {
4 const PDFNet = exports.Core.PDFNet;
5
6 const main = async () => {
7 let ret = 0;
8
9 // Relative path to the folder containing test files.
10 const inputUrl = '../TestFiles/';
11
12 try {
13 const doc = await PDFNet.PDFDoc.create();
14
15 // ElementBuilder is used to build new Element objects
16 const eb = await PDFNet.ElementBuilder.create();
17 // ElementWriter is used to write Elements to the page
18 const writer = await PDFNet.ElementWriter.create();
19
20 let element;
21 let gstate;
22
23 // Start a new page ------------------------------------
24
25 const pageRect = await PDFNet.Rect.init(0, 0, 612, 794);
26 let page = await doc.pageCreate(pageRect);
27
28 // begin writing to the page
29 writer.beginOnPage(page);
30
31 // Create an Image that can be reused in the document or on the same page.
32 const img = await PDFNet.Image.createFromURL(doc, inputUrl + 'peppers.jpg');
33
34 element = await eb.createImageFromMatrix(img, await PDFNet.Matrix2D.create((await img.getImageWidth()) / 2, -145, 20, (await img.getImageHeight()) / 2, 200, 150));
35 writer.writePlacedElement(element);
36
37 // use the same image (just change its matrix)
38 gstate = await element.getGState();
39 gstate.setTransform(200, 0, 0, 300, 50, 450);
40 writer.writePlacedElement(element);
41
42 // use the same image again (just change its matrix).
43 writer.writePlacedElement(await eb.createImageScaled(img, 300, 600, 200, -150));
44
45 writer.end(); // save changes to the current page
46 doc.pagePushBack(page);
47
48 // Start a new page ------------------------------------
49 // Construct and draw a path object using different styles
50 page = await doc.pageCreate(pageRect);
51
52 // begin writing to this page
53 writer.beginOnPage(page);
54 // Reset the GState to default
55 eb.reset();
56
57 // start constructing the path
58 eb.pathBegin();
59 eb.moveTo(306, 396);
60 eb.curveTo(681, 771, 399.75, 864.75, 306, 771);
61 eb.curveTo(212.25, 864.75, -69, 771, 306, 396);
62 eb.closePath();
63 // the path is now finished
64 element = await eb.pathEnd();
65 // the path should be filled
66 element.setPathFill(true);
67
68 // Set the path color space and color
69 gstate = await element.getGState();
70 gstate.setFillColorSpace(await PDFNet.ColorSpace.createDeviceCMYK());
71 gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0, 0)); // cyan
72 gstate.setTransform(0.5, 0, 0, 0.5, -20, 300);
73 writer.writePlacedElement(element);
74
75 // Draw the same path using a different stroke color
76 // this path is should be filled and stroked
77 element.setPathStroke(true);
78 gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(0, 0, 1, 0)); // yellow
79 gstate.setStrokeColorSpace(await PDFNet.ColorSpace.createDeviceRGB());
80 gstate.setStrokeColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0)); // red
81 gstate.setTransform(0.5, 0, 0, 0.5, 280, 300);
82 gstate.setLineWidth(20);
83 writer.writePlacedElement(element);
84
85 // Draw the same path with with a given dash pattern
86 // this path is should be only stroked
87 element.setPathFill(false);
88 gstate.setStrokeColorWithColorPt(await PDFNet.ColorPt.init(0, 0, 1)); // blue
89 gstate.setTransform(0.5, 0, 0, 0.5, 280, 0);
90 const dashPattern = [];
91 dashPattern.push(30);
92 gstate.setDashPattern(dashPattern, 0);
93 writer.writePlacedElement(element);
94
95 // Use the path as a clipping path
96 // Save the graphics state
97 writer.writeElement(await eb.createGroupBegin());
98 // Start constructing the new path (the old path was lost when we created
99 // a new Element using CreateGroupBegin()).
100 eb.pathBegin();
101 eb.moveTo(306, 396);
102 eb.curveTo(681, 771, 399.75, 864.75, 306, 771);
103 eb.curveTo(212.25, 864.75, -69, 771, 306, 396);
104 eb.closePath();
105 // path is now constructed
106 element = await eb.pathEnd();
107 // this path is a clipping path
108 element.setPathClip(true);
109 // this path should be filled and stroked
110 element.setPathStroke(true);
111 gstate = await element.getGState();
112 gstate.setTransform(0.5, 0, 0, 0.5, -20, 0);
113
114 writer.writeElement(element);
115
116 writer.writeElement(await eb.createImageScaled(img, 100, 300, 400, 600));
117
118 // Restore the graphics state
119 writer.writeElement(await eb.createGroupEnd());
120
121 writer.end(); // save changes to the current page
122 doc.pagePushBack(page);
123
124 // Start a new page ------------------------------------
125 page = await doc.pageCreate(pageRect);
126
127 // begin writing to this page
128 writer.beginOnPage(page);
129 // Reset the GState to default
130 eb.reset();
131
132 // Begin writing a block of text
133 element = await eb.createTextBeginWithFont(await PDFNet.Font.create(doc, PDFNet.Font.StandardType1Font.e_times_roman), 12);
134 writer.writeElement(element);
135
136 element = await eb.createNewTextRun('Hello World!');
137 element.setTextMatrixEntries(10, 0, 0, 10, 0, 600);
138 gstate = await element.getGState();
139 // Set the spacing between lines
140 gstate.setLeading(15);
141 writer.writeElement(element);
142
143 writer.writeElement(await eb.createTextNewLine()); // New line
144
145 element = await eb.createNewTextRun('Hello World!');
146 gstate = await element.getGState();
147 gstate.setTextRenderMode(PDFNet.GState.TextRenderingMode.e_stroke_text);
148 gstate.setCharSpacing(-1.25);
149 gstate.setWordSpacing(-1.25);
150 writer.writeElement(element);
151
152 writer.writeElement(await eb.createTextNewLine()); // New line
153
154 element = await eb.createNewTextRun('Hello World!');
155 gstate = await element.getGState();
156 gstate.setCharSpacing(0);
157 gstate.setWordSpacing(0);
158 gstate.setLineWidth(3);
159 gstate.setTextRenderMode(PDFNet.GState.TextRenderingMode.e_fill_stroke_text);
160 gstate.setStrokeColorSpace(await PDFNet.ColorSpace.createDeviceRGB());
161 gstate.setStrokeColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0)); // red
162 gstate.setFillColorSpace(await PDFNet.ColorSpace.createDeviceCMYK());
163 gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0, 0)); // cyan
164 writer.writeElement(element);
165
166 writer.writeElement(await eb.createTextNewLine()); // New line
167
168 // Set text as a clipping path to the image.
169 element = await eb.createNewTextRun('Hello World!');
170 gstate = await element.getGState();
171 gstate.setTextRenderMode(PDFNet.GState.TextRenderingMode.e_clip_text);
172 writer.writeElement(element);
173
174 // Finish the block of text
175 writer.writeElement(await eb.createTextEnd());
176
177 // Draw an image that will be clipped by the above text
178 writer.writeElement(await eb.createImageScaled(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 also shows how ElementReader can be used to copy and modify
186 // Elements between pages.
187
188 const reader = await PDFNet.ElementReader.create();
189
190 // Start reading Elements from the last page. We will copy all Elements to
191 // a new page but will modify the font associated with text.
192 reader.beginOnPage(await doc.getPage(await doc.getPageCount()));
193
194 page = await doc.pageCreate(await PDFNet.Rect.init(0, 0, 1300, 794));
195
196 // begin writing to this page
197 writer.beginOnPage(page);
198 // Reset the GState to default
199 eb.reset();
200
201 const font = await PDFNet.Font.create(doc, PDFNet.Font.StandardType1Font.e_helvetica);
202
203 // Read page contents
204 while ((element = await reader.next())) {
205 if ((await element.getType()) === PDFNet.Element.Type.e_text) {
206 (await element.getGState()).setFont(font, 14);
207 }
208
209 writer.writeElement(element);
210 }
211
212 reader.end();
213 writer.end(); // save changes to the current page
214
215 doc.pagePushBack(page);
216
217 // Start a new page ------------------------------------
218 //
219 // The example also shows how ElementReader can be used to copy and modify
220 // Elements between pages.
221
222 // Start reading Elements from the last page. We will copy all Elements to
223 // a new page but will modify the font associated with text.
224 reader.beginOnPage(await doc.getPage(await doc.getPageCount()));
225
226 page = await doc.pageCreate(await PDFNet.Rect.init(0, 0, 1300, 794));
227
228 // begin writing to this page
229 writer.beginOnPage(page);
230 // Reset the GState to default
231 eb.reset();
232
233 // Embed an external font in the document.
234 // MISSING createType1Font
235 // Font font2 = Font::CreateType1Font(doc, (inputUrl + "Misc-Fixed.pfa").c_str());
236 const font2 = await PDFNet.Font.create(doc, PDFNet.Font.StandardType1Font.e_courier_bold);
237
238 // Read page contents
239 while ((element = await reader.next())) {
240 if ((await element.getType()) === PDFNet.Element.Type.e_text) {
241 (await element.getGState()).setFont(font2, 16);
242 }
243 writer.writeElement(element);
244 }
245
246 reader.end();
247 writer.end(); // save changes to the current page
248 doc.pagePushBack(page);
249
250 // Start a new page ------------------------------------
251 page = await doc.pageCreate();
252 // begin writing to this page
253 writer.beginOnPage(page);
254 // Reset the GState to default
255 eb.reset();
256
257 // Begin writing a block of text
258 element = await eb.createTextBeginWithFont(await PDFNet.Font.create(doc, PDFNet.Font.StandardType1Font.e_times_roman), 12);
259 element.setTextMatrixEntries(1.5, 0, 0, 1.5, 50, 600);
260 // Set the spacing between lines
261 (await element.getGState()).setLeading(15);
262 writer.writeElement(element);
263
264 const para =
265 'A PDF text object consists of operators that can show ' +
266 'text strings, move the text position, and set text state and certain ' +
267 'other parameters. In addition, there are three parameters that are ' +
268 'defined only within a text object and do not persist from one text ' +
269 'object to the next: Tm, the text matrix, Tlm, the text line matrix, ' +
270 'Trm, the text rendering matrix, actually just an intermediate result ' +
271 'that combines the effects of text state parameters, the text matrix ' +
272 '(Tm), and the current transformation matrix';
273
274 const paraEnd = para.length;
275 let textRun = 0;
276 let textRunEnd;
277
278 const paraWidth = 300; // paragraph width is 300 units
279 let curWidth = 0;
280
281 while (textRun < paraEnd) {
282 textRunEnd = para.indexOf(' ', textRun);
283 if (textRunEnd < 0) {
284 textRunEnd = paraEnd - 1;
285 }
286
287 let text = para.substring(textRun, textRunEnd - textRun + 1);
288 element = await eb.createNewTextRun(text);
289 if (curWidth + (await element.getTextLength()) < paraWidth) {
290 writer.writeElement(element);
291 curWidth += await element.getTextLength();
292 } else {
293 writer.writeElement(await eb.createTextNewLine()); // New line
294 text = para.substr(textRun, textRunEnd - textRun + 1);
295 element = await eb.createNewTextRun(text);
296 curWidth = await element.getTextLength();
297 writer.writeElement(element);
298 }
299
300 textRun = textRunEnd + 1;
301 }
302
303 // -----------------------------------------------------------------------
304 // The following code snippet illustrates how to adjust spacing between
305 // characters (text runs).
306 element = await eb.createTextNewLine();
307 writer.writeElement(element); // Skip 2 lines
308 writer.writeElement(element);
309
310 writer.writeElement(await eb.createNewTextRun('An example of space adjustments between inter-characters:'));
311 writer.writeElement(await eb.createTextNewLine());
312
313 // Write string "AWAY" without space adjustments between characters.
314 element = await eb.createNewTextRun('AWAY');
315 writer.writeElement(element);
316
317 writer.writeElement(await eb.createTextNewLine());
318
319 // Write string "AWAY" with space adjustments between characters.
320 element = await eb.createNewTextRun('A');
321 writer.writeElement(element);
322
323 element = await eb.createNewTextRun('W');
324 element.setPosAdjustment(140);
325 writer.writeElement(element);
326
327 element = await eb.createNewTextRun('A');
328 element.setPosAdjustment(140);
329 writer.writeElement(element);
330
331 element = await eb.createNewTextRun('Y again');
332 element.setPosAdjustment(115);
333 writer.writeElement(element);
334
335 // Draw the same strings using direct content output...
336 writer.flush(); // flush pending Element writing operations.
337
338 // You can also write page content directly to the content stream using
339 // ElementWriter.WriteString(...) and ElementWriter.WriteBuffer(...) methods.
340 // Note that if you are planning to use these functions you need to be familiar
341 // with PDF page content operators (see Appendix A in PDF Reference Manual).
342 // Because it is easy to make mistakes during direct output we recommend that
343 // you use ElementBuilder and Element interface instead.
344
345 writer.writeString('T* T* '); // Skip 2 lines
346 writer.writeString('(Direct output to PDF page content stream:) Tj T* ');
347 writer.writeString('(AWAY) Tj T* ');
348 writer.writeString('[(A)140(W)140(A)115(Y again)] TJ ');
349
350 // Finish the block of text
351 writer.writeElement(await eb.createTextEnd());
352
353 writer.end(); // save changes to the current page
354 doc.pagePushBack(page);
355
356 // Start a new page ------------------------------------
357
358 // Image Masks
359 //
360 // In the opaque imaging model, images mark all areas they occupy on the page as
361 // if with opaque paint. All portions of the image, whether black, white, gray,
362 // or color, completely obscure any marks that may previously have existed in the
363 // same place on the page.
364 // In the graphic arts industry and page layout applications, however, it is common
365 // to crop or 'mask out' the background of an image and then place the masked image
366 // on a different background, allowing the existing background to show through the
367 // masked areas. This sample illustrates how to use image masks.
368
369 page = await doc.pageCreate();
370 // begin writing to the page
371 writer.beginOnPage(page);
372
373 // INVESTIGATE THIS SECTION
374
375 // Create the Image Mask
376 const embedFile = await PDFNet.Filter.createURLFilter(inputUrl + 'imagemask.dat');
377 const maskRead = await PDFNet.FilterReader.create(embedFile);
378
379 // INVESTIGATE THIS SECTION
380
381 const deviceGray = await PDFNet.ColorSpace.createDeviceGray();
382 const mask = await PDFNet.Image.createDirectFromStream(doc, maskRead, 64, 64, 1, deviceGray, PDFNet.Image.InputFilter.e_ascii_hex);
383
384 (await mask.getSDFObj()).putBool('ImageMask', true);
385
386 element = await eb.createRect(0, 0, 612, 794);
387 element.setPathStroke(false);
388 element.setPathFill(true);
389 gstate = await element.getGState();
390
391 gstate.setFillColorSpace(deviceGray);
392 gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(0.8));
393 writer.writePlacedElement(element);
394
395 element = await eb.createImageFromMatrix(mask, await PDFNet.Matrix2D.create(200, 0, 0, -200, 40, 680));
396 (await element.getGState()).setFillColorWithColorPt(await PDFNet.ColorPt.init(0.1));
397 writer.writePlacedElement(element);
398
399 gstate = await element.getGState();
400 gstate.setFillColorSpace(await PDFNet.ColorSpace.createDeviceRGB());
401 gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0));
402 element = await eb.createImageFromMatrix(mask, await PDFNet.Matrix2D.create(200, 0, 0, -200, 320, 680));
403 writer.writePlacedElement(element);
404
405 (await element.getGState()).setFillColorWithColorPt(await PDFNet.ColorPt.init(0, 1, 0));
406 element = await eb.createImageFromMatrix(mask, await PDFNet.Matrix2D.create(200, 0, 0, -200, 40, 380));
407 writer.writePlacedElement(element);
408
409 {
410 // This sample illustrates Explicit Masking.
411 const img = await PDFNet.Image.createFromURL(doc, inputUrl + 'peppers.jpg');
412
413 // mask is the explicit mask for the primary (base) image
414 img.setMask(mask);
415
416 element = await eb.createImageFromMatrix(img, await PDFNet.Matrix2D.create(200, 0, 0, -200, 320, 380));
417 writer.writePlacedElement(element);
418 }
419
420 writer.end(); // save changes to the current page
421 doc.pagePushBack(page);
422
423 // Transparency sample ----------------------------------
424
425 // Start a new page -------------------------------------
426 page = await doc.pageCreate();
427 // begin writing to this page
428 writer.beginOnPage(page);
429 // Reset the GState to default
430 eb.reset();
431
432 // Write some transparent text at the bottom of the page.
433 element = await eb.createTextBeginWithFont(await PDFNet.Font.create(doc, PDFNet.Font.StandardType1Font.e_times_roman), 100);
434
435 // Set the text knockout attribute. Text knockout must be set outside of
436 // the text group.
437 gstate = await element.getGState();
438 gstate.setTextKnockout(false);
439 gstate.setBlendMode(PDFNet.GState.BlendMode.e_bl_difference);
440 writer.writeElement(element);
441
442 element = await eb.createNewTextRun('Transparency');
443 element.setTextMatrixEntries(1, 0, 0, 1, 30, 30);
444 gstate = await element.getGState();
445 gstate.setFillColorSpace(await PDFNet.ColorSpace.createDeviceCMYK());
446 gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0, 0));
447
448 gstate.setFillOpacity(0.5);
449 writer.writeElement(element);
450
451 // Write the same text on top the old; shifted by 3 points
452 element.setTextMatrixEntries(1, 0, 0, 1, 33, 33);
453 gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(0, 1, 0, 0));
454 gstate.setFillOpacity(0.5);
455
456 writer.writeElement(element);
457 writer.writeElement(await eb.createTextEnd());
458
459 // Draw three overlapping transparent circles.
460 // start constructing the path
461 eb.pathBegin();
462 eb.moveTo(459.223, 505.646);
463 eb.curveTo(459.223, 415.841, 389.85, 343.04, 304.273, 343.04);
464 eb.curveTo(218.697, 343.04, 149.324, 415.841, 149.324, 505.646);
465 eb.curveTo(149.324, 595.45, 218.697, 668.25, 304.273, 668.25);
466 eb.curveTo(389.85, 668.25, 459.223, 595.45, 459.223, 505.646);
467 element = await eb.pathEnd();
468 element.setPathFill(true);
469
470 gstate = await element.getGState();
471 gstate.setFillColorSpace(await PDFNet.ColorSpace.createDeviceRGB());
472 gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(0, 0, 1)); // Blue Circle
473
474 gstate.setBlendMode(PDFNet.GState.BlendMode.e_bl_normal);
475 gstate.setFillOpacity(0.5);
476 writer.writeElement(element);
477
478 // Translate relative to the Blue Circle
479 gstate.setTransform(1, 0, 0, 1, 113, -185);
480 gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(0, 1, 0)); // Green Circle
481 gstate.setFillOpacity(0.5);
482 writer.writeElement(element);
483
484 // Translate relative to the Green Circle
485 gstate.setTransform(1, 0, 0, 1, -220, 0);
486 gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0)); // Red Circle
487 gstate.setFillOpacity(0.5);
488 writer.writeElement(element);
489
490 writer.end(); // save changes to the current page
491 doc.pagePushBack(page);
492
493 // End page ------------------------------------
494
495 const docBuffer = await doc.saveMemoryBuffer(PDFNet.SDFDoc.SaveOptions.e_remove_unused);
496 saveBufferAsPDFDoc(docBuffer, 'element_builder.pdf');
497
498 console.log('Done. Result saved in element_builder.pdf...');
499 } catch (e) {
500 console.log(e);
501 ret = 1;
502 }
503 return ret;
504 };
505
506 // add your own license key as the second parameter, e.g. PDFNet.runWithCleanup(main, 'YOUR_LICENSE_KEY')
507 PDFNet.runWithCleanup(main);
508 };
509})(window);
510// eslint-disable-next-line spaced-comment
511//# sourceURL=ElementBuilderTest.js
Did you find this helpful?
Trial setup questions?
Ask experts on DiscordNeed other help?
Contact SupportPricing or product questions?
Contact Sales