Edición acotada de párrafos

HPDFParagraphReflow selecciona los centros de glifos cargados dentro de un rectángulo de origen 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, disposición y preservación

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

La selección puede abarcar varias baselines originales y varios streams de contenido de página; los operandos de texto literal, hexadecimal, TJ, comilla simple y comilla doble se reescriben en los bordes de los códigos de carácter seleccionados

Los prefijos y sufijos retenidos, los avances de texto y los ajustes de kerning numéricos originales permanecen en su sitio; el texto de origen 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 las otras páginas que comparten los Forms originales

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

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

La geometría de glifos generada se interpreta de forma independiente y se comprueba 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 de origen seleccionado; usa RequireSourceText = False para insertar un párrafo en una región de origen vacía

Evidencia de colisiones

El texto no seleccionado que no es espacio en blanco, las imágenes XObject e inline, los bounds de trazados 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 total se conserva incluso cuando la lista de colisiones devuelta alcanza su tope

Los puntos de control de trazados, los bounds de clip de Forms transformados, la anchura de trazo y los límites de miter producen cajas conservadoras; un shading con extensión de pintado desconocida ocupa de forma conservadora todo el rectángulo objetivo

Esta prueba geométrica puede sobrerreportar imágenes transparentes, áreas de anotaciones sin pintar, curvas, trazados con clip y envolventes de Forms rotados; no prueba una separación de tinta píxel-perfecta ni inspecciona clipping paths arbitrarios, composición de blending ni contornos de fuentes

RejectCollisions = True rechaza los reemplazos que se solapan sin mutar nada; ponerlo en false conserva el informe permitiendo la política de solapamiento deliberada del llamador

Preview, commit y rollback

HPDFPreviewParagraphReflow devuelve un plan sellado propio del llamador, la disposición semántica de reemplazo, fingerprints y evidencia de colisiones, y después hace rollback de los objetos de documento generados

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

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

THPDFParagraphReflowSession añade 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 grafo original

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

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

Trabajo finito y comportamiento ante fallos

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 las cadenas codificadas se comprueban antes de interpretar los glifos contra el límite de glifos restante, de modo que las codificaciones multibyte pueden consumir presupuesto de forma conservadora por encima de su número de glifos visibles

Los límites decodificados y generados cubren el contenido que maneja el helper; el tamaño del stream generado se comprueba antes de publicar 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 del contenido y de los bucles del helper, con comprobaciones alrededor de las llamadas existentes de generación de fuentes; retén el token hasta que la llamada termine

Origen ausente, entrada inválida, colisiones, planes obsoletos, contenido no soportado, presupuestos agotados, cancelación y fallos ordinarios devuelven false con un estado explícito y preservan el grafo de objetos original

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

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 reales de PDF cargado para párrafos multibaseline, operandos parciales, Forms anidados compartidos, texto de Form con clip, cambios de anchura y de fuente, clases de colisiones, cancelación y rollback del grafo

Los guardados repetidos file/file y stream/file preservan el grafo editado; los documentos cargados nuevos e intactos conservan sus bytes de origen exactos, y tras un fallo de escritura de salida inyectado puede seguir un reintento con éxito

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 de forma independiente el segundo fichero

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 Python opcional Tests/Fixtures/ParagraphReflow/verify_output.py usa PyMuPDF para extraer el texto Unicode realmente guardado y renderizar las páginas editadas; todos los runners suprimen el arranque automático del visor

Temas relacionados

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