UnicodeWrite

Sample Obj-C code for using Apryse SDK to create Unicode text and embed composite fonts in PDF files. Learn more about our iOS 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
6#import <OBJC/PDFNetOBJC.h>
7#import <Foundation/Foundation.h>
8
9/**
10 * This example illustrates how to create Unicode text and how to embed composite fonts.
11 *
12 * Note: This demo assumes that 'arialuni.ttf' is present in '/Samples/TestFiles'
13 * directory. Arial Unicode MS is about 24MB in size and it comes together with Windows and
14 * MS Office.
15 *
16 * For more information about Arial Unicode MS, please consult the following Microsoft Knowledge
17 * Base Article: WD2002: General Information About the Arial Unicode MS Font
18 * http://support.microsoft.com/support/kb/articles/q287/2/47.asp
19 *
20 * For more information consult:
21 * http://office.microsoft.com/search/results.aspx?Scope=DC&Query=font&CTT=6&Origin=EC010331121033
22 * http://www.microsoft.com/downloads/details.aspx?FamilyID=1F0303AE-F055-41DA-A086-A65F22CB5593
23 *
24 * In case you don't have access to Arial Unicode MS you can use cyberbit.ttf
25 * (http://ftp.netscape.com/pub/communicator/extras/fonts/windows/) instead.
26 */
27
28int main(int argc, char *argv[])
29{
30 @autoreleasepool {
31 int ret = 0;
32 [PTPDFNet Initialize: 0];
33
34 // Relative path to the folder containing test files.
35 NSString *input_path = @"../../TestFiles/";
36 NSString *output_path = @"../../TestFiles/Output/";
37
38
39 PTPDFDoc *doc = [[PTPDFDoc alloc] init];
40
41 PTElementBuilder *eb = [[PTElementBuilder alloc] init];
42 PTElementWriter *writer = [[PTElementWriter alloc] init];
43
44 // Start a new page ------------------------------------
45 PTPDFRect * rect = [[PTPDFRect alloc] init];
46 [rect Set: 0 y1: 0 x2: 612 y2: 794];
47 PTPage *page = [doc PageCreate: rect];
48
49 [writer WriterBeginWithPage: page placement: e_ptoverlay page_coord_sys: YES compress: YES resources: NULL]; // begin writing to this page
50
51 PTFont *fnt = [[PTFont alloc] init];
52 @try
53 {
54 // Embed and subset the font
55 fnt = [PTFont CreateCIDTrueTypeFont: [doc GetSDFDoc] font_path: @"../../TestFiles/ARIALUNI.ttf" embed: true subset: true encoding:e_ptIdentityH ttc_font_index:0];
56 }
57 @catch(NSException *e)
58 {
59 }
60 if(fnt != nil) {
61 NSLog(@"Note: using %@ for unshaped unicode text", @"../../TestFiles/ARIALUNI.ttf");
62 }
63 else {
64 NSLog(@"Note: using system font substitution for unshaped unicode text");
65 fnt = [PTFont CreateFromName: [doc GetSDFDoc] name: @"Helvetica" char_set:@""];
66 }
67 PTElement *element = [eb CreateTextBeginWithFont: fnt font_sz: 1];
68 PTMatrix2D *m = [[PTMatrix2D alloc] initWithA: 10 b: 0 c: 0 d: 10 h: 50 v: 600];
69 [element SetTextMatrixWithMatrix2D: m];
70 [[element GetGState] SetLeading: 2]; // Set the spacing between lines
71 [writer WriteElement: element];
72
73 // Hello World!
74 unsigned short hello[] = {'H','e','l','l','o',' ','W','o','r','l','d','!'};
75 [writer WriteElement: [eb CreateUnicodeTextRun: (unsigned short*)&hello text_data_sz: sizeof(hello)/sizeof(unsigned short)]];
76 [writer WriteElement: [eb CreateTextNewLine]];
77
78 // Latin
79 unsigned short latin[] = {'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 0x45, 0x0046, 0x00C0,
80 0x00C1, 0x00C2, 0x0143, 0x0144, 0x0145, 0x0152, '1', '2' // etc.
81 };
82 [writer WriteElement: [eb CreateUnicodeTextRun: (unsigned short*)&latin text_data_sz: sizeof(latin)/sizeof(unsigned short)]];
83 [writer WriteElement: [eb CreateTextNewLine]];
84
85 // Greek
86 unsigned short greek[] = {
87 0x039E, 0x039F, 0x03A0, 0x03A1,0x03A3, 0x03A6, 0x03A8, 0x03A9 // etc.
88 };
89 [writer WriteElement: [eb CreateUnicodeTextRun: (unsigned short*)&greek text_data_sz: sizeof(greek)/sizeof(unsigned short)]];
90 [writer WriteElement: [eb CreateTextNewLine]];
91
92 // Cyrillic
93 unsigned short cyrillic[] = {
94 0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0x0410, 0x0411,
95 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419 // etc.
96 };
97 [writer WriteElement: [eb CreateUnicodeTextRun: (unsigned short*)&cyrillic text_data_sz: sizeof(cyrillic)/sizeof(unsigned short)]];
98 [writer WriteElement: [eb CreateTextNewLine]];
99
100 // Hebrew
101 unsigned short hebrew[] = {
102 0x05D0, 0x05D1, 0x05D3, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8,
103 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1 // etc.
104 };
105 [writer WriteElement: [eb CreateUnicodeTextRun: (unsigned short*)&hebrew text_data_sz: sizeof(hebrew)/sizeof(unsigned short)]];
106 [writer WriteElement: [eb CreateTextNewLine]];
107
108 // Arabic
109 unsigned short arabic[] = {
110 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C,
111 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635 // etc.
112 };
113 [writer WriteElement: [eb CreateUnicodeTextRun: (unsigned short*)&arabic text_data_sz: sizeof(arabic)/sizeof(unsigned short)]];
114 [writer WriteElement: [eb CreateTextNewLine]];
115
116 // Thai
117 unsigned short thai[] = {
118 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09,
119 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12 // etc.
120 };
121 [writer WriteElement: [eb CreateUnicodeTextRun: (unsigned short*)&thai text_data_sz: sizeof(thai)/sizeof(unsigned short)]];
122 [writer WriteElement: [eb CreateTextNewLine]];
123
124 // Hiragana - Japanese
125 unsigned short hiragana[] = {
126 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049,
127 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, 0x3051, 0x3051, 0x3052 // etc.
128 };
129 [writer WriteElement: [eb CreateUnicodeTextRun: (unsigned short*)&hiragana text_data_sz: sizeof(hiragana)/sizeof(unsigned short)]];
130 [writer WriteElement: [eb CreateTextNewLine]];
131
132 // CJK Unified Ideographs
133 unsigned short cjk_uni[] = {
134 0x5841, 0x5842, 0x5843, 0x5844, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849,
135 0x584A, 0x584B, 0x584C, 0x584D, 0x584E, 0x584F, 0x5850, 0x5851, 0x5852 // etc.
136 };
137 [writer WriteElement: [eb CreateUnicodeTextRun: (unsigned short*)&cjk_uni text_data_sz: sizeof(cjk_uni)/sizeof(unsigned short)]];
138 [writer WriteElement: [eb CreateTextNewLine]];
139
140 // Simplified Chinese
141 unsigned short chinese_simplified[] = {
142 0x4e16, 0x754c, 0x60a8, 0x597d
143 };
144 [writer WriteElement: [eb CreateUnicodeTextRun: (unsigned short*)&chinese_simplified text_data_sz: sizeof(chinese_simplified)/sizeof(unsigned short)]];
145 [writer WriteElement: [eb CreateTextNewLine]];
146
147 // Finish the block of text
148 [writer WriteElement: [eb CreateTextEnd]];
149
150 NSLog(@"Now using text shaping logic to place text");
151
152 // Create a font in indexed encoding mode
153 // normally this would mean that we are required to provide glyph indices
154 // directly to CreateUnicodeTextRun, but instead, we will use the GetShapedText
155 // method to take care of this detail for us.
156 PTFont* indexedFont = [PTFont CreateCIDTrueTypeFont: [doc GetSDFDoc] font_path: @"../../TestFiles/NotoSans_with_hindi.ttf" embed: true subset: true encoding:e_ptIdentityH ttc_font_index:0];
157 element = [eb CreateTextBeginWithFont: indexedFont font_sz: 10.0];
158 [writer WriteElement: element];
159
160 double linePos = 350.0;
161 double lineSpace = 20.0;
162
163 // Transform unicode text into an abstract collection of glyph indices and positioning info
164 PTShapedText* shapedText = [indexedFont GetShapedText: @"Shaped Hindi Text:"];
165
166 // transform the shaped text info into a PDF element and write it to the page
167 element = [eb CreateShapedTextRun : shapedText];
168 PTMatrix2D *m1 = [[PTMatrix2D alloc] initWithA: 1.5 b: 0 c: 0 d: 1.5 h: 50 v: linePos];
169 [element SetTextMatrixWithMatrix2D: m1];
170 linePos -= lineSpace;
171 [writer WriteElement: element];
172
173 // read in unicode text lines from a file
174
175
176 NSString *filepath = [[NSBundle mainBundle] pathForResource:@"../../TestFiles/hindi_sample_utf16le" ofType:@"txt"];
177 NSError *error;
178 NSString *fileContents = [NSString stringWithContentsOfFile:filepath encoding:NSUTF16StringEncoding error:&error];
179
180 if (error)
181 NSLog(@"Error reading file: %@", error.localizedDescription);
182
183 NSArray *listArray = [fileContents componentsSeparatedByString:@"\n"];
184
185 NSLog(@"Read in %ld lines of Unicode text from file", [listArray count]);
186 for (NSString *textLine in listArray)
187 {
188 shapedText = [indexedFont GetShapedText: textLine];
189 element = [eb CreateShapedTextRun: shapedText];
190 PTMatrix2D *m1 = [[PTMatrix2D alloc] initWithA: 1.5 b: 0 c: 0 d: 1.5 h: 50 v: linePos];
191 [element SetTextMatrixWithMatrix2D: m1];
192 NSLog(@"Wrote shaped line to page");
193 }
194
195 // Finish the shaped block of text
196 [writer WriteElement: [eb CreateTextEnd]];
197
198 [writer End]; // save changes to the current page
199 [doc PagePushBack: page];
200
201 [doc SaveToFile: @"../../TestFiles/Output/unicodewrite.pdf" flags: e_ptremove_unused | e_pthex_strings];
202 NSLog(@"Done. Result saved in unicodewrite.pdf...");
203 [PTPDFNet Terminate: 0];
204 return ret;
205 }
206}

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales
Create Unicode Text, Embed CID Fonts in PDF in Obj-C | Apryse documentation