A jelölt tartalom az a mechanizmus, amelyet az ISO 32000-1 §14.6 határoz meg az oldaltartalom címkézésére, és a tagged PDF és a PDF/UA is erre épül. A PDFium Component közvetlenül elérhetővé teszi: a PageObjectMarks minden BDC-címkét és tulajdonságlistáját kiolvassa egy oldalobjektumról, az AddPageObjectMark egyet ír, a RemovePageObjectMark egyet töröl, és a PageObjectMarkedContentID jelzi azt az MCID-t, amely a tartalmat a szerkezeti fához köti
Amíg a szerkezeti fa nem köthető vissza ahhoz a tartalomhoz, amelyet leír, az akadálymentességi eszközözés találgatás. A szerkezeti fa azt mondja „ez egy címsor”; az MCID mondja meg, hogy az a címsor valójában mely oldalakon mely jelöletek. Mindkét felet olvashatóvá kell tenni, mielőtt egy alkalmazás ellenőrizni, javítani vagy jelenteni tudja a címkézést
Mi egy jelölet, bájtokban?
Egy BDC operátor egy címkénévvel és egy opcionális tulajdonságlistával, amelyet EMC zár. A tartalomfolyamban így néz ki: /P <</MCID 3>> BDC ... EMC: a /P címke nevezi meg a szerepet, a szótár tulajdonságokat hordoz, és a két operátor között minden a jelölt tartalom. Egy oldalobjektum, amely abban a tartományban van, hordozza a jelöletet, amelyet a PDFium visszaküld, és amelyet a PDFium Component rekorddá alakít
A TPdfContentMark egy fogantyút, a címke Name-jét és egy TPdfContentMarkParam tömböt tartalmaz. Minden paraméternek van egy Key-je, egy Kind-ja és egy jelentésnélküli értékmezője, amelyet ez a fajta választ ki: pmpInt, pmpFloat, pmpString vagy pmpBlob. A fajta a PDFium saját típusjelentéséből származik, nem abból, hogy melyik getter sikerült, ami a különbség egy tulajdonságlista olvasása és egyről való találgatás között
var
Marks: TPdfContentMarks;
M: TPdfContentMark;
P: TPdfContentMarkParam;
I: Integer;
begin
Pdf.PageNumber := 1; // PageNumber is 1-based
for I := 0 to Pdf.ObjectCount - 1 do // page object indexes are 0-based
begin
Marks := Pdf.PageObjectMarks(I);
for M in Marks do
begin
Memo1.Lines.Add('mark ' + M.Name +
' (MCID ' + IntToStr(Pdf.PageObjectMarkedContentID(I)) + ')');
for P in M.Params do
case P.Kind of
pmpInt: Memo1.Lines.Add(' ' + P.Key + ' = ' + IntToStr(P.IntValue));
pmpString: Memo1.Lines.Add(' ' + P.Key + ' = ' + P.StringValue);
pmpFloat: Memo1.Lines.Add(' ' + P.Key + ' = ' + FloatToStr(P.FloatValue));
pmpBlob: Memo1.Lines.Add(' ' + P.Key + ' = ' +
IntToStr(Length(P.BlobValue)) + ' bytes');
end;
end;
end;
end;
Miért jelent a pmpUnknown két különböző dolgot?
A pmpUnknown akkor kerül visszaadásra, amikor a PDFium FPDF_OBJECT_UNKNOWN-ot jelent, és a PDFium azt egy nem létező kulcsra is visszaadja. A két eset ezen a rétegen nem különíthető el, és másnak feltüntetése rosszabb lenne, mint kimondani
A kódunkra vonatkozó gyakori következmény: a pmpUnknown-ot úgy kezeljük, mint „itt nincs használható érték”, nem mint egy típus, amelyet esetleg még dekódolhatnánk. Ha egy tulajdonság számít a workflow-nkban, ellenőrizzük, hogy jelen van-e egy általunk felismert fajtával, és ne következtessünk hiányt egy unknown-ból — egy olyan jelölet, amelynek tulajdonságlistáját nem tudjuk elolvasni, olyan jelölet, amelyről jelentést kell tennünk, nem amelyet csendben el kell fogadnunk
Egy jelölet-rekord pillanatkép, nem birtokolt fogantyú
A Handle mező a könyvtáré. Abban a pillanatban elévül, amikor a jelöletet eltávolítják, az oldalobjektumot megsemmisítik vagy az oldalt kirakják, így a rekord egy csak olvasható pillanatkép, rövid élettel. Gyorsítótárazzuk oldalváltás között, és egy olyan memóriára mutató mutatónk van, amelyet a motor visszavett
Ez ugyanaz a fegyelem, amely az oldalobjektum-fogantyúkra általánosságban vonatkozik a PDFiumnál, és ugyanott kapja el az embereket: egy jelölet-rekordokkal feltöltött lista-kontroll, egy felhasználó, aki másik oldalra navigál, és egy összeomlás, amely látszólag nem kapcsolódik a navigáláshoz. Másoljuk ki a szükséges értékeket — a nevet, a kulcsokat, a számokat —, és engedjük el a fogantyút. Az oldalobjektum-fogantyúk transzformáció utáni elévüléséről szóló jegyzetek tárgyalják az általános szabályt és azt, hogyan harap máshol
Jelölet hozzáadása, és a mentési lépés, amelyet könnyű kihagyni
Az AddPageObjectMark átveszi az oldalobjektum-indexet, egy címkenevet és egy teljes paraméterhalmazt. A paraméterek halmazként íródnak, nem kulcsonkénti foltozással, amiért a TPdfContentMarkParam-nak nincsenek Has* szenitinjei — az az „egy meglévő rekord egy mezőjének frissítése” eset, amelyeket ezek védenének, nem merül fel
Azt a részt érdemes nyíltan kimondani: egy jelölet hozzáadása újraépíti az oldaltartalom-folyamot, hogy a címke túltegye a mentést. Ennek kifejezettnek kellett lennie, mert a SaveAs önállóan nem regenerál tartalmat — egy olyan változás, amely csak az objektummodellben élt, eldobásra kerülne, és a mentett fájl pontosan úgy nézne ki, mint amelyivel kezdtük. Ha már adtunk valami egy PDFium-oldalhoz, és hiányzott a kimenetből, általában ez az oka
var
Params: TPdfContentMarkParams;
begin
SetLength(Params, 1);
Params[0].Key := 'MCID';
Params[0].Kind := pmpInt;
Params[0].IntValue := NextMcid;
Pdf.AddPageObjectMark(ObjectIndex, 'P', Params); // rebuilds the content stream
Pdf.UpdatePage;
Pdf.SaveAs('tagged-out.pdf');
end;
Mit tesz és mit nem tesz ez a dokumentumból?
A jelöletek önmagukban nem tesznek tagged PDF-et. Egy megfelelő tagged dokumentumhoz szerkezeti fa kell, amelynek elemei ezekre az MCID-kre hivatkoznak, egy /MarkInfo bejegyzés, amely taggedként deklarálja a dokumentumot, és olyan szerepnevek, amelyek azt jelentik, amit a szabvány mond. Egy /P jelölet írása olyan MCID-vel, amelyre egyetlen szerkezeti elem sem mutat, olyan tartalmat ad, amely taggednek állítja be magát, és egy olyan szerkezeti fát, amely sosem említi
Ahol a jelölt tartalom ezen a szinten valóban megéri a helyét, az a vizsgálat és a javítás: annak auditálása, hogy mely oldalobjektumok taggedek, olyan artifactok megtalálása, amelyeket úgy kellett volna megjelölni, vagy MCID-k szerkezeti fához való párosítása az árvák megtalálására. A munka szerkezeti-fa feléért lásd a PDF/UA szerkezeti fa-ellenőrzés átjárását, az olvasási élményért, amelyre a címkék végső soron szolgálnak, pedig az akadálymentes PDF-olvasó Delphiben építéséről szóló jegyzeteket
A PDFium Component magas szintű VCL API-t ad Delphi, C++Builder és Lazarus alkalmazásoknak a PDFium motor fölé, a jelölt tartalommal, a szerkezeti fákkal és az akadálymentesség-ellenőrzéssel mindennapi Pascal-kódból elérhetően — a teljes API-felülethez lásd a PDFium Component termékoldal-át