HotPDF vie minkä tahansa ladatun PDF-dokumentin sivun itsenäiseksi SVG-merkinnäksi yhdellä kutsulla, BuildLoadedPageSVG, joka palauttaa koko SVG-dokumentin merkkijonona. Viety merkintä sisältää sivun geometrian, tekstin oikeina SVG:n text-elementteinä, upotetut rasterikuvat sekä piirtotilan, jonka PDF-operaattorit olivat asettaneet kussakin piirtotoiminnossa
Juuri tämä viimeinen osa on kohta, jossa useimmat itse tehdyt muuntimet hiljaa pettävät. PDF-sivun muuttaminen SVG:ksi näyttää koordinaattiongelmalta, mutta osoittautuu tilaongelmaksi. PDF on pinokone, jonka piirtotila muuttuu sisältövirtaa tulkittaessa; SVG puolestaan on deklaratiivinen puu, jonka jokainen elementti kantaa omat esitysattribuuttinsa. Kaikki, mitä tulkki ei onnistu tallentamaan hetkellä, jolloin elementti tuotetaan, katoaa tulosteesta jäljettömiin, ja virhe on äänetön: tuloksena on kelvollinen SVG, joka piirtää hienovaraisesti väärän sivun
Miksi PDF-sivu ei vain muunnu suoraan SVG:ksi?
Kolme yhteensopimattomuutta tekevät muunnoksesta ei-triviaalin, ja kaikki kolme tuottavat tulosteen, joka näyttää uskottavalta, kunnes sitä vertaa rinnakkain alkuperäiseen. Ensimmäinen on y-akseli. PDF:n käyttäjätila kasvaa ylöspäin sivun vasemmasta alakulmasta; SVG kasvaa alaspäin vasemmasta yläkulmasta. Yksittäinen sivutason peilaus korjaa piirtokoordinaatit ja rikkoo sitten jokaisen glyyfin, koska koko piirtoalueen peilaaminen peilaa myös kirjainmuodot
Toinen yhteensopimattomuus on periytyminen. PDF:ssä q ja Q työntävät ja palauttavat piirtotilan pinosta, mikä kattaa viivan leveyden, viivan päätteen, viivan liitoksen, kulmarajan, viivakuvion, viivakuvion vaiheen ja alfa-arvon. SVG:ssä elementti, joka ei nimeä attribuuttia, perii sen esi-isäryhmältä, mikä on täysin eri näkyvyyssääntö. Vientityökalu, joka seuraa vain nykyistä muunnosmatriisia ja unohtaa piirtotilan, päästää Q:n jälkeen palautetun tilan vuotamaan seuraaviin elementteihin
Kolmas on se, että PDF ilmaisee useita asioita sopimuksenvaraisesti, ei arvon kautta. Viivan päätteet ja liitokset ovat kokonaislukuja, nollaviivanleveys tarkoittaa laitetilan hiusviivaa eikä näkymätöntä viivaa, ja piirto-operaattorien tähtimuunnokset muuttavat kiertosääntöä värin sijaan. Jokainen näistä vaatii käännöksen, ei kopiointia
Yksi kutsu tavalliseen tapaukseen
Tavalliseen tehtävään, jossa sivuja viedään verkkokatseluohjelmaa, diff-työkalua tai suunnittelun luovutusta varten, API-pinta on yksi funktio. BuildLoadedPageSVG ottaa nollapohjaisen sivuindeksin nykyisin ladattua dokumenttia vastaan ja palauttaa SVG-dokumentin AnsiString-tyyppisenä:
var
Pdf: THotPDF;
I: Integer;
Svg: AnsiString;
Output: TFileStream;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('statements.pdf', '') <= 0 then
Exit; // LoadFromFile palauttaa sivujen määrän
for I := 0 to Pdf.LoadedPageCount - 1 do
begin
Svg := Pdf.BuildLoadedPageSVG(I);
if Length(Svg) = 0 then
Continue;
Output := TFileStream.Create(Format('page-%d.svg', [I + 1]), fmCreate);
try
Output.WriteBuffer(Svg[1], Length(Svg));
finally
Output.Free;
end;
end;
finally
Pdf.Free;
end;
end;
Sama vienti on käytettävissä myös HotPDF:n komentorivityökalun export-svg-komentona, mikä on hyödyllistä koontiputkissa ja regressioskripteissä, joissa halutaan tekstinä diffattava esitys sivusta kirjoittamatta Pascal-koodia. Koska SVG on tekstiä, se toimii luontevana parina rasteripolulle, joka kuvataan artikkelissa PDF-sivun renderöinti bittikartaksi: bittikartta kertoo, miltä sivu näyttää, SVG kertoo, mistä se koostuu
Miten PDF-teksti kuvataan SVG:n text-elementeiksi?
HotPDF muodostaa tekstimatriisiketjun järjestyksessä etuliite kertaa CTM kertaa tekstimatriisi kertaa glyyfipeilaus, jossa glyyfipeilaus on oikealta kertominen matriisilla matrix(1,0,0,-1,0,0). Tämä oikeanpuoleinen tekijä on olemassa ainoastaan kumotakseen sivutason pystysuuntaisen peilauksen glyyfimuodoille, sillä muuten peilatussa paikallisessa kehyksessä piirretty SVG-teksti näkyisi ylösalaisin. Kun korjaus tehdään matriisissa erikoistapauskoodin sijaan, kierretty, peilattu ja vinoutettu teksti tulee kaikki oikein ilman ylimääräisiä haaroja
Vaakasuora sijoittelu käyttää SVG:n text-elementin monilukuista x-syntaksia, yksi koordinaatti merkkiä kohden, kertyneenä jokaisesta glyyfin etenemästä sekä kulloinkin voimassa olevasta merkkivälistyksestä Tc ja sanavälistyksestä Tw. Vaakasuora skaalaus Tz on taitettu tekstimatriisin a- ja c-sarakkeisiin erillisen tuottamisen sijaan, joten katseluohjelma, joka jättää huomiotta eksoottiset tekstiattribuutit, silti sijoittaa jokaisen glyyfin sinne, minne PDF sen asetti. Monimutkaisen muotoilun kautta tuotettu teksti, josta kerrotaan artikkelissa monimutkaisten kirjoitusjärjestelmien tekstin muotoilu, kulkee saman polun, koska muotoilija on jo ratkaissut klusterit sijoitetuiksi glyyfeiksi siihen mennessä, kun sisältövirtaa tulkitaan
Kierto ja kuvat: kaksi peilausta, jotka on helppo tehdä väärinpäin
Sivu, jolla on nollasta poikkeava /Rotate-arvo, tarvitsee esimuunnoksen, joka koostuu peilauksesta kierretyn piirtoalueen korkeutta vasten sekä kierrosta ilmaistuna y-ylös-näyttötilassa. Kolme kiertomatriisia ovat (0,-1,1,0,0,W) 90 asteelle, (-1,0,0,-1,W,H) 180 asteelle ja (0,1,-1,0,H,0) 270 asteelle, missä W ja H ovat sivun mitat ennen kiertoa. Näiden johtaminen käsin altistaa merkkivirheille juuri kolmessa kohdassa, joten vientityökalu muodostaa ne saman matriisikertolaskurutiinin kautta, joka käsittelee kaikki muutkin muunnokset
Upotetut kuvat tarvitsevat oman peilauksensa, koska PDF:n kuvatila sijoittaa ensimmäisen näyterivin yksikköneliön yläreunaan, kun taas SVG:n image-elementillä on y-alas-paikallinen kehys. Tuotettu muunnos on siis CTM oikealta kerrottuna matriisilla matrix(1,0,0,-1,0,1). Tämän tekeminen väärin tuottaa pystysuunnassa peilattuja valokuvia muuten täydellisellä sivulla, ja tällaisen virheen arvioija huomaa välittömästi, mutta automaattinen testi usein ei
Mitä piirtotilalaite todella säilyttää?
HotPDF ohjaa piirtotilan operaattorit w, J, j, M ja d erillisen valinnaisen laiterajapinnan kautta, joten viivan piirtotarkkuus lisättiin muuttamatta olemassa olevan sisältölaitteen vtable-taulua ja rikkomatta binaarista yhteensopivuutta aiempia versioita vasten käännetylle koodille. Käytännössä viety SVG saa käännettyjä avainsanoja raakojen PDF-kokonaislukujen sijaan:
// PDF:n kokonaislukuenumeraatioista tulee SVG:n avainsana-attribuutteja
// line cap 0, 1, 2 -> butt, round, square
// line join 0, 1, 2 -> miter, round, bevel
//
// Nollaviivanleveys tarkoittaa PDF:ssä laitetilan hiusviivaa, joten
// vientityökalu tuottaa vector-effect="non-scaling-stroke", jotta
// viiva pysyy näkyvänä ja lähes yhden laitepikselin levyisenä CTM:n jälkeen
//
// f* B* b* valitsevat parillinen-pariton-säännön ja tuottavat fill-rule="evenodd",
// kun taas f B b säilyttävät SVG:n oletuksena olevan nonzero-kiertosäännön
Tilan palautus Q:ssa kattaa läpinäkyvyyden, viivan leveyden, päätteen, liitoksen, kulmarajan, viivakuvion ja viivakuvion vaiheen yhdessä. Sisäkkäiset Form XObject -objektit tallentavat ja palauttavat saman täyden joukon rajoillaan, joten leimauksen sisällä määritelty katkoviivainen reuna ei voi vuotaa kuviotaan seuraavaan sivusisältöön. Jos seuraat jo leikkausta ja CTM-käyttäytymistä muista syistä, tämä on sama tilamalli, joka esiintyy artikkelissa EMF- ja WMF-vektorituonti, vain vastakkaiseen suuntaan käytettynä
Rajat, jotka kannattaa tuntea ennen käyttöönottoa
Vientityökalu on rehellinen kattavuudestaan, ja rajojen tunteminen etukäteen on halvempaa kuin niiden löytäminen tuotannossa. Väri saapuu SVG-laitteelle operaattoreiden rg, RG, g ja G kautta. Väriavaruuden ja scn:n kautta määritetyt täytöt, joilla Separation-, DeviceN- ja ICCBased-värit maalataan, eivät saavu laitteelle ratkaistuna RGB-kolmikkona, joten sivut, jotka käyttävät spottivärejä tällä tavoin, vievät geometriansa mutta eivät näitä värejä. Painotarkoituksiin suunnatuille lähteille rasteroi sen sijaan tai litistä spottivärit ensin; itse maalausmalli käydään läpi artikkelissa Separation- ja DeviceN-spottivärien renderöinti
Kaksi pienempää huomiota säästää vianetsintäaikaa. Heksadesimaaliset värikirjaimet tuotetaan isoin kirjaimin, joten testi, joka väittää arvoa #ff0000, epäonnistuu täysin oikeaa arvoa #FF0000 vastaan. Ja SVG-laite on viiteytetty rajapintansa kautta, mikä tarkoittaa, että sen vapauttaminen tapahtuu antamalla rajapinnan pudota käytöstä Free-kutsun sijaan objektille, ja tällä erolla on merkitystä, jos laajennat laitetta tuottamaan omaa merkintääsi sivusisällön rinnalle
SVG-vienti sopii luontevasti yhteen rakenteellisen vertailun kanssa, kun on tarpeen tietää, muuttuiko tuotettu dokumentti todella kahden koonnoksen välillä. Laajempi ladattujen dokumenttien ympärillä oleva työkalupakki, renderöinnistä muokkaukseen ja vientiin, on dokumentoitu sivulla HotPDF Delphi PDF -komponentin sivulla