diff options
author | Dave Chapman <dave@dchapman.com> | 2008-01-07 20:34:11 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2008-01-07 20:34:11 +0000 |
commit | 945c8a221ade41c462a93f8452320a806e5645b3 (patch) | |
tree | 2a17823e286e6252e60c44c7f4753d5c18ef5172 | |
parent | 2a8f39820b49f116820356c2ca224f82f2106c21 (diff) | |
download | rockbox-945c8a221ade41c462a93f8452320a806e5645b3.tar.gz rockbox-945c8a221ade41c462a93f8452320a806e5645b3.zip |
Add viewport capabilities to all the LCD drivers, and adapt scrolling code. This is the firmware/ part of FS#8385 - the changes to the WPS code still need more work and will be committed at a later date. NOTE: There are no user-visible changes with this commit - just the infrastructure.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16018 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/drivers/lcd-16bit.c | 478 | ||||
-rw-r--r-- | firmware/drivers/lcd-1bit-vert.c | 250 | ||||
-rw-r--r-- | firmware/drivers/lcd-2bit-horz.c | 277 | ||||
-rw-r--r-- | firmware/drivers/lcd-2bit-vert.c | 294 | ||||
-rw-r--r-- | firmware/drivers/lcd-charcell.c | 159 | ||||
-rw-r--r-- | firmware/drivers/lcd-remote-1bit-v.c | 260 | ||||
-rw-r--r-- | firmware/drivers/lcd-remote-2bit-vi.c | 294 | ||||
-rw-r--r-- | firmware/export/lcd-remote.h | 7 | ||||
-rw-r--r-- | firmware/export/lcd.h | 28 | ||||
-rw-r--r-- | firmware/export/scroll_engine.h | 14 | ||||
-rw-r--r-- | firmware/scroll_engine.c | 68 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c | 7 |
12 files changed, 1473 insertions, 663 deletions
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index b990f556d3..cc5a6c5ab7 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c | |||
@@ -49,25 +49,31 @@ fb_data lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] | |||
49 | static fb_data* lcd_backdrop = NULL; | 49 | static fb_data* lcd_backdrop = NULL; |
50 | static long lcd_backdrop_offset IDATA_ATTR = 0; | 50 | static long lcd_backdrop_offset IDATA_ATTR = 0; |
51 | 51 | ||
52 | static struct viewport default_vp = | ||
53 | { | ||
54 | .x = 0, | ||
55 | .y = 0, | ||
56 | .width = LCD_WIDTH, | ||
57 | .height = LCD_HEIGHT, | ||
58 | .font = FONT_SYSFIXED, | ||
59 | .drawmode = DRMODE_SOLID, | ||
60 | .xmargin = 0, | ||
61 | .ymargin = 0, | ||
62 | .fg_pattern = LCD_DEFAULT_FG, | ||
63 | .bg_pattern = LCD_DEFAULT_BG, | ||
64 | .lss_pattern = LCD_DEFAULT_BG, | ||
65 | .lse_pattern = LCD_DEFAULT_BG, | ||
66 | .lst_pattern = LCD_DEFAULT_BG, | ||
67 | }; | ||
68 | |||
69 | /* The Gigabeat target build requires access to the current fg_pattern | ||
70 | in lcd-meg-fx.c */ | ||
52 | #if !defined(TOSHIBA_GIGABEAT_F) || defined(SIMULATOR) | 71 | #if !defined(TOSHIBA_GIGABEAT_F) || defined(SIMULATOR) |
53 | static unsigned fg_pattern IDATA_ATTR = LCD_DEFAULT_FG; | 72 | static struct viewport* current_vp IDATA_ATTR = &default_vp; |
54 | static unsigned bg_pattern IDATA_ATTR = LCD_DEFAULT_BG; | ||
55 | static unsigned lss_pattern IDATA_ATTR = LCD_DEFAULT_LS; | ||
56 | static unsigned lse_pattern IDATA_ATTR = LCD_DEFAULT_BG; | ||
57 | static unsigned lst_pattern IDATA_ATTR = LCD_DEFAULT_FG; | ||
58 | #else | 73 | #else |
59 | unsigned fg_pattern IDATA_ATTR = LCD_DEFAULT_FG; | 74 | struct viewport* current_vp IDATA_ATTR = &default_vp; |
60 | unsigned bg_pattern IDATA_ATTR = LCD_DEFAULT_BG; | ||
61 | unsigned lss_pattern IDATA_ATTR = LCD_DEFAULT_LS; | ||
62 | unsigned lse_pattern IDATA_ATTR = LCD_DEFAULT_BG; | ||
63 | unsigned lst_pattern IDATA_ATTR = LCD_DEFAULT_FG; | ||
64 | #endif | 75 | #endif |
65 | 76 | ||
66 | static int drawmode = DRMODE_SOLID; | ||
67 | static int xmargin = 0; | ||
68 | static int ymargin = 0; | ||
69 | static int curfont = FONT_SYSFIXED; | ||
70 | |||
71 | /* LCD init */ | 77 | /* LCD init */ |
72 | void lcd_init(void) | 78 | void lcd_init(void) |
73 | { | 79 | { |
@@ -78,84 +84,115 @@ void lcd_init(void) | |||
78 | scroll_init(); | 84 | scroll_init(); |
79 | } | 85 | } |
80 | 86 | ||
87 | /*** Viewports ***/ | ||
88 | |||
89 | void lcd_set_viewport(struct viewport* vp) | ||
90 | { | ||
91 | if (vp == NULL) | ||
92 | current_vp = &default_vp; | ||
93 | else | ||
94 | current_vp = vp; | ||
95 | } | ||
96 | |||
97 | void lcd_update_viewport(void) | ||
98 | { | ||
99 | lcd_update_rect(current_vp->x, current_vp->y, | ||
100 | current_vp->width, current_vp->height); | ||
101 | } | ||
102 | |||
103 | void lcd_update_viewport_rect(int x, int y, int width, int height) | ||
104 | { | ||
105 | lcd_update_rect(current_vp->x + x, current_vp->y + y, width, height); | ||
106 | } | ||
107 | |||
81 | /*** parameter handling ***/ | 108 | /*** parameter handling ***/ |
82 | 109 | ||
83 | void lcd_set_drawmode(int mode) | 110 | void lcd_set_drawmode(int mode) |
84 | { | 111 | { |
85 | drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); | 112 | current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); |
86 | } | 113 | } |
87 | 114 | ||
88 | int lcd_get_drawmode(void) | 115 | int lcd_get_drawmode(void) |
89 | { | 116 | { |
90 | return drawmode; | 117 | return current_vp->drawmode; |
91 | } | 118 | } |
92 | 119 | ||
93 | void lcd_set_foreground(unsigned color) | 120 | void lcd_set_foreground(unsigned color) |
94 | { | 121 | { |
95 | fg_pattern = color; | 122 | current_vp->fg_pattern = color; |
96 | } | 123 | } |
97 | 124 | ||
98 | unsigned lcd_get_foreground(void) | 125 | unsigned lcd_get_foreground(void) |
99 | { | 126 | { |
100 | return fg_pattern; | 127 | return current_vp->fg_pattern; |
101 | } | 128 | } |
102 | 129 | ||
103 | void lcd_set_background(unsigned color) | 130 | void lcd_set_background(unsigned color) |
104 | { | 131 | { |
105 | bg_pattern = color; | 132 | current_vp->bg_pattern = color; |
106 | } | 133 | } |
107 | 134 | ||
108 | unsigned lcd_get_background(void) | 135 | unsigned lcd_get_background(void) |
109 | { | 136 | { |
110 | return bg_pattern; | 137 | return current_vp->bg_pattern; |
111 | } | 138 | } |
112 | 139 | ||
113 | void lcd_set_selector_start(unsigned color) | 140 | void lcd_set_selector_start(unsigned color) |
114 | { | 141 | { |
115 | lss_pattern = color; | 142 | current_vp->lss_pattern = color; |
116 | } | 143 | } |
117 | 144 | ||
118 | void lcd_set_selector_end(unsigned color) | 145 | void lcd_set_selector_end(unsigned color) |
119 | { | 146 | { |
120 | lse_pattern = color; | 147 | current_vp->lse_pattern = color; |
121 | } | 148 | } |
122 | 149 | ||
123 | void lcd_set_selector_text(unsigned color) | 150 | void lcd_set_selector_text(unsigned color) |
124 | { | 151 | { |
125 | lst_pattern = color; | 152 | current_vp->lst_pattern = color; |
126 | } | 153 | } |
127 | 154 | ||
128 | void lcd_set_drawinfo(int mode, unsigned fg_color, unsigned bg_color) | 155 | void lcd_set_drawinfo(int mode, unsigned fg_color, unsigned bg_color) |
129 | { | 156 | { |
130 | lcd_set_drawmode(mode); | 157 | lcd_set_drawmode(mode); |
131 | fg_pattern = fg_color; | 158 | current_vp->fg_pattern = fg_color; |
132 | bg_pattern = bg_color; | 159 | current_vp->bg_pattern = bg_color; |
133 | } | 160 | } |
134 | 161 | ||
135 | void lcd_setmargins(int x, int y) | 162 | void lcd_setmargins(int x, int y) |
136 | { | 163 | { |
137 | xmargin = x; | 164 | current_vp->xmargin = x; |
138 | ymargin = y; | 165 | current_vp->ymargin = y; |
166 | } | ||
167 | |||
168 | int lcd_getwidth(void) | ||
169 | { | ||
170 | return current_vp->width; | ||
171 | } | ||
172 | |||
173 | int lcd_getheight(void) | ||
174 | { | ||
175 | return current_vp->height; | ||
139 | } | 176 | } |
140 | 177 | ||
141 | int lcd_getxmargin(void) | 178 | int lcd_getxmargin(void) |
142 | { | 179 | { |
143 | return xmargin; | 180 | return current_vp->xmargin; |
144 | } | 181 | } |
145 | 182 | ||
146 | int lcd_getymargin(void) | 183 | int lcd_getymargin(void) |
147 | { | 184 | { |
148 | return ymargin; | 185 | return current_vp->ymargin; |
149 | } | 186 | } |
150 | 187 | ||
151 | void lcd_setfont(int newfont) | 188 | void lcd_setfont(int newfont) |
152 | { | 189 | { |
153 | curfont = newfont; | 190 | current_vp->font = newfont; |
154 | } | 191 | } |
155 | 192 | ||
156 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) | 193 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) |
157 | { | 194 | { |
158 | return font_getstringsize(str, w, h, curfont); | 195 | return font_getstringsize(str, w, h, current_vp->font); |
159 | } | 196 | } |
160 | 197 | ||
161 | /*** low-level drawing functions ***/ | 198 | /*** low-level drawing functions ***/ |
@@ -165,13 +202,13 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h) | |||
165 | static void setpixel(fb_data *address) ICODE_ATTR; | 202 | static void setpixel(fb_data *address) ICODE_ATTR; |
166 | static void setpixel(fb_data *address) | 203 | static void setpixel(fb_data *address) |
167 | { | 204 | { |
168 | *address = fg_pattern; | 205 | *address = current_vp->fg_pattern; |
169 | } | 206 | } |
170 | 207 | ||
171 | static void clearpixel(fb_data *address) ICODE_ATTR; | 208 | static void clearpixel(fb_data *address) ICODE_ATTR; |
172 | static void clearpixel(fb_data *address) | 209 | static void clearpixel(fb_data *address) |
173 | { | 210 | { |
174 | *address = bg_pattern; | 211 | *address = current_vp->bg_pattern; |
175 | } | 212 | } |
176 | 213 | ||
177 | static void clearimgpixel(fb_data *address) ICODE_ATTR; | 214 | static void clearimgpixel(fb_data *address) ICODE_ATTR; |
@@ -226,31 +263,74 @@ fb_data* lcd_get_backdrop(void) | |||
226 | 263 | ||
227 | /*** drawing functions ***/ | 264 | /*** drawing functions ***/ |
228 | 265 | ||
229 | /* Clear the whole display */ | 266 | /* Clear the current viewport */ |
230 | void lcd_clear_display(void) | 267 | void lcd_clear_viewport(void) |
231 | { | 268 | { |
232 | fb_data *dst = LCDADDR(0, 0); | 269 | fb_data *dst, *dst_end; |
270 | |||
271 | dst = LCDADDR(current_vp->x, current_vp->y); | ||
272 | dst_end = dst + current_vp->height * LCD_WIDTH; | ||
233 | 273 | ||
234 | if (drawmode & DRMODE_INVERSEVID) | 274 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
235 | { | 275 | { |
236 | memset16(dst, fg_pattern, LCD_WIDTH*LCD_HEIGHT); | 276 | do |
277 | { | ||
278 | memset16(dst, current_vp->fg_pattern, current_vp->width); | ||
279 | dst += LCD_WIDTH; | ||
280 | } | ||
281 | while (dst < dst_end); | ||
237 | } | 282 | } |
238 | else | 283 | else |
239 | { | 284 | { |
240 | if (!lcd_backdrop) | 285 | if (!lcd_backdrop) |
241 | memset16(dst, bg_pattern, LCD_WIDTH*LCD_HEIGHT); | 286 | { |
287 | do | ||
288 | { | ||
289 | memset16(dst, current_vp->bg_pattern, current_vp->width); | ||
290 | dst += LCD_WIDTH; | ||
291 | } | ||
292 | while (dst < dst_end); | ||
293 | } | ||
242 | else | 294 | else |
243 | memcpy(dst, lcd_backdrop, sizeof(lcd_framebuffer)); | 295 | { |
296 | do | ||
297 | { | ||
298 | memcpy(dst, (void *)((long)dst + lcd_backdrop_offset), | ||
299 | current_vp->width * sizeof(fb_data)); | ||
300 | dst += LCD_WIDTH; | ||
301 | } | ||
302 | while (dst < dst_end); | ||
303 | } | ||
244 | } | 304 | } |
245 | 305 | ||
246 | lcd_scroll_info.lines = 0; | 306 | if (current_vp == &default_vp) |
307 | { | ||
308 | lcd_scroll_info.lines = 0; | ||
309 | } | ||
310 | else | ||
311 | { | ||
312 | lcd_scroll_stop(current_vp); | ||
313 | } | ||
314 | } | ||
315 | |||
316 | /* Clear the whole display */ | ||
317 | void lcd_clear_display(void) | ||
318 | { | ||
319 | struct viewport* old_vp = current_vp; | ||
320 | |||
321 | current_vp = &default_vp; | ||
322 | |||
323 | lcd_clear_viewport(); | ||
324 | |||
325 | current_vp = old_vp; | ||
247 | } | 326 | } |
248 | 327 | ||
249 | /* Set a single pixel */ | 328 | /* Set a single pixel */ |
250 | void lcd_drawpixel(int x, int y) | 329 | void lcd_drawpixel(int x, int y) |
251 | { | 330 | { |
252 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) | 331 | if (((unsigned)x < (unsigned)current_vp->width) && |
253 | lcd_fastpixelfuncs[drawmode](LCDADDR(x, y)); | 332 | ((unsigned)y < (unsigned)current_vp->height)) |
333 | lcd_fastpixelfuncs[current_vp->drawmode](LCDADDR(current_vp->x+x, current_vp->y+y)); | ||
254 | } | 334 | } |
255 | 335 | ||
256 | /* Draw a line */ | 336 | /* Draw a line */ |
@@ -262,7 +342,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
262 | int d, dinc1, dinc2; | 342 | int d, dinc1, dinc2; |
263 | int x, xinc1, xinc2; | 343 | int x, xinc1, xinc2; |
264 | int y, yinc1, yinc2; | 344 | int y, yinc1, yinc2; |
265 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[drawmode]; | 345 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; |
266 | 346 | ||
267 | deltax = abs(x2 - x1); | 347 | deltax = abs(x2 - x1); |
268 | deltay = abs(y2 - y1); | 348 | deltay = abs(y2 - y1); |
@@ -306,8 +386,8 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
306 | 386 | ||
307 | for (i = 0; i < numpixels; i++) | 387 | for (i = 0; i < numpixels; i++) |
308 | { | 388 | { |
309 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) | 389 | if (((unsigned)x < (unsigned)current_vp->width) && ((unsigned)y < (unsigned)current_vp->height)) |
310 | pfunc(LCDADDR(x, y)); | 390 | pfunc(LCDADDR(x + current_vp->x, y + current_vp->y)); |
311 | 391 | ||
312 | if (d < 0) | 392 | if (d < 0) |
313 | { | 393 | { |
@@ -331,7 +411,7 @@ void lcd_hline(int x1, int x2, int y) | |||
331 | unsigned bits = 0; | 411 | unsigned bits = 0; |
332 | enum fill_opt fillopt = OPT_NONE; | 412 | enum fill_opt fillopt = OPT_NONE; |
333 | fb_data *dst, *dst_end; | 413 | fb_data *dst, *dst_end; |
334 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[drawmode]; | 414 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; |
335 | 415 | ||
336 | /* direction flip */ | 416 | /* direction flip */ |
337 | if (x2 < x1) | 417 | if (x2 < x1) |
@@ -342,23 +422,31 @@ void lcd_hline(int x1, int x2, int y) | |||
342 | } | 422 | } |
343 | 423 | ||
344 | /* nothing to draw? */ | 424 | /* nothing to draw? */ |
345 | if (((unsigned)y >= LCD_HEIGHT) || (x1 >= LCD_WIDTH) || (x2 < 0)) | 425 | if (((unsigned)y >= (unsigned)current_vp->height) || |
426 | (x1 >= current_vp->width) || | ||
427 | (x2 < 0)) | ||
346 | return; | 428 | return; |
347 | 429 | ||
348 | /* clipping */ | 430 | /* clipping */ |
349 | if (x1 < 0) | 431 | if (x1 < 0) |
350 | x1 = 0; | 432 | x1 = 0; |
351 | if (x2 >= LCD_WIDTH) | 433 | if (x2 >= current_vp->width) |
352 | x2 = LCD_WIDTH-1; | 434 | x2 = current_vp->width-1; |
435 | |||
436 | width = x2 - x1 + 1; | ||
353 | 437 | ||
354 | if (drawmode & DRMODE_INVERSEVID) | 438 | /* Adjust x1 and y to viewport */ |
439 | x1 += current_vp->x; | ||
440 | y += current_vp->y; | ||
441 | |||
442 | if (current_vp->drawmode & DRMODE_INVERSEVID) | ||
355 | { | 443 | { |
356 | if (drawmode & DRMODE_BG) | 444 | if (current_vp->drawmode & DRMODE_BG) |
357 | { | 445 | { |
358 | if (!lcd_backdrop) | 446 | if (!lcd_backdrop) |
359 | { | 447 | { |
360 | fillopt = OPT_SET; | 448 | fillopt = OPT_SET; |
361 | bits = bg_pattern; | 449 | bits = current_vp->bg_pattern; |
362 | } | 450 | } |
363 | else | 451 | else |
364 | fillopt = OPT_COPY; | 452 | fillopt = OPT_COPY; |
@@ -366,14 +454,13 @@ void lcd_hline(int x1, int x2, int y) | |||
366 | } | 454 | } |
367 | else | 455 | else |
368 | { | 456 | { |
369 | if (drawmode & DRMODE_FG) | 457 | if (current_vp->drawmode & DRMODE_FG) |
370 | { | 458 | { |
371 | fillopt = OPT_SET; | 459 | fillopt = OPT_SET; |
372 | bits = fg_pattern; | 460 | bits = current_vp->fg_pattern; |
373 | } | 461 | } |
374 | } | 462 | } |
375 | dst = LCDADDR(x1, y); | 463 | dst = LCDADDR(x1, y); |
376 | width = x2 - x1 + 1; | ||
377 | 464 | ||
378 | switch (fillopt) | 465 | switch (fillopt) |
379 | { | 466 | { |
@@ -400,7 +487,7 @@ void lcd_vline(int x, int y1, int y2) | |||
400 | { | 487 | { |
401 | int y; | 488 | int y; |
402 | fb_data *dst, *dst_end; | 489 | fb_data *dst, *dst_end; |
403 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[drawmode]; | 490 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; |
404 | 491 | ||
405 | /* direction flip */ | 492 | /* direction flip */ |
406 | if (y2 < y1) | 493 | if (y2 < y1) |
@@ -411,16 +498,18 @@ void lcd_vline(int x, int y1, int y2) | |||
411 | } | 498 | } |
412 | 499 | ||
413 | /* nothing to draw? */ | 500 | /* nothing to draw? */ |
414 | if (((unsigned)x >= LCD_WIDTH) || (y1 >= LCD_HEIGHT) || (y2 < 0)) | 501 | if ((x >= current_vp->width) || |
502 | (y1 >= current_vp->height) || | ||
503 | (y2 < 0)) | ||
415 | return; | 504 | return; |
416 | 505 | ||
417 | /* clipping */ | 506 | /* clipping */ |
418 | if (y1 < 0) | 507 | if (y1 < 0) |
419 | y1 = 0; | 508 | y1 = 0; |
420 | if (y2 >= LCD_HEIGHT) | 509 | if (y2 >= current_vp->height) |
421 | y2 = LCD_HEIGHT-1; | 510 | y2 = current_vp->height-1; |
422 | 511 | ||
423 | dst = LCDADDR(x, y1); | 512 | dst = LCDADDR(x + current_vp->x, y1 + current_vp->y); |
424 | dst_end = dst + (y2 - y1) * LCD_WIDTH; | 513 | dst_end = dst + (y2 - y1) * LCD_WIDTH; |
425 | 514 | ||
426 | do | 515 | do |
@@ -452,11 +541,11 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
452 | unsigned bits = 0; | 541 | unsigned bits = 0; |
453 | enum fill_opt fillopt = OPT_NONE; | 542 | enum fill_opt fillopt = OPT_NONE; |
454 | fb_data *dst, *dst_end; | 543 | fb_data *dst, *dst_end; |
455 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[drawmode]; | 544 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; |
456 | 545 | ||
457 | /* nothing to draw? */ | 546 | /* nothing to draw? */ |
458 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 547 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
459 | || (x + width <= 0) || (y + height <= 0)) | 548 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
460 | return; | 549 | return; |
461 | 550 | ||
462 | /* clipping */ | 551 | /* clipping */ |
@@ -470,19 +559,19 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
470 | height += y; | 559 | height += y; |
471 | y = 0; | 560 | y = 0; |
472 | } | 561 | } |
473 | if (x + width > LCD_WIDTH) | 562 | if (x + width > current_vp->width) |
474 | width = LCD_WIDTH - x; | 563 | width = current_vp->width - x; |
475 | if (y + height > LCD_HEIGHT) | 564 | if (y + height > current_vp->height) |
476 | height = LCD_HEIGHT - y; | 565 | height = current_vp->height - y; |
477 | 566 | ||
478 | if (drawmode & DRMODE_INVERSEVID) | 567 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
479 | { | 568 | { |
480 | if (drawmode & DRMODE_BG) | 569 | if (current_vp->drawmode & DRMODE_BG) |
481 | { | 570 | { |
482 | if (!lcd_backdrop) | 571 | if (!lcd_backdrop) |
483 | { | 572 | { |
484 | fillopt = OPT_SET; | 573 | fillopt = OPT_SET; |
485 | bits = bg_pattern; | 574 | bits = current_vp->bg_pattern; |
486 | } | 575 | } |
487 | else | 576 | else |
488 | fillopt = OPT_COPY; | 577 | fillopt = OPT_COPY; |
@@ -490,13 +579,13 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
490 | } | 579 | } |
491 | else | 580 | else |
492 | { | 581 | { |
493 | if (drawmode & DRMODE_FG) | 582 | if (current_vp->drawmode & DRMODE_FG) |
494 | { | 583 | { |
495 | fillopt = OPT_SET; | 584 | fillopt = OPT_SET; |
496 | bits = fg_pattern; | 585 | bits = current_vp->fg_pattern; |
497 | } | 586 | } |
498 | } | 587 | } |
499 | dst = LCDADDR(x, y); | 588 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); |
500 | dst_end = dst + height * LCD_WIDTH; | 589 | dst_end = dst + height * LCD_WIDTH; |
501 | 590 | ||
502 | do | 591 | do |
@@ -530,24 +619,28 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
530 | /* Fill a rectangle with a gradient */ | 619 | /* Fill a rectangle with a gradient */ |
531 | void lcd_gradient_rect(int x1, int x2, int y, int h) | 620 | void lcd_gradient_rect(int x1, int x2, int y, int h) |
532 | { | 621 | { |
622 | int old_pattern = current_vp->fg_pattern; | ||
623 | |||
533 | if (h == 0) return; | 624 | if (h == 0) return; |
534 | 625 | ||
535 | int h_r = RGB_UNPACK_RED(lss_pattern) << 16; | 626 | int h_r = RGB_UNPACK_RED(current_vp->lss_pattern) << 16; |
536 | int h_b = RGB_UNPACK_BLUE(lss_pattern) << 16; | 627 | int h_b = RGB_UNPACK_BLUE(current_vp->lss_pattern) << 16; |
537 | int h_g = RGB_UNPACK_GREEN(lss_pattern) << 16; | 628 | int h_g = RGB_UNPACK_GREEN(current_vp->lss_pattern) << 16; |
538 | int rstep = (h_r - ((signed)RGB_UNPACK_RED(lse_pattern) << 16)) / h; | 629 | int rstep = (h_r - ((signed)RGB_UNPACK_RED(current_vp->lse_pattern) << 16)) / h; |
539 | int gstep = (h_g - ((signed)RGB_UNPACK_GREEN(lse_pattern) << 16)) / h; | 630 | int gstep = (h_g - ((signed)RGB_UNPACK_GREEN(current_vp->lse_pattern) << 16)) / h; |
540 | int bstep = (h_b - ((signed)RGB_UNPACK_BLUE(lse_pattern) << 16)) / h; | 631 | int bstep = (h_b - ((signed)RGB_UNPACK_BLUE(current_vp->lse_pattern) << 16)) / h; |
541 | int count; | 632 | int count; |
542 | 633 | ||
543 | fg_pattern = lss_pattern; | 634 | current_vp->fg_pattern = current_vp->lss_pattern; |
544 | for(count = 0; count < h; count++) { | 635 | for(count = 0; count < h; count++) { |
545 | lcd_hline(x1, x2, y + count); | 636 | lcd_hline(x1, x2, y + count); |
546 | h_r -= rstep; | 637 | h_r -= rstep; |
547 | h_g -= gstep; | 638 | h_g -= gstep; |
548 | h_b -= bstep; | 639 | h_b -= bstep; |
549 | fg_pattern = LCD_RGBPACK(h_r >> 16, h_g >> 16, h_b >> 16); | 640 | current_vp->fg_pattern = LCD_RGBPACK(h_r >> 16, h_g >> 16, h_b >> 16); |
550 | } | 641 | } |
642 | |||
643 | current_vp->fg_pattern = old_pattern; | ||
551 | } | 644 | } |
552 | 645 | ||
553 | #define H_COLOR(lss, lse, cur_line, max_line) \ | 646 | #define H_COLOR(lss, lse, cur_line, max_line) \ |
@@ -562,14 +655,14 @@ void lcd_gradient_rect_scroll(int x1, int x2, int y, int h, | |||
562 | { | 655 | { |
563 | if (h == 0 || num_lines == 0) return; | 656 | if (h == 0 || num_lines == 0) return; |
564 | 657 | ||
565 | unsigned tmp_lss = lss_pattern; | 658 | unsigned tmp_lss = current_vp->lss_pattern; |
566 | unsigned tmp_lse = lse_pattern; | 659 | unsigned tmp_lse = current_vp->lse_pattern; |
567 | int lss_r = (signed)RGB_UNPACK_RED(lss_pattern); | 660 | int lss_r = (signed)RGB_UNPACK_RED(current_vp->lss_pattern); |
568 | int lss_b = (signed)RGB_UNPACK_BLUE(lss_pattern); | 661 | int lss_b = (signed)RGB_UNPACK_BLUE(current_vp->lss_pattern); |
569 | int lss_g = (signed)RGB_UNPACK_GREEN(lss_pattern); | 662 | int lss_g = (signed)RGB_UNPACK_GREEN(current_vp->lss_pattern); |
570 | int lse_r = (signed)RGB_UNPACK_RED(lse_pattern); | 663 | int lse_r = (signed)RGB_UNPACK_RED(current_vp->lse_pattern); |
571 | int lse_b = (signed)RGB_UNPACK_BLUE(lse_pattern); | 664 | int lse_b = (signed)RGB_UNPACK_BLUE(current_vp->lse_pattern); |
572 | int lse_g = (signed)RGB_UNPACK_GREEN(lse_pattern); | 665 | int lse_g = (signed)RGB_UNPACK_GREEN(current_vp->lse_pattern); |
573 | 666 | ||
574 | int h_r = H_COLOR(lss_r, lse_r, cur_line, num_lines); | 667 | int h_r = H_COLOR(lss_r, lse_r, cur_line, num_lines); |
575 | int h_g = H_COLOR(lss_g, lse_g, cur_line, num_lines); | 668 | int h_g = H_COLOR(lss_g, lse_g, cur_line, num_lines); |
@@ -583,8 +676,8 @@ void lcd_gradient_rect_scroll(int x1, int x2, int y, int h, | |||
583 | 676 | ||
584 | lcd_gradient_rect(x1, x2, y, h); | 677 | lcd_gradient_rect(x1, x2, y, h); |
585 | 678 | ||
586 | lcd_set_selector_start(tmp_lss); | 679 | current_vp->lss_pattern = tmp_lss; |
587 | lcd_set_selector_end(tmp_lse); | 680 | current_vp->lse_pattern = tmp_lse; |
588 | } | 681 | } |
589 | 682 | ||
590 | /* About Rockbox' internal monochrome bitmap format: | 683 | /* About Rockbox' internal monochrome bitmap format: |
@@ -613,8 +706,8 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
613 | lcd_fastpixelfunc_type *fgfunc, *bgfunc; | 706 | lcd_fastpixelfunc_type *fgfunc, *bgfunc; |
614 | 707 | ||
615 | /* nothing to draw? */ | 708 | /* nothing to draw? */ |
616 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 709 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
617 | || (x + width <= 0) || (y + height <= 0)) | 710 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
618 | return; | 711 | return; |
619 | 712 | ||
620 | /* clipping */ | 713 | /* clipping */ |
@@ -630,20 +723,20 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
630 | src_y -= y; | 723 | src_y -= y; |
631 | y = 0; | 724 | y = 0; |
632 | } | 725 | } |
633 | if (x + width > LCD_WIDTH) | 726 | if (x + width > current_vp->width) |
634 | width = LCD_WIDTH - x; | 727 | width = current_vp->width - x; |
635 | if (y + height > LCD_HEIGHT) | 728 | if (y + height > current_vp->height) |
636 | height = LCD_HEIGHT - y; | 729 | height = current_vp->height - y; |
637 | 730 | ||
638 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 731 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
639 | src_y &= 7; | 732 | src_y &= 7; |
640 | src_end = src + width; | 733 | src_end = src + width; |
641 | 734 | ||
642 | dst = LCDADDR(x, y); | 735 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); |
643 | has_backdrop = (lcd_backdrop != NULL); | 736 | has_backdrop = (lcd_backdrop != NULL); |
644 | backdrop = lcd_backdrop + y * LCD_WIDTH + x; | 737 | backdrop = lcd_backdrop + (current_vp->y + y) * LCD_WIDTH + current_vp->x + x; |
645 | fgfunc = lcd_fastpixelfuncs[drawmode]; | 738 | fgfunc = lcd_fastpixelfuncs[current_vp->drawmode]; |
646 | bgfunc = lcd_fastpixelfuncs[drawmode ^ DRMODE_INVERSEVID]; | 739 | bgfunc = lcd_fastpixelfuncs[current_vp->drawmode ^ DRMODE_INVERSEVID]; |
647 | do | 740 | do |
648 | { | 741 | { |
649 | const unsigned char *src_col = src++; | 742 | const unsigned char *src_col = src++; |
@@ -654,23 +747,23 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
654 | dst_end = dst_col + height * LCD_WIDTH; | 747 | dst_end = dst_col + height * LCD_WIDTH; |
655 | do | 748 | do |
656 | { | 749 | { |
657 | switch (drawmode) | 750 | switch (current_vp->drawmode) |
658 | { | 751 | { |
659 | case DRMODE_SOLID: | 752 | case DRMODE_SOLID: |
660 | if (data & 0x01) | 753 | if (data & 0x01) |
661 | *dst_col = fg_pattern; | 754 | *dst_col = current_vp->fg_pattern; |
662 | else | 755 | else |
663 | *dst_col = has_backdrop ? *backdrop_col : bg_pattern; | 756 | *dst_col = has_backdrop ? *backdrop_col : current_vp->bg_pattern; |
664 | break; | 757 | break; |
665 | case DRMODE_FG: | 758 | case DRMODE_FG: |
666 | if (data & 0x01) | 759 | if (data & 0x01) |
667 | *dst_col = fg_pattern; | 760 | *dst_col = current_vp->fg_pattern; |
668 | break; | 761 | break; |
669 | case (DRMODE_SOLID|DRMODE_INVERSEVID): | 762 | case (DRMODE_SOLID|DRMODE_INVERSEVID): |
670 | if (data & 0x01) | 763 | if (data & 0x01) |
671 | *dst_col = has_backdrop ? *backdrop_col : bg_pattern; | 764 | *dst_col = has_backdrop ? *backdrop_col : current_vp->bg_pattern; |
672 | else | 765 | else |
673 | *dst_col = fg_pattern; | 766 | *dst_col = current_vp->fg_pattern; |
674 | break; | 767 | break; |
675 | default: | 768 | default: |
676 | if (data & 0x01) | 769 | if (data & 0x01) |
@@ -709,8 +802,8 @@ void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
709 | fb_data *dst, *dst_end; | 802 | fb_data *dst, *dst_end; |
710 | 803 | ||
711 | /* nothing to draw? */ | 804 | /* nothing to draw? */ |
712 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 805 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
713 | || (x + width <= 0) || (y + height <= 0)) | 806 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
714 | return; | 807 | return; |
715 | 808 | ||
716 | /* clipping */ | 809 | /* clipping */ |
@@ -726,13 +819,13 @@ void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
726 | src_y -= y; | 819 | src_y -= y; |
727 | y = 0; | 820 | y = 0; |
728 | } | 821 | } |
729 | if (x + width > LCD_WIDTH) | 822 | if (x + width > current_vp->width) |
730 | width = LCD_WIDTH - x; | 823 | width = current_vp->width - x; |
731 | if (y + height > LCD_HEIGHT) | 824 | if (y + height > current_vp->height) |
732 | height = LCD_HEIGHT - y; | 825 | height = current_vp->height - y; |
733 | 826 | ||
734 | src += stride * src_y + src_x; /* move starting point */ | 827 | src += stride * src_y + src_x; /* move starting point */ |
735 | dst = LCDADDR(x, y); | 828 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); |
736 | dst_end = dst + height * LCD_WIDTH; | 829 | dst_end = dst + height * LCD_WIDTH; |
737 | 830 | ||
738 | do | 831 | do |
@@ -763,8 +856,8 @@ void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y, | |||
763 | fb_data *dst, *dst_end; | 856 | fb_data *dst, *dst_end; |
764 | 857 | ||
765 | /* nothing to draw? */ | 858 | /* nothing to draw? */ |
766 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 859 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
767 | || (x + width <= 0) || (y + height <= 0)) | 860 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
768 | return; | 861 | return; |
769 | 862 | ||
770 | /* clipping */ | 863 | /* clipping */ |
@@ -780,13 +873,13 @@ void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y, | |||
780 | src_y -= y; | 873 | src_y -= y; |
781 | y = 0; | 874 | y = 0; |
782 | } | 875 | } |
783 | if (x + width > LCD_WIDTH) | 876 | if (x + width > current_vp->width) |
784 | width = LCD_WIDTH - x; | 877 | width = current_vp->width - x; |
785 | if (y + height > LCD_HEIGHT) | 878 | if (y + height > current_vp->height) |
786 | height = LCD_HEIGHT - y; | 879 | height = current_vp->height - y; |
787 | 880 | ||
788 | src += stride * src_y + src_x; /* move starting point */ | 881 | src += stride * src_y + src_x; /* move starting point */ |
789 | dst = LCDADDR(x, y); | 882 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); |
790 | dst_end = dst + height * LCD_WIDTH; | 883 | dst_end = dst + height * LCD_WIDTH; |
791 | 884 | ||
792 | do | 885 | do |
@@ -795,7 +888,7 @@ void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y, | |||
795 | for(i = 0;i < width;i++) | 888 | for(i = 0;i < width;i++) |
796 | { | 889 | { |
797 | if (src[i] == REPLACEWITHFG_COLOR) | 890 | if (src[i] == REPLACEWITHFG_COLOR) |
798 | dst[i] = fg_pattern; | 891 | dst[i] = current_vp->fg_pattern; |
799 | else if(src[i] != TRANSPARENT_COLOR) | 892 | else if(src[i] != TRANSPARENT_COLOR) |
800 | dst[i] = src[i]; | 893 | dst[i] = src[i]; |
801 | } | 894 | } |
@@ -818,11 +911,11 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
818 | { | 911 | { |
819 | unsigned short ch; | 912 | unsigned short ch; |
820 | unsigned short *ucs; | 913 | unsigned short *ucs; |
821 | struct font* pf = font_get(curfont); | 914 | struct font* pf = font_get(current_vp->font); |
822 | 915 | ||
823 | ucs = bidi_l2v(str, 1); | 916 | ucs = bidi_l2v(str, 1); |
824 | 917 | ||
825 | while ((ch = *ucs++) != 0 && x < LCD_WIDTH) | 918 | while ((ch = *ucs++) != 0 && x < current_vp->width) |
826 | { | 919 | { |
827 | int width; | 920 | int width; |
828 | const unsigned char *bits; | 921 | const unsigned char *bits; |
@@ -875,51 +968,51 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str, int style, | |||
875 | int offset) | 968 | int offset) |
876 | { | 969 | { |
877 | int xpos,ypos,w,h,xrect; | 970 | int xpos,ypos,w,h,xrect; |
878 | int lastmode = drawmode; | 971 | int lastmode = current_vp->drawmode; |
879 | int oldfgcolor = fg_pattern; | 972 | int oldfgcolor = current_vp->fg_pattern; |
880 | int oldbgcolor = bg_pattern; | 973 | int oldbgcolor = current_vp->bg_pattern; |
881 | 974 | ||
882 | /* make sure scrolling is turned off on the line we are updating */ | 975 | /* make sure scrolling is turned off on the line we are updating */ |
883 | lcd_scroll_info.lines &= ~(1 << y); | 976 | lcd_scroll_stop_line(current_vp, y); |
884 | 977 | ||
885 | if(!str || !str[0]) | 978 | if(!str || !str[0]) |
886 | return; | 979 | return; |
887 | 980 | ||
888 | lcd_getstringsize(str, &w, &h); | 981 | lcd_getstringsize(str, &w, &h); |
889 | xpos = xmargin + x*w / utf8length(str); | 982 | xpos = current_vp->xmargin + x*w / utf8length(str); |
890 | ypos = ymargin + y*h; | 983 | ypos = current_vp->ymargin + y*h; |
891 | drawmode = (style & STYLE_INVERT) ? | 984 | current_vp->drawmode = (style & STYLE_INVERT) ? |
892 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | 985 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; |
893 | if (style & STYLE_COLORED) { | 986 | if (style & STYLE_COLORED) { |
894 | if (drawmode == DRMODE_SOLID) | 987 | if (current_vp->drawmode == DRMODE_SOLID) |
895 | fg_pattern = style & STYLE_COLOR_MASK; | 988 | current_vp->fg_pattern = style & STYLE_COLOR_MASK; |
896 | else | 989 | else |
897 | bg_pattern = style & STYLE_COLOR_MASK; | 990 | current_vp->bg_pattern = style & STYLE_COLOR_MASK; |
898 | } | 991 | } |
899 | drawmode ^= DRMODE_INVERSEVID; | 992 | current_vp->drawmode ^= DRMODE_INVERSEVID; |
900 | xrect = xpos + MAX(w - offset, 0); | 993 | xrect = xpos + MAX(w - offset, 0); |
901 | 994 | ||
902 | if (style & STYLE_GRADIENT) { | 995 | if (style & STYLE_GRADIENT) { |
903 | drawmode = DRMODE_FG; | 996 | current_vp->drawmode = DRMODE_FG; |
904 | if (CURLN_UNPACK(style) == 0) | 997 | if (CURLN_UNPACK(style) == 0) |
905 | lcd_gradient_rect(xpos, LCD_WIDTH, ypos, h*NUMLN_UNPACK(style)); | 998 | lcd_gradient_rect(xpos, current_vp->width, ypos, h*NUMLN_UNPACK(style)); |
906 | fg_pattern = lst_pattern; | 999 | current_vp->fg_pattern = current_vp->lst_pattern; |
907 | } | 1000 | } |
908 | else if (style & STYLE_COLORBAR) { | 1001 | else if (style & STYLE_COLORBAR) { |
909 | drawmode = DRMODE_FG; | 1002 | current_vp->drawmode = DRMODE_FG; |
910 | fg_pattern = lss_pattern; | 1003 | current_vp->fg_pattern = current_vp->lss_pattern; |
911 | lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, h); | 1004 | lcd_fillrect(xpos, ypos, current_vp->width - xpos, h); |
912 | fg_pattern = lst_pattern; | 1005 | current_vp->fg_pattern = current_vp->lst_pattern; |
913 | } | 1006 | } |
914 | else { | 1007 | else { |
915 | lcd_fillrect(xrect, ypos, LCD_WIDTH - xrect, h); | 1008 | lcd_fillrect(xrect, ypos, current_vp->width - xrect, h); |
916 | drawmode = (style & STYLE_INVERT) ? | 1009 | current_vp->drawmode = (style & STYLE_INVERT) ? |
917 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | 1010 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; |
918 | } | 1011 | } |
919 | lcd_putsxyofs(xpos, ypos, offset, str); | 1012 | lcd_putsxyofs(xpos, ypos, offset, str); |
920 | drawmode = lastmode; | 1013 | current_vp->drawmode = lastmode; |
921 | fg_pattern = oldfgcolor; | 1014 | current_vp->fg_pattern = oldfgcolor; |
922 | bg_pattern = oldbgcolor; | 1015 | current_vp->bg_pattern = oldbgcolor; |
923 | } | 1016 | } |
924 | 1017 | ||
925 | /*** scrolling ***/ | 1018 | /*** scrolling ***/ |
@@ -938,15 +1031,23 @@ void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, int offse | |||
938 | lcd_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset); | 1031 | lcd_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset); |
939 | } | 1032 | } |
940 | 1033 | ||
1034 | /* Initialise a scrolling line at (x,y) in current viewport */ | ||
1035 | |||
941 | void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | 1036 | void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, |
942 | int style, int offset) | 1037 | int style, int offset) |
943 | { | 1038 | { |
944 | struct scrollinfo* s; | 1039 | struct scrollinfo* s; |
945 | int w, h; | 1040 | int w, h; |
946 | 1041 | ||
947 | if(y>=LCD_SCROLLABLE_LINES) return; | 1042 | if ((unsigned)y >= (unsigned)current_vp->height) |
1043 | return; | ||
1044 | |||
1045 | /* remove any previously scrolling line at the same location */ | ||
1046 | lcd_scroll_stop_line(current_vp, y); | ||
1047 | |||
1048 | if (lcd_scroll_info.lines >= LCD_SCROLLABLE_LINES) return; | ||
948 | 1049 | ||
949 | s = &lcd_scroll_info.scroll[y]; | 1050 | s = &lcd_scroll_info.scroll[lcd_scroll_info.lines]; |
950 | 1051 | ||
951 | s->start_tick = current_tick + lcd_scroll_info.delay; | 1052 | s->start_tick = current_tick + lcd_scroll_info.delay; |
952 | s->style = style; | 1053 | s->style = style; |
@@ -954,7 +1055,7 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
954 | 1055 | ||
955 | lcd_getstringsize(string, &w, &h); | 1056 | lcd_getstringsize(string, &w, &h); |
956 | 1057 | ||
957 | if (LCD_WIDTH - x * 8 - xmargin < w) { | 1058 | if (current_vp->width - x * 8 - current_vp->xmargin < w) { |
958 | /* prepare scroll line */ | 1059 | /* prepare scroll line */ |
959 | char *end; | 1060 | char *end; |
960 | 1061 | ||
@@ -967,7 +1068,7 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
967 | /* scroll bidirectional or forward only depending on the string | 1068 | /* scroll bidirectional or forward only depending on the string |
968 | width */ | 1069 | width */ |
969 | if ( lcd_scroll_info.bidir_limit ) { | 1070 | if ( lcd_scroll_info.bidir_limit ) { |
970 | s->bidir = s->width < (LCD_WIDTH - xmargin) * | 1071 | s->bidir = s->width < (current_vp->width - current_vp->xmargin) * |
971 | (100 + lcd_scroll_info.bidir_limit) / 100; | 1072 | (100 + lcd_scroll_info.bidir_limit) / 100; |
972 | } | 1073 | } |
973 | else | 1074 | else |
@@ -980,17 +1081,16 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
980 | } | 1081 | } |
981 | 1082 | ||
982 | end = strchr(s->line, '\0'); | 1083 | end = strchr(s->line, '\0'); |
983 | strncpy(end, string, LCD_WIDTH/2); | 1084 | strncpy(end, string, current_vp->width/2); |
984 | 1085 | ||
1086 | s->vp = current_vp; | ||
1087 | s->y = y; | ||
985 | s->len = utf8length(string); | 1088 | s->len = utf8length(string); |
986 | s->offset = offset; | 1089 | s->offset = offset; |
987 | s->startx = xmargin + x * s->width / s->len; | 1090 | s->startx = current_vp->xmargin + x * s->width / s->len; |
988 | s->backward = false; | 1091 | s->backward = false; |
989 | lcd_scroll_info.lines |= (1<<y); | 1092 | lcd_scroll_info.lines++; |
990 | } | 1093 | } |
991 | else | ||
992 | /* force a bit switch-off since it doesn't scroll */ | ||
993 | lcd_scroll_info.lines &= ~(1<<y); | ||
994 | } | 1094 | } |
995 | 1095 | ||
996 | void lcd_scroll_fn(void) | 1096 | void lcd_scroll_fn(void) |
@@ -1000,28 +1100,29 @@ void lcd_scroll_fn(void) | |||
1000 | int index; | 1100 | int index; |
1001 | int xpos, ypos; | 1101 | int xpos, ypos; |
1002 | int lastmode; | 1102 | int lastmode; |
1003 | unsigned old_fgcolor = fg_pattern; | 1103 | unsigned old_fgcolor; |
1004 | unsigned old_bgcolor = bg_pattern; | 1104 | unsigned old_bgcolor; |
1005 | 1105 | struct viewport* old_vp = current_vp; | |
1006 | for ( index = 0; index < LCD_SCROLLABLE_LINES; index++ ) { | ||
1007 | /* really scroll? */ | ||
1008 | if ((lcd_scroll_info.lines & (1 << index)) == 0) | ||
1009 | continue; | ||
1010 | 1106 | ||
1107 | for ( index = 0; index < lcd_scroll_info.lines; index++ ) { | ||
1011 | s = &lcd_scroll_info.scroll[index]; | 1108 | s = &lcd_scroll_info.scroll[index]; |
1012 | 1109 | ||
1013 | /* check pause */ | 1110 | /* check pause */ |
1014 | if (TIME_BEFORE(current_tick, s->start_tick)) | 1111 | if (TIME_BEFORE(current_tick, s->start_tick)) |
1015 | continue; | 1112 | continue; |
1016 | 1113 | ||
1114 | lcd_set_viewport(s->vp); | ||
1115 | old_fgcolor = current_vp->fg_pattern; | ||
1116 | old_bgcolor = current_vp->bg_pattern; | ||
1117 | |||
1017 | if (s->style&STYLE_COLORED) { | 1118 | if (s->style&STYLE_COLORED) { |
1018 | if (s->style&STYLE_MODE_MASK) { | 1119 | if (s->style&STYLE_MODE_MASK) { |
1019 | fg_pattern = old_fgcolor; | 1120 | current_vp->fg_pattern = old_fgcolor; |
1020 | bg_pattern = s->style&STYLE_COLOR_MASK; | 1121 | current_vp->bg_pattern = s->style&STYLE_COLOR_MASK; |
1021 | } | 1122 | } |
1022 | else { | 1123 | else { |
1023 | fg_pattern = s->style&STYLE_COLOR_MASK; | 1124 | current_vp->fg_pattern = s->style&STYLE_COLOR_MASK; |
1024 | bg_pattern = old_bgcolor; | 1125 | current_vp->bg_pattern = old_bgcolor; |
1025 | } | 1126 | } |
1026 | } | 1127 | } |
1027 | 1128 | ||
@@ -1030,9 +1131,9 @@ void lcd_scroll_fn(void) | |||
1030 | else | 1131 | else |
1031 | s->offset += lcd_scroll_info.step; | 1132 | s->offset += lcd_scroll_info.step; |
1032 | 1133 | ||
1033 | pf = font_get(curfont); | 1134 | pf = font_get(current_vp->font); |
1034 | xpos = s->startx; | 1135 | xpos = s->startx; |
1035 | ypos = ymargin + index * pf->height; | 1136 | ypos = current_vp->ymargin + s->y * pf->height; |
1036 | 1137 | ||
1037 | if (s->bidir) { /* scroll bidirectional */ | 1138 | if (s->bidir) { /* scroll bidirectional */ |
1038 | if (s->offset <= 0) { | 1139 | if (s->offset <= 0) { |
@@ -1041,9 +1142,9 @@ void lcd_scroll_fn(void) | |||
1041 | s->backward = false; | 1142 | s->backward = false; |
1042 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | 1143 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; |
1043 | } | 1144 | } |
1044 | if (s->offset >= s->width - (LCD_WIDTH - xpos)) { | 1145 | if (s->offset >= s->width - (current_vp->width - xpos)) { |
1045 | /* at end of line */ | 1146 | /* at end of line */ |
1046 | s->offset = s->width - (LCD_WIDTH - xpos); | 1147 | s->offset = s->width - (current_vp->width - xpos); |
1047 | s->backward = true; | 1148 | s->backward = true; |
1048 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | 1149 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; |
1049 | } | 1150 | } |
@@ -1054,35 +1155,36 @@ void lcd_scroll_fn(void) | |||
1054 | s->offset %= s->width; | 1155 | s->offset %= s->width; |
1055 | } | 1156 | } |
1056 | 1157 | ||
1057 | lastmode = drawmode; | 1158 | lastmode = current_vp->drawmode; |
1058 | switch (s->style&STYLE_MODE_MASK) { | 1159 | switch (s->style&STYLE_MODE_MASK) { |
1059 | case STYLE_INVERT: | 1160 | case STYLE_INVERT: |
1060 | drawmode = DRMODE_SOLID|DRMODE_INVERSEVID; | 1161 | current_vp->drawmode = DRMODE_SOLID|DRMODE_INVERSEVID; |
1061 | break; | 1162 | break; |
1062 | case STYLE_COLORBAR: | 1163 | case STYLE_COLORBAR: |
1063 | /* Solid colour line selector */ | 1164 | /* Solid colour line selector */ |
1064 | drawmode = DRMODE_FG; | 1165 | current_vp->drawmode = DRMODE_FG; |
1065 | fg_pattern = lss_pattern; | 1166 | current_vp->fg_pattern = current_vp->lss_pattern; |
1066 | lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | 1167 | lcd_fillrect(xpos, ypos, current_vp->width - xpos, pf->height); |
1067 | fg_pattern = lst_pattern; | 1168 | current_vp->fg_pattern = current_vp->lst_pattern; |
1068 | break; | 1169 | break; |
1069 | case STYLE_GRADIENT: | 1170 | case STYLE_GRADIENT: |
1070 | /* Gradient line selector */ | 1171 | /* Gradient line selector */ |
1071 | drawmode = DRMODE_FG; | 1172 | current_vp->drawmode = DRMODE_FG; |
1072 | lcd_gradient_rect_scroll(xpos, LCD_WIDTH, ypos, (signed)pf->height, | 1173 | lcd_gradient_rect_scroll(xpos, current_vp->width, ypos, (signed)pf->height, |
1073 | NUMLN_UNPACK(s->style), | 1174 | NUMLN_UNPACK(s->style), |
1074 | CURLN_UNPACK(s->style)); | 1175 | CURLN_UNPACK(s->style)); |
1075 | fg_pattern = lst_pattern; | 1176 | current_vp->fg_pattern = current_vp->lst_pattern; |
1076 | break; | 1177 | break; |
1077 | default: | 1178 | default: |
1078 | drawmode = DRMODE_SOLID; | 1179 | current_vp->drawmode = DRMODE_SOLID; |
1079 | break; | 1180 | break; |
1080 | } | 1181 | } |
1081 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); | 1182 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); |
1082 | drawmode = lastmode; | 1183 | current_vp->drawmode = lastmode; |
1083 | lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | 1184 | current_vp->fg_pattern = old_fgcolor; |
1185 | current_vp->bg_pattern = old_bgcolor; | ||
1186 | lcd_update_viewport_rect(xpos, ypos, current_vp->width - xpos, pf->height); | ||
1084 | } | 1187 | } |
1085 | 1188 | ||
1086 | fg_pattern = old_fgcolor; | 1189 | lcd_set_viewport(old_vp); |
1087 | bg_pattern = old_bgcolor; | ||
1088 | } | 1190 | } |
diff --git a/firmware/drivers/lcd-1bit-vert.c b/firmware/drivers/lcd-1bit-vert.c index bd62e105cb..5c651a9613 100644 --- a/firmware/drivers/lcd-1bit-vert.c +++ b/firmware/drivers/lcd-1bit-vert.c | |||
@@ -35,10 +35,40 @@ | |||
35 | 35 | ||
36 | unsigned char lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]; | 36 | unsigned char lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]; |
37 | 37 | ||
38 | static int drawmode = DRMODE_SOLID; | 38 | static struct viewport default_vp = |
39 | static int xmargin = 0; | 39 | { |
40 | static int ymargin = 0; | 40 | .x = 0, |
41 | static int curfont = FONT_SYSFIXED; | 41 | .y = 0, |
42 | .width = LCD_WIDTH, | ||
43 | .height = LCD_HEIGHT, | ||
44 | .font = FONT_SYSFIXED, | ||
45 | .drawmode = DRMODE_SOLID, | ||
46 | .xmargin = 0, | ||
47 | .ymargin = 0, | ||
48 | }; | ||
49 | |||
50 | static struct viewport* current_vp = &default_vp; | ||
51 | |||
52 | /*** Viewports ***/ | ||
53 | |||
54 | void lcd_set_viewport(struct viewport* vp) | ||
55 | { | ||
56 | if (vp == NULL) | ||
57 | current_vp = &default_vp; | ||
58 | else | ||
59 | current_vp = vp; | ||
60 | } | ||
61 | |||
62 | void lcd_update_viewport(void) | ||
63 | { | ||
64 | lcd_update_rect(current_vp->x, current_vp->y, | ||
65 | current_vp->width, current_vp->height); | ||
66 | } | ||
67 | |||
68 | void lcd_update_viewport_rect(int x, int y, int width, int height) | ||
69 | { | ||
70 | lcd_update_rect(current_vp->x + x, current_vp->y + y, width, height); | ||
71 | } | ||
42 | 72 | ||
43 | /* LCD init */ | 73 | /* LCD init */ |
44 | void lcd_init(void) | 74 | void lcd_init(void) |
@@ -53,38 +83,48 @@ void lcd_init(void) | |||
53 | 83 | ||
54 | void lcd_set_drawmode(int mode) | 84 | void lcd_set_drawmode(int mode) |
55 | { | 85 | { |
56 | drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); | 86 | current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); |
57 | } | 87 | } |
58 | 88 | ||
59 | int lcd_get_drawmode(void) | 89 | int lcd_get_drawmode(void) |
60 | { | 90 | { |
61 | return drawmode; | 91 | return current_vp->drawmode; |
62 | } | 92 | } |
63 | 93 | ||
64 | void lcd_setmargins(int x, int y) | 94 | void lcd_setmargins(int x, int y) |
65 | { | 95 | { |
66 | xmargin = x; | 96 | current_vp->xmargin = x; |
67 | ymargin = y; | 97 | current_vp->ymargin = y; |
68 | } | 98 | } |
69 | 99 | ||
70 | int lcd_getxmargin(void) | 100 | int lcd_getxmargin(void) |
71 | { | 101 | { |
72 | return xmargin; | 102 | return current_vp->xmargin; |
73 | } | 103 | } |
74 | 104 | ||
75 | int lcd_getymargin(void) | 105 | int lcd_getymargin(void) |
76 | { | 106 | { |
77 | return ymargin; | 107 | return current_vp->ymargin; |
108 | } | ||
109 | |||
110 | int lcd_getwidth(void) | ||
111 | { | ||
112 | return current_vp->width; | ||
113 | } | ||
114 | |||
115 | int lcd_getheight(void) | ||
116 | { | ||
117 | return current_vp->height; | ||
78 | } | 118 | } |
79 | 119 | ||
80 | void lcd_setfont(int newfont) | 120 | void lcd_setfont(int newfont) |
81 | { | 121 | { |
82 | curfont = newfont; | 122 | current_vp->font = newfont; |
83 | } | 123 | } |
84 | 124 | ||
85 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) | 125 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) |
86 | { | 126 | { |
87 | return font_getstringsize(str, w, h, curfont); | 127 | return font_getstringsize(str, w, h, current_vp->font); |
88 | } | 128 | } |
89 | 129 | ||
90 | /*** low-level drawing functions ***/ | 130 | /*** low-level drawing functions ***/ |
@@ -187,17 +227,42 @@ lcd_blockfunc_type* const lcd_blockfuncs[8] = { | |||
187 | /* Clear the whole display */ | 227 | /* Clear the whole display */ |
188 | void lcd_clear_display(void) | 228 | void lcd_clear_display(void) |
189 | { | 229 | { |
190 | unsigned bits = (drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; | 230 | unsigned bits = (current_vp->drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; |
191 | 231 | ||
192 | memset(lcd_framebuffer, bits, sizeof lcd_framebuffer); | 232 | memset(lcd_framebuffer, bits, sizeof lcd_framebuffer); |
193 | lcd_scroll_info.lines = 0; | 233 | lcd_scroll_info.lines = 0; |
194 | } | 234 | } |
195 | 235 | ||
236 | void lcd_clear_viewport(void) | ||
237 | { | ||
238 | int oldmode; | ||
239 | |||
240 | if (current_vp == &default_vp) | ||
241 | { | ||
242 | lcd_clear_display(); | ||
243 | } | ||
244 | else | ||
245 | { | ||
246 | oldmode = current_vp->drawmode; | ||
247 | |||
248 | /* Invert the INVERSEVID bit and set basic mode to SOLID */ | ||
249 | current_vp->drawmode = (~current_vp->drawmode & DRMODE_INVERSEVID) | | ||
250 | DRMODE_SOLID; | ||
251 | |||
252 | lcd_fillrect(0, 0, current_vp->width, current_vp->height); | ||
253 | |||
254 | current_vp->drawmode = oldmode; | ||
255 | |||
256 | lcd_scroll_stop(current_vp); | ||
257 | } | ||
258 | } | ||
259 | |||
196 | /* Set a single pixel */ | 260 | /* Set a single pixel */ |
197 | void lcd_drawpixel(int x, int y) | 261 | void lcd_drawpixel(int x, int y) |
198 | { | 262 | { |
199 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) | 263 | if (((unsigned)x < (unsigned)current_vp->width) && |
200 | lcd_pixelfuncs[drawmode](x, y); | 264 | ((unsigned)y < (unsigned)current_vp->height)) |
265 | lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); | ||
201 | } | 266 | } |
202 | 267 | ||
203 | /* Draw a line */ | 268 | /* Draw a line */ |
@@ -209,7 +274,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
209 | int d, dinc1, dinc2; | 274 | int d, dinc1, dinc2; |
210 | int x, xinc1, xinc2; | 275 | int x, xinc1, xinc2; |
211 | int y, yinc1, yinc2; | 276 | int y, yinc1, yinc2; |
212 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; | 277 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[current_vp->drawmode]; |
213 | 278 | ||
214 | deltax = abs(x2 - x1); | 279 | deltax = abs(x2 - x1); |
215 | deltay = abs(y2 - y1); | 280 | deltay = abs(y2 - y1); |
@@ -253,8 +318,9 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
253 | 318 | ||
254 | for (i = 0; i < numpixels; i++) | 319 | for (i = 0; i < numpixels; i++) |
255 | { | 320 | { |
256 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) | 321 | if (((unsigned)x < (unsigned)current_vp->width) && |
257 | pfunc(x, y); | 322 | ((unsigned)y < (unsigned)current_vp->height)) |
323 | pfunc(current_vp->x + x, current_vp->y + y); | ||
258 | 324 | ||
259 | if (d < 0) | 325 | if (d < 0) |
260 | { | 326 | { |
@@ -288,16 +354,22 @@ void lcd_hline(int x1, int x2, int y) | |||
288 | } | 354 | } |
289 | 355 | ||
290 | /* nothing to draw? */ | 356 | /* nothing to draw? */ |
291 | if (((unsigned)y >= LCD_HEIGHT) || (x1 >= LCD_WIDTH) || (x2 < 0)) | 357 | if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) |
358 | || (x2 < 0)) | ||
292 | return; | 359 | return; |
293 | 360 | ||
294 | /* clipping */ | 361 | /* clipping */ |
295 | if (x1 < 0) | 362 | if (x1 < 0) |
296 | x1 = 0; | 363 | x1 = 0; |
297 | if (x2 >= LCD_WIDTH) | 364 | if (x2 >= current_vp->width) |
298 | x2 = LCD_WIDTH-1; | 365 | x2 = current_vp->width-1; |
299 | 366 | ||
300 | bfunc = lcd_blockfuncs[drawmode]; | 367 | /* adjust for viewport */ |
368 | y += current_vp->y; | ||
369 | x1 += current_vp->x; | ||
370 | x2 += current_vp->x; | ||
371 | |||
372 | bfunc = lcd_blockfuncs[current_vp->drawmode]; | ||
301 | dst = &lcd_framebuffer[y>>3][x1]; | 373 | dst = &lcd_framebuffer[y>>3][x1]; |
302 | mask = 1 << (y & 7); | 374 | mask = 1 << (y & 7); |
303 | 375 | ||
@@ -324,16 +396,22 @@ void lcd_vline(int x, int y1, int y2) | |||
324 | } | 396 | } |
325 | 397 | ||
326 | /* nothing to draw? */ | 398 | /* nothing to draw? */ |
327 | if (((unsigned)x >= LCD_WIDTH) || (y1 >= LCD_HEIGHT) || (y2 < 0)) | 399 | if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) |
400 | || (y2 < 0)) | ||
328 | return; | 401 | return; |
329 | 402 | ||
330 | /* clipping */ | 403 | /* clipping */ |
331 | if (y1 < 0) | 404 | if (y1 < 0) |
332 | y1 = 0; | 405 | y1 = 0; |
333 | if (y2 >= LCD_HEIGHT) | 406 | if (y2 >= current_vp->height) |
334 | y2 = LCD_HEIGHT-1; | 407 | y2 = current_vp->height-1; |
335 | 408 | ||
336 | bfunc = lcd_blockfuncs[drawmode]; | 409 | /* adjust for viewport */ |
410 | y1 += current_vp->y; | ||
411 | y2 += current_vp->y; | ||
412 | x += current_vp->x; | ||
413 | |||
414 | bfunc = lcd_blockfuncs[current_vp->drawmode]; | ||
337 | dst = &lcd_framebuffer[y1>>3][x]; | 415 | dst = &lcd_framebuffer[y1>>3][x]; |
338 | ny = y2 - (y1 & ~7); | 416 | ny = y2 - (y1 & ~7); |
339 | mask = 0xFFu << (y1 & 7); | 417 | mask = 0xFFu << (y1 & 7); |
@@ -375,8 +453,8 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
375 | bool fillopt = false; | 453 | bool fillopt = false; |
376 | 454 | ||
377 | /* nothing to draw? */ | 455 | /* nothing to draw? */ |
378 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 456 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
379 | || (x + width <= 0) || (y + height <= 0)) | 457 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
380 | return; | 458 | return; |
381 | 459 | ||
382 | /* clipping */ | 460 | /* clipping */ |
@@ -390,27 +468,31 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
390 | height += y; | 468 | height += y; |
391 | y = 0; | 469 | y = 0; |
392 | } | 470 | } |
393 | if (x + width > LCD_WIDTH) | 471 | if (x + width > current_vp->width) |
394 | width = LCD_WIDTH - x; | 472 | width = current_vp->width - x; |
395 | if (y + height > LCD_HEIGHT) | 473 | if (y + height > current_vp->height) |
396 | height = LCD_HEIGHT - y; | 474 | height = current_vp->height - y; |
397 | 475 | ||
398 | if (drawmode & DRMODE_INVERSEVID) | 476 | /* adjust for viewport */ |
477 | x += current_vp->x; | ||
478 | y += current_vp->y; | ||
479 | |||
480 | if (current_vp->drawmode & DRMODE_INVERSEVID) | ||
399 | { | 481 | { |
400 | if (drawmode & DRMODE_BG) | 482 | if (current_vp->drawmode & DRMODE_BG) |
401 | { | 483 | { |
402 | fillopt = true; | 484 | fillopt = true; |
403 | } | 485 | } |
404 | } | 486 | } |
405 | else | 487 | else |
406 | { | 488 | { |
407 | if (drawmode & DRMODE_FG) | 489 | if (current_vp->drawmode & DRMODE_FG) |
408 | { | 490 | { |
409 | fillopt = true; | 491 | fillopt = true; |
410 | bits = 0xFFu; | 492 | bits = 0xFFu; |
411 | } | 493 | } |
412 | } | 494 | } |
413 | bfunc = lcd_blockfuncs[drawmode]; | 495 | bfunc = lcd_blockfuncs[current_vp->drawmode]; |
414 | dst = &lcd_framebuffer[y>>3][x]; | 496 | dst = &lcd_framebuffer[y>>3][x]; |
415 | ny = height - 1 + (y & 7); | 497 | ny = height - 1 + (y & 7); |
416 | mask = 0xFFu << (y & 7); | 498 | mask = 0xFFu << (y & 7); |
@@ -470,8 +552,8 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
470 | lcd_blockfunc_type *bfunc; | 552 | lcd_blockfunc_type *bfunc; |
471 | 553 | ||
472 | /* nothing to draw? */ | 554 | /* nothing to draw? */ |
473 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 555 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
474 | || (x + width <= 0) || (y + height <= 0)) | 556 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
475 | return; | 557 | return; |
476 | 558 | ||
477 | /* clipping */ | 559 | /* clipping */ |
@@ -487,10 +569,14 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
487 | src_y -= y; | 569 | src_y -= y; |
488 | y = 0; | 570 | y = 0; |
489 | } | 571 | } |
490 | if (x + width > LCD_WIDTH) | 572 | if (x + width > current_vp->width) |
491 | width = LCD_WIDTH - x; | 573 | width = current_vp->width - x; |
492 | if (y + height > LCD_HEIGHT) | 574 | if (y + height > current_vp->height) |
493 | height = LCD_HEIGHT - y; | 575 | height = current_vp->height - y; |
576 | |||
577 | /* adjust for viewport */ | ||
578 | x += current_vp->x; | ||
579 | y += current_vp->y; | ||
494 | 580 | ||
495 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 581 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
496 | src_y &= 7; | 582 | src_y &= 7; |
@@ -499,13 +585,13 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
499 | shift = y & 7; | 585 | shift = y & 7; |
500 | ny = height - 1 + shift + src_y; | 586 | ny = height - 1 + shift + src_y; |
501 | 587 | ||
502 | bfunc = lcd_blockfuncs[drawmode]; | 588 | bfunc = lcd_blockfuncs[current_vp->drawmode]; |
503 | mask = 0xFFu << (shift + src_y); | 589 | mask = 0xFFu << (shift + src_y); |
504 | mask_bottom = 0xFFu >> (~ny & 7); | 590 | mask_bottom = 0xFFu >> (~ny & 7); |
505 | 591 | ||
506 | if (shift == 0) | 592 | if (shift == 0) |
507 | { | 593 | { |
508 | bool copyopt = (drawmode == DRMODE_SOLID); | 594 | bool copyopt = (current_vp->drawmode == DRMODE_SOLID); |
509 | 595 | ||
510 | for (; ny >= 8; ny -= 8) | 596 | for (; ny >= 8; ny -= 8) |
511 | { | 597 | { |
@@ -582,11 +668,11 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
582 | { | 668 | { |
583 | unsigned short ch; | 669 | unsigned short ch; |
584 | unsigned short *ucs; | 670 | unsigned short *ucs; |
585 | struct font* pf = font_get(curfont); | 671 | struct font* pf = font_get(current_vp->font); |
586 | 672 | ||
587 | ucs = bidi_l2v(str, 1); | 673 | ucs = bidi_l2v(str, 1); |
588 | 674 | ||
589 | while ((ch = *ucs++) != 0 && x < LCD_WIDTH) | 675 | while ((ch = *ucs++) != 0 && x < current_vp->width) |
590 | { | 676 | { |
591 | int width; | 677 | int width; |
592 | const unsigned char *bits; | 678 | const unsigned char *bits; |
@@ -639,24 +725,24 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str, | |||
639 | int style, int offset) | 725 | int style, int offset) |
640 | { | 726 | { |
641 | int xpos,ypos,w,h,xrect; | 727 | int xpos,ypos,w,h,xrect; |
642 | int lastmode = drawmode; | 728 | int lastmode = current_vp->drawmode; |
643 | 729 | ||
644 | /* make sure scrolling is turned off on the line we are updating */ | 730 | /* make sure scrolling is turned off on the line we are updating */ |
645 | lcd_scroll_info.lines &= ~(1 << y); | 731 | lcd_scroll_stop_line(current_vp, y); |
646 | 732 | ||
647 | if(!str || !str[0]) | 733 | if(!str || !str[0]) |
648 | return; | 734 | return; |
649 | 735 | ||
650 | lcd_getstringsize(str, &w, &h); | 736 | lcd_getstringsize(str, &w, &h); |
651 | xpos = xmargin + x*w / utf8length(str); | 737 | xpos = current_vp->xmargin + x*w / utf8length(str); |
652 | ypos = ymargin + y*h; | 738 | ypos = current_vp->ymargin + y*h; |
653 | drawmode = (style & STYLE_INVERT) ? | 739 | current_vp->drawmode = (style & STYLE_INVERT) ? |
654 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | 740 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; |
655 | lcd_putsxyofs(xpos, ypos, offset, str); | 741 | lcd_putsxyofs(xpos, ypos, offset, str); |
656 | drawmode ^= DRMODE_INVERSEVID; | 742 | current_vp->drawmode ^= DRMODE_INVERSEVID; |
657 | xrect = xpos + MAX(w - offset, 0); | 743 | xrect = xpos + MAX(w - offset, 0); |
658 | lcd_fillrect(xrect, ypos, LCD_WIDTH - xrect, h); | 744 | lcd_fillrect(xrect, ypos, current_vp->width - xrect, h); |
659 | drawmode = lastmode; | 745 | current_vp->drawmode = lastmode; |
660 | } | 746 | } |
661 | 747 | ||
662 | /*** scrolling ***/ | 748 | /*** scrolling ***/ |
@@ -682,9 +768,15 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
682 | struct scrollinfo* s; | 768 | struct scrollinfo* s; |
683 | int w, h; | 769 | int w, h; |
684 | 770 | ||
685 | if(y>=LCD_SCROLLABLE_LINES) return; | 771 | if ((unsigned)y >= (unsigned)current_vp->height) |
772 | return; | ||
773 | |||
774 | /* remove any previously scrolling line at the same location */ | ||
775 | lcd_scroll_stop_line(current_vp, y); | ||
776 | |||
777 | if (lcd_scroll_info.lines >= LCD_SCROLLABLE_LINES) return; | ||
686 | 778 | ||
687 | s = &lcd_scroll_info.scroll[y]; | 779 | s = &lcd_scroll_info.scroll[lcd_scroll_info.lines]; |
688 | 780 | ||
689 | s->start_tick = current_tick + lcd_scroll_info.delay; | 781 | s->start_tick = current_tick + lcd_scroll_info.delay; |
690 | s->style = style; | 782 | s->style = style; |
@@ -696,7 +788,7 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
696 | 788 | ||
697 | lcd_getstringsize(string, &w, &h); | 789 | lcd_getstringsize(string, &w, &h); |
698 | 790 | ||
699 | if (LCD_WIDTH - x * 8 - xmargin < w) { | 791 | if (current_vp->width - x * 8 - current_vp->xmargin < w) { |
700 | /* prepare scroll line */ | 792 | /* prepare scroll line */ |
701 | char *end; | 793 | char *end; |
702 | 794 | ||
@@ -709,7 +801,7 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
709 | /* scroll bidirectional or forward only depending on the string | 801 | /* scroll bidirectional or forward only depending on the string |
710 | width */ | 802 | width */ |
711 | if ( lcd_scroll_info.bidir_limit ) { | 803 | if ( lcd_scroll_info.bidir_limit ) { |
712 | s->bidir = s->width < (LCD_WIDTH - xmargin) * | 804 | s->bidir = s->width < (current_vp->width - current_vp->xmargin) * |
713 | (100 + lcd_scroll_info.bidir_limit) / 100; | 805 | (100 + lcd_scroll_info.bidir_limit) / 100; |
714 | } | 806 | } |
715 | else | 807 | else |
@@ -722,17 +814,16 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
722 | } | 814 | } |
723 | 815 | ||
724 | end = strchr(s->line, '\0'); | 816 | end = strchr(s->line, '\0'); |
725 | strncpy(end, string, LCD_WIDTH/2); | 817 | strncpy(end, string, current_vp->width/2); |
726 | 818 | ||
819 | s->vp = current_vp; | ||
820 | s->y = y; | ||
727 | s->len = utf8length(string); | 821 | s->len = utf8length(string); |
728 | s->offset = offset; | 822 | s->offset = offset; |
729 | s->startx = xmargin + x * s->width / s->len;; | 823 | s->startx = current_vp->xmargin + x * s->width / s->len;; |
730 | s->backward = false; | 824 | s->backward = false; |
731 | lcd_scroll_info.lines |= (1<<y); | 825 | lcd_scroll_info.lines++; |
732 | } | 826 | } |
733 | else | ||
734 | /* force a bit switch-off since it doesn't scroll */ | ||
735 | lcd_scroll_info.lines &= ~(1<<y); | ||
736 | } | 827 | } |
737 | 828 | ||
738 | void lcd_scroll_fn(void) | 829 | void lcd_scroll_fn(void) |
@@ -742,26 +833,25 @@ void lcd_scroll_fn(void) | |||
742 | int index; | 833 | int index; |
743 | int xpos, ypos; | 834 | int xpos, ypos; |
744 | int lastmode; | 835 | int lastmode; |
836 | struct viewport* old_vp = current_vp; | ||
745 | 837 | ||
746 | for ( index = 0; index < LCD_SCROLLABLE_LINES; index++ ) { | 838 | for ( index = 0; index < lcd_scroll_info.lines; index++ ) { |
747 | /* really scroll? */ | ||
748 | if ((lcd_scroll_info.lines & (1 << index)) == 0) | ||
749 | continue; | ||
750 | |||
751 | s = &lcd_scroll_info.scroll[index]; | 839 | s = &lcd_scroll_info.scroll[index]; |
752 | 840 | ||
753 | /* check pause */ | 841 | /* check pause */ |
754 | if (TIME_BEFORE(current_tick, s->start_tick)) | 842 | if (TIME_BEFORE(current_tick, s->start_tick)) |
755 | continue; | 843 | continue; |
756 | 844 | ||
845 | lcd_set_viewport(s->vp); | ||
846 | |||
757 | if (s->backward) | 847 | if (s->backward) |
758 | s->offset -= lcd_scroll_info.step; | 848 | s->offset -= lcd_scroll_info.step; |
759 | else | 849 | else |
760 | s->offset += lcd_scroll_info.step; | 850 | s->offset += lcd_scroll_info.step; |
761 | 851 | ||
762 | pf = font_get(curfont); | 852 | pf = font_get(current_vp->font); |
763 | xpos = s->startx; | 853 | xpos = s->startx; |
764 | ypos = ymargin + index * pf->height; | 854 | ypos = current_vp->ymargin + s->y * pf->height; |
765 | 855 | ||
766 | if (s->bidir) { /* scroll bidirectional */ | 856 | if (s->bidir) { /* scroll bidirectional */ |
767 | if (s->offset <= 0) { | 857 | if (s->offset <= 0) { |
@@ -770,9 +860,9 @@ void lcd_scroll_fn(void) | |||
770 | s->backward = false; | 860 | s->backward = false; |
771 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | 861 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; |
772 | } | 862 | } |
773 | if (s->offset >= s->width - (LCD_WIDTH - xpos)) { | 863 | if (s->offset >= s->width - (current_vp->width - xpos)) { |
774 | /* at end of line */ | 864 | /* at end of line */ |
775 | s->offset = s->width - (LCD_WIDTH - xpos); | 865 | s->offset = s->width - (current_vp->width - xpos); |
776 | s->backward = true; | 866 | s->backward = true; |
777 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | 867 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; |
778 | } | 868 | } |
@@ -783,11 +873,13 @@ void lcd_scroll_fn(void) | |||
783 | s->offset %= s->width; | 873 | s->offset %= s->width; |
784 | } | 874 | } |
785 | 875 | ||
786 | lastmode = drawmode; | 876 | lastmode = current_vp->drawmode; |
787 | drawmode = (s->style&STYLE_INVERT) ? | 877 | current_vp->drawmode = (s->style&STYLE_INVERT) ? |
788 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | 878 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; |
789 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); | 879 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); |
790 | drawmode = lastmode; | 880 | current_vp->drawmode = lastmode; |
791 | lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | 881 | lcd_update_viewport_rect(xpos, ypos, current_vp->width - xpos, pf->height); |
792 | } | 882 | } |
883 | |||
884 | lcd_set_viewport(old_vp); | ||
793 | } | 885 | } |
diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c index 32ebfa7f81..1ee0addba4 100644 --- a/firmware/drivers/lcd-2bit-horz.c +++ b/firmware/drivers/lcd-2bit-horz.c | |||
@@ -46,52 +46,92 @@ static const unsigned char pixmask[4] ICONST_ATTR = { | |||
46 | static fb_data* lcd_backdrop = NULL; | 46 | static fb_data* lcd_backdrop = NULL; |
47 | static long lcd_backdrop_offset IDATA_ATTR = 0; | 47 | static long lcd_backdrop_offset IDATA_ATTR = 0; |
48 | 48 | ||
49 | static unsigned fg_pattern IDATA_ATTR = 0xFF; /* initially black */ | 49 | static struct viewport default_vp = |
50 | static unsigned bg_pattern IDATA_ATTR = 0x00; /* initially white */ | 50 | { |
51 | static int drawmode = DRMODE_SOLID; | 51 | .x = 0, |
52 | static int xmargin = 0; | 52 | .y = 0, |
53 | static int ymargin = 0; | 53 | .width = LCD_WIDTH, |
54 | static int curfont = FONT_SYSFIXED; | 54 | .height = LCD_HEIGHT, |
55 | .font = FONT_SYSFIXED, | ||
56 | .drawmode = DRMODE_SOLID, | ||
57 | .xmargin = 0, | ||
58 | .ymargin = 0, | ||
59 | .fg_pattern = LCD_DEFAULT_FG, | ||
60 | .bg_pattern = LCD_DEFAULT_BG | ||
61 | }; | ||
62 | |||
63 | static struct viewport* current_vp IBSS_ATTR; | ||
64 | static unsigned fg_pattern IBSS_ATTR; | ||
65 | static unsigned bg_pattern IBSS_ATTR; | ||
55 | 66 | ||
56 | /* LCD init */ | 67 | /* LCD init */ |
57 | void lcd_init(void) | 68 | void lcd_init(void) |
58 | { | 69 | { |
70 | /* Initialise the viewport */ | ||
71 | lcd_set_viewport(NULL); | ||
72 | |||
59 | lcd_clear_display(); | 73 | lcd_clear_display(); |
60 | /* Call device specific init */ | 74 | /* Call device specific init */ |
61 | lcd_init_device(); | 75 | lcd_init_device(); |
62 | scroll_init(); | 76 | scroll_init(); |
63 | } | 77 | } |
64 | 78 | ||
79 | /*** Viewports ***/ | ||
80 | |||
81 | void lcd_set_viewport(struct viewport* vp) | ||
82 | { | ||
83 | if (vp == NULL) | ||
84 | current_vp = &default_vp; | ||
85 | else | ||
86 | current_vp = vp; | ||
87 | |||
88 | fg_pattern = 0x55 * (~current_vp->fg_pattern & 3); | ||
89 | bg_pattern = 0x55 * (~current_vp->bg_pattern & 3); | ||
90 | } | ||
91 | |||
92 | void lcd_update_viewport(void) | ||
93 | { | ||
94 | lcd_update_rect(current_vp->x, current_vp->y, | ||
95 | current_vp->width, current_vp->height); | ||
96 | } | ||
97 | |||
98 | void lcd_update_viewport_rect(int x, int y, int width, int height) | ||
99 | { | ||
100 | lcd_update_rect(current_vp->x + x, current_vp->y + y, width, height); | ||
101 | } | ||
102 | |||
65 | /*** parameter handling ***/ | 103 | /*** parameter handling ***/ |
66 | 104 | ||
67 | void lcd_set_drawmode(int mode) | 105 | void lcd_set_drawmode(int mode) |
68 | { | 106 | { |
69 | drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); | 107 | current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); |
70 | } | 108 | } |
71 | 109 | ||
72 | int lcd_get_drawmode(void) | 110 | int lcd_get_drawmode(void) |
73 | { | 111 | { |
74 | return drawmode; | 112 | return current_vp->drawmode; |
75 | } | 113 | } |
76 | 114 | ||
77 | void lcd_set_foreground(unsigned brightness) | 115 | void lcd_set_foreground(unsigned brightness) |
78 | { | 116 | { |
117 | current_vp->fg_pattern = brightness; | ||
79 | fg_pattern = 0x55 * (~brightness & 3); | 118 | fg_pattern = 0x55 * (~brightness & 3); |
80 | } | 119 | } |
81 | 120 | ||
82 | unsigned lcd_get_foreground(void) | 121 | unsigned lcd_get_foreground(void) |
83 | { | 122 | { |
84 | return ~fg_pattern & 3; | 123 | return current_vp->fg_pattern; |
85 | } | 124 | } |
86 | 125 | ||
87 | void lcd_set_background(unsigned brightness) | 126 | void lcd_set_background(unsigned brightness) |
88 | { | 127 | { |
128 | current_vp->bg_pattern = brightness; | ||
89 | bg_pattern = 0x55 * (~brightness & 3); | 129 | bg_pattern = 0x55 * (~brightness & 3); |
90 | } | 130 | } |
91 | 131 | ||
92 | unsigned lcd_get_background(void) | 132 | unsigned lcd_get_background(void) |
93 | { | 133 | { |
94 | return ~bg_pattern & 3; | 134 | return current_vp->bg_pattern; |
95 | } | 135 | } |
96 | 136 | ||
97 | void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) | 137 | void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) |
@@ -103,28 +143,38 @@ void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) | |||
103 | 143 | ||
104 | void lcd_setmargins(int x, int y) | 144 | void lcd_setmargins(int x, int y) |
105 | { | 145 | { |
106 | xmargin = x; | 146 | current_vp->xmargin = x; |
107 | ymargin = y; | 147 | current_vp->ymargin = y; |
108 | } | 148 | } |
109 | 149 | ||
110 | int lcd_getxmargin(void) | 150 | int lcd_getxmargin(void) |
111 | { | 151 | { |
112 | return xmargin; | 152 | return current_vp->xmargin; |
113 | } | 153 | } |
114 | 154 | ||
115 | int lcd_getymargin(void) | 155 | int lcd_getymargin(void) |
116 | { | 156 | { |
117 | return ymargin; | 157 | return current_vp->ymargin; |
158 | } | ||
159 | |||
160 | int lcd_getwidth(void) | ||
161 | { | ||
162 | return current_vp->width; | ||
163 | } | ||
164 | |||
165 | int lcd_getheight(void) | ||
166 | { | ||
167 | return current_vp->height; | ||
118 | } | 168 | } |
119 | 169 | ||
120 | void lcd_setfont(int newfont) | 170 | void lcd_setfont(int newfont) |
121 | { | 171 | { |
122 | curfont = newfont; | 172 | current_vp->font = newfont; |
123 | } | 173 | } |
124 | 174 | ||
125 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) | 175 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) |
126 | { | 176 | { |
127 | return font_getstringsize(str, w, h, curfont); | 177 | return font_getstringsize(str, w, h, current_vp->font); |
128 | } | 178 | } |
129 | 179 | ||
130 | /*** low-level drawing functions ***/ | 180 | /*** low-level drawing functions ***/ |
@@ -345,7 +395,7 @@ static inline void setblock(fb_data *address, unsigned mask, unsigned bits) | |||
345 | /* Clear the whole display */ | 395 | /* Clear the whole display */ |
346 | void lcd_clear_display(void) | 396 | void lcd_clear_display(void) |
347 | { | 397 | { |
348 | if (drawmode & DRMODE_INVERSEVID) | 398 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
349 | { | 399 | { |
350 | memset(lcd_framebuffer, fg_pattern, sizeof lcd_framebuffer); | 400 | memset(lcd_framebuffer, fg_pattern, sizeof lcd_framebuffer); |
351 | } | 401 | } |
@@ -360,11 +410,37 @@ void lcd_clear_display(void) | |||
360 | lcd_scroll_info.lines = 0; | 410 | lcd_scroll_info.lines = 0; |
361 | } | 411 | } |
362 | 412 | ||
413 | /* Clear the current viewport */ | ||
414 | void lcd_clear_viewport(void) | ||
415 | { | ||
416 | int lastmode; | ||
417 | |||
418 | if (current_vp == &default_vp) | ||
419 | { | ||
420 | lcd_clear_display(); | ||
421 | } | ||
422 | else | ||
423 | { | ||
424 | lastmode = current_vp->drawmode; | ||
425 | |||
426 | /* Invert the INVERSEVID bit and set basic mode to SOLID */ | ||
427 | current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | | ||
428 | DRMODE_SOLID; | ||
429 | |||
430 | lcd_fillrect(0, 0, current_vp->width, current_vp->height); | ||
431 | |||
432 | current_vp->drawmode = lastmode; | ||
433 | |||
434 | lcd_scroll_stop(current_vp); | ||
435 | } | ||
436 | } | ||
437 | |||
363 | /* Set a single pixel */ | 438 | /* Set a single pixel */ |
364 | void lcd_drawpixel(int x, int y) | 439 | void lcd_drawpixel(int x, int y) |
365 | { | 440 | { |
366 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) | 441 | if (((unsigned)x < (unsigned)current_vp->width) && |
367 | lcd_pixelfuncs[drawmode](x, y); | 442 | ((unsigned)y < (unsigned)current_vp->height)) |
443 | lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); | ||
368 | } | 444 | } |
369 | 445 | ||
370 | /* Draw a line */ | 446 | /* Draw a line */ |
@@ -376,7 +452,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
376 | int d, dinc1, dinc2; | 452 | int d, dinc1, dinc2; |
377 | int x, xinc1, xinc2; | 453 | int x, xinc1, xinc2; |
378 | int y, yinc1, yinc2; | 454 | int y, yinc1, yinc2; |
379 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; | 455 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[current_vp->drawmode]; |
380 | 456 | ||
381 | deltax = abs(x2 - x1); | 457 | deltax = abs(x2 - x1); |
382 | deltay = abs(y2 - y1); | 458 | deltay = abs(y2 - y1); |
@@ -420,8 +496,9 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
420 | 496 | ||
421 | for (i = 0; i < numpixels; i++) | 497 | for (i = 0; i < numpixels; i++) |
422 | { | 498 | { |
423 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) | 499 | if (((unsigned)x < (unsigned)current_vp->width) && |
424 | pfunc(x, y); | 500 | ((unsigned)y < (unsigned)current_vp->height)) |
501 | pfunc(current_vp->x + x, current_vp->y + y); | ||
425 | 502 | ||
426 | if (d < 0) | 503 | if (d < 0) |
427 | { | 504 | { |
@@ -455,16 +532,22 @@ void lcd_hline(int x1, int x2, int y) | |||
455 | } | 532 | } |
456 | 533 | ||
457 | /* nothing to draw? */ | 534 | /* nothing to draw? */ |
458 | if (((unsigned)y >= LCD_HEIGHT) || (x1 >= LCD_WIDTH) || (x2 < 0)) | 535 | if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) |
536 | || (x2 < 0)) | ||
459 | return; | 537 | return; |
460 | 538 | ||
461 | /* clipping */ | 539 | /* clipping */ |
462 | if (x1 < 0) | 540 | if (x1 < 0) |
463 | x1 = 0; | 541 | x1 = 0; |
464 | if (x2 >= LCD_WIDTH) | 542 | if (x2 >= current_vp->width) |
465 | x2 = LCD_WIDTH-1; | 543 | x2 = current_vp->width-1; |
466 | 544 | ||
467 | bfunc = lcd_blockfuncs[drawmode]; | 545 | /* adjust to viewport */ |
546 | x1 += current_vp->x; | ||
547 | x2 += current_vp->x; | ||
548 | y += current_vp->y; | ||
549 | |||
550 | bfunc = lcd_blockfuncs[current_vp->drawmode]; | ||
468 | dst = &lcd_framebuffer[y][x1>>2]; | 551 | dst = &lcd_framebuffer[y][x1>>2]; |
469 | nx = x2 - (x1 & ~3); | 552 | nx = x2 - (x1 & ~3); |
470 | mask = 0xFFu >> (2 * (x1 & 3)); | 553 | mask = 0xFFu >> (2 * (x1 & 3)); |
@@ -496,16 +579,22 @@ void lcd_vline(int x, int y1, int y2) | |||
496 | } | 579 | } |
497 | 580 | ||
498 | /* nothing to draw? */ | 581 | /* nothing to draw? */ |
499 | if (((unsigned)x >= LCD_WIDTH) || (y1 >= LCD_HEIGHT) || (y2 < 0)) | 582 | if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) |
583 | || (y2 < 0)) | ||
500 | return; | 584 | return; |
501 | 585 | ||
502 | /* clipping */ | 586 | /* clipping */ |
503 | if (y1 < 0) | 587 | if (y1 < 0) |
504 | y1 = 0; | 588 | y1 = 0; |
505 | if (y2 >= LCD_HEIGHT) | 589 | if (y2 >= current_vp->height) |
506 | y2 = LCD_HEIGHT-1; | 590 | y2 = current_vp->height-1; |
591 | |||
592 | /* adjust for viewport */ | ||
593 | y1 += current_vp->y; | ||
594 | y2 += current_vp->y; | ||
595 | x += current_vp->x; | ||
507 | 596 | ||
508 | bfunc = lcd_blockfuncs[drawmode]; | 597 | bfunc = lcd_blockfuncs[current_vp->drawmode]; |
509 | dst = &lcd_framebuffer[y1][x>>2]; | 598 | dst = &lcd_framebuffer[y1][x>>2]; |
510 | mask = pixmask[x & 3]; | 599 | mask = pixmask[x & 3]; |
511 | 600 | ||
@@ -542,7 +631,7 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
542 | lcd_blockfunc_type *bfunc; | 631 | lcd_blockfunc_type *bfunc; |
543 | 632 | ||
544 | /* nothing to draw? */ | 633 | /* nothing to draw? */ |
545 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 634 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || (y >= current_vp->height) |
546 | || (x + width <= 0) || (y + height <= 0)) | 635 | || (x + width <= 0) || (y + height <= 0)) |
547 | return; | 636 | return; |
548 | 637 | ||
@@ -557,12 +646,16 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
557 | height += y; | 646 | height += y; |
558 | y = 0; | 647 | y = 0; |
559 | } | 648 | } |
560 | if (x + width > LCD_WIDTH) | 649 | if (x + width > current_vp->width) |
561 | width = LCD_WIDTH - x; | 650 | width = current_vp->width - x; |
562 | if (y + height > LCD_HEIGHT) | 651 | if (y + height > current_vp->height) |
563 | height = LCD_HEIGHT - y; | 652 | height = current_vp->height - y; |
653 | |||
654 | /* adjust for viewport */ | ||
655 | x += current_vp->x; | ||
656 | y += current_vp->y; | ||
564 | 657 | ||
565 | bfunc = lcd_blockfuncs[drawmode]; | 658 | bfunc = lcd_blockfuncs[current_vp->drawmode]; |
566 | dst = &lcd_framebuffer[y][x>>2]; | 659 | dst = &lcd_framebuffer[y][x>>2]; |
567 | nx = width - 1 + (x & 3); | 660 | nx = width - 1 + (x & 3); |
568 | mask = 0xFFu >> (2 * (x & 3)); | 661 | mask = 0xFFu >> (2 * (x & 3)); |
@@ -616,8 +709,8 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
616 | lcd_pixelfunc_type* bgfunc; | 709 | lcd_pixelfunc_type* bgfunc; |
617 | 710 | ||
618 | /* nothing to draw? */ | 711 | /* nothing to draw? */ |
619 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 712 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
620 | || (x + width <= 0) || (y + height <= 0)) | 713 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
621 | return; | 714 | return; |
622 | 715 | ||
623 | /* clipping */ | 716 | /* clipping */ |
@@ -633,17 +726,21 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
633 | src_y -= y; | 726 | src_y -= y; |
634 | y = 0; | 727 | y = 0; |
635 | } | 728 | } |
636 | if (x + width > LCD_WIDTH) | 729 | if (x + width > current_vp->width) |
637 | width = LCD_WIDTH - x; | 730 | width = current_vp->width - x; |
638 | if (y + height > LCD_HEIGHT) | 731 | if (y + height > current_vp->height) |
639 | height = LCD_HEIGHT - y; | 732 | height = current_vp->height - y; |
733 | |||
734 | /* adjust for viewport */ | ||
735 | x += current_vp->x; | ||
736 | y += current_vp->y; | ||
640 | 737 | ||
641 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 738 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
642 | src_y &= 7; | 739 | src_y &= 7; |
643 | src_end = src + width; | 740 | src_end = src + width; |
644 | 741 | ||
645 | fgfunc = lcd_pixelfuncs[drawmode]; | 742 | fgfunc = lcd_pixelfuncs[current_vp->drawmode]; |
646 | bgfunc = lcd_pixelfuncs[drawmode ^ DRMODE_INVERSEVID]; | 743 | bgfunc = lcd_pixelfuncs[current_vp->drawmode ^ DRMODE_INVERSEVID]; |
647 | nx = x; | 744 | nx = x; |
648 | do | 745 | do |
649 | { | 746 | { |
@@ -704,8 +801,8 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
704 | unsigned mask, mask_right; | 801 | unsigned mask, mask_right; |
705 | 802 | ||
706 | /* nothing to draw? */ | 803 | /* nothing to draw? */ |
707 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 804 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
708 | || (x + width <= 0) || (y + height <= 0)) | 805 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
709 | return; | 806 | return; |
710 | 807 | ||
711 | /* clipping */ | 808 | /* clipping */ |
@@ -721,10 +818,14 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
721 | src_y -= y; | 818 | src_y -= y; |
722 | y = 0; | 819 | y = 0; |
723 | } | 820 | } |
724 | if (x + width > LCD_WIDTH) | 821 | if (x + width > current_vp->width) |
725 | width = LCD_WIDTH - x; | 822 | width = current_vp->width - x; |
726 | if (y + height > LCD_HEIGHT) | 823 | if (y + height > current_vp->height) |
727 | height = LCD_HEIGHT - y; | 824 | height = current_vp->height - y; |
825 | |||
826 | /* adjust for viewport */ | ||
827 | x += current_vp->x; | ||
828 | y += current_vp->y; | ||
728 | 829 | ||
729 | stride = (stride + 3) >> 2; /* convert to no. of bytes */ | 830 | stride = (stride + 3) >> 2; /* convert to no. of bytes */ |
730 | 831 | ||
@@ -781,11 +882,11 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
781 | { | 882 | { |
782 | unsigned short ch; | 883 | unsigned short ch; |
783 | unsigned short *ucs; | 884 | unsigned short *ucs; |
784 | struct font* pf = font_get(curfont); | 885 | struct font* pf = font_get(current_vp->font); |
785 | 886 | ||
786 | ucs = bidi_l2v(str, 1); | 887 | ucs = bidi_l2v(str, 1); |
787 | 888 | ||
788 | while ((ch = *ucs++) != 0 && x < LCD_WIDTH) | 889 | while ((ch = *ucs++) != 0 && x < current_vp->width) |
789 | { | 890 | { |
790 | int width; | 891 | int width; |
791 | const unsigned char *bits; | 892 | const unsigned char *bits; |
@@ -839,24 +940,24 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str, | |||
839 | int style, int offset) | 940 | int style, int offset) |
840 | { | 941 | { |
841 | int xpos,ypos,w,h,xrect; | 942 | int xpos,ypos,w,h,xrect; |
842 | int lastmode = drawmode; | 943 | int lastmode = current_vp->drawmode; |
843 | 944 | ||
844 | /* make sure scrolling is turned off on the line we are updating */ | 945 | /* make sure scrolling is turned off on the line we are updating */ |
845 | lcd_scroll_info.lines &= ~(1 << y); | 946 | lcd_scroll_stop_line(current_vp, y); |
846 | 947 | ||
847 | if(!str || !str[0]) | 948 | if(!str || !str[0]) |
848 | return; | 949 | return; |
849 | 950 | ||
850 | lcd_getstringsize(str, &w, &h); | 951 | lcd_getstringsize(str, &w, &h); |
851 | xpos = xmargin + x*w / utf8length((char *)str); | 952 | xpos = current_vp->xmargin + x*w / utf8length((char *)str); |
852 | ypos = ymargin + y*h; | 953 | ypos = current_vp->ymargin + y*h; |
853 | drawmode = (style & STYLE_INVERT) ? | 954 | current_vp->drawmode = (style & STYLE_INVERT) ? |
854 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | 955 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; |
855 | lcd_putsxyofs(xpos, ypos, offset, str); | 956 | lcd_putsxyofs(xpos, ypos, offset, str); |
856 | drawmode ^= DRMODE_INVERSEVID; | 957 | current_vp->drawmode ^= DRMODE_INVERSEVID; |
857 | xrect = xpos + MAX(w - offset, 0); | 958 | xrect = xpos + MAX(w - offset, 0); |
858 | lcd_fillrect(xrect, ypos, LCD_WIDTH - xrect, h); | 959 | lcd_fillrect(xrect, ypos, current_vp->width - xrect, h); |
859 | drawmode = lastmode; | 960 | current_vp->drawmode = lastmode; |
860 | } | 961 | } |
861 | 962 | ||
862 | /*** scrolling ***/ | 963 | /*** scrolling ***/ |
@@ -881,9 +982,15 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
881 | struct scrollinfo* s; | 982 | struct scrollinfo* s; |
882 | int w, h; | 983 | int w, h; |
883 | 984 | ||
884 | if(y>=LCD_SCROLLABLE_LINES) return; | 985 | if ((unsigned)y >= (unsigned)current_vp->height) |
986 | return; | ||
987 | |||
988 | /* remove any previously scrolling line at the same location */ | ||
989 | lcd_scroll_stop_line(current_vp, y); | ||
885 | 990 | ||
886 | s = &lcd_scroll_info.scroll[y]; | 991 | if (lcd_scroll_info.lines >= LCD_SCROLLABLE_LINES) return; |
992 | |||
993 | s = &lcd_scroll_info.scroll[lcd_scroll_info.lines]; | ||
887 | 994 | ||
888 | s->start_tick = current_tick + lcd_scroll_info.delay; | 995 | s->start_tick = current_tick + lcd_scroll_info.delay; |
889 | s->style = style; | 996 | s->style = style; |
@@ -895,7 +1002,7 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
895 | 1002 | ||
896 | lcd_getstringsize(string, &w, &h); | 1003 | lcd_getstringsize(string, &w, &h); |
897 | 1004 | ||
898 | if (LCD_WIDTH - x * 8 - xmargin < w) { | 1005 | if (current_vp->width - x * 8 - current_vp->xmargin < w) { |
899 | /* prepare scroll line */ | 1006 | /* prepare scroll line */ |
900 | char *end; | 1007 | char *end; |
901 | 1008 | ||
@@ -908,7 +1015,7 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
908 | /* scroll bidirectional or forward only depending on the string | 1015 | /* scroll bidirectional or forward only depending on the string |
909 | width */ | 1016 | width */ |
910 | if ( lcd_scroll_info.bidir_limit ) { | 1017 | if ( lcd_scroll_info.bidir_limit ) { |
911 | s->bidir = s->width < (LCD_WIDTH - xmargin) * | 1018 | s->bidir = s->width < (current_vp->width - current_vp->xmargin) * |
912 | (100 + lcd_scroll_info.bidir_limit) / 100; | 1019 | (100 + lcd_scroll_info.bidir_limit) / 100; |
913 | } | 1020 | } |
914 | else | 1021 | else |
@@ -921,17 +1028,16 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
921 | } | 1028 | } |
922 | 1029 | ||
923 | end = strchr(s->line, '\0'); | 1030 | end = strchr(s->line, '\0'); |
924 | strncpy(end, (char *)string, LCD_WIDTH/2); | 1031 | strncpy(end, (char *)string, current_vp->width/2); |
925 | 1032 | ||
1033 | s->vp = current_vp; | ||
1034 | s->y = y; | ||
926 | s->len = utf8length((char *)string); | 1035 | s->len = utf8length((char *)string); |
927 | s->offset = offset; | 1036 | s->offset = offset; |
928 | s->startx = xmargin + x * s->width / s->len;; | 1037 | s->startx = current_vp->xmargin + x * s->width / s->len;; |
929 | s->backward = false; | 1038 | s->backward = false; |
930 | lcd_scroll_info.lines |= (1<<y); | 1039 | lcd_scroll_info.lines++; |
931 | } | 1040 | } |
932 | else | ||
933 | /* force a bit switch-off since it doesn't scroll */ | ||
934 | lcd_scroll_info.lines &= ~(1<<y); | ||
935 | } | 1041 | } |
936 | 1042 | ||
937 | void lcd_scroll_fn(void) | 1043 | void lcd_scroll_fn(void) |
@@ -941,26 +1047,25 @@ void lcd_scroll_fn(void) | |||
941 | int index; | 1047 | int index; |
942 | int xpos, ypos; | 1048 | int xpos, ypos; |
943 | int lastmode; | 1049 | int lastmode; |
1050 | struct viewport* old_vp = current_vp; | ||
944 | 1051 | ||
945 | for ( index = 0; index < LCD_SCROLLABLE_LINES; index++ ) { | 1052 | for ( index = 0; index < lcd_scroll_info.lines; index++ ) { |
946 | /* really scroll? */ | ||
947 | if ((lcd_scroll_info.lines & (1 << index)) == 0) | ||
948 | continue; | ||
949 | |||
950 | s = &lcd_scroll_info.scroll[index]; | 1053 | s = &lcd_scroll_info.scroll[index]; |
951 | 1054 | ||
952 | /* check pause */ | 1055 | /* check pause */ |
953 | if (TIME_BEFORE(current_tick, s->start_tick)) | 1056 | if (TIME_BEFORE(current_tick, s->start_tick)) |
954 | continue; | 1057 | continue; |
955 | 1058 | ||
1059 | lcd_set_viewport(s->vp); | ||
1060 | |||
956 | if (s->backward) | 1061 | if (s->backward) |
957 | s->offset -= lcd_scroll_info.step; | 1062 | s->offset -= lcd_scroll_info.step; |
958 | else | 1063 | else |
959 | s->offset += lcd_scroll_info.step; | 1064 | s->offset += lcd_scroll_info.step; |
960 | 1065 | ||
961 | pf = font_get(curfont); | 1066 | pf = font_get(current_vp->font); |
962 | xpos = s->startx; | 1067 | xpos = s->startx; |
963 | ypos = ymargin + index * pf->height; | 1068 | ypos = current_vp->ymargin + s->y * pf->height; |
964 | 1069 | ||
965 | if (s->bidir) { /* scroll bidirectional */ | 1070 | if (s->bidir) { /* scroll bidirectional */ |
966 | if (s->offset <= 0) { | 1071 | if (s->offset <= 0) { |
@@ -969,9 +1074,9 @@ void lcd_scroll_fn(void) | |||
969 | s->backward = false; | 1074 | s->backward = false; |
970 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | 1075 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; |
971 | } | 1076 | } |
972 | if (s->offset >= s->width - (LCD_WIDTH - xpos)) { | 1077 | if (s->offset >= s->width - (current_vp->width - xpos)) { |
973 | /* at end of line */ | 1078 | /* at end of line */ |
974 | s->offset = s->width - (LCD_WIDTH - xpos); | 1079 | s->offset = s->width - (current_vp->width - xpos); |
975 | s->backward = true; | 1080 | s->backward = true; |
976 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | 1081 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; |
977 | } | 1082 | } |
@@ -982,11 +1087,13 @@ void lcd_scroll_fn(void) | |||
982 | s->offset %= s->width; | 1087 | s->offset %= s->width; |
983 | } | 1088 | } |
984 | 1089 | ||
985 | lastmode = drawmode; | 1090 | lastmode = current_vp->drawmode; |
986 | drawmode = (s->style&STYLE_INVERT) ? | 1091 | current_vp->drawmode = (s->style&STYLE_INVERT) ? |
987 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | 1092 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; |
988 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); | 1093 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); |
989 | drawmode = lastmode; | 1094 | current_vp->drawmode = lastmode; |
990 | lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | 1095 | lcd_update_viewport_rect(xpos, ypos, current_vp->width - xpos, pf->height); |
991 | } | 1096 | } |
1097 | |||
1098 | lcd_set_viewport(old_vp); | ||
992 | } | 1099 | } |
diff --git a/firmware/drivers/lcd-2bit-vert.c b/firmware/drivers/lcd-2bit-vert.c index aa3cd2cc3b..2341ddb3df 100644 --- a/firmware/drivers/lcd-2bit-vert.c +++ b/firmware/drivers/lcd-2bit-vert.c | |||
@@ -48,52 +48,93 @@ static const unsigned char pixmask[4] ICONST_ATTR = { | |||
48 | static fb_data* lcd_backdrop = NULL; | 48 | static fb_data* lcd_backdrop = NULL; |
49 | static long lcd_backdrop_offset IDATA_ATTR = 0; | 49 | static long lcd_backdrop_offset IDATA_ATTR = 0; |
50 | 50 | ||
51 | static unsigned fg_pattern IDATA_ATTR = 0xFF; /* initially black */ | 51 | static struct viewport default_vp = |
52 | static unsigned bg_pattern IDATA_ATTR = 0x00; /* initially white */ | 52 | { |
53 | static int drawmode = DRMODE_SOLID; | 53 | .x = 0, |
54 | static int xmargin = 0; | 54 | .y = 0, |
55 | static int ymargin = 0; | 55 | .width = LCD_WIDTH, |
56 | static int curfont = FONT_SYSFIXED; | 56 | .height = LCD_HEIGHT, |
57 | .font = FONT_SYSFIXED, | ||
58 | .drawmode = DRMODE_SOLID, | ||
59 | .xmargin = 0, | ||
60 | .ymargin = 0, | ||
61 | .fg_pattern = LCD_DEFAULT_FG, | ||
62 | .bg_pattern = LCD_DEFAULT_BG | ||
63 | }; | ||
64 | |||
65 | static struct viewport* current_vp IBSS_ATTR; | ||
66 | static unsigned fg_pattern IBSS_ATTR; | ||
67 | static unsigned bg_pattern IBSS_ATTR; | ||
57 | 68 | ||
58 | /* LCD init */ | 69 | /* LCD init */ |
59 | void lcd_init(void) | 70 | void lcd_init(void) |
60 | { | 71 | { |
72 | /* Initialise the viewport */ | ||
73 | lcd_set_viewport(NULL); | ||
74 | |||
61 | lcd_clear_display(); | 75 | lcd_clear_display(); |
62 | /* Call device specific init */ | 76 | /* Call device specific init */ |
63 | lcd_init_device(); | 77 | lcd_init_device(); |
64 | scroll_init(); | 78 | scroll_init(); |
65 | } | 79 | } |
66 | 80 | ||
81 | /*** Viewports ***/ | ||
82 | |||
83 | void lcd_set_viewport(struct viewport* vp) | ||
84 | { | ||
85 | if (vp == NULL) | ||
86 | current_vp = &default_vp; | ||
87 | else | ||
88 | current_vp = vp; | ||
89 | |||
90 | fg_pattern = 0x55 * (~current_vp->fg_pattern & 3); | ||
91 | bg_pattern = 0x55 * (~current_vp->bg_pattern & 3); | ||
92 | } | ||
93 | |||
94 | void lcd_update_viewport(void) | ||
95 | { | ||
96 | lcd_update_rect(current_vp->x, current_vp->y, | ||
97 | current_vp->width, current_vp->height); | ||
98 | } | ||
99 | |||
100 | void lcd_update_viewport_rect(int x, int y, int width, int height) | ||
101 | { | ||
102 | lcd_update_rect(current_vp->x + x, current_vp->y + y, width, height); | ||
103 | } | ||
104 | |||
105 | |||
67 | /*** parameter handling ***/ | 106 | /*** parameter handling ***/ |
68 | 107 | ||
69 | void lcd_set_drawmode(int mode) | 108 | void lcd_set_drawmode(int mode) |
70 | { | 109 | { |
71 | drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); | 110 | current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); |
72 | } | 111 | } |
73 | 112 | ||
74 | int lcd_get_drawmode(void) | 113 | int lcd_get_drawmode(void) |
75 | { | 114 | { |
76 | return drawmode; | 115 | return current_vp->drawmode; |
77 | } | 116 | } |
78 | 117 | ||
79 | void lcd_set_foreground(unsigned brightness) | 118 | void lcd_set_foreground(unsigned brightness) |
80 | { | 119 | { |
120 | current_vp->fg_pattern = brightness; | ||
81 | fg_pattern = 0x55 * (~brightness & 3); | 121 | fg_pattern = 0x55 * (~brightness & 3); |
82 | } | 122 | } |
83 | 123 | ||
84 | unsigned lcd_get_foreground(void) | 124 | unsigned lcd_get_foreground(void) |
85 | { | 125 | { |
86 | return ~fg_pattern & 3; | 126 | return current_vp->fg_pattern; |
87 | } | 127 | } |
88 | 128 | ||
89 | void lcd_set_background(unsigned brightness) | 129 | void lcd_set_background(unsigned brightness) |
90 | { | 130 | { |
131 | current_vp->fg_pattern = brightness; | ||
91 | bg_pattern = 0x55 * (~brightness & 3); | 132 | bg_pattern = 0x55 * (~brightness & 3); |
92 | } | 133 | } |
93 | 134 | ||
94 | unsigned lcd_get_background(void) | 135 | unsigned lcd_get_background(void) |
95 | { | 136 | { |
96 | return ~bg_pattern & 3; | 137 | return current_vp->bg_pattern; |
97 | } | 138 | } |
98 | 139 | ||
99 | void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) | 140 | void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) |
@@ -105,28 +146,38 @@ void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) | |||
105 | 146 | ||
106 | void lcd_setmargins(int x, int y) | 147 | void lcd_setmargins(int x, int y) |
107 | { | 148 | { |
108 | xmargin = x; | 149 | current_vp->xmargin = x; |
109 | ymargin = y; | 150 | current_vp->ymargin = y; |
110 | } | 151 | } |
111 | 152 | ||
112 | int lcd_getxmargin(void) | 153 | int lcd_getxmargin(void) |
113 | { | 154 | { |
114 | return xmargin; | 155 | return current_vp->xmargin; |
115 | } | 156 | } |
116 | 157 | ||
117 | int lcd_getymargin(void) | 158 | int lcd_getymargin(void) |
118 | { | 159 | { |
119 | return ymargin; | 160 | return current_vp->ymargin; |
161 | } | ||
162 | |||
163 | int lcd_getwidth(void) | ||
164 | { | ||
165 | return current_vp->width; | ||
166 | } | ||
167 | |||
168 | int lcd_getheight(void) | ||
169 | { | ||
170 | return current_vp->height; | ||
120 | } | 171 | } |
121 | 172 | ||
122 | void lcd_setfont(int newfont) | 173 | void lcd_setfont(int newfont) |
123 | { | 174 | { |
124 | curfont = newfont; | 175 | current_vp->font = newfont; |
125 | } | 176 | } |
126 | 177 | ||
127 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) | 178 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) |
128 | { | 179 | { |
129 | return font_getstringsize(str, w, h, curfont); | 180 | return font_getstringsize(str, w, h, current_vp->font); |
130 | } | 181 | } |
131 | 182 | ||
132 | /*** low-level drawing functions ***/ | 183 | /*** low-level drawing functions ***/ |
@@ -347,7 +398,7 @@ static inline void setblock(fb_data *address, unsigned mask, unsigned bits) | |||
347 | /* Clear the whole display */ | 398 | /* Clear the whole display */ |
348 | void lcd_clear_display(void) | 399 | void lcd_clear_display(void) |
349 | { | 400 | { |
350 | if (drawmode & DRMODE_INVERSEVID) | 401 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
351 | { | 402 | { |
352 | memset(lcd_framebuffer, fg_pattern, sizeof lcd_framebuffer); | 403 | memset(lcd_framebuffer, fg_pattern, sizeof lcd_framebuffer); |
353 | } | 404 | } |
@@ -362,11 +413,37 @@ void lcd_clear_display(void) | |||
362 | lcd_scroll_info.lines = 0; | 413 | lcd_scroll_info.lines = 0; |
363 | } | 414 | } |
364 | 415 | ||
416 | /* Clear the current viewport */ | ||
417 | void lcd_clear_viewport(void) | ||
418 | { | ||
419 | int lastmode; | ||
420 | |||
421 | if (current_vp == &default_vp) | ||
422 | { | ||
423 | lcd_clear_display(); | ||
424 | } | ||
425 | else | ||
426 | { | ||
427 | lastmode = current_vp->drawmode; | ||
428 | |||
429 | /* Invert the INVERSEVID bit and set basic mode to SOLID */ | ||
430 | current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | | ||
431 | DRMODE_SOLID; | ||
432 | |||
433 | lcd_fillrect(0, 0, current_vp->width, current_vp->height); | ||
434 | |||
435 | current_vp->drawmode = lastmode; | ||
436 | |||
437 | lcd_scroll_stop(current_vp); | ||
438 | } | ||
439 | } | ||
440 | |||
365 | /* Set a single pixel */ | 441 | /* Set a single pixel */ |
366 | void lcd_drawpixel(int x, int y) | 442 | void lcd_drawpixel(int x, int y) |
367 | { | 443 | { |
368 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) | 444 | if (((unsigned)x < (unsigned)current_vp->width) && |
369 | lcd_pixelfuncs[drawmode](x, y); | 445 | ((unsigned)y < (unsigned)current_vp->height)) |
446 | lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); | ||
370 | } | 447 | } |
371 | 448 | ||
372 | /* Draw a line */ | 449 | /* Draw a line */ |
@@ -378,7 +455,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
378 | int d, dinc1, dinc2; | 455 | int d, dinc1, dinc2; |
379 | int x, xinc1, xinc2; | 456 | int x, xinc1, xinc2; |
380 | int y, yinc1, yinc2; | 457 | int y, yinc1, yinc2; |
381 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; | 458 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[current_vp->drawmode]; |
382 | 459 | ||
383 | deltax = abs(x2 - x1); | 460 | deltax = abs(x2 - x1); |
384 | deltay = abs(y2 - y1); | 461 | deltay = abs(y2 - y1); |
@@ -422,8 +499,9 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
422 | 499 | ||
423 | for (i = 0; i < numpixels; i++) | 500 | for (i = 0; i < numpixels; i++) |
424 | { | 501 | { |
425 | if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) | 502 | if (((unsigned)x < (unsigned)current_vp->width) && |
426 | pfunc(x, y); | 503 | ((unsigned)y < (unsigned)current_vp->height)) |
504 | pfunc(current_vp->x + x, current_vp->y + y); | ||
427 | 505 | ||
428 | if (d < 0) | 506 | if (d < 0) |
429 | { | 507 | { |
@@ -444,6 +522,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
444 | void lcd_hline(int x1, int x2, int y) | 522 | void lcd_hline(int x1, int x2, int y) |
445 | { | 523 | { |
446 | int x; | 524 | int x; |
525 | int width; | ||
447 | fb_data *dst, *dst_end; | 526 | fb_data *dst, *dst_end; |
448 | unsigned mask; | 527 | unsigned mask; |
449 | lcd_blockfunc_type *bfunc; | 528 | lcd_blockfunc_type *bfunc; |
@@ -457,23 +536,30 @@ void lcd_hline(int x1, int x2, int y) | |||
457 | } | 536 | } |
458 | 537 | ||
459 | /* nothing to draw? */ | 538 | /* nothing to draw? */ |
460 | if (((unsigned)y >= LCD_HEIGHT) || (x1 >= LCD_WIDTH) || (x2 < 0)) | 539 | if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) |
540 | || (x2 < 0)) | ||
461 | return; | 541 | return; |
462 | 542 | ||
463 | /* clipping */ | 543 | /* clipping */ |
464 | if (x1 < 0) | 544 | if (x1 < 0) |
465 | x1 = 0; | 545 | x1 = 0; |
466 | if (x2 >= LCD_WIDTH) | 546 | if (x2 >= current_vp->width) |
467 | x2 = LCD_WIDTH-1; | 547 | x2 = current_vp->width-1; |
468 | 548 | ||
469 | bfunc = lcd_blockfuncs[drawmode]; | 549 | width = x2 - x1 + 1; |
550 | |||
551 | /* adjust x1 and y to viewport */ | ||
552 | x1 += current_vp->x; | ||
553 | y += current_vp->y; | ||
554 | |||
555 | bfunc = lcd_blockfuncs[current_vp->drawmode]; | ||
470 | dst = &lcd_framebuffer[y>>2][x1]; | 556 | dst = &lcd_framebuffer[y>>2][x1]; |
471 | mask = pixmask[y & 3]; | 557 | mask = pixmask[y & 3]; |
472 | 558 | ||
473 | dst_end = dst + x2 - x1; | 559 | dst_end = dst + width; |
474 | do | 560 | do |
475 | bfunc(dst++, mask, 0xFFu); | 561 | bfunc(dst++, mask, 0xFFu); |
476 | while (dst <= dst_end); | 562 | while (dst < dst_end); |
477 | } | 563 | } |
478 | 564 | ||
479 | /* Draw a vertical line (optimised) */ | 565 | /* Draw a vertical line (optimised) */ |
@@ -493,16 +579,22 @@ void lcd_vline(int x, int y1, int y2) | |||
493 | } | 579 | } |
494 | 580 | ||
495 | /* nothing to draw? */ | 581 | /* nothing to draw? */ |
496 | if (((unsigned)x >= LCD_WIDTH) || (y1 >= LCD_HEIGHT) || (y2 < 0)) | 582 | if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) |
583 | || (y2 < 0)) | ||
497 | return; | 584 | return; |
498 | 585 | ||
499 | /* clipping */ | 586 | /* clipping */ |
500 | if (y1 < 0) | 587 | if (y1 < 0) |
501 | y1 = 0; | 588 | y1 = 0; |
502 | if (y2 >= LCD_HEIGHT) | 589 | if (y2 >= current_vp->height) |
503 | y2 = LCD_HEIGHT-1; | 590 | y2 = current_vp->height-1; |
504 | 591 | ||
505 | bfunc = lcd_blockfuncs[drawmode]; | 592 | /* adjust for viewport */ |
593 | y1 += current_vp->y; | ||
594 | y2 += current_vp->y; | ||
595 | x += current_vp->x; | ||
596 | |||
597 | bfunc = lcd_blockfuncs[current_vp->drawmode]; | ||
506 | dst = &lcd_framebuffer[y1>>2][x]; | 598 | dst = &lcd_framebuffer[y1>>2][x]; |
507 | ny = y2 - (y1 & ~3); | 599 | ny = y2 - (y1 & ~3); |
508 | mask = 0xFFu << (2 * (y1 & 3)); | 600 | mask = 0xFFu << (2 * (y1 & 3)); |
@@ -544,8 +636,8 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
544 | bool fillopt = false; | 636 | bool fillopt = false; |
545 | 637 | ||
546 | /* nothing to draw? */ | 638 | /* nothing to draw? */ |
547 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 639 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
548 | || (x + width <= 0) || (y + height <= 0)) | 640 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
549 | return; | 641 | return; |
550 | 642 | ||
551 | /* clipping */ | 643 | /* clipping */ |
@@ -559,14 +651,18 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
559 | height += y; | 651 | height += y; |
560 | y = 0; | 652 | y = 0; |
561 | } | 653 | } |
562 | if (x + width > LCD_WIDTH) | 654 | if (x + width > current_vp->width) |
563 | width = LCD_WIDTH - x; | 655 | width = current_vp->width - x; |
564 | if (y + height > LCD_HEIGHT) | 656 | if (y + height > current_vp->height) |
565 | height = LCD_HEIGHT - y; | 657 | height = current_vp->height - y; |
566 | 658 | ||
567 | if (drawmode & DRMODE_INVERSEVID) | 659 | /* adjust for viewport */ |
660 | x += current_vp->x; | ||
661 | y += current_vp->y; | ||
662 | |||
663 | if (current_vp->drawmode & DRMODE_INVERSEVID) | ||
568 | { | 664 | { |
569 | if ((drawmode & DRMODE_BG) && !lcd_backdrop) | 665 | if ((current_vp->drawmode & DRMODE_BG) && !lcd_backdrop) |
570 | { | 666 | { |
571 | fillopt = true; | 667 | fillopt = true; |
572 | bits = bg_pattern; | 668 | bits = bg_pattern; |
@@ -574,13 +670,13 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
574 | } | 670 | } |
575 | else | 671 | else |
576 | { | 672 | { |
577 | if (drawmode & DRMODE_FG) | 673 | if (current_vp->drawmode & DRMODE_FG) |
578 | { | 674 | { |
579 | fillopt = true; | 675 | fillopt = true; |
580 | bits = fg_pattern; | 676 | bits = fg_pattern; |
581 | } | 677 | } |
582 | } | 678 | } |
583 | bfunc = lcd_blockfuncs[drawmode]; | 679 | bfunc = lcd_blockfuncs[current_vp->drawmode]; |
584 | dst = &lcd_framebuffer[y>>2][x]; | 680 | dst = &lcd_framebuffer[y>>2][x]; |
585 | ny = height - 1 + (y & 3); | 681 | ny = height - 1 + (y & 3); |
586 | mask = 0xFFu << (2 * (y & 3)); | 682 | mask = 0xFFu << (2 * (y & 3)); |
@@ -640,8 +736,8 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
640 | lcd_blockfunc_type *bfunc; | 736 | lcd_blockfunc_type *bfunc; |
641 | 737 | ||
642 | /* nothing to draw? */ | 738 | /* nothing to draw? */ |
643 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 739 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
644 | || (x + width <= 0) || (y + height <= 0)) | 740 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
645 | return; | 741 | return; |
646 | 742 | ||
647 | /* clipping */ | 743 | /* clipping */ |
@@ -657,10 +753,14 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
657 | src_y -= y; | 753 | src_y -= y; |
658 | y = 0; | 754 | y = 0; |
659 | } | 755 | } |
660 | if (x + width > LCD_WIDTH) | 756 | if (x + width > current_vp->width) |
661 | width = LCD_WIDTH - x; | 757 | width = current_vp->width - x; |
662 | if (y + height > LCD_HEIGHT) | 758 | if (y + height > current_vp->height) |
663 | height = LCD_HEIGHT - y; | 759 | height = current_vp->height - y; |
760 | |||
761 | /* adjust for viewport */ | ||
762 | x += current_vp->x; | ||
763 | y += current_vp->y; | ||
664 | 764 | ||
665 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 765 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
666 | src_y &= 7; | 766 | src_y &= 7; |
@@ -669,7 +769,7 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
669 | shift = y & 3; | 769 | shift = y & 3; |
670 | ny = height - 1 + shift + src_y; | 770 | ny = height - 1 + shift + src_y; |
671 | 771 | ||
672 | bfunc = lcd_blockfuncs[drawmode]; | 772 | bfunc = lcd_blockfuncs[current_vp->drawmode]; |
673 | mask = 0xFFu << (shift + src_y); | 773 | mask = 0xFFu << (shift + src_y); |
674 | mask_bottom = 0xFFu >> (~ny & 7); | 774 | mask_bottom = 0xFFu >> (~ny & 7); |
675 | 775 | ||
@@ -807,8 +907,8 @@ void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
807 | unsigned mask, mask_bottom; | 907 | unsigned mask, mask_bottom; |
808 | 908 | ||
809 | /* nothing to draw? */ | 909 | /* nothing to draw? */ |
810 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 910 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
811 | || (x + width <= 0) || (y + height <= 0)) | 911 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
812 | return; | 912 | return; |
813 | 913 | ||
814 | /* clipping */ | 914 | /* clipping */ |
@@ -824,10 +924,14 @@ void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
824 | src_y -= y; | 924 | src_y -= y; |
825 | y = 0; | 925 | y = 0; |
826 | } | 926 | } |
827 | if (x + width > LCD_WIDTH) | 927 | if (x + width > current_vp->width) |
828 | width = LCD_WIDTH - x; | 928 | width = current_vp->width - x; |
829 | if (y + height > LCD_HEIGHT) | 929 | if (y + height > current_vp->height) |
830 | height = LCD_HEIGHT - y; | 930 | height = current_vp->height - y; |
931 | |||
932 | /* adjust for viewport */ | ||
933 | x += current_vp->x; | ||
934 | y += current_vp->y; | ||
831 | 935 | ||
832 | src += stride * (src_y >> 2) + src_x; /* move starting point */ | 936 | src += stride * (src_y >> 2) + src_x; /* move starting point */ |
833 | src_y &= 3; | 937 | src_y &= 3; |
@@ -916,11 +1020,11 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
916 | { | 1020 | { |
917 | unsigned short ch; | 1021 | unsigned short ch; |
918 | unsigned short *ucs; | 1022 | unsigned short *ucs; |
919 | struct font* pf = font_get(curfont); | 1023 | struct font* pf = font_get(current_vp->font); |
920 | 1024 | ||
921 | ucs = bidi_l2v(str, 1); | 1025 | ucs = bidi_l2v(str, 1); |
922 | 1026 | ||
923 | while ((ch = *ucs++) != 0 && x < LCD_WIDTH) | 1027 | while ((ch = *ucs++) != 0 && x < current_vp->width) |
924 | { | 1028 | { |
925 | int width; | 1029 | int width; |
926 | const unsigned char *bits; | 1030 | const unsigned char *bits; |
@@ -974,24 +1078,24 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str, | |||
974 | int style, int offset) | 1078 | int style, int offset) |
975 | { | 1079 | { |
976 | int xpos,ypos,w,h,xrect; | 1080 | int xpos,ypos,w,h,xrect; |
977 | int lastmode = drawmode; | 1081 | int lastmode = current_vp->drawmode; |
978 | 1082 | ||
979 | /* make sure scrolling is turned off on the line we are updating */ | 1083 | /* make sure scrolling is turned off on the line we are updating */ |
980 | lcd_scroll_info.lines &= ~(1 << y); | 1084 | lcd_scroll_stop_line(current_vp, y); |
981 | 1085 | ||
982 | if(!str || !str[0]) | 1086 | if(!str || !str[0]) |
983 | return; | 1087 | return; |
984 | 1088 | ||
985 | lcd_getstringsize(str, &w, &h); | 1089 | lcd_getstringsize(str, &w, &h); |
986 | xpos = xmargin + x*w / utf8length((char *)str); | 1090 | xpos = current_vp->xmargin + x*w / utf8length((char *)str); |
987 | ypos = ymargin + y*h; | 1091 | ypos = current_vp->ymargin + y*h; |
988 | drawmode = (style & STYLE_INVERT) ? | 1092 | current_vp->drawmode = (style & STYLE_INVERT) ? |
989 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | 1093 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; |
990 | lcd_putsxyofs(xpos, ypos, offset, str); | 1094 | lcd_putsxyofs(xpos, ypos, offset, str); |
991 | drawmode ^= DRMODE_INVERSEVID; | 1095 | current_vp->drawmode ^= DRMODE_INVERSEVID; |
992 | xrect = xpos + MAX(w - offset, 0); | 1096 | xrect = xpos + MAX(w - offset, 0); |
993 | lcd_fillrect(xrect, ypos, LCD_WIDTH - xrect, h); | 1097 | lcd_fillrect(xrect, ypos, current_vp->width - xrect, h); |
994 | drawmode = lastmode; | 1098 | current_vp->drawmode = lastmode; |
995 | } | 1099 | } |
996 | 1100 | ||
997 | /*** scrolling ***/ | 1101 | /*** scrolling ***/ |
@@ -1017,9 +1121,15 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
1017 | struct scrollinfo* s; | 1121 | struct scrollinfo* s; |
1018 | int w, h; | 1122 | int w, h; |
1019 | 1123 | ||
1020 | if(y>=LCD_SCROLLABLE_LINES) return; | 1124 | if ((unsigned)y >= (unsigned)current_vp->height) |
1125 | return; | ||
1126 | |||
1127 | /* remove any previously scrolling line at the same location */ | ||
1128 | lcd_scroll_stop_line(current_vp, y); | ||
1129 | |||
1130 | if (lcd_scroll_info.lines >= LCD_SCROLLABLE_LINES) return; | ||
1021 | 1131 | ||
1022 | s = &lcd_scroll_info.scroll[y]; | 1132 | s = &lcd_scroll_info.scroll[lcd_scroll_info.lines]; |
1023 | 1133 | ||
1024 | s->start_tick = current_tick + lcd_scroll_info.delay; | 1134 | s->start_tick = current_tick + lcd_scroll_info.delay; |
1025 | s->style = style; | 1135 | s->style = style; |
@@ -1031,7 +1141,7 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
1031 | 1141 | ||
1032 | lcd_getstringsize(string, &w, &h); | 1142 | lcd_getstringsize(string, &w, &h); |
1033 | 1143 | ||
1034 | if (LCD_WIDTH - x * 8 - xmargin < w) { | 1144 | if (current_vp->width - x * 8 - current_vp->xmargin < w) { |
1035 | /* prepare scroll line */ | 1145 | /* prepare scroll line */ |
1036 | char *end; | 1146 | char *end; |
1037 | 1147 | ||
@@ -1044,7 +1154,7 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
1044 | /* scroll bidirectional or forward only depending on the string | 1154 | /* scroll bidirectional or forward only depending on the string |
1045 | width */ | 1155 | width */ |
1046 | if ( lcd_scroll_info.bidir_limit ) { | 1156 | if ( lcd_scroll_info.bidir_limit ) { |
1047 | s->bidir = s->width < (LCD_WIDTH - xmargin) * | 1157 | s->bidir = s->width < (current_vp->width - current_vp->xmargin) * |
1048 | (100 + lcd_scroll_info.bidir_limit) / 100; | 1158 | (100 + lcd_scroll_info.bidir_limit) / 100; |
1049 | } | 1159 | } |
1050 | else | 1160 | else |
@@ -1057,17 +1167,17 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | |||
1057 | } | 1167 | } |
1058 | 1168 | ||
1059 | end = strchr(s->line, '\0'); | 1169 | end = strchr(s->line, '\0'); |
1060 | strncpy(end, (char *)string, LCD_WIDTH/2); | 1170 | strncpy(end, (char *)string, current_vp->width/2); |
1061 | 1171 | ||
1172 | s->vp = current_vp; | ||
1173 | s->y = y; | ||
1062 | s->len = utf8length((char *)string); | 1174 | s->len = utf8length((char *)string); |
1063 | s->offset = offset; | 1175 | s->offset = offset; |
1064 | s->startx = xmargin + x * s->width / s->len; | 1176 | s->startx = current_vp->xmargin + x * s->width / s->len; |
1065 | s->backward = false; | 1177 | s->backward = false; |
1066 | lcd_scroll_info.lines |= (1<<y); | 1178 | |
1179 | lcd_scroll_info.lines++; | ||
1067 | } | 1180 | } |
1068 | else | ||
1069 | /* force a bit switch-off since it doesn't scroll */ | ||
1070 | lcd_scroll_info.lines &= ~(1<<y); | ||
1071 | } | 1181 | } |
1072 | 1182 | ||
1073 | void lcd_scroll_fn(void) | 1183 | void lcd_scroll_fn(void) |
@@ -1077,26 +1187,25 @@ void lcd_scroll_fn(void) | |||
1077 | int index; | 1187 | int index; |
1078 | int xpos, ypos; | 1188 | int xpos, ypos; |
1079 | int lastmode; | 1189 | int lastmode; |
1190 | struct viewport* old_vp = current_vp; | ||
1080 | 1191 | ||
1081 | for ( index = 0; index < LCD_SCROLLABLE_LINES; index++ ) { | 1192 | for ( index = 0; index < lcd_scroll_info.lines; index++ ) { |
1082 | /* really scroll? */ | ||
1083 | if ((lcd_scroll_info.lines & (1 << index)) == 0) | ||
1084 | continue; | ||
1085 | |||
1086 | s = &lcd_scroll_info.scroll[index]; | 1193 | s = &lcd_scroll_info.scroll[index]; |
1087 | 1194 | ||
1088 | /* check pause */ | 1195 | /* check pause */ |
1089 | if (TIME_BEFORE(current_tick, s->start_tick)) | 1196 | if (TIME_BEFORE(current_tick, s->start_tick)) |
1090 | continue; | 1197 | continue; |
1091 | 1198 | ||
1199 | lcd_set_viewport(s->vp); | ||
1200 | |||
1092 | if (s->backward) | 1201 | if (s->backward) |
1093 | s->offset -= lcd_scroll_info.step; | 1202 | s->offset -= lcd_scroll_info.step; |
1094 | else | 1203 | else |
1095 | s->offset += lcd_scroll_info.step; | 1204 | s->offset += lcd_scroll_info.step; |
1096 | 1205 | ||
1097 | pf = font_get(curfont); | 1206 | pf = font_get(current_vp->font); |
1098 | xpos = s->startx; | 1207 | xpos = s->startx; |
1099 | ypos = ymargin + index * pf->height; | 1208 | ypos = current_vp->ymargin + s->y * pf->height; |
1100 | 1209 | ||
1101 | if (s->bidir) { /* scroll bidirectional */ | 1210 | if (s->bidir) { /* scroll bidirectional */ |
1102 | if (s->offset <= 0) { | 1211 | if (s->offset <= 0) { |
@@ -1105,9 +1214,9 @@ void lcd_scroll_fn(void) | |||
1105 | s->backward = false; | 1214 | s->backward = false; |
1106 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | 1215 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; |
1107 | } | 1216 | } |
1108 | if (s->offset >= s->width - (LCD_WIDTH - xpos)) { | 1217 | if (s->offset >= s->width - (current_vp->width - xpos)) { |
1109 | /* at end of line */ | 1218 | /* at end of line */ |
1110 | s->offset = s->width - (LCD_WIDTH - xpos); | 1219 | s->offset = s->width - (current_vp->width - xpos); |
1111 | s->backward = true; | 1220 | s->backward = true; |
1112 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | 1221 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; |
1113 | } | 1222 | } |
@@ -1118,11 +1227,14 @@ void lcd_scroll_fn(void) | |||
1118 | s->offset %= s->width; | 1227 | s->offset %= s->width; |
1119 | } | 1228 | } |
1120 | 1229 | ||
1121 | lastmode = drawmode; | 1230 | lastmode = current_vp->drawmode; |
1122 | drawmode = (s->style&STYLE_INVERT) ? | 1231 | current_vp->drawmode = (s->style&STYLE_INVERT) ? |
1123 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | 1232 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; |
1124 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); | 1233 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); |
1125 | drawmode = lastmode; | 1234 | current_vp->drawmode = lastmode; |
1126 | lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height); | 1235 | lcd_update_viewport_rect(xpos, ypos, |
1236 | current_vp->width - xpos, pf->height); | ||
1127 | } | 1237 | } |
1238 | |||
1239 | lcd_set_viewport(old_vp); | ||
1128 | } | 1240 | } |
diff --git a/firmware/drivers/lcd-charcell.c b/firmware/drivers/lcd-charcell.c index 0fd41481c5..1bc634cd2f 100644 --- a/firmware/drivers/lcd-charcell.c +++ b/firmware/drivers/lcd-charcell.c | |||
@@ -52,8 +52,17 @@ static unsigned char xfont_variable[VARIABLE_XCHARS][HW_PATTERN_SIZE]; | |||
52 | static bool xfont_variable_locked[VARIABLE_XCHARS]; | 52 | static bool xfont_variable_locked[VARIABLE_XCHARS]; |
53 | static int xspace; /* stores xhcar id of ' ' - often needed */ | 53 | static int xspace; /* stores xhcar id of ' ' - often needed */ |
54 | 54 | ||
55 | static int xmargin = 0; | 55 | static struct viewport default_vp = |
56 | static int ymargin = 0; | 56 | { |
57 | .x = 0, | ||
58 | .y = 0, | ||
59 | .width = LCD_WIDTH, | ||
60 | .height = LCD_HEIGHT, | ||
61 | .xmargin = 0, | ||
62 | .ymargin = 0, | ||
63 | }; | ||
64 | |||
65 | static struct viewport* current_vp = &default_vp; | ||
57 | 66 | ||
58 | /* LCD init */ | 67 | /* LCD init */ |
59 | void lcd_init (void) | 68 | void lcd_init (void) |
@@ -66,22 +75,47 @@ void lcd_init (void) | |||
66 | scroll_init(); | 75 | scroll_init(); |
67 | } | 76 | } |
68 | 77 | ||
78 | /* Viewports */ | ||
79 | |||
80 | void lcd_set_viewport(struct viewport* vp) | ||
81 | { | ||
82 | if (vp == NULL) | ||
83 | current_vp = &default_vp; | ||
84 | else | ||
85 | current_vp = vp; | ||
86 | } | ||
87 | |||
88 | void lcd_update_viewport(void) | ||
89 | { | ||
90 | lcd_update(); | ||
91 | } | ||
92 | |||
69 | /** parameter handling **/ | 93 | /** parameter handling **/ |
70 | 94 | ||
71 | void lcd_setmargins(int x, int y) | 95 | void lcd_setmargins(int x, int y) |
72 | { | 96 | { |
73 | xmargin = x; | 97 | current_vp->xmargin = x; |
74 | ymargin = y; | 98 | current_vp->ymargin = y; |
75 | } | 99 | } |
76 | 100 | ||
77 | int lcd_getxmargin(void) | 101 | int lcd_getxmargin(void) |
78 | { | 102 | { |
79 | return xmargin; | 103 | return current_vp->xmargin; |
80 | } | 104 | } |
81 | 105 | ||
82 | int lcd_getymargin(void) | 106 | int lcd_getymargin(void) |
83 | { | 107 | { |
84 | return ymargin; | 108 | return current_vp->ymargin; |
109 | } | ||
110 | |||
111 | int lcd_getwidth(void) | ||
112 | { | ||
113 | return current_vp->width; | ||
114 | } | ||
115 | |||
116 | int lcd_getheight(void) | ||
117 | { | ||
118 | return current_vp->height; | ||
85 | } | 119 | } |
86 | 120 | ||
87 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) | 121 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) |
@@ -225,7 +259,13 @@ static int map_xchar(int xchar, unsigned char *substitute) | |||
225 | 259 | ||
226 | static void lcd_putxchar(int x, int y, int xchar) | 260 | static void lcd_putxchar(int x, int y, int xchar) |
227 | { | 261 | { |
228 | int lcd_char = lcd_charbuffer[y][x]; | 262 | int lcd_char; |
263 | |||
264 | /* Adjust for viewport */ | ||
265 | x += current_vp->x; | ||
266 | y += current_vp->y; | ||
267 | |||
268 | lcd_char = lcd_charbuffer[y][x]; | ||
229 | 269 | ||
230 | if (lcd_char < lcd_pattern_count) /* old char was soft */ | 270 | if (lcd_char < lcd_pattern_count) /* old char was soft */ |
231 | lcd_patterns[lcd_char].count--; /* decrease old reference count */ | 271 | lcd_patterns[lcd_char].count--; /* decrease old reference count */ |
@@ -283,19 +323,55 @@ void lcd_define_pattern(unsigned long ucs, const char *pattern) | |||
283 | void lcd_clear_display(void) | 323 | void lcd_clear_display(void) |
284 | { | 324 | { |
285 | int x, y; | 325 | int x, y; |
326 | struct viewport* old_vp = current_vp; | ||
286 | 327 | ||
287 | lcd_stop_scroll(); | 328 | lcd_scroll_info.lines = 0; |
288 | lcd_remove_cursor(); | 329 | lcd_remove_cursor(); |
289 | 330 | ||
331 | /* Set the default viewport - required for lcd_putxchar */ | ||
332 | current_vp = &default_vp; | ||
333 | |||
290 | for (x = 0; x < LCD_WIDTH; x++) | 334 | for (x = 0; x < LCD_WIDTH; x++) |
291 | for (y = 0; y < LCD_HEIGHT; y++) | 335 | for (y = 0; y < LCD_HEIGHT; y++) |
292 | lcd_putxchar(x, y, xspace); | 336 | lcd_putxchar(x, y, xspace); |
337 | |||
338 | current_vp = old_vp; | ||
339 | } | ||
340 | |||
341 | /* Clear the current viewport */ | ||
342 | void lcd_clear_viewport(void) | ||
343 | { | ||
344 | int x, y; | ||
345 | |||
346 | if (current_vp == &default_vp) | ||
347 | { | ||
348 | lcd_clear_display(); | ||
349 | } | ||
350 | else | ||
351 | { | ||
352 | /* Remove the cursor if it is within the current viewport */ | ||
353 | if (lcd_cursor.enabled && | ||
354 | (lcd_cursor.x >= current_vp->x) && | ||
355 | (lcd_cursor.x <= current_vp->x + current_vp->width) && | ||
356 | (lcd_cursor.y >= current_vp->y) && | ||
357 | (lcd_cursor.y <= current_vp->y + current_vp->height)) | ||
358 | { | ||
359 | lcd_remove_cursor(); | ||
360 | } | ||
361 | |||
362 | for (x = 0; x < current_vp->width; x++) | ||
363 | for (y = 0; y < current_vp->height; y++) | ||
364 | lcd_putxchar(x, y, xspace); | ||
365 | |||
366 | lcd_scroll_stop(current_vp); | ||
367 | } | ||
293 | } | 368 | } |
294 | 369 | ||
295 | /* Put an unicode character at the given position */ | 370 | /* Put an unicode character at the given position */ |
296 | void lcd_putc(int x, int y, unsigned long ucs) | 371 | void lcd_putc(int x, int y, unsigned long ucs) |
297 | { | 372 | { |
298 | if ((unsigned)x >= LCD_WIDTH || (unsigned)y >= LCD_HEIGHT) | 373 | if ((unsigned)x >= (unsigned)current_vp->width || |
374 | (unsigned)y >= (unsigned)current_vp->height) | ||
299 | return; | 375 | return; |
300 | 376 | ||
301 | lcd_putxchar(x, y, find_xchar(ucs)); | 377 | lcd_putxchar(x, y, find_xchar(ucs)); |
@@ -304,15 +380,16 @@ void lcd_putc(int x, int y, unsigned long ucs) | |||
304 | /* Show cursor (alternating with existing character) at the given position */ | 380 | /* Show cursor (alternating with existing character) at the given position */ |
305 | void lcd_put_cursor(int x, int y, unsigned long cursor_ucs) | 381 | void lcd_put_cursor(int x, int y, unsigned long cursor_ucs) |
306 | { | 382 | { |
307 | if ((unsigned)x >= LCD_WIDTH || (unsigned)y >= LCD_HEIGHT | 383 | if ((unsigned)x >= (unsigned)current_vp->width || |
308 | || lcd_cursor.enabled) | 384 | (unsigned)y >= (unsigned)current_vp->height || |
385 | lcd_cursor.enabled) | ||
309 | return; | 386 | return; |
310 | 387 | ||
311 | lcd_cursor.enabled = true; | 388 | lcd_cursor.enabled = true; |
312 | lcd_cursor.visible = false; | 389 | lcd_cursor.visible = false; |
313 | lcd_cursor.hw_char = map_xchar(find_xchar(cursor_ucs), &lcd_cursor.subst_char); | 390 | lcd_cursor.hw_char = map_xchar(find_xchar(cursor_ucs), &lcd_cursor.subst_char); |
314 | lcd_cursor.x = x; | 391 | lcd_cursor.x = current_vp->x + x; |
315 | lcd_cursor.y = y; | 392 | lcd_cursor.y = current_vp->y + y; |
316 | lcd_cursor.downcount = 0; | 393 | lcd_cursor.downcount = 0; |
317 | lcd_cursor.divider = MAX((HZ/2) / lcd_scroll_info.ticks, 1); | 394 | lcd_cursor.divider = MAX((HZ/2) / lcd_scroll_info.ticks, 1); |
318 | } | 395 | } |
@@ -335,7 +412,7 @@ static int lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
335 | unsigned short ucs; | 412 | unsigned short ucs; |
336 | const unsigned char *utf8 = str; | 413 | const unsigned char *utf8 = str; |
337 | 414 | ||
338 | while (*utf8 && x < LCD_WIDTH) | 415 | while (*utf8 && x < current_vp->width) |
339 | { | 416 | { |
340 | utf8 = utf8decode(utf8, &ucs); | 417 | utf8 = utf8decode(utf8, &ucs); |
341 | 418 | ||
@@ -352,7 +429,7 @@ static int lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
352 | /* Put a string at a given position */ | 429 | /* Put a string at a given position */ |
353 | void lcd_putsxy(int x, int y, const unsigned char *str) | 430 | void lcd_putsxy(int x, int y, const unsigned char *str) |
354 | { | 431 | { |
355 | if ((unsigned)y >= LCD_HEIGHT) | 432 | if ((unsigned)y >= (unsigned)current_vp->height) |
356 | return; | 433 | return; |
357 | 434 | ||
358 | lcd_putsxyofs(x, y, 0, str); | 435 | lcd_putsxyofs(x, y, 0, str); |
@@ -369,17 +446,14 @@ void lcd_puts(int x, int y, const unsigned char *str) | |||
369 | /* Put a string at a given char position, skipping first offset chars */ | 446 | /* Put a string at a given char position, skipping first offset chars */ |
370 | void lcd_puts_offset(int x, int y, const unsigned char *str, int offset) | 447 | void lcd_puts_offset(int x, int y, const unsigned char *str, int offset) |
371 | { | 448 | { |
372 | x += xmargin; | 449 | if ((unsigned)y >= (unsigned)current_vp->height) |
373 | y += ymargin; | ||
374 | |||
375 | if ((unsigned)y >= LCD_HEIGHT) | ||
376 | return; | 450 | return; |
377 | 451 | ||
378 | /* make sure scrolling is turned off on the line we are updating */ | 452 | /* make sure scrolling is turned off on the line we are updating */ |
379 | lcd_scroll_info.lines &= ~(1 << y); | 453 | lcd_scroll_stop_line(current_vp, y); |
380 | 454 | ||
381 | x = lcd_putsxyofs(x, y, offset, str); | 455 | x = lcd_putsxyofs(x, y, offset, str); |
382 | while (x < LCD_WIDTH) | 456 | while (x < current_vp->width) |
383 | lcd_putxchar(x++, y, xspace); | 457 | lcd_putxchar(x++, y, xspace); |
384 | } | 458 | } |
385 | 459 | ||
@@ -395,16 +469,22 @@ void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, | |||
395 | struct scrollinfo* s; | 469 | struct scrollinfo* s; |
396 | int len; | 470 | int len; |
397 | 471 | ||
398 | if(y>=LCD_SCROLLABLE_LINES) return; | 472 | if ((unsigned)y >= (unsigned)current_vp->height) |
473 | return; | ||
474 | |||
475 | /* remove any previously scrolling line at the same location */ | ||
476 | lcd_scroll_stop_line(current_vp, y); | ||
399 | 477 | ||
400 | s = &lcd_scroll_info.scroll[y]; | 478 | if (lcd_scroll_info.lines >= LCD_SCROLLABLE_LINES) return; |
479 | |||
480 | s = &lcd_scroll_info.scroll[lcd_scroll_info.lines]; | ||
401 | 481 | ||
402 | s->start_tick = current_tick + lcd_scroll_info.delay; | 482 | s->start_tick = current_tick + lcd_scroll_info.delay; |
403 | 483 | ||
404 | lcd_puts_offset(x, y, string, offset); | 484 | lcd_puts_offset(x, y, string, offset); |
405 | len = utf8length(string); | 485 | len = utf8length(string); |
406 | 486 | ||
407 | if (LCD_WIDTH - x - xmargin < len) | 487 | if (current_vp->width - x - current_vp->xmargin < len) |
408 | { | 488 | { |
409 | /* prepare scroll line */ | 489 | /* prepare scroll line */ |
410 | char *end; | 490 | char *end; |
@@ -418,7 +498,7 @@ void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, | |||
418 | /* scroll bidirectional or forward only depending on the string width */ | 498 | /* scroll bidirectional or forward only depending on the string width */ |
419 | if (lcd_scroll_info.bidir_limit) | 499 | if (lcd_scroll_info.bidir_limit) |
420 | { | 500 | { |
421 | s->bidir = s->len < (LCD_WIDTH - xmargin) * | 501 | s->bidir = s->len < (current_vp->width - current_vp->xmargin) * |
422 | (100 + lcd_scroll_info.bidir_limit) / 100; | 502 | (100 + lcd_scroll_info.bidir_limit) / 100; |
423 | } | 503 | } |
424 | else | 504 | else |
@@ -432,16 +512,15 @@ void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, | |||
432 | } | 512 | } |
433 | 513 | ||
434 | end = strchr(s->line, '\0'); | 514 | end = strchr(s->line, '\0'); |
435 | strncpy(end, string, utf8seek(s->line, LCD_WIDTH)); | 515 | strncpy(end, string, utf8seek(s->line, current_vp->width)); |
436 | 516 | ||
517 | s->vp = current_vp; | ||
518 | s->y = y; | ||
437 | s->offset = offset; | 519 | s->offset = offset; |
438 | s->startx = xmargin + x; | 520 | s->startx = current_vp->xmargin + x; |
439 | s->backward = false; | 521 | s->backward = false; |
440 | lcd_scroll_info.lines |= (1<<y); | 522 | lcd_scroll_info.lines++; |
441 | } | 523 | } |
442 | else | ||
443 | /* force a bit switch-off since it doesn't scroll */ | ||
444 | lcd_scroll_info.lines &= ~(1<<y); | ||
445 | } | 524 | } |
446 | 525 | ||
447 | void lcd_scroll_fn(void) | 526 | void lcd_scroll_fn(void) |
@@ -450,27 +529,25 @@ void lcd_scroll_fn(void) | |||
450 | int index; | 529 | int index; |
451 | int xpos, ypos; | 530 | int xpos, ypos; |
452 | bool update; | 531 | bool update; |
532 | struct viewport* old_vp = current_vp; | ||
453 | 533 | ||
454 | update = false; | 534 | update = false; |
455 | for (index = 0; index < LCD_SCROLLABLE_LINES; index++) | 535 | for ( index = 0; index < lcd_scroll_info.lines; index++ ) { |
456 | { | ||
457 | /* really scroll? */ | ||
458 | if ((lcd_scroll_info.lines & (1 << index)) == 0) | ||
459 | continue; | ||
460 | |||
461 | s = &lcd_scroll_info.scroll[index]; | 536 | s = &lcd_scroll_info.scroll[index]; |
462 | 537 | ||
463 | /* check pause */ | 538 | /* check pause */ |
464 | if (TIME_BEFORE(current_tick, s->start_tick)) | 539 | if (TIME_BEFORE(current_tick, s->start_tick)) |
465 | continue; | 540 | continue; |
466 | 541 | ||
542 | lcd_set_viewport(s->vp); | ||
543 | |||
467 | if (s->backward) | 544 | if (s->backward) |
468 | s->offset--; | 545 | s->offset--; |
469 | else | 546 | else |
470 | s->offset++; | 547 | s->offset++; |
471 | 548 | ||
472 | xpos = s->startx; | 549 | xpos = s->startx; |
473 | ypos = ymargin + index; | 550 | ypos = current_vp->ymargin + s->y; |
474 | 551 | ||
475 | if (s->bidir) /* scroll bidirectional */ | 552 | if (s->bidir) /* scroll bidirectional */ |
476 | { | 553 | { |
@@ -480,9 +557,9 @@ void lcd_scroll_fn(void) | |||
480 | s->backward = false; | 557 | s->backward = false; |
481 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | 558 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; |
482 | } | 559 | } |
483 | if (s->offset >= s->len - (LCD_WIDTH - xpos)) { | 560 | if (s->offset >= s->len - (current_vp->width - xpos)) { |
484 | /* at end of line */ | 561 | /* at end of line */ |
485 | s->offset = s->len - (LCD_WIDTH - xpos); | 562 | s->offset = s->len - (current_vp->width - xpos); |
486 | s->backward = true; | 563 | s->backward = true; |
487 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | 564 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; |
488 | } | 565 | } |
@@ -497,6 +574,8 @@ void lcd_scroll_fn(void) | |||
497 | update = true; | 574 | update = true; |
498 | } | 575 | } |
499 | 576 | ||
577 | lcd_set_viewport(old_vp); | ||
578 | |||
500 | if (lcd_cursor.enabled) | 579 | if (lcd_cursor.enabled) |
501 | { | 580 | { |
502 | if (--lcd_cursor.downcount <= 0) | 581 | if (--lcd_cursor.downcount <= 0) |
diff --git a/firmware/drivers/lcd-remote-1bit-v.c b/firmware/drivers/lcd-remote-1bit-v.c index 9bfbf580d9..a33648b76a 100644 --- a/firmware/drivers/lcd-remote-1bit-v.c +++ b/firmware/drivers/lcd-remote-1bit-v.c | |||
@@ -38,47 +38,88 @@ | |||
38 | fb_remote_data lcd_remote_framebuffer[LCD_REMOTE_FBHEIGHT][LCD_REMOTE_FBWIDTH] | 38 | fb_remote_data lcd_remote_framebuffer[LCD_REMOTE_FBHEIGHT][LCD_REMOTE_FBWIDTH] |
39 | IBSS_ATTR; | 39 | IBSS_ATTR; |
40 | 40 | ||
41 | static int drawmode = DRMODE_SOLID; | 41 | static struct viewport default_vp = |
42 | static int xmargin = 0; | 42 | { |
43 | static int ymargin = 0; | 43 | .x = 0, |
44 | static int curfont = FONT_SYSFIXED; | 44 | .y = 0, |
45 | .width = LCD_REMOTE_WIDTH, | ||
46 | .height = LCD_REMOTE_HEIGHT, | ||
47 | .font = FONT_SYSFIXED, | ||
48 | .drawmode = DRMODE_SOLID, | ||
49 | .xmargin = 0, | ||
50 | .ymargin = 0, | ||
51 | }; | ||
52 | |||
53 | static struct viewport* current_vp IDATA_ATTR = &default_vp; | ||
54 | |||
55 | /*** Viewports ***/ | ||
56 | |||
57 | void lcd_remote_set_viewport(struct viewport* vp) | ||
58 | { | ||
59 | if (vp == NULL) | ||
60 | current_vp = &default_vp; | ||
61 | else | ||
62 | current_vp = vp; | ||
63 | } | ||
64 | |||
65 | void lcd_remote_update_viewport(void) | ||
66 | { | ||
67 | lcd_remote_update_rect(current_vp->x, current_vp->y, | ||
68 | current_vp->width, current_vp->height); | ||
69 | } | ||
70 | |||
71 | void lcd_remote_update_viewport_rect(int x, int y, int width, int height) | ||
72 | { | ||
73 | lcd_remote_update_rect(current_vp->x + x, current_vp->y + y, width, height); | ||
74 | } | ||
75 | |||
45 | 76 | ||
46 | /*** parameter handling ***/ | 77 | /*** parameter handling ***/ |
47 | 78 | ||
48 | void lcd_remote_set_drawmode(int mode) | 79 | void lcd_remote_set_drawmode(int mode) |
49 | { | 80 | { |
50 | drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); | 81 | current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); |
51 | } | 82 | } |
52 | 83 | ||
53 | int lcd_remote_get_drawmode(void) | 84 | int lcd_remote_get_drawmode(void) |
54 | { | 85 | { |
55 | return drawmode; | 86 | return current_vp->drawmode; |
56 | } | 87 | } |
57 | 88 | ||
58 | void lcd_remote_setmargins(int x, int y) | 89 | void lcd_remote_setmargins(int x, int y) |
59 | { | 90 | { |
60 | xmargin = x; | 91 | current_vp->xmargin = x; |
61 | ymargin = y; | 92 | current_vp->ymargin = y; |
93 | } | ||
94 | |||
95 | int lcd_remote_getwidth(void) | ||
96 | { | ||
97 | return current_vp->width; | ||
98 | } | ||
99 | |||
100 | int lcd_remote_getheight(void) | ||
101 | { | ||
102 | return current_vp->height; | ||
62 | } | 103 | } |
63 | 104 | ||
64 | int lcd_remote_getxmargin(void) | 105 | int lcd_remote_getxmargin(void) |
65 | { | 106 | { |
66 | return xmargin; | 107 | return current_vp->xmargin; |
67 | } | 108 | } |
68 | 109 | ||
69 | int lcd_remote_getymargin(void) | 110 | int lcd_remote_getymargin(void) |
70 | { | 111 | { |
71 | return ymargin; | 112 | return current_vp->ymargin; |
72 | } | 113 | } |
73 | 114 | ||
74 | void lcd_remote_setfont(int newfont) | 115 | void lcd_remote_setfont(int newfont) |
75 | { | 116 | { |
76 | curfont = newfont; | 117 | current_vp->font = newfont; |
77 | } | 118 | } |
78 | 119 | ||
79 | int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h) | 120 | int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h) |
80 | { | 121 | { |
81 | return font_getstringsize(str, w, h, curfont); | 122 | return font_getstringsize(str, w, h, current_vp->font); |
82 | } | 123 | } |
83 | 124 | ||
84 | /*** low-level drawing functions ***/ | 125 | /*** low-level drawing functions ***/ |
@@ -181,17 +222,44 @@ lcd_remote_blockfunc_type* const lcd_remote_blockfuncs[8] = { | |||
181 | /* Clear the whole display */ | 222 | /* Clear the whole display */ |
182 | void lcd_remote_clear_display(void) | 223 | void lcd_remote_clear_display(void) |
183 | { | 224 | { |
184 | unsigned bits = (drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; | 225 | unsigned bits = (current_vp->drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; |
185 | 226 | ||
186 | memset(lcd_remote_framebuffer, bits, sizeof lcd_remote_framebuffer); | 227 | memset(lcd_remote_framebuffer, bits, sizeof lcd_remote_framebuffer); |
228 | |||
187 | lcd_remote_scroll_info.lines = 0; | 229 | lcd_remote_scroll_info.lines = 0; |
188 | } | 230 | } |
189 | 231 | ||
232 | /* Clear the current viewport */ | ||
233 | void lcd_remote_clear_viewport(void) | ||
234 | { | ||
235 | int oldmode; | ||
236 | |||
237 | if (current_vp == &default_vp) | ||
238 | { | ||
239 | lcd_remote_clear_display(); | ||
240 | } | ||
241 | else | ||
242 | { | ||
243 | oldmode = current_vp->drawmode; | ||
244 | |||
245 | /* Invert the INVERSEVID bit and set basic mode to SOLID */ | ||
246 | current_vp->drawmode = (~current_vp->drawmode & DRMODE_INVERSEVID) | | ||
247 | DRMODE_SOLID; | ||
248 | |||
249 | lcd_remote_fillrect(0, 0, current_vp->width, current_vp->height); | ||
250 | |||
251 | current_vp->drawmode = oldmode; | ||
252 | |||
253 | lcd_remote_scroll_stop(current_vp); | ||
254 | } | ||
255 | } | ||
256 | |||
190 | /* Set a single pixel */ | 257 | /* Set a single pixel */ |
191 | void lcd_remote_drawpixel(int x, int y) | 258 | void lcd_remote_drawpixel(int x, int y) |
192 | { | 259 | { |
193 | if (((unsigned)x < LCD_REMOTE_WIDTH) && ((unsigned)y < LCD_REMOTE_HEIGHT)) | 260 | if (((unsigned)x < (unsigned)current_vp->width) && |
194 | lcd_remote_pixelfuncs[drawmode](x, y); | 261 | ((unsigned)y < (unsigned)current_vp->height)) |
262 | lcd_remote_pixelfuncs[current_vp->drawmode](current_vp->x+x, current_vp->y+y); | ||
195 | } | 263 | } |
196 | 264 | ||
197 | /* Draw a line */ | 265 | /* Draw a line */ |
@@ -203,7 +271,7 @@ void lcd_remote_drawline(int x1, int y1, int x2, int y2) | |||
203 | int d, dinc1, dinc2; | 271 | int d, dinc1, dinc2; |
204 | int x, xinc1, xinc2; | 272 | int x, xinc1, xinc2; |
205 | int y, yinc1, yinc2; | 273 | int y, yinc1, yinc2; |
206 | lcd_remote_pixelfunc_type *pfunc = lcd_remote_pixelfuncs[drawmode]; | 274 | lcd_remote_pixelfunc_type *pfunc = lcd_remote_pixelfuncs[current_vp->drawmode]; |
207 | 275 | ||
208 | deltax = abs(x2 - x1); | 276 | deltax = abs(x2 - x1); |
209 | deltay = abs(y2 - y1); | 277 | deltay = abs(y2 - y1); |
@@ -247,8 +315,8 @@ void lcd_remote_drawline(int x1, int y1, int x2, int y2) | |||
247 | 315 | ||
248 | for (i = 0; i < numpixels; i++) | 316 | for (i = 0; i < numpixels; i++) |
249 | { | 317 | { |
250 | if (((unsigned)x < LCD_REMOTE_WIDTH) && ((unsigned)y < LCD_REMOTE_HEIGHT)) | 318 | if (((unsigned)x < (unsigned)current_vp->width) && ((unsigned)y < (unsigned)current_vp->height)) |
251 | pfunc(x, y); | 319 | pfunc(x + current_vp->x, y + current_vp->y); |
252 | 320 | ||
253 | if (d < 0) | 321 | if (d < 0) |
254 | { | 322 | { |
@@ -268,7 +336,7 @@ void lcd_remote_drawline(int x1, int y1, int x2, int y2) | |||
268 | /* Draw a horizontal line (optimised) */ | 336 | /* Draw a horizontal line (optimised) */ |
269 | void lcd_remote_hline(int x1, int x2, int y) | 337 | void lcd_remote_hline(int x1, int x2, int y) |
270 | { | 338 | { |
271 | int x; | 339 | int x, width; |
272 | fb_remote_data *dst, *dst_end; | 340 | fb_remote_data *dst, *dst_end; |
273 | unsigned mask; | 341 | unsigned mask; |
274 | lcd_remote_blockfunc_type *bfunc; | 342 | lcd_remote_blockfunc_type *bfunc; |
@@ -282,24 +350,30 @@ void lcd_remote_hline(int x1, int x2, int y) | |||
282 | } | 350 | } |
283 | 351 | ||
284 | /* nothing to draw? */ | 352 | /* nothing to draw? */ |
285 | if (((unsigned)y >= LCD_REMOTE_HEIGHT) || (x1 >= LCD_REMOTE_WIDTH) | 353 | if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) |
286 | || (x2 < 0)) | 354 | || (x2 < 0)) |
287 | return; | 355 | return; |
288 | 356 | ||
289 | /* clipping */ | 357 | /* clipping */ |
290 | if (x1 < 0) | 358 | if (x1 < 0) |
291 | x1 = 0; | 359 | x1 = 0; |
292 | if (x2 >= LCD_REMOTE_WIDTH) | 360 | if (x2 >= current_vp->width) |
293 | x2 = LCD_REMOTE_WIDTH-1; | 361 | x2 = current_vp->width-1; |
294 | 362 | ||
295 | bfunc = lcd_remote_blockfuncs[drawmode]; | 363 | width = x2 - x1 + 1; |
364 | |||
365 | /* Adjust x1 and y to viewport */ | ||
366 | x1 += current_vp->x; | ||
367 | y += current_vp->y; | ||
368 | |||
369 | bfunc = lcd_remote_blockfuncs[current_vp->drawmode]; | ||
296 | dst = &lcd_remote_framebuffer[y>>3][x1]; | 370 | dst = &lcd_remote_framebuffer[y>>3][x1]; |
297 | mask = 1 << (y & 7); | 371 | mask = 1 << (y & 7); |
298 | 372 | ||
299 | dst_end = dst + x2 - x1; | 373 | dst_end = dst + width; |
300 | do | 374 | do |
301 | bfunc(dst++, mask, 0xFFu); | 375 | bfunc(dst++, mask, 0xFFu); |
302 | while (dst <= dst_end); | 376 | while (dst < dst_end); |
303 | } | 377 | } |
304 | 378 | ||
305 | /* Draw a vertical line (optimised) */ | 379 | /* Draw a vertical line (optimised) */ |
@@ -319,17 +393,22 @@ void lcd_remote_vline(int x, int y1, int y2) | |||
319 | } | 393 | } |
320 | 394 | ||
321 | /* nothing to draw? */ | 395 | /* nothing to draw? */ |
322 | if (((unsigned)x >= LCD_REMOTE_WIDTH) || (y1 >= LCD_REMOTE_HEIGHT) | 396 | if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) |
323 | || (y2 < 0)) | 397 | || (y2 < 0)) |
324 | return; | 398 | return; |
325 | 399 | ||
326 | /* clipping */ | 400 | /* clipping */ |
327 | if (y1 < 0) | 401 | if (y1 < 0) |
328 | y1 = 0; | 402 | y1 = 0; |
329 | if (y2 >= LCD_REMOTE_HEIGHT) | 403 | if (y2 >= current_vp->height) |
330 | y2 = LCD_REMOTE_HEIGHT-1; | 404 | y2 = current_vp->height-1; |
405 | |||
406 | /* adjust for viewport */ | ||
407 | y1 += current_vp->y; | ||
408 | y2 += current_vp->y; | ||
409 | x += current_vp->x; | ||
331 | 410 | ||
332 | bfunc = lcd_remote_blockfuncs[drawmode]; | 411 | bfunc = lcd_remote_blockfuncs[current_vp->drawmode]; |
333 | dst = &lcd_remote_framebuffer[y1>>3][x]; | 412 | dst = &lcd_remote_framebuffer[y1>>3][x]; |
334 | ny = y2 - (y1 & ~7); | 413 | ny = y2 - (y1 & ~7); |
335 | mask = 0xFFu << (y1 & 7); | 414 | mask = 0xFFu << (y1 & 7); |
@@ -371,8 +450,8 @@ void lcd_remote_fillrect(int x, int y, int width, int height) | |||
371 | bool fillopt = false; | 450 | bool fillopt = false; |
372 | 451 | ||
373 | /* nothing to draw? */ | 452 | /* nothing to draw? */ |
374 | if ((width <= 0) || (height <= 0) || (x >= LCD_REMOTE_WIDTH) | 453 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
375 | || (y >= LCD_REMOTE_HEIGHT) || (x + width <= 0) || (y + height <= 0)) | 454 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
376 | return; | 455 | return; |
377 | 456 | ||
378 | /* clipping */ | 457 | /* clipping */ |
@@ -386,27 +465,32 @@ void lcd_remote_fillrect(int x, int y, int width, int height) | |||
386 | height += y; | 465 | height += y; |
387 | y = 0; | 466 | y = 0; |
388 | } | 467 | } |
389 | if (x + width > LCD_REMOTE_WIDTH) | 468 | if (x + width > current_vp->width) |
390 | width = LCD_REMOTE_WIDTH - x; | 469 | width = current_vp->width - x; |
391 | if (y + height > LCD_REMOTE_HEIGHT) | 470 | if (y + height > current_vp->height) |
392 | height = LCD_REMOTE_HEIGHT - y; | 471 | height = current_vp->height - y; |
393 | 472 | ||
394 | if (drawmode & DRMODE_INVERSEVID) | 473 | /* adjust for viewport */ |
474 | x += current_vp->x; | ||
475 | y += current_vp->y; | ||
476 | |||
477 | if (current_vp->drawmode & DRMODE_INVERSEVID) | ||
395 | { | 478 | { |
396 | if (drawmode & DRMODE_BG) | 479 | if (current_vp->drawmode & DRMODE_BG) |
397 | { | 480 | { |
398 | fillopt = true; | 481 | fillopt = true; |
399 | } | 482 | } |
400 | } | 483 | } |
401 | else | 484 | else |
402 | { | 485 | { |
403 | if (drawmode & DRMODE_FG) | 486 | if (current_vp->drawmode & DRMODE_FG) |
404 | { | 487 | { |
405 | fillopt = true; | 488 | fillopt = true; |
406 | bits = 0xFFu; | 489 | bits = 0xFFu; |
407 | } | 490 | } |
408 | } | 491 | } |
409 | bfunc = lcd_remote_blockfuncs[drawmode]; | 492 | |
493 | bfunc = lcd_remote_blockfuncs[current_vp->drawmode]; | ||
410 | dst = &lcd_remote_framebuffer[y>>3][x]; | 494 | dst = &lcd_remote_framebuffer[y>>3][x]; |
411 | ny = height - 1 + (y & 7); | 495 | ny = height - 1 + (y & 7); |
412 | mask = 0xFFu << (y & 7); | 496 | mask = 0xFFu << (y & 7); |
@@ -466,8 +550,8 @@ void lcd_remote_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
466 | lcd_remote_blockfunc_type *bfunc; | 550 | lcd_remote_blockfunc_type *bfunc; |
467 | 551 | ||
468 | /* nothing to draw? */ | 552 | /* nothing to draw? */ |
469 | if ((width <= 0) || (height <= 0) || (x >= LCD_REMOTE_WIDTH) | 553 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
470 | || (y >= LCD_REMOTE_HEIGHT) || (x + width <= 0) || (y + height <= 0)) | 554 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
471 | return; | 555 | return; |
472 | 556 | ||
473 | /* clipping */ | 557 | /* clipping */ |
@@ -483,10 +567,14 @@ void lcd_remote_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
483 | src_y -= y; | 567 | src_y -= y; |
484 | y = 0; | 568 | y = 0; |
485 | } | 569 | } |
486 | if (x + width > LCD_REMOTE_WIDTH) | 570 | if (x + width > current_vp->width) |
487 | width = LCD_REMOTE_WIDTH - x; | 571 | width = current_vp->width - x; |
488 | if (y + height > LCD_REMOTE_HEIGHT) | 572 | if (y + height > current_vp->height) |
489 | height = LCD_REMOTE_HEIGHT - y; | 573 | height = current_vp->height - y; |
574 | |||
575 | /* adjust for viewports */ | ||
576 | x += current_vp->x; | ||
577 | y += current_vp->y; | ||
490 | 578 | ||
491 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 579 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
492 | src_y &= 7; | 580 | src_y &= 7; |
@@ -495,13 +583,13 @@ void lcd_remote_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
495 | shift = y & 7; | 583 | shift = y & 7; |
496 | ny = height - 1 + shift + src_y; | 584 | ny = height - 1 + shift + src_y; |
497 | 585 | ||
498 | bfunc = lcd_remote_blockfuncs[drawmode]; | 586 | bfunc = lcd_remote_blockfuncs[current_vp->drawmode]; |
499 | mask = 0xFFu << (shift + src_y); | 587 | mask = 0xFFu << (shift + src_y); |
500 | mask_bottom = 0xFFu >> (~ny & 7); | 588 | mask_bottom = 0xFFu >> (~ny & 7); |
501 | 589 | ||
502 | if (shift == 0) | 590 | if (shift == 0) |
503 | { | 591 | { |
504 | bool copyopt = (drawmode == DRMODE_SOLID); | 592 | bool copyopt = (current_vp->drawmode == DRMODE_SOLID); |
505 | 593 | ||
506 | for (; ny >= 8; ny -= 8) | 594 | for (; ny >= 8; ny -= 8) |
507 | { | 595 | { |
@@ -579,11 +667,11 @@ void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
579 | { | 667 | { |
580 | unsigned short ch; | 668 | unsigned short ch; |
581 | unsigned short *ucs; | 669 | unsigned short *ucs; |
582 | struct font* pf = font_get(curfont); | 670 | struct font* pf = font_get(current_vp->font); |
583 | 671 | ||
584 | ucs = bidi_l2v(str, 1); | 672 | ucs = bidi_l2v(str, 1); |
585 | 673 | ||
586 | while ((ch = *ucs++) != 0 && x < LCD_REMOTE_WIDTH) | 674 | while ((ch = *ucs++) != 0 && x < current_vp->width) |
587 | { | 675 | { |
588 | int width; | 676 | int width; |
589 | const unsigned char *bits; | 677 | const unsigned char *bits; |
@@ -637,24 +725,24 @@ void lcd_remote_puts_style_offset(int x, int y, const unsigned char *str, | |||
637 | int style, int offset) | 725 | int style, int offset) |
638 | { | 726 | { |
639 | int xpos,ypos,w,h,xrect; | 727 | int xpos,ypos,w,h,xrect; |
640 | int lastmode = drawmode; | 728 | int lastmode = current_vp->drawmode; |
641 | 729 | ||
642 | /* make sure scrolling is turned off on the line we are updating */ | 730 | /* make sure scrolling is turned off on the line we are updating */ |
643 | lcd_remote_scroll_info.lines &= ~(1 << y); | 731 | lcd_remote_scroll_stop_line(current_vp, y); |
644 | 732 | ||
645 | if(!str || !str[0]) | 733 | if(!str || !str[0]) |
646 | return; | 734 | return; |
647 | 735 | ||
648 | lcd_remote_getstringsize(str, &w, &h); | 736 | lcd_remote_getstringsize(str, &w, &h); |
649 | xpos = xmargin + x*w / utf8length((char *)str); | 737 | xpos = current_vp->xmargin + x*w / utf8length((char *)str); |
650 | ypos = ymargin + y*h; | 738 | ypos = current_vp->ymargin + y*h; |
651 | drawmode = (style & STYLE_INVERT) ? | 739 | current_vp->drawmode = (style & STYLE_INVERT) ? |
652 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | 740 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; |
653 | lcd_remote_putsxyofs(xpos, ypos, offset, str); | 741 | lcd_remote_putsxyofs(xpos, ypos, offset, str); |
654 | drawmode ^= DRMODE_INVERSEVID; | 742 | current_vp->drawmode ^= DRMODE_INVERSEVID; |
655 | xrect = xpos + MAX(w - offset, 0); | 743 | xrect = xpos + MAX(w - offset, 0); |
656 | lcd_remote_fillrect(xrect, ypos, LCD_REMOTE_WIDTH - xrect, h); | 744 | lcd_remote_fillrect(xrect, ypos, current_vp->width - xrect, h); |
657 | drawmode = lastmode; | 745 | current_vp->drawmode = lastmode; |
658 | } | 746 | } |
659 | 747 | ||
660 | /*** scrolling ***/ | 748 | /*** scrolling ***/ |
@@ -680,9 +768,15 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri | |||
680 | struct scrollinfo* s; | 768 | struct scrollinfo* s; |
681 | int w, h; | 769 | int w, h; |
682 | 770 | ||
683 | if(y>=LCD_REMOTE_SCROLLABLE_LINES) return; | 771 | if ((unsigned)y >= (unsigned)current_vp->height) |
772 | return; | ||
773 | |||
774 | /* remove any previously scrolling line at the same location */ | ||
775 | lcd_remote_scroll_stop_line(current_vp, y); | ||
776 | |||
777 | if (lcd_remote_scroll_info.lines >= LCD_REMOTE_SCROLLABLE_LINES) return; | ||
684 | 778 | ||
685 | s = &lcd_remote_scroll_info.scroll[y]; | 779 | s = &lcd_remote_scroll_info.scroll[lcd_remote_scroll_info.lines]; |
686 | 780 | ||
687 | s->start_tick = current_tick + lcd_remote_scroll_info.delay; | 781 | s->start_tick = current_tick + lcd_remote_scroll_info.delay; |
688 | s->style = style; | 782 | s->style = style; |
@@ -694,7 +788,7 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri | |||
694 | 788 | ||
695 | lcd_remote_getstringsize(string, &w, &h); | 789 | lcd_remote_getstringsize(string, &w, &h); |
696 | 790 | ||
697 | if (LCD_REMOTE_WIDTH - x * 8 - xmargin < w) { | 791 | if (current_vp->width - x * 8 - current_vp->xmargin < w) { |
698 | /* prepare scroll line */ | 792 | /* prepare scroll line */ |
699 | char *end; | 793 | char *end; |
700 | 794 | ||
@@ -707,7 +801,7 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri | |||
707 | /* scroll bidirectional or forward only depending on the string | 801 | /* scroll bidirectional or forward only depending on the string |
708 | width */ | 802 | width */ |
709 | if ( lcd_remote_scroll_info.bidir_limit ) { | 803 | if ( lcd_remote_scroll_info.bidir_limit ) { |
710 | s->bidir = s->width < (LCD_REMOTE_WIDTH - xmargin) * | 804 | s->bidir = s->width < (current_vp->width - current_vp->xmargin) * |
711 | (100 + lcd_remote_scroll_info.bidir_limit) / 100; | 805 | (100 + lcd_remote_scroll_info.bidir_limit) / 100; |
712 | } | 806 | } |
713 | else | 807 | else |
@@ -720,17 +814,17 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri | |||
720 | } | 814 | } |
721 | 815 | ||
722 | end = strchr(s->line, '\0'); | 816 | end = strchr(s->line, '\0'); |
723 | strncpy(end, (char *)string, LCD_REMOTE_WIDTH/2); | 817 | strncpy(end, (char *)string, current_vp->width/2); |
724 | 818 | ||
819 | s->vp = current_vp; | ||
820 | s->y = y; | ||
725 | s->len = utf8length((char *)string); | 821 | s->len = utf8length((char *)string); |
726 | s->offset = offset; | 822 | s->offset = offset; |
727 | s->startx = xmargin + x * s->width / s->len;; | 823 | s->startx = current_vp->xmargin + x * s->width / s->len; |
728 | s->backward = false; | 824 | s->backward = false; |
729 | lcd_remote_scroll_info.lines |= (1<<y); | 825 | |
826 | lcd_remote_scroll_info.lines++; | ||
730 | } | 827 | } |
731 | else | ||
732 | /* force a bit switch-off since it doesn't scroll */ | ||
733 | lcd_remote_scroll_info.lines &= ~(1<<y); | ||
734 | } | 828 | } |
735 | 829 | ||
736 | void lcd_remote_scroll_fn(void) | 830 | void lcd_remote_scroll_fn(void) |
@@ -740,26 +834,25 @@ void lcd_remote_scroll_fn(void) | |||
740 | int index; | 834 | int index; |
741 | int xpos, ypos; | 835 | int xpos, ypos; |
742 | int lastmode; | 836 | int lastmode; |
837 | struct viewport* old_vp = current_vp; | ||
743 | 838 | ||
744 | for ( index = 0; index < LCD_REMOTE_SCROLLABLE_LINES; index++ ) { | 839 | for ( index = 0; index < lcd_remote_scroll_info.lines; index++ ) { |
745 | /* really scroll? */ | ||
746 | if ((lcd_remote_scroll_info.lines & (1 << index)) == 0) | ||
747 | continue; | ||
748 | |||
749 | s = &lcd_remote_scroll_info.scroll[index]; | 840 | s = &lcd_remote_scroll_info.scroll[index]; |
750 | 841 | ||
751 | /* check pause */ | 842 | /* check pause */ |
752 | if (TIME_BEFORE(current_tick, s->start_tick)) | 843 | if (TIME_BEFORE(current_tick, s->start_tick)) |
753 | continue; | 844 | continue; |
754 | 845 | ||
846 | lcd_remote_set_viewport(s->vp); | ||
847 | |||
755 | if (s->backward) | 848 | if (s->backward) |
756 | s->offset -= lcd_remote_scroll_info.step; | 849 | s->offset -= lcd_remote_scroll_info.step; |
757 | else | 850 | else |
758 | s->offset += lcd_remote_scroll_info.step; | 851 | s->offset += lcd_remote_scroll_info.step; |
759 | 852 | ||
760 | pf = font_get(curfont); | 853 | pf = font_get(current_vp->font); |
761 | xpos = s->startx; | 854 | xpos = s->startx; |
762 | ypos = ymargin + index * pf->height; | 855 | ypos = current_vp->ymargin + s->y * pf->height; |
763 | 856 | ||
764 | if (s->bidir) { /* scroll bidirectional */ | 857 | if (s->bidir) { /* scroll bidirectional */ |
765 | if (s->offset <= 0) { | 858 | if (s->offset <= 0) { |
@@ -768,9 +861,9 @@ void lcd_remote_scroll_fn(void) | |||
768 | s->backward = false; | 861 | s->backward = false; |
769 | s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; | 862 | s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; |
770 | } | 863 | } |
771 | if (s->offset >= s->width - (LCD_REMOTE_WIDTH - xpos)) { | 864 | if (s->offset >= s->width - (current_vp->width - xpos)) { |
772 | /* at end of line */ | 865 | /* at end of line */ |
773 | s->offset = s->width - (LCD_REMOTE_WIDTH - xpos); | 866 | s->offset = s->width - (current_vp->width - xpos); |
774 | s->backward = true; | 867 | s->backward = true; |
775 | s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; | 868 | s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; |
776 | } | 869 | } |
@@ -781,13 +874,16 @@ void lcd_remote_scroll_fn(void) | |||
781 | s->offset %= s->width; | 874 | s->offset %= s->width; |
782 | } | 875 | } |
783 | 876 | ||
784 | lastmode = drawmode; | 877 | lastmode = current_vp->drawmode; |
785 | drawmode = (s->style&STYLE_INVERT) ? | 878 | current_vp->drawmode = (s->style&STYLE_INVERT) ? |
786 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | 879 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; |
787 | lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line); | 880 | lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line); |
788 | drawmode = lastmode; | 881 | current_vp->drawmode = lastmode; |
789 | lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height); | 882 | lcd_remote_update_viewport_rect(xpos, ypos, |
883 | current_vp->width - xpos, pf->height); | ||
790 | } | 884 | } |
885 | |||
886 | lcd_remote_set_viewport(old_vp); | ||
791 | } | 887 | } |
792 | 888 | ||
793 | /* LCD init */ | 889 | /* LCD init */ |
diff --git a/firmware/drivers/lcd-remote-2bit-vi.c b/firmware/drivers/lcd-remote-2bit-vi.c index d5757f4dbb..9ab98c69aa 100644 --- a/firmware/drivers/lcd-remote-2bit-vi.c +++ b/firmware/drivers/lcd-remote-2bit-vi.c | |||
@@ -46,12 +46,48 @@ static const fb_remote_data patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000}; | |||
46 | static fb_remote_data* remote_backdrop = NULL; | 46 | static fb_remote_data* remote_backdrop = NULL; |
47 | static long remote_backdrop_offset IDATA_ATTR = 0; | 47 | static long remote_backdrop_offset IDATA_ATTR = 0; |
48 | 48 | ||
49 | static unsigned fg_pattern IDATA_ATTR = 0xFFFF; /* initially black */ | 49 | static struct viewport default_vp = |
50 | static unsigned bg_pattern IDATA_ATTR = 0x0000; /* initially white */ | 50 | { |
51 | static int drawmode = DRMODE_SOLID; | 51 | .x = 0, |
52 | static int xmargin = 0; | 52 | .y = 0, |
53 | static int ymargin = 0; | 53 | .width = LCD_REMOTE_WIDTH, |
54 | static int curfont = FONT_SYSFIXED; | 54 | .height = LCD_REMOTE_HEIGHT, |
55 | .font = FONT_SYSFIXED, | ||
56 | .drawmode = DRMODE_SOLID, | ||
57 | .xmargin = 0, | ||
58 | .ymargin = 0, | ||
59 | .fg_pattern = LCD_REMOTE_DEFAULT_FG, | ||
60 | .bg_pattern = LCD_REMOTE_DEFAULT_BG | ||
61 | }; | ||
62 | |||
63 | static unsigned fg_pattern IBSS_ATTR; | ||
64 | static unsigned bg_pattern IBSS_ATTR; | ||
65 | |||
66 | static struct viewport* current_vp IBSS_ATTR;; | ||
67 | |||
68 | /*** Viewports ***/ | ||
69 | |||
70 | void lcd_remote_set_viewport(struct viewport* vp) | ||
71 | { | ||
72 | if (vp == NULL) | ||
73 | current_vp = &default_vp; | ||
74 | else | ||
75 | current_vp = vp; | ||
76 | |||
77 | fg_pattern = patterns[current_vp->fg_pattern & 3]; | ||
78 | bg_pattern = patterns[current_vp->bg_pattern & 3]; | ||
79 | } | ||
80 | |||
81 | void lcd_remote_update_viewport(void) | ||
82 | { | ||
83 | lcd_remote_update_rect(current_vp->x, current_vp->y, | ||
84 | current_vp->width, current_vp->height); | ||
85 | } | ||
86 | |||
87 | void lcd_remote_update_viewport_rect(int x, int y, int width, int height) | ||
88 | { | ||
89 | lcd_remote_update_rect(current_vp->x + x, current_vp->y + y, width, height); | ||
90 | } | ||
55 | 91 | ||
56 | /*** parameter handling ***/ | 92 | /*** parameter handling ***/ |
57 | unsigned lcd_remote_color_to_native(unsigned color) | 93 | unsigned lcd_remote_color_to_native(unsigned color) |
@@ -69,32 +105,34 @@ unsigned lcd_remote_color_to_native(unsigned color) | |||
69 | 105 | ||
70 | void lcd_remote_set_drawmode(int mode) | 106 | void lcd_remote_set_drawmode(int mode) |
71 | { | 107 | { |
72 | drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); | 108 | current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); |
73 | } | 109 | } |
74 | 110 | ||
75 | int lcd_remote_get_drawmode(void) | 111 | int lcd_remote_get_drawmode(void) |
76 | { | 112 | { |
77 | return drawmode; | 113 | return current_vp->drawmode; |
78 | } | 114 | } |
79 | 115 | ||
80 | void lcd_remote_set_foreground(unsigned brightness) | 116 | void lcd_remote_set_foreground(unsigned brightness) |
81 | { | 117 | { |
118 | current_vp->fg_pattern = brightness; | ||
82 | fg_pattern = patterns[brightness & 3]; | 119 | fg_pattern = patterns[brightness & 3]; |
83 | } | 120 | } |
84 | 121 | ||
85 | unsigned lcd_remote_get_foreground(void) | 122 | unsigned lcd_remote_get_foreground(void) |
86 | { | 123 | { |
87 | return (~fg_pattern >> 7) & 3; | 124 | return current_vp->fg_pattern; |
88 | } | 125 | } |
89 | 126 | ||
90 | void lcd_remote_set_background(unsigned brightness) | 127 | void lcd_remote_set_background(unsigned brightness) |
91 | { | 128 | { |
129 | current_vp->bg_pattern = brightness; | ||
92 | bg_pattern = patterns[brightness & 3]; | 130 | bg_pattern = patterns[brightness & 3]; |
93 | } | 131 | } |
94 | 132 | ||
95 | unsigned lcd_remote_get_background(void) | 133 | unsigned lcd_remote_get_background(void) |
96 | { | 134 | { |
97 | return (~bg_pattern >> 7) & 3; | 135 | return current_vp->bg_pattern; |
98 | } | 136 | } |
99 | 137 | ||
100 | void lcd_remote_set_drawinfo(int mode, unsigned fg_brightness, | 138 | void lcd_remote_set_drawinfo(int mode, unsigned fg_brightness, |
@@ -105,30 +143,40 @@ void lcd_remote_set_drawinfo(int mode, unsigned fg_brightness, | |||
105 | lcd_remote_set_background(bg_brightness); | 143 | lcd_remote_set_background(bg_brightness); |
106 | } | 144 | } |
107 | 145 | ||
146 | int lcd_remote_getwidth(void) | ||
147 | { | ||
148 | return current_vp->width; | ||
149 | } | ||
150 | |||
151 | int lcd_remote_getheight(void) | ||
152 | { | ||
153 | return current_vp->height; | ||
154 | } | ||
155 | |||
108 | void lcd_remote_setmargins(int x, int y) | 156 | void lcd_remote_setmargins(int x, int y) |
109 | { | 157 | { |
110 | xmargin = x; | 158 | current_vp->xmargin = x; |
111 | ymargin = y; | 159 | current_vp->ymargin = y; |
112 | } | 160 | } |
113 | 161 | ||
114 | int lcd_remote_getxmargin(void) | 162 | int lcd_remote_getxmargin(void) |
115 | { | 163 | { |
116 | return xmargin; | 164 | return current_vp->xmargin; |
117 | } | 165 | } |
118 | 166 | ||
119 | int lcd_remote_getymargin(void) | 167 | int lcd_remote_getymargin(void) |
120 | { | 168 | { |
121 | return ymargin; | 169 | return current_vp->ymargin; |
122 | } | 170 | } |
123 | 171 | ||
124 | void lcd_remote_setfont(int newfont) | 172 | void lcd_remote_setfont(int newfont) |
125 | { | 173 | { |
126 | curfont = newfont; | 174 | current_vp->font = newfont; |
127 | } | 175 | } |
128 | 176 | ||
129 | int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h) | 177 | int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h) |
130 | { | 178 | { |
131 | return font_getstringsize(str, w, h, curfont); | 179 | return font_getstringsize(str, w, h, current_vp->font); |
132 | } | 180 | } |
133 | 181 | ||
134 | /*** low-level drawing functions ***/ | 182 | /*** low-level drawing functions ***/ |
@@ -351,9 +399,9 @@ static inline void setblock(fb_remote_data *address, unsigned mask, unsigned bit | |||
351 | /* Clear the whole display */ | 399 | /* Clear the whole display */ |
352 | void lcd_remote_clear_display(void) | 400 | void lcd_remote_clear_display(void) |
353 | { | 401 | { |
354 | if (drawmode & DRMODE_INVERSEVID) | 402 | if (default_vp.drawmode & DRMODE_INVERSEVID) |
355 | { | 403 | { |
356 | memset(lcd_remote_framebuffer, fg_pattern, | 404 | memset(lcd_remote_framebuffer, patterns[default_vp.fg_pattern & 3], |
357 | sizeof lcd_remote_framebuffer); | 405 | sizeof lcd_remote_framebuffer); |
358 | } | 406 | } |
359 | else | 407 | else |
@@ -362,18 +410,44 @@ void lcd_remote_clear_display(void) | |||
362 | memcpy(lcd_remote_framebuffer, remote_backdrop, | 410 | memcpy(lcd_remote_framebuffer, remote_backdrop, |
363 | sizeof lcd_remote_framebuffer); | 411 | sizeof lcd_remote_framebuffer); |
364 | else | 412 | else |
365 | memset(lcd_remote_framebuffer, bg_pattern, | 413 | memset(lcd_remote_framebuffer, patterns[default_vp.bg_pattern & 3], |
366 | sizeof lcd_remote_framebuffer); | 414 | sizeof lcd_remote_framebuffer); |
367 | } | 415 | } |
368 | 416 | ||
369 | lcd_remote_scroll_info.lines = 0; | 417 | lcd_remote_scroll_info.lines = 0; |
370 | } | 418 | } |
371 | 419 | ||
420 | /* Clear the current viewport */ | ||
421 | void lcd_remote_clear_viewport(void) | ||
422 | { | ||
423 | int lastmode; | ||
424 | |||
425 | if (current_vp == &default_vp) | ||
426 | { | ||
427 | lcd_remote_clear_display(); | ||
428 | } | ||
429 | else | ||
430 | { | ||
431 | lastmode = current_vp->drawmode; | ||
432 | |||
433 | /* Invert the INVERSEVID bit and set basic mode to SOLID */ | ||
434 | current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | | ||
435 | DRMODE_SOLID; | ||
436 | |||
437 | lcd_remote_fillrect(0, 0, current_vp->width, current_vp->height); | ||
438 | |||
439 | current_vp->drawmode = lastmode; | ||
440 | |||
441 | lcd_remote_scroll_stop(current_vp); | ||
442 | } | ||
443 | } | ||
444 | |||
372 | /* Set a single pixel */ | 445 | /* Set a single pixel */ |
373 | void lcd_remote_drawpixel(int x, int y) | 446 | void lcd_remote_drawpixel(int x, int y) |
374 | { | 447 | { |
375 | if (((unsigned)x < LCD_REMOTE_WIDTH) && ((unsigned)y < LCD_REMOTE_HEIGHT)) | 448 | if (((unsigned)x < (unsigned)current_vp->width) && |
376 | lcd_remote_pixelfuncs[drawmode](x, y); | 449 | ((unsigned)y < (unsigned)current_vp->height)) |
450 | lcd_remote_pixelfuncs[current_vp->drawmode](current_vp->x+x, current_vp->y+y); | ||
377 | } | 451 | } |
378 | 452 | ||
379 | /* Draw a line */ | 453 | /* Draw a line */ |
@@ -385,7 +459,7 @@ void lcd_remote_drawline(int x1, int y1, int x2, int y2) | |||
385 | int d, dinc1, dinc2; | 459 | int d, dinc1, dinc2; |
386 | int x, xinc1, xinc2; | 460 | int x, xinc1, xinc2; |
387 | int y, yinc1, yinc2; | 461 | int y, yinc1, yinc2; |
388 | lcd_remote_pixelfunc_type *pfunc = lcd_remote_pixelfuncs[drawmode]; | 462 | lcd_remote_pixelfunc_type *pfunc = lcd_remote_pixelfuncs[current_vp->drawmode]; |
389 | 463 | ||
390 | deltax = abs(x2 - x1); | 464 | deltax = abs(x2 - x1); |
391 | deltay = abs(y2 - y1); | 465 | deltay = abs(y2 - y1); |
@@ -429,8 +503,9 @@ void lcd_remote_drawline(int x1, int y1, int x2, int y2) | |||
429 | 503 | ||
430 | for (i = 0; i < numpixels; i++) | 504 | for (i = 0; i < numpixels; i++) |
431 | { | 505 | { |
432 | if (((unsigned)x < LCD_REMOTE_WIDTH) && ((unsigned)y < LCD_REMOTE_HEIGHT)) | 506 | if (((unsigned)x < (unsigned)current_vp->width) && |
433 | pfunc(x, y); | 507 | ((unsigned)y < (unsigned)current_vp->height)) |
508 | pfunc(current_vp->x + x, current_vp->y + y); | ||
434 | 509 | ||
435 | if (d < 0) | 510 | if (d < 0) |
436 | { | 511 | { |
@@ -451,6 +526,7 @@ void lcd_remote_drawline(int x1, int y1, int x2, int y2) | |||
451 | void lcd_remote_hline(int x1, int x2, int y) | 526 | void lcd_remote_hline(int x1, int x2, int y) |
452 | { | 527 | { |
453 | int x; | 528 | int x; |
529 | int width; | ||
454 | fb_remote_data *dst, *dst_end; | 530 | fb_remote_data *dst, *dst_end; |
455 | unsigned mask; | 531 | unsigned mask; |
456 | lcd_remote_blockfunc_type *bfunc; | 532 | lcd_remote_blockfunc_type *bfunc; |
@@ -464,24 +540,30 @@ void lcd_remote_hline(int x1, int x2, int y) | |||
464 | } | 540 | } |
465 | 541 | ||
466 | /* nothing to draw? */ | 542 | /* nothing to draw? */ |
467 | if (((unsigned)y >= LCD_REMOTE_HEIGHT) || (x1 >= LCD_REMOTE_WIDTH) | 543 | if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) |
468 | || (x2 < 0)) | 544 | || (x2 < 0)) |
469 | return; | 545 | return; |
470 | 546 | ||
471 | /* clipping */ | 547 | /* clipping */ |
472 | if (x1 < 0) | 548 | if (x1 < 0) |
473 | x1 = 0; | 549 | x1 = 0; |
474 | if (x2 >= LCD_REMOTE_WIDTH) | 550 | if (x2 >= current_vp->width) |
475 | x2 = LCD_REMOTE_WIDTH-1; | 551 | x2 = current_vp->width-1; |
476 | 552 | ||
477 | bfunc = lcd_remote_blockfuncs[drawmode]; | 553 | width = x2 - x1 + 1; |
554 | |||
555 | /* adjust x1 and y to viewport */ | ||
556 | x1 += current_vp->x; | ||
557 | y += current_vp->y; | ||
558 | |||
559 | bfunc = lcd_remote_blockfuncs[current_vp->drawmode]; | ||
478 | dst = &lcd_remote_framebuffer[y>>3][x1]; | 560 | dst = &lcd_remote_framebuffer[y>>3][x1]; |
479 | mask = 0x0101 << (y & 7); | 561 | mask = 0x0101 << (y & 7); |
480 | 562 | ||
481 | dst_end = dst + x2 - x1; | 563 | dst_end = dst + width; |
482 | do | 564 | do |
483 | bfunc(dst++, mask, 0xFFFFu); | 565 | bfunc(dst++, mask, 0xFFFFu); |
484 | while (dst <= dst_end); | 566 | while (dst < dst_end); |
485 | } | 567 | } |
486 | 568 | ||
487 | /* Draw a vertical line (optimised) */ | 569 | /* Draw a vertical line (optimised) */ |
@@ -501,17 +583,22 @@ void lcd_remote_vline(int x, int y1, int y2) | |||
501 | } | 583 | } |
502 | 584 | ||
503 | /* nothing to draw? */ | 585 | /* nothing to draw? */ |
504 | if (((unsigned)x >= LCD_REMOTE_WIDTH) || (y1 >= LCD_REMOTE_HEIGHT) | 586 | if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) |
505 | || (y2 < 0)) | 587 | || (y2 < 0)) |
506 | return; | 588 | return; |
507 | 589 | ||
508 | /* clipping */ | 590 | /* clipping */ |
509 | if (y1 < 0) | 591 | if (y1 < 0) |
510 | y1 = 0; | 592 | y1 = 0; |
511 | if (y2 >= LCD_REMOTE_HEIGHT) | 593 | if (y2 >= current_vp->height) |
512 | y2 = LCD_REMOTE_HEIGHT-1; | 594 | y2 = current_vp->height-1; |
595 | |||
596 | /* adjust for viewport */ | ||
597 | y1 += current_vp->y; | ||
598 | y2 += current_vp->y; | ||
599 | x += current_vp->x; | ||
513 | 600 | ||
514 | bfunc = lcd_remote_blockfuncs[drawmode]; | 601 | bfunc = lcd_remote_blockfuncs[current_vp->drawmode]; |
515 | dst = &lcd_remote_framebuffer[y1>>3][x]; | 602 | dst = &lcd_remote_framebuffer[y1>>3][x]; |
516 | ny = y2 - (y1 & ~7); | 603 | ny = y2 - (y1 & ~7); |
517 | mask = (0xFFu << (y1 & 7)) & 0xFFu; | 604 | mask = (0xFFu << (y1 & 7)) & 0xFFu; |
@@ -555,8 +642,8 @@ void lcd_remote_fillrect(int x, int y, int width, int height) | |||
555 | bool fillopt = false; | 642 | bool fillopt = false; |
556 | 643 | ||
557 | /* nothing to draw? */ | 644 | /* nothing to draw? */ |
558 | if ((width <= 0) || (height <= 0) || (x >= LCD_REMOTE_WIDTH) | 645 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
559 | || (y >= LCD_REMOTE_HEIGHT) || (x + width <= 0) || (y + height <= 0)) | 646 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
560 | return; | 647 | return; |
561 | 648 | ||
562 | /* clipping */ | 649 | /* clipping */ |
@@ -570,14 +657,18 @@ void lcd_remote_fillrect(int x, int y, int width, int height) | |||
570 | height += y; | 657 | height += y; |
571 | y = 0; | 658 | y = 0; |
572 | } | 659 | } |
573 | if (x + width > LCD_REMOTE_WIDTH) | 660 | if (x + width > current_vp->width) |
574 | width = LCD_REMOTE_WIDTH - x; | 661 | width = current_vp->width - x; |
575 | if (y + height > LCD_REMOTE_HEIGHT) | 662 | if (y + height > current_vp->height) |
576 | height = LCD_REMOTE_HEIGHT - y; | 663 | height = current_vp->height - y; |
577 | 664 | ||
578 | if (drawmode & DRMODE_INVERSEVID) | 665 | /* adjust for viewport */ |
666 | x += current_vp->x; | ||
667 | y += current_vp->y; | ||
668 | |||
669 | if (current_vp->drawmode & DRMODE_INVERSEVID) | ||
579 | { | 670 | { |
580 | if ((drawmode & DRMODE_BG) && !remote_backdrop) | 671 | if ((current_vp->drawmode & DRMODE_BG) && !remote_backdrop) |
581 | { | 672 | { |
582 | fillopt = true; | 673 | fillopt = true; |
583 | bits = bg_pattern; | 674 | bits = bg_pattern; |
@@ -585,13 +676,13 @@ void lcd_remote_fillrect(int x, int y, int width, int height) | |||
585 | } | 676 | } |
586 | else | 677 | else |
587 | { | 678 | { |
588 | if (drawmode & DRMODE_FG) | 679 | if (current_vp->drawmode & DRMODE_FG) |
589 | { | 680 | { |
590 | fillopt = true; | 681 | fillopt = true; |
591 | bits = fg_pattern; | 682 | bits = fg_pattern; |
592 | } | 683 | } |
593 | } | 684 | } |
594 | bfunc = lcd_remote_blockfuncs[drawmode]; | 685 | bfunc = lcd_remote_blockfuncs[current_vp->drawmode]; |
595 | dst = &lcd_remote_framebuffer[y>>3][x]; | 686 | dst = &lcd_remote_framebuffer[y>>3][x]; |
596 | ny = height - 1 + (y & 7); | 687 | ny = height - 1 + (y & 7); |
597 | mask = (0xFFu << (y & 7)) & 0xFFu; | 688 | mask = (0xFFu << (y & 7)) & 0xFFu; |
@@ -653,8 +744,8 @@ void lcd_remote_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
653 | lcd_remote_blockfunc_type *bfunc; | 744 | lcd_remote_blockfunc_type *bfunc; |
654 | 745 | ||
655 | /* nothing to draw? */ | 746 | /* nothing to draw? */ |
656 | if ((width <= 0) || (height <= 0) || (x >= LCD_REMOTE_WIDTH) | 747 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
657 | || (y >= LCD_REMOTE_HEIGHT) || (x + width <= 0) || (y + height <= 0)) | 748 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
658 | return; | 749 | return; |
659 | 750 | ||
660 | /* clipping */ | 751 | /* clipping */ |
@@ -670,10 +761,14 @@ void lcd_remote_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
670 | src_y -= y; | 761 | src_y -= y; |
671 | y = 0; | 762 | y = 0; |
672 | } | 763 | } |
673 | if (x + width > LCD_REMOTE_WIDTH) | 764 | if (x + width > current_vp->width) |
674 | width = LCD_REMOTE_WIDTH - x; | 765 | width = current_vp->width - x; |
675 | if (y + height > LCD_REMOTE_HEIGHT) | 766 | if (y + height > current_vp->height) |
676 | height = LCD_REMOTE_HEIGHT - y; | 767 | height = current_vp->height - y; |
768 | |||
769 | /* adjust for viewport */ | ||
770 | x += current_vp->x; | ||
771 | y += current_vp->y; | ||
677 | 772 | ||
678 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 773 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
679 | src_y &= 7; | 774 | src_y &= 7; |
@@ -682,7 +777,7 @@ void lcd_remote_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
682 | shift = y & 7; | 777 | shift = y & 7; |
683 | ny = height - 1 + shift + src_y; | 778 | ny = height - 1 + shift + src_y; |
684 | 779 | ||
685 | bfunc = lcd_remote_blockfuncs[drawmode]; | 780 | bfunc = lcd_remote_blockfuncs[current_vp->drawmode]; |
686 | mask = 0xFFu << (shift + src_y); | 781 | mask = 0xFFu << (shift + src_y); |
687 | /* not byte-doubled here because shift+src_y can be > 7 */ | 782 | /* not byte-doubled here because shift+src_y can be > 7 */ |
688 | mask_bottom = 0xFFu >> (~ny & 7); | 783 | mask_bottom = 0xFFu >> (~ny & 7); |
@@ -793,8 +888,8 @@ void lcd_remote_bitmap_part(const fb_remote_data *src, int src_x, int src_y, | |||
793 | unsigned mask, mask_bottom; | 888 | unsigned mask, mask_bottom; |
794 | 889 | ||
795 | /* nothing to draw? */ | 890 | /* nothing to draw? */ |
796 | if ((width <= 0) || (height <= 0) || (x >= LCD_REMOTE_WIDTH) | 891 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
797 | || (y >= LCD_REMOTE_HEIGHT) || (x + width <= 0) || (y + height <= 0)) | 892 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
798 | return; | 893 | return; |
799 | 894 | ||
800 | /* clipping */ | 895 | /* clipping */ |
@@ -810,10 +905,14 @@ void lcd_remote_bitmap_part(const fb_remote_data *src, int src_x, int src_y, | |||
810 | src_y -= y; | 905 | src_y -= y; |
811 | y = 0; | 906 | y = 0; |
812 | } | 907 | } |
813 | if (x + width > LCD_REMOTE_WIDTH) | 908 | if (x + width > current_vp->width) |
814 | width = LCD_REMOTE_WIDTH - x; | 909 | width = current_vp->width - x; |
815 | if (y + height > LCD_REMOTE_HEIGHT) | 910 | if (y + height > current_vp->height) |
816 | height = LCD_REMOTE_HEIGHT - y; | 911 | height = current_vp->height - y; |
912 | |||
913 | /* adjust for viewport */ | ||
914 | x += current_vp->x; | ||
915 | y += current_vp->y; | ||
817 | 916 | ||
818 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 917 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
819 | src_y &= 7; | 918 | src_y &= 7; |
@@ -917,11 +1016,11 @@ void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
917 | { | 1016 | { |
918 | unsigned short ch; | 1017 | unsigned short ch; |
919 | unsigned short *ucs; | 1018 | unsigned short *ucs; |
920 | struct font* pf = font_get(curfont); | 1019 | struct font* pf = font_get(current_vp->font); |
921 | 1020 | ||
922 | ucs = bidi_l2v(str, 1); | 1021 | ucs = bidi_l2v(str, 1); |
923 | 1022 | ||
924 | while ((ch = *ucs++) != 0 && x < LCD_REMOTE_WIDTH) | 1023 | while ((ch = *ucs++) != 0 && x < current_vp->width) |
925 | { | 1024 | { |
926 | int width; | 1025 | int width; |
927 | const unsigned char *bits; | 1026 | const unsigned char *bits; |
@@ -975,24 +1074,24 @@ void lcd_remote_puts_style_offset(int x, int y, const unsigned char *str, | |||
975 | int style, int offset) | 1074 | int style, int offset) |
976 | { | 1075 | { |
977 | int xpos,ypos,w,h,xrect; | 1076 | int xpos,ypos,w,h,xrect; |
978 | int lastmode = drawmode; | 1077 | int lastmode = current_vp->drawmode; |
979 | 1078 | ||
980 | /* make sure scrolling is turned off on the line we are updating */ | 1079 | /* make sure scrolling is turned off on the line we are updating */ |
981 | lcd_remote_scroll_info.lines &= ~(1 << y); | 1080 | lcd_remote_scroll_stop_line(current_vp, y); |
982 | 1081 | ||
983 | if(!str || !str[0]) | 1082 | if(!str || !str[0]) |
984 | return; | 1083 | return; |
985 | 1084 | ||
986 | lcd_remote_getstringsize(str, &w, &h); | 1085 | lcd_remote_getstringsize(str, &w, &h); |
987 | xpos = xmargin + x*w / utf8length((char *)str); | 1086 | xpos = current_vp->xmargin + x*w / utf8length((char *)str); |
988 | ypos = ymargin + y*h; | 1087 | ypos = current_vp->ymargin + y*h; |
989 | drawmode = (style & STYLE_INVERT) ? | 1088 | current_vp->drawmode = (style & STYLE_INVERT) ? |
990 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | 1089 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; |
991 | lcd_remote_putsxyofs(xpos, ypos, offset, str); | 1090 | lcd_remote_putsxyofs(xpos, ypos, offset, str); |
992 | drawmode ^= DRMODE_INVERSEVID; | 1091 | current_vp->drawmode ^= DRMODE_INVERSEVID; |
993 | xrect = xpos + MAX(w - offset, 0); | 1092 | xrect = xpos + MAX(w - offset, 0); |
994 | lcd_remote_fillrect(xrect, ypos, LCD_REMOTE_WIDTH - xrect, h); | 1093 | lcd_remote_fillrect(xrect, ypos, current_vp->width - xrect, h); |
995 | drawmode = lastmode; | 1094 | current_vp->drawmode = lastmode; |
996 | } | 1095 | } |
997 | 1096 | ||
998 | /*** scrolling ***/ | 1097 | /*** scrolling ***/ |
@@ -1017,9 +1116,15 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri | |||
1017 | struct scrollinfo* s; | 1116 | struct scrollinfo* s; |
1018 | int w, h; | 1117 | int w, h; |
1019 | 1118 | ||
1020 | if(y>=LCD_REMOTE_SCROLLABLE_LINES) return; | 1119 | if ((unsigned)y >= (unsigned)current_vp->height) |
1120 | return; | ||
1021 | 1121 | ||
1022 | s = &lcd_remote_scroll_info.scroll[y]; | 1122 | /* remove any previously scrolling line at the same location */ |
1123 | lcd_remote_scroll_stop_line(current_vp, y); | ||
1124 | |||
1125 | if (lcd_remote_scroll_info.lines >= LCD_REMOTE_SCROLLABLE_LINES) return; | ||
1126 | |||
1127 | s = &lcd_remote_scroll_info.scroll[lcd_remote_scroll_info.lines]; | ||
1023 | 1128 | ||
1024 | s->start_tick = current_tick + lcd_remote_scroll_info.delay; | 1129 | s->start_tick = current_tick + lcd_remote_scroll_info.delay; |
1025 | s->style = style; | 1130 | s->style = style; |
@@ -1031,7 +1136,7 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri | |||
1031 | 1136 | ||
1032 | lcd_remote_getstringsize(string, &w, &h); | 1137 | lcd_remote_getstringsize(string, &w, &h); |
1033 | 1138 | ||
1034 | if (LCD_REMOTE_WIDTH - x * 8 - xmargin < w) { | 1139 | if (current_vp->width - x * 8 - current_vp->xmargin < w) { |
1035 | /* prepare scroll line */ | 1140 | /* prepare scroll line */ |
1036 | char *end; | 1141 | char *end; |
1037 | 1142 | ||
@@ -1044,7 +1149,7 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri | |||
1044 | /* scroll bidirectional or forward only depending on the string | 1149 | /* scroll bidirectional or forward only depending on the string |
1045 | width */ | 1150 | width */ |
1046 | if ( lcd_remote_scroll_info.bidir_limit ) { | 1151 | if ( lcd_remote_scroll_info.bidir_limit ) { |
1047 | s->bidir = s->width < (LCD_REMOTE_WIDTH - xmargin) * | 1152 | s->bidir = s->width < (current_vp->width - current_vp->xmargin) * |
1048 | (100 + lcd_remote_scroll_info.bidir_limit) / 100; | 1153 | (100 + lcd_remote_scroll_info.bidir_limit) / 100; |
1049 | } | 1154 | } |
1050 | else | 1155 | else |
@@ -1057,17 +1162,17 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri | |||
1057 | } | 1162 | } |
1058 | 1163 | ||
1059 | end = strchr(s->line, '\0'); | 1164 | end = strchr(s->line, '\0'); |
1060 | strncpy(end, (char *)string, LCD_REMOTE_WIDTH/2); | 1165 | strncpy(end, (char *)string, current_vp->width/2); |
1061 | 1166 | ||
1167 | s->vp = current_vp; | ||
1168 | s->y = y; | ||
1062 | s->len = utf8length((char *)string); | 1169 | s->len = utf8length((char *)string); |
1063 | s->offset = offset; | 1170 | s->offset = offset; |
1064 | s->startx = xmargin + x * s->width / s->len;; | 1171 | s->startx = current_vp->xmargin + x * s->width / s->len; |
1065 | s->backward = false; | 1172 | s->backward = false; |
1066 | lcd_remote_scroll_info.lines |= (1<<y); | 1173 | |
1174 | lcd_remote_scroll_info.lines++; | ||
1067 | } | 1175 | } |
1068 | else | ||
1069 | /* force a bit switch-off since it doesn't scroll */ | ||
1070 | lcd_remote_scroll_info.lines &= ~(1<<y); | ||
1071 | } | 1176 | } |
1072 | 1177 | ||
1073 | void lcd_remote_scroll_fn(void) | 1178 | void lcd_remote_scroll_fn(void) |
@@ -1077,26 +1182,25 @@ void lcd_remote_scroll_fn(void) | |||
1077 | int index; | 1182 | int index; |
1078 | int xpos, ypos; | 1183 | int xpos, ypos; |
1079 | int lastmode; | 1184 | int lastmode; |
1185 | struct viewport* old_vp = current_vp; | ||
1080 | 1186 | ||
1081 | for ( index = 0; index < LCD_REMOTE_SCROLLABLE_LINES; index++ ) { | 1187 | for ( index = 0; index < lcd_remote_scroll_info.lines; index++ ) { |
1082 | /* really scroll? */ | ||
1083 | if ((lcd_remote_scroll_info.lines & (1 << index)) == 0) | ||
1084 | continue; | ||
1085 | |||
1086 | s = &lcd_remote_scroll_info.scroll[index]; | 1188 | s = &lcd_remote_scroll_info.scroll[index]; |
1087 | 1189 | ||
1088 | /* check pause */ | 1190 | /* check pause */ |
1089 | if (TIME_BEFORE(current_tick, s->start_tick)) | 1191 | if (TIME_BEFORE(current_tick, s->start_tick)) |
1090 | continue; | 1192 | continue; |
1091 | 1193 | ||
1194 | lcd_remote_set_viewport(s->vp); | ||
1195 | |||
1092 | if (s->backward) | 1196 | if (s->backward) |
1093 | s->offset -= lcd_remote_scroll_info.step; | 1197 | s->offset -= lcd_remote_scroll_info.step; |
1094 | else | 1198 | else |
1095 | s->offset += lcd_remote_scroll_info.step; | 1199 | s->offset += lcd_remote_scroll_info.step; |
1096 | 1200 | ||
1097 | pf = font_get(curfont); | 1201 | pf = font_get(current_vp->font); |
1098 | xpos = s->startx; | 1202 | xpos = s->startx; |
1099 | ypos = ymargin + index * pf->height; | 1203 | ypos = current_vp->ymargin + s->y * pf->height; |
1100 | 1204 | ||
1101 | if (s->bidir) { /* scroll bidirectional */ | 1205 | if (s->bidir) { /* scroll bidirectional */ |
1102 | if (s->offset <= 0) { | 1206 | if (s->offset <= 0) { |
@@ -1105,9 +1209,9 @@ void lcd_remote_scroll_fn(void) | |||
1105 | s->backward = false; | 1209 | s->backward = false; |
1106 | s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; | 1210 | s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; |
1107 | } | 1211 | } |
1108 | if (s->offset >= s->width - (LCD_REMOTE_WIDTH - xpos)) { | 1212 | if (s->offset >= s->width - (current_vp->width - xpos)) { |
1109 | /* at end of line */ | 1213 | /* at end of line */ |
1110 | s->offset = s->width - (LCD_REMOTE_WIDTH - xpos); | 1214 | s->offset = s->width - (current_vp->width - xpos); |
1111 | s->backward = true; | 1215 | s->backward = true; |
1112 | s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; | 1216 | s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; |
1113 | } | 1217 | } |
@@ -1118,18 +1222,24 @@ void lcd_remote_scroll_fn(void) | |||
1118 | s->offset %= s->width; | 1222 | s->offset %= s->width; |
1119 | } | 1223 | } |
1120 | 1224 | ||
1121 | lastmode = drawmode; | 1225 | lastmode = current_vp->drawmode; |
1122 | drawmode = (s->style&STYLE_INVERT) ? | 1226 | current_vp->drawmode = (s->style&STYLE_INVERT) ? |
1123 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | 1227 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; |
1124 | lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line); | 1228 | lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line); |
1125 | drawmode = lastmode; | 1229 | current_vp->drawmode = lastmode; |
1126 | lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height); | 1230 | lcd_remote_update_viewport_rect(xpos, ypos, |
1231 | current_vp->width - xpos, pf->height); | ||
1127 | } | 1232 | } |
1233 | |||
1234 | lcd_remote_set_viewport(old_vp); | ||
1128 | } | 1235 | } |
1129 | 1236 | ||
1130 | /* LCD init */ | 1237 | /* LCD init */ |
1131 | void lcd_remote_init(void) | 1238 | void lcd_remote_init(void) |
1132 | { | 1239 | { |
1240 | /* Initialise the viewport */ | ||
1241 | lcd_remote_set_viewport(NULL); | ||
1242 | |||
1133 | #ifndef SIMULATOR | 1243 | #ifndef SIMULATOR |
1134 | /* Call device specific init */ | 1244 | /* Call device specific init */ |
1135 | lcd_remote_init_device(); | 1245 | lcd_remote_init_device(); |
diff --git a/firmware/export/lcd-remote.h b/firmware/export/lcd-remote.h index 3be23747ea..34c40e52c1 100644 --- a/firmware/export/lcd-remote.h +++ b/firmware/export/lcd-remote.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "cpu.h" | 24 | #include "cpu.h" |
25 | #include "config.h" | 25 | #include "config.h" |
26 | #include "adc.h" | 26 | #include "adc.h" |
27 | #include "lcd.h" | ||
27 | 28 | ||
28 | #ifdef HAVE_REMOTE_LCD | 29 | #ifdef HAVE_REMOTE_LCD |
29 | 30 | ||
@@ -109,7 +110,9 @@ extern void lcd_remote_init(void); | |||
109 | extern int lcd_remote_default_contrast(void); | 110 | extern int lcd_remote_default_contrast(void); |
110 | extern void lcd_remote_set_contrast(int val); | 111 | extern void lcd_remote_set_contrast(int val); |
111 | 112 | ||
113 | extern void lcd_remote_set_viewport(struct viewport* vp); | ||
112 | extern void lcd_remote_clear_display(void); | 114 | extern void lcd_remote_clear_display(void); |
115 | extern void lcd_remote_clear_viewport(void); | ||
113 | extern void lcd_remote_puts(int x, int y, const unsigned char *str); | 116 | extern void lcd_remote_puts(int x, int y, const unsigned char *str); |
114 | extern void lcd_remote_puts_style(int x, int y, const unsigned char *str, | 117 | extern void lcd_remote_puts_style(int x, int y, const unsigned char *str, |
115 | int style); | 118 | int style); |
@@ -132,6 +135,8 @@ extern void lcd_remote_puts_scroll_style_offset(int x, int y, | |||
132 | 135 | ||
133 | extern void lcd_remote_update(void); | 136 | extern void lcd_remote_update(void); |
134 | extern void lcd_remote_update_rect(int x, int y, int width, int height); | 137 | extern void lcd_remote_update_rect(int x, int y, int width, int height); |
138 | extern void lcd_remote_update_viewport(void); | ||
139 | extern void lcd_remote_update_viewport_rect(int x, int y, int width, int height); | ||
135 | 140 | ||
136 | extern void lcd_remote_set_invert_display(bool yesno); | 141 | extern void lcd_remote_set_invert_display(bool yesno); |
137 | extern void lcd_remote_set_flip(bool yesno); | 142 | extern void lcd_remote_set_flip(bool yesno); |
@@ -141,6 +146,8 @@ extern int lcd_remote_get_drawmode(void); | |||
141 | extern void lcd_remote_setmargins(int xmargin, int ymargin); | 146 | extern void lcd_remote_setmargins(int xmargin, int ymargin); |
142 | extern int lcd_remote_getxmargin(void); | 147 | extern int lcd_remote_getxmargin(void); |
143 | extern int lcd_remote_getymargin(void); | 148 | extern int lcd_remote_getymargin(void); |
149 | extern int lcd_remote_getwidth(void); | ||
150 | extern int lcd_remote_getheight(void); | ||
144 | extern void lcd_remote_setfont(int font); | 151 | extern void lcd_remote_setfont(int font); |
145 | extern int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h); | 152 | extern int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h); |
146 | 153 | ||
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index 60d9efaf92..276dcdfedc 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h | |||
@@ -24,6 +24,28 @@ | |||
24 | #include "cpu.h" | 24 | #include "cpu.h" |
25 | #include "config.h" | 25 | #include "config.h" |
26 | 26 | ||
27 | struct viewport { | ||
28 | int x; | ||
29 | int y; | ||
30 | int width; | ||
31 | int height; | ||
32 | #ifdef HAVE_LCD_BITMAP | ||
33 | int font; | ||
34 | int drawmode; | ||
35 | #endif | ||
36 | int xmargin; /* During the transition only - to be removed */ | ||
37 | int ymargin; /* During the transition only - to be removed */ | ||
38 | #if LCD_DEPTH > 1 | ||
39 | unsigned fg_pattern; | ||
40 | unsigned bg_pattern; | ||
41 | #ifdef HAVE_LCD_COLOR | ||
42 | unsigned lss_pattern; | ||
43 | unsigned lse_pattern; | ||
44 | unsigned lst_pattern; | ||
45 | #endif | ||
46 | #endif | ||
47 | }; | ||
48 | |||
27 | #define STYLE_DEFAULT 0x00000000 | 49 | #define STYLE_DEFAULT 0x00000000 |
28 | #define STYLE_COLORED 0x10000000 | 50 | #define STYLE_COLORED 0x10000000 |
29 | #define STYLE_INVERT 0x20000000 | 51 | #define STYLE_INVERT 0x20000000 |
@@ -76,9 +98,14 @@ extern void lcd_set_contrast(int val); | |||
76 | extern void lcd_setmargins(int xmargin, int ymargin); | 98 | extern void lcd_setmargins(int xmargin, int ymargin); |
77 | extern int lcd_getxmargin(void); | 99 | extern int lcd_getxmargin(void); |
78 | extern int lcd_getymargin(void); | 100 | extern int lcd_getymargin(void); |
101 | extern int lcd_getwidth(void); | ||
102 | extern int lcd_getheight(void); | ||
79 | extern int lcd_getstringsize(const unsigned char *str, int *w, int *h); | 103 | extern int lcd_getstringsize(const unsigned char *str, int *w, int *h); |
80 | 104 | ||
105 | extern void lcd_set_viewport(struct viewport* vp); | ||
81 | extern void lcd_update(void); | 106 | extern void lcd_update(void); |
107 | extern void lcd_update_viewport(void); | ||
108 | extern void lcd_clear_viewport(void); | ||
82 | extern void lcd_clear_display(void); | 109 | extern void lcd_clear_display(void); |
83 | extern void lcd_putsxy(int x, int y, const unsigned char *string); | 110 | extern void lcd_putsxy(int x, int y, const unsigned char *string); |
84 | extern void lcd_puts(int x, int y, const unsigned char *string); | 111 | extern void lcd_puts(int x, int y, const unsigned char *string); |
@@ -119,6 +146,7 @@ extern void lcd_blit(const fb_data* data, int x, int by, int width, | |||
119 | 146 | ||
120 | /* update a fraction of the screen */ | 147 | /* update a fraction of the screen */ |
121 | extern void lcd_update_rect(int x, int y, int width, int height); | 148 | extern void lcd_update_rect(int x, int y, int width, int height); |
149 | extern void lcd_update_viewport_rect(int x, int y, int width, int height); | ||
122 | 150 | ||
123 | #ifdef HAVE_REMOTE_LCD | 151 | #ifdef HAVE_REMOTE_LCD |
124 | extern void lcd_remote_update(void); | 152 | extern void lcd_remote_update(void); |
diff --git a/firmware/export/scroll_engine.h b/firmware/export/scroll_engine.h index 5e39990129..48d5c5cb8c 100644 --- a/firmware/export/scroll_engine.h +++ b/firmware/export/scroll_engine.h | |||
@@ -23,9 +23,17 @@ | |||
23 | #ifndef __SCROLL_ENGINE_H__ | 23 | #ifndef __SCROLL_ENGINE_H__ |
24 | #define __SCROLL_ENGINE_H__ | 24 | #define __SCROLL_ENGINE_H__ |
25 | 25 | ||
26 | #include <lcd.h> | ||
27 | |||
26 | void scroll_init(void); | 28 | void scroll_init(void); |
29 | void lcd_scroll_stop(struct viewport* vp); | ||
30 | void lcd_scroll_stop_line(struct viewport* vp, int y); | ||
27 | void lcd_scroll_fn(void); | 31 | void lcd_scroll_fn(void); |
32 | #ifdef HAVE_REMOTE_LCD | ||
28 | void lcd_remote_scroll_fn(void); | 33 | void lcd_remote_scroll_fn(void); |
34 | void lcd_remote_scroll_stop(struct viewport* vp); | ||
35 | void lcd_remote_scroll_stop_line(struct viewport* vp, int y); | ||
36 | #endif | ||
29 | 37 | ||
30 | /* internal usage, but in multiple drivers */ | 38 | /* internal usage, but in multiple drivers */ |
31 | #define SCROLL_SPACING 3 | 39 | #define SCROLL_SPACING 3 |
@@ -37,8 +45,10 @@ void lcd_remote_scroll_fn(void); | |||
37 | 45 | ||
38 | struct scrollinfo | 46 | struct scrollinfo |
39 | { | 47 | { |
48 | struct viewport* vp; | ||
40 | char line[SCROLL_LINE_SIZE]; | 49 | char line[SCROLL_LINE_SIZE]; |
41 | int len; /* length of line in chars */ | 50 | int len; /* length of line in chars */ |
51 | int y; /* Position of the line on the screen (char co-ordinates) */ | ||
42 | int offset; | 52 | int offset; |
43 | int startx; | 53 | int startx; |
44 | #ifdef HAVE_LCD_BITMAP | 54 | #ifdef HAVE_LCD_BITMAP |
@@ -54,7 +64,7 @@ struct scroll_screen_info | |||
54 | { | 64 | { |
55 | struct scrollinfo * const scroll; | 65 | struct scrollinfo * const scroll; |
56 | const int num_scroll; /* number of scrollable lines (also number of scroll structs) */ | 66 | const int num_scroll; /* number of scrollable lines (also number of scroll structs) */ |
57 | int lines; /* Bitpattern of which lines are scrolling */ | 67 | int lines; /* Number of currently scrolling lines */ |
58 | long ticks; /* # of ticks between updates*/ | 68 | long ticks; /* # of ticks between updates*/ |
59 | long delay; /* ticks delay before start */ | 69 | long delay; /* ticks delay before start */ |
60 | int bidir_limit; /* percent */ | 70 | int bidir_limit; /* percent */ |
@@ -74,7 +84,7 @@ struct scroll_screen_info | |||
74 | #ifdef HAVE_LCD_BITMAP | 84 | #ifdef HAVE_LCD_BITMAP |
75 | #define LCD_SCROLLABLE_LINES ((LCD_HEIGHT+4)/5 < 32 ? (LCD_HEIGHT+4)/5 : 32) | 85 | #define LCD_SCROLLABLE_LINES ((LCD_HEIGHT+4)/5 < 32 ? (LCD_HEIGHT+4)/5 : 32) |
76 | #else | 86 | #else |
77 | #define LCD_SCROLLABLE_LINES LCD_HEIGHT | 87 | #define LCD_SCROLLABLE_LINES LCD_HEIGHT * 2 |
78 | #endif | 88 | #endif |
79 | 89 | ||
80 | extern struct scroll_screen_info lcd_scroll_info; | 90 | extern struct scroll_screen_info lcd_scroll_info; |
diff --git a/firmware/scroll_engine.c b/firmware/scroll_engine.c index 599e7f58b5..4783e9f1ef 100644 --- a/firmware/scroll_engine.c +++ b/firmware/scroll_engine.c | |||
@@ -82,6 +82,40 @@ void lcd_stop_scroll(void) | |||
82 | lcd_scroll_info.lines = 0; | 82 | lcd_scroll_info.lines = 0; |
83 | } | 83 | } |
84 | 84 | ||
85 | /* Stop scrolling line y in the specified viewport, or all lines if y < 0 */ | ||
86 | void lcd_scroll_stop_line(struct viewport* current_vp, int y) | ||
87 | { | ||
88 | int i = 0; | ||
89 | |||
90 | while (i < lcd_scroll_info.lines) | ||
91 | { | ||
92 | if ((lcd_scroll_info.scroll[i].vp == current_vp) && | ||
93 | ((y < 0) || (lcd_scroll_info.scroll[i].y == y))) | ||
94 | { | ||
95 | /* If i is not the last active line in the array, then move | ||
96 | the last item to position i */ | ||
97 | if ((i + 1) != lcd_scroll_info.lines) | ||
98 | { | ||
99 | lcd_scroll_info.scroll[i] = lcd_scroll_info.scroll[lcd_scroll_info.lines-1]; | ||
100 | } | ||
101 | lcd_scroll_info.lines--; | ||
102 | |||
103 | /* A line can only appear once, so we're done. */ | ||
104 | return ; | ||
105 | } | ||
106 | else | ||
107 | { | ||
108 | i++; | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | |||
113 | /* Stop all scrolling lines in the specified viewport */ | ||
114 | void lcd_scroll_stop(struct viewport* vp) | ||
115 | { | ||
116 | lcd_scroll_stop_line(vp, -1); | ||
117 | } | ||
118 | |||
85 | void lcd_scroll_speed(int speed) | 119 | void lcd_scroll_speed(int speed) |
86 | { | 120 | { |
87 | lcd_scroll_info.ticks = scroll_tick_table[speed]; | 121 | lcd_scroll_info.ticks = scroll_tick_table[speed]; |
@@ -122,6 +156,40 @@ void lcd_remote_stop_scroll(void) | |||
122 | lcd_remote_scroll_info.lines = 0; | 156 | lcd_remote_scroll_info.lines = 0; |
123 | } | 157 | } |
124 | 158 | ||
159 | /* Stop scrolling line y in the specified viewport, or all lines if y < 0 */ | ||
160 | void lcd_remote_scroll_stop_line(struct viewport* current_vp, int y) | ||
161 | { | ||
162 | int i = 0; | ||
163 | |||
164 | while (i < lcd_remote_scroll_info.lines) | ||
165 | { | ||
166 | if ((lcd_remote_scroll_info.scroll[i].vp == current_vp) && | ||
167 | ((y < 0) || (lcd_remote_scroll_info.scroll[i].y == y))) | ||
168 | { | ||
169 | /* If i is not the last active line in the array, then move | ||
170 | the last item to position i */ | ||
171 | if ((i + 1) != lcd_remote_scroll_info.lines) | ||
172 | { | ||
173 | lcd_remote_scroll_info.scroll[i] = lcd_remote_scroll_info.scroll[lcd_remote_scroll_info.lines-1]; | ||
174 | } | ||
175 | lcd_remote_scroll_info.lines--; | ||
176 | |||
177 | /* A line can only appear once, so we're done. */ | ||
178 | return ; | ||
179 | } | ||
180 | else | ||
181 | { | ||
182 | i++; | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | /* Stop all scrolling lines in the specified viewport */ | ||
188 | void lcd_remote_scroll_stop(struct viewport* vp) | ||
189 | { | ||
190 | lcd_remote_scroll_stop_line(vp, -1); | ||
191 | } | ||
192 | |||
125 | void lcd_remote_scroll_speed(int speed) | 193 | void lcd_remote_scroll_speed(int speed) |
126 | { | 194 | { |
127 | lcd_remote_scroll_info.ticks = scroll_tick_table[speed]; | 195 | lcd_remote_scroll_info.ticks = scroll_tick_table[speed]; |
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c index 91b2eae986..9b066d61d0 100644 --- a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c +++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c | |||
@@ -11,10 +11,9 @@ static volatile bool lcd_on = true; | |||
11 | volatile bool lcd_poweroff = false; | 11 | volatile bool lcd_poweroff = false; |
12 | static unsigned lcd_yuv_options = 0; | 12 | static unsigned lcd_yuv_options = 0; |
13 | /* | 13 | /* |
14 | ** These are imported from lcd-16bit.c | 14 | ** This is imported from lcd-16bit.c |
15 | */ | 15 | */ |
16 | extern unsigned fg_pattern; | 16 | extern struct viewport* current_vp; |
17 | extern unsigned bg_pattern; | ||
18 | 17 | ||
19 | /* Copies a rectangle from one framebuffer to another. Can be used in | 18 | /* Copies a rectangle from one framebuffer to another. Can be used in |
20 | single transfer mode with width = num pixels, and height = 1 which | 19 | single transfer mode with width = num pixels, and height = 1 which |
@@ -245,7 +244,7 @@ void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y, | |||
245 | [dstp]"r"(LCD_WIDTH - width), | 244 | [dstp]"r"(LCD_WIDTH - width), |
246 | [transcolor]"r"(TRANSPARENT_COLOR), | 245 | [transcolor]"r"(TRANSPARENT_COLOR), |
247 | [fgcolor]"r"(REPLACEWITHFG_COLOR), | 246 | [fgcolor]"r"(REPLACEWITHFG_COLOR), |
248 | [fgpat]"r"(fg_pattern) | 247 | [fgpat]"r"(current_vp->fg_pattern) |
249 | ); | 248 | ); |
250 | } | 249 | } |
251 | 250 | ||