> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/core/get-started/samples/elementbuildertest.md).

# Build, Write and Embed Elements in PDF

Use Apryse SDK's page writing API to generate new pages, embed fonts & images, and copy graphical elements from one page to another.  Sample code provided in Python, C++, C#, Java, Node.js (JavaScript

Sample 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. Sample code provided in Python, C++, C#, Java, Node.js (JavaScript), PHP, Ruby and VB.

Learn more about our [Server SDK](/core/get-started/get-started.md) and [PDF Editing & Manipulation Library](/core/page-manipulation/manipulation.md).

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
//
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
//

using System;
using pdftron;
using pdftron.Common;
using pdftron.Filters;
using pdftron.SDF;
using pdftron.PDF;

namespace ElementBuilderTestCS
{
	/// <summary>
	/// Summary description for Class1.
	/// </summary>
	class Class1
	{
		private static pdftron.PDFNetLoader pdfNetLoader = pdftron.PDFNetLoader.Instance();
		static Class1() {}

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{
			PDFNet.Initialize(PDFTronLicense.Key);

			// Relative path to the folder containing test files.
			string input_path =  "../../../../TestFiles/";
			string output_path = "../../../../TestFiles/Output/";


			try
			{
				using (PDFDoc doc = new PDFDoc())
				using (ElementBuilder eb = new ElementBuilder())		// ElementBuilder is used to build new Element objects
				using (ElementWriter writer = new ElementWriter())	// ElementWriter is used to write Elements to the page	
				{
					// Start a new page ------------------------------------
					// Position an image stream on several places on the page
					Page page = doc.PageCreate(new Rect(0, 0, 612, 794));

					writer.Begin(page);	// begin writing to this page

					// Create an Image that can be reused multiple times in the document or 
					// multiple on the same page.
					MappedFile img_file = new MappedFile(input_path + "peppers.jpg");
					FilterReader img_data = new FilterReader(img_file);
					Image img = Image.Create(doc, img_data, 400, 600, 8, ColorSpace.CreateDeviceRGB(), Image.InputFilter.e_jpeg);

					Element element = eb.CreateImage(img, new Matrix2D(200, -145, 20, 300, 200, 150));
					writer.WritePlacedElement(element);

					GState gstate = element.GetGState();	// use the same image (just change its matrix)
					gstate.SetTransform(200, 0, 0, 300, 50, 450);
					writer.WritePlacedElement(element);

					// use the same image again (just change its matrix).
					writer.WritePlacedElement(eb.CreateImage(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 = doc.PageCreate(new Rect(0, 0, 612, 794));

					writer.Begin(page);	// begin writing to this page
					eb.Reset(); 		// Reset GState to default
			

					eb.PathBegin();		// start constructing the path				                            
					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();
					element = eb.PathEnd();			// the path is now finished
					element.SetPathFill(true);		// the path should be filled

					// Set the path color space and color
					gstate = element.GetGState();
					gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK()); 
					gstate.SetFillColor(new ColorPt(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
					element.SetPathStroke(true);		// this path is should be filled and stroked
					gstate.SetFillColor(new ColorPt(0, 0, 1, 0));  // yellow
					gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB()); 
					gstate.SetStrokeColor(new ColorPt(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
					element.SetPathFill(false);	// this path is should be only stroked
					gstate.SetStrokeColor(new ColorPt(0, 0, 1));  // blue
					gstate.SetTransform(0.5, 0, 0, 0.5, 280, 0);
					double[] dash_pattern = {30};
					gstate.SetDashPattern(dash_pattern, 0);
					writer.WritePlacedElement(element);

					// Use the path as a clipping path
					writer.WriteElement(eb.CreateGroupBegin());	// Save the graphics state
					// Start constructing a 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();
					element = eb.PathEnd();	// path is now built
					element.SetPathClip(true);	// this path is a clipping path
					element.SetPathStroke(true);		// this path is should be filled and stroked
					gstate = element.GetGState();
					gstate.SetTransform(0.5, 0, 0, 0.5, -20, 0);
					writer.WriteElement(element);
					writer.WriteElement(eb.CreateImage(img, 100, 300, 400, 600));
					writer.WriteElement(eb.CreateGroupEnd());	// Restore the graphics state

					writer.End();  // save changes to the current page
					doc.PagePushBack(page);


					// Start a new page ------------------------------------
					page = doc.PageCreate(new Rect(0, 0, 612, 794));

					writer.Begin(page);	// begin writing to this page
					eb.Reset(); 		// Reset GState to default

					// Begin writing a block of text
					element = eb.CreateTextBegin(Font.Create(doc, Font.StandardType1Font.e_times_roman), 12);
					writer.WriteElement(element);

					string data = "Hello World!";
					element = eb.CreateTextRun(data);
					element.SetTextMatrix(10, 0, 0, 10, 0, 600);
					element.GetGState().SetLeading(15);		 // Set the spacing between lines
					writer.WriteElement(element);

					writer.WriteElement(eb.CreateTextNewLine());  // New line

					element = eb.CreateTextRun(data);
					gstate = element.GetGState(); 
					gstate.SetTextRenderMode(GState.TextRenderingMode.e_stroke_text);
					gstate.SetCharSpacing(-1.25);
					gstate.SetWordSpacing(-1.25);
					writer.WriteElement(element);

					writer.WriteElement(eb.CreateTextNewLine());  // New line

					element = eb.CreateTextRun(data);
					gstate = element.GetGState(); 
					gstate.SetCharSpacing(0);
					gstate.SetWordSpacing(0);
					gstate.SetLineWidth(3);
					gstate.SetTextRenderMode(GState.TextRenderingMode.e_fill_stroke_text);
					gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB()); 
					gstate.SetStrokeColor(new ColorPt(1, 0, 0));	// red
					gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK()); 
					gstate.SetFillColor(new ColorPt(1, 0, 0, 0));	// cyan
					writer.WriteElement(element);

					writer.WriteElement(eb.CreateTextNewLine());  // New line

					// Set text as a clipping path to the image.
					element = eb.CreateTextRun(data);
					gstate = element.GetGState(); 
					gstate.SetTextRenderMode(GState.TextRenderingMode.e_clip_text);
					writer.WriteElement(element);

					// Finish the block of text
					writer.WriteElement(eb.CreateTextEnd());		

					// Draw an image that will be clipped by the above text
					writer.WriteElement(eb.CreateImage(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.

					using (ElementReader reader = new ElementReader())
					{
						// 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.Begin(doc.GetPage(doc.GetPageCount()));

						page = doc.PageCreate(new Rect(0, 0, 1300, 794));

						writer.Begin(page);	// begin writing to this page
						eb.Reset(); 		// Reset GState to default

						// Embed an external font in the document.
						Font font = Font.CreateTrueTypeFont(doc, input_path + "font.ttf");

						while ((element = reader.Next()) != null) 	// Read page contents
						{
							if (element.GetType() == Element.Type.e_text) 
							{
								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 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.

						// 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.Begin(doc.GetPage(doc.GetPageCount()));

						page = doc.PageCreate(new Rect(0, 0, 1300, 794));

						writer.Begin(page);	// begin writing to this page
						eb.Reset(); 		// Reset GState to default

						// Embed an external font in the document.
						Font font2 = Font.CreateType1Font(doc, input_path + "Misc-Fixed.pfa");

						while ((element = reader.Next()) != null) 	// Read page contents
						{
							if (element.GetType() == Element.Type.e_text) 
							{
								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 = doc.PageCreate();
						writer.Begin(page);	// begin writing to this page
						eb.Reset(); 		// Reset GState to default

						// Begin writing a block of text
						element = eb.CreateTextBegin(Font.Create(doc, Font.StandardType1Font.e_times_roman), 12);
						element.SetTextMatrix(1.5, 0, 0, 1.5, 50, 600);
						element.GetGState().SetLeading(15);	// Set the spacing between lines
						writer.WriteElement(element);

						string 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";

						int para_end = para.Length;
						int text_run = 0;
						int text_run_end;

						double para_width = 300; // paragraph width is 300 units
						double cur_width = 0;

						while (text_run < para_end) 
						{
							text_run_end = para.IndexOf(' ', text_run);
							if (text_run_end < 0)
								text_run_end = para_end - 1;

							string text = para.Substring(text_run, text_run_end-text_run+1); 
							element = eb.CreateTextRun(text);
							if (cur_width + element.GetTextLength() < para_width) 
							{
								writer.WriteElement(element);
								cur_width += element.GetTextLength();
							}
							else 
							{
								writer.WriteElement(eb.CreateTextNewLine());  // New line
								text = para.Substring(text_run, text_run_end-text_run+1); 
								element = eb.CreateTextRun(text);
								cur_width = element.GetTextLength();
								writer.WriteElement(element);
							}

							text_run = text_run_end+1;
						}

						// -----------------------------------------------------------------------
						// The following code snippet illustrates how to adjust spacing between 
						// characters (text runs).
						element = eb.CreateTextNewLine();
						writer.WriteElement(element);  // Skip 2 lines
						writer.WriteElement(element);

						writer.WriteElement(eb.CreateTextRun("An example of space adjustments between inter-characters:"));
						writer.WriteElement(eb.CreateTextNewLine());

						// Write string "AWAY" without space adjustments between characters.
						element = eb.CreateTextRun("AWAY");
						writer.WriteElement(element);

						writer.WriteElement(eb.CreateTextNewLine());

						// Write string "AWAY" with space adjustments between characters.
						element = eb.CreateTextRun("A");
						writer.WriteElement(element);

						element = eb.CreateTextRun("W");
						element.SetPosAdjustment(140);
						writer.WriteElement(element);

						element = eb.CreateTextRun("A");
						element.SetPosAdjustment(140);
						writer.WriteElement(element);

						element = eb.CreateTextRun("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* "); // New Lines 
						// writer.WriteElement(eb.CreateTextNewLine()); 
						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(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 = doc.PageCreate();
						writer.Begin(page); // begin writing to the page

						// Create the Image Mask
						MappedFile imgf = new MappedFile(input_path + "imagemask.dat");
						FilterReader mask_read = new FilterReader(imgf);

						ColorSpace device_gray = ColorSpace.CreateDeviceGray();
						Image mask = Image.Create(doc, mask_read, 64, 64, 1, device_gray, Image.InputFilter.e_ascii_hex);

						mask.GetSDFObj().PutBool("ImageMask", true);

						element = eb.CreateRect(0, 0, 612, 794);
						element.SetPathStroke(false);
						element.SetPathFill(true);
						element.GetGState().SetFillColorSpace(device_gray);
						element.GetGState().SetFillColor(new ColorPt(0.8));
						writer.WritePlacedElement(element);

						element = eb.CreateImage(mask, new Matrix2D(200, 0, 0, -200, 40, 680));
						element.GetGState().SetFillColor(new ColorPt(0.1));
						writer.WritePlacedElement(element);

						element.GetGState().SetFillColorSpace(ColorSpace.CreateDeviceRGB());
						element.GetGState().SetFillColor(new ColorPt(1, 0, 0));
						element = eb.CreateImage(mask, new Matrix2D(200, 0, 0, -200, 320, 680));
						writer.WritePlacedElement(element);

						element.GetGState().SetFillColor(new ColorPt(0, 1, 0));
						element = eb.CreateImage(mask, new Matrix2D(200, 0, 0, -200, 40, 380));
						writer.WritePlacedElement(element);

						{
							// This sample illustrates Explicit Masking. 
							img = Image.Create(doc, input_path + "peppers.jpg");

							// mask is the explicit mask for the primary (base) image
							img.SetMask(mask);

							element = eb.CreateImage(img, new Matrix2D(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 = doc.PageCreate();
						writer.Begin(page);	// begin writing to this page
						eb.Reset();			// Reset the GState to default

						// Write some transparent text at the bottom of the page.
						element = eb.CreateTextBegin(Font.Create(doc, Font.StandardType1Font.e_times_roman), 100);

						// Set the text knockout attribute. Text knockout must be set outside of 
						// the text group.
						gstate = element.GetGState();
						gstate.SetTextKnockout(false);
						gstate.SetBlendMode(GState.BlendMode.e_bl_difference);
						writer.WriteElement(element);

						element = eb.CreateTextRun("Transparency");
						element.SetTextMatrix(1, 0, 0, 1, 30, 30);
						gstate = element.GetGState();
						gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK());
						gstate.SetFillColor(new ColorPt(1, 0, 0, 0));

						gstate.SetFillOpacity(0.5);
						writer.WriteElement(element);

						// Write the same text on top the old; shifted by 3 points
						element.SetTextMatrix(1, 0, 0, 1, 33, 33);
						gstate.SetFillColor(new ColorPt(0, 1, 0, 0));
						gstate.SetFillOpacity(0.5);

						writer.WriteElement(element);
						writer.WriteElement(eb.CreateTextEnd());

						// Draw three overlapping transparent circles.
						eb.PathBegin();		// start constructing the path
						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 = eb.PathEnd();
						element.SetPathFill(true);

						gstate = element.GetGState();
						gstate.SetFillColorSpace(ColorSpace.CreateDeviceRGB());
						gstate.SetFillColor(new ColorPt(0, 0, 1));                     // Blue Circle

						gstate.SetBlendMode(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.SetFillColor(new ColorPt(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.SetFillColor(new ColorPt(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 ------------------------------------
					}

					doc.Save(output_path + "element_builder.pdf", SDFDoc.SaveOptions.e_remove_unused);
					Console.WriteLine("Done. Result saved in element_builder.pdf...");
				}
			}
			catch (PDFNetException e)
			{
				Console.WriteLine(e.Message);
			}
			PDFNet.Terminate();
		}
	}
}
```

{% endcode %}
{% endtab %}

{% tab title="Go" %}
{% code lineNumbers="true" %}

```go
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2021 by PDFTron Systems Inc. All Rights Reserved.
// Consult LICENSE.txt regarding license information.
//---------------------------------------------------------------------------------------

package main
import (
    "fmt"
    "strings"
    . "pdftron"
)

import  "pdftron/Samples/LicenseKey/GO"

// Relative path to the folder containing the test files.
var inputPath = "../../TestFiles/"
var outputPath = "../../TestFiles/Output/"

func Find(s, substr string, offset int) int {
    if len(s) < offset {
        return -1
    }
    if idx := strings.Index(s[offset:], substr); idx >= 0 {
        return offset + idx
    }
    return -1
}

//-----------------------------------------------------------------------------------------------------------------------
func main(){
    PDFNetInitialize(PDFTronLicense.Key)
    
    doc := NewPDFDoc()
    
    // ElementBuilder is used to build new Element objects
    eb := NewElementBuilder()
    // ElementWriter is used to write Elements to the page
    writer := NewElementWriter()
    
    // Start a new page ------------------------------------
    page := doc.PageCreate(NewRect(0.0, 0.0, 612.0, 794.0))
    
    writer.Begin(page)  // begin writing to the page

    // Create an Image that can be reused in the document or on the same page.
    img := ImageCreate(doc.GetSDFDoc(), inputPath + "peppers.jpg")
    
    element := eb.CreateImage(img, NewMatrix2D(float64(img.GetImageWidth()/2), -145.0, 20.0, float64(img.GetImageHeight()/2), 200.0, 150.0))
    writer.WritePlacedElement(element)
    
    gstate := element.GetGState()    // use the same image (just change its matrix)
    gstate.SetTransform(200.0, 0.0, 0.0, 300.0, 50.0, 450.0)
    writer.WritePlacedElement(element)
    
    // use the same image again (just change its matrix)
    writer.WritePlacedElement(eb.CreateImage(img, 300.0, 600.0, 200.0, -150.0))
    
    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 = doc.PageCreate(NewRect(0.0, 0.0, 612.0, 794.0))
    
    writer.Begin(page)  // begin writing to this page
    eb.Reset()          // Reset the GState to default
    
    eb.PathBegin()      // start constructing the path
    eb.MoveTo(306.0, 396.0)
    eb.CurveTo(681.0, 771.0, 399.75, 864.75, 306.0, 771.0)
    eb.CurveTo(212.25, 864.75, -69, 771.0, 306.0, 396.0)
    eb.ClosePath()
    element = eb.PathEnd()      // the path is now finished
    element.SetPathFill(true)   // the path should be filled
    
    // Set the path color space and color
    gstate = element.GetGState()
    gstate.SetFillColorSpace(ColorSpaceCreateDeviceCMYK())
    gstate.SetFillColor(NewColorPt(1.0, 0.0, 0.0, 0.0))  // cyan
    gstate.SetTransform(0.5, 0.0, 0.0, 0.5, -20.0, 300.0)
    writer.WritePlacedElement(element)
    
    // Draw the same path using a different stroke color
    element.SetPathStroke(true)     // this path is should be filled and stroked
    gstate.SetFillColor(NewColorPt(0.0, 0.0, 1.0, 0.0))  // yellow
    gstate.SetStrokeColorSpace(ColorSpaceCreateDeviceRGB())
    gstate.SetStrokeColor(NewColorPt(1.0, 0.0, 0.0))  // red
    gstate.SetTransform(0.5, 0.0, 0.0, 0.5, 280.0, 300.0)
    gstate.SetLineWidth(20)
    writer.WritePlacedElement(element)
    
    // Draw the same path with a given dash pattern
    element.SetPathFill(false)      // this path should be only stroked
    
    gstate.SetStrokeColor(NewColorPt(0.0,0.0,1.0))   // blue
    gstate.SetTransform(0.5, 0.0, 0.0, 0.5, 280.0, 0.0)
    dashPattern := NewVectorDouble()
    dashPattern.Add(30.0)
    gstate.SetDashPattern(dashPattern, 0)
    writer.WritePlacedElement(element)
    
    // Use the path as a clipping path
    writer.WriteElement(eb.CreateGroupBegin())    // Save the graphics state
    // Start constructing the new path (the old path was lost when we created 
    // a new Element using CreateGroupBegin()).
    eb.PathBegin()
    eb.MoveTo(306.0, 396.0)
    eb.CurveTo(681.0, 771.0, 399.75, 864.75, 306.0, 771.0)
    eb.CurveTo(212.25, 864.75, -69.0, 771.0, 306.0, 396.0)
    eb.ClosePath()
    element = eb.PathEnd()    // path is now constructed
    element.SetPathClip(true)    // this path is a clipping path
    element.SetPathStroke(true)        // this path should be filled and stroked
    gstate = element.GetGState()
    gstate.SetTransform(0.5, 0.0, 0.0, 0.5, -20.0, 0.0)
    
    writer.WriteElement(element)

    writer.WriteElement(eb.CreateImage(img, 100.0, 300.0, 400.0, 600.0))
        
    writer.WriteElement(eb.CreateGroupEnd())    // Restore the graphics state

    writer.End()  // save changes to the current page
    doc.PagePushBack(page)

    // Start a new page ------------------------------------
    page = doc.PageCreate(NewRect(0.0, 0.0, 612.0, 794.0))

    writer.Begin(page)    // begin writing to this page
    eb.Reset()          // Reset the GState to default

    // Begin writing a block of text
    element = eb.CreateTextBegin(FontCreate(doc.GetSDFDoc(), FontE_times_roman), 12.0)
    writer.WriteElement(element)

    element = eb.CreateTextRun("Hello World!")
    element.SetTextMatrix(10.0, 0.0, 0.0, 10.0, 0.0, 600.0)
    element.GetGState().SetLeading(15)         // Set the spacing between lines
    writer.WriteElement(element)

    writer.WriteElement(eb.CreateTextNewLine())  // New line

    element = eb.CreateTextRun("Hello World!")
    gstate = element.GetGState() 
    gstate.SetTextRenderMode(GStateE_stroke_text)
    gstate.SetCharSpacing(-1.25)
    gstate.SetWordSpacing(-1.25)
    writer.WriteElement(element)

    writer.WriteElement(eb.CreateTextNewLine())  // New line

    element = eb.CreateTextRun("Hello World!")
    gstate = element.GetGState() 
    gstate.SetCharSpacing(0)
    gstate.SetWordSpacing(0)
    gstate.SetLineWidth(3)
    gstate.SetTextRenderMode(GStateE_fill_stroke_text)
    gstate.SetStrokeColorSpace(ColorSpaceCreateDeviceRGB()) 
    gstate.SetStrokeColor(NewColorPt(1.0, 0.0, 0.0))    // red
    gstate.SetFillColorSpace(ColorSpaceCreateDeviceCMYK()) 
    gstate.SetFillColor(NewColorPt(1.0, 0.0, 0.0, 0.0))    // cyan
    writer.WriteElement(element)
    
    writer.WriteElement(eb.CreateTextNewLine())  // New line

    // Set text as a clipping path to the image.
    element = eb.CreateTextRun("Hello World!")
    gstate = element.GetGState() 
    gstate.SetTextRenderMode(GStateE_clip_text)
    writer.WriteElement(element)

    // Finish the block of text
    writer.WriteElement(eb.CreateTextEnd())        

    // Draw an image that will be clipped by the above text
    writer.WriteElement(eb.CreateImage(img, 10.0, 100.0, 1300.0, 720.0))

    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.

    reader := NewElementReader()

    // 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.Begin(doc.GetPage(uint(doc.GetPageCount())))

    page = doc.PageCreate(NewRect(0.0, 0.0, 1300.0, 794.0))

    writer.Begin(page)    // begin writing to this page
    eb.Reset()          // Reset the GState to default

    // Embed an external font in the document.
    font := FontCreateTrueTypeFont(doc.GetSDFDoc(), (inputPath + "font.ttf"))
    element = reader.Next()
    for element.GetMp_elem().Swigcptr() != 0{
        if element.GetType() == ElementE_text{
            element.GetGState().SetFont(font, 12.0)
        }
        writer.WriteElement(element)
        element = reader.Next()
    }
    

    reader.End()
    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.

    // 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.Begin(doc.GetPage(uint(doc.GetPageCount())))

    page = doc.PageCreate(NewRect(0.0, 0.0, 1300.0, 794.0))

    writer.Begin(page)    // begin writing to this page
    eb.Reset()          // Reset the GState to default

    // Embed an external font in the document.
    font2 := FontCreateType1Font(doc.GetSDFDoc(), (inputPath + "Misc-Fixed.pfa"))
    
    element = reader.Next()
    for element.GetMp_elem().Swigcptr() != 0{
        if element.GetType() == ElementE_text{
            element.GetGState().SetFont(font2, 12.0)
        }
        writer.WriteElement(element)
        element = reader.Next()
    }

    reader.End()
    writer.End()    // save changes to the current page
    doc.PagePushBack(page)
    // Start a new page ------------------------------------
    page = doc.PageCreate()
    writer.Begin(page)    // begin writing to this page
    eb.Reset()          // Reset the GState to default

    // Begin writing a block of text
    element = eb.CreateTextBegin(FontCreate(doc.GetSDFDoc(), FontE_times_roman), 12.0)
    element.SetTextMatrix(1.5, 0.0, 0.0, 1.5, 50.0, 600.0)
    element.GetGState().SetLeading(15)    // Set the spacing between lines
    writer.WriteElement(element)
    
    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\n"

    paraEnd := len(para)
    textRun := 0
    
    paraWidth := 300 // paragraph width is 300 units 
    curWidth := 0

    for textRun < paraEnd{
        textRunEnd := Find(para, " ", textRun)  
        if textRunEnd < 0{
            textRunEnd = paraEnd - 1
        }
        text := para[textRun:textRunEnd+1]
        element = eb.CreateTextRun(text)
        if curWidth + int(element.GetTextLength() )< paraWidth{
            writer.WriteElement(element)
            curWidth = curWidth + int(element.GetTextLength())
        }else{
            writer.WriteElement(eb.CreateTextNewLine())    // new line
            element = eb.CreateTextRun(text)
            curWidth = int(element.GetTextLength())
            writer.WriteElement(element)
        }
        textRun = textRunEnd + 1
    }
    
    // -----------------------------------------------------------------------
    // The following code snippet illustrates how to adjust spacing between 
    // characters (text runs).
    element = eb.CreateTextNewLine()
    writer.WriteElement(element)  // Skip 2 lines
    writer.WriteElement(element) 
        
    writer.WriteElement(eb.CreateTextRun("An example of space adjustments between inter-characters:")) 
    writer.WriteElement(eb.CreateTextNewLine()) 
        
    // Write string "AWAY" without space adjustments between characters.
    element = eb.CreateTextRun("AWAY")
    writer.WriteElement(element)  
        
    writer.WriteElement(eb.CreateTextNewLine()) 
        
    // Write string "AWAY" with space adjustments between characters.
    element = eb.CreateTextRun("A")
    writer.WriteElement(element)
        
    element = eb.CreateTextRun("W")
    element.SetPosAdjustment(140)
    writer.WriteElement(element)
        
    element = eb.CreateTextRun("A")
    element.SetPosAdjustment(140)
    writer.WriteElement(element)
        
    element = eb.CreateTextRun("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(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 = doc.PageCreate()
    writer.Begin(page)    // begin writing to the page

    // Create the Image Mask
    imgf := NewMappedFile(inputPath + "imagemask.dat")
    maskRead := NewFilterReader(imgf)

    deviceGray := ColorSpaceCreateDeviceGray()
    mask := ImageCreate(doc.GetSDFDoc(), maskRead, 64, 64, 1, deviceGray, ImageE_ascii_hex)
    
    mask.GetSDFObj().PutBool("ImageMask", true)

    element = eb.CreateRect(0, 0, 612, 794)
    element.SetPathStroke(false)
    element.SetPathFill(true)
    element.GetGState().SetFillColorSpace(deviceGray)
    element.GetGState().SetFillColor(NewColorPt(0.8))
    writer.WritePlacedElement(element)

    element = eb.CreateImage(mask, NewMatrix2D(200.0, 0.0, 0.0, -200.0, 40.0, 680.0))
    element.GetGState().SetFillColor(NewColorPt(0.1))
    writer.WritePlacedElement(element)

    element.GetGState().SetFillColorSpace(ColorSpaceCreateDeviceRGB())
    element.GetGState().SetFillColor(NewColorPt(1.0, 0.0, 0.0))
    element = eb.CreateImage(mask, NewMatrix2D(200.0, 0.0, 0.0, -200.0, 320.0, 680.0))
    writer.WritePlacedElement(element)

    element.GetGState().SetFillColor(NewColorPt(0.0, 1.0, 0.0))
    element = eb.CreateImage(mask, NewMatrix2D(200.0, 0.0, 0.0, -200.0, 40.0, 380.0))
    writer.WritePlacedElement(element)
    
    // This sample illustrates Explicit Masking. 
    img = ImageCreate(doc.GetSDFDoc(), (inputPath + "peppers.jpg"))

    // mask is the explicit mask for the primary (base) image
    img.SetMask(mask)

    element = eb.CreateImage(img, NewMatrix2D(200.0, 0.0, 0.0, -200.0, 320.0, 380.0))
    writer.WritePlacedElement(element)
    
    writer.End()  // save changes to the current page
    doc.PagePushBack(page)
    
    // Transparency sample ----------------------------------
        
    // Start a new page -------------------------------------
    page = doc.PageCreate()
    writer.Begin(page)    // begin writing to this page
    eb.Reset()          // Reset the GState to default

    // Write some transparent text at the bottom of the page.
    element = eb.CreateTextBegin(FontCreate(doc.GetSDFDoc(), FontE_times_roman), 100.0)

    // Set the text knockout attribute. Text knockout must be set outside of 
    // the text group.
    gstate = element.GetGState()
    gstate.SetTextKnockout(false)
    gstate.SetBlendMode(GStateE_bl_difference)
    writer.WriteElement(element)

    element = eb.CreateTextRun("Transparency")
    element.SetTextMatrix(1.0, 0.0, 0.0, 1.0, 30.0, 30.0)
    gstate = element.GetGState()
    gstate.SetFillColorSpace(ColorSpaceCreateDeviceCMYK())
    gstate.SetFillColor(NewColorPt(1.0, 0.0, 0.0, 0.0))

    gstate.SetFillOpacity(0.5)
    writer.WriteElement(element)

    // Write the same text on top the old; shifted by 3 points
    element.SetTextMatrix(1.0, 0.0, 0.0, 1.0, 33.0, 33.0)
    gstate.SetFillColor(NewColorPt(0.0, 1.0, 0.0, 0.0))
    gstate.SetFillOpacity(0.5)

    writer.WriteElement(element)
    writer.WriteElement(eb.CreateTextEnd())

    // Draw three overlapping transparent circles.
    eb.PathBegin()        // start constructing the path
    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 = eb.PathEnd()
    element.SetPathFill(true)
    
    gstate = element.GetGState()
    gstate.SetFillColorSpace(ColorSpaceCreateDeviceRGB())
    gstate.SetFillColor(NewColorPt(0.0, 0.0, 1.0))                     // Blue Circle

    gstate.SetBlendMode(GStateE_bl_normal)
    gstate.SetFillOpacity(0.5)
    writer.WriteElement(element)

    // Translate relative to the Blue Circle
    gstate.SetTransform(1.0, 0.0, 0.0, 1.0, 113.0, -185.0)                
    gstate.SetFillColor(NewColorPt(0.0, 1.0, 0.0))                     // Green Circle
    gstate.SetFillOpacity(0.5)
    writer.WriteElement(element)

    // Translate relative to the Green Circle
    gstate.SetTransform(1.0, 0.0, 0.0, 1.0, -220.0, 0.0)
    gstate.SetFillColor(NewColorPt(1.0, 0.0, 0.0))                     // Red Circle
    gstate.SetFillOpacity(0.5)
    writer.WriteElement(element)

    writer.End()  // save changes to the current page
    doc.PagePushBack(page)

    // End page ------------------------------------

    doc.Save((outputPath + "element_builder.pdf"), uint(SDFDocE_remove_unused))
    doc.Close()
    PDFNetTerminate()
    fmt.Println("Done. Result saved in element_builder.pdf...")
}
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

import com.pdftron.common.Matrix2D;
import com.pdftron.pdf.*;
import com.pdftron.sdf.SDFDoc;
import com.pdftron.filters.*;
import java.io.*;

public class ElementBuilderTest {


    public static void main(String[] args) {
        PDFNet.initialize(PDFTronLicense.Key());

        // Relative path to the folder containing test files.
        String input_path = "../../TestFiles/";
        String output_path = "../../TestFiles/Output/";

        InputStream stream = null;
        try (PDFDoc doc = new PDFDoc()) {        
            ElementBuilder eb = new ElementBuilder();        // ElementBuilder is used to build new
            // Element objects
            ElementWriter writer = new ElementWriter();    // ElementWriter is used to write
            // Elements to the page

            Element element;
            GState gstate;

            // Start a new page ------------------------------------
            Page page = doc.pageCreate(new Rect(0, 0, 612, 794));

            writer.begin(page);    // begin writing to the page

            // Create an Image that can be reused in the document or on the
            // same page.
            Image img = Image.create(doc.getSDFDoc(), (input_path + "peppers.jpg"));

            element = eb.createImage(img, new Matrix2D(img.getImageWidth() / 2, -145, 20, img.getImageHeight() / 2, 200, 150));
            writer.writePlacedElement(element);

            gstate = element.getGState();    // use the same image (just
            // change its matrix)
            gstate.setTransform(200, 0, 0, 300, 50, 450);
            writer.writePlacedElement(element);

            // use the same image again (just change its matrix).
            writer.writePlacedElement(eb.createImage(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 = doc.pageCreate(new Rect(0, 0, 612, 794));

            writer.begin(page);    // begin writing to this page
            eb.reset();            // Reset the GState to default

            eb.pathBegin();        // start constructing the path
            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();
            element = eb.pathEnd();            // the path is now finished
            element.setPathFill(true);        // the path should be filled

            // Set the path color space and color
            gstate = element.getGState();
            gstate.setFillColorSpace(ColorSpace.createDeviceCMYK());
            gstate.setFillColor(new ColorPt(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
            element.setPathStroke(true);        // this path is should be
            // filled and stroked
            gstate.setFillColor(new ColorPt(0, 0, 1, 0));  // yellow
            gstate.setStrokeColorSpace(ColorSpace.createDeviceRGB());
            gstate.setStrokeColor(new ColorPt(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
            element.setPathFill(false);    // this path is should be only
            // stroked
            gstate.setStrokeColor(new ColorPt(0, 0, 1));  // blue
            gstate.setTransform(0.5, 0, 0, 0.5, 280, 0);
            double[] dash_pattern = {30};
            gstate.setDashPattern(dash_pattern, 0);
            writer.writePlacedElement(element);

            // Use the path as a clipping path
            writer.writeElement(eb.createGroupBegin());    // Save the graphics
            // state
            // 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();
            element = eb.pathEnd();    // path is now constructed
            element.setPathClip(true);    // this path is a clipping path
            element.setPathStroke(true);        // this path should be
            // filled and stroked
            gstate = element.getGState();
            gstate.setTransform(0.5, 0, 0, 0.5, -20, 0);

            writer.writeElement(element);

            writer.writeElement(eb.createImage(img, 100, 300, 400, 600));

            writer.writeElement(eb.createGroupEnd());    // Restore the
            // graphics state

            writer.end();  // save changes to the current page
            doc.pagePushBack(page);


            // Start a new page ------------------------------------
            page = doc.pageCreate(new Rect(0, 0, 612, 794));

            writer.begin(page);    // begin writing to this page
            eb.reset();            // Reset the GState to default

            // Begin writing a block of text
            element = eb.createTextBegin(Font.create(doc, Font.e_times_roman), 12);
            writer.writeElement(element);

            element = eb.createTextRun("Hello World!");
            element.setTextMatrix(10, 0, 0, 10, 0, 600);
            element.getGState().setLeading(15);         // Set the spacing
            // between lines
            writer.writeElement(element);

            writer.writeElement(eb.createTextNewLine());  // New line

            element = eb.createTextRun("Hello World!");
            gstate = element.getGState();
            gstate.setTextRenderMode(GState.e_stroke_text);
            gstate.setCharSpacing(-1.25);
            gstate.setWordSpacing(-1.25);
            writer.writeElement(element);

            writer.writeElement(eb.createTextNewLine());  // New line

            element = eb.createTextRun("Hello World!");
            gstate = element.getGState();
            gstate.setCharSpacing(0);
            gstate.setWordSpacing(0);
            gstate.setLineWidth(3);
            gstate.setTextRenderMode(GState.e_fill_stroke_text);
            gstate.setStrokeColorSpace(ColorSpace.createDeviceRGB());
            gstate.setStrokeColor(new ColorPt(1, 0, 0));    // red
            gstate.setFillColorSpace(ColorSpace.createDeviceCMYK());
            gstate.setFillColor(new ColorPt(1, 0, 0, 0));    // cyan
            writer.writeElement(element);


            writer.writeElement(eb.createTextNewLine());  // New line

            // Set text as a clipping path to the image.
            element = eb.createTextRun("Hello World!");
            gstate = element.getGState();
            gstate.setTextRenderMode(GState.e_clip_text);
            writer.writeElement(element);

            // Finish the block of text
            writer.writeElement(eb.createTextEnd());

            // Draw an image that will be clipped by the above text
            writer.writeElement(eb.createImage(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.

            ElementReader reader = new ElementReader();

            // 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.begin((doc.getPage(doc.getPageCount())));

            page = doc.pageCreate(new Rect(0, 0, 1300, 794));

            writer.begin(page);    // begin writing to this page
            eb.reset();        // Reset the GState to default

            // Embed an external font in the document.
            Font font;
            File file = new File(input_path, "font.ttf");
            stream = new FileInputStream(file);
            font = Font.createTrueTypeFont(doc, stream);
            //Alternatively, the font can be created from the file path.
            //font = Font.createTrueTypeFont(doc, (input_path + "font.ttf"));

            while ((element = reader.next()) != null)    // Read page
            // contents
            {
                if (element.getType() == Element.e_text) {
                    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 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.

            // 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.begin(((doc.getPage(doc.getPageCount()))));

            page = doc.pageCreate(new Rect(0, 0, 1300, 794));

            writer.begin(page);    // begin writing to this page
            eb.reset();        // Reset the GState to default

            // Embed an external font in the document.
            Font font2 = Font.createType1Font(doc, (input_path + "Misc-Fixed.pfa"));

            while ((element = reader.next()) != null)    // Read page contents
            {
                if (element.getType() == Element.e_text) {
                    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 = doc.pageCreate();
            writer.begin(page);    // begin writing to this page
            eb.reset();            // Reset the GState to default

            // Begin writing a block of text
            element = eb.createTextBegin(Font.create(doc, Font.e_times_roman), 12);
            element.setTextMatrix(1.5, 0, 0, 1.5, 50, 600);
            element.getGState().setLeading(15);    // Set the spacing between
            // lines
            writer.writeElement(element);

            String 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";

            int para_end = para.length();
            int text_run = 0;
            int text_run_end;

            double para_width = 300; // paragraph width is 300 units
            double cur_width = 0;

            while (text_run < para_end) {
                text_run_end = para.indexOf(' ', text_run);
                if (text_run_end < 0)
                    text_run_end = para_end - 1;

                String text = para.substring(text_run, text_run_end + 1);
                element = eb.createTextRun(text);
                if (cur_width + element.getTextLength() < para_width) {
                    writer.writeElement(element);
                    cur_width += element.getTextLength();
                } else {
                    writer.writeElement(eb.createTextNewLine());  // New
                    text = para.substring(text_run, text_run_end + 1);                                            // line
                    element = eb.createTextRun(text);
                    cur_width = element.getTextLength();
                    writer.writeElement(element);
                }

                text_run = text_run_end + 1;
            }

            // -----------------------------------------------------------------------
            // The following code snippet illustrates how to adjust
            // spacing between
            // characters (text runs).
            element = eb.createTextNewLine();
            writer.writeElement(element);  // Skip 2 lines
            writer.writeElement(element);

            writer.writeElement(eb.createTextRun("An example of space adjustments between inter-characters:"));
            writer.writeElement(eb.createTextNewLine());

            // Write string "AWAY" without space adjustments between
            // characters.
            element = eb.createTextRun("AWAY");
            writer.writeElement(element);

            writer.writeElement(eb.createTextNewLine());

            // Write string "AWAY" with space adjustments between
            // characters.
            element = eb.createTextRun("A");
            writer.writeElement(element);

            element = eb.createTextRun("W");
            element.setPosAdjustment(140);
            writer.writeElement(element);

            element = eb.createTextRun("A");
            element.setPosAdjustment(140);
            writer.writeElement(element);

            element = eb.createTextRun("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(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 = doc.pageCreate();
            writer.begin(page);    // begin writing to the page

            // Create the Image Mask
            MappedFile imgf=new MappedFile(input_path + "imagemask.dat");
            com.pdftron.filters.FilterReader mask_read=new com.pdftron.filters.FilterReader(imgf);

            ColorSpace device_gray = ColorSpace.createDeviceGray();
            Image mask = Image.create(doc, mask_read, 64, 64, 1, device_gray, Image.e_ascii_hex);

            mask.getSDFObj().putBool("ImageMask", true);

            element = eb.createRect(0, 0, 612, 794);
            element.setPathStroke(false);
            element.setPathFill(true);
            element.getGState().setFillColorSpace(device_gray);
            element.getGState().setFillColor(new ColorPt(0.8,0,0));
            writer.writePlacedElement(element);

            element = eb.createImage(mask, new Matrix2D(200, 0, 0, -200, 40, 680));
            element.getGState().setFillColor(new ColorPt(0.1,0,0));
            writer.writePlacedElement(element);

            element.getGState().setFillColorSpace(ColorSpace.createDeviceRGB());
            element.getGState().setFillColor(new ColorPt(1, 0, 0));
            element = eb.createImage(mask, new Matrix2D(200, 0, 0, -200, 320, 680));
            writer.writePlacedElement(element);

            element.getGState().setFillColor(new ColorPt(0, 1, 0));
            element = eb.createImage(mask, new Matrix2D(200, 0, 0, -200, 40, 380));
            writer.writePlacedElement(element);

            {
                // This sample illustrates Explicit Masking.
                img = Image.create(doc, (input_path + "peppers.jpg"));

                // mask is the explicit mask for the primary (base) image
                img.setMask(mask);

                element = eb.createImage(img, new Matrix2D(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 = doc.pageCreate();
            writer.begin(page);    // begin writing to this page
            eb.reset();            // Reset the GState to default

            // Write some transparent text at the bottom of the page.
            element = eb.createTextBegin(Font.create(doc, Font.e_times_roman), 100);

            // Set the text knockout attribute. Text knockout must be set
            // outside of
            // the text group.
            gstate = element.getGState();
            gstate.setTextKnockout(false);
            gstate.setBlendMode(GState.e_bl_difference);
            writer.writeElement(element);

            element = eb.createTextRun("Transparency");
            element.setTextMatrix(1, 0, 0, 1, 30, 30);
            gstate = element.getGState();
            gstate.setFillColorSpace(ColorSpace.createDeviceCMYK());
            gstate.setFillColor(new ColorPt(1, 0, 0, 0));

            gstate.setFillOpacity(0.5);
            writer.writeElement(element);

            // Write the same text on top the old; shifted by 3 points
            element.setTextMatrix(1, 0, 0, 1, 33, 33);
            gstate.setFillColor(new ColorPt(0, 1, 0, 0));
            gstate.setFillOpacity(0.5);

            writer.writeElement(element);
            writer.writeElement(eb.createTextEnd());

            // Draw three overlapping transparent circles.
            eb.pathBegin();        // start constructing the path
            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 = eb.pathEnd();
            element.setPathFill(true);

            gstate = element.getGState();
            gstate.setFillColorSpace(ColorSpace.createDeviceRGB());
            gstate.setFillColor(new ColorPt(0, 0, 1));                     // Blue
            // Circle

            gstate.setBlendMode(GState.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.setFillColor(new ColorPt(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.setFillColor(new ColorPt(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 ------------------------------------

            doc.save((output_path + "element_builder.pdf"), SDFDoc.SaveMode.REMOVE_UNUSED, null);
            System.out.println("Done. Result saved in element_builder.pdf...");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (Exception ignored) {
                }
            }
        }

        PDFNet.terminate();
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="C++" %}
{% code lineNumbers="true" %}

```cpp
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

#include <SDF/Obj.h>
#include <PDF/PDFNet.h>
#include <PDF/PDFDoc.h>
#include <PDF/ElementBuilder.h>
#include <PDF/ElementWriter.h>
#include <PDF/ElementReader.h>

#include <Filters/MappedFile.h>
#include <Filters/FilterReader.h>

#include <SDF/SDFDoc.h>
#include <iostream>
#include "../../LicenseKey/CPP/LicenseKey.h"

using namespace std;
using namespace pdftron;
using namespace SDF;
using namespace PDF;
using namespace Filters;

int main(int argc, char *argv[])
{
	int ret = 0;
	PDFNet::Initialize(LicenseKey);

	// Relative path to the folder containing test files.
	string input_path =  "../../TestFiles/";
	string output_path = "../../TestFiles/Output/";

	try  
	{	 
		PDFDoc doc;

		ElementBuilder eb;		// ElementBuilder is used to build new Element objects
		ElementWriter writer;	// ElementWriter is used to write Elements to the page	

		Element element;
		GState gstate;

		// Start a new page ------------------------------------
		Page page = doc.PageCreate(Rect(0, 0, 612, 794));

		writer.Begin(page);	// begin writing to the page

		// Create an Image that can be reused in the document or on the same page.		
		Image img = Image::Create(doc, (input_path + "peppers.jpg").c_str());

		element = eb.CreateImage(img, Common::Matrix2D(img.GetImageWidth()/2, -145, 20, img.GetImageHeight()/2, 200, 150));
		writer.WritePlacedElement(element);

		gstate = element.GetGState();	// use the same image (just change its matrix)
		gstate.SetTransform(200, 0, 0, 300, 50, 450);
		writer.WritePlacedElement(element);

		// use the same image again (just change its matrix).
		writer.WritePlacedElement(eb.CreateImage(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 = doc.PageCreate(Rect(0, 0, 612, 794));

		writer.Begin(page);	// begin writing to this page
		eb.Reset();			// Reset the GState to default

		eb.PathBegin();		// start constructing the path
		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();
		element = eb.PathEnd();			// the path is now finished
		element.SetPathFill(true);		// the path should be filled

		// Set the path color space and color
		gstate = element.GetGState();
		gstate.SetFillColorSpace(ColorSpace::CreateDeviceCMYK()); 
		gstate.SetFillColor(ColorPt(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
		element.SetPathStroke(true);		// this path is should be filled and stroked
		gstate.SetFillColor(ColorPt(0, 0, 1, 0));  // yellow
		gstate.SetStrokeColorSpace(ColorSpace::CreateDeviceRGB()); 
		gstate.SetStrokeColor(ColorPt(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
		element.SetPathFill(false);	// this path is should be only stroked
		gstate.SetStrokeColor(ColorPt(0, 0, 1));  // blue
		gstate.SetTransform(0.5, 0, 0, 0.5, 280, 0);
		vector<double> dash_pattern;
		dash_pattern.push_back(30);
		gstate.SetDashPattern(dash_pattern, 0);
		writer.WritePlacedElement(element);

		// Use the path as a clipping path
		writer.WriteElement(eb.CreateGroupBegin());	// Save the graphics state
		// 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();
		element = eb.PathEnd();	// path is now constructed
		element.SetPathClip(true);	// this path is a clipping path
		element.SetPathStroke(true);		// this path should be filled and stroked
		gstate = element.GetGState();
		gstate.SetTransform(0.5, 0, 0, 0.5, -20, 0);

		writer.WriteElement(element);

		writer.WriteElement(eb.CreateImage(img, 100, 300, 400, 600));
		
		writer.WriteElement(eb.CreateGroupEnd());	// Restore the graphics state

		writer.End();  // save changes to the current page
		doc.PagePushBack(page);


		// Start a new page ------------------------------------
		page = doc.PageCreate(Rect(0, 0, 612, 794));

		writer.Begin(page);	// begin writing to this page
		eb.Reset();			// Reset the GState to default

		// Begin writing a block of text
		element = eb.CreateTextBegin(Font::Create(doc, Font::e_times_roman), 12);
		writer.WriteElement(element);

		element = eb.CreateTextRun("Hello World!");
		element.SetTextMatrix(10, 0, 0, 10, 0, 600);
		element.GetGState().SetLeading(15);		 // Set the spacing between lines
		writer.WriteElement(element);

		writer.WriteElement(eb.CreateTextNewLine());  // New line

		element = eb.CreateTextRun("Hello World!");
		gstate = element.GetGState(); 
		gstate.SetTextRenderMode(GState::e_stroke_text);
		gstate.SetCharSpacing(-1.25);
		gstate.SetWordSpacing(-1.25);
		writer.WriteElement(element);

		writer.WriteElement(eb.CreateTextNewLine());  // New line

		element = eb.CreateTextRun("Hello World!");
		gstate = element.GetGState(); 
		gstate.SetCharSpacing(0);
		gstate.SetWordSpacing(0);
		gstate.SetLineWidth(3);
		gstate.SetTextRenderMode(GState::e_fill_stroke_text);
		gstate.SetStrokeColorSpace(ColorSpace::CreateDeviceRGB()); 
		gstate.SetStrokeColor(ColorPt(1, 0, 0));	// red
		gstate.SetFillColorSpace(ColorSpace::CreateDeviceCMYK()); 
		gstate.SetFillColor(ColorPt(1, 0, 0, 0));	// cyan
		writer.WriteElement(element);


		writer.WriteElement(eb.CreateTextNewLine());  // New line

		// Set text as a clipping path to the image.
		element = eb.CreateTextRun("Hello World!");
		gstate = element.GetGState(); 
		gstate.SetTextRenderMode(GState::e_clip_text);
		writer.WriteElement(element);

		// Finish the block of text
		writer.WriteElement(eb.CreateTextEnd());		

		// Draw an image that will be clipped by the above text
		writer.WriteElement(eb.CreateImage(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.

		ElementReader reader;

		// 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.Begin(doc.GetPage(doc.GetPageCount()));

		page = doc.PageCreate(Rect(0, 0, 1300, 794));

		writer.Begin(page);	// begin writing to this page
		eb.Reset();		// Reset the GState to default

		// Embed an external font in the document.
		Font font = Font::CreateTrueTypeFont(doc, (input_path + "font.ttf").c_str());

		while ((element = reader.Next())==true) 	// Read page contents
		{
			if (element.GetType() == Element::e_text) 
			{
				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 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.

		// 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.Begin(doc.GetPage(doc.GetPageCount()));

		page = doc.PageCreate(Rect(0, 0, 1300, 794));

		writer.Begin(page);	// begin writing to this page
		eb.Reset();		// Reset the GState to default

		// Embed an external font in the document.
		Font font2 = Font::CreateType1Font(doc, (input_path + "Misc-Fixed.pfa").c_str());

		while ((element = reader.Next())) 	// Read page contents
		{
			if (element.GetType() == Element::e_text) 
			{
				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 = doc.PageCreate();
		writer.Begin(page);	// begin writing to this page
		eb.Reset();			// Reset the GState to default

		// Begin writing a block of text
		element = eb.CreateTextBegin(Font::Create(doc, Font::e_times_roman), 12);
		element.SetTextMatrix(1.5, 0, 0, 1.5, 50, 600);
		element.GetGState().SetLeading(15);	// Set the spacing between lines
		writer.WriteElement(element);

		const char* 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 char* para_end = para + strlen(para);
		const char* text_run = para;
		const char* text_run_end;

		double para_width = 300; // paragraph width is 300 units
		double cur_width = 0;

		while (text_run < para_end) 
		{
			text_run_end = strchr(text_run, ' ');
			if (!text_run_end) text_run_end = para_end;

			element = eb.CreateTextRun(text_run, UInt32(text_run_end-text_run+1));
			if (cur_width + element.GetTextLength() < para_width) 
			{
				writer.WriteElement(element);
				cur_width += element.GetTextLength();
			}
			else 
			{
				writer.WriteElement(eb.CreateTextNewLine());  // New line
				element = eb.CreateTextRun(text_run, UInt32(text_run_end-text_run+1));
				cur_width = element.GetTextLength();
				writer.WriteElement(element);
			}

			text_run = text_run_end+1;
		}
		
		// -----------------------------------------------------------------------
			// The following code snippet illustrates how to adjust spacing between 
		// characters (text runs).
		element = eb.CreateTextNewLine();
		writer.WriteElement(element);  // Skip 2 lines
		writer.WriteElement(element); 
		
		writer.WriteElement(eb.CreateTextRun("An example of space adjustments between inter-characters:")); 
		writer.WriteElement(eb.CreateTextNewLine()); 
		
		// Write string "AWAY" without space adjustments between characters.
		element = eb.CreateTextRun("AWAY");
		writer.WriteElement(element);  
		
		writer.WriteElement(eb.CreateTextNewLine()); 
		
		// Write string "AWAY" with space adjustments between characters.
		element = eb.CreateTextRun("A");
		writer.WriteElement(element);
		
		element = eb.CreateTextRun("W");
		element.SetPosAdjustment(140);
		writer.WriteElement(element);
		
		element = eb.CreateTextRun("A");
		element.SetPosAdjustment(140);
		writer.WriteElement(element);
		
		element = eb.CreateTextRun("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(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 = doc.PageCreate();
		writer.Begin(page);	// begin writing to the page

		// Create the Image Mask
		MappedFile imgf(input_path + "imagemask.dat");
		FilterReader mask_read(imgf);

		ColorSpace device_gray = ColorSpace::CreateDeviceGray();
		Image mask = Image::Create(doc, mask_read, 64, 64, 1, device_gray, Image::e_ascii_hex);
		
		mask.GetSDFObj().PutBool("ImageMask", true);

		element = eb.CreateRect(0, 0, 612, 794);
		element.SetPathStroke(false);
		element.SetPathFill(true);
		element.GetGState().SetFillColorSpace(device_gray);
		element.GetGState().SetFillColor(ColorPt(0.8));
		writer.WritePlacedElement(element);

		element = eb.CreateImage(mask, Common::Matrix2D(200, 0, 0, -200, 40, 680));
		element.GetGState().SetFillColor(ColorPt(0.1));
		writer.WritePlacedElement(element);

		element.GetGState().SetFillColorSpace(ColorSpace::CreateDeviceRGB());
		element.GetGState().SetFillColor(ColorPt(1, 0, 0));
		element = eb.CreateImage(mask, Common::Matrix2D(200, 0, 0, -200, 320, 680));
		writer.WritePlacedElement(element);

		element.GetGState().SetFillColor(ColorPt(0, 1, 0));
		element = eb.CreateImage(mask, Common::Matrix2D(200, 0, 0, -200, 40, 380));
		writer.WritePlacedElement(element);

		{
			// This sample illustrates Explicit Masking. 
			Image img = Image::Create(doc, (input_path + "peppers.jpg").c_str());

			// mask is the explicit mask for the primary (base) image
			img.SetMask(mask);

			element = eb.CreateImage(img, Common::Matrix2D(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 = doc.PageCreate();
		writer.Begin(page);	// begin writing to this page
		eb.Reset();			// Reset the GState to default

		// Write some transparent text at the bottom of the page.
		element = eb.CreateTextBegin(Font::Create(doc, Font::e_times_roman), 100);

		// Set the text knockout attribute. Text knockout must be set outside of 
		// the text group.
		gstate = element.GetGState();
		gstate.SetTextKnockout(false);
		gstate.SetBlendMode(GState::e_bl_difference);
		writer.WriteElement(element);

		element = eb.CreateTextRun("Transparency");
		element.SetTextMatrix(1, 0, 0, 1, 30, 30);
		gstate = element.GetGState();
		gstate.SetFillColorSpace(ColorSpace::CreateDeviceCMYK());
		gstate.SetFillColor(ColorPt(1, 0, 0, 0));

		gstate.SetFillOpacity(0.5);
		writer.WriteElement(element);

		// Write the same text on top the old; shifted by 3 points
		element.SetTextMatrix(1, 0, 0, 1, 33, 33);
		gstate.SetFillColor(ColorPt(0, 1, 0, 0));
		gstate.SetFillOpacity(0.5);

		writer.WriteElement(element);
		writer.WriteElement(eb.CreateTextEnd());

		// Draw three overlapping transparent circles.
		eb.PathBegin();		// start constructing the path
		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 = eb.PathEnd();
		element.SetPathFill(true);

		gstate = element.GetGState();
		gstate.SetFillColorSpace(ColorSpace::CreateDeviceRGB());
		gstate.SetFillColor(ColorPt(0, 0, 1));                     // Blue Circle

		gstate.SetBlendMode(GState::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.SetFillColor(ColorPt(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.SetFillColor(ColorPt(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 ------------------------------------

		doc.Save((output_path + "element_builder.pdf").c_str(), SDFDoc::e_remove_unused, NULL);
		// doc.Save((output_path + "element_builder.pdf").c_str(), Doc::e_linearized, NULL);
		cout << "Done. Result saved in element_builder.pdf..." << endl;
	}
	catch(Common::Exception& e)
	{
		cout << e << endl;
		ret = 1;
	}
	catch(...)
	{
		cout << "Unknown Exception" << endl;
		ret = 1;
	}

	PDFNet::Terminate();
	return ret;
}
```

{% endcode %}
{% endtab %}

{% tab title="PHP" %}
{% code lineNumbers="true" %}

```php
<?php
#---------------------------------------------------------------------------------------
# Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
# Consult LICENSE.txt regarding license information.
#---------------------------------------------------------------------------------------
if(file_exists("../../../PDFNetC/Lib/PDFNetPHP.php"))
include("../../../PDFNetC/Lib/PDFNetPHP.php");
include("../../LicenseKey/PHP/LicenseKey.php");

# This sample illustrates how to edit existing text strings.

# Relative path to the folder containing the test files.
$input_path = getcwd()."/../../TestFiles/";
$output_path = $input_path."Output/";

	PDFNet::Initialize($LicenseKey);
	PDFNet::GetSystemFontList();    // Wait for fonts to be loaded if they haven't already. This is done because PHP can run into errors when shutting down if font loading is still in progress.
	$doc = new PDFDoc();
	$builder = new ElementBuilder();	// ElementBuilder is used to build new Element objects
	$writer = new ElementWriter();		// ElementWriter is used to write Elements to the page

	// Start a new page ------------------------------------
	$page = $doc->PageCreate(new Rect(0.0, 0.0, 612.0, 794.0));

	$writer->Begin($page);	// begin writing to the page
	
	// Create an Image that can be reused in the document or on the same page.		
	$img = Image::Create($doc->GetSDFDoc(), $input_path."peppers.jpg");

	$element = $builder->CreateImage($img, new Matrix2D((double)($img->GetImageWidth()/2), -145.0, 20.0, (double)($img->GetImageHeight()/2), 200.0, 150.0));
	$writer->WritePlacedElement($element);
	$gstate = $element->GetGState();	// use the same image (just change its matrix)
	$gstate->SetTransform(200.0, 0.0, 0.0, 300.0, 50.0, 450.0);
	$writer->WritePlacedElement($element);

	// use the same image again (just change its matrix).
	$writer->WritePlacedElement($builder->CreateImage($img, 300.0, 600.0, 200.0, -150.0));

	$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 = $doc->PageCreate(new Rect(0.0, 0.0, 612.0, 794.0));

	$writer->Begin($page);	// begin writing to this page
	$builder->Reset();	// Reset the GState to default

	$builder->PathBegin();	// start constructing the path
	$builder->MoveTo(306, 396);
	$builder->CurveTo(681, 771, 399.75, 864.75, 306, 771);
	$builder->CurveTo(212.25, 864.75, -69, 771, 306, 396);
	$builder->ClosePath();
	$element = $builder->PathEnd();		// the path is now finished
	$element->SetPathFill(true);		// the path should be filled

	// Set the path color space and color
	$gstate = $element->GetGState();
	$gstate->SetFillColorSpace(ColorSpace::CreateDeviceCMYK());
	$gstate->SetFillColor(new ColorPt(1.0, 0.0, 0.0, 0.0));  // cyan
	$gstate->SetTransform(0.5, 0.0, 0.0, 0.5, -20.0, 300.0);
	$writer->WritePlacedElement($element);

	// Draw the same path using a different stroke color
	$element->SetPathStroke(true);		// this path is should be filled and stroked
	$gstate->SetFillColor(new ColorPt(0.0, 0.0, 1.0, 0.0));  // yellow
	$gstate->SetStrokeColorSpace(ColorSpace::CreateDeviceRGB()); 
	$gstate->SetStrokeColor(new ColorPt(1.0, 0.0, 0.0));  // red
	$gstate->SetTransform(0.5, 0.0, 0.0, 0.5, 280.0, 300.0);
	$gstate->SetLineWidth(20.0);
	$writer->WritePlacedElement($element);

	// Draw the same path with with a given dash pattern
	$element->SetPathFill(false);	// this path is should be only stroked

	$gstate->SetStrokeColor(new ColorPt(0.0, 0.0, 1.0));  // blue
	$gstate->SetTransform(0.5, 0.0, 0.0, 0.5, 280.0, 0.0);
	$gstate->SetDashPattern(array(30.0), 0);
	$writer->WritePlacedElement($element);

	// Use the path as a clipping path
	$writer->WriteElement($builder->CreateGroupBegin());	// Save the graphics state
	// Start constructing the new path (the old path was lost when we created 
	// a new Element using CreateGroupBegin()).
	$builder->PathBegin();		
	$builder->MoveTo(306, 396);
	$builder->CurveTo(681, 771, 399.75, 864.75, 306, 771);
	$builder->CurveTo(212.25, 864.75, -69, 771, 306, 396);
	$builder->ClosePath();
	$element = $builder->PathEnd();	// path is now constructed
	$element->SetPathClip(true);	// this path is a clipping path
	$element->SetPathStroke(true);		// this path should be filled and stroked
	$gstate = $element->GetGState();
	$gstate->SetTransform(0.5, 0.0, 0.0, 0.5, -20.0, 0.0);

	$writer->WriteElement($element);

	$writer->WriteElement($builder->CreateImage($img, 100.0, 300.0, 400.0, 600.0));
		
	$writer->WriteElement($builder->CreateGroupEnd());	// Restore the graphics state

	$writer->End();  // save changes to the current page
	$doc->PagePushBack($page);

	// Start a new page ------------------------------------
	$page = $doc->PageCreate(new Rect(0.0, 0.0, 612.0, 794.0));

	$writer->Begin($page);	// begin writing to this page
	$builder->Reset();		// Reset the GState to default

	// Begin writing a block of text
	$element = $builder->CreateTextBegin(Font::Create($doc->GetSDFDoc(), Font::e_times_roman), 12.0);
	$writer->WriteElement($element);

	$element = $builder->CreateTextRun("Hello World!");
	$element->SetTextMatrix(10.0, 0.0, 0.0, 10.0, 0.0, 600.0);
	$element->GetGState()->SetLeading(15);		 // Set the spacing between lines
	$writer->WriteElement($element);

	$writer->WriteElement($builder->CreateTextNewLine());  // New line

	$element = $builder->CreateTextRun("Hello World!");
	$gstate = $element->GetGState(); 
	$gstate->SetTextRenderMode(GState::e_stroke_text);
	$gstate->SetCharSpacing(-1.25);
	$gstate->SetWordSpacing(-1.25);
	$writer->WriteElement($element);

	$writer->WriteElement($builder->CreateTextNewLine());  // New line

	$element = $builder->CreateTextRun("Hello World!");
	$gstate = $element->GetGState(); 
	$gstate->SetCharSpacing(0);
	$gstate->SetWordSpacing(0);
	$gstate->SetLineWidth(3);
	$gstate->SetTextRenderMode(GState::e_fill_stroke_text);
	$gstate->SetStrokeColorSpace(ColorSpace::CreateDeviceRGB()); 
	$gstate->SetStrokeColor(new ColorPt(1.0, 0.0, 0.0));	// red
	$gstate->SetFillColorSpace(ColorSpace::CreateDeviceCMYK()); 
	$gstate->SetFillColor(new ColorPt(1.0, 0.0, 0.0, 0.0));	// cyan
	$writer->WriteElement($element);

	$writer->WriteElement($builder->CreateTextNewLine());  // New line

	// Set text as a clipping path to the image.
	$element = $builder->CreateTextRun("Hello World!");
	$gstate = $element->GetGState(); 
	$gstate->SetTextRenderMode(GState::e_clip_text);
	$writer->WriteElement($element);

	// Finish the block of text
	$writer->WriteElement($builder->CreateTextEnd());		

	// Draw an image that will be clipped by the above text
	$writer->WriteElement($builder->CreateImage($img, 10.0, 100.0, 1300.0, 720.0));

	$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.

	$reader = new ElementReader();

	// 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->Begin($doc->GetPage($doc->GetPageCount()));

	$page = $doc->PageCreate(new Rect(0.0, 0.0, 1300.0, 794.0));

	$writer->Begin($page);		// begin writing to this page
	$builder->Reset();		// Reset the GState to default

	// Embed an external font in the document.
	$font = Font::CreateTrueTypeFont($doc->GetSDFDoc(), $input_path."font.ttf");

	while (($element = $reader->Next()) != null) 	// Read page contents
	{
		if ($element->GetType() == Element::e_text) 
		{
			$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 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.

	// 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->Begin($doc->GetPage($doc->GetPageCount()));

	$page = $doc->PageCreate(new Rect(0.0, 0.0, 1300.0, 794.0));

	$writer->Begin($page);	// begin writing to this page
	$builder->Reset();	// Reset the GState to default

	// Embed an external font in the document.
	$font2 = Font::CreateType1Font($doc->GetSDFDoc(), $input_path."Misc-Fixed.pfa");

	while (($element = $reader->Next())) 	// Read page contents
	{
		if ($element->GetType() == Element::e_text) 
		{
			$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 = $doc->PageCreate();
	$writer->Begin($page);	// begin writing to this page
	$builder->Reset();		// Reset the GState to default

	// Begin writing a block of text
	$element = $builder->CreateTextBegin(Font::Create($doc->GetSDFDoc(), Font::e_times_roman), 12.0);
	$element->SetTextMatrix(1.5, 0.0, 0.0, 1.5, 50.0, 600.0);
	$element->GetGState()->SetLeading(15);	// Set the spacing between lines
	$writer->WriteElement($element);

	$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";

	$para_end = strlen($para);
	$text_run = 0;

	$para_width = 300;
	$cur_width = 0;

	while ($text_run < $para_end) 
	{
		$text_run_end = strpos($para, ' ', $text_run);
		if (!$text_run_end) $text_run_end = $para_end;

		$text = substr($para, $text_run, $text_run_end-$text_run+1);
		$element = $builder->CreateTextRun($text);
		if ($cur_width + $element->GetTextLength() < $para_width) 
		{
			$writer->WriteElement($element);
 			$cur_width += $element->GetTextLength();
		}
		else 
		{
			$writer->WriteElement($builder->CreateTextNewLine());  // New line
			$element = $builder->CreateTextRun($text);
			$cur_width = $element->GetTextLength();
			$writer->WriteElement($element);
		}

		$text_run = $text_run_end+1;
	}

	// -----------------------------------------------------------------------
	// The following code snippet illustrates how to adjust spacing between 
	// characters (text runs).
	$element = $builder->CreateTextNewLine();
	$writer->WriteElement($element);  // Skip 2 lines
	$writer->WriteElement($element); 
	
	$writer->WriteElement($builder->CreateTextRun("An example of space adjustments between inter-characters:")); 
	$writer->WriteElement($builder->CreateTextNewLine()); 
		
	// Write string "AWAY" without space adjustments between characters.
	$element = $builder->CreateTextRun("AWAY");
	$writer->WriteElement($element);  
		
	$writer->WriteElement($builder->CreateTextNewLine()); 
		
	// Write string "AWAY" with space adjustments between characters.
	$element = $builder->CreateTextRun("A");
	$writer->WriteElement($element);
		
	$element = $builder->CreateTextRun("W");
	$element->SetPosAdjustment(140);
	$writer->WriteElement($element);
		
	$element = $builder->CreateTextRun("A");
	$element->SetPosAdjustment(140);
	$writer->WriteElement($element);
		
	$element = $builder->CreateTextRun("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($builder->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 = $doc->PageCreate();
	$writer->Begin($page);	// begin writing to the page

	// Create the Image Mask
	$imgf = new MappedFile($input_path."imagemask.dat");
	$mask_read = new FilterReader($imgf);

	$device_gray = ColorSpace::CreateDeviceGray();
	$mask = Image::Create($doc->GetSDFDoc(), $mask_read, 64, 64, 1, $device_gray, Image::e_ascii_hex);
		
	$mask->GetSDFObj()->PutBool("ImageMask", true);

	$element = $builder->CreateRect(0, 0, 612, 794);
	$element->SetPathStroke(false);
	$element->SetPathFill(true);
	$element->GetGState()->SetFillColorSpace($device_gray);
	$element->GetGState()->SetFillColor(new ColorPt(0.8));
	$writer->WritePlacedElement($element);

	$element = $builder->CreateImage($mask, new Matrix2D(200.0, 0.0, 0.0, -200.0, 40.0, 680.0));
	$element->GetGState()->SetFillColor(new ColorPt(0.1));
	$writer->WritePlacedElement($element);

	$element->GetGState()->SetFillColorSpace(ColorSpace::CreateDeviceRGB());
	$element->GetGState()->SetFillColor(new ColorPt(1.0, 0.0, 0.0));
	$element = $builder->CreateImage($mask, new Matrix2D(200.0, 0.0, 0.0, -200.0, 320.0, 680.0));
	$writer->WritePlacedElement($element);

	$element->GetGState()->SetFillColor(new ColorPt(0.0, 1.0, 0.0));
	$element = $builder->CreateImage($mask, new Matrix2D(200.0, 0.0, 0.0, -200.0, 40.0, 380.0));
	$writer->WritePlacedElement($element);

	// This sample illustrates Explicit Masking. 
	$img = Image::Create($doc->GetSDFDoc(), $input_path."peppers.jpg");

	// mask is the explicit mask for the primary (base) image
	$img->SetMask($mask);

	$element = $builder->CreateImage($img, new Matrix2D(200.0, 0.0, 0.0, -200.0, 320.0, 380.0));
	$writer->WritePlacedElement($element);

	$writer->End();  // save changes to the current page
	$doc->PagePushBack($page);

	// Transparency sample ----------------------------------
		
	// Start a new page -------------------------------------
	$page = $doc->PageCreate();
	$writer->Begin($page);		// begin writing to this page
	$builder->Reset();		// Reset the GState to default

	// Write some transparent text at the bottom of the page.
	$element = $builder->CreateTextBegin(Font::Create($doc->GetSDFDoc(), Font::e_times_roman), 100.0);

	// Set the text knockout attribute. Text knockout must be set outside of 
	// the text group.
	$gstate = $element->GetGState();
	$gstate->SetTextKnockout(false);
	$gstate->SetBlendMode(GState::e_bl_difference);
	$writer->WriteElement($element);

	$element = $builder->CreateTextRun("Transparency");
	$element->SetTextMatrix(1.0, 0.0, 0.0, 1.0, 30.0, 30.0);
	$gstate = $element->GetGState();
	$gstate->SetFillColorSpace(ColorSpace::CreateDeviceCMYK());
	$gstate->SetFillColor(new ColorPt(1.0, 0.0, 0.0, 0.0));

	$gstate->SetFillOpacity(0.5);
	$writer->WriteElement($element);

	// Write the same text on top the old; shifted by 3 points
	$element->SetTextMatrix(1.0, 0.0, 0.0, 1.0, 33.0, 33.0);
  	$gstate->SetFillColor(new ColorPt(0.0, 1.0, 0.0, 0.0));
	$gstate->SetFillOpacity(0.5);

	$writer->WriteElement($element);
	$writer->WriteElement($builder->CreateTextEnd());

	// Draw three overlapping transparent circles.
	$builder->PathBegin();		// start constructing the path
	$builder->MoveTo(459.223, 505.646);
	$builder->CurveTo(459.223, 415.841, 389.85, 343.04, 304.273, 343.04);
	$builder->CurveTo(218.697, 343.04, 149.324, 415.841, 149.324, 505.646);
	$builder->CurveTo(149.324, 595.45, 218.697, 668.25, 304.273, 668.25);
	$builder->CurveTo(389.85, 668.25, 459.223, 595.45, 459.223, 505.646);
	$element = $builder->PathEnd();
	$element->SetPathFill(true);

	$gstate = $element->GetGState();
	$gstate->SetFillColorSpace(ColorSpace::CreateDeviceRGB());
	$gstate->SetFillColor(new ColorPt(0.0, 0.0, 1.0));

	$gstate->SetBlendMode(GState::e_bl_normal);
	$gstate->SetFillOpacity(0.5);
	$writer->WriteElement($element);

	// Translate relative to the Blue Circle
	$gstate->SetTransform(1.0, 0.0, 0.0, 1.0, 113.0, -185.0);                
	$gstate->SetFillColor(new ColorPt(0.0, 1.0, 0.0));                     // Green Circle
	$gstate->SetFillOpacity(0.5);
	$writer->WriteElement($element);

	// Translate relative to the Green Circle
	$gstate->SetTransform(1.0, 0.0, 0.0, 1.0, -220.0, 0.0);
	$gstate->SetFillColor(new ColorPt(1.0, 0.0, 0.0));                     // Red Circle
	$gstate->SetFillOpacity(0.5);
	$writer->WriteElement($element);

	$writer->End();  // save changes to the current page
	$doc->PagePushBack($page);

	// End page ------------------------------------

	$doc->Save($output_path."element_builder.pdf", SDFDoc::e_remove_unused);
	PDFNet::Terminate();
	echo "Done. Result saved in element_builder.pdf...\n";
?>
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
//---------------------------------------------------------------------------------------
// 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
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
{% code lineNumbers="true" %}

```python
#---------------------------------------------------------------------------------------
# Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
# Consult LICENSE.txt regarding license information.
#---------------------------------------------------------------------------------------

import site
site.addsitedir("../../../PDFNetC/Lib")
import sys
from PDFNetPython import *

sys.path.append("../../LicenseKey/PYTHON")
from LicenseKey import *

# Relative path to the folder containing the test files.
input_path = "../../TestFiles/"
output_path = "../../TestFiles/Output/"

def main():
    PDFNet.Initialize(LicenseKey)
    
    doc = PDFDoc()
    
    # ElementBuilder is used to build new Element objects
    eb = ElementBuilder()
    # ElementWriter is used to write Elements to the page
    writer = ElementWriter()
    
    # Start a new page ------------------------------------
    page = doc.PageCreate(Rect(0, 0, 612, 794))
    
    writer.Begin(page)  # begin writing to the page

    # Create an Image that can be reused in the document or on the same page.
    img = Image.Create(doc.GetSDFDoc(), input_path + "peppers.jpg")
    
    element = eb.CreateImage(img, Matrix2D(img.GetImageWidth()/2, -145, 20, img.GetImageHeight()/2, 200, 150))
    writer.WritePlacedElement(element)
    
    gstate = element.GetGState()    # use the same image (just change its matrix)
    gstate.SetTransform(200, 0, 0, 300, 50, 450)
    writer.WritePlacedElement(element)
    
    # use the same image again (just change its matrix)
    writer.WritePlacedElement(eb.CreateImage(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 = doc.PageCreate(Rect(0, 0, 612, 794))
    
    writer.Begin(page)  # begin writing to this page
    eb.Reset()          # Reset the GState to default
    
    eb.PathBegin()      # start constructing the path
    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()
    element = eb.PathEnd()      # the path is now finished
    element.SetPathFill(True)   # the path should be filled
    
    # Set the path color space and color
    gstate = element.GetGState()
    gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK())
    gstate.SetFillColor(ColorPt(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
    element.SetPathStroke(True)     # this path is should be filled and stroked
    gstate.SetFillColor(ColorPt(0, 0, 1, 0))  # yellow
    gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB())
    gstate.SetStrokeColor(ColorPt(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 a given dash pattern
    element.SetPathFill(False)      # this path should be only stroked
    
    gstate.SetStrokeColor(ColorPt(0,0,1))   # blue
    gstate.SetTransform(0.5, 0, 0, 0.5, 280, 0)
    dash_pattern = VectorDouble()
    dash_pattern.append(30)
    gstate.SetDashPattern(dash_pattern, 0)
    writer.WritePlacedElement(element)
    
    # Use the path as a clipping path
    writer.WriteElement(eb.CreateGroupBegin())    # Save the graphics state
    # 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()
    element = eb.PathEnd()    # path is now constructed
    element.SetPathClip(True)    # this path is a clipping path
    element.SetPathStroke(True)        # this path should be filled and stroked
    gstate = element.GetGState()
    gstate.SetTransform(0.5, 0, 0, 0.5, -20, 0)
    
    writer.WriteElement(element)

    writer.WriteElement(eb.CreateImage(img, 100, 300, 400, 600))
        
    writer.WriteElement(eb.CreateGroupEnd())    # Restore the graphics state

    writer.End()  # save changes to the current page
    doc.PagePushBack(page)

    # Start a new page ------------------------------------
    page = doc.PageCreate(Rect(0, 0, 612, 794))

    writer.Begin(page)    # begin writing to this page
    eb.Reset()            # Reset the GState to default

    # Begin writing a block of text
    element = eb.CreateTextBegin(Font.Create(doc.GetSDFDoc(), Font.e_times_roman), 12)
    writer.WriteElement(element)

    element = eb.CreateTextRun("Hello World!")
    element.SetTextMatrix(10, 0, 0, 10, 0, 600)
    element.GetGState().SetLeading(15)         # Set the spacing between lines
    writer.WriteElement(element)

    writer.WriteElement(eb.CreateTextNewLine())  # New line

    element = eb.CreateTextRun("Hello World!")
    gstate = element.GetGState() 
    gstate.SetTextRenderMode(GState.e_stroke_text)
    gstate.SetCharSpacing(-1.25)
    gstate.SetWordSpacing(-1.25)
    writer.WriteElement(element)

    writer.WriteElement(eb.CreateTextNewLine())  # New line

    element = eb.CreateTextRun("Hello World!")
    gstate = element.GetGState() 
    gstate.SetCharSpacing(0)
    gstate.SetWordSpacing(0)
    gstate.SetLineWidth(3)
    gstate.SetTextRenderMode(GState.e_fill_stroke_text)
    gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB()) 
    gstate.SetStrokeColor(ColorPt(1, 0, 0))    # red
    gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK()) 
    gstate.SetFillColor(ColorPt(1, 0, 0, 0))    # cyan
    writer.WriteElement(element)
    
    writer.WriteElement(eb.CreateTextNewLine())  # New line

    # Set text as a clipping path to the image.
    element = eb.CreateTextRun("Hello World!")
    gstate = element.GetGState() 
    gstate.SetTextRenderMode(GState.e_clip_text)
    writer.WriteElement(element)

    # Finish the block of text
    writer.WriteElement(eb.CreateTextEnd())        

    # Draw an image that will be clipped by the above text
    writer.WriteElement(eb.CreateImage(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.

    reader = ElementReader()

    # 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.Begin(doc.GetPage(doc.GetPageCount()))

    page = doc.PageCreate(Rect(0, 0, 1300, 794))

    writer.Begin(page)    # begin writing to this page
    eb.Reset()            # Reset the GState to default

    # Embed an external font in the document.
    font = Font.CreateTrueTypeFont(doc.GetSDFDoc(), (input_path + "font.ttf"))
    
    element = reader.Next()
    while element != None:		# Read page contents
        if element.GetType() == Element.e_text:
            element.GetGState().SetFont(font, 12)
        writer.WriteElement(element)
        element = reader.Next()
    
    reader.End()
    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.

    # 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.Begin(doc.GetPage(doc.GetPageCount()))

    page = doc.PageCreate(Rect(0, 0, 1300, 794))

    writer.Begin(page)    # begin writing to this page
    eb.Reset()        # Reset the GState to default

    # Embed an external font in the document.
    font2 = Font.CreateType1Font(doc.GetSDFDoc(), (input_path + "Misc-Fixed.pfa"))
    
    element = reader.Next()
    while element != None:
        if element.GetType() == Element.e_text:
            element.GetGState().SetFont(font2, 12)
        writer.WriteElement(element)
        element = reader.Next()
    
    reader.End()
    writer.End()    # save changes to the current page
    doc.PagePushBack(page)
    
    # Start a new page ------------------------------------
    page = doc.PageCreate()
    writer.Begin(page)    # begin writing to this page
    eb.Reset()            # Reset the GState to default

    # Begin writing a block of text
    element = eb.CreateTextBegin(Font.Create(doc.GetSDFDoc(), Font.e_times_roman), 12)
    element.SetTextMatrix(1.5, 0, 0, 1.5, 50, 600)
    element.GetGState().SetLeading(15)    # Set the spacing between lines
    writer.WriteElement(element)
    
    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")

    para_end = len(para)
    text_run = 0
    
    para_width = 300 # paragraph width is 300 units 
    cur_width = 0
    
    while text_run < para_end:
        text_run_end = para.find(' ', text_run)  
        if text_run_end < 0:
            text_run_end = para_end - 1
        
        text = para[text_run:text_run_end+1]
        element = eb.CreateTextRun(text)
        if cur_width + element.GetTextLength() < para_width:
            writer.WriteElement(element)
            cur_width = cur_width + element.GetTextLength()
        else:
            writer.WriteElement(eb.CreateTextNewLine())    # new line
            element = eb.CreateTextRun(text)
            cur_width = element.GetTextLength()
            writer.WriteElement(element)
        text_run = text_run_end + 1
        
    # -----------------------------------------------------------------------
    # The following code snippet illustrates how to adjust spacing between 
    # characters (text runs).
    element = eb.CreateTextNewLine()
    writer.WriteElement(element)  # Skip 2 lines
    writer.WriteElement(element) 
        
    writer.WriteElement(eb.CreateTextRun("An example of space adjustments between inter-characters:")) 
    writer.WriteElement(eb.CreateTextNewLine()) 
        
    # Write string "AWAY" without space adjustments between characters.
    element = eb.CreateTextRun("AWAY")
    writer.WriteElement(element)  
        
    writer.WriteElement(eb.CreateTextNewLine()) 
        
    # Write string "AWAY" with space adjustments between characters.
    element = eb.CreateTextRun("A")
    writer.WriteElement(element)
        
    element = eb.CreateTextRun("W")
    element.SetPosAdjustment(140)
    writer.WriteElement(element)
        
    element = eb.CreateTextRun("A")
    element.SetPosAdjustment(140)
    writer.WriteElement(element)
        
    element = eb.CreateTextRun("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(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 = doc.PageCreate()
    writer.Begin(page)    # begin writing to the page

    # Create the Image Mask
    imgf = MappedFile(input_path + "imagemask.dat")
    mask_read = FilterReader(imgf)

    device_gray = ColorSpace.CreateDeviceGray()
    mask = Image.Create(doc.GetSDFDoc(), mask_read, 64, 64, 1, device_gray, Image.e_ascii_hex)
    
    mask.GetSDFObj().PutBool("ImageMask", True)

    element = eb.CreateRect(0, 0, 612, 794)
    element.SetPathStroke(False)
    element.SetPathFill(True)
    element.GetGState().SetFillColorSpace(device_gray)
    element.GetGState().SetFillColor(ColorPt(0.8))
    writer.WritePlacedElement(element)

    element = eb.CreateImage(mask, Matrix2D(200, 0, 0, -200, 40, 680))
    element.GetGState().SetFillColor(ColorPt(0.1))
    writer.WritePlacedElement(element)

    element.GetGState().SetFillColorSpace(ColorSpace.CreateDeviceRGB())
    element.GetGState().SetFillColor(ColorPt(1, 0, 0))
    element = eb.CreateImage(mask, Matrix2D(200, 0, 0, -200, 320, 680))
    writer.WritePlacedElement(element)

    element.GetGState().SetFillColor(ColorPt(0, 1, 0))
    element = eb.CreateImage(mask, Matrix2D(200, 0, 0, -200, 40, 380))
    writer.WritePlacedElement(element)
    
    # This sample illustrates Explicit Masking. 
    img = Image.Create(doc.GetSDFDoc(), (input_path + "peppers.jpg"))

    # mask is the explicit mask for the primary (base) image
    img.SetMask(mask)

    element = eb.CreateImage(img, Matrix2D(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 = doc.PageCreate()
    writer.Begin(page)    # begin writing to this page
    eb.Reset()            # Reset the GState to default

    # Write some transparent text at the bottom of the page.
    element = eb.CreateTextBegin(Font.Create(doc.GetSDFDoc(), Font.e_times_roman), 100)

    # Set the text knockout attribute. Text knockout must be set outside of 
    # the text group.
    gstate = element.GetGState()
    gstate.SetTextKnockout(False)
    gstate.SetBlendMode(GState.e_bl_difference)
    writer.WriteElement(element)

    element = eb.CreateTextRun("Transparency")
    element.SetTextMatrix(1, 0, 0, 1, 30, 30)
    gstate = element.GetGState()
    gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK())
    gstate.SetFillColor(ColorPt(1, 0, 0, 0))

    gstate.SetFillOpacity(0.5)
    writer.WriteElement(element)

    # Write the same text on top the old; shifted by 3 points
    element.SetTextMatrix(1, 0, 0, 1, 33, 33)
    gstate.SetFillColor(ColorPt(0, 1, 0, 0))
    gstate.SetFillOpacity(0.5)

    writer.WriteElement(element)
    writer.WriteElement(eb.CreateTextEnd())

    # Draw three overlapping transparent circles.
    eb.PathBegin()        # start constructing the path
    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 = eb.PathEnd()
    element.SetPathFill(True)
    
    gstate = element.GetGState()
    gstate.SetFillColorSpace(ColorSpace.CreateDeviceRGB())
    gstate.SetFillColor(ColorPt(0, 0, 1))                     # Blue Circle

    gstate.SetBlendMode(GState.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.SetFillColor(ColorPt(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.SetFillColor(ColorPt(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 ------------------------------------

    doc.Save((output_path + "element_builder.pdf"), SDFDoc.e_remove_unused)
    doc.Close()
    PDFNet.Terminate()
    print("Done. Result saved in element_builder.pdf...")
    
if __name__ == '__main__':
    main()
```

{% endcode %}
{% endtab %}

{% tab title="VB" %}
{% code lineNumbers="true" %}

```vb
'
' Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
'

Imports System

Imports pdftron
Imports pdftron.Common
Imports pdftron.Filters
Imports pdftron.SDF
Imports pdftron.PDF

Module ElementBuilderTestVB
	Dim pdfNetLoader As PDFNetLoader
	Sub New()
		pdfNetLoader = pdftron.PDFNetLoader.Instance()
	End Sub

	Sub Main()

		PDFNet.Initialize(PDFTronLicense.Key)

		' Relative path to the folder containing test files.
		Dim input_path As String = "../../../../TestFiles/"
		Dim output_path As String = "../../../../TestFiles/Output/"


		Try
			Using doc As PDFDoc = New PDFDoc
				Using eb As ElementBuilder = New ElementBuilder		  ' ElementBuilder is used to build new Element objects
					Using writer As ElementWriter = New ElementWriter		  ' ElementWriter is used to write Elements to the page	
						' Start a new page ------------------------------------
						' Position an image stream on several places on the page
						Dim page As Page = doc.PageCreate(New Rect(0, 0, 612, 794))

						writer.Begin(page)		  ' begin writing to this page           

						' Create an Image that can be reused multiple times in the document or 
						' multiple on the same page.
						Dim img_file As MappedFile = New MappedFile(input_path + "peppers.jpg")
						Dim img_data As FilterReader = New FilterReader(img_file)
						Dim img As Image = Image.Create(doc.GetSDFDoc(), _
						 img_data, 400, 600, 8, ColorSpace.CreateDeviceRGB(), Image.InputFilter.e_jpeg)

						Dim element As Element = eb.CreateImage(img, New Matrix2D(200, -145, 20, 300, 200, 150))
						writer.WritePlacedElement(element)

						Dim gstate As GState = element.GetGState()		  ' use the same image (just change its matrix)
						gstate.SetTransform(200, 0, 0, 300, 50, 450)
						writer.WritePlacedElement(element)

						' use the same image again (just change its matrix).
						writer.WritePlacedElement(eb.CreateImage(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 = doc.PageCreate(New Rect(0, 0, 612, 794))

						writer.Begin(page)		  ' begin writing to this page
						eb.Reset()				   ' Reset GState to default

						eb.PathBegin()			   ' start constructing the path
						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()
						element = eb.PathEnd()			' the path is now finished
						element.SetPathFill(True)		   ' the path should be filled

						' Set the path color space and color
						gstate = element.GetGState()
						gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK())
						gstate.SetFillColor(New ColorPt(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
						element.SetPathStroke(True)		   ' this path is should be filled and stroked
						gstate.SetFillColor(New ColorPt(0, 0, 1, 0))		   ' yellow
						gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB())
						gstate.SetStrokeColor(New ColorPt(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
						element.SetPathFill(False)		  ' this path is should be only stroked
						gstate.SetStrokeColor(New ColorPt(0, 0, 1))		   ' blue
						gstate.SetTransform(0.5, 0, 0, 0.5, 280, 0)
						Dim dash_pattern(0) As Double
						dash_pattern(0) = 30
						gstate.SetDashPattern(dash_pattern, 0)
						writer.WritePlacedElement(element)

						' Use the path as a clipping path
						writer.WriteElement(eb.CreateGroupBegin())		  ' Save the graphics state
						' Start constructing a 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()
						element = eb.PathEnd()		  ' path is now built
						element.SetPathClip(True)		  ' this path is a clipping path
						element.SetPathStroke(True)		   ' this path is should be filled and stroked
						gstate = element.GetGState()
						gstate.SetTransform(0.5, 0, 0, 0.5, -20, 0)
						writer.WriteElement(element)
						writer.WriteElement(eb.CreateImage(img, 100, 300, 400, 600))
						writer.WriteElement(eb.CreateGroupEnd())		  ' Restore the graphics state

						writer.End()		  ' save changes to the current page
						doc.PagePushBack(page)


						' Start a new page ------------------------------------
						page = doc.PageCreate(New Rect(0, 0, 612, 794))

						writer.Begin(page)		  ' begin writing to this page
						eb.Reset()				   ' Reset GState to default

						' Begin writing a block of text
						element = eb.CreateTextBegin(PDF.Font.Create(doc, PDF.Font.StandardType1Font.e_times_roman), 12)
						writer.WriteElement(element)

						Dim data As String = "Hello World!"
						element = eb.CreateTextRun(data)
						element.SetTextMatrix(10, 0, 0, 10, 0, 600)
						element.GetGState().SetLeading(15)			' Set the spacing between lines
						writer.WriteElement(element)

						writer.WriteElement(eb.CreateTextNewLine())		  ' New line

						element = eb.CreateTextRun(data)
						gstate = element.GetGState()
						gstate.SetTextRenderMode(gstate.TextRenderingMode.e_stroke_text)
						gstate.SetCharSpacing(-1.25)
						gstate.SetWordSpacing(-1.25)
						writer.WriteElement(element)

						writer.WriteElement(eb.CreateTextNewLine())		  ' New line

						element = eb.CreateTextRun(data)
						gstate = element.GetGState()
						gstate.SetCharSpacing(0)
						gstate.SetWordSpacing(0)
						gstate.SetLineWidth(3)
						gstate.SetTextRenderMode(gstate.TextRenderingMode.e_fill_stroke_text)
						gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB())
						gstate.SetStrokeColor(New ColorPt(1, 0, 0))		  ' red
						gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK())
						gstate.SetFillColor(New ColorPt(1, 0, 0, 0))		  ' cyan
						writer.WriteElement(element)

						writer.WriteElement(eb.CreateTextNewLine())		   ' New line

						' Set text as a clipping path to the image.
						element = eb.CreateTextRun(data)
						gstate = element.GetGState()
						gstate.SetTextRenderMode(gstate.TextRenderingMode.e_clip_text)
						writer.WriteElement(element)

						' Finish the block of text
						writer.WriteElement(eb.CreateTextEnd())

						' Draw an image that will be clipped by the above text
						writer.WriteElement(eb.CreateImage(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.

						Using reader As ElementReader = New ElementReader

							' 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.Begin(doc.GetPage(doc.GetPageCount()))

							page = doc.PageCreate(New Rect(0, 0, 1300, 794))

							writer.Begin(page)		  ' begin writing to this page
							eb.Reset()				   ' Reset GState to default

							' Embed an external font in the document.
							Dim font As Font = font.CreateTrueTypeFont(doc, input_path + "font.ttf")

							element = reader.Next()
							While (Not IsNothing(element))			' Read page contents

								If (element.GetType() = element.Type.e_text) Then
									element.GetGState().SetFont(font, 12)
								End If

								writer.WriteElement(element)
								element = reader.Next()
							End While

							reader.End()
							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.

							' 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.Begin(doc.GetPage(doc.GetPageCount()))

							page = doc.PageCreate(New Rect(0, 0, 1300, 794))

							writer.Begin(page)		  ' begin writing to this page
							eb.Reset()				   ' Reset GState to default

							' Embed an external font in the document.
							Dim font2 As Font = font.CreateType1Font(doc, input_path + "Misc-Fixed.pfa")

							element = reader.Next()
							While (Not IsNothing(element))			' Read page contents
								If (element.GetType() = element.Type.e_text) Then
									element.GetGState().SetFont(font2, 12)
								End If

								writer.WriteElement(element)
								element = reader.Next()
							End While

							reader.End()
							writer.End()		   ' save changes to the current page
							doc.PagePushBack(page)


							' Start a new page ------------------------------------
							page = doc.PageCreate()
							writer.Begin(page)		  ' begin writing to this page
							eb.Reset()				   ' Reset GState to default

							' Begin writing a block of text
							Dim sys_font As Font = Font.Create(doc, Font.StandardType1Font.e_times_roman)
							element = eb.CreateTextBegin(sys_font, 12)
							element.SetTextMatrix(1.5, 0, 0, 1.5, 50, 600)
							element.GetGState().SetLeading(15)		  ' Set the spacing between lines
							writer.WriteElement(element)

							Dim para As String = "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"

							Dim para_end As Integer = para.Length
							Dim text_run As Integer = 0
							Dim text_run_end As Integer

							Dim para_width As Double = 300		   ' paragraph width is 300 units
							Dim cur_width As Double = 0

							While (text_run < para_end)
								text_run_end = para.IndexOf(" ", text_run)
								If (text_run_end < 0) Then
									text_run_end = para_end - 1
								End If

								Dim text As String = para.Substring(text_run, text_run_end - text_run + 1)
								element = eb.CreateTextRun(text)
								If (cur_width + element.GetTextLength() < para_width) Then
									writer.WriteElement(element)
									cur_width += element.GetTextLength()
								Else
									writer.WriteElement(eb.CreateTextNewLine())					' New line
									text = para.Substring(text_run, text_run_end - text_run + 1)
									element = eb.CreateTextRun(text)
									cur_width = element.GetTextLength()
									writer.WriteElement(element)
								End If

								text_run = text_run_end + 1
							End While
							' -----------------------------------------------------------------------
							' The following code snippet illustrates how to adjust spacing between 
							' characters (text runs).
							element = eb.CreateTextNewLine()
							writer.WriteElement(element)  ' Skip 2 lines
							writer.WriteElement(element)

							writer.WriteElement(eb.CreateTextRun("An example of space adjustments between inter-characters:"))
							writer.WriteElement(eb.CreateTextNewLine())

							' Write string "AWAY" without space adjustments between characters.
							element = eb.CreateTextRun("AWAY")
							writer.WriteElement(element)

							writer.WriteElement(eb.CreateTextNewLine())

							' Write string "AWAY" with space adjustments between characters.
							element = eb.CreateTextRun("A")
							writer.WriteElement(element)

							element = eb.CreateTextRun("W")
							element.SetPosAdjustment(140)
							writer.WriteElement(element)

							element = eb.CreateTextRun("A")
							element.SetPosAdjustment(140)
							writer.WriteElement(element)

							element = eb.CreateTextRun("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* ")
							' writer.WriteElement(eb.CreateTextNewLine())
							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(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 = doc.PageCreate()
							writer.Begin(page)  ' begin writing to the page

							' Create the Image Mask
							Dim imgf As MappedFile = New MappedFile(input_path + "imagemask.dat")
							Dim mask_read As FilterReader = New FilterReader(imgf)

							Dim device_gray As ColorSpace = ColorSpace.CreateDeviceGray()
							Dim mask As Image = Image.Create(doc, mask_read, 64, 64, 1, device_gray, Image.InputFilter.e_ascii_hex)

							mask.GetSDFObj().PutBool("ImageMask", True)

							element = eb.CreateRect(0, 0, 612, 794)
							element.SetPathStroke(False)
							element.SetPathFill(True)
							element.GetGState().SetFillColorSpace(device_gray)
							element.GetGState().SetFillColor(New ColorPt(0.8))
							writer.WritePlacedElement(element)

							element = eb.CreateImage(mask, New Matrix2D(200, 0, 0, -200, 40, 680))
							element.GetGState().SetFillColor(New ColorPt(0.1))
							writer.WritePlacedElement(element)

							element.GetGState().SetFillColorSpace(ColorSpace.CreateDeviceRGB())
							element.GetGState().SetFillColor(New ColorPt(1, 0, 0))
							element = eb.CreateImage(mask, New Matrix2D(200, 0, 0, -200, 320, 680))
							writer.WritePlacedElement(element)

							element.GetGState().SetFillColor(New ColorPt(0, 1, 0))
							element = eb.CreateImage(mask, New Matrix2D(200, 0, 0, -200, 40, 380))
							writer.WritePlacedElement(element)


							' This sample illustrates Explicit Masking. 
							img = Image.Create(doc, input_path + "peppers.jpg")

							' mask is the explicit mask for the primary (base) image
							img.SetMask(mask)

							element = eb.CreateImage(img, New Matrix2D(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 = doc.PageCreate()
							writer.Begin(page)			  ' begin writing to this page
							eb.Reset()			 ' Reset the GState to default

							' Write some transparent text at the bottom of the page.
							element = eb.CreateTextBegin(Font.Create(doc, Font.StandardType1Font.e_times_roman), 100)

							' Set the text knockout attribute. Text knockout must be set outside of 
							' the text group.
							gstate = element.GetGState()
							gstate.SetTextKnockout(False)
							gstate.SetBlendMode(gstate.BlendMode.e_bl_difference)
							writer.WriteElement(element)

							element = eb.CreateTextRun("Transparency")
							element.SetTextMatrix(1, 0, 0, 1, 30, 30)
							gstate = element.GetGState()
							gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK())
							gstate.SetFillColor(New ColorPt(1, 0, 0, 0))

							gstate.SetFillOpacity(0.5)
							writer.WriteElement(element)

							' Write the same text on top the old; shifted by 3 points
							element.SetTextMatrix(1, 0, 0, 1, 33, 33)
							gstate.SetFillColor(New ColorPt(0, 1, 0, 0))
							gstate.SetFillOpacity(0.5)

							writer.WriteElement(element)
							writer.WriteElement(eb.CreateTextEnd())

							' Draw three overlapping transparent circles.
							eb.PathBegin()			  ' start constrcting the path
							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 = eb.PathEnd()
							element.SetPathFill(True)

							gstate = element.GetGState()
							gstate.SetFillColorSpace(ColorSpace.CreateDeviceRGB())
							gstate.SetFillColor(New ColorPt(0, 0, 1))			' Blue Circle
							gstate.SetBlendMode(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.SetFillColor(New ColorPt(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.SetFillColor(New ColorPt(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 ------------------------------------

							doc.Save(output_path + "element_builder.pdf", SDF.SDFDoc.SaveOptions.e_remove_unused)
						End Using
					End Using
				End Using
			End Using
			Console.WriteLine("Done. Result saved in element_builder.pdf...")

		Catch ex As PDFNetException
			Console.WriteLine(ex.Message)
		Catch ex As Exception
			MsgBox(ex.Message)
		End Try
		PDFNet.Terminate()
	End Sub
End Module
```

{% endcode %}
{% endtab %}

{% tab title="Ruby" %}
{% code lineNumbers="true" %}

```ruby
#---------------------------------------------------------------------------------------
# Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
# Consult LICENSE.txt regarding license information.
#---------------------------------------------------------------------------------------

require '../../../PDFNetC/Lib/PDFNetRuby'
include PDFNetRuby
require '../../LicenseKey/RUBY/LicenseKey'

$stdout.sync = true

# Relative path to the folder containing the test files.
input_path = "../../TestFiles/"
output_path = "../../TestFiles/Output/"

	PDFNet.Initialize(PDFTronLicense.Key)
	
	doc = PDFDoc.new()
	
	# ElementBuilder is used to build new Element objects
	eb = ElementBuilder.new()
	# ElementWriter is used to write Elements to the page
	writer = ElementWriter.new()
	
	# Start a new page ------------------------------------
	page = doc.PageCreate(Rect.new(0, 0, 612, 794))
	
	writer.Begin(page)  # begin writing to the page

	# Create an Image that can be reused in the document or on the same page.
	img = Image.Create(doc.GetSDFDoc(), input_path + "peppers.jpg")
	
	element = eb.CreateImage(img, Matrix2D.new(img.GetImageWidth()/2, -145, 20, img.GetImageHeight()/2, 200, 150))
	writer.WritePlacedElement(element)
	
	gstate = element.GetGState()	# use the same image (just change its matrix)
	gstate.SetTransform(200, 0, 0, 300, 50, 450)
	writer.WritePlacedElement(element)
	
	# use the same image again (just change its matrix)
	writer.WritePlacedElement(eb.CreateImage(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 = doc.PageCreate(Rect.new(0, 0, 612, 794))
	
	writer.Begin(page)	# begin writing to this page
	eb.Reset()		# Reset the GState to default
	
	eb.PathBegin()	# start constructing the path
	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()
	element = eb.PathEnd()	# the path is now finished
	element.SetPathFill(true)	# the path should be filled
	
	# Set the path color space and color
	gstate = element.GetGState()
	gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK())
	gstate.SetFillColor(ColorPt.new(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
	element.SetPathStroke(true)	 # this path is should be filled and stroked
	gstate.SetFillColor(ColorPt.new(0, 0, 1, 0))  # yellow
	gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB())
	gstate.SetStrokeColor(ColorPt.new(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 a given dash pattern
	element.SetPathFill(false)	  # this path should be only stroked
	
	gstate.SetStrokeColor(ColorPt.new(0,0,1))   # blue
	gstate.SetTransform(0.5, 0, 0, 0.5, 280, 0)
	gstate.SetDashPattern([30], 0)
	writer.WritePlacedElement(element)
	
	# Use the path as a clipping path
	writer.WriteElement(eb.CreateGroupBegin())	# Save the graphics state
	# 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()
	element = eb.PathEnd()		# path is now constructed
	element.SetPathClip(true)	# this path is a clipping path
	element.SetPathStroke(true)	# this path should be filled and stroked
	gstate = element.GetGState()
	gstate.SetTransform(0.5, 0, 0, 0.5, -20, 0)
	
	writer.WriteElement(element)

	writer.WriteElement(eb.CreateImage(img, 100, 300, 400, 600))
		
	writer.WriteElement(eb.CreateGroupEnd())	# Restore the graphics state

	writer.End()	# save changes to the current page
	doc.PagePushBack(page)

	# Start a new page ------------------------------------
	page = doc.PageCreate(Rect.new(0, 0, 612, 794))

	writer.Begin(page)	# begin writing to this page
	eb.Reset()		# Reset the GState to default

	# Begin writing a block of text
	element = eb.CreateTextBegin(Font.Create(doc.GetSDFDoc(), Font::E_times_roman), 12)
	writer.WriteElement(element)

	element = eb.CreateTextRun("Hello World!")
	element.SetTextMatrix(10, 0, 0, 10, 0, 600)
	element.GetGState().SetLeading(15)	# Set the spacing between lines
	writer.WriteElement(element)

	writer.WriteElement(eb.CreateTextNewLine())	# New line

	element = eb.CreateTextRun("Hello World!")
	gstate = element.GetGState() 
	gstate.SetTextRenderMode(GState::E_stroke_text)
	gstate.SetCharSpacing(-1.25)
	gstate.SetWordSpacing(-1.25)
	writer.WriteElement(element)

	writer.WriteElement(eb.CreateTextNewLine())  # New line

	element = eb.CreateTextRun("Hello World!")
	gstate = element.GetGState() 
	gstate.SetCharSpacing(0)
	gstate.SetWordSpacing(0)
	gstate.SetLineWidth(3)
	gstate.SetTextRenderMode(GState::E_fill_stroke_text)
	gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB()) 
	gstate.SetStrokeColor(ColorPt.new(1, 0, 0))	# red
	gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK()) 
	gstate.SetFillColor(ColorPt.new(1, 0, 0, 0))	# cyan
	writer.WriteElement(element)
	
	writer.WriteElement(eb.CreateTextNewLine())  # New line

	# Set text as a clipping path to the image.
	element = eb.CreateTextRun("Hello World!")
	gstate = element.GetGState() 
	gstate.SetTextRenderMode(GState::E_clip_text)
	writer.WriteElement(element)

	# Finish the block of text
	writer.WriteElement(eb.CreateTextEnd())		

	# Draw an image that will be clipped by the above text
	writer.WriteElement(eb.CreateImage(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.

	reader = ElementReader.new()

	# 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.Begin(doc.GetPage(doc.GetPageCount()))

	page = doc.PageCreate(Rect.new(0, 0, 1300, 794))

	writer.Begin(page)	# begin writing to this page
	eb.Reset()		# Reset the GState to default

	# Embed an external font in the document.
	font = Font.CreateTrueTypeFont(doc.GetSDFDoc(), (input_path + "font.ttf"))
	
	element = reader.Next()
	while !element.nil? do		# Read page contents
		if element.GetType() == Element::E_text
			element.GetGState().SetFont(font, 12)
		end
		writer.WriteElement(element)
		element = reader.Next()
	end
	
	reader.End()
	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.

	# 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.Begin(doc.GetPage(doc.GetPageCount()))

	page = doc.PageCreate(Rect.new(0, 0, 1300, 794))

	writer.Begin(page)	# begin writing to this page
	eb.Reset()		# Reset the GState to default

	# Embed an external font in the document.
	font2 = Font.CreateType1Font(doc.GetSDFDoc(), (input_path + "Misc-Fixed.pfa"))
	
	element = reader.Next()
	while !element.nil? do
		if element.GetType() == Element::E_text
			element.GetGState().SetFont(font2, 12)
		end
		writer.WriteElement(element)
		element = reader.Next()
	end
	
	reader.End()
	writer.End()	# save changes to the current page
	doc.PagePushBack(page)
	
	# Start a new page ------------------------------------
	page = doc.PageCreate()
	writer.Begin(page)	# begin writing to this page
	eb.Reset()		# Reset the GState to default

	# Begin writing a block of text
	element = eb.CreateTextBegin(Font.Create(doc.GetSDFDoc(), Font::E_times_roman), 12)
	element.SetTextMatrix(1.5, 0, 0, 1.5, 50, 600)
	element.GetGState().SetLeading(15)	# Set the spacing between lines
	writer.WriteElement(element)
	
	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"

	para_end = para.length
	text_run = 0
	
	para_width = 300 # paragraph width is 300 units 
	cur_width = 0

	while text_run < para_end do
		text_run_end = para.index(' ', text_run)

		if text_run_end == nil
			text_run_end = para_end - 1
		end
		
		text = para[text_run..text_run_end]
		element = eb.CreateTextRun(text)
		if cur_width + element.GetTextLength() < para_width
			writer.WriteElement(element)
			cur_width = cur_width + element.GetTextLength()
		else
			writer.WriteElement(eb.CreateTextNewLine())	# new line
			element = eb.CreateTextRun(text)
			cur_width = element.GetTextLength()
			writer.WriteElement(element)
		end
		text_run = text_run_end + 1
	end
		
	# -----------------------------------------------------------------------
	# The following code snippet illustrates how to adjust spacing between 
	# characters (text runs).
	element = eb.CreateTextNewLine()
	writer.WriteElement(element)  # Skip 2 lines
	writer.WriteElement(element) 
		
	writer.WriteElement(eb.CreateTextRun("An example of space adjustments between inter-characters:")) 
	writer.WriteElement(eb.CreateTextNewLine()) 
		
	# Write string "AWAY" without space adjustments between characters.
	element = eb.CreateTextRun("AWAY")
	writer.WriteElement(element)  
		
	writer.WriteElement(eb.CreateTextNewLine()) 
		
	# Write string "AWAY" with space adjustments between characters.
	element = eb.CreateTextRun("A")
	writer.WriteElement(element)
		
	element = eb.CreateTextRun("W")
	element.SetPosAdjustment(140)
	writer.WriteElement(element)
		
	element = eb.CreateTextRun("A")
	element.SetPosAdjustment(140)
	writer.WriteElement(element)
		
	element = eb.CreateTextRun("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(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 = doc.PageCreate()
	writer.Begin(page)	# begin writing to the page

	# Create the Image Mask
	imgf = MappedFile.new((input_path + "imagemask.dat"))
	mask_read = FilterReader.new(imgf)

	device_gray = ColorSpace.CreateDeviceGray()
	mask = Image.Create(doc.GetSDFDoc(), mask_read, 64, 64, 1, device_gray, Image::E_ascii_hex)
	
	mask.GetSDFObj().PutBool("ImageMask", true)

	element = eb.CreateRect(0, 0, 612, 794)
	element.SetPathStroke(false)
	element.SetPathFill(true)
	element.GetGState().SetFillColorSpace(device_gray)
	element.GetGState().SetFillColor(ColorPt.new(0.8))
	writer.WritePlacedElement(element)

	element = eb.CreateImage(mask, Matrix2D.new(200, 0, 0, -200, 40, 680))
	element.GetGState().SetFillColor(ColorPt.new(0.1))
	writer.WritePlacedElement(element)

	element.GetGState().SetFillColorSpace(ColorSpace.CreateDeviceRGB())
	element.GetGState().SetFillColor(ColorPt.new(1, 0, 0))
	element = eb.CreateImage(mask, Matrix2D.new(200, 0, 0, -200, 320, 680))
	writer.WritePlacedElement(element)

	element.GetGState().SetFillColor(ColorPt.new(0, 1, 0))
	element = eb.CreateImage(mask, Matrix2D.new(200, 0, 0, -200, 40, 380))
	writer.WritePlacedElement(element)
	
	# This sample illustrates Explicit Masking. 
	img = Image.Create(doc.GetSDFDoc(), (input_path + "peppers.jpg"))

	# mask is the explicit mask for the primary (base) image
	img.SetMask(mask)

	element = eb.CreateImage(img, Matrix2D.new(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 = doc.PageCreate()
	writer.Begin(page)	# begin writing to this page
	eb.Reset()		# Reset the GState to default

	# Write some transparent text at the bottom of the page.
	element = eb.CreateTextBegin(Font.Create(doc.GetSDFDoc(), Font::E_times_roman), 100)

	# Set the text knockout attribute. Text knockout must be set outside of 
	# the text group.
	gstate = element.GetGState()
	gstate.SetTextKnockout(false)
	gstate.SetBlendMode(GState::E_bl_difference)
	writer.WriteElement(element)

	element = eb.CreateTextRun("Transparency")
	element.SetTextMatrix(1, 0, 0, 1, 30, 30)
	gstate = element.GetGState()
	gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK())
	gstate.SetFillColor(ColorPt.new(1, 0, 0, 0))

	gstate.SetFillOpacity(0.5)
	writer.WriteElement(element)

	# Write the same text on top the old; shifted by 3 points
	element.SetTextMatrix(1, 0, 0, 1, 33, 33)
	gstate.SetFillColor(ColorPt.new(0, 1, 0, 0))
	gstate.SetFillOpacity(0.5)

	writer.WriteElement(element)
	writer.WriteElement(eb.CreateTextEnd())

	# Draw three overlapping transparent circles.
	eb.PathBegin()		# start constructing the path
	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 = eb.PathEnd()
	element.SetPathFill(true)
	
	gstate = element.GetGState()
	gstate.SetFillColorSpace(ColorSpace.CreateDeviceRGB())
	gstate.SetFillColor(ColorPt.new(0, 0, 1))	# Blue Circle

	gstate.SetBlendMode(GState::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.SetFillColor(ColorPt.new(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.SetFillColor(ColorPt.new(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 ------------------------------------

	doc.Save((output_path + "element_builder.pdf"), SDFDoc::E_remove_unused)
	doc.Close()
	PDFNet.Terminate
	puts "Done. Result saved in element_builder.pdf..."
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/core/get-started/samples/elementbuildertest.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
