Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(496)

Unified Diff: third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp

Issue 1802673003: Move consumeColor and consumePosition to CSSPropertyParserHelpers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
index 2e39e04fe694793600a537849750f10235ce3a63..6a0d58dc6547f9b40b628a58d71b436696b2b0dd 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
@@ -6,6 +6,9 @@
#include "core/css/CSSCalculationValue.h"
#include "core/css/CSSStringValue.h"
+#include "core/css/CSSValuePair.h"
+// TODO(timloh): Remove this dependency
+#include "core/css/parser/CSSPropertyParser.h"
namespace blink {
@@ -323,6 +326,275 @@ String consumeUrl(CSSParserTokenRange& range)
return String();
}
+static int clampRGBComponent(const CSSPrimitiveValue& value)
+{
+ double result = value.getDoubleValue();
+ // TODO(timloh): Multiply by 2.55 and round instead of floor.
+ if (value.isPercentage())
+ result *= 2.56;
+ return clampTo<int>(result, 0, 255);
+}
+
+static bool parseRGBParameters(CSSParserTokenRange& range, RGBA32& result, bool parseAlpha)
+{
+ ASSERT(range.peek().functionId() == CSSValueRgb || range.peek().functionId() == CSSValueRgba);
+ CSSParserTokenRange args = consumeFunction(range);
+ RefPtrWillBeRawPtr<CSSPrimitiveValue> colorParameter = consumeInteger(args);
+ if (!colorParameter)
+ colorParameter = consumePercent(args, ValueRangeAll);
+ if (!colorParameter)
+ return false;
+ const bool isPercent = colorParameter->isPercentage();
+ int colorArray[3];
+ colorArray[0] = clampRGBComponent(*colorParameter);
+ for (int i = 1; i < 3; i++) {
+ if (!consumeCommaIncludingWhitespace(args))
+ return false;
+ colorParameter = isPercent ? consumePercent(args, ValueRangeAll) : consumeInteger(args);
+ if (!colorParameter)
+ return false;
+ colorArray[i] = clampRGBComponent(*colorParameter);
+ }
+ if (parseAlpha) {
+ if (!consumeCommaIncludingWhitespace(args))
+ return false;
+ double alpha;
+ if (!consumeNumberRaw(args, alpha))
+ return false;
+ // Convert the floating pointer number of alpha to an integer in the range [0, 256),
+ // with an equal distribution across all 256 values.
+ int alphaComponent = static_cast<int>(clampTo<double>(alpha, 0.0, 1.0) * nextafter(256.0, 0.0));
+ result = makeRGBA(colorArray[0], colorArray[1], colorArray[2], alphaComponent);
+ } else {
+ result = makeRGB(colorArray[0], colorArray[1], colorArray[2]);
+ }
+ return args.atEnd();
+}
+
+static bool parseHSLParameters(CSSParserTokenRange& range, RGBA32& result, bool parseAlpha)
+{
+ ASSERT(range.peek().functionId() == CSSValueHsl || range.peek().functionId() == CSSValueHsla);
+ CSSParserTokenRange args = consumeFunction(range);
+ RefPtrWillBeRawPtr<CSSPrimitiveValue> hslValue = consumeNumber(args, ValueRangeAll);
+ if (!hslValue)
+ return false;
+ double colorArray[3];
+ colorArray[0] = (((hslValue->getIntValue() % 360) + 360) % 360) / 360.0;
+ for (int i = 1; i < 3; i++) {
+ if (!consumeCommaIncludingWhitespace(args))
+ return false;
+ hslValue = consumePercent(args, ValueRangeAll);
+ if (!hslValue)
+ return false;
+ double doubleValue = hslValue->getDoubleValue();
+ colorArray[i] = clampTo<double>(doubleValue, 0.0, 100.0) / 100.0; // Needs to be value between 0 and 1.0.
+ }
+ double alpha = 1.0;
+ if (parseAlpha) {
+ if (!consumeCommaIncludingWhitespace(args))
+ return false;
+ if (!consumeNumberRaw(args, alpha))
+ return false;
+ alpha = clampTo<double>(alpha, 0.0, 1.0);
+ }
+ result = makeRGBAFromHSLA(colorArray[0], colorArray[1], colorArray[2], alpha);
+ return args.atEnd();
+}
+
+static bool parseHexColor(CSSParserTokenRange& range, RGBA32& result, bool acceptQuirkyColors)
+{
+ const CSSParserToken& token = range.peek();
+ String color;
+ if (acceptQuirkyColors) {
+ if (token.type() == NumberToken && token.numericValueType() == IntegerValueType
+ && token.numericValue() >= 0. && token.numericValue() < 1000000.) { // e.g. 112233
+ color = String::format("%06d", static_cast<int>(token.numericValue()));
+ } else if (token.type() == DimensionToken) { // e.g. 0001FF
+ // TODO(timloh): This should check the numericValueType flag
Timothy Loh 2016/03/15 03:59:41 I added a TODO here, this would fix the remaining
+ color = String::number(static_cast<int>(token.numericValue())) + String(token.value());
+ if (color.length() > 6)
+ return false;
+ while (color.length() < 6)
+ color = "0" + color;
+ } else if (token.type() == IdentToken) { // e.g. FF0000
+ color = token.value();
+ }
+ }
+ if (token.type() == HashToken)
+ color = token.value();
+ if (!Color::parseHexColor(color, result))
+ return false;
+ range.consumeIncludingWhitespace();
+ return true;
+}
+
+static bool parseColorFunction(CSSParserTokenRange& range, RGBA32& result)
+{
+ CSSValueID functionId = range.peek().functionId();
+ if (functionId < CSSValueRgb || functionId > CSSValueHsla)
+ return false;
+ CSSParserTokenRange colorRange = range;
+ if ((functionId <= CSSValueRgba && !parseRGBParameters(colorRange, result, functionId == CSSValueRgba))
+ || (functionId >= CSSValueHsl && !parseHSLParameters(colorRange, result, functionId == CSSValueHsla)))
+ return false;
+ range = colorRange;
+ return true;
+}
+
+PassRefPtrWillBeRawPtr<CSSValue> consumeColor(CSSParserTokenRange& range, CSSParserMode cssParserMode, bool acceptQuirkyColors)
+{
+ CSSValueID id = range.peek().id();
+ if (CSSPropertyParser::isColorKeyword(id)) {
+ if (!isValueAllowedInMode(id, cssParserMode))
+ return nullptr;
+ return consumeIdent(range);
+ }
+ RGBA32 color = Color::transparent;
+ if (!parseHexColor(range, color, acceptQuirkyColors) && !parseColorFunction(range, color))
+ return nullptr;
+ return cssValuePool().createColorValue(color);
+}
+
+static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumePositionComponent(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)
+{
+ if (range.peek().type() == IdentToken)
+ return consumeIdent<CSSValueLeft, CSSValueTop, CSSValueBottom, CSSValueRight, CSSValueCenter>(range);
+ return consumeLengthOrPercent(range, cssParserMode, ValueRangeAll, unitless);
+}
+
+static bool isHorizontalPositionKeywordOnly(const CSSPrimitiveValue& value)
+{
+ return value.isValueID() && (value.getValueID() == CSSValueLeft || value.getValueID() == CSSValueRight);
+}
+
+static bool isVerticalPositionKeywordOnly(const CSSPrimitiveValue& value)
+{
+ return value.isValueID() && (value.getValueID() == CSSValueTop || value.getValueID() == CSSValueBottom);
+}
+
+static void positionFromOneValue(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> value, RefPtrWillBeRawPtr<CSSValue>& resultX, RefPtrWillBeRawPtr<CSSValue>& resultY)
+{
+ bool valueAppliesToYAxisOnly = isVerticalPositionKeywordOnly(*value);
+ resultX = value;
+ resultY = cssValuePool().createIdentifierValue(CSSValueCenter);
+ if (valueAppliesToYAxisOnly)
+ swap(resultX, resultY);
+}
+
+static bool positionFromTwoValues(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> value1, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> value2,
+ RefPtrWillBeRawPtr<CSSValue>& resultX, RefPtrWillBeRawPtr<CSSValue>& resultY)
+{
+ bool mustOrderAsXY = isHorizontalPositionKeywordOnly(*value1) || isVerticalPositionKeywordOnly(*value2)
+ || !value1->isValueID() || !value2->isValueID();
+ bool mustOrderAsYX = isVerticalPositionKeywordOnly(*value1) || isHorizontalPositionKeywordOnly(*value2);
+ if (mustOrderAsXY && mustOrderAsYX)
+ return false;
+ resultX = value1;
+ resultY = value2;
+ if (mustOrderAsYX)
+ swap(resultX, resultY);
+ return true;
+}
+
+static bool positionFromThreeOrFourValues(CSSPrimitiveValue** values, RefPtrWillBeRawPtr<CSSValue>& resultX, RefPtrWillBeRawPtr<CSSValue>& resultY)
+{
+ CSSPrimitiveValue* center = nullptr;
+ for (int i = 0; values[i]; i++) {
+ CSSPrimitiveValue* currentValue = values[i];
+ if (!currentValue->isValueID())
+ return false;
+ CSSValueID id = currentValue->getValueID();
+
+ if (id == CSSValueCenter) {
+ if (center)
+ return false;
+ center = currentValue;
+ continue;
+ }
+
+ RefPtrWillBeRawPtr<CSSValue> result = nullptr;
+ if (values[i + 1] && !values[i + 1]->isValueID()) {
+ result = CSSValuePair::create(currentValue, values[++i], CSSValuePair::KeepIdenticalValues);
+ } else {
+ result = currentValue;
+ }
+
+ if (id == CSSValueLeft || id == CSSValueRight) {
+ if (resultX)
+ return false;
+ resultX = result.release();
+ } else {
+ ASSERT(id == CSSValueTop || id == CSSValueBottom);
+ if (resultY)
+ return false;
+ resultY = result.release();
+ }
+ }
+
+ if (center) {
+ ASSERT(resultX || resultY);
+ if (resultX && resultY)
+ return false;
+ if (!resultX)
+ resultX = center;
+ else
+ resultY = center;
+ }
+
+ ASSERT(resultX && resultY);
+ return true;
+}
+
+// TODO(timloh): This may consume from the range upon failure. The background
Timothy Loh 2016/03/15 03:59:41 I changed the previous comment into this TODO.
+// shorthand works around it, but we should just fix it here.
+bool consumePosition(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, RefPtrWillBeRawPtr<CSSValue>& resultX, RefPtrWillBeRawPtr<CSSValue>& resultY)
+{
+ RefPtrWillBeRawPtr<CSSPrimitiveValue> value1 = consumePositionComponent(range, cssParserMode, unitless);
+ if (!value1)
+ return false;
+
+ RefPtrWillBeRawPtr<CSSPrimitiveValue> value2 = consumePositionComponent(range, cssParserMode, unitless);
+ if (!value2) {
+ positionFromOneValue(value1.release(), resultX, resultY);
+ return true;
+ }
+
+ RefPtrWillBeRawPtr<CSSPrimitiveValue> value3 = consumePositionComponent(range, cssParserMode, unitless);
+ if (!value3)
+ return positionFromTwoValues(value1.release(), value2.release(), resultX, resultY);
+
+ RefPtrWillBeRawPtr<CSSPrimitiveValue> value4 = consumePositionComponent(range, cssParserMode, unitless);
+ CSSPrimitiveValue* values[5];
+ values[0] = value1.get();
+ values[1] = value2.get();
+ values[2] = value3.get();
+ values[3] = value4.get();
+ values[4] = nullptr;
+ return positionFromThreeOrFourValues(values, resultX, resultY);
+}
+
+PassRefPtrWillBeRawPtr<CSSValuePair> consumePosition(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)
+{
+ RefPtrWillBeRawPtr<CSSValue> resultX = nullptr;
+ RefPtrWillBeRawPtr<CSSValue> resultY = nullptr;
+ if (consumePosition(range, cssParserMode, unitless, resultX, resultY))
+ return CSSValuePair::create(resultX.release(), resultY.release(), CSSValuePair::KeepIdenticalValues);
+ return nullptr;
+}
+
+bool consumeOneOrTwoValuedPosition(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, RefPtrWillBeRawPtr<CSSValue>& resultX, RefPtrWillBeRawPtr<CSSValue>& resultY)
+{
+ RefPtrWillBeRawPtr<CSSPrimitiveValue> value1 = consumePositionComponent(range, cssParserMode, unitless);
+ if (!value1)
+ return false;
+ RefPtrWillBeRawPtr<CSSPrimitiveValue> value2 = consumePositionComponent(range, cssParserMode, unitless);
+ if (!value2) {
+ positionFromOneValue(value1.release(), resultX, resultY);
+ return true;
+ }
+ return positionFromTwoValues(value1.release(), value2.release(), resultX, resultY);
+}
+
} // namespace CSSPropertyParserHelpers
} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698