Bỏ qua để đến nội dung

Content: mô hình nội dung văn bản và nội dung có cấu trúc

Module Content dựng các toán tử hiển thị văn bản, toán tử trạng thái văn bản, bóng văn bản, JavaScript ở cấp tài liệu và từ điển thuộc tính marked-content. Module này nằm giữa bố cục và luồng nội dung.

Terminal window
composer require nextpdf/core:^3

Content cung cấp các thành phần nền tảng để biến văn bản đã phân giải thành các toán tử Portable Document Format (PDF). TextRenderer là thành phần trung tâm. Nó dựng toán tử hiển thị văn bản cho một chuỗi, cùng các toán tử trạng thái văn bản cần đặt trước chuỗi đó. Theo International Organization for Standardization (ISO) 32000-2 §9, toán tử Tj vẽ các glyph của một chuỗi bằng phông chữ hiện tại và các tham số đồ họa liên quan đến văn bản. TextRenderer chọn một toán tử hiển thị đơn lẻ hoặc một mảng TJ có định vị, tùy theo TypographyMode đang hoạt động. Nó áp dụng điều chỉnh kerning khi chế độ dùng các mảng TJ.

Trạng thái văn bản được mô hình hóa thành một tập hợp đầy đủ. setTextRenderingMode() nhận một enum TextRenderingMode. Tám trường hợp của enum này ánh xạ một-một tới các chế độ kết xuất văn bản của ISO 32000-2: tô (fill), nét (stroke), tô-rồi-nét (fill-then-stroke), ẩn (invisible) và bốn biến thể clip (Bảng 104). Renderer cũng kiểm soát độ rộng nét, khoảng cách ký tự, khoảng cách từ, độ giãn ngang, độ nâng văn bản, hướng phải-sang-trái và một Hyphenator tùy chọn. Khi gọi buildTextStateOperators(), trạng thái đã tích lũy sẽ được phát ra dưới dạng một khối toán tử duy nhất.

TextShadow là một value object gồm màu, độ lệch X và Y theo đơn vị người dùng, và độ mờ. Renderer dùng nó để phát ra lượt vẽ thứ hai tại độ lệch đó. Độ lệch mặc định 0,5/−0,5 khá nhẹ, với độ mờ 0,5, tương tự một bóng mềm trong Cascading Style Sheets (CSS).

JavaScriptManager phụ trách ghi script ở cấp tài liệu. includeJs() đăng ký một script tài liệu. addJsObject() đăng ký một đối tượng script có tên. writeJavaScript() / writeOpenAction() tuần tự hóa các script vào catalog và OpenAction. Manager xác thực và mã hóa-chuỗi-PDF toàn bộ nội dung script trước khi phát ra.

PropertiesRegistry là kho lưu thuộc tính marked-content. register() trả về một chỉ mục tag ổn định cho một từ điển thuộc tính. registerOcg() / registerOcgs() liên kết các nhóm nội dung tùy chọn (OCG) theo số đối tượng. writeProperties() tuần tự hóa registry vào từ điển tài nguyên của trang. Module ContentStream đọc dữ liệu này khi mở một chuỗi đã đánh dấu kèm danh sách thuộc tính.

Hai bộ giải mã ảnh nằm trong module này vì chúng xử lý các định dạng pass-through gốc của PDF. JBig2LoaderJpxLoader phân tích cấu trúc segment của JBIG2 và JPEG 2000, rồi trả về ImageData mà không rasterize pixel. Các byte đã mã hóa được chuyển nguyên vẹn tới trình xem. Khi một nguồn JBIG2 mang theo một segment globals riêng, JBig2Loader nhúng nó qua một tham chiếu luồng /JBIG2Globals trên image XObject; dạng in-stream/in-line vẫn round-trip như trước. Đây chỉ là kết nối cấu trúc: các byte globals được chuyển qua mà không rasterize hay giải mã.

LớpPhương thức chínhVai trò
TextRendererbuildTextShowOperator(), buildTextStateOperators(), setTextRenderingMode(), setTextStrokeWidth(), setTextShadow(), setFontSpacing(), setWordSpacing(), setFontStretching(), setTextRise(), setRTL(), setHyphenation()Bộ dựng toán tử hiển thị văn bản và trạng thái văn bản
TextRenderingMode (enum)Fill, Stroke, FillStroke, Invisible, FillClip, StrokeClip, FillStrokeClip, ClipCác chế độ kết xuất văn bản ISO 32000-2
TextShadow__construct(Color, offsetX, offsetY, opacity)Value object cho lượt vẽ có độ lệch
JavaScriptManagerincludeJs(), addJsObject(), hasJavaScript(), writeJavaScript(), writeOpenAction()Kết nối catalog JavaScript ở cấp tài liệu
PropertiesRegistryregister(), getTagIndex(), registerOcg(), registerOcgs(), getAll(), writeProperties()Kho thuộc tính marked-content + OCG
JBig2Loaderload(), loadFromString(), parseSegments()Bộ giải mã pass-through JBIG2
JpxLoaderload(), loadFromString(), parseBoxes()Bộ giải mã pass-through JPEG 2000

Chạy composer docs:generate-api-php -- --module=Content để xem bảng PHPDoc đầy đủ.

Nguồn: 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();

Phần này thêm một bóng mềm và một hyphenator, rồi dựng toán tử hiển thị bằng hàm escape do bên gọi cung cấp, với ranh giới chuẩn tắc là PdfStringEscaper từ bản ghi quyết định kiến trúc 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() trả về chuỗi rỗng khi đầu vào rỗng. Đừng phát ra một Tj rỗng; hãy chặn ở tầng trên nếu bố cục của bạn có thể tạo ra các run trống.
  • Callback escape là bắt buộc và chịu trách nhiệm về độ an toàn của chuỗi. Hãy truyền PdfStringEscaper::escapeLiteral() chuẩn tắc từ ADR-015. Một escaper không đầy đủ sẽ tạo ra một chuỗi literal sai cú pháp.
  • Trong hệ tọa độ có gốc ở góc trên trái, TextShadow::offsetY âm sẽ đi xuống. Giá trị Y dương đẩy bóng lên trên, điều hiếm khi là chủ ý.
  • JavaScriptManager xác thực đầu vào script. Nội dung script không hợp lệ bị từ chối ngay khi đăng ký, thay vì bị âm thầm bỏ qua lúc ghi.
  • JBig2LoaderJpxLoader không bao giờ rasterize. Chúng xác thực và chuyển tiếp các byte đã mã hóa. Một segment bị hỏng sẽ xuất hiện dưới dạng lỗi phân tích, không phải một ảnh trắng.
  • PropertiesRegistry::register() là idempotent cho mỗi từ điển; các từ điển thuộc tính giống hệt nhau dùng chung một chỉ mục tag.

Việc dựng toán tử là O(n) theo độ dài chuỗi, cộng thêm một lượt kerning O(n) khi chế độ typography dùng các mảng TJ. Ở đây không có chi phí bố cục hay shaping; phần việc đó nằm trong các module Typography và Layout. Tuần tự hóa JavaScript và thuộc tính là O(entries). Các bộ tải ảnh pass-through dùng phân tích O(bytes) với chi phí giải mã bằng không. Đây là ưu thế chính của chúng đối với workload tài liệu quét. performance_budget cho workload tham chiếu là 1500 ms thời gian thực và 64 MB đỉnh.

JavaScriptManager chấp nhận nội dung script có thể đến từ template không tin cậy. Nó xác thực và mã hóa-chuỗi-PDF toàn bộ nội dung, nhưng JavaScript trong tài liệu vẫn là một bề mặt nội dung động. Hãy tắt nó cho đầu ra không tin cậy, hoặc loại bỏ nó bằng đường dẫn làm sạch được mô tả trong /modules/core/security/. JBig2LoaderJpxLoader phân tích cấu trúc segment không tin cậy: hãy giới hạn kích thước đầu vào và thời gian phân tích, đồng thời chạy việc trích xuất trong một worker bị ràng buộc khi nguồn do người dùng cung cấp. Ranh giới escape văn bản chính là callback do bên gọi cung cấp. Luôn truyền escaper chuẩn tắc để các byte điều khiển không thể thoát ra khỏi một chuỗi literal.

Module phát ra các toán tử hiển thị văn bản và trạng thái văn bản nhất quán với mô hình văn bản ISO 32000-2 §9. Điều này bao gồm ngữ nghĩa của toán tử Tj và các chế độ kết xuất trong Bảng 104 được enum TextRenderingMode phản chiếu. Đây là các sự kiện về hiện thực: src/Content/TextRenderer.php và enum TextRenderingMode tạo ra các dạng toán tử, còn tests/Unit/Content/TextRenderer*, JavaScriptManagerIsoTest, và PropertiesRegistryTest kiểm thử chúng. Chúng không khẳng định tuân thủ PDF 2.0 đầu-cuối. Hợp đồng escape chuỗi tuân theo ADR-015 và ISO 32000-2 §7.3.4.2. Các đường dẫn pass-through của JBIG2 và JPEG 2000 giữ nguyên các luồng đã mã hóa không thay đổi. Một segment globals JBIG2 riêng được nhúng dưới dạng một tham chiếu luồng /JBIG2Globals trên image XObject; điều này được kiểm chứng như kết nối cấu trúc, không phải như một tuyên bố về độ trung thực giải mã. Tuân thủ ở cấp tài liệu được xác thực bởi các bộ oracle và golden trong /modules/core/conformance/.