Lines 55-60
Link Here
|
55 |
#include FT_SYNTHESIS_H |
55 |
#include FT_SYNTHESIS_H |
56 |
#endif |
56 |
#endif |
57 |
|
57 |
|
|
|
58 |
#include FT_LCD_FILTER_H |
59 |
|
58 |
#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0)) |
60 |
#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0)) |
59 |
#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0) |
61 |
#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0) |
60 |
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0)) |
62 |
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0)) |
Lines 701-723
Link Here
|
701 |
return CAIRO_STATUS_SUCCESS; |
703 |
return CAIRO_STATUS_SUCCESS; |
702 |
} |
704 |
} |
703 |
|
705 |
|
704 |
/* Empirically-derived subpixel filtering values thanks to Keith |
706 |
/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot |
705 |
* Packard and libXft. */ |
707 |
* into a different format. For example, we want to convert a |
706 |
static const int filters[3][3] = { |
708 |
* FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit |
707 |
/* red */ |
709 |
* ARGB or ABGR bitmap. |
708 |
#if 0 |
710 |
* |
709 |
{ 65538*4/7,65538*2/7,65538*1/7 }, |
711 |
* this function prepares a target descriptor for this operation. |
710 |
/* green */ |
712 |
* |
711 |
{ 65536*1/4, 65536*2/4, 65537*1/4 }, |
713 |
* input :: target bitmap descriptor. The function will set its |
712 |
/* blue */ |
714 |
* 'width', 'rows' and 'pitch' fields, and only these |
713 |
{ 65538*1/7,65538*2/7,65538*4/7 }, |
715 |
* |
|
|
716 |
* slot :: the glyph slot containing the source bitmap. this |
717 |
* function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP |
718 |
* |
719 |
* mode :: the requested final rendering mode. supported values are |
720 |
* MONO, NORMAL (i.e. gray), LCD and LCD_V |
721 |
* |
722 |
* the function returns the size in bytes of the corresponding buffer, |
723 |
* it's up to the caller to allocate the corresponding memory block |
724 |
* before calling _fill_xrender_bitmap |
725 |
* |
726 |
* it also returns -1 in case of error (e.g. incompatible arguments, |
727 |
* like trying to convert a gray bitmap into a monochrome one) |
728 |
*/ |
729 |
static int |
730 |
_compute_xrender_bitmap_size( FT_Bitmap* target, |
731 |
FT_GlyphSlot slot, |
732 |
FT_Render_Mode mode ) |
733 |
{ |
734 |
FT_Bitmap* ftbit; |
735 |
int width, height, pitch; |
736 |
|
737 |
if ( slot->format != FT_GLYPH_FORMAT_BITMAP ) |
738 |
return -1; |
739 |
|
740 |
// compute the size of the final bitmap |
741 |
ftbit = &slot->bitmap; |
742 |
|
743 |
width = ftbit->width; |
744 |
height = ftbit->rows; |
745 |
pitch = (width+3) & ~3; |
746 |
|
747 |
switch ( ftbit->pixel_mode ) |
748 |
{ |
749 |
case FT_PIXEL_MODE_MONO: |
750 |
if ( mode == FT_RENDER_MODE_MONO ) |
751 |
{ |
752 |
pitch = (((width+31) & ~31) >> 3); |
753 |
break; |
754 |
} |
755 |
/* fall-through */ |
756 |
|
757 |
case FT_PIXEL_MODE_GRAY: |
758 |
if ( mode == FT_RENDER_MODE_LCD || |
759 |
mode == FT_RENDER_MODE_LCD_V ) |
760 |
{ |
761 |
/* each pixel is replicated into a 32-bit ARGB value */ |
762 |
pitch = width*4; |
763 |
} |
764 |
break; |
765 |
|
766 |
case FT_PIXEL_MODE_LCD: |
767 |
if ( mode != FT_RENDER_MODE_LCD ) |
768 |
return -1; |
769 |
|
770 |
/* horz pixel triplets are packed into 32-bit ARGB values */ |
771 |
width /= 3; |
772 |
pitch = width*4; |
773 |
break; |
774 |
|
775 |
case FT_PIXEL_MODE_LCD_V: |
776 |
if ( mode != FT_RENDER_MODE_LCD_V ) |
777 |
return -1; |
778 |
|
779 |
/* vert pixel triplets are packed into 32-bit ARGB values */ |
780 |
height /= 3; |
781 |
pitch = width*4; |
782 |
break; |
783 |
|
784 |
default: /* unsupported source format */ |
785 |
return -1; |
786 |
} |
787 |
|
788 |
target->width = width; |
789 |
target->rows = height; |
790 |
target->pitch = pitch; |
791 |
target->buffer = NULL; |
792 |
|
793 |
return pitch * height; |
794 |
} |
795 |
|
796 |
/* this functions converts the glyph bitmap found in a FT_GlyphSlot |
797 |
* into a different format (see _compute_xrender_bitmap_size) |
798 |
* |
799 |
* you should call this function after _compute_xrender_bitmap_size |
800 |
* |
801 |
* target :: target bitmap descriptor. Note that its 'buffer' pointer |
802 |
* must point to memory allocated by the caller |
803 |
* |
804 |
* slot :: the glyph slot containing the source bitmap |
805 |
* |
806 |
* mode :: the requested final rendering mode |
807 |
* |
808 |
* bgr :: boolean, set if BGR or VBGR pixel ordering is needed |
809 |
*/ |
810 |
static void |
811 |
_fill_xrender_bitmap( FT_Bitmap* target, |
812 |
FT_GlyphSlot slot, |
813 |
FT_Render_Mode mode, |
814 |
int bgr ) |
815 |
{ |
816 |
FT_Bitmap* ftbit = &slot->bitmap; |
817 |
unsigned char* srcLine = ftbit->buffer; |
818 |
unsigned char* dstLine = target->buffer; |
819 |
int src_pitch = ftbit->pitch; |
820 |
int width = target->width; |
821 |
int height = target->rows; |
822 |
int pitch = target->pitch; |
823 |
int subpixel; |
824 |
int h; |
825 |
|
826 |
subpixel = ( mode == FT_RENDER_MODE_LCD || |
827 |
mode == FT_RENDER_MODE_LCD_V ); |
828 |
|
829 |
if ( src_pitch < 0 ) |
830 |
srcLine -= src_pitch*(ftbit->rows-1); |
831 |
|
832 |
target->pixel_mode = ftbit->pixel_mode; |
833 |
|
834 |
switch ( ftbit->pixel_mode ) |
835 |
{ |
836 |
case FT_PIXEL_MODE_MONO: |
837 |
if ( subpixel ) /* convert mono to ARGB32 values */ |
838 |
{ |
839 |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) |
840 |
{ |
841 |
int x; |
842 |
|
843 |
for ( x = 0; x < width; x++ ) |
844 |
{ |
845 |
if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) ) |
846 |
((unsigned int*)dstLine)[x] = 0xffffffffU; |
847 |
} |
848 |
} |
849 |
target->pixel_mode = FT_PIXEL_MODE_LCD; |
850 |
} |
851 |
else if ( mode == FT_RENDER_MODE_NORMAL ) /* convert mono to 8-bit gray */ |
852 |
{ |
853 |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) |
854 |
{ |
855 |
int x; |
856 |
|
857 |
for ( x = 0; x < width; x++ ) |
858 |
{ |
859 |
if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) ) |
860 |
dstLine[x] = 0xff; |
861 |
} |
862 |
} |
863 |
target->pixel_mode = FT_PIXEL_MODE_GRAY; |
864 |
} |
865 |
else /* copy mono to mono */ |
866 |
{ |
867 |
int bytes = (width+7) >> 3; |
868 |
|
869 |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) |
870 |
memcpy( dstLine, srcLine, bytes ); |
871 |
} |
872 |
break; |
873 |
|
874 |
case FT_PIXEL_MODE_GRAY: |
875 |
if ( subpixel ) /* convert gray to ARGB32 values */ |
876 |
{ |
877 |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) |
878 |
{ |
879 |
int x; |
880 |
unsigned int* dst = (unsigned int*)dstLine; |
881 |
|
882 |
for ( x = 0; x < width; x++ ) |
883 |
{ |
884 |
unsigned int pix = srcLine[x]; |
885 |
|
886 |
pix |= (pix << 8); |
887 |
pix |= (pix << 16); |
888 |
|
889 |
dst[x] = pix; |
890 |
} |
891 |
} |
892 |
target->pixel_mode = FT_PIXEL_MODE_LCD; |
893 |
} |
894 |
else /* copy gray into gray */ |
895 |
{ |
896 |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) |
897 |
memcpy( dstLine, srcLine, width ); |
898 |
} |
899 |
break; |
900 |
|
901 |
case FT_PIXEL_MODE_LCD: |
902 |
if ( !bgr ) |
903 |
{ |
904 |
/* convert horizontal RGB into ARGB32 */ |
905 |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) |
906 |
{ |
907 |
int x; |
908 |
unsigned char* src = srcLine; |
909 |
unsigned int* dst = (unsigned int*)dstLine; |
910 |
|
911 |
for ( x = 0; x < width; x++, src += 3 ) |
912 |
{ |
913 |
unsigned int pix; |
914 |
|
915 |
pix = ((unsigned int)src[0] << 16) | |
916 |
((unsigned int)src[1] << 8) | |
917 |
((unsigned int)src[2] ) | |
918 |
((unsigned int)src[1] << 24) ; |
919 |
|
920 |
dst[x] = pix; |
921 |
} |
922 |
} |
923 |
} |
924 |
else |
925 |
{ |
926 |
/* convert horizontal BGR into ARGB32 */ |
927 |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) |
928 |
{ |
929 |
int x; |
930 |
unsigned char* src = srcLine; |
931 |
unsigned int* dst = (unsigned int*)dstLine; |
932 |
|
933 |
for ( x = 0; x < width; x++, src += 3 ) |
934 |
{ |
935 |
unsigned int pix; |
936 |
|
937 |
pix = ((unsigned int)src[2] << 16) | |
938 |
((unsigned int)src[1] << 8) | |
939 |
((unsigned int)src[0] ) | |
940 |
((unsigned int)src[1] << 24) ; |
941 |
|
942 |
dst[x] = pix; |
943 |
} |
944 |
} |
945 |
} |
946 |
break; |
947 |
|
948 |
default: /* FT_PIXEL_MODE_LCD_V */ |
949 |
/* convert vertical RGB into ARGB32 */ |
950 |
if ( !bgr ) |
951 |
{ |
952 |
for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch ) |
953 |
{ |
954 |
int x; |
955 |
unsigned char* src = srcLine; |
956 |
unsigned int* dst = (unsigned int*)dstLine; |
957 |
|
958 |
for ( x = 0; x < width; x++, src += 1 ) |
959 |
{ |
960 |
unsigned int pix; |
961 |
#if 1 |
962 |
pix = ((unsigned int)src[0] << 16) | |
963 |
((unsigned int)src[src_pitch] << 8) | |
964 |
((unsigned int)src[src_pitch*2] ) | |
965 |
0xFF000000 ; |
966 |
#else |
967 |
pix = ((unsigned int)src[0] << 16) | |
968 |
((unsigned int)src[src_pitch] << 8) | |
969 |
((unsigned int)src[src_pitch*2] ) | |
970 |
((unsigned int)src[src_pitch] << 24) ; |
714 |
#endif |
971 |
#endif |
715 |
{ 65538*9/13,65538*3/13,65538*1/13 }, |
972 |
dst[x] = pix; |
716 |
/* green */ |
973 |
} |
717 |
{ 65538*1/6, 65538*4/6, 65538*1/6 }, |
974 |
} |
718 |
/* blue */ |
975 |
} |
719 |
{ 65538*1/13,65538*3/13,65538*9/13 }, |
976 |
else |
720 |
}; |
977 |
{ |
|
|
978 |
for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch ) |
979 |
{ |
980 |
int x; |
981 |
unsigned char* src = srcLine; |
982 |
unsigned int* dst = (unsigned int*)dstLine; |
983 |
|
984 |
for ( x = 0; x < width; x++, src += 1 ) |
985 |
{ |
986 |
unsigned int pix; |
987 |
|
988 |
pix = ((unsigned int)src[src_pitch*2] << 16) | |
989 |
((unsigned int)src[src_pitch] << 8) | |
990 |
((unsigned int)src[0] ) | |
991 |
((unsigned int)src[src_pitch] << 24) ; |
992 |
|
993 |
dst[x] = pix; |
994 |
} |
995 |
} |
996 |
} |
997 |
} |
998 |
} |
999 |
|
721 |
|
1000 |
|
722 |
/* Fills in val->image with an image surface created from @bitmap |
1001 |
/* Fills in val->image with an image surface created from @bitmap |
723 |
*/ |
1002 |
*/ |
Lines 730-741
Link Here
|
730 |
int width, height, stride; |
1009 |
int width, height, stride; |
731 |
unsigned char *data; |
1010 |
unsigned char *data; |
732 |
int format = CAIRO_FORMAT_A8; |
1011 |
int format = CAIRO_FORMAT_A8; |
733 |
cairo_bool_t subpixel = FALSE; |
1012 |
cairo_image_surface_t *image; |
734 |
|
1013 |
|
735 |
width = bitmap->width; |
1014 |
width = bitmap->width; |
736 |
height = bitmap->rows; |
1015 |
height = bitmap->rows; |
737 |
|
1016 |
|
738 |
switch (bitmap->pixel_mode) { |
1017 |
{ |
|
|
1018 |
switch (bitmap->pixel_mode) |
1019 |
{ |
739 |
case FT_PIXEL_MODE_MONO: |
1020 |
case FT_PIXEL_MODE_MONO: |
740 |
stride = (((width + 31) & ~31) >> 3); |
1021 |
stride = (((width + 31) & ~31) >> 3); |
741 |
if (own_buffer) { |
1022 |
if (own_buffer) { |
Lines 765-771
Link Here
|
765 |
} |
1046 |
} |
766 |
} |
1047 |
} |
767 |
} |
1048 |
} |
768 |
|
|
|
769 |
#ifndef WORDS_BIGENDIAN |
1049 |
#ifndef WORDS_BIGENDIAN |
770 |
{ |
1050 |
{ |
771 |
unsigned char *d = data; |
1051 |
unsigned char *d = data; |
Lines 777-793
Link Here
|
777 |
} |
1057 |
} |
778 |
} |
1058 |
} |
779 |
#endif |
1059 |
#endif |
|
|
1060 |
|
780 |
format = CAIRO_FORMAT_A1; |
1061 |
format = CAIRO_FORMAT_A1; |
781 |
break; |
1062 |
break; |
782 |
|
1063 |
|
783 |
case FT_PIXEL_MODE_LCD: |
1064 |
case FT_PIXEL_MODE_LCD: |
784 |
case FT_PIXEL_MODE_LCD_V: |
1065 |
case FT_PIXEL_MODE_LCD_V: |
785 |
case FT_PIXEL_MODE_GRAY: |
1066 |
case FT_PIXEL_MODE_GRAY: |
786 |
switch (font_options->antialias) { |
1067 |
if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) |
787 |
case CAIRO_ANTIALIAS_DEFAULT: |
1068 |
{ |
788 |
case CAIRO_ANTIALIAS_GRAY: |
|
|
789 |
case CAIRO_ANTIALIAS_NONE: |
790 |
default: |
791 |
stride = bitmap->pitch; |
1069 |
stride = bitmap->pitch; |
792 |
if (own_buffer) { |
1070 |
if (own_buffer) { |
793 |
data = bitmap->buffer; |
1071 |
data = bitmap->buffer; |
Lines 800-906
Link Here
|
800 |
memcpy (data, bitmap->buffer, stride * height); |
1078 |
memcpy (data, bitmap->buffer, stride * height); |
801 |
} |
1079 |
} |
802 |
format = CAIRO_FORMAT_A8; |
1080 |
format = CAIRO_FORMAT_A8; |
803 |
break; |
1081 |
} else { |
804 |
case CAIRO_ANTIALIAS_SUBPIXEL: { |
1082 |
// if we get there, the data from the source bitmap |
805 |
int x, y; |
1083 |
// really comes from _fill_xrender_bitmap, and is |
806 |
unsigned char *in_line, *out_line, *in; |
1084 |
// made of 32-bit ARGB or ABGR values |
807 |
unsigned int *out; |
1085 |
assert(own_buffer != 0); |
808 |
unsigned int red, green, blue; |
1086 |
assert(bitmap->pixel_mode != FT_PIXEL_MODE_GRAY); |
809 |
int rf, gf, bf; |
|
|
810 |
int s; |
811 |
int o, os; |
812 |
unsigned char *data_rgba; |
813 |
unsigned int width_rgba, stride_rgba; |
814 |
int vmul = 1; |
815 |
int hmul = 1; |
816 |
|
817 |
switch (font_options->subpixel_order) { |
818 |
case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
819 |
case CAIRO_SUBPIXEL_ORDER_RGB: |
820 |
case CAIRO_SUBPIXEL_ORDER_BGR: |
821 |
default: |
822 |
width /= 3; |
823 |
hmul = 3; |
824 |
break; |
825 |
case CAIRO_SUBPIXEL_ORDER_VRGB: |
826 |
case CAIRO_SUBPIXEL_ORDER_VBGR: |
827 |
vmul = 3; |
828 |
height /= 3; |
829 |
break; |
830 |
} |
831 |
/* |
832 |
* Filter the glyph to soften the color fringes |
833 |
*/ |
834 |
width_rgba = width; |
835 |
stride = bitmap->pitch; |
836 |
stride_rgba = (width_rgba * 4 + 3) & ~3; |
837 |
data_rgba = calloc (1, stride_rgba * height); |
838 |
if (data_rgba == NULL) { |
839 |
if (own_buffer) |
840 |
free (bitmap->buffer); |
841 |
_cairo_error (CAIRO_STATUS_NO_MEMORY); |
842 |
return CAIRO_STATUS_NO_MEMORY; |
843 |
} |
844 |
|
845 |
os = 1; |
846 |
switch (font_options->subpixel_order) { |
847 |
case CAIRO_SUBPIXEL_ORDER_VRGB: |
848 |
os = stride; |
849 |
case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
850 |
case CAIRO_SUBPIXEL_ORDER_RGB: |
851 |
default: |
852 |
rf = 0; |
853 |
gf = 1; |
854 |
bf = 2; |
855 |
break; |
856 |
case CAIRO_SUBPIXEL_ORDER_VBGR: |
857 |
os = stride; |
858 |
case CAIRO_SUBPIXEL_ORDER_BGR: |
859 |
bf = 0; |
860 |
gf = 1; |
861 |
rf = 2; |
862 |
break; |
863 |
} |
864 |
in_line = bitmap->buffer; |
865 |
out_line = data_rgba; |
866 |
for (y = 0; y < height; y++) |
867 |
{ |
868 |
in = in_line; |
869 |
out = (unsigned int *) out_line; |
870 |
in_line += stride * vmul; |
871 |
out_line += stride_rgba; |
872 |
for (x = 0; x < width * hmul; x += hmul) |
873 |
{ |
874 |
red = green = blue = 0; |
875 |
o = 0; |
876 |
for (s = 0; s < 3; s++) |
877 |
{ |
878 |
red += filters[rf][s]*in[x+o]; |
879 |
green += filters[gf][s]*in[x+o]; |
880 |
blue += filters[bf][s]*in[x+o]; |
881 |
o += os; |
882 |
} |
883 |
red = red / 65536; |
884 |
green = green / 65536; |
885 |
blue = blue / 65536; |
886 |
*out++ = (green << 24) | (red << 16) | (green << 8) | blue; |
887 |
} |
888 |
} |
889 |
|
1087 |
|
890 |
/* Images here are stored in native format. The |
1088 |
data = bitmap->buffer; |
891 |
* backend must convert to its own format as needed |
1089 |
stride = bitmap->pitch; |
892 |
*/ |
|
|
893 |
|
894 |
if (own_buffer) |
895 |
free (bitmap->buffer); |
896 |
data = data_rgba; |
897 |
stride = stride_rgba; |
898 |
format = CAIRO_FORMAT_ARGB32; |
1090 |
format = CAIRO_FORMAT_ARGB32; |
899 |
subpixel = TRUE; |
|
|
900 |
break; |
901 |
} |
902 |
} |
1091 |
} |
903 |
break; |
1092 |
break; |
|
|
1093 |
|
904 |
case FT_PIXEL_MODE_GRAY2: |
1094 |
case FT_PIXEL_MODE_GRAY2: |
905 |
case FT_PIXEL_MODE_GRAY4: |
1095 |
case FT_PIXEL_MODE_GRAY4: |
906 |
/* These could be triggered by very rare types of TrueType fonts */ |
1096 |
/* These could be triggered by very rare types of TrueType fonts */ |
Lines 911-930
Link Here
|
911 |
return CAIRO_STATUS_NO_MEMORY; |
1101 |
return CAIRO_STATUS_NO_MEMORY; |
912 |
} |
1102 |
} |
913 |
|
1103 |
|
914 |
*surface = (cairo_image_surface_t *) |
1104 |
/* XXX */ |
|
|
1105 |
*surface = image = (cairo_image_surface_t *) |
915 |
cairo_image_surface_create_for_data (data, |
1106 |
cairo_image_surface_create_for_data (data, |
916 |
format, |
1107 |
format, |
917 |
width, height, stride); |
1108 |
width, height, stride); |
918 |
if ((*surface)->base.status) { |
1109 |
if (image->base.status) { |
919 |
free (data); |
1110 |
free (data); |
920 |
return CAIRO_STATUS_NO_MEMORY; |
1111 |
return CAIRO_STATUS_NO_MEMORY; |
921 |
} |
1112 |
} |
922 |
|
1113 |
|
923 |
if (subpixel) |
1114 |
if (font_options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) |
924 |
pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE); |
1115 |
pixman_image_set_component_alpha (image->pixman_image, TRUE); |
925 |
|
|
|
926 |
_cairo_image_surface_assume_ownership_of_data ((*surface)); |
927 |
|
1116 |
|
|
|
1117 |
_cairo_image_surface_assume_ownership_of_data (image); |
1118 |
} |
928 |
return CAIRO_STATUS_SUCCESS; |
1119 |
return CAIRO_STATUS_SUCCESS; |
929 |
} |
1120 |
} |
930 |
|
1121 |
|
Lines 948-963
Link Here
|
948 |
cairo_font_options_t *font_options, |
1139 |
cairo_font_options_t *font_options, |
949 |
cairo_image_surface_t **surface) |
1140 |
cairo_image_surface_t **surface) |
950 |
{ |
1141 |
{ |
|
|
1142 |
int rgba = FC_RGBA_UNKNOWN; |
951 |
FT_GlyphSlot glyphslot = face->glyph; |
1143 |
FT_GlyphSlot glyphslot = face->glyph; |
952 |
FT_Outline *outline = &glyphslot->outline; |
1144 |
FT_Outline *outline = &glyphslot->outline; |
953 |
FT_Bitmap bitmap; |
1145 |
FT_Bitmap bitmap; |
954 |
FT_BBox cbox; |
1146 |
FT_BBox cbox; |
955 |
FT_Matrix matrix; |
|
|
956 |
int hmul = 1; |
957 |
int vmul = 1; |
958 |
unsigned int width, height, stride; |
1147 |
unsigned int width, height, stride; |
959 |
cairo_bool_t subpixel = FALSE; |
1148 |
cairo_format_t format; |
960 |
cairo_status_t status; |
1149 |
cairo_status_t status; |
|
|
1150 |
FT_Error fterror; |
1151 |
FT_Library library = glyphslot->library; |
1152 |
FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL; |
1153 |
|
1154 |
switch (font_options->antialias) |
1155 |
{ |
1156 |
case CAIRO_ANTIALIAS_NONE: |
1157 |
render_mode = FT_RENDER_MODE_MONO; |
1158 |
break; |
1159 |
|
1160 |
case CAIRO_ANTIALIAS_SUBPIXEL: |
1161 |
switch (font_options->subpixel_order) |
1162 |
{ |
1163 |
case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
1164 |
case CAIRO_SUBPIXEL_ORDER_RGB: |
1165 |
case CAIRO_SUBPIXEL_ORDER_BGR: |
1166 |
render_mode = FT_RENDER_MODE_LCD; |
1167 |
break; |
1168 |
|
1169 |
case CAIRO_SUBPIXEL_ORDER_VRGB: |
1170 |
case CAIRO_SUBPIXEL_ORDER_VBGR: |
1171 |
render_mode = FT_RENDER_MODE_LCD_V; |
1172 |
break; |
1173 |
} |
1174 |
break; |
1175 |
|
1176 |
case CAIRO_ANTIALIAS_DEFAULT: |
1177 |
case CAIRO_ANTIALIAS_GRAY: |
1178 |
render_mode = FT_RENDER_MODE_NORMAL; |
1179 |
} |
961 |
|
1180 |
|
962 |
FT_Outline_Get_CBox (outline, &cbox); |
1181 |
FT_Outline_Get_CBox (outline, &cbox); |
963 |
|
1182 |
|
Lines 968-1067
Link Here
|
968 |
|
1187 |
|
969 |
width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6); |
1188 |
width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6); |
970 |
height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6); |
1189 |
height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6); |
971 |
stride = (width * hmul + 3) & ~3; |
1190 |
stride = (width + 3) & ~3; |
972 |
|
1191 |
|
973 |
if (width * height == 0) { |
1192 |
if (width * height == 0) { |
974 |
cairo_format_t format; |
|
|
975 |
/* Looks like fb handles zero-sized images just fine */ |
1193 |
/* Looks like fb handles zero-sized images just fine */ |
976 |
switch (font_options->antialias) { |
1194 |
switch (render_mode) |
977 |
case CAIRO_ANTIALIAS_NONE: |
1195 |
{ |
|
|
1196 |
case FT_RENDER_MODE_MONO: |
978 |
format = CAIRO_FORMAT_A1; |
1197 |
format = CAIRO_FORMAT_A1; |
979 |
break; |
1198 |
break; |
980 |
case CAIRO_ANTIALIAS_SUBPIXEL: |
1199 |
case FT_RENDER_MODE_LCD: |
981 |
format= CAIRO_FORMAT_ARGB32; |
1200 |
case FT_RENDER_MODE_LCD_V: |
|
|
1201 |
format = CAIRO_FORMAT_ARGB32; |
982 |
break; |
1202 |
break; |
983 |
case CAIRO_ANTIALIAS_DEFAULT: |
|
|
984 |
case CAIRO_ANTIALIAS_GRAY: |
985 |
default: |
1203 |
default: |
986 |
format = CAIRO_FORMAT_A8; |
1204 |
format = CAIRO_FORMAT_A8; |
987 |
break; |
|
|
988 |
} |
1205 |
} |
989 |
|
1206 |
|
990 |
(*surface) = (cairo_image_surface_t *) |
1207 |
(*surface) = (cairo_image_surface_t *) |
991 |
cairo_image_surface_create_for_data (NULL, format, 0, 0, 0); |
1208 |
cairo_image_surface_create_for_data (NULL, format, 0, 0, 0); |
992 |
if ((*surface)->base.status) |
1209 |
if ((*surface)->base.status) |
993 |
return CAIRO_STATUS_NO_MEMORY; |
1210 |
return CAIRO_STATUS_NO_MEMORY; |
|
|
1211 |
|
994 |
} else { |
1212 |
} else { |
995 |
|
1213 |
|
996 |
matrix.xx = matrix.yy = 0x10000L; |
1214 |
int bitmap_size; |
997 |
matrix.xy = matrix.yx = 0; |
|
|
998 |
|
1215 |
|
999 |
switch (font_options->antialias) { |
1216 |
switch (render_mode) |
1000 |
case CAIRO_ANTIALIAS_NONE: |
1217 |
{ |
1001 |
bitmap.pixel_mode = FT_PIXEL_MODE_MONO; |
1218 |
case FT_RENDER_MODE_LCD: |
1002 |
bitmap.num_grays = 1; |
1219 |
if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR ) { |
1003 |
stride = ((width + 31) & -32) >> 3; |
1220 |
rgba = FC_RGBA_BGR; |
|
|
1221 |
} else { |
1222 |
rgba = FC_RGBA_RGB; |
1223 |
} |
1004 |
break; |
1224 |
break; |
1005 |
case CAIRO_ANTIALIAS_DEFAULT: |
1225 |
|
1006 |
case CAIRO_ANTIALIAS_GRAY: |
1226 |
case FT_RENDER_MODE_LCD_V: |
1007 |
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; |
1227 |
if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR ) { |
1008 |
bitmap.num_grays = 256; |
1228 |
rgba = FC_RGBA_VBGR; |
1009 |
stride = (width + 3) & -4; |
1229 |
} else { |
|
|
1230 |
rgba = FC_RGBA_VRGB; |
1231 |
} |
1010 |
break; |
1232 |
break; |
1011 |
case CAIRO_ANTIALIAS_SUBPIXEL: |
1233 |
|
1012 |
switch (font_options->subpixel_order) { |
|
|
1013 |
case CAIRO_SUBPIXEL_ORDER_RGB: |
1014 |
case CAIRO_SUBPIXEL_ORDER_BGR: |
1015 |
case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
1016 |
default: |
1234 |
default: |
1017 |
matrix.xx *= 3; |
1235 |
; |
1018 |
hmul = 3; |
|
|
1019 |
subpixel = TRUE; |
1020 |
break; |
1021 |
case CAIRO_SUBPIXEL_ORDER_VRGB: |
1022 |
case CAIRO_SUBPIXEL_ORDER_VBGR: |
1023 |
matrix.yy *= 3; |
1024 |
vmul = 3; |
1025 |
subpixel = TRUE; |
1026 |
break; |
1027 |
} |
1236 |
} |
1028 |
FT_Outline_Transform (outline, &matrix); |
|
|
1029 |
|
1237 |
|
1030 |
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; |
1238 |
FT_Library_SetLcdFilter( library, FT_LCD_FILTER_DEFAULT ); |
1031 |
bitmap.num_grays = 256; |
|
|
1032 |
stride = (width * hmul + 3) & -4; |
1033 |
} |
1034 |
|
1239 |
|
1035 |
bitmap.pitch = stride; |
1240 |
fterror = FT_Render_Glyph( face->glyph, render_mode ); |
1036 |
bitmap.width = width * hmul; |
|
|
1037 |
bitmap.rows = height * vmul; |
1038 |
bitmap.buffer = calloc (1, stride * bitmap.rows); |
1039 |
|
1241 |
|
1040 |
if (bitmap.buffer == NULL) { |
1242 |
FT_Library_SetLcdFilter( library, FT_LCD_FILTER_NONE ); |
|
|
1243 |
|
1244 |
if (fterror != 0) { |
1041 |
_cairo_error (CAIRO_STATUS_NO_MEMORY); |
1245 |
_cairo_error (CAIRO_STATUS_NO_MEMORY); |
1042 |
return CAIRO_STATUS_NO_MEMORY; |
1246 |
return CAIRO_STATUS_NO_MEMORY; |
1043 |
} |
1247 |
} |
1044 |
|
1248 |
|
1045 |
FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul); |
1249 |
bitmap_size = _compute_xrender_bitmap_size( &bitmap, |
|
|
1250 |
face->glyph, |
1251 |
render_mode ); |
1252 |
if ( bitmap_size < 0 ) { |
1253 |
_cairo_error (CAIRO_STATUS_NO_MEMORY); |
1254 |
return CAIRO_STATUS_NO_MEMORY; |
1255 |
} |
1046 |
|
1256 |
|
1047 |
if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) { |
1257 |
bitmap.buffer = calloc(1, bitmap_size); |
1048 |
free (bitmap.buffer); |
1258 |
if (bitmap.buffer == NULL) { |
1049 |
_cairo_error (CAIRO_STATUS_NO_MEMORY); |
1259 |
_cairo_error (CAIRO_STATUS_NO_MEMORY); |
1050 |
return CAIRO_STATUS_NO_MEMORY; |
1260 |
return CAIRO_STATUS_NO_MEMORY; |
1051 |
} |
1261 |
} |
1052 |
|
1262 |
|
|
|
1263 |
_fill_xrender_bitmap( &bitmap, face->glyph, render_mode, |
1264 |
(rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR) ); |
1265 |
|
1266 |
// NOTE: _get_bitmap_surface will free bitmap.buffer if there is an error |
1053 |
status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface); |
1267 |
status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface); |
1054 |
if (status) |
1268 |
if (status) |
1055 |
return status; |
1269 |
return status; |
1056 |
} |
|
|
1057 |
|
1270 |
|
1058 |
/* |
1271 |
/* |
1059 |
* Note: the font's coordinate system is upside down from ours, so the |
1272 |
* Note: the font's coordinate system is upside down from ours, so the |
1060 |
* Y coordinate of the control box needs to be negated. |
1273 |
* Y coordinate of the control box needs to be negated. |
1061 |
*/ |
1274 |
*/ |
1062 |
cairo_surface_set_device_offset (&(*surface)->base, |
1275 |
cairo_surface_set_device_offset (&(*surface)->base, |
1063 |
floor ((double) cbox.xMin / 64.0), |
1276 |
(double) glyphslot->bitmap_left, |
1064 |
floor (-(double) cbox.yMax / 64.0)); |
1277 |
(double)-glyphslot->bitmap_top); |
|
|
1278 |
} |
1065 |
|
1279 |
|
1066 |
return CAIRO_STATUS_SUCCESS; |
1280 |
return CAIRO_STATUS_SUCCESS; |
1067 |
} |
1281 |
} |
Lines 1433-1443
Link Here
|
1433 |
case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
1647 |
case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
1434 |
case CAIRO_SUBPIXEL_ORDER_RGB: |
1648 |
case CAIRO_SUBPIXEL_ORDER_RGB: |
1435 |
case CAIRO_SUBPIXEL_ORDER_BGR: |
1649 |
case CAIRO_SUBPIXEL_ORDER_BGR: |
1436 |
load_target |= FT_LOAD_TARGET_LCD; |
1650 |
load_target = FT_LOAD_TARGET_LCD; |
1437 |
break; |
1651 |
break; |
1438 |
case CAIRO_SUBPIXEL_ORDER_VRGB: |
1652 |
case CAIRO_SUBPIXEL_ORDER_VRGB: |
1439 |
case CAIRO_SUBPIXEL_ORDER_VBGR: |
1653 |
case CAIRO_SUBPIXEL_ORDER_VBGR: |
1440 |
load_target |= FT_LOAD_TARGET_LCD_V; |
1654 |
load_target = FT_LOAD_TARGET_LCD_V; |
1441 |
break; |
1655 |
break; |
1442 |
} |
1656 |
} |
1443 |
} |
1657 |
} |