summaryrefslogtreecommitdiff
path: root/firmware/drivers/lcd-scroll.c
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 /firmware/drivers/lcd-scroll.c
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
Diffstat (limited to 'firmware/drivers/lcd-scroll.c')
-rw-r--r--firmware/drivers/lcd-scroll.c111
1 files changed, 97 insertions, 14 deletions
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}