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(..) == input-text-centering-1.xul input-text-centering-1-ref.xul
HTTP(..) == text-control-baseline-1.html text-control-baseline-1-ref.html 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 == 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 == radio-label-dynamic.html radio-label-dynamic-ref.html
== out-of-bounds-selectedindex.html out-of-bounds-selectedindex-ref.html # bug 471741 == out-of-bounds-selectedindex.html out-of-bounds-selectedindex-ref.html # bug 471741

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

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

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

@ -241,8 +241,6 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
nsBoxSize* boxSizes = nsnull; nsBoxSize* boxSizes = nsnull;
nsComputedBoxSize* computedBoxSizes = nsnull; nsComputedBoxSize* computedBoxSizes = nsnull;
nscoord maxAscent = aBox->GetBoxAscent(aState);
nscoord min = 0; nscoord min = 0;
nscoord max = 0; nscoord max = 0;
PRInt32 flexes = 0; PRInt32 flexes = 0;
@ -415,33 +413,26 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
if (childRect.height > clientRect.height) if (childRect.height > clientRect.height)
clientRect.height = childRect.height; clientRect.height = childRect.height;
// |x|, |y|, |nextX|, and |nextY| are updated by this function call. This call // Either |nextX| or |nextY| is updated by this function call, according
// also deals with box ALIGNMENT (when stretching is not turned on). // to our axis.
ComputeChildsNextPosition(aBox, ComputeChildsNextPosition(aBox, x, y, nextX, nextY, childRect);
x,
y,
nextX,
nextY,
childRect,
originalClientRect,
childBoxSize->ascent,
maxAscent);
// Now we update our nextX/Y along our axis and we update our x/y along the opposite // Now we further update our nextX/Y along our axis.
// axis (since a non-stretching alignment could have caused an adjustment). // 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_HORIZONTAL) {
if (frameState & NS_STATE_IS_DIRECTION_NORMAL) if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
nextX += (childBoxSize->right); nextX += (childBoxSize->right);
else else
nextX -= (childBoxSize->left); nextX -= (childBoxSize->left);
childRect.y = y; childRect.y = originalClientRect.y;
} }
else { else {
if (frameState & NS_STATE_IS_DIRECTION_NORMAL) if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
nextY += (childBoxSize->right); nextY += (childBoxSize->right);
else else
nextY -= (childBoxSize->left); nextY -= (childBoxSize->left);
childRect.x = x; childRect.x = originalClientRect.x;
} }
// If we encounter a completely bogus box size, we just leave this child completely // 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; 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. // 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 // If our old rect is different, then we know our size changed and we cache that fact
// in the |sizeChanged| variable. // in the |sizeChanged| variable.
nsRect oldRect(child->GetRect());
PRBool sizeChanged = PR_FALSE;
child->SetBounds(aState, childRect); 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) { if (sizeChanged) {
// Our size is different. Sanity check against our maximum allowed size to ensure // Our size is different. Sanity check against our maximum allowed size to ensure
@ -570,22 +572,7 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
} }
// If the child resized then recompute its position. // If the child resized then recompute its position.
ComputeChildsNextPosition(aBox, ComputeChildsNextPosition(aBox, x, y, nextX, nextY, newChildRect);
x,
y,
nextX,
nextY,
newChildRect,
originalClientRect,
childBoxSize->ascent,
maxAscent);
// 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) if (newChildRect.width >= margin.left + margin.right && newChildRect.height >= margin.top + margin.bottom)
newChildRect.Deflate(margin); 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. // Now do our redraw.
if (needsRedraw) if (needsRedraw)
aBox->Redraw(aState); aBox->Redraw(aState);
@ -879,7 +871,6 @@ nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBox
aMaxSize = maxSize.height; aMaxSize = maxSize.height;
} }
currentBox->ascent = ascent;
currentBox->collapsed = collapsed; currentBox->collapsed = collapsed;
aFlexes += currentBox->flex; aFlexes += currentBox->flex;
@ -934,77 +925,126 @@ nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBox
void void
nsSprocketLayout::ComputeChildsNextPosition(nsIBox* aBox, nsSprocketLayout::ComputeChildsNextPosition(nsIBox* aBox,
nscoord& aCurX, const nscoord& aCurX,
nscoord& aCurY, const nscoord& aCurY,
nscoord& aNextX, nscoord& aNextX,
nscoord& aNextY, nscoord& aNextY,
const nsRect& aCurrentChildSize, const nsRect& aCurrentChildSize)
const nsRect& aBoxRect,
nscoord childAscent,
nscoord aMaxAscent)
{ {
// Get the position along the box axis for the child.
// The out-of-axis position is not set.
nsFrameState frameState = 0; nsFrameState frameState = 0;
GetFrameState(aBox, frameState); GetFrameState(aBox, frameState);
nsIBox::Halignment halign = aBox->GetHAlign();
nsIBox::Valignment valign = aBox->GetVAlign();
if (IsHorizontal(aBox)) { if (IsHorizontal(aBox)) {
// Handle alignment of a horizontal box's children. // horizontal box's children.
if (frameState & NS_STATE_IS_DIRECTION_NORMAL) if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
aNextX = aCurX + aCurrentChildSize.width; 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 { } else {
// Handle alignment of a vertical box's children. // vertical box's children.
if (frameState & NS_STATE_IS_DIRECTION_NORMAL) if (frameState & NS_STATE_IS_DIRECTION_NORMAL)
aNextY = aCurY + aCurrentChildSize.height; aNextY = aCurY + aCurrentChildSize.height;
else else
aNextY = aCurY - aCurrentChildSize.height; aNextY = aCurY - aCurrentChildSize.height;
}
}
if (frameState & NS_STATE_AUTO_STRETCH) void
aCurX = aBoxRect.x; nsSprocketLayout::AlignChildren(nsIBox* aBox,
else { nsBoxLayoutState& aState,
PRUint8 frameDirection = GetFrameDirection(aBox); PRBool* aNeedsRedraw)
switch (halign) {
{ nsFrameState frameState = 0;
case nsBoxFrame::hAlign_Left: GetFrameState(aBox, frameState);
if (frameDirection == NS_STYLE_DIRECTION_LTR) PRBool isHorizontal = (frameState & NS_STATE_IS_HORIZONTAL) != 0;
aCurX = aBoxRect.x; nsRect clientRect;
else aBox->GetClientRect(clientRect);
aCurX = aBoxRect.x + aBoxRect.width - aCurrentChildSize.width;
break; NS_PRECONDITION(!(frameState & NS_STATE_AUTO_STRETCH),
case nsBoxFrame::hAlign_Center: "Only AlignChildren() with non-stretch alignment");
aCurX = aBoxRect.x + (aBoxRect.width/2 - aCurrentChildSize.width/2);
break; // These are only calculated if needed
case nsBoxFrame::hAlign_Right: nsIBox::Halignment halign;
if (frameDirection == NS_STYLE_DIRECTION_LTR) nsIBox::Valignment valign;
aCurX = aBoxRect.x + aBoxRect.width - aCurrentChildSize.width; nscoord maxAscent;
else PRBool isLTR;
aCurX = aBoxRect.x;
break; 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(); child = child->GetNextBox();
} }
return vAscent; nsMargin borderPadding;
aBox->GetBorderAndPadding(borderPadding);
return vAscent + borderPadding.top;
} }
void void
@ -1614,7 +1657,6 @@ nsBoxSize::nsBoxSize()
min = 0; min = 0;
max = NS_INTRINSICSIZE; max = NS_INTRINSICSIZE;
collapsed = PR_FALSE; collapsed = PR_FALSE;
ascent = 0;
left = 0; left = 0;
right = 0; right = 0;
flex = 0; flex = 0;

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

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