Обратите внимание, что Truetype допускает кривые bspline И прямые в определении глифа.
Если вам нужно изменить эти команды на серию MoveTo и LineTo, вы можете использовать следующее:
Преобразование данных TrueType в список подсказок координат. Это то, что ваша ОС может сделать для вас (следующий код использует API Windows).
Пройдите по всем координатам и переведите кривые в линии (см. Фрагмент кода ниже):
procedure TGlyphEvaluator.EvaluateFromBuffer( Action: TGlyphEvaluatorAction );
var
H : TTPOLYGONHEADER;
C : TTPOLYCURVE;
Points : array of TPointFX;
P, PE : DWORD;
i, j : Integer;
F : Double;
PA, PB, PC : TPoint;
begin
SetLength( Points, 10 );
P := 0;
repeat
// Eat the polygon header
Move( FBuffer[ P ], H, sizeof( H ) );
if H.dwType <> TT_POLYGON_TYPE then Break; // Sanity check!
PE := P + H.cb;
Inc( P, sizeof( H ) );
Points[ 0 ] := H.pfxStart;
// Eat all the curve records
while P < PE do begin
// Get the curve record
Move( FBuffer[ P ], C, sizeof( C ) - sizeof( TPointFX ) );
Inc( P, sizeof( C ) - sizeof( TPointFX ) );
// Get the points from the curve record
if Length( Points ) < C.cpfx + 1 then Setlength( Points, C.cpfx + 1 );
Move( FBuffer[ P ], Points[ 1 ], sizeof( TPointFX ) * C.cpfx );
Inc( P, sizeof( TPointFX ) * C.cpfx );
case C.wType of
TT_PRIM_LINE: begin
MoveTo( Action, Points[ 0 ].x.value, Points[ 0 ].y.value );
for i := 1 to C.cpfx do
LineTo( Action, Points[ i ].x.value, Points[ i ].y.value );
end;
TT_PRIM_QSPLINE: begin
MoveTo( Action, Points[ 0 ].x.value, Points[ 0 ].y.value );
PA.X := Points[ 0 ].x.value;
PA.Y := Points[ 0 ].y.value;
for i := 1 to C.cpfx - 1 do begin // DrawQSpline is called C.cpfx - 1 times
PB.X := Points[ i ].x.value;
PB.Y := Points[ i ].y.value;
PC.X := Points[ i + 1 ].x.value;
PC.Y := Points[ i + 1 ].y.value;
if i < C.cpfx - 1 then begin
PC.X := ( PC.X + PB.X ) div 2;
PC.Y := ( PC.Y + PB.Y ) div 2;
end;
for j := 1 to 8 do begin
F := j / 8;
LineTo( Action, Round( ( PA.x - 2 * PB.x + PC.x ) * Sqr( F ) + ( 2 * PB.x - 2 * PA.x ) * F + PA.x ),
Round( ( PA.y - 2 * PB.y + PC.y ) * Sqr( F ) + ( 2 * PB.y - 2 * PA.y ) * F + PA.y ) );
end;
PA := PC;
end;
end;
end;
// Update last point.
Points[ 0 ] := Points[ C.cpfx ];
end;
MoveTo( Action, Points[ 0 ].x.value, Points[ 0 ].y.value );
LineTo( Action, H.pfxStart.x.value, H.pfxStart.y.value );
until P >= Longword( Length( FBuffer ) );
end;