Merge branch '63-add-badges-decals-e-g-for-favorites-completed-games-non-working-games-collections-and-folders' into 575-theme-add-a-modern-clean-switch-like-theme-as-an-official-theme-in-es-de-to-choose-from

This commit is contained in:
Sophia Hadash 2021-10-11 23:38:30 +02:00
commit 1c6a80fcc7
7 changed files with 360 additions and 383 deletions

View file

@ -404,17 +404,19 @@ void DetailedGameListView::updateInfoPanel()
mGenre.setValue(file->metadata.get("genre"));
mPlayers.setValue(file->metadata.get("players"));
// Generate badges slots value based on the game metadata.
std::stringstream ss;
ss << (file->metadata.get("favorite").compare("true") ? "" : "favorite ");
ss << (file->metadata.get("completed").compare("true") ? "" : "completed ");
ss << (file->metadata.get("kidgame").compare("true") ? "" : "kidgame ");
ss << (file->metadata.get("broken").compare("true") ? "" : "broken ");
ss << (file->metadata.get("altemulator").compare("") ? "altemulator " : "");
std::string slots = ss.str();
if (!slots.empty())
slots.pop_back();
mBadges.setValue(slots);
// Populate the badge slots based on game metadata.
std::vector<std::string> badgeSlots;
for (auto badge : mBadges.getBadgeTypes()) {
if (badge == "altemulator") {
if (file->metadata.get(badge).compare("") != 0)
badgeSlots.push_back(badge);
}
else {
if (file->metadata.get(badge).compare("true") == 0)
badgeSlots.push_back(badge);
}
}
mBadges.setBadges(badgeSlots);
mName.setValue(file->metadata.get("name"));

View file

@ -445,17 +445,19 @@ void VideoGameListView::updateInfoPanel()
mGenre.setValue(file->metadata.get("genre"));
mPlayers.setValue(file->metadata.get("players"));
// Generate badges slots value based on the game metadata.
std::stringstream ss;
ss << (file->metadata.get("favorite").compare("true") ? "" : "favorite ");
ss << (file->metadata.get("completed").compare("true") ? "" : "completed ");
ss << (file->metadata.get("kidgame").compare("true") ? "" : "kidgame ");
ss << (file->metadata.get("broken").compare("true") ? "" : "broken ");
ss << (file->metadata.get("altemulator").compare("") ? "altemulator " : "");
std::string slots = ss.str();
if (!slots.empty())
slots.pop_back();
mBadges.setValue(slots);
// Populate the badge slots based on game metadata.
std::vector<std::string> badgeSlots;
for (auto badge : mBadges.getBadgeTypes()) {
if (badge == "altemulator") {
if (file->metadata.get(badge).compare("") != 0)
badgeSlots.push_back(badge);
}
else {
if (file->metadata.get(badge).compare("true") == 0)
badgeSlots.push_back(badge);
}
}
mBadges.setBadges(badgeSlots);
mName.setValue(file->metadata.get("name"));

View file

@ -7,72 +7,55 @@
// Used by gamelist views.
//
#define SLOT_FAVORITE "favorite"
#define SLOT_COMPLETED "completed"
#define SLOT_KIDGAME "kidgame"
#define SLOT_BROKEN "broken"
#define SLOT_ALTERNATIVE_EMULATOR "altemulator"
#include "components/BadgesComponent.h"
#include "Settings.h"
#include "ThemeData.h"
#include "resources/TextureResource.h"
// Available slot definitions.
std::vector<std::string> BadgesComponent::mSlots = {SLOT_FAVORITE, SLOT_COMPLETED, SLOT_KIDS,
SLOT_BROKEN, SLOT_ALTERNATIVE_EMULATOR};
#include "utils/StringUtil.h"
BadgesComponent::BadgesComponent(Window* window)
: FlexboxComponent(window)
: FlexboxComponent{window, mBadgeImages}
, mBadgeTypes{
{SLOT_FAVORITE, SLOT_COMPLETED, SLOT_KIDGAME, SLOT_BROKEN, SLOT_ALTERNATIVE_EMULATOR}}
{
mBadgeIcons[SLOT_FAVORITE] = ":/graphics/badge_favorite.svg";
mBadgeIcons[SLOT_COMPLETED] = ":/graphics/badge_completed.svg";
mBadgeIcons[SLOT_KIDS] = ":/graphics/badge_kidgame.svg";
mBadgeIcons[SLOT_KIDGAME] = ":/graphics/badge_kidgame.svg";
mBadgeIcons[SLOT_BROKEN] = ":/graphics/badge_broken.svg";
mBadgeIcons[SLOT_ALTERNATIVE_EMULATOR] = ":/graphics/badge_altemulator.svg";
ImageComponent mImageFavorite = ImageComponent(window);
mImageComponents.insert({SLOT_FAVORITE, mImageFavorite});
ImageComponent mImageCompleted = ImageComponent(window);
mImageComponents.insert({SLOT_COMPLETED, mImageCompleted});
ImageComponent mImageKids = ImageComponent(window);
mImageComponents.insert({SLOT_KIDS, mImageKids});
ImageComponent mImageBroken = ImageComponent(window);
mImageComponents.insert({SLOT_BROKEN, mImageBroken});
ImageComponent mImageAltEmulator = ImageComponent(window);
mImageComponents.insert({SLOT_ALTERNATIVE_EMULATOR, mImageAltEmulator});
}
BadgesComponent::~BadgesComponent()
void BadgesComponent::setBadges(const std::vector<std::string>& badges)
{
for (GuiComponent* c : mChildren)
c->clearChildren();
clearChildren();
mBadgeIcons.clear();
mImageComponents.clear();
std::map<std::string, bool> prevVisibility;
// Save the visibility status to know whether any badges changed.
for (auto& image : mBadgeImages) {
prevVisibility[image.first] = image.second.isVisible();
image.second.setVisible(false);
}
void BadgesComponent::setValue(const std::string& value)
{
mChildren.clear();
if (!value.empty()) {
std::string temp;
std::istringstream ss(value);
while (std::getline(ss, temp, ' ')) {
if (!(temp == SLOT_FAVORITE || temp == SLOT_COMPLETED || temp == SLOT_KIDS ||
temp == SLOT_BROKEN || temp == SLOT_ALTERNATIVE_EMULATOR))
LOG(LogError) << "Badge slot '" << temp << "' is invalid.";
else if (std::find(mSlots.begin(), mSlots.end(), temp) != mSlots.end())
mChildren.push_back(&mImageComponents.find(temp)->second);
}
for (auto& badge : badges) {
auto it = std::find_if(
mBadgeImages.begin(), mBadgeImages.end(),
[badge](std::pair<std::string, ImageComponent> image) { return image.first == badge; });
if (it != mBadgeImages.cend())
it->second.setVisible(true);
}
// Only recalculate the flexbox if any badges changed.
for (auto& image : mBadgeImages) {
if (prevVisibility[image.first] != image.second.isVisible()) {
onSizeChanged();
break;
}
}
std::string BadgesComponent::getValue() const
{
std::stringstream ss;
for (auto& slot : mSlots)
ss << slot << ' ';
std::string r = ss.str();
r.pop_back();
return r;
}
void BadgesComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
@ -82,39 +65,31 @@ void BadgesComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
{
using namespace ThemeFlags;
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "badges");
const ThemeData::ThemeElement* elem{theme->getElement(view, element, "badges")};
if (!elem)
return;
for (auto& slot : mSlots) {
if (properties & PATH && elem->has(slot)) {
if (elem->has("slots")) {
std::vector<std::string> slots = Utils::String::delimitedStringToVector(
Utils::String::toLower(elem->get<std::string>("slots")), " ");
for (auto slot : slots) {
if (std::find(mBadgeTypes.cbegin(), mBadgeTypes.cend(), slot) != mBadgeTypes.end()) {
if (properties & PATH && elem->has(slot))
mBadgeIcons[slot] = elem->get<std::string>(slot);
mImageComponents.find(slot)->second.setImage(mBadgeIcons[slot]);
ImageComponent badgeImage{mWindow};
badgeImage.setImage(mBadgeIcons[slot]);
badgeImage.setVisible(false);
mBadgeImages.push_back(std::make_pair(slot, badgeImage));
}
else {
mImageComponents.find(slot)->second.setImage(mBadgeIcons[slot]);
std::string teststring;
}
}
if (elem->has("slots")) {
auto value = elem->get<std::string>("slots");
mSlots = {};
if (!value.empty()) {
std::string temp;
std::istringstream ss(value);
while (std::getline(ss, temp, ' ')) {
if (!(temp == SLOT_FAVORITE || temp == SLOT_COMPLETED || temp == SLOT_KIDS ||
temp == SLOT_BROKEN || temp == SLOT_ALTERNATIVE_EMULATOR))
LOG(LogError) << "Badge slot '" << temp << "' is invalid.";
else
mSlots.push_back(temp);
}
LOG(LogError) << "Invalid badge slot \"" << slot << "\" defined";
}
}
// Apply theme on the flexbox component parent.
FlexboxComponent::applyTheme(theme, view, element, properties);
onSizeChanged();
}
}

View file

@ -11,30 +11,14 @@
#define ES_CORE_COMPONENTS_BADGES_COMPONENT_H
#include "FlexboxComponent.h"
#include "GuiComponent.h"
#include "ImageComponent.h"
#include "renderers/Renderer.h"
#define NUM_SLOTS 4
#define SLOT_FAVORITE "favorite"
#define SLOT_COMPLETED "completed"
#define SLOT_KIDS "kidgame"
#define SLOT_BROKEN "broken"
#define SLOT_ALTERNATIVE_EMULATOR "altemulator"
class TextureResource;
class BadgesComponent : public FlexboxComponent
{
public:
BadgesComponent(Window* window);
~BadgesComponent();
static std::shared_ptr<BadgesComponent>& getInstance();
std::string getValue() const override;
// Should be a list of strings.
void setValue(const std::string& value) override;
std::vector<std::string> getBadgeTypes() { return mBadgeTypes; }
void setBadges(const std::vector<std::string>& badges);
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme,
const std::string& view,
@ -42,9 +26,9 @@ public:
unsigned int properties) override;
private:
static std::vector<std::string> mSlots;
std::vector<std::string> mBadgeTypes;
std::map<std::string, std::string> mBadgeIcons;
std::map<std::string, ImageComponent> mImageComponents;
std::vector<std::pair<std::string, ImageComponent>> mBadgeImages;
};
#endif // ES_CORE_COMPONENTS_BADGES_COMPONENT_H

View file

@ -7,35 +7,41 @@
// Used by gamelist views.
//
#include "components/FlexboxComponent.h"
#include "Settings.h"
#include "ThemeData.h"
#include "resources/TextureResource.h"
#define DEFAULT_DIRECTION Direction::row
#define DEFAULT_ALIGN Align::center
#define DEFAULT_ITEMS_PER_LINE 4
#define DEFAULT_LINES 1
#define DEFAULT_MARGIN_X 10.0f
#define DEFAULT_MARGIN_Y 10.0f
FlexboxComponent::FlexboxComponent(Window* window)
: GuiComponent(window)
, mDirection(DEFAULT_DIRECTION)
, mAlign(DEFAULT_ALIGN)
, mItemsPerLine(DEFAULT_ITEMS_PER_LINE)
, mLines(DEFAULT_LINES)
, mItemMargin({DEFAULT_MARGIN_X, DEFAULT_MARGIN_Y})
, mLayoutValid(false)
#include "components/FlexboxComponent.h"
#include "ThemeData.h"
FlexboxComponent::FlexboxComponent(Window* window,
std::vector<std::pair<std::string, ImageComponent>>& images)
: GuiComponent{window}
, mDirection{DEFAULT_DIRECTION}
, mAlign{DEFAULT_ALIGN}
, mImages(images)
, mItemsPerLine{DEFAULT_ITEMS_PER_LINE}
, mLines{DEFAULT_LINES}
, mItemMargin{glm::vec2{DEFAULT_MARGIN_X, DEFAULT_MARGIN_Y}}
, mLayoutValid{false}
{
}
void FlexboxComponent::onSizeChanged() { mLayoutValid = false; }
void FlexboxComponent::computeLayout()
{
// Start placing items in the top-left.
float anchorX = 0;
float anchorY = 0;
float anchorOriginX = 0;
float anchorOriginY = 0;
float anchorX{0.0f};
float anchorY{0.0f};
float anchorOriginX{0.0f};
float anchorOriginY{0.0f};
// Translation directions when placing items.
glm::ivec2 directionLine = {1, 0};
glm::ivec2 directionRow = {0, 1};
glm::ivec2 directionLine{1, 0};
glm::ivec2 directionRow{0, 1};
// Change direction.
if (mDirection == Direction::column) {
@ -43,21 +49,23 @@ void FlexboxComponent::computeLayout()
directionRow = {1, 0};
}
// Compute children maximal dimensions.
// Compute maximum image dimensions.
glm::vec2 grid;
if (mDirection == Direction::row)
grid = {mItemsPerLine, mLines};
else
grid = {mLines, mItemsPerLine};
glm::vec2 maxItemSize = (mSize + mItemMargin - grid * mItemMargin) / grid;
glm::vec2 maxItemSize{(mSize + mItemMargin - grid * mItemMargin) / grid};
// Set final children dimensions.
for (auto i : mChildren) {
auto oldSize = i->getSize();
// Set final image dimensions.
for (auto& image : mImages) {
if (!image.second.isVisible())
continue;
auto oldSize{image.second.getSize()};
if (oldSize.x == 0)
oldSize.x = maxItemSize.x;
glm::vec2 sizeMaxX = {maxItemSize.x, oldSize.y * (maxItemSize.x / oldSize.x)};
glm::vec2 sizeMaxY = {oldSize.x * (maxItemSize.y / oldSize.y), maxItemSize.y};
glm::vec2 sizeMaxX{maxItemSize.x, oldSize.y * (maxItemSize.x / oldSize.x)};
glm::vec2 sizeMaxY{oldSize.x * (maxItemSize.y / oldSize.y), maxItemSize.y};
glm::vec2 newSize;
if (sizeMaxX.y > maxItemSize.y)
newSize = sizeMaxY;
@ -65,23 +73,27 @@ void FlexboxComponent::computeLayout()
newSize = sizeMaxX;
else
newSize = sizeMaxX.x * sizeMaxX.y >= sizeMaxY.x * sizeMaxY.y ? sizeMaxX : sizeMaxY;
i->setSize(newSize);
image.second.setResize(newSize.x, newSize.y);
}
// Pre-compute layout parameters.
float lineWidth = (mDirection == Direction::row ? (maxItemSize.y + mItemMargin.y) :
(maxItemSize.x + mItemMargin.x));
float anchorXStart = anchorX;
float anchorYStart = anchorY;
float anchorXStart{anchorX};
float anchorYStart{anchorY};
// Iterate through the children.
for (int i = 0; i < static_cast<int>(mChildren.size()); i++) {
GuiComponent* child = mChildren[i];
auto size = child->getSize();
int i = 0;
// Iterate through the images.
for (auto& image : mImages) {
if (!image.second.isVisible())
continue;
auto size{image.second.getSize()};
// Top-left anchor position.
float x = anchorX - anchorOriginX * size.x;
float y = anchorY - anchorOriginY * size.y;
float x{anchorX - anchorOriginX * size.x};
float y{anchorY - anchorOriginY * size.y};
// Apply alignment
if (mAlign == Align::end) {
@ -93,7 +105,7 @@ void FlexboxComponent::computeLayout()
y += directionLine.y == 0 ? (maxItemSize.y - size.y) / 2 : 0;
}
else if (mAlign == Align::stretch && mDirection == Direction::row) {
child->setSize(child->getSize().x, maxItemSize.y);
image.second.setSize(image.second.getSize().x, maxItemSize.y);
}
// Apply origin.
@ -103,10 +115,10 @@ void FlexboxComponent::computeLayout()
y -= mOrigin.y * mSize.y;
// Store final item position.
child->setPosition(getPosition().x + x, getPosition().y + y);
image.second.setPosition(getPosition().x + x, getPosition().y + y);
// Translate anchor.
if ((i + 1) % std::max(1, static_cast<int>(mItemsPerLine)) != 0) {
if ((i++ + 1) % std::max(1, static_cast<int>(mItemsPerLine)) != 0) {
// Translate on same line.
anchorX += (size.x + mItemMargin.x) * static_cast<float>(directionLine.x);
anchorY += (size.y + mItemMargin.y) * static_cast<float>(directionLine.y);
@ -135,7 +147,8 @@ void FlexboxComponent::render(const glm::mat4& parentTrans)
if (!mLayoutValid)
computeLayout();
renderChildren(parentTrans);
for (auto& image : mImages)
image.second.render(parentTrans);
}
void FlexboxComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
@ -149,7 +162,6 @@ void FlexboxComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
glm::vec2{static_cast<float>(Renderer::getScreenWidth()),
static_cast<float>(Renderer::getScreenHeight())}};
// TODO: How to do this without explicit 'badges' property?
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "badges");
if (!elem)
return;
@ -179,9 +191,3 @@ void FlexboxComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
// Layout no longer valid.
mLayoutValid = false;
}
std::vector<HelpPrompt> FlexboxComponent::getHelpPrompts()
{
std::vector<HelpPrompt> prompts;
return prompts;
}

View file

@ -11,67 +11,75 @@
#define ES_CORE_COMPONENTS_FLEXBOX_COMPONENT_H
#include "GuiComponent.h"
#include "renderers/Renderer.h"
// Default values.
#define DEFAULT_DIRECTION Direction::row
#define DEFAULT_ALIGN Align::center
#define DEFAULT_ITEMS_PER_LINE 4
#define DEFAULT_LINES 1
#define DEFAULT_MARGIN_X 10.0f
#define DEFAULT_MARGIN_Y 10.0f
#include "components/ImageComponent.h"
class FlexboxComponent : public GuiComponent
{
public:
enum class Direction : char { row, column };
enum class Align : char { start, end, center, stretch };
enum class Direction : char {
row, // Replace with AllowShortEnumsOnASingleLine: false (clang-format >=11.0).
column
};
explicit FlexboxComponent(Window* window);
enum class Align : char {
start, // Replace with AllowShortEnumsOnASingleLine: false (clang-format >=11.0).
end,
center,
stretch
};
explicit FlexboxComponent(Window* window,
std::vector<std::pair<std::string, ImageComponent>>& images);
// Getters/Setters for rendering options.
[[nodiscard]] Align getAlign() const { return mAlign; };
Align getAlign() const { return mAlign; }
void setAlign(Align value)
{
mAlign = value;
mLayoutValid = false;
};
[[nodiscard]] unsigned int getItemsPerLine() const { return mItemsPerLine; };
}
unsigned int getItemsPerLine() const { return mItemsPerLine; }
void setItemsPerLine(unsigned int value)
{
mItemsPerLine = value;
mLayoutValid = false;
};
[[nodiscard]] unsigned int getLines() const { return mLines; };
}
unsigned int getLines() const { return mLines; }
void setLines(unsigned int value)
{
mLines = value;
mLayoutValid = false;
};
[[nodiscard]] glm::vec2 getItemMargin() const { return mItemMargin; };
}
glm::vec2 getItemMargin() const { return mItemMargin; }
void setItemMargin(glm::vec2 value)
{
mItemMargin = value;
mLayoutValid = false;
};
}
void onSizeChanged() override;
void onSizeChanged() override { mLayoutValid = false; }
void render(const glm::mat4& parentTrans) override;
void applyTheme(const std::shared_ptr<ThemeData>& theme,
const std::string& view,
const std::string& element,
unsigned int properties) override;
std::vector<HelpPrompt> getHelpPrompts() override;
private:
// Calculate flexbox layout.
void computeLayout();
// Rendering options.
// Layout options.
Direction mDirection;
Align mAlign;
std::vector<std::pair<std::string, ImageComponent>>& mImages;
unsigned int mItemsPerLine;
unsigned int mLines;
glm::vec2 mItemMargin;
bool mLayoutValid;
};

View file

@ -12,7 +12,7 @@
viewBox="0 0 21.166666 29.633334"
version="1.1"
id="svg4842"
inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
sodipodi:docname="badge_altemulator.svg">
<defs
id="defs4836" />
@ -23,15 +23,15 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.0546875"
inkscape:cx="29.041584"
inkscape:cy="62.825107"
inkscape:zoom="12.442154"
inkscape:cx="-18.41824"
inkscape:cy="59.681612"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:current-layer="layer2"
showgrid="false"
inkscape:window-width="3440"
inkscape:window-height="1355"
inkscape:window-x="2560"
inkscape:window-width="3840"
inkscape:window-height="2065"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
fit-margin-top="0"
@ -51,7 +51,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@ -401,30 +401,30 @@
aria-label="ALT EMU"
transform="scale(1.0680187,0.93631321)"
id="text41"
style="font-size:4.97619px;line-height:1.25;font-family:'Bebas Neue';-inkscape-font-specification:'Bebas Neue';display:inline;stroke-width:0.0339285">
style="font-size:4.97619px;line-height:1.25;font-family:'Bebas Neue';-inkscape-font-specification:'Bebas Neue';display:inline;stroke-width:0.0339285;fill:#f0f0f0;fill-opacity:1">
<path
d="m 1.7229501,4.7457954 c 0,0.024881 0.019905,0.03981 0.044786,0.03981 0.1642143,0.00995 0.3383809,0.014928 0.5075714,0.014928 0.1642142,0 0.2537857,-0.00498 0.4130238,-0.014928 0.034833,-0.1791429 0.06469,-0.3632619 0.094548,-0.547381 h 0.4627856 c 0.024881,0.1691905 0.054738,0.338381 0.089571,0.4976191 0.00498,0.029857 0.029857,0.049762 0.054738,0.049762 0.1741666,0.014928 0.3184761,0.014928 0.4876666,0.014928 0.1691904,0 0.2786666,-0.00498 0.4329285,-0.014928 C 4.1662594,3.8202241 3.9323785,2.8050813 3.7432833,1.8496528 3.7383071,1.8247719 3.7134261,1.7998909 3.6885452,1.7998909 3.449688,1.7949147 3.2158071,1.7899385 2.97695,1.7899385 c -0.233881,0 -0.4627857,0 -0.6867143,0.00995 -0.184119,0.9205952 -0.393119,1.8809999 -0.5424047,2.7916426 -0.00995,0.049762 -0.024881,0.1443096 -0.024881,0.1542619 z M 2.8674738,3.5913193 c 0.03981,-0.3732142 0.079619,-0.7464285 0.1244047,-1.1146665 0.049762,0.3732142 0.099524,0.7464285 0.1542619,1.1146665 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.97619px;font-family:Digitalt;-inkscape-font-specification:Digitalt;fill:#ffffff;stroke-width:0.0339285"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.97619px;font-family:Digitalt;-inkscape-font-specification:Digitalt;fill:#f0f0f0;stroke-width:0.0339285;fill-opacity:1"
id="path975" />
<path
d="m 4.4946808,3.2927479 c 0,0.497619 0.00995,0.9753333 0.019905,1.4430952 0,0.029857 0.019905,0.049762 0.049762,0.049762 0.1642143,0.00995 0.8857619,0.024881 1.0549523,0.024881 0.1642143,0 0.5772381,-0.00498 0.7364762,-0.014929 0,-0.1244047 0,-0.2438333 0,-0.3632618 0,-0.1393334 0,-0.2786667 0,-0.4329286 C 6.3507997,3.974486 6.3308949,3.949605 6.306014,3.949605 6.1368235,3.9446288 5.7138474,3.9396526 5.5446569,3.9396526 h -0.019905 c 0,-0.2089999 0.00498,-0.4229761 0.00498,-0.6469047 0,-0.497619 -0.00995,-0.9753332 -0.019905,-1.4430951 0,-0.024881 -0.024881,-0.049762 -0.049762,-0.049762 -0.1691905,-0.00498 -0.3433572,-0.00995 -0.5125476,-0.00995 -0.1642143,0 -0.2786667,0.00498 -0.4329286,0.00995 -0.014928,0.497619 -0.019905,0.995238 -0.019905,1.492857 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.97619px;font-family:Digitalt;-inkscape-font-specification:Digitalt;fill:#ffffff;stroke-width:0.0339285"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.97619px;font-family:Digitalt;-inkscape-font-specification:Digitalt;fill:#f0f0f0;stroke-width:0.0339285;fill-opacity:1"
id="path977" />
<path
d="m 6.1318408,2.1780813 c 0,0.1343572 0,0.2687143 0.00498,0.4080476 0,0.029857 0.019905,0.049762 0.049762,0.049762 0.084595,0.00498 0.3234523,0.00995 0.5473809,0.014929 0,0.209 0,0.4130238 0,0.6419285 0,0.497619 0.00995,0.9753333 0.019905,1.4430952 0,0.029857 0.019905,0.049762 0.049762,0.049762 0.1642143,0.00995 0.338381,0.014928 0.5075714,0.014928 0.1642143,0 0.2786667,-0.00498 0.4379048,-0.014928 0.00995,-0.4976191 0.019905,-0.9952381 0.019905,-1.4928571 0,-0.2289047 -0.00498,-0.4329285 -0.00995,-0.6369523 0.2587619,0 0.5225,-0.00498 0.6070952,-0.00995 0,-0.1244047 0,-0.2488095 0,-0.3682381 0,-0.1443095 0,-0.2836428 0,-0.4279523 -0.00498,-0.024881 -0.024881,-0.049762 -0.049762,-0.049762 -0.1691904,-0.00498 -0.8608809,-0.00995 -1.0300713,-0.00995 -0.1642143,0 -0.995238,0.00498 -1.1494999,0.00995 -0.00498,0.1343571 -0.00498,0.2587619 -0.00498,0.3781904 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.97619px;font-family:Digitalt;-inkscape-font-specification:Digitalt;fill:#ffffff;stroke-width:0.0339285"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.97619px;font-family:Digitalt;-inkscape-font-specification:Digitalt;fill:#f0f0f0;stroke-width:0.0339285;fill-opacity:1"
id="path979" />
<path
d="m 10.067999,3.2927479 c 0,0.497619 0.01,0.9753333 0.0199,1.4430952 0,0.029857 0.0199,0.049762 0.04976,0.049762 0.164215,0.00995 0.885762,0.024881 1.054953,0.024881 0.164214,0 0.696666,-0.00498 0.855904,-0.014929 0,-0.1244047 0,-0.2438333 0,-0.3632618 0,-0.1393334 0,-0.2786667 0,-0.4329286 -0.005,-0.024881 -0.02488,-0.049762 -0.04976,-0.049762 -0.169191,-0.00498 -0.711596,-0.00995 -0.880786,-0.00995 h -0.06469 c 0,-0.084595 0,-0.1691904 0,-0.2587618 h 0.646905 c 0,-0.1194286 0,-0.2239286 0,-0.3284286 0,-0.1194286 0,-0.2388571 0,-0.3781904 -0.005,-0.024881 -0.02488,-0.049762 -0.04976,-0.049762 -0.129381,0 -0.398095,-0.00498 -0.597143,-0.00498 0,-0.089571 0,-0.1791429 0,-0.2637381 0.0846,0 0.154262,0 0.194072,0 0.164214,0 0.631976,0 0.791214,-0.00995 0,-0.1244047 0,-0.2438333 0,-0.3632619 0,-0.1393333 0,-0.2786666 0,-0.4329285 -0.005,-0.024881 -0.02488,-0.049762 -0.04976,-0.049762 -0.16919,-0.00498 -0.701643,-0.00995 -0.870833,-0.00995 -0.164214,0 -0.87581,0.00498 -1.030071,0.00995 -0.01493,0.497619 -0.0199,0.995238 -0.0199,1.492857 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.97619px;font-family:Digitalt;-inkscape-font-specification:Digitalt;fill:#ffffff;stroke-width:0.0339285"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.97619px;font-family:Digitalt;-inkscape-font-specification:Digitalt;fill:#f0f0f0;stroke-width:0.0339285;fill-opacity:1"
id="path981" />
<path
d="m 12.327182,3.2927479 c 0,0.497619 0.01,0.9753333 0.0199,1.4430952 0,0.029857 0.01991,0.049762 0.04976,0.049762 0.164215,0.00995 0.363262,0.014928 0.482691,0.014928 0.164214,0 0.253786,-0.00498 0.413024,-0.014928 l -0.0199,-1.3485476 0.542405,1.099738 0.04976,0.00995 0.05474,-0.00995 0.567285,-1.1544761 c 0,0.4677619 0.0199,0.915619 0.02986,1.3535238 0,0.029857 0.0199,0.049762 0.04976,0.049762 0.164215,0.00995 0.338381,0.014928 0.45781,0.014928 0.164214,0 0.243833,-0.00498 0.388143,-0.014928 0.01,-0.4976191 0.0199,-0.9952381 0.0199,-1.4928571 0,-0.497619 -0.01,-0.9753332 -0.0199,-1.4430951 0,-0.024881 -0.02488,-0.044786 -0.04976,-0.049762 -0.139334,-0.00498 -0.293596,-0.00995 -0.462786,-0.00995 -0.139333,0 -0.258762,0.00498 -0.348333,0.014929 -0.02488,0 -0.04479,0.024881 -0.05972,0.044786 l -0.627,1.2788809 -0.622023,-1.2788809 c -0.01,-0.019905 -0.02986,-0.044786 -0.05474,-0.049762 -0.149286,-0.00498 -0.263738,-0.00995 -0.432929,-0.00995 -0.164214,0 -0.253786,0.00498 -0.408048,0.00995 -0.01493,0.497619 -0.0199,0.995238 -0.0199,1.492857 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.97619px;font-family:Digitalt;-inkscape-font-specification:Digitalt;fill:#ffffff;stroke-width:0.0339285"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.97619px;font-family:Digitalt;-inkscape-font-specification:Digitalt;fill:#f0f0f0;stroke-width:0.0339285;fill-opacity:1"
id="path983" />
<path
d="m 15.696059,3.3126527 c 0,1.2539999 0.447857,1.5227142 1.348547,1.5227142 0.701643,-0.034833 1.109691,-0.442881 1.109691,-1.5227142 0,-0.497619 -0.01,-0.995238 -0.01991,-1.4629999 0,-0.024881 -0.02488,-0.049762 -0.04976,-0.049762 -0.16919,-0.00498 -0.343357,-0.00995 -0.512548,-0.00995 -0.164214,0 -0.278666,0.00498 -0.432928,0.00995 -0.01493,0.497619 -0.01991,1.1644285 -0.01991,1.6620475 0,0.4428809 -0.05474,0.5075714 -0.189095,0.5075714 -0.134357,0 -0.199048,-0.06469 -0.199048,-0.5075714 0,-0.497619 -0.01,-1.1445237 -0.0199,-1.6122856 0,-0.024881 -0.02488,-0.049762 -0.04976,-0.049762 -0.169191,-0.00498 -0.343357,-0.00995 -0.512548,-0.00995 -0.164214,0 -0.278667,0.00498 -0.432928,0.00995 -0.01493,0.497619 -0.0199,1.0151428 -0.0199,1.5127618 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.97619px;font-family:Digitalt;-inkscape-font-specification:Digitalt;fill:#ffffff;stroke-width:0.0339285"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.97619px;font-family:Digitalt;-inkscape-font-specification:Digitalt;fill:#f0f0f0;stroke-width:0.0339285;fill-opacity:1"
id="path985" />
</g>
</g>

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 51 KiB