diff options
author | Jens Arnold <amiconn@rockbox.org> | 2005-06-28 23:15:47 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2005-06-28 23:15:47 +0000 |
commit | 7e11acbce9b9a63c28ded055d02301175391e027 (patch) | |
tree | ea8d30e7281e8d720d6dc8ea51804e1749282697 /firmware/drivers/lcd-recorder.c | |
parent | c2bf5dfe12978b44d5d890a37f256c8d9f510660 (diff) | |
download | rockbox-7e11acbce9b9a63c28ded055d02301175391e027.tar.gz rockbox-7e11acbce9b9a63c28ded055d02301175391e027.zip |
Second part of graphics api rework. Bitmap drawing and text output converted; some code cleanup and more optimisations.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6906 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/lcd-recorder.c')
-rw-r--r-- | firmware/drivers/lcd-recorder.c | 360 |
1 files changed, 188 insertions, 172 deletions
diff --git a/firmware/drivers/lcd-recorder.c b/firmware/drivers/lcd-recorder.c index d464e30f0a..9513c26380 100644 --- a/firmware/drivers/lcd-recorder.c +++ b/firmware/drivers/lcd-recorder.c | |||
@@ -265,20 +265,20 @@ void lcd_init(void) | |||
265 | /*** Update functions ***/ | 265 | /*** Update functions ***/ |
266 | 266 | ||
267 | /* Performance function that works with an external buffer | 267 | /* Performance function that works with an external buffer |
268 | note that y and height are in 8-pixel units! */ | 268 | note that by and bheight are in 8-pixel units! */ |
269 | void lcd_blit(const unsigned char* p_data, int x, int y, int width, | 269 | void lcd_blit(const unsigned char* data, int x, int by, int width, |
270 | int height, int stride) | 270 | int bheight, int stride) |
271 | { | 271 | { |
272 | /* Copy display bitmap to hardware */ | 272 | /* Copy display bitmap to hardware */ |
273 | while (height--) | 273 | while (bheight--) |
274 | { | 274 | { |
275 | lcd_write_command (LCD_CNTL_PAGE | (y++ & 0xf)); | 275 | lcd_write_command (LCD_CNTL_PAGE | (by++ & 0xf)); |
276 | lcd_write_command (LCD_CNTL_HIGHCOL | (((x+xoffset)>>4) & 0xf)); | 276 | lcd_write_command (LCD_CNTL_HIGHCOL | (((x+xoffset)>>4) & 0xf)); |
277 | lcd_write_command (LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf)); | 277 | lcd_write_command (LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf)); |
278 | 278 | ||
279 | lcd_write_data(p_data, width); | 279 | lcd_write_data(data, width); |
280 | p_data += stride; | 280 | data += stride; |
281 | } | 281 | } |
282 | } | 282 | } |
283 | 283 | ||
284 | 284 | ||
@@ -302,29 +302,31 @@ void lcd_update(void) | |||
302 | 302 | ||
303 | /* Update a fraction of the display. */ | 303 | /* Update a fraction of the display. */ |
304 | void lcd_update_rect(int, int, int, int) __attribute__ ((section (".icode"))); | 304 | void lcd_update_rect(int, int, int, int) __attribute__ ((section (".icode"))); |
305 | void lcd_update_rect(int x_start, int y, int width, int height) | 305 | void lcd_update_rect(int x, int y, int width, int height) |
306 | { | 306 | { |
307 | int ymax; | 307 | int ymax; |
308 | 308 | ||
309 | /* The Y coordinates have to work on even 8 pixel rows */ | 309 | /* The Y coordinates have to work on even 8 pixel rows */ |
310 | ymax = (y + height-1)/8; | 310 | ymax = (y + height-1) >> 3; |
311 | y /= 8; | 311 | y >>= 3; |
312 | 312 | ||
313 | if(x_start + width > LCD_WIDTH) | 313 | if(x + width > LCD_WIDTH) |
314 | width = LCD_WIDTH - x_start; | 314 | width = LCD_WIDTH - x; |
315 | if (width <= 0) | 315 | if (width <= 0) |
316 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ | 316 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ |
317 | if(ymax >= LCD_HEIGHT/8) | 317 | if(ymax >= LCD_HEIGHT/8) |
318 | ymax = LCD_HEIGHT/8-1; | 318 | ymax = LCD_HEIGHT/8-1; |
319 | |||
320 | x += xoffset; | ||
319 | 321 | ||
320 | /* Copy specified rectange bitmap to hardware */ | 322 | /* Copy specified rectange bitmap to hardware */ |
321 | for (; y <= ymax; y++) | 323 | for (; y <= ymax; y++) |
322 | { | 324 | { |
323 | lcd_write_command (LCD_CNTL_PAGE | (y & 0xf)); | 325 | lcd_write_command (LCD_CNTL_PAGE | (y & 0xf)); |
324 | lcd_write_command (LCD_CNTL_HIGHCOL | (((x_start+xoffset)>>4) & 0xf)); | 326 | lcd_write_command (LCD_CNTL_HIGHCOL | ((x >> 4) & 0xf)); |
325 | lcd_write_command (LCD_CNTL_LOWCOL | ((x_start+xoffset) & 0xf)); | 327 | lcd_write_command (LCD_CNTL_LOWCOL | (x & 0xf)); |
326 | 328 | ||
327 | lcd_write_data (&lcd_framebuffer[y][x_start], width); | 329 | lcd_write_data (&lcd_framebuffer[y][x], width); |
328 | } | 330 | } |
329 | } | 331 | } |
330 | #endif /* !SIMULATOR */ | 332 | #endif /* !SIMULATOR */ |
@@ -390,8 +392,10 @@ static void nopixel(int x, int y) | |||
390 | (void)y; | 392 | (void)y; |
391 | } | 393 | } |
392 | 394 | ||
393 | lcd_pixelfunc_type* pixelfunc[8] = {flippixel, nopixel, setpixel, setpixel, | 395 | lcd_pixelfunc_type* pixelfunc[8] = { |
394 | nopixel, clearpixel, nopixel, clearpixel}; | 396 | flippixel, nopixel, setpixel, setpixel, |
397 | nopixel, clearpixel, nopixel, clearpixel | ||
398 | }; | ||
395 | 399 | ||
396 | static void flipblock(unsigned char *address, unsigned mask, unsigned bits) | 400 | static void flipblock(unsigned char *address, unsigned mask, unsigned bits) |
397 | { | 401 | { |
@@ -413,7 +417,30 @@ static void solidblock(unsigned char *address, unsigned mask, unsigned bits) | |||
413 | *address = (*address & ~mask) | (bits & mask); | 417 | *address = (*address & ~mask) | (bits & mask); |
414 | } | 418 | } |
415 | 419 | ||
416 | lcd_blockfunc_type* blockfunc[4] = {flipblock, bgblock, fgblock, solidblock}; | 420 | static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) |
421 | { | ||
422 | *address ^= (~bits & mask); | ||
423 | } | ||
424 | |||
425 | static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
426 | { | ||
427 | *address &= ~(bits & mask); | ||
428 | } | ||
429 | |||
430 | static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
431 | { | ||
432 | *address |= (~bits & mask); | ||
433 | } | ||
434 | |||
435 | static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
436 | { | ||
437 | *address = (*address & ~mask) | (~bits & mask); | ||
438 | } | ||
439 | |||
440 | lcd_blockfunc_type* blockfunc[8] = { | ||
441 | flipblock, bgblock, fgblock, solidblock, | ||
442 | flipinvblock, bginvblock, fginvblock, solidinvblock | ||
443 | }; | ||
417 | 444 | ||
418 | /*** drawing functions ***/ | 445 | /*** drawing functions ***/ |
419 | 446 | ||
@@ -509,7 +536,7 @@ void lcd_hline(int x1, int x2, int y) | |||
509 | { | 536 | { |
510 | int x; | 537 | int x; |
511 | unsigned char *dst; | 538 | unsigned char *dst; |
512 | unsigned char mask, bits; | 539 | unsigned mask; |
513 | lcd_blockfunc_type *bfunc; | 540 | lcd_blockfunc_type *bfunc; |
514 | 541 | ||
515 | /* direction flip */ | 542 | /* direction flip */ |
@@ -530,13 +557,12 @@ void lcd_hline(int x1, int x2, int y) | |||
530 | if (x2 >= LCD_WIDTH) | 557 | if (x2 >= LCD_WIDTH) |
531 | x2 = LCD_WIDTH-1; | 558 | x2 = LCD_WIDTH-1; |
532 | 559 | ||
533 | bfunc = blockfunc[drawmode & ~DRMODE_INVERSEVID]; | 560 | bfunc = blockfunc[drawmode]; |
534 | bits = (drawmode & DRMODE_INVERSEVID) ? 0x00 : 0xFFu; | 561 | dst = &lcd_framebuffer[y>>3][x1]; |
535 | dst = &lcd_framebuffer[y/8][x1]; | ||
536 | mask = 1 << (y & 7); | 562 | mask = 1 << (y & 7); |
537 | 563 | ||
538 | for (x = x1; x <= x2; x++) | 564 | for (x = x1; x <= x2; x++) |
539 | bfunc(dst++, mask, bits); | 565 | bfunc(dst++, mask, 0xFFu); |
540 | } | 566 | } |
541 | 567 | ||
542 | /* Draw a vertical line (optimised) */ | 568 | /* Draw a vertical line (optimised) */ |
@@ -544,7 +570,7 @@ void lcd_vline(int x, int y1, int y2) | |||
544 | { | 570 | { |
545 | int ny; | 571 | int ny; |
546 | unsigned char *dst; | 572 | unsigned char *dst; |
547 | unsigned char mask_top, mask_bottom, bits; | 573 | unsigned mask, mask_bottom; |
548 | lcd_blockfunc_type *bfunc; | 574 | lcd_blockfunc_type *bfunc; |
549 | 575 | ||
550 | /* direction flip */ | 576 | /* direction flip */ |
@@ -565,28 +591,20 @@ void lcd_vline(int x, int y1, int y2) | |||
565 | if (y2 >= LCD_HEIGHT) | 591 | if (y2 >= LCD_HEIGHT) |
566 | y2 = LCD_HEIGHT-1; | 592 | y2 = LCD_HEIGHT-1; |
567 | 593 | ||
568 | bfunc = blockfunc[drawmode & ~DRMODE_INVERSEVID]; | 594 | bfunc = blockfunc[drawmode]; |
569 | bits = (drawmode & DRMODE_INVERSEVID) ? 0x00 : 0xFFu; | 595 | dst = &lcd_framebuffer[y1>>3][x]; |
570 | dst = &lcd_framebuffer[y1/8][x]; | ||
571 | ny = y2 - (y1 & ~7); | 596 | ny = y2 - (y1 & ~7); |
572 | mask_top = 0xFFu << (y1 & 7); | 597 | mask = 0xFFu << (y1 & 7); |
573 | mask_bottom = 0xFFu >> (7 - (ny & 7)); | 598 | mask_bottom = 0xFFu >> (7 - (ny & 7)); |
574 | 599 | ||
575 | if (ny >= 8) | 600 | for (; ny >= 8; ny -= 8) |
576 | { | 601 | { |
577 | bfunc(dst, mask_top, bits); | 602 | bfunc(dst, mask, 0xFFu); |
578 | dst += LCD_WIDTH; | 603 | dst += LCD_WIDTH; |
579 | 604 | mask = 0xFFu; | |
580 | for (; ny > 15; ny -= 8) | ||
581 | { | ||
582 | bfunc(dst, 0xFFu, bits); | ||
583 | dst += LCD_WIDTH; | ||
584 | } | ||
585 | } | 605 | } |
586 | else | 606 | mask_bottom &= mask; |
587 | mask_bottom &= mask_top; | 607 | bfunc(dst, mask_bottom, 0xFFu); |
588 | |||
589 | bfunc(dst, mask_bottom, bits); | ||
590 | } | 608 | } |
591 | 609 | ||
592 | /* Draw a rectangular box */ | 610 | /* Draw a rectangular box */ |
@@ -604,29 +622,19 @@ void lcd_drawrect(int x, int y, int width, int height) | |||
604 | lcd_hline(x, x2, y2); | 622 | lcd_hline(x, x2, y2); |
605 | } | 623 | } |
606 | 624 | ||
607 | /* helper function for lcd_fillrect() */ | ||
608 | static void fillrow(lcd_blockfunc_type *bfunc, unsigned char *address, | ||
609 | int width, unsigned mask, unsigned bits) | ||
610 | { | ||
611 | int i; | ||
612 | |||
613 | for (i = 0; i < width; i++) | ||
614 | bfunc(address++, mask, bits); | ||
615 | } | ||
616 | |||
617 | /* Fill a rectangular area */ | 625 | /* Fill a rectangular area */ |
618 | void lcd_fillrect(int x, int y, int width, int height) | 626 | void lcd_fillrect(int x, int y, int width, int height) |
619 | { | 627 | { |
620 | int ny; | 628 | int ny, i; |
621 | unsigned char *dst; | 629 | unsigned char *dst; |
622 | unsigned char mask_top, mask_bottom, bits; | 630 | unsigned mask, mask_bottom; |
631 | unsigned bits = 0xFFu; | ||
623 | lcd_blockfunc_type *bfunc; | 632 | lcd_blockfunc_type *bfunc; |
624 | bool fillopt = (drawmode & DRMODE_INVERSEVID) ? | 633 | bool fillopt; |
625 | (drawmode & DRMODE_BG) : (drawmode & DRMODE_FG); | ||
626 | 634 | ||
627 | /* nothing to draw? */ | 635 | /* nothing to draw? */ |
628 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 636 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) |
629 | || (x + width < 0) || (y + height < 0)) | 637 | || (x + width <= 0) || (y + height <= 0)) |
630 | return; | 638 | return; |
631 | 639 | ||
632 | /* clipping */ | 640 | /* clipping */ |
@@ -644,38 +652,41 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
644 | width = LCD_WIDTH - x; | 652 | width = LCD_WIDTH - x; |
645 | if (y + height > LCD_HEIGHT) | 653 | if (y + height > LCD_HEIGHT) |
646 | height = LCD_HEIGHT - y; | 654 | height = LCD_HEIGHT - y; |
647 | 655 | ||
648 | bfunc = blockfunc[drawmode & ~DRMODE_INVERSEVID]; | 656 | fillopt = (drawmode & DRMODE_INVERSEVID) ? |
649 | bits = (drawmode & DRMODE_INVERSEVID) ? 0x00 : 0xFFu; | 657 | (drawmode & DRMODE_BG) : (drawmode & DRMODE_FG); |
650 | dst = &lcd_framebuffer[y/8][x]; | 658 | if (fillopt &&(drawmode & DRMODE_INVERSEVID)) |
659 | bits = 0; | ||
660 | bfunc = blockfunc[drawmode]; | ||
661 | dst = &lcd_framebuffer[y>>3][x]; | ||
651 | ny = height - 1 + (y & 7); | 662 | ny = height - 1 + (y & 7); |
652 | mask_top = 0xFFu << (y & 7); | 663 | mask = 0xFFu << (y & 7); |
653 | mask_bottom = 0xFFu >> (7 - (ny & 7)); | 664 | mask_bottom = 0xFFu >> (7 - (ny & 7)); |
654 | 665 | ||
655 | if (ny >= 8) | 666 | for (; ny >= 8; ny -= 8) |
656 | { | 667 | { |
657 | if (fillopt && mask_top == 0xFF) | 668 | if (fillopt && (mask == 0xFFu)) |
658 | memset(dst, bits, width); | 669 | memset(dst, bits, width); |
659 | else | 670 | else |
660 | fillrow(bfunc, dst, width, mask_top, bits); | ||
661 | dst += LCD_WIDTH; | ||
662 | |||
663 | for (; ny > 15; ny -= 8) | ||
664 | { | 671 | { |
665 | if (fillopt) | 672 | unsigned char *dst_row = dst; |
666 | memset(dst, bits, width); | 673 | |
667 | else | 674 | for (i = width; i > 0; i--) |
668 | fillrow(bfunc, dst, width, 0xFFu, bits); | 675 | bfunc(dst_row++, mask, 0xFFu); |
669 | dst += LCD_WIDTH; | ||
670 | } | 676 | } |
677 | |||
678 | dst += LCD_WIDTH; | ||
679 | mask = 0xFFu; | ||
671 | } | 680 | } |
672 | else | 681 | mask_bottom &= mask; |
673 | mask_bottom &= mask_top; | 682 | |
674 | 683 | if (fillopt && (mask_bottom == 0xFFu)) | |
675 | if (fillopt && mask_bottom == 0xFF) | ||
676 | memset(dst, bits, width); | 684 | memset(dst, bits, width); |
677 | else | 685 | else |
678 | fillrow(bfunc, dst, width, mask_bottom, bits); | 686 | { |
687 | for (i = width; i > 0; i--) | ||
688 | bfunc(dst++, mask_bottom, 0xFFu); | ||
689 | } | ||
679 | } | 690 | } |
680 | 691 | ||
681 | /* About Rockbox' internal bitmap format: | 692 | /* About Rockbox' internal bitmap format: |
@@ -689,95 +700,120 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
689 | * | 700 | * |
690 | * This is the same as the internal lcd hw format. */ | 701 | * This is the same as the internal lcd hw format. */ |
691 | 702 | ||
692 | /* Draw a bitmap at (x, y), size (nx, ny) | 703 | /* Draw a partial bitmap */ |
693 | if 'clear' is true, clear destination area first */ | 704 | void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, |
694 | void lcd_bitmap(const unsigned char *src, int x, int y, int nx, int ny, | 705 | int stride, int x, int y, int width, int height) |
695 | bool clear) __attribute__ ((section (".icode"))); | 706 | __attribute__ ((section(".icode"))); |
696 | void lcd_bitmap(const unsigned char *src, int x, int y, int nx, int ny, | 707 | void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, |
697 | bool clear) | 708 | int stride, int x, int y, int width, int height) |
698 | { | 709 | { |
699 | const unsigned char *src_col; | 710 | int shift, ny, i; |
700 | unsigned char *dst, *dst_col; | 711 | unsigned char *dst; |
701 | unsigned int data, mask1, mask2, mask3, mask4; | 712 | unsigned mask, mask_bottom; |
702 | int stride, shift; | 713 | lcd_blockfunc_type *bfunc; |
703 | 714 | ||
704 | if (((unsigned) x >= LCD_WIDTH) || ((unsigned) y >= LCD_HEIGHT)) | 715 | /* nothing to draw? */ |
716 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
717 | || (x + width <= 0) || (y + height <= 0)) | ||
705 | return; | 718 | return; |
719 | |||
720 | /* clipping */ | ||
721 | if (x < 0) | ||
722 | { | ||
723 | width += x; | ||
724 | src_x -= x; | ||
725 | x = 0; | ||
726 | } | ||
727 | if (y < 0) | ||
728 | { | ||
729 | height += y; | ||
730 | src_y -= y; | ||
731 | y = 0; | ||
732 | } | ||
733 | if (x + width > LCD_WIDTH) | ||
734 | width = LCD_WIDTH - x; | ||
735 | if (y + height > LCD_HEIGHT) | ||
736 | height = LCD_HEIGHT - y; | ||
706 | 737 | ||
707 | stride = nx; /* otherwise right-clipping will destroy the image */ | 738 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
739 | src_y &= 7; | ||
740 | y -= src_y; | ||
741 | dst = &lcd_framebuffer[y>>3][x]; | ||
742 | shift = y & 7; | ||
743 | ny = height - 1 + shift + src_y; | ||
708 | 744 | ||
709 | if (((unsigned) (x + nx)) >= LCD_WIDTH) | 745 | bfunc = blockfunc[drawmode]; |
710 | nx = LCD_WIDTH - x; | 746 | mask = 0xFFu << (shift + src_y); |
711 | if (((unsigned) (y + ny)) >= LCD_HEIGHT) | 747 | mask_bottom = 0xFFu >> (7 - (ny & 7)); |
712 | ny = LCD_HEIGHT - y; | ||
713 | |||
714 | dst = &lcd_framebuffer[y >> 3][x]; | ||
715 | shift = y & 7; | ||
716 | 748 | ||
717 | if (!shift && clear) /* shortcut for byte aligned match with clear */ | 749 | if (shift == 0) |
718 | { | 750 | { |
719 | while (ny >= 8) /* all full rows */ | 751 | bool copyopt = (drawmode == DRMODE_SOLID); |
752 | |||
753 | for (; ny >= 8; ny -= 8) | ||
720 | { | 754 | { |
721 | memcpy(dst, src, nx); | 755 | if (copyopt && (mask == 0xFFu)) |
756 | memcpy(dst, src, width); | ||
757 | else | ||
758 | { | ||
759 | const unsigned char *src_row = src; | ||
760 | unsigned char *dst_row = dst; | ||
761 | |||
762 | for (i = width; i > 0; i--) | ||
763 | bfunc(dst_row++, mask, *src_row++); | ||
764 | } | ||
765 | |||
722 | src += stride; | 766 | src += stride; |
723 | dst += LCD_WIDTH; | 767 | dst += LCD_WIDTH; |
724 | ny -= 8; | 768 | mask = 0xFFu; |
725 | } | 769 | } |
726 | if (ny == 0) /* nothing left to do? */ | 770 | mask_bottom &= mask; |
727 | return; | ||
728 | /* last partial row to do by default routine */ | ||
729 | } | ||
730 | |||
731 | ny += shift; | ||
732 | 771 | ||
733 | /* Calculate bit masks */ | 772 | if (copyopt && (mask_bottom == 0xFFu)) |
734 | mask4 = ~(0xfe << ((ny-1) & 7)); /* data mask for last partial row */ | 773 | memcpy(dst, src, width); |
735 | if (clear) | 774 | else |
736 | { | 775 | { |
737 | mask1 = ~(0xff << shift); /* clearing of first partial row */ | 776 | for (i = width; i > 0; i--) |
738 | mask2 = 0; /* clearing of intermediate (full) rows */ | 777 | bfunc(dst++, mask_bottom, *src++); |
739 | mask3 = ~mask4; /* clearing of last partial row */ | 778 | } |
740 | if (ny <= 8) | ||
741 | mask3 |= mask1; | ||
742 | } | 779 | } |
743 | else | 780 | else |
744 | mask1 = mask2 = mask3 = 0xff; | ||
745 | |||
746 | /* Loop for each column */ | ||
747 | for (x = 0; x < nx; x++) | ||
748 | { | 781 | { |
749 | src_col = src++; | 782 | for (x = 0; x < width; x++) |
750 | dst_col = dst++; | ||
751 | data = 0; | ||
752 | y = 0; | ||
753 | |||
754 | if (ny > 8) | ||
755 | { | 783 | { |
756 | /* First partial row */ | 784 | const unsigned char *src_col = src++; |
757 | data = *src_col << shift; | 785 | unsigned char *dst_col = dst++; |
758 | *dst_col = (*dst_col & mask1) | data; | 786 | unsigned mask_col = mask; |
759 | src_col += stride; | 787 | unsigned data = 0; |
760 | dst_col += LCD_WIDTH; | 788 | |
761 | data >>= 8; | 789 | for (y = ny; y >= 8; y -= 8) |
762 | |||
763 | /* Intermediate rows */ | ||
764 | for (y = 8; y < ny-8; y += 8) | ||
765 | { | 790 | { |
766 | data |= *src_col << shift; | 791 | data |= *src_col << shift; |
767 | *dst_col = (*dst_col & mask2) | data; | 792 | |
793 | if (mask_col & 0xFFu) | ||
794 | { | ||
795 | bfunc(dst_col, mask_col, data); | ||
796 | mask_col = 0xFFu; | ||
797 | } | ||
798 | else | ||
799 | mask_col >>= 8; | ||
800 | |||
768 | src_col += stride; | 801 | src_col += stride; |
769 | dst_col += LCD_WIDTH; | 802 | dst_col += LCD_WIDTH; |
770 | data >>= 8; | 803 | data >>= 8; |
771 | } | 804 | } |
772 | } | ||
773 | |||
774 | /* Last partial row */ | ||
775 | if (y + shift < ny) | ||
776 | data |= *src_col << shift; | 805 | data |= *src_col << shift; |
777 | *dst_col = (*dst_col & mask3) | (data & mask4); | 806 | bfunc(dst_col, mask_col & mask_bottom, data); |
807 | } | ||
778 | } | 808 | } |
779 | } | 809 | } |
780 | 810 | ||
811 | /* Draw a full bitmap */ | ||
812 | void lcd_bitmap(const unsigned char *src, int x, int y, int width, int height) | ||
813 | { | ||
814 | lcd_bitmap_part(src, 0, 0, width, x, y, width, height); | ||
815 | } | ||
816 | |||
781 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | 817 | /* put a string at a given pixel position, skipping first ofs pixel columns */ |
782 | static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | 818 | static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) |
783 | { | 819 | { |
@@ -786,7 +822,8 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
786 | 822 | ||
787 | while ((ch = *str++) != '\0' && x < LCD_WIDTH) | 823 | while ((ch = *str++) != '\0' && x < LCD_WIDTH) |
788 | { | 824 | { |
789 | int gwidth, width; | 825 | int width; |
826 | const unsigned char *bits; | ||
790 | 827 | ||
791 | /* check input range */ | 828 | /* check input range */ |
792 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) | 829 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) |
@@ -794,44 +831,23 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
794 | ch -= pf->firstchar; | 831 | ch -= pf->firstchar; |
795 | 832 | ||
796 | /* get proportional width and glyph bits */ | 833 | /* get proportional width and glyph bits */ |
797 | gwidth = pf->width ? pf->width[ch] : pf->maxwidth; | 834 | width = pf->width ? pf->width[ch] : pf->maxwidth; |
798 | width = MIN (gwidth, LCD_WIDTH - x); | ||
799 | 835 | ||
800 | if (ofs != 0) | 836 | if (ofs > width) |
801 | { | 837 | { |
802 | if (ofs > width) | 838 | ofs -= width; |
803 | { | 839 | continue; |
804 | ofs -= width; | ||
805 | continue; | ||
806 | } | ||
807 | width -= ofs; | ||
808 | } | 840 | } |
809 | 841 | ||
810 | if (width > 0) | 842 | bits = pf->bits + (pf->offset ? |
811 | { | 843 | pf->offset[ch] : ((pf->height + 7) / 8 * pf->maxwidth * ch)); |
812 | unsigned int i; | ||
813 | const unsigned char* bits = pf->bits + | ||
814 | (pf->offset ? pf->offset[ch] | ||
815 | : ((pf->height + 7) / 8 * pf->maxwidth * ch)); | ||
816 | 844 | ||
817 | if (ofs != 0) | 845 | lcd_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); |
818 | { | 846 | |
819 | for (i = 0; i < pf->height; i += 8) | 847 | x += width - ofs; |
820 | { | ||
821 | lcd_bitmap (bits + ofs, x, y + i, width, | ||
822 | MIN(8, pf->height - i), true); | ||
823 | bits += gwidth; | ||
824 | } | ||
825 | } | ||
826 | else | ||
827 | lcd_bitmap ((unsigned char*) bits, x, y, gwidth, | ||
828 | pf->height, true); | ||
829 | x += width; | ||
830 | } | ||
831 | ofs = 0; | 848 | ofs = 0; |
832 | } | 849 | } |
833 | } | 850 | } |
834 | |||
835 | /* put a string at a given pixel position */ | 851 | /* put a string at a given pixel position */ |
836 | void lcd_putsxy(int x, int y, const unsigned char *str) | 852 | void lcd_putsxy(int x, int y, const unsigned char *str) |
837 | { | 853 | { |