Diff
Modified: trunk/LayoutTests/ChangeLog (224164 => 224165)
--- trunk/LayoutTests/ChangeLog 2017-10-29 21:08:46 UTC (rev 224164)
+++ trunk/LayoutTests/ChangeLog 2017-10-29 23:07:45 UTC (rev 224165)
@@ -1,3 +1,17 @@
+2017-10-29 Sam Weinig <s...@webkit.org>
+
+ [Conic Gradients] Add support for parsing conic gradients
+ https://bugs.webkit.org/show_bug.cgi?id=178987
+
+ Reviewed by Dean Jackson.
+
+ * http/wpt/css: Added.
+ * http/wpt/css/css-images-4: Added.
+ * http/wpt/css/css-images-4/conic-gradient-parsing-expected.txt: Added.
+ * http/wpt/css/css-images-4/conic-gradient-parsing.html: Added.
+
+ Add tests for basic parsing of conic gradients.
+
2017-10-29 Antoine Quint <grao...@apple.com>
[Web Animations] Expose the currentTime property on Animation
Added: trunk/LayoutTests/http/wpt/css/css-images-4/conic-gradient-parsing-expected.txt (0 => 224165)
--- trunk/LayoutTests/http/wpt/css/css-images-4/conic-gradient-parsing-expected.txt (rev 0)
+++ trunk/LayoutTests/http/wpt/css/css-images-4/conic-gradient-parsing-expected.txt 2017-10-29 23:07:45 UTC (rev 224165)
@@ -0,0 +1,4 @@
+
+PASS Test conic-gradient parsing
+PASS Test repeating-conic-gradient parsing
+
Added: trunk/LayoutTests/http/wpt/css/css-images-4/conic-gradient-parsing.html (0 => 224165)
--- trunk/LayoutTests/http/wpt/css/css-images-4/conic-gradient-parsing.html (rev 0)
+++ trunk/LayoutTests/http/wpt/css/css-images-4/conic-gradient-parsing.html 2017-10-29 23:07:45 UTC (rev 224165)
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+
+if (window.internals)
+ internals.settings.setConicGradientsEnabled(true);
+
+function roundTrip(css)
+{
+ var div = document.createElement('div');
+ div.setAttribute('style', css);
+ document.body.appendChild(div);
+
+ var result = getComputedStyle(div).backgroundImage;
+ document.body.removeChild(div);
+ return result;
+}
+
+function testGradient(actual, expected)
+{
+ if (expected === undefined)
+ expected = actual;
+
+ assert_equals(roundTrip("background-image:" + actual), expected, "Testing round trip of " + actual);
+}
+
+// FIXME Test invalid parameters.
+// FIXME Test double position syntax for color stops.
+
+test(function() {
+ testGradient("conic-gradient(red, gold)")
+ testGradient("conic-gradient(from 0deg, red, gold)")
+ testGradient("conic-gradient(at center, red, gold)", "conic-gradient(at center center, red, gold)")
+ testGradient("conic-gradient(at 25% 75%, red, gold)")
+ testGradient("conic-gradient(from 0deg at 50% 50%, red, gold)")
+ testGradient("conic-gradient(red 0%, gold 100%)")
+ testGradient("conic-gradient(red 0deg, gold 1turn)");
+ testGradient("conic-gradient(white -50%, black 150%)");
+ testGradient("conic-gradient(white -180deg, black 540deg)");
+ testGradient("conic-gradient(hsl(0,0%,75%), hsl(0,0%,25%))", "conic-gradient(rgb(191, 191, 191), rgb(63, 63, 63))");
+ testGradient("conic-gradient(from 45deg, white, black, white)");
+ testGradient("conic-gradient(hsl(0,0%,87.5%), white 45deg, black 225deg, hsl(0,0%,87.5%))", "conic-gradient(rgb(223, 223, 223), white 45deg, black 225deg, rgb(223, 223, 223))");
+
+ var s = "conic-gradient(";
+ for (var x = 0; x < 500; x++)
+ s += `white ${x/500}%, ${(2 * x + 1) / 1000}%, `;
+ s += "black)";
+ testGradient(s);
+}, "Test conic-gradient parsing");
+
+test(function() {
+ testGradient("repeating-conic-gradient(red, gold)");
+ testGradient("repeating-conic-gradient(from 0deg at center, red, gold)", "repeating-conic-gradient(from 0deg at center center, red, gold)");
+}, "Test repeating-conic-gradient parsing");
+
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (224164 => 224165)
--- trunk/Source/WebCore/ChangeLog 2017-10-29 21:08:46 UTC (rev 224164)
+++ trunk/Source/WebCore/ChangeLog 2017-10-29 23:07:45 UTC (rev 224165)
@@ -1,3 +1,105 @@
+2017-10-29 Sam Weinig <s...@webkit.org>
+
+ [Conic Gradients] Add support for parsing conic gradients
+ https://bugs.webkit.org/show_bug.cgi?id=178987
+
+ Reviewed by Dean Jackson.
+
+ Adds initial support, disabled by default, for parsing conic gradients as per
+ CSS 4 Images - https://www.w3.org/TR/css-images-4/#conic-gradients.
+
+ Test: fast/gradients/conic-gradient-parsing.html
+
+ * css/CSSGradientValue.cpp:
+ (WebCore::clone):
+ (WebCore::CSSGradientValue::isCacheable const):
+ (WebCore::CSSConicGradientValue::customCSSText const):
+ (WebCore::CSSConicGradientValue::createGradient):
+ (WebCore::CSSConicGradientValue::equals const):
+ * css/CSSGradientValue.h:
+
+ Add CSSConicGradientValue as a subclass of CSSGradientValue and implement
+ customCSSText() and equals(). Stub out createGradient() as painting is not
+ yet implemented.
+
+ * css/CSSImageGeneratorValue.cpp:
+ (WebCore::CSSImageGeneratorValue::image):
+ (WebCore::CSSImageGeneratorValue::isFixedSize const):
+ (WebCore::CSSImageGeneratorValue::fixedSize):
+ (WebCore::CSSImageGeneratorValue::isPending const):
+ (WebCore::CSSImageGeneratorValue::knownToBeOpaque const):
+ (WebCore::CSSImageGeneratorValue::loadSubimages):
+ * css/CSSValue.cpp:
+ (WebCore::CSSValue::equals const):
+ (WebCore::CSSValue::cssText const):
+ (WebCore::CSSValue::destroy):
+
+ Dispatch to CSSConicGradientValue as needed.
+
+ * css/CSSValue.h:
+ (WebCore::CSSValue::isImageGeneratorValue const):
+ (WebCore::CSSValue::isGradientValue const):
+ (WebCore::CSSValue::isConicGradientValue const):
+
+ Add conic gradient predicate support and update isImageGeneratorValue and
+ isGradientValue to include conic gradient.
+
+ * css/CSSValueKeywords.in:
+
+ Add conic-gradient and repeating-conic-gradient.
+
+ * css/parser/CSSParser.cpp:
+ (WebCore::CSSParserContext::CSSParserContext):
+ (WebCore::operator==):
+ * css/parser/CSSParserMode.h:
+ (WebCore::CSSParserContextHash::hash):
+
+ Add runtime flags to enable conic gradients.
+
+ * css/parser/CSSPropertyParserHelpers.cpp:
+ (WebCore::CSSPropertyParserHelpers::consumeAngleOrPercent):
+
+ Helper, similar to consumeLengthOrPercent, for consumeGradientColorStops.
+ Corresponds to https://drafts.csswg.org/css-values-4/#typedef-angle-percentage
+
+ (WebCore::CSSPropertyParserHelpers::consumeGradientColorStops):
+
+ Convert to take CSSGradientValue by reference.
+
+ (WebCore::CSSPropertyParserHelpers::consumeAngularGradientColorStops):
+
+ Helper, similar to consumeGradientColorStops, but for angular color stops
+ used in conic gradients. Corresponds to https://www.w3.org/TR/css-images-4/#typedef-angular-color-stop-list
+ but does not yet support double position syntax.
+
+ (WebCore::CSSPropertyParserHelpers::consumeDeprecatedRadialGradient):
+ (WebCore::CSSPropertyParserHelpers::consumeRadialGradient):
+ (WebCore::CSSPropertyParserHelpers::consumeLinearGradient):
+
+ Pass CSSGradientValue by reference.
+
+ (WebCore::CSSPropertyParserHelpers::consumeConicGradient):
+
+ Parse conic gradient.
+
+ (WebCore::CSSPropertyParserHelpers::consumeGeneratedImage):
+
+ Dispatch to consumeConicGradient for repeating and non-repeating
+ conic gradients.
+
+ (WebCore::CSSPropertyParserHelpers::isGeneratedImage):
+
+ Put each value on its own line to make it more readable and add CSSValueConicGradient
+ and CSSValueRepeatingConicGradient.
+
+ * page/Settings.yaml:
+
+ Add a setting to enable conic gradients. Disabled by default.
+
+ * features.json:
+
+ Move conic gradients to "In Development".
+
2017-10-29 Antoine Quint <grao...@apple.com>
[Web Animations] Expose the currentTime property on Animation
Modified: trunk/Source/WebCore/css/CSSGradientValue.cpp (224164 => 224165)
--- trunk/Source/WebCore/css/CSSGradientValue.cpp 2017-10-29 21:08:46 UTC (rev 224164)
+++ trunk/Source/WebCore/css/CSSGradientValue.cpp 2017-10-29 23:07:45 UTC (rev 224165)
@@ -95,8 +95,10 @@
{
if (is<CSSLinearGradientValue>(value))
return downcast<CSSLinearGradientValue>(value).clone();
- ASSERT(is<CSSRadialGradientValue>(value));
- return downcast<CSSRadialGradientValue>(value).clone();
+ if (is<CSSRadialGradientValue>(value))
+ return downcast<CSSRadialGradientValue>(value).clone();
+ ASSERT(is<CSSConicGradientValue>(value));
+ return downcast<CSSConicGradientValue>(value).clone();
}
Ref<CSSGradientValue> CSSGradientValue::gradientWithStylesResolved(const StyleResolver& styleResolver)
@@ -544,9 +546,7 @@
bool CSSGradientValue::isCacheable() const
{
- for (size_t i = 0; i < m_stops.size(); ++i) {
- const CSSGradientColorStop& stop = m_stops[i];
-
+ for (auto& stop : m_stops) {
if (stop.m_colorIsDerivedFromElement)
return false;
@@ -1274,4 +1274,80 @@
return equalShape && equalSizingBehavior && equalHorizontalAndVerticalSize && m_stops == other.m_stops;
}
+
+String CSSConicGradientValue::customCSSText() const
+{
+ StringBuilder result;
+
+ if (m_repeating)
+ result.appendLiteral("repeating-conic-gradient(");
+ else
+ result.appendLiteral("conic-gradient(");
+
+ bool wroteSomething = false;
+
+ if (m_angle) {
+ result.appendLiteral("from ");
+ result.append(m_angle->cssText());
+ wroteSomething = true;
+ }
+
+ if (m_firstX && m_firstY) {
+ if (wroteSomething)
+ result.appendLiteral(" ");
+ result.appendLiteral("at ");
+ result.append(m_firstX->cssText());
+ result.append(' ');
+ result.append(m_firstY->cssText());
+ wroteSomething = true;
+ }
+
+ if (wroteSomething)
+ result.appendLiteral(", ");
+
+ bool wroteFirstStop = false;
+ for (auto& stop : m_stops) {
+ if (wroteFirstStop)
+ result.appendLiteral(", ");
+ wroteFirstStop = true;
+ if (!stop.isMidpoint)
+ result.append(stop.m_color->cssText());
+ if (stop.m_position) {
+ if (!stop.isMidpoint)
+ result.append(' ');
+ result.append(stop.m_position->cssText());
+ }
+ }
+
+ result.append(')');
+ return result.toString();
+}
+
+Ref<Gradient> CSSConicGradientValue::createGradient(RenderElement&, const FloatSize&)
+{
+ // FIXME: Implement.
+ return Gradient::create(FloatPoint { }, FloatPoint { });
+}
+
+bool CSSConicGradientValue::equals(const CSSConicGradientValue& other) const
+{
+ if (m_repeating != other.m_repeating)
+ return false;
+
+ if (!compareCSSValuePtr(m_angle, other.m_angle))
+ return false;
+
+ bool equalXandY = false;
+ if (m_firstX && m_firstY)
+ equalXandY = compareCSSValuePtr(m_firstX, other.m_firstX) && compareCSSValuePtr(m_firstY, other.m_firstY);
+ else if (m_firstX)
+ equalXandY = compareCSSValuePtr(m_firstX, other.m_firstX) && !other.m_firstY;
+ else if (m_firstY)
+ equalXandY = compareCSSValuePtr(m_firstY, other.m_firstY) && !other.m_firstX;
+ else
+ equalXandY = !other.m_firstX && !other.m_firstY;
+
+ return equalXandY && m_stops == other.m_stops;
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/css/CSSGradientValue.h (224164 => 224165)
--- trunk/Source/WebCore/css/CSSGradientValue.h 2017-10-29 21:08:46 UTC (rev 224164)
+++ trunk/Source/WebCore/css/CSSGradientValue.h 2017-10-29 23:07:45 UTC (rev 224165)
@@ -41,7 +41,8 @@
CSSPrefixedLinearGradient,
CSSPrefixedRadialGradient,
CSSLinearGradient,
- CSSRadialGradient
+ CSSRadialGradient,
+ CSSConicGradient
};
enum CSSGradientRepeat { NonRepeating, Repeating };
@@ -225,8 +226,45 @@
RefPtr<CSSPrimitiveValue> m_endVerticalSize;
};
+class CSSConicGradientValue final : public CSSGradientValue {
+public:
+ static Ref<CSSConicGradientValue> create(CSSGradientRepeat repeat)
+ {
+ return adoptRef(*new CSSConicGradientValue(repeat));
+ }
+
+ Ref<CSSConicGradientValue> clone() const
+ {
+ return adoptRef(*new CSSConicGradientValue(*this));
+ }
+
+ String customCSSText() const;
+
+ void setAngle(RefPtr<CSSPrimitiveValue>&& val) { m_angle = WTFMove(val); }
+
+ // Create the gradient for a given size.
+ Ref<Gradient> createGradient(RenderElement&, const FloatSize&);
+
+ bool equals(const CSSConicGradientValue&) const;
+
+private:
+ CSSConicGradientValue(CSSGradientRepeat repeat)
+ : CSSGradientValue(ConicGradientClass, repeat, CSSConicGradient)
+ {
+ }
+
+ CSSConicGradientValue(const CSSConicGradientValue& other)
+ : CSSGradientValue(other, ConicGradientClass, other.gradientType())
+ , m_angle(other.m_angle)
+ {
+ }
+
+ RefPtr<CSSPrimitiveValue> m_angle; // may be null.
+};
+
} // namespace WebCore
SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSGradientValue, isGradientValue())
SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSLinearGradientValue, isLinearGradientValue())
SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSRadialGradientValue, isRadialGradientValue())
+SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSConicGradientValue, isConicGradientValue())
Modified: trunk/Source/WebCore/css/CSSImageGeneratorValue.cpp (224164 => 224165)
--- trunk/Source/WebCore/css/CSSImageGeneratorValue.cpp 2017-10-29 21:08:46 UTC (rev 224164)
+++ trunk/Source/WebCore/css/CSSImageGeneratorValue.cpp 2017-10-29 23:07:45 UTC (rev 224165)
@@ -148,6 +148,8 @@
return downcast<CSSLinearGradientValue>(*this).image(renderer, size);
case RadialGradientClass:
return downcast<CSSRadialGradientValue>(*this).image(renderer, size);
+ case ConicGradientClass:
+ return downcast<CSSConicGradientValue>(*this).image(renderer, size);
default:
ASSERT_NOT_REACHED();
}
@@ -169,6 +171,8 @@
return downcast<CSSLinearGradientValue>(*this).isFixedSize();
case RadialGradientClass:
return downcast<CSSRadialGradientValue>(*this).isFixedSize();
+ case ConicGradientClass:
+ return downcast<CSSConicGradientValue>(*this).isFixedSize();
default:
ASSERT_NOT_REACHED();
}
@@ -188,6 +192,8 @@
return downcast<CSSLinearGradientValue>(*this).fixedSize(renderer);
case RadialGradientClass:
return downcast<CSSRadialGradientValue>(*this).fixedSize(renderer);
+ case ConicGradientClass:
+ return downcast<CSSConicGradientValue>(*this).fixedSize(renderer);
default:
ASSERT_NOT_REACHED();
}
@@ -209,6 +215,8 @@
return downcast<CSSLinearGradientValue>(*this).isPending();
case RadialGradientClass:
return downcast<CSSRadialGradientValue>(*this).isPending();
+ case ConicGradientClass:
+ return downcast<CSSConicGradientValue>(*this).isPending();
default:
ASSERT_NOT_REACHED();
}
@@ -230,6 +238,8 @@
return downcast<CSSLinearGradientValue>(*this).knownToBeOpaque();
case RadialGradientClass:
return downcast<CSSRadialGradientValue>(*this).knownToBeOpaque();
+ case ConicGradientClass:
+ return downcast<CSSConicGradientValue>(*this).knownToBeOpaque();
default:
ASSERT_NOT_REACHED();
}
@@ -254,6 +264,9 @@
case RadialGradientClass:
downcast<CSSRadialGradientValue>(*this).loadSubimages(cachedResourceLoader, options);
break;
+ case ConicGradientClass:
+ downcast<CSSConicGradientValue>(*this).loadSubimages(cachedResourceLoader, options);
+ break;
default:
ASSERT_NOT_REACHED();
}
Modified: trunk/Source/WebCore/css/CSSValue.cpp (224164 => 224165)
--- trunk/Source/WebCore/css/CSSValue.cpp 2017-10-29 21:08:46 UTC (rev 224164)
+++ trunk/Source/WebCore/css/CSSValue.cpp 2017-10-29 23:07:45 UTC (rev 224165)
@@ -156,6 +156,8 @@
return compareCSSValues<CSSLinearGradientValue>(*this, other);
case RadialGradientClass:
return compareCSSValues<CSSRadialGradientValue>(*this, other);
+ case ConicGradientClass:
+ return compareCSSValues<CSSConicGradientValue>(*this, other);
case CrossfadeClass:
return compareCSSValues<CSSCrossfadeValue>(*this, other);
case ImageClass:
@@ -254,6 +256,8 @@
return downcast<CSSLinearGradientValue>(*this).customCSSText();
case RadialGradientClass:
return downcast<CSSRadialGradientValue>(*this).customCSSText();
+ case ConicGradientClass:
+ return downcast<CSSConicGradientValue>(*this).customCSSText();
case CrossfadeClass:
return downcast<CSSCrossfadeValue>(*this).customCSSText();
case ImageClass:
@@ -359,6 +363,9 @@
case RadialGradientClass:
delete downcast<CSSRadialGradientValue>(this);
return;
+ case ConicGradientClass:
+ delete downcast<CSSConicGradientValue>(this);
+ return;
case CrossfadeClass:
delete downcast<CSSCrossfadeValue>(this);
return;
Modified: trunk/Source/WebCore/css/CSSValue.h (224164 => 224165)
--- trunk/Source/WebCore/css/CSSValue.h 2017-10-29 21:08:46 UTC (rev 224164)
+++ trunk/Source/WebCore/css/CSSValue.h 2017-10-29 23:07:45 UTC (rev 224165)
@@ -81,8 +81,8 @@
bool isFontValue() const { return m_classType == FontClass; }
bool isFontStyleValue() const { return m_classType == FontStyleClass; }
bool isFontStyleRangeValue() const { return m_classType == FontStyleRangeClass; }
- bool isImageGeneratorValue() const { return m_classType >= CanvasClass && m_classType <= RadialGradientClass; }
- bool isGradientValue() const { return m_classType >= LinearGradientClass && m_classType <= RadialGradientClass; }
+ bool isImageGeneratorValue() const { return m_classType >= CanvasClass && m_classType <= ConicGradientClass; }
+ bool isGradientValue() const { return m_classType >= LinearGradientClass && m_classType <= ConicGradientClass; }
bool isNamedImageValue() const { return m_classType == NamedImageClass; }
bool isImageSetValue() const { return m_classType == ImageSetClass; }
bool isImageValue() const { return m_classType == ImageClass; }
@@ -95,6 +95,7 @@
bool treatAsInheritedValue(CSSPropertyID) const;
bool isLinearGradientValue() const { return m_classType == LinearGradientClass; }
bool isRadialGradientValue() const { return m_classType == RadialGradientClass; }
+ bool isConicGradientValue() const { return m_classType == ConicGradientClass; }
bool isReflectValue() const { return m_classType == ReflectClass; }
bool isShadowValue() const { return m_classType == ShadowClass; }
bool isCubicBezierTimingFunctionValue() const { return m_classType == CubicBezierTimingFunctionClass; }
@@ -143,6 +144,7 @@
FilterImageClass,
LinearGradientClass,
RadialGradientClass,
+ ConicGradientClass,
// Timing function classes.
CubicBezierTimingFunctionClass,
Modified: trunk/Source/WebCore/css/CSSValueKeywords.in (224164 => 224165)
--- trunk/Source/WebCore/css/CSSValueKeywords.in 2017-10-29 21:08:46 UTC (rev 224164)
+++ trunk/Source/WebCore/css/CSSValueKeywords.in 2017-10-29 23:07:45 UTC (rev 224165)
@@ -1155,8 +1155,10 @@
image-set
linear-gradient
radial-gradient
+conic-gradient
repeating-linear-gradient
repeating-radial-gradient
+repeating-conic-gradient
-webkit-canvas
-webkit-cross-fade
-webkit-gradient
Modified: trunk/Source/WebCore/css/parser/CSSParser.cpp (224164 => 224165)
--- trunk/Source/WebCore/css/parser/CSSParser.cpp 2017-10-29 21:08:46 UTC (rev 224164)
+++ trunk/Source/WebCore/css/parser/CSSParser.cpp 2017-10-29 23:07:45 UTC (rev 224165)
@@ -87,6 +87,7 @@
#endif
springTimingFunctionEnabled = document.settings().springTimingFunctionEnabled();
constantPropertiesEnabled = document.settings().constantPropertiesEnabled();
+ conicGradientsEnabled = document.settings().conicGradientsEnabled();
deferredCSSParserEnabled = document.settings().deferredCSSParserEnabled();
#if PLATFORM(IOS)
@@ -109,6 +110,7 @@
&& a.useLegacyBackgroundSizeShorthandBehavior == b.useLegacyBackgroundSizeShorthandBehavior
&& a.springTimingFunctionEnabled == b.springTimingFunctionEnabled
&& a.constantPropertiesEnabled == b.constantPropertiesEnabled
+ && a.conicGradientsEnabled == b.conicGradientsEnabled
&& a.deferredCSSParserEnabled == b.deferredCSSParserEnabled;
}
Modified: trunk/Source/WebCore/css/parser/CSSParserMode.h (224164 => 224165)
--- trunk/Source/WebCore/css/parser/CSSParserMode.h 2017-10-29 21:08:46 UTC (rev 224164)
+++ trunk/Source/WebCore/css/parser/CSSParserMode.h 2017-10-29 23:07:45 UTC (rev 224165)
@@ -105,7 +105,7 @@
bool useLegacyBackgroundSizeShorthandBehavior { false };
bool springTimingFunctionEnabled { false };
bool constantPropertiesEnabled { false };
-
+ bool conicGradientsEnabled { false };
bool deferredCSSParserEnabled { false };
URL completeURL(const String& url) const
@@ -139,8 +139,9 @@
& key.enforcesCSSMIMETypeInNoQuirksMode << 5
& key.useLegacyBackgroundSizeShorthandBehavior << 6
& key.springTimingFunctionEnabled << 7
- & key.deferredCSSParserEnabled << 8
- & key.mode << 9;
+ & key.conicGradientsEnabled << 8
+ & key.deferredCSSParserEnabled << 9
+ & key.mode << 10;
hash ^= WTF::intHash(bits);
return hash;
}
Modified: trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp (224164 => 224165)
--- trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp 2017-10-29 21:08:46 UTC (rev 224164)
+++ trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp 2017-10-29 23:07:45 UTC (rev 224165)
@@ -356,6 +356,34 @@
return nullptr;
}
+static RefPtr<CSSPrimitiveValue> consumeAngleOrPercent(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
+{
+ const CSSParserToken& token = range.peek();
+ if (token.type() == DimensionToken) {
+ switch (token.unitType()) {
+ case CSSPrimitiveValue::UnitType::CSS_DEG:
+ case CSSPrimitiveValue::UnitType::CSS_RAD:
+ case CSSPrimitiveValue::UnitType::CSS_GRAD:
+ case CSSPrimitiveValue::UnitType::CSS_TURN:
+ return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), token.unitType());
+ default:
+ return nullptr;
+ }
+ }
+ if (token.type() == NumberToken && shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless))
+ return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), CSSPrimitiveValue::UnitType::CSS_DEG);
+ if (token.type() == PercentageToken)
+ return consumePercent(range, valueRange);
+
+ CalcParser calcParser(range, CalcAngle, valueRange);
+ if (const CSSCalcValue* calculation = calcParser.value()) {
+ if (calculation->category() == CalcAngle)
+ return calcParser.consumeValue();
+ }
+ return nullptr;
+}
+
+
RefPtr<CSSPrimitiveValue> consumeTime(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
{
const CSSParserToken& token = range.peek();
@@ -904,9 +932,9 @@
return result;
}
-static bool consumeGradientColorStops(CSSParserTokenRange& range, CSSParserMode cssParserMode, CSSGradientValue* gradient)
+static bool consumeGradientColorStops(CSSParserTokenRange& range, CSSParserMode cssParserMode, CSSGradientValue& gradient)
{
- bool supportsColorHints = gradient->gradientType() == CSSLinearGradient || gradient->gradientType() == CSSRadialGradient;
+ bool supportsColorHints = gradient.gradientType() == CSSLinearGradient || gradient.gradientType() == CSSRadialGradient;
// The first color stop cannot be a color hint.
bool previousStopWasColorHint = true;
@@ -925,7 +953,7 @@
stop.m_position = consumeLengthOrPercent(range, cssParserMode, ValueRangeAll);
if (!stop.m_color && !stop.m_position)
return false;
- gradient->addStop(stop);
+ gradient.addStop(stop);
} while (consumeCommaIncludingWhitespace(range));
// The last color stop cannot be a color hint.
@@ -933,9 +961,42 @@
return false;
// Must have 2 or more stops to be valid.
- return gradient->stopCount() >= 2;
+ return gradient.stopCount() >= 2;
}
+// https://www.w3.org/TR/css-images-4/#typedef-angular-color-stop-list
+// FIXME: This should support up to two position hints per color stop.
+static bool consumeAngularGradientColorStops(CSSParserTokenRange& range, CSSParserMode cssParserMode, CSSGradientValue& gradient)
+{
+ // The first color stop cannot be a color hint.
+ bool previousStopWasColorHint = true;
+ do {
+ CSSGradientColorStop stop;
+ stop.m_color = consumeColor(range, cssParserMode);
+
+ // Two hints in a row are not allowed.
+ if (!stop.m_color && previousStopWasColorHint)
+ return false;
+
+ previousStopWasColorHint = !stop.m_color;
+
+ // FIXME-NEWPARSER: This boolean could be removed. Null checking color would be sufficient.
+ stop.isMidpoint = !stop.m_color;
+
+ stop.m_position = consumeAngleOrPercent(range, cssParserMode, ValueRangeAll, UnitlessQuirk::Forbid);
+ if (!stop.m_color && !stop.m_position)
+ return false;
+ gradient.addStop(stop);
+ } while (consumeCommaIncludingWhitespace(range));
+
+ // The last color stop cannot be a color hint.
+ if (previousStopWasColorHint)
+ return false;
+
+ // Must have 2 or more stops to be valid.
+ return gradient.stopCount() >= 2;
+}
+
static RefPtr<CSSValue> consumeDeprecatedRadialGradient(CSSParserTokenRange& args, CSSParserMode cssParserMode, CSSGradientRepeat repeating)
{
RefPtr<CSSRadialGradientValue> result = CSSRadialGradientValue::create(repeating, CSSPrefixedRadialGradient);
@@ -972,7 +1033,7 @@
} else {
consumeCommaIncludingWhitespace(args);
}
- if (!consumeGradientColorStops(args, cssParserMode, result.get()))
+ if (!consumeGradientColorStops(args, cssParserMode, *result))
return nullptr;
return result;
@@ -1059,7 +1120,7 @@
if ((shape || sizeKeyword || horizontalSize || centerX || centerY) && !consumeCommaIncludingWhitespace(args))
return nullptr;
- if (!consumeGradientColorStops(args, cssParserMode, result.get()))
+ if (!consumeGradientColorStops(args, cssParserMode, *result))
return nullptr;
return result;
}
@@ -1092,11 +1153,53 @@
if (expectComma && !consumeCommaIncludingWhitespace(args))
return nullptr;
- if (!consumeGradientColorStops(args, cssParserMode, result.get()))
+ if (!consumeGradientColorStops(args, cssParserMode, *result))
return nullptr;
return result;
}
+static RefPtr<CSSValue> consumeConicGradient(CSSParserTokenRange& args, CSSParserContext context, CSSGradientRepeat repeating)
+{
+ if (!context.conicGradientsEnabled)
+ return nullptr;
+
+ RefPtr<CSSConicGradientValue> result = CSSConicGradientValue::create(repeating);
+
+ bool expectComma = false;
+ if (args.peek().type() == IdentToken) {
+ if (consumeIdent<CSSValueFrom>(args)) {
+ auto angle = consumeAngle(args, context.mode, UnitlessQuirk::Forbid);
+ if (!angle)
+ return nullptr;
+ result->setAngle(angle.releaseNonNull());
+ expectComma = true;
+ }
+
+ if (consumeIdent<CSSValueAt>(args)) {
+ RefPtr<CSSPrimitiveValue> centerX;
+ RefPtr<CSSPrimitiveValue> centerY;
+ consumePosition(args, context.mode, UnitlessQuirk::Forbid, centerX, centerY);
+ if (!(centerX && centerY))
+ return nullptr;
+
+ result->setFirstX(centerX.copyRef());
+ result->setFirstY(centerY.copyRef());
+
+ // Right now, conic gradients have the same start and end centers.
+ result->setSecondX(centerX.copyRef());
+ result->setSecondY(centerY.copyRef());
+
+ expectComma = true;
+ }
+ }
+
+ if (expectComma && !consumeCommaIncludingWhitespace(args))
+ return nullptr;
+ if (!consumeAngularGradientColorStops(args, context.mode, *result))
+ return nullptr;
+ return result;
+}
+
RefPtr<CSSValue> consumeImageOrNone(CSSParserTokenRange& range, CSSParserContext context)
{
if (range.peek().id() == CSSValueNone)
@@ -1186,6 +1289,10 @@
result = consumeDeprecatedRadialGradient(args, context.mode, NonRepeating);
else if (id == CSSValueWebkitRepeatingRadialGradient)
result = consumeDeprecatedRadialGradient(args, context.mode, Repeating);
+ else if (id == CSSValueConicGradient)
+ result = consumeConicGradient(args, context, NonRepeating);
+ else if (id == CSSValueRepeatingConicGradient)
+ result = consumeConicGradient(args, context, Repeating);
else if (id == CSSValueWebkitCrossFade || id == CSSValueCrossFade)
result = consumeCrossFade(args, context, id == CSSValueWebkitCrossFade);
else if (id == CSSValueWebkitCanvas)
@@ -1232,12 +1339,23 @@
static bool isGeneratedImage(CSSValueID id)
{
- return id == CSSValueLinearGradient || id == CSSValueRadialGradient
- || id == CSSValueRepeatingLinearGradient || id == CSSValueRepeatingRadialGradient
- || id == CSSValueWebkitLinearGradient || id == CSSValueWebkitRadialGradient
- || id == CSSValueWebkitRepeatingLinearGradient || id == CSSValueWebkitRepeatingRadialGradient
- || id == CSSValueWebkitGradient || id == CSSValueWebkitCrossFade || id == CSSValueWebkitCanvas
- || id == CSSValueCrossFade || id == CSSValueWebkitNamedImage || id == CSSValueWebkitFilter || id == CSSValueFilter;
+ return id == CSSValueLinearGradient
+ || id == CSSValueRadialGradient
+ || id == CSSValueConicGradient
+ || id == CSSValueRepeatingLinearGradient
+ || id == CSSValueRepeatingRadialGradient
+ || id == CSSValueRepeatingConicGradient
+ || id == CSSValueWebkitLinearGradient
+ || id == CSSValueWebkitRadialGradient
+ || id == CSSValueWebkitRepeatingLinearGradient
+ || id == CSSValueWebkitRepeatingRadialGradient
+ || id == CSSValueWebkitGradient
+ || id == CSSValueWebkitCrossFade
+ || id == CSSValueWebkitCanvas
+ || id == CSSValueCrossFade
+ || id == CSSValueWebkitNamedImage
+ || id == CSSValueWebkitFilter
+ || id == CSSValueFilter;
}
static bool isValidPrimitiveFilterFunction(CSSValueID filterFunction)
Modified: trunk/Source/WebCore/features.json (224164 => 224165)
--- trunk/Source/WebCore/features.json 2017-10-29 21:08:46 UTC (rev 224164)
+++ trunk/Source/WebCore/features.json 2017-10-29 23:07:45 UTC (rev 224165)
@@ -782,7 +782,7 @@
{
"name": "Conic Gradients",
"status": {
- "status": "Under Consideration"
+ "status": "In Development"
},
"url": "https://www.w3.org/TR/css4-images/#conic-gradients",
"specification": "CSS Image Values and Replaced Content Module Level 4",
Modified: trunk/Source/WebCore/page/Settings.yaml (224164 => 224165)
--- trunk/Source/WebCore/page/Settings.yaml 2017-10-29 21:08:46 UTC (rev 224164)
+++ trunk/Source/WebCore/page/Settings.yaml 2017-10-29 23:07:45 UTC (rev 224165)
@@ -509,6 +509,8 @@
springTimingFunctionEnabled:
initial: false
+conicGradientsEnabled:
+ initial: false
treatIPAddressAsDomain:
initial: false