Bug 1176792 part 1 - [css-grid] Implement the 'grid-column-gap', 'grid-row-gap', and 'grid-gap' properties in the style system. r=dholbert,dbaron

This commit is contained in:
Mats Palmgren 2015-11-18 19:52:27 +01:00
Родитель a852415412
Коммит 0edbd4ad4c
13 изменённых файлов: 245 добавлений и 2 удалений

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

@ -1019,6 +1019,18 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue,
// This can express either grid-template-{areas,columns,rows}
// or grid-auto-{flow,columns,rows}, but not both.
case eCSSProperty_grid: {
const nsCSSValue& columnGapValue =
*data->ValueFor(eCSSProperty_grid_column_gap);
if (columnGapValue.GetUnit() != eCSSUnit_Pixel ||
columnGapValue.GetFloatValue() != 0.0f) {
return; // Not serializable, bail.
}
const nsCSSValue& rowGapValue =
*data->ValueFor(eCSSProperty_grid_row_gap);
if (rowGapValue.GetUnit() != eCSSUnit_Pixel ||
rowGapValue.GetFloatValue() != 0.0f) {
return; // Not serializable, bail.
}
const nsCSSValue& areasValue =
*data->ValueFor(eCSSProperty_grid_template_areas);
const nsCSSValue& columnsValue =
@ -1151,6 +1163,25 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue,
}
break;
}
case eCSSProperty_grid_gap: {
const nsCSSProperty* subprops =
nsCSSProps::SubpropertyEntryFor(aProperty);
MOZ_ASSERT(subprops[2] == eCSSProperty_UNKNOWN,
"must have exactly two subproperties");
nsAutoString val1, val2;
AppendValueToString(subprops[0], val1, aSerialization);
AppendValueToString(subprops[1], val2, aSerialization);
if (val1 == val2) {
aValue.Append(val1);
} else {
aValue.Append(val1);
aValue.Append(' ');
aValue.Append(val2);
}
break;
}
case eCSSProperty__moz_transform: {
// shorthands that are just aliases with different parsing rules
const nsCSSProperty* subprops =

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

@ -960,6 +960,7 @@ protected:
bool ParseGridColumnRow(nsCSSProperty aStartPropID,
nsCSSProperty aEndPropID);
bool ParseGridArea();
bool ParseGridGap();
// parsing 'align/justify-items/self' from the css-align spec
bool ParseAlignJustifyPosition(nsCSSValue& aResult,
@ -9146,6 +9147,13 @@ CSSParserImpl::ParseGrid()
return false;
}
// https://drafts.csswg.org/css-grid/#grid-shorthand
// "Also, the gutter properties are reset by this shorthand,
// even though they can't be set by it."
value.SetFloatValue(0.0f, eCSSUnit_Pixel);
AppendValue(eCSSProperty_grid_column_gap, value);
AppendValue(eCSSProperty_grid_row_gap, value);
// The values starts with a <'grid-auto-flow'> if and only if
// it starts with a 'dense', 'column' or 'row' keyword.
if (mToken.mType == eCSSToken_Ident) {
@ -9411,6 +9419,30 @@ CSSParserImpl::ParseGridArea()
return true;
}
bool
CSSParserImpl::ParseGridGap()
{
nsCSSValue first;
if (ParseSingleTokenVariant(first, VARIANT_INHERIT, nullptr)) {
AppendValue(eCSSProperty_grid_column_gap, first);
AppendValue(eCSSProperty_grid_row_gap, first);
return true;
}
if (ParseNonNegativeVariant(first, VARIANT_LCALC, nullptr) !=
CSSParseResult::Ok) {
return false;
}
nsCSSValue second;
auto result = ParseNonNegativeVariant(second, VARIANT_LCALC, nullptr);
if (result == CSSParseResult::Error) {
return false;
}
AppendValue(eCSSProperty_grid_column_gap, first);
AppendValue(eCSSProperty_grid_row_gap,
result == CSSParseResult::NotFound ? first : second);
return true;
}
// [ $aTable && <overflow-position>? ] ?
// $aTable is for <content-position> or <self-position>
bool
@ -10655,6 +10687,8 @@ CSSParserImpl::ParsePropertyByFunction(nsCSSProperty aPropID)
eCSSProperty_grid_row_end);
case eCSSProperty_grid_area:
return ParseGridArea();
case eCSSProperty_grid_gap:
return ParseGridGap();
case eCSSProperty_image_region:
return ParseRect(eCSSProperty_image_region);
case eCSSProperty_align_content:

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

@ -2125,6 +2125,34 @@ CSS_PROP_SHORTHAND(
GridArea,
CSS_PROPERTY_PARSE_FUNCTION,
"layout.css.grid.enabled")
CSS_PROP_POSITION(
grid-column-gap,
grid_column_gap,
GridColumnGap,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_VALUE_NONNEGATIVE,
"layout.css.grid.enabled",
VARIANT_HL | VARIANT_CALC,
nullptr,
offsetof(nsStylePosition, mGridColumnGap),
eStyleAnimType_nscoord)
CSS_PROP_POSITION(
grid-row-gap,
grid_row_gap,
GridRowGap,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_VALUE_NONNEGATIVE,
"layout.css.grid.enabled",
VARIANT_HL | VARIANT_CALC,
nullptr,
offsetof(nsStylePosition, mGridRowGap),
eStyleAnimType_nscoord)
CSS_PROP_SHORTHAND(
grid-gap,
grid_gap,
GridGap,
CSS_PROPERTY_PARSE_FUNCTION,
"layout.css.grid.enabled")
CSS_PROP_POSITION(
height,
height,

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

@ -2702,6 +2702,8 @@ static const nsCSSProperty gGridSubpropTable[] = {
eCSSProperty_grid_auto_flow,
eCSSProperty_grid_auto_columns,
eCSSProperty_grid_auto_rows,
eCSSProperty_grid_column_gap, // can only be reset, not get/set
eCSSProperty_grid_row_gap, // can only be reset, not get/set
eCSSProperty_UNKNOWN
};
@ -2725,6 +2727,12 @@ static const nsCSSProperty gGridAreaSubpropTable[] = {
eCSSProperty_UNKNOWN
};
static const nsCSSProperty gGridGapSubpropTable[] = {
eCSSProperty_grid_column_gap,
eCSSProperty_grid_row_gap,
eCSSProperty_UNKNOWN
};
static const nsCSSProperty gOverflowSubpropTable[] = {
eCSSProperty_overflow_x,
eCSSProperty_overflow_y,

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

@ -2556,6 +2556,22 @@ nsComputedDOMStyle::DoGetGridRowEnd()
return GetGridLine(StylePosition()->mGridRowEnd);
}
CSSValue*
nsComputedDOMStyle::DoGetGridColumnGap()
{
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
val->SetAppUnits(StylePosition()->mGridColumnGap);
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetGridRowGap()
{
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
val->SetAppUnits(StylePosition()->mGridRowGap);
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetPaddingTop()
{

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

@ -266,6 +266,8 @@ private:
mozilla::dom::CSSValue* DoGetGridColumnEnd();
mozilla::dom::CSSValue* DoGetGridRowStart();
mozilla::dom::CSSValue* DoGetGridRowEnd();
mozilla::dom::CSSValue* DoGetGridColumnGap();
mozilla::dom::CSSValue* DoGetGridRowGap();
/* Background properties */
mozilla::dom::CSSValue* DoGetBackgroundAttachment();

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

@ -138,8 +138,10 @@ COMPUTED_STYLE_PROP(grid_auto_columns, GridAutoColumns)
COMPUTED_STYLE_PROP(grid_auto_flow, GridAutoFlow)
COMPUTED_STYLE_PROP(grid_auto_rows, GridAutoRows)
COMPUTED_STYLE_PROP(grid_column_end, GridColumnEnd)
COMPUTED_STYLE_PROP(grid_column_gap, GridColumnGap)
COMPUTED_STYLE_PROP(grid_column_start, GridColumnStart)
COMPUTED_STYLE_PROP(grid_row_end, GridRowEnd)
COMPUTED_STYLE_PROP(grid_row_gap, GridRowGap)
COMPUTED_STYLE_PROP(grid_row_start, GridRowStart)
COMPUTED_STYLE_PROP(grid_template_areas, GridTemplateAreas)
COMPUTED_STYLE_PROP(grid_template_columns, GridTemplateColumns)

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

@ -8117,6 +8117,33 @@ nsRuleNode::ComputePositionData(void* aStartStruct,
parentPos->mGridRowEnd,
conditions);
// grid-column-gap
nsStyleCoord tempCoord;
if (SetCoord(*aRuleData->ValueForGridColumnGap(),
tempCoord, nsStyleCoord(parentPos->mGridColumnGap,
nsStyleCoord::CoordConstructor),
SETCOORD_LH | SETCOORD_INITIAL_ZERO | SETCOORD_CALC_LENGTH_ONLY |
SETCOORD_CALC_CLAMP_NONNEGATIVE | SETCOORD_UNSET_INITIAL,
aContext, mPresContext, conditions)) {
pos->mGridColumnGap = tempCoord.GetCoordValue();
} else {
MOZ_ASSERT(aRuleData->ValueForGridColumnGap()->GetUnit() == eCSSUnit_Null,
"unexpected unit");
}
// grid-row-gap
if (SetCoord(*aRuleData->ValueForGridRowGap(),
tempCoord, nsStyleCoord(parentPos->mGridRowGap,
nsStyleCoord::CoordConstructor),
SETCOORD_LH | SETCOORD_INITIAL_ZERO | SETCOORD_CALC_LENGTH_ONLY |
SETCOORD_CALC_CLAMP_NONNEGATIVE | SETCOORD_UNSET_INITIAL,
aContext, mPresContext, conditions)) {
pos->mGridRowGap = tempCoord.GetCoordValue();
} else {
MOZ_ASSERT(aRuleData->ValueForGridRowGap()->GetUnit() == eCSSUnit_Null,
"unexpected unit");
}
// z-index
const nsCSSValue* zIndexValue = aRuleData->ValueForZIndex();
if (! SetCoord(*zIndexValue, pos->mZIndex, parentPos->mZIndex,

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

@ -1496,6 +1496,8 @@ nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
, mGridColumnEnd(aSource.mGridColumnEnd)
, mGridRowStart(aSource.mGridRowStart)
, mGridRowEnd(aSource.mGridRowEnd)
, mGridColumnGap(aSource.mGridColumnGap)
, mGridRowGap(aSource.mGridRowGap)
{
MOZ_COUNT_CTOR(nsStylePosition);
}
@ -1589,7 +1591,9 @@ nsStylePosition::CalcDifference(const nsStylePosition& aOther,
if (mGridColumnStart != aOther.mGridColumnStart ||
mGridColumnEnd != aOther.mGridColumnEnd ||
mGridRowStart != aOther.mGridRowStart ||
mGridRowEnd != aOther.mGridRowEnd) {
mGridRowEnd != aOther.mGridRowEnd ||
mGridColumnGap != aOther.mGridColumnGap ||
mGridRowGap != aOther.mGridRowGap) {
return NS_CombineHint(hint, nsChangeHint_AllReflowHints);
}

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

@ -1490,6 +1490,8 @@ public:
nsStyleGridLine mGridColumnEnd;
nsStyleGridLine mGridRowStart;
nsStyleGridLine mGridRowEnd;
nscoord mGridColumnGap; // [reset] coord, calc
nscoord mGridRowGap; // [reset] coord, calc
// FIXME: Logical-coordinate equivalents to these WidthDepends... and
// HeightDepends... methods have been introduced (see below); we probably

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

@ -5954,6 +5954,8 @@ if (IsCSSPropertyPrefEnabled("layout.css.grid.enabled")) {
"grid-auto-flow",
"grid-auto-columns",
"grid-auto-rows",
"grid-column-gap",
"grid-row-gap",
],
initial_values: [
"none",
@ -6133,6 +6135,33 @@ if (IsCSSPropertyPrefEnabled("layout.css.grid.enabled")) {
other_values: gridAreaOtherValues,
invalid_values: gridAreaInvalidValues
};
gCSSProperties["grid-column-gap"] = {
domProp: "gridColumnGap",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "0" ],
other_values: [ "2px", "1em", "calc(1px + 1em)" ],
invalid_values: [ "-1px", "2%", "auto", "none", "1px 1px", "calc(1%)" ],
};
gCSSProperties["grid-row-gap"] = {
domProp: "gridRowGap",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "0" ],
other_values: [ "2px", "1em", "calc(1px + 1em)" ],
invalid_values: [ "-1px", "2%", "auto", "none", "1px 1px", "calc(1%)" ],
};
gCSSProperties["grid-gap"] = {
domProp: "gridGap",
inherited: false,
type: CSS_TYPE_TRUE_SHORTHAND,
subproperties: [ "grid-column-gap", "grid-row-gap" ],
initial_values: [ "0", "0 0" ],
other_values: [ "1ch 0", "1em 1px", "calc(1px + 1ch)" ],
invalid_values: [ "-1px", "1px -1px", "1px 1px 1px", "inherit 1px",
"1px 1%", "1px auto" ]
};
}
if (IsCSSPropertyPrefEnabled("layout.css.display-contents.enabled")) {

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

@ -19,6 +19,8 @@ var initial_values = {
gridAutoFlow: "row",
gridAutoColumns: "auto",
gridAutoRows: "auto",
gridRowGap: "0px",
gridColumnGap: "0px",
};
// For various specified values of the grid-template subproperties,
@ -106,8 +108,37 @@ grid_test_cases = grid_template_test_cases.concat([
gridAutoRows: "100px",
shorthand: "row 40px / 100px",
},
{
gridAutoFlow: "row",
gridRowGap: "0px",
shorthand: "row auto / auto",
},
{
gridAutoFlow: "row",
gridRowGap: "1px",
shorthand: "",
},
{
gridAutoFlow: "row",
gridColumnGap: "1px",
shorthand: "",
},
]);
var grid_important_test_cases = [
{
"grid-auto-flow": "row",
"grid-row-gap": "0px",
shorthand: "",
},
{
"grid-auto-flow": "row",
"grid-column-gap": "1px",
shorthand: "",
},
];
function run_tests(test_cases, shorthand, subproperties) {
test_cases.forEach(function(test_case) {
test(function() {
@ -122,12 +153,31 @@ function run_tests(test_cases, shorthand, subproperties) {
});
}
function run_important_tests(test_cases, shorthand, subproperties) {
test_cases.forEach(function(test_case) {
test(function() {
var element = document.createElement('div');
document.body.appendChild(element);
subproperties.forEach(function(longhand) {
element.style.setProperty(longhand,
test_case[longhand] || initial_values[longhand],
"important");
});
assert_equals(element.style[shorthand], test_case.shorthand);
}, "test shorthand serialization " + JSON.stringify(test_case));
});
}
run_tests(grid_template_test_cases, "gridTemplate", [
"gridTemplateAreas", "gridTemplateColumns", "gridTemplateRows"]);
run_tests(grid_test_cases, "grid", [
"gridTemplateAreas", "gridTemplateColumns", "gridTemplateRows",
"gridAutoFlow", "gridAutoColumns", "gridAutoRows"]);
"gridAutoFlow", "gridAutoColumns", "gridAutoRows", "gridColumnGap", "gridRowGap"]);
run_important_tests(grid_important_test_cases, "grid", [
"grid-template-areas", "grid-template-columns", "grid-template-rows",
"grid-auto-flow", "grid-auto-columns", "grid-auto-rows", "grid-column-gap", "grid-row-gap"]);
</script>
</body>

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

@ -142,6 +142,8 @@ var supported_properties = {
/* test_float_zeroToOne_clamped */ ],
"font-stretch": [ test_font_stretch ],
"font-weight": [ test_font_weight ],
"grid-column-gap": [ test_grid_gap ],
"grid-row-gap": [ test_grid_gap ],
"height": [ test_length_transition, test_percent_transition,
test_length_percent_calc_transition,
test_length_clamped, test_percent_clamped ],
@ -1601,6 +1603,14 @@ function test_font_weight(prop) {
div.style.setProperty("transition-timing-function", "linear", "");
}
function test_grid_gap(prop) {
if (!SpecialPowers.getBoolPref("layout.css.grid.enabled")) {
return;
}
test_length_transition(prop);
test_length_clamped(prop);
}
function test_pos_integer_or_auto_transition(prop) {
div.style.setProperty("transition-property", "none", "");
div.style.setProperty(prop, "4", "");