void RenderSVGShape::layout() { LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout()); SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); bool updateCachedBoundariesInParents = false; bool needsShapeUpdate = m_needsShapeUpdate; if (needsShapeUpdate || m_needsBoundariesUpdate) { setIsPaintingFallback(false); m_path.clear(); createShape(); m_needsShapeUpdate = false; updateCachedBoundariesInParents = true; } if (m_needsTransformUpdate) { m_localTransform = element->animatedLocalTransform(); m_needsTransformUpdate = false; updateCachedBoundariesInParents = true; } // Invalidate all resources of this client if our layout changed. if (everHadLayout() && selfNeedsLayout()) { SVGResourcesCache::clientLayoutChanged(this); m_markerLayoutInfo.clear(); } // At this point LayoutRepainter already grabbed the old bounds, // recalculate them now so repaintAfterLayout() uses the new bounds. if (needsShapeUpdate || m_needsBoundariesUpdate) { updateCachedBoundaries(); m_needsBoundariesUpdate = false; } // If our bounds changed, notify the parents. if (updateCachedBoundariesInParents) RenderSVGModelObject::setNeedsBoundariesUpdate(); repainter.repaintAfterLayout(); setNeedsLayout(false); }
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); } }