mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-30 15:32:38 +00:00
Add ligatures button to Text tool (#4679)
Doesn't fully fix the issue as we cannot move the cursor between the ligature clusters, but at least we can disable the ligatures now.
This commit is contained in:
parent
e700cce987
commit
5c7a3a41f6
2
laf
2
laf
@ -1 +1 @@
|
||||
Subproject commit 851bdbc2454aa381131cd0972781aa86e149504a
|
||||
Subproject commit 61aba133e6de5197cdf490696ae7aba5f56273fd
|
@ -26,24 +26,24 @@ FontInfo::FontInfo(Type type,
|
||||
const std::string& name,
|
||||
const float size,
|
||||
const text::FontStyle style,
|
||||
const bool antialias)
|
||||
const Flags flags)
|
||||
: m_type(type)
|
||||
, m_name(name)
|
||||
, m_size(size)
|
||||
, m_style(style)
|
||||
, m_antialias(antialias)
|
||||
, m_flags(flags)
|
||||
{
|
||||
}
|
||||
|
||||
FontInfo::FontInfo(const FontInfo& other,
|
||||
const float size,
|
||||
const text::FontStyle style,
|
||||
const bool antialias)
|
||||
const Flags flags)
|
||||
: m_type(other.type())
|
||||
, m_name(other.name())
|
||||
, m_size(size)
|
||||
, m_style(style)
|
||||
, m_antialias(antialias)
|
||||
, m_flags(flags)
|
||||
{
|
||||
}
|
||||
|
||||
@ -89,7 +89,8 @@ FontInfo FontInfo::getFromPreferences()
|
||||
pref.textTool.fontFace(),
|
||||
pref.textTool.fontSize(),
|
||||
text::FontStyle(),
|
||||
pref.textTool.antialias());
|
||||
pref.textTool.antialias() ? FontInfo::Flags::Antialias :
|
||||
FontInfo::Flags::None);
|
||||
}
|
||||
// New configuration
|
||||
if (!pref.textTool.fontInfo().empty()) {
|
||||
@ -124,7 +125,7 @@ template<> app::FontInfo convert_to(const std::string& from)
|
||||
float size = 0.0f;
|
||||
bool bold = false;
|
||||
bool italic = false;
|
||||
bool antialias = false;
|
||||
app::FontInfo::Flags flags = app::FontInfo::Flags::None;
|
||||
|
||||
if (!parts.empty()) {
|
||||
if (parts[0].compare(0, 5, "file=") == 0) {
|
||||
@ -141,7 +142,9 @@ template<> app::FontInfo convert_to(const std::string& from)
|
||||
}
|
||||
for (int i=1; i<parts.size(); ++i) {
|
||||
if (parts[i] == "antialias")
|
||||
antialias = true;
|
||||
flags |= app::FontInfo::Flags::Antialias;
|
||||
else if (parts[i] == "ligatures")
|
||||
flags |= app::FontInfo::Flags::Ligatures;
|
||||
else if (parts[i] == "bold")
|
||||
bold = true;
|
||||
else if (parts[i] == "italic")
|
||||
@ -157,7 +160,7 @@ template<> app::FontInfo convert_to(const std::string& from)
|
||||
else if (bold) style = text::FontStyle::Bold();
|
||||
else if (italic) style = text::FontStyle::Italic();
|
||||
|
||||
return app::FontInfo(type, name, size, style, antialias);
|
||||
return app::FontInfo(type, name, size, style, flags);
|
||||
}
|
||||
|
||||
template<> std::string convert_to(const app::FontInfo& from)
|
||||
@ -186,6 +189,8 @@ template<> std::string convert_to(const app::FontInfo& from)
|
||||
result += ",italic";
|
||||
if (from.antialias())
|
||||
result += ",antialias";
|
||||
if (from.ligatures())
|
||||
result += ",ligatures";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "base/convert_to.h"
|
||||
#include "base/enum_flags.h"
|
||||
#include "text/font_style.h"
|
||||
#include "text/fwd.h"
|
||||
#include "text/typeface.h"
|
||||
@ -28,18 +29,24 @@ namespace app {
|
||||
System,
|
||||
};
|
||||
|
||||
enum class Flags {
|
||||
None = 0,
|
||||
Antialias = 1,
|
||||
Ligatures = 2,
|
||||
};
|
||||
|
||||
static constexpr const float kDefaultSize = 0.0f;
|
||||
|
||||
FontInfo(Type type = Type::Unknown,
|
||||
const std::string& name = {},
|
||||
float size = kDefaultSize,
|
||||
text::FontStyle style = text::FontStyle(),
|
||||
bool antialias = false);
|
||||
Flags flags = Flags::None);
|
||||
|
||||
FontInfo(const FontInfo& other,
|
||||
float size,
|
||||
text::FontStyle style,
|
||||
bool antialias);
|
||||
Flags flags);
|
||||
|
||||
bool isValid() const { return m_type != Type::Unknown; }
|
||||
bool useDefaultSize() const { return m_size == kDefaultSize; }
|
||||
@ -57,7 +64,9 @@ namespace app {
|
||||
|
||||
float size() const { return m_size; }
|
||||
text::FontStyle style() const { return m_style; }
|
||||
bool antialias() const { return m_antialias; }
|
||||
Flags flags() const { return m_flags; }
|
||||
bool antialias() const;
|
||||
bool ligatures() const;
|
||||
|
||||
text::TypefaceRef findTypeface(const text::FontMgrRef& fontMgr) const;
|
||||
|
||||
@ -68,7 +77,7 @@ namespace app {
|
||||
return (m_type == other.m_type &&
|
||||
m_name == other.m_name &&
|
||||
std::fabs(m_size-other.m_size) < 0.001f &&
|
||||
m_antialias == other.m_antialias);
|
||||
m_flags == other.m_flags);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -76,9 +85,19 @@ namespace app {
|
||||
std::string m_name;
|
||||
float m_size = kDefaultSize;
|
||||
text::FontStyle m_style;
|
||||
bool m_antialias = false;
|
||||
Flags m_flags = Flags::None;
|
||||
};
|
||||
|
||||
LAF_ENUM_FLAGS(FontInfo::Flags);
|
||||
|
||||
inline bool FontInfo::antialias() const {
|
||||
return (m_flags & Flags::Antialias) == Flags::Antialias;
|
||||
}
|
||||
|
||||
inline bool FontInfo::ligatures() const {
|
||||
return (m_flags & Flags::Ligatures) == Flags::Ligatures;
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
namespace base {
|
||||
|
@ -47,9 +47,10 @@ TEST(FontInfo, ByFile)
|
||||
TEST(FontInfo, BySystem)
|
||||
{
|
||||
FontInfo a(FontInfo::Type::System, "FreeMono");
|
||||
FontInfo b(FontInfo::Type::System, "DejaVu Serif", 12, text::FontStyle(), true);
|
||||
FontInfo c(FontInfo::Type::System, "Arial", 14, text::FontStyle::Bold(), false);
|
||||
FontInfo d(FontInfo::Type::System, "Arial", 16, text::FontStyle::BoldItalic(), false);
|
||||
FontInfo b(FontInfo::Type::System, "DejaVu Serif", 12, text::FontStyle(),
|
||||
FontInfo::Flags::Antialias);
|
||||
FontInfo c(FontInfo::Type::System, "Arial", 14, text::FontStyle::Bold());
|
||||
FontInfo d(FontInfo::Type::System, "Arial", 16, text::FontStyle::BoldItalic());
|
||||
EXPECT_EQ("system=FreeMono", base::convert_to<std::string>(a));
|
||||
EXPECT_EQ("system=DejaVu Serif,size=12,antialias", base::convert_to<std::string>(b));
|
||||
EXPECT_EQ("system=Arial,size=14,bold", base::convert_to<std::string>(c));
|
||||
|
@ -148,6 +148,13 @@ private:
|
||||
onNewTextBlob();
|
||||
}
|
||||
|
||||
text::ShaperFeatures onGetTextShaperFeatures() const override {
|
||||
const FontInfo fontInfo = App::instance()->contextBar()->fontInfo();
|
||||
text::ShaperFeatures features;
|
||||
features.ligatures = fontInfo.ligatures();
|
||||
return features;
|
||||
}
|
||||
|
||||
void onNewTextBlob() {
|
||||
text::TextBlobRef blob = textBlob();
|
||||
if (!blob)
|
||||
|
@ -144,16 +144,25 @@ FontEntry::FontStyle::FontStyle()
|
||||
setMultiMode(MultiMode::Set);
|
||||
}
|
||||
|
||||
FontEntry::FontLigatures::FontLigatures()
|
||||
: ButtonSet(1, true)
|
||||
{
|
||||
addItem("fi");
|
||||
setMultiMode(MultiMode::Set);
|
||||
}
|
||||
|
||||
FontEntry::FontEntry()
|
||||
: m_antialias("Antialias")
|
||||
{
|
||||
m_face.setExpansive(true);
|
||||
m_size.setExpansive(false);
|
||||
m_style.setExpansive(false);
|
||||
m_ligatures.setExpansive(false);
|
||||
m_antialias.setExpansive(false);
|
||||
addChild(&m_face);
|
||||
addChild(&m_size);
|
||||
addChild(&m_style);
|
||||
addChild(&m_ligatures);
|
||||
addChild(&m_antialias);
|
||||
|
||||
m_face.setMinSize(gfx::Size(128*guiscale(), 0));
|
||||
@ -162,7 +171,7 @@ FontEntry::FontEntry()
|
||||
setInfo(FontInfo(newTypeName,
|
||||
m_info.size(),
|
||||
m_info.style(),
|
||||
m_info.antialias()),
|
||||
m_info.flags()),
|
||||
From::Face);
|
||||
invalidate();
|
||||
});
|
||||
@ -172,7 +181,7 @@ FontEntry::FontEntry()
|
||||
setInfo(FontInfo(m_info,
|
||||
newSize,
|
||||
m_info.style(),
|
||||
m_info.antialias()),
|
||||
m_info.flags()),
|
||||
From::Size);
|
||||
});
|
||||
|
||||
@ -202,17 +211,21 @@ FontEntry::FontEntry()
|
||||
setInfo(FontInfo(m_info,
|
||||
m_info.size(),
|
||||
style,
|
||||
m_info.antialias()),
|
||||
m_info.flags()),
|
||||
From::Style);
|
||||
});
|
||||
|
||||
m_antialias.Click.connect([this](){
|
||||
setInfo(FontInfo(m_info,
|
||||
m_info.size(),
|
||||
m_info.style(),
|
||||
m_antialias.isSelected()),
|
||||
From::Antialias);
|
||||
});
|
||||
auto flagsChange = [this]() {
|
||||
FontInfo::Flags flags = FontInfo::Flags::None;
|
||||
if (m_antialias.isSelected())
|
||||
flags |= FontInfo::Flags::Antialias;
|
||||
if (m_ligatures.getItem(0)->isSelected())
|
||||
flags |= FontInfo::Flags::Ligatures;
|
||||
setInfo(FontInfo(m_info, m_info.size(), m_info.style(), flags),
|
||||
From::Flags);
|
||||
};
|
||||
m_ligatures.ItemChange.connect(flagsChange);
|
||||
m_antialias.Click.connect(flagsChange);
|
||||
}
|
||||
|
||||
// Defined here as FontPopup type is not fully defined in the header
|
||||
@ -236,8 +249,10 @@ void FontEntry::setInfo(const FontInfo& info,
|
||||
m_style.getItem(1)->setSelected(info.style().slant() != text::FontStyle::Slant::Upright);
|
||||
}
|
||||
|
||||
if (fromField != From::Antialias)
|
||||
if (fromField != From::Flags) {
|
||||
m_ligatures.getItem(0)->setSelected(info.ligatures());
|
||||
m_antialias.setSelected(info.antialias());
|
||||
}
|
||||
|
||||
FontChange(m_info);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace app {
|
||||
Face,
|
||||
Size,
|
||||
Style,
|
||||
Antialias,
|
||||
Flags,
|
||||
};
|
||||
|
||||
FontEntry();
|
||||
@ -63,10 +63,16 @@ namespace app {
|
||||
FontStyle();
|
||||
};
|
||||
|
||||
class FontLigatures : public ButtonSet {
|
||||
public:
|
||||
FontLigatures();
|
||||
};
|
||||
|
||||
FontInfo m_info;
|
||||
FontFace m_face;
|
||||
FontSize m_size;
|
||||
FontStyle m_style;
|
||||
FontLigatures m_ligatures;
|
||||
ui::CheckBox m_antialias;
|
||||
};
|
||||
|
||||
|
@ -64,7 +64,8 @@ public:
|
||||
: ListItem(name)
|
||||
, m_fontInfo(FontInfo::Type::Name, name,
|
||||
FontInfo::kDefaultSize,
|
||||
text::FontStyle(), true) {
|
||||
text::FontStyle(),
|
||||
FontInfo::Flags::Antialias) {
|
||||
getCachedThumbnail();
|
||||
}
|
||||
|
||||
@ -72,7 +73,8 @@ public:
|
||||
: ListItem(base::get_file_title(fn))
|
||||
, m_fontInfo(FontInfo::Type::File, fn,
|
||||
FontInfo::kDefaultSize,
|
||||
text::FontStyle(), true) {
|
||||
text::FontStyle(),
|
||||
FontInfo::Flags::Antialias) {
|
||||
getCachedThumbnail();
|
||||
}
|
||||
|
||||
@ -81,7 +83,8 @@ public:
|
||||
const text::FontStyleSetRef& set)
|
||||
: ListItem(name)
|
||||
, m_fontInfo(FontInfo::Type::System, name,
|
||||
FontInfo::kDefaultSize, style, true)
|
||||
FontInfo::kDefaultSize, style,
|
||||
FontInfo::Flags::Antialias)
|
||||
, m_set(set) {
|
||||
getCachedThumbnail();
|
||||
}
|
||||
|
@ -180,8 +180,10 @@ doc::ImageRef render_text(
|
||||
// fonts (e.g. if the given font is not enough to shape other code
|
||||
// points/languages).
|
||||
MeasureHandler handler;
|
||||
text::ShaperFeatures features;
|
||||
features.ligatures = fontInfo.ligatures();
|
||||
text::TextBlobRef blob =
|
||||
text::TextBlob::MakeWithShaper(fontMgr, font, text, &handler);
|
||||
text::TextBlob::MakeWithShaper(fontMgr, font, text, &handler, features);
|
||||
if (!blob)
|
||||
return nullptr;
|
||||
|
||||
|
@ -958,7 +958,9 @@ void Entry::recalcCharBoxes(const std::string& text)
|
||||
text::draw_text(nullptr,
|
||||
theme()->fontMgr(),
|
||||
base::AddRef(font()), text,
|
||||
gfx::ColorNone, gfx::ColorNone, 0, 0, &delegate).w;
|
||||
gfx::ColorNone, gfx::ColorNone, 0, 0,
|
||||
&delegate,
|
||||
onGetTextShaperFeatures()).w;
|
||||
m_boxes = delegate.boxes();
|
||||
|
||||
if (!m_boxes.empty()) {
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "text/draw_text.h"
|
||||
#include "text/font.h"
|
||||
#include "text/font_metrics.h"
|
||||
#include "text/shaper_features.h"
|
||||
#include "ui/display.h"
|
||||
#include "ui/scale.h"
|
||||
#include "ui/theme.h"
|
||||
@ -338,7 +339,8 @@ void Graphics::setFont(const text::FontRef& font)
|
||||
void Graphics::drawText(const std::string& str,
|
||||
gfx::Color fg, gfx::Color bg,
|
||||
const gfx::Point& origPt,
|
||||
text::DrawTextDelegate* delegate)
|
||||
text::DrawTextDelegate* delegate,
|
||||
text::ShaperFeatures features)
|
||||
{
|
||||
if (str.empty())
|
||||
return;
|
||||
@ -348,7 +350,7 @@ void Graphics::drawText(const std::string& str,
|
||||
os::SurfaceLock lock(m_surface.get());
|
||||
gfx::Rect textBounds =
|
||||
text::draw_text(m_surface.get(), get_theme()->fontMgr(),
|
||||
m_font, str, fg, bg, pt.x, pt.y, delegate);
|
||||
m_font, str, fg, bg, pt.x, pt.y, delegate, features);
|
||||
|
||||
dirty(gfx::Rect(pt.x, pt.y, textBounds.w, textBounds.h));
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "gfx/size.h"
|
||||
#include "os/surface.h"
|
||||
#include "text/font.h"
|
||||
#include "text/fwd.h"
|
||||
#include "text/shaper_features.h"
|
||||
#include "ui/paint.h"
|
||||
|
||||
#include <memory>
|
||||
@ -32,10 +34,6 @@ namespace os {
|
||||
struct Sampling;
|
||||
}
|
||||
|
||||
namespace text {
|
||||
class DrawTextDelegate;
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
class Display;
|
||||
|
||||
@ -110,7 +108,8 @@ namespace ui {
|
||||
void drawText(const std::string& str,
|
||||
gfx::Color fg, gfx::Color bg,
|
||||
const gfx::Point& pt,
|
||||
text::DrawTextDelegate* delegate = nullptr);
|
||||
text::DrawTextDelegate* delegate = nullptr,
|
||||
text::ShaperFeatures features = {});
|
||||
|
||||
void drawUIText(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Point& pt, const int mnemonic);
|
||||
void drawAlignedUIText(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Rect& rc, const int align);
|
||||
|
@ -929,12 +929,8 @@ void Widget::getDrawableRegion(gfx::Region& region, DrawableRegionFlags flags)
|
||||
|
||||
text::TextBlobRef Widget::textBlob() const
|
||||
{
|
||||
if (!m_blob && !m_text.empty()) {
|
||||
m_blob = text::TextBlob::MakeWithShaper(
|
||||
theme()->fontMgr(),
|
||||
AddRef(font()),
|
||||
m_text);
|
||||
}
|
||||
if (!m_blob && !m_text.empty())
|
||||
m_blob = onMakeTextBlob();
|
||||
return m_blob;
|
||||
}
|
||||
|
||||
@ -1789,6 +1785,21 @@ double Widget::onGetTextDouble() const
|
||||
return std::strtod(m_text.c_str(), nullptr);
|
||||
}
|
||||
|
||||
text::TextBlobRef Widget::onMakeTextBlob() const
|
||||
{
|
||||
return text::TextBlob::MakeWithShaper(
|
||||
theme()->fontMgr(),
|
||||
AddRef(font()),
|
||||
text(),
|
||||
nullptr,
|
||||
onGetTextShaperFeatures());
|
||||
}
|
||||
|
||||
text::ShaperFeatures Widget::onGetTextShaperFeatures() const
|
||||
{
|
||||
return text::ShaperFeatures();
|
||||
}
|
||||
|
||||
void Widget::offsetWidgets(int dx, int dy)
|
||||
{
|
||||
if (dx == 0 && dy == 0)
|
||||
|
@ -442,6 +442,8 @@ namespace ui {
|
||||
virtual void onSetBgColor();
|
||||
virtual int onGetTextInt() const;
|
||||
virtual double onGetTextDouble() const;
|
||||
virtual text::TextBlobRef onMakeTextBlob() const;
|
||||
virtual text::ShaperFeatures onGetTextShaperFeatures() const;
|
||||
|
||||
private:
|
||||
void removeChild(const WidgetsList::iterator& it);
|
||||
|
Loading…
x
Reference in New Issue
Block a user