Create Unicode Text, Embed CID in PDFs - Java Sample Code

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.

1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6import com.pdftron.pdf.*;
7import com.pdftron.sdf.SDFDoc;
8import java.util.List;
9import java.nio.file.Files;
10import java.nio.file.Paths;
11import java.nio.charset.StandardCharsets;
12
13/**
14 * This example illustrates how to create Unicode text and how to embed composite fonts.
15 * <p>
16 * Note: This demo attempts to make use of 'arialuni.ttf' in the '/Samples/TestFiles'
17 * directory. Arial Unicode MS is about 24MB in size and used to come together with Windows and
18 * MS Office.
19 * <p>
20 * In case you don't have access to Arial Unicode MS you can use another wide coverage
21 * font, like Google Noto, GNU UniFont, or cyberbit. Many of these are freely available,
22 * and there is a list maintained at https://en.wikipedia.org/wiki/Unicode_font
23 * <p>
24 * If no specific font file can be loaded, the demo will fall back to system specific font
25 * substitution routines, and the result will depend on which fonts are available.
26 *
27 */
28public class UnicodeWriteTest {
29 public static void main(String[] args) {
30 PDFNet.initialize(PDFTronLicense.Key());
31
32 // Relative path to the folder containing test files.
33 String input_path = "../../TestFiles/";
34 String output_path = "../../TestFiles/Output/";
35
36 try (PDFDoc doc = new PDFDoc()) {
37 ElementBuilder eb = new ElementBuilder();
38 ElementWriter writer = new ElementWriter();
39
40 // Start a new page ------------------------------------
41 Page page = doc.pageCreate(new Rect(0, 0, 612, 794));
42
43 writer.begin(page); // begin writing to this page
44
45 String fontLocation = input_path + "ARIALUNI.TTF";
46
47 Font fnt = null;
48 try {
49 // Embed and subset the font
50 fnt = Font.createCIDTrueTypeFont(doc, fontLocation, true, true);
51 } catch (Exception e) {
52 fontLocation = "C:/Windows/Fonts/ARIALUNI.TTF";
53 try {
54 fnt = Font.createCIDTrueTypeFont(doc, fontLocation, true, true);
55 }
56 catch (Exception e2) {
57 fontLocation = null;
58 }
59 }
60
61 if(fnt != null) {
62 System.out.println("Note: using " + fontLocation + " for unshaped unicode text");
63 }
64 else {
65 System.out.println("Note: using system font substitution for unshaped unicode text");
66 fnt = Font.create(doc, "Helvetica", "");
67 }
68
69 Element element = eb.createTextBegin(fnt, 1);
70 element.setTextMatrix(10, 0, 0, 10, 50, 600);
71 element.getGState().setLeading(2); // Set the spacing between lines
72 writer.writeElement(element);
73
74 // Hello World!
75 char hello[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'};
76 writer.writeElement(eb.createUnicodeTextRun(new String(hello)));
77 writer.writeElement(eb.createTextNewLine());
78
79 // Latin
80 char latin[] = {
81 'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 0x45, 0x0046, 0x00C0,
82 0x00C1, 0x00C2, 0x0143, 0x0144, 0x0145, 0x0152, '1', '2' // etc.
83 };
84 writer.writeElement(eb.createUnicodeTextRun(new String(latin)));
85 writer.writeElement(eb.createTextNewLine());
86
87 // Greek
88 char greek[] = {
89 0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A3, 0x03A6, 0x03A8, 0x03A9 // etc.
90 };
91 writer.writeElement(eb.createUnicodeTextRun(new String(greek)));
92 writer.writeElement(eb.createTextNewLine());
93
94 // Cyrillic
95 char cyrilic[] = {
96 0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0x0410, 0x0411,
97 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419 // etc.
98 };
99 writer.writeElement(eb.createUnicodeTextRun(new String(cyrilic)));
100 writer.writeElement(eb.createTextNewLine());
101
102 // Hebrew
103 char hebrew[] = {
104 0x05D0, 0x05D1, 0x05D3, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8,
105 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1 // etc.
106 };
107 writer.writeElement(eb.createUnicodeTextRun(new String(hebrew)));
108 writer.writeElement(eb.createTextNewLine());
109
110 // Arabic
111 char arabic[] = {
112 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C,
113 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635 // etc.
114 };
115 writer.writeElement(eb.createUnicodeTextRun(new String(arabic)));
116 writer.writeElement(eb.createTextNewLine());
117
118 // Thai
119 char thai[] = {
120 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09,
121 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12 // etc.
122 };
123 writer.writeElement(eb.createUnicodeTextRun(new String(thai)));
124 writer.writeElement(eb.createTextNewLine());
125
126 // Hiragana - Japanese
127 char hiragana[] = {
128 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049,
129 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, 0x3051, 0x3051, 0x3052 // etc.
130 };
131 writer.writeElement(eb.createUnicodeTextRun(new String(hiragana)));
132 writer.writeElement(eb.createTextNewLine());
133
134 // CJK Unified Ideographs
135 char cjk_uni[] = {
136 0x5841, 0x5842, 0x5843, 0x5844, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849,
137 0x584A, 0x584B, 0x584C, 0x584D, 0x584E, 0x584F, 0x5850, 0x5851, 0x5852 // etc.
138 };
139 writer.writeElement(eb.createUnicodeTextRun(new String(cjk_uni)));
140 writer.writeElement(eb.createTextNewLine());
141
142 // Simplified Chinese
143 char chinese_simplified[] = {
144 0x4e16, 0x754c, 0x60a8, 0x597d
145 };
146 writer.writeElement(eb.createUnicodeTextRun(new String(chinese_simplified)));
147 writer.writeElement(eb.createTextNewLine());
148
149 // Finish the block of text
150 writer.writeElement(eb.createTextEnd());
151
152 System.out.println("Now using text shaping logic to place text");
153
154 // Create a font in indexed encoding mode
155 // normally this would mean that we are required to provide glyph indices
156 // directly to CreateUnicodeTextRun, but instead, we will use the GetShapedText
157 // method to take care of this detail for us.
158 Font indexedFont = Font.createCIDTrueTypeFont(doc, input_path + "NotoSans_with_hindi.ttf", true, true, Font.e_Indices);
159 element = eb.createTextBegin(indexedFont, 10.0);
160 writer.writeElement(element);
161
162 double linePos = 350.0;
163 double lineSpace = 20.0;
164
165 // Transform unicode text into an abstract collection of glyph indices and positioning info
166 ShapedText shapedText = indexedFont.getShapedText("Shaped Hindi Text:");
167
168 // transform the shaped text info into a PDF element and write it to the page
169 element = eb.createShapedTextRun(shapedText);
170 element.setTextMatrix(1.5, 0, 0, 1.5, 50, linePos);
171 linePos -= lineSpace;
172 writer.writeElement(element);
173
174 // read in unicode text lines from a file
175 List<String> hindiTextLines = Files.readAllLines(Paths.get(input_path + "hindi_sample_utf16le.txt"), StandardCharsets.UTF_16LE);
176
177 System.out.println("Read in " + hindiTextLines.size() + " lines of Unicode text from file");
178 for (String textLine : hindiTextLines)
179 {
180 shapedText = indexedFont.getShapedText(textLine);
181 element = eb.createShapedTextRun(shapedText);
182 element.setTextMatrix(1.5, 0, 0, 1.5, 50, linePos);
183 linePos -= lineSpace;
184 writer.writeElement(element);
185 System.out.println("Wrote shaped line to page");
186 }
187
188 // Finish the shaped block of text
189 writer.writeElement(eb.createTextEnd());
190
191
192 writer.end(); // save changes to the current page
193 doc.pagePushBack(page);
194
195 doc.save(output_path + "unicodewrite.pdf", new SDFDoc.SaveMode[]{SDFDoc.SaveMode.REMOVE_UNUSED, SDFDoc.SaveMode.HEX_STRINGS}, null);
196 System.out.println("Done. Result saved in unicodewrite.pdf...");
197 } catch (Exception e) {
198 e.printStackTrace();
199 }
200
201 PDFNet.terminate();
202 }
203
204}

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales