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 }
void SkSVGDevice::AutoElement::addClipResources(const SkDraw& draw, Resources* resources) { SkASSERT(!draw.fClipStack->isWideOpen()); SkPath clipPath; (void) draw.fClipStack->asPath(&clipPath); SkString clipID = fResourceBucket->addClip(); const char* clipRule = clipPath.getFillType() == SkPath::kEvenOdd_FillType ? "evenodd" : "nonzero"; { // clipPath is in device space, but since we're only pushing transform attributes // to the leaf nodes, so are all our elements => SVG userSpaceOnUse == device space. AutoElement clipPathElement("clipPath", fWriter); clipPathElement.addAttribute("id", clipID); SkRect clipRect = SkRect::MakeEmpty(); if (clipPath.isEmpty() || clipPath.isRect(&clipRect)) { AutoElement rectElement("rect", fWriter); rectElement.addRectAttributes(clipRect); rectElement.addAttribute("clip-rule", clipRule); } else { AutoElement pathElement("path", fWriter); pathElement.addPathAttributes(clipPath); pathElement.addAttribute("clip-rule", clipRule); } } resources->fClip.printf("url(#%s)", clipID.c_str()); }
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(); // Fallback to RenderSVGShape if rect has rounded corners or a non-scaling stroke. if (rectElement().hasAttribute(SVGNames::rxAttr) || rectElement().hasAttribute(SVGNames::ryAttr) || hasNonScalingStroke()) { RenderSVGShape::updateShapeFromElement(); m_usePathFallback = true; return; } else m_usePathFallback = false; SVGLengthContext lengthContext(&rectElement()); FloatSize boundingBoxSize(rectElement().width().value(lengthContext), rectElement().height().value(lengthContext)); if (boundingBoxSize.isEmpty()) return; m_fillBoundingBox = FloatRect(FloatPoint(rectElement().x().value(lengthContext), rectElement().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 }