diff options
author | Karl Kurbjun <kkurbjun@gmail.com> | 2009-11-07 18:38:46 +0000 |
---|---|---|
committer | Karl Kurbjun <kkurbjun@gmail.com> | 2009-11-07 18:38:46 +0000 |
commit | 765ff0130ab58c67e82a2ed17c64c577c6434d57 (patch) | |
tree | c825c50286a468ecb421eca0cc571c1a07dfca24 /firmware | |
parent | b1783c3c64d530e77ea2301e70a000f2a624bb74 (diff) | |
download | rockbox-765ff0130ab58c67e82a2ed17c64c577c6434d57.tar.gz rockbox-765ff0130ab58c67e82a2ed17c64c577c6434d57.zip |
Add optional viewport clipping, can be enabled with HAVE_VIEWPORT_CLIP. A simulator check is also added to set_viewport that will show an error/note when DEBUGF is enabled.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23551 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/lcd-16bit-vert.c | 283 | ||||
-rw-r--r-- | firmware/drivers/lcd-16bit.c | 315 | ||||
-rw-r--r-- | firmware/drivers/lcd-1bit-vert.c | 133 | ||||
-rw-r--r-- | firmware/drivers/lcd-2bit-horz.c | 165 | ||||
-rw-r--r-- | firmware/drivers/lcd-2bit-vert.c | 165 | ||||
-rw-r--r-- | firmware/drivers/lcd-2bit-vi.c | 167 | ||||
-rw-r--r-- | firmware/drivers/lcd-charcell.c | 27 | ||||
-rw-r--r-- | firmware/export/config-mrobe500.h | 3 |
8 files changed, 1092 insertions, 166 deletions
diff --git a/firmware/drivers/lcd-16bit-vert.c b/firmware/drivers/lcd-16bit-vert.c index 1e49bb354d..586feabeca 100644 --- a/firmware/drivers/lcd-16bit-vert.c +++ b/firmware/drivers/lcd-16bit-vert.c | |||
@@ -92,6 +92,28 @@ void lcd_set_viewport(struct viewport* vp) | |||
92 | current_vp = &default_vp; | 92 | current_vp = &default_vp; |
93 | else | 93 | else |
94 | current_vp = vp; | 94 | current_vp = vp; |
95 | |||
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. | ||
100 | */ | ||
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) | ||
105 | { | ||
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); | ||
114 | } | ||
115 | |||
116 | #endif | ||
95 | } | 117 | } |
96 | 118 | ||
97 | void lcd_update_viewport(void) | 119 | void lcd_update_viewport(void) |
@@ -312,8 +334,13 @@ void lcd_clear_display(void) | |||
312 | /* Set a single pixel */ | 334 | /* Set a single pixel */ |
313 | void lcd_drawpixel(int x, int y) | 335 | void lcd_drawpixel(int x, int y) |
314 | { | 336 | { |
315 | if (((unsigned)x < (unsigned)current_vp->width) && | 337 | if ( ((unsigned)x < (unsigned)current_vp->width) |
316 | ((unsigned)y < (unsigned)current_vp->height)) | 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 | ||
343 | ) | ||
317 | lcd_fastpixelfuncs[current_vp->drawmode](LCDADDR(current_vp->x+x, current_vp->y+y)); | 344 | lcd_fastpixelfuncs[current_vp->drawmode](LCDADDR(current_vp->x+x, current_vp->y+y)); |
318 | } | 345 | } |
319 | 346 | ||
@@ -382,7 +409,13 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
382 | 409 | ||
383 | for (i = 0; i < numpixels; i++) | 410 | for (i = 0; i < numpixels; i++) |
384 | { | 411 | { |
385 | if (((unsigned)x < (unsigned)current_vp->width) && ((unsigned)y < (unsigned)current_vp->height)) | 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 | ||
418 | ) | ||
386 | pfunc(LCDADDR(x + current_vp->x, y + current_vp->y)); | 419 | pfunc(LCDADDR(x + current_vp->x, y + current_vp->y)); |
387 | 420 | ||
388 | if (d < 0) | 421 | if (d < 0) |
@@ -415,19 +448,38 @@ void lcd_hline(int x1, int x2, int y) | |||
415 | x2 = x; | 448 | x2 = x; |
416 | } | 449 | } |
417 | 450 | ||
451 | /******************** In viewport clipping **********************/ | ||
418 | /* nothing to draw? */ | 452 | /* nothing to draw? */ |
419 | if (((unsigned)y >= (unsigned)current_vp->height) || | 453 | if (((unsigned)y >= (unsigned)current_vp->height) || |
420 | (x1 >= current_vp->width) || | 454 | (x1 >= current_vp->width) || |
421 | (x2 < 0)) | 455 | (x2 < 0)) |
422 | return; | 456 | return; |
423 | 457 | ||
424 | /* clipping */ | ||
425 | if (x1 < 0) | 458 | if (x1 < 0) |
426 | x1 = 0; | 459 | x1 = 0; |
427 | if (x2 >= current_vp->width) | 460 | if (x2 >= current_vp->width) |
428 | x2 = current_vp->width-1; | 461 | x2 = current_vp->width-1; |
462 | |||
463 | /* Adjust x1 and y to viewport */ | ||
464 | x1 += current_vp->x; | ||
465 | x2 += current_vp->x; | ||
466 | y += current_vp->y; | ||
467 | |||
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; | ||
474 | |||
475 | /* clipping */ | ||
476 | if (x1 < 0) | ||
477 | x1 = 0; | ||
478 | if (x2 >= LCD_WIDTH) | ||
479 | x2 = LCD_WIDTH-1; | ||
480 | #endif | ||
429 | 481 | ||
430 | dst = LCDADDR(x1 + current_vp->x, y + current_vp->y); | 482 | dst = LCDADDR(x1 , y ); |
431 | dst_end = dst + (x2 - x1) * LCD_HEIGHT; | 483 | dst_end = dst + (x2 - x1) * LCD_HEIGHT; |
432 | 484 | ||
433 | do | 485 | do |
@@ -454,12 +506,39 @@ void lcd_vline(int x, int y1, int y2) | |||
454 | y2 = y; | 506 | y2 = y; |
455 | } | 507 | } |
456 | 508 | ||
509 | /******************** In viewport clipping **********************/ | ||
457 | /* nothing to draw? */ | 510 | /* nothing to draw? */ |
458 | if (((unsigned)x >= (unsigned)current_vp->width) || | 511 | if (((unsigned)x >= (unsigned)current_vp->width) || |
459 | (y1 >= current_vp->height) || | 512 | (y1 >= current_vp->height) || |
460 | (y2 < 0)) | 513 | (y2 < 0)) |
461 | return; | 514 | return; |
462 | 515 | ||
516 | if (y1 < 0) | ||
517 | y1 = 0; | ||
518 | if (y2 >= current_vp->height) | ||
519 | y2 = current_vp->height-1; | ||
520 | |||
521 | /* adjust for viewport */ | ||
522 | x += current_vp->x; | ||
523 | y1 += current_vp->y; | ||
524 | y2 += current_vp->y; | ||
525 | |||
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; | ||
532 | |||
533 | /* clipping */ | ||
534 | if (y1 < 0) | ||
535 | y1 = 0; | ||
536 | if (y2 >= LCD_HEIGHT) | ||
537 | y2 = LCD_HEIGHT-1; | ||
538 | #endif | ||
539 | |||
540 | height = y2 - y1 + 1; | ||
541 | |||
463 | /* drawmode and optimisation */ | 542 | /* drawmode and optimisation */ |
464 | if (current_vp->drawmode & DRMODE_INVERSEVID) | 543 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
465 | { | 544 | { |
@@ -485,18 +564,6 @@ void lcd_vline(int x, int y1, int y2) | |||
485 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) | 564 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) |
486 | return; | 565 | return; |
487 | 566 | ||
488 | /* clipping */ | ||
489 | if (y1 < 0) | ||
490 | y1 = 0; | ||
491 | if (y2 >= current_vp->height) | ||
492 | y2 = current_vp->height-1; | ||
493 | |||
494 | height = y2 - y1 + 1; | ||
495 | |||
496 | /* Adjust y1 and x to viewport */ | ||
497 | y1 += current_vp->y; | ||
498 | x += current_vp->x; | ||
499 | |||
500 | dst = LCDADDR(x, y1); | 567 | dst = LCDADDR(x, y1); |
501 | 568 | ||
502 | switch (fillopt) | 569 | switch (fillopt) |
@@ -541,11 +608,55 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
541 | enum fill_opt fillopt = OPT_NONE; | 608 | enum fill_opt fillopt = OPT_NONE; |
542 | fb_data *dst, *dst_end; | 609 | fb_data *dst, *dst_end; |
543 | 610 | ||
611 | /******************** In viewport clipping **********************/ | ||
544 | /* nothing to draw? */ | 612 | /* nothing to draw? */ |
545 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 613 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
546 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 614 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
547 | return; | 615 | return; |
548 | 616 | ||
617 | if (x < 0) | ||
618 | { | ||
619 | width += x; | ||
620 | x = 0; | ||
621 | } | ||
622 | if (y < 0) | ||
623 | { | ||
624 | height += y; | ||
625 | y = 0; | ||
626 | } | ||
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; | ||
631 | |||
632 | /* adjust for viewport */ | ||
633 | x += current_vp->x; | ||
634 | y += current_vp->y; | ||
635 | |||
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; | ||
642 | |||
643 | /* clip image in viewport in screen */ | ||
644 | if (x < 0) | ||
645 | { | ||
646 | width += x; | ||
647 | x = 0; | ||
648 | } | ||
649 | if (y < 0) | ||
650 | { | ||
651 | height += y; | ||
652 | y = 0; | ||
653 | } | ||
654 | if (x + width > LCD_WIDTH) | ||
655 | width = LCD_WIDTH - x; | ||
656 | if (y + height > LCD_HEIGHT) | ||
657 | height = LCD_HEIGHT - y; | ||
658 | #endif | ||
659 | |||
549 | /* drawmode and optimisation */ | 660 | /* drawmode and optimisation */ |
550 | if (current_vp->drawmode & DRMODE_INVERSEVID) | 661 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
551 | { | 662 | { |
@@ -571,23 +682,7 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
571 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) | 682 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) |
572 | return; | 683 | return; |
573 | 684 | ||
574 | /* clipping */ | 685 | dst = LCDADDR(x, y); |
575 | if (x < 0) | ||
576 | { | ||
577 | width += x; | ||
578 | x = 0; | ||
579 | } | ||
580 | if (y < 0) | ||
581 | { | ||
582 | height += y; | ||
583 | y = 0; | ||
584 | } | ||
585 | if (x + width > current_vp->width) | ||
586 | width = current_vp->width - x; | ||
587 | if (y + height > current_vp->height) | ||
588 | height = current_vp->height - y; | ||
589 | |||
590 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | ||
591 | dst_end = dst + width * LCD_HEIGHT; | 686 | dst_end = dst + width * LCD_HEIGHT; |
592 | 687 | ||
593 | do | 688 | do |
@@ -641,12 +736,12 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
641 | unsigned dmask = 0x100; /* bit 8 == sentinel */ | 736 | unsigned dmask = 0x100; /* bit 8 == sentinel */ |
642 | int drmode = current_vp->drawmode; | 737 | int drmode = current_vp->drawmode; |
643 | 738 | ||
739 | /******************** Image in viewport clipping **********************/ | ||
644 | /* nothing to draw? */ | 740 | /* nothing to draw? */ |
645 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 741 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
646 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 742 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
647 | return; | 743 | return; |
648 | 744 | ||
649 | /* clipping */ | ||
650 | if (x < 0) | 745 | if (x < 0) |
651 | { | 746 | { |
652 | width += x; | 747 | width += x; |
@@ -663,11 +758,41 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
663 | width = current_vp->width - x; | 758 | width = current_vp->width - x; |
664 | if (y + height > current_vp->height) | 759 | if (y + height > current_vp->height) |
665 | height = current_vp->height - y; | 760 | height = current_vp->height - y; |
761 | |||
762 | /* adjust for viewport */ | ||
763 | x += current_vp->x; | ||
764 | y += current_vp->y; | ||
765 | |||
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; | ||
772 | |||
773 | /* clip image in viewport in screen */ | ||
774 | if (x < 0) | ||
775 | { | ||
776 | width += x; | ||
777 | src_x -= x; | ||
778 | x = 0; | ||
779 | } | ||
780 | if (y < 0) | ||
781 | { | ||
782 | height += y; | ||
783 | src_y -= y; | ||
784 | y = 0; | ||
785 | } | ||
786 | if (x + width > LCD_WIDTH) | ||
787 | width = LCD_WIDTH - x; | ||
788 | if (y + height > LCD_HEIGHT) | ||
789 | height = LCD_HEIGHT - y; | ||
790 | #endif | ||
666 | 791 | ||
667 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 792 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
668 | src_y &= 7; | 793 | src_y &= 7; |
669 | src_end = src + width; | 794 | src_end = src + width; |
670 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 795 | dst = LCDADDR(x, y); |
671 | dst_end = dst + height; | 796 | dst_end = dst + height; |
672 | 797 | ||
673 | if (drmode & DRMODE_INVERSEVID) | 798 | if (drmode & DRMODE_INVERSEVID) |
@@ -793,12 +918,12 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
793 | { | 918 | { |
794 | fb_data *dst, *dst_end; | 919 | fb_data *dst, *dst_end; |
795 | 920 | ||
921 | /******************** Image in viewport clipping **********************/ | ||
796 | /* nothing to draw? */ | 922 | /* nothing to draw? */ |
797 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 923 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
798 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 924 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
799 | return; | 925 | return; |
800 | 926 | ||
801 | /* clipping */ | ||
802 | if (x < 0) | 927 | if (x < 0) |
803 | { | 928 | { |
804 | width += x; | 929 | width += x; |
@@ -811,13 +936,44 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
811 | src_y -= y; | 936 | src_y -= y; |
812 | y = 0; | 937 | y = 0; |
813 | } | 938 | } |
939 | |||
814 | if (x + width > current_vp->width) | 940 | if (x + width > current_vp->width) |
815 | width = current_vp->width - x; | 941 | width = current_vp->width - x; |
816 | if (y + height > current_vp->height) | 942 | if (y + height > current_vp->height) |
817 | height = current_vp->height - y; | 943 | height = current_vp->height - y; |
944 | |||
945 | /* adjust for viewport */ | ||
946 | x += current_vp->x; | ||
947 | y += current_vp->y; | ||
948 | |||
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; | ||
955 | |||
956 | /* clip image in viewport in screen */ | ||
957 | if (x < 0) | ||
958 | { | ||
959 | width += x; | ||
960 | src_x -= x; | ||
961 | x = 0; | ||
962 | } | ||
963 | if (y < 0) | ||
964 | { | ||
965 | height += y; | ||
966 | src_y -= y; | ||
967 | y = 0; | ||
968 | } | ||
969 | if (x + width > LCD_WIDTH) | ||
970 | width = LCD_WIDTH - x; | ||
971 | if (y + height > LCD_HEIGHT) | ||
972 | height = LCD_HEIGHT - y; | ||
973 | #endif | ||
818 | 974 | ||
819 | src += stride * src_x + src_y; /* move starting point */ | 975 | src += stride * src_x + src_y; /* move starting point */ |
820 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 976 | dst = LCDADDR(x, y); |
821 | dst_end = dst + width * LCD_HEIGHT; | 977 | dst_end = dst + width * LCD_HEIGHT; |
822 | 978 | ||
823 | do | 979 | do |
@@ -843,13 +999,13 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, | |||
843 | int y, int width, int height) | 999 | int y, int width, int height) |
844 | { | 1000 | { |
845 | fb_data *dst, *dst_end; | 1001 | fb_data *dst, *dst_end; |
846 | 1002 | ||
1003 | /******************** Image in viewport clipping **********************/ | ||
847 | /* nothing to draw? */ | 1004 | /* nothing to draw? */ |
848 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 1005 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
849 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 1006 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
850 | return; | 1007 | return; |
851 | 1008 | ||
852 | /* clipping */ | ||
853 | if (x < 0) | 1009 | if (x < 0) |
854 | { | 1010 | { |
855 | width += x; | 1011 | width += x; |
@@ -862,13 +1018,44 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, | |||
862 | src_y -= y; | 1018 | src_y -= y; |
863 | y = 0; | 1019 | y = 0; |
864 | } | 1020 | } |
1021 | |||
865 | if (x + width > current_vp->width) | 1022 | if (x + width > current_vp->width) |
866 | width = current_vp->width - x; | 1023 | width = current_vp->width - x; |
867 | if (y + height > current_vp->height) | 1024 | if (y + height > current_vp->height) |
868 | height = current_vp->height - y; | 1025 | height = current_vp->height - y; |
1026 | |||
1027 | /* adjust for viewport */ | ||
1028 | x += current_vp->x; | ||
1029 | y += current_vp->y; | ||
1030 | |||
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; | ||
1037 | |||
1038 | /* clip image in viewport in screen */ | ||
1039 | if (x < 0) | ||
1040 | { | ||
1041 | width += x; | ||
1042 | src_x -= x; | ||
1043 | x = 0; | ||
1044 | } | ||
1045 | if (y < 0) | ||
1046 | { | ||
1047 | height += y; | ||
1048 | src_y -= y; | ||
1049 | y = 0; | ||
1050 | } | ||
1051 | if (x + width > LCD_WIDTH) | ||
1052 | width = LCD_WIDTH - x; | ||
1053 | if (y + height > LCD_HEIGHT) | ||
1054 | height = LCD_HEIGHT - y; | ||
1055 | #endif | ||
869 | 1056 | ||
870 | src += stride * src_x + src_y; /* move starting point */ | 1057 | src += stride * src_x + src_y; /* move starting point */ |
871 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 1058 | dst = LCDADDR(x, y); |
872 | dst_end = dst + width * LCD_HEIGHT; | 1059 | dst_end = dst + width * LCD_HEIGHT; |
873 | 1060 | ||
874 | do | 1061 | do |
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index 6d6a3b2104..d8405235f7 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c | |||
@@ -85,6 +85,28 @@ void lcd_set_viewport(struct viewport* vp) | |||
85 | current_vp = &default_vp; | 85 | current_vp = &default_vp; |
86 | else | 86 | else |
87 | current_vp = vp; | 87 | current_vp = vp; |
88 | |||
89 | #if defined(SIMULATOR) | ||
90 | /* Force the viewport to be within bounds. If this happens it should | ||
91 | * be considered an error - the viewport will not draw as it might be | ||
92 | * expected. | ||
93 | */ | ||
94 | if((unsigned) current_vp->x > (unsigned) LCD_WIDTH | ||
95 | || (unsigned) current_vp->y > (unsigned) LCD_HEIGHT | ||
96 | || current_vp->x + current_vp->width > LCD_WIDTH | ||
97 | || current_vp->y + current_vp->height > LCD_HEIGHT) | ||
98 | { | ||
99 | #if !defined(HAVE_VIEWPORT_CLIP) | ||
100 | DEBUGF("ERROR: " | ||
101 | #else | ||
102 | DEBUGF("NOTE: " | ||
103 | #endif | ||
104 | "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n", | ||
105 | current_vp->x, current_vp->y, | ||
106 | current_vp->width, current_vp->height); | ||
107 | } | ||
108 | |||
109 | #endif | ||
88 | } | 110 | } |
89 | 111 | ||
90 | void lcd_update_viewport(void) | 112 | void lcd_update_viewport(void) |
@@ -305,8 +327,13 @@ void lcd_clear_display(void) | |||
305 | /* Set a single pixel */ | 327 | /* Set a single pixel */ |
306 | void lcd_drawpixel(int x, int y) | 328 | void lcd_drawpixel(int x, int y) |
307 | { | 329 | { |
308 | if (((unsigned)x < (unsigned)current_vp->width) && | 330 | if ( ((unsigned)x < (unsigned)current_vp->width) |
309 | ((unsigned)y < (unsigned)current_vp->height)) | 331 | && ((unsigned)y < (unsigned)current_vp->height) |
332 | #if defined(HAVE_VIEWPORT_CLIP) | ||
333 | && ((unsigned)x < (unsigned)LCD_WIDTH) | ||
334 | && ((unsigned)y < (unsigned)LCD_HEIGHT) | ||
335 | #endif | ||
336 | ) | ||
310 | lcd_fastpixelfuncs[current_vp->drawmode](LCDADDR(current_vp->x+x, current_vp->y+y)); | 337 | lcd_fastpixelfuncs[current_vp->drawmode](LCDADDR(current_vp->x+x, current_vp->y+y)); |
311 | } | 338 | } |
312 | 339 | ||
@@ -375,7 +402,13 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
375 | 402 | ||
376 | for (i = 0; i < numpixels; i++) | 403 | for (i = 0; i < numpixels; i++) |
377 | { | 404 | { |
378 | if (((unsigned)x < (unsigned)current_vp->width) && ((unsigned)y < (unsigned)current_vp->height)) | 405 | if ( ((unsigned)x < (unsigned)current_vp->width) |
406 | && ((unsigned)y < (unsigned)current_vp->height) | ||
407 | #if defined(HAVE_VIEWPORT_CLIP) | ||
408 | && ((unsigned)x < (unsigned)LCD_WIDTH) | ||
409 | && ((unsigned)y < (unsigned)LCD_HEIGHT) | ||
410 | #endif | ||
411 | ) | ||
379 | pfunc(LCDADDR(x + current_vp->x, y + current_vp->y)); | 412 | pfunc(LCDADDR(x + current_vp->x, y + current_vp->y)); |
380 | 413 | ||
381 | if (d < 0) | 414 | if (d < 0) |
@@ -409,11 +442,38 @@ void lcd_hline(int x1, int x2, int y) | |||
409 | x2 = x; | 442 | x2 = x; |
410 | } | 443 | } |
411 | 444 | ||
445 | /******************** In viewport clipping **********************/ | ||
412 | /* nothing to draw? */ | 446 | /* nothing to draw? */ |
413 | if (((unsigned)y >= (unsigned)current_vp->height) || | 447 | if (((unsigned)y >= (unsigned)current_vp->height) || |
414 | (x1 >= current_vp->width) || | 448 | (x1 >= current_vp->width) || |
415 | (x2 < 0)) | 449 | (x2 < 0)) |
416 | return; | 450 | return; |
451 | |||
452 | if (x1 < 0) | ||
453 | x1 = 0; | ||
454 | if (x2 >= current_vp->width) | ||
455 | x2 = current_vp->width-1; | ||
456 | |||
457 | /* Adjust x1 and y to viewport */ | ||
458 | x1 += current_vp->x; | ||
459 | x2 += current_vp->x; | ||
460 | y += current_vp->y; | ||
461 | |||
462 | #if defined(HAVE_VIEWPORT_CLIP) | ||
463 | /********************* Viewport on screen clipping ********************/ | ||
464 | /* nothing to draw? */ | ||
465 | if (((unsigned)y >= (unsigned) LCD_HEIGHT) || (x1 >= LCD_WIDTH) | ||
466 | || (x2 < 0)) | ||
467 | return; | ||
468 | |||
469 | /* clipping */ | ||
470 | if (x1 < 0) | ||
471 | x1 = 0; | ||
472 | if (x2 >= LCD_WIDTH) | ||
473 | x2 = LCD_WIDTH-1; | ||
474 | #endif | ||
475 | |||
476 | width = x2 - x1 + 1; | ||
417 | 477 | ||
418 | /* drawmode and optimisation */ | 478 | /* drawmode and optimisation */ |
419 | if (current_vp->drawmode & DRMODE_INVERSEVID) | 479 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
@@ -440,18 +500,6 @@ void lcd_hline(int x1, int x2, int y) | |||
440 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) | 500 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) |
441 | return; | 501 | return; |
442 | 502 | ||
443 | /* clipping */ | ||
444 | if (x1 < 0) | ||
445 | x1 = 0; | ||
446 | if (x2 >= current_vp->width) | ||
447 | x2 = current_vp->width-1; | ||
448 | |||
449 | width = x2 - x1 + 1; | ||
450 | |||
451 | /* Adjust x1 and y to viewport */ | ||
452 | x1 += current_vp->x; | ||
453 | y += current_vp->y; | ||
454 | |||
455 | dst = LCDADDR(x1, y); | 503 | dst = LCDADDR(x1, y); |
456 | 504 | ||
457 | switch (fillopt) | 505 | switch (fillopt) |
@@ -489,19 +537,38 @@ void lcd_vline(int x, int y1, int y2) | |||
489 | y2 = y; | 537 | y2 = y; |
490 | } | 538 | } |
491 | 539 | ||
540 | /******************** In viewport clipping **********************/ | ||
492 | /* nothing to draw? */ | 541 | /* nothing to draw? */ |
493 | if (((unsigned)x >= (unsigned)current_vp->width) || | 542 | if (((unsigned)x >= (unsigned)current_vp->width) || |
494 | (y1 >= current_vp->height) || | 543 | (y1 >= current_vp->height) || |
495 | (y2 < 0)) | 544 | (y2 < 0)) |
496 | return; | 545 | return; |
497 | 546 | ||
498 | /* clipping */ | ||
499 | if (y1 < 0) | 547 | if (y1 < 0) |
500 | y1 = 0; | 548 | y1 = 0; |
501 | if (y2 >= current_vp->height) | 549 | if (y2 >= current_vp->height) |
502 | y2 = current_vp->height-1; | 550 | y2 = current_vp->height-1; |
551 | |||
552 | /* adjust for viewport */ | ||
553 | x += current_vp->x; | ||
554 | y1 += current_vp->y; | ||
555 | y2 += current_vp->y; | ||
556 | |||
557 | #if defined(HAVE_VIEWPORT_CLIP) | ||
558 | /********************* Viewport on screen clipping ********************/ | ||
559 | /* nothing to draw? */ | ||
560 | if (( (unsigned) x >= (unsigned)LCD_WIDTH) || (y1 >= LCD_HEIGHT) | ||
561 | || (y2 < 0)) | ||
562 | return; | ||
563 | |||
564 | /* clipping */ | ||
565 | if (y1 < 0) | ||
566 | y1 = 0; | ||
567 | if (y2 >= LCD_HEIGHT) | ||
568 | y2 = LCD_HEIGHT-1; | ||
569 | #endif | ||
503 | 570 | ||
504 | dst = LCDADDR(x + current_vp->x, y1 + current_vp->y); | 571 | dst = LCDADDR(x , y1); |
505 | dst_end = dst + (y2 - y1) * LCD_WIDTH; | 572 | dst_end = dst + (y2 - y1) * LCD_WIDTH; |
506 | 573 | ||
507 | do | 574 | do |
@@ -534,11 +601,55 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
534 | enum fill_opt fillopt = OPT_NONE; | 601 | enum fill_opt fillopt = OPT_NONE; |
535 | fb_data *dst, *dst_end; | 602 | fb_data *dst, *dst_end; |
536 | 603 | ||
604 | /******************** In viewport clipping **********************/ | ||
537 | /* nothing to draw? */ | 605 | /* nothing to draw? */ |
538 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 606 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
539 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 607 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
540 | return; | 608 | return; |
541 | 609 | ||
610 | if (x < 0) | ||
611 | { | ||
612 | width += x; | ||
613 | x = 0; | ||
614 | } | ||
615 | if (y < 0) | ||
616 | { | ||
617 | height += y; | ||
618 | y = 0; | ||
619 | } | ||
620 | if (x + width > current_vp->width) | ||
621 | width = current_vp->width - x; | ||
622 | if (y + height > current_vp->height) | ||
623 | height = current_vp->height - y; | ||
624 | |||
625 | /* adjust for viewport */ | ||
626 | x += current_vp->x; | ||
627 | y += current_vp->y; | ||
628 | |||
629 | #if defined(HAVE_VIEWPORT_CLIP) | ||
630 | /********************* Viewport on screen clipping ********************/ | ||
631 | /* nothing to draw? */ | ||
632 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
633 | || (x + width <= 0) || (y + height <= 0)) | ||
634 | return; | ||
635 | |||
636 | /* clip image in viewport in screen */ | ||
637 | if (x < 0) | ||
638 | { | ||
639 | width += x; | ||
640 | x = 0; | ||
641 | } | ||
642 | if (y < 0) | ||
643 | { | ||
644 | height += y; | ||
645 | y = 0; | ||
646 | } | ||
647 | if (x + width > LCD_WIDTH) | ||
648 | width = LCD_WIDTH - x; | ||
649 | if (y + height > LCD_HEIGHT) | ||
650 | height = LCD_HEIGHT - y; | ||
651 | #endif | ||
652 | |||
542 | /* drawmode and optimisation */ | 653 | /* drawmode and optimisation */ |
543 | if (current_vp->drawmode & DRMODE_INVERSEVID) | 654 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
544 | { | 655 | { |
@@ -564,23 +675,7 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
564 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) | 675 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) |
565 | return; | 676 | return; |
566 | 677 | ||
567 | /* clipping */ | 678 | dst = LCDADDR(x, y); |
568 | if (x < 0) | ||
569 | { | ||
570 | width += x; | ||
571 | x = 0; | ||
572 | } | ||
573 | if (y < 0) | ||
574 | { | ||
575 | height += y; | ||
576 | y = 0; | ||
577 | } | ||
578 | if (x + width > current_vp->width) | ||
579 | width = current_vp->width - x; | ||
580 | if (y + height > current_vp->height) | ||
581 | height = current_vp->height - y; | ||
582 | |||
583 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | ||
584 | dst_end = dst + height * LCD_WIDTH; | 679 | dst_end = dst + height * LCD_WIDTH; |
585 | 680 | ||
586 | do | 681 | do |
@@ -634,12 +729,12 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
634 | unsigned dmask = 0x100; /* bit 8 == sentinel */ | 729 | unsigned dmask = 0x100; /* bit 8 == sentinel */ |
635 | int drmode = current_vp->drawmode; | 730 | int drmode = current_vp->drawmode; |
636 | 731 | ||
732 | /******************** Image in viewport clipping **********************/ | ||
637 | /* nothing to draw? */ | 733 | /* nothing to draw? */ |
638 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 734 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
639 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 735 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
640 | return; | 736 | return; |
641 | 737 | ||
642 | /* clipping */ | ||
643 | if (x < 0) | 738 | if (x < 0) |
644 | { | 739 | { |
645 | width += x; | 740 | width += x; |
@@ -656,11 +751,41 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
656 | width = current_vp->width - x; | 751 | width = current_vp->width - x; |
657 | if (y + height > current_vp->height) | 752 | if (y + height > current_vp->height) |
658 | height = current_vp->height - y; | 753 | height = current_vp->height - y; |
754 | |||
755 | /* adjust for viewport */ | ||
756 | x += current_vp->x; | ||
757 | y += current_vp->y; | ||
758 | |||
759 | #if defined(HAVE_VIEWPORT_CLIP) | ||
760 | /********************* Viewport on screen clipping ********************/ | ||
761 | /* nothing to draw? */ | ||
762 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
763 | || (x + width <= 0) || (y + height <= 0)) | ||
764 | return; | ||
765 | |||
766 | /* clip image in viewport in screen */ | ||
767 | if (x < 0) | ||
768 | { | ||
769 | width += x; | ||
770 | src_x -= x; | ||
771 | x = 0; | ||
772 | } | ||
773 | if (y < 0) | ||
774 | { | ||
775 | height += y; | ||
776 | src_y -= y; | ||
777 | y = 0; | ||
778 | } | ||
779 | if (x + width > LCD_WIDTH) | ||
780 | width = LCD_WIDTH - x; | ||
781 | if (y + height > LCD_HEIGHT) | ||
782 | height = LCD_HEIGHT - y; | ||
783 | #endif | ||
659 | 784 | ||
660 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 785 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
661 | src_y &= 7; | 786 | src_y &= 7; |
662 | src_end = src + width; | 787 | src_end = src + width; |
663 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 788 | dst = LCDADDR(x, y); |
664 | dst_end = dst + height * LCD_WIDTH; | 789 | dst_end = dst + height * LCD_WIDTH; |
665 | 790 | ||
666 | if (drmode & DRMODE_INVERSEVID) | 791 | if (drmode & DRMODE_INVERSEVID) |
@@ -784,34 +909,62 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
784 | { | 909 | { |
785 | fb_data *dst; | 910 | fb_data *dst; |
786 | 911 | ||
787 | if (x + width > current_vp->width) | 912 | /******************** Image in viewport clipping **********************/ |
788 | width = current_vp->width - x; /* Clip right */ | 913 | /* nothing to draw? */ |
789 | 914 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | |
790 | if (x < 0) /* Clip left */ | 915 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
916 | return; | ||
917 | |||
918 | if (x < 0) | ||
791 | { | 919 | { |
792 | width += x; | 920 | width += x; |
793 | src_x -= x; | 921 | src_x -= x; |
794 | x = 0; | 922 | x = 0; |
795 | } | 923 | } |
796 | 924 | if (y < 0) | |
797 | if (width <= 0) | 925 | { |
798 | return; /* nothing left to do */ | 926 | height += y; |
799 | 927 | src_y -= y; | |
928 | y = 0; | ||
929 | } | ||
930 | |||
931 | if (x + width > current_vp->width) | ||
932 | width = current_vp->width - x; | ||
800 | if (y + height > current_vp->height) | 933 | if (y + height > current_vp->height) |
801 | height = current_vp->height - y; /* Clip bottom */ | 934 | height = current_vp->height - y; |
802 | 935 | ||
803 | if (y < 0) /* Clip top */ | 936 | /* adjust for viewport */ |
937 | x += current_vp->x; | ||
938 | y += current_vp->y; | ||
939 | |||
940 | #if defined(HAVE_VIEWPORT_CLIP) | ||
941 | /********************* Viewport on screen clipping ********************/ | ||
942 | /* nothing to draw? */ | ||
943 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
944 | || (x + width <= 0) || (y + height <= 0)) | ||
945 | return; | ||
946 | |||
947 | /* clip image in viewport in screen */ | ||
948 | if (x < 0) | ||
949 | { | ||
950 | width += x; | ||
951 | src_x -= x; | ||
952 | x = 0; | ||
953 | } | ||
954 | if (y < 0) | ||
804 | { | 955 | { |
805 | height += y; | 956 | height += y; |
806 | src_y -= y; | 957 | src_y -= y; |
807 | y = 0; | 958 | y = 0; |
808 | } | 959 | } |
809 | 960 | if (x + width > LCD_WIDTH) | |
810 | if (height <= 0) | 961 | width = LCD_WIDTH - x; |
811 | return; /* nothing left to do */ | 962 | if (y + height > LCD_HEIGHT) |
812 | 963 | height = LCD_HEIGHT - y; | |
964 | #endif | ||
965 | |||
813 | src += stride * src_y + src_x; /* move starting point */ | 966 | src += stride * src_y + src_x; /* move starting point */ |
814 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 967 | dst = LCDADDR(x, y); |
815 | 968 | ||
816 | do | 969 | do |
817 | { | 970 | { |
@@ -836,34 +989,62 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, | |||
836 | fb_data *dst; | 989 | fb_data *dst; |
837 | unsigned fg = current_vp->fg_pattern; | 990 | unsigned fg = current_vp->fg_pattern; |
838 | 991 | ||
839 | if (x + width > current_vp->width) | 992 | /******************** Image in viewport clipping **********************/ |
840 | width = current_vp->width - x; /* Clip right */ | 993 | /* nothing to draw? */ |
841 | 994 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | |
842 | if (x < 0) /* Clip left */ | 995 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
996 | return; | ||
997 | |||
998 | if (x < 0) | ||
843 | { | 999 | { |
844 | width += x; | 1000 | width += x; |
845 | src_x -= x; | 1001 | src_x -= x; |
846 | x = 0; | 1002 | x = 0; |
847 | } | 1003 | } |
848 | 1004 | if (y < 0) | |
849 | if (width <= 0) | 1005 | { |
850 | return; /* nothing left to do */ | 1006 | height += y; |
851 | 1007 | src_y -= y; | |
1008 | y = 0; | ||
1009 | } | ||
1010 | |||
1011 | if (x + width > current_vp->width) | ||
1012 | width = current_vp->width - x; | ||
852 | if (y + height > current_vp->height) | 1013 | if (y + height > current_vp->height) |
853 | height = current_vp->height - y; /* Clip bottom */ | 1014 | height = current_vp->height - y; |
854 | 1015 | ||
855 | if (y < 0) /* Clip top */ | 1016 | /* adjust for viewport */ |
1017 | x += current_vp->x; | ||
1018 | y += current_vp->y; | ||
1019 | |||
1020 | #if defined(HAVE_VIEWPORT_CLIP) | ||
1021 | /********************* Viewport on screen clipping ********************/ | ||
1022 | /* nothing to draw? */ | ||
1023 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
1024 | || (x + width <= 0) || (y + height <= 0)) | ||
1025 | return; | ||
1026 | |||
1027 | /* clip image in viewport in screen */ | ||
1028 | if (x < 0) | ||
1029 | { | ||
1030 | width += x; | ||
1031 | src_x -= x; | ||
1032 | x = 0; | ||
1033 | } | ||
1034 | if (y < 0) | ||
856 | { | 1035 | { |
857 | height += y; | 1036 | height += y; |
858 | src_y -= y; | 1037 | src_y -= y; |
859 | y = 0; | 1038 | y = 0; |
860 | } | 1039 | } |
861 | 1040 | if (x + width > LCD_WIDTH) | |
862 | if (height <= 0) | 1041 | width = LCD_WIDTH - x; |
863 | return; /* nothing left to do */ | 1042 | if (y + height > LCD_HEIGHT) |
1043 | height = LCD_HEIGHT - y; | ||
1044 | #endif | ||
864 | 1045 | ||
865 | src += stride * src_y + src_x; /* move starting point */ | 1046 | src += stride * src_y + src_x; /* move starting point */ |
866 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 1047 | dst = LCDADDR(x, y); |
867 | 1048 | ||
868 | #ifdef CPU_ARM | 1049 | #ifdef CPU_ARM |
869 | { | 1050 | { |
diff --git a/firmware/drivers/lcd-1bit-vert.c b/firmware/drivers/lcd-1bit-vert.c index 9607f284aa..ae7cddb19a 100644 --- a/firmware/drivers/lcd-1bit-vert.c +++ b/firmware/drivers/lcd-1bit-vert.c | |||
@@ -66,6 +66,28 @@ void LCDFN(set_viewport)(struct viewport* vp) | |||
66 | current_vp = &default_vp; | 66 | current_vp = &default_vp; |
67 | else | 67 | else |
68 | current_vp = vp; | 68 | current_vp = vp; |
69 | |||
70 | #if defined(SIMULATOR) | ||
71 | /* Force the viewport to be within bounds. If this happens it should | ||
72 | * be considered an error - the viewport will not draw as it might be | ||
73 | * expected. | ||
74 | */ | ||
75 | if((unsigned) current_vp->x > (unsigned) LCDM(WIDTH) | ||
76 | || (unsigned) current_vp->y > (unsigned) LCDM(HEIGHT) | ||
77 | || current_vp->x + current_vp->width > LCDM(WIDTH) | ||
78 | || current_vp->y + current_vp->height > LCDM(HEIGHT)) | ||
79 | { | ||
80 | #if !defined(HAVE_VIEWPORT_CLIP) | ||
81 | DEBUGF("ERROR: " | ||
82 | #else | ||
83 | DEBUGF("NOTE: " | ||
84 | #endif | ||
85 | "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n", | ||
86 | current_vp->x, current_vp->y, | ||
87 | current_vp->width, current_vp->height); | ||
88 | } | ||
89 | |||
90 | #endif | ||
69 | } | 91 | } |
70 | 92 | ||
71 | void LCDFN(update_viewport)(void) | 93 | void LCDFN(update_viewport)(void) |
@@ -254,8 +276,13 @@ void LCDFN(clear_viewport)(void) | |||
254 | /* Set a single pixel */ | 276 | /* Set a single pixel */ |
255 | void LCDFN(drawpixel)(int x, int y) | 277 | void LCDFN(drawpixel)(int x, int y) |
256 | { | 278 | { |
257 | if (((unsigned)x < (unsigned)current_vp->width) && | 279 | if ( ((unsigned)x < (unsigned)current_vp->width) |
258 | ((unsigned)y < (unsigned)current_vp->height)) | 280 | && ((unsigned)y < (unsigned)current_vp->height) |
281 | #if defined(HAVE_VIEWPORT_CLIP) | ||
282 | && ((unsigned)x < (unsigned)LCDM(WIDTH)) | ||
283 | && ((unsigned)y < (unsigned)LCDM(HEIGHT)) | ||
284 | #endif | ||
285 | ) | ||
259 | LCDFN(pixelfuncs)[current_vp->drawmode](current_vp->x + x, current_vp->y + y); | 286 | LCDFN(pixelfuncs)[current_vp->drawmode](current_vp->x + x, current_vp->y + y); |
260 | } | 287 | } |
261 | 288 | ||
@@ -324,8 +351,13 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2) | |||
324 | 351 | ||
325 | for (i = 0; i < numpixels; i++) | 352 | for (i = 0; i < numpixels; i++) |
326 | { | 353 | { |
327 | if (((unsigned)x < (unsigned)current_vp->width) | 354 | if ( ((unsigned)x < (unsigned)current_vp->width) |
328 | && ((unsigned)y < (unsigned)current_vp->height)) | 355 | && ((unsigned)y < (unsigned)current_vp->height) |
356 | #if defined(HAVE_VIEWPORT_CLIP) | ||
357 | && ((unsigned)x < (unsigned)LCDM(WIDTH)) | ||
358 | && ((unsigned)y < (unsigned)LCDM(HEIGHT)) | ||
359 | #endif | ||
360 | ) | ||
329 | pfunc(current_vp->x + x, current_vp->y + y); | 361 | pfunc(current_vp->x + x, current_vp->y + y); |
330 | 362 | ||
331 | if (d < 0) | 363 | if (d < 0) |
@@ -359,22 +391,38 @@ void LCDFN(hline)(int x1, int x2, int y) | |||
359 | x2 = x; | 391 | x2 = x; |
360 | } | 392 | } |
361 | 393 | ||
394 | /******************** In viewport clipping **********************/ | ||
362 | /* nothing to draw? */ | 395 | /* nothing to draw? */ |
363 | if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) | 396 | if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) |
364 | || (x2 < 0)) | 397 | || (x2 < 0)) |
365 | return; | 398 | return; |
366 | 399 | ||
367 | /* clipping */ | ||
368 | if (x1 < 0) | 400 | if (x1 < 0) |
369 | x1 = 0; | 401 | x1 = 0; |
370 | if (x2 >= current_vp->width) | 402 | if (x2 >= current_vp->width) |
371 | x2 = current_vp->width-1; | 403 | x2 = current_vp->width-1; |
372 | 404 | ||
373 | width = x2 - x1 + 1; | ||
374 | |||
375 | /* adjust to viewport */ | 405 | /* adjust to viewport */ |
376 | x1 += current_vp->x; | 406 | x1 += current_vp->x; |
377 | y += current_vp->y; | 407 | y += current_vp->y; |
408 | |||
409 | #if defined(HAVE_VIEWPORT_CLIP) | ||
410 | x2 += current_vp->x; | ||
411 | |||
412 | /********************* Viewport on screen clipping ********************/ | ||
413 | /* nothing to draw? */ | ||
414 | if (((unsigned)y >= (unsigned) LCDM(HEIGHT)) || (x1 >= LCDM(WIDTH)) | ||
415 | || (x2 < 0)) | ||
416 | return; | ||
417 | |||
418 | /* clipping */ | ||
419 | if (x1 < 0) | ||
420 | x1 = 0; | ||
421 | if (x2 >= LCDM(WIDTH)) | ||
422 | x2 = LCDM(WIDTH)-1; | ||
423 | #endif | ||
424 | |||
425 | width = x2 - x1 + 1; | ||
378 | 426 | ||
379 | bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; | 427 | bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; |
380 | dst = &LCDFN(framebuffer)[y>>3][x1]; | 428 | dst = &LCDFN(framebuffer)[y>>3][x1]; |
@@ -402,12 +450,12 @@ void LCDFN(vline)(int x, int y1, int y2) | |||
402 | y2 = ny; | 450 | y2 = ny; |
403 | } | 451 | } |
404 | 452 | ||
453 | /******************** In viewport clipping **********************/ | ||
405 | /* nothing to draw? */ | 454 | /* nothing to draw? */ |
406 | if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) | 455 | if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) |
407 | || (y2 < 0)) | 456 | || (y2 < 0)) |
408 | return; | 457 | return; |
409 | 458 | ||
410 | /* clipping */ | ||
411 | if (y1 < 0) | 459 | if (y1 < 0) |
412 | y1 = 0; | 460 | y1 = 0; |
413 | if (y2 >= current_vp->height) | 461 | if (y2 >= current_vp->height) |
@@ -417,6 +465,20 @@ void LCDFN(vline)(int x, int y1, int y2) | |||
417 | y1 += current_vp->y; | 465 | y1 += current_vp->y; |
418 | y2 += current_vp->y; | 466 | y2 += current_vp->y; |
419 | x += current_vp->x; | 467 | x += current_vp->x; |
468 | |||
469 | #if defined(HAVE_VIEWPORT_CLIP) | ||
470 | /********************* Viewport on screen clipping ********************/ | ||
471 | /* nothing to draw? */ | ||
472 | if (( (unsigned) x >= (unsigned)LCDM(WIDTH)) || (y1 >= LCDM(HEIGHT)) | ||
473 | || (y2 < 0)) | ||
474 | return; | ||
475 | |||
476 | /* clipping */ | ||
477 | if (y1 < 0) | ||
478 | y1 = 0; | ||
479 | if (y2 >= LCDM(HEIGHT)) | ||
480 | y2 = LCDM(HEIGHT)-1; | ||
481 | #endif | ||
420 | 482 | ||
421 | bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; | 483 | bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; |
422 | dst = &LCDFN(framebuffer)[y1>>3][x]; | 484 | dst = &LCDFN(framebuffer)[y1>>3][x]; |
@@ -459,12 +521,12 @@ void LCDFN(fillrect)(int x, int y, int width, int height) | |||
459 | LCDFN(blockfunc_type) *bfunc; | 521 | LCDFN(blockfunc_type) *bfunc; |
460 | bool fillopt = false; | 522 | bool fillopt = false; |
461 | 523 | ||
524 | /******************** In viewport clipping **********************/ | ||
462 | /* nothing to draw? */ | 525 | /* nothing to draw? */ |
463 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) | 526 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
464 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 527 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
465 | return; | 528 | return; |
466 | 529 | ||
467 | /* clipping */ | ||
468 | if (x < 0) | 530 | if (x < 0) |
469 | { | 531 | { |
470 | width += x; | 532 | width += x; |
@@ -483,6 +545,30 @@ void LCDFN(fillrect)(int x, int y, int width, int height) | |||
483 | /* adjust for viewport */ | 545 | /* adjust for viewport */ |
484 | x += current_vp->x; | 546 | x += current_vp->x; |
485 | y += current_vp->y; | 547 | y += current_vp->y; |
548 | |||
549 | #if defined(HAVE_VIEWPORT_CLIP) | ||
550 | /********************* Viewport on screen clipping ********************/ | ||
551 | /* nothing to draw? */ | ||
552 | if ((x >= LCDM(WIDTH)) || (y >= LCDM(HEIGHT)) | ||
553 | || (x + width <= 0) || (y + height <= 0)) | ||
554 | return; | ||
555 | |||
556 | /* clip image in viewport in screen */ | ||
557 | if (x < 0) | ||
558 | { | ||
559 | width += x; | ||
560 | x = 0; | ||
561 | } | ||
562 | if (y < 0) | ||
563 | { | ||
564 | height += y; | ||
565 | y = 0; | ||
566 | } | ||
567 | if (x + width > LCDM(WIDTH)) | ||
568 | width = LCDM(WIDTH) - x; | ||
569 | if (y + height > LCDM(HEIGHT)) | ||
570 | height = LCDM(HEIGHT) - y; | ||
571 | #endif | ||
486 | 572 | ||
487 | if (current_vp->drawmode & DRMODE_INVERSEVID) | 573 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
488 | { | 574 | { |
@@ -556,12 +642,13 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x, | |||
556 | unsigned mask, mask_bottom; | 642 | unsigned mask, mask_bottom; |
557 | LCDFN(blockfunc_type) *bfunc; | 643 | LCDFN(blockfunc_type) *bfunc; |
558 | 644 | ||
645 | /******************** Image in viewport clipping **********************/ | ||
559 | /* nothing to draw? */ | 646 | /* nothing to draw? */ |
560 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) | 647 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
561 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 648 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
562 | return; | 649 | return; |
563 | 650 | ||
564 | /* clipping */ | 651 | /* clip image in viewport */ |
565 | if (x < 0) | 652 | if (x < 0) |
566 | { | 653 | { |
567 | width += x; | 654 | width += x; |
@@ -582,6 +669,32 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x, | |||
582 | /* adjust for viewport */ | 669 | /* adjust for viewport */ |
583 | x += current_vp->x; | 670 | x += current_vp->x; |
584 | y += current_vp->y; | 671 | y += current_vp->y; |
672 | |||
673 | #if defined(HAVE_VIEWPORT_CLIP) | ||
674 | /********************* Viewport on screen clipping ********************/ | ||
675 | /* nothing to draw? */ | ||
676 | if ((x >= LCDM(WIDTH)) || (y >= LCDM(HEIGHT)) | ||
677 | || (x + width <= 0) || (y + height <= 0)) | ||
678 | return; | ||
679 | |||
680 | /* clip image in viewport in screen */ | ||
681 | if (x < 0) | ||
682 | { | ||
683 | width += x; | ||
684 | src_x -= x; | ||
685 | x = 0; | ||
686 | } | ||
687 | if (y < 0) | ||
688 | { | ||
689 | height += y; | ||
690 | src_y -= y; | ||
691 | y = 0; | ||
692 | } | ||
693 | if (x + width > LCDM(WIDTH)) | ||
694 | width = LCDM(WIDTH) - x; | ||
695 | if (y + height > LCDM(HEIGHT)) | ||
696 | height = LCDM(HEIGHT) - y; | ||
697 | #endif | ||
585 | 698 | ||
586 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 699 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
587 | src_y &= 7; | 700 | src_y &= 7; |
diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c index f9a53ee20c..2e965b35fa 100644 --- a/firmware/drivers/lcd-2bit-horz.c +++ b/firmware/drivers/lcd-2bit-horz.c | |||
@@ -87,6 +87,28 @@ void lcd_set_viewport(struct viewport* vp) | |||
87 | 87 | ||
88 | fg_pattern = 0x55 * (~current_vp->fg_pattern & 3); | 88 | fg_pattern = 0x55 * (~current_vp->fg_pattern & 3); |
89 | bg_pattern = 0x55 * (~current_vp->bg_pattern & 3); | 89 | bg_pattern = 0x55 * (~current_vp->bg_pattern & 3); |
90 | |||
91 | #if defined(SIMULATOR) | ||
92 | /* Force the viewport to be within bounds. If this happens it should | ||
93 | * be considered an error - the viewport will not draw as it might be | ||
94 | * expected. | ||
95 | */ | ||
96 | if((unsigned) current_vp->x > (unsigned) LCD_WIDTH | ||
97 | || (unsigned) current_vp->y > (unsigned) LCD_HEIGHT | ||
98 | || current_vp->x + current_vp->width > LCD_WIDTH | ||
99 | || current_vp->y + current_vp->height > LCD_HEIGHT) | ||
100 | { | ||
101 | #if !defined(HAVE_VIEWPORT_CLIP) | ||
102 | DEBUGF("ERROR: " | ||
103 | #else | ||
104 | DEBUGF("NOTE: " | ||
105 | #endif | ||
106 | "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n", | ||
107 | current_vp->x, current_vp->y, | ||
108 | current_vp->width, current_vp->height); | ||
109 | } | ||
110 | |||
111 | #endif | ||
90 | } | 112 | } |
91 | 113 | ||
92 | void lcd_update_viewport(void) | 114 | void lcd_update_viewport(void) |
@@ -415,8 +437,13 @@ void lcd_clear_viewport(void) | |||
415 | /* Set a single pixel */ | 437 | /* Set a single pixel */ |
416 | void lcd_drawpixel(int x, int y) | 438 | void lcd_drawpixel(int x, int y) |
417 | { | 439 | { |
418 | if (((unsigned)x < (unsigned)current_vp->width) && | 440 | if ( ((unsigned)x < (unsigned)current_vp->width) |
419 | ((unsigned)y < (unsigned)current_vp->height)) | 441 | && ((unsigned)y < (unsigned)current_vp->height) |
442 | #if defined(HAVE_VIEWPORT_CLIP) | ||
443 | && ((unsigned)x < (unsigned)LCD_WIDTH) | ||
444 | && ((unsigned)y < (unsigned)LCD_HEIGHT) | ||
445 | #endif | ||
446 | ) | ||
420 | lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); | 447 | lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); |
421 | } | 448 | } |
422 | 449 | ||
@@ -485,8 +512,13 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
485 | 512 | ||
486 | for (i = 0; i < numpixels; i++) | 513 | for (i = 0; i < numpixels; i++) |
487 | { | 514 | { |
488 | if (((unsigned)x < (unsigned)current_vp->width) && | 515 | if ( ((unsigned)x < (unsigned)current_vp->width) |
489 | ((unsigned)y < (unsigned)current_vp->height)) | 516 | && ((unsigned)y < (unsigned)current_vp->height) |
517 | #if defined(HAVE_VIEWPORT_CLIP) | ||
518 | && ((unsigned)x < (unsigned)LCD_WIDTH) | ||
519 | && ((unsigned)y < (unsigned)LCD_HEIGHT) | ||
520 | #endif | ||
521 | ) | ||
490 | pfunc(current_vp->x + x, current_vp->y + y); | 522 | pfunc(current_vp->x + x, current_vp->y + y); |
491 | 523 | ||
492 | if (d < 0) | 524 | if (d < 0) |
@@ -520,12 +552,12 @@ void lcd_hline(int x1, int x2, int y) | |||
520 | x2 = nx; | 552 | x2 = nx; |
521 | } | 553 | } |
522 | 554 | ||
555 | /******************** In viewport clipping **********************/ | ||
523 | /* nothing to draw? */ | 556 | /* nothing to draw? */ |
524 | if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) | 557 | if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) |
525 | || (x2 < 0)) | 558 | || (x2 < 0)) |
526 | return; | 559 | return; |
527 | 560 | ||
528 | /* clipping */ | ||
529 | if (x1 < 0) | 561 | if (x1 < 0) |
530 | x1 = 0; | 562 | x1 = 0; |
531 | if (x2 >= current_vp->width) | 563 | if (x2 >= current_vp->width) |
@@ -535,6 +567,20 @@ void lcd_hline(int x1, int x2, int y) | |||
535 | x1 += current_vp->x; | 567 | x1 += current_vp->x; |
536 | x2 += current_vp->x; | 568 | x2 += current_vp->x; |
537 | y += current_vp->y; | 569 | y += current_vp->y; |
570 | |||
571 | #if defined(HAVE_VIEWPORT_CLIP) | ||
572 | /********************* Viewport on screen clipping ********************/ | ||
573 | /* nothing to draw? */ | ||
574 | if (((unsigned)y >= (unsigned) LCD_HEIGHT) || (x1 >= LCD_WIDTH) | ||
575 | || (x2 < 0)) | ||
576 | return; | ||
577 | |||
578 | /* clipping */ | ||
579 | if (x1 < 0) | ||
580 | x1 = 0; | ||
581 | if (x2 >= LCD_WIDTH) | ||
582 | x2 = LCD_WIDTH-1; | ||
583 | #endif | ||
538 | 584 | ||
539 | bfunc = lcd_blockfuncs[current_vp->drawmode]; | 585 | bfunc = lcd_blockfuncs[current_vp->drawmode]; |
540 | dst = &lcd_framebuffer[y][x1>>2]; | 586 | dst = &lcd_framebuffer[y][x1>>2]; |
@@ -567,12 +613,12 @@ void lcd_vline(int x, int y1, int y2) | |||
567 | y2 = y; | 613 | y2 = y; |
568 | } | 614 | } |
569 | 615 | ||
616 | /******************** In viewport clipping **********************/ | ||
570 | /* nothing to draw? */ | 617 | /* nothing to draw? */ |
571 | if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) | 618 | if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) |
572 | || (y2 < 0)) | 619 | || (y2 < 0)) |
573 | return; | 620 | return; |
574 | 621 | ||
575 | /* clipping */ | ||
576 | if (y1 < 0) | 622 | if (y1 < 0) |
577 | y1 = 0; | 623 | y1 = 0; |
578 | if (y2 >= current_vp->height) | 624 | if (y2 >= current_vp->height) |
@@ -582,6 +628,20 @@ void lcd_vline(int x, int y1, int y2) | |||
582 | y1 += current_vp->y; | 628 | y1 += current_vp->y; |
583 | y2 += current_vp->y; | 629 | y2 += current_vp->y; |
584 | x += current_vp->x; | 630 | x += current_vp->x; |
631 | |||
632 | #if defined(HAVE_VIEWPORT_CLIP) | ||
633 | /********************* Viewport on screen clipping ********************/ | ||
634 | /* nothing to draw? */ | ||
635 | if (( (unsigned) x >= (unsigned)LCD_WIDTH) || (y1 >= LCD_HEIGHT) | ||
636 | || (y2 < 0)) | ||
637 | return; | ||
638 | |||
639 | /* clipping */ | ||
640 | if (y1 < 0) | ||
641 | y1 = 0; | ||
642 | if (y2 >= LCD_HEIGHT) | ||
643 | y2 = LCD_HEIGHT-1; | ||
644 | #endif | ||
585 | 645 | ||
586 | bfunc = lcd_blockfuncs[current_vp->drawmode]; | 646 | bfunc = lcd_blockfuncs[current_vp->drawmode]; |
587 | dst = &lcd_framebuffer[y1][x>>2]; | 647 | dst = &lcd_framebuffer[y1][x>>2]; |
@@ -619,12 +679,12 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
619 | unsigned mask, mask_right; | 679 | unsigned mask, mask_right; |
620 | lcd_blockfunc_type *bfunc; | 680 | lcd_blockfunc_type *bfunc; |
621 | 681 | ||
682 | /******************** In viewport clipping **********************/ | ||
622 | /* nothing to draw? */ | 683 | /* nothing to draw? */ |
623 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || (y >= current_vp->height) | 684 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || (y >= current_vp->height) |
624 | || (x + width <= 0) || (y + height <= 0)) | 685 | || (x + width <= 0) || (y + height <= 0)) |
625 | return; | 686 | return; |
626 | 687 | ||
627 | /* clipping */ | ||
628 | if (x < 0) | 688 | if (x < 0) |
629 | { | 689 | { |
630 | width += x; | 690 | width += x; |
@@ -643,6 +703,30 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
643 | /* adjust for viewport */ | 703 | /* adjust for viewport */ |
644 | x += current_vp->x; | 704 | x += current_vp->x; |
645 | y += current_vp->y; | 705 | y += current_vp->y; |
706 | |||
707 | #if defined(HAVE_VIEWPORT_CLIP) | ||
708 | /********************* Viewport on screen clipping ********************/ | ||
709 | /* nothing to draw? */ | ||
710 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
711 | || (x + width <= 0) || (y + height <= 0)) | ||
712 | return; | ||
713 | |||
714 | /* clip image in viewport in screen */ | ||
715 | if (x < 0) | ||
716 | { | ||
717 | width += x; | ||
718 | x = 0; | ||
719 | } | ||
720 | if (y < 0) | ||
721 | { | ||
722 | height += y; | ||
723 | y = 0; | ||
724 | } | ||
725 | if (x + width > LCD_WIDTH) | ||
726 | width = LCD_WIDTH - x; | ||
727 | if (y + height > LCD_HEIGHT) | ||
728 | height = LCD_HEIGHT - y; | ||
729 | #endif | ||
646 | 730 | ||
647 | bfunc = lcd_blockfuncs[current_vp->drawmode]; | 731 | bfunc = lcd_blockfuncs[current_vp->drawmode]; |
648 | dst = &lcd_framebuffer[y][x>>2]; | 732 | dst = &lcd_framebuffer[y][x>>2]; |
@@ -696,12 +780,12 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
696 | unsigned dst_mask; | 780 | unsigned dst_mask; |
697 | int drmode = current_vp->drawmode; | 781 | int drmode = current_vp->drawmode; |
698 | 782 | ||
783 | /******************** Image in viewport clipping **********************/ | ||
699 | /* nothing to draw? */ | 784 | /* nothing to draw? */ |
700 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 785 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
701 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 786 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
702 | return; | 787 | return; |
703 | 788 | ||
704 | /* clipping */ | ||
705 | if (x < 0) | 789 | if (x < 0) |
706 | { | 790 | { |
707 | width += x; | 791 | width += x; |
@@ -718,12 +802,41 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
718 | width = current_vp->width - x; | 802 | width = current_vp->width - x; |
719 | if (y + height > current_vp->height) | 803 | if (y + height > current_vp->height) |
720 | height = current_vp->height - y; | 804 | height = current_vp->height - y; |
805 | |||
806 | x += current_vp->x; /* adjust for viewport */ | ||
807 | y += current_vp->y; /* adjust for viewport */ | ||
808 | |||
809 | #if defined(HAVE_VIEWPORT_CLIP) | ||
810 | /********************* Viewport on screen clipping ********************/ | ||
811 | /* nothing to draw? */ | ||
812 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
813 | || (x + width <= 0) || (y + height <= 0)) | ||
814 | return; | ||
815 | |||
816 | /* clip image in viewport in screen */ | ||
817 | if (x < 0) | ||
818 | { | ||
819 | width += x; | ||
820 | src_x -= x; | ||
821 | x = 0; | ||
822 | } | ||
823 | if (y < 0) | ||
824 | { | ||
825 | height += y; | ||
826 | src_y -= y; | ||
827 | y = 0; | ||
828 | } | ||
829 | if (x + width > LCD_WIDTH) | ||
830 | width = LCD_WIDTH - x; | ||
831 | if (y + height > LCD_HEIGHT) | ||
832 | height = LCD_HEIGHT - y; | ||
833 | #endif | ||
721 | 834 | ||
722 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 835 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
723 | src_y &= 7; | 836 | src_y &= 7; |
724 | src_end = src + width; | 837 | src_end = src + width; |
725 | x += current_vp->x; /* adjust for viewport */ | 838 | |
726 | dst = &lcd_framebuffer[current_vp->y + y][x >> 2]; | 839 | dst = &lcd_framebuffer[y][x >> 2]; |
727 | dst_end = dst + height * LCD_FBWIDTH; | 840 | dst_end = dst + height * LCD_FBWIDTH; |
728 | dst_mask = pixmask[x & 3]; | 841 | dst_mask = pixmask[x & 3]; |
729 | 842 | ||
@@ -879,12 +992,12 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x, | |||
879 | unsigned char *dst, *dst_end; | 992 | unsigned char *dst, *dst_end; |
880 | unsigned mask, mask_right; | 993 | unsigned mask, mask_right; |
881 | 994 | ||
995 | /******************** Image in viewport clipping **********************/ | ||
882 | /* nothing to draw? */ | 996 | /* nothing to draw? */ |
883 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 997 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
884 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 998 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
885 | return; | 999 | return; |
886 | 1000 | ||
887 | /* clipping */ | ||
888 | if (x < 0) | 1001 | if (x < 0) |
889 | { | 1002 | { |
890 | width += x; | 1003 | width += x; |
@@ -905,6 +1018,32 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x, | |||
905 | /* adjust for viewport */ | 1018 | /* adjust for viewport */ |
906 | x += current_vp->x; | 1019 | x += current_vp->x; |
907 | y += current_vp->y; | 1020 | y += current_vp->y; |
1021 | |||
1022 | #if defined(HAVE_VIEWPORT_CLIP) | ||
1023 | /********************* Viewport on screen clipping ********************/ | ||
1024 | /* nothing to draw? */ | ||
1025 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
1026 | || (x + width <= 0) || (y + height <= 0)) | ||
1027 | return; | ||
1028 | |||
1029 | /* clip image in viewport in screen */ | ||
1030 | if (x < 0) | ||
1031 | { | ||
1032 | width += x; | ||
1033 | src_x -= x; | ||
1034 | x = 0; | ||
1035 | } | ||
1036 | if (y < 0) | ||
1037 | { | ||
1038 | height += y; | ||
1039 | src_y -= y; | ||
1040 | y = 0; | ||
1041 | } | ||
1042 | if (x + width > LCD_WIDTH) | ||
1043 | width = LCD_WIDTH - x; | ||
1044 | if (y + height > LCD_HEIGHT) | ||
1045 | height = LCD_HEIGHT - y; | ||
1046 | #endif | ||
908 | 1047 | ||
909 | stride = (stride + 3) >> 2; /* convert to no. of bytes */ | 1048 | stride = (stride + 3) >> 2; /* convert to no. of bytes */ |
910 | 1049 | ||
diff --git a/firmware/drivers/lcd-2bit-vert.c b/firmware/drivers/lcd-2bit-vert.c index a124e3e15d..3a089722f4 100644 --- a/firmware/drivers/lcd-2bit-vert.c +++ b/firmware/drivers/lcd-2bit-vert.c | |||
@@ -89,6 +89,28 @@ void lcd_set_viewport(struct viewport* vp) | |||
89 | 89 | ||
90 | fg_pattern = 0x55 * (~current_vp->fg_pattern & 3); | 90 | fg_pattern = 0x55 * (~current_vp->fg_pattern & 3); |
91 | bg_pattern = 0x55 * (~current_vp->bg_pattern & 3); | 91 | bg_pattern = 0x55 * (~current_vp->bg_pattern & 3); |
92 | |||
93 | #if defined(SIMULATOR) | ||
94 | /* Force the viewport to be within bounds. If this happens it should | ||
95 | * be considered an error - the viewport will not draw as it might be | ||
96 | * expected. | ||
97 | */ | ||
98 | if((unsigned) current_vp->x > (unsigned) LCD_WIDTH | ||
99 | || (unsigned) current_vp->y > (unsigned) LCD_HEIGHT | ||
100 | || current_vp->x + current_vp->width > LCD_WIDTH | ||
101 | || current_vp->y + current_vp->height > LCD_HEIGHT) | ||
102 | { | ||
103 | #if !defined(HAVE_VIEWPORT_CLIP) | ||
104 | DEBUGF("ERROR: " | ||
105 | #else | ||
106 | DEBUGF("NOTE: " | ||
107 | #endif | ||
108 | "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n", | ||
109 | current_vp->x, current_vp->y, | ||
110 | current_vp->width, current_vp->height); | ||
111 | } | ||
112 | |||
113 | #endif | ||
92 | } | 114 | } |
93 | 115 | ||
94 | void lcd_update_viewport(void) | 116 | void lcd_update_viewport(void) |
@@ -418,8 +440,13 @@ void lcd_clear_viewport(void) | |||
418 | /* Set a single pixel */ | 440 | /* Set a single pixel */ |
419 | void lcd_drawpixel(int x, int y) | 441 | void lcd_drawpixel(int x, int y) |
420 | { | 442 | { |
421 | if (((unsigned)x < (unsigned)current_vp->width) && | 443 | if ( ((unsigned)x < (unsigned)current_vp->width) |
422 | ((unsigned)y < (unsigned)current_vp->height)) | 444 | && ((unsigned)y < (unsigned)current_vp->height) |
445 | #if defined(HAVE_VIEWPORT_CLIP) | ||
446 | && ((unsigned)x < (unsigned)LCD_WIDTH) | ||
447 | && ((unsigned)y < (unsigned)LCD_HEIGHT) | ||
448 | #endif | ||
449 | ) | ||
423 | lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); | 450 | lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); |
424 | } | 451 | } |
425 | 452 | ||
@@ -488,8 +515,13 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
488 | 515 | ||
489 | for (i = 0; i < numpixels; i++) | 516 | for (i = 0; i < numpixels; i++) |
490 | { | 517 | { |
491 | if (((unsigned)x < (unsigned)current_vp->width) && | 518 | if ( ((unsigned)x < (unsigned)current_vp->width) |
492 | ((unsigned)y < (unsigned)current_vp->height)) | 519 | && ((unsigned)y < (unsigned)current_vp->height) |
520 | #if defined(HAVE_VIEWPORT_CLIP) | ||
521 | && ((unsigned)x < (unsigned)LCD_WIDTH) | ||
522 | && ((unsigned)y < (unsigned)LCD_HEIGHT) | ||
523 | #endif | ||
524 | ) | ||
493 | pfunc(current_vp->x + x, current_vp->y + y); | 525 | pfunc(current_vp->x + x, current_vp->y + y); |
494 | 526 | ||
495 | if (d < 0) | 527 | if (d < 0) |
@@ -524,22 +556,37 @@ void lcd_hline(int x1, int x2, int y) | |||
524 | x2 = x; | 556 | x2 = x; |
525 | } | 557 | } |
526 | 558 | ||
559 | /******************** In viewport clipping **********************/ | ||
527 | /* nothing to draw? */ | 560 | /* nothing to draw? */ |
528 | if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) | 561 | if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) |
529 | || (x2 < 0)) | 562 | || (x2 < 0)) |
530 | return; | 563 | return; |
531 | 564 | ||
532 | /* clipping */ | ||
533 | if (x1 < 0) | 565 | if (x1 < 0) |
534 | x1 = 0; | 566 | x1 = 0; |
535 | if (x2 >= current_vp->width) | 567 | if (x2 >= current_vp->width) |
536 | x2 = current_vp->width-1; | 568 | x2 = current_vp->width-1; |
537 | 569 | ||
538 | width = x2 - x1 + 1; | ||
539 | |||
540 | /* adjust x1 and y to viewport */ | 570 | /* adjust x1 and y to viewport */ |
541 | x1 += current_vp->x; | 571 | x1 += current_vp->x; |
572 | x2 += current_vp->x; | ||
542 | y += current_vp->y; | 573 | y += current_vp->y; |
574 | |||
575 | #if defined(HAVE_VIEWPORT_CLIP) | ||
576 | /********************* Viewport on screen clipping ********************/ | ||
577 | /* nothing to draw? */ | ||
578 | if (((unsigned)y >= (unsigned) LCD_HEIGHT) || (x1 >= LCD_WIDTH) | ||
579 | || (x2 < 0)) | ||
580 | return; | ||
581 | |||
582 | /* clipping */ | ||
583 | if (x1 < 0) | ||
584 | x1 = 0; | ||
585 | if (x2 >= LCD_WIDTH) | ||
586 | x2 = LCD_WIDTH-1; | ||
587 | #endif | ||
588 | |||
589 | width = x2 - x1 + 1; | ||
543 | 590 | ||
544 | bfunc = lcd_blockfuncs[current_vp->drawmode]; | 591 | bfunc = lcd_blockfuncs[current_vp->drawmode]; |
545 | dst = &lcd_framebuffer[y>>2][x1]; | 592 | dst = &lcd_framebuffer[y>>2][x1]; |
@@ -567,12 +614,12 @@ void lcd_vline(int x, int y1, int y2) | |||
567 | y2 = ny; | 614 | y2 = ny; |
568 | } | 615 | } |
569 | 616 | ||
617 | /******************** In viewport clipping **********************/ | ||
570 | /* nothing to draw? */ | 618 | /* nothing to draw? */ |
571 | if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) | 619 | if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) |
572 | || (y2 < 0)) | 620 | || (y2 < 0)) |
573 | return; | 621 | return; |
574 | 622 | ||
575 | /* clipping */ | ||
576 | if (y1 < 0) | 623 | if (y1 < 0) |
577 | y1 = 0; | 624 | y1 = 0; |
578 | if (y2 >= current_vp->height) | 625 | if (y2 >= current_vp->height) |
@@ -582,6 +629,20 @@ void lcd_vline(int x, int y1, int y2) | |||
582 | y1 += current_vp->y; | 629 | y1 += current_vp->y; |
583 | y2 += current_vp->y; | 630 | y2 += current_vp->y; |
584 | x += current_vp->x; | 631 | x += current_vp->x; |
632 | |||
633 | #if defined(HAVE_VIEWPORT_CLIP) | ||
634 | /********************* Viewport on screen clipping ********************/ | ||
635 | /* nothing to draw? */ | ||
636 | if (( (unsigned) x >= (unsigned)LCD_WIDTH) || (y1 >= LCD_HEIGHT) | ||
637 | || (y2 < 0)) | ||
638 | return; | ||
639 | |||
640 | /* clipping */ | ||
641 | if (y1 < 0) | ||
642 | y1 = 0; | ||
643 | if (y2 >= LCD_HEIGHT) | ||
644 | y2 = LCD_HEIGHT-1; | ||
645 | #endif | ||
585 | 646 | ||
586 | bfunc = lcd_blockfuncs[current_vp->drawmode]; | 647 | bfunc = lcd_blockfuncs[current_vp->drawmode]; |
587 | dst = &lcd_framebuffer[y1>>2][x]; | 648 | dst = &lcd_framebuffer[y1>>2][x]; |
@@ -624,12 +685,12 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
624 | lcd_blockfunc_type *bfunc; | 685 | lcd_blockfunc_type *bfunc; |
625 | bool fillopt = false; | 686 | bool fillopt = false; |
626 | 687 | ||
688 | /******************** In viewport clipping **********************/ | ||
627 | /* nothing to draw? */ | 689 | /* nothing to draw? */ |
628 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) | 690 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
629 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 691 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
630 | return; | 692 | return; |
631 | 693 | ||
632 | /* clipping */ | ||
633 | if (x < 0) | 694 | if (x < 0) |
634 | { | 695 | { |
635 | width += x; | 696 | width += x; |
@@ -648,6 +709,30 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
648 | /* adjust for viewport */ | 709 | /* adjust for viewport */ |
649 | x += current_vp->x; | 710 | x += current_vp->x; |
650 | y += current_vp->y; | 711 | y += current_vp->y; |
712 | |||
713 | #if defined(HAVE_VIEWPORT_CLIP) | ||
714 | /********************* Viewport on screen clipping ********************/ | ||
715 | /* nothing to draw? */ | ||
716 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
717 | || (x + width <= 0) || (y + height <= 0)) | ||
718 | return; | ||
719 | |||
720 | /* clip image in viewport in screen */ | ||
721 | if (x < 0) | ||
722 | { | ||
723 | width += x; | ||
724 | x = 0; | ||
725 | } | ||
726 | if (y < 0) | ||
727 | { | ||
728 | height += y; | ||
729 | y = 0; | ||
730 | } | ||
731 | if (x + width > LCD_WIDTH) | ||
732 | width = LCD_WIDTH - x; | ||
733 | if (y + height > LCD_HEIGHT) | ||
734 | height = LCD_HEIGHT - y; | ||
735 | #endif | ||
651 | 736 | ||
652 | if (current_vp->drawmode & DRMODE_INVERSEVID) | 737 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
653 | { | 738 | { |
@@ -722,12 +807,12 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
722 | unsigned mask, mask_bottom; | 807 | unsigned mask, mask_bottom; |
723 | lcd_blockfunc_type *bfunc; | 808 | lcd_blockfunc_type *bfunc; |
724 | 809 | ||
810 | /******************** Image in viewport clipping **********************/ | ||
725 | /* nothing to draw? */ | 811 | /* nothing to draw? */ |
726 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 812 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
727 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 813 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
728 | return; | 814 | return; |
729 | 815 | ||
730 | /* clipping */ | ||
731 | if (x < 0) | 816 | if (x < 0) |
732 | { | 817 | { |
733 | width += x; | 818 | width += x; |
@@ -748,6 +833,32 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
748 | /* adjust for viewport */ | 833 | /* adjust for viewport */ |
749 | x += current_vp->x; | 834 | x += current_vp->x; |
750 | y += current_vp->y; | 835 | y += current_vp->y; |
836 | |||
837 | #if defined(HAVE_VIEWPORT_CLIP) | ||
838 | /********************* Viewport on screen clipping ********************/ | ||
839 | /* nothing to draw? */ | ||
840 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
841 | || (x + width <= 0) || (y + height <= 0)) | ||
842 | return; | ||
843 | |||
844 | /* clip image in viewport in screen */ | ||
845 | if (x < 0) | ||
846 | { | ||
847 | width += x; | ||
848 | src_x -= x; | ||
849 | x = 0; | ||
850 | } | ||
851 | if (y < 0) | ||
852 | { | ||
853 | height += y; | ||
854 | src_y -= y; | ||
855 | y = 0; | ||
856 | } | ||
857 | if (x + width > LCD_WIDTH) | ||
858 | width = LCD_WIDTH - x; | ||
859 | if (y + height > LCD_HEIGHT) | ||
860 | height = LCD_HEIGHT - y; | ||
861 | #endif | ||
751 | 862 | ||
752 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 863 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
753 | src_y &= 7; | 864 | src_y &= 7; |
@@ -893,12 +1004,12 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
893 | fb_data *dst, *dst_end; | 1004 | fb_data *dst, *dst_end; |
894 | unsigned mask, mask_bottom; | 1005 | unsigned mask, mask_bottom; |
895 | 1006 | ||
1007 | /******************** Image in viewport clipping **********************/ | ||
896 | /* nothing to draw? */ | 1008 | /* nothing to draw? */ |
897 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) | 1009 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
898 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 1010 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
899 | return; | 1011 | return; |
900 | 1012 | ||
901 | /* clipping */ | ||
902 | if (x < 0) | 1013 | if (x < 0) |
903 | { | 1014 | { |
904 | width += x; | 1015 | width += x; |
@@ -919,6 +1030,32 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
919 | /* adjust for viewport */ | 1030 | /* adjust for viewport */ |
920 | x += current_vp->x; | 1031 | x += current_vp->x; |
921 | y += current_vp->y; | 1032 | y += current_vp->y; |
1033 | |||
1034 | #if defined(HAVE_VIEWPORT_CLIP) | ||
1035 | /********************* Viewport on screen clipping ********************/ | ||
1036 | /* nothing to draw? */ | ||
1037 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
1038 | || (x + width <= 0) || (y + height <= 0)) | ||
1039 | return; | ||
1040 | |||
1041 | /* clip image in viewport in screen */ | ||
1042 | if (x < 0) | ||
1043 | { | ||
1044 | width += x; | ||
1045 | src_x -= x; | ||
1046 | x = 0; | ||
1047 | } | ||
1048 | if (y < 0) | ||
1049 | { | ||
1050 | height += y; | ||
1051 | src_y -= y; | ||
1052 | y = 0; | ||
1053 | } | ||
1054 | if (x + width > LCD_WIDTH) | ||
1055 | width = LCD_WIDTH - x; | ||
1056 | if (y + height > LCD_HEIGHT) | ||
1057 | height = LCD_HEIGHT - y; | ||
1058 | #endif | ||
922 | 1059 | ||
923 | src += stride * (src_y >> 2) + src_x; /* move starting point */ | 1060 | src += stride * (src_y >> 2) + src_x; /* move starting point */ |
924 | src_y &= 3; | 1061 | src_y &= 3; |
diff --git a/firmware/drivers/lcd-2bit-vi.c b/firmware/drivers/lcd-2bit-vi.c index 9ce952b9e0..5edb588ce0 100644 --- a/firmware/drivers/lcd-2bit-vi.c +++ b/firmware/drivers/lcd-2bit-vi.c | |||
@@ -82,6 +82,28 @@ void LCDFN(set_viewport)(struct viewport* vp) | |||
82 | 82 | ||
83 | fg_pattern = patterns[current_vp->fg_pattern & 3]; | 83 | fg_pattern = patterns[current_vp->fg_pattern & 3]; |
84 | bg_pattern = patterns[current_vp->bg_pattern & 3]; | 84 | bg_pattern = patterns[current_vp->bg_pattern & 3]; |
85 | |||
86 | #if defined(SIMULATOR) | ||
87 | /* Force the viewport to be within bounds. If this happens it should | ||
88 | * be considered an error - the viewport will not draw as it might be | ||
89 | * expected. | ||
90 | */ | ||
91 | if((unsigned) current_vp->x > (unsigned) LCDM(WIDTH) | ||
92 | || (unsigned) current_vp->y > (unsigned) LCDM(HEIGHT) | ||
93 | || current_vp->x + current_vp->width > LCDM(WIDTH) | ||
94 | || current_vp->y + current_vp->height > LCDM(HEIGHT)) | ||
95 | { | ||
96 | #if !defined(HAVE_VIEWPORT_CLIP) | ||
97 | DEBUGF("ERROR: " | ||
98 | #else | ||
99 | DEBUGF("NOTE: " | ||
100 | #endif | ||
101 | "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n", | ||
102 | current_vp->x, current_vp->y, | ||
103 | current_vp->width, current_vp->height); | ||
104 | } | ||
105 | |||
106 | #endif | ||
85 | } | 107 | } |
86 | 108 | ||
87 | void LCDFN(update_viewport)(void) | 109 | void LCDFN(update_viewport)(void) |
@@ -443,8 +465,13 @@ void LCDFN(clear_viewport)(void) | |||
443 | /* Set a single pixel */ | 465 | /* Set a single pixel */ |
444 | void LCDFN(drawpixel)(int x, int y) | 466 | void LCDFN(drawpixel)(int x, int y) |
445 | { | 467 | { |
446 | if (((unsigned)x < (unsigned)current_vp->width) && | 468 | if ( ((unsigned)x < (unsigned)current_vp->width) |
447 | ((unsigned)y < (unsigned)current_vp->height)) | 469 | && ((unsigned)y < (unsigned)current_vp->height) |
470 | #if defined(HAVE_VIEWPORT_CLIP) | ||
471 | && ((unsigned)x < (unsigned)LCDM(WIDTH)) | ||
472 | && ((unsigned)y < (unsigned)LCDM(HEIGHT)) | ||
473 | #endif | ||
474 | ) | ||
448 | LCDFN(pixelfuncs)[current_vp->drawmode](current_vp->x+x, current_vp->y+y); | 475 | LCDFN(pixelfuncs)[current_vp->drawmode](current_vp->x+x, current_vp->y+y); |
449 | } | 476 | } |
450 | 477 | ||
@@ -513,8 +540,13 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2) | |||
513 | 540 | ||
514 | for (i = 0; i < numpixels; i++) | 541 | for (i = 0; i < numpixels; i++) |
515 | { | 542 | { |
516 | if (((unsigned)x < (unsigned)current_vp->width) && | 543 | if ( ((unsigned)x < (unsigned)current_vp->width) |
517 | ((unsigned)y < (unsigned)current_vp->height)) | 544 | && ((unsigned)y < (unsigned)current_vp->height) |
545 | #if defined(HAVE_VIEWPORT_CLIP) | ||
546 | && ((unsigned)x < (unsigned)LCDM(WIDTH)) | ||
547 | && ((unsigned)y < (unsigned)LCDM(HEIGHT)) | ||
548 | #endif | ||
549 | ) | ||
518 | pfunc(current_vp->x + x, current_vp->y + y); | 550 | pfunc(current_vp->x + x, current_vp->y + y); |
519 | 551 | ||
520 | if (d < 0) | 552 | if (d < 0) |
@@ -548,24 +580,40 @@ void LCDFN(hline)(int x1, int x2, int y) | |||
548 | x1 = x2; | 580 | x1 = x2; |
549 | x2 = x; | 581 | x2 = x; |
550 | } | 582 | } |
551 | 583 | ||
584 | /******************** In viewport clipping **********************/ | ||
552 | /* nothing to draw? */ | 585 | /* nothing to draw? */ |
553 | if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) | 586 | if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) |
554 | || (x2 < 0)) | 587 | || (x2 < 0)) |
555 | return; | 588 | return; |
556 | 589 | ||
557 | /* clipping */ | ||
558 | if (x1 < 0) | 590 | if (x1 < 0) |
559 | x1 = 0; | 591 | x1 = 0; |
560 | if (x2 >= current_vp->width) | 592 | if (x2 >= current_vp->width) |
561 | x2 = current_vp->width-1; | 593 | x2 = current_vp->width-1; |
562 | 594 | ||
563 | width = x2 - x1 + 1; | ||
564 | |||
565 | /* adjust x1 and y to viewport */ | 595 | /* adjust x1 and y to viewport */ |
566 | x1 += current_vp->x; | 596 | x1 += current_vp->x; |
567 | y += current_vp->y; | 597 | y += current_vp->y; |
568 | 598 | ||
599 | #if defined(HAVE_VIEWPORT_CLIP) | ||
600 | x2 += current_vp->x; | ||
601 | |||
602 | /********************* Viewport on screen clipping ********************/ | ||
603 | /* nothing to draw? */ | ||
604 | if (((unsigned)y >= (unsigned) LCDM(HEIGHT)) || (x1 >= LCDM(WIDTH)) | ||
605 | || (x2 < 0)) | ||
606 | return; | ||
607 | |||
608 | /* clipping */ | ||
609 | if (x1 < 0) | ||
610 | x1 = 0; | ||
611 | if (x2 >= LCDM(WIDTH)) | ||
612 | x2 = LCDM(WIDTH)-1; | ||
613 | #endif | ||
614 | |||
615 | width = x2 - x1 + 1; | ||
616 | |||
569 | bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; | 617 | bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; |
570 | dst = &LCDFN(framebuffer)[y>>3][x1]; | 618 | dst = &LCDFN(framebuffer)[y>>3][x1]; |
571 | mask = 0x0101 << (y & 7); | 619 | mask = 0x0101 << (y & 7); |
@@ -592,12 +640,12 @@ void LCDFN(vline)(int x, int y1, int y2) | |||
592 | y2 = ny; | 640 | y2 = ny; |
593 | } | 641 | } |
594 | 642 | ||
643 | /******************** In viewport clipping **********************/ | ||
595 | /* nothing to draw? */ | 644 | /* nothing to draw? */ |
596 | if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) | 645 | if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) |
597 | || (y2 < 0)) | 646 | || (y2 < 0)) |
598 | return; | 647 | return; |
599 | 648 | ||
600 | /* clipping */ | ||
601 | if (y1 < 0) | 649 | if (y1 < 0) |
602 | y1 = 0; | 650 | y1 = 0; |
603 | if (y2 >= current_vp->height) | 651 | if (y2 >= current_vp->height) |
@@ -607,6 +655,20 @@ void LCDFN(vline)(int x, int y1, int y2) | |||
607 | y1 += current_vp->y; | 655 | y1 += current_vp->y; |
608 | y2 += current_vp->y; | 656 | y2 += current_vp->y; |
609 | x += current_vp->x; | 657 | x += current_vp->x; |
658 | |||
659 | #if defined(HAVE_VIEWPORT_CLIP) | ||
660 | /********************* Viewport on screen clipping ********************/ | ||
661 | /* nothing to draw? */ | ||
662 | if (( (unsigned) x >= (unsigned)LCDM(WIDTH)) || (y1 >= LCDM(HEIGHT)) | ||
663 | || (y2 < 0)) | ||
664 | return; | ||
665 | |||
666 | /* clipping */ | ||
667 | if (y1 < 0) | ||
668 | y1 = 0; | ||
669 | if (y2 >= LCDM(HEIGHT)) | ||
670 | y2 = LCDM(HEIGHT)-1; | ||
671 | #endif | ||
610 | 672 | ||
611 | bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; | 673 | bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; |
612 | dst = &LCDFN(framebuffer)[y1>>3][x]; | 674 | dst = &LCDFN(framebuffer)[y1>>3][x]; |
@@ -651,12 +713,12 @@ void LCDFN(fillrect)(int x, int y, int width, int height) | |||
651 | LCDFN(blockfunc_type) *bfunc; | 713 | LCDFN(blockfunc_type) *bfunc; |
652 | bool fillopt = false; | 714 | bool fillopt = false; |
653 | 715 | ||
716 | /******************** In viewport clipping **********************/ | ||
654 | /* nothing to draw? */ | 717 | /* nothing to draw? */ |
655 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) | 718 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
656 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 719 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
657 | return; | 720 | return; |
658 | 721 | ||
659 | /* clipping */ | ||
660 | if (x < 0) | 722 | if (x < 0) |
661 | { | 723 | { |
662 | width += x; | 724 | width += x; |
@@ -675,6 +737,31 @@ void LCDFN(fillrect)(int x, int y, int width, int height) | |||
675 | /* adjust for viewport */ | 737 | /* adjust for viewport */ |
676 | x += current_vp->x; | 738 | x += current_vp->x; |
677 | y += current_vp->y; | 739 | y += current_vp->y; |
740 | |||
741 | #if defined(HAVE_VIEWPORT_CLIP) | ||
742 | /********************* Viewport on screen clipping ********************/ | ||
743 | /* nothing to draw? */ | ||
744 | if ((x >= LCDM(WIDTH)) || (y >= LCDM(HEIGHT)) | ||
745 | || (x + width <= 0) || (y + height <= 0)) | ||
746 | return; | ||
747 | |||
748 | /* clip image in viewport in screen */ | ||
749 | if (x < 0) | ||
750 | { | ||
751 | width += x; | ||
752 | x = 0; | ||
753 | } | ||
754 | if (y < 0) | ||
755 | { | ||
756 | height += y; | ||
757 | y = 0; | ||
758 | } | ||
759 | if (x + width > LCDM(WIDTH)) | ||
760 | width = LCDM(WIDTH) - x; | ||
761 | if (y + height > LCDM(HEIGHT)) | ||
762 | height = LCDM(HEIGHT) - y; | ||
763 | #endif | ||
764 | |||
678 | 765 | ||
679 | if (current_vp->drawmode & DRMODE_INVERSEVID) | 766 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
680 | { | 767 | { |
@@ -751,12 +838,12 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x, | |||
751 | unsigned data, mask, mask_bottom; | 838 | unsigned data, mask, mask_bottom; |
752 | LCDFN(blockfunc_type) *bfunc; | 839 | LCDFN(blockfunc_type) *bfunc; |
753 | 840 | ||
841 | /******************** Image in viewport clipping **********************/ | ||
754 | /* nothing to draw? */ | 842 | /* nothing to draw? */ |
755 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 843 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
756 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 844 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
757 | return; | 845 | return; |
758 | 846 | ||
759 | /* clipping */ | ||
760 | if (x < 0) | 847 | if (x < 0) |
761 | { | 848 | { |
762 | width += x; | 849 | width += x; |
@@ -777,6 +864,32 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x, | |||
777 | /* adjust for viewport */ | 864 | /* adjust for viewport */ |
778 | x += current_vp->x; | 865 | x += current_vp->x; |
779 | y += current_vp->y; | 866 | y += current_vp->y; |
867 | |||
868 | #if defined(HAVE_VIEWPORT_CLIP) | ||
869 | /********************* Viewport on screen clipping ********************/ | ||
870 | /* nothing to draw? */ | ||
871 | if ((x >= LCDM(WIDTH)) || (y >= LCDM(HEIGHT)) | ||
872 | || (x + width <= 0) || (y + height <= 0)) | ||
873 | return; | ||
874 | |||
875 | /* clip image in viewport in screen */ | ||
876 | if (x < 0) | ||
877 | { | ||
878 | width += x; | ||
879 | src_x -= x; | ||
880 | x = 0; | ||
881 | } | ||
882 | if (y < 0) | ||
883 | { | ||
884 | height += y; | ||
885 | src_y -= y; | ||
886 | y = 0; | ||
887 | } | ||
888 | if (x + width > LCDM(WIDTH)) | ||
889 | width = LCDM(WIDTH) - x; | ||
890 | if (y + height > LCDM(HEIGHT)) | ||
891 | height = LCDM(HEIGHT) - y; | ||
892 | #endif | ||
780 | 893 | ||
781 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 894 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
782 | src_y &= 7; | 895 | src_y &= 7; |
@@ -893,12 +1006,12 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x, | |||
893 | FBFN(data) *dst, *dst_end; | 1006 | FBFN(data) *dst, *dst_end; |
894 | unsigned mask, mask_bottom; | 1007 | unsigned mask, mask_bottom; |
895 | 1008 | ||
1009 | /******************** Image in viewport clipping **********************/ | ||
896 | /* nothing to draw? */ | 1010 | /* nothing to draw? */ |
897 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) | 1011 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) |
898 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 1012 | || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
899 | return; | 1013 | return; |
900 | 1014 | ||
901 | /* clipping */ | ||
902 | if (x < 0) | 1015 | if (x < 0) |
903 | { | 1016 | { |
904 | width += x; | 1017 | width += x; |
@@ -920,6 +1033,32 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x, | |||
920 | x += current_vp->x; | 1033 | x += current_vp->x; |
921 | y += current_vp->y; | 1034 | y += current_vp->y; |
922 | 1035 | ||
1036 | #if defined(HAVE_VIEWPORT_CLIP) | ||
1037 | /********************* Viewport on screen clipping ********************/ | ||
1038 | /* nothing to draw? */ | ||
1039 | if ((x >= LCDM(WIDTH)) || (y >= LCDM(HEIGHT)) | ||
1040 | || (x + width <= 0) || (y + height <= 0)) | ||
1041 | return; | ||
1042 | |||
1043 | /* clip image in viewport in screen */ | ||
1044 | if (x < 0) | ||
1045 | { | ||
1046 | width += x; | ||
1047 | src_x -= x; | ||
1048 | x = 0; | ||
1049 | } | ||
1050 | if (y < 0) | ||
1051 | { | ||
1052 | height += y; | ||
1053 | src_y -= y; | ||
1054 | y = 0; | ||
1055 | } | ||
1056 | if (x + width > LCDM(WIDTH)) | ||
1057 | width = LCDM(WIDTH) - x; | ||
1058 | if (y + height > LCDM(HEIGHT)) | ||
1059 | height = LCDM(HEIGHT) - y; | ||
1060 | #endif | ||
1061 | |||
923 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 1062 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
924 | src_y &= 7; | 1063 | src_y &= 7; |
925 | y -= src_y; | 1064 | y -= src_y; |
diff --git a/firmware/drivers/lcd-charcell.c b/firmware/drivers/lcd-charcell.c index d02c5eeaad..9fabeb4a22 100644 --- a/firmware/drivers/lcd-charcell.c +++ b/firmware/drivers/lcd-charcell.c | |||
@@ -84,6 +84,28 @@ void lcd_set_viewport(struct viewport* vp) | |||
84 | current_vp = &default_vp; | 84 | current_vp = &default_vp; |
85 | else | 85 | else |
86 | current_vp = vp; | 86 | current_vp = vp; |
87 | |||
88 | #if defined(SIMULATOR) | ||
89 | /* Force the viewport to be within bounds. If this happens it should | ||
90 | * be considered an error - the viewport will not draw as it might be | ||
91 | * expected. | ||
92 | */ | ||
93 | if((unsigned) current_vp->x > (unsigned) LCD_WIDTH | ||
94 | || (unsigned) current_vp->y > (unsigned) LCD_HEIGHT | ||
95 | || current_vp->x + current_vp->width > LCD_WIDTH | ||
96 | || current_vp->y + current_vp->height > LCD_HEIGHT) | ||
97 | { | ||
98 | #if !defined(HAVE_VIEWPORT_CLIP) | ||
99 | DEBUGF("ERROR: " | ||
100 | #else | ||
101 | DEBUGF("NOTE: " | ||
102 | #endif | ||
103 | "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n", | ||
104 | current_vp->x, current_vp->y, | ||
105 | current_vp->width, current_vp->height); | ||
106 | } | ||
107 | |||
108 | #endif | ||
87 | } | 109 | } |
88 | 110 | ||
89 | void lcd_update_viewport(void) | 111 | void lcd_update_viewport(void) |
@@ -250,6 +272,11 @@ static void lcd_putxchar(int x, int y, int xchar) | |||
250 | x += current_vp->x; | 272 | x += current_vp->x; |
251 | y += current_vp->y; | 273 | y += current_vp->y; |
252 | 274 | ||
275 | #if defined(HAVE_VIEWPORT_CLIP) | ||
276 | if((unsigned)x > (unsigned)LCD_WIDTH || (unsigned)y > (unsigned)LCD_HEIGHT) | ||
277 | return; | ||
278 | #endif | ||
279 | |||
253 | lcd_char = lcd_charbuffer[y][x]; | 280 | lcd_char = lcd_charbuffer[y][x]; |
254 | 281 | ||
255 | if (lcd_char < lcd_pattern_count) /* old char was soft */ | 282 | if (lcd_char < lcd_pattern_count) /* old char was soft */ |
diff --git a/firmware/export/config-mrobe500.h b/firmware/export/config-mrobe500.h index 7b73fe7ad6..82ba8a8e83 100644 --- a/firmware/export/config-mrobe500.h +++ b/firmware/export/config-mrobe500.h | |||
@@ -65,6 +65,9 @@ | |||
65 | /* define this if the target has volume keys which can be used in the lists */ | 65 | /* define this if the target has volume keys which can be used in the lists */ |
66 | #define HAVE_VOLUME_IN_LIST | 66 | #define HAVE_VOLUME_IN_LIST |
67 | 67 | ||
68 | /* define this if you want viewport clipping enabled for safe LCD functions */ | ||
69 | #define HAVE_VIEWPORT_CLIP | ||
70 | |||
68 | /* LCD dimensions */ | 71 | /* LCD dimensions */ |
69 | #define CONFIG_LCD LCD_MROBE500 | 72 | #define CONFIG_LCD LCD_MROBE500 |
70 | 73 | ||