Elke zichtbare tekenreeks in een HotPDF-document komt tot stand via één aanroep: TextOut(X, Y, angle, Text). Het Hello World-voorbeeld gebruikt het in zijn eenvoudigste vorm, lettertype eenmalig ingesteld en vier argumenten op zinvolle standaardwaarden gelaten. Na die eerste pagina dragen diezelfde vier argumenten het volledige gewicht van de opmaak. Het derde argument roteert de tekstregel. Het lettertype dat er net voor is ingesteld bepaalt grootte en stijl. En het X, Y-paar, gemeten vanuit de paginahoek in punten, is het enige dat staat tussen een nette rapportpagina en tekst die overlapt, wegvalt of op iemand anders zijn printer een regel te laag staat. Hier verdient TextOut zijn waarde, en hier houden de standaardwaarden op toereikend te zijn.
De handtekening is het waard om te onthouden voordat u verder gaat: X en Y zijn Single in punten, angle is een Extended in graden en Text is een WideString, zodat Unicode er zonder extra aanroep doorheen gaat. Een tweede overload neemt een PWORD plus een lengte voor wanneer u al glyphcodes in handen heeft, maar voor gewone tekenreeksen is de WideString-vorm de gebruikelijke keuze.
Grootte en stijl komen uit SetFont, niet uit TextOut
TextOut heeft geen groottteparameter. De grootte, het gewicht en de schuinstand wonen allemaal in de SetFont-aanroep die voorafgaat aan de tekstregel, en ze blijven van kracht totdat de volgende SetFont ze vervangt. Dat is het ene feit dat de meeste verwarring op de eerste dag verklaart: een regel komt vet uit omdat drie aanroepen eerder iets [fsBold] heeft ingesteld en niets het heeft gewist.
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
Het tweede argument is een TFontStyles-set, dus [fsBold, fsItalic] is vetgedrukt cursief en [] is gewone tekst. De grootte is in punten, dezelfde eenheid als de coördinaten, wat verticale spatiëring gemakkelijk te redeneren maakt: een regel van 12 punten heeft ruwweg 14 tot 16 punten verticale stap nodig om te ademen, dus Y met 14 per regel verlagen is een redelijk begininterval. Er is geen automatische regelafstand. U berekent elke basislijn zelf, wat vervelend is voor een alinea maar exact voor een formulier, waar elk veld op een vaste coördinaat staat.
Twee praktische opmerkingen over de lettertypenaam. Het wordt omgezet via de op de bouwmachine geïnstalleerde lettertypen, en wat het besturingssysteem teruggeeft is wat wordt ingesloten, dus een naam die op uw desktop wordt omgezet en een naam die op een bouwserver wordt omgezet zijn niet gegarandeerd hetzelfde lettertype. En het lettertype moet de schriften in de tekenreeks ondersteunen. Een reeks Cyrillische of CJK-tekst onder een puur Latijns lettertype wordt weergegeven als vakjes voor ontbrekende glyphs, zonder foutmelding, wat de reden is dat de Hello World-pagina naar een breed Unicode-lettertype grijpt als talen worden gemengd.
Het hoekargument roteert rond het ankerpunt
Het derde argument is degene die de meeste code voor altijd op nul laat staan. Geef een waarde ongelijk aan nul mee en de tekstregel roteert tegen de klok in rond zijn eigen ankerpunt (X, Y), de linkeronderkant van de tekst, met dat aantal graden. Het ankerpunt zelf beweegt niet, dus dezelfde coördinaat die een horizontaal label plaatst, plaatst zijn geroteerde tegenhanger; alleen de richting waarin de glyphs lopen verandert.
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');
Negentig graden is het meest voorkomende geval: een label dat langs de zijkant van een grafiek omhoog loopt of een ruggetitel. Vijfenveertig graden behandelt gekantelde kolomkoppen, de truc waarmee een breed label boven een smalle kolom past zonder in de buurkolommen te lopen. Rotatie verandert niet hoe het ankerpunt wordt geïnterpreteerd, wat mensen in verwarring brengt: een tekstregel van 90 graden begint nog steeds bij (X, Y) en groeit vandaar omhoog, dus om een geroteerd label te centreren past u het ankerpunt aan, niet de hoek. Als meerdere geroteerde tekstregel een gemeenschappelijke basislijn delen, geef ze dezelfde Y en stap X op, precies zoals u Y zou stappen voor gestapelde horizontale regels.
Coördinaten plaatsen zonder te gokken
Coördinaten zijn het deel dat een review doorstaat of stilzwijgend faalt. HotPDF meet vanuit de linkeronderhoek van de pagina, Y groeit omhoog, in punten bij 72 per inch. Een US Letter-pagina is 612 bij 792 punten; A4 is 595 bij 842. Een bovenmarge van één inch op Letter plaatst uw eerste basislijn dus nabij Y = 792 min 72 min de lettergrootte, niet bij een klein getal vlak boven de bovenkant. Wie gewend is aan schermcoördinaten, waar Y van boven naar beneden groeit, schrijft de eerste regel buiten de onderrand en brengt tien minuten door met afvragen waar het naartoe is gegaan.
Behandel opmaak als rekenkundige bewerkingen op benoemde ankers in plaats van een kolom magische getallen. Een linkermarge, een aflopende basislijn en een vaste regelafstand veranderen een blok labels in een korte lus in plaats van een muur van letterlijke waarden:
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;
De pagina-einde-controle is de regel die iedereen als eerste vergeet en die in het veld het hardst toeslaat. Er is geen stroomdistributie onder TextOut. Afnemen voorbij de ondermarge en de tekst blijft tekenen in de goot, buiten de pagina, in het niets, zonder waarschuwing. Dus u houdt Y zelf in de gaten, roept AddPage aan als het de bodem kruist, en stelt de basislijn opnieuw in. De SetFont na AddPage is geen optionele opvulling: het huidige lettertype overleeft een pagina-einde niet, en de eerste tekstregel op de nieuwe pagina verschijnt in het standaardlettertype van de viewer als u het overslaat.
Teken- en woordspatiëring voor pasvorm en uitlijning
Soms is een tekenreeks correct maar heeft de verkeerde breedte: een koptekst die een vaste lijn moet beslaan, een code die luchtiger cijfers moet lezen, een kolom waarvan de waarden moeten worden bijgesteld om uit te lijnen. PDF heeft twee tekststatus-operatoren hiervoor: tekenspatiëring (Tc, extra ruimte na elk glyph) en woordspatiëring (Tw, extra ruimte bij elk spatieteken), en beide worden uitgedrukt in ongeschaalde tekstruimte-eenheden, effectief punten bij de huidige lettergrootte. Het zijn toestandselementen, geen argumenten voor TextOut, dus u stelt ze in, tekent en stelt ze terug.
// 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);
Woordspatiëring werkt alleen op het spatieteken (code 32), wat een gevolg heeft dat het waard is te kennen: het doet niets in een CJK-reeks zonder ASCII-spaties, en het interageert vreemd met tekst die als glyphindices is gecodeerd in plaats van als bytes. Voor Latijnse tabeluitvoer is het de goedkope manier om gaten te verbreden zonder de tekenreeks opnieuw te typen. Tekenspatiëring is het betere hulpmiddel voor een koptekst die een doelbreedte moet bereiken, omdat het de aanpassing gelijkmatig over elk glyph verdeelt in plaats van het te clusteren bij de spaties.
Het terugstellen is de hele discipline. Spatiëring is, net als het lettertype, onderdeel van de tekenstatus van de pagina, en de status blijft bestaan totdat u deze wijzigt. Spatieer één koptekst en vergeet het op nul te zetten, en elke alinea eronder erft de rek, wat wordt gelezen als een subtiele, moeilijk te plaatsen merkwaardigheid die een vluchtige proeflezing overleeft en een nauwkeurige niet. De betrouwbare gewoonte is: stel een spatiëringswaarde in, teken de reeks die het nodig heeft en zet het op nul terug in de volgende regel, zodat geen latere code hoeft te weten wat een eerdere sectie heeft gedaan.
De uitvoer controleren waar het daadwerkelijk fout gaat
Tekstopmaak faalt op de tweede machine, niet de eerste, dus de controles die er toe doen vinden plaats buiten uw bureau. Open het gegenereerde bestand op een systeem zonder uw ontwikkelingslettertypenset geïnstalleerd en bevestig dat de ingesloten lettertypen nog steeds worden weergegeven, inclusief letters met accenten, niet-Latijnse schriften en leestekens, in één keer in plaats van het puntgewijs controleren van de makkelijke tekens. Selecteer en kopieer een paar regels om te bevestigen dat de tekst echte tekst is en geen omtrekken, wat van belang is zodra zoeken of extractie in beeld komt. Geef de opmaak representatieve gegevens: het langste Duitse label en het breedste getal, niet een nette tijdelijke aanduiding, want de reeks die een veld overloopt is altijd de reeks die u niet met de hand heeft getypt. En als de pagina op een voorgedrukt formulier moet vallen, druk of rasteriseer één voorbeeld af en leg het naast het origineel; een kwart millimeter basislijndrift is onzichtbaar op scherm en duidelijk op papier.
Als u nog geen enkele pagina heeft geschreven, begin dan met het HotPDF Hello World-voorbeeld, dat het document, het lettertype en het coördinatenstelsel met linkeronderhoek instelt waarop alles hierboven steunt. De hier getoonde aanroepen TextOut, SetFont en spatiëring maken deel uit van de HotPDF Component voor Delphi en C++Builder.