diff options
Diffstat (limited to 'firmware/drivers/lcd-h100.c')
-rw-r--r-- | firmware/drivers/lcd-h100.c | 355 |
1 files changed, 185 insertions, 170 deletions
diff --git a/firmware/drivers/lcd-h100.c b/firmware/drivers/lcd-h100.c index 15cb351195..616a8521b0 100644 --- a/firmware/drivers/lcd-h100.c +++ b/firmware/drivers/lcd-h100.c | |||
@@ -208,19 +208,19 @@ void lcd_init(void) | |||
208 | /*** update functions ***/ | 208 | /*** update functions ***/ |
209 | 209 | ||
210 | /* Performance function that works with an external buffer | 210 | /* Performance function that works with an external buffer |
211 | note that y and height are in 8-pixel units! */ | 211 | note that by and bheight are in 8-pixel units! */ |
212 | void lcd_blit(const unsigned char* p_data, int x, int y, int width, | 212 | void lcd_blit(const unsigned char* data, int x, int by, int width, |
213 | int height, int stride) | 213 | int bheight, int stride) |
214 | { | 214 | { |
215 | /* Copy display bitmap to hardware */ | 215 | /* Copy display bitmap to hardware */ |
216 | while (height--) | 216 | while (bheight--) |
217 | { | 217 | { |
218 | lcd_write_command_ex(LCD_CNTL_PAGE, y++ & 0xf, -1); | 218 | lcd_write_command_ex(LCD_CNTL_PAGE, by++ & 0xf, -1); |
219 | lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); | 219 | lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); |
220 | 220 | ||
221 | lcd_write_command(LCD_CNTL_DATA_WRITE); | 221 | lcd_write_command(LCD_CNTL_DATA_WRITE); |
222 | lcd_write_data(p_data, width); | 222 | lcd_write_data(data, width); |
223 | p_data += stride; | 223 | data += stride; |
224 | } | 224 | } |
225 | } | 225 | } |
226 | 226 | ||
@@ -245,16 +245,16 @@ void lcd_update(void) | |||
245 | 245 | ||
246 | /* Update a fraction of the display. */ | 246 | /* Update a fraction of the display. */ |
247 | void lcd_update_rect(int, int, int, int) __attribute__ ((section (".icode"))); | 247 | void lcd_update_rect(int, int, int, int) __attribute__ ((section (".icode"))); |
248 | void lcd_update_rect(int x_start, int y, int width, int height) | 248 | void lcd_update_rect(int x, int y, int width, int height) |
249 | { | 249 | { |
250 | int ymax; | 250 | int ymax; |
251 | 251 | ||
252 | /* The Y coordinates have to work on even 8 pixel rows */ | 252 | /* The Y coordinates have to work on even 8 pixel rows */ |
253 | ymax = (y + height-1)/8; | 253 | ymax = (y + height-1) >> 3; |
254 | y /= 8; | 254 | y >>= 3; |
255 | 255 | ||
256 | if(x_start + width > LCD_WIDTH) | 256 | if(x + width > LCD_WIDTH) |
257 | width = LCD_WIDTH - x_start; | 257 | width = LCD_WIDTH - x; |
258 | if (width <= 0) | 258 | if (width <= 0) |
259 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ | 259 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ |
260 | if(ymax >= LCD_HEIGHT/8) | 260 | if(ymax >= LCD_HEIGHT/8) |
@@ -264,10 +264,10 @@ void lcd_update_rect(int x_start, int y, int width, int height) | |||
264 | for (; y <= ymax; y++) | 264 | for (; y <= ymax; y++) |
265 | { | 265 | { |
266 | lcd_write_command_ex(LCD_CNTL_PAGE, y, -1); | 266 | lcd_write_command_ex(LCD_CNTL_PAGE, y, -1); |
267 | lcd_write_command_ex(LCD_CNTL_COLUMN, x_start, -1); | 267 | lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1); |
268 | 268 | ||
269 | lcd_write_command(LCD_CNTL_DATA_WRITE); | 269 | lcd_write_command(LCD_CNTL_DATA_WRITE); |
270 | lcd_write_data (&lcd_framebuffer[y][x_start], width); | 270 | lcd_write_data (&lcd_framebuffer[y][x], width); |
271 | } | 271 | } |
272 | } | 272 | } |
273 | #endif /* !SIMULATOR */ | 273 | #endif /* !SIMULATOR */ |
@@ -333,8 +333,10 @@ static void nopixel(int x, int y) | |||
333 | (void)y; | 333 | (void)y; |
334 | } | 334 | } |
335 | 335 | ||
336 | lcd_pixelfunc_type* pixelfunc[8] = {flippixel, nopixel, setpixel, setpixel, | 336 | lcd_pixelfunc_type* pixelfunc[8] = { |
337 | nopixel, clearpixel, nopixel, clearpixel}; | 337 | flippixel, nopixel, setpixel, setpixel, |
338 | nopixel, clearpixel, nopixel, clearpixel | ||
339 | }; | ||
338 | 340 | ||
339 | static void flipblock(unsigned char *address, unsigned mask, unsigned bits) | 341 | static void flipblock(unsigned char *address, unsigned mask, unsigned bits) |
340 | { | 342 | { |
@@ -356,7 +358,30 @@ static void solidblock(unsigned char *address, unsigned mask, unsigned bits) | |||
356 | *address = (*address & ~mask) | (bits & mask); | 358 | *address = (*address & ~mask) | (bits & mask); |
357 | } | 359 | } |
358 | 360 | ||
359 | lcd_blockfunc_type* blockfunc[4] = {flipblock, bgblock, fgblock, solidblock}; | 361 | static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) |
362 | { | ||
363 | *address ^= (~bits & mask); | ||
364 | } | ||
365 | |||
366 | static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
367 | { | ||
368 | *address &= ~(bits & mask); | ||
369 | } | ||
370 | |||
371 | static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
372 | { | ||
373 | *address |= (~bits & mask); | ||
374 | } | ||
375 | |||
376 | static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
377 | { | ||
378 | *address = (*address & ~mask) | (~bits & mask); | ||
379 | } | ||
380 | |||
381 | lcd_blockfunc_type* blockfunc[8] = { | ||
382 | flipblock, bgblock, fgblock, solidblock, | ||
383 | flipinvblock, bginvblock, fginvblock, solidinvblock | ||
384 | }; | ||
360 | 385 | ||
361 | /*** drawing functions ***/ | 386 | /*** drawing functions ***/ |
362 | 387 | ||
@@ -452,7 +477,7 @@ void lcd_hline(int x1, int x2, int y) | |||
452 | { | 477 | { |
453 | int x; | 478 | int x; |
454 | unsigned char *dst; | 479 | unsigned char *dst; |
455 | unsigned char mask, bits; | 480 | unsigned mask; |
456 | lcd_blockfunc_type *bfunc; | 481 | lcd_blockfunc_type *bfunc; |
457 | 482 | ||
458 | /* direction flip */ | 483 | /* direction flip */ |
@@ -473,13 +498,12 @@ void lcd_hline(int x1, int x2, int y) | |||
473 | if (x2 >= LCD_WIDTH) | 498 | if (x2 >= LCD_WIDTH) |
474 | x2 = LCD_WIDTH-1; | 499 | x2 = LCD_WIDTH-1; |
475 | 500 | ||
476 | bfunc = blockfunc[drawmode & ~DRMODE_INVERSEVID]; | 501 | bfunc = blockfunc[drawmode]; |
477 | bits = (drawmode & DRMODE_INVERSEVID) ? 0x00 : 0xFFu; | 502 | dst = &lcd_framebuffer[y>>3][x1]; |
478 | dst = &lcd_framebuffer[y/8][x1]; | ||
479 | mask = 1 << (y & 7); | 503 | mask = 1 << (y & 7); |
480 | 504 | ||
481 | for (x = x1; x <= x2; x++) | 505 | for (x = x1; x <= x2; x++) |
482 | bfunc(dst++, mask, bits); | 506 | bfunc(dst++, mask, 0xFFu); |
483 | } | 507 | } |
484 | 508 | ||
485 | /* Draw a vertical line (optimised) */ | 509 | /* Draw a vertical line (optimised) */ |
@@ -487,7 +511,7 @@ void lcd_vline(int x, int y1, int y2) | |||
487 | { | 511 | { |
488 | int ny; | 512 | int ny; |
489 | unsigned char *dst; | 513 | unsigned char *dst; |
490 | unsigned char mask_top, mask_bottom, bits; | 514 | unsigned mask, mask_bottom; |
491 | lcd_blockfunc_type *bfunc; | 515 | lcd_blockfunc_type *bfunc; |
492 | 516 | ||
493 | /* direction flip */ | 517 | /* direction flip */ |
@@ -508,28 +532,20 @@ void lcd_vline(int x, int y1, int y2) | |||
508 | if (y2 >= LCD_HEIGHT) | 532 | if (y2 >= LCD_HEIGHT) |
509 | y2 = LCD_HEIGHT-1; | 533 | y2 = LCD_HEIGHT-1; |
510 | 534 | ||
511 | bfunc = blockfunc[drawmode & ~DRMODE_INVERSEVID]; | 535 | bfunc = blockfunc[drawmode]; |
512 | bits = (drawmode & DRMODE_INVERSEVID) ? 0x00 : 0xFFu; | 536 | dst = &lcd_framebuffer[y1>>3][x]; |
513 | dst = &lcd_framebuffer[y1/8][x]; | ||
514 | ny = y2 - (y1 & ~7); | 537 | ny = y2 - (y1 & ~7); |
515 | mask_top = 0xFFu << (y1 & 7); | 538 | mask = 0xFFu << (y1 & 7); |
516 | mask_bottom = 0xFFu >> (7 - (ny & 7)); | 539 | mask_bottom = 0xFFu >> (7 - (ny & 7)); |
517 | 540 | ||
518 | if (ny >= 8) | 541 | for (; ny >= 8; ny -= 8) |
519 | { | 542 | { |
520 | bfunc(dst, mask_top, bits); | 543 | bfunc(dst, mask, 0xFFu); |
521 | dst += LCD_WIDTH; | 544 | dst += LCD_WIDTH; |
522 | 545 | mask = 0xFFu; | |
523 | for (; ny > 15; ny -= 8) | ||
524 | { | ||
525 | bfunc(dst, 0xFFu, bits); | ||
526 | dst += LCD_WIDTH; | ||
527 | } | ||
528 | } | 546 | } |
529 | else | 547 | mask_bottom &= mask; |
530 | mask_bottom &= mask_top; | 548 | bfunc(dst, mask_bottom, 0xFFu); |
531 | |||
532 | bfunc(dst, mask_bottom, bits); | ||
533 | } | 549 | } |
534 | 550 | ||
535 | /* Draw a rectangular box */ | 551 | /* Draw a rectangular box */ |
@@ -547,29 +563,19 @@ void lcd_drawrect(int x, int y, int width, int height) | |||
547 | lcd_hline(x, x2, y2); | 563 | lcd_hline(x, x2, y2); |
548 | } | 564 | } |
549 | 565 | ||
550 | /* helper function for lcd_fillrect() */ | ||
551 | static void fillrow(lcd_blockfunc_type *bfunc, unsigned char *address, | ||
552 | int width, unsigned mask, unsigned bits) | ||
553 | { | ||
554 | int i; | ||
555 | |||
556 | for (i = 0; i < width; i++) | ||
557 | bfunc(address++, mask, bits); | ||
558 | } | ||
559 | |||
560 | /* Fill a rectangular area */ | 566 | /* Fill a rectangular area */ |
561 | void lcd_fillrect(int x, int y, int width, int height) | 567 | void lcd_fillrect(int x, int y, int width, int height) |
562 | { | 568 | { |
563 | int ny; | 569 | int ny, i; |
564 | unsigned char *dst; | 570 | unsigned char *dst; |
565 | unsigned char mask_top, mask_bottom, bits; | 571 | unsigned mask, mask_bottom; |
572 | unsigned bits = 0xFFu; | ||
566 | lcd_blockfunc_type *bfunc; | 573 | lcd_blockfunc_type *bfunc; |
567 | bool fillopt = (drawmode & DRMODE_INVERSEVID) ? | 574 | bool fillopt; |
568 | (drawmode & DRMODE_BG) : (drawmode & DRMODE_FG); | ||
569 | 575 | ||
570 | /* nothing to draw? */ | 576 | /* nothing to draw? */ |
571 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 577 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) |
572 | || (x + width < 0) || (y + height < 0)) | 578 | || (x + width <= 0) || (y + height <= 0)) |
573 | return; | 579 | return; |
574 | 580 | ||
575 | /* clipping */ | 581 | /* clipping */ |
@@ -587,38 +593,41 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
587 | width = LCD_WIDTH - x; | 593 | width = LCD_WIDTH - x; |
588 | if (y + height > LCD_HEIGHT) | 594 | if (y + height > LCD_HEIGHT) |
589 | height = LCD_HEIGHT - y; | 595 | height = LCD_HEIGHT - y; |
590 | 596 | ||
591 | bfunc = blockfunc[drawmode & ~DRMODE_INVERSEVID]; | 597 | fillopt = (drawmode & DRMODE_INVERSEVID) ? |
592 | bits = (drawmode & DRMODE_INVERSEVID) ? 0x00 : 0xFFu; | 598 | (drawmode & DRMODE_BG) : (drawmode & DRMODE_FG); |
593 | dst = &lcd_framebuffer[y/8][x]; | 599 | if (fillopt &&(drawmode & DRMODE_INVERSEVID)) |
600 | bits = 0; | ||
601 | bfunc = blockfunc[drawmode]; | ||
602 | dst = &lcd_framebuffer[y>>3][x]; | ||
594 | ny = height - 1 + (y & 7); | 603 | ny = height - 1 + (y & 7); |
595 | mask_top = 0xFFu << (y & 7); | 604 | mask = 0xFFu << (y & 7); |
596 | mask_bottom = 0xFFu >> (7 - (ny & 7)); | 605 | mask_bottom = 0xFFu >> (7 - (ny & 7)); |
597 | 606 | ||
598 | if (ny >= 8) | 607 | for (; ny >= 8; ny -= 8) |
599 | { | 608 | { |
600 | if (fillopt && mask_top == 0xFF) | 609 | if (fillopt && (mask == 0xFFu)) |
601 | memset(dst, bits, width); | 610 | memset(dst, bits, width); |
602 | else | 611 | else |
603 | fillrow(bfunc, dst, width, mask_top, bits); | ||
604 | dst += LCD_WIDTH; | ||
605 | |||
606 | for (; ny > 15; ny -= 8) | ||
607 | { | 612 | { |
608 | if (fillopt) | 613 | unsigned char *dst_row = dst; |
609 | memset(dst, bits, width); | 614 | |
610 | else | 615 | for (i = width; i > 0; i--) |
611 | fillrow(bfunc, dst, width, 0xFFu, bits); | 616 | bfunc(dst_row++, mask, 0xFFu); |
612 | dst += LCD_WIDTH; | ||
613 | } | 617 | } |
618 | |||
619 | dst += LCD_WIDTH; | ||
620 | mask = 0xFFu; | ||
614 | } | 621 | } |
615 | else | 622 | mask_bottom &= mask; |
616 | mask_bottom &= mask_top; | 623 | |
617 | 624 | if (fillopt && (mask_bottom == 0xFFu)) | |
618 | if (fillopt && mask_bottom == 0xFF) | ||
619 | memset(dst, bits, width); | 625 | memset(dst, bits, width); |
620 | else | 626 | else |
621 | fillrow(bfunc, dst, width, mask_bottom, bits); | 627 | { |
628 | for (i = width; i > 0; i--) | ||
629 | bfunc(dst++, mask_bottom, 0xFFu); | ||
630 | } | ||
622 | } | 631 | } |
623 | 632 | ||
624 | /* About Rockbox' internal bitmap format: | 633 | /* About Rockbox' internal bitmap format: |
@@ -632,95 +641,120 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
632 | * | 641 | * |
633 | * This is the same as the internal lcd hw format. */ | 642 | * This is the same as the internal lcd hw format. */ |
634 | 643 | ||
635 | /* Draw a bitmap at (x, y), size (nx, ny) | 644 | /* Draw a partial bitmap */ |
636 | if 'clear' is true, clear destination area first */ | 645 | void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, |
637 | void lcd_bitmap(const unsigned char *src, int x, int y, int nx, int ny, | 646 | int stride, int x, int y, int width, int height) |
638 | bool clear) __attribute__ ((section (".icode"))); | 647 | __attribute__ ((section(".icode"))); |
639 | void lcd_bitmap(const unsigned char *src, int x, int y, int nx, int ny, | 648 | void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, |
640 | bool clear) | 649 | int stride, int x, int y, int width, int height) |
641 | { | 650 | { |
642 | const unsigned char *src_col; | 651 | int shift, ny, i; |
643 | unsigned char *dst, *dst_col; | 652 | unsigned char *dst; |
644 | unsigned int data, mask1, mask2, mask3, mask4; | 653 | unsigned mask, mask_bottom; |
645 | int stride, shift; | 654 | lcd_blockfunc_type *bfunc; |
646 | 655 | ||
647 | if (((unsigned) x >= LCD_WIDTH) || ((unsigned) y >= LCD_HEIGHT)) | 656 | /* nothing to draw? */ |
657 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
658 | || (x + width <= 0) || (y + height <= 0)) | ||
648 | return; | 659 | return; |
660 | |||
661 | /* clipping */ | ||
662 | if (x < 0) | ||
663 | { | ||
664 | width += x; | ||
665 | src_x -= x; | ||
666 | x = 0; | ||
667 | } | ||
668 | if (y < 0) | ||
669 | { | ||
670 | height += y; | ||
671 | src_y -= y; | ||
672 | y = 0; | ||
673 | } | ||
674 | if (x + width > LCD_WIDTH) | ||
675 | width = LCD_WIDTH - x; | ||
676 | if (y + height > LCD_HEIGHT) | ||
677 | height = LCD_HEIGHT - y; | ||
649 | 678 | ||
650 | stride = nx; /* otherwise right-clipping will destroy the image */ | 679 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
680 | src_y &= 7; | ||
681 | y -= src_y; | ||
682 | dst = &lcd_framebuffer[y>>3][x]; | ||
683 | shift = y & 7; | ||
684 | ny = height - 1 + shift + src_y; | ||
651 | 685 | ||
652 | if (((unsigned) (x + nx)) >= LCD_WIDTH) | 686 | bfunc = blockfunc[drawmode]; |
653 | nx = LCD_WIDTH - x; | 687 | mask = 0xFFu << (shift + src_y); |
654 | if (((unsigned) (y + ny)) >= LCD_HEIGHT) | 688 | mask_bottom = 0xFFu >> (7 - (ny & 7)); |
655 | ny = LCD_HEIGHT - y; | ||
656 | |||
657 | dst = &lcd_framebuffer[y >> 3][x]; | ||
658 | shift = y & 7; | ||
659 | 689 | ||
660 | if (!shift && clear) /* shortcut for byte aligned match with clear */ | 690 | if (shift == 0) |
661 | { | 691 | { |
662 | while (ny >= 8) /* all full rows */ | 692 | bool copyopt = (drawmode == DRMODE_SOLID); |
693 | |||
694 | for (; ny >= 8; ny -= 8) | ||
663 | { | 695 | { |
664 | memcpy(dst, src, nx); | 696 | if (copyopt && (mask == 0xFFu)) |
697 | memcpy(dst, src, width); | ||
698 | else | ||
699 | { | ||
700 | const unsigned char *src_row = src; | ||
701 | unsigned char *dst_row = dst; | ||
702 | |||
703 | for (i = width; i > 0; i--) | ||
704 | bfunc(dst_row++, mask, *src_row++); | ||
705 | } | ||
706 | |||
665 | src += stride; | 707 | src += stride; |
666 | dst += LCD_WIDTH; | 708 | dst += LCD_WIDTH; |
667 | ny -= 8; | 709 | mask = 0xFFu; |
668 | } | 710 | } |
669 | if (ny == 0) /* nothing left to do? */ | 711 | mask_bottom &= mask; |
670 | return; | ||
671 | /* last partial row to do by default routine */ | ||
672 | } | ||
673 | |||
674 | ny += shift; | ||
675 | 712 | ||
676 | /* Calculate bit masks */ | 713 | if (copyopt && (mask_bottom == 0xFFu)) |
677 | mask4 = ~(0xfe << ((ny-1) & 7)); /* data mask for last partial row */ | 714 | memcpy(dst, src, width); |
678 | if (clear) | 715 | else |
679 | { | 716 | { |
680 | mask1 = ~(0xff << shift); /* clearing of first partial row */ | 717 | for (i = width; i > 0; i--) |
681 | mask2 = 0; /* clearing of intermediate (full) rows */ | 718 | bfunc(dst++, mask_bottom, *src++); |
682 | mask3 = ~mask4; /* clearing of last partial row */ | 719 | } |
683 | if (ny <= 8) | ||
684 | mask3 |= mask1; | ||
685 | } | 720 | } |
686 | else | 721 | else |
687 | mask1 = mask2 = mask3 = 0xff; | ||
688 | |||
689 | /* Loop for each column */ | ||
690 | for (x = 0; x < nx; x++) | ||
691 | { | 722 | { |
692 | src_col = src++; | 723 | for (x = 0; x < width; x++) |
693 | dst_col = dst++; | ||
694 | data = 0; | ||
695 | y = 0; | ||
696 | |||
697 | if (ny > 8) | ||
698 | { | 724 | { |
699 | /* First partial row */ | 725 | const unsigned char *src_col = src++; |
700 | data = *src_col << shift; | 726 | unsigned char *dst_col = dst++; |
701 | *dst_col = (*dst_col & mask1) | data; | 727 | unsigned mask_col = mask; |
702 | src_col += stride; | 728 | unsigned data = 0; |
703 | dst_col += LCD_WIDTH; | 729 | |
704 | data >>= 8; | 730 | for (y = ny; y >= 8; y -= 8) |
705 | |||
706 | /* Intermediate rows */ | ||
707 | for (y = 8; y < ny-8; y += 8) | ||
708 | { | 731 | { |
709 | data |= *src_col << shift; | 732 | data |= *src_col << shift; |
710 | *dst_col = (*dst_col & mask2) | data; | 733 | |
734 | if (mask_col & 0xFFu) | ||
735 | { | ||
736 | bfunc(dst_col, mask_col, data); | ||
737 | mask_col = 0xFFu; | ||
738 | } | ||
739 | else | ||
740 | mask_col >>= 8; | ||
741 | |||
711 | src_col += stride; | 742 | src_col += stride; |
712 | dst_col += LCD_WIDTH; | 743 | dst_col += LCD_WIDTH; |
713 | data >>= 8; | 744 | data >>= 8; |
714 | } | 745 | } |
715 | } | ||
716 | |||
717 | /* Last partial row */ | ||
718 | if (y + shift < ny) | ||
719 | data |= *src_col << shift; | 746 | data |= *src_col << shift; |
720 | *dst_col = (*dst_col & mask3) | (data & mask4); | 747 | bfunc(dst_col, mask_col & mask_bottom, data); |
748 | } | ||
721 | } | 749 | } |
722 | } | 750 | } |
723 | 751 | ||
752 | /* Draw a full bitmap */ | ||
753 | void lcd_bitmap(const unsigned char *src, int x, int y, int width, int height) | ||
754 | { | ||
755 | lcd_bitmap_part(src, 0, 0, width, x, y, width, height); | ||
756 | } | ||
757 | |||
724 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | 758 | /* put a string at a given pixel position, skipping first ofs pixel columns */ |
725 | static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | 759 | static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) |
726 | { | 760 | { |
@@ -729,7 +763,8 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
729 | 763 | ||
730 | while ((ch = *str++) != '\0' && x < LCD_WIDTH) | 764 | while ((ch = *str++) != '\0' && x < LCD_WIDTH) |
731 | { | 765 | { |
732 | int gwidth, width; | 766 | int width; |
767 | const unsigned char *bits; | ||
733 | 768 | ||
734 | /* check input range */ | 769 | /* check input range */ |
735 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) | 770 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) |
@@ -737,40 +772,20 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
737 | ch -= pf->firstchar; | 772 | ch -= pf->firstchar; |
738 | 773 | ||
739 | /* get proportional width and glyph bits */ | 774 | /* get proportional width and glyph bits */ |
740 | gwidth = pf->width ? pf->width[ch] : pf->maxwidth; | 775 | width = pf->width ? pf->width[ch] : pf->maxwidth; |
741 | width = MIN (gwidth, LCD_WIDTH - x); | ||
742 | 776 | ||
743 | if (ofs != 0) | 777 | if (ofs > width) |
744 | { | 778 | { |
745 | if (ofs > width) | 779 | ofs -= width; |
746 | { | 780 | continue; |
747 | ofs -= width; | ||
748 | continue; | ||
749 | } | ||
750 | width -= ofs; | ||
751 | } | 781 | } |
782 | |||
783 | bits = pf->bits + (pf->offset ? | ||
784 | pf->offset[ch] : ((pf->height + 7) / 8 * pf->maxwidth * ch)); | ||
752 | 785 | ||
753 | if (width > 0) | 786 | lcd_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); |
754 | { | 787 | |
755 | unsigned int i; | 788 | x += width - ofs; |
756 | const unsigned char* bits = pf->bits + | ||
757 | (pf->offset ? pf->offset[ch] | ||
758 | : ((pf->height + 7) / 8 * pf->maxwidth * ch)); | ||
759 | |||
760 | if (ofs != 0) | ||
761 | { | ||
762 | for (i = 0; i < pf->height; i += 8) | ||
763 | { | ||
764 | lcd_bitmap (bits + ofs, x, y + i, width, | ||
765 | MIN(8, pf->height - i), true); | ||
766 | bits += gwidth; | ||
767 | } | ||
768 | } | ||
769 | else | ||
770 | lcd_bitmap ((unsigned char*) bits, x, y, gwidth, | ||
771 | pf->height, true); | ||
772 | x += width; | ||
773 | } | ||
774 | ofs = 0; | 789 | ofs = 0; |
775 | } | 790 | } |
776 | } | 791 | } |