Hver synlige streng i et HotPDF-dokument kommer gjennom ett kall: TextOut(X, Y, angle, Text). Hello World-eksempelet bruker det på sitt enkleste, med skriften satt én gang og fire argumenter latt stå på fornuftige standardverdier. Etter den første siden bærer de samme fire argumentene hele vekten av layouten. Det tredje argumentet roterer tekstsekvensen. Skriften som settes rett før, avgjør størrelse og stil. Og X, Y-paret, målt fra sidehjørnet i punkter, er det eneste som står mellom en ren rapport og tekst som overlapper, klippes eller driver en linje lavere på en annens skriver. Det er her TextOut gjør nytte for seg, og der standardverdiene slutter å strekke til
Signaturen er verdt å feste seg ved før noe annet: X og Y er Single i punkter, angle er en Extended i grader, og Text er en WideString, så Unicode går gjennom uten et eget kall. En andre overlast tar en PWORD pluss en lengde for de gangene du allerede har glyfkodene, men for vanlige strenger er WideString-formen den du griper til
Størrelse og stil kommer fra SetFont, ikke fra TextOut
TextOut har ingen størrelsesparameter. Størrelsen, vekten, hellingen, alt sammen ligger i SetFont-kallet som kommer foran sekvensen, og det gjelder til neste SetFont erstatter det. Det er det ene faktumet som forklarer mesteparten av forvirringen den første dagen: en linje kommer ut i fet skrift fordi noe tre kall tidligere satte [fsBold] og ingenting nullstilte det
Pdf.CurrentPage.SetFont('Times New Roman', [], 24);
Pdf.CurrentPage.TextOut(72, 740, 0, 'Quarterly Report'); // 24 pt vanlig
Pdf.CurrentPage.SetFont('Times New Roman', [fsBold], 12);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Revenue'); // 12 pt fet
Pdf.CurrentPage.SetFont('Times New Roman', [fsItalic], 11);
Pdf.CurrentPage.TextOut(72, 694, 0, 'figures in thousands'); // 11 pt kursiv
Pdf.CurrentPage.SetFont('Courier New', [fsBold, fsItalic], 10);
Pdf.CurrentPage.TextOut(72, 676, 0, ' +18.4% YoY'); // stiler kombineres
Det andre argumentet er et TFontStyles-sett, så [fsBold, fsItalic] er fet kursiv og [] er vanlig. Størrelsen er i punkter, den samme enheten som koordinatene, noe som gjør loddrett avstand lett å resonnere om: en linje på 12 punkter vil ha omtrent 14 til 16 punkter loddrett steg for å puste, så å senke Y med 14 per linje er et rimelig utgangspunkt for linjeavstanden. Det finnes ingen automatisk linjeframføring. Du regner ut hver grunnlinje selv, noe som er kjedelig for et avsnitt, men eksakt for et skjema, der hvert felt sitter på en fast koordinat
To praktiske merknader om skriftnavnet. Det løses opp mot skriftene som er installert på byggemaskinen, og det operativsystemet gir tilbake, er det som bygges inn, så et navn som løses opp på skrivebordet ditt og et navn som løses opp på en byggeserver er ikke garantert å være samme skriftsnitt. Og skriften må dekke skriftsystemene i strengen. En sekvens med kyrillisk eller CJK-tekst under et snitt som bare har latinske tegn, gjengis som bokser for manglende glyfer uten noen feilmelding, og det er grunnen til at Hello World-siden griper til et bredt Unicode-snitt når den blander språk
Vinkelargumentet roterer rundt ankeret
Det tredje argumentet er det de fleste lar stå på null for alltid. Send inn en verdi ulik null, og sekvensen roterer mot klokken om sitt eget (X, Y)-anker, nederst til venstre i teksten, med så mange grader. Selve ankeret flytter seg ikke, så den samme koordinaten som plasserte en vannrett etikett, plasserer den roterte tvillingen; bare retningen glyfene marsjerer i, endres
Pdf.CurrentPage.SetFont('Arial', [fsBold], 11);
// En loddrett akseetikett ned langs venstre marg: 90 grader leses nedenfra og opp.
Pdf.CurrentPage.TextOut(40, 300, 90, 'Units sold');
// Et diagonalt DRAFT-vannmerke tvers over sidekroppen.
Pdf.CurrentPage.SetFont('Arial', [fsBold], 60);
Pdf.CurrentPage.TextOut(150, 250, 45, 'DRAFT');
// Kolonneoverskrifter vippet 60 grader så lange etiketter får plass i en smal tabell.
Pdf.CurrentPage.SetFont('Arial', [], 9);
Pdf.CurrentPage.TextOut(120, 600, 60, 'Q1 actual');
Pdf.CurrentPage.TextOut(160, 600, 60, 'Q2 actual');
Nitti grader er det vanlige tilfellet, en etikett som går opp langs siden av et diagram eller en ryggtittel. Førtifem grader dekker skråstilte kolonneoverskrifter, trikset som lar en bred etikett sitte over en smal kolonne uten å søle inn i naboene. Rotasjon endrer ikke hvordan ankeret tolkes, og det snubler folk i: en sekvens på 90 grader starter fortsatt i (X, Y) og vokser oppover derfra, så for å sentrere en rotert etikett justerer du ankeret, ikke vinkelen. Når flere roterte sekvenser deler en grunnlinje, gir du dem samme Y og stepper X, akkurat som du ville steppet Y for stablede vannrette linjer
Plassere koordinater uten å gjette
Koordinatene er den delen som overlever en gjennomgang eller stille feiler den. HotPDF måler fra nedre venstre hjørne av siden, med Y som vokser oppover, i punkter à 72 per tomme. En US Letter-side er 612 ganger 792 punkter; A4 er 595 ganger 842. En toppmarg på én tomme på Letter legger derfor den første grunnlinjen nær Y = 792 minus 72 minus skriftstørrelsen, ikke på et lite tall nær toppen. Alle som kommer fra skjermkoordinater, der Y vokser nedover fra null, skriver den første linjen utenfor nedre kant og bruker ti minutter på å lure på hvor den ble av
Behandle layout som aritmetikk mot navngitte ankre heller enn som en kolonne med magiske tall. En venstremarg, en løpende grunnlinje du trekker fra per linje, og en fast linjeavstand gjør en blokk med etiketter om til en kort løkke i stedet for en vegg av litteraler:
const
LeftMargin = 72; // 1 tomme inn
TopBaseline = 720; // første linje, ca. 1 tomme ned på Letter
Leading = 16; // loddrett steg mellom linjene
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 // bunnmargen er nådd
begin
Pdf.AddPage;
Pdf.CurrentPage.SetFont('Arial', [], 11); // skriften nullstilles på ny side
Y := TopBaseline;
end;
end;
end;
Sidebruddsvakten er linjen alle glemmer først og som slår hardest ute i felten. Det finnes ingen flytlayout under TextOut. Trekk deg forbi bunnmargen, og teksten fortsetter å tegne ned i renna, utenfor siden, ut i ingenting, uten noen advarsel. Så du holder øye med Y selv, kaller AddPage når den krysser gulvet, og nullstiller grunnlinjen. SetFont etter AddPage er ikke overflødig fyll: den gjeldende skriften overlever ikke et sidebrudd, og den første sekvensen på den nye siden kommer ut i visningsprogrammets standardsnitt hvis du hopper over den
Tegn- og ordavstand for tilpasning og justering
Noen ganger er en streng riktig, men har feil bredde: en overskrift som skal spenne over en fast strek, en kode som bør leses med luftigere sifre, en kolonne som trenger verdiene dyttet på plass. PDF har to teksttilstandsoperatorer for dette, tegnavstand (Tc, ekstra plass lagt til etter hver glyf) og ordavstand (Tw, ekstra plass lagt til ved hvert mellomromstegn), og begge uttrykkes i uskalerte tekstromsenheter, i praksis punkter ved gjeldende skriftstørrelse. De er tilstand, ikke argumenter til TextOut, så du setter dem, tegner, og setter dem tilbake
// Sperr en kort overskrift så den strekker seg over en strek.
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); // nullstill før vanlig brødtekst
// Åpne opp mellomrommene mellom ordene på én bred linje.
Pdf.CurrentPage.SetWordSpacing(6);
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Name Department Extension');
Pdf.CurrentPage.SetWordSpacing(0);
Ordavstand virker bare på mellomromstegnet (kode 32), noe som har en konsekvens verdt å kjenne: den gjør ingenting inne i en CJK-sekvens uten ASCII-mellomrom, og den samvirker rart med tekst kodet som glyfindekser i stedet for byte. For latinsk tabelloppsett er den den billige måten å utvide mellomrom på uten å skrive strengen om. Tegnavstand er det bedre verktøyet for en overskrift som må nå en målbredde, siden den sprer justeringen jevnt over hver glyf i stedet for å samle den ved mellomrommene
Nullstillingen er hele disiplinen. Avstand er, som skriften, en del av sidens tegnetilstand, og tilstand varer til du endrer den. Sperr én overskrift og glem å nulle den, så arver hvert avsnitt under strekket, noe som leses som en subtil og vanskelig plasserbar skjevhet som overlever en rask korrektur og feller en grundig. Den pålitelige vanen er å sette en avstandsverdi, tegne sekvensen som trenger den, og sette den tilbake til null på neste linje, slik at ingen senere kode må vite hva en tidligere del gjorde
Sjekke resultatet der det faktisk brekker
Tekstlayout feiler på den andre maskinen, ikke den første, så sjekkene som betyr noe skjer borte fra pulten din. Åpne den genererte filen på et system uten utviklerskriftene dine installert og bekreft at de innebygde snittene fortsatt gjengis, inkludert aksenterte latinske tegn, eventuelle ikke-latinske skriftsystemer og tegnsetting, i én omgang heller enn å stikkprøve de lette tegnene. Merk og kopier noen linjer for å bekrefte at teksten er ekte tekst og ikke omriss, noe som betyr noe i det øyeblikket søk eller uttrekk er i bildet. Mat layouten med representative data, den lengste tyske etiketten og det bredeste tallet, ikke et pent plassholderord, for sekvensen som flommer over et felt er alltid den du ikke skrev inn for hånd. Og skal siden lande på et forhåndstrykt skjema, skriv ut eller rastrer én prøve og legg den mot originalen; en grunnlinjeforskyvning på en kvart millimeter er usynlig på skjermen og åpenbar på papir
Har du ennå ikke skrevet en eneste side, start med Hello World-eksempelet for HotPDF, som setter opp dokumentet, skriften og koordinatsystemet med origo nederst til venstre som alt over hviler på. Kallene TextOut og SetFont og avstandskallene som er vist her, er en del av HotPDF Delphi Component for Delphi og C++Builder