Scheduled Maintenance
-
February 10, 2026, from 8:00 AM to 9:00 AM PST. Account-related operations might be temporarily unavailable.

UnicodeWrite

Sample Java code for using Apryse SDK to create Unicode text and embed composite fonts in PDF files. Learn more about our Android SDK.

1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6package com.pdftron.android.pdfnetsdksamples.samples;
7
8import com.pdftron.android.pdfnetsdksamples.OutputListener;
9import com.pdftron.android.pdfnetsdksamples.PDFNetSample;
10import com.pdftron.android.pdfnetsdksamples.R;
11import com.pdftron.android.pdfnetsdksamples.util.Utils;
12import com.pdftron.pdf.Element;
13import com.pdftron.pdf.ElementBuilder;
14import com.pdftron.pdf.ElementWriter;
15import com.pdftron.pdf.Font;
16import com.pdftron.pdf.PDFDoc;
17import com.pdftron.pdf.Page;
18import com.pdftron.pdf.Rect;
19import com.pdftron.pdf.ShapedText;
20import com.pdftron.sdf.SDFDoc;
21
22import java.nio.charset.StandardCharsets;
23import java.nio.file.Files;
24import java.nio.file.Paths;
25import java.util.ArrayList;
26import java.util.List;
27
28/**
29 * This example illustrates how to create Unicode text and how to embed
30 * composite fonts.
31 * <p>
32 * Note: This sample assumes that your device contains some of the regular
33 * fonts distributed with the Android SDK. Since not all fonts are shipped
34 * depending on the manufacturer, you may need to change the sample code
35 * or add a font that covers the text you want to use.
36 * <p>
37 * In case some of the text used in this sample does not work properly
38 * (squared or dot characters appear instead of the real characters) you can
39 * search for the correct fonts in the Android SDK or download and use the
40 * Cyberbit font, available here:
41 * http://ftp.netscape.com/pub/communicator/extras/fonts/windows/
42 * <p>
43 * Add the font file to the assets\TestFiles folder and change the code
44 * accordingly.
45 */
46public class UnicodeWriteTest extends PDFNetSample {
47
48 private static OutputListener mOutputListener;
49
50 private static ArrayList<String> mFileList = new ArrayList<>();
51
52 public UnicodeWriteTest() {
53 setTitle(R.string.sample_unicodewrite_title);
54 setDescription(R.string.sample_unicodewrite_description);
55 }
56
57 @Override
58 public void run(OutputListener outputListener) {
59 super.run(outputListener);
60 mOutputListener = outputListener;
61 mFileList.clear();
62 printHeader(outputListener);
63
64 try (PDFDoc doc = new PDFDoc()) {
65 ElementBuilder eb = new ElementBuilder();
66 ElementWriter writer = new ElementWriter();
67
68 // Start a new page ------------------------------------
69 Page page = doc.pageCreate(new Rect(0, 0, 612, 794));
70
71 writer.begin(page); // begin writing to this page
72
73 String fontLocation = Utils.getAssetTempFile(INPUT_PATH + "ARIALUNI.TTF").getAbsolutePath();
74
75 Font fnt = null;
76 try {
77 // Embed and subset the font
78 fnt = Font.createCIDTrueTypeFont(doc, fontLocation, true, true);
79 } catch (Exception e) {
80 fontLocation = "C:/Windows/Fonts/ARIALUNI.TTF";
81 try {
82 fnt = Font.createCIDTrueTypeFont(doc, fontLocation, true, true);
83 }
84 catch (Exception e2) {
85 fontLocation = null;
86 }
87 }
88
89 if(fnt != null) {
90 mOutputListener.println("Note: using " + fontLocation + " for unshaped unicode text");
91 }
92 else {
93 mOutputListener.println("Note: using system font substitution for unshaped unicode text");
94 fnt = Font.create(doc, "Helvetica", "");
95 }
96
97 Element element = eb.createTextBegin(fnt, 1);
98 element.setTextMatrix(10, 0, 0, 10, 50, 600);
99 element.getGState().setLeading(2); // Set the spacing between lines
100 writer.writeElement(element);
101
102 // Hello World!
103 char hello[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'};
104 writer.writeElement(eb.createUnicodeTextRun(new String(hello)));
105 writer.writeElement(eb.createTextNewLine());
106
107 // Latin
108 char latin[] = {
109 'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 0x45, 0x0046, 0x00C0,
110 0x00C1, 0x00C2, 0x0143, 0x0144, 0x0145, 0x0152, '1', '2' // etc.
111 };
112 writer.writeElement(eb.createUnicodeTextRun(new String(latin)));
113 writer.writeElement(eb.createTextNewLine());
114
115 // Greek
116 char greek[] = {
117 0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A3, 0x03A6, 0x03A8, 0x03A9 // etc.
118 };
119 writer.writeElement(eb.createUnicodeTextRun(new String(greek)));
120 writer.writeElement(eb.createTextNewLine());
121
122 // Cyrillic
123 char cyrilic[] = {
124 0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0x0410, 0x0411,
125 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419 // etc.
126 };
127 writer.writeElement(eb.createUnicodeTextRun(new String(cyrilic)));
128 writer.writeElement(eb.createTextNewLine());
129
130 // Hebrew
131 char hebrew[] = {
132 0x05D0, 0x05D1, 0x05D3, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8,
133 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1 // etc.
134 };
135 writer.writeElement(eb.createUnicodeTextRun(new String(hebrew)));
136 writer.writeElement(eb.createTextNewLine());
137
138 // Arabic
139 char arabic[] = {
140 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C,
141 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635 // etc.
142 };
143 writer.writeElement(eb.createUnicodeTextRun(new String(arabic)));
144 writer.writeElement(eb.createTextNewLine());
145
146 // Thai
147 char thai[] = {
148 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09,
149 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12 // etc.
150 };
151 writer.writeElement(eb.createUnicodeTextRun(new String(thai)));
152 writer.writeElement(eb.createTextNewLine());
153
154 // Hiragana - Japanese
155 char hiragana[] = {
156 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049,
157 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, 0x3051, 0x3051, 0x3052 // etc.
158 };
159 writer.writeElement(eb.createUnicodeTextRun(new String(hiragana)));
160 writer.writeElement(eb.createTextNewLine());
161
162 // CJK Unified Ideographs
163 char cjk_uni[] = {
164 0x5841, 0x5842, 0x5843, 0x5844, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849,
165 0x584A, 0x584B, 0x584C, 0x584D, 0x584E, 0x584F, 0x5850, 0x5851, 0x5852 // etc.
166 };
167 writer.writeElement(eb.createUnicodeTextRun(new String(cjk_uni)));
168 writer.writeElement(eb.createTextNewLine());
169
170 // Simplified Chinese
171 char chinese_simplified[] = {
172 0x4e16, 0x754c, 0x60a8, 0x597d
173 };
174 writer.writeElement(eb.createUnicodeTextRun(new String(chinese_simplified)));
175 writer.writeElement(eb.createTextNewLine());
176
177 // Finish the block of text
178 writer.writeElement(eb.createTextEnd());
179
180 mOutputListener.println("Now using text shaping logic to place text");
181
182 // Create a font in indexed encoding mode
183 // normally this would mean that we are required to provide glyph indices
184 // directly to CreateUnicodeTextRun, but instead, we will use the GetShapedText
185 // method to take care of this detail for us.
186 Font indexedFont = Font.createCIDTrueTypeFont(doc, Utils.getAssetTempFile(INPUT_PATH + "NotoSans_with_hindi.ttf").getAbsolutePath(), true, true, Font.e_Indices);
187 element = eb.createTextBegin(indexedFont, 10.0);
188 writer.writeElement(element);
189
190 double linePos = 350.0;
191 double lineSpace = 20.0;
192
193 // Transform unicode text into an abstract collection of glyph indices and positioning info
194 ShapedText shapedText = indexedFont.getShapedText("Shaped Hindi Text:");
195
196 // transform the shaped text info into a PDF element and write it to the page
197 element = eb.createShapedTextRun(shapedText);
198 element.setTextMatrix(1.5, 0, 0, 1.5, 50, linePos);
199 linePos -= lineSpace;
200 writer.writeElement(element);
201
202 // read in unicode text lines from a file
203 List<String> hindiTextLines = Files.readAllLines(Paths.get(Utils.getAssetTempFile(INPUT_PATH + "hindi_sample_utf16le.txt").getAbsolutePath()), StandardCharsets.UTF_16LE);
204
205 mOutputListener.println("Read in " + hindiTextLines.size() + " lines of Unicode text from file");
206 for (String textLine : hindiTextLines)
207 {
208 shapedText = indexedFont.getShapedText(textLine);
209 element = eb.createShapedTextRun(shapedText);
210 element.setTextMatrix(1.5, 0, 0, 1.5, 50, linePos);
211 linePos -= lineSpace;
212 writer.writeElement(element);
213 mOutputListener.println("Wrote shaped line to page");
214 }
215
216 // Finish the shaped block of text
217 writer.writeElement(eb.createTextEnd());
218
219 writer.end(); // save changes to the current page
220 doc.pagePushBack(page);
221
222 doc.save(Utils.createExternalFile("unicodewrite.pdf", mFileList).getAbsolutePath(), new SDFDoc.SaveMode[]{SDFDoc.SaveMode.REMOVE_UNUSED, SDFDoc.SaveMode.HEX_STRINGS}, null);
223 mOutputListener.println("Done. Result saved in unicodewrite.pdf...");
224 } catch (Exception e) {
225 mOutputListener.printError(e.getStackTrace());
226 }
227
228 for (String file : mFileList) {
229 addToFileList(file);
230 }
231 printFooter(outputListener);
232 }
233
234}

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales