Create Unicode Text, Embed CID in PDFs - Go 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-2021 by PDFTron Systems Inc. All Rights Reserved.
3// Consult LICENSE.txt regarding license information.
4//---------------------------------------------------------------------------------------
5
6package main
7import (
8 "fmt"
9 "os"
10 "bufio"
11 "strconv"
12 "runtime"
13 . "pdftron"
14 "golang.org/x/text/encoding/unicode"
15 "golang.org/x/text/transform"
16)
17
18import "pdftron/Samples/LicenseKey/GO"
19
20// Relative path to the folder containing the test files.
21var inputPath = "../../TestFiles/"
22var outputPath = "../../TestFiles/Output/"
23
24// This example illustrates how to create Unicode text and how to embed composite fonts.
25//
26// Note: This demo attempts to make use of 'arialuni.ttf' in the '/Samples/TestFiles'
27// directory. Arial Unicode MS is about 24MB in size and used to come together with Windows and
28// MS Office.
29//
30// In case you don't have access to Arial Unicode MS you can use another wide coverage
31// font, like Google Noto, GNU UniFont, or cyberbit. Many of these are freely available,
32// and there is a list maintained at https://en.wikipedia.org/wiki/Unicode_font
33//
34// If no specific font file can be loaded, the demo will fall back to system specific font
35// substitution routines, and the result will depend on which fonts are available.
36//
37// Run "go get golang.org/x/text/encoding/unicode" and "go get golang.org/x/text/transform" to install,
38// if these two packages are not presented.
39
40func ReadUnicodeTextLinesFromFile( writer ElementWriter,
41 indexedFont Font,
42 eb ElementBuilder,
43 linePos float64,
44 lineSpace float64,
45 showNumOfLines bool,
46 readLines bool){
47 file, err := os.Open(inputPath + "hindi_sample_utf16le.txt")
48 if err != nil {
49 fmt.Println(err)
50 }
51 defer file.Close()
52 scanner := bufio.NewScanner(transform.NewReader(file, unicode.UTF16(unicode.LittleEndian, unicode.UseBOM).NewDecoder()))
53 i := 0
54 if(showNumOfLines){
55 for scanner.Scan() {
56 i++
57 }
58 fmt.Println("Read in " + strconv.Itoa(i) + " lines of Unicode text from file")
59 }else if(readLines){
60 for scanner.Scan() {
61 shapedText := indexedFont.GetShapedText(scanner.Text())
62 element := eb.CreateShapedTextRun(shapedText)
63 element.SetTextMatrix(1.5, 0.0, 0.0, 1.5, 50.0, linePos-lineSpace*(float64(i+1)))
64 writer.WriteElement(element)
65 fmt.Println("Wrote shaped line to page")
66 i++
67 }
68 }
69 if err := scanner.Err(); err != nil {
70 fmt.Println(err)
71 }
72}
73
74func main(){
75 PDFNetInitialize(PDFTronLicense.Key)
76
77 doc := NewPDFDoc()
78 eb := NewElementBuilder()
79 writer := NewElementWriter()
80
81 // Start a new page ------------------------------------
82 page := doc.PageCreate(NewRect(0.0, 0.0, 612.0, 794.0))
83
84 writer.Begin(page) // begin writing to this page
85
86 // Embed and subset the font
87 fontProgram := inputPath + "ARIALUNI.TTF"
88 fnt := FontCreate(doc.GetSDFDoc(), "Helvetica", "")
89 if _, err := os.Stat(fontProgram); err == nil{
90 // fontProgram exists
91 fnt = FontCreateCIDTrueTypeFont(doc.GetSDFDoc(), fontProgram, true, true)
92 fmt.Println("Note: using " + fontProgram + " for unshaped unicode text")
93 }else if os.IsNotExist(err){
94 if runtime.GOOS == "windows"{
95 fontProgram = "C:/Windows/Fonts/ARIALUNI.TTF"
96 if _, err := os.Stat(fontProgram); err == nil{
97 // fontProgram exists
98 fnt = FontCreateCIDTrueTypeFont(doc.GetSDFDoc(), fontProgram, true, true)
99 fmt.Println("Note: using " + fontProgram + " for unshaped unicode text")
100 }else if os.IsNotExist(err){
101 fmt.Println("Note: using system font substitution for unshaped unicode text")
102 }else{
103 fmt.Println(err)
104 }
105 }
106 }else{
107 fmt.Println(err)
108 }
109
110 element := eb.CreateTextBegin(fnt, 1.0)
111 element.SetTextMatrix(10.0, 0.0, 0.0, 10.0, 50.0, 600.0)
112 element.GetGState().SetLeading(2) // Set the spacing between lines
113 writer.WriteElement(element)
114
115 // Hello World!
116 hello := []uint16{'H','e','l','l','o',' ','W','o','r','l','d','!'}
117 fmt.Println(hello)
118 writer.WriteElement(eb.CreateUnicodeTextRun(&hello[0], uint(len(hello))))
119 writer.WriteElement(eb.CreateTextNewLine())
120
121 // Latin
122 latin := []uint16{'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 0x45, 0x0046, 0x00C0,
123 0x00C1, 0x00C2, 0x0143, 0x0144, 0x0145, 0x0152, '1', '2' }// etc.
124 writer.WriteElement(eb.CreateUnicodeTextRun(&latin[0], uint(len(latin))))
125 writer.WriteElement(eb.CreateTextNewLine())
126
127 // Greek
128 greek := []uint16{0x039E, 0x039F, 0x03A0, 0x03A1,0x03A3, 0x03A6, 0x03A8, 0x03A9}
129 writer.WriteElement(eb.CreateUnicodeTextRun(&greek[0], uint(len(greek))))
130 writer.WriteElement(eb.CreateTextNewLine())
131
132 // Cyrillic
133 cyrillic := []uint16{0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0x0410, 0x0411,
134 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419}
135 writer.WriteElement(eb.CreateUnicodeTextRun(&cyrillic[0], uint(len(cyrillic))))
136 writer.WriteElement(eb.CreateTextNewLine())
137
138 // Hebrew
139 hebrew := []uint16{0x05D0, 0x05D1, 0x05D3, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8,
140 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1}
141 writer.WriteElement(eb.CreateUnicodeTextRun(&hebrew[0], uint(len(hebrew))))
142 writer.WriteElement(eb.CreateTextNewLine())
143
144 // Arabic
145 arabic := []uint16{0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C,
146 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635}
147 writer.WriteElement(eb.CreateUnicodeTextRun(&arabic[0], uint(len(arabic))))
148 writer.WriteElement(eb.CreateTextNewLine())
149
150 // Thai
151 thai := []uint16{0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09,
152 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12}
153 writer.WriteElement(eb.CreateUnicodeTextRun(&thai[0], uint(len(thai))))
154 writer.WriteElement(eb.CreateTextNewLine())
155
156 // Hiragana - Japanese
157 hiragana := []uint16{0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, 0x3048, 0x3049,
158 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, 0x3051, 0x3051, 0x3052}
159 writer.WriteElement(eb.CreateUnicodeTextRun(&hiragana[0], uint(len(hiragana))))
160 writer.WriteElement(eb.CreateTextNewLine())
161
162 // CJK Unified Ideographs
163 cjk_uni := []uint16{0x5841, 0x5842, 0x5843, 0x5844, 0x5845, 0x5846, 0x5847, 0x5848, 0x5849,
164 0x584A, 0x584B, 0x584C, 0x584D, 0x584E, 0x584F, 0x5850, 0x5851, 0x5852}
165 writer.WriteElement(eb.CreateUnicodeTextRun(&cjk_uni[0], uint(len(cjk_uni))))
166 writer.WriteElement(eb.CreateTextNewLine())
167
168 // Simplified Chinese
169 chineseSimplified := []uint16{0x4e16, 0x754c, 0x60a8, 0x597d}
170 writer.WriteElement(eb.CreateUnicodeTextRun(&chineseSimplified[0], uint(len(chineseSimplified))))
171 writer.WriteElement(eb.CreateTextNewLine())
172
173 // Finish the block of text
174 writer.WriteElement(eb.CreateTextEnd())
175
176 fmt.Println("Now using text shaping logic to place text")
177
178 // Create a font in indexed encoding mode
179 // normally this would mean that we are required to provide glyph indices
180 // directly to CreateUnicodeTextRun, but instead, we will use the GetShapedText
181 // method to take care of this detail for us.
182 indexedFont := FontCreateCIDTrueTypeFont(doc.GetSDFDoc(), inputPath + "NotoSans_with_hindi.ttf", true, true, FontE_Indices)
183 element = eb.CreateTextBegin(indexedFont, 10.0)
184 writer.WriteElement(element)
185
186 linePos := 350.0
187 lineSpace := 20.0
188
189 // Transform unicode text into an abstract collection of glyph indices and positioning info
190 shapedText := indexedFont.GetShapedText("Shaped Hindi Text:")
191
192 // transform the shaped text info into a PDF element and write it to the page
193 element = eb.CreateShapedTextRun(shapedText)
194 element.SetTextMatrix(1.5, 0.0, 0.0, 1.5, 50.0, linePos)
195 writer.WriteElement(element)
196 // read in unicode text lines from a file
197 ReadUnicodeTextLinesFromFile(writer, indexedFont, eb, linePos, lineSpace, true, false)
198 ReadUnicodeTextLinesFromFile(writer, indexedFont, eb, linePos, lineSpace, false, true)
199
200 // Finish the block of text
201 writer.WriteElement(eb.CreateTextEnd())
202
203 writer.End() // save changes to the current page
204 doc.PagePushBack(page)
205
206 doc.Save(outputPath + "unicodewrite.pdf", uint(SDFDocE_remove_unused | SDFDocE_hex_strings))
207 fmt.Println("Done. Result saved in unicodewrite.pdf...")
208
209 doc.Close()
210 PDFNetTerminate()
211}

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales