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: ~BasicShape()49 virtual ~BasicShape() { } 50 51 enum Type { 52 BasicShapeEllipseType, 53 BasicShapePolygonType, 54 BasicShapeCircleType, 55 BasicShapeInsetType 56 }; 57 58 bool canBlend(const BasicShape*) const; isSameType(const BasicShape & other)59 bool isSameType(const BasicShape& other) const { return type() == other.type(); } 60 61 virtual void path(Path&, const FloatRect&) = 0; windRule()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: BasicShape()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 }; BasicShapeCenterCoordinate()84 BasicShapeCenterCoordinate() 85 : m_direction(TopLeft) 86 , m_length(Undefined) 87 { 88 updateComputedLength(); 89 } 90 BasicShapeCenterCoordinate(Direction direction,const Length & length)91 BasicShapeCenterCoordinate(Direction direction, const Length& length) 92 : m_direction(direction) 93 , m_length(length) 94 { 95 updateComputedLength(); 96 } 97 BasicShapeCenterCoordinate(const BasicShapeCenterCoordinate & other)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 direction()107 Direction direction() const { return m_direction; } length()108 const Length& length() const { return m_length; } computedLength()109 const Length& computedLength() const { return m_computedLength; } 110 blend(const BasicShapeCenterCoordinate & other,double progress)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 }; BasicShapeRadius()131 BasicShapeRadius() : m_value(Undefined), m_type(ClosestSide) { } BasicShapeRadius(const Length & v)132 explicit BasicShapeRadius(const Length& v) : m_value(v), m_type(Value) { } BasicShapeRadius(Type t)133 explicit BasicShapeRadius(Type t) : m_value(Undefined), m_type(t) { } BasicShapeRadius(const BasicShapeRadius & other)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 value()137 const Length& value() const { return m_value; } type()138 Type type() const { return m_type; } 139 canBlend(const BasicShapeRadius & other)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 blend(const BasicShapeRadius & other,double progress)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: create()162 static PassRefPtr<BasicShapeCircle> create() { return adoptRef(new BasicShapeCircle); } 163 centerX()164 const BasicShapeCenterCoordinate& centerX() const { return m_centerX; } centerY()165 const BasicShapeCenterCoordinate& centerY() const { return m_centerY; } radius()166 const BasicShapeRadius& radius() const { return m_radius; } 167 168 float floatValueForRadiusInBox(FloatSize) const; setCenterX(BasicShapeCenterCoordinate centerX)169 void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = centerX; } setCenterY(BasicShapeCenterCoordinate centerY)170 void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = centerY; } setRadius(BasicShapeRadius radius)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 type()177 virtual Type type() const OVERRIDE { return BasicShapeCircleType; } 178 private: BasicShapeCircle()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: create()190 static PassRefPtr<BasicShapeEllipse> create() { return adoptRef(new BasicShapeEllipse); } 191 centerX()192 const BasicShapeCenterCoordinate& centerX() const { return m_centerX; } centerY()193 const BasicShapeCenterCoordinate& centerY() const { return m_centerY; } radiusX()194 const BasicShapeRadius& radiusX() const { return m_radiusX; } radiusY()195 const BasicShapeRadius& radiusY() const { return m_radiusY; } 196 float floatValueForRadiusInBox(const BasicShapeRadius&, float center, float boxWidthOrHeight) const; 197 setCenterX(BasicShapeCenterCoordinate centerX)198 void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = centerX; } setCenterY(BasicShapeCenterCoordinate centerY)199 void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = centerY; } setRadiusX(BasicShapeRadius radiusX)200 void setRadiusX(BasicShapeRadius radiusX) { m_radiusX = radiusX; } setRadiusY(BasicShapeRadius radiusY)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 type()207 virtual Type type() const OVERRIDE { return BasicShapeEllipseType; } 208 private: BasicShapeEllipse()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: create()221 static PassRefPtr<BasicShapePolygon> create() { return adoptRef(new BasicShapePolygon); } 222 values()223 const Vector<Length>& values() const { return m_values; } getXAt(unsigned i)224 Length getXAt(unsigned i) const { return m_values.at(2 * i); } getYAt(unsigned i)225 Length getYAt(unsigned i) const { return m_values.at(2 * i + 1); } 226 setWindRule(WindRule windRule)227 void setWindRule(WindRule windRule) { m_windRule = windRule; } appendPoint(const Length & x,const Length & y)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 windRule()234 virtual WindRule windRule() const OVERRIDE { return m_windRule; } 235 type()236 virtual Type type() const OVERRIDE { return BasicShapePolygonType; } 237 private: BasicShapePolygon()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: create()250 static PassRefPtr<BasicShapeInset> create() { return adoptRef(new BasicShapeInset); } 251 top()252 const Length& top() const { return m_top; } right()253 const Length& right() const { return m_right; } bottom()254 const Length& bottom() const { return m_bottom; } left()255 const Length& left() const { return m_left; } 256 topLeftRadius()257 const LengthSize& topLeftRadius() const { return m_topLeftRadius; } topRightRadius()258 const LengthSize& topRightRadius() const { return m_topRightRadius; } bottomRightRadius()259 const LengthSize& bottomRightRadius() const { return m_bottomRightRadius; } bottomLeftRadius()260 const LengthSize& bottomLeftRadius() const { return m_bottomLeftRadius; } 261 setTop(const Length & top)262 void setTop(const Length& top) { m_top = top; } setRight(const Length & right)263 void setRight(const Length& right) { m_right = right; } setBottom(const Length & bottom)264 void setBottom(const Length& bottom) { m_bottom = bottom; } setLeft(const Length & left)265 void setLeft(const Length& left) { m_left = left; } 266 setTopLeftRadius(const LengthSize & radius)267 void setTopLeftRadius(const LengthSize& radius) { m_topLeftRadius = radius; } setTopRightRadius(const LengthSize & radius)268 void setTopRightRadius(const LengthSize& radius) { m_topRightRadius = radius; } setBottomRightRadius(const LengthSize & radius)269 void setBottomRightRadius(const LengthSize& radius) { m_bottomRightRadius = radius; } setBottomLeftRadius(const LengthSize & 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 type()276 virtual Type type() const OVERRIDE { return BasicShapeInsetType; } 277 private: BasicShapeInset()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