> 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/unicodewritetest.md).

# Create Unicode Text, Embed CID in PDFs - UnicodeWrite

Sample code for using Apryse SDK to create Unicode text and embed composite fonts in PDF files. Samples provided in Python, C++, C#, Java, Node.js (JavaScript), PHP, Ruby, Go and VB.

Sample code for using Apryse SDK to create Unicode text and embed composite fonts in PDF files. Samples provided in Python, C++, C#, Java, Node.js (JavaScript), PHP, Ruby, Go and VB. Learn more about our [Server SDK](/core/get-started/get-started.md).

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

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

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

namespace UnicodeWriteTestCS
{
	/// <summary>
	/// This example illustrates how to create Unicode text and how to embed composite fonts.
	/// </summary>
	class Class1
	{
		private static pdftron.PDFNetLoader pdfNetLoader = pdftron.PDFNetLoader.Instance();
		static Class1() {}
		
		// Note: This demo assumes that 'arialuni.ttf' is present in '/Samples/TestFiles' 
		// directory. Arial Unicode MS is about 24MB in size and it comes together with Windows and 
		// MS Office.
		// 
		// For more information about Arial Unicode MS, please consult the following Microsoft Knowledge 
		// Base Article: WD2002: General Information About the Arial Unicode MS Font
		//  http://support.microsoft.com/support/kb/articles/q287/2/47.asp
		//
		// For more information consult: 
		//    http://office.microsoft.com/search/results.aspx?Scope=DC&Query=font&CTT=6&Origin=EC010331121033
		//    http://www.microsoft.com/downloads/details.aspx?FamilyID=1F0303AE-F055-41DA-A086-A65F22CB5593
		// 
		// In case you don't have access to Arial Unicode MS you can use cyberbit.ttf 
		// (ftp://ftp.netscape.com/pub/communicator/extras/fonts/windows/) instead.
		//
		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())
					{
						using (ElementWriter writer = new ElementWriter())
						{
							// Start a new page ------------------------------------
							Page page = doc.PageCreate(new Rect(0, 0, 612, 794));

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

							Font fnt = null;
							try
							{
								// Full font embedding
								System.Drawing.Font myfont = new System.Drawing.Font("Arial Unicode MS", 12);
								fnt = Font.CreateCIDTrueTypeFont(doc, myfont, true, true);
							}
							catch (PDFNetException e)
							{
								Console.WriteLine(e.Message);
							}

							if (fnt == null) {
								try
								{
									fnt = Font.CreateCIDTrueTypeFont(doc, input_path + "ARIALUNI.TTF", true, true);
								}
								catch (PDFNetException e)
								{
									Console.WriteLine(e.Message);
								}
							}

							if (fnt == null)
							{
								try
								{
									fnt = Font.CreateCIDTrueTypeFont(doc, "C:/Windows/Fonts/ARIALUNI.TTF", true, true);
								}
								catch (PDFNetException e)
								{
									Console.WriteLine(e.Message);
								}
							}

							if (fnt == null)
							{
								Console.WriteLine("Note: using system font substitution for unshaped unicode text");
								fnt = Font.Create(doc, "Helvetica", "");
							}
							else
							{
								Console.WriteLine("Note: using Arial Unicode for unshaped unicode text");
							}

							Element element = eb.CreateTextBegin(fnt, 1);
							element.SetTextMatrix(10, 0, 0, 10, 50, 600);
							element.GetGState().SetLeading(2);		 // Set the spacing between lines
							writer.WriteElement(element);

							// Hello World!!!
							string hello = "Hello World!";
							writer.WriteElement(eb.CreateUnicodeTextRun(hello));
							writer.WriteElement(eb.CreateTextNewLine());

							// Latin
							char[] latin = {   
								'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', '\x45', '\x0046', '\x00C0', 
								'\x00C1', '\x00C2', '\x0143', '\x0144', '\x0145', '\x0152', '1', '2' // etc.
							};
							writer.WriteElement(eb.CreateUnicodeTextRun(new string(latin)));
							writer.WriteElement(eb.CreateTextNewLine());

							// Greek
							char[] greek = {   
								(char)0x039E, (char)0x039F, (char)0x03A0, (char)0x03A1, (char)0x03A3,
								(char)0x03A6, (char)0x03A8, (char)0x03A9  // etc.
							};
							writer.WriteElement(eb.CreateUnicodeTextRun(new string(greek)));
							writer.WriteElement(eb.CreateTextNewLine());

							// Cyrillic
							char[] cyrillic = {   
								(char)0x0409, (char)0x040A, (char)0x040B, (char)0x040C, (char)0x040E, (char)0x040F, (char)0x0410, (char)0x0411,
								(char)0x0412, (char)0x0413, (char)0x0414, (char)0x0415, (char)0x0416, (char)0x0417, (char)0x0418, (char)0x0419 // etc.
							};
							writer.WriteElement(eb.CreateUnicodeTextRun(new string(cyrillic)));
							writer.WriteElement(eb.CreateTextNewLine());

							// Hebrew
							char[] hebrew = {
								(char)0x05D0, (char)0x05D1, (char)0x05D3, (char)0x05D3, (char)0x05D4, (char)0x05D5, (char)0x05D6, (char)0x05D7, (char)0x05D8, 
								(char)0x05D9, (char)0x05DA, (char)0x05DB, (char)0x05DC, (char)0x05DD, (char)0x05DE, (char)0x05DF, (char)0x05E0, (char)0x05E1 // etc. 
							};
							writer.WriteElement(eb.CreateUnicodeTextRun(new string(hebrew)));
							writer.WriteElement(eb.CreateTextNewLine());

							// Arabic
							char[] arabic = {
								(char)0x0624, (char)0x0625, (char)0x0626, (char)0x0627, (char)0x0628, (char)0x0629, (char)0x062A, (char)0x062B, (char)0x062C, 
								(char)0x062D, (char)0x062E, (char)0x062F, (char)0x0630, (char)0x0631, (char)0x0632, (char)0x0633, (char)0x0634, (char)0x0635 // etc. 
							};
							writer.WriteElement(eb.CreateUnicodeTextRun(new string(arabic)));
							writer.WriteElement(eb.CreateTextNewLine());

							// Thai 
							char[] thai = {
								(char)0x0E01, (char)0x0E02, (char)0x0E03, (char)0x0E04, (char)0x0E05, (char)0x0E06, (char)0x0E07, (char)0x0E08, (char)0x0E09, 
								(char)0x0E0A, (char)0x0E0B, (char)0x0E0C, (char)0x0E0D, (char)0x0E0E, (char)0x0E0F, (char)0x0E10, (char)0x0E11, (char)0x0E12 // etc. 
							};
							writer.WriteElement(eb.CreateUnicodeTextRun(new string(thai)));
							writer.WriteElement(eb.CreateTextNewLine());

							// Hiragana - Japanese 
							char[] hiragana = {
								(char)0x3041, (char)0x3042, (char)0x3043, (char)0x3044, (char)0x3045, (char)0x3046, (char)0x3047, (char)0x3048, (char)0x3049, 
								(char)0x304A, (char)0x304B, (char)0x304C, (char)0x304D, (char)0x304E, (char)0x304F, (char)0x3051, (char)0x3051, (char)0x3052 // etc. 
							};
							writer.WriteElement(eb.CreateUnicodeTextRun(new string(hiragana)));
							writer.WriteElement(eb.CreateTextNewLine());

							// CJK Unified Ideographs
							char[] cjk_uni = {
								(char)0x5841, (char)0x5842, (char)0x5843, (char)0x5844, (char)0x5845, (char)0x5846, (char)0x5847, (char)0x5848, (char)0x5849, 
								(char)0x584A, (char)0x584B, (char)0x584C, (char)0x584D, (char)0x584E, (char)0x584F, (char)0x5850, (char)0x5851, (char)0x5852 // etc. 
							};
							writer.WriteElement(eb.CreateUnicodeTextRun(new string(cjk_uni)));
							writer.WriteElement(eb.CreateTextNewLine());

							// Simplified Chinese
							char[] chinese_simplified = {
								(char)0x4e16, (char)0x754c, (char)0x60a8,(char) 0x597d
							};
							writer.WriteElement(eb.CreateUnicodeTextRun(new string(chinese_simplified)));
							writer.WriteElement(eb.CreateTextNewLine());

							// Finish the block of text
							writer.WriteElement(eb.CreateTextEnd());		
							Console.WriteLine("Now using text shaping logic to place text");

							// Create a font in indexed encoding mode 
							// normally this would mean that we are required to provide glyph indices
							// directly to CreateUnicodeTextRun, but instead, we will use the GetShapedText
							// method to take care of this detail for us.
							Font indexedFont = Font.CreateCIDTrueTypeFont(doc, input_path + "NotoSans_with_hindi.ttf", true, true, Font.Encoding.e_Indices);
							element = eb.CreateTextBegin(indexedFont, 10.0);
							writer.WriteElement(element);

							double linePos = 350.0;
							double lineSpace = 20.0;

							// Transform unicode text into an abstract collection of glyph indices and positioning info 
							ShapedText shapedText = indexedFont.GetShapedText("Shaped Hindi Text:");

							// transform the shaped text info into a PDF element and write it to the page
							element = eb.CreateShapedTextRun(shapedText);
							element.SetTextMatrix(1.5, 0, 0, 1.5, 50, linePos);
							linePos -= lineSpace;
							writer.WriteElement(element);

							// read in unicode text lines from a file File. ReadAllLines(path, Encoding.UTF8)
							String[] hindiTextLines = File.ReadAllLines(input_path + "hindi_sample_utf16le.txt", Encoding.UTF8);

							Console.WriteLine("Read in " + hindiTextLines.Length + " lines of Unicode text from file");
							foreach (String textLine in hindiTextLines)
							{
								shapedText = indexedFont.GetShapedText(textLine);
								element = eb.CreateShapedTextRun(shapedText);
								element.SetTextMatrix(1.5, 0, 0, 1.5, 50, linePos);
								linePos -= lineSpace;
								writer.WriteElement(element);
								Console.WriteLine("Wrote shaped line to page");
							}

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

							writer.End();  // save changes to the current page
							doc.PagePushBack(page);
							doc.Save(output_path + "unicodewrite.pdf", SDFDoc.SaveOptions.e_remove_unused | SDFDoc.SaveOptions.e_hex_strings);
							Console.WriteLine("Done. Result saved in unicodewrite.pdf...");
						}
					}
				}
			}
			catch (PDFNetException e)
			{
				Console.WriteLine(e.Message);
			}
			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 <PDF/PDFNet.h>
#include <PDF/PDFDoc.h>
#include <PDF/ElementBuilder.h>
#include <PDF/ElementWriter.h>
#include <PDF/ColorSpace.h>
#include <PDF/ShapedText.h>
#include <PDF/Rect.h>

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

#include <fstream>
#include <iostream>
#include "../../LicenseKey/CPP/LicenseKey.h"

using namespace std;

using namespace pdftron;
using namespace SDF;
using namespace PDF;

std::vector<UString> TextFileToStringList(const UString& file_path);

/**
 * This example illustrates how to create Unicode text and how to embed composite fonts.
 * 
 * Note: This demo attempts to make use of 'arialuni.ttf' in the '/Samples/TestFiles' 
 * directory. Arial Unicode MS is about 24MB in size and used to come together with Windows and 
 * MS Office.
 * 
 * In case you don't have access to Arial Unicode MS you can use another wide coverage
 * font, like Google Noto, GNU UniFont, or cyberbit. Many of these are freely available,
 * and there is a list maintained at https://en.wikipedia.org/wiki/Unicode_font
 * 
 * If no specific font file can be loaded, the demo will fall back to system specific font
 * substitution routines, and the result will depend on which fonts are available.
 * 
 */
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;		
		ElementWriter writer;	

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

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

		string font_program = input_path + "ARIALUNI.TTF";

		// RAII block for ifstream
		{
			std::ifstream ifs(font_program.c_str(), ios_base::in);
#if defined(_WIN32)
			if (!ifs.is_open()) {
				font_program = string("C:/Windows/Fonts/ARIALUNI.TTF");
				ifs.open(font_program.c_str(), ios_base::in);
			}
#endif
			if (!ifs.is_open()) {
				font_program.clear();
			}
		}

		Font fnt;
		if(font_program.size())
		{
			cout << "Note: using " << font_program << " for unshaped unicode text" << endl;
			// if we can find a specific wide-coverage font file, then use that directly
			fnt = Font::CreateCIDTrueTypeFont(doc, font_program.c_str(), true, true);
		}
		else
		{
			cout << "Note: using system font substitution for unshaped unicode text" << endl;
			// if we can't find a specific file, then use system font subsitution 
			// as a fallback, using "Helvetica" as a hint
			UString empty_temp;
			fnt = Font::Create(doc, "Helvetica", empty_temp);
		}
		
		Element element = eb.CreateTextBegin(fnt, 1);
		element.SetTextMatrix(10, 0, 0, 10, 50, 600);
		element.GetGState().SetLeading(2);		 // Set the spacing between lines
		writer.WriteElement(element);

		// Hello World!
		Unicode hello[] = { 'H','e','l','l','o',' ','W','o','r','l','d','!'};
		writer.WriteElement(eb.CreateUnicodeTextRun(hello, sizeof(hello)/sizeof(Unicode)));
		writer.WriteElement(eb.CreateTextNewLine());

		// Latin
		Unicode latin[] = {   
			'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 0x45, 0x0046, 0x00C0, 
			0x00C1, 0x00C2, 0x0143, 0x0144, 0x0145, 0x0152, '1', '2' // etc.
		};
		writer.WriteElement(eb.CreateUnicodeTextRun(latin, sizeof(latin)/sizeof(Unicode)));
		writer.WriteElement(eb.CreateTextNewLine());

		// Greek
		Unicode greek[] = {   
			0x039E, 0x039F, 0x03A0, 0x03A1,0x03A3, 0x03A6, 0x03A8, 0x03A9  // etc.
		};
		writer.WriteElement(eb.CreateUnicodeTextRun(greek, sizeof(greek)/sizeof(Unicode)));
		writer.WriteElement(eb.CreateTextNewLine());

		// Cyrillic
		Unicode cyrillic[] = {   
			0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0x0410, 0x0411,
			0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419 // etc.
		};
		writer.WriteElement(eb.CreateUnicodeTextRun(cyrillic, sizeof(cyrillic)/sizeof(Unicode)));
		writer.WriteElement(eb.CreateTextNewLine());

		// Hebrew
		Unicode hebrew[] = {
			0x05D0, 0x05D1, 0x05D3, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 
			0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1 // etc. 
		};
		writer.WriteElement(eb.CreateUnicodeTextRun(hebrew, sizeof(hebrew)/sizeof(Unicode)));
		writer.WriteElement(eb.CreateTextNewLine());

		// Arabic
		Unicode arabic[] = {
			0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 
			0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635 // etc. 
		};
		writer.WriteElement(eb.CreateUnicodeTextRun(arabic, sizeof(arabic)/sizeof(Unicode)));
		writer.WriteElement(eb.CreateTextNewLine());

		// Thai 
		Unicode thai[] = {
			0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 
			0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12 // etc. 
		};
		writer.WriteElement(eb.CreateUnicodeTextRun(thai, sizeof(thai)/sizeof(Unicode)));
		writer.WriteElement(eb.CreateTextNewLine());

		// Hiragana - Japanese 
		Unicode hiragana[] = {
			0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049, 
			0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, 0x3051, 0x3051, 0x3052 // etc. 
		};
		writer.WriteElement(eb.CreateUnicodeTextRun(hiragana, sizeof(hiragana)/sizeof(Unicode)));
		writer.WriteElement(eb.CreateTextNewLine());

		// CJK Unified Ideographs
		Unicode cjk_uni[] = {
			0x5841, 0x5842, 0x5843, 0x5844, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849, 
			0x584A, 0x584B, 0x584C, 0x584D, 0x584E, 0x584F, 0x5850, 0x5851, 0x5852 // etc. 
		};
		writer.WriteElement(eb.CreateUnicodeTextRun(cjk_uni, sizeof(cjk_uni)/sizeof(Unicode)));
		writer.WriteElement(eb.CreateTextNewLine());

		// Simplified Chinese
		Unicode chinese_simplified[] = {
			0x4e16, 0x754c, 0x60a8, 0x597d
		};
		writer.WriteElement(eb.CreateUnicodeTextRun(chinese_simplified, sizeof(chinese_simplified)/sizeof(Unicode)));
		writer.WriteElement(eb.CreateTextNewLine());

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

		cout << "Now using text shaping logic to place text" << endl;

		// Create a font in indexed encoding mode 
		// normally this would mean that we are required to provide glyph indices
		// directly to CreateUnicodeTextRun, but instead, we will use the GetShapedText
		// method to take care of this detail for us.
		Font indexed_font = Font::CreateCIDTrueTypeFont(doc, input_path + "NotoSans_with_hindi.ttf", true, true, Font::e_Indices);
		element = eb.CreateTextBegin(indexed_font, 10);
		writer.WriteElement(element);

		double line_pos = 350.0;
		double line_space = 20.0;

		// Transform unicode text into an abstract collection of glyph indices and positioning info 
		ShapedText shaped_text = indexed_font.GetShapedText(UString("Shaped Hindi Text:"));

		// transform the shaped text info into a PDF element and write it to the page
		element = eb.CreateShapedTextRun(shaped_text);
		element.SetTextMatrix(1.5, 0, 0, 1.5, 50, line_pos);
		writer.WriteElement(element);

		// read in unicode text lines from a file 
		std::vector<UString> hindi_text = TextFileToStringList(input_path + "hindi_sample_utf16le.txt");

		cout << "Read in " << hindi_text.size() << " lines of Unicode text from file" << endl;
		for (size_t i = 0; i < hindi_text.size(); ++i)
		{
			shaped_text = indexed_font.GetShapedText(hindi_text[i]);
			element = eb.CreateShapedTextRun(shaped_text);
			element.SetTextMatrix(1.5, 0, 0, 1.5, 50, line_pos-line_space*(i+1));
			writer.WriteElement(element);
			cout << "Wrote shaped line to page" << endl;
		}
		
		// Finish the shaped block of text
		writer.WriteElement(eb.CreateTextEnd());

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

		doc.Save((output_path + "unicodewrite.pdf").c_str(), SDFDoc::e_remove_unused | SDFDoc::e_hex_strings , NULL);
		cout << "Done. Result saved in unicodewrite.pdf..." << endl;
	}
	catch(Common::Exception& e)
	{
		cout << e << endl;
		ret = 1;
	}
	catch(...)
	{
		cout << "Unknown Exception" << endl;
		ret = 1;
	}
	
	PDFNet::Terminate();
	return ret;
}

std::vector<UString> TextFileToStringList(const UString& file_path)
{
	Filters::MappedFile utf_text_filter(file_path);
	size_t file_size = utf_text_filter.FileSize();
	Filters::FilterReader utf_reader(utf_text_filter);
	std::vector<unsigned char> data = utf_reader.Read(file_size);
	data.push_back(0);
	data.push_back(0);
	std::vector<UString> ret;
	size_t line_start = 0;
	for (size_t i = 0; i+1 < data.size(); i +=2)
	{
		bool has_newline = false;
		size_t end_index = i;
		while(i+1 < data.size() && data[i+1] == 0 && (data[i] == '\n' || data[i] == '\r'))
		{
			i+=2;
			has_newline = true;
		}
		if(has_newline || (i + 2 >=  data.size() && line_start < data.size()))
		{
			ret.push_back(UString(reinterpret_cast<Unicode*>(&data[line_start]), (end_index - line_start)/2));
			line_start = i;
		}
	}
	return ret;
}
```

{% 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.pdf.*;
import com.pdftron.sdf.SDFDoc;
import java.util.List;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;

/**
 * This example illustrates how to create Unicode text and how to embed composite fonts.
 * <p>
 * Note: This demo attempts to make use of 'arialuni.ttf' in the '/Samples/TestFiles' 
 * directory. Arial Unicode MS is about 24MB in size and used to come together with Windows and 
 * MS Office.
 * <p>
 * In case you don't have access to Arial Unicode MS you can use another wide coverage
 * font, like Google Noto, GNU UniFont, or cyberbit. Many of these are freely available,
 * and there is a list maintained at https://en.wikipedia.org/wiki/Unicode_font
 * <p>
 * If no specific font file can be loaded, the demo will fall back to system specific font
 * substitution routines, and the result will depend on which fonts are available.
 * 
 */
public class UnicodeWriteTest {
    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/";

        try (PDFDoc doc = new PDFDoc()) {
            ElementBuilder eb = new ElementBuilder();
            ElementWriter writer = new ElementWriter();

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

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

            String fontLocation = input_path + "ARIALUNI.TTF";

            Font fnt = null;
            try {
                // Embed and subset the font
                fnt = Font.createCIDTrueTypeFont(doc, fontLocation, true, true);
            } catch (Exception e) {
                fontLocation = "C:/Windows/Fonts/ARIALUNI.TTF";
                try {
                     fnt = Font.createCIDTrueTypeFont(doc, fontLocation, true, true);
                }
                catch (Exception e2) {
                    fontLocation = null;
                }
            }

            if(fnt != null) {
                System.out.println("Note: using " + fontLocation + " for unshaped unicode text");
            }
            else {
                System.out.println("Note: using system font substitution for unshaped unicode text");
                fnt = Font.create(doc, "Helvetica", "");
            }

            Element element = eb.createTextBegin(fnt, 1);
            element.setTextMatrix(10, 0, 0, 10, 50, 600);
            element.getGState().setLeading(2);         // Set the spacing between lines
            writer.writeElement(element);

            // Hello World!
            char hello[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'};
            writer.writeElement(eb.createUnicodeTextRun(new String(hello)));
            writer.writeElement(eb.createTextNewLine());

            // Latin
            char latin[] = {
                    'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 0x45, 0x0046, 0x00C0,
                    0x00C1, 0x00C2, 0x0143, 0x0144, 0x0145, 0x0152, '1', '2' // etc.
            };
            writer.writeElement(eb.createUnicodeTextRun(new String(latin)));
            writer.writeElement(eb.createTextNewLine());

            // Greek
            char greek[] = {
                    0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A3, 0x03A6, 0x03A8, 0x03A9  // etc.
            };
            writer.writeElement(eb.createUnicodeTextRun(new String(greek)));
            writer.writeElement(eb.createTextNewLine());

            // Cyrillic
            char cyrilic[] = {
                    0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0x0410, 0x0411,
                    0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419 // etc.
            };
            writer.writeElement(eb.createUnicodeTextRun(new String(cyrilic)));
            writer.writeElement(eb.createTextNewLine());

            // Hebrew
            char hebrew[] = {
                    0x05D0, 0x05D1, 0x05D3, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8,
                    0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1 // etc.
            };
            writer.writeElement(eb.createUnicodeTextRun(new String(hebrew)));
            writer.writeElement(eb.createTextNewLine());

            // Arabic
            char arabic[] = {
                    0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C,
                    0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635 // etc.
            };
            writer.writeElement(eb.createUnicodeTextRun(new String(arabic)));
            writer.writeElement(eb.createTextNewLine());

            // Thai
            char thai[] = {
                    0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09,
                    0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12 // etc.
            };
            writer.writeElement(eb.createUnicodeTextRun(new String(thai)));
            writer.writeElement(eb.createTextNewLine());

            // Hiragana - Japanese
            char hiragana[] = {
                    0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049,
                    0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, 0x3051, 0x3051, 0x3052 // etc.
            };
            writer.writeElement(eb.createUnicodeTextRun(new String(hiragana)));
            writer.writeElement(eb.createTextNewLine());

            // CJK Unified Ideographs
            char cjk_uni[] = {
                    0x5841, 0x5842, 0x5843, 0x5844, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849,
                    0x584A, 0x584B, 0x584C, 0x584D, 0x584E, 0x584F, 0x5850, 0x5851, 0x5852 // etc.
            };
            writer.writeElement(eb.createUnicodeTextRun(new String(cjk_uni)));
            writer.writeElement(eb.createTextNewLine());

            // Simplified Chinese
            char chinese_simplified[] = {
              0x4e16, 0x754c, 0x60a8, 0x597d
            };
            writer.writeElement(eb.createUnicodeTextRun(new String(chinese_simplified)));
            writer.writeElement(eb.createTextNewLine());

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

            System.out.println("Now using text shaping logic to place text");

            // Create a font in indexed encoding mode 
            // normally this would mean that we are required to provide glyph indices
            // directly to CreateUnicodeTextRun, but instead, we will use the GetShapedText
            // method to take care of this detail for us.
            Font indexedFont = Font.createCIDTrueTypeFont(doc, input_path + "NotoSans_with_hindi.ttf", true, true, Font.e_Indices);
            element = eb.createTextBegin(indexedFont, 10.0);
            writer.writeElement(element);

            double linePos = 350.0;
            double lineSpace = 20.0;

            // Transform unicode text into an abstract collection of glyph indices and positioning info 
            ShapedText shapedText = indexedFont.getShapedText("Shaped Hindi Text:");

            // transform the shaped text info into a PDF element and write it to the page
            element = eb.createShapedTextRun(shapedText);
            element.setTextMatrix(1.5, 0, 0, 1.5, 50, linePos);
            linePos -= lineSpace;
            writer.writeElement(element);

            // read in unicode text lines from a file 
            List<String> hindiTextLines = Files.readAllLines(Paths.get(input_path + "hindi_sample_utf16le.txt"), StandardCharsets.UTF_16LE);

            System.out.println("Read in " + hindiTextLines.size() + " lines of Unicode text from file");
            for (String textLine : hindiTextLines)  
            {
                shapedText = indexedFont.getShapedText(textLine);
                element = eb.createShapedTextRun(shapedText);
                element.setTextMatrix(1.5, 0, 0, 1.5, 50, linePos);
                linePos -= lineSpace;
                writer.writeElement(element);
                System.out.println("Wrote shaped line to page");
            }
        
            // Finish the shaped block of text
            writer.writeElement(eb.createTextEnd());


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

            doc.save(output_path + "unicodewrite.pdf", new SDFDoc.SaveMode[]{SDFDoc.SaveMode.REMOVE_UNUSED, SDFDoc.SaveMode.HEX_STRINGS}, null);
            System.out.println("Done. Result saved in unicodewrite.pdf...");
        } catch (Exception e) {
            e.printStackTrace();
        }

        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"
    "os"
    "bufio"
    "strconv"
    "runtime"
	. "pdftron"
    "golang.org/x/text/encoding/unicode"
    "golang.org/x/text/transform"
)

import  "pdftron/Samples/LicenseKey/GO"

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

// This example illustrates how to create Unicode text and how to embed composite fonts.
// 
// Note: This demo attempts to make use of 'arialuni.ttf' in the '/Samples/TestFiles' 
// directory. Arial Unicode MS is about 24MB in size and used to come together with Windows and 
// MS Office.
// 
// In case you don't have access to Arial Unicode MS you can use another wide coverage
// font, like Google Noto, GNU UniFont, or cyberbit. Many of these are freely available,
// and there is a list maintained at https://en.wikipedia.org/wiki/Unicode_font
// 
// If no specific font file can be loaded, the demo will fall back to system specific font
// substitution routines, and the result will depend on which fonts are available.
//
// Run "go get golang.org/x/text/encoding/unicode" and "go get golang.org/x/text/transform" to install, 
// if these two packages are not presented.
 
func ReadUnicodeTextLinesFromFile(  writer ElementWriter, 
                                    indexedFont Font, 
                                    eb ElementBuilder, 
                                    linePos float64, 
                                    lineSpace float64, 
                                    showNumOfLines bool, 
                                    readLines bool){
    file, err := os.Open(inputPath + "hindi_sample_utf16le.txt")
    if err != nil {
        fmt.Println(err)
    }
    defer file.Close()
    scanner := bufio.NewScanner(transform.NewReader(file, unicode.UTF16(unicode.LittleEndian, unicode.UseBOM).NewDecoder()))
    i := 0
    if(showNumOfLines){
        for scanner.Scan() {
            i++
        }
        fmt.Println("Read in " + strconv.Itoa(i) + " lines of Unicode text from file")
    }else if(readLines){
        for scanner.Scan() {
            shapedText := indexedFont.GetShapedText(scanner.Text())
            element := eb.CreateShapedTextRun(shapedText)
            element.SetTextMatrix(1.5, 0.0, 0.0, 1.5, 50.0, linePos-lineSpace*(float64(i+1)))
            writer.WriteElement(element)
            fmt.Println("Wrote shaped line to page")  
            i++
        }
    }
    if err := scanner.Err(); err != nil {
        fmt.Println(err)
    }
}

func main(){
    PDFNetInitialize(PDFTronLicense.Key)
    
    doc := NewPDFDoc()
    eb := NewElementBuilder()
    writer := NewElementWriter()
    
    // Start a new page ------------------------------------
    page := doc.PageCreate(NewRect(0.0, 0.0, 612.0, 794.0))
    
    writer.Begin(page)    // begin writing to this page
       
    // Embed and subset the font
    fontProgram := inputPath + "ARIALUNI.TTF"
    fnt := FontCreate(doc.GetSDFDoc(), "Helvetica", "")
    if _, err := os.Stat(fontProgram); err == nil{
      // fontProgram exists
      fnt = FontCreateCIDTrueTypeFont(doc.GetSDFDoc(), fontProgram, true, true)
      fmt.Println("Note: using " + fontProgram + " for unshaped unicode text")
    }else if os.IsNotExist(err){
        if runtime.GOOS == "windows"{
            fontProgram = "C:/Windows/Fonts/ARIALUNI.TTF"
            if _, err := os.Stat(fontProgram); err == nil{
              // fontProgram exists
                fnt = FontCreateCIDTrueTypeFont(doc.GetSDFDoc(), fontProgram, true, true)
                fmt.Println("Note: using " + fontProgram + " for unshaped unicode text")
            }else if os.IsNotExist(err){
                fmt.Println("Note: using system font substitution for unshaped unicode text")
            }else{
                fmt.Println(err)
            }
        }
    }else{
        fmt.Println(err)
    }

    element := eb.CreateTextBegin(fnt, 1.0)
    element.SetTextMatrix(10.0, 0.0, 0.0, 10.0, 50.0, 600.0)
    element.GetGState().SetLeading(2)         // Set the spacing between lines
    writer.WriteElement(element)

    // Hello World!
    hello := []uint16{'H','e','l','l','o',' ','W','o','r','l','d','!'}
    fmt.Println(hello)
    writer.WriteElement(eb.CreateUnicodeTextRun(&hello[0], uint(len(hello))))
    writer.WriteElement(eb.CreateTextNewLine())
    
    // Latin
    latin := []uint16{'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 0x45, 0x0046, 0x00C0, 
            0x00C1, 0x00C2, 0x0143, 0x0144, 0x0145, 0x0152, '1', '2' }// etc.
    writer.WriteElement(eb.CreateUnicodeTextRun(&latin[0], uint(len(latin))))
    writer.WriteElement(eb.CreateTextNewLine())

    // Greek
    greek := []uint16{0x039E, 0x039F, 0x03A0, 0x03A1,0x03A3, 0x03A6, 0x03A8, 0x03A9}
    writer.WriteElement(eb.CreateUnicodeTextRun(&greek[0], uint(len(greek))))
    writer.WriteElement(eb.CreateTextNewLine())
    
    // Cyrillic
    cyrillic := []uint16{0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0x0410, 0x0411,
                0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419}
    writer.WriteElement(eb.CreateUnicodeTextRun(&cyrillic[0], uint(len(cyrillic))))
    writer.WriteElement(eb.CreateTextNewLine())
    
    // Hebrew
    hebrew := []uint16{0x05D0, 0x05D1, 0x05D3, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8,
              0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1}
    writer.WriteElement(eb.CreateUnicodeTextRun(&hebrew[0], uint(len(hebrew))))
    writer.WriteElement(eb.CreateTextNewLine())
    
    // Arabic
    arabic := []uint16{0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C,
              0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635}
    writer.WriteElement(eb.CreateUnicodeTextRun(&arabic[0], uint(len(arabic))))
    writer.WriteElement(eb.CreateTextNewLine())
    
    // Thai
    thai := []uint16{0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 
            0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12}
    writer.WriteElement(eb.CreateUnicodeTextRun(&thai[0], uint(len(thai))))
    writer.WriteElement(eb.CreateTextNewLine())
    
    // Hiragana - Japanese 
    hiragana := []uint16{0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049,
                0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, 0x3051, 0x3051, 0x3052}
    writer.WriteElement(eb.CreateUnicodeTextRun(&hiragana[0], uint(len(hiragana))))
    writer.WriteElement(eb.CreateTextNewLine())
    
    // CJK Unified Ideographs 
    cjk_uni := []uint16{0x5841, 0x5842, 0x5843, 0x5844, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849, 
               0x584A, 0x584B, 0x584C, 0x584D, 0x584E, 0x584F, 0x5850, 0x5851, 0x5852}
    writer.WriteElement(eb.CreateUnicodeTextRun(&cjk_uni[0], uint(len(cjk_uni))))
    writer.WriteElement(eb.CreateTextNewLine())
    
    // Simplified Chinese
    chineseSimplified := []uint16{0x4e16, 0x754c, 0x60a8, 0x597d}
    writer.WriteElement(eb.CreateUnicodeTextRun(&chineseSimplified[0], uint(len(chineseSimplified))))
    writer.WriteElement(eb.CreateTextNewLine())

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

    fmt.Println("Now using text shaping logic to place text")

    // Create a font in indexed encoding mode 
    // normally this would mean that we are required to provide glyph indices
    // directly to CreateUnicodeTextRun, but instead, we will use the GetShapedText
    // method to take care of this detail for us.
    indexedFont := FontCreateCIDTrueTypeFont(doc.GetSDFDoc(), inputPath + "NotoSans_with_hindi.ttf", true, true, FontE_Indices)
    element = eb.CreateTextBegin(indexedFont, 10.0)
    writer.WriteElement(element)

    linePos := 350.0
    lineSpace := 20.0

    // Transform unicode text into an abstract collection of glyph indices and positioning info 
    shapedText := indexedFont.GetShapedText("Shaped Hindi Text:")

    // transform the shaped text info into a PDF element and write it to the page
    element = eb.CreateShapedTextRun(shapedText)
    element.SetTextMatrix(1.5, 0.0, 0.0, 1.5, 50.0, linePos)
    writer.WriteElement(element)
    // read in unicode text lines from a file
    ReadUnicodeTextLinesFromFile(writer, indexedFont, eb, linePos, lineSpace, true, false)
    ReadUnicodeTextLinesFromFile(writer, indexedFont, eb, linePos, lineSpace, false, true)
    
    // Finish the block of text
    writer.WriteElement(eb.CreateTextEnd())

    writer.End()    // save changes to the current page
    doc.PagePushBack(page)
    
    doc.Save(outputPath + "unicodewrite.pdf", uint(SDFDocE_remove_unused | SDFDocE_hex_strings))
    fmt.Println("Done. Result saved in unicodewrite.pdf...")
    
    doc.Close()
    PDFNetTerminate()
}
```

{% 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 fs = require('fs')
const process = require('process');
const { PDFNet } = require('@pdftron/pdfnet-node');
const PDFTronLicense = require('../LicenseKey/LicenseKey');

((exports) => {

  exports.runUnicodeWriteTest = () => {

    const main = async () => {
      try {
        // Relative path to the folder containing test files.
        const inputPath = '../TestFiles/';
        const outputPath = '../TestFiles/Output/';

        const doc = await PDFNet.PDFDoc.create();
        doc.initSecurityHandler();

        const eb = await PDFNet.ElementBuilder.create(); // ElementBuilder, used to build new element Objects
        const writer = await PDFNet.ElementWriter.create(); // ElementWriter, used to write elements to the page

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

        await writer.beginOnPage(page);

        let font_program = inputPath + 'ARIALUNI.TTF';

        if (!fs.existsSync(font_program)) {
          font_program = 'C:/Windows/Fonts/ARIALUNI.TTF';
          if (process.platform !== 'win32' || !fs.existsSync(font_program)) {
            font_program = '';
          }
        }

        let fnt;
        if (font_program.length) {
          console.log('Note: using ' + font_program + ' for unshaped unicode text');
          // if we can find a specific wide-coverage font file, then use that directly
          fnt = await PDFNet.Font.createCIDTrueTypeFont(doc, font_program, true, true);
        } else {
          console.log('Note: using system font substitution for unshaped unicode text');
          // if we can't find a specific file, then use system font subsitution 
          // as a fallback, using 'Helvetica' as a hint
          fnt = await PDFNet.Font.createFromName(doc, 'Helvetica', '');
        }

        let element = await eb.createTextBeginWithFont(fnt, 1);
        await element.setTextMatrixEntries(10, 0, 0, 10, 50, 600);
        await (await element.getGState()).setLeading(2);		 // Set the spacing between lines
        await writer.writeElement(element);

        // Hello World!
        const hello = 'Hello World!';
        await writer.writeElement(await eb.createUnicodeTextRun(hello));
        await writer.writeElement(await eb.createTextNewLine());

        // Latin
        const latin = 'aAbBcCdD' + String.fromCharCode(0x45, 0x0046, 0x00C0, 0x00C1, 0x00C2, 0x0143, 0x0144, 0x0145, 0x0152) + '12';
        await writer.writeElement(await eb.createUnicodeTextRun(latin));
        await writer.writeElement(await eb.createTextNewLine());

        // Greek
        const greek = String.fromCharCode(0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A3, 0x03A6, 0x03A8, 0x03A9);
        await writer.writeElement(await eb.createUnicodeTextRun(greek));
        await writer.writeElement(await eb.createTextNewLine());

        // Cyrillic
        const cyrillic = String.fromCharCode(
          0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0x0410, 0x0411,
          0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419);
        await writer.writeElement(await eb.createUnicodeTextRun(cyrillic));
        await writer.writeElement(await eb.createTextNewLine());

        // Hebrew
        const hebrew = String.fromCharCode(
          0x05D0, 0x05D1, 0x05D3, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8,
          0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1);
        await writer.writeElement(await eb.createUnicodeTextRun(hebrew));
        await writer.writeElement(await eb.createTextNewLine());

        // Arabic
        const arabic = String.fromCharCode(
          0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C,
          0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635);
        await writer.writeElement(await eb.createUnicodeTextRun(arabic));
        await writer.writeElement(await eb.createTextNewLine());

        // Thai 
        const thai = String.fromCharCode(
          0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09,
          0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12);
        await writer.writeElement(await eb.createUnicodeTextRun(thai));
        await writer.writeElement(await eb.createTextNewLine());

        // Hiragana - Japanese 
        const hiragana = String.fromCharCode(
          0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049,
          0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, 0x3051, 0x3051, 0x3052);
        await writer.writeElement(await eb.createUnicodeTextRun(hiragana));
        await writer.writeElement(await eb.createTextNewLine());

        // CJK Unified Ideographs
        const cjk_uni = String.fromCharCode(
          0x5841, 0x5842, 0x5843, 0x5844, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849,
          0x584A, 0x584B, 0x584C, 0x584D, 0x584E, 0x584F, 0x5850, 0x5851, 0x5852);
        await writer.writeElement(await eb.createUnicodeTextRun(cjk_uni));
        await writer.writeElement(await eb.createTextNewLine());

        // Simplified Chinese
        const chinese_simplified = String.fromCharCode(0x4e16, 0x754c, 0x60a8, 0x597d);
        await writer.writeElement(await eb.createUnicodeTextRun(chinese_simplified));
        await writer.writeElement(await eb.createTextNewLine());

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

        console.log('Now using text shaping logic to place text');

        // Create a font in indexed encoding mode 
        // normally this would mean that we are required to provide glyph indices
        // directly to CreateUnicodeTextRun, but instead, we will use the GetShapedText
        // method to take care of this detail for us.
        const indexed_font = await PDFNet.Font.createCIDTrueTypeFont(doc, inputPath + 'NotoSans_with_hindi.ttf', true, true, PDFNet.Font.Encoding.e_Indices);
        element = await eb.createTextBeginWithFont(indexed_font, 10);
        await writer.writeElement(element);

        const line_pos = 350.0;
        const line_space = 20.0;

        // Transform unicode text into an abstract collection of glyph indices and positioning info 
        let shaped_text = await indexed_font.getShapedText('Shaped Hindi Text:');

        // transform the shaped text info into a PDF element and write it to the page
        element = await eb.createShapedTextRun(shaped_text);
        await element.setTextMatrixEntries(1.5, 0, 0, 1.5, 50, line_pos);
        await writer.writeElement(element);

        // read in unicode text lines from a file 
        const hindi_text = fs.readFileSync(inputPath + 'hindi_sample_utf16le.txt', 'utf16le').toString().split(/\n/);

        console.log('Read in ' + hindi_text.length + ' lines of Unicode text from file');
        for (let i = 0; i < hindi_text.length; ++i) {
          shaped_text = await indexed_font.getShapedText(hindi_text[i]);
          element = await eb.createShapedTextRun(shaped_text);
          await element.setTextMatrixEntries(1.5, 0, 0, 1.5, 50, line_pos - line_space * (i + 1));
          await writer.writeElement(element);
          console.log('Wrote shaped line to page');
        }

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

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

        await doc.save(outputPath + 'unicodewrite.pdf', PDFNet.SDFDoc.SaveOptions.e_remove_unused | PDFNet.SDFDoc.SaveOptions.e_hex_strings);

        console.log('Done. Result saved in unicodewrite.pdf...');
      } catch (err) {
        console.log(err);
      }
    };
    PDFNet.runWithCleanup(main, PDFTronLicense.Key).catch(function (error) { console.log('Error: ' + JSON.stringify(error)); }).then(function () { return PDFNet.shutdown(); });
  };
  exports.runUnicodeWriteTest();
})(exports);
// eslint-disable-next-line spaced-comment
//# sourceURL=UnicodeWriteTest.js
```

{% 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");

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

//---------------------------------------------------------------------------------------
// This example illustrates how to create Unicode text and how to embed composite fonts.
// 
// Note: This demo assumes that 'arialuni.ttf' is present in '/Samples/TestFiles' 
// directory. Arial Unicode MS is about 24MB in size and it comes together with Windows and 
// MS Office.
//---------------------------------------------------------------------------------------
function main()
{
    global $input_path, $output_path, $LicenseKey;

	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();
	$writer = new ElementWriter();	

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

	// Embed and subset the font
	$font_program = $input_path."ARIALUNI.TTF";
	if (!file_exists($font_program)) {
		if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
			$font_program = "C:/Windows/Fonts/ARIALUNI.TTF";
		}
	}
	$fnt = NULL;
	try {
		$fnt = Font::CreateCIDTrueTypeFont($doc->GetSDFDoc(), $font_program, true, true);
	}
	catch(Exception $e){

	}
	if($fnt)
	{
		echo(nl2br("Note: using " . $font_program . " for unshaped unicode text\n"));
	}
	else
	{
		echo(nl2br("Note: using system font substitution for unshaped unicode text\n"));
		$fnt = Font::Create($doc->GetSDFDoc(), "Helvetica", "");		
	}

	$element = $builder->CreateTextBegin($fnt, 1.0);
	$element->SetTextMatrix(10.0, 0.0, 0.0, 10.0, 50.0, 600.0);
	$element->GetGState()->SetLeading(2);		 // Set the spacing between lines
	$writer->WriteElement($element);

	// Hello World!
	$hello = array( 'H','e','l','l','o',' ','W','o','r','l','d','!');
	$writer->WriteElement($builder->CreateUnicodeTextRun($hello, count($hello)));
	$writer->WriteElement($builder->CreateTextNewLine());

	// Latin
	$latin = array(   
		'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 0x45, 0x0046, 0x00C0, 
		0x00C1, 0x00C2, 0x0143, 0x0144, 0x0145, 0x0152, '1', '2' // etc.
	);
	$writer->WriteElement($builder->CreateUnicodeTextRun($latin, count($latin)));
	$writer->WriteElement($builder->CreateTextNewLine());

	// Greek
	$greek = array(   
		0x039E, 0x039F, 0x03A0, 0x03A1,0x03A3, 0x03A6, 0x03A8, 0x03A9  // etc.
	);
	$writer->WriteElement($builder->CreateUnicodeTextRun($greek, count($greek)));
	$writer->WriteElement($builder->CreateTextNewLine());

	// Cyrillic
	$cyrillic = array(   
		0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0x0410, 0x0411,
		0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419 // etc.
	);
	$writer->WriteElement($builder->CreateUnicodeTextRun($cyrillic, count($cyrillic)));
	$writer->WriteElement($builder->CreateTextNewLine());

	// Hebrew
	$hebrew = array(
		0x05D0, 0x05D1, 0x05D3, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 
		0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1 // etc. 
	);
	$writer->WriteElement($builder->CreateUnicodeTextRun($hebrew, count($hebrew)));
	$writer->WriteElement($builder->CreateTextNewLine());

	// Arabic
	$arabic = array(
		0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 
		0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635 // etc. 
	);
	$writer->WriteElement($builder->CreateUnicodeTextRun($arabic, count($arabic)));
	$writer->WriteElement($builder->CreateTextNewLine());

	// Thai 
	$thai = array(
		0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 
		0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12 // etc. 
	);
	$writer->WriteElement($builder->CreateUnicodeTextRun($thai, count($thai)));
	$writer->WriteElement($builder->CreateTextNewLine());

	// Hiragana - Japanese 
	$hiragana = array(
		0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049, 
		0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, 0x3051, 0x3051, 0x3052 // etc. 
	);
	$writer->WriteElement($builder->CreateUnicodeTextRun($hiragana, count($hiragana)));
	$writer->WriteElement($builder->CreateTextNewLine());

	// CJK Unified Ideographs
	$cjk_uni = array(
		0x5841, 0x5842, 0x5843, 0x5844, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849, 
		0x584A, 0x584B, 0x584C, 0x584D, 0x584E, 0x584F, 0x5850, 0x5851, 0x5852 // etc. 
	);
	$writer->WriteElement($builder->CreateUnicodeTextRun($cjk_uni, count($cjk_uni)));
	$writer->WriteElement($builder->CreateTextNewLine());

	// Simplified Chinese
	$chinese_simplified = array(
		0x4e16, 0x754c, 0x60a8, 0x597d
	);
	$writer->WriteElement($builder->CreateUnicodeTextRun($chinese_simplified, count($chinese_simplified)));
	$writer->WriteElement($builder->CreateTextNewLine());

	echo("Now using text shaping logic to place text\n");

	// Create a font in indexed encoding mode 
	// normally this would mean that we are required to provide glyph indices
	// directly to CreateUnicodeTextRun, but instead, we will use the GetShapedText
	// method to take care of this detail for us.
	$indexed_font = Font::CreateCIDTrueTypeFont($doc->GetSDFDoc(), $input_path . "NotoSans_with_hindi.ttf", true, true, Font::e_Indices);
	$element = $builder->CreateTextBegin($indexed_font, 10.0);
	$writer->WriteElement($element);

	$line_pos = 350.0;
	$line_space = 20.0;

	// Transform unicode text into an abstract collection of glyph indices and positioning info 
	$shaped_text = $indexed_font->GetShapedText("Shaped Hindi Text:");

	// transform the shaped text info into a PDF element and write it to the page
	$element = $builder->CreateShapedTextRun($shaped_text);
	$element->SetTextMatrix(1.5, 0.0, 0.0, 1.5, 50.0, $line_pos);
	$writer->WriteElement($element);

	# read in unicode text lines from a file 
	$f = fopen($input_path . "hindi_sample_utf16le.txt", "r");
	$i = 0;
	while($hindi_text = fgets($f)){$i++;}
	fclose($f);
	echo("Read in " . $i . " lines of Unicode text from file\n");

	$f = fopen($input_path . "hindi_sample_utf16le.txt", "r");
	$i = 0;
	while($hindi_text = fgets($f)){
		if ($i == 0)
			$tmp1 = substr($hindi_text,0,-1);
		else if($i == 1)
			$tmp1 = substr($hindi_text,1,-2); // remove the first and the last 2 characters so encoding to UTF-8 looks correct in PHP 
		$tmp = iconv($in_charset = "UTF-16LE", $out_charset="UTF-8", $tmp1);
		$shaped_text = $indexed_font->GetShapedText($tmp);
		$element = $builder->CreateShapedTextRun($shaped_text);
		$element->SetTextMatrix(1.5, 0.0, 0.0, 1.5, 50.0, $line_pos-$line_space*($i+1));
		$writer->WriteElement($element);
		echo("Wrote shaped line to page\n");
		$i++;

	}
	fclose($f);

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

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

	$doc->Save($output_path."unicodewrite.pdf", SDFDoc::e_remove_unused | SDFDoc::e_hex_strings);
	PDFNet::Terminate();
	echo "Done. Result saved in unicodewrite.pdf...\n";
}

main();
?>
```

{% 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 *
import os, io

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

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

# This example illustrates how to create Unicode text and how to embed composite fonts.
# 
# Note: This demo assumes that 'arialuni.ttf' is present in '/Samples/TestFiles' 
# directory. Arial Unicode MS is about 24MB in size and it comes together with Windows and 
# MS Office.
# 
# For more information about Arial Unicode MS, please consult the following Microsoft Knowledge 
# Base Article: WD2002: General Information About the Arial Unicode MS Font
#    http://support.microsoft.com/support/kb/articles/q287/2/47.asp
# 
# For more information consult: 
#    http://office.microsoft.com/search/results.aspx?Scope=DC&Query=font&CTT=6&Origin=EC010331121033
#    http://www.microsoft.com/downloads/details.aspx?FamilyID=1F0303AE-F055-41DA-A086-A65F22CB5593
# 
# In case you don't have access to Arial Unicode MS you can use cyberbit.ttf 
# (http://ftp.netscape.com/pub/communicator/extras/fonts/windows/) instead.
def main():
    PDFNet.Initialize(LicenseKey)
    
    doc = PDFDoc()
    eb = ElementBuilder()
    writer = ElementWriter()
    
    # Start a new page ------------------------------------
    page = doc.PageCreate(Rect(0, 0, 612, 794))
    
    writer.Begin(page)    # begin writing to this page
       
    # Embed and subset the font
    font_program = input_path + "ARIALUNI.TTF"
    if not os.path.isfile(font_program):
        if sys.platform == 'win32':
            font_program = "C:/Windows/Fonts/ARIALUNI.TTF"
    fnt = None
    try:
        fnt = Font.CreateCIDTrueTypeFont(doc.GetSDFDoc(), font_program, True, True)
    except:
        pass

    if fnt:
        print("Note: using " + font_program + " for unshaped unicode text")
    else:
        print("Note: using system font substitution for unshaped unicode text")
        fnt = Font.Create(doc.GetSDFDoc(), "Helvetica", "")

    element = eb.CreateTextBegin(fnt, 1)
    element.SetTextMatrix(10, 0, 0, 10, 50, 600)
    element.GetGState().SetLeading(2)         # Set the spacing between lines
    writer.WriteElement(element)

    # Hello World!
    hello = ['H','e','l','l','o',' ','W','o','r','l','d','!']
    writer.WriteElement(eb.CreateUnicodeTextRun(hello, len(hello)))
    writer.WriteElement(eb.CreateTextNewLine())
    
    # Latin
    latin = ['a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 0x45, 0x0046, 0x00C0, 
            0x00C1, 0x00C2, 0x0143, 0x0144, 0x0145, 0x0152, '1', '2' ]# etc.
    writer.WriteElement(eb.CreateUnicodeTextRun((latin), len(latin)))
    writer.WriteElement(eb.CreateTextNewLine())
    
    # Greek
    greek = [0x039E, 0x039F, 0x03A0, 0x03A1,0x03A3, 0x03A6, 0x03A8, 0x03A9]
    writer.WriteElement(eb.CreateUnicodeTextRun((greek), len(greek)))
    writer.WriteElement(eb.CreateTextNewLine())
    
    # Cyrillic
    cyrillic = [0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0x0410, 0x0411,
                0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419]
    writer.WriteElement(eb.CreateUnicodeTextRun((cyrillic), len(cyrillic)))
    writer.WriteElement(eb.CreateTextNewLine())
    
    # Hebrew
    hebrew = [0x05D0, 0x05D1, 0x05D3, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8,
              0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1]
    writer.WriteElement(eb.CreateUnicodeTextRun((hebrew), len(hebrew)))
    writer.WriteElement(eb.CreateTextNewLine())
    
    # Arabic
    arabic = [0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C,
              0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635]
    writer.WriteElement(eb.CreateUnicodeTextRun((arabic), len(arabic)))
    writer.WriteElement(eb.CreateTextNewLine())
    
    # Thai
    thai = [0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 
            0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12]
    writer.WriteElement(eb.CreateUnicodeTextRun((thai), len(thai)))
    writer.WriteElement(eb.CreateTextNewLine())
    
    # Hiragana - Japanese 
    hiragana = [0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049,
                0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, 0x3051, 0x3051, 0x3052]
    writer.WriteElement(eb.CreateUnicodeTextRun(hiragana, len(hiragana)))
    writer.WriteElement(eb.CreateTextNewLine())
    
    # CJK Unified Ideographs 
    cjk_uni = [0x5841, 0x5842, 0x5843, 0x5844, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849, 
               0x584A, 0x584B, 0x584C, 0x584D, 0x584E, 0x584F, 0x5850, 0x5851, 0x5852]
    writer.WriteElement(eb.CreateUnicodeTextRun((cjk_uni), len(cjk_uni)))
    writer.WriteElement(eb.CreateTextNewLine())
    
    # Simplified Chinese
    chinese_simplified = [0x4e16, 0x754c, 0x60a8, 0x597d]
    writer.WriteElement(eb.CreateUnicodeTextRun((chinese_simplified), len(chinese_simplified)))
    writer.WriteElement(eb.CreateTextNewLine())

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

    print("Now using text shaping logic to place text")

    # Create a font in indexed encoding mode 
    # normally this would mean that we are required to provide glyph indices
    # directly to CreateUnicodeTextRun, but instead, we will use the GetShapedText
    # method to take care of this detail for us.
    indexed_font = Font.CreateCIDTrueTypeFont(doc.GetSDFDoc(), input_path + "NotoSans_with_hindi.ttf", True, True, Font.e_Indices)
    element = eb.CreateTextBegin(indexed_font, 10)
    writer.WriteElement(element)

    line_pos = 350.0
    line_space = 20.0

    # Transform unicode text into an abstract collection of glyph indices and positioning info 
    shaped_text = indexed_font.GetShapedText("Shaped Hindi Text:")

    # transform the shaped text info into a PDF element and write it to the page
    element = eb.CreateShapedTextRun(shaped_text);
    element.SetTextMatrix(1.5, 0, 0, 1.5, 50, line_pos);
    writer.WriteElement(element);

    # read in unicode text lines from a file 
    with io.open(input_path + "hindi_sample_utf16le.txt", "r", encoding='utf-16-le') as f:
        hindi_text = f.readlines()
        print("Read in " + str(len(hindi_text)) + " lines of Unicode text from file")
        for i in range(len(hindi_text)):
            shaped_text = indexed_font.GetShapedText(hindi_text[i][:-1])
            element = eb.CreateShapedTextRun(shaped_text)
            element.SetTextMatrix(1.5, 0, 0, 1.5, 50, line_pos-line_space*(i+1))
            writer.WriteElement(element)
            print("Wrote shaped line to page")

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

    writer.End()    # save changes to the current page
    doc.PagePushBack(page)
    
    doc.Save(output_path + "unicodewrite.pdf", SDFDoc.e_remove_unused | SDFDoc.e_hex_strings)
    print("Done. Result saved in unicodewrite.pdf...")
    
    doc.Close()
    PDFNet.Terminate()

if __name__ == '__main__':
    main()
```

{% 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/"

# This example illustrates how to create Unicode text and how to embed composite fonts.
# 
# Note: This demo assumes that 'arialuni.ttf' is present in '/Samples/TestFiles' 
# directory. Arial Unicode MS is about 24MB in size and it comes together with Windows and 
# MS Office.
# 
# For more information about Arial Unicode MS, please consult the following Microsoft Knowledge 
# Base Article: WD2002: General Information About the Arial Unicode MS Font
#    http://support.microsoft.com/support/kb/articles/q287/2/47.asp
# 
# For more information consult: 
#    http://office.microsoft.com/search/results.aspx?Scope=DC&Query=font&CTT=6&Origin=EC010331121033
#    http://www.microsoft.com/downloads/details.aspx?FamilyID=1F0303AE-F055-41DA-A086-A65F22CB5593
# 
# In case you don't have access to Arial Unicode MS you can use cyberbit.ttf 
# (http://ftp.netscape.com/pub/communicator/extras/fonts/windows/) instead.
def main()
	PDFNet.Initialize(PDFTronLicense.Key)
    
	doc = PDFDoc.new
	eb = ElementBuilder.new
	writer = ElementWriter.new
	# Start a new page ------------------------------------
	page = doc.PageCreate(Rect.new(0, 0, 612, 794))
	writer.Begin(page)    # begin writing to this page

	# Embed and subset the font
	font_program = $input_path + "ARIALUNI.TTF"
	if not File.file?(font_program)
		if ENV['OS'] == "Windows_NT"
			font_program = "C:/Windows/Fonts/ARIALUNI.TTF"
			puts "Note: Using ARIALUNI.TTF from C:/Windows/Fonts directory."
		end
	end
	begin
		fnt = Font.CreateCIDTrueTypeFont(doc.GetSDFDoc(), font_program, true, true)
	rescue
	end

	if not fnt.nil?
		puts "Note: using " + font_program + " for unshaped unicode text"
	else
		puts "Note: using system font substitution for unshaped unicode text"
		fnt = Font.Create(doc.GetSDFDoc(), "Helvetica", "")
	end

	element = eb.CreateTextBegin(fnt, 1)
	element.SetTextMatrix(10, 0, 0, 10, 50, 600)
	element.GetGState.SetLeading(2)         # Set the spacing between lines
	writer.WriteElement(element)

	# Hello World!
	hello = ['H','e','l','l','o',' ','W','o','r','l','d','!']
	writer.WriteElement(eb.CreateUnicodeTextRun(hello, hello.length))
	writer.WriteElement(eb.CreateTextNewLine)

	# Latin
	latin = ['a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 0x45, 0x0046, 0x00C0, 
		0x00C1, 0x00C2, 0x0143, 0x0144, 0x0145, 0x0152, '1', '2' ]# etc.
	writer.WriteElement(eb.CreateUnicodeTextRun(latin, latin.length))
	writer.WriteElement(eb.CreateTextNewLine)
    
	# Greek
	greek = [0x039E, 0x039F, 0x03A0, 0x03A1,0x03A3, 0x03A6, 0x03A8, 0x03A9]
	writer.WriteElement(eb.CreateUnicodeTextRun(greek, greek.length))
	writer.WriteElement(eb.CreateTextNewLine)
    
	# Cyrillic
	cyrillic = [0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0x0410, 0x0411,
		0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419]
	writer.WriteElement(eb.CreateUnicodeTextRun(cyrillic, cyrillic.length))
	writer.WriteElement(eb.CreateTextNewLine)
    
	# Hebrew
	hebrew = [0x05D0, 0x05D1, 0x05D3, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8,
		0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1]
	writer.WriteElement(eb.CreateUnicodeTextRun(hebrew, hebrew.length))
	writer.WriteElement(eb.CreateTextNewLine)
    
	# Arabic
	arabic = [0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C,
		0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635]
	writer.WriteElement(eb.CreateUnicodeTextRun(arabic, arabic.length))
	writer.WriteElement(eb.CreateTextNewLine)
    
	# Thai
	thai = [0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 
		0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12]
	writer.WriteElement(eb.CreateUnicodeTextRun(thai, thai.length))
	writer.WriteElement(eb.CreateTextNewLine)
    
	# Hiragana - Japanese 
	hiragana = [0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049,
		0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, 0x3051, 0x3051, 0x3052]
	writer.WriteElement(eb.CreateUnicodeTextRun(hiragana, hiragana.length))
	writer.WriteElement(eb.CreateTextNewLine)
    
	# CJK Unified Ideographs 
	cjk_uni = [0x5841, 0x5842, 0x5843, 0x5844, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849, 
		0x584A, 0x584B, 0x584C, 0x584D, 0x584E, 0x584F, 0x5850, 0x5851, 0x5852]
	writer.WriteElement(eb.CreateUnicodeTextRun(cjk_uni, cjk_uni.length))
	writer.WriteElement(eb.CreateTextNewLine)
    
	# Simplified Chinese
	chinese_simplified = [0x4e16, 0x754c, 0x60a8, 0x597d]
	writer.WriteElement(eb.CreateUnicodeTextRun(chinese_simplified, chinese_simplified.length))
	writer.WriteElement(eb.CreateTextNewLine)

	puts "Now using text shaping logic to place text"

	# Create a font in indexed encoding mode 
	# normally this would mean that we are required to provide glyph indices
	# directly to CreateUnicodeTextRun, but instead, we will use the GetShapedText
	# method to take care of this detail for us.
	indexed_font = Font.CreateCIDTrueTypeFont(doc.GetSDFDoc(), $input_path + "NotoSans_with_hindi.ttf", true, true, Font::E_Indices)
	element = eb.CreateTextBegin(indexed_font, 10)
	writer.WriteElement(element)

	line_pos = 350.0
	line_space = 20.0

	# Transform unicode text into an abstract collection of glyph indices and positioning info 
	shaped_text = indexed_font.GetShapedText("Shaped Hindi Text:")

	# transform the shaped text info into a PDF element and write it to the page
	element = eb.CreateShapedTextRun(shaped_text)
	element.SetTextMatrix(1.5, 0, 0, 1.5, 50, line_pos)
	writer.WriteElement(element)

	# read in unicode text lines from a file 
	line_num=0
	File.open($input_path +"hindi_sample_utf16le.txt", "rb:UTF-16LE").each do |line|
		line_num += 1
	end
	puts "Read in %d lines of Unicode text from file" % line_num

	i=0
	File.open($input_path + "hindi_sample_utf16le.txt", "rb:UTF-16LE") do |f|
	f.each_line do |line|
		begin
			shaped_text = indexed_font.GetShapedText(line[0..-2].encode('utf-8'))
			element = eb.CreateShapedTextRun(shaped_text)
			element.SetTextMatrix(1.5, 0, 0, 1.5, 50, line_pos-line_space*(i+1))
			writer.WriteElement(element)
			puts "Wrote shaped line to page"
			i+=1
		rescue
		end
	end
	end

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

	# Finish the block of text
	writer.WriteElement(eb.CreateTextEnd)
    
	writer.End    # save changes to the current page
	doc.PagePushBack(page)
    
	doc.Save($output_path + "unicodewrite.pdf", SDFDoc::E_remove_unused | SDFDoc::E_hex_strings)
	puts "Done. Result saved in unicodewrite.pdf..."
    
	doc.Close
	PDFNet.Terminate
end

main()
```

{% endcode %}
{% endtab %}

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

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

Imports System
Imports System.IO
Imports System.Text
Imports pdftron
Imports pdftron.Common
Imports pdftron.Filters
Imports pdftron.SDF
Imports pdftron.PDF

' This example illustrates how to create Unicode text and how to embed composite fonts.
Module UnicodeWriteTestVB
	Dim pdfNetLoader As PDFNetLoader
	Sub New()
		pdfNetLoader = pdftron.PDFNetLoader.Instance()
	End Sub

	' Note: This demo assumes that 'arialuni.ttf' is present in '/Samples/TestFiles' 
	' directory. Arial Unicode MS is about 24MB in size and it comes together with Windows and 
	' MS Office.
	' 
	' For more information about Arial Unicode MS, please consult the following Microsoft Knowledge 
	' Base Article: WD2002: General Information About the Arial Unicode MS Font
	'  http://support.microsoft.com/support/kb/articles/q287/2/47.asp
	'
	' For more information consult: 
	'    http://office.microsoft.com/search/results.aspx?Scope=DC&Query=font&CTT=6&Origin=EC010331121033
	'    http://www.microsoft.com/downloads/details.aspx?FamilyID=1F0303AE-F055-41DA-A086-A65F22CB5593
	' 
	' In case you don't have access to Arial Unicode MS you can use cyberbit.ttf 
	' (ftp://ftp.netscape.com/pub/communicator/extras/fonts/windows/) instead.
	'
	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
					Using writer As ElementWriter = New ElementWriter

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

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

						Dim fnt As Font
						Try

							' Full font embedding
							Dim myfont As System.Drawing.Font = New System.Drawing.Font("Arial Unicode MS", 12)
							fnt = Font.CreateCIDTrueTypeFont(doc.GetSDFDoc(), myfont, True, True)

							' To embed the font file directly use:
							' fnt = Font.CreateCIDTrueTypeFont(doc, input_path + "arialuni.ttf", true, true)

							' Example of font substitution
							' fnt = Font.CreateCIDTrueTypeFont(doc, input_path + "arialuni.ttf", false)
						Catch e As PDFNetException
						End Try

						If fnt Is Nothing Then
							Try
								fnt = Font.CreateCIDTrueTypeFont(doc, input_path & "ARIALUNI.TTF", True, True)
							Catch e As PDFNetException
							End Try
						End If

						If fnt Is Nothing Then
							Try
								fnt = Font.CreateCIDTrueTypeFont(doc, "C:/Windows/Fonts/ARIALUNI.TTF", True, True)
							Catch e As PDFNetException
							End Try
						End If

						If fnt Is Nothing Then
							Console.WriteLine("Note: using system font substitution for unshaped unicode text")
							fnt = Font.Create(doc, "Helvetica", "")
						Else
							Console.WriteLine("Note: using Arial Unicode for unshaped unicode text")
						End If

						Dim element As Element = eb.CreateTextBegin(fnt, 1)
						element.SetTextMatrix(10, 0, 0, 10, 50, 600)
						element.GetGState().SetLeading(2)			' Set the spacing between lines
						writer.WriteElement(element)

						' Hello World!!!
						Dim hello As String = "Hello World!"
						writer.WriteElement(eb.CreateUnicodeTextRun(hello))
						writer.WriteElement(eb.CreateTextNewLine())

						' Latin
						Dim latin As Char() = { _
							"a"c, "A"c, "b"c, "B"c, "c"c, "C"c, "d"c, "D"c, ChrW(&H45), ChrW(&H46), ChrW(&HC0), _
							ChrW(&HC1), ChrW(&HC2), ChrW(&H143), ChrW(&H144), ChrW(&H145), ChrW(&H152), "1"c, "2"c _
							}			 ' etc.

						writer.WriteElement(eb.CreateUnicodeTextRun(New String(latin)))
						writer.WriteElement(eb.CreateTextNewLine())

						' Greek
						Dim greek As Char() = { _
							ChrW(&H39E), ChrW(&H39F), ChrW(&H3A0), ChrW(&H3A1), ChrW(&H3A3), ChrW(&H3A6), ChrW(&H3A8), ChrW(&H3A9) _
							}			 ' etc.

						writer.WriteElement(eb.CreateUnicodeTextRun(New String(greek)))
						writer.WriteElement(eb.CreateTextNewLine())

						' Cyrillic
						Dim cyrillic As Char() = { _
							ChrW(&H409), ChrW(&H40A), ChrW(&H40B), ChrW(&H40C), ChrW(&H40E), ChrW(&H40F), ChrW(&H410), ChrW(&H411), _
							ChrW(&H412), ChrW(&H413), ChrW(&H414), ChrW(&H415), ChrW(&H416), ChrW(&H417), ChrW(&H418), ChrW(&H419) _
							}			 ' etc.

						writer.WriteElement(eb.CreateUnicodeTextRun(New String(cyrillic)))
						writer.WriteElement(eb.CreateTextNewLine())

						' Hebrew
						Dim hebrew As Char() = { _
							ChrW(&H5D0), ChrW(&H5D1), ChrW(&H5D3), ChrW(&H5D3), ChrW(&H5D4), ChrW(&H5D5), ChrW(&H5D6), ChrW(&H5D7), ChrW(&H5D8), _
							ChrW(&H5D9), ChrW(&H5DA), ChrW(&H5DB), ChrW(&H5DC), ChrW(&H5DD), ChrW(&H5DE), ChrW(&H5DF), ChrW(&H5E0), ChrW(&H5E1) _
							}			 ' etc. 

						writer.WriteElement(eb.CreateUnicodeTextRun(New String(hebrew)))
						writer.WriteElement(eb.CreateTextNewLine())

						' Arabic
						Dim arabic As Char() = { _
							ChrW(&H624), ChrW(&H625), ChrW(&H626), ChrW(&H627), ChrW(&H628), ChrW(&H629), ChrW(&H62A), ChrW(&H62B), ChrW(&H62C), _
							ChrW(&H62D), ChrW(&H62E), ChrW(&H62F), ChrW(&H630), ChrW(&H631), ChrW(&H632), ChrW(&H633), ChrW(&H634), ChrW(&H635) _
							}			 ' etc. 

						writer.WriteElement(eb.CreateUnicodeTextRun(New String(arabic)))
						writer.WriteElement(eb.CreateTextNewLine())

						' Thai 
						Dim thai As Char() = { _
							ChrW(&HE01), ChrW(&HE02), ChrW(&HE03), ChrW(&HE04), ChrW(&HE05), ChrW(&HE06), ChrW(&HE07), ChrW(&HE08), ChrW(&HE09), _
							ChrW(&HE0A), ChrW(&HE0B), ChrW(&HE0C), ChrW(&HE0D), ChrW(&HE0E), ChrW(&HE0F), ChrW(&HE10), ChrW(&HE11), ChrW(&HE12) _
							}			 ' etc. 

						writer.WriteElement(eb.CreateUnicodeTextRun(New String(thai)))
						writer.WriteElement(eb.CreateTextNewLine())

						' Hiragana - Japanese 
						Dim hiragana As Char() = { _
							ChrW(&H3041), ChrW(&H3042), ChrW(&H3043), ChrW(&H3044), ChrW(&H3045), ChrW(&H3046), ChrW(&H3047), ChrW(&H3048), ChrW(&H3049), _
							ChrW(&H304A), ChrW(&H304B), ChrW(&H304C), ChrW(&H304D), ChrW(&H304E), ChrW(&H304F), ChrW(&H3051), ChrW(&H3051), ChrW(&H3052) _
							}			 ' etc. 

						writer.WriteElement(eb.CreateUnicodeTextRun(New String(hiragana)))
						writer.WriteElement(eb.CreateTextNewLine())

						' CJK Unified Ideographs
						Dim cjk_uni As Char() = { _
							ChrW(&H5841), ChrW(&H5842), ChrW(&H5843), ChrW(&H5844), ChrW(&H5845), ChrW(&H5846), ChrW(&H5847), ChrW(&H5848), ChrW(&H5849), _
							ChrW(&H584A), ChrW(&H584B), ChrW(&H584C), ChrW(&H584D), ChrW(&H584E), ChrW(&H584F), ChrW(&H5850), ChrW(&H5851), ChrW(&H5852) _
							}			 ' etc. 

						writer.WriteElement(eb.CreateUnicodeTextRun(New String(cjk_uni)))
						writer.WriteElement(eb.CreateTextNewLine())

						Dim chinese_simplified As Char() = {ChrW(&H4e16), ChrW(&H754c), ChrW(&H60a8),ChrW(&H597D)}
						writer.WriteElement(eb.CreateUnicodeTextRun(New String(chinese_simplified)))
							writer.WriteElement(eb.CreateTextNewLine())
	
						' Finish the block of text
						writer.WriteElement(eb.CreateTextEnd())
						Console.WriteLine("Now using text shaping logic to place text")

						Dim indexedFont As Font = Font.CreateCIDTrueTypeFont(doc, input_path & "NotoSans_with_hindi.ttf", True, True, Font.Encoding.e_Indices)
						element = eb.CreateTextBegin(indexedFont, 10.0)
						writer.WriteElement(element)
						Dim linePos As Double = 350.0
						Dim lineSpace As Double = 20.0
						Dim shapedText As ShapedText = indexedFont.GetShapedText("Shaped Hindi Text:")
						element = eb.CreateShapedTextRun(shapedText)
						element.SetTextMatrix(1.5, 0, 0, 1.5, 50, linePos)
						linePos -= lineSpace
						writer.WriteElement(element)
						Dim hindiTextLines As String() = File.ReadAllLines(input_path & "hindi_sample_utf16le.txt", Encoding.UTF8)

						Console.WriteLine("Read in " & hindiTextLines.Length & " lines of Unicode text from file")
						For Each textLine As String In hindiTextLines
							shapedText = indexedFont.GetShapedText(textLine)
							element = eb.CreateShapedTextRun(shapedText)
							element.SetTextMatrix(1.5, 0, 0, 1.5, 50, linePos)
							linePos -= lineSpace
							writer.WriteElement(element)
							Console.WriteLine("Wrote shaped line to page")
						Next
						writer.WriteElement(eb.CreateTextEnd())
						writer.End()			  ' save changes to the current page
						doc.PagePushBack(page)

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

		Catch ex As PDFNetException

			Console.WriteLine(ex.Message)
			Console.WriteLine()

		Catch ex As Exception

			MsgBox(ex.Message)

		End Try
		PDFNet.Terminate()
	End Sub

End Module
```

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