summaryrefslogtreecommitdiff
path: root/apps/gui/line.c
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2014-01-12 01:30:26 +0100
committerThomas Martitz <kugel@rockbox.org>2014-01-12 01:34:06 +0100
commit488a1b983e1c2fac14de25aa781caf12628e53c8 (patch)
tree8d5b5b33e0c7eb9e5222b843f84c6b2d65d1a352 /apps/gui/line.c
parent656261bde1122612d1bf8ffc3c992c75a7fbc52e (diff)
downloadrockbox-488a1b983e1c2fac14de25aa781caf12628e53c8.tar.gz
rockbox-488a1b983e1c2fac14de25aa781caf12628e53c8.zip
put_line/scrolling: Make the scroll engine inform custom scrollers about start/stop of scrolling.
With the new lcd_putsxy_scroll_func() code can register custom scroll functions (put_line() makes use of that). In order for the custom scroller to be able to properly manage its userdata pointer (set via struct scrollinfo::userdata) the scroll engine must inform the scroller about start and stop of scrolling. To inform about start the lcd_scroll_* functions now return true when the line will scroll. To inform about stop the scroll engine calls into the scroller one last time, with the text set to NULL. put_line() can use this to release the userdata registered per scrolling line so that it can be recycled. This fixes that some scrolling lines became glitchy after some time because the userdata was recycled too early. Change-Id: Iff0a6ce2a4f9ae2bada1b8e62f4f5950224942a9
Diffstat (limited to 'apps/gui/line.c')
-rw-r--r--apps/gui/line.c49
1 files changed, 34 insertions, 15 deletions
diff --git a/apps/gui/line.c b/apps/gui/line.c
index d561f08c76..e2eb6f277b 100644
--- a/apps/gui/line.c
+++ b/apps/gui/line.c
@@ -50,18 +50,27 @@ static void style_line(struct screen *display, int x, int y, struct line_desc *l
50static void put_text(struct screen *display, int x, int y, struct line_desc *line, 50static void put_text(struct screen *display, int x, int y, struct line_desc *line,
51 const char *text, bool prevent_scroll, int text_skip_pixels); 51 const char *text, bool prevent_scroll, int text_skip_pixels);
52 52
53struct line_desc_scroll {
54 struct line_desc desc; /* must be first! */
55 bool used;
56};
57
58#define NOINLINE __attribute__ ((noinline))
53 59
54static struct line_desc *get_line_desc(void) 60struct line_desc_scroll *get_line_desc(void) NOINLINE;
61struct line_desc_scroll *get_line_desc(void)
55{ 62{
56 static struct line_desc lines[MAX_LINES]; 63 static struct line_desc_scroll lines[MAX_LINES];
57 static unsigned line_index; 64 static unsigned line_index;
58 struct line_desc *ret; 65 struct line_desc_scroll *this;
59 66
60 ret = &lines[line_index++]; 67 do {
61 if (line_index >= ARRAYLEN(lines)) 68 this = &lines[line_index++];
62 line_index = 0; 69 if (line_index >= ARRAYLEN(lines))
70 line_index = 0;
71 } while (this->used);
63 72
64 return ret; 73 return this;
65} 74}
66 75
67static void scroller(struct scrollinfo *s, struct screen *display) 76static void scroller(struct scrollinfo *s, struct screen *display)
@@ -72,9 +81,17 @@ static void scroller(struct scrollinfo *s, struct screen *display)
72 * line padding. this needs to be corrected for calling style_line(). 81 * line padding. this needs to be corrected for calling style_line().
73 * The alternative would be to really redraw only the text area, 82 * The alternative would be to really redraw only the text area,
74 * but that would complicate the code a lot */ 83 * but that would complicate the code a lot */
75 struct line_desc *line = s->userdata; 84 struct line_desc_scroll *line = s->userdata;
76 style_line(display, s->x, s->y - (line->height/2 - display->getcharheight()/2), line); 85 if (!s->line)
77 put_text(display, s->x, s->y, line, s->line, true, s->offset); 86 {
87 line->used = false;
88 }
89 else
90 if (s->line)
91 {
92 style_line(display, s->x, s->y - (line->desc.height/2 - display->getcharheight()/2), &line->desc);
93 put_text(display, s->x, s->y, &line->desc, s->line, true, s->offset);
94 }
78} 95}
79 96
80static void scroller_main(struct scrollinfo *s) 97static void scroller_main(struct scrollinfo *s)
@@ -126,14 +143,16 @@ static void put_text(struct screen *display,
126 143
127 if (line->scroll && !prevent_scroll) 144 if (line->scroll && !prevent_scroll)
128 { 145 {
129 struct line_desc *line_data = get_line_desc(); 146 bool scrolls;
130 *line_data = *line; 147 struct line_desc_scroll *line_data = get_line_desc();
148 line_data->desc = *line;
131 /* precalculate to avoid doing it in the scroller, it's save to 149 /* precalculate to avoid doing it in the scroller, it's save to
132 * do this on the copy of the original line_desc*/ 150 * do this on the copy of the original line_desc*/
133 if (line_data->height == -1) 151 if (line_data->desc.height == -1)
134 line_data->height = display->getcharheight(); 152 line_data->desc.height = display->getcharheight();
135 display->putsxy_scroll_func(x, y, text, 153 scrolls = display->putsxy_scroll_func(x, y, text,
136 scrollers[display->screen_type], line_data, text_skip_pixels); 154 scrollers[display->screen_type], line_data, text_skip_pixels);
155 line_data->used = scrolls;
137 } 156 }
138 else 157 else
139 display->putsxy_scroll_func(x, y, text, NULL, NULL, text_skip_pixels); 158 display->putsxy_scroll_func(x, y, text, NULL, NULL, text_skip_pixels);