diff options
Diffstat (limited to 'apps/gui/color_picker.c')
-rw-r--r-- | apps/gui/color_picker.c | 386 |
1 files changed, 273 insertions, 113 deletions
diff --git a/apps/gui/color_picker.c b/apps/gui/color_picker.c index 1217fcd08c..06653976a6 100644 --- a/apps/gui/color_picker.c +++ b/apps/gui/color_picker.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "kernel.h" | 23 | #include "kernel.h" |
24 | #include "system.h" | 24 | #include "system.h" |
25 | #include "screen_access.h" | 25 | #include "screen_access.h" |
26 | #include "font.h" | ||
26 | #include "debug.h" | 27 | #include "debug.h" |
27 | #include "misc.h" | 28 | #include "misc.h" |
28 | #include "settings.h" | 29 | #include "settings.h" |
@@ -31,115 +32,291 @@ | |||
31 | #include "splash.h" | 32 | #include "splash.h" |
32 | #include "action.h" | 33 | #include "action.h" |
33 | 34 | ||
34 | #define TEXT_MARGIN display->char_width+2 | 35 | /* structure for color info */ |
35 | #define SLIDER_START 20 | 36 | struct rgb_pick |
37 | { | ||
38 | unsigned color; /* native color value */ | ||
39 | union | ||
40 | { | ||
41 | unsigned char rgb_val[6]; /* access to components as array */ | ||
42 | struct | ||
43 | { | ||
44 | unsigned char r; /* native red value */ | ||
45 | unsigned char g; /* native green value */ | ||
46 | unsigned char b; /* native blue value */ | ||
47 | unsigned char red; /* 8 bit red value */ | ||
48 | unsigned char green; /* 8 bit green value */ | ||
49 | unsigned char blue; /* 8 bit blue value */ | ||
50 | } __attribute__ ((__packed__)); /* assume byte packing */ | ||
51 | }; | ||
52 | }; | ||
53 | |||
54 | /* maximum values for components */ | ||
55 | static const unsigned char max_val[3] = | ||
56 | { | ||
57 | LCD_MAX_RED, | ||
58 | LCD_MAX_GREEN, | ||
59 | LCD_MAX_BLUE | ||
60 | }; | ||
61 | |||
62 | /* list of primary colors */ | ||
63 | static const unsigned prim_rgb[3] = | ||
64 | { | ||
65 | LCD_RGBPACK(255, 0, 0), | ||
66 | LCD_RGBPACK(0, 255, 0), | ||
67 | LCD_RGBPACK(0, 0 ,255), | ||
68 | }; | ||
69 | |||
70 | /* Unpacks the color value into native rgb values and 24 bit rgb values */ | ||
71 | static void unpack_rgb(struct rgb_pick *rgb) | ||
72 | { | ||
73 | unsigned color = rgb->color; | ||
74 | #if LCD_PIXELFORMAT == RGB565SWAPPED | ||
75 | swap16(color); | ||
76 | #endif | ||
77 | rgb->r = (color & 0xf800) >> 11; | ||
78 | rgb->g = (color & 0x07e0) >> 5; | ||
79 | rgb->b = (color & 0x001f); | ||
80 | rgb->red = _RGB_UNPACK_RED(color); | ||
81 | rgb->green = _RGB_UNPACK_GREEN(color); | ||
82 | rgb->blue = _RGB_UNPACK_BLUE(color); | ||
83 | } | ||
36 | 84 | ||
37 | static const int max_val[3] = {LCD_MAX_RED,LCD_MAX_GREEN,LCD_MAX_BLUE}; | 85 | /* Packs the native rgb colors into a color value */ |
86 | static void pack_rgb(struct rgb_pick *rgb) | ||
87 | { | ||
88 | unsigned color = (rgb->r & 0x1f) << 11 | | ||
89 | (rgb->g & 0x3f) << 5 | | ||
90 | (rgb->b & 0x1f); | ||
91 | #if LCD_PIXELFORMAT == RGB565SWAPPED | ||
92 | swap16(color); | ||
93 | #endif | ||
94 | rgb->color = color; | ||
95 | } | ||
96 | |||
97 | /* Returns LCD_BLACK if the color is above a threshold brightness | ||
98 | else return LCD_WHITE */ | ||
99 | static inline unsigned get_black_or_white(const struct rgb_pick *rgb) | ||
100 | { | ||
101 | return (4*rgb->r + 5*rgb->g + 2*rgb->b) >= 256 ? | ||
102 | LCD_BLACK : LCD_WHITE; | ||
103 | } | ||
104 | |||
105 | #define MARGIN_LEFT 2 /* Left margin of screen */ | ||
106 | #define MARGIN_TOP 4 /* Top margin of screen */ | ||
107 | #define MARGIN_RIGHT 2 /* Right margin of screen */ | ||
108 | #define MARGIN_BOTTOM 4 /* Bottom margin of screen */ | ||
109 | #define SLIDER_MARGIN_LEFT 2 /* Gap to left of sliders */ | ||
110 | #define SLIDER_MARGIN_RIGHT 2 /* Gap to right of sliders */ | ||
111 | #define TITLE_MARGIN_BOTTOM 4 /* Space below title bar */ | ||
112 | #define SELECTOR_LR_MARGIN 1 /* Margin between ">" and text */ | ||
113 | #define SELECTOR_TB_MARGIN 1 /* Margin on top and bottom of selector */ | ||
114 | #define SWATCH_TOP_MARGIN 4 /* Space between last slider and swatch */ | ||
115 | |||
116 | /* dunno why lcd_set_drawinfo should be left out of struct screen */ | ||
117 | static void set_drawinfo(struct screen *display, int mode, | ||
118 | unsigned foreground, unsigned background) | ||
119 | { | ||
120 | display->set_drawmode(mode); | ||
121 | if (display->depth > 1) | ||
122 | { | ||
123 | display->set_foreground(foreground); | ||
124 | display->set_background(background); | ||
125 | } | ||
126 | } | ||
38 | 127 | ||
39 | static void draw_screen(struct screen *display, char *title, | 128 | static void draw_screen(struct screen *display, char *title, |
40 | int *rgb_val, int color, int row) | 129 | struct rgb_pick *rgb, int row) |
41 | { | 130 | { |
42 | int i; | 131 | unsigned text_color = LCD_BLACK; |
43 | char *textrgb = str(LANG_COLOR_RGB_LABELS), rgb_dummy[2] = {0,0}; | 132 | unsigned background_color = LCD_WHITE; |
44 | int text_top; | 133 | char buf[32]; |
45 | int text_centre, bg_col; | 134 | int i, x, y; |
46 | char buf[32]; | 135 | int text_top; |
47 | int slider_width = (display->width-SLIDER_START-(display->char_width*5)); | 136 | int slider_left, slider_width; |
48 | int background_color = global_settings.bg_color; | 137 | bool display_three_rows; |
49 | int text_color = global_settings.fg_color; | 138 | int max_label_width; |
50 | bool display_three_rows = (display->height/6) > display->char_height; | ||
51 | 139 | ||
52 | display->clear_display(); | 140 | display->clear_display(); |
53 | 141 | ||
54 | if (display->depth > 1) { | 142 | if (display->depth > 1) |
55 | display->set_foreground(text_color); | 143 | { |
144 | text_color = display->get_foreground(); | ||
145 | background_color = display->get_background(); | ||
56 | } | 146 | } |
57 | 147 | ||
58 | i = display->getstringsize(title,0,0); | 148 | /* Find out if there's enought room for three slider or just |
59 | display->putsxy((display->width-i)/2,6,title ); | 149 | enought to display the selected slider */ |
150 | display_three_rows = display->height >= display->char_height*4 + | ||
151 | MARGIN_TOP + | ||
152 | TITLE_MARGIN_BOTTOM + | ||
153 | MARGIN_BOTTOM; | ||
60 | 154 | ||
61 | text_top = display->char_height*2; | 155 | /* Figure out widest label character in case they vary */ |
62 | bg_col = background_color; | 156 | for (i = 0, max_label_width = 0; i < 3; i++) |
63 | for (i=0; i<3 ;i++) | ||
64 | { | 157 | { |
158 | buf[0] = str(LANG_COLOR_RGB_LABELS)[i]; | ||
159 | buf[1] = '\0'; | ||
160 | x = display->getstringsize(buf, NULL, NULL); | ||
161 | if (x > max_label_width) | ||
162 | max_label_width = x; | ||
163 | } | ||
164 | |||
165 | /* Draw title string */ | ||
166 | set_drawinfo(display, DRMODE_SOLID, text_color, background_color); | ||
167 | display->getstringsize(title, &x, &y); | ||
168 | display->putsxy((display->width - x) / 2, MARGIN_TOP, title); | ||
169 | |||
170 | /* Get slider positions and top starting position */ | ||
171 | text_top = MARGIN_TOP + y + TITLE_MARGIN_BOTTOM + SELECTOR_TB_MARGIN; | ||
172 | slider_left = MARGIN_LEFT + SELECTOR_LR_MARGIN + display->char_width + | ||
173 | max_label_width + SLIDER_MARGIN_LEFT; | ||
174 | slider_width = display->width - slider_left - SLIDER_MARGIN_RIGHT - | ||
175 | SELECTOR_LR_MARGIN - display->char_width*3 - MARGIN_RIGHT; | ||
176 | |||
177 | for (i = 0; i < 3; i++) | ||
178 | { | ||
179 | int mode = DRMODE_SOLID; | ||
180 | unsigned fg = text_color; | ||
181 | unsigned bg = background_color; | ||
182 | |||
65 | if (!display_three_rows) | 183 | if (!display_three_rows) |
66 | i = row; | 184 | i = row; |
67 | 185 | ||
68 | if (i==row) | 186 | if (i == row) |
69 | { | 187 | { |
70 | if ((global_settings.invert_cursor) && (display->depth >2)) | 188 | set_drawinfo(display, DRMODE_SOLID, text_color, |
189 | background_color); | ||
190 | |||
191 | if (global_settings.invert_cursor) | ||
71 | { | 192 | { |
72 | display->fillrect(0,text_top-1,display->width,display->char_height+2); | 193 | /* Draw solid bar selection bar */ |
73 | bg_col = text_color; | 194 | display->fillrect(0, |
195 | text_top - SELECTOR_TB_MARGIN, | ||
196 | display->width, | ||
197 | display->char_height + | ||
198 | SELECTOR_TB_MARGIN*2); | ||
199 | |||
200 | if (display->depth == 1) | ||
201 | { | ||
202 | /* Just invert for low mono display */ | ||
203 | mode |= DRMODE_INVERSEVID; | ||
204 | } | ||
205 | else | ||
206 | { | ||
207 | if (display->depth >= 16) | ||
208 | { | ||
209 | /* Backdrops will show through text in | ||
210 | DRMODE_SOLID */ | ||
211 | mode = DRMODE_FG; | ||
212 | fg = prim_rgb[i]; | ||
213 | } | ||
214 | else | ||
215 | { | ||
216 | fg = background_color; | ||
217 | } | ||
218 | |||
219 | bg = text_color; | ||
220 | } | ||
74 | } | 221 | } |
75 | else if (display_three_rows) | 222 | else if (display_three_rows) |
76 | { | 223 | { |
77 | display->putsxy(0,text_top,">"); | 224 | /* Draw "> <" around sliders */ |
78 | display->putsxy(display->width-display->char_width-2,text_top,"<"); | 225 | display->putsxy(MARGIN_LEFT, text_top, ">"); |
79 | bg_col = background_color; | 226 | display->putsxy(display->width-display->char_width - |
80 | } | 227 | MARGIN_RIGHT, text_top, "<"); |
81 | if (display->depth > 1) | 228 | if (display->depth >= 16) |
82 | { | 229 | fg = prim_rgb[i]; |
83 | if (i==0) | ||
84 | display->set_foreground(LCD_RGBPACK(255, 0, 0)); | ||
85 | else if (i==1) | ||
86 | display->set_foreground(LCD_RGBPACK(0, 255, 0)); | ||
87 | else if (i==2) | ||
88 | display->set_foreground(LCD_RGBPACK(0 ,0 ,255)); | ||
89 | } | 230 | } |
90 | } | 231 | } |
91 | else | 232 | |
92 | { | 233 | set_drawinfo(display, mode, fg, bg); |
93 | if (display->depth > 1) | 234 | |
94 | display->set_foreground(text_color); | 235 | /* Draw label - assumes labels are one character */ |
95 | bg_col = background_color; | 236 | buf[0] = str(LANG_COLOR_RGB_LABELS)[i]; |
96 | } | 237 | buf[1] = '\0'; |
238 | display->putsxy(slider_left - display->char_width - | ||
239 | SLIDER_MARGIN_LEFT, text_top, buf); | ||
97 | 240 | ||
98 | if (display->depth > 1) | 241 | /* Draw color value */ |
99 | display->set_background(bg_col); | 242 | snprintf(buf, 3, "%02d", rgb->rgb_val[i]); |
243 | display->putsxy(slider_left + slider_width + SLIDER_MARGIN_RIGHT, | ||
244 | text_top, buf); | ||
100 | 245 | ||
101 | text_centre = text_top+(display->char_height/2); | 246 | /* Draw scrollbar */ |
102 | rgb_dummy[0] = textrgb[i]; | 247 | gui_scrollbar_draw(display, |
103 | display->putsxy(TEXT_MARGIN,text_top,rgb_dummy); | 248 | slider_left, |
104 | snprintf(buf,3,"%02d",rgb_val[i]); | 249 | text_top + display->char_height / 4, |
105 | display->putsxy(display->width-(display->char_width*4),text_top,buf); | 250 | slider_width, |
251 | display->char_height / 2, | ||
252 | max_val[i], | ||
253 | 0, | ||
254 | rgb->rgb_val[i], | ||
255 | HORIZONTAL); | ||
106 | 256 | ||
107 | text_top += display->char_height/4; | 257 | /* Advance to next line */ |
258 | text_top += display->char_height + 2*SELECTOR_TB_MARGIN; | ||
108 | 259 | ||
109 | gui_scrollbar_draw(display,SLIDER_START,text_top,slider_width, | ||
110 | display->char_height/2, | ||
111 | max_val[i],0,rgb_val[i],HORIZONTAL); | ||
112 | if (!display_three_rows) | 260 | if (!display_three_rows) |
113 | break; | 261 | break; |
114 | text_top += display->char_height; | ||
115 | } | 262 | } |
116 | 263 | ||
117 | if (display->depth > 1) { | 264 | /* Format RGB: #rrggbb */ |
118 | display->set_background(background_color); | 265 | snprintf(buf, sizeof(buf), str(LANG_COLOR_RGB_VALUE), |
119 | display->set_foreground(text_color); | 266 | rgb->red, rgb->green, rgb->blue); |
120 | } | 267 | |
268 | if (display->depth >= 16) | ||
269 | { | ||
270 | /* Display color swatch on color screens only */ | ||
271 | int left = slider_left; | ||
272 | int top = text_top + SWATCH_TOP_MARGIN; | ||
273 | int width = display->width - slider_left - left; | ||
274 | int height = display->height - top - MARGIN_BOTTOM; | ||
121 | 275 | ||
122 | if (text_top + (display->char_height*2) < (display->height-40-display->char_height)) | 276 | display->setfont(FONT_SYSFIXED); |
123 | text_top += (display->char_height*2); | ||
124 | else text_top += (display->char_height); | ||
125 | 277 | ||
126 | /* Display RGB: #rrggbb */ | 278 | /* Only draw if room */ |
127 | snprintf(buf,sizeof(buf),str(LANG_COLOR_RGB_VALUE), | 279 | if (height >= display->char_height + 2) |
128 | RGB_UNPACK_RED(color), | 280 | { |
129 | RGB_UNPACK_GREEN(color), | 281 | display->set_foreground(rgb->color); |
130 | RGB_UNPACK_BLUE(color)); | 282 | display->fillrect(left, top, width, height); |
131 | 283 | ||
132 | display->putsxy((display->width-(display->char_width*11))/2,text_top,buf); | 284 | /* Draw RGB: #rrggbb in middle of swatch */ |
285 | display->set_drawmode(DRMODE_FG); | ||
286 | display->getstringsize(buf, &x, &y); | ||
287 | display->set_foreground(get_black_or_white(rgb)); | ||
133 | 288 | ||
134 | if (display->depth > 1) { | 289 | x = left + (width - x) / 2; |
135 | display->set_foreground(color); | 290 | y = top + (height - y) / 2; |
136 | display->fillrect(SLIDER_START,LCD_HEIGHT-40,slider_width,35); | ||
137 | 291 | ||
138 | display->set_foreground(LCD_BLACK); | 292 | display->putsxy(x, y, buf); |
139 | display->drawrect(SLIDER_START-1,LCD_HEIGHT-41,slider_width+2,37); | 293 | display->set_drawmode(DRMODE_SOLID); |
294 | |||
295 | /* Draw border */ | ||
296 | display->set_foreground(text_color); | ||
297 | display->drawrect(left - 1, top - 1, width + 2, height + 2); | ||
298 | } | ||
299 | |||
300 | display->setfont(FONT_UI); | ||
301 | } | ||
302 | else | ||
303 | { | ||
304 | /* Display RGB value only centered on remaining display if room */ | ||
305 | display->getstringsize(buf, &x, &y); | ||
306 | i = text_top + SWATCH_TOP_MARGIN; | ||
307 | |||
308 | if (i + y <= display->height - MARGIN_BOTTOM) | ||
309 | { | ||
310 | set_drawinfo(display, DRMODE_SOLID, text_color, background_color); | ||
311 | x = (display->width - x) / 2; | ||
312 | y = (i + display->height - MARGIN_BOTTOM - y) / 2; | ||
313 | display->putsxy(x, y, buf); | ||
314 | } | ||
140 | } | 315 | } |
141 | 316 | ||
142 | display->update(); | 317 | display->update(); |
318 | /* Be sure screen mode is reset */ | ||
319 | set_drawinfo(display, DRMODE_SOLID, text_color, background_color); | ||
143 | } | 320 | } |
144 | 321 | ||
145 | /*********** | 322 | /*********** |
@@ -148,74 +325,59 @@ static void draw_screen(struct screen *display, char *title, | |||
148 | color is a pointer to the colour (in native format) to modify | 325 | color is a pointer to the colour (in native format) to modify |
149 | set banned_color to -1 to allow all | 326 | set banned_color to -1 to allow all |
150 | ***********/ | 327 | ***********/ |
151 | bool set_color(struct screen *display,char *title, int* color, int banned_color) | 328 | bool set_color(struct screen *display, char *title, int* color, int banned_color) |
152 | { | 329 | { |
153 | int exit = 0, button, slider=0; | 330 | int exit = 0, button, slider = 0; |
154 | int rgb_val[3]; /* native depth r,g,b*/; | ||
155 | int fgcolor = display->get_foreground(); | ||
156 | int newcolor = *color; | ||
157 | int i; | 331 | int i; |
332 | struct rgb_pick rgb; | ||
333 | (void)display; | ||
158 | 334 | ||
159 | #if LCD_PIXELFORMAT == RGB565 | 335 | rgb.color = *color; |
160 | rgb_val[0] = ((*color)&0xf800) >> 11; | ||
161 | rgb_val[1] = ((*color)&0x07e0) >> 5; | ||
162 | rgb_val[2] = ((*color)&0x001f); | ||
163 | #elif LCD_PIXELFORMAT == RGB565SWAPPED | ||
164 | rgb_val[0] = ((swap16(*color))&0xf800) >> 11; | ||
165 | rgb_val[1] = ((swap16(*color))&0x07e0) >> 5; | ||
166 | rgb_val[2] = ((swap16(*color))&0x001f); | ||
167 | #endif | ||
168 | 336 | ||
169 | while (!exit) | 337 | while (!exit) |
170 | { | 338 | { |
171 | /* We need to maintain three versions of the colour: | 339 | unpack_rgb(&rgb); |
172 | |||
173 | rgb_val[3] - the native depth RGB values | ||
174 | newcolor - the native format packed colour | ||
175 | */ | ||
176 | 340 | ||
177 | #if LCD_PIXELFORMAT == RGB565 | ||
178 | newcolor = (rgb_val[0] << 11) | (rgb_val[1] << 5) | (rgb_val[2]); | ||
179 | #elif LCD_PIXELFORMAT == RGB565SWAPPED | ||
180 | newcolor = swap16((rgb_val[0] << 11) | (rgb_val[1] << 5) | (rgb_val[2])); | ||
181 | #endif | ||
182 | FOR_NB_SCREENS(i) | 341 | FOR_NB_SCREENS(i) |
183 | { | 342 | { |
184 | draw_screen(&screens[i], title, rgb_val, newcolor, slider); | 343 | draw_screen(&screens[i], title, &rgb, slider); |
185 | } | 344 | } |
186 | 345 | ||
187 | button = get_action(CONTEXT_SETTINGS_COLOURCHOOSER,TIMEOUT_BLOCK); | 346 | button = get_action(CONTEXT_SETTINGS_COLOURCHOOSER, TIMEOUT_BLOCK); |
347 | |||
188 | switch (button) | 348 | switch (button) |
189 | { | 349 | { |
190 | case ACTION_STD_PREV: | 350 | case ACTION_STD_PREV: |
191 | case ACTION_STD_PREVREPEAT: | 351 | case ACTION_STD_PREVREPEAT: |
192 | slider = (slider+2)%3; | 352 | slider = (slider + 2) % 3; |
193 | break; | 353 | break; |
194 | 354 | ||
195 | case ACTION_STD_NEXT: | 355 | case ACTION_STD_NEXT: |
196 | case ACTION_STD_NEXTREPEAT: | 356 | case ACTION_STD_NEXTREPEAT: |
197 | slider = (slider+1)%3; | 357 | slider = (slider + 1) % 3; |
198 | break; | 358 | break; |
199 | 359 | ||
200 | case ACTION_SETTINGS_INC: | 360 | case ACTION_SETTINGS_INC: |
201 | case ACTION_SETTINGS_INCREPEAT: | 361 | case ACTION_SETTINGS_INCREPEAT: |
202 | if (rgb_val[slider] < max_val[slider]) | 362 | if (rgb.rgb_val[slider] < max_val[slider]) |
203 | rgb_val[slider]++; | 363 | rgb.rgb_val[slider]++; |
364 | pack_rgb(&rgb); | ||
204 | break; | 365 | break; |
205 | 366 | ||
206 | case ACTION_SETTINGS_DEC: | 367 | case ACTION_SETTINGS_DEC: |
207 | case ACTION_SETTINGS_DECREPEAT: | 368 | case ACTION_SETTINGS_DECREPEAT: |
208 | if (rgb_val[slider] > 0) | 369 | if (rgb.rgb_val[slider] > 0) |
209 | rgb_val[slider]--; | 370 | rgb.rgb_val[slider]--; |
371 | pack_rgb(&rgb); | ||
210 | break; | 372 | break; |
211 | 373 | ||
212 | case ACTION_STD_OK: | 374 | case ACTION_STD_OK: |
213 | if ((banned_color!=-1) && (banned_color == newcolor)) | 375 | if (banned_color != -1 && (unsigned)banned_color == rgb.color) |
214 | { | 376 | { |
215 | gui_syncsplash(HZ*2,true,str(LANG_COLOR_UNACCEPTABLE)); | 377 | gui_syncsplash(HZ*2, true, str(LANG_COLOR_UNACCEPTABLE)); |
216 | break; | 378 | break; |
217 | } | 379 | } |
218 | *color = newcolor; | 380 | *color = rgb.color; |
219 | exit = 1; | 381 | exit = 1; |
220 | break; | 382 | break; |
221 | 383 | ||
@@ -224,14 +386,12 @@ bool set_color(struct screen *display,char *title, int* color, int banned_color) | |||
224 | break; | 386 | break; |
225 | 387 | ||
226 | default: | 388 | default: |
227 | if(default_event_handler(button) == SYS_USB_CONNECTED) { | 389 | if (default_event_handler(button) == SYS_USB_CONNECTED) |
228 | display->set_foreground(fgcolor); | ||
229 | return true; | 390 | return true; |
230 | } | ||
231 | break; | 391 | break; |
232 | } | 392 | } |
233 | } | 393 | } |
234 | display->set_foreground(fgcolor); | 394 | |
235 | action_signalscreenchange(); | 395 | action_signalscreenchange(); |
236 | return false; | 396 | return false; |
237 | } | 397 | } |