Browse Source

constrain and scroll rendered text

Thomas Buck 11 months ago
parent
commit
3162df3c2d
4 changed files with 57 additions and 28 deletions
  1. 7
    2
      include/text.h
  2. 6
    0
      src/lcd.c
  3. 5
    1
      src/menu.c
  4. 39
    25
      src/text.c

+ 7
- 2
include/text.h View File

@@ -34,6 +34,7 @@ struct text_conf {
34 34
     const char *text;
35 35
     int x;
36 36
     int y;
37
+    int y_text_off;
37 38
     bool justify;
38 39
     enum mf_align_t alignment;
39 40
     int width;
@@ -46,8 +47,12 @@ struct text_conf {
46 47
 };
47 48
 
48 49
 void text_prepare_font(struct text_font *tf);
49
-void text_draw(struct text_conf *tc);
50
+int16_t text_draw(struct text_conf *tc);
50 51
 
51
-void text_box(const char *s, bool centered);
52
+int16_t text_box(const char *s, bool centered,
53
+                 const char *fontname,
54
+                 uint16_t x_off, uint16_t width,
55
+                 uint16_t y_off, uint16_t height,
56
+                 int16_t y_text_off);
52 57
 
53 58
 #endif // __TEXT_H__

+ 6
- 0
src/lcd.c View File

@@ -279,6 +279,12 @@ void lcd_write_rect(uint16_t left, uint16_t top, uint16_t right, uint16_t bottom
279 279
     if (bottom >= ST7789_PICO_COLUMN) {
280 280
         bottom = ST7789_PICO_COLUMN - 1;
281 281
     }
282
+    if (top >= bottom) {
283
+        return;
284
+    }
285
+    if (left >= right) {
286
+        return;
287
+    }
282 288
     //                 handle,       left,         top,      right,    bottom, color);
283 289
     st7789_fill_rect(&gs_handle, 240 - bottom - 1, left, 240 - top - 1, right, color);
284 290
 }

+ 5
- 1
src/menu.c View File

@@ -137,6 +137,10 @@ void menu_run(void (*draw)(struct menu_state *), bool centered) {
137 137
 
138 138
     if (strncmp(menu.buff, prev_buff, MENU_MAX_LEN) != 0) {
139 139
         strncpy(prev_buff, menu.buff, MENU_MAX_LEN);
140
-        text_box(menu.buff, centered);
140
+        text_box(menu.buff, centered,
141
+                 "fixed_10x20",
142
+                 0, LCD_WIDTH,
143
+                 50, (MENU_MAX_LINES * 20) + ((MENU_MAX_LINES - 1) * 2),
144
+                 0);
141 145
     }
142 146
 }

+ 39
- 25
src/text.c View File

@@ -16,6 +16,8 @@
16 16
  * See <http://www.gnu.org/licenses/>.
17 17
  */
18 18
 
19
+#include <string.h>
20
+
19 21
 #include "config.h"
20 22
 #include "log.h"
21 23
 #include "lcd.h"
@@ -25,6 +27,7 @@
25 27
 typedef struct {
26 28
     struct text_conf *options;
27 29
     uint16_t anchor;
30
+    int y;
28 31
 } state_t;
29 32
 
30 33
 static uint32_t blend(uint32_t fg_c, uint32_t bg_c, uint8_t alpha) {
@@ -51,7 +54,9 @@ static void pixel_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha,
51 54
                            void *state) {
52 55
     state_t *s = (state_t*)state;
53 56
 
54
-    if ((y < 0) || (y >= (s->options->y + s->options->height))
57
+    if ((y < 0) || (y >= (s->options->y + s->options->height)
58
+        || (y < s->options->y)
59
+        || (y >= LCD_HEIGHT)) || (x >= LCD_WIDTH)
55 60
         || (x < 0) || ((x + count) >= (s->options->x + s->options->width))) {
56 61
         return;
57 62
     }
@@ -73,43 +78,49 @@ static uint8_t character_callback(int16_t x, int16_t y, mf_char character,
73 78
 static bool line_callback(const char *line, uint16_t count, void *state) {
74 79
     state_t *s = (state_t*)state;
75 80
 
81
+    if (s->y < (s->options->y - s->options->font->font->line_height)) {
82
+        s->y += s->options->font->font->line_height;
83
+        return true;
84
+    }
85
+
76 86
     if (s->options->bg != TEXT_BG_NONE) {
77 87
         int16_t width = mf_get_string_width(s->options->font->font, line, count, false) + 2 * s->options->margin;
78 88
         int16_t line_height = s->options->font->font->line_height;
79 89
 
80 90
         if (s->options->alignment == MF_ALIGN_LEFT) {
81 91
             lcd_write_rect(s->options->x,
82
-                           s->options->y,
92
+                           MAX(s->y, s->options->y),
83 93
                            s->options->x + width,
84
-                           s->options->y + line_height,
94
+                           MIN(s->y + line_height, s->options->y + s->options->height),
85 95
                            s->options->bg);
86 96
         } else if (s->options->alignment == MF_ALIGN_CENTER) {
87 97
             lcd_write_rect(s->options->x + s->options->width / 2 - width / 2,
88
-                           s->options->y,
98
+                           MAX(s->y, s->options->y),
89 99
                            s->options->x + s->options->width / 2 + width / 2,
90
-                           s->options->y + line_height,
100
+                           MIN(s->y + line_height, s->options->y + s->options->height),
91 101
                            s->options->bg);
92 102
         } else if (s->options->alignment == MF_ALIGN_RIGHT) {
93 103
             lcd_write_rect(s->options->x + s->options->width - width,
94
-                           s->options->y,
104
+                           MAX(s->y, s->options->y),
95 105
                            s->options->x + s->options->width,
96
-                           s->options->y + line_height,
106
+                           MIN(s->y + line_height, s->options->y + s->options->height),
97 107
                            s->options->bg);
98 108
         }
99 109
     }
100 110
 
101 111
     if (s->options->justify) {
102
-        mf_render_justified(s->options->font->font, s->anchor + s->options->x, s->options->y,
112
+        mf_render_justified(s->options->font->font, s->anchor + s->options->x, s->y,
103 113
                             s->options->width - s->options->margin * 2,
104 114
                             line, count, character_callback, state);
105 115
     } else {
106
-        mf_render_aligned(s->options->font->font, s->anchor + s->options->x, s->options->y,
116
+        mf_render_aligned(s->options->font->font, s->anchor + s->options->x, s->y,
107 117
                           s->options->alignment, line, count,
108 118
                           character_callback, state);
109 119
     }
110 120
 
111
-    s->options->y += s->options->font->font->line_height;
112
-    return true;
121
+    s->y += s->options->font->font->line_height;
122
+    return (s->y < (s->options->y + s->options->height))
123
+            && (s->y < LCD_HEIGHT);
113 124
 }
114 125
 
115 126
 void text_prepare_font(struct text_font *tf) {
@@ -136,14 +147,15 @@ void text_prepare_font(struct text_font *tf) {
136 147
     //}
137 148
 }
138 149
 
139
-void text_draw(struct text_conf *tc) {
150
+int16_t text_draw(struct text_conf *tc) {
140 151
     if ((!tc) || (!tc->font) || (!tc->font->font)) {
141 152
         debug("invalid param");
142
-        return;
153
+        return 0;
143 154
     }
144 155
 
145 156
     state_t state;
146 157
     state.options = tc;
158
+    state.y = tc->y + tc->y_text_off;
147 159
 
148 160
     if (tc->alignment == MF_ALIGN_LEFT) {
149 161
         state.anchor = tc->margin;
@@ -155,27 +167,30 @@ void text_draw(struct text_conf *tc) {
155 167
 
156 168
     mf_wordwrap(tc->font->font, tc->width - 2 * tc->margin,
157 169
                 tc->text, line_callback, &state);
170
+
171
+    return state.y;
158 172
 }
159 173
 
160
-void text_box(const char *s, bool centered) {
174
+int16_t text_box(const char *s, bool centered,
175
+                 const char *fontname,
176
+                 uint16_t x_off, uint16_t width,
177
+                 uint16_t y_off, uint16_t height,
178
+                 int16_t y_text_off) {
161 179
     static struct text_font font = {
162
-        .fontname = "fixed_10x20",
180
+        .fontname = "",
163 181
         .font = NULL,
164 182
     };
165
-    if (font.font == NULL) {
183
+
184
+    if ((font.font == NULL) || (strcmp(font.fontname, fontname) != 0)) {
185
+        font.fontname = fontname;
166 186
         text_prepare_font(&font);
167 187
     }
168 188
 
169
-    int x_off = 0;
170
-    int width = LCD_WIDTH;
171
-
172
-    int y_off = 50;
173
-    int height = (MENU_MAX_LINES * 20) + ((MENU_MAX_LINES - 1) * 2);
174
-
175 189
     struct text_conf text = {
176
-        .text = "",
190
+        .text = s,
177 191
         .x = x_off,
178 192
         .y = y_off,
193
+        .y_text_off = y_text_off,
179 194
         .justify = false,
180 195
         .alignment = centered ? MF_ALIGN_CENTER : MF_ALIGN_LEFT,
181 196
         .width = width,
@@ -191,6 +206,5 @@ void text_box(const char *s, bool centered) {
191 206
                    y_off + height - 1,
192 207
                    RGB_565(0x00, 0x00, 0x00));
193 208
 
194
-    text.text = s;
195
-    text_draw(&text);
209
+    return text_draw(&text);
196 210
 }

Loading…
Cancel
Save