1 /* 2 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following 13 * disclaimer in the documentation and/or other materials 14 * provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AS IS AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 21 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 25 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 26 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include "config.h" 31 #include "core/css/BasicShapeFunctions.h" 32 33 #include "core/css/CSSBasicShapes.h" 34 #include "core/css/CSSPrimitiveValueMappings.h" 35 #include "core/css/CSSValuePool.h" 36 #include "core/css/resolver/StyleResolverState.h" 37 #include "core/rendering/style/BasicShapes.h" 38 #include "core/rendering/style/RenderStyle.h" 39 40 namespace WebCore { 41 42 PassRefPtr<CSSValue> valueForBasicShape(const RenderStyle& style, const BasicShape* basicShape) 43 { 44 CSSValuePool& pool = cssValuePool(); 45 46 RefPtr<CSSBasicShape> basicShapeValue; 47 switch (basicShape->type()) { 48 case BasicShape::BasicShapeRectangleType: { 49 const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(basicShape); 50 RefPtr<CSSBasicShapeRectangle> rectangleValue = CSSBasicShapeRectangle::create(); 51 52 rectangleValue->setX(pool.createValue(rectangle->x(), style)); 53 rectangleValue->setY(pool.createValue(rectangle->y(), style)); 54 rectangleValue->setWidth(pool.createValue(rectangle->width(), style)); 55 rectangleValue->setHeight(pool.createValue(rectangle->height(), style)); 56 rectangleValue->setRadiusX(pool.createValue(rectangle->cornerRadiusX(), style)); 57 rectangleValue->setRadiusY(pool.createValue(rectangle->cornerRadiusY(), style)); 58 59 basicShapeValue = rectangleValue.release(); 60 break; 61 } 62 case BasicShape::BasicShapeCircleType: { 63 const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape); 64 RefPtr<CSSBasicShapeCircle> circleValue = CSSBasicShapeCircle::create(); 65 66 circleValue->setCenterX(pool.createValue(circle->centerX(), style)); 67 circleValue->setCenterY(pool.createValue(circle->centerY(), style)); 68 circleValue->setRadius(pool.createValue(circle->radius(), style)); 69 70 basicShapeValue = circleValue.release(); 71 break; 72 } 73 case BasicShape::BasicShapeEllipseType: { 74 const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape); 75 RefPtr<CSSBasicShapeEllipse> ellipseValue = CSSBasicShapeEllipse::create(); 76 77 ellipseValue->setCenterX(pool.createValue(ellipse->centerX(), style)); 78 ellipseValue->setCenterY(pool.createValue(ellipse->centerY(), style)); 79 ellipseValue->setRadiusX(pool.createValue(ellipse->radiusX(), style)); 80 ellipseValue->setRadiusY(pool.createValue(ellipse->radiusY(), style)); 81 82 basicShapeValue = ellipseValue.release(); 83 break; 84 } 85 case BasicShape::BasicShapePolygonType: { 86 const BasicShapePolygon* polygon = static_cast<const BasicShapePolygon*>(basicShape); 87 RefPtr<CSSBasicShapePolygon> polygonValue = CSSBasicShapePolygon::create(); 88 89 polygonValue->setWindRule(polygon->windRule()); 90 const Vector<Length>& values = polygon->values(); 91 for (unsigned i = 0; i < values.size(); i += 2) 92 polygonValue->appendPoint(pool.createValue(values.at(i), style), pool.createValue(values.at(i + 1), style)); 93 94 basicShapeValue = polygonValue.release(); 95 break; 96 } 97 case BasicShape::BasicShapeInsetRectangleType: { 98 const BasicShapeInsetRectangle* rectangle = static_cast<const BasicShapeInsetRectangle*>(basicShape); 99 RefPtr<CSSBasicShapeInsetRectangle> rectangleValue = CSSBasicShapeInsetRectangle::create(); 100 101 rectangleValue->setTop(cssValuePool().createValue(rectangle->top())); 102 rectangleValue->setRight(cssValuePool().createValue(rectangle->right())); 103 rectangleValue->setBottom(cssValuePool().createValue(rectangle->bottom())); 104 rectangleValue->setLeft(cssValuePool().createValue(rectangle->left())); 105 rectangleValue->setRadiusX(cssValuePool().createValue(rectangle->cornerRadiusX())); 106 rectangleValue->setRadiusY(cssValuePool().createValue(rectangle->cornerRadiusY())); 107 108 basicShapeValue = rectangleValue.release(); 109 break; 110 } 111 default: 112 break; 113 } 114 return pool.createValue(basicShapeValue.release()); 115 } 116 117 static Length convertToLength(const StyleResolverState& state, CSSPrimitiveValue* value) 118 { 119 return value->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()); 120 } 121 122 PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState& state, const CSSBasicShape* basicShapeValue) 123 { 124 RefPtr<BasicShape> basicShape; 125 126 switch (basicShapeValue->type()) { 127 case CSSBasicShape::CSSBasicShapeRectangleType: { 128 const CSSBasicShapeRectangle* rectValue = static_cast<const CSSBasicShapeRectangle *>(basicShapeValue); 129 RefPtr<BasicShapeRectangle> rect = BasicShapeRectangle::create(); 130 131 rect->setX(convertToLength(state, rectValue->x())); 132 rect->setY(convertToLength(state, rectValue->y())); 133 rect->setWidth(convertToLength(state, rectValue->width())); 134 rect->setHeight(convertToLength(state, rectValue->height())); 135 if (rectValue->radiusX()) { 136 Length radiusX = convertToLength(state, rectValue->radiusX()); 137 rect->setCornerRadiusX(radiusX); 138 if (rectValue->radiusY()) 139 rect->setCornerRadiusY(convertToLength(state, rectValue->radiusY())); 140 else 141 rect->setCornerRadiusY(radiusX); 142 } else { 143 rect->setCornerRadiusX(Length(0, Fixed)); 144 rect->setCornerRadiusY(Length(0, Fixed)); 145 } 146 basicShape = rect.release(); 147 break; 148 } 149 case CSSBasicShape::CSSBasicShapeCircleType: { 150 const CSSBasicShapeCircle* circleValue = static_cast<const CSSBasicShapeCircle *>(basicShapeValue); 151 RefPtr<BasicShapeCircle> circle = BasicShapeCircle::create(); 152 153 circle->setCenterX(convertToLength(state, circleValue->centerX())); 154 circle->setCenterY(convertToLength(state, circleValue->centerY())); 155 circle->setRadius(convertToLength(state, circleValue->radius())); 156 157 basicShape = circle.release(); 158 break; 159 } 160 case CSSBasicShape::CSSBasicShapeEllipseType: { 161 const CSSBasicShapeEllipse* ellipseValue = static_cast<const CSSBasicShapeEllipse *>(basicShapeValue); 162 RefPtr<BasicShapeEllipse> ellipse = BasicShapeEllipse::create(); 163 164 ellipse->setCenterX(convertToLength(state, ellipseValue->centerX())); 165 ellipse->setCenterY(convertToLength(state, ellipseValue->centerY())); 166 ellipse->setRadiusX(convertToLength(state, ellipseValue->radiusX())); 167 ellipse->setRadiusY(convertToLength(state, ellipseValue->radiusY())); 168 169 basicShape = ellipse.release(); 170 break; 171 } 172 case CSSBasicShape::CSSBasicShapePolygonType: { 173 const CSSBasicShapePolygon* polygonValue = static_cast<const CSSBasicShapePolygon *>(basicShapeValue); 174 RefPtr<BasicShapePolygon> polygon = BasicShapePolygon::create(); 175 176 polygon->setWindRule(polygonValue->windRule()); 177 const Vector<RefPtr<CSSPrimitiveValue> >& values = polygonValue->values(); 178 for (unsigned i = 0; i < values.size(); i += 2) 179 polygon->appendPoint(convertToLength(state, values.at(i).get()), convertToLength(state, values.at(i + 1).get())); 180 181 basicShape = polygon.release(); 182 break; 183 } 184 case CSSBasicShape::CSSBasicShapeInsetRectangleType: { 185 const CSSBasicShapeInsetRectangle* rectValue = static_cast<const CSSBasicShapeInsetRectangle *>(basicShapeValue); 186 RefPtr<BasicShapeInsetRectangle> rect = BasicShapeInsetRectangle::create(); 187 188 rect->setTop(convertToLength(state, rectValue->top())); 189 rect->setRight(convertToLength(state, rectValue->right())); 190 rect->setBottom(convertToLength(state, rectValue->bottom())); 191 rect->setLeft(convertToLength(state, rectValue->left())); 192 if (rectValue->radiusX()) { 193 Length radiusX = convertToLength(state, rectValue->radiusX()); 194 rect->setCornerRadiusX(radiusX); 195 if (rectValue->radiusY()) 196 rect->setCornerRadiusY(convertToLength(state, rectValue->radiusY())); 197 else 198 rect->setCornerRadiusY(radiusX); 199 } else { 200 rect->setCornerRadiusX(Length(0, Fixed)); 201 rect->setCornerRadiusY(Length(0, Fixed)); 202 } 203 basicShape = rect.release(); 204 break; 205 } 206 default: 207 break; 208 } 209 return basicShape.release(); 210 } 211 } 212