AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Algorithmus für Text zu Polygon/TPath (Vector)

Ein Thema von milos · begonnen am 24. Jul 2016 · letzter Beitrag vom 25. Jul 2016
Antwort Antwort
Benutzerbild von milos
milos

Registriert seit: 14. Jul 2008
Ort: Bern (CH)
510 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: Algorithmus für Text zu Polygon/TPath (Vector)

  Alt 25. Jul 2016, 01:11
Hi,

habe vorhin angefangen das Ding einfach irgendwie zu implementieren, was (sehr unerwartet) sehr gut funktioniert hat.
Beim optimieren bin ich jedoch auf Delphi-Referenz durchsuchenFMX.TextLayout gestossen welche die Klasse Delphi-Referenz durchsuchenTTextLayout beinhaltet, die es anscheinend ermöglicht auf jeder Platform einen Text mit gewünschtem Font in ein TPathData umzuwandeln.

Beispielcode mit leerem Formular (Nur das OnPaint Event reicht zum testen):
Delphi-Quellcode:
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;
Mehr infos: http://riversoftavg.com/blogs/index....text-with-fmx/

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
Milos

Geändert von milos (25. Jul 2016 um 01:16 Uhr)
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.222 Beiträge
 
Delphi 12 Athens
 
#2

AW: Algorithmus für Text zu Polygon/TPath (Vector)

  Alt 25. Jul 2016, 13:38
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:
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;
Rollo

Geändert von Rollo62 (25. Jul 2016 um 13:42 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:32 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-2025 by Thomas Breitkreuz