Stigne zahtev na vaš sto: uzmite gomilu već renderovanih izveštaja, zacrnite brojeve računa i pošaljite dve stranice po listu da biste uštedeli papir. Oba dela tog posla su operacije nad sadržajnim strimom na PDF-u koji niste vi stvorili, pa nema ljubaznog platna stranice na koje biste crtali i nema menadžera fontova na koje biste se oslonili. Direktno menjate graf objekata učitanog dokumenta, dodajući sirove operatorske crteže na stranicu koju je neki drugi alat već rasporedio. HotPDF za to izlaže tačno dve ulazne tačke, a opasnija od njih je ona koja izgleda bezazleno
HotPDF je nativna VCL PDF komponenta za Delphi i C++Builder. Njegov loaded-document API u devetoj verziji dodao je prve metode koje kreiraju potpuno novi sadržaj na stranici koju ste otvorili sa diska, a ne na onoj koju ste napravili od nule. Dve od njih su tema ovog teksta: RedactLoadedRect, koja boji neproziran pravougaonik preko nekog regiona, i StitchLoadedPage, koja skalira jednu stranicu i crta je na drugu. Obe rade tako što upisuju operatorske naredbe ISO 32000-1 §8.5 u strim /Contents sadržaja stranice. Razumevanje šta ti operatori rade, a još važnije šta ne rade, razlika je između alata koji radi i curenja podataka
Dodavanje operatora na učitanu stranicu
Kada stranicu pravite normalnim HotPDF API-jem, komponenta poseduje sadržajni strim i sama serijalizuje vaše TextOutTextOut/Contents i vektorske pozive. Učitana stranica je drugačija: njen NewIndirectStream je postojeći strim objekat, možda deljen, možda deo niza sadržaja, i morate da se ubacite u njega bez kvarenja onoga što već postoji. Deveto izdanje je uvelo tri mala pomoćnika koji to čine bezbednim. THPDFStreamObject dodeljuje svež indirektni /Length 0 sa praznim baferom i unosom ResolveLoadedStream; AppendLoadedStream prati indirektnu referencu do osnovnog strima; i /Length upisuje sirove bajtove na kraj strima i prepisuje
tako da sačuvani objekat ostane ispravan./ContentsObrazac koji slede obe javne metode je isti. Pronađite , razrešite ga do strima, i ako ne postoji upotrebljiv strim, napravite jedan i zakačite ga. Zatim dodajte operatore. Pošto novi bajtovi idu na kraj
strima, model slikara garantuje da će oni da se iscrtaju preko svega što je originalni raspored nacrtao. Taj redosled je čitav mehanizam iza pravougaonika za redakciju, i takođe je razlog što taj pravougaonik nije ono što većina ljudi misli da jeste
RedactLoadedRectRedactLoadedRect: neproziran pokrivač, ne brisanje
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('statement.pdf') > 0 then
begin
// Cover the account-number band on page 1 with solid black.
// Coordinates are PDF user space: origin bottom-left, points.
Pdf.RedactLoadedRect(0, 56, 690, 320, 706, 0, 0, 0);
Pdf.SaveLoadedDocument('statement-covered.pdf');
end;
finally
Pdf.Free;
end;
end;
uzima indeks stranice sa nulom kao početkom, četiri koordinate u korisničkom prostoru i tri komponente boje u opsegu 0–1:r g b rgNa nivou implementacije metoda emituje tri operatora u sadržajni strim: postavljanje boje ispune u DeviceRGB (x y w h re), putanju pravougaonika (f), i ispunu (X2 - X1). Širina i visina se izvode kao Y2 - Y1 i 0, 0, 0, pa prosleđujete dva suprotna ugla i puštate metodu da izračuna obim. Prosledite 1, 1, 1 za boju i dobićete crnu traku; prosledite /MediaBox za belu koja odgovara beloj stranici. Koordinate su sopstveni korisnički prostor učitane stranice, što znači da je početak u donjem levom uglu i da su jedinice poeni, a to takođe znači da vam treba GetLoadedPageBox stranice da biste nešto postavili precizno; pbMediaBox sa
daje vam to
Naziv metode kaže "Redact", i to je korisno upozorenje o tome kako će rezultat biti pogrešno pročitan, a ne obećanje šta briše. Implementacija je o tome iskrena i u sopstvenom komentaru: zove se "visual redaction primitive" i napominje da redakcija koja uklanja sadržaj zahteva interpreter sadržajnog strima koji prolazi i prepisuje postojeće operatore. Putanja učitanog dokumenta u HotPDF-u ovde to ne radi. Zato je bezbedno pravilo usko: koristite RedactLoadedRect za neosetljivo kozmetičko maskiranje — skrivanje nacrtnog vodenog žiga, praznjenje regiona pre snimka ekrana, prekrivanje zastarelog logotipa na internom probnom otisku. U trenutku kada bi stvar ispod pravougaonika bila važna ako procure, ova metoda je pogrešan alat, a pravi odgovor je da dokument ponovo generišete bez tih podataka ili da koristite pravi pipeline za uklanjanje sadržaja
StitchLoadedPage: skaliranje, pomeranje, crtanje
N-up slaganje je prijateljskiji problem zato što ništa nije skriveno, samo preuređeno. StitchLoadedPage uzima indeks ciljne stranice, indeks izvorne stranice, X/Y pomeraj i faktor skale, i crta izvor na cilj na toj poziciji i toj veličini:
// Overlay page 2 (index 1) onto page 1 (index 0),
// scaled to 70% and nudged up-right.
Pdf.StitchLoadedPage(0, 1, 40, 380, 0.7);
// Convenience 2-up: source page on the right half of the target.
Pdf.StitchLoadedPageSideBySide(0, 1);
Niz operatora koji dodaje je standardni transform-and-paint niz: q da sačuva grafičko stanje, cm matriца koja nosi skalu na dijagonali i pomeraj u slots za translaciju, /StitchSrc Do da pozove spoljni objekat, i Q da vrati stanje. q/Q par je važan: izoluje transformaciju tako da ušivena stranica ne prospe svoj koordinatni sistem u bilo šta što se naknadno doda. Metoda takođe štiti od očiglednih grešaka — indeksi van opsega, cilj jednak izvoru, nepozitivna skala (koju ona ograničava na 1.0) — i izlazi tiho umesto da baca izuzetak, pa proverite ulaze jer tihi no-op izgleda isto kao uspeh
StitchLoadedPageSideBySide je tanka pogodnost preko opšte metode. Ona čita širinu media box-a cilja, deli je na pola i poziva StitchLoadedPage sa tom poluširinom kao X pomerajem i fiksnom skalom od 0.5, stavljajući izvor na desnu polovinu. Ta hard-kodirana 0.5 pretpostavlja da izvor i cilj imaju istu širinu; ako je nemaju, izvor neće lepo ispuniti svoju polovinu i biće vam potrebna opšta StitchLoadedPage sa skalom koju sami izračunate iz oba media box-a
Ovde dolazimo do namernog prečica u implementaciji koju morate da znate pre nego što poverujete izlazu u različitim pregledima. Ispravno N-up slaganje obavija sadržaj izvorne stranice u Form XObject — samostalan objekat za crtanje koji ISO 32000-1 §8.10.1 kaže da mora da nosi
, /Type /XObject i sopstveni /Subtype /Form clipping box. Deveto izdanje HotPDF stitch ne gradi taj omotač. Umesto toga registruje samu /BBoxstranicu izvorne stranice direktno pod cilja pod imenom /Resources /XObject, a zatim je crta pomoću StitchSrc. Page dict i Form XObject dele dovoljno svog modela sadržaja — oba referišu na content stream i resource dictionary — da će mnogi čitači prikazati rezultat.DoAli to nije usaglašeni Form XObject. Nedostaje mu marker
i sopstveni /Subtype /Form, što znači da strogi potrošač ima pravo da /BBox ignoriše Do ili da ga iseče drugačije nego što očekujete. TechnicalNotes za ovu rundu to kaže otvoreno: pristup "renders under most readers" ali je "not a strictly ISO-compliant Form XObject", a potpuna usaglašenost zahteva da se pravi Form XObject stream sintetizuje kao poseban korak. Zato izlaz stitch-a tretirajte kao bilo koji neusaglašen konstrukt: proverite ga u konkretnim pregledima koje vaši kupci koriste, a ne samo u onom na vašoj mašini, i ako vam trebaju arhivski ili striktno-validatorski čisti PDF-ovi, ne oslanjajte se na ovu putanju. Ista disciplina važi za sve što gradite na učitanom grafu objekata, zbog čega jedan PDF preflight pass u Delphiju zaslužuje svoje mesto u release pipeline-u svaki put kada dokumente menjate programatski
Gde ovo spada, a gde ne spada
Obe metode su alati za sadržajni strim, pa je mentalni model isti kao kada direktno crtate. Ako ste stranicе gradili od nule komponentom, vektorski i kolor operatori iza ovih poziva delovaće poznato iz HotPDF canvas drawing u Delphiju; razlika je samo u tome što ovde dodajete sadržaj u strim koji je neko drugi autorisao, a ne u onaj koji je vaš. Držite tri granice u glavi:
- Redakcija je kozmetička.
RedactLoadedRectprekriva sadržaj i nikada ga ne briše. Za sve osetljivo, regenerišite izvor ili koristite pravo uklanjanje sadržaja — crna kutija nije bezbednost - Stitch je po dizajnu neusaglašen. izvorna stranica se referencira kao pseudo-XObject bez §8.10.1
/Subtype /Formi/BBoxi recite da proverite prikaz u svojim ciljanim pregledima i izbegavajte ovu putanju tamo gde je potrebna stroga validacija - Koordinate su korisnički prostor stranice. Donji levi početak, poeni, vođeni sopstvenim media box-om stranice. Pročitajte box pomoću
GetLoadedPageBoxpre nego što postavite bilo šta, jer stranica koju ste učitali možda nije veličine kakvu ste pretpostavili
Kada se koriste u tim granicama, ovaj par pokriva stvaran tok posla: preuređivanje stranica za štampu, maskiranje nepoverljivih regiona i upis rezultata nazad sa SaveLoadedDocument — sve bez potpunog ponovnog renderovanja. API za učitane dokumente koji uključuje ove stitch i mask primitive dolazi uz HotPDF Component za Delphi i C++Builder, zajedno sa metodama za polja formi, anotacije i FDF iz iste runde