مقاله فنی

اعتبارسنجی PDF/X در دلفی با استفاده از کامپوننت PDFium

کامپوننت PDFium برای دلفی، اسناد PDF/X آماده چاپ را از طریق متد TPdf.ValidatePdfX اعتبارسنجی می‌کند، که بررسی‌های استاندارد ISO 15930 را در دو لایه پیاده‌سازی می‌نماید: هشت بررسی محتوای سطح بایت (شامل ممنوعیت فشرده‌سازی LZW، جاوااسکریپت، فیلدهای فرم، ارجاعات OPI، مفقود بودن TrimBox، تنظیم نشدن کلید Trapped و غیره) به همراه یک گذر مدل شیء پی‌دی‌اف‌یوم که از متد FPDFFont_GetIsEmbedded برای بررسی تعبیه‌سازی فونت در تک‌تک اشیاء متنی در تمام صفحات استفاده می‌کند. نتیجه یک رکورد TPdfXValidationResult است که سطح انطباق تشخیص داده شده را مشخص کرده و هر تخلف را به صورت یک نوع شمارشی (enum) لیست می‌کند، تا برنامه دلفی شما بتواند قبل از شروع چاپ، دلیل دقیق رد شدن فایل در چاپخانه را به مشتری اعلام کند

اگر تا به حال کاری را برای چاپگر تجاری ارسال کرده و آن را با یک خط پیام رد کار مواجه شده باشید — مانند «نبود TrimBox»، «فونت‌ها تعبیه نشده‌اند»، «Trapped تنظیم نشده است» — هزینه دیر متوجه شدن را به خوبی می‌دانید. استاندارد PDF/X معادل پیش‌چاپ (prepress) استاندارد PDF/A است: در حالی که نسخه آرشیوی PDF/A تضمین می‌کند که سند در دهه‌های آینده دقیقاً به همان شکل رندر می‌شود، استاندارد PDF/X تضمین می‌نماید که سند فردا صبح در پردازنده تصویر چاپخانه (RIP) شخص دیگری، با همان تفکیک رنگ و برش دقیق پردازش می‌شود. این دو استاندارد از سازوکارهای مشترکی استفاده می‌کنند (مانند شناسایی XMP، مشخصه‌های OutputIntents، و پروفایل‌های رنگی تعبیه‌شده ICC) اما به سؤالات متفاوتی پاسخ می‌دهند، به همین دلیل است که این کامپوننت برای هر کدام ابزارهای اعتبارسنجی جداگانه‌ای ارائه می‌دهد — بخش PDF/A در اعتبارسنجی پیش‌چاپ PDF/A با کامپوننت PDFium پوشش داده شده است

استاندارد ISO 15930 واقعاً چه چیزهایی را برای یک PDF آماده چاپ الزامی می‌کند؟

استاندارد ISO 15930 برای امکان‌پذیر ساختن تبادل کور (blind exchange) وجود دارد: طراح یک فایل را به چاپخانه‌ای تحویل می‌دهد که هرگز با آنها صحبت نکرده است، و چاپخانه می‌تواند بدون تماس تلفنی، بدون ارسال ایمیل برای فونت‌های مفقود، و بدون تصویر لینک‌شده‌ای که در لپ‌تاپ طراح جا مانده باشد، خروجی درستی تولید کند. تک‌تک قوانین موجود در این استاندارد در خدمت این هدف هستند. فونت‌ها باید تعبیه شده باشند زیرا نمی‌توان فرض کرد که RIP دریافت‌کننده مالک آنهاست. ارجاعات خارجی ممنوع هستند زیرا فایل باید خودکفا و کامل باشد. قابلیت‌های تعاملی ممنوع هستند زیرا جوهر روی کاغذ هندلر onclick ندارد

کامپوننت PDFium سه خانواده انطباق را شناسایی کرده و آنها را از طریق نوع شمارشی TPdfXConformance در نتیجه اعتبارسنجی گزارش می‌دهد: pxc1a برای استاندارد PDF/X-1a:2001 (ISO 15930-1، یعنی پایه سخت‌گیرانه رنگ‌های CMYK و spot روی نسخه‌های PDF 1.3/1.4)، مقدار pxc3 برای استاندارد PDF/X-3:2002 (ISO 15930-3، که سیستم‌های رنگی RGB، Lab و ICC-managed را می‌پذیرد)، و pxc4 برای استاندارد PDF/X-4:2010 (ISO 15930-7، که سرانجام شفافیت زنده و لایه‌ها را روی پایه PDF 1.6 مجاز می‌داند). فایلی که اصلاً حاوی اطلاعات شناسایی PDF/X نباشد به عنوان pxcNone گزارش می‌شود، که این خود یک پاسخ کاربردی است: یعنی سند هرگز ادعای آماده چاپ بودن نداشته است، و هر مورد دیگری که اعتبارسنج گزارش می‌دهد، توضیح می‌دهد که برای رسیدن به آن شرایط چه کارهایی لازم است

وقتی مانند یک چاپخانه فکر کنید، این ممنوعیت‌ها کاملاً منطقی به نظر می‌رسند. فیلتر /LZWDecode در تمام نسخه‌های PDF/X ممنوع شده است تا برنامه‌های سازگار هرگز به فیلتری با تاریخچه سازگاری و لایسنس خاص وابسته نباشند؛ فیلتر Flate همان کار را بدون دردسرهای جانبی انجام می‌دهد. جاوااسکریپت، فیلدهای AcroForm، و دیکشنری‌های عملیات اضافه /AA ممنوع هستند زیرا یک فایل چاپی باید یک توصیف ثابت از علائم روی کاغذ باشد — هر چیزی که بتواند ظاهر سند را در زمان باز کردن تغییر دهد، تضمین مطابقت خروجی چاپی با نسخه تایید شده را از بین می‌برد. فیلدهای OPI (Open Prepress Interface) ممنوع هستند زیرا به طور پیش‌فرض، ارجاعاتی به تصاویر با کیفیت بالا هستند که در جای دیگری ذخیره شده‌اند، و «جای دیگر» دقیقاً همان چیزی است که تبادل کور آن را ممنوع می‌کند

چرا چاپخانه‌ها فایل‌های PDF بدون TrimBox را رد می‌کنند؟

TrimBox همان صفحه نهایی است — یعنی مستطیلی که پس از برش کاغذ باقی می‌ماند. در مقابل، MediaBox که هر صفحه PDF دارد، صرفاً ورق کاغذ است: شامل محدوده اضافه رنگ (bleed)، نشانه‌های برش، اهداف ثبت تراز رنگ و نوارهای رنگی. نرم‌افزار چیدمان صفحات، موقعیت صفحات را روی ورق چاپ بر اساس TrimBox آنها تنظیم می‌کند؛ بدون وجود آن، اپراتور باید حدس بزند که کارت ویزیت شما واقعاً کجا به پایان می‌رسد، و یک حدس اشتباه باعث برش خوردن بخش‌های مهم کار یا باقی ماندن یک نوار سفید در لبه‌ها می‌شود. به همین دلیل استاندارد ISO 15930 وجود TrimBox (یا ArtBox) را در تمام صفحات الزامی می‌کند، و متد ValidatePdfX در صورت عدم وجود کلید /TrimBox در هر صفحه‌ای از سند، خطای pvxiMissingTrimBox را ایجاد می‌نماید

کلید /Trapped به یک سؤال فنی دیگر پاسخ می‌دهد. Trapping تکنیک پیش‌چاپی برای ایجاد همپوشانی جزئی بین رنگ‌های مجاور است تا انحراف‌های جزئی دستگاه چاپ باعث ایجاد شکاف‌های سفید بین آنها نشود. چاپگر باید بداند که آیا این کار قبلاً انجام شده است یا خیر: اجرای مجدد trapping روی فایلی که قبلاً این کار روی آن انجام شده همپوشانی‌ها را دوبرابر می‌کند، و نادیده گرفتن آن در فایلی که فاقد آن است، ریسک ایجاد شکاف‌های قابل مشاهده را دارد. بنابراین استاندارد PDF/X نیاز دارد که دیکشنری Info به طور صریح مقادیر /Trapped /True یا /Trapped /False را اعلام کند — نبود این کلید یا مقدار /Unknown یک انسان را مجبور به بررسی فایل می‌کند، که این دقیقاً همان نوع ارتباطی است که تبادل کور برای حذف آن ایجاد شده است. کامپوننت این موضوع را با خطای pvxiTrappedNotSet مشخص می‌کند

اجرای اعتبارسنجی دو لایه با استفاده از TPdf.ValidatePdfX

متد TPdf.ValidatePdfX پارامتری دریافت نکرده و یک رکورد TPdfXValidationResult با سه عضو برمی‌گرداند: Conformance (نوع انطباق PDF/X شناسایی شده)، Issues (مجموعه پاسکالی از مقادیر TPdfXValidationIssue)، و متد کمکی IsCompliant. در پس‌زمینه، این متد سند بارگذاری‌شده را در یک جریانِ حافظه (memory stream) سریال‌سازی می‌کند، بازرس سطح بایت را روی آن اجرا می‌نماید، و سپس مدل شیء پی‌دی‌اف‌یوم را برای بررسی تعبیه‌سازی فونت پیمایش می‌کند. یک بررسی ساده پیش‌چاپ به این صورت است:

uses PDFium, FPdfPdfx;

procedure CheckPrintReadiness(const FileName: string);
var
  Pdf: TPdf;
  Res: TPdfXValidationResult;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := FileName;
    Pdf.Active := True;

    Res := Pdf.ValidatePdfX;
    Writeln('Detected conformance: ',
      Ord(Res.Conformance)); // pxc1a, pxc3, pxc4, pxcNone...

    if Res.IsCompliant then
      Writeln('PDF/X checks passed')
    else
    begin
      if pvxiMissingTrimBox in Res.Issues then
        Writeln('REJECT: no /TrimBox on the pages');
      if pvxiTrappedNotSet in Res.Issues then
        Writeln('REJECT: /Trapped missing or /Unknown');
      if pvxiPdfiumFontNotEmbedded in Res.Issues then
        Writeln('REJECT: a page uses a non-embedded font');
      if pvxiLzwForbidden in Res.Issues then
        Writeln('REJECT: LZWDecode filter present');
    end;
  finally
    Pdf.Free;
  end;
end;

از آنجا که ویژگی Issues یک مجموعه پاسکالی معمولی است، می‌توانید آن را بر اساس نیازهای گردش کار خود دسته‌بندی کنید — مشکلات ساختاری را به عنوان رد کار جدی در نظر بگیرید، ویژگی pvxiMissingTitle (که در استاندارد توصیه شده است و الزامی نیست) را به عنوان هشدار قرار دهید، و بقیه موارد را ثبت کنید. همین نوع رکورد اطلاعات مورد نیاز بخش تولید گزارش کامپوننت را نیز تامین می‌کند، بنابراین اگر ترجیح می‌دهید به جای کار با مقادیر شمارشی (enums)، یک مستند قابل خواندن توسط انسان تولید کنید، الگوی ذکرشده در ساخت ابزار گزارش‌دهی دسته‌ای پیش‌چاپ تحت خط فرمان با کامپوننت PDFium به همان صورت برای PDF/X نیز کاربرد دارد

آنچه لایه سطح بایت شناسایی می‌کند — و آنچه نادیده می‌گیرد

لایه سطح بایت یک اسکن نشانه‌ای (token scan) روی بایت‌های ساختاری سند است در حالی که بدنه جریان‌ها (streams) نادیده گرفته می‌شوند، بنابراین یک تصویر JPEG که حاوی الگوی بایت /JavaScript باشد، نمی‌تواند باعث ایجاد یک هشدار نادرست شود. علاوه بر بررسی‌های نشانگر (شامل ویژگی XMP pdfxid:GTS_PDFXVersion، مشخصه OutputIntent با یک پروفایل ICC تعبیه‌شده، تریلر /ID، و ممنوعیت رمزگذاری)، بخش بررسی محتوا هشت مورد را اضافه می‌کند که هر کدام دارای مقدار شمارشی خود هستند:

  • pvxiLzwForbidden — وجود فیلتر /LZWDecode در هر جایی از فایل (که در تمام نسخه‌های PDF/X ممنوع است)
  • pvxiJavaScriptForbidden — وجود یک اکشن یا درخت نام /JavaScript
  • pvxiFormFieldsForbidden — وجود دیکشنری /AcroForm یا ورودی /XFA
  • pvxiAdditionalActions — وجود دیکشنری عملیات اضافه /AA
  • pvxiEmbeddedFilesForbidden — وجود مشخصه /EmbeddedFiles یا یادداشت /FileAttachment
  • pvxiOpiForbidden — وجود یک ورودی /OPI یا /Alternates که به محتوای تصویری قابل جایگزینی ارجاع می‌دهد
  • pvxiMissingTrimBox — پیدا نشدن /TrimBox در هر یک از صفحات
  • pvxiTrappedNotSet — مفقود بودن /Trapped یا تنظیم شدن آن روی /Unknown

اسکن بایت سریع است و نیازی به موتور رندر ندارد، اما با یک نقطه کور ذاتی در رابطه با فونت‌ها مواجه است: در این سطح، بازرس تنها می‌تواند یک ارزیابی کلی را اعمال کند — یعنی وقتی که سند اصلاً فاقد برنامه فونت تعبیه‌شده باشد، آن را علامت‌گذاری می‌کند. فایلی با نه فونت تعبیه‌شده و یک فونت سیستم که به فایل نفوذ کرده باشد در اسکن بایت بدون اشکال به نظر می‌رسد. این شکاف دلیلی است که لایه دوم برای آن طراحی شده است

بررسی تعبیه‌سازی فونت‌ها از طریق مدل شیء PDFium

لایه مدل شیء در کامپوننت PDFium به سؤال مربوط به فونت‌ها به طور دقیق پاسخ می‌دهد. پس از مرحله اسکن بایت، متد TPdf.ValidatePdfX تمام صفحات را پیمایش می‌کند، با متد FPDFPage_CountObjects تعداد اشیاء را به دست می‌آورد، و برای هر شیء متنی هندل فونت را از طریق FPDFTextObj_GetFont دریافت کرده و متد FPDFFont_GetIsEmbedded را فراخوانی می‌کند. وجود حتی یک فونت غیرتعبیه‌شده در هر جایی از سند، مقدار pvxiPdfiumFontNotEmbedded را به مجموعه مشکلات اضافه می‌کند. این پیمایش در صورت تایید خطا متوقف می‌شود — یعنی به محض تأیید وجود مشکل، اسکن اشیاء در صفحه و بارگذاری صفحات دیگر را متوقف می‌کند — بنابراین در یک کاتالوگ ۳۰۰ صفحه‌ای دارای اشکال، نتیجه کار اغلب پس از صفحه اول مشخص می‌شود

دو نکته درباره مرز عملکردی که دانستن آنها مفید است. اول اینکه، این لایه نیاز به بارگذاری کتابخانه پی‌دی‌اف‌یوم دارد و به نسخه‌هایی نیاز دارد که تابع FPDFFont_GetIsEmbedded را صادر کنند; در صورت عدم وجود این تابع صادرشده، این بررسی به جای ایجاد خطا نادیده گرفته می‌شود، بنابراین یک DLL قدیمی هرگز هشدارهای اشتباهی تولید نخواهد کرد. دوم اینکه، این بررسی تنها به وضعیت تعبیه‌شدن یا نشدن پاسخ می‌دهد — تفاوتی بین تعبیه‌سازی کامل (full embedding) یا زیرمجموعه (subsetting) قائل نمی‌شود، و پوشش گلیف‌ها را بررسی نمی‌کند. وقتی یک فایل رد می‌شود و می‌خواهید بدانید کدام فونت در کدام صفحه مشکل دارد، تکنیک‌های پیمایش ذکرشده در بخش تجزیه و تحلیل ویژگی‌های فونت PDF با پی‌دی‌اف‌یوم در دلفی دقیقاً از همان جایی شروع می‌کنند که خروجی بولی اعتبارسنجی به پایان رسیده است

اعتبارسنجی جریان‌ها بدون بارگذاری سند — یا فایل DLL

سیستم بررسی سطح بایت به صورت یک تابع مستقل با نام ValidatePdfXCompliance(Source: TStream) نیز در یونیت FPdfPdfx ارائه شده است و کدهای آن به صورت آبجکت پاسکال خالص و بدون هیچ وابستگی به DLL پی‌دی‌اف‌یوم می‌باشد. این امر باعث می‌شود در محیط‌هایی که موتور رندرینگ مناسب نیست قابل استفاده باشد: مانند یک فیلتر آپلود سبک روی وب‌سرور، یک فرآیند CI که تصاویر تولیدشده را بررسی می‌کند، یا یک سرویس تحت لازاروس روی پلتفرمی که ترجیح می‌دهید باینری‌های بومی را در آن ارائه ندهید. شما می‌توانید هر جریان با قابلیت جستجو (seekable stream) را به آن ارسال کنید:

uses Classes, FPdfPdfx;

function QuickPdfXGate(const FileName: string): Boolean;
var
  Fs: TFileStream;
  Res: TPdfXValidationResult;
begin
  Fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    Res := ValidatePdfXCompliance(Fs);
    Result := Res.IsCompliant and (Res.Conformance <> pxcNone);
  finally
    Fs.Free;
  end;
end;

این یک موازنه صریح است: مسیر مستقل، بررسی‌های نشانگر و هر هشت بررسی محتوا را اجرا می‌کند، اما لایه بررسی فونت پی‌دی‌اف‌یوم را ندارد، بنابراین ارزیابی فونت در آن به بررسی کلی محدود می‌شود. یک معماری منطقی از متد ValidatePdfXCompliance به عنوان فیلتر اول ارزان استفاده می‌کند و متد کامل TPdf.ValidatePdfX را برای فایل‌هایی که از فیلتر اول عبور می‌کنند رزرو می‌نماید

نقطه پایان عملکرد این اعتبارسنج و شروع یک پیش‌چاپ کامل

در ابزارهای پیش‌چاپ واقع‌بینی اهمیت دارد، بنابراین مرز عملکردی به این صورت است. متد ValidatePdfX نشانگرهای شناسایی، ممنوعیت‌های ساختاری، فیلدهای هندسی صفحه، وضعیت Trapped، و تعبیه‌سازی فونت‌ها را تا تک‌تک اشیاء متنی بررسی می‌کند. اما این متد میزان پوشش کل جوهر را اندازه‌گیری نمی‌کند، قانونی بودن فضاهای رنگی برای نسخه اعلام‌شده را تایید نمی‌نماید (مثلاً قانون CMYK-only در استاندارد X-1a)، رزولوشن تصویر را بررسی نمی‌کند، یا رفتار همپوشانی رنگ‌ها (overprint) و تخت‌سازی شفافیت را ارزیابی نمی‌نماید — این‌ها به یک موتور مدیریت رنگ پیش‌چاپ نیاز دارند، و مستندات خود یونیت نیز توصیه می‌کند برای تایید نهایی کار، آن را در کنار یک سیستم پیش‌چاپ کامل قرار دهید. آنچه این بررسی دو لایه به شما ارائه می‌دهد، شناسایی ۸۰٪ از موارد رد کار است که ساختاری بوده و در زمان کوتاه چند میلی‌ثانیه‌ای در کدهای دلفی شما شناسایی می‌شوند، به جای اینکه فردا ایمیل رد کار را از چاپخانه دریافت کنید

هر دو لایه اعتبارسنجی، APIهای تزریق نشانگر PDF/X برای تولید خروجی‌های منطبق، و اعتبارسنج‌های استانداردهای PDF/A، PDF/UA, PDF/E، و PDF/VT که ساختار مشابهی دارند همگی همراه با PDFium Component برای دلفی و سی‌پلاس‌پلاس‌بیلدر ارائه می‌شوند — یک کامپوننت جامع، از رندرینگ تا کنترل‌های پیش‌چاپ