utf8fontfile.go 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154
  1. /*
  2. * Copyright (c) 2019 Arteom Korotkiy (Gmail: arteomkorotkiy)
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. package gofpdf
  17. import (
  18. "bytes"
  19. "encoding/binary"
  20. "fmt"
  21. "math"
  22. "sort"
  23. )
  24. // flags
  25. const symbolWords = 1 << 0
  26. const symbolScale = 1 << 3
  27. const symbolContinue = 1 << 5
  28. const symbolAllScale = 1 << 6
  29. const symbol2x2 = 1 << 7
  30. // CID map Init
  31. const toUnicode = "/CIDInit /ProcSet findresource begin\n12 dict begin\nbegincmap\n/CIDSystemInfo\n<</Registry (Adobe)\n/Ordering (UCS)\n/Supplement 0\n>> def\n/CMapName /Adobe-Identity-UCS def\n/CMapType 2 def\n1 begincodespacerange\n<0000> <FFFF>\nendcodespacerange\n1 beginbfrange\n<0000> <FFFF> <0000>\nendbfrange\nendcmap\nCMapName currentdict /CMap defineresource pop\nend\nend"
  32. type utf8FontFile struct {
  33. fileReader *fileReader
  34. LastRune int
  35. tableDescriptions map[string]*tableDescription
  36. outTablesData map[string][]byte
  37. symbolPosition []int
  38. charSymbolDictionary map[int]int
  39. Ascent int
  40. Descent int
  41. fontElementSize int
  42. Bbox fontBoxType
  43. CapHeight int
  44. StemV int
  45. ItalicAngle int
  46. Flags int
  47. UnderlinePosition float64
  48. UnderlineThickness float64
  49. CharWidths []int
  50. DefaultWidth float64
  51. symbolData map[int]map[string][]int
  52. CodeSymbolDictionary map[int]int
  53. }
  54. type tableDescription struct {
  55. name string
  56. checksum []int
  57. position int
  58. size int
  59. }
  60. type fileReader struct {
  61. readerPosition int64
  62. array []byte
  63. }
  64. func (fr *fileReader) Read(s int) []byte {
  65. b := fr.array[fr.readerPosition : fr.readerPosition+int64(s)]
  66. fr.readerPosition += int64(s)
  67. return b
  68. }
  69. func (fr *fileReader) seek(shift int64, flag int) (int64, error) {
  70. if flag == 0 {
  71. fr.readerPosition = shift
  72. } else if flag == 1 {
  73. fr.readerPosition += shift
  74. } else if flag == 2 {
  75. fr.readerPosition = int64(len(fr.array)) - shift
  76. }
  77. return int64(fr.readerPosition), nil
  78. }
  79. func newUTF8Font(reader *fileReader) *utf8FontFile {
  80. utf := utf8FontFile{
  81. fileReader: reader,
  82. }
  83. return &utf
  84. }
  85. func (utf *utf8FontFile) parseFile() error {
  86. utf.fileReader.readerPosition = 0
  87. utf.symbolPosition = make([]int, 0)
  88. utf.charSymbolDictionary = make(map[int]int)
  89. utf.tableDescriptions = make(map[string]*tableDescription)
  90. utf.outTablesData = make(map[string][]byte)
  91. utf.Ascent = 0
  92. utf.Descent = 0
  93. codeType := uint32(utf.readUint32())
  94. if codeType == 0x4F54544F {
  95. return fmt.Errorf("not supported\n ")
  96. }
  97. if codeType == 0x74746366 {
  98. return fmt.Errorf("not supported\n ")
  99. }
  100. if codeType != 0x00010000 && codeType != 0x74727565 {
  101. return fmt.Errorf("Not a TrueType font: codeType=%v\n ", codeType)
  102. }
  103. utf.generateTableDescriptions()
  104. utf.parseTables()
  105. return nil
  106. }
  107. func (utf *utf8FontFile) generateTableDescriptions() {
  108. tablesCount := utf.readUint16()
  109. _ = utf.readUint16()
  110. _ = utf.readUint16()
  111. _ = utf.readUint16()
  112. utf.tableDescriptions = make(map[string]*tableDescription)
  113. for i := 0; i < tablesCount; i++ {
  114. record := tableDescription{
  115. name: utf.readTableName(),
  116. checksum: []int{utf.readUint16(), utf.readUint16()},
  117. position: utf.readUint32(),
  118. size: utf.readUint32(),
  119. }
  120. utf.tableDescriptions[record.name] = &record
  121. }
  122. }
  123. func (utf *utf8FontFile) readTableName() string {
  124. return string(utf.fileReader.Read(4))
  125. }
  126. func (utf *utf8FontFile) readUint16() int {
  127. s := utf.fileReader.Read(2)
  128. return (int(s[0]) << 8) + int(s[1])
  129. }
  130. func (utf *utf8FontFile) readUint32() int {
  131. s := utf.fileReader.Read(4)
  132. return (int(s[0]) * 16777216) + (int(s[1]) << 16) + (int(s[2]) << 8) + int(s[3]) // 16777216 = 1<<24
  133. }
  134. func (utf *utf8FontFile) calcInt32(x, y []int) []int {
  135. answer := make([]int, 2)
  136. if y[1] > x[1] {
  137. x[1] += 1 << 16
  138. x[0]++
  139. }
  140. answer[1] = x[1] - y[1]
  141. if y[0] > x[0] {
  142. x[0] += 1 << 16
  143. }
  144. answer[0] = x[0] - y[0]
  145. answer[0] = answer[0] & 0xFFFF
  146. return answer
  147. }
  148. func (utf *utf8FontFile) generateChecksum(data []byte) []int {
  149. if (len(data) % 4) != 0 {
  150. for i := 0; (len(data) % 4) != 0; i++ {
  151. data = append(data, 0)
  152. }
  153. }
  154. answer := []int{0x0000, 0x0000}
  155. for i := 0; i < len(data); i += 4 {
  156. answer[0] += (int(data[i]) << 8) + int(data[i+1])
  157. answer[1] += (int(data[i+2]) << 8) + int(data[i+3])
  158. answer[0] += answer[1] >> 16
  159. answer[1] = answer[1] & 0xFFFF
  160. answer[0] = answer[0] & 0xFFFF
  161. }
  162. return answer
  163. }
  164. func (utf *utf8FontFile) seek(shift int) {
  165. _, _ = utf.fileReader.seek(int64(shift), 0)
  166. }
  167. func (utf *utf8FontFile) skip(delta int) {
  168. _, _ = utf.fileReader.seek(int64(delta), 1)
  169. }
  170. //SeekTable position
  171. func (utf *utf8FontFile) SeekTable(name string) int {
  172. return utf.seekTable(name, 0)
  173. }
  174. func (utf *utf8FontFile) seekTable(name string, offsetInTable int) int {
  175. _, _ = utf.fileReader.seek(int64(utf.tableDescriptions[name].position+offsetInTable), 0)
  176. return int(utf.fileReader.readerPosition)
  177. }
  178. func (utf *utf8FontFile) readInt16() int16 {
  179. s := utf.fileReader.Read(2)
  180. a := (int16(s[0]) << 8) + int16(s[1])
  181. if (int(a) & (1 << 15)) == 0 {
  182. a = int16(int(a) - (1 << 16))
  183. }
  184. return a
  185. }
  186. func (utf *utf8FontFile) getUint16(pos int) int {
  187. _, _ = utf.fileReader.seek(int64(pos), 0)
  188. s := utf.fileReader.Read(2)
  189. return (int(s[0]) << 8) + int(s[1])
  190. }
  191. func (utf *utf8FontFile) splice(stream []byte, offset int, value []byte) []byte {
  192. stream = append([]byte{}, stream...)
  193. return append(append(stream[:offset], value...), stream[offset+len(value):]...)
  194. }
  195. func (utf *utf8FontFile) insertUint16(stream []byte, offset int, value int) []byte {
  196. up := make([]byte, 2)
  197. binary.BigEndian.PutUint16(up, uint16(value))
  198. return utf.splice(stream, offset, up)
  199. }
  200. func (utf *utf8FontFile) getRange(pos, length int) []byte {
  201. _, _ = utf.fileReader.seek(int64(pos), 0)
  202. if length < 1 {
  203. return make([]byte, 0)
  204. }
  205. s := utf.fileReader.Read(length)
  206. return s
  207. }
  208. func (utf *utf8FontFile) getTableData(name string) []byte {
  209. desckrip := utf.tableDescriptions[name]
  210. if desckrip == nil {
  211. return nil
  212. }
  213. if desckrip.size == 0 {
  214. return nil
  215. }
  216. _, _ = utf.fileReader.seek(int64(desckrip.position), 0)
  217. s := utf.fileReader.Read(desckrip.size)
  218. return s
  219. }
  220. func (utf *utf8FontFile) setOutTable(name string, data []byte) {
  221. if data == nil {
  222. return
  223. }
  224. if name == "head" {
  225. data = utf.splice(data, 8, []byte{0, 0, 0, 0})
  226. }
  227. utf.outTablesData[name] = data
  228. }
  229. func arrayKeys(arr map[int]string) []int {
  230. answer := make([]int, len(arr))
  231. i := 0
  232. for key := range arr {
  233. answer[i] = key
  234. i++
  235. }
  236. return answer
  237. }
  238. func inArray(s int, arr []int) bool {
  239. for _, i := range arr {
  240. if s == i {
  241. return true
  242. }
  243. }
  244. return false
  245. }
  246. func (utf *utf8FontFile) parseNAMETable() int {
  247. namePosition := utf.SeekTable("name")
  248. format := utf.readUint16()
  249. if format != 0 {
  250. fmt.Printf("Illegal format %d\n", format)
  251. return format
  252. }
  253. nameCount := utf.readUint16()
  254. stringDataPosition := namePosition + utf.readUint16()
  255. names := map[int]string{1: "", 2: "", 3: "", 4: "", 6: ""}
  256. keys := arrayKeys(names)
  257. counter := len(names)
  258. for i := 0; i < nameCount; i++ {
  259. system := utf.readUint16()
  260. code := utf.readUint16()
  261. local := utf.readUint16()
  262. nameID := utf.readUint16()
  263. size := utf.readUint16()
  264. position := utf.readUint16()
  265. if !inArray(nameID, keys) {
  266. continue
  267. }
  268. currentName := ""
  269. if system == 3 && code == 1 && local == 0x409 {
  270. oldPos := utf.fileReader.readerPosition
  271. utf.seek(stringDataPosition + position)
  272. if size%2 != 0 {
  273. fmt.Printf("name is not binar byte format\n")
  274. return format
  275. }
  276. size /= 2
  277. currentName = ""
  278. for size > 0 {
  279. char := utf.readUint16()
  280. currentName += string(rune(char))
  281. size--
  282. }
  283. utf.fileReader.readerPosition = oldPos
  284. utf.seek(int(oldPos))
  285. } else if system == 1 && code == 0 && local == 0 {
  286. oldPos := utf.fileReader.readerPosition
  287. currentName = string(utf.getRange(stringDataPosition+position, size))
  288. utf.fileReader.readerPosition = oldPos
  289. utf.seek(int(oldPos))
  290. }
  291. if currentName != "" && names[nameID] == "" {
  292. names[nameID] = currentName
  293. counter--
  294. if counter == 0 {
  295. break
  296. }
  297. }
  298. }
  299. return format
  300. }
  301. func (utf *utf8FontFile) parseHEADTable() {
  302. utf.SeekTable("head")
  303. utf.skip(18)
  304. utf.fontElementSize = utf.readUint16()
  305. scale := 1000.0 / float64(utf.fontElementSize)
  306. utf.skip(16)
  307. xMin := utf.readInt16()
  308. yMin := utf.readInt16()
  309. xMax := utf.readInt16()
  310. yMax := utf.readInt16()
  311. utf.Bbox = fontBoxType{int(float64(xMin) * scale), int(float64(yMin) * scale), int(float64(xMax) * scale), int(float64(yMax) * scale)}
  312. utf.skip(3 * 2)
  313. _ = utf.readUint16()
  314. symbolDataFormat := utf.readUint16()
  315. if symbolDataFormat != 0 {
  316. fmt.Printf("Unknown symbol data format %d\n", symbolDataFormat)
  317. return
  318. }
  319. }
  320. func (utf *utf8FontFile) parseHHEATable() int {
  321. metricsCount := 0
  322. if _, OK := utf.tableDescriptions["hhea"]; OK {
  323. scale := 1000.0 / float64(utf.fontElementSize)
  324. utf.SeekTable("hhea")
  325. utf.skip(4)
  326. hheaAscender := utf.readInt16()
  327. hheaDescender := utf.readInt16()
  328. utf.Ascent = int(float64(hheaAscender) * scale)
  329. utf.Descent = int(float64(hheaDescender) * scale)
  330. utf.skip(24)
  331. metricDataFormat := utf.readUint16()
  332. if metricDataFormat != 0 {
  333. fmt.Printf("Unknown horizontal metric data format %d\n", metricDataFormat)
  334. return 0
  335. }
  336. metricsCount = utf.readUint16()
  337. if metricsCount == 0 {
  338. fmt.Printf("Number of horizontal metrics is 0\n")
  339. return 0
  340. }
  341. }
  342. return metricsCount
  343. }
  344. func (utf *utf8FontFile) parseOS2Table() int {
  345. var weightType int
  346. scale := 1000.0 / float64(utf.fontElementSize)
  347. if _, OK := utf.tableDescriptions["OS/2"]; OK {
  348. utf.SeekTable("OS/2")
  349. version := utf.readUint16()
  350. utf.skip(2)
  351. weightType = utf.readUint16()
  352. utf.skip(2)
  353. fsType := utf.readUint16()
  354. if fsType == 0x0002 || (fsType&0x0300) != 0 {
  355. fmt.Printf("ERROR - copyright restrictions.\n")
  356. return 0
  357. }
  358. utf.skip(20)
  359. _ = utf.readInt16()
  360. utf.skip(36)
  361. sTypoAscender := utf.readInt16()
  362. sTypoDescender := utf.readInt16()
  363. if utf.Ascent == 0 {
  364. utf.Ascent = int(float64(sTypoAscender) * scale)
  365. }
  366. if utf.Descent == 0 {
  367. utf.Descent = int(float64(sTypoDescender) * scale)
  368. }
  369. if version > 1 {
  370. utf.skip(16)
  371. sCapHeight := utf.readInt16()
  372. utf.CapHeight = int(float64(sCapHeight) * scale)
  373. } else {
  374. utf.CapHeight = utf.Ascent
  375. }
  376. } else {
  377. weightType = 500
  378. if utf.Ascent == 0 {
  379. utf.Ascent = int(float64(utf.Bbox.Ymax) * scale)
  380. }
  381. if utf.Descent == 0 {
  382. utf.Descent = int(float64(utf.Bbox.Ymin) * scale)
  383. }
  384. utf.CapHeight = utf.Ascent
  385. }
  386. utf.StemV = 50 + int(math.Pow(float64(weightType)/65.0, 2))
  387. return weightType
  388. }
  389. func (utf *utf8FontFile) parsePOSTTable(weight int) {
  390. utf.SeekTable("post")
  391. utf.skip(4)
  392. utf.ItalicAngle = int(utf.readInt16()) + utf.readUint16()/65536.0
  393. scale := 1000.0 / float64(utf.fontElementSize)
  394. utf.UnderlinePosition = float64(utf.readInt16()) * scale
  395. utf.UnderlineThickness = float64(utf.readInt16()) * scale
  396. fixed := utf.readUint32()
  397. utf.Flags = 4
  398. if utf.ItalicAngle != 0 {
  399. utf.Flags = utf.Flags | 64
  400. }
  401. if weight >= 600 {
  402. utf.Flags = utf.Flags | 262144
  403. }
  404. if fixed != 0 {
  405. utf.Flags = utf.Flags | 1
  406. }
  407. }
  408. func (utf *utf8FontFile) parseCMAPTable(format int) int {
  409. cmapPosition := utf.SeekTable("cmap")
  410. utf.skip(2)
  411. cmapTableCount := utf.readUint16()
  412. cidCMAPPosition := 0
  413. for i := 0; i < cmapTableCount; i++ {
  414. system := utf.readUint16()
  415. coded := utf.readUint16()
  416. position := utf.readUint32()
  417. oldReaderPosition := utf.fileReader.readerPosition
  418. if (system == 3 && coded == 1) || system == 0 { // Microsoft, Unicode
  419. format = utf.getUint16(cmapPosition + position)
  420. if format == 4 {
  421. if cidCMAPPosition == 0 {
  422. cidCMAPPosition = cmapPosition + position
  423. }
  424. break
  425. }
  426. }
  427. utf.seek(int(oldReaderPosition))
  428. }
  429. if cidCMAPPosition == 0 {
  430. fmt.Printf("Font does not have cmap for Unicode\n")
  431. return cidCMAPPosition
  432. }
  433. return cidCMAPPosition
  434. }
  435. func (utf *utf8FontFile) parseTables() {
  436. f := utf.parseNAMETable()
  437. utf.parseHEADTable()
  438. n := utf.parseHHEATable()
  439. w := utf.parseOS2Table()
  440. utf.parsePOSTTable(w)
  441. runeCMAPPosition := utf.parseCMAPTable(f)
  442. utf.SeekTable("maxp")
  443. utf.skip(4)
  444. numSymbols := utf.readUint16()
  445. symbolCharDictionary := make(map[int][]int)
  446. charSymbolDictionary := make(map[int]int)
  447. utf.generateSCCSDictionaries(runeCMAPPosition, symbolCharDictionary, charSymbolDictionary)
  448. scale := 1000.0 / float64(utf.fontElementSize)
  449. utf.parseHMTXTable(n, numSymbols, symbolCharDictionary, scale)
  450. }
  451. func (utf *utf8FontFile) generateCMAP() map[int][]int {
  452. cmapPosition := utf.SeekTable("cmap")
  453. utf.skip(2)
  454. cmapTableCount := utf.readUint16()
  455. runeCmapPosition := 0
  456. for i := 0; i < cmapTableCount; i++ {
  457. system := utf.readUint16()
  458. coder := utf.readUint16()
  459. position := utf.readUint32()
  460. oldPosition := utf.fileReader.readerPosition
  461. if (system == 3 && coder == 1) || system == 0 {
  462. format := utf.getUint16(cmapPosition + position)
  463. if format == 4 {
  464. runeCmapPosition = cmapPosition + position
  465. break
  466. }
  467. }
  468. utf.seek(int(oldPosition))
  469. }
  470. if runeCmapPosition == 0 {
  471. fmt.Printf("Font does not have cmap for Unicode\n")
  472. return nil
  473. }
  474. symbolCharDictionary := make(map[int][]int)
  475. charSymbolDictionary := make(map[int]int)
  476. utf.generateSCCSDictionaries(runeCmapPosition, symbolCharDictionary, charSymbolDictionary)
  477. utf.charSymbolDictionary = charSymbolDictionary
  478. return symbolCharDictionary
  479. }
  480. func (utf *utf8FontFile) parseSymbols(usedRunes map[int]int) (map[int]int, map[int]int, map[int]int, []int) {
  481. symbolCollection := map[int]int{0: 0}
  482. charSymbolPairCollection := make(map[int]int)
  483. for _, char := range usedRunes {
  484. if _, OK := utf.charSymbolDictionary[char]; OK {
  485. symbolCollection[utf.charSymbolDictionary[char]] = char
  486. charSymbolPairCollection[char] = utf.charSymbolDictionary[char]
  487. }
  488. utf.LastRune = max(utf.LastRune, char)
  489. }
  490. begin := utf.tableDescriptions["glyf"].position
  491. symbolArray := make(map[int]int)
  492. symbolCollectionKeys := keySortInt(symbolCollection)
  493. symbolCounter := 0
  494. maxRune := 0
  495. for _, oldSymbolIndex := range symbolCollectionKeys {
  496. maxRune = max(maxRune, symbolCollection[oldSymbolIndex])
  497. symbolArray[oldSymbolIndex] = symbolCounter
  498. symbolCounter++
  499. }
  500. charSymbolPairCollectionKeys := keySortInt(charSymbolPairCollection)
  501. runeSymbolPairCollection := make(map[int]int)
  502. for _, runa := range charSymbolPairCollectionKeys {
  503. runeSymbolPairCollection[runa] = symbolArray[charSymbolPairCollection[runa]]
  504. }
  505. utf.CodeSymbolDictionary = runeSymbolPairCollection
  506. symbolCollectionKeys = keySortInt(symbolCollection)
  507. for _, oldSymbolIndex := range symbolCollectionKeys {
  508. _, symbolArray, symbolCollection, symbolCollectionKeys = utf.getSymbols(oldSymbolIndex, &begin, symbolArray, symbolCollection, symbolCollectionKeys)
  509. }
  510. return runeSymbolPairCollection, symbolArray, symbolCollection, symbolCollectionKeys
  511. }
  512. func (utf *utf8FontFile) generateCMAPTable(cidSymbolPairCollection map[int]int, numSymbols int) []byte {
  513. cidSymbolPairCollectionKeys := keySortInt(cidSymbolPairCollection)
  514. cidID := 0
  515. cidArray := make(map[int][]int)
  516. prevCid := -2
  517. prevSymbol := -1
  518. for _, cid := range cidSymbolPairCollectionKeys {
  519. if cid == (prevCid+1) && cidSymbolPairCollection[cid] == (prevSymbol+1) {
  520. if n, OK := cidArray[cidID]; !OK || n == nil {
  521. cidArray[cidID] = make([]int, 0)
  522. }
  523. cidArray[cidID] = append(cidArray[cidID], cidSymbolPairCollection[cid])
  524. } else {
  525. cidID = cid
  526. cidArray[cidID] = make([]int, 0)
  527. cidArray[cidID] = append(cidArray[cidID], cidSymbolPairCollection[cid])
  528. }
  529. prevCid = cid
  530. prevSymbol = cidSymbolPairCollection[cid]
  531. }
  532. cidArrayKeys := keySortArrayRangeMap(cidArray)
  533. segCount := len(cidArray) + 1
  534. searchRange := 1
  535. entrySelector := 0
  536. for searchRange*2 <= segCount {
  537. searchRange = searchRange * 2
  538. entrySelector = entrySelector + 1
  539. }
  540. searchRange = searchRange * 2
  541. rangeShift := segCount*2 - searchRange
  542. length := 16 + (8 * segCount) + (numSymbols + 1)
  543. cmap := []int{0, 1, 3, 1, 0, 12, 4, length, 0, segCount * 2, searchRange, entrySelector, rangeShift}
  544. for _, start := range cidArrayKeys {
  545. endCode := start + (len(cidArray[start]) - 1)
  546. cmap = append(cmap, endCode)
  547. }
  548. cmap = append(cmap, 0xFFFF)
  549. cmap = append(cmap, 0)
  550. for _, cidKey := range cidArrayKeys {
  551. cmap = append(cmap, cidKey)
  552. }
  553. cmap = append(cmap, 0xFFFF)
  554. for _, cidKey := range cidArrayKeys {
  555. idDelta := -(cidKey - cidArray[cidKey][0])
  556. cmap = append(cmap, idDelta)
  557. }
  558. cmap = append(cmap, 1)
  559. for range cidArray {
  560. cmap = append(cmap, 0)
  561. }
  562. cmap = append(cmap, 0)
  563. for _, start := range cidArrayKeys {
  564. for _, glidx := range cidArray[start] {
  565. cmap = append(cmap, glidx)
  566. }
  567. }
  568. cmap = append(cmap, 0)
  569. cmapstr := make([]byte, 0)
  570. for _, cm := range cmap {
  571. cmapstr = append(cmapstr, packUint16(cm)...)
  572. }
  573. return cmapstr
  574. }
  575. //GenerateCutFont fill utf8FontFile from .utf file, only with runes from usedRunes
  576. func (utf *utf8FontFile) GenerateCutFont(usedRunes map[int]int) []byte {
  577. utf.fileReader.readerPosition = 0
  578. utf.symbolPosition = make([]int, 0)
  579. utf.charSymbolDictionary = make(map[int]int)
  580. utf.tableDescriptions = make(map[string]*tableDescription)
  581. utf.outTablesData = make(map[string][]byte)
  582. utf.Ascent = 0
  583. utf.Descent = 0
  584. utf.skip(4)
  585. utf.LastRune = 0
  586. utf.generateTableDescriptions()
  587. utf.SeekTable("head")
  588. utf.skip(50)
  589. LocaFormat := utf.readUint16()
  590. utf.SeekTable("hhea")
  591. utf.skip(34)
  592. metricsCount := utf.readUint16()
  593. oldMetrics := metricsCount
  594. utf.SeekTable("maxp")
  595. utf.skip(4)
  596. numSymbols := utf.readUint16()
  597. symbolCharDictionary := utf.generateCMAP()
  598. if symbolCharDictionary == nil {
  599. return nil
  600. }
  601. utf.parseHMTXTable(metricsCount, numSymbols, symbolCharDictionary, 1.0)
  602. utf.parseLOCATable(LocaFormat, numSymbols)
  603. cidSymbolPairCollection, symbolArray, symbolCollection, symbolCollectionKeys := utf.parseSymbols(usedRunes)
  604. metricsCount = len(symbolCollection)
  605. numSymbols = metricsCount
  606. utf.setOutTable("name", utf.getTableData("name"))
  607. utf.setOutTable("cvt ", utf.getTableData("cvt "))
  608. utf.setOutTable("fpgm", utf.getTableData("fpgm"))
  609. utf.setOutTable("prep", utf.getTableData("prep"))
  610. utf.setOutTable("gasp", utf.getTableData("gasp"))
  611. postTable := utf.getTableData("post")
  612. postTable = append(append([]byte{0x00, 0x03, 0x00, 0x00}, postTable[4:16]...), []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}...)
  613. utf.setOutTable("post", postTable)
  614. delete(cidSymbolPairCollection, 0)
  615. utf.setOutTable("cmap", utf.generateCMAPTable(cidSymbolPairCollection, numSymbols))
  616. symbolData := utf.getTableData("glyf")
  617. offsets := make([]int, 0)
  618. glyfData := make([]byte, 0)
  619. pos := 0
  620. hmtxData := make([]byte, 0)
  621. utf.symbolData = make(map[int]map[string][]int, 0)
  622. for _, originalSymbolIdx := range symbolCollectionKeys {
  623. hm := utf.getMetrics(oldMetrics, originalSymbolIdx)
  624. hmtxData = append(hmtxData, hm...)
  625. offsets = append(offsets, pos)
  626. symbolPos := utf.symbolPosition[originalSymbolIdx]
  627. symbolLen := utf.symbolPosition[originalSymbolIdx+1] - symbolPos
  628. data := symbolData[symbolPos : symbolPos+symbolLen]
  629. var up int
  630. if symbolLen > 0 {
  631. up = unpackUint16(data[0:2])
  632. }
  633. if symbolLen > 2 && (up&(1<<15)) != 0 {
  634. posInSymbol := 10
  635. flags := symbolContinue
  636. nComponentElements := 0
  637. for (flags & symbolContinue) != 0 {
  638. nComponentElements++
  639. up = unpackUint16(data[posInSymbol : posInSymbol+2])
  640. flags = up
  641. up = unpackUint16(data[posInSymbol+2 : posInSymbol+4])
  642. symbolIdx := up
  643. if _, OK := utf.symbolData[originalSymbolIdx]; !OK {
  644. utf.symbolData[originalSymbolIdx] = make(map[string][]int)
  645. }
  646. if _, OK := utf.symbolData[originalSymbolIdx]["compSymbols"]; !OK {
  647. utf.symbolData[originalSymbolIdx]["compSymbols"] = make([]int, 0)
  648. }
  649. utf.symbolData[originalSymbolIdx]["compSymbols"] = append(utf.symbolData[originalSymbolIdx]["compSymbols"], symbolIdx)
  650. data = utf.insertUint16(data, posInSymbol+2, symbolArray[symbolIdx])
  651. posInSymbol += 4
  652. if (flags & symbolWords) != 0 {
  653. posInSymbol += 4
  654. } else {
  655. posInSymbol += 2
  656. }
  657. if (flags & symbolScale) != 0 {
  658. posInSymbol += 2
  659. } else if (flags & symbolAllScale) != 0 {
  660. posInSymbol += 4
  661. } else if (flags & symbol2x2) != 0 {
  662. posInSymbol += 8
  663. }
  664. }
  665. }
  666. glyfData = append(glyfData, data...)
  667. pos += symbolLen
  668. if pos%4 != 0 {
  669. padding := 4 - (pos % 4)
  670. glyfData = append(glyfData, make([]byte, padding)...)
  671. pos += padding
  672. }
  673. }
  674. offsets = append(offsets, pos)
  675. utf.setOutTable("glyf", glyfData)
  676. utf.setOutTable("hmtx", hmtxData)
  677. locaData := make([]byte, 0)
  678. if ((pos + 1) >> 1) > 0xFFFF {
  679. LocaFormat = 1
  680. for _, offset := range offsets {
  681. locaData = append(locaData, packUint32(offset)...)
  682. }
  683. } else {
  684. LocaFormat = 0
  685. for _, offset := range offsets {
  686. locaData = append(locaData, packUint16(offset/2)...)
  687. }
  688. }
  689. utf.setOutTable("loca", locaData)
  690. headData := utf.getTableData("head")
  691. headData = utf.insertUint16(headData, 50, LocaFormat)
  692. utf.setOutTable("head", headData)
  693. hheaData := utf.getTableData("hhea")
  694. hheaData = utf.insertUint16(hheaData, 34, metricsCount)
  695. utf.setOutTable("hhea", hheaData)
  696. maxp := utf.getTableData("maxp")
  697. maxp = utf.insertUint16(maxp, 4, numSymbols)
  698. utf.setOutTable("maxp", maxp)
  699. os2Data := utf.getTableData("OS/2")
  700. utf.setOutTable("OS/2", os2Data)
  701. return utf.assembleTables()
  702. }
  703. func (utf *utf8FontFile) getSymbols(originalSymbolIdx int, start *int, symbolSet map[int]int, SymbolsCollection map[int]int, SymbolsCollectionKeys []int) (*int, map[int]int, map[int]int, []int) {
  704. symbolPos := utf.symbolPosition[originalSymbolIdx]
  705. symbolSize := utf.symbolPosition[originalSymbolIdx+1] - symbolPos
  706. if symbolSize == 0 {
  707. return start, symbolSet, SymbolsCollection, SymbolsCollectionKeys
  708. }
  709. utf.seek(*start + symbolPos)
  710. lineCount := utf.readInt16()
  711. if lineCount < 0 {
  712. utf.skip(8)
  713. flags := symbolContinue
  714. for flags&symbolContinue != 0 {
  715. flags = utf.readUint16()
  716. symbolIndex := utf.readUint16()
  717. if _, OK := symbolSet[symbolIndex]; !OK {
  718. symbolSet[symbolIndex] = len(SymbolsCollection)
  719. SymbolsCollection[symbolIndex] = 1
  720. SymbolsCollectionKeys = append(SymbolsCollectionKeys, symbolIndex)
  721. }
  722. oldPosition, _ := utf.fileReader.seek(0, 1)
  723. _, _, _, SymbolsCollectionKeys = utf.getSymbols(symbolIndex, start, symbolSet, SymbolsCollection, SymbolsCollectionKeys)
  724. utf.seek(int(oldPosition))
  725. if flags&symbolWords != 0 {
  726. utf.skip(4)
  727. } else {
  728. utf.skip(2)
  729. }
  730. if flags&symbolScale != 0 {
  731. utf.skip(2)
  732. } else if flags&symbolAllScale != 0 {
  733. utf.skip(4)
  734. } else if flags&symbol2x2 != 0 {
  735. utf.skip(8)
  736. }
  737. }
  738. }
  739. return start, symbolSet, SymbolsCollection, SymbolsCollectionKeys
  740. }
  741. func (utf *utf8FontFile) parseHMTXTable(numberOfHMetrics, numSymbols int, symbolToChar map[int][]int, scale float64) {
  742. var widths int
  743. start := utf.SeekTable("hmtx")
  744. arrayWidths := 0
  745. var arr []int
  746. utf.CharWidths = make([]int, 256*256)
  747. charCount := 0
  748. arr = unpackUint16Array(utf.getRange(start, numberOfHMetrics*4))
  749. for symbol := 0; symbol < numberOfHMetrics; symbol++ {
  750. arrayWidths = arr[(symbol*2)+1]
  751. if _, OK := symbolToChar[symbol]; OK || symbol == 0 {
  752. if arrayWidths >= (1 << 15) {
  753. arrayWidths = 0
  754. }
  755. if symbol == 0 {
  756. utf.DefaultWidth = scale * float64(arrayWidths)
  757. continue
  758. }
  759. for _, char := range symbolToChar[symbol] {
  760. if char != 0 && char != 65535 {
  761. widths = int(math.Round(scale * float64(arrayWidths)))
  762. if widths == 0 {
  763. widths = 65535
  764. }
  765. if char < 196608 {
  766. utf.CharWidths[char] = widths
  767. charCount++
  768. }
  769. }
  770. }
  771. }
  772. }
  773. diff := numSymbols - numberOfHMetrics
  774. for pos := 0; pos < diff; pos++ {
  775. symbol := pos + numberOfHMetrics
  776. if _, OK := symbolToChar[symbol]; OK {
  777. for _, char := range symbolToChar[symbol] {
  778. if char != 0 && char != 65535 {
  779. widths = int(math.Round(scale * float64(arrayWidths)))
  780. if widths == 0 {
  781. widths = 65535
  782. }
  783. if char < 196608 {
  784. utf.CharWidths[char] = widths
  785. charCount++
  786. }
  787. }
  788. }
  789. }
  790. }
  791. utf.CharWidths[0] = charCount
  792. }
  793. func (utf *utf8FontFile) getMetrics(metricCount, gid int) []byte {
  794. start := utf.SeekTable("hmtx")
  795. var metrics []byte
  796. if gid < metricCount {
  797. utf.seek(start + (gid * 4))
  798. metrics = utf.fileReader.Read(4)
  799. } else {
  800. utf.seek(start + ((metricCount - 1) * 4))
  801. metrics = utf.fileReader.Read(2)
  802. utf.seek(start + (metricCount * 2) + (gid * 2))
  803. metrics = append(metrics, utf.fileReader.Read(2)...)
  804. }
  805. return metrics
  806. }
  807. func (utf *utf8FontFile) parseLOCATable(format, numSymbols int) {
  808. start := utf.SeekTable("loca")
  809. utf.symbolPosition = make([]int, 0)
  810. if format == 0 {
  811. data := utf.getRange(start, (numSymbols*2)+2)
  812. arr := unpackUint16Array(data)
  813. for n := 0; n <= numSymbols; n++ {
  814. utf.symbolPosition = append(utf.symbolPosition, arr[n+1]*2)
  815. }
  816. } else if format == 1 {
  817. data := utf.getRange(start, (numSymbols*4)+4)
  818. arr := unpackUint32Array(data)
  819. for n := 0; n <= numSymbols; n++ {
  820. utf.symbolPosition = append(utf.symbolPosition, arr[n+1])
  821. }
  822. } else {
  823. fmt.Printf("Unknown loca table format %d\n", format)
  824. return
  825. }
  826. }
  827. func (utf *utf8FontFile) generateSCCSDictionaries(runeCmapPosition int, symbolCharDictionary map[int][]int, charSymbolDictionary map[int]int) {
  828. maxRune := 0
  829. utf.seek(runeCmapPosition + 2)
  830. size := utf.readUint16()
  831. rim := runeCmapPosition + size
  832. utf.skip(2)
  833. segmentSize := utf.readUint16() / 2
  834. utf.skip(6)
  835. completers := make([]int, 0)
  836. for i := 0; i < segmentSize; i++ {
  837. completers = append(completers, utf.readUint16())
  838. }
  839. utf.skip(2)
  840. beginners := make([]int, 0)
  841. for i := 0; i < segmentSize; i++ {
  842. beginners = append(beginners, utf.readUint16())
  843. }
  844. sizes := make([]int, 0)
  845. for i := 0; i < segmentSize; i++ {
  846. sizes = append(sizes, int(utf.readInt16()))
  847. }
  848. readerPositionStart := utf.fileReader.readerPosition
  849. positions := make([]int, 0)
  850. for i := 0; i < segmentSize; i++ {
  851. positions = append(positions, utf.readUint16())
  852. }
  853. var symbol int
  854. for n := 0; n < segmentSize; n++ {
  855. completePosition := completers[n] + 1
  856. for char := beginners[n]; char < completePosition; char++ {
  857. if positions[n] == 0 {
  858. symbol = (char + sizes[n]) & 0xFFFF
  859. } else {
  860. position := (char-beginners[n])*2 + positions[n]
  861. position = int(readerPositionStart) + 2*n + position
  862. if position >= rim {
  863. symbol = 0
  864. } else {
  865. symbol = utf.getUint16(position)
  866. if symbol != 0 {
  867. symbol = (symbol + sizes[n]) & 0xFFFF
  868. }
  869. }
  870. }
  871. charSymbolDictionary[char] = symbol
  872. if char < 196608 {
  873. maxRune = max(char, maxRune)
  874. }
  875. symbolCharDictionary[symbol] = append(symbolCharDictionary[symbol], char)
  876. }
  877. }
  878. }
  879. func max(i, n int) int {
  880. if n > i {
  881. return n
  882. }
  883. return i
  884. }
  885. func (utf *utf8FontFile) assembleTables() []byte {
  886. answer := make([]byte, 0)
  887. tablesCount := len(utf.outTablesData)
  888. findSize := 1
  889. writer := 0
  890. for findSize*2 <= tablesCount {
  891. findSize = findSize * 2
  892. writer = writer + 1
  893. }
  894. findSize = findSize * 16
  895. rOffset := tablesCount*16 - findSize
  896. answer = append(answer, packHeader(0x00010000, tablesCount, findSize, writer, rOffset)...)
  897. tables := utf.outTablesData
  898. tablesNames := keySortStrings(tables)
  899. offset := 12 + tablesCount*16
  900. begin := 0
  901. for _, name := range tablesNames {
  902. if name == "head" {
  903. begin = offset
  904. }
  905. answer = append(answer, []byte(name)...)
  906. checksum := utf.generateChecksum(tables[name])
  907. answer = append(answer, pack2Uint16(checksum[0], checksum[1])...)
  908. answer = append(answer, pack2Uint32(offset, len(tables[name]))...)
  909. paddedLength := (len(tables[name]) + 3) &^ 3
  910. offset = offset + paddedLength
  911. }
  912. for _, key := range tablesNames {
  913. data := append([]byte{}, tables[key]...)
  914. data = append(data, []byte{0, 0, 0}...)
  915. answer = append(answer, data[:(len(data)&^3)]...)
  916. }
  917. checksum := utf.generateChecksum([]byte(answer))
  918. checksum = utf.calcInt32([]int{0xB1B0, 0xAFBA}, checksum)
  919. answer = utf.splice(answer, (begin + 8), pack2Uint16(checksum[0], checksum[1]))
  920. return answer
  921. }
  922. func unpackUint16Array(data []byte) []int {
  923. answer := make([]int, 1)
  924. r := bytes.NewReader(data)
  925. bs := make([]byte, 2)
  926. var e error
  927. var c int
  928. c, e = r.Read(bs)
  929. for e == nil && c > 0 {
  930. answer = append(answer, int(binary.BigEndian.Uint16(bs)))
  931. c, e = r.Read(bs)
  932. }
  933. return answer
  934. }
  935. func unpackUint32Array(data []byte) []int {
  936. answer := make([]int, 1)
  937. r := bytes.NewReader(data)
  938. bs := make([]byte, 4)
  939. var e error
  940. var c int
  941. c, e = r.Read(bs)
  942. for e == nil && c > 0 {
  943. answer = append(answer, int(binary.BigEndian.Uint32(bs)))
  944. c, e = r.Read(bs)
  945. }
  946. return answer
  947. }
  948. func unpackUint16(data []byte) int {
  949. return int(binary.BigEndian.Uint16(data))
  950. }
  951. func packHeader(N uint32, n1, n2, n3, n4 int) []byte {
  952. answer := make([]byte, 0)
  953. bs4 := make([]byte, 4)
  954. binary.BigEndian.PutUint32(bs4, N)
  955. answer = append(answer, bs4...)
  956. bs := make([]byte, 2)
  957. binary.BigEndian.PutUint16(bs, uint16(n1))
  958. answer = append(answer, bs...)
  959. binary.BigEndian.PutUint16(bs, uint16(n2))
  960. answer = append(answer, bs...)
  961. binary.BigEndian.PutUint16(bs, uint16(n3))
  962. answer = append(answer, bs...)
  963. binary.BigEndian.PutUint16(bs, uint16(n4))
  964. answer = append(answer, bs...)
  965. return answer
  966. }
  967. func pack2Uint16(n1, n2 int) []byte {
  968. answer := make([]byte, 0)
  969. bs := make([]byte, 2)
  970. binary.BigEndian.PutUint16(bs, uint16(n1))
  971. answer = append(answer, bs...)
  972. binary.BigEndian.PutUint16(bs, uint16(n2))
  973. answer = append(answer, bs...)
  974. return answer
  975. }
  976. func pack2Uint32(n1, n2 int) []byte {
  977. answer := make([]byte, 0)
  978. bs := make([]byte, 4)
  979. binary.BigEndian.PutUint32(bs, uint32(n1))
  980. answer = append(answer, bs...)
  981. binary.BigEndian.PutUint32(bs, uint32(n2))
  982. answer = append(answer, bs...)
  983. return answer
  984. }
  985. func packUint32(n1 int) []byte {
  986. bs := make([]byte, 4)
  987. binary.BigEndian.PutUint32(bs, uint32(n1))
  988. return bs
  989. }
  990. func packUint16(n1 int) []byte {
  991. bs := make([]byte, 2)
  992. binary.BigEndian.PutUint16(bs, uint16(n1))
  993. return bs
  994. }
  995. func keySortStrings(s map[string][]byte) []string {
  996. keys := make([]string, len(s))
  997. i := 0
  998. for key := range s {
  999. keys[i] = key
  1000. i++
  1001. }
  1002. sort.Strings(keys)
  1003. return keys
  1004. }
  1005. func keySortInt(s map[int]int) []int {
  1006. keys := make([]int, len(s))
  1007. i := 0
  1008. for key := range s {
  1009. keys[i] = key
  1010. i++
  1011. }
  1012. sort.Ints(keys)
  1013. return keys
  1014. }
  1015. func keySortArrayRangeMap(s map[int][]int) []int {
  1016. keys := make([]int, len(s))
  1017. i := 0
  1018. for key := range s {
  1019. keys[i] = key
  1020. i++
  1021. }
  1022. sort.Ints(keys)
  1023. return keys
  1024. }
  1025. // UTF8CutFont is a utility function that generates a TrueType font composed
  1026. // only of the runes included in cutset. The rune glyphs are copied from This
  1027. // function is demonstrated in ExampleUTF8CutFont().
  1028. func UTF8CutFont(inBuf []byte, cutset string) (outBuf []byte) {
  1029. f := newUTF8Font(&fileReader{readerPosition: 0, array: inBuf})
  1030. runes := map[int]int{}
  1031. for i, r := range cutset {
  1032. runes[i] = int(r)
  1033. }
  1034. outBuf = f.GenerateCutFont(runes)
  1035. return
  1036. }