PDFlibPas flödar ett bevarat textstycke genom en till 64 lika breda spalter med DrawTextFlowColumns, och bryter dess rader med begränsad språkmedveten avstavning så snart du anropar SetTextFlowLanguage och SetTextFlowHyphenation. Nio språk stöds, och språket kan ärvas från dokumentets Catalog-värde /Lang i stället för att sättas per flöde
Båda funktionerna finns av samma anledning: en smal spalt är där naiv radbrytning slutar likna sättning och börjar likna en felrapport
Varför faller marginaljusterad text sönder i smala spalter?
Därför att marginaljustering fördelar överbliven plats i radens ordmellanrum, och mängden som blir över beror på vad som får plats. På en bred spaltbredd är det överblivna litet och ögat märker det aldrig. Halvera bredden och ett enda långt ord som inte får plats trycks till nästa rad, och lämnar sina föregångare att absorbera hela den platsen. Tre sådana rader i följd skapar de vertikala vita kanaler som typografer kallar floder, och som läsare upplever som text som är svår att följa utan att veta varför
Avstavning åtgärdar orsaken i stället för symptomet genom att tillåta en brytning inuti ordet. Tyska och nederländska sammansättningar gör avstavning ofrånkomlig här: ett 24 tecken långt substantiv i en 60-millimeters spalt har inget bra utfall utan en brytpunkt. Engelska tolererar frånvaron bättre, vilket är varför engelskcentrerade produkter ofta levererar layoutkod som faller ihop första gången en tysk kund kör den
Vilka språk, och varifrån kommer språket?
Avstavning täcker engelska, tyska, nederländska, franska, spanska, italienska, portugisiska, ryska och turkiska. Sätt det explicit per flöde med SetTextFlowLanguage, eller låt det ärvas från dokumentets Catalog-post /Lang, vilket är värdet ett taggat och tillgängligt dokument redan bär med sig
Det arvet är värt att använda i stället för att skriva över. Ett dokument som deklarerar sitt språk i Catalog talar om samma sak för skärmläsare, sökindexerare och avstavning från ett enda ställe, och ett enda ställe är där ett faktum bör bo. Om du redan producerar taggad utdata enligt beskrivningen i automatisk taggning för tillgängliga PDF:er, är språkposten redan satt och flödet kan helt enkelt följa den
var
Lib: TPDFlib;
Flow, Drawn: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.SetOrigin(1);
Lib.AddTrueTypeFont('Georgia', 1);
Lib.SetTextSize(10.5);
Flow := Lib.NewTextFlow(ArticleBody);
try
Lib.SetTextFlowLanguage(Flow, 'de');
// Aktivera, minst 3 tecken före brytningen, 3 efter
Lib.SetTextFlowHyphenation(Flow, 1, 3, 3);
Lib.SetTextFlowMinLines(Flow, 2); // strandsätt aldrig en ensam rad
repeat
// Tre spalter över ett område på 480 pt, 18 pt mellanrum, balanserat
Drawn := Lib.DrawTextFlowColumns(Flow, 72, 720, 480, 620, 3, 18, 1);
if (Drawn = 0) or (Lib.TextFlowFinished(Flow) = 1) then
Break;
Lib.NewPage;
until False;
finally
Lib.ReleaseTextFlow(Flow);
end;
Lib.SaveToFile('newsletter.pdf');
finally
Lib.Free;
end;
end;
MinPrefix och MinSuffix är typografi, inte validering
De två heltalen efter aktiveringsflaggan anger minsta antal tecken som måste finnas kvar före och efter en brytning. Tre och tre är ett konservativt standardvärde som de flesta husstilar accepterar. Två och två ger fler brytmöjligheter och märkbart fulare resultat, eftersom ett tvåbokstavsfragment som hänger löst i radslutet läses som ett stavfel
Höj minimivärdena när typsnittsstorleken är stor, där varje fragment är visuellt framträdande, och sänk dem bara när spalten är genuint smal och du har bestämt att en snäv spaltbredd väger tyngre än en ren. Det här är ett husstilsbeslut snarare än ett tekniskt, vilket är precis varför det är en parameter i stället för en konstant
Vad betyder ”balanserat” egentligen här?
Parametern Balance ändrar bara beteende i slutet av ett textstycke. Med balansering på förkortas spalterna till exakt samma radantal när allt återstående får plats inom området, vilket är det som hindrar en sista sida från att visa två fulla spalter och en tredje med bara en enda ensam rad. När textstycket inte får plats behåller varje spalt sin fulla höjd så att sidan bär så mycket text den kan, och resten fortsätter på nästa sida
Den asymmetrin är rätt standardval för löpande dokument. Balansering mitt i en flödande artikel skulle slösa vertikalt utrymme på varje sida för en kosmetisk effekt ingen ser, eftersom spalterna ändå är fulla. Balansering i slutet är där ögat faktiskt märker det, och det är precis där det tillämpas
Radbrytning mäter hela ord
Brytningsalgoritmen mäter kompletta ord i stället för att ackumulera teckenbredder, och reserverar en begränsad sökning för överdimensionerade token som inte får plats på en rad alls, som en URL eller ett accessionsnummer. Det håller det vanliga fallet snabbt och det patologiska fallet begränsat, i stället för tvärtom
Frivilliga mjuka bindestreck och automatiska bindestreck ritas bara ut när brytningen de markerar är den brytning som faktiskt väljs. Det låter självklart och är ett klassiskt fel: en naiv implementation skriver bindestreckstecknet under mätningen, och om brytningen flyttas blir bindestrecket kvar mitt i en rad. Inget ser mer ut som en trasig textmotor än ett bindestreck som blivit kvar mitt inuti ett ord
var
Lib: TPDFlib;
Flow, Needed: Integer;
begin
// Bestäm layouten innan något ritas
Flow := Lib.NewTextFlow(ArticleBody);
try
Lib.SetTextFlowLanguage(Flow, 'fr');
Lib.SetTextFlowHyphenation(Flow, 1, 3, 3);
// Rader resten av textstycket behöver vid en spaltbredd
Needed := Lib.MeasureTextFlow(Flow, 148);
if Needed > 3 * LinesPerColumn then
UseTwoPageSpread
else
UseSinglePage;
Lib.DrawTextFlowColumns(Flow, 72, 720, 480, 620, 3, 18, 1);
if Lib.TextFlowFinished(Flow) <> 1 then
CarryOver(Lib.GetTextFlowRemaining(Flow));
finally
Lib.ReleaseTextFlow(Flow);
end;
end;
Håll teckensnittsinställningarna identiska mellan rutor
En regel styr varje flödesbaserad layout och den är värd att säga rakt ut: DrawTextFlow, DrawTextFlowColumns och MeasureTextFlow bryter alla rader med det teckensnitt som är valt i det ögonblick de anropas. Byt teckensnitt eller storlek mellan två rutor i samma flöde, eller starta en ny sida utan att välja om ett, och den andra rutan bryts annorlunda än vad den första mätte
Symptomet är rasande irriterande just för att det ser intermittent ut: text som får plats på sida ett flödar över på sida två, eller ett uppmätt radantal stämmer inte med det som ritades. Välj teckensnittet en gång före loopen, välj om det efter varje NewPage, och flödet beter sig som förväntat. När blandade skriftsystem förekommer i samma textstycke gäller lösningen som beskrivs i automatisk teckensnittsfallback för CJK och emoji-text både mätning och ritning, så bredderna förblir konsekventa även över fallback-blocken
För rapportlayouter där flödet är ett element bland sidhuvuden, sidfötter och datadrivna block, kombineras kompositionsmönstren i dataset-rapportmotorn rent med spaltflöden: mät först, placera de fasta inslagen, och ge sedan flödet vilket område som blir kvar
PDFlibPas är ett PDF-bibliotek för Delphi, C++Builder och Lazarus, och hela TextFlow-livscykeln, skapande, ritning, mätning, inspektion, återspolning och frisläppande, exponeras även genom DLL- och ActiveX-gränssnitten. Fullständig dokumentation finns på sidan för PDFlibPas Delphi PDF-bibliotek