| diff -rup libcairo-1.2.4.orig/src/cairo-ft-font.c libcairo-1.2.4/src/cairo-ft-font.c |
| --- libcairo-1.2.4.orig/src/cairo-ft-font.c 2006-08-22 21:40:02.802247352 +0800 |
| +++ libcairo-1.2.4/src/cairo-ft-font.c 2006-08-22 21:40:39.443677008 +0800 |
| @@ -53,6 +53,8 @@ |
| #include FT_SYNTHESIS_H |
| #endif |
| |
| +#define FIR_FILTER 1 |
| + |
| #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0)) |
| #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0) |
| #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0)) |
| @@ -492,6 +494,8 @@ _cairo_ft_unscaled_font_destroy (void *a |
| } |
| } |
| |
| +static const int fir_filter[5] = { 0x1C, 0x38, 0x55, 0x38, 0x1C }; |
| + |
| static cairo_bool_t |
| _has_unlocked_face (void *entry) |
| { |
| @@ -779,7 +783,220 @@ _get_bitmap_surface (FT_Bitmap *bi |
| } |
| format = CAIRO_FORMAT_A8; |
| break; |
| - case CAIRO_ANTIALIAS_SUBPIXEL: { |
| + case CAIRO_ANTIALIAS_SUBPIXEL: |
| +#ifdef FIR_FILTER |
| + { |
| + unsigned char* line; |
| + unsigned char* bufBitmap; |
| + int pitch; |
| + unsigned char *data_rgba; |
| + unsigned int width_rgba, stride_rgba; |
| + int vmul = 1; |
| + int hmul = 1; |
| + |
| + switch (font_options->subpixel_order) { |
| + case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
| + case CAIRO_SUBPIXEL_ORDER_RGB: |
| + case CAIRO_SUBPIXEL_ORDER_BGR: |
| + default: |
| + width /= 3; |
| + hmul = 3; |
| + break; |
| + case CAIRO_SUBPIXEL_ORDER_VRGB: |
| + case CAIRO_SUBPIXEL_ORDER_VBGR: |
| + vmul = 3; |
| + height /= 3; |
| + break; |
| + } |
| + /* |
| + * Filter the glyph to soften the color fringes |
| + */ |
| + width_rgba = width; |
| + stride = bitmap->pitch; |
| + stride_rgba = (width_rgba * 4 + 3) & ~3; |
| + data_rgba = calloc (1, stride_rgba * height); |
| + |
| + /* perform in-place FIR filtering in either the horizontal or |
| + * vertical direction. We're going to modify the RGB graymap, |
| + * but that's ok, because we either own it, or its part of |
| + * the FreeType glyph slot, which will not be used anymore. |
| + */ |
| + pitch = bitmap->pitch; |
| + line = (unsigned char*)bitmap->buffer; |
| + if ( pitch < 0 ) |
| + line -= pitch*(height-1); |
| + |
| + bufBitmap = line; |
| + |
| + switch (font_options->subpixel_order) { |
| + case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
| + case CAIRO_SUBPIXEL_ORDER_RGB: |
| + case CAIRO_SUBPIXEL_ORDER_BGR: |
| + { |
| + int h; |
| + |
| + for ( h = height; h > 0; h--, line += pitch ) { |
| + int pix[6] = { 0, 0, 0, 0, 0, 0 }; |
| + unsigned char* p = line; |
| + unsigned char* limit = line + width*3; |
| + int nn, val, val2; |
| + |
| + val = p[0]; |
| + for (nn = 0; nn < 3; nn++) |
| + pix[2 + nn] += val * fir_filter[nn]; |
| + |
| + val = p[1]; |
| + for (nn = 0; nn < 4; nn++) |
| + pix[1 + nn] += val * fir_filter[nn]; |
| + |
| + p += 2; |
| + |
| + for ( ; p < limit; p++ ) { |
| + val = p[0]; |
| + for (nn = 0; nn < 5; nn++) |
| + pix[nn] += val * fir_filter[nn]; |
| + |
| + val2 = pix[0] / 256; |
| + val2 |= -(val2 >> 8); |
| + p[-2] = (unsigned char)val2; |
| + |
| + for (nn = 0; nn < 5; nn++) |
| + pix[nn] = pix[nn + 1]; |
| + } |
| + for (nn = 0; nn < 2; nn++ ) { |
| + val2 = pix[nn] / 256; |
| + val2 |= -(val2 >> 8); |
| + p[nn - 2] = (unsigned char)val2; |
| + } |
| + } |
| + } |
| + break; |
| + case CAIRO_SUBPIXEL_ORDER_VRGB: |
| + case CAIRO_SUBPIXEL_ORDER_VBGR: |
| + { |
| + int w; |
| + |
| + for (w = 0; w < width; w++ ) { |
| + int pix[6] = { 0, 0, 0, 0, 0, 0 }; |
| + unsigned char* p = bufBitmap + w; |
| + unsigned char* limit = bufBitmap + w + height*3*pitch; |
| + int nn, val, val2; |
| + |
| + val = p[0]; |
| + for (nn = 0; nn < 3; nn++) |
| + pix[2 + nn] += val*fir_filter[nn]; |
| + |
| + val = p[pitch]; |
| + for (nn = 0; nn < 4; nn++ ) |
| + pix[1 + nn] += val * fir_filter[nn]; |
| + |
| + p += 2*pitch; |
| + for ( ; p < limit; p += pitch ) { |
| + val = p[0]; |
| + for (nn = 0; nn < 5; nn++ ) |
| + pix[nn] += val * fir_filter[nn]; |
| + |
| + val2 = pix[0] / 256; |
| + val2 |= -(val2 >> 8); |
| + p[-2 * pitch] = (unsigned char)val2; |
| + |
| + for (nn = 0; nn < 5; nn++) |
| + pix[nn] = pix[nn+1]; |
| + } |
| + |
| + for (nn = 0; nn < 2; nn++) { |
| + val2 = pix[nn] / 256; |
| + val2 |= -(val2 >> 8); |
| + p[(nn - 2) * pitch] = (unsigned char)val2; |
| + } |
| + } |
| + } |
| + break; |
| + default: /* shouldn't happen */ |
| + break; |
| + } |
| + |
| + /* now copy the resulting graymap into an ARGB32 image */ |
| + { |
| + unsigned char* in_line = bufBitmap; |
| + unsigned char* out_line = data_rgba; |
| + int h = height; |
| + |
| + switch (font_options->subpixel_order) { |
| + case CAIRO_SUBPIXEL_ORDER_DEFAULT: |
| + case CAIRO_SUBPIXEL_ORDER_RGB: |
| + for ( ; h > 0; h--, in_line += pitch, out_line += stride_rgba) { |
| + unsigned char* in = in_line; |
| + int* out = (int*)out_line; |
| + int w; |
| + |
| + for (w = width; w > 0; w--, in += 3, out += 1) { |
| + int r = in[0]; |
| + int g = in[1]; |
| + int b = in[2]; |
| + |
| + out[0] = (g << 24) | (r << 16) | (g << 8) | b; |
| + } |
| + } |
| + break; |
| + case CAIRO_SUBPIXEL_ORDER_BGR: |
| + for ( ; h > 0; h--, in_line += pitch, out_line += stride_rgba) { |
| + unsigned char* in = in_line; |
| + int* out = (int*)out_line; |
| + int w; |
| + |
| + for (w = width; w > 0; w--, in += 3, out += 1) { |
| + int r = in[2]; |
| + int g = in[1]; |
| + int b = in[0]; |
| + |
| + out[0] = (g << 24) | (r << 16) | (g << 8) | b; |
| + } |
| + } |
| + break; |
| + case CAIRO_SUBPIXEL_ORDER_VRGB: |
| + for ( ; h > 0; h--, in_line += pitch*3, out_line += stride_rgba) { |
| + unsigned char* in = in_line; |
| + int* out = (int*)out_line; |
| + int w; |
| + |
| + for (w = width; w > 0; w--, in += 1, out += 1) { |
| + int r = in[0]; |
| + int g = in[pitch]; |
| + int b = in[pitch*2]; |
| + |
| + out[0] = (g << 24) | (r << 16) | (g << 8) | b; |
| + } |
| + } |
| + break; |
| + case CAIRO_SUBPIXEL_ORDER_VBGR: |
| + for ( ; h > 0; h--, in_line += pitch*3, out_line += stride_rgba) { |
| + unsigned char* in = in_line; |
| + int* out = (int*)out_line; |
| + int w; |
| + |
| + for (w = width; w > 0; w--, in += 1, out += 1) { |
| + int r = in[2*pitch]; |
| + int g = in[pitch]; |
| + int b = in[0]; |
| + |
| + out[0] = (g << 24) | (r << 16) | (g << 8) | b; |
| + } |
| + } |
| + break; |
| + } |
| + } |
| + |
| + if (own_buffer) |
| + free (bitmap->buffer); |
| + data = data_rgba; |
| + stride = stride_rgba; |
| + format = CAIRO_FORMAT_ARGB32; |
| + subpixel = TRUE; |
| + break; |
| + } |
| +#else /* !FIR_FILTER */ |
| + { |
| int x, y; |
| unsigned char *in_line, *out_line, *in; |
| unsigned int *out; |
| @@ -871,6 +1088,7 @@ _get_bitmap_surface (FT_Bitmap *bi |
| subpixel = TRUE; |
| break; |
| } |
| +#endif /* !FIR_FILTER */ |
| } |
| break; |
| case FT_PIXEL_MODE_GRAY2: |
| @@ -986,12 +1204,22 @@ _render_glyph_outline (FT_Face |
| matrix.xx *= 3; |
| hmul = 3; |
| subpixel = TRUE; |
| +#ifdef FIR_FILTER |
| + cbox.xMin -= 64; |
| + cbox.xMax += 64; |
| + width += 2; |
| +#endif |
| break; |
| case CAIRO_SUBPIXEL_ORDER_VRGB: |
| case CAIRO_SUBPIXEL_ORDER_VBGR: |
| matrix.yy *= 3; |
| vmul = 3; |
| subpixel = TRUE; |
| +#ifdef FIR_FILTER |
| + cbox.yMin -= 64; |
| + cbox.yMax += 64; |
| + height += 2; |
| +#endif |
| break; |
| } |
| FT_Outline_Transform (outline, &matrix); |
| Only in libcairo-1.2.4/src: cairo-ft-font.c.orig |