Esempio n. 1
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
}
Esempio n. 2
0
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());
}
Esempio n. 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();

    // 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
}