summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2013-01-31 07:24:19 +0100
committerThomas Martitz <kugel@rockbox.org>2013-12-14 23:11:31 +0100
commit50eb528bc1f9d2f7b7260eff8b85a5ed5b96e679 (patch)
tree47b53d62c0880a3ea6b9e761efdf0628855d13e0
parent26801b3bd8f11fe680146086aa0a2fd12e7de289 (diff)
downloadrockbox-50eb528bc1f9d2f7b7260eff8b85a5ed5b96e679.tar.gz
rockbox-50eb528bc1f9d2f7b7260eff8b85a5ed5b96e679.zip
scroll_engine: Major rework to support pixel-based scrolling and scroll callbacks.
Much of the scrolling work is moved from lcd-bitmap-common to lcd-scroll.c, a small scroll callback routine remains. This callback can potentially be overridden by more extensive scrollers. The callback also gets fed with pixel-based scrolling information, which finally removes the strict line-based nature of the scroll engine. Along with this is the change from scroll_stop_viewport_line() to scroll_stop_viewport_rect() which works on a pixel-based rectangle instead of lines. The ultimate goal is to move most of the scroll work to apps, which can much better decide which line decorations to apply etc. This work is laying the ground work. Change-Id: I3b2885cf7d8696ddd9253d5a9a73318d3d42831a
-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 */