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

Unified Diff: third_party/WebKit/Source/core/css/properties/CSSPropertyShapeUtil.cpp

Issue 2642013002: Implements CSSPropertyAPI for the shape-outside property. (Closed)
Patch Set: Created 3 years, 11 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
Index: third_party/WebKit/Source/core/css/properties/CSSPropertyShapeUtil.cpp
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyShapeUtil.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyShapeUtil.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6a368c366051f2f20a583f760cb2a4d7a7519402
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyShapeUtil.cpp
@@ -0,0 +1,213 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSPropertyShapeUtil.h"
+
+#include "core/css/CSSBasicShapeValues.h"
+#include "core/css/parser/CSSParserContext.h"
+#include "core/css/parser/CSSParserMode.h"
+#include "core/css/parser/CSSParserTokenRange.h"
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+
+namespace blink {
+
+using namespace CSSPropertyParserHelpers;
+
+namespace {
+
+static CSSValue* consumeShapeRadius(CSSParserTokenRange& args,
aazzam 2017/01/19 01:48:38 put all these static helper functions into an anon
+ CSSParserMode cssParserMode) {
+ if (identMatches<CSSValueClosestSide, CSSValueFarthestSide>(args.peek().id()))
+ return consumeIdent(args);
+ return consumeLengthOrPercent(args, cssParserMode, ValueRangeNonNegative);
+}
+
+static CSSBasicShapeCircleValue* consumeBasicShapeCircle(
+ CSSParserTokenRange& args,
+ const CSSParserContext* context) {
+ // spec: https://drafts.csswg.org/css-shapes/#supported-basic-shapes
+ // circle( [<shape-radius>]? [at <position>]? )
+ CSSBasicShapeCircleValue* shape = CSSBasicShapeCircleValue::create();
+ if (CSSValue* radius = consumeShapeRadius(args, context->mode()))
+ shape->setRadius(radius);
+ if (consumeIdent<CSSValueAt>(args)) {
+ CSSValue* centerX = nullptr;
+ CSSValue* centerY = nullptr;
+ if (!consumePosition(args, context->mode(), UnitlessQuirk::Forbid, centerX,
+ centerY))
+ return nullptr;
+ shape->setCenterX(centerX);
+ shape->setCenterY(centerY);
+ }
+ return shape;
+}
+
+static CSSBasicShapeEllipseValue* consumeBasicShapeEllipse(
+ CSSParserTokenRange& args,
+ const CSSParserContext* context) {
+ // spec: https://drafts.csswg.org/css-shapes/#supported-basic-shapes
+ // ellipse( [<shape-radius>{2}]? [at <position>]? )
+ CSSBasicShapeEllipseValue* shape = CSSBasicShapeEllipseValue::create();
+ if (CSSValue* radiusX = consumeShapeRadius(args, context->mode())) {
+ shape->setRadiusX(radiusX);
+ if (CSSValue* radiusY = consumeShapeRadius(args, context->mode()))
+ shape->setRadiusY(radiusY);
+ }
+ if (consumeIdent<CSSValueAt>(args)) {
+ CSSValue* centerX = nullptr;
+ CSSValue* centerY = nullptr;
+ if (!consumePosition(args, context->mode(), UnitlessQuirk::Forbid, centerX,
+ centerY))
+ return nullptr;
+ shape->setCenterX(centerX);
+ shape->setCenterY(centerY);
+ }
+ return shape;
+}
+
+static CSSBasicShapePolygonValue* consumeBasicShapePolygon(
+ CSSParserTokenRange& args,
+ const CSSParserContext* context) {
+ CSSBasicShapePolygonValue* shape = CSSBasicShapePolygonValue::create();
+ if (identMatches<CSSValueEvenodd, CSSValueNonzero>(args.peek().id())) {
+ shape->setWindRule(args.consumeIncludingWhitespace().id() == CSSValueEvenodd
+ ? RULE_EVENODD
+ : RULE_NONZERO);
+ if (!consumeCommaIncludingWhitespace(args))
+ return nullptr;
+ }
+
+ do {
+ CSSPrimitiveValue* xLength =
+ consumeLengthOrPercent(args, context->mode(), ValueRangeAll);
+ if (!xLength)
+ return nullptr;
+ CSSPrimitiveValue* yLength =
+ consumeLengthOrPercent(args, context->mode(), ValueRangeAll);
+ if (!yLength)
+ return nullptr;
+ shape->appendPoint(xLength, yLength);
+ } while (consumeCommaIncludingWhitespace(args));
+ return shape;
+}
+
+static CSSBasicShapeInsetValue* consumeBasicShapeInset(
+ CSSParserTokenRange& args,
+ const CSSParserContext* context) {
+ CSSBasicShapeInsetValue* shape = CSSBasicShapeInsetValue::create();
+ CSSPrimitiveValue* top =
+ consumeLengthOrPercent(args, context->mode(), ValueRangeAll);
+ if (!top)
+ return nullptr;
+ CSSPrimitiveValue* right =
+ consumeLengthOrPercent(args, context->mode(), ValueRangeAll);
+ CSSPrimitiveValue* bottom = nullptr;
+ CSSPrimitiveValue* left = nullptr;
+ if (right) {
+ bottom = consumeLengthOrPercent(args, context->mode(), ValueRangeAll);
+ if (bottom)
+ left = consumeLengthOrPercent(args, context->mode(), ValueRangeAll);
+ }
+ if (left)
+ shape->updateShapeSize4Values(top, right, bottom, left);
+ else if (bottom)
+ shape->updateShapeSize3Values(top, right, bottom);
+ else if (right)
+ shape->updateShapeSize2Values(top, right);
+ else
+ shape->updateShapeSize1Value(top);
+
+ if (consumeIdent<CSSValueRound>(args)) {
+ CSSValue* horizontalRadii[4] = {0};
+ CSSValue* verticalRadii[4] = {0};
+ if (!CSSPropertyShapeUtil::consumeRadii(
+ horizontalRadii, verticalRadii, args, context->mode(), false))
+ return nullptr;
+ shape->setTopLeftRadius(
+ CSSValuePair::create(horizontalRadii[0], verticalRadii[0],
+ CSSValuePair::DropIdenticalValues));
+ shape->setTopRightRadius(
+ CSSValuePair::create(horizontalRadii[1], verticalRadii[1],
+ CSSValuePair::DropIdenticalValues));
+ shape->setBottomRightRadius(
+ CSSValuePair::create(horizontalRadii[2], verticalRadii[2],
+ CSSValuePair::DropIdenticalValues));
+ shape->setBottomLeftRadius(
+ CSSValuePair::create(horizontalRadii[3], verticalRadii[3],
+ CSSValuePair::DropIdenticalValues));
+ }
+ return shape;
+}
+
+} // namespace
+
+bool CSSPropertyShapeUtil::consumeRadii(
+ CSSValue* horizontalRadii[4],
+ CSSValue* verticalRadii[4],
+ CSSParserTokenRange& range,
+ CSSParserMode cssParserMode,
+ bool useLegacyParsing) {
+ unsigned i = 0;
+ for (; i < 4 && !range.atEnd() && range.peek().type() != DelimiterToken;
+ ++i) {
+ horizontalRadii[i] =
+ consumeLengthOrPercent(range, cssParserMode, ValueRangeNonNegative);
+ if (!horizontalRadii[i])
+ return false;
+ }
+ if (!horizontalRadii[0])
+ return false;
+ if (range.atEnd()) {
+ // Legacy syntax: -webkit-border-radius: l1 l2; is equivalent to
+ // border-radius: l1 / l2;
+ if (useLegacyParsing && i == 2) {
+ verticalRadii[0] = horizontalRadii[1];
+ horizontalRadii[1] = nullptr;
+ } else {
+ complete4Sides(horizontalRadii);
+ for (unsigned i = 0; i < 4; ++i)
+ verticalRadii[i] = horizontalRadii[i];
+ return true;
+ }
+ } else {
+ if (!consumeSlashIncludingWhitespace(range))
+ return false;
+ for (i = 0; i < 4 && !range.atEnd(); ++i) {
+ verticalRadii[i] =
+ consumeLengthOrPercent(range, cssParserMode, ValueRangeNonNegative);
+ if (!verticalRadii[i])
+ return false;
+ }
+ if (!verticalRadii[0] || !range.atEnd())
+ return false;
+ }
+ complete4Sides(horizontalRadii);
+ complete4Sides(verticalRadii);
+ return true;
+}
+
+CSSValue* CSSPropertyShapeUtil::consumeBasicShape(
+ CSSParserTokenRange& range,
+ const CSSParserContext* context) {
+ CSSValue* shape = nullptr;
+ if (range.peek().type() != FunctionToken)
+ return nullptr;
+ CSSValueID id = range.peek().functionId();
+ CSSParserTokenRange rangeCopy = range;
+ CSSParserTokenRange args = consumeFunction(rangeCopy);
+ if (id == CSSValueCircle)
+ shape = consumeBasicShapeCircle(args, context);
+ else if (id == CSSValueEllipse)
+ shape = consumeBasicShapeEllipse(args, context);
+ else if (id == CSSValuePolygon)
+ shape = consumeBasicShapePolygon(args, context);
+ else if (id == CSSValueInset)
+ shape = consumeBasicShapeInset(args, context);
+ if (!shape || !args.atEnd())
+ return nullptr;
+ range = rangeCopy;
+ return shape;
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698