Skip to content

Commit c492102

Browse files
mattnchrisbra
authored andcommitted
patch 9.2.0311: redrawing logic with text properties can be improved
Problem: redrawing logic with text properties can be improved in win_line() Solution: Avoid repeated sorts, use stack storage for small properties, pre-compute whether trailing virtual text follows (Yasuhiro Matsumoto) closes: #19880 Signed-off-by: Yasuhiro Matsumoto <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent f9981bb commit c492102

2 files changed

Lines changed: 78 additions & 24 deletions

File tree

src/drawline.c

Lines changed: 76 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,13 +1213,19 @@ win_line(
12131213
int save_did_emsg;
12141214
#endif
12151215
#ifdef FEAT_PROP_POPUP
1216+
# define WIN_LINE_TEXT_PROP_STACK_LEN 32
12161217
int did_line = FALSE; // set to TRUE when line text done
12171218
int text_prop_count;
12181219
int last_textprop_text_idx = -1;
12191220
int text_prop_next = 0; // next text property to use
1221+
textprop_T text_props_buf[WIN_LINE_TEXT_PROP_STACK_LEN];
1222+
int text_prop_idxs_buf[WIN_LINE_TEXT_PROP_STACK_LEN];
1223+
char_u text_prop_suffix_flags_buf[WIN_LINE_TEXT_PROP_STACK_LEN + 1];
12201224
textprop_T *text_props = NULL;
12211225
int *text_prop_idxs = NULL;
1226+
char_u *text_prop_suffix_flags = NULL;
12221227
int text_props_active = 0;
1228+
int text_props_need_sort = FALSE;
12231229
proptype_T *text_prop_type = NULL;
12241230
int text_prop_attr = 0;
12251231
int text_prop_attr_comb = 0; // text_prop_attr combined with
@@ -1694,15 +1700,40 @@ win_line(
16941700
{
16951701
// Make a copy of the properties, so that they are properly
16961702
// aligned.
1697-
text_props = ALLOC_MULT(textprop_T, text_prop_count);
1703+
if (text_prop_count <= WIN_LINE_TEXT_PROP_STACK_LEN)
1704+
text_props = text_props_buf;
1705+
else
1706+
text_props = ALLOC_MULT(textprop_T, text_prop_count);
16981707
if (text_props != NULL)
16991708
mch_memmove(text_props, prop_start,
17001709
text_prop_count * sizeof(textprop_T));
17011710

17021711
// Allocate an array for the indexes.
1703-
text_prop_idxs = ALLOC_MULT(int, text_prop_count);
1712+
if (text_prop_count <= WIN_LINE_TEXT_PROP_STACK_LEN)
1713+
text_prop_idxs = text_prop_idxs_buf;
1714+
else
1715+
text_prop_idxs = ALLOC_MULT(int, text_prop_count);
17041716
if (text_prop_idxs == NULL)
1705-
VIM_CLEAR(text_props);
1717+
{
1718+
if (text_props != text_props_buf)
1719+
VIM_CLEAR(text_props);
1720+
else
1721+
text_props = NULL;
1722+
}
1723+
if (text_prop_count <= WIN_LINE_TEXT_PROP_STACK_LEN)
1724+
text_prop_suffix_flags = text_prop_suffix_flags_buf;
1725+
else
1726+
text_prop_suffix_flags = ALLOC_MULT(char_u, text_prop_count + 1);
1727+
if (text_prop_suffix_flags == NULL)
1728+
{
1729+
if (text_prop_idxs != text_prop_idxs_buf)
1730+
vim_free(text_prop_idxs);
1731+
text_prop_idxs = NULL;
1732+
if (text_props != text_props_buf)
1733+
VIM_CLEAR(text_props);
1734+
else
1735+
text_props = NULL;
1736+
}
17061737

17071738
if (text_props != NULL)
17081739
{
@@ -1736,6 +1767,20 @@ win_line(
17361767
else
17371768
++wlv.text_prop_above_count;
17381769
}
1770+
1771+
text_prop_suffix_flags[text_prop_count] = 0;
1772+
for (int i = text_prop_count - 1; i >= 0; --i)
1773+
{
1774+
int flags = text_prop_suffix_flags[i + 1];
1775+
1776+
if (text_props[i].tp_col == MAXCOL)
1777+
{
1778+
flags |= 1;
1779+
if (text_props[i].tp_flags & TP_FLAG_ALIGN_BELOW)
1780+
flags |= 2;
1781+
}
1782+
text_prop_suffix_flags[i] = flags;
1783+
}
17391784
}
17401785
}
17411786

@@ -1745,8 +1790,12 @@ win_line(
17451790
wlv.row += wlv.text_prop_above_count;
17461791
if (wlv.row >= endrow)
17471792
{
1748-
vim_free(text_props);
1749-
vim_free(text_prop_idxs);
1793+
if (text_props != text_props_buf)
1794+
vim_free(text_props);
1795+
if (text_prop_idxs != text_prop_idxs_buf)
1796+
vim_free(text_prop_idxs);
1797+
if (text_prop_suffix_flags != text_prop_suffix_flags_buf)
1798+
vim_free(text_prop_suffix_flags);
17501799
return wlv.row;
17511800
}
17521801
wlv.screen_row += wlv.text_prop_above_count;
@@ -2122,6 +2171,7 @@ win_line(
21222171
sizeof(int)
21232172
* (text_props_active - (pi + 1)));
21242173
--text_props_active;
2174+
text_props_need_sort = TRUE;
21252175
--pi;
21262176
# ifdef FEAT_LINEBREAK
21272177
// not exactly right but should work in most cases
@@ -2164,7 +2214,10 @@ win_line(
21642214
}
21652215

21662216
if (active)
2217+
{
21672218
text_prop_idxs[text_props_active++] = text_prop_next;
2219+
text_props_need_sort = TRUE;
2220+
}
21682221
++text_prop_next;
21692222
}
21702223

@@ -2190,10 +2243,14 @@ win_line(
21902243
text_prop_above = FALSE;
21912244
text_prop_follows = FALSE;
21922245

2193-
// Sort the properties on priority and/or starting last.
2194-
// Then combine the attributes, highest priority last.
2195-
sort_text_props(wp->w_buffer, text_props,
2196-
text_prop_idxs, text_props_active);
2246+
if (text_props_need_sort)
2247+
{
2248+
// The active set only changes when a property starts
2249+
// or ends, so avoid sorting again for every column.
2250+
sort_text_props(wp->w_buffer, text_props,
2251+
text_prop_idxs, text_props_active);
2252+
text_props_need_sort = FALSE;
2253+
}
21972254

21982255
for (pi = 0; pi < text_props_active; ++pi)
21992256
{
@@ -2402,19 +2459,10 @@ win_line(
24022459
// Or when not wrapping and at the rightmost column.
24032460

24042461
int only_below_follows = !wp->w_p_wrap && wlv.col == wp->w_width - 1;
2405-
// TODO: Store "after"/"right"/"below" text properties in order
2406-
// in the buffer so only `text_props[text_prop_count - 1]`
2407-
// needs to be checked for following "below" virtual text
2408-
for (int i = text_prop_next; i < text_prop_count; ++i)
2409-
{
2410-
if (text_props[i].tp_col == MAXCOL
2411-
&& (!only_below_follows
2412-
|| (text_props[i].tp_flags & TP_FLAG_ALIGN_BELOW)))
2413-
{
2414-
text_prop_follows = TRUE;
2415-
break;
2416-
}
2417-
}
2462+
int suffix_flags = text_prop_suffix_flags[text_prop_next];
2463+
2464+
text_prop_follows = (suffix_flags
2465+
& (only_below_follows ? 2 : 1)) != 0;
24182466
}
24192467
}
24202468

@@ -4500,8 +4548,12 @@ win_line(
45004548

45014549
} // for every character in the line
45024550
#ifdef FEAT_PROP_POPUP
4503-
vim_free(text_props);
4504-
vim_free(text_prop_idxs);
4551+
if (text_props != text_props_buf)
4552+
vim_free(text_props);
4553+
if (text_prop_idxs != text_prop_idxs_buf)
4554+
vim_free(text_prop_idxs);
4555+
if (text_prop_suffix_flags != text_prop_suffix_flags_buf)
4556+
vim_free(text_prop_suffix_flags);
45054557
vim_free(p_extra_free2);
45064558
#endif
45074559

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,8 @@ static char *(features[]) =
734734

735735
static int included_patches[] =
736736
{ /* Add new patch number below this line */
737+
/**/
738+
311,
737739
/**/
738740
310,
739741
/**/

0 commit comments

Comments
 (0)