refactor attribute system and rename set_highlight_area

This commit is contained in:
Subhraman Sarkar 2024-08-11 16:52:51 +05:30 committed by Celtic Minstrel
parent 5958ca209e
commit 8bca642854
7 changed files with 54 additions and 96 deletions

View file

@ -433,7 +433,7 @@ void pango_text::add_attribute_font_family(const unsigned start_offset, const un
}
}
void pango_text::set_highlight_area(const unsigned start_offset, const unsigned end_offset, const color_t& color) {
void pango_text::add_attribute_bg_color(const unsigned start_offset, const unsigned end_offset, const color_t& color) {
attribute_start_offset_ = start_offset;
attribute_end_offset_ = end_offset;
highlight_color_ = color;

View file

@ -324,12 +324,11 @@ public:
* @param end_offset Column offset of the cursor where selection/highlight ends
* @param color Highlight color
*/
void set_highlight_area(const unsigned start_offset, const unsigned end_offset, const color_t& color);
void add_attribute_weight(const unsigned start_offset, const unsigned end_offset, PangoWeight weight);
void add_attribute_style(const unsigned start_offset, const unsigned end_offset, PangoStyle style);
void add_attribute_underline(const unsigned start_offset, const unsigned end_offset, PangoUnderline underline);
void add_attribute_fg_color(const unsigned start_offset, const unsigned end_offset, const color_t& color);
void add_attribute_bg_color(const unsigned start_offset, const unsigned end_offset, const color_t& color);
void add_attribute_size(const unsigned start_offset, const unsigned end_offset, int size);
void add_attribute_font_family(const unsigned start_offset, const unsigned end_offset, std::string family);

View file

@ -31,6 +31,7 @@
#include "gui/auxiliary/typed_formula.hpp"
#include "gui/core/log.hpp"
#include "gui/widgets/helper.hpp"
#include "font/font_config.hpp"
#include "font/standard_colors.hpp"
#include "picture.hpp"
#include "sdl/point.hpp"
@ -414,6 +415,7 @@ image_shape::resize_mode image_shape::get_resize_mode(const std::string& resize_
text_shape::text_shape(const config& cfg, wfl::action_function_symbol_table& functions)
: rect_bounded_shape(cfg)
, cfg_(cfg)
, font_family_(font::str_to_family_class(cfg["font_family"]))
, font_size_(cfg["font_size"])
, font_style_(decode_font_style(cfg["font_style"]))
@ -464,68 +466,51 @@ void text_shape::draw(wfl::map_formula_callable& variables)
font::pango_text& text_renderer = font::get_text_renderer();
text_renderer.clear_attribute_list();
//
// Highlight
//
std::vector<std::string> starts = utils::split(highlight_start_, ',');
std::vector<std::string> stops = utils::split(highlight_end_, ',');
for(size_t i = 0; i < std::min(starts.size(), stops.size()); i++) {
typed_formula<int> hstart(starts.at(i));
typed_formula<int> hstop(stops.at(i));
text_renderer.set_highlight_area(hstart(variables), hstop(variables), highlight_color_(variables));
text_renderer.add_attribute_bg_color(hstart(variables), hstop(variables), highlight_color_(variables));
}
// TODO check the strings before parsing them
starts = utils::split(attr_start_, ',');
stops = utils::split(attr_end_, ',');
std::vector<std::string> styles = utils::split(attr_name_, ',');
std::vector<std::string> data = utils::split(attr_data_, ',');
for(size_t i = 0, data_index = 0; i < std::min(starts.size(), stops.size()); i++) {
if (styles.at(i).empty()) {
//
// Attribute subtags
//
for (const auto& attr : cfg_.child_range("attribute")) {
if (attr["name"].empty()) {
continue;
}
typed_formula<int> attr_start(starts.at(i));
typed_formula<int> attr_stop(stops.at(i));
const unsigned start = attr["start"].to_int(0);
const unsigned end = attr["end"].to_int(text.size());
// Note that the value corresponding to the attribute is not the i-th item
// but rather the data_index-th one. Using data_index so that we can get rid of excess commas
// that is, things like 'attr_data=value1,,,valu2,value3'
if (styles.at(i) == "color"||styles.at(i) == "fgcolor"||styles.at(i) == "foreground") {
text_renderer.add_attribute_fg_color(attr_start(variables), attr_stop(variables), font::string_to_color(data.at(data_index)));
data_index++;
} else if (styles.at(i) == "bgcolor"||styles.at(i) == "background") {
text_renderer.set_highlight_area(attr_start(variables), attr_stop(variables), font::string_to_color(data.at(data_index)));
data_index++;
} else if (styles.at(i) == "font_size"||styles.at(i) == "size") {
text_renderer.add_attribute_size(attr_start(variables), attr_stop(variables), std::stoi(data.at(data_index)));
data_index++;
} else if (styles.at(i) == "font_family"||styles.at(i) == "face") {
text_renderer.add_attribute_font_family(attr_start(variables), attr_stop(variables), data.at(data_index));
data_index++;
} else if (styles.at(i) == "weight") {
text_renderer.add_attribute_weight(attr_start(variables), attr_stop(variables), decode_text_weight(data.at(data_index)));
data_index++;
} else if (styles.at(i) == "style") {
text_renderer.add_attribute_style(attr_start(variables), attr_stop(variables), decode_text_style(data.at(data_index)));
data_index++;
if (attr["name"] == "color" || attr["name"] == "fgcolor" || attr["name"] == "foreground") {
text_renderer.add_attribute_fg_color(start, end, attr["value"].empty() ? font::NORMAL_COLOR : font::string_to_color(attr["value"]));
} else if (attr["name"] == "bgcolor"||attr["name"] == "background") {
text_renderer.add_attribute_bg_color(start, end, attr["value"].empty() ? font::GOOD_COLOR : font::string_to_color(attr["value"]));
} else if (attr["name"] == "font_size"||attr["name"] == "size") {
text_renderer.add_attribute_size(start, end, attr["value"].to_int(font::SIZE_NORMAL));
} else if (attr["name"] == "font_family"||attr["name"] == "face") {
text_renderer.add_attribute_font_family(start, end, attr["value"].str(font::get_font_families(font::FONT_SANS_SERIF)));
} else if (attr["name"] == "weight") {
text_renderer.add_attribute_weight(start, end, decode_text_weight(attr["value"]));
} else if (attr["name"] == "style") {
text_renderer.add_attribute_style(start, end, decode_text_style(attr["value"]));
} else if (attr["name"] == "bold" || attr["name"] == "b") {
text_renderer.add_attribute_weight(start, end, PANGO_WEIGHT_BOLD);
} else if (attr["name"] == "italic" || attr["name"] == "i") {
text_renderer.add_attribute_style(start, end, PANGO_STYLE_ITALIC);
} else if (attr["name"] == "underline" || attr["name"] == "u") {
text_renderer.add_attribute_underline(start, end, PANGO_UNDERLINE_SINGLE);
} else {
font::pango_text::FONT_STYLE attr_style = decode_font_style(styles.at(i));
switch(attr_style)
{
case font::pango_text::STYLE_BOLD:
text_renderer.add_attribute_weight(attr_start(variables), attr_stop(variables), PANGO_WEIGHT_BOLD);
break;
case font::pango_text::STYLE_ITALIC:
text_renderer.add_attribute_style(attr_start(variables), attr_stop(variables), PANGO_STYLE_ITALIC);
break;
case font::pango_text::STYLE_UNDERLINE:
text_renderer.add_attribute_underline(attr_start(variables), attr_stop(variables), PANGO_UNDERLINE_SINGLE);
break;
default:
// Unsupported formatting or normal text
text_renderer.add_attribute_weight(attr_start(variables), attr_stop(variables), PANGO_WEIGHT_NORMAL);
text_renderer.add_attribute_style(attr_start(variables), attr_stop(variables), PANGO_STYLE_NORMAL);
}
// Unsupported formatting or normal text
text_renderer.add_attribute_weight(start, end, PANGO_WEIGHT_NORMAL);
text_renderer.add_attribute_style(start, end, PANGO_STYLE_NORMAL);
}
}

View file

@ -246,6 +246,9 @@ public:
void draw(wfl::map_formula_callable& variables) override;
private:
/** the source config */
config cfg_;
/** The text font family. */
font::family_class font_family_;

View file

@ -108,49 +108,24 @@ point rich_label::get_image_size(config img_cfg) {
return point(variables.query_value("image_width").as_int(), variables.query_value("image_height").as_int());
}
void rich_label::add_text_with_attribute(config& curr_item, std::string text, std::string attr_name, std::string extra_data) {
size_t start = curr_item["text"].str().size();
curr_item["text"] = curr_item["text"].str() + text;
if (!attr_name.empty()) {
append_if_not_empty(&curr_item["attr_name"], ",");
curr_item["attr_name"] = curr_item["attr_name"].str() + attr_name;
append_if_not_empty(&curr_item["attr_start"], ",");
curr_item["attr_start"] = curr_item["attr_start"].str() + std::to_string(start);
append_if_not_empty(&curr_item["attr_end"], ",");
curr_item["attr_end"] = curr_item["attr_end"].str() + std::to_string(curr_item["text"].str().size());
if (!extra_data.empty()) {
append_if_not_empty(&curr_item["attr_data"], ",");
curr_item["attr_data"] = curr_item["attr_data"].str() + extra_data;
}
}
}
void rich_label::add_text_with_attributes(config& curr_item, std::string text, std::vector<std::string> attr_names, std::vector<std::string> extra_data) {
size_t start = curr_item["text"].str().size();
curr_item["text"] = curr_item["text"].str() + text;
size_t end = curr_item["text"].str().size();
if (!attr_names.empty()) {
append_if_not_empty(&curr_item["attr_name"], ",");
curr_item["attr_name"] = curr_item["attr_name"].str() + utils::join(attr_names);
for (size_t i = 0; i < attr_names.size(); i++) {
append_if_not_empty(&curr_item["attr_start"], ",");
curr_item["attr_start"] = curr_item["attr_start"].str() + std::to_string(start);
append_if_not_empty(&curr_item["attr_end"], ",");
curr_item["attr_end"] = curr_item["attr_end"].str() + std::to_string(curr_item["text"].str().size());
}
config& attr_cfg = curr_item.add_child("attribute");
attr_cfg["name"] = attr_names[i];
attr_cfg["start"] = start;
attr_cfg["end"] = end;
if (!extra_data.empty()) {
append_if_not_empty(&curr_item["attr_data"], ",");
curr_item["attr_data"] = curr_item["attr_data"].str() + utils::join(extra_data);
if (!extra_data.empty()) {
attr_cfg["value"] = extra_data[i];
}
}
}
}
void rich_label::add_image(config& curr_item, std::string name, std::string align, bool has_prev_image, bool is_prev_float, bool floating, point& img_size, point& float_size) {
@ -544,7 +519,6 @@ config rich_label::get_parsed_text(const config& parsed_text)
DBG_GUI_RL << "ref: dst=" << child["dst"];
} else if(tag.key == "bold" || tag.key == "b") {
add_text_with_attribute(*curr_item, line, "bold");
is_image = false;
@ -566,11 +540,6 @@ config rich_label::get_parsed_text(const config& parsed_text)
} else if(tag.key == "header" || tag.key == "h") {
append_if_not_empty(&((*curr_item)["attr_name"]), ",");
append_if_not_empty(&((*curr_item)["attr_start"]), ",");
append_if_not_empty(&((*curr_item)["attr_end"]), ",");
append_if_not_empty(&((*curr_item)["attr_data"]), ",");
std::vector<std::string> attrs = {"face", "color", "size"};
std::vector<std::string> attr_data;
attr_data.push_back("serif");

View file

@ -209,10 +209,12 @@ private:
/** Height of all previous blocks, combined */
unsigned prev_blk_height_;
/** template for canvas text config */
/** Create template for text config that can be shown in canvas */
void default_text_config(config* txt_ptr, t_string text = "");
void add_text_with_attribute(config& curr_item, std::string text, std::string attr_name = "", std::string extra_data = "");
void add_text_with_attribute(config& curr_item, std::string text, std::string attr_name = "", std::string extra_data = "") {
add_text_with_attributes(curr_item, text, {attr_name}, {extra_data});
}
void add_text_with_attributes(config& curr_item, std::string text, std::vector<std::string> attr_names, std::vector<std::string> extra_data);
void add_image(config& curr_item, std::string name, std::string align, bool has_prev_image, bool is_prev_float, bool floating, point& img_size, point& float_size);
void add_link(config& curr_item, std::string name, std::string dest, int img_width);

View file

@ -121,11 +121,11 @@ public:
/**
* Wrapper function, sets the area between column start and end
* offset to be highlighted in a specific color.
* See @ref font::pango_text::set_highlight_area.
* See @ref font::pango_text::add_attribute_bg_color.
*/
void set_highlight_area(const unsigned start_offset, const unsigned end_offset, const color_t& color)
{
text_.set_highlight_area(start_offset, end_offset, color);
text_.add_attribute_bg_color(start_offset, end_offset, color);
}
/***** ***** ***** setters / getters for members ***** ****** *****/