Zbigniew Jędrzejewski-Szmek 62fe94
From be5022138495d2e509735dec7486a040d3e2eb2d Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 62fe94
From: David Herrmann <dh.herrmann@gmail.com>
Zbigniew Jędrzejewski-Szmek 62fe94
Date: Thu, 2 Oct 2014 19:31:43 +0200
Zbigniew Jędrzejewski-Szmek 62fe94
Subject: [PATCH] terminal: add screen renderer
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
We don't want to expose the term_screen internals for rendering.
Zbigniew Jędrzejewski-Szmek 62fe94
Therefore, provide an iterator that allows external renderers to draw
Zbigniew Jędrzejewski-Szmek 62fe94
terminals.
Zbigniew Jędrzejewski-Szmek 62fe94
---
Zbigniew Jędrzejewski-Szmek 62fe94
 src/libsystemd-terminal/term-screen.c | 66 +++++++++++++++++++++++++++++++++++
Zbigniew Jędrzejewski-Szmek 62fe94
 src/libsystemd-terminal/term.h        | 12 +++++++
Zbigniew Jędrzejewski-Szmek 62fe94
 2 files changed, 78 insertions(+)
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/libsystemd-terminal/term-screen.c b/src/libsystemd-terminal/term-screen.c
Zbigniew Jędrzejewski-Szmek 62fe94
index 2f3f6f91cb..b442b96050 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/libsystemd-terminal/term-screen.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/libsystemd-terminal/term-screen.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -3892,3 +3892,69 @@ int term_screen_set_answerback(term_screen *screen, const char *answerback) {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int term_screen_draw(term_screen *screen,
Zbigniew Jędrzejewski-Szmek 62fe94
+                     int (*draw_fn) (term_screen *screen,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     void *userdata,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     unsigned int x,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     unsigned int y,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     const term_attr *attr,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     const uint32_t *ch,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     size_t n_ch,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     unsigned int ch_width),
Zbigniew Jędrzejewski-Szmek 62fe94
+                     void *userdata,
Zbigniew Jędrzejewski-Szmek 62fe94
+                     uint64_t *fb_age) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        uint64_t cell_age, line_age, age = 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+        term_charbuf_t ch_buf;
Zbigniew Jędrzejewski-Szmek 62fe94
+        const uint32_t *ch_str;
Zbigniew Jędrzejewski-Szmek 62fe94
+        unsigned int i, j, cw;
Zbigniew Jędrzejewski-Szmek 62fe94
+        term_page *page;
Zbigniew Jędrzejewski-Szmek 62fe94
+        term_line *line;
Zbigniew Jędrzejewski-Szmek 62fe94
+        term_cell *cell;
Zbigniew Jędrzejewski-Szmek 62fe94
+        size_t ch_n;
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(screen);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(draw_fn);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (fb_age)
Zbigniew Jędrzejewski-Szmek 62fe94
+                age = *fb_age;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        page = screen->page;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        for (j = 0; j < page->height; ++j) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                line = page->lines[j];
Zbigniew Jędrzejewski-Szmek 62fe94
+                line_age = MAX(line->age, page->age);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                for (i = 0; i < page->width; ++i) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        cell = &line->cells[i];
Zbigniew Jędrzejewski-Szmek 62fe94
+                        cell_age = MAX(cell->age, line_age);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (age != 0 && cell_age <= age)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                continue;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                        ch_str = term_char_resolve(cell->ch, &ch_n, &ch_buf);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                        /* Character-width of 0 is used for cleared cells.
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * Always treat this as single-cell character, so
Zbigniew Jędrzejewski-Szmek 62fe94
+                         * renderers can assume ch_width is set properpy. */
Zbigniew Jędrzejewski-Szmek 62fe94
+                        cw = MAX(cell->cwidth, 1U);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                        r = draw_fn(screen,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                    userdata,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                    i,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                    j,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                    &cell->attr,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                    ch_str,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                    ch_n,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                    cw);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (r != 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                return r;
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (fb_age)
Zbigniew Jędrzejewski-Szmek 62fe94
+                *fb_age = screen->age++;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/libsystemd-terminal/term.h b/src/libsystemd-terminal/term.h
Zbigniew Jędrzejewski-Szmek 62fe94
index d5b934fc59..a3ca252e31 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/libsystemd-terminal/term.h
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/libsystemd-terminal/term.h
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -147,3 +147,15 @@ void term_screen_soft_reset(term_screen *screen);
Zbigniew Jędrzejewski-Szmek 62fe94
 void term_screen_hard_reset(term_screen *screen);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 int term_screen_set_answerback(term_screen *screen, const char *answerback);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int term_screen_draw(term_screen *screen,
Zbigniew Jędrzejewski-Szmek 62fe94
+                     int (*draw_fn) (term_screen *screen,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     void *userdata,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     unsigned int x,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     unsigned int y,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     const term_attr *attr,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     const uint32_t *ch,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     size_t n_ch,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                     unsigned int ch_width),
Zbigniew Jędrzejewski-Szmek 62fe94
+                     void *userdata,
Zbigniew Jędrzejewski-Szmek 62fe94
+                     uint64_t *fb_age);