Esempio n. 1
0
void SVGElement::updateRelativeLengthsInformation(bool clientHasRelativeLengths, SVGElement* clientElement)
{
    // If we're not yet in a document, this function will be called again from insertedInto(). Do nothing now.
    if (!inDocument())
        return;

    // An element wants to notify us that its own relative lengths state changed.
    // Register it in the relative length map, and register us in the parent relative length map.
    // Register the parent in the grandparents map, etc. Repeat procedure until the root of the SVG tree.
    for (ContainerNode* currentNode = this; currentNode && currentNode->isSVGElement(); currentNode = currentNode->parentNode()) {
        SVGElement* currentElement = toSVGElement(currentNode);
        ASSERT(!currentElement->m_inRelativeLengthClientsInvalidation);

        bool hadRelativeLengths = currentElement->hasRelativeLengths();
        if (clientHasRelativeLengths)
            currentElement->m_elementsWithRelativeLengths.add(clientElement);
        else
            currentElement->m_elementsWithRelativeLengths.remove(clientElement);

        // If the relative length state hasn't changed, we can stop propagating the notfication.
        if (hadRelativeLengths == currentElement->hasRelativeLengths())
            break;

        clientElement = currentElement;
        clientHasRelativeLengths = clientElement->hasRelativeLengths();
    }
}
Esempio n. 2
0
PassRefPtr<SkImageFilter> FEImage::createImageFilterForRenderer(RenderObject* renderer, SkiaImageFilterBuilder* builder)
{
    FloatRect dstRect = filterPrimitiveSubregion();

    AffineTransform transform;
    SVGElement* contextNode = toSVGElement(renderer->node());

    if (contextNode->hasRelativeLengths()) {
        SVGLengthContext lengthContext(contextNode);
        FloatSize viewportSize;

        // If we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport.
        // Build up a transformation that maps from the viewport space to the filter primitive subregion.
        if (lengthContext.determineViewport(viewportSize))
            transform = makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), dstRect);
    } else {
        transform.translate(dstRect.x(), dstRect.y());
    }

    GraphicsContext* context = builder->context();
    if (!context)
        return adoptRef(SkBitmapSource::Create(SkBitmap()));
    AffineTransform contentTransformation;
    context->save();
    context->beginRecording(FloatRect(FloatPoint(), dstRect.size()));
    context->concatCTM(transform);
    SVGRenderingContext::renderSubtree(context, renderer, contentTransformation);
    RefPtr<DisplayList> displayList = context->endRecording();
    context->restore();
    RefPtr<SkImageFilter> result = adoptRef(SkPictureImageFilter::Create(displayList->picture(), dstRect));
    return result.release();
}
Esempio n. 3
0
sk_sp<SkImageFilter> FEImage::createImageFilterForLayoutObject(const LayoutObject& layoutObject)
{
    FloatRect dstRect = filterPrimitiveSubregion();

    AffineTransform transform;
    SVGElement* contextNode = toSVGElement(layoutObject.node());

    if (contextNode->hasRelativeLengths()) {
        SVGLengthContext lengthContext(contextNode);
        FloatSize viewportSize;

        // If we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport.
        // Build up a transformation that maps from the viewport space to the filter primitive subregion.
        if (lengthContext.determineViewport(viewportSize))
            transform = makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), dstRect);
    } else {
        transform.translate(dstRect.x(), dstRect.y());
    }

    SkPictureBuilder filterPicture(dstRect);
    {
        TransformRecorder transformRecorder(filterPicture.context(), layoutObject, transform);
        SVGPaintContext::paintSubtree(filterPicture.context(), &layoutObject);
    }

    return SkPictureImageFilter::Make(toSkSp(filterPicture.endRecording()), dstRect);
}
Esempio n. 4
0
void FEImage::applySoftware()
{
    RenderObject* renderer = referencedRenderer();
    if (!m_image && !renderer)
        return;

    ImageBuffer* resultImage = createImageBufferResult();
    if (!resultImage)
        return;

    FloatRect destRect = filter()->absoluteTransform().mapRect(filterPrimitiveSubregion());

    FloatRect srcRect;
    if (renderer)
        srcRect = filter()->absoluteTransform().mapRect(renderer->repaintRectInLocalCoordinates());
    else {
        srcRect = FloatRect(FloatPoint(), m_image->size());
        m_preserveAspectRatio.transformRect(destRect, srcRect);
    }

    IntPoint paintLocation = absolutePaintRect().location();
    destRect.move(-paintLocation.x(), -paintLocation.y());

    // FEImage results are always in ColorSpaceDeviceRGB
    setResultColorSpace(ColorSpaceDeviceRGB);

    if (renderer) {
        SVGElement* contextNode = toSVGElement(renderer->node());
        if (contextNode->hasRelativeLengths()) {
            SVGLengthContext lengthContext(contextNode);
            float width = 0;
            float height = 0;

            // If we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport.
            // Build up a transformation that maps from the viewport space to the filter primitive subregion.
            if (lengthContext.determineViewport(width, height))
                resultImage->context()->concatCTM(makeMapBetweenRects(FloatRect(0, 0, width, height), destRect));
        } else {
            const AffineTransform& absoluteTransform = filter()->absoluteTransform();
            resultImage->context()->concatCTM(absoluteTransform);
        }

        AffineTransform contentTransformation;
        SVGRenderingContext::renderSubtree(resultImage->context(), renderer, contentTransformation);
        return;
    }

    resultImage->context()->drawImage(m_image.get(), destRect, srcRect);
}
Esempio n. 5
0
bool SVGUseElement::selfHasRelativeLengths() const
{
    if (x().isRelative()
     || y().isRelative()
     || width().isRelative()
     || height().isRelative())
        return true;

    if (!m_targetElementInstance)
        return false;

    SVGElement* element = m_targetElementInstance->correspondingElement();
    if (!element)
        return false;

    return element->hasRelativeLengths();
}
Esempio n. 6
0
void FEImage::applySoftware()
{
    RenderObject* renderer = referencedRenderer();
    if (!m_image && !renderer)
        return;

    ImageBuffer* resultImage = createImageBufferResult();
    if (!resultImage)
        return;
    IntPoint paintLocation = absolutePaintRect().location();
    resultImage->context()->translate(-paintLocation.x(), -paintLocation.y());

    // FEImage results are always in ColorSpaceDeviceRGB
    setResultColorSpace(ColorSpaceDeviceRGB);

    FloatRect destRect = filter()->mapLocalRectToAbsoluteRect(filterPrimitiveSubregion());
    FloatRect srcRect;

    if (!renderer) {
        srcRect = FloatRect(FloatPoint(), m_image->size());
        m_preserveAspectRatio->transformRect(destRect, srcRect);

        resultImage->context()->drawImage(m_image.get(), destRect, srcRect);
        return;
    }

    SVGElement* contextNode = toSVGElement(renderer->node());
    if (contextNode->hasRelativeLengths()) {
        // FIXME: This fixes relative lengths but breaks non-relative ones (see crbug/260709).
        SVGLengthContext lengthContext(contextNode);
        FloatSize viewportSize;

        // If we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport.
        // Build up a transformation that maps from the viewport space to the filter primitive subregion.
        if (lengthContext.determineViewport(viewportSize))
            resultImage->context()->concatCTM(makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), destRect));
    } else {
        resultImage->context()->translate(destRect.x(), destRect.y());
        resultImage->context()->concatCTM(filter()->absoluteTransform());
    }

    AffineTransform contentTransformation;
    SVGRenderingContext::renderSubtree(resultImage->context(), renderer, contentTransformation);
}
Esempio n. 7
0
FloatRect FEImage::determineAbsolutePaintRect(const FloatRect& originalRequestedRect)
{
    RenderObject* renderer = referencedRenderer();
    if (!m_image && !renderer)
        return FloatRect();

    FloatRect requestedRect = originalRequestedRect;
    if (clipsToBounds())
        requestedRect.intersect(maxEffectRect());

    FloatRect destRect = filter()->mapLocalRectToAbsoluteRect(filterPrimitiveSubregion());
    FloatRect srcRect;
    if (renderer) {
        srcRect = getRendererRepaintRect(renderer);
        SVGElement* contextNode = toSVGElement(renderer->node());

        if (contextNode->hasRelativeLengths()) {
            // FIXME: This fixes relative lengths but breaks non-relative ones (see crbug/260709).
            SVGLengthContext lengthContext(contextNode);
            FloatSize viewportSize;
            if (lengthContext.determineViewport(viewportSize)) {
                srcRect = makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), destRect).mapRect(srcRect);
            }
        } else {
            srcRect = filter()->mapLocalRectToAbsoluteRect(srcRect);
            srcRect.move(destRect.x(), destRect.y());
        }
        destRect.intersect(srcRect);
    } else {
        srcRect = FloatRect(FloatPoint(), m_image->size());
        m_preserveAspectRatio->transformRect(destRect, srcRect);
    }

    destRect.intersect(requestedRect);
    addAbsolutePaintRect(destRect);
    return destRect;
}