github.com/danbrough/mobile@v0.0.3-beta03/exp/font/font_darwin.go (about)

     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  
     5  package font
     6  
     7  /*
     8  #cgo darwin LDFLAGS: -framework CoreFoundation -framework CoreText
     9  #include <CoreFoundation/CFArray.h>
    10  #include <CoreFoundation/CFBase.h>
    11  #include <CoreFoundation/CFData.h>
    12  #include <CoreText/CTFont.h>
    13  */
    14  import "C"
    15  import "unsafe"
    16  
    17  func buildFont(f C.CTFontRef) []byte {
    18  	ctags := C.CTFontCopyAvailableTables(f, C.kCTFontTableOptionExcludeSynthetic)
    19  	tagsCount := C.CFArrayGetCount(ctags)
    20  
    21  	var tags []uint32
    22  	var dataRefs []C.CFDataRef
    23  	var dataLens []uint32
    24  
    25  	for i := C.CFIndex(0); i < tagsCount; i++ {
    26  		tag := (C.CTFontTableTag)((uintptr)(C.CFArrayGetValueAtIndex(ctags, i)))
    27  		dataRef := C.CTFontCopyTable(f, tag, 0) // retained
    28  		tags = append(tags, uint32(tag))
    29  		dataRefs = append(dataRefs, dataRef)
    30  		dataLens = append(dataLens, uint32(C.CFDataGetLength(dataRef)))
    31  	}
    32  
    33  	totalLen := 0
    34  	for _, l := range dataLens {
    35  		totalLen += int(l)
    36  	}
    37  
    38  	// Big-endian output.
    39  	buf := make([]byte, 0, 12+16*len(tags)+totalLen)
    40  	write16 := func(x uint16) { buf = append(buf, byte(x>>8), byte(x)) }
    41  	write32 := func(x uint32) { buf = append(buf, byte(x>>24), byte(x>>16), byte(x>>8), byte(x)) }
    42  
    43  	// File format description: http://www.microsoft.com/typography/otspec/otff.htm
    44  	write32(0x00010000)        // version 1.0
    45  	write16(uint16(len(tags))) // numTables
    46  	write16(0)                 // searchRange
    47  	write16(0)                 // entrySelector
    48  	write16(0)                 // rangeShift
    49  
    50  	// Table tags, includes offsets into following data segments.
    51  	offset := uint32(12 + 16*len(tags)) // offset starts after table tags
    52  	for i, tag := range tags {
    53  		write32(tag)
    54  		write32(0)
    55  		write32(offset)
    56  		write32(dataLens[i])
    57  		offset += dataLens[i]
    58  	}
    59  
    60  	// Data segments.
    61  	for i, dataRef := range dataRefs {
    62  		data := (*[1<<31 - 2]byte)((unsafe.Pointer)(C.CFDataGetBytePtr(dataRef)))[:dataLens[i]]
    63  		buf = append(buf, data...)
    64  		C.CFRelease(C.CFTypeRef(dataRef))
    65  	}
    66  
    67  	return buf
    68  }
    69  
    70  func buildDefault() ([]byte, error) {
    71  	return buildFont(C.CTFontCreateUIFontForLanguage(C.kCTFontSystemFontType, 0, 0)), nil
    72  }
    73  
    74  func buildMonospace() ([]byte, error) {
    75  	return buildFont(C.CTFontCreateUIFontForLanguage(C.kCTFontUserFixedPitchFontType, 0, 0)), nil
    76  }