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