Az akadálymentes PDF olyan szerkezeten nyugszik, amelyet a látható oldal soha nem mutat meg: az ISO 32000-1 §14.7 szerinti struktúrafán. Ez címsorok, bekezdések, táblázatok és ábrák logikai hierarchiája, amely a kifestett tartalom fölé rétegződik, és szereptérképen át képződik le a szabványos szerepekre. A képernyőolvasó ezt a fát olvassa fel, nem az oldalra tett jeleket. Nélküle egy makulátlanul kinéző, generált számla jelentés szempontjából üres, mert a tartalomfolyam csak a rajzolási sorrendet rögzíti, semmi mást. A végösszeg elhangozhat a tételsorok előtt, a lábléc belevághat egy bekezdésbe, a tételtáblázat pedig szavak egyetlen tagolatlan folyamává eshet össze. Ennek megelőzési költsége az Ön javára billen. A szerkezet kibocsátása rajzolás közben percnyi kód; utólag beleépíteni kész dokumentumokba már helyreállítási projekt. A losLab PDF Library (PDF Library for Delphi) néhány hívásból álló kis készlettel teszi elérhetővé a fát Delphi és C++Builder alatt, és ezek minden rajzolási műveletet a saját logikai szerepébe csomagolnak
Hogyan kötődik a megjelölt tartalom a struktúrafához?
Két réteg működik együtt. A tartalomfolyamban a rajzolási műveletek megjelölt tartalmi szakaszokba kerülnek zárójelbe, amelyek mindegyike egész számú MCID értéket hordoz. A dokumentumkatalógusban a struktúrafa ezeket az MCID értékeket típusos elemek (H1, P, Table, Figure) hierarchiájába képezi le olyan attribútumokkal, mint az alternatív szöveg és a nyelv. Egyedi elemtípusok is szabályosak, de mindegyiknek szabványos szerepre kell feloldódnia a szereptérképen át (ISO 32000-1 §14.8.4). Az a tartalom, amely egyáltalán nem hordoz jelentést — vonalak, hátterek, ismétlődő oldalkellékek —, artifactként jelölendő, hogy a segítő technológia átugorja ahelyett, hogy mondat közben felolvasná
A PDF Library for Delphi mindkét réteget egyetlen zárójelpár mögött tartja karban. A BeginTag struktúraelemet nyit és elindítja a megjelölt tartalmi szakaszt, a rajzolási hívások ebbe esnek, az EndTag pedig mindkettőt lezárja. Az a könyvelés, amely a kézzel gyártott címkézést elgáncsolja — az MCID értékek, a szülőfa és az oldalhivatkozások —, belül történik, ahol nem tudja elrontani
Két dokumentumszintű kapcsoló keretezi a munkát, mielőtt bármely címke megnyílna. A SetMarkInfo írja ki azt a katalógusjelzőt, amely címkézettnek nyilvánítja a dokumentumot, az IsTaggedPDF pedig visszaolvassa, és ez az olcsó első vizsgálat, amikor arról dönt, van-e egy beérkező fájlban megőrzésre érdemes szerkezet. A nyelvnek két belépési pontja van. A SetDocumentLanguage önmagában állítja be a dokumentum alapértelmezését, míg a SetPDFUAMode a teljes PDF/UA kimenet bekapcsolásának részeként teszi ezt. Egy fájl hasznosan címkézhető anélkül is, hogy PDF/UA megfelelőséget állítana magáról, és a szakaszos bevezetés gyakran pontosan ott kezdődik
Címkézés rajzolás közben, nem utólag
A működő generálási minta az, hogy a címkezárójelet minden rajzolási hívás aláírásának részeként kezeli, soha nem későbbi menetként:
var
Lib: TPDFlib;
begin
Lib := TPDFlib.Create;
try
Lib.SetOrigin(1); // bal felső origó
Lib.SetPDFUAMode('en-US'); // a mentési verziót PDF 1.7-re emeli
Lib.SetInformation(1, 'Service Manual'); // a /Title kötelező a PDF/UA-hoz
Lib.AddRoleMap('ManualTitle', 'H1'); // egyedi típus -> szabványos szerep
Lib.AddStandardFont(4);
Lib.SetTextSize(18);
Lib.BeginTagEx2('ManualTitle', '', '', 'en-US', '', 'h1-cover', '');
Lib.DrawText(72, 96, 'Service Manual');
Lib.EndTag;
Lib.BeginTag('Figure', 'Exploded view of the gearbox assembly', '');
Lib.AddImageFromFile('gearbox.png', 0);
Lib.EndTag;
Lib.BeginArtifact('Layout'); // oldaldíszítés: kimarad az olvasásból
// ... vonalak és háttérszínezés rajzolása ...
Lib.EndArtifact;
Lib.SaveToFile('manual.pdf');
finally
Lib.Free;
end;
end;
Ebben a sorozatban három hívás hordoz megfelelőségi súlyt. A SetPDFUAMode bekapcsolja a PDF/UA kimenetet, és némán PDF 1.7-re emeli a dokumentumverziót, ami ütközik a verziórögzítéssel. Az a dokumentum, amelyet a LockSaveVersion PDF 1.4-re zárt, UA mód mellett megtagadja a mentést, és 602-es hibakódot ad vissza — ez az összeütközés jellemzően akkor bukkan fel, amikor az archiválási profilokat és az akadálymentességi követelményeket különböző csapatok állítják be. A SetInformation(1, ...) a dokumentum címét írja ki, amelyet az ISO 14289 szerint a megjelenítőknek a fájlnév helyett kell mutatniuk; ennek hiánya a vadonban az egyik leggyakoribb PDF/UA megállapítás. Az AddRoleMap az egyedi ManualTitle típust H1 szerepként regisztrálja, kihagyása esetén pedig az alább leírt diagnosztika feltérképezetlen szerepet jelez
A címsorszintek átgondolt irányelvet érdemelnek, nem az oldal kinézete alapján hozott alkalmi döntéseket. A képernyőolvasót használók címsor-billentyűparanccsal ugrálnak a szakaszok között, tehát az a sablon, amely H1 szintről H3 szintre lép, mert a köztes szint túl nagynak tűnt a látványtervben, csendben tönkreteszi ezt a navigációt, és semmilyen vizuális átnézés nem fogja elkapni. Pontosan ez az a hiba, amelynek megnevezésére a HEADING-LEVEL-SKIP diagnosztika létezik. Képezze le minden sablon vizuális stílusait egyszer, egyetlen helyen, rögzített címsorlétrára, és az elcsúszás el sem kezdődik
Táblázatok, amelyekben a képernyőolvasó valóban navigálni tud
A megrajzolt rácsvonalak képernyőn kívül semmit sem jelentenek. A képernyőolvasók szerkezeti kapcsolatokban navigálnak: mely cellák fejlécek, mit ural az egyes fejlécek, és hogyan kötődnek az adatcellák a fejlécekhez szabálytalan elrendezésekben. A struktúraelem-attribútum hívásai mind a hármat kezelik:
Lib.BeginTag('Table', '', '');
Lib.BeginTag('TR', '', '');
Lib.BeginTagEx2('TH', '', '', '', '', 'col-part', '');
Lib.SetStructElemScope('Column'); // csak addig érvényes, amíg ez a TH nyitva van
Lib.DrawText(72, 120, 'Part');
Lib.EndTag;
Lib.BeginTagEx2('TH', '', '', '', '', 'col-torque', '');
Lib.SetStructElemScope('Column');
Lib.SetStructElemColSpan(2); // a fejléc az érték- és a mértékegység-oszlopra terjed ki
Lib.DrawText(200, 120, 'Tightening torque');
Lib.EndTag;
Lib.EndTag;
Lib.BeginTag('TR', '', '');
Lib.BeginTag('TD', '', '');
Lib.SetStructElemHeaders('col-part'); // kifejezett kötés szabálytalan táblázatokhoz
Lib.DrawText(72, 140, 'M8 flange bolt');
Lib.EndTag;
Lib.EndTag;
Lib.EndTag; // Table
A sorrendi szabály szigorú, és némán érvényesül. Minden SetStructElem* hívás arra a címkére vonatkozik, amely abban a pillanatban nyitva van, a BeginTag és az EndTag hívása között, és 0 értéket ad vissza minden jelzés nélkül, ha nincs nyitott címke, vagy az attribútum nem vonatkozik az aktuálisra. Egy rossz helyre tett hívás egyszerűen elpárolog. Ha fejlesztés közben állításokba csomagolja a visszatérési értékeket, akkor még idejében elkapja az elcsúszást; magára hagyva egy hiányzó hatókör csak akkor derül ki, amikor egy akadálymentességi ellenőrzés valódi képernyőolvasót futtat végig a táblázaton. A BeginTagEx2 hívásán átadott elemazonosítók az azonosítófát táplálják (ISO 32000-1 §14.7.4), és eleve ettől lesz feloldható a SetStructElemHeaders kötése
Ugyanez az attribútumcsalád fedi le mindazt, amire a segítő technológia támaszkodik. A SetStructElemListNumbering deklarálja, hogyan címkézettek a listaelemek, így a képernyőolvasó a listán belüli helyzetet mondja be a felsorolásjelek felsorolása helyett. A SetStructElemBBox rögzíti az ábrák és táblázatok befoglaló keretét, amelyet az újratördelő nézetek használnak a tartalom elhelyezésére. A SetStructElemActualText helyettesítő szöveget ad azokhoz a szakaszokhoz, amelyek jelalakjai nem képezhetők le olvasható karakterekre, például egy vektorgrafikából összerakott iniciáléhoz. Mindegyik ugyanazt a szabályt követi: a nyitott címkéhez kötődik, vagy elpárolog
Artifactok, nyelv és a mentés előtti diagnosztikai kapu
Az ismétlődő oldalkellékek — vagyis az élőfejek, a hajtásjelek, a vízjelek és a háttérszínezések — a BeginArtifact és az EndArtifact zárójelei közé valók, hogy sose kerüljenek be az olvasási folyamba. A nyelv örökölhető. A dokumentum alapértelmezése a SetPDFUAMode argumentumából jön, egy másik nyelvű szakasz pedig elemenként írja felül a BeginTagEx vagy a SetStructElemLang hívással. Ettől marad kiejthető egy francia idézet egy angol kézikönyvben
Mentés előtt a GetPDFUADiagnostics lefuttatja a könyvtár szerkezeti ellenőrzéseit a memóriabeli dokumentumon, és szövegként adja vissza a megállapításokat, ahol az üres karakterlánc azt jelenti, hogy semmit sem talált. A kódok közvetlenül nevezik meg a klasszikus szerkesztési hibákat: a FIGURE-NO-ALT az alternatív szöveg nélküli képet, a HEADING-LEVEL-SKIP a H1 után következő H3 szintet, a ROLEMAP-UNMAPPED pedig a soha nem regisztrált egyedi típust. Drótozza ezt a fordítási folyamatba (állítsa elő a dokumentumkészletet, és buktassa el a lépést nem üres diagnosztika esetén), és az akadálymentességi visszalépésekből fordításidő-szerű hibák lesznek ahelyett, hogy hónapokkal későbbi ellenőrzési megállapítások lennének. A teljes megfelelőségi ítélet továbbra is a mentett fájl előellenőrzéséé, amelyet a PDF/A és PDF/UA előellenőrzés Delphiben tárgyal, mert bizonyos normalizálások csak a sorosítás során történnek meg
A jegyzetek közti navigációnak saját gombja van. A PDF/UA elvárja, hogy az űrlapmezők és hivatkozások billentyűzetes bejárása a szerkezeti sorrendet kövesse, és a SetTabOrderMode írja ki azt az oldalszintű tabulátorsorrend-bejegyzést, amelyet a megjelenítők tiszteletben tartanak, míg a GetTabOrderMode a beérkező fájlok ellenőrzéséhez áll rendelkezésre. Ez olyan követelmény, amelyet senki sem vesz észre, amíg egy csak billentyűzetet használó felhasználó hibát nem jelent, a helyes megoldás pedig dokumentumonként egyetlen hívásba kerül
A struktúrafák nem élnek túl minden egyesítést
A címkézett dokumentumok csak akkor maradnak címkézettek, ha minden későbbi feldolgozási lépés megőrzi a fát, és a PDF Library for Delphi éles pereme az egyesítési lista családja. A MergeFileListFast a struktúrafa megőrzését váltja sebességre. Ez a helyes alku beolvasott képkötegeknél és a helytelen címkézett jelentéseknél, mert a kimenet rendben megnyílik, azonosan rajzolódik ki, és csendben elvesztette az akadálymentességi rétegét. Használja az alapértelmezett MergeFileList hívást vagy a szigorú változatot, valahányszor bármely bemenet címkézett, és tegye az IsTaggedPDF hívást az összeállítás utáni ellenőrzések részévé, hogy egy laposra vasalt köteg ne juthasson ki anélkül, hogy bárki észrevenné. A nagy dokumentumkészletek összeállítási munkafolyamatai több ilyen alkut hordoznak, amelyeket a nagy PDF-ek egyesítéséről, darabolásáról és közvetlen eléréséről szóló cikk jár körül
Az ellenőrzési kör a könyvtáron kívül zárul: nyissa meg a kimenetet Acrobatban, vizsgálja meg a címkepanelt, és sabloncsaládonként legalább egy dokumentumot olvastasson fel valódi képernyőolvasóval. A diagnosztika a szerkezeti hibákat kapja el; azt az olvasási sorrendet, amely technikailag érvényes, gyakorlatilag mégis zavarba ejtő, csak emberi fül fogja meg. A kiértékelési változatok és a teljes címkézési API-hivatkozás a losLab PDF Library for Delphi termékoldalán találhatók