[Applies to: FreeType 2.4.8, file "ftgrays.c"]
I believe there is discrepancy between what's written in ftgrays.c and its actual functioning.
It is said it "computes the _exact_ coverage of the outline on each pixel cell".
But the following program shows this is not true.
I used quadratic Bezier arc P0(0,1)-P1(1,1)-P2(1,0) (in integer pixel coords), that is, the whole
outline lies inside one pixel.
And I calculated coverage using equations (=5/6). So grey level should be 255*(5/6)=213,
but
ftgrays returns 192.
This is not just because outline is too small, the problem persists for larger outlines
too.
I don't test larger outlines here to keep example as simple as possible.
The program uses ftgrays in standalone mode (see ftgrays.c).
// file: test.c
#define _STANDALONE_
#define FT_ABS(a) ( (a) < 0 ? -(a) : (a) )
#include "ftgrays.c"
void main()
{
FT_Raster_New_Func raster_new = ft_grays_raster.raster_new;
FT_Raster_Reset_Func raster_reset = ft_grays_raster.raster_reset;
FT_Raster_Render_Func raster_render = ft_grays_raster.raster_render;
FT_Raster raster = 0;
char pool[16*1024] = {0}; // raster pool
//////////////////////////////////////////////////////////////////////////
FT_Raster_Params params = {0};
FT_Outline outline = {0};
FT_Bitmap bitmap = {0};
// init source outline
{
enum{ n = 4 }; // number of points
FT_Vector points[n] = {{0,0},{0,1},{1,1},{1,0}}; // in integer pixel coords
char tags[n] = {1,1,0,1}; // P1(1,1) is off the curve
short endpoint = n-1;
int i;
outline.n_contours = 1;
outline.n_points = n;
// convert points to
26.6 format
for(i=0; i<n; i++) points[i].x <<= 6, points[i].y <<= 6;
outline.points = points;
outline.tags = tags;
outline.contours = &endpoint;
}
// init target bitmap
{
enum{ a = 1 }; // width and height of target bitmap in pixels
char buffer[a*a] = {0}; // buffer for target bitmap
bitmap.rows = bitmap.width = bitmap.pitch = a;
bitmap.buffer = buffer;
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; //
ignored
bitmap.num_grays = 256; // ignored
}
//
init raster params
params.source = &outline;
params.target = &bitmap;
params.flags = FT_RASTER_FLAG_AA;
//params.clip_box; // used only if both FT_RASTER_FLAG_DIRECT and FT_RASTER_FLAG_CLIP are set
//////////////////////////////////////////////////////////////////////////
raster_new( 0, &raster );
raster_reset( raster, pool, sizeof pool );
raster_render( raster, ¶ms );
// 213 == (5/6)*255 (with math rounding)
if( bitmap.buffer[0] != 213 ) __asm int 3;
}