> -----Original Message-----
> From: Jeremias Maerki [mailto:[EMAIL PROTECTED]
(OK, apologies for my alias turning up... Completely unintended.
here's the remainder of the response. Other comments, much longer than the
> On 17.05.2005 23:24:55 Andreas L. Delmelle wrote:
> > The current fact that there's an explicit reference to the
> > border-*styles* in an essentially layout-related class...
> > Well, somehow it does not sit completely right with me --could
> > be a matter of taste, but IMO, layout needs to concern
> > itself only with sizes...
> That was a natural outcome since there are certain specialities in the
> "collapse" model. If you look closely there's a little special case
> where the collapsed border between two cells has the same style and
> width but potentially different colors. If you follow through the rules
> 1 to 5 you end up in rule 5 "solid 0.5pt red" specified in one cell,
> "solid 0.5pt green" in the neighbouring cell. See
> table-border-collapse1.xml in testcases for an example. There's no rule
> that says how to decide which of the two wins.
Very good point! Still, I would argue in that case that the layout engine
only needs to know that the border is going to be 0.5pt wide in case of no
breaks/spans. It is, strictly speaking, only when rendering the borders that
the implementation has to know for sure which colour to use.
If we are at liberty to determine that rule ourselves, I would obviously
feel much for an approach like 'before/start cell wins' or 'after/end cell
loses', and this as early in the process as possible. That would be very
convenient. Another idea is to use the color value to decide, or if you
really want a nasty solution that is bound to turn up in a bug report: XOR
the color values. "A bug?? Shame on you for having no sense of humour! Read
the CSS Spec and study your table-border source very closely. It's *all* in
> Furthermore, looking at those rules again, you will see that the style
> is used to determine winners, styles having implicit precedence values.
Yes, but this could also be done when creating the FObjs --the styles map to
a numeric constant anyway. If we place them in the right precedence-order in
the Constants interface(*), we might not even need to assign precedence
values in a separate step. We'd directly use the integer value they map
> That's why you need them aside from having to pipe such information
> through to the addAreas() stage where the traits are set.
So, I would seem to disagree? Up until the 'aside from': the _latter_ part
is obviously necessary...
> If you're talking about the border resolution you can't avoid looking at
> the style, too. After that, in the table stepper, only the widths are
Getting hotter, I feel it! :-)
> I still think you're not quite where I am. Take the following methods:
> - TableContentLayoutManager.resolveNormalBeforeAfterBordersForRowGroup()
> - TableRowIterator.resolveStartEndBorders()
> These are the two isolated places where the border resolution for
> non-break cases are done. After that, the table stepper simply fetches
> the table widths from the grid units to do the right calculations.
... and a large part of what happens in the above two methods --in the
background-- would already be dealt with in the FOTree, so the *only* parts
of the code remaining there would be dealing with the break-cases and the
span-cases. Very layout-specific stuff indeed!
Quite simply put: if a GridUnit corresponds with exactly one TableCell, in a
collapsing model, the *only* border-widths you'd really need to take into
account would be those of its TableCell. The rest I see as ruled out at that
point, *unless* in the following three cases
- after-border => still need to compare that to the Cell/GridUnit
- row/column-spans => check the appropriate TableRow/TableColumn for start-
- page-breaks => check the TableBody/-Header/-Footer for the before- or
> The part where I gave up for now was how exactly to handle the
> border resolution for break situations and how to bring the values into
> the overall calculation.
Resolution to be done by layout in the break-situations would come down to:
* First, compare after-border with GridUnit below.
This step is always taken (see above) and yields
the after-border in no-break situation.
The dominant border is used in the following step.
* Then, only before- or after-borders matter here, so
either the current GridUnits' TableCell
(possibly corrected through the first step)
or the TableBody/-Header/-Footer
will yield the right border-width.
Resolution between TableCell and TableRow would already have been handled in
the FOTree. Same goes for the resolution between TableColumn and
TableBody/-Header/-Footer. If the order of fo:table-header, -footer
and -body is enforced by the Rec --so, header and footer *have* to appear
before body in the FO source--, then the same could be done for the
after/before-border pairs between header/footer and body.
Which would make the related layout code far less demanding for the
For the real 'collapsing' mechanism, we'd have to point them to the FObjs
and the Properties.
> I get the impression that you're trying to solve a problem that is
> already solved, but if you find a better solution (i.e. one that makes
> the code faster and/or less memory consuming and/or clearer/easier) then
> I'm all for it. I've taken the straight-forward approach creating a data
> structure (grid units in EffRows) where I have all the information
Which flows naturally from the fact that your coding efforts these last
couple of months have been directed mainly towards the layout engine, I hear
you loud and clear!
But I got to thinking: part of the difficulty and main source of confusion
may exactly be that you're trying to handle *all* of the resolution in
layout... see above (?)
Maybe, approaching border-resolution *not* as a layout-problem can make
those parts of it that *do* need to be handled by layout a bit easier... and
who knows, maybe even more efficient. I'd have to gather more details about
the two approaches to say that for sure --ultimately depends on the
complexity of the table definition, of course....
> Joke aside, if you see a way to make the current approach considerably
> faster and less wasteful, then yes, it's worth digging deeper. But
> before you do that, make sure you understand what the collapsing model
> together with break conditions have as consequence for the table stepper.
Yes, the stepper will be the very next thing to look at, but this was more
of a 'first things first' sanity check... Up to here, I get the impression
that what's currently in my head will turn out to be very beneficial to the
rest of the process.
> On the paper (i.e. in our example on the Wiki) the problem is already
> solved. What I had trouble with was not the border resolution, but the
> step after that. I guess it should be functionality before speed,
> especially when most of the issues are already solved in some way.
Functionality indeed, but most importantly, functionality where it belongs.
If all goes well, speed and efficiency should necessarily follow from that.
[(*) = OT: instead of non-contextually sorting the integer values according
to the alphabetical name of the constants in question, which only _looks_
nice code-wise, but seems to serve no other purpose. What does it mean
'EN_DOTTED' is 'enum constant number/value 36'? When/where is that
information ever going to be relevant? Maybe this line of thinking can also
be applied to other constants...? Admitted, some constants can pop up in a
few different types of situations, so there, we'd need to very careful when
establishing relationships between them at a level so global as the
interface, but in this particular case the keywords are so specific to the
context of border-style, there would be no harm in reserving a set of ints
starting at N and define the constants as:
// Border style constants
EN_INSET = N;
EN_GROOVE = EN_INSET + 1;
EN_SOLID = EN_DASHED + 1;
EN_DOUBLE = EN_SOLID + 1;
and we can conveniently compare two border-style constants to see which one
is 'larger' --in any class that implements the interface, at whatever stage
of processing. There may be other scenarios where such functionality would
be useful... and may avoid having to locally re-establish this type of
relationship between constants in classes implementing Constants.]