AtlatestRepositorysigil-freetype
sigil-freetype / tree / srcfreetype.sgl
1
;;; (freetype) — FreeType font loading bindings for Sigil2
;;;3
;;; Pure-Scheme bindings using the dynamic FFI. No native C code required.4
;;; Requires libfreetype.so / libfreetype.dylib to be installed on the system.6
(define-library (freetype)7
(import (sigil core)8
(sigil ffi)9
(sigil math))11
(export12
;; Library handle13
ft-lib15
;; Constants — Load flags16
FT_LOAD_DEFAULT17
FT_LOAD_NO_SCALE18
FT_LOAD_NO_HINTING19
FT_LOAD_RENDER20
FT_LOAD_NO_BITMAP21
FT_LOAD_VERTICAL_LAYOUT22
FT_LOAD_FORCE_AUTOHINT23
FT_LOAD_NO_AUTOHINT24
FT_LOAD_COLOR26
;; Constants — Face flags27
FT_FACE_FLAG_SCALABLE28
FT_FACE_FLAG_FIXED_SIZES29
FT_FACE_FLAG_FIXED_WIDTH30
FT_FACE_FLAG_HORIZONTAL31
FT_FACE_FLAG_VERTICAL32
FT_FACE_FLAG_KERNING34
;; Struct layouts35
ft-face-layout36
ft-glyph-slot-layout38
;; Library lifecycle39
ft-init40
ft-done-freetype42
;; Face lifecycle43
ft-new-face44
ft-done-face46
;; Face configuration47
ft-set-char-size48
ft-set-pixel-sizes50
;; Glyph loading51
ft-get-char-index52
ft-load-glyph53
ft-load-char55
;; Face property accessors56
ft-face-family-name57
ft-face-style-name58
ft-face-num-glyphs59
ft-face-flags60
ft-face-has-flag?61
ft-face-units-per-em62
ft-face-ascender63
ft-face-descender64
ft-face-height65
ft-face-glyph67
;; Glyph metrics68
ft-glyph-metrics)70
(begin72
;; ============================================================73
;; Library Loading74
;; ============================================================76
(define ft-lib (c-library "libfreetype"))78
;; ============================================================79
;; Constants — Load Flags80
;; ============================================================82
(define FT_LOAD_DEFAULT 0)83
(define FT_LOAD_NO_SCALE 1)84
(define FT_LOAD_NO_HINTING 2)85
(define FT_LOAD_RENDER 4)86
(define FT_LOAD_NO_BITMAP 8)87
(define FT_LOAD_VERTICAL_LAYOUT 16)88
(define FT_LOAD_FORCE_AUTOHINT 32)89
(define FT_LOAD_NO_AUTOHINT #x8000)90
(define FT_LOAD_COLOR #x100000)92
;; ============================================================93
;; Constants — Face Flags94
;; ============================================================96
(define FT_FACE_FLAG_SCALABLE 1)97
(define FT_FACE_FLAG_FIXED_SIZES 2)98
(define FT_FACE_FLAG_FIXED_WIDTH 4)99
(define FT_FACE_FLAG_HORIZONTAL 16)100
(define FT_FACE_FLAG_VERTICAL 32)101
(define FT_FACE_FLAG_KERNING 64)103
;; ============================================================104
;; Struct Layouts105
;; ============================================================107
;; FT_FaceRec_ — modeled with flattened nested structs.108
;; FT_Generic = 2 pointers, FT_BBox = 4 FT_Pos (long).109
;; c-struct-layout handles alignment automatically, matching C layout.110
(define ft-face-layout111
(c-struct-layout112
num-faces: ffi/long113
face-index: ffi/long114
face-flags: ffi/long115
style-flags: ffi/long116
num-glyphs: ffi/long117
family-name: ffi/pointer118
style-name: ffi/pointer119
num-fixed-sizes: ffi/int120
available-sizes: ffi/pointer121
num-charmaps: ffi/int122
charmaps: ffi/pointer123
generic-data: ffi/pointer124
generic-finalizer: ffi/pointer125
bbox-x-min: ffi/long126
bbox-y-min: ffi/long127
bbox-x-max: ffi/long128
bbox-y-max: ffi/long129
units-per-em: ffi/uint16130
ascender: ffi/int16131
descender: ffi/int16132
height: ffi/int16133
max-advance-width: ffi/int16134
max-advance-height: ffi/int16135
underline-position: ffi/int16136
underline-thickness: ffi/int16137
glyph: ffi/pointer138
size: ffi/pointer139
charmap: ffi/pointer))141
;; FT_GlyphSlotRec_ — partial layout up through metrics.142
;; FT_Glyph_Metrics has 8 FT_Pos (long) fields.143
(define ft-glyph-slot-layout144
(c-struct-layout145
library: ffi/pointer146
face: ffi/pointer147
next: ffi/pointer148
glyph-index: ffi/uint149
generic-data: ffi/pointer150
generic-finalizer: ffi/pointer151
metrics-width: ffi/long152
metrics-height: ffi/long153
metrics-hori-bearing-x: ffi/long154
metrics-hori-bearing-y: ffi/long155
metrics-hori-advance: ffi/long156
metrics-vert-bearing-x: ffi/long157
metrics-vert-bearing-y: ffi/long158
metrics-vert-advance: ffi/long))160
;; ============================================================161
;; Finalizer Pointers (looked up once)162
;; ============================================================164
(define %ft-done-face-ptr (c-symbol ft-lib "FT_Done_Face"))165
(define %ft-done-freetype-ptr (c-symbol ft-lib "FT_Done_FreeType"))167
;; ============================================================168
;; Raw Function Bindings169
;; ============================================================171
(define %ft-init-freetype172
(c-function ft-lib "FT_Init_FreeType"173
(list ffi/pointer) ffi/int))175
(define %ft-new-face176
(c-function ft-lib "FT_New_Face"177
(list ffi/pointer ffi/string ffi/long ffi/pointer) ffi/int))179
(define %ft-set-char-size180
(c-function ft-lib "FT_Set_Char_Size"181
(list ffi/pointer ffi/long ffi/long ffi/uint ffi/uint) ffi/int))183
(define %ft-set-pixel-sizes184
(c-function ft-lib "FT_Set_Pixel_Sizes"185
(list ffi/pointer ffi/uint ffi/uint) ffi/int))187
(define %ft-get-char-index188
(c-function ft-lib "FT_Get_Char_Index"189
(list ffi/pointer ffi/ulong) ffi/uint))191
(define %ft-load-glyph192
(c-function ft-lib "FT_Load_Glyph"193
(list ffi/pointer ffi/uint ffi/int) ffi/int))195
(define %ft-load-char196
(c-function ft-lib "FT_Load_Char"197
(list ffi/pointer ffi/ulong ffi/int) ffi/int))199
(define %ft-done-face200
(c-function ft-lib "FT_Done_Face"201
(list ffi/pointer) ffi/int))203
(define %ft-done-freetype204
(c-function ft-lib "FT_Done_FreeType"205
(list ffi/pointer) ffi/int))207
;; ============================================================208
;; Public API — Library Lifecycle209
;; ============================================================211
;;; Initialize the FreeType library, returning a library handle.212
(define (ft-init)213
(: -> pointer?)214
(let ((out (c-alloc (c-sizeof ffi/pointer))))215
(let ((err (%ft-init-freetype out)))216
(if (= err 0)217
(let ((lib (pointer-ref out ffi/pointer 0)))218
(c-free out)219
(set-pointer-finalizer! lib %ft-done-freetype-ptr)220
lib)221
(begin222
(c-free out)223
(error "FT_Init_FreeType failed" err))))))225
;;; Destroy the FreeType library handle.226
(define (ft-done-freetype lib)227
(: pointer? -> void?)228
(set-pointer-finalizer! lib #f)229
(%ft-done-freetype lib))231
;; ============================================================232
;; Public API — Face Lifecycle233
;; ============================================================235
;;; Load a font face from a file path.236
;;;237
;;; INDEX defaults to 0 (first face in the file).238
(define (ft-new-face lib path . rest)239
(: pointer? string? -> pointer?)240
(let ((face-index (if (pair? rest) (car rest) 0))241
(out (c-alloc (c-sizeof ffi/pointer))))242
(let ((err (%ft-new-face lib path face-index out)))243
(if (= err 0)244
(let ((face (pointer-ref out ffi/pointer 0)))245
(c-free out)246
(set-pointer-finalizer! face %ft-done-face-ptr)247
face)248
(begin249
(c-free out)250
(error "FT_New_Face failed" err))))))252
;;; Destroy a face, freeing its resources.253
(define (ft-done-face face)254
(: pointer? -> void?)255
(set-pointer-finalizer! face #f)256
(%ft-done-face face))258
;; ============================================================259
;; Public API — Face Configuration260
;; ============================================================262
;;; Set the character size in 26.6 fractional points.263
;;;264
;;; Width and height are in 1/64th of a point (multiply point size by 64).265
;;; Pass 0 for width to use height for both dimensions.266
(define (ft-set-char-size face char-width char-height horz-res vert-res)267
(: pointer? integer? integer? integer? integer? -> void?)268
(let ((err (%ft-set-char-size face char-width char-height horz-res vert-res)))269
(unless (= err 0)270
(error "FT_Set_Char_Size failed" err))))272
;;; Set the pixel size for a face.273
;;;274
;;; Pass 0 for width to use height for both dimensions.275
(define (ft-set-pixel-sizes face width height)276
(: pointer? integer? integer? -> void?)277
(let ((err (%ft-set-pixel-sizes face width height)))278
(unless (= err 0)279
(error "FT_Set_Pixel_Sizes failed" err))))281
;; ============================================================282
;; Public API — Glyph Loading283
;; ============================================================285
;;; Get the glyph index for a Unicode character code.286
;;;287
;;; Returns 0 if the character is not found in the font.288
(define (ft-get-char-index face charcode)289
(: pointer? integer? -> integer?)290
(%ft-get-char-index face charcode))292
;;; Load a glyph by index into the face's glyph slot.293
(define (ft-load-glyph face glyph-index load-flags)294
(: pointer? integer? integer? -> void?)295
(let ((err (%ft-load-glyph face glyph-index load-flags)))296
(unless (= err 0)297
(error "FT_Load_Glyph failed" err))))299
;;; Load a glyph by character code into the face's glyph slot.300
;;;301
;;; Convenience function equivalent to ft-get-char-index + ft-load-glyph.302
(define (ft-load-char face charcode load-flags)303
(: pointer? integer? integer? -> void?)304
(let ((err (%ft-load-char face charcode load-flags)))305
(unless (= err 0)306
(error "FT_Load_Char failed" err))))308
;; ============================================================309
;; Public API — Face Property Accessors310
;; ============================================================312
;;; Get the family name of a face as a string.313
(define (ft-face-family-name face)314
(: pointer? -> string?)315
(pointer->string (c-struct-ref face ft-face-layout family-name:)))317
;;; Get the style name of a face as a string.318
(define (ft-face-style-name face)319
(: pointer? -> string?)320
(pointer->string (c-struct-ref face ft-face-layout style-name:)))322
;;; Get the number of glyphs in a face.323
(define (ft-face-num-glyphs face)324
(: pointer? -> integer?)325
(c-struct-ref face ft-face-layout num-glyphs:))327
;;; Get the face flags bitmask.328
(define (ft-face-flags face)329
(: pointer? -> integer?)330
(c-struct-ref face ft-face-layout face-flags:))332
;;; Check if a face has a specific flag set.333
(define (ft-face-has-flag? face flag)334
(: pointer? integer? -> boolean?)335
(not (= 0 (bitwise-and (ft-face-flags face) flag))))337
;;; Get units-per-EM for the face.338
(define (ft-face-units-per-em face)339
(: pointer? -> integer?)340
(c-struct-ref face ft-face-layout units-per-em:))342
;;; Get the typographic ascender in font units.343
(define (ft-face-ascender face)344
(: pointer? -> integer?)345
(c-struct-ref face ft-face-layout ascender:))347
;;; Get the typographic descender in font units (typically negative).348
(define (ft-face-descender face)349
(: pointer? -> integer?)350
(c-struct-ref face ft-face-layout descender:))352
;;; Get the recommended line height in font units.353
(define (ft-face-height face)354
(: pointer? -> integer?)355
(c-struct-ref face ft-face-layout height:))357
;;; Get the glyph slot pointer from a face.358
;;;359
;;; The glyph slot is populated after calling ft-load-char or ft-load-glyph.360
(define (ft-face-glyph face)361
(: pointer? -> pointer?)362
(c-struct-ref face ft-face-layout glyph:))364
;; ============================================================365
;; Public API — Glyph Metrics366
;; ============================================================368
;;; Get metrics from the face's current glyph slot as a dict.369
;;;370
;;; Returns a dict with keys: width:, height:, hori-bearing-x:,371
;;; hori-bearing-y:, hori-advance:, vert-bearing-x:, vert-bearing-y:,372
;;; vert-advance:. All values are in 26.6 fractional pixel format373
;;; (divide by 64 for pixels).374
(define (ft-glyph-metrics face)375
(: pointer? -> any?)376
(let ((slot (ft-face-glyph face)))377
(dict378
width: (c-struct-ref slot ft-glyph-slot-layout metrics-width:)379
height: (c-struct-ref slot ft-glyph-slot-layout metrics-height:)380
hori-bearing-x: (c-struct-ref slot ft-glyph-slot-layout metrics-hori-bearing-x:)381
hori-bearing-y: (c-struct-ref slot ft-glyph-slot-layout metrics-hori-bearing-y:)382
hori-advance: (c-struct-ref slot ft-glyph-slot-layout metrics-hori-advance:)383
vert-bearing-x: (c-struct-ref slot ft-glyph-slot-layout metrics-vert-bearing-x:)384
vert-bearing-y: (c-struct-ref slot ft-glyph-slot-layout metrics-vert-bearing-y:)385
vert-advance: (c-struct-ref slot ft-glyph-slot-layout metrics-vert-advance:))))))