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