Bug 1532122 - Make word-spacing, letter-spacing, and line-height use Rust lengths. r=boris

This also adopts the resolution from [1] while at it, making letter-spacing
compute to a length, serializing 0 to normal rather than keeping normal in the
computed value, which matches every other engine.

This removes the SMIL tests for percentages from letter-spacing since
letter-spacing does in fact not support percentages, so they were passing just
by chance.

[1]: https://github.com/w3c/csswg-drafts/issues/1484

Differential Revision: https://phabricator.services.mozilla.com/D21850

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2019-03-04 18:19:40 +00:00
Родитель 2a809aa796
Коммит 25098daaaa
22 изменённых файлов: 170 добавлений и 317 удалений

Просмотреть файл

@ -149,6 +149,16 @@ var _fromToTestLists = {
],
};
function _tweakForLetterSpacing(testcases) {
return testcases.map(function(t) {
let valMap = Object.assign({}, t.computedValMap);
for (let prop of Object.keys(valMap))
if (valMap[prop] == "0px")
valMap[prop] = "normal";
return new AnimTestcaseFromTo(t.from, t.to, valMap)
});
}
// List of attribute/testcase-list bundles to be tested
var gFromToBundles = [
new TestcaseBundle(gPropList.clip, [
@ -341,13 +351,9 @@ var gFromToBundles = [
toComp: "optimizespeed" }),
]),
new TestcaseBundle(gPropList.letter_spacing,
[].concat(_fromToTestLists.lengthNoUnits,
_fromToTestLists.lengthPx,
_fromToTestLists.lengthPxPctSVG)),
new TestcaseBundle(gPropList.letter_spacing,
_fromToTestLists.lengthPctSVG,
"pct->pct animations don't currently work for " +
"*-spacing properties"),
_tweakForLetterSpacing(
[].concat(_fromToTestLists.lengthNoUnits,
_fromToTestLists.lengthPx))),
new TestcaseBundle(gPropList.lighting_color,
[].concat(_fromToTestLists.color,
_fromToTestLists.colorFromInheritWhite)),

Просмотреть файл

@ -201,12 +201,9 @@ LogicalSize nsTextControlFrame::CalcIntrinsicSize(
// Increment width with cols * letter-spacing.
{
const nsStyleCoord& lsCoord = StyleText()->mLetterSpacing;
if (eStyleUnit_Coord == lsCoord.GetUnit()) {
nscoord letterSpacing = lsCoord.GetCoordValue();
if (letterSpacing != 0) {
intrinsicSize.ISize(aWM) += cols * letterSpacing;
}
const StyleLength& letterSpacing = StyleText()->mLetterSpacing;
if (!letterSpacing.IsZero()) {
intrinsicSize.ISize(aWM) += cols * letterSpacing.ToAppUnits();
}
}

Просмотреть файл

@ -734,11 +734,7 @@ void ReflowInput::InitResizeFlags(nsPresContext* aPresContext,
mStylePosition->OffsetHasPercent(wm.PhysicalSide(eLogicalSideBStart)) ||
!mStylePosition->mOffset.GetBEnd(wm).IsAuto() || mFrame->IsXULBoxFrame();
if (mStyleText->mLineHeight.GetUnit() == eStyleUnit_Enumerated) {
NS_ASSERTION(mStyleText->mLineHeight.GetIntValue() ==
NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT,
"bad line-height value");
if (mStyleText->mLineHeight.IsMozBlockHeight()) {
// line-height depends on block bsize
mFrame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
// but only on containing blocks if this frame is not a suitable block
@ -2849,33 +2845,26 @@ static inline nscoord ComputeLineHeight(ComputedStyle* aComputedStyle,
nsPresContext* aPresContext,
nscoord aBlockBSize,
float aFontSizeInflation) {
const nsStyleCoord& lhCoord = aComputedStyle->StyleText()->mLineHeight;
if (lhCoord.GetUnit() == eStyleUnit_Coord) {
nscoord result = lhCoord.GetCoordValue();
const StyleLineHeight& lineHeight = aComputedStyle->StyleText()->mLineHeight;
if (lineHeight.IsLength()) {
nscoord result = lineHeight.length._0.ToAppUnits();
if (aFontSizeInflation != 1.0f) {
result = NSToCoordRound(result * aFontSizeInflation);
}
return result;
}
if (lhCoord.GetUnit() == eStyleUnit_Factor)
if (lineHeight.IsNumber()) {
// For factor units the computed value of the line-height property
// is found by multiplying the factor by the font's computed size
// (adjusted for min-size prefs and text zoom).
return NSToCoordRound(lhCoord.GetFactorValue() * aFontSizeInflation *
return NSToCoordRound(lineHeight.number._0 * aFontSizeInflation *
aComputedStyle->StyleFont()->mFont.size);
}
NS_ASSERTION(lhCoord.GetUnit() == eStyleUnit_Normal ||
lhCoord.GetUnit() == eStyleUnit_Enumerated,
"bad line-height unit");
if (lhCoord.GetUnit() == eStyleUnit_Enumerated) {
NS_ASSERTION(lhCoord.GetIntValue() == NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT,
"bad line-height value");
if (aBlockBSize != NS_AUTOHEIGHT) {
return aBlockBSize;
}
MOZ_ASSERT(lineHeight.IsNormal() || lineHeight.IsMozBlockHeight());
if (lineHeight.IsMozBlockHeight() && aBlockBSize != NS_AUTOHEIGHT) {
return aBlockBSize;
}
RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetFontMetricsForComputedStyle(

Просмотреть файл

@ -1877,7 +1877,7 @@ void nsLineLayout::VerticalAlignFrames(PerSpanData* psd) {
// the frame block size if the user has left line-height == normal
const nsStyleText* styleText = spanFrame->StyleText();
if (spanFramePFD->mIsLetterFrame && !spanFrame->GetPrevInFlow() &&
styleText->mLineHeight.GetUnit() == eStyleUnit_Normal) {
styleText->mLineHeight.IsNormal()) {
logicalBSize = spanFramePFD->mBounds.BSize(lineWM);
}
@ -2191,7 +2191,7 @@ void nsLineLayout::VerticalAlignFrames(PerSpanData* psd) {
// line-height=normal.
canUpdate =
pfd->mIsNonWhitespaceTextFrame &&
frame->StyleText()->mLineHeight.GetUnit() == eStyleUnit_Normal;
frame->StyleText()->mLineHeight.IsNormal();
} else {
canUpdate = !pfd->mIsPlaceholder;
}

Просмотреть файл

@ -1729,7 +1729,7 @@ static gfxFont::Metrics GetFirstFontMetrics(gfxFontGroup* aFontGroup,
: gfxFont::eHorizontal);
}
static gfxFloat GetSpaceWidthAppUnits(const gfxTextRun* aTextRun) {
static nscoord GetSpaceWidthAppUnits(const gfxTextRun* aTextRun) {
// Round the space width when converting to appunits the same way textruns
// do.
gfxFloat spaceWidthAppUnits =
@ -1757,12 +1757,7 @@ static nscoord LetterSpacing(nsIFrame* aFrame,
if (!aStyleText) {
aStyleText = aFrame->StyleText();
}
const nsStyleCoord& coord = aStyleText->mLetterSpacing;
if (eStyleUnit_Coord == coord.GetUnit()) {
return coord.GetCoordValue();
}
return 0;
return aStyleText->mLetterSpacing.ToAppUnits();
}
// This function converts non-coord values (e.g. percentages) to nscoord.
@ -1775,12 +1770,9 @@ static nscoord WordSpacing(nsIFrame* aFrame, const gfxTextRun* aTextRun,
aStyleText = aFrame->StyleText();
}
const nsStyleCoord& coord = aStyleText->mWordSpacing;
if (coord.IsCoordPercentCalcUnit()) {
nscoord pctBasis = coord.HasPercent() ? GetSpaceWidthAppUnits(aTextRun) : 0;
return coord.ComputeCoordPercentCalc(pctBasis);
}
return 0;
return aStyleText->mWordSpacing.Resolve([&] {
return GetSpaceWidthAppUnits(aTextRun);
});
}
// Returns gfxTextRunFactory::TEXT_ENABLE_SPACING if non-standard
@ -1792,20 +1784,14 @@ static gfx::ShapedTextFlags GetSpacingFlags(
}
const nsStyleText* styleText = aFrame->StyleText();
const nsStyleCoord& ls = styleText->mLetterSpacing;
const nsStyleCoord& ws = styleText->mWordSpacing;
const auto& ls = styleText->mLetterSpacing;
const auto& ws = styleText->mWordSpacing;
// It's possible to have a calc() value that computes to zero but for which
// IsDefinitelyZero() is false, in which case we'll return
// TEXT_ENABLE_SPACING unnecessarily. That's ok because such cases are likely
// to be rare, and avoiding TEXT_ENABLE_SPACING is just an optimization.
bool nonStandardSpacing =
(eStyleUnit_Coord == ls.GetUnit() && ls.GetCoordValue() != 0) ||
(eStyleUnit_Coord == ws.GetUnit() && ws.GetCoordValue() != 0) ||
(eStyleUnit_Percent == ws.GetUnit() && ws.GetPercentValue() != 0) ||
(eStyleUnit_Calc == ws.GetUnit() &&
!ws.GetCalcValue()->IsDefinitelyZero());
bool nonStandardSpacing = !ls.IsZero() || !ws.IsDefinitelyZero();
return nonStandardSpacing ? gfx::ShapedTextFlags::TEXT_ENABLE_SPACING
: gfx::ShapedTextFlags();
}

Просмотреть файл

@ -446,6 +446,8 @@ cbindgen-types = [
{ gecko = "StyleGenericZIndex", servo = "values::generics::position::ZIndex" },
{ gecko = "StyleTransformOrigin", servo = "values::computed::TransformOrigin" },
{ gecko = "StyleGenericBorderRadius", servo = "values::generics::border::BorderRadius" },
{ gecko = "StyleLetterSpacing", servo = "values::computed::text::LetterSpacing" },
{ gecko = "StyleGenericLineHeight", servo = "values::generics::text::LineHeight" },
]
mapped-generic-types = [

Просмотреть файл

@ -101,7 +101,6 @@ LONGHANDS_NOT_SERIALIZED_WITH_SERVO = [
"grid-row-start",
"grid-template-areas",
"initial-letter",
"letter-spacing",
"marker-end",
"marker-mid",
"marker-start",
@ -140,7 +139,6 @@ LONGHANDS_NOT_SERIALIZED_WITH_SERVO = [
"vertical-align",
"-webkit-text-stroke-width",
"will-change",
"word-spacing",
]
def serialized_by_servo(prop):

Просмотреть файл

@ -2012,14 +2012,25 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetInitialLetter() {
already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetLineHeight() {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
nscoord lineHeight;
if (GetLineHeightCoord(lineHeight)) {
val->SetAppUnits(lineHeight);
} else {
SetValueToCoord(val, StyleText()->mLineHeight, true, nullptr,
nsCSSProps::kLineHeightKTable);
{
nscoord lineHeight;
if (GetLineHeightCoord(lineHeight)) {
val->SetAppUnits(lineHeight);
return val.forget();
}
}
auto& lh = StyleText()->mLineHeight;
if (lh.IsLength()) {
val->SetAppUnits(lh.length._0.ToAppUnits());
} else if (lh.IsNumber()) {
val->SetNumber(lh.number._0);
} else if (lh.IsMozBlockHeight()) {
val->SetIdent(eCSSKeyword__moz_block_height);
} else {
MOZ_ASSERT(lh.IsNormal());
val->SetIdent(eCSSKeyword_normal);
}
return val.forget();
}
@ -2188,18 +2199,6 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetTextShadow() {
return GetCSSShadowArray(StyleText()->mTextShadow, false);
}
already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetLetterSpacing() {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToCoord(val, StyleText()->mLetterSpacing, false);
return val.forget();
}
already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetWordSpacing() {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToCoord(val, StyleText()->mWordSpacing, false);
return val.forget();
}
already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetWebkitTextStrokeWidth() {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetAppUnits(StyleText()->mWebkitTextStrokeWidth);
@ -2674,7 +2673,7 @@ bool nsComputedDOMStyle::GetLineHeightCoord(nscoord& aCoord) {
AssertFlushedPendingReflows();
nscoord blockHeight = NS_AUTOHEIGHT;
if (StyleText()->mLineHeight.GetUnit() == eStyleUnit_Enumerated) {
if (StyleText()->mLineHeight.IsMozBlockHeight()) {
if (!mInnerFrame) return false;
if (nsLayoutUtils::IsNonWrapperBlock(mInnerFrame)) {

Просмотреть файл

@ -294,7 +294,6 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
already_AddRefed<CSSValue> DoGetBorderTopLeftRadius();
already_AddRefed<CSSValue> DoGetBorderTopRightRadius();
/* Border Image */
already_AddRefed<CSSValue> DoGetBorderImageWidth();
@ -314,7 +313,6 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
already_AddRefed<CSSValue> DoGetOutlineRadiusTopLeft();
already_AddRefed<CSSValue> DoGetOutlineRadiusTopRight();
/* Text Properties */
already_AddRefed<CSSValue> DoGetInitialLetter();
already_AddRefed<CSSValue> DoGetLineHeight();
@ -326,8 +324,6 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
already_AddRefed<CSSValue> DoGetTextEmphasisStyle();
already_AddRefed<CSSValue> DoGetTextOverflow();
already_AddRefed<CSSValue> DoGetTextShadow();
already_AddRefed<CSSValue> DoGetLetterSpacing();
already_AddRefed<CSSValue> DoGetWordSpacing();
already_AddRefed<CSSValue> DoGetWebkitTextStrokeWidth();
/* Display properties */
@ -379,8 +375,6 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
already_AddRefed<CSSValue> DoGetMarkerMid();
already_AddRefed<CSSValue> DoGetMarkerStart();
already_AddRefed<CSSValue> DoGetFilter();
already_AddRefed<CSSValue> DoGetPaintOrder();

Просмотреть файл

@ -46,6 +46,10 @@ using NonNegativeLengthPercentageOrAuto =
StyleNonNegativeLengthPercentageOrAuto;
using BorderRadius = StyleBorderRadius;
bool StyleCSSPixelLength::IsZero() const {
return _0 == 0.0f;
}
nscoord StyleCSSPixelLength::ToAppUnits() const {
// We want to resolve the length part of the calc() expression rounding 0.5
// away from zero, instead of the default behavior of NSToCoordRoundWithClamp
@ -95,7 +99,7 @@ nscoord LengthPercentage::ToLength() const {
}
bool LengthPercentage::ConvertsToPercentage() const {
return has_percentage && length._0 == 0.0f;
return has_percentage && length.IsZero();
}
float LengthPercentage::ToPercentage() const {
@ -107,6 +111,10 @@ bool LengthPercentage::HasLengthAndPercentage() const {
return !ConvertsToLength() && !ConvertsToPercentage();
}
bool LengthPercentage::IsDefinitelyZero() const {
return length.IsZero() && Percentage() == 0.0f;
}
CSSCoord LengthPercentage::ResolveToCSSPixels(CSSCoord aPercentageBasis) const {
return LengthInCSSPixels() + Percentage() * aPercentageBasis;
}

Просмотреть файл

@ -3711,9 +3711,9 @@ nsStyleText::nsStyleText(const Document& aDocument)
mWebkitTextStrokeColor(StyleComplexColor::CurrentColor()),
mMozTabSize(
StyleNonNegativeLengthOrNumber::Number(NS_STYLE_TABSIZE_INITIAL)),
mWordSpacing(0, nsStyleCoord::CoordConstructor),
mLetterSpacing(eStyleUnit_Normal),
mLineHeight(eStyleUnit_Normal),
mWordSpacing(LengthPercentage::Zero()),
mLetterSpacing({0.}),
mLineHeight(StyleLineHeight::Normal()),
mTextIndent(LengthPercentage::Zero()),
mWebkitTextStrokeWidth(0),
mTextShadow(nullptr) {

Просмотреть файл

@ -1476,9 +1476,9 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText {
mozilla::StyleComplexColor mWebkitTextStrokeColor;
mozilla::StyleNonNegativeLengthOrNumber mMozTabSize;
nsStyleCoord mWordSpacing; // coord, percent, calc
nsStyleCoord mLetterSpacing; // coord, normal
nsStyleCoord mLineHeight; // coord, factor, normal
mozilla::LengthPercentage mWordSpacing;
mozilla::StyleLetterSpacing mLetterSpacing;
mozilla::StyleLineHeight mLineHeight;
mozilla::LengthPercentage mTextIndent;
nscoord mWebkitTextStrokeWidth; // coord

Просмотреть файл

@ -3962,11 +3962,9 @@ var gCSSProperties = {
applies_to_first_letter: true,
applies_to_first_line: true,
applies_to_placeholder: true,
initial_values: [ "normal" ],
other_values: [ "0", "0px", "1em", "2px", "-3px",
"calc(0px)", "calc(1em)", "calc(1em + 3px)",
"calc(15px / 2)", "calc(15px/2)", "calc(-3px)"
],
initial_values: [ "normal", "0", "0px", "calc(0px)" ],
other_values: [ "1em", "2px", "-3px", "calc(1em)", "calc(1em + 3px)",
"calc(15px / 2)", "calc(15px/2)", "calc(-3px)" ],
invalid_values: [],
quirks_values: { "5": "5px" },
},

Просмотреть файл

@ -1284,11 +1284,10 @@ function test_length_clamped_or_unclamped(prop, is_clamped) {
div.style.setProperty("transition-timing-function", FUNC_NEGATIVE, "");
div.style.setProperty("transition-property", "none", "");
div.style.setProperty(prop, "0px", "");
is(cs.getPropertyValue(prop), "0px",
"length-valued property " + prop + ": flush before clamping test");
let zero_val = cs.getPropertyValue(prop); // Flushes
div.style.setProperty("transition-property", prop, "");
div.style.setProperty(prop, "100px", "");
(is_clamped ? is : isnot)(cs.getPropertyValue(prop), "0px",
(is_clamped ? is : isnot)(cs.getPropertyValue(prop), zero_val,
"length-valued property " + prop + ": clamping of negatives");
div.style.setProperty("transition-timing-function", "linear", "");
}

Просмотреть файл

@ -78,8 +78,10 @@ include = [
"Resize",
"Overflow",
"LengthPercentage",
"LetterSpacing",
"NonNegativeLengthPercentage",
"LengthPercentageOrAuto",
"LineHeight",
"NonNegativeLengthPercentageOrAuto",
"Rect",
"IntersectionObserverRootMargin",
@ -102,6 +104,7 @@ item_types = ["enums", "structs", "typedefs"]
[export.body]
"CSSPixelLength" = """
inline nscoord ToAppUnits() const;
inline bool IsZero() const;
"""
"LengthPercentage" = """
@ -118,6 +121,7 @@ item_types = ["enums", "structs", "typedefs"]
inline bool ConvertsToPercentage() const;
inline bool HasLengthAndPercentage() const;
inline float ToPercentage() const;
inline bool IsDefinitelyZero() const;
inline CSSCoord ResolveToCSSPixels(CSSCoord aPercentageBasisInCSSPixels) const;
template<typename T> inline CSSCoord ResolveToCSSPixelsWith(T aPercentageGetter) const;
template<typename T, typename U>

Просмотреть файл

@ -1227,56 +1227,23 @@ impl Clone for ${style_struct.gecko_struct_name} {
# Types used with predefined_type()-defined properties that we can auto-generate.
predefined_types = {
"Appearance": impl_simple,
"OverscrollBehavior": impl_simple,
"OverflowClipBox": impl_simple,
"ScrollSnapAlign": impl_simple,
"ScrollSnapType": impl_simple,
"Float": impl_simple,
"Overflow": impl_simple,
"BreakBetween": impl_simple,
"BreakWithin": impl_simple,
"Resize": impl_simple,
"Color": impl_color,
"ColorOrAuto": impl_color,
"GreaterThanOrEqualToOneNumber": impl_simple,
"Integer": impl_simple,
"length::LengthOrAuto": impl_style_coord,
"length::LengthOrNormal": impl_style_coord,
"length::NonNegativeLengthOrAuto": impl_style_coord,
"length::NonNegativeLengthPercentageOrNormal": impl_style_coord,
"FillRule": impl_simple,
"FlexBasis": impl_simple,
"Length": impl_absolute_length,
"LengthOrNormal": impl_style_coord,
"LengthPercentage": impl_simple,
"LengthPercentageOrAuto": impl_style_coord,
"MaxSize": impl_simple,
"Size": impl_simple,
"MozScriptMinSize": impl_absolute_length,
"MozScriptSizeMultiplier": impl_simple,
"NonNegativeLengthPercentage": impl_simple,
"NonNegativeLengthOrNumber": impl_simple,
"NonNegativeLengthOrNumberRect": impl_simple,
"BorderImageSlice": impl_simple,
"NonNegativeNumber": impl_simple,
"Number": impl_simple,
"Opacity": impl_simple,
"OverflowWrap": impl_simple,
"OverflowAnchor": impl_simple,
"Perspective": impl_simple,
"Position": impl_simple,
"RGBAColor": impl_rgba_color,
"SVGLength": impl_svg_length,
"SVGOpacity": impl_svg_opacity,
"SVGPaint": impl_svg_paint,
"SVGWidth": impl_svg_length,
"Transform": impl_transform,
"TransformOrigin": impl_simple,
"UserSelect": impl_simple,
"url::UrlOrNone": impl_css_url,
"WordBreak": impl_simple,
"ZIndex": impl_simple,
}
def longhand_method(longhand):
@ -1291,15 +1258,12 @@ impl Clone for ${style_struct.gecko_struct_name} {
args.update(keyword=longhand.keyword)
if "font" in longhand.ident:
args.update(cast_type=longhand.cast_type)
else:
elif longhand.predefined_type in predefined_types:
method = predefined_types[longhand.predefined_type]
else:
method = impl_simple
method(**args)
picked_longhands = []
for x in longhands:
if x.keyword or x.predefined_type in predefined_types or x.logical:
picked_longhands.append(x)
%>
impl ${style_struct.gecko_struct_name} {
/*
@ -1311,7 +1275,7 @@ impl ${style_struct.gecko_struct_name} {
* Auto-Generated Methods.
*/
<%
for longhand in picked_longhands:
for longhand in longhands:
longhand_method(longhand)
%>
}
@ -1992,6 +1956,7 @@ fn static_assert() {
<%
skip_font_longhands = """font-family font-size font-size-adjust font-weight
font-style font-stretch -moz-script-level
font-synthesis -x-lang font-variant-alternates
font-variant-east-asian font-variant-ligatures
font-variant-numeric font-language-override
@ -2783,6 +2748,7 @@ fn static_assert() {
animation-iteration-count animation-timing-function
clear transition-duration transition-delay
transition-timing-function transition-property
transform-style
rotate scroll-snap-points-x scroll-snap-points-y
scroll-snap-coordinate -moz-binding will-change
offset-path shape-outside contain touch-action
@ -4158,7 +4124,7 @@ fn static_assert() {
<%self:impl_trait style_struct_name="InheritedText"
skip_longhands="text-align text-emphasis-style text-shadow line-height letter-spacing word-spacing
skip_longhands="text-align text-emphasis-style text-shadow
-webkit-text-stroke-width text-emphasis-position">
<% text_align_keyword = Keyword("text-align",
@ -4190,78 +4156,6 @@ fn static_assert() {
longhands::text_shadow::computed_value::List(buf)
}
pub fn set_line_height(&mut self, v: longhands::line_height::computed_value::T) {
use crate::values::generics::text::LineHeight;
// FIXME: Align binary representations and ditch |match| for cast + static_asserts
let en = match v {
LineHeight::Normal => CoordDataValue::Normal,
LineHeight::Length(val) => CoordDataValue::Coord(val.0.to_i32_au()),
LineHeight::Number(val) => CoordDataValue::Factor(val.0),
LineHeight::MozBlockHeight =>
CoordDataValue::Enumerated(structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT),
};
self.gecko.mLineHeight.set_value(en);
}
pub fn clone_line_height(&self) -> longhands::line_height::computed_value::T {
use crate::values::generics::text::LineHeight;
return match self.gecko.mLineHeight.as_value() {
CoordDataValue::Normal => LineHeight::Normal,
CoordDataValue::Coord(coord) => LineHeight::Length(Au(coord).into()),
CoordDataValue::Factor(n) => LineHeight::Number(n.into()),
CoordDataValue::Enumerated(val) if val == structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT =>
LineHeight::MozBlockHeight,
_ => panic!("this should not happen"),
}
}
<%call expr="impl_coord_copy('line_height', 'mLineHeight')"></%call>
pub fn set_letter_spacing(&mut self, v: longhands::letter_spacing::computed_value::T) {
use crate::values::generics::text::Spacing;
match v {
Spacing::Value(value) => self.gecko.mLetterSpacing.set(value),
Spacing::Normal => self.gecko.mLetterSpacing.set_value(CoordDataValue::Normal)
}
}
pub fn clone_letter_spacing(&self) -> longhands::letter_spacing::computed_value::T {
use crate::values::computed::Length;
use crate::values::generics::text::Spacing;
debug_assert!(
matches!(self.gecko.mLetterSpacing.as_value(),
CoordDataValue::Normal |
CoordDataValue::Coord(_)),
"Unexpected computed value for letter-spacing");
Length::from_gecko_style_coord(&self.gecko.mLetterSpacing).map_or(Spacing::Normal, Spacing::Value)
}
<%call expr="impl_coord_copy('letter_spacing', 'mLetterSpacing')"></%call>
pub fn set_word_spacing(&mut self, v: longhands::word_spacing::computed_value::T) {
use crate::values::generics::text::Spacing;
match v {
Spacing::Value(lp) => self.gecko.mWordSpacing.set(lp),
// https://drafts.csswg.org/css-text-3/#valdef-word-spacing-normal
Spacing::Normal => self.gecko.mWordSpacing.set_value(CoordDataValue::Coord(0)),
}
}
pub fn clone_word_spacing(&self) -> longhands::word_spacing::computed_value::T {
use crate::values::computed::LengthPercentage;
use crate::values::generics::text::Spacing;
debug_assert!(
matches!(self.gecko.mWordSpacing.as_value(),
CoordDataValue::Normal |
CoordDataValue::Coord(_) |
CoordDataValue::Percent(_) |
CoordDataValue::Calc(_)),
"Unexpected computed value for word-spacing");
LengthPercentage::from_gecko_style_coord(&self.gecko.mWordSpacing).map_or(Spacing::Normal, Spacing::Value)
}
<%call expr="impl_coord_copy('word_spacing', 'mWordSpacing')"></%call>
fn clear_text_emphasis_style_if_string(&mut self) {
if self.gecko.mTextEmphasisStyle == structs::NS_STYLE_TEXT_EMPHASIS_STYLE_STRING as u8 {
self.gecko.mTextEmphasisStyleString.truncate();

Просмотреть файл

@ -157,7 +157,7 @@ ${helpers.predefined_type(
${helpers.predefined_type(
"word-spacing",
"WordSpacing",
"computed::WordSpacing::normal()",
"computed::WordSpacing::zero()",
animation_value_type="ComputedValue",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text/#propdef-word-spacing",

Просмотреть файл

@ -7,13 +7,14 @@
#[cfg(feature = "servo")]
use crate::properties::StyleBuilder;
use crate::values::computed::length::{Length, LengthPercentage};
use crate::values::computed::{NonNegativeLength, NonNegativeNumber};
use crate::values::computed::{Context, NonNegativeLength, NonNegativeNumber, ToComputedValue};
use crate::values::generics::text::InitialLetter as GenericInitialLetter;
use crate::values::generics::text::LineHeight as GenericLineHeight;
use crate::values::generics::text::Spacing;
use crate::values::specified::text::TextOverflowSide;
use crate::values::specified::text::{self as specified, TextOverflowSide};
use crate::values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword};
use crate::values::{CSSFloat, CSSInteger};
use crate::Zero;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
@ -25,10 +26,78 @@ pub use crate::values::specified::TextEmphasisPosition;
pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
/// A computed value for the `letter-spacing` property.
pub type LetterSpacing = Spacing<Length>;
#[repr(transparent)]
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
ToAnimatedValue,
ToAnimatedZero,
)]
pub struct LetterSpacing(Length);
impl LetterSpacing {
/// Return the `normal` computed value, which is just zero.
#[inline]
pub fn normal() -> Self {
LetterSpacing(Length::zero())
}
}
impl ToCss for LetterSpacing {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
// https://drafts.csswg.org/css-text/#propdef-letter-spacing
//
// For legacy reasons, a computed letter-spacing of zero yields a
// resolved value (getComputedStyle() return value) of normal.
if self.0.is_zero() {
return dest.write_str("normal");
}
self.0.to_css(dest)
}
}
impl ToComputedValue for specified::LetterSpacing {
type ComputedValue = LetterSpacing;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
match *self {
Spacing::Normal => LetterSpacing(Length::zero()),
Spacing::Value(ref v) => LetterSpacing(v.to_computed_value(context)),
}
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
if computed.0.is_zero() {
return Spacing::Normal;
}
Spacing::Value(ToComputedValue::from_computed_value(&computed.0))
}
}
/// A computed value for the `word-spacing` property.
pub type WordSpacing = Spacing<LengthPercentage>;
pub type WordSpacing = LengthPercentage;
impl ToComputedValue for specified::WordSpacing {
type ComputedValue = WordSpacing;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
match *self {
Spacing::Normal => LengthPercentage::zero(),
Spacing::Value(ref v) => v.to_computed_value(context),
}
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
Spacing::Value(ToComputedValue::from_computed_value(computed))
}
}
/// A computed value for the `line-height` property.
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>;

Просмотреть файл

@ -5,9 +5,7 @@
//! Generic types for text properties.
use crate::parser::ParserContext;
use crate::values::animated::{Animate, Procedure, ToAnimatedZero};
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
use app_units::Au;
use crate::values::animated::ToAnimatedZero;
use cssparser::Parser;
use style_traits::ParseError;
@ -32,7 +30,7 @@ impl<N, I> InitialLetter<N, I> {
/// A generic spacing value for the `letter-spacing` and `word-spacing` properties.
#[derive(
Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss,
)]
pub enum Spacing<Value> {
/// `normal`
@ -63,51 +61,6 @@ impl<Value> Spacing<Value> {
}
parse(context, input).map(Spacing::Value)
}
/// Returns the spacing value, if not `normal`.
#[inline]
pub fn value(&self) -> Option<&Value> {
match *self {
Spacing::Normal => None,
Spacing::Value(ref value) => Some(value),
}
}
}
impl<Value> Animate for Spacing<Value>
where
Value: Animate + From<Au>,
{
#[inline]
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
if let (&Spacing::Normal, &Spacing::Normal) = (self, other) {
return Ok(Spacing::Normal);
}
let zero = Value::from(Au(0));
let this = self.value().unwrap_or(&zero);
let other = other.value().unwrap_or(&zero);
Ok(Spacing::Value(this.animate(other, procedure)?))
}
}
impl<V> ComputeSquaredDistance for Spacing<V>
where
V: ComputeSquaredDistance + From<Au>,
{
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
let zero = V::from(Au(0));
let this = self.value().unwrap_or(&zero);
let other = other.value().unwrap_or(&zero);
this.compute_squared_distance(other)
}
}
impl<V> ToAnimatedZero for Spacing<V> {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Err(())
}
}
/// A generic value for the `line-height` property.
@ -123,18 +76,21 @@ impl<V> ToAnimatedZero for Spacing<V> {
ToAnimatedValue,
ToCss,
)]
pub enum LineHeight<Number, LengthPercentage> {
#[repr(C, u8)]
pub enum GenericLineHeight<N, L> {
/// `normal`
Normal,
/// `-moz-block-height`
#[cfg(feature = "gecko")]
MozBlockHeight,
/// `<number>`
Number(Number),
/// `<length-or-percentage>`
Length(LengthPercentage),
Number(N),
/// `<length-percentage>`
Length(L),
}
pub use self::GenericLineHeight as LineHeight;
impl<N, L> ToAnimatedZero for LineHeight<N, L> {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {

Просмотреть файл

@ -1,16 +1,5 @@
prefs: [layout.css.font-variations.enabled:true, layout.css.overflow-clip-box.enabled:true, layout.css.individual-transform.enabled:true]
[accumulation-per-property.html]
[word-spacing: calc]
expected: FAIL
[word-spacing: units "calc" onto "px"]
expected: FAIL
[word-spacing: units "rem" onto "%"]
expected: FAIL
[word-spacing: units "px" onto "%"]
expected: FAIL
[flex-basis: units "%" onto "px"]
expected: FAIL
@ -18,9 +7,6 @@ prefs: [layout.css.font-variations.enabled:true, layout.css.overflow-clip-box.en
[flex-basis: units "%" onto "rem"]
expected: FAIL
[word-spacing: units "%" onto "px"]
expected: FAIL
[flex-basis: units "px" onto "%"]
expected: FAIL
@ -30,9 +16,6 @@ prefs: [layout.css.font-variations.enabled:true, layout.css.overflow-clip-box.en
[flex-basis: units "rem" onto "%"]
expected: FAIL
[word-spacing: units "%" onto "rem"]
expected: FAIL
[flex-basis: units "calc" onto "px"]
expected: FAIL

Просмотреть файл

@ -1,13 +1,5 @@
prefs: [layout.css.font-variations.enabled:true, layout.css.overflow-clip-box.enabled:true, layout.css.individual-transform.enabled:true]
[addition-per-property.html]
[word-spacing: calc]
expected: FAIL
[word-spacing: units "rem" onto "%"]
expected: FAIL
[word-spacing: units "px" onto "%"]
expected: FAIL
[flex-basis: units "px" onto "%"]
expected: FAIL
@ -15,12 +7,6 @@ prefs: [layout.css.font-variations.enabled:true, layout.css.overflow-clip-box.en
[flex-basis: units "%" onto "rem"]
expected: FAIL
[word-spacing: units "calc" onto "px"]
expected: FAIL
[word-spacing: units "%" onto "px"]
expected: FAIL
[flex-basis: calc]
expected: FAIL
@ -30,9 +16,6 @@ prefs: [layout.css.font-variations.enabled:true, layout.css.overflow-clip-box.en
[flex-basis: units "%" onto "px"]
expected: FAIL
[word-spacing: units "%" onto "rem"]
expected: FAIL
[flex-basis: units "calc" onto "px"]
expected: FAIL

Просмотреть файл

@ -7,24 +7,12 @@ prefs: [layout.css.font-variations.enabled:true, layout.css.overflow-clip-box.en
[flex-basis supports animating as combination units "px" and "%"]
expected: FAIL
[word-spacing supports animating as combination units "px" and "%"]
expected: FAIL
[flex-basis supports animating as combination units "px" and "calc"]
expected: FAIL
[flex-basis supports animating as a calc]
expected: FAIL
[word-spacing supports animating as combination units "px" and "calc"]
expected: FAIL
[word-spacing supports animating as a calc]
expected: FAIL
[word-spacing supports animating as combination units "%" and "em"]
expected: FAIL
[flex-basis supports animating as combination units "%" and "em"]
expected: FAIL