Repository: PixiEditor/PixiEditor
File: src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/FilterNodes/ApplyFilterNode.cs (C#)

Code before:

        using var srgbSurface = Texture.ForProcessing(intermediate.Size, ColorSpace.CreateSrgb());

        srgbSurface.DrawingSurface.Canvas.SaveLayer(_paint);
        srgbSurface.DrawingSurface.Canvas.DrawSurface(intermediate.DrawingSurface, 0, 0);
        srgbSurface.DrawingSurface.Canvas.Restore();

        var saved = targetSurface.Canvas.Save();
        targetSurface.Canvas.SetMatrix(Matrix3X3.Identity);

        targetSurface.Canvas.DrawSurface(srgbSurface.DrawingSurface, 0, 0);
        targetSurface.Canvas.RestoreToCount(saved);
    }

    private Texture? DetermineTargetSurface(RenderContext context, DrawingSurface outputSurface, out DrawingSurface targetSurface)
    {
        targetSurface = outputSurface;
        
        if (Mask.Value == null)
            return null;
        
        Background.Value?.Paint(context, outputSurface);
        var texture = Texture.ForProcessing(outputSurface, context.ProcessingColorSpace);
        targetSurface = texture.DrawingSurface;
        
        return texture;
    }

    private void ApplyWithMask(RenderContext context, DrawingSurface processedSurface, DrawingSurface finalSurface)
    {
        _maskPaint.BlendMode = !InvertMask.Value ? BlendMode.DstIn : BlendMode.DstOut;
        var maskLayer = processedSurface.Canvas.SaveLayer(_maskPaint);
        Mask.Value?.Paint(context, processedSurface);
        processedSurface.Canvas.RestoreToCount(maskLayer);

        var saved = finalSurface.Canvas.Save();
        finalSurface.Canvas.SetMatrix(Matrix3X3.Identity);

        finalSurface.Canvas.DrawSurface(processedSurface, 0, 0);
        finalSurface.Canvas.RestoreToCount(saved);
    }

    public override RectD? GetPreviewBounds(int frame, string elementToRenderName = "") =>
        PreviewUtils.FindPreviewBounds(Background.Connection, frame, elementToRenderName);

    public override Node CreateCopy() => new ApplyFilterNode();
}


Review comment (suggestion):
Even though targetSurface on the output can't be `outputSurface`, you dispose the targetSurface in the code and setting it to `outpuSurface` on line 96 feels dangerous if at any point code changes and returns before reapplying the `targetSurface`

Code after:

        using var srgbSurface = Texture.ForProcessing(intermediate.Size, ColorSpace.CreateSrgb());

        srgbSurface.DrawingSurface.Canvas.SaveLayer(_paint);
        srgbSurface.DrawingSurface.Canvas.DrawSurface(intermediate.DrawingSurface, 0, 0);
        srgbSurface.DrawingSurface.Canvas.Restore();

        var saved = targetSurface.Canvas.Save();
        targetSurface.Canvas.SetMatrix(Matrix3X3.Identity);

        targetSurface.Canvas.DrawSurface(srgbSurface.DrawingSurface, 0, 0);
        targetSurface.Canvas.RestoreToCount(saved);
    }

    private Texture? DetermineTargetSurface(RenderContext context, DrawingSurface outputSurface, out DrawingSurface targetSurface)
    {
        targetSurface = outputSurface;
        
        if (Mask.Value == null)
            return null;
        
        Background.Value?.Paint(context, outputSurface);
        var texture = Texture.ForProcessing(outputSurface, context.ProcessingColorSpace);
        targetSurface = texture.DrawingSurface;
        
        return texture;
    }

    private void ApplyWithMask(RenderContext context, DrawingSurface processedSurface, DrawingSurface finalSurface)
    {
        _maskPaint.BlendMode = !InvertMask.Value ? BlendMode.DstIn : BlendMode.DstOut;
        var maskLayer = processedSurface.Canvas.SaveLayer(_maskPaint);
        Mask.Value?.Paint(context, processedSurface);
        processedSurface.Canvas.RestoreToCount(maskLayer);

        var saved = finalSurface.Canvas.Save();
        finalSurface.Canvas.SetMatrix(Matrix3X3.Identity);

        finalSurface.Canvas.DrawSurface(processedSurface, 0, 0);
        finalSurface.Canvas.RestoreToCount(saved);
    }

    public override RectD? GetPreviewBounds(int frame, string elementToRenderName = "") =>
        PreviewUtils.FindPreviewBounds(Background.Connection, frame, elementToRenderName);

    public override Node CreateCopy() => new ApplyFilterNode();

    public override void Dispose()
    {
        base.Dispose();