The Battle for Wesnoth  1.19.9+dev
text_box_base.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2025
3  by Mark de Wever <koraq@xs4all.nl>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #pragma once
17 
18 //#include "gui/core/event/dispatcher.hpp"
20 #include "font/text.hpp" // We want the file in src/
21 
22 #include <string>
23 
24 #include <functional>
25 
26 namespace gui2
27 {
28 
29 /**
30  * Abstract base class for text items.
31  *
32  * All other text classes should inherit from this base class.
33  *
34  * The NOTIFY_MODIFIED event is send when the text is modified.
35  *
36  * @todo Validate whether the NOTIFY_MODIFIED is always fired properly. The
37  * current implementation is added for some quick testing so some cases might
38  * be forgotten.
39  *
40  * Common signal handlers:
41  * - connect_signal_pre_key_press
42  */
44 {
45 
46 public:
47  text_box_base(const implementation::builder_styled_widget& builder, const std::string& control_type);
48 
50 
51  /** See @ref styled_widget::set_active. */
52  virtual void set_active(const bool active) override;
53 
54  /** See @ref styled_widget::get_active. */
55  virtual bool get_active() const override;
56 
57  /** See @ref styled_widget::get_state. */
58  virtual unsigned get_state() const override;
59 
60  /***** ***** ***** ***** expose some functions ***** ***** ***** *****/
61 
62  void set_maximum_length(const std::size_t maximum_length);
63 
64  /**
65  * Wrapper function, returns length of the text in pango column offsets.
66  * See @ref font::pango_text::get_length.
67  */
68  std::size_t get_length() const
69  {
70  return text_.get_length();
71  }
72 
73  /**
74  * Wrapper function, returns a vector with the lines.
75  * See @ref font::pango_text::get_lines.
76  */
77  std::vector<std::string> get_lines()
78  {
79  return text_.get_lines();
80  }
81 
82  /**
83  * Wrapper function, returns the line corresponding
84  * to index.
85  * See @ref font::pango_text::get_line.
86  */
87  PangoLayoutLine* get_line(int index)
88  {
89  return text_.get_line(index);
90  }
91 
92  /**
93  * Wrapper function, return the line number
94  * given the byte index.
95  * See @ref font::pango_text::get_line_num_from_offset.
96  */
97  int get_line_number(const unsigned offset)
98  {
99  return text_.get_line_num_from_offset(offset);
100  }
101 
102  /**
103  * Wrapper function, return the cursor position
104  * given the byte index.
105  * See @ref font::pango_text::get_cursor_pos_from_index.
106  */
107  point get_cursor_pos_from_index(const unsigned offset) const
108  {
109  return text_.get_cursor_pos_from_index(offset);
110  }
111 
112  /**
113  * Wrapper function, return number of lines.
114  * See @ref font::pango_text::get_lines_count.
115  */
116  unsigned get_lines_count() const
117  {
118  return text_.get_lines_count();
119  }
120 
121  /**
122  * Wrapper function, sets the area between column start and end
123  * offset to be highlighted in a specific color.
124  * See @ref font::add_attribute_bg_color.
125  */
126  void set_highlight_area(const unsigned start_offset, const unsigned end_offset, const color_t& color);
127 
128  /***** ***** ***** setters / getters for members ***** ****** *****/
129 
130  /**
131  * The set_value is virtual for the @ref password_box class.
132  *
133  * That class overrides the set_value function to replace it with asterisk.
134  * There might be more generic way to do it when more classes are needed.
135  */
136  virtual void set_value(const std::string& text);
137  std::string get_value() const
138  {
139  return text_.text();
140  }
141 
142  const std::string& text() const
143  {
144  return text_.text();
145  }
146 
147  std::string plain_text()
148  {
149  char* plain_text = nullptr;
150  pango_parse_markup(text().c_str(), text().size(), 0, nullptr, &plain_text, nullptr, nullptr);
151  return plain_text ? std::string(plain_text) : std::string();
152  }
153 
154  /**
155  * Registers a NOTIFY_MODIFIED handler.
156  *
157  * For convenience, the handler is invoked with a text_box_base reference
158  * as its first (and only) argument, rather than the usual widget reference.
159  *
160  * @todo Should we pass the other callback parameters to the handler?
161  */
162  template<typename Func>
163  void on_modified(const Func& f)
164  {
165  connect_signal<event::NOTIFY_MODIFIED>(
166  [f](widget& w, auto&&...) { f(dynamic_cast<text_box_base&>(w)); });
167  }
168 
169  /**
170  * Sets or clears the text selection.
171  *
172  * Setting the selection range will re-position the cursor depending on the
173  * selection direction, specified by the length's sign. Selecting beyond the
174  * start or end of the text is safe; the final selection will be limited
175  * accordingly.
176  *
177  * @note The range extents are measured in Unicode characters, not bytes.
178  * Using byte offsets may produce unexpected results depending on the
179  * text contents.
180  *
181  * @param start Start offset, in characters.
182  * @param length Selection length, in characters. If zero, the
183  * current selection is canceled. If negative, the
184  * selection extends towards the start of the text
185  * and the cursor will be re-positioned in that
186  * direction as well; otherwise the selection and
187  * cursor extend towards the end.
188  */
189  void set_selection(std::size_t start, int length);
190 
191  /**
192  * Set or unset whether text can be edited or not
193  * Text can only be copied and scrolled through when editable is false.
194  */
195  void set_editable(bool editable)
196  {
197  editable_ = editable;
198  update_canvas();
199  }
200 
201  /**
202  * Check whether text can be edited or not
203  */
204  bool is_editable() const
205  {
206  return editable_;
207  }
208 
209 protected:
210  /** Get length of composition text by IME **/
211  size_t get_composition_length() const;
212 
213  /**
214  * Moves the cursor to the end of the line.
215  *
216  * @param select Select the text from the original cursor
217  * position till the end of the line?
218  */
219  virtual void goto_end_of_line(const bool select = false) = 0;
220 
221  /**
222  * Moves the cursor to the end of all text.
223  *
224  * For a single line text this is the same as goto_end_of_line().
225  *
226  * @param select Select the text from the original cursor
227  * position till the end of the data?
228  */
229  virtual void goto_end_of_data(const bool select = false)
230  {
231  set_cursor(text_.get_length(), select);
232  }
233 
234  /**
235  * Moves the cursor to the beginning of the line
236  *
237  * @param select Select the text from the original cursor
238  * position till the beginning of the line?
239  */
240  virtual void goto_start_of_line(const bool select = false) = 0;
241 
242  /**
243  * Moves the cursor to the beginning of the data.
244  *
245  * @param select Select the text from the original cursor
246  * position till the beginning of the data?
247  */
248  virtual void goto_start_of_data(const bool select = false)
249  {
250  set_cursor(0, select);
251  }
252 
253  /** Selects all text. */
254  void select_all()
255  {
256  selection_start_ = 0;
257  goto_end_of_data(true);
258  }
259 
260  /**
261  * Moves the cursor at the wanted position.
262  *
263  * @param offset The wanted new cursor position.
264  * @param select Select the text from the original cursor
265  * position till the new position?
266  */
267  virtual void set_cursor(const std::size_t offset, const bool select);
268 
269  /**
270  * Inserts a character at the cursor.
271  *
272  * This function is preferred over set_text since it's optimized for
273  * updating the internal bookkeeping.
274  *
275  * @param unicode The unicode value of the character to insert.
276  */
277  virtual void insert_char(const std::string& unicode);
278 
279  /**
280  * Deletes the character.
281  *
282  * @param before_cursor If true it deletes the character before the
283  * cursor (backspace) else the character after
284  * the cursor (delete).
285  */
286  virtual void delete_char(const bool before_cursor) = 0;
287 
288  /** Deletes the current selection. */
289  virtual void delete_selection() = 0;
290 
291  /** Copies the current selection. */
292  virtual void copy_selection();
293 
294  /** Pastes the current selection. */
295  virtual void paste_selection();
296 
297  /***** ***** ***** ***** expose some functions ***** ***** ***** *****/
298 
299  point get_cursor_position(const unsigned column,
300  const unsigned line = 0) const
301  {
302  return text_.get_cursor_position(column, line);
303  }
304 
305  point get_column_line(const point& position) const
306  {
307  return text_.get_column_line(position);
308  }
309 
311  {
312  return font_family_;
313  }
314 
316  {
317  font_family_ = fclass;
319  }
320 
321  void set_font_size(const unsigned font_size)
322  {
323  text_.set_font_size(font_size);
324  }
325 
327  {
328  text_.set_font_style(font_style);
329  }
330 
331  void set_maximum_width(const int width)
332  {
333  text_.set_maximum_width(width);
334  }
335 
336  void set_maximum_height(const int height, const bool multiline)
337  {
338  text_.set_maximum_height(height, multiline);
339  }
340 
341  void set_ellipse_mode(const PangoEllipsizeMode ellipse_mode)
342  {
343  text_.set_ellipse_mode(ellipse_mode);
344  }
345 
346  /***** ***** ***** setters / getters for members ***** ****** *****/
347 
348  std::size_t get_selection_start() const
349  {
350  return selection_start_;
351  }
352  void set_selection_start(const std::size_t selection_start);
353 
354  std::size_t get_selection_length() const
355  {
356  return selection_length_;
357  }
358  void set_selection_length(const int selection_length);
359 
360  std::size_t get_composition_start() const
361  {
362  return ime_start_point_;
363  }
364 
365 public:
366  bool is_composing() const
367  {
368  return ime_composing_;
369  }
370 
371  void interrupt_composition();
372 
373  /** Note the order of the states must be the same as defined in
374  * settings.hpp. */
375  enum state_t {
380  };
381 
382 private:
383  void set_state(const state_t state);
384 
385  virtual void toggle_cursor_timer(bool enable);
386 
387  /** Implements blinking cursor functionality. */
388  virtual void cursor_timer_callback();
389 
390  virtual void reset_cursor_state();
391 
392  void update_mouse_cursor(bool enable);
393 
394  /**
395  * Current state of the widget.
396  *
397  * The state of the widget determines what to render and how the widget
398  * reacts to certain 'events'.
399  */
401 
402  /** The text entered in the widget. */
404 
405  /** font family */
407 
408  /** Cached version of the text without any pending IME modifications. */
409  std::string text_cached_;
410 
411  /** Start of the selected text. */
412  std::size_t selection_start_;
413 
414  /**
415  * Length of the selected text.
416  *
417  * * positive selection_len_ means selection to the right.
418  * * negative selection_len_ means selection to the left.
419  * * selection_len_ == 0 means no selection.
420  */
422 
423  /** If this text_box_base is editable */
424  bool editable_;
425 
426  // Values to support input method editors
429 
430  std::size_t cursor_timer_;
431 
432  unsigned short cursor_alpha_;
433  std::chrono::milliseconds cursor_blink_rate_;
434 
435  /****** handling of special keys first the pure virtuals *****/
436 
437  /**
438  * Every key can have several behaviors.
439  *
440  * Unmodified No modifier is pressed.
441  * Control The control key is pressed.
442  * Shift The shift key is pressed.
443  * Alt The alt key is pressed.
444  *
445  * If modifiers together do something else as the sum of the modifiers
446  * it's listed separately eg.
447  *
448  * Control Moves 10 steps at the time.
449  * Shift Selects the text.
450  * Control + Shift Inserts 42 in the text.
451  *
452  * There are some predefined actions for results.
453  * Unhandled The key/modifier is ignored and also reported
454  * unhandled.
455  * Ignored The key/modifier is ignored and it's
456  * _expected_ the inherited classes do the same.
457  * Implementation defined The key/modifier is ignored and it's expected
458  * the inherited classes will define some meaning
459  * to it.
460  */
461 
462  /**
463  * Up arrow key pressed.
464  *
465  * The behavior is implementation defined.
466  */
467  virtual void handle_key_up_arrow(SDL_Keymod modifier, bool& handled) = 0;
468 
469  /**
470  * Down arrow key pressed.
471  *
472  * The behavior is implementation defined.
473  */
474  virtual void handle_key_down_arrow(SDL_Keymod modifier, bool& handled) = 0;
475 
476  /**
477  * Clears the current line.
478  *
479  * Unmodified Clears the current line.
480  * Control Ignored.
481  * Shift Ignored.
482  * Alt Ignored.
483  */
484  virtual void handle_key_clear_line(SDL_Keymod modifier, bool& handled) = 0;
485 protected:
486  /**
487  * Left arrow key pressed.
488  *
489  * Unmodified Moves the cursor a character to the left.
490  * Control Like unmodified but a word instead of a letter
491  * at the time.
492  * Shift Selects the text while moving.
493  * Alt Ignored.
494  */
495  virtual void handle_key_left_arrow(SDL_Keymod modifier, bool& handled);
496 
497  /**
498  * Right arrow key pressed.
499  *
500  * Unmodified Moves the cursor a character to the right.
501  * Control Like unmodified but a word instead of a letter
502  * at the time.
503  * Shift Selects the text while moving.
504  * Alt Ignored.
505  */
506  virtual void handle_key_right_arrow(SDL_Keymod modifier, bool& handled);
507 
508 private:
509  /**
510  * Home key pressed.
511  *
512  * Unmodified Moves the cursor a to the beginning of the
513  * line.
514  * Control Like unmodified but to the beginning of the
515  * data.
516  * Shift Selects the text while moving.
517  * Alt Ignored.
518  */
519  virtual void handle_key_home(SDL_Keymod modifier, bool& handled);
520 
521  /**
522  * End key pressed.
523  *
524  * Unmodified Moves the cursor a to the end of the line.
525  * Control Like unmodified but to the end of the data.
526  * Shift Selects the text while moving.
527  * Alt Ignored.
528  */
529  virtual void handle_key_end(SDL_Keymod modifier, bool& handled);
530 
531  /**
532  * Backspace key pressed.
533  *
534  * Unmodified Deletes the character before the cursor,
535  * ignored if at the beginning of the data.
536  * Control Ignored.
537  * Shift Ignored.
538  * Alt Ignored.
539  */
540  virtual void handle_key_backspace(SDL_Keymod modifier, bool& handled);
541 
542  /**
543  * Delete key pressed.
544  *
545  * Unmodified If there is a selection that's deleted.
546  * Else if not at the end of the data the
547  * character after the cursor is deleted.
548  * Else the key is ignored.
549  * ignored if at the beginning of the data.
550  * Control Ignored.
551  * Shift Ignored.
552  * Alt Ignored.
553  */
554  virtual void handle_key_delete(SDL_Keymod modifier, bool& handled);
555 
556  /**
557  * Page up key.
558  *
559  * Unmodified Unhandled.
560  * Control Ignored.
561  * Shift Ignored.
562  * Alt Ignored.
563  */
564  virtual void handle_key_page_up(SDL_Keymod /*modifier*/, bool& /*handled*/)
565  {
566  }
567 
568  /**
569  * Page down key.
570  *
571  * Unmodified Unhandled.
572  * Control Ignored.
573  * Shift Ignored.
574  * Alt Ignored.
575  */
576  virtual void handle_key_page_down(SDL_Keymod /*modifier*/, bool& /*handled*/)
577  {
578  }
579 
580  /**
581  * Tab key.
582  *
583  * Unmodified Implementation defined.
584  * Control Implementation defined.
585  * Shift Implementation defined.
586  * Alt Implementation defined.
587  */
588  virtual void handle_key_tab(SDL_Keymod /*modifier*/, bool& /*handled*/)
589  {
590  }
591 
592  /**
593  * Enter key.
594  *
595  * Unmodified Handled by Window.
596  * Control Implementation defined.
597  * Shift Implementation defined.
598  * Alt Implementation defined.
599  */
600  virtual void handle_key_enter(SDL_Keymod /*modifier*/, bool& /*handled*/)
601  {
602  }
603 
604 protected:
605  virtual void handle_commit(bool& handled,
606  const std::string& unicode);
607  virtual void handle_editing(bool& handled,
608  const std::string& unicode,
609  int32_t start,
610  int32_t length);
611 
612 private:
613  /***** ***** ***** signal handlers ***** ****** *****/
614 
616  bool& handled);
617 
619  bool& handled,
620  const SDL_Keycode key,
621  SDL_Keymod modifier);
622 
624  bool& handled,
625  const std::string& unicode,
626  int32_t start,
627  int32_t len);
628 
631 
632  void signal_handler_mouse_enter(const event::ui_event event, bool& handled);
633  void signal_handler_mouse_leave(const event::ui_event event, bool& handled);
634 };
635 
636 } // namespace gui2
Text class.
Definition: text.hpp:78
unsigned get_lines_count() const
Get number of lines in the text.
Definition: text.hpp:264
pango_text & set_font_style(const FONT_STYLE font_style)
Definition: text.cpp:374
std::size_t get_length() const
Gets the length of the text in bytes.
Definition: text.hpp:272
int get_line_num_from_offset(const unsigned offset)
Given a byte index, find out at which line the corresponding character is located.
Definition: text.cpp:951
point get_column_line(const point &position) const
Gets the column of line of the character at the position.
Definition: text.cpp:259
PangoLayoutLine * get_line(int index)
Get a specific line from the pango layout.
Definition: text.cpp:946
pango_text & set_family_class(font::family_class fclass)
Definition: text.cpp:352
std::vector< std::string > get_lines() const
Retrieves a list of strings with contents for each rendered line.
Definition: text.cpp:920
pango_text & set_ellipse_mode(const PangoEllipsizeMode ellipse_mode)
Definition: text.cpp:445
point get_cursor_position(const unsigned column, const unsigned line=0) const
Gets the location for the cursor, in drawing coordinates.
Definition: text.cpp:158
pango_text & set_font_size(unsigned font_size)
Definition: text.cpp:362
point get_cursor_pos_from_index(const unsigned offset) const
Gets the location for the cursor, in drawing coordinates.
Definition: text.cpp:198
pango_text & set_maximum_height(int height, bool multiline)
Definition: text.cpp:420
pango_text & set_maximum_width(int width)
Definition: text.cpp:393
const std::string & text() const
Definition: text.hpp:290
virtual void update_canvas()
Updates the canvas(ses).
Abstract base class for text items.
virtual void handle_key_backspace(SDL_Keymod modifier, bool &handled)
Backspace key pressed.
std::size_t get_length() const
Wrapper function, returns length of the text in pango column offsets.
virtual void handle_commit(bool &handled, const std::string &unicode)
virtual bool get_active() const override
See styled_widget::get_active.
virtual unsigned get_state() const override
See styled_widget::get_state.
void set_font_size(const unsigned font_size)
void update_mouse_cursor(bool enable)
point get_column_line(const point &position) const
virtual void goto_start_of_line(const bool select=false)=0
Moves the cursor to the beginning of the line.
virtual void handle_key_delete(SDL_Keymod modifier, bool &handled)
Delete key pressed.
virtual void insert_char(const std::string &unicode)
Inserts a character at the cursor.
virtual void handle_editing(bool &handled, const std::string &unicode, int32_t start, int32_t length)
SDL_TEXTEDITING handler.
void set_state(const state_t state)
std::chrono::milliseconds cursor_blink_rate_
virtual void copy_selection()
Copies the current selection.
void signal_handler_sdl_text_input(const event::ui_event event, bool &handled, const std::string &unicode, int32_t start, int32_t len)
virtual void handle_key_left_arrow(SDL_Keymod modifier, bool &handled)
Left arrow key pressed.
void on_modified(const Func &f)
Registers a NOTIFY_MODIFIED handler.
virtual void toggle_cursor_timer(bool enable)
point get_cursor_pos_from_index(const unsigned offset) const
Wrapper function, return the cursor position given the byte index.
text_box_base(const implementation::builder_styled_widget &builder, const std::string &control_type)
std::string get_value() const
void set_editable(bool editable)
Set or unset whether text can be edited or not Text can only be copied and scrolled through when edit...
void set_highlight_area(const unsigned start_offset, const unsigned end_offset, const color_t &color)
Wrapper function, sets the area between column start and end offset to be highlighted in a specific c...
state_t state_
Current state of the widget.
virtual void goto_end_of_line(const bool select=false)=0
Moves the cursor to the end of the line.
std::size_t get_composition_start() const
void signal_handler_mouse_leave(const event::ui_event event, bool &handled)
void set_selection(std::size_t start, int length)
Sets or clears the text selection.
std::size_t selection_start_
Start of the selected text.
size_t get_composition_length() const
Get length of composition text by IME.
std::string plain_text()
virtual void handle_key_enter(SDL_Keymod, bool &)
Enter key.
int selection_length_
Length of the selected text.
unsigned short cursor_alpha_
std::size_t cursor_timer_
virtual void handle_key_up_arrow(SDL_Keymod modifier, bool &handled)=0
Every key can have several behaviors.
const std::string & text() const
point get_cursor_position(const unsigned column, const unsigned line=0) const
void set_font_style(const font::pango_text::FONT_STYLE font_style)
unsigned get_lines_count() const
Wrapper function, return number of lines.
void signal_handler_mouse_enter(const event::ui_event event, bool &handled)
virtual void handle_key_tab(SDL_Keymod, bool &)
Tab key.
std::string text_cached_
Cached version of the text without any pending IME modifications.
void set_font_family(font::family_class fclass)
virtual void set_value(const std::string &text)
The set_value is virtual for the password_box class.
virtual void paste_selection()
Pastes the current selection.
state_t
Note the order of the states must be the same as defined in settings.hpp.
font::pango_text text_
The text entered in the widget.
void signal_handler_lose_keyboard_focus(const event::ui_event event)
void signal_handler_sdl_key_down(const event::ui_event event, bool &handled, const SDL_Keycode key, SDL_Keymod modifier)
virtual void handle_key_right_arrow(SDL_Keymod modifier, bool &handled)
Right arrow key pressed.
std::size_t get_selection_length() const
virtual void handle_key_clear_line(SDL_Keymod modifier, bool &handled)=0
Clears the current line.
PangoLayoutLine * get_line(int index)
Wrapper function, returns the line corresponding to index.
void set_maximum_height(const int height, const bool multiline)
font::family_class font_family_
font family
void set_ellipse_mode(const PangoEllipsizeMode ellipse_mode)
font::family_class get_font_family()
void set_selection_start(const std::size_t selection_start)
virtual void set_cursor(const std::size_t offset, const bool select)
Moves the cursor at the wanted position.
std::vector< std::string > get_lines()
Wrapper function, returns a vector with the lines.
void set_maximum_width(const int width)
virtual void handle_key_page_up(SDL_Keymod, bool &)
Page up key.
virtual void handle_key_home(SDL_Keymod modifier, bool &handled)
Home key pressed.
bool is_editable() const
Check whether text can be edited or not.
virtual void handle_key_down_arrow(SDL_Keymod modifier, bool &handled)=0
Down arrow key pressed.
void signal_handler_receive_keyboard_focus(const event::ui_event event)
virtual void goto_end_of_data(const bool select=false)
Moves the cursor to the end of all text.
void signal_handler_middle_button_click(const event::ui_event event, bool &handled)
virtual void handle_key_end(SDL_Keymod modifier, bool &handled)
End key pressed.
virtual void handle_key_page_down(SDL_Keymod, bool &)
Page down key.
std::size_t get_selection_start() const
virtual void set_active(const bool active) override
See styled_widget::set_active.
void set_selection_length(const int selection_length)
bool is_composing() const
bool editable_
If this text_box_base is editable.
virtual void goto_start_of_data(const bool select=false)
Moves the cursor to the beginning of the data.
virtual void cursor_timer_callback()
Implements blinking cursor functionality.
virtual void reset_cursor_state()
void set_maximum_length(const std::size_t maximum_length)
int get_line_number(const unsigned offset)
Wrapper function, return the line number given the byte index.
virtual void delete_selection()=0
Deletes the current selection.
virtual void delete_char(const bool before_cursor)=0
Deletes the character.
void select_all()
Selects all text.
Base class for all widgets.
Definition: widget.hpp:55
int w
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
Definition: draw.cpp:187
EXIT_STATUS start(bool clear_id, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
family_class
Font classes for get_font_families().
ui_event
The event sent to the dispatcher.
Definition: handler.hpp:115
Generic file dialog.
std::size_t size(std::string_view str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:85
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:70
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:59
Holds a 2D point.
Definition: point.hpp:25
#define f