15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011 University of Szeged 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011 Renata Hodovan <reni@webkit.org> 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * All rights reserved. 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met: 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * documentation and/or other materials provided with the distribution. 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGRect.h" 315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "platform/graphics/GraphicsContext.h" 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 33c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderSVGRect::RenderSVGRect(SVGRectElement* node) 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : RenderSVGShape(node) 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_usePathFallback(false) 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderSVGRect::~RenderSVGRect() 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGRect::updateShapeFromElement() 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Before creating a new object we need to clear the cached bounding box 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // to avoid using garbage. 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_fillBoundingBox = FloatRect(); 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_innerStrokeRect = FloatRect(); 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outerStrokeRect = FloatRect(); 527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_usePathFallback = false; 538abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) SVGRectElement* rect = toSVGRectElement(element()); 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(rect); 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 56521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) SVGLengthContext lengthContext(rect); 5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) FloatSize boundingBoxSize(rect->width()->currentValue()->value(lengthContext), rect->height()->currentValue()->value(lengthContext)); 5807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 59f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) // Spec: "A negative value is an error." 60f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) if (boundingBoxSize.width() < 0 || boundingBoxSize.height() < 0) 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 63f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) // Spec: "A value of zero disables rendering of the element." 64f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) if (!boundingBoxSize.isEmpty()) { 65f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) // Fallback to RenderSVGShape if rect has rounded corners or a non-scaling stroke. 66f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) if (rect->rx()->currentValue()->value(lengthContext) > 0 || rect->ry()->currentValue()->value(lengthContext) > 0 || hasNonScalingStroke()) { 67f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) RenderSVGShape::updateShapeFromElement(); 68f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) m_usePathFallback = true; 69f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) return; 70f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) } 71f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) } 72f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_fillBoundingBox = FloatRect(FloatPoint(rect->x()->currentValue()->value(lengthContext), rect->y()->currentValue()->value(lengthContext)), boundingBoxSize); 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // To decide if the stroke contains a point we create two rects which represent the inner and 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the outer stroke borders. A stroke contains the point, if the point is between them. 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_innerStrokeRect = m_fillBoundingBox; 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outerStrokeRect = m_fillBoundingBox; 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 80197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (style()->svgStyle().hasStroke()) { 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float strokeWidth = this->strokeWidth(); 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_innerStrokeRect.inflate(-strokeWidth / 2); 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_outerStrokeRect.inflate(strokeWidth / 2); 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_strokeBoundingBox = m_outerStrokeRect; 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGRect::fillShape(GraphicsContext* context) const 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_usePathFallback) { 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderSVGShape::fillShape(context); 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) context->fillRect(m_fillBoundingBox); 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGRect::strokeShape(GraphicsContext* context) const 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 101197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (!style()->svgStyle().hasVisibleStroke()) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_usePathFallback) { 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderSVGShape::strokeShape(context); 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) context->strokeRect(m_fillBoundingBox, strokeWidth()); 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderSVGRect::shapeDependentStrokeContains(const FloatPoint& point) 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The optimized contains code below does not support non-smooth strokes so we need 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // to fall back to RenderSVGShape::shapeDependentStrokeContains in these cases. 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_usePathFallback || !hasSmoothStroke()) { 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!hasPath()) 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderSVGShape::updateShapeFromElement(); 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return RenderSVGShape::shapeDependentStrokeContains(point); 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_outerStrokeRect.contains(point, FloatRect::InsideOrOnStroke) && !m_innerStrokeRect.contains(point, FloatRect::InsideButNotOnStroke); 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderSVGRect::shapeDependentFillContains(const FloatPoint& point, const WindRule fillRule) const 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_usePathFallback) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return RenderSVGShape::shapeDependentFillContains(point, fillRule); 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_fillBoundingBox.contains(point.x(), point.y()); 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 133