예제 #1
0
bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* object, const FloatRect& objectBoundingBox,
        const FloatRect& repaintRect, GraphicsContext* context)
{
    bool missingClipperData = !m_clipper.contains(object);
    if (missingClipperData)
        m_clipper.set(object, new ClipperData);

    bool shouldCreateClipData = false;
    AffineTransform animatedLocalTransform = static_cast<SVGClipPathElement*>(node())->animatedLocalTransform();
    ClipperData* clipperData = m_clipper.get(object);
    if (!clipperData->clipMaskImage) {
        if (pathOnlyClipping(context, animatedLocalTransform, objectBoundingBox))
            return true;
        shouldCreateClipData = true;
    }

    AffineTransform absoluteTransform;
    SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransform);

    if (shouldCreateClipData && !repaintRect.isEmpty()) {
        if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, clipperData->clipMaskImage, ColorSpaceDeviceRGB, Unaccelerated))
            return false;

        GraphicsContext* maskContext = clipperData->clipMaskImage->context();
        ASSERT(maskContext);

        maskContext->concatCTM(animatedLocalTransform);

        // clipPath can also be clipped by another clipPath.
        SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
        RenderSVGResourceClipper* clipper;
        bool succeeded;
        if (resources && (clipper = resources->clipper())) {
            GraphicsContextStateSaver stateSaver(*maskContext);

            if (!clipper->applyClippingToContext(this, objectBoundingBox, repaintRect, maskContext))
                return false;

            succeeded = drawContentIntoMaskImage(clipperData, objectBoundingBox);
            // The context restore applies the clipping on non-CG platforms.
        } else
            succeeded = drawContentIntoMaskImage(clipperData, objectBoundingBox);

        if (!succeeded)
            clipperData->clipMaskImage.clear();
    }

    if (!clipperData->clipMaskImage)
        return false;

    SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, clipperData->clipMaskImage, missingClipperData);
    return true;
}
예제 #2
0
bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* object, const FloatRect& objectBoundingBox,
                                                      const FloatRect& repaintRect, GraphicsContext* context)
{
    if (!m_clipper.contains(object))
        m_clipper.set(object, new ClipperData);

    bool shouldCreateClipData = false;
    ClipperData* clipperData = m_clipper.get(object);
    if (!clipperData->clipMaskImage) {
        if (pathOnlyClipping(context, objectBoundingBox))
            return true;
        shouldCreateClipData = true;
    }

    AffineTransform absoluteTransform;
    SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform);

    FloatRect absoluteTargetRect = absoluteTransform.mapRect(repaintRect);
    FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRectForRenderer(object, absoluteTargetRect);

    if (shouldCreateClipData && !clampedAbsoluteTargetRect.isEmpty()) {
        if (!SVGImageBufferTools::createImageBuffer(absoluteTargetRect, clampedAbsoluteTargetRect, clipperData->clipMaskImage, ColorSpaceDeviceRGB))
            return false;

        GraphicsContext* maskContext = clipperData->clipMaskImage->context();
        ASSERT(maskContext);

        // The save/restore pair is needed for clipToImageBuffer - it doesn't work without it on non-Cg platforms.
        maskContext->save();
        maskContext->translate(-clampedAbsoluteTargetRect.x(), -clampedAbsoluteTargetRect.y());
        maskContext->concatCTM(absoluteTransform);

        // clipPath can also be clipped by another clipPath.
        if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this)) {
            if (RenderSVGResourceClipper* clipper = resources->clipper()) {
                if (!clipper->applyClippingToContext(this, objectBoundingBox, repaintRect, maskContext)) {
                    maskContext->restore();
                    return false;
                }
            }
        }

        drawContentIntoMaskImage(clipperData, objectBoundingBox);
        maskContext->restore();
    }

    if (!clipperData->clipMaskImage)
        return false;

    SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, clampedAbsoluteTargetRect, clipperData->clipMaskImage);
    return true;
}
bool RenderSVGResourceClipper::applyClippingToContext(RenderElement& renderer, const FloatRect& objectBoundingBox, const FloatRect& repaintRect, GraphicsContext& context)
{
    ClipperMaskImage& clipperMaskImage = addRendererToClipper(renderer);
    bool shouldCreateClipperMaskImage = !clipperMaskImage;

    AffineTransform animatedLocalTransform = clipPathElement().animatedLocalTransform();

    if (shouldCreateClipperMaskImage && pathOnlyClipping(context, animatedLocalTransform, objectBoundingBox))
        return true;

    AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);

    if (shouldCreateClipperMaskImage && !repaintRect.isEmpty()) {
        // FIXME (149469): This image buffer should not be unconditionally unaccelerated. Making it match the context breaks nested clipping, though.
        clipperMaskImage = SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, ColorSpaceSRGB, Unaccelerated);
        if (!clipperMaskImage)
            return false;

        GraphicsContext& maskContext = clipperMaskImage->context();
        maskContext.concatCTM(animatedLocalTransform);

        // clipPath can also be clipped by another clipPath.
        auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*this);
        RenderSVGResourceClipper* clipper;
        bool succeeded;
        if (resources && (clipper = resources->clipper())) {
            GraphicsContextStateSaver stateSaver(maskContext);

            if (!clipper->applyClippingToContext(*this, objectBoundingBox, repaintRect, maskContext))
                return false;

            succeeded = drawContentIntoMaskImage(clipperMaskImage, objectBoundingBox);
            // The context restore applies the clipping on non-CG platforms.
        } else
            succeeded = drawContentIntoMaskImage(clipperMaskImage, objectBoundingBox);

        if (!succeeded)
            clipperMaskImage.reset();
    }

    if (!clipperMaskImage)
        return false;

    SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, clipperMaskImage, shouldCreateClipperMaskImage);
    return true;
}