From a2c26490b4ad94336a7940e691d17f7aef040fa2 Mon Sep 17 00:00:00 2001 From: athenian200 Date: Sun, 25 Oct 2020 14:27:17 -0500 Subject: Issue #1673 - Part 3: Bring minimum tab advance up to spec. This provides a clearer rule for the minimum tab advance that brings us to alignment with the spec and both major browsers. --- layout/generic/nsTextFrame.cpp | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) (limited to 'layout/generic') diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 0aab2717f..07e7a3655 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -1716,6 +1716,16 @@ GetSpaceWidthAppUnits(const gfxTextRun* aTextRun) return spaceWidthAppUnits; } +static gfxFloat +GetMinTabAdvanceAppUnits(const gfxTextRun* aTextRun) +{ + gfxFloat chWidthAppUnits = + NS_round(GetFirstFontMetrics(aTextRun->GetFontGroup(), + aTextRun->IsVertical()).zeroOrAveCharWidth * + aTextRun->GetAppUnitsPerDevUnit()); + return 0.5 * chWidthAppUnits; +} + static nscoord LetterSpacing(nsIFrame* aFrame, const nsStyleText* aStyleText = nullptr) { @@ -3090,6 +3100,7 @@ public: mLength(aLength), mWordSpacing(WordSpacing(aFrame, mTextRun, aTextStyle)), mLetterSpacing(LetterSpacing(aFrame, aTextStyle)), + mMinTabAdvance(-1.0), mHyphenWidth(-1), mOffsetFromBlockOriginForTabs(aOffsetFromBlockOriginForTabs), mReflowing(true), @@ -3114,6 +3125,7 @@ public: mLength(aFrame->GetContentLength()), mWordSpacing(WordSpacing(aFrame, mTextRun)), mLetterSpacing(LetterSpacing(aFrame)), + mMinTabAdvance(-1.0), mHyphenWidth(-1), mOffsetFromBlockOriginForTabs(0), mReflowing(false), @@ -3178,6 +3190,13 @@ public: void CalcTabWidths(Range aTransformedRange, gfxFloat aTabWidth); + gfxFloat MinTabAdvance() { + if (mMinTabAdvance < 0.0) { + mMinTabAdvance = GetMinTabAdvanceAppUnits(mTextRun); + } + return mMinTabAdvance; + } + const gfxSkipCharsIterator& GetEndHint() { return mTempIterator; } protected: @@ -3210,6 +3229,7 @@ protected: int32_t mLength; // DOM string length, may be INT32_MAX gfxFloat mWordSpacing; // space for each whitespace char gfxFloat mLetterSpacing; // space for each letter + gfxFloat mMinTabAdvance; // min advance for char gfxFloat mHyphenWidth; gfxFloat mOffsetFromBlockOriginForTabs; @@ -3465,14 +3485,13 @@ PropertyProvider::GetSpacingInternal(Range aRange, Spacing* aSpacing, // aX and the result are in whole appunits. static gfxFloat -AdvanceToNextTab(gfxFloat aX, nsIFrame* aFrame, - gfxTextRun* aTextRun, gfxFloat aTabWidth) +AdvanceToNextTab(gfxFloat aX, nsIFrame* aFrame, gfxTextRun* aTextRun, + gfxFloat aTabWidth, gfxFloat aMinAdvance) { - // 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 NS_round((aX + 1) / aTabWidth) * aTabWidth; + // Advance aX to the next multiple of aTabWidth. We must advance + // by at least aMinAdvance. + return ceil((aX + aMinAdvance) / aTabWidth) * aTabWidth; } void @@ -3535,7 +3554,7 @@ PropertyProvider::CalcTabWidths(Range aRange, gfxFloat aTabWidth) mFrame->SetProperty(TabWidthProperty(), mTabWidths); } double nextTab = AdvanceToNextTab(mOffsetFromBlockOriginForTabs, - mFrame, mTextRun, aTabWidth); + mFrame, mTextRun, aTabWidth, MinTabAdvance()); mTabWidths->mWidths.AppendElement(TabWidth(i - startOffset, NSToIntRound(nextTab - mOffsetFromBlockOriginForTabs))); mOffsetFromBlockOriginForTabs = nextTab; @@ -8333,8 +8352,8 @@ nsTextFrame::AddInlineMinISizeForFlow(nsRenderingContext *aRenderingContext, tabWidth = ComputeTabWidthAppUnits(this, textRun); } gfxFloat afterTab = - AdvanceToNextTab(aData->mCurrentLine, this, - textRun, tabWidth); + AdvanceToNextTab(aData->mCurrentLine, this, textRun, tabWidth, + provider.MinTabAdvance()); aData->mCurrentLine = nscoord(afterTab + spacing.mAfter); wordStart = i + 1; } else if (i < flowEndInTextRun || @@ -8495,8 +8514,8 @@ nsTextFrame::AddInlinePrefISizeForFlow(nsRenderingContext *aRenderingContext, tabWidth = ComputeTabWidthAppUnits(this, textRun); } gfxFloat afterTab = - AdvanceToNextTab(aData->mCurrentLine, this, - textRun, tabWidth); + AdvanceToNextTab(aData->mCurrentLine, this, textRun, tabWidth, + provider.MinTabAdvance()); aData->mCurrentLine = nscoord(afterTab + spacing.mAfter); lineStart = i + 1; } else if (preformattedNewline) { -- cgit v1.2.3