Bug 976787 part 1: Add the grid-template-{columns,rows} properties to the style system. r=dholbert

This commit is contained in:
Simon Sapin 2014-03-10 15:54:13 -07:00
parent 5d1e1310a3
commit ed42775975
17 changed files with 687 additions and 20 deletions

View File

@ -376,11 +376,14 @@ CSS_KEY(margin-box, margin_box)
CSS_KEY(markers, markers)
CSS_KEY(matrix, matrix)
CSS_KEY(matrix3d, matrix3d)
CSS_KEY(max-content, max_content)
CSS_KEY(medium, medium)
CSS_KEY(menu, menu)
CSS_KEY(menutext, menutext)
CSS_KEY(message-box, message_box)
CSS_KEY(middle, middle)
CSS_KEY(min-content, min_content)
CSS_KEY(minmax, minmax)
CSS_KEY(mix, mix)
CSS_KEY(mm, mm)
CSS_KEY(monospace, monospace)

View File

@ -631,6 +631,12 @@ protected:
// For "flex-flow" shorthand property, defined in CSS Flexbox spec
bool ParseFlexFlow();
// CSS Grid
bool ParseGridLineNames(nsCSSValue& aValue);
bool ParseGridTrackBreadth(nsCSSValue& aValue);
bool ParseGridTrackSize(nsCSSValue& aValue);
bool ParseGridTrackList(nsCSSProperty aPropID);
// for 'clip' and '-moz-image-region'
bool ParseRect(nsCSSProperty aPropID);
bool ParseColumns();
@ -781,6 +787,24 @@ protected:
bool ParseOneOrLargerVariant(nsCSSValue& aValue,
int32_t aVariantMask,
const KTableValue aKeywordTable[]);
// http://dev.w3.org/csswg/css-values/#custom-idents
// Parse an identifier that is none of:
// * a CSS-wide keyword
// * "default"
// * a keyword in |aExcludedKeywords|
// * a keyword in |aPropertyKTable|
//
// |aExcludedKeywords| is an array of nsCSSKeyword
// that ends with a eCSSKeyword_UNKNOWN marker.
//
// |aPropertyKTable| can be used if some of the keywords to exclude
// also appear in an existing nsCSSProps::KTableValue,
// to avoid duplicating them.
bool ParseCustomIdent(nsCSSValue& aValue,
const nsAutoString& aIdentValue,
const nsCSSKeyword aExcludedKeywords[] = nullptr,
const nsCSSProps::KTableValue aPropertyKTable[] = nullptr);
bool ParseCounter(nsCSSValue& aValue);
bool ParseAttr(nsCSSValue& aValue);
bool SetValueToURL(nsCSSValue& aValue, const nsString& aURL);
@ -6159,6 +6183,9 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
// XXX Should we check IsParsingCompoundProperty, or do all
// callers handle it? (Not all callers set it, though, since
// they want the quirks that are disabled by setting it.)
// IMPORTANT: If new keywords are added here,
// they probably need to be added in ParseCustomIdent as well.
if (eCSSKeyword_inherit == keyword) {
aValue.SetInheritValue();
return true;
@ -6392,6 +6419,40 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
return false;
}
bool
CSSParserImpl::ParseCustomIdent(nsCSSValue& aValue,
const nsAutoString& aIdentValue,
const nsCSSKeyword aExcludedKeywords[],
const nsCSSProps::KTableValue aPropertyKTable[])
{
nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(aIdentValue);
if (keyword == eCSSKeyword_UNKNOWN) {
// Fast path for identifiers that are not known CSS keywords:
aValue.SetStringValue(mToken.mIdent, eCSSUnit_Ident);
return true;
}
if (keyword == eCSSKeyword_inherit ||
keyword == eCSSKeyword_initial ||
keyword == eCSSKeyword_unset ||
keyword == eCSSKeyword_default ||
(aPropertyKTable &&
nsCSSProps::FindIndexOfKeyword(keyword, aPropertyKTable) >= 0)) {
return false;
}
if (aExcludedKeywords) {
for (uint32_t i = 0;; i++) {
nsCSSKeyword excludedKeyword = aExcludedKeywords[i];
if (excludedKeyword == eCSSKeyword_UNKNOWN) {
break;
}
if (excludedKeyword == keyword) {
return false;
}
}
}
aValue.SetStringValue(mToken.mIdent, eCSSUnit_Ident);
return true;
}
bool
CSSParserImpl::ParseCounter(nsCSSValue& aValue)
@ -6808,6 +6869,136 @@ CSSParserImpl::ParseFlexFlow()
return true;
}
// Parse an optional <line-names> expression.
// If successful, leaves aValue with eCSSUnit_Null for the empty list,
// or sets it to a eCSSUnit_List of eCSSUnit_Ident.
// Not finding an open paren is considered the same as an empty list.
// aPropertyKeywords contains additional keywords for the 'grid' shorthand.
bool
CSSParserImpl::ParseGridLineNames(nsCSSValue& aValue)
{
MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Null,
"Unexpected unit, aValue should not be initialized yet");
if (!GetToken(true)) {
return true;
}
if (!mToken.IsSymbol('(')) {
UngetToken();
return true;
}
if (!GetToken(true) || mToken.IsSymbol(')')) {
return true;
}
// 'return true' so far keeps eCSSUnit_Null, to represent an empty list.
nsCSSValueList* item = aValue.SetListValue();
for (;;) {
if (!(eCSSToken_Ident == mToken.mType &&
ParseCustomIdent(item->mValue, mToken.mIdent))) {
UngetToken();
SkipUntil(')');
return false;
}
if (!GetToken(true) || mToken.IsSymbol(')')) {
return true;
}
item->mNext = new nsCSSValueList;
item = item->mNext;
}
}
// Parse a <track-breadth>
bool
CSSParserImpl::ParseGridTrackBreadth(nsCSSValue& aValue)
{
if (ParseNonNegativeVariant(aValue,
VARIANT_LPCALC | VARIANT_KEYWORD,
nsCSSProps::kGridTrackBreadthKTable)) {
return true;
}
// Attempt to parse <flex> (a dimension with the "fr" unit)
if (!GetToken(true)) {
return false;
}
if (!(eCSSToken_Dimension == mToken.mType &&
mToken.mIdent.LowerCaseEqualsLiteral("fr") &&
mToken.mNumber >= 0)) {
UngetToken();
return false;
}
aValue.SetFloatValue(mToken.mNumber, eCSSUnit_FlexFraction);
return true;
}
// Parse a <track-size>
bool
CSSParserImpl::ParseGridTrackSize(nsCSSValue& aValue)
{
// Attempt to parse 'auto' or a single <track-breadth>
if (ParseGridTrackBreadth(aValue) ||
ParseVariant(aValue, VARIANT_AUTO, nullptr)) {
return true;
}
// Attempt to parse a minmax() function
if (!GetToken(true)) {
return false;
}
if (!(eCSSToken_Function == mToken.mType &&
mToken.mIdent.LowerCaseEqualsLiteral("minmax"))) {
UngetToken();
return false;
}
nsCSSValue::Array* func = aValue.InitFunction(eCSSKeyword_minmax, 2);
if (ParseGridTrackBreadth(func->Item(1)) &&
ExpectSymbol(',', true) &&
ParseGridTrackBreadth(func->Item(2)) &&
ExpectSymbol(')', true)) {
return true;
}
SkipUntil(')');
return false;
}
bool
CSSParserImpl::ParseGridTrackList(nsCSSProperty aPropID)
{
nsCSSValue value;
if (ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE, nullptr)) {
AppendValue(aPropID, value);
return true;
}
// FIXME: add subgrid
// |value| will be a list of odd length >= 3,
// starting with a <line-names> (which is itself a list)
// and alternating between that and <track-size>
nsCSSValueList* item = value.SetListValue();
if (!ParseGridLineNames(item->mValue)) {
return false;
}
do {
item->mNext = new nsCSSValueList;
item = item->mNext;
// FIXME: add repeat()
if (!ParseGridTrackSize(item->mValue)) {
return false;
}
item->mNext = new nsCSSValueList;
item = item->mNext;
if (!ParseGridLineNames(item->mValue)) {
return false;
}
} while (!CheckEndProperty());
MOZ_ASSERT(value.GetListValue() && value.GetListValue()->mNext &&
value.GetListValue()->mNext->mNext,
"<track-list> should have a minimum length of 3");
AppendValue(aPropID, value);
return true;
}
// <color-stop> : <color> [ <percentage> | <length> ]?
bool
CSSParserImpl::ParseColorStop(nsCSSValueGradient* aGradient)
@ -7822,6 +8013,9 @@ CSSParserImpl::ParsePropertyByFunction(nsCSSProperty aPropID)
return ParseFlexFlow();
case eCSSProperty_font:
return ParseFont();
case eCSSProperty_grid_template_columns:
case eCSSProperty_grid_template_rows:
return ParseGridTrackList(aPropID);
case eCSSProperty_image_region:
return ParseRect(eCSSProperty_image_region);
case eCSSProperty_list_style:
@ -9799,6 +9993,10 @@ CSSParserImpl::ParseContent()
bool
CSSParserImpl::ParseCounterData(nsCSSProperty aPropID)
{
static const nsCSSKeyword kCounterDataKTable[] = {
eCSSKeyword_none,
eCSSKeyword_UNKNOWN
};
nsCSSValue value;
if (!ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE, nullptr)) {
if (!GetToken(true) || mToken.mType != eCSSToken_Ident) {
@ -9807,17 +10005,9 @@ CSSParserImpl::ParseCounterData(nsCSSProperty aPropID)
nsCSSValuePairList *cur = value.SetPairListValue();
for (;;) {
// check for "none", "default" and the CSS-wide keywords,
// which can't be used as counter names
nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
if (keyword == eCSSKeyword_inherit ||
keyword == eCSSKeyword_default ||
keyword == eCSSKeyword_none ||
keyword == eCSSKeyword_unset ||
keyword == eCSSKeyword_initial) {
if (!ParseCustomIdent(cur->mXValue, mToken.mIdent, kCounterDataKTable)) {
return false;
}
cur->mXValue.SetStringValue(mToken.mIdent, eCSSUnit_Ident);
if (!GetToken(true)) {
break;
}

View File

@ -2008,6 +2008,30 @@ CSS_PROP_UIRESET(
nullptr,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None) // bug 58646
CSS_PROP_POSITION(
grid-template-columns,
grid_template_columns,
GridTemplateColumns,
CSS_PROPERTY_PARSE_FUNCTION |
CSS_PROPERTY_STORES_CALC |
CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH,
"layout.css.grid.enabled",
0,
kGridTrackBreadthKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_POSITION(
grid-template-rows,
grid_template_rows,
GridTemplateRows,
CSS_PROPERTY_PARSE_FUNCTION |
CSS_PROPERTY_STORES_CALC |
CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH,
"layout.css.grid.enabled",
0,
kGridTrackBreadthKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_POSITION(
height,
height,

View File

@ -1251,6 +1251,12 @@ const KTableValue nsCSSProps::kFontWeightKTable[] = {
eCSSKeyword_UNKNOWN,-1
};
const KTableValue nsCSSProps::kGridTrackBreadthKTable[] = {
eCSSKeyword_min_content, NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT,
eCSSKeyword_max_content, NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT,
eCSSKeyword_UNKNOWN,-1
};
const KTableValue nsCSSProps::kImageOrientationKTable[] = {
eCSSKeyword_flip, NS_STYLE_IMAGE_ORIENTATION_FLIP,
eCSSKeyword_from_image, NS_STYLE_IMAGE_ORIENTATION_FROM_IMAGE,

View File

@ -572,6 +572,7 @@ public:
static const KTableValue kFontVariantNumericKTable[];
static const KTableValue kFontVariantPositionKTable[];
static const KTableValue kFontWeightKTable[];
static const KTableValue kGridTrackBreadthKTable[];
static const KTableValue kImageOrientationKTable[];
static const KTableValue kImageOrientationFlipKTable[];
static const KTableValue kIMEModeKTable[];

View File

@ -1398,6 +1398,8 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
case eCSSUnit_Seconds: aResult.Append(char16_t('s')); break;
case eCSSUnit_Milliseconds: aResult.AppendLiteral("ms"); break;
case eCSSUnit_FlexFraction: aResult.AppendLiteral("fr"); break;
}
}
@ -1554,6 +1556,7 @@ nsCSSValue::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
case eCSSUnit_Kilohertz:
case eCSSUnit_Seconds:
case eCSSUnit_Milliseconds:
case eCSSUnit_FlexFraction:
break;
default:
@ -1594,11 +1597,11 @@ nsCSSValueList::CloneInto(nsCSSValueList* aList) const
aList->mNext = mNext ? mNext->Clone() : nullptr;
}
void
nsCSSValueList::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aSerialization) const
static void
AppendValueListToString(const nsCSSValueList* val,
nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aSerialization)
{
const nsCSSValueList* val = this;
for (;;) {
val->mValue.AppendToString(aProperty, aResult, aSerialization);
val = val->mNext;
@ -1612,6 +1615,55 @@ nsCSSValueList::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
}
}
static void
AppendGridTemplateToString(const nsCSSValueList* val,
nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aSerialization)
{
// This is called for the "list" that's the top-level value of the property.
for (;;) {
bool addSpaceSpearator = true;
nsCSSUnit unit = val->mValue.GetUnit();
if (unit == eCSSUnit_Null) {
// Empty or omitted <line-names>. Serializes to nothing.
addSpaceSpearator = false; // Avoid a double space.
} else if (unit == eCSSUnit_List || unit == eCSSUnit_ListDep) {
// Non-empty <line-names>
aResult.AppendLiteral("(");
AppendValueListToString(val->mValue.GetListValue(), aProperty,
aResult, aSerialization);
aResult.AppendLiteral(")");
} else {
// <track-size>
val->mValue.AppendToString(aProperty, aResult, aSerialization);
}
val = val->mNext;
if (!val) {
break;
}
if (addSpaceSpearator) {
aResult.Append(char16_t(' '));
}
}
}
void
nsCSSValueList::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
nsCSSValue::Serialization aSerialization) const
{
if (aProperty == eCSSProperty_grid_template_columns ||
aProperty == eCSSProperty_grid_template_rows) {
AppendGridTemplateToString(this, aProperty, aResult, aSerialization);
} else {
AppendValueListToString(this, aProperty, aResult, aSerialization);
}
}
bool
nsCSSValueList::operator==(const nsCSSValueList& aOther) const
{

View File

@ -258,7 +258,10 @@ enum nsCSSUnit {
// Time units
eCSSUnit_Seconds = 3000, // (float) Standard time
eCSSUnit_Milliseconds = 3001 // (float) 1/1000 second
eCSSUnit_Milliseconds = 3001, // (float) 1/1000 second
// Flexible fraction (CSS Grid)
eCSSUnit_FlexFraction = 4000 // (float) Fraction of free space
};
struct nsCSSValueGradient;

View File

@ -2271,6 +2271,106 @@ nsComputedDOMStyle::DoGetBackgroundSize()
return valueList;
}
// aLineNames must not be empty
CSSValue*
nsComputedDOMStyle::GetGridLineNames(const nsTArray<nsString>& aLineNames)
{
nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
nsAutoString lineNamesString;
uint32_t i_end = aLineNames.Length();
MOZ_ASSERT(i_end > 0, "GetGridLineNames called with an empty array");
lineNamesString.AssignLiteral("(");
for (uint32_t i = 0;;) {
nsStyleUtil::AppendEscapedCSSIdent(aLineNames[i], lineNamesString);
if (++i == i_end) {
break;
}
lineNamesString.AppendLiteral(" ");
}
lineNamesString.AppendLiteral(")");
val->SetString(lineNamesString);
return val;
}
CSSValue*
nsComputedDOMStyle::GetGridTrackSize(const nsStyleCoord& aMinValue,
const nsStyleCoord& aMaxValue)
{
// FIXME bug 978212: If we have frame, every <track-size> should
// be resolved into 'px' here, based on layout results.
if (aMinValue == aMaxValue) {
nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
SetValueToCoord(val, aMinValue, true,
nullptr, nsCSSProps::kGridTrackBreadthKTable);
return val;
}
nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
nsAutoString argumentStr, minmaxStr;
minmaxStr.AppendLiteral("minmax(");
SetValueToCoord(val, aMinValue, true,
nullptr, nsCSSProps::kGridTrackBreadthKTable);
val->GetCssText(argumentStr);
minmaxStr.Append(argumentStr);
minmaxStr.AppendLiteral(", ");
SetValueToCoord(val, aMaxValue, true,
nullptr, nsCSSProps::kGridTrackBreadthKTable);
val->GetCssText(argumentStr);
minmaxStr.Append(argumentStr);
minmaxStr.Append(char16_t(')'));
val->SetString(minmaxStr);
return val;
}
CSSValue*
nsComputedDOMStyle::GetGridTrackList(const nsStyleGridTrackList& aTrackList)
{
uint32_t numSizes = aTrackList.mMinTrackSizingFunctions.Length();
MOZ_ASSERT(aTrackList.mMaxTrackSizingFunctions.Length() == numSizes,
"Different number of min and max track sizing functions");
// An empty <track-list> is represented as "none" in syntax.
if (numSizes == 0) {
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
val->SetIdent(eCSSKeyword_none);
return val;
}
nsDOMCSSValueList* valueList = GetROCSSValueList(false);
// Delimiting N tracks requires N+1 lines:
// one before each track, plus one at the very end.
MOZ_ASSERT(aTrackList.mLineNameLists.Length() == numSizes + 1,
"Unexpected number of line name lists");
for (uint32_t i = 0;; i++) {
const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
if (!lineNames.IsEmpty()) {
valueList->AppendCSSValue(GetGridLineNames(aTrackList.mLineNameLists[i]));
}
if (i == numSizes) {
break;
}
valueList->AppendCSSValue(GetGridTrackSize(aTrackList.mMinTrackSizingFunctions[i],
aTrackList.mMaxTrackSizingFunctions[i]));
}
return valueList;
}
CSSValue*
nsComputedDOMStyle::DoGetGridTemplateColumns()
{
return GetGridTrackList(StylePosition()->mGridTemplateColumns);
}
CSSValue*
nsComputedDOMStyle::DoGetGridTemplateRows()
{
return GetGridTrackList(StylePosition()->mGridTemplateRows);
}
CSSValue*
nsComputedDOMStyle::DoGetPaddingTop()
{
@ -4402,6 +4502,14 @@ nsComputedDOMStyle::SetValueToCoord(nsROCSSPrimitiveValue* aValue,
aValue->SetTurn(aCoord.GetAngleValue());
break;
case eStyleUnit_FlexFraction: {
nsAutoString tmpStr;
nsStyleUtil::AppendCSSNumber(aCoord.GetFlexFractionValue(), tmpStr);
tmpStr.AppendLiteral("fr");
aValue->SetString(tmpStr);
break;
}
default:
NS_ERROR("Can't handle this unit");
break;

View File

@ -189,6 +189,11 @@ private:
mozilla::dom::CSSValue* GetSVGPaintFor(bool aFill);
mozilla::dom::CSSValue* GetGridLineNames(const nsTArray<nsString>& aLineNames);
mozilla::dom::CSSValue* GetGridTrackSize(const nsStyleCoord& aMinSize,
const nsStyleCoord& aMaxSize);
mozilla::dom::CSSValue* GetGridTrackList(const nsStyleGridTrackList& aTrackList);
bool GetLineHeightCoord(nscoord& aCoord);
mozilla::dom::CSSValue* GetCSSShadowArray(nsCSSShadowArray* aArray,
@ -257,6 +262,10 @@ private:
mozilla::dom::CSSValue* DoGetFontVariantPosition();
mozilla::dom::CSSValue* DoGetFontWeight();
/* Grid properties */
mozilla::dom::CSSValue* DoGetGridTemplateColumns();
mozilla::dom::CSSValue* DoGetGridTemplateRows();
/* Background properties */
mozilla::dom::CSSValue* DoGetBackgroundAttachment();
mozilla::dom::CSSValue* DoGetBackgroundColor();

View File

@ -130,6 +130,8 @@ COMPUTED_STYLE_PROP(font_variant_ligatures, FontVariantLigatures)
COMPUTED_STYLE_PROP(font_variant_numeric, FontVariantNumeric)
COMPUTED_STYLE_PROP(font_variant_position, FontVariantPosition)
COMPUTED_STYLE_PROP(font_weight, FontWeight)
COMPUTED_STYLE_PROP(grid_template_columns, GridTemplateColumns)
COMPUTED_STYLE_PROP(grid_template_rows, GridTemplateRows)
COMPUTED_STYLE_PROP(height, Height)
COMPUTED_STYLE_PROP(image_orientation, ImageOrientation)
COMPUTED_STYLE_PROP(ime_mode, IMEMode)

View File

@ -683,7 +683,8 @@ GetFloatFromBoxPosition(int32_t aEnumValue)
#define SETCOORD_LAH (SETCOORD_AUTO | SETCOORD_LENGTH | SETCOORD_INHERIT)
#define SETCOORD_LPH (SETCOORD_LP | SETCOORD_INHERIT)
#define SETCOORD_LPAH (SETCOORD_LP | SETCOORD_AH)
#define SETCOORD_LPEH (SETCOORD_LP | SETCOORD_ENUMERATED | SETCOORD_INHERIT)
#define SETCOORD_LPE (SETCOORD_LP | SETCOORD_ENUMERATED)
#define SETCOORD_LPEH (SETCOORD_LPE | SETCOORD_INHERIT)
#define SETCOORD_LPAEH (SETCOORD_LPAH | SETCOORD_ENUMERATED)
#define SETCOORD_LPO (SETCOORD_LP | SETCOORD_NONE)
#define SETCOORD_LPOH (SETCOORD_LPH | SETCOORD_NONE)
@ -7062,6 +7063,120 @@ nsRuleNode::ComputeListData(void* aStartStruct,
COMPUTE_END_INHERITED(List, list)
}
static void
SetGridTrackBreadth(const nsCSSValue& aValue,
nsStyleCoord& aResult,
nsStyleContext* aStyleContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree)
{
nsCSSUnit unit = aValue.GetUnit();
if (unit == eCSSUnit_FlexFraction) {
aResult.SetFlexFractionValue(aValue.GetFloatValue());
} else {
MOZ_ASSERT(unit != eCSSUnit_Inherit && unit != eCSSUnit_Unset,
"Unexpected value that would use dummyParentCoord");
const nsStyleCoord dummyParentCoord;
SetCoord(aValue, aResult, dummyParentCoord,
SETCOORD_LPE | SETCOORD_STORE_CALC,
aStyleContext, aPresContext, aCanStoreInRuleTree);
}
}
static void
SetGridTrackList(const nsCSSValue& aValue,
nsStyleGridTrackList& aResult,
const nsStyleGridTrackList& aParentValue,
nsStyleContext* aStyleContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree)
{
switch (aValue.GetUnit()) {
case eCSSUnit_Null:
break;
case eCSSUnit_Inherit:
aCanStoreInRuleTree = false;
aResult.mLineNameLists = aParentValue.mLineNameLists;
aResult.mMinTrackSizingFunctions = aParentValue.mMinTrackSizingFunctions;
aResult.mMaxTrackSizingFunctions = aParentValue.mMaxTrackSizingFunctions;
break;
case eCSSUnit_Initial:
case eCSSUnit_Unset:
case eCSSUnit_None:
aResult.mLineNameLists.Clear();
aResult.mMinTrackSizingFunctions.Clear();
aResult.mMaxTrackSizingFunctions.Clear();
break;
default:
aResult.mLineNameLists.Clear();
aResult.mMinTrackSizingFunctions.Clear();
aResult.mMaxTrackSizingFunctions.Clear();
// This list is expected to have odd number of items, at least 3
// starting with a <line-names> (sub list of identifiers),
// and alternating between that and <track-size>.
const nsCSSValueList* item = aValue.GetListValue();
for (;;) {
// Compute a <line-names> value
nsTArray<nsString>* nameList = aResult.mLineNameLists.AppendElement();
// Null unit means empty list, nothing more to do.
if (item->mValue.GetUnit() != eCSSUnit_Null) {
const nsCSSValueList* subItem = item->mValue.GetListValue();
do {
nsString* name = nameList->AppendElement();
subItem->mValue.GetStringValue(*name);
subItem = subItem->mNext;
} while (subItem);
}
item = item->mNext;
if (!item) {
break;
}
// Compute a <track-size> value
nsStyleCoord minSizingFunction;
nsStyleCoord maxSizingFunction;
if (item->mValue.GetUnit() == eCSSUnit_Function) {
// A minmax() function.
nsCSSValue::Array* func = item->mValue.GetArrayValue();
NS_ASSERTION(func->Item(0).GetKeywordValue() == eCSSKeyword_minmax,
"Expected minmax(), got another function name.");
SetGridTrackBreadth(func->Item(1), minSizingFunction,
aStyleContext, aPresContext, aCanStoreInRuleTree);
SetGridTrackBreadth(func->Item(2), maxSizingFunction,
aStyleContext, aPresContext, aCanStoreInRuleTree);
} else if (item->mValue.GetUnit() == eCSSUnit_Auto) {
// 'auto' computes to 'minmax(min-content, max-content)'
minSizingFunction.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT,
eStyleUnit_Enumerated);
maxSizingFunction.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT,
eStyleUnit_Enumerated);
} else {
// A single <track-breadth>,
// specifies identical min and max sizing functions.
SetGridTrackBreadth(item->mValue, minSizingFunction,
aStyleContext, aPresContext, aCanStoreInRuleTree);
maxSizingFunction = minSizingFunction;
}
aResult.mMinTrackSizingFunctions.AppendElement(minSizingFunction);
aResult.mMaxTrackSizingFunctions.AppendElement(maxSizingFunction);
item = item->mNext;
MOZ_ASSERT(item, "Expected a eCSSUnit_List of odd length");
}
MOZ_ASSERT(!aResult.mMinTrackSizingFunctions.IsEmpty() &&
aResult.mMinTrackSizingFunctions.Length() ==
aResult.mMaxTrackSizingFunctions.Length() &&
aResult.mMinTrackSizingFunctions.Length() + 1 ==
aResult.mLineNameLists.Length(),
"Inconstistent array lengths for nsStyleGridTrackList");
}
}
const void*
nsRuleNode::ComputePositionData(void* aStartStruct,
const nsRuleData* aRuleData,
@ -7235,6 +7350,16 @@ nsRuleNode::ComputePositionData(void* aStartStruct,
parentPos->mJustifyContent,
NS_STYLE_JUSTIFY_CONTENT_FLEX_START, 0, 0, 0, 0);
// grid-template-columns
SetGridTrackList(*aRuleData->ValueForGridTemplateColumns(),
pos->mGridTemplateColumns, parentPos->mGridTemplateColumns,
aContext, mPresContext, canStoreInRuleTree);
// grid-template-rows
SetGridTrackList(*aRuleData->ValueForGridTemplateRows(),
pos->mGridTemplateRows, parentPos->mGridTemplateRows,
aContext, mPresContext, canStoreInRuleTree);
// z-index
const nsCSSValue* zIndexValue = aRuleData->ValueForZIndex();
if (! SetCoord(*zIndexValue, pos->mZIndex, parentPos->mZIndex,

View File

@ -539,6 +539,10 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) {
#define NS_STYLE_FONT_LIST 15
#define NS_STYLE_FONT_FIELD 16
// CSS Grid <track-breadth> keywords
#define NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT 1
#define NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT 2
// defaults per MathML spec
#define NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER 0.71f
#define NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT 8

View File

@ -63,6 +63,7 @@ bool nsStyleCoord::operator==(const nsStyleCoord& aOther) const
case eStyleUnit_Grad:
case eStyleUnit_Radian:
case eStyleUnit_Turn:
case eStyleUnit_FlexFraction:
return mValue.mFloat == aOther.mValue.mFloat;
case eStyleUnit_Coord:
case eStyleUnit_Integer:
@ -91,6 +92,7 @@ uint32_t nsStyleCoord::HashValue(uint32_t aHash = 0) const
case eStyleUnit_Grad:
case eStyleUnit_Radian:
case eStyleUnit_Turn:
case eStyleUnit_FlexFraction:
return mozilla::AddToHash(aHash, mValue.mFloat);
case eStyleUnit_Coord:
case eStyleUnit_Integer:
@ -160,6 +162,12 @@ void nsStyleCoord::SetAngleValue(float aValue, nsStyleUnit aUnit)
}
}
void nsStyleCoord::SetFlexFractionValue(float aValue)
{
mUnit = eStyleUnit_FlexFraction;
mValue.mFloat = aValue;
}
void nsStyleCoord::SetCalcValue(Calc* aValue)
{
mUnit = eStyleUnit_Calc;

View File

@ -22,6 +22,7 @@ enum nsStyleUnit {
eStyleUnit_Grad = 13, // (float) angle in grads
eStyleUnit_Radian = 14, // (float) angle in radians
eStyleUnit_Turn = 15, // (float) angle in turns
eStyleUnit_FlexFraction = 16, // (float) <flex> in fr units
eStyleUnit_Coord = 20, // (nscoord) value is twips
eStyleUnit_Integer = 30, // (int) value is simple integer
eStyleUnit_Enumerated = 32, // (int) value has enumerated meaning
@ -129,6 +130,7 @@ public:
float GetFactorValue() const;
float GetAngleValue() const;
double GetAngleValueInRadians() const;
float GetFlexFractionValue() const;
Calc* GetCalcValue() const;
void GetUnionValue(nsStyleUnion& aValue) const;
uint32_t HashValue(uint32_t aHash) const;
@ -139,6 +141,7 @@ public:
void SetPercentValue(float aValue);
void SetFactorValue(float aValue);
void SetAngleValue(float aValue, nsStyleUnit aUnit);
void SetFlexFractionValue(float aValue);
void SetNormalValue();
void SetAutoValue();
void SetNoneValue();
@ -300,6 +303,15 @@ inline float nsStyleCoord::GetAngleValue() const
return 0.0f;
}
inline float nsStyleCoord::GetFlexFractionValue() const
{
NS_ASSERTION(mUnit == eStyleUnit_FlexFraction, "not a fr value");
if (mUnit == eStyleUnit_FlexFraction) {
return mValue.mFloat;
}
return 0.0f;
}
inline nsStyleCoord::Calc* nsStyleCoord::GetCalcValue() const
{
NS_ASSERTION(IsCalcUnit(), "not a pointer value");

View File

@ -1212,8 +1212,8 @@ bool nsStyleSVGPaint::operator==(const nsStyleSVGPaint& aOther) const
// --------------------
// nsStylePosition
//
nsStylePosition::nsStylePosition(void)
{
nsStylePosition::nsStylePosition(void)
{
MOZ_COUNT_CTOR(nsStylePosition);
// positioning values not inherited
nsStyleCoord autoCoord(eStyleUnit_Auto);
@ -1239,17 +1239,34 @@ nsStylePosition::nsStylePosition(void)
mFlexGrow = 0.0f;
mFlexShrink = 1.0f;
mZIndex.SetAutoValue();
// mGridTemplateRows and mGridTemplateColumns get their default constructors
// which initializes them to empty arrays,
// which represent the propertys initial value 'none'
}
nsStylePosition::~nsStylePosition(void)
{
nsStylePosition::~nsStylePosition(void)
{
MOZ_COUNT_DTOR(nsStylePosition);
}
nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
: mGridTemplateColumns(aSource.mGridTemplateColumns)
, mGridTemplateRows(aSource.mGridTemplateRows)
{
MOZ_COUNT_CTOR(nsStylePosition);
memcpy((nsStylePosition*)this, &aSource, sizeof(nsStylePosition));
// If you add any memcpy'able member vars,
// they should be declared before mGridTemplateColumns.
// If you add any non-memcpy'able member vars,
// they should be declared after mGridTemplateColumns,
// and you should invoke their copy constructor in the init list above
// and update this static-assert to include their "sizeof()"
static_assert(sizeof(nsStylePosition) ==
offsetof(nsStylePosition, mGridTemplateColumns) +
sizeof(mGridTemplateColumns) + sizeof(mGridTemplateRows),
"Unexpected size or offset in nsStylePosition");
memcpy((nsStylePosition*) this,
&aSource,
offsetof(nsStylePosition, mGridTemplateColumns));
}
static bool
@ -1299,6 +1316,13 @@ nsChangeHint nsStylePosition::CalcDifference(const nsStylePosition& aOther) cons
}
// Properties that apply to grid containers:
if (mGridTemplateColumns != aOther.mGridTemplateColumns ||
mGridTemplateRows != aOther.mGridTemplateRows) {
return NS_CombineHint(hint, nsChangeHint_AllReflowHints);
}
// Changing justify-content on a flexbox might affect the positioning of its
// children, but it won't affect any sizing.
if (mJustifyContent != aOther.mJustifyContent) {

View File

@ -1152,6 +1152,38 @@ public:
nsRect mImageRegion; // [inherited] the rect to use within an image
};
struct nsStyleGridTrackList {
// http://dev.w3.org/csswg/css-grid/#track-sizing
// This represents either:
// * 'none': all three arrays are empty
// * A <track-list>: mMinTrackSizingFunctions and mMaxTrackSizingFunctions
// are of identical non-zero size,
// and mLineNameLists is one element longer than that.
// (Delimiting N columns requires N+1 lines:
// one before each track, plus one at the very end.)
//
// An omitted <line-names> is still represented in mLineNameLists,
// as an empty sub-array.
//
// A <track-size> specified as a single <track-breadth> is represented
// as identical min and max sizing functions.
//
// The units for nsStyleCoord are:
// * eStyleUnit_Percent represents a <percentage>
// * eStyleUnit_FlexFraction represents a <flex> flexible fraction
// * eStyleUnit_Coord represents a <length>
// * eStyleUnit_Enumerated represents min-content or max-content
nsTArray<nsTArray<nsString>> mLineNameLists;
nsTArray<nsStyleCoord> mMinTrackSizingFunctions;
nsTArray<nsStyleCoord> mMaxTrackSizingFunctions;
inline bool operator!=(const nsStyleGridTrackList& aOther) const {
return mLineNameLists != aOther.mLineNameLists ||
mMinTrackSizingFunctions != aOther.mMinTrackSizingFunctions ||
mMaxTrackSizingFunctions != aOther.mMaxTrackSizingFunctions;
}
};
struct nsStylePosition {
nsStylePosition(void);
nsStylePosition(const nsStylePosition& aOther);
@ -1196,6 +1228,12 @@ struct nsStylePosition {
float mFlexGrow; // [reset] float
float mFlexShrink; // [reset] float
nsStyleCoord mZIndex; // [reset] integer, auto
// NOTE: Fields so far can be memcpy()'ed, while following fields
// need to have their copy constructor called when we're being copied.
// See nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
// in nsStyleStruct.cpp
nsStyleGridTrackList mGridTemplateColumns;
nsStyleGridTrackList mGridTemplateRows;
bool WidthDependsOnContainer() const
{ return WidthCoordDependsOnContainer(mWidth); }

View File

@ -4792,6 +4792,64 @@ if (SpecialPowers.getBoolPref("layout.css.filters.enabled")) {
if (SpecialPowers.getBoolPref("layout.css.grid.enabled")) {
gCSSProperties["display"].other_values.push("grid", "inline-grid");
gCSSProperties["grid-template-columns"] = {
domProp: "gridTemplateColumns",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: [
"auto",
"40px",
"2.5fr",
"(normal) 40px () auto ( ) 12%",
"(foo) 40px min-content ( bar ) calc(20px + 10%) max-content",
"40px min-content calc(20px + 10%) max-content",
"m\\69nmax(20px, 4Fr)",
"40px MinMax(min-content, calc(20px + 10%)) max-content",
"40px 2em",
"() 40px (-foo) 2em (bar baz This\ is\ one\ ident)",
// TODO bug 978478: "(a) repeat(3, (b) 20px (c) 40px (d)) (e)",
// See https://bugzilla.mozilla.org/show_bug.cgi?id=981300
"(none auto subgrid min-content max-content foo) 40px",
],
invalid_values: [
"",
"normal",
"40ms",
"-40px",
"-12%",
"-2fr",
"(foo)",
"(inherit) 40px",
"(initial) 40px",
"(unset) 40px",
"(default) 40px",
"(6%) 40px",
"(5th) 40px",
"(foo() bar) 40px",
"(foo)) 40px",
"(foo] 40px",
"[foo] 40px",
"(foo) (bar) 40px",
"40px (foo) (bar)",
"minmax()",
"minmax(20px)",
"mİnmax(20px, 100px)",
"minmax(20px, 100px, 200px)",
"maxmin(100px, 20px)",
"minmax(min-content, auto)",
"minmax(min-content, minmax(30px, max-content))",
]
};
gCSSProperties["grid-template-rows"] = {
domProp: "gridTemplateRows",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: gCSSProperties["grid-template-columns"].initial_values,
other_values: gCSSProperties["grid-template-columns"].other_values,
invalid_values: gCSSProperties["grid-template-columns"].invalid_values
};
}
if (SpecialPowers.getBoolPref("layout.css.image-orientation.enabled")) {