package display import "github.com/veandco/go-sdl2/sdl" // Bitmap font: 5x7 pixel glyphs for ASCII 32–126, rendered via FillRect. // Each glyph is 7 rows of 5 bits (MSB = leftmost pixel). const ( glyphW = 5 // pixels per character width glyphH = 7 // pixels per character height charGap = 1 // horizontal gap between characters ) // font5x7 maps ASCII 32–126 to 7-byte bitmaps (one byte per row, top 5 bits used). // Index 0 = space (0x20), index 94 = tilde (0x7E). var font5x7 = [95][7]byte{ // space (0x20) {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ! (0x21) {0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20}, // " (0x22) {0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00}, // # (0x23) {0x50, 0xF8, 0x50, 0x50, 0x50, 0xF8, 0x50}, // $ (0x24) {0x20, 0x70, 0xA0, 0x70, 0x28, 0x70, 0x20}, // % (0x25) {0xC8, 0xC8, 0x10, 0x20, 0x40, 0x98, 0x98}, // & (0x26) {0x40, 0xA0, 0xA0, 0x40, 0xA8, 0x90, 0x68}, // ' (0x27) {0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, // ( (0x28) {0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10}, // ) (0x29) {0x40, 0x20, 0x10, 0x10, 0x10, 0x20, 0x40}, // * (0x2A) {0x00, 0x20, 0xA8, 0x70, 0xA8, 0x20, 0x00}, // + (0x2B) {0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00}, // , (0x2C) {0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40}, // - (0x2D) {0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00}, // . (0x2E) {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20}, // / (0x2F) {0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80}, // 0 (0x30) {0x70, 0x88, 0x98, 0xA8, 0xC8, 0x88, 0x70}, // 1 (0x31) {0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x70}, // 2 (0x32) {0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xF8}, // 3 (0x33) {0x70, 0x88, 0x08, 0x30, 0x08, 0x88, 0x70}, // 4 (0x34) {0x10, 0x30, 0x50, 0x90, 0xF8, 0x10, 0x10}, // 5 (0x35) {0xF8, 0x80, 0xF0, 0x08, 0x08, 0x88, 0x70}, // 6 (0x36) {0x30, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70}, // 7 (0x37) {0xF8, 0x08, 0x10, 0x20, 0x40, 0x40, 0x40}, // 8 (0x38) {0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70}, // 9 (0x39) {0x70, 0x88, 0x88, 0x78, 0x08, 0x10, 0x60}, // : (0x3A) {0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00}, // ; (0x3B) {0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x40}, // < (0x3C) {0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08}, // = (0x3D) {0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x00}, // > (0x3E) {0x80, 0x40, 0x20, 0x10, 0x20, 0x40, 0x80}, // ? (0x3F) {0x70, 0x88, 0x08, 0x10, 0x20, 0x00, 0x20}, // @ (0x40) {0x70, 0x88, 0xB8, 0xA8, 0xB8, 0x80, 0x70}, // A (0x41) {0x70, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88}, // B (0x42) {0xF0, 0x88, 0x88, 0xF0, 0x88, 0x88, 0xF0}, // C (0x43) {0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70}, // D (0x44) {0xF0, 0x88, 0x88, 0x88, 0x88, 0x88, 0xF0}, // E (0x45) {0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8}, // F (0x46) {0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80}, // G (0x47) {0x70, 0x88, 0x80, 0xB8, 0x88, 0x88, 0x70}, // H (0x48) {0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88}, // I (0x49) {0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70}, // J (0x4A) {0x38, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60}, // K (0x4B) {0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88}, // L (0x4C) {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF8}, // M (0x4D) {0x88, 0xD8, 0xA8, 0xA8, 0x88, 0x88, 0x88}, // N (0x4E) {0x88, 0xC8, 0xA8, 0x98, 0x88, 0x88, 0x88}, // O (0x4F) {0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70}, // P (0x50) {0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80, 0x80}, // Q (0x51) {0x70, 0x88, 0x88, 0x88, 0xA8, 0x90, 0x68}, // R (0x52) {0xF0, 0x88, 0x88, 0xF0, 0xA0, 0x90, 0x88}, // S (0x53) {0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70}, // T (0x54) {0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}, // U (0x55) {0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70}, // V (0x56) {0x88, 0x88, 0x88, 0x88, 0x88, 0x50, 0x20}, // W (0x57) {0x88, 0x88, 0x88, 0xA8, 0xA8, 0xD8, 0x88}, // X (0x58) {0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88}, // Y (0x59) {0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x20}, // Z (0x5A) {0xF8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xF8}, // [ (0x5B) {0x70, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70}, // \ (0x5C) {0x80, 0x80, 0x40, 0x20, 0x10, 0x08, 0x08}, // ] (0x5D) {0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70}, // ^ (0x5E) {0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00}, // _ (0x5F) {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8}, // ` (0x60) {0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, // a (0x61) {0x00, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78}, // b (0x62) {0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0xF0}, // c (0x63) {0x00, 0x00, 0x70, 0x80, 0x80, 0x80, 0x70}, // d (0x64) {0x08, 0x08, 0x78, 0x88, 0x88, 0x88, 0x78}, // e (0x65) {0x00, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70}, // f (0x66) {0x30, 0x48, 0x40, 0xE0, 0x40, 0x40, 0x40}, // g (0x67) {0x00, 0x00, 0x78, 0x88, 0x78, 0x08, 0x70}, // h (0x68) {0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x88}, // i (0x69) {0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70}, // j (0x6A) {0x10, 0x00, 0x30, 0x10, 0x10, 0x90, 0x60}, // k (0x6B) {0x80, 0x80, 0x90, 0xA0, 0xC0, 0xA0, 0x90}, // l (0x6C) {0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70}, // m (0x6D) {0x00, 0x00, 0xD0, 0xA8, 0xA8, 0xA8, 0xA8}, // n (0x6E) {0x00, 0x00, 0xF0, 0x88, 0x88, 0x88, 0x88}, // o (0x6F) {0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70}, // p (0x70) {0x00, 0x00, 0xF0, 0x88, 0xF0, 0x80, 0x80}, // q (0x71) {0x00, 0x00, 0x78, 0x88, 0x78, 0x08, 0x08}, // r (0x72) {0x00, 0x00, 0xB0, 0xC8, 0x80, 0x80, 0x80}, // s (0x73) {0x00, 0x00, 0x78, 0x80, 0x70, 0x08, 0xF0}, // t (0x74) {0x40, 0x40, 0xE0, 0x40, 0x40, 0x48, 0x30}, // u (0x75) {0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x78}, // v (0x76) {0x00, 0x00, 0x88, 0x88, 0x88, 0x50, 0x20}, // w (0x77) {0x00, 0x00, 0x88, 0x88, 0xA8, 0xA8, 0x50}, // x (0x78) {0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88}, // y (0x79) {0x00, 0x00, 0x88, 0x88, 0x78, 0x08, 0x70}, // z (0x7A) {0x00, 0x00, 0xF8, 0x10, 0x20, 0x40, 0xF8}, // { (0x7B) {0x10, 0x20, 0x20, 0x40, 0x20, 0x20, 0x10}, // | (0x7C) {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}, // } (0x7D) {0x40, 0x20, 0x20, 0x10, 0x20, 0x20, 0x40}, // ~ (0x7E) {0x00, 0x00, 0x40, 0xA8, 0x10, 0x00, 0x00}, } // drawChar renders a single ASCII character at (x, y) using filled rectangles. // Each pixel of the 5x7 glyph is drawn as a scale×scale block. func drawChar(renderer *sdl.Renderer, ch byte, x, y, scale int32) { if ch < 0x20 || ch > 0x7E { ch = '?' // replace unprintable characters } glyph := font5x7[ch-0x20] for row := 0; row < glyphH; row++ { bits := glyph[row] for col := 0; col < glyphW; col++ { if bits&(0x80>>uint(col)) != 0 { renderer.FillRect(&sdl.Rect{ X: x + int32(col)*scale, Y: y + int32(row)*scale, W: scale, H: scale, }) } } } } // drawString renders a string at (x, y) with the given pixel scale. // Returns the total width in pixels consumed by the string. func drawString(renderer *sdl.Renderer, s string, x, y, scale int32) int32 { cx := x for i := 0; i < len(s); i++ { drawChar(renderer, s[i], cx, y, scale) cx += (glyphW + charGap) * scale } return cx - x } // stringWidth returns the pixel width of a string at the given scale. func stringWidth(s string, scale int32) int32 { if len(s) == 0 { return 0 } return int32(len(s))*(glyphW+charGap)*scale - charGap*scale }