From dde224fe442751b09aa858c35479d2fa69ead1cb Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 3 Apr 2019 15:23:13 +0200 Subject: [PATCH] FontEditor: Break out classes into separate files. --- Applications/FontEditor/FontEditor.cpp | 182 +----------------- Applications/FontEditor/FontEditor.h | 62 ------ Applications/FontEditor/GlyphEditorWidget.cpp | 97 ++++++++++ Applications/FontEditor/GlyphEditorWidget.h | 31 +++ Applications/FontEditor/GlyphMapWidget.cpp | 87 +++++++++ Applications/FontEditor/GlyphMapWidget.h | 37 ++++ Applications/FontEditor/Makefile | 4 +- 7 files changed, 257 insertions(+), 243 deletions(-) create mode 100644 Applications/FontEditor/GlyphEditorWidget.cpp create mode 100644 Applications/FontEditor/GlyphEditorWidget.h create mode 100644 Applications/FontEditor/GlyphMapWidget.cpp create mode 100644 Applications/FontEditor/GlyphMapWidget.h diff --git a/Applications/FontEditor/FontEditor.cpp b/Applications/FontEditor/FontEditor.cpp index 3260c6c189..1a0d0523db 100644 --- a/Applications/FontEditor/FontEditor.cpp +++ b/Applications/FontEditor/FontEditor.cpp @@ -1,4 +1,6 @@ #include "FontEditor.h" +#include "GlyphMapWidget.h" +#include "GlyphEditorWidget.h" #include #include #include @@ -112,183 +114,3 @@ FontEditorWidget::FontEditorWidget(const String& path, RetainPtr&& edited_ FontEditorWidget::~FontEditorWidget() { } - -GlyphMapWidget::GlyphMapWidget(Font& mutable_font, GWidget* parent) - : GWidget(parent) - , m_font(mutable_font) -{ - set_relative_rect({ 0, 0, preferred_width(), preferred_height() }); -} - -GlyphMapWidget::~GlyphMapWidget() -{ -} - -int GlyphMapWidget::preferred_width() const -{ - return columns() * (font().max_glyph_width() + m_horizontal_spacing) + 2; -} - -int GlyphMapWidget::preferred_height() const -{ - return rows() * (font().glyph_height() + m_vertical_spacing) + 2; -} - -void GlyphMapWidget::set_selected_glyph(byte glyph) -{ - if (m_selected_glyph == glyph) - return; - m_selected_glyph = glyph; - if (on_glyph_selected) - on_glyph_selected(glyph); - update(); -} - -Rect GlyphMapWidget::get_outer_rect(byte glyph) const -{ - int row = glyph / columns(); - int column = glyph % columns(); - return { - column * (font().max_glyph_width() + m_horizontal_spacing) + 1, - row * (font().glyph_height() + m_vertical_spacing) + 1, - font().max_glyph_width() + m_horizontal_spacing, - font().glyph_height() + m_horizontal_spacing - }; -} - -void GlyphMapWidget::paint_event(GPaintEvent&) -{ - GPainter painter(*this); - painter.set_font(font()); - painter.fill_rect(rect(), Color::White); - painter.draw_rect(rect(), Color::Black); - - byte glyph = 0; - - for (int row = 0; row < rows(); ++row) { - for (int column = 0; column < columns(); ++column, ++glyph) { - Rect outer_rect = get_outer_rect(glyph); - Rect inner_rect( - outer_rect.x() + m_horizontal_spacing / 2, - outer_rect.y() + m_vertical_spacing / 2, - font().max_glyph_width(), - font().glyph_height() - ); - if (glyph == m_selected_glyph) { - painter.fill_rect(outer_rect, Color::Red); - painter.draw_glyph(inner_rect.location(), glyph, Color::White); - } else { - painter.draw_glyph(inner_rect.location(), glyph, Color::Black); - } - } - } - - if (is_focused()) - painter.draw_focus_rect(rect()); -} - -void GlyphMapWidget::mousedown_event(GMouseEvent& event) -{ - // FIXME: This is a silly loop. - for (unsigned glyph = 0; glyph < 256; ++glyph) { - if (get_outer_rect(glyph).contains(event.position())) { - set_selected_glyph(glyph); - break; - } - } -} - -GlyphEditorWidget::GlyphEditorWidget(Font& mutable_font, GWidget* parent) - : GWidget(parent) - , m_font(mutable_font) -{ - set_relative_rect({ 0, 0, preferred_width(), preferred_height() }); -} - -GlyphEditorWidget::~GlyphEditorWidget() -{ -} - -void GlyphEditorWidget::set_glyph(byte glyph) -{ - if (m_glyph == glyph) - return; - m_glyph = glyph; - update(); -} - -void GlyphEditorWidget::paint_event(GPaintEvent&) -{ - GPainter painter(*this); - painter.fill_rect(rect(), Color::White); - painter.draw_rect(rect(), Color::Black); - - for (int y = 0; y < font().glyph_height(); ++y) - painter.draw_line({ 0, y * m_scale }, { font().max_glyph_width() * m_scale, y * m_scale }, Color::Black); - - for (int x = 0; x < font().max_glyph_width(); ++x) - painter.draw_line({ x * m_scale, 0 }, { x * m_scale, font().glyph_height() * m_scale }, Color::Black); - - painter.translate(1, 1); - - auto bitmap = font().glyph_bitmap(m_glyph); - - for (int y = 0; y < font().glyph_height(); ++y) { - for (int x = 0; x < font().max_glyph_width(); ++x) { - Rect rect { x * m_scale, y * m_scale, m_scale, m_scale }; - if (x >= font().glyph_width(m_glyph)) { - painter.fill_rect(rect, Color::MidGray); - } else { - if (bitmap.bit_at(x, y)) - painter.fill_rect(rect, Color::Black); - } - } - } - - if (is_focused()) { - painter.translate(-1, -1); - painter.draw_focus_rect(rect()); - } -} - -void GlyphEditorWidget::mousedown_event(GMouseEvent& event) -{ - draw_at_mouse(event); -} - -void GlyphEditorWidget::mousemove_event(GMouseEvent& event) -{ - if (event.buttons() & (GMouseButton::Left | GMouseButton::Right)) - draw_at_mouse(event); -} - -void GlyphEditorWidget::draw_at_mouse(const GMouseEvent& event) -{ - bool set = event.buttons() & GMouseButton::Left; - bool unset = event.buttons() & GMouseButton::Right; - if (!(set ^ unset)) - return; - int x = (event.x() - 1) / m_scale; - int y = (event.y() - 1) / m_scale; - auto bitmap = font().glyph_bitmap(m_glyph); - if (x >= bitmap.width()) - return; - if (y >= bitmap.height()) - return; - if (bitmap.bit_at(x, y) == set) - return; - bitmap.set_bit_at(x, y, set); - if (on_glyph_altered) - on_glyph_altered(); - update(); -} - -int GlyphEditorWidget::preferred_width() const -{ - return font().max_glyph_width() * m_scale + 1; -} - -int GlyphEditorWidget::preferred_height() const -{ - return font().glyph_height() * m_scale + 1; -} diff --git a/Applications/FontEditor/FontEditor.h b/Applications/FontEditor/FontEditor.h index c53d8bb087..3d41d6b768 100644 --- a/Applications/FontEditor/FontEditor.h +++ b/Applications/FontEditor/FontEditor.h @@ -22,65 +22,3 @@ private: String m_path; }; - -class GlyphMapWidget final : public GWidget { -public: - GlyphMapWidget(Font&, GWidget* parent); - virtual ~GlyphMapWidget() override; - - byte selected_glyph() const { return m_selected_glyph; } - void set_selected_glyph(byte); - - int rows() const { return m_rows; } - int columns() const { return 256 / m_rows; } - - int preferred_width() const; - int preferred_height() const; - - Font& font() { return *m_font; } - const Font& font() const { return *m_font; } - - Function on_glyph_selected; - -private: - virtual void paint_event(GPaintEvent&) override; - virtual void mousedown_event(GMouseEvent&) override; - virtual bool accepts_focus() const override { return true; } - - Rect get_outer_rect(byte glyph) const; - - RetainPtr m_font; - int m_rows { 8 }; - int m_horizontal_spacing { 2 }; - int m_vertical_spacing { 2 }; - byte m_selected_glyph { 0 }; -}; - -class GlyphEditorWidget final : public GWidget { -public: - GlyphEditorWidget(Font&, GWidget* parent); - virtual ~GlyphEditorWidget() override; - - byte glyph() const { return m_glyph; } - void set_glyph(byte); - - int preferred_width() const; - int preferred_height() const; - - Font& font() { return *m_font; } - const Font& font() const { return *m_font; } - - Function on_glyph_altered; - -private: - virtual void paint_event(GPaintEvent&) override; - virtual void mousedown_event(GMouseEvent&) override; - virtual void mousemove_event(GMouseEvent&) override; - virtual bool accepts_focus() const override { return true; } - - void draw_at_mouse(const GMouseEvent&); - - RetainPtr m_font; - byte m_glyph { 0 }; - int m_scale { 10 }; -}; diff --git a/Applications/FontEditor/GlyphEditorWidget.cpp b/Applications/FontEditor/GlyphEditorWidget.cpp new file mode 100644 index 0000000000..2d1107f7a9 --- /dev/null +++ b/Applications/FontEditor/GlyphEditorWidget.cpp @@ -0,0 +1,97 @@ +#include "GlyphEditorWidget.h" +#include + +GlyphEditorWidget::GlyphEditorWidget(Font& mutable_font, GWidget* parent) + : GWidget(parent) + , m_font(mutable_font) +{ + set_relative_rect({ 0, 0, preferred_width(), preferred_height() }); +} + +GlyphEditorWidget::~GlyphEditorWidget() +{ +} + +void GlyphEditorWidget::set_glyph(byte glyph) +{ + if (m_glyph == glyph) + return; + m_glyph = glyph; + update(); +} + +void GlyphEditorWidget::paint_event(GPaintEvent&) +{ + GPainter painter(*this); + painter.fill_rect(rect(), Color::White); + painter.draw_rect(rect(), Color::Black); + + for (int y = 0; y < font().glyph_height(); ++y) + painter.draw_line({ 0, y * m_scale }, { font().max_glyph_width() * m_scale, y * m_scale }, Color::Black); + + for (int x = 0; x < font().max_glyph_width(); ++x) + painter.draw_line({ x * m_scale, 0 }, { x * m_scale, font().glyph_height() * m_scale }, Color::Black); + + painter.translate(1, 1); + + auto bitmap = font().glyph_bitmap(m_glyph); + + for (int y = 0; y < font().glyph_height(); ++y) { + for (int x = 0; x < font().max_glyph_width(); ++x) { + Rect rect { x * m_scale, y * m_scale, m_scale, m_scale }; + if (x >= font().glyph_width(m_glyph)) { + painter.fill_rect(rect, Color::MidGray); + } else { + if (bitmap.bit_at(x, y)) + painter.fill_rect(rect, Color::Black); + } + } + } + + if (is_focused()) { + painter.translate(-1, -1); + painter.draw_focus_rect(rect()); + } +} + +void GlyphEditorWidget::mousedown_event(GMouseEvent& event) +{ + draw_at_mouse(event); +} + +void GlyphEditorWidget::mousemove_event(GMouseEvent& event) +{ + if (event.buttons() & (GMouseButton::Left | GMouseButton::Right)) + draw_at_mouse(event); +} + +void GlyphEditorWidget::draw_at_mouse(const GMouseEvent& event) +{ + bool set = event.buttons() & GMouseButton::Left; + bool unset = event.buttons() & GMouseButton::Right; + if (!(set ^ unset)) + return; + int x = (event.x() - 1) / m_scale; + int y = (event.y() - 1) / m_scale; + auto bitmap = font().glyph_bitmap(m_glyph); + if (x >= bitmap.width()) + return; + if (y >= bitmap.height()) + return; + if (bitmap.bit_at(x, y) == set) + return; + bitmap.set_bit_at(x, y, set); + if (on_glyph_altered) + on_glyph_altered(); + update(); +} + +int GlyphEditorWidget::preferred_width() const +{ + return font().max_glyph_width() * m_scale + 1; +} + +int GlyphEditorWidget::preferred_height() const +{ + return font().glyph_height() * m_scale + 1; +} diff --git a/Applications/FontEditor/GlyphEditorWidget.h b/Applications/FontEditor/GlyphEditorWidget.h new file mode 100644 index 0000000000..4d048742c6 --- /dev/null +++ b/Applications/FontEditor/GlyphEditorWidget.h @@ -0,0 +1,31 @@ +#include +#include + +class GlyphEditorWidget final : public GWidget { +public: + GlyphEditorWidget(Font&, GWidget* parent); + virtual ~GlyphEditorWidget() override; + + byte glyph() const { return m_glyph; } + void set_glyph(byte); + + int preferred_width() const; + int preferred_height() const; + + Font& font() { return *m_font; } + const Font& font() const { return *m_font; } + + Function on_glyph_altered; + +private: + virtual void paint_event(GPaintEvent&) override; + virtual void mousedown_event(GMouseEvent&) override; + virtual void mousemove_event(GMouseEvent&) override; + virtual bool accepts_focus() const override { return true; } + + void draw_at_mouse(const GMouseEvent&); + + RetainPtr m_font; + byte m_glyph { 0 }; + int m_scale { 10 }; +}; diff --git a/Applications/FontEditor/GlyphMapWidget.cpp b/Applications/FontEditor/GlyphMapWidget.cpp new file mode 100644 index 0000000000..78a86dda64 --- /dev/null +++ b/Applications/FontEditor/GlyphMapWidget.cpp @@ -0,0 +1,87 @@ +#include "GlyphMapWidget.h" +#include + +GlyphMapWidget::GlyphMapWidget(Font& mutable_font, GWidget* parent) + : GWidget(parent) + , m_font(mutable_font) +{ + set_relative_rect({ 0, 0, preferred_width(), preferred_height() }); +} + +GlyphMapWidget::~GlyphMapWidget() +{ +} + +int GlyphMapWidget::preferred_width() const +{ + return columns() * (font().max_glyph_width() + m_horizontal_spacing) + 2; +} + +int GlyphMapWidget::preferred_height() const +{ + return rows() * (font().glyph_height() + m_vertical_spacing) + 2; +} + +void GlyphMapWidget::set_selected_glyph(byte glyph) +{ + if (m_selected_glyph == glyph) + return; + m_selected_glyph = glyph; + if (on_glyph_selected) + on_glyph_selected(glyph); + update(); +} + +Rect GlyphMapWidget::get_outer_rect(byte glyph) const +{ + int row = glyph / columns(); + int column = glyph % columns(); + return { + column * (font().max_glyph_width() + m_horizontal_spacing) + 1, + row * (font().glyph_height() + m_vertical_spacing) + 1, + font().max_glyph_width() + m_horizontal_spacing, + font().glyph_height() + m_horizontal_spacing + }; +} + +void GlyphMapWidget::paint_event(GPaintEvent&) +{ + GPainter painter(*this); + painter.set_font(font()); + painter.fill_rect(rect(), Color::White); + painter.draw_rect(rect(), Color::Black); + + byte glyph = 0; + + for (int row = 0; row < rows(); ++row) { + for (int column = 0; column < columns(); ++column, ++glyph) { + Rect outer_rect = get_outer_rect(glyph); + Rect inner_rect( + outer_rect.x() + m_horizontal_spacing / 2, + outer_rect.y() + m_vertical_spacing / 2, + font().max_glyph_width(), + font().glyph_height() + ); + if (glyph == m_selected_glyph) { + painter.fill_rect(outer_rect, Color::Red); + painter.draw_glyph(inner_rect.location(), glyph, Color::White); + } else { + painter.draw_glyph(inner_rect.location(), glyph, Color::Black); + } + } + } + + if (is_focused()) + painter.draw_focus_rect(rect()); +} + +void GlyphMapWidget::mousedown_event(GMouseEvent& event) +{ + // FIXME: This is a silly loop. + for (unsigned glyph = 0; glyph < 256; ++glyph) { + if (get_outer_rect(glyph).contains(event.position())) { + set_selected_glyph(glyph); + break; + } + } +} diff --git a/Applications/FontEditor/GlyphMapWidget.h b/Applications/FontEditor/GlyphMapWidget.h new file mode 100644 index 0000000000..23c85d6cf4 --- /dev/null +++ b/Applications/FontEditor/GlyphMapWidget.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include + +class GlyphMapWidget final : public GWidget { +public: + GlyphMapWidget(Font&, GWidget* parent); + virtual ~GlyphMapWidget() override; + + byte selected_glyph() const { return m_selected_glyph; } + void set_selected_glyph(byte); + + int rows() const { return m_rows; } + int columns() const { return 256 / m_rows; } + + int preferred_width() const; + int preferred_height() const; + + Font& font() { return *m_font; } + const Font& font() const { return *m_font; } + + Function on_glyph_selected; + +private: + virtual void paint_event(GPaintEvent&) override; + virtual void mousedown_event(GMouseEvent&) override; + virtual bool accepts_focus() const override { return true; } + + Rect get_outer_rect(byte glyph) const; + + RetainPtr m_font; + int m_rows { 8 }; + int m_horizontal_spacing { 2 }; + int m_vertical_spacing { 2 }; + byte m_selected_glyph { 0 }; +}; diff --git a/Applications/FontEditor/Makefile b/Applications/FontEditor/Makefile index b7e27cbfb9..7999e83d7a 100644 --- a/Applications/FontEditor/Makefile +++ b/Applications/FontEditor/Makefile @@ -1,10 +1,12 @@ OBJS = \ FontEditor.o \ + GlyphMapWidget.o \ + GlyphEditorWidget.o \ main.o APP = FontEditor -STANDARD_FLAGS = -std=c++17 +STANDARD_FLAGS = -std=c++17 -Wno-sized-deallocation WARNING_FLAGS = -Wextra -Wall -Wundef -Wcast-qual -Wwrite-strings -Wimplicit-fallthrough FLAVOR_FLAGS = -fno-exceptions -fno-rtti OPTIMIZATION_FLAGS = -Os