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 #ifndef BasicShapes_h 31 #define BasicShapes_h 32 33 #include "core/rendering/style/RenderStyleConstants.h" 34 #include "platform/Length.h" 35 #include "platform/LengthSize.h" 36 #include "platform/graphics/WindRule.h" 37 #include "wtf/RefCounted.h" 38 #include "wtf/RefPtr.h" 39 #include "wtf/Vector.h" 40 41 namespace WebCore { 42 43 class FloatRect; 44 class FloatSize; 45 class Path; 46 47 class BasicShape : public RefCounted<BasicShape> { 48 public: 49 virtual ~BasicShape() { } 50 51 enum Type { 52 BasicShapeEllipseType, 53 BasicShapePolygonType, 54 BasicShapeCircleType, 55 BasicShapeInsetType 56 }; 57 58 bool canBlend(const BasicShape*) const; 59 bool isSameType(const BasicShape& other) const { return type() == other.type(); } 60 61 virtual void path(Path&, const FloatRect&) = 0; 62 virtual WindRule windRule() const { return RULE_NONZERO; } 63 virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const = 0; 64 virtual bool operator==(const BasicShape&) const = 0; 65 66 virtual Type type() const = 0; 67 68 protected: 69 BasicShape() 70 { 71 } 72 73 }; 74 75 #define DEFINE_BASICSHAPE_TYPE_CASTS(thisType) \ 76 DEFINE_TYPE_CASTS(thisType, BasicShape, value, value->type() == BasicShape::thisType##Type, value.type() == BasicShape::thisType##Type) 77 78 class BasicShapeCenterCoordinate { 79 public: 80 enum Direction { 81 TopLeft, 82 BottomRight 83 }; 84 BasicShapeCenterCoordinate() 85 : m_direction(TopLeft) 86 , m_length(Undefined) 87 { 88 updateComputedLength(); 89 } 90 91 BasicShapeCenterCoordinate(Direction direction, const Length& length) 92 : m_direction(direction) 93 , m_length(length) 94 { 95 updateComputedLength(); 96 } 97 98 BasicShapeCenterCoordinate(const BasicShapeCenterCoordinate& other) 99 : m_direction(other.direction()) 100 , m_length(other.length()) 101 , m_computedLength(other.m_computedLength) 102 { 103 } 104 105 bool operator==(const BasicShapeCenterCoordinate& other) const { return m_direction == other.m_direction && m_length == other.m_length && m_computedLength == other.m_computedLength; } 106 107 Direction direction() const { return m_direction; } 108 const Length& length() const { return m_length; } 109 const Length& computedLength() const { return m_computedLength; } 110 111 BasicShapeCenterCoordinate blend(const BasicShapeCenterCoordinate& other, double progress) const 112 { 113 return BasicShapeCenterCoordinate(TopLeft, m_computedLength.blend(other.m_computedLength, progress, ValueRangeAll)); 114 } 115 116 private: 117 Direction m_direction; 118 Length m_length; 119 Length m_computedLength; 120 121 void updateComputedLength(); 122 }; 123 124 class BasicShapeRadius { 125 public: 126 enum Type { 127 Value, 128 ClosestSide, 129 FarthestSide 130 }; 131 BasicShapeRadius() : m_value(Undefined), m_type(ClosestSide) { } 132 explicit BasicShapeRadius(const Length& v) : m_value(v), m_type(Value) { } 133 explicit BasicShapeRadius(Type t) : m_value(Undefined), m_type(t) { } 134 BasicShapeRadius(const BasicShapeRadius& other) : m_value(other.value()), m_type(other.type()) { } 135 bool operator==(const BasicShapeRadius& other) const { return m_type == other.m_type && m_value == other.m_value; } 136 137 const Length& value() const { return m_value; } 138 Type type() const { return m_type; } 139 140 bool canBlend(const BasicShapeRadius& other) const 141 { 142 // FIXME determine how to interpolate between keywords. See issue 330248. 143 return m_type == Value && other.type() == Value; 144 } 145 146 BasicShapeRadius blend(const BasicShapeRadius& other, double progress) const 147 { 148 if (m_type != Value || other.type() != Value) 149 return BasicShapeRadius(other); 150 151 return BasicShapeRadius(m_value.blend(other.value(), progress, ValueRangeNonNegative)); 152 } 153 154 private: 155 Length m_value; 156 Type m_type; 157 158 }; 159 160 class BasicShapeCircle FINAL : public BasicShape { 161 public: 162 static PassRefPtr<BasicShapeCircle> create() { return adoptRef(new BasicShapeCircle); } 163 164 const BasicShapeCenterCoordinate& centerX() const { return m_centerX; } 165 const BasicShapeCenterCoordinate& centerY() const { return m_centerY; } 166 const BasicShapeRadius& radius() const { return m_radius; } 167 168 float floatValueForRadiusInBox(FloatSize) const; 169 void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = centerX; } 170 void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = centerY; } 171 void setRadius(BasicShapeRadius radius) { m_radius = radius; } 172 173 virtual void path(Path&, const FloatRect&) OVERRIDE; 174 virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE; 175 virtual bool operator==(const BasicShape&) const OVERRIDE; 176 177 virtual Type type() const OVERRIDE { return BasicShapeCircleType; } 178 private: 179 BasicShapeCircle() { } 180 181 BasicShapeCenterCoordinate m_centerX; 182 BasicShapeCenterCoordinate m_centerY; 183 BasicShapeRadius m_radius; 184 }; 185 186 DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapeCircle); 187 188 class BasicShapeEllipse FINAL : public BasicShape { 189 public: 190 static PassRefPtr<BasicShapeEllipse> create() { return adoptRef(new BasicShapeEllipse); } 191 192 const BasicShapeCenterCoordinate& centerX() const { return m_centerX; } 193 const BasicShapeCenterCoordinate& centerY() const { return m_centerY; } 194 const BasicShapeRadius& radiusX() const { return m_radiusX; } 195 const BasicShapeRadius& radiusY() const { return m_radiusY; } 196 float floatValueForRadiusInBox(const BasicShapeRadius&, float center, float boxWidthOrHeight) const; 197 198 void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = centerX; } 199 void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = centerY; } 200 void setRadiusX(BasicShapeRadius radiusX) { m_radiusX = radiusX; } 201 void setRadiusY(BasicShapeRadius radiusY) { m_radiusY = radiusY; } 202 203 virtual void path(Path&, const FloatRect&) OVERRIDE; 204 virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE; 205 virtual bool operator==(const BasicShape&) const OVERRIDE; 206 207 virtual Type type() const OVERRIDE { return BasicShapeEllipseType; } 208 private: 209 BasicShapeEllipse() { } 210 211 BasicShapeCenterCoordinate m_centerX; 212 BasicShapeCenterCoordinate m_centerY; 213 BasicShapeRadius m_radiusX; 214 BasicShapeRadius m_radiusY; 215 }; 216 217 DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapeEllipse); 218 219 class BasicShapePolygon FINAL : public BasicShape { 220 public: 221 static PassRefPtr<BasicShapePolygon> create() { return adoptRef(new BasicShapePolygon); } 222 223 const Vector<Length>& values() const { return m_values; } 224 Length getXAt(unsigned i) const { return m_values.at(2 * i); } 225 Length getYAt(unsigned i) const { return m_values.at(2 * i + 1); } 226 227 void setWindRule(WindRule windRule) { m_windRule = windRule; } 228 void appendPoint(const Length& x, const Length& y) { m_values.append(x); m_values.append(y); } 229 230 virtual void path(Path&, const FloatRect&) OVERRIDE; 231 virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE; 232 virtual bool operator==(const BasicShape&) const OVERRIDE; 233 234 virtual WindRule windRule() const OVERRIDE { return m_windRule; } 235 236 virtual Type type() const OVERRIDE { return BasicShapePolygonType; } 237 private: 238 BasicShapePolygon() 239 : m_windRule(RULE_NONZERO) 240 { } 241 242 WindRule m_windRule; 243 Vector<Length> m_values; 244 }; 245 246 DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapePolygon); 247 248 class BasicShapeInset : public BasicShape { 249 public: 250 static PassRefPtr<BasicShapeInset> create() { return adoptRef(new BasicShapeInset); } 251 252 const Length& top() const { return m_top; } 253 const Length& right() const { return m_right; } 254 const Length& bottom() const { return m_bottom; } 255 const Length& left() const { return m_left; } 256 257 const LengthSize& topLeftRadius() const { return m_topLeftRadius; } 258 const LengthSize& topRightRadius() const { return m_topRightRadius; } 259 const LengthSize& bottomRightRadius() const { return m_bottomRightRadius; } 260 const LengthSize& bottomLeftRadius() const { return m_bottomLeftRadius; } 261 262 void setTop(const Length& top) { m_top = top; } 263 void setRight(const Length& right) { m_right = right; } 264 void setBottom(const Length& bottom) { m_bottom = bottom; } 265 void setLeft(const Length& left) { m_left = left; } 266 267 void setTopLeftRadius(const LengthSize& radius) { m_topLeftRadius = radius; } 268 void setTopRightRadius(const LengthSize& radius) { m_topRightRadius = radius; } 269 void setBottomRightRadius(const LengthSize& radius) { m_bottomRightRadius = radius; } 270 void setBottomLeftRadius(const LengthSize& radius) { m_bottomLeftRadius = radius; } 271 272 virtual void path(Path&, const FloatRect&) OVERRIDE; 273 virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE; 274 virtual bool operator==(const BasicShape&) const OVERRIDE; 275 276 virtual Type type() const OVERRIDE { return BasicShapeInsetType; } 277 private: 278 BasicShapeInset() { } 279 280 Length m_right; 281 Length m_top; 282 Length m_bottom; 283 Length m_left; 284 285 LengthSize m_topLeftRadius; 286 LengthSize m_topRightRadius; 287 LengthSize m_bottomRightRadius; 288 LengthSize m_bottomLeftRadius; 289 }; 290 291 DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapeInset); 292 293 } 294 #endif 295