1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Bitmap graphics on player LCD!
12 * Copyright (C) 2005 Jens Arnold
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
26 #include "playergfx.h"
30 static int char_width
;
31 static int char_height
;
32 static int pixel_height
;
33 static int pixel_width
;
34 static unsigned long gfx_chars
[8];
35 static unsigned char gfx_buffer
[56];
36 static int drawmode
= DRMODE_SOLID
;
38 /*** Special functions ***/
41 bool pgfx_init(int cwidth
, int cheight
)
45 if (((unsigned) cwidth
* (unsigned) cheight
) > 8 || (unsigned) cheight
> 2)
49 char_height
= cheight
;
50 pixel_height
= 7 * char_height
;
51 pixel_width
= 5 * char_width
;
53 for (i
= 0; i
< cwidth
* cheight
; i
++)
55 if ((gfx_chars
[i
] = rb
->lcd_get_locked_pattern()) == 0)
66 void pgfx_release(void)
70 for (i
= 0; i
< 8; i
++)
72 rb
->lcd_unlock_pattern(gfx_chars
[i
]);
75 /* place the display */
76 void pgfx_display(int cx
, int cy
)
79 int width
= MIN(char_width
, 11 - cx
);
80 int height
= MIN(char_height
, 2 - cy
);
82 for (i
= 0; i
< width
; i
++)
83 for (j
= 0; j
< height
; j
++)
84 rb
->lcd_putc(cx
+ i
, cy
+ j
, gfx_chars
[char_height
* i
+ j
]);
87 void pgfx_display_block(int cx
, int cy
, int x
, int y
)
89 rb
->lcd_putc(cx
, cy
, gfx_chars
[char_height
* x
+ y
]);
93 /*** Update functions ***/
95 void pgfx_update(void)
99 for (i
= 0; i
< char_width
* char_height
; i
++)
100 rb
->lcd_define_pattern(gfx_chars
[i
], gfx_buffer
+ 7 * i
);
105 /*** Parameter handling ***/
107 void pgfx_set_drawmode(int mode
)
109 drawmode
= mode
& (DRMODE_SOLID
|DRMODE_INVERSEVID
);
112 int pgfx_get_drawmode(void)
117 /*** Low-level drawing functions ***/
119 static void setpixel(int x
, int y
)
121 gfx_buffer
[pixel_height
* (x
/5) + y
] |= 0x10 >> (x
%5);
124 static void clearpixel(int x
, int y
)
126 gfx_buffer
[pixel_height
* (x
/5) + y
] &= ~(0x10 >> (x
%5));
129 static void flippixel(int x
, int y
)
131 gfx_buffer
[pixel_height
* (x
/5) + y
] ^= 0x10 >> (x
%5);
134 static void nopixel(int x
, int y
)
140 lcd_pixelfunc_type
* pgfx_pixelfuncs
[8] = {
141 flippixel
, nopixel
, setpixel
, setpixel
,
142 nopixel
, clearpixel
, nopixel
, clearpixel
145 static void flipblock(unsigned char *address
, unsigned mask
, unsigned bits
)
147 *address
^= (bits
& mask
);
150 static void bgblock(unsigned char *address
, unsigned mask
, unsigned bits
)
152 *address
&= (bits
| ~mask
);
155 static void fgblock(unsigned char *address
, unsigned mask
, unsigned bits
)
157 *address
|= (bits
& mask
);
160 static void solidblock(unsigned char *address
, unsigned mask
, unsigned bits
)
162 unsigned data
= *(char *)address
;
165 *address
= data
^ (bits
& mask
);
168 static void flipinvblock(unsigned char *address
, unsigned mask
, unsigned bits
)
170 *address
^= (~bits
& mask
);
173 static void bginvblock(unsigned char *address
, unsigned mask
, unsigned bits
)
175 *address
&= ~(bits
& mask
);
178 static void fginvblock(unsigned char *address
, unsigned mask
, unsigned bits
)
180 *address
|= (~bits
& mask
);
183 static void solidinvblock(unsigned char *address
, unsigned mask
, unsigned bits
)
185 unsigned data
= *(char *)address
;
188 *address
= data
^ (bits
& mask
);
191 lcd_blockfunc_type
* pgfx_blockfuncs
[8] = {
192 flipblock
, bgblock
, fgblock
, solidblock
,
193 flipinvblock
, bginvblock
, fginvblock
, solidinvblock
196 /*** Drawing functions ***/
198 /* Clear the whole display */
199 void pgfx_clear_display(void)
201 unsigned bits
= (drawmode
& DRMODE_INVERSEVID
) ? 0x1F : 0;
203 rb
->memset(gfx_buffer
, bits
, char_width
* pixel_height
);
206 /* Set a single pixel */
207 void pgfx_drawpixel(int x
, int y
)
209 if (((unsigned)x
< (unsigned)pixel_width
)
210 && ((unsigned)y
< (unsigned)pixel_height
))
211 pgfx_pixelfuncs
[drawmode
](x
, y
);
215 void pgfx_drawline(int x1
, int y1
, int x2
, int y2
)
223 lcd_pixelfunc_type
*pfunc
= pgfx_pixelfuncs
[drawmode
];
225 deltax
= abs(x2
- x1
);
226 deltay
= abs(y2
- y1
);
230 if (deltax
>= deltay
)
233 d
= 2 * deltay
- deltax
;
235 dinc2
= (deltay
- deltax
) * 2;
242 d
= 2 * deltax
- deltay
;
244 dinc2
= (deltax
- deltay
) * 2;
248 numpixels
++; /* include endpoints */
265 for (i
= 0; i
< numpixels
; i
++)
267 if (((unsigned)x
< (unsigned)pixel_width
)
268 && ((unsigned)y
< (unsigned)pixel_height
))
286 /* Draw a horizontal line (optimised) */
287 void pgfx_hline(int x1
, int x2
, int y
)
291 unsigned mask
, mask_right
;
292 lcd_blockfunc_type
*bfunc
;
302 /* nothing to draw? */
303 if (((unsigned)y
>= (unsigned)pixel_height
) || (x1
>= pixel_width
)
310 if (x2
>= pixel_width
)
311 x2
= pixel_width
- 1;
313 bfunc
= pgfx_blockfuncs
[drawmode
];
314 dst
= &gfx_buffer
[pixel_height
* (x1
/5) + y
];
315 nx
= x2
- (x1
- (x1
% 5));
316 mask
= 0x1F >> (x1
% 5);
317 mask_right
= 0x1F0 >> (nx
% 5);
319 for (; nx
>= 5; nx
-= 5)
321 bfunc(dst
, mask
, 0xFFu
);
326 bfunc(dst
, mask
, 0x1F);
329 /* Draw a vertical line (optimised) */
330 void pgfx_vline(int x
, int y1
, int y2
)
333 unsigned char *dst
, *dst_end
;
335 lcd_blockfunc_type
*bfunc
;
345 /* nothing to draw? */
346 if (((unsigned)x
>= (unsigned)pixel_width
) || (y1
>= pixel_height
)
353 if (y2
>= pixel_height
)
354 y2
= pixel_height
- 1;
356 bfunc
= pgfx_blockfuncs
[drawmode
];
357 dst
= &gfx_buffer
[pixel_height
* (x
/5) + y1
];
358 mask
= 0x10 >> (x
% 5);
360 dst_end
= dst
+ y2
- y1
;
362 bfunc(dst
++, mask
, 0x1F);
363 while (dst
<= dst_end
);
366 /* Draw a rectangular box */
367 void pgfx_drawrect(int x
, int y
, int width
, int height
)
369 if ((width
<= 0) || (height
<= 0))
372 int x2
= x
+ width
- 1;
373 int y2
= y
+ height
- 1;
375 pgfx_vline(x
, y
, y2
);
376 pgfx_vline(x2
, y
, y2
);
377 pgfx_hline(x
, x2
, y
);
378 pgfx_hline(x
, x2
, y2
);
381 /* Fill a rectangular area */
382 void pgfx_fillrect(int x
, int y
, int width
, int height
)
385 unsigned char *dst
, *dst_end
;
386 unsigned mask
, mask_right
;
387 lcd_blockfunc_type
*bfunc
;
389 /* nothing to draw? */
390 if ((width
<= 0) || (height
<= 0) || (x
>= pixel_width
)
391 || (y
>= pixel_height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
405 if (x
+ width
> pixel_width
)
406 width
= pixel_width
- x
;
407 if (y
+ height
> pixel_height
)
408 height
= pixel_height
- y
;
410 bfunc
= pgfx_blockfuncs
[drawmode
];
411 dst
= &gfx_buffer
[pixel_height
* (x
/5) + y
];
412 nx
= width
- 1 + (x
% 5);
413 mask
= 0x1F >> (x
% 5);
414 mask_right
= 0x1F0 >> (nx
% 5);
416 for (; nx
>= 5; nx
-= 5)
418 unsigned char *dst_col
= dst
;
420 dst_end
= dst_col
+ height
;
422 bfunc(dst_col
++, mask
, 0x1F);
423 while (dst_col
< dst_end
);
430 dst_end
= dst
+ height
;
432 bfunc(dst
++, mask
, 0x1F);
433 while (dst
< dst_end
);
436 /* About PlayerGFX internal bitmap format:
438 * A bitmap contains one bit for every pixel that defines if that pixel is
439 * black (1) or white (0). Bits within a byte are arranged horizontally,
441 * The bytes are stored in row-major order, with byte 0 being top left,
442 * byte 1 2nd from left etc. Each row of bytes defines one pixel row.
444 * This approximates the (even more strange) internal hardware format. */
446 /* Draw a partial bitmap. stride is given in pixels */
447 void pgfx_bitmap_part(const unsigned char *src
, int src_x
, int src_y
,
448 int stride
, int x
, int y
, int width
, int height
)
451 unsigned char *dst
, *dst_end
;
452 unsigned mask
, mask_right
;
453 lcd_blockfunc_type
*bfunc
;
455 /* nothing to draw? */
456 if ((width
<= 0) || (height
<= 0) || (x
>= pixel_width
)
457 || (y
>= pixel_height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
473 if (x
+ width
> pixel_width
)
474 width
= pixel_width
- x
;
475 if (y
+ height
> pixel_height
)
476 height
= pixel_height
- y
;
478 stride
= (stride
+ 7) >> 3; /* convert to no. of bytes */
480 src
+= stride
* src_y
+ (src_x
>> 3); /* move starting point */
481 dst
= &gfx_buffer
[pixel_height
* (x
/5) + y
];
482 shift
= 3 + (x
% 5) - (src_x
& 7);
483 nx
= width
- 1 + (x
% 5);
485 bfunc
= pgfx_blockfuncs
[drawmode
];
486 mask
= 0x1F >> (x
% 5);
487 mask_right
= 0x1F0 >> (nx
% 5);
489 dst_end
= dst
+ height
;
492 const unsigned char *src_row
= src
;
493 unsigned char *dst_row
= dst
++;
494 unsigned mask_row
= mask
;
495 unsigned data
= *src_row
++;
496 int extrabits
= shift
;
498 for (x
= nx
; x
>= 5; x
-= 5)
502 data
= (data
<< 8) | *src_row
++;
505 bfunc(dst_row
, mask_row
, data
>> extrabits
);
507 dst_row
+= pixel_height
;
512 data
= (data
<< 8) | *src_row
;
515 bfunc(dst_row
, mask_row
& mask_right
, data
>> extrabits
);
519 while (dst
< dst_end
);
522 /* Draw a full bitmap */
523 void pgfx_bitmap(const unsigned char *src
, int x
, int y
, int width
, int height
)
525 pgfx_bitmap_part(src
, 0, 0, width
, x
, y
, width
, height
);