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 /firmware/drivers/lcd-2bit-vert.c | |
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
Diffstat (limited to 'firmware/drivers/lcd-2bit-vert.c')
-rw-r--r-- | firmware/drivers/lcd-2bit-vert.c | 294 |
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 = { | |||
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 | } |