When we invalidate a y_range using the common pattern of y==0 and
old_height==new_height, we are generally invalidating the entire buffer.
This short-circuits that case to just invalidate the buffer in a faster
and more complete form. The problem here appears to be that we can't
always calculate the ranges properly to invalidate because validation
has not run far enough.
If we have a y==-1 then we are generally invalidating the whole textview.
For this case, we can just discard the entire GtkTextLineDisplay cache.
Fixes#2975
Previously, with selection bounds, we could have a state where a line
display with selections set would eroniously stay in the cache. This
aggresively releases those at the boundary cases fixing deselection
drawing state.
We can avoid recreating a number of text nodes from render_para() on
sub-sequent runs if we cache the rendernode instead of just the
PangoLayout.
When used with GtkSourceMap, this can yield a ~7 FPS improvement during
smooth scrolling at the cost of some more memory.
This tries to estimate the number of visible rows in a textview based on
the default text size and then tunes the GtkTextLineDisplayCache to keep
3*n_rows entries in the cache.
This was found imperically to be near the right cache size. In most cases,
this is less than the number of items we cache now. However, in some cases,
such as the "overview map" from GtkSourceView, it allows us to reach a
higher value such as 1000+. This is needed to keep scrolling smooth on
the larger view sizes.
With this patch, a HiDPI system with a GtkSourceView and GtkSourceMap
from the GTK 4 port can perform smooth scrolling simultaneously.
We want to ensure all of the display cache entries are released in the
normal fashion before releasing the structures so that we can maintain
the invariant that cache_iter will always exist while in the cache.
This adds a GtkTextLineDisplayCache which can be used to cache a number
of GtkTextLineDisplay (and thus, PangoLayout) while displaying a view.
It uses a GSequence to track the position of the GtkTextLineDisplay
relative to each other, a MRU to cull the least recently used display,
and and a direct hashtable to lookup display by GtkTextLine.
We only cache lines that are to be displayed (!size_only). We may want to
either create a second collection of "size_only" lines to speed that up,
or determine that it is unnecessary (which is likely the case).