diff options
author | Thomas Martitz <kugel@rockbox.org> | 2011-03-05 18:36:51 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2011-03-05 18:36:51 +0000 |
commit | 9edd6d4ee912273690b2600e8c52183dfa058eb9 (patch) | |
tree | cf6b0723f42c090022b94b38b3c4d856e9378d40 | |
parent | 396ddd9fd79e458d1107f4065ce072eef99b6bce (diff) | |
download | rockbox-9edd6d4ee912273690b2600e8c52183dfa058eb9.tar.gz rockbox-9edd6d4ee912273690b2600e8c52183dfa058eb9.zip |
Anti-Aliased Fonts support.
This enables Rockbox to render anti-aliased fonts using an alpha blending method.
The input font bitmaps are 4bit, i.e. 4x larger, but the metadata size stays the same.
A tool, convttf, for converting ttf fonts directly to the Rockbox fnt format is provided.
It has a useful help output, but the parameter that works best is -c1 or -c2 (2 for larger font sizes).
Flyspray: FS#8961
Author: Initial work by Jonas Hurrelmann, further work by Fred Bauer, Andrew Mahone, Teruaki Kawashima and myself.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29523 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/plugins/mpegplayer/mpegplayer.c | 174 | ||||
-rw-r--r-- | apps/plugins/rockpaint.c | 182 | ||||
-rw-r--r-- | firmware/drivers/lcd-16bit.c | 252 | ||||
-rw-r--r-- | firmware/drivers/lcd-bitmap-common.c | 10 | ||||
-rw-r--r-- | firmware/export/font.h | 3 | ||||
-rw-r--r-- | firmware/font.c | 31 | ||||
-rw-r--r-- | tools/Makefile | 9 | ||||
-rw-r--r-- | tools/convbdf.c | 15 | ||||
-rw-r--r-- | tools/convttf.c | 1283 | ||||
-rw-r--r-- | tools/root.make | 2 | ||||
-rw-r--r-- | tools/tools.make | 5 |
11 files changed, 1939 insertions, 27 deletions
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index 2361ba0fbd..22136d8393 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c | |||
@@ -663,6 +663,172 @@ static void draw_oriented_mono_bitmap_part(const unsigned char *src, | |||
663 | while (src < src_end); | 663 | while (src < src_end); |
664 | } | 664 | } |
665 | 665 | ||
666 | /* draw alpha bitmap for anti-alias font */ | ||
667 | #define ALPHA_COLOR_FONT_DEPTH 2 | ||
668 | #define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH) | ||
669 | #define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1) | ||
670 | #define ALPHA_COLOR_PIXEL_PER_BYTE (8 >> ALPHA_COLOR_FONT_DEPTH) | ||
671 | #define ALPHA_COLOR_PIXEL_PER_WORD (32 >> ALPHA_COLOR_FONT_DEPTH) | ||
672 | #ifdef CPU_ARM | ||
673 | #define BLEND_INIT do {} while (0) | ||
674 | #define BLEND_START(acc, color, alpha) \ | ||
675 | asm volatile("mul %0, %1, %2" : "=&r" (acc) : "r" (color), "r" (alpha)) | ||
676 | #define BLEND_CONT(acc, color, alpha) \ | ||
677 | asm volatile("mla %0, %1, %2, %0" : "+&r" (acc) : "r" (color), "r" (alpha)) | ||
678 | #define BLEND_OUT(acc) do {} while (0) | ||
679 | #elif defined(CPU_COLDFIRE) | ||
680 | #define ALPHA_BITMAP_READ_WORDS | ||
681 | #define BLEND_INIT coldfire_set_macsr(EMAC_UNSIGNED) | ||
682 | #define BLEND_START(acc, color, alpha) \ | ||
683 | asm volatile("mac.l %0, %1, %%acc0" :: "%d" (color), "d" (alpha)) | ||
684 | #define BLEND_CONT BLEND_START | ||
685 | #define BLEND_OUT(acc) asm volatile("movclr.l %%acc0, %0" : "=d" (acc)) | ||
686 | #else | ||
687 | #define BLEND_INIT do {} while (0) | ||
688 | #define BLEND_START(acc, color, alpha) ((acc) = (color) * (alpha)) | ||
689 | #define BLEND_CONT(acc, color, alpha) ((acc) += (color) * (alpha)) | ||
690 | #define BLEND_OUT(acc) do {} while (0) | ||
691 | #endif | ||
692 | |||
693 | /* Blend the given two colors */ | ||
694 | static inline unsigned blend_two_colors(unsigned c1, unsigned c2, unsigned a) | ||
695 | { | ||
696 | a += a >> (ALPHA_COLOR_LOOKUP_SHIFT - 1); | ||
697 | #if (LCD_PIXELFORMAT == RGB565SWAPPED) | ||
698 | c1 = swap16(c1); | ||
699 | c2 = swap16(c2); | ||
700 | #endif | ||
701 | unsigned c1l = (c1 | (c1 << 16)) & 0x07e0f81f; | ||
702 | unsigned c2l = (c2 | (c2 << 16)) & 0x07e0f81f; | ||
703 | unsigned p; | ||
704 | BLEND_START(p, c1l, a); | ||
705 | BLEND_CONT(p, c2l, ALPHA_COLOR_LOOKUP_SIZE + 1 - a); | ||
706 | BLEND_OUT(p); | ||
707 | p = (p >> ALPHA_COLOR_LOOKUP_SHIFT) & 0x07e0f81f; | ||
708 | p |= (p >> 16); | ||
709 | #if (LCD_PIXELFORMAT == RGB565SWAPPED) | ||
710 | return swap16(p); | ||
711 | #else | ||
712 | return p; | ||
713 | #endif | ||
714 | } | ||
715 | |||
716 | static void draw_oriented_alpha_bitmap_part(const unsigned char *src, | ||
717 | int src_x, int src_y, | ||
718 | int stride, int x, int y, | ||
719 | int width, int height) | ||
720 | { | ||
721 | fb_data *dst, *dst_start; | ||
722 | unsigned fg_pattern, bg_pattern; | ||
723 | |||
724 | if (x + width > SCREEN_WIDTH) | ||
725 | width = SCREEN_WIDTH - x; /* Clip right */ | ||
726 | if (x < 0) | ||
727 | width += x, x = 0; /* Clip left */ | ||
728 | if (width <= 0) | ||
729 | return; /* nothing left to do */ | ||
730 | |||
731 | if (y + height > SCREEN_HEIGHT) | ||
732 | height = SCREEN_HEIGHT - y; /* Clip bottom */ | ||
733 | if (y < 0) | ||
734 | height += y, y = 0; /* Clip top */ | ||
735 | if (height <= 0) | ||
736 | return; /* nothing left to do */ | ||
737 | |||
738 | /* initialize blending */ | ||
739 | BLEND_INIT; | ||
740 | |||
741 | fg_pattern = rb->lcd_get_foreground(); | ||
742 | bg_pattern = rb->lcd_get_background(); | ||
743 | |||
744 | dst_start = rb->lcd_framebuffer + (LCD_WIDTH - y - 1) + x*LCD_WIDTH; | ||
745 | int col, row = height; | ||
746 | unsigned data, pixels; | ||
747 | unsigned skip_end = (stride - width); | ||
748 | unsigned skip_start = src_y * stride + src_x; | ||
749 | |||
750 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
751 | uint32_t *src_w = (uint32_t *)((uintptr_t)src & ~3); | ||
752 | skip_start += ALPHA_COLOR_PIXEL_PER_BYTE * ((uintptr_t)src & 3); | ||
753 | src_w += skip_start / ALPHA_COLOR_PIXEL_PER_WORD; | ||
754 | data = letoh32(*src_w++); | ||
755 | #else | ||
756 | src += skip_start / ALPHA_COLOR_PIXEL_PER_BYTE; | ||
757 | data = *src; | ||
758 | #endif | ||
759 | pixels = skip_start % ALPHA_COLOR_PIXEL_PER_WORD; | ||
760 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
761 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
762 | pixels = 8 - pixels; | ||
763 | #endif | ||
764 | |||
765 | do | ||
766 | { | ||
767 | col = width; | ||
768 | dst = dst_start--; | ||
769 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
770 | #define UPDATE_SRC_ALPHA do { \ | ||
771 | if (--pixels) \ | ||
772 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
773 | else \ | ||
774 | { \ | ||
775 | data = letoh32(*src_w++); \ | ||
776 | pixels = ALPHA_COLOR_PIXEL_PER_WORD; \ | ||
777 | } \ | ||
778 | } while (0) | ||
779 | #elif ALPHA_COLOR_PIXEL_PER_BYTE == 2 | ||
780 | #define UPDATE_SRC_ALPHA do { \ | ||
781 | if (pixels ^= 1) \ | ||
782 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
783 | else \ | ||
784 | data = *(++src); \ | ||
785 | } while (0) | ||
786 | #else | ||
787 | #define UPDATE_SRC_ALPHA do { \ | ||
788 | if (pixels = (++pixels % ALPHA_COLOR_PIXEL_PER_BYTE)) \ | ||
789 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
790 | else \ | ||
791 | data = *(++src); \ | ||
792 | } while (0) | ||
793 | #endif | ||
794 | do | ||
795 | { | ||
796 | *dst=blend_two_colors(*dst, fg_pattern, | ||
797 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
798 | dst += LCD_WIDTH; | ||
799 | UPDATE_SRC_ALPHA; | ||
800 | } | ||
801 | while (--col); | ||
802 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
803 | if (skip_end < pixels) | ||
804 | { | ||
805 | pixels -= skip_end; | ||
806 | data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; | ||
807 | } else { | ||
808 | pixels = skip_end - pixels; | ||
809 | src_w += pixels / ALPHA_COLOR_PIXEL_PER_WORD; | ||
810 | pixels %= ALPHA_COLOR_PIXEL_PER_WORD; | ||
811 | data = letoh32(*src_w++); | ||
812 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
813 | pixels = 8 - pixels; | ||
814 | } | ||
815 | #else | ||
816 | if (skip_end) | ||
817 | { | ||
818 | pixels += skip_end; | ||
819 | if (pixels >= ALPHA_COLOR_PIXEL_PER_BYTE) | ||
820 | { | ||
821 | src += pixels / ALPHA_COLOR_PIXEL_PER_BYTE; | ||
822 | pixels %= ALPHA_COLOR_PIXEL_PER_BYTE; | ||
823 | data = *src; | ||
824 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
825 | } else | ||
826 | data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; | ||
827 | } | ||
828 | #endif | ||
829 | } while (--row); | ||
830 | } | ||
831 | |||
666 | static void draw_putsxy_oriented(int x, int y, const char *str) | 832 | static void draw_putsxy_oriented(int x, int y, const char *str) |
667 | { | 833 | { |
668 | unsigned short ch; | 834 | unsigned short ch; |
@@ -690,8 +856,12 @@ static void draw_putsxy_oriented(int x, int y, const char *str) | |||
690 | 856 | ||
691 | bits = rb->font_get_bits(pf, ch); | 857 | bits = rb->font_get_bits(pf, ch); |
692 | 858 | ||
693 | draw_oriented_mono_bitmap_part(bits, ofs, 0, width, x, y, | 859 | if (pf->depth) |
694 | width - ofs, pf->height); | 860 | draw_oriented_alpha_bitmap_part(bits, ofs, 0, width, x, y, |
861 | width - ofs, pf->height); | ||
862 | else | ||
863 | draw_oriented_mono_bitmap_part(bits, ofs, 0, width, x, y, | ||
864 | width - ofs, pf->height); | ||
695 | 865 | ||
696 | x += width - ofs; | 866 | x += width - ofs; |
697 | ofs = 0; | 867 | ofs = 0; |
diff --git a/apps/plugins/rockpaint.c b/apps/plugins/rockpaint.c index 0acbe41aaf..1fef0e9f5f 100644 --- a/apps/plugins/rockpaint.c +++ b/apps/plugins/rockpaint.c | |||
@@ -562,6 +562,180 @@ static void buffer_mono_bitmap_part( | |||
562 | } while( src < src_end ); | 562 | } while( src < src_end ); |
563 | } | 563 | } |
564 | 564 | ||
565 | /* draw alpha bitmap for anti-alias font */ | ||
566 | #define ALPHA_COLOR_FONT_DEPTH 2 | ||
567 | #define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH) | ||
568 | #define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1) | ||
569 | #define ALPHA_COLOR_PIXEL_PER_BYTE (8 >> ALPHA_COLOR_FONT_DEPTH) | ||
570 | #define ALPHA_COLOR_PIXEL_PER_WORD (32 >> ALPHA_COLOR_FONT_DEPTH) | ||
571 | #ifdef CPU_ARM | ||
572 | #define BLEND_INIT do {} while (0) | ||
573 | #define BLEND_START(acc, color, alpha) \ | ||
574 | asm volatile("mul %0, %1, %2" : "=&r" (acc) : "r" (color), "r" (alpha)) | ||
575 | #define BLEND_CONT(acc, color, alpha) \ | ||
576 | asm volatile("mla %0, %1, %2, %0" : "+&r" (acc) : "r" (color), "r" (alpha)) | ||
577 | #define BLEND_OUT(acc) do {} while (0) | ||
578 | #elif defined(CPU_COLDFIRE) | ||
579 | #define ALPHA_BITMAP_READ_WORDS | ||
580 | #define BLEND_INIT coldfire_set_macsr(EMAC_UNSIGNED) | ||
581 | #define BLEND_START(acc, color, alpha) \ | ||
582 | asm volatile("mac.l %0, %1, %%acc0" :: "%d" (color), "d" (alpha)) | ||
583 | #define BLEND_CONT BLEND_START | ||
584 | #define BLEND_OUT(acc) asm volatile("movclr.l %%acc0, %0" : "=d" (acc)) | ||
585 | #else | ||
586 | #define BLEND_INIT do {} while (0) | ||
587 | #define BLEND_START(acc, color, alpha) ((acc) = (color) * (alpha)) | ||
588 | #define BLEND_CONT(acc, color, alpha) ((acc) += (color) * (alpha)) | ||
589 | #define BLEND_OUT(acc) do {} while (0) | ||
590 | #endif | ||
591 | |||
592 | /* Blend the given two colors */ | ||
593 | static inline unsigned blend_two_colors(unsigned c1, unsigned c2, unsigned a) | ||
594 | { | ||
595 | a += a >> (ALPHA_COLOR_LOOKUP_SHIFT - 1); | ||
596 | #if (LCD_PIXELFORMAT == RGB565SWAPPED) | ||
597 | c1 = swap16(c1); | ||
598 | c2 = swap16(c2); | ||
599 | #endif | ||
600 | unsigned c1l = (c1 | (c1 << 16)) & 0x07e0f81f; | ||
601 | unsigned c2l = (c2 | (c2 << 16)) & 0x07e0f81f; | ||
602 | unsigned p; | ||
603 | BLEND_START(p, c1l, a); | ||
604 | BLEND_CONT(p, c2l, ALPHA_COLOR_LOOKUP_SIZE + 1 - a); | ||
605 | BLEND_OUT(p); | ||
606 | p = (p >> ALPHA_COLOR_LOOKUP_SHIFT) & 0x07e0f81f; | ||
607 | p |= (p >> 16); | ||
608 | #if (LCD_PIXELFORMAT == RGB565SWAPPED) | ||
609 | return swap16(p); | ||
610 | #else | ||
611 | return p; | ||
612 | #endif | ||
613 | } | ||
614 | |||
615 | static void buffer_alpha_bitmap_part( | ||
616 | fb_data *buf, int buf_width, int buf_height, | ||
617 | const unsigned char *src, int src_x, int src_y, | ||
618 | int stride, int x, int y, int width, int height ) | ||
619 | { | ||
620 | fb_data *dst; | ||
621 | unsigned fg_pattern = rb->lcd_get_foreground(); | ||
622 | |||
623 | /* nothing to draw? */ | ||
624 | if ((width <= 0) || (height <= 0) || (x >= buf_width) || | ||
625 | (y >= buf_height) || (x + width <= 0) || (y + height <= 0)) | ||
626 | return; | ||
627 | |||
628 | /* initialize blending */ | ||
629 | BLEND_INIT; | ||
630 | |||
631 | /* clipping */ | ||
632 | if (x < 0) | ||
633 | { | ||
634 | width += x; | ||
635 | src_x -= x; | ||
636 | x = 0; | ||
637 | } | ||
638 | if (y < 0) | ||
639 | { | ||
640 | height += y; | ||
641 | src_y -= y; | ||
642 | y = 0; | ||
643 | } | ||
644 | if (x + width > buf_width) | ||
645 | width = buf_width - x; | ||
646 | if (y + height > buf_height) | ||
647 | height = buf_height - y; | ||
648 | |||
649 | dst = buf + y*buf_width + x; | ||
650 | |||
651 | int col, row = height; | ||
652 | unsigned data, pixels; | ||
653 | unsigned skip_end = (stride - width); | ||
654 | unsigned skip_start = src_y * stride + src_x; | ||
655 | |||
656 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
657 | uint32_t *src_w = (uint32_t *)((uintptr_t)src & ~3); | ||
658 | skip_start += ALPHA_COLOR_PIXEL_PER_BYTE * ((uintptr_t)src & 3); | ||
659 | src_w += skip_start / ALPHA_COLOR_PIXEL_PER_WORD; | ||
660 | data = letoh32(*src_w++); | ||
661 | #else | ||
662 | src += skip_start / ALPHA_COLOR_PIXEL_PER_BYTE; | ||
663 | data = *src; | ||
664 | #endif | ||
665 | pixels = skip_start % ALPHA_COLOR_PIXEL_PER_WORD; | ||
666 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
667 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
668 | pixels = 8 - pixels; | ||
669 | #endif | ||
670 | |||
671 | do | ||
672 | { | ||
673 | col = width; | ||
674 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
675 | #define UPDATE_SRC_ALPHA do { \ | ||
676 | if (--pixels) \ | ||
677 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
678 | else \ | ||
679 | { \ | ||
680 | data = letoh32(*src_w++); \ | ||
681 | pixels = ALPHA_COLOR_PIXEL_PER_WORD; \ | ||
682 | } \ | ||
683 | } while (0) | ||
684 | #elif ALPHA_COLOR_PIXEL_PER_BYTE == 2 | ||
685 | #define UPDATE_SRC_ALPHA do { \ | ||
686 | if (pixels ^= 1) \ | ||
687 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
688 | else \ | ||
689 | data = *(++src); \ | ||
690 | } while (0) | ||
691 | #else | ||
692 | #define UPDATE_SRC_ALPHA do { \ | ||
693 | if (pixels = (++pixels % ALPHA_COLOR_PIXEL_PER_BYTE)) \ | ||
694 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
695 | else \ | ||
696 | data = *(++src); \ | ||
697 | } while (0) | ||
698 | #endif | ||
699 | |||
700 | do | ||
701 | { | ||
702 | *dst=blend_two_colors(*dst, fg_pattern, | ||
703 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
704 | dst++; | ||
705 | UPDATE_SRC_ALPHA; | ||
706 | } | ||
707 | while (--col); | ||
708 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
709 | if (skip_end < pixels) | ||
710 | { | ||
711 | pixels -= skip_end; | ||
712 | data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; | ||
713 | } else { | ||
714 | pixels = skip_end - pixels; | ||
715 | src_w += pixels / ALPHA_COLOR_PIXEL_PER_WORD; | ||
716 | pixels %= ALPHA_COLOR_PIXEL_PER_WORD; | ||
717 | data = letoh32(*src_w++); | ||
718 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
719 | pixels = 8 - pixels; | ||
720 | } | ||
721 | #else | ||
722 | if (skip_end) | ||
723 | { | ||
724 | pixels += skip_end; | ||
725 | if (pixels >= ALPHA_COLOR_PIXEL_PER_BYTE) | ||
726 | { | ||
727 | src += pixels / ALPHA_COLOR_PIXEL_PER_BYTE; | ||
728 | pixels %= ALPHA_COLOR_PIXEL_PER_BYTE; | ||
729 | data = *src; | ||
730 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
731 | } else | ||
732 | data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; | ||
733 | } | ||
734 | #endif | ||
735 | dst += LCD_WIDTH - width; | ||
736 | } while (--row); | ||
737 | } | ||
738 | |||
565 | static void buffer_putsxyofs( fb_data *buf, int buf_width, int buf_height, | 739 | static void buffer_putsxyofs( fb_data *buf, int buf_width, int buf_height, |
566 | int x, int y, int ofs, const unsigned char *str ) | 740 | int x, int y, int ofs, const unsigned char *str ) |
567 | { | 741 | { |
@@ -589,8 +763,12 @@ static void buffer_putsxyofs( fb_data *buf, int buf_width, int buf_height, | |||
589 | 763 | ||
590 | bits = rb->font_get_bits( pf, ch ); | 764 | bits = rb->font_get_bits( pf, ch ); |
591 | 765 | ||
592 | buffer_mono_bitmap_part( buf, buf_width, buf_height, bits, ofs, 0, | 766 | if (pf->depth) |
593 | width, x, y, width - ofs, pf->height); | 767 | buffer_alpha_bitmap_part( buf, buf_width, buf_height, bits, ofs, 0, |
768 | width, x, y, width - ofs, pf->height); | ||
769 | else | ||
770 | buffer_mono_bitmap_part( buf, buf_width, buf_height, bits, ofs, 0, | ||
771 | width, x, y, width - ofs, pf->height); | ||
594 | 772 | ||
595 | x += width - ofs; | 773 | x += width - ofs; |
596 | ofs = 0; | 774 | ofs = 0; |
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index be4f21f412..a2eb3e630c 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c | |||
@@ -901,6 +901,258 @@ void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int heig | |||
901 | lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height); | 901 | lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height); |
902 | } | 902 | } |
903 | 903 | ||
904 | /* draw alpha bitmap for anti-alias font */ | ||
905 | #define ALPHA_COLOR_FONT_DEPTH 2 | ||
906 | #define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH) | ||
907 | #define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1) | ||
908 | #define ALPHA_COLOR_PIXEL_PER_BYTE (8 >> ALPHA_COLOR_FONT_DEPTH) | ||
909 | #define ALPHA_COLOR_PIXEL_PER_WORD (32 >> ALPHA_COLOR_FONT_DEPTH) | ||
910 | #ifdef CPU_ARM | ||
911 | #define BLEND_INIT do {} while (0) | ||
912 | #define BLEND_START(acc, color, alpha) \ | ||
913 | asm volatile("mul %0, %1, %2" : "=&r" (acc) : "r" (color), "r" (alpha)) | ||
914 | #define BLEND_CONT(acc, color, alpha) \ | ||
915 | asm volatile("mla %0, %1, %2, %0" : "+&r" (acc) : "r" (color), "r" (alpha)) | ||
916 | #define BLEND_OUT(acc) do {} while (0) | ||
917 | #elif defined(CPU_COLDFIRE) | ||
918 | #define ALPHA_BITMAP_READ_WORDS | ||
919 | #define BLEND_INIT coldfire_set_macsr(EMAC_UNSIGNED) | ||
920 | #define BLEND_START(acc, color, alpha) \ | ||
921 | asm volatile("mac.l %0, %1, %%acc0" :: "%d" (color), "d" (alpha)) | ||
922 | #define BLEND_CONT BLEND_START | ||
923 | #define BLEND_OUT(acc) asm volatile("movclr.l %%acc0, %0" : "=d" (acc)) | ||
924 | #else | ||
925 | #define BLEND_INIT do {} while (0) | ||
926 | #define BLEND_START(acc, color, alpha) ((acc) = (color) * (alpha)) | ||
927 | #define BLEND_CONT(acc, color, alpha) ((acc) += (color) * (alpha)) | ||
928 | #define BLEND_OUT(acc) do {} while (0) | ||
929 | #endif | ||
930 | |||
931 | /* Blend the given two colors */ | ||
932 | static inline unsigned blend_two_colors(unsigned c1, unsigned c2, unsigned a) | ||
933 | { | ||
934 | a += a >> (ALPHA_COLOR_LOOKUP_SHIFT - 1); | ||
935 | #if (LCD_PIXELFORMAT == RGB565SWAPPED) | ||
936 | c1 = swap16(c1); | ||
937 | c2 = swap16(c2); | ||
938 | #endif | ||
939 | unsigned c1l = (c1 | (c1 << 16)) & 0x07e0f81f; | ||
940 | unsigned c2l = (c2 | (c2 << 16)) & 0x07e0f81f; | ||
941 | unsigned p; | ||
942 | BLEND_START(p, c1l, a); | ||
943 | BLEND_CONT(p, c2l, ALPHA_COLOR_LOOKUP_SIZE + 1 - a); | ||
944 | BLEND_OUT(p); | ||
945 | p = (p >> ALPHA_COLOR_LOOKUP_SHIFT) & 0x07e0f81f; | ||
946 | p |= (p >> 16); | ||
947 | #if (LCD_PIXELFORMAT == RGB565SWAPPED) | ||
948 | return swap16(p); | ||
949 | #else | ||
950 | return p; | ||
951 | #endif | ||
952 | } | ||
953 | |||
954 | /* Blend the given color with the value from the alpha_color_lookup table */ | ||
955 | static inline unsigned blend_color(unsigned c, unsigned a) | ||
956 | { | ||
957 | return blend_two_colors(c, current_vp->fg_pattern, a); | ||
958 | } | ||
959 | |||
960 | void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x, | ||
961 | int src_y, int stride, int x, int y, | ||
962 | int width, int height) | ||
963 | { | ||
964 | fb_data *dst, *backdrop; | ||
965 | unsigned dmask = 0x00000000; | ||
966 | int drmode = current_vp->drawmode; | ||
967 | /* nothing to draw? */ | ||
968 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | ||
969 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | ||
970 | return; | ||
971 | /* initialize blending */ | ||
972 | BLEND_INIT; | ||
973 | |||
974 | /* clipping */ | ||
975 | if (x < 0) | ||
976 | { | ||
977 | width += x; | ||
978 | src_x -= x; | ||
979 | x = 0; | ||
980 | } | ||
981 | if (y < 0) | ||
982 | { | ||
983 | height += y; | ||
984 | src_y -= y; | ||
985 | y = 0; | ||
986 | } | ||
987 | if (x + width > current_vp->width) | ||
988 | width = current_vp->width - x; | ||
989 | if (y + height > current_vp->height) | ||
990 | height = current_vp->height - y; | ||
991 | |||
992 | if (drmode & DRMODE_INVERSEVID) | ||
993 | { | ||
994 | dmask = 0xffffffff; | ||
995 | drmode &= DRMODE_SOLID; /* mask out inversevid */ | ||
996 | } | ||
997 | if (drmode == DRMODE_BG) | ||
998 | { | ||
999 | dmask = ~dmask; | ||
1000 | } | ||
1001 | |||
1002 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | ||
1003 | |||
1004 | int col, row = height; | ||
1005 | unsigned data, pixels; | ||
1006 | unsigned skip_end = (stride - width); | ||
1007 | unsigned skip_start = src_y * stride + src_x; | ||
1008 | |||
1009 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
1010 | uint32_t *src_w = (uint32_t *)((uintptr_t)src & ~3); | ||
1011 | skip_start += ALPHA_COLOR_PIXEL_PER_BYTE * ((uintptr_t)src & 3); | ||
1012 | src_w += skip_start / ALPHA_COLOR_PIXEL_PER_WORD; | ||
1013 | data = letoh32(*src_w++) ^ dmask; | ||
1014 | pixels = skip_start % ALPHA_COLOR_PIXEL_PER_WORD; | ||
1015 | #else | ||
1016 | src += skip_start / ALPHA_COLOR_PIXEL_PER_BYTE; | ||
1017 | data = *src ^ dmask; | ||
1018 | pixels = skip_start % ALPHA_COLOR_PIXEL_PER_BYTE; | ||
1019 | #endif | ||
1020 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
1021 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
1022 | pixels = 8 - pixels; | ||
1023 | #endif | ||
1024 | |||
1025 | do | ||
1026 | { | ||
1027 | col = width; | ||
1028 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
1029 | #define UPDATE_SRC_ALPHA do { \ | ||
1030 | if (--pixels) \ | ||
1031 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
1032 | else \ | ||
1033 | { \ | ||
1034 | data = letoh32(*src_w++) ^ dmask; \ | ||
1035 | pixels = ALPHA_COLOR_PIXEL_PER_WORD; \ | ||
1036 | } \ | ||
1037 | } while (0) | ||
1038 | #elif ALPHA_COLOR_PIXEL_PER_BYTE == 2 | ||
1039 | #define UPDATE_SRC_ALPHA do { \ | ||
1040 | if (pixels ^= 1) \ | ||
1041 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
1042 | else \ | ||
1043 | data = *(++src) ^ dmask; \ | ||
1044 | } while (0) | ||
1045 | #else | ||
1046 | #define UPDATE_SRC_ALPHA do { \ | ||
1047 | if (pixels = (++pixels % ALPHA_COLOR_PIXEL_PER_BYTE)) \ | ||
1048 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
1049 | else \ | ||
1050 | data = *(++src) ^ dmask; \ | ||
1051 | } while (0) | ||
1052 | #endif | ||
1053 | /* we don't want to have this in our inner | ||
1054 | * loop and the codesize increase is minimal */ | ||
1055 | switch (drmode) | ||
1056 | { | ||
1057 | case DRMODE_COMPLEMENT: | ||
1058 | do | ||
1059 | { | ||
1060 | *dst=blend_two_colors(*dst, ~(*dst), | ||
1061 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1062 | dst++; | ||
1063 | UPDATE_SRC_ALPHA; | ||
1064 | } | ||
1065 | while (--col); | ||
1066 | break; | ||
1067 | case DRMODE_BG: | ||
1068 | if(lcd_backdrop) | ||
1069 | { | ||
1070 | backdrop = (fb_data *)((long)dst+lcd_backdrop_offset); | ||
1071 | do | ||
1072 | { | ||
1073 | *dst=blend_two_colors(*dst, *(backdrop++), | ||
1074 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1075 | dst++; | ||
1076 | UPDATE_SRC_ALPHA; | ||
1077 | } | ||
1078 | while (--col); | ||
1079 | } | ||
1080 | else | ||
1081 | { | ||
1082 | do | ||
1083 | { | ||
1084 | *dst=blend_two_colors(*dst, current_vp->bg_pattern, | ||
1085 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1086 | dst++; | ||
1087 | UPDATE_SRC_ALPHA; | ||
1088 | } | ||
1089 | while (--col); | ||
1090 | } | ||
1091 | break; | ||
1092 | case DRMODE_FG: | ||
1093 | do | ||
1094 | { | ||
1095 | *dst=blend_color(*dst, data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1096 | dst++; | ||
1097 | UPDATE_SRC_ALPHA; | ||
1098 | } | ||
1099 | while (--col); | ||
1100 | break; | ||
1101 | case DRMODE_SOLID: | ||
1102 | if(lcd_backdrop) | ||
1103 | { | ||
1104 | backdrop = (fb_data *)((long)dst+lcd_backdrop_offset); | ||
1105 | do | ||
1106 | { | ||
1107 | *(dst++)=blend_color(*(backdrop++), | ||
1108 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1109 | UPDATE_SRC_ALPHA; | ||
1110 | } | ||
1111 | while (--col); | ||
1112 | } | ||
1113 | else | ||
1114 | { | ||
1115 | do | ||
1116 | { | ||
1117 | *(dst++)=blend_color(current_vp->bg_pattern, | ||
1118 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1119 | UPDATE_SRC_ALPHA; | ||
1120 | } | ||
1121 | while (--col); | ||
1122 | } | ||
1123 | break; | ||
1124 | } | ||
1125 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
1126 | if (skip_end < pixels) | ||
1127 | { | ||
1128 | pixels -= skip_end; | ||
1129 | data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; | ||
1130 | } else { | ||
1131 | pixels = skip_end - pixels; | ||
1132 | src_w += pixels / ALPHA_COLOR_PIXEL_PER_WORD; | ||
1133 | pixels %= ALPHA_COLOR_PIXEL_PER_WORD; | ||
1134 | data = letoh32(*src_w++) ^ dmask; | ||
1135 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
1136 | pixels = 8 - pixels; | ||
1137 | } | ||
1138 | #else | ||
1139 | if (skip_end) | ||
1140 | { | ||
1141 | pixels += skip_end; | ||
1142 | if (pixels >= ALPHA_COLOR_PIXEL_PER_BYTE) | ||
1143 | { | ||
1144 | src += pixels / ALPHA_COLOR_PIXEL_PER_BYTE; | ||
1145 | pixels %= ALPHA_COLOR_PIXEL_PER_BYTE; | ||
1146 | data = *src ^ dmask; | ||
1147 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
1148 | } else | ||
1149 | data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; | ||
1150 | } | ||
1151 | #endif | ||
1152 | dst += LCD_WIDTH - width; | ||
1153 | } while (--row); | ||
1154 | } | ||
1155 | |||
904 | /* Draw a partial native bitmap */ | 1156 | /* Draw a partial native bitmap */ |
905 | void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | 1157 | void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, |
906 | int stride, int x, int y, int width, | 1158 | int stride, int x, int y, int width, |
diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c index 364fb3c527..fc84fdd6a1 100644 --- a/firmware/drivers/lcd-bitmap-common.c +++ b/firmware/drivers/lcd-bitmap-common.c | |||
@@ -203,9 +203,15 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) | |||
203 | } | 203 | } |
204 | 204 | ||
205 | bits = font_get_bits(pf, *ucs); | 205 | bits = font_get_bits(pf, *ucs); |
206 | LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x + base_ofs, y, | ||
207 | width - ofs, pf->height); | ||
208 | 206 | ||
207 | #if defined(MAIN_LCD) && defined(HAVE_LCD_COLOR) | ||
208 | if (pf->depth) | ||
209 | lcd_alpha_bitmap_part(bits, ofs, 0, width, x + base_ofs, y, | ||
210 | width - ofs, pf->height); | ||
211 | else | ||
212 | #endif | ||
213 | LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x + base_ofs, | ||
214 | y, width - ofs, pf->height); | ||
209 | if (is_diac) | 215 | if (is_diac) |
210 | { | 216 | { |
211 | current_vp->drawmode = drawmode; | 217 | current_vp->drawmode = drawmode; |
diff --git a/firmware/export/font.h b/firmware/export/font.h index 0a75768fa5..a85f95e6ae 100644 --- a/firmware/export/font.h +++ b/firmware/export/font.h | |||
@@ -68,7 +68,7 @@ enum { | |||
68 | * USHORT maxwidth 2 font max width in pixels | 68 | * USHORT maxwidth 2 font max width in pixels |
69 | * USHORT height 2 font height in pixels | 69 | * USHORT height 2 font height in pixels |
70 | * USHORT ascent 2 font ascent (baseline) in pixels | 70 | * USHORT ascent 2 font ascent (baseline) in pixels |
71 | * USHORT pad 2 unused, pad to 32-bit boundary | 71 | * USHORT depth 2 depth of the font, 0=1bit and 1=4bit |
72 | * ULONG firstchar 4 first character code in font | 72 | * ULONG firstchar 4 first character code in font |
73 | * ULONG defaultchar 4 default character code in font | 73 | * ULONG defaultchar 4 default character code in font |
74 | * ULONG size 4 # characters in font | 74 | * ULONG size 4 # characters in font |
@@ -92,6 +92,7 @@ struct font { | |||
92 | int ascent; /* ascent (baseline) height*/ | 92 | int ascent; /* ascent (baseline) height*/ |
93 | int firstchar; /* first character in bitmap*/ | 93 | int firstchar; /* first character in bitmap*/ |
94 | int size; /* font size in glyphs*/ | 94 | int size; /* font size in glyphs*/ |
95 | int depth; /* depth of the font, 0=1bit and 1=4bit */ | ||
95 | const unsigned char *bits; /* 8-bit column bitmap data*/ | 96 | const unsigned char *bits; /* 8-bit column bitmap data*/ |
96 | const void *offset; /* offsets into bitmap data, | 97 | const void *offset; /* offsets into bitmap data, |
97 | uint16_t if bits_size < 0xFFDB else uint32_t*/ | 98 | uint16_t if bits_size < 0xFFDB else uint32_t*/ |
diff --git a/firmware/font.c b/firmware/font.c index 45ddef3afe..0f9f453ae2 100644 --- a/firmware/font.c +++ b/firmware/font.c | |||
@@ -89,7 +89,7 @@ static struct font* sysfonts[MAXFONTS] = { &sysfont, &font_ui, NULL}; | |||
89 | 89 | ||
90 | 90 | ||
91 | /* Font cache structures */ | 91 | /* Font cache structures */ |
92 | static void cache_create(struct font* pf, int maxwidth, int height); | 92 | static void cache_create(struct font* pf); |
93 | static void glyph_cache_load(struct font* pf); | 93 | static void glyph_cache_load(struct font* pf); |
94 | /* End Font cache structures */ | 94 | /* End Font cache structures */ |
95 | 95 | ||
@@ -132,6 +132,13 @@ static int32_t readlong(struct font *pf) | |||
132 | return l; | 132 | return l; |
133 | } | 133 | } |
134 | 134 | ||
135 | static int glyph_bytes( struct font *pf, int width ) | ||
136 | { | ||
137 | return pf->depth ? | ||
138 | (pf->height * width + 1) / 2: | ||
139 | width * ((pf->height + 7) / 8); | ||
140 | } | ||
141 | |||
135 | void font_reset(struct font *pf) | 142 | void font_reset(struct font *pf) |
136 | { | 143 | { |
137 | unsigned char* buffer = NULL; | 144 | unsigned char* buffer = NULL; |
@@ -168,7 +175,7 @@ static struct font* font_load_header(struct font *pf) | |||
168 | pf->maxwidth = readshort(pf); | 175 | pf->maxwidth = readshort(pf); |
169 | pf->height = readshort(pf); | 176 | pf->height = readshort(pf); |
170 | pf->ascent = readshort(pf); | 177 | pf->ascent = readshort(pf); |
171 | pf->buffer_position += 2; /* Skip padding */ | 178 | pf->depth = readshort(pf); |
172 | pf->firstchar = readlong(pf); | 179 | pf->firstchar = readlong(pf); |
173 | pf->defaultchar = readlong(pf); | 180 | pf->defaultchar = readlong(pf); |
174 | pf->size = readlong(pf); | 181 | pf->size = readlong(pf); |
@@ -308,7 +315,7 @@ static struct font* font_load_cached(struct font* pf) | |||
308 | pf->buffer_position = oldfileptr; | 315 | pf->buffer_position = oldfileptr; |
309 | 316 | ||
310 | /* Create the cache */ | 317 | /* Create the cache */ |
311 | cache_create(pf, pf->maxwidth, pf->height); | 318 | cache_create(pf); |
312 | 319 | ||
313 | return pf; | 320 | return pf; |
314 | } | 321 | } |
@@ -436,7 +443,8 @@ int font_load(struct font* pf, const char *path) | |||
436 | { | 443 | { |
437 | /* currently, font loading replaces earlier font allocation*/ | 444 | /* currently, font loading replaces earlier font allocation*/ |
438 | buffer = (unsigned char *)(((intptr_t)main_buf + 3) & ~3); | 445 | buffer = (unsigned char *)(((intptr_t)main_buf + 3) & ~3); |
439 | buffer_size = MAX_FONT_SIZE; | 446 | /* make sure above doesn't exceed */ |
447 | buffer_size = MAX_FONT_SIZE-3; | ||
440 | } | 448 | } |
441 | else | 449 | else |
442 | { | 450 | { |
@@ -516,24 +524,23 @@ load_cache_entry(struct font_cache_entry* p, void* callback_data) | |||
516 | } | 524 | } |
517 | else | 525 | else |
518 | { | 526 | { |
519 | bitmap_offset = ((pf->height + 7) / 8) * p->width * char_code; | 527 | bitmap_offset = char_code * glyph_bytes(pf, p->width); |
520 | } | 528 | } |
521 | 529 | ||
522 | int32_t file_offset = FONT_HEADER_SIZE + bitmap_offset; | 530 | int32_t file_offset = FONT_HEADER_SIZE + bitmap_offset; |
523 | lseek(pf->fd, file_offset, SEEK_SET); | 531 | lseek(pf->fd, file_offset, SEEK_SET); |
524 | 532 | int src_bytes = glyph_bytes(pf, p->width); | |
525 | int src_bytes = p->width * ((pf->height + 7) / 8); | ||
526 | read(pf->fd, p->bitmap, src_bytes); | 533 | read(pf->fd, p->bitmap, src_bytes); |
527 | } | 534 | } |
528 | 535 | ||
529 | /* | 536 | /* |
530 | * Converts cbuf into a font cache | 537 | * Converts cbuf into a font cache |
531 | */ | 538 | */ |
532 | static void cache_create(struct font* pf, int maxwidth, int height) | 539 | static void cache_create(struct font* pf) |
533 | { | 540 | { |
534 | /* maximum size of rotated bitmap */ | 541 | /* maximum size of rotated bitmap */ |
535 | int bitmap_size = maxwidth * ((height + 7) / 8); | 542 | int bitmap_size = glyph_bytes( pf, pf->maxwidth); |
536 | 543 | ||
537 | /* Initialise cache */ | 544 | /* Initialise cache */ |
538 | font_cache_create(&pf->cache, pf->buffer_start, pf->buffer_size, bitmap_size); | 545 | font_cache_create(&pf->cache, pf->buffer_start, pf->buffer_size, bitmap_size); |
539 | } | 546 | } |
@@ -578,7 +585,7 @@ const unsigned char* font_get_bits(struct font* pf, unsigned short char_code) | |||
578 | bits += ((uint32_t*)(pf->offset))[char_code]; | 585 | bits += ((uint32_t*)(pf->offset))[char_code]; |
579 | } | 586 | } |
580 | else | 587 | else |
581 | bits += ((pf->height + 7) / 8) * pf->maxwidth * char_code; | 588 | bits += char_code * glyph_bytes(pf, pf->maxwidth); |
582 | } | 589 | } |
583 | 590 | ||
584 | return bits; | 591 | return bits; |
@@ -655,7 +662,7 @@ int font_glyphs_to_bufsize(const char *path, int glyphs) | |||
655 | 662 | ||
656 | bufsize = LRU_SLOT_OVERHEAD + sizeof(struct font_cache_entry) + | 663 | bufsize = LRU_SLOT_OVERHEAD + sizeof(struct font_cache_entry) + |
657 | sizeof( unsigned short); | 664 | sizeof( unsigned short); |
658 | bufsize += f.maxwidth * ((f.height + 7) / 8); | 665 | bufsize += glyph_bytes(&f, f.maxwidth); |
659 | bufsize *= glyphs; | 666 | bufsize *= glyphs; |
660 | if ( bufsize < FONT_HEADER_SIZE ) | 667 | if ( bufsize < FONT_HEADER_SIZE ) |
661 | bufsize = FONT_HEADER_SIZE; | 668 | bufsize = FONT_HEADER_SIZE; |
diff --git a/tools/Makefile b/tools/Makefile index 0a69dde5da..c33d152c41 100644 --- a/tools/Makefile +++ b/tools/Makefile | |||
@@ -13,10 +13,10 @@ LDFLAGS := -g | |||
13 | 13 | ||
14 | CLEANALL := scramble descramble iriver sh2d bmp2rb rdf2binary convbdf \ | 14 | CLEANALL := scramble descramble iriver sh2d bmp2rb rdf2binary convbdf \ |
15 | generate_rocklatin mkboot ipod_fw codepages uclpack mi4 gigabeat lngdump \ | 15 | generate_rocklatin mkboot ipod_fw codepages uclpack mi4 gigabeat lngdump \ |
16 | telechips gigabeats creative hmac-sha1 rbspeexenc mkzenboot mk500boot | 16 | telechips gigabeats creative hmac-sha1 rbspeexenc mkzenboot mk500boot convttf |
17 | 17 | ||
18 | all: scramble descramble sh2d rdf2binary mkboot mkzenboot convbdf codepages \ | 18 | all: scramble descramble sh2d rdf2binary mkboot mkzenboot convbdf codepages \ |
19 | uclpack rbspeexenc voicefont mk500boot | 19 | uclpack rbspeexenc voicefont mk500boot convttf |
20 | 20 | ||
21 | scramble: scramble.o iriver.o mi4.o gigabeat.o gigabeats.o telechips.o \ | 21 | scramble: scramble.o iriver.o mi4.o gigabeat.o gigabeats.o telechips.o \ |
22 | iaudio_bl_flash.o creative.o hmac-sha1.o | 22 | iaudio_bl_flash.o creative.o hmac-sha1.o |
@@ -97,6 +97,11 @@ voicefont: voicefont.c | |||
97 | usb_benchmark: usb_benchmark.c | 97 | usb_benchmark: usb_benchmark.c |
98 | $(SILENT)$(CC) $(CFLAGS) -lusb $+ -o $@ | 98 | $(SILENT)$(CC) $(CFLAGS) -lusb $+ -o $@ |
99 | 99 | ||
100 | convttf: convttf.c | ||
101 | $(call PRINTS,CC $(@F)) | ||
102 | $(SILENT)$(CC) $(CFLAGS) -lm -std=c99 -O2 -Wall -g $+ -o $@ \ | ||
103 | `freetype-config --libs` `freetype-config --cflags` | ||
104 | |||
100 | clean: | 105 | clean: |
101 | @echo "Cleaning tools" | 106 | @echo "Cleaning tools" |
102 | $(SILENT)rm -f $(CLEANALL) $(shell for f in $(CLEANALL) ; do \ | 107 | $(SILENT)rm -f $(CLEANALL) $(shell for f in $(CLEANALL) ; do \ |
diff --git a/tools/convbdf.c b/tools/convbdf.c index 5a563220fd..671312e66b 100644 --- a/tools/convbdf.c +++ b/tools/convbdf.c | |||
@@ -46,6 +46,7 @@ struct font { | |||
46 | int ascent; /* ascent (baseline) height */ | 46 | int ascent; /* ascent (baseline) height */ |
47 | int firstchar; /* first character in bitmap */ | 47 | int firstchar; /* first character in bitmap */ |
48 | int size; /* font size in glyphs ('holes' included) */ | 48 | int size; /* font size in glyphs ('holes' included) */ |
49 | int depth; /* depth of the font, 0=1bit 1=4bit */ | ||
49 | bitmap_t* bits; /* 16-bit right-padded bitmap data */ | 50 | bitmap_t* bits; /* 16-bit right-padded bitmap data */ |
50 | int* offset; /* offsets into bitmap data */ | 51 | int* offset; /* offsets into bitmap data */ |
51 | unsigned char* width; /* character widths or NULL if fixed */ | 52 | unsigned char* width; /* character widths or NULL if fixed */ |
@@ -1220,6 +1221,7 @@ int gen_c_source(struct font* pf, char *path) | |||
1220 | " size: %d\n" | 1221 | " size: %d\n" |
1221 | " ascent: %d\n" | 1222 | " ascent: %d\n" |
1222 | " descent: %d\n" | 1223 | " descent: %d\n" |
1224 | " depth: %d\n" | ||
1223 | " first char: %d (0x%02x)\n" | 1225 | " first char: %d (0x%02x)\n" |
1224 | " last char: %d (0x%02x)\n" | 1226 | " last char: %d (0x%02x)\n" |
1225 | " default char: %d (0x%02x)\n" | 1227 | " default char: %d (0x%02x)\n" |
@@ -1245,7 +1247,7 @@ int gen_c_source(struct font* pf, char *path) | |||
1245 | pf->facename? pf->facename: "", | 1247 | pf->facename? pf->facename: "", |
1246 | pf->maxwidth, pf->height, | 1248 | pf->maxwidth, pf->height, |
1247 | pf->size, | 1249 | pf->size, |
1248 | pf->ascent, pf->descent, | 1250 | pf->ascent, pf->descent, pf->depth, |
1249 | pf->firstchar, pf->firstchar, | 1251 | pf->firstchar, pf->firstchar, |
1250 | pf->firstchar+pf->size-1, pf->firstchar+pf->size-1, | 1252 | pf->firstchar+pf->size-1, pf->firstchar+pf->size-1, |
1251 | pf->defaultchar, pf->defaultchar, | 1253 | pf->defaultchar, pf->defaultchar, |
@@ -1392,6 +1394,7 @@ int gen_c_source(struct font* pf, char *path) | |||
1392 | " %d, /* ascent */\n" | 1394 | " %d, /* ascent */\n" |
1393 | " %d, /* firstchar */\n" | 1395 | " %d, /* firstchar */\n" |
1394 | " %d, /* size */\n" | 1396 | " %d, /* size */\n" |
1397 | " %d, /* depth */\n" | ||
1395 | " _font_bits, /* bits */\n" | 1398 | " _font_bits, /* bits */\n" |
1396 | " %s /* offset */\n" | 1399 | " %s /* offset */\n" |
1397 | " %s\n" | 1400 | " %s\n" |
@@ -1411,7 +1414,7 @@ int gen_c_source(struct font* pf, char *path) | |||
1411 | pf->maxwidth, pf->height, | 1414 | pf->maxwidth, pf->height, |
1412 | pf->ascent, | 1415 | pf->ascent, |
1413 | pf->firstchar, | 1416 | pf->firstchar, |
1414 | pf->size, | 1417 | pf->size, 0, |
1415 | obuf, | 1418 | obuf, |
1416 | buf, | 1419 | buf, |
1417 | pf->defaultchar, | 1420 | pf->defaultchar, |
@@ -1436,7 +1439,8 @@ int gen_h_header(struct font* pf, char *path) | |||
1436 | "#define SYSFONT_WIDTH %d\n" | 1439 | "#define SYSFONT_WIDTH %d\n" |
1437 | "#define SYSFONT_HEIGHT %d\n" | 1440 | "#define SYSFONT_HEIGHT %d\n" |
1438 | "#define SYSFONT_SIZE %d\n" | 1441 | "#define SYSFONT_SIZE %d\n" |
1439 | "#define SYSFONT_ASCENT %d\n"; | 1442 | "#define SYSFONT_ASCENT %d\n" |
1443 | "#define SYSFONT_DEPTH %d\n"; | ||
1440 | char *hdr2 = | 1444 | char *hdr2 = |
1441 | "#define SYSFONT_DESCENT %d\n" | 1445 | "#define SYSFONT_DESCENT %d\n" |
1442 | "#define SYSFONT_FIRST_CHAR %d\n" | 1446 | "#define SYSFONT_FIRST_CHAR %d\n" |
@@ -1463,7 +1467,8 @@ int gen_h_header(struct font* pf, char *path) | |||
1463 | pf->maxwidth, | 1467 | pf->maxwidth, |
1464 | pf->height, | 1468 | pf->height, |
1465 | pf->size, | 1469 | pf->size, |
1466 | pf->ascent); | 1470 | pf->ascent, |
1471 | pf->depth); | ||
1467 | 1472 | ||
1468 | fprintf(ofp, hdr2, | 1473 | fprintf(ofp, hdr2, |
1469 | pf->descent, | 1474 | pf->descent, |
@@ -1546,7 +1551,7 @@ int gen_fnt_file(struct font* pf, char *path) | |||
1546 | writeshort(ofp, pf->maxwidth); | 1551 | writeshort(ofp, pf->maxwidth); |
1547 | writeshort(ofp, pf->height); | 1552 | writeshort(ofp, pf->height); |
1548 | writeshort(ofp, pf->ascent); | 1553 | writeshort(ofp, pf->ascent); |
1549 | writeshort(ofp, 0); | 1554 | writeshort(ofp, 0); /* depth = 0 for bdffonts */ |
1550 | writeint(ofp, pf->firstchar); | 1555 | writeint(ofp, pf->firstchar); |
1551 | writeint(ofp, pf->defaultchar); | 1556 | writeint(ofp, pf->defaultchar); |
1552 | writeint(ofp, pf->size); | 1557 | writeint(ofp, pf->size); |
diff --git a/tools/convttf.c b/tools/convttf.c new file mode 100644 index 0000000000..ca9e4fbb4d --- /dev/null +++ b/tools/convttf.c | |||
@@ -0,0 +1,1283 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 Jonas Hurrelmann | ||
11 | * | ||
12 | * A command-line tool to convert ttf file to bitmap fonts | ||
13 | * | ||
14 | * All files in this archive are subject to the GNU General Public License. | ||
15 | * See the file COPYING in the source tree root for full license agreement. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include <ft2build.h> | ||
22 | #include FT_FREETYPE_H | ||
23 | #include FT_GLYPH_H | ||
24 | |||
25 | #include <stdbool.h> | ||
26 | #include <stdio.h> | ||
27 | #ifdef WIN32 | ||
28 | #include <windows.h> | ||
29 | #else | ||
30 | #include <stdlib.h> | ||
31 | #include <unistd.h> | ||
32 | #endif | ||
33 | #include FT_SFNT_NAMES_H | ||
34 | #include FT_TRUETYPE_TABLES_H | ||
35 | |||
36 | #include <string.h> | ||
37 | /* | ||
38 | * Set the default values used to generate a BDF font. | ||
39 | */ | ||
40 | #ifndef DEFAULT_PLATFORM_ID | ||
41 | #define DEFAULT_PLATFORM_ID 3 | ||
42 | #endif | ||
43 | |||
44 | #ifndef DEFAULT_ENCODING_ID | ||
45 | #define DEFAULT_ENCODING_ID 1 | ||
46 | #endif | ||
47 | |||
48 | #define ABS(x) (((x) < 0) ? -(x) : (x)) | ||
49 | |||
50 | #define VERSION "RB12" | ||
51 | /* | ||
52 | * nameID macros for getting strings from the OT font. | ||
53 | */ | ||
54 | enum { | ||
55 | BDFOTF_COPYRIGHT_STRING = 0, | ||
56 | BDFOTF_FAMILY_STRING, | ||
57 | BDFOTF_SUBFAMILY_STRING, | ||
58 | BDFOTF_UNIQUEID_STRING, | ||
59 | BDFOTF_FULLNAME_STRING, | ||
60 | BDFOTF_VENDOR_STRING, | ||
61 | BDFOTF_POSTSCRIPT_STRING, | ||
62 | BDFOTF_TRADEMARK_STRING, | ||
63 | }; | ||
64 | /* | ||
65 | * String names for the string indexes. Used for error messages. | ||
66 | */ | ||
67 | static char *string_names[] = { | ||
68 | "\"Copyright\"", | ||
69 | "\"Family\"", | ||
70 | "\"SubFamily\"", | ||
71 | "\"Unique ID\"", | ||
72 | "\"Full Name\"", | ||
73 | "\"Vendor\"", | ||
74 | "\"Postscript Name\"", | ||
75 | "\"Trademark\"" | ||
76 | }; | ||
77 | |||
78 | |||
79 | /* | ||
80 | * The default platform and encoding ID's. | ||
81 | */ | ||
82 | static int pid = DEFAULT_PLATFORM_ID; | ||
83 | static int eid = DEFAULT_ENCODING_ID; | ||
84 | |||
85 | |||
86 | /* | ||
87 | * A flag indicating if a CMap was found or not. | ||
88 | */ | ||
89 | static FT_UShort nocmap; | ||
90 | |||
91 | int pct = 0; /* display ttc table if it is not zero. */ | ||
92 | unsigned long max_char = 65535; | ||
93 | int pixel_size = 15; | ||
94 | unsigned long start_char = 0; | ||
95 | unsigned long limit_char; | ||
96 | unsigned long firstchar = 0; | ||
97 | unsigned long lastchar; | ||
98 | FT_Long ttc_index = -1; | ||
99 | int flg_all_ttc = 0; | ||
100 | short antialias = 1; /* smooth fonts with gray levels */ | ||
101 | int oflag = 0; | ||
102 | char outfile[1024]; | ||
103 | float between_chr = 0.0f; | ||
104 | float between_row = 0.0f; | ||
105 | int hv_resolution = 60; | ||
106 | int dump_glyphs = 0; | ||
107 | int trimming = 0; | ||
108 | int trim_dp = 0; /* trim descent percent */ | ||
109 | int trim_da = 0; /* trim descnet actual */ | ||
110 | int trim_ap = 0; /* trim ascent precent */ | ||
111 | int trim_aa = 0; /* trim ascent actual */ | ||
112 | |||
113 | struct font_header_struct { | ||
114 | char header[4]; /* magic number and version bytes */ | ||
115 | unsigned short maxwidth; /* max width in pixels */ | ||
116 | unsigned short height; /* height in pixels */ | ||
117 | unsigned short ascent; /* ascent (baseline) height */ | ||
118 | unsigned short depth; /* depth 0=1-bit, 1=4-bit */ | ||
119 | unsigned long firstchar; /* first character in font */ | ||
120 | unsigned long defaultchar; /* default character in font */ | ||
121 | unsigned long size; /* # characters in font */ | ||
122 | unsigned long nbits; /* # bytes imagebits data in file */ /* = bits_size */ | ||
123 | |||
124 | FT_Long noffset; /* # longs offset data in file */ | ||
125 | FT_Long nwidth; /* # bytes width data in file */ | ||
126 | }; | ||
127 | |||
128 | struct font_struct { | ||
129 | struct font_header_struct header; | ||
130 | unsigned char *chars_data; | ||
131 | unsigned short *offset; | ||
132 | FT_Long *offset_long; | ||
133 | unsigned char *width; | ||
134 | }; | ||
135 | |||
136 | struct ttc_table{ | ||
137 | FT_Long ttc_count; | ||
138 | char **ttf_name; | ||
139 | }; | ||
140 | |||
141 | /* exit the program with given message */ | ||
142 | static void | ||
143 | panic( const char* message) | ||
144 | { | ||
145 | fprintf( stderr, "%s\n", message ); | ||
146 | exit( 1 ); | ||
147 | } | ||
148 | |||
149 | static void | ||
150 | arg_panic( const char* message, const char* arg ) | ||
151 | { | ||
152 | fprintf( stderr, "%s: %s\n", message, arg ); | ||
153 | exit( 1 ); | ||
154 | } | ||
155 | |||
156 | static int writebyte(FILE *fp, unsigned char c) | ||
157 | { | ||
158 | return putc(c, fp) != EOF; | ||
159 | } | ||
160 | |||
161 | static int writeshort(FILE *fp, unsigned short s) | ||
162 | { | ||
163 | putc(s, fp); | ||
164 | return putc(s>>8, fp) != EOF; | ||
165 | } | ||
166 | |||
167 | static int writeint(FILE *fp, unsigned int l) | ||
168 | { | ||
169 | putc(l, fp); | ||
170 | putc(l>>8, fp); | ||
171 | putc(l>>16, fp); | ||
172 | return putc(l>>24, fp) != EOF; | ||
173 | } | ||
174 | |||
175 | static int writestr(FILE *fp, char *str, int count) | ||
176 | { | ||
177 | return (int)fwrite(str, 1, count, fp) == count; | ||
178 | } | ||
179 | |||
180 | /* print usage information */ | ||
181 | void usage(void) | ||
182 | { | ||
183 | char help[] = { | ||
184 | "Usage: convttf [options] [input-files]\n" | ||
185 | " convttf [options] [-o output-file] [single-input-file]\n\n" | ||
186 | " Default output-file : <font-size>-<basename>.fnt.\n" | ||
187 | " When '-ta' or '-tc' is specified in command line,\n " | ||
188 | " default output-file is: \n" | ||
189 | " <font-size>-<internal postscript-name of input-file>.fnt.\n" | ||
190 | "Options:\n" | ||
191 | " -s N Start output at character encodings >= N\n" | ||
192 | " -l N Limit output to character encodings <= N\n" | ||
193 | " -p N Font size N in pixel (default N=15)\n" | ||
194 | " -c N Character separation in pixel.Insert space between lines.\n" | ||
195 | " -x Trim glyphs horizontally of nearly empty space\n" | ||
196 | " (to improve spacing on V's W's, etc.)\n" | ||
197 | " -X Set the horizontal and vertical resolution (default: 60)\n" | ||
198 | " -TA N Trim vertical ascent (N percent)\n" | ||
199 | " -TD N Trim vertical descent (N percent)\n" | ||
200 | " -Ta N Trim vertical ascent (N pixels)\n" | ||
201 | " -Td N Trim vertical descent (N pixels)\n" | ||
202 | " -r N Row separation in pixel.Insert space between characters\n" | ||
203 | " -d Debug: print converted glyph images\n" | ||
204 | " -tt Display the True Type Collection tables available in the font\n" | ||
205 | " -t N Index of true type collection. It must be start from 0.(default N=0).\n" | ||
206 | " -ta Convert all fonts in ttc (ignores outfile option)\n" | ||
207 | }; | ||
208 | fprintf(stderr, "%s", help); | ||
209 | exit( 1 ); | ||
210 | } | ||
211 | |||
212 | /* remove directory prefix and file suffix from full path*/ | ||
213 | char *basename(char *path) | ||
214 | { | ||
215 | char *p, *b; | ||
216 | static char base[256]; | ||
217 | |||
218 | /* remove prepended path and extension*/ | ||
219 | b = path; | ||
220 | for (p=path; *p; ++p) { | ||
221 | if (*p == '/') | ||
222 | b = p + 1; | ||
223 | } | ||
224 | strcpy(base, b); | ||
225 | for (p=base; *p; ++p) { | ||
226 | if (*p == '.') { | ||
227 | *p = 0; | ||
228 | break; | ||
229 | } | ||
230 | } | ||
231 | return base; | ||
232 | } | ||
233 | |||
234 | |||
235 | void setcharmap(FT_Face face) | ||
236 | { | ||
237 | FT_Long i; | ||
238 | |||
239 | /* | ||
240 | * Get the requested cmap. | ||
241 | */ | ||
242 | for (i = 0; i < face->num_charmaps; i++) { | ||
243 | if (face->charmaps[i]->platform_id == pid && | ||
244 | face->charmaps[i]->encoding_id == eid) | ||
245 | break; | ||
246 | } | ||
247 | |||
248 | if (i == face->num_charmaps && pid == 3 && eid == 1) { | ||
249 | /* | ||
250 | * Make a special case when this fails with pid == 3 and eid == 1. | ||
251 | * Change to eid == 0 and try again. This captures the two possible | ||
252 | * cases for MS fonts. Some other method should be used to cycle | ||
253 | * through all the alternatives later. | ||
254 | */ | ||
255 | for (i = 0; i < face->num_charmaps; i++) { | ||
256 | if (face->charmaps[i]->platform_id == pid && | ||
257 | face->charmaps[i]->encoding_id == 0) | ||
258 | break; | ||
259 | } | ||
260 | if (i < face->num_charmaps) { | ||
261 | pid = 3; | ||
262 | eid = 1; | ||
263 | FT_Set_Charmap(face, face->charmaps[i]); | ||
264 | } else { | ||
265 | /* | ||
266 | * No CMAP was found. | ||
267 | */ | ||
268 | nocmap = 1; | ||
269 | pid = eid = -1; | ||
270 | } | ||
271 | } else { | ||
272 | FT_Set_Charmap(face, face->charmaps[i]); | ||
273 | nocmap = 0; | ||
274 | } | ||
275 | |||
276 | } | ||
277 | |||
278 | /* | ||
279 | * quote in otf2bdf. | ||
280 | * A generic routine to get a name from the OT name table. This routine | ||
281 | * always looks for English language names and checks three possibilities: | ||
282 | * 1. English names with the MS Unicode encoding ID. | ||
283 | * 2. English names with the MS unknown encoding ID. | ||
284 | * 3. English names with the Apple Unicode encoding ID. | ||
285 | * | ||
286 | * The particular name ID mut be provided (e.g. nameID = 0 for copyright | ||
287 | * string, nameID = 6 for Postscript name, nameID = 1 for typeface name. | ||
288 | * | ||
289 | * If the `dash_to_space' flag is non-zero, all dashes (-) in the name will be | ||
290 | * replaced with the character passed. | ||
291 | * | ||
292 | * Returns the number of bytes added. | ||
293 | */ | ||
294 | static int | ||
295 | otf_get_english_string(FT_Face face, int nameID, int dash_to_space, | ||
296 | char *name, int name_size) | ||
297 | { | ||
298 | |||
299 | int j, encid; | ||
300 | FT_UInt i, nrec; | ||
301 | FT_SfntName sfntName; | ||
302 | unsigned char *s; | ||
303 | unsigned short slen; | ||
304 | |||
305 | nrec = FT_Get_Sfnt_Name_Count(face); | ||
306 | |||
307 | for (encid = 1, j = 0; j < 2; j++, encid--) { | ||
308 | /* | ||
309 | * Locate one of the MS English font names. | ||
310 | */ | ||
311 | for (i = 0; i < nrec; i++) { | ||
312 | FT_Get_Sfnt_Name(face, i, &sfntName); | ||
313 | if (sfntName.platform_id == 3 && | ||
314 | sfntName.encoding_id == encid && | ||
315 | sfntName.name_id == nameID && | ||
316 | (sfntName.language_id == 0x0409 || | ||
317 | sfntName.language_id == 0x0809 || | ||
318 | sfntName.language_id == 0x0c09 || | ||
319 | sfntName.language_id == 0x1009 || | ||
320 | sfntName.language_id == 0x1409 || | ||
321 | sfntName.language_id == 0x1809)) { | ||
322 | s = sfntName.string; | ||
323 | slen = sfntName.string_len; | ||
324 | break; | ||
325 | } | ||
326 | } | ||
327 | |||
328 | if (i < nrec) { | ||
329 | if (slen >> 1 >= name_size) { | ||
330 | fprintf(stderr, "warning: %s string longer than buffer." | ||
331 | "Truncating to %d bytes.\n", string_names[nameID], name_size); | ||
332 | slen = name_size << 1; | ||
333 | } | ||
334 | |||
335 | /* | ||
336 | * Found one of the MS English font names. The name is by | ||
337 | * definition encoded in Unicode, so copy every second byte into | ||
338 | * the `name' parameter, assuming there is enough space. | ||
339 | */ | ||
340 | for (i = 1; i < slen; i += 2) { | ||
341 | if (dash_to_space) | ||
342 | *name++ = (s[i] != '-') ? s[i] : ' '; | ||
343 | else if (s[i] == '\r' || s[i] == '\n') { | ||
344 | if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n') | ||
345 | i += 2; | ||
346 | *name++ = ' '; | ||
347 | *name++ = ' '; | ||
348 | } else | ||
349 | *name++ = s[i]; | ||
350 | } | ||
351 | *name = 0; | ||
352 | return (slen >> 1); | ||
353 | } | ||
354 | } | ||
355 | |||
356 | /* | ||
357 | * No MS English name found, attempt to find an Apple Unicode English | ||
358 | * name. | ||
359 | */ | ||
360 | for (i = 0; i < nrec; i++) { | ||
361 | FT_Get_Sfnt_Name(face, i, &sfntName); | ||
362 | if (sfntName.platform_id == 0 && sfntName.language_id == 0 && | ||
363 | sfntName.name_id == nameID) { | ||
364 | s = sfntName.string; | ||
365 | slen = sfntName.string_len; | ||
366 | break; | ||
367 | } | ||
368 | } | ||
369 | |||
370 | if (i < nrec) { | ||
371 | if (slen >> 1 >= name_size) { | ||
372 | fprintf(stderr, "warning: %s string longer than buffer." | ||
373 | "Truncating to %d bytes.\n", string_names[nameID], name_size); | ||
374 | slen = name_size << 1; | ||
375 | } | ||
376 | |||
377 | /* | ||
378 | * Found the Apple Unicode English name. The name is by definition | ||
379 | * encoded in Unicode, so copy every second byte into the `name' | ||
380 | * parameter, assuming there is enough space. | ||
381 | */ | ||
382 | for (i = 1; i < slen; i += 2) { | ||
383 | if (dash_to_space) | ||
384 | *name++ = (s[i] != '-') ? s[i] : ' '; | ||
385 | else if (s[i] == '\r' || s[i] == '\n') { | ||
386 | if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n') | ||
387 | i += 2; | ||
388 | *name++ = ' '; | ||
389 | *name++ = ' '; | ||
390 | } else | ||
391 | *name++ = s[i]; | ||
392 | } | ||
393 | *name = 0; | ||
394 | return (slen >> 1); | ||
395 | } | ||
396 | |||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | |||
401 | int get_ttc_table(char *path, struct ttc_table *ttcname ) | ||
402 | { | ||
403 | |||
404 | |||
405 | FT_Error error; | ||
406 | FT_Library library; | ||
407 | FT_Face face; | ||
408 | FT_Long i; | ||
409 | char xlfd[BUFSIZ]; | ||
410 | |||
411 | /* init number of ttf in ttc */ | ||
412 | ttcname->ttc_count = 0; | ||
413 | |||
414 | /* Initialize engine */ | ||
415 | if ( ( error = FT_Init_FreeType( &library ) ) != 0 ) | ||
416 | { | ||
417 | panic( "Error while initializing engine" ); | ||
418 | return error; | ||
419 | } | ||
420 | |||
421 | |||
422 | /* Load face */ | ||
423 | error = FT_New_Face( library, path, (FT_Long) 0, &face ); | ||
424 | if ( error ) | ||
425 | { | ||
426 | arg_panic( "Could not find/open font", path ); | ||
427 | return error; | ||
428 | } | ||
429 | |||
430 | ttcname->ttc_count = face->num_faces; | ||
431 | ttcname->ttf_name = malloc( sizeof(char*) * ttcname->ttc_count); | ||
432 | |||
433 | for(i = 0; i < ttcname->ttc_count; i++) | ||
434 | { | ||
435 | error = FT_New_Face( library, path, i, &face ); | ||
436 | if ( error == FT_Err_Cannot_Open_Stream ) | ||
437 | arg_panic( "Could not find/open font", path ); | ||
438 | otf_get_english_string(face, BDFOTF_POSTSCRIPT_STRING, 0, xlfd, | ||
439 | sizeof(xlfd)); | ||
440 | ttcname->ttf_name[i] = malloc(sizeof(char) * (strlen(xlfd) + 1 )); | ||
441 | strcpy(ttcname->ttf_name[i], xlfd); | ||
442 | } | ||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | void print_ttc_table(char* path) | ||
447 | { | ||
448 | struct ttc_table ttcname; | ||
449 | FT_Long i; | ||
450 | |||
451 | get_ttc_table(path, &ttcname); | ||
452 | printf("ttc header count = %ld \n\n", ttcname.ttc_count); | ||
453 | printf("Encoding tables available in the true type collection\n\n"); | ||
454 | printf("INDEX\tPOSTSCRIPT NAME\n"); | ||
455 | printf("-----------------------------------------------------\n"); | ||
456 | for(i = 0; i < ttcname.ttc_count; i++) | ||
457 | { | ||
458 | printf("%ld\t%s\n", i, ttcname.ttf_name[i]); | ||
459 | } | ||
460 | for(i = 0; i < ttcname.ttc_count; i++) | ||
461 | { | ||
462 | free(ttcname.ttf_name[i]); | ||
463 | } | ||
464 | printf("\n\n"); | ||
465 | free(ttcname.ttf_name); | ||
466 | |||
467 | return; | ||
468 | } | ||
469 | |||
470 | FT_Long getcharindex(FT_Face face, FT_Long code) | ||
471 | { | ||
472 | FT_Long idx; | ||
473 | if (nocmap) { | ||
474 | if (code >= face->num_glyphs) | ||
475 | idx = 0; | ||
476 | else | ||
477 | idx = code; | ||
478 | } else | ||
479 | idx = FT_Get_Char_Index( face, code); | ||
480 | |||
481 | if ( idx <= 0 || idx > face->num_glyphs) | ||
482 | return 0; | ||
483 | else | ||
484 | return idx; | ||
485 | } | ||
486 | |||
487 | void print_raw_glyph( FT_Face face) | ||
488 | { | ||
489 | int pixel,row,col,width; | ||
490 | width = face->glyph->metrics.width >> 6; | ||
491 | |||
492 | printf("\n---Raw-Glyph---\n"); | ||
493 | for(row=0; row < face->glyph->metrics.height >> 6; row++) | ||
494 | { | ||
495 | printf("_"); | ||
496 | for(col=0; col < width; col++) | ||
497 | { | ||
498 | pixel = *(face->glyph->bitmap.buffer+width*row+col)/26; | ||
499 | if ( pixel ) printf("%d",pixel); else printf(" "); | ||
500 | } | ||
501 | printf("_\n"); | ||
502 | } | ||
503 | printf("----End-----\n"); | ||
504 | } | ||
505 | |||
506 | int glyph_width( FT_Face face) | ||
507 | { | ||
508 | int pitch, h_adv, width; | ||
509 | unsigned spacing = (unsigned)(between_chr * (1<<6));/* convert to fixed point */ | ||
510 | |||
511 | pitch = ABS(face->glyph->bitmap.pitch); | ||
512 | h_adv = face->glyph->metrics.horiAdvance >> 6; | ||
513 | width = (face->glyph->metrics.width + spacing) >> 6; | ||
514 | |||
515 | if(pitch == 0) pitch = h_adv; | ||
516 | if(width < pitch) width = pitch; | ||
517 | if(width == 0) return 0; | ||
518 | |||
519 | return width; | ||
520 | } | ||
521 | |||
522 | |||
523 | void trim_glyph( FT_GlyphSlot glyph, int *empty_first_col, | ||
524 | int *empty_last_col, int *width ) | ||
525 | { | ||
526 | int row; | ||
527 | int stride = glyph->bitmap.pitch; | ||
528 | int end = stride-1; | ||
529 | int trim_left = 2, trim_right = 2; | ||
530 | |||
531 | const unsigned char limit = 64u; | ||
532 | const unsigned char *image = glyph->bitmap.buffer; | ||
533 | |||
534 | if (*width < 2) | ||
535 | return; /* nothing to do? */ | ||
536 | |||
537 | for(row=0; row< glyph->metrics.height >> 6; row++) | ||
538 | { | ||
539 | const unsigned char *column = image+row*stride; | ||
540 | if (*column++ < limit && trim_left) | ||
541 | { | ||
542 | if (*column >= limit/2) | ||
543 | trim_left = 1; | ||
544 | } | ||
545 | else | ||
546 | trim_left = 0; | ||
547 | |||
548 | column = image+row*stride+end; | ||
549 | if (*column-- < limit && trim_right) | ||
550 | { | ||
551 | if (*column >= limit/2) | ||
552 | trim_right = 1; | ||
553 | } | ||
554 | else | ||
555 | trim_right = 0; | ||
556 | } | ||
557 | |||
558 | |||
559 | (*width) -= trim_left + trim_right; | ||
560 | if (*width < 0) *width = 0; | ||
561 | |||
562 | *empty_first_col = trim_left; | ||
563 | *empty_last_col = trim_right; | ||
564 | } | ||
565 | |||
566 | void convttf(char* path, char* destfile, FT_Long face_index) | ||
567 | { | ||
568 | FT_Error error; | ||
569 | FT_Library library; | ||
570 | FT_Face face; | ||
571 | int w,h; | ||
572 | int row,col; | ||
573 | int empty_first_col, empty_last_col; | ||
574 | FT_Long charindex; | ||
575 | FT_Long index = 0; | ||
576 | FT_Long code; | ||
577 | |||
578 | int depth = 2; | ||
579 | unsigned char bit_shift = 1 << depth; | ||
580 | unsigned char pixel_per_byte = CHAR_BIT / bit_shift; | ||
581 | |||
582 | /* Initialize engine */ | ||
583 | if ( ( error = FT_Init_FreeType( &library ) ) != 0 ) | ||
584 | panic( "Error while initializing engine" ); | ||
585 | |||
586 | /* Load face */ | ||
587 | error = FT_New_Face( library, path, (FT_Long) face_index, &face ); | ||
588 | if ( error == FT_Err_Cannot_Open_Stream ) | ||
589 | arg_panic( "Could not find/open font\n", path ); | ||
590 | else if ( error ) | ||
591 | arg_panic( "Error while opening font\n", path ); | ||
592 | |||
593 | |||
594 | setcharmap( face ); | ||
595 | /* Set font header data */ | ||
596 | struct font_struct export_font; | ||
597 | export_font.header.header[0] = 'R'; | ||
598 | export_font.header.header[1] = 'B'; | ||
599 | export_font.header.header[2] = '1'; | ||
600 | export_font.header.header[3] = '2'; | ||
601 | //export_font.header.height = 0; | ||
602 | //export_font.header.ascent = 0; | ||
603 | |||
604 | float extra_space = (float)(between_row-trim_aa-trim_da); | ||
605 | FT_Set_Char_Size( face, 0, pixel_size << 6, hv_resolution, hv_resolution ); | ||
606 | export_font.header.ascent = | ||
607 | ((face->size->metrics.ascender*(100-trim_ap)/100) >> 6) - trim_aa; | ||
608 | |||
609 | export_font.header.height = | ||
610 | (((face->size->metrics.ascender*(100-trim_ap)/100) - | ||
611 | (face->size->metrics.descender*(100-trim_dp)/100)) >> 6) + extra_space; | ||
612 | |||
613 | printf("\n"); | ||
614 | printf("Please wait, converting %s:\n", path); | ||
615 | |||
616 | /* "face->num_glyphs" is NG.; */ | ||
617 | if ( limit_char == 0 ) limit_char = max_char; | ||
618 | if ( limit_char > max_char ) limit_char = max_char; | ||
619 | |||
620 | FT_Long char_count = 0; | ||
621 | |||
622 | |||
623 | |||
624 | export_font.header.maxwidth = 1; | ||
625 | export_font.header.depth = 1; | ||
626 | firstchar = limit_char; | ||
627 | lastchar = start_char; | ||
628 | |||
629 | /* calculate memory usage */ | ||
630 | for(code = start_char; code <= limit_char ; code++ ) | ||
631 | { | ||
632 | charindex = getcharindex( face, code); | ||
633 | if ( !(charindex) ) continue; | ||
634 | error = FT_Load_Glyph( face, charindex, | ||
635 | (FT_LOAD_RENDER | FT_LOAD_NO_BITMAP) ); | ||
636 | if ( error ) continue; | ||
637 | |||
638 | w = glyph_width( face ); | ||
639 | if (w == 0) continue; | ||
640 | empty_first_col = empty_last_col = 0; | ||
641 | if(trimming) | ||
642 | trim_glyph( face->glyph, &empty_first_col, &empty_last_col, &w); | ||
643 | |||
644 | if (export_font.header.maxwidth < w) | ||
645 | export_font.header.maxwidth = w; | ||
646 | |||
647 | |||
648 | char_count++; | ||
649 | index += (w*export_font.header.height + pixel_per_byte - 1)/pixel_per_byte; | ||
650 | |||
651 | if (code >= lastchar) | ||
652 | lastchar = code; | ||
653 | |||
654 | if (code <= firstchar) | ||
655 | firstchar = code; | ||
656 | } | ||
657 | export_font.header.defaultchar = firstchar; | ||
658 | export_font.header.firstchar = firstchar; | ||
659 | export_font.header.size = lastchar - firstchar + 1; | ||
660 | export_font.header.nbits = index; | ||
661 | export_font.header.noffset = export_font.header.size; | ||
662 | export_font.header.nwidth = export_font.header.size; | ||
663 | |||
664 | /* check if we need to use long offsets */ | ||
665 | char use_long_offset = (export_font.header.nbits >= 0xFFDB ); | ||
666 | |||
667 | /* allocate memory */ | ||
668 | export_font.offset = NULL; | ||
669 | export_font.offset_long = NULL; | ||
670 | if (use_long_offset) | ||
671 | export_font.offset_long = | ||
672 | malloc( sizeof(FT_Long)* export_font.header.noffset ); | ||
673 | else | ||
674 | export_font.offset = | ||
675 | malloc( sizeof(unsigned short)* export_font.header.noffset ); | ||
676 | |||
677 | export_font.width = | ||
678 | malloc( sizeof(unsigned char) * export_font.header.nwidth ); | ||
679 | export_font.chars_data = | ||
680 | malloc( sizeof(unsigned char) * export_font.header.nbits ); | ||
681 | |||
682 | /* for now we use the full height for each character */ | ||
683 | h = export_font.header.height; | ||
684 | |||
685 | index = 0; | ||
686 | int done = 0; | ||
687 | char char_name[1024]; | ||
688 | int converted_char_count = 0; | ||
689 | int failed_char_count = 0; | ||
690 | |||
691 | for( code = firstchar; code <= lastchar; code++ ) | ||
692 | { | ||
693 | /* Get gylph index from the char and render it */ | ||
694 | charindex = getcharindex( face, code); | ||
695 | if ( !charindex ) | ||
696 | { | ||
697 | if ( use_long_offset ) | ||
698 | export_font.offset_long[code - firstchar] = export_font.offset_long[0]; | ||
699 | else | ||
700 | export_font.offset[code - firstchar] = export_font.offset[0]; | ||
701 | export_font.width[code - firstchar] = export_font.width[0]; | ||
702 | continue; | ||
703 | } | ||
704 | |||
705 | error = FT_Load_Glyph( face, charindex , | ||
706 | (FT_LOAD_RENDER | FT_LOAD_NO_BITMAP) ); | ||
707 | if ( error ) { | ||
708 | continue; | ||
709 | } | ||
710 | if FT_HAS_GLYPH_NAMES( face ) | ||
711 | FT_Get_Glyph_Name( face, charindex, char_name, 16); | ||
712 | else | ||
713 | char_name[0] = '\0'; | ||
714 | |||
715 | FT_GlyphSlot slot = face->glyph; | ||
716 | FT_Bitmap* source = &slot->bitmap; | ||
717 | //print_raw_glyph( face ); | ||
718 | w = glyph_width( face ); | ||
719 | if (w == 0) continue; | ||
720 | empty_first_col = empty_last_col = 0; | ||
721 | |||
722 | if(trimming) | ||
723 | trim_glyph( face->glyph, &empty_first_col, &empty_last_col, &w ); | ||
724 | |||
725 | if ( use_long_offset ) | ||
726 | export_font.offset_long[code - firstchar] = index; | ||
727 | else | ||
728 | export_font.offset[code - firstchar] = index; | ||
729 | |||
730 | export_font.width[code - firstchar] = w; | ||
731 | |||
732 | /* copy the glyph bitmap to a full sized glyph bitmap */ | ||
733 | unsigned char* src = source->buffer; | ||
734 | unsigned char* tmpbuf = malloc(sizeof(unsigned char) * w * h); | ||
735 | memset(tmpbuf, 0xff, w*h); | ||
736 | int start_y = export_font.header.ascent - slot->bitmap_top; | ||
737 | |||
738 | int glyph_height = source->rows; | ||
739 | int stride = source->pitch; | ||
740 | unsigned char* buf = tmpbuf; | ||
741 | unsigned char* endbuf = tmpbuf + w*h; | ||
742 | |||
743 | int error = 0; | ||
744 | /* insert empty pixels on the left */ | ||
745 | int col_off = w - stride; | ||
746 | if (col_off > 1) col_off /= 2; | ||
747 | if (col_off < 0) col_off = 0; | ||
748 | |||
749 | for(row=0; row < glyph_height; row++) | ||
750 | { | ||
751 | if(row+start_y < 0 || row+start_y >= h) | ||
752 | continue; | ||
753 | for(col = empty_first_col; col < stride; col++) | ||
754 | { | ||
755 | unsigned char *tsrc, *dst; | ||
756 | dst = buf + (w*(start_y+row)) + col + col_off; | ||
757 | tsrc = src + stride*row + col; | ||
758 | if (dst < endbuf && dst >= tmpbuf) | ||
759 | *dst = 0xff - *tsrc; | ||
760 | else { | ||
761 | error = 1; | ||
762 | printf("Error! row: %3d col: %3d\n", row, col); | ||
763 | } | ||
764 | } | ||
765 | } | ||
766 | if(error) print_raw_glyph(face); | ||
767 | |||
768 | buf = tmpbuf; | ||
769 | int numbits; | ||
770 | unsigned int field; | ||
771 | field = 0; | ||
772 | numbits = pixel_per_byte; | ||
773 | |||
774 | for(row=0; row < h; row++) | ||
775 | { | ||
776 | for(col=0; col < w; col++) | ||
777 | { | ||
778 | unsigned int src = *buf++; | ||
779 | unsigned int cur_col = (src + 8) / 17; | ||
780 | field |= (cur_col << (bit_shift*(pixel_per_byte-numbits))); | ||
781 | |||
782 | if (--numbits == 0) | ||
783 | { | ||
784 | export_font.chars_data[index++] = (unsigned char)field; | ||
785 | numbits = pixel_per_byte; | ||
786 | field = 0; | ||
787 | } | ||
788 | } | ||
789 | } | ||
790 | |||
791 | /* Pad last byte */ | ||
792 | if (numbits != pixel_per_byte) | ||
793 | { | ||
794 | export_font.chars_data[index++] = (unsigned char)field; | ||
795 | } | ||
796 | |||
797 | if( dump_glyphs ) | ||
798 | { | ||
799 | /* debug: dump char */ | ||
800 | printf("\n---Converted Glyph Dump---\n"); | ||
801 | unsigned char bit_max = (1 << bit_shift) - 1; | ||
802 | if ( code > 32 && code < 255 ) { | ||
803 | row = h; | ||
804 | if(use_long_offset) | ||
805 | buf = &(export_font.chars_data[export_font.offset_long[ | ||
806 | code - firstchar]]); | ||
807 | else | ||
808 | buf = &(export_font.chars_data[export_font.offset[ | ||
809 | code - firstchar]]); | ||
810 | unsigned char current_data; | ||
811 | unsigned char font_bits; | ||
812 | numbits = pixel_per_byte; | ||
813 | current_data = *buf; | ||
814 | do | ||
815 | { | ||
816 | col = w; | ||
817 | printf("-"); | ||
818 | do | ||
819 | { | ||
820 | font_bits = current_data & bit_max; | ||
821 | if (font_bits==bit_max) | ||
822 | printf(" "); | ||
823 | else | ||
824 | { | ||
825 | if(font_bits > bit_max/2) | ||
826 | printf("."); | ||
827 | else | ||
828 | printf("@"); | ||
829 | } | ||
830 | if (--numbits == 0) | ||
831 | { | ||
832 | current_data = *(++buf); | ||
833 | numbits = pixel_per_byte; | ||
834 | } | ||
835 | else | ||
836 | { | ||
837 | current_data >>= bit_shift; | ||
838 | } | ||
839 | } while (--col); | ||
840 | printf("-\n"); | ||
841 | } while (--row); | ||
842 | } | ||
843 | buf = NULL; | ||
844 | printf("---End Glyph Dump---\n"); | ||
845 | } | ||
846 | |||
847 | free(tmpbuf); | ||
848 | converted_char_count++; | ||
849 | done = (100*(converted_char_count))/char_count; | ||
850 | printf("Converted %s %d (%d%%)\e[K\r", | ||
851 | char_name,converted_char_count,done); fflush(stdout); | ||
852 | } | ||
853 | |||
854 | FILE *file = fopen(destfile, "w"); | ||
855 | printf("Writing %s\n", destfile); | ||
856 | |||
857 | /* font info */ | ||
858 | writestr(file, VERSION, 4); | ||
859 | writeshort(file, export_font.header.maxwidth); | ||
860 | writeshort(file, export_font.header.height); | ||
861 | writeshort(file, export_font.header.ascent); | ||
862 | writeshort(file, export_font.header.depth); | ||
863 | writeint(file, export_font.header.firstchar); | ||
864 | writeint(file, export_font.header.defaultchar); | ||
865 | writeint(file, export_font.header.size); | ||
866 | writeint(file, export_font.header.nbits); | ||
867 | writeint(file, export_font.header.noffset); | ||
868 | writeint(file, export_font.header.nwidth); | ||
869 | |||
870 | fwrite( (char*)export_font.chars_data, 1, | ||
871 | export_font.header.nbits, file); | ||
872 | free(export_font.chars_data); | ||
873 | |||
874 | int skip,i; | ||
875 | char pad[] = {0,0,0,0}; | ||
876 | if ( use_long_offset ) | ||
877 | { | ||
878 | skip = ((export_font.header.nbits + 3) & ~3) - | ||
879 | export_font.header.nbits; | ||
880 | fwrite(pad, 1, skip, file); /* pad */ | ||
881 | for(i = 0; i < export_font.header.noffset; i++) | ||
882 | writeint(file, export_font.offset_long[i]); | ||
883 | } | ||
884 | else | ||
885 | { | ||
886 | skip = ((export_font.header.nbits + 1) & ~1) - | ||
887 | export_font.header.nbits; | ||
888 | fwrite(pad, 1, skip, file); /* pad */ | ||
889 | for(i = 0; i < export_font.header.noffset; i++) | ||
890 | writeshort(file, export_font.offset[i]); | ||
891 | } | ||
892 | |||
893 | for(i = 0; i < export_font.header.nwidth; i++) | ||
894 | writebyte(file, export_font.width[i]); | ||
895 | free(export_font.width); | ||
896 | |||
897 | if ( use_long_offset ) | ||
898 | free(export_font.offset_long); | ||
899 | else | ||
900 | free(export_font.offset); | ||
901 | |||
902 | fclose(file); | ||
903 | FT_Done_Face( face ); | ||
904 | FT_Done_FreeType( library ); | ||
905 | printf("done (converted %d glyphs, %d errors).\e[K\n\n", | ||
906 | converted_char_count, failed_char_count); | ||
907 | |||
908 | } | ||
909 | |||
910 | void convttc(char* path) | ||
911 | { | ||
912 | struct ttc_table ttcname; | ||
913 | FT_Long i; | ||
914 | |||
915 | get_ttc_table(path, &ttcname); | ||
916 | |||
917 | if (ttcname.ttc_count == 0) | ||
918 | { | ||
919 | printf("This file is a not true type font.\n"); | ||
920 | return; | ||
921 | } | ||
922 | |||
923 | /* default */ | ||
924 | if (!flg_all_ttc && ttc_index == -1) | ||
925 | { | ||
926 | if (!oflag) | ||
927 | { /* generate filename */ | ||
928 | snprintf(outfile, sizeof(outfile), | ||
929 | "%d-%s.fnt", pixel_size, basename(path)); | ||
930 | } | ||
931 | convttf(path, outfile, (FT_Long) 0); | ||
932 | } | ||
933 | |||
934 | /* set face_index of ttc */ | ||
935 | else if (!flg_all_ttc) | ||
936 | { | ||
937 | print_ttc_table(path); | ||
938 | if ( !oflag ) | ||
939 | { | ||
940 | if (ttc_index >= 0 && | ||
941 | ttc_index < ttcname.ttc_count) | ||
942 | { | ||
943 | if (strcmp(ttcname.ttf_name[ttc_index], "") != 0) | ||
944 | { | ||
945 | snprintf(outfile, sizeof(outfile), "%d-%s.fnt", | ||
946 | pixel_size, ttcname.ttf_name[ttc_index]); | ||
947 | } | ||
948 | else | ||
949 | { | ||
950 | snprintf(outfile, sizeof(outfile), "%d-%s-%ld.fnt", | ||
951 | pixel_size, basename(path), ttc_index); | ||
952 | } | ||
953 | } | ||
954 | else | ||
955 | { | ||
956 | printf("illegal face index of ttc.\n"); | ||
957 | } | ||
958 | } | ||
959 | convttf(path, outfile, ttc_index); | ||
960 | } | ||
961 | else { /* convert all fonts */ | ||
962 | print_ttc_table(path); | ||
963 | for(i = 0; i < ttcname.ttc_count; i++) | ||
964 | { | ||
965 | snprintf(outfile, sizeof(outfile), "%d-%s.fnt", | ||
966 | pixel_size, ttcname.ttf_name[i]); | ||
967 | convttf(path, outfile, i); | ||
968 | } | ||
969 | } | ||
970 | |||
971 | for(i = 0; i < ttcname.ttc_count; i++) | ||
972 | { | ||
973 | free(ttcname.ttf_name[i]); | ||
974 | } | ||
975 | free(ttcname.ttf_name); | ||
976 | } | ||
977 | |||
978 | |||
979 | |||
980 | /* parse command line options*/ | ||
981 | void getopts(int *pac, char ***pav) | ||
982 | { | ||
983 | char *p; | ||
984 | char **av; | ||
985 | int ac; | ||
986 | ac = *pac; | ||
987 | av = *pav; | ||
988 | |||
989 | limit_char = max_char; | ||
990 | start_char = 0; | ||
991 | |||
992 | while (ac > 0 && av[0][0] == '-') { | ||
993 | p = &av[0][1]; | ||
994 | while( *p) | ||
995 | switch(*p++) { | ||
996 | case 'h':case 'H': | ||
997 | usage(); | ||
998 | break; | ||
999 | case ' ': /* multiple -args on av[]*/ | ||
1000 | while( *p && *p == ' ') | ||
1001 | p++; | ||
1002 | if( *p++ != '-') /* next option must have dash*/ | ||
1003 | p = ""; | ||
1004 | break; /* proceed to next option*/ | ||
1005 | case 'o': /* set output file*/ | ||
1006 | oflag = 1; | ||
1007 | if (*p) { | ||
1008 | strcpy(outfile, p); | ||
1009 | while (*p && *p != ' ') | ||
1010 | p++; | ||
1011 | } | ||
1012 | else { | ||
1013 | av++; ac--; | ||
1014 | if (ac > 0) | ||
1015 | strcpy(outfile, av[0]); | ||
1016 | } | ||
1017 | break; | ||
1018 | case 'l': /* set encoding limit*/ | ||
1019 | if (*p) { | ||
1020 | limit_char = atoi(p); | ||
1021 | while (*p && *p != ' ') | ||
1022 | p++; | ||
1023 | } | ||
1024 | else { | ||
1025 | av++; ac--; | ||
1026 | if (ac > 0) | ||
1027 | limit_char = atoi(av[0]); | ||
1028 | } | ||
1029 | break; | ||
1030 | case 's': /* set encoding start*/ | ||
1031 | if (*p) { | ||
1032 | start_char = atol(p); | ||
1033 | while (*p && *p != ' ') | ||
1034 | p++; | ||
1035 | } | ||
1036 | else { | ||
1037 | av++; ac--; | ||
1038 | if (ac > 0) | ||
1039 | start_char = atol(av[0]); | ||
1040 | } | ||
1041 | break; | ||
1042 | case 'p': /* set pixel size*/ | ||
1043 | if (*p) { | ||
1044 | pixel_size = atoi(p); | ||
1045 | while (*p && *p != ' ') | ||
1046 | p++; | ||
1047 | } | ||
1048 | else { | ||
1049 | av++; ac--; | ||
1050 | if (ac > 0) | ||
1051 | pixel_size = atoi(av[0]); | ||
1052 | } | ||
1053 | break; | ||
1054 | case 'c': /* set spaece between characters */ | ||
1055 | { | ||
1056 | if (*p) { | ||
1057 | between_chr = atof(p); | ||
1058 | while (*p && *p != ' ') | ||
1059 | p++; | ||
1060 | } | ||
1061 | else { | ||
1062 | av++; ac--; | ||
1063 | if (ac > 0) | ||
1064 | between_chr = atof(av[0]); | ||
1065 | } | ||
1066 | break; | ||
1067 | } | ||
1068 | case 'd': | ||
1069 | dump_glyphs = 1; | ||
1070 | while (*p && *p != ' ') | ||
1071 | p++; | ||
1072 | break; | ||
1073 | case 'x': | ||
1074 | trimming = 1; | ||
1075 | while (*p && *p != ' ') | ||
1076 | p++; | ||
1077 | break; | ||
1078 | case 'X': | ||
1079 | if (*p) { | ||
1080 | hv_resolution = atoi(p); | ||
1081 | while (*p && *p != ' ') | ||
1082 | p++; | ||
1083 | } | ||
1084 | else { | ||
1085 | av++; ac--; | ||
1086 | if (ac > 0) | ||
1087 | hv_resolution = atoi(av[0]); | ||
1088 | } | ||
1089 | break; | ||
1090 | case 'r': | ||
1091 | if (*p) { | ||
1092 | between_row = atof(p); | ||
1093 | while (*p && *p != ' ') | ||
1094 | p++; | ||
1095 | } | ||
1096 | else { | ||
1097 | av++; ac--; | ||
1098 | if (ac > 0) | ||
1099 | between_row = atof(av[0]); | ||
1100 | } | ||
1101 | break; | ||
1102 | case 'T': | ||
1103 | if(*p == 'A') { | ||
1104 | if(*(++p)) { | ||
1105 | trim_ap = atoi(p); | ||
1106 | while (*p && *p != ' ') | ||
1107 | p++; | ||
1108 | } | ||
1109 | else { | ||
1110 | av++; ac--; | ||
1111 | if (ac > 0) | ||
1112 | trim_ap = atoi(av[0]); | ||
1113 | } | ||
1114 | break; | ||
1115 | } | ||
1116 | if(*p == 'D') { | ||
1117 | if(*(++p)) { | ||
1118 | trim_dp = atoi(p); | ||
1119 | while (*p && *p != ' ') | ||
1120 | p++; | ||
1121 | } | ||
1122 | else { | ||
1123 | av++; ac--; | ||
1124 | if (ac > 0) | ||
1125 | trim_dp = atoi(av[0]); | ||
1126 | } | ||
1127 | break; | ||
1128 | } | ||
1129 | if(*p == 'a') { | ||
1130 | if(*(++p)) { | ||
1131 | trim_aa = atoi(p); | ||
1132 | while (*p && *p != ' ') | ||
1133 | p++; | ||
1134 | } | ||
1135 | else { | ||
1136 | av++; ac--; | ||
1137 | if (ac > 0) | ||
1138 | trim_aa = atoi(av[0]); | ||
1139 | } | ||
1140 | break; | ||
1141 | } | ||
1142 | if(*p == 'd') { | ||
1143 | if(*(++p)) { | ||
1144 | trim_da = atoi(p); | ||
1145 | |||
1146 | } | ||
1147 | else { | ||
1148 | av++; ac--; | ||
1149 | if (ac > 0) | ||
1150 | trim_da = atoi(av[0]); | ||
1151 | } | ||
1152 | break; | ||
1153 | } | ||
1154 | fprintf(stderr, "Unknown option ignored: %s\n", p-1); | ||
1155 | while (*p && *p != ' ') | ||
1156 | p++; | ||
1157 | break; | ||
1158 | case 't': /* display ttc table */ | ||
1159 | if (*p == 't') { | ||
1160 | pct = 1; | ||
1161 | while (*p && *p != ' ') | ||
1162 | p++; | ||
1163 | } | ||
1164 | |||
1165 | else if (*p == 'a') { | ||
1166 | flg_all_ttc = 1; | ||
1167 | while (*p && *p != ' ') | ||
1168 | p++; | ||
1169 | } | ||
1170 | |||
1171 | else if (*p) { | ||
1172 | ttc_index = atoi(p); | ||
1173 | while (*p && *p != ' ') | ||
1174 | p++; | ||
1175 | } | ||
1176 | else { | ||
1177 | av++; ac--; | ||
1178 | if (ac > 0) | ||
1179 | ttc_index = atoi(av[0]); | ||
1180 | } | ||
1181 | break; | ||
1182 | |||
1183 | default: | ||
1184 | fprintf(stderr, "Unknown option ignored: %s\n", p-1); | ||
1185 | while (*p && *p != ' ') | ||
1186 | p++; | ||
1187 | } | ||
1188 | ++av; --ac; | ||
1189 | } | ||
1190 | *pac = ac; | ||
1191 | *pav = av; | ||
1192 | } | ||
1193 | |||
1194 | |||
1195 | int main(int ac, char **av) | ||
1196 | { | ||
1197 | int ret = 0; | ||
1198 | |||
1199 | ++av; --ac; /* skip av[0]*/ | ||
1200 | |||
1201 | getopts(&ac, &av); /* read command line options*/ | ||
1202 | |||
1203 | if (ac < 1) | ||
1204 | { | ||
1205 | usage(); | ||
1206 | } | ||
1207 | if (oflag) | ||
1208 | { | ||
1209 | if (ac > 1) | ||
1210 | { | ||
1211 | usage(); | ||
1212 | } | ||
1213 | } | ||
1214 | |||
1215 | if (limit_char < start_char) | ||
1216 | { | ||
1217 | usage(); | ||
1218 | exit(0); | ||
1219 | } | ||
1220 | |||
1221 | while (pct && ac > 0) | ||
1222 | { | ||
1223 | print_ttc_table(av[0]); | ||
1224 | ++av; --ac; | ||
1225 | exit(0); | ||
1226 | } | ||
1227 | |||
1228 | while (ac > 0) | ||
1229 | { | ||
1230 | convttc(av[0]); | ||
1231 | ++av; --ac; | ||
1232 | } | ||
1233 | |||
1234 | exit(ret); | ||
1235 | } | ||
1236 | |||
1237 | |||
1238 | |||
1239 | /* | ||
1240 | * Trie node structure. | ||
1241 | */ | ||
1242 | typedef struct { | ||
1243 | unsigned short key; /* Key value. */ | ||
1244 | unsigned short val; /* Data for the key. */ | ||
1245 | unsigned long sibs; /* Offset of siblings from trie beginning. */ | ||
1246 | unsigned long kids; /* Offset of children from trie beginning. */ | ||
1247 | } node_t; | ||
1248 | |||
1249 | /* | ||
1250 | * The trie used for remapping codes. | ||
1251 | */ | ||
1252 | static node_t *nodes; | ||
1253 | static unsigned long nodes_used = 0; | ||
1254 | |||
1255 | int | ||
1256 | otf2bdf_remap(unsigned short *code) | ||
1257 | { | ||
1258 | unsigned long i, n, t; | ||
1259 | unsigned short c, codes[2]; | ||
1260 | |||
1261 | /* | ||
1262 | * If no mapping table was loaded, then simply return the code. | ||
1263 | */ | ||
1264 | if (nodes_used == 0) | ||
1265 | return 1; | ||
1266 | |||
1267 | c = *code; | ||
1268 | codes[0] = (c >> 8) & 0xff; | ||
1269 | codes[1] = c & 0xff; | ||
1270 | |||
1271 | for (i = n = 0; i < 2; i++) { | ||
1272 | t = nodes[n].kids; | ||
1273 | if (t == 0) | ||
1274 | return 0; | ||
1275 | for (; nodes[t].sibs && nodes[t].key != codes[i]; t = nodes[t].sibs); | ||
1276 | if (nodes[t].key != codes[i]) | ||
1277 | return 0; | ||
1278 | n = t; | ||
1279 | } | ||
1280 | |||
1281 | *code = nodes[n].val; | ||
1282 | return 1; | ||
1283 | } | ||
diff --git a/tools/root.make b/tools/root.make index 85a996fc62..20b11ae1fb 100644 --- a/tools/root.make +++ b/tools/root.make | |||
@@ -21,7 +21,7 @@ ASMFLAGS = -D__ASSEMBLER__ # work around gcc 3.4.x bug with -std=gnu99, onl | |||
21 | TOOLS = $(TOOLSDIR)/rdf2binary $(TOOLSDIR)/convbdf \ | 21 | TOOLS = $(TOOLSDIR)/rdf2binary $(TOOLSDIR)/convbdf \ |
22 | $(TOOLSDIR)/codepages $(TOOLSDIR)/scramble $(TOOLSDIR)/bmp2rb \ | 22 | $(TOOLSDIR)/codepages $(TOOLSDIR)/scramble $(TOOLSDIR)/bmp2rb \ |
23 | $(TOOLSDIR)/uclpack $(TOOLSDIR)/mkboot $(TOOLSDIR)/iaudio_bl_flash.c \ | 23 | $(TOOLSDIR)/uclpack $(TOOLSDIR)/mkboot $(TOOLSDIR)/iaudio_bl_flash.c \ |
24 | $(TOOLSDIR)/iaudio_bl_flash.h | 24 | $(TOOLSDIR)/iaudio_bl_flash.h $(TOOLSDIR)/convttf |
25 | 25 | ||
26 | 26 | ||
27 | ifeq (,$(PREFIX)) | 27 | ifeq (,$(PREFIX)) |
diff --git a/tools/tools.make b/tools/tools.make index 64a47c53de..c143157dab 100644 --- a/tools/tools.make +++ b/tools/tools.make | |||
@@ -33,6 +33,11 @@ $(TOOLSDIR)/uclpack: $(TOOLSDIR)/ucl/uclpack.c $(wildcard $(TOOLSDIR)/ucl/src/*. | |||
33 | $(call PRINTS,CC $(@F))$(HOSTCC) $(TOOLSCFLAGS) -I$(TOOLSDIR)/ucl \ | 33 | $(call PRINTS,CC $(@F))$(HOSTCC) $(TOOLSCFLAGS) -I$(TOOLSDIR)/ucl \ |
34 | -I$(TOOLSDIR)/ucl/include -o $@ $^ | 34 | -I$(TOOLSDIR)/ucl/include -o $@ $^ |
35 | 35 | ||
36 | $(TOOLSDIR)/convttf: $(TOOLSDIR)/convttf.c | ||
37 | $(call PRINTS,CC $(@F)) | ||
38 | $(SILENT)$(HOSTCC) $(TOOLSFLAGS) -lm -O2 -Wall -g $+ -o $@ \ | ||
39 | `freetype-config --libs` `freetype-config --cflags` | ||
40 | |||
36 | # implicit rule for simple tools | 41 | # implicit rule for simple tools |
37 | $(TOOLSDIR)/%: $(TOOLSDIR)/%.c | 42 | $(TOOLSDIR)/%: $(TOOLSDIR)/%.c |
38 | $(call PRINTS,CC $(subst $(ROOTDIR)/,,$@)) | 43 | $(call PRINTS,CC $(subst $(ROOTDIR)/,,$@)) |