Edición acotada de párrafos

HPDFParagraphReflow selecciona los centros de glifos cargados dentro de un rectángulo fuente explícito y escribe un párrafo recién medido dentro de un rectángulo objetivo explícito en la misma página

El perfil de aceptación cubre Delphi Win32/Win64 y Windows FPC/Lazarus; la generación de fuentes medidas usa el builder de apariencias existente del documento y su soporte de fuentes instaladas

Selección, layout y preservación

Las coordenadas son puntos de user space de página PDF sin rotar, con eje y hacia arriba; ambos rectángulos deben ser finitos, tener dimensiones positivas de 14400 puntos como máximo y caber en el MediaBox de la página

La selección puede abarcar múltiples líneas base originales y múltiples content streams de página; los operandos de texto literal, hexadecimal, TJ, comilla simple y comilla doble se reescriben en los límites de código de carácter seleccionados

Los prefijos y sufijos retenidos, los advances de texto y los ajustes originales de kerning numérico permanecen en su lugar; el texto fuente se elimina de los operandos reales en lugar de ocultarse con un rectángulo de fondo

Los Form XObjects anidados usan su Matrix y BBox; cada invocación seleccionada y sus recursos ancestro se copian en privado, preservando las demás invocaciones y páginas que comparten los Forms originales

Los centros de glifos fuera del BBox de un Form se excluyen; los bounds parciales de glifos fuente rechazan por defecto, y RejectPartialSourceGlyphs = False permite explícitamente eliminar un código de carácter completo cuando su centro está seleccionado

Appearance elige la fuente instalada, estilo, tamaño, color, padding, alineación y política de overflow; el ancho objetivo controla el ajuste de línea, y shrink-to-fit reporta el EffectiveFontSize real

La geometría de glifos generada se interpreta y comprueba de forma independiente contra el rectángulo objetivo; la rotación queda fija en cero y la opacidad en uno para este helper acotado

Un reemplazo vacío elimina el texto fuente seleccionado; usa RequireSourceText = False para insertar un párrafo en una región fuente vacía

Evidencia de colisiones

El texto no seleccionado que no es whitespace, las imágenes XObject e inline, los bounds de paths pintados y los rectángulos de anotaciones se comparan con los bounds de los glifos de reemplazo generados

Cada colisión identifica su tipo, los bounds en espacio de página, el texto vecino opcional y un índice de glifo de reemplazo; el conteo total se retiene incluso cuando la lista de colisiones devuelta alcanza su tope

Los puntos de control de paths, los bounds de clip de Forms transformados, el ancho de trazo y los límites de miter producen boxes conservadores; el shading con extensión de pintura desconocida ocupa conservadoramente todo el rectángulo objetivo

Esta prueba de geometría puede sobreportar imágenes transparentes, áreas de anotaciones sin pintar, curvas, paths recortados y envelopes de Forms rotados; no prueba separación de tinta píxel a píxel ni inspecciona clipping paths arbitrarios, composición de blends ni outlines de fuentes

RejectCollisions = True rechaza los reemplazos que se solapan sin mutar; ponerlo en false conserva el reporte mientras permite la política deliberada de solapamiento del caller

Preview, commit y rollback

HPDFPreviewParagraphReflow devuelve un plan sellado propio del caller, el layout semántico de reemplazo, fingerprints y evidencia de colisiones, y luego hace rollback de los objetos de documento generados

HPDFCommitParagraphReflow repite el análisis acotado y aplica el plan atómicamente solo cuando el contenido fuente, los bounds de Forms, la geometría de anotaciones y la geometría de fuentes de reemplazo siguen coincidiendo con el preview

Un plan pertenece a la misma instancia viva de documento; libéralo al terminar, mantén vivo el documento durante todo el proceso y regenera el preview después de cargar otro documento o de cambiar el contenido seleccionado

THPDFParagraphReflowSession agrega un estado de revisión aplicada: Apply expone el documento editado para extracción o rendering, Commit lo publica y Rollback o la destrucción restauran el graph original

Usa las sesiones en serie; el documento debe sobrevivir a la sesión, y otras transacciones de graph o llamadas de edición no deben intercalarse mientras Pending sea true

El rollback restaura el estado en memoria del documento; los archivos externos ya guardados siguen siendo responsabilidad del caller

Trabajo finito y comportamiento de fallo

Los límites por defecto son 64 MiB de contenido decodificado, 64 MiB de streams generados, 100000000 unidades de trabajo, 100000 glifos, 250000 tokens, 12 niveles de Form, 256 invocaciones de Form, 256 colisiones devueltas y 100000 nodos de recursos clonados

Los bytes de cadenas codificadas se comprueban antes de interpretar glifos contra el límite de glifos restante, de modo que las codificaciones multibyte pueden consumir conservadoramente más presupuesto que su conteo visible de glifos

Los límites decodificados y generados cubren el contenido manejado por el helper; el tamaño del stream generado se comprueba antes de la publicación y no representa un límite de memoria pico del proceso ni acota todas las asignaciones del builder de fuentes instaladas

La cancelación es cooperativa a través de la tokenización de contenido y los loops del helper, con comprobaciones alrededor de las llamadas existentes de generación de fuentes; retén el token hasta que la llamada complete

Fuente ausente, entrada inválida, colisiones, planes obsoletos, contenido no soportado, presupuestos agotados, cancelación y fallos ordinarios devuelven false con un status explícito y preservan el object graph original

El texto vertical o singular seleccionado, los Forms cíclicos o no resueltos, los tipos de XObject pintados no soportados y los documentos con campos de firma se rechazan; la edición incremental que preserva firmas exige un workflow separado

Ejemplo

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;

Aceptación y salida guardada

Los runners dedicados de Delphi y FPC usan fixtures PDF cargados reales para párrafos multilínea, operandos parciales, Forms anidados compartidos, texto de Forms recortado, cambios de ancho y fuente, tipos de colisiones, cancelación y rollback de graph

Los guardados repetidos file/file y stream/file preservan el graph editado; los documentos cargados nuevos y sin cambios conservan sus bytes fuente exactos, y un fallo inyectado de escritura de salida puede ir seguido de un reintento exitoso

Tests/Fixtures/ParagraphReflow/loaded-repeat-save.pdf aísla la regresión de guardado sin usar el helper de párrafos: carga, inserta un marcador, guarda dos veces y lee independientemente el segundo archivo

Ejecuta Tests/Delphi/Run-ParagraphReflowTests.ps1 -Platform Win64 o Tests/FPC/Run-ParagraphReflowTests.ps1 -Platform Win64, y selecciona Win32 para la otra arquitectura

El verificador opcional de Python Tests/Fixtures/ParagraphReflow/verify_output.py usa PyMuPDF para extraer el texto Unicode realmente guardado y renderizar las páginas editadas; cada runner suprime el lanzamiento automático del visor

Temas relacionados

Edición acotada de párrafos · Opciones · Reporte