RE: [VOTE] Properties API
Peter B. West wrote: The topic at hand is what API is needed for the FO Tree to be able to pass property values to its clients. Ok. The trouble is that the relationship between FO Tree and Area Tree is, for me, still very much an unresolved question. When we start talking about these things, I go back to thinking about the details of the interaction between FO Nodes and Areas in the Area Tree. Isn't part of your rationale in this get method to provide for the feedback of FO data to the Areas? At what points do you see the method being invoked? To the first question, yes. Layout will be invoking the method as it computes traits for Areas. If Layout is trying to compute, say, the width for an Area, and information about the Area's ancestry is needed to complete that computation, then pass that Area to the FO Tree get method that does the computation. The Area needs to conform to an interface that has methods that can return the appropriate values. For example, the percentage rule whose URL you referenced refers in item 1 to the content-rectangle of the closest ancestor block-area that is not a line-area. So, perhaps a getNotLineAreaAncestorBlockWidth is a method in that interface. Similar methods can be created for other values that may be needed in a computation. 1) markers I have a pretty well-developed idea of how to implement the FO tree building side of this in alt.design. It involves static-content-specific changes to the current FO tree building algorithm, and a slight generalization of the SyncedFoXmlEventsBuffer class to allow events to be read from a variety of sources. In a word, grafting. OK, I have addressed this. We do have very different grafting methodologies. I understand. What I am trying to get you to do is to *consider* the possibility that grafting may not be any more complicated than passing a grafting point around. I am trying to get you to take a step back from your implementation, and help us determine whether, in theory, it really needs to be any more complicated than that. 2) Area tree dependencies for FO expressions. Basically, length calculations involving percentages. OK, I proposed passing the relevant Area to the get method. Is this happening when an area is looking for information about its generating FO? Yes. Why not? The problem before us is that the generating FO says I need to know some resolved values from the Area tree to complete this computation. So we say OK, here is an object that conforms to an interface that will give you that information. FO Tree says OK, here is the value that I compute for that, based upon that object's responses. Layout says Thank you and plugs the value into the Area's traits. 2a) Handling the expressions. This can all be done within the FO Tree. But, if I understand you correctly, only with reference to the Area Tree (via the passing of Area parameters in the get method.) Yes, in some cases that is true. 2b) Designing the interaction between the FO builder and the Area tree builder. OK. I proposed the following, which you have not addressed: from-previous-posting Your experience and insight on this issue are extremely important. If Areas know how to find their FOTree heritage as well as their AreaTree heritage, can you think of any concept that is missing to do Property resolution, assuming that the relevant Area is passed to the get method on the FOTree side? /from-previous-posting This seems to me to be begging the question to some extent. Rather than the Areas knowing how to find their FOTree heritage, isn't it necessary for the FOs to be able to find the AreaTree ancestry of the Areas that the FOs are generating? Isn't that what passing the relevant area in the get is all about? At the same time, however, it does get us thinking about the precise nature of this interaction. The reason that the Area Tree needs to know its FO Tree ancestry is precisely because of the grafting issue. You are correct that the FO Tree needs information from the Area Tree to complete its computations, but how does this beg the question? The question is How do we get the Area information to the FO Tree so that it can complete its computation? My answer is Pass the Area to it, and let the FO TRee ask the Area for the needed information? It may not be a good answer, but I don't think it begged the question. 3) Layout look-ahead and backtracking. Closely related to 2b. AFACT, these would become simply re-getting the value from the FO Tree, passing a new Area as a parameter. 4) Managing the association out-of-line areas (footnotes and floats) with the FONode/Area in which it was defined and the higher-level areas (e.g. before-float-reference-area, footnote-reference-area, main-reference-area) which are juggled as a result of the lower-level contents. Is this not just a specialized case for the general case #2 above? Very
RE: [VOTE] Properties API
Peter B. West wrote: Yes, this is the real issue. Only one of the real issues, I'm afraid. OK, what are the others? The thorns that immediately stick in my finger are The topic at hand is what API is needed for the FO Tree to be able to pass property values to its clients. 1) markers I have a pretty well-developed idea of how to implement the FO tree building side of this in alt.design. It involves static-content-specific changes to the current FO tree building algorithm, and a slight generalization of the SyncedFoXmlEventsBuffer class to allow events to be read from a variety of sources. In a word, grafting. OK, I have addressed this. 2) Area tree dependencies for FO expressions. Basically, length calculations involving percentages. OK, I proposed passing the relevant Area to the get method. 2a) Handling the expressions. This can all be done within the FO Tree. 2b) Designing the interaction between the FO builder and the Area tree builder. OK. I proposed the following, which you have not addressed: from-previous-posting Your experience and insight on this issue are extremely important. If Areas know how to find their FOTree heritage as well as their AreaTree heritage, can you think of any concept that is missing to do Property resolution, assuming that the relevant Area is passed to the get method on the FOTree side? /from-previous-posting 3) Layout look-ahead and backtracking. Closely related to 2b. AFACT, these would become simply re-getting the value from the FO Tree, passing a new Area as a parameter. 4) Managing the association out-of-line areas (footnotes and floats) with the FONode/Area in which it was defined and the higher-level areas (e.g. before-float-reference-area, footnote-reference-area, main-reference-area) which are juggled as a result of the lower-level contents. Is this not just a specialized case for the general case #2 above? Victor Mote
Re: [VOTE] Properties API
Peter B. West wrote: 4) Managing the association out-of-line areas (footnotes and floats) with the FONode/Area in which it was defined and the higher-level areas (e.g. before-float-reference-area, footnote-reference-area, main-reference-area) which are juggled as a result of the lower-level contents. Footnotes are basically float-after areas. Both float before and footnotes are not much of a problem except for multi column layout (and, well, in tables). In multi-column layouts, the equal width of the column should allow reassigning content after decreasing column height without doing a complete re-layout. Side floats, of course, are a real pain, especially if you want to do conflict resolution properly. J.Pietschmann
Re: [VOTE] Properties API
J.Pietschmann wrote: Footnotes are basically float-after areas. Both float before and footnotes are not much of a problem except for multi column layout (and, well, in tables). In multi-column layouts, the equal width of the column should allow reassigning content after decreasing column height without doing a complete re-layout. Side floats, of course, are a real pain, especially if you want to do conflict resolution properly. I'm still attached to my proposed footnote processing method as described in the alt.design notes. http://xml.apache.org/fop/design/alt.design/footnotes.html I'm looking at extending it to cope with footnotes in tables within columns. Peter -- Peter B. West http://www.powerup.com.au/~pbwest/resume.html
Re: [VOTE] Properties API
Victor Mote wrote: Peter B. West wrote: ... The topic at hand is what API is needed for the FO Tree to be able to pass property values to its clients. Ok. The trouble is that the relationship between FO Tree and Area Tree is, for me, still very much an unresolved question. When we start talking about these things, I go back to thinking about the details of the interaction between FO Nodes and Areas in the Area Tree. Isn't part of your rationale in this get method to provide for the feedback of FO data to the Areas? At what points do you see the method being invoked? 1) markers I have a pretty well-developed idea of how to implement the FO tree building side of this in alt.design. It involves static-content-specific changes to the current FO tree building algorithm, and a slight generalization of the SyncedFoXmlEventsBuffer class to allow events to be read from a variety of sources. In a word, grafting. OK, I have addressed this. We do have very different grafting methodologies. 2) Area tree dependencies for FO expressions. Basically, length calculations involving percentages. OK, I proposed passing the relevant Area to the get method. Is this happening when an area is looking for information about its generating FO? 2a) Handling the expressions. This can all be done within the FO Tree. But, if I understand you correctly, only with reference to the Area Tree (via the passing of Area parameters in the get method.) 2b) Designing the interaction between the FO builder and the Area tree builder. OK. I proposed the following, which you have not addressed: from-previous-posting Your experience and insight on this issue are extremely important. If Areas know how to find their FOTree heritage as well as their AreaTree heritage, can you think of any concept that is missing to do Property resolution, assuming that the relevant Area is passed to the get method on the FOTree side? /from-previous-posting This seems to me to be begging the question to some extent. Rather than the Areas knowing how to find their FOTree heritage, isn't it necessary for the FOs to be able to find the AreaTree ancestry of the Areas that the FOs are generating? Isn't that what passing the relevant area in the get is all about? At the same time, however, it does get us thinking about the precise nature of this interaction. 3) Layout look-ahead and backtracking. Closely related to 2b. AFACT, these would become simply re-getting the value from the FO Tree, passing a new Area as a parameter. 4) Managing the association out-of-line areas (footnotes and floats) with the FONode/Area in which it was defined and the higher-level areas (e.g. before-float-reference-area, footnote-reference-area, main-reference-area) which are juggled as a result of the lower-level contents. Is this not just a specialized case for the general case #2 above? Very specialized. These things can force re-layout of the existing page, and can even ramify to previous pages, as we move towards a more intelligent layout strategy. There are two problematical aspects: Layout look-ahead, to determine layout errors (e.g. footnote overflow, last page), and Layout lookahead to determine actual dimensions (auto table layout.) Peter -- Peter B. West http://www.powerup.com.au/~pbwest/resume.html
Re: [VOTE] Properties API
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
Re: [VOTE] Properties API
Victor Mote wrote: Peter B. West wrote: 2% of what? Of a reference area. Of what actually gets laid out on a page. If a single flow object gets laid out over more than one page, that reference may vary, but nothing changes in the FO Tree. It makes o sense to second-guess the Area tree within the FO tree. It's within the Area tree that all of these floe objects begin to take on concrete dimensions. Sec. 7.8.4 indicate that font-size percentages apply to the parent element's font size, which would be from the FOTree, not from areas. However, I fear that in the general case you may be right. The relative column-width problem in tables may fall into this category. If so, then the solution is to pass the relevant Area object to the get method so that it can see more of the Area's context. Any Area can (or should) be able to see not only its Area Tree ancestry, but its FOTree ancestry as well. See Section 7.3 Reference Rectangle for Percentage Computations http://www.w3.org/TR/xsl/slice7.html#percrule are maintained in spite of any to-ing and fro-ing with the Area Tree. Markers are an exception, and because marker properties are resolved in the context of the static-content into which they are eventually placed, all the information required for from-nearest-specified() must be available in the static-content FO subtrees. Yes, this is the real issue. Only one of the real issues, I'm afraid. OK, what are the others? The thorns that immediately stick in my finger are 1) markers I have a pretty well-developed idea of how to implement the FO tree building side of this in alt.design. It involves static-content-specific changes to the current FO tree building algorithm, and a slight generalization of the SyncedFoXmlEventsBuffer class to allow events to be read from a variety of sources. In a word, grafting. 2) Area tree dependencies for FO expressions. Basically, length calculations involving percentages. 2a) Handling the expressions. 2b) Designing the interaction between the FO builder and the Area tree builder. 3) Layout look-ahead and backtracking. Closely related to 2b. 4) Managing the association out-of-line areas (footnotes and floats) with the FONode/Area in which it was defined and the higher-level areas (e.g. before-float-reference-area, footnote-reference-area, main-reference-area) which are juggled as a result of the lower-level contents. More on these design issues in a subsequent post. -- Peter B. West http://www.powerup.com.au/~pbwest/resume.html
Re: [VOTE] Properties API
J.Pietschmann wrote: Victor Mote wrote: This is a good question. The answer to the first part is that it should return an int, representing the number of millipoints. When it cannot be resolved, it should return an int constant TBD_LAYOUT (or whatever), which is equal to -32,987 (or whatever). So, the Area Tree or Layout needs to then perhaps query another get method to determine how it should compute the value from its Area Tree context, or, as I mentioned in a recent (within the past hour or so) posting in response to Glen, either 1) passing context data to get, or 2) making get look at the area tree context before returning the value. What about font-size=12pt+2%+0.8*from-parent(height div 32) ? Good question. Make it font-size=12pt+2%+0.8*(from-parent(height) div 32) though. Even nastier is font-size=12pt+2%+0.8*(from-nearest-specified(height) div 32) because in markers and in static-content, we have to keep track of where *all* property specifications occur in the ancestry FO tree to resolve it. In general, the functions will be resolvable as the FO tree is built. The tree is static, in the sense that the tree relationships are maintained in spite of any to-ing and fro-ing with the Area Tree. Markers are an exception, and because marker properties are resolved in the context of the static-content into which they are eventually placed, all the information required for from-nearest-specified() must be available in the static-content FO subtrees. Because this is not required in the fo:flows, a good deal of property storage efficiency is realizable. This is why I was talking some time ago about a PropertyValue type which is an RPN-style expression, which can be rapidly resolved without recourse to the general parser. Without it, we have to carry at least some expressions around in the raw, after having first parsed them in order to determine that we can't resolve them, and then throw them to the parser again whenever a) we have sufficient context, or b) the page is re-laid. The idea of performing a full parse on a given expression more than once makes me nauseous. The approach I am thinking about with such expressions is to associate the expression, and therefore the FO node, with the *area* which will provide the context for the resolution of the percentage component(s) of the expression. (It may be enough to use the parent area of the areas that the node generates, and to work back to the appropriate reference area or other dimension when the parent dimensions are resolved.) When the dimensions of such an area are resolved, the list of attached FO property expressions can also be resolved. Exactly how to do this I am not yet sure, but I am thinking of something along the lines of a co-routine, implemented by message-passing queues, similar to the existing structure of the parser/FOtree-builder interaction. Peter -- Peter B. West http://www.powerup.com.au/~pbwest/resume.html
Re: [VOTE] Properties API
Peter B. West wrote: Good question. Make it font-size=12pt+2%+0.8*(from-parent(height) div 32) though. O well, the perils of staying awake late... This is why I was talking some time ago about a PropertyValue type which is an RPN-style expression, which can be rapidly resolved without recourse to the general parser. I'm not quite sure what the intend of this sentence is. The maintenance branch uses a recursive descending parser to parse the property expressions as defined in the spec in section 5.9 (complications due to shorthand lists and font lists aside). The parser generates a tree of property expression objects. If the property value is inquired, the expression is evaluated, and the various subexpressions pull necessary context values from their associated FOs. I vaguely remember PropertyList and PropertyManager work somewhat differently, and this is for example the reason why percentages still don't work for table columns and why it is not possible to define a leader length as 2cm+30% (you can have either 2cm or 30%), despite the expression is parsed correctly. Note that while expressions may be *evaluated* repeatedly, they are *parsed* exactly once. Without it, we have to carry at least some expressions around in the raw, after having first parsed them in order to determine that we can't resolve them, and then throw them to the parser again whenever a) we have sufficient context, or b) the page is re-laid. We don't have to carry the expression as string and reparse every time, parsing into an expression tree and evaluating as necessary works just fine. A possible concern could be memory waste, for example if people write start-indent=2cm + 0.8*( 10.4cm div 2) this would create a tree sum + length 2cm + mul + number 0.8 + div + length 10.4cm + number 2 or 7 objects. Compilers use constant folding, i.e. using arithmetic laws for rearranging and possibly combining terms in the expression. A valid length expression would be canonicalized into a sum of an absolute length measure, a percentage and unresolvable functions. Whether building a constant folding mechanism is worthwile is quite another matter. I didn't see complicated expressions all that often, and optimizing the parsed tree may as well cost more time than is saved later. Anyway, the folding mechanism will detect a lot of invalid expressions early during parsing, which may be an advantage. The idea of performing a full parse on a given expression more than once makes me nauseous. Just don't do it. The approach I am thinking about with such expressions is to associate the expression, and therefore the FO node, with the *area* which will provide the context for the resolution of the percentage component(s) of the expression. (It may be enough to use the parent area of the areas that the node generates, and to work back to the appropriate reference area or other dimension when the parent dimensions are resolved.) When the dimensions of such an area are resolved, the list of attached FO property expressions can also be resolved. Exactly how to do this I am not yet sure, but I am thinking of something along the lines of a co-routine, implemented by message-passing queues, similar to the existing structure of the parser/FOtree-builder interaction. Sorry, I think this is overcomplicated. J.Pietschmann
RE: [VOTE] Properties API
Peter B. West wrote: What about font-size=12pt+2%+0.8*from-parent(height div 32) ? Good question. Make it font-size=12pt+2%+0.8*(from-parent(height) div 32) though. Even nastier is font-size=12pt+2%+0.8*(from-nearest-specified(height) div 32) because in markers and in static-content, we have to keep track of where *all* property specifications occur in the ancestry FO tree to resolve it. In general, the functions will be resolvable as the FO tree is built. The tree is static, in the sense that the tree relationships Correct. Neither of the examples given has anything to do with the interface proposed, because all of the computations are done on the FOTree side of the house. are maintained in spite of any to-ing and fro-ing with the Area Tree. Markers are an exception, and because marker properties are resolved in the context of the static-content into which they are eventually placed, all the information required for from-nearest-specified() must be available in the static-content FO subtrees. 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. 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). Because this is not required in the fo:flows, a good deal of property storage efficiency is realizable. This is why I was talking some time ago about a PropertyValue type which is an RPN-style expression, which can be rapidly resolved without recourse to the general parser. Without it, we have to carry at least some expressions around in the raw, after having first parsed them in order to determine that we can't resolve them, and then throw them to the parser again whenever a) we have sufficient context, or b) the page is re-laid. The idea of performing a full parse on a given expression more than once makes me nauseous. Again, this is an implementation detail, and doesn't affect the interface. However, on the implementation side, it seems that the tradeoff will be between doing a full parse each time, or creating lots of objects. John Austin's inquiry about the huge number of objects created is what got me started down this line of thinking. I suppose that the best way would be to have your cake and eat it too -- store integers where possible, and create objects where not possible, and teach everything how to tell the difference. (Here is a half-baked idea that I don't want to even think about pursuing for a while -- PropertyStrategy. With the API I have proposed, one could conceivably store the Properties one of several ways, and have the user select which one they want based on performance needs). The approach I am thinking about
Re: [VOTE] Properties API
J.Pietschmann wrote: Peter B. West wrote: This is why I was talking some time ago about a PropertyValue type which is an RPN-style expression, which can be rapidly resolved without recourse to the general parser. I'm not quite sure what the intend of this sentence is. The maintenance branch uses a recursive descending parser to parse the property expressions as defined in the spec in section 5.9 (complications due to shorthand lists and font lists aside). The parser generates a tree of property expression objects. If the property value is inquired, the expression is evaluated, and the various subexpressions pull necessary context values from their associated FOs. I vaguely remember PropertyList and PropertyManager work somewhat differently, and this is for example the reason why percentages still don't work for table columns and why it is not possible to define a leader length as 2cm+30% (you can have either 2cm or 30%), despite the expression is parsed correctly. Note that while expressions may be *evaluated* repeatedly, they are *parsed* exactly once. Without it, we have to carry at least some expressions around in the raw, after having first parsed them in order to determine that we can't resolve them, and then throw them to the parser again whenever a) we have sufficient context, or b) the page is re-laid. We don't have to carry the expression as string and reparse every time, parsing into an expression tree and evaluating as necessary works just fine. A possible concern could be memory waste, for example if people write start-indent=2cm + 0.8*( 10.4cm div 2) this would create a tree sum + length 2cm + mul + number 0.8 + div + length 10.4cm + number 2 or 7 objects. I missed the import of this when I built the alt.design parser on top of the maintenance branch parser code. This is what I am trying to achieve. If it already exists, so much the better. Where does repeated evaluation of the parse tree occur? Is there a parse tree object? Peter -- Peter B. West http://www.powerup.com.au/~pbwest/resume.html
RE: [VOTE] Properties API
On Thu, 2003-11-27 at 13:58, Victor Mote wrote: ... Again, this is an implementation detail, and doesn't affect the interface. However, on the implementation side, it seems that the tradeoff will be between doing a full parse each time, or creating lots of objects. John Austin's inquiry about the huge number of objects created is what got me started down this line of thinking. I am critical of what I percieve to be a pathological growth of objects (and search times). If those problems are corrected, there are plenty of resources left to do a few extra parses. How often will you encounter expressions this complex ? Rarely. If they become common (and someone will do that!), we can call THAT a pathalogical development and smirkblame the victim/smirk. I suppose that the best way would be to have your cake and eat it too -- store integers where possible, and create objects where not possible, and teach everything how to tell the difference. (Here is a half-baked idea that I don't want to even think about pursuing for a while -- PropertyStrategy. With the API I have proposed, one could conceivably store the Properties one of several ways, and have the user select which one they want based on performance needs). As Peter knows, I have been reading the code. I shall attempt the XSL-FO Spec soon. I understand the spec defines the behavior of the program in terms of fully parsed/expanded trees. This implies that objects must exist even if they will never be used after the parser moves past their end-points. Optimization anyone? What I infer of the Tree structures in your discussion and Peter's code suggests to me that FOP creates a DOM-ish view of the document in one or more trees. This is a mis-match with the SAX parser that is in there somewhere. And just to say something completely ludicrous, because someone will take it seriously ... You could convert those expressions to a Java class, compile, load and invoke it with Reflection ... -- John Austin [EMAIL PROTECTED]
RE: [VOTE] Properties API
Glen Mazza wrote: Sent: Wednesday, November 26, 2003 3:17 PM To: [EMAIL PROTECTED] Subject: RE: [VOTE] Properties API --- Victor Mote [EMAIL PROTECTED] wrote: The current implementation might look like this: public class FObj { public int getMaxWidth() { //WARNING -- unchecked or tested!! return properties.get(max-width).getLength().getValue(); } A subclass that doesn't use max-width might override with: public int getMaxWidth() { return FObj.INVALID_PROPERTY; } Not to be a pain here--but this just occurred to me--if we are going to do this, it may be cleaner to rely on enumeration constants--that way, we probably can avoid all these return FObj.INVALID_PROPERTY overrides in the various FO's for each unsupported property. This is what I'm thinking (pseudocode here): In FOObj (similar to your code above): public int getProperty(int propVal) { if (validateValidProperty(propVal) == false) { return FObj.INVALID_PROPERTY; } return properties.get(max-width).getLength().getValue(); } Then we may just need a single validateValidProperty() method in each FO, that would check if propVal is an accepted property for that FO. Each FO's validateValidProperty() would not need to degenerate into a huge list of comparisons like this: if (prop_val == PROPVAL1 || prop_val == PROPVAL2 || ... on and on and on) return true; else return false; because I think we can simplify the properties supported by an FO into an integer array of 1's (supported) and 0's (not) so the validate() function for any FO would look like this: validateValidProperty(int propVal) { return (supportedProps[propVal] == 1); } (Come to think of it, we can probably keep validateValidProperty() in the FObj base class alone as well!) IOW (I assume) use a 2-dimensional array, the first dimenension representing the Object, the second dimension representing the list of possible Properties. Then, finally, we can perhaps expand this array of 1's and 0's to include a 2--supported by the spec but not yet by FOP, i.e., FObj.NOT_YET_SUPPORTED, and other codes as needed. Comments? This would again be one of the implementation details that I am trying to hide, but yes, it makes sense to me, at least as one of several possibilities. Victor Mote
RE: [VOTE] Properties API
John Austin wrote: I am critical of what I percieve to be a pathological growth of objects (and search times). If those problems are corrected, there are plenty of resources left to do a few extra parses. How often will you encounter expressions this complex ? Rarely. If they become common (and someone will do that!), we can call THAT a pathalogical development and smirkblame the victim/smirk. I tend to agree with all of this, at least in terms of which end of the spectrum we should favor. I suppose that the best way would be to have your cake and eat it too -- store integers where possible, and create objects where not possible, and teach everything how to tell the difference. (Here is a half-baked idea that I don't want to even think about pursuing for a while -- PropertyStrategy. With the API I have proposed, one could conceivably store the Properties one of several ways, and have the user select which one they want based on performance needs). As Peter knows, I have been reading the code. I shall attempt the XSL-FO Spec soon. I understand the spec defines the behavior of the program in terms of fully parsed/expanded trees. This implies that objects must exist even if they will never be used after the parser moves past their end-points. Optimization anyone? This doesn't sound right to me. I think you may have misunderstood something, but you'll need to be more specific for me to tell. What I infer of the Tree structures in your discussion and Peter's code suggests to me that FOP creates a DOM-ish view of the document in one or more trees. This is a mis-match with the SAX parser that is in there somewhere. FOP's design on the SAX/DOM issue was a difficult issue for me to grasp, and when I did, I documented it here: http://xml.apache.org/fop/design/parsing.html#input There is no mismatch at all. The input we work with is a tree. Therefore a tree-like structure is absolutely necessary to represent it. I am pretty sure from past discussions with Peter that he employs a tree-like structure as part of this pull-parsing. So, if it is important for FOP to use a tree-like structure to represent its input, the only issue is whether to use DOM or some home-grown structure. Since a home-grown structure is much lighter and more flexible for our needs (AFAIK, adding business logic to a DOM would be impossible), the only question is what standard way should the home-grown structure be built. SAX provides a much lighter-weight way of building our home-grown structure than anything else that I have seen. Now, if you can figure out how to digest an FO document without building a tree that represents a page-sequence object, I hope you'll share it with the rest of us. That could be a breakthrough indeed. Victor Mote
Re: [VOTE] Properties API
Peter B. West wrote: Where does repeated evaluation of the parse tree occur? Is there a parse tree object? The necessary classes are somewhat distributed across the packages. Some necessary classes are in fop.datatypes, the common property superclasses are in fop.fo, with fop.fo.Property being the top of the hierarchy, there's somethiing in fop.fo.expr and the concrete implementations along with their makers (for parsing) are of course generated. The tree isn't build from classes deriving from a single class, like the FO tree. Instead, the fop.fo.Property class is used for both unevaluated and evaluated properties and for computing functions, while length expressions are built from Length subclasses (the only expressions of nontrivial complexity, everything else which is not a shorthand or text-decoration is either a single token or a function call). The relevant class is LinearCombinationLength. Unfortunately, I can't find the expression parser, but I recall I've seen it. The seemingly clever but ultimately misguided attempt to press all property handling including shorthands, font-family lists and text-decoration in a unified framework has lead to a number of kludges which may make reengineering the whole stuff a bit difficult. Regards J.Pietschmann
RE: [VOTE] Properties API
On Thu, 2003-11-27 at 14:57, Victor Mote wrote: John Austin wrote: I am critical Now, if you can figure out how to digest an FO document without building a tree that represents a page-sequence object, I hope you'll share it with the rest of us. That could be a breakthrough indeed. I am just thinking of ensuring that objects disappear after the page they are on has been printed. At the point that 0.20.5 prints: [INFO] [1] The related objects from Page 1, should ... join the choir invisibule ... They don't appear to, which is why the memory use of FOP increases in proportion to document length. You only need to retain the useful parts of the page-sequence object. Stuff that has been 'printed' isn't useful. Victor Mote -- John Austin [EMAIL PROTECTED]
Re: [VOTE] Properties API
John Austin wrote: I am critical of what I percieve to be a pathological growth of objects (and search times). If those problems are corrected, there are plenty of resources left to do a few extra parses. How often will you encounter expressions this complex ? Rarely. A complex expression tree *will* *not* have any influence on search times in the inheritance lattice of a property. Unless there are functions referencing other properties of course. And more offten than not, there will be exactly one object in the tree, representing the only token parsed from the property value, which is hardly a pathological growth of objects. This implies that objects must exist even if they will never be used after the parser moves past their end-points. Optimization anyone? Be careful, proper layout needs backtracking. J.Pietschmann
Re: [VOTE] Properties API
Victor Mote wrote: John Austin wrote: What I infer of the Tree structures in your discussion and Peter's code suggests to me that FOP creates a DOM-ish view of the document in one or more trees. This is a mis-match with the SAX parser that is in there somewhere. FOP's design on the SAX/DOM issue was a difficult issue for me to grasp, and when I did, I documented it here: http://xml.apache.org/fop/design/parsing.html#input There is no mismatch at all. The input we work with is a tree. Therefore a tree-like structure is absolutely necessary to represent it. I am pretty sure from past discussions with Peter that he employs a tree-like structure as part of this pull-parsing. So, if it is important for FOP to use a tree-like structure to represent its input, the only issue is whether to use DOM or some home-grown structure. Since a home-grown structure is much lighter and more flexible for our needs (AFAIK, adding business logic to a DOM would be impossible), the only question is what standard way should the home-grown structure be built. SAX provides a much lighter-weight way of building our home-grown structure than anything else that I have seen. Even the dreaded pull-parser uses SAX. Now, if you can figure out how to digest an FO document without building a tree that represents a page-sequence object, I hope you'll share it with the rest of us. That could be a breakthrough indeed. The problem is the same one that FOP has always struggled with - how to 1) discard subtrees in a timely manner, and 2) serialize subtrees for efficient caching and retrieval when they will be needed at some time in the future. Peter -- Peter B. West http://www.powerup.com.au/~pbwest/resume.html
Re: [VOTE] Properties API
Victor Mote wrote: Peter B. West wrote: What about font-size=12pt+2%+0.8*from-parent(height div 32) ? Good question. Make it font-size=12pt+2%+0.8*(from-parent(height) div 32) though. Even nastier is font-size=12pt+2%+0.8*(from-nearest-specified(height) div 32) because in markers and in static-content, we have to keep track of where *all* property specifications occur in the ancestry FO tree to resolve it. In general, the functions will be resolvable as the FO tree is built. The tree is static, in the sense that the tree relationships Correct. Neither of the examples given has anything to do with the interface proposed, because all of the computations are done on the FOTree side of the house. 2% of what? Of a reference area. Of what actually gets laid out on a page. If a single flow object gets laid out over more than one page, that reference may vary, but nothing changes in the FO Tree. It makes o sense to second-guess the Area tree within the FO tree. It's within the Area tree that all of these floe objects begin to take on concrete dimensions. are maintained in spite of any to-ing and fro-ing with the Area Tree. Markers are an exception, and because marker properties are resolved in the context of the static-content into which they are eventually placed, all the information required for from-nearest-specified() must be available in the static-content FO subtrees. Yes, this is the real issue. Only one of the real issues, I'm afraid. 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. 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. Not so. Grafting, OK. But you can't resolve the expressions without the areas. 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). Because this is not required in the fo:flows, a good deal of property storage efficiency is realizable. This is why I was talking some time ago about a PropertyValue type which is an RPN-style expression, which can be rapidly resolved without recourse to the general parser. Without it, we have to carry at least some expressions around in the raw, after having first parsed them in order to determine that we can't resolve them, and then throw them to the parser again whenever a) we have sufficient context, or b) the page is re-laid. The idea of performing a full parse on a given expression more than once makes me nauseous. Again, this is an implementation detail, and doesn't affect the interface. However, on the implementation side, it seems that the tradeoff will be between doing a full parse each time, or creating lots of objects. John Austin's inquiry about the huge number of objects created is what got me started down this line of thinking. I suppose that the
RE: [VOTE] Properties API
Peter B. West wrote: What about font-size=12pt+2%+0.8*from-parent(height div 32) ? Good question. Make it font-size=12pt+2%+0.8*(from-parent(height) div 32) though. Even nastier is font-size=12pt+2%+0.8*(from-nearest-specified(height) div 32) because in markers and in static-content, we have to keep track of where *all* property specifications occur in the ancestry FO tree to resolve it. In general, the functions will be resolvable as the FO tree is built. The tree is static, in the sense that the tree relationships Correct. Neither of the examples given has anything to do with the interface proposed, because all of the computations are done on the FOTree side of the house. 2% of what? Of a reference area. Of what actually gets laid out on a page. If a single flow object gets laid out over more than one page, that reference may vary, but nothing changes in the FO Tree. It makes o sense to second-guess the Area tree within the FO tree. It's within the Area tree that all of these floe objects begin to take on concrete dimensions. Sec. 7.8.4 indicate that font-size percentages apply to the parent element's font size, which would be from the FOTree, not from areas. However, I fear that in the general case you may be right. The relative column-width problem in tables may fall into this category. If so, then the solution is to pass the relevant Area object to the get method so that it can see more of the Area's context. Any Area can (or should) be able to see not only its Area Tree ancestry, but its FOTree ancestry as well. are maintained in spite of any to-ing and fro-ing with the Area Tree. Markers are an exception, and because marker properties are resolved in the context of the static-content into which they are eventually placed, all the information required for from-nearest-specified() must be available in the static-content FO subtrees. Yes, this is the real issue. Only one of the real issues, I'm afraid. OK, what are the others? 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. 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. Not so. Grafting, OK. But you can't resolve the expressions without the areas. OK. You may be right. See above. 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). Because this is not required in the fo:flows, a good deal of property storage efficiency is realizable. This is why I was talking some time ago about a PropertyValue type which is an RPN-style expression, which can be rapidly resolved without recourse to the general
RE: [VOTE] Properties API
--- Victor Mote [EMAIL PROTECTED] wrote: validateValidProperty(int propVal) { return (supportedProps[propVal] == 1); } (Come to think of it, we can probably keep validateValidProperty() in the FObj base class alone as well!) IOW (I assume) use a 2-dimensional array, the first dimenension representing the Object, the second dimension representing the list of possible Properties. No--I was thinking just overriding the (static?) member variable array supportProps in each FObj subclass. That way we can keep validateValidProperty() in just the parent class. Minor point, though, from what I was thinking. Glen __ Do you Yahoo!? Free Pop-Up Blocker - Get it now http://companion.yahoo.com/
Re: [VOTE] Properties API
Victor Mote wrote: FOP Developers: This has been kicked around recently, but I realized that it may be beneficial to go ahead and propose a change to get things going. The issue of how Properties are stored in the FO Tree is in play. Since we now have FO Tree pretty well isolated, I see some benefits to nailing down an API for it that should be durable enough to work for any scheme that is used for storing property values. Proposal: I propose that public get methods be used to retrieve FO Tree property values, and that the data behind these values be made as private as possible. The methods should be given a name based on the XSL-FO Standard. For example, the max-width property should be accessed using the method getMaxWidth. The values returned should be the refined values. Discussion: 1. The purpose here is to separate the storage of the property values from their presentation (API) to the rest of the system. This opens the door for later changes to the storage without disrupting the remainder of the system. 2. This could perhaps be implemented for now only in FObj (??). 3. This is not directly relevant to the question, but needs to be addressed from the big picture standpoint. With the FO Tree mostly isolated, and LayoutStrategy implemented, the issue of whether a certain feature is implemented or not moves from the FO Tree to the specific LayoutStrategy. Each LayoutStrategy eventually needs to track which objects and properties it supports. The FO Tree should always store and return the data, without regard to whether it can be used or not. In the future, our properties.xml file, compliance page, and perhaps other things need to handle this. The LayoutStrategy needs to be the entity that reports on whether a feature is supported (perhaps using a scheme similar to properties.xml). 4. If accepted, this would be a great project for one of the new developers to tackle. I don't mean to volunteer anyone, but it might be a good feet wet project. In alt.design, all of the property values are implementations of fop.datatypes.PropertyValue. Every PropertyValue must be able to report its type as an int. Every PropertyValue must also have a Property with which it is associated, and must be able to report this, again as an int. The set of property values relevant to a particular FO are available in a sparse array, accessible by the int index corresponding to the Property. That, it seems to me, is as far as the FO Tree can take things. What are the get methods going to return? In alt.design, they will always return a value of type PropertyValue. This proposal seems to imply that the type returned by the accessors will depend on the type supported by the Property. Take MaxWidth. What value will be returned? An int, representing the number of millipoints? An Integer? A Length object? What happens when the width is, as yet, unresolved, because it depends upon the resolution of the width of a reference area in the Area Tree? The value is not undefined, just unresolved. When the FO Tree interacts with the Area Tree, the length will be resolved. But the Area Tree may be re-laid, in which case the value will revert to unresolved. The resolution of properties within the FO Tree has dependencies on the resolution of areas in the Area Tree. Peter -- Peter B. West http://www.powerup.com.au/~pbwest/resume.html
Re: [VOTE] Properties API
--- Peter B. West [EMAIL PROTECTED] wrote: The set of property values relevant to a particular FO are available in a sparse array, accessible by the int index corresponding to the Property. Which source file has the enumerations of the properties--I'd like to see how you listed them. Are you satisfied with those enumerations--anything you would change if you had to do it over? What happens when the width is, as yet, unresolved, because it depends upon the resolution of the width of a reference area in the Area Tree? The value is not undefined, just unresolved. When the FO Tree interacts with the Area Tree, the length will be resolved. But the Area Tree may be re-laid, in which case the value will revert to unresolved. It may be good to create a sample FO document that would exhibit what you're saying above. Hopefully something that shows a important feature that would clearly fail if we don't take into account the Area Tree while resolving properties. That would help clarify things, and we can use it for testing. The resolution of properties within the FO Tree has dependencies on the resolution of areas in the Area Tree. Yes, that appears in Section 3.1 of the spec under Conceptual Procedure: Unless otherwise specified, processing a formatting object creates areas and returns them to its parent to be placed in the area treeThe formatting object supplies parameters to its children based on the traits of areas already in the area tree, possibly including areas generated by the formatting object or its ancestors. Our changes to property resolution will (probably? eventually?) need to take this into account. First thing's first though--I think we need to stop using string constants for properties in HEAD, and move out the property manager references from the renderers and layout (and Area Tree, possibly). Glen __ Do you Yahoo!? Free Pop-Up Blocker - Get it now http://companion.yahoo.com/
RE: [VOTE] Properties API
Glen Mazza wrote: A few more ideas: (1.) You may find that most of the properties that need to be pulled out of the renderers and layout are actually Area Tree object traits, so renderers layout will probably also benefit from having the Area Tree having these types of accessor functions. Now whether you're inclined (1) to allow Area Tree objects direct access to property list items (like the FOObj's will have) in order to do whatever business logic needed to determine a trait, or (2) provide additional accessor functions--for potentially non-refined properties--in the FOObj's to shield the Area Tree from the property manager, both have their benefits. I suspect you're more comfortable with (2), which I can be OK with. Getting the properties out of layout and the renderers is more important for me, the Area Tree less a priority. Yes, #2 would be my preference. However, you raise a critical point here. Since a Property object can encapsulate more than one piece of data, and a get method can only return one, we may end up having multiple get statements needed in some cases to convey the same amount of information. I *think* this should only be true in the cases that Peter has mentioned where the computation cannot be done until more is known about layout. I think these can be handled cleanly either by 1) passing context data to the get method that it can either use or ignore as its internal data drives, or 2) getting the FO Tree and Area Tree tied together well enough that the FO object can see the Area(s) from which its context is derived, and return the appropriate value. (2.) Just as an FYI, as to the issue of whether the FO's themselves have traits--from our previous discussion, you were saying that elements have attributes, FOs have properties and Area Tree elements have traits, I believe. That fact is confirmed in the second paragraph of the Ch. 3 of the spec[1]. However, somewhat confusingly, if you look at the second, third, and fourth diagrams in 1.1.2, Formatting[2], the spec also refers to traits as the refined/finished properties of the refined formatting object tree. So in some cases, they do consider traits to be both at the finished FO tree and the area tree. [1] http://www.w3.org/TR/2001/REC-xsl-20011015/slice3.html#fo-jc-intro [2] http://www.w3.org/TR/2001/REC-xsl-20011015/slice1.html#section-N74 2-Formatting I don't think I had noticed this before. It looks like the standard *does* consider the refined properties to be traits. Since a refined value in the FO Tree should be the same as the value used in the Area Tree, that makes some sense. (3.) Another option for us, is that rather than create all--or most--of the accessor functions first, and *then* recode the renderers, layout, and possibly area tree to eliminate any property manager references--it may be better to work in the other direction. Hunt down references in the renderers, layout, and area tree (in that order, I suspect) to the property manager, and then create new accessor functions, one-by-one, to replace those property manager references found. This way, we may need to implement only 50 or 60 accessor functions right now, also, we can pound out the necessary lessons learned and layout/renderer code changes needed while trying to replace the properties references (for example, the layout manager classes are sometimes not very good at allowing you to reference the actual FO item or Area Tree object being processed. BlockLayoutManager, for example, does not make it easy to reference the Area.Block being processed.) Makes sense. I always like to let the compiler do the work for me, so I would probably first make all of the Property stuff private, recompile, and start fixing compile errors. Later, when we're ready to implement new layout/renderer functionality requiring new accessor functions, we can then add them to the FObj's/Area Tree as needed. (4.) Finally, there is a question of replacing the property string constants with enumerations, which I believe *all* of us support as a performance booster. Any benefits to getting this out of the way *before* we add the accessor functions? If you are talking about the property values, yes, any that are not yet expressed as enumerations, and that can be, should be. If you are talking about using enumerations to distinguish between Property A and Property B, then this gets done automatically, as each has its own get method. Victor Mote
RE: [VOTE] Properties API
--- Victor Mote [EMAIL PROTECTED] wrote: Makes sense. I always like to let the compiler do the work for me, so I would probably first make all of the Property stuff private, recompile, and start fixing compile errors. Oh...the smoke 'em out! style of programming! I enjoy that too... If you are talking about using enumerations to distinguish between Property A and Property B, then this gets done automatically, as each has its own get method. Oh you got me here...and disregard that portion of my previous response to Peter. I forgot that those would be no longer be needed as a result of these methods. Glen __ Do you Yahoo!? Free Pop-Up Blocker - Get it now http://companion.yahoo.com/
Re: [VOTE] Properties API
On Wed, 2003-11-26 at 14:45, Glen Mazza wrote: --- Peter B. West [EMAIL PROTECTED] wrote: The set of property values relevant to a particular FO are available in a sparse array, accessible by the int index corresponding to the Property. Which source file has the enumerations of the properties--I'd like to see how you listed them. Are you satisfied with those enumerations--anything you would change if you had to do it over? org.apache.fop.fo.PropNames.java has the property strings and assigned numbers. He even states a Perl program (and how to execute it in emacs) to regenerate the numbers. Similar file is org.apache.fop.fo.FObjectNames It may be good to create a sample FO document that would exhibit what you're saying above. Hopefully something that shows a important feature that would clearly fail if we don't take into account the Area Tree while resolving properties. That would help clarify things, and we can use it for testing. And there are reasons to create a set of XSL-FO documents providing test cases. I am concerned that some of Peter's NameSpace code hasn't been tested (or is just hard to grok). -- John Austin [EMAIL PROTECTED]
RE: [VOTE] Properties API
Peter B. West wrote: depend on the type supported by the Property. Take MaxWidth. What value will be returned? An int, representing the number of millipoints? An Integer? A Length object? What happens when the width is, as yet, unresolved, because it depends upon the resolution of the width of a reference area in the Area Tree? The value is not undefined, just unresolved. When the FO Tree interacts with the Area Tree, the length will be resolved. But the Area Tree may be re-laid, in which case the value will revert to unresolved. This is a good question. The answer to the first part is that it should return an int, representing the number of millipoints. When it cannot be resolved, it should return an int constant TBD_LAYOUT (or whatever), which is equal to -32,987 (or whatever). So, the Area Tree or Layout needs to then perhaps query another get method to determine how it should compute the value from its Area Tree context, or, as I mentioned in a recent (within the past hour or so) posting in response to Glen, either 1) passing context data to get, or 2) making get look at the area tree context before returning the value. The second of these requires making the FO Tree nodes know about their Area Tree children. Each node in the Area Tree not only has a parent, and possible siblings, and possible children in the Area, but also has a parent in the FO Tree. Each node in the FO Tree can therefore know what its children in the Area Tree are as well. The resolution of properties within the FO Tree has dependencies on the resolution of areas in the Area Tree. Do you like any of the 3 possibilities above as potential solutions? And, importantly, are there ways that your work can help us implement any of this? I know you have a huge investment in trying to solve this problem, and, although I don't get all of it, I want to make sure that 1) all of your concerns are addressed, and 2) as much of your work is used in the solution as possible. Victor Mote
Re: [VOTE] Properties API
Victor Mote wrote: This is a good question. The answer to the first part is that it should return an int, representing the number of millipoints. When it cannot be resolved, it should return an int constant TBD_LAYOUT (or whatever), which is equal to -32,987 (or whatever). So, the Area Tree or Layout needs to then perhaps query another get method to determine how it should compute the value from its Area Tree context, or, as I mentioned in a recent (within the past hour or so) posting in response to Glen, either 1) passing context data to get, or 2) making get look at the area tree context before returning the value. What about font-size=12pt+2%+0.8*from-parent(height div 32) ? J.Pietschmann
RE: [VOTE] Properties API
--- Victor Mote [EMAIL PROTECTED] wrote: The current implementation might look like this: public class FObj { public int getMaxWidth() { //WARNING -- unchecked or tested!! return properties.get(max-width).getLength().getValue(); } A subclass that doesn't use max-width might override with: public int getMaxWidth() { return FObj.INVALID_PROPERTY; } Not to be a pain here--but this just occurred to me--if we are going to do this, it may be cleaner to rely on enumeration constants--that way, we probably can avoid all these return FObj.INVALID_PROPERTY overrides in the various FO's for each unsupported property. This is what I'm thinking (pseudocode here): In FOObj (similar to your code above): public int getProperty(int propVal) { if (validateValidProperty(propVal) == false) { return FObj.INVALID_PROPERTY; } return properties.get(max-width).getLength().getValue(); } Then we may just need a single validateValidProperty() method in each FO, that would check if propVal is an accepted property for that FO. Each FO's validateValidProperty() would not need to degenerate into a huge list of comparisons like this: if (prop_val == PROPVAL1 || prop_val == PROPVAL2 || ... on and on and on) return true; else return false; because I think we can simplify the properties supported by an FO into an integer array of 1's (supported) and 0's (not) so the validate() function for any FO would look like this: validateValidProperty(int propVal) { return (supportedProps[propVal] == 1); } (Come to think of it, we can probably keep validateValidProperty() in the FObj base class alone as well!) Then, finally, we can perhaps expand this array of 1's and 0's to include a 2--supported by the spec but not yet by FOP, i.e., FObj.NOT_YET_SUPPORTED, and other codes as needed. Comments? Glen __ Do you Yahoo!? Free Pop-Up Blocker - Get it now http://companion.yahoo.com/
Re: [VOTE] Properties API
Glen Mazza wrote: --- Peter B. West [EMAIL PROTECTED] wrote: The set of property values relevant to a particular FO are available in a sparse array, accessible by the int index corresponding to the Property. Which source file has the enumerations of the properties--I'd like to see how you listed them. Are you satisfied with those enumerations--anything you would change if you had to do it over? fo.PropertyNames No, I'm still happy with this. Note that there is one property which no longer exists. I can't remember which, off hand. The editors created it in response to one of Karen's typically incisive questions, and I added it. Months later, they came back with a different response, scrapping the new property and clarifying the behaviour of related pre-existing properties. Note also that there is no such thing as a compound property. The editors were suffering from OO fever, compounded by CSS2 compatibility-itis (a disease which afflicted the Recommendation in a number of places.) I treat compounds as a special case of shorthands. Note also that alt.design, as yet, has no corresponding property handling, but corresponding properties must be defined in a particular way in the list of properties. What happens when the width is, as yet, unresolved, because it depends upon the resolution of the width of a reference area in the Area Tree? The value is not undefined, just unresolved. When the FO Tree interacts with the Area Tree, the length will be resolved. But the Area Tree may be re-laid, in which case the value will revert to unresolved. It may be good to create a sample FO document that would exhibit what you're saying above. Hopefully something that shows a important feature that would clearly fail if we don't take into account the Area Tree while resolving properties. That would help clarify things, and we can use it for testing. The resolution of properties within the FO Tree has dependencies on the resolution of areas in the Area Tree. Yes, that appears in Section 3.1 of the spec under Conceptual Procedure: Unless otherwise specified, processing a formatting object creates areas and returns them to its parent to be placed in the area treeThe formatting object supplies parameters to its children based on the traits of areas already in the area tree, possibly including areas generated by the formatting object or its ancestors. Our changes to property resolution will (probably? eventually?) definitely, absolutely need to take this into account. First thing's first though--I think we need to stop using string constants for properties in HEAD, and move out the property manager references from the renderers and layout (and Area Tree, possibly). As I've said before, we've tried the first things first approach before - it's called FOP 0.*.*. FOP 1.0 *must* be so designed that it can be fully conformant, even if it isn't in the first releases. We cannot get into a position where another redesign is needed to get to conformance. Peter -- Peter B. West http://www.powerup.com.au/~pbwest/resume.html
Re: [VOTE] Properties API
Glen Mazza wrote: --- Victor Mote [EMAIL PROTECTED] wrote: The current implementation might look like this: public class FObj { public int getMaxWidth() { //WARNING -- unchecked or tested!! return properties.get(max-width).getLength().getValue(); } A subclass that doesn't use max-width might override with: public int getMaxWidth() { return FObj.INVALID_PROPERTY; } Not to be a pain here--but this just occurred to me--if we are going to do this, it may be cleaner to rely on enumeration constants--that way, we probably can avoid all these return FObj.INVALID_PROPERTY overrides in the various FO's for each unsupported property. This is what I'm thinking (pseudocode here): In FOObj (similar to your code above): public int getProperty(int propVal) { if (validateValidProperty(propVal) == false) { return FObj.INVALID_PROPERTY; } return properties.get(max-width).getLength().getValue(); } Then we may just need a single validateValidProperty() method in each FO, that would check if propVal is an accepted property for that FO. Each FO's validateValidProperty() would not need to degenerate into a huge list of comparisons like this: if (prop_val == PROPVAL1 || prop_val == PROPVAL2 || ... on and on and on) return true; else return false; because I think we can simplify the properties supported by an FO into an integer array of 1's (supported) and 0's (not) so the validate() function for any FO would look like this: validateValidProperty(int propVal) { return (supportedProps[propVal] == 1); } (Come to think of it, we can probably keep validateValidProperty() in the FObj base class alone as well!) Then, finally, we can perhaps expand this array of 1's and 0's to include a 2--supported by the spec but not yet by FOP, i.e., FObj.NOT_YET_SUPPORTED, and other codes as needed. Comments? Alt.design makes *extensive* use of BitSets (don't have the Javadocs handy, but they're in Collections). datastructs.ROBitSet.java is an attempt at a read-only BitSet. See: fo.PropertySets.java fo.FOPropertySets.java fo.FObjectSets.java You will probably also want to look at fo.PropNames.java and fo.FObjectNames.java Peter -- Peter B. West http://www.powerup.com.au/~pbwest/resume.html
Re: [VOTE] Properties API
I've read your proposal with great interest. I still have to say that I'm still not knowledgeable in the property-resolving area that I can cast a vote here. But it sounds good, nothing that disturbs me. I hope that the people with intimate knowledge in this area all participate and bring up any issue if they see anything problematic. On 25.11.2003 00:17:35 Victor Mote wrote: Proposal: I propose Jeremias Maerki
Re: [VOTE] Properties API
Note: I added a page to the wiki for this thread. http://nagoya.apache.org/wiki/apachewiki.cgi?PropertiesRedesign After thinking about the proposal, I'm not sure it solves anything. There are two aspects to the redesign of Property handling in FOP. * Interface means the external points of contact for Property data * Interface determines impact of changes on other components of the system. * Implementation means the internal construction of classes * Implementation determines performance characteristics of the program. The discussion favours the proposal. Interface The current proposal asks that FOP will employ Java-Bean-like accessors for the properties of Formatting Objects visible to the FOTree. As an example: getMaxWidth?() for the property max-width There are between 250 and 380 of these methods required and they could be generated automatically from an XML-based list of properties. This list could be derived (if not generated) from the XSL-FO Specification itself. Some kind of simple adapter class can be used to equate the proposed interface to the existing one: class PropertyAdapter? extends Property{ // Ugh! just f'rinstance // repeat the following about 380 times: final public Property getMaxWidth?() { // use final to inline and annoy return get(max-width); } } There is no statement defining the current interface. This will be determined from existing code. Implementation The proposal makes no suggestion for implementation and my earlier submission is not relevant except as an indication that this issue is linked to performance. -- John Austin [EMAIL PROTECTED]
RE: [VOTE] Properties API
John Austin wrote: After thinking about the proposal, I'm not sure it solves anything. Perhaps not. If the purpose of building a house is to supply shelter, then building a foundation would seem also not to solve anything. However, it is kind of a necessary first step toward the ultimate goal. All the proposal attempts to do is to separate the interface from the implementation. Right now the interface is pretty tightly tied to the implementation. Changes that you might make to the implementation would require (I think) changes to the LayoutStrategys and to the Renderers. Also, as Glen has pointed out, there is business logic that can be pulled out of these code modules back into FO Tree where they more properly belong, and where duplication and confusion can be minimized. There are two aspects to the redesign of Property handling in FOP. * Interface means the external points of contact for Property data * Interface determines impact of changes on other components of the system. * Implementation means the internal construction of classes * Implementation determines performance characteristics of the program. The discussion favours the proposal. I don't understand what you are saying here. Interface The current proposal asks that FOP will employ Java-Bean-like accessors for the properties of Formatting Objects visible to the FOTree. As an example: getMaxWidth?() for the property max-width There are between 250 and 380 of these methods required and they could be generated automatically from an XML-based list of properties. This list could be derived (if not generated) from the XSL-FO Specification itself. Some kind of simple adapter class can be used to equate the proposed interface to the existing one: class PropertyAdapter? extends Property{ // Ugh! just f'rinstance // repeat the following about 380 times: final public Property getMaxWidth?() { // use final to inline and annoy return get(max-width); } } Sorry -- I was not clear here. I meant to suggest that these methods be added to FObj (and its subclasses to the extent necessary). There is no statement defining the current interface. This will be determined from existing code. Implementation The proposal makes no suggestion for implementation and my earlier submission is not relevant except as an indication that this issue is linked to performance. Again, I am not sure what you are saying here. The proposal deliberately does *not* address implementation. I am quite glad to have you address the performance aspects of implementation, but I think it is a separate issue from the interface. We can (and should, IMO) fix the interface before or at least during any changes to the implementation. All I am trying to do is to hide the implementation from the rest of the system. Your earlier submission *is* relevant to implementation side of the question, just not to the question that I raised, which is totally interface, and which I consider to be foundational to the changes that you are contemplating. The changes you are considering would need to conform to the interface being discussed. Now, if something in my proposal is harmful to the implementation(s) that you are considering, that is definitely relevant. Since FO Tree (and Properties) kind of works right now, we have been paying much more attention to other parts of the FOP code. Your questions and interest are forcing us to address it sooner than we would have. Obviously, one of our highest priorities should be to make other developers as productive as possible. Also, to a certain extent, we have been waiting on Peter West's work, hoping that his efforts can be useful in all of this. I am still hoping to hear from Peter on this, but in the meantime, I am trying to do some housekeeping that IMO will be important to clear the decks for you. Sorry to be so dense -- I may just not be used to your style of writing. Please let me know if I am missing something. Victor Mote
RE: [VOTE] Properties API
Victor, I was mostly backing away from my earlier posting which was off-target. On Tue, 2003-11-25 at 13:26, Victor Mote wrote: John Austin wrote: After thinking about the proposal, I'm not sure it solves anything. you might make to the implementation would require (I think) changes to the LayoutStrategys and to the Renderers. Also, as Glen has pointed out, there is business logic that can be pulled out of these code modules back into FO Tree where they more properly belong, and where duplication and confusion can be minimized. In order to adapt Peter's ideas, I would need identify the current Interface(s). Ideally a re-implementation of Property handling would be invisible outside of those classes. All the proposal addresses is the signature of some accessors. It does not identify the set of property-related classes. I think an adapter class could convert the current interface to the proposed interface. This could be useful if it covers the entire properties interface. The discussion favours the proposal. I don't understand what you are saying here. All/most other postings agreed with the proposal. class PropertyAdapter? extends Property{ // Ugh! just f'rinstance // repeat the following about 380 times: final public Property getMaxWidth?() { // use final to inline and annoy return get(max-width); } } Sorry -- I was not clear here. I meant to suggest that these methods be added to FObj (and its subclasses to the extent necessary). Just a for-instance sketch of an Adapter. Reference to properties has to come from somewhere. I used Inheritence as a convenience. There is no statement defining the current interface. This will be determined from existing code. Implementation The proposal makes no suggestion for implementation and my earlier submission is not relevant except as an indication that this issue is linked to performance. Again, I am not sure what you are saying here. The proposal deliberately does *not* address implementation. I am quite glad to have you address the performance aspects of implementation, but I think it is a separate issue from the interface. We can (and should, IMO) fix the interface before or at least during any changes to the implementation. All I am trying to do is to hide the implementation from the rest of the system. What else is needed to 'get' properties ? Your accessors just have the property name. Since FO Tree (and Properties) kind of works right now, we have been paying much more attention to other parts of the FOP code. Your questions and interest are forcing us to address it sooner than we would have. Obviously, Don't feel forced. You CAN ignore me. I appreciate your efforts to clue me in. one of our highest priorities should be to make other developers as productive as possible. Also, to a certain extent, we have been waiting on Peter West's work, hoping that his efforts can be useful in all of this. I am still hoping to hear from Peter on this, but in the meantime, I am trying to do some housekeeping that IMO will be important to clear the decks for you. I support your Interface-view of properties but would like to have the scope of the Property interface mapped out to include more than the accessors. Of course, if these accessors and some references all ready held by FObj, can do the trick, lets get on with it! -- John Austin [EMAIL PROTECTED]
RE: [VOTE] Properties API
John Austin wrote: In order to adapt Peter's ideas, I would need identify the current Interface(s). Ideally a re-implementation of Property handling would be invisible outside of those classes. I think we have a one-time cost of changing the interface. IOW, I think any changes that you make to the way Properties are handled will require changes to Layout and Render. I just want to make sure that it is handled so that any future changes can be handled transparently. All the proposal addresses is the signature of some accessors. It does not identify the set of property-related classes. I think an adapter class could convert the current interface to the proposed interface. Yes, that is absolutely true. Or the existing interface can simply become the back-end to the new one (at least until the implementation changes). All of that is negotiable as a separate issue. class PropertyAdapter? extends Property{ // Ugh! just f'rinstance // repeat the following about 380 times: final public Property getMaxWidth?() { // use final to inline and annoy return get(max-width); } } Sorry -- I was not clear here. I meant to suggest that these methods be added to FObj (and its subclasses to the extent necessary). Just a for-instance sketch of an Adapter. Reference to properties has to come from somewhere. I used Inheritence as a convenience. I think I must not be following you here. Since properties are logically attached to FO Object instances, it made sense to me that the methods for getting them should live there as well. So the 250-380 methods would go (I think) into FObj and subclasses. If the adapter needs to have a similar number of methods, which is what I think you are suggesting, that is OK. I just want to make it clear that the part of this that would be visible to the rest of FOP would *only* be the stuff in FObj and subclasses. What else is needed to 'get' properties ? Your accessors just have the property name. That, of course, depends on the implementation. Right now, they would be looked up in the PropertyList. However, there are conversions that need to take place. I am thinking, for example, that lengths should always return a millipoint value, to simplify Layout and Render. Since FO Tree (and Properties) kind of works right now, we have been paying much more attention to other parts of the FOP code. Your questions and interest are forcing us to address it sooner than we would have. Obviously, Don't feel forced. You CAN ignore me. I appreciate your efforts to clue me in. I understand, and forced is too strong a word. However, I think we are all very, very, VERY eager to help develop new developers. Your observations about FOP's performance and the causes ring true, and it makes sense to help make you productive. Three months ago, I would not have been as excited about this project, because we still had a lot of overlap between FO Tree and Layout. That has mostly been factored out, and cleaning up the interface for Properties is IMO a logical extension of that work. I support your Interface-view of properties but would like to have the scope of the Property interface mapped out to include more than the accessors. Of course, if these accessors and some references all ready held by FObj, can do the trick, lets get on with it! As far as the interface to the remainder of FOP goes, I think the signatures of the accessors is all of it. I can't think of anything else. If I want the max-width property, I should be able to do something like: int maxWidth = someFObj.getMaxWidth(); The current implementation might look like this: public class FObj { public int getMaxWidth() { //WARNING -- unchecked or tested!! return properties.get(max-width).getLength().getValue(); } A subclass that doesn't use max-width might override with: public int getMaxWidth() { return FObj.INVALID_PROPERTY; } A future implementation might have very different internals, but would have the same signature. Victor Mote
RE: [VOTE] Properties API
--- Victor Mote [EMAIL PROTECTED] wrote: Also, as Glen has pointed out, there is business logic that can be pulled out of these code modules back into FO Tree where they more properly belong, and where duplication and confusion can be minimized. A few more ideas: (1.) You may find that most of the properties that need to be pulled out of the renderers and layout are actually Area Tree object traits, so renderers layout will probably also benefit from having the Area Tree having these types of accessor functions. Now whether you're inclined (1) to allow Area Tree objects direct access to property list items (like the FOObj's will have) in order to do whatever business logic needed to determine a trait, or (2) provide additional accessor functions--for potentially non-refined properties--in the FOObj's to shield the Area Tree from the property manager, both have their benefits. I suspect you're more comfortable with (2), which I can be OK with. Getting the properties out of layout and the renderers is more important for me, the Area Tree less a priority. (2.) Just as an FYI, as to the issue of whether the FO's themselves have traits--from our previous discussion, you were saying that elements have attributes, FOs have properties and Area Tree elements have traits, I believe. That fact is confirmed in the second paragraph of the Ch. 3 of the spec[1]. However, somewhat confusingly, if you look at the second, third, and fourth diagrams in 1.1.2, Formatting[2], the spec also refers to traits as the refined/finished properties of the refined formatting object tree. So in some cases, they do consider traits to be both at the finished FO tree and the area tree. [1] http://www.w3.org/TR/2001/REC-xsl-20011015/slice3.html#fo-jc-intro [2] http://www.w3.org/TR/2001/REC-xsl-20011015/slice1.html#section-N742-Formatting (3.) Another option for us, is that rather than create all--or most--of the accessor functions first, and *then* recode the renderers, layout, and possibly area tree to eliminate any property manager references--it may be better to work in the other direction. Hunt down references in the renderers, layout, and area tree (in that order, I suspect) to the property manager, and then create new accessor functions, one-by-one, to replace those property manager references found. This way, we may need to implement only 50 or 60 accessor functions right now, also, we can pound out the necessary lessons learned and layout/renderer code changes needed while trying to replace the properties references (for example, the layout manager classes are sometimes not very good at allowing you to reference the actual FO item or Area Tree object being processed. BlockLayoutManager, for example, does not make it easy to reference the Area.Block being processed.) Later, when we're ready to implement new layout/renderer functionality requiring new accessor functions, we can then add them to the FObj's/Area Tree as needed. (4.) Finally, there is a question of replacing the property string constants with enumerations, which I believe *all* of us support as a performance booster. Any benefits to getting this out of the way *before* we add the accessor functions? Anyway, after reading your responses to my concerns as well as others' concerns, I'm now +1. Glen __ Do you Yahoo!? Free Pop-Up Blocker - Get it now http://companion.yahoo.com/
Re: [VOTE] Properties API
Please correct me if I'm wrong, I'm just sort of restating your proposal to make sure I understand it and how it fits in the app. What you're suggesting here is not to abandon the PropertyList, but to encapsulate it by replacing get(name) with getName(). Then we lose the dependency on the HashMap implementation of PropertyList, and we prevent people from thinking they'll get a property back from a FObj that doesn't support that property. I just want to make sure we're on the same page, especially before I volunteer :) On Nov 24, 2003, at 6:17 PM, Victor Mote wrote: FOP Developers: This has been kicked around recently, but I realized that it may be beneficial to go ahead and propose a change to get things going. The issue of how Properties are stored in the FO Tree is in play. Since we now have FO Tree pretty well isolated, I see some benefits to nailing down an API for it that should be durable enough to work for any scheme that is used for storing property values. Proposal: I propose that public get methods be used to retrieve FO Tree property values, and that the data behind these values be made as private as possible. The methods should be given a name based on the XSL-FO Standard. For example, the max-width property should be accessed using the method getMaxWidth. The values returned should be the refined values. Discussion: 1. The purpose here is to separate the storage of the property values from their presentation (API) to the rest of the system. This opens the door for later changes to the storage without disrupting the remainder of the system. 2. This could perhaps be implemented for now only in FObj (??). 3. This is not directly relevant to the question, but needs to be addressed from the big picture standpoint. With the FO Tree mostly isolated, and LayoutStrategy implemented, the issue of whether a certain feature is implemented or not moves from the FO Tree to the specific LayoutStrategy. Each LayoutStrategy eventually needs to track which objects and properties it supports. The FO Tree should always store and return the data, without regard to whether it can be used or not. In the future, our properties.xml file, compliance page, and perhaps other things need to handle this. The LayoutStrategy needs to be the entity that reports on whether a feature is supported (perhaps using a scheme similar to properties.xml). 4. If accepted, this would be a great project for one of the new developers to tackle. I don't mean to volunteer anyone, but it might be a good feet wet project. My vote: +1 Victor Mote
Re: [VOTE] Properties API
On Mon, 2003-11-24 at 19:47, Victor Mote wrote: FOP Developers: Proposal: I propose that public get methods be used to retrieve FO Tree property values, and that the data behind these values be made as private as possible. The methods should be given a name based on the XSL-FO Standard. For example, the max-width property should be accessed using the method getMaxWidth. The values returned should be the refined values. I have been thinking about this a bit and I would like to throw out a few rambling observations: Properties are defined in the spec, so there are a finite number of them meaning that they map nicely in to an enumeration type*. Peter West had written some stuff along that line. This allows us to get away from object-and-compute-intensive String types. There are about 380 of these in Peter's Mapping. Some 249 are simple attributes and the rest are more complex, like space-after.optimum, space-after.miumum etc. One train of thought I've had asks whether we need an atomic 'Property' type alone or whether we can use a larger aggregate object type like PropertyList that is a vector with each attribute value in a fixed position. The idea here is that such a vector, something like a vTable, can be merged quickly to resolve inheritence. v[FONT_FAMILY] = sans-serif v[FONT_SIZE] - 10pt v[...] - ... v has 400 entries or 250 entries and we use polymorphism somehow on the complex properties Discussion: 1. The purpose here is to separate the storage of the property values from their presentation (API) to the rest of the system. This opens the door for later changes to the storage without disrupting the remainder of the system. We need to contain the number of objects here. say with canonical mapping of the property name strings. Possibly also use canonical mapping of the attribute values too. How many times is 10pt or bold coded in an document ? Especially, given that patterns of FO are emitted by XSLT in other programs. Allows faster compares when we can test with == rather than Object.equals( Object). I had thought that the fact that all of the attributes are in the XSL-FO Specification and that there are some simple structures used, I might want to generate the property name list and some of the acccessors like you have named them, automatically. Is there an XSL Schema for XSL-FO, or would I just extract them from xml in the Spec document ? I can't say anything about how this stuff gets used, points 2 3. I'd be interested in being involved in item 4. 2. This could perhaps be implemented for now only in FObj (??). 3. This is not directly relevant to the question, but needs to be addressed from the big picture standpoint. With the FO Tree mostly isolated, and LayoutStrategy implemented, the issue of whether a certain feature is implemented or not moves from the FO Tree to the specific LayoutStrategy. Each LayoutStrategy eventually needs to track which objects and properties it supports. The FO Tree should always store and return the data, without regard to whether it can be used or not. In the future, our properties.xml file, compliance page, and perhaps other things need to handle this. The LayoutStrategy needs to be the entity that reports on whether a feature is supported (perhaps using a scheme similar to properties.xml). 4. If accepted, this would be a great project for one of the new developers to tackle. I don't mean to volunteer anyone, but it might be a good feet wet project. My vote: +1 Victor Mote * we don' need no steenking enumeration type! For years I thought the 'steenkin badges' quote originated with WKRP's Dr. Johnny Fever. -- John Austin [EMAIL PROTECTED]
Re: [VOTE] Properties API
--- Victor Mote [EMAIL PROTECTED] wrote: Proposal: I propose that public get methods be used to retrieve FO Tree property values, and that the data behind these values be made as private as possible. The methods should be given a name based on the XSL-FO Standard. For example, the max-width property should be accessed using the method getMaxWidth. The values returned should be the refined values. (a) be careful--refined (resolved) values here would imply traits according to the spec[1]--which would be only a fairly small subset of all possible property values. Which do you mean (I'm personally inclined to just returning traits.) [1] http://www.w3.org/TR/2001/REC-xsl-20011015/slice5.html#refine-border-padding (b) Where possible, I would like the API to encapsulate the business logic away from the renderers and the layout strategies to save repetition of business logic code (for example, default-value setting). (c) Also, as I was mentioning above with limiting just to traits, some properties should not need to be accessible via the API. Examples: 1.) Resolving absolute and relative border properties. The spec[2] gives specific rules for resolving precedence when both relative and absolute properties are given: (say, both padding-left and padding-start are given). What I'd like is the API *not* to expose intermediate properties that would need subsequent business logic before using, such as getPaddingLeft()--layout and renderers don't need it. Have the API just provide getPaddingStart(), and let that method determine, based on the presence of absence of the PaddingLeft (or PaddingRight, etc.) what the PaddingStart() value is. Would you be in agreement with this? [2] http://www.w3.org/TR/2001/REC-xsl-20011015/slice5.html#refine-border-padding 2.) Resolving specific vs. the shorthand properties (sec. 7.29)--Shorthand properties should not need to be exposed, for similar reasons as above. Discussion: 2. This could perhaps be implemented for now only in FObj (??). 3. This is not directly relevant to the question, but needs to be addressed from the big picture standpoint. With the FO Tree mostly isolated, and LayoutStrategy implemented, the issue of whether a certain feature is implemented or not moves from the FO Tree to the specific LayoutStrategy. Not necessarily--although it now above the FO Tree, it's really with the specific renderer. For two reasons: 1) Some properties, such as background-color, aren't even touched by LayoutStrategy. LS never gets into those properties. 2) (degenerate case) Some of our 1.0 renderers are all of 50 or 60 LOC right now. Now matter how work-of-art the LS is or can be, certain feature is implemented will be a no for those renderers, while not for others. Each LayoutStrategy eventually needs to track which objects and properties it supports. The LayoutStrategy needs to be the entity that reports on whether a feature is supported (perhaps using a scheme similar to properties.xml). Be careful--besides the background-color stuff mentioned above, even certain border and padding features end up being implemented via the specific Renderer code. So you'll have to ask the Renderer--the LS wouldn't know. The FO Tree should always store and return the data, without regard to whether it can be used or not. What would you think about storing these accessor methods (not necessarily the data itself) in the Area.xxx class objects instead, for referencing by the layout strategies and the renderers? [However, not all FO's are represented by Area objects, I believe, so storing the methods with the Area Tree class object may not be possible. Also, there is not always a 1-to-1 mapping between fo:block and Area.block (a new instance of the latter gets created for each page needed in rendering the fo:block). So some properties defined for an fo:block, such as space-after, would probably need to resolve to '0' for each Area object created for its rendering, except for the last, *if* we kept the accessor methods in the Area.xxx objects.] In the future, our properties.xml file, compliance page, and perhaps other things need to handle this. I would like to see the compliance page change into several pages. The first page would just be a list of FO's. Clicking on one of the FO's will bring the reader to another page, showing a table: 1) first column: All the possible properties for that FO. 2) second--umpteeth column, one column for each output type: whether that property is implemented for that current render-type. 3) at the bottom of the table--various partially implemented comments, caveats, notes, etc. That way people will know what works for PCL, PDF, etc. 4. If accepted, this would be a great project for one of the new developers to tackle. I don't mean to volunteer anyone, but it might be a good feet wet project. Not always--a getBorderBeforeColor() for a table cell will need to take into account what
RE: [VOTE] Properties API
John Austin wrote: Proposal: I propose that public get methods be used to retrieve FO Tree property values, and that the data behind these values be made as private as possible. The methods should be given a name based on the XSL-FO Standard. For example, the max-width property should be accessed using the method getMaxWidth. The values returned should be the refined values. I have been thinking about this a bit and I would like to throw out a few rambling observations: Properties are defined in the spec, so there are a finite number of them meaning that they map nicely in to an enumeration type*. Peter West had I almost misunderstood your point here. I now understand you to be referring to the distinguishing between property A and property B, not the values of the properties themselves. written some stuff along that line. This allows us to get away from object-and-compute-intensive String types. There are about 380 of these in Peter's Mapping. Some 249 are simple attributes and the rest are more complex, like space-after.optimum, space-after.miumum etc. One train of thought I've had asks whether we need an atomic 'Property' type alone or whether we can use a larger aggregate object type like PropertyList that is a vector with each attribute value in a fixed position. The idea here is that such a vector, something like a vTable, can be merged quickly to resolve inheritence. v[FONT_FAMILY] = sans-serif v[FONT_SIZE] - 10pt v[...] - ... v has 400 entries or 250 entries and we use polymorphism somehow on the complex properties OK. This is actually the stuff I am trying to hide, so is not entirely relevant to the question at hand, although the purpose of the proposal is to make it easier to do exactly this, or something like it. That said, I wonder why we can't just store these values in fields in the FO object itself. Many of the values are boolean or enumeration types, others are stated or computed lengths, which, in their *refined* terms can be spit out in millipoints. There are some properties which may require non-primitive types, so pointers get stored to them. Discussion: 1. The purpose here is to separate the storage of the property values from their presentation (API) to the rest of the system. This opens the door for later changes to the storage without disrupting the remainder of the system. We need to contain the number of objects here. say with canonical mapping of the property name strings. Possibly also use canonical mapping of the attribute values too. How many times is 10pt or bold coded in an document ? Especially, given that patterns of FO are emitted by XSLT in other programs. Allows faster compares when we can test with == rather than Object.equals( Object). I agree. Fonts are a special case -- the Font object will encapsulate the font-family, size, variant, etc. Eventually, a collection of Fonts used will be searched for a match before creating a new Font object. I had thought that the fact that all of the attributes are in the XSL-FO Specification and that there are some simple structures used, I might want to generate the property name list and some of the acccessors like you have named them, automatically. Is there an XSL Schema for XSL-FO, or would I just extract them from xml in the Spec document ? There is a properties.xml file (I think that is the name) that has some of this. I can't say anything about how this stuff gets used, points 2 3. I'd be interested in being involved in item 4. 2. This could perhaps be implemented for now only in FObj (??). Point 2 is pretty relevant to point 4. What I was saying is that to get this done, it might only require placing the 250 or 400 get methods in FObj, for now anyway. * we don' need no steenking enumeration type! For years I thought the 'steenkin badges' quote originated with WKRP's Dr. Johnny Fever. Could be. I would have guessed Cheech Marin. Victor Mote
Re: [VOTE] Properties API
Glen Mazza wrote: Not always--a getBorderBeforeColor() for a table cell will need to take into account what was declared for any row, column, and possibly table-edge that the its before edge shares. The border conflict resolution algorithm is described in the CSS2 spec, see http://www.w3.org/TR/REC-CSS2/tables.html#borders and especially http://www.w3.org/TR/REC-CSS2/tables.html#border-conflict-resolution However, background images and placement and some other stuff should be fairly simple compared to table borders. J.Pietschmann
RE: [VOTE] Properties API
Glen Mazza wrote: --- Victor Mote [EMAIL PROTECTED] wrote: Proposal: I propose that public get methods be used to retrieve FO Tree property values, and that the data behind these values be made as private as possible. The methods should be given a name based on the XSL-FO Standard. For example, the max-width property should be accessed using the method getMaxWidth. The values returned should be the refined values. (a) be careful--refined (resolved) values here would imply traits according to the spec[1]--which would be only a fairly small subset of all possible property values. Which do you mean (I'm personally inclined to just returning traits.) [1] http://www.w3.org/TR/2001/REC-xsl-20011015/slice5.html#refine-bord er-padding Hmmm. AFAIK, traits is just a semantical distinction for the Area Tree equivalent of the FO Tree properties. (Elements have attributes, Objects have properties, Areas have traits). Not all properties require refinement. For those that don't, you spit back out the user-supplied value. For those that do (because of inheritance, etc.) you spit out the computed or otherwise refined value. Or perhaps I missed your point? (b) Where possible, I would like the API to encapsulate the business logic away from the renderers and the layout strategies to save repetition of business logic code (for example, default-value setting). Yes, default-values should be handled in the FO Tree. You are absolutely right that none of that should be hard-coded in the renderers or the layout strategies. (c) Also, as I was mentioning above with limiting just to traits, some properties should not need to be accessible via the API. Examples: 1.) Resolving absolute and relative border properties. The spec[2] gives specific rules for resolving precedence when both relative and absolute properties are given: (say, both padding-left and padding-start are given). What I'd like is the API *not* to expose intermediate properties that would need subsequent business logic before using, such as getPaddingLeft()--layout and renderers don't need it. Have the API just provide getPaddingStart(), and let that method determine, based on the presence of absence of the PaddingLeft (or PaddingRight, etc.) what the PaddingStart() value is. Would you be in agreement with this? Yes. AFAIK, the getPaddingLeft() is just a convenience for the user. [2] http://www.w3.org/TR/2001/REC-xsl-20011015/slice5.html#refine-bord er-padding 2.) Resolving specific vs. the shorthand properties (sec. 7.29)--Shorthand properties should not need to be exposed, for similar reasons as above. Agreed. Discussion: 2. This could perhaps be implemented for now only in FObj (??). 3. This is not directly relevant to the question, but needs to be addressed from the big picture standpoint. With the FO Tree mostly isolated, and LayoutStrategy implemented, the issue of whether a certain feature is implemented or not moves from the FO Tree to the specific LayoutStrategy. Not necessarily--although it now above the FO Tree, it's really with the specific renderer. For two reasons: 1) Some properties, such as background-color, aren't even touched by LayoutStrategy. LS never gets into those properties. 2) (degenerate case) Some of our 1.0 renderers are all of 50 or 60 LOC right now. Now matter how work-of-art the LS is or can be, certain feature is implemented will be a no for those renderers, while not for others. Point taken. The point I was trying to make is that it is downstream of the FOTree, which I would like to be fairly capability-agnostic. Make Layout or Renderer complain if they can't handle a requested feature. We do have to (for now anyway) deal with Renderer-contextual things (AWT fonts for example), but we should IMO pretty aggressively keep these to a minimum with the hope of eventually getting rid of all of them. Each LayoutStrategy eventually needs to track which objects and properties it supports. The LayoutStrategy needs to be the entity that reports on whether a feature is supported (perhaps using a scheme similar to properties.xml). Be careful--besides the background-color stuff mentioned above, even certain border and padding features end up being implemented via the specific Renderer code. So you'll have to ask the Renderer--the LS wouldn't know. OK. The FO Tree should always store and return the data, without regard to whether it can be used or not. What would you think about storing these accessor methods (not necessarily the data itself) in the Area.xxx class objects instead, for referencing by the layout strategies and the renderers? [However, not all FO's are represented by Area objects, I believe, so storing the methods with the Area Tree class object may not be possible. Also, there is not always a 1-to-1 mapping between fo:block and Area.block (a new instance of the latter