Closed Bug 10207 Opened 25 years ago Closed 24 years ago

vertical-align: baseline not implemented for table cells

Categories

(Core :: Layout: Tables, defect, P2)

defect

Tracking

()

VERIFIED FIXED

People

(Reporter: dbaron, Assigned: buster)

References

Details

(Keywords: css2, testcase, Whiteboard: [TESTCASE] blocking mathml)

Attachments

(8 files)

vertical-align: baseline is not yet working on tables.  Test case to be
attached.  Also see bug 2886 for other examples, except you can't see the
difference there...
Note that you should be sure the testcase works with the window very narrow so
the cells carry to multiple lines.  Probably, more complicated testcases are
needed.

Also, the rules governing this weren't formally given until CSS2, even though
the properties existed in CSS1.  So this isn't technically a CSS1 bug.
Status: NEW → ASSIGNED
Target Milestone: M12
Whiteboard: [TESTCASE]
Marking [TESTCASE].
Many further tests for this are in
http://www.fas.harvard.edu/~dbaron/css/test/sec170503 (which crashes in builds
before (and possibly including) the August 10 build).

This page also tests that the values 'sub', 'super', 'text-top', 'text-bottom'
(see CSS2 17.5.3) and length and percentage values (see
http://lists.w3.org/Archives/Public/www-style/1999Jul/0083.html ) should be
treated as baseline, not top as they are currently treated.  Once 'baseline' is
implemented, this is trivial to fix.
Bug 2886 (for which the fix is attached) also causes problems on the above test
page.
mass move to m14.
This bug is currently a severe hindrance to the progress of MathML. That's why
I have increased the severity to critical. By default, all MathML alignments 
involve the baseline. Expressions are difficult do decipher if their alignments 
are wrong. Moreover, we cannot properly layout matrices, arrays, commutative 
diagrams and such.

Chris, I don't know when you were planning to address this bug. If it is not 
in your "urgent" list, I would really like to start helping to get it fixed.
If you provide me with some directions as to where to look at, I could try
to investigative further. Please help.

What is needed:
- each cell should cache its ascent (presently, they don't cache their ascent)
- each row should cache the max-ascent amongst all cells which have 
vertical-align: baseline (presently each row is only caching the max height
of cells).

From my reading of the code, it is not trivial to get the ascent out of the 
innards of layout. Acccording to CSS, the "ascent" of the cell should be the 
ascent of the first linebox on that cell. But this information seems to be
lost in the entrails of layout.

PS: I will probably submit other issues to your consideration later on. But
for now, this is the most urgent thing that the MathML effort needs help for. 
Severity: normal → critical
The stumbling block is that the nsTableCellFrame code has no way to know the 
ascent of its content. Layout doesn't seem to care about this information. If it
is possible to export that information when the table row code is reflowing its
children, then the cell can cache its ascent and the table row code can later
pass the max of the ascents when it is doing VerticallyAlignChild().
rbs, I've asked the folks who are working on the block code how to get the 
baseline of the table cell's block. If it isn't being set, I'm hoping it won't 
be difficult for the block code to set it, since lines understand how to align 
text on baselines and the block's baseline should just be the baseline of its 
first line.
Apparently, the block code is not yet setting the ascent. Printing aDesiredSize 
in the table cell code gives invariably zero for the descent. But indeed, if the 
block code properly set the ascent, then getting the vertical-align on the 
baseline should be fine.
Troy said that ascent of the block should be the baseline. In the following 
html, the ascent of the cell's block during reflow is always equal to its 
desired height. Reassigning to Kipp and CCing the block busters (pun intended, 
Steve).

<table border width=100>
 <tr>
  <td>some wrapped text some wrapped text some wrapped text some</td>
 </tr>
</table> 
Assignee: karnaze → kipp
Status: ASSIGNED → NEW
Bulk moving [testcase] code to new testcase keyword. Sorry for the spam!
Keywords: testcase
Yes, Chris. Agreed. The ascent is (presently) always set to the height (and 
that's why the descent is zero). 
Block folks, any comments/good news? Is this a demaning job for you?
Fixing this will require that the block frame cache the first line's "ascent" 
information, because when doing an incremental reflow we'll need to recover that 
information.

It's not a large job, but it's a days worth of work, and I know Steve has more 
urgent things to deal with like the compatibility problem with <FONT size=1> 
problem. Nisheeth is working on finishing up reflow command coalescing
Keywords: beta1
Severity: critical → blocker
Keywords: 4xp, css2
Whiteboard: [TESTCASE] → [TESTCASE] blocking mathml
As MathML QA, I'm switching from critical to blocker, since it is blocking 
MathML work. As CSS QA, I'm flagging this as CSS2 compliance. 

I'm also marking this 4xp as IE5 does this correctly (!).
adding beta1 keyword to potential beta blockers
Removing beta1 keyword. Come on guys, this is not a beta1 blocker. We have 
hundreds of bugs, real compatibility issues to resolve, and enough performance 
issues to keep us all busy for many months
Keywords: beta1
here's the deal:  as I grovel through the block/inline reflow code, I'll keep 
this in mind. If it just falls out, I'll do it.  But I can't commit to it until 
M16.  I haven't been working with the code long enough to know just how big this 
job might become.  Sorry to be vague, but it's all I can offer today.  If 
someone else is interested in working on this, I'd be happy to guide them as 
best I can.
Priority: P3 → P2
Target Milestone: M14 → M16
Making summary clearer.
Summary: vertical-align: baseline not implemented → vertical-align: baseline not implemented for table cells
mine! mine mine mine!  all mine!  whoo-hoo!
Assignee: kipp → buster
*** Bug 32436 has been marked as a duplicate of this bug. ***
sorry, there's no way I can get this in for M16.  Hoping for M16
Target Milestone: M16 → M17
OK Steve, I can see that there is a lot of pressure in the air...

I have now managed to get the ascent of the first line, and it gets
propagated quite well out of the block reflow operation up into the table-cell.
It has turned that it is no necessary to worry about incremental reflows since
the first line is either clean (in which case the ascent doesn't change),
or it is dirty (in which case it is reflowed anyway so that the ascent
is recomputed by the reflow code).

I am attaching the patch. There is one thing that is still unclear
to me regarding what the code is doing when there is these line-height and
min/max values. Perhaps, the CSS experts (David and Ian) would have more 
insights as to what to do?

The other part in the table-cell is a bit circonvoluted since the
baseline can change the height of the cell... I am not yet done with that
table-cell part yet.
Just attached a screenshot of what I got so far. Recovering state
for incremental reflow and the fact that a rowgroup can fire ReflowCellFrame() 
are not yet tuned up.

[The ascent should stay the same, no matter what happens when applying the 
line-height and min-max values to the block frame, right? In this case,
eveything is fine with the block frame code then.]
While testing the testcase attached on bug 32436, I have observed that the
diff that I attached for the block code doesn't take care of special cases
where the code path executed by the block code does not involve
VerticalAlignFrames(). This happens, for example, when the first child
of <td> is a block, as in <td><div>...</div></td>.

I have made a further change to test the case where mLines->IsBlock(),
and fetch the ascent of mLines->mFisrtChild. Unfortunately, this still
doesn't fix the problem. Any clues as to remaining missing link? I will
be attaching a screenshot to demonstrate the problem.
Adding chris to the Cc list so that he may have a look at the table code.
(I used cvs diff -u10 to produce a wider context and have kept everything
in #ifdef MOZ_MATHML for now to ease development/identification).
Checked-in
Note: Although the code was reviewed by buster and karnaze, it is still in 
#ifdef MOZ_MATHML and so 'vertical-align: baseline' is still not available for
normal HTML documents, pending QA after M16.
I suggest we check this in as soon as beta2 ships
Pursuing further the issue I mentioned on 2000-05-30 06:26, I have observed
that the problem is due to the fact that the dectection of the case where the
first child of <td> is a block was insufficient.

If on the test case, I remove all the whitespace/blank-lines before <div>,
i.e, if 

<td> 
  <div> ... </div>
</td>

becomes

<td><div>
       ... </div>
</td>

then the code works as expected. I will try to attach a screenshot if I can.
(On the screenshot, all the <td><div>...</div></td> are represented
by red rectangles inside green rectangles. Of note is the fact the
baselines from inside the red <div>s are aligned properly.)

Therefore, it is not enough to just check

+    if (mLines && mLines->mFirstChild && mLines->IsBlock()) {

because the real first line may be something else.
Index: nsBlockFrame.cpp
===================================================================
RCS file: /cvsroot/mozilla/layout/html/base/src/nsBlockFrame.cpp,v
retrieving revision 3.389
diff -u -r3.389 nsBlockFrame.cpp
--- nsBlockFrame.cpp	2000/06/14 23:15:58	3.389
+++ nsBlockFrame.cpp	2000/06/22 06:20:50
@@ -2330,11 +2330,20 @@
     aMetrics.ascent = aMetrics.height;
     aMetrics.descent = 0;
 #else
-    if (mLines && mLines->mFirstChild && mLines->IsBlock()) {
-      // mAscent is not yet set because we didn't call VerticalAlignFrames()
-      // on mLines. So we need to fetch the ascent of the first child of mLines
+    // Need to check for special cases where mAscent is not yet properly set.
+    // There are two cases to consider: when the first line is a block, or
+    // when the first line is empty and is followed by a second line that
+    // is a block (e.g., <td>\n<div>). In these two cases, we need to fetch
+    // the ascent of the first child of the line.
+    nsLineBox* line = mLines;
+    // see if this first line is empty. if so, move on to the second line
+    if (line && (0 == line->GetHeight())) {
+      line = line->mNext;
+    }
+    // see if the line contains a block. if so, fetch the ascent of the block
+    if (line && line->mFirstChild && line->IsBlock()) {
       nsBlockFrame* bf;
-      nsresult res = mLines->mFirstChild->QueryInterface(kBlockFrameCID, 
(void**)&bf);
+      nsresult res = line->mFirstChild->QueryInterface(kBlockFrameCID, 
(void**)&bf);
       if (NS_SUCCEEDED(res) && bf) {
         mAscent = bf->GetAscent();
       }

Change to account for the special cases.
Need to fill r=? before heading to waterson!
Do you want to initialize mAscent to 0 in case there are no lines?  Or is it 
somehow set correctly already (in PlaceLine?)?  Also, do you want to change the 
way mAscent is set in nsBlockFrame::PlaceLine to correspond to these changes?  
(Also, I assume the comment you removed about VerticalAlignFrames() not having 
been called was wrong, since you have to call VerticalAlignFrames before you 
know what the ascent is.)
> Do you want to initialize mAscent to 0 in case there are no lines?  Or is it 
> somehow set correctly already (in PlaceLine?)?
buster, do you want to chime in here? None of the other data members of the
block frame (like mLines itself) are initialized. Is there a zeroing new
somewhere in the hierarchy? Or should I put 'mAscent = 0' in the constructor
to account for this special case that dbaron mentions?

>  Also, do you want to change the 
> way mAscent is set in nsBlockFrame::PlaceLine to correspond to these changes? 
> (Also, I assume the comment you removed about VerticalAlignFrames() not having 
> been called was wrong, since you have to call VerticalAlignFrames before you 
> know what the ascent is.)

There are some code-paths that don't lead to VerticalAlignFrames(), so the
comment wasn't wrong. Perhaps I should put that comment back...
nsBlockFrame::PlaceLine() is fine. If we ever get there, that will mean
that mLines is not a block, so mAscent will be set properly.
If we don't get there (or if the first line was empty), then the
final adjustments that I added will take care of setting mAscent properly.
> (... since you have to call VerticalAlignFrames before you 
> know what the ascent is.)
Yep, that's right. But in the case of a containing block, mAscent just
needs to 'bubble up'. (In this case, VerticalAlignFrames() would have called 
in the inner-most block frame for which mLines wasn't a containing block).
BTW, after enabling this patch, it will remain one important piece of
the puzzle before this bug is nailed down for HTML/CSS tables. The remaing
case is that of <td> <table> ... </table> </td>. This other special case (but
frequent case) won't work because the table code is not yet honoring the ascent.
Hence the table code still needs some further tuning so that it returns its
ascent (i.e., the ascent of its first row).
rbs, should these changes get turned on now?  (Since it looks like, from
previous comments, you have an r= but not an a=, adding approval keyword.)
Keywords: approval
Now got a=waterson. Will check-in once I have updated my tree to the tip with
the latest flood of changes that have followed the branch.
Checked-in. Code to support valign=baseline is now active in default builds.
dbaron, your tests with invalid length and percentage values will not work as
you documented because the Style System layer is filtering invalid length and
percentage values and mapping the corresponding valign to a default or whatever
is inherited from the parent (i.e., middle in most case).

The only invalid values that reach the table code are 'sub', 'super',
'text-top', 'text-bottom', which the code will remap to baseline as per 
your comments of 1999-08-10 14:12.
rbs:  Are you sure it's not coming through from the style system?  Isn't it just
a bug in nsTableCellFrame::VerticallyAlignChild - the "default:" in the case
statement should be the same as BASELINE instead of the same as MIDDLE, right?
Yep. When I was unit-testing the code, my printfs couldn't catch length and 
percentage values and I had a quick look at the Style System (though I don't 
remember the section). In fact, the "default:" in the case is not effective 
because the verticalAlignFlags used in the switch is defaulted to BASELINE
earlier, for any value other than top, middle, bottom. (the same goes for the
HasVerticalAlignBaseline() function that are queried by parent frames).
What's the state of this bug?  According to:
Additional Comments From rbs@maths.uq.edu.au 2000-07-28 02:56
sounds like a fix was checked in.
But it's still assigned to me and marked "NEW", with no nsbeta specification.
Need an update, please.  And thanks for carrying the torch on this while I was 
out!
Yes the fix is in, and is gaining some maturity. So the bug can be closed.
But for things to work right, all frames should honor the ascent information.
Currently, <table> is the remaining HTML frame that is not honoring that 
information, and 
   <td valign="baseline"> <table>...</table> </td>
doesn't mean anything.

So the table code should return the ascent of its first row. But this is a 
different problem and should probably be filed as a separate bug. dbaron
also asked for clarifications about the mapping of erroneous valign values.
This is a separate issue (from the Style System) and the fix is not going to be
affected.
Verified fixed in MacOS 9.0.4 build 2000-09-04-08, Linux  2000-09-06-08, and Win 
98 2000-09-06-08.
Actually folks, I take that back.  baseline works in most places but not in <col> 
or <colgroup>.

Testcase URLs:
http://slip/projects/marvin/html/col_valign_baseline.html
http://slip/projects/marvin/html/colgroup_valign_baseline.html
Ummm...  why *should* it work for col or colgroup?  CSS properties inherit
through the document tree.
This bug should be marked fixed. Valign is working but, as stated, not for COL 
and COLRGROUP (and HTML attribute for these elements). However, that problem is 
written up 12 bug #915.
I actually ran into the problem with baseline info not propagating out of nested
tables in a real world page yesterday. :-/

Is there a bug on that issue? Chris?
Status: NEW → RESOLVED
Closed: 24 years ago
Resolution: --- → FIXED
fixed, per chrid d's comment.  thanks, chris.
this bug is a request for support, and we support it now.  if there are bugs
with specific aspects of that support, please open a new bug with a focused test
case.
Verified fixed.
Status: RESOLVED → VERIFIED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: