Add possibility to customize theme fonts (#712, #4307)

From Edit > Preferences > Themes we now can customize the theme Font
and Mini Font.
This commit is contained in:
David Capello 2025-02-12 17:31:27 -03:00
parent bc3433fcf2
commit d4406629e6
7 changed files with 147 additions and 18 deletions

View File

@ -1513,6 +1513,12 @@ alpha_range = Alpha Range:
opacity_range = Opacity Range:
8bit_value = 0-255
percentage = 0%-100%
customize_theme = Customize Theme
font = Font:
mini_font = Mini Font:
preview = Preview:
font_preview = Font Preview
mini_font_preview = Mini Font Preview
available_themes = Available Themes
extension_themes = Extension Themes
select_theme = &Select

View File

@ -1,5 +1,5 @@
<!-- Aseprite -->
<!-- Copyright (C) 2018-2024 Igara Studio S.A. -->
<!-- Copyright (C) 2018-2025 Igara Studio S.A. -->
<!-- Copyright (C) 2001-2018 David Capello -->
<gui>
<window id="options" text="@.title" help="preferences">
@ -537,6 +537,20 @@
<!-- Theme -->
<vbox id="section_theme">
<separator text="@.customize_theme" horizontal="true" />
<grid columns="2">
<label text="@.preview" />
<vbox cell_align="horizontal" >
<label id="font_preview" text="@.font_preview" />
<label id="mini_font_preview" text="@.mini_font_preview" />
</vbox>
<check id="custom_theme_font" text="@.font" />
<font id="theme_font" cell_align="horizontal" />
<check id="custom_mini_font" text="@.mini_font" />
<font id="theme_mini_font" cell_align="horizontal" />
</grid>
<separator text="@.available_themes" horizontal="true" />
<view expansive="true" maxsize="true">
<listbox id="theme_list" />

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2018-2024 Igara Studio S.A.
// Copyright (C) 2018-2025 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -35,6 +35,7 @@
#include "app/ui/sampling_selector.h"
#include "app/ui/separator_in_view.h"
#include "app/ui/skin/skin_theme.h"
#include "app/util/render_text.h"
#include "base/convert_to.h"
#include "base/fs.h"
#include "base/string.h"
@ -267,8 +268,10 @@ public:
{
sectionListbox()->Change.connect([this] { onChangeSection(); });
// Theme variants
// Theme variants/fonts.
fillThemeVariants();
fillThemeFonts();
updateFontPreviews();
// Recent files
clearRecentFiles()->Click.connect([this] { onClearRecentFiles(); });
@ -440,6 +443,22 @@ public:
// Undo preferences
limitUndo()->Click.connect([this] { onLimitUndoCheck(); });
// Theme Custom Font
customThemeFont()->Click.connect([this] {
const bool state = customThemeFont()->isSelected();
themeFont()->setEnabled(state);
if (!state)
themeFont()->setInfo(FontInfo(), FontEntry::From::Init);
});
customMiniFont()->Click.connect([this] {
const bool state = customMiniFont()->isSelected();
themeMiniFont()->setEnabled(state);
if (!state)
themeMiniFont()->setInfo(FontInfo(), FontEntry::From::Init);
});
themeFont()->FontChange.connect([this] { updateFontPreviews(); });
themeMiniFont()->FontChange.connect([this] { updateFontPreviews(); });
// Theme buttons
themeList()->Change.connect([this] { onThemeChange(); });
themeList()->DoubleClickItem.connect([this] { onSelectTheme(); });
@ -893,6 +912,23 @@ public:
ui::set_use_native_cursors(m_pref.cursor.useNativeCursor());
ui::set_mouse_cursor_scale(m_pref.cursor.cursorScale());
// Change theme font
bool reset_theme = false;
{
const FontInfo fontInfo = themeFont()->info();
const FontInfo miniFontInfo = themeMiniFont()->info();
auto fontStr = base::convert_to<std::string>(fontInfo);
auto miniFontStr = base::convert_to<std::string>(miniFontInfo);
if (m_pref.theme.font() != fontStr || m_pref.theme.miniFont() != miniFontStr) {
m_pref.theme.font(fontStr);
m_pref.theme.miniFont(miniFontStr);
reset_theme = true;
}
}
bool reset_screen = false;
const int newScreenScale = base::convert_to<int>(screenScale()->getValue());
if (newScreenScale != m_pref.general.screenScale()) {
@ -903,10 +939,13 @@ public:
const int newUIScale = base::convert_to<int>(uiScale()->getValue());
if (newUIScale != m_pref.general.uiScale()) {
m_pref.general.uiScale(newUIScale);
ui::set_theme(ui::get_theme(), newUIScale);
reset_theme = true;
reset_screen = true;
}
if (reset_theme)
ui::set_theme(ui::get_theme(), newUIScale);
#ifdef ENABLE_DEVMODE
const bool newGpuAccel = gpuAcceleration()->isSelected();
if (newGpuAccel != m_pref.general.gpuAcceleration()) {
@ -989,6 +1028,14 @@ public:
}
private:
void onInitTheme(InitThemeEvent& ev) override
{
app::gen::Options::onInitTheme(ev);
fontPreview()->setFont(m_font);
miniFontPreview()->setFont(m_miniFont);
}
void fillThemeVariants()
{
ButtonSet* list = nullptr;
@ -1027,6 +1074,34 @@ private:
themeVariants()->initTheme();
}
void fillThemeFonts()
{
auto& pref = Preferences::instance();
const FontInfo fontInfo = base::convert_to<FontInfo>(pref.theme.font());
const FontInfo miniInfo = base::convert_to<FontInfo>(pref.theme.miniFont());
customThemeFont()->setSelected(fontInfo.isValid());
customMiniFont()->setSelected(miniInfo.isValid());
themeFont()->setEnabled(fontInfo.isValid());
themeMiniFont()->setEnabled(miniInfo.isValid());
themeFont()->setInfo(fontInfo, FontEntry::From::Init);
themeMiniFont()->setInfo(miniInfo, FontEntry::From::Init);
}
void updateFontPreviews()
{
m_font = get_font_from_info(themeFont()->info());
m_miniFont = get_font_from_info(themeMiniFont()->info());
if (!m_miniFont)
m_miniFont = skin::SkinTheme::get(this)->getMiniFont();
fontPreview()->setFont(m_font);
miniFontPreview()->setFont(m_miniFont);
layout();
}
void fillExtensionsCombobox(ui::ComboBox* combobox, const std::string& defExt)
{
base::paths exts = get_writable_extensions();
@ -2034,6 +2109,8 @@ private:
BestFitCriteriaSelector m_bestFitCriteriaSelector;
ButtonSet* m_themeVars = nullptr;
SamplingSelector* m_samplingSelector = nullptr;
text::FontRef m_font;
text::FontRef m_miniFont;
};
class OptionsCommand : public Command {

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (c) 2024 Igara Studio S.A.
// Copyright (c) 2024-2025 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -159,7 +159,7 @@ app::FontInfo convert_to(const std::string& from)
type = app::FontInfo::Type::System;
name = parts[0].substr(7);
}
else {
else if (!parts[0].empty()) {
type = app::FontInfo::Type::Name;
name = parts[0];
}

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2024 Igara Studio S.A.
// Copyright (C) 2019-2025 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -14,6 +14,7 @@
#include "app/app.h"
#include "app/console.h"
#include "app/extensions.h"
#include "app/font_info.h"
#include "app/font_path.h"
#include "app/modules/gui.h"
#include "app/pref/preferences.h"
@ -23,6 +24,7 @@
#include "app/ui/skin/font_data.h"
#include "app/ui/skin/skin_property.h"
#include "app/ui/skin/skin_slider_property.h"
#include "app/util/render_text.h"
#include "app/xml_document.h"
#include "app/xml_exception.h"
#include "base/fs.h"
@ -482,6 +484,19 @@ void SkinTheme::loadXml(BackwardCompatibility* backward)
if (!m_miniFont)
m_miniFont = m_defaultFont;
// Overwrite theme fonts by user defined fonts.
Preferences& pref = Preferences::instance();
if (!pref.theme.font().empty()) {
auto fi = base::convert_to<FontInfo>(pref.theme.font());
if (auto f = get_font_from_info(fi, this))
m_defaultFont = f;
}
if (!pref.theme.miniFont().empty()) {
auto fi = base::convert_to<FontInfo>(pref.theme.miniFont());
if (auto f = get_font_from_info(fi, this))
m_miniFont = f;
}
// Load dimension
{
XMLElement* xmlDim = handle.FirstChildElement("theme")
@ -781,10 +796,22 @@ void SkinTheme::loadXml(BackwardCompatibility* backward)
{
const char* fontId = xmlStyle->Attribute("font");
if (fontId) {
// Use m_defaultFont/m_miniFont just in case the user
// customized these fonts.
if (std::strcmp(fontId, "default") == 0) {
style->setFont(m_defaultFont);
style->setMnemonics(true);
}
else if (std::strcmp(fontId, "mini") == 0) {
style->setFont(m_miniFont);
style->setMnemonics(false);
}
else {
auto themeFont = m_themeFonts[fontId];
style->setFont(themeFont.font());
style->setMnemonics(themeFont.mnemonics());
}
}
// Override mnemonics value if it is defined for this style.
const char* mnemonicsStr = xmlStyle->Attribute("mnemonics");

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2022-2024 Igara Studio S.A.
// Copyright (C) 2022-2025 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -63,12 +63,14 @@ private:
} // anonymous namespace
text::FontRef get_font_from_info(const FontInfo& fontInfo)
text::FontRef get_font_from_info(const FontInfo& fontInfo, skin::SkinTheme* theme)
{
auto* theme = skin::SkinTheme::instance();
if (!theme) {
theme = skin::SkinTheme::instance();
ASSERT(theme);
if (!theme)
return nullptr;
}
const text::FontMgrRef fontMgr = theme->fontMgr();
if (!fontMgr)

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2024 Igara Studio S.A.
// Copyright (C) 2024-2025 Igara Studio S.A.
// Copyright (C) 2001-2015 David Capello
//
// This program is distributed under the terms of
@ -20,8 +20,11 @@ namespace app {
class Color;
class FontInfo;
namespace skin {
class SkinTheme;
}
text::FontRef get_font_from_info(const FontInfo& fontInfo);
text::FontRef get_font_from_info(const FontInfo& fontInfo, skin::SkinTheme* theme = nullptr);
text::TextBlobRef create_text_blob(const FontInfo& fontInfo, const std::string& text);