PDFlibPas는 문서를 그리는 동시에 태깅할 수 있습니다. SetAutoTagMode를 켜면 일반적인 DrawText 호출은 문단이 되고, RegisterHeading 직후에 그려진 텍스트는 해당 레벨의 제목이 되며, 반복되는 머리말과 꼬리말은 리더가 건너뛰는 아티팩트가 되고, 이미지는 그림이 되며, DrawTableRows는 표와 그 행, 셀을 구조 트리로 옮깁니다
대안은 — 그리고 최근까지 유일한 선택지였던 방식은 — 모든 그리기 호출을 BeginTag와 EndTag로 직접 감싸는 것이었습니다. 이 방식도 동작하며, 구조가 특이한 문서에는 여전히 알맞은 도구입니다. 하지만 일반적인 보고서, 청구서, 명세서에서는 출력의 접근성이 무언가를 그리는 모든 코드 경로에서 아무도 한 쌍을 잊지 않았는지에 달리게 됩니다
모드 비트가 커버하는 범위
SetAutoTagMode는 비트 마스크를 받아 이전에 적용되던 모드를 반환합니다. AUTOTAG_TEXT(1)는 텍스트를 문단으로, 또는 차례가 된 경우 제목으로 태깅합니다. AUTOTAG_FURNITURE(2)는 반복 머리말, 꼬리말, 페이지 번호를 아티팩트로 표시합니다. AUTOTAG_FIGURE(4)는 그려진 이미지를 그림으로, 장식용으로 선언된 경우 아티팩트로 바꿉니다. AUTOTAG_TABLE(8)은 그려진 표를 구조 트리로 옮깁니다. AUTOTAG_DEFAULT는 15이며, 네 가지 모두를 켭니다
모드를 켜면 문서를 태깅된 것으로 표시하는데, 이 단계는 들리는 것보다 단순한 장식이 아닙니다. 카탈로그가 달리 표시하지 않는 한 리더는 문서를 태깅되지 않은 것으로 간주합니다(ISO 32000-1 §14.7.1). 따라서 완전한 구조 트리를 담고 있으면서 /MarkInfo 선언이 없는 파일은 보조 기술에 의해 구조가 전혀 없는 것으로 알려집니다. 트리는 있지만 아무것도 그것을 읽지 않습니다
var
Lib: TPDFlib;
begin
Lib := TPDFlib.Create;
try
Lib.SetOrigin(1);
Lib.SetAutoTagMode(AUTOTAG_DEFAULT); // text + furniture + figures + tables
Lib.AddStandardFont(4);
Lib.SetTextSize(18);
Lib.RegisterHeading(1, 'Annual service report');
Lib.DrawText(72, 96, 'Annual service report'); // becomes H1
Lib.SetTextSize(11);
Lib.DrawText(72, 130, 'Every unit installed before 2024 was inspected.');
Lib.SaveToFile('report.pdf');
finally
Lib.Free;
end;
end;
제목은 어떤 텍스트에 속하는지 어떻게 알까
RegisterHeading은 다음에 그려질 텍스트의 레벨을 정하고, 텍스트를 기다립니다. 그 사이에 이미지가 그려지면 이미지는 그림이 되고 제목은 뒤따라올 텍스트를 위해 대기 상태로 남습니다. 이 동작은 의도적입니다. 이미지가 제목 레벨을 가져가는 대안은 제목 아래의 장식용 선이 제목 자체로 알려지는 문서를 만들어냈기 때문입니다
같은 한 항목에 한 번만 소비되는 규칙이 그림에도 적용됩니다. RegisterFigure는 다음 이미지가 담을 설명을 제공하고, RegisterDecoration은 다음 이미지를 의미가 없는 선, 테두리, 배경으로 선언합니다. 둘 다 한 이미지에 의해 소비되므로 나중의 이미지는 결코 이전 이미지를 위한 설명을 물려받지 않습니다. 수동으로 태깅한 코드에서 대체 텍스트가 잘못된 그림에 붙는 것은 바로 이런 방식 때문입니다
이 설명은 접근성 문서에서 그 어떤 단일 문자열보다 중요합니다. 시각장애 독자는 그림 대신 설명을 받으며, 그것이 돌아오는 전부입니다. Chart는 설명이 아니며, Quarterly revenue by region, with the eastern region highest in Q3가 설명입니다
Lib.RegisterFigure('Exploded view of the gearbox assembly');
Lib.AddImageFromFile('gearbox.png', 0); // becomes a tagged Figure
Lib.RegisterDecoration; // meaningless rule
Lib.AddImageFromFile('divider.png', 0); // drawn inside a layout artifact
표, 머리말 행, 그리고 반복 결정이 자리하는 곳
표 비트가 켜진 상태에서 DrawTableRows는 표와 그 행, 셀을 구조 트리로 옮겨, 리더가 표 전체를 무관한 텍스트의 연속으로 읽는 대신 어떤 값이 어느 열에 있는지 말할 수 있게 합니다. SetTableHeaderRowCount는 선행 몇 행이 머리말인지 정합니다. 그 행들은 열 스코프를 담은 머리말 셀로 기록되며, 이것이 리더가 사용자가 위치한 값의 제목을 알려줄 수 있는 근거가 됩니다
이 방식으로 지정된 머리말 행은 제자리에 머무릅니다. 각 페이지 상단에 반복하는 것은 레이아웃 결정이며, 그대로 둡니다. DrawTaggedTableRows는 정확히 그 목적을 위해 RepeatHeaderRows 매개변수를 받습니다. 둘을 분리해 두면 페이지마다 구조 트리가 머리말의 복사본을 추가로 얻는 일을 막을 수 있으며, 자동 반복이라면 정확히 그 결과가 나옵니다
var
TableID: Integer;
begin
TableID := Lib.CreateTable(40, 3);
Lib.SetTableHeaderRowCount(TableID, 1); // row 1 is the header band
Lib.SetTableCellContent(TableID, 1, 1, 'Part');
Lib.SetTableCellContent(TableID, 1, 2, 'Torque');
Lib.SetTableCellContent(TableID, 1, 3, 'Unit');
// ... fill the data rows ...
// Draw rows 1..40 into a 600pt band, repeating one header row per page
Lib.DrawTaggedTableRows(TableID, 72, 150, 600, 1, 40, 1);
end;
자동 태깅과 수동 태깅의 조합
자동 태깅은 손으로 열린 태그 안에서는 한 발 물러섭니다. 문서의 일부는 여러분의 코드로 기술하고 나머지는 라이브러리에 맡길 수 있으며, 둘이 서로 중첩되지 않습니다. 이것이 대부분의 실제 문서가 원하는 배치입니다. 표지와 서명 블록은 오직 여러분만 이해하는 구조를 갖지만, 그 사이의 200페이지 분량 본문 텍스트는 그렇지 않습니다
두 안전 규칙이 출력을 깨끗하게 유지합니다. 아티팩트 안에서는 아무것도 태깅되지 않는데, 아티팩트로 표시된 콘텐츠는 구조 요소를 전혀 가져서는 안 되기 때문입니다. 그리고 빈 텍스트는 어떤 요소도 열지 않으므로, 빈 문자열을 가진 엉뚱한 DrawText 호출이 리더가 빈 것으로 알려줄 구조 요소를 만들어낼 수 없습니다. 둘 다 수동으로 태깅된 문서가 조용히 축적하는 결함이며, 검증기가 몇 달이 지나서야 한꺼번에 보고하는 종류입니다
자동 태깅이 여전히 대신 결정하지 않는 것
그리기 순서를 넘어서는 읽기 순서, 문단·제목·그림·표가 아닌 의미론적 역할, 그리고 언어 선언입니다. 자동 태깅은 콘텐츠가 그려지는 순서대로 구조를 할당합니다. 즉 레이아웃 코드가 본문보다 사이드바를 먼저 그린다면 트리가 기록하는 순서도 그렇게 됩니다. 시각적 순서와 읽기 순서가 실제로 다른 문서에서는 수동 태깅 API가 여전히 알맞은 도구이며, 태깅된 PDF와 접근성 구조 산책문이 역할, 스코프, 머리말 바인딩을 자세히 다룹니다
문서가 완성되면 추정 대신 검증하십시오. PDF/A와 PDF/UA 프리플라이트에 관한 글이 생성한 구조에 대한 판정을 받는 방법을 보여주며, 데이터셋 기반 보고서 내보내기 산책문은 이 호출들이 데이터로부터 레이아웃을 생성하는 보고서 엔진에서 어디에 들어맞는지 다룹니다
PDFlibPas는 외부 PDF 런타임 없이 Delphi, C++Builder, Lazarus를 위한 네이티브 Pascal PDF 라이브러리이므로 접근성 출력은 문서를 그리는 동일한 코드가 만듭니다. 전체 API와 플랫폼 목록은 PDFlibPas 제품 페이지를 보십시오