b=494901 textbox misaligned when using align=baseline r=dbaron

--HG--
extra : rebase_source : 6322f30a5eabd9c4662a1cc817dde8abaecacaaa
This commit is contained in:
Karl Tomlinson 2009-10-22 13:11:25 +13:00
Родитель 1207213155
Коммит 790c69b995
4 изменённых файлов: 146 добавлений и 101 удалений

Просмотреть файл

@ -10,6 +10,7 @@ HTTP(..) == input-text-baseline-1.html input-text-baseline-1-ref.html
HTTP(..) == input-text-centering-1.xul input-text-centering-1-ref.xul
HTTP(..) == text-control-baseline-1.html text-control-baseline-1-ref.html
== input-text-dynamic-height-1.xul input-text-dynamic-height-1-ref.xul
== textbox-align-baseline-1.xul textbox-align-baseline-1-ref.xul # bug 494901
== radio-label-dynamic.html radio-label-dynamic-ref.html
== out-of-bounds-selectedindex.html out-of-bounds-selectedindex-ref.html # bug 471741

Просмотреть файл

@ -934,8 +934,10 @@ nsBoxFrame::DoLayout(nsBoxLayoutState& aState)
aState.SetLayoutFlags(0);
nsresult rv = NS_OK;
if (mLayoutManager)
if (mLayoutManager) {
CoordNeedsRecalc(mAscent);
rv = mLayoutManager->Layout(this, aState);
}
aState.SetLayoutFlags(oldFlags);

Просмотреть файл

@ -241,8 +241,6 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
nsBoxSize* boxSizes = nsnull;
nsComputedBoxSize* computedBoxSizes = nsnull;
nscoord maxAscent = aBox->GetBoxAscent(aState);
nscoord min = 0;
nscoord max = 0;
PRInt32 flexes = 0;
@ -415,33 +413,26 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
if (childRect.height > clientRect.height)
clientRect.height = childRect.height;
// |x|, |y|, |nextX|, and |nextY| are updated by this function call. This call
// also deals with box ALIGNMENT (when stretching is not turned on).
ComputeChildsNextPosition(aBox,
x,
y,
nextX,
nextY,
childRect,
originalClientRect,
childBoxSize->ascent,
maxAscent);
// Either |nextX| or |nextY| is updated by this function call, according
// to our axis.
ComputeChildsNextPosition(aBox, x, y, nextX, nextY, childRect);
// Now we update our nextX/Y along our axis and we update our x/y along the opposite
// axis (since a non-stretching alignment could have caused an adjustment).
// Now we further update our nextX/Y along our axis.
// We also set childRect.y/x along the opposite axis appropriately for a
// stretch alignment. (Non-stretch alignment is handled below.)
if (frameState & NS_STATE_IS_HORIZONTAL) {
if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
nextX += (childBoxSize->right);
else
nextX -= (childBoxSize->left);
childRect.y = y;
childRect.y = originalClientRect.y;
}
else {
if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
nextY += (childBoxSize->right);
else
nextY -= (childBoxSize->left);
childRect.x = x;
childRect.x = originalClientRect.x;
}
// If we encounter a completely bogus box size, we just leave this child completely
@ -478,14 +469,25 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
layout = PR_FALSE;
}
nsRect oldRect(child->GetRect());
// Non-stretch alignment will be handled in AlignChildren(), so don't
// change child out-of-axis positions yet.
if (!(frameState & NS_STATE_AUTO_STRETCH)) {
if (frameState & NS_STATE_IS_HORIZONTAL) {
childRect.y = oldRect.y;
} else {
childRect.x = oldRect.x;
}
}
// We computed a childRect. Now we want to set the bounds of the child to be that rect.
// If our old rect is different, then we know our size changed and we cache that fact
// in the |sizeChanged| variable.
nsRect oldRect(child->GetRect());
PRBool sizeChanged = PR_FALSE;
child->SetBounds(aState, childRect);
sizeChanged = (childRect.width != oldRect.width || childRect.height != oldRect.height);
PRBool sizeChanged = (childRect.width != oldRect.width ||
childRect.height != oldRect.height);
if (sizeChanged) {
// Our size is different. Sanity check against our maximum allowed size to ensure
@ -570,23 +572,8 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
}
// If the child resized then recompute its position.
ComputeChildsNextPosition(aBox,
x,
y,
nextX,
nextY,
newChildRect,
originalClientRect,
childBoxSize->ascent,
maxAscent);
ComputeChildsNextPosition(aBox, x, y, nextX, nextY, newChildRect);
// Only update the variable in the opposite axis (since this is only here to deal with
// a non-stretching ALIGNMENT)
if (frameState & NS_STATE_IS_HORIZONTAL)
newChildRect.y = y;
else
newChildRect.x = x;
if (newChildRect.width >= margin.left + margin.right && newChildRect.height >= margin.top + margin.bottom)
newChildRect.Deflate(margin);
@ -676,6 +663,11 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
}
}
// Perform out-of-axis alignment for non-stretch alignments
if (!(frameState & NS_STATE_AUTO_STRETCH)) {
AlignChildren(aBox, aState, &needsRedraw);
}
// Now do our redraw.
if (needsRedraw)
aBox->Redraw(aState);
@ -879,7 +871,6 @@ nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBox
aMaxSize = maxSize.height;
}
currentBox->ascent = ascent;
currentBox->collapsed = collapsed;
aFlexes += currentBox->flex;
@ -934,77 +925,126 @@ nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBox
void
nsSprocketLayout::ComputeChildsNextPosition(nsIBox* aBox,
nscoord& aCurX,
nscoord& aCurY,
const nscoord& aCurX,
const nscoord& aCurY,
nscoord& aNextX,
nscoord& aNextY,
const nsRect& aCurrentChildSize,
const nsRect& aBoxRect,
nscoord childAscent,
nscoord aMaxAscent)
const nsRect& aCurrentChildSize)
{
// Get the position along the box axis for the child.
// The out-of-axis position is not set.
nsFrameState frameState = 0;
GetFrameState(aBox, frameState);
nsIBox::Halignment halign = aBox->GetHAlign();
nsIBox::Valignment valign = aBox->GetVAlign();
if (IsHorizontal(aBox)) {
// Handle alignment of a horizontal box's children.
// horizontal box's children.
if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
aNextX = aCurX + aCurrentChildSize.width;
else aNextX = aCurX - aCurrentChildSize.width;
else
aNextX = aCurX - aCurrentChildSize.width;
if (frameState & NS_STATE_AUTO_STRETCH)
aCurY = aBoxRect.y;
else {
switch (valign)
{
case nsBoxFrame::vAlign_BaseLine:
aCurY = aBoxRect.y + (aMaxAscent - childAscent);
break;
case nsBoxFrame::vAlign_Top:
aCurY = aBoxRect.y;
break;
case nsBoxFrame::vAlign_Middle:
aCurY = aBoxRect.y + (aBoxRect.height/2 - aCurrentChildSize.height/2);
break;
case nsBoxFrame::vAlign_Bottom:
aCurY = aBoxRect.y + aBoxRect.height - aCurrentChildSize.height;
break;
}
}
} else {
// Handle alignment of a vertical box's children.
// vertical box's children.
if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
aNextY = aCurY + aCurrentChildSize.height;
else
aNextY = aCurY - aCurrentChildSize.height;
}
}
if (frameState & NS_STATE_AUTO_STRETCH)
aCurX = aBoxRect.x;
else {
PRUint8 frameDirection = GetFrameDirection(aBox);
switch (halign)
{
case nsBoxFrame::hAlign_Left:
if (frameDirection == NS_STYLE_DIRECTION_LTR)
aCurX = aBoxRect.x;
else
aCurX = aBoxRect.x + aBoxRect.width - aCurrentChildSize.width;
break;
case nsBoxFrame::hAlign_Center:
aCurX = aBoxRect.x + (aBoxRect.width/2 - aCurrentChildSize.width/2);
break;
case nsBoxFrame::hAlign_Right:
if (frameDirection == NS_STYLE_DIRECTION_LTR)
aCurX = aBoxRect.x + aBoxRect.width - aCurrentChildSize.width;
else
aCurX = aBoxRect.x;
break;
}
void
nsSprocketLayout::AlignChildren(nsIBox* aBox,
nsBoxLayoutState& aState,
PRBool* aNeedsRedraw)
{
nsFrameState frameState = 0;
GetFrameState(aBox, frameState);
PRBool isHorizontal = (frameState & NS_STATE_IS_HORIZONTAL) != 0;
nsRect clientRect;
aBox->GetClientRect(clientRect);
NS_PRECONDITION(!(frameState & NS_STATE_AUTO_STRETCH),
"Only AlignChildren() with non-stretch alignment");
// These are only calculated if needed
nsIBox::Halignment halign;
nsIBox::Valignment valign;
nscoord maxAscent;
PRBool isLTR;
if (isHorizontal) {
valign = aBox->GetVAlign();
if (valign == nsBoxFrame::vAlign_BaseLine) {
maxAscent = aBox->GetBoxAscent(aState);
}
} else {
isLTR = GetFrameDirection(aBox) == NS_STYLE_DIRECTION_LTR;
halign = aBox->GetHAlign();
}
nsIBox* child = aBox->GetChildBox();
while (child) {
nsMargin margin;
child->GetMargin(margin);
nsRect childRect = child->GetRect();
if (isHorizontal) {
const nscoord startAlign = clientRect.y + margin.top;
const nscoord endAlign =
clientRect.YMost() - margin.bottom - childRect.height;
nscoord y;
switch (valign) {
case nsBoxFrame::vAlign_Top:
y = startAlign;
break;
case nsBoxFrame::vAlign_Middle:
// Should this center the border box?
// This centers the margin box, the historical behavior.
y = (startAlign + endAlign) / 2;
break;
case nsBoxFrame::vAlign_Bottom:
y = endAlign;
break;
case nsBoxFrame::vAlign_BaseLine:
// Alignments don't force the box to grow (only sizes do),
// so keep the children within the box.
y = maxAscent - child->GetBoxAscent(aState);
y = NS_MAX(startAlign, y);
y = NS_MIN(y, endAlign);
break;
}
childRect.y = y;
} else { // vertical box
const nscoord leftAlign = clientRect.x + margin.left;
const nscoord rightAlign =
clientRect.XMost() - margin.right - childRect.width;
nscoord x;
switch (halign) {
case nsBoxFrame::hAlign_Left: // start
x = isLTR ? leftAlign : rightAlign;
break;
case nsBoxFrame::hAlign_Center:
x = (leftAlign + rightAlign) / 2;
break;
case nsBoxFrame::hAlign_Right: // end
x = isLTR ? rightAlign : leftAlign;
break;
}
childRect.x = x;
}
if (childRect.TopLeft() != child->GetPosition()) {
*aNeedsRedraw = PR_TRUE;
child->SetBounds(aState, childRect);
}
child = child->GetNextBox();
}
}
@ -1530,7 +1570,10 @@ nsSprocketLayout::GetAscent(nsIBox* aBox, nsBoxLayoutState& aState)
child = child->GetNextBox();
}
return vAscent;
nsMargin borderPadding;
aBox->GetBorderAndPadding(borderPadding);
return vAscent + borderPadding.top;
}
void
@ -1614,7 +1657,6 @@ nsBoxSize::nsBoxSize()
min = 0;
max = NS_INTRINSICSIZE;
collapsed = PR_FALSE;
ascent = 0;
left = 0;
right = 0;
flex = 0;

Просмотреть файл

@ -50,7 +50,6 @@ public:
nscoord pref;
nscoord min;
nscoord max;
nscoord ascent;
nscoord flex;
nscoord left;
nscoord right;
@ -121,14 +120,11 @@ protected:
void ComputeChildsNextPosition(nsIBox* aBox,
nscoord& aCurX,
nscoord& aCurY,
const nscoord& aCurX,
const nscoord& aCurY,
nscoord& aNextX,
nscoord& aNextY,
const nsRect& aChildSize,
const nsRect& aContainingRect,
nscoord childAscent,
nscoord aMaxAscent);
const nsRect& aChildSize);
void ChildResized(nsIBox* aBox,
nsBoxLayoutState& aState,
@ -143,6 +139,10 @@ protected:
PRInt32 aFlexes,
PRBool& aFinished);
void AlignChildren(nsIBox* aBox,
nsBoxLayoutState& aState,
PRBool* aNeedsRedraw);
virtual void ComputeChildSizes(nsIBox* aBox,
nsBoxLayoutState& aState,
nscoord& aGivenSize,