TVt2sChunkKind = (vtckInlinePdf, vtckAttachmentPdf, vtckIccProfile);
TPdfVT2sChunk = record
Kind: TVt2sChunkKind;
Bytes: TBytes;
FileName: AnsiString;
end;
TPdfVT2sChunks = array of TPdfVT2sChunk;
TAnsiStrings = array of AnsiString;
TPdfVT2sValidationResult = record
Issues: TPdfVT2sValidationIssues;
function IsCompliant: Boolean;
end;
TPdfVTPrintingConditionSource = (vtpcsNone, vtpcsEmbeddedProfile, vtpcsMimeProfile);
TPdfVTPrintingConditionEvidence = record
PartIndex: Integer;
Conformance: TPdfVTConformance;
PdfXVersion: AnsiString;
OutputIntentObjectNumber: Integer;
OutputConditionIdentifier: AnsiString;
RegistryName: AnsiString;
Source: TPdfVTPrintingConditionSource;
ProfileFileName: AnsiString;
ProfileName: AnsiString;
ProfileColorSpace: AnsiString;
ProfileByteSize: Int64;
ProfileMd5: string;
ProfileSha256: string;
ProfileVersion: string;
ProfileDeviceClass: string;
ProfilePcs: string;
ProfileComponentCount: Integer;
Resolved: Boolean;
ProfileValid: Boolean;
DPart: TPdfVTDPartEvidence;
end;
TPdfVT2sValidationReport = record
Validation: TPdfVT2sValidationResult;
PrintingConditions: TPdfVTPrintingConditionEvidenceArray;
end;
procedure BuildPdfVT2sStream(const Chunks: TPdfVT2sChunks; Dest: TStream);
function ValidatePdfVT2sStream(Source: TStream): TPdfVT2sValidationResult;
function InspectPdfVT2sStream(Source: TStream): TPdfVT2sValidationReport;
FPdfPdfvtMime implements the PDF/VT-2s transport defined in ISO 16612-2 Annex, where a PDF/VT document plus its referenced reusable PDF content and ICC profile are packaged as a single MIME multipart stream
Unlike the TPdf.SaveAsPdfVT path that writes a standalone PDF/VT-1 file, this unit operates purely on byte streams and never loads pdfium.dll, so it can run in headless servers and batch pipelines
BuildPdfVT2sStream assembles the chunks in order and emits the StreamVersion header, part boundaries and per-part Content-Type / Content-Disposition headers; ValidatePdfVT2sStream parses an existing stream back and reports structural, printing-condition and ICC deviations as a typed issue set
InspectPdfVT2sStream returns the same compatibility result plus evidence for each PDF/VT part, including PDF/VT conformance, PDF/X base, OutputIntent identity, profile provenance, MD5 and SHA-256, raw ICC metadata and DPart page and recipient-record counts
Each PDF part is first classified with ValidatePdfVTCompliance; PDF/X-only reusable attachments remain eligible reference targets but are excluded from PDF/VT hierarchy and printing-condition comparisons
Profile packaging follows the file base: PDF/VT-1 with PDF/X-4 and PDF/VT-2 with PDF/X-5g use an embedded DestOutputProfile, whilst PDF/VT-2 with PDF/X-4p or PDF/X-5pg uses DestOutputProfileRef resolved to an earlier ICC MIME part
| Value | MIME role |
|---|---|
vtckInlinePdf | A PDF/VT document carried as an inline application/pdf part; at least one is required |
vtckAttachmentPdf | A reusable PDF content part referenced by the inline document, carried as an attachment with a filename |
vtckIccProfile | An ICC profile part (application/vnd.iccprofile) supplied as an attachment with a filename |
| Type | Purpose |
|---|---|
TPdfVT2sChunks | Dynamic array of ordered MIME chunks supplied to BuildPdfVT2sStream |
TAnsiStrings | Dynamic filename array used when validating external-file references in the inline PDF |
TPdfVT2sValidationIssues | Set of TPdfVT2sValidationIssue findings returned by validation |
TPdfVTPrintingConditionSource | Origin of the profile evidence: vtpcsNone when unresolved, vtpcsEmbeddedProfile for an embedded DestOutputProfile stream, vtpcsMimeProfile for a DestOutputProfileRef resolved from an ICC MIME part |
TPdfVTPrintingConditionEvidence | Per-part PDF/VT and PDF/X classification, OutputIntent, profile source, identity, digest, ICC header and DPart facts |
TPdfVT2sValidationReport | Detailed result returned by InspectPdfVT2sStream without changing the legacy result layout |
| Value | Reported when |
|---|---|
vtmviNotMultipart | The stream is not a multipart MIME container |
vtmviMissingStreamVersion | The required PDF/VT StreamVersion header is absent |
vtmviStreamVersionValue | The StreamVersion value is not the expected 1 |
vtmviStreamVersionAfterCt | StreamVersion appears after the Content-Type line instead of before it |
vtmviMissingBoundary | The Content-Type boundary parameter is missing |
vtmviNoInlinePdf | No inline PDF/VT part is present |
vtmviInlinePdfNotPdfVT | The inline part is not declared as PDF/VT |
vtmviIccProfileBadDisposition | An ICC profile part is not an attachment |
vtmviAttachmentMissingFilename | An attachment part lacks the required filename |
vtmviInlineHasFilename | The inline PDF part carries a filename, which is not permitted |
vtmviNodeNameListMismatch | Two PDF/VT files in the stream expose different NodeNameList values |
vtmviRecordLevelMismatch | DPart record levels are inconsistent across the container |
vtmviForwardReference | An attachment is referenced before it appears in the stream |
vtmviBoundaryInvalidChar | The boundary string contains characters not allowed by RFC 2046 |
vtmviDuplicateFilename | Two MIME attachments expose the same case-sensitive filename |
vtmviOutputIntentAmbiguous | A PDF part has zero or multiple authoritative GTS_PDFX OutputIntents |
vtmviOutputProfilePackagingMismatch | The OutputIntent has both profile forms, neither form, or a form incompatible with the PDF/X-4, PDF/X-4p, PDF/X-5g or PDF/X-5pg base |
vtmviOutputProfileReferenceInvalid | A DestOutputProfileRef omits required metadata, a URL file specification or uses a forbidden ColorantTable |
vtmviReferencedPartWrongType | The referenced filename resolves to a MIME part that is not an ICC profile |
vtmviIccProfileInvalid | The ICC header, declared size, signature, tag table or supported process colour space is invalid |
vtmviIccChecksumMismatch | The decoded 16-byte CheckSum differs from MD5 of the complete ICC file |
vtmviIccVersionMismatch | The declared four ICCVersion bytes differ from ICC header bytes 8 through 11 |
vtmviIccColorSpaceMismatch | ProfileCS differs from ICC header bytes 16 through 19 or is not GRAY, RGB or CMYK |
vtmviIccProfileNameMismatch | ProfileName matches no valid profileDescriptionTag locale value |
vtmviPrintingConditionUnresolved | The authoritative OutputIntent, identifier or external ICC dependency cannot be resolved |
vtmviPrintingConditionMismatch | PDF/VT parts disagree on OutputConditionIdentifier, RegistryName presence or value, or process colour space |
vtmviIccDeviceClassMismatch | An embedded or external destination profile is not an output-device prtr profile |
ValidatePdfVT2sStream on any stream produced by BuildPdfVT2sStream round-trip testing or on externally authored PDF/VT-2s containers before processingTPdfVT2sValidationResult.IsCompliant returns True only when the Issues set is empty
var Chunks: TPdfVT2sChunks;
begin
SetLength(Chunks, 2);
Chunks[0].Kind := vtckIccProfile;
Chunks[0].FileName := 'profile.icc';
Chunks[0].Bytes := IccBytes;
Chunks[1].Kind := vtckInlinePdf;
Chunks[1].Bytes := InlinePdfBytes;
BuildPdfVT2sStream(Chunks, MimeStream);
end;