diff options
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/lcd-16bit.c | 347 | ||||
-rw-r--r-- | firmware/drivers/lcd-1bit-vert.c | 224 | ||||
-rw-r--r-- | firmware/drivers/lcd-2bit-horz.c | 221 | ||||
-rw-r--r-- | firmware/drivers/lcd-2bit-vert.c | 226 | ||||
-rw-r--r-- | firmware/drivers/lcd-2bit-vi.c | 225 | ||||
-rw-r--r-- | firmware/drivers/lcd-bitmap-common.c | 329 |
6 files changed, 336 insertions, 1236 deletions
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index 882bfa0854..7238d7a923 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c | |||
@@ -638,70 +638,6 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
638 | while (dst < dst_end); | 638 | while (dst < dst_end); |
639 | } | 639 | } |
640 | 640 | ||
641 | /* Fill a rectangle with a gradient */ | ||
642 | static void lcd_gradient_rect(int x1, int x2, int y, int h) | ||
643 | { | ||
644 | int old_pattern = current_vp->fg_pattern; | ||
645 | |||
646 | if (h == 0) return; | ||
647 | |||
648 | int h_r = RGB_UNPACK_RED(current_vp->lss_pattern) << 16; | ||
649 | int h_b = RGB_UNPACK_BLUE(current_vp->lss_pattern) << 16; | ||
650 | int h_g = RGB_UNPACK_GREEN(current_vp->lss_pattern) << 16; | ||
651 | int rstep = (h_r - ((signed)RGB_UNPACK_RED(current_vp->lse_pattern) << 16)) / h; | ||
652 | int gstep = (h_g - ((signed)RGB_UNPACK_GREEN(current_vp->lse_pattern) << 16)) / h; | ||
653 | int bstep = (h_b - ((signed)RGB_UNPACK_BLUE(current_vp->lse_pattern) << 16)) / h; | ||
654 | int count; | ||
655 | |||
656 | current_vp->fg_pattern = current_vp->lss_pattern; | ||
657 | for(count = 0; count < h; count++) { | ||
658 | lcd_hline(x1, x2, y + count); | ||
659 | h_r -= rstep; | ||
660 | h_g -= gstep; | ||
661 | h_b -= bstep; | ||
662 | current_vp->fg_pattern = LCD_RGBPACK(h_r >> 16, h_g >> 16, h_b >> 16); | ||
663 | } | ||
664 | |||
665 | current_vp->fg_pattern = old_pattern; | ||
666 | } | ||
667 | |||
668 | #define H_COLOR(lss, lse, cur_line, max_line) \ | ||
669 | (((lse) - (lss)) * (cur_line) / (max_line) + (lss)) | ||
670 | |||
671 | /* Fill a rectangle with a gradient for scrolling line. To draw a gradient that | ||
672 | covers several lines, we need to know how many lines will be covered | ||
673 | (the num_lines arg), and which one is the current line within the selection | ||
674 | (the cur_line arg). */ | ||
675 | static void lcd_gradient_rect_scroll(int x1, int x2, int y, int h, | ||
676 | unsigned char num_lines, unsigned char cur_line) | ||
677 | { | ||
678 | if (h == 0 || num_lines == 0) return; | ||
679 | |||
680 | unsigned tmp_lss = current_vp->lss_pattern; | ||
681 | unsigned tmp_lse = current_vp->lse_pattern; | ||
682 | int lss_r = (signed)RGB_UNPACK_RED(current_vp->lss_pattern); | ||
683 | int lss_b = (signed)RGB_UNPACK_BLUE(current_vp->lss_pattern); | ||
684 | int lss_g = (signed)RGB_UNPACK_GREEN(current_vp->lss_pattern); | ||
685 | int lse_r = (signed)RGB_UNPACK_RED(current_vp->lse_pattern); | ||
686 | int lse_b = (signed)RGB_UNPACK_BLUE(current_vp->lse_pattern); | ||
687 | int lse_g = (signed)RGB_UNPACK_GREEN(current_vp->lse_pattern); | ||
688 | |||
689 | int h_r = H_COLOR(lss_r, lse_r, cur_line, num_lines); | ||
690 | int h_g = H_COLOR(lss_g, lse_g, cur_line, num_lines); | ||
691 | int h_b = H_COLOR(lss_b, lse_b, cur_line, num_lines); | ||
692 | lcd_set_selector_start(LCD_RGBPACK(h_r, h_g, h_b)); | ||
693 | |||
694 | int l_r = H_COLOR(lss_r, lse_r, cur_line+1, num_lines); | ||
695 | int l_g = H_COLOR(lss_g, lse_g, cur_line+1, num_lines); | ||
696 | int l_b = H_COLOR(lss_b, lse_b, cur_line+1, num_lines); | ||
697 | lcd_set_selector_end(LCD_RGBPACK(l_r, l_g, l_b)); | ||
698 | |||
699 | lcd_gradient_rect(x1, x2, y, h); | ||
700 | |||
701 | current_vp->lss_pattern = tmp_lss; | ||
702 | current_vp->lse_pattern = tmp_lse; | ||
703 | } | ||
704 | |||
705 | /* About Rockbox' internal monochrome bitmap format: | 641 | /* About Rockbox' internal monochrome bitmap format: |
706 | * | 642 | * |
707 | * A bitmap contains one bit for every pixel that defines if that pixel is | 643 | * A bitmap contains one bit for every pixel that defines if that pixel is |
@@ -977,285 +913,4 @@ void lcd_bitmap_transparent(const fb_data *src, int x, int y, | |||
977 | lcd_bitmap_transparent_part(src, 0, 0, width, x, y, width, height); | 913 | lcd_bitmap_transparent_part(src, 0, 0, width, x, y, width, height); |
978 | } | 914 | } |
979 | 915 | ||
980 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | 916 | #include "lcd-bitmap-common.c" |
981 | static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | ||
982 | { | ||
983 | unsigned short ch; | ||
984 | unsigned short *ucs; | ||
985 | struct font* pf = font_get(current_vp->font); | ||
986 | |||
987 | ucs = bidi_l2v(str, 1); | ||
988 | |||
989 | while ((ch = *ucs++) != 0 && x < current_vp->width) | ||
990 | { | ||
991 | int width; | ||
992 | const unsigned char *bits; | ||
993 | |||
994 | /* get proportional width and glyph bits */ | ||
995 | width = font_get_width(pf,ch); | ||
996 | |||
997 | if (ofs > width) | ||
998 | { | ||
999 | ofs -= width; | ||
1000 | continue; | ||
1001 | } | ||
1002 | |||
1003 | bits = font_get_bits(pf, ch); | ||
1004 | |||
1005 | lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); | ||
1006 | |||
1007 | x += width - ofs; | ||
1008 | ofs = 0; | ||
1009 | } | ||
1010 | } | ||
1011 | |||
1012 | /* put a string at a given pixel position */ | ||
1013 | void lcd_putsxy(int x, int y, const unsigned char *str) | ||
1014 | { | ||
1015 | lcd_putsxyofs(x, y, 0, str); | ||
1016 | } | ||
1017 | |||
1018 | /*** line oriented text output ***/ | ||
1019 | |||
1020 | /* put a string at a given char position */ | ||
1021 | void lcd_puts(int x, int y, const unsigned char *str) | ||
1022 | { | ||
1023 | lcd_puts_style_offset(x, y, str, STYLE_DEFAULT, 0); | ||
1024 | } | ||
1025 | |||
1026 | void lcd_puts_style(int x, int y, const unsigned char *str, int style) | ||
1027 | { | ||
1028 | lcd_puts_style_offset(x, y, str, style, 0); | ||
1029 | } | ||
1030 | |||
1031 | void lcd_puts_offset(int x, int y, const unsigned char *str, int offset) | ||
1032 | { | ||
1033 | lcd_puts_style_offset(x, y, str, STYLE_DEFAULT, offset); | ||
1034 | } | ||
1035 | |||
1036 | /* put a string at a given char position, style, and pixel position, | ||
1037 | * skipping first offset pixel columns */ | ||
1038 | void lcd_puts_style_offset(int x, int y, const unsigned char *str, int style, | ||
1039 | int offset) | ||
1040 | { | ||
1041 | int xpos,ypos,w,h,xrect; | ||
1042 | int lastmode = current_vp->drawmode; | ||
1043 | int oldfgcolor = current_vp->fg_pattern; | ||
1044 | int oldbgcolor = current_vp->bg_pattern; | ||
1045 | |||
1046 | /* make sure scrolling is turned off on the line we are updating */ | ||
1047 | lcd_scroll_stop_line(current_vp, y); | ||
1048 | |||
1049 | if(!str || !str[0]) | ||
1050 | return; | ||
1051 | |||
1052 | lcd_getstringsize(str, &w, &h); | ||
1053 | xpos = x*w / utf8length(str); | ||
1054 | ypos = y*h; | ||
1055 | current_vp->drawmode = (style & STYLE_INVERT) ? | ||
1056 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | ||
1057 | if (style & STYLE_COLORED) { | ||
1058 | if (current_vp->drawmode == DRMODE_SOLID) | ||
1059 | current_vp->fg_pattern = style & STYLE_COLOR_MASK; | ||
1060 | else | ||
1061 | current_vp->bg_pattern = style & STYLE_COLOR_MASK; | ||
1062 | } | ||
1063 | current_vp->drawmode ^= DRMODE_INVERSEVID; | ||
1064 | xrect = xpos + MAX(w - offset, 0); | ||
1065 | |||
1066 | if (style & STYLE_GRADIENT) { | ||
1067 | current_vp->drawmode = DRMODE_FG; | ||
1068 | if (CURLN_UNPACK(style) == 0) | ||
1069 | lcd_gradient_rect(xpos, current_vp->width, ypos, h*NUMLN_UNPACK(style)); | ||
1070 | current_vp->fg_pattern = current_vp->lst_pattern; | ||
1071 | } | ||
1072 | else if (style & STYLE_COLORBAR) { | ||
1073 | current_vp->drawmode = DRMODE_FG; | ||
1074 | current_vp->fg_pattern = current_vp->lss_pattern; | ||
1075 | lcd_fillrect(xpos, ypos, current_vp->width - xpos, h); | ||
1076 | current_vp->fg_pattern = current_vp->lst_pattern; | ||
1077 | } | ||
1078 | else { | ||
1079 | lcd_fillrect(xrect, ypos, current_vp->width - xrect, h); | ||
1080 | current_vp->drawmode = (style & STYLE_INVERT) ? | ||
1081 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | ||
1082 | } | ||
1083 | lcd_putsxyofs(xpos, ypos, offset, str); | ||
1084 | current_vp->drawmode = lastmode; | ||
1085 | current_vp->fg_pattern = oldfgcolor; | ||
1086 | current_vp->bg_pattern = oldbgcolor; | ||
1087 | } | ||
1088 | |||
1089 | /*** scrolling ***/ | ||
1090 | void lcd_puts_scroll(int x, int y, const unsigned char *string) | ||
1091 | { | ||
1092 | lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT); | ||
1093 | } | ||
1094 | |||
1095 | void lcd_puts_scroll_style(int x, int y, const unsigned char *string, int style) | ||
1096 | { | ||
1097 | lcd_puts_scroll_style_offset(x, y, string, style, 0); | ||
1098 | } | ||
1099 | |||
1100 | void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, int offset) | ||
1101 | { | ||
1102 | lcd_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset); | ||
1103 | } | ||
1104 | |||
1105 | /* Initialise a scrolling line at (x,y) in current viewport */ | ||
1106 | |||
1107 | void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | ||
1108 | int style, int offset) | ||
1109 | { | ||
1110 | struct scrollinfo* s; | ||
1111 | int w, h; | ||
1112 | |||
1113 | if ((unsigned)y >= (unsigned)current_vp->height) | ||
1114 | return; | ||
1115 | |||
1116 | /* remove any previously scrolling line at the same location */ | ||
1117 | lcd_scroll_stop_line(current_vp, y); | ||
1118 | |||
1119 | if (lcd_scroll_info.lines >= LCD_SCROLLABLE_LINES) return; | ||
1120 | |||
1121 | s = &lcd_scroll_info.scroll[lcd_scroll_info.lines]; | ||
1122 | |||
1123 | s->start_tick = current_tick + lcd_scroll_info.delay; | ||
1124 | s->style = style; | ||
1125 | lcd_puts_style_offset(x,y,string,style,offset); | ||
1126 | |||
1127 | lcd_getstringsize(string, &w, &h); | ||
1128 | |||
1129 | if (current_vp->width - x * 8 < w) { | ||
1130 | /* prepare scroll line */ | ||
1131 | char *end; | ||
1132 | |||
1133 | memset(s->line, 0, sizeof s->line); | ||
1134 | strcpy(s->line, string); | ||
1135 | |||
1136 | /* get width */ | ||
1137 | s->width = lcd_getstringsize(s->line, &w, &h); | ||
1138 | |||
1139 | /* scroll bidirectional or forward only depending on the string | ||
1140 | width */ | ||
1141 | if ( lcd_scroll_info.bidir_limit ) { | ||
1142 | s->bidir = s->width < (current_vp->width) * | ||
1143 | (100 + lcd_scroll_info.bidir_limit) / 100; | ||
1144 | } | ||
1145 | else | ||
1146 | s->bidir = false; | ||
1147 | |||
1148 | if (!s->bidir) { /* add spaces if scrolling in the round */ | ||
1149 | strcat(s->line, " "); | ||
1150 | /* get new width incl. spaces */ | ||
1151 | s->width = lcd_getstringsize(s->line, &w, &h); | ||
1152 | } | ||
1153 | |||
1154 | end = strchr(s->line, '\0'); | ||
1155 | strlcpy(end, string, current_vp->width/2); | ||
1156 | |||
1157 | s->vp = current_vp; | ||
1158 | s->y = y; | ||
1159 | s->len = utf8length(string); | ||
1160 | s->offset = offset; | ||
1161 | s->startx = x * s->width / s->len; | ||
1162 | s->backward = false; | ||
1163 | lcd_scroll_info.lines++; | ||
1164 | } | ||
1165 | } | ||
1166 | |||
1167 | void lcd_scroll_fn(void) | ||
1168 | { | ||
1169 | struct font* pf; | ||
1170 | struct scrollinfo* s; | ||
1171 | int index; | ||
1172 | int xpos, ypos; | ||
1173 | int lastmode; | ||
1174 | unsigned old_fgcolor; | ||
1175 | unsigned old_bgcolor; | ||
1176 | struct viewport* old_vp = current_vp; | ||
1177 | |||
1178 | for ( index = 0; index < lcd_scroll_info.lines; index++ ) { | ||
1179 | s = &lcd_scroll_info.scroll[index]; | ||
1180 | |||
1181 | /* check pause */ | ||
1182 | if (TIME_BEFORE(current_tick, s->start_tick)) | ||
1183 | continue; | ||
1184 | |||
1185 | lcd_set_viewport(s->vp); | ||
1186 | old_fgcolor = current_vp->fg_pattern; | ||
1187 | old_bgcolor = current_vp->bg_pattern; | ||
1188 | |||
1189 | if (s->style&STYLE_COLORED) { | ||
1190 | if (s->style&STYLE_MODE_MASK) { | ||
1191 | current_vp->fg_pattern = old_fgcolor; | ||
1192 | current_vp->bg_pattern = s->style&STYLE_COLOR_MASK; | ||
1193 | } | ||
1194 | else { | ||
1195 | current_vp->fg_pattern = s->style&STYLE_COLOR_MASK; | ||
1196 | current_vp->bg_pattern = old_bgcolor; | ||
1197 | } | ||
1198 | } | ||
1199 | |||
1200 | if (s->backward) | ||
1201 | s->offset -= lcd_scroll_info.step; | ||
1202 | else | ||
1203 | s->offset += lcd_scroll_info.step; | ||
1204 | |||
1205 | pf = font_get(current_vp->font); | ||
1206 | xpos = s->startx; | ||
1207 | ypos = s->y * pf->height; | ||
1208 | |||
1209 | if (s->bidir) { /* scroll bidirectional */ | ||
1210 | if (s->offset <= 0) { | ||
1211 | /* at beginning of line */ | ||
1212 | s->offset = 0; | ||
1213 | s->backward = false; | ||
1214 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | ||
1215 | } | ||
1216 | if (s->offset >= s->width - (current_vp->width - xpos)) { | ||
1217 | /* at end of line */ | ||
1218 | s->offset = s->width - (current_vp->width - xpos); | ||
1219 | s->backward = true; | ||
1220 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | ||
1221 | } | ||
1222 | } | ||
1223 | else { | ||
1224 | /* scroll forward the whole time */ | ||
1225 | if (s->offset >= s->width) | ||
1226 | s->offset %= s->width; | ||
1227 | } | ||
1228 | |||
1229 | lastmode = current_vp->drawmode; | ||
1230 | switch (s->style&STYLE_MODE_MASK) { | ||
1231 | case STYLE_INVERT: | ||
1232 | current_vp->drawmode = DRMODE_SOLID|DRMODE_INVERSEVID; | ||
1233 | break; | ||
1234 | case STYLE_COLORBAR: | ||
1235 | /* Solid colour line selector */ | ||
1236 | current_vp->drawmode = DRMODE_FG; | ||
1237 | current_vp->fg_pattern = current_vp->lss_pattern; | ||
1238 | lcd_fillrect(xpos, ypos, current_vp->width - xpos, pf->height); | ||
1239 | current_vp->fg_pattern = current_vp->lst_pattern; | ||
1240 | break; | ||
1241 | case STYLE_GRADIENT: | ||
1242 | /* Gradient line selector */ | ||
1243 | current_vp->drawmode = DRMODE_FG; | ||
1244 | lcd_gradient_rect_scroll(xpos, current_vp->width, ypos, (signed)pf->height, | ||
1245 | NUMLN_UNPACK(s->style), | ||
1246 | CURLN_UNPACK(s->style)); | ||
1247 | current_vp->fg_pattern = current_vp->lst_pattern; | ||
1248 | break; | ||
1249 | default: | ||
1250 | current_vp->drawmode = DRMODE_SOLID; | ||
1251 | break; | ||
1252 | } | ||
1253 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); | ||
1254 | current_vp->drawmode = lastmode; | ||
1255 | current_vp->fg_pattern = old_fgcolor; | ||
1256 | current_vp->bg_pattern = old_bgcolor; | ||
1257 | lcd_update_viewport_rect(xpos, ypos, current_vp->width - xpos, pf->height); | ||
1258 | } | ||
1259 | |||
1260 | lcd_set_viewport(old_vp); | ||
1261 | } | ||
diff --git a/firmware/drivers/lcd-1bit-vert.c b/firmware/drivers/lcd-1bit-vert.c index f11fd6fdf9..db8cc6771b 100644 --- a/firmware/drivers/lcd-1bit-vert.c +++ b/firmware/drivers/lcd-1bit-vert.c | |||
@@ -692,226 +692,4 @@ void LCDFN(bitmap)(const unsigned char *src, int x, int y, int width, | |||
692 | LCDFN(bitmap_part)(src, 0, 0, width, x, y, width, height); | 692 | LCDFN(bitmap_part)(src, 0, 0, width, x, y, width, height); |
693 | } | 693 | } |
694 | 694 | ||
695 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | 695 | #include "lcd-bitmap-common.c" |
696 | static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) | ||
697 | { | ||
698 | unsigned short ch; | ||
699 | unsigned short *ucs; | ||
700 | struct font* pf = font_get(current_vp->font); | ||
701 | |||
702 | ucs = bidi_l2v(str, 1); | ||
703 | |||
704 | while ((ch = *ucs++) != 0 && x < current_vp->width) | ||
705 | { | ||
706 | int width; | ||
707 | const unsigned char *bits; | ||
708 | |||
709 | /* get proportional width and glyph bits */ | ||
710 | width = font_get_width(pf, ch); | ||
711 | |||
712 | if (ofs > width) | ||
713 | { | ||
714 | ofs -= width; | ||
715 | continue; | ||
716 | } | ||
717 | |||
718 | bits = font_get_bits(pf, ch); | ||
719 | |||
720 | LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x, y, width - ofs, | ||
721 | pf->height); | ||
722 | |||
723 | x += width - ofs; | ||
724 | ofs = 0; | ||
725 | } | ||
726 | } | ||
727 | /* put a string at a given pixel position */ | ||
728 | void LCDFN(putsxy)(int x, int y, const unsigned char *str) | ||
729 | { | ||
730 | LCDFN(putsxyofs)(x, y, 0, str); | ||
731 | } | ||
732 | |||
733 | /*** Line oriented text output ***/ | ||
734 | |||
735 | /* put a string at a given char position */ | ||
736 | void LCDFN(puts)(int x, int y, const unsigned char *str) | ||
737 | { | ||
738 | LCDFN(puts_style_offset)(x, y, str, STYLE_DEFAULT, 0); | ||
739 | } | ||
740 | |||
741 | void LCDFN(puts_style)(int x, int y, const unsigned char *str, int style) | ||
742 | { | ||
743 | LCDFN(puts_style_offset)(x, y, str, style, 0); | ||
744 | } | ||
745 | |||
746 | void LCDFN(puts_offset)(int x, int y, const unsigned char *str, int offset) | ||
747 | { | ||
748 | LCDFN(puts_style_offset)(x, y, str, STYLE_DEFAULT, offset); | ||
749 | } | ||
750 | |||
751 | /* put a string at a given char position, style, and pixel position, | ||
752 | * skipping first offset pixel columns */ | ||
753 | void LCDFN(puts_style_offset)(int x, int y, const unsigned char *str, | ||
754 | int style, int offset) | ||
755 | { | ||
756 | int xpos,ypos,w,h,xrect; | ||
757 | int lastmode = current_vp->drawmode; | ||
758 | |||
759 | /* make sure scrolling is turned off on the line we are updating */ | ||
760 | LCDFN(scroll_stop_line)(current_vp, y); | ||
761 | |||
762 | if(!str || !str[0]) | ||
763 | return; | ||
764 | |||
765 | LCDFN(getstringsize)(str, &w, &h); | ||
766 | xpos = x*w / utf8length(str); | ||
767 | ypos = y*h; | ||
768 | current_vp->drawmode = (style & STYLE_INVERT) ? | ||
769 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | ||
770 | LCDFN(putsxyofs)(xpos, ypos, offset, str); | ||
771 | current_vp->drawmode ^= DRMODE_INVERSEVID; | ||
772 | xrect = xpos + MAX(w - offset, 0); | ||
773 | LCDFN(fillrect)(xrect, ypos, current_vp->width - xrect, h); | ||
774 | current_vp->drawmode = lastmode; | ||
775 | } | ||
776 | |||
777 | /*** scrolling ***/ | ||
778 | |||
779 | void LCDFN(puts_scroll)(int x, int y, const unsigned char *string) | ||
780 | { | ||
781 | LCDFN(puts_scroll_style)(x, y, string, STYLE_DEFAULT); | ||
782 | } | ||
783 | |||
784 | void LCDFN(puts_scroll_style)(int x, int y, const unsigned char *string, | ||
785 | int style) | ||
786 | { | ||
787 | LCDFN(puts_scroll_style_offset)(x, y, string, style, 0); | ||
788 | } | ||
789 | |||
790 | void LCDFN(puts_scroll_offset)(int x, int y, const unsigned char *string, | ||
791 | int offset) | ||
792 | { | ||
793 | LCDFN(puts_scroll_style_offset)(x, y, string, STYLE_DEFAULT, offset); | ||
794 | } | ||
795 | |||
796 | void LCDFN(puts_scroll_style_offset)(int x, int y, const unsigned char *string, | ||
797 | int style, int offset) | ||
798 | { | ||
799 | struct scrollinfo* s; | ||
800 | int w, h; | ||
801 | |||
802 | if ((unsigned)y >= (unsigned)current_vp->height) | ||
803 | return; | ||
804 | |||
805 | /* remove any previously scrolling line at the same location */ | ||
806 | LCDFN(scroll_stop_line)(current_vp, y); | ||
807 | |||
808 | if (LCDFN(scroll_info.lines) >= LCDM(SCROLLABLE_LINES)) return; | ||
809 | |||
810 | s = &LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines]; | ||
811 | |||
812 | s->start_tick = current_tick + LCDFN(scroll_info).delay; | ||
813 | s->style = style; | ||
814 | if (style & STYLE_INVERT) { | ||
815 | LCDFN(puts_style_offset)(x,y,string,STYLE_INVERT,offset); | ||
816 | } | ||
817 | else | ||
818 | LCDFN(puts_offset)(x,y,string,offset); | ||
819 | |||
820 | LCDFN(getstringsize)(string, &w, &h); | ||
821 | |||
822 | if (current_vp->width - x * 8 < w) { | ||
823 | /* prepare scroll line */ | ||
824 | char *end; | ||
825 | |||
826 | memset(s->line, 0, sizeof s->line); | ||
827 | strcpy(s->line, string); | ||
828 | |||
829 | /* get width */ | ||
830 | s->width = LCDFN(getstringsize)(s->line, &w, &h); | ||
831 | |||
832 | /* scroll bidirectional or forward only depending on the string | ||
833 | width */ | ||
834 | if ( LCDFN(scroll_info).bidir_limit ) { | ||
835 | s->bidir = s->width < (current_vp->width) * | ||
836 | (100 + LCDFN(scroll_info).bidir_limit) / 100; | ||
837 | } | ||
838 | else | ||
839 | s->bidir = false; | ||
840 | |||
841 | if (!s->bidir) { /* add spaces if scrolling in the round */ | ||
842 | strcat(s->line, " "); | ||
843 | /* get new width incl. spaces */ | ||
844 | s->width = LCDFN(getstringsize)(s->line, &w, &h); | ||
845 | } | ||
846 | |||
847 | end = strchr(s->line, '\0'); | ||
848 | strlcpy(end, string, current_vp->width/2); | ||
849 | |||
850 | s->vp = current_vp; | ||
851 | s->y = y; | ||
852 | s->len = utf8length(string); | ||
853 | s->offset = offset; | ||
854 | s->startx = x * s->width / s->len; | ||
855 | s->backward = false; | ||
856 | |||
857 | LCDFN(scroll_info).lines++; | ||
858 | } | ||
859 | } | ||
860 | |||
861 | void LCDFN(scroll_fn)(void) | ||
862 | { | ||
863 | struct font* pf; | ||
864 | struct scrollinfo* s; | ||
865 | int index; | ||
866 | int xpos, ypos; | ||
867 | int lastmode; | ||
868 | struct viewport* old_vp = current_vp; | ||
869 | |||
870 | for ( index = 0; index < LCDFN(scroll_info).lines; index++ ) { | ||
871 | s = &LCDFN(scroll_info).scroll[index]; | ||
872 | |||
873 | /* check pause */ | ||
874 | if (TIME_BEFORE(current_tick, s->start_tick)) | ||
875 | continue; | ||
876 | |||
877 | LCDFN(set_viewport)(s->vp); | ||
878 | |||
879 | if (s->backward) | ||
880 | s->offset -= LCDFN(scroll_info).step; | ||
881 | else | ||
882 | s->offset += LCDFN(scroll_info).step; | ||
883 | |||
884 | pf = font_get(current_vp->font); | ||
885 | xpos = s->startx; | ||
886 | ypos = s->y * pf->height; | ||
887 | |||
888 | if (s->bidir) { /* scroll bidirectional */ | ||
889 | if (s->offset <= 0) { | ||
890 | /* at beginning of line */ | ||
891 | s->offset = 0; | ||
892 | s->backward = false; | ||
893 | s->start_tick = current_tick + LCDFN(scroll_info).delay * 2; | ||
894 | } | ||
895 | if (s->offset >= s->width - (current_vp->width - xpos)) { | ||
896 | /* at end of line */ | ||
897 | s->offset = s->width - (current_vp->width - xpos); | ||
898 | s->backward = true; | ||
899 | s->start_tick = current_tick + LCDFN(scroll_info).delay * 2; | ||
900 | } | ||
901 | } | ||
902 | else { | ||
903 | /* scroll forward the whole time */ | ||
904 | if (s->offset >= s->width) | ||
905 | s->offset %= s->width; | ||
906 | } | ||
907 | |||
908 | lastmode = current_vp->drawmode; | ||
909 | current_vp->drawmode = (s->style&STYLE_INVERT) ? | ||
910 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | ||
911 | LCDFN(putsxyofs)(xpos, ypos, s->offset, s->line); | ||
912 | current_vp->drawmode = lastmode; | ||
913 | LCDFN(update_viewport_rect)(xpos, ypos, current_vp->width - xpos, pf->height); | ||
914 | } | ||
915 | |||
916 | LCDFN(set_viewport)(old_vp); | ||
917 | } | ||
diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c index 463eece569..bb540a9ae1 100644 --- a/firmware/drivers/lcd-2bit-horz.c +++ b/firmware/drivers/lcd-2bit-horz.c | |||
@@ -956,223 +956,4 @@ void lcd_bitmap(const unsigned char *src, int x, int y, int width, int height) | |||
956 | lcd_bitmap_part(src, 0, 0, width, x, y, width, height); | 956 | lcd_bitmap_part(src, 0, 0, width, x, y, width, height); |
957 | } | 957 | } |
958 | 958 | ||
959 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | 959 | #include "lcd-bitmap-common.c" |
960 | static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | ||
961 | { | ||
962 | unsigned short ch; | ||
963 | unsigned short *ucs; | ||
964 | struct font* pf = font_get(current_vp->font); | ||
965 | |||
966 | ucs = bidi_l2v(str, 1); | ||
967 | |||
968 | while ((ch = *ucs++) != 0 && x < current_vp->width) | ||
969 | { | ||
970 | int width; | ||
971 | const unsigned char *bits; | ||
972 | |||
973 | /* get proportional width and glyph bits */ | ||
974 | width = font_get_width(pf,ch); | ||
975 | |||
976 | if (ofs > width) | ||
977 | { | ||
978 | ofs -= width; | ||
979 | continue; | ||
980 | } | ||
981 | |||
982 | bits = font_get_bits(pf, ch); | ||
983 | |||
984 | lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, | ||
985 | pf->height); | ||
986 | |||
987 | x += width - ofs; | ||
988 | ofs = 0; | ||
989 | } | ||
990 | } | ||
991 | |||
992 | /* put a string at a given pixel position */ | ||
993 | void lcd_putsxy(int x, int y, const unsigned char *str) | ||
994 | { | ||
995 | lcd_putsxyofs(x, y, 0, str); | ||
996 | } | ||
997 | |||
998 | /*** line oriented text output ***/ | ||
999 | |||
1000 | /* put a string at a given char position */ | ||
1001 | void lcd_puts(int x, int y, const unsigned char *str) | ||
1002 | { | ||
1003 | lcd_puts_style_offset(x, y, str, STYLE_DEFAULT, 0); | ||
1004 | } | ||
1005 | |||
1006 | void lcd_puts_style(int x, int y, const unsigned char *str, int style) | ||
1007 | { | ||
1008 | lcd_puts_style_offset(x, y, str, style, 0); | ||
1009 | } | ||
1010 | |||
1011 | void lcd_puts_offset(int x, int y, const unsigned char *str, int offset) | ||
1012 | { | ||
1013 | lcd_puts_style_offset(x, y, str, STYLE_DEFAULT, offset); | ||
1014 | } | ||
1015 | |||
1016 | /* put a string at a given char position, style, and pixel position, | ||
1017 | * skipping first offset pixel columns */ | ||
1018 | void lcd_puts_style_offset(int x, int y, const unsigned char *str, | ||
1019 | int style, int offset) | ||
1020 | { | ||
1021 | int xpos,ypos,w,h,xrect; | ||
1022 | int lastmode = current_vp->drawmode; | ||
1023 | |||
1024 | /* make sure scrolling is turned off on the line we are updating */ | ||
1025 | lcd_scroll_stop_line(current_vp, y); | ||
1026 | |||
1027 | if(!str || !str[0]) | ||
1028 | return; | ||
1029 | |||
1030 | lcd_getstringsize(str, &w, &h); | ||
1031 | xpos = x*w / utf8length((char *)str); | ||
1032 | ypos = y*h; | ||
1033 | current_vp->drawmode = (style & STYLE_INVERT) ? | ||
1034 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | ||
1035 | lcd_putsxyofs(xpos, ypos, offset, str); | ||
1036 | current_vp->drawmode ^= DRMODE_INVERSEVID; | ||
1037 | xrect = xpos + MAX(w - offset, 0); | ||
1038 | lcd_fillrect(xrect, ypos, current_vp->width - xrect, h); | ||
1039 | current_vp->drawmode = lastmode; | ||
1040 | } | ||
1041 | |||
1042 | /*** scrolling ***/ | ||
1043 | void lcd_puts_scroll(int x, int y, const unsigned char *string) | ||
1044 | { | ||
1045 | lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT); | ||
1046 | } | ||
1047 | |||
1048 | void lcd_puts_scroll_style(int x, int y, const unsigned char *string, int style) | ||
1049 | { | ||
1050 | lcd_puts_scroll_style_offset(x, y, string, style, 0); | ||
1051 | } | ||
1052 | |||
1053 | void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, int offset) | ||
1054 | { | ||
1055 | lcd_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset); | ||
1056 | } | ||
1057 | |||
1058 | void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | ||
1059 | int style, int offset) | ||
1060 | { | ||
1061 | struct scrollinfo* s; | ||
1062 | int w, h; | ||
1063 | |||
1064 | if ((unsigned)y >= (unsigned)current_vp->height) | ||
1065 | return; | ||
1066 | |||
1067 | /* remove any previously scrolling line at the same location */ | ||
1068 | lcd_scroll_stop_line(current_vp, y); | ||
1069 | |||
1070 | if (lcd_scroll_info.lines >= LCD_SCROLLABLE_LINES) return; | ||
1071 | |||
1072 | s = &lcd_scroll_info.scroll[lcd_scroll_info.lines]; | ||
1073 | |||
1074 | s->start_tick = current_tick + lcd_scroll_info.delay; | ||
1075 | s->style = style; | ||
1076 | if (style & STYLE_INVERT) { | ||
1077 | lcd_puts_style_offset(x,y,string,STYLE_INVERT,offset); | ||
1078 | } | ||
1079 | else | ||
1080 | lcd_puts_offset(x,y,string,offset); | ||
1081 | |||
1082 | lcd_getstringsize(string, &w, &h); | ||
1083 | |||
1084 | if (current_vp->width - x * 8 < w) { | ||
1085 | /* prepare scroll line */ | ||
1086 | char *end; | ||
1087 | |||
1088 | memset(s->line, 0, sizeof s->line); | ||
1089 | strcpy(s->line, (char *)string); | ||
1090 | |||
1091 | /* get width */ | ||
1092 | s->width = lcd_getstringsize((unsigned char *)s->line, &w, &h); | ||
1093 | |||
1094 | /* scroll bidirectional or forward only depending on the string | ||
1095 | width */ | ||
1096 | if ( lcd_scroll_info.bidir_limit ) { | ||
1097 | s->bidir = s->width < (current_vp->width) * | ||
1098 | (100 + lcd_scroll_info.bidir_limit) / 100; | ||
1099 | } | ||
1100 | else | ||
1101 | s->bidir = false; | ||
1102 | |||
1103 | if (!s->bidir) { /* add spaces if scrolling in the round */ | ||
1104 | strcat(s->line, " "); | ||
1105 | /* get new width incl. spaces */ | ||
1106 | s->width = lcd_getstringsize((unsigned char *)s->line, &w, &h); | ||
1107 | } | ||
1108 | |||
1109 | end = strchr(s->line, '\0'); | ||
1110 | strlcpy(end, (char *)string, current_vp->width/2); | ||
1111 | |||
1112 | s->vp = current_vp; | ||
1113 | s->y = y; | ||
1114 | s->len = utf8length((char *)string); | ||
1115 | s->offset = offset; | ||
1116 | s->startx = x * s->width / s->len; | ||
1117 | s->backward = false; | ||
1118 | lcd_scroll_info.lines++; | ||
1119 | } | ||
1120 | } | ||
1121 | |||
1122 | void lcd_scroll_fn(void) | ||
1123 | { | ||
1124 | struct font* pf; | ||
1125 | struct scrollinfo* s; | ||
1126 | int index; | ||
1127 | int xpos, ypos; | ||
1128 | int lastmode; | ||
1129 | struct viewport* old_vp = current_vp; | ||
1130 | |||
1131 | for ( index = 0; index < lcd_scroll_info.lines; index++ ) { | ||
1132 | s = &lcd_scroll_info.scroll[index]; | ||
1133 | |||
1134 | /* check pause */ | ||
1135 | if (TIME_BEFORE(current_tick, s->start_tick)) | ||
1136 | continue; | ||
1137 | |||
1138 | lcd_set_viewport(s->vp); | ||
1139 | |||
1140 | if (s->backward) | ||
1141 | s->offset -= lcd_scroll_info.step; | ||
1142 | else | ||
1143 | s->offset += lcd_scroll_info.step; | ||
1144 | |||
1145 | pf = font_get(current_vp->font); | ||
1146 | xpos = s->startx; | ||
1147 | ypos = s->y * pf->height; | ||
1148 | |||
1149 | if (s->bidir) { /* scroll bidirectional */ | ||
1150 | if (s->offset <= 0) { | ||
1151 | /* at beginning of line */ | ||
1152 | s->offset = 0; | ||
1153 | s->backward = false; | ||
1154 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | ||
1155 | } | ||
1156 | if (s->offset >= s->width - (current_vp->width - xpos)) { | ||
1157 | /* at end of line */ | ||
1158 | s->offset = s->width - (current_vp->width - xpos); | ||
1159 | s->backward = true; | ||
1160 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | ||
1161 | } | ||
1162 | } | ||
1163 | else { | ||
1164 | /* scroll forward the whole time */ | ||
1165 | if (s->offset >= s->width) | ||
1166 | s->offset %= s->width; | ||
1167 | } | ||
1168 | |||
1169 | lastmode = current_vp->drawmode; | ||
1170 | current_vp->drawmode = (s->style&STYLE_INVERT) ? | ||
1171 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | ||
1172 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); | ||
1173 | current_vp->drawmode = lastmode; | ||
1174 | lcd_update_viewport_rect(xpos, ypos, current_vp->width - xpos, pf->height); | ||
1175 | } | ||
1176 | |||
1177 | lcd_set_viewport(old_vp); | ||
1178 | } | ||
diff --git a/firmware/drivers/lcd-2bit-vert.c b/firmware/drivers/lcd-2bit-vert.c index 57d27d2ead..7342cbd4ff 100644 --- a/firmware/drivers/lcd-2bit-vert.c +++ b/firmware/drivers/lcd-2bit-vert.c | |||
@@ -404,7 +404,7 @@ void lcd_clear_viewport(void) | |||
404 | lastmode = current_vp->drawmode; | 404 | lastmode = current_vp->drawmode; |
405 | 405 | ||
406 | /* Invert the INVERSEVID bit and set basic mode to SOLID */ | 406 | /* Invert the INVERSEVID bit and set basic mode to SOLID */ |
407 | current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | | 407 | current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | |
408 | DRMODE_SOLID; | 408 | DRMODE_SOLID; |
409 | 409 | ||
410 | lcd_fillrect(0, 0, current_vp->width, current_vp->height); | 410 | lcd_fillrect(0, 0, current_vp->width, current_vp->height); |
@@ -1002,226 +1002,4 @@ void lcd_bitmap(const fb_data *src, int x, int y, int width, int height) | |||
1002 | lcd_bitmap_part(src, 0, 0, width, x, y, width, height); | 1002 | lcd_bitmap_part(src, 0, 0, width, x, y, width, height); |
1003 | } | 1003 | } |
1004 | 1004 | ||
1005 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | 1005 | #include "lcd-bitmap-common.c" |
1006 | static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | ||
1007 | { | ||
1008 | unsigned short ch; | ||
1009 | unsigned short *ucs; | ||
1010 | struct font* pf = font_get(current_vp->font); | ||
1011 | |||
1012 | ucs = bidi_l2v(str, 1); | ||
1013 | |||
1014 | while ((ch = *ucs++) != 0 && x < current_vp->width) | ||
1015 | { | ||
1016 | int width; | ||
1017 | const unsigned char *bits; | ||
1018 | |||
1019 | /* get proportional width and glyph bits */ | ||
1020 | width = font_get_width(pf,ch); | ||
1021 | |||
1022 | if (ofs > width) | ||
1023 | { | ||
1024 | ofs -= width; | ||
1025 | continue; | ||
1026 | } | ||
1027 | |||
1028 | bits = font_get_bits(pf, ch); | ||
1029 | |||
1030 | lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, | ||
1031 | pf->height); | ||
1032 | |||
1033 | x += width - ofs; | ||
1034 | ofs = 0; | ||
1035 | } | ||
1036 | } | ||
1037 | |||
1038 | /* put a string at a given pixel position */ | ||
1039 | void lcd_putsxy(int x, int y, const unsigned char *str) | ||
1040 | { | ||
1041 | lcd_putsxyofs(x, y, 0, str); | ||
1042 | } | ||
1043 | |||
1044 | /*** line oriented text output ***/ | ||
1045 | |||
1046 | /* put a string at a given char position */ | ||
1047 | void lcd_puts(int x, int y, const unsigned char *str) | ||
1048 | { | ||
1049 | lcd_puts_style_offset(x, y, str, STYLE_DEFAULT, 0); | ||
1050 | } | ||
1051 | |||
1052 | void lcd_puts_style(int x, int y, const unsigned char *str, int style) | ||
1053 | { | ||
1054 | lcd_puts_style_offset(x, y, str, style, 0); | ||
1055 | } | ||
1056 | |||
1057 | void lcd_puts_offset(int x, int y, const unsigned char *str, int offset) | ||
1058 | { | ||
1059 | lcd_puts_style_offset(x, y, str, STYLE_DEFAULT, offset); | ||
1060 | } | ||
1061 | |||
1062 | /* put a string at a given char position, style, and pixel position, | ||
1063 | * skipping first offset pixel columns */ | ||
1064 | void lcd_puts_style_offset(int x, int y, const unsigned char *str, | ||
1065 | int style, int offset) | ||
1066 | { | ||
1067 | int xpos,ypos,w,h,xrect; | ||
1068 | int lastmode = current_vp->drawmode; | ||
1069 | |||
1070 | /* make sure scrolling is turned off on the line we are updating */ | ||
1071 | lcd_scroll_stop_line(current_vp, y); | ||
1072 | |||
1073 | if(!str || !str[0]) | ||
1074 | return; | ||
1075 | |||
1076 | lcd_getstringsize(str, &w, &h); | ||
1077 | xpos = x*w / utf8length((char *)str); | ||
1078 | ypos = y*h; | ||
1079 | current_vp->drawmode = (style & STYLE_INVERT) ? | ||
1080 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | ||
1081 | lcd_putsxyofs(xpos, ypos, offset, str); | ||
1082 | current_vp->drawmode ^= DRMODE_INVERSEVID; | ||
1083 | xrect = xpos + MAX(w - offset, 0); | ||
1084 | lcd_fillrect(xrect, ypos, current_vp->width - xrect, h); | ||
1085 | current_vp->drawmode = lastmode; | ||
1086 | } | ||
1087 | |||
1088 | /*** scrolling ***/ | ||
1089 | |||
1090 | void lcd_puts_scroll(int x, int y, const unsigned char *string) | ||
1091 | { | ||
1092 | lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT); | ||
1093 | } | ||
1094 | |||
1095 | void lcd_puts_scroll_style(int x, int y, const unsigned char *string, int style) | ||
1096 | { | ||
1097 | lcd_puts_scroll_style_offset(x, y, string, style, 0); | ||
1098 | } | ||
1099 | |||
1100 | void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, int offset) | ||
1101 | { | ||
1102 | lcd_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset); | ||
1103 | } | ||
1104 | |||
1105 | void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, | ||
1106 | int style, int offset) | ||
1107 | { | ||
1108 | struct scrollinfo* s; | ||
1109 | int w, h; | ||
1110 | |||
1111 | if ((unsigned)y >= (unsigned)current_vp->height) | ||
1112 | return; | ||
1113 | |||
1114 | /* remove any previously scrolling line at the same location */ | ||
1115 | lcd_scroll_stop_line(current_vp, y); | ||
1116 | |||
1117 | if (lcd_scroll_info.lines >= LCD_SCROLLABLE_LINES) return; | ||
1118 | |||
1119 | s = &lcd_scroll_info.scroll[lcd_scroll_info.lines]; | ||
1120 | |||
1121 | s->start_tick = current_tick + lcd_scroll_info.delay; | ||
1122 | s->style = style; | ||
1123 | if (style & STYLE_INVERT) { | ||
1124 | lcd_puts_style_offset(x,y,string,STYLE_INVERT,offset); | ||
1125 | } | ||
1126 | else | ||
1127 | lcd_puts_offset(x,y,string,offset); | ||
1128 | |||
1129 | lcd_getstringsize(string, &w, &h); | ||
1130 | |||
1131 | if (current_vp->width - x * 8< w) { | ||
1132 | /* prepare scroll line */ | ||
1133 | char *end; | ||
1134 | |||
1135 | memset(s->line, 0, sizeof s->line); | ||
1136 | strcpy(s->line, (char *)string); | ||
1137 | |||
1138 | /* get width */ | ||
1139 | s->width = lcd_getstringsize((unsigned char *)s->line, &w, &h); | ||
1140 | |||
1141 | /* scroll bidirectional or forward only depending on the string | ||
1142 | width */ | ||
1143 | if ( lcd_scroll_info.bidir_limit ) { | ||
1144 | s->bidir = s->width < (current_vp->width) * | ||
1145 | (100 + lcd_scroll_info.bidir_limit) / 100; | ||
1146 | } | ||
1147 | else | ||
1148 | s->bidir = false; | ||
1149 | |||
1150 | if (!s->bidir) { /* add spaces if scrolling in the round */ | ||
1151 | strcat(s->line, " "); | ||
1152 | /* get new width incl. spaces */ | ||
1153 | s->width = lcd_getstringsize((unsigned char *)s->line, &w, &h); | ||
1154 | } | ||
1155 | |||
1156 | end = strchr(s->line, '\0'); | ||
1157 | strlcpy(end, (char *)string, current_vp->width/2); | ||
1158 | |||
1159 | s->vp = current_vp; | ||
1160 | s->y = y; | ||
1161 | s->len = utf8length((char *)string); | ||
1162 | s->offset = offset; | ||
1163 | s->startx = x * s->width / s->len; | ||
1164 | s->backward = false; | ||
1165 | |||
1166 | lcd_scroll_info.lines++; | ||
1167 | } | ||
1168 | } | ||
1169 | |||
1170 | void lcd_scroll_fn(void) | ||
1171 | { | ||
1172 | struct font* pf; | ||
1173 | struct scrollinfo* s; | ||
1174 | int index; | ||
1175 | int xpos, ypos; | ||
1176 | int lastmode; | ||
1177 | struct viewport* old_vp = current_vp; | ||
1178 | |||
1179 | for ( index = 0; index < lcd_scroll_info.lines; index++ ) { | ||
1180 | s = &lcd_scroll_info.scroll[index]; | ||
1181 | |||
1182 | /* check pause */ | ||
1183 | if (TIME_BEFORE(current_tick, s->start_tick)) | ||
1184 | continue; | ||
1185 | |||
1186 | lcd_set_viewport(s->vp); | ||
1187 | |||
1188 | if (s->backward) | ||
1189 | s->offset -= lcd_scroll_info.step; | ||
1190 | else | ||
1191 | s->offset += lcd_scroll_info.step; | ||
1192 | |||
1193 | pf = font_get(current_vp->font); | ||
1194 | xpos = s->startx; | ||
1195 | ypos = s->y * pf->height; | ||
1196 | |||
1197 | if (s->bidir) { /* scroll bidirectional */ | ||
1198 | if (s->offset <= 0) { | ||
1199 | /* at beginning of line */ | ||
1200 | s->offset = 0; | ||
1201 | s->backward = false; | ||
1202 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | ||
1203 | } | ||
1204 | if (s->offset >= s->width - (current_vp->width - xpos)) { | ||
1205 | /* at end of line */ | ||
1206 | s->offset = s->width - (current_vp->width - xpos); | ||
1207 | s->backward = true; | ||
1208 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | ||
1209 | } | ||
1210 | } | ||
1211 | else { | ||
1212 | /* scroll forward the whole time */ | ||
1213 | if (s->offset >= s->width) | ||
1214 | s->offset %= s->width; | ||
1215 | } | ||
1216 | |||
1217 | lastmode = current_vp->drawmode; | ||
1218 | current_vp->drawmode = (s->style&STYLE_INVERT) ? | ||
1219 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | ||
1220 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); | ||
1221 | current_vp->drawmode = lastmode; | ||
1222 | lcd_update_viewport_rect(xpos, ypos, | ||
1223 | current_vp->width - xpos, pf->height); | ||
1224 | } | ||
1225 | |||
1226 | lcd_set_viewport(old_vp); | ||
1227 | } | ||
diff --git a/firmware/drivers/lcd-2bit-vi.c b/firmware/drivers/lcd-2bit-vi.c index 0a73f0dd25..47f755f240 100644 --- a/firmware/drivers/lcd-2bit-vi.c +++ b/firmware/drivers/lcd-2bit-vi.c | |||
@@ -66,7 +66,7 @@ static struct viewport default_vp = | |||
66 | .bg_pattern = LCDM(DEFAULT_BG) | 66 | .bg_pattern = LCDM(DEFAULT_BG) |
67 | }; | 67 | }; |
68 | 68 | ||
69 | static struct viewport *current_vp IBSS_ATTR; | 69 | static struct viewport * current_vp IBSS_ATTR; |
70 | 70 | ||
71 | static unsigned fg_pattern IBSS_ATTR; | 71 | static unsigned fg_pattern IBSS_ATTR; |
72 | static unsigned bg_pattern IBSS_ATTR; | 72 | static unsigned bg_pattern IBSS_ATTR; |
@@ -1016,225 +1016,4 @@ void LCDFN(bitmap)(const FBFN(data) *src, int x, int y, int width, int height) | |||
1016 | LCDFN(bitmap_part)(src, 0, 0, width, x, y, width, height); | 1016 | LCDFN(bitmap_part)(src, 0, 0, width, x, y, width, height); |
1017 | } | 1017 | } |
1018 | 1018 | ||
1019 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | 1019 | #include "lcd-bitmap-common.c" |
1020 | static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) | ||
1021 | { | ||
1022 | unsigned short ch; | ||
1023 | unsigned short *ucs; | ||
1024 | struct font* pf = font_get(current_vp->font); | ||
1025 | |||
1026 | ucs = bidi_l2v(str, 1); | ||
1027 | |||
1028 | while ((ch = *ucs++) != 0 && x < current_vp->width) | ||
1029 | { | ||
1030 | int width; | ||
1031 | const unsigned char *bits; | ||
1032 | |||
1033 | /* get proportional width and glyph bits */ | ||
1034 | width = font_get_width(pf, ch); | ||
1035 | |||
1036 | if (ofs > width) | ||
1037 | { | ||
1038 | ofs -= width; | ||
1039 | continue; | ||
1040 | } | ||
1041 | |||
1042 | bits = font_get_bits(pf, ch); | ||
1043 | |||
1044 | LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x, y, width - ofs, | ||
1045 | pf->height); | ||
1046 | |||
1047 | x += width - ofs; | ||
1048 | ofs = 0; | ||
1049 | } | ||
1050 | } | ||
1051 | |||
1052 | /* put a string at a given pixel position */ | ||
1053 | void LCDFN(putsxy)(int x, int y, const unsigned char *str) | ||
1054 | { | ||
1055 | LCDFN(putsxyofs)(x, y, 0, str); | ||
1056 | } | ||
1057 | |||
1058 | /*** line oriented text output ***/ | ||
1059 | |||
1060 | /* put a string at a given char position */ | ||
1061 | void LCDFN(puts)(int x, int y, const unsigned char *str) | ||
1062 | { | ||
1063 | LCDFN(puts_style_offset)(x, y, str, STYLE_DEFAULT, 0); | ||
1064 | } | ||
1065 | |||
1066 | void LCDFN(puts_style)(int x, int y, const unsigned char *str, int style) | ||
1067 | { | ||
1068 | LCDFN(puts_style_offset)(x, y, str, style, 0); | ||
1069 | } | ||
1070 | |||
1071 | void LCDFN(puts_offset)(int x, int y, const unsigned char *str, int offset) | ||
1072 | { | ||
1073 | LCDFN(puts_style_offset)(x, y, str, STYLE_DEFAULT, offset); | ||
1074 | } | ||
1075 | |||
1076 | /* put a string at a given char position, style, and pixel position, | ||
1077 | * skipping first offset pixel columns */ | ||
1078 | void LCDFN(puts_style_offset)(int x, int y, const unsigned char *str, | ||
1079 | int style, int offset) | ||
1080 | { | ||
1081 | int xpos,ypos,w,h,xrect; | ||
1082 | int lastmode = current_vp->drawmode; | ||
1083 | |||
1084 | /* make sure scrolling is turned off on the line we are updating */ | ||
1085 | LCDFN(scroll_stop_line)(current_vp, y); | ||
1086 | |||
1087 | if(!str || !str[0]) | ||
1088 | return; | ||
1089 | |||
1090 | LCDFN(getstringsize)(str, &w, &h); | ||
1091 | xpos = x*w / utf8length((char *)str); | ||
1092 | ypos = y*h; | ||
1093 | current_vp->drawmode = (style & STYLE_INVERT) ? | ||
1094 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | ||
1095 | LCDFN(putsxyofs)(xpos, ypos, offset, str); | ||
1096 | current_vp->drawmode ^= DRMODE_INVERSEVID; | ||
1097 | xrect = xpos + MAX(w - offset, 0); | ||
1098 | LCDFN(fillrect)(xrect, ypos, current_vp->width - xrect, h); | ||
1099 | current_vp->drawmode = lastmode; | ||
1100 | } | ||
1101 | |||
1102 | /*** scrolling ***/ | ||
1103 | void LCDFN(puts_scroll)(int x, int y, const unsigned char *string) | ||
1104 | { | ||
1105 | LCDFN(puts_scroll_style)(x, y, string, STYLE_DEFAULT); | ||
1106 | } | ||
1107 | |||
1108 | void LCDFN(puts_scroll_style)(int x, int y, const unsigned char *string, int style) | ||
1109 | { | ||
1110 | LCDFN(puts_scroll_style_offset)(x, y, string, style, 0); | ||
1111 | } | ||
1112 | |||
1113 | void LCDFN(puts_scroll_offset)(int x, int y, const unsigned char *string, int offset) | ||
1114 | { | ||
1115 | LCDFN(puts_scroll_style_offset)(x, y, string, STYLE_DEFAULT, offset); | ||
1116 | } | ||
1117 | |||
1118 | void LCDFN(puts_scroll_style_offset)(int x, int y, const unsigned char *string, | ||
1119 | int style, int offset) | ||
1120 | { | ||
1121 | struct scrollinfo* s; | ||
1122 | int w, h; | ||
1123 | |||
1124 | if ((unsigned)y >= (unsigned)current_vp->height) | ||
1125 | return; | ||
1126 | |||
1127 | /* remove any previously scrolling line at the same location */ | ||
1128 | LCDFN(scroll_stop_line)(current_vp, y); | ||
1129 | |||
1130 | if (LCDFN(scroll_info).lines >= LCDM(SCROLLABLE_LINES)) return; | ||
1131 | |||
1132 | s = &LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines]; | ||
1133 | |||
1134 | s->start_tick = current_tick + LCDFN(scroll_info).delay; | ||
1135 | s->style = style; | ||
1136 | if (style & STYLE_INVERT) { | ||
1137 | LCDFN(puts_style_offset)(x,y,string,STYLE_INVERT,offset); | ||
1138 | } | ||
1139 | else | ||
1140 | LCDFN(puts_offset)(x,y,string,offset); | ||
1141 | |||
1142 | LCDFN(getstringsize)(string, &w, &h); | ||
1143 | |||
1144 | if (current_vp->width - x * 8 < w) { | ||
1145 | /* prepare scroll line */ | ||
1146 | char *end; | ||
1147 | |||
1148 | memset(s->line, 0, sizeof s->line); | ||
1149 | strcpy(s->line, string); | ||
1150 | |||
1151 | /* get width */ | ||
1152 | s->width = LCDFN(getstringsize)(s->line, &w, &h); | ||
1153 | |||
1154 | /* scroll bidirectional or forward only depending on the string | ||
1155 | width */ | ||
1156 | if ( LCDFN(scroll_info).bidir_limit ) { | ||
1157 | s->bidir = s->width < (current_vp->width) * | ||
1158 | (100 + LCDFN(scroll_info).bidir_limit) / 100; | ||
1159 | } | ||
1160 | else | ||
1161 | s->bidir = false; | ||
1162 | |||
1163 | if (!s->bidir) { /* add spaces if scrolling in the round */ | ||
1164 | strcat(s->line, " "); | ||
1165 | /* get new width incl. spaces */ | ||
1166 | s->width = LCDFN(getstringsize)(s->line, &w, &h); | ||
1167 | } | ||
1168 | |||
1169 | end = strchr(s->line, '\0'); | ||
1170 | strlcpy(end, (char *)string, current_vp->width/2); | ||
1171 | |||
1172 | s->vp = current_vp; | ||
1173 | s->y = y; | ||
1174 | s->len = utf8length((char *)string); | ||
1175 | s->offset = offset; | ||
1176 | s->startx = x * s->width / s->len; | ||
1177 | s->backward = false; | ||
1178 | |||
1179 | LCDFN(scroll_info).lines++; | ||
1180 | } | ||
1181 | } | ||
1182 | |||
1183 | void LCDFN(scroll_fn)(void) | ||
1184 | { | ||
1185 | struct font* pf; | ||
1186 | struct scrollinfo* s; | ||
1187 | int index; | ||
1188 | int xpos, ypos; | ||
1189 | int lastmode; | ||
1190 | struct viewport* old_vp = current_vp; | ||
1191 | |||
1192 | for ( index = 0; index < LCDFN(scroll_info).lines; index++ ) { | ||
1193 | s = &LCDFN(scroll_info).scroll[index]; | ||
1194 | |||
1195 | /* check pause */ | ||
1196 | if (TIME_BEFORE(current_tick, s->start_tick)) | ||
1197 | continue; | ||
1198 | |||
1199 | LCDFN(set_viewport)(s->vp); | ||
1200 | |||
1201 | if (s->backward) | ||
1202 | s->offset -= LCDFN(scroll_info).step; | ||
1203 | else | ||
1204 | s->offset += LCDFN(scroll_info).step; | ||
1205 | |||
1206 | pf = font_get(current_vp->font); | ||
1207 | xpos = s->startx; | ||
1208 | ypos = s->y * pf->height; | ||
1209 | |||
1210 | if (s->bidir) { /* scroll bidirectional */ | ||
1211 | if (s->offset <= 0) { | ||
1212 | /* at beginning of line */ | ||
1213 | s->offset = 0; | ||
1214 | s->backward = false; | ||
1215 | s->start_tick = current_tick + LCDFN(scroll_info).delay * 2; | ||
1216 | } | ||
1217 | if (s->offset >= s->width - (current_vp->width - xpos)) { | ||
1218 | /* at end of line */ | ||
1219 | s->offset = s->width - (current_vp->width - xpos); | ||
1220 | s->backward = true; | ||
1221 | s->start_tick = current_tick + LCDFN(scroll_info).delay * 2; | ||
1222 | } | ||
1223 | } | ||
1224 | else { | ||
1225 | /* scroll forward the whole time */ | ||
1226 | if (s->offset >= s->width) | ||
1227 | s->offset %= s->width; | ||
1228 | } | ||
1229 | |||
1230 | lastmode = current_vp->drawmode; | ||
1231 | current_vp->drawmode = (s->style&STYLE_INVERT) ? | ||
1232 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | ||
1233 | LCDFN(putsxyofs)(xpos, ypos, s->offset, s->line); | ||
1234 | current_vp->drawmode = lastmode; | ||
1235 | LCDFN(update_viewport_rect)(xpos, ypos, | ||
1236 | current_vp->width - xpos, pf->height); | ||
1237 | } | ||
1238 | |||
1239 | LCDFN(set_viewport)(old_vp); | ||
1240 | } | ||
diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c new file mode 100644 index 0000000000..c1efd9097e --- /dev/null +++ b/firmware/drivers/lcd-bitmap-common.c | |||
@@ -0,0 +1,329 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 Dave Chapman | ||
11 | * Text rendering | ||
12 | * Copyright (C) 2006 Shachar Liberman | ||
13 | * Offset text, scrolling | ||
14 | * Copyright (C) 2007 Nicolas Pennequin, Tom Ross, Ken Fazzone, Akio Idehara | ||
15 | * Color gradient background | ||
16 | * Copyright (C) 2009 Andrew Mahone | ||
17 | * Merged common LCD bitmap code | ||
18 | * | ||
19 | * Rockbox common bitmap LCD functions | ||
20 | * | ||
21 | * This program is free software; you can redistribute it and/or | ||
22 | * modify it under the terms of the GNU General Public License | ||
23 | * as published by the Free Software Foundation; either version 2 | ||
24 | * of the License, or (at your option) any later version. | ||
25 | * | ||
26 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
27 | * KIND, either express or implied. | ||
28 | * | ||
29 | ****************************************************************************/ | ||
30 | |||
31 | #ifndef LCDFN /* Not compiling for remote - define macros for main LCD. */ | ||
32 | #define LCDFN(fn) lcd_ ## fn | ||
33 | #define FBFN(fn) fb_ ## fn | ||
34 | #define LCDM(ma) LCD_ ## ma | ||
35 | #define LCDNAME "lcd_" | ||
36 | #define MAIN_LCD | ||
37 | #endif | ||
38 | |||
39 | #if defined(MAIN_LCD) && defined(HAVE_LCD_COLOR) | ||
40 | /* Fill a rectangle with a gradient */ | ||
41 | static void lcd_gradient_rect(int x1, int x2, int y, unsigned h, | ||
42 | int num_lines, int cur_line) | ||
43 | { | ||
44 | int old_pattern = current_vp->fg_pattern; | ||
45 | int step_mul; | ||
46 | if (h == 0) return; | ||
47 | |||
48 | num_lines *= h; | ||
49 | cur_line *= h; | ||
50 | step_mul = (1 << 16) / (num_lines); | ||
51 | int h_r = RGB_UNPACK_RED(current_vp->lss_pattern); | ||
52 | int h_g = RGB_UNPACK_GREEN(current_vp->lss_pattern); | ||
53 | int h_b = RGB_UNPACK_BLUE(current_vp->lss_pattern); | ||
54 | int rstep = (h_r - RGB_UNPACK_RED(current_vp->lse_pattern)) * step_mul; | ||
55 | int gstep = (h_g - RGB_UNPACK_GREEN(current_vp->lse_pattern)) * step_mul; | ||
56 | int bstep = (h_b - RGB_UNPACK_BLUE(current_vp->lse_pattern)) * step_mul; | ||
57 | h_r = (h_r << 16) + (1 << 15); | ||
58 | h_g = (h_g << 16) + (1 << 15); | ||
59 | h_b = (h_b << 16) + (1 << 15); | ||
60 | if (cur_line) | ||
61 | { | ||
62 | h_r -= cur_line * rstep; | ||
63 | h_g -= cur_line * gstep; | ||
64 | h_b -= cur_line * bstep; | ||
65 | } | ||
66 | unsigned count; | ||
67 | |||
68 | for(count = 0; count < h; count++) { | ||
69 | current_vp->fg_pattern = LCD_RGBPACK(h_r >> 16, h_g >> 16, h_b >> 16); | ||
70 | lcd_hline(x1, x2, y + count); | ||
71 | h_r -= rstep; | ||
72 | h_g -= gstep; | ||
73 | h_b -= bstep; | ||
74 | } | ||
75 | |||
76 | current_vp->fg_pattern = old_pattern; | ||
77 | } | ||
78 | #endif | ||
79 | |||
80 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | ||
81 | static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) | ||
82 | { | ||
83 | unsigned short ch; | ||
84 | unsigned short *ucs; | ||
85 | struct font* pf = font_get(current_vp->font); | ||
86 | |||
87 | ucs = bidi_l2v(str, 1); | ||
88 | |||
89 | while ((ch = *ucs++) != 0 && x < current_vp->width) | ||
90 | { | ||
91 | int width; | ||
92 | const unsigned char *bits; | ||
93 | |||
94 | /* get proportional width and glyph bits */ | ||
95 | width = font_get_width(pf, ch); | ||
96 | |||
97 | if (ofs > width) | ||
98 | { | ||
99 | ofs -= width; | ||
100 | continue; | ||
101 | } | ||
102 | |||
103 | bits = font_get_bits(pf, ch); | ||
104 | |||
105 | LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x, y, width - ofs, | ||
106 | pf->height); | ||
107 | |||
108 | x += width - ofs; | ||
109 | ofs = 0; | ||
110 | } | ||
111 | } | ||
112 | /* put a string at a given pixel position */ | ||
113 | void LCDFN(putsxy)(int x, int y, const unsigned char *str) | ||
114 | { | ||
115 | LCDFN(putsxyofs)(x, y, 0, str); | ||
116 | } | ||
117 | |||
118 | static void LCDFN(putsxyofs_style)(int xpos, int ypos, | ||
119 | const unsigned char *str, int style, | ||
120 | int w, int h, int offset) | ||
121 | { | ||
122 | int lastmode = current_vp->drawmode; | ||
123 | int xrect = xpos + MAX(w - offset, 0); | ||
124 | #if defined(MAIN_LCD) && defined(HAVE_LCD_COLOR) | ||
125 | int oldfgcolor = current_vp->fg_pattern; | ||
126 | int oldbgcolor = current_vp->bg_pattern; | ||
127 | current_vp->drawmode = DRMODE_SOLID | ((style & STYLE_INVERT) ? | ||
128 | DRMODE_INVERSEVID : 0); | ||
129 | if (style & STYLE_COLORED) { | ||
130 | if (current_vp->drawmode == DRMODE_SOLID) | ||
131 | current_vp->fg_pattern = style & STYLE_COLOR_MASK; | ||
132 | else | ||
133 | current_vp->bg_pattern = style & STYLE_COLOR_MASK; | ||
134 | } | ||
135 | current_vp->drawmode ^= DRMODE_INVERSEVID; | ||
136 | if (style & STYLE_GRADIENT) { | ||
137 | current_vp->drawmode = DRMODE_FG; | ||
138 | lcd_gradient_rect(xpos, current_vp->width, ypos, h, | ||
139 | NUMLN_UNPACK(style), CURLN_UNPACK(style)); | ||
140 | current_vp->fg_pattern = current_vp->lst_pattern; | ||
141 | } | ||
142 | else if (style & STYLE_COLORBAR) { | ||
143 | current_vp->drawmode = DRMODE_FG; | ||
144 | current_vp->fg_pattern = current_vp->lss_pattern; | ||
145 | lcd_fillrect(xpos, ypos, current_vp->width - xpos, h); | ||
146 | current_vp->fg_pattern = current_vp->lst_pattern; | ||
147 | } | ||
148 | else { | ||
149 | lcd_fillrect(xrect, ypos, current_vp->width - xrect, h); | ||
150 | current_vp->drawmode = (style & STYLE_INVERT) ? | ||
151 | (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; | ||
152 | } | ||
153 | lcd_putsxyofs(xpos, ypos, offset, str); | ||
154 | current_vp->fg_pattern = oldfgcolor; | ||
155 | current_vp->bg_pattern = oldbgcolor; | ||
156 | #else | ||
157 | current_vp->drawmode = DRMODE_SOLID | ((style & STYLE_INVERT) ? | ||
158 | 0 : DRMODE_INVERSEVID); | ||
159 | LCDFN(fillrect)(xrect, ypos, current_vp->width - xrect, h); | ||
160 | current_vp->drawmode ^= DRMODE_INVERSEVID; | ||
161 | LCDFN(putsxyofs)(xpos, ypos, offset, str); | ||
162 | #endif | ||
163 | current_vp->drawmode = lastmode; | ||
164 | } | ||
165 | |||
166 | /*** Line oriented text output ***/ | ||
167 | |||
168 | /* put a string at a given char position */ | ||
169 | void LCDFN(puts_style_offset)(int x, int y, const unsigned char *str, | ||
170 | int style, int offset) | ||
171 | { | ||
172 | int xpos, ypos, w, h; | ||
173 | LCDFN(scroll_stop_line)(current_vp, y); | ||
174 | if(!str || !str[0]) | ||
175 | return; | ||
176 | LCDFN(getstringsize)(str, &w, &h); | ||
177 | xpos = x * w / utf8length((char *)str); | ||
178 | ypos = y * h; | ||
179 | LCDFN(putsxyofs_style)(xpos, ypos, str, style, w, h, offset); | ||
180 | } | ||
181 | |||
182 | void LCDFN(puts)(int x, int y, const unsigned char *str) | ||
183 | { | ||
184 | LCDFN(puts_style_offset)(x, y, str, STYLE_DEFAULT, 0); | ||
185 | } | ||
186 | |||
187 | void LCDFN(puts_style)(int x, int y, const unsigned char *str, int style) | ||
188 | { | ||
189 | LCDFN(puts_style_offset)(x, y, str, style, 0); | ||
190 | } | ||
191 | |||
192 | void LCDFN(puts_offset)(int x, int y, const unsigned char *str, int offset) | ||
193 | { | ||
194 | LCDFN(puts_style_offset)(x, y, str, STYLE_DEFAULT, offset); | ||
195 | } | ||
196 | |||
197 | /*** scrolling ***/ | ||
198 | |||
199 | void LCDFN(puts_scroll_style_offset)(int x, int y, const unsigned char *string, | ||
200 | int style, int offset) | ||
201 | { | ||
202 | int w, h; | ||
203 | |||
204 | if ((unsigned)y >= (unsigned)current_vp->height) | ||
205 | return; | ||
206 | |||
207 | /* remove any previously scrolling line at the same location */ | ||
208 | lcd_scroll_stop_line(current_vp, y); | ||
209 | |||
210 | if (LCDFN(scroll_info.lines) >= LCDM(SCROLLABLE_LINES)) return; | ||
211 | if (!string) | ||
212 | return; | ||
213 | LCDFN(puts_style_offset)(x, y, string, style, offset); | ||
214 | |||
215 | LCDFN(getstringsize)(string, &w, &h); | ||
216 | |||
217 | if (current_vp->width - x * 8 < w) { | ||
218 | /* prepare scroll line */ | ||
219 | struct scrollinfo* s; | ||
220 | s = &LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines]; | ||
221 | s->start_tick = current_tick + LCDFN(scroll_info).delay; | ||
222 | s->style = style; | ||
223 | |||
224 | char *end; | ||
225 | |||
226 | memset(s->line, 0, sizeof s->line); | ||
227 | strcpy(s->line, string); | ||
228 | |||
229 | /* get width */ | ||
230 | s->width = LCDFN(getstringsize)(s->line, &w, &h); | ||
231 | |||
232 | /* scroll bidirectional or forward only depending on the string | ||
233 | width */ | ||
234 | if ( LCDFN(scroll_info).bidir_limit ) { | ||
235 | s->bidir = s->width < (current_vp->width) * | ||
236 | (100 + LCDFN(scroll_info).bidir_limit) / 100; | ||
237 | } | ||
238 | else | ||
239 | s->bidir = false; | ||
240 | |||
241 | if (!s->bidir) { /* add spaces if scrolling in the round */ | ||
242 | strcat(s->line, " "); | ||
243 | /* get new width incl. spaces */ | ||
244 | s->width = LCDFN(getstringsize)(s->line, &w, &h); | ||
245 | } | ||
246 | |||
247 | end = strchr(s->line, '\0'); | ||
248 | strlcpy(end, string, current_vp->width/2); | ||
249 | |||
250 | s->vp = current_vp; | ||
251 | s->y = y; | ||
252 | s->len = utf8length(string); | ||
253 | s->offset = offset; | ||
254 | s->startx = x * s->width / s->len; | ||
255 | s->backward = false; | ||
256 | |||
257 | LCDFN(scroll_info).lines++; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | void LCDFN(puts_scroll)(int x, int y, const unsigned char *string) | ||
262 | { | ||
263 | LCDFN(puts_scroll_style)(x, y, string, STYLE_DEFAULT); | ||
264 | } | ||
265 | |||
266 | void LCDFN(puts_scroll_style)(int x, int y, const unsigned char *string, | ||
267 | int style) | ||
268 | { | ||
269 | LCDFN(puts_scroll_style_offset)(x, y, string, style, 0); | ||
270 | } | ||
271 | |||
272 | void LCDFN(puts_scroll_offset)(int x, int y, const unsigned char *string, | ||
273 | int offset) | ||
274 | { | ||
275 | LCDFN(puts_scroll_style_offset)(x, y, string, STYLE_DEFAULT, offset); | ||
276 | } | ||
277 | |||
278 | void LCDFN(scroll_fn)(void) | ||
279 | { | ||
280 | struct font* pf; | ||
281 | struct scrollinfo* s; | ||
282 | int index; | ||
283 | int xpos, ypos; | ||
284 | struct viewport* old_vp = current_vp; | ||
285 | |||
286 | for ( index = 0; index < LCDFN(scroll_info).lines; index++ ) { | ||
287 | s = &LCDFN(scroll_info).scroll[index]; | ||
288 | |||
289 | /* check pause */ | ||
290 | if (TIME_BEFORE(current_tick, s->start_tick)) | ||
291 | continue; | ||
292 | |||
293 | LCDFN(set_viewport)(s->vp); | ||
294 | |||
295 | if (s->backward) | ||
296 | s->offset -= LCDFN(scroll_info).step; | ||
297 | else | ||
298 | s->offset += LCDFN(scroll_info).step; | ||
299 | |||
300 | pf = font_get(current_vp->font); | ||
301 | xpos = s->startx; | ||
302 | ypos = s->y * pf->height; | ||
303 | |||
304 | if (s->bidir) { /* scroll bidirectional */ | ||
305 | if (s->offset <= 0) { | ||
306 | /* at beginning of line */ | ||
307 | s->offset = 0; | ||
308 | s->backward = false; | ||
309 | s->start_tick = current_tick + LCDFN(scroll_info).delay * 2; | ||
310 | } | ||
311 | if (s->offset >= s->width - (current_vp->width - xpos)) { | ||
312 | /* at end of line */ | ||
313 | s->offset = s->width - (current_vp->width - xpos); | ||
314 | s->backward = true; | ||
315 | s->start_tick = current_tick + LCDFN(scroll_info).delay * 2; | ||
316 | } | ||
317 | } | ||
318 | else { | ||
319 | /* scroll forward the whole time */ | ||
320 | if (s->offset >= s->width) | ||
321 | s->offset %= s->width; | ||
322 | } | ||
323 | LCDFN(putsxyofs_style)(xpos, ypos, s->line, s->style, s->width, | ||
324 | pf->height, s->offset); | ||
325 | LCDFN(update_viewport_rect)(xpos, ypos, current_vp->width - xpos, | ||
326 | pf->height); | ||
327 | } | ||
328 | LCDFN(set_viewport)(old_vp); | ||
329 | } | ||