Content: โมเดลเนื้อหาแบบข้อความและแบบมีโครงสร้าง
ภาพรวมโดยสังเขป
หัวข้อที่มีชื่อว่า “ภาพรวมโดยสังเขป”โมดูล Content สร้างโอเปอเรเตอร์แสดงข้อความ โอเปอเรเตอร์สถานะข้อความ เงาข้อความ JavaScript ระดับเอกสาร และดิกชันนารีคุณสมบัติของ marked-content โมดูลนี้ทำงานอยู่ระหว่างเลเยอร์ layout กับ content stream
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”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 จะถูกส่งผ่านโดยไม่แรสเตอร์ไรซ์และไม่ถอดรหัส
พื้นผิว API
หัวข้อที่มีชื่อว่า “พื้นผิว API”| คลาส | เมธอดสำคัญ | บทบาท |
|---|---|---|
TextRenderer | buildTextShowOperator(), 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 สำหรับรอบการวาดที่ออฟเซ็ต |
JavaScriptManager | includeJs(), addJsObject(), hasJavaScript(), writeJavaScript(), writeOpenAction() | การเชื่อม JavaScript ระดับเอกสารเข้ากับแคตาล็อก |
PropertiesRegistry | register(), getTagIndex(), registerOcg(), registerOcgs(), getAll(), writeProperties() | ที่จัดเก็บคุณสมบัติ marked-content และ OCG |
JBig2Loader | load(), loadFromString(), parseSegments() | ตัวถอดรหัสแบบส่งผ่าน JBIG2 |
JpxLoader | load(), 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/ ของโปรเจกต์