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(); }
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); }
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); }
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); }
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; }