font.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. // Font extension
  2. package al
  3. /*
  4. #cgo pkg-config: allegro_font-5
  5. #cgo CFLAGS: -I/usr/local/include
  6. #cgo linux LDFLAGS: -lc_nonshared
  7. #include <stdlib.h>
  8. #include <allegro5/allegro.h>
  9. #include <allegro5/allegro_font.h>
  10. #include "helpers.h"
  11. */
  12. import "C"
  13. import "runtime"
  14. import "unsafe"
  15. import "fmt"
  16. type Font struct {
  17. handle *C.ALLEGRO_FONT
  18. }
  19. const (
  20. ALIGN_LEFT = C.ALLEGRO_ALIGN_LEFT
  21. ALIGN_CENTRE = C.ALLEGRO_ALIGN_CENTRE
  22. ALIGN_CENTER = C.ALLEGRO_ALIGN_CENTER
  23. ALIGN_RIGHT = C.ALLEGRO_ALIGN_RIGHT
  24. ALIGN_INTEGER = C.ALLEGRO_ALIGN_INTEGER
  25. )
  26. // Converts a font to it's underlying C pointer
  27. func (self *Font) toC() *C.ALLEGRO_FONT {
  28. return (*C.ALLEGRO_FONT)(self.handle)
  29. }
  30. // Destroys the font.
  31. func (self *Font) Destroy() {
  32. if self.handle != nil {
  33. C.al_destroy_font(self.toC())
  34. }
  35. self.handle = nil
  36. }
  37. // Wraps a C font into a go font
  38. func wrapFontRaw(data *C.ALLEGRO_FONT) *Font {
  39. if data == nil {
  40. return nil
  41. }
  42. return &Font{data}
  43. }
  44. // Sets up a finalizer for this Font that calls Destroy()
  45. func (self *Font) SetDestroyFinalizer() *Font {
  46. if self != nil {
  47. runtime.SetFinalizer(self, func(me *Font) { me.Destroy() })
  48. }
  49. return self
  50. }
  51. // Wraps a C voice into a go mixer and sets up a finalizer that calls Destroy()
  52. func wrapFont(data *C.ALLEGRO_FONT) *Font {
  53. self := wrapFontRaw(data)
  54. return self.SetDestroyFinalizer()
  55. }
  56. /*
  57. TODO:
  58. ALLEGRO_FONT_FUNC(bool, al_register_font_loader, (const char *ext, ALLEGRO_FONT *(*load)(const char *filename, int size, int flags)));
  59. */
  60. func loadBitmapFont(filename string) *C.ALLEGRO_FONT {
  61. cfilename := cstr(filename)
  62. defer cstrFree(cfilename)
  63. return C.al_load_bitmap_font(cfilename)
  64. }
  65. func loadBitmapFontFlags(filename string, flags int) *C.ALLEGRO_FONT {
  66. cfilename := cstr(filename)
  67. defer cstrFree(cfilename)
  68. return C.al_load_bitmap_font_flags(cfilename, C.int(flags))
  69. }
  70. func loadFont(filename string, size, flags int) *C.ALLEGRO_FONT {
  71. cfilename := cstr(filename)
  72. defer cstrFree(cfilename)
  73. return C.al_load_font(cfilename, C.int(size), C.int(flags))
  74. }
  75. func (self *Bitmap) grabFont(ranges []int) *C.ALLEGRO_FONT {
  76. cn := C.int(len(ranges) / 2)
  77. cranges := (*C.int)(unsafe.Pointer(&ranges[0]))
  78. return C.al_grab_font_from_bitmap(self.handle, cn, cranges)
  79. }
  80. func createBuiltinFont() *C.ALLEGRO_FONT {
  81. return C.al_create_builtin_font()
  82. }
  83. // Loads a font from the give bitmap filename
  84. func LoadBitmapFontRaw(filename string) *Font {
  85. return wrapFontRaw(loadBitmapFont(filename))
  86. }
  87. // Loads a font from the give bitmap filename
  88. func LoadBitmapFont(filename string) *Font {
  89. return LoadBitmapFontRaw(filename).SetDestroyFinalizer()
  90. }
  91. // Loads a font from the give bitmap filename with the given flags
  92. func LoadBitmapFontFlagsRaw(filename string, flags int) *Font {
  93. return wrapFontRaw(loadBitmapFontFlags(filename, flags))
  94. }
  95. // Loads a font from the give bitmap filename with the given flags
  96. func LoadBitmapFontFlags(filename string, flags int) *Font {
  97. return LoadBitmapFontFlagsRaw(filename, flags).SetDestroyFinalizer()
  98. }
  99. // Loads a font from the give font filename with the given size and flags.
  100. func LoadFontRaw(filename string, size, flags int) *Font {
  101. return wrapFontRaw(loadFont(filename, size, flags))
  102. }
  103. // Loads a font from the give font filename with the given size and flags.
  104. func LoadFont(filename string, size, flags int) *Font {
  105. return LoadFontRaw(filename, size, flags).SetDestroyFinalizer()
  106. }
  107. // Converts this bitmap into a font
  108. func (self *Bitmap) GrabFontRaw(ranges []int) *Font {
  109. return wrapFontRaw(self.grabFont(ranges))
  110. }
  111. // Converts this bitmap into a font
  112. func (self *Bitmap) GrabFont(ranges []int) *Font {
  113. return self.GrabFontRaw(ranges).SetDestroyFinalizer()
  114. }
  115. // Creates a builtin font. It must be Destroy() when done using it just like any other font.
  116. func CreateBuiltinFontRaw() *Font {
  117. return wrapFontRaw(createBuiltinFont())
  118. }
  119. // Creates a builtin font. Has a finalizer set that will call Destroy().
  120. func CreateBuiltinFont() *Font {
  121. return wrapFont(createBuiltinFont())
  122. }
  123. // Ustr basics
  124. type Ustr struct {
  125. handle *C.ALLEGRO_USTR
  126. }
  127. // Converts a USTR to it's underlying C pointer
  128. func (self *Ustr) toC() *C.ALLEGRO_USTR {
  129. return (*C.ALLEGRO_USTR)(self.handle)
  130. }
  131. // Destroys the USTR.
  132. func (self *Ustr) Destroy() {
  133. if self.handle != nil {
  134. C.al_ustr_free(self.toC())
  135. }
  136. self.handle = nil
  137. }
  138. // Wraps a C USTR into a go font
  139. func wrapUstrRaw(data *C.ALLEGRO_USTR) *Ustr {
  140. if data == nil {
  141. return nil
  142. }
  143. return &Ustr{data}
  144. }
  145. // Sets up a finalizer for this Ustr that calls Destroy()
  146. func (self *Ustr) SetDestroyFinalizer() *Ustr {
  147. if self != nil {
  148. runtime.SetFinalizer(self, func(me *Ustr) { me.Destroy() })
  149. }
  150. return self
  151. }
  152. // Wraps a C Ustr into go Ustr and sets up a finalizer that calls Destroy()
  153. func wrapUstr(data *C.ALLEGRO_USTR) *Ustr {
  154. self := wrapUstrRaw(data)
  155. return self.SetDestroyFinalizer()
  156. }
  157. // Draws an allegro UTF8 string
  158. func (font *Font) DrawUstr(color Color, x, y float32, flags int, ustr *Ustr) {
  159. C.al_draw_ustr(font.toC(), color.toC(), C.float(x), C.float(y), C.int(flags), ustr.toC())
  160. }
  161. // Draws a C string
  162. func (font *Font) DrawText(color Color, x, y float32, flags int, text string) {
  163. ctext := cstr(text)
  164. defer cstrFree(ctext)
  165. C.al_draw_text(font.toC(), color.toC(), C.float(x), C.float(y), C.int(flags), ctext)
  166. }
  167. // Draws an allegro UTF8 string, justified
  168. func (font *Font) DrawJustifiedUstr(color Color, x1, x2, y, diff float32, flags int, ustr *Ustr) {
  169. C.al_draw_justified_ustr(font.toC(), color.toC(), cf(x1), cf(x2), cf(y), cf(diff), ci(flags), ustr.toC())
  170. }
  171. // Draws a C string, justified
  172. func (font *Font) DrawJustifiedText(color Color, x1, x2, y, diff float32, flags int, text string) {
  173. ctext := cstr(text)
  174. defer cstrFree(ctext)
  175. C.al_draw_justified_text(font.toC(), color.toC(), cf(x1), cf(x2), cf(y), cf(diff), ci(flags), ctext)
  176. }
  177. // Formats a single line of text
  178. func (font * Font) DrawTextf(color Color, x, y float32, flags int,
  179. format string, args ...interface{}) {
  180. text := fmt.Sprintf(format, args...)
  181. font.DrawText(color, x, y, flags, text)
  182. }
  183. // Formats justified text.
  184. func (font * Font) DrawJustifiedTextf(color Color, x1, x2, y, diff float32, flags int,
  185. format string, args ...interface{}) {
  186. text := fmt.Sprintf(format, args...)
  187. font.DrawJustifiedText(color, x1, x2, y, diff, flags, text)
  188. }
  189. // Gets the width of a UTF8 encoded string for this font.
  190. func (font *Font) UstrWidth(ustr *Ustr) int {
  191. return int(C.al_get_ustr_width(font.toC(), ustr.toC()))
  192. }
  193. // Gets the width of a string for this font.
  194. func (font *Font) TextWidth(text string) int {
  195. ctext := cstr(text)
  196. defer cstrFree(ctext)
  197. return int(C.al_get_text_width(font.toC(), ctext))
  198. }
  199. // Gets the line height of this font.
  200. func (font *Font) LineHeight() int {
  201. return int(C.al_get_font_line_height(font.toC()))
  202. }
  203. // Gets the ascent of this font.
  204. func (font *Font) Ascent() int {
  205. return int(C.al_get_font_ascent(font.toC()))
  206. }
  207. // Gets the descent of this font.
  208. func (font *Font) Descent() int {
  209. return int(C.al_get_font_descent(font.toC()))
  210. }
  211. // Gets the dimension of a UTF-8 text in this font.
  212. func (font *Font) UstrDimension(ustr *Ustr) (bbx, bby, bbw, bbh int) {
  213. var cbbx, cbby, cbbw, cbbh C.int
  214. C.al_get_ustr_dimensions(font.toC(), ustr.toC(), &cbbx, &cbby, &cbbw, &cbbh)
  215. return int(cbbx), int(cbby), int(cbbw), int(cbbh)
  216. }
  217. // Gets the dimension of a text in this font.
  218. func (font *Font) TextDimension(text string) (bbx, bby, bbw, bbh int) {
  219. ctext := cstr(text)
  220. defer cstrFree(ctext)
  221. var cbbx, cbby, cbbw, cbbh C.int
  222. C.al_get_text_dimensions(font.toC(), ctext, &cbbx, &cbby, &cbbw, &cbbh)
  223. return int(cbbx), int(cbby), int(cbbw), int(cbbh)
  224. }
  225. // Initializes the font addon
  226. func InitFontAddon() {
  227. C.al_init_font_addon()
  228. }
  229. // Close the font addon
  230. func ShutdownFontAddon() {
  231. C.al_init_font_addon()
  232. }
  233. // Gets the allegro font addon version
  234. func GetAllegroFontVersion() uint32 {
  235. return (uint32)(C.al_get_allegro_font_version())
  236. }
  237. // Gets the range of characters supported by the font
  238. func (font *Font) Ranges() (ranges []int, count int) {
  239. count = int(C.al_get_font_ranges(font.toC(), 0, nil))
  240. ranges = make([]int, count * 2)
  241. isize := C.sizeof_int
  242. cranges := C.malloc(C.size_t(isize * count * 2))
  243. defer C.free(cranges)
  244. C.al_get_font_ranges(font.toC(), ci(count), (*C.int)(cranges))
  245. for i := 0 ; i < count * 2; i++ {
  246. ranges[i] = int(*(*C.int)(unsafe.Pointer(uintptr(cranges) + uintptr(i * isize))))
  247. }
  248. return ranges, count
  249. }
  250. // Draws a C string text over multiple lines
  251. func (font *Font) DrawMultilineText(color Color, x, y, max_width, line_height float32,
  252. flags int, text string) {
  253. ctext := cstr(text)
  254. defer cstrFree(ctext)
  255. C.al_draw_multiline_text(font.toC(), color.toC(), C.float(x), C.float(y),
  256. C.float(max_width), C.float(line_height), C.int(flags), ctext)
  257. }
  258. // Formats text over multiple lines
  259. func (font * Font) DrawMultilineTextf(color Color, x, y, max_width, line_height float32, flags int,
  260. format string, args ...interface{}) {
  261. text := fmt.Sprintf(format, args...)
  262. font.DrawMultilineText(color, x, y, max_width, line_height, flags, text)
  263. }
  264. func (font * Font) SetFallbackFont(fallback * Font) {
  265. C.al_set_fallback_font(font.toC(), fallback.toC())
  266. }
  267. func (font * Font) FallbackFont() (* Font) {
  268. return wrapFontRaw(C.al_get_fallback_font(font.toC()))
  269. }
  270. // Glyph per glyph drawing
  271. // Draws an individual glyph from a font
  272. func (font * Font) DrawGlyph(color Color, x, y float32, codepoint int) {
  273. C.al_draw_glyph(font.toC(), color.toC(), C.float(x), C.float(y), C.int(codepoint))
  274. }
  275. // Gets the width of the glyph for the font
  276. func (font * Font) GlyphWidth(color Color, codepoint int) int {
  277. return int(C.al_get_glyph_width(font.toC(), C.int(codepoint)))
  278. }
  279. // Gets the advance between two code points for the font
  280. func (font * Font) GlyphAdvance(color Color, cp1, cp2 int) int {
  281. return int(C.al_get_glyph_advance(font.toC(), C.int(cp1), C.int(cp2)))
  282. }
  283. // Gets the dimensions of the glyph for the font
  284. func (font * Font) GlyphDimensions(color Color, cp int) (ok bool, bbx, bby, bbw, bbh int) {
  285. var cbbx, cbby, cbbw, cbbh C.int
  286. ok = bool(C.al_get_glyph_dimensions(font.toC(), C.int(cp), &cbbx, &cbby, &cbbw, &cbbh))
  287. bbx = int(cbbx)
  288. bby = int(cbby)
  289. bbw = int(cbbw)
  290. bbh = int(cbbh)
  291. return ok, bbx, bby, bbw, bbh
  292. }
  293. /*
  294. The fallback is a hassle, might be better to do this in Go.
  295. ALLEGRO_FONT_FUNC(void, al_do_multiline_text, (const ALLEGRO_FONT *font,
  296. float max_width, const char *text,
  297. bool (*cb)(int line_num, const char *line, int size, void *extra),
  298. void *extra));
  299. */