author | Morris Tseng <mtseng@mozilla.com> |
Tue, 15 Mar 2016 10:37:37 +0800 | |
changeset 288686 | 2f3cc8818587cc3b25d196cb61a2063f37227ab9 |
parent 288685 | 8e35ad3b586f7aabdfce8050893a45a8c47f518c |
child 288687 | df2429673c945e1fe476c8056547cca787e727d7 |
push id | 30087 |
push user | cbook@mozilla.com |
push date | Tue, 15 Mar 2016 09:43:43 +0000 |
treeherder | mozilla-central@5e14887312d4 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | dbaron |
bugs | 594933 |
milestone | 48.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
new file mode 100644 --- /dev/null +++ b/layout/reftests/css-calc/line-height-1-ref.html @@ -0,0 +1,62 @@ +<!DOCTYPE html> +<style> +div { + width:100px; + height:600px; + margin:5px 0 0 5px; + font-size: 30px; + float:left; +} +div#one { + line-height: 300%; +} +div#two { + line-height: 100px; +} +div#three { + line-height: 110px; +} +div#four { + line-height: 20px; +} +div#five { + line-height: 12px; +} +div#six { + line-height: 12px; +} +div#seven { + line-height: 12px; +} +div#eight { + line-height: 12px; +} +div#nine { + line-height: 12px; +} +div#nine { + line-height: 12px; +} +div#ten { + line-height: 12px; +} +div#div-11 { + line-height: 15px; +} +div#div-12 { + line-height: 195px; +} +</style> +<div id="one">line height is 300%</div> +<div id="two">line height is 100px</div> +<div id="three">line height is 50px</div> +<div id="four">line height is 10px * 2</div> +<div id="five">line height is 50% - 3px</div> +<div id="six">line height is 25% - 3px + 25%</div> +<div id="seven">line height is 25% - 3px + 12.5% * 2</div> +<div id="eight">line height is 25% - 3px + 12.5%*2</div> +<div id="nine">line height is 25% - 3px + 2*12.5%</div> +<div id="ten">line height is 25% - 3px + 2 * 12.5%</div> +<div id="div-11">line height is 30% + 20%</div> +<div id="div-12">line height is 3 * 2 + 3 / 6</div> +</html>
new file mode 100644 --- /dev/null +++ b/layout/reftests/css-calc/line-height-1.html @@ -0,0 +1,62 @@ +<!DOCTYPE html> +<style> +div { + width:100px; + height:600px; + margin:5px 0 0 5px; + font-size: 30px; + float:left; +} +div#one { + line-height: calc(300%); +} +div#two { + line-height: calc(100px); +} +div#three { + line-height: calc(20px + 300%); +} +div#four { + line-height: calc(10px * 2); +} +div#five { + line-height: calc(50% - 3px); +} +div#six { + line-height: calc(25% - 3px + 25%); +} +div#seven { + line-height: calc(25% - 3px + 12.5% * 2); +} +div#eight { + line-height: calc(25% - 3px + 12.5%*2); +} +div#nine { + line-height: calc(25% - 3px + 2 * 12.5%); +} +div#nine { + line-height: calc(25% - 3px + 2*12.5%); +} +div#ten { + line-height: calc(25% - 3px + 2 * 12.5%); +} +div#div-11 { + line-height: calc(30% + 20%); +} +div#div-12 { + line-height: calc(3 * 2 + 3 / 6); +} +</style> +<div id="one">line height is 300%</div> +<div id="two">line height is 100px</div> +<div id="three">line height is 50px</div> +<div id="four">line height is 10px * 2</div> +<div id="five">line height is 50% - 3px</div> +<div id="six">line height is 25% - 3px + 25%</div> +<div id="seven">line height is 25% - 3px + 12.5% * 2</div> +<div id="eight">line height is 25% - 3px + 12.5%*2</div> +<div id="nine">line height is 25% - 3px + 2*12.5%</div> +<div id="ten">line height is 25% - 3px + 2 * 12.5%</div> +<div id="div-11">line height is 30% + 20%</div> +<div id="div-12">line height is 3 * 2 + 3 / 6</div> +</html>
--- a/layout/reftests/css-calc/reftest.list +++ b/layout/reftests/css-calc/reftest.list @@ -1,1 +1,2 @@ == background-image-gradient-1.html background-image-gradient-1-ref.html +== line-height-1.html line-height-1-ref.html
--- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -13554,20 +13554,20 @@ CSSParserImpl::ParseFont() if (!ParseSingleTokenNonNegativeVariant(size, VARIANT_KEYWORD | VARIANT_LP, nsCSSProps::kFontSizeKTable)) { return false; } // Get optional "/" line-height nsCSSValue lineHeight; if (ExpectSymbol('/', true)) { - if (!ParseSingleTokenNonNegativeVariant(lineHeight, - VARIANT_NUMBER | VARIANT_LP | - VARIANT_NORMAL, - nullptr)) { + if (ParseNonNegativeVariant(lineHeight, + VARIANT_NUMBER | VARIANT_LP | + VARIANT_NORMAL | VARIANT_CALC, + nullptr) != CSSParseResult::Ok) { return false; } } else { lineHeight.SetNormalValue(); } // Get final mandatory font-family
--- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -2267,17 +2267,17 @@ CSS_PROP_TEXT( line_height, LineHeight, CSS_PROPERTY_PARSE_VALUE | CSS_PROPERTY_VALUE_NONNEGATIVE | CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE | CSS_PROPERTY_APPLIES_TO_PLACEHOLDER | CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH, "", - VARIANT_HLPN | VARIANT_KEYWORD | VARIANT_NORMAL | VARIANT_SYSFONT, + VARIANT_HLPN | VARIANT_KEYWORD | VARIANT_NORMAL | VARIANT_SYSFONT | VARIANT_CALC, kLineHeightKTable, offsetof(nsStyleText, mLineHeight), eStyleAnimType_Coord) CSS_PROP_SHORTHAND( list-style, list_style, ListStyle, CSS_PROPERTY_PARSE_FUNCTION,
--- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -4267,16 +4267,111 @@ TruncateStringToSingleGrapheme(nsAString // Not mutating the string for common cases helps memory use // since we share the buffer from the specified style into the // computed style. aStr.Truncate(iter - aStr.Data()); } } } +struct LineHeightCalcObj +{ + float mLineHeight; + bool mIsNumber; +}; + +struct SetLineHeightCalcOps : public css::NumbersAlreadyNormalizedOps +{ + typedef LineHeightCalcObj result_type; + nsStyleContext* const mStyleContext; + nsPresContext* const mPresContext; + RuleNodeCacheConditions& mConditions; + + SetLineHeightCalcOps(nsStyleContext* aStyleContext, + nsPresContext* aPresContext, + RuleNodeCacheConditions& aConditions) + : mStyleContext(aStyleContext), + mPresContext(aPresContext), + mConditions(aConditions) + { + } + + result_type + MergeAdditive(nsCSSUnit aCalcFunction, + result_type aValue1, result_type aValue2) + { + MOZ_ASSERT(aValue1.mIsNumber == aValue2.mIsNumber); + + LineHeightCalcObj result; + result.mIsNumber = aValue1.mIsNumber; + if (aCalcFunction == eCSSUnit_Calc_Plus) { + result.mLineHeight = aValue1.mLineHeight + aValue2.mLineHeight; + return result; + } + MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Minus, + "unexpected unit"); + result.mLineHeight = aValue1.mLineHeight - aValue2.mLineHeight; + return result; + } + + result_type + MergeMultiplicativeL(nsCSSUnit aCalcFunction, + float aValue1, result_type aValue2) + { + MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_L, + "unexpected unit"); + LineHeightCalcObj result; + result.mIsNumber = aValue2.mIsNumber; + result.mLineHeight = aValue1 * aValue2.mLineHeight; + return result; + } + + result_type + MergeMultiplicativeR(nsCSSUnit aCalcFunction, + result_type aValue1, float aValue2) + { + LineHeightCalcObj result; + result.mIsNumber = aValue1.mIsNumber; + if (aCalcFunction == eCSSUnit_Calc_Times_R) { + result.mLineHeight = aValue1.mLineHeight * aValue2; + return result; + } + MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Divided, + "unexpected unit"); + result.mLineHeight = aValue1.mLineHeight / aValue2; + return result; + } + + result_type ComputeLeafValue(const nsCSSValue& aValue) + { + LineHeightCalcObj result; + if (aValue.IsLengthUnit()) { + result.mIsNumber = false; + result.mLineHeight = CalcLength(aValue, mStyleContext, + mPresContext, mConditions); + } + else if (eCSSUnit_Percent == aValue.GetUnit()) { + mConditions.SetUncacheable(); + result.mIsNumber = false; + nscoord fontSize = mStyleContext->StyleFont()->mFont.size; + result.mLineHeight = fontSize * aValue.GetPercentValue(); + } + else if (eCSSUnit_Number == aValue.GetUnit()) { + result.mIsNumber = true; + result.mLineHeight = aValue.GetFloatValue(); + } else { + MOZ_ASSERT(false, "unexpected value"); + result.mIsNumber = true; + result.mLineHeight = 1.0f; + } + + return result; + } +}; + const void* nsRuleNode::ComputeTextData(void* aStartStruct, const nsRuleData* aRuleData, nsStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail aRuleDetail, const RuleNodeCacheConditions aConditions) { @@ -4309,29 +4404,39 @@ nsRuleNode::ComputeTextData(void* aStart } else if (textShadowValue->GetUnit() == eCSSUnit_List || textShadowValue->GetUnit() == eCSSUnit_ListDep) { // List of arrays text->mTextShadow = GetShadowData(textShadowValue->GetListValue(), aContext, false, conditions); } } - // line-height: normal, number, length, percent, inherit + // line-height: normal, number, length, percent, calc, inherit const nsCSSValue* lineHeightValue = aRuleData->ValueForLineHeight(); if (eCSSUnit_Percent == lineHeightValue->GetUnit()) { conditions.SetUncacheable(); // Use |mFont.size| to pick up minimum font size. text->mLineHeight.SetCoordValue( NSToCoordRound(float(aContext->StyleFont()->mFont.size) * lineHeightValue->GetPercentValue())); } else if (eCSSUnit_Initial == lineHeightValue->GetUnit() || eCSSUnit_System_Font == lineHeightValue->GetUnit()) { text->mLineHeight.SetNormalValue(); } + else if (eCSSUnit_Calc == lineHeightValue->GetUnit()) { + SetLineHeightCalcOps ops(aContext, mPresContext, conditions); + LineHeightCalcObj obj = css::ComputeCalc(*lineHeightValue, ops); + if (obj.mIsNumber) { + text->mLineHeight.SetFactorValue(obj.mLineHeight); + } else { + text->mLineHeight.SetCoordValue( + NSToCoordRoundWithClamp(obj.mLineHeight)); + } + } else { SetCoord(*lineHeightValue, text->mLineHeight, parentText->mLineHeight, SETCOORD_LEH | SETCOORD_FACTOR | SETCOORD_NORMAL | SETCOORD_UNSET_INHERIT, aContext, mPresContext, conditions); if (lineHeightValue->IsLengthUnit() && !lineHeightValue->IsRelativeLengthUnit()) { nscoord lh = nsStyleFont::ZoomText(mPresContext,
--- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -2792,18 +2792,29 @@ var gCSSProperties = { "font-kerning", "font-synthesis", "font-variant-alternates", "font-variant-caps", "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric", "font-variant-position" ], initial_values: [ (gInitialFontFamilyIsSansSerif ? "medium sans-serif" : "medium serif") ], other_values: [ "large serif", "9px fantasy", "condensed bold italic small-caps 24px/1.4 Times New Roman, serif", "small inherit roman", "small roman inherit", // system fonts "caption", "icon", "menu", "message-box", "small-caption", "status-bar", // Gecko-specific system fonts "-moz-window", "-moz-document", "-moz-desktop", "-moz-info", "-moz-dialog", "-moz-button", "-moz-pull-down-menu", "-moz-list", "-moz-field", "-moz-workspace", + // line-height with calc() + "condensed bold italic small-caps 24px/calc(2px) Times New Roman, serif", + "condensed bold italic small-caps 24px/calc(50%) Times New Roman, serif", + "condensed bold italic small-caps 24px/calc(3*25px) Times New Roman, serif", + "condensed bold italic small-caps 24px/calc(25px*3) Times New Roman, serif", + "condensed bold italic small-caps 24px/calc(3*25px + 50%) Times New Roman, serif", + "condensed bold italic small-caps 24px/calc(1 + 2*3/4) Times New Roman, serif", ], - invalid_values: [ "9 fantasy", "-2px fantasy" ] + invalid_values: [ "9 fantasy", "-2px fantasy", + // line-height with calc() + "condensed bold italic small-caps 24px/calc(1 + 2px) Times New Roman, serif", + "condensed bold italic small-caps 24px/calc(100% + 0.1) Times New Roman, serif", + ] }, "font-family": { domProp: "fontFamily", inherited: true, type: CSS_TYPE_LONGHAND, initial_values: [ (gInitialFontFamilyIsSansSerif ? "sans-serif" : "serif") ], other_values: [ (gInitialFontFamilyIsSansSerif ? "serif" : "sans-serif"), "Times New Roman, serif", "'Times New Roman', serif", "cursive", "fantasy", "\\\"Times New Roman", "\"Times New Roman\"", "Times, \\\"Times New Roman", "Times, \"Times New Roman\"", "-no-such-font-installed", "inherit roman", "roman inherit", "Times, inherit roman", "inherit roman, Times", "roman inherit, Times", "Times, roman inherit" ], invalid_values: [ "\"Times New\" Roman", "\"Times New Roman\n", "Times, \"Times New Roman\n" ] @@ -3055,18 +3066,18 @@ var gCSSProperties = { * getComputedStyle (which uses the CSS2 computed value, or * CSS2.1 used value) doesn't match what the CSS2.1 computed * value is. And they even require consistent font metrics for * computation of 'normal'. -moz-block-height requires height * on a block. */ prerequisites: { "font-size": "19px", "font-size-adjust": "none", "font-family": "serif", "font-weight": "normal", "font-style": "normal", "height": "18px", "display": "block"}, initial_values: [ "normal" ], - other_values: [ "1.0", "1", "1em", "47px", "-moz-block-height" ], - invalid_values: [] + other_values: [ "1.0", "1", "1em", "47px", "-moz-block-height", "calc(2px)", "calc(50%)", "calc(3*25px)", "calc(25px*3)", "calc(3*25px + 50%)", "calc(1 + 2*3/4)" ], + invalid_values: [ "calc(1 + 2px)", "calc(100% + 0.1)" ] }, "list-style": { domProp: "listStyle", inherited: true, type: CSS_TYPE_TRUE_SHORTHAND, subproperties: [ "list-style-type", "list-style-position", "list-style-image" ], initial_values: [ "outside", "disc", "disc outside", "outside disc", "disc none", "none disc", "none disc outside", "none outside disc", "disc none outside", "disc outside none", "outside none disc", "outside disc none" ], other_values: [ "inside none", "none inside", "none none inside", "square", "none", "none none", "outside none none", "none outside none", "none none outside", "none outside", "outside none", "outside outside", "outside inside", "\\32 style", "\\32 style inside",