From e0b9b51e9f2f744c3ab517083579b567ac1d3fca Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Tue, 23 Jul 2019 14:52:14 -0700 Subject: [PATCH 1/2] textlayout: make GtkTextLineDisplay reference counted This makes GtkTextLineDisplay use GRcBox instead of g_slice_* directly. By using reference counting for this structure, we can ensure that we hold an extra ref for one_display_cache as well as caching additional GtkTextLineDisplay for the visible range in the future. --- gtk/gtktextlayout.c | 62 ++++++++++++++++++++------------------ gtk/gtktextlayoutprivate.h | 2 ++ 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index 6974353b7c..f150c927fa 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -197,12 +197,7 @@ gtk_text_layout_dispose (GObject *object) g_clear_object (&layout->ltr_context); g_clear_object (&layout->rtl_context); - if (layout->one_display_cache) - { - GtkTextLineDisplay *tmp_display = layout->one_display_cache; - layout->one_display_cache = NULL; - gtk_text_layout_free_line_display (layout, tmp_display); - } + g_clear_pointer (&layout->one_display_cache, gtk_text_line_display_unref); if (layout->preedit_attrs != NULL) { @@ -826,20 +821,17 @@ gtk_text_layout_invalidate_cache (GtkTextLayout *layout, { if (layout->one_display_cache && line == layout->one_display_cache->line) { - GtkTextLineDisplay *display = layout->one_display_cache; - if (cursors_only) { - if (display->cursors) - g_array_free (display->cursors, TRUE); - display->cursors = NULL; + GtkTextLineDisplay *display = layout->one_display_cache; + + g_clear_pointer (&display->cursors, g_array_unref); display->cursors_invalid = TRUE; display->has_block_cursor = FALSE; } else { - layout->one_display_cache = NULL; - gtk_text_layout_free_line_display (layout, display); + g_clear_pointer (&layout->one_display_cache, gtk_text_line_display_unref); } } } @@ -2287,19 +2279,17 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, { if (!size_only) update_text_display_cursors (layout, line, layout->one_display_cache); - return layout->one_display_cache; + return gtk_text_line_display_ref (layout->one_display_cache); } else { - GtkTextLineDisplay *tmp_display = layout->one_display_cache; - layout->one_display_cache = NULL; - gtk_text_layout_free_line_display (layout, tmp_display); + g_clear_pointer (&layout->one_display_cache, gtk_text_line_display_unref); } } DV (g_print ("creating one line display cache (%s)\n", G_STRLOC)); - display = g_slice_new0 (GtkTextLineDisplay); + display = g_rc_box_new0 (GtkTextLineDisplay); display->size_only = size_only; display->line = line; @@ -2619,7 +2609,9 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, if (tags != NULL) g_ptr_array_free (tags, TRUE); - layout->one_display_cache = display; + g_assert (layout->one_display_cache == NULL); + + layout->one_display_cache = gtk_text_line_display_ref (display); if (saw_widget) allocate_child_widgets (layout, display); @@ -2627,20 +2619,32 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout, return display; } +static void +gtk_text_line_display_finalize (GtkTextLineDisplay *display) +{ + g_clear_object (&display->layout); + g_clear_pointer (&display->cursors, g_array_unref); +} + +GtkTextLineDisplay * +gtk_text_line_display_ref (GtkTextLineDisplay *display) +{ + return g_rc_box_acquire (display); +} + +void +gtk_text_line_display_unref (GtkTextLineDisplay *display) +{ + g_rc_box_release_full (display, (GDestroyNotify)gtk_text_line_display_finalize); +} + +/* For compat until we switch away from this */ void gtk_text_layout_free_line_display (GtkTextLayout *layout, GtkTextLineDisplay *display) { - if (display != layout->one_display_cache) - { - if (display->layout) - g_object_unref (display->layout); - - if (display->cursors) - g_array_free (display->cursors, TRUE); - - g_slice_free (GtkTextLineDisplay, display); - } + if (display != NULL) + gtk_text_line_display_unref (display); } /* Functions to convert iter <=> index for the line of a GtkTextLineDisplay diff --git a/gtk/gtktextlayoutprivate.h b/gtk/gtktextlayoutprivate.h index 7aff2074ff..366fbb86c8 100644 --- a/gtk/gtktextlayoutprivate.h +++ b/gtk/gtktextlayoutprivate.h @@ -300,6 +300,8 @@ GtkTextLineDisplay* gtk_text_layout_get_line_display (GtkTextLayout *layou gboolean size_only); void gtk_text_layout_free_line_display (GtkTextLayout *layout, GtkTextLineDisplay *display); +GtkTextLineDisplay *gtk_text_line_display_ref (GtkTextLineDisplay *display); +void gtk_text_line_display_unref (GtkTextLineDisplay *display); void gtk_text_layout_get_line_at_y (GtkTextLayout *layout, GtkTextIter *target_iter, From 02d8e95b73aadf0f28e1e285810860f9ac423c6e Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Tue, 23 Jul 2019 14:59:40 -0700 Subject: [PATCH 2/2] textlayout: remove use of gtk_text_layout_free_line_display Now that these are reference counted, we no longer need to use the variant requiring access to the GtkTextLayout. --- gtk/gtktextlayout.c | 47 +++++++++++++++----------------------- gtk/gtktextlayoutprivate.h | 2 -- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index f150c927fa..08c511ec33 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -1182,7 +1182,7 @@ gtk_text_layout_real_wrap (GtkTextLayout *layout, pango_layout_get_pixel_extents (display->layout, &ink_rect, &logical_rect); line_data->top_ink = MAX (0, logical_rect.x - ink_rect.x); line_data->bottom_ink = MAX (0, logical_rect.x + logical_rect.width - ink_rect.x - ink_rect.width); - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); return line_data; } @@ -2638,15 +2638,6 @@ gtk_text_line_display_unref (GtkTextLineDisplay *display) g_rc_box_release_full (display, (GDestroyNotify)gtk_text_line_display_finalize); } -/* For compat until we switch away from this */ -void -gtk_text_layout_free_line_display (GtkTextLayout *layout, - GtkTextLineDisplay *display) -{ - if (display != NULL) - gtk_text_line_display_unref (display); -} - /* Functions to convert iter <=> index for the line of a GtkTextLineDisplay * taking into account the preedit string and invisible text if necessary. */ @@ -2820,7 +2811,7 @@ gtk_text_layout_get_iter_at_position (GtkTextLayout *layout, line_display_index_to_iter (layout, display, target_iter, byte_index, 0); - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); return inside; } @@ -2893,7 +2884,7 @@ gtk_text_layout_get_cursor_locations (GtkTextLayout *layout, weak_pos->height = pango_weak_pos.height / PANGO_SCALE; } - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); } /** @@ -2952,7 +2943,8 @@ _gtk_text_layout_get_block_cursor (GtkTextLayout *layout, pos->y += line_top + display->top_margin; } - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); + return block; } @@ -3028,7 +3020,7 @@ gtk_text_layout_get_iter_location (GtkTextLayout *layout, rect->width = PANGO_PIXELS (pango_rect.width); rect->height = PANGO_PIXELS (pango_rect.height); - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); } /* FFIXX */ @@ -3089,7 +3081,7 @@ find_display_line_below (GtkTextLayout *layout, pango_layout_iter_free (layout_iter); line_top += display->bottom_margin; - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); next = _gtk_text_line_next_excluding_last (line); if (!next) @@ -3160,7 +3152,7 @@ find_display_line_above (GtkTextLayout *layout, pango_layout_iter_free (layout_iter); - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); line = _gtk_text_line_previous (line); } @@ -3264,7 +3256,7 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout, goto out; } - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); line = prev_line; display = gtk_text_layout_get_line_display (layout, prev_line, FALSE); @@ -3291,7 +3283,7 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout, while (prev_line) { - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); display = gtk_text_layout_get_line_display (layout, prev_line, FALSE); @@ -3331,7 +3323,7 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout, out: - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); return !gtk_text_iter_equal (iter, &orig) && @@ -3402,7 +3394,7 @@ gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout, next: - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); line = _gtk_text_line_next_excluding_last (line); } @@ -3468,7 +3460,7 @@ gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout, tmp_list = tmp_list->next; } - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); return !gtk_text_iter_equal (iter, &orig) && @@ -3510,7 +3502,7 @@ gtk_text_layout_iter_starts_line (GtkTextLayout *layout, /* We're located on this line or the para delimiters before * it */ - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); if (line_byte == layout_line->start_index) return TRUE; @@ -3591,7 +3583,7 @@ gtk_text_layout_move_iter_to_x (GtkTextLayout *layout, pango_layout_iter_free (layout_iter); - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); } /** @@ -3686,7 +3678,7 @@ gtk_text_layout_move_iter_visually (GtkTextLayout *layout, } while (totally_invisible_line (layout, line, &lineiter)); - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); display = gtk_text_layout_get_line_display (layout, line, FALSE); gtk_text_iter_forward_to_line_end (&lineiter); new_index = gtk_text_iter_get_visible_line_index (&lineiter); @@ -3701,7 +3693,7 @@ gtk_text_layout_move_iter_visually (GtkTextLayout *layout, } while (totally_invisible_line (layout, line, &lineiter)); - gtk_text_layout_free_line_display (layout, display); + gtk_text_line_display_unref (display); display = gtk_text_layout_get_line_display (layout, line, FALSE); new_index = 0; } @@ -3711,8 +3703,7 @@ gtk_text_layout_move_iter_visually (GtkTextLayout *layout, gtk_text_iter_backward_char (iter); } - if (display) - gtk_text_layout_free_line_display (layout, display); + g_clear_pointer (&display, gtk_text_line_display_unref); done: @@ -4119,7 +4110,7 @@ gtk_text_layout_snapshot (GtkTextLayout *layout, offset_y += line_display->height; - gtk_text_layout_free_line_display (layout, line_display); + gtk_text_line_display_unref (line_display); tmp_list = tmp_list->next; } diff --git a/gtk/gtktextlayoutprivate.h b/gtk/gtktextlayoutprivate.h index 366fbb86c8..7905d2b542 100644 --- a/gtk/gtktextlayoutprivate.h +++ b/gtk/gtktextlayoutprivate.h @@ -298,8 +298,6 @@ void gtk_text_layout_wrap_loop_end (GtkTextLayout *layout); GtkTextLineDisplay* gtk_text_layout_get_line_display (GtkTextLayout *layout, GtkTextLine *line, gboolean size_only); -void gtk_text_layout_free_line_display (GtkTextLayout *layout, - GtkTextLineDisplay *display); GtkTextLineDisplay *gtk_text_line_display_ref (GtkTextLineDisplay *display); void gtk_text_line_display_unref (GtkTextLineDisplay *display);