More languages
Some test text!
More languages
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 JavaScript PDF Library and PDF Editing & Manipulation Library.
Get Started Samples DownloadTo run this sample, get started with a free trial of Apryse SDK.
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------
const { PDFNet } = require('@pdftron/pdfnet-node');
const PDFTronLicense = require('../LicenseKey/LicenseKey');
((exports) => {
exports.runElementBuilderTest = () => {
const main = async() => {
let ret = 0;
// Relative path to the folder containing test files.
const inputPath = '../TestFiles/';
try {
const doc = await PDFNet.PDFDoc.create();
// ElementBuilder is used to build new Element objects
const eb = await PDFNet.ElementBuilder.create();
// ElementWriter is used to write Elements to the page
const writer = await PDFNet.ElementWriter.create();
let element;
let gstate;
// Start a new page ------------------------------------
const pageRect = await PDFNet.Rect.init(0, 0, 612, 794);
let page = await doc.pageCreate(pageRect);
// begin writing to the page
writer.beginOnPage(page);
// Create an Image that can be reused in the document or on the same page.
const img = await PDFNet.Image.createFromFile(doc, inputPath + 'peppers.jpg');
element = await eb.createImageFromMatrix(img, await PDFNet.Matrix2D.create((await img.getImageWidth()) / 2, -145, 20, (await img.getImageHeight()) / 2, 200, 150));
writer.writePlacedElement(element);
// use the same image (just change its matrix)
gstate = await element.getGState();
gstate.setTransform(200, 0, 0, 300, 50, 450);
writer.writePlacedElement(element);
// use the same image again (just change its matrix).
writer.writePlacedElement(await eb.createImageScaled(img, 300, 600, 200, -150));
writer.end(); // save changes to the current page
doc.pagePushBack(page);
// Start a new page ------------------------------------
// Construct and draw a path object using different styles
page = await doc.pageCreate(pageRect);
// begin writing to this page
writer.beginOnPage(page);
// Reset the GState to default
eb.reset();
// start constructing the path
eb.pathBegin();
eb.moveTo(306, 396);
eb.curveTo(681, 771, 399.75, 864.75, 306, 771);
eb.curveTo(212.25, 864.75, -69, 771, 306, 396);
eb.closePath();
// the path is now finished
element = await eb.pathEnd();
// the path should be filled
element.setPathFill(true);
// Set the path color space and color
gstate = await element.getGState();
gstate.setFillColorSpace(await PDFNet.ColorSpace.createDeviceCMYK());
gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0, 0)); // cyan
gstate.setTransform(0.5, 0, 0, 0.5, -20, 300);
writer.writePlacedElement(element);
// Draw the same path using a different stroke color
// this path is should be filled and stroked
element.setPathStroke(true);
gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(0, 0, 1, 0)); // yellow
gstate.setStrokeColorSpace(await PDFNet.ColorSpace.createDeviceRGB());
gstate.setStrokeColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0)); // red
gstate.setTransform(0.5, 0, 0, 0.5, 280, 300);
gstate.setLineWidth(20);
writer.writePlacedElement(element);
// Draw the same path with with a given dash pattern
// this path is should be only stroked
element.setPathFill(false);
gstate.setStrokeColorWithColorPt(await PDFNet.ColorPt.init(0, 0, 1)); // blue
gstate.setTransform(0.5, 0, 0, 0.5, 280, 0);
const dashPattern = [];
dashPattern.push(30);
gstate.setDashPattern(dashPattern, 0);
writer.writePlacedElement(element);
// Use the path as a clipping path
// Save the graphics state
writer.writeElement(await eb.createGroupBegin());
// Start constructing the new path (the old path was lost when we created
// a new Element using CreateGroupBegin()).
eb.pathBegin();
eb.moveTo(306, 396);
eb.curveTo(681, 771, 399.75, 864.75, 306, 771);
eb.curveTo(212.25, 864.75, -69, 771, 306, 396);
eb.closePath();
// path is now constructed
element = await eb.pathEnd();
// this path is a clipping path
element.setPathClip(true);
// this path should be filled and stroked
element.setPathStroke(true);
gstate = await element.getGState();
gstate.setTransform(0.5, 0, 0, 0.5, -20, 0);
writer.writeElement(element);
writer.writeElement(await eb.createImageScaled(img, 100, 300, 400, 600));
// Restore the graphics state
writer.writeElement(await eb.createGroupEnd());
writer.end(); // save changes to the current page
doc.pagePushBack(page);
// Start a new page ------------------------------------
page = await doc.pageCreate(pageRect);
// begin writing to this page
writer.beginOnPage(page);
// Reset the GState to default
eb.reset();
// Begin writing a block of text
element = await eb.createTextBeginWithFont(await PDFNet.Font.create(doc, PDFNet.Font.StandardType1Font.e_times_roman), 12);
writer.writeElement(element);
element = await eb.createNewTextRun('Hello World!');
element.setTextMatrixEntries(10, 0, 0, 10, 0, 600);
gstate = await element.getGState();
// Set the spacing between lines
gstate.setLeading(15);
writer.writeElement(element);
writer.writeElement(await eb.createTextNewLine()); // New line
element = await eb.createNewTextRun('Hello World!');
gstate = await element.getGState();
gstate.setTextRenderMode(PDFNet.GState.TextRenderingMode.e_stroke_text);
gstate.setCharSpacing(-1.25);
gstate.setWordSpacing(-1.25);
writer.writeElement(element);
writer.writeElement(await eb.createTextNewLine()); // New line
element = await eb.createNewTextRun('Hello World!');
gstate = await element.getGState();
gstate.setCharSpacing(0);
gstate.setWordSpacing(0);
gstate.setLineWidth(3);
gstate.setTextRenderMode(PDFNet.GState.TextRenderingMode.e_fill_stroke_text);
gstate.setStrokeColorSpace(await PDFNet.ColorSpace.createDeviceRGB());
gstate.setStrokeColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0)); // red
gstate.setFillColorSpace(await PDFNet.ColorSpace.createDeviceCMYK());
gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0, 0)); // cyan
writer.writeElement(element);
writer.writeElement(await eb.createTextNewLine()); // New line
// Set text as a clipping path to the image.
element = await eb.createNewTextRun('Hello World!');
gstate = await element.getGState();
gstate.setTextRenderMode(PDFNet.GState.TextRenderingMode.e_clip_text);
writer.writeElement(element);
// Finish the block of text
writer.writeElement(await eb.createTextEnd());
// Draw an image that will be clipped by the above text
writer.writeElement(await eb.createImageScaled(img, 10, 100, 1300, 720));
writer.end(); // save changes to the current page
doc.pagePushBack(page);
// Start a new page ------------------------------------
//
// The example illustrates how to embed the external font in a PDF document.
// The example also shows how ElementReader can be used to copy and modify
// Elements between pages.
const reader = await PDFNet.ElementReader.create();
// Start reading Elements from the last page. We will copy all Elements to
// a new page but will modify the font associated with text.
reader.beginOnPage(await doc.getPage(await doc.getPageCount()));
page = await doc.pageCreate(await PDFNet.Rect.init(0, 0, 1300, 794));
// begin writing to this page
writer.beginOnPage(page);
// Reset the GState to default
eb.reset();
const font = await PDFNet.Font.createTrueTypeFont(doc, inputPath + 'font.ttf');
// Read page contents
while ((element = await reader.next())) {
if ((await element.getType()) === PDFNet.Element.Type.e_text) {
(await element.getGState()).setFont(font, 12);
}
writer.writeElement(element);
}
reader.end();
writer.end(); // save changes to the current page
doc.pagePushBack(page);
// Start a new page ------------------------------------
//
// The example also shows how ElementReader can be used to copy and modify
// Elements between pages.
// Start reading Elements from the last page. We will copy all Elements to
// a new page but will modify the font associated with text.
reader.beginOnPage(await doc.getPage(await doc.getPageCount()));
page = await doc.pageCreate(await PDFNet.Rect.init(0, 0, 1300, 794));
// begin writing to this page
writer.beginOnPage(page);
// Reset the GState to default
eb.reset();
// Embed an external font in the document.
const font2 = await PDFNet.Font.createType1Font(doc, inputPath + 'Misc-Fixed.pfa');
// Read page contents
while ((element = await reader.next())) {
if ((await element.getType()) === PDFNet.Element.Type.e_text) {
(await element.getGState()).setFont(font2, 12);
}
writer.writeElement(element);
}
reader.end();
writer.end(); // save changes to the current page
doc.pagePushBack(page);
// Start a new page ------------------------------------
page = await doc.pageCreate();
// begin writing to this page
writer.beginOnPage(page);
// Reset the GState to default
eb.reset();
// Begin writing a block of text
element = await eb.createTextBeginWithFont(await PDFNet.Font.create(doc, PDFNet.Font.StandardType1Font.e_times_roman), 12);
element.setTextMatrixEntries(1.5, 0, 0, 1.5, 50, 600);
// Set the spacing between lines
(await element.getGState()).setLeading(15);
writer.writeElement(element);
const para = 'A PDF text object consists of operators that can show '
+ 'text strings, move the text position, and set text state and certain '
+ 'other parameters. In addition, there are three parameters that are '
+ 'defined only within a text object and do not persist from one text '
+ 'object to the next: Tm, the text matrix, Tlm, the text line matrix, '
+ 'Trm, the text rendering matrix, actually just an intermediate result '
+ 'that combines the effects of text state parameters, the text matrix '
+ '(Tm), and the current transformation matrix';
const paraEnd = para.length;
let textRun = 0;
let textRunEnd;
const paraWidth = 300; // paragraph width is 300 units
let curWidth = 0;
while (textRun < paraEnd) {
textRunEnd = para.indexOf(' ', textRun);
if (textRunEnd < 0) {
textRunEnd = paraEnd - 1;
}
let text = para.substring(textRun, textRunEnd + 1);
element = await eb.createNewTextRun(text);
if (curWidth + (await element.getTextLength()) < paraWidth) {
curWidth += await element.getTextLength();
} else {
writer.writeElement(await eb.createTextNewLine()); // New line
element = await eb.createNewTextRun(text);
curWidth = await element.getTextLength();
}
writer.writeElement(element);
textRun = textRunEnd + 1;
}
// -----------------------------------------------------------------------
// The following code snippet illustrates how to adjust spacing between
// characters (text runs).
element = await eb.createTextNewLine();
writer.writeElement(element); // Skip 2 lines
writer.writeElement(element);
writer.writeElement(await eb.createNewTextRun('An example of space adjustments between inter-characters:'));
writer.writeElement(await eb.createTextNewLine());
// Write string "AWAY" without space adjustments between characters.
element = await eb.createNewTextRun('AWAY');
writer.writeElement(element);
writer.writeElement(await eb.createTextNewLine());
// Write string "AWAY" with space adjustments between characters.
element = await eb.createNewTextRun('A');
writer.writeElement(element);
element = await eb.createNewTextRun('W');
element.setPosAdjustment(140);
writer.writeElement(element);
element = await eb.createNewTextRun('A');
element.setPosAdjustment(140);
writer.writeElement(element);
element = await eb.createNewTextRun('Y again');
element.setPosAdjustment(115);
writer.writeElement(element);
// Draw the same strings using direct content output...
writer.flush(); // flush pending Element writing operations.
// You can also write page content directly to the content stream using
// ElementWriter.WriteString(...) and ElementWriter.WriteBuffer(...) methods.
// Note that if you are planning to use these functions you need to be familiar
// with PDF page content operators (see Appendix A in PDF Reference Manual).
// Because it is easy to make mistakes during direct output we recommend that
// you use ElementBuilder and Element interface instead.
writer.writeString('T* T* '); // Skip 2 lines
writer.writeString('(Direct output to PDF page content stream:) Tj T* ');
writer.writeString('(AWAY) Tj T* ');
writer.writeString('[(A)140(W)140(A)115(Y again)] TJ ');
// Finish the block of text
writer.writeElement(await eb.createTextEnd());
writer.end(); // save changes to the current page
doc.pagePushBack(page);
// Start a new page ------------------------------------
// Image Masks
//
// In the opaque imaging model, images mark all areas they occupy on the page as
// if with opaque paint. All portions of the image, whether black, white, gray,
// or color, completely obscure any marks that may previously have existed in the
// same place on the page.
// In the graphic arts industry and page layout applications, however, it is common
// to crop or 'mask out' the background of an image and then place the masked image
// on a different background, allowing the existing background to show through the
// masked areas. This sample illustrates how to use image masks.
page = await doc.pageCreate();
// begin writing to the page
writer.beginOnPage(page);
// Create the Image Mask
const embedFile = await PDFNet.Filter.createMappedFileFromUString(inputPath + 'imagemask.dat');
const maskRead = await PDFNet.FilterReader.create(embedFile);
const deviceGray = await PDFNet.ColorSpace.createDeviceGray();
const mask = await PDFNet.Image.createDirectFromStream(doc, maskRead, 64, 64, 1, deviceGray, PDFNet.Image.InputFilter.e_ascii_hex);
(await mask.getSDFObj()).putBool('ImageMask', true);
element = await eb.createRect(0, 0, 612, 794);
element.setPathStroke(false);
element.setPathFill(true);
gstate = await element.getGState();
gstate.setFillColorSpace(deviceGray);
gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(0.8));
writer.writePlacedElement(element);
element = await eb.createImageFromMatrix(mask, await PDFNet.Matrix2D.create(200, 0, 0, -200, 40, 680));
(await element.getGState()).setFillColorWithColorPt(await PDFNet.ColorPt.init(0.1));
writer.writePlacedElement(element);
gstate = await element.getGState();
gstate.setFillColorSpace(await PDFNet.ColorSpace.createDeviceRGB());
gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0));
element = await eb.createImageFromMatrix(mask, await PDFNet.Matrix2D.create(200, 0, 0, -200, 320, 680));
writer.writePlacedElement(element);
(await element.getGState()).setFillColorWithColorPt(await PDFNet.ColorPt.init(0, 1, 0));
element = await eb.createImageFromMatrix(mask, await PDFNet.Matrix2D.create(200, 0, 0, -200, 40, 380));
writer.writePlacedElement(element);
{
// This sample illustrates Explicit Masking.
const img = await PDFNet.Image.createFromFile(doc, (inputPath + 'peppers.jpg'));
// mask is the explicit mask for the primary (base) image
img.setMask(mask);
element = await eb.createImageFromMatrix(img, await PDFNet.Matrix2D.create(200, 0, 0, -200, 320, 380));
writer.writePlacedElement(element);
}
writer.end(); // save changes to the current page
doc.pagePushBack(page);
// Transparency sample ----------------------------------
// Start a new page -------------------------------------
page = await doc.pageCreate();
// begin writing to this page
writer.beginOnPage(page);
// Reset the GState to default
eb.reset();
// Write some transparent text at the bottom of the page.
element = await eb.createTextBeginWithFont(await PDFNet.Font.create(doc, PDFNet.Font.StandardType1Font.e_times_roman), 100);
// Set the text knockout attribute. Text knockout must be set outside of
// the text group.
gstate = await element.getGState();
gstate.setTextKnockout(false);
gstate.setBlendMode(PDFNet.GState.BlendMode.e_bl_difference);
writer.writeElement(element);
element = await eb.createNewTextRun('Transparency');
element.setTextMatrixEntries(1, 0, 0, 1, 30, 30);
gstate = await element.getGState();
gstate.setFillColorSpace(await PDFNet.ColorSpace.createDeviceCMYK());
gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0, 0));
gstate.setFillOpacity(0.5);
writer.writeElement(element);
// Write the same text on top the old; shifted by 3 points
element.setTextMatrixEntries(1, 0, 0, 1, 33, 33);
gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(0, 1, 0, 0));
gstate.setFillOpacity(0.5);
writer.writeElement(element);
writer.writeElement(await eb.createTextEnd());
// Draw three overlapping transparent circles.
// start constructing the path
eb.pathBegin();
eb.moveTo(459.223, 505.646);
eb.curveTo(459.223, 415.841, 389.85, 343.04, 304.273, 343.04);
eb.curveTo(218.697, 343.04, 149.324, 415.841, 149.324, 505.646);
eb.curveTo(149.324, 595.45, 218.697, 668.25, 304.273, 668.25);
eb.curveTo(389.85, 668.25, 459.223, 595.45, 459.223, 505.646);
element = await eb.pathEnd();
element.setPathFill(true);
gstate = await element.getGState();
gstate.setFillColorSpace(await PDFNet.ColorSpace.createDeviceRGB());
gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(0, 0, 1)); // Blue Circle
gstate.setBlendMode(PDFNet.GState.BlendMode.e_bl_normal);
gstate.setFillOpacity(0.5);
writer.writeElement(element);
// Translate relative to the Blue Circle
gstate.setTransform(1, 0, 0, 1, 113, -185);
gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(0, 1, 0)); // Green Circle
gstate.setFillOpacity(0.5);
writer.writeElement(element);
// Translate relative to the Green Circle
gstate.setTransform(1, 0, 0, 1, -220, 0);
gstate.setFillColorWithColorPt(await PDFNet.ColorPt.init(1, 0, 0)); // Red Circle
gstate.setFillOpacity(0.5);
writer.writeElement(element);
writer.end(); // save changes to the current page
doc.pagePushBack(page);
// End page ------------------------------------
await doc.save('../TestFiles/Output/element_builder.pdf', PDFNet.SDFDoc.SaveOptions.e_remove_unused);
console.log('Done. Result saved in element_builder.pdf...');
} catch (e) {
console.log(e);
ret = 1;
}
return ret;
};
PDFNet.runWithCleanup(main, PDFTronLicense.Key).catch(function(error){console.log('Error: ' + JSON.stringify(error));}).then(function(){return PDFNet.shutdown();});
};
exports.runElementBuilderTest();
})(exports);
// eslint-disable-next-line spaced-comment
//# sourceURL=ElementBuilderTest.js