package main

// Embedded bitmap glyph set.
//
// StepShot links against no font files and no font library. Callout numbers and
// labels are drawn from this table, which is compiled into the binary.
//
// Each glyph is a 5-wide, 7-tall bitmap written as seven row strings, '#' for an
// ink pixel and '.' for background. The table covers the digits, the uppercase
// letters and the ASCII punctuation listed below. Lowercase input is folded to
// uppercase; any rune with no glyph is drawn as a hollow box so that a missing
// character is visible rather than silently dropped.

const (
	glyphW = 5
	glyphH = 7
)

var glyphs = map[rune][glyphH]string{
	' ': {".....", ".....", ".....", ".....", ".....", ".....", "....."},

	'0': {".###.", "#...#", "#..##", "#.#.#", "##..#", "#...#", ".###."},
	'1': {"..#..", ".##..", "..#..", "..#..", "..#..", "..#..", ".###."},
	'2': {".###.", "#...#", "....#", "...#.", "..#..", ".#...", "#####"},
	'3': {"#####", "...#.", "..#..", "...#.", "....#", "#...#", ".###."},
	'4': {"...#.", "..##.", ".#.#.", "#..#.", "#####", "...#.", "...#."},
	'5': {"#####", "#....", "####.", "....#", "....#", "#...#", ".###."},
	'6': {"..##.", ".#...", "#....", "####.", "#...#", "#...#", ".###."},
	'7': {"#####", "....#", "...#.", "..#..", ".#...", ".#...", ".#..."},
	'8': {".###.", "#...#", "#...#", ".###.", "#...#", "#...#", ".###."},
	'9': {".###.", "#...#", "#...#", ".####", "....#", "...#.", ".##.."},

	'A': {"..#..", ".#.#.", "#...#", "#...#", "#####", "#...#", "#...#"},
	'B': {"####.", "#...#", "#...#", "####.", "#...#", "#...#", "####."},
	'C': {".####", "#....", "#....", "#....", "#....", "#....", ".####"},
	'D': {"####.", "#...#", "#...#", "#...#", "#...#", "#...#", "####."},
	'E': {"#####", "#....", "#....", "####.", "#....", "#....", "#####"},
	'F': {"#####", "#....", "#....", "####.", "#....", "#....", "#...."},
	'G': {".####", "#....", "#....", "#..##", "#...#", "#...#", ".###."},
	'H': {"#...#", "#...#", "#...#", "#####", "#...#", "#...#", "#...#"},
	'I': {".###.", "..#..", "..#..", "..#..", "..#..", "..#..", ".###."},
	'J': {"..###", "...#.", "...#.", "...#.", "...#.", "#..#.", ".##.."},
	'K': {"#...#", "#..#.", "#.#..", "##...", "#.#..", "#..#.", "#...#"},
	'L': {"#....", "#....", "#....", "#....", "#....", "#....", "#####"},
	'M': {"#...#", "##.##", "#.#.#", "#.#.#", "#...#", "#...#", "#...#"},
	'N': {"#...#", "##..#", "#.#.#", "#..##", "#...#", "#...#", "#...#"},
	'O': {".###.", "#...#", "#...#", "#...#", "#...#", "#...#", ".###."},
	'P': {"####.", "#...#", "#...#", "####.", "#....", "#....", "#...."},
	'Q': {".###.", "#...#", "#...#", "#...#", "#.#.#", "#..#.", ".##.#"},
	'R': {"####.", "#...#", "#...#", "####.", "#.#..", "#..#.", "#...#"},
	'S': {".####", "#....", "#....", ".###.", "....#", "....#", "####."},
	'T': {"#####", "..#..", "..#..", "..#..", "..#..", "..#..", "..#.."},
	'U': {"#...#", "#...#", "#...#", "#...#", "#...#", "#...#", ".###."},
	'V': {"#...#", "#...#", "#...#", "#...#", "#...#", ".#.#.", "..#.."},
	'W': {"#...#", "#...#", "#...#", "#.#.#", "#.#.#", "##.##", "#...#"},
	'X': {"#...#", "#...#", ".#.#.", "..#..", ".#.#.", "#...#", "#...#"},
	'Y': {"#...#", "#...#", ".#.#.", "..#..", "..#..", "..#..", "..#.."},
	'Z': {"#####", "....#", "...#.", "..#..", ".#...", "#....", "#####"},

	'.':  {".....", ".....", ".....", ".....", ".....", ".##..", ".##.."},
	',':  {".....", ".....", ".....", ".....", ".##..", ".##..", ".#..."},
	':':  {".....", ".##..", ".##..", ".....", ".##..", ".##..", "....."},
	';':  {".....", ".##..", ".##..", ".....", ".##..", ".##..", ".#..."},
	'!':  {"..#..", "..#..", "..#..", "..#..", "..#..", ".....", "..#.."},
	'?':  {".###.", "#...#", "....#", "...#.", "..#..", ".....", "..#.."},
	'-':  {".....", ".....", ".....", "#####", ".....", ".....", "....."},
	'+':  {".....", "..#..", "..#..", "#####", "..#..", "..#..", "....."},
	'*':  {".....", "..#..", "#.#.#", ".###.", "#.#.#", "..#..", "....."},
	'/':  {"....#", "....#", "...#.", "..#..", ".#...", "#....", "#...."},
	'\\': {"#....", "#....", ".#...", "..#..", "...#.", "....#", "....#"},
	'(':  {"...#.", "..#..", ".#...", ".#...", ".#...", "..#..", "...#."},
	')':  {".#...", "..#..", "...#.", "...#.", "...#.", "..#..", ".#..."},
	'[':  {"..###", "..#..", "..#..", "..#..", "..#..", "..#..", "..###"},
	']':  {"###..", "..#..", "..#..", "..#..", "..#..", "..#..", "###.."},
	'{':  {"...##", "..#..", "..#..", ".##..", "..#..", "..#..", "...##"},
	'}':  {"##...", "..#..", "..#..", "..##.", "..#..", "..#..", "##..."},
	'#':  {".#.#.", ".#.#.", "#####", ".#.#.", "#####", ".#.#.", ".#.#."},
	'%':  {"##..#", "##.#.", "...#.", "..#..", ".#...", "#.##.", "#..##"},
	'=':  {".....", ".....", "#####", ".....", "#####", ".....", "....."},
	'<':  {"...#.", "..#..", ".#...", "#....", ".#...", "..#..", "...#."},
	'>':  {".#...", "..#..", "...#.", "....#", "...#.", "..#..", ".#..."},
	'&':  {".##..", "#..#.", "#.#..", ".#...", "#.#.#", "#..#.", ".##.#"},
	'@':  {".###.", "#...#", "#.###", "#.#.#", "#.###", "#....", ".###."},
	'_':  {".....", ".....", ".....", ".....", ".....", ".....", "#####"},
	'\'': {"..#..", "..#..", ".#...", ".....", ".....", ".....", "....."},
	'"':  {".#.#.", ".#.#.", ".....", ".....", ".....", ".....", "....."},
	'$':  {"..#..", ".####", "#.#..", ".###.", "..#.#", "####.", "..#.."},
	'^':  {"..#..", ".#.#.", "#...#", ".....", ".....", ".....", "....."},
	'~':  {".....", ".....", ".##.#", "#.##.", ".....", ".....", "....."},
	'|':  {"..#..", "..#..", "..#..", "..#..", "..#..", "..#..", "..#.."},
	'`':  {".#...", "..#..", ".....", ".....", ".....", ".....", "....."},
}

var missingGlyph = [glyphH]string{"#####", "#...#", "#...#", "#...#", "#...#", "#...#", "#####"}

// glyphFor returns the bitmap for r and whether the table had an exact entry.
// Lowercase letters are folded to uppercase before lookup.
func glyphFor(r rune) ([glyphH]string, bool) {
	if r >= 'a' && r <= 'z' {
		r -= 'a' - 'A'
	}
	if g, ok := glyphs[r]; ok {
		return g, true
	}
	return missingGlyph, false
}

// glyphPixels reports whether the glyph for r has ink at column x, row y.
func glyphPixels(r rune, x, y int) bool {
	g, _ := glyphFor(r)
	if y < 0 || y >= glyphH || x < 0 || x >= glyphW {
		return false
	}
	return g[y][x] == '#'
}

// textWidth returns the width in glyph cells of s rendered at scale 1,
// including a one-pixel gap between characters.
func textWidth(s string) int {
	n := len([]rune(s))
	if n == 0 {
		return 0
	}
	return n*glyphW + (n - 1)
}
