HotPDF izvozi stranicu bilo kog učitanog PDF dokumenta u samostalni SVG markup jednim pozivom, BuildLoadedPageSVG, koji vraća kompletan SVG dokument kao string. Izvezeni markup nosi geometriju stranice, tekst kao prave SVG text elemente, ugrađene rasterske slike i stanje poteza koje su PDF operatori uspostavili pri svakoj operaciji crtanja
Tu se najčešće raspadaju domaći konvertori, tiho i neprimetno. Pretvaranje PDF stranice u SVG deluje kao problem koordinata, a ispostavlja se da je problem stanja. PDF je stek mašina čije se grafičko stanje menja dok se interpretira tok sadržaja; SVG je deklarativno stablo čiji svaki element nosi sopstvene atribute prikaza. Sve što interpreter ne uspe da snimi u trenutku kada se element emituje jednostavno nestaje iz izlaza, a otkaz je tih: dobijate ispravan SVG koji renderuje suptilno pogrešnu stranicu
Zašto se PDF stranica ne pretvara jednostavno u SVG?
Tri neslaganja čine konverziju netrivijalnom, i sva tri proizvode izlaz koji izgleda uverljivo dok ga ne uporedite jedno pored drugog sa originalom. Prvo je y-osa. PDF korisnički prostor raste naviše od donjeg levog ugla stranice; SVG raste naniže od gornjeg levog. Jedno okretanje na nivou cele stranice ispravlja koordinate crtanja, a zatim pokvari svaki glif, jer okretanje celog platna takođe ogleda oblike slova
Drugo neslaganje je nasleđivanje. U PDF-u, q i Q guraju i skidaju grafičko stanje koje uključuje širinu linije, završetak linije, spoj linija, granicu zaošijavanja, šablon isprekidane linije, fazu isprekidane linije i alfu. U SVG-u, element koji ne navodi atribut nasleđuje ga od pretka-grupe, što je potpuno drugačije pravilo opsega. Izvoznik koji prati samo trenutnu matricu transformacije, a zaboravi stanje poteza, dozvoljava da vraćeno stanje posle Q procuri u elemente koji slede
Treće je da PDF izražava nekoliko stvari konvencijom, a ne vrednošću. Završeci i spojevi linija su celi brojevi, nulta širina linije znači liniju tanku kao dlaka u prostoru uređaja, a ne nevidljivu liniju, a zvezda-varijante operatora za bojenje menjaju pravilo namotavanja umesto boje. Svaka od njih zahteva prevod, ne kopiju
Jedan poziv za uobičajen slučaj
Za uobičajen posao izvoza stranica za veb pregledač, alat za poređenje razlika ili predaju dizajna, površina API-ja je jedna funkcija. BuildLoadedPageSVG uzima indeks stranice od nule za trenutno učitan dokument i vraća SVG dokument kao AnsiString:
var
Pdf: THotPDF;
I: Integer;
Svg: AnsiString;
Output: TFileStream;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('statements.pdf', '') <= 0 then
Exit; // LoadFromFile vraća broj stranica
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;
Isti izvoz je izložen preko HotPDF alatke za komandnu liniju kao njena komanda export-svg, koja je korisna u pipeline-ovima izgradnje i regresionim skriptama gde želite reprezentaciju stranice koja se može upoređivati kao tekst, bez pisanja ijedne linije Pascal koda. Pošto je SVG tekst, prirodno se nadopunjuje sa rasterskim putem opisanim u renderovanju PDF stranice u bitmapu: bitmapa vam govori kako stranica izgleda, SVG vam govori od čega je napravljena
Kako se PDF tekst mapira na SVG text elemente?
HotPDF sastavlja lanac matrice teksta kao prefiks puta CTM puta matrica teksta puta okretanje glifa, gde je okretanje glifa desno množenje sa matrix(1,0,0,-1,0,0). Taj desni faktor postoji isključivo da poništi vertikalno okretanje na nivou stranice za oblike glifova, jer bi SVG tekst nacrtan u okrenutom lokalnom okviru inače izgledao naopako. Stavljanje ispravke u matricu umesto u posebno obrađen kod znači da rotiran, ogledalski i iskošen tekst svi ispadnu ispravno bez dodatnih grananja
Horizontalno pozicioniranje koristi sintaksu x sa više vrednosti SVG text elementa, jednu koordinatu po karakteru, akumuliranu iz svakog pomaka glifa plus razmak karaktera Tc i razmak reči Tw koji su bili na snazi u tom trenutku. Horizontalno skaliranje Tz je uklopljeno u a i c kolone matrice teksta umesto da se emituje posebno, tako da pregledač koji ignoriše egzotične atribute teksta ipak postavlja svaki glif tamo gde ga je PDF postavio. Tekst proizveden složenim oblikovanjem, obrađen u oblikovanju teksta složenih pisama, prolazi istim putem, jer je oblikovač već razrešio klastere u pozicionirane glifove do trenutka kada se tok sadržaja interpretira
Rotacija i slike: dva okretanja koja se lako pobrkaju
Stranica sa nenultim unosom /Rotate zahteva pred-transformaciju sastavljenu od okretanja u odnosu na visinu rotiranog platna i rotacije izražene u prostoru prikaza sa y-osom naviše. Tri matrice rotacije su (0,-1,1,0,0,W) za 90 stepeni, (-1,0,0,-1,W,H) za 180 i (0,1,-1,0,H,0) za 270, gde su W i H dimenzije stranice pre rotacije. Izvođenje ovih ručno poziva na greške u znaku tačno na tri mesta, pa izvoznik sastavlja ih kroz istu rutinu množenja matrica koja obrađuje svaku drugu transformaciju
Ugrađene slike zahtevaju sopstveno okretanje, jer PDF prostor slike stavlja prvi red uzoraka na gornju ivicu jediničnog kvadrata, dok SVG image element nosi lokalni okvir sa y-osom naniže. Emitovana transformacija je stoga CTM pomnožen zdesna sa matrix(1,0,0,-1,0,1). Pogrešno urađeno ovo proizvodi vertikalno ogledalske fotografije na inače savršenoj stranici, što je vrsta defekta koju recenzent primeti odmah, a automatizovan test često ne primeti
Šta uređaj grafičkog stanja zapravo čuva?
HotPDF prosleđuje operatore stanja poteza w, J, j, M i d kroz poseban opcioni interfejs uređaja, tako da je vernost poteza dodata bez menjanja vtabele postojećeg uređaja sadržaja i bez kvarenja binarne kompatibilnosti za kod izgrađen na starijim verzijama. Konkretno, izvezeni SVG dobija prevedene ključne reči umesto sirovih PDF celih brojeva:
// PDF celobrojne enumeracije postaju SVG ključne reči atributa
// završetak linije 0, 1, 2 -> butt, round, square
// spoj linija 0, 1, 2 -> miter, round, bevel
//
// Nulta širina linije u PDF-u znači liniju tanku kao dlaka u prostoru
// uređaja, pa izvoznik emituje vector-effect="non-scaling-stroke" da
// zadrži potez vidljivim i blizu jednog piksela uređaja posle CTM-a
//
// f* B* b* biraju pravilo parno-neparno i emituju fill-rule="evenodd",
// dok f B b zadržavaju SVG podrazumevano nenulto namotavanje
Vraćanje stanja pri Q pokriva neprozirnost, širinu linije, završetak, spoj, granicu zaošijavanja, šablon isprekidane linije i fazu isprekidane linije zajedno. Ugnježdeni Form XObjects snimaju i vraćaju isti pun skup na svojim granicama, tako da isprekidana ivica definisana unutar pečata ne može procuriti svoj šablon u sadržaj stranice koji sledi. Ako već pratite ponašanje isecanja i CTM-a iz drugih razloga, ovo je isti model stanja koji se pojavljuje u uvozu EMF i WMF vektora, koji se odvija u suprotnom smeru
Granice koje vredi znati pre nego što ga pustite u produkciju
Izvoznik je iskren o svom obimu, a učenje granica unapred jeftinije je nego njihovo otkrivanje u produkciji. Boja stiže do SVG uređaja kroz operatore rg, RG, g i G. Popune uspostavljene kroz prostor boja plus scn, što je način na koji se boje Separation, DeviceN i ICCBased iscrtavaju, ne stižu do uređaja kao razrešena RGB trojka, pa stranice koje ovako koriste tačne boje izvoze svoju geometriju, ali ne i te boje. Za izvore orijentisane na štampu, rasterizujte umesto toga ili prvo spljoštite tačne boje; sam model bojenja je obrađen u renderovanju Separation i DeviceN tačnih boja
Dve manje napomene štede vreme otklanjanja grešaka. Heksadecimalni literali boja se emituju velikim slovima, tako da test koji tvrdi #ff0000 ne uspe protiv savršeno ispravnog #FF0000. A SVG uređaj se broji referencama kroz svoj interfejs, što znači da je njegovo oslobađanje pitanje puštanja interfejsa da izađe iz opsega, a ne pozivanja Free na objektu, razlika koja je bitna ako proširite uređaj da emituje sopstveni markup uz sadržaj stranice
SVG izvoz se prirodno uparuje sa strukturnim poređenjem kada trebate znati da li se generisani dokument zaista promenio između dve izgradnje. Šira zbirka alatki oko učitanih dokumenata, od renderovanja preko uređivanja do izvoza, dokumentovana je na stranici HotPDF Delphi PDF komponente