summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2011-03-05 18:36:51 +0000
committerThomas Martitz <kugel@rockbox.org>2011-03-05 18:36:51 +0000
commit9edd6d4ee912273690b2600e8c52183dfa058eb9 (patch)
treecf6b0723f42c090022b94b38b3c4d856e9378d40
parent396ddd9fd79e458d1107f4065ce072eef99b6bce (diff)
downloadrockbox-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.c174
-rw-r--r--apps/plugins/rockpaint.c182
-rw-r--r--firmware/drivers/lcd-16bit.c252
-rw-r--r--firmware/drivers/lcd-bitmap-common.c10
-rw-r--r--firmware/export/font.h3
-rw-r--r--firmware/font.c31
-rw-r--r--tools/Makefile9
-rw-r--r--tools/convbdf.c15
-rw-r--r--tools/convttf.c1283
-rw-r--r--tools/root.make2
-rw-r--r--tools/tools.make5
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 */
694static 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
716static 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
666static void draw_putsxy_oriented(int x, int y, const char *str) 832static 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 */
593static 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
615static 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
565static void buffer_putsxyofs( fb_data *buf, int buf_width, int buf_height, 739static 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 */
932static 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 */
955static inline unsigned blend_color(unsigned c, unsigned a)
956{
957 return blend_two_colors(c, current_vp->fg_pattern, a);
958}
959
960void 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 */
905void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, 1157void 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 */
92static void cache_create(struct font* pf, int maxwidth, int height); 92static void cache_create(struct font* pf);
93static void glyph_cache_load(struct font* pf); 93static 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
135static 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
135void font_reset(struct font *pf) 142void 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 */
532static void cache_create(struct font* pf, int maxwidth, int height) 539static 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
14CLEANALL := scramble descramble iriver sh2d bmp2rb rdf2binary convbdf \ 14CLEANALL := 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
18all: scramble descramble sh2d rdf2binary mkboot mkzenboot convbdf codepages \ 18all: scramble descramble sh2d rdf2binary mkboot mkzenboot convbdf codepages \
19 uclpack rbspeexenc voicefont mk500boot 19 uclpack rbspeexenc voicefont mk500boot convttf
20 20
21scramble: scramble.o iriver.o mi4.o gigabeat.o gigabeats.o telechips.o \ 21scramble: 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
97usb_benchmark: usb_benchmark.c 97usb_benchmark: usb_benchmark.c
98 $(SILENT)$(CC) $(CFLAGS) -lusb $+ -o $@ 98 $(SILENT)$(CC) $(CFLAGS) -lusb $+ -o $@
99 99
100convttf: 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
100clean: 105clean:
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 */
54enum {
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 */
67static 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 */
82static int pid = DEFAULT_PLATFORM_ID;
83static int eid = DEFAULT_ENCODING_ID;
84
85
86/*
87 * A flag indicating if a CMap was found or not.
88 */
89static FT_UShort nocmap;
90
91int pct = 0; /* display ttc table if it is not zero. */
92unsigned long max_char = 65535;
93int pixel_size = 15;
94unsigned long start_char = 0;
95unsigned long limit_char;
96unsigned long firstchar = 0;
97unsigned long lastchar;
98FT_Long ttc_index = -1;
99int flg_all_ttc = 0;
100short antialias = 1; /* smooth fonts with gray levels */
101int oflag = 0;
102char outfile[1024];
103float between_chr = 0.0f;
104float between_row = 0.0f;
105int hv_resolution = 60;
106int dump_glyphs = 0;
107int trimming = 0;
108int trim_dp = 0; /* trim descent percent */
109int trim_da = 0; /* trim descnet actual */
110int trim_ap = 0; /* trim ascent precent */
111int trim_aa = 0; /* trim ascent actual */
112
113struct 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
128struct 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
136struct ttc_table{
137 FT_Long ttc_count;
138 char **ttf_name;
139};
140
141/* exit the program with given message */
142static void
143panic( const char* message)
144{
145 fprintf( stderr, "%s\n", message );
146 exit( 1 );
147}
148
149static void
150arg_panic( const char* message, const char* arg )
151{
152 fprintf( stderr, "%s: %s\n", message, arg );
153 exit( 1 );
154}
155
156static int writebyte(FILE *fp, unsigned char c)
157{
158 return putc(c, fp) != EOF;
159}
160
161static int writeshort(FILE *fp, unsigned short s)
162{
163 putc(s, fp);
164 return putc(s>>8, fp) != EOF;
165}
166
167static 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
175static int writestr(FILE *fp, char *str, int count)
176{
177 return (int)fwrite(str, 1, count, fp) == count;
178}
179
180/* print usage information */
181void 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*/
213char *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
235void 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 */
294static int
295otf_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
401int 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
446void 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
470FT_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
487void 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
506int 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
523void 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
566void 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
910void 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*/
981void 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
1195int 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 */
1242typedef 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 */
1252static node_t *nodes;
1253static unsigned long nodes_used = 0;
1254
1255int
1256otf2bdf_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
21TOOLS = $(TOOLSDIR)/rdf2binary $(TOOLSDIR)/convbdf \ 21TOOLS = $(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
27ifeq (,$(PREFIX)) 27ifeq (,$(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)/,,$@))