make fractions look better

This commit is contained in:
Joe Lothan 2026-06-15 18:52:35 -04:00
parent 6efed3be72
commit c1447e5852

325
glyphs.py
View file

@ -1,14 +1,18 @@
"""Custom fraction glyphs for the TM-T88V receipt printer. """Custom fraction glyphs for the TM-T88V receipt printer.
Each glyph is a 12-wide x 24-tall pixel bitmap defined as a list of 24 strings. Fractions are composed from small digit patterns stacked vertically:
'#' = pixel on, '.' = pixel off. numerator on top, denominator on bottom matching the old ticker tape style.
To customize a glyph, edit its pattern below. Each row must be exactly 12 To customize:
characters wide and there must be exactly 24 rows per glyph. - Edit DIGIT_PATTERNS to change how a digit looks in ALL fractions using it.
- Or override a specific fraction in GLYPH_OVERRIDES with a full 12x24 grid.
- '#' = pixel on, '.' = pixel off
- Each digit pattern is 12 wide x 11 tall.
- Each full glyph is 12 wide x 24 tall (11 + 2 gap + 11).
""" """
# Map each fraction to a character code on the printer. # Character codes used on the printer for each fraction.
# Must be in 0x20-0x7E range and not conflict with output chars (A-Z, 0-9, '.', 's', ' ') # Must be 0x20-0x7E and not conflict with output chars (A-Z, 0-9, '.', 's', ' ')
CHAR_MAP = { CHAR_MAP = {
"1/8": "a", "1/8": "a",
"1/4": "b", "1/4": "b",
@ -30,194 +34,149 @@ EIGHTHS_TO_NAME = {
7: "7/8", 7: "7/8",
} }
# ── Digit patterns (12 wide x 11 tall) ───────────────────────────────────────
# These are composed into the fraction glyphs below.
# fmt: off # fmt: off
GLYPHS = { DIGIT_PATTERNS = {
"1/8": [ 1: [
"............", # 0 ".....##.....",
".........#..", # 1 ── numerator "1" "....###.....",
"........##..", # 2 "...####.....",
".........#..", # 3 ".....##.....",
".........#..", # 4 ".....##.....",
".........#..", # 5 ".....##.....",
".........#..", # 6 ".....##.....",
".........#..", # 7 ".....##.....",
"........#...", # 8 ── slash ".....##.....",
".......#....", # 9 ".....##.....",
"......#.....", # 10 "...######...",
".....#......", # 11
"....#.......", # 12
"...#........", # 13
"..#.........", # 14
".#..........", # 15
"..##........", # 16 ── denominator "8"
".#..#.......", # 17
".#..#.......", # 18
"..##........", # 19
".#..#.......", # 20
".#..#.......", # 21
"..##........", # 22
"............", # 23
], ],
"1/4": [ 2: [
"............", # 0 "..########..",
".........#..", # 1 ── "1" ".##......##.",
"........##..", # 2 "..........##",
".........#..", # 3 "..........##",
".........#..", # 4 "........##..",
".........#..", # 5 "......##....",
".........#..", # 6 "....##......",
".........#..", # 7 "..##........",
"........#...", # 8 ── slash ".##.........",
".......#....", # 9 ".##.........",
"......#.....", # 10 "############",
".....#......", # 11
"....#.......", # 12
"...#........", # 13
"..#.........", # 14
".#..........", # 15
"....#.......", # 16 ── "4"
"...##.......", # 17
"..#.#.......", # 18
".#..#.......", # 19
".####.......", # 20
"....#.......", # 21
"....#.......", # 22
"............", # 23
], ],
"3/8": [ 3: [
"............", # 0 "..########..",
"........##..", # 1 ── "3" ".##......##.",
".......#..#.", # 2 "..........##",
"..........#.", # 3 "..........##",
"........##..", # 4 ".....####...",
"..........#.", # 5 "..........##",
".......#..#.", # 6 "..........##",
"........##..", # 7 "..........##",
"........#...", # 8 ── slash ".##......##.",
".......#....", # 9 ".##......##.",
"......#.....", # 10 "..########..",
".....#......", # 11
"....#.......", # 12
"...#........", # 13
"..#.........", # 14
".#..........", # 15
"..##........", # 16 ── "8"
".#..#.......", # 17
".#..#.......", # 18
"..##........", # 19
".#..#.......", # 20
".#..#.......", # 21
"..##........", # 22
"............", # 23
], ],
"1/2": [ 4: [
"............", # 0 ".......##...",
".........#..", # 1 ── "1" "......###...",
"........##..", # 2 ".....####...",
".........#..", # 3 "....##.##...",
".........#..", # 4 "...##..##...",
".........#..", # 5 "..##...##...",
".........#..", # 6 ".##....##...",
".........#..", # 7 "############",
"........#...", # 8 ── slash ".......##...",
".......#....", # 9 ".......##...",
"......#.....", # 10 ".......##...",
".....#......", # 11
"....#.......", # 12
"...#........", # 13
"..#.........", # 14
".#..........", # 15
"..##........", # 16 ── "2"
".#..#.......", # 17
"....#.......", # 18
"...#........", # 19
"..#.........", # 20
".#..........", # 21
".####.......", # 22
"............", # 23
], ],
"5/8": [ 5: [
"............", # 0 "############",
".......####.", # 1 ── "5" "##..........",
".......#....", # 2 "##..........",
".......###..", # 3 "##..........",
"..........#.", # 4 "##########..",
"..........#.", # 5 "..........##",
".......#..#.", # 6 "..........##",
"........##..", # 7 "..........##",
"........#...", # 8 ── slash "..........##",
".......#....", # 9 ".##......##.",
"......#.....", # 10 "..########..",
".....#......", # 11
"....#.......", # 12
"...#........", # 13
"..#.........", # 14
".#..........", # 15
"..##........", # 16 ── "8"
".#..#.......", # 17
".#..#.......", # 18
"..##........", # 19
".#..#.......", # 20
".#..#.......", # 21
"..##........", # 22
"............", # 23
], ],
"3/4": [ 7: [
"............", # 0 "############",
"........##..", # 1 ── "3" "##........##",
".......#..#.", # 2 "..........##",
"..........#.", # 3 ".........##.",
"........##..", # 4 "........##..",
"..........#.", # 5 ".......##...",
".......#..#.", # 6 "......##....",
"........##..", # 7 ".....##.....",
"........#...", # 8 ── slash "....##......",
".......#....", # 9 "....##......",
"......#.....", # 10 "....##......",
".....#......", # 11
"....#.......", # 12
"...#........", # 13
"..#.........", # 14
".#..........", # 15
"....#.......", # 16 ── "4"
"...##.......", # 17
"..#.#.......", # 18
".#..#.......", # 19
".####.......", # 20
"....#.......", # 21
"....#.......", # 22
"............", # 23
], ],
"7/8": [ 8: [
"............", # 0 "..########..",
".......####.", # 1 ── "7" ".##......##.",
"..........#.", # 2 ".##......##.",
".........#..", # 3 ".##......##.",
".........#..", # 4 "..########..",
"........#...", # 5 ".##......##.",
"........#...", # 6 ".##......##.",
"........#...", # 7 ".##......##.",
"........#...", # 8 ── slash ".##......##.",
".......#....", # 9 ".##......##.",
"......#.....", # 10 "..########..",
".....#......", # 11
"....#.......", # 12
"...#........", # 13
"..#.........", # 14
".#..........", # 15
"..##........", # 16 ── "8"
".#..#.......", # 17
".#..#.......", # 18
"..##........", # 19
".#..#.......", # 20
".#..#.......", # 21
"..##........", # 22
"............", # 23
], ],
} }
# fmt: on # fmt: on
def _compose_fraction(num, den):
"""Build a 12x24 glyph: numerator digit stacked over denominator digit.
Layout (24 rows):
rows 0-10: numerator digit (11 rows)
rows 11-12: gap (2 rows)
rows 13-23: denominator digit (11 rows)
"""
blank = "." * 12
rows = list(DIGIT_PATTERNS[num])
rows.extend([blank] * 2)
rows.extend(DIGIT_PATTERNS[den])
return rows
# ── Composed glyphs (auto-generated from digit patterns) ────────────────────
GLYPHS = {
"1/8": _compose_fraction(1, 8),
"1/4": _compose_fraction(1, 4),
"3/8": _compose_fraction(3, 8),
"1/2": _compose_fraction(1, 2),
"5/8": _compose_fraction(5, 8),
"3/4": _compose_fraction(3, 4),
"7/8": _compose_fraction(7, 8),
}
# ── Per-fraction overrides ──────────────────────────────────────────────────
# To hand-craft a specific fraction, add it here as a 24-row list of 12-char
# strings. It will replace the auto-composed version above.
#
# GLYPH_OVERRIDES = {
# "1/2": [
# "............",
# ... # 24 rows total
# ],
# }
GLYPH_OVERRIDES = {}
# Apply overrides
GLYPHS.update(GLYPH_OVERRIDES)
# ── ESC/POS conversion & upload ─────────────────────────────────────────────
def glyph_to_escpos(rows): def glyph_to_escpos(rows):
"""Convert a visual glyph (24 rows of 12-char strings) to ESC/POS column data. """Convert a visual glyph (24 rows of 12-char strings) to ESC/POS column data.
@ -254,7 +213,7 @@ def price_to_fraction(price):
"""Convert a decimal price to dollar amount + fraction character. """Convert a decimal price to dollar amount + fraction character.
Rounds to the nearest eighth of a dollar, like old ticker tapes. Rounds to the nearest eighth of a dollar, like old ticker tapes.
Returns e.g. "246" or "57a" where 'a' is the custom glyph. Returns e.g. "246" or "57d" where 'd' is the custom ½ glyph.
""" """
dollars = int(price) dollars = int(price)
eighths = round((price - dollars) * 8) eighths = round((price - dollars) * 8)