Put decoder array into IRAM. Improves Coldfire (h300) performance 218MHz ->102.84...
[kugel-rb.git] / apps / gui / scrollbar.c
blob67bf60de3fc7d6cebb6e3d8dd7b1d752bd2d3458
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) Markus Braun (2002)
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "scrollbar.h"
23 #ifdef HAVE_LCD_BITMAP
24 #include "config.h"
25 #include "limits.h"
26 #include "bmp.h"
28 /* calculates the start and size of the knob */
29 static void scrollbar_helper(int min_shown, int max_shown, int items,
30 int inner_len, int *size, int *start)
32 int min, max, range;
34 /* min should be min */
35 if(min_shown < max_shown) {
36 min = min_shown;
37 max = max_shown;
39 else {
40 min = max_shown;
41 max = min_shown;
44 /* limit min and max */
45 if(min < 0)
46 min = 0;
47 if(min > items)
48 min = items;
50 if(max < 0)
51 max = 0;
52 if(max > items)
53 max = items;
55 range = max - min;
57 /* avoid overflows */
58 while (items > (INT_MAX / inner_len)) {
59 items >>= 1;
60 range >>= 1;
63 /* calc start and end of the knob */
64 if (items > 0 && items > range) {
65 *size = inner_len * range / items;
66 if (*size == 0) { /* width of knob is null */
67 *size = 1;
68 *start = (inner_len - 1) * min / items;
69 } else {
70 *start = (inner_len - *size) * min / (items - range);
72 } else { /* if null draw full bar */
73 *size = inner_len;
74 *start = 0;
77 return;
80 void gui_scrollbar_draw(struct screen * screen, int x, int y,
81 int width, int height, int items,
82 int min_shown, int max_shown,
83 unsigned flags)
85 int inner_x, inner_y, inner_wd, inner_ht, inner_len;
86 int start, size;
87 #ifdef HAVE_LCD_COLOR
88 int infill;
89 #endif
91 inner_x = x + 1;
92 inner_y = y + 1;
93 inner_wd = width - 2;
94 inner_ht = height - 2;
96 /* Boundary check to make sure that height is reasonable, otherwise nothing
97 * to do
99 if ((inner_wd | inner_ht) < 0)
100 return;
102 if (flags & HORIZONTAL)
103 inner_len = inner_wd;
104 else
105 inner_len = inner_ht;
107 scrollbar_helper(min_shown, max_shown, items, inner_len, &size, &start);
109 /* draw box */
110 #ifdef HAVE_LCD_COLOR
111 /* must avoid corners if case of (flags & FOREGROUND) */
112 screen->hline(inner_x, x + inner_wd, y);
113 screen->hline(inner_x, x + inner_wd, y + height - 1);
114 screen->vline(x, inner_y, y + inner_ht);
115 screen->vline(x + width - 1, inner_y, y + inner_ht);
116 #else
117 screen->drawrect(x, y, width, height);
118 #endif
120 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
122 #ifdef HAVE_LCD_COLOR
123 infill = flags & (screen->depth > 1 ? INNER_FILL_MASK : INNER_FILL);
125 if (!(flags & FOREGROUND))
127 #endif
128 /* clear corner pixels */
129 screen->drawpixel(x, y);
130 screen->drawpixel(x + width - 1, y);
131 screen->drawpixel(x, y + height - 1);
132 screen->drawpixel(x + width - 1, y + height - 1);
134 #ifdef HAVE_LCD_COLOR
135 if (infill != INNER_BGFILL)
136 infill = INNER_FILL;
139 if (infill == INNER_FILL)
140 #endif
142 /* clear pixels in progress bar */
143 screen->fillrect(inner_x, inner_y, inner_wd, inner_ht);
146 screen->set_drawmode(DRMODE_SOLID);
148 #ifdef HAVE_LCD_COLOR
149 if (infill == INNER_BGFILL)
151 /* fill inner area with current background color */
152 unsigned fg = screen->get_foreground();
153 screen->set_foreground(screen->get_background());
154 screen->fillrect(inner_x, inner_y, inner_wd, inner_ht);
155 screen->set_foreground(fg);
157 #endif
159 if (flags & HORIZONTAL)
161 inner_x += start;
162 inner_wd = size;
164 else
166 inner_y += start;
167 inner_ht = size;
170 screen->fillrect(inner_x, inner_y, inner_wd, inner_ht);
173 void gui_bitmap_scrollbar_draw(struct screen * screen, struct bitmap bm, int x, int y,
174 int width, int height, int items,
175 int min_shown, int max_shown,
176 unsigned flags)
178 int start;
179 int size;
180 int inner_len;
182 screen->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
184 /* clear pixels in progress bar */
185 screen->fillrect(x, y, width, height);
187 if (flags & HORIZONTAL)
188 inner_len = width;
189 else
190 inner_len = height;
192 scrollbar_helper(min_shown, max_shown, items, inner_len, &size, &start);
194 screen->set_drawmode(DRMODE_SOLID);
196 if (flags & HORIZONTAL) {
197 x += start;
198 width = size;
199 } else {
200 y += start;
201 height = size;
204 #if LCD_DEPTH > 1
205 if (bm.format == FORMAT_MONO)
206 #endif
207 screen->mono_bitmap_part(bm.data, 0, 0,
208 bm.width, x, y, width, height);
209 #if LCD_DEPTH > 1
210 else
211 screen->transparent_bitmap_part((fb_data *)bm.data, 0, 0,
212 STRIDE(screen->screen_type,
213 bm.width, bm.height),
214 x, y, width, height);
215 #endif
218 void show_busy_slider(struct screen *s, int x, int y, int width, int height)
220 static int start = 0, dir = 1;
221 gui_scrollbar_draw(s, x, y, width, height, 100,
222 start, start+20, HORIZONTAL);
223 #if NB_SCREENS > 1
224 if (s->screen_type == SCREEN_MAIN)
225 #endif
227 start += (dir*2);
228 if (start > 79)
229 dir = -1;
230 else if (start < 1)
231 dir = 1;
235 #endif /* HAVE_LCD_BITMAP */