Tekninen artikkeli

PDFlibPas: tavutus ja tasapainotetut tekstipalstat

PDFlibPas virtaa säilytetyn tekstipätkän yhdestä 64:ään yhtä leveään palstaan DrawTextFlowColumns-metodilla, ja katkaisee sen rivit rajatulla kieliriippuvaisella tavutuksella, kun kutsut metodeja SetTextFlowLanguage ja SetTextFlowHyphenation. Yhdeksän kieltä on tuettuna, ja kieli voidaan periä asiakirjan Catalog-objektin /Lang-arvosta virtakohtaisen asettamisen sijaan

Molemmat ominaisuudet ovat olemassa samasta syystä: kapea palsta on paikka, jossa naiivi rivinkatkaisu lakkaa näyttämästä ladonnalta ja alkaa näyttää bugiraportilta

Miksi tasapalstattu teksti hajoaa kapeissa palstoissa?

Koska tasapalstaus jakaa ylijäävän tilan rivin sananvälien kesken, ja ylijäävä määrä riippuu siitä, mikä mahtuu. Leveässä mitassa ylijäämä on pieni, eikä silmä koskaan huomaa sitä. Puolita leveys, ja yksi pitkä sana, joka ei mahdu, siirtyy seuraavalle riville, jättäen edeltäjänsä imemään kaiken tuon tilan. Kolme tällaista riviä peräkkäin tuottaa pystysuuntaisia valkoisia kanavia, joita typografit kutsuvat joiksi, ja jotka lukijat kokevat tekstinä, jota on vaikea seurata tietämättä miksi

Tavutus korjaa syyn oireen sijaan sallimalla katkon sanan sisällä. Saksan ja hollannin yhdyssanat tekevät tästä välttämättömän: 24-merkkiselle substantiiville 60 millimetrin palstassa ei ole hyvää lopputulosta ilman katkokohtaa. Englanti sietää puuttumisen paremmin, minkä vuoksi englanninkieliset tuotteet toimittavat usein asettelukoodia, joka kaatuu ensimmäistä kertaa, kun saksalainen asiakas ajaa sitä

Mitkä kielet, ja mistä kieli tulee?

Tavutus kattaa englannin, saksan, hollannin, ranskan, espanjan, italian, portugalin, venäjän ja turkin. Aseta se eksplisiittisesti virtakohtaisesti SetTextFlowLanguage-metodilla, tai anna sen periytyä asiakirjan Catalog-objektin /Lang-merkinnästä, joka on arvo, jonka tagattu ja esteetön asiakirja jo kantaa

Tuota perintää kannattaa käyttää eikä ylikirjoittaa. Asiakirja, joka ilmoittaa kielensä Catalog-objektissa, kertoo ruudunlukijoille, hakuindeksoijille ja tavutukselle saman faktan yhdestä paikasta, ja yksi paikka on se, missä faktan pitäisi asua. Jos tuotat jo tagattua tulostetta, kuten kuvataan artikkelissa automaattinen tagaus esteettömille PDF-tiedostoille, kielimerkintä on asetettu, ja virta voi yksinkertaisesti seurata sitä

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');
      // Käytössä, vähintään 3 merkkiä ennen katkoa, 3 jälkeen
      Lib.SetTextFlowHyphenation(Flow, 1, 3, 3);
      Lib.SetTextFlowMinLines(Flow, 2);   // älä koskaan jätä yksittäistä riviä orvoksi

      repeat
        // Kolme palstaa 480 pt:n alueella, 18 pt:n välit, tasapainotettu
        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 ja MinSuffix ovat typografiaa, ei validointia

Kaksi kokonaislukua käyttöönottolipun jälkeen asettavat vähimmäismäärän merkkejä, joiden täytyy jäädä ennen ja jälkeen katkon. Kolme ja kolme on varovainen oletus, jonka useimmat talotyylit hyväksyvät. Kaksi ja kaksi tuottaa enemmän katkomahdollisuuksia ja huomattavasti rumempia tuloksia, koska kaksikirjaiminen fragmentti rivin lopussa lukeutuu kirjoitusvirheeltä

Nosta vähimmäismääriä, kun kirjasinkoko on suuri, jolloin jokainen fragmentti on visuaalisesti näkyvä, ja laske niitä vain, kun palsta on aidosti kapea ja olet päättänyt, että tiukka mitta on tärkeämpi kuin siisti. Tämä on talotyylipäätös eikä tekninen päätös, mikä on juuri syy siihen, miksi se on parametri eikä vakio

Mitä "tasapainotettu" oikeastaan tarkoittaa tässä?

Balance-parametri muuttaa käyttäytymistä vain pätkän lopussa. Tasapainotuksen ollessa päällä palstat lyhennetään täsmälleen yhtä suureen rivimäärään, kun kaikki jäljellä oleva mahtuu alueen sisään, mikä estää viimeistä sivua näyttämästä kahta täyttä palstaa ja kolmatta, jossa on yksi yksinäinen rivi. Kun pätkä ei mahdu, jokainen palsta säilyttää täyden korkeutensa, jotta sivu kantaa niin paljon tekstiä kuin se voi, ja loppu jatkuu seuraavalla sivulla

Tuo epäsymmetria on oikea oletus jatkuville asiakirjoille. Tasapainottaminen virtaavan artikkelin keskellä tuhlaisi pystysuuntaista tilaa jokaisella sivulla kosmeettisen efektin vuoksi, jota kukaan ei näe, koska palstat ovat joka tapauksessa täynnä. Tasapainottaminen lopussa on se paikka, jossa silmä todella huomaa, ja juuri siellä sitä sovelletaan

Rivinkatkaisu mittaa kokonaisia sanoja

Katkaisualgoritmi mittaa kokonaisia sanoja sen sijaan, että se keräisi merkkien leveyksiä, ja varaa rajatun haun ylikokoisille tokeneille, jotka eivät mahdu riville lainkaan, kuten URL-osoitteelle tai luettelonumerolle. Se pitää tavallisen tapauksen nopeana ja patologisen tapauksen rajattuna, sen sijaan että olisi toisin päin

Valinnaiset pehmeät tavuviivat ja automaattiset tavuviivat renderöidään vain, kun katko, jonka ne merkitsevät, on se katko, joka valitaan. Tämä kuulostaa itsestäänselvältä ja on klassinen virhe: naiivi toteutus kirjoittaa tavuviivamerkin mittauksen aikana, ja jos katko siirtyy, tavuviiva jää rivin keskelle. Mikään ei näytä enemmän rikkinäiseltä tekstimoottorilta kuin harhaan jäänyt tavuviiva sanan sisällä

var
  Lib: TPDFlib;
  Flow, Needed: Integer;
begin
  // Päätä asettelu ennen kuin piirrät mitään
  Flow := Lib.NewTextFlow(ArticleBody);
  try
    Lib.SetTextFlowLanguage(Flow, 'fr');
    Lib.SetTextFlowHyphenation(Flow, 1, 3, 3);

    // Rivit, jotka pätkän loppuosa tarvitsee yhden palstan leveydellä
    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;

Pidä fonttiasetukset identtisinä laatikoiden yli

Yksi sääntö hallitsee jokaista virtapohjaista asettelua, ja se kannattaa sanoa suoraan: DrawTextFlow, DrawTextFlowColumns ja MeasureTextFlow katkaisevat kaikki rivit käyttäen fonttia, joka on valittuna kutsuhetkellä. Vaihda fonttia tai kokoa kahden saman virran laatikon välillä, tai aloita uusi sivu valitsematta fonttia uudelleen, ja toinen laatikko katkeaa eri tavalla kuin mitä ensimmäinen mittasi

Oire on raivostuttava juuri siksi, että se näyttää ajoittaiselta: teksti, joka mahtuu sivulle yksi, ylivuotaa sivulla kaksi, tai mitattu rivimäärä on eri mieltä sen kanssa, mitä piirrettiin. Valitse fontti kerran ennen silmukkaa, valitse se uudelleen jokaisen NewPage-kutsun jälkeen, ja virta käyttäytyy oikein. Kun sekoitettuja kirjoitusjärjestelmiä esiintyy samassa pätkässä, artikkelissa automaattinen fonttivaraus CJK- ja emojitekstille kuvattu ratkaisu koskee sekä mittausta että piirtoa, joten leveydet pysyvät johdonmukaisina myös varausajojen yli

Raporttiasetteluille, joissa virta on yksi elementti otsikoiden, alatunnisteiden ja datavetoisten lohkojen joukossa, artikkelissa tietojoukkoraporttimoottori kuvatut kompositiokuviot yhdistyvät siististi palstavirtoihin: mittaa ensin, sijoita kiinteä kalustus, ja anna sitten virralle mikä tahansa alue, joka jää jäljelle

PDFlibPas on Delphi-, C++Builder- ja Lazarus-PDF-kirjasto, ja täydellinen TextFlow-elinkaari, luonti, piirto, mittaus, tarkastelu, kelaus taaksepäin ja vapautus, on paljastettu myös DLL- ja ActiveX-rajapintojen kautta. Täydellinen dokumentaatio löytyy sivulta PDFlibPas Delphi PDF library page