diff --git a/content/html/style/src/nsCSSLayout.cpp b/content/html/style/src/nsCSSLayout.cpp
index d7598032889f..d103285c0dd0 100644
--- a/content/html/style/src/nsCSSLayout.cpp
+++ b/content/html/style/src/nsCSSLayout.cpp
@@ -56,8 +56,9 @@ nsCSSLayout::VerticallyAlignChildren(nsIPresContext* aCX,
nscoord maxY = aY0;
PRIntn pass2Kids = 0;
PRIntn kidCount = aChildCount;
+ nscoord* ascents = aAscents;
while (--kidCount >= 0) {
- nscoord kidAscent = *aAscents++;
+ nscoord kidAscent = *ascents++;
const nsStyleText* textStyle;
kid->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)textStyle);
@@ -70,10 +71,17 @@ nsCSSLayout::VerticallyAlignChildren(nsIPresContext* aCX,
nscoord kidYTop = 0;
PRBool isPass2Kid = PR_FALSE;
- nscoord fontHeight, fontAscent, fontDescent;
+ nscoord fontParam;
switch (verticalAlignUnit) {
case eStyleUnit_Coord:
- kidYTop = aMaxAscent + textStyle->mVerticalAlign.GetCoordValue();
+ // According to the spec, a positive value "raises" the box by
+ // the given distance while a negative value "lowers" the box
+ // by the given distance. Since Y coordinates increase towards
+ // the bottom of the screen we reverse the sign. All of the
+ // raising and lowering is done relative to the baseline, so
+ // we start our adjustments there.
+ kidYTop = aMaxAscent - kidAscent; // get baseline first
+ kidYTop -= textStyle->mVerticalAlign.GetCoordValue();
break;
case eStyleUnit_Percent:
@@ -95,17 +103,15 @@ nsCSSLayout::VerticallyAlignChildren(nsIPresContext* aCX,
break;
case NS_STYLE_VERTICAL_ALIGN_SUB:
- // Move baseline by 1/2 the ascent of the child.
- // NOTE: CSSx doesn't seem to specify what subscripting does
- // so we are using ebina's logic
- kidYTop = aMaxAscent + (kidAscent/2) - kidAscent;
+ // Align the child's baseline on the superscript baseline
+ fm->GetSubscriptOffset(fontParam);
+ kidYTop = aMaxAscent + fontParam - kidAscent;
break;
case NS_STYLE_VERTICAL_ALIGN_SUPER:
- // Move baseline by 1/2 the ascent of the child
- // NOTE: CSSx doesn't seem to specify what superscripting does
- // so we are using ebina's logic
- kidYTop = aMaxAscent - (kidAscent/2) - kidAscent;
+ // Align the child's baseline on the subscript baseline
+ fm->GetSuperscriptOffset(fontParam);
+ kidYTop = aMaxAscent - fontParam - kidAscent;
break;
case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
@@ -114,22 +120,20 @@ nsCSSLayout::VerticallyAlignChildren(nsIPresContext* aCX,
break;
case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
- // XXX spec says use the 'x' height but our font api
- // doesn't give us that information.
- fm->GetHeight(fontHeight);
- kidYTop = aMaxAscent - (fontHeight / 2) - kidRect.height/2;
+ // Align the midpoint of the box with 1/2 the parent's x-height
+ fm->GetXHeight(fontParam);
+ kidYTop = aMaxAscent - (fontParam / 2) - (kidRect.height/2);
break;
case NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM:
- fm->GetMaxDescent(fontDescent);
- kidYTop = aMaxAscent + fontDescent - kidRect.height;
+ fm->GetMaxDescent(fontParam);
+ kidYTop = aMaxAscent + fontParam - kidRect.height;
break;
case NS_STYLE_VERTICAL_ALIGN_TEXT_TOP:
- fm->GetMaxAscent(fontAscent);
- kidYTop = aMaxAscent - fontAscent;
+ fm->GetMaxAscent(fontParam);
+ kidYTop = aMaxAscent - fontParam;
break;
-
}
break;
@@ -139,6 +143,11 @@ nsCSSLayout::VerticallyAlignChildren(nsIPresContext* aCX,
break;
}
+ /* XXX or grow the box - which is it? */
+ if (kidYTop < 0) {
+ kidYTop = 0;
+ }
+
// Place kid and update min and max Y values
if (!isPass2Kid) {
nscoord y = aY0 + kidYTop;
@@ -162,14 +171,24 @@ nsCSSLayout::VerticallyAlignChildren(nsIPresContext* aCX,
// Position all of the bottom aligned children
kidCount = aChildCount;
kid = aFirstChild;
+ ascents = aAscents;
while (--kidCount >= 0) {
+ nscoord kidAscent = *ascents++;
+
// Get kid's vertical align style data
const nsStyleText* textStyle;
kid->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)textStyle);
nsStyleUnit verticalAlignUnit = textStyle->mVerticalAlign.GetUnit();
if (eStyleUnit_Percent == verticalAlignUnit) {
- nscoord kidYTop = aMaxAscent +
+ // According to the spec, a positive value "raises" the box by
+ // the given distance while a negative value "lowers" the box
+ // by the given distance. Since Y coordinates increase towards
+ // the bottom of the screen we reverse the sign. All of the
+ // raising and lowering is done relative to the baseline, so
+ // we start our adjustments there.
+ nscoord kidYTop = aMaxAscent - kidAscent; // get baseline first
+ kidYTop -=
nscoord(textStyle->mVerticalAlign.GetPercentValue() * lineHeight);
kid->GetRect(kidRect);
kid->MoveTo(kidRect.x, aY0 + kidYTop);
diff --git a/layout/html/style/src/nsCSSLayout.cpp b/layout/html/style/src/nsCSSLayout.cpp
index d7598032889f..d103285c0dd0 100644
--- a/layout/html/style/src/nsCSSLayout.cpp
+++ b/layout/html/style/src/nsCSSLayout.cpp
@@ -56,8 +56,9 @@ nsCSSLayout::VerticallyAlignChildren(nsIPresContext* aCX,
nscoord maxY = aY0;
PRIntn pass2Kids = 0;
PRIntn kidCount = aChildCount;
+ nscoord* ascents = aAscents;
while (--kidCount >= 0) {
- nscoord kidAscent = *aAscents++;
+ nscoord kidAscent = *ascents++;
const nsStyleText* textStyle;
kid->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)textStyle);
@@ -70,10 +71,17 @@ nsCSSLayout::VerticallyAlignChildren(nsIPresContext* aCX,
nscoord kidYTop = 0;
PRBool isPass2Kid = PR_FALSE;
- nscoord fontHeight, fontAscent, fontDescent;
+ nscoord fontParam;
switch (verticalAlignUnit) {
case eStyleUnit_Coord:
- kidYTop = aMaxAscent + textStyle->mVerticalAlign.GetCoordValue();
+ // According to the spec, a positive value "raises" the box by
+ // the given distance while a negative value "lowers" the box
+ // by the given distance. Since Y coordinates increase towards
+ // the bottom of the screen we reverse the sign. All of the
+ // raising and lowering is done relative to the baseline, so
+ // we start our adjustments there.
+ kidYTop = aMaxAscent - kidAscent; // get baseline first
+ kidYTop -= textStyle->mVerticalAlign.GetCoordValue();
break;
case eStyleUnit_Percent:
@@ -95,17 +103,15 @@ nsCSSLayout::VerticallyAlignChildren(nsIPresContext* aCX,
break;
case NS_STYLE_VERTICAL_ALIGN_SUB:
- // Move baseline by 1/2 the ascent of the child.
- // NOTE: CSSx doesn't seem to specify what subscripting does
- // so we are using ebina's logic
- kidYTop = aMaxAscent + (kidAscent/2) - kidAscent;
+ // Align the child's baseline on the superscript baseline
+ fm->GetSubscriptOffset(fontParam);
+ kidYTop = aMaxAscent + fontParam - kidAscent;
break;
case NS_STYLE_VERTICAL_ALIGN_SUPER:
- // Move baseline by 1/2 the ascent of the child
- // NOTE: CSSx doesn't seem to specify what superscripting does
- // so we are using ebina's logic
- kidYTop = aMaxAscent - (kidAscent/2) - kidAscent;
+ // Align the child's baseline on the subscript baseline
+ fm->GetSuperscriptOffset(fontParam);
+ kidYTop = aMaxAscent - fontParam - kidAscent;
break;
case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
@@ -114,22 +120,20 @@ nsCSSLayout::VerticallyAlignChildren(nsIPresContext* aCX,
break;
case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
- // XXX spec says use the 'x' height but our font api
- // doesn't give us that information.
- fm->GetHeight(fontHeight);
- kidYTop = aMaxAscent - (fontHeight / 2) - kidRect.height/2;
+ // Align the midpoint of the box with 1/2 the parent's x-height
+ fm->GetXHeight(fontParam);
+ kidYTop = aMaxAscent - (fontParam / 2) - (kidRect.height/2);
break;
case NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM:
- fm->GetMaxDescent(fontDescent);
- kidYTop = aMaxAscent + fontDescent - kidRect.height;
+ fm->GetMaxDescent(fontParam);
+ kidYTop = aMaxAscent + fontParam - kidRect.height;
break;
case NS_STYLE_VERTICAL_ALIGN_TEXT_TOP:
- fm->GetMaxAscent(fontAscent);
- kidYTop = aMaxAscent - fontAscent;
+ fm->GetMaxAscent(fontParam);
+ kidYTop = aMaxAscent - fontParam;
break;
-
}
break;
@@ -139,6 +143,11 @@ nsCSSLayout::VerticallyAlignChildren(nsIPresContext* aCX,
break;
}
+ /* XXX or grow the box - which is it? */
+ if (kidYTop < 0) {
+ kidYTop = 0;
+ }
+
// Place kid and update min and max Y values
if (!isPass2Kid) {
nscoord y = aY0 + kidYTop;
@@ -162,14 +171,24 @@ nsCSSLayout::VerticallyAlignChildren(nsIPresContext* aCX,
// Position all of the bottom aligned children
kidCount = aChildCount;
kid = aFirstChild;
+ ascents = aAscents;
while (--kidCount >= 0) {
+ nscoord kidAscent = *ascents++;
+
// Get kid's vertical align style data
const nsStyleText* textStyle;
kid->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)textStyle);
nsStyleUnit verticalAlignUnit = textStyle->mVerticalAlign.GetUnit();
if (eStyleUnit_Percent == verticalAlignUnit) {
- nscoord kidYTop = aMaxAscent +
+ // According to the spec, a positive value "raises" the box by
+ // the given distance while a negative value "lowers" the box
+ // by the given distance. Since Y coordinates increase towards
+ // the bottom of the screen we reverse the sign. All of the
+ // raising and lowering is done relative to the baseline, so
+ // we start our adjustments there.
+ nscoord kidYTop = aMaxAscent - kidAscent; // get baseline first
+ kidYTop -=
nscoord(textStyle->mVerticalAlign.GetPercentValue() * lineHeight);
kid->GetRect(kidRect);
kid->MoveTo(kidRect.x, aY0 + kidYTop);