summaryrefslogtreecommitdiff
path: root/firmware/drivers/lcd-2bit-vert.c
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2008-01-07 20:34:11 +0000
committerDave Chapman <dave@dchapman.com>2008-01-07 20:34:11 +0000
commit945c8a221ade41c462a93f8452320a806e5645b3 (patch)
tree2a17823e286e6252e60c44c7f4753d5c18ef5172 /firmware/drivers/lcd-2bit-vert.c
parent2a8f39820b49f116820356c2ca224f82f2106c21 (diff)
downloadrockbox-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
Diffstat (limited to 'firmware/drivers/lcd-2bit-vert.c')
-rw-r--r--firmware/drivers/lcd-2bit-vert.c294
1 files changed, 203 insertions, 91 deletions
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 = {
48static fb_data* lcd_backdrop = NULL; 48static fb_data* lcd_backdrop = NULL;
49static long lcd_backdrop_offset IDATA_ATTR = 0; 49static long lcd_backdrop_offset IDATA_ATTR = 0;
50 50
51static unsigned fg_pattern IDATA_ATTR = 0xFF; /* initially black */ 51static struct viewport default_vp =
52static unsigned bg_pattern IDATA_ATTR = 0x00; /* initially white */ 52{
53static int drawmode = DRMODE_SOLID; 53 .x = 0,
54static int xmargin = 0; 54 .y = 0,
55static int ymargin = 0; 55 .width = LCD_WIDTH,
56static 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
65static struct viewport* current_vp IBSS_ATTR;
66static unsigned fg_pattern IBSS_ATTR;
67static unsigned bg_pattern IBSS_ATTR;
57 68
58/* LCD init */ 69/* LCD init */
59void lcd_init(void) 70void 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
83void 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
94void lcd_update_viewport(void)
95{
96 lcd_update_rect(current_vp->x, current_vp->y,
97 current_vp->width, current_vp->height);
98}
99
100void 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
69void lcd_set_drawmode(int mode) 108void 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
74int lcd_get_drawmode(void) 113int lcd_get_drawmode(void)
75{ 114{
76 return drawmode; 115 return current_vp->drawmode;
77} 116}
78 117
79void lcd_set_foreground(unsigned brightness) 118void 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
84unsigned lcd_get_foreground(void) 124unsigned lcd_get_foreground(void)
85{ 125{
86 return ~fg_pattern & 3; 126 return current_vp->fg_pattern;
87} 127}
88 128
89void lcd_set_background(unsigned brightness) 129void 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
94unsigned lcd_get_background(void) 135unsigned lcd_get_background(void)
95{ 136{
96 return ~bg_pattern & 3; 137 return current_vp->bg_pattern;
97} 138}
98 139
99void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) 140void 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
106void lcd_setmargins(int x, int y) 147void 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
112int lcd_getxmargin(void) 153int lcd_getxmargin(void)
113{ 154{
114 return xmargin; 155 return current_vp->xmargin;
115} 156}
116 157
117int lcd_getymargin(void) 158int lcd_getymargin(void)
118{ 159{
119 return ymargin; 160 return current_vp->ymargin;
161}
162
163int lcd_getwidth(void)
164{
165 return current_vp->width;
166}
167
168int lcd_getheight(void)
169{
170 return current_vp->height;
120} 171}
121 172
122void lcd_setfont(int newfont) 173void lcd_setfont(int newfont)
123{ 174{
124 curfont = newfont; 175 current_vp->font = newfont;
125} 176}
126 177
127int lcd_getstringsize(const unsigned char *str, int *w, int *h) 178int 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 */
348void lcd_clear_display(void) 399void 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 */
417void 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 */
366void lcd_drawpixel(int x, int y) 442void 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)
444void lcd_hline(int x1, int x2, int y) 522void 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
1073void lcd_scroll_fn(void) 1183void 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}