> 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/android/get-started/samples/elementbuildertest.md).

# ElementBuilder

Sample Java code to use Apryse SDK's page writing API to generate new pages, embed fonts & images, and copy graphical elements from one page to another.

Sample Java code to use Apryse SDK's page writing API to generate new pages, embed fonts & images, and copy graphical elements from one page to another. Learn more about our [Android SDK](/core/get-started/languages/java.md) and [PDF Editing & Manipulation Library](/core/page-manipulation/manipulation.md).

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

```java
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

package com.pdftron.android.pdfnetsdksamples.samples;

import com.pdftron.android.pdfnetsdksamples.OutputListener;
import com.pdftron.android.pdfnetsdksamples.PDFNetSample;
import com.pdftron.android.pdfnetsdksamples.R;
import com.pdftron.android.pdfnetsdksamples.util.Utils;
import com.pdftron.common.Matrix2D;
import com.pdftron.filters.MappedFile;
import com.pdftron.pdf.ColorPt;
import com.pdftron.pdf.ColorSpace;
import com.pdftron.pdf.Element;
import com.pdftron.pdf.ElementBuilder;
import com.pdftron.pdf.ElementReader;
import com.pdftron.pdf.ElementWriter;
import com.pdftron.pdf.Font;
import com.pdftron.pdf.GState;
import com.pdftron.pdf.Image;
import com.pdftron.pdf.PDFDoc;
import com.pdftron.pdf.Page;
import com.pdftron.pdf.Rect;
import com.pdftron.sdf.SDFDoc;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;

public class ElementBuilderTest extends PDFNetSample {

	private static OutputListener mOutputListener;

	private static ArrayList<String> mFileList = new ArrayList<>();

    public ElementBuilderTest() {
        setTitle(R.string.sample_elementbuilder_title);
        setDescription(R.string.sample_elementbuilder_description);
    }

	@Override
	public void run(OutputListener outputListener) {
		super.run(outputListener);
		mOutputListener = outputListener;
		mFileList.clear();
		printHeader(outputListener);

        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(), (Utils.getAssetTempFile(INPUT_PATH + "peppers.jpg").getAbsolutePath()));

            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 = Utils.getAssetTempFile(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, (Utils.getAssetTempFile(INPUT_PATH + "font.ttf").getAbsolutePath()));

            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, (Utils.getAssetTempFile(INPUT_PATH + "Misc-Fixed.pfa").getAbsolutePath()));

            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(Utils.getAssetTempFile(INPUT_PATH + "imagemask.dat").getAbsolutePath());
            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, (Utils.getAssetTempFile(INPUT_PATH + "peppers.jpg").getAbsolutePath()));

                // 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((Utils.createExternalFile("element_builder.pdf", mFileList).getAbsolutePath()), SDFDoc.SaveMode.REMOVE_UNUSED, null);
            mOutputListener.println("Done. Result saved in element_builder.pdf...");
        } catch (Exception e) {
            mOutputListener.printError(e.getStackTrace());
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (Exception ignored) {
                }
            }
        }

		for (String file : mFileList) {
			addToFileList(file);
		}
		printFooter(outputListener);
	}


}
```

{% endcode %}
{% endtab %}

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

```kotlin
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

package com.pdftron.android.pdfnetsdksamples.samples

import com.pdftron.android.pdfnetsdksamples.OutputListener
import com.pdftron.android.pdfnetsdksamples.PDFNetSample
import com.pdftron.android.pdfnetsdksamples.R
import com.pdftron.android.pdfnetsdksamples.util.Utils
import com.pdftron.common.Matrix2D
import com.pdftron.filters.FilterReader
import com.pdftron.filters.MappedFile
import com.pdftron.pdf.*
import com.pdftron.sdf.SDFDoc
import java.io.FileInputStream
import java.io.InputStream
import java.util.*

class ElementBuilderTest : PDFNetSample() {

    init {
        setTitle(R.string.sample_elementbuilder_title)
        setDescription(R.string.sample_elementbuilder_description)
    }

    override fun run(outputListener: OutputListener?) {
        super.run(outputListener)
        mOutputListener = outputListener
        mFileList.clear()
        printHeader(outputListener!!)
        var stream: InputStream? = null
        try {
            PDFDoc().use { doc ->
                val eb = ElementBuilder() // ElementBuilder is used to build new
                // Element objects
                val writer = ElementWriter() // ElementWriter is used to write
                // Elements to the page
                var element: Element?
                var gstate: GState

                // Start a new page ------------------------------------
                var page = doc.pageCreate(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.
                var img = Image.create(doc.sdfDoc, Utils.getAssetTempFile(INPUT_PATH + "peppers.jpg")!!.absolutePath)
                element = eb.createImage(img, Matrix2D((img.imageWidth / 2).toDouble(), (-145).toDouble(), 20.0, (img.imageHeight / 2).toDouble(), 200.0, 150.0))
                writer.writePlacedElement(element)
                gstate = element!!.gState // 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(Rect(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.0, 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!!.gState
                gstate.fillColorSpace = ColorSpace.createDeviceCMYK()
                gstate.fillColor = 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.fillColor = ColorPt(0.0, 0.0, 1.0, 0.0) // yellow
                gstate.strokeColorSpace = ColorSpace.createDeviceRGB()
                gstate.strokeColor = ColorPt(1.0, 0.0, 0.0) // red
                gstate.setTransform(0.5, 0.0, 0.0, 0.5, 280.0, 300.0)
                gstate.lineWidth = 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.strokeColor = ColorPt(0.0, 0.0, 1.0) // blue
                gstate.setTransform(0.5, 0.0, 0.0, 0.5, 280.0, 0.0)
                val dash_pattern = doubleArrayOf(30.0)
                gstate.setDashPattern(dash_pattern, 0.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!!.gState
                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(Rect(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(Font.create(doc, Font.e_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!!.gState.leading = 15.0 // Set the spacing
                // between lines
                writer.writeElement(element)
                writer.writeElement(eb.createTextNewLine()) // New line
                element = eb.createTextRun("Hello World!")
                gstate = element!!.gState
                gstate.textRenderMode = GState.e_stroke_text
                gstate.charSpacing = -1.25
                gstate.wordSpacing = -1.25
                writer.writeElement(element)
                writer.writeElement(eb.createTextNewLine()) // New line
                element = eb.createTextRun("Hello World!")
                gstate = element!!.gState
                gstate.charSpacing = 0.0
                gstate.wordSpacing = 0.0
                gstate.lineWidth = 3.0
                gstate.textRenderMode = GState.e_fill_stroke_text
                gstate.strokeColorSpace = ColorSpace.createDeviceRGB()
                gstate.strokeColor = ColorPt(1.0, 0.0, 0.0) // red
                gstate.fillColorSpace = ColorSpace.createDeviceCMYK()
                gstate.fillColor = ColorPt(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!!.gState
                gstate.textRenderMode = 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.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.
                val 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.pageCount))
                page = doc.pageCreate(Rect(
                    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.
                val font: Font
                val file = Utils.getAssetTempFile(INPUT_PATH + "font.ttf")
                stream = FileInputStream(file)
                font = Font.createTrueTypeFont(doc, stream!!)
                //Alternatively, the font can be created from the file path.
                //font = Font.createTrueTypeFont(doc, (Utils.getAssetTempFile(INPUT_PATH + "font.ttf").getAbsolutePath()));
                while (reader.next().also { element = it } != null) // Read page
                // contents
                {
                    if (element!!.type == Element.e_text) {
                        element!!.gState.setFont(font, 12.0)
                    }
                    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.pageCount))
                page = doc.pageCreate(Rect(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.
                val font2 = Font.createType1Font(doc, Utils.getAssetTempFile(INPUT_PATH + "Misc-Fixed.pfa")!!.absolutePath)
                while (reader.next().also { element = it } != null) // Read page contents
                {
                    if (element!!.type == Element.e_text) {
                        element!!.gState.setFont(font2, 12.0)
                    }
                    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.0)
                element!!.setTextMatrix(1.5, 0.0, 0.0, 1.5, 50.0, 600.0)
                element!!.gState.leading = 15.0 // Set the spacing between
                // lines
                writer.writeElement(element)
                val 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"
                val para_end = para.length
                var text_run = 0
                var text_run_end: Int
                val para_width = 300.0 // paragraph width is 300 units
                var cur_width = 0.0
                while (text_run < para_end) {
                    text_run_end = para.indexOf(' ', text_run)
                    if (text_run_end < 0) text_run_end = para_end - 1
                    var text = para.substring(text_run, text_run_end + 1)
                    element = eb.createTextRun(text)
                    if (cur_width + element!!.textLength < para_width) {
                        writer.writeElement(element)
                        cur_width += element!!.textLength
                    } else {
                        writer.writeElement(eb.createTextNewLine()) // New
                        text = para.substring(text_run, text_run_end + 1) // line
                        element = eb.createTextRun(text)
                        cur_width = element!!.textLength
                        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!!.posAdjustment = 140.0
                writer.writeElement(element)
                element = eb.createTextRun("A")
                element!!.posAdjustment = 140.0
                writer.writeElement(element)
                element = eb.createTextRun("Y again")
                element!!.posAdjustment = 115.0
                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
                val imgf = MappedFile(Utils.getAssetTempFile(INPUT_PATH + "imagemask.dat")!!.absolutePath)
                val mask_read = FilterReader(imgf)
                val device_gray = ColorSpace.createDeviceGray()
                val mask = Image.create(doc, mask_read, 64, 64, 1, device_gray, Image.e_ascii_hex)
                mask.sdfObj.putBool("ImageMask", true)
                element = eb.createRect(0.0, 0.0, 612.0, 794.0)
                element!!.setPathStroke(false)
                element!!.setPathFill(true)
                element!!.gState.fillColorSpace = device_gray
                element!!.gState.fillColor = ColorPt(0.8, 0.0, 0.0)
                writer.writePlacedElement(element)
                element = eb.createImage(mask, Matrix2D(200.0, 0.0, 0.0, (-200).toDouble(), 40.0, 680.0))
                element!!.gState.fillColor = ColorPt(0.1, 0.0, 0.0)
                writer.writePlacedElement(element)
                element!!.gState.fillColorSpace = ColorSpace.createDeviceRGB()
                element!!.gState.fillColor = ColorPt(1.0, 0.0, 0.0)
                element = eb.createImage(mask, Matrix2D(200.0, 0.0, 0.0, (-200).toDouble(), 320.0, 680.0))
                writer.writePlacedElement(element)
                element!!.gState.fillColor = ColorPt(0.0, 1.0, 0.0)
                element = eb.createImage(mask, Matrix2D(200.0, 0.0, 0.0, (-200).toDouble(), 40.0, 380.0))
                writer.writePlacedElement(element)
                run {

                    // This sample illustrates Explicit Masking.
                    img = Image.create(doc, Utils.getAssetTempFile(INPUT_PATH + "peppers.jpg")!!.absolutePath)

                    // mask is the explicit mask for the primary (base) image
                    img.setMask(mask)
                    element = eb.createImage(img, Matrix2D(200.0, 0.0, 0.0, (-200).toDouble(), 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(Font.create(doc, Font.e_times_roman), 100.0)

                // Set the text knockout attribute. Text knockout must be set
                // outside of
                // the text group.
                gstate = element!!.gState
                gstate.isTextKnockout = false
                gstate.blendMode = GState.e_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!!.gState
                gstate.fillColorSpace = ColorSpace.createDeviceCMYK()
                gstate.fillColor = ColorPt(1.0, 0.0, 0.0, 0.0)
                gstate.fillOpacity = 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.fillColor = ColorPt(0.0, 1.0, 0.0, 0.0)
                gstate.fillOpacity = 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!!.gState
                gstate.fillColorSpace = ColorSpace.createDeviceRGB()
                gstate.fillColor = ColorPt(0.0, 0.0, 1.0) // Blue
                // Circle
                gstate.blendMode = GState.e_bl_normal
                gstate.fillOpacity = 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.fillColor = ColorPt(0.0, 1.0, 0.0) // Green
                // Circle
                gstate.fillOpacity = 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.fillColor = ColorPt(1.0, 0.0, 0.0) // Red
                // Circle
                gstate.fillOpacity = 0.5
                writer.writeElement(element)
                writer.end() // save changes to the current page
                doc.pagePushBack(page)

                // End page ------------------------------------
                doc.save(Utils.createExternalFile("element_builder.pdf", mFileList).absolutePath, SDFDoc.SaveMode.REMOVE_UNUSED, null)
                mOutputListener!!.println("Done. Result saved in element_builder.pdf...")
            }
        } catch (e: Exception) {
            mOutputListener!!.printError(e.stackTrace)
        } finally {
            if (stream != null) {
                try {
                    stream!!.close()
                } catch (ignored: Exception) {
                }
            }
        }
        for (file in mFileList) {
            addToFileList(file)
        }
        printFooter(outputListener)
    }

    companion object {
        private var mOutputListener: OutputListener? = null
        private val mFileList = ArrayList<String>()
    }
}
```

{% 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/android/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.
