Add support for conics

gsoc-anurag-2023
Anurag Thakur 1 year ago
parent 579d9385ef
commit 0f715c8b90
  1. 160
      src/base/ftobjs.c

@ -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;
}
}

Loading…
Cancel
Save