ضع تقريرًا ممسوحًا بحجم 80 ميغابايت خلف رابط، وافتحه في متصفح، وشاهد ما يحدث: يبقى العارض على لوحة فارغة حتى يصل جزء كبير من تلك البايتات، ثم يرسم الصفحة الأولى دفعة واحدة. انتقل إلى الصفحة 40، وفي ملف مبني بشكل سيئ قد يبدأ التنزيل كله من جديد. المزعج أن القارئ لم يكن يريد سوى الصفحة الأولى. الخطية هي الجواب البنيوي على هذه المشكلة. فهي تعيد ترتيب PDF بحيث يستطيع العارض رسم الصفحة الافتتاحية من بادئة صغيرة من الملف وجلب الباقي عند الطلب، ولهذا تسوق Adobe الميزة باسم "Fast Web View"
ولا شيء من هذا يمثل تنسيق ملف مختلفًا. ملف PDF الخطي هو PDF عادي يفتحه القارئ المطابق للمواصفة من دون معالجة خاصة. الحيلة كلها في ترتيب البايتات وفي البنيتين الإضافيتين اللتين يحملهما الملف. يحدد ISO 32000-1 هذا الترتيب كاملًا في Annex F، وما إن ترى التخطيط حتى يتوقف السلوك عن الظهور كالسحر ويبدأ في الظهور كصفقة مقصودة بين ترتيب الملف وزمن ظهور الإطار الأول
ما الذي تعيد الخطية ترتيبه فعليًا
يمكن لـ PDF العادي أن يبعثر كائناته تقريبًا بأي ترتيب. ما يجعل ذلك يعمل هو جدول المراجع المتقاطعة في نهاية الملف: ينتقل القارئ إلى النهاية، ويقرأ المؤشر startxref، ويحمل xref، ومن هناك يستطيع تحديد موقع كل كائن بواسطة إزاحته. هذا التصميم ممتاز للملفات المحلية، حيث لا تكلفك القفزة إلى النهاية شيئًا، لكنه ضعيف مع ملف يتدفق عبر الشبكة، لأن النهاية هي بالضبط الجزء الذي يصل أخيرًا. ولرسم الصفحة الأولى يحتاج القارئ التقليدي إلى كائن الصفحة وتدفق محتواها والخطوط التي تشير إليها وأي صور يرسمها، وفي ملف غير مرتب يمكن أن توجد هذه العناصر في أي مكان، حتى في الميغابايت الأخيرة
تصلح الخطية الترتيب. تُجمع الكائنات اللازمة لعرض الصفحة الأولى في كتلة متجاورة قرب المقدمة، مباشرة بعد قسم رأس صغير، حتى تصل مبكرًا في تيار البايتات. أما كل شيء آخر، الصفحات المتبقية والموارد المشتركة بينها، فيتبع تسلسلًا يمكن التنبؤ به. يظل جدول المراجع المتقاطعة الكامل موجودًا في النهاية للقراء الذين يتجاهلون التحسين، لكن الملف الخطي يضع أيضًا مرجعًا متقاطعًا للصفحة الأولى والبارامترات التي يحتاجها القارئ المتدفق في المقدمة. عندها لا يعود القارئ مضطرًا إلى الوصول إلى الذيل قبل أن يرسم أي شيء
مجموعة كائنات الصفحة الأولى وقاموس بارامترات الخطية
أول كائن في الملف الخطي، بعد رأس %PDF، هو قاموس بارامترات الخطية. وهو ما يبحث عنه القارئ المتدفق ليتأكد من وجود التحسين وكيفية استخدامه. يسجل القاموس طول الملف كله، وإزاحة البايت التي يبدأ عندها قسم المراجع المتقاطعة الرئيسي، ورقم كائن الصفحة الأولى، وموقع تيار التلميح الذي يلي ذلك وطوله. بهذه الأرقام يعرف القارئ، من الكيلوبايتات الأولى وحدها، كم يجب أن يجلب لعرض الصفحة الأولى وأين يجد الفهرس الذي يسمح له بالقفز إلى موضع آخر
يكون Annex F صارمًا بشأن معنى "الصفحة الأولى" هنا. يجب أن يحتوي قسم الصفحة الأولى على كائن الصفحة نفسه وتيارات المحتوى والموارد التي تشير إليها تلك التيارات، بحيث تصبح الصفحة مكتفية ذاتيًا بعد تنزيل تلك البادئة. أما الموارد المشتركة، مثل خط مستخدم في كل صفحة أو شعار يتكرر في رأس الصفحة، فتعالج بطريقة خاصة: تظهر مبكرًا بما يكفي لخدمة الصفحة الأولى لكنها تُعلَّم على أنها مشتركة حتى لا يعيد القارئ جلبها عندما يرسم الصفحة 30 لاحقًا. هذا الفرق بين الكائنات الخاصة بالصفحة والكائنات المشتركة هو أكثر ما يخطئ فيه "محسنو" التوليد اليدوي، وخطؤهم هو ما ينتج ملفًا يدّعي أنه خطي لكنه ما يزال يتوقف
تيارات التلميح: الفهرس الذي يجعل القفز بين الصفحات رخيصًا
عرض الصفحة الأولى بسرعة ليس سوى نصف الفائدة. النصف الآخر هو القفز إلى أي صفحة من دون تنزيل كل ما بينهما، وهذا ما توفره تيارات التلميح. يحمل الملف الخطي جدول تلميح لإزاحات الصفحات وجدولًا لتلميح الكائنات المشتركة، محفوظين كتيار مشار إليه من قاموس البارامترات. يسجل جدول إزاحات الصفحات، لكل صفحة، أين تبدأ كائناتها في الملف وكم يمتد طولها. ويفعل جدول الكائنات المشتركة الشيء نفسه للموارد المستخدمة عبر صفحات متعددة
وبهذه الجداول لا يحلل القارئ الذي يريد الصفحة 40 الملف تسلسليًا. بل يرجع إلى جدول التلميح ليتعرف إلى نطاق البايتات الذي تشغله الصفحة 40، ويطلب من الخادم ذلك النطاق تحديدًا، ثم يرسم الصفحة ما إن تصل تلك البايتات، مع جلب أي موارد مشتركة لا يملكها عبر الآلية نفسها. يمكن اعتبار تيار التلميح خريطة وصول عشوائي موضوعة فوق المستند، وهو سبب شعور ملف من 500 صفحة، إذا كان خطيًا جيدًا، بأنه سريع الاستجابة عبر اتصال بطيء بينما لا يفعل الملف غير المحسن من الحجم نفسه ذلك
لماذا يجب أن يتعاون الخادم
تفترض الخطية أن وسيط النقل يستطيع تسليم مقاطع عشوائية من الملف، وهذا افتراض يستحق الفحص قبل أن تنسب النتائج السيئة إلى الصيغة. الآلية هنا هي خدمة البايتات عبر HTTP: يصدر القارئ طلبات نطاقات، ويجيب الخادم عليها باستجابات 206 Partial Content. إذا لم يعلن الخادم Accept-Ranges: bytes، أو إذا قام proxy أو CDN أمامه بتسطيح طلبات النطاق إلى عمليات نقل كاملة، فلن يملك القارئ طريقة لجلب الصفحة 40 بمعزل، وسيعود إلى تنزيل الملف كله. عندها تكون البنية داخل PDF صحيحة تمامًا لكنها مهدورة بالكامل
هذا هو الفشل الذي يُساء تشخيصه غالبًا على أنه "الخطية لا تعمل". الملف سليم، لكن طريق التسليم ليس كذلك. قبل أن تعيد بناء المستند، تحقق بطلب مشروط من أن المضيف يعيد فعلًا محتوى جزئيًا للرابط الذي يصل إليه القارئ. كثير من المضيفات الثابتة تفعل ذلك افتراضيًا، وكثير من خوادم التطبيقات وطبقات التخزين المؤقت سيئة الإعداد لا تفعل
التحديثات التزايدية تكسر الخطية بهدوء
هذه هي القاعدة التي تفاجئ من يولدون ملفات خطية بشكل صحيح ثم يتساءلون لماذا يتبخر التحسين. تعتمد الخطية على تخطيط واحد مرتب بعناية مع فهرسه في المقدمة. أما التحديث التزايدي فيكسر ذلك بطبيعته. عندما تضيف أداة توقيعًا أو تملأ حقل نموذج أو تلحق تعليقًا توضيحيًا عبر حفظ تزايدي، فهي لا تعيد كتابة الملف. بل تلحق الكائنات المتغيرة وقسمًا جديدًا من المراجع المتقاطعة و trailer جديدًا في النهاية، وتترك البايتات الأصلية دون مساس. وهذه الإضافة هي جوهر التحديثات التزايدية: فهي سريعة وتحفظ المراجعة السابقة لأغراض التدقيق أو التحقق من التوقيع
والأثر الجانبي هو أن الملف يصبح الآن يملك أحدث بيانات المراجع المتقاطعة في الذيل، بعد كتلة الصفحة الأولى الموضوعة بعناية، بينما يصف قاموس بارامترات الخطية في المقدمة تخطيطًا لم يعد يطابق الملف. يكتشف القارئ المطابق للمواصفة هذا التعارض ويعامل المستند كملف PDF عادي غير خطي. عندها يختفي Fast Web View، رغم أن البنية الخطية الأصلية ما تزال جالسة في النصف الأول من الملف. وإذا ألحقت عدة تحديثات فكل واحد منها يضيف مراجعة أخرى في النهاية، وتتسع الفجوة بين الفهرس الأمامي القديم والحالة الحقيقية
إذا كان سير العمل يحتاج إلى التعديلات وإلى Fast Web View معًا، فالقاعِدة تخرج مباشرة من البنية: عدّل تزايديًا بينما يكون المستند في حالة تغير، ثم أعد الخطية مرة واحدة في النهاية. إعادة الكتابة الكاملة هي ما يعيد التخطيط. بلغة HotPDF، يعني ذلك أن التحرير الجاري يمر عبر BeginIncrementalUpdate وSaveIncrementalUpdate، اللذين يلحقان الفرق، بينما خطوة الإنهاء تحمل المستند كله وتعيد تسلسله من جديد باستخدام LoadFromFile يتبعه SaveLoadedDocument، وهذا يزيل المراجعات القديمة المتراكمة ويصدر تخطيطًا نظيفًا واحدًا. وتظهر الصفقة نفسها مع object streams: فتمكين UseObjectStreams مع UseXRefStream يضغط المراجع المتقاطعة ويحزم الكائنات بإحكام، وهو ما يفيد حجم الملف، لكنه مثل أي قرار بنيوي يجب تطبيقه في إعادة الكتابة النهائية لا إلصاقه بمراجعة مضافة
// In-flight edits: append a delta, keep prior revisions intact.
// This leaves the file NOT linearized.
Pdf.BeginIncrementalUpdate('report.pdf');
Pdf.AddPage;
Pdf.CurrentPage.TextOut(72, 760, 0, 'Addendum');
Pdf.SaveIncrementalUpdate('report.pdf');
// Finishing step: full re-serialization produces one clean layout,
// dropping the stacked revisions. Re-run your linearizer on the output.
Pdf.LoadFromFile('report.pdf');
Pdf.SaveLoadedDocument('report-final.pdf');
لا يوفّر HotPDF روتينًا من استدعاء واحد لـ "linearize"، لذا فإن النمط العملي هو إنتاج ملف نظيف معاد كتابته بالكامل ثم تمرير محسن مخصص عليه. تتولى أدوات سطر الأوامر إعادة الترتيب مباشرة. يعيد qpdf كتابة الملف إلى صيغة خطية بعلم واحد:
qpdf --linearize report-final.pdf report-web.pdf
كيف تتأكد من أن الملف خطي
لا تثق باسم الملف أو بالأداة التي تقول إنها أنشأته، بل تحقق من البايتات نفسها. أوضح فحص هو رأس الملف: افتحه وابحث عن قاموس بارامترات الخطية كأول كائن بعد الرأس، ويحمل المفتاح /Linearized. أما الاختصار المواجه للقارئ فهو مربع Document Properties في Acrobat، الذي لا يعرض "Fast Web View: Yes" إلا عندما تكون البنية موجودة فعلًا ومحدثة
أما للفحوصات البرمجية، فيبلغ qpdf عن وجود البنية وعن سلامتها معًا، وهذا مهم لأن الملف قد يحمل قاموس خطية لم يعد يعكس تخطيطه، وهي بالضبط الحالة التي يتركها التحديث التزايدي:
# Reports "File is linearized" and validates hint tables against the layout
qpdf --check report-web.pdf
# Dumps the linearization parameters and hint data in detail
qpdf --show-linearization report-web.pdf
خطوة التحقق هي التي تستحق وقتها. ففحص يؤكد وجود القاموس فقط سيبارك بسعادة ملفًا يشير فهرسه إلى إزاحات خاطئة؛ أما الفحص الذي يطابق جداول التلميح مع مواقع الكائنات الفعلية فهو ما يخبرك بأن التحسين سيصمد أمام طلبات النطاق من قارئ حقيقي
تظل الخطية جديرة بالتطبيق على أي مستند كبير يُقدَّم عبر الويب، خصوصًا للقراء على الأجهزة المحمولة والاتصالات المتذبذبة، وتكلف بضع نسب مئوية من حجم الملف بسبب الفهرس المحمّل في المقدمة. المهم إبقاؤه واضحًا هو أن البنية داخل PDF وخدمة البايتات خارجه يجب أن تكونا صحيحتين معًا، وأن أي تعديل لاحق ينسف التحسين حتى تعيد كتابة الملف. عامل إعادة الخطية كآخر خطوة في المسار، بعد أن يستقر كل تغيير آخر. إن سلوك المراجع المتقاطعة وobject streams والتحديث التزايدي الموصوف هنا هو جزء من النموذج البنيوي الذي تنفذه HotPDF Component لـ Delphi و C++Builder؛ ولخلفية أوسع عن تخطيط الملفات راجع كيف تُبنى بنية PDF، وللسير العملي للتحديث التزايدي والملفات الكبيرة في الشفرة راجع معالجة ملفات PDF الكبيرة من Delphi