Line data Source code
1 : /* Types for drawing 2d "text art".
2 : Copyright (C) 2023-2026 Free Software Foundation, Inc.
3 : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it
8 : under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3, or (at your option)
10 : any later version.
11 :
12 : GCC is distributed in the hope that it will be useful, but
13 : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #ifndef GCC_TEXT_ART_TYPES_H
22 : #define GCC_TEXT_ART_TYPES_H
23 :
24 : /* This header uses std::vector, but <vector> can't be directly
25 : included due to issues with macros. Hence it must be included from
26 : system.h by defining INCLUDE_VECTOR in any source file using it. */
27 :
28 : #ifndef INCLUDE_VECTOR
29 : # error "You must define INCLUDE_VECTOR before including system.h to use text-art/types.h"
30 : #endif
31 :
32 : #include "cpplib.h"
33 : #include "pretty-print.h"
34 :
35 : namespace text_art {
36 :
37 : /* Forward decls. */
38 :
39 : class canvas;
40 : class table;
41 : class theme;
42 :
43 : /* Classes for geometry.
44 : We use templates to avoid mixing up e.g. canvas coordinates
45 : with table coordinates. */
46 :
47 : template <typename CoordinateSystem>
48 : struct size
49 : {
50 4394 : size (int w_, int h_) : w (w_), h (h_) {}
51 : int w;
52 : int h;
53 : };
54 :
55 : template <typename CoordinateSystem>
56 : struct coord
57 : {
58 140591 : coord (int x_, int y_) : x (x_), y (y_) {}
59 : int x;
60 : int y;
61 : };
62 :
63 : template <typename CoordinateSystem>
64 63550 : coord<CoordinateSystem> operator+ (coord<CoordinateSystem> a,
65 : coord<CoordinateSystem> b)
66 : {
67 63206 : return coord<CoordinateSystem> (a.x + b.x, a.y + b.y);
68 : }
69 :
70 : /* A half-open range [start, next) of int. */
71 :
72 : template <typename CoordinateSystem>
73 : struct range
74 : {
75 335 : range (int start_, int next_)
76 454 : : start (start_), next (next_)
77 : {}
78 :
79 712 : int get_min () const { return start; }
80 10072 : int get_max () const { return next - 1; }
81 599 : int get_next () const { return next; }
82 462 : int get_size () const { return next - start; }
83 :
84 280 : int get_midpoint () const { return get_min () + get_size () / 2; }
85 :
86 : int start;
87 : int next;
88 : };
89 :
90 : /* A rectangle area within CoordinateSystem. */
91 :
92 : template <typename CoordinateSystem>
93 : struct rect
94 : {
95 3504 : rect (coord<CoordinateSystem> top_left,
96 : size<CoordinateSystem> size)
97 2278 : : m_top_left (top_left),
98 2118 : m_size (size)
99 : {
100 : }
101 :
102 150 : rect (range<CoordinateSystem> x_range,
103 : range<CoordinateSystem> y_range)
104 150 : : m_top_left (x_range.get_min (), y_range.get_min ()),
105 150 : m_size (x_range.get_size (), y_range.get_size ())
106 : {
107 : }
108 :
109 3761 : int get_min_x () const { return m_top_left.x; }
110 6184 : int get_min_y () const { return m_top_left.y; }
111 45 : int get_max_x () const { return m_top_left.x + m_size.w - 1; }
112 301 : int get_max_y () const { return m_top_left.y + m_size.h - 1; }
113 111898 : int get_next_x () const { return m_top_left.x + m_size.w; }
114 12925 : int get_next_y () const { return m_top_left.y + m_size.h; }
115 :
116 189 : range<CoordinateSystem> get_x_range () const
117 : {
118 189 : return range<CoordinateSystem> (get_min_x (), get_next_x ());
119 : }
120 280 : range<CoordinateSystem> get_y_range () const
121 : {
122 280 : return range<CoordinateSystem> (get_min_y (), get_next_y ());
123 : }
124 :
125 1345 : int get_width () const { return m_size.w; }
126 244 : int get_height () const { return m_size.h; }
127 :
128 : coord<CoordinateSystem> m_top_left;
129 : size<CoordinateSystem> m_size;
130 : };
131 :
132 : template <typename CoordinateSystem>
133 228 : rect<CoordinateSystem> operator+ (rect<CoordinateSystem> r,
134 : coord<CoordinateSystem> offset)
135 : {
136 228 : return rect<CoordinateSystem> (r.m_top_left + offset, r.m_size);
137 : }
138 :
139 : template <typename ElementType, typename SizeType, typename CoordType>
140 689 : class array2
141 : {
142 : public:
143 : typedef ElementType element_t;
144 : typedef SizeType size_t;
145 : typedef CoordType coord_t;
146 :
147 545 : array2 (size_t sz)
148 545 : : m_size (sz),
149 545 : m_elements (sz.w * sz.h)
150 : {
151 : }
152 426 : array2 (array2 &&other)
153 426 : : m_size (other.m_size),
154 426 : m_elements (std::move (other.m_elements))
155 : {
156 : }
157 :
158 : /* Move assignment not implemented or used. */
159 : array2 &operator== (array2 &&other) = delete;
160 :
161 : /* No copy ctor or assignment op. */
162 : array2 (const array2 &other) = delete;
163 : array2 &operator= (const array2 &other) = delete;
164 :
165 :
166 : const size_t &get_size () const { return m_size; }
167 :
168 250 : void add_row (const element_t &element)
169 : {
170 250 : m_size.h++;
171 250 : m_elements.insert (m_elements.end (), m_size.w, element);
172 250 : }
173 :
174 318496 : const element_t &get (const coord_t &coord) const
175 : {
176 318496 : ::size_t idx = get_idx (coord);
177 318496 : return m_elements[idx];
178 : }
179 :
180 155885 : void set (const coord_t &coord, const element_t &element)
181 : {
182 155885 : ::size_t idx = get_idx (coord);
183 155885 : m_elements[idx] = element;
184 155885 : }
185 :
186 172390 : void set (const coord_t &coord, element_t &&element)
187 : {
188 172390 : ::size_t idx = get_idx (coord);
189 172390 : m_elements[idx] = std::move (element);
190 172390 : }
191 :
192 545 : void fill (element_t element)
193 : {
194 3630 : for (int y = 0; y < m_size.h; y++)
195 152986 : for (int x = 0; x < m_size.w; x++)
196 149901 : set (coord_t (x, y), element);
197 545 : }
198 :
199 : private:
200 646771 : ::size_t get_idx (const coord_t &coord) const
201 : {
202 646771 : gcc_assert (coord.x >= 0);
203 646771 : gcc_assert (coord.x < m_size.w);
204 646771 : gcc_assert (coord.y >= 0);
205 646771 : gcc_assert (coord.y < m_size.h);
206 646771 : return (coord.y * m_size.w) + coord.x;
207 : }
208 :
209 : size_t m_size;
210 : std::vector<element_t> m_elements;
211 : };
212 :
213 : /* A combination of attributes describing how to style a text cell.
214 : We only support those attributes mentioned in invoke.texi:
215 : - bold,
216 : - underscore,
217 : - blink,
218 : - inverse,
219 : - colors for foreground and background:
220 : - default color
221 : - named colors
222 : - 16-color mode colors (the "bright" variants)
223 : - 88-color mode
224 : - 256-color mode
225 : plus URLs. */
226 :
227 21432 : struct style
228 : {
229 : typedef unsigned char id_t;
230 : static const id_t id_plain = 0;
231 :
232 : /* Colors. */
233 : enum class named_color
234 : {
235 : DEFAULT,
236 : // ANSI order
237 : BLACK,
238 : RED,
239 : GREEN,
240 : YELLOW,
241 : BLUE,
242 : MAGENTA,
243 : CYAN,
244 : WHITE
245 : };
246 :
247 :
248 : struct color
249 : {
250 : enum class kind
251 : {
252 : NAMED,
253 : BITS_8,
254 : BITS_24,
255 : } m_kind;
256 :
257 : union
258 : {
259 : struct {
260 : enum named_color m_name;
261 : bool m_bright;
262 : } m_named;
263 : uint8_t m_8bit;
264 : struct {
265 : uint8_t r;
266 : uint8_t g;
267 : uint8_t b;
268 : } m_24bit;
269 : } u;
270 :
271 : /* Constructor for named colors. */
272 22132 : color (enum named_color name = named_color::DEFAULT,
273 : bool bright = false)
274 21648 : : m_kind (kind::NAMED)
275 : {
276 22132 : u.m_named.m_name = name;
277 10042 : u.m_named.m_bright = bright;
278 : }
279 :
280 : /* Constructor for 8-bit colors. */
281 64 : color (uint8_t col_val)
282 8 : : m_kind (kind::BITS_8)
283 : {
284 56 : u.m_8bit = col_val;
285 : }
286 :
287 : /* Constructor for 24-bit colors. */
288 24 : color (uint8_t r, uint8_t g, uint8_t b)
289 8 : : m_kind (kind::BITS_24)
290 : {
291 24 : u.m_24bit.r = r;
292 24 : u.m_24bit.g = g;
293 16 : u.m_24bit.b = b;
294 : }
295 :
296 : bool operator== (const color &other) const;
297 768 : bool operator!= (const color &other) const
298 : {
299 768 : return !(*this == other);
300 : }
301 :
302 : void print_sgr (pretty_printer *pp, bool fg, bool &need_separator) const;
303 : };
304 :
305 21644 : style ()
306 21632 : : m_bold (false),
307 21640 : m_underscore (false),
308 21640 : m_blink (false),
309 21644 : m_reverse (false),
310 21644 : m_fg_color (named_color::DEFAULT),
311 21644 : m_bg_color (named_color::DEFAULT),
312 10264 : m_url ()
313 : {}
314 :
315 11969 : bool operator== (const style &other) const
316 : {
317 11969 : return (m_bold == other.m_bold
318 6853 : && m_underscore == other.m_underscore
319 6841 : && m_blink == other.m_blink
320 6829 : && m_reverse == other.m_reverse
321 6829 : && m_fg_color == other.m_fg_color
322 2601 : && m_bg_color == other.m_bg_color
323 13442 : && m_url == other.m_url);
324 : }
325 :
326 : style &set_style_url (const char *url);
327 :
328 : static void print_changes (pretty_printer *pp,
329 : const style &old_style,
330 : const style &new_style);
331 :
332 : bool m_bold;
333 : bool m_underscore;
334 : bool m_blink;
335 : bool m_reverse;
336 : color m_fg_color;
337 : color m_bg_color;
338 : std::vector<cppchar_t> m_url; // empty = no URL
339 : };
340 :
341 : extern style get_style_from_color_cap_name (const char *name);
342 :
343 : /* A class to keep track of all the styles in use in a drawing, so that
344 : we can refer to them via the compact style::id_t type, rather than
345 : via e.g. pointers. */
346 :
347 9298 : class style_manager
348 : {
349 : public:
350 : style_manager ();
351 : style::id_t get_or_create_id (const style &style);
352 216 : const style &get_style (style::id_t id) const
353 : {
354 192 : return m_styles[id];
355 : }
356 : void print_any_style_changes (pretty_printer *pp,
357 : style::id_t old_id,
358 : style::id_t new_id) const;
359 248 : unsigned get_num_styles () const { return m_styles.size (); }
360 :
361 : private:
362 : std::vector<style> m_styles;
363 : };
364 :
365 2236870 : class styled_unichar
366 : {
367 : public:
368 : friend class styled_string;
369 :
370 145685 : explicit styled_unichar ()
371 145685 : : m_code (0),
372 145685 : m_style_id (style::id_plain)
373 : {}
374 25087 : explicit styled_unichar (cppchar_t ch)
375 25087 : : m_code (ch),
376 25087 : m_emoji_variant_p (false),
377 8549 : m_style_id (style::id_plain)
378 : {}
379 178003 : explicit styled_unichar (cppchar_t ch, bool emoji, style::id_t style_id)
380 178003 : : m_code (ch),
381 178003 : m_emoji_variant_p (emoji),
382 177898 : m_style_id (style_id)
383 : {
384 178003 : gcc_assert (style_id <= 0x7f);
385 177898 : }
386 :
387 149470 : cppchar_t get_code () const { return m_code; }
388 133962 : bool emoji_variant_p () const { return m_emoji_variant_p; }
389 146635 : style::id_t get_style_id () const { return m_style_id; }
390 :
391 150567 : bool double_width_p () const
392 : {
393 150567 : int width = cpp_wcwidth (get_code ());
394 150567 : gcc_assert (width == 1 || width == 2);
395 150567 : return width == 2;
396 : }
397 :
398 120 : bool operator== (const styled_unichar &other) const
399 : {
400 120 : return (m_code == other.m_code
401 120 : && m_emoji_variant_p == other.m_emoji_variant_p
402 240 : && m_style_id == other.m_style_id);
403 : }
404 :
405 6 : void set_emoji_variant () { m_emoji_variant_p = true; }
406 :
407 169575 : int get_canvas_width () const
408 : {
409 169575 : return cpp_wcwidth (m_code);
410 : }
411 :
412 4 : void add_combining_char (cppchar_t ch)
413 : {
414 4 : m_combining_chars.push_back (ch);
415 : }
416 :
417 8 : const std::vector<cppchar_t> get_combining_chars () const
418 : {
419 8 : return m_combining_chars;
420 : }
421 :
422 : private:
423 : cppchar_t m_code : 24;
424 : bool m_emoji_variant_p : 1;
425 : style::id_t m_style_id : 7;
426 : std::vector<cppchar_t> m_combining_chars;
427 : };
428 :
429 20866 : class styled_string
430 : {
431 : public:
432 : explicit styled_string () = default;
433 : explicit styled_string (style_manager &sm, const char *str);
434 : explicit styled_string (cppchar_t cppchar, bool emoji = false);
435 :
436 10822 : styled_string (styled_string &&) = default;
437 68 : styled_string &operator= (styled_string &&) = default;
438 :
439 : /* No copy ctor or assignment op. */
440 : styled_string (const styled_string &) = delete;
441 : styled_string &operator= (const styled_string &) = delete;
442 :
443 : /* For the few cases where copying is required, spell it out explicitly. */
444 306 : styled_string copy () const
445 : {
446 306 : styled_string result;
447 306 : result.m_chars = m_chars;
448 306 : return result;
449 : }
450 :
451 120 : bool operator== (const styled_string &other) const
452 : {
453 120 : return m_chars == other.m_chars;
454 : }
455 :
456 : static styled_string from_fmt (style_manager &sm,
457 : printer_fn format_decoder,
458 : const char *fmt, ...)
459 : ATTRIBUTE_GCC_PPDIAG(3, 4);
460 : static styled_string from_fmt_va (style_manager &sm,
461 : printer_fn format_decoder,
462 : const char *fmt,
463 : va_list *args)
464 : ATTRIBUTE_GCC_PPDIAG(3, 0);
465 :
466 356 : size_t size () const { return m_chars.size (); }
467 924 : styled_unichar operator[] (size_t idx) const { return m_chars[idx]; }
468 :
469 2823 : std::vector<styled_unichar>::const_iterator begin () const
470 : {
471 2823 : return m_chars.begin ();
472 : }
473 2823 : std::vector<styled_unichar>::const_iterator end () const
474 : {
475 2823 : return m_chars.end ();
476 : }
477 :
478 : int calc_canvas_width () const;
479 :
480 : void append (const styled_string &suffix);
481 :
482 : void set_url (style_manager &sm, const char *url);
483 :
484 : private:
485 : std::vector<styled_unichar> m_chars;
486 : };
487 :
488 : enum class x_align
489 : {
490 : LEFT,
491 : CENTER,
492 : RIGHT
493 : };
494 :
495 : enum class y_align
496 : {
497 : TOP,
498 : CENTER,
499 : BOTTOM
500 : };
501 :
502 : /* A set of cardinal directions within a canvas or table. */
503 :
504 : struct directions
505 : {
506 : public:
507 25432 : directions (bool up, bool down, bool left, bool right)
508 14579 : : m_up (up), m_down (down), m_left (left), m_right (right)
509 : {
510 : }
511 :
512 16554 : size_t as_index () const
513 : {
514 16554 : return (m_up << 3) | (m_down << 2) | (m_left << 1) | m_right;
515 : }
516 :
517 : bool m_up: 1;
518 : bool m_down: 1;
519 : bool m_left: 1;
520 : bool m_right: 1;
521 : };
522 :
523 : } // namespace text_art
524 :
525 : #endif /* GCC_TEXT_ART_TYPES_H */
|