From 53f045a369deb833eee6b5df79682253d1ea4fdc Mon Sep 17 00:00:00 2001 From: David Capello Date: Mon, 15 Apr 2024 18:52:36 -0300 Subject: [PATCH] Add Bold/Italic buttons to select a font --- src/app/commands/cmd_paste_text.cpp | 1 + src/app/font_info.cpp | 28 +++++++++++++++-- src/app/font_info.h | 5 +++ src/app/ui/button_set.cpp | 7 +++-- src/app/ui/button_set.h | 4 +-- src/app/ui/font_entry.cpp | 48 +++++++++++++++++++++++++++++ src/app/ui/font_entry.h | 8 +++++ src/app/ui/font_popup.cpp | 46 ++++++++++++--------------- 8 files changed, 112 insertions(+), 35 deletions(-) diff --git a/src/app/commands/cmd_paste_text.cpp b/src/app/commands/cmd_paste_text.cpp index 41816786f..565b23972 100644 --- a/src/app/commands/cmd_paste_text.cpp +++ b/src/app/commands/cmd_paste_text.cpp @@ -82,6 +82,7 @@ void PasteTextCommand::onExecute(Context* ctx) fontInfo = FontInfo(FontInfo::Type::File, pref.textTool.fontFace(), pref.textTool.fontSize(), + text::FontStyle(), pref.textTool.antialias()); } // New configuration diff --git a/src/app/font_info.cpp b/src/app/font_info.cpp index 220790a7f..d1d62f6cd 100644 --- a/src/app/font_info.cpp +++ b/src/app/font_info.cpp @@ -24,11 +24,13 @@ namespace app { FontInfo::FontInfo(Type type, const std::string& name, const float size, + const text::FontStyle style, const bool antialias, const text::TypefaceRef& typeface) : m_type(type) , m_name(name) , m_size(size) + , m_style(style) , m_antialias(antialias) , m_typeface(typeface) { @@ -36,10 +38,12 @@ FontInfo::FontInfo(Type type, FontInfo::FontInfo(const FontInfo& other, const float size, + const text::FontStyle style, const bool antialias) : m_type(other.type()) , m_name(other.name()) , m_size(size) + , m_style(style) , m_antialias(antialias) , m_typeface(other.typeface()) { @@ -71,8 +75,10 @@ void FontInfo::findTypeface(const text::FontMgrRef& fontMgr) const } const text::FontStyleSetRef set = fontMgr->matchFamily(m_name); - if (set && set->typeface(0)) - m_typeface = set->typeface(0); + if (set) { + if (auto newTypeface = set->matchStyle(m_style)) + m_typeface = newTypeface; + } } } // namespace app @@ -87,6 +93,8 @@ template<> app::FontInfo convert_to(const std::string& from) app::FontInfo::Type type = app::FontInfo::Type::Unknown; std::string name; float size = 0.0f; + bool bold = false; + bool italic = false; bool antialias = false; if (!parts.empty()) { @@ -105,12 +113,22 @@ template<> app::FontInfo convert_to(const std::string& from) for (int i=1; i= text::FontStyle::Weight::SemiBold) + result += ",bold"; + if (from.style().slant() != text::FontStyle::Slant::Upright) + result += ",italic"; if (from.antialias()) result += ",antialias"; } diff --git a/src/app/font_info.h b/src/app/font_info.h index c9abf8d74..90c9fdf4e 100644 --- a/src/app/font_info.h +++ b/src/app/font_info.h @@ -9,6 +9,7 @@ #pragma once #include "base/convert_to.h" +#include "text/font_style.h" #include "text/fwd.h" #include "text/typeface.h" @@ -32,11 +33,13 @@ namespace app { FontInfo(Type type = Type::Unknown, const std::string& name = {}, float size = kDefaultSize, + text::FontStyle style = text::FontStyle(), bool antialias = false, const text::TypefaceRef& typeface = nullptr); FontInfo(const FontInfo& other, float size, + text::FontStyle style, bool antialias); bool isValid() const { return m_type != Type::Unknown; } @@ -54,6 +57,7 @@ namespace app { std::string thumbnailId() const; float size() const { return m_size; } + text::FontStyle style() const { return m_style; } bool antialias() const { return m_antialias; } void findTypeface(const text::FontMgrRef& fontMgr) const; @@ -70,6 +74,7 @@ namespace app { Type m_type = Type::Unknown; std::string m_name; float m_size = kDefaultSize; + text::FontStyle m_style; bool m_antialias = false; mutable text::TypefaceRef m_typeface; }; diff --git a/src/app/ui/button_set.cpp b/src/app/ui/button_set.cpp index 32fc0ca73..76769eb05 100644 --- a/src/app/ui/button_set.cpp +++ b/src/app/ui/button_set.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2023 Igara Studio S.A. +// Copyright (C) 2018-2024 Igara Studio S.A. // Copyright (C) 2001-2017 David Capello // // This program is distributed under the terms of @@ -190,8 +190,9 @@ void ButtonSet::Item::onRightClick() buttonSet()->onRightClick(this); } -ButtonSet::ButtonSet(int columns) - : Grid(columns, false) +ButtonSet::ButtonSet(const int columns, + const bool same_width_columns) + : Grid(columns, same_width_columns) , m_offerCapture(true) , m_triggerOnMouseUp(false) , m_multiMode(MultiMode::One) diff --git a/src/app/ui/button_set.h b/src/app/ui/button_set.h index a8a0ae002..d92dd7053 100644 --- a/src/app/ui/button_set.h +++ b/src/app/ui/button_set.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019 Igara Studio S.A. +// Copyright (C) 2019-2024 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -42,7 +42,7 @@ namespace app { OneOrMore, // One click selects one button, ctrl+click multiple selections }; - ButtonSet(int columns); + ButtonSet(int columns, bool same_width_columns = false); Item* addItem(const std::string& text, ui::Style* style); Item* addItem(const std::string& text, int hspan = 1, int vspan = 1, ui::Style* style = nullptr); diff --git a/src/app/ui/font_entry.cpp b/src/app/ui/font_entry.cpp index 5c58804ff..95c286624 100644 --- a/src/app/ui/font_entry.cpp +++ b/src/app/ui/font_entry.cpp @@ -135,19 +135,30 @@ void FontEntry::FontSize::onEntryChange() Change(); } +FontEntry::FontStyle::FontStyle() + : ButtonSet(2, true) +{ + addItem("B"); + addItem("I"); + setMultiMode(MultiMode::Set); +} + FontEntry::FontEntry() : m_antialias("Antialias") { m_face.setExpansive(true); m_size.setExpansive(false); + m_style.setExpansive(false); m_antialias.setExpansive(false); addChild(&m_face); addChild(&m_size); + addChild(&m_style); addChild(&m_antialias); m_face.FontChange.connect([this](const FontInfo& newTypeName) { setInfo(FontInfo(newTypeName, m_info.size(), + m_info.style(), m_info.antialias()), From::Face); invalidate(); @@ -157,13 +168,45 @@ FontEntry::FontEntry() const float newSize = std::strtof(m_size.getValue().c_str(), nullptr); setInfo(FontInfo(m_info, newSize, + m_info.style(), m_info.antialias()), From::Size); }); + m_style.ItemChange.connect([this](ButtonSet::Item* item){ + text::FontStyle style = m_info.style(); + switch (m_style.getItemIndex(item)) { + // Bold button changed + case 0: { + const bool bold = m_style.getItem(0)->isSelected(); + style = text::FontStyle(bold ? text::FontStyle::Weight::Bold: + text::FontStyle::Weight::Normal, + style.width(), + style.slant()); + break; + } + // Italic button changed + case 1: { + const bool italic = m_style.getItem(1)->isSelected(); + style = text::FontStyle(style.weight(), + style.width(), + italic ? text::FontStyle::Slant::Italic: + text::FontStyle::Slant::Upright); + break; + } + } + + setInfo(FontInfo(m_info, + m_info.size(), + style, + m_info.antialias()), + From::Style); + }); + m_antialias.Click.connect([this](){ setInfo(FontInfo(m_info, m_info.size(), + m_info.style(), m_antialias.isSelected()), From::Antialias); }); @@ -179,6 +222,11 @@ void FontEntry::setInfo(const FontInfo& info, if (fromField != From::Size) m_size.setValue(fmt::format("{}", info.size())); + if (fromField != From::Style) { + m_style.getItem(0)->setSelected(info.style().weight() >= text::FontStyle::Weight::SemiBold); + m_style.getItem(1)->setSelected(info.style().slant() != text::FontStyle::Slant::Upright); + } + if (fromField != From::Antialias) m_antialias.setSelected(info.antialias()); diff --git a/src/app/ui/font_entry.h b/src/app/ui/font_entry.h index bf95e1c98..3dfb8d78c 100644 --- a/src/app/ui/font_entry.h +++ b/src/app/ui/font_entry.h @@ -9,6 +9,7 @@ #pragma once #include "app/font_info.h" +#include "app/ui/button_set.h" #include "app/ui/search_entry.h" #include "ui/box.h" #include "ui/button.h" @@ -25,6 +26,7 @@ namespace app { User, Face, Size, + Style, Antialias, }; @@ -55,9 +57,15 @@ namespace app { void onEntryChange() override; }; + class FontStyle : public ButtonSet { + public: + FontStyle(); + }; + FontInfo m_info; FontFace m_face; FontSize m_size; + FontStyle m_style; ui::CheckBox m_antialias; }; diff --git a/src/app/ui/font_popup.cpp b/src/app/ui/font_popup.cpp index e94404cf0..44acfb47d 100644 --- a/src/app/ui/font_popup.cpp +++ b/src/app/ui/font_popup.cpp @@ -63,22 +63,28 @@ public: FontItem(const std::string& name, ByName) : ListItem(name) , m_fontInfo(FontInfo::Type::Name, name, - FontInfo::kDefaultSize, true) { + FontInfo::kDefaultSize, + text::FontStyle(), true) { getCachedThumbnail(); } FontItem(const std::string& fn) : ListItem(base::get_file_title(fn)) , m_fontInfo(FontInfo::Type::File, fn, - FontInfo::kDefaultSize, true) { + FontInfo::kDefaultSize, + text::FontStyle(), true) { getCachedThumbnail(); } FontItem(const std::string& name, + const text::FontStyle& style, + const text::FontStyleSetRef& set, const text::TypefaceRef& typeface) : ListItem(name) , m_fontInfo(FontInfo::Type::System, name, - FontInfo::kDefaultSize, true, typeface) { + FontInfo::kDefaultSize, + style, true, typeface) + , m_set(set) { getCachedThumbnail(); } @@ -161,6 +167,7 @@ private: private: os::SurfaceRef m_thumbnail; FontInfo m_fontInfo; + text::FontStyleSetRef m_set; }; bool FontPopup::FontListBox::onProcessMessage(ui::Message* msg) @@ -229,31 +236,16 @@ FontPopup::FontPopup(const FontInfo& fontInfo) std::string name = fontMgr->familyName(i); text::FontStyleSetRef set = fontMgr->familyStyleSet(i); if (set && set->count() > 0) { - // Best style for preview purposes, i.e. the most regular - // style, without bold, italic, etc. - int best; - text::FontStyle bestStyle; - - for (int i=0; icount(); ++i) { - text::FontStyle style; - std::string subname; - set->getStyle(i, style, subname); - if ((i == 0) || - ((style.weight() == text::FontStyle::Weight::Normal && - bestStyle.weight() != text::FontStyle::Weight::Normal) || - (style.width() == text::FontStyle::Width::Normal && - bestStyle.width() != text::FontStyle::Width::Normal) || - (style.slant() == text::FontStyle::Slant::Upright && - bestStyle.slant() != text::FontStyle::Slant::Upright))) { - best = i; - bestStyle = style; - } + // Match the typeface with the default FontStyle (Normal + // weight, Upright slant, etc.) + auto typeface = set->matchStyle(text::FontStyle()); + if (typeface) { + auto* item = new FontItem(name, typeface->fontStyle(), + set, typeface); + item->ThumbnailGenerated.connect([this]{ onThumbnailGenerated(); }); + m_listBox.addChild(item); + empty = false; } - - auto* item = new FontItem(name, set->typeface(best)); - item->ThumbnailGenerated.connect([this]{ onThumbnailGenerated(); }); - m_listBox.addChild(item); - empty = false; } } }