在给定的TrueType字体中的b样条坐标的情况下,在x,y空间中绘制直线的公式是什么?
答案 0 :(得分:2)
请注意,Truetype允许在字形定义中使用bspline曲线和直线。
如果您需要将这些命令更改为一系列MoveTo和LineTo,您可以使用以下内容:
将TrueType数据转换为提示坐标列表。这是您的操作系统可以为您做的事情(以下代码使用Windows API)。
遍历所有坐标并将曲线转换为直线(请参阅下面的代码片段):
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;