Grafo de dependências de cálculo de formulários
O HotPDF constrói um grafo de dependências sobre os campos de cálculo de um AcroForm carregado, para que uma alteração de valor recalcule apenas os cálculos que a leem transitivamente, numa ordem em que cada valor recalculado já é visível para os cálculos que o consomem
Graph construction
THotPDF.BuildLoadedFormCalculationGraph devolve um snapshot pertencente a quem chama. Cada campo torna-se um nó; cada script Calculate registado em /CO é analisado estaticamente com HPDFExtractSafeJavaScriptFieldReferences, que lê os nomes de campo que um script do subconjunto seguro toca: os argumentos entre aspas de AFSimple_Calculate("OP", ["a","b"]) e os nomes entre aspas dos acessos getField("x"), ignorando os literais de string para que menções textuais não sejam tratadas como referências
THPDFFormCalcGraph.ResolveLinks resolve esses nomes em arestas source → dependent e ordena os alvos com uma ordenação topológica. Os campos que estão num ciclo de dependências mantêm a ordem de documento de /CO, de acordo com a semântica de passagem única de um recálculo completo; um campo alterado nunca recalcula o seu próprio script, pelo que os ciclos não oscilam e um valor escrito pelo utilizador prevalece sempre. Os nomes de origem que não correspondem a nenhum campo são reportados através de UnresolvedFieldNameCount e não produzem arestas, tal como no resolver em runtime
Incremental recalculation
RecalculateLoadedFormFieldsIncremental avalia apenas o fecho afetado pelos campos alterados indicados. As escritas através de SetFormFieldValue e SetLoadedFormFieldValueByName acumulam um dirty set; o overload sem parâmetros recalcula a partir desse conjunto, pelo que uma importação FDF ou XFDF seguida de uma passagem incremental atualiza todos os cálculos dependentes sem tocar nos que não estão relacionados. Ambos os overloads e a passagem completa de RecalculateLoadedFormFields consomem depois o dirty set
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']);
Graph inspection
O grafo expõe o estado de cálculo por campo (GetNode), a sequência de avaliação completa (AllTargets), o fecho afetado (AffectedTargets), o número de alvos em ciclos (CyclicTargetCount) e os nomes de origem não resolvidos, para que as ferramentas possam antever exatamente que cálculos uma edição vai disparar