Properties Redesign Discussion

Proposal (Victor Mote)

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 "feetwet" project.

Response (Joe DeVivo)

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 :)

Response (John Austin)

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 (properties) 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.

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.

Response: (Victor Moto to Joe DeVivo)

{{{ Joe DeVivo wrote:

Yes, or any other implementation-specific structure. Now, I think it may make sense to abandon PropertyList, but that is a separate question. All Iam really trying to do here is lay the groundwork for someone to come along & make the Properties more efficient.

{{{ prevent people from thinking they'll get a property back from a FObj

This would at least be possible under the proposal, but wouldn't necessarily be so. One possible implementation is to simply put a "get" method for each property in FObj and have it use the current system to retrieve the value from the PropertyList. This approach wouldn't address the issue you raise, unless an overridden method that returns a "not supported" value werecreated in the subclass.

Response (Glen Mazza to Victor Mote)

{{{ Victor Mote <vic@outfitr.com> wrote:

(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:

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'teven 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

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

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

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: #) first column: All the possible properties for that FO. #) second--umpteeth column, one column for each output type: whether that property is implemented for that current render-type. #) 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

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. Keep in mind, some of thes eaccessor functions will require significant programming logic that we don't presently have.

{{{ > My vote:

Abstaining currently--although I don't see anything that bad right now. I'd like to wait for more comments from you and the others.

Glen

Response (Victor responds to Glen's response)

{{{ > --- Victor Mote <vic@outfitr.com

Hmmm. AFAIK, "traits" is just a semantical distinction for the Area Tree equivalent of the FO Tree properties. (Elements have attributes, Objectshave properties, Areas have traits). Not all properties require refinement.For those that don't, you spit back out the user-supplied value. For thosethat do (because of inheritance, etc.) you spit out the computed orotherwise refined value. Or perhaps I missed your point? {{{ > (b) Where possible, I would like the API to

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

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

Agreed. {{{ >> Discussion:

OK. {{{ >> The FO Tree should always store and

I don't see any advantage to even trying this and lots of disadvantages. However, it almost certainly makes sense to have similar accessor methods inthe Area Tree that return its traits for the renderers. Also (this is wayoff-topic), someday I want to look at the possibility of having the content(as opposed to placement) portions of the Area Tree be "views" of the FO Tree. IOW, getText for an area might look like:

{{{ String getText() { //maybe return char[] instead -- you getthe idea

The Area has stored the starting place and size of the text, which exists only in the parent FO. This goes against our current philosophy of a self-contained Area Tree, but once we get the FO Tree serialized when needed that concern should go away. Then, (someday) you can put a GUI on top of the Area Tree, and, (someday) if you can find a way to make the FO Tree simply be a view of the semantic XML document (XSLT is pretty one-way), you can have a nice GUI editor for your XML. Way, way off topic, pie-in-the-sky. But I think it is OK to think in these terms when your building the smaller pieces.

{{{ >> In the

Interesting, but sounds like a chunk of work, esp. with our Forrest workflow. I hope that if we get all of these foundation pieces built, it will by then just be easier to go make the PCL renderer do it. {{{ >> 4. If accepted, this would be a great project for

Fair enough. Also, we need to make sure we handle Peter West's gotchas in this scheme, i.e. the situations where we pass through an "I don't know"value that will be resolved in layout.

Victor Mote

Response (Jeremias Maerki)

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.

Response (John Austin)

After thinking about the proposal, I'm not sure it solves anything.

There are two aspects to the redesign of Property handling in FOP.

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

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.

PropertiesRedesign (last edited 2009-09-20 23:32:41 by localhost)