PDF yang aksesibel bertumpu pada satu struktur yang tidak pernah diperlihatkan halaman kasatmata: pohon struktur yang didefinisikan dalam ISO 32000-1 §14.7. Ia adalah hierarki logis berisi heading, paragraf, tabel, dan gambar, berlapis di atas konten yang dilukis dan dipetakan ke peran standar lewat sebuah role map. Pembaca layar membaca pohon itu, bukan tanda-tanda di halaman. Tanpanya, faktur yang dihasilkan dan tampak rapi jelita justru kosong secara semantik, sebab aliran konten hanya merekam urutan penggambaran dan tidak lebih. Totalnya bisa dibacakan sebelum baris rinciannya, footer-nya bisa menyelinap ke tengah paragraf, tabel itemnya bisa runtuh menjadi satu deretan kata tanpa pembeda. Ongkos mencegahnya berat sebelah dan menguntungkan Anda. Memancarkan struktur sambil menggambar hanya soal beberapa menit kode; memasangnya belakangan ke dokumen yang sudah jadi adalah proyek remediasi. losLab PDF Library (PDF Library for Delphi) memaparkan pohon itu ke Delphi dan C++Builder lewat sekumpulan kecil pemanggilan yang membungkus tiap operasi gambar dengan peran logisnya
Bagaimana marked content terikat ke pohon struktur
Dua lapisan bekerja sama. Di aliran konten, operasi penggambaran dikurung ke dalam sekuens marked-content, masing-masing membawa sebuah MCID bertipe integer. Di katalog dokumen, pohon struktur memetakan MCID itu menjadi hierarki elemen bertipe (H1, P, Table, Figure) berikut atribut seperti teks alternatif dan bahasa. Tipe elemen kustom itu sah, tetapi masing-masing wajib meresolusi ke peran standar lewat role map (ISO 32000-1 §14.8.4). Konten yang sama sekali tidak bermakna, seperti garis, latar belakang, dan perabot halaman yang berulang, ditandai sebagai artifact supaya teknologi bantu melewatinya alih-alih membacanya di tengah kalimat
PDF Library for Delphi memelihara kedua lapisan itu di balik satu pasang kurung. BeginTag membuka elemen struktur dan memulai sekuens marked-content, pemanggilan gambar mendarat di dalamnya, dan EndTag menutup keduanya. Pembukuan yang menjegal penandaan rakitan tangan, yakni MCID, pohon induk, dan referensi halaman, terjadi di dalam, di tempat yang tak bisa Anda salahi
Dua sakelar tingkat dokumen membingkai pekerjaan ini sebelum tag mana pun terbuka. SetMarkInfo menulis flag katalog yang menyatakan dokumen itu bertanda, dan IsTaggedPDF membacanya kembali, dan itulah penyelidikan pertama yang murah ketika memutuskan apakah berkas masuk punya struktur yang layak dipertahankan. Bahasa punya dua titik masuk. SetDocumentLanguage menetapkan default dokumen secara mandiri, sementara SetPDFUAMode menetapkannya sebagai bagian dari mengaktifkan keluaran PDF/UA penuh. Sebuah berkas bisa ditandai dengan berguna tanpa mengklaim konformansi PDF/UA, dan peluncuran bertahap sering bermula persis di titik itu
Menandai sambil menggambar, bukan sesudahnya
Pola pembangkitan yang berhasil adalah memperlakukan kurung tag sebagai bagian dari signature setiap pemanggilan gambar, bukan sebagai tahap belakangan:
var
Lib: TPDFlib;
begin
Lib := TPDFlib.Create;
try
Lib.SetOrigin(1); // titik asal kiri atas
Lib.SetPDFUAMode('en-US'); // menaikkan versi simpan ke PDF 1.7
Lib.SetInformation(1, 'Service Manual'); // /Title wajib untuk PDF/UA
Lib.AddRoleMap('ManualTitle', 'H1'); // tipe kustom -> peran standar
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'); // hiasan halaman: dikecualikan dari pembacaan
// ... gambar garis dan rona latar di sini ...
Lib.EndArtifact;
Lib.SaveToFile('manual.pdf');
finally
Lib.Free;
end;
end;
Tiga pemanggilan dalam rangkaian itu memikul bobot kepatuhan. SetPDFUAMode mengaktifkan keluaran PDF/UA dan diam-diam menaikkan versi dokumen ke PDF 1.7, dan itu bertabrakan dengan penguncian versi. Dokumen yang dikunci ke PDF 1.4 dengan LockSaveVersion menolak disimpan dan mengembalikan kode kesalahan 602 begitu mode UA aktif, benturan yang cenderung muncul ketika profil arsip dan persyaratan aksesibilitas dikonfigurasi oleh tim yang berbeda. SetInformation(1, ...) menulis judul dokumen, yang menurut ISO 14289 diharapkan ditampilkan viewer menggantikan nama berkas; ketiadaannya adalah salah satu temuan PDF/UA paling umum di lapangan. AddRoleMap mendaftarkan tipe kustom ManualTitle sebagai sebuah H1, dan melewatkannya membuat diagnostik yang dijelaskan di bawah menandai peran yang tak terpetakan
Tingkat heading pantas mendapat kebijakan yang disengaja, bukan pilihan dadakan demi tampilan sebuah halaman. Pengguna pembaca layar melompat antar bagian lewat pintasan heading, sehingga templat yang meloncat dari H1 ke H3 karena tingkat perantaranya terlihat terlalu besar dalam desain visual diam-diam merusak navigasi itu, dan tak ada tinjauan visual yang akan menangkapnya. Itu persis cacat yang keberadaan diagnostik HEADING-LEVEL-SKIP dimaksudkan untuk menyebutnya. Petakan gaya visual tiap templat ke satu tangga heading yang tetap, sekali saja, di satu tempat, dan pergeserannya tidak akan pernah bermula
Tabel yang sungguh dapat dinavigasi pembaca layar
Garis kisi yang digambar tidak berarti apa-apa di luar layar. Yang dinavigasi pembaca layar adalah hubungan struktural: sel mana yang berupa header, apa yang dinaungi tiap header, dan bagaimana sel data terikat ke header pada tata letak yang tidak beraturan. Pemanggilan atribut elemen struktur menangani ketiganya:
Lib.BeginTag('Table', '', '');
Lib.BeginTag('TR', '', '');
Lib.BeginTagEx2('TH', '', '', '', '', 'col-part', '');
Lib.SetStructElemScope('Column'); // hanya sah selagi TH ini terbuka
Lib.DrawText(72, 120, 'Part');
Lib.EndTag;
Lib.BeginTagEx2('TH', '', '', '', '', 'col-torque', '');
Lib.SetStructElemScope('Column');
Lib.SetStructElemColSpan(2); // header membentang ke kolom nilai dan satuan
Lib.DrawText(200, 120, 'Tightening torque');
Lib.EndTag;
Lib.EndTag;
Lib.BeginTag('TR', '', '');
Lib.BeginTag('TD', '', '');
Lib.SetStructElemHeaders('col-part'); // pengikatan eksplisit untuk tabel tak beraturan
Lib.DrawText(72, 140, 'M8 flange bolt');
Lib.EndTag;
Lib.EndTag;
Lib.EndTag; // Table
Aturan urutannya ketat dan ditegakkan dalam senyap. Setiap pemanggilan SetStructElem* berlaku untuk tag yang sedang terbuka pada saat itu, di antara BeginTag dan EndTag-nya, dan ia mengembalikan 0 tanpa melempar apa pun ketika tidak ada tag yang terbuka atau atributnya tidak berlaku untuk tag saat ini. Pemanggilan yang salah tempat sekadar lenyap. Membungkus nilai kembaliannya dalam assertion selama pengembangan menangkap pergeseran itu selagi Anda masih bisa melihatnya; jika dibiarkan, scope yang hilang baru muncul ketika audit aksesibilitas menjalankan pembaca layar sungguhan menyusuri tabelnya. ID elemen yang dioper lewat BeginTagEx2 memasok pohon ID (ISO 32000-1 §14.7.4), dan itulah yang membuat pengikatan SetStructElemHeaders bisa diresolusi sejak awal
Keluarga atribut yang sama mencakup sisa hal yang disandari teknologi bantu. SetStructElemListNumbering menyatakan bagaimana item daftar dilabeli, sehingga pembaca layar mengumumkan posisi di dalam daftar alih-alih melafalkan glif bullet. SetStructElemBBox merekam kotak pembatas gambar dan tabel, yang dipakai tampilan reflow untuk menempatkan konten. SetStructElemActualText memasok teks pengganti untuk deretan yang glifnya tidak memetakan ke karakter terbaca, misalnya drop cap yang dirakit dari seni vektor. Masing-masing mengikuti aturan yang sama: ia terikat ke tag yang terbuka, atau ia lenyap
Artifact, bahasa, dan gerbang diagnostik sebelum simpan
Perabot halaman yang berulang, yakni running header, tanda lipat, watermark, dan rona latar, seharusnya berada di dalam kurung BeginArtifact dan EndArtifact agar tidak pernah masuk ke aliran bacaan. Bahasa bersifat dapat diwariskan. Default dokumen datang dari argumen SetPDFUAMode, dan deretan berbahasa lain menimpanya per elemen lewat BeginTagEx atau SetStructElemLang. Itulah yang menjaga kutipan berbahasa Prancis di dalam manual berbahasa Inggris tetap bisa dilafalkan
Sebelum menyimpan, GetPDFUADiagnostics menjalankan pemeriksaan struktural pustaka atas dokumen di memori dan mengembalikan temuannya sebagai teks, dengan string kosong berarti tidak ada yang ditemukan. Kode-kodenya menyebut kesalahan penulisan klasik secara langsung: FIGURE-NO-ALT untuk gambar tanpa teks alternatif, HEADING-LEVEL-SKIP untuk H3 yang menyusul H1, ROLEMAP-UNMAPPED untuk tipe kustom yang tak pernah didaftarkan. Sambungkan ini ke dalam build (bangkitkan kumpulan dokumennya, gagalkan langkahnya bila diagnostiknya tidak kosong) dan regresi aksesibilitas berubah menjadi kegagalan bergaya waktu kompilasi alih-alih temuan audit berbulan-bulan kemudian. Vonis konformansi selengkapnya tetap milik preflight atas berkas tersimpan, yang dibahas di preflight PDF/A dan PDF/UA di Delphi, sebab sebagian normalisasi baru diterapkan saat serialisasi
Navigasi anotasi punya tombolnya sendiri. PDF/UA mengharapkan penyusuran field formulir dan tautan lewat papan ketik mengikuti urutan struktur, dan SetTabOrderMode menulis entri tab-order tingkat halaman yang dihormati viewer, dengan GetTabOrderMode tersedia untuk mengaudit berkas masuk. Ini jenis persyaratan yang tak seorang pun sadari sampai pengguna papan-ketik-saja melaporkan bugnya, dan membetulkannya hanya berongkos satu pemanggilan per dokumen
Pohon struktur tidak bertahan pada setiap penggabungan
Dokumen bertanda tetap bertanda hanya jika setiap langkah pemrosesan berikutnya melestarikan pohonnya, dan tepi tajam di dalam PDF Library for Delphi adalah keluarga merge-list. MergeFileListFast menukar pelestarian pohon struktur demi kecepatan. Itu pertukaran yang tepat untuk batch citra pindaian dan keliru untuk laporan bertanda, sebab keluarannya terbuka dengan baik, dirender identik, dan diam-diam kehilangan lapisan aksesibilitasnya. Gunakan MergeFileList default atau varian ketatnya kapan pun ada masukan yang bertanda, dan jadikan IsTaggedPDF bagian dari assertion pasca-perakitan supaya batch yang sudah rata tidak bisa dikirim tanpa ada yang menyadarinya. Pipeline perakitan untuk kumpulan dokumen besar membawa lebih banyak pertukaran semacam ini, yang ditelusuri di gabung, pecah, dan direct access untuk PDF besar
Lingkar verifikasinya ditutup di luar pustaka: buka keluarannya di Acrobat, periksa panel tag-nya, dan bacalah setidaknya satu dokumen per keluarga templat dengan pembaca layar sungguhan. Diagnostik menangkap kesalahan struktural; hanya telinga manusia yang menangkap urutan baca yang secara teknis sah namun praktisnya membingungkan. Build evaluasi dan referensi API penandaan selengkapnya ada di halaman produk losLab PDF Library for Delphi