FS#12756 by Marek Salaba - update Czech translation
[maemo-rb.git] / apps / plugins / lib / xlcd_draw.c
blob3be15718f6dd4f75b4f2584063f7d9dccbb0ff8a
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 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
25 #include "plugin.h"
27 #ifdef HAVE_LCD_BITMAP
28 #include "xlcd.h"
30 /* sort the given coordinates by increasing x value */
31 static void sort_points_by_increasing_x(int* x1, int* y1,
32 int* x2, int* y2,
33 int* x3, int* y3)
35 int x, y;
36 if (*x1 > *x3)
38 if (*x2 < *x3) /* x2 < x3 < x1 */
40 x = *x1; *x1 = *x2; *x2 = *x3; *x3 = x;
41 y = *y1; *y1 = *y2; *y2 = *y3; *y3 = y;
43 else if (*x2 > *x1) /* x3 < x1 < x2 */
45 x = *x1; *x1 = *x3; *x3 = *x2; *x2 = x;
46 y = *y1; *y1 = *y3; *y3 = *y2; *y2 = y;
48 else /* x3 <= x2 <= x1 */
50 x = *x1; *x1 = *x3; *x3 = x;
51 y = *y1; *y1 = *y3; *y3 = y;
54 else
56 if (*x2 < *x1) /* x2 < x1 <= x3 */
58 x = *x1; *x1 = *x2; *x2 = x;
59 y = *y1; *y1 = *y2; *y2 = y;
61 else if (*x2 > *x3) /* x1 <= x3 < x2 */
63 x = *x2; *x2 = *x3; *x3 = x;
64 y = *y2; *y2 = *y3; *y3 = y;
66 /* else already sorted */
70 #define sort_points_by_increasing_y(x1, y1, x2, y2, x3, y3) \
71 sort_points_by_increasing_x(y1, x1, y2, x2, y3, x3)
73 /* draw a filled triangle, using horizontal lines for speed */
74 static void xlcd_filltriangle_horizontal(struct screen* display,
75 int x1, int y1,
76 int x2, int y2,
77 int x3, int y3)
79 long fp_x1, fp_x2, fp_dx1, fp_dx2;
80 int y;
81 sort_points_by_increasing_y(&x1, &y1, &x2, &y2, &x3, &y3);
83 if (y1 < y3) /* draw */
85 fp_dx1 = ((x3 - x1) << 16) / (y3 - y1);
86 fp_x1 = (x1 << 16) + (1<<15) + (fp_dx1 >> 1);
88 if (y1 < y2) /* first part */
90 fp_dx2 = ((x2 - x1) << 16) / (y2 - y1);
91 fp_x2 = (x1 << 16) + (1<<15) + (fp_dx2 >> 1);
92 for (y = y1; y < y2; y++)
94 display->hline(fp_x1 >> 16, fp_x2 >> 16, y);
95 fp_x1 += fp_dx1;
96 fp_x2 += fp_dx2;
99 if (y2 < y3) /* second part */
101 fp_dx2 = ((x3 - x2) << 16) / (y3 - y2);
102 fp_x2 = (x2 << 16) + (1<<15) + (fp_dx2 >> 1);
103 for (y = y2; y < y3; y++)
105 display->hline(fp_x1 >> 16, fp_x2 >> 16, y);
106 fp_x1 += fp_dx1;
107 fp_x2 += fp_dx2;
113 /* draw a filled triangle, using vertical lines for speed */
114 static void xlcd_filltriangle_vertical(struct screen* display,
115 int x1, int y1,
116 int x2, int y2,
117 int x3, int y3)
119 long fp_y1, fp_y2, fp_dy1, fp_dy2;
120 int x;
121 sort_points_by_increasing_x(&x1, &y1, &x2, &y2, &x3, &y3);
123 if (x1 < x3) /* draw */
125 fp_dy1 = ((y3 - y1) << 16) / (x3 - x1);
126 fp_y1 = (y1 << 16) + (1<<15) + (fp_dy1 >> 1);
128 if (x1 < x2) /* first part */
130 fp_dy2 = ((y2 - y1) << 16) / (x2 - x1);
131 fp_y2 = (y1 << 16) + (1<<15) + (fp_dy2 >> 1);
132 for (x = x1; x < x2; x++)
134 display->vline(x, fp_y1 >> 16, fp_y2 >> 16);
135 fp_y1 += fp_dy1;
136 fp_y2 += fp_dy2;
139 if (x2 < x3) /* second part */
141 fp_dy2 = ((y3 - y2) << 16) / (x3 - x2);
142 fp_y2 = (y2 << 16) + (1<<15) + (fp_dy2 >> 1);
143 for (x = x2; x < x3; x++)
145 display->vline(x, fp_y1 >> 16, fp_y2 >> 16);
146 fp_y1 += fp_dy1;
147 fp_y2 += fp_dy2;
153 void xlcd_filltriangle(int x1, int y1,
154 int x2, int y2,
155 int x3, int y3)
157 /* default is main screen */
158 xlcd_filltriangle_screen(rb->screens[SCREEN_MAIN],
159 x1, y1, x2, y2, x3, y3);
162 void xlcd_filltriangle_screen(struct screen* display,
163 int x1, int y1,
164 int x2, int y2,
165 int x3, int y3)
167 if(display->pixel_format==HORIZONTAL_PACKING || display->depth>=8)
168 xlcd_filltriangle_horizontal(display, x1, y1, x2, y2, x3, y3);
169 else
170 xlcd_filltriangle_vertical(display, x1, y1, x2, y2, x3, y3);
173 #if LCD_DEPTH >= 8
175 #ifdef HAVE_LCD_COLOR
176 static const fb_data graylut[256] = {
177 #if LCD_PIXELFORMAT == RGB565
178 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0821, 0x0821, 0x0841,
179 0x0841, 0x0841, 0x0841, 0x0861, 0x0861, 0x1062, 0x1062, 0x1082,
180 0x1082, 0x1082, 0x1082, 0x10a2, 0x10a2, 0x18a3, 0x18a3, 0x18c3,
181 0x18c3, 0x18c3, 0x18c3, 0x18e3, 0x18e3, 0x20e4, 0x20e4, 0x2104,
182 0x2104, 0x2104, 0x2104, 0x2124, 0x2124, 0x2124, 0x2925, 0x2945,
183 0x2945, 0x2945, 0x2945, 0x2965, 0x2965, 0x2965, 0x3166, 0x3186,
184 0x3186, 0x3186, 0x3186, 0x31a6, 0x31a6, 0x31a6, 0x39a7, 0x39c7,
185 0x39c7, 0x39c7, 0x39c7, 0x39e7, 0x39e7, 0x39e7, 0x41e8, 0x4208,
186 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x4a29, 0x4a49,
187 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a,
188 0x528a, 0x528a, 0x528a, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x5aab,
189 0x5acb, 0x5acb, 0x5acb, 0x5acb, 0x5aeb, 0x5aeb, 0x5aeb, 0x62ec,
190 0x630c, 0x630c, 0x630c, 0x630c, 0x632c, 0x632c, 0x632c, 0x6b2d,
191 0x6b4d, 0x6b4d, 0x6b4d, 0x6b4d, 0x6b6d, 0x6b6d, 0x6b6d, 0x6b6d,
192 0x738e, 0x738e, 0x738e, 0x738e, 0x73ae, 0x73ae, 0x73ae, 0x73ae,
193 0x7bcf, 0x7bcf, 0x7bcf, 0x7bcf, 0x7bef, 0x7bef, 0x7bef, 0x7bef,
194 0x8410, 0x8410, 0x8410, 0x8410, 0x8430, 0x8430, 0x8430, 0x8430,
195 0x8c51, 0x8c51, 0x8c51, 0x8c51, 0x8c71, 0x8c71, 0x8c71, 0x8c71,
196 0x9492, 0x9492, 0x9492, 0x9492, 0x94b2, 0x94b2, 0x94b2, 0x94b2,
197 0x94d2, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cf3, 0x9cf3, 0x9cf3, 0x9cf3,
198 0x9d13, 0xa514, 0xa514, 0xa514, 0xa534, 0xa534, 0xa534, 0xa534,
199 0xa554, 0xad55, 0xad55, 0xad55, 0xad55, 0xad75, 0xad75, 0xad75,
200 0xad75, 0xb596, 0xb596, 0xb596, 0xb596, 0xb5b6, 0xb5b6, 0xb5b6,
201 0xb5b6, 0xb5d6, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdf7, 0xbdf7, 0xbdf7,
202 0xbdf7, 0xbe17, 0xc618, 0xc618, 0xc618, 0xc638, 0xc638, 0xc638,
203 0xc638, 0xc658, 0xce59, 0xce59, 0xce59, 0xce79, 0xce79, 0xce79,
204 0xce79, 0xce99, 0xd69a, 0xd69a, 0xd69a, 0xd6ba, 0xd6ba, 0xd6ba,
205 0xd6ba, 0xd6da, 0xd6da, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb,
206 0xdefb, 0xdf1b, 0xdf1b, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c,
207 0xe73c, 0xe75c, 0xe75c, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d,
208 0xef7d, 0xef9d, 0xef9d, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be,
209 0xf7be, 0xf7de, 0xf7de, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff
210 #elif LCD_PIXELFORMAT == RGB565SWAPPED
211 0x0000, 0x0000, 0x0000, 0x2000, 0x2000, 0x2108, 0x2108, 0x4108,
212 0x4108, 0x4108, 0x4108, 0x6108, 0x6108, 0x6210, 0x6210, 0x8210,
213 0x8210, 0x8210, 0x8210, 0xa210, 0xa210, 0xa318, 0xa318, 0xc318,
214 0xc318, 0xc318, 0xc318, 0xe318, 0xe318, 0xe420, 0xe420, 0x0421,
215 0x0421, 0x0421, 0x0421, 0x2421, 0x2421, 0x2421, 0x2529, 0x4529,
216 0x4529, 0x4529, 0x4529, 0x6529, 0x6529, 0x6529, 0x6631, 0x8631,
217 0x8631, 0x8631, 0x8631, 0xa631, 0xa631, 0xa631, 0xa739, 0xc739,
218 0xc739, 0xc739, 0xc739, 0xe739, 0xe739, 0xe739, 0xe841, 0x0842,
219 0x0842, 0x0842, 0x0842, 0x2842, 0x2842, 0x2842, 0x294a, 0x494a,
220 0x494a, 0x494a, 0x494a, 0x694a, 0x694a, 0x694a, 0x694a, 0x8a52,
221 0x8a52, 0x8a52, 0x8a52, 0xaa52, 0xaa52, 0xaa52, 0xaa52, 0xab5a,
222 0xcb5a, 0xcb5a, 0xcb5a, 0xcb5a, 0xeb5a, 0xeb5a, 0xeb5a, 0xec62,
223 0x0c63, 0x0c63, 0x0c63, 0x0c63, 0x2c63, 0x2c63, 0x2c63, 0x2d6b,
224 0x4d6b, 0x4d6b, 0x4d6b, 0x4d6b, 0x6d6b, 0x6d6b, 0x6d6b, 0x6d6b,
225 0x8e73, 0x8e73, 0x8e73, 0x8e73, 0xae73, 0xae73, 0xae73, 0xae73,
226 0xcf7b, 0xcf7b, 0xcf7b, 0xcf7b, 0xef7b, 0xef7b, 0xef7b, 0xef7b,
227 0x1084, 0x1084, 0x1084, 0x1084, 0x3084, 0x3084, 0x3084, 0x3084,
228 0x518c, 0x518c, 0x518c, 0x518c, 0x718c, 0x718c, 0x718c, 0x718c,
229 0x9294, 0x9294, 0x9294, 0x9294, 0xb294, 0xb294, 0xb294, 0xb294,
230 0xd294, 0xd39c, 0xd39c, 0xd39c, 0xf39c, 0xf39c, 0xf39c, 0xf39c,
231 0x139d, 0x14a5, 0x14a5, 0x14a5, 0x34a5, 0x34a5, 0x34a5, 0x34a5,
232 0x54a5, 0x55ad, 0x55ad, 0x55ad, 0x55ad, 0x75ad, 0x75ad, 0x75ad,
233 0x75ad, 0x96b5, 0x96b5, 0x96b5, 0x96b5, 0xb6b5, 0xb6b5, 0xb6b5,
234 0xb6b5, 0xd6b5, 0xd7bd, 0xd7bd, 0xd7bd, 0xf7bd, 0xf7bd, 0xf7bd,
235 0xf7bd, 0x17be, 0x18c6, 0x18c6, 0x18c6, 0x38c6, 0x38c6, 0x38c6,
236 0x38c6, 0x58c6, 0x59ce, 0x59ce, 0x59ce, 0x79ce, 0x79ce, 0x79ce,
237 0x79ce, 0x99ce, 0x9ad6, 0x9ad6, 0x9ad6, 0xbad6, 0xbad6, 0xbad6,
238 0xbad6, 0xdad6, 0xdad6, 0xdbde, 0xdbde, 0xfbde, 0xfbde, 0xfbde,
239 0xfbde, 0x1bdf, 0x1bdf, 0x1ce7, 0x1ce7, 0x3ce7, 0x3ce7, 0x3ce7,
240 0x3ce7, 0x5ce7, 0x5ce7, 0x5def, 0x5def, 0x7def, 0x7def, 0x7def,
241 0x7def, 0x9def, 0x9def, 0x9ef7, 0x9ef7, 0xbef7, 0xbef7, 0xbef7,
242 0xbef7, 0xdef7, 0xdef7, 0xdfff, 0xdfff, 0xffff, 0xffff, 0xffff
243 #endif /* LCD_PIXELFORMAT */
245 #endif /* HAVE_LCD_COLOR */
247 /* Draw a partial greyscale bitmap, canonical 8 bit format */
248 void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
249 int stride, int x, int y, int width, int height)
251 const unsigned char *src_end;
252 fb_data *dst;
254 /* nothing to draw? */
255 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
256 || (x + width <= 0) || (y + height <= 0))
257 return;
259 /* clipping */
260 if (x < 0)
262 width += x;
263 src_x -= x;
264 x = 0;
266 if (y < 0)
268 height += y;
269 src_y -= y;
270 y = 0;
272 if (x + width > LCD_WIDTH)
273 width = LCD_WIDTH - x;
274 if (y + height > LCD_HEIGHT)
275 height = LCD_HEIGHT - y;
277 src += stride * src_y + src_x; /* move starting point */
278 src_end = src + stride * height;
279 dst = rb->lcd_framebuffer + LCD_WIDTH * y + x;
283 const unsigned char *src_row = src;
284 const unsigned char *row_end = src_row + width;
285 fb_data *dst_row = dst;
287 #ifdef HAVE_LCD_COLOR
289 *dst_row++ = graylut[*src_row++];
290 while (src_row < row_end);
291 #endif
293 src += stride;
294 dst += LCD_WIDTH;
296 while (src < src_end);
299 /* Draw a full greyscale bitmap, canonical 8 bit format */
300 void xlcd_gray_bitmap(const unsigned char *src, int x, int y, int width,
301 int height)
303 xlcd_gray_bitmap_part(src, 0, 0, width, x, y, width, height);
306 #ifdef HAVE_LCD_COLOR
307 /* Draw a partial colour bitmap, canonical 24 bit RGB format */
308 void xlcd_color_bitmap_part(const unsigned char *src, int src_x, int src_y,
309 int stride, int x, int y, int width, int height)
311 const unsigned char *src_end;
312 fb_data *dst;
314 /* nothing to draw? */
315 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
316 || (x + width <= 0) || (y + height <= 0))
317 return;
319 /* clipping */
320 if (x < 0)
322 width += x;
323 src_x -= x;
324 x = 0;
326 if (y < 0)
328 height += y;
329 src_y -= y;
330 y = 0;
332 if (x + width > LCD_WIDTH)
333 width = LCD_WIDTH - x;
334 if (y + height > LCD_HEIGHT)
335 height = LCD_HEIGHT - y;
337 src += 3 * (stride * src_y + src_x); /* move starting point */
338 src_end = src + 3 * stride * height;
339 dst = rb->lcd_framebuffer + LCD_WIDTH * y + x;
343 const unsigned char *src_row = src;
344 const unsigned char *row_end = src_row + 3 * width;
345 fb_data *dst_row = dst;
348 { /* only RGB565 and RGB565SWAPPED so far */
349 unsigned red = 31 * (*src_row++) + 127;
350 unsigned green = 63 * (*src_row++) + 127;
351 unsigned blue = 31 * (*src_row++) + 127;
353 red = (red + (red >> 8)) >> 8; /* approx red /= 255: */
354 green = (green + (green >> 8)) >> 8; /* approx green /= 255: */
355 blue = (blue + (blue >> 8)) >> 8; /* approx blue /= 255: */
357 #if LCD_PIXELFORMAT == RGB565
358 *dst_row++ = (red << 11) | (green << 5) | blue;
359 #elif LCD_PIXELFORMAT == RGB565SWAPPED
360 *dst_row++ = swap16((red << 11) | (green << 5) | blue);
361 #endif
363 while (src_row < row_end);
365 src += 3 * stride;
366 dst += LCD_WIDTH;
368 while (src < src_end);
371 /* Draw a full colour bitmap, canonical 24 bit RGB format */
372 void xlcd_color_bitmap(const unsigned char *src, int x, int y, int width,
373 int height)
375 xlcd_color_bitmap_part(src, 0, 0, width, x, y, width, height);
377 #endif /* HAVE_LCD_COLOR */
379 #endif /* LCD_DEPTH >= 8 */
381 #endif /* HAVE_LCD_BITMAP */