Add calc() support for 'font-size' property, which is the only property for which percents are computed to lengths in nsRuleNode. (Bug 363249) r=bzbarsky

This commit is contained in:
L. David Baron 2010-05-11 08:49:44 -07:00
parent a834b40a01
commit 97f744099a
3 changed files with 87 additions and 21 deletions

View File

@ -5985,7 +5985,8 @@ CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue,
return ParseFamily(aValue);
case eCSSProperty_font_size:
return ParseNonNegativeVariant(aValue,
VARIANT_HKLP | VARIANT_SYSFONT,
VARIANT_HKLP | VARIANT_SYSFONT |
VARIANT_CALC,
nsCSSProps::kFontSizeKTable);
case eCSSProperty_font_size_adjust:
return ParseVariant(aValue, VARIANT_HON | VARIANT_SYSFONT,

View File

@ -2659,6 +2659,59 @@ ComputeScriptLevelSize(const nsStyleFont* aFont, const nsStyleFont* aParentFont,
}
#endif
struct SetFontSizeCalcOps : public mozilla::css::BasicCoordCalcOps,
public mozilla::css::NumbersAlreadyNormalizedOps
{
struct ComputeData {
// The parameters beyond aValue that we need for CalcLengthWith.
nscoord mParentSize;
const nsStyleFont* mParentFont;
nsPresContext* mPresContext;
PRBool mAtRoot;
PRBool& mCanStoreInRuleTree;
ComputeData(nscoord aParentSize, const nsStyleFont* aParentFont,
nsPresContext* aPresContext, PRBool aAtRoot,
PRBool& aCanStoreInRuleTree)
: mParentSize(aParentSize),
mParentFont(aParentFont),
mPresContext(aPresContext),
mAtRoot(aAtRoot),
mCanStoreInRuleTree(aCanStoreInRuleTree)
{
}
};
static result_type ComputeLeafValue(const nsCSSValue& aValue,
const ComputeData& aClosure)
{
nscoord size;
if (aValue.IsLengthUnit()) {
// Note that font-based length units use the parent's size
// unadjusted for scriptlevel changes. A scriptlevel change
// between us and the parent is simply ignored.
size = CalcLengthWith(aValue, aClosure.mParentSize, aClosure.mParentFont,
nsnull, aClosure.mPresContext, aClosure.mAtRoot,
PR_TRUE, aClosure.mCanStoreInRuleTree);
if (aValue.IsFixedLengthUnit() || aValue.GetUnit() == eCSSUnit_Pixel) {
size = nsStyleFont::ZoomText(aClosure.mPresContext, size);
}
}
else if (eCSSUnit_Percent == aValue.GetUnit()) {
aClosure.mCanStoreInRuleTree = PR_FALSE;
// Note that % units use the parent's size unadjusted for scriptlevel
// changes. A scriptlevel change between us and the parent is simply
// ignored.
size = NSToCoordRound(aClosure.mParentSize * aValue.GetPercentValue());
} else {
NS_ABORT_IF_FALSE(PR_FALSE, "unexpected value");
size = aClosure.mParentSize;
}
return size;
}
};
/* static */ void
nsRuleNode::SetFontSize(nsPresContext* aPresContext,
const nsRuleDataFont& aFontData,
@ -2720,23 +2773,21 @@ nsRuleNode::SetFontSize(nsPresContext* aPresContext,
NS_NOTREACHED("unexpected value");
}
}
else if (aFontData.mSize.IsLengthUnit()) {
// Note that font-based length units use the parent's size unadjusted
// for scriptlevel changes. A scriptlevel change between us and the parent
// is simply ignored.
*aSize = CalcLengthWith(aFontData.mSize, aParentSize, aParentFont, nsnull,
aPresContext, aAtRoot, PR_TRUE,
aCanStoreInRuleTree);
zoom = aFontData.mSize.IsFixedLengthUnit() ||
aFontData.mSize.GetUnit() == eCSSUnit_Pixel;
}
else if (eCSSUnit_Percent == aFontData.mSize.GetUnit()) {
aCanStoreInRuleTree = PR_FALSE;
// Note that % units use the parent's size unadjusted for scriptlevel
// changes. A scriptlevel change between us and the parent is simply
// ignored.
*aSize = NSToCoordRound(aParentSize *
aFontData.mSize.GetPercentValue());
else if (aFontData.mSize.IsLengthUnit() ||
aFontData.mSize.GetUnit() == eCSSUnit_Percent ||
aFontData.mSize.IsCalcUnit()) {
SetFontSizeCalcOps::ComputeData data(aParentSize, aParentFont,
aPresContext, aAtRoot,
aCanStoreInRuleTree);
*aSize =
mozilla::css::ComputeCalc<SetFontSizeCalcOps>(aFontData.mSize, data);
if (*aSize < 0) {
NS_ABORT_IF_FALSE(aFontData.mSize.IsCalcUnit(),
"negative lengths and percents should be rejected "
"by parser");
*aSize = 0;
}
// Zoom is handled inside the calc ops when needed.
zoom = PR_FALSE;
}
else if (eCSSUnit_System_Font == aFontData.mSize.GetUnit()) {

View File

@ -1480,9 +1480,23 @@ var gCSSProperties = {
domProp: "fontSize",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "medium" ],
other_values: [ "large", "2em", "50%", "xx-small", "36pt", "8px" ],
invalid_values: []
initial_values: [ "medium",
"1rem",
"-moz-calc(1rem)",
"-moz-calc(0.75rem + 200% - 125% + 0.25rem - 75%)"
],
other_values: [ "large", "2em", "50%", "xx-small", "36pt", "8px",
"0px",
"0%",
"-moz-calc(2em)",
"-moz-min(36pt, 2em)",
"-moz-max(50%, 8px)",
"-moz-min(36pt + 75%, 30% + 2em + 2px)",
"-moz-calc(-2em)",
"-moz-calc(-50%)",
"-moz-calc(-1px)"
],
invalid_values: [ "-2em", "-50%", "-1px" ]
},
"font-size-adjust": {
domProp: "fontSizeAdjust",