Wie geht das: rechtsbündiger Text mit fpPDF?

Rund um die LCL und andere Komponenten
kirchfritz
Beiträge: 227
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win11 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von kirchfritz »

Hallo,

ich möchte mit Hilfe von fpPDF eine Rechnung im PDF-Format erstellen.
Das klappt soweit so gut, nur wenn ich rechtsbündigen Text ausgeben will, versagen meine Kenntnisse.

Es gibt scheinbar nur WriteText(x,y, Zeichenkette...). Damit kann man an einer Stelle X,Y auf der Seite einen Text ausgeben.
Ich müsste aber irgendwie an die Länge der Zeichenkette "rankommen" bei gegebenem Font und gegebener Fontgröße.
Aber selbst das schaffe ich nicht.

Weiß jemand Rat, wie ich den Text rechtsbündig setzen kann?


Fritz

Benutzeravatar
theo
Beiträge: 10921
Registriert: Mo 11. Sep 2006, 19:01

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von theo »

kirchfritz hat geschrieben: Di 3. Jun 2025, 08:07 Ich müsste aber irgendwie an die Länge der Zeichenkette "rankommen" bei gegebenem Font und gegebener Fontgröße.
Vielleicht hilft dir GetTextDimsMm von hier:
viewtopic.php?p=135742#p135742

Habe ich aber länger nicht mehr ausprobiert.

Joh
Lazarusforum e. V.
Beiträge: 288
Registriert: Sa 26. Mai 2012, 17:31
OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
CPU-Target: 64Bit

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von Joh »

hmmm,
eigentlich hat jede pdf-Komponente eine Eigenschaft TextWidth...

Bei fppdf gibt es GetTextWidth; das müsste es doch sein?!
just my two Beer

kirchfritz
Beiträge: 227
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win11 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von kirchfritz »

hmmm,
eigentlich hat jede pdf-Komponente eine Eigenschaft TextWidth...

Bei fppdf gibt es GetTextWidth; das müsste es doch sein?!
Ich und mein Compiler sind der Meinung, dass es die Methode GetTextWidth in fppdf nicht gibt.

Hier mein Beispielprogramm:

Code: Alles auswählen

program rechtsbuendigerText;

{$mode objfpc}{$H+}

uses
  fppdf, fpttf;

var
  FontID, FontBoldID: Integer;
  Document: TPDFDocument;
  Section: TPDFSection;
  Page: TPDFPage;
begin
  Document := TPDFDocument.Create(nil);
  Document.FontDirectory := 'C:\Windows\Fonts';
  Document.Options := Document.Options + [poPageOriginAtTop, poNoEmbeddedFonts];
  Document.StartDocument;
  FontID := Document.AddFont('arial.ttf', 'Arial');
  FontBoldID := Document.AddFont('arialbd.ttf', 'Arial Bold');

  Section := Document.Sections.AddSection;

  Page := Document.Pages.AddPage;
  Section.AddPage(Page);

  Page.SetFont(FontID, 11);
  Page.WriteText(20, 20, UTF8Decode('Die nachfolgenden Zahlen sollen rechtsbündig zu diesem Text sein'));

  Page.SetFont(FontBoldID, 11);
  Page.WriteText(20, 30, '999999999');
  Page.WriteText(20, 36, '88888888');
  Page.WriteText(20, 42, '7777777');
  Page.WriteText(20, 48, '666666');

  Document.SaveToFile('output.pdf');
end.   
Möge der, der weiß, wie man GetTextWidth hier aufruft, dies direkt hier eintragen.
Bin für jeden Hinweis dankbar
Fritz

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1650
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von fliegermichl »

Ich hab mal im Ordner fpcsrc\packages\fcl-pdf nach "TextWidth suchen lassen und da findet sich in fpcsrc\packages\fcl-pdf\src\fppdf.pp in Zeile 444 in der Klasse TPDFText die function GetTextWidth : Single; Damit muss sich doch was anfangen lassen?

kirchfritz
Beiträge: 227
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win11 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von kirchfritz »

theo hat geschrieben: Di 3. Jun 2025, 08:50
kirchfritz hat geschrieben: Di 3. Jun 2025, 08:07 Ich müsste aber irgendwie an die Länge der Zeichenkette "rankommen" bei gegebenem Font und gegebener Fontgröße.
Vielleicht hilft dir GetTextDimsMm von hier:
viewtopic.php?p=135742#p135742

Habe ich aber länger nicht mehr ausprobiert.
Wenn ich pdfhelpers in mein Programm einbaue bekomme ich beim Kompilieren seltsame Fehlermeldungen, mit denen ich nicht umzugehen weiß:
Screenshot 2025-06-03 172313.png
Screenshot 2025-06-03 172313.png (172.19 KiB) 439 mal betrachtet
Ist jetzt auch nicht unbedingt die ersehnte Hilfe!

wp_xyz
Beiträge: 5189
Registriert: Fr 8. Apr 2011, 09:01

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von wp_xyz »

fliegermichl hat geschrieben: Di 3. Jun 2025, 17:16 Ich hab mal im Ordner fpcsrc\packages\fcl-pdf nach "TextWidth suchen lassen und da findet sich in fpcsrc\packages\fcl-pdf\src\fppdf.pp in Zeile 444 in der Klasse TPDFText die function GetTextWidth : Single; Damit muss sich doch was anfangen lassen?
Guckst du aber zwei Zeilen höher, dann steht da "private" - das heißt, die Funktion ist von außen gar nicht aufrufbar. Es gibt auch ein SetTextWidth - das Pärchen klingt nach Getter/Setter einer Property "TextWidth", aber diese gibt es auch nicht. Könnte es sein, dass der Entwickler vergessen hat, die Property zu deklarieren?

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 385
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von Jorg3000 »

Hi!
An dem Thema habe ich mir vor drei Jahren schon die Zähne ausgebissen.
Letztlich hat es damit geendet, dass ich mittels der Unit fpTTF den gleichen Zeichensatz wie im PDF rausgesucht habe und mit Angabe des DPI vom PDF die Zeichenbreiten vom Zeichensatz habe errechnen lassen.
Also alles zu Fuß. Es war nicht trivial, wenn man den richtigen Zeichensatz ggf. für Fett und Kursiv finden will.
Ich würde gerne Quellcode bereitstellen, aber es ist bei mir mit anderen Klassen verwoben, so dass ich es jetzt nicht einfach rauskopieren kann.

Benutzeravatar
theo
Beiträge: 10921
Registriert: Mo 11. Sep 2006, 19:01

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von theo »

kirchfritz hat geschrieben: Di 3. Jun 2025, 17:27 Ist jetzt auch nicht unbedingt die ersehnte Hilfe!
Ich denke schon. Man muss es halt etwas anpassen. Das war die Version für LCL, nicht für ein Kommandozeilenprog.
Das PDF Zeug ist immer eine Tüftelei, da muss man sich etwas hineindenken.
Probier nochmal so (Nur auf Linux getestet).
Dateianhänge
PDF_Archiv.zip
(6.12 KiB) 84-mal heruntergeladen

wp_xyz
Beiträge: 5189
Registriert: Fr 8. Apr 2011, 09:01

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von wp_xyz »

Ich habe mir jetzt das testfppdf Demo-Programm im fppdf-Ordner angesehen, und da gibt es eine Routine TextInABox(), die ein passgenaues Rechteck um einen vorher ausgegebenen String ausgibt. Diese muss natürlich die Textgröße bestimmen, und daher findet man dort alles. Und wenn man alles unnötige weglässt, kommt man auf folgende allgemein verwendbare Funktion (die man vielleicht noch effizierter schreiben kann, damit man nicht immer Fontname und Größe übergeben muss):

Code: Alles auswählen

uses
  Types, ...
  
function PDFTextSize(const AFontName: String; const APointSize: integer;
  const AText: String): TPointF;
var
  lFC: TFPFontCacheItem;
  lHeight: single;
  lDescenderHeight: single;
  lTextHeightInMM: single;
  lWidth: single;
  lTextWidthInMM: single;
  lDescenderHeightInMM: single;
begin
  lFC := gTTFontCache.Find(AFontName, False, False);
  if not Assigned(lFC) then
    raise Exception.Create(AFontName + ' font not found');

  lHeight := lFC.TextHeight(AText, APointSize, lDescenderHeight);
  { convert the Font Units to mm as our PDFPage.UnitOfMeasure is set to mm. }
  lTextHeightInMM := (lHeight * 25.4) / gTTFontCache.DPI;
  lDescenderHeightInMM := (lDescenderHeight * 25.4) / gTTFontCache.DPI;

  lWidth := lFC.TextWidth(AText, APointSize);
  { convert the Font Units to mm as our PDFPage.UnitOfMeasure is set to mm. }
  lTextWidthInMM := (lWidth * 25.4) / gTTFontCache.DPI;

  Result.X := lTextWidthInMM;
  Result.Y := lTextHeightInMM + lDescenderHeightInMM;
end;
Die Routine wird in dem beigefügten Mini-Programm, einer Modifikation von testfppdf für rechtsbündige Textausgabe, angewendet, so dass man sieht, dass sie funktioniert.

[EDIT]
Sorry, theo, habe gerade erst gesehen, dass in deinen PDFHelpers genau dasselbe steht...
Dateianhänge
pdf_textwidth.zip
(367.08 KiB) 81-mal heruntergeladen

kirchfritz
Beiträge: 227
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win11 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von kirchfritz »

theo hat geschrieben: Di 3. Jun 2025, 18:35 Ich denke schon. Man muss es halt etwas anpassen. Das war die Version für LCL, nicht für ein Kommandozeilenprog.
Das PDF Zeug ist immer eine Tüftelei, da muss man sich etwas hineindenken.
Probier nochmal so (Nur auf Linux getestet).
Ich habe theos Variante erfolgreich umgesetzt.
Siehe Dateianhang
PDF_Archiv_v2.zip
(27.66 KiB) 53-mal heruntergeladen
output.pdf
(25.05 KiB) 54-mal heruntergeladen
Ausstehend der Test, ob es auch mit Nicht-Standard Fonts funktioniert.
Danke theo!

Benutzeravatar
theo
Beiträge: 10921
Registriert: Mo 11. Sep 2006, 19:01

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von theo »

kirchfritz hat geschrieben: Mi 4. Jun 2025, 08:29 Ausstehend der Test, ob es auch mit Nicht-Standard Fonts funktioniert.
Eigentlich gibt es drei Arten in diesem System.

PDF Standard (Eingebaute) Fonts. Die "Metrics" dafür stehen in "fontmetrics_stdpdf.inc"
Bsp: StdFtHelvetica := Document.AddFont('Helvetica');

Systemfonts (Installierte)
Bsp: ArialItalic := Document.AddSystemFont('Arial', False, True);

Andere Fontdateien, die nicht installiert sind.
Bsp: FreeSans := Document.AddFont('/home/theo/lazarus/projects/pdf/fonts/FreeSans.ttf', 'FreeSans');

Benutzeravatar
Zvoni
Beiträge: 396
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von Zvoni »

fliegermichl hat geschrieben: Di 3. Jun 2025, 17:16 Ich hab mal im Ordner fpcsrc\packages\fcl-pdf nach "TextWidth suchen lassen und da findet sich in fpcsrc\packages\fcl-pdf\src\fppdf.pp in Zeile 444 in der Klasse TPDFText die function GetTextWidth : Single; Damit muss sich doch was anfangen lassen?
Oder besser in
fpcsrc\packages\fcl-pdf\src\fpttf.pp in Zeile 44ff (TFPFontCacheItem)
Da ist TextWidth Public
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

kirchfritz
Beiträge: 227
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win11 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von kirchfritz »

theo hat geschrieben: Mi 4. Jun 2025, 09:19
kirchfritz hat geschrieben: Mi 4. Jun 2025, 08:29 Ausstehend der Test, ob es auch mit Nicht-Standard Fonts funktioniert.
Eigentlich gibt es drei Arten in diesem System.

PDF Standard (Eingebaute) Fonts. Die "Metrics" dafür stehen in "fontmetrics_stdpdf.inc"
Bsp: StdFtHelvetica := Document.AddFont('Helvetica');

Systemfonts (Installierte)
Bsp: ArialItalic := Document.AddSystemFont('Arial', False, True);

Andere Fontdateien, die nicht installiert sind.
Bsp: FreeSans := Document.AddFont('/home/theo/lazarus/projects/pdf/fonts/FreeSans.ttf', 'FreeSans');
Das Laden eines nicht installierten Font funktioniert irgendwie nicht so richtig:
Das ist mein Versuch:

Code: Alles auswählen

  if not FileExists('\fonts\NotoSansSymbols-Regular.ttf') then
  begin
    Writeln('Fontdatei nicht gefunden: '+ 'fonts\NotoSansSymbols-Regular.ttf');
    exit;
  end;
  AndererFontID := Document.AddFont('fonts\NotoSansSymbols-Regular.ttf','NotoSansSymbols-Regular');
Document.AddFont wirft exception mit "font not found", obwohl die TTF-Datei im Dateisystem vorhanden.
Was mache ich verkehrt?

Benutzeravatar
theo
Beiträge: 10921
Registriert: Mo 11. Sep 2006, 19:01

Re: Wie geht das: rechtsbündiger Text mit fpPDF?

Beitrag von theo »

Was sind das für Pfade? Windows?
Bei FileExists hast du ein "\" am Anfang, bei AddFont nicht.
Mach doch vollständige Windows Pfade (C:\Meinpfad...).

Antworten