package tiny_libs
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
From-scratch libraries for teaching: graphics, audio, compression, crypto, networking and more
Install
dune-project
Dependency
Authors
Maintainers
Sources
0.3.6.tar.gz
md5=7c636383d146d30ac6f2fa234a6253c8
sha512=c79f3823c5f8f57e5038eb640d487c61168b84aa07c61999d6622ef9fd0c890e2b03b4c6a7cdbbe9352a49e25dda00ac7bb14693cee8e3d7beeed251351a2af0
doc/src/tiny_libs.graphics_font/Hershey.ml.html
Source file Hershey.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76(* Claude Code * * Copyright (C) 2026 Yoann Padioleau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * (LGPL) as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. *) (* See Hershey.mli for the font format, with an example *) type glyph = { left : int; right : int; strokes : (int * int) list list } (*****************************************************************************) (* Decoding *) (*****************************************************************************) let coordinate (c : char) : int = Char.code c - Char.code 'R' let decode_glyph (s : string) : glyph = (* the characters two by two: the left/right pair, then the points *) let pairs = List.init (String.length s / 2) (fun i -> (s.[2 * i], s.[(2 * i) + 1])) in match pairs with | [] -> failwith "empty glyph" | (l, r) :: points -> (* split the points into strokes at each pen up, " R" *) let finish stroke strokes = if stroke = [] then strokes else List.rev stroke :: strokes in let stroke, strokes = List.fold_left (fun (stroke, strokes) (cx, cy) -> if cx = ' ' && cy = 'R' then ([], finish stroke strokes) else ((coordinate cx, coordinate cy) :: stroke, strokes)) ([], []) points in { left = coordinate l; right = coordinate r; strokes = List.rev (finish stroke strokes) } (*****************************************************************************) (* The font *) (*****************************************************************************) (* One line per glyph, for ASCII 32 (space) to 127 in order; each line * starts with a 5-character number and a 3-character count *) let font : glyph array Lazy.t = lazy (String.split_on_char '\n' Hershey_futural.jhf |> List.filter (fun line -> String.length line >= 10) |> List.map (fun line -> decode_glyph (String.sub line 8 (String.length line - 8))) |> Array.of_list) let glyph (c : char) : glyph = let font = Lazy.force font in let i = Char.code c - 32 in if i >= 0 && i < Array.length font then font.(i) else font.(Char.code '?' - 32) (* Capital letters go from -12 to 9, 21 units, and in usual fonts * capitals are about 0.7 em tall: 21 / 0.7 = 30 *) let units_per_em = 30. (*****************************************************************************) (* Layout *) (*****************************************************************************) let layout (str : string) : (float * float) list list * float = let strokes, width = List.fold_left (fun (strokes, x) c -> let g = glyph c in (* move the glyph so that its left side is at x *) let dx = x - g.left in let moved = List.map (List.map (fun (px, py) -> (float (px + dx), float py))) g.strokes in (strokes @ moved, x + (g.right - g.left))) ([], 0) (List.init (String.length str) (String.get str)) in (strokes, float width)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>