Označeni sadržaj mehanizam je koji ISO 32000-1 §14.6 definira za označavanje sadržaja stranice, a na njemu su izgrađeni i označeni PDF i PDF/UA. PDFium Component izlaže ga izravno: PageObjectMarks čita svaku BDC oznaku i njen popis svojstava s objekta stranice, AddPageObjectMark zapisuje jednu, RemovePageObjectMark briše jednu, a PageObjectMarkedContentID prijavljuje MCID koji povezuje sadržaj sa stablom strukture
Dok se stablo strukture ne može spojiti natrag sa sadržajem koji opisuje, alati za pristupačnost puko su nagađanje. Stablo strukture kaže ovo je naslov; MCID kaže koje oznake na kojoj stranici taj naslov doista jesu. Obje polovice moraju biti čitljive prije nego što aplikacija može provjeriti, popraviti ili izviještavati o označavanju
Što je oznaka, u bajtovima?
Operator BDC s imenom oznake i neobaveznim popisom svojstava, zatvoren EMC-om. U streamu sadržaja izgleda kao /P <</MCID 3>> BDC ... EMC: oznaka /P imenuje ulogu, rječnik nosi svojstva, a sve između operatora jest označeni sadržaj. Objekt stranice unutar tog raspona nosi oznaku, što je što PDFium vraća i što PDFium Component pretvara u zapis
TPdfContentMark drži ručicu, oznaku Name i polje TPdfContentMarkParam. Svaki parametar ima Key, Kind i jedno značajno polje vrijednosti koje bira taj tip: pmpInt, pmpFloat, pmpString ili pmpBlob. Tip dolazi iz PDFiumovog vlastitog izvješća o tipu, a ne iz toga koji getter slučajno uspije, što je razlika između čitanja popisa svojstava i pogađanja istog
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;
Zašto pmpUnknown znači dvije različite stvari
pmpUnknown vraća se kad PDFium prijavi FPDF_OBJECT_UNKNOWN, a PDFium to vraća i za ključ koji ne postoji. Ta se dva slučaja na ovom sloju ne mogu razlikovati, a pretvaranje da se može bilo bi gore od toga da se kaže
Praktična posljedica za vaš kod: tretirajte pmpUnknown kao ovdje nema upotrebljive vrijednosti, a ne kao tip koji biste mogli dekodirati ionako. Ako svojstvo važi za vaš cjevovod, provjerite je li prisutno s tipom koji prepoznajete, i ne zaključujte o odsutnosti iz nepoznatog; oznaka čiji popis svojstava ne možete pročitati jeste oznaka o kojoj biste trebali izvijestiti, a ne ona koju biste šutke prihvatili
Zapis oznake jest snimka, a ne ručica koju posjedujete
Polje Handle pripada knjižnici. Postaje ustajalo čim je oznaka uklonjena, objekt stranice uništen ili stranica istovarena, pa je zapis snimka samo za čitanje s kratkim životom. Predmemorirajte je preko prebacivanja stranice i držite pokazivač u memoriju koju je motor povratio
To je ista disciplina koja se općenito primjenjuje na ručice objekata stranice u PDFiumu, i hvata ljude na istom mjestu: kontrola popisa popunjena zapisima oznaka, korisnik koji navigira na drugu stranicu i rušenje koje izgleda nepovezano s navigacijom. Kopirajte van vrijednosti koje trebate, ime, ključeve, brojeve, i pustite ručicu. Bilješke o ručicama objekata stranice koje postaju ustajale nakon transformacije pokrivaju opće pravilo i kako grize drugdje
Dodavanje oznake i korak spremanja koji je lako propustiti
AddPageObjectMark uzima indeks objekta stranice, ime oznake i potpuni skup parametara. Parametri se zapisuju kao skup, a ne zakrpljuju jedan ključ u vrijeme, što je razlog zašto TPdfContentMarkParam nema Has* čuvare: slučaj ažuriranja jednog polja postojećeg zapisa koji bi oni čuvali ne pojavljuje se
Dio koji vrijedi izreći izričito: dodavanje oznake ponovno izgrađuje stream sadržaja stranice tako da oznaka preživi spremanje. To je moralo biti izričito jer SaveAs sam po sebi ne obnavlja sadržaj; promjena koja je živjela samo u objektnom modelu bi se odbacila, a spremljena datoteka izgledala bi točno kao ona s kojom ste započeli. Ako ste ikad dodali nešto na PDFium stranicu i našli ga nedostajućeg u izlazu, to je obično 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;
Što ovo čini, a što ne čini od dokumenta
Samo oznake ne čine označeni PDF. Sukladni označeni dokument treba stablo strukture čiji elementi referenciraju te MCID-ove, unos /MarkInfo koji deklarira dokument označenim te imena uloga koja znače ono što standard kaže da znače. Pisanje oznake /P s MCID-om na koji nijedan element strukture ne pokazuje daje vam sadržaj koji tvrdi da je označen i stablo strukture koje ga nikad ne spominje
Gdje označeni sadržaj doista opravdava svoje mjesto na ovoj razini jest pregled i popravak: revizija koji su objekti stranice označeni, pronalaženje artefakata koji su trebali biti označeni kao takvi, ili usporedba MCID-ova sa stablom strukture da se pronađu siročad. Za polovicu stabla strukture u tom radu, pogledajte prikaz provjere valjanosti stabla strukture PDF/UA, a za iskustvo čitanja kojem su oznake naposljetku namijenjene, bilješke o izgradnji pristupačnog PDF čitača u Delphiju
PDFium Component daje aplikacijama Delphi, C++Builder i Lazarus visokorazinski VCL API preko PDFium motora, s označenim sadržajem, stablima strukture i provjerom valjanosti pristupačnosti dohvatljivima iz običnog Pascal koda. Pogledajte stranicu proizvoda PDFium Component za cijelu površinu API-ja