[vte] draw: C++ify
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte] draw: C++ify
- Date: Mon, 1 Jun 2020 20:50:22 +0000 (UTC)
commit c1a86839eea2ca95f9cf1cfc3405472609ec5132
Author: Christian Persch <chpe src gnome org>
Date: Mon Jun 1 22:48:43 2020 +0200
draw: C++ify
src/vte.cc | 25 +--
src/vtedraw.cc | 462 +++++++++++++++++++++++++----------------------------
src/vtedraw.hh | 338 +++++++++++++++++++++++++++++++--------
src/vteinternal.hh | 6 +-
4 files changed, 492 insertions(+), 339 deletions(-)
---
diff --git a/src/vte.cc b/src/vte.cc
index 92d3df48..09cd22d1 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -7234,7 +7234,7 @@ Terminal::apply_font_metrics(int cell_width,
void
Terminal::ensure_font()
{
- if (m_draw != NULL) {
+ {
/* Load default fonts, if no fonts have been loaded. */
if (!m_has_fonts) {
set_font_desc(m_unscaled_font_desc.get());
@@ -7744,9 +7744,6 @@ Terminal::Terminal(vte::platform::Widget* w,
m_match_span.clear(); // FIXMEchpe unnecessary
match_hilite_clear(); // FIXMEchpe unnecessary
- /* Rendering data */
- m_draw = _vte_draw_new();
-
/* Word chars */
set_word_char_exceptions(WORD_CHAR_EXCEPTIONS_DEFAULT);
@@ -7892,11 +7889,8 @@ Terminal::widget_unrealize()
m_im_preedit_active = FALSE;
- /* Clean up our draw structure. */
- if (m_draw != NULL) {
- _vte_draw_free(m_draw);
- m_draw = NULL;
- }
+ /* Drop font cache */
+ m_draw.clear_font_cache();
m_fontdirty = true;
/* Remove the cursor blink timeout function. */
@@ -7954,11 +7948,6 @@ Terminal::~Terminal()
/* Stop processing input. */
stop_processing(this);
- /* Free the draw structure. */
- if (m_draw != NULL) {
- _vte_draw_free(m_draw);
- }
-
/* Free matching data. */
if (m_match_attributes != NULL) {
g_array_free(m_match_attributes, TRUE);
@@ -8020,16 +8009,12 @@ Terminal::widget_realize()
{
m_mouse_cursor_over_widget = FALSE; /* We'll receive an enter_notify_event if the window appears
under the cursor. */
- /* Create rendering data if this is a re-realise */
- if (m_draw == NULL) {
- m_draw = _vte_draw_new();
- }
-
m_im_preedit_active = FALSE;
/* Clear modifiers. */
m_modifiers = 0;
+ // Create the font cache
ensure_font();
}
@@ -9291,7 +9276,7 @@ Terminal::widget_draw(cairo_t *cr)
cairo_restore(cr);
/* Done with various structures. */
- _vte_draw_set_cairo(m_draw, NULL);
+ _vte_draw_set_cairo(m_draw, nullptr);
cairo_region_destroy (region);
diff --git a/src/vtedraw.cc b/src/vtedraw.cc
index 621bcb5c..56e09f39 100644
--- a/src/vtedraw.cc
+++ b/src/vtedraw.cc
@@ -766,92 +766,72 @@ guint _vte_draw_get_style(gboolean bold, gboolean italic) {
return style;
}
-struct _vte_draw {
- struct font_info *fonts[4];
- /* cell metrics, already adjusted by cell_{width,height}_scale */
- int cell_width, cell_height;
- GtkBorder char_spacing;
-
- cairo_t *cr;
-
- /* Cache the undercurl's rendered look. */
- cairo_surface_t *undercurl_surface;
-};
+static inline constexpr double
+_vte_draw_get_undercurl_rad(gint width)
+{
+ return width / 2. / sqrt(2);
+}
-struct _vte_draw *
-_vte_draw_new (void)
+static inline constexpr double
+_vte_draw_get_undercurl_arc_height(gint width)
{
- struct _vte_draw *draw;
+ return _vte_draw_get_undercurl_rad(width) * (1. - sqrt(2) / 2.);
+}
- /* Create the structure. */
- draw = g_slice_new0 (struct _vte_draw);
+double
+_vte_draw_get_undercurl_height(gint width, double line_width)
+{
+ return 2. * _vte_draw_get_undercurl_arc_height(width) + line_width;
+}
- _vte_debug_print (VTE_DEBUG_DRAW, "draw_new\n");
+namespace vte {
+namespace view {
- return draw;
+DrawingContext::~DrawingContext()
+{
+ clear_font_cache();
}
void
-_vte_draw_free (struct _vte_draw *draw)
+DrawingContext::clear_font_cache()
{
- gint style;
- _vte_debug_print (VTE_DEBUG_DRAW, "draw_free\n");
-
/* Free all fonts (make sure to destroy every font only once)*/
- for (style = 3; style >= 0; style--) {
- if (draw->fonts[style] != NULL &&
- (style == 0 || draw->fonts[style] != draw->fonts[style-1])) {
- font_info_destroy (draw->fonts[style]);
- draw->fonts[style] = NULL;
+ for (auto style = int{3}; style >= 0; style--) {
+ if (m_fonts[style] != nullptr &&
+ (style == 0 || m_fonts[style] != m_fonts[style-1])) {
+ font_info_destroy(m_fonts[style]);
+ m_fonts[style] = nullptr;
}
}
-
- if (draw->undercurl_surface != NULL) {
- cairo_surface_destroy (draw->undercurl_surface);
- draw->undercurl_surface = NULL;
- }
-
- g_slice_free (struct _vte_draw, draw);
}
void
-_vte_draw_set_cairo (struct _vte_draw *draw,
- cairo_t *cr)
+DrawingContext::set_cairo(cairo_t* cr) noexcept
{
- _vte_debug_print (VTE_DEBUG_DRAW, "%s cairo context\n", cr ? "Settings" : "Unsetting");
-
- if (cr) {
- g_assert (draw->cr == NULL);
- draw->cr = cr;
- } else {
- g_assert (draw->cr != NULL);
- draw->cr = NULL;
- }
+ m_cr = cr;
}
void
-_vte_draw_clip(struct _vte_draw *draw,
- cairo_rectangle_int_t const* rect)
+DrawingContext::clip(cairo_rectangle_int_t const* rect)
{
- cairo_save(draw->cr);
- cairo_rectangle(draw->cr,
+ cairo_save(m_cr);
+ cairo_rectangle(m_cr,
rect->x, rect->y, rect->width, rect->height);
- cairo_clip(draw->cr);
+ cairo_clip(m_cr);
}
void
-_vte_draw_unclip(struct _vte_draw *draw)
+DrawingContext::unclip()
{
- cairo_restore(draw->cr);
+ cairo_restore(m_cr);
}
-static void
-_vte_draw_set_source_color_alpha (struct _vte_draw *draw,
- vte::color::rgb const* color,
- double alpha)
+void
+DrawingContext::set_source_color_alpha(vte::color::rgb const* color,
+ double alpha)
{
- g_assert(draw->cr);
- cairo_set_source_rgba (draw->cr,
+ g_assert(m_cr);
+ cairo_set_source_rgba(m_cr,
color->red / 65535.,
color->green / 65535.,
color->blue / 65535.,
@@ -859,41 +839,34 @@ _vte_draw_set_source_color_alpha (struct _vte_draw *draw,
}
void
-_vte_draw_clear (struct _vte_draw *draw, gint x, gint y, gint width, gint height,
- vte::color::rgb const* color, double alpha)
+DrawingContext::clear(int x,
+ int y,
+ int width,
+ int height,
+ vte::color::rgb const* color,
+ double alpha)
{
- _vte_debug_print (VTE_DEBUG_DRAW, "draw_clear (%d, %d, %d, %d)\n",
- x,y,width, height);
-
- g_assert(draw->cr);
- cairo_rectangle (draw->cr, x, y, width, height);
- cairo_set_operator (draw->cr, CAIRO_OPERATOR_SOURCE);
- _vte_draw_set_source_color_alpha(draw, color, alpha);
- cairo_fill (draw->cr);
+ g_assert(m_cr);
+ cairo_rectangle(m_cr, x, y, width, height);
+ cairo_set_operator(m_cr, CAIRO_OPERATOR_SOURCE);
+ set_source_color_alpha(color, alpha);
+ cairo_fill(m_cr);
}
void
-_vte_draw_set_text_font (struct _vte_draw *draw,
- GtkWidget *widget,
- const PangoFontDescription *fontdesc,
- double cell_width_scale,
- double cell_height_scale)
+DrawingContext::set_text_font (GtkWidget* widget,
+ PangoFontDescription const* fontdesc,
+ double cell_width_scale,
+ double cell_height_scale)
{
- PangoFontDescription *bolddesc = NULL;
- PangoFontDescription *italicdesc = NULL;
- PangoFontDescription *bolditalicdesc = NULL;
- gint style, normal, bold, ratio;
+ PangoFontDescription *bolddesc = nullptr;
+ PangoFontDescription *italicdesc = nullptr;
+ PangoFontDescription *bolditalicdesc = nullptr;
+ gint normal, bold, ratio;
_vte_debug_print (VTE_DEBUG_DRAW, "draw_set_text_font\n");
- /* Free all fonts (make sure to destroy every font only once)*/
- for (style = 3; style >= 0; style--) {
- if (draw->fonts[style] != NULL &&
- (style == 0 || draw->fonts[style] != draw->fonts[style-1])) {
- font_info_destroy (draw->fonts[style]);
- draw->fonts[style] = NULL;
- }
- }
+ clear_font_cache();
/* calculate bold font desc */
bolddesc = pango_font_description_copy (fontdesc);
@@ -907,10 +880,10 @@ _vte_draw_set_text_font (struct _vte_draw *draw,
bolditalicdesc = pango_font_description_copy (bolddesc);
pango_font_description_set_style (bolditalicdesc, PANGO_STYLE_ITALIC);
- draw->fonts[VTE_DRAW_NORMAL] = font_info_create_for_widget (widget, fontdesc);
- draw->fonts[VTE_DRAW_BOLD] = font_info_create_for_widget (widget, bolddesc);
- draw->fonts[VTE_DRAW_ITALIC] = font_info_create_for_widget (widget, italicdesc);
- draw->fonts[VTE_DRAW_ITALIC | VTE_DRAW_BOLD] =
+ m_fonts[VTE_DRAW_NORMAL] = font_info_create_for_widget (widget, fontdesc);
+ m_fonts[VTE_DRAW_BOLD] = font_info_create_for_widget (widget, bolddesc);
+ m_fonts[VTE_DRAW_ITALIC] = font_info_create_for_widget (widget, italicdesc);
+ m_fonts[VTE_DRAW_ITALIC | VTE_DRAW_BOLD] =
font_info_create_for_widget (widget, bolditalicdesc);
pango_font_description_free (bolddesc);
pango_font_description_free (italicdesc);
@@ -921,62 +894,59 @@ _vte_draw_set_text_font (struct _vte_draw *draw,
*/
normal = VTE_DRAW_NORMAL;
bold = normal | VTE_DRAW_BOLD;
- ratio = draw->fonts[bold]->width * 100 / draw->fonts[normal]->width;
+ ratio = m_fonts[bold]->width * 100 / m_fonts[normal]->width;
if (abs(ratio - 100) > 10) {
_vte_debug_print (VTE_DEBUG_DRAW,
"Rejecting bold font (%i%%).\n", ratio);
- font_info_destroy (draw->fonts[bold]);
- draw->fonts[bold] = draw->fonts[normal];
+ font_info_destroy (m_fonts[bold]);
+ m_fonts[bold] = m_fonts[normal];
}
normal = VTE_DRAW_ITALIC;
bold = normal | VTE_DRAW_BOLD;
- ratio = draw->fonts[bold]->width * 100 / draw->fonts[normal]->width;
+ ratio = m_fonts[bold]->width * 100 / m_fonts[normal]->width;
if (abs(ratio - 100) > 10) {
_vte_debug_print (VTE_DEBUG_DRAW,
"Rejecting italic bold font (%i%%).\n", ratio);
- font_info_destroy (draw->fonts[bold]);
- draw->fonts[bold] = draw->fonts[normal];
+ font_info_destroy (m_fonts[bold]);
+ m_fonts[bold] = m_fonts[normal];
}
/* Apply letter spacing and line spacing. */
- draw->cell_width = draw->fonts[VTE_DRAW_NORMAL]->width * cell_width_scale;
- draw->char_spacing.left = (draw->cell_width - draw->fonts[VTE_DRAW_NORMAL]->width) / 2;
- draw->char_spacing.right = (draw->cell_width - draw->fonts[VTE_DRAW_NORMAL]->width + 1) / 2;
- draw->cell_height = draw->fonts[VTE_DRAW_NORMAL]->height * cell_height_scale;
- draw->char_spacing.top = (draw->cell_height - draw->fonts[VTE_DRAW_NORMAL]->height + 1) / 2;
- draw->char_spacing.bottom = (draw->cell_height - draw->fonts[VTE_DRAW_NORMAL]->height) / 2;
-
- /* Drop the undercurl's cached look. Will recache on demand. */
- if (draw->undercurl_surface != NULL) {
- cairo_surface_destroy (draw->undercurl_surface);
- draw->undercurl_surface = NULL;
- }
+ m_cell_width = m_fonts[VTE_DRAW_NORMAL]->width * cell_width_scale;
+ m_char_spacing.left = (m_cell_width - m_fonts[VTE_DRAW_NORMAL]->width) / 2;
+ m_char_spacing.right = (m_cell_width - m_fonts[VTE_DRAW_NORMAL]->width + 1) / 2;
+ m_cell_height = m_fonts[VTE_DRAW_NORMAL]->height * cell_height_scale;
+ m_char_spacing.top = (m_cell_height - m_fonts[VTE_DRAW_NORMAL]->height + 1) / 2;
+ m_char_spacing.bottom = (m_cell_height - m_fonts[VTE_DRAW_NORMAL]->height) / 2;
+
+ m_undercurl_surface.reset();
}
void
-_vte_draw_get_text_metrics(struct _vte_draw *draw,
- int *cell_width, int *cell_height,
- int *char_ascent, int *char_descent,
- GtkBorder *char_spacing)
+DrawingContext::get_text_metrics(int* cell_width,
+ int* cell_height,
+ int* char_ascent,
+ int* char_descent,
+ GtkBorder* char_spacing)
{
- g_return_if_fail (draw->fonts[VTE_DRAW_NORMAL] != NULL);
+ g_return_if_fail (m_fonts[VTE_DRAW_NORMAL] != nullptr);
if (cell_width)
- *cell_width = draw->cell_width;
+ *cell_width = m_cell_width;
if (cell_height)
- *cell_height = draw->cell_height;
+ *cell_height = m_cell_height;
if (char_ascent)
- *char_ascent = draw->fonts[VTE_DRAW_NORMAL]->ascent;
+ *char_ascent = m_fonts[VTE_DRAW_NORMAL]->ascent;
if (char_descent)
- *char_descent = draw->fonts[VTE_DRAW_NORMAL]->height - draw->fonts[VTE_DRAW_NORMAL]->ascent;
+ *char_descent = m_fonts[VTE_DRAW_NORMAL]->height - m_fonts[VTE_DRAW_NORMAL]->ascent;
if (char_spacing)
- *char_spacing = draw->char_spacing;
+ *char_spacing = m_char_spacing;
}
/* Check if a unicode character is actually a graphic character we draw
* ourselves to handle cases where fonts don't have glyphs for them. */
-static gboolean
-_vte_draw_unichar_is_local_graphic(vteunistr c)
+static constexpr bool
+unichar_is_local_graphic(vteunistr c) noexcept
{
/* Box Drawing & Block Elements */
return ((c >= 0x2500 && c <= 0x259f) ||
@@ -986,20 +956,23 @@ _vte_draw_unichar_is_local_graphic(vteunistr c)
/* Stores the left and right edges of the given glyph, relative to the cell's left edge. */
void
-_vte_draw_get_char_edges (struct _vte_draw *draw, vteunistr c, int columns, guint style,
- int *left, int *right)
+DrawingContext::get_char_edges(vteunistr c,
+ int columns,
+ guint style,
+ int* left,
+ int* right)
{
- if (G_UNLIKELY (_vte_draw_unichar_is_local_graphic (c))) {
+ if (G_UNLIKELY(unichar_is_local_graphic (c))) {
if (left)
*left = 0;
if (right)
- *right = draw->cell_width * columns;
+ *right = m_cell_width * columns;
return;
}
int l, w, normal_width, fits_width;
- if (G_UNLIKELY (draw->fonts[VTE_DRAW_NORMAL] == NULL)) {
+ if (G_UNLIKELY (m_fonts[VTE_DRAW_NORMAL] == nullptr)) {
if (left)
*left = 0;
if (right)
@@ -1007,14 +980,14 @@ _vte_draw_get_char_edges (struct _vte_draw *draw, vteunistr c, int columns, guin
return;
}
- w = font_info_get_unistr_info (draw->fonts[style], c)->width;
- normal_width = draw->fonts[VTE_DRAW_NORMAL]->width * columns;
- fits_width = draw->cell_width * columns;
+ w = font_info_get_unistr_info (m_fonts[style], c)->width;
+ normal_width = m_fonts[VTE_DRAW_NORMAL]->width * columns;
+ fits_width = m_cell_width * columns;
if (G_LIKELY (w <= normal_width)) {
/* The regular case: The glyph is not wider than one (CJK: two) regular character(s).
* Align to the left, after applying half (CJK: one) letter spacing. */
- l = draw->char_spacing.left + (columns == 2 ? draw->char_spacing.right : 0);
+ l = m_char_spacing.left + (columns == 2 ? m_char_spacing.right : 0);
} else if (G_UNLIKELY (w <= fits_width)) {
/* Slightly wider glyph, but still fits in the cell (spacing included). This case can
* only happen with nonzero letter spacing. Center the glyph in the cell(s). */
@@ -1148,24 +1121,26 @@ pattern(cairo_t* cr,
/* Draw the graphic representation of a line-drawing or special graphics
* character. */
-static void
-_vte_draw_terminal_draw_graphic(struct _vte_draw *draw,
- vteunistr c,
- uint32_t attr,
- vte::color::rgb const* fg,
- gint x, gint y,
- gint font_width, gint columns, gint font_height)
+void
+DrawingContext::draw_graphic(vteunistr c,
+ uint32_t attr,
+ vte::color::rgb const* fg,
+ int x,
+ int y,
+ int font_width,
+ int columns,
+ int font_height)
{
gint width, height, xcenter, xright, ycenter, ybottom;
int upper_half, left_half;
int light_line_width, heavy_line_width;
double adjust;
- cairo_t *cr = draw->cr;
+ cairo_t *cr = m_cr;
cairo_save (cr);
- width = draw->cell_width * columns;
- height = draw->cell_height;
+ width = m_cell_width * columns;
+ height = m_cell_height;
upper_half = height / 2;
left_half = width / 2;
@@ -2110,23 +2085,25 @@ _vte_draw_terminal_draw_graphic(struct _vte_draw *draw,
cairo_restore(cr);
}
-static void
-_vte_draw_text_internal (struct _vte_draw *draw,
- struct _vte_draw_text_request *requests, gsize n_requests,
- uint32_t attr,
- vte::color::rgb const* color, double alpha, guint style)
+void
+DrawingContext::draw_text_internal(struct _vte_draw_text_request *requests,
+ gsize n_requests,
+ uint32_t attr,
+ vte::color::rgb const* color,
+ double alpha,
+ guint style)
{
gsize i;
- cairo_scaled_font_t *last_scaled_font = NULL;
+ cairo_scaled_font_t *last_scaled_font = nullptr;
int n_cr_glyphs = 0;
cairo_glyph_t cr_glyphs[MAX_RUN_LENGTH];
- struct font_info *font = draw->fonts[style];
+ struct font_info *font = m_fonts[style];
- g_return_if_fail (font != NULL);
+ g_return_if_fail (font != nullptr);
- g_assert(draw->cr);
- _vte_draw_set_source_color_alpha (draw, color, alpha);
- cairo_set_operator (draw->cr, CAIRO_OPERATOR_OVER);
+ g_assert(m_cr);
+ set_source_color_alpha(color, alpha);
+ cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
for (i = 0; i < n_requests; i++) {
vteunistr c = requests[i].c;
@@ -2135,8 +2112,8 @@ _vte_draw_text_internal (struct _vte_draw *draw,
vte_bidi_get_mirror_char (c, requests[i].box_mirror, &c);
}
- if (_vte_draw_unichar_is_local_graphic(c)) {
- _vte_draw_terminal_draw_graphic(draw, c,
+ if (unichar_is_local_graphic(c)) {
+ draw_graphic(c,
attr,
color,
requests[i].x, requests[i].y,
@@ -2148,11 +2125,11 @@ _vte_draw_text_internal (struct _vte_draw *draw,
union unistr_font_info *ufi = &uinfo->ufi;
int x, y;
- _vte_draw_get_char_edges(draw, c, requests[i].columns, style, &x, NULL);
+ get_char_edges(c, requests[i].columns, style, &x, nullptr);
x += requests[i].x;
/* Bold/italic versions might have different ascents. In order to align their
* baselines, we offset by the normal font's ascent here. (Bug 137.) */
- y = requests[i].y + draw->char_spacing.top + draw->fonts[VTE_DRAW_NORMAL]->ascent;
+ y = requests[i].y + m_char_spacing.top + m_fonts[VTE_DRAW_NORMAL]->ascent;
switch (uinfo->coverage) {
default:
@@ -2160,21 +2137,21 @@ _vte_draw_text_internal (struct _vte_draw *draw,
g_assert_not_reached ();
break;
case COVERAGE_USE_PANGO_LAYOUT_LINE:
- cairo_move_to (draw->cr, x, y);
- pango_cairo_show_layout_line (draw->cr,
+ cairo_move_to(m_cr, x, y);
+ pango_cairo_show_layout_line(m_cr,
ufi->using_pango_layout_line.line);
break;
case COVERAGE_USE_PANGO_GLYPH_STRING:
- cairo_move_to (draw->cr, x, y);
- pango_cairo_show_glyph_string (draw->cr,
+ cairo_move_to(m_cr, x, y);
+ pango_cairo_show_glyph_string(m_cr,
ufi->using_pango_glyph_string.font,
ufi->using_pango_glyph_string.glyph_string);
break;
case COVERAGE_USE_CAIRO_GLYPH:
if (last_scaled_font != ufi->using_cairo_glyph.scaled_font || n_cr_glyphs ==
MAX_RUN_LENGTH) {
if (n_cr_glyphs) {
- cairo_set_scaled_font (draw->cr, last_scaled_font);
- cairo_show_glyphs (draw->cr,
+ cairo_set_scaled_font(m_cr, last_scaled_font);
+ cairo_show_glyphs(m_cr,
cr_glyphs,
n_cr_glyphs);
n_cr_glyphs = 0;
@@ -2189,8 +2166,8 @@ _vte_draw_text_internal (struct _vte_draw *draw,
}
}
if (n_cr_glyphs) {
- cairo_set_scaled_font (draw->cr, last_scaled_font);
- cairo_show_glyphs (draw->cr,
+ cairo_set_scaled_font(m_cr, last_scaled_font);
+ cairo_show_glyphs(m_cr,
cr_glyphs,
n_cr_glyphs);
n_cr_glyphs = 0;
@@ -2198,12 +2175,14 @@ _vte_draw_text_internal (struct _vte_draw *draw,
}
void
-_vte_draw_text (struct _vte_draw *draw,
- struct _vte_draw_text_request *requests, gsize n_requests,
- uint32_t attr,
- vte::color::rgb const* color, double alpha, guint style)
+DrawingContext::draw_text(struct _vte_draw_text_request *requests,
+ gsize n_requests,
+ uint32_t attr,
+ vte::color::rgb const* color,
+ double alpha,
+ guint style)
{
- g_assert(draw->cr);
+ g_assert(m_cr);
if (_vte_debug_on (VTE_DEBUG_DRAW)) {
GString *string = g_string_new ("");
@@ -2220,14 +2199,15 @@ _vte_draw_text (struct _vte_draw *draw,
g_free (str);
}
- _vte_draw_text_internal (draw, requests, n_requests, attr, color, alpha, style);
+ draw_text_internal(requests, n_requests, attr, color, alpha, style);
}
/* The following two functions are unused since commit 154abade902850afb44115cccf8fcac51fc082f0,
* but let's keep them for now since they may become used again.
*/
-gboolean
-_vte_draw_has_char (struct _vte_draw *draw, vteunistr c, guint style)
+bool
+DrawingContext::has_char(vteunistr c,
+ guint style)
{
struct unistr_info *uinfo;
@@ -2235,20 +2215,19 @@ _vte_draw_has_char (struct _vte_draw *draw, vteunistr c, guint style)
(style & VTE_DRAW_BOLD) ? "bold" : "normal",
(style & VTE_DRAW_ITALIC) ? "italic" : "regular");
- g_return_val_if_fail (draw->fonts[VTE_DRAW_NORMAL] != NULL, FALSE);
+ g_return_val_if_fail (m_fonts[VTE_DRAW_NORMAL] != nullptr, FALSE);
- uinfo = font_info_get_unistr_info (draw->fonts[style], c);
+ uinfo = font_info_get_unistr_info (m_fonts[style], c);
return !uinfo->has_unknown_chars;
}
-gboolean
-_vte_draw_char (struct _vte_draw *draw,
- struct _vte_draw_text_request *request,
- uint32_t attr,
- vte::color::rgb const* color, double alpha, guint style)
+bool
+DrawingContext::draw_char(struct _vte_draw_text_request *request,
+ uint32_t attr,
+ vte::color::rgb const* color,
+ double alpha,
+ guint style)
{
- gboolean has_char;
-
_vte_debug_print (VTE_DEBUG_DRAW,
"draw_char ('%c', color=(%d,%d,%d,%.3f), %s, %s)\n",
request->c,
@@ -2257,19 +2236,22 @@ _vte_draw_char (struct _vte_draw *draw,
(style & VTE_DRAW_BOLD) ? "bold" : "normal",
(style & VTE_DRAW_ITALIC) ? "italic" : "regular");
- has_char =_vte_draw_has_char (draw, request->c, style);
- if (has_char)
- _vte_draw_text (draw, request, 1, attr, color, alpha, style);
+ auto const have_char = has_char(request->c, style);
+ if (have_char)
+ draw_text(request, 1, attr, color, alpha, style);
- return has_char;
+ return have_char;
}
void
-_vte_draw_draw_rectangle (struct _vte_draw *draw,
- gint x, gint y, gint width, gint height,
- vte::color::rgb const* color, double alpha)
+DrawingContext::draw_rectangle(int x,
+ int y,
+ int width,
+ int height,
+ vte::color::rgb const* color,
+ double alpha)
{
- g_assert(draw->cr);
+ g_assert(m_cr);
_vte_debug_print (VTE_DEBUG_DRAW,
"draw_rectangle (%d, %d, %d, %d, color=(%d,%d,%d,%.3f))\n",
@@ -2277,19 +2259,22 @@ _vte_draw_draw_rectangle (struct _vte_draw *draw,
color->red, color->green, color->blue,
alpha);
- cairo_set_operator (draw->cr, CAIRO_OPERATOR_OVER);
- cairo_rectangle (draw->cr, x+VTE_LINE_WIDTH/2., y+VTE_LINE_WIDTH/2., width-VTE_LINE_WIDTH,
height-VTE_LINE_WIDTH);
- _vte_draw_set_source_color_alpha (draw, color, alpha);
- cairo_set_line_width (draw->cr, VTE_LINE_WIDTH);
- cairo_stroke (draw->cr);
+ cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
+ cairo_rectangle(m_cr, x+VTE_LINE_WIDTH/2., y+VTE_LINE_WIDTH/2., width-VTE_LINE_WIDTH,
height-VTE_LINE_WIDTH);
+ set_source_color_alpha(color, alpha);
+ cairo_set_line_width(m_cr, VTE_LINE_WIDTH);
+ cairo_stroke (m_cr);
}
void
-_vte_draw_fill_rectangle (struct _vte_draw *draw,
- gint x, gint y, gint width, gint height,
- vte::color::rgb const* color, double alpha)
+DrawingContext::fill_rectangle(int x,
+ int y,
+ int width,
+ int height,
+ vte::color::rgb const* color,
+ double alpha)
{
- g_assert(draw->cr);
+ g_assert(m_cr);
_vte_debug_print (VTE_DEBUG_DRAW,
"draw_fill_rectangle (%d, %d, %d, %d, color=(%d,%d,%d,%.3f))\n",
@@ -2297,49 +2282,34 @@ _vte_draw_fill_rectangle (struct _vte_draw *draw,
color->red, color->green, color->blue,
alpha);
- cairo_set_operator (draw->cr, CAIRO_OPERATOR_OVER);
- cairo_rectangle (draw->cr, x, y, width, height);
- _vte_draw_set_source_color_alpha (draw, color, alpha);
- cairo_fill (draw->cr);
+ cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
+ cairo_rectangle(m_cr, x, y, width, height);
+ set_source_color_alpha(color, alpha);
+ cairo_fill (m_cr);
}
-
void
-_vte_draw_draw_line(struct _vte_draw *draw,
- gint x, gint y, gint xp, gint yp,
- int line_width,
- vte::color::rgb const *color, double alpha)
+DrawingContext::draw_line(int x,
+ int y,
+ int xp,
+ int yp,
+ int line_width,
+ vte::color::rgb const *color,
+ double alpha)
{
- _vte_draw_fill_rectangle(draw,
+ fill_rectangle(
x, y,
MAX(line_width, xp - x + 1), MAX(line_width, yp - y + 1),
color, alpha);
}
-static inline double
-_vte_draw_get_undercurl_rad(gint width)
-{
- return width / 2. / sqrt(2);
-}
-
-static inline double
-_vte_draw_get_undercurl_arc_height(gint width)
-{
- return _vte_draw_get_undercurl_rad(width) * (1. - sqrt(2) / 2.);
-}
-
-double
-_vte_draw_get_undercurl_height(gint width, double line_width)
-{
- return 2. * _vte_draw_get_undercurl_arc_height(width) + line_width;
-}
-
void
-_vte_draw_draw_undercurl(struct _vte_draw *draw,
- gint x, double y,
- double line_width,
- gint count,
- vte::color::rgb const *color, double alpha)
+DrawingContext::draw_undercurl(int x,
+ double y,
+ double line_width,
+ int count,
+ vte::color::rgb const *color,
+ double alpha)
{
/* The end of the curly line slightly overflows to the next cell, so the canvas
* caching the rendered look has to be wider not to chop this off. */
@@ -2347,7 +2317,7 @@ _vte_draw_draw_undercurl(struct _vte_draw *draw,
gint surface_top = y; /* floor */
- g_assert(draw->cr);
+ g_assert(m_cr);
_vte_debug_print (VTE_DEBUG_DRAW,
"draw_undercurl (x=%d, y=%f, count=%d, color=(%d,%d,%d,%.3f))\n",
@@ -2355,15 +2325,15 @@ _vte_draw_draw_undercurl(struct _vte_draw *draw,
color->red, color->green, color->blue,
alpha);
- if (G_UNLIKELY (draw->undercurl_surface == NULL)) {
+ if (G_UNLIKELY (!m_undercurl_surface)) {
/* Cache the undercurl's look. The design assumes that until the cached look is
* invalidated (the font is changed), this method is always called with the "y"
* parameter having the same fractional part, and the same "line_width" parameter.
* For caching, only the fractional part of "y" is used. */
cairo_t *undercurl_cr;
- double rad = _vte_draw_get_undercurl_rad(draw->cell_width);
- double y_bottom = y + _vte_draw_get_undercurl_height(draw->cell_width, line_width);
+ double rad = _vte_draw_get_undercurl_rad(m_cell_width);
+ double y_bottom = y + _vte_draw_get_undercurl_height(m_cell_width, line_width);
double y_center = (y + y_bottom) / 2.;
gint surface_bottom = y_bottom + 1; /* ceil, kind of */
@@ -2371,16 +2341,17 @@ _vte_draw_draw_undercurl(struct _vte_draw *draw,
"caching undercurl shape\n");
/* Add a line_width of margin horizontally on both sides, for nice antialias overflowing. */
- draw->undercurl_surface = cairo_surface_create_similar (cairo_get_target (draw->cr),
- CAIRO_CONTENT_ALPHA,
- draw->cell_width + 2 * x_padding,
- surface_bottom - surface_top);
- undercurl_cr = cairo_create (draw->undercurl_surface);
+ m_undercurl_surface = {cairo_surface_create_similar (cairo_get_target (m_cr),
+ CAIRO_CONTENT_ALPHA,
+ m_cell_width + 2 * x_padding,
+ surface_bottom - surface_top),
+ &cairo_surface_destroy};
+ undercurl_cr = cairo_create (m_undercurl_surface.get());
cairo_set_operator (undercurl_cr, CAIRO_OPERATOR_OVER);
/* First quarter circle, similar to the left half of the tilde symbol. */
- cairo_arc (undercurl_cr, x_padding + draw->cell_width / 4., y_center - surface_top +
draw->cell_width / 4., rad, M_PI * 5 / 4, M_PI * 7 / 4);
+ cairo_arc (undercurl_cr, x_padding + m_cell_width / 4., y_center - surface_top +
m_cell_width / 4., rad, M_PI * 5 / 4, M_PI * 7 / 4);
/* Second quarter circle, similar to the right half of the tilde symbol. */
- cairo_arc_negative (undercurl_cr, x_padding + draw->cell_width * 3 / 4., y_center -
surface_top - draw->cell_width / 4., rad, M_PI * 3 / 4, M_PI / 4);
+ cairo_arc_negative (undercurl_cr, x_padding + m_cell_width * 3 / 4., y_center - surface_top
- m_cell_width / 4., rad, M_PI * 3 / 4, M_PI / 4);
cairo_set_line_width (undercurl_cr, line_width);
cairo_stroke (undercurl_cr);
cairo_destroy (undercurl_cr);
@@ -2389,11 +2360,14 @@ _vte_draw_draw_undercurl(struct _vte_draw *draw,
/* Paint the cached look of the undercurl using the desired look.
* The cached look takes the fractional part of "y" into account,
* here we only offset by its integer part. */
- cairo_save (draw->cr);
- cairo_set_operator (draw->cr, CAIRO_OPERATOR_OVER);
- _vte_draw_set_source_color_alpha (draw, color, alpha);
+ cairo_save (m_cr);
+ cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER);
+ set_source_color_alpha(color, alpha);
for (int i = 0; i < count; i++) {
- cairo_mask_surface (draw->cr, draw->undercurl_surface, x - x_padding + i * draw->cell_width,
surface_top);
+ cairo_mask_surface(m_cr, m_undercurl_surface.get(), x - x_padding + i * m_cell_width,
surface_top);
}
- cairo_restore (draw->cr);
+ cairo_restore (m_cr);
}
+
+} // namespace view
+} // namespace vte
diff --git a/src/vtedraw.hh b/src/vtedraw.hh
index dc64b84d..a10c08c3 100644
--- a/src/vtedraw.hh
+++ b/src/vtedraw.hh
@@ -1,10 +1,11 @@
/*
* Copyright (C) 2003 Red Hat, Inc.
+ * Copyright © 2020 Christian Persch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,10 +17,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-/* The interfaces in this file are subject to change at any time. */
+#pragma once
-#ifndef vte_vtedraw_h_included
-#define vte_vtedraw_h_included
+#include <memory>
#include <glib.h>
#include <gtk/gtk.h>
@@ -27,16 +27,12 @@
#include "vteunistr.h"
#include "vtetypes.hh"
-G_BEGIN_DECLS
-
#define VTE_DRAW_OPAQUE (1.0)
#define VTE_DRAW_NORMAL 0
#define VTE_DRAW_BOLD 1
#define VTE_DRAW_ITALIC 2
-struct _vte_draw;
-
/* A request to draw a particular character spanning a given number of columns
at the given location. Unlike most APIs, (x,y) specifies the top-left
corner of the cell into which the character will be drawn instead of the
@@ -48,84 +44,284 @@ struct _vte_draw_text_request {
guint8 box_mirror : 1; /* Add box drawing chars to the set of mirrorable characters. */
};
-guint _vte_draw_get_style(gboolean bold, gboolean italic);
+struct font_info;
+
+namespace vte {
+namespace view {
+
+class DrawingContext {
+public:
+ DrawingContext() noexcept = default;
+ ~DrawingContext();
+
+ DrawingContext(DrawingContext const&) = delete;
+ DrawingContext(DrawingContext&&) = delete;
+ DrawingContext& operator=(DrawingContext const&) = delete;
+ DrawingContext& operator=(DrawingContext&&) = delete;
+
+ void set_cairo(cairo_t* cr) noexcept;
+
+ void clip(cairo_rectangle_int_t const* rect);
+ void unclip();
+
+ void clear(int x,
+ int y,
+ int width,
+ int height,
+ vte::color::rgb const* color,
+ double alpha);
+ void clear_font_cache();
+ void set_text_font(GtkWidget* widget,
+ PangoFontDescription const* fontdesc,
+ double cell_width_scale,
+ double cell_height_scale);
+ void get_text_metrics(int* cell_width,
+ int* cell_height,
+ int* char_ascent,
+ int* char_descent,
+ GtkBorder* char_spacing);
+ void get_char_edges(vteunistr c,
+ int columns,
+ guint style,
+ int* left,
+ int* right);
+ bool has_bold(guint style);
+
+ void draw_text(struct _vte_draw_text_request *requests,
+ gsize n_requests,
+ uint32_t attr,
+ vte::color::rgb const* color,
+ double alpha,
+ guint style);
+ bool draw_char(struct _vte_draw_text_request *request,
+ uint32_t attr,
+ vte::color::rgb const* color,
+ double alpha,
+ guint style);
+ bool has_char(vteunistr c,
+ guint style);
+ void fill_rectangle(int x,
+ int y,
+ int width,
+ int height,
+ vte::color::rgb const* color,
+ double alpha);
+ void draw_rectangle(int x,
+ int y,
+ int width,
+ int height,
+ vte::color::rgb const* color,
+ double alpha);
+ void draw_line(int x,
+ int y,
+ int xp,
+ int yp,
+ int line_width,
+ vte::color::rgb const *color,
+ double alpha);
+
+ void draw_undercurl(int x,
+ double y,
+ double line_width,
+ int count,
+ vte::color::rgb const* color,
+ double alpha);
+
+private:
+ void set_source_color_alpha (vte::color::rgb const* color,
+ double alpha);
+ void draw_graphic(vteunistr c,
+ uint32_t attr,
+ vte::color::rgb const* fg,
+ int x,
+ int y,
+ int font_width,
+ int columns,
+ int font_height);
+ void draw_text_internal(struct _vte_draw_text_request *requests,
+ gsize n_requests,
+ uint32_t attr,
+ vte::color::rgb const* color,
+ double alpha,
+ guint style);
+
+ struct font_info *m_fonts[4]{nullptr, nullptr, nullptr, nullptr};
+ int m_cell_width{1};
+ int m_cell_height{1};
+ GtkBorder m_char_spacing{1, 1, 1, 1};
+
+ cairo_t *m_cr{nullptr}; // unowned
+
+ /* Cache the undercurl's rendered look. */
+ std::unique_ptr<cairo_surface_t, decltype(&cairo_surface_destroy)> m_undercurl_surface{nullptr,
nullptr};
+};
+
+} // namespace view
+} // namespace vte
/* Create and destroy a draw structure. */
-struct _vte_draw *_vte_draw_new(void);
-void _vte_draw_free(struct _vte_draw *draw);
-
-void _vte_draw_set_cairo(struct _vte_draw *draw,
- cairo_t *cr);
-
-void _vte_draw_clip(struct _vte_draw *draw,
- cairo_rectangle_int_t const* rect);
-
-void _vte_draw_unclip(struct _vte_draw *draw);
-
-void _vte_draw_clear(struct _vte_draw *draw,
- gint x, gint y, gint width, gint height,
- vte::color::rgb const* color, double alpha);
-
-void _vte_draw_set_text_font(struct _vte_draw *draw,
- GtkWidget *widget,
- const PangoFontDescription *fontdesc,
- double cell_width_scale, double cell_height_scale);
-void _vte_draw_get_text_metrics(struct _vte_draw *draw,
- int *cell_width, int *cell_height,
- int *char_ascent, int *char_descent,
- GtkBorder *char_spacing);
-void _vte_draw_get_char_edges (struct _vte_draw *draw, vteunistr c, int columns, guint style,
- int *left, int *right);
-
-void _vte_draw_text(struct _vte_draw *draw,
- struct _vte_draw_text_request *requests, gsize n_requests,
- uint32_t attr,
- vte::color::rgb const* color, double alpha, guint style);
-gboolean _vte_draw_char(struct _vte_draw *draw,
- struct _vte_draw_text_request *request,
- uint32_t attr,
- vte::color::rgb const* color, double alpha, guint style);
-gboolean _vte_draw_has_char(struct _vte_draw *draw, vteunistr c, guint style);
-
-void _vte_draw_fill_rectangle(struct _vte_draw *draw,
- gint x, gint y, gint width, gint height,
- vte::color::rgb const* color, double alpha);
-void _vte_draw_draw_rectangle(struct _vte_draw *draw,
- gint x, gint y, gint width, gint height,
- vte::color::rgb const* color, double alpha);
-
-void _vte_draw_draw_line(struct _vte_draw *draw,
- gint x, gint y, gint xp, gint yp,
- int line_width,
- vte::color::rgb const *color, double alpha);
-double
-_vte_draw_get_undercurl_height(gint width, double line_width);
+static inline void _vte_draw_set_cairo(vte::view::DrawingContext& ctx,
+ cairo_t *cr)
+{
+ ctx.set_cairo(cr);
+}
+
+static inline void _vte_draw_clip(vte::view::DrawingContext& ctx,
+ cairo_rectangle_int_t const* rect)
+{
+ ctx.clip(rect);
+}
+
+static inline void _vte_draw_unclip(vte::view::DrawingContext& ctx)
+{
+ ctx.unclip();
+}
+
+static inline void _vte_draw_clear(vte::view::DrawingContext& ctx,
+ int x,
+ int y,
+ int width,
+ int height,
+ vte::color::rgb const* color,
+ double alpha)
+{
+ ctx.clear(x, y, width, height, color, alpha);
+}
+
+static inline void _vte_draw_clear_font_cache(vte::view::DrawingContext& ctx)
+{
+ ctx.clear_font_cache();
+}
+
+static inline void _vte_draw_set_text_font(vte::view::DrawingContext& ctx,
+ GtkWidget* widget,
+ PangoFontDescription const* fontdesc,
+ double cell_width_scale,
+ double cell_height_scale)
+{
+ ctx.set_text_font(widget, fontdesc, cell_width_scale, cell_height_scale);
+}
+
+static inline void _vte_draw_get_text_metrics(vte::view::DrawingContext& ctx,
+ int* cell_width,
+ int* cell_height,
+ int* char_ascent,
+ int* char_descent,
+ GtkBorder* char_spacing)
+{
+ ctx.get_text_metrics(cell_width, cell_height,
+ char_ascent, char_descent,
+ char_spacing);
+}
+
+static inline void _vte_draw_get_char_edges(vte::view::DrawingContext& ctx,
+ vteunistr c,
+ int columns,
+ guint style,
+ int* left,
+ int* right)
+{
+ ctx.get_char_edges(c, columns, style, left, right);
+}
+
+static inline gboolean _vte_draw_has_bold(vte::view::DrawingContext& ctx,
+ guint style)
+{
+ return ctx.has_bold(style);
+}
+
+static inline void _vte_draw_text(vte::view::DrawingContext& ctx,
+ struct _vte_draw_text_request *requests,
+ gsize n_requests,
+ uint32_t attr,
+ vte::color::rgb const* color,
+ double alpha,
+ guint style)
+{
+ ctx.draw_text(requests, n_requests, attr, color, alpha, style);
+}
-void
-_vte_draw_draw_undercurl(struct _vte_draw *draw,
- gint x, double y,
- double line_width,
- gint count,
- vte::color::rgb const *color, double alpha);
+static inline gboolean _vte_draw_char(vte::view::DrawingContext& ctx,
+ struct _vte_draw_text_request *request,
+ uint32_t attr,
+ vte::color::rgb const* color,
+ double alpha,
+ guint style)
+{
+ return ctx.draw_char(request, attr, color, alpha, style);
+}
-G_END_DECLS
+static inline gboolean _vte_draw_has_char(vte::view::DrawingContext& ctx,
+ vteunistr c,
+ guint style)
+{
+ return ctx.has_char(c, style);
+}
+
+static inline void _vte_draw_fill_rectangle(vte::view::DrawingContext& ctx,
+ int x,
+ int y,
+ int width,
+ int height,
+ vte::color::rgb const* color,
+ double alpha)
+{
+ ctx.fill_rectangle(x, y, width, height, color, alpha);
+}
+
+static inline void _vte_draw_draw_rectangle(vte::view::DrawingContext& ctx,
+ int x,
+ int y,
+ int width,
+ int height,
+ vte::color::rgb const* color,
+ double alpha)
+{
+ ctx.draw_rectangle(x, y, width, height, color, alpha);
+}
+
+static inline void _vte_draw_draw_line(vte::view::DrawingContext& ctx,
+ int x,
+ int y,
+ int xp,
+ int yp,
+ int line_width,
+ vte::color::rgb const *color,
+ double alpha)
+{
+ ctx.draw_line(x, y, xp, yp, line_width, color, alpha);
+}
+
+static inline void _vte_draw_draw_undercurl(vte::view::DrawingContext& ctx,
+ int x,
+ double y,
+ double line_width,
+ int count,
+ vte::color::rgb const* color,
+ double alpha)
+{
+ ctx.draw_undercurl(x, y, line_width, count, color, alpha);
+}
+
+guint _vte_draw_get_style(gboolean bold, gboolean italic);
+
+double
+_vte_draw_get_undercurl_height(gint width, double line_width);
class _vte_draw_autoclip_t {
private:
- struct _vte_draw* m_draw;
+ vte::view::DrawingContext& m_draw;
public:
- _vte_draw_autoclip_t(struct _vte_draw* draw,
+ _vte_draw_autoclip_t(vte::view::DrawingContext& draw,
cairo_rectangle_int_t const* rect)
: m_draw{draw}
{
- _vte_draw_clip(m_draw, rect);
+ m_draw.clip(rect);
}
~_vte_draw_autoclip_t()
{
- _vte_draw_unclip(m_draw);
+ m_draw.unclip();
}
};
-
-#endif
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index bfb7e5ed..2feb6460 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -889,10 +889,8 @@ public:
return int(m_overline_position + m_overline_thickness);
}
- /* Data used when rendering the text which reflects server resources
- * and data, which should be dropped when unrealizing and (re)created
- * when realizing. */
- struct _vte_draw *m_draw;
+ /* Data used when rendering */
+ vte::view::DrawingContext m_draw{};
bool m_clear_background{true};
VtePaletteColor m_palette[VTE_PALETTE_SIZE];
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]