PDFium Component는 ISO 19005-1 부록 C의 구현 한계, 즉 127바이트 이름 토큰, 8191 배열 요소, 4095 딕셔너리 항목, 28 수준의 컨테이너 중첩을 검증하며, /Encoding 항목을 담은 심볼릭 TrueType 폰트를 보고합니다. 두 검사 모두 바이트 스캔 경로에서 실행되므로, Delphi 또는 Lazarus 애플리케이션은 PDFium DLL을 전혀 로드하지 않고 판정을 받습니다
이것이 사람을 가장 당혹하게 만드는 실패인데, 문서가 멀쩡해 보이기 때문입니다. 렌더링도 되고 인쇄도 되며, 모든 폰트가 임베드되어 있고 출력 인텐트도 있습니다. 그런데 검증기가 4096 항목을 가진 딕셔너리 때문에 거부하며, 보이는 문서 어디에서도 그 이유를 설명하지 않습니다
부록 C 한계가 실제로 보호하는 것은 무엇인가
여러분의 생성기보다 앞선 구현과의 상호 운용성입니다. 부록 C는 PDF 레퍼런스 구현 한계를 모든 PDF/A 파트로 가져오며, 그 숫자는 임의가 아닙니다. 규칙을 준수하는 리더가 역사적으로 처리해야 했던 것을 기술합니다. 그 한계를 넘는 파일은 최신 뷰어에서는 완벽하게 열릴 수 있지만, 기록 시스템이 15년 전에 표준화한 보존용 리더에서는 실패할 수 있으며, 이것이 정확히 PDF/A가 막기 위해 존재하는 시나리오입니다
네 한계는 포함적입니다. 정확히 127바이트인 이름 토큰은 검증을 통과하며, 128은 그렇지 않습니다. 정확히 8191 요소인 배열은 검증을 통과하며, 8192는 그렇지 않습니다. PDFium Component는 그 이유로 모든 경계의 양쪽을 테스트 스위트에서 고정하는데, 한계 검사에서의 오프바이원이 규칙을 준수하는 파일을 거부하면서도 믿음을 받는 최악의 종류의 검증기를 만들어내기 때문입니다
uses FPdfPdfa;
var
Src: TFileStream;
Res: TPdfAValidationResult;
begin
Src := TFileStream.Create('archive.pdf', fmOpenRead or fmShareDenyWrite);
try
Res := ValidatePdfACompliance(Src);
if pvaiArrayOverLimit in Res.Issues then
Memo1.Lines.Add('An array carries more than 8191 elements');
if pvaiDictOverLimit in Res.Issues then
Memo1.Lines.Add('A dictionary carries more than 4095 entries');
if pvaiNestingOverLimit in Res.Issues then
Memo1.Lines.Add('Containers nest deeper than 28 levels');
if pvaiNameOverLimit in Res.Issues then
Memo1.Lines.Add('A name token is longer than 127 bytes');
finally
Src.Free;
end;
end;
실제로 이 한계에 부딪히는 생성기는 무엇인가
구조를 프로그램적으로 구축하는 것들이며, 이는 대부분의 업무용 출력입니다. 수천 개의 필드를 가진 양식은 8191을 넘어 자라는 /Annots 배열이나 AcroForm /Fields 배열을 만듭니다. 생성된 이미지나 폰트 인스턴스마다 하나의 항목을 축적하는 페이지 리소스 딕셔너리가 4095를 넘습니다. 깊이 생성된 구조 트리, 즉 중첩된 데이터 모델에 대한 재귀로 구축된 태깅된 문서는 아무도 중첩 깊이를 보지 않기 때문에 28 수준을 아무도 모르게 지나칩니다
긴 이름은 다른 습관에서 옵니다. 데이터를 이름 토큰으로 인코딩하는 것입니다. 고객 식별자로 만들어진 색료 이름, 전체 파일 경로를 따서 이름 지어진 옵셔널 콘텐츠 그룹, 여섯 수준의 계층을 이어 붙인 완전한 자격 이름을 가진 양식 필드가 그것입니다. 이름은 생성하기 싸고 길게 만들기 쉬우며, UTF-8로 인코딩된 레이블이 관여하면 127바이트는 예상보다 빠르게 사라집니다
수정은 모든 사례에서 구조적입니다. 배열을 나누고, 딕셔너리를 나누고, 중첩을 평면화하고, 이름을 짧게 하는 것입니다. 각 문제에 대한 프리플라이트 권고는 파일이 무효라고 말하는 대신 구체적인 한계를 이름 지습니다. 마커 주입은 여기서 도울 수 없습니다. 이것들은 메타데이터 주장이 아니라 객체 그래프의 모양입니다
심볼릭 TrueType 폰트가 Encoding을 담지 말아야 하는 이유
ISO 19005-1 §6.3.7이 심볼릭 TrueType 폰트에 대해 폰트의 빌트인 cmap만 인정하며, /Encoding 항목은 그것과 모순되기 때문입니다. 심볼릭 폰트는 자체 방식으로 코드를 글리프에 매핑하며, 그것이 심볼릭이 의미하는 바입니다. 인코딩 테이블을 추가하면 바이트 0x41이 어느 글리프를 선택하는가라는 질문에 두 개의 답이 생기며, 어느 쪽이 이기는지 말하는 규칙이 파일에 없습니다. 다른 리더가 다르게 해석하여, 어떤 뷰어에서는 텍스트로 렌더링되는 문서가 다른 곳에서는 딩뱃으로 렌더링됩니다
PDFium Component는 서술자가 폰트 딕셔너리에 인라인으로 기록되었든 간접으로 참조되었든 /FontDescriptor에서 심볼릭 플래그를 읽습니다. 비심볼릭 TrueType 폰트는 필수 /WinAnsiEncoding 또는 /MacRomanEncoding을 플래그 없이 유지하는데, 비심볼릭 폰트에 대해 인코딩은 정확히 표준이 요구하는 것이기 때문입니다. 검사는 인코딩의 존재가 아니라 모순에서 발화합니다
if pvaiSymbolicTrueTypeEncoding in Res.Issues then
Memo1.Lines.Add(
'A symbolic TrueType font carries /Encoding; PDF/A admits only its ' +
'built-in cmap (ISO 19005-1 6.3.7)');
이 결함의 실질적 원천은 모든 TrueType 폰트를 같은 방식으로 취급하는 생성기가 한 서브세팅입니다. Symbol, Wingdings, 바코드 폰트, 아이콘 폰트가 보통의 운반체이며, 이것은 비즈니스 문서가 체크박스, 로고, 바코드에 사용하는 바로 그 폰트이자 문서가 폰트 때문에 검증에 실패할 때 아무도 다시 살피지 않는 바로 그것들입니다
문제들이 프리플라이트 보고서에 도착하는 방식
네 컨테이너 한계는 구조로 분류되며, 심볼릭 TrueType 인코딩 문제는 콘텐츠로 분류됩니다. 이 분할은 보고서가 두 사람에게 갈 때 중요합니다. 구조 발견은 보통 생성기를 작성한 사람에게 속하고, 콘텐츠 발견은 보통 자산을 공급한 사람에게 속합니다
각 문제는 구체적인 용어로 치료법을 이름 짓는 권고를 담습니다. 이름 토큰을 127바이트 이하로 줄이세요, 어느 배열도 8191 요소를 넘지 않게 나누세요, 심볼릭 TrueType 폰트에서 /Encoding을 제거하세요. PDF/A를 준수하지 않는다고 말하는 보고서는 조사를 시작합니다. 어느 한계가 얼마나 초과되었는지 말하는 보고서는 조사를 끝냅니다
DLL 없이 검증하기, 그리고 여기서 그것이 중요한 이유
위의 모든 검사는 파일 바이트에 대해 실행되므로, PDFium 바이너리가 배포되지 않은 서비스에서, 빌드 단계에서, 또는 네이티브 DLL 로드가 정책 문제인 기계에서 작동합니다. 이것은 PDFium Component의 의도적 설계 노선입니다. 구조에서 답할 수 있는 검사는 구조에서 답하며, DLL은 진정으로 렌더링 엔진이 필요한 것을 위해 남겨둡니다
주변 워크플로, 즉 폴더에 대해 검증을 실행하고 보고서를 생산하며 발견을 어떻게 할지 결정하는 것은 Delphi에서 PDF/A 프리플라이트 검증 산책문과 배치 프리플라이트 보고 CLI를 보십시오. 이 모든 검사 위에 놓인 보존 프로파일 선택은 PDF/A 보존 규정 준수에 관한 글이 발견을 고치기 시작하기 전에 어느 파트와 레벨을 목표로 할지 다룹니다
PDFium Component는 Delphi, C++Builder, Lazarus를 위해 PDFium 엔진을 고수준 VCL API와 DLL 유무에 상관없이 실행되는 일련의 규정 준수 검증기로 감쌉니다. 지원 표준과 플랫폼은 PDFium Component 제품 페이지를 보십시오