From a486415f03771989cb1c5871454a3f47e0256824 Mon Sep 17 00:00:00 2001 From: thankyouverycool <66646555+thankyouverycool@users.noreply.github.com> Date: Thu, 9 Sep 2021 07:41:08 -0400 Subject: [PATCH] FontEditor: Update editor to handle new font format The editor now unmasks fonts on load, mapping their glyphs to the complete unicode character set, and masks them upon saving to reduce disk space. This is a naive approach in terms of memory usage and can be improved but whose immediate goal is to allow editing any glyph without concern for range allocation. --- .../Applications/FontEditor/FontEditor.cpp | 24 +++--------------- Userland/Applications/FontEditor/FontEditor.h | 2 -- .../FontEditor/FontEditorWindow.gml | 9 ------- .../FontEditor/GlyphEditorWidget.cpp | 16 ++++++------ .../FontEditor/GlyphMapWidget.cpp | 12 ++++++--- .../Applications/FontEditor/GlyphMapWidget.h | 3 ++- .../Applications/FontEditor/NewFontDialog.cpp | 17 ------------- .../Applications/FontEditor/NewFontDialog.h | 4 --- .../FontEditor/NewFontDialogPage1.gml | 25 +------------------ Userland/Applications/FontEditor/main.cpp | 5 ++-- 10 files changed, 26 insertions(+), 91 deletions(-) diff --git a/Userland/Applications/FontEditor/FontEditor.cpp b/Userland/Applications/FontEditor/FontEditor.cpp index d98ce12049f..17b4f0532a9 100644 --- a/Userland/Applications/FontEditor/FontEditor.cpp +++ b/Userland/Applications/FontEditor/FontEditor.cpp @@ -119,7 +119,6 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& m_family_textbox = *find_descendant_of_type_named("family_textbox"); m_presentation_spinbox = *find_descendant_of_type_named("presentation_spinbox"); m_weight_combobox = *find_descendant_of_type_named("weight_combobox"); - m_type_combobox = *find_descendant_of_type_named("type_combobox"); m_spacing_spinbox = *find_descendant_of_type_named("spacing_spinbox"); m_mean_line_spinbox = *find_descendant_of_type_named("mean_line_spinbox"); m_baseline_spinbox = *find_descendant_of_type_named("baseline_spinbox"); @@ -170,7 +169,7 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& if (new_font_wizard->exec() == GUI::Dialog::ExecOK) { auto metadata = new_font_wizard->new_font_metadata(); - RefPtr new_font = Gfx::BitmapFont::create(metadata.glyph_height, metadata.glyph_width, metadata.is_fixed_width, metadata.type); + RefPtr new_font = Gfx::BitmapFont::create(metadata.glyph_height, metadata.glyph_width, metadata.is_fixed_width, 0x110000); if (!new_font) { GUI::MessageBox::show(window(), "Failed to create new font.", "Font Editor", GUI::MessageBox::Type::Error); return; @@ -208,7 +207,7 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& GUI::MessageBox::show(window(), message, "Font Editor", GUI::MessageBox::Type::Error); return; } - RefPtr new_font = static_ptr_cast(bitmap_font->clone()); + RefPtr new_font = static_ptr_cast(bitmap_font->unmasked_character_set()); if (!new_font) { String message = String::formatted("Couldn't load font: {}\n", open_path.value()); GUI::MessageBox::show(window(), message, "Font Editor", GUI::MessageBox::Type::Error); @@ -396,12 +395,6 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& did_modify_font(); }; - m_type_combobox->on_change = [this](auto&, const auto& index) { - m_edited_font->set_type(static_cast(index.row())); - m_glyph_map_widget->reprobe_font(); - did_modify_font(); - }; - m_presentation_spinbox->on_change = [this, update_demo](int value) { m_edited_font->set_presentation_size(value); update_demo(); @@ -487,16 +480,6 @@ void FontEditorWidget::initialize(const String& path, RefPtr&& i++; } - m_font_type_list.clear(); - StringBuilder type_count; - for (int i = 0; i < Gfx::FontTypes::__Count; i++) { - type_count.appendff("{}", Gfx::BitmapFont::type_name_by_type(static_cast(i))); - m_font_type_list.append(type_count.to_string()); - type_count.clear(); - } - m_type_combobox->set_model(*GUI::ItemListModel::create(m_font_type_list)); - m_type_combobox->set_selected_index(m_edited_font->type()); - m_fixed_width_checkbox->set_checked(m_edited_font->is_fixed_width()); m_glyph_map_widget->set_selected_glyph('A'); @@ -562,7 +545,8 @@ void FontEditorWidget::initialize_menubar(GUI::Window& window) bool FontEditorWidget::save_as(const String& path) { - auto ret_val = m_edited_font->write_to_file(path); + auto saved_font = m_edited_font->masked_character_set(); + auto ret_val = saved_font->write_to_file(path); if (!ret_val) { GUI::MessageBox::show(window(), "The font file could not be saved.", "Save failed", GUI::MessageBox::Type::Error); return false; diff --git a/Userland/Applications/FontEditor/FontEditor.h b/Userland/Applications/FontEditor/FontEditor.h index 13e9da8bf2b..d78311e363f 100644 --- a/Userland/Applications/FontEditor/FontEditor.h +++ b/Userland/Applications/FontEditor/FontEditor.h @@ -73,7 +73,6 @@ private: RefPtr m_left_column_container; RefPtr m_glyph_editor_container; RefPtr m_weight_combobox; - RefPtr m_type_combobox; RefPtr m_spacing_spinbox; RefPtr m_baseline_spinbox; RefPtr m_mean_line_spinbox; @@ -87,6 +86,5 @@ private: String m_path; Vector m_font_weight_list; - Vector m_font_type_list; bool m_font_metadata { true }; }; diff --git a/Userland/Applications/FontEditor/FontEditorWindow.gml b/Userland/Applications/FontEditor/FontEditorWindow.gml index 45c9b8bc4c3..0ccf0577d63 100644 --- a/Userland/Applications/FontEditor/FontEditorWindow.gml +++ b/Userland/Applications/FontEditor/FontEditorWindow.gml @@ -207,15 +207,6 @@ text: "Fixed width" autosize: true } - - @GUI::Widget { - fixed_width: 12 - } - - @GUI::ComboBox { - name: "type_combobox" - model_only: true - } } } } diff --git a/Userland/Applications/FontEditor/GlyphEditorWidget.cpp b/Userland/Applications/FontEditor/GlyphEditorWidget.cpp index 9a25ed3e71f..8844d731137 100644 --- a/Userland/Applications/FontEditor/GlyphEditorWidget.cpp +++ b/Userland/Applications/FontEditor/GlyphEditorWidget.cpp @@ -39,7 +39,7 @@ void GlyphEditorWidget::delete_glyph() { if (on_undo_event) on_undo_event(); - auto bitmap = font().glyph(m_glyph).glyph_bitmap(); + auto bitmap = font().raw_glyph(m_glyph).glyph_bitmap(); for (int x = 0; x < bitmap.width(); x++) for (int y = 0; y < bitmap.height(); y++) bitmap.set_bit_at(x, y, false); @@ -56,7 +56,7 @@ void GlyphEditorWidget::cut_glyph() void GlyphEditorWidget::copy_glyph() { - auto bitmap = font().glyph(m_glyph).glyph_bitmap(); + auto bitmap = font().raw_glyph(m_glyph).glyph_bitmap(); u8 bits[bitmap.width()][bitmap.height()]; for (int x = 0; x < bitmap.width(); x++) { for (int y = 0; y < bitmap.height(); y++) { @@ -105,7 +105,7 @@ void GlyphEditorWidget::paste_glyph() } } - auto bitmap = font().glyph(m_glyph).glyph_bitmap(); + auto bitmap = font().raw_glyph(m_glyph).glyph_bitmap(); for (int x = 0; x < min(bitmap.width(), buffer_width.value()); x++) { for (int y = 0; y < min(bitmap.height(), buffer_height.value()); y++) { if (bits[x][y]) @@ -138,7 +138,7 @@ void GlyphEditorWidget::paint_event(GUI::PaintEvent& event) for (int x = 1; x < font().max_glyph_width(); ++x) painter.draw_line({ x * m_scale, 0 }, { x * m_scale, font().glyph_height() * m_scale }, palette().threed_shadow2()); - auto bitmap = font().glyph(m_glyph).glyph_bitmap(); + auto bitmap = font().raw_glyph(m_glyph).glyph_bitmap(); for (int y = 0; y < font().glyph_height(); ++y) { for (int x = 0; x < font().max_glyph_width(); ++x) { @@ -155,7 +155,7 @@ void GlyphEditorWidget::paint_event(GUI::PaintEvent& event) bool GlyphEditorWidget::is_glyph_empty() { - auto bitmap = font().glyph(m_glyph).glyph_bitmap(); + auto bitmap = font().raw_glyph(m_glyph).glyph_bitmap(); for (int x = 0; x < bitmap.width(); x++) for (int y = 0; y < bitmap.height(); y++) if (bitmap.bit_at(x, y)) @@ -176,7 +176,7 @@ void GlyphEditorWidget::mousedown_event(GUI::MouseEvent& event) draw_at_mouse(event); } else { memset(m_movable_bits, 0, sizeof(m_movable_bits)); - auto bitmap = font().glyph(m_glyph).glyph_bitmap(); + auto bitmap = font().raw_glyph(m_glyph).glyph_bitmap(); for (int x = s_max_width; x < s_max_width + bitmap.width(); x++) for (int y = s_max_height; y < s_max_height + bitmap.height(); y++) m_movable_bits[x][y] = bitmap.bit_at(x - s_max_width, y - s_max_height); @@ -221,7 +221,7 @@ void GlyphEditorWidget::draw_at_mouse(const GUI::MouseEvent& event) return; int x = (event.x() - 1) / m_scale; int y = (event.y() - 1) / m_scale; - auto bitmap = font().glyph(m_glyph).glyph_bitmap(); + auto bitmap = font().raw_glyph(m_glyph).glyph_bitmap(); if (x < 0 || x >= bitmap.width()) return; if (y < 0 || y >= bitmap.height()) @@ -238,7 +238,7 @@ void GlyphEditorWidget::move_at_mouse(const GUI::MouseEvent& event) { int x_delta = ((event.x() - 1) / m_scale) - x_offset; int y_delta = ((event.y() - 1) / m_scale) - y_offset; - auto bitmap = font().glyph(m_glyph).glyph_bitmap(); + auto bitmap = font().raw_glyph(m_glyph).glyph_bitmap(); if (abs(x_delta) > bitmap.width() || abs(y_delta) > bitmap.height()) return; for (int x = 0; x < bitmap.width(); x++) { diff --git a/Userland/Applications/FontEditor/GlyphMapWidget.cpp b/Userland/Applications/FontEditor/GlyphMapWidget.cpp index 4de71039480..b88e3d9b9c4 100644 --- a/Userland/Applications/FontEditor/GlyphMapWidget.cpp +++ b/Userland/Applications/FontEditor/GlyphMapWidget.cpp @@ -25,7 +25,6 @@ void GlyphMapWidget::initialize(Gfx::BitmapFont& mutable_font) if (m_font == mutable_font) return; m_font = mutable_font; - m_glyph_count = mutable_font.glyph_count(); m_selected_glyph = 0; vertical_scrollbar().set_step(font().glyph_height() + m_vertical_spacing); } @@ -33,6 +32,8 @@ void GlyphMapWidget::initialize(Gfx::BitmapFont& mutable_font) void GlyphMapWidget::resize_event(GUI::ResizeEvent& event) { int event_width = event.size().width() - this->vertical_scrollbar().width() - (frame_thickness() * 2) - m_horizontal_spacing; + int event_height = event.size().height() - (frame_thickness() * 2); + m_visible_glyphs = (event_width * event_height) / (font().max_glyph_width() * font().glyph_height()); m_columns = max(event_width / (font().max_glyph_width() + m_horizontal_spacing), 1); m_rows = ceil_div(m_glyph_count, m_columns); @@ -90,7 +91,10 @@ void GlyphMapWidget::paint_event(GUI::PaintEvent& event) painter.set_font(font()); painter.fill_rect(widget_inner_rect(), palette().inactive_window_title()); - for (int glyph = 0; glyph < m_glyph_count; ++glyph) { + int scroll_steps = this->vertical_scrollbar().value() / this->vertical_scrollbar().step(); + int first_visible_glyph = scroll_steps * columns(); + + for (int glyph = first_visible_glyph; glyph <= first_visible_glyph + m_visible_glyphs && glyph < m_glyph_count; ++glyph) { Gfx::IntRect outer_rect = get_outer_rect(glyph); Gfx::IntRect inner_rect( outer_rect.x() + m_horizontal_spacing / 2, @@ -99,9 +103,9 @@ void GlyphMapWidget::paint_event(GUI::PaintEvent& event) font().glyph_height()); if (glyph == m_selected_glyph) { painter.fill_rect(outer_rect, is_focused() ? palette().selection() : palette().inactive_selection()); - if (m_font->contains_glyph(glyph)) + if (m_font->raw_glyph_width(glyph)) painter.draw_glyph(inner_rect.location(), glyph, is_focused() ? palette().selection_text() : palette().inactive_selection_text()); - } else if (m_font->contains_glyph(glyph)) { + } else if (m_font->raw_glyph_width(glyph)) { painter.fill_rect(outer_rect, palette().base()); painter.draw_glyph(inner_rect.location(), glyph, palette().base_text()); } diff --git a/Userland/Applications/FontEditor/GlyphMapWidget.h b/Userland/Applications/FontEditor/GlyphMapWidget.h index a2dbcb4897f..af95f6e0507 100644 --- a/Userland/Applications/FontEditor/GlyphMapWidget.h +++ b/Userland/Applications/FontEditor/GlyphMapWidget.h @@ -41,10 +41,11 @@ private: Gfx::IntRect get_outer_rect(int glyph) const; RefPtr m_font; - int m_glyph_count { 384 }; + int m_glyph_count { 0x110000 }; int m_columns { 32 }; int m_rows { 12 }; int m_horizontal_spacing { 2 }; int m_vertical_spacing { 2 }; int m_selected_glyph { 0 }; + int m_visible_glyphs { 0 }; }; diff --git a/Userland/Applications/FontEditor/NewFontDialog.cpp b/Userland/Applications/FontEditor/NewFontDialog.cpp index 3d6a61c44b6..f6024a3226e 100644 --- a/Userland/Applications/FontEditor/NewFontDialog.cpp +++ b/Userland/Applications/FontEditor/NewFontDialog.cpp @@ -134,30 +134,14 @@ NewFontDialog::NewFontDialog(GUI::Window* parent_window) m_name_textbox = m_font_properties_page->body_widget().find_descendant_of_type_named("name_textbox"); m_family_textbox = m_font_properties_page->body_widget().find_descendant_of_type_named("family_textbox"); - m_type_combobox = m_font_properties_page->body_widget().find_descendant_of_type_named("type_combobox"); - m_type_info_label = m_font_properties_page->body_widget().find_descendant_of_type_named("type_info_label"); m_weight_combobox = m_font_properties_page->body_widget().find_descendant_of_type_named("weight_combobox"); m_presentation_spinbox = m_font_properties_page->body_widget().find_descendant_of_type_named("presentation_spinbox"); - m_type_info_label->set_text("\xE2\x84\xB9\t"); - m_type_info_label->set_tooltip("Font type governs maximum glyph count"); - for (auto& it : GUI::font_weight_names) m_font_weight_list.append(it.name); m_weight_combobox->set_model(*GUI::ItemListModel::create(m_font_weight_list)); m_weight_combobox->set_selected_index(3); - StringBuilder type_count; - for (int i = 0; i < Gfx::FontTypes::__Count; i++) { - type_count.appendff("{} ({})", - Gfx::BitmapFont::type_name_by_type(static_cast(i)), - Gfx::BitmapFont::glyph_count_by_type(static_cast(i))); - m_font_type_list.append(type_count.to_string()); - type_count.clear(); - } - m_type_combobox->set_model(*GUI::ItemListModel::create(m_font_type_list)); - m_type_combobox->set_selected_index(0); - m_presentation_spinbox->set_value(12); m_font_properties_page->on_page_enter = [&]() { @@ -225,7 +209,6 @@ void NewFontDialog::save_metadata() m_new_font_metadata.name = m_name_textbox->text(); m_new_font_metadata.family = m_family_textbox->text(); m_new_font_metadata.weight = GUI::name_to_weight(m_weight_combobox->text()); - m_new_font_metadata.type = static_cast(m_type_combobox->selected_index()); m_new_font_metadata.presentation_size = m_presentation_spinbox->value(); m_new_font_metadata.baseline = m_baseline_spinbox->value(); diff --git a/Userland/Applications/FontEditor/NewFontDialog.h b/Userland/Applications/FontEditor/NewFontDialog.h index 85724436b57..6245848ed48 100644 --- a/Userland/Applications/FontEditor/NewFontDialog.h +++ b/Userland/Applications/FontEditor/NewFontDialog.h @@ -36,7 +36,6 @@ private: u16 weight; String name; String family; - Gfx::FontTypes type; bool is_fixed_width; } m_new_font_metadata; @@ -47,8 +46,6 @@ private: RefPtr m_font_properties_page; RefPtr m_name_textbox; RefPtr m_family_textbox; - RefPtr m_type_combobox; - RefPtr m_type_info_label; RefPtr m_weight_combobox; RefPtr m_presentation_spinbox; @@ -62,6 +59,5 @@ private: RefPtr m_fixed_width_checkbox; Vector m_font_list; - Vector m_font_type_list; Vector m_font_weight_list; }; diff --git a/Userland/Applications/FontEditor/NewFontDialogPage1.gml b/Userland/Applications/FontEditor/NewFontDialogPage1.gml index 2f372622dcc..d70bc5a7936 100644 --- a/Userland/Applications/FontEditor/NewFontDialogPage1.gml +++ b/Userland/Applications/FontEditor/NewFontDialogPage1.gml @@ -4,7 +4,7 @@ } @GUI::Widget { - fixed_height: 160 + fixed_height: 138 layout: @GUI::VerticalBoxLayout { } @@ -42,29 +42,6 @@ fixed_height: 22 } - @GUI::Widget { - layout: @GUI::HorizontalBoxLayout { - } - - @GUI::Label { - fixed_width: 100 - text_alignment: "CenterLeft" - text: "Type:" - } - - @GUI::ComboBox { - name: "type_combobox" - fixed_width: 180 - model_only: true - } - - @GUI::Label { - name: "type_info_label" - text_alignment: "CenterLeft" - autosize: true - } - } - @GUI::Widget { layout: @GUI::HorizontalBoxLayout { } diff --git a/Userland/Applications/FontEditor/main.cpp b/Userland/Applications/FontEditor/main.cpp index 4c87e48ee0e..cca06c4ed79 100644 --- a/Userland/Applications/FontEditor/main.cpp +++ b/Userland/Applications/FontEditor/main.cpp @@ -52,7 +52,8 @@ int main(int argc, char** argv) RefPtr edited_font; if (path == nullptr) { - edited_font = static_ptr_cast(Gfx::FontDatabase::default_font().clone()); + auto bitmap_font = static_ptr_cast(Gfx::FontDatabase::default_font().clone()); + edited_font = static_ptr_cast(bitmap_font->unmasked_character_set()); } else { auto bitmap_font = Gfx::BitmapFont::load_from_file(path); if (!bitmap_font) { @@ -60,7 +61,7 @@ int main(int argc, char** argv) GUI::MessageBox::show(nullptr, message, "Font Editor", GUI::MessageBox::Type::Error); return 1; } - edited_font = static_ptr_cast(bitmap_font->clone()); + edited_font = static_ptr_cast(bitmap_font->unmasked_character_set()); if (!edited_font) { String message = String::formatted("Couldn't load font: {}\n", path); GUI::MessageBox::show(nullptr, message, "Font Editor", GUI::MessageBox::Type::Error);