Teknisk artikel

HotPDF TextOut i Delphi: Størrelse, stil, rotation og afstand

Hver synlig streng i et HotPDF-dokument ankommer via ét kald: TextOut(X, Y, angle, Text). Hello World-eksemplet bruger det på sin mest simple måde, med skrifttypen indstillet én gang og fire argumenter efterladt ved fornuftige standarder. Ud over den første side bærer de samme fire argumenter hele vægten af layoutet. Det tredje argument roterer tekstforløbet. Skrifttypen, der er indstillet lige før, bestemmer størrelse og stil. Og X, Y-parret, målt fra sidehjørnet i punkter, er det eneste, der står mellem en ren rapport og tekst, der overlapper, klippes eller glider en linje lavere på en andens printer. Det er her TextOut tjener sine penge, og hvor standarderne holder op med at være nok

Signaturen er værd at huske før noget andet: X og Y er Single i punkter, angle er en Extended i grader, og Text er en WideString, så Unicode passerer igennem uden et separat kald. En anden overbelastning tager et PWORD plus en længde til når du allerede har glyph-koder, men for almindelige strenge er WideString-formen den, du rækker ud efter

Størrelse og stil kommer fra SetFont, ikke TextOut

TextOut har ingen størrelsesparameter. Størrelsen, vægten, hældningen, alt dette lever i SetFont-kaldet, der går forud for forløbet, og det forbliver i kraft, indtil det næste SetFont erstatter det. Det er den ene kendsgerning, der forklarer det meste af den første dags forvirring: en linje bliver fed, fordi noget tre kald tidligere indstillede [fsBold], og intet ryddede det

Pdf.CurrentPage.SetFont('Times New Roman', [], 24);
Pdf.CurrentPage.TextOut(72, 740, 0, 'Quarterly Report');        // 24pt regular

Pdf.CurrentPage.SetFont('Times New Roman', [fsBold], 12);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Revenue');                 // 12pt bold

Pdf.CurrentPage.SetFont('Times New Roman', [fsItalic], 11);
Pdf.CurrentPage.TextOut(72, 694, 0, 'figures in thousands');    // 11pt italic

Pdf.CurrentPage.SetFont('Courier New', [fsBold, fsItalic], 10);
Pdf.CurrentPage.TextOut(72, 676, 0, '  +18.4% YoY');            // styles combine

Det andet argument er et TFontStyles-sæt, så [fsBold, fsItalic] er fed kursiv og [] er almindelig. Størrelsen er i punkter, den samme enhed som koordinaterne, hvilket gør lodret afstand nem at tænke over: en 12-punkts linje kræver omtrent 14 til 16 punkters lodret trin for at ånde, så at sænke Y med 14 pr. linje er en fornuftig startlinjeafstand. Der er ingen automatisk linjefremføring. Du beregner hver grundlinje selv, hvilket er kedeligt for et afsnit, men nøjagtigt for en formular, hvor hvert felt sidder ved en fast koordinat

To praktiske bemærkninger om skrifttypenavnet. Det løses mod de skrifttyper, der er installeret på bygge-maskinen, og uanset hvad operativsystemet returnerer, er det, der bliver indlejret, så et navn, der løses på dit skrivebord, og et navn, der løses på en bygge-server, er ikke garanteret at være den samme skrifttype. Og skrifttypen skal dække de scripts, der er i strengen. Et forløb af kyrillisk eller CJK-tekst under en skrifttype, der kun er latinsk, gengives som manglende glyph-bokse uden fejl, hvilket er grunden til, at Hello World-siden rækker ud efter en bred Unicode-skrifttype, når den blander sprog

HotPDF TextOut-side, der viser Arial, Times New Roman og Courier New gengivet med almindelig, fed og kursiv stil på tværs af flere tegnsæt

Vinkelargumentet roterer omkring ankeret

Det tredje argument er det, de fleste koder efterlader på nul for evigt. Videregiv en værdi, der ikke er nul, og forløbet roterer mod uret omkring sit eget (X, Y)-anker, nederst til venstre for teksten, med det antal grader. Ankeret i sig selv bevæger sig ikke, så den samme koordinat, der placerede en vandret etiket, placerer dens roterede tvilling; kun retningen, som glyfferne marcherer, ændres

Pdf.CurrentPage.SetFont('Arial', [fsBold], 11);

// A vertical axis label down the left margin: 90 degrees reads bottom-to-top.
Pdf.CurrentPage.TextOut(40, 300, 90, 'Units sold');

// A diagonal DRAFT watermark across the page body.
Pdf.CurrentPage.SetFont('Arial', [fsBold], 60);
Pdf.CurrentPage.TextOut(150, 250, 45, 'DRAFT');

// Column headers tilted 60 degrees so long labels fit a narrow table.
Pdf.CurrentPage.SetFont('Arial', [], 9);
Pdf.CurrentPage.TextOut(120, 600, 60, 'Q1 actual');
Pdf.CurrentPage.TextOut(160, 600, 60, 'Q2 actual');

Halvfems grader er det almindelige tilfælde, en etiket, der løber op ad siden af et diagram eller en rygtitel. Fyrretyve grader håndterer vippede kolonneoverskrifter, tricket, der lader en bred etiket sidde over en smal kolonne uden at spilde over i sine naboer. Rotation ændrer ikke på, hvordan ankeret fortolkes, hvilket snyder folk: et 90-graders forløb starter stadig ved (X, Y) og vokser opad derfra, så for at centrere en roteret etiket justerer du ankeret, ikke vinklen. Når flere roterede forløb deler en grundlinje, skal du give dem det samme Y og træde X, nøjagtigt som du ville træde Y for stablede vandrette linjer

Placering af koordinater uden at gætte

Koordinater er den del, der overlever en gennemgang eller stille og roligt fejler. HotPDF måler fra nederste venstre hjørne af siden, Y vokser opad, i punkter på 72 pr. tomme. En US Letter-side er 612 gange 792 punkter; A4 er 595 gange 842. En tommes topmargen på Letter placerer derfor din første grundlinje nær Y = 792 minus 72 minus skriftstørrelsen, ikke ved et lille tal nær toppen. Enhver, der ankommer fra skærmkoordinater, hvor Y vokser nedad fra nul, skriver den første linje uden for den nederste kant og bruger ti minutter på at undre sig over, hvor den blev af

Behandl layout som aritmetik mod navngivne ankre i stedet for en kolonne af magiske tal. En venstre margen, en løbende grundlinje, du dekrementerer pr. linje, og en fast linjeafstand forvandler en blok af etiketter til en kort løkke i stedet for en væg af bogstaver:

const
  LeftMargin = 72;        // 1 inch in
  TopBaseline = 720;       // first line, ~1 inch down on Letter
  Leading = 16;            // vertical step between lines
var
  Y: Single;
  Line: string;
begin
  Pdf.CurrentPage.SetFont('Arial', [], 11);
  Y := TopBaseline;
  for Line in ReportLines do
  begin
    Pdf.CurrentPage.TextOut(LeftMargin, Y, 0, Line);
    Y := Y - Leading;
    if Y < 72 then            // bottom margin reached
    begin
      Pdf.AddPage;
      Pdf.CurrentPage.SetFont('Arial', [], 11);  // font resets on a new page
      Y := TopBaseline;
    end;
  end;
end;

Sideinddelingsvagten er den linje, alle glemmer først, og feltet rammer hårdest. Der er intet flow-layout under TextOut. Dekrementér forbi den nederste margen, og teksten fortsætter med at tegne ned i rendestenen, ud af siden, ind i ingenting, uden advarsel. Så du holder selv øje med Y, kalder AddPage, når det krydser gulvet, og nulstiller grundlinjen. SetFont efter AddPage er ikke valgfri polstring: den aktuelle skrifttype overlever ikke et sideskift, og det første forløb på den nye side kommer ud i fremviserens standardskrifttype, hvis du springer det over

Tegn- og ordafstand til tilpasning og justering

Nogle gange er en streng korrekt, men har den forkerte bredde: en overskrift, der skal spænde over en fast linje, en kode, der skal læses med mere luftige cifre, en kolonne, der har brug for, at dens værdier skubbes til for at flugte. PDF bærer to teksttilstandsoperatører til dette, tegnafstand (Tc, ekstra plads tilføjet efter hver glyph) og ordafstand (Tw, ekstra plads tilføjet ved hvert mellemrumstegn), og begge er udtrykt i uskalerede tekst-rum enheder, effektivt punkter ved den aktuelle skriftstørrelse. De er tilstand, ikke argumenter til TextOut, så du indstiller dem, tegner og indstiller dem tilbage

// Letter-space a short heading so it stretches across a rule.
Pdf.CurrentPage.SetCharacterSpacing(4);
Pdf.CurrentPage.SetFont('Arial', [fsBold], 14);
Pdf.CurrentPage.TextOut(72, 740, 0, 'S U M M A R Y');
Pdf.CurrentPage.SetCharacterSpacing(0);   // reset before normal body text

// Open up the gaps between words on a single wide line.
Pdf.CurrentPage.SetWordSpacing(6);
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Name        Department        Extension');
Pdf.CurrentPage.SetWordSpacing(0);

Ordafstand virker kun på mellemrumstegnet (kode 32), hvilket har en konsekvens, der er værd at vide: det gør intet inde i et CJK-forløb, der ikke har nogen ASCII-mellemrum, og det interagerer mærkeligt med tekst kodet som glyph-indeks i stedet for bytes. For latinsk tabeloutput er det den billige måde at udvide huller på uden at genindtaste strengen. Tegnafstand er det bedre værktøj til en overskrift, der skal nå en målbredde, da den spreder justeringen jævnt over hver glyph i stedet for at samle den ved mellemrummene

Nulstillingen er hele disciplinen. Afstand, ligesom skrifttypen, er en del af sidens tegnetilstand, og tilstand vedbliver, indtil du ændrer den. Lav bogstavafstand på én overskrift og glem at nulstille den, og hvert afsnit nedenfor arver strækningen, som læses som en subtil, svær at placere forkerthed, der overlever en tilfældig korrekturlæsning og fejler en omhyggelig. Den pålidelige vane er at indstille en afstandsværdi, tegne det forløb, der har brug for det, og indstille det tilbage til nul i den næste linje, så ingen senere kode behøver at vide, hvad et tidligere afsnit gjorde

HotPDF TextOut-side, der sammenligner vandret tekstskalering, tegnafstand, ordafstand og udfyldning versus streg-gengivelsestilstande

Kontrol af outputtet, hvor det faktisk går i stykker

Tekstlayout fejler på den anden maskine, ikke den første, så de kontroller, der betyder noget, sker væk fra dit skrivebord. Åbn den genererede fil på et system, der ikke har din udviklerskrifttype installeret, og bekræft, at de indlejrede skrifttyper stadig gengives, inklusive latinsk med accent, eventuelle ikke-latinske scripts og tegnsætning, i én arbejdsgang i stedet for at stikprøvekontrollere de lette tegn. Vælg og kopier et par linjer for at bekræfte, at teksten er rigtig tekst og ikke omrids, hvilket betyder noget i det øjeblik søgning eller udtrækning er inden for rækkevidde. Giv layoutet repræsentative data, den længste tyske etiket og det bredeste tal, ikke en pæn pladsholder, fordi det forløb, der flyder over et felt, altid er det, du ikke indtastede manuelt. Og hvis siden skal lande på en fortrykt formular, skal du udskrive eller rasterisere en prøve og lægge den mod originalen; en kvart millimeters grundlinjedrift er usynlig på skærmen og åbenlys på papir

Hvis du ikke har skrevet en eneste side endnu, skal du starte med HotPDF Hello World-eksemplet, som opsætter dokumentet, skrifttypen og det nederste venstre koordinatsystem, som alt ovenstående afhænger af. TextOut-, SetFont- og afstandskaldene, der vises her, er en del af HotPDF Component til Delphi og C++Builder