| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2003, 2006, 2009 Apple Inc. All rights reserved. | |
| 3 * Copyright (C) 2010 Google Inc. All rights reserved. | |
| 4 * Copyright (C) 2013 Xidorn Quan (quanxunzhen@gmail.com) | |
| 5 * | |
| 6 * Redistribution and use in source and binary forms, with or without | |
| 7 * modification, are permitted provided that the following conditions | |
| 8 * are met: | |
| 9 * | |
| 10 * 1. Redistributions of source code must retain the above copyright | |
| 11 * notice, this list of conditions and the following disclaimer. | |
| 12 * 2. Redistributions in binary form must reproduce the above copyright | |
| 13 * notice, this list of conditions and the following disclaimer in the | |
| 14 * documentation and/or other materials provided with the distribution. | |
| 15 * | |
| 16 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | |
| 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| 19 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | |
| 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
| 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 26 */ | |
| 27 | |
| 28 #include "config.h" | |
| 29 #include "platform/geometry/RoundedRect.h" | |
| 30 | |
| 31 #include "wtf/Assertions.h" | |
| 32 #include <algorithm> | |
| 33 | |
| 34 namespace blink { | |
| 35 | |
| 36 bool RoundedRect::Radii::isZero() const | |
| 37 { | |
| 38 return m_topLeft.isZero() && m_topRight.isZero() && m_bottomLeft.isZero() &&
m_bottomRight.isZero(); | |
| 39 } | |
| 40 | |
| 41 void RoundedRect::Radii::scale(float factor) | |
| 42 { | |
| 43 if (factor == 1) | |
| 44 return; | |
| 45 | |
| 46 // If either radius on a corner becomes zero, reset both radii on that corne
r. | |
| 47 m_topLeft.scale(factor); | |
| 48 if (!m_topLeft.width() || !m_topLeft.height()) | |
| 49 m_topLeft = IntSize(); | |
| 50 m_topRight.scale(factor); | |
| 51 if (!m_topRight.width() || !m_topRight.height()) | |
| 52 m_topRight = IntSize(); | |
| 53 m_bottomLeft.scale(factor); | |
| 54 if (!m_bottomLeft.width() || !m_bottomLeft.height()) | |
| 55 m_bottomLeft = IntSize(); | |
| 56 m_bottomRight.scale(factor); | |
| 57 if (!m_bottomRight.width() || !m_bottomRight.height()) | |
| 58 m_bottomRight = IntSize(); | |
| 59 | |
| 60 } | |
| 61 | |
| 62 void RoundedRect::Radii::expand(int topWidth, int bottomWidth, int leftWidth, in
t rightWidth) | |
| 63 { | |
| 64 if (m_topLeft.width() > 0 && m_topLeft.height() > 0) { | |
| 65 m_topLeft.setWidth(std::max<int>(0, m_topLeft.width() + leftWidth)); | |
| 66 m_topLeft.setHeight(std::max<int>(0, m_topLeft.height() + topWidth)); | |
| 67 } | |
| 68 if (m_topRight.width() > 0 && m_topRight.height() > 0) { | |
| 69 m_topRight.setWidth(std::max<int>(0, m_topRight.width() + rightWidth)); | |
| 70 m_topRight.setHeight(std::max<int>(0, m_topRight.height() + topWidth)); | |
| 71 } | |
| 72 if (m_bottomLeft.width() > 0 && m_bottomLeft.height() > 0) { | |
| 73 m_bottomLeft.setWidth(std::max<int>(0, m_bottomLeft.width() + leftWidth)
); | |
| 74 m_bottomLeft.setHeight(std::max<int>(0, m_bottomLeft.height() + bottomWi
dth)); | |
| 75 } | |
| 76 if (m_bottomRight.width() > 0 && m_bottomRight.height() > 0) { | |
| 77 m_bottomRight.setWidth(std::max<int>(0, m_bottomRight.width() + rightWid
th)); | |
| 78 m_bottomRight.setHeight(std::max<int>(0, m_bottomRight.height() + bottom
Width)); | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 void RoundedRect::inflateWithRadii(int size) | |
| 83 { | |
| 84 IntRect old = m_rect; | |
| 85 | |
| 86 m_rect.inflate(size); | |
| 87 // Considering the inflation factor of shorter size to scale the radii seems
appropriate here | |
| 88 float factor; | |
| 89 if (m_rect.width() < m_rect.height()) | |
| 90 factor = old.width() ? (float)m_rect.width() / old.width() : int(0); | |
| 91 else | |
| 92 factor = old.height() ? (float)m_rect.height() / old.height() : int(0); | |
| 93 | |
| 94 m_radii.scale(factor); | |
| 95 } | |
| 96 | |
| 97 void RoundedRect::Radii::includeLogicalEdges(const RoundedRect::Radii& edges, bo
ol isHorizontal, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) | |
| 98 { | |
| 99 if (includeLogicalLeftEdge) { | |
| 100 if (isHorizontal) | |
| 101 m_bottomLeft = edges.bottomLeft(); | |
| 102 else | |
| 103 m_topRight = edges.topRight(); | |
| 104 m_topLeft = edges.topLeft(); | |
| 105 } | |
| 106 | |
| 107 if (includeLogicalRightEdge) { | |
| 108 if (isHorizontal) | |
| 109 m_topRight = edges.topRight(); | |
| 110 else | |
| 111 m_bottomLeft = edges.bottomLeft(); | |
| 112 m_bottomRight = edges.bottomRight(); | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 void RoundedRect::Radii::excludeLogicalEdges(bool isHorizontal, bool excludeLogi
calLeftEdge, bool excludeLogicalRightEdge) | |
| 117 { | |
| 118 if (excludeLogicalLeftEdge) { | |
| 119 if (isHorizontal) | |
| 120 m_bottomLeft = IntSize(); | |
| 121 else | |
| 122 m_topRight = IntSize(); | |
| 123 m_topLeft = IntSize(); | |
| 124 } | |
| 125 | |
| 126 if (excludeLogicalRightEdge) { | |
| 127 if (isHorizontal) | |
| 128 m_topRight = IntSize(); | |
| 129 else | |
| 130 m_bottomLeft = IntSize(); | |
| 131 m_bottomRight = IntSize(); | |
| 132 } | |
| 133 } | |
| 134 | |
| 135 RoundedRect::RoundedRect(int x, int y, int width, int height) | |
| 136 : m_rect(x, y, width, height) | |
| 137 { | |
| 138 } | |
| 139 | |
| 140 RoundedRect::RoundedRect(const IntRect& rect, const Radii& radii) | |
| 141 : m_rect(rect) | |
| 142 , m_radii(radii) | |
| 143 { | |
| 144 } | |
| 145 | |
| 146 RoundedRect::RoundedRect(const IntRect& rect, const IntSize& topLeft, const IntS
ize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight) | |
| 147 : m_rect(rect) | |
| 148 , m_radii(topLeft, topRight, bottomLeft, bottomRight) | |
| 149 { | |
| 150 } | |
| 151 | |
| 152 IntRect RoundedRect::radiusCenterRect() const | |
| 153 { | |
| 154 ASSERT(isRenderable()); | |
| 155 int minX = m_rect.x() + std::max(m_radii.topLeft().width(), m_radii.bottomLe
ft().width()); | |
| 156 int minY = m_rect.y() + std::max(m_radii.topLeft().height(), m_radii.topRigh
t().height()); | |
| 157 int maxX = m_rect.maxX() - std::max(m_radii.topRight().width(), m_radii.bott
omRight().width()); | |
| 158 int maxY = m_rect.maxY() - std::max(m_radii.bottomLeft().height(), m_radii.b
ottomRight().height()); | |
| 159 return IntRect(minX, minY, maxX - minX, maxY - minY); | |
| 160 } | |
| 161 | |
| 162 void RoundedRect::includeLogicalEdges(const Radii& edges, bool isHorizontal, boo
l includeLogicalLeftEdge, bool includeLogicalRightEdge) | |
| 163 { | |
| 164 m_radii.includeLogicalEdges(edges, isHorizontal, includeLogicalLeftEdge, inc
ludeLogicalRightEdge); | |
| 165 } | |
| 166 | |
| 167 void RoundedRect::excludeLogicalEdges(bool isHorizontal, bool excludeLogicalLeft
Edge, bool excludeLogicalRightEdge) | |
| 168 { | |
| 169 m_radii.excludeLogicalEdges(isHorizontal, excludeLogicalLeftEdge, excludeLog
icalRightEdge); | |
| 170 } | |
| 171 | |
| 172 bool RoundedRect::isRenderable() const | |
| 173 { | |
| 174 return m_radii.topLeft().width() + m_radii.topRight().width() <= m_rect.widt
h() | |
| 175 && m_radii.bottomLeft().width() + m_radii.bottomRight().width() <= m_rec
t.width() | |
| 176 && m_radii.topLeft().height() + m_radii.bottomLeft().height() <= m_rect.
height() | |
| 177 && m_radii.topRight().height() + m_radii.bottomRight().height() <= m_rec
t.height(); | |
| 178 } | |
| 179 | |
| 180 void RoundedRect::adjustRadii() | |
| 181 { | |
| 182 int maxRadiusWidth = std::max(m_radii.topLeft().width() + m_radii.topRight()
.width(), m_radii.bottomLeft().width() + m_radii.bottomRight().width()); | |
| 183 int maxRadiusHeight = std::max(m_radii.topLeft().height() + m_radii.bottomLe
ft().height(), m_radii.topRight().height() + m_radii.bottomRight().height()); | |
| 184 | |
| 185 if (maxRadiusWidth <= 0 || maxRadiusHeight <= 0) { | |
| 186 m_radii.scale(0.0f); | |
| 187 return; | |
| 188 } | |
| 189 float widthRatio = static_cast<float>(m_rect.width()) / maxRadiusWidth; | |
| 190 float heightRatio = static_cast<float>(m_rect.height()) / maxRadiusHeight; | |
| 191 m_radii.scale(widthRatio < heightRatio ? widthRatio : heightRatio); | |
| 192 } | |
| 193 | |
| 194 bool RoundedRect::intersectsQuad(const FloatQuad& quad) const | |
| 195 { | |
| 196 FloatRect rect(m_rect); | |
| 197 if (!quad.intersectsRect(rect)) | |
| 198 return false; | |
| 199 | |
| 200 const IntSize& topLeft = m_radii.topLeft(); | |
| 201 if (!topLeft.isEmpty()) { | |
| 202 FloatRect rect(m_rect.x(), m_rect.y(), topLeft.width(), topLeft.height()
); | |
| 203 if (quad.intersectsRect(rect)) { | |
| 204 FloatPoint center(m_rect.x() + topLeft.width(), m_rect.y() + topLeft
.height()); | |
| 205 FloatSize size(topLeft.width(), topLeft.height()); | |
| 206 if (!quad.intersectsEllipse(center, size)) | |
| 207 return false; | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 const IntSize& topRight = m_radii.topRight(); | |
| 212 if (!topRight.isEmpty()) { | |
| 213 FloatRect rect(m_rect.maxX() - topRight.width(), m_rect.y(), topRight.wi
dth(), topRight.height()); | |
| 214 if (quad.intersectsRect(rect)) { | |
| 215 FloatPoint center(m_rect.maxX() - topRight.width(), m_rect.y() + top
Right.height()); | |
| 216 FloatSize size(topRight.width(), topRight.height()); | |
| 217 if (!quad.intersectsEllipse(center, size)) | |
| 218 return false; | |
| 219 } | |
| 220 } | |
| 221 | |
| 222 const IntSize& bottomLeft = m_radii.bottomLeft(); | |
| 223 if (!bottomLeft.isEmpty()) { | |
| 224 FloatRect rect(m_rect.x(), m_rect.maxY() - bottomLeft.height(), bottomLe
ft.width(), bottomLeft.height()); | |
| 225 if (quad.intersectsRect(rect)) { | |
| 226 FloatPoint center(m_rect.x() + bottomLeft.width(), m_rect.maxY() - b
ottomLeft.height()); | |
| 227 FloatSize size(bottomLeft.width(), bottomLeft.height()); | |
| 228 if (!quad.intersectsEllipse(center, size)) | |
| 229 return false; | |
| 230 } | |
| 231 } | |
| 232 | |
| 233 const IntSize& bottomRight = m_radii.bottomRight(); | |
| 234 if (!bottomRight.isEmpty()) { | |
| 235 FloatRect rect(m_rect.maxX() - bottomRight.width(), m_rect.maxY() - bott
omRight.height(), bottomRight.width(), bottomRight.height()); | |
| 236 if (quad.intersectsRect(rect)) { | |
| 237 FloatPoint center(m_rect.maxX() - bottomRight.width(), m_rect.maxY()
- bottomRight.height()); | |
| 238 FloatSize size(bottomRight.width(), bottomRight.height()); | |
| 239 if (!quad.intersectsEllipse(center, size)) | |
| 240 return false; | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 return true; | |
| 245 } | |
| 246 | |
| 247 } // namespace blink | |
| OLD | NEW |