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