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