Varje synlig sträng i ett HotPDF-dokument kommer via ett enda anrop: TextOut(X, Y, angle, Text). Hello World-exemplet använder det på sitt enklaste sätt, med teckensnitt inställt en gång och fyra argument lämnade vid rimliga standardvärden. Efter den första sidan bär samma fyra argument hela tyngden av layouten. Det tredje argumentet roterar körningen. Teckensnittet som ställs in precis innan bestämmer storlek och stil. Och X, Y-paret, mätt från sidans hörn i punkter, är det enda som står mellan en ren rapport och text som överlappar, klipps av eller glider en rad lägre på någon annans skrivare. Det är här TextOut gör skäl för sig, och där standardvärdena slutar vara tillräckliga
Signaturen är värd att lägga på minnet innan något annat: X och Y är Single i punkter, angle är en Extended i grader och Text är en WideString, så Unicode passerar igenom utan ett separat anrop. En andra överlagring tar en PWORD plus en längd för när du redan håller i glyfkoder, men för vanliga strängar är WideString-formen den du ska sträcka dig efter
Storlek och stil kommer från SetFont, inte TextOut
TextOut har ingen storleksparameter. Storleken, viktningen (weight), lutningen, alltihop lever i det SetFont-anrop som föregår körningen, och det gäller tills nästa SetFont ersätter det. Det är det enskilda faktum som förklarar det mesta av förvirringen under den första dagen: en rad blir fetstil eftersom ett anrop tre steg tidigare ställde in [fsBold] och inget rensade 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 andra argumentet är en TFontStyles-uppsättning, så [fsBold, fsItalic] är fet kursiv och [] är vanligt. Storleken mäts i punkter, samma enhet som koordinaterna, vilket gör vertikalt avstånd enkelt att resonera om: en 12-punkters rad behöver ungefär 14 till 16 punkters vertikalt steg (leading) för att andas, så att sänka Y med 14 per rad är en rimlig startradhöjd (leading). Det finns ingen automatisk radmatning. Du beräknar varje baslinje själv, vilket är tjatigt för ett stycke men exakt för ett formulär, där varje fält sitter vid en fast koordinat
Två praktiska anmärkningar om teckensnittsnamnet. Det löses mot de teckensnitt som är installerade på byggmaskinen, och vad OS:et än skickar tillbaka är det som bäddas in, så ett namn som löses upp på ditt skrivbord och ett namn som löses upp på en byggserver är inte garanterat att vara samma stil (face). Och teckensnittet måste täcka skripten i strängen. En körning av kyrillisk eller CJK-text under ett enbart latinskt teckensnitt (Latin-only face) renderas som lådor för saknade glyfer utan något fel, vilket är anledningen till att Hello World-sidan sträcker sig efter en bred Unicode-stil när den blandar språk
Vinkelargumentet roterar runt ankaret
Det tredje argumentet är det som de flesta koder lämnar på noll för alltid. Skicka med ett värde skilt från noll och körningen roterar moturs kring sitt eget (X, Y) ankare, textens nedre vänstra hörn, med så många grader. Själva ankaret rör sig inte, så samma koordinat som placerade en horisontell etikett placerar sin roterade tvilling; endast riktningen som glyferna marscherar åt ändras
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');
Nittio grader är det vanliga fallet, en etikett som löper upp längs sidan av ett diagram eller en ryggtitel. Fyrtiofem grader hanterar lutade kolumnrubriker, knepet som låter en bred etikett sitta över en smal kolumn utan att spilla över på sina grannar. Rotation ändrar inte hur ankaret tolkas, vilket ställer till det för folk: en 90-graders körning startar fortfarande vid (X, Y) och växer uppåt därifrån, så för att centrera en roterad etikett justerar du ankaret, inte vinkeln. När flera roterade körningar delar baslinje, ge dem samma Y och stega X, precis som du skulle stega Y för staplade horisontella rader
Placering av koordinater utan att gissa
Koordinater är den del som överlever en granskning eller som i tysthet misslyckas i den. HotPDF mäter från sidans nedre vänstra hörn, med Y växande uppåt, i punkter om 72 till tummen. En US Letter-sida är 612 x 792 punkter; A4 är 595 x 842. En en tums toppmarginal på Letter sätter därför din första baslinje nära Y = 792 minus 72 minus teckenstorleken, inte vid någon liten siffra nära toppen. Den som anländer från skärmkoordinater, där Y växer nedåt från noll, skriver den första raden utanför underkanten och tillbringar tio minuter med att undra vart den tog vägen
Hantera layout som aritmetik mot namngivna ankare i stället för en kolumn med magiska siffror. En vänstermarginal, en löpande baslinje som du räknar ner för varje rad, och ett fast radavstånd (leading) gör ett block med etiketter till en kort loop i stället för en vägg av bokstavliga (literal) värden:
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;
Sidbrytningsskyddet är den rad som alla glömmer först och som fältet drabbas hårdast av. Det finns ingen flödeslayout under TextOut. Minska förbi bottenmarginalen och texten fortsätter rita ner i rännstenen, ut från sidan, in i ingenting, utan varning. Så du vakar över Y själv, anropar AddPage när den passerar golvet, och återställer baslinjen. Det SetFont som kommer efter AddPage är inte en valfri utfyllnad: det nuvarande teckensnittet överlever inte en sidbrytning, och den första körningen på den nya sidan kommer ut i visarens standardtypsnitt om du hoppar över det
Tecken- och ordbredd för passform och inriktning
Ibland är en sträng korrekt men har fel bredd: en rubrik som måste spänna över en fast linje (rule), en kod som bör läsas med luftigare siffror, en kolumn som behöver få sina värden knuffade för att justeras (align). PDF bär med sig två texttillståndsoperatörer för detta, teckenavstånd (character spacing, Tc, extra utrymme läggs till efter varje glyf) och ordavstånd (word spacing, Tw, extra utrymme läggs till vid varje mellanslag), och båda uttrycks i oskalade textrymdsenheter, vilket i praktiken är punkter vid den aktuella teckenstorleken. De är ett tillstånd, inte argument till TextOut, så du ställer in dem, ritar och ställer tillbaka dem
// 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);
Ordavstånd (word spacing) verkar bara på mellanslagstecknet (kod 32), vilket får en konsekvens som är värd att veta: det gör ingenting inuti en CJK-körning som saknar ASCII-mellanslag, och det interagerar konstigt med text som är kodad som glyf-index i stället för bytes. För latinsk tabulär utmatning är det ett billigt sätt att bredda mellanrummen utan att skriva om strängen. Teckenavstånd (character spacing) är ett bättre verktyg för en rubrik som måste nå en viss målbredd, eftersom det sprider justeringen jämnt över varje glyf i stället för att samla det på mellanslagen
Återställningen är hela disciplinen. Spacing, liksom teckensnittet, är en del av sidans ritningstillstånd (drawing state), och tillståndet kvarstår tills du ändrar det. Ställ in teckenavstånd (letter-space) på en rubrik och glöm att nollställa det, så ärver varje stycke därunder sträckningen, vilket läses som en subtil, svårplacerad felaktighet som överlever en slarvig korrekturläsning och fälls av en noggrann. Den pålitliga vanan är att ställa in ett mellanrumsvärde (spacing value), rita den körning som behöver det, och nollställa det på nästa rad, så att ingen senare kod behöver veta vad ett tidigare avsnitt gjorde
Kontrollera utmatningen där den faktiskt går sönder
Textlayout misslyckas på den andra maskinen, inte den första, så de kontroller som spelar roll sker borta från ditt skrivbord. Öppna den genererade filen på ett system utan din utvecklarteckensnittsuppsättning installerad och bekräfta att de inbäddade stilarna (faces) fortfarande renderas, inklusive accentuerad latinsk text, alla icke-latinska skript och skiljetecken, i ett svep i stället för att stickprovskontrollera de enkla tecknen. Markera och kopiera några rader för att bekräfta att texten är riktig text och inte konturer (outlines), vilket spelar roll från det ögonblick sökning eller extraktion är av intresse (in scope). Mata layouten med representativ data, den längsta tyska etiketten och det bredaste numret, inte en prydlig platshållare, eftersom körningen som svämmar över ett fält alltid är den du inte skrev för hand. Och om sidan måste landa på ett förtryckt formulär, skriv ut eller rastrera ett prov och lägg det över originalet; en kvarts millimeters glidning i baslinjen är osynlig på skärmen men uppenbar på papper
Om du ännu inte har skrivit en enda sida, börja med HotPDF Hello World-exemplet, som sätter upp dokumentet, teckensnittet och det nedre vänstra koordinatsystem som allt ovanstående bygger på. TextOut, SetFont och avståndsanropen (spacing calls) som visas här är en del av HotPDF Component för Delphi och C++Builder