diff options
Diffstat (limited to 'firmware/drivers/lcd-2bit-horz.c')
-rw-r--r-- | firmware/drivers/lcd-2bit-horz.c | 277 |
1 files changed, 192 insertions, 85 deletions
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 | } |