Pro edição
Flow Layout — Referência Profunda
Visão geral
Seção intitulada “Visão geral”Esta página é a referência profunda do módulo Pro Flow Layout. Ela cobre o motor de posicionamento, o modelo de elementos, as estratégias de quebra de página, seus contratos de comportamento e seus modos de falha. O StreamingLayoutEngine percorre uma lista de valores FlowElement em ordem. Ele atribui a cada um um índice de página baseado em zero e uma posição dentro de uma LayoutRegion. O resultado é um LayoutResult de registros PlacedElement imutáveis. O módulo calcula apenas o posicionamento; ele não renderiza nada e não realiza nenhuma I/O.
Disponibilidade e licenciamento
Seção intitulada “Disponibilidade e licenciamento”Este recurso é distribuído no NextPDF Pro (nextpdf/pro) e é ativado com um envelope de licença de nível Pro. Uma implantação sem essa habilitação não carrega as classes do recurso. Compare as edições e obtenha uma licença.
Não existe sinalizador de licença por recurso. Este é um recurso da edição Pro.
Superfície da API pública
Seção intitulada “Superfície da API pública”Todos os símbolos vivem no namespace NextPDF\Pro\FlowLayout. Todos os value objects são final e imutáveis.
| Símbolo | Parâmetros | Comportamento padrão | Retorna | Lança ou falha com | Notas |
|---|---|---|---|---|---|
StreamingLayoutEngine::__construct | LayoutRegion $region, PageBreakStrategy $strategy = PageBreakStrategy::Greedy | Vincula uma área de conteúdo por página a uma estratégia de quebra | StreamingLayoutEngine | — | A estratégia tem padrão Greedy. |
StreamingLayoutEngine::layout | list<FlowElement> $elements | Passagem única para frente; posicionamento sequencial com quebras de página guiadas pela estratégia | LayoutResult | Nunca lança | Uma lista vazia produz uma página vazia. |
StreamingLayoutEngine::withStrategy | PageBreakStrategy $strategy | Deriva um novo motor com a mesma região | self | — | O receptor permanece inalterado. |
StreamingLayoutEngine::withRegion | LayoutRegion $region | Deriva um novo motor com a mesma estratégia | self | — | O receptor permanece inalterado. |
FlowElement::__construct | FlowElementType $type, string $content, float $widthPt = 0, float $heightPt = 0, float $marginTopPt = 0, float $marginBottomPt = 0, bool $keepWithNext = false | Value object de elemento imutável | FlowElement | — | Único caminho de construção para elementos Table. |
FlowElement::text | string $content, float $height | Elemento de texto com altura medida pelo chamador | self (estático) | — | Largura 0 resolve para a largura da região no posicionamento. |
FlowElement::image | string $path, float $width, float $height | Elemento de imagem; content carrega o caminho | self (estático) | — | O motor nunca abre o arquivo. |
FlowElement::spacer | float $height | Espaço em branco vertical com conteúdo vazio | self (estático) | — | — |
FlowElement::pageBreak | — | Marcador de quebra explícita | self (estático) | — | Não emite nenhum PlacedElement. |
FlowElement::totalHeight | — | Altura mais as margens superior e inferior | float | — | Todas as verificações de encaixe usam este valor. |
FlowElementType | casos de enum Text, Image, Table, Spacer, PageBreak | Baseado em string: text, image, table, spacer, page_break | — | — | — |
FlowElementType::isBreakable | — | Text e Table retornam true; os outros retornam false | bool | — | Apenas classificação; veja o contrato de posicionamento atômico abaixo. |
LayoutRegion::__construct | float $x, float $y, float $width, float $height | Caixa de conteúdo com origem no canto superior esquerdo, medida em pontos | LayoutRegion | — | Sem validação; os valores são tomados como fornecidos. |
LayoutRegion::contains | float $px, float $py | Teste de ponto-na-região com fronteira inclusiva | bool | — | — |
LayoutRegion::remainingHeight | float $currentY | Altura da região menos o deslocamento vertical consumido | float | — | Zero ou negativo depois que o cursor transbordou. |
LayoutResult::__construct | list<PlacedElement> $placements, int $pageCount, float $totalHeightPt | Resultado de layout imutável | LayoutResult | — | — |
LayoutResult::placementsOnPage | int $pageIndex | Filtra posicionamentos por índice de página baseado em zero | list<PlacedElement> | — | A lista retornada é reindexada. |
LayoutResult::isEmpty | — | True quando nenhum elemento foi posicionado | bool | — | True para entrada vazia e apenas com quebras. |
PageBreakStrategy | casos de enum Greedy, AvoidOrphans, KeepTogether | Baseado em string: greedy, avoid_orphans, keep_together | — | — | — |
PageBreakStrategy::label | — | Rótulo legível da estratégia | string | — | — |
PlacedElement::__construct | FlowElement $element, int $pageIndex, float $x, float $y, float $width, float $height | Registro de posicionamento imutável | PlacedElement | — | Coordenadas em pontos, origem no canto superior esquerdo. |
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(): selfContrato de comportamento
Seção intitulada “Contrato de comportamento”O StreamingLayoutEngine::layout() realiza uma passagem única para frente sobre a lista de entrada. Para cada elemento ele verifica o encaixe, quebra a página quando necessário e então registra um PlacedElement. Uma lista de entrada vazia retorna um LayoutResult sem posicionamentos, com contagem de páginas igual a 1 e altura total igual a 0.
A geometria de posicionamento é determinística:
xé a borda esquerda da região.yé a posição atual do cursor mais a margem superior do elemento.widthé owidthPtdo elemento quando positivo, caso contrário a largura da região.heighté oheightPtdo elemento, exatamente como fornecido.
Após cada posicionamento o cursor avança em totalHeight(), margens incluídas. O mesmo valor acumula em LayoutResult::totalHeightPt.
Regras de quebra de página, em ordem de avaliação:
- Um elemento
PageBreakexplícito incrementa o índice de página e reinicia o cursor no topo da região. Ele não emite posicionamento e não adiciona nada à altura total. - Quando o
totalHeight()de um elemento excede a altura restante, o motor quebra — a menos que o cursor já esteja no topo da página. Greedynão adiciona nenhuma condição adicional: elementos que cabem são sempre posicionados.AvoidOrphansquebra antes de um elemento que cabe quando o espaço restante após o posicionamento seria positivo, porém abaixo da metade da altura requerida pelo próprio elemento. A própria altura do elemento é a unidade de referência, com um divisor fixo de dois; nenhuma métrica de fonte está envolvida. Ele nunca quebra no topo de uma página.KeepTogetherquebra antes de um elemento que cabe quando seu sinalizadorkeepWithNextestá definido, existe um próximo elemento, o cursor não está no topo da página e ototalHeight()combinado de ambos os elementos excede o espaço restante. O sinalizador no elemento final não tem efeito.
Posicionamento atômico: o motor posiciona cada elemento como uma unidade. Ele nunca divide o conteúdo de um elemento entre páginas. O FlowElementType::isBreakable() classifica quais tipos um chamador pode pré-dividir em elementos menores; o próprio motor não o consulta.
Ausência de estado e determinismo: o motor mantém apenas sua região e sua estratégia. layout() não compartilha estado entre chamadas, e entradas idênticas produzem resultados idênticos. withStrategy() e withRegion() retornam novos motores e nunca mutam o receptor.
Casos extremos e modos de falha
Seção intitulada “Casos extremos e modos de falha”- Nenhum método deste módulo lança. Não há hierarquia de exceções a capturar.
- Os construtores não validam nada. Dimensões de região negativas ou zero, alturas de elemento negativas e margens negativas são aceitas e fluem pela aritmética inalteradas.
- Um elemento mais alto que a região ainda é posicionado. No topo de uma página ele é posicionado ali e transborda; em qualquer outro lugar o motor quebra primeiro e ele transborda uma página nova. O próximo elemento então sempre dispara uma quebra, de modo que o transbordamento fica confinado a uma página.
- Um
PageBreakinicial posiciona o primeiro elemento de conteúdo no índice de página 1, dando uma contagem de páginas de pelo menos 2. - Elementos
PageBreakconsecutivos cada um avança o contador de páginas, produzindo páginas em branco. Um ao final deixa uma página vazia final empageCount. - O keep-together vale somente quando ambos os elementos emparelhados cabem juntos em uma página. Um par cuja altura combinada excede uma página inteira ainda se divide.
- Um
widthPtnão positivo resolve para a largura da região; a verificação de substituição é estritamente maior que zero. remainingHeight()pode retornar zero ou um valor negativo depois que o cursor transbordou.contains()trata a fronteira da região como interna.placementsOnPage()com um índice fora do intervalo retorna uma lista vazia.- Este módulo não realiza operações criptográficas e não define nenhum comportamento específico de FIPS.
Conformidade
Seção intitulada “Conformidade”O Flow Layout implementa o comportamento de posicionamento definido pelo NextPDF. Ele não tem como alvo nenhum padrão externo de layout ou tipografia, portanto esta página não carrega tabela de citação normativa. As estratégias de quebra de página são semânticas do NextPDF; elas não são implementações de propriedades de fragmentação do CSS nem de qualquer modelo keep do XSL-FO. Todas as dimensões são expressas em pontos, correspondendo às unidades que o writer do Core consome.
Estas afirmações descrevem apenas o recurso. O NextPDF não possui nenhuma certificação de conformidade, e nenhuma alegação de certificação é feita ou implícita.
Notas de desenvolvimento
Seção intitulada “Notas de desenvolvimento”- Meça o conteúdo a montante. O motor consome alturas fornecidas pelo chamador; ele não tem métricas de fonte e não realiza medição de texto.
- Pré-divida conteúdo longo de texto ou tabela em múltiplos elementos antes do layout. Use
isBreakable()para decidir quais tipos um chunker pode dividir. - Reutilize um motor por geometria de página. Derive variantes de forma barata com
withStrategy()ewithRegion(). - Agrupe a saída por página com
placementsOnPage()ao renderizar página a página. - O layout é uma passagem única, linear na contagem de elementos, e não retém árvore de documento. Os resultados são determinísticos, o que se adequa a testes de golden-file.
- Para renderização de HTML para PDF, use o pipeline HTML do Core em vez disso; este módulo não é um motor de HTML ou CSS.
Limite de publicação
Seção intitulada “Limite de publicação”Esta página documenta somente o comportamento observável externamente e a superfície da API pública suportada. Caminhos de namespace internos, classes auxiliares, tabelas de mecanismos, nomes de arquivos de runbook e prefixos de tickets estão fora de escopo.