diff options
-rw-r--r-- | layout/generic/nsTextFrame.cpp | 74 | ||||
-rw-r--r-- | layout/style/nsCSSPropList.h | 2 | ||||
-rw-r--r-- | layout/style/nsComputedDOMStyle.cpp | 2 | ||||
-rw-r--r-- | layout/style/nsRuleNode.cpp | 96 | ||||
-rw-r--r-- | layout/style/nsStyleStruct.cpp | 4 | ||||
-rw-r--r-- | layout/style/nsStyleStruct.h | 2 | ||||
-rw-r--r-- | layout/style/test/property_database.js | 6 |
7 files changed, 124 insertions, 62 deletions
diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index c7b55961c..749b8b944 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -3178,7 +3178,7 @@ public: return mFontMetrics; } - void CalcTabWidths(Range aTransformedRange); + void CalcTabWidths(Range aTransformedRange, gfxFloat aTabWidth); const gfxSkipCharsIterator& GetEndHint() { return mTempIterator; } @@ -3364,6 +3364,28 @@ CanAddSpacingAfter(const gfxTextRun* aTextRun, uint32_t aOffset) aTextRun->IsLigatureGroupStart(aOffset + 1); } +static gfxFloat +ComputeTabWidthAppUnits(nsIFrame* aFrame, gfxTextRun* aTextRun) +{ + const nsStyleText* textStyle = aFrame->StyleText(); + if (textStyle->mTabSize.GetUnit() != eStyleUnit_Factor) { + nscoord w = textStyle->mTabSize.GetCoordValue(); + MOZ_ASSERT(w >= 0); + return w; + } + + gfxFloat spaces = textStyle->mTabSize.GetFactorValue(); + MOZ_ASSERT(spaces >= 0); + + // Round the space width when converting to appunits the same way + // textruns do. + gfxFloat spaceWidthAppUnits = + NS_round(GetFirstFontMetrics(aTextRun->GetFontGroup(), + aTextRun->IsVertical()).spaceWidth * + aTextRun->GetAppUnitsPerDevUnit()); + return spaces * spaceWidthAppUnits; +} + void PropertyProvider::GetSpacingInternal(Range aRange, Spacing* aSpacing, bool aIgnoreTabs) @@ -3411,17 +3433,16 @@ PropertyProvider::GetSpacingInternal(Range aRange, Spacing* aSpacing, } } - // Ignore tab spacing rather than computing it, if the tab size is 0 - if (!aIgnoreTabs) - aIgnoreTabs = mFrame->StyleText()->mTabSize == 0; - // Now add tab spacing, if there is any if (!aIgnoreTabs) { - CalcTabWidths(aRange); - if (mTabWidths) { - mTabWidths->ApplySpacing(aSpacing, - aRange.start - mStart.GetSkippedOffset(), - aRange.Length()); + gfxFloat tabWidth = ComputeTabWidthAppUnits(mFrame, mTextRun); + if (tabWidth > 0) { + CalcTabWidths(aRange); + if (mTabWidths) { + mTabWidths->ApplySpacing(aSpacing, + aRange.start - mStart.GetSkippedOffset(), + aRange.Length()); + } } } @@ -3444,33 +3465,23 @@ PropertyProvider::GetSpacingInternal(Range aRange, Spacing* aSpacing, } } -static gfxFloat -ComputeTabWidthAppUnits(nsIFrame* aFrame, const gfxTextRun* aTextRun) -{ - // Get the number of spaces from CSS -moz-tab-size - const nsStyleText* textStyle = aFrame->StyleText(); - - return textStyle->mTabSize * GetSpaceWidthAppUnits(aTextRun); -} - // aX and the result are in whole appunits. static gfxFloat AdvanceToNextTab(gfxFloat aX, nsIFrame* aFrame, - const gfxTextRun* aTextRun, gfxFloat* aCachedTabWidth) + gfxTextRun* aTextRun, gfxFloat* aTabWidth) { - if (*aCachedTabWidth < 0) { - *aCachedTabWidth = ComputeTabWidthAppUnits(aFrame, aTextRun); - } // Advance aX to the next multiple of *aCachedTabWidth. We must advance // by at least 1 appunit. // XXX should we make this 1 CSS pixel? - return ceil((aX + 1)/(*aCachedTabWidth))*(*aCachedTabWidth); + return ceil((aX + 1)/ aTabWidth) * aTabWidth; } void -PropertyProvider::CalcTabWidths(Range aRange) +PropertyProvider::CalcTabWidths(Range aRange, gfxFloat aTabWidth) { + MOZ_ASSERT(aTabWidth > 0); + if (!mTabWidths) { if (mReflowing && !mLineContainer) { // Intrinsic width computation does its own tab processing. We @@ -3505,7 +3516,6 @@ PropertyProvider::CalcTabWidths(Range aRange) NS_ASSERTION(mReflowing, "We need precomputed tab widths, but don't have enough."); - gfxFloat tabWidth = -1; for (uint32_t i = tabsEnd; i < aRange.end; ++i) { Spacing spacing; GetSpacingInternal(Range(i, i + 1), &spacing, true); @@ -3527,7 +3537,7 @@ PropertyProvider::CalcTabWidths(Range aRange) mFrame->SetProperty(TabWidthProperty(), mTabWidths); } double nextTab = AdvanceToNextTab(mOffsetFromBlockOriginForTabs, - mFrame, mTextRun, &tabWidth); + mFrame, mTextRun, aTabWidth); mTabWidths->mWidths.AppendElement(TabWidth(i - startOffset, NSToIntRound(nextTab - mOffsetFromBlockOriginForTabs))); mOffsetFromBlockOriginForTabs = nextTab; @@ -8321,9 +8331,12 @@ nsTextFrame::AddInlineMinISizeForFlow(nsRenderingContext *aRenderingContext, PropertyProvider::Spacing spacing; provider.GetSpacing(Range(i, i + 1), &spacing); aData->mCurrentLine += nscoord(spacing.mBefore); + if (tabWidth < 0) { + tabWidth = ComputeTabWidthAppUnits(this, textRun); + } gfxFloat afterTab = AdvanceToNextTab(aData->mCurrentLine, this, - textRun, &tabWidth); + textRun, tabWidth); aData->mCurrentLine = nscoord(afterTab + spacing.mAfter); wordStart = i + 1; } else if (i < flowEndInTextRun || @@ -8480,9 +8493,12 @@ nsTextFrame::AddInlinePrefISizeForFlow(nsRenderingContext *aRenderingContext, PropertyProvider::Spacing spacing; provider.GetSpacing(Range(i, i + 1), &spacing); aData->mCurrentLine += nscoord(spacing.mBefore); + if (tabWidth < 0) { + tabWidth = ComputeTabWidthAppUnits(this, textRun); + } gfxFloat afterTab = AdvanceToNextTab(aData->mCurrentLine, this, - textRun, &tabWidth); + textRun, tabWidth); aData->mCurrentLine = nscoord(afterTab + spacing.mAfter); lineStart = i + 1; } else if (preformattedNewline) { diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index 4f79db5a5..5c5cfcda1 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -3885,7 +3885,7 @@ CSS_PROP_TEXT( CSS_PROPERTY_PARSE_VALUE | CSS_PROPERTY_VALUE_NONNEGATIVE, "", - VARIANT_HI, + VARIANT_INHERIT | VARIANT_LNCALC, nullptr, offsetof(nsStyleText, mTabSize), eStyleAnimType_Discrete) diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 08c2846f7..bbad9c371 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -3972,7 +3972,7 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetTabSize() { RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue; - val->SetNumber(StyleText()->mTabSize); + SetValueToCoord(val, StyleText()->mTabSize, true); return val.forget(); } diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 1136edee2..c2fd70879 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -4508,20 +4508,20 @@ TruncateStringToSingleGrapheme(nsAString& aStr) } } -struct LineHeightCalcObj +struct LengthNumberCalcObj { - float mLineHeight; + float LengthNumberCalcObj; bool mIsNumber; }; -struct SetLineHeightCalcOps : public css::NumbersAlreadyNormalizedOps +struct LengthNumberCalcOps : public css::FloatCoeffsAlreadyNormalizedOps { - typedef LineHeightCalcObj result_type; + typedef LengthNumberCalcObj result_type; nsStyleContext* const mStyleContext; nsPresContext* const mPresContext; RuleNodeCacheConditions& mConditions; - SetLineHeightCalcOps(nsStyleContext* aStyleContext, + LengthNumberCalcOps(nsStyleContext* aStyleContext, nsPresContext* aPresContext, RuleNodeCacheConditions& aConditions) : mStyleContext(aStyleContext), @@ -4536,15 +4536,15 @@ struct SetLineHeightCalcOps : public css::NumbersAlreadyNormalizedOps { MOZ_ASSERT(aValue1.mIsNumber == aValue2.mIsNumber); - LineHeightCalcObj result; + LengthNumberCalcObj result; result.mIsNumber = aValue1.mIsNumber; if (aCalcFunction == eCSSUnit_Calc_Plus) { - result.mLineHeight = aValue1.mLineHeight + aValue2.mLineHeight; + result.mValue = aValue1.mValue + aValue2.mValue; return result; } MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Minus, "unexpected unit"); - result.mLineHeight = aValue1.mLineHeight - aValue2.mLineHeight; + result.mValue = aValue1.mValue - aValue2.mValue; return result; } @@ -4554,9 +4554,9 @@ struct SetLineHeightCalcOps : public css::NumbersAlreadyNormalizedOps { MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_L, "unexpected unit"); - LineHeightCalcObj result; + LengthNumberCalcObj result; result.mIsNumber = aValue2.mIsNumber; - result.mLineHeight = aValue1 * aValue2.mLineHeight; + result.mValue = aValue1 * aValue2.mValue; return result; } @@ -4564,39 +4564,69 @@ struct SetLineHeightCalcOps : public css::NumbersAlreadyNormalizedOps MergeMultiplicativeR(nsCSSUnit aCalcFunction, result_type aValue1, float aValue2) { - LineHeightCalcObj result; + LengthNumberCalcObj result; result.mIsNumber = aValue1.mIsNumber; if (aCalcFunction == eCSSUnit_Calc_Times_R) { - result.mLineHeight = aValue1.mLineHeight * aValue2; + result.mValue = aValue1.mValue * aValue2; return result; } MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Divided, "unexpected unit"); - result.mLineHeight = aValue1.mLineHeight / aValue2; + result.mValue = aValue1.mValue / aValue2; return result; } result_type ComputeLeafValue(const nsCSSValue& aValue) { - LineHeightCalcObj result; + LengthNumberCalcObj result; if (aValue.IsLengthUnit()) { result.mIsNumber = false; - result.mLineHeight = CalcLength(aValue, mStyleContext, + result.mValue = CalcLength(aValue, mStyleContext, + mPresContext, mConditions); + } + else if (eCSSUnit_Number == aValue.GetUnit()) { + result.mIsNumber = true; + result.mValue = aValue.GetFloatValue(); + } else { + MOZ_ASSERT(false, "unexpected value"); + result.mIsNumber = true; + result.mValue = 1.0f; + } + + return result; + } +}; + +struct SetLineHeightCalcOps : public LengthNumberCalcOps +{ + SetLineHeightCalcOps(nsStyleContext* aStyleContext, + nsPresContext* aPresContext, + RuleNodeCacheConditions& aConditions) + : LengthNumberCalcOps(aStyleContext, aPresContext, aConditions) + { + } + + result_type ComputeLeafValue(const nsCSSValue& aValue) + { + LengthNumberCalcObj result; + if (aValue.IsLengthUnit()) { + result.mIsNumber = false; + result.mValue = 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(); + result.mValue = fontSize * aValue.GetPercentValue(); } else if (eCSSUnit_Number == aValue.GetUnit()) { result.mIsNumber = true; - result.mLineHeight = aValue.GetFloatValue(); + result.mValue = aValue.GetFloatValue(); } else { MOZ_ASSERT(false, "unexpected value"); result.mIsNumber = true; - result.mLineHeight = 1.0f; + result.mValue = 1.0f; } return result; @@ -4620,11 +4650,25 @@ nsRuleNode::ComputeTextData(void* aStartStruct, mPresContext, text->*aField, conditions); }; - // tab-size: integer, inherit - SetValue(*aRuleData->ValueForTabSize(), - text->mTabSize, conditions, - SETVAL_INTEGER | SETVAL_UNSET_INHERIT, parentText->mTabSize, - NS_STYLE_TABSIZE_INITIAL); + // tab-size: number, length, calc, inherit + const nsCSSValue* tabSizeValue = aRuleData->ValueForTabSize(); + if (tabSizeValue->GetUnit() == eCSSUnit_Initial) { + text->mTabSize = nsStyleCoord(float(NS_STYLE_TABSIZE_INITIAL), eStyleUnit_Factor); + } else if (eCSSUnit_Calc == tabSizeValue->GetUnit()) { + LengthNumberCalcOps ops(aContext, mPresContext, conditions); + LengthNumberCalcObj obj = css::ComputeCalc(*tabSizeValue, ops); + float value = obj.mValue < 0 ? 0 : obj.mValue; + if (obj.mIsNumber) { + text->mTabSize.SetFactorValue(value); + } else { + text->mTabSize.SetCoordValue( + NSToCoordRoundWithClamp(value)); + } + } else { + SetCoord(*tabSizeValue, text->mTabSize, parentText->mTabSize, + SETCOORD_LH | SETCOORD_FACTOR | SETCOORD_UNSET_INHERIT, + aContext, mPresContext, conditions); + } // letter-spacing: normal, length, inherit SetCoord(*aRuleData->ValueForLetterSpacing(), @@ -4667,12 +4711,12 @@ nsRuleNode::ComputeTextData(void* aStartStruct, } else if (eCSSUnit_Calc == lineHeightValue->GetUnit()) { SetLineHeightCalcOps ops(aContext, mPresContext, conditions); - LineHeightCalcObj obj = css::ComputeCalc(*lineHeightValue, ops); + LengthNumberCalcObj obj = css::ComputeCalc(*lineHeightValue, ops); if (obj.mIsNumber) { - text->mLineHeight.SetFactorValue(obj.mLineHeight); + text->mLineHeight.SetFactorValue(obj.mValue); } else { text->mLineHeight.SetCoordValue( - NSToCoordRoundWithClamp(obj.mLineHeight)); + NSToCoordRoundWithClamp(obj.mValue)); } } else { diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 4c610cf08..a2b6833ac 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -3807,10 +3807,10 @@ nsStyleText::nsStyleText(StyleStructContext aContext) , mControlCharacterVisibility(nsCSSParser::ControlCharVisibilityDefault()) , mTextEmphasisStyle(NS_STYLE_TEXT_EMPHASIS_STYLE_NONE) , mTextRendering(NS_STYLE_TEXT_RENDERING_AUTO) - , mTabSize(NS_STYLE_TABSIZE_INITIAL) , mTextEmphasisColor(StyleComplexColor::CurrentColor()) , mWebkitTextFillColor(StyleComplexColor::CurrentColor()) , mWebkitTextStrokeColor(StyleComplexColor::CurrentColor()) + , mTabSize(float(NS_STYLE_TABSIZE_INITIAL), eStyleUnit_Factor) , mWordSpacing(0, nsStyleCoord::CoordConstructor) , mLetterSpacing(eStyleUnit_Normal) , mLineHeight(eStyleUnit_Normal) @@ -3845,10 +3845,10 @@ nsStyleText::nsStyleText(const nsStyleText& aSource) , mTextEmphasisPosition(aSource.mTextEmphasisPosition) , mTextEmphasisStyle(aSource.mTextEmphasisStyle) , mTextRendering(aSource.mTextRendering) - , mTabSize(aSource.mTabSize) , mTextEmphasisColor(aSource.mTextEmphasisColor) , mWebkitTextFillColor(aSource.mWebkitTextFillColor) , mWebkitTextStrokeColor(aSource.mWebkitTextStrokeColor) + , mTabSize(aSource.mTabSize) , mWordSpacing(aSource.mWordSpacing) , mLetterSpacing(aSource.mLetterSpacing) , mLineHeight(aSource.mLineHeight) diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 97724571d..c948d6056 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -2088,11 +2088,11 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText uint8_t mTextEmphasisPosition; // [inherited] see nsStyleConsts.h uint8_t mTextEmphasisStyle; // [inherited] see nsStyleConsts.h uint8_t mTextRendering; // [inherited] see nsStyleConsts.h - int32_t mTabSize; // [inherited] see nsStyleConsts.h mozilla::StyleComplexColor mTextEmphasisColor; // [inherited] mozilla::StyleComplexColor mWebkitTextFillColor; // [inherited] mozilla::StyleComplexColor mWebkitTextStrokeColor; // [inherited] + nsStyleCoord mTabSize; // [inherited] coord, factor, calc nsStyleCoord mWordSpacing; // [inherited] coord, percent, calc nsStyleCoord mLetterSpacing; // [inherited] coord, normal nsStyleCoord mLineHeight; // [inherited] coord, factor, normal diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index a7014c043..8624e17dd 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -2033,8 +2033,10 @@ var gCSSProperties = { inherited: true, type: CSS_TYPE_LONGHAND, initial_values: [ "8" ], - other_values: [ "0", "3", "99", "12000" ], - invalid_values: [ "-1", "-808", "3.0", "17.5" ] + other_values: [ "0", "2.5", "3", "99", "12000", "0px", "1em", + "calc(1px + 1em)", "calc(1px - 2px)", "calc(1 + 1)", "calc(-2.5)" ], + invalid_values: [ "9%", "calc(9% + 1px)", "calc(1 + 1em)", "-1", "-808", + "auto" ] }, "-moz-text-size-adjust": { domProp: "MozTextSizeAdjust", |