Move c/h files implementing/defining standard library stuff into a new libc directory...
[kugel-rb.git] / apps / plugins / lib / grey_scroll.c
blob35f73b70c40511d17f4c62dab668da1bc5575afc
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * New greyscale framework
11 * Scrolling routines
13 * This is a generic framework to display 129 shades of grey on low-depth
14 * bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins.
16 * Copyright (C) 2008 Jens Arnold
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
24 * KIND, either express or implied.
26 ****************************************************************************/
28 #include "plugin.h"
29 #include "grey.h"
31 /*** Scrolling ***/
33 /* Scroll left */
34 void grey_scroll_left(int count)
36 unsigned char *data, *data_end;
37 int length, blank;
39 if ((unsigned)count >= (unsigned)_grey_info.width)
41 grey_clear_display();
42 return;
45 data = _grey_info.buffer;
46 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height);
47 length = _grey_info.width - count;
48 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
49 _grey_info.fg_brightness : _grey_info.bg_brightness;
53 rb->memmove(data, data + count, length);
54 data += length;
55 rb->memset(data, blank, count);
56 data += count;
58 while (data < data_end);
61 /* Scroll right */
62 void grey_scroll_right(int count)
64 unsigned char *data, *data_end;
65 int length, blank;
67 if ((unsigned)count >= (unsigned)_grey_info.width)
69 grey_clear_display();
70 return;
73 data = _grey_info.buffer;
74 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height);
75 length = _grey_info.width - count;
76 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
77 _grey_info.fg_brightness : _grey_info.bg_brightness;
81 rb->memmove(data + count, data, length);
82 rb->memset(data, blank, count);
83 data += _grey_info.width;
85 while (data < data_end);
88 /* Scroll up */
89 void grey_scroll_up(int count)
91 long shift, length;
92 int blank;
94 if ((unsigned)count >= (unsigned)_grey_info.height)
96 grey_clear_display();
97 return;
100 shift = _GREY_MULUQ(_grey_info.width, count);
101 length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count);
102 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
103 _grey_info.fg_brightness : _grey_info.bg_brightness;
105 rb->memmove(_grey_info.buffer, _grey_info.buffer + shift,
106 length);
107 rb->memset(_grey_info.buffer + length, blank, shift);
110 /* Scroll down */
111 void grey_scroll_down(int count)
113 long shift, length;
114 int blank;
116 if ((unsigned)count >= (unsigned)_grey_info.height)
118 grey_clear_display();
119 return;
122 shift = _GREY_MULUQ(_grey_info.width, count);
123 length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count);
124 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ?
125 _grey_info.fg_brightness : _grey_info.bg_brightness;
127 rb->memmove(_grey_info.buffer + shift, _grey_info.buffer,
128 length);
129 rb->memset(_grey_info.buffer, blank, shift);
132 /*** Unbuffered scrolling functions ***/
134 /* Scroll left */
135 void grey_ub_scroll_left(int count)
137 unsigned char *data, *data_end;
138 int blank, length;
140 if ((unsigned)count >= (unsigned)_grey_info.width)
142 grey_ub_clear_display();
143 return;
146 data = _grey_info.values;
147 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height);
148 length = (_grey_info.width - count) << _GREY_BSHIFT;
149 count <<= _GREY_BSHIFT;
150 blank = _grey_info.gvalue[(_grey_info.drawmode & DRMODE_INVERSEVID) ?
151 _grey_info.fg_brightness :
152 _grey_info.bg_brightness];
155 rb->memmove(data, data + count, length);
156 data += length;
157 rb->memset(data, blank, count);
158 data += count;
160 while (data < data_end);
161 #ifdef SIMULATOR
162 rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y,
163 _grey_info.width, _grey_info.height);
164 #endif
167 /* Scroll right */
168 void grey_ub_scroll_right(int count)
170 unsigned char *data, *data_end;
171 int blank, length;
173 if ((unsigned)count >= (unsigned)_grey_info.width)
175 grey_ub_clear_display();
176 return;
179 data = _grey_info.values;
180 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height);
181 length = (_grey_info.width - count) << _GREY_BSHIFT;
182 count <<= _GREY_BSHIFT;
183 blank = _grey_info.gvalue[(_grey_info.drawmode & DRMODE_INVERSEVID) ?
184 _grey_info.fg_brightness :
185 _grey_info.bg_brightness];
188 rb->memmove(data + count, data, length);
189 rb->memset(data, blank, count);
190 data += _grey_info.width << _GREY_BSHIFT;
192 while (data < data_end);
193 #ifdef SIMULATOR
194 rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y,
195 _grey_info.width, _grey_info.height);
196 #endif
199 /* Scroll up */
200 void grey_ub_scroll_up(int count)
202 unsigned char *dst, *end, *src;
203 int blank;
205 if ((unsigned)count >= (unsigned)_grey_info.height)
207 grey_ub_clear_display();
208 return;
211 dst = _grey_info.values;
212 end = dst + _GREY_MULUQ(_grey_info.height, _grey_info.width);
213 blank = _grey_info.gvalue[(_grey_info.drawmode & DRMODE_INVERSEVID) ?
214 _grey_info.fg_brightness :
215 _grey_info.bg_brightness];
217 #if (LCD_PIXELFORMAT == VERTICAL_PACKING) \
218 || (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
219 if (count & _GREY_BMASK)
221 /* Scrolling by fractional blocks - move pixel wise. */
222 unsigned char *line_end;
223 int ys, yd;
225 for (ys = count, yd = 0; ys < _grey_info.height; ys++, yd++)
227 dst = _grey_info.values
228 + _GREY_MULUQ(_grey_info.width, yd & ~_GREY_BMASK)
229 + (~yd & _GREY_BMASK);
230 src = _grey_info.values
231 + _GREY_MULUQ(_grey_info.width, ys & ~_GREY_BMASK)
232 + (~ys & _GREY_BMASK);
233 line_end = dst + _grey_info.width * _GREY_BSIZE;
237 *dst = *src;
238 dst += _GREY_BSIZE;
239 src += _GREY_BSIZE;
241 while (dst < line_end);
243 for (; yd & _GREY_BMASK; yd++) /* Fill remainder of current block. */
245 dst = _grey_info.values
246 + _GREY_MULUQ(_grey_info.width, yd & ~_GREY_BMASK)
247 + (~yd & _GREY_BMASK);
248 line_end = dst + _grey_info.width * _GREY_BSIZE;
252 *dst = blank;
253 dst += _GREY_BSIZE;
255 while (dst < line_end);
258 else
259 #endif
261 int blen = _GREY_MULUQ(_grey_info.height - count, _grey_info.width);
263 src = dst + _GREY_MULUQ(count, _grey_info.width);
264 rb->memmove(dst, src, blen);
265 dst += blen;
267 rb->memset(dst, blank, end - dst); /* Fill remainder at once. */
268 #ifdef SIMULATOR
269 rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y,
270 _grey_info.width, _grey_info.height);
271 #endif
274 /* Scroll down */
275 void grey_ub_scroll_down(int count)
277 unsigned char *start, *dst;
278 int blank;
280 if ((unsigned)count >= (unsigned)_grey_info.height)
282 grey_ub_clear_display();
283 return;
286 start = _grey_info.values;
287 dst = start + _GREY_MULUQ(_grey_info.height, _grey_info.width);
288 blank = _grey_info.gvalue[(_grey_info.drawmode & DRMODE_INVERSEVID) ?
289 _grey_info.fg_brightness :
290 _grey_info.bg_brightness];
292 #if (LCD_PIXELFORMAT == VERTICAL_PACKING) \
293 || (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
294 if (count & _GREY_BMASK)
296 /* Scrolling by fractional blocks - move pixel wise. */
297 unsigned char *src, *line_end;
298 int ys, yd;
300 yd = _grey_info.height - 1;
301 for (ys = yd - count; ys >= 0; ys--, yd--)
303 dst = _grey_info.values
304 + _GREY_MULUQ(_grey_info.width, yd & ~_GREY_BMASK)
305 + (~yd & _GREY_BMASK);
306 src = _grey_info.values
307 + _GREY_MULUQ(_grey_info.width, ys & ~_GREY_BMASK)
308 + (~ys & _GREY_BMASK);
309 line_end = dst + _grey_info.width * _GREY_BSIZE;
313 *dst = *src;
314 dst += _GREY_BSIZE;
315 src += _GREY_BSIZE;
317 while (dst < line_end);
319 for (; ~yd & _GREY_BMASK; yd--) /* Fill remainder of current block. */
321 dst = _grey_info.values
322 + _GREY_MULUQ(_grey_info.width, yd & ~_GREY_BMASK)
323 + (~yd & _GREY_BMASK);
324 line_end = dst + _grey_info.width * _GREY_BSIZE;
328 line_end -= _GREY_BSIZE;
329 *line_end = blank;
331 while (dst < line_end);
333 /* Top pixel in a block has the highest address, but dst must point
334 * to the lowest address in that block for the subsequent fill. */
335 dst -= _GREY_BMASK;
337 else
338 #endif
340 int blen = _GREY_MULUQ(_grey_info.height - count, _grey_info.width);
342 dst -= blen;
343 rb->memmove(dst, start, blen);
345 rb->memset(start, blank, dst - start);
346 /* Fill remainder at once. */
347 #ifdef SIMULATOR
348 rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y,
349 _grey_info.width, _grey_info.height);
350 #endif