|
|
|
@ -2543,6 +2543,98 @@ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static FT_Vector |
|
|
|
|
Lerp( float T, FT_Vector P0, FT_Vector P1 ) |
|
|
|
|
{ |
|
|
|
|
FT_Vector p; |
|
|
|
|
p.x = P0.x + T * ( P1.x - P0.x ); |
|
|
|
|
p.y = P0.y + T * ( P1.y - P0.y ); |
|
|
|
|
return p; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int conic_to2(FT_GlyphSlot* slot, FT_Vector *control, FT_Vector *from, FT_Vector *to, FT_PreLine *ptr) |
|
|
|
|
{ |
|
|
|
|
/*
|
|
|
|
|
Calculate devsq as the square of four times the |
|
|
|
|
distance from the control point to the midpoint of the curve. |
|
|
|
|
This is the place at which the curve is furthest from the |
|
|
|
|
line joining the control points. |
|
|
|
|
|
|
|
|
|
4 x point on curve = p0 + 2p1 + p2 |
|
|
|
|
4 x midpoint = 4p1 |
|
|
|
|
|
|
|
|
|
The division by four is omitted to save time. |
|
|
|
|
*/ |
|
|
|
|
//FT_PreLine ptr = (*slot)->prelines;
|
|
|
|
|
if((*slot)->glyph_index == 38) |
|
|
|
|
printf("conic from %d, %d to %d, %d via %d, %d\n", from->x, from->y, to->x, to->y, control->x, control->y); |
|
|
|
|
FT_Vector aP0 = { from->x , from->y}; |
|
|
|
|
FT_Vector aP1 = { control->x, control->y }; |
|
|
|
|
FT_Vector aP2 = { to->x, to->y }; |
|
|
|
|
|
|
|
|
|
float devx = aP0.x - aP1.x - aP1.x + aP2.x; |
|
|
|
|
float devy = aP0.y - aP1.y - aP1.y + aP2.y; |
|
|
|
|
float devsq = devx * devx + devy * devy; |
|
|
|
|
|
|
|
|
|
if ( devsq < 0.333f ) |
|
|
|
|
{ |
|
|
|
|
//dense_line_to( &aP2, worker );
|
|
|
|
|
FT_PreLine pl3 = malloc(sizeof(FT_PreLineRec)); |
|
|
|
|
pl3->x1 = (*ptr)->x2; |
|
|
|
|
pl3->y1 = (*ptr)->y2; |
|
|
|
|
pl3->x2 = aP2.x; |
|
|
|
|
pl3->y2 = aP2.y; |
|
|
|
|
pl3->next = NULL; |
|
|
|
|
pl3->ismove = 0; |
|
|
|
|
(*ptr)->next = pl3; |
|
|
|
|
*ptr = (*ptr)->next; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
According to Raph Levien, the reason for the subdivision by n (instead of |
|
|
|
|
recursive division by the Casteljau system) is that "I expect the flatness |
|
|
|
|
computation to be semi-expensive (it's done once rather than on each potential |
|
|
|
|
subdivision) and also because you'll often get fewer subdivisions. Taking a |
|
|
|
|
circular arc as a simplifying assumption, where I get n, a recursive approach |
|
|
|
|
would get 2^ceil(lg n), which, if I haven't made any horrible mistakes, is |
|
|
|
|
expected to be 33% more in the limit". |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
const float tol = 3.0f; |
|
|
|
|
int n = (int)floor( sqrt( sqrt( tol * devsq ) ) )/8; |
|
|
|
|
FT_Vector p = aP0; |
|
|
|
|
float nrecip = 1.0f / ( n + 1.0f ); |
|
|
|
|
float t = 0.0f; |
|
|
|
|
for ( int i = 0; i < n; i++ ) |
|
|
|
|
{ |
|
|
|
|
t += nrecip; |
|
|
|
|
FT_Vector next = Lerp( t, Lerp( t, aP0, aP1 ), Lerp( t, aP1, aP2 ) ); |
|
|
|
|
//dense_line_to(&next, worker );
|
|
|
|
|
FT_PreLine pl4 = malloc(sizeof(FT_PreLineRec)); |
|
|
|
|
pl4->x1 = (*ptr)->x2; |
|
|
|
|
pl4->y1 = (*ptr)->y2; |
|
|
|
|
pl4->x2 = next.x; |
|
|
|
|
pl4->y2 = next.y; |
|
|
|
|
pl4->next = NULL; |
|
|
|
|
pl4->ismove = 0; |
|
|
|
|
(*ptr)->next = pl4; |
|
|
|
|
*ptr = (*ptr)->next; |
|
|
|
|
p = next; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//dense_line_to( &aP2, worker );
|
|
|
|
|
FT_PreLine pl5 = malloc(sizeof(FT_PreLineRec)); |
|
|
|
|
pl5->x1 = (*ptr)->x2; |
|
|
|
|
pl5->y1 = (*ptr)->y2; |
|
|
|
|
pl5->x2 = aP2.x; |
|
|
|
|
pl5->y2 = aP2.y; |
|
|
|
|
pl5->next = NULL; |
|
|
|
|
pl5->ismove = 0; |
|
|
|
|
(*ptr)->next = pl5; |
|
|
|
|
*ptr = (*ptr)->next; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static FT_Error ft_decompose_outline(FT_GlyphSlot* slot){ |
|
|
|
@ -2688,6 +2780,74 @@ |
|
|
|
|
ptr = ptr->next; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case FT_CURVE_TAG_CONIC: /* consume conic arcs */ |
|
|
|
|
// v_control.x = SCALED( point->x );
|
|
|
|
|
// v_control.y = SCALED( point->y );
|
|
|
|
|
|
|
|
|
|
Do_Conic: |
|
|
|
|
if ( point < limit ) |
|
|
|
|
{ |
|
|
|
|
FT_Vector vec; |
|
|
|
|
FT_Vector v_middle; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
point++; |
|
|
|
|
tags++; |
|
|
|
|
tag = FT_CURVE_TAG( tags[0] ); |
|
|
|
|
|
|
|
|
|
// vec.x = SCALED( point->x );
|
|
|
|
|
// vec.y = SCALED( point->y );
|
|
|
|
|
vec.x = point->x; |
|
|
|
|
vec.y = point->y; |
|
|
|
|
|
|
|
|
|
if ( tag == FT_CURVE_TAG_ON ) |
|
|
|
|
{ |
|
|
|
|
FT_TRACE5(( " conic to (%.2f, %.2f)" |
|
|
|
|
" with control (%.2f, %.2f)\n", |
|
|
|
|
(double)vec.x / 64, |
|
|
|
|
(double)vec.y / 64, |
|
|
|
|
(double)v_control.x / 64, |
|
|
|
|
(double)v_control.y / 64 )); |
|
|
|
|
FT_Vector vex0 = {ptr->x2, ptr->y2}; |
|
|
|
|
error = conic_to2(slot, &v_control, &vex0,&vec , &ptr); |
|
|
|
|
// if ( error )
|
|
|
|
|
// goto Exit;
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ( tag != FT_CURVE_TAG_CONIC ) |
|
|
|
|
{ |
|
|
|
|
FT_TRACE5( ( "Invalid Outline" ) ); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
v_middle.x = ( v_control.x + vec.x ) / 2; |
|
|
|
|
v_middle.y = ( v_control.y + vec.y ) / 2; |
|
|
|
|
|
|
|
|
|
FT_TRACE5(( " conic to (%.2f, %.2f)" |
|
|
|
|
" with control (%.2f, %.2f)\n", |
|
|
|
|
(double)v_middle.x / 64, |
|
|
|
|
(double)v_middle.y / 64, |
|
|
|
|
(double)v_control.x / 64, |
|
|
|
|
(double)v_control.y / 64 )); |
|
|
|
|
FT_Vector vex = {ptr->x2, ptr->y2}; |
|
|
|
|
error = conic_to2(slot, &v_control, &vex,&v_middle, &ptr); |
|
|
|
|
// if ( error )
|
|
|
|
|
// goto Exit;
|
|
|
|
|
|
|
|
|
|
v_control = vec; |
|
|
|
|
goto Do_Conic; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
FT_TRACE5(( " conic to (%.2f, %.2f)" |
|
|
|
|
" with control (%.2f, %.2f)\n", |
|
|
|
|
(double)v_start.x / 64, |
|
|
|
|
(double)v_start.y / 64, |
|
|
|
|
(double)v_control.x / 64, |
|
|
|
|
(double)v_control.y / 64 )); |
|
|
|
|
FT_Vector vex2 = {ptr->x2, ptr->y2}; |
|
|
|
|
error = conic_to2( slot, &v_control, &vex2, &v_start, &ptr ); |
|
|
|
|
//goto Close;
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|