Šrafiranje koje se renderira kao jedan ravni sivi blok klasičan je neuspjeh tiling uzorka. HotPDF, izvorna VCL PDF komponenta za Delphi i C++Builder, boji PatternType 1 pretvarajući trenutnu putanju u privremeni clip i ponovno reproducirajući sadržajni stream uzorka jednom po vidljivoj pločici, s odabirom uzorka koji se drži u stanju grafike i vraća pomoću q i Q
Simptomi stižu u dva okusa, i izgledaju nepovezano dok ne saznate uzrok. CAD crtež gubi svoje presječno šrafiranje i vraća se kao pune ispune, jer je renderer razriješio uzorak u prosječnu boju i obojio to. Ili šrafiranje pobjegne: naslovni okvir koji bi trebao biti obično bijel pokupi dijagonalne linije iz detaljnog prikaza dva puta ranije. Oboje su problemi stanja uzorka, a samo je jedan uopće o crtanju pločica
Zašto tiling uzorak procuri u sljedeću putanju?
Zato što je odabrano ime uzorka dio stanja grafike, a ne svojstvo operatora koji ga je koristio. ISO 32000-1 §8.6.6.2 definira Pattern prostor boje kao onaj čija je vrijednost boje ime uzorka dostavljeno scn ili SCN, a svaka druga komponenta stanja boje spremljena je s q i vraćena s Q. Ime uzorka mora slijediti isto pravilo. HotPDF ga drži u zapisu stanja kao FillPatternName i StrokePatternName, uz obitelj prostora boje ispune i poteza, tako da Q vraća prethodni odabir točno onako kako vraća prethodni CTM
Pohranite li to ime umjesto toga u lokalnu varijablu unutar dispečera operatora, ono preživljava svaki Q u streamu. Neuspjeh se onda pojavi negdje neočekivano: Form XObject nacrtan nakon uzorkovane putanje nasljeđuje odabir uzorka koji njegov vlastiti sadržajni stream nikad nije napravio, a njegove ispune izlaze šrafirane. Ugniježđeni obrasci to pogoršavaju, jer svaka razina ugniježđenja gura i skida stanje koje zalutala varijabla ignorira. Postavljanje prostora boje koji nije uzorak pomoću cs ili CS, ili izdavanje običnog g / rg / k, također mora obrisati ime uzorka, inače zastarjeli odabir nadživljava prostor boje koji mu je dao značenje
q
/Pattern cs % pattern colour space, ISO 32000-1 8.6.6.2
/P1 scn % coloured tiling pattern, PaintType 1
10 10 200 120 re f % this rectangle is hatched
Q
0 0 300 200 re f % must be black again, not hatched
q
/Cs2 cs % [/Pattern /DeviceCMYK] array
0 0.6 1 0 /P2 scn % uncoloured pattern plus its underlying colour
20 20 160 90 re f*
Q
Uzorak se boji kroz clip, nikad kao ispuna
Ispravan model je oduzimajući: ograničiti clip uređaja na oblik koji se boji, zatim pokrenuti sadržaj uzorka unutar njega. HotPDF nikad ne crta punu aproksimaciju prvo pa je premazuje, jer bi srednja puna boja bila vidljiva kroz razmake između pločica i sukobila bi se s bilo kojom prozirnošću u sadržaju pločice. §8.7.3.2 opisuje tiling uzorak kao sadržajni stream repliciran u fiksnim vodoravnim i okomitim razmacima, a repliciranje ima smisla samo nasuprot clipu koji već ima pravi oblik. Za ispune pretvorba je izravna: HPDFSelectFillPathClip postavlja način ispune poligona na ALTERNATE za f*, B* i b*, a na WINDING za nulte varijante, gradi GDI putanju i presijeca je u clip pomoću SelectClipPath. Upravo ta jedna linija čini da uzorkovana ispuna even-odd ostavlja iste rupe kao puna ispuna even-odd, što je točno ono što regija šrafirana u obliku krafne treba
Potezi su dio koji je lako pogrešno napraviti. Potez nema unutrašnjost, pa presijecanje same putanje u clip daje praznu regiju i ništa se ne boji. HPDFSelectStrokePathClip stoga prvo gradi geometrijsko pero iz trenutnog stanja, koristeći PS_GEOMETRIC s krajnjim vrhom iz J, spojem iz j, granicom miter iz M, i PS_USERSTYLE kad je aktivan niz crtica, zatim poziva WidenPath za pretvaranje obrisa poteza u ispunjivu regiju prije obrezivanja. Ponašanje kraja, spoja, mitera i crtica na uzorkom potegnutoj putanji tada se poklapa s normalnim potezom po konstrukciji, a ne po drugoj implementaciji. Dvije iskrene granice žive ovdje: širine linija ispod jedne jedinice uređaja stežu se na jedan piksel, a niz crtica se skraćuje na šesnaest unosa, što je granica koju ExtCreatePen prihvaća
Koje su pločice zapravo vidljive?
Vidljivi raspon dolazi iz izvođenja transformacije unatrag. Postavljanje pločica događa se u prostoru uzorka, ali jedino što zna koliko se stranice dotiče je okvir clipa uređaja, koji je u prostoru uređaja. HotPDF sastavlja BaseMatrix := CTM * PatternMatrix, invertira ga, i mapira četiri kuta GDI okvira clipa natrag kroz inverz. Osno poravnate granice tih četiri mapirana kuta daju pravokutnik u prostoru uzorka koji se možda pokriva, a dijeljenje tog pravokutnika s XStep i YStep nasuprot BBox uzorka daje zatvorene raspone indeksa. Svaka se ćelija zatim renderira s CTM-om CTM * PatternMatrix * Translate(i * XStep, j * YStep), i obrezuje se drugi put na svoj vlastiti transformirani poligon BBox. Taj drugi clip bitan je kad je XStep manji od širine graničnog okvira, što je način na koji se izražavaju preklapajući dizajni pločica; bez njega bi susjedne ćelije bojile jedna preko druge izvan svog deklariranog dosega. Ako se clip po ćeliji vrati kao NULLREGION, ćelija se preskače bez tokeniziranja ili izvršavanja ičega
// Map the device clip box back into pattern space through the inverse of
// CTM * PatternMatrix, then convert those bounds into tile index ranges.
BaseMatrix := HPDFMatMul(FGSStack.State.CTM, PatternMatrix);
if not HPDFMatInvert(BaseMatrix, InverseMatrix) then Exit; // singular: refuse
if GetClipBox(FDC, ClipRect) = ERROR then Exit;
// MinX..MaxY are the axis-aligned bounds of the four mapped clip corners.
I0 := Floor((MinX - BBox[2]) / StepXAbs);
I1 := Ceil ((MaxX - BBox[0]) / StepXAbs);
J0 := Floor((MinY - BBox[3]) / StepYAbs);
J1 := Ceil ((MaxY - BBox[1]) / StepYAbs);
PlannedTiles := Int64(I1 - I0 + 1) * Int64(J1 - J0 + 1);
if (PlannedTiles <= 0) or (PlannedTiles > FPatternTilesRemaining) then Exit;
Dec(FPatternTilesRemaining, Integer(PlannedTiles));
Neobojani uzorci i boja koja dolazi izvana
Uzorak PaintType 2 nosi oblik, ali ne i boju, a boja stiže s imenom uzorka. §8.7.3.2 propisuje da se neobojani uzorak koristi samo s Pattern prostorom boje koji deklarira temeljni prostor, pa scn prvo prima vrijednosti komponenti, a ime uzorka posljednje. HotPDF razrješava te komponente kroz temeljni prostor pohranjen u unosu prostora boje uzorka, što znači da se neobojano šrafiranje može obojiti Separation tintom ili kombinacijom DeviceN posve poput svake druge ispune; mehanika tog razrješavanja obrađena je u renderiranju Separation i DeviceN spot boja. Unutar pločice, dva tipa boje oštro se razilaze. Za PaintType 2 renderer postavlja zastavicu potiskivanja operatora boje za trajanje pločice, tako da se svaki g, rg, k ili scn u sadržaju uzorka ignorira, a svaka oznaka uzima izvana dostavljenu boju. Za PaintType 1 vrijedi suprotno: stanje ispune i poteza resetira se na PDF zadane vrijednosti, DeviceGray crno s identitetskim prostorom boje, a pločica sama sebe boji. Preskakanje tog resetiranja dopušta boji koja je slučajno bila trenutna kod operatora f da procuri u uzorak koji je trebao biti samoopisiv
Zašto se dubina stoga stanja grafike mora vratiti nakon svake pločice?
Zato što sadržajni stream uzorka smije biti neuravnotežen, a šteta se nakuplja preko ćelija. Pločica čiji stream sadrži tri operatora q i dva operatora Q ostavlja stog jedan okvir dubljim nego što je počeo. Vratite samo trenutni zapis stanja između ćelija i dubina nastavlja rasti, tako da ćelija broj dvjesto izvršava iz okvira stoga koji pripada ćeliji broj sto devedeset devet, s bilo kojim CTM-om i clipom koje je taj okvir nosio. HotPDF stoga snima zapis stanja i dubinu stoga prije petlje pločica i poziva RestoreSnapshot na vrhu svake iteracije, koja skraćuje stog natrag na spremljenu duljinu i ponovno instalira spremljeno stanje u jednom koraku. Rječnik Resources stranice i zastavica potiskivanja operatora boje vraćaju se na istoj granici, jer se pločica može referencirati na vlastite resurse i ne smije ih predati svom susjedu. Stanje clipa GDI-ja dobiva isti tretman kroz par SaveDC / RestoreDC oko svake ćelije, tako da pločica koja instalira vlastiti clip W n ne može smanjiti regiju dostupnu sljedećoj
Proračuni, odbijanja i ono što renderer neće crtati
Tiling uzorci su najlakše mjesto u PDF-u za pisanje datoteke uskraćivanja usluge, pa su granice tvrde brojke, a ne heuristike. Ugniježđenje uzoraka ograničeno je na dubinu 4, ista zaštita koja se koristi za rekurziju Form XObjecta, koja zaustavlja uzorak koji referencira sebe kroz vlastiti rječnik resursa. Jedno bojanje putanje smije izvršiti najviše 16.384 pločica ukupno, brojano unazad preko ugniježđenih uzoraka i resetirano samo kad počne bojanje najvanjskijeg uzorka. Mreža pločica čiji planirani broj ćelija premašuje ono što je preostalo od tog proračuna posve se odbija, prije nego se ijedna ćelija izvrši
Degenerirana geometrija se odbija, a ne aproksimira. Nedostajući ili nulte-površine BBox, XStep ili YStep čija je veličina ispod 1e-6, umnožak CTM * PatternMatrix bez inverza, mapirane koordinate clipa iznad 1e9, ili veličina indeksa iznad milijun, sve uzrokuje da bojanje uzorka vrati bez crtanja. Rezultat je neobojena regija umjesto obješene niti renderiranja, što je kompromis koji želite u paketnom pretvaraču. Performanse dolaze iz jedne odluke: stream uzorka tokenizira se jednom po bojanju pomoću HPDFTokenizeContentStream, a niz tokena ponovno se koristi preko svake vidljive ćelije, tako da broj pločica množi trošak izvršavanja, ali nikad trošak leksiranja
Renderiranje uzorkovane stranice iz Delphija
Ništa u podršci za uzorke ne mijenja pozivajući kod. Učitajte dokument, zatražite stranicu, i posao pločica događa se unutar tumača sadržajnog streama koji već pokreće renderiranje stranice u bitmapu. Isti tumač hrani bitmap, metafile i printer kontekste uređaja, pa šrafirani crtež koji izgleda ispravno u pregledu sličice ispisuje se s istom geometrijom pločica. Uzorci sjenčanja PatternType 2 idu drugom granom koja dijeli svoj put procjene s golim operatorom sh, opisan detaljno pod renderiranjem osnih i radijalnih sjenčanja
var
Pdf: THotPDF;
Bmp: TBitmap;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('assembly-drawing.pdf') > 0 then
begin
// Section hatching that previously flattened to a solid block now
// replays the tile content once per visible cell.
Bmp := Pdf.RenderLoadedPageToBitmap(0, 200);
if Assigned(Bmp) then
try
Bmp.SaveToFile('sheet1.bmp');
finally
Bmp.Free;
end;
end;
finally
Pdf.Free;
end;
end;
Kad uzorkovana regija i dalje izgleda pogrešno, provjerite tri klase neuspjeha redom. Regija koja je posve prazna obično znači odbijanje: ispitajte XStep, YStep i BBox za degenerirane vrijednosti, ili izbrojite pločice koje bi mreži trebale nasuprot granici od 16.384. Regija obojena u jednu ravnu boju znači da ime uzorka nikad nije stiglo do operatora bojanja, što upućuje na redoslijed cs i scn u streamu. Uzorak koji se pojavi gdje ne pripada znači obnovu stanja, a mjesto koje treba pogledati je rukovanje q / Q oko obrasca ili putanje koja ga je naslijedila
Tiling uzorci jedna su od onih PDF značajki koje ostaju nevidljive dok datoteka koja ih treba ne sleti u vaš inbox, a onda su cijeli posao. Ako gradite preglednike crteža, pretvarače inženjerskih dokumenata ili renderere izvještaja na Delphiju ili C++Builderu, puna komponenta i njen API renderiranja dokumentirani su na stranici HotPDF Delphi PDF komponente