Editing limitato dei paragrafi
HPDFParagraphReflow seleziona i centri dei glifi caricati dentro un rettangolo sorgente esplicito e scrive un paragrafo appena misurato dentro un rettangolo target esplicito sulla stessa pagina
Il profilo di accettazione copre Delphi Win32/Win64 e FPC/Lazarus Windows; la generazione dei font misurati usa il builder di appearance del documento esistente e il suo supporto dei font installati
Selezione, layout e preservazione
Le coordinate sono punti user-space non ruotati della pagina PDF, con asse y verso l'alto; entrambi i rettangoli devono essere finiti, avere dimensioni positive non superiori a 14400 punti e stare nel MediaBox della pagina
La selezione può estendersi su più baseline originali e più stream di contenuto di pagina; gli operandi testuali literal, esadecimali, TJ, apice singolo e apice doppio vengono riscritti ai confini dei codici carattere selezionati
Prefissi e suffissi trattenuti, advance testuali e aggiustamenti kerning numerici originali restano al loro posto; il testo sorgente viene rimosso dagli operandi reali anziché nascosto da un rettangolo di sfondo
I Form XObjects annidati usano il proprio Matrix e BBox; ogni invocazione selezionata e le sue risorse ancestrali vengono copiate privatamente, preservando le altre invocazioni e le altre pagine che condividono i Form originali
I centri dei glifi fuori dal BBox di un Form sono esclusi; i bounds parziali dei glifi sorgente rifiutano per default, e RejectPartialSourceGlyphs = False consente esplicitamente la rimozione di un intero codice carattere quando il suo centro è selezionato
Appearance sceglie il font installato, lo stile, la dimensione, il colore, il padding, l'allineamento e la policy di overflow; la larghezza target controlla il wrapping, e shrink-to-fit riporta la EffectiveFontSize reale
La geometria dei glifi generati viene interpretata in modo indipendente e controllata contro il rettangolo target; la rotazione è fissata a zero e l'opacità a uno per questo helper limitato
Un rimpiazzo vuoto elimina il testo sorgente selezionato; impostate RequireSourceText = False per inserire un paragrafo in una regione sorgente vuota
Evidenza delle collisioni
Testo non whitespace non selezionato, immagini XObject e inline, bounds dei path dipinti e rettangoli delle annotazioni vengono confrontati con i bounds dei glifi del rimpiazzo generato
Ogni collisione identifica il proprio tipo, i bounds in spazio pagina, il testo adiacente opzionale e un indice di glifo del rimpiazzo; il conteggio totale viene trattenuto anche quando la lista collisioni restituita raggiunge il proprio tetto
Punti di controllo dei path, bounds di clip Form trasformati, larghezza stroke e limiti miter producono box conservativi; uno shading con estensione di paint sconosciuta occupa conservativamente l'intero rettangolo target
Questo test geometrico può sovrastimare immagini trasparenti, aree di annotazioni non dipinte, curve, path clippati ed envelope Form ruotati; non prova una separazione pixel-perfect dell'inchiostro né ispeziona path di clipping arbitrari, compositing dei blend o outline dei font
RejectCollisions = True rifiuta i rimpiazzi sovrapposti senza mutazioni; impostandolo a false il report viene trattenuto consentendo la policy di sovrapposizione deliberata del chiamante
Preview, commit e rollback
HPDFPreviewParagraphReflow restituisce un piano sigillato di proprietà del chiamante, il layout semantico del rimpiazzo, fingerprint ed evidenza delle collisioni, poi riporta indietro gli oggetti documento generati
HPDFCommitParagraphReflow ripete l'analisi limitata e applica atomicamente il piano solo quando contenuto sorgente, bounds dei Form, geometria delle annotazioni e geometria dei font del rimpiazzo corrispondono ancora alla preview
Un piano appartiene alla stessa istanza documento viva; liberatelo quando avete finito, tenete il documento vivo per tutto il tempo e rigenerate la preview dopo aver caricato un altro documento o modificato il contenuto selezionato
THPDFParagraphReflowSession aggiunge uno stato di revisione applicata: Apply espone il documento modificato per estrazione o rendering, Commit lo pubblica, e Rollback o la distruzione ripristinano il grafo originale
Usate le sessioni in modo seriale; il documento deve sopravvivere alla sessione, e altre transazioni del grafo o chiamate di editing non devono essere intercalate mentre Pending è true
Il rollback ripristina lo stato del documento in memoria; i file esterni già salvati restano responsabilità del chiamante
Lavoro finito e comportamento in caso di fallimento
I limiti default sono 64 MiB di contenuto decodificato, 64 MiB di stream generati, 100000000 di unità di lavoro, 100000 glifi, 250000 token, 12 livelli Form, 256 invocazioni Form, 256 collisioni restituite e 100000 nodi risorsa clonati
I byte delle stringhe codificate vengono controllati prima dell'interpretazione dei glifi contro il limite di glifi residuo, così gli encoding multi-byte per carattere possono consumare conservativamente più budget del proprio conteggio di glifi visibili
I limiti decodificati e generati coprono il contenuto gestito dall'helper; la dimensione degli stream generati viene controllata prima della pubblicazione e non rappresenta un limite di memoria di picco del processo né copre tutte le allocazioni del builder dei font installati
La cancellazione è cooperativa attraverso la tokenization del contenuto e i loop dell'helper, con controlli attorno alle chiamate esistenti di generazione font; trattenete il token finché la chiamata non è completa
Sorgente mancante, input non valido, collisioni, piani stanti, contenuto non supportato, budget esauriti, cancellazione e fallimenti ordinari restituiscono false con uno stato esplicito e preservano il grafo di oggetti originale
Testo verticale o singolare selezionato, Form ciclici o irrisolti, tipi XObject dipinti non supportati e documenti con campi firma vengono rifiutati; l'editing incrementale con preservazione delle firme richiede un workflow separato
Esempio
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;
Accettazione e output salvato
I runner dedicati Delphi e FPC usano fixture PDF caricati reali per paragrafi multi-baseline, operandi parziali, Form annidati condivisi, testo Form clippato, cambi di larghezza e font, tipi di collisione, cancellazione e rollback del grafo
Salvataggi ripetuti file/file e stream/file preservano il grafo modificato; documenti caricati freschi e invariati conservano gli esatti byte sorgente, e un fallimento di scrittura iniettato sull'output può essere seguito da un retry riuscito
Tests/Fixtures/ParagraphReflow/loaded-repeat-save.pdf isola la regressione dei salvataggi senza usare l'helper dei paragrafi: caricamento, inserimento di un marker, doppio salvataggio e lettura indipendente del secondo file
Eseguite Tests/Delphi/Run-ParagraphReflowTests.ps1 -Platform Win64 oppure Tests/FPC/Run-ParagraphReflowTests.ps1 -Platform Win64, e selezionate Win32 per l'altra architettura
Il verificatore Python opzionale Tests/Fixtures/ParagraphReflow/verify_output.py usa PyMuPDF per estrarre il testo Unicode realmente salvato e renderizzare le pagine modificate; ogni runner sopprime il lancio automatico del viewer