Added text style modifiers
This commit is contained in:
parent
640d4673ad
commit
b43fedaaac
11 changed files with 385 additions and 34 deletions
|
|
@ -54,6 +54,7 @@ set(sources "src/main.cpp"
|
|||
"src/Server/MainServer.cpp"
|
||||
"src/Server/ServerData.cpp"
|
||||
"src/RichTextBox/RichTextBox.cpp"
|
||||
"src/RichTextBox/TextStyleModifier.cpp"
|
||||
"src/DrawingProgram/DrawingProgramCache.cpp"
|
||||
"src/DrawingProgram/DrawingProgram.cpp"
|
||||
"src/DrawingProgram/BrushTool.cpp"
|
||||
|
|
|
|||
|
|
@ -4,9 +4,22 @@
|
|||
#include <nlohmann/json.hpp>
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
#include "FixedPoint.hpp"
|
||||
#include <include/core/SkString.h>
|
||||
|
||||
#include <include/core/SkColor.h>
|
||||
|
||||
template <class Archive> void save(Archive& ar, SkString const & str) {
|
||||
ar(cereal::make_size_tag(static_cast<uint64_t>(str.size())));
|
||||
ar(cereal::binary_data(str.data(), str.size() * sizeof(char)));
|
||||
}
|
||||
|
||||
template <class Archive> void load(Archive& ar, SkString& str) {
|
||||
uint64_t size;
|
||||
ar(cereal::make_size_tag(size));
|
||||
str.resize(static_cast<size_t>(size));
|
||||
ar(cereal::binary_data(const_cast<char*>(str.data()), static_cast<size_t>(size) * sizeof(char)));
|
||||
}
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
// https://stackoverflow.com/questions/22884216/serializing-eigenmatrix-using-cereal-library (with some modifications using constexpr)
|
||||
|
|
|
|||
|
|
@ -26,11 +26,7 @@ bool TextBoxEditTool::edit_gui(const std::shared_ptr<DrawComponent>& comp) {
|
|||
//});
|
||||
t.gui.pop_id();
|
||||
|
||||
TextBoxEditToolAllData newData = get_all_data(a);
|
||||
bool editHappened = newData != oldData;
|
||||
if(editHappened)
|
||||
oldData = newData;
|
||||
return editHappened;
|
||||
return true; // NOTE: In general, the update data should always be sent even if no changes were made, because we're sending the data over an unreliable channel.
|
||||
}
|
||||
|
||||
void TextBoxEditTool::commit_edit_updates(const std::shared_ptr<DrawComponent>& comp, std::any& prevData) {
|
||||
|
|
@ -74,8 +70,7 @@ void TextBoxEditTool::edit_start(EditTool& editTool, const std::shared_ptr<DrawC
|
|||
cur = std::make_shared<RichTextBox::Cursor>();
|
||||
Vector2f textSelectPos = a->get_mouse_pos(drawP);
|
||||
textbox->process_mouse_left_button(*cur, textSelectPos, true, false, false);
|
||||
oldData = get_all_data(a);
|
||||
prevData = oldData;
|
||||
prevData = get_all_data(a);
|
||||
a->d.editing = true;
|
||||
a->client_send_update(drawP, false);
|
||||
editTool.add_point_handle({&a->d.p1, nullptr, &a->d.p2});
|
||||
|
|
|
|||
|
|
@ -18,10 +18,6 @@ class TextBoxEditTool : public DrawingProgramEditToolBase {
|
|||
struct TextBoxEditToolAllData {
|
||||
DrawTextBox::Data textboxData;
|
||||
RichTextBox::RichTextData richText;
|
||||
bool operator==(const TextBoxEditToolAllData& o) const = default;
|
||||
bool operator!=(const TextBoxEditToolAllData& o) const = default;
|
||||
};
|
||||
TextBoxEditToolAllData get_all_data(const std::shared_ptr<DrawTextBox>& a);
|
||||
|
||||
TextBoxEditToolAllData oldData;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ void SelectableButton::update(UpdateInputData& io, DrawType drawType, const std:
|
|||
.cornerRadius = CLAY_CORNER_RADIUS(4),
|
||||
.border = {
|
||||
.color = convert_vec4<Clay_Color>(borderColor),
|
||||
.width = CLAY_BORDER_OUTSIDE(1)
|
||||
.width = CLAY_BORDER_OUTSIDE(2)
|
||||
}
|
||||
}) {
|
||||
CLAY({.layout = {
|
||||
|
|
|
|||
|
|
@ -59,13 +59,23 @@ template <typename T> class TextBox : public Element {
|
|||
|
||||
canvas->clipRect(SkRect::MakeXYWH(bb.min.x(), bb.min.y(), bb.width(), bb.height()));
|
||||
|
||||
canvas->translate(bb.min.x(), bb.min.y());
|
||||
canvas->translate(bb.min.x() + 2.0f, bb.min.y());
|
||||
|
||||
RichTextBox::PaintOpts paintOpts;
|
||||
if(selection.selected)
|
||||
paintOpts.cursor = *cur;
|
||||
paintOpts.cursorColor = {io.theme->fillColor1.fR, io.theme->fillColor1.fG, io.theme->fillColor1.fB};
|
||||
|
||||
auto fontFamiliesMod = std::make_shared<FontFamiliesTextStyleModifier>();
|
||||
fontFamiliesMod->families.emplace_back("Roboto");
|
||||
textbox->set_initial_text_style_modifier(fontFamiliesMod);
|
||||
auto fontSizeMod = std::make_shared<SizeTextStyleModifier>();
|
||||
fontSizeMod->size = io.fontSize;
|
||||
textbox->set_initial_text_style_modifier(fontSizeMod);
|
||||
auto fontColorMod = std::make_shared<ColorTextStyleModifier>();
|
||||
fontColorMod->color = convert_vec4<Vector4f>(io.theme->frontColor1);
|
||||
textbox->set_initial_text_style_modifier(fontColorMod);
|
||||
|
||||
textbox->paint(canvas, paintOpts);
|
||||
|
||||
canvas->restore();
|
||||
|
|
@ -80,6 +90,7 @@ template <typename T> class TextBox : public Element {
|
|||
textbox = std::make_shared<RichTextBox>();
|
||||
textbox->set_font_collection(io.fontCollection);
|
||||
textbox->set_allow_newlines(!singleLine);
|
||||
|
||||
cur = std::make_shared<RichTextBox::Cursor>();
|
||||
|
||||
if(data) {
|
||||
|
|
|
|||
|
|
@ -209,6 +209,16 @@ void GUIManager::draw(SkCanvas* canvas) {
|
|||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_START: {
|
||||
Clay_ClipRenderData* clip = &command->renderData.clip;
|
||||
if(!clip->horizontal) {
|
||||
bb.x = 0.0f;
|
||||
bb.width = std::numeric_limits<float>::max();
|
||||
}
|
||||
if(!clip->vertical) {
|
||||
bb.y = 0.0f;
|
||||
bb.height = std::numeric_limits<float>::max();
|
||||
}
|
||||
|
||||
canvas->save();
|
||||
SkRect clipRect = SkRect::MakeXYWH(bb.x - 1.0f, bb.y - 1.0f, bb.width + 1.0f, bb.height + 1.0f);
|
||||
canvas->clipRect(clipRect);
|
||||
|
|
@ -578,6 +588,7 @@ void GUIManager::dropdown_select(const std::string& id, size_t* val, const std::
|
|||
CLAY({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0)},
|
||||
.childGap = 1,
|
||||
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_TOP},
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
}
|
||||
|
|
@ -727,7 +738,7 @@ void GUIManager::scroll_bar_many_entries_area(const std::string& uniqueId, float
|
|||
scrollAmount = std::fabs(scrollAmount);
|
||||
float entryHeight = 25.0f;
|
||||
size_t startPoint = scrollAmount / entryHeight;
|
||||
size_t elementsContainable = (containerHeight / entryHeight) + 1;
|
||||
size_t elementsContainable = (containerHeight / entryHeight) + 2; // Displaying 2 more elements ensures that there isn't any empty space in the container
|
||||
size_t endPoint = std::min(entryCount, startPoint + elementsContainable);
|
||||
|
||||
if(startPoint != 0) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "RichTextBox.hpp"
|
||||
#include "TextStyleModifier.hpp"
|
||||
#include <limits>
|
||||
#include <modules/skparagraph/include/DartTypes.h>
|
||||
#include <modules/skparagraph/include/Metrics.h>
|
||||
|
|
@ -9,6 +10,37 @@
|
|||
#include <modules/skparagraph/src/ParagraphImpl.h>
|
||||
#include <Helpers/MathExtras.hpp>
|
||||
#include <src/base/SkUTF.h>
|
||||
#include <cereal/types/string.hpp>
|
||||
|
||||
void RichTextBox::RichTextData::Paragraph::save(cereal::PortableBinaryOutputArchive& a) const {
|
||||
a(text);
|
||||
a(static_cast<uint32_t>(tStyles.size()));
|
||||
for(auto& [pos, styles] : tStyles) {
|
||||
a(pos, static_cast<uint16_t>(styles.size()));
|
||||
for(auto& [styleType, style] : styles)
|
||||
a(static_cast<uint16_t>(styleType), *style);
|
||||
}
|
||||
}
|
||||
|
||||
void RichTextBox::RichTextData::Paragraph::load(cereal::PortableBinaryInputArchive& a) {
|
||||
a(text);
|
||||
uint32_t styleCount;
|
||||
a(styleCount);
|
||||
tStyles.clear();
|
||||
for(uint32_t i = 0; i < styleCount; i++) {
|
||||
uint32_t pos;
|
||||
uint16_t styleCountAtPos;
|
||||
a(pos, styleCountAtPos);
|
||||
TextModAtPosContainer& mods = tStyles[pos];
|
||||
for(uint16_t j = 0; j < styleCountAtPos; j++) {
|
||||
uint16_t styleType;
|
||||
a(styleType);
|
||||
std::shared_ptr<TextStyleModifier> modifier = TextStyleModifier::allocate_modifier(static_cast<TextStyleModifier::ModifierType>(styleType));
|
||||
a(*modifier);
|
||||
mods.emplace(static_cast<TextStyleModifier::ModifierType>(styleType), modifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RichTextBox::TextPosition::operator<(const RichTextBox::TextPosition& o) const {
|
||||
return (this->fParagraphIndex < o.fParagraphIndex) || (this->fParagraphIndex == o.fParagraphIndex && this->fTextByteIndex < o.fTextByteIndex);
|
||||
|
|
@ -50,13 +82,13 @@ void RichTextBox::process_key_input(Cursor& cur, InputKey in, bool ctrl, bool sh
|
|||
if(cur.selectionBeginPos != cur.selectionEndPos)
|
||||
cur.selectionEndPos = cur.selectionBeginPos = cur.pos = remove(cur.selectionBeginPos, cur.selectionEndPos);
|
||||
else
|
||||
cur.selectionEndPos = cur.selectionBeginPos = cur.pos = remove(cur.pos, move(Movement::LEFT, cur.pos));
|
||||
cur.selectionEndPos = cur.selectionBeginPos = cur.pos = remove(cur.pos, move(ctrl ? Movement::LEFT_WORD : Movement::LEFT, cur.pos));
|
||||
break;
|
||||
case InputKey::DELETE:
|
||||
if(cur.selectionBeginPos != cur.selectionEndPos)
|
||||
cur.selectionEndPos = cur.selectionBeginPos = cur.pos = remove(cur.selectionBeginPos, cur.selectionEndPos);
|
||||
else
|
||||
cur.selectionEndPos = cur.selectionBeginPos = cur.pos = remove(cur.pos, move(Movement::RIGHT, cur.pos));
|
||||
cur.selectionEndPos = cur.selectionBeginPos = cur.pos = remove(cur.pos, move(ctrl ? Movement::RIGHT_WORD : Movement::RIGHT, cur.pos));
|
||||
break;
|
||||
case InputKey::ENTER:
|
||||
process_text_input(cur, "\n");
|
||||
|
|
@ -217,7 +249,13 @@ RichTextBox::TextPosition RichTextBox::get_text_pos_closest_to_point(Vector2f po
|
|||
}
|
||||
|
||||
RichTextBox::RichTextData RichTextBox::get_rich_text_data() {
|
||||
return {get_string()};
|
||||
RichTextData toRet;
|
||||
for(auto& p : paragraphs) {
|
||||
toRet.paragraphs.emplace_back();
|
||||
toRet.paragraphs.back().text = p.text;
|
||||
toRet.paragraphs.back().tStyles = p.tStyles;
|
||||
}
|
||||
return toRet;
|
||||
}
|
||||
|
||||
void RichTextBox::clear_text() {
|
||||
|
|
@ -231,7 +269,15 @@ void RichTextBox::set_string(const std::string& str) {
|
|||
}
|
||||
|
||||
void RichTextBox::set_rich_text_data(const RichTextData& richText) {
|
||||
set_string(richText.text);
|
||||
paragraphs.clear();
|
||||
for(auto& p : richText.paragraphs) {
|
||||
paragraphs.emplace_back();
|
||||
paragraphs.back().text = p.text;
|
||||
paragraphs.back().tStyles = p.tStyles;
|
||||
}
|
||||
if(richText.paragraphs.empty())
|
||||
paragraphs.emplace_back();
|
||||
needsRebuild = true;
|
||||
}
|
||||
|
||||
std::string RichTextBox::get_string() {
|
||||
|
|
@ -261,6 +307,16 @@ std::string RichTextBox::get_text_between(TextPosition p1, TextPosition p2) {
|
|||
return toRet;
|
||||
}
|
||||
|
||||
void RichTextBox::set_initial_text_style_modifier(const std::shared_ptr<TextStyleModifier>& modifier) {
|
||||
std::shared_ptr<TextStyleModifier>& modToSet = paragraphs.back().tStyles[0][modifier->get_type()];
|
||||
needsRebuild |= ((modToSet == nullptr) || (!modifier->equivalent(*modToSet)));
|
||||
modToSet = modifier;
|
||||
}
|
||||
|
||||
void RichTextBox::set_text_style_modifier_between(TextPosition p1, TextPosition p2, const std::shared_ptr<TextStyleModifier>& modifier) {
|
||||
needsRebuild = true;
|
||||
}
|
||||
|
||||
RichTextBox::TextPosition RichTextBox::move(Movement movement, TextPosition pos, std::optional<float>* previousX, bool flipDependingOnTextDirection) {
|
||||
if(pos.fParagraphIndex >= paragraphs.size()) {
|
||||
pos.fParagraphIndex = paragraphs.size() - 1;
|
||||
|
|
@ -457,18 +513,35 @@ void RichTextBox::set_font_collection(const sk_sp<skia::textlayout::FontCollecti
|
|||
|
||||
void RichTextBox::rebuild() {
|
||||
if(needsRebuild) {
|
||||
|
||||
float heightOffset = 0.0f;
|
||||
skia::textlayout::TextStyle tStyle;
|
||||
|
||||
for(ParagraphData& pData : paragraphs) {
|
||||
pData.pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft);
|
||||
pData.pStyle.setTextDirection(skia::textlayout::TextDirection::kLtr);
|
||||
skia::textlayout::TextStyle tStyle;
|
||||
tStyle.setFontSize(16.0f);
|
||||
tStyle.setFontFamilies({SkString{"Roboto"}});
|
||||
pData.pStyle.setTextStyle(tStyle);
|
||||
|
||||
skia::textlayout::ParagraphBuilderImpl a(pData.pStyle, fontCollection, SkUnicodes::ICU::Make());
|
||||
a.addText(pData.text.c_str(), pData.text.length());
|
||||
|
||||
size_t startPos = 0;
|
||||
for(auto& [pos, tStylesAtPos] : pData.tStyles) {
|
||||
if(pos > pData.text.size())
|
||||
break;
|
||||
|
||||
for(auto& [styleType, styleMod] : tStylesAtPos)
|
||||
styleMod->modify_text_style(tStyle);
|
||||
if(startPos != pos) {
|
||||
a.pushStyle(tStyle);
|
||||
a.addText(pData.text.c_str() + startPos, pos - startPos);
|
||||
a.pop();
|
||||
}
|
||||
startPos = pos;
|
||||
}
|
||||
|
||||
if(startPos < pData.text.size()) {
|
||||
a.pushStyle(tStyle);
|
||||
a.addText(pData.text.c_str() + startPos, pData.text.size() - startPos);
|
||||
a.pop();
|
||||
}
|
||||
|
||||
pData.p = a.Build();
|
||||
pData.p->layout(width);
|
||||
pData.heightOffset = heightOffset;
|
||||
|
|
|
|||
|
|
@ -3,10 +3,16 @@
|
|||
#include <include/core/SkCanvas.h>
|
||||
#include <modules/skparagraph/include/FontCollection.h>
|
||||
#include <modules/skparagraph/include/Paragraph.h>
|
||||
#include <map>
|
||||
#include "../SharedTypes.hpp"
|
||||
#include "TextStyleModifier.hpp"
|
||||
#include "cereal/archives/portable_binary.hpp"
|
||||
|
||||
class RichTextBox {
|
||||
public:
|
||||
typedef std::unordered_map<TextStyleModifier::ModifierType, std::shared_ptr<TextStyleModifier>> TextModAtPosContainer;
|
||||
typedef std::map<size_t, TextModAtPosContainer> TextModContainer;
|
||||
|
||||
RichTextBox();
|
||||
|
||||
enum class Movement {
|
||||
|
|
@ -48,15 +54,16 @@ class RichTextBox {
|
|||
};
|
||||
|
||||
struct RichTextData {
|
||||
std::string text;
|
||||
bool operator==(const RichTextData& o) const = default;
|
||||
bool operator!=(const RichTextData& o) const = default;
|
||||
template <typename Archive> void save(Archive& a) const {
|
||||
a(text);
|
||||
}
|
||||
template <typename Archive> void load(Archive& a) {
|
||||
a(text);
|
||||
struct Paragraph {
|
||||
std::string text;
|
||||
TextModContainer tStyles;
|
||||
void save(cereal::PortableBinaryOutputArchive& a) const;
|
||||
void load(cereal::PortableBinaryInputArchive& a);
|
||||
};
|
||||
template<typename Archive> void serialize(Archive& a) {
|
||||
a(paragraphs);
|
||||
}
|
||||
std::vector<Paragraph> paragraphs;
|
||||
};
|
||||
|
||||
TextPosition move(Movement movement, TextPosition pos, std::optional<float>* previousX = nullptr, bool flipDependingOnTextDirection = false);
|
||||
|
|
@ -81,6 +88,9 @@ class RichTextBox {
|
|||
SELECT_ALL
|
||||
};
|
||||
|
||||
void set_initial_text_style_modifier(const std::shared_ptr<TextStyleModifier>& modifier);
|
||||
void set_text_style_modifier_between(TextPosition p1, TextPosition p2, const std::shared_ptr<TextStyleModifier>& modifier);
|
||||
|
||||
RichTextData get_rich_text_data();
|
||||
void set_rich_text_data(const RichTextData& richText);
|
||||
void clear_text();
|
||||
|
|
@ -100,6 +110,7 @@ class RichTextBox {
|
|||
static size_t next_grapheme(const std::string& text, size_t textBytePos);
|
||||
static size_t prev_grapheme(const std::string& text, size_t textBytePos);
|
||||
static TextPosition get_text_pos_from_byte_pos(const std::string& text, size_t textBytePos);
|
||||
|
||||
size_t get_byte_pos_from_text_pos(TextPosition textPos);
|
||||
|
||||
void rects_between_text_positions_func(TextPosition p1, TextPosition p2, std::function<void(const SkRect& r)> f);
|
||||
|
|
@ -112,7 +123,6 @@ class RichTextBox {
|
|||
|
||||
bool newlinesAllowed = true;
|
||||
float width = 0.0f;
|
||||
float fontSize = 0.0f;
|
||||
bool needsRebuild = true;
|
||||
unsigned tabWidth = 8;
|
||||
sk_sp<skia::textlayout::FontCollection> fontCollection;
|
||||
|
|
@ -122,6 +132,7 @@ class RichTextBox {
|
|||
std::unique_ptr<skia::textlayout::Paragraph> p;
|
||||
float heightOffset;
|
||||
skia::textlayout::ParagraphStyle pStyle;
|
||||
TextModContainer tStyles;
|
||||
};
|
||||
|
||||
std::vector<ParagraphData> paragraphs;
|
||||
|
|
|
|||
155
src/RichTextBox/TextStyleModifier.cpp
Normal file
155
src/RichTextBox/TextStyleModifier.cpp
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
#include "TextStyleModifier.hpp"
|
||||
#include <Helpers/ConvertVec.hpp>
|
||||
#include <Helpers/Serializers.hpp>
|
||||
|
||||
#define WEIGHT_VALUE_MODIFIER 100
|
||||
|
||||
std::shared_ptr<TextStyleModifier> TextStyleModifier::allocate_modifier(ModifierType type) {
|
||||
switch(type) {
|
||||
case ModifierType::SIZE:
|
||||
return std::make_shared<SizeTextStyleModifier>();
|
||||
case ModifierType::COLOR:
|
||||
return std::make_shared<ColorTextStyleModifier>();
|
||||
case ModifierType::WEIGHT:
|
||||
return std::make_shared<WeightTextStyleModifier>();
|
||||
case ModifierType::SLANT:
|
||||
return std::make_shared<SlantTextStyleModifier>();
|
||||
case ModifierType::FONT_FAMILIES:
|
||||
return std::make_shared<FontFamiliesTextStyleModifier>();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool TextStyleModifier::equivalent(TextStyleModifier& modifier) const {
|
||||
if(modifier.get_type() != get_type())
|
||||
return false;
|
||||
return equivalent_data(modifier);
|
||||
}
|
||||
|
||||
TextStyleModifier::~TextStyleModifier() {}
|
||||
|
||||
|
||||
|
||||
TextStyleModifier::ModifierType WeightTextStyleModifier::get_type() const {
|
||||
return ModifierType::WEIGHT;
|
||||
}
|
||||
|
||||
void WeightTextStyleModifier::save(cereal::PortableBinaryOutputArchive& a) const {
|
||||
a(weightValue);
|
||||
}
|
||||
|
||||
void WeightTextStyleModifier::load(cereal::PortableBinaryInputArchive& a) {
|
||||
a(weightValue);
|
||||
}
|
||||
|
||||
void WeightTextStyleModifier::set_weight(SkFontStyle::Weight newWeight) {
|
||||
weightValue = newWeight / WEIGHT_VALUE_MODIFIER;
|
||||
}
|
||||
|
||||
SkFontStyle::Weight WeightTextStyleModifier::get_weight() {
|
||||
return static_cast<SkFontStyle::Weight>(static_cast<int>(weightValue) * WEIGHT_VALUE_MODIFIER);
|
||||
}
|
||||
|
||||
void WeightTextStyleModifier::modify_text_style(skia::textlayout::TextStyle& style) const {
|
||||
style.setFontStyle(SkFontStyle(static_cast<int>(weightValue) * WEIGHT_VALUE_MODIFIER, style.getFontStyle().width(), style.getFontStyle().slant()));
|
||||
}
|
||||
|
||||
bool WeightTextStyleModifier::equivalent_data(TextStyleModifier& modifier) const {
|
||||
return weightValue == static_cast<WeightTextStyleModifier&>(modifier).weightValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TextStyleModifier::ModifierType SlantTextStyleModifier::get_type() const {
|
||||
return ModifierType::SLANT;
|
||||
}
|
||||
|
||||
void SlantTextStyleModifier::save(cereal::PortableBinaryOutputArchive& a) const {
|
||||
a(slantValue);
|
||||
}
|
||||
|
||||
void SlantTextStyleModifier::load(cereal::PortableBinaryInputArchive& a) {
|
||||
a(slantValue);
|
||||
}
|
||||
|
||||
void SlantTextStyleModifier::set_slant(SkFontStyle::Slant newSlant) {
|
||||
slantValue = newSlant;
|
||||
}
|
||||
|
||||
SkFontStyle::Slant SlantTextStyleModifier::get_slant() {
|
||||
return static_cast<SkFontStyle::Slant>(slantValue);
|
||||
}
|
||||
|
||||
void SlantTextStyleModifier::modify_text_style(skia::textlayout::TextStyle& style) const {
|
||||
style.setFontStyle(SkFontStyle(style.getFontStyle().weight(), style.getFontStyle().width(), static_cast<SkFontStyle::Slant>(slantValue)));
|
||||
}
|
||||
|
||||
bool SlantTextStyleModifier::equivalent_data(TextStyleModifier& modifier) const {
|
||||
return slantValue == static_cast<SlantTextStyleModifier&>(modifier).slantValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TextStyleModifier::ModifierType ColorTextStyleModifier::get_type() const {
|
||||
return ModifierType::COLOR;
|
||||
}
|
||||
|
||||
void ColorTextStyleModifier::save(cereal::PortableBinaryOutputArchive& a) const {
|
||||
a(color);
|
||||
}
|
||||
|
||||
void ColorTextStyleModifier::load(cereal::PortableBinaryInputArchive& a) {
|
||||
a(color);
|
||||
}
|
||||
|
||||
void ColorTextStyleModifier::modify_text_style(skia::textlayout::TextStyle& style) const {
|
||||
style.setForegroundPaint(SkPaint{convert_vec4<SkColor4f>(color)});
|
||||
}
|
||||
|
||||
bool ColorTextStyleModifier::equivalent_data(TextStyleModifier& modifier) const {
|
||||
return color == static_cast<ColorTextStyleModifier&>(modifier).color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TextStyleModifier::ModifierType SizeTextStyleModifier::get_type() const {
|
||||
return ModifierType::SIZE;
|
||||
}
|
||||
|
||||
void SizeTextStyleModifier::save(cereal::PortableBinaryOutputArchive& a) const {
|
||||
a(size);
|
||||
}
|
||||
|
||||
void SizeTextStyleModifier::load(cereal::PortableBinaryInputArchive& a) {
|
||||
a(size);
|
||||
}
|
||||
|
||||
void SizeTextStyleModifier::modify_text_style(skia::textlayout::TextStyle& style) const {
|
||||
style.setFontSize(size);
|
||||
}
|
||||
|
||||
bool SizeTextStyleModifier::equivalent_data(TextStyleModifier& modifier) const {
|
||||
return size == static_cast<SizeTextStyleModifier&>(modifier).size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TextStyleModifier::ModifierType FontFamiliesTextStyleModifier::get_type() const {
|
||||
return ModifierType::FONT_FAMILIES;
|
||||
}
|
||||
|
||||
void FontFamiliesTextStyleModifier::save(cereal::PortableBinaryOutputArchive& a) const {
|
||||
a(families);
|
||||
}
|
||||
|
||||
void FontFamiliesTextStyleModifier::load(cereal::PortableBinaryInputArchive& a) {
|
||||
a(families);
|
||||
}
|
||||
|
||||
void FontFamiliesTextStyleModifier::modify_text_style(skia::textlayout::TextStyle& style) const {
|
||||
style.setFontFamilies(families);
|
||||
}
|
||||
|
||||
bool FontFamiliesTextStyleModifier::equivalent_data(TextStyleModifier& modifier) const {
|
||||
return families == static_cast<FontFamiliesTextStyleModifier&>(modifier).families;
|
||||
}
|
||||
85
src/RichTextBox/TextStyleModifier.hpp
Normal file
85
src/RichTextBox/TextStyleModifier.hpp
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <modules/skparagraph/include/Paragraph.h>
|
||||
#include <modules/skparagraph/include/TextStyle.h>
|
||||
#include "cereal/archives/portable_binary.hpp"
|
||||
#include "../SharedTypes.hpp"
|
||||
|
||||
class TextStyleModifier {
|
||||
public:
|
||||
enum class ModifierType : uint16_t {
|
||||
SIZE = 0,
|
||||
COLOR,
|
||||
WEIGHT,
|
||||
SLANT,
|
||||
FONT_FAMILIES
|
||||
};
|
||||
static std::shared_ptr<TextStyleModifier> allocate_modifier(ModifierType type);
|
||||
virtual ModifierType get_type() const = 0;
|
||||
virtual void save(cereal::PortableBinaryOutputArchive& a) const = 0;
|
||||
virtual void load(cereal::PortableBinaryInputArchive& a) = 0;
|
||||
virtual void modify_text_style(skia::textlayout::TextStyle& style) const = 0;
|
||||
bool equivalent(TextStyleModifier& modifier) const;
|
||||
virtual ~TextStyleModifier();
|
||||
private:
|
||||
virtual bool equivalent_data(TextStyleModifier& modifier) const = 0;
|
||||
};
|
||||
|
||||
class WeightTextStyleModifier : public TextStyleModifier {
|
||||
public:
|
||||
virtual ModifierType get_type() const override;
|
||||
virtual void save(cereal::PortableBinaryOutputArchive& a) const override;
|
||||
virtual void load(cereal::PortableBinaryInputArchive& a) override;
|
||||
virtual void modify_text_style(skia::textlayout::TextStyle& style) const override;
|
||||
void set_weight(SkFontStyle::Weight newWeight);
|
||||
SkFontStyle::Weight get_weight();
|
||||
private:
|
||||
virtual bool equivalent_data(TextStyleModifier& modifier) const override;
|
||||
uint8_t weightValue;
|
||||
};
|
||||
|
||||
class SlantTextStyleModifier : public TextStyleModifier {
|
||||
public:
|
||||
virtual ModifierType get_type() const override;
|
||||
virtual void save(cereal::PortableBinaryOutputArchive& a) const override;
|
||||
virtual void load(cereal::PortableBinaryInputArchive& a) override;
|
||||
virtual void modify_text_style(skia::textlayout::TextStyle& style) const override;
|
||||
void set_slant(SkFontStyle::Slant newSlant);
|
||||
SkFontStyle::Slant get_slant();
|
||||
private:
|
||||
virtual bool equivalent_data(TextStyleModifier& modifier) const override;
|
||||
uint8_t slantValue;
|
||||
};
|
||||
|
||||
class ColorTextStyleModifier : public TextStyleModifier {
|
||||
public:
|
||||
virtual ModifierType get_type() const override;
|
||||
virtual void save(cereal::PortableBinaryOutputArchive& a) const override;
|
||||
virtual void load(cereal::PortableBinaryInputArchive& a) override;
|
||||
virtual void modify_text_style(skia::textlayout::TextStyle& style) const override;
|
||||
Vector4f color;
|
||||
private:
|
||||
virtual bool equivalent_data(TextStyleModifier& modifier) const override;
|
||||
};
|
||||
|
||||
class SizeTextStyleModifier : public TextStyleModifier {
|
||||
public:
|
||||
virtual ModifierType get_type() const override;
|
||||
virtual void save(cereal::PortableBinaryOutputArchive& a) const override;
|
||||
virtual void load(cereal::PortableBinaryInputArchive& a) override;
|
||||
virtual void modify_text_style(skia::textlayout::TextStyle& style) const override;
|
||||
float size;
|
||||
private:
|
||||
virtual bool equivalent_data(TextStyleModifier& modifier) const override;
|
||||
};
|
||||
|
||||
class FontFamiliesTextStyleModifier : public TextStyleModifier {
|
||||
public:
|
||||
virtual ModifierType get_type() const override;
|
||||
virtual void save(cereal::PortableBinaryOutputArchive& a) const override;
|
||||
virtual void load(cereal::PortableBinaryInputArchive& a) override;
|
||||
virtual void modify_text_style(skia::textlayout::TextStyle& style) const override;
|
||||
std::vector<SkString> families;
|
||||
private:
|
||||
virtual bool equivalent_data(TextStyleModifier& modifier) const override;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue