font_darwin.go 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // Copyright 2014 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package font
  5. /*
  6. #cgo darwin LDFLAGS: -framework CoreFoundation -framework CoreText
  7. #include <CoreFoundation/CFArray.h>
  8. #include <CoreFoundation/CFBase.h>
  9. #include <CoreFoundation/CFData.h>
  10. #include <CoreText/CTFont.h>
  11. */
  12. import "C"
  13. import "unsafe"
  14. func buildFont(f C.CTFontRef) []byte {
  15. ctags := C.CTFontCopyAvailableTables(f, C.kCTFontTableOptionExcludeSynthetic)
  16. tagsCount := C.CFArrayGetCount(ctags)
  17. var tags []uint32
  18. var dataRefs []C.CFDataRef
  19. var dataLens []uint32
  20. for i := C.CFIndex(0); i < tagsCount; i++ {
  21. tag := (C.CTFontTableTag)((uintptr)(C.CFArrayGetValueAtIndex(ctags, i)))
  22. dataRef := C.CTFontCopyTable(f, tag, 0) // retained
  23. tags = append(tags, uint32(tag))
  24. dataRefs = append(dataRefs, dataRef)
  25. dataLens = append(dataLens, uint32(C.CFDataGetLength(dataRef)))
  26. }
  27. totalLen := 0
  28. for _, l := range dataLens {
  29. totalLen += int(l)
  30. }
  31. // Big-endian output.
  32. buf := make([]byte, 0, 12+16*len(tags)+totalLen)
  33. write16 := func(x uint16) { buf = append(buf, byte(x>>8), byte(x)) }
  34. write32 := func(x uint32) { buf = append(buf, byte(x>>24), byte(x>>16), byte(x>>8), byte(x)) }
  35. // File format description: http://www.microsoft.com/typography/otspec/otff.htm
  36. write32(0x00010000) // version 1.0
  37. write16(uint16(len(tags))) // numTables
  38. write16(0) // searchRange
  39. write16(0) // entrySelector
  40. write16(0) // rangeShift
  41. // Table tags, includes offsets into following data segments.
  42. offset := uint32(12 + 16*len(tags)) // offset starts after table tags
  43. for i, tag := range tags {
  44. write32(tag)
  45. write32(0)
  46. write32(offset)
  47. write32(dataLens[i])
  48. offset += dataLens[i]
  49. }
  50. // Data segments.
  51. for i, dataRef := range dataRefs {
  52. data := (*[1<<31 - 2]byte)((unsafe.Pointer)(C.CFDataGetBytePtr(dataRef)))[:dataLens[i]]
  53. buf = append(buf, data...)
  54. C.CFRelease(C.CFTypeRef(dataRef))
  55. }
  56. return buf
  57. }
  58. func buildDefault() ([]byte, error) {
  59. return buildFont(C.CTFontCreateUIFontForLanguage(C.kCTFontSystemFontType, 0, 0)), nil
  60. }
  61. func buildMonospace() ([]byte, error) {
  62. return buildFont(C.CTFontCreateUIFontForLanguage(C.kCTFontUserFixedPitchFontType, 0, 0)), nil
  63. }