summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorKarl Kurbjun <kkurbjun@gmail.com>2009-09-01 00:50:43 +0000
committerKarl Kurbjun <kkurbjun@gmail.com>2009-09-01 00:50:43 +0000
commit8cb5df6a469ab69179ef304b30455925806b7b95 (patch)
tree12ecaa52684bde519bedbd275fd8e124750fdb0b /firmware
parentb9093b2b35310af1ea28a5a96d036818146783ab (diff)
downloadrockbox-8cb5df6a469ab69179ef304b30455925806b7b95.tar.gz
rockbox-8cb5df6a469ab69179ef304b30455925806b7b95.zip
Initial vertical stride LCD driver. Backdrop is inverted with it currently.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22579 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/lcd-16bit-vert.c923
1 files changed, 923 insertions, 0 deletions
diff --git a/firmware/drivers/lcd-16bit-vert.c b/firmware/drivers/lcd-16bit-vert.c
new file mode 100644
index 0000000000..3b05c09e44
--- /dev/null
+++ b/firmware/drivers/lcd-16bit-vert.c
@@ -0,0 +1,923 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Dave Chapman
11 * Copyright (C) 2009 by Karl Kurbjun
12 *
13 * Rockbox driver for 16-bit colour LCDs with vertical strides
14 *
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.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24#include "config.h"
25
26#include "cpu.h"
27#include "lcd.h"
28#include "kernel.h"
29#include "thread.h"
30#include <string.h>
31#include <stdlib.h>
32#include "memory.h"
33#include "file.h"
34#include "debug.h"
35#include "system.h"
36#include "font.h"
37#include "rbunicode.h"
38#include "bidi.h"
39#include "scroll_engine.h"
40
41enum fill_opt {
42 OPT_NONE = 0,
43 OPT_SET,
44 OPT_COPY
45};
46
47/*** globals ***/
48fb_data lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]
49 IRAM_LCDFRAMEBUFFER CACHEALIGN_AT_LEAST_ATTR(16);
50
51
52static fb_data* lcd_backdrop = NULL;
53static long lcd_backdrop_offset IDATA_ATTR = 0;
54
55static struct viewport default_vp =
56{
57 .x = 0,
58 .y = 0,
59 .width = LCD_WIDTH,
60 .height = LCD_HEIGHT,
61 .font = FONT_SYSFIXED,
62 .drawmode = DRMODE_SOLID,
63 .fg_pattern = LCD_DEFAULT_FG,
64 .bg_pattern = LCD_DEFAULT_BG,
65 .lss_pattern = LCD_DEFAULT_BG,
66 .lse_pattern = LCD_DEFAULT_BG,
67 .lst_pattern = LCD_DEFAULT_BG,
68};
69
70/* The Gigabeat target build requires access to the current fg_pattern
71 in lcd-meg-fx.c */
72#if (!defined(TOSHIBA_GIGABEAT_F)&& !defined(TOSHIBA_GIGABEAT_S)) || defined(SIMULATOR)
73static struct viewport* current_vp IDATA_ATTR = &default_vp;
74#else
75struct viewport* current_vp IDATA_ATTR = &default_vp;
76#endif
77
78
79/*** Helpers - consolidate optional code ***/
80#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
81static void (*lcd_activation_hook)(void) = NULL;
82
83void lcd_activation_set_hook(void (*func)(void))
84{
85 lcd_activation_hook = func;
86}
87
88/* To be called by target driver after enabling display and refreshing it */
89void lcd_activation_call_hook(void)
90{
91 void (*func)(void) = lcd_activation_hook;
92
93 if (func != NULL)
94 func();
95}
96
97#endif
98
99/* LCD init */
100void lcd_init(void)
101{
102 lcd_clear_display();
103
104 /* Call device specific init */
105 lcd_init_device();
106 scroll_init();
107}
108/*** Viewports ***/
109
110void lcd_set_viewport(struct viewport* vp)
111{
112 if (vp == NULL)
113 current_vp = &default_vp;
114 else
115 current_vp = vp;
116}
117
118void lcd_update_viewport(void)
119{
120 lcd_update_rect(current_vp->x, current_vp->y,
121 current_vp->width, current_vp->height);
122}
123
124void lcd_update_viewport_rect(int x, int y, int width, int height)
125{
126 lcd_update_rect(current_vp->x + x, current_vp->y + y, width, height);
127}
128
129/*** parameter handling ***/
130
131void lcd_set_drawmode(int mode)
132{
133 current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
134}
135
136int lcd_get_drawmode(void)
137{
138 return current_vp->drawmode;
139}
140
141void lcd_set_foreground(unsigned color)
142{
143 current_vp->fg_pattern = color;
144}
145
146unsigned lcd_get_foreground(void)
147{
148 return current_vp->fg_pattern;
149}
150
151void lcd_set_background(unsigned color)
152{
153 current_vp->bg_pattern = color;
154}
155
156unsigned lcd_get_background(void)
157{
158 return current_vp->bg_pattern;
159}
160
161void lcd_set_selector_start(unsigned color)
162{
163 current_vp->lss_pattern = color;
164}
165
166void lcd_set_selector_end(unsigned color)
167{
168 current_vp->lse_pattern = color;
169}
170
171void lcd_set_selector_text(unsigned color)
172{
173 current_vp->lst_pattern = color;
174}
175
176void lcd_set_drawinfo(int mode, unsigned fg_color, unsigned bg_color)
177{
178 lcd_set_drawmode(mode);
179 current_vp->fg_pattern = fg_color;
180 current_vp->bg_pattern = bg_color;
181}
182
183int lcd_getwidth(void)
184{
185 return current_vp->width;
186}
187
188int lcd_getheight(void)
189{
190 return current_vp->height;
191}
192
193void lcd_setfont(int newfont)
194{
195 current_vp->font = newfont;
196}
197
198int lcd_getfont(void)
199{
200 return current_vp->font;
201}
202
203int lcd_getstringsize(const unsigned char *str, int *w, int *h)
204{
205 return font_getstringsize(str, w, h, current_vp->font);
206}
207
208/*** low-level drawing functions ***/
209
210#define LCDADDR(x, y) (&lcd_framebuffer[0][0] + (LCD_HEIGHT*(LCD_WIDTH-1)) \
211 - LCD_HEIGHT*(x) + (y))
212
213#define LCDBACKADDR(x, y) (lcd_backdrop + LCD_HEIGHT*(x) + (y))
214
215static void ICODE_ATTR setpixel(fb_data *address)
216{
217 *address = current_vp->fg_pattern;
218}
219
220static void ICODE_ATTR clearpixel(fb_data *address)
221{
222 *address = current_vp->bg_pattern;
223}
224
225static void ICODE_ATTR clearimgpixel(fb_data *address)
226{
227 *address = *(fb_data *)((long)address + lcd_backdrop_offset);
228}
229
230static void ICODE_ATTR flippixel(fb_data *address)
231{
232 *address = ~(*address);
233}
234
235static void ICODE_ATTR nopixel(fb_data *address)
236{
237 (void)address;
238}
239
240lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_bgcolor[8] = {
241 flippixel, nopixel, setpixel, setpixel,
242 nopixel, clearpixel, nopixel, clearpixel
243};
244
245lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[8] = {
246 flippixel, nopixel, setpixel, setpixel,
247 nopixel, clearimgpixel, nopixel, clearimgpixel
248};
249
250lcd_fastpixelfunc_type* const * lcd_fastpixelfuncs = lcd_fastpixelfuncs_bgcolor;
251
252void lcd_set_backdrop(fb_data* backdrop)
253{
254 lcd_backdrop = backdrop;
255 if (backdrop)
256 {
257 lcd_backdrop_offset = (long)backdrop - (long)&lcd_framebuffer[0][0];
258 lcd_fastpixelfuncs = lcd_fastpixelfuncs_backdrop;
259 }
260 else
261 {
262 lcd_backdrop_offset = 0;
263 lcd_fastpixelfuncs = lcd_fastpixelfuncs_bgcolor;
264 }
265}
266
267fb_data* lcd_get_backdrop(void)
268{
269 return lcd_backdrop;
270}
271
272/*** drawing functions ***/
273
274/* Clear the current viewport */
275void lcd_clear_viewport(void)
276{
277 fb_data *dst, *dst_end;
278
279 dst = LCDADDR(current_vp->x, current_vp->y);
280 dst_end = dst - current_vp->width * LCD_HEIGHT;
281
282 if (current_vp->drawmode & DRMODE_INVERSEVID)
283 {
284 do
285 {
286 memset16(dst, current_vp->fg_pattern, current_vp->height);
287 dst -= LCD_HEIGHT;
288 }
289 while (dst > dst_end);
290 }
291 else
292 {
293 if (!lcd_backdrop)
294 {
295 do
296 {
297 memset16(dst, current_vp->bg_pattern, current_vp->height);
298 dst -= LCD_HEIGHT;
299 }
300 while (dst > dst_end);
301 }
302 else
303 {
304 do
305 {
306 memcpy(dst, (void *)((long)dst + lcd_backdrop_offset),
307 current_vp->height * sizeof(fb_data));
308 dst -= LCD_HEIGHT;
309 }
310 while (dst > dst_end);
311 }
312 }
313
314 if (current_vp == &default_vp)
315 {
316 lcd_scroll_info.lines = 0;
317 }
318 else
319 {
320 lcd_scroll_stop(current_vp);
321 }
322}
323
324/* Clear the whole display */
325void lcd_clear_display(void)
326{
327 struct viewport* old_vp = current_vp;
328
329 current_vp = &default_vp;
330
331 lcd_clear_viewport();
332
333 current_vp = old_vp;
334}
335
336/* Set a single pixel */
337void lcd_drawpixel(int x, int y)
338{
339 if (((unsigned)x < (unsigned)current_vp->width) &&
340 ((unsigned)y < (unsigned)current_vp->height))
341 lcd_fastpixelfuncs[current_vp->drawmode](LCDADDR(current_vp->x+x, current_vp->y+y));
342}
343
344/* Draw a line */
345void lcd_drawline(int x1, int y1, int x2, int y2)
346{
347 int numpixels;
348 int i;
349 int deltax, deltay;
350 int d, dinc1, dinc2;
351 int x, xinc1, xinc2;
352 int y, yinc1, yinc2;
353 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode];
354
355 deltay = abs(y2 - y1);
356 if (deltay == 0)
357 {
358 DEBUGF("lcd_drawline() called for horizontal line - optimisation.\n");
359 lcd_hline(x1, x2, y1);
360 return;
361 }
362 deltax = abs(x2 - x1);
363 if (deltax == 0)
364 {
365 DEBUGF("lcd_drawline() called for vertical line - optimisation.\n");
366 lcd_vline(x1, y1, y2);
367 return;
368 }
369 xinc2 = 1;
370 yinc2 = 1;
371
372 if (deltax >= deltay)
373 {
374 numpixels = deltax;
375 d = 2 * deltay - deltax;
376 dinc1 = deltay * 2;
377 dinc2 = (deltay - deltax) * 2;
378 xinc1 = 1;
379 yinc1 = 0;
380 }
381 else
382 {
383 numpixels = deltay;
384 d = 2 * deltax - deltay;
385 dinc1 = deltax * 2;
386 dinc2 = (deltax - deltay) * 2;
387 xinc1 = 0;
388 yinc1 = 1;
389 }
390 numpixels++; /* include endpoints */
391
392 if (x1 > x2)
393 {
394 xinc1 = -xinc1;
395 xinc2 = -xinc2;
396 }
397
398 if (y1 > y2)
399 {
400 yinc1 = -yinc1;
401 yinc2 = -yinc2;
402 }
403
404 x = x1;
405 y = y1;
406
407 for (i = 0; i < numpixels; i++)
408 {
409 if (((unsigned)x < (unsigned)current_vp->width) && ((unsigned)y < (unsigned)current_vp->height))
410 pfunc(LCDADDR(x + current_vp->x, y + current_vp->y));
411
412 if (d < 0)
413 {
414 d += dinc1;
415 x += xinc1;
416 y += yinc1;
417 }
418 else
419 {
420 d += dinc2;
421 x += xinc2;
422 y += yinc2;
423 }
424 }
425}
426
427/* Draw a horizontal line (optimised) */
428void lcd_hline(int x1, int x2, int y)
429{
430 int x;
431 fb_data *dst, *dst_end;
432 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode];
433
434 /* direction flip */
435 if (x2 < x1)
436 {
437 x = x1;
438 x1 = x2;
439 x2 = x;
440 }
441
442 /* nothing to draw? */
443 if (((unsigned)y >= (unsigned)current_vp->height) ||
444 (x1 >= current_vp->width) ||
445 (x2 < 0))
446 return;
447
448 /* clipping */
449 if (x1 < 0)
450 x1 = 0;
451 if (x2 >= current_vp->width)
452 x2 = current_vp->width-1;
453
454 dst = LCDADDR(x1 + current_vp->x, y + current_vp->y);
455 dst_end = dst - (x2 - x1) * LCD_HEIGHT;
456
457 do
458 {
459 pfunc(dst);
460 dst -= LCD_HEIGHT;
461 }
462 while (dst >= dst_end);
463}
464
465/* Draw a vertical line (optimised) */
466void lcd_vline(int x, int y1, int y2)
467{
468 int y, height;
469 unsigned bits = 0;
470 enum fill_opt fillopt = OPT_NONE;
471 fb_data *dst, *dst_end;
472
473 /* direction flip */
474 if (y2 < y1)
475 {
476 y = y1;
477 y1 = y2;
478 y2 = y;
479 }
480
481 /* nothing to draw? */
482 if (((unsigned)x >= (unsigned)current_vp->width) ||
483 (y1 >= current_vp->height) ||
484 (y2 < 0))
485 return;
486
487 /* drawmode and optimisation */
488 if (current_vp->drawmode & DRMODE_INVERSEVID)
489 {
490 if (current_vp->drawmode & DRMODE_BG)
491 {
492 if (!lcd_backdrop)
493 {
494 fillopt = OPT_SET;
495 bits = current_vp->bg_pattern;
496 }
497 else
498 fillopt = OPT_COPY;
499 }
500 }
501 else
502 {
503 if (current_vp->drawmode & DRMODE_FG)
504 {
505 fillopt = OPT_SET;
506 bits = current_vp->fg_pattern;
507 }
508 }
509 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT)
510 return;
511
512 /* clipping */
513 if (y1 < 0)
514 y1 = 0;
515 if (y2 >= current_vp->height)
516 y2 = current_vp->height-1;
517
518 height = y2 - y1 + 1;
519
520 /* Adjust y1 and x to viewport */
521 y1 += current_vp->y;
522 x += current_vp->x;
523
524 dst = LCDADDR(x, y1);
525
526 switch (fillopt)
527 {
528 case OPT_SET:
529 memset16(dst, bits, height);
530 break;
531
532 case OPT_COPY:
533 memcpy(dst, (void *)((long)dst + lcd_backdrop_offset),
534 height * sizeof(fb_data));
535 break;
536
537 case OPT_NONE: /* DRMODE_COMPLEMENT */
538 dst_end = dst + height;
539 do
540 *dst = ~(*dst);
541 while (++dst < dst_end);
542 break;
543 }
544}
545
546/* Draw a rectangular box */
547void lcd_drawrect(int x, int y, int width, int height)
548{
549 if ((width <= 0) || (height <= 0))
550 return;
551
552 int x2 = x + width - 1;
553 int y2 = y + height - 1;
554
555 lcd_vline(x, y, y2);
556 lcd_vline(x2, y, y2);
557 lcd_hline(x, x2, y);
558 lcd_hline(x, x2, y2);
559}
560
561/* Fill a rectangular area */
562void lcd_fillrect(int x, int y, int width, int height)
563{
564 unsigned bits = 0;
565 enum fill_opt fillopt = OPT_NONE;
566 fb_data *dst, *dst_end;
567
568 /* nothing to draw? */
569 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
570 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
571 return;
572
573 /* drawmode and optimisation */
574 if (current_vp->drawmode & DRMODE_INVERSEVID)
575 {
576 if (current_vp->drawmode & DRMODE_BG)
577 {
578 if (!lcd_backdrop)
579 {
580 fillopt = OPT_SET;
581 bits = current_vp->bg_pattern;
582 }
583 else
584 fillopt = OPT_COPY;
585 }
586 }
587 else
588 {
589 if (current_vp->drawmode & DRMODE_FG)
590 {
591 fillopt = OPT_SET;
592 bits = current_vp->fg_pattern;
593 }
594 }
595 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT)
596 return;
597
598 /* clipping */
599 if (x < 0)
600 {
601 width += x;
602 x = 0;
603 }
604 if (y < 0)
605 {
606 height += y;
607 y = 0;
608 }
609 if (x + width > current_vp->width)
610 width = current_vp->width - x;
611 if (y + height > current_vp->height)
612 height = current_vp->height - y;
613
614 dst = LCDADDR(current_vp->x + x, current_vp->y + y);
615 dst_end = dst - width * LCD_HEIGHT;
616
617 do
618 {
619 fb_data *dst_col, *col_end;
620
621 switch (fillopt)
622 {
623 case OPT_SET:
624 memset16(dst, bits, height);
625 break;
626
627 case OPT_COPY:
628 memcpy(dst, (void *)((long)dst + lcd_backdrop_offset),
629 height * sizeof(fb_data));
630 break;
631
632 case OPT_NONE: /* DRMODE_COMPLEMENT */
633 dst_col = dst;
634 col_end = dst_col + height;
635 do
636 *dst_col = ~(*dst_col);
637 while (++dst_col < col_end);
638 break;
639 }
640 dst-=LCD_HEIGHT;
641 }
642 while (dst > dst_end);
643}
644
645/* About Rockbox' internal monochrome bitmap format:
646 *
647 * A bitmap contains one bit for every pixel that defines if that pixel is
648 * black (1) or white (0). Bits within a byte are arranged vertically, LSB
649 * at top.
650 * The bytes are stored in row-major order, with byte 0 being top left,
651 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
652 * 0..7, the second row defines pixel row 8..15 etc.
653 *
654 * This is the mono bitmap format used on all other targets so far; the
655 * pixel packing doesn't really matter on a 8bit+ target. */
656
657/* Draw a partial monochrome bitmap */
658
659void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
660 int src_y, int stride, int x, int y,
661 int width, int height)
662{
663 const unsigned char *src_end;
664 fb_data *dst, *dst_end;
665 unsigned dmask = 0x100; /* bit 8 == sentinel */
666 int drmode = current_vp->drawmode;
667
668 /* nothing to draw? */
669 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
670 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
671 return;
672
673 /* clipping */
674 if (x < 0)
675 {
676 width += x;
677 src_x -= x;
678 x = 0;
679 }
680 if (y < 0)
681 {
682 height += y;
683 src_y -= y;
684 y = 0;
685 }
686 if (x + width > current_vp->width)
687 width = current_vp->width - x;
688 if (y + height > current_vp->height)
689 height = current_vp->height - y;
690
691 src += stride * (src_y >> 3) + src_x; /* move starting point */
692 src_y &= 7;
693 src_end = src + width;
694 dst = LCDADDR(current_vp->x + x, current_vp->y + y);
695 dst_end = dst + height;
696
697 if (drmode & DRMODE_INVERSEVID)
698 {
699 dmask = 0x1ff; /* bit 8 == sentinel */
700 drmode &= DRMODE_SOLID; /* mask out inversevid */
701 }
702
703 do
704 {
705 const unsigned char *src_col = src++;
706 unsigned data = (*src_col ^ dmask) >> src_y;
707 fb_data *dst_col = dst;
708 int fg, bg;
709 long bo;
710
711#define UPDATE_SRC do { \
712 data >>= 1; \
713 if (data == 0x001) { \
714 src_col += stride; \
715 data = *src_col ^ dmask; \
716 } \
717 } while (0)
718
719 switch (drmode)
720 {
721 case DRMODE_COMPLEMENT:
722 do
723 {
724 if (data & 0x01)
725 *dst_col = ~(*dst_col);
726
727 dst_col++;
728 UPDATE_SRC;
729 }
730 while (dst_col < dst_end);
731 break;
732
733 case DRMODE_BG:
734 if (lcd_backdrop)
735 {
736 bo = lcd_backdrop_offset;
737 do
738 {
739 if (!(data & 0x01))
740 *dst_col = *(fb_data *)((long)dst_col + bo);
741
742 dst_col++;
743 UPDATE_SRC;
744 }
745 while (dst_col < dst_end);
746 }
747 else
748 {
749 bg = current_vp->bg_pattern;
750 do
751 {
752 if (!(data & 0x01))
753 *dst_col = bg;
754
755 dst_col++;
756 UPDATE_SRC;
757 }
758 while (dst_col < dst_end);
759 }
760 break;
761
762 case DRMODE_FG:
763 fg = current_vp->fg_pattern;
764 do
765 {
766 if (data & 0x01)
767 *dst_col = fg;
768
769 dst_col++;
770 UPDATE_SRC;
771 }
772 while (dst_col < dst_end);
773 break;
774
775 case DRMODE_SOLID:
776 fg = current_vp->fg_pattern;
777 if (lcd_backdrop)
778 {
779 bo = lcd_backdrop_offset;
780 do
781 {
782 *dst_col = (data & 0x01) ? fg
783 : *(fb_data *)((long)dst_col + bo);
784 dst_col++;
785 UPDATE_SRC;
786 }
787 while (dst_col < dst_end);
788 }
789 else
790 {
791 bg = current_vp->bg_pattern;
792 do
793 {
794 *dst_col = (data & 0x01) ? fg : bg;
795 dst_col ++;
796 UPDATE_SRC;
797 }
798 while (dst_col < dst_end);
799 }
800 break;
801 }
802
803 dst -= LCD_HEIGHT;
804 dst_end -= LCD_HEIGHT;
805 } while (src < src_end);
806}
807/* Draw a full monochrome bitmap */
808void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int height)
809{
810 lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height);
811}
812
813/* Draw a partial native bitmap */
814void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
815 int stride, int x, int y, int width,
816 int height)
817{
818 fb_data *dst, *dst_end;
819
820 /* nothing to draw? */
821 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
822 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
823 return;
824
825 /* clipping */
826 if (x < 0)
827 {
828 width += x;
829 src_x -= x;
830 x = 0;
831 }
832 if (y < 0)
833 {
834 height += y;
835 src_y -= y;
836 y = 0;
837 }
838 if (x + width > current_vp->width)
839 width = current_vp->width - x;
840 if (y + height > current_vp->height)
841 height = current_vp->height - y;
842
843 src += stride * src_x + src_y; /* move starting point */
844 dst = LCDADDR(current_vp->x + x, current_vp->y + y);
845 dst_end = dst - width * LCD_HEIGHT;
846
847 do
848 {
849 memcpy(dst, src, height * sizeof(fb_data));
850 src += stride;
851 dst -= LCD_HEIGHT;
852 }
853 while (dst > dst_end);
854}
855
856/* Draw a full native bitmap */
857void lcd_bitmap(const fb_data *src, int x, int y, int width, int height)
858{
859 lcd_bitmap_part(src, 0, 0, STRIDE(width, height), x, y, width, height);
860}
861
862#if !defined(TOSHIBA_GIGABEAT_F) && !defined(TOSHIBA_GIGABEAT_S) \
863 || defined(SIMULATOR)
864/* Draw a partial native bitmap */
865void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
866 int src_y, int stride, int x,
867 int y, int width, int height)
868{
869 fb_data *dst, *dst_end;
870
871 /* nothing to draw? */
872 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
873 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
874 return;
875
876 /* clipping */
877 if (x < 0)
878 {
879 width += x;
880 src_x -= x;
881 x = 0;
882 }
883 if (y < 0)
884 {
885 height += y;
886 src_y -= y;
887 y = 0;
888 }
889 if (x + width > current_vp->width)
890 width = current_vp->width - x;
891 if (y + height > current_vp->height)
892 height = current_vp->height - y;
893
894 src += stride * src_x + src_y; /* move starting point */
895 dst = LCDADDR(current_vp->x + x, current_vp->y + y);
896 dst_end = dst - width * LCD_HEIGHT;
897
898 do
899 {
900 int i;
901 for(i = 0;i < height;i++)
902 {
903 if (src[i] == REPLACEWITHFG_COLOR)
904 dst[i] = current_vp->fg_pattern;
905 else if(src[i] != TRANSPARENT_COLOR)
906 dst[i] = src[i];
907 }
908 src += stride;
909 dst -= LCD_HEIGHT;
910 }
911 while (dst > dst_end);
912}
913#endif /* !defined(TOSHIBA_GIGABEAT_F) || defined(SIMULATOR) */
914
915/* Draw a full native bitmap with a transparent color */
916void lcd_bitmap_transparent(const fb_data *src, int x, int y,
917 int width, int height)
918{
919 lcd_bitmap_transparent_part(src, 0, 0,
920 STRIDE(width, height), x, y, width, height);
921}
922
923#include "lcd-bitmap-common.c"