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 39 namespace WebCore { 40 41 PassRefPtr<CSSValue> valueForBasicShape(const BasicShape* basicShape) 42 { 43 RefPtr<CSSBasicShape> basicShapeValue; 44 switch (basicShape->type()) { 45 case BasicShape::BasicShapeRectangleType: { 46 const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(basicShape); 47 RefPtr<CSSBasicShapeRectangle> rectangleValue = CSSBasicShapeRectangle::create(); 48 49 rectangleValue->setX(cssValuePool().createValue(rectangle->x())); 50 rectangleValue->setY(cssValuePool().createValue(rectangle->y())); 51 rectangleValue->setWidth(cssValuePool().createValue(rectangle->width())); 52 rectangleValue->setHeight(cssValuePool().createValue(rectangle->height())); 53 rectangleValue->setRadiusX(cssValuePool().createValue(rectangle->cornerRadiusX())); 54 rectangleValue->setRadiusY(cssValuePool().createValue(rectangle->cornerRadiusY())); 55 56 basicShapeValue = rectangleValue.release(); 57 break; 58 } 59 case BasicShape::BasicShapeCircleType: { 60 const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape); 61 RefPtr<CSSBasicShapeCircle> circleValue = CSSBasicShapeCircle::create(); 62 63 circleValue->setCenterX(cssValuePool().createValue(circle->centerX())); 64 circleValue->setCenterY(cssValuePool().createValue(circle->centerY())); 65 circleValue->setRadius(cssValuePool().createValue(circle->radius())); 66 67 basicShapeValue = circleValue.release(); 68 break; 69 } 70 case BasicShape::BasicShapeEllipseType: { 71 const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape); 72 RefPtr<CSSBasicShapeEllipse> ellipseValue = CSSBasicShapeEllipse::create(); 73 74 ellipseValue->setCenterX(cssValuePool().createValue(ellipse->centerX())); 75 ellipseValue->setCenterY(cssValuePool().createValue(ellipse->centerY())); 76 ellipseValue->setRadiusX(cssValuePool().createValue(ellipse->radiusX())); 77 ellipseValue->setRadiusY(cssValuePool().createValue(ellipse->radiusY())); 78 79 basicShapeValue = ellipseValue.release(); 80 break; 81 } 82 case BasicShape::BasicShapePolygonType: { 83 const BasicShapePolygon* polygon = static_cast<const BasicShapePolygon*>(basicShape); 84 RefPtr<CSSBasicShapePolygon> polygonValue = CSSBasicShapePolygon::create(); 85 86 polygonValue->setWindRule(polygon->windRule()); 87 const Vector<Length>& values = polygon->values(); 88 for (unsigned i = 0; i < values.size(); i += 2) 89 polygonValue->appendPoint(cssValuePool().createValue(values.at(i)), cssValuePool().createValue(values.at(i + 1))); 90 91 basicShapeValue = polygonValue.release(); 92 break; 93 } 94 case BasicShape::BasicShapeInsetRectangleType: { 95 const BasicShapeInsetRectangle* rectangle = static_cast<const BasicShapeInsetRectangle*>(basicShape); 96 RefPtr<CSSBasicShapeInsetRectangle> rectangleValue = CSSBasicShapeInsetRectangle::create(); 97 98 rectangleValue->setTop(cssValuePool().createValue(rectangle->top())); 99 rectangleValue->setRight(cssValuePool().createValue(rectangle->right())); 100 rectangleValue->setBottom(cssValuePool().createValue(rectangle->bottom())); 101 rectangleValue->setLeft(cssValuePool().createValue(rectangle->left())); 102 rectangleValue->setRadiusX(cssValuePool().createValue(rectangle->cornerRadiusX())); 103 rectangleValue->setRadiusY(cssValuePool().createValue(rectangle->cornerRadiusY())); 104 105 basicShapeValue = rectangleValue.release(); 106 break; 107 } 108 default: 109 break; 110 } 111 return cssValuePool().createValue<PassRefPtr<CSSBasicShape> >(basicShapeValue.release()); 112 } 113 114 static Length convertToLength(const StyleResolverState& state, CSSPrimitiveValue* value) 115 { 116 return value->convertToLength<FixedIntegerConversion | FixedFloatConversion | PercentConversion>(state.style(), state.rootElementStyle(), state.style()->effectiveZoom()); 117 } 118 119 PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState& state, const CSSBasicShape* basicShapeValue) 120 { 121 RefPtr<BasicShape> basicShape; 122 123 switch (basicShapeValue->type()) { 124 case CSSBasicShape::CSSBasicShapeRectangleType: { 125 const CSSBasicShapeRectangle* rectValue = static_cast<const CSSBasicShapeRectangle *>(basicShapeValue); 126 RefPtr<BasicShapeRectangle> rect = BasicShapeRectangle::create(); 127 128 rect->setX(convertToLength(state, rectValue->x())); 129 rect->setY(convertToLength(state, rectValue->y())); 130 rect->setWidth(convertToLength(state, rectValue->width())); 131 rect->setHeight(convertToLength(state, rectValue->height())); 132 if (rectValue->radiusX()) { 133 Length radiusX = convertToLength(state, rectValue->radiusX()); 134 rect->setCornerRadiusX(radiusX); 135 if (rectValue->radiusY()) 136 rect->setCornerRadiusY(convertToLength(state, rectValue->radiusY())); 137 else 138 rect->setCornerRadiusY(radiusX); 139 } else { 140 rect->setCornerRadiusX(Length(0, Fixed)); 141 rect->setCornerRadiusY(Length(0, Fixed)); 142 } 143 basicShape = rect.release(); 144 break; 145 } 146 case CSSBasicShape::CSSBasicShapeCircleType: { 147 const CSSBasicShapeCircle* circleValue = static_cast<const CSSBasicShapeCircle *>(basicShapeValue); 148 RefPtr<BasicShapeCircle> circle = BasicShapeCircle::create(); 149 150 circle->setCenterX(convertToLength(state, circleValue->centerX())); 151 circle->setCenterY(convertToLength(state, circleValue->centerY())); 152 circle->setRadius(convertToLength(state, circleValue->radius())); 153 154 basicShape = circle.release(); 155 break; 156 } 157 case CSSBasicShape::CSSBasicShapeEllipseType: { 158 const CSSBasicShapeEllipse* ellipseValue = static_cast<const CSSBasicShapeEllipse *>(basicShapeValue); 159 RefPtr<BasicShapeEllipse> ellipse = BasicShapeEllipse::create(); 160 161 ellipse->setCenterX(convertToLength(state, ellipseValue->centerX())); 162 ellipse->setCenterY(convertToLength(state, ellipseValue->centerY())); 163 ellipse->setRadiusX(convertToLength(state, ellipseValue->radiusX())); 164 ellipse->setRadiusY(convertToLength(state, ellipseValue->radiusY())); 165 166 basicShape = ellipse.release(); 167 break; 168 } 169 case CSSBasicShape::CSSBasicShapePolygonType: { 170 const CSSBasicShapePolygon* polygonValue = static_cast<const CSSBasicShapePolygon *>(basicShapeValue); 171 RefPtr<BasicShapePolygon> polygon = BasicShapePolygon::create(); 172 173 polygon->setWindRule(polygonValue->windRule()); 174 const Vector<RefPtr<CSSPrimitiveValue> >& values = polygonValue->values(); 175 for (unsigned i = 0; i < values.size(); i += 2) 176 polygon->appendPoint(convertToLength(state, values.at(i).get()), convertToLength(state, values.at(i + 1).get())); 177 178 basicShape = polygon.release(); 179 break; 180 } 181 case CSSBasicShape::CSSBasicShapeInsetRectangleType: { 182 const CSSBasicShapeInsetRectangle* rectValue = static_cast<const CSSBasicShapeInsetRectangle *>(basicShapeValue); 183 RefPtr<BasicShapeInsetRectangle> rect = BasicShapeInsetRectangle::create(); 184 185 rect->setTop(convertToLength(state, rectValue->top())); 186 rect->setRight(convertToLength(state, rectValue->right())); 187 rect->setBottom(convertToLength(state, rectValue->bottom())); 188 rect->setLeft(convertToLength(state, rectValue->left())); 189 if (rectValue->radiusX()) { 190 Length radiusX = convertToLength(state, rectValue->radiusX()); 191 rect->setCornerRadiusX(radiusX); 192 if (rectValue->radiusY()) 193 rect->setCornerRadiusY(convertToLength(state, rectValue->radiusY())); 194 else 195 rect->setCornerRadiusY(radiusX); 196 } else { 197 rect->setCornerRadiusX(Length(0, Fixed)); 198 rect->setCornerRadiusY(Length(0, Fixed)); 199 } 200 basicShape = rect.release(); 201 break; 202 } 203 default: 204 break; 205 } 206 return basicShape.release(); 207 } 208 } 209