Pro 版本
Flow Layout — 深入參考
本頁是 Pro 版 Flow Layout 模組的深入參考。內容涵蓋置放引擎、元素模型、斷頁策略,以及它們的行為合約與失效模式。StreamingLayoutEngine 會依序走訪一份 FlowElement 值的清單,為每一項指派一個從零起算的頁面索引,以及在 LayoutRegion 內的位置。其結果是一個由不可變的 PlacedElement 記錄構成的 LayoutResult。此模組僅計算置放;它不進行任何算繪,也不執行任何 I/O。
供應與授權
標題為「供應與授權」的區段此功能隨 NextPDF Pro(nextpdf/pro)提供,並以 Pro 層級的授權封套啟用。未持有該權利的部署不會載入此功能的類別。比較各版本並取得授權。
沒有任何單功能授權旗標。這是一項 Pro 版本的功能。
公開 API 介面
標題為「公開 API 介面」的區段所有符號都位於 NextPDF\Pro\FlowLayout 命名空間中。所有值物件皆為 final 且不可變。
| 符號 | 參數 | 預設行為 | 回傳 | 拋出或失敗於 | 備註 |
|---|---|---|---|---|---|
StreamingLayoutEngine::__construct | LayoutRegion $region, PageBreakStrategy $strategy = PageBreakStrategy::Greedy | 將每頁的內容區域繫結到一個斷頁策略 | StreamingLayoutEngine | — | 策略預設為 Greedy。 |
StreamingLayoutEngine::layout | list<FlowElement> $elements | 單次向前掃描;依序置放,並由策略驅動斷頁 | LayoutResult | 永不拋出 | 空清單會產生一個空白頁面。 |
StreamingLayoutEngine::withStrategy | PageBreakStrategy $strategy | 以相同的區域衍生出一個新引擎 | self | — | 接收者維持不變。 |
StreamingLayoutEngine::withRegion | LayoutRegion $region | 以相同的策略衍生出一個新引擎 | self | — | 接收者維持不變。 |
FlowElement::__construct | FlowElementType $type, string $content, float $widthPt = 0, float $heightPt = 0, float $marginTopPt = 0, float $marginBottomPt = 0, bool $keepWithNext = false | 不可變的元素值物件 | FlowElement | — | Table 元素的唯一建構途徑。 |
FlowElement::text | string $content, float $height | 帶有呼叫端量測高度的文字元素 | self(靜態) | — | 寬度為 0 時,會在置放時解析為區域寬度。 |
FlowElement::image | string $path, float $width, float $height | 影像元素;content 承載該路徑 | self(靜態) | — | 引擎絕不會開啟該檔案。 |
FlowElement::spacer | float $height | 內容為空的垂直空白 | self(靜態) | — | — |
FlowElement::pageBreak | — | 明確的斷頁標記 | self(靜態) | — | 不會產生任何 PlacedElement。 |
FlowElement::totalHeight | — | 高度加上上下邊界 | float | — | 所有容納檢查都使用此值。 |
FlowElementType | 列舉案例 Text、Image、Table、Spacer、PageBreak | 以字串為底:text、image、table、spacer、page_break | — | — | — |
FlowElementType::isBreakable | — | Text 與 Table 回傳 true;其餘回傳 false | bool | — | 僅為分類;請參閱下方的不可分割置放合約。 |
LayoutRegion::__construct | float $x, float $y, float $width, float $height | 以左上角為原點的內容框,以點為單位量測 | LayoutRegion | — | 不做任何驗證;值一律照單全收。 |
LayoutRegion::contains | float $px, float $py | 含邊界的點是否落在區域內的檢測 | bool | — | — |
LayoutRegion::remainingHeight | float $currentY | 區域高度減去已消耗的垂直位移 | float | — | 游標一旦溢出即為零或負值。 |
LayoutResult::__construct | list<PlacedElement> $placements, int $pageCount, float $totalHeightPt | 不可變的版面配置結果 | LayoutResult | — | — |
LayoutResult::placementsOnPage | int $pageIndex | 依從零起算的頁面索引篩選置放結果 | list<PlacedElement> | — | 回傳的清單會重新索引。 |
LayoutResult::isEmpty | — | 當沒有任何元素被置放時為 true | bool | — | 空輸入與僅含斷頁的輸入皆為 true。 |
PageBreakStrategy | 列舉案例 Greedy、AvoidOrphans、KeepTogether | 以字串為底:greedy、avoid_orphans、keep_together | — | — | — |
PageBreakStrategy::label | — | 人類可讀的策略標籤 | string | — | — |
PlacedElement::__construct | FlowElement $element, int $pageIndex, float $x, float $y, float $width, float $height | 不可變的置放記錄 | PlacedElement | — | 座標以點為單位,左上角為原點。 |
public function layout(array $elements): LayoutResultpublic function withStrategy(PageBreakStrategy $strategy): selfpublic function withRegion(LayoutRegion $region): selfpublic static function text(string $content, float $height): selfpublic static function image(string $path, float $width, float $height): selfpublic static function spacer(float $height): selfpublic static function pageBreak(): self行為合約
標題為「行為合約」的區段StreamingLayoutEngine::layout() 會對輸入清單執行單次向前掃描。針對每一個元素,它會檢查是否容納得下、必要時斷頁,然後記錄一個 PlacedElement。空的輸入清單會回傳一個沒有任何置放、頁數為 1、總高度為 0 的 LayoutResult。
置放的幾何是決定性的:
x是區域的左邊緣。y是目前的游標位置加上元素的上邊界。width在widthPt為正時取其值,否則取區域寬度。height是元素的heightPt,與所提供的完全一致。
每次置放後,游標會前進 totalHeight()(含邊界)。同樣的量會累加到 LayoutResult::totalHeightPt。
斷頁規則,依評估順序:
- 明確的
PageBreak元素會遞增頁面索引,並將游標重設到區域頂端。它不會產生任何置放,也不會為總高度增加任何量。 - 當某個元素的
totalHeight()超過剩餘高度時,引擎會斷頁——除非游標已經位於頁面頂端。 Greedy不附加任何額外條件:容納得下的元素一律會被置放。AvoidOrphans會在一個容納得下的元素之前斷頁,條件是置放後剩餘的空間為正、但低於該元素自身所需高度的一半。參考單位是元素自身的高度,除數固定為二;不牽涉任何字型度量。它絕不會在頁面頂端斷頁。KeepTogether會在一個容納得下的元素之前斷頁,條件是其keepWithNext旗標已設定、存在下一個元素、游標不在頁面頂端,且兩個元素合計的totalHeight()超過剩餘空間。最後一個元素上的旗標不會有任何作用。
不可分割置放:引擎會將每個元素當作一個整體來置放。它絕不會將元素內容跨頁拆分。FlowElementType::isBreakable() 用於分類呼叫端可以將哪些類型預先拆分成較小的元素;引擎本身不會參考它。
無狀態與決定性:引擎只持有它的區域與策略。layout() 在各次呼叫之間不共用任何狀態,且相同的輸入會產生相同的結果。withStrategy() 與 withRegion() 會回傳新引擎,絕不會變動接收者。
邊界案例與失效模式
標題為「邊界案例與失效模式」的區段- 此模組中沒有任何方法會拋出例外。沒有可供攔截的例外階層。
- 建構式不做任何驗證。負值或零的區域尺寸、負值的元素高度,以及負值的邊界都會被接受,並原封不動地流經運算。
- 高度超過區域的元素仍會被置放。在頁面頂端時,它會被置放於該處並溢出;在其他位置時,引擎會先斷頁,讓它溢出一個新頁面。接著的下一個元素一定會觸發斷頁,因此溢出會被侷限在單一頁面內。
- 位於開頭的
PageBreak會將第一個內容元素置放在頁面索引 1,使頁數至少為 2。 - 連續的
PageBreak元素會各自推進頁面計數器,產生空白頁面。位於結尾的一個會在pageCount中留下一個最終的空白頁面。 - keep-together 只有在成對的兩個元素能一起容納於同一頁時才成立。若某一對的合計高度超過整頁,仍會被拆開。
- 非正值的
widthPt會解析為區域寬度;此替代檢查為嚴格大於零。 remainingHeight()在游標溢出後可能回傳零或負值。contains()會將區域邊界視為在內。placementsOnPage()若給定超出範圍的索引,會回傳一個空清單。- 此模組不執行任何密碼學運算,也不定義任何 FIPS 專屬行為。
一致性
標題為「一致性」的區段Flow Layout 實作的是 NextPDF 所定義的置放行為。它並未以任何外部的版面配置或排版標準為目標,因此本頁不附帶規範性的引用表。這些斷頁策略是 NextPDF 的語意;它們並非 CSS fragmentation 屬性或任何 XSL-FO keep 模型的實作。所有尺寸皆以點表示,與 Core 寫入器所使用的單位一致。
這些陳述僅描述功能。NextPDF 並未持有任何一致性認證,亦未做出或暗示任何認證主張。
開發注意事項
標題為「開發注意事項」的區段- 在上游量測內容。引擎會消費呼叫端提供的高度;它沒有字型度量,也不執行任何文字量測。
- 在版面配置之前,先將冗長的文字或表格內容預先拆分成多個元素。使用
isBreakable()來判斷分塊器可以拆分哪些類型。 - 每一種頁面幾何重複使用單一引擎。以
withStrategy()與withRegion()廉價地衍生出各種變體。 - 逐頁算繪時,以
placementsOnPage()將輸出依頁分組。 - 版面配置是單次掃描、與元素數量呈線性,且不保留任何文件樹。結果具決定性,適合用於黃金檔案測試。
- 若要進行 HTML 轉 PDF 算繪,請改用 Core 的 HTML 管線;此模組並非 HTML 或 CSS 引擎。
出版邊界
標題為「出版邊界」的區段本頁僅記載外部可觀察的行為,以及受支援的公開 API 介面。內部命名空間路徑、輔助類別、機制表、維運手冊檔名,以及工單前綴皆不在範圍內。