diff --git a/Widgets/Font.cpp b/Widgets/Font.cpp new file mode 100644 index 0000000000..a4bda1a184 --- /dev/null +++ b/Widgets/Font.cpp @@ -0,0 +1,31 @@ +#include "Font.h" +#include "Peanut8x10.h" +#include +#include + +Font& Font::defaultFont() +{ + static auto* f = adopt(*new Font(Peanut8x10::glyphs, Peanut8x10::glyphWidth, Peanut8x10::glyphHeight, Peanut8x10::firstGlyph, Peanut8x10::lastGlyph)).leakRef(); + return *f; +} + +Font::Font(const char* const* glyphs, unsigned glyphWidth, unsigned glyphHeight, byte firstGlyph, byte lastGlyph) + : m_glyphs(glyphs) + , m_glyphWidth(glyphWidth) + , m_glyphHeight(glyphHeight) + , m_firstGlyph(firstGlyph) + , m_lastGlyph(lastGlyph) +{ +} + +Font::~Font() +{ +} + +const char* Font::glyph(char ch) const +{ + if (ch < m_firstGlyph || ch > m_lastGlyph) + return nullptr; + return m_glyphs[(unsigned)ch - m_firstGlyph]; +} + diff --git a/Widgets/Font.h b/Widgets/Font.h new file mode 100644 index 0000000000..1c53e4d449 --- /dev/null +++ b/Widgets/Font.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +class Font : public Retainable { +public: + static Font& defaultFont(); + + ~Font(); + + const char* glyph(char) const; + + unsigned glyphWidth() const { return m_glyphWidth; } + unsigned glyphHeight() const { return m_glyphHeight; } + +private: + Font(const char* const* glyphs, unsigned glyphWidth, unsigned glyphHeight, byte firstGlyph, byte lastGlyph); + + const char* const* m_glyphs { nullptr }; + + unsigned m_glyphWidth { 0 }; + unsigned m_glyphHeight { 0 }; + + byte m_firstGlyph { 0 }; + byte m_lastGlyph { 0 }; +}; diff --git a/Widgets/Makefile b/Widgets/Makefile index 31295d7dae..aa59e78b3d 100644 --- a/Widgets/Makefile +++ b/Widgets/Makefile @@ -20,6 +20,7 @@ VFS_OBJS = \ Button.o \ TerminalWidget.o \ WindowManager.o \ + Font.o \ test.o OBJS = $(AK_OBJS) $(VFS_OBJS) diff --git a/Widgets/Painter.cpp b/Widgets/Painter.cpp index 2f54370106..4750d17419 100644 --- a/Widgets/Painter.cpp +++ b/Widgets/Painter.cpp @@ -1,19 +1,13 @@ #include "Painter.h" #include "FrameBufferSDL.h" #include "Widget.h" +#include "Font.h" #include #include -#if 0 -#include "Peanut8x8.h" -#define FONT_NAMESPACE Peanut8x8 -#else -#include "Peanut8x10.h" -#define FONT_NAMESPACE Peanut8x10 -#endif - Painter::Painter(Widget& widget) : m_widget(widget) + , m_font(Font::defaultFont()) { } @@ -66,31 +60,31 @@ void Painter::drawText(const Rect& rect, const String& text, TextAlignment align if (alignment == TextAlignment::TopLeft) { point = rect.location(); - point.moveBy(m_widget.x(), m_widget.y());; + point.moveBy(m_widget.x(), m_widget.y()); } else if (alignment == TextAlignment::Center) { - int textWidth = text.length() * FONT_NAMESPACE::fontWidth; + int textWidth = text.length() * m_font.glyphWidth(); point = rect.center(); - point.moveBy(-(textWidth / 2), -(FONT_NAMESPACE::fontWidth / 2)); + point.moveBy(-(textWidth / 2), -(m_font.glyphWidth() / 2)); point.moveBy(m_widget.x(), m_widget.y()); } else { ASSERT_NOT_REACHED(); } - for (int row = 0; row < FONT_NAMESPACE::fontHeight; ++row) { + for (int row = 0; row < m_font.glyphHeight(); ++row) { int y = point.y() + row; dword* bits = scanline(y); for (unsigned i = 0; i < text.length(); ++i) { byte ch = text[i]; if (ch == ' ') continue; - if (ch < FONT_NAMESPACE::firstCharacter || ch > FONT_NAMESPACE::lastCharacter) { + const char* glyph = m_font.glyph(ch); + if (!ch) { printf("Font doesn't have 0x%02x ('%c')\n", ch, ch); ASSERT_NOT_REACHED(); } - const char* fontCharacter = FONT_NAMESPACE::font[ch - FONT_NAMESPACE::firstCharacter]; - int x = point.x() + i * FONT_NAMESPACE::fontWidth; - for (unsigned j = 0; j < FONT_NAMESPACE::fontWidth; ++j) { - char fc = fontCharacter[row * FONT_NAMESPACE::fontWidth + j]; + int x = point.x() + i * m_font.glyphWidth(); + for (unsigned j = 0; j < m_font.glyphWidth(); ++j) { + char fc = glyph[row * m_font.glyphWidth() + j]; if (fc == '#') bits[x + j] = color.value(); } diff --git a/Widgets/Painter.h b/Widgets/Painter.h index 459ec5ce8a..857815fd88 100644 --- a/Widgets/Painter.h +++ b/Widgets/Painter.h @@ -5,6 +5,7 @@ #include "Rect.h" #include +class Font; class Widget; class Painter { @@ -16,6 +17,9 @@ public: void drawRect(const Rect&, Color); void drawText(const Rect&, const String&, TextAlignment = TextAlignment::TopLeft, const Color& = Color()); + const Font& font() const; + private: Widget& m_widget; + Font& m_font; }; diff --git a/Widgets/Peanut8x10.h b/Widgets/Peanut8x10.h index 607a7a422a..4b5608f4e0 100644 --- a/Widgets/Peanut8x10.h +++ b/Widgets/Peanut8x10.h @@ -2,12 +2,12 @@ namespace Peanut8x10 { -static constexpr char firstCharacter = '!'; -static constexpr char lastCharacter = '~'; -static constexpr byte fontWidth = 8; -static constexpr byte fontHeight = 10; +static constexpr char firstGlyph = '!'; +static constexpr char lastGlyph = '~'; +static constexpr byte glyphWidth = 8; +static constexpr byte glyphHeight = 10; -static constexpr const char* font[] { +static constexpr const char* glyphs[] { " ## " " ## "