Edição de parágrafos com limites

HPDFParagraphReflow seleciona centros de glyphs carregados dentro de um retângulo explícito de origem e grava um parágrafo recém-medido dentro de um retângulo explícito de alvo na mesma página

O perfil de aceitação cobre Delphi Win32/Win64 e FPC/Lazarus do Windows; a geração de fontes medidas usa o builder existente de aparências de documentos e o suporte dele a fontes instaladas

Seleção, layout e preservação

As coordenadas são pontos não rotacionados do user space de páginas PDF, com eixo y para cima; ambos os retângulos precisam ser finitos, ter dimensões positivas de no máximo 14400 pontos e caber no MediaBox da página

A seleção pode atravessar múltiplas baselines originais e múltiplos streams de conteúdo de páginas; operands de texto literal, hexadecimal, TJ, aspas simples e aspas duplas são regravados nas fronteiras selecionadas de códigos de caracteres

Prefixos e sufixos retidos, advances de texto e ajustes originais numéricos de kerning permanecem no lugar; o texto de origem é removido dos operands reais, em vez de ser escondido por um retângulo de fundo

Form XObjects aninhadas usam o Matrix e o BBox delas; cada invocação selecionada e os recursos ancestrais dela são copiados privadamente, preservando outras invocações e outras páginas que compartilham as Forms originais

Centros de glyphs fora do BBox de uma Form são excluídos; limites parciais de glyphs da origem são rejeitados por default, e RejectPartialSourceGlyphs = False permite explicitamente a remoção de um código de caractere inteiro quando o centro dele está selecionado

Appearance escolhe a fonte instalada, estilo, tamanho, cor, padding, alinhamento e política de overflow; a largura do alvo controla o wrapping, e shrink-to-fit reporta o EffectiveFontSize real

A geometria gerada de glyphs é interpretada de forma independente e checada contra o retângulo alvo; a rotação é fixa em zero e a opacidade em um para este helper delimitado

Uma substituição vazia exclui o texto de origem selecionado; defina RequireSourceText = False para inserir um parágrafo numa região de origem vazia

Evidências de colisões

Texto não selecionado que não é whitespace, imagens XObject e inline, limites de paths pintados e retângulos de anotações são comparados com os limites gerados de glyphs de substituição

Cada colisão identifica o tipo dela, os limites em page space, o texto vizinho opcional e um índice de glyph de substituição; a contagem total é retida mesmo quando a lista retornada de colisões atinge o teto dela

Control points de paths, clip bounds transformados de Forms, largura de strokes e limites de miter produzem caixas conservadoras; shading com extensão de pintura desconhecida ocupa conservadoramente o retângulo alvo inteiro

Este teste geométrico pode reportar em excesso imagens transparentes, áreas de anotações não pintadas, curvas, paths clipados e envelopes rotacionados de Forms; ele não prova separação de tinta pixel-perfect nem inspeciona clipping paths arbitrários, composição de blend nem contornos de fontes

RejectCollisions = True rejeita substituições sobrepostas sem mutação; defini-lo como false retém o relatório permitindo a política deliberada de sobreposição do chamador

Preview, commit e rollback

HPDFPreviewParagraphReflow retorna um plan selado de posse do chamador, layout semântico de substituição, fingerprints e evidências de colisões, e depois reverte os objetos gerados do documento

HPDFCommitParagraphReflow repete a análise delimitada e aplica atomicamente o plan somente quando o conteúdo da origem, os bounds das Forms, a geometria das anotações e a geometria da fonte de substituição ainda correspondem ao preview

Um plan pertence à mesma instância viva de documento; libere-o ao terminar, mantenha o documento vivo durante todo o processo, e regenere o preview depois de carregar outro documento ou alterar o conteúdo selecionado

THPDFParagraphReflowSession adiciona um estado aplicado de revisão: Apply expõe o documento editado para extração ou rendering, Commit o publica, e Rollback ou a destruição restaura o grafo original

Use sessões serialmente; o documento precisa sobreviver à sessão, e outras transações de grafo ou chamadas de edição não podem ser intercaladas enquanto Pending for true

Rollback restaura o estado em memória do documento; arquivos externos já salvos permanecem responsabilidade do chamador

Trabalho finito e comportamento de falhas

Os limites default são 64 MiB de conteúdo decodificado, 64 MiB de streams gerados, 100000000 unidades de trabalho, 100000 glyphs, 250000 tokens, 12 levels de Forms, 256 invocações de Forms, 256 colisões retornadas e 100000 nós clonados de recursos

Os bytes de strings codificadas são checados antes da interpretação de glyphs contra o limite restante de glyphs, de modo que encodings de caracteres multibyte podem consumir conservadoramente mais orçamento do que a contagem visível de glyphs deles

Os limites decodificados e gerados cobrem o conteúdo tratado pelo helper; o tamanho do stream gerado é checado antes da publicação, e não representa um limite de memória de pico do processo nem limita todas as alocações do builder de fontes instaladas

O cancelamento é cooperativo através da tokenização de conteúdo e dos loops do helper, com checagens em torno das chamadas existentes de geração de fontes; retenha o token até a chamada completar

Origem ausente, entrada inválida, colisões, plans velhos, conteúdo não suportado, orçamentos esgotados, cancelamento e falhas comuns retornam false com um status explícito e preservam o grafo original de objetos

Texto vertical ou singular selecionado, Forms cíclicas ou não resolvidas, tipos não suportados de XObjects pintados e documentos com campos de assinaturas são rejeitados; edição incremental que preserva assinaturas exige um workflow separado

Exemplo

Options := HPDFDefaultParagraphReflowOptions;
Options.Appearance.FontName := 'Arial';
Options.Appearance.FontSize := 11;
Source.Left := 55; Source.Bottom := 659;
Source.Right := 350; Source.Top := 714;
Target := Source;
Plan := nil;
try
  if HPDFPreviewParagraphReflow(Document, 0, Source, Target,
    'The Supplier must deliver signed monthly reports.', Options,
    Plan, Report, CancellationToken) then
    if HPDFCommitParagraphReflow(Document, Plan, Report, CancellationToken) then
      Document.SaveLoadedDocument('reviewed-contract.pdf');
finally
  Plan.Free;
end;

Aceitação e saída salva

Os runners dedicados de Delphi e FPC usam fixtures reais de PDFs carregados para parágrafos multibaseline, operands parciais, Forms aninhadas compartilhadas, texto de Forms clipado, mudanças de largura e fonte, tipos de colisões, cancelamento e rollback de grafos

Saves repetidos arquivo/arquivo e stream/arquivo preservam o grafo editado; documentos carregados novos e inalterados mantêm os bytes exatos da origem deles, e uma falha injetada de gravação de saída pode ser seguida de um retry bem-sucedido

Tests/Fixtures/ParagraphReflow/loaded-repeat-save.pdf isola a regressão de saves sem usar o helper de parágrafos: carregue, insira um marcador, salve duas vezes, e leia de forma independente o segundo arquivo

Execute Tests/Delphi/Run-ParagraphReflowTests.ps1 -Platform Win64 ou Tests/FPC/Run-ParagraphReflowTests.ps1 -Platform Win64, e selecione Win32 para a outra arquitetura

O verifier Python opcional Tests/Fixtures/ParagraphReflow/verify_output.py usa PyMuPDF para extrair o texto Unicode realmente salvo e renderizar páginas editadas; todo runner suprime a chamada automática de viewers

Tópicos relacionados

Edição de parágrafos com limites · Opções · Relatório