summaryrefslogtreecommitdiff
path: root/Source/WebCore/css/BasicShapeFunctions.cpp
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebCore/css/BasicShapeFunctions.cpp
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/WebCore/css/BasicShapeFunctions.cpp')
-rw-r--r--Source/WebCore/css/BasicShapeFunctions.cpp310
1 files changed, 196 insertions, 114 deletions
diff --git a/Source/WebCore/css/BasicShapeFunctions.cpp b/Source/WebCore/css/BasicShapeFunctions.cpp
index c5885095e..0c9c2d6e3 100644
--- a/Source/WebCore/css/BasicShapeFunctions.cpp
+++ b/Source/WebCore/css/BasicShapeFunctions.cpp
@@ -34,175 +34,257 @@
#include "CSSBasicShapes.h"
#include "CSSPrimitiveValueMappings.h"
#include "CSSValuePool.h"
+#include "Pair.h"
#include "RenderStyle.h"
+#include "SVGPathByteStream.h"
namespace WebCore {
-PassRefPtr<CSSValue> valueForBasicShape(const BasicShape* basicShape)
+static Ref<CSSPrimitiveValue> valueForCenterCoordinate(CSSValuePool& pool, const RenderStyle& style, const BasicShapeCenterCoordinate& center, EBoxOrient orientation)
{
- RefPtr<CSSBasicShape> basicShapeValue;
- switch (basicShape->type()) {
- case BasicShape::BasicShapeRectangleType: {
- const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(basicShape);
- RefPtr<CSSBasicShapeRectangle> rectangleValue = CSSBasicShapeRectangle::create();
-
- rectangleValue->setX(cssValuePool().createValue(rectangle->x()));
- rectangleValue->setY(cssValuePool().createValue(rectangle->y()));
- rectangleValue->setWidth(cssValuePool().createValue(rectangle->width()));
- rectangleValue->setHeight(cssValuePool().createValue(rectangle->height()));
- rectangleValue->setRadiusX(cssValuePool().createValue(rectangle->cornerRadiusX()));
- rectangleValue->setRadiusY(cssValuePool().createValue(rectangle->cornerRadiusY()));
-
- basicShapeValue = rectangleValue.release();
- break;
+ if (center.direction() == BasicShapeCenterCoordinate::TopLeft)
+ return pool.createValue(center.length(), style);
+
+ CSSValueID keyword = orientation == HORIZONTAL ? CSSValueRight : CSSValueBottom;
+
+ return pool.createValue(Pair::create(pool.createIdentifierValue(keyword), pool.createValue(center.length(), style)));
+}
+
+static Ref<CSSPrimitiveValue> basicShapeRadiusToCSSValue(const RenderStyle& style, CSSValuePool& pool, const BasicShapeRadius& radius)
+{
+ switch (radius.type()) {
+ case BasicShapeRadius::Value:
+ return pool.createValue(radius.value(), style);
+ case BasicShapeRadius::ClosestSide:
+ return pool.createIdentifierValue(CSSValueClosestSide);
+ case BasicShapeRadius::FarthestSide:
+ return pool.createIdentifierValue(CSSValueFarthestSide);
}
+
+ ASSERT_NOT_REACHED();
+ return pool.createIdentifierValue(CSSValueClosestSide);
+}
+
+Ref<CSSValue> valueForBasicShape(const RenderStyle& style, const BasicShape& basicShape)
+{
+ auto& cssValuePool = CSSValuePool::singleton();
+
+ RefPtr<CSSBasicShape> basicShapeValue;
+ switch (basicShape.type()) {
case BasicShape::BasicShapeCircleType: {
- const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape);
- RefPtr<CSSBasicShapeCircle> circleValue = CSSBasicShapeCircle::create();
+ auto& circle = downcast<BasicShapeCircle>(basicShape);
+ auto circleValue = CSSBasicShapeCircle::create();
- circleValue->setCenterX(cssValuePool().createValue(circle->centerX()));
- circleValue->setCenterY(cssValuePool().createValue(circle->centerY()));
- circleValue->setRadius(cssValuePool().createValue(circle->radius()));
+ circleValue->setCenterX(valueForCenterCoordinate(cssValuePool, style, circle.centerX(), HORIZONTAL));
+ circleValue->setCenterY(valueForCenterCoordinate(cssValuePool, style, circle.centerY(), VERTICAL));
+ circleValue->setRadius(basicShapeRadiusToCSSValue(style, cssValuePool, circle.radius()));
- basicShapeValue = circleValue.release();
+ basicShapeValue = WTFMove(circleValue);
break;
}
case BasicShape::BasicShapeEllipseType: {
- const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape);
- RefPtr<CSSBasicShapeEllipse> ellipseValue = CSSBasicShapeEllipse::create();
+ auto& ellipse = downcast<BasicShapeEllipse>(basicShape);
+ auto ellipseValue = CSSBasicShapeEllipse::create();
- ellipseValue->setCenterX(cssValuePool().createValue(ellipse->centerX()));
- ellipseValue->setCenterY(cssValuePool().createValue(ellipse->centerY()));
- ellipseValue->setRadiusX(cssValuePool().createValue(ellipse->radiusX()));
- ellipseValue->setRadiusY(cssValuePool().createValue(ellipse->radiusY()));
+ ellipseValue->setCenterX(valueForCenterCoordinate(cssValuePool, style, ellipse.centerX(), HORIZONTAL));
+ ellipseValue->setCenterY(valueForCenterCoordinate(cssValuePool, style, ellipse.centerY(), VERTICAL));
+ ellipseValue->setRadiusX(basicShapeRadiusToCSSValue(style, cssValuePool, ellipse.radiusX()));
+ ellipseValue->setRadiusY(basicShapeRadiusToCSSValue(style, cssValuePool, ellipse.radiusY()));
- basicShapeValue = ellipseValue.release();
+ basicShapeValue = WTFMove(ellipseValue);
break;
}
case BasicShape::BasicShapePolygonType: {
- const BasicShapePolygon* polygon = static_cast<const BasicShapePolygon*>(basicShape);
- RefPtr<CSSBasicShapePolygon> polygonValue = CSSBasicShapePolygon::create();
+ auto& polygon = downcast<BasicShapePolygon>(basicShape);
+ auto polygonValue = CSSBasicShapePolygon::create();
- polygonValue->setWindRule(polygon->windRule());
- const Vector<Length>& values = polygon->values();
+ polygonValue->setWindRule(polygon.windRule());
+ const Vector<Length>& values = polygon.values();
for (unsigned i = 0; i < values.size(); i += 2)
- polygonValue->appendPoint(cssValuePool().createValue(values.at(i)), cssValuePool().createValue(values.at(i + 1)));
+ polygonValue->appendPoint(cssValuePool.createValue(values.at(i), style), cssValuePool.createValue(values.at(i + 1), style));
- basicShapeValue = polygonValue.release();
+ basicShapeValue = WTFMove(polygonValue);
break;
}
- case BasicShape::BasicShapeInsetRectangleType: {
- const BasicShapeInsetRectangle* rectangle = static_cast<const BasicShapeInsetRectangle*>(basicShape);
- RefPtr<CSSBasicShapeInsetRectangle> rectangleValue = CSSBasicShapeInsetRectangle::create();
-
- rectangleValue->setTop(cssValuePool().createValue(rectangle->top()));
- rectangleValue->setRight(cssValuePool().createValue(rectangle->right()));
- rectangleValue->setBottom(cssValuePool().createValue(rectangle->bottom()));
- rectangleValue->setLeft(cssValuePool().createValue(rectangle->left()));
- rectangleValue->setRadiusX(cssValuePool().createValue(rectangle->cornerRadiusX()));
- rectangleValue->setRadiusY(cssValuePool().createValue(rectangle->cornerRadiusY()));
-
- basicShapeValue = rectangleValue.release();
+ case BasicShape::BasicShapePathType: {
+ auto& pathShape = downcast<BasicShapePath>(basicShape);
+ auto pathShapeValue = CSSBasicShapePath::create(pathShape.pathData()->copy());
+ pathShapeValue->setWindRule(pathShape.windRule());
+
+ basicShapeValue = WTFMove(pathShapeValue);
break;
}
+ case BasicShape::BasicShapeInsetType: {
+ auto& inset = downcast<BasicShapeInset>(basicShape);
+ auto insetValue = CSSBasicShapeInset::create();
+
+ insetValue->setTop(cssValuePool.createValue(inset.top(), style));
+ insetValue->setRight(cssValuePool.createValue(inset.right(), style));
+ insetValue->setBottom(cssValuePool.createValue(inset.bottom(), style));
+ insetValue->setLeft(cssValuePool.createValue(inset.left(), style));
+
+ insetValue->setTopLeftRadius(cssValuePool.createValue(inset.topLeftRadius(), style));
+ insetValue->setTopRightRadius(cssValuePool.createValue(inset.topRightRadius(), style));
+ insetValue->setBottomRightRadius(cssValuePool.createValue(inset.bottomRightRadius(), style));
+ insetValue->setBottomLeftRadius(cssValuePool.createValue(inset.bottomLeftRadius(), style));
+
+ basicShapeValue = WTFMove(insetValue);
+ break;
+ }
+ }
+
+ return cssValuePool.createValue(basicShapeValue.releaseNonNull());
+}
+
+static Length convertToLength(const CSSToLengthConversionData& conversionData, CSSPrimitiveValue* value)
+{
+ return value->convertToLength<FixedIntegerConversion | FixedFloatConversion | PercentConversion | CalculatedConversion>(conversionData);
+}
+
+static LengthSize convertToLengthSize(const CSSToLengthConversionData& conversionData, CSSPrimitiveValue* value)
+{
+ if (!value)
+ return LengthSize(Length(0, Fixed), Length(0, Fixed));
+
+ Pair* pair = value->getPairValue();
+ return LengthSize(convertToLength(conversionData, pair->first()), convertToLength(conversionData, pair->second()));
+}
+
+static BasicShapeCenterCoordinate convertToCenterCoordinate(const CSSToLengthConversionData& conversionData, CSSPrimitiveValue* value)
+{
+ BasicShapeCenterCoordinate::Direction direction;
+ Length offset = Length(0, Fixed);
+
+ CSSValueID keyword = CSSValueTop;
+ if (!value)
+ keyword = CSSValueCenter;
+ else if (value->isValueID())
+ keyword = value->getValueID();
+ else if (Pair* pair = value->getPairValue()) {
+ keyword = pair->first()->getValueID();
+ offset = convertToLength(conversionData, pair->second());
+ } else
+ offset = convertToLength(conversionData, value);
+
+ switch (keyword) {
+ case CSSValueTop:
+ case CSSValueLeft:
+ direction = BasicShapeCenterCoordinate::TopLeft;
+ break;
+ case CSSValueRight:
+ case CSSValueBottom:
+ direction = BasicShapeCenterCoordinate::BottomRight;
+ break;
+ case CSSValueCenter:
+ direction = BasicShapeCenterCoordinate::TopLeft;
+ offset = Length(50, Percent);
+ break;
default:
+ ASSERT_NOT_REACHED();
+ direction = BasicShapeCenterCoordinate::TopLeft;
break;
}
- return cssValuePool().createValue<PassRefPtr<CSSBasicShape> >(basicShapeValue.release());
+
+ return BasicShapeCenterCoordinate(direction, offset);
}
-static Length convertToLength(const RenderStyle* style, const RenderStyle* rootStyle, CSSPrimitiveValue* value)
+static BasicShapeRadius cssValueToBasicShapeRadius(const CSSToLengthConversionData& conversionData, PassRefPtr<CSSPrimitiveValue> radius)
{
- return value->convertToLength<FixedIntegerConversion | FixedFloatConversion | PercentConversion | ViewportPercentageConversion>(style, rootStyle, style->effectiveZoom());
+ if (!radius)
+ return BasicShapeRadius(BasicShapeRadius::ClosestSide);
+
+ if (radius->isValueID()) {
+ switch (radius->getValueID()) {
+ case CSSValueClosestSide:
+ return BasicShapeRadius(BasicShapeRadius::ClosestSide);
+ case CSSValueFarthestSide:
+ return BasicShapeRadius(BasicShapeRadius::FarthestSide);
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+
+ return BasicShapeRadius(convertToLength(conversionData, radius.get()));
}
-PassRefPtr<BasicShape> basicShapeForValue(const RenderStyle* style, const RenderStyle* rootStyle, const CSSBasicShape* basicShapeValue)
+Ref<BasicShape> basicShapeForValue(const CSSToLengthConversionData& conversionData, const CSSBasicShape* basicShapeValue)
{
RefPtr<BasicShape> basicShape;
switch (basicShapeValue->type()) {
- case CSSBasicShape::CSSBasicShapeRectangleType: {
- const CSSBasicShapeRectangle* rectValue = static_cast<const CSSBasicShapeRectangle *>(basicShapeValue);
- RefPtr<BasicShapeRectangle> rect = BasicShapeRectangle::create();
-
- rect->setX(convertToLength(style, rootStyle, rectValue->x()));
- rect->setY(convertToLength(style, rootStyle, rectValue->y()));
- rect->setWidth(convertToLength(style, rootStyle, rectValue->width()));
- rect->setHeight(convertToLength(style, rootStyle, rectValue->height()));
- if (rectValue->radiusX()) {
- Length radiusX = convertToLength(style, rootStyle, rectValue->radiusX());
- rect->setCornerRadiusX(radiusX);
- if (rectValue->radiusY())
- rect->setCornerRadiusY(convertToLength(style, rootStyle, rectValue->radiusY()));
- else
- rect->setCornerRadiusY(radiusX);
- } else {
- rect->setCornerRadiusX(Length(0, Fixed));
- rect->setCornerRadiusY(Length(0, Fixed));
- }
- basicShape = rect.release();
- break;
- }
case CSSBasicShape::CSSBasicShapeCircleType: {
- const CSSBasicShapeCircle* circleValue = static_cast<const CSSBasicShapeCircle *>(basicShapeValue);
- RefPtr<BasicShapeCircle> circle = BasicShapeCircle::create();
+ auto& circleValue = downcast<CSSBasicShapeCircle>(*basicShapeValue);
+ auto circle = BasicShapeCircle::create();
- circle->setCenterX(convertToLength(style, rootStyle, circleValue->centerX()));
- circle->setCenterY(convertToLength(style, rootStyle, circleValue->centerY()));
- circle->setRadius(convertToLength(style, rootStyle, circleValue->radius()));
+ circle->setCenterX(convertToCenterCoordinate(conversionData, circleValue.centerX()));
+ circle->setCenterY(convertToCenterCoordinate(conversionData, circleValue.centerY()));
+ circle->setRadius(cssValueToBasicShapeRadius(conversionData, circleValue.radius()));
- basicShape = circle.release();
+ basicShape = WTFMove(circle);
break;
}
case CSSBasicShape::CSSBasicShapeEllipseType: {
- const CSSBasicShapeEllipse* ellipseValue = static_cast<const CSSBasicShapeEllipse *>(basicShapeValue);
- RefPtr<BasicShapeEllipse> ellipse = BasicShapeEllipse::create();
+ auto& ellipseValue = downcast<CSSBasicShapeEllipse>(*basicShapeValue);
+ auto ellipse = BasicShapeEllipse::create();
+
+ ellipse->setCenterX(convertToCenterCoordinate(conversionData, ellipseValue.centerX()));
+ ellipse->setCenterY(convertToCenterCoordinate(conversionData, ellipseValue.centerY()));
- ellipse->setCenterX(convertToLength(style, rootStyle, ellipseValue->centerX()));
- ellipse->setCenterY(convertToLength(style, rootStyle, ellipseValue->centerY()));
- ellipse->setRadiusX(convertToLength(style, rootStyle, ellipseValue->radiusX()));
- ellipse->setRadiusY(convertToLength(style, rootStyle, ellipseValue->radiusY()));
+ ellipse->setRadiusX(cssValueToBasicShapeRadius(conversionData, ellipseValue.radiusX()));
+ ellipse->setRadiusY(cssValueToBasicShapeRadius(conversionData, ellipseValue.radiusY()));
- basicShape = ellipse.release();
+ basicShape = WTFMove(ellipse);
break;
}
case CSSBasicShape::CSSBasicShapePolygonType: {
- const CSSBasicShapePolygon* polygonValue = static_cast<const CSSBasicShapePolygon *>(basicShapeValue);
- RefPtr<BasicShapePolygon> polygon = BasicShapePolygon::create();
+ auto& polygonValue = downcast<CSSBasicShapePolygon>(*basicShapeValue);
+ auto polygon = BasicShapePolygon::create();
- polygon->setWindRule(polygonValue->windRule());
- const Vector<RefPtr<CSSPrimitiveValue> >& values = polygonValue->values();
+ polygon->setWindRule(polygonValue.windRule());
+ const Vector<RefPtr<CSSPrimitiveValue>>& values = polygonValue.values();
for (unsigned i = 0; i < values.size(); i += 2)
- polygon->appendPoint(convertToLength(style, rootStyle, values.at(i).get()), convertToLength(style, rootStyle, values.at(i + 1).get()));
+ polygon->appendPoint(convertToLength(conversionData, values.at(i).get()), convertToLength(conversionData, values.at(i + 1).get()));
- basicShape = polygon.release();
+ basicShape = WTFMove(polygon);
break;
}
- case CSSBasicShape::CSSBasicShapeInsetRectangleType: {
- const CSSBasicShapeInsetRectangle* rectValue = static_cast<const CSSBasicShapeInsetRectangle *>(basicShapeValue);
- RefPtr<BasicShapeInsetRectangle> rect = BasicShapeInsetRectangle::create();
-
- rect->setTop(convertToLength(style, rootStyle, rectValue->top()));
- rect->setRight(convertToLength(style, rootStyle, rectValue->right()));
- rect->setBottom(convertToLength(style, rootStyle, rectValue->bottom()));
- rect->setLeft(convertToLength(style, rootStyle, rectValue->left()));
- if (rectValue->radiusX()) {
- Length radiusX = convertToLength(style, rootStyle, rectValue->radiusX());
- rect->setCornerRadiusX(radiusX);
- if (rectValue->radiusY())
- rect->setCornerRadiusY(convertToLength(style, rootStyle, rectValue->radiusY()));
- else
- rect->setCornerRadiusY(radiusX);
- } else {
- rect->setCornerRadiusX(Length(0, Fixed));
- rect->setCornerRadiusY(Length(0, Fixed));
- }
- basicShape = rect.release();
+ case CSSBasicShape::CSSBasicShapeInsetType: {
+ auto& rectValue = downcast<CSSBasicShapeInset>(*basicShapeValue);
+ auto rect = BasicShapeInset::create();
+
+ rect->setTop(convertToLength(conversionData, rectValue.top()));
+ rect->setRight(convertToLength(conversionData, rectValue.right()));
+ rect->setBottom(convertToLength(conversionData, rectValue.bottom()));
+ rect->setLeft(convertToLength(conversionData, rectValue.left()));
+
+ rect->setTopLeftRadius(convertToLengthSize(conversionData, rectValue.topLeftRadius()));
+ rect->setTopRightRadius(convertToLengthSize(conversionData, rectValue.topRightRadius()));
+ rect->setBottomRightRadius(convertToLengthSize(conversionData, rectValue.bottomRightRadius()));
+ rect->setBottomLeftRadius(convertToLengthSize(conversionData, rectValue.bottomLeftRadius()));
+
+ basicShape = WTFMove(rect);
break;
}
- default:
+ case CSSBasicShape::CSSBasicShapePathType: {
+ auto& pathValue = downcast<CSSBasicShapePath>(*basicShapeValue);
+ auto path = BasicShapePath::create(pathValue.pathData().copy());
+ path->setWindRule(pathValue.windRule());
+
+ basicShape = WTFMove(path);
break;
}
- return basicShape.release();
+ }
+
+ return basicShape.releaseNonNull();
}
+
+float floatValueForCenterCoordinate(const BasicShapeCenterCoordinate& center, float boxDimension)
+{
+ float offset = floatValueForLength(center.length(), boxDimension);
+ if (center.direction() == BasicShapeCenterCoordinate::TopLeft)
+ return offset;
+ return boxDimension - offset;
+}
+
}