التخطيط: الترويسات والتذييلات والأعمدة والكتيّب وإدارة الصفحات
لمحة سريعة
قسم بعنوان «لمحة سريعة»تضم وحدة Layout محرّكات تجهيزات الصفحة خلف واجهة Document: الترويسات والتذييلات والتخطيط متعدد الأعمدة وفرض ترتيب الكتيّب بخياطة السرج والعمليات الهيكلية للصفحات. وهي وحدة صغيرة ومستقرة: ست فئات، جميعها @since 1.0.0.
التثبيت
قسم بعنوان «التثبيت»composer require nextpdf/core:^3نظرة مفاهيمية عامة
قسم بعنوان «نظرة مفاهيمية عامة»Layout (src/Layout/، ست فئات، @since 1.0.0) هي طبقة المحرّك أسفل الجانب البرمجي HasLayout. يستدعي تطبيقك أساليب الواجهة على Document؛ وتوجّه السمة كل استدعاء إلى أحد هذه المحرّكات. يصنّف البيان الوحدة بمخاطر من نوع standard واستقرار من نوع internal، وتبقى Core الوحدة الوحيدة المعتمِدة عليها. استخدمها عبر الواجهة، لا عبر إنشاء الفئات مباشرةً.
يعرض HeaderFooter الترويسة والتذييل المتكررين. ويخزّن حالة العنوان والوصف والشعار والخط والهامش واللون لكل شريط. ويُصدِر معاملات تدفق المحتوى لتنسيق المستندات المحمول (PDF) عند الطلب عبر renderHeader() وrenderFooter(). يطبع التذييل الافتراضي سلسلة "page / total" بمحاذاة إلى اليمين. يستبدل setHeaderCallback() وsetFooterCallback() التخطيط الافتراضي بإغلاق يوفّره المستدعي. يُبلِغ getHeaderContentHeight() عن المساحة الرأسية التي تشغلها الترويسة، حتى يبدأ متن الصفحة أسفلها. عندما يكون المستند في وضع PDF الموسوم، يكبت HasPages الترويسة التلقائية أعلى السلسلة لأن محتوى الترويسة يقع خارج شجرة البنية.
يدير ColumnLayout التدفق متعدد الأعمدة. يقسّم setEqualColumns(int $count, float $totalWidth, float $gap = 5) العرض المتاح إلى أعمدة متساوية. يقبل setColumnsArray() مواضع وعروضًا صريحة من نوع ColumnDefinition. استخدم selectColumn() لاختيار عمود، أو nextColumn() للتقدّم إلى العمود التالي. يُرجِع getCurrentColumnX() / getCurrentColumnWidth() هندسة العمود النشط. يؤدي عدد أعمدة غير صالح أو فجوة سالبة أو عرض عمود محسوب غير موجب إلى رفع PageLayoutException.
يعيد BookletLayout ترتيب الصفحات للتجليد بخياطة السرج (الطي من المنتصف). يحشو reorderPages() قائمة الصفحات لتصبح من مضاعفات الأربعة لأن ورقة الكتيّب تستوعب أربع خانات للصفحات، ثم يفرض ترتيب الصفحات من الخارج إلى الداخل بحيث تُقرأ الأوراق المطوية والمدبّسة بالترتيب. يُرجِع getMarginAdjustments() الهامشين الداخلي (عند الكعب) والخارجي (عند الحافة) لكل جانب عند موضع معيّن. يُبلِغ getSheetCount() عن عدد الأوراق ذات الوجهين التي يتطلبها عدد صفحات معيّن. تغيّر إعادة الترتيب موضع المحتوى فقط. ويبقى تسلسل صفحات PDF الأساسي خطيًا، بما يتسق مع شجرة الصفحات التي تحدد ترتيب الصفحات في المستند (ISO 32000-2 §7.7).
يوفّر PageManager عمليات هيكلية على الصفحات منفصلة عن عرض المحتوى. تعمل movePage() وcopyPage() وdeletePage() على مصفوفة PageData بالمرجع. تحدد مناطق الصفحات (addPageRegion() وisInRegion() وgetRegionOffset()) مناطق المنع من الكتابة. تدعم مجموعات الصفحات (startPageGroup() وgetGroupPageNo()) ترقيم الصفحات لكل قسم. PageRegion وColumnDefinition هما حاملا القيم اللذان تستخدمهما هذه المحرّكات. تسلسل وحدة Writer الصفحات الناتجة في شجرة صفحات يكون مدخل Kids فيها مصفوفة من المراجع غير المباشرة إلى الأبناء المباشرين لعقدة شجرة الصفحات (ISO 32000-2 §7.7.3.2).
سطح واجهة برمجة التطبيقات
قسم بعنوان «سطح واجهة برمجة التطبيقات»| الرمز | الفئة | الاستقرار | منذ |
|---|---|---|---|
HeaderFooter::setHeaderData(string, string, string, float): self | أسلوب | مستقر | 1.0.0 |
HeaderFooter::setHeaderFont(string, float): self / setHeaderMargin(float): self | أسلوب | مستقر | 1.0.0 |
HeaderFooter::setFooterFont(string, float): self / setFooterMargin(float): self | أسلوب | مستقر | 1.0.0 |
HeaderFooter::setHeaderCallback(Closure): self / setFooterCallback(Closure): self | أسلوب | مستقر | 1.0.0 |
HeaderFooter::getHeaderContentHeight(): float | أسلوب | مستقر | 1.0.0 |
HeaderFooter::renderHeader(float, float, float, float, int, int): string | أسلوب | مستقر | 1.0.0 |
HeaderFooter::renderFooter(float, float, float, float, int, int, string): string | أسلوب | مستقر | 1.0.0 |
ColumnLayout::setEqualColumns(int, float, float): self | أسلوب | مستقر | 1.0.0 |
ColumnLayout::setColumnsArray(array): self / resetColumns(): self | أسلوب | مستقر | 1.0.0 |
ColumnLayout::selectColumn(int): self / nextColumn(): bool | أسلوب | مستقر | 1.0.0 |
ColumnLayout::getCurrentColumnX(float): float / getCurrentColumnWidth(float): float | أسلوب | مستقر | 1.0.0 |
BookletLayout::setBooklet(bool, float, float): void | أسلوب | مستقر | 1.0.0 |
BookletLayout::reorderPages(array): array | أسلوب | مستقر | 1.0.0 |
BookletLayout::getMarginAdjustments(int): array{left: float, right: float} | أسلوب | مستقر | 1.0.0 |
BookletLayout::getSheetCount(int): int | أسلوب | مستقر | 1.0.0 |
PageManager::movePage(int, int, array): void / copyPage(int, array): void / deletePage(int, array): void | أسلوب | مستقر | 1.0.0 |
PageManager::addPageRegion(float, float, float, float): void / isInRegion(float, float): bool | أسلوب | مستقر | 1.0.0 |
PageManager::getRegionOffset(float, float, float, float): float | أسلوب | مستقر | 1.0.0 |
PageManager::startPageGroup(): void / getGroupPageNo(int): int | أسلوب | مستقر | 1.0.0 |
PageRegion / ColumnDefinition | حامل قيمة | مستقر | 1.0.0 |
عينة برمجية — بدء سريع
قسم بعنوان «عينة برمجية — بدء سريع»<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Header and Footer');
$doc->setHeaderData( title: 'NextPDF Example', description: 'Header and Footer Demonstration',);$doc->setHeaderFont('helvetica', 10);$doc->setHeaderMargin(5);$doc->setFooterFont('helvetica', 8);$doc->setFooterMargin(10);
$doc->addPage();$doc->setFont('helvetica', 'B', 16);$doc->cell(0, 12, 'Document with Header and Footer', newLine: true);
$doc->save(__DIR__ . '/output/13-header-footer.pdf');المصدر: examples/13-header-footer.php. تُعرض الترويسة عند كل استدعاء لـ addPage()؛ ويُعرض التذييل عند تفريغ الصفحة.
عينة برمجية — إنتاج
قسم بعنوان «عينة برمجية — إنتاج»يتحكم رد نداء التذييل في نص رقم الصفحة، ويقود محرّك الأعمدة متنًا بعمودين. تصل إلى كلا المحرّكين عبر الواجهة.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Two-Column Report');
$doc->setFooterCallback(static function (Document $d): void { $d->setFont('helvetica', '', 8); $d->text(180.0, 285.0, 'Page ' . ($d->getPage() + 1));});
$doc->addPage();$doc->setEqualColumns(2, gap: 8);$doc->selectColumn(0);$doc->setFont('helvetica', '', 10);$doc->multiCell(0, 6, 'Left column flows here.');$doc->selectColumn(1);$doc->multiCell(0, 6, 'Right column flows here.');
$doc->save(__DIR__ . '/output/two-column-report.pdf');المصدر: نمط مأخوذ من examples/13-header-footer.php.
الحالات الطرفية والمزالق
قسم بعنوان «الحالات الطرفية والمزالق»- يرفض
setEqualColumns()عدد أعمدة أقل من 1، أو فجوة سالبة، أو أي تخطيط يكون عرض العمود المحسوب فيه غير موجب. ويرفعPageLayoutExceptionبدلًا من إرجاع تخطيط منقوص. - يتجاهل
selectColumn()أي فهرس خارج النطاق ويحتفظ بالعمود الحالي؛ ولا يطرح استثناءً أبدًا لفهرس غير صالح. يُرجِعnextColumn()القيمةfalseعندما يكون في العمود الأخير بالفعل. - يحشو
BookletLayout::reorderPages()إلى مضاعف الأربعة بصفحات فارغة مستنسخة من أبعاد الصفحة الأخيرة. وتُرجِع قائمة الصفحات الفارغة مصفوفة فارغة. تؤثر إعادة الترتيب في الموضع فقط؛ ولا تزال فهارسmovePage()تشير إلى الترتيب المنطقي. - لا تفعل
PageManager::movePage()وcopyPage()وdeletePage()شيئًا بصمت لفهرس خارج النطاق؛ إذ تتحقق بواسطةisset()وتعود دون تعديل المصفوفة. تحقّق من الفهرس بنفسك عندما تكون الصفحة المفقودة خطأً من المستدعي. - يُرجِع
getHeaderContentHeight()القيمة0.0عندما تكون الترويسة معطّلة أو لا تحمل عنوانًا ولا وصفًا. عندئذٍ يبدأ متن الصفحة عند الهامش العلوي. - في وضع PDF الموسوم، تُكبت الترويسة التلقائية أعلى السلسلة. أنشئ تخطيطًا واعيًا بالبنية للمستندات القابلة للوصول.
الأداء
قسم بعنوان «الأداء»يلحق عرض الترويسة والتذييل المعاملات بمخزّن الصفحة النشطة بتعقيد O(محتوى التجهيزات)؛ إذ تتناسب التكلفة مع العنوان والوصف والفاصل المكتوب، لا مع حجم المستند. ويكون حساب الأعمدة بتعقيد O(1) لكل استدعاء. يعمل BookletLayout::reorderPages() بتعقيد O(n) في عدد الصفحات، مع تمريرة حشو لمرة واحدة؛ وتلمس حلقة الفرض كل خانة محشوة مرة واحدة. تعمل اختبارات المناطق في PageManager بتعقيد O(المناطق) لكل نقطة، وتعمل عمليات الصفحات بتعقيد O(n) بسبب عمليات وصل المصفوفة. لا تحتفظ هذه المحرّكات بأي حالة لكل صفحة عبر المستند، لذلك لا تضيف نموًا في الذاكرة على المستندات الطويلة. التكلفة الأكبر في الذاكرة هي تدفق المحتوى المتراكم، ويغطيها مفهوم التدفق والذاكرة. بوابة زمن الاستجابة وميزانية الذاكرة لأنبوب لغة ترميز النص التشعبي (HTML) موثّقة في PERFORMANCE-BUDGETS؛ وهي محصورة في مسار عرض HTML ولا تضبط محرّكات التخطيط هذه مباشرةً. performance_budget البالغ 1500 ms / 64 MB هو مغلّف اللوحة للبدء السريع، وليس عقدًا لكل استدعاء.
ملاحظات أمنية
قسم بعنوان «ملاحظات أمنية»تستهلك هذه المحرّكات سلاسل يوفّرها المستدعي ومسار شعار يوفّره المستدعي. يمر مسار الشعار عبر محرّك الصور، الذي يتحقق من الملف قبل تضمينه. يهرّب renderHeader() وrenderFooter() نص العنوان والوصف ورقم الصفحة عبر مُهرّب سلاسل PDF المركزي قبل أن تصل إلى تدفق المحتوى، بحيث لا يمكن لنص المستدعي أن يخرج عن قواعد السلسلة الحرفية. يشغّل رد نداء الترويسة أو التذييل شيفرة المستدعي بدرجة الثقة نفسها الممنوحة لبقية المستند؛ فتعامل مع أي بيانات خارجية يقرأها وفقًا لذلك. تنقل عمليات الصفحات في PageManager مراجع إلى PageData قائمة؛ ولا تحلّل بايتات غير موثوقة.
المطابقة
قسم بعنوان «المطابقة»| الادّعاء | المعيار | البند | الدليل |
|---|---|---|---|
| تغيّر إعادة ترتيب الصفحات لإخراج الكتيّب الموضع فقط؛ ولا تزال شجرة الصفحات تحدد الترتيب الخطي للصفحات في المستند. | ISO 32000-2 | §7.7 | |
مدخل Kids لعقدة شجرة الصفحات المُسلسلة هو مصفوفة من المراجع غير المباشرة إلى الأبناء المباشرين لتلك العقدة. | ISO 32000-2 | §7.7.3.2 |
يعيد الجدول صياغة كل بند ويُبقي مصطلحات المسرد ثابتة؛ ولا يعيد إنتاج النص المعياري.
انظر أيضًا
قسم بعنوان «انظر أيضًا»- السمة Core/HasLayout — الجانب البرمجي للواجهة الذي يركّب محرّكات التخطيط.
- السمة Core/HasPages — حجم الصفحة والهوامش المستخدمة في حساب الأعمدة.
- Writer — باعث كائن PDF وشجرة الصفحات الذي يُسلسل الصفحات المخططة.
- التدفق والذاكرة — لماذا لا تحتفظ محرّكات التجهيزات بأي حالة لكل صفحة، وكيف يعمل مسار العرض المقيّد بالذاكرة.
- قيود HTML / التدفق (ADR-001) — المبرر لنطاق التدفق أحادي المرور.