text renderer: remove caching and get_byte_offset, add get_cursor_pos_from_index

This commit is contained in:
Subhraman Sarkar 2024-08-14 10:21:14 +05:30
parent b874b8c6d4
commit cf5cc8ec3f
2 changed files with 56 additions and 138 deletions

View file

@ -87,7 +87,6 @@ pango_text::pango_text()
, attribute_start_offset_(0)
, attribute_end_offset_(0)
, highlight_color_()
, attrib_hash_(0)
, pixel_scale_(1)
, surface_buffer_()
{
@ -118,22 +117,9 @@ texture pango_text::render_texture(const SDL_Rect& viewport)
texture pango_text::render_and_get_texture()
{
// Update our settings then hash them.
update_pixel_scale(); // TODO: this should be in recalculate()
recalculate();
const std::size_t hash = std::hash<pango_text>{}(*this);
// If we already have the appropriate texture in-cache, use it.
if(const auto iter = rendered_cache.find(hash); iter != rendered_cache.end()) {
return with_draw_scale(iter->second);
}
if(surface text_surf = create_surface(); text_surf) {
const auto& [new_iter, added] = rendered_cache.try_emplace(hash, std::move(text_surf));
return with_draw_scale(new_iter->second);
}
// Render output was null for some reason. Don't cache.
return {};
return with_draw_scale(texture(create_surface()));
}
surface pango_text::render_surface(const SDL_Rect& viewport)
@ -196,29 +182,6 @@ unsigned pango_text::insert_text(const unsigned offset, const std::string& text)
return len;
}
int pango_text::get_byte_offset(const unsigned column) const
{
// First we need to determine the byte offset
std::unique_ptr<PangoLayoutIter, std::function<void(PangoLayoutIter*)>> itor(
pango_layout_get_iter(layout_.get()), pango_layout_iter_free);
// Go the wanted column.
for(std::size_t i = 0; i < column; ++i) {
if(!pango_layout_iter_next_char(itor.get())) {
// It seems that the documentation is wrong and causes and off by
// one error... the result should be false if already at the end of
// the data when started.
if(i + 1 == column) {
break;
}
}
}
// Get the byte offset
const int offset = pango_layout_iter_get_index(itor.get());
return offset;
}
point pango_text::get_cursor_position(const unsigned column, const unsigned line) const
{
this->recalculate();
@ -256,6 +219,11 @@ point pango_text::get_cursor_position(const unsigned column, const unsigned line
// Get the byte offset
const int offset = pango_layout_iter_get_index(itor.get());
return get_cursor_pos_from_index(offset);
}
point pango_text::get_cursor_pos_from_index(const unsigned offset) const
{
// Convert the byte offset in a position.
PangoRectangle rect;
pango_layout_get_cursor_pos(layout_.get(), offset, &rect, nullptr);
@ -362,11 +330,6 @@ void pango_text::add_attribute_size(const unsigned start_offset, const unsigned
DBG_GUI_D << "attribute: size";
DBG_GUI_D << "attribute start: " << start_offset << " end : " << end_offset;
// Update hash
boost::hash_combine(attrib_hash_, attribute_start_offset_);
boost::hash_combine(attrib_hash_, attribute_end_offset_);
boost::hash_combine(attrib_hash_, size);
// Insert all attributes
pango_attr_list_insert(global_attribute_list_, attr);
}
@ -385,11 +348,6 @@ void pango_text::add_attribute_weight(const unsigned start_offset, const unsigne
DBG_GUI_D << "attribute: weight";
DBG_GUI_D << "attribute start: " << start_offset << " end : " << end_offset;
// Update hash
boost::hash_combine(attrib_hash_, attribute_start_offset_);
boost::hash_combine(attrib_hash_, attribute_end_offset_);
boost::hash_combine(attrib_hash_, weight);
// Insert all attributes
pango_attr_list_insert(global_attribute_list_, attr);
}
@ -409,10 +367,6 @@ void pango_text::add_attribute_style(const unsigned start_offset, const unsigned
DBG_GUI_D << "attribute: style";
DBG_GUI_D << "attribute start: " << attribute_start_offset_ << " end : " << attribute_end_offset_;
// Update hash
boost::hash_combine(attrib_hash_, attribute_start_offset_);
boost::hash_combine(attrib_hash_, attribute_end_offset_);
// Insert all attributes
pango_attr_list_insert(global_attribute_list_, attr);
}
@ -431,11 +385,6 @@ void pango_text::add_attribute_underline(const unsigned start_offset, const unsi
DBG_GUI_D << "attribute: underline";
DBG_GUI_D << "attribute start: " << start_offset << " end : " << end_offset;
// Update hash
boost::hash_combine(attrib_hash_, attribute_start_offset_);
boost::hash_combine(attrib_hash_, attribute_end_offset_);
boost::hash_combine(attrib_hash_, underline);
// Insert all attributes
pango_attr_list_insert(global_attribute_list_, attr);
}
@ -460,11 +409,6 @@ void pango_text::add_attribute_fg_color(const unsigned start_offset, const unsig
DBG_GUI_D << "attribute start: " << attribute_start_offset_ << " end : " << attribute_end_offset_;
DBG_GUI_D << "color: " << col_r << "," << col_g << "," << col_b;
// Update hash
boost::hash_combine(attrib_hash_, attribute_start_offset_);
boost::hash_combine(attrib_hash_, attribute_end_offset_);
boost::hash_combine(attrib_hash_, color.to_rgba_bytes());
// Insert all attributes
pango_attr_list_insert(global_attribute_list_, attr);
}
@ -484,11 +428,6 @@ void pango_text::add_attribute_font_family(const unsigned start_offset, const un
DBG_GUI_D << "attribute start: " << start_offset << " end : " << end_offset;
DBG_GUI_D << "font family: " << family;
// Update hash
boost::hash_combine(attrib_hash_, attribute_start_offset_);
boost::hash_combine(attrib_hash_, attribute_end_offset_);
boost::hash_combine(attrib_hash_, family);
// Insert all attributes
pango_attr_list_insert(global_attribute_list_, attr);
}
@ -499,27 +438,20 @@ void pango_text::set_highlight_area(const unsigned start_offset, const unsigned
attribute_end_offset_ = end_offset;
highlight_color_ = color;
if (attribute_start_offset_ != attribute_end_offset_) {
// Highlight
int col_r = highlight_color_.r / 255.0 * 65535.0;
int col_g = highlight_color_.g / 255.0 * 65535.0;
int col_b = highlight_color_.b / 255.0 * 65535.0;
// Highlight
int col_r = highlight_color_.r / 255.0 * 65535.0;
int col_g = highlight_color_.g / 255.0 * 65535.0;
int col_b = highlight_color_.b / 255.0 * 65535.0;
DBG_GUI_D << "highlight start: " << attribute_start_offset_ << "end : " << attribute_end_offset_;
DBG_GUI_D << "highlight color: " << col_r << "," << col_g << "," << col_b;
DBG_GUI_D << "highlight start: " << attribute_start_offset_ << "end : " << attribute_end_offset_;
DBG_GUI_D << "highlight color: " << col_r << "," << col_g << "," << col_b;
PangoAttribute *attr = pango_attr_background_new(col_r, col_g, col_b);
attr->start_index = attribute_start_offset_;
attr->end_index = attribute_end_offset_;
PangoAttribute *attr = pango_attr_background_new(col_r, col_g, col_b);
attr->start_index = attribute_start_offset_;
attr->end_index = attribute_end_offset_;
// Update hash
boost::hash_combine(attrib_hash_, attribute_start_offset_);
boost::hash_combine(attrib_hash_, attribute_end_offset_);
boost::hash_combine(attrib_hash_, highlight_color_.to_rgba_bytes());
// Insert all attributes
pango_attr_list_insert(global_attribute_list_, attr);
}
// Insert all attributes
pango_attr_list_change(global_attribute_list_, attr);
}
void pango_text::clear_attribute_list() {
@ -1171,6 +1103,18 @@ std::vector<std::string> pango_text::get_lines() const
return res;
}
PangoLayoutLine* pango_text::get_line(int index)
{
return pango_layout_get_line_readonly(layout_.get(), index);
}
int pango_text::get_line_num_from_offset(const unsigned offset)
{
int line_num = 0;
pango_layout_index_to_line_x(layout_.get(), offset, 0, &line_num, nullptr);
return line_num;
}
pango_text& get_text_renderer()
{
static pango_text text_renderer;
@ -1188,30 +1132,3 @@ int get_max_height(unsigned size, font::family_class fclass, pango_text::FONT_ST
}
} // namespace font
namespace std
{
std::size_t hash<font::pango_text>::operator()(const font::pango_text& t) const
{
std::size_t hash = 0;
boost::hash_combine(hash, t.text_);
boost::hash_combine(hash, t.font_class_);
boost::hash_combine(hash, t.font_size_);
boost::hash_combine(hash, t.font_style_);
boost::hash_combine(hash, t.foreground_color_.to_rgba_bytes());
boost::hash_combine(hash, t.rect_.width);
boost::hash_combine(hash, t.rect_.height);
boost::hash_combine(hash, t.maximum_width_);
boost::hash_combine(hash, t.maximum_height_);
boost::hash_combine(hash, t.alignment_);
boost::hash_combine(hash, t.ellipse_mode_);
boost::hash_combine(hash, t.add_outline_);
// Hash for the global attribute list
boost::hash_combine(hash, t.attrib_hash_);
return hash;
}
} // namespace std

View file

@ -161,8 +161,8 @@ public:
/**
* Gets the location for the cursor, in drawing coordinates.
*
* @param column The column offset of the cursor.
* @param line The line offset of the cursor.
* @param column The column character index of the cursor.
* @param line The line character index of the cursor.
*
* @returns The position of the top of the cursor. It the
* requested location is out of range 0,0 is
@ -172,16 +172,15 @@ public:
const unsigned column, const unsigned line = 0) const;
/**
* Gets the correct number of columns to move the cursor
* from Pango. Needed in case the text contains multibyte
* characters. Return value == column if the text has no
* multibyte characters.
* Gets the location for the cursor, in drawing coordinates.
*
* @param column The column offset of the cursor.
* @param offset The column byte index of the cursor.
*
* @returns Corrected column offset.
* @returns The position of the top of the cursor. It the
* requested location is out of range 0,0 is
* returned.
*/
int get_byte_offset(const unsigned column) const;
point get_cursor_pos_from_index(const unsigned offset) const;
/**
* Get maximum length.
@ -235,6 +234,25 @@ public:
*/
std::vector<std::string> get_lines() const;
/**
* Get a specific line from the pango layout
*
* @param index the line number of the line to retrieve
*
* @returns the PangoLayoutLine* corresponding to line number index
*/
PangoLayoutLine* get_line(int index);
/**
* Given a byte index, find out at which line the corresponding character
* is located.
*
* @param offset the byte index
*
* @returns the line number corresponding to the given index
*/
int get_line_num_from_offset(const unsigned offset);
/**
* Get number of lines in the text.
*
@ -424,9 +442,6 @@ private:
*/
PangoAttrList* global_attribute_list_;
/** Hash for the global_attribute_list_ */
std::size_t attrib_hash_;
/** The pixel scale, used to render high-DPI text. */
int pixel_scale_;
@ -436,9 +451,6 @@ private:
/** Calculates surface size. */
PangoRectangle calculate_size(PangoLayout& layout) const;
/** Allow specialization of std::hash for pango_text. */
friend struct std::hash<pango_text>;
/**
* Equivalent to create_surface(viewport), where the viewport's top-left is
* at (0,0) and the area is large enough to contain the full text.
@ -545,14 +557,3 @@ int get_max_height(unsigned size, font::family_class fclass = font::FONT_SANS_SE
constexpr float get_line_spacing_factor() { return 1.3f; };
} // namespace font
// Specialize std::hash for pango_text
namespace std
{
template<>
struct hash<font::pango_text>
{
std::size_t operator()(const font::pango_text&) const;
};
} // namespace std