Manual: Fix part 1 of FS#11874 - touchscreen region in the manual isn't 100% correct.
[kugel-rb.git] / apps / plugins / clock / clock_draw_analog.c
blobb8ec308eedfffd96a68834b3552dd791db8df5b1
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Copyright Kévin Ferrare based on Zakk Roberts's work
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 "clock_draw_analog.h"
23 #include "lib/xlcd.h"
24 #include "lib/fixedpoint.h"
25 #include "clock_bitmaps.h"
26 #include "clock_bitmap_strings.h"
28 #define ANALOG_SECOND_RADIUS(screen, round) \
29 ANALOG_MINUTE_RADIUS(screen, round)
30 #define ANALOG_MINUTE_RADIUS(screen, round) \
31 (round?MIN(screen->getheight()/2 -10, screen->getwidth()/2 -10):screen->getheight()/2)
32 #define ANALOG_HOUR_RADIUS(screen, round) \
33 (2*ANALOG_MINUTE_RADIUS(screen, round)/3)
35 #define HOUR_ANGLE(hour, minute, second) (30*(hour) +(minute)/2)
36 #define MINUTE_ANGLE(minute, second) (6*(minute)+(second)/10)
37 #define SECOND_ANGLE(second) (6 * (second))
39 /* Note that the given angle's origin is midday and not 3 o'clock */
40 void polar_to_cartesian(int a, int r, int* x, int* y)
42 #if CONFIG_LCD == LCD_SSD1815
43 /* Correct non-square pixel aspect of archos recorder LCD */
44 *x = (fp14_sin(a) * 5 / 4 * r) >> 14;
45 #else
46 *x = (fp14_sin(a) * r) >> 14;
47 #endif
48 *y = (fp14_sin(a-90) * r) >> 14;
51 void polar_to_cartesian_screen_centered(struct screen * display,
52 int a, int r, int* x, int* y)
54 polar_to_cartesian(a, r, x, y);
55 *x+=display->getwidth()/2;
56 *y+=display->getheight()/2;
59 void angle_to_square(int square_width, int square_height,
60 int a, int* x, int* y)
62 a = (a+360-90)%360;
63 if(a>45 && a<=135){/* top line */
64 a-=45;
65 *x=square_width-(square_width*2*a)/90;
66 *y=square_height;
67 }else if(a>135 && a<=225){/* left line */
68 a-=135;
69 *x=-square_width;
70 *y=square_height-(square_height*2*a)/90;
71 }else if(a>225 && a<=315){/* bottom line */
72 a-=225;
73 *x=(square_width*2*a)/90-square_width;
74 *y=-square_height;
75 }else if(a>315 || a<=45){/* right line */
76 if(a>315)
77 a-=315;
78 else
79 a+=45;
80 *x=square_width;
81 *y=(square_height*2*a)/90-square_height;
85 void angle_to_square_screen_centered(struct screen * display,
86 int square_width, int square_height,
87 int a, int* x, int* y)
89 angle_to_square(square_width, square_height, a, x, y);
90 *x+=display->getwidth()/2;
91 *y+=display->getheight()/2;
94 void draw_hand(struct screen* display, int angle,
95 int radius, int thickness, bool round)
97 int x1, y1; /* the longest */
98 int x2, y2, x3, y3; /* the base */
99 if(round){/* round clock */
100 polar_to_cartesian_screen_centered(display, angle, radius, &x1, &y1);
101 }else{/* fullscreen clock, hands describes square motions */
102 int square_width, square_height;
103 /* radius is defined smallest between getwidth() and getheight() */
104 square_height=radius;
105 square_width=(radius*display->getwidth())/display->getheight();
106 angle_to_square_screen_centered(
107 display, square_width, square_height, angle, &x1, &y1);
109 polar_to_cartesian_screen_centered(display, (angle+120)%360,
110 radius/40+thickness, &x2, &y2);
111 polar_to_cartesian_screen_centered(display, (angle+240)%360,
112 radius/40+thickness, &x3, &y3);
113 xlcd_filltriangle_screen(display, x1, y1, x2, y2, x3, y3);
114 rb->lcd_drawline(x1, y1, x2, y2);
115 rb->lcd_drawline(x1, y1, x3, y3);
118 void draw_hands(struct screen* display, int hour, int minute, int second,
119 int thickness, bool round, bool draw_seconds)
121 if(draw_seconds){
122 draw_hand(display, SECOND_ANGLE(second),
123 ANALOG_SECOND_RADIUS(display, round), thickness, round);
125 draw_hand(display, MINUTE_ANGLE(minute, second),
126 ANALOG_MINUTE_RADIUS(display, round), thickness+2, round);
127 draw_hand(display, HOUR_ANGLE(hour, minute, second),
128 ANALOG_HOUR_RADIUS(display, round), thickness+2, round);
131 void draw_counter(struct screen* display, struct counter* counter)
133 char buffer[10];
134 int second_str_w, hour_str_w, str_h;
135 const struct picture* smalldigits_bitmaps =
136 &(smalldigits[display->screen_type]);
137 struct time counter_time;
138 counter_get_elapsed_time(counter, &counter_time);
139 rb->snprintf(buffer, 10, "%02d:%02d",
140 counter_time.hour, counter_time.minute);
141 getstringsize(smalldigits_bitmaps, buffer, &hour_str_w, &str_h);
142 draw_string(display, smalldigits_bitmaps, buffer,
143 display->getwidth()-hour_str_w,
144 display->getheight()-2*str_h);
146 rb->snprintf(buffer, 10, "%02d", counter_time.second);
147 getstringsize(smalldigits_bitmaps, buffer, &second_str_w, &str_h);
148 draw_string(display, smalldigits_bitmaps, buffer,
149 display->getwidth()-(hour_str_w+second_str_w)/2,
150 display->getheight()-str_h);
153 void draw_date(struct screen* display, struct time* time, int date_format)
155 char buffer[10];
156 int year_str_w, monthday_str_w, str_h;
157 int year_line=date_format==JAPANESE?1:2;
158 int monthday_line=date_format==JAPANESE?2:1;
159 const struct picture* smalldigits_bitmaps =
160 &(smalldigits[display->screen_type]);
161 if(date_format==ENGLISH || date_format==JAPANESE){
162 rb->snprintf(buffer, 10, "%02d/%02d", time->month, time->day);
163 }else{
164 rb->snprintf(buffer, 10, "%02d/%02d", time->day, time->month);
166 /* draws month and day */
167 getstringsize(smalldigits_bitmaps, buffer, &monthday_str_w, &str_h);
168 draw_string(display, smalldigits_bitmaps, buffer,
169 0, display->getheight()-year_line*str_h);
170 rb->snprintf(buffer, 10, "%04d", time->year);
172 /* draws year */
173 getstringsize(smalldigits_bitmaps, buffer, &year_str_w, &str_h);
174 draw_string(display, smalldigits_bitmaps, buffer,
175 (monthday_str_w-year_str_w)/2,
176 display->getheight()-monthday_line*str_h);
179 void draw_border(struct screen* display, int skin)
181 /* Draws square dots every 5 minutes */
182 int i;
183 int x, y;
184 int size=display->getheight()/50;/* size of the square dots */
185 if(size%2)/* a pair number */
186 size++;
187 for(i=0; i < 60; i+=5){
188 if(skin){
189 polar_to_cartesian_screen_centered(display, MINUTE_ANGLE(i, 0),
190 ANALOG_MINUTE_RADIUS(display, skin), &x, &y);
191 }else{
192 angle_to_square_screen_centered(
193 display, display->getwidth()/2-size/2, display->getheight()/2-size/2,
194 MINUTE_ANGLE(i, 0), &x, &y);
196 display->fillrect(x-size/2, y-size/2, size, size);
200 void draw_hour(struct screen* display, struct time* time,
201 bool show_seconds, int skin)
203 int hour=time->hour;
204 if(hour >= 12)
205 hour -= 12;
207 /* Crappy fake antialiasing (color LCDs only)!
208 * how this works is we draw a large mid-gray hr/min/sec hand,
209 * then the actual (slightly smaller) hand on top of those.
210 * End result: mid-gray edges to the black hands, smooths them out. */
211 #ifdef HAVE_LCD_COLOR
212 if(display->is_color){
213 display->set_foreground(LCD_RGBPACK(100,110,125));
214 draw_hands(display, hour, time->minute, time->second,
215 1, skin, show_seconds);
216 display->set_foreground(LCD_BLACK);
218 #endif
219 draw_hands(display, hour, time->minute, time->second,
220 0, skin, show_seconds);
223 void draw_center_cover(struct screen* display)
225 display->hline((display->getwidth()/2)-1,
226 (display->getwidth()/2)+1, (display->getheight()/2)+3);
227 display->hline((display->getwidth()/2)-3,
228 (display->getwidth()/2)+3, (display->getheight()/2)+2);
229 display->fillrect((display->getwidth()/2)-4, (display->getheight()/2)-1, 9, 3);
230 display->hline((display->getwidth()/2)-3,
231 (display->getwidth()/2)+3, (display->getheight()/2)-2);
232 display->hline((display->getwidth()/2)-1,
233 (display->getwidth()/2)+1, (display->getheight()/2)-3);
236 void analog_clock_draw(struct screen* display, struct time* time,
237 struct clock_settings* settings,
238 struct counter* counter,
239 int skin)
242 draw_hour(display, time, settings->analog.show_seconds, skin);
243 if(settings->analog.show_border)
244 draw_border(display, skin);
245 if(counter)
246 draw_counter(display, counter);
247 if(settings->analog.show_date && settings->general.date_format!=NONE)
248 draw_date(display, time, settings->general.date_format);
249 draw_center_cover(display);