Marked content adalah mekanisme yang didefinisikan ISO 32000-1 §14.6 untuk menandai konten halaman, dan tagged PDF dan PDF/UA keduanya dibangun di atasnya. PDFium Component mengeksposnya secara langsung: PageObjectMarks membaca setiap tag BDC dan property list-nya dari objek halaman, AddPageObjectMark menulis satu, RemovePageObjectMark menghapus satu, dan PageObjectMarkedContentID melaporkan MCID yang menautkan konten ke pohon struktur
Sampai pohon struktur dapat dihubungkan kembali ke konten yang dijelaskannya, tooling aksesibilitas adalah tebakan. Pohon struktur mengatakan "ini heading"; MCID mengatakan mark mana pada halaman mana heading itu sebenarnya. Kedua bagian harus dapat dibaca sebelum aplikasi dapat memeriksa, memperbaiki, atau melaporkan penandaan
Apa itu mark, dalam byte?
Operator BDC dengan nama tag dan property list opsional, ditutup oleh EMC. Di content stream terlihat seperti /P <</MCID 3>> BDC ... EMC: tag /P menamai peran, dictionary membawa properti, dan segalanya di antara operator adalah marked content. Objek halaman di dalam rentang itu membawa mark, yang adalah apa yang diserahkan PDFium kembali dan apa yang diubah PDFium Component menjadi record
TPdfContentMark menyimpan handle, Name tag, dan array TPdfContentMarkParam. Setiap parameter memiliki Key, Kind dan satu field nilai yang bermakna yang dipilih oleh kind itu: pmpInt, pmpFloat, pmpString atau pmpBlob. Kind datang dari laporan tipe PDFium sendiri alih-alih dari getter mana yang kebetulan berhasil, yang merupakan perbedaan antara membaca property list dan menebak-nebak satu
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;
Kenapa pmpUnknown berarti dua hal berbeda
pmpUnknown dikembalikan ketika PDFium melaporkan FPDF_OBJECT_UNKNOWN, dan PDFium juga mengembalikannya untuk kunci yang tidak ada. Dua kasus itu tidak dapat dibedakan di lapisan ini, dan berpura-pura sebaliknya lebih buruk daripada mengatakannya
Konsekuensi praktis untuk kode Anda: perlakukan pmpUnknown sebagai "tidak ada nilai yang dapat digunakan di sini" alih-alih sebagai tipe yang mungkin tetap Anda dekode. Jika properti penting bagi workflow Anda, verifikasi kehadirannya dengan kind yang Anda kenali, dan jangan menyimpulkan ketidakhadiran dari yang tidak dikenal — mark yang property list-nya tidak dapat Anda baca adalah mark yang harus Anda laporkan, bukan yang harus Anda terima diam-diam
Record mark adalah snapshot, bukan handle yang Anda miliki
Field Handle milik library. Ia menjadi basi saat mark dihapus, objek halaman dimusnahkan atau halaman dibongkar, jadi record adalah snapshot read-only dengan masa hidup pendek. Cache lintas peralihan halaman dan Anda memegang pointer ke memori yang telah diklaim kembali engine
Ini adalah disiplin yang sama yang berlaku untuk handle objek halaman secara umum di PDFium, dan ia menangkap orang di tempat yang sama: kontrol list yang diisi dengan record mark, pengguna menavigasi ke halaman lain, dan crash yang terlihat tidak terkait dengan navigasi. Salin nilai yang Anda butuhkan — nama, kunci, angka — dan lepaskan handlenya. Catatan tentang handle objek halaman menjadi basi setelah transform membahas aturan umum dan bagaimana ia menggigit di tempat lain
Menambahkan mark, dan langkah simpan yang mudah terlewat
AddPageObjectMark mengambil indeks objek halaman, nama tag, dan set parameter lengkap. Parameter ditulis sebagai set alih-alih ditambal satu kunci pada satu waktu, itulah mengapa TPdfContentMarkParam tidak punya sentinel Has* — kasus "perbarui satu field dari record yang ada" yang akan mereka jaga tidak muncul
Bagian yang patut dinyatakan secara eksplisit: menambahkan mark membangun kembali content stream halaman sehingga tag bertahan dari simpan. Ini harus eksplisit karena SaveAs tidak meregenerasi konten sendiri — perubahan yang hanya hidup di object model akan dibuang, dan file yang disimpan akan terlihat persis seperti yang Anda mulai. Jika Anda pernah menambahkan sesuatu ke halaman PDFium dan menemukannya hilang dari output, biasanya ini penyebabnya
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;
Apa yang ini lakukan dan tidak lakukan pada sebuah dokumen
Mark saja tidak membuat PDF tagged. Dokumen tagged yang patuh membutuhkan pohon struktur yang elemennya mereferensikan MCID ini, entri /MarkInfo yang mendeklarasikan dokumen ditandai, dan nama peran yang berarti apa yang dikatakan standar. Menulis mark /P dengan MCID yang tidak ditunjuk oleh elemen struktur apa pun memberi Anda konten yang mengklaim ditandai dan pohon struktur yang tidak pernah menyebutnya
Di mana marked content benar-benar menghasilkan nilainya pada level ini adalah inspeksi dan perbaikan: mengaudit objek halaman mana yang ditandai, menemukan artefak yang seharusnya ditandai sebagai demikian, atau mencocokkan MCID dengan pohon struktur untuk menemukan yatim. Untuk separuh pohon struktur dari pekerjaan itu, lihat panduan validasi pohon struktur PDF/UA, dan untuk pengalaman baca yang akhirnya menjadi tujuan tag, catatan tentang membangun pembaca PDF aksesibel di Delphi
PDFium Component memberikan aplikasi Delphi, C++Builder dan Lazarus API VCL tingkat tinggi di atas engine PDFium, dengan marked content, pohon struktur, dan validasi aksesibilitas yang dapat dijangkau dari kode Pascal biasa — lihat halaman produk PDFium Component untuk permukaan API lengkap