void LayoutSVGRect::updateStrokeAndFillBoundingBoxes()
{
    SVGLengthContext lengthContext(toSVGRectElement(element()));
    FloatSize boundingBoxSize(
        lengthContext.valueForLength(styleRef().width(), styleRef(), SVGLengthMode::Width),
        lengthContext.valueForLength(styleRef().height(), styleRef(), SVGLengthMode::Height));

    // Spec: "A negative value is an error."
    if (boundingBoxSize.width() < 0 || boundingBoxSize.height() < 0) {
        m_fillBoundingBox = FloatRect();
        m_strokeBoundingBox = FloatRect();
        return;
    }

    if (m_usePathFallback) {
        // Spec: "A value of zero disables rendering of the element." so we can skip
        // the path fallback and rely on the existing bounding box calculation.
        if (!boundingBoxSize.isEmpty()) {
            LayoutSVGShape::updateStrokeAndFillBoundingBoxes();
            return;
        }
        m_usePathFallback = false;
        clearPath();
    }

    m_fillBoundingBox = FloatRect(
        FloatPoint(
            lengthContext.valueForLength(styleRef().svgStyle().x(), styleRef(), SVGLengthMode::Width),
            lengthContext.valueForLength(styleRef().svgStyle().y(), styleRef(), SVGLengthMode::Height)),
        boundingBoxSize);
    m_strokeBoundingBox = m_fillBoundingBox;
    if (style()->svgStyle().hasStroke())
        m_strokeBoundingBox.inflate(strokeWidth() / 2);
}
Exemple #2
0
void RenderSVGRect::updateShapeFromElement()
{
    // Before creating a new object we need to clear the cached bounding box
    // to avoid using garbage.
    m_fillBoundingBox = FloatRect();
    m_innerStrokeRect = FloatRect();
    m_outerStrokeRect = FloatRect();

    SVGLengthContext lengthContext(&rectElement());
    FloatSize boundingBoxSize(lengthContext.valueForLength(style().width(), LengthModeWidth), lengthContext.valueForLength(style().height(), LengthModeHeight));

    // Element is invalid if either dimension is negative.
    if (boundingBoxSize.width() < 0 || boundingBoxSize.height() < 0)
        return;

    // Rendering enabled? Spec: "A value of zero disables rendering of the element."
    if (!boundingBoxSize.isEmpty()) {
        if (rectElement().rx().value(lengthContext) > 0 || rectElement().ry().value(lengthContext) > 0 || hasNonScalingStroke()) {
            // Fall back to RenderSVGShape
            RenderSVGShape::updateShapeFromElement();
            m_usePathFallback = true;
            return;
        }
        m_usePathFallback = false;
    }

    m_fillBoundingBox = FloatRect(FloatPoint(lengthContext.valueForLength(style().svgStyle().x(), LengthModeWidth),
        lengthContext.valueForLength(style().svgStyle().y(), LengthModeHeight)),
        boundingBoxSize);

    // To decide if the stroke contains a point we create two rects which represent the inner and
    // the outer stroke borders. A stroke contains the point, if the point is between them.
    m_innerStrokeRect = m_fillBoundingBox;
    m_outerStrokeRect = m_fillBoundingBox;

    if (style().svgStyle().hasStroke()) {
        float strokeWidth = this->strokeWidth();
        m_innerStrokeRect.inflate(-strokeWidth / 2);
        m_outerStrokeRect.inflate(strokeWidth / 2);
    }

    m_strokeBoundingBox = m_outerStrokeRect;

#if USE(CG)
    // CoreGraphics can inflate the stroke by 1px when drawing a rectangle with antialiasing disabled at non-integer coordinates, we need to compensate.
    if (style().svgStyle().shapeRendering() == SR_CRISPEDGES)
        m_strokeBoundingBox.inflate(1);
#endif
}
Exemple #3
0
void RenderSVGRect::updateShapeFromElement()
{
    // Before creating a new object we need to clear the cached bounding box
    // to avoid using garbage.
    m_fillBoundingBox = FloatRect();
    m_innerStrokeRect = FloatRect();
    m_outerStrokeRect = FloatRect();
    SVGRectElement* rect = static_cast<SVGRectElement*>(node());
    ASSERT(rect);

    // Fallback to RenderSVGShape if rect has rounded corners or a non-scaling stroke.
    if (rect->hasAttribute(SVGNames::rxAttr) || rect->hasAttribute(SVGNames::ryAttr) || hasNonScalingStroke()) {
        RenderSVGShape::updateShapeFromElement();
        m_usePathFallback = true;
        return;
    } else
        m_usePathFallback = false;

    SVGLengthContext lengthContext(rect);
    FloatSize boundingBoxSize(rect->width().value(lengthContext), rect->height().value(lengthContext));
    if (boundingBoxSize.isEmpty())
        return;

    m_fillBoundingBox = FloatRect(FloatPoint(rect->x().value(lengthContext), rect->y().value(lengthContext)), boundingBoxSize);

    // To decide if the stroke contains a point we create two rects which represent the inner and
    // the outer stroke borders. A stroke contains the point, if the point is between them.
    m_innerStrokeRect = m_fillBoundingBox;
    m_outerStrokeRect = m_fillBoundingBox;

    if (style()->svgStyle()->hasStroke()) {
        float strokeWidth = this->strokeWidth();
        m_innerStrokeRect.inflate(-strokeWidth / 2);
        m_outerStrokeRect.inflate(strokeWidth / 2);
    }

    m_strokeBoundingBox = m_outerStrokeRect;

#if USE(CG)
    // CoreGraphics can inflate the stroke by 1px when drawing a rectangle with antialiasing disabled at non-integer coordinates, we need to compensate.
    if (style()->svgStyle()->shapeRendering() == SR_CRISPEDGES)
        m_strokeBoundingBox.inflate(1);
#endif
}
void LayoutSVGRect::updateShapeFromElement()
{
    // Before creating a new object we need to clear the cached bounding box
    // to avoid using garbage.
    m_fillBoundingBox = FloatRect();
    m_strokeBoundingBox = FloatRect();
    m_usePathFallback = false;
    SVGRectElement* rect = toSVGRectElement(element());
    ASSERT(rect);

    SVGLengthContext lengthContext(rect);
    FloatSize boundingBoxSize(
        lengthContext.valueForLength(styleRef().width(), styleRef(), SVGLengthMode::Width),
        lengthContext.valueForLength(styleRef().height(), styleRef(), SVGLengthMode::Height));

    // Spec: "A negative value is an error."
    if (boundingBoxSize.width() < 0 || boundingBoxSize.height() < 0)
        return;

    // Spec: "A value of zero disables rendering of the element."
    if (!boundingBoxSize.isEmpty()) {
        // Fallback to LayoutSVGShape and path-based hit detection if the rect
        // has rounded corners or a non-scaling or non-simple stroke.
        if (lengthContext.valueForLength(styleRef().svgStyle().rx(), styleRef(), SVGLengthMode::Width) > 0
                || lengthContext.valueForLength(styleRef().svgStyle().ry(), styleRef(), SVGLengthMode::Height) > 0
                || hasNonScalingStroke()
                || !definitelyHasSimpleStroke()) {
            LayoutSVGShape::updateShapeFromElement();
            m_usePathFallback = true;
            return;
        }
    }

    m_fillBoundingBox = FloatRect(
                            FloatPoint(
                                lengthContext.valueForLength(styleRef().svgStyle().x(), styleRef(), SVGLengthMode::Width),
                                lengthContext.valueForLength(styleRef().svgStyle().y(), styleRef(), SVGLengthMode::Height)),
                            boundingBoxSize);
    m_strokeBoundingBox = m_fillBoundingBox;
    if (style()->svgStyle().hasStroke())
        m_strokeBoundingBox.inflate(strokeWidth() / 2);
}
void RenderSVGRect::createShape()
{
    // Before creating a new object we need to clear the cached bounding box
    // to avoid using garbage.
    m_boundingBox = FloatRect();
    m_innerStrokeRect = FloatRect();
    m_outerStrokeRect = FloatRect();
    SVGRectElement* rect = static_cast<SVGRectElement*>(node());
    ASSERT(rect);

    bool nonScalingStroke = style()->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE;
    // Fallback to RenderSVGShape if rect has rounded corners.
    if (rect->hasAttribute(SVGNames::rxAttr) || rect->hasAttribute(SVGNames::ryAttr) || nonScalingStroke) {
       RenderSVGShape::createShape();
       setIsPaintingFallback(true);
       return;
    }

    SVGLengthContext lengthContext(rect);
    FloatSize boundingBoxSize(rect->width().value(lengthContext), rect->height().value(lengthContext));
    if (boundingBoxSize.isEmpty())
        return;

    m_boundingBox = FloatRect(FloatPoint(rect->x().value(lengthContext), rect->y().value(lengthContext)), boundingBoxSize);

    // To decide if the stroke contains a point we create two rects which represent the inner and
    // the outer stroke borders. A stroke contains the point, if the point is between them.
    m_innerStrokeRect = m_boundingBox;
    m_outerStrokeRect = m_boundingBox;

    if (style()->svgStyle()->hasStroke()) {
        float strokeWidth = this->strokeWidth();
        m_innerStrokeRect.inflate(-strokeWidth / 2);
        m_outerStrokeRect.inflate(strokeWidth / 2);
    }
}