On Oct 19, 2007, at 13:32, Vincent Hennebert wrote:

Andreas L Delmelle wrote:
On Oct 18, 2007, at 19:23, Vincent Hennebert wrote:
<snip/>
I think I see your point. Basically you’re proposing a push method (a LM notifies its parent LM that it has a break-before) while mine is a pull
method (a LM asks its children LMs if they have break-before).

Yep, although it would not be the LM but rather the FO that pushes the
break-before upwards to its parent if it is also the first child. The

Sure, of course. BTW, that may be a dumb question, but: how does a FO
know that it is the first child of its parent? AFAICT there’s no such
information in the FObjs.

Oh, that's pretty easy. Each FObj has a firstChild member, so the most straightforward idiom for this would be something like:

if (parent.firstChild == null) { ... } //if checking before addChildNode() has been called if (this == parent.firstChild) { ... } //if you check after addChildNode() has been called

Which means that an object would blindly
notify its parent that it has a break, and that would be up to the
parent to figure out whether it should take it into account or not.
Would be a bit overkill, wouldn’t it?

No, it wouldn't.

Or at least: depends on what you mean exactly by 'overkill'?

LMs would largely continue to work as they do now, except that under a certain set of conditions, they don't need to check the outside anymore: only take into account the forced break on its own FO. If there is none,
then no need to recursively check for first descendants having forced
breaks.

Of course, but I’m concerned about spreading code relevant to the same
functionality over several places of the codebase.

That will always be a concern. If you separate some related logic into YAUC[*], the same reasoning applies, IMO. Even if the logic is contained in a separate class, you still have to look at/know of the other classes.

[*] (yet-another-utility-class)

<snip />
Keeping in mind the above mentioned idea of triggering layout sooner, if
we can guarantee that the layoutengine always receives complete rows,
then the table-layout job should become a bit simpler in the general
use-case, while still not adding much complexity in trickier, more
exotic cases, like:
//table-cell/block[position() > [EMAIL PROTECTED]'page']

That one triggers a break /inside/ the table-row, not before it.

What I meant precisely... and, in practice, this will occur far less often than forced breaks on the first block in a cell, IIC.

Anyway, at a given LM level the work to do looks simple enough to me.


especially where the cell's column-number corresponds to the highest
column-number.

Triggering layout sooner is the only way we are ever going to get FOP to
accept arbitrarily large tables, without consuming massive amounts of
heap. A 'simple' grid of 5 x 500 cells generates +5000 FONodes
(table-cells must have at least one block each) that stay in memory
until the page-sequence is completely finished. I wonder how many
break-possibilities that generates... :/

Like said above, I don’t think anything in my approach prevents that
from happening.

Indeed not. Did I say anything else?

A matter of taste, probably, but I think I’d prefer the pull method: the LM performs requests to the appropriate children LMs exactly when and if
needed.

The only thing an LM should initially pull/request from its children,
AFAIU, is a list of elements, given a certain LayoutContext.
When composing its own element list, an LM should ideally be able to
rely on the lists it receives from its children. Then add/delete/ update
elements and (un)wrap, depending on context that is unknown or
irrelevant to the child.

That one I don’t quite agree with. Although I thought of it too on
a first step. I think it’s more complicated to play with a list of
elements, try and get the first one from children if any, create a new
one if necessary, change the break context (column, page) if needed,
etc., rather than simply request the applicable children LMs for their
break-before values. And again, in the case of tables that means that
the merging algorithm needs to deal with many possibilities of break
elements to occur. That’s really not its job I think.


That may simplify code as well (and improve its readability) as
some form of pull method is necessary anyway (the
mustKeepWithPrevious/WithNext/Together methods).

Keeps are a different story indeed. Big difference is that keeps have
strengths, and breaks do not.

Yes, but keeps and breaks are handled at the same place, mainly, when
a LM considers the stacking of children LMs (BlockLM, for example). And
the treatment is very similar.

The point is that the layoutengine/-algorithm can focus on the keeps, since the breaks would have been 'normalized' (since it is very easy to do so; for keeps this much less straightforward, since the strengths need to be considered as well, so that might indeed lead to unnecessary overhead when done too early)

<snip />

I wouldn't really see this as a problem. The related methods will never
be called, unless there is a flaw in our logic[*]. To stress the fact
that they serve no purpose there, we could add overrides that always
return false.

That really looks like bad design to me. If some methods don’t apply to
an object then that object shouldn’t inherit the related
class/interface.

I don't see this as bad design, just a few subclasses for which the inherited methods are useless/not applicable. That will happen in virtually any context. Reality is /very/ badly designed. Alas, no developer to take the blame for that. ;-)

Seriously, as you said, to a great extent this is a matter of taste.

<snip />
That's a special case, since in principle a graphic does not itself
consist of more layout-objects that need to be stacked. To the
layoutengine, a graphic is simply a monolithic box. Graphics are inline by definition nonetheless, so it could be InlineStackingLM with the same
reservations as for FlowLM and StaticContentLM, but for other methods
(the actual 'inline-stacking' can be considered to be delegated to the
producer of the graphic, here).

So it’s not stacking, but stacked. Might make sense to introduce that
concept, actually.

Mmmmno, I think...
What I mean is: from the layoutengine's point-of-view, the elements of the graphic don't matter. If you include SVG, FOP calls on Batik, passing a reference to the SVG and the viewport dimensions. With a little imagination, you could say that Batik 'stacks' the graphic's elements properly (compliant to the SVG Rec). That is not a concern for a GraphicLM like it is for an InlineLM.

To sum up, my main concern is to find code for a same functionality at
several places of the codebase. Some form of treatment is necessary at
the LM level anyway, so why not just put all the code there? It may also
be good to keep FO tree building code as much independent as possible
from the layout code. Simpler, easier to understand, easier to debug,
easier to replace a component which another one, etc. The collaborative
approach you’re proposing looks interesting, but for practical reasons
it may be best to keeps things separated. The codebase is quite large
and it’s difficult to have a detailed understanding of all its parts.
That might be good to be able to concentrate on just one part. Easier
for newcomers, too.


WDYT?

Good enough for me. I certainly did not mean to keep you from going about it. As long as it's an improvement when compared to the current situation, I don't really have /strong/ feelings on how it /should/ be done.


Cheers

Andreas

Reply via email to