Browse Source

Add kerning

master
Macoy Madson 1 year ago
parent
commit
254c1728cd
  1. 2
      data/DrivingCodeWithData.cakedata
  2. 50
      src/FontAtlas.cake
  3. 22
      src/Presentation.cake

2
data/DrivingCodeWithData.cakedata

@ -206,4 +206,6 @@ is hard.
That doesn't mean it shouldn't be done, but does
mean it should be done carefully.")
(slide-data :heading "In conclusion"
:body "Using data to drive code is generally useful.")
(slide-data :heading "Questions?"))

50
src/FontAtlas.cake

@ -1,3 +1,5 @@
;; FontAtlas.cake: Cache FreeType-rendered fonts into a font atlas and kerning table
;; TODO: Support UTF-8 by using non char-sized keys
(import
;; GameLib
"FreeType.cake" "Dictionary.cake")
@ -13,10 +15,17 @@
height uint16_t
to-origin-left int16_t
to-origin-top int16_t
advance-x uint16_t)
advance-x int16_t)
(defstruct kerning-entry
key uint16_t ;; first character << 8, second character
x int16_t
;; Unused
y int16_t)
(defstruct font-atlas
glyph-lookup-table (* glyph-entry) ;; dictionary
kerning-lookup-table (* kerning-entry) ;; dictionary
pixel-buffer (* (unsigned char)) ;; malloc'd
width uint16_t
height uint16_t
@ -28,6 +37,11 @@
(dict-free (path font-atlas-to-free > glyph-lookup-table))
(free (path font-atlas-to-free > pixel-buffer)))
(defun font-atlas-make-character-pair (character-a char
character-b char
&return uint16_t)
(return (bit-or (bit-<< character-a 8) character-b)))
;; Returns 0 for success or anything else for failure
(defun build-font-atlas (font-face (* (const (unsigned char)))
font-face-size (unsigned int)
@ -161,4 +175,38 @@
;; Wrapping happens after we know what the next glyph's dimensions are
(set atlas-write-x (+ atlas-write-x num-columns))))
;; Build kerning lookup table
(each-in-array ranges-to-render range-index-a
(var range-a (* ascii-glyph-range) (addr (at range-index-a ranges-to-render)))
(each-in-range (- (+ 1 (path range-a > end-character-inclusive)) (path range-a > start-character))
character-offset-from-start
(var character-a char (+ character-offset-from-start (path range-a > start-character)))
(var glyph-index-a int (FT_Get_Char_Index typeface character-a))
(unless glyph-index-a
(continue))
(each-in-array ranges-to-render range-index-b
(var range-b (* ascii-glyph-range) (addr (at range-index-b ranges-to-render)))
(each-in-range (- (+ 1 (path range-b > end-character-inclusive)) (path range-b > start-character))
character-offset-from-start
(var character-b char (+ character-offset-from-start (path range-b > start-character)))
;; If this is slow, it might make sense to cache it in the outer loop
(var glyph-index-b int (FT_Get_Char_Index typeface character-b))
(unless glyph-index-b
(continue))
(var kerning FT_Vector)
(set result (FT_Get_Kerning typeface glyph-index-a glyph-index-b
FT_KERNING_DEFAULT (addr kerning)))
(freetype-check-result-or-return result "Getting kerning value")
(when (or (field kerning x) (field kerning y))
(var new-kerning-entry kerning-entry (array 0))
(var character-pair uint16_t (font-atlas-make-character-pair
character-a character-b))
(set (field new-kerning-entry key) character-pair)
(set (field new-kerning-entry x) (bit->> (field kerning x) 6))
(set (field new-kerning-entry y) (bit->> (field kerning y) 6))
(dict-set-struct (path font-atlas-out > kerning-lookup-table)
new-kerning-entry))))))
(return 0))

22
src/Presentation.cake

@ -13,6 +13,8 @@
&with-decls "<stdint.h>")
(var s-draw-atlases bool false)
(var s-enable-kerning bool true) ;; F2
(var s-enable-debug-overlay bool false) ;; F1
(bundle-file s-start-ubuntu-regular-font s-end-ubuntu-regular-font
(unsigned char) "data/Fonts/Ubuntu-R.ttf")
@ -31,6 +33,9 @@
(array SDL_SCANCODE_BACKSPACE)
(array SDL_SCANCODE_PAGEUP))
(define-keybind s-toggle-kerning-keybind (array SDL_SCANCODE_F2))
(define-keybind s-toggle-debug-overlay-keybind (array SDL_SCANCODE_F1))
(var s-key-states sdl-key-states (array 0))
(defmacro preslog (format string &optional &rest arguments any)
@ -187,7 +192,15 @@
(path glyph > height)))
(SDL_RenderCopy renderer font-texture
(addr source-rectangle) (addr destination-rectangle))
(set write-x (+ write-x (path glyph > advance-x)))))
(set write-x (+ write-x (path glyph > advance-x)))
(when (and s-enable-kerning (+ 1 current-char))
(var character-pair uint16_t (font-atlas-make-character-pair
(deref current-char) (at 1 current-char)))
(var kerning (* kerning-entry)
(dict-ptr-at (path font > kerning-lookup-table) character-pair))
(when kerning
(set write-x (+ write-x (path kerning > x)))))))
(defun-local make-font-atlas-and-texture (renderer (* SDL_Renderer)
font-atlas-out (* font-atlas) font-texture-out (* (* SDL_Texture))
@ -375,6 +388,11 @@
(when (< current-slide-index 0)
(set current-slide-index 0)))
(when (keybind-tapped (addr s-toggle-kerning-keybind) (addr s-key-states))
(set s-enable-kerning (not s-enable-kerning)))
(when (keybind-tapped (addr s-toggle-debug-overlay-keybind) (addr s-key-states))
(set s-enable-debug-overlay (not s-enable-debug-overlay)))
(SDL_SetRenderDrawColor renderer 17 17 17 255)
(SDL_RenderClear renderer)
@ -427,7 +445,7 @@
(+ text-x (/ window-width 7)) (/ window-height 4)
(path slide > body)))
(scope
(when s-enable-debug-overlay
(var buffer ([] 256 char) (array 0))
(var mouse-x int 0)
(var mouse-y int 0)

Loading…
Cancel
Save