1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 by Dave Chapman
12 * Rockbox driver for 16-bit colour LCDs
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
34 #include "rbunicode.h"
36 #include "scroll_engine.h"
45 fb_data lcd_framebuffer
[LCD_FBHEIGHT
][LCD_FBWIDTH
] IRAM_LCDFRAMEBUFFER
__attribute__ ((aligned (16)));
48 static fb_data
* lcd_backdrop
= NULL
;
49 static long lcd_backdrop_offset IDATA_ATTR
= 0;
51 #if !defined(TOSHIBA_GIGABEAT_F) || defined(SIMULATOR)
52 static unsigned fg_pattern IDATA_ATTR
= LCD_DEFAULT_FG
;
53 static unsigned bg_pattern IDATA_ATTR
= LCD_DEFAULT_BG
;
54 static unsigned lss_pattern IDATA_ATTR
= LCD_DEFAULT_LS
;
55 static unsigned lse_pattern IDATA_ATTR
= LCD_DEFAULT_BG
;
56 static unsigned lst_pattern IDATA_ATTR
= LCD_DEFAULT_FG
;
58 unsigned fg_pattern IDATA_ATTR
= LCD_DEFAULT_FG
;
59 unsigned bg_pattern IDATA_ATTR
= LCD_DEFAULT_BG
;
60 unsigned lss_pattern IDATA_ATTR
= LCD_DEFAULT_LS
;
61 unsigned lse_pattern IDATA_ATTR
= LCD_DEFAULT_BG
;
62 unsigned lst_pattern IDATA_ATTR
= LCD_DEFAULT_FG
;
65 static int drawmode
= DRMODE_SOLID
;
66 static int xmargin
= 0;
67 static int ymargin
= 0;
68 static int curfont
= FONT_SYSFIXED
;
75 /* Call device specific init */
80 /*** parameter handling ***/
82 void lcd_set_drawmode(int mode
)
84 drawmode
= mode
& (DRMODE_SOLID
|DRMODE_INVERSEVID
);
87 int lcd_get_drawmode(void)
92 void lcd_set_foreground(unsigned color
)
97 unsigned lcd_get_foreground(void)
102 void lcd_set_background(unsigned color
)
107 unsigned lcd_get_background(void)
112 void lcd_set_selector_start(unsigned color
)
117 void lcd_set_selector_end(unsigned color
)
122 void lcd_set_selector_text(unsigned color
)
127 void lcd_set_drawinfo(int mode
, unsigned fg_color
, unsigned bg_color
)
129 lcd_set_drawmode(mode
);
130 fg_pattern
= fg_color
;
131 bg_pattern
= bg_color
;
134 void lcd_setmargins(int x
, int y
)
140 int lcd_getxmargin(void)
145 int lcd_getymargin(void)
150 void lcd_setfont(int newfont
)
155 int lcd_getstringsize(const unsigned char *str
, int *w
, int *h
)
157 return font_getstringsize(str
, w
, h
, curfont
);
160 /*** low-level drawing functions ***/
162 #define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)])
164 static void setpixel(fb_data
*address
) ICODE_ATTR
;
165 static void setpixel(fb_data
*address
)
167 *address
= fg_pattern
;
170 static void clearpixel(fb_data
*address
) ICODE_ATTR
;
171 static void clearpixel(fb_data
*address
)
173 *address
= bg_pattern
;
176 static void clearimgpixel(fb_data
*address
) ICODE_ATTR
;
177 static void clearimgpixel(fb_data
*address
)
179 *address
= *(fb_data
*)((long)address
+ lcd_backdrop_offset
);
182 static void flippixel(fb_data
*address
) ICODE_ATTR
;
183 static void flippixel(fb_data
*address
)
185 *address
= ~(*address
);
188 static void nopixel(fb_data
*address
) ICODE_ATTR
;
189 static void nopixel(fb_data
*address
)
194 lcd_fastpixelfunc_type
* const lcd_fastpixelfuncs_bgcolor
[8] = {
195 flippixel
, nopixel
, setpixel
, setpixel
,
196 nopixel
, clearpixel
, nopixel
, clearpixel
199 lcd_fastpixelfunc_type
* const lcd_fastpixelfuncs_backdrop
[8] = {
200 flippixel
, nopixel
, setpixel
, setpixel
,
201 nopixel
, clearimgpixel
, nopixel
, clearimgpixel
204 lcd_fastpixelfunc_type
* const * lcd_fastpixelfuncs
= lcd_fastpixelfuncs_bgcolor
;
206 void lcd_set_backdrop(fb_data
* backdrop
)
208 lcd_backdrop
= backdrop
;
211 lcd_backdrop_offset
= (long)backdrop
- (long)&lcd_framebuffer
[0][0];
212 lcd_fastpixelfuncs
= lcd_fastpixelfuncs_backdrop
;
216 lcd_backdrop_offset
= 0;
217 lcd_fastpixelfuncs
= lcd_fastpixelfuncs_bgcolor
;
221 fb_data
* lcd_get_backdrop(void)
226 /*** drawing functions ***/
228 /* Clear the whole display */
229 void lcd_clear_display(void)
231 fb_data
*dst
= LCDADDR(0, 0);
233 if (drawmode
& DRMODE_INVERSEVID
)
235 memset16(dst
, fg_pattern
, LCD_WIDTH
*LCD_HEIGHT
);
240 memset16(dst
, bg_pattern
, LCD_WIDTH
*LCD_HEIGHT
);
242 memcpy(dst
, lcd_backdrop
, sizeof(lcd_framebuffer
));
245 lcd_scroll_info
.lines
= 0;
248 /* Set a single pixel */
249 void lcd_drawpixel(int x
, int y
)
251 if (((unsigned)x
< LCD_WIDTH
) && ((unsigned)y
< LCD_HEIGHT
))
252 lcd_fastpixelfuncs
[drawmode
](LCDADDR(x
, y
));
256 void lcd_drawline(int x1
, int y1
, int x2
, int y2
)
264 lcd_fastpixelfunc_type
*pfunc
= lcd_fastpixelfuncs
[drawmode
];
266 deltax
= abs(x2
- x1
);
267 deltay
= abs(y2
- y1
);
271 if (deltax
>= deltay
)
274 d
= 2 * deltay
- deltax
;
276 dinc2
= (deltay
- deltax
) * 2;
283 d
= 2 * deltax
- deltay
;
285 dinc2
= (deltax
- deltay
) * 2;
289 numpixels
++; /* include endpoints */
306 for (i
= 0; i
< numpixels
; i
++)
308 if (((unsigned)x
< LCD_WIDTH
) && ((unsigned)y
< LCD_HEIGHT
))
309 pfunc(LCDADDR(x
, y
));
326 /* Draw a horizontal line (optimised) */
327 void lcd_hline(int x1
, int x2
, int y
)
331 enum fill_opt fillopt
= OPT_NONE
;
332 fb_data
*dst
, *dst_end
;
333 lcd_fastpixelfunc_type
*pfunc
= lcd_fastpixelfuncs
[drawmode
];
343 /* nothing to draw? */
344 if (((unsigned)y
>= LCD_HEIGHT
) || (x1
>= LCD_WIDTH
) || (x2
< 0))
353 if (drawmode
& DRMODE_INVERSEVID
)
355 if (drawmode
& DRMODE_BG
)
368 if (drawmode
& DRMODE_FG
)
374 dst
= LCDADDR(x1
, y
);
380 memset16(dst
, bits
, width
);
384 memcpy(dst
, (void *)((long)dst
+ lcd_backdrop_offset
),
385 width
* sizeof(fb_data
));
389 dst_end
= dst
+ width
;
392 while (dst
< dst_end
);
397 /* Draw a vertical line (optimised) */
398 void lcd_vline(int x
, int y1
, int y2
)
401 fb_data
*dst
, *dst_end
;
402 lcd_fastpixelfunc_type
*pfunc
= lcd_fastpixelfuncs
[drawmode
];
412 /* nothing to draw? */
413 if (((unsigned)x
>= LCD_WIDTH
) || (y1
>= LCD_HEIGHT
) || (y2
< 0))
419 if (y2
>= LCD_HEIGHT
)
422 dst
= LCDADDR(x
, y1
);
423 dst_end
= dst
+ (y2
- y1
) * LCD_WIDTH
;
430 while (dst
<= dst_end
);
433 /* Draw a rectangular box */
434 void lcd_drawrect(int x
, int y
, int width
, int height
)
436 if ((width
<= 0) || (height
<= 0))
439 int x2
= x
+ width
- 1;
440 int y2
= y
+ height
- 1;
443 lcd_vline(x2
, y
, y2
);
445 lcd_hline(x
, x2
, y2
);
448 /* Fill a rectangular area */
449 void lcd_fillrect(int x
, int y
, int width
, int height
)
452 enum fill_opt fillopt
= OPT_NONE
;
453 fb_data
*dst
, *dst_end
;
454 lcd_fastpixelfunc_type
*pfunc
= lcd_fastpixelfuncs
[drawmode
];
456 /* nothing to draw? */
457 if ((width
<= 0) || (height
<= 0) || (x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
458 || (x
+ width
<= 0) || (y
+ height
<= 0))
472 if (x
+ width
> LCD_WIDTH
)
473 width
= LCD_WIDTH
- x
;
474 if (y
+ height
> LCD_HEIGHT
)
475 height
= LCD_HEIGHT
- y
;
477 if (drawmode
& DRMODE_INVERSEVID
)
479 if (drawmode
& DRMODE_BG
)
492 if (drawmode
& DRMODE_FG
)
499 dst_end
= dst
+ height
* LCD_WIDTH
;
503 fb_data
*dst_row
, *row_end
;
508 memset16(dst
, bits
, width
);
512 memcpy(dst
, (void *)((long)dst
+ lcd_backdrop_offset
),
513 width
* sizeof(fb_data
));
518 row_end
= dst_row
+ width
;
521 while (dst_row
< row_end
);
526 while (dst
< dst_end
);
529 /* Fill a rectangle with a gradient */
530 void lcd_gradient_rect(int x1
, int x2
, int y
, int h
)
534 int h_r
= RGB_UNPACK_RED(lss_pattern
) << 16;
535 int h_b
= RGB_UNPACK_BLUE(lss_pattern
) << 16;
536 int h_g
= RGB_UNPACK_GREEN(lss_pattern
) << 16;
537 int rstep
= (h_r
- ((signed)RGB_UNPACK_RED(lse_pattern
) << 16)) / h
;
538 int gstep
= (h_g
- ((signed)RGB_UNPACK_GREEN(lse_pattern
) << 16)) / h
;
539 int bstep
= (h_b
- ((signed)RGB_UNPACK_BLUE(lse_pattern
) << 16)) / h
;
542 fg_pattern
= lss_pattern
;
543 for(count
= 0; count
< h
; count
++) {
544 lcd_hline(x1
, x2
, y
+ count
);
548 fg_pattern
= LCD_RGBPACK(h_r
>> 16, h_g
>> 16, h_b
>> 16);
552 /* About Rockbox' internal monochrome bitmap format:
554 * A bitmap contains one bit for every pixel that defines if that pixel is
555 * black (1) or white (0). Bits within a byte are arranged vertically, LSB
557 * The bytes are stored in row-major order, with byte 0 being top left,
558 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
559 * 0..7, the second row defines pixel row 8..15 etc.
561 * This is the mono bitmap format used on all other targets so far; the
562 * pixel packing doesn't really matter on a 8bit+ target. */
564 /* Draw a partial monochrome bitmap */
566 void lcd_mono_bitmap_part(const unsigned char *src
, int src_x
, int src_y
,
567 int stride
, int x
, int y
, int width
, int height
)
569 void lcd_mono_bitmap_part(const unsigned char *src
, int src_x
, int src_y
,
570 int stride
, int x
, int y
, int width
, int height
)
572 const unsigned char *src_end
;
574 fb_data
*dst
, *dst_end
, *backdrop
;
575 lcd_fastpixelfunc_type
*fgfunc
, *bgfunc
;
577 /* nothing to draw? */
578 if ((width
<= 0) || (height
<= 0) || (x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
579 || (x
+ width
<= 0) || (y
+ height
<= 0))
595 if (x
+ width
> LCD_WIDTH
)
596 width
= LCD_WIDTH
- x
;
597 if (y
+ height
> LCD_HEIGHT
)
598 height
= LCD_HEIGHT
- y
;
600 src
+= stride
* (src_y
>> 3) + src_x
; /* move starting point */
602 src_end
= src
+ width
;
605 has_backdrop
= (lcd_backdrop
!= NULL
);
606 backdrop
= lcd_backdrop
+ y
* LCD_WIDTH
+ x
;
607 fgfunc
= lcd_fastpixelfuncs
[drawmode
];
608 bgfunc
= lcd_fastpixelfuncs
[drawmode
^ DRMODE_INVERSEVID
];
611 const unsigned char *src_col
= src
++;
612 unsigned data
= *src_col
>> src_y
;
613 fb_data
*dst_col
= dst
++;
614 int numbits
= 8 - src_y
;
615 fb_data
*backdrop_col
= backdrop
++;
616 dst_end
= dst_col
+ height
* LCD_WIDTH
;
623 *dst_col
= fg_pattern
;
625 *dst_col
= has_backdrop
? *backdrop_col
: bg_pattern
;
629 *dst_col
= fg_pattern
;
631 case (DRMODE_SOLID
|DRMODE_INVERSEVID
):
633 *dst_col
= has_backdrop
? *backdrop_col
: bg_pattern
;
635 *dst_col
= fg_pattern
;
644 dst_col
+= LCD_WIDTH
;
645 backdrop_col
+= LCD_WIDTH
;
654 while (dst_col
< dst_end
);
656 while (src
< src_end
);
658 /* Draw a full monochrome bitmap */
659 void lcd_mono_bitmap(const unsigned char *src
, int x
, int y
, int width
, int height
)
661 lcd_mono_bitmap_part(src
, 0, 0, width
, x
, y
, width
, height
);
664 /* Draw a partial native bitmap */
665 void lcd_bitmap_part(const fb_data
*src
, int src_x
, int src_y
,
666 int stride
, int x
, int y
, int width
, int height
)
668 void lcd_bitmap_part(const fb_data
*src
, int src_x
, int src_y
,
669 int stride
, int x
, int y
, int width
, int height
)
671 fb_data
*dst
, *dst_end
;
673 /* nothing to draw? */
674 if ((width
<= 0) || (height
<= 0) || (x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
675 || (x
+ width
<= 0) || (y
+ height
<= 0))
691 if (x
+ width
> LCD_WIDTH
)
692 width
= LCD_WIDTH
- x
;
693 if (y
+ height
> LCD_HEIGHT
)
694 height
= LCD_HEIGHT
- y
;
696 src
+= stride
* src_y
+ src_x
; /* move starting point */
698 dst_end
= dst
+ height
* LCD_WIDTH
;
702 memcpy(dst
, src
, width
* sizeof(fb_data
));
706 while (dst
< dst_end
);
709 /* Draw a full native bitmap */
710 void lcd_bitmap(const fb_data
*src
, int x
, int y
, int width
, int height
)
712 lcd_bitmap_part(src
, 0, 0, width
, x
, y
, width
, height
);
715 #if !defined(TOSHIBA_GIGABEAT_F) && !defined(TOSHIBA_GIGABEAT_S) \
716 || defined(SIMULATOR)
717 /* Draw a partial native bitmap */
718 void lcd_bitmap_transparent_part(const fb_data
*src
, int src_x
, int src_y
,
719 int stride
, int x
, int y
, int width
,
720 int height
) ICODE_ATTR
;
721 void lcd_bitmap_transparent_part(const fb_data
*src
, int src_x
, int src_y
,
722 int stride
, int x
, int y
, int width
,
725 fb_data
*dst
, *dst_end
;
727 /* nothing to draw? */
728 if ((width
<= 0) || (height
<= 0) || (x
>= LCD_WIDTH
) || (y
>= LCD_HEIGHT
)
729 || (x
+ width
<= 0) || (y
+ height
<= 0))
745 if (x
+ width
> LCD_WIDTH
)
746 width
= LCD_WIDTH
- x
;
747 if (y
+ height
> LCD_HEIGHT
)
748 height
= LCD_HEIGHT
- y
;
750 src
+= stride
* src_y
+ src_x
; /* move starting point */
752 dst_end
= dst
+ height
* LCD_WIDTH
;
757 for(i
= 0;i
< width
;i
++)
759 if (src
[i
] == REPLACEWITHFG_COLOR
)
761 else if(src
[i
] != TRANSPARENT_COLOR
)
767 while (dst
< dst_end
);
769 #endif /* !defined(TOSHIBA_GIGABEAT_F) || defined(SIMULATOR) */
771 /* Draw a full native bitmap with a transparent color */
772 void lcd_bitmap_transparent(const fb_data
*src
, int x
, int y
,
773 int width
, int height
)
775 lcd_bitmap_transparent_part(src
, 0, 0, width
, x
, y
, width
, height
);
778 /* put a string at a given pixel position, skipping first ofs pixel columns */
779 static void lcd_putsxyofs(int x
, int y
, int ofs
, const unsigned char *str
)
783 struct font
* pf
= font_get(curfont
);
785 ucs
= bidi_l2v(str
, 1);
787 while ((ch
= *ucs
++) != 0 && x
< LCD_WIDTH
)
790 const unsigned char *bits
;
792 /* get proportional width and glyph bits */
793 width
= font_get_width(pf
,ch
);
801 bits
= font_get_bits(pf
, ch
);
803 lcd_mono_bitmap_part(bits
, ofs
, 0, width
, x
, y
, width
- ofs
, pf
->height
);
810 /* put a string at a given pixel position */
811 void lcd_putsxy(int x
, int y
, const unsigned char *str
)
813 lcd_putsxyofs(x
, y
, 0, str
);
816 /*** line oriented text output ***/
818 /* put a string at a given char position */
819 void lcd_puts(int x
, int y
, const unsigned char *str
)
821 lcd_puts_style_offset(x
, y
, str
, STYLE_DEFAULT
, 0);
824 void lcd_puts_style(int x
, int y
, const unsigned char *str
, int style
)
826 lcd_puts_style_offset(x
, y
, str
, style
, 0);
829 void lcd_puts_offset(int x
, int y
, const unsigned char *str
, int offset
)
831 lcd_puts_style_offset(x
, y
, str
, STYLE_DEFAULT
, offset
);
834 /* put a string at a given char position, style, and pixel position,
835 * skipping first offset pixel columns */
836 void lcd_puts_style_offset(int x
, int y
, const unsigned char *str
, int style
,
839 int xpos
,ypos
,w
,h
,xrect
;
840 int lastmode
= drawmode
;
841 int oldfgcolor
= fg_pattern
;
842 int oldbgcolor
= bg_pattern
;
844 /* make sure scrolling is turned off on the line we are updating */
845 lcd_scroll_info
.lines
&= ~(1 << y
);
850 lcd_getstringsize(str
, &w
, &h
);
851 xpos
= xmargin
+ x
*w
/ utf8length(str
);
852 ypos
= ymargin
+ y
*h
;
853 drawmode
= (style
& STYLE_INVERT
) ?
854 (DRMODE_SOLID
|DRMODE_INVERSEVID
) : DRMODE_SOLID
;
855 if (style
& STYLE_COLORED
) {
856 if (drawmode
== DRMODE_SOLID
)
857 fg_pattern
= style
& STYLE_COLOR_MASK
;
859 bg_pattern
= style
& STYLE_COLOR_MASK
;
861 drawmode
^= DRMODE_INVERSEVID
;
862 xrect
= xpos
+ MAX(w
- offset
, 0);
864 if (style
& STYLE_GRADIENT
) {
865 drawmode
= DRMODE_FG
;
866 lcd_gradient_rect(xpos
, LCD_WIDTH
, ypos
, h
*(style
& STYLE_COLOR_MASK
));
867 fg_pattern
= lst_pattern
;
869 else if (style
& STYLE_COLORBAR
) {
870 drawmode
= DRMODE_FG
;
871 fg_pattern
= lss_pattern
;
872 lcd_fillrect(xpos
, ypos
, LCD_WIDTH
- xpos
, h
);
873 fg_pattern
= lst_pattern
;
876 lcd_fillrect(xrect
, ypos
, LCD_WIDTH
- xrect
, h
);
877 drawmode
= (style
& STYLE_INVERT
) ?
878 (DRMODE_SOLID
|DRMODE_INVERSEVID
) : DRMODE_SOLID
;
880 lcd_putsxyofs(xpos
, ypos
, offset
, str
);
882 fg_pattern
= oldfgcolor
;
883 bg_pattern
= oldbgcolor
;
887 void lcd_puts_scroll(int x
, int y
, const unsigned char *string
)
889 lcd_puts_scroll_style(x
, y
, string
, STYLE_DEFAULT
);
892 void lcd_puts_scroll_style(int x
, int y
, const unsigned char *string
, int style
)
894 lcd_puts_scroll_style_offset(x
, y
, string
, style
, 0);
897 void lcd_puts_scroll_offset(int x
, int y
, const unsigned char *string
, int offset
)
899 lcd_puts_scroll_style_offset(x
, y
, string
, STYLE_DEFAULT
, offset
);
902 void lcd_puts_scroll_style_offset(int x
, int y
, const unsigned char *string
,
903 int style
, int offset
)
905 struct scrollinfo
* s
;
908 if(y
>=LCD_SCROLLABLE_LINES
) return;
910 s
= &lcd_scroll_info
.scroll
[y
];
912 s
->start_tick
= current_tick
+ lcd_scroll_info
.delay
;
914 lcd_puts_style_offset(x
,y
,string
,style
,offset
);
916 lcd_getstringsize(string
, &w
, &h
);
918 if (LCD_WIDTH
- x
* 8 - xmargin
< w
) {
919 /* prepare scroll line */
922 memset(s
->line
, 0, sizeof s
->line
);
923 strcpy(s
->line
, string
);
926 s
->width
= lcd_getstringsize(s
->line
, &w
, &h
);
928 /* scroll bidirectional or forward only depending on the string
930 if ( lcd_scroll_info
.bidir_limit
) {
931 s
->bidir
= s
->width
< (LCD_WIDTH
- xmargin
) *
932 (100 + lcd_scroll_info
.bidir_limit
) / 100;
937 if (!s
->bidir
) { /* add spaces if scrolling in the round */
938 strcat(s
->line
, " ");
939 /* get new width incl. spaces */
940 s
->width
= lcd_getstringsize(s
->line
, &w
, &h
);
943 end
= strchr(s
->line
, '\0');
944 strncpy(end
, string
, LCD_WIDTH
/2);
946 s
->len
= utf8length(string
);
948 s
->startx
= xmargin
+ x
* s
->width
/ s
->len
;
950 lcd_scroll_info
.lines
|= (1<<y
);
953 /* force a bit switch-off since it doesn't scroll */
954 lcd_scroll_info
.lines
&= ~(1<<y
);
957 void lcd_scroll_fn(void)
960 struct scrollinfo
* s
;
964 unsigned old_fgcolor
= fg_pattern
;
965 unsigned old_bgcolor
= bg_pattern
;
967 for ( index
= 0; index
< LCD_SCROLLABLE_LINES
; index
++ ) {
969 if ((lcd_scroll_info
.lines
& (1 << index
)) == 0)
972 s
= &lcd_scroll_info
.scroll
[index
];
975 if (TIME_BEFORE(current_tick
, s
->start_tick
))
978 if (s
->style
&STYLE_COLORED
) {
979 if (s
->style
&STYLE_MODE_MASK
) {
980 fg_pattern
= old_fgcolor
;
981 bg_pattern
= s
->style
&STYLE_COLOR_MASK
;
984 fg_pattern
= s
->style
&STYLE_COLOR_MASK
;
985 bg_pattern
= old_bgcolor
;
990 s
->offset
-= lcd_scroll_info
.step
;
992 s
->offset
+= lcd_scroll_info
.step
;
994 pf
= font_get(curfont
);
996 ypos
= ymargin
+ index
* pf
->height
;
998 if (s
->bidir
) { /* scroll bidirectional */
999 if (s
->offset
<= 0) {
1000 /* at beginning of line */
1002 s
->backward
= false;
1003 s
->start_tick
= current_tick
+ lcd_scroll_info
.delay
* 2;
1005 if (s
->offset
>= s
->width
- (LCD_WIDTH
- xpos
)) {
1006 /* at end of line */
1007 s
->offset
= s
->width
- (LCD_WIDTH
- xpos
);
1009 s
->start_tick
= current_tick
+ lcd_scroll_info
.delay
* 2;
1013 /* scroll forward the whole time */
1014 if (s
->offset
>= s
->width
)
1015 s
->offset
%= s
->width
;
1018 lastmode
= drawmode
;
1019 switch (s
->style
&STYLE_MODE_MASK
) {
1021 drawmode
= DRMODE_SOLID
|DRMODE_INVERSEVID
;
1023 case STYLE_COLORBAR
:
1024 /* Solid colour line selector */
1025 drawmode
= DRMODE_FG
;
1026 fg_pattern
= lss_pattern
;
1027 lcd_fillrect(xpos
, ypos
, LCD_WIDTH
- xpos
, pf
->height
);
1028 fg_pattern
= lst_pattern
;
1030 case STYLE_GRADIENT
:
1031 /* Gradient line selector */
1032 drawmode
= DRMODE_FG
;
1033 lcd_gradient_rect(xpos
, LCD_WIDTH
, ypos
, (signed)pf
->height
);
1034 fg_pattern
= lst_pattern
;
1037 drawmode
= DRMODE_SOLID
;
1040 lcd_putsxyofs(xpos
, ypos
, s
->offset
, s
->line
);
1041 drawmode
= lastmode
;
1042 lcd_update_rect(xpos
, ypos
, LCD_WIDTH
- xpos
, pf
->height
);
1045 fg_pattern
= old_fgcolor
;
1046 bg_pattern
= old_bgcolor
;