Victor Mote wrote:
Peter B. West wrote:
...

Yes, this is the real issue. Since an fo:marker's content can be used more than one place, this requires that its contents be "grafted" into the tree where needed.

I think the only trick here is to pass the static content context back to
the "get" method so that it knows how to get the information it needs. Sec
6.11.4 says that fo:retrieve-marker "is (conceptually) replaced by the
children of the fo:marker that it retrieves." The most general way that I
can think of to implement this is to force the passage of a parent
fop.fo.flow.RetrieveMarker in the "get" method's signature. This tells the
"get" method: "One of your ancestors is an fo:marker object, and, for
purposes of this "get", consider that ancestor grafted into the tree at this
fo:retrieve-marker's location." Of course, if there is no ancestor
fo:marker, pass a null.

Now, this raises another issue. FONode has a getParent() method. This method
may need to be expanded to include this concept. Any child could then ask
for its parent either with null (go up the tree through fo:marker, i.e. the
way the input specifies, and the way it works now), or with a "grafting
point" specified, so that if a grafting point is specified, it will go up
the tree in that direction instead. In fact, it may be good to create a
GraftingPoint interface that RetrieveMarker implements, in case there are
additional similar items now or in the future.

class Marker {
...
    getParent(GraftingPoint gp) {
        if (gp == null) {
            return this.parent;
        }
        return gp.getParent(null);
    }
...
}

So, lets use:
font-size="12pt+2%+0.8*(from-nearest-specified(height) div 32)
as an example. Lets assume an FOTree fragment that looks like this:

  fo:marker
    fo:block
      fo:inline

For both the block and the inline, the "get" will need to research its
ancestry to resolve the expression. If we pass the grafting point to the
"get", and the "get" directly or indirectly uses the getParent(GraftingPoint
gp) method to find that ancestry, it seems to me that everybody has
everything they need.


To restate a particular point here about grafting:- In the model I am developing for grafting, it is a pure implementation activity. It is a method of building static-content FO subtrees in a "transparent" manner. Once these static-content/marker subtrees are built, they look just like the other subtrees of the FO tree. In particular, they still suffer from the same sort of problems of interaction with the Area tree that afflict the rest of the FO tree.

What that means for higher level interfaces is that the grafting is
transparent - higher level interfaces, like your "get", just won't see it.

The key insight for me here is that *none* of this is actually dependent on
the Area Tree at all, that what we are really doing is grafting. I had
originally thought that some Area Tree information would need to be passed
in, but I really think the above is much more elegant, and more clearly
follows the concepts that are in play. Of cource, I rely on the rest of you
guys to tell me if I have missed something (a real possibility).


Peter -- Peter B. West <http://www.powerup.com.au/~pbwest/resume.html>





Reply via email to