diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp')
-rw-r--r-- | chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp | 237 |
1 files changed, 153 insertions, 84 deletions
diff --git a/chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp b/chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp index a49ea1495f1..e6399b99187 100644 --- a/chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp +++ b/chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp @@ -33,58 +33,68 @@ #include "core/css/CSSBasicShapes.h" #include "core/css/CSSPrimitiveValueMappings.h" #include "core/css/CSSValuePool.h" +#include "core/css/Pair.h" #include "core/css/resolver/StyleResolverState.h" #include "core/rendering/style/BasicShapes.h" #include "core/rendering/style/RenderStyle.h" namespace WebCore { -PassRefPtr<CSSValue> valueForBasicShape(const RenderStyle& style, const BasicShape* basicShape) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> valueForCenterCoordinate(CSSValuePool& pool, const RenderStyle& style, const BasicShapeCenterCoordinate& center, EBoxOrient orientation) +{ + 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), Pair::DropIdenticalValues)); +} + +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> basicShapeRadiusToCSSValue(CSSValuePool& pool, const RenderStyle& style, 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 nullptr; +} + +PassRefPtrWillBeRawPtr<CSSValue> valueForBasicShape(const RenderStyle& style, const BasicShape* basicShape) { CSSValuePool& pool = cssValuePool(); - RefPtr<CSSBasicShape> basicShapeValue; + RefPtrWillBeRawPtr<CSSBasicShape> basicShapeValue = nullptr; switch (basicShape->type()) { - case BasicShape::BasicShapeRectangleType: { - const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(basicShape); - RefPtr<CSSBasicShapeRectangle> rectangleValue = CSSBasicShapeRectangle::create(); - - rectangleValue->setX(pool.createValue(rectangle->x(), style)); - rectangleValue->setY(pool.createValue(rectangle->y(), style)); - rectangleValue->setWidth(pool.createValue(rectangle->width(), style)); - rectangleValue->setHeight(pool.createValue(rectangle->height(), style)); - rectangleValue->setRadiusX(pool.createValue(rectangle->cornerRadiusX(), style)); - rectangleValue->setRadiusY(pool.createValue(rectangle->cornerRadiusY(), style)); - - basicShapeValue = rectangleValue.release(); - break; - } case BasicShape::BasicShapeCircleType: { const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape); - RefPtr<CSSBasicShapeCircle> circleValue = CSSBasicShapeCircle::create(); - - circleValue->setCenterX(pool.createValue(circle->centerX(), style)); - circleValue->setCenterY(pool.createValue(circle->centerY(), style)); - circleValue->setRadius(pool.createValue(circle->radius(), style)); + RefPtrWillBeRawPtr<CSSBasicShapeCircle> circleValue = CSSBasicShapeCircle::create(); + circleValue->setCenterX(valueForCenterCoordinate(pool, style, circle->centerX(), HORIZONTAL)); + circleValue->setCenterY(valueForCenterCoordinate(pool, style, circle->centerY(), VERTICAL)); + circleValue->setRadius(basicShapeRadiusToCSSValue(pool, style, circle->radius())); basicShapeValue = circleValue.release(); break; } case BasicShape::BasicShapeEllipseType: { const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape); - RefPtr<CSSBasicShapeEllipse> ellipseValue = CSSBasicShapeEllipse::create(); - - ellipseValue->setCenterX(pool.createValue(ellipse->centerX(), style)); - ellipseValue->setCenterY(pool.createValue(ellipse->centerY(), style)); - ellipseValue->setRadiusX(pool.createValue(ellipse->radiusX(), style)); - ellipseValue->setRadiusY(pool.createValue(ellipse->radiusY(), style)); + RefPtrWillBeRawPtr<CSSBasicShapeEllipse> ellipseValue = CSSBasicShapeEllipse::create(); + ellipseValue->setCenterX(valueForCenterCoordinate(pool, style, ellipse->centerX(), HORIZONTAL)); + ellipseValue->setCenterY(valueForCenterCoordinate(pool, style, ellipse->centerY(), VERTICAL)); + ellipseValue->setRadiusX(basicShapeRadiusToCSSValue(pool, style, ellipse->radiusX())); + ellipseValue->setRadiusY(basicShapeRadiusToCSSValue(pool, style, ellipse->radiusY())); basicShapeValue = ellipseValue.release(); break; } case BasicShape::BasicShapePolygonType: { const BasicShapePolygon* polygon = static_cast<const BasicShapePolygon*>(basicShape); - RefPtr<CSSBasicShapePolygon> polygonValue = CSSBasicShapePolygon::create(); + RefPtrWillBeRawPtr<CSSBasicShapePolygon> polygonValue = CSSBasicShapePolygon::create(); polygonValue->setWindRule(polygon->windRule()); const Vector<Length>& values = polygon->values(); @@ -94,65 +104,117 @@ PassRefPtr<CSSValue> valueForBasicShape(const RenderStyle& style, const BasicSha basicShapeValue = polygonValue.release(); 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::BasicShapeInsetType: { + const BasicShapeInset* inset = static_cast<const BasicShapeInset*>(basicShape); + RefPtrWillBeRawPtr<CSSBasicShapeInset> insetValue = CSSBasicShapeInset::create(); + + insetValue->setTop(pool.createValue(inset->top(), style)); + insetValue->setRight(pool.createValue(inset->right(), style)); + insetValue->setBottom(pool.createValue(inset->bottom(), style)); + insetValue->setLeft(pool.createValue(inset->left(), style)); + + insetValue->setTopLeftRadius(CSSPrimitiveValue::create(inset->topLeftRadius(), style)); + insetValue->setTopRightRadius(CSSPrimitiveValue::create(inset->topRightRadius(), style)); + insetValue->setBottomRightRadius(CSSPrimitiveValue::create(inset->bottomRightRadius(), style)); + insetValue->setBottomLeftRadius(CSSPrimitiveValue::create(inset->bottomLeftRadius(), style)); + + basicShapeValue = insetValue.release(); break; } default: break; } + return pool.createValue(basicShapeValue.release()); } static Length convertToLength(const StyleResolverState& state, CSSPrimitiveValue* value) { + if (!value) + return Length(0, Fixed); return value->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()); } +static LengthSize convertToLengthSize(const StyleResolverState& state, CSSPrimitiveValue* value) +{ + if (!value) + return LengthSize(Length(0, Fixed), Length(0, Fixed)); + + Pair* pair = value->getPairValue(); + return LengthSize(convertToLength(state, pair->first()), convertToLength(state, pair->second())); +} + +static BasicShapeCenterCoordinate convertToCenterCoordinate(const StyleResolverState& state, 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(state, pair->second()); + } else { + offset = convertToLength(state, 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 BasicShapeCenterCoordinate(direction, offset); +} + +static BasicShapeRadius cssValueToBasicShapeRadius(const StyleResolverState& state, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> radius) +{ + 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(state, radius.get())); +} + PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState& state, 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(state, rectValue->x())); - rect->setY(convertToLength(state, rectValue->y())); - rect->setWidth(convertToLength(state, rectValue->width())); - rect->setHeight(convertToLength(state, rectValue->height())); - if (rectValue->radiusX()) { - Length radiusX = convertToLength(state, rectValue->radiusX()); - rect->setCornerRadiusX(radiusX); - if (rectValue->radiusY()) - rect->setCornerRadiusY(convertToLength(state, 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(); - circle->setCenterX(convertToLength(state, circleValue->centerX())); - circle->setCenterY(convertToLength(state, circleValue->centerY())); - circle->setRadius(convertToLength(state, circleValue->radius())); + circle->setCenterX(convertToCenterCoordinate(state, circleValue->centerX())); + circle->setCenterY(convertToCenterCoordinate(state, circleValue->centerY())); + circle->setRadius(cssValueToBasicShapeRadius(state, circleValue->radius())); basicShape = circle.release(); break; @@ -161,10 +223,10 @@ PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState& state, const const CSSBasicShapeEllipse* ellipseValue = static_cast<const CSSBasicShapeEllipse *>(basicShapeValue); RefPtr<BasicShapeEllipse> ellipse = BasicShapeEllipse::create(); - ellipse->setCenterX(convertToLength(state, ellipseValue->centerX())); - ellipse->setCenterY(convertToLength(state, ellipseValue->centerY())); - ellipse->setRadiusX(convertToLength(state, ellipseValue->radiusX())); - ellipse->setRadiusY(convertToLength(state, ellipseValue->radiusY())); + ellipse->setCenterX(convertToCenterCoordinate(state, ellipseValue->centerX())); + ellipse->setCenterY(convertToCenterCoordinate(state, ellipseValue->centerY())); + ellipse->setRadiusX(cssValueToBasicShapeRadius(state, ellipseValue->radiusX())); + ellipse->setRadiusY(cssValueToBasicShapeRadius(state, ellipseValue->radiusY())); basicShape = ellipse.release(); break; @@ -174,38 +236,45 @@ PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState& state, const RefPtr<BasicShapePolygon> polygon = BasicShapePolygon::create(); polygon->setWindRule(polygonValue->windRule()); - const Vector<RefPtr<CSSPrimitiveValue> >& values = polygonValue->values(); + const WillBeHeapVector<RefPtrWillBeMember<CSSPrimitiveValue> >& values = polygonValue->values(); for (unsigned i = 0; i < values.size(); i += 2) polygon->appendPoint(convertToLength(state, values.at(i).get()), convertToLength(state, values.at(i + 1).get())); basicShape = polygon.release(); break; } - case CSSBasicShape::CSSBasicShapeInsetRectangleType: { - const CSSBasicShapeInsetRectangle* rectValue = static_cast<const CSSBasicShapeInsetRectangle *>(basicShapeValue); - RefPtr<BasicShapeInsetRectangle> rect = BasicShapeInsetRectangle::create(); + case CSSBasicShape::CSSBasicShapeInsetType: { + const CSSBasicShapeInset* rectValue = static_cast<const CSSBasicShapeInset* >(basicShapeValue); + RefPtr<BasicShapeInset> rect = BasicShapeInset::create(); rect->setTop(convertToLength(state, rectValue->top())); rect->setRight(convertToLength(state, rectValue->right())); rect->setBottom(convertToLength(state, rectValue->bottom())); rect->setLeft(convertToLength(state, rectValue->left())); - if (rectValue->radiusX()) { - Length radiusX = convertToLength(state, rectValue->radiusX()); - rect->setCornerRadiusX(radiusX); - if (rectValue->radiusY()) - rect->setCornerRadiusY(convertToLength(state, rectValue->radiusY())); - else - rect->setCornerRadiusY(radiusX); - } else { - rect->setCornerRadiusX(Length(0, Fixed)); - rect->setCornerRadiusY(Length(0, Fixed)); - } + + rect->setTopLeftRadius(convertToLengthSize(state, rectValue->topLeftRadius())); + rect->setTopRightRadius(convertToLengthSize(state, rectValue->topRightRadius())); + rect->setBottomRightRadius(convertToLengthSize(state, rectValue->bottomRightRadius())); + rect->setBottomLeftRadius(convertToLengthSize(state, rectValue->bottomLeftRadius())); + basicShape = rect.release(); break; } default: break; } + return basicShape.release(); } + +FloatPoint floatPointForCenterCoordinate(const BasicShapeCenterCoordinate& centerX, const BasicShapeCenterCoordinate& centerY, FloatSize boxSize) +{ + FloatPoint p; + float offset = floatValueForLength(centerX.length(), boxSize.width()); + p.setX(centerX.direction() == BasicShapeCenterCoordinate::TopLeft ? offset : boxSize.width() - offset); + offset = floatValueForLength(centerY.length(), boxSize.height()); + p.setY(centerY.direction() == BasicShapeCenterCoordinate::TopLeft ? offset : boxSize.height() - offset); + return p; +} + } |