![]() |
Algorithmus für Text zu Polygon/TPath (Vector)
Hi,
ich hätte gerne die Möglichkeit einen Text mit bestimmter Schriftart zu einem Polygon (oder vielleicht ![]() Ich dachte dabei, dass ich den Text (gross genug) auf ein TBitmap zeichnen lasse und das gezeichnete dann mit einem Algorithmus "scanne". Gibt es da gute und schnelle Algorithmen die das auch schön hinbekommen? Wie macht man z.B. Buchstaben mit Leerräumen dazwischen? Da müsste ich doch mit mehreren Polygonen arbeiten oder? Freundliche Grüsse |
AW: Algorithmus für Text zu Polygon/TPath (Vector)
Wenn es für TrueType Fonts reicht, könnte
![]() |
AW: Algorithmus für Text zu Polygon/TPath (Vector)
Hallo Uwe,
Danke für den Link. Sitze leider gerade im Zug und kann erst morgen das ganze genauer in der IDE ansehen. Auch scheint mir der Code zu sehr von der Windows API abzuhängen. (z.B. GetGlyphOutline/GetGlyphOutlineW und diverse andere Klassen/Strukturen die wichtig zu sein scheinen) Das müsste jedoch auch auf Android laufen, wenn das schon implementiert werden soll. Ich weiss wie gesagt leider nicht was da im Hintergrund passiert aber ich dachte zunächst an etwas wie den ![]() PS: Die erste Version des Source Codes ist 2 Monate jünger als ich. :lol: Das ganze Pointergedöns hätte mir aber Angst eingejagt. :stupid: Freundliche Grüsse |
AW: Algorithmus für Text zu Polygon/TPath (Vector)
Im Wesentlichen interpretiert man hier die Vektordefinition des TrueType. Für andere Plattformen müsste man das aber noch selbst implementierten.
|
AW: Algorithmus für Text zu Polygon/TPath (Vector)
Hi,
habe vorhin angefangen das Ding einfach irgendwie zu implementieren, was (sehr unerwartet) sehr gut funktioniert hat. Beim optimieren bin ich jedoch auf ![]() ![]() Beispielcode mit leerem Formular (Nur das OnPaint Event reicht zum testen):
Delphi-Quellcode:
Mehr infos:
procedure TForm1.FormPaint(Sender: TObject; Canvas: TCanvas;
const [Ref] ARect: TRectF); var LTextLayout : TTextLayout; LPathData : TPathData; begin Canvas.Font.Family := 'Comic Sans MS'; Canvas.Font.Size := 128; LTextLayout := TTextLayoutManager.DefaultTextLayout.Create; try LPathData := TPathData.Create; try LTextLayout.Text := '@'; LTextLayout.Font := Canvas.Font; LTextLAyout.ConvertToPath(LPathData); // Magic Canvas.Fill.Color := $FF0070FF; Canvas.FillPath(LPathData,1); Canvas.Stroke.Color := $FF000000; Canvas.DrawPath(LPathData,1); finally LPathData.Free; end; finally LTextLayout.Free; end; end; ![]() Ich hoffe das auch andere hiervon Gebrauch machen können. Ich mag es wie Firemonkey schon sehr vieles von Haus aus mitbringt auch wen einiges ab und zu mal buggy ist aber seit ich für Freizeitprojekte Firemonkey benutze, schreibe ich viel weniger Nebensächlichen Code den man zwar immer braucht, aber auch immer wieder neu schreibt weil das meist nur einige Zeilen sind. Da bleibt mehr Zeit für das eigentliche Vorhaben ;) Freundliche Grüsse |
AW: Algorithmus für Text zu Polygon/TPath (Vector)
Hallo Milos,
hier ist noch ein "grober" Versuch Text in einen Pfad zu rendern unter FMX. Jedenfalls hatte ich immer Probleme mit dem Scaling untern verschiedenen Plattformen, und auch davon einen Screenshot zu machen hatte diverse Probleme. Mit viel manuellen Korrekturen läuft es, aber ob es auf allen Geräten gleich aussieht kann ich nicht garantieren. Ich will den Text erst im 0,0 Punkt mittig zentrieren, dann drehen und verschieben, und an die finale Position positioinieren. Das alles mit den Matrizen. Vielleicht hilft dir das ja auch it´rgendwie weiter.
Delphi-Quellcode:
Rollo
procedure TS4Shape.PaintToLayout_Text(Canvas: TCanvas; const ARect: TRectF);
var ptS, ptE, ptC: TPointF; // sAng: Single; // mtrx: TMatrix; // mtrxOfs: TMatrix; // sAngL: Single; F_Arm : Single; len : Single; // mtrxTrn: TMatrix; // mtrxRot: TMatrix; // rcText: TRectF; // szBmp: TSizeF; // MState: TMatrix; // ptVP: TPointF; // sSclC: Single; // sSclCP: Single; // sSclP: Single; // sSclB: Single; // sSclSC: Single; pd: TPathData; ang: Single; rcImg: TRectF; lenOfs: Single; sHeight: Single; rcTxt: TRectF; sScale: Single; mat: TMatrix; sSclScrn: Single; sSclCan: Single; sSclBmp: Single; bOrientH: Boolean; FScrn: IFMXScreenService; sGetScrnScale: Single; sTxtFak: Single; // bIsTablet: Boolean; begin // New Approach 24.04.16 if FShapes.IsSuppressText then begin Exit; // Don'T want Text here end; sGetScrnScale := 1.0; if TPlatformServices.Current.SupportsPlatformService( IFMXScreenService, FScrn) then begin sGetScrnScale := FScrn.GetScreenScale; FScrn := nil; end; // New Approach 24.04.16 pd := TPathData.Create; try if (FText <> '') and (FSelPtsTextIdx[0] >= 0) and (FSelPtsTextIdx[1] >= 0) then begin pd.Clear; rcImg := RectF(0, 0, Min(Canvas.Width, Canvas.Height), Max(Canvas.Width, Canvas.Height) ); if Canvas.TextToPath(pd, rcImg, // RectF(0, // 0, // Min(Canvas.Width, Canvas.Height), // Max(Canvas.Width, Canvas.Height)), FText, True, TTextAlign.Center, TTextAlign.Leading ) then begin ptS := FSelPtsList.Items[FSelPtsTextIdx[0]].Position.Point; ptE := FSelPtsList.Items[FSelPtsTextIdx[1]].Position.Point; len := ptS.Distance( ptE ); if len >= 10 then begin // Retrieve ScreenOrient bOrientH := TS4View_Manager.Orientation_Current_IsPortrait; ang := ptS.Angle( ptE ) + Pi; // As Radian ptC := (ptS + ptE) / 2; if FSelPtsList.Count >= 3 then FSelPtsList.Items[2].Position.Point := ptC else ptC := ptC; // FLine.Center.Offset ang + Pi/2; // Turn 90° // if bOrientH then F_Arm := ang - Pi * 0.5; // 90° direction angFac; // - for L-Arm + for R-Arm // else // F_Arm := ang + Pi * 0.5; // 90° direction angFac; // - for L-Arm + for R-Arm // len := TextSize * sSclB * sSclP * FShapes.ScaleShapes * 1.0; // mtrxOfs := TMatrix.CreateTranslation(Cos(FL) * len, Sin(FL) * len); // rcImg := RectF(0, 0, Canvas.Width, Canvas.Height); pd.FitToRect( rcImg ); lenOfs := pd.GetBounds.Height; sSclScrn := sGetScrnScale; sSclCan := Canvas.Scale; sSclBmp := FShapes.GetImgViewCtrl.Bitmap.BitmapScale; sHeight := rcImg.Width; // Min(Canvas.Width, Canvas.Height ); sHeight := sHeight / 6; // sHeight := 40; {$IFDEF MSWINDOWS} // sHeight := 80; {$ENDIF MSWINDOWS} {$IFDEF MACOS} // sHeight := 80; {$ENDIF MACOS} {$IF DEFINED(IOS) or DEFINED(ANDROID)} {$IF DEFINED(IOS)} sHeight := 40; {$ENDIF DEFINED(IOS)} {$IF DEFINED(ANDROID)} sHeight := 20; {$ENDIF DEFINED(ANDROID)} if sSclScrn <= 2 then begin sHeight := sHeight * 1.5; end else begin sHeight := sHeight / 1.5; end; if not FShapes.IsInMakeScreenshot then sHeight := sHeight * sSclScrn; {$ENDIF DEFINED(IOS) or DEFINED(ANDROID)} rcTxt := RectF(0,0, len * sSclScrn, sHeight * sSclScrn); // Height/Size of Text sTxtFak := 1.5; //!!! Hier ist der Faktor der die Größe bestimmt ?? if FText.Length >= 3 then begin sTxtFak := sTxtFak * (Min(Max(FText.Length, 2), 10) / 6); // Get TextLen dependend Factor lenOfs := lenOfs * 0.95; end else begin sTxtFak := sTxtFak * (Min(Max(FText.Length, 1), 10) / 7); // Get TextLen dependend Factor lenOfs := lenOfs * 0.80; end; rcImg.FitInto(rcTxt, sScale); if sScale > 0.0 then sScale := Max(0.1, 1 / sScale) * sTxtFak else sScale := Max(0.1, 1 / 1.0) * sTxtFak; lenOfs := 1.05 * lenOfs * sScale; mat := TMatrix.Identity; // Center at 0/0 mat := mat * TMatrix.CreateTranslation( -rcImg.Width /2, // -Canvas.Width /2, -rcImg.Height/2); // -Canvas.Height/2 ); // Scale to TextRect mat := mat * TMatrix.CreateScaling(sScale, sScale); // Rotate to TextRect mat := mat * TMatrix.CreateRotation( ang ); // ang ); // Translate OffCenter, to Upper Line // if bOrientH then mat := mat * TMatrix.CreateTranslation( Cos(F_Arm) * lenOfs, Sin(F_Arm) * lenOfs); // else // mat := mat * TMatrix.CreateTranslation( Cos(F_Arm) * lenOfs * 4, // Sin(F_Arm) * lenOfs * 4); // Translate to TextRect Center mat := mat * TMatrix.CreateTranslation( ptC.X, // + rcTxt.Width /2, ptC.Y // + rcTxt.Height/2 ); ); pd.ApplyMatrix( mat ); Canvas.Stroke.Color := Canvas.Fill.Color; Canvas.FillPath( pd, 1); Canvas.DrawPath( pd, 1); end; end; end; finally pd.Free; end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz