utf8fontfile.go 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153
  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. return append(append(stream[:offset], value...), stream[offset+len(value):]...)
  193. }
  194. func (utf *utf8FontFile) insertUint16(stream []byte, offset int, value int) []byte {
  195. up := make([]byte, 2)
  196. binary.BigEndian.PutUint16(up, uint16(value))
  197. return utf.splice(stream, offset, up)
  198. }
  199. func (utf *utf8FontFile) getRange(pos, length int) []byte {
  200. utf.fileReader.seek(int64(pos), 0)
  201. if length < 1 {
  202. return make([]byte, 0)
  203. }
  204. s := utf.fileReader.Read(length)
  205. return s
  206. }
  207. func (utf *utf8FontFile) getTableData(name string) []byte {
  208. desckrip := utf.tableDescriptions[name]
  209. if desckrip == nil {
  210. return nil
  211. }
  212. if desckrip.size == 0 {
  213. return nil
  214. }
  215. utf.fileReader.seek(int64(desckrip.position), 0)
  216. s := utf.fileReader.Read(desckrip.size)
  217. return s
  218. }
  219. func (utf *utf8FontFile) setOutTable(name string, data []byte) {
  220. if data == nil {
  221. return
  222. }
  223. if name == "head" {
  224. data = utf.splice(data, 8, []byte{0, 0, 0, 0})
  225. }
  226. utf.outTablesData[name] = data
  227. }
  228. func arrayKeys(arr map[int]string) []int {
  229. answer := make([]int, len(arr))
  230. i := 0
  231. for key := range arr {
  232. answer[i] = key
  233. i++
  234. }
  235. return answer
  236. }
  237. func inArray(s int, arr []int) bool {
  238. for _, i := range arr {
  239. if s == i {
  240. return true
  241. }
  242. }
  243. return false
  244. }
  245. func (utf *utf8FontFile) parseNAMETable() int {
  246. namePosition := utf.SeekTable("name")
  247. format := utf.readUint16()
  248. if format != 0 {
  249. fmt.Printf("Illegal format %d\n", format)
  250. return format
  251. }
  252. nameCount := utf.readUint16()
  253. stringDataPosition := namePosition + utf.readUint16()
  254. names := map[int]string{1: "", 2: "", 3: "", 4: "", 6: ""}
  255. keys := arrayKeys(names)
  256. counter := len(names)
  257. for i := 0; i < nameCount; i++ {
  258. system := utf.readUint16()
  259. code := utf.readUint16()
  260. local := utf.readUint16()
  261. nameID := utf.readUint16()
  262. size := utf.readUint16()
  263. position := utf.readUint16()
  264. if !inArray(nameID, keys) {
  265. continue
  266. }
  267. currentName := ""
  268. if system == 3 && code == 1 && local == 0x409 {
  269. oldPos := utf.fileReader.readerPosition
  270. utf.seek(stringDataPosition + position)
  271. if size%2 != 0 {
  272. fmt.Printf("name is not binar byte format\n")
  273. return format
  274. }
  275. size /= 2
  276. currentName = ""
  277. for size > 0 {
  278. char := utf.readUint16()
  279. currentName += string(rune(char))
  280. size--
  281. }
  282. utf.fileReader.readerPosition = oldPos
  283. utf.seek(int(oldPos))
  284. } else if system == 1 && code == 0 && local == 0 {
  285. oldPos := utf.fileReader.readerPosition
  286. currentName = string(utf.getRange(stringDataPosition+position, size))
  287. utf.fileReader.readerPosition = oldPos
  288. utf.seek(int(oldPos))
  289. }
  290. if currentName != "" && names[nameID] == "" {
  291. names[nameID] = currentName
  292. counter--
  293. if counter == 0 {
  294. break
  295. }
  296. }
  297. }
  298. return format
  299. }
  300. func (utf *utf8FontFile) parseHEADTable() {
  301. utf.SeekTable("head")
  302. utf.skip(18)
  303. utf.fontElementSize = utf.readUint16()
  304. scale := 1000.0 / float64(utf.fontElementSize)
  305. utf.skip(16)
  306. xMin := utf.readInt16()
  307. yMin := utf.readInt16()
  308. xMax := utf.readInt16()
  309. yMax := utf.readInt16()
  310. utf.Bbox = fontBoxType{int(float64(xMin) * scale), int(float64(yMin) * scale), int(float64(xMax) * scale), int(float64(yMax) * scale)}
  311. utf.skip(3 * 2)
  312. _ = utf.readUint16()
  313. symbolDataFormat := utf.readUint16()
  314. if symbolDataFormat != 0 {
  315. fmt.Printf("Unknown symbol data format %d\n", symbolDataFormat)
  316. return
  317. }
  318. }
  319. func (utf *utf8FontFile) parseHHEATable() int {
  320. metricsCount := 0
  321. if _, OK := utf.tableDescriptions["hhea"]; OK {
  322. scale := 1000.0 / float64(utf.fontElementSize)
  323. utf.SeekTable("hhea")
  324. utf.skip(4)
  325. hheaAscender := utf.readInt16()
  326. hheaDescender := utf.readInt16()
  327. utf.Ascent = int(float64(hheaAscender) * scale)
  328. utf.Descent = int(float64(hheaDescender) * scale)
  329. utf.skip(24)
  330. metricDataFormat := utf.readUint16()
  331. if metricDataFormat != 0 {
  332. fmt.Printf("Unknown horizontal metric data format %d\n", metricDataFormat)
  333. return 0
  334. }
  335. metricsCount = utf.readUint16()
  336. if metricsCount == 0 {
  337. fmt.Printf("Number of horizontal metrics is 0\n")
  338. return 0
  339. }
  340. }
  341. return metricsCount
  342. }
  343. func (utf *utf8FontFile) parseOS2Table() int {
  344. var weightType int
  345. scale := 1000.0 / float64(utf.fontElementSize)
  346. if _, OK := utf.tableDescriptions["OS/2"]; OK {
  347. utf.SeekTable("OS/2")
  348. version := utf.readUint16()
  349. utf.skip(2)
  350. weightType = utf.readUint16()
  351. utf.skip(2)
  352. fsType := utf.readUint16()
  353. if fsType == 0x0002 || (fsType&0x0300) != 0 {
  354. fmt.Printf("ERROR - copyright restrictions.\n")
  355. return 0
  356. }
  357. utf.skip(20)
  358. _ = utf.readInt16()
  359. utf.skip(36)
  360. sTypoAscender := utf.readInt16()
  361. sTypoDescender := utf.readInt16()
  362. if utf.Ascent == 0 {
  363. utf.Ascent = int(float64(sTypoAscender) * scale)
  364. }
  365. if utf.Descent == 0 {
  366. utf.Descent = int(float64(sTypoDescender) * scale)
  367. }
  368. if version > 1 {
  369. utf.skip(16)
  370. sCapHeight := utf.readInt16()
  371. utf.CapHeight = int(float64(sCapHeight) * scale)
  372. } else {
  373. utf.CapHeight = utf.Ascent
  374. }
  375. } else {
  376. weightType = 500
  377. if utf.Ascent == 0 {
  378. utf.Ascent = int(float64(utf.Bbox.Ymax) * scale)
  379. }
  380. if utf.Descent == 0 {
  381. utf.Descent = int(float64(utf.Bbox.Ymin) * scale)
  382. }
  383. utf.CapHeight = utf.Ascent
  384. }
  385. utf.StemV = 50 + int(math.Pow(float64(weightType)/65.0, 2))
  386. return weightType
  387. }
  388. func (utf *utf8FontFile) parsePOSTTable(weight int) {
  389. utf.SeekTable("post")
  390. utf.skip(4)
  391. utf.ItalicAngle = int(utf.readInt16()) + utf.readUint16()/65536.0
  392. scale := 1000.0 / float64(utf.fontElementSize)
  393. utf.UnderlinePosition = float64(utf.readInt16()) * scale
  394. utf.UnderlineThickness = float64(utf.readInt16()) * scale
  395. fixed := utf.readUint32()
  396. utf.Flags = 4
  397. if utf.ItalicAngle != 0 {
  398. utf.Flags = utf.Flags | 64
  399. }
  400. if weight >= 600 {
  401. utf.Flags = utf.Flags | 262144
  402. }
  403. if fixed != 0 {
  404. utf.Flags = utf.Flags | 1
  405. }
  406. }
  407. func (utf *utf8FontFile) parseCMAPTable(format int) int {
  408. cmapPosition := utf.SeekTable("cmap")
  409. utf.skip(2)
  410. cmapTableCount := utf.readUint16()
  411. cidCMAPPosition := 0
  412. for i := 0; i < cmapTableCount; i++ {
  413. system := utf.readUint16()
  414. coded := utf.readUint16()
  415. position := utf.readUint32()
  416. oldReaderPosition := utf.fileReader.readerPosition
  417. if (system == 3 && coded == 1) || system == 0 { // Microsoft, Unicode
  418. format = utf.getUint16(cmapPosition + position)
  419. if format == 4 {
  420. if cidCMAPPosition == 0 {
  421. cidCMAPPosition = cmapPosition + position
  422. }
  423. break
  424. }
  425. }
  426. utf.seek(int(oldReaderPosition))
  427. }
  428. if cidCMAPPosition == 0 {
  429. fmt.Printf("Font does not have cmap for Unicode\n")
  430. return cidCMAPPosition
  431. }
  432. return cidCMAPPosition
  433. }
  434. func (utf *utf8FontFile) parseTables() {
  435. f := utf.parseNAMETable()
  436. utf.parseHEADTable()
  437. n := utf.parseHHEATable()
  438. w := utf.parseOS2Table()
  439. utf.parsePOSTTable(w)
  440. runeCMAPPosition := utf.parseCMAPTable(f)
  441. utf.SeekTable("maxp")
  442. utf.skip(4)
  443. numSymbols := utf.readUint16()
  444. symbolCharDictionary := make(map[int][]int)
  445. charSymbolDictionary := make(map[int]int)
  446. utf.generateSCCSDictionaries(runeCMAPPosition, symbolCharDictionary, charSymbolDictionary)
  447. scale := 1000.0 / float64(utf.fontElementSize)
  448. utf.parseHMTXTable(n, numSymbols, symbolCharDictionary, scale)
  449. }
  450. func (utf *utf8FontFile) generateCMAP() map[int][]int {
  451. cmapPosition := utf.SeekTable("cmap")
  452. utf.skip(2)
  453. cmapTableCount := utf.readUint16()
  454. runeCmapPosition := 0
  455. for i := 0; i < cmapTableCount; i++ {
  456. system := utf.readUint16()
  457. coder := utf.readUint16()
  458. position := utf.readUint32()
  459. oldPosition := utf.fileReader.readerPosition
  460. if (system == 3 && coder == 1) || system == 0 {
  461. format := utf.getUint16(cmapPosition + position)
  462. if format == 4 {
  463. runeCmapPosition = cmapPosition + position
  464. break
  465. }
  466. }
  467. utf.seek(int(oldPosition))
  468. }
  469. if runeCmapPosition == 0 {
  470. fmt.Printf("Font does not have cmap for Unicode\n")
  471. return nil
  472. }
  473. symbolCharDictionary := make(map[int][]int)
  474. charSymbolDictionary := make(map[int]int)
  475. utf.generateSCCSDictionaries(runeCmapPosition, symbolCharDictionary, charSymbolDictionary)
  476. utf.charSymbolDictionary = charSymbolDictionary
  477. return symbolCharDictionary
  478. }
  479. func (utf *utf8FontFile) parseSymbols(usedRunes map[int]int) (map[int]int, map[int]int, map[int]int, []int) {
  480. symbolCollection := map[int]int{0: 0}
  481. charSymbolPairCollection := make(map[int]int)
  482. for _, char := range usedRunes {
  483. if _, OK := utf.charSymbolDictionary[char]; OK {
  484. symbolCollection[utf.charSymbolDictionary[char]] = char
  485. charSymbolPairCollection[char] = utf.charSymbolDictionary[char]
  486. }
  487. utf.LastRune = max(utf.LastRune, char)
  488. }
  489. begin := utf.tableDescriptions["glyf"].position
  490. symbolArray := make(map[int]int)
  491. symbolCollectionKeys := keySortInt(symbolCollection)
  492. symbolCounter := 0
  493. maxRune := 0
  494. for _, oldSymbolIndex := range symbolCollectionKeys {
  495. maxRune = max(maxRune, symbolCollection[oldSymbolIndex])
  496. symbolArray[oldSymbolIndex] = symbolCounter
  497. symbolCounter++
  498. }
  499. charSymbolPairCollectionKeys := keySortInt(charSymbolPairCollection)
  500. runeSymbolPairCollection := make(map[int]int)
  501. for _, runa := range charSymbolPairCollectionKeys {
  502. runeSymbolPairCollection[runa] = symbolArray[charSymbolPairCollection[runa]]
  503. }
  504. utf.CodeSymbolDictionary = runeSymbolPairCollection
  505. symbolCollectionKeys = keySortInt(symbolCollection)
  506. for _, oldSymbolIndex := range symbolCollectionKeys {
  507. _, symbolArray, symbolCollection, symbolCollectionKeys = utf.getSymbols(oldSymbolIndex, &begin, symbolArray, symbolCollection, symbolCollectionKeys)
  508. }
  509. return runeSymbolPairCollection, symbolArray, symbolCollection, symbolCollectionKeys
  510. }
  511. func (utf *utf8FontFile) generateCMAPTable(cidSymbolPairCollection map[int]int, numSymbols int) []byte {
  512. cidSymbolPairCollectionKeys := keySortInt(cidSymbolPairCollection)
  513. cidID := 0
  514. cidArray := make(map[int][]int)
  515. prevCid := -2
  516. prevSymbol := -1
  517. for _, cid := range cidSymbolPairCollectionKeys {
  518. if cid == (prevCid+1) && cidSymbolPairCollection[cid] == (prevSymbol+1) {
  519. if n, OK := cidArray[cidID]; !OK || n == nil {
  520. cidArray[cidID] = make([]int, 0)
  521. }
  522. cidArray[cidID] = append(cidArray[cidID], cidSymbolPairCollection[cid])
  523. } else {
  524. cidID = cid
  525. cidArray[cidID] = make([]int, 0)
  526. cidArray[cidID] = append(cidArray[cidID], cidSymbolPairCollection[cid])
  527. }
  528. prevCid = cid
  529. prevSymbol = cidSymbolPairCollection[cid]
  530. }
  531. cidArrayKeys := keySortArrayRangeMap(cidArray)
  532. segCount := len(cidArray) + 1
  533. searchRange := 1
  534. entrySelector := 0
  535. for searchRange*2 <= segCount {
  536. searchRange = searchRange * 2
  537. entrySelector = entrySelector + 1
  538. }
  539. searchRange = searchRange * 2
  540. rangeShift := segCount*2 - searchRange
  541. length := 16 + (8 * segCount) + (numSymbols + 1)
  542. cmap := []int{0, 1, 3, 1, 0, 12, 4, length, 0, segCount * 2, searchRange, entrySelector, rangeShift}
  543. for _, start := range cidArrayKeys {
  544. endCode := start + (len(cidArray[start]) - 1)
  545. cmap = append(cmap, endCode)
  546. }
  547. cmap = append(cmap, 0xFFFF)
  548. cmap = append(cmap, 0)
  549. for _, cidKey := range cidArrayKeys {
  550. cmap = append(cmap, cidKey)
  551. }
  552. cmap = append(cmap, 0xFFFF)
  553. for _, cidKey := range cidArrayKeys {
  554. idDelta := -(cidKey - cidArray[cidKey][0])
  555. cmap = append(cmap, idDelta)
  556. }
  557. cmap = append(cmap, 1)
  558. for range cidArray {
  559. cmap = append(cmap, 0)
  560. }
  561. cmap = append(cmap, 0)
  562. for _, start := range cidArrayKeys {
  563. for _, glidx := range cidArray[start] {
  564. cmap = append(cmap, glidx)
  565. }
  566. }
  567. cmap = append(cmap, 0)
  568. cmapstr := make([]byte, 0)
  569. for _, cm := range cmap {
  570. cmapstr = append(cmapstr, packUint16(cm)...)
  571. }
  572. return cmapstr
  573. }
  574. //GenerateСutFont fill utf8FontFile from .utf file, only with runes from usedRunes
  575. func (utf *utf8FontFile) GenerateСutFont(usedRunes map[int]int) []byte {
  576. utf.fileReader.readerPosition = 0
  577. utf.symbolPosition = make([]int, 0)
  578. utf.charSymbolDictionary = make(map[int]int)
  579. utf.tableDescriptions = make(map[string]*tableDescription)
  580. utf.outTablesData = make(map[string][]byte)
  581. utf.Ascent = 0
  582. utf.Descent = 0
  583. utf.skip(4)
  584. utf.LastRune = 0
  585. utf.generateTableDescriptions()
  586. utf.SeekTable("head")
  587. utf.skip(50)
  588. LocaFormat := utf.readUint16()
  589. utf.SeekTable("hhea")
  590. utf.skip(34)
  591. metricsCount := utf.readUint16()
  592. oldMetrics := metricsCount
  593. utf.SeekTable("maxp")
  594. utf.skip(4)
  595. numSymbols := utf.readUint16()
  596. symbolCharDictionary := utf.generateCMAP()
  597. if symbolCharDictionary == nil {
  598. return nil
  599. }
  600. utf.parseHMTXTable(metricsCount, numSymbols, symbolCharDictionary, 1.0)
  601. utf.parseLOCATable(LocaFormat, numSymbols)
  602. cidSymbolPairCollection, symbolArray, symbolCollection, symbolCollectionKeys := utf.parseSymbols(usedRunes)
  603. metricsCount = len(symbolCollection)
  604. numSymbols = metricsCount
  605. utf.setOutTable("name", utf.getTableData("name"))
  606. utf.setOutTable("cvt ", utf.getTableData("cvt "))
  607. utf.setOutTable("fpgm", utf.getTableData("fpgm"))
  608. utf.setOutTable("prep", utf.getTableData("prep"))
  609. utf.setOutTable("gasp", utf.getTableData("gasp"))
  610. postTable := utf.getTableData("post")
  611. 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}...)
  612. utf.setOutTable("post", postTable)
  613. delete(cidSymbolPairCollection, 0)
  614. utf.setOutTable("cmap", utf.generateCMAPTable(cidSymbolPairCollection, numSymbols))
  615. symbolData := utf.getTableData("glyf")
  616. offsets := make([]int, 0)
  617. glyfData := make([]byte, 0)
  618. pos := 0
  619. hmtxData := make([]byte, 0)
  620. utf.symbolData = make(map[int]map[string][]int, 0)
  621. for _, originalSymbolIdx := range symbolCollectionKeys {
  622. hm := utf.getMetrics(oldMetrics, originalSymbolIdx)
  623. hmtxData = append(hmtxData, hm...)
  624. offsets = append(offsets, pos)
  625. symbolPos := utf.symbolPosition[originalSymbolIdx]
  626. symbolLen := utf.symbolPosition[originalSymbolIdx+1] - symbolPos
  627. data := symbolData[symbolPos : symbolPos+symbolLen]
  628. var up int
  629. if symbolLen > 0 {
  630. up = unpackUint16(data[0:2])
  631. }
  632. if symbolLen > 2 && (up&(1<<15)) != 0 {
  633. posInSymbol := 10
  634. flags := symbolContinue
  635. nComponentElements := 0
  636. for (flags & symbolContinue) != 0 {
  637. nComponentElements++
  638. up = unpackUint16(data[posInSymbol : posInSymbol+2])
  639. flags = up
  640. up = unpackUint16(data[posInSymbol+2 : posInSymbol+4])
  641. symbolIdx := up
  642. if _, OK := utf.symbolData[originalSymbolIdx]; !OK {
  643. utf.symbolData[originalSymbolIdx] = make(map[string][]int)
  644. }
  645. if _, OK := utf.symbolData[originalSymbolIdx]["compSymbols"]; !OK {
  646. utf.symbolData[originalSymbolIdx]["compSymbols"] = make([]int, 0)
  647. }
  648. utf.symbolData[originalSymbolIdx]["compSymbols"] = append(utf.symbolData[originalSymbolIdx]["compSymbols"], symbolIdx)
  649. data = utf.insertUint16(data, posInSymbol+2, symbolArray[symbolIdx])
  650. posInSymbol += 4
  651. if (flags & symbolWords) != 0 {
  652. posInSymbol += 4
  653. } else {
  654. posInSymbol += 2
  655. }
  656. if (flags & symbolScale) != 0 {
  657. posInSymbol += 2
  658. } else if (flags & symbolAllScale) != 0 {
  659. posInSymbol += 4
  660. } else if (flags & symbol2x2) != 0 {
  661. posInSymbol += 8
  662. }
  663. }
  664. }
  665. glyfData = append(glyfData, data...)
  666. pos += symbolLen
  667. if pos%4 != 0 {
  668. padding := 4 - (pos % 4)
  669. glyfData = append(glyfData, make([]byte, padding)...)
  670. pos += padding
  671. }
  672. }
  673. offsets = append(offsets, pos)
  674. utf.setOutTable("glyf", glyfData)
  675. utf.setOutTable("hmtx", hmtxData)
  676. locaData := make([]byte, 0)
  677. if ((pos + 1) >> 1) > 0xFFFF {
  678. LocaFormat = 1
  679. for _, offset := range offsets {
  680. locaData = append(locaData, packUint32(offset)...)
  681. }
  682. } else {
  683. LocaFormat = 0
  684. for _, offset := range offsets {
  685. locaData = append(locaData, packUint16(offset/2)...)
  686. }
  687. }
  688. utf.setOutTable("loca", locaData)
  689. headData := utf.getTableData("head")
  690. headData = utf.insertUint16(headData, 50, LocaFormat)
  691. utf.setOutTable("head", headData)
  692. hheaData := utf.getTableData("hhea")
  693. hheaData = utf.insertUint16(hheaData, 34, metricsCount)
  694. utf.setOutTable("hhea", hheaData)
  695. maxp := utf.getTableData("maxp")
  696. maxp = utf.insertUint16(maxp, 4, numSymbols)
  697. utf.setOutTable("maxp", maxp)
  698. os2Data := utf.getTableData("OS/2")
  699. utf.setOutTable("OS/2", os2Data)
  700. return utf.assembleTables()
  701. }
  702. 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) {
  703. symbolPos := utf.symbolPosition[originalSymbolIdx]
  704. symbolSize := utf.symbolPosition[originalSymbolIdx+1] - symbolPos
  705. if symbolSize == 0 {
  706. return start, symbolSet, SymbolsCollection, SymbolsCollectionKeys
  707. }
  708. utf.seek(*start + symbolPos)
  709. lineCount := utf.readInt16()
  710. if lineCount < 0 {
  711. utf.skip(8)
  712. flags := symbolContinue
  713. for flags&symbolContinue != 0 {
  714. flags = utf.readUint16()
  715. symbolIndex := utf.readUint16()
  716. if _, OK := symbolSet[symbolIndex]; !OK {
  717. symbolSet[symbolIndex] = len(SymbolsCollection)
  718. SymbolsCollection[symbolIndex] = 1
  719. SymbolsCollectionKeys = append(SymbolsCollectionKeys, symbolIndex)
  720. }
  721. oldPosition, _ := utf.fileReader.seek(0, 1)
  722. _, _, _, SymbolsCollectionKeys = utf.getSymbols(symbolIndex, start, symbolSet, SymbolsCollection, SymbolsCollectionKeys)
  723. utf.seek(int(oldPosition))
  724. if flags&symbolWords != 0 {
  725. utf.skip(4)
  726. } else {
  727. utf.skip(2)
  728. }
  729. if flags&symbolScale != 0 {
  730. utf.skip(2)
  731. } else if flags&symbolAllScale != 0 {
  732. utf.skip(4)
  733. } else if flags&symbol2x2 != 0 {
  734. utf.skip(8)
  735. }
  736. }
  737. }
  738. return start, symbolSet, SymbolsCollection, SymbolsCollectionKeys
  739. }
  740. func (utf *utf8FontFile) parseHMTXTable(numberOfHMetrics, numSymbols int, symbolToChar map[int][]int, scale float64) {
  741. var widths int
  742. start := utf.SeekTable("hmtx")
  743. arrayWidths := 0
  744. var arr []int
  745. utf.CharWidths = make([]int, 256*256)
  746. charCount := 0
  747. arr = unpackUint16Array(utf.getRange(start, numberOfHMetrics*4))
  748. for symbol := 0; symbol < numberOfHMetrics; symbol++ {
  749. arrayWidths = arr[(symbol*2)+1]
  750. if _, OK := symbolToChar[symbol]; OK || symbol == 0 {
  751. if arrayWidths >= (1 << 15) {
  752. arrayWidths = 0
  753. }
  754. if symbol == 0 {
  755. utf.DefaultWidth = scale * float64(arrayWidths)
  756. continue
  757. }
  758. for _, char := range symbolToChar[symbol] {
  759. if char != 0 && char != 65535 {
  760. widths = int(math.Round(scale * float64(arrayWidths)))
  761. if widths == 0 {
  762. widths = 65535
  763. }
  764. if char < 196608 {
  765. utf.CharWidths[char] = widths
  766. charCount++
  767. }
  768. }
  769. }
  770. }
  771. }
  772. diff := numSymbols - numberOfHMetrics
  773. for pos := 0; pos < diff; pos++ {
  774. symbol := pos + numberOfHMetrics
  775. if _, OK := symbolToChar[symbol]; OK {
  776. for _, char := range symbolToChar[symbol] {
  777. if char != 0 && char != 65535 {
  778. widths = int(math.Round(scale * float64(arrayWidths)))
  779. if widths == 0 {
  780. widths = 65535
  781. }
  782. if char < 196608 {
  783. utf.CharWidths[char] = widths
  784. charCount++
  785. }
  786. }
  787. }
  788. }
  789. }
  790. utf.CharWidths[0] = charCount
  791. }
  792. func (utf *utf8FontFile) getMetrics(metricCount, gid int) []byte {
  793. start := utf.SeekTable("hmtx")
  794. var metrics []byte
  795. if gid < metricCount {
  796. utf.seek(start + (gid * 4))
  797. metrics = utf.fileReader.Read(4)
  798. } else {
  799. utf.seek(start + ((metricCount - 1) * 4))
  800. metrics = utf.fileReader.Read(2)
  801. utf.seek(start + (metricCount * 2) + (gid * 2))
  802. metrics = append(metrics, utf.fileReader.Read(2)...)
  803. }
  804. return metrics
  805. }
  806. func (utf *utf8FontFile) parseLOCATable(format, numSymbols int) {
  807. start := utf.SeekTable("loca")
  808. utf.symbolPosition = make([]int, 0)
  809. if format == 0 {
  810. data := utf.getRange(start, (numSymbols*2)+2)
  811. arr := unpackUint16Array(data)
  812. for n := 0; n <= numSymbols; n++ {
  813. utf.symbolPosition = append(utf.symbolPosition, arr[n+1]*2)
  814. }
  815. } else if format == 1 {
  816. data := utf.getRange(start, (numSymbols*4)+4)
  817. arr := unpackUint32Array(data)
  818. for n := 0; n <= numSymbols; n++ {
  819. utf.symbolPosition = append(utf.symbolPosition, arr[n+1])
  820. }
  821. } else {
  822. fmt.Printf("Unknown loca table format %d\n", format)
  823. return
  824. }
  825. }
  826. func (utf *utf8FontFile) generateSCCSDictionaries(runeCmapPosition int, symbolCharDictionary map[int][]int, charSymbolDictionary map[int]int) {
  827. maxRune := 0
  828. utf.seek(runeCmapPosition + 2)
  829. size := utf.readUint16()
  830. rim := runeCmapPosition + size
  831. utf.skip(2)
  832. segmentSize := utf.readUint16() / 2
  833. utf.skip(6)
  834. completers := make([]int, 0)
  835. for i := 0; i < segmentSize; i++ {
  836. completers = append(completers, utf.readUint16())
  837. }
  838. utf.skip(2)
  839. beginners := make([]int, 0)
  840. for i := 0; i < segmentSize; i++ {
  841. beginners = append(beginners, utf.readUint16())
  842. }
  843. sizes := make([]int, 0)
  844. for i := 0; i < segmentSize; i++ {
  845. sizes = append(sizes, int(utf.readInt16()))
  846. }
  847. readerPositionStart := utf.fileReader.readerPosition
  848. positions := make([]int, 0)
  849. for i := 0; i < segmentSize; i++ {
  850. positions = append(positions, utf.readUint16())
  851. }
  852. var symbol int
  853. for n := 0; n < segmentSize; n++ {
  854. completePosition := completers[n] + 1
  855. for char := beginners[n]; char < completePosition; char++ {
  856. if positions[n] == 0 {
  857. symbol = (char + sizes[n]) & 0xFFFF
  858. } else {
  859. position := (char-beginners[n])*2 + positions[n]
  860. position = int(readerPositionStart) + 2*n + position
  861. if position >= rim {
  862. symbol = 0
  863. } else {
  864. symbol = utf.getUint16(position)
  865. if symbol != 0 {
  866. symbol = (symbol + sizes[n]) & 0xFFFF
  867. }
  868. }
  869. }
  870. charSymbolDictionary[char] = symbol
  871. if char < 196608 {
  872. maxRune = max(char, maxRune)
  873. }
  874. symbolCharDictionary[symbol] = append(symbolCharDictionary[symbol], char)
  875. }
  876. }
  877. }
  878. func max(i, n int) int {
  879. if n > i {
  880. return n
  881. }
  882. return i
  883. }
  884. func (utf *utf8FontFile) assembleTables() []byte {
  885. answer := make([]byte, 0)
  886. tablesCount := len(utf.outTablesData)
  887. findSize := 1
  888. writer := 0
  889. for findSize*2 <= tablesCount {
  890. findSize = findSize * 2
  891. writer = writer + 1
  892. }
  893. findSize = findSize * 16
  894. rOffset := tablesCount*16 - findSize
  895. answer = append(answer, packHeader(0x00010000, tablesCount, findSize, writer, rOffset)...)
  896. tables := utf.outTablesData
  897. tablesNames := keySortStrings(tables)
  898. offset := 12 + tablesCount*16
  899. begin := 0
  900. for _, name := range tablesNames {
  901. if name == "head" {
  902. begin = offset
  903. }
  904. answer = append(answer, []byte(name)...)
  905. checksum := utf.generateChecksum(tables[name])
  906. answer = append(answer, pack2Uint16(checksum[0], checksum[1])...)
  907. answer = append(answer, pack2Uint32(offset, len(tables[name]))...)
  908. paddedLength := (len(tables[name]) + 3) &^ 3
  909. offset = offset + paddedLength
  910. }
  911. for _, key := range tablesNames {
  912. data := tables[key]
  913. data = append(data, []byte{0, 0, 0}...)
  914. answer = append(answer, data[:(len(data)&^3)]...)
  915. }
  916. checksum := utf.generateChecksum([]byte(answer))
  917. checksum = utf.calcInt32([]int{0xB1B0, 0xAFBA}, checksum)
  918. answer = utf.splice(answer, (begin + 8), pack2Uint16(checksum[0], checksum[1]))
  919. return answer
  920. }
  921. func unpackUint16Array(data []byte) []int {
  922. answer := make([]int, 1)
  923. r := bytes.NewReader(data)
  924. bs := make([]byte, 2)
  925. var e error
  926. var c int
  927. c, e = r.Read(bs)
  928. for e == nil && c > 0 {
  929. answer = append(answer, int(binary.BigEndian.Uint16(bs)))
  930. c, e = r.Read(bs)
  931. }
  932. return answer
  933. }
  934. func unpackUint32Array(data []byte) []int {
  935. answer := make([]int, 1)
  936. r := bytes.NewReader(data)
  937. bs := make([]byte, 4)
  938. var e error
  939. var c int
  940. c, e = r.Read(bs)
  941. for e == nil && c > 0 {
  942. answer = append(answer, int(binary.BigEndian.Uint32(bs)))
  943. c, e = r.Read(bs)
  944. }
  945. return answer
  946. }
  947. func unpackUint16(data []byte) int {
  948. return int(binary.BigEndian.Uint16(data))
  949. }
  950. func packHeader(N uint32, n1, n2, n3, n4 int) []byte {
  951. answer := make([]byte, 0)
  952. bs4 := make([]byte, 4)
  953. binary.BigEndian.PutUint32(bs4, N)
  954. answer = append(answer, bs4...)
  955. bs := make([]byte, 2)
  956. binary.BigEndian.PutUint16(bs, uint16(n1))
  957. answer = append(answer, bs...)
  958. binary.BigEndian.PutUint16(bs, uint16(n2))
  959. answer = append(answer, bs...)
  960. binary.BigEndian.PutUint16(bs, uint16(n3))
  961. answer = append(answer, bs...)
  962. binary.BigEndian.PutUint16(bs, uint16(n4))
  963. answer = append(answer, bs...)
  964. return answer
  965. }
  966. func pack2Uint16(n1, n2 int) []byte {
  967. answer := make([]byte, 0)
  968. bs := make([]byte, 2)
  969. binary.BigEndian.PutUint16(bs, uint16(n1))
  970. answer = append(answer, bs...)
  971. binary.BigEndian.PutUint16(bs, uint16(n2))
  972. answer = append(answer, bs...)
  973. return answer
  974. }
  975. func pack2Uint32(n1, n2 int) []byte {
  976. answer := make([]byte, 0)
  977. bs := make([]byte, 4)
  978. binary.BigEndian.PutUint32(bs, uint32(n1))
  979. answer = append(answer, bs...)
  980. binary.BigEndian.PutUint32(bs, uint32(n2))
  981. answer = append(answer, bs...)
  982. return answer
  983. }
  984. func packUint32(n1 int) []byte {
  985. bs := make([]byte, 4)
  986. binary.BigEndian.PutUint32(bs, uint32(n1))
  987. return bs
  988. }
  989. func packUint16(n1 int) []byte {
  990. bs := make([]byte, 2)
  991. binary.BigEndian.PutUint16(bs, uint16(n1))
  992. return bs
  993. }
  994. func keySortStrings(s map[string][]byte) []string {
  995. keys := make([]string, len(s))
  996. i := 0
  997. for key := range s {
  998. keys[i] = key
  999. i++
  1000. }
  1001. sort.Strings(keys)
  1002. return keys
  1003. }
  1004. func keySortInt(s map[int]int) []int {
  1005. keys := make([]int, len(s))
  1006. i := 0
  1007. for key := range s {
  1008. keys[i] = key
  1009. i++
  1010. }
  1011. sort.Ints(keys)
  1012. return keys
  1013. }
  1014. func keySortArrayRangeMap(s map[int][]int) []int {
  1015. keys := make([]int, len(s))
  1016. i := 0
  1017. for key := range s {
  1018. keys[i] = key
  1019. i++
  1020. }
  1021. sort.Ints(keys)
  1022. return keys
  1023. }
  1024. // UTF8CutFont is a utility function that generates a TrueType font composed
  1025. // only of the runes included in cutset. The rune glyphs are copied from This
  1026. // function is demonstrated in ExampleUTF8CutFont().
  1027. func UTF8CutFont(inBuf []byte, cutset string) (outBuf []byte) {
  1028. f := newUTF8Font(&fileReader{readerPosition: 0, array: inBuf})
  1029. runes := map[int]int{}
  1030. for i, r := range cutset {
  1031. runes[i] = int(r)
  1032. }
  1033. outBuf = f.GenerateСutFont(runes)
  1034. return
  1035. }