ข้ามไปยังเนื้อหา

สร้างเลเยอร์เนื้อหาที่เลือกได้ (OCG)

ครอบเนื้อหาด้วยกลุ่มเนื้อหาที่เลือกได้ (OCG) ที่มีชื่อ ซึ่งมักเรียกว่าเลเยอร์ โปรแกรมอ่าน PDF สามารถเปิดหรือปิดแต่ละเลเยอร์ได้ในแผงเลเยอร์ และสามารถกำหนดให้เลเยอร์หนึ่งซ่อนอยู่ตั้งแต่ต้นได้ สูตรนี้อิงตาม examples/26-layers.php

OCG คือดิกชันนารีของกลุ่มเนื้อหาที่เลือกได้ตาม ISO 32000-2 ซึ่งมี Type /OCG NextPDF ครอบมาร์กของเลเยอร์ไว้ระหว่าง BDC/EMC และใช้ OC เป็นแท็ก marked-content

Terminal window
composer require nextpdf/core:^3

คุณไม่จำเป็นต้องใช้ส่วนขยายเพิ่มเติมใด ๆ API ของเลเยอร์มีความเสถียรมาตั้งแต่ 1.0.0 และทำงานได้บน backport matrix 8.1–8.4

startLayer($name, $visible) เปิด OCG โดยเนื้อหาทั้งหมดที่คุณวาดจนถึง endLayer() ที่จับคู่กันจะเป็นของกลุ่มนั้น $name คือป้ายชื่อที่โปรแกรมอ่าน PDF แสดงในแผงเลเยอร์ ISO 32000-2 กำหนดให้ OCG ต้องมี Name ซึ่งเป็นสตริงที่แสดงต่อผู้ใช้ การส่ง $visible: false จะลงทะเบียนกลุ่มในสถานะ OFF ของการกำหนดค่าเริ่มต้น ดังนั้นโปรแกรมอ่านจะซ่อนกลุ่มนั้นไว้จนกว่าผู้ใช้จะเปิด

การมองเห็นขึ้นอยู่กับความร่วมมือของโปรแกรมอ่าน สำหรับดิกชันนารีการเป็นสมาชิกของเนื้อหาที่เลือกได้ (OCMD) นโยบายการมองเห็นเริ่มต้นคือ AnyOn เลเยอร์จะมองเห็นได้หากกลุ่มใดกลุ่มหนึ่งที่อ้างอิงอยู่ในสถานะ ON เลเยอร์ที่ซ่อนไว้จะถูกซ่อนตามแบบแผนของโปรแกรมอ่านเท่านั้น เนื้อหานั้นไม่ได้ถูกนำออกหรือปกป้อง และไม่ใช่การปิดทับ (redaction) หรือมาตรการควบคุมความปลอดภัย หากต้องการนำเนื้อหาออก อย่าวาดเนื้อหานั้น

ขอบเขต API นี้สร้างจาก PHPDoc โดยอัตโนมัติ สูตรนี้ใช้เมธอดสองรายการต่อไปนี้:

  • startLayer(string $name, bool $visible = true): static — เปิด OCG ที่มีชื่อ โดย $visible: false จะทำให้กลุ่มถูกซ่อนไว้เป็นค่าเริ่มต้น
  • endLayer(): static — ปิดเลเยอร์ที่เปิดล่าสุด ซึ่งจับคู่กับ startLayer()
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->addPage();
$doc->startLayer('Content', visible: true);
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 8, 'Always-visible body content.', newLine: true);
$doc->endLayer();
$doc->startLayer('Debug Grid', visible: false); // hidden until toggled
$doc->setDrawColor(200, 200, 200);
for ($x = 0.0; $x <= 210.0; $x += 10.0) {
$doc->line($x, 0, $x, 297);
}
$doc->endLayer();
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/layers.pdf');

ใช้ตัวอย่างฉบับสมบูรณ์ที่พร้อมสำหรับ harness นี้ ตัวอย่างนี้ใช้ค่า NEXTPDF_COOKBOOK_OUTPUT ตามที่กำหนด และไม่สร้าง entropy เอง

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Contracts\Alignment;
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Layer Examples (OCG)');
$doc->addPage();
// Layer 1 — background, visible by default.
$doc->startLayer('Background', visible: true);
$doc->setFillColor(230, 240, 250);
$doc->rect(10, 10, 190, 277, 'F');
$doc->endLayer();
// Layer 2 — watermark, visible by default; can be toggled off.
$doc->startLayer('Watermark', visible: true);
$doc->setFont('helvetica', 'B', 54);
$doc->setTextColor(200, 200, 200);
$doc->startTransform();
$doc->rotate(45, 105, 148);
$doc->setXY(30, 135);
$doc->cell(150, 20, 'DRAFT', align: Alignment::Center);
$doc->stopTransform();
$doc->endLayer();
// Layer 3 — main content, visible by default.
$doc->startLayer('Content', visible: true);
$doc->setTextColor(0);
$doc->setFont('helvetica', 'B', 20);
$doc->setXY(10, 15);
$doc->cell(0, 14, 'Layer Examples (OCG)', newLine: true);
$doc->ln(4);
$doc->setFont('helvetica', '', 11);
$doc->multiCell(0, 7, 'This document contains four optional content groups. '
. "Toggle them in your reader's Layers panel.");
$doc->endLayer();
// Layer 4 — debug grid, hidden by default.
$doc->startLayer('Debug Grid', visible: false);
$doc->setDrawColor(180, 180, 180);
$doc->setLineWidth(0.15);
for ($x = 0.0; $x <= 210.0; $x += 10.0) {
$doc->line($x, 0, $x, 297);
}
for ($y = 0.0; $y <= 297.0; $y += 10.0) {
$doc->line(0, $y, 210, $y);
}
$doc->endLayer();
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/layers.pdf';
$doc->save($out);
echo "Created layers.pdf\n";
  • จับคู่ทุก startLayer() ด้วย endLayer() เสมอ เลเยอร์ที่ไม่ได้ปิดจะปล่อยให้มี BDC ค้างอยู่โดยไม่มี EMC และทำให้โครงสร้างเอกสารไม่ถูกต้องตามรูปแบบ ให้จับคู่การเรียกเปิดแต่ละครั้งกับการเรียกปิดที่ตรงกัน
  • เลเยอร์ที่ซ่อนไว้ไม่ได้ถูกนำออก visible: false ซ่อนเนื้อหาตามแบบแผนของโปรแกรมอ่านเท่านั้น มาร์กและข้อความใด ๆ ยังคงอยู่ในไฟล์และสามารถกู้คืนได้ นี่ไม่ใช่การปิดทับ (redaction) สำหรับข้อมูลที่อ่อนไหว อย่าวาดข้อมูลนั้น
  • การรองรับแผงเลเยอร์แตกต่างกันไป การสลับเปิดปิดต้องใช้โปรแกรมอ่านที่รองรับเนื้อหาที่เลือกได้ ไปป์ไลน์การพิมพ์และโปรแกรมดูแบบเรียบง่ายอาจแสดงเลเยอร์ที่ปิดเป็นค่าเริ่มต้นเสมอ หรือซ่อนเลเยอร์เหล่านั้นเสมอ
  • การซ้อนเลเยอร์ สามารถซ้อนเลเยอร์ได้ แต่การมองเห็นของกลุ่มภายในแต่ละกลุ่มยังคงเป็นอิสระต่อกัน อย่าถือว่าเลเยอร์ภายนอกที่ OFF จะซ่อนกลุ่มภายในที่ ON เว้นแต่คุณจะกำหนดนโยบายการเป็นสมาชิกไว้

แต่ละเลเยอร์เพิ่มดิกชันนารี OCG หนึ่งรายการและคู่ BDC/EMC หนึ่งคู่เพื่อล้อมมาร์กของเลเยอร์นั้น โอเวอร์เฮดน้อยจนแทบไม่มีนัยสำคัญ ต้นทุนแปรผันตามเนื้อหาภายในเลเยอร์ ไม่ใช่ตามจำนวนเลเยอร์ ดังนั้นจึงอยู่ในงบประมาณ 2000 ms / 64 MB ได้อย่างเหลือเฟือ

การมองเห็นเนื้อหาที่เลือกได้นั้น ขึ้นอยู่กับความร่วมมือของโปรแกรมอ่าน ไม่ใช่การควบคุมการเข้าถึง การซ่อนเลเยอร์ไม่ได้เข้ารหัสลับ ไม่ได้ปิดทับ และไม่ได้นำเนื้อหาของเลเยอร์นั้นออก ใครก็ตามสามารถเปิดเลเยอร์อีกครั้งหรือดึงไบต์ออกมาได้ อย่าใช้เลเยอร์ที่ซ่อนไว้เพื่อปกปิดข้อความที่เป็นความลับโดยเด็ดขาด แต่ให้ละเว้นเนื้อหานั้นทั้งหมดแทน สูตรนี้ไม่แยกวิเคราะห์อินพุตใด ๆ และไม่ส่งคำขอผ่านเครือข่าย

ข้อความระบุข้อกำหนดข้อรหัสอ้างอิง (reference_id)
ดิกชันนารี OCG มี Type /OCGISO 32000-2§8.11.2
ค่า Name ของ OCG เป็นป้ายชื่อที่แสดงต่อผู้ใช้และจำเป็นต้องมีISO 32000-2§8.11.2
เนื้อหาที่เลือกได้จะถูกครอบไว้ระหว่าง BDC/EMC ด้วย OC เป็นแท็กISO 32000-2§8.11.3.2
นโยบายของ OCMD คือ AllOn/AnyOn/AnyOff/AllOff (ค่าเริ่มต้นคือ AnyOn)ISO 32000-2§8.11.4.3

โปรไฟล์ความสามารถในการทำซ้ำ — เชิงโครงสร้าง ค่า /ID ในเทรลเลอร์และอะตอมวันที่จะเปลี่ยนทุกครั้งที่บันทึก harness จะตัดอะตอมเหล่านั้นออกและเปรียบเทียบโครงสร้างที่ผ่านการนอร์มัลไลซ์ด้วย qpdf สูตรนี้อธิบายว่า NextPDF สร้างโครงสร้างนั้นอย่างไร สูตรนี้ไม่ได้ยืนยันความสอดคล้องตาม ISO 32000-2 โดยทั่วไป

ไม่เกี่ยวข้อง กลุ่มเนื้อหาที่เลือกได้เป็นความสามารถของ Core และไม่ได้ถูกจำกัดด้วย Premium