1a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)/*
2a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
3a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) *
4a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
5a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * modification, are permitted provided that the following conditions
6a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * are met:
7a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) *
8a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * 1. Redistributions of source code must retain the above
9a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) *    copyright notice, this list of conditions and the following
10a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) *    disclaimer.
11a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above
12a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) *    copyright notice, this list of conditions and the following
13a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) *    disclaimer in the documentation and/or other materials
14a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) *    provided with the distribution.
15a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) *
16a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
27a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * OF THE POSSIBILITY OF SUCH DAMAGE.
28a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) */
29a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
30a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "config.h"
31a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/geometry/FloatRoundedRect.h"
32a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
33a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include <algorithm>
34a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
35a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)namespace WebCore {
36a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
37a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)FloatRoundedRect::FloatRoundedRect(float x, float y, float width, float height)
38a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    : m_rect(x, y, width, height)
39a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
40a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
41a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
42a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)FloatRoundedRect::FloatRoundedRect(const FloatRect& rect, const Radii& radii)
43a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    : m_rect(rect)
44a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    , m_radii(radii)
45a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
46a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
47a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
48a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)FloatRoundedRect::FloatRoundedRect(const FloatRect& rect, const FloatSize& topLeft, const FloatSize& topRight, const FloatSize& bottomLeft, const FloatSize& bottomRight)
49a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    : m_rect(rect)
50a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    , m_radii(topLeft, topRight, bottomLeft, bottomRight)
51a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
52a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
53a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
54a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)bool FloatRoundedRect::Radii::isZero() const
55a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
56a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    return m_topLeft.isZero() && m_topRight.isZero() && m_bottomLeft.isZero() && m_bottomRight.isZero();
57a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
58a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
59a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void FloatRoundedRect::Radii::scale(float factor)
60a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
61a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (factor == 1)
62a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return;
63a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
64a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    // If either radius on a corner becomes zero, reset both radii on that corner.
65a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    m_topLeft.scale(factor);
66a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (!m_topLeft.width() || !m_topLeft.height())
67a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_topLeft = FloatSize();
68a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    m_topRight.scale(factor);
69a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (!m_topRight.width() || !m_topRight.height())
70a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_topRight = FloatSize();
71a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    m_bottomLeft.scale(factor);
72a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (!m_bottomLeft.width() || !m_bottomLeft.height())
73a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_bottomLeft = FloatSize();
74a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    m_bottomRight.scale(factor);
75a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (!m_bottomRight.width() || !m_bottomRight.height())
76a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_bottomRight = FloatSize();
77a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
78a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
79a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
80a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void FloatRoundedRect::Radii::expand(float topWidth, float bottomWidth, float leftWidth, float rightWidth)
81a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
82a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (m_topLeft.width() > 0 && m_topLeft.height() > 0) {
83a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_topLeft.setWidth(std::max<float>(0, m_topLeft.width() + leftWidth));
84a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_topLeft.setHeight(std::max<float>(0, m_topLeft.height() + topWidth));
85a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
86a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (m_topRight.width() > 0 && m_topRight.height() > 0) {
87a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_topRight.setWidth(std::max<float>(0, m_topRight.width() + rightWidth));
88a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_topRight.setHeight(std::max<float>(0, m_topRight.height() + topWidth));
89a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
90a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (m_bottomLeft.width() > 0 && m_bottomLeft.height() > 0) {
91a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_bottomLeft.setWidth(std::max<float>(0, m_bottomLeft.width() + leftWidth));
92a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_bottomLeft.setHeight(std::max<float>(0, m_bottomLeft.height() + bottomWidth));
93a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
94a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (m_bottomRight.width() > 0 && m_bottomRight.height() > 0) {
95a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_bottomRight.setWidth(std::max<float>(0, m_bottomRight.width() + rightWidth));
96a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_bottomRight.setHeight(std::max<float>(0, m_bottomRight.height() + bottomWidth));
97a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
98a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
99a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
100a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static inline float cornerRectIntercept(float y, const FloatRect& cornerRect)
101a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
102a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    ASSERT(cornerRect.height() > 0);
103a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    return cornerRect.width() * sqrt(1 - (y * y) / (cornerRect.height() * cornerRect.height()));
104a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
105a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
106a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)bool FloatRoundedRect::xInterceptsAtY(float y, float& minXIntercept, float& maxXIntercept) const
107a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
108e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    if (y < rect().y() || y >  rect().maxY())
109a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return false;
110a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
111e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    if (!isRounded()) {
112e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        minXIntercept = rect().x();
113e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        maxXIntercept = rect().maxX();
114e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        return true;
115e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    }
116e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)
117a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    const FloatRect& topLeftRect = topLeftCorner();
118a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    const FloatRect& bottomLeftRect = bottomLeftCorner();
119a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
120e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    if (!topLeftRect.isEmpty() && y >= topLeftRect.y() && y < topLeftRect.maxY())
121a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        minXIntercept = topLeftRect.maxX() - cornerRectIntercept(topLeftRect.maxY() - y, topLeftRect);
122e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    else if (!bottomLeftRect.isEmpty() && y >= bottomLeftRect.y() && y <= bottomLeftRect.maxY())
123a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        minXIntercept =  bottomLeftRect.maxX() - cornerRectIntercept(y - bottomLeftRect.y(), bottomLeftRect);
124a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    else
125a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        minXIntercept = m_rect.x();
126a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
127a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    const FloatRect& topRightRect = topRightCorner();
128a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    const FloatRect& bottomRightRect = bottomRightCorner();
129a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
130e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    if (!topRightRect.isEmpty() && y >= topRightRect.y() && y <= topRightRect.maxY())
131a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        maxXIntercept = topRightRect.x() + cornerRectIntercept(topRightRect.maxY() - y, topRightRect);
132e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    else if (!bottomRightRect.isEmpty() && y >= bottomRightRect.y() && y <= bottomRightRect.maxY())
133a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        maxXIntercept = bottomRightRect.x() + cornerRectIntercept(y - bottomRightRect.y(), bottomRightRect);
134a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    else
135a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        maxXIntercept = m_rect.maxX();
136a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
137a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    return true;
138a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
139a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
140a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)} // namespace WebCore
141