PDF/E-1 پروفایل آرشیوی اسناد مهندسی است، و PDFlibPas آن را بهصورت یک author mode پیاده میکند که با SetPDFEMode روشنش میکنید، بهعلاوه یک preflight محدوددامه که content streamها را عملگر به عملگر میخواند. این پروفایل PDF/A با برچسب متفاوت نیست: فضای نام شناسایی خودش را دارد، الزام metadata چرخه عمر خودش را، و یک قاعده که راستیآزمایی محتوا را سختگیرانهتر از هر پروفایل آرشیوی میکند که تا حالا دیدهاید
محصولات تحویلی مهندسی دلیل وجود این پروفایلاند. یک مجموعه نقشه که باید بیست سال دیگر هم خوانا باشد و بهاثباتپذیری تغییرنکرده باشد، با تاریخچه بازنگریای که دوام میآورد، و با رنگی که در plotter ساختمان دیگر هم همان معنا را دارد. این الزامات مشخصهای تولید میکنند که مطالباتش بیشتر بیرون از محتوای صفحه مینشیند، در metadata و مدیریت رنگ، که دقیقاً همان جایی است که یک PDF writer عمومی اشتباهش میکند
شناسایی خودش، نه یک گونه از PDF/A
اولین چیزی که باید درست بگیرید این است که شناسایی PDF/E-1 را نمیشود با تطبیق دادن الگوی PDF/A یا PDF/X تولید کرد. از یک فضای نام XMP مجزا استفاده میکند، http://www.aim.org/pdfe/ns/id/، و مقدار نسخه باید در دو جا ظاهر شود: بهعنوان یک مدخل document information و بهعنوان property XMP با پیشوند فضای نام. خروجی دادن فقط property XMP، یا فقط مدخل information، فایلی تولید میکند که نیت را حمل میکند و در راستیآزمایی میافتد
output intent شکل به همان اندازه خاصی دارد. PDF/E-1 یک پروفایل ICC جاسازیشده با شناسه زیرگروه ISO_PDFE1 میخواهد، و پروفایل باید تعداد مؤلفهای موافق خانواده رنگی دستگاهی که سند واقعاً استفاده میکند داشته باشد. همان بند آخر است که پیادهسازیها بیسروصدا در آن گم میشوند، چون یعنی intent را نمیشود از قبل انتخاب کرد و بعد فراموش
چرا رنگ دستگاه به یک sweep کل سند نیاز دارد؟
چون فضاهای رنگی در دیکشنریهای resource پنهان میشوند که اسکن سطح صفحه هرگز به آنها نمیرسد. PDF/E-1 با DeviceRGB و DeviceCMYK بهعنوان دو خانواده بهطور متقابل انحصاری برای یک سند رفتار میکند، پس راستیآزمایی پروفایل یعنی دانستن هر فضای رنگ دستگاهی که هر چیزی در فایل استفاده میکند. یک form XObject resource خودش را دارد. pattern هم همینطور، و image هم. یک tiling pattern درون یک form XObject درون یک صفحه سه سطح عمق دارد، و validatorای که فقط resourceهای سطح بالای صفحه را چک کند سندی را که از هر دو خانواده استفاده میکند پاس میکند
پس sweep فضاها رنگی را حین گشتن صفحات، فرمها، تصاویر و patternها بهعنوان یک پیمایش واحد ثبت میکند، و فقط بعد از آن تصمیم میگیرد که آیا سند منسجم است و آیا output intent جور درمیآید. همان استدلال بهطور کلی معماری preflight را پیش میبرد: پیمایش جزئی پاس کاذب تولید میکند، و یک پاس کاذب روی چک انطباق بدتر از هیچ چکی است، چون بهعنوان مدرک ثبت میشود
var
Lib: TPDFlib;
Diag: WideString;
begin
Lib := TPDFlib.Create(nil);
try
Lib.LoadFromFile('assembly-drawings.pdf');
if Lib.SetPDFEMode(1) = 0 then
raise Exception.Create('PDF/E author mode was refused');
// author mode metadata چرخه عمر را در هر ذخیره همگام نگه میدارد.
// پیش از ذخیره بپرسید که آیا سند از گیت خودش عبور میکند
if not Lib.PDFEReadyForSave then
begin
Diag := Lib.GetPDFEDiagnostics;
Writeln('PDF/E blockers: ', Diag);
Exit;
end;
Lib.SaveToFile('assembly-drawings-pdfe.pdf');
finally
Lib.Free;
end;
end;
metadata چرخه عمر یک الزام بهازای هر ذخیره است
PDF/E-1 بیشتر از یک شناسه سند میخواهد. مجموعه حداقلی شامل شناسه سند مدیریت رسانه، یک شناسه نسخه، یک rendition class، زمان ایجاد، زمان اصلاح، زمان metadata و یک عنوان است. این یک واژگان پیگیری بازنگری است، و وجودش برای این است که از یک محصول تحویلی مهندسی انتظار میرود بازانتشار شود نه اینکه یک بار نوشته شود
پیامدش برای پیادهسازی این است که این فیلدها را نمیشود در لحظه ساخت سند مقدار داد. اگر زمان اصلاح وقتی حالت را فعال میکنید نوشته شود و سند بعداً ویرایش شود، snapshot XMP و وضعیت واقعی سند از هم فاصله میگیرند، و validatorای که آنها را مقایسه میکند یک ناسازگاری گزارش میکند که هیچکس قصدش را نکرده بود. به همین دلیل author mode این فیلدها را بلافاصله پیش از هر ذخیره همگام میکند، تا metadata بایتهایی را توصیف کند که در آستانه نوشته شدناند نه بایتهایی که وقتی حالت روشن شد وجود داشتند
این یک اصل کلی برای metadata انطباق است و ارزش دارد جدا از PDF/E گفته شود: metadata مشتقشده مال مسیر ذخیره است نه مسیر ویرایش. هر فیلدی که از وضعیت سند محاسبه میشود باید در لحظه انجماد وضعیت از نو محاسبه شود، وگرنه یک cache بدون invalidation است
قاعدهای که راستیآزمایی محتوا را سختگیرانه میکند
PDF/E-1 اجازه نمیدهد عملگرهای بخش سازگاری محتوای ناشناخته را قورت بدهند. در PDF معمولی، BX و EX ناحیهای را قاب میکنند که consumer در آن باید عملگرهایی را که نمیشناسد نادیده بگیرد، که همان دریچه گریز است که به producer اجازه میدهد سازههای جدیدتر را بدون شکستن readerهای قدیمیتر خروجی بدهد. زیر PDF/E-1 آن گریز بسته است، پس هر عملگری که preflight نشناسد بیقید و شرط گزارش میشود، چه داخل یک بخش سازگاری باشد چه نباشد
اثرش روی validator چشمگیر است. نمیتواند ناحیههایی را که نمیفهمد رد کند، یعنی parser عملوندها باید واقعاً هر عملگر در هر content stream را parse کند. اینجاست که مرزها معنا پیدا میکنند. پیمایش روی ۱۲۸ سطح تو در تو، یک میلیون آبجکت و ۶۴ مگابایت محتوا سقف دارد، و این محدودیتها تنظیم کارایی نیستند. یک فایل خصمانه یا صرفاً خراب میتواند گراف آبجکتی با cycle یا عمق تو در تویی ارائه دهد که یک validator بازگشتی را به stack overflow بکشاند، و همین محدودیتها هستند که مانع میشوند یک گذر راستیآزمایی به بردار denial-of-service تبدیل شود. همان موضع دفاعی در parse امن PDFهای نامطمئن توصیف شده
// راستیآزمایی مستقل یک فایل که خودتان تولیدش نکردهاید، بدون لودکردن
// آن در یک instance سند
var
Issues: TStringList;
Stream: TFileStream;
I: Integer;
begin
Issues := TStringList.Create;
Stream := TFileStream.Create('incoming.pdf', fmOpenRead or fmShareDenyWrite);
try
if CheckCompliancePDFE(Stream, '', 0, Issues) = 0 then
for I := 0 to Issues.Count - 1 do
Writeln('PDF/E: ', Issues[I]);
finally
Stream.Free;
Issues.Free;
end;
end;
گیت ذخیره چه چیزهایی را تعمیر میکند و چه چیزهایی را رد
گیت کارش را به دو مرحله تقسیم میکند، و همین تقسیم بهخودیخود یک ایده طراحی قابل استفاده است. اول چیزهایی را نرمال میکند که بهطور امن قابل تعمیرند: پرچمهای چاپ annotation، پرچمهای no-zoom و no-rotate روی annotationهای متنی، و پرچم تولید ظاهر روی دیکشنری فرم. اینها تنظیماتی هستند با یک مقدار درست زیر پروفایل و بدون هیچ محتوای اطلاعاتی، پس تعمیر بیسروصدایشان درست است و ردکردن بهخاطرشان pedantry میشود
بعد محدودیتهایی را چک میکند که بدون تغییر معنای سند قابل تعمیر نیستند: نسخه، شناسایی، رمزگذاری، output intent، انسجام رنگ دستگاهی و حضور محتوای فرم دینامیک. سندی که هرکدام از اینها را رد کند رد میشود، چون از پای اختراعکردن یک output intent یا انتخاب یک خانواده رنگی به نمایندگی از نویسنده، فایلی تولید میکند که راستیآزمایی را پاس میکند و محتوا را غلط معرفی میکند
خواندن diagnostics از طریق GetPDFEDiagnostics پیش از ذخیره آن ردشدن را به یک لیست قابل اقدام تبدیل میکند نه یک عملیات شکستخورده. در یک خط لوله دستهای، روی هر سند صدا بزنیدش، بلاکرها را بهازای هر فایل لاگ کنید، و شکستها را به صفی بفرستید که یک انسان نگاهشان میکند. این بهمراتب مفیدتر از ذخیرهای است که raise میکند، چون بلاکرها معمولاً خوشهایاند: چهل سندی که برای یک output intent غایب یکسان fail میشوند یک fix هستند، نه چهل
انتخاب میان پروفایلهای آرشیوی
وقتی محصول تحویلی، مستندات مهندسی با چرخه عمر بازنگری است، و مشخصاً وقتی انسجام رنگ دستگاهی مهم است چون خروجی به plotterها و چاپگرهای فرمت بزرگ میرود، PDF/E-1 تارگت درست است. وقتی هدف خوانایی بلندمدت اسناد بهطور کلی است، PDF/A تارگت درست است، و همان پروفایلی است که پشتیبانی validator از آن گستردهترین است. این دو جایگزین هم نیستند، و یک سند میتواند یکی را پاس کند و در دیگری بیفتد
اگر در حال انتخاباید، از این شروع کنید که سر خط چه کسی فایل را راستیآزمایی میکند. ابزار راستیآزمایی PDF/A همهجا هست، و preflight متناظرش در PDFlibPas در preflight PDF/A و PDF/UA توصیف شده. راستیآزمایی PDF/E تخصصیتر است و معمولاً یک الزام قراردادی است نه پیشفرض. وقتی یک آرشیو موجود باید به پروفایلی ارتقا پیدا کند که برایش نوشته نشده بود، مسیر تعمیر metadata در تبدیل به PDF/A با تعمیر metadata الگوی قابل پیروی است، و همین شکل اینجا هم صادق است: شناسایی کن، چیز امن را تعمیر کن، بقیه را با یک لیست رد کن
author mode، preflight محتوای محدوددامه و چک انطباق مستقل همگی همراه PDFlibPas Delphi PDF library عرضه میشوند، پس میشود سندی زیر پروفایل تولید کرد و بعداً بهطور مستقل از یک مسیر کد جداگانه راستیآزماییاش کرد، که برای یک ادعای انطباق تنها چیدمانی است که ارزش اعتماد دارد