// Hiermit kann man
Strings endtlang einer Bézierkurve ausgeben. Die Grundidee
uses Types, Math;
var
Tabelle: array [#32 .. chr(65276)] of Integer;
ok: Boolean = false;
Canv: TCanvas;
procedure TForm1.FormCreate(Sender: TObject);
begin
Canv := Form1.Canvas; // <<< Hier die entsprechende Zeichenfläche festlegen
ok := GetCharWidth32W(Canv.Handle, 32, 65276, Tabelle[#32]);
end;
function Dist2(a, b: TPoint): single;
var
dx, dy: single;
begin
dx := sqr(a.X - b.X);
dy := sqr(a.Y - b.Y);
result := sqrt(dx + dy);
end;
function GetPtdst(pt: TPoint; dist: Integer; angle: single): TPoint;
begin
result.X := round(dist * cos(angle));
result.Y := -round(dist * sin(angle));
inc(result.X, pt.X);
inc(result.Y, pt.Y);
end;
function PDist2(a, b: TPoint; relativea: single): TPoint;
begin
if b.X = a.X then
result.X := b.X
else
result.X := a.X + round((b.X - a.X) * relativea);
if b.Y = a.Y then
result.Y := b.Y
else
result.Y := a.Y + round((b.Y - a.Y) * relativea);
end;
function Angleab(a, b: TPoint): single;
begin
dec(b.X, a.X);
dec(b.Y, a.Y);
with b do
if X = 0 then
begin
result := pi / 2;
if Y > 0 then
result := 3 * result;
end
else
begin
result := arctan2(-Y, X);
if result < 0 then
result := result + pi * 2;
end;
end;
function AnglechO(cn: TCanvas; pt: TPoint; c: char; bogenmss: single;
offsX, offsY: Integer): Boolean;
var
lf: TLogFont;
OldFontHdl, NewFontHdl: HFont;
angle: Integer;
p2: single;
begin
angle := round(bogenmss * 180 / pi);
if angle > 180 then
angle := angle - 360;
inc(angle, ord(angle = 0));
p2 := pi / 2;
with cn do
begin
if GetObject(Font.Handle, SizeOf(lf), @lf) = 0 then
begin
result := false;
exit;
end;
lf.lfEscapement := angle * 10;
lf.lfOrientation := angle * 10;
lf.lfOutPrecision := OUT_TT_ONLY_PRECIS;
NewFontHdl := CreateFontIndirect(lf);
OldFontHdl := selectObject(Handle, NewFontHdl);
if offsX < 0 then
pt := GetPtdst(pt, -offsX, bogenmss + pi)
else if offsX > 0 then
pt := GetPtdst(pt, offsX, bogenmss);
if offsY < 0 then
pt := GetPtdst(pt, -offsY, bogenmss + p2)
else if offsY > 0 then
pt := GetPtdst(pt, offsY, bogenmss - p2);
TextOut(pt.X, pt.Y, c);
selectObject(Handle, OldFontHdl);
DeleteObject(NewFontHdl);
result := true;
end;
end;
procedure TextKurve(cn: TCanvas; Pts: array of TPoint; const s: string);
var
i, j, ptCnt, txtLpx, txtLch, vertOffset: Integer;
CcInsDst, chWd2: Integer;
pt: TPoint;
flatPts: array of TPoint;
tps: array of byte;
distances: array of single;
dummyPtr: pointer;
angle, spcPxls, bezierLen, relDstP1: single;
begin
if not ok then
raise exception.Create('Die Belegung der Tabelle ist fehlgeschlagen.');
if Trim(s) = '' then
raise exception.Create('Es wurde kein Text gefunden.');
if high(Pts) mod 3 <> 0 then
raise exception.Create('Die Anzahl der Punkte ist unzulässig.');
txtLch := length(s);
with cn do
begin
BeginPath(Handle);
PolyBezier(Pts);
EndPath(Handle);
FlattenPath(Handle);
dummyPtr := nil;
ptCnt := GetPath(Handle, dummyPtr, dummyPtr, 0);
if ptCnt < 1 then
raise exception.Create('Der Schriftpfad wurde nicht ermittelt.');
setLength(flatPts, ptCnt);
setLength(tps, ptCnt);
setLength(distances, ptCnt);
GetPath(Handle, @flatPts[0], @tps[0], ptCnt);
distances[0] := 0;
bezierLen := 0;
for i := 1 to ptCnt - 1 do
begin
bezierLen := bezierLen + Dist2(flatPts[i], flatPts[i - 1]);
distances[i] := bezierLen;
end;
txtLpx := 0;
for i := 1 to txtLch do
inc(txtLpx, Tabelle[s[i]]);
if txtLch = 1 then
spcPxls := 0
else
spcPxls := (bezierLen - txtLpx) / (txtLch - 1);
SetBkMode(Handle, TRANSPARENT);
vertOffset := -trunc(2 / 3 * TextHeight('Äy'));
j := 1;
CcInsDst := 0;
for i := 1 to txtLch do
begin
chWd2 := Tabelle[s[i]] div 2;
inc(CcInsDst, chWd2);
while (j < ptCnt - 1) and (distances[j] < CcInsDst) do
inc(j);
if distances[j] = CcInsDst then
pt := flatPts[j]
else
begin
relDstP1 := (CcInsDst - distances[j - 1]) /
(distances[j] - distances[j - 1]);
pt := PDist2(flatPts[j - 1], flatPts[j], relDstP1);
end;
angle := Angleab(flatPts[j - 1], flatPts[j]);
if not AnglechO(cn, pt, s[i], angle, -chWd2, vertOffset) then
raise exception.Create('Die benötigte Schrift wurde nicht erstellt.');
inc(CcInsDst, chWd2 + trunc(spcPxls) + round(frac(spcPxls * i)));
end;
end;
end;
// Beispiel Bézierkurve (Bild 1)
procedure TForm1.Button1Click(Sender: TObject);
var
pt: array [0 .. 6] of TPoint;
begin
Canv.Font.Color := clRed;
Canv.Font.Name := 'Arial';
Canv.Font.Size := 16;
pt[0] := Point(125, 200);
pt[1] := Point(150, 250);
pt[2] := Point(225, 250);
pt[3] := Point(225, 175);
pt[4] := Point(275, 100);
pt[5] := Point(350, 100);
pt[6] := Point(350, 200);
TextKurve(Canv, pt, 'Das ist ein Versuch');
// nur zur Kontrolle:
Canv.Pen.Style := psDot;
Canv.PolyBezier(pt);
end;
// Beispiel Kreis (Bild 2)
procedure Kreis(cn: TCanvas; X, Y, Abstand, fSize: Integer; fName, txt: String;
cl: TColor);
var
pt: Array [0 .. 6] of TPoint;
a2, a15: Integer;
begin
cn.Font.Size := fSize;
cn.Font.Name := fName;
cn.Font.Color := cl;
a2 := Abstand * 2;
a15 := round(Abstand * 1.5);
pt[0] := Point(X + Abstand, Y);
pt[1] := Point(X + a2, Y);
pt[2] := Point(X + a2, Y + a15);
pt[3] := Point(X + Abstand, Y + a15);
pt[4] := Point(X, Y + a15);
pt[5] := Point(X, Y);
pt[6] := pt[0];
TextKurve(cn, pt, txt);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Kreis(Canv, 120, 100, 150, 14, 'Arial',
'Das ist einer von mehreren Versuchen. ', clBlack);
end;
// 2 Beispiele für Halbkreise
Procedure HalbKreisOben(cn: TCanvas; X, Y: Integer; const txt: String);
var
pt: array [0 .. 3] of TPoint;
M, M2: Integer;
begin
M := 145;
M2 := round(M * 1.5);
pt[0] := Point(X, Y + M);
pt[1] := Point(X, Y);
pt[2] := Point(X + M2, Y);
pt[3] := Point(X + M2, Y + M);
TextKurve(cn, pt, txt);
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
Canv.Font.Color := clRed;
Canv.Font.Size := 14;
Canv.Font.Name := 'Arial';
HalbKreisOben(Canv, 160, 65, 'Das ist ein Test');
end;
Procedure HalbKreisLinks(cn: TCanvas; X, Y: Integer; const txt: String);
var
pt: array [0 .. 3] of TPoint;
M, M2: Integer;
begin
M := 145;
M2 := round(M * 1.5);
pt[0] := Point(X + M, Y + M2);
pt[1] := Point(X, Y + M2);
pt[2] := Point(X, Y);
pt[3] := Point(X + M, Y);
TextKurve(cn, pt, txt);
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
Canv.Font.Color := clGreen;
Canv.Font.Name := 'Arial';
Canv.Font.Size := 14;
HalbKreisLinks(Canv, 120, 100, 'Das ist ein Versuch');
end;
|
Zugriffe seit 6.9.2001 auf Delphi-Ecke





