1 /*
2  * Copyright (C) 2003 Red Hat, Inc.
3  * Copyright © 2020 Christian Persch
4  *
5  * This library is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published
7  * by the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library.  If not, see <https://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include <cstdint>
22 
23 #include <memory>
24 
25 #include <cairo.h>
26 
27 #include <glib.h>
28 #include <gtk/gtk.h>
29 
30 #include "cairo-glue.hh"
31 #include "fwd.hh"
32 #include "minifont.hh"
33 #include "vtetypes.hh"
34 #include "vteunistr.h"
35 
36 namespace vte {
37 namespace view {
38 
39 class DrawingContext {
40 public:
41 
42         /* A request to draw a particular character spanning a given number of columns
43            at the given location.  Unlike most APIs, (x,y) specifies the top-left
44            corner of the cell into which the character will be drawn instead of the
45            left end of the baseline. */
46         struct TextRequest {
47                 vteunistr c;
48                 int16_t x, y, columns;
49 
50                 /* Char has RTL resolved directionality, mirror if mirrorable. */
51                 uint8_t mirror : 1;
52 
53                 /* Add box drawing chars to the set of mirrorable characters. */
54                 uint8_t box_mirror : 1;
55         };
56 
57         DrawingContext() noexcept = default;
58         ~DrawingContext();
59 
60         DrawingContext(DrawingContext const&) = delete;
61         DrawingContext(DrawingContext&&) = delete;
62         DrawingContext& operator=(DrawingContext const&) = delete;
63         DrawingContext& operator=(DrawingContext&&) = delete;
64 
65         void set_cairo(cairo_t* cr) noexcept;
cairo() const66         auto cairo() const noexcept { return m_cr; }
67 
68         void clip(cairo_rectangle_int_t const* rect);
69         void unclip();
70 
71         void clear(int x,
72                    int y,
73                    int width,
74                    int height,
75                    vte::color::rgb const* color,
76                    double alpha);
77         void clear_font_cache();
78         void set_text_font(GtkWidget* widget,
79                            PangoFontDescription const* fontdesc,
80                            double cell_width_scale,
81                            double cell_height_scale);
82         void get_text_metrics(int* cell_width,
83                               int* cell_height,
84                               int* char_ascent,
85                               int* char_descent,
86                               GtkBorder* char_spacing);
87         void get_char_edges(vteunistr c,
88                             int columns,
89                             uint32_t attr,
90                             int& left,
91                             int& right);
92         void draw_text(TextRequest* requests,
93                        gsize n_requests,
94                        uint32_t attr,
95                        vte::color::rgb const* color,
96                        double alpha);
97         bool draw_char(TextRequest* request,
98                        uint32_t attr,
99                        vte::color::rgb const* color,
100                        double alpha);
101         bool has_char(vteunistr c,
102                       uint32_t attr);
103         void fill_rectangle(int x,
104                             int y,
105                             int width,
106                             int height,
107                             vte::color::rgb const* color,
108                             double alpha);
109         void draw_rectangle(int x,
110                             int y,
111                             int width,
112                             int height,
113                             vte::color::rgb const* color,
114                             double alpha);
115         void draw_line(int x,
116                        int y,
117                        int xp,
118                        int yp,
119                        int line_width,
120                        vte::color::rgb const *color,
121                        double alpha);
122 
123         void draw_undercurl(int x,
124                             double y,
125                             double line_width,
126                             int count,
127                             vte::color::rgb const* color,
128                             double alpha);
129 
cell_width() const130         auto cell_width()  const noexcept { return m_cell_width; }
cell_height() const131         auto cell_height() const noexcept { return m_cell_height; }
132 
133 private:
134         void set_source_color_alpha (vte::color::rgb const* color,
135                                      double alpha);
136         void draw_graphic(vteunistr c,
137                           uint32_t attr,
138                           vte::color::rgb const* fg,
139                           int x,
140                           int y,
141                           int font_width,
142                           int columns,
143                           int font_height);
144         void draw_text_internal(TextRequest* requests,
145                                 gsize n_requests,
146                                 uint32_t attr,
147                                 vte::color::rgb const* color,
148                                 double alpha);
149 
150         //        std::array<vte::base::RefPtr<FontInfo>, 4> m_fonts{};
151 	FontInfo* m_fonts[4]{nullptr, nullptr, nullptr, nullptr};
152         int m_cell_width{1};
153         int m_cell_height{1};
154         GtkBorder m_char_spacing{1, 1, 1, 1};
155 
156 	cairo_t *m_cr{nullptr}; // unowned
157 
158         Minifont m_minifont{};
159 
160         /* Cache the undercurl's rendered look. */
161         vte::Freeable<cairo_surface_t> m_undercurl_surface{};
162 
163 }; // class DrawingContext
164 
165 } // namespace view
166 } // namespace vte
167 
168 double
169 _vte_draw_get_undercurl_height(gint width, double line_width);
170 
171 class _vte_draw_autoclip_t {
172 private:
173         vte::view::DrawingContext& m_draw;
174 public:
_vte_draw_autoclip_t(vte::view::DrawingContext & draw,cairo_rectangle_int_t const * rect)175         _vte_draw_autoclip_t(vte::view::DrawingContext& draw,
176                              cairo_rectangle_int_t const* rect)
177                 : m_draw{draw}
178         {
179                 m_draw.clip(rect);
180         }
181 
~_vte_draw_autoclip_t()182         ~_vte_draw_autoclip_t()
183         {
184                 m_draw.unclip();
185         }
186 };
187