Elke zichtbare string in een HotPDF document komt tot stand via één aanroep: TextOut(X, Y, hoek, Tekst). Het Hello World voorbeeld gebruikt het op zijn eenvoudigst, met een eenmalig ingesteld lettertype en vier argumenten die op logische standaardwaarden zijn gelaten. Voorbij die eerste pagina dragen diezelfde vier argumenten het volledige gewicht van de lay-out. Het derde argument roteert de run. Het lettertype dat er net voor is ingesteld bepaalt de grootte en stijl. En het X, Y paar, gemeten vanaf de paginahoek in punten, is het enige dat tussen een net rapport staat en tekst die overlapt, afsnijdt of een regel lager wegdrijft op de printer van iemand anders. Dit is waar TextOut zijn geld opbrengt, en waar de standaardwaarden niet meer volstaan
De signatuur is de moeite waard om in gedachten te prenten voordat u iets anders doet: X en Y zijn Single in punten, hoek is een Extended in graden, en Tekst is een WideString, dus Unicode gaat erdoorheen zonder een aparte aanroep. Een tweede overload neemt een PWORD plus een lengte voor wanneer u al glyphcodes vasthoudt, maar voor gewone strings is de WideString-vorm degene waar u naar grijpt
Grootte en stijl komen van SetFont, niet van TextOut
TextOut heeft geen parameter voor grootte. De grootte, het gewicht, de schuinte, alles leeft in de SetFont aanroep die aan de run voorafgaat, en het blijft van kracht totdat de volgende SetFont het vervangt. Dat is het enige feit dat de meeste verwarring op de eerste dag verklaart: een regel wordt vetgedrukt omdat iets drie aanroepen eerder [fsBold] instelde 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 verzameling, dus [fsBold, fsItalic] is vet cursief en [] is normaal. De grootte is in punten, dezelfde eenheid als de coördinaten, wat het redeneren over verticale spatiëring eenvoudig maakt: een 12-punts regel heeft ruwweg 14 tot 16 punten verticale stap nodig om te ademen, dus Y met 14 laten zakken per regel is een redelijke start-regelafstand. Er is geen automatische regelopschuiving. 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 naam van het lettertype. Het wordt herleid aan de hand van de lettertypen die op de build-machine zijn geïnstalleerd, en wat het besturingssysteem ook teruggeeft, wordt ingesloten. Een naam die op uw bureaublad wordt herleid, hoeft dus niet gegarandeerd hetzelfde lettertype te zijn als een naam die op een buildserver wordt herleid. En het lettertype moet de scripts in de string dekken. Een reeks Cyrillische of CJK-tekst onder een lettertype dat alleen Latijns is, wordt zonder foutmelding weergegeven als ontbrekende-glyph-vakjes, wat de reden is dat de Hello World-pagina naar een breed Unicode-lettertype grijpt wanneer het talen combineert
Het hoekargument roteert rond het anker
Het derde argument is het argument dat de meeste code voor altijd op nul laat staan. Geef een waarde ongelijk aan nul door en de run roteert tegen de klok in rond zijn eigen (X, Y) anker, de linkerbenedenhoek van de tekst, met dat aantal graden. Het anker zelf beweegt niet, dus dezelfde coördinaat die een horizontaal label plaatste, plaatst zijn geroteerde tweelingbroer; alleen de richting waarin de glyphs marcheren 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 veelvoorkomende geval, een label dat langs de zijkant van een grafiek loopt of een rugtitel. Vijfenveertig graden behandelt gekantelde kolomkoppen, de truc waarmee een breed label boven een smalle kolom kan staan zonder over te lopen in zijn buren. Rotatie verandert niet hoe het anker wordt geïnterpreteerd, wat mensen op het verkeerde been zet: een 90-graden run begint nog steeds op (X, Y) en groeit van daaruit naar boven, dus om een geroteerd label te centreren past u het anker aan, niet de hoek. Wanneer meerdere geroteerde runs een basislijn delen, geef ze dan dezelfde Y en stap X, precies zoals u Y zou stappen voor gestapelde horizontale lijnen
Coördinaten plaatsen zonder te gissen
Coördinaten zijn het onderdeel dat een beoordeling overleeft of deze stilletjes faalt. HotPDF meet vanaf de linkerbenedenhoek van de pagina, Y neemt naar boven toe, in punten op 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 daarom uw eerste basislijn in de buurt van Y = 792 min 72 min de lettergrootte, niet bij een klein getal in de buurt van de bovenkant. Iedereen die van schermcoördinaten komt, waarbij Y vanaf nul naar beneden groeit, schrijft de eerste regel buiten de onderrand en vraagt zich tien minuten lang af waar deze gebleven is
Behandel lay-out als rekenkunde ten opzichte van benoemde ankers in plaats van een kolom met magische getallen. Een linkermarge, een lopende basislijn die u per regel verlaagt, 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 bewaking tegen pagina-einden is de regel die iedereen als eerste vergeet en die in de praktijk het hardst toeslaat. Er zit geen flow-layout onder TextOut. Verlaag voorbij de ondermarge en de tekst blijft in de goot tekenen, van de pagina af, in het niets, zonder waarschuwing. Dus u houdt Y zelf in de gaten, roept AddPage aan wanneer deze de drempel overschrijdt, 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 run op de nieuwe pagina wordt in het standaardlettertype van de viewer weergegeven als u deze overslaat
Teken- en woordafstand voor pasvorm en uitlijning
Soms is een string correct, maar is de breedte verkeerd: een koptekst die een vaste regel moet overspannen, een code die met luchtigere cijfers moet lezen, een kolom waarvan de waarden verschoven moeten worden om uit te lijnen. PDF heeft hiervoor twee tekststatus-operatoren, tekenafstand (Tc, extra ruimte toegevoegd na elke glyph) en woordafstand (Tw, extra ruimte toegevoegd bij elk spatiekarakter), en beide worden uitgedrukt in ongeschaalde tekstruimte-eenheden, effectief punten bij de huidige lettergrootte. Ze zijn status, geen argumenten voor TextOut, dus u stelt ze in, tekent en stelt ze weer 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);
Woordafstand werkt alleen op de spatie (code 32), wat een consequentie heeft die goed is om te weten: het doet niets binnen een CJK-run die geen ASCII-spaties heeft, en het werkt vreemd in combinatie met tekst die als glyph-indexen gecodeerd is in plaats van als bytes. Voor Latijnse tabeluitvoer is het de goedkope manier om ruimtes te verbreden zonder de string opnieuw te typen. Tekenafstand is de betere tool voor een koptekst die een doelbreedte moet bereiken, omdat het de aanpassing gelijkmatig over elke glyph verspreidt in plaats van het te bundelen bij de spaties
Het terugzetten is de hele discipline. Spatiëring maakt, net als het lettertype, deel uit van de tekenstatus van de pagina, en de status blijft bestaan totdat u deze wijzigt. Als u de letterafstand van een kop vergroot en vergeet deze op nul te zetten, neemt elke alinea eronder de uitrekking over, wat leest als een subtiele, moeilijk te plaatsen onjuistheid die een vluchtige proeflezing overleeft en faalt bij een zorgvuldige. De betrouwbare gewoonte is om een spatiëringswaarde in te stellen, de run te tekenen die het nodig heeft, en het op de volgende regel terug op nul te zetten, zodat latere code niet hoeft te weten wat een eerdere sectie deed
De uitvoer controleren waar deze daadwerkelijk faalt
Tekstopmaak faalt op de tweede machine, niet op de eerste, dus de controles die ertoe doen vinden plaats weg van uw bureau. Open het gegenereerde bestand op een systeem waarop uw ontwikkelaars-lettertype-set niet is geïnstalleerd en bevestig dat de ingesloten lettertypes nog steeds worden weergegeven, inclusief Latijns met accenten, eventuele niet-Latijnse scripts en leestekens, in één keer in plaats van de makkelijke tekens steekproefsgewijs te controleren. Selecteer en kopieer een paar regels om te bevestigen dat de tekst echte tekst is en geen contouren, wat ertoe doet op het moment dat zoeken of extractie van toepassing is. Voer representatieve gegevens in de lay-out, het langste Duitse label en het breedste getal, niet een nette tijdelijke aanduiding, want de run die buiten een veld loopt, is altijd degene die u niet met de hand hebt getypt. En als de pagina op een voorbedrukt formulier moet landen, print of raster dan één monster en leg het tegen het origineel; een afwijking in de basislijn van een kwart millimeter is onzichtbaar op het scherm en overduidelijk 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 linksonder-coördinatensysteem instelt waar alles hierboven van afhangt. De TextOut, SetFont en spatiërings-aanroepen die hier worden getoond maken deel uit van de HotPDF Component voor Delphi en C++Builder