Sorry for the long post... Just trying to put a few ideas together.
Alt-design (trying the hyphen for a while) takes different approaches at different times. While building the subtree of any node, all of the properties are maintained in a HashMap, along with a BitSet of specified properties.
When the subtree construction is complete, the HashMap and BitSet are used to build the sparse array of only the relevant *resolved* property values (not properties - one of the differences with HEAD) and then thrown away.
Yum... so a Collection of Objects is traded for a handful of --what? (Would this be the propertyValue singletons you mention?)
If I mentioned PropertyValue singletons, it was a slip of the fingers. I maintain Property singletons, which are exist solely to provide access to certain "static" information about individual properties.
What happens with 'unresolvable' Props at that point (for the cases you mention below)?
See the package org.apache.fop.datatypes.indirect, especially IndirectValue, which the others extend. IndirectValue itself extends AbstractPropertyValue. Unresolved values take their place alongside the resolved properties.
Do they get thrown away, or placed in a sort of Property stack for later accessing? If so, how exactly do you indicate in the FObj (or FONode) that the property in question still has to be resolved? So that, when Layout asks for this property, it is signaled that some computations still need to be made? (Pardon me if these questions mean I haven't read your docs thoroughly enough; I did read some of them, but it seems I still miss a bit of technical background to fully understand it.)
The docs are far from adequate.
This approach has to be modified in two environments - fo:static-content and fo:marker. In the case of fo:marker, the inherited environment is not known at parse time, and in the case of static-content, the appropriate fo:retrieve-marker subtrees are not know until the region-body area tree is constructed.
Yes... cases I was overlooking --not so plain inheritance as the FObj's for static-content appear only once or twice every page-sequence, but their inherited properties and values vary, depending on the further processing of the tree. Still, I'm wondering whether you really need to re-parse them (as you indicated)... Couldn't you just, say, keep the Property alive and alter its value when needed? (If this would save you any re-initializing, I mean) The re-parsing idea seems very interesting to be able to say after a threesome of pages have been processed: collapse the branches of the FOTree that have already been layed out to the level below the current fo:flow (or fo:block; in any case some logical point of reference). If downstream, it turns out that their layout needs to be modified again (what are the odds? any way of predicting this?), one could trigger a re-parse from the subtree in question onwards. (This would, I think, save us some memory)
The re-parse may not be strictly necessary, but it is a workable first cut. Generally, static-content and markers will not be large subtrees, so re-parsing them ought not to have a major impact. This can be experimented with once the layout is working. The beauty of the approach is that it simplifies the logic, without (I hope) costing too much in performance.
In terms of the re-layout, re-parsing is not required (Re, re, re your boat...) IndirectValues will need to be re-evaluated in the new context, but the process of re-layout is not markedly different from the normal layout process. Any particular lineage descendant from an fo:flow must be able to adapt to a new environment.
Because the page is a logical unit different from the flow, some line of descent from the fo:flow will be unresolved when any particular page, which is being laid out from that flow, fills up. The incomplete lineage must somehow be associated with the new page, whose region-body dimensions may be different. The layout must then proceed from the point at which the previous page filled.
There are similarities here with backtracking. Backtracking layout involves backtracking to a particular lineage in a particular state (even it that is the beginning of an fo:flow.)
Perhaps the same approach can be taken WRT tables: collapse all finished rows, so their cells are released. When their layed-out state turns out to be insufficient, start processing again from the row in question onwards, *with* the knowledge of what lies ahead this time...
Peter -- Peter B. West <http://www.powerup.com.au/~pbwest/resume.html>