Skip to content

Commit

Permalink
glyph margins support
Browse files Browse the repository at this point in the history
  • Loading branch information
Kolcha committed Sep 21, 2024
1 parent ed12d5a commit 4f64acd
Show file tree
Hide file tree
Showing 12 changed files with 141 additions and 17 deletions.
5 changes: 4 additions & 1 deletion app/skin/legacy_skin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "skin/skin.hpp"

// TODO: convert it to "pure factory"
class LegacySkin : public Skin {
public:
bool hasAlternateSeparator() const override
Expand All @@ -17,11 +18,13 @@ class LegacySkin : public Skin {

bool supportsCustomSeparator() const override { return false; }

std::shared_ptr<Glyph> glyph(char32_t c) const override
protected:
std::shared_ptr<Glyph> create(char32_t c) const override
{
return _glyphs.value(c, nullptr);
}

public:
void addGlyph(char32_t c, std::shared_ptr<Glyph> g)
{
_glyphs[c] = std::move(g);
Expand Down
1 change: 1 addition & 0 deletions skin_engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ qt_add_library(${PROJECT_NAME} SHARED
skin/image_glyph.cpp
skin/image_glyph.hpp
skin/observable.hpp
skin/skin.cpp
skin/skin.hpp
skin_engine_global.hpp
)
Expand Down
15 changes: 14 additions & 1 deletion skin_engine/skin/container.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class SKIN_ENGINE_EXPORT ContainerImplBase : public Skin::Glyph {
public:
explicit ContainerImplBase(std::shared_ptr<Algorithm> algo);

QRectF rect() const override { return _rect; }
QRectF rect() const override { return _rect.marginsAdded(_mgs); }
QPointF advance() const override { return _adv; }

void draw(QPainter* p) const override;
Expand All @@ -38,6 +38,10 @@ class SKIN_ENGINE_EXPORT ContainerImplBase : public Skin::Glyph {

auto algorithm() const { return _algo; }

QMarginsF margins() const { return _mgs; }
// no geometry update propagation!
void setMargins(QMarginsF mgs) { _mgs = std::move(mgs); }

void updateGeometry();

private:
Expand All @@ -46,6 +50,7 @@ class SKIN_ENGINE_EXPORT ContainerImplBase : public Skin::Glyph {
// cache geometry data
QRectF _rect;
QPointF _adv;
QMarginsF _mgs;
};


Expand Down Expand Up @@ -140,6 +145,14 @@ class SKIN_ENGINE_EXPORT ContainerGlyph : public Glyph {
return std::static_pointer_cast<AlgorithmType>(_impl->algorithm());
}

QMarginsF margins() const { return _impl->margins(); }

void setMargins(QMarginsF mgs)
{
_impl->setMargins(std::move(mgs));
Glyph::updateGeometry();
}

// no implicit geometry updates propagation
// to allow multiple glyphs to be updated at once
// without unnecessary intermediate updates for each of them
Expand Down
2 changes: 1 addition & 1 deletion skin_engine/skin/font_skin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#include <QFont>

class SKIN_ENGINE_EXPORT FontSkin : public SkinBase {
class SKIN_ENGINE_EXPORT FontSkin : public Skin {
public:
explicit FontSkin(QFont font);

Expand Down
10 changes: 10 additions & 0 deletions skin_engine/skin/glyph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Glyph::Glyph(std::shared_ptr<Skin::Glyph> g)
, _t(std::make_shared<Transform>())
, _a(std::make_shared<Appearance>())
{
_g->subscribe(this);
_t->subscribe(this);
_a->subscribe(this);
updateGeometry();
Expand All @@ -62,12 +63,15 @@ Glyph::~Glyph()
{
_a->unsubscribe(this);
_t->unsubscribe(this);
_g->unsubscribe(this);
}

void Glyph::setGlyph(std::shared_ptr<Skin::Glyph> g)
{
if (_g == g) return;
if (_g) _g->unsubscribe(this);
_g = std::move(g);
if (_g) _g->subscribe(this);
updateGeometry();
dropCachedData();
}
Expand Down Expand Up @@ -185,6 +189,12 @@ void Glyph::onAppearanceChanged()
dropCachedData();
}

void Glyph::onGeometryChanged()
{
updateGeometry();
dropCachedData();
}

void Glyph::updateGeometry()
{
if (!_g) return;
Expand Down
6 changes: 4 additions & 2 deletions skin_engine/skin/glyph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ class SKIN_ENGINE_EXPORT Transform : public Observable<AppearanceChangeListener>


// non-shareable, as has unique data such as position
class SKIN_ENGINE_EXPORT Glyph : public AppearanceChangeListener {
class SKIN_ENGINE_EXPORT Glyph : public AppearanceChangeListener,
public GeometryChangeListener {
public:
Glyph() = default;
explicit Glyph(std::shared_ptr<Skin::Glyph> g);
Expand Down Expand Up @@ -124,7 +125,8 @@ class SKIN_ENGINE_EXPORT Glyph : public AppearanceChangeListener {
void draw(QPainter* p) const;

// listeners
void onAppearanceChanged();
void onAppearanceChanged() override;
void onGeometryChanged() override;

protected:
void updateGeometry();
Expand Down
5 changes: 5 additions & 0 deletions skin_engine/skin/graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ void GraphicsBase::setLineSpacing(qreal spacing)
_tg.updateGeometry();
}

void GraphicsBase::setMargins(QMarginsF margins)
{
_tg.setMargins(std::move(margins));
}

void GraphicsBase::setAlignment(Qt::Alignment a)
{
_tg.algorithm()->setAlignment(a);
Expand Down
4 changes: 4 additions & 0 deletions skin_engine/skin/graphics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class SKIN_ENGINE_EXPORT GraphicsBase {
qreal charSpacing() const { return _char_spacing; }
qreal lineSpacing() const { return _line_spacing; }

QMarginsF margins() const { return _tg.margins(); }

Qt::Alignment alignment() const { return _tg.algorithm()->alignment(); }
Qt::Alignment alignment(size_t i) const
{ return _tg.algorithm()->alignment(i); }
Expand Down Expand Up @@ -50,6 +52,8 @@ class SKIN_ENGINE_EXPORT GraphicsBase {
void setCharSpacing(qreal spacing);
void setLineSpacing(qreal spacing);

void setMargins(QMarginsF margins);

void setAlignment(Qt::Alignment a);
void setAlignment(size_t i, Qt::Alignment a);

Expand Down
7 changes: 7 additions & 0 deletions skin_engine/skin/graphics_widgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ void GraphicsWidgetBase::setLineSpacing(qreal spacing)
update();
}

void GraphicsWidgetBase::setMargins(QMarginsF margins)
{
_gt->setMargins(std::move(margins));
updateGeometry();
update();
}

void GraphicsWidgetBase::setScaling(qreal sx, qreal sy)
{
_sx = sx;
Expand Down
4 changes: 4 additions & 0 deletions skin_engine/skin/graphics_widgets.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class SKIN_ENGINE_EXPORT GraphicsWidgetBase : public QWidget
qreal charSpacing() const { return _gt->charSpacing(); }
qreal lineSpacing() const { return _gt->lineSpacing(); }

QMarginsF margins() const { return _gt->margins(); }

qreal scalingX() const { return _sx; }
qreal scalingY() const { return _sy; }

Expand Down Expand Up @@ -75,6 +77,8 @@ public slots:
void setCharSpacing(qreal spacing);
void setLineSpacing(qreal spacing);

void setMargins(QMarginsF margins);

void setScalingX(qreal sx) { setScaling(sx, scalingY()); }
void setScalingY(qreal sy) { setScaling(scalingX(), sy); }
void setScaling(qreal sx, qreal sy);
Expand Down
70 changes: 70 additions & 0 deletions skin_engine/skin/skin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* SPDX-FileCopyrightText: 2024 Nick Korotysh <[email protected]>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/

#include "skin.hpp"

namespace {

class GlyphDecoratorBase : public Skin::Glyph {
public:
explicit GlyphDecoratorBase(std::shared_ptr<Glyph> g)
: _g(std::move(g))
{
Q_ASSERT(_g);
}

std::shared_ptr<Glyph> inner() const { return _g; }

QRectF rect() const override { return _g->rect(); }
QPointF advance() const override { return _g->advance(); }

void draw(QPainter* p) const override { _g->draw(p); }

private:
std::shared_ptr<Glyph> _g;
};

} // namespace

class Skin::DecoratedGlyph : public GlyphDecoratorBase {
public:
using GlyphDecoratorBase::GlyphDecoratorBase;

QMarginsF margins() const { return _mgs; }

void setMargins(QMarginsF mgs)
{
if (_mgs == mgs) return;
_mgs = std::move(mgs);
notify(&GeometryChangeListener::onGeometryChanged);
}

QRectF rect() const override { return inner()->rect().marginsAdded(_mgs); }

private:
QMarginsF _mgs;
};


std::shared_ptr<Skin::Glyph> Skin::glyph(char32_t c) const
{
auto& cached_glyph = _cache[c];
if (!cached_glyph) {
if (auto g = create(c)) {
cached_glyph = std::make_shared<DecoratedGlyph>(std::move(g));
cached_glyph->setMargins(_mgs);
}
}
return cached_glyph;
}

void Skin::setMargins(QMarginsF mgs)
{
if (_mgs == mgs) return;
for (auto& g : std::as_const(_cache))
g->setMargins(mgs);
_mgs = std::move(mgs);
}
29 changes: 17 additions & 12 deletions skin_engine/skin/skin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,18 @@
#include <QRect>

#include "skin_engine_global.hpp"
#include "observable.hpp"

class QPainter;

class SKIN_ENGINE_EXPORT GeometryChangeListener {
public:
virtual ~GeometryChangeListener() = default;

virtual void onGeometryChanged() = 0;
};


class SKIN_ENGINE_EXPORT Skin {
public:
virtual ~Skin() = default;
Expand All @@ -24,7 +33,7 @@ class SKIN_ENGINE_EXPORT Skin {
virtual bool hasAlternateSeparator() const = 0;
virtual bool supportsCustomSeparator() const = 0;

class Glyph {
class Glyph : public Observable<GeometryChangeListener> {
public:
virtual ~Glyph() = default;

Expand All @@ -35,22 +44,18 @@ class SKIN_ENGINE_EXPORT Skin {
virtual void draw(QPainter* p) const = 0;
};

virtual std::shared_ptr<Glyph> glyph(char32_t c) const = 0;
};
std::shared_ptr<Glyph> glyph(char32_t c) const;

QMarginsF margins() const { return _mgs; }

class SKIN_ENGINE_EXPORT SkinBase : public Skin {
public:
std::shared_ptr<Glyph> glyph(char32_t c) const override
{
auto& cached_glyph = _cache[c];
if (!cached_glyph) cached_glyph = create(c);
return cached_glyph;
}
void setMargins(QMarginsF mgs);

protected:
virtual std::shared_ptr<Glyph> create(char32_t c) const = 0;

private:
mutable QHash<char32_t, std::shared_ptr<Glyph>> _cache;
QMarginsF _mgs;

class DecoratedGlyph;
mutable QHash<char32_t, std::shared_ptr<DecoratedGlyph>> _cache;
};

0 comments on commit 4f64acd

Please sign in to comment.