mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-22 09:21:57 -05:00
Add a simple Font class.
This commit is contained in:
parent
a6e0577f30
commit
110d01941a
6 changed files with 79 additions and 22 deletions
31
Widgets/Font.cpp
Normal file
31
Widgets/Font.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include "Font.h"
|
||||
#include "Peanut8x10.h"
|
||||
#include <AK/RetainPtr.h>
|
||||
#include <cstdio>
|
||||
|
||||
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];
|
||||
}
|
||||
|
27
Widgets/Font.h
Normal file
27
Widgets/Font.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Retainable.h>
|
||||
#include <AK/Types.h>
|
||||
|
||||
class Font : public Retainable<Font> {
|
||||
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 };
|
||||
};
|
|
@ -20,6 +20,7 @@ VFS_OBJS = \
|
|||
Button.o \
|
||||
TerminalWidget.o \
|
||||
WindowManager.o \
|
||||
Font.o \
|
||||
test.o
|
||||
|
||||
OBJS = $(AK_OBJS) $(VFS_OBJS)
|
||||
|
|
|
@ -1,19 +1,13 @@
|
|||
#include "Painter.h"
|
||||
#include "FrameBufferSDL.h"
|
||||
#include "Widget.h"
|
||||
#include "Font.h"
|
||||
#include <AK/Assertions.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#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();
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Rect.h"
|
||||
#include <AK/String.h>
|
||||
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -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[] {
|
||||
|
||||
" ## "
|
||||
" ## "
|
||||
|
|
Loading…
Reference in a new issue