Philips GoGear SA9200 port. Working bootloader and normal builds, including sound...
[Rockbox.git] / apps / plugins / lib / xlcd_draw.c
blob506fe9987777e3ffa3ded28ac71423f982409cfc
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Additional LCD routines not present in the rockbox core
11 * Drawing functions
13 * Copyright (C) 2005 Jens Arnold
15 * All files in this archive are subject to the GNU General Public License.
16 * See the file COPYING in the source tree root for full license agreement.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
23 #include "plugin.h"
25 #ifdef HAVE_LCD_BITMAP
26 #include "xlcd.h"
28 /* sort the given coordinates by increasing x value */
29 static void sort_points_by_increasing_x(int* x1, int* y1,
30 int* x2, int* y2,
31 int* x3, int* y3)
33 int x, y;
34 if (*x1 > *x3)
36 if (*x2 < *x3) /* x2 < x3 < x1 */
38 x = *x1; *x1 = *x2; *x2 = *x3; *x3 = x;
39 y = *y1; *y1 = *y2; *y2 = *y3; *y3 = y;
41 else if (*x2 > *x1) /* x3 < x1 < x2 */
43 x = *x1; *x1 = *x3; *x3 = *x2; *x2 = x;
44 y = *y1; *y1 = *y3; *y3 = *y2; *y2 = y;
46 else /* x3 <= x2 <= x1 */
48 x = *x1; *x1 = *x3; *x3 = x;
49 y = *y1; *y1 = *y3; *y3 = y;
52 else
54 if (*x2 < *x1) /* x2 < x1 <= x3 */
56 x = *x1; *x1 = *x2; *x2 = x;
57 y = *y1; *y1 = *y2; *y2 = y;
59 else if (*x2 > *x3) /* x1 <= x3 < x2 */
61 x = *x2; *x2 = *x3; *x3 = x;
62 y = *y2; *y2 = *y3; *y3 = y;
64 /* else already sorted */
68 #define sort_points_by_increasing_y(x1, y1, x2, y2, x3, y3) \
69 sort_points_by_increasing_x(y1, x1, y2, x2, y3, x3)
71 /* draw a filled triangle, using horizontal lines for speed */
72 static void xlcd_filltriangle_horizontal(struct screen* display,
73 int x1, int y1,
74 int x2, int y2,
75 int x3, int y3)
77 long fp_x1, fp_x2, fp_dx1, fp_dx2;
78 int y;
79 sort_points_by_increasing_y(&x1, &y1, &x2, &y2, &x3, &y3);
81 if (y1 < y3) /* draw */
83 fp_dx1 = ((x3 - x1) << 16) / (y3 - y1);
84 fp_x1 = (x1 << 16) + (1<<15) + (fp_dx1 >> 1);
86 if (y1 < y2) /* first part */
88 fp_dx2 = ((x2 - x1) << 16) / (y2 - y1);
89 fp_x2 = (x1 << 16) + (1<<15) + (fp_dx2 >> 1);
90 for (y = y1; y < y2; y++)
92 display->hline(fp_x1 >> 16, fp_x2 >> 16, y);
93 fp_x1 += fp_dx1;
94 fp_x2 += fp_dx2;
97 if (y2 < y3) /* second part */
99 fp_dx2 = ((x3 - x2) << 16) / (y3 - y2);
100 fp_x2 = (x2 << 16) + (1<<15) + (fp_dx2 >> 1);
101 for (y = y2; y < y3; y++)
103 display->hline(fp_x1 >> 16, fp_x2 >> 16, y);
104 fp_x1 += fp_dx1;
105 fp_x2 += fp_dx2;
111 /* draw a filled triangle, using vertical lines for speed */
112 static void xlcd_filltriangle_vertical(struct screen* display,
113 int x1, int y1,
114 int x2, int y2,
115 int x3, int y3)
117 long fp_y1, fp_y2, fp_dy1, fp_dy2;
118 int x;
119 sort_points_by_increasing_x(&x1, &y1, &x2, &y2, &x3, &y3);
121 if (x1 < x3) /* draw */
123 fp_dy1 = ((y3 - y1) << 16) / (x3 - x1);
124 fp_y1 = (y1 << 16) + (1<<15) + (fp_dy1 >> 1);
126 if (x1 < x2) /* first part */
128 fp_dy2 = ((y2 - y1) << 16) / (x2 - x1);
129 fp_y2 = (y1 << 16) + (1<<15) + (fp_dy2 >> 1);
130 for (x = x1; x < x2; x++)
132 display->vline(x, fp_y1 >> 16, fp_y2 >> 16);
133 fp_y1 += fp_dy1;
134 fp_y2 += fp_dy2;
137 if (x2 < x3) /* second part */
139 fp_dy2 = ((y3 - y2) << 16) / (x3 - x2);
140 fp_y2 = (y2 << 16) + (1<<15) + (fp_dy2 >> 1);
141 for (x = x2; x < x3; x++)
143 display->vline(x, fp_y1 >> 16, fp_y2 >> 16);
144 fp_y1 += fp_dy1;
145 fp_y2 += fp_dy2;
151 void xlcd_filltriangle(int x1, int y1,
152 int x2, int y2,
153 int x3, int y3)
155 /* default is main screen */
156 xlcd_filltriangle_screen(_xlcd_rb->screens[SCREEN_MAIN],
157 x1, y1, x2, y2, x3, y3);
160 void xlcd_filltriangle_screen(struct screen* display,
161 int x1, int y1,
162 int x2, int y2,
163 int x3, int y3)
165 if(display->pixel_format==HORIZONTAL_PACKING || display->depth>=8)
166 xlcd_filltriangle_horizontal(display, x1, y1, x2, y2, x3, y3);
167 else
168 xlcd_filltriangle_vertical(display, x1, y1, x2, y2, x3, y3);
171 #if LCD_DEPTH >= 8
173 #ifdef HAVE_LCD_COLOR
174 static const fb_data graylut[256] = {
175 #if LCD_PIXELFORMAT == RGB565
176 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0821, 0x0821, 0x0841,
177 0x0841, 0x0841, 0x0841, 0x0861, 0x0861, 0x1062, 0x1062, 0x1082,
178 0x1082, 0x1082, 0x1082, 0x10a2, 0x10a2, 0x18a3, 0x18a3, 0x18c3,
179 0x18c3, 0x18c3, 0x18c3, 0x18e3, 0x18e3, 0x20e4, 0x20e4, 0x2104,
180 0x2104, 0x2104, 0x2104, 0x2124, 0x2124, 0x2124, 0x2925, 0x2945,
181 0x2945, 0x2945, 0x2945, 0x2965, 0x2965, 0x2965, 0x3166, 0x3186,
182 0x3186, 0x3186, 0x3186, 0x31a6, 0x31a6, 0x31a6, 0x39a7, 0x39c7,
183 0x39c7, 0x39c7, 0x39c7, 0x39e7, 0x39e7, 0x39e7, 0x41e8, 0x4208,
184 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x4a29, 0x4a49,
185 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a,
186 0x528a, 0x528a, 0x528a, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x5aab,
187 0x5acb, 0x5acb, 0x5acb, 0x5acb, 0x5aeb, 0x5aeb, 0x5aeb, 0x62ec,
188 0x630c, 0x630c, 0x630c, 0x630c, 0x632c, 0x632c, 0x632c, 0x6b2d,
189 0x6b4d, 0x6b4d, 0x6b4d, 0x6b4d, 0x6b6d, 0x6b6d, 0x6b6d, 0x6b6d,
190 0x738e, 0x738e, 0x738e, 0x738e, 0x73ae, 0x73ae, 0x73ae, 0x73ae,
191 0x7bcf, 0x7bcf, 0x7bcf, 0x7bcf, 0x7bef, 0x7bef, 0x7bef, 0x7bef,
192 0x8410, 0x8410, 0x8410, 0x8410, 0x8430, 0x8430, 0x8430, 0x8430,
193 0x8c51, 0x8c51, 0x8c51, 0x8c51, 0x8c71, 0x8c71, 0x8c71, 0x8c71,
194 0x9492, 0x9492, 0x9492, 0x9492, 0x94b2, 0x94b2, 0x94b2, 0x94b2,
195 0x94d2, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cf3, 0x9cf3, 0x9cf3, 0x9cf3,
196 0x9d13, 0xa514, 0xa514, 0xa514, 0xa534, 0xa534, 0xa534, 0xa534,
197 0xa554, 0xad55, 0xad55, 0xad55, 0xad55, 0xad75, 0xad75, 0xad75,
198 0xad75, 0xb596, 0xb596, 0xb596, 0xb596, 0xb5b6, 0xb5b6, 0xb5b6,
199 0xb5b6, 0xb5d6, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdf7, 0xbdf7, 0xbdf7,
200 0xbdf7, 0xbe17, 0xc618, 0xc618, 0xc618, 0xc638, 0xc638, 0xc638,
201 0xc638, 0xc658, 0xce59, 0xce59, 0xce59, 0xce79, 0xce79, 0xce79,
202 0xce79, 0xce99, 0xd69a, 0xd69a, 0xd69a, 0xd6ba, 0xd6ba, 0xd6ba,
203 0xd6ba, 0xd6da, 0xd6da, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb,
204 0xdefb, 0xdf1b, 0xdf1b, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c,
205 0xe73c, 0xe75c, 0xe75c, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d,
206 0xef7d, 0xef9d, 0xef9d, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be,
207 0xf7be, 0xf7de, 0xf7de, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff
208 #elif LCD_PIXELFORMAT == RGB565SWAPPED
209 0x0000, 0x0000, 0x0000, 0x2000, 0x2000, 0x2108, 0x2108, 0x4108,
210 0x4108, 0x4108, 0x4108, 0x6108, 0x6108, 0x6210, 0x6210, 0x8210,
211 0x8210, 0x8210, 0x8210, 0xa210, 0xa210, 0xa318, 0xa318, 0xc318,
212 0xc318, 0xc318, 0xc318, 0xe318, 0xe318, 0xe420, 0xe420, 0x0421,
213 0x0421, 0x0421, 0x0421, 0x2421, 0x2421, 0x2421, 0x2529, 0x4529,
214 0x4529, 0x4529, 0x4529, 0x6529, 0x6529, 0x6529, 0x6631, 0x8631,
215 0x8631, 0x8631, 0x8631, 0xa631, 0xa631, 0xa631, 0xa739, 0xc739,
216 0xc739, 0xc739, 0xc739, 0xe739, 0xe739, 0xe739, 0xe841, 0x0842,
217 0x0842, 0x0842, 0x0842, 0x2842, 0x2842, 0x2842, 0x294a, 0x494a,
218 0x494a, 0x494a, 0x494a, 0x694a, 0x694a, 0x694a, 0x694a, 0x8a52,
219 0x8a52, 0x8a52, 0x8a52, 0xaa52, 0xaa52, 0xaa52, 0xaa52, 0xab5a,
220 0xcb5a, 0xcb5a, 0xcb5a, 0xcb5a, 0xeb5a, 0xeb5a, 0xeb5a, 0xec62,
221 0x0c63, 0x0c63, 0x0c63, 0x0c63, 0x2c63, 0x2c63, 0x2c63, 0x2d6b,
222 0x4d6b, 0x4d6b, 0x4d6b, 0x4d6b, 0x6d6b, 0x6d6b, 0x6d6b, 0x6d6b,
223 0x8e73, 0x8e73, 0x8e73, 0x8e73, 0xae73, 0xae73, 0xae73, 0xae73,
224 0xcf7b, 0xcf7b, 0xcf7b, 0xcf7b, 0xef7b, 0xef7b, 0xef7b, 0xef7b,
225 0x1084, 0x1084, 0x1084, 0x1084, 0x3084, 0x3084, 0x3084, 0x3084,
226 0x518c, 0x518c, 0x518c, 0x518c, 0x718c, 0x718c, 0x718c, 0x718c,
227 0x9294, 0x9294, 0x9294, 0x9294, 0xb294, 0xb294, 0xb294, 0xb294,
228 0xd294, 0xd39c, 0xd39c, 0xd39c, 0xf39c, 0xf39c, 0xf39c, 0xf39c,
229 0x139d, 0x14a5, 0x14a5, 0x14a5, 0x34a5, 0x34a5, 0x34a5, 0x34a5,
230 0x54a5, 0x55ad, 0x55ad, 0x55ad, 0x55ad, 0x75ad, 0x75ad, 0x75ad,
231 0x75ad, 0x96b5, 0x96b5, 0x96b5, 0x96b5, 0xb6b5, 0xb6b5, 0xb6b5,
232 0xb6b5, 0xd6b5, 0xd7bd, 0xd7bd, 0xd7bd, 0xf7bd, 0xf7bd, 0xf7bd,
233 0xf7bd, 0x17be, 0x18c6, 0x18c6, 0x18c6, 0x38c6, 0x38c6, 0x38c6,
234 0x38c6, 0x58c6, 0x59ce, 0x59ce, 0x59ce, 0x79ce, 0x79ce, 0x79ce,
235 0x79ce, 0x99ce, 0x9ad6, 0x9ad6, 0x9ad6, 0xbad6, 0xbad6, 0xbad6,
236 0xbad6, 0xdad6, 0xdad6, 0xdbde, 0xdbde, 0xfbde, 0xfbde, 0xfbde,
237 0xfbde, 0x1bdf, 0x1bdf, 0x1ce7, 0x1ce7, 0x3ce7, 0x3ce7, 0x3ce7,
238 0x3ce7, 0x5ce7, 0x5ce7, 0x5def, 0x5def, 0x7def, 0x7def, 0x7def,
239 0x7def, 0x9def, 0x9def, 0x9ef7, 0x9ef7, 0xbef7, 0xbef7, 0xbef7,
240 0xbef7, 0xdef7, 0xdef7, 0xdfff, 0xdfff, 0xffff, 0xffff, 0xffff
241 #endif /* LCD_PIXELFORMAT */
243 #endif /* HAVE_LCD_COLOR */
245 /* Draw a partial greyscale bitmap, canonical 8 bit format */
246 void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
247 int stride, int x, int y, int width, int height)
249 const unsigned char *src_end;
250 fb_data *dst;
252 /* nothing to draw? */
253 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
254 || (x + width <= 0) || (y + height <= 0))
255 return;
257 /* clipping */
258 if (x < 0)
260 width += x;
261 src_x -= x;
262 x = 0;
264 if (y < 0)
266 height += y;
267 src_y -= y;
268 y = 0;
270 if (x + width > LCD_WIDTH)
271 width = LCD_WIDTH - x;
272 if (y + height > LCD_HEIGHT)
273 height = LCD_HEIGHT - y;
275 src += stride * src_y + src_x; /* move starting point */
276 src_end = src + stride * height;
277 dst = _xlcd_rb->lcd_framebuffer + LCD_WIDTH * y + x;
281 const unsigned char *src_row = src;
282 const unsigned char *row_end = src_row + width;
283 fb_data *dst_row = dst;
285 #ifdef HAVE_LCD_COLOR
287 *dst_row++ = graylut[*src_row++];
288 while (src_row < row_end);
289 #endif
291 src += stride;
292 dst += LCD_WIDTH;
294 while (src < src_end);
297 /* Draw a full greyscale bitmap, canonical 8 bit format */
298 void xlcd_gray_bitmap(const unsigned char *src, int x, int y, int width,
299 int height)
301 xlcd_gray_bitmap_part(src, 0, 0, width, x, y, width, height);
304 #ifdef HAVE_LCD_COLOR
305 /* Draw a partial colour bitmap, canonical 24 bit RGB format */
306 void xlcd_color_bitmap_part(const unsigned char *src, int src_x, int src_y,
307 int stride, int x, int y, int width, int height)
309 const unsigned char *src_end;
310 fb_data *dst;
312 /* nothing to draw? */
313 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
314 || (x + width <= 0) || (y + height <= 0))
315 return;
317 /* clipping */
318 if (x < 0)
320 width += x;
321 src_x -= x;
322 x = 0;
324 if (y < 0)
326 height += y;
327 src_y -= y;
328 y = 0;
330 if (x + width > LCD_WIDTH)
331 width = LCD_WIDTH - x;
332 if (y + height > LCD_HEIGHT)
333 height = LCD_HEIGHT - y;
335 src += 3 * (stride * src_y + src_x); /* move starting point */
336 src_end = src + 3 * stride * height;
337 dst = _xlcd_rb->lcd_framebuffer + LCD_WIDTH * y + x;
341 const unsigned char *src_row = src;
342 const unsigned char *row_end = src_row + 3 * width;
343 fb_data *dst_row = dst;
346 { /* only RGB565 and RGB565SWAPPED so far */
347 unsigned red = 31 * (*src_row++) + 127;
348 unsigned green = 63 * (*src_row++) + 127;
349 unsigned blue = 31 * (*src_row++) + 127;
351 red = (red + (red >> 8)) >> 8; /* approx red /= 255: */
352 green = (green + (green >> 8)) >> 8; /* approx green /= 255: */
353 blue = (blue + (blue >> 8)) >> 8; /* approx blue /= 255: */
355 #if LCD_PIXELFORMAT == RGB565
356 *dst_row++ = (red << 11) | (green << 5) | blue;
357 #elif LCD_PIXELFORMAT == RGB565SWAPPED
358 *dst_row++ = swap16((red << 11) | (green << 5) | blue);
359 #endif
361 while (src_row < row_end);
363 src += 3 * stride;
364 dst += LCD_WIDTH;
366 while (src < src_end);
369 /* Draw a full colour bitmap, canonical 24 bit RGB format */
370 void xlcd_color_bitmap(const unsigned char *src, int x, int y, int width,
371 int height)
373 xlcd_color_bitmap_part(src, 0, 0, width, x, y, width, height);
375 #endif /* HAVE_LCD_COLOR */
377 #endif /* LCD_DEPTH >= 8 */
379 #endif /* HAVE_LCD_BITMAP */