]> git.neil.brown.name Git - edlib.git/commitdiff
lib-renderline: only measure line when needed
authorNeilBrown <neil@brown.name>
Wed, 16 Aug 2023 21:59:35 +0000 (07:59 +1000)
committerNeilBrown <neil@brown.name>
Wed, 16 Aug 2023 22:40:10 +0000 (08:40 +1000)
Before performing measure_line work, check if any of the inputs have
changed.

Signed-off-by: NeilBrown <neil@brown.name>
DOC/TODO.md
lib-renderline.c

index b830f219b56c6fc1c712839c94d55f100abb6169..08aacccbbf9a948a20a3f0c8492fc9df436b91de 100644 (file)
@@ -10,6 +10,8 @@ the file.
 ### Triage
 
 
+- [ ] in xcb, find-file draws result a pixel high, then moves done
+      when cursor moves
 - [ ] favourites...  I want some favourite documents that are easy to
       find, favourite directories, favourite make or shell commands.
       Maybe that are found by moving "down" in history?  Maybe alt-*
@@ -29,7 +31,7 @@ the file.
 - [X] resolve fixme around wrap_margin when splitting
 - [X] resolve fixme reguarding margin in find_curs
 - [X] search "\brl([123]*|end)\b" replace "ri\1" does rlend -> rirlend
-- [ ] when should lib-renderline call measure_line? Only when asked?
+- [X] when should lib-renderline call measure_line? Only when asked?
       Or whenever content, width, scale change?
 - [ ] When is left_margin used?  Can I use it for hanging indent?  If
       not, how do I do that?  Can I tab out, set margin, tab back for
index 14a983654cba1794ad30e4dbc0233972c67fa30f..d7889b64fd9ae37d6db71118c1a0763123b2c92d 100644 (file)
@@ -130,6 +130,10 @@ struct rline_data {
        bool            image;
        int             curspos;
 
+       /* These used to check is measuring is needed, or to record
+        * results of last measurement */
+       unsigned short measure_width, measure_height;
+       short measure_offset, measure_shift_left;
        struct render_item *content;
 };
 #include "core-pane.h"
@@ -313,6 +317,7 @@ static void parse_line(struct rline_data *rd safe)
 
        ri = rd->content;
        rd->content = NULL;
+       rd->measure_width = 0; // force re-measure
        while (ri) {
                struct render_item *r = ri;
                ri = r->next;
@@ -603,8 +608,9 @@ static bool measure_line(struct pane *p safe, struct pane *focus safe, int offse
        int shift_left = pane_attr_get_int(focus, "shift_left", 0);
        bool wrap = shift_left < 0;
        int wrap_margin;
-       int right_margin = p->w - (rd->right_margin * rd->scale / 1000);
-       int left_margin = rd->left_margin * rd->scale / 1000;
+       int right_margin;
+       int left_margin;
+       struct xy xyscale = pane_scale(focus);
        int xdiff, ydiff;
        struct call_return cr;
        int x, y;
@@ -613,6 +619,24 @@ static bool measure_line(struct pane *p safe, struct pane *focus safe, int offse
 
        if (!rd->content)
                return eop;
+       if (xyscale.x == rd->scale && p->w == rd->measure_width &&
+           shift_left == rd->measure_shift_left &&
+           offset == rd->measure_offset) {
+               /* No change */
+               for (ri = rd->content ; ri ; ri = ri->next)
+                       if (ri->eol && rd->line[ri->start] == '\f')
+                               eop = True;
+               pane_resize(p, p->x, p->y, p->w, rd->measure_height);
+               return eop;
+       }
+       rd->scale = xyscale.x;
+       rd->measure_width = p->w;
+       rd->measure_offset = offset;
+       rd->measure_shift_left = shift_left;
+
+       right_margin = p->w - (rd->right_margin * rd->scale / 1000);
+       left_margin = rd->left_margin * rd->scale / 1000;
+
        cr = measure_str(p, "M", "");
        rd->curs_width = cr.x;
        rd->line_height = cr.y;
@@ -847,9 +871,10 @@ static bool measure_line(struct pane *p safe, struct pane *focus safe, int offse
        }
        /* We add rd->line_height for the EOL, whether a NL is present of not */
        ydiff += rd->line_height;
-       pane_resize(p, p->x, p->y, p->w,
-                   (rd->space_above + rd->space_below) * rd->scale / 1000 +
-                   ydiff);
+       rd->measure_height =
+               (rd->space_above + rd->space_below) * rd->scale / 1000 +
+               ydiff;
+       pane_resize(p, p->x, p->y, p->w, rd->measure_height);
        attr_set_int(&p->attrs, "line-height", rd->line_height);
        return eop;
 }
@@ -1047,7 +1072,7 @@ static void parse_map(const char *map safe, short *rowsp safe, short *colsp safe
 
 static int render_image(struct pane *p safe, struct pane *focus safe,
                        const char *line safe,
-                       int dodraw, int scale,
+                       int dodraw,
                        int offset, int want_xypos, short x, short y)
 {
        char *fname = NULL;
@@ -1056,6 +1081,8 @@ static int render_image(struct pane *p safe, struct pane *focus safe,
        short rows = -1, cols = -1;
        int map_offset = 0;
        int ioffset;
+       struct xy xyscale = pane_scale(focus);
+       int scale = xyscale.x;
        char *ssize = attr_find(p->attrs, "cached-size");
        struct xy size= {-1, -1};
 
@@ -1176,7 +1203,7 @@ DEF_CMD(renderline_draw)
 
        if (rd->image)
                render_image(ci->home, ci->focus, rd->line, True,
-                            rd->scale, offset, False, 0, 0);
+                            offset, False, 0, 0);
        else
                draw_line(ci->home, ci->focus, offset);
 
@@ -1197,7 +1224,7 @@ DEF_CMD(renderline_refresh)
                offset = rd->prefix_bytes + rd->curspos;
        if (rd->image)
                render_image(ci->home, ci->focus, rd->line, True,
-                            rd->scale, offset, False, 0, 0);
+                            offset, False, 0, 0);
        else {
                measure_line(ci->home, ci->focus, offset);
                draw_line(ci->home, ci->focus, offset);
@@ -1211,7 +1238,7 @@ DEF_CMD(renderline_measure)
        bool end_of_page;
        if (rd->image)
                return render_image(ci->home, ci->focus, rd->line,
-                                   False, rd->scale, ci->num, False, 0, 0);
+                                   False, ci->num, False, 0, 0);
 
        end_of_page = measure_line(ci->home, ci->focus,
                                   ci->num < 0 ? -1 : rd->prefix_bytes + ci->num);
@@ -1241,7 +1268,7 @@ DEF_CMD(renderline_findxy)
 
        if (rd->image)
                return render_image(ci->home, ci->focus, rd->line,
-                                   False, rd->scale, -1, True,
+                                   False, -1, True,
                                    ci->x, ci->y);
 
        measure_line(ci->home, ci->focus,
@@ -1315,7 +1342,6 @@ DEF_CMD(renderline_set)
 {
        struct rline_data *rd = &ci->home->data;
        const char *old = rd->line;
-       struct xy xyscale = pane_scale(ci->focus);
        char *prefix = pane_attr_get(ci->focus, "prefix");
        bool word_wrap = pane_attr_get_int(ci->focus, "word-wrap", 0) != 0;
 
@@ -1333,11 +1359,9 @@ DEF_CMD(renderline_set)
 
        rd->curspos = ci->num;
        if (strcmp(rd->line, old) != 0 ||
-           (old && xyscale.x != rd->scale) ||
            (old && word_wrap != rd->word_wrap)) {
                pane_damaged(ci->home, DAMAGED_REFRESH);
                pane_damaged(ci->home->parent, DAMAGED_REFRESH);
-               rd->scale = xyscale.x;
                rd->word_wrap = word_wrap;
                parse_line(rd);
        }
@@ -1378,7 +1402,7 @@ DEF_CMD(renderline_attach)
        if (!p)
                return Efail;
        rd = &p->data;
-       rd->line = strdup("");
+       rd->line = strdup(ETX); // Imposible string
 
        return comm_call(ci->comm2, "cb", p);
 }