font.go 11 KB

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