summaryrefslogtreecommitdiff
path: root/apps/plugins/lib/xlcd_draw.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/lib/xlcd_draw.c')
-rwxr-xr-xapps/plugins/lib/xlcd_draw.c379
1 files changed, 379 insertions, 0 deletions
diff --git a/apps/plugins/lib/xlcd_draw.c b/apps/plugins/lib/xlcd_draw.c
new file mode 100755
index 0000000000..3ccdea9139
--- /dev/null
+++ b/apps/plugins/lib/xlcd_draw.c
@@ -0,0 +1,379 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Additional LCD routines not present in the rockbox core
11* Drawing functions
12*
13* Copyright (C) 2005 Jens Arnold
14*
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.
17*
18* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19* KIND, either express or implied.
20*
21****************************************************************************/
22
23#include "plugin.h"
24
25#ifdef HAVE_LCD_BITMAP
26#include "xlcd.h"
27
28#if (LCD_DEPTH >= 8) || (LCD_PIXELFORMAT == HORIZONTAL_PACKING)
29/* draw a filled triangle, using horizontal lines for speed */
30void xlcd_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3)
31{
32 int x, y;
33 long fp_x1, fp_x2, fp_dx1, fp_dx2;
34
35 /* sort vertices by increasing y value */
36 if (y1 > y3)
37 {
38 if (y2 < y3) /* y2 < y3 < y1 */
39 {
40 x = x1; x1 = x2; x2 = x3; x3 = x;
41 y = y1; y1 = y2; y2 = y3; y3 = y;
42 }
43 else if (y2 > y1) /* y3 < y1 < y2 */
44 {
45 x = x1; x1 = x3; x3 = x2; x2 = x;
46 y = y1; y1 = y3; y3 = y2; y2 = y;
47 }
48 else /* y3 <= y2 <= y1 */
49 {
50 x = x1; x1 = x3; x3 = x;
51 y = y1; y1 = y3; y3 = y;
52 }
53 }
54 else
55 {
56 if (y2 < y1) /* y2 < y1 <= y3 */
57 {
58 x = x1; x1 = x2; x2 = x;
59 y = y1; y1 = y2; y2 = y;
60 }
61 else if (y2 > y3) /* y1 <= y3 < y2 */
62 {
63 x = x2; x2 = x3; x3 = x;
64 y = y2; y2 = y3; y3 = y;
65 }
66 /* else already sorted */
67 }
68
69 if (y1 < y3) /* draw */
70 {
71 fp_dx1 = ((x3 - x1) << 16) / (y3 - y1);
72 fp_x1 = (x1 << 16) + (1<<15) + (fp_dx1 >> 1);
73
74 if (y1 < y2) /* first part */
75 {
76 fp_dx2 = ((x2 - x1) << 16) / (y2 - y1);
77 fp_x2 = (x1 << 16) + (1<<15) + (fp_dx2 >> 1);
78 for (y = y1; y < y2; y++)
79 {
80 _xlcd_rb->lcd_hline(fp_x1 >> 16, fp_x2 >> 16, y);
81 fp_x1 += fp_dx1;
82 fp_x2 += fp_dx2;
83 }
84 }
85 if (y2 < y3) /* second part */
86 {
87 fp_dx2 = ((x3 - x2) << 16) / (y3 - y2);
88 fp_x2 = (x2 << 16) + (1<<15) + (fp_dx2 >> 1);
89 for (y = y2; y < y3; y++)
90 {
91 _xlcd_rb->lcd_hline(fp_x1 >> 16, fp_x2 >> 16, y);
92 fp_x1 += fp_dx1;
93 fp_x2 += fp_dx2;
94 }
95 }
96 }
97}
98#else /* (LCD_DEPTH < 8) && (LCD_PIXELFORMAT == VERTICAL_PACKING) */
99/* draw a filled triangle, using vertical lines for speed */
100void xlcd_filltriangle(int x1, int y1, int x2, int y2, int x3, int y3)
101{
102 int x, y;
103 long fp_y1, fp_y2, fp_dy1, fp_dy2;
104
105 /* sort vertices by increasing x value */
106 if (x1 > x3)
107 {
108 if (x2 < x3) /* x2 < x3 < x1 */
109 {
110 x = x1; x1 = x2; x2 = x3; x3 = x;
111 y = y1; y1 = y2; y2 = y3; y3 = y;
112 }
113 else if (x2 > x1) /* x3 < x1 < x2 */
114 {
115 x = x1; x1 = x3; x3 = x2; x2 = x;
116 y = y1; y1 = y3; y3 = y2; y2 = y;
117 }
118 else /* x3 <= x2 <= x1 */
119 {
120 x = x1; x1 = x3; x3 = x;
121 y = y1; y1 = y3; y3 = y;
122 }
123 }
124 else
125 {
126 if (x2 < x1) /* x2 < x1 <= x3 */
127 {
128 x = x1; x1 = x2; x2 = x;
129 y = y1; y1 = y2; y2 = y;
130 }
131 else if (x2 > x3) /* x1 <= x3 < x2 */
132 {
133 x = x2; x2 = x3; x3 = x;
134 y = y2; y2 = y3; y3 = y;
135 }
136 /* else already sorted */
137 }
138
139 if (x1 < x3) /* draw */
140 {
141 fp_dy1 = ((y3 - y1) << 16) / (x3 - x1);
142 fp_y1 = (y1 << 16) + (1<<15) + (fp_dy1 >> 1);
143
144 if (x1 < x2) /* first part */
145 {
146 fp_dy2 = ((y2 - y1) << 16) / (x2 - x1);
147 fp_y2 = (y1 << 16) + (1<<15) + (fp_dy2 >> 1);
148 for (x = x1; x < x2; x++)
149 {
150 _xlcd_rb->lcd_vline(x, fp_y1 >> 16, fp_y2 >> 16);
151 fp_y1 += fp_dy1;
152 fp_y2 += fp_dy2;
153 }
154 }
155 if (x2 < x3) /* second part */
156 {
157 fp_dy2 = ((y3 - y2) << 16) / (x3 - x2);
158 fp_y2 = (y2 << 16) + (1<<15) + (fp_dy2 >> 1);
159 for (x = x2; x < x3; x++)
160 {
161 _xlcd_rb->lcd_vline(x, fp_y1 >> 16, fp_y2 >> 16);
162 fp_y1 += fp_dy1;
163 fp_y2 += fp_dy2;
164 }
165 }
166 }
167}
168#endif /* LCD_DEPTH, LCD_PIXELFORMAT */
169
170#if LCD_DEPTH >= 8
171
172#ifdef HAVE_LCD_COLOR
173static const fb_data graylut[256] = {
174#if LCD_PIXELFORMAT == RGB565
175 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0821, 0x0821, 0x0841,
176 0x0841, 0x0841, 0x0841, 0x0861, 0x0861, 0x1062, 0x1062, 0x1082,
177 0x1082, 0x1082, 0x1082, 0x10a2, 0x10a2, 0x18a3, 0x18a3, 0x18c3,
178 0x18c3, 0x18c3, 0x18c3, 0x18e3, 0x18e3, 0x20e4, 0x20e4, 0x2104,
179 0x2104, 0x2104, 0x2104, 0x2124, 0x2124, 0x2124, 0x2925, 0x2945,
180 0x2945, 0x2945, 0x2945, 0x2965, 0x2965, 0x2965, 0x3166, 0x3186,
181 0x3186, 0x3186, 0x3186, 0x31a6, 0x31a6, 0x31a6, 0x39a7, 0x39c7,
182 0x39c7, 0x39c7, 0x39c7, 0x39e7, 0x39e7, 0x39e7, 0x41e8, 0x4208,
183 0x4208, 0x4208, 0x4208, 0x4228, 0x4228, 0x4228, 0x4a29, 0x4a49,
184 0x4a49, 0x4a49, 0x4a49, 0x4a69, 0x4a69, 0x4a69, 0x4a69, 0x528a,
185 0x528a, 0x528a, 0x528a, 0x52aa, 0x52aa, 0x52aa, 0x52aa, 0x5aab,
186 0x5acb, 0x5acb, 0x5acb, 0x5acb, 0x5aeb, 0x5aeb, 0x5aeb, 0x62ec,
187 0x630c, 0x630c, 0x630c, 0x630c, 0x632c, 0x632c, 0x632c, 0x6b2d,
188 0x6b4d, 0x6b4d, 0x6b4d, 0x6b4d, 0x6b6d, 0x6b6d, 0x6b6d, 0x6b6d,
189 0x738e, 0x738e, 0x738e, 0x738e, 0x73ae, 0x73ae, 0x73ae, 0x73ae,
190 0x7bcf, 0x7bcf, 0x7bcf, 0x7bcf, 0x7bef, 0x7bef, 0x7bef, 0x7bef,
191 0x8410, 0x8410, 0x8410, 0x8410, 0x8430, 0x8430, 0x8430, 0x8430,
192 0x8c51, 0x8c51, 0x8c51, 0x8c51, 0x8c71, 0x8c71, 0x8c71, 0x8c71,
193 0x9492, 0x9492, 0x9492, 0x9492, 0x94b2, 0x94b2, 0x94b2, 0x94b2,
194 0x94d2, 0x9cd3, 0x9cd3, 0x9cd3, 0x9cf3, 0x9cf3, 0x9cf3, 0x9cf3,
195 0x9d13, 0xa514, 0xa514, 0xa514, 0xa534, 0xa534, 0xa534, 0xa534,
196 0xa554, 0xad55, 0xad55, 0xad55, 0xad55, 0xad75, 0xad75, 0xad75,
197 0xad75, 0xb596, 0xb596, 0xb596, 0xb596, 0xb5b6, 0xb5b6, 0xb5b6,
198 0xb5b6, 0xb5d6, 0xbdd7, 0xbdd7, 0xbdd7, 0xbdf7, 0xbdf7, 0xbdf7,
199 0xbdf7, 0xbe17, 0xc618, 0xc618, 0xc618, 0xc638, 0xc638, 0xc638,
200 0xc638, 0xc658, 0xce59, 0xce59, 0xce59, 0xce79, 0xce79, 0xce79,
201 0xce79, 0xce99, 0xd69a, 0xd69a, 0xd69a, 0xd6ba, 0xd6ba, 0xd6ba,
202 0xd6ba, 0xd6da, 0xd6da, 0xdedb, 0xdedb, 0xdefb, 0xdefb, 0xdefb,
203 0xdefb, 0xdf1b, 0xdf1b, 0xe71c, 0xe71c, 0xe73c, 0xe73c, 0xe73c,
204 0xe73c, 0xe75c, 0xe75c, 0xef5d, 0xef5d, 0xef7d, 0xef7d, 0xef7d,
205 0xef7d, 0xef9d, 0xef9d, 0xf79e, 0xf79e, 0xf7be, 0xf7be, 0xf7be,
206 0xf7be, 0xf7de, 0xf7de, 0xffdf, 0xffdf, 0xffff, 0xffff, 0xffff
207#elif LCD_PIXELFORMAT == RGB565SWAPPED
208 0x0000, 0x0000, 0x0000, 0x2000, 0x2000, 0x2108, 0x2108, 0x4108,
209 0x4108, 0x4108, 0x4108, 0x6108, 0x6108, 0x6210, 0x6210, 0x8210,
210 0x8210, 0x8210, 0x8210, 0xa210, 0xa210, 0xa318, 0xa318, 0xc318,
211 0xc318, 0xc318, 0xc318, 0xe318, 0xe318, 0xe420, 0xe420, 0x0421,
212 0x0421, 0x0421, 0x0421, 0x2421, 0x2421, 0x2421, 0x2529, 0x4529,
213 0x4529, 0x4529, 0x4529, 0x6529, 0x6529, 0x6529, 0x6631, 0x8631,
214 0x8631, 0x8631, 0x8631, 0xa631, 0xa631, 0xa631, 0xa739, 0xc739,
215 0xc739, 0xc739, 0xc739, 0xe739, 0xe739, 0xe739, 0xe841, 0x0842,
216 0x0842, 0x0842, 0x0842, 0x2842, 0x2842, 0x2842, 0x294a, 0x494a,
217 0x494a, 0x494a, 0x494a, 0x694a, 0x694a, 0x694a, 0x694a, 0x8a52,
218 0x8a52, 0x8a52, 0x8a52, 0xaa52, 0xaa52, 0xaa52, 0xaa52, 0xab5a,
219 0xcb5a, 0xcb5a, 0xcb5a, 0xcb5a, 0xeb5a, 0xeb5a, 0xeb5a, 0xec62,
220 0x0c63, 0x0c63, 0x0c63, 0x0c63, 0x2c63, 0x2c63, 0x2c63, 0x2d6b,
221 0x4d6b, 0x4d6b, 0x4d6b, 0x4d6b, 0x6d6b, 0x6d6b, 0x6d6b, 0x6d6b,
222 0x8e73, 0x8e73, 0x8e73, 0x8e73, 0xae73, 0xae73, 0xae73, 0xae73,
223 0xcf7b, 0xcf7b, 0xcf7b, 0xcf7b, 0xef7b, 0xef7b, 0xef7b, 0xef7b,
224 0x1084, 0x1084, 0x1084, 0x1084, 0x3084, 0x3084, 0x3084, 0x3084,
225 0x518c, 0x518c, 0x518c, 0x518c, 0x718c, 0x718c, 0x718c, 0x718c,
226 0x9294, 0x9294, 0x9294, 0x9294, 0xb294, 0xb294, 0xb294, 0xb294,
227 0xd294, 0xd39c, 0xd39c, 0xd39c, 0xf39c, 0xf39c, 0xf39c, 0xf39c,
228 0x139d, 0x14a5, 0x14a5, 0x14a5, 0x34a5, 0x34a5, 0x34a5, 0x34a5,
229 0x54a5, 0x55ad, 0x55ad, 0x55ad, 0x55ad, 0x75ad, 0x75ad, 0x75ad,
230 0x75ad, 0x96b5, 0x96b5, 0x96b5, 0x96b5, 0xb6b5, 0xb6b5, 0xb6b5,
231 0xb6b5, 0xd6b5, 0xd7bd, 0xd7bd, 0xd7bd, 0xf7bd, 0xf7bd, 0xf7bd,
232 0xf7bd, 0x17be, 0x18c6, 0x18c6, 0x18c6, 0x38c6, 0x38c6, 0x38c6,
233 0x38c6, 0x58c6, 0x59ce, 0x59ce, 0x59ce, 0x79ce, 0x79ce, 0x79ce,
234 0x79ce, 0x99ce, 0x9ad6, 0x9ad6, 0x9ad6, 0xbad6, 0xbad6, 0xbad6,
235 0xbad6, 0xdad6, 0xdad6, 0xdbde, 0xdbde, 0xfbde, 0xfbde, 0xfbde,
236 0xfbde, 0x1bdf, 0x1bdf, 0x1ce7, 0x1ce7, 0x3ce7, 0x3ce7, 0x3ce7,
237 0x3ce7, 0x5ce7, 0x5ce7, 0x5def, 0x5def, 0x7def, 0x7def, 0x7def,
238 0x7def, 0x9def, 0x9def, 0x9ef7, 0x9ef7, 0xbef7, 0xbef7, 0xbef7,
239 0xbef7, 0xdef7, 0xdef7, 0xdfff, 0xdfff, 0xffff, 0xffff, 0xffff
240#endif /* LCD_PIXELFORMAT */
241};
242#endif /* HAVE_LCD_COLOR */
243
244/* Draw a partial greyscale bitmap, canonical 8 bit format */
245void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
246 int stride, int x, int y, int width, int height)
247{
248 const unsigned char *src_end;
249 fb_data *dst;
250
251 /* nothing to draw? */
252 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
253 || (x + width <= 0) || (y + height <= 0))
254 return;
255
256 /* clipping */
257 if (x < 0)
258 {
259 width += x;
260 src_x -= x;
261 x = 0;
262 }
263 if (y < 0)
264 {
265 height += y;
266 src_y -= y;
267 y = 0;
268 }
269 if (x + width > LCD_WIDTH)
270 width = LCD_WIDTH - x;
271 if (y + height > LCD_HEIGHT)
272 height = LCD_HEIGHT - y;
273
274 src += stride * src_y + src_x; /* move starting point */
275 src_end = src + stride * height;
276 dst = _xlcd_rb->lcd_framebuffer + LCD_WIDTH * y + x;
277
278 do
279 {
280 const unsigned char *src_row = src;
281 const unsigned char *row_end = src_row + width;
282 fb_data *dst_row = dst;
283
284#ifdef HAVE_LCD_COLOR
285 do
286 *dst_row++ = graylut[*src_row++];
287 while (src_row < row_end);
288#endif
289
290 src += stride;
291 dst += LCD_WIDTH;
292 }
293 while (src < src_end);
294}
295
296/* Draw a full greyscale bitmap, canonical 8 bit format */
297void xlcd_gray_bitmap(const unsigned char *src, int x, int y, int width,
298 int height)
299{
300 xlcd_gray_bitmap_part(src, 0, 0, width, x, y, width, height);
301}
302
303#ifdef HAVE_LCD_COLOR
304/* Draw a partial colour bitmap, canonical 24 bit RGB format */
305void xlcd_color_bitmap_part(const unsigned char *src, int src_x, int src_y,
306 int stride, int x, int y, int width, int height)
307{
308 const unsigned char *src_end;
309 fb_data *dst;
310
311 /* nothing to draw? */
312 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
313 || (x + width <= 0) || (y + height <= 0))
314 return;
315
316 /* clipping */
317 if (x < 0)
318 {
319 width += x;
320 src_x -= x;
321 x = 0;
322 }
323 if (y < 0)
324 {
325 height += y;
326 src_y -= y;
327 y = 0;
328 }
329 if (x + width > LCD_WIDTH)
330 width = LCD_WIDTH - x;
331 if (y + height > LCD_HEIGHT)
332 height = LCD_HEIGHT - y;
333
334 src += 3 * (stride * src_y + src_x); /* move starting point */
335 src_end = src + 3 * stride * height;
336 dst = _xlcd_rb->lcd_framebuffer + LCD_WIDTH * y + x;
337
338 do
339 {
340 const unsigned char *src_row = src;
341 const unsigned char *row_end = src_row + 3 * width;
342 fb_data *dst_row = dst;
343
344 do
345 { /* only RGB565 and RGB565SWAPPED so far */
346 unsigned red = 31 * (*src_row++) + 127;
347 unsigned green = 63 * (*src_row++) + 127;
348 unsigned blue = 31 * (*src_row++) + 127;
349
350 red = (red + (red >> 8)) >> 8; /* approx red /= 255: */
351 green = (green + (green >> 8)) >> 8; /* approx green /= 255: */
352 blue = (blue + (blue >> 8)) >> 8; /* approx blue /= 255: */
353
354#if LCD_PIXELFORMAT == RGB565
355 *dst_row++ = (red << 11) | (green << 5) | blue;
356#elif LCD_PIXELFORMAT == RGB565SWAPPED
357 *dst_row++ = swap16((red << 11) | (green << 5) | blue);
358#endif
359 }
360 while (src_row < row_end);
361
362 src += 3 * stride;
363 dst += LCD_WIDTH;
364 }
365 while (src < src_end);
366}
367
368/* Draw a full colour bitmap, canonical 24 bit RGB format */
369void xlcd_color_bitmap(const unsigned char *src, int x, int y, int width,
370 int height)
371{
372 xlcd_color_bitmap_part(src, 0, 0, width, x, y, width, height);
373}
374#endif /* HAVE_LCD_COLOR */
375
376#endif /* LCD_DEPTH >= 8 */
377
378#endif /* HAVE_LCD_BITMAP */
379