Teknisk artikkel

Legge til tekst i PDF-er i Delphi med HotPDF TextOut og Font-metoder

Å få tekst ut på en PDF-side ser enkelt ut til du innser at PDF ikke gir deg noen flyt av innhold (document flow). Det er ingen <br> eller automatisk ord-innpakning. PDF er en sidebeskrivelsesstandard der hver streng er plassert på en absolutt matematisk posisjon. HotPDF tilbyr tre lag med tekstutdata som bygger på hverandre: rå, fast posisjon med TextOut, avgrensningsbokser med TextRect for justering, og MultiCell-avsnitt for tekst som brytes og sprer seg

Koordinatsystemet er fra bunnen og opp

En typisk Delphi-utvikler, som har brukt år på å tegne til en TCanvas, forventer en Y-akse som starter ved null øverst og vokser nedover. PDF gjør det motsatte. Standard opprinnelse (0,0) er det nederste venstre hjørnet av siden. Y-verdier øker når du beveger deg oppover siden

Når du plasserer en 12-punkts font på Y = 100, faller bunnen av teksten (grunnlinjen) på den koordinaten, og toppen av teksten når opp til 112. Dette gjelder alle kall som har X- og Y-parametere direkte. En US Letter-side er 612 punkter bred og 792 punkter høy, så TextOut(50, 750, ...) plasserer et ord nær øverste venstre marg

Sette opp pennen: Skrifttype (Font) og farge

I PDF bærer ikke teksten selv stil. Siden har en tekst-tilstand ("text state"), som inkluderer den gjeldende skrifttypen, størrelsen og utfyllingsfargen (fill color). Du setter den tilstanden én gang, og hvert påfølgende tekstkall bruker den inntil du setter den til noe annet

var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := 'TextDemo.pdf';
    Pdf.BeginDoc;

    // Angi fonten til Arial, Standard (ingen stilflagg), 14pt
    Pdf.CurrentPage.SetFont('Arial', [], 14);
    
    // Sett fyllfargen (tekstfargen). Du kan bruke Delphis cl-konstanter
    Pdf.CurrentPage.SetRGBFillColor(clBlack);

    // Kaller TextOut(X, Y, Rotasjonsvinkel, Streng)
    Pdf.CurrentPage.TextOut(50, 750, 0, 'Svart 14pt overskrift');

    // Endre tilstand for neste avsnitt
    Pdf.CurrentPage.SetFont('Times New Roman', [fsItalic], 10);
    Pdf.CurrentPage.SetRGBFillColor(RGB(100, 100, 100)); // En mørkegrå
    Pdf.CurrentPage.TextOut(50, 720, 0, 'Grå 10pt kursiv tekst under den');

    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

De 3 utdatametodene

1. TextOut: Ren og fast

TextOut tar nøyaktig X og Y for hvor strengen skal begynne. Det er ingen justering eller ord-innpakning. Strengen vil kjøre utenfor den høyre kanten av siden hvis den er for lang. Det du imidlertid får er en rotasjonsvinkel: Pdf.CurrentPage.TextOut(100, 100, 90, 'Vertikal'); skriver ordet rett opp

2. TextRect: Den justerte avgrensningsboksen

Når du genererer tabeller, skjemaer eller sidehoder, trenger du høyrestilling av tall, eller midtstilling av kolonneoverskrifter. Det er hva TextRect er til for. Du forsyner den med en boks (et rektangel for formålets skyld) og et justeringsflagg. Den bryter ikke teksten, men den vil bruke justeringsmatematikk basert på boksens grenser. Avgrensningsboks-argumentene er X og Y (nederst til venstre hjørne av cellen), pluss bokshøyde og -bredde

  // Høyrejuster et beløp innenfor en 200pt bred boks ved X=300
  // Parametere: LeftX, BottomY, Width, Height, Text, Alignment
  Pdf.CurrentPage.TextRect(300, 600, 200, 20, '$1,250.00', hjRight);
  
  // Midtstill en tittel inni en boks over en bestemt kolonne
  Pdf.CurrentPage.TextRect(50, 600, 150, 20, 'Overskrift', hjCenter);

3. MultiCell: Linjebryting av lange avsnitt

Hvis teksten din stammer fra brukerinndata eller en databasememo, aner du ikke hvor lang den er. Å mate den til TextOut vil bare produsere én enkelt, ubrutt linje av blekk som renner ut av høyre side av arket. MultiCell er funksjonen som beregner ordbryting. Du angir margene den må respektere, og metoden skyver markøren ned en linjehøyde for hver retur og hvert ord som ikke får plass, og bygger et rektangel av løpende tekst

  // MultiCell(X, Y, Width, Height, Text)
  // X og Y definerer panelets ØVRE VENSTRE hjørne,
  // som er et sjeldent unntak fra regelen om opprinnelse nede til venstre for layout!
  Pdf.CurrentPage.SetFont('Arial', [], 10);
  Pdf.CurrentPage.MultiCell(50, 500, 400, 200, 
    'Dette er et langt avsnitt som vil bli brutt og stilt opp ' +
    'mot høyre grense av 400pt boksen. Linjeskift '#13#10 + 
    'respekteres også og tvinger neste ord til neste rad ned.');

Advarsel: I motsetning til TextOut, refererer Y i MultiCell vanligvis til toppen av blokken for layoutformål, noe som gjør at innhold kan flyte nedover inne i rektanglet ditt. Sjekk alltid utdataene dine når du blander TextOut (bunnopp-logikk) med rektangel-byggere

Den manglende brikken: Måling av tekst i koden

Ofte vil du ønske å kombinere skrifttype og stiler i samme setning, for eksempel "Summen er $500.00 i dag". Du kan ikke gjøre det med ett enkelt kall fordi, igjen, strengen selv inneholder ikke utheving. Du må skrive den første halvdelen, bytte skrifttype til uthevet (bold), og skrive den andre halvdelen nøyaktig der den første slapp

Hvordan vet du hvor den første slapp? Du bruker TextWidth. Denne metoden ser på strengen og den gjeldende fonttilstanden, og returnerer den nøyaktige poengbredden (point width) for det blekket. Ved å beregne bredden før du tegner, kan du lenke sammen flere tekstkall og variere stilene sømløst over en setning

For en dypdykning i tekstjustering på tvers av en felles grunnlinje (baseline), se artikkelen om generering av komplekse rapporter

Tekst- og fontmetodene vist her er en del av HotPDF-komponenten for Delphi og C++Builder