افحص صناديق التخطيط قبل وضع المحتوى
لمحة سريعة
قسم بعنوان «لمحة سريعة»اقرأ هندسة التخطيط الحية للمستند قبل وضع المحتوى. تقرأ هذه الوصفة صندوق الصفحة والهوامش ومناطق منع الكتابة والمؤشر الحالي. عندها يستطيع منطق الوضع لديك استخدام أرقام حقيقية بدلًا من إحداثيات مُخمَّنة. تستند الوصفة إلى examples/34-inspect-layout-boxes.php وإلى منظومة الاختبار tests/Cookbook/Php/InspectLayoutBoxesRecipeTest.php الخاصة بها.
التثبيت
قسم بعنوان «التثبيت»composer require nextpdf/core:^3لا تحتاج إلى حزمة Pro أو Enterprise. فواجهة استعلام التخطيط جزء من Core وتعمل على PHP 8.1 حتى 8.4.
نظرة عامة مفاهيمية
قسم بعنوان «نظرة عامة مفاهيمية»تحتوي صفحة Portable Document Format (PDF) على صناديق حدود. الحد الأدنى هو MediaBox، وهو المستطيل الذي يحدد امتداد الصفحة (ISO 32000-2 §7.7.3.3). يُوضع المحتوى في فضاء المستخدم. افتراضيًا، يبدأ فضاء المستخدم من الزاوية السفلية اليسرى، وتساوي الوحدة الواحدة 1/72 بوصة (§8.3.2). يمنحك NextPDF منظورًا مريحًا للمؤلف يبدأ من أعلى اليسار، ويكشف الهندسة عبر طرائق استعلام للقراءة فقط:
getPageWidth()/getPageHeight()— أبعاد صندوق الصفحة.getMargins()— كائن القيمةMarginالفعّال (أعلى/يمين/أسفل/يسار).getPageRegions()— مناطق منع الكتابة المُعلَنة (PageRegion[]). كل منطقة مستطيل غير قابل للتغيير يُحظَر فيه وضع المحتوى.getX()/getY()— المؤشر الحي في فضاء المؤلف.
هذه عمليات قراءة بلا تأثيرات جانبية. فهي لا تُصدر محتوى ولا تحرّك المؤشر ولا تغيّر الحالة. استخدمها لحساب المساحة الرأسية المتبقية، ثم قرّر ما إذا كنت ستواصل الكتابة أم تستدعي addPage(). يمكنك أيضًا تخطيط كتلة بالنسبة إلى منطقة منع كتابة بدلًا من استخدام إزاحة ثابتة مكتوبة يدويًا.
واجهة API
قسم بعنوان «واجهة API»تُولَّد واجهة برمجة التطبيقات application programming interface (API) من PHPDoc. تقع نقاط الدخول الرئيسية في السمتين \NextPDF\Core\Concerns\HasPages وHasLayout:
Document::getPageWidth(): float/Document::getPageHeight(): floatDocument::getMargins(): \NextPDF\ValueObjects\MarginDocument::getPageRegions(): array(list<\NextPDF\Layout\PageRegion>)Document::addPageRegion(float $x, float $y, float $w, float $h): staticDocument::getX(): float/Document::getY(): float
عيّنة شيفرة — بداية سريعة
قسم بعنوان «عيّنة شيفرة — بداية سريعة»<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->addPage();
$pageHeight = $doc->getPageHeight();$margins = $doc->getMargins();$cursorY = $doc->getY();
// Vertical space left before the bottom margin.$remaining = $pageHeight - $margins->bottom - $cursorY;
// Geometry is in user-space units (PDF points; 1 pt = 1/72 in).echo sprintf("Page height: %.2f pt\n", $pageHeight);echo sprintf("Bottom margin: %.2f pt\n", $margins->bottom);echo sprintf("Cursor Y: %.2f pt\n", $cursorY);echo sprintf("Remaining: %.2f pt\n", $remaining);عيّنة شيفرة — للإنتاج
قسم بعنوان «عيّنة شيفرة — للإنتاج»يعمل هذا البرنامج المكتفي ذاتيًا ضمن منظومة الاختبار، وهو يعكس examples/34-inspect-layout-boxes.php. يقرأ هندسة الصفحة، ويُعلن منطقة منع كتابة في التذييل، ويتخذ قرارًا مبنيًا على البيانات لكل كتلة. إذا كانت الكتلة التالية ستصطدم بمنطقة أو تتجاوز الهامش السفلي، فإنه يضيف صفحة بدلًا من الطباعة فوق المحتوى.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Layout Box Inspection Demo');$doc->setLanguage('en');$doc->addPage();
// Read the geometry (idempotent, no side effects). Values are in// user-space units (PDF points; 1 pt = 1/72 in).$pageWidth = $doc->getPageWidth();$pageHeight = $doc->getPageHeight();$margins = $doc->getMargins();
echo sprintf("Page box: %.2f x %.2f pt\n", $pageWidth, $pageHeight);echo sprintf("Cursor start: (%.2f, %.2f)\n", $doc->getX(), $doc->getY());
// A 15 pt tall footer no-write zone across the text column.$footerHeight = 15.0;$footerTop = $pageHeight - $margins->bottom - $footerHeight;$doc->addPageRegion( $margins->left, $footerTop, $pageWidth - $margins->left - $margins->right, $footerHeight,);
$blocks = [ 'Section 1. Each block measures the live cursor against the page box ' . 'and any no-write region before it is placed.', 'Section 2. The lowest Y at which any region starts is the hard floor ' . 'for new content; crossing it forces a page break.', 'Section 3. Reading geometry is idempotent — the query methods never ' . 'advance the cursor, so they are safe in the placement loop.', 'Section 4. This final block forces a second page when the column is ' . 'already near the footer keep-out zone.',];
$blockHeight = 42.0;$pagesUsed = 1;
foreach ($blocks as $index => $text) { $cursorY = $doc->getY();
// Lowest Y a region starts at — the hard floor for new content. $regionFloor = $pageHeight - $margins->bottom; foreach ($doc->getPageRegions() as $region) { $regionFloor = min($regionFloor, $region->y); }
if ($cursorY + $blockHeight > $regionFloor) { $doc->addPage(); ++$pagesUsed; // A fresh page resets the region set; re-declare the footer zone. $footerTop = $doc->getPageHeight() - $doc->getMargins()->bottom - $footerHeight; $doc->addPageRegion( $doc->getMargins()->left, $footerTop, $doc->getPageWidth() - $doc->getMargins()->left - $doc->getMargins()->right, $footerHeight, ); }
$doc->setFont('helvetica', 'B', 12); $doc->cell(0, 8, 'Block ' . ($index + 1), newLine: true); $doc->setFont('helvetica', '', 11); $doc->multiCell(0, 7, $text); $doc->ln(6);}
// The harness sets NEXTPDF_COOKBOOK_OUTPUT and runs this script under the// semantic profile (validated by structural AST + metadata, not a byte hash).$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');$doc->save($out !== false && $out !== '' ? $out : __DIR__ . '/inspect-layout-boxes.pdf');
echo sprintf("Pages used: %d (page breaks decided from layout geometry)\n", $pagesUsed);المُخرَج القياسي المتوقّع (STDOUT). تعكس أرقام صندوق الصفحة حجم الصفحة A4 الافتراضي، ويبدأ المؤشر من نقطة أصل المحتوى في أعلى اليسار:
Page box: 595.28 x 841.89 ptCursor start: (<x>, <y>)Pages used: 2 (page breaks decided from layout geometry)الحالات الحدّية والمزالق
قسم بعنوان «الحالات الحدّية والمزالق»- القراءة قبل وجود الصفحة. يعكس كلٌّ من
getPageWidth()وgetPageHeight()الصفحة الحالية، لذا استدعِهما بعدaddPage(). قبل الصفحة الأولى، يُرجعان هندسة حجم الصفحة الافتراضي، لا صفحةً لم تُضِفها بعد. - المناطق مستطيلات في فضاء المؤلف. قيمة
PageRegionyهي مسافة المؤلف من أعلى اليسار، بما يتسق معgetY(). لا تخلطها بإحداثيات PDF الخام من الزاوية السفلية اليسرى. - عمليات القراءة خالية من التأثير الجانبي. لا تحرّك أيٌّ من طرائق الاستعلام المؤشر ولا تُصدر محتوى. استدعاؤها داخل حلقة مكثّفة آمن وتكلفته ضئيلة.
- يمكن أن تتغير الهوامش من صفحة إلى أخرى. إذا ضبطت صفحة لاحقة هوامش مختلفة، فأعِد قراءة
getMargins()بدلًا من تخزين القيمة الأولى مؤقتًا. - المناطق لا تعيد تدفّق النص تلقائيًا. منطقة منع الكتابة هي قيد يجب أن تحترمه، وليست حدًّا تلقائيًا لالتفاف النص. تُظهر الوصفة فحص التصادم الصريح. في الكتابة الحرة الموضع، لا ينقل المحرّك المحتوى خارج المنطقة من تلقاء نفسه أبدًا.
الأداء
قسم بعنوان «الأداء»كل طريقة هنا هي قراءة لخاصية. تعمل في زمن ثابت، دون تخصيص ذاكرة ودون إدخال أو إخراج. يبني المثال مستندًا صغيرًا متعدد الصفحات ضمن ميزانية 1500 ms / 96 MB بهامش مريح. ملف تعريف قابلية التكرار دلالي، لأن ملف PDF المُولَّد يحمل /ID في المُذيِّل وبيانات إنشاء وصفية. قرارات الهندسة الملحوظة في المثال هي الأهم، لذا تتحقّق منظومة الاختبار من تلك القرارات عبر شجرة بنية تجريدية (AST) بنيوية مع مقارنة البيانات الوصفية بدلًا من تجزئة البايتات.
ملاحظات أمنية
قسم بعنوان «ملاحظات أمنية»- إقامة البيانات وإجراءات التخفيف الخاصة بالبيانات الشخصية (PII). غير منطبق. تقرأ الوصفة الهندسة وتخطّط النص المُقدَّم من المستدعي، لذا فهي لا تُدخل أي مسار بيانات جديد. طبّق على النص الذي تضعه قواعد التقليل نفسها التي تطبّقها في أي موضع آخر.
- القياس عن بُعد الآمن وتنقية السجلات. يطبع المثال أرقام الهندسة وسطر تقدّم ثابتًا، ولا يسجّل نص المستند.
- نموذج التهديد. غير منطبق. واجهة الاستعلام للقراءة فقط ولا تحلّل أي إدخال خارجي. وهي ليست حدًّا للثقة.
- سلوك وضع FIPS. غير منطبق. لا تُجرى أي عملية تشفير.
المطابقة
قسم بعنوان «المطابقة»| العبارة | المواصفة | البند | reference_id |
|---|---|---|---|
| يحدد كائن الصفحة امتداده عبر صناديق الحدود (MediaBox). | ISO 32000-2 | §7.7.3.3 | |
| مستطيل الصفحة هو حدّ المحتوى. | ISO 32000-2 | §7.7.3.3 | |
| تُقاس المواضع في فضاء المستخدم؛ والوحدة الواحدة هي 1/72 بوصة. | ISO 32000-2 | §8.3.2 |
تقرأ هذه الوصفة الهندسة التي تحددها بنود صندوق الصفحة وفضاء المستخدم المُستشهَد بها في ISO 32000-2. ولا تدّعي مطابقة شاملة لـISO 32000-2. تعتمد واجهة استعلام التخطيط على البنود المُستشهَد بها.