[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: [ft-devel] Two patches for FT
From: |
Turner, David |
Subject: |
RE: [ft-devel] Two patches for FT |
Date: |
Fri, 1 Apr 2005 14:28:01 +0200 |
Hello everyone,
according to the little program below, the arc passes just below
the pixel center. However, the distance is *very* small,
we're speaking about 1/300th of a pixel here !!
The FreeType monochrome rasterizer is capable of dealing with this
because in "high precision mode", which is selected automatically
for small character pixel sizes, it uses a grid of 1024 units per
pixel to decompose the splines.
If there is nothing wrong in the previous bytecode computations,
then it probably means that:
- the Windows engine is less accurate when computing the intersection
of bezier curves with scanlines
- the font was developed on Windows, and the DELTAP offset was
found through trial and error on this platform to disable the
pixel on it.
in other words, it's going to be hard to reproduce the feature in
the rasterizer. An easier fix would be to hack the interpreter to
'spot' the DELTAP instruction and change its offset dynamically
on purpose (as long as we're sure we're at the correct size, on the
correct font).
OR, we could do something wrong before the DELTAP, but I doubt we
do.
Any comments ?
- David Turner
- The FreeType Project (www.freetype.org)
> Thanks. Before DELTAP the coordinates are the same; after DELTAP
> FontForge shows (3.61, 3.62).
>
> George, Rogier, is it possible to see the coordinates with greater
> precision?
>
> David, for checking the spline, here are the values as given in
> FontForge:
>
> intermediate point between p16 and p17: (3.80,3.20)
> p17 (3.61,3.62)
> p18 (3.05,3.52)
>
> The pixel center in question is (3.5,3.5).
>
-------------------------- cut here -----------------------------
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
double x0, x1, x2, x3, y0, y1, y2, y3, a, b, c, delta, y, z, t;
/* technical note about the computation here:
*
* points on the bezier curve are defined with:
*
* P(t) = (1-t)*(1-t)*P1 + 2*t*(1-t)*P2 + t*t*P3
* = t*t*(P3+P1-2*P2) + 2*t*(P2-P1) + P1
*
* with t belonging to 0.0 ... 1.0
*
* the pixel center is at P0
*
* we first find 't' where P(t).x == P0.x, then compute P(t).y
* and compare it to P0.y
*
* - find t such as:
*
* t*t*(x3+x1-2*x2) + 2*t*(x2-x1) + x1 == x0
*
* or
*
* a.t² + 2b.t² + c = 0 a = (P3+P1-2P2), b = (P2-P1), c = (P1-P0)
* t² + 2(b/a)t + (c/a) = 0
*
* (t + b/a)² - (b/a)² + (c/a) = 0
* (t + b/a)² = (b² - ac)/a²
*
* compute:
* delta = (b²-ac)/a²
*
* t is one of:
*
* sqrt(delta) - (b/a)
* sqrt(delta) + (b/a)
*
* when delta >= 0
*/
x0 = 3.5;
x1 = 3.8;
x2 = 3.61;
x3 = 3.05;
/* find 't' which corresponds to P(t).x == P0.x */
a = x1+x3-2.0*x2;
b = x2-x1;
c = x1-x0;
if ( a < 0 )
{
a = -a;
b = -b;
c = -c;
}
delta = b*b - a*c;
if ( delta < 0 )
{
printf( "no solution !" );
return 1;
}
delta = sqrt(delta)/a;
z = b/a;
t = delta+z;
if ( t > 1.0 || t < 0.0 )
{
t = delta-z;
if ( t > 1.0 || t < 0.0 )
{
printf( "no solution in 0..1 !\n" );
return 2;
}
}
/* find the corresponding P(t).y */
y0 = 3.5;
y1 = 3.2;
y2 = 3.62;
y3 = 3.52;
y = t*t*(y1+y3-2.0*y2) + 2*t*(y2-y1) + y1;
if ( y < y0 )
{
printf( "arc is below pixel (y == %.3f < %.3f)\n", y, y0 );
}
else if ( y > y0 )
{
printf( "arc is above pixel (y == %.3f > %.3f)\n", y, y0 );
}
else
printf( "arc is on the curve (y == %.3f)\n", y );
return 0;
}
------------------------ cut here ------------------------------