Issue #1673 - Part 1: Allow tab-size to accept <length>.

Currently -moz-tab-size only accepts <number> values, and both Chrome and Firefox currently support <length> values and have for some time now. So with this you would be able to support sizes in px or em, for instance. This was implemented in Firefox 53 and was trivial to backport.
This commit is contained in:
athenian200 2020-10-23 14:34:55 -05:00 committed by roytam1
commit 633d50eb3f
7 changed files with 124 additions and 62 deletions

View file

@ -3176,7 +3176,7 @@ public:
return mFontMetrics;
}
void CalcTabWidths(Range aTransformedRange);
void CalcTabWidths(Range aTransformedRange, gfxFloat aTabWidth);
const gfxSkipCharsIterator& GetEndHint() { return mTempIterator; }
@ -3362,6 +3362,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)
@ -3409,17 +3431,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());
}
}
}
@ -3442,33 +3463,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
@ -3503,7 +3514,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);
@ -3525,7 +3535,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;
@ -8319,9 +8329,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 ||
@ -8478,9 +8491,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) {

View file

@ -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)

View file

@ -4013,7 +4013,7 @@ already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetTabSize()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetNumber(StyleText()->mTabSize);
SetValueToCoord(val, StyleText()->mTabSize, true);
return val.forget();
}

View file

@ -4507,20 +4507,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),
@ -4535,15 +4535,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;
}
@ -4553,9 +4553,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;
}
@ -4563,39 +4563,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;
@ -4619,11 +4649,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(),
@ -4666,12 +4710,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 {

View file

@ -3806,10 +3806,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)
@ -3844,10 +3844,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)

View file

@ -2087,11 +2087,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

View file

@ -2032,8 +2032,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",