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

Content: โมเดลเนื้อหาแบบข้อความและแบบมีโครงสร้าง

โมดูล Content สร้างโอเปอเรเตอร์แสดงข้อความ โอเปอเรเตอร์สถานะข้อความ เงาข้อความ JavaScript ระดับเอกสาร และดิกชันนารีคุณสมบัติของ marked-content โมดูลนี้ทำงานอยู่ระหว่างเลเยอร์ layout กับ content stream

Terminal window
composer require nextpdf/core:^3

Content จัดเตรียมพรีมิทีฟสำหรับเปลี่ยนข้อความที่แปลงค่าแล้วให้เป็นโอเปอเรเตอร์ของ Portable Document Format (PDF) TextRenderer คือคอมโพเนนต์หลัก ซึ่งสร้างโอเปอเรเตอร์แสดงข้อความของสตริงและโอเปอเรเตอร์สถานะข้อความที่นำหน้าโอเปอเรเตอร์นั้น ตาม International Organization for Standardization (ISO) 32000-2 §9 โอเปอเรเตอร์ Tj จะวาดกลิฟของสตริงด้วยฟอนต์ปัจจุบันและพารามิเตอร์กราฟิกที่เกี่ยวข้องกับข้อความ TextRenderer จะเลือกใช้โอเปอเรเตอร์แสดงผลแบบเดี่ยวหรืออาเรย์ TJ แบบกำหนดตำแหน่งตาม TypographyMode ที่ใช้งานอยู่ และจะปรับค่า kerning เมื่อโหมดนั้นใช้อาเรย์ TJ

สถานะข้อความถูกจำลองไว้อย่างครบชุด setTextRenderingMode() รับ enum TextRenderingMode เคสทั้งแปดของ enum นี้สอดคล้องแบบหนึ่งต่อหนึ่งกับโหมดการเรนเดอร์ข้อความของ ISO 32000-2 ได้แก่ fill, stroke, fill-then-stroke, invisible และตัวแปร clip อีกสี่แบบ (Table 104) นอกจากนี้ renderer ยังควบคุมความกว้างของ stroke ระยะห่างระหว่างอักขระ ระยะห่างระหว่างคำ การยืดในแนวนอน การยกข้อความ ทิศทางจากขวาไปซ้าย และ Hyphenator ที่เป็นทางเลือกได้ด้วย การเรียก buildTextStateOperators() จะปล่อยสถานะที่สะสมไว้เป็นบล็อกโอเปอเรเตอร์เดียว

TextShadow เป็น value object ที่ประกอบด้วยสี ออฟเซ็ต X และ Y ในหน่วยผู้ใช้ และค่าความทึบ renderer ใช้ออบเจ็กต์นี้เพื่อปล่อยรอบการวาดครั้งที่สองที่ตำแหน่งออฟเซ็ต ค่าออฟเซ็ตเริ่มต้นเป็นค่าเบา ๆ ที่ 0.5/−0.5 พร้อมความทึบ 0.5 คล้ายเงานุ่มใน Cascading Style Sheets (CSS)

JavaScriptManager รับผิดชอบการเขียนสคริปต์ระดับเอกสาร includeJs() ลงทะเบียนสคริปต์ของเอกสาร addJsObject() ลงทะเบียนอ็อบเจ็กต์สคริปต์แบบมีชื่อ ส่วน writeJavaScript() / writeOpenAction() จะซีเรียลไลซ์สคริปต์ลงในแคตาล็อกและ OpenAction ตัวจัดการนี้ตรวจสอบความถูกต้องและเข้ารหัสเนื้อสคริปต์ทุกชุดเป็น PDF string ก่อนปล่อยออก

PropertiesRegistry คือที่จัดเก็บคุณสมบัติของ marked-content register() คืนค่าดัชนีแท็กที่เสถียรสำหรับดิกชันนารีคุณสมบัติ registerOcg() / registerOcgs() ผูก optional-content groups (OCGs) ด้วยหมายเลขอ็อบเจ็กต์ ส่วน writeProperties() จะซีเรียลไลซ์รีจิสทรีลงในดิกชันนารีทรัพยากรของหน้า โมดูล ContentStream อ่านข้อมูลนี้เมื่อเปิดลำดับ marked พร้อมรายการคุณสมบัติ

ตัวถอดรหัสภาพสองตัวอยู่ในโมดูลนี้เพราะรองรับรูปแบบ PDF-native ที่ส่งผ่านได้โดยตรง JBig2Loader และ JpxLoader แจงโครงสร้างเซกเมนต์ของ JBIG2 และ JPEG 2000 แล้วคืนค่า ImageData โดยไม่แรสเตอร์ไรซ์พิกเซล ไบต์ที่เข้ารหัสแล้วจะถูกส่งต่อไปยังโปรแกรมดูโดยไม่เปลี่ยนแปลง เมื่อแหล่งข้อมูล JBIG2 มีเซกเมนต์ globals แยกต่างหาก JBig2Loader จะฝังเซกเมนต์นั้นผ่านการอ้างอิงสตรีม /JBIG2Globals บนภาพ XObject ส่วนรูปแบบ in-stream/in-line ยังคง round-trip ได้เหมือนเดิม นี่เป็นเพียงการเชื่อมโยงเชิงโครงสร้างเท่านั้น ไบต์ของ globals จะถูกส่งผ่านโดยไม่แรสเตอร์ไรซ์และไม่ถอดรหัส

คลาสเมธอดสำคัญบทบาท
TextRendererbuildTextShowOperator(), buildTextStateOperators(), setTextRenderingMode(), setTextStrokeWidth(), setTextShadow(), setFontSpacing(), setWordSpacing(), setFontStretching(), setTextRise(), setRTL(), setHyphenation()ตัวสร้างโอเปอเรเตอร์แสดงข้อความและโอเปอเรเตอร์สถานะข้อความ
TextRenderingMode (enum)Fill, Stroke, FillStroke, Invisible, FillClip, StrokeClip, FillStrokeClip, Clipโหมดการเรนเดอร์ข้อความของ ISO 32000-2
TextShadow__construct(Color, offsetX, offsetY, opacity)value object สำหรับรอบการวาดที่ออฟเซ็ต
JavaScriptManagerincludeJs(), addJsObject(), hasJavaScript(), writeJavaScript(), writeOpenAction()การเชื่อม JavaScript ระดับเอกสารเข้ากับแคตาล็อก
PropertiesRegistryregister(), getTagIndex(), registerOcg(), registerOcgs(), getAll(), writeProperties()ที่จัดเก็บคุณสมบัติ marked-content และ OCG
JBig2Loaderload(), loadFromString(), parseSegments()ตัวถอดรหัสแบบส่งผ่าน JBIG2
JpxLoaderload(), loadFromString(), parseBoxes()ตัวถอดรหัสแบบส่งผ่าน JPEG 2000

เรียกใช้ composer docs:generate-api-php -- --module=Content เพื่อดูตาราง PHPDoc แบบเต็ม

ใช้ไฟล์ตัวอย่าง examples/28-text-rendering.php เป็นแหล่งที่มา

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Content\TextRenderer;
use NextPDF\Content\TextRenderingMode;
$renderer = new TextRenderer();
$renderer
->setTextRenderingMode(TextRenderingMode::FillStroke)
->setTextStrokeWidth(0.3)
->setWordSpacing(0.5);
$stateOps = $renderer->buildTextStateOperators();

ตัวอย่างนี้เพิ่มเงานุ่มและ hyphenator จากนั้นสร้างโอเปอเรเตอร์แสดงผลด้วยฟังก์ชัน escape ที่ผู้เรียกจัดเตรียมมา ซึ่งเป็นขอบเขต PdfStringEscaper มาตรฐานจาก architecture decision record ADR-015

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Content\TextRenderer;
use NextPDF\Content\TextShadow;
use NextPDF\Graphics\Color;
use NextPDF\Support\PdfStringEscaper;
$renderer = new TextRenderer();
$renderer
->setTextShadow(new TextShadow(Color::rgb(0, 0, 0), 0.4, -0.4, 0.45))
->setRTL(false);
$showOp = $renderer->buildTextShowOperator(
text: 'Quarterly report',
fontKey: 'F1',
metrics: $fontMetrics,
escapeSegment: static fn (string $s): string => PdfStringEscaper::escapeLiteral($s),
);
$pageContent = $renderer->buildTextStateOperators() . $showOp;
  • buildTextShowOperator() คืนค่าสตริงว่างเมื่ออินพุตว่างเปล่า อย่าปล่อย Tj ที่ว่างเปล่า ให้ป้องกันที่ต้นทางหาก layout ของคุณอาจสร้าง run ว่างได้
  • คอลแบ็ก escape เป็นสิ่งจำเป็นและรับผิดชอบความปลอดภัยของสตริง ให้ส่ง PdfStringEscaper::escapeLiteral() ที่เป็นมาตรฐานจาก ADR-015 escaper ที่ทำงานไม่ครบจะสร้างสตริงลิเทอรัลที่ผิดไวยากรณ์
  • ในจุดกำเนิดแบบมุมบนซ้าย TextShadow::offsetY ค่าลบคือทิศลง ค่า Y ที่เป็นบวกจะดันเงาขึ้นด้านบน ซึ่งมักไม่ใช่ผลลัพธ์ที่ตั้งใจ
  • JavaScriptManager ตรวจสอบความถูกต้องของอินพุตสคริปต์ เนื้อสคริปต์ที่ไม่ถูกต้องจะถูกปฏิเสธตั้งแต่ตอนลงทะเบียน ไม่ใช่ถูกทิ้งอย่างเงียบ ๆ ระหว่างการเขียน
  • JBig2Loader และ JpxLoader ไม่แรสเตอร์ไรซ์เลย ทั้งสองตัวตรวจสอบความถูกต้องและส่งผ่านไบต์ที่เข้ารหัสแล้ว เซกเมนต์ที่เสียหายจะแสดงเป็นข้อผิดพลาดในการแจง ไม่ใช่ภาพว่างเปล่า
  • PropertiesRegistry::register() เป็น idempotent ต่อหนึ่งดิกชันนารี ดิกชันนารีคุณสมบัติที่เหมือนกันจะใช้ดัชนีแท็กเดียวกันซ้ำ

การสร้างโอเปอเรเตอร์มีความซับซ้อนเป็น O(n) ตามความยาวของสตริง บวกกับรอบการทำ kerning แบบ O(n) เมื่อโหมด typography ใช้อาเรย์ TJ ส่วนนี้ไม่มีต้นทุนด้าน layout หรือ shaping งานเหล่านั้นยังอยู่ในโมดูล Typography และ Layout การซีเรียลไลซ์ JavaScript และคุณสมบัติเป็น O(entries) ตัวโหลดภาพแบบส่งผ่านใช้การแจงแบบ O(bytes) โดยไม่มีต้นทุนการถอดรหัส นี่คือข้อได้เปรียบหลักของตัวโหลดเหล่านี้สำหรับงานเอกสารสแกน performance_budget สำหรับงานอ้างอิงคือ 1500 ms ของเวลารวมและ 64 MB ของหน่วยความจำสูงสุด

JavaScriptManager ยอมรับเนื้อสคริปต์ที่อาจมาจากเทมเพลตที่ไม่น่าเชื่อถือ ตัวจัดการนี้ตรวจสอบความถูกต้องและเข้ารหัสเนื้อทุกชุดเป็น PDF string แต่ JavaScript ในเอกสารยังคงเป็นพื้นผิวของเนื้อหาแบบทำงานได้ ให้ปิดใช้งานสำหรับเอาต์พุตที่ไม่น่าเชื่อถือ หรือถอดออกด้วยเส้นทางการ sanitize ที่อธิบายไว้ใน /modules/core/security/ JBig2Loader และ JpxLoader แจงโครงสร้างเซกเมนต์ที่ไม่น่าเชื่อถือ ให้จำกัดขนาดอินพุตและเวลาในการแจง และรันการแยกข้อมูลใน worker ที่ถูกจำกัดเมื่อแหล่งข้อมูลมาจากผู้ใช้ ขอบเขตการ escape ข้อความคือคอลแบ็กที่ผู้เรียกจัดเตรียมมา ให้ส่ง escaper ที่เป็นมาตรฐานเสมอ เพื่อไม่ให้ไบต์ควบคุมหลุดออกจากสตริงลิเทอรัลได้

โมดูลนี้ปล่อยโอเปอเรเตอร์แสดงข้อความและโอเปอเรเตอร์สถานะข้อความที่สอดคล้องกับโมเดลข้อความใน ISO 32000-2 §9 ซึ่งรวมถึงความหมายของโอเปอเรเตอร์ Tj และโหมดการเรนเดอร์ใน Table 104 ที่สะท้อนโดย enum TextRenderingMode รายการเหล่านี้เป็นข้อเท็จจริงของการนำไปใช้งาน src/Content/TextRenderer.php และ enum TextRenderingMode สร้างรูปแบบของโอเปอเรเตอร์ และ tests/Unit/Content/TextRenderer*, JavaScriptManagerIsoTest และ PropertiesRegistryTest ทดสอบพฤติกรรมเหล่านี้ รายการเหล่านี้ไม่ได้ยืนยันความสอดคล้องของ PDF 2.0 แบบครบวงจร สัญญาการ escape สตริงเป็นไปตาม ADR-015 และ ISO 32000-2 §7.3.4.2 เส้นทางส่งผ่านของ JBIG2 และ JPEG 2000 รักษาสตรีมที่เข้ารหัสแล้วไว้โดยไม่เปลี่ยนแปลง เซกเมนต์ globals ของ JBIG2 ที่แยกต่างหากจะถูกฝังเป็นการอ้างอิงสตรีม /JBIG2Globals บนภาพ XObject ซึ่งได้รับการตรวจสอบในฐานะการเชื่อมโยงเชิงโครงสร้าง ไม่ใช่การอ้างความเที่ยงตรงของการถอดรหัส ความสอดคล้องระดับเอกสารได้รับการตรวจสอบโดยชุด oracle และ golden ที่อยู่ในไดเรกทอรี /modules/core/conformance/ ของโปรเจกต์