/* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #pragma once // the drawing the Lua screens get from the game (eu07.image, eu07.font, eu07.sprite): bitmap fonts and sprites in the // format of the python LED screens (scripts/led_util.py: a .png with the glyphs side by side and a .txt with their // widths), and RGBA images to draw them on. drawn natively, the script only says what goes where #include #include #include #include #include #include #include #include #include namespace script_screens { using rgb = std::array; // the code points of UTF-8 text; a byte that doesn't start a valid sequence stands for itself std::u32string decode_utf8(std::string_view Text); // a character or a sprite: its lit pixels, column by column class glyph { public: glyph() = default; glyph(int Width, int Height, std::vector Lit) : m_width{Width}, m_height{Height}, m_lit{std::move(Lit)} {} int width() const { return m_width; } int height() const { return m_height; } bool lit(int const X, int const Y) const { return m_lit[static_cast(X) * m_height + Y]; } private: int m_width{0}; int m_height{0}; std::vector m_lit; }; class bitmap_font { public: // a font as led_util.load_font() reads it: Rgba (Width x Height) has the glyphs side by side, a column apart; // Description has a comment line, then a line per glyph: the character and its width. a pixel is lit unless it is // opaque white. nothing for a description without glyphs static std::optional parse(std::span Rgba, int Width, int Height, std::string_view Description); // a sprite as led_util.load_spr() reads it: the whole image as one glyph static glyph sprite(std::span Rgba, int Width, int Height); int height() const { return m_height; } // the glyph of the character. a character the font lacks gets the font's first glyph (led_util picks a random one; // here every refresh draws the same) glyph const &find(char32_t Character) const; // the width of the text, a column of Spacing after every character (led_util's get_str_len) int text_width(std::string_view Text, int Spacing) const; private: int m_height{0}; std::unordered_map m_glyphs; glyph m_fallback; }; // an RGBA image, from the top row down class canvas { public: canvas(int Width, int Height, rgb Color); canvas(int Width, int Height, std::vector Pixels); int width() const { return m_width; } int height() const { return m_height; } std::vector const &pixels() const { return m_pixels; } void fill(rgb Color); // a pixel outside the image is skipped void set(int X, int Y, rgb Color); // black outside the image rgb get(int X, int Y) const; // clipped to the image void fill_rect(int X, int Y, int Width, int Height, rgb Color); // the lit pixels of the glyph, its top left corner at (X, Y) void draw_glyph(glyph const &Glyph, int X, int Y, rgb Color); // text from X rightwards, Spacing columns between the characters (led_util's draw_str). returns the X after it int draw_text(bitmap_font const &Font, int X, int Y, std::string_view Text, rgb Color, int Spacing); // another image, its top left corner at (X, Y), clipped void draw_image(canvas const &Image, int X, int Y); private: int m_width; int m_height; std::vector m_pixels; }; } // namespace script_screens