(->baked-font path font-height bitmap)
(->baked-font path font-height bitmap first-char char-buffer-size)
Returns a map containing all the info needed to crop letters out of a font atlas.
Source
(defn ->baked-font
"Returns a map containing all the info needed to crop letters out of a font atlas."
([path font-height bitmap]
(->baked-font path font-height bitmap default-first-char default-char-buffer-size))
([path font-height bitmap first-char char-buffer-size]
(let [^bytes ttf-bytes (cond-> path
(string? path)
resource->bytes)
ttf (doto (java.nio.ByteBuffer/allocateDirect (alength ttf-bytes))
(.order (java.nio.ByteOrder/nativeOrder))
(.put ttf-bytes)
.flip)
info (STBTTFontinfo/create)
_ (or (STBTruetype/stbtt_InitFont info ttf)
(throw (IllegalStateException. "Failed to initialize font information.")))
cdata (STBTTBakedChar/malloc char-buffer-size)
{:keys [data width height]} bitmap
bake-ret (STBTruetype/stbtt_BakeFontBitmap ttf font-height data width height first-char cdata)
stack (MemoryStack/stackPush)
*ascent (.callocInt stack 1)
*descent (.callocInt stack 1)
*line-gap (.callocInt stack 1)
_ (STBTruetype/stbtt_GetFontVMetrics info *ascent *descent *line-gap)
ascent (.get *ascent 0)
descent (.get *descent 0)
line-gap (.get *line-gap 0)
scale (double (STBTruetype/stbtt_ScaleForPixelHeight info font-height))
baseline (* ascent scale)
chars (->> cdata .iterator iterator-seq
(mapv (fn [^STBTTBakedChar q]
{:x (int (.x0 q))
:y (int (.y0 q))
:w (int (- (.x1 q) (.x0 q)))
:h (int (- (.y1 q) (.y0 q)))
:xoff (double (.xoff q))
:yoff (double (.yoff q))
:xadv (double (.xadvance q))})))]
{:baked-chars chars
:ascent ascent
:descent descent
:line-gap line-gap
:scale scale
:baseline baseline
:first-unused-row (when (pos? bake-ret)
bake-ret)
:chars-that-fit (when (neg? bake-ret)
(* -1 bake-ret))
:font-height font-height
:first-char first-char
:bitmap-width width
:bitmap-height height})))