Označena vsebina je mehanizem, ki ga ISO 32000-1 §14.6 opredeljuje za označevanje vsebine strani, na njej pa sta zgrajena tako označeni PDF kot PDF/UA. PDFium Component jo izpostavi neposredno: PageObjectMarks prebere vsako oznako BDC in njen seznam lastnosti z objekta strani, AddPageObjectMark eno zapiše, RemovePageObjectMark eno izbriše, PageObjectMarkedContentID pa poroča o MCID, ki povezuje vsebino z drevesom strukture
Dokler drevesa strukture ni mogoče spojiti nazaj z vsebino, ki jo opisuje, je orodje dostopnosti ugibanje. Drevo strukture pravi "to je naslov"; MCID pove, katere oznake na kateri strani je ta naslov dejansko. Oboji polovici morata biti berljivi, preden aplikacija lahko preverja, popravlja ali poroča o označevanju
Kaj je oznaka, v bajtih?
Operator BDC z imenom oznake in izbirnim seznamom lastnosti, zaprt z EMC. V toku vsebine izgleda kot /P <</MCID 3>> BDC ... EMC: oznaka /P poimenuje vlogo, slovar nosi lastnosti, vse med operatorjema pa je označena vsebina. Objekt strani znotraj tega razpona nosi oznako, kar je tisto, kar vrne PDFium in kar PDFium Component spremeni v zapis
TPdfContentMark drži ročaj, oznako Name in polje TPdfContentMarkParam. Vsak parameter ima Key, Kind in eno smiselno polje vrednosti, ki ga izbere ta vrsta: pmpInt, pmpFloat, pmpString ali pmpBlob. Vrsta prihaja iz poročila o vrsti samega PDFium in ne od tega, kateri getter je slučajno uspel, kar je razlika med branjem seznama lastnosti in ugibanjem o njem
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;
Zakaj pmpUnknown pomeni dve različni stvari
pmpUnknown se vrne, ko PDFium poroča FPDF_OBJECT_UNKNOWN, PDFium pa to vrne tudi za ključ, ki ne obstaja. Obeh primerov na tej plasti ni mogoče razločiti in delati, kot da bi bilo, bi bilo huje kot priznati
Praktična posledica za vašo kodo: obravnavajte pmpUnknown kot "tukaj ni uporabne vrednosti" in ne kot vrsto, ki bi jo morda vseeno dekodirali. Če lastnost šteje za vaš delovni tok, preverite, da je prisotna z vrsto, ki jo prepoznate, in ne sklepite o odsotnosti iz neznanega — oznaka, katere seznama lastnosti ne morete prebrati, je oznaka, o kateri bi morali poročati, in ne tista, ki bi jo tiho sprejeli
Zapis oznake je posnetek in ne ročaj, ki ga posedujete
Polje Handle pripada knjižnici. Postane zastarelo v trenutku, ko je oznaka odstranjena, objekt strani uničen ali stran razložena, tako je zapis bralni posnetek s kratko življenjsko dobo. Predpomnilnite ga čez preklop strani in držite kazalec v pomnilnik, ki ga je pogon prevzel nazaj
To je ista disciplina, ki velja za ročaje objektov strani pri PDFiumu na splošno, in ljudi ujame na istem mestu: kontrolnik seznama, naseljen z zapisi oznak, uporabnik, ki navigira na drugo stran, in zrušitev, ki je videti nepovezana z navigacijo. Kopirajte ven vrednosti, ki jih potrebujete — ime, ključe, številke — in ročaj izpustite. Zapiski o zastarevanju ročajev objektov strani po transformaciji obravnavajo splošno pravilo in kako grize drugje
Dodajanje oznake in korak shranjevanja, ki ga je lahko spregledati
AddPageObjectMark vzame indeks objekta strani, ime oznake in popolno množico parametrov. Parametri se zapišejo kot množica in ne zakrpajo enega ključa naenkrat, zato TPdfContentMarkParam nima stražarskih Has* — primer "posodobi eno polje obstoječega zapisa", ki bi ga ti varovali, ne nastopi
Del, ki se splača povedati izrecno: dodajanje oznake znova zgradi tok vsebine strani, tako oznaka preživi shranjevanje. To je moralo biti izrecno, ker SaveAs sam po sebi ne regenerira vsebine — sprememba, ki bi živela samo v modelu objektov, bi bila zavržena, shranjena datoteka pa bi izgledala natanko tako kot tista, s katero ste začeli. Če ste kdaj dodali kaj na stran PDFium in ugotovili, da manjka v izhodu, je to običajno razlog
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;
Kaj to dokument naredi in česa ne
Oznake same ne naredijo označenega PDF. Skladen označeni dokument potrebuje drevo strukture, katerega elementi referencirajo te MCID, vnos /MarkInfo, ki dokument razglaša označen, in imena vlog, ki pomenijo to, kar pravi standard. Pisanje oznake /P z MCID, na katerega ne kaže noben element strukture, vam da vsebino, ki trdi, da je označena, in drevo strukture, ki se je nikoli ne dotakne
Kjer označena vsebina na tej ravni resnično prispeva svoj delež, so pregled in popravilo: revizija, kateri objekti strani so označeni, iskanje pripomočkov, ki bi morali biti označeni kot taki, ali primerjava MCID z drevesom strukture, da se najdejo sirote. Za polovico dela na drevesu strukture glejte sprehod skozi validacijo drevesa strukture PDF/UA, za izkušnjo branja, za katero so oznake končno namenjene, pa zapiske o gradnji dostopnega bralnika PDF v Delphiju
PDFium Component daje aplikacijam Delphi, C++Builder in Lazarus visokonivojski API VCL nad pogonom PDFium, z označeno vsebino, drevesi strukture in validacijo dostopnosti dosegljivimi iz običajne kode Pascal — glejte stran izdelka PDFium Component za popolno ploskev API