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}
1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6import PDFNet
7import Foundation
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 * (https://web.archive.org/web/20060504053941/http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q287/2/47.asp&NoWebContent=1)
20 *
21 * For more information consult:
22 * http://office.microsoft.com/search/results.aspx?Scope=DC&Query=font&CTT=6&Origin=EC010331121033
23 * http://www.microsoft.com/downloads/details.aspx?FamilyID=1F0303AE-F055-41DA-A086-A65F22CB5593
24 *
25 * In case you don't have access to Arial Unicode MS you can use cyberbit.ttf
26 * (http://ftp.netscape.com/pub/communicator/extras/fonts/windows/) instead.
27 */
28
29func runUnicodeWriteTest() -> Int {
30 return autoreleasepool {
31 var ret = 0
32
33
34 do {
35 try PTPDFNet.catchException {
36
37 // Relative path to the folder containing test files.
38 let input_path: String = Bundle.main.resourcePath ?? "" + ("/")
39
40 let doc: PTPDFDoc = PTPDFDoc()
41
42 let eb: PTElementBuilder = PTElementBuilder()
43 let writer: PTElementWriter = PTElementWriter()
44
45 // Start a new page ------------------------------------
46 let rect = PTPDFRect(x1: 0, y1: 0, x2: 612, y2: 794)
47 let page: PTPage = doc.pageCreate(rect)
48
49 writer.writerBegin(with: page, placement: e_ptoverlay, page_coord_sys: true, compress: true, resources: nil) // begin writing to this page
50 var fnt = PTFont()
51 do {
52 try PTPDFNet.catchException {
53 // Embed and subset the font
54 fnt = PTFont.createCIDTrueTypeFont(doc.getSDFDoc(), font_path: Bundle.main.path(forResource: "ARIALUNI", ofType: "ttf"), embed: true, subset: true, encoding: e_ptIdentityH, ttc_font_index: 0)
55 }
56 } catch {
57 print("Note: 'arialuni.ttf' font file was not found in \(input_path) directory.")
58 ret = 1
59 }
60
61 let element: PTElement = eb.createTextBegin(with: fnt, font_sz: 1)
62 let m = PTMatrix2D(a: 10, b: 0, c: 0, d: 10, h: 50, v: 600)
63 element.setTextMatrix(with: m)
64 element.getGState().setLeading(2) // Set the spacing between lines
65 writer.write(element)
66
67 // Hello World!
68 let helloRaw: [Character] = [
69 "H", "e", "l", "l", "o", " ", "W", "o", "r", "l", "d", "!"
70 ]
71 var hello: [UInt16] = String(helloRaw).utf16.map{ UInt16($0) }
72 writer.write(eb.createUnicodeTextRun(&hello, text_data_sz: UInt32(hello.count)))
73 writer.write(eb.createTextNewLine())
74
75 // Latin
76 let latinRaw: [Character] = [
77 "a", "A", "b", "B", "c", "C", "d", "D", "\u{45}", "\u{0046}", "\u{00c0}", "\u{00c1}", "\u{00c2}", "\u{0143}", "\u{0144}", "\u{0145}", "\u{0152}", "1", "2" // etc.
78 ]
79 var latin: [UInt16] = String(latinRaw).utf16.map{ UInt16($0) }
80 writer.write(eb.createUnicodeTextRun(&latin, text_data_sz: UInt32(latin.count)))
81 writer.write(eb.createTextNewLine())
82
83 // Greek
84 var greek: [UInt16] = [
85 0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A3, 0x03A6, 0x03A8, 0x03A9 // etc.
86 ]
87 writer.write(eb.createUnicodeTextRun(&greek, text_data_sz: UInt32(greek.count)))
88 writer.write(eb.createTextNewLine())
89
90 // Cyrillic
91 var cyrillic: [UInt16] = [
92 0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0x0410, 0x0411,
93 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419 // etc.
94 ]
95 writer.write(eb.createUnicodeTextRun(&cyrillic, text_data_sz: UInt32(cyrillic.count)))
96 writer.write(eb.createTextNewLine())
97
98 // Hebrew
99 var hebrew: [UInt16] = [
100 0x05D0, 0x05D1, 0x05D3, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8,
101 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1 // etc.
102 ]
103 writer.write(eb.createUnicodeTextRun(&hebrew, text_data_sz: UInt32(hebrew.count)))
104 writer.write(eb.createTextNewLine())
105
106 // Arabic
107 var arabic: [UInt16] = [
108 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C,
109 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635 // etc.
110 ]
111 writer.write(eb.createUnicodeTextRun(&arabic, text_data_sz: UInt32(arabic.count)))
112 writer.write(eb.createTextNewLine())
113
114 // Thai
115 var thai: [UInt16] = [
116 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09,
117 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12 // etc.
118 ]
119 writer.write(eb.createUnicodeTextRun(&thai, text_data_sz: UInt32(thai.count)))
120 writer.write(eb.createTextNewLine())
121
122 // Hiragana - Japanese
123 var hiragana: [UInt16] = [
124 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049,
125 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, 0x3051, 0x3051, 0x3052 // etc.
126 ]
127 writer.write(eb.createUnicodeTextRun(&hiragana, text_data_sz: UInt32(hiragana.count)))
128 writer.write(eb.createTextNewLine())
129
130 // CJK Unified Ideographs
131 var cjk_uni: [UInt16] = [
132 0x5841, 0x5842, 0x5843, 0x5844, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849,
133 0x584A, 0x584B, 0x584C, 0x584D, 0x584E, 0x584F, 0x5850, 0x5851, 0x5852 // etc.
134 ]
135 writer.write(eb.createUnicodeTextRun(&cjk_uni, text_data_sz: UInt32(cjk_uni.count)))
136 writer.write(eb.createTextNewLine())
137
138 // Simplified Chinese
139 var chinese_simplified: [UInt16] = [
140 0x4e16, 0x754c, 0x60a8, 0x597d
141 ]
142 writer.write(eb.createUnicodeTextRun(&chinese_simplified, text_data_sz: UInt32(chinese_simplified.count)))
143 writer.write(eb.createTextNewLine())
144
145 // Finish the block of text
146 writer.write(eb.createTextEnd())
147
148 writer.end() // save changes to the current page
149 doc.pagePushBack(page)
150 print(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
151 doc.save(toFile: URL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]).appendingPathComponent("unicodewrite.pdf").path, flags: e_ptremove_unused.rawValue | e_pthex_strings.rawValue)
152 print("Done. Result saved in unicodewrite.pdf...")
153 }
154 } catch let e as NSError {
155 print("\(e)")
156 ret = 1
157 }
158
159 return ret
160 }
161}
Did you find this helpful?
Trial setup questions?
Ask experts on DiscordNeed other help?
Contact SupportPricing or product questions?
Contact Sales