fuzev2: prevent button light flickering when accessing µSD
[kugel-rb.git] / firmware / drivers / lcd-16bit-vert.c
blob2b4faef4a14165f3aa8900550ba426dd0bb5bb29
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 by Dave Chapman
11 * Copyright (C) 2009 by Karl Kurbjun
13 * Rockbox driver for 16-bit colour LCDs with vertical strides
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 ****************************************************************************/
24 #include "config.h"
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"
41 enum fill_opt {
42 OPT_NONE = 0,
43 OPT_SET,
44 OPT_COPY
47 /*** globals ***/
48 fb_data lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]
49 IRAM_LCDFRAMEBUFFER CACHEALIGN_AT_LEAST_ATTR(16);
52 static fb_data* lcd_backdrop = NULL;
53 static long lcd_backdrop_offset IDATA_ATTR = 0;
55 static struct viewport default_vp =
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,
70 /* The Gigabeat target build requires access to the current fg_pattern
71 in lcd-meg-fx.c */
72 #if defined(SIMULATOR)
73 static struct viewport* current_vp IDATA_ATTR = &default_vp;
74 #else
75 struct viewport* current_vp IDATA_ATTR = &default_vp;
76 #endif
78 /* LCD init */
79 void lcd_init(void)
81 lcd_clear_display();
83 /* Call device specific init */
84 lcd_init_device();
85 scroll_init();
87 /*** Viewports ***/
89 void lcd_set_viewport(struct viewport* vp)
91 if (vp == NULL)
92 current_vp = &default_vp;
93 else
94 current_vp = vp;
96 #if defined(SIMULATOR)
97 /* Force the viewport to be within bounds. If this happens it should
98 * be considered an error - the viewport will not draw as it might be
99 * expected.
101 if((unsigned) current_vp->x > (unsigned) LCD_WIDTH
102 || (unsigned) current_vp->y > (unsigned) LCD_HEIGHT
103 || current_vp->x + current_vp->width > LCD_WIDTH
104 || current_vp->y + current_vp->height > LCD_HEIGHT)
106 #if !defined(HAVE_VIEWPORT_CLIP)
107 DEBUGF("ERROR: "
108 #else
109 DEBUGF("NOTE: "
110 #endif
111 "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n",
112 current_vp->x, current_vp->y,
113 current_vp->width, current_vp->height);
116 #endif
119 void lcd_update_viewport(void)
121 lcd_update_rect(current_vp->x, current_vp->y,
122 current_vp->width, current_vp->height);
125 void lcd_update_viewport_rect(int x, int y, int width, int height)
127 lcd_update_rect(current_vp->x + x, current_vp->y + y, width, height);
130 /*** parameter handling ***/
132 void lcd_set_drawmode(int mode)
134 current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
137 int lcd_get_drawmode(void)
139 return current_vp->drawmode;
142 void lcd_set_foreground(unsigned color)
144 current_vp->fg_pattern = color;
147 unsigned lcd_get_foreground(void)
149 return current_vp->fg_pattern;
152 void lcd_set_background(unsigned color)
154 current_vp->bg_pattern = color;
157 unsigned lcd_get_background(void)
159 return current_vp->bg_pattern;
162 void lcd_set_selector_start(unsigned color)
164 current_vp->lss_pattern = color;
167 void lcd_set_selector_end(unsigned color)
169 current_vp->lse_pattern = color;
172 void lcd_set_selector_text(unsigned color)
174 current_vp->lst_pattern = color;
177 void lcd_set_drawinfo(int mode, unsigned fg_color, unsigned bg_color)
179 lcd_set_drawmode(mode);
180 current_vp->fg_pattern = fg_color;
181 current_vp->bg_pattern = bg_color;
184 int lcd_getwidth(void)
186 return current_vp->width;
189 int lcd_getheight(void)
191 return current_vp->height;
194 void lcd_setfont(int newfont)
196 current_vp->font = newfont;
199 int lcd_getfont(void)
201 return current_vp->font;
204 int lcd_getstringsize(const unsigned char *str, int *w, int *h)
206 return font_getstringsize(str, w, h, current_vp->font);
209 /*** low-level drawing functions ***/
211 #define LCDADDR(x, y) (&lcd_framebuffer[0][0] + LCD_HEIGHT*(x) + (y))
213 static void ICODE_ATTR setpixel(fb_data *address)
215 *address = current_vp->fg_pattern;
218 static void ICODE_ATTR clearpixel(fb_data *address)
220 *address = current_vp->bg_pattern;
223 static void ICODE_ATTR clearimgpixel(fb_data *address)
225 *address = *(fb_data *)((long)address + lcd_backdrop_offset);
228 static void ICODE_ATTR flippixel(fb_data *address)
230 *address = ~(*address);
233 static void ICODE_ATTR nopixel(fb_data *address)
235 (void)address;
238 lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_bgcolor[8] = {
239 flippixel, nopixel, setpixel, setpixel,
240 nopixel, clearpixel, nopixel, clearpixel
243 lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[8] = {
244 flippixel, nopixel, setpixel, setpixel,
245 nopixel, clearimgpixel, nopixel, clearimgpixel
248 lcd_fastpixelfunc_type* const * lcd_fastpixelfuncs = lcd_fastpixelfuncs_bgcolor;
250 void lcd_set_backdrop(fb_data* backdrop)
252 lcd_backdrop = backdrop;
253 if (backdrop)
255 lcd_backdrop_offset = (long)backdrop - (long)&lcd_framebuffer[0][0];
256 lcd_fastpixelfuncs = lcd_fastpixelfuncs_backdrop;
258 else
260 lcd_backdrop_offset = 0;
261 lcd_fastpixelfuncs = lcd_fastpixelfuncs_bgcolor;
265 fb_data* lcd_get_backdrop(void)
267 return lcd_backdrop;
270 /*** drawing functions ***/
272 /* Clear the current viewport */
273 void lcd_clear_viewport(void)
275 fb_data *dst, *dst_end;
277 dst = LCDADDR(current_vp->x, current_vp->y);
278 dst_end = dst + current_vp->width * LCD_HEIGHT;
280 if (current_vp->drawmode & DRMODE_INVERSEVID)
284 memset16(dst, current_vp->fg_pattern, current_vp->height);
285 dst += LCD_HEIGHT;
287 while (dst < dst_end);
289 else
291 if (!lcd_backdrop)
295 memset16(dst, current_vp->bg_pattern, current_vp->height);
296 dst += LCD_HEIGHT;
298 while (dst < dst_end);
300 else
304 memcpy(dst, (void *)((long)dst + lcd_backdrop_offset),
305 current_vp->height * sizeof(fb_data));
306 dst += LCD_HEIGHT;
308 while (dst < dst_end);
312 if (current_vp == &default_vp)
314 lcd_scroll_info.lines = 0;
316 else
318 lcd_scroll_stop(current_vp);
322 /* Clear the whole display */
323 void lcd_clear_display(void)
325 struct viewport* old_vp = current_vp;
327 current_vp = &default_vp;
329 lcd_clear_viewport();
331 current_vp = old_vp;
334 /* Set a single pixel */
335 void lcd_drawpixel(int x, int y)
337 if ( ((unsigned)x < (unsigned)current_vp->width)
338 && ((unsigned)y < (unsigned)current_vp->height)
339 #if defined(HAVE_VIEWPORT_CLIP)
340 && ((unsigned)x < (unsigned)LCD_WIDTH)
341 && ((unsigned)y < (unsigned)LCD_HEIGHT)
342 #endif
344 lcd_fastpixelfuncs[current_vp->drawmode](LCDADDR(current_vp->x+x, current_vp->y+y));
347 /* Draw a line */
348 void lcd_drawline(int x1, int y1, int x2, int y2)
350 int numpixels;
351 int i;
352 int deltax, deltay;
353 int d, dinc1, dinc2;
354 int x, xinc1, xinc2;
355 int y, yinc1, yinc2;
356 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode];
358 deltay = abs(y2 - y1);
359 if (deltay == 0)
361 /* DEBUGF("lcd_drawline() called for horizontal line - optimisation.\n"); */
362 lcd_hline(x1, x2, y1);
363 return;
365 deltax = abs(x2 - x1);
366 if (deltax == 0)
368 /* DEBUGF("lcd_drawline() called for vertical line - optimisation.\n"); */
369 lcd_vline(x1, y1, y2);
370 return;
372 xinc2 = 1;
373 yinc2 = 1;
375 if (deltax >= deltay)
377 numpixels = deltax;
378 d = 2 * deltay - deltax;
379 dinc1 = deltay * 2;
380 dinc2 = (deltay - deltax) * 2;
381 xinc1 = 1;
382 yinc1 = 0;
384 else
386 numpixels = deltay;
387 d = 2 * deltax - deltay;
388 dinc1 = deltax * 2;
389 dinc2 = (deltax - deltay) * 2;
390 xinc1 = 0;
391 yinc1 = 1;
393 numpixels++; /* include endpoints */
395 if (x1 > x2)
397 xinc1 = -xinc1;
398 xinc2 = -xinc2;
401 if (y1 > y2)
403 yinc1 = -yinc1;
404 yinc2 = -yinc2;
407 x = x1;
408 y = y1;
410 for (i = 0; i < numpixels; i++)
412 if ( ((unsigned)x < (unsigned)current_vp->width)
413 && ((unsigned)y < (unsigned)current_vp->height)
414 #if defined(HAVE_VIEWPORT_CLIP)
415 && ((unsigned)x < (unsigned)LCD_WIDTH)
416 && ((unsigned)y < (unsigned)LCD_HEIGHT)
417 #endif
419 pfunc(LCDADDR(x + current_vp->x, y + current_vp->y));
421 if (d < 0)
423 d += dinc1;
424 x += xinc1;
425 y += yinc1;
427 else
429 d += dinc2;
430 x += xinc2;
431 y += yinc2;
436 /* Draw a horizontal line (optimised) */
437 void lcd_hline(int x1, int x2, int y)
439 int x;
440 fb_data *dst, *dst_end;
441 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode];
443 /* direction flip */
444 if (x2 < x1)
446 x = x1;
447 x1 = x2;
448 x2 = x;
451 /******************** In viewport clipping **********************/
452 /* nothing to draw? */
453 if (((unsigned)y >= (unsigned)current_vp->height) ||
454 (x1 >= current_vp->width) ||
455 (x2 < 0))
456 return;
458 if (x1 < 0)
459 x1 = 0;
460 if (x2 >= current_vp->width)
461 x2 = current_vp->width-1;
463 /* Adjust x1 and y to viewport */
464 x1 += current_vp->x;
465 x2 += current_vp->x;
466 y += current_vp->y;
468 #if defined(HAVE_VIEWPORT_CLIP)
469 /********************* Viewport on screen clipping ********************/
470 /* nothing to draw? */
471 if (((unsigned)y >= (unsigned) LCD_HEIGHT) || (x1 >= LCD_WIDTH)
472 || (x2 < 0))
473 return;
475 /* clipping */
476 if (x1 < 0)
477 x1 = 0;
478 if (x2 >= LCD_WIDTH)
479 x2 = LCD_WIDTH-1;
480 #endif
482 dst = LCDADDR(x1 , y );
483 dst_end = dst + (x2 - x1) * LCD_HEIGHT;
487 pfunc(dst);
488 dst += LCD_HEIGHT;
490 while (dst <= dst_end);
493 /* Draw a vertical line (optimised) */
494 void lcd_vline(int x, int y1, int y2)
496 int y, height;
497 unsigned bits = 0;
498 enum fill_opt fillopt = OPT_NONE;
499 fb_data *dst, *dst_end;
501 /* direction flip */
502 if (y2 < y1)
504 y = y1;
505 y1 = y2;
506 y2 = y;
509 /******************** In viewport clipping **********************/
510 /* nothing to draw? */
511 if (((unsigned)x >= (unsigned)current_vp->width) ||
512 (y1 >= current_vp->height) ||
513 (y2 < 0))
514 return;
516 if (y1 < 0)
517 y1 = 0;
518 if (y2 >= current_vp->height)
519 y2 = current_vp->height-1;
521 /* adjust for viewport */
522 x += current_vp->x;
523 y1 += current_vp->y;
524 y2 += current_vp->y;
526 #if defined(HAVE_VIEWPORT_CLIP)
527 /********************* Viewport on screen clipping ********************/
528 /* nothing to draw? */
529 if (( (unsigned) x >= (unsigned)LCD_WIDTH) || (y1 >= LCD_HEIGHT)
530 || (y2 < 0))
531 return;
533 /* clipping */
534 if (y1 < 0)
535 y1 = 0;
536 if (y2 >= LCD_HEIGHT)
537 y2 = LCD_HEIGHT-1;
538 #endif
540 height = y2 - y1 + 1;
542 /* drawmode and optimisation */
543 if (current_vp->drawmode & DRMODE_INVERSEVID)
545 if (current_vp->drawmode & DRMODE_BG)
547 if (!lcd_backdrop)
549 fillopt = OPT_SET;
550 bits = current_vp->bg_pattern;
552 else
553 fillopt = OPT_COPY;
556 else
558 if (current_vp->drawmode & DRMODE_FG)
560 fillopt = OPT_SET;
561 bits = current_vp->fg_pattern;
564 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT)
565 return;
567 dst = LCDADDR(x, y1);
569 switch (fillopt)
571 case OPT_SET:
572 memset16(dst, bits, height);
573 break;
575 case OPT_COPY:
576 memcpy(dst, (void *)((long)dst + lcd_backdrop_offset),
577 height * sizeof(fb_data));
578 break;
580 case OPT_NONE: /* DRMODE_COMPLEMENT */
581 dst_end = dst + height;
583 *dst = ~(*dst);
584 while (++dst < dst_end);
585 break;
589 /* Draw a rectangular box */
590 void lcd_drawrect(int x, int y, int width, int height)
592 if ((width <= 0) || (height <= 0))
593 return;
595 int x2 = x + width - 1;
596 int y2 = y + height - 1;
598 lcd_vline(x, y, y2);
599 lcd_vline(x2, y, y2);
600 lcd_hline(x, x2, y);
601 lcd_hline(x, x2, y2);
604 /* Fill a rectangular area */
605 void lcd_fillrect(int x, int y, int width, int height)
607 unsigned bits = 0;
608 enum fill_opt fillopt = OPT_NONE;
609 fb_data *dst, *dst_end;
611 /******************** In viewport clipping **********************/
612 /* nothing to draw? */
613 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
614 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
615 return;
617 if (x < 0)
619 width += x;
620 x = 0;
622 if (y < 0)
624 height += y;
625 y = 0;
627 if (x + width > current_vp->width)
628 width = current_vp->width - x;
629 if (y + height > current_vp->height)
630 height = current_vp->height - y;
632 /* adjust for viewport */
633 x += current_vp->x;
634 y += current_vp->y;
636 #if defined(HAVE_VIEWPORT_CLIP)
637 /********************* Viewport on screen clipping ********************/
638 /* nothing to draw? */
639 if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
640 || (x + width <= 0) || (y + height <= 0))
641 return;
643 /* clip image in viewport in screen */
644 if (x < 0)
646 width += x;
647 x = 0;
649 if (y < 0)
651 height += y;
652 y = 0;
654 if (x + width > LCD_WIDTH)
655 width = LCD_WIDTH - x;
656 if (y + height > LCD_HEIGHT)
657 height = LCD_HEIGHT - y;
658 #endif
660 /* drawmode and optimisation */
661 if (current_vp->drawmode & DRMODE_INVERSEVID)
663 if (current_vp->drawmode & DRMODE_BG)
665 if (!lcd_backdrop)
667 fillopt = OPT_SET;
668 bits = current_vp->bg_pattern;
670 else
671 fillopt = OPT_COPY;
674 else
676 if (current_vp->drawmode & DRMODE_FG)
678 fillopt = OPT_SET;
679 bits = current_vp->fg_pattern;
682 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT)
683 return;
685 dst = LCDADDR(x, y);
686 dst_end = dst + width * LCD_HEIGHT;
690 fb_data *dst_col, *col_end;
692 switch (fillopt)
694 case OPT_SET:
695 memset16(dst, bits, height);
696 break;
698 case OPT_COPY:
699 memcpy(dst, (void *)((long)dst + lcd_backdrop_offset),
700 height * sizeof(fb_data));
701 break;
703 case OPT_NONE: /* DRMODE_COMPLEMENT */
704 dst_col = dst;
705 col_end = dst_col + height;
707 *dst_col = ~(*dst_col);
708 while (++dst_col < col_end);
709 break;
711 dst+=LCD_HEIGHT;
713 while (dst < dst_end);
716 /* About Rockbox' internal monochrome bitmap format:
718 * A bitmap contains one bit for every pixel that defines if that pixel is
719 * black (1) or white (0). Bits within a byte are arranged vertically, LSB
720 * at top.
721 * The bytes are stored in row-major order, with byte 0 being top left,
722 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
723 * 0..7, the second row defines pixel row 8..15 etc.
725 * This is the mono bitmap format used on all other targets so far; the
726 * pixel packing doesn't really matter on a 8bit+ target. */
728 /* Draw a partial monochrome bitmap */
730 void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
731 int src_y, int stride, int x, int y,
732 int width, int height)
734 const unsigned char *src_end;
735 fb_data *dst, *dst_end;
736 unsigned dmask = 0x100; /* bit 8 == sentinel */
737 int drmode = current_vp->drawmode;
739 /******************** Image in viewport clipping **********************/
740 /* nothing to draw? */
741 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
742 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
743 return;
745 if (x < 0)
747 width += x;
748 src_x -= x;
749 x = 0;
751 if (y < 0)
753 height += y;
754 src_y -= y;
755 y = 0;
757 if (x + width > current_vp->width)
758 width = current_vp->width - x;
759 if (y + height > current_vp->height)
760 height = current_vp->height - y;
762 /* adjust for viewport */
763 x += current_vp->x;
764 y += current_vp->y;
766 #if defined(HAVE_VIEWPORT_CLIP)
767 /********************* Viewport on screen clipping ********************/
768 /* nothing to draw? */
769 if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
770 || (x + width <= 0) || (y + height <= 0))
771 return;
773 /* clip image in viewport in screen */
774 if (x < 0)
776 width += x;
777 src_x -= x;
778 x = 0;
780 if (y < 0)
782 height += y;
783 src_y -= y;
784 y = 0;
786 if (x + width > LCD_WIDTH)
787 width = LCD_WIDTH - x;
788 if (y + height > LCD_HEIGHT)
789 height = LCD_HEIGHT - y;
790 #endif
792 src += stride * (src_y >> 3) + src_x; /* move starting point */
793 src_y &= 7;
794 src_end = src + width;
795 dst = LCDADDR(x, y);
796 dst_end = dst + height;
798 if (drmode & DRMODE_INVERSEVID)
800 dmask = 0x1ff; /* bit 8 == sentinel */
801 drmode &= DRMODE_SOLID; /* mask out inversevid */
806 const unsigned char *src_col = src++;
807 unsigned data = (*src_col ^ dmask) >> src_y;
808 fb_data *dst_col = dst;
809 int fg, bg;
810 long bo;
812 #define UPDATE_SRC do { \
813 data >>= 1; \
814 if (data == 0x001) { \
815 src_col += stride; \
816 data = *src_col ^ dmask; \
818 } while (0)
820 switch (drmode)
822 case DRMODE_COMPLEMENT:
825 if (data & 0x01)
826 *dst_col = ~(*dst_col);
828 dst_col++;
829 UPDATE_SRC;
831 while (dst_col < dst_end);
832 break;
834 case DRMODE_BG:
835 if (lcd_backdrop)
837 bo = lcd_backdrop_offset;
840 if (!(data & 0x01))
841 *dst_col = *(fb_data *)((long)dst_col + bo);
843 dst_col++;
844 UPDATE_SRC;
846 while (dst_col < dst_end);
848 else
850 bg = current_vp->bg_pattern;
853 if (!(data & 0x01))
854 *dst_col = bg;
856 dst_col++;
857 UPDATE_SRC;
859 while (dst_col < dst_end);
861 break;
863 case DRMODE_FG:
864 fg = current_vp->fg_pattern;
867 if (data & 0x01)
868 *dst_col = fg;
870 dst_col++;
871 UPDATE_SRC;
873 while (dst_col < dst_end);
874 break;
876 case DRMODE_SOLID:
877 fg = current_vp->fg_pattern;
878 if (lcd_backdrop)
880 bo = lcd_backdrop_offset;
883 *dst_col = (data & 0x01) ? fg
884 : *(fb_data *)((long)dst_col + bo);
885 dst_col++;
886 UPDATE_SRC;
888 while (dst_col < dst_end);
890 else
892 bg = current_vp->bg_pattern;
895 *dst_col = (data & 0x01) ? fg : bg;
896 dst_col ++;
897 UPDATE_SRC;
899 while (dst_col < dst_end);
901 break;
904 dst += LCD_HEIGHT;
905 dst_end += LCD_HEIGHT;
906 } while (src < src_end);
908 /* Draw a full monochrome bitmap */
909 void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int height)
911 lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height);
914 /* Draw a partial native bitmap */
915 void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
916 int stride, int x, int y, int width,
917 int height)
919 fb_data *dst, *dst_end;
921 /******************** Image in viewport clipping **********************/
922 /* nothing to draw? */
923 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
924 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
925 return;
927 if (x < 0)
929 width += x;
930 src_x -= x;
931 x = 0;
933 if (y < 0)
935 height += y;
936 src_y -= y;
937 y = 0;
940 if (x + width > current_vp->width)
941 width = current_vp->width - x;
942 if (y + height > current_vp->height)
943 height = current_vp->height - y;
945 /* adjust for viewport */
946 x += current_vp->x;
947 y += current_vp->y;
949 #if defined(HAVE_VIEWPORT_CLIP)
950 /********************* Viewport on screen clipping ********************/
951 /* nothing to draw? */
952 if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
953 || (x + width <= 0) || (y + height <= 0))
954 return;
956 /* clip image in viewport in screen */
957 if (x < 0)
959 width += x;
960 src_x -= x;
961 x = 0;
963 if (y < 0)
965 height += y;
966 src_y -= y;
967 y = 0;
969 if (x + width > LCD_WIDTH)
970 width = LCD_WIDTH - x;
971 if (y + height > LCD_HEIGHT)
972 height = LCD_HEIGHT - y;
973 #endif
975 src += stride * src_x + src_y; /* move starting point */
976 dst = LCDADDR(x, y);
977 dst_end = dst + width * LCD_HEIGHT;
981 memcpy(dst, src, height * sizeof(fb_data));
982 src += stride;
983 dst += LCD_HEIGHT;
985 while (dst < dst_end);
988 /* Draw a full native bitmap */
989 void lcd_bitmap(const fb_data *src, int x, int y, int width, int height)
991 lcd_bitmap_part(src, 0, 0, STRIDE(SCREEN_MAIN, width, height), x, y, width, height);
994 #if !defined(TOSHIBA_GIGABEAT_F) && !defined(TOSHIBA_GIGABEAT_S) \
995 || defined(SIMULATOR)
996 /* Draw a partial native bitmap */
997 void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
998 int src_y, int stride, int x,
999 int y, int width, int height)
1001 fb_data *dst, *dst_end;
1003 /******************** Image in viewport clipping **********************/
1004 /* nothing to draw? */
1005 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
1006 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
1007 return;
1009 if (x < 0)
1011 width += x;
1012 src_x -= x;
1013 x = 0;
1015 if (y < 0)
1017 height += y;
1018 src_y -= y;
1019 y = 0;
1022 if (x + width > current_vp->width)
1023 width = current_vp->width - x;
1024 if (y + height > current_vp->height)
1025 height = current_vp->height - y;
1027 /* adjust for viewport */
1028 x += current_vp->x;
1029 y += current_vp->y;
1031 #if defined(HAVE_VIEWPORT_CLIP)
1032 /********************* Viewport on screen clipping ********************/
1033 /* nothing to draw? */
1034 if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
1035 || (x + width <= 0) || (y + height <= 0))
1036 return;
1038 /* clip image in viewport in screen */
1039 if (x < 0)
1041 width += x;
1042 src_x -= x;
1043 x = 0;
1045 if (y < 0)
1047 height += y;
1048 src_y -= y;
1049 y = 0;
1051 if (x + width > LCD_WIDTH)
1052 width = LCD_WIDTH - x;
1053 if (y + height > LCD_HEIGHT)
1054 height = LCD_HEIGHT - y;
1055 #endif
1057 src += stride * src_x + src_y; /* move starting point */
1058 dst = LCDADDR(x, y);
1059 dst_end = dst + width * LCD_HEIGHT;
1063 int i;
1064 for(i = 0;i < height;i++)
1066 if (src[i] == REPLACEWITHFG_COLOR)
1067 dst[i] = current_vp->fg_pattern;
1068 else if(src[i] != TRANSPARENT_COLOR)
1069 dst[i] = src[i];
1071 src += stride;
1072 dst += LCD_HEIGHT;
1074 while (dst < dst_end);
1076 #endif /* !defined(TOSHIBA_GIGABEAT_F) || defined(SIMULATOR) */
1078 /* Draw a full native bitmap with a transparent color */
1079 void lcd_bitmap_transparent(const fb_data *src, int x, int y,
1080 int width, int height)
1082 lcd_bitmap_transparent_part(src, 0, 0,
1083 STRIDE(SCREEN_MAIN, width, height), x, y, width, height);
1086 #include "lcd-bitmap-common.c"