Grafo de dependencias de cálculos de formulario
HotPDF construye un grafo de dependencias sobre los campos de cálculo de un AcroForm cargado, de modo que un cambio de valor recalcula solo los cálculos que lo leen transitivamente, en un orden donde cada valor recomputado ya es visible para los cálculos que lo consumen
Construcción del grafo
THotPDF.BuildLoadedFormCalculationGraph devuelve un snapshot propiedad del caller. Cada campo se convierte en un nodo; cada script Calculate registrado en /CO se analiza estáticamente con HPDFExtractSafeJavaScriptFieldReferences, que lee los nombres de campo que un script del subset seguro toca: los argumentos entre comillas de AFSimple_Calculate("OP", ["a","b"]) y los nombres entre comillas de los accesos getField("x"), saltándose los string literals para que las menciones textuales no se traten como referencias
THPDFFormCalcGraph.ResolveLinks resuelve esos nombres en aristas source → dependent y ordena los targets con un topological sort. Los campos dentro de un ciclo de dependencias conservan en cambio el orden de documento de /CO, lo que coincide con la semántica de una pasada de la recálculación completa; un campo cambiado nunca recalcula su propio script, así que los ciclos no pueden hacer ping-pong y un valor escrito por el usuario siempre gana. Los nombres de source que no coinciden con ningún campo se reportan mediante UnresolvedFieldNameCount y no producen aristas, igual que el resolver de runtime
Recálculación incremental
RecalculateLoadedFormFieldsIncremental evalúa solo la clausura afectada de los campos cambiados dados. Las escrituras a través de SetFormFieldValue y SetLoadedFormFieldValueByName acumulan un dirty set; el overload sin parámetros recalcula a partir de ese conjunto, de modo que una importación FDF o XFDF seguida de una pasada incremental refresca cada cálculo dependiente sin tocar los no relacionados. Ambos overloads y la pasada completa de RecalculateLoadedFormFields consumen el dirty set después
PDF.LoadFromFile('Order.pdf');
PDF.SetLoadedFormFieldValueByName('qty', '3');
PDF.SetLoadedFormFieldValueByName('price', '19.5');
// Recomputes subtotal and total only, chained in one pass
PDF.RecalculateLoadedFormFieldsIncremental(['qty', 'price']);
Inspección del grafo
El grafo expone el estado de cálculo por campo (GetNode), la secuencia completa de evaluación (AllTargets), la clausura afectada (AffectedTargets), el número de targets en ciclos (CyclicTargetCount) y los nombres de source sin resolver, de modo que las herramientas pueden previsualizar exactamente qué cálculos disparará una edición