Añada FPdfStyledEdit y suministre un IPdfRegexEngine para planificar y ejecutar reemplazos en objetos de texto nativos de primer nivel
PlanStyledPdfRegexReplacements captura un snapshot reproducible, concatena glyphs Unicode reales por orden de página y objeto y mapea coincidencias a anclajes estables; excluye espacios y saltos generados por la extracción
ExecuteStyledPdfReplacements valida SHA-256 del snapshot, identidad actual del origen, anclajes e intervalos no solapados antes de modificar un documento cargado de forma independiente
La identidad del origen usa serialización reproducible con timestamps e identificadores normalizados, no los bytes originales del fichero; el plan guarda los bytes reales del snapshot y su SHA-256
Se reutilizan fuente nativa, tamaño, color y matriz cuando es posible; los reemplazos entre objetos o páginas mantienen el estilo del primero y eliminan los caracteres consumidos de los siguientes, conservando el resto del texto y orden de páginas
FallbackFontName selecciona explícitamente una fuente PostScript estándar si no se puede reproducir el Unicode nativo; ForceFallbackFont solicita esa vía directamente
El fallback conserva orden de dibujo, matriz, modo de renderizado y atributos de relleno y trazo; objetos recortados, transparentes, marcados o tagged se rechazan en lugar de perder silenciosamente su semántica gráfica
El texto más ancho que el original puede reducirse horizontalmente si la matriz está recta y sin shear; MinHorizontalScale vale 0.5 por defecto, y los reemplazos más estrechos mantienen la matriz original
Este flujo admite reemplazos de una línea y ajuste horizontal limitado; no recorre Form XObjects anidados, no reescribe Tagged PDF ni realiza redistribución de párrafos
Se rechazan documentos firmados o cifrados y XFA; cancelación, planes obsoletos, UTF-16 inválido, fuentes no compatibles o límites agotados dejan intacto el documento del llamador
PreviewOnly devuelve el resultado reabierto independientemente en PreviewPdf sin sustituir al llamador; un commit correcto solo reemplaza el documento tras verificar extracción de glyphs y número de páginas después de guardar y reabrir
Todas las coincidencias se ensamblan en el texto final del objeto antes de modificar objetos nativos; el ajuste y escala mínima se comprueban una vez contra los límites originales, evitando que varias coincidencias acumulen reducciones excesivas
El reemplazo vacío elimina un objeto de texto consumido completamente tras todas las ediciones ancladas; varios reemplazos se ejecutan de atrás hacia delante para conservar los desplazamientos originales anteriores
Los límites predeterminados son 256 MiB de documento, 10,000 páginas, 100,000 objetos de texto, 16,777,216 unidades UTF-16 y 100,000 reemplazos; el presupuesto de exploración es 67,108,864 visitas a caracteres nativos y unidades de copia UTF-16 para planificación
Los máximos estrictos mantienen esos límites de páginas, objetos, caracteres y reemplazos, permiten 512 MiB de documento y 1,073,741,824 visitas y limitan el nombre de fuente fallback a 1,024 bytes
El informe incluye SHA-256 de origen y salida, recuentos de reemplazos, fallbacks y escalados y texto y límites originales/finales por objeto en puntos del espacio de usuario PDF; los índices de página y objeto tienen base cero respecto al origen
Un reemplazo no es un flujo de redaction de seguridad; use las API específicas para eliminar contenido sensible y datos asociados
Options := TPdfStyledEditOptions.Default; Plan := PlanStyledPdfRegexReplacements(Pdf, Pattern, Replacement, Engine, Options); Options.PreviewOnly := True; if not ExecuteStyledPdfReplacements(Pdf, Plan, Options, PreviewPdf, Report) then raise EPdfProduction.Create(Report.ErrorMessage);
type
TPdfStyledEditOptions= record
MaxDocumentBytes: Integer;
MaxPages, MaxTextObjects, MaxCharacters, MaxReplacements: Integer;
MaxTextScanWork: Int64;
MinHorizontalScale: Double;
FallbackFontName: AnsiString;
ForceFallbackFont: Boolean;
PreviewOnly: Boolean;
CancellationToken: IPdfCancellationToken;
class function Default: TPdfStyledEditOptions; static;
end;
TPdfStyledEditPlan= record
SourceSha256: string;
SourceBytes: TBytes;
Spans: TPdfStyledSpans;
Replacements: TPdfStyledReplacements;
end;
TPdfStyledObjectChange= record
PageIndex, ObjectIndex: Integer;
BeforeText, AfterText: WideString;
BeforeBounds, AfterBounds: TPdfRectangle;
HorizontalScale: Double;
FontFallback: Boolean;
end;
TPdfStyledObjectChanges= array of TPdfStyledObjectChange;
TPdfStyledEditReport= record
Succeeded, Cancelled, PreviewOnly: Boolean;
AppliedReplacementCount, FontFallbackCount, ScaledObjectCount: Integer;
SourceSha256, OutputSha256, ErrorMessage: string;
Changes: TPdfStyledObjectChanges;
end;
function PlanStyledPdfRegexReplacements(Pdf: TPdf;
const Pattern, Replacement: WideString; Engine: IPdfRegexEngine;
const Options: TPdfStyledEditOptions): TPdfStyledEditPlan;
function ExecuteStyledPdfReplacements(Pdf: TPdf;
const Plan: TPdfStyledEditPlan; const Options: TPdfStyledEditOptions;
out PreviewPdf: TBytes; out Report: TPdfStyledEditReport): Boolean;