summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/gui/skin_engine/skin_render.c9
-rw-r--r--apps/screen_access.c4
-rw-r--r--apps/screen_access.h2
-rw-r--r--firmware/drivers/lcd-bitmap-common.c180
-rw-r--r--firmware/drivers/lcd-scroll.c111
-rw-r--r--firmware/export/scroll_engine.h30
-rw-r--r--firmware/scroll_engine.c19
7 files changed, 201 insertions, 154 deletions
diff --git a/apps/gui/skin_engine/skin_render.c b/apps/gui/skin_engine/skin_render.c
index 67f1f0f448..28483cbc49 100644
--- a/apps/gui/skin_engine/skin_render.c
+++ b/apps/gui/skin_engine/skin_render.c
@@ -779,7 +779,9 @@ void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps,
779 if (refresh_type && needs_update) 779 if (refresh_type && needs_update)
780 { 780 {
781 if (info.force_redraw) 781 if (info.force_redraw)
782 display->scroll_stop_viewport_line(&skin_viewport->vp, info.line_number); 782 display->scroll_stop_viewport_rect(&skin_viewport->vp,
783 0, info.line_number*display->getcharheight(),
784 skin_viewport->vp.width, display->getcharheight());
783 write_line(display, align, info.line_number, 785 write_line(display, align, info.line_number,
784 info.line_scrolls, info.text_style); 786 info.line_scrolls, info.text_style);
785 } 787 }
@@ -967,8 +969,11 @@ void skin_render_playlistviewer(struct playlistviewer* viewer,
967 /* only update if the line needs to be, and there is something to write */ 969 /* only update if the line needs to be, and there is something to write */
968 if (refresh_type && needs_update) 970 if (refresh_type && needs_update)
969 { 971 {
972 struct viewport *vp = SKINOFFSETTOPTR(skin_buffer, viewer->vp);
970 if (!info.force_redraw) 973 if (!info.force_redraw)
971 display->scroll_stop_viewport_line(&skin_viewport->vp, info.line_number); 974 display->scroll_stop_viewport_rect(vp,
975 0, info.line_number*display->getcharheight(),
976 vp->width, display->getcharheight());
972 write_line(display, align, info.line_number, 977 write_line(display, align, info.line_number,
973 info.line_scrolls, info.text_style); 978 info.line_scrolls, info.text_style);
974 } 979 }
diff --git a/apps/screen_access.c b/apps/screen_access.c
index 161e596aa2..f454e0adef 100644
--- a/apps/screen_access.c
+++ b/apps/screen_access.c
@@ -247,9 +247,9 @@ struct screen screens[NB_SCREENS] =
247 .scroll_delay=&lcd_scroll_delay, 247 .scroll_delay=&lcd_scroll_delay,
248 .clear_display=&lcd_clear_display, 248 .clear_display=&lcd_clear_display,
249 .clear_viewport=&lcd_clear_viewport, 249 .clear_viewport=&lcd_clear_viewport,
250 .scroll_stop_viewport_rect=&lcd_scroll_stop_viewport_rect,
250 .scroll_stop=&lcd_scroll_stop, 251 .scroll_stop=&lcd_scroll_stop,
251 .scroll_stop_viewport=&lcd_scroll_stop_viewport, 252 .scroll_stop_viewport=&lcd_scroll_stop_viewport,
252 .scroll_stop_viewport_line=&lcd_scroll_stop_viewport_line,
253 .update=&lcd_update, 253 .update=&lcd_update,
254 .update_viewport=&lcd_update_viewport, 254 .update_viewport=&lcd_update_viewport,
255 .backlight_on=&backlight_on, 255 .backlight_on=&backlight_on,
@@ -348,9 +348,9 @@ struct screen screens[NB_SCREENS] =
348 .scroll_delay=&lcd_remote_scroll_delay, 348 .scroll_delay=&lcd_remote_scroll_delay,
349 .clear_display=&lcd_remote_clear_display, 349 .clear_display=&lcd_remote_clear_display,
350 .clear_viewport=&lcd_remote_clear_viewport, 350 .clear_viewport=&lcd_remote_clear_viewport,
351 .scroll_stop_viewport_rect=&lcd_remote_scroll_stop_viewport_rect,
351 .scroll_stop=&lcd_remote_scroll_stop, 352 .scroll_stop=&lcd_remote_scroll_stop,
352 .scroll_stop_viewport=&lcd_remote_scroll_stop_viewport, 353 .scroll_stop_viewport=&lcd_remote_scroll_stop_viewport,
353 .scroll_stop_viewport_line=&lcd_remote_scroll_stop_viewport_line,
354 .update=&lcd_remote_update, 354 .update=&lcd_remote_update,
355 .update_viewport=&lcd_remote_update_viewport, 355 .update_viewport=&lcd_remote_update_viewport,
356 .backlight_on=&remote_backlight_on, 356 .backlight_on=&remote_backlight_on,
diff --git a/apps/screen_access.h b/apps/screen_access.h
index 448437c637..90b63ea338 100644
--- a/apps/screen_access.h
+++ b/apps/screen_access.h
@@ -149,7 +149,7 @@ struct screen
149 void (*clear_viewport)(void); 149 void (*clear_viewport)(void);
150 void (*scroll_stop)(void); 150 void (*scroll_stop)(void);
151 void (*scroll_stop_viewport)(const struct viewport *vp); 151 void (*scroll_stop_viewport)(const struct viewport *vp);
152 void (*scroll_stop_viewport_line)(const struct viewport *vp, int line); 152 void (*scroll_stop_viewport_rect)(const struct viewport* vp, int x, int y, int width, int height);
153 void (*update)(void); 153 void (*update)(void);
154 void (*update_viewport)(void); 154 void (*update_viewport)(void);
155 void (*backlight_on)(void); 155 void (*backlight_on)(void);
diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c
index c04f57ef22..f3e700a4a1 100644
--- a/firmware/drivers/lcd-bitmap-common.c
+++ b/firmware/drivers/lcd-bitmap-common.c
@@ -412,12 +412,10 @@ static void LCDFN(putsxyofs_style)(int xpos, int ypos,
412 412
413/*** Line oriented text output ***/ 413/*** Line oriented text output ***/
414 414
415/* put a string at a given char position */
416void LCDFN(puts_style_xyoffset)(int x, int y, const unsigned char *str, 415void LCDFN(puts_style_xyoffset)(int x, int y, const unsigned char *str,
417 int style, int x_offset, int y_offset) 416 int style, int x_offset, int y_offset)
418{ 417{
419 int xpos, ypos, h; 418 int xpos, ypos, h;
420 LCDFN(scroll_stop_viewport_line)(current_vp, y);
421 if(!str) 419 if(!str)
422 return; 420 return;
423 421
@@ -425,14 +423,15 @@ void LCDFN(puts_style_xyoffset)(int x, int y, const unsigned char *str,
425 if ((style&STYLE_XY_PIXELS) == 0) 423 if ((style&STYLE_XY_PIXELS) == 0)
426 { 424 {
427 xpos = x * LCDFN(getstringsize)(" ", NULL, NULL); 425 xpos = x * LCDFN(getstringsize)(" ", NULL, NULL);
428 ypos = y * h + y_offset; 426 ypos = y * h;
429 } 427 }
430 else 428 else
431 { 429 {
432 xpos = x; 430 xpos = x;
433 ypos = y + y_offset; 431 ypos = y;
434 } 432 }
435 LCDFN(putsxyofs_style)(xpos, ypos, str, style, h, x_offset); 433 LCDFN(scroll_stop_viewport_rect)(current_vp, x, y, current_vp->width - x, h);
434 LCDFN(putsxyofs_style)(xpos, ypos+y_offset, str, style, h, x_offset);
436} 435}
437 436
438void LCDFN(puts_style_offset)(int x, int y, const unsigned char *str, 437void LCDFN(puts_style_offset)(int x, int y, const unsigned char *str,
@@ -469,7 +468,7 @@ void LCDFN(puts_offset)(int x, int y, const unsigned char *str, int offset)
469 468
470/*** scrolling ***/ 469/*** scrolling ***/
471 470
472static struct scrollinfo* find_scrolling_line(int line) 471static struct scrollinfo* find_scrolling_line(int x, int y)
473{ 472{
474 struct scrollinfo* s = NULL; 473 struct scrollinfo* s = NULL;
475 int i; 474 int i;
@@ -477,93 +476,101 @@ static struct scrollinfo* find_scrolling_line(int line)
477 for(i=0; i<LCDFN(scroll_info).lines; i++) 476 for(i=0; i<LCDFN(scroll_info).lines; i++)
478 { 477 {
479 s = &LCDFN(scroll_info).scroll[i]; 478 s = &LCDFN(scroll_info).scroll[i];
480 if (s->y == line && s->vp == current_vp) 479 if (s->x == x && s->y == y && s->vp == current_vp)
481 return s; 480 return s;
482 } 481 }
483 return NULL; 482 return NULL;
484} 483}
485 484
486void LCDFN(puts_scroll_style_xyoffset)(int x, int y, const unsigned char *string, 485void LCDFN(scroll_fn)(struct scrollinfo* s)
487 int style, int x_offset, int y_offset) 486{
487 LCDFN(putsxyofs_style)(s->x, s->y, s->line, s->style, s->height, s->offset);
488}
489
490static void LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string,
491 int style, int x_offset, int y_offset,
492 bool linebased,
493 void (*scroll_func)(struct scrollinfo *),
494 void *data)
488{ 495{
489 struct scrollinfo* s; 496 struct scrollinfo* s;
490 char *end; 497 int width, height;
491 int w, h; 498 int w, h, cwidth, margin;
492 int len; 499 bool restart;
493 bool restart = false;
494 int space_width;
495 500
496 if (!string || ((unsigned)y >= (unsigned)current_vp->height)) 501 if (!string)
497 return; 502 return;
498 503
499 s = find_scrolling_line(y); 504 /* prepare rectangle for scrolling. x and y must be calculated early
500 if (!s) 505 * for find_scrolling_line() to work */
501 restart = true; 506 cwidth = font_get(current_vp->font)->maxwidth;
507 height = current_vp->line_height ?: (int)font_get(current_vp->font)->height;
508 y = y * (linebased ? height : 1) + y_offset;
509 x = x * (linebased ? cwidth : 1);
510 width = current_vp->width - x;
502 511
503 if (restart) 512 if (y >= current_vp->height)
504 { 513 return;
514
515 s = find_scrolling_line(x, y);
516 restart = !s;
517
518 if (restart) {
505 /* remove any previously scrolling line at the same location */ 519 /* remove any previously scrolling line at the same location */
506 LCDFN(scroll_stop_viewport_line)(current_vp, y); 520 LCDFN(scroll_stop_viewport_rect)(current_vp, x, y, width, height);
521 LCDFN(putsxyofs_style)(x, y, string, style, height, x_offset);
507 522
508 if (LCDFN(scroll_info).lines >= LCDM(SCROLLABLE_LINES)) return; 523 if (LCDFN(scroll_info).lines >= LCDM(SCROLLABLE_LINES))
509 LCDFN(puts_style_xyoffset)(x, y, string, style, x_offset, y_offset); 524 return;
510 } 525 }
511 526
527 /* get width (pixeks) of the string */
512 LCDFN(getstringsize)(string, &w, &h); 528 LCDFN(getstringsize)(string, &w, &h);
513 529
514 if (current_vp->width - x * 8 >= w) 530 /* check if scrolling is actually necessary (consider the actual start
531 * of the line) */
532 margin = x * linebased ? cwidth : 1;
533 if (current_vp->width >= margin+w)
515 return; 534 return;
516 535
517 if (restart) 536 if (restart) {
518 {
519 /* prepare scroll line */ 537 /* prepare scroll line */
520 s = &LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines]; 538 s = &LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines];
521 s->start_tick = current_tick + LCDFN(scroll_info).delay; 539 s->start_tick = current_tick + LCDFN(scroll_info).delay;
522 } 540 }
523 strlcpy(s->line, string, sizeof s->line);
524 space_width = LCDFN(getstringsize)(" ", NULL, NULL);
525 541
526 /* get width */ 542 /* copy contents to the line buffer */
527 LCDFN(getstringsize)(s->line, &w, &h); 543 strlcpy(s->linebuffer, string, sizeof(s->linebuffer));
528 if (!restart && s->width > w) 544 /* scroll bidirectional or forward only depending on the string width */
529 {
530 if (s->startx > w)
531 s->startx = w;
532 }
533 s->width = w;
534
535 /* scroll bidirectional or forward only depending on the string
536 width */
537 if ( LCDFN(scroll_info).bidir_limit ) { 545 if ( LCDFN(scroll_info).bidir_limit ) {
538 s->bidir = s->width < (current_vp->width) * 546 s->bidir = w < (current_vp->width) *
539 (100 + LCDFN(scroll_info).bidir_limit) / 100; 547 (100 + LCDFN(scroll_info).bidir_limit) / 100;
540 } 548 }
541 else 549 else
542 s->bidir = false; 550 s->bidir = false;
543 551
544 if (!s->bidir) { /* add spaces if scrolling in the round */ 552 s->scroll_func = scroll_func;
545 strlcat(s->line, " ", sizeof s->line); 553 s->userdata = data;
546 /* get new width incl. spaces */
547 s->width += space_width * 3;
548 }
549
550 end = strchr(s->line, '\0');
551 len = sizeof s->line - (end - s->line);
552 strlcpy(end, string, MIN(current_vp->width/2, len));
553 554
554 s->vp = current_vp; 555 if (restart) {
555 s->y = y;
556 if (restart)
557 {
558 s->offset = x_offset; 556 s->offset = x_offset;
559 s->startx = x * space_width;
560 s->backward = false; 557 s->backward = false;
561 s->style = style; 558 s->style = style;
559 /* assign the rectangle. not necessary if continuing an earlier line */
560 s->x = x;
561 s->y = y;
562 s->width = width;
563 s->height = height;
564 s->vp = current_vp;
565 LCDFN(scroll_info).lines++;
562 } 566 }
563 s->y_offset = y_offset; 567}
564 568
565 if (restart) 569void LCDFN(puts_scroll_style_xyoffset)(int x, int y, const unsigned char *string,
566 LCDFN(scroll_info).lines++; 570 int style, int x_offset, int y_offset)
571{
572 LCDFN(puts_scroll_worker)(x, y, string, style, x_offset, y_offset,
573 true, LCDFN(scroll_fn), NULL);
567} 574}
568 575
569void LCDFN(puts_scroll)(int x, int y, const unsigned char *string) 576void LCDFN(puts_scroll)(int x, int y, const unsigned char *string)
@@ -583,65 +590,6 @@ void LCDFN(puts_scroll_offset)(int x, int y, const unsigned char *string,
583 LCDFN(puts_scroll_style_offset)(x, y, string, STYLE_DEFAULT, offset); 590 LCDFN(puts_scroll_style_offset)(x, y, string, STYLE_DEFAULT, offset);
584} 591}
585 592
586void LCDFN(scroll_fn)(void)
587{
588 struct scrollinfo* s;
589 int index;
590 int xpos, ypos, height;
591 struct viewport* old_vp = current_vp;
592 bool makedelay;
593
594 for ( index = 0; index < LCDFN(scroll_info).lines; index++ ) {
595 s = &LCDFN(scroll_info).scroll[index];
596
597 /* check pause */
598 if (TIME_BEFORE(current_tick, s->start_tick))
599 continue;
600
601 LCDFN(set_viewport)(s->vp);
602 height = s->vp->line_height ?: (int)font_get(s->vp->font)->height;
603
604 if (s->backward)
605 s->offset -= LCDFN(scroll_info).step;
606 else
607 s->offset += LCDFN(scroll_info).step;
608
609 xpos = s->startx;
610 ypos = s->y * height + s->y_offset;
611
612 makedelay = false;
613 if (s->bidir) { /* scroll bidirectional */
614 if (s->offset <= 0) {
615 /* at beginning of line */
616 s->offset = 0;
617 s->backward = false;
618 makedelay = true;
619 }
620 else if (s->offset >= s->width - (current_vp->width - xpos)) {
621 /* at end of line */
622 s->offset = s->width - (current_vp->width - xpos);
623 s->backward = true;
624 makedelay = true;
625 }
626 }
627 else {
628 /* scroll forward the whole time */
629 if (s->offset >= s->width) {
630 s->offset = 0;
631 makedelay = true;
632 }
633 }
634
635 if (makedelay)
636 s->start_tick = current_tick + LCDFN(scroll_info).delay +
637 LCDFN(scroll_info).ticks;
638
639 LCDFN(putsxyofs_style)(xpos, ypos, s->line, s->style, height, s->offset);
640 LCDFN(update_viewport_rect)(xpos, ypos, current_vp->width-xpos, height);
641 }
642 LCDFN(set_viewport)(old_vp);
643}
644
645void LCDFN(puts_scroll_style_offset)(int x, int y, const unsigned char *string, 593void LCDFN(puts_scroll_style_offset)(int x, int y, const unsigned char *string,
646 int style, int x_offset) 594 int style, int x_offset)
647{ 595{
diff --git a/firmware/drivers/lcd-scroll.c b/firmware/drivers/lcd-scroll.c
index ffd4663c79..31c2cf20b0 100644
--- a/firmware/drivers/lcd-scroll.c
+++ b/firmware/drivers/lcd-scroll.c
@@ -54,30 +54,27 @@ void LCDFN(scroll_stop)(void)
54 LCDFN(scroll_info).lines = 0; 54 LCDFN(scroll_info).lines = 0;
55} 55}
56 56
57/* Stop scrolling line y in the specified viewport, or all lines if y < 0 */ 57/* Clears scrolling lines that intersect with the area */
58void LCDFN(scroll_stop_viewport_line)(const struct viewport *current_vp, int line) 58void LCDFN(scroll_stop_viewport_rect)(const struct viewport *vp, int x, int y, int width, int height)
59{ 59{
60 int i = 0; 60 int i = 0;
61
62 while (i < LCDFN(scroll_info).lines) 61 while (i < LCDFN(scroll_info).lines)
63 { 62 {
64 struct viewport *vp = LCDFN(scroll_info).scroll[i].vp; 63 struct scrollinfo *s = &LCDFN(scroll_info).scroll[i];
65 if (((vp == current_vp)) && 64 /* check if the specified area crosses the viewport in some way */
66 ((line < 0) || (LCDFN(scroll_info).scroll[i].y == line))) 65 if (s->vp == vp
66 && (x < (s->x+s->width) && (x+width) >= s->x)
67 && (y < (s->y+s->height) && (y+height) >= s->y))
67 { 68 {
68 /* If i is not the last active line in the array, then move 69 /* If i is not the last active line in the array, then move
69 the last item to position i */ 70 the last item to position i. This compacts
71 the scroll array at the same time of removing the line */
70 if ((i + 1) != LCDFN(scroll_info).lines) 72 if ((i + 1) != LCDFN(scroll_info).lines)
71 { 73 {
72 LCDFN(scroll_info).scroll[i] = 74 LCDFN(scroll_info).scroll[i] =
73 LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines-1]; 75 LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines-1];
74 } 76 }
75 LCDFN(scroll_info).lines--; 77 LCDFN(scroll_info).lines--;
76
77 /* A line can only appear once, so we're done,
78 * unless we are clearing the whole viewport */
79 if (line >= 0)
80 return ;
81 } 78 }
82 else 79 else
83 { 80 {
@@ -87,9 +84,9 @@ void LCDFN(scroll_stop_viewport_line)(const struct viewport *current_vp, int lin
87} 84}
88 85
89/* Stop all scrolling lines in the specified viewport */ 86/* Stop all scrolling lines in the specified viewport */
90void LCDFN(scroll_stop_viewport)(const struct viewport *current_vp) 87void LCDFN(scroll_stop_viewport)(const struct viewport *vp)
91{ 88{
92 LCDFN(scroll_stop_viewport_line)(current_vp, -1); 89 LCDFN(scroll_stop_viewport_rect)(vp, 0, 0, vp->width, vp->height);
93} 90}
94 91
95void LCDFN(scroll_speed)(int speed) 92void LCDFN(scroll_speed)(int speed)
@@ -125,3 +122,89 @@ void LCDFN(jump_scroll_delay)(int ms)
125 LCDFN(scroll_info).jump_scroll_delay = ms / (HZ / 10); 122 LCDFN(scroll_info).jump_scroll_delay = ms / (HZ / 10);
126} 123}
127#endif 124#endif
125
126static void LCDFN(scroll_worker)(void)
127{
128 int index, width;
129 bool makedelay;
130 static char line_buf[SCROLL_LINE_SIZE];
131 bool is_default;
132 struct scroll_screen_info *si = &LCDFN(scroll_info);
133 struct scrollinfo *s;
134 struct viewport *vp;
135
136 unsigned fg_pattern, bg_pattern, drawmode;
137
138 for ( index = 0; index < si->lines; index++ ) {
139 s = &si->scroll[index];
140
141 /* check pause */
142 if (TIME_BEFORE(current_tick, s->start_tick))
143 continue;
144
145 s->start_tick = current_tick;
146
147 /* this runs out of the ui thread, thus we need to
148 * save and restore the current viewport since the ui thread
149 * is unaware of the swapped viewports. the vp must
150 * be switched early so that lcd_getstringsize() picks the
151 * correct font */
152 vp = LCDFN(get_viewport)(&is_default);
153 LCDFN(set_viewport)(s->vp);
154
155 width = LCDFN(getstringsize)(s->linebuffer, NULL, NULL);
156 makedelay = false;
157
158 if (s->backward)
159 s->offset -= si->step;
160 else
161 s->offset += si->step;
162
163 if (s->bidir) { /* scroll bidirectional */
164
165 s->line = s->linebuffer;
166 if (s->offset <= 0) {
167 /* at beginning of line */
168 s->offset = 0;
169 s->backward = false;
170 makedelay = true;
171 }
172 else if (s->offset >= width - (s->width - s->x)) {
173 /* at end of line */
174 s->offset = width - (s->width - s->x);
175 s->backward = true;
176 makedelay = true;
177 }
178 }
179 else {
180
181 snprintf(line_buf, sizeof(line_buf)-1, "%s%s%s",
182 s->linebuffer, " ", s->linebuffer);
183 s->line = line_buf;
184 width += LCDFN(getstringsize)(" ", NULL, NULL);
185 /* scroll forward the whole time */
186 if (s->offset >= width) {
187 s->offset = 0;
188 makedelay = true;
189 }
190 }
191
192 /* Stash and restore these three, so that the scroll_func
193 * can do whatever it likes without destroying the state */
194 fg_pattern = s->vp->fg_pattern;
195 bg_pattern = s->vp->bg_pattern;
196 drawmode = s->vp->drawmode;
197
198 s->scroll_func(s);
199 LCDFN(update_viewport_rect)(s->x, s->y, s->width, s->height);
200
201 s->vp->fg_pattern = fg_pattern;
202 s->vp->bg_pattern = bg_pattern;
203 s->vp->drawmode = drawmode;
204
205 LCDFN(set_viewport)(vp);
206
207 if (makedelay)
208 s->start_tick += si->delay + si->ticks;
209 }
210}
diff --git a/firmware/export/scroll_engine.h b/firmware/export/scroll_engine.h
index 01a9a5e33d..c7eb97aecc 100644
--- a/firmware/export/scroll_engine.h
+++ b/firmware/export/scroll_engine.h
@@ -37,19 +37,19 @@ extern void lcd_scroll_delay(int ms);
37 37
38extern void lcd_scroll_stop(void); 38extern void lcd_scroll_stop(void);
39extern void lcd_scroll_stop_viewport(const struct viewport *vp); 39extern void lcd_scroll_stop_viewport(const struct viewport *vp);
40extern void lcd_scroll_stop_viewport_line(const struct viewport *vp, int line); 40extern void lcd_scroll_stop_viewport_rect(const struct viewport *vp, int x, int y, int width, int height);
41extern void lcd_scroll_fn(void);
42#ifdef HAVE_REMOTE_LCD 41#ifdef HAVE_REMOTE_LCD
43extern void lcd_remote_scroll_speed(int speed); 42extern void lcd_remote_scroll_speed(int speed);
44extern void lcd_remote_scroll_delay(int ms); 43extern void lcd_remote_scroll_delay(int ms);
45 44
46extern void lcd_remote_scroll_stop(void); 45extern void lcd_remote_scroll_stop(void);
47extern void lcd_remote_scroll_stop_viewport(const struct viewport *vp); 46extern void lcd_remote_scroll_stop_viewport(const struct viewport *vp);
48extern void lcd_remote_scroll_stop_viewport_line(const struct viewport *vp, int line); 47extern void lcd_remote_scroll_stop_viewport_rect(const struct viewport *vp, int x, int y, int width, int height);
49extern void lcd_remote_scroll_fn(void);
50#endif 48#endif
51 49
52/* internal usage, but in multiple drivers */ 50/* internal usage, but in multiple drivers
51 * larger than the normal linebuffer since it holds the line a second
52 * time (+3 spaces) for non-bidir scrolling */
53#define SCROLL_SPACING 3 53#define SCROLL_SPACING 3
54#ifdef HAVE_LCD_BITMAP 54#ifdef HAVE_LCD_BITMAP
55#define SCROLL_LINE_SIZE (MAX_PATH + SCROLL_SPACING + 3*LCD_WIDTH/2 + 2) 55#define SCROLL_LINE_SIZE (MAX_PATH + SCROLL_SPACING + 3*LCD_WIDTH/2 + 2)
@@ -60,21 +60,27 @@ extern void lcd_remote_scroll_fn(void);
60struct scrollinfo 60struct scrollinfo
61{ 61{
62 struct viewport* vp; 62 struct viewport* vp;
63 char line[SCROLL_LINE_SIZE]; 63 char linebuffer[9*MAX_PATH/10];
64 const char *line;
64#ifdef HAVE_LCD_CHARCELLS 65#ifdef HAVE_LCD_CHARCELLS
65 int len; /* length of line in chars */ 66 int len; /* length of line in chars */
66#endif 67#endif
67 int y; /* Position of the line on the screen (char co-ordinates) */ 68 /* rectangle for the line */
69 int x, y; /* relative to the viewort */
70 int width, height;
71 /* pixel to skip from the beginning of the string, increments as the text scrolls */
68 int offset; 72 int offset;
69 int startx;
70 int y_offset; /* y offset of the line, used for pixel-accurate list scrolling */
71#ifdef HAVE_LCD_BITMAP 73#ifdef HAVE_LCD_BITMAP
72 int width; /* length of line in pixels */
73 int style; /* line style */ 74 int style; /* line style */
74#endif/* HAVE_LCD_BITMAP */ 75#endif /* HAVE_LCD_BITMAP */
75 bool backward; /* scroll presently forward or backward? */ 76 /* scroll presently forward or backward? */
77 bool backward;
76 bool bidir; 78 bool bidir;
77 long start_tick; 79 long start_tick;
80
81 /* support for custom scrolling functions */
82 void (*scroll_func)(struct scrollinfo *s);
83 void *userdata;
78}; 84};
79 85
80struct scroll_screen_info 86struct scroll_screen_info
diff --git a/firmware/scroll_engine.c b/firmware/scroll_engine.c
index d134f7b2ce..d1bc2976a1 100644
--- a/firmware/scroll_engine.c
+++ b/firmware/scroll_engine.c
@@ -23,6 +23,7 @@
23 * 23 *
24 ****************************************************************************/ 24 ****************************************************************************/
25 25
26#include <stdio.h>
26#include "config.h" 27#include "config.h"
27#include "gcc_extensions.h" 28#include "gcc_extensions.h"
28#include "cpu.h" 29#include "cpu.h"
@@ -36,16 +37,20 @@
36#endif 37#endif
37#include "scroll_engine.h" 38#include "scroll_engine.h"
38 39
40
41/* private helper function for the scroll engine. Do not use in apps/.
42 * defined in lcd-bitmap-common.c */
43extern struct viewport *lcd_get_viewport(bool *is_defaut);
44#ifdef HAVE_REMOTE_LCD
45extern struct viewport *lcd_remote_get_viewport(bool *is_defaut);
46#endif
47
39static const char scroll_tick_table[18] = { 48static const char scroll_tick_table[18] = {
40 /* Hz values [f(x)=100.8/(x+.048)]: 49 /* Hz values [f(x)=100.8/(x+.048)]:
41 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33, 49.2, 96.2 */ 50 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33, 49.2, 96.2 */
42 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3, 2, 1 51 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3, 2, 1
43}; 52};
44 53
45/* imported private functions from lcd-bitmap-common.c */
46extern struct viewport *lcd_get_viewport(void);
47extern struct viewport *lcd_remote_get_viewport(void);
48
49static void scroll_thread(void); 54static void scroll_thread(void);
50static char scroll_stack[DEFAULT_STACK_SIZE*3]; 55static char scroll_stack[DEFAULT_STACK_SIZE*3];
51static const char scroll_name[] = "scroll"; 56static const char scroll_name[] = "scroll";
@@ -156,7 +161,7 @@ static void scroll_thread(void)
156#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 161#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
157 if (lcd_active()) 162 if (lcd_active())
158#endif 163#endif
159 lcd_scroll_fn(); 164 lcd_scroll_worker();
160 lcd_scroll_info.last_scroll = current_tick; 165 lcd_scroll_info.last_scroll = current_tick;
161 } 166 }
162 167
@@ -165,7 +170,7 @@ static void scroll_thread(void)
165 170
166 if (scroll & SCROLL_LCD_REMOTE) 171 if (scroll & SCROLL_LCD_REMOTE)
167 { 172 {
168 lcd_remote_scroll_fn(); 173 lcd_remote_scroll_worker();
169 lcd_remote_scroll_info.last_scroll = current_tick; 174 lcd_remote_scroll_info.last_scroll = current_tick;
170 } 175 }
171 } 176 }
@@ -179,7 +184,7 @@ static void scroll_thread(void)
179#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 184#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
180 if (lcd_active()) 185 if (lcd_active())
181#endif 186#endif
182 lcd_scroll_fn(); 187 lcd_scroll_worker();
183 } 188 }
184} 189}
185#endif /* HAVE_REMOTE_LCD */ 190#endif /* HAVE_REMOTE_LCD */