From 18ae37439a4fdd65d98b94c75c5d64480a827289 Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Sun, 18 Apr 2021 21:12:52 +0300 Subject: [PATCH] FontEditor+LibGfx: Allow user to specify if a specific glyph is present This replaces the glyph width spinbox in the font editor with a checkbox when editing fixed width fonts that indicates if the currently selected character's glyph is present in the edited font (For variable width fonts a non zero width implies presence) This commit also changes the background color of glyphs in the glyph map based on the presence of each specific glyph in the font. --- .../Applications/FontEditor/FontEditor.cpp | 28 +++++++++++++++---- Userland/Applications/FontEditor/FontEditor.h | 1 + .../FontEditor/FontEditorWindow.gml | 5 ++++ .../FontEditor/GlyphMapWidget.cpp | 5 ++-- Userland/Libraries/LibGfx/BitmapFont.h | 2 ++ 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/Userland/Applications/FontEditor/FontEditor.cpp b/Userland/Applications/FontEditor/FontEditor.cpp index 5887d93199..69bae932e0 100644 --- a/Userland/Applications/FontEditor/FontEditor.cpp +++ b/Userland/Applications/FontEditor/FontEditor.cpp @@ -105,6 +105,7 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& m_glyph_editor_container = *find_descendant_of_type_named("glyph_editor_container"); m_left_column_container = *find_descendant_of_type_named("left_column_container"); m_glyph_editor_width_spinbox = *find_descendant_of_type_named("glyph_editor_width_spinbox"); + m_glyph_editor_present_checkbox = *find_descendant_of_type_named("glyph_editor_present_checkbox"); m_name_textbox = *find_descendant_of_type_named("name_textbox"); m_family_textbox = *find_descendant_of_type_named("family_textbox"); m_presentation_spinbox = *find_descendant_of_type_named("presentation_spinbox"); @@ -206,7 +207,9 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& m_edited_font->set_glyph_width(m_glyph_map_widget->selected_glyph(), m_edited_font->max_glyph_width()); m_glyph_editor_widget->delete_glyph(); m_glyph_map_widget->update_glyph(m_glyph_map_widget->selected_glyph()); - m_glyph_editor_width_spinbox->set_value(m_edited_font->glyph_width(m_glyph_map_widget->selected_glyph())); + auto glyph_width = m_edited_font->raw_glyph_width(m_glyph_map_widget->selected_glyph()); + m_glyph_editor_width_spinbox->set_value(glyph_width); + m_glyph_editor_present_checkbox->set_checked(glyph_width > 0); }); m_open_preview_action = GUI::Action::create("Preview Font", Gfx::Bitmap::load_from_file("/res/icons/16x16/find.png"), [&](auto&) { if (!m_font_preview_window) @@ -242,7 +245,9 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& m_glyph_map_widget->on_glyph_selected = [&](int glyph) { m_glyph_editor_widget->set_glyph(glyph); - m_glyph_editor_width_spinbox->set_value(m_edited_font->glyph_width(m_glyph_map_widget->selected_glyph())); + auto glyph_width = m_edited_font->raw_glyph_width(m_glyph_map_widget->selected_glyph()); + m_glyph_editor_width_spinbox->set_value(glyph_width); + m_glyph_editor_present_checkbox->set_checked(glyph_width > 0); StringBuilder builder; builder.appendff("{:#02x} (", glyph); if (glyph < 128) { @@ -255,7 +260,7 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& builder.append(128 | (glyph % 64)); } builder.append(") "); - builder.appendff("[{}x{}]", m_edited_font->glyph_width(glyph), m_edited_font->glyph_height()); + builder.appendff("[{}x{}]", m_edited_font->raw_glyph_width(glyph), m_edited_font->glyph_height()); statusbar.set_text(builder.to_string()); }; @@ -269,8 +274,11 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& m_fixed_width_checkbox->on_checked = [&, update_demo](bool checked) { m_edited_font->set_fixed_width(checked); - m_glyph_editor_width_spinbox->set_enabled(!m_edited_font->is_fixed_width()); - m_glyph_editor_width_spinbox->set_value(m_edited_font->glyph_width(m_glyph_map_widget->selected_glyph())); + auto glyph_width = m_edited_font->raw_glyph_width(m_glyph_map_widget->selected_glyph()); + m_glyph_editor_width_spinbox->set_visible(!checked); + m_glyph_editor_width_spinbox->set_value(glyph_width); + m_glyph_editor_present_checkbox->set_visible(checked); + m_glyph_editor_present_checkbox->set_checked(glyph_width > 0); m_glyph_editor_widget->update(); update_demo(); }; @@ -282,6 +290,13 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& update_demo(); }; + m_glyph_editor_present_checkbox->on_checked = [this, update_demo](bool checked) { + m_edited_font->set_glyph_width(m_glyph_map_widget->selected_glyph(), checked ? m_edited_font->glyph_fixed_width() : 0); + m_glyph_editor_widget->update(); + m_glyph_map_widget->update_glyph(m_glyph_map_widget->selected_glyph()); + update_demo(); + }; + m_weight_combobox->on_change = [this]() { m_edited_font->set_weight(GUI::name_to_weight(m_weight_combobox->text())); }; @@ -332,8 +347,9 @@ void FontEditorWidget::initialize(const String& path, RefPtr&& m_glyph_editor_container->set_fixed_size(m_glyph_editor_widget->preferred_width(), m_glyph_editor_widget->preferred_height()); m_left_column_container->set_fixed_width(m_glyph_editor_widget->preferred_width()); - m_glyph_editor_width_spinbox->set_enabled(!m_edited_font->is_fixed_width()); + m_glyph_editor_width_spinbox->set_visible(!m_edited_font->is_fixed_width()); m_glyph_editor_width_spinbox->set_max(m_edited_font->max_glyph_width()); + m_glyph_editor_present_checkbox->set_visible(m_edited_font->is_fixed_width()); m_name_textbox->set_text(m_edited_font->name()); m_family_textbox->set_text(m_edited_font->family()); diff --git a/Userland/Applications/FontEditor/FontEditor.h b/Userland/Applications/FontEditor/FontEditor.h index ec3a2cce49..5bc64e19d6 100644 --- a/Userland/Applications/FontEditor/FontEditor.h +++ b/Userland/Applications/FontEditor/FontEditor.h @@ -79,6 +79,7 @@ private: RefPtr m_mean_line_spinbox; RefPtr m_presentation_spinbox; RefPtr m_glyph_editor_width_spinbox; + RefPtr m_glyph_editor_present_checkbox; RefPtr m_name_textbox; RefPtr m_family_textbox; RefPtr m_fixed_width_checkbox; diff --git a/Userland/Applications/FontEditor/FontEditorWindow.gml b/Userland/Applications/FontEditor/FontEditorWindow.gml index 37969dc29c..7c9e7a0dc8 100644 --- a/Userland/Applications/FontEditor/FontEditorWindow.gml +++ b/Userland/Applications/FontEditor/FontEditorWindow.gml @@ -34,6 +34,11 @@ @GUI::SpinBox { name: "glyph_editor_width_spinbox" } + + @GUI::CheckBox { + name: "glyph_editor_present_checkbox" + text: "Glyph Present" + } } @GUI::Widget { diff --git a/Userland/Applications/FontEditor/GlyphMapWidget.cpp b/Userland/Applications/FontEditor/GlyphMapWidget.cpp index c03302f93e..3ed04e3529 100644 --- a/Userland/Applications/FontEditor/GlyphMapWidget.cpp +++ b/Userland/Applications/FontEditor/GlyphMapWidget.cpp @@ -107,7 +107,7 @@ void GlyphMapWidget::paint_event(GUI::PaintEvent& event) painter.add_clip_rect(event.rect()); painter.set_font(font()); - painter.fill_rect(widget_inner_rect(), palette().base()); + painter.fill_rect(widget_inner_rect(), palette().inactive_window_title()); for (int glyph = 0; glyph < m_glyph_count; ++glyph) { Gfx::IntRect outer_rect = get_outer_rect(glyph); @@ -119,7 +119,8 @@ void GlyphMapWidget::paint_event(GUI::PaintEvent& event) if (glyph == m_selected_glyph) { painter.fill_rect(outer_rect, is_focused() ? palette().selection() : palette().inactive_selection()); painter.draw_glyph(inner_rect.location(), glyph, is_focused() ? palette().selection_text() : palette().inactive_selection_text()); - } else { + } else if (m_font->contains_glyph(glyph)) { + painter.fill_rect(outer_rect, palette().base()); painter.draw_glyph(inner_rect.location(), glyph, palette().base_text()); } } diff --git a/Userland/Libraries/LibGfx/BitmapFont.h b/Userland/Libraries/LibGfx/BitmapFont.h index 4fab8edc27..67f7354e9c 100644 --- a/Userland/Libraries/LibGfx/BitmapFont.h +++ b/Userland/Libraries/LibGfx/BitmapFont.h @@ -70,6 +70,8 @@ public: u8 glyph_height() const { return m_glyph_height; } int x_height() const { return m_x_height; } + u8 raw_glyph_width(size_t ch) const { return m_glyph_widths[ch]; } + u8 min_glyph_width() const { return m_min_glyph_width; } u8 max_glyph_width() const { return m_max_glyph_width; } u8 glyph_fixed_width() const { return m_glyph_width; }