示例#1
0
SkImageFilter::CropRect FilterEffect::getCropRect() const {
  if (!filterPrimitiveSubregion().isEmpty()) {
    FloatRect rect =
        getFilter()->mapLocalRectToAbsoluteRect(filterPrimitiveSubregion());
    return SkImageFilter::CropRect(rect);
  } else {
    return SkImageFilter::CropRect(SkRect::MakeEmpty(), 0);
  }
}
示例#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();
}
示例#3
0
PassRefPtr<SkImageFilter> FEImage::createImageFilter(SkiaImageFilterBuilder* builder)
{
    RenderObject* renderer = referencedRenderer();
    if (!m_image && !renderer)
        return adoptRef(SkBitmapSource::Create(SkBitmap()));

    setOperatingColorSpace(ColorSpaceDeviceRGB);

    if (renderer)
        return createImageFilterForRenderer(renderer, builder);

    FloatRect srcRect = FloatRect(FloatPoint(), m_image->size());
    FloatRect dstRect = filterPrimitiveSubregion();

    // FIXME: CSS image filters currently do not seem to set filter primitive
    // subregion correctly if unspecified. So default to srcRect size if so.
    if (dstRect.isEmpty())
        dstRect = srcRect;

    m_preserveAspectRatio->transformRect(dstRect, srcRect);

    if (!m_image->nativeImageForCurrentFrame())
        return adoptRef(SkBitmapSource::Create(SkBitmap()));

    RefPtr<SkImageFilter> result = adoptRef(SkBitmapSource::Create(m_image->nativeImageForCurrentFrame()->bitmap(), srcRect, dstRect));
    return result.release();
}
示例#4
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);
}
示例#5
0
void FETurbulence::apply()
{
    if (hasResult())
        return;
    ByteArray* pixelArray = createUnmultipliedImageResult();
    if (!pixelArray)
        return;

    if (absolutePaintRect().isEmpty())
        return;

    PaintingData paintingData(m_seed, roundedIntSize(filterPrimitiveSubregion().size()));
    initPaint(paintingData);

#if ENABLE(PARALLEL_JOBS)

    int optimalThreadNumber = (absolutePaintRect().width() * absolutePaintRect().height()) / s_minimalRectDimension;
    if (optimalThreadNumber > 1) {
        // Initialize parallel jobs
        ParallelJobs<FillRegionParameters> parallelJobs(&WebCore::FETurbulence::fillRegionWorker, optimalThreadNumber);

        // Fill the parameter array
        int i = parallelJobs.numberOfJobs();
        if (i > 1) {
            int startY = 0;
            int stepY = absolutePaintRect().height() / i;
            for (; i > 0; --i) {
                FillRegionParameters& params = parallelJobs.parameter(i-1);
                params.filter = this;
                params.pixelArray = pixelArray;
                params.paintingData = &paintingData;
                params.startY = startY;
                if (i != 1) {
                    params.endY = startY + stepY;
                    startY = startY + stepY;
                } else
                    params.endY = absolutePaintRect().height();
            }

            // Execute parallel jobs
            parallelJobs.execute();

            return;
        }
    }
    // Fallback to sequential mode if there is no room for a new thread or the paint area is too small

#endif // ENABLE(PARALLEL_JOBS)

    fillRegion(pixelArray, paintingData, 0, absolutePaintRect().height());
}
示例#6
0
void FEImage::platformApplySoftware()
{
    RenderObject* renderer = referencedRenderer();
    if (!m_image && !renderer)
        return;

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

    SVGFilter* svgFilter = static_cast<SVGFilter*>(filter());
    FloatRect destRect = svgFilter->absoluteTransform().mapRect(filterPrimitiveSubregion());

    FloatRect srcRect;
    if (renderer)
        srcRect = svgFilter->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) {
        const AffineTransform& absoluteTransform = svgFilter->absoluteTransform();
        resultImage->context()->concatCTM(absoluteTransform);

        SVGElement* contextNode = static_cast<SVGElement*>(renderer->node());
        if (contextNode->isStyled() && static_cast<SVGStyledElement*>(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));
        }

        AffineTransform contentTransformation;
        SVGRenderingContext::renderSubtreeToImageBuffer(resultImage, renderer, contentTransformation);
        return;
    }

    resultImage->context()->drawImage(m_image.get(), ColorSpaceDeviceRGB, destRect, srcRect);
}
示例#7
0
void FETurbulence::applySoftware()
{
    Uint8ClampedArray* pixelArray = createUnmultipliedImageResult();
    if (!pixelArray)
        return;

    if (absolutePaintRect().isEmpty()) {
        pixelArray->zeroFill();
        return;
    }

    PaintingData paintingData(m_seed, roundedIntSize(filterPrimitiveSubregion().size()));
    initPaint(paintingData);

    int optimalThreadNumber = (absolutePaintRect().width() * absolutePaintRect().height()) / s_minimalRectDimension;
    if (optimalThreadNumber > 1) {
        // Initialize parallel jobs
        ParallelJobs<FillRegionParameters> parallelJobs(&WebCore::FETurbulence::fillRegionWorker, optimalThreadNumber);

        // Fill the parameter array
        int i = parallelJobs.numberOfJobs();
        if (i > 1) {
            // Split the job into "stepY"-sized jobs but there a few jobs that need to be slightly larger since
            // stepY * jobs < total size. These extras are handled by the remainder "jobsWithExtra".
            const int stepY = absolutePaintRect().height() / i;
            const int jobsWithExtra = absolutePaintRect().height() % i;

            int startY = 0;
            for (; i > 0; --i) {
                FillRegionParameters& params = parallelJobs.parameter(i-1);
                params.filter = this;
                params.pixelArray = pixelArray;
                params.paintingData = &paintingData;
                params.startY = startY;
                startY += i < jobsWithExtra ? stepY + 1 : stepY;
                params.endY = startY;
                params.baseFrequencyX = m_baseFrequencyX;
                params.baseFrequencyY = m_baseFrequencyY;
            }

            // Execute parallel jobs
            parallelJobs.execute();
            return;
        }
    }

    // Fallback to single threaded mode if there is no room for a new thread or the paint area is too small.
    fillRegion(pixelArray, paintingData, 0, absolutePaintRect().height(), m_baseFrequencyX, m_baseFrequencyY);
}
示例#8
0
void FEImage::determineAbsolutePaintRect()
{
    FloatRect paintRect = filter().absoluteTransform().mapRect(filterPrimitiveSubregion());
    FloatRect srcRect;
    if (m_image) {
        srcRect.setSize(m_image->size());
        m_preserveAspectRatio.transformRect(paintRect, srcRect);
    } else if (RenderElement* renderer = referencedRenderer())
        srcRect = filter().absoluteTransform().mapRect(renderer->repaintRectInLocalCoordinates());

    if (clipsToBounds())
        paintRect.intersect(maxEffectRect());
    else
        paintRect.unite(maxEffectRect());
    setAbsolutePaintRect(enclosingIntRect(paintRect));
}
示例#9
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);
}
示例#10
0
sk_sp<SkImageFilter> FEImage::createImageFilter()
{
    if (auto* layoutObject = referencedLayoutObject())
        return createImageFilterForLayoutObject(*layoutObject);

    sk_sp<SkImage> image = m_image ? toSkSp(m_image->imageForCurrentFrame()) : nullptr;
    if (!image) {
        // "A href reference that is an empty image (zero width or zero height), that fails
        // to download, is non-existent, or that cannot be displayed (e.g. because it is
        // not in a supported image format) fills the filter primitive subregion with
        // transparent black."
        return createTransparentBlack();
    }

    FloatRect srcRect = FloatRect(FloatPoint(), FloatSize(m_image->size()));
    FloatRect dstRect = filterPrimitiveSubregion();

    m_preserveAspectRatio->transformRect(dstRect, srcRect);

    return SkImageSource::Make(std::move(image), srcRect, dstRect, kHigh_SkFilterQuality);
}
示例#11
0
PassRefPtr<SkImageFilter> FEImage::createImageFilter(SkiaImageFilterBuilder* builder)
{
    if (auto* layoutObject = referencedLayoutObject())
        return createImageFilterForLayoutObject(*layoutObject, builder);

    FloatRect dstRect = filterPrimitiveSubregion();

    RefPtr<SkImage> image = m_image ? m_image->imageForCurrentFrame() : nullptr;
    if (!image) {
        // "A href reference that is an empty image (zero width or zero height), that fails
        // to download, is non-existent, or that cannot be displayed (e.g. because it is
        // not in a supported image format) fills the filter primitive subregion with
        // transparent black."
        return adoptRef(SkPictureImageFilter::Create(nullptr, dstRect));
    }

    FloatRect srcRect = FloatRect(FloatPoint(), m_image->size());

    m_preserveAspectRatio->transformRect(dstRect, srcRect);

    return adoptRef(SkImageSource::Create(image.get(), srcRect, dstRect, kHigh_SkFilterQuality));
}
示例#12
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;
}
示例#13
0
FloatRect FilterEffect::absoluteBounds() const {
  FloatRect computedBounds = getFilter()->filterRegion();
  if (!filterPrimitiveSubregion().isEmpty())
    computedBounds.intersect(filterPrimitiveSubregion());
  return getFilter()->mapLocalRectToAbsoluteRect(computedBounds);
}