Added UI to change paragraph style
This commit is contained in:
parent
435d9346a9
commit
def4ccb984
12 changed files with 117 additions and 43 deletions
1
data/icons/RemixIcon/align-center.svg
Normal file
1
data/icons/RemixIcon/align-center.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M3 4H21V6H3V4ZM5 19H19V21H5V19ZM3 14H21V16H3V14ZM5 9H19V11H5V9Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 167 B |
1
data/icons/RemixIcon/align-justify.svg
Normal file
1
data/icons/RemixIcon/align-justify.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M3 4H21V6H3V4ZM3 19H21V21H3V19ZM3 14H21V16H3V14ZM3 9H21V11H3V9Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 167 B |
1
data/icons/RemixIcon/align-left.svg
Normal file
1
data/icons/RemixIcon/align-left.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M3 4H21V6H3V4ZM3 19H17V21H3V19ZM3 14H21V16H3V14ZM3 9H17V11H3V9Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 167 B |
1
data/icons/RemixIcon/align-right.svg
Normal file
1
data/icons/RemixIcon/align-right.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M3 4H21V6H3V4ZM7 19H21V21H7V19ZM3 14H21V16H3V14ZM7 9H21V11H7V9Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 167 B |
1
data/icons/RemixIcon/text-direction-l.svg
Normal file
1
data/icons/RemixIcon/text-direction-l.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M11 5V15H9V11C6.79086 11 5 9.20914 5 7C5 4.79086 6.79086 3 9 3H17V5H15V15H13V5H11ZM9 5C7.89543 5 7 5.89543 7 7C7 8.10457 7.89543 9 9 9V5ZM17 17V14.5L21 18L17 21.5V19H5V17H17Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 278 B |
1
data/icons/RemixIcon/text-direction-r.svg
Normal file
1
data/icons/RemixIcon/text-direction-r.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M11 5V15H9V11C6.79086 11 5 9.20914 5 7C5 4.79086 6.79086 3 9 3H17V5H15V15H13V5H11ZM9 5C7.89543 5 7 5.89543 7 7C7 8.10457 7.89543 9 9 9V5ZM7 17H19V19H7V21.5L3 18L7 14.5V17Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 275 B |
|
|
@ -68,6 +68,21 @@ bool TextBoxEditTool::edit_gui(const std::shared_ptr<DrawComponent>& comp) {
|
|||
}
|
||||
});
|
||||
|
||||
t.gui.left_to_right_line_centered_layout([&]() {
|
||||
if(t.gui.svg_icon_button("Align left button", "data/icons/RemixIcon/align-left.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kLeft))
|
||||
a->textBox->set_text_alignment_between(a->cursor->selectionBeginPos.fParagraphIndex, a->cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kLeft);
|
||||
if(t.gui.svg_icon_button("Align center button", "data/icons/RemixIcon/align-center.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kCenter))
|
||||
a->textBox->set_text_alignment_between(a->cursor->selectionBeginPos.fParagraphIndex, a->cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kCenter);
|
||||
if(t.gui.svg_icon_button("Align right button", "data/icons/RemixIcon/align-right.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kRight))
|
||||
a->textBox->set_text_alignment_between(a->cursor->selectionBeginPos.fParagraphIndex, a->cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kRight);
|
||||
if(t.gui.svg_icon_button("Align justify button", "data/icons/RemixIcon/align-justify.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kJustify))
|
||||
a->textBox->set_text_alignment_between(a->cursor->selectionBeginPos.fParagraphIndex, a->cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kJustify);
|
||||
if(t.gui.svg_icon_button("Text direction left", "data/icons/RemixIcon/text-direction-l.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kLtr))
|
||||
a->textBox->set_text_direction_between(a->cursor->selectionBeginPos.fParagraphIndex, a->cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kLtr);
|
||||
if(t.gui.svg_icon_button("Text direction right", "data/icons/RemixIcon/text-direction-r.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kRtl))
|
||||
a->textBox->set_text_direction_between(a->cursor->selectionBeginPos.fParagraphIndex, a->cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kRtl);
|
||||
});
|
||||
|
||||
if(t.gui.slider_scalar_field<uint32_t>("Font Size Slider", "Font Size", &newFontSize, 3, 100)) {
|
||||
currentMods[TextStyleModifier::ModifierType::SIZE] = std::make_shared<SizeTextStyleModifier>(newFontSize);
|
||||
a->textBox->set_text_style_modifier_between(a->cursor->selectionBeginPos, a->cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SIZE]);
|
||||
|
|
@ -90,17 +105,8 @@ bool TextBoxEditTool::edit_gui(const std::shared_ptr<DrawComponent>& comp) {
|
|||
|
||||
t.gui.pop_id();
|
||||
|
||||
if(a->textBox->inputChangedTextBox) {
|
||||
set_mods_at_selection(a);
|
||||
newFontName = std::static_pointer_cast<FontFamiliesTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES])->get_families().back().c_str();
|
||||
newFontSize = std::static_pointer_cast<SizeTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::SIZE])->get_size();
|
||||
newTextColor = std::static_pointer_cast<ColorTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::COLOR])->get_color();
|
||||
newIsBold = std::static_pointer_cast<WeightTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::WEIGHT])->get_weight() == SkFontStyle::Weight::kBold_Weight;
|
||||
newIsItalic = std::static_pointer_cast<SlantTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::SLANT])->get_slant() == SkFontStyle::Slant::kItalic_Slant;
|
||||
newIsUnderlined = std::static_pointer_cast<DecorationTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::DECORATION])->get_decoration_value() & skia::textlayout::TextDecoration::kUnderline;
|
||||
newIsLinethrough = std::static_pointer_cast<DecorationTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::DECORATION])->get_decoration_value() & skia::textlayout::TextDecoration::kLineThrough;
|
||||
newIsOverline = std::static_pointer_cast<DecorationTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::DECORATION])->get_decoration_value() & skia::textlayout::TextDecoration::kOverline;
|
||||
}
|
||||
if(a->textBox->inputChangedTextBox)
|
||||
set_styles_at_selection(a);
|
||||
|
||||
// NOTE: There should be a system that periodically sends updates even if no changes are made, since unreliable channels can drop update data
|
||||
bool oldInputChangedTextBox = a->textBox->inputChangedTextBox;
|
||||
|
|
@ -119,13 +125,24 @@ uint8_t TextBoxEditTool::get_new_decoration_value() {
|
|||
return toRet;
|
||||
}
|
||||
|
||||
void TextBoxEditTool::set_mods_at_selection(const std::shared_ptr<DrawTextBox>& a) {
|
||||
void TextBoxEditTool::set_styles_at_selection(const std::shared_ptr<DrawTextBox>& a) {
|
||||
TextPosition start = std::min(a->cursor->selectionBeginPos, a->cursor->selectionEndPos);
|
||||
TextPosition end = std::max(a->cursor->selectionBeginPos, a->cursor->selectionEndPos);
|
||||
if(start == end)
|
||||
currentMods = a->textBox->get_mods_used_at_pos(a->textBox->move(TextBox::Movement::LEFT, start));
|
||||
else
|
||||
currentMods = a->textBox->get_mods_used_at_pos(start);
|
||||
|
||||
newFontName = std::static_pointer_cast<FontFamiliesTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES])->get_families().back().c_str();
|
||||
newFontSize = std::static_pointer_cast<SizeTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::SIZE])->get_size();
|
||||
newTextColor = std::static_pointer_cast<ColorTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::COLOR])->get_color();
|
||||
newIsBold = std::static_pointer_cast<WeightTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::WEIGHT])->get_weight() == SkFontStyle::Weight::kBold_Weight;
|
||||
newIsItalic = std::static_pointer_cast<SlantTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::SLANT])->get_slant() == SkFontStyle::Slant::kItalic_Slant;
|
||||
newIsUnderlined = std::static_pointer_cast<DecorationTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::DECORATION])->get_decoration_value() & skia::textlayout::TextDecoration::kUnderline;
|
||||
newIsLinethrough = std::static_pointer_cast<DecorationTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::DECORATION])->get_decoration_value() & skia::textlayout::TextDecoration::kLineThrough;
|
||||
newIsOverline = std::static_pointer_cast<DecorationTextStyleModifier>(currentMods[TextStyleModifier::ModifierType::DECORATION])->get_decoration_value() & skia::textlayout::TextDecoration::kOverline;
|
||||
|
||||
currentPStyle = a->textBox->get_paragraph_style_data_at(start.fParagraphIndex);
|
||||
}
|
||||
|
||||
void TextBoxEditTool::commit_edit_updates(const std::shared_ptr<DrawComponent>& comp, std::any& prevData) {
|
||||
|
|
@ -176,7 +193,7 @@ void TextBoxEditTool::edit_start(EditTool& editTool, const std::shared_ptr<DrawC
|
|||
a->commit_update(drawP);
|
||||
a->client_send_update(drawP, false);
|
||||
|
||||
set_mods_at_selection(a);
|
||||
set_styles_at_selection(a);
|
||||
|
||||
editTool.add_point_handle({&a->d.p1, nullptr, &a->d.p2});
|
||||
editTool.add_point_handle({&a->d.p2, &a->d.p1, nullptr});
|
||||
|
|
|
|||
|
|
@ -28,9 +28,10 @@ class TextBoxEditTool : public DrawingProgramEditToolBase {
|
|||
bool newIsLinethrough = false;
|
||||
bool newIsOverline = false;
|
||||
std::string newFontName;
|
||||
ParagraphStyleData currentPStyle;
|
||||
|
||||
uint8_t get_new_decoration_value();
|
||||
void set_mods_at_selection(const std::shared_ptr<DrawTextBox>& a);
|
||||
void set_styles_at_selection(const std::shared_ptr<DrawTextBox>& a);
|
||||
RichText::TextStyleModifier::ModifierMap currentMods;
|
||||
|
||||
std::vector<std::string> sortedFontList;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
#include "ParagraphStyleData.hpp"
|
||||
|
||||
skia::textlayout::ParagraphStyle ParagraphStyleData::get_paragraph_style() const {
|
||||
skia::textlayout::ParagraphStyle pStyle;
|
||||
pStyle.setTextAlign(textAlignment);
|
||||
pStyle.setTextDirection(textDirection);
|
||||
return pStyle;
|
||||
}
|
||||
|
|
@ -1,6 +1,18 @@
|
|||
#pragma once
|
||||
#include <modules/skparagraph/include/ParagraphStyle.h>
|
||||
|
||||
struct ParagraphStyleData {
|
||||
|
||||
skia::textlayout::TextAlign textAlignment = skia::textlayout::TextAlign::kLeft;
|
||||
skia::textlayout::TextDirection textDirection = skia::textlayout::TextDirection::kLtr;
|
||||
template <typename Archive> void save(Archive& a) const {
|
||||
a(static_cast<uint8_t>(textAlignment), static_cast<uint8_t>(textDirection));
|
||||
}
|
||||
template <typename Archive> void load(Archive& a) {
|
||||
uint8_t alignRead, directionRead;
|
||||
a(alignRead, directionRead);
|
||||
textAlignment = static_cast<skia::textlayout::TextAlign>(alignRead);
|
||||
textDirection = static_cast<skia::textlayout::TextDirection>(directionRead);
|
||||
}
|
||||
skia::textlayout::ParagraphStyle get_paragraph_style() const;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -274,6 +274,7 @@ TextData TextBox::get_rich_text_data() {
|
|||
for(auto& p : paragraphs) {
|
||||
toRet.paragraphs.emplace_back();
|
||||
toRet.paragraphs.back().text = p.text;
|
||||
toRet.paragraphs.back().pStyleData = p.pStyleData;
|
||||
}
|
||||
toRet.tStyleMods = tStyleMods;
|
||||
return toRet;
|
||||
|
|
@ -295,6 +296,7 @@ void TextBox::set_rich_text_data(const TextData& richText) {
|
|||
for(auto& p : richText.paragraphs) {
|
||||
paragraphs.emplace_back();
|
||||
paragraphs.back().text = p.text;
|
||||
paragraphs.back().pStyleData = p.pStyleData;
|
||||
}
|
||||
if(richText.paragraphs.empty())
|
||||
paragraphs.emplace_back();
|
||||
|
|
@ -308,15 +310,11 @@ std::string TextBox::get_string() {
|
|||
}
|
||||
|
||||
std::string TextBox::get_text_between(TextPosition p1, TextPosition p2) {
|
||||
p1 = move(Movement::NOWHERE, p1);
|
||||
p2 = move(Movement::NOWHERE, p2);
|
||||
auto [start, end] = get_start_end_text_pos(p1, p2);
|
||||
|
||||
if(p1 == p2)
|
||||
if(start == end)
|
||||
return "";
|
||||
|
||||
TextPosition start = std::min(p1, p2);
|
||||
TextPosition end = std::max(p1, p2);
|
||||
|
||||
std::string toRet;
|
||||
|
||||
for(size_t pIndex = start.fParagraphIndex; pIndex <= end.fParagraphIndex; pIndex++) {
|
||||
|
|
@ -395,11 +393,8 @@ void TextBox::erase_if_over_all_styles_until_pos(TextPosition pos, const std::fu
|
|||
}
|
||||
|
||||
void TextBox::set_text_style_modifier_between(TextPosition p1, TextPosition p2, const std::shared_ptr<TextStyleModifier>& modifier) {
|
||||
p1 = move(Movement::NOWHERE, p1);
|
||||
p2 = move(Movement::NOWHERE, p2);
|
||||
if(p1 != p2) {
|
||||
TextPosition start = std::min(p1, p2);
|
||||
TextPosition end = std::max(p1, p2);
|
||||
auto [start, end] = get_start_end_text_pos(p1, p2);
|
||||
if(start != end) {
|
||||
auto lastModOfThisTypeBeforeEnd = get_last_text_style_mod_before_pos(end, modifier->get_type());
|
||||
assert(lastModOfThisTypeBeforeEnd != nullptr);
|
||||
erase_if_over_all_styles_until_pos(end, [&](TextPosition p, const std::shared_ptr<TextStyleModifier>& modToCheck) {
|
||||
|
|
@ -413,6 +408,26 @@ void TextBox::set_text_style_modifier_between(TextPosition p1, TextPosition p2,
|
|||
}
|
||||
}
|
||||
|
||||
void TextBox::set_text_alignment_between(size_t paragraphIndex1, size_t paragraphIndex2, skia::textlayout::TextAlign newAlignment) {
|
||||
auto [start, end] = get_start_end_paragraph_pos(paragraphIndex1, paragraphIndex2);
|
||||
for(size_t i = start; i <= end; i++)
|
||||
paragraphs[i].pStyleData.textAlignment = newAlignment;
|
||||
inputChangedTextBox = true;
|
||||
needsRebuild = true;
|
||||
}
|
||||
|
||||
void TextBox::set_text_direction_between(size_t paragraphIndex1, size_t paragraphIndex2, skia::textlayout::TextDirection newDirection) {
|
||||
auto [start, end] = get_start_end_paragraph_pos(paragraphIndex1, paragraphIndex2);
|
||||
for(size_t i = start; i <= end; i++)
|
||||
paragraphs[i].pStyleData.textDirection = newDirection;
|
||||
inputChangedTextBox = true;
|
||||
needsRebuild = true;
|
||||
}
|
||||
|
||||
ParagraphStyleData TextBox::get_paragraph_style_data_at(size_t paragraphIndex) {
|
||||
return paragraphs[std::min(paragraphIndex, paragraphs.size() - 1)].pStyleData;
|
||||
}
|
||||
|
||||
void TextBox::insert_style_at_pos(TextPosition pos, const std::shared_ptr<TextStyleModifier>& modifier) {
|
||||
size_t indexToPlaceAt = 0;
|
||||
bool finishedInsertingStyle = false;
|
||||
|
|
@ -445,7 +460,7 @@ TextPosition TextBox::move(Movement movement, TextPosition pos, std::optional<fl
|
|||
|
||||
if(movement != Movement::NOWHERE && movement != Movement::HOME && movement != Movement::END) {
|
||||
rebuild();
|
||||
if(flipDependingOnTextDirection && paragraphs[pos.fParagraphIndex].pStyle.getTextDirection() == skia::textlayout::TextDirection::kRtl) {
|
||||
if(flipDependingOnTextDirection && paragraphs[pos.fParagraphIndex].pStyleData.textDirection == skia::textlayout::TextDirection::kRtl) {
|
||||
if(movement == Movement::LEFT)
|
||||
movement = Movement::RIGHT;
|
||||
else if(movement == Movement::RIGHT)
|
||||
|
|
@ -640,11 +655,10 @@ void TextBox::rebuild() {
|
|||
|
||||
for(size_t pIndex = 0; pIndex < paragraphs.size(); pIndex++) {
|
||||
ParagraphData& pData = paragraphs[pIndex];
|
||||
pData.pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft);
|
||||
pData.pStyle.setTextDirection(skia::textlayout::TextDirection::kLtr);
|
||||
pData.pStyle.setTextStyle(tStyle);
|
||||
skia::textlayout::ParagraphStyle pStyle = pData.pStyleData.get_paragraph_style();
|
||||
pStyle.setTextStyle(tStyle);
|
||||
size_t tIndex = 0;
|
||||
skia::textlayout::ParagraphBuilderImpl a(pData.pStyle, fontCollection, SkUnicodes::ICU::Make());
|
||||
skia::textlayout::ParagraphBuilderImpl a(pStyle, fontCollection, SkUnicodes::ICU::Make());
|
||||
|
||||
for(;;) {
|
||||
if(nextTStyleModIt == tStyleMods.end() || nextTStyleModIt->pos.fParagraphIndex != pIndex) {
|
||||
|
|
@ -721,6 +735,7 @@ TextPosition TextBox::insert(TextPosition pos, std::string_view textToInsert, co
|
|||
}
|
||||
}
|
||||
paragraphs.insert(paragraphs.begin() + pos.fParagraphIndex + 1, ParagraphData{});
|
||||
paragraphs[pos.fParagraphIndex + 1].pStyleData = paragraphs[pos.fParagraphIndex].pStyleData;
|
||||
paragraphs[pos.fParagraphIndex + 1].text = paragraphs[pos.fParagraphIndex].text.substr(pos.fTextByteIndex, paragraphs[pos.fParagraphIndex].text.size() - pos.fTextByteIndex);
|
||||
paragraphs[pos.fParagraphIndex].text.erase(pos.fTextByteIndex, paragraphs[pos.fParagraphIndex].text.size() - pos.fTextByteIndex);
|
||||
pos.fParagraphIndex++;
|
||||
|
|
@ -759,11 +774,8 @@ TextPosition TextBox::insert(TextPosition pos, std::string_view textToInsert, co
|
|||
}
|
||||
|
||||
TextPosition TextBox::remove(TextPosition p1, TextPosition p2) {
|
||||
p1 = move(Movement::NOWHERE, p1);
|
||||
p2 = move(Movement::NOWHERE, p2);
|
||||
auto [start, end] = get_start_end_text_pos(p1, p2);
|
||||
|
||||
TextPosition start = std::min(p1, p2);
|
||||
TextPosition end = std::max(p1, p2);
|
||||
if(start == end || start.fParagraphIndex == paragraphs.size())
|
||||
return start;
|
||||
if(start.fParagraphIndex == end.fParagraphIndex) {
|
||||
|
|
@ -817,7 +829,7 @@ SkRect TextBox::get_cursor_rect(TextPosition pos) {
|
|||
|
||||
const ParagraphData& pData = paragraphs[pos.fParagraphIndex];
|
||||
if(pData.text.empty()) {
|
||||
bool isAlignLeft = (pData.pStyle.getTextAlign() == skia::textlayout::TextAlign::kLeft) || (pData.pStyle.getTextAlign() == skia::textlayout::TextAlign::kJustify && pData.pStyle.getTextDirection() == skia::textlayout::TextDirection::kLtr);
|
||||
bool isAlignLeft = (pData.pStyleData.textAlignment == skia::textlayout::TextAlign::kLeft) || (pData.pStyleData.textAlignment == skia::textlayout::TextAlign::kJustify && pData.pStyleData.textDirection == skia::textlayout::TextDirection::kLtr);
|
||||
topPoint = {isAlignLeft ? 0.0f : pData.p->getMaxWidth(), pData.heightOffset};
|
||||
height = pData.p->getHeight();
|
||||
}
|
||||
|
|
@ -856,14 +868,10 @@ SkRect TextBox::get_cursor_rect(TextPosition pos) {
|
|||
}
|
||||
|
||||
void TextBox::rects_between_text_positions_func(TextPosition p1, TextPosition p2, std::function<void(const SkRect& r)> f) {
|
||||
p1 = move(Movement::NOWHERE, p1);
|
||||
p2 = move(Movement::NOWHERE, p2);
|
||||
auto [start, end] = get_start_end_text_pos(p1, p2);
|
||||
|
||||
constexpr float SELECTION_RECT_EXTRA_AREA = 1.0f;
|
||||
|
||||
TextPosition start = std::min(p1, p2);
|
||||
TextPosition end = std::max(p1, p2);
|
||||
|
||||
for(size_t p = start.fParagraphIndex; p <= end.fParagraphIndex; p++) {
|
||||
size_t tStart = p == start.fParagraphIndex ? start.fTextByteIndex : 0;
|
||||
size_t tEnd = p == end.fParagraphIndex ? end.fTextByteIndex : paragraphs[p].text.size();
|
||||
|
|
@ -884,6 +892,18 @@ void TextBox::rects_between_text_positions_func(TextPosition p1, TextPosition p2
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<TextPosition, TextPosition> TextBox::get_start_end_text_pos(TextPosition p1, TextPosition p2) {
|
||||
p1 = move(Movement::NOWHERE, p1);
|
||||
p2 = move(Movement::NOWHERE, p2);
|
||||
return {std::min(p1, p2), std::max(p1, p2)};
|
||||
}
|
||||
|
||||
std::pair<size_t, size_t> TextBox::get_start_end_paragraph_pos(size_t p1, size_t p2) {
|
||||
p1 = std::min(p1, paragraphs.size() - 1);
|
||||
p2 = std::min(p2, paragraphs.size() - 1);
|
||||
return {std::min(p1, p2), std::max(p1, p2)};
|
||||
}
|
||||
|
||||
void TextBox::paint(SkCanvas* canvas, const PaintOpts& paintOpts) {
|
||||
rebuild();
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "../SharedTypes.hpp"
|
||||
#include "TextStyleModifier.hpp"
|
||||
#include "cereal/archives/portable_binary.hpp"
|
||||
#include "ParagraphStyleData.hpp"
|
||||
|
||||
namespace RichText {
|
||||
|
||||
|
|
@ -35,8 +36,9 @@ typedef std::vector<PositionedTextStyleMod> TextStyleModContainer;
|
|||
struct TextData {
|
||||
struct Paragraph {
|
||||
std::string text;
|
||||
ParagraphStyleData pStyleData;
|
||||
template<typename Archive> void serialize(Archive& a) {
|
||||
a(text);
|
||||
a(text, pStyleData);
|
||||
}
|
||||
};
|
||||
void save(cereal::PortableBinaryOutputArchive& a) const;
|
||||
|
|
@ -105,6 +107,11 @@ class TextBox {
|
|||
void set_initial_text_style(const skia::textlayout::TextStyle& tStyle);
|
||||
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);
|
||||
|
||||
void set_text_alignment_between(size_t paragraphIndex1, size_t paragraphIndex2, skia::textlayout::TextAlign newAlignment);
|
||||
void set_text_direction_between(size_t paragraphIndex1, size_t paragraphIndex2, skia::textlayout::TextDirection newDirection);
|
||||
ParagraphStyleData get_paragraph_style_data_at(size_t paragraphIndex);
|
||||
|
||||
TextStyleModifier::ModifierMap get_mods_used_at_pos(TextPosition p);
|
||||
|
||||
TextData get_rich_text_data();
|
||||
|
|
@ -122,6 +129,9 @@ class TextBox {
|
|||
void process_text_input(Cursor& cur, const std::string& in, const std::optional<TextStyleModifier::ModifierMap>& inputModMap = std::nullopt);
|
||||
|
||||
private:
|
||||
std::pair<TextPosition, TextPosition> get_start_end_text_pos(TextPosition p1, TextPosition p2);
|
||||
std::pair<size_t, size_t> get_start_end_paragraph_pos(size_t p1, size_t p2);
|
||||
|
||||
static size_t count_grapheme(const std::string& text);
|
||||
static size_t next_grapheme(const std::string& text, size_t textBytePos);
|
||||
static size_t prev_grapheme(const std::string& text, size_t textBytePos);
|
||||
|
|
@ -152,7 +162,7 @@ class TextBox {
|
|||
std::string text;
|
||||
std::unique_ptr<skia::textlayout::Paragraph> p;
|
||||
float heightOffset;
|
||||
skia::textlayout::ParagraphStyle pStyle;
|
||||
ParagraphStyleData pStyleData;
|
||||
};
|
||||
|
||||
skia::textlayout::TextStyle initialTStyle;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue