1 /* Types for drawing 2d "text art".
2 Copyright (C) 2023-2024 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
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)
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.
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/>. */
21 #ifndef GCC_TEXT_ART_TYPES_H
22 #define GCC_TEXT_ART_TYPES_H
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_MEMORY in any source file using it. */
28 #ifndef INCLUDE_VECTOR
29 # error "You must define INCLUDE_VECTOR before including system.h to use text-art/types.h"
33 #include "pretty-print.h"
43 /* Classes for geometry.
44 We use templates to avoid mixing up e.g. canvas coordinates
45 with table coordinates. */
47 template <typename CoordinateSystem
>
50 size (int w_
, int h_
) : w (w_
), h (h_
) {}
55 template <typename CoordinateSystem
>
58 coord (int x_
, int y_
) : x (x_
), y (y_
) {}
63 template <typename CoordinateSystem
>
64 coord
<CoordinateSystem
> operator+ (coord
<CoordinateSystem
> a
,
65 coord
<CoordinateSystem
> b
)
67 return coord
<CoordinateSystem
> (a
.x
+ b
.x
, a
.y
+ b
.y
);
70 /* A half-open range [start, next) of int. */
72 template <typename CoordinateSystem
>
75 range (int start_
, int next_
)
76 : start (start_
), next (next_
)
79 int get_min () const { return start
; }
80 int get_max () const { return next
- 1; }
81 int get_next () const { return next
; }
82 int get_size () const { return next
- start
; }
84 int get_midpoint () const { return get_min () + get_size () / 2; }
90 /* A rectangle area within CoordinateSystem. */
92 template <typename CoordinateSystem
>
95 rect (coord
<CoordinateSystem
> top_left
,
96 size
<CoordinateSystem
> size
)
97 : m_top_left (top_left
),
102 rect (range
<CoordinateSystem
> x_range
,
103 range
<CoordinateSystem
> y_range
)
104 : m_top_left (x_range
.get_min (), y_range
.get_min ()),
105 m_size (x_range
.get_size (), y_range
.get_size ())
109 int get_min_x () const { return m_top_left
.x
; }
110 int get_min_y () const { return m_top_left
.y
; }
111 int get_max_x () const { return m_top_left
.x
+ m_size
.w
- 1; }
112 int get_max_y () const { return m_top_left
.y
+ m_size
.h
- 1; }
113 int get_next_x () const { return m_top_left
.x
+ m_size
.w
; }
114 int get_next_y () const { return m_top_left
.y
+ m_size
.h
; }
116 range
<CoordinateSystem
> get_x_range () const
118 return range
<CoordinateSystem
> (get_min_x (), get_next_x ());
120 range
<CoordinateSystem
> get_y_range () const
122 return range
<CoordinateSystem
> (get_min_y (), get_next_y ());
125 int get_width () const { return m_size
.w
; }
126 int get_height () const { return m_size
.h
; }
128 coord
<CoordinateSystem
> m_top_left
;
129 size
<CoordinateSystem
> m_size
;
132 template <typename CoordinateSystem
>
133 rect
<CoordinateSystem
> operator+ (rect
<CoordinateSystem
> r
,
134 coord
<CoordinateSystem
> offset
)
136 return rect
<CoordinateSystem
> (r
.m_top_left
+ offset
, r
.m_size
);
139 template <typename ElementType
, typename SizeType
, typename CoordType
>
143 typedef ElementType element_t
;
144 typedef SizeType
size_t;
145 typedef CoordType coord_t
;
149 m_elements (sz
.w
* sz
.h
)
152 array2 (array2
&&other
)
153 : m_size (other
.m_size
),
154 m_elements (std::move (other
.m_elements
))
158 /* Move assignment not implemented or used. */
159 array2
&operator== (array2
&&other
) = delete;
161 /* No copy ctor or assignment op. */
162 array2 (const array2
&other
) = delete;
163 array2
&operator= (const array2
&other
) = delete;
166 const size_t &get_size () const { return m_size
; }
168 void add_row (const element_t
&element
)
171 m_elements
.insert (m_elements
.end (), m_size
.w
, element
);
174 const element_t
&get (const coord_t
&coord
) const
176 ::size_t idx
= get_idx (coord
);
177 return m_elements
[idx
];
180 void set (const coord_t
&coord
, const element_t
&element
)
182 ::size_t idx
= get_idx (coord
);
183 m_elements
[idx
] = element
;
186 void fill (element_t element
)
188 for (int y
= 0; y
< m_size
.h
; y
++)
189 for (int x
= 0; x
< m_size
.w
; x
++)
190 set (coord_t (x
, y
), element
);
194 ::size_t get_idx (const coord_t
&coord
) const
196 gcc_assert (coord
.x
>= 0);
197 gcc_assert (coord
.x
< m_size
.w
);
198 gcc_assert (coord
.y
>= 0);
199 gcc_assert (coord
.y
< m_size
.h
);
200 return (coord
.y
* m_size
.w
) + coord
.x
;
204 std::vector
<element_t
> m_elements
;
207 /* A combination of attributes describing how to style a text cell.
208 We only support those attributes mentioned in invoke.texi:
213 - colors for foreground and background:
216 - 16-color mode colors (the "bright" variants)
223 typedef unsigned char id_t
;
224 static const id_t id_plain
= 0;
227 enum class named_color
254 enum named_color m_name
;
265 /* Constructor for named colors. */
266 color (enum named_color name
= named_color::DEFAULT
,
268 : m_kind (kind::NAMED
)
270 u
.m_named
.m_name
= name
;
271 u
.m_named
.m_bright
= bright
;
274 /* Constructor for 8-bit colors. */
275 color (uint8_t col_val
)
276 : m_kind (kind::BITS_8
)
281 /* Constructor for 24-bit colors. */
282 color (uint8_t r
, uint8_t g
, uint8_t b
)
283 : m_kind (kind::BITS_24
)
290 bool operator== (const color
&other
) const;
291 bool operator!= (const color
&other
) const
293 return !(*this == other
);
296 void print_sgr (pretty_printer
*pp
, bool fg
, bool &need_separator
) const;
301 m_underscore (false),
304 m_fg_color (named_color::DEFAULT
),
305 m_bg_color (named_color::DEFAULT
),
309 bool operator== (const style
&other
) const
311 return (m_bold
== other
.m_bold
312 && m_underscore
== other
.m_underscore
313 && m_blink
== other
.m_blink
314 && m_reverse
== other
.m_reverse
315 && m_fg_color
== other
.m_fg_color
316 && m_bg_color
== other
.m_bg_color
317 && m_url
== other
.m_url
);
320 style
&set_style_url (const char *url
);
322 static void print_changes (pretty_printer
*pp
,
323 const style
&old_style
,
324 const style
&new_style
);
332 std::vector
<cppchar_t
> m_url
; // empty = no URL
335 extern style
get_style_from_color_cap_name (const char *name
);
337 /* A class to keep track of all the styles in use in a drawing, so that
338 we can refer to them via the compact style::id_t type, rather than
339 via e.g. pointers. */
345 style::id_t
get_or_create_id (const style
&style
);
346 const style
&get_style (style::id_t id
) const
350 void print_any_style_changes (pretty_printer
*pp
,
352 style::id_t new_id
) const;
353 unsigned get_num_styles () const { return m_styles
.size (); }
356 std::vector
<style
> m_styles
;
362 friend class styled_string
;
364 explicit styled_unichar ()
366 m_style_id (style::id_plain
)
368 explicit styled_unichar (cppchar_t ch
)
370 m_emoji_variant_p (false),
371 m_style_id (style::id_plain
)
373 explicit styled_unichar (cppchar_t ch
, bool emoji
, style::id_t style_id
)
375 m_emoji_variant_p (emoji
),
376 m_style_id (style_id
)
378 gcc_assert (style_id
<= 0x7f);
381 cppchar_t
get_code () const { return m_code
; }
382 bool emoji_variant_p () const { return m_emoji_variant_p
; }
383 style::id_t
get_style_id () const { return m_style_id
; }
385 bool double_width_p () const
387 int width
= cpp_wcwidth (get_code ());
388 gcc_assert (width
== 1 || width
== 2);
392 bool operator== (const styled_unichar
&other
) const
394 return (m_code
== other
.m_code
395 && m_emoji_variant_p
== other
.m_emoji_variant_p
396 && m_style_id
== other
.m_style_id
);
399 void set_emoji_variant () { m_emoji_variant_p
= true; }
401 int get_canvas_width () const
403 return cpp_wcwidth (m_code
);
406 void add_combining_char (cppchar_t ch
)
408 m_combining_chars
.push_back (ch
);
411 const std::vector
<cppchar_t
> get_combining_chars () const
413 return m_combining_chars
;
417 cppchar_t m_code
: 24;
418 bool m_emoji_variant_p
: 1;
419 style::id_t m_style_id
: 7;
420 std::vector
<cppchar_t
> m_combining_chars
;
426 explicit styled_string () = default;
427 explicit styled_string (style_manager
&sm
, const char *str
);
428 explicit styled_string (cppchar_t cppchar
, bool emoji
= false);
430 styled_string (styled_string
&&) = default;
431 styled_string
&operator= (styled_string
&&) = default;
433 /* No copy ctor or assignment op. */
434 styled_string (const styled_string
&) = delete;
435 styled_string
&operator= (const styled_string
&) = delete;
437 /* For the few cases where copying is required, spell it out explicitly. */
438 styled_string
copy () const
440 styled_string result
;
441 result
.m_chars
= m_chars
;
445 bool operator== (const styled_string
&other
) const
447 return m_chars
== other
.m_chars
;
450 static styled_string
from_fmt (style_manager
&sm
,
451 printer_fn format_decoder
,
452 const char *fmt
, ...)
453 ATTRIBUTE_GCC_PPDIAG(3, 4);
454 static styled_string
from_fmt_va (style_manager
&sm
,
455 printer_fn format_decoder
,
458 ATTRIBUTE_GCC_PPDIAG(3, 0);
460 size_t size () const { return m_chars
.size (); }
461 styled_unichar
operator[] (size_t idx
) const { return m_chars
[idx
]; }
463 std::vector
<styled_unichar
>::const_iterator
begin () const
465 return m_chars
.begin ();
467 std::vector
<styled_unichar
>::const_iterator
end () const
469 return m_chars
.end ();
472 int calc_canvas_width () const;
474 void append (const styled_string
&suffix
);
476 void set_url (style_manager
&sm
, const char *url
);
479 std::vector
<styled_unichar
> m_chars
;
496 /* A set of cardinal directions within a canvas or table. */
501 directions (bool up
, bool down
, bool left
, bool right
)
502 : m_up (up
), m_down (down
), m_left (left
), m_right (right
)
506 size_t as_index () const
508 return (m_up
<< 3) | (m_down
<< 2) | (m_left
<< 1) | m_right
;
517 } // namespace text_art
519 #endif /* GCC_TEXT_ART_TYPES_H */