From 08fc8b7c3e06eceed1aaccaab034fcea19310c2a Mon Sep 17 00:00:00 2001
From: Emilia <emilia@jumpsca.re>
Date: Mon, 17 Mar 2025 17:24:03 +0200
Subject: [PATCH] Switch to real Avalonia.Labs.Gif, disable assembly info
 autogeneration

---
 Avalonia.Labs.Gif/Avalonia.Labs.Gif.csproj    |  15 -
 Avalonia.Labs.Gif/Decoding/BlockTypes.cs      |   9 -
 Avalonia.Labs.Gif/Decoding/ExtensionType.cs   |   7 -
 Avalonia.Labs.Gif/Decoding/FrameDisposal.cs   |   9 -
 Avalonia.Labs.Gif/Decoding/GifColor.cs        |  35 -
 Avalonia.Labs.Gif/Decoding/GifDecoder.cs      | 661 ------------------
 Avalonia.Labs.Gif/Decoding/GifFrame.cs        |  16 -
 Avalonia.Labs.Gif/Decoding/GifHeader.cs       |  13 -
 Avalonia.Labs.Gif/Decoding/GifRect.cs         |  45 --
 .../Decoding/GifRepeatBehavior.cs             |   7 -
 .../Decoding/InvalidGifStreamException.cs     |   9 -
 .../Decoding/LzwDecompressionException.cs     |   9 -
 .../Extensions/StreamExtensions.cs            |  79 ---
 .../GifCompositionCustomVisualHandler.cs      | 128 ----
 Avalonia.Labs.Gif/GifDrawPayload.cs           |  14 -
 Avalonia.Labs.Gif/GifImage.cs                 | 237 -------
 Avalonia.Labs.Gif/GifInstance.cs              | 128 ----
 Avalonia.Labs.Gif/HandlerCommand.cs           |   9 -
 Blacklight.Desktop/Blacklight.Desktop.csproj  |   4 +
 Blacklight.Desktop/Properties/AssemblyInfo.cs |   3 +-
 Blacklight.sln                                |   4 -
 Blacklight/Blacklight.csproj                  |   2 +-
 22 files changed, 7 insertions(+), 1436 deletions(-)
 delete mode 100644 Avalonia.Labs.Gif/Avalonia.Labs.Gif.csproj
 delete mode 100644 Avalonia.Labs.Gif/Decoding/BlockTypes.cs
 delete mode 100644 Avalonia.Labs.Gif/Decoding/ExtensionType.cs
 delete mode 100644 Avalonia.Labs.Gif/Decoding/FrameDisposal.cs
 delete mode 100644 Avalonia.Labs.Gif/Decoding/GifColor.cs
 delete mode 100644 Avalonia.Labs.Gif/Decoding/GifDecoder.cs
 delete mode 100644 Avalonia.Labs.Gif/Decoding/GifFrame.cs
 delete mode 100644 Avalonia.Labs.Gif/Decoding/GifHeader.cs
 delete mode 100644 Avalonia.Labs.Gif/Decoding/GifRect.cs
 delete mode 100644 Avalonia.Labs.Gif/Decoding/GifRepeatBehavior.cs
 delete mode 100644 Avalonia.Labs.Gif/Decoding/InvalidGifStreamException.cs
 delete mode 100644 Avalonia.Labs.Gif/Decoding/LzwDecompressionException.cs
 delete mode 100644 Avalonia.Labs.Gif/Extensions/StreamExtensions.cs
 delete mode 100644 Avalonia.Labs.Gif/GifCompositionCustomVisualHandler.cs
 delete mode 100644 Avalonia.Labs.Gif/GifDrawPayload.cs
 delete mode 100644 Avalonia.Labs.Gif/GifImage.cs
 delete mode 100644 Avalonia.Labs.Gif/GifInstance.cs
 delete mode 100644 Avalonia.Labs.Gif/HandlerCommand.cs

diff --git a/Avalonia.Labs.Gif/Avalonia.Labs.Gif.csproj b/Avalonia.Labs.Gif/Avalonia.Labs.Gif.csproj
deleted file mode 100644
index 7356e1e..0000000
--- a/Avalonia.Labs.Gif/Avalonia.Labs.Gif.csproj
+++ /dev/null
@@ -1,15 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFrameworks>netstandard2.1;net6.0</TargetFrameworks>
-    <LangVersion>latest</LangVersion>
-    <IsPackable>true</IsPackable>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Avalonia" Version="11.2.5" />
-    <PackageReference Include="Avalonia.Skia" Version="11.2.5" /> 
-  </ItemGroup>
-
-</Project>
diff --git a/Avalonia.Labs.Gif/Decoding/BlockTypes.cs b/Avalonia.Labs.Gif/Decoding/BlockTypes.cs
deleted file mode 100644
index abfd316..0000000
--- a/Avalonia.Labs.Gif/Decoding/BlockTypes.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Avalonia.Labs.Gif.Decoding;
-
-internal enum BlockTypes
-{
-    Empty = 0,
-    Extension = 0x21,
-    ImageDescriptor = 0x2C,
-    Trailer = 0x3B,
-}
\ No newline at end of file
diff --git a/Avalonia.Labs.Gif/Decoding/ExtensionType.cs b/Avalonia.Labs.Gif/Decoding/ExtensionType.cs
deleted file mode 100644
index aa35e14..0000000
--- a/Avalonia.Labs.Gif/Decoding/ExtensionType.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Avalonia.Labs.Gif.Decoding;
-
-internal enum ExtensionType
-{
-    GraphicsControl = 0xF9,
-    Application = 0xFF
-}
\ No newline at end of file
diff --git a/Avalonia.Labs.Gif/Decoding/FrameDisposal.cs b/Avalonia.Labs.Gif/Decoding/FrameDisposal.cs
deleted file mode 100644
index 4f0607f..0000000
--- a/Avalonia.Labs.Gif/Decoding/FrameDisposal.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Avalonia.Labs.Gif.Decoding;
-
-internal enum FrameDisposal
-{
-    Unknown = 0,
-    Leave = 1,
-    Background = 2,
-    Restore = 3
-}
diff --git a/Avalonia.Labs.Gif/Decoding/GifColor.cs b/Avalonia.Labs.Gif/Decoding/GifColor.cs
deleted file mode 100644
index 4076734..0000000
--- a/Avalonia.Labs.Gif/Decoding/GifColor.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace Avalonia.Labs.Gif.Decoding;
-
-[StructLayout(LayoutKind.Explicit)]
-internal readonly struct GifColor
-{
-    [FieldOffset(3)]
-    public readonly byte A;
-
-    [FieldOffset(2)]
-    public readonly byte R;
-
-    [FieldOffset(1)]
-    public readonly byte G;
-        
-    [FieldOffset(0)]
-    public readonly byte B;
-
-    /// <summary>
-    /// A struct that represents a ARGB color and is aligned as
-    /// a BGRA bytefield in memory.
-    /// </summary>
-    /// <param name="r">Red</param>
-    /// <param name="g">Green</param>
-    /// <param name="b">Blue</param>
-    /// <param name="a">Alpha</param>
-    public GifColor(byte r, byte g, byte b, byte a = byte.MaxValue)
-    {
-            A = a;
-            R = r;
-            G = g;
-            B = b;
-    }
-}
diff --git a/Avalonia.Labs.Gif/Decoding/GifDecoder.cs b/Avalonia.Labs.Gif/Decoding/GifDecoder.cs
deleted file mode 100644
index 63878bf..0000000
--- a/Avalonia.Labs.Gif/Decoding/GifDecoder.cs
+++ /dev/null
@@ -1,661 +0,0 @@
-// This source file's Lempel-Ziv-Welch algorithm is derived from Chromium's Android GifPlayer
-// as seen here (https://github.com/chromium/chromium/blob/master/third_party/gif_player/src/jp/tomorrowkey/android/gifplayer)
-// Licensed under the Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
-// Copyright (C) 2015 The Gifplayer Authors. All Rights Reserved.
-
-// The rest of the source file is licensed under MIT License.
-// Copyright (C) 2018 Jumar A. Macato, All Rights Reserved.
-
-using System;
-using System.Buffers;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading;
-using Avalonia.Media.Imaging;
-using static Avalonia.Labs.Gif.Extensions.StreamExtensions;
-
-namespace Avalonia.Labs.Gif.Decoding;
-
-internal sealed class GifDecoder : IDisposable
-{
-    private static readonly ReadOnlyMemory<byte> s_g87AMagic
-        = "GIF87a"u8.ToArray().AsMemory();
-
-    private static readonly ReadOnlyMemory<byte> s_g89AMagic
-        = "GIF89a"u8.ToArray().AsMemory();
-
-    private static readonly ReadOnlyMemory<byte> s_netscapeMagic
-        = "NETSCAPE2.0"u8.ToArray().AsMemory();
-
-    private static readonly TimeSpan s_frameDelayThreshold = TimeSpan.FromMilliseconds(10);
-    private static readonly TimeSpan s_frameDelayDefault = TimeSpan.FromMilliseconds(100);
-    private static readonly GifColor s_transparentColor = new(0, 0, 0, 0);
-    private const int MaxTempBuf = 768;
-    private const int MaxStackSize = 4096;
-    private const int MaxBits = 4097;
-
-    private readonly Stream _fileStream;
-    private readonly CancellationToken _currentCtsToken;
-    private readonly bool _hasFrameBackups;
-
-    private int _gctSize, _prevFrame = -1, _backupFrame = -1;
-    private bool _gctUsed;
-
-    private GifRect _gifDimensions;
-
-    private readonly int _backBufferBytes;
-    private GifColor[]? _bitmapBackBuffer;
-
-    private short[]? _prefixBuf;
-    private byte[]? _suffixBuf;
-    private byte[]? _pixelStack;
-    private byte[]? _indexBuf;
-    private byte[]? _backupFrameIndexBuf;
-    private volatile bool _hasNewFrame;
-
-    public GifHeader? Header { get; private set; }
-
-    internal readonly List<GifFrame> _frames = new();
-
-    public PixelSize Size => new(Header?.Dimensions.Width ?? 0, Header?.Dimensions.Height ?? 0);
-
-    public GifDecoder(Stream fileStream, CancellationToken currentCtsToken)
-    {
-        _fileStream = fileStream;
-        _currentCtsToken = currentCtsToken;
-
-        ProcessHeaderData();
-        ProcessFrameData();
-
-        if (Header != null)
-            Header.IterationCount = Header.Iterations switch
-            {
-                -1 => new GifRepeatBehavior { Count = 1 },
-                0 => new GifRepeatBehavior { LoopForever = true },
-                > 0 => new GifRepeatBehavior { Count = Header.Iterations },
-                _ => Header.IterationCount
-            };
-
-        var pixelCount = _gifDimensions.TotalPixels;
-
-        _hasFrameBackups = _frames
-            .Any(f => f.FrameDisposalMethod == FrameDisposal.Restore);
-
-        _bitmapBackBuffer = new GifColor[pixelCount];
-        _indexBuf = new byte[pixelCount];
-
-        if (_hasFrameBackups)
-            _backupFrameIndexBuf = new byte[pixelCount];
-
-        _prefixBuf = new short[MaxStackSize];
-        _suffixBuf = new byte[MaxStackSize];
-        _pixelStack = new byte[MaxStackSize + 1];
-
-        _backBufferBytes = pixelCount * Marshal.SizeOf(typeof(GifColor));
-    }
-
-    public void Dispose()
-    {
-        _frames.Clear();
-
-        _bitmapBackBuffer = null;
-        _prefixBuf = null;
-        _suffixBuf = null;
-        _pixelStack = null;
-        _indexBuf = null;
-        _backupFrameIndexBuf = null;
-    }
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    private int PixelCoordinate(int x, int y) => x + y * _gifDimensions.Width;
-
-    private static readonly (int Start, int Step)[] s_pass = [(0, 8), (4, 8), (2, 4), (1, 2)];
-
-    private void ClearImage()
-    {
-        if (_bitmapBackBuffer != null)
-            Array.Fill(_bitmapBackBuffer, s_transparentColor);
-
-        _prevFrame = -1;
-        _backupFrame = -1;
-    }
-
-    public void RenderFrame(int fIndex, WriteableBitmap? writeableBitmap, bool forceClear = false)
-    {
-        if (_currentCtsToken.IsCancellationRequested)
-            return;
-
-        if (fIndex < 0 | fIndex >= _frames.Count)
-            return;
-
-        if (_prevFrame == fIndex)
-            return;
-
-        if (fIndex == 0 || forceClear || fIndex < _prevFrame)
-            ClearImage();
-
-        DisposePreviousFrame();
-
-        _prevFrame++;
-
-        // render intermediate frame
-        for (int idx = _prevFrame; idx < fIndex; ++idx)
-        {
-            var prevFrame = _frames[idx];
-
-            if (prevFrame.FrameDisposalMethod == FrameDisposal.Restore)
-                continue;
-
-            if (prevFrame.FrameDisposalMethod == FrameDisposal.Background)
-            {
-                ClearArea(prevFrame.Dimensions);
-                continue;
-            }
-
-            RenderFrameAt(idx, writeableBitmap);
-        }
-
-        RenderFrameAt(fIndex, writeableBitmap);
-    }
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    private void RenderFrameAt(int idx, WriteableBitmap? writeableBitmap)
-    {
-        if(writeableBitmap is null)
-            return;
-
-        var tmpB = ArrayPool<byte>.Shared.Rent(MaxTempBuf);
-
-        var curFrame = _frames[idx];
-        DecompressFrameToIndexBuffer(curFrame, _indexBuf, tmpB);
-
-        if (_hasFrameBackups & curFrame.ShouldBackup
-            && _indexBuf != null && _backupFrameIndexBuf != null)
-        {
-            Buffer.BlockCopy(_indexBuf, 0,
-                _backupFrameIndexBuf, 0,
-                curFrame.Dimensions.TotalPixels);
-            _backupFrame = idx;
-        }
-
-        DrawFrame(curFrame, _indexBuf);
-
-        _prevFrame = idx;
-        _hasNewFrame = true;
-
-        using var lockedBitmap = writeableBitmap.Lock();
-        WriteBackBufToFb(lockedBitmap.Address);
-
-        ArrayPool<byte>.Shared.Return(tmpB);
-    }
-
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    private void DrawFrame(GifFrame curFrame, Memory<byte> frameIndexSpan)
-    {
-        var activeColorTable =
-            curFrame.IsLocalColorTableUsed ? curFrame.LocalColorTable : Header?.GlobalColorTable;
-
-        var cX = curFrame.Dimensions.X;
-        var cY = curFrame.Dimensions.Y;
-        var cH = curFrame.Dimensions.Height;
-        var cW = curFrame.Dimensions.Width;
-        var tC = curFrame.TransparentColorIndex;
-        var hT = curFrame.HasTransparency;
-
-        if (curFrame.IsInterlaced)
-        {
-            int curSrcRow = 0;
-            for (var i = 0; i < 4; i++)
-            {
-                var curPass = s_pass[i];
-                var y = curPass.Start;
-                while (y < cH)
-                {
-                    DrawRow(curSrcRow++, y);
-                    y += curPass.Step;
-                }
-            }
-        }
-        else
-        {
-            for (var i = 0; i < cH; i++)
-                DrawRow(i, i);
-        }
-
-        return;
-
-        void DrawRow(int srcRow, int destRow)
-        {
-            // Get the starting point of the current row on frame's index stream.
-            var indexOffset = srcRow * cW;
-
-            // Get the target back buffer offset from the frames coords.
-            var targetOffset = PixelCoordinate(cX, destRow + cY);
-            if (_bitmapBackBuffer == null) return;
-            var len = _bitmapBackBuffer.Length;
-
-            for (var i = 0; i < cW; i++)
-            {
-                var indexColor = frameIndexSpan.Span[indexOffset + i];
-
-                if (activeColorTable == null || targetOffset >= len ||
-                    indexColor > activeColorTable.Length) return;
-
-                if (!(hT & indexColor == tC))
-                    _bitmapBackBuffer[targetOffset] = activeColorTable[indexColor];
-
-                targetOffset++;
-            }
-        }
-    }
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    private void DisposePreviousFrame()
-    {
-        if (_prevFrame == -1)
-            return;
-
-        var prevFrame = _frames[_prevFrame];
-
-        switch (prevFrame.FrameDisposalMethod)
-        {
-            case FrameDisposal.Background:
-                ClearArea(prevFrame.Dimensions);
-                break;
-            case FrameDisposal.Restore:
-                if (_hasFrameBackups && _backupFrame != -1)
-                    DrawFrame(_frames[_backupFrame], _backupFrameIndexBuf);
-                else
-                    ClearArea(prevFrame.Dimensions);
-                break;
-        }
-    }
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    private void ClearArea(GifRect area)
-    {
-        if (_bitmapBackBuffer is null) return;
-
-        for (var y = 0; y < area.Height; y++)
-        {
-            var targetOffset = PixelCoordinate(area.X, y + area.Y);
-            for (var x = 0; x < area.Width; x++)
-                _bitmapBackBuffer[targetOffset + x] = s_transparentColor;
-        }
-    }
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    private void DecompressFrameToIndexBuffer(GifFrame curFrame, Span<byte> indexSpan, byte[] tempBuf)
-    {
-        if (_prefixBuf is null || _suffixBuf is null || _pixelStack is null) return;
-
-        _fileStream.Position = curFrame.LzwStreamPosition;
-        var totalPixels = curFrame.Dimensions.TotalPixels;
-
-        // Initialize GIF data stream decoder.
-        var dataSize = curFrame.LzwMinCodeSize;
-        var clear = 1 << dataSize;
-        var endOfInformation = clear + 1;
-        var available = clear + 2;
-        var oldCode = -1;
-        var codeSize = dataSize + 1;
-        var codeMask = (1 << codeSize) - 1;
-
-        for (var code = 0; code < clear; code++)
-        {
-            _prefixBuf[code] = 0;
-            _suffixBuf[code] = (byte)code;
-        }
-
-        // Decode GIF pixel stream.
-        int bits, first, top, pixelIndex;
-        var datum = bits = first = top = pixelIndex = 0;
-
-        while (pixelIndex < totalPixels)
-        {
-            var blockSize = _fileStream.ReadBlock(tempBuf);
-
-            if (blockSize == 0)
-                break;
-
-            var blockPos = 0;
-
-            while (blockPos < blockSize)
-            {
-                datum += tempBuf[blockPos] << bits;
-                blockPos++;
-
-                bits += 8;
-
-                while (bits >= codeSize)
-                {
-                    // Get the next code.
-                    var code = datum & codeMask;
-                    datum >>= codeSize;
-                    bits -= codeSize;
-
-                    // Interpret the code
-                    if (code == clear)
-                    {
-                        // Reset decoder.
-                        codeSize = dataSize + 1;
-                        codeMask = (1 << codeSize) - 1;
-                        available = clear + 2;
-                        oldCode = -1;
-                        continue;
-                    }
-
-                    // Check for explicit end-of-stream
-                    if (code == endOfInformation)
-                        return;
-
-                    if (oldCode == -1)
-                    {
-                        indexSpan[pixelIndex++] = _suffixBuf[code];
-                        oldCode = code;
-                        first = code;
-                        continue;
-                    }
-
-                    var inCode = code;
-                    if (code >= available)
-                    {
-                        _pixelStack[top++] = (byte)first;
-                        code = oldCode;
-
-                        if (top == MaxBits)
-                            ThrowLswException();
-                    }
-
-                    while (code >= clear)
-                    {
-                        if (code >= MaxBits || code == _prefixBuf[code])
-                            ThrowLswException();
-
-                        _pixelStack[top++] = _suffixBuf[code];
-                        code = _prefixBuf[code];
-
-                        if (top == MaxBits)
-                            ThrowLswException();
-                    }
-
-                    first = _suffixBuf[code];
-                    _pixelStack[top++] = (byte)first;
-
-                    // Add new code to the dictionary
-                    if (available < MaxStackSize)
-                    {
-                        _prefixBuf[available] = (short)oldCode;
-                        _suffixBuf[available] = (byte)first;
-                        available++;
-
-                        if ((available & codeMask) == 0 && available < MaxStackSize)
-                        {
-                            codeSize++;
-                            codeMask += available;
-                        }
-                    }
-
-                    oldCode = inCode;
-
-                    // Drain the pixel stack.
-                    do
-                    {
-                        indexSpan[pixelIndex++] = _pixelStack[--top];
-                    } while (top > 0);
-                }
-            }
-        }
-
-        while (pixelIndex < totalPixels)
-            indexSpan[pixelIndex++] = 0; // clear missing pixels
-    }
-
-    private static void ThrowLswException() => throw new LzwDecompressionException();
-
-    /// <summary>
-    /// Directly copies the <see cref="GifColor"/> struct array to a bitmap IntPtr.
-    /// </summary>
-    private void WriteBackBufToFb(IntPtr targetPointer)
-    {
-        if (_currentCtsToken.IsCancellationRequested)
-            return;
-
-        if (!(_hasNewFrame && _bitmapBackBuffer != null)) return;
-
-        unsafe
-        {
-            fixed (void* src = &_bitmapBackBuffer[0])
-                Buffer.MemoryCopy(src, targetPointer.ToPointer(), (uint)_backBufferBytes,
-                    (uint)_backBufferBytes);
-            _hasNewFrame = false;
-        }
-    }
-
-    /// <summary>
-    /// Processes GIF Header.
-    /// </summary>
-    private void ProcessHeaderData()
-    {
-        var str = _fileStream;
-        var tmpB = ArrayPool<byte>.Shared.Rent(MaxTempBuf);
-        var tempBuf = tmpB.AsSpan();
-
-        var _ = str.Read(tmpB, 0, 6);
-
-        if (!tempBuf[..3].SequenceEqual(s_g87AMagic[..3].Span))
-            throw new InvalidGifStreamException("Not a GIF stream.");
-
-        if (!(tempBuf[..6].SequenceEqual(s_g87AMagic.Span) |
-              tempBuf[..6].SequenceEqual(s_g89AMagic.Span)))
-            throw new InvalidGifStreamException("Unsupported GIF Version: " +
-                                                Encoding.ASCII.GetString(tempBuf[..6].ToArray()));
-
-        ProcessScreenDescriptor(tmpB);
-
-        Header = new GifHeader
-        {
-            Dimensions = _gifDimensions,
-            GlobalColorTable =
-                _gctUsed ? ProcessColorTable(ref str, tmpB, _gctSize) : [],
-            HeaderSize = _fileStream.Position
-        };
-
-        ArrayPool<byte>.Shared.Return(tmpB);
-    }
-
-    /// <summary>
-    /// Parses colors from file stream to target color table.
-    /// </summary> 
-    private static GifColor[] ProcessColorTable(ref Stream stream, byte[] rawBufSpan, int nColors)
-    {
-        var nBytes = 3 * nColors;
-        var target = new GifColor[nColors];
-
-        var n = stream.Read(rawBufSpan, 0, nBytes);
-
-        if (n < nBytes)
-            throw new InvalidOperationException("Wrong color table bytes.");
-
-        int i = 0, j = 0;
-
-        while (i < nColors)
-        {
-            var r = rawBufSpan[j++];
-            var g = rawBufSpan[j++];
-            var b = rawBufSpan[j++];
-            target[i++] = new GifColor(r, g, b);
-        }
-
-        return target;
-    }
-
-    /// <summary>
-    /// Parses screen and other GIF descriptors. 
-    /// </summary>
-    private void ProcessScreenDescriptor(byte[] tempBuf)
-    {
-        var width = _fileStream.ReadUShortS(tempBuf);
-        var height = _fileStream.ReadUShortS(tempBuf);
-
-        var packed = _fileStream.ReadByteS(tempBuf);
-
-        _gctUsed = (packed & 0x80) != 0;
-        _gctSize = 2 << (packed & 7);
-        _ = _fileStream.ReadByteS(tempBuf);
-
-        _gifDimensions = new GifRect(0, 0, width, height);
-        _fileStream.Skip(1);
-    }
-
-    /// <summary>
-    /// Parses all frame data.
-    /// </summary>
-    private void ProcessFrameData()
-    {
-        _fileStream.Position = Header?.HeaderSize ?? -1;
-
-        var tempBuf = ArrayPool<byte>.Shared.Rent(MaxTempBuf);
-
-        var terminate = false;
-        var curFrame = 0;
-
-        _frames.Add(new GifFrame());
-
-        do
-        {
-            var blockType = (BlockTypes)_fileStream.ReadByteS(tempBuf);
-
-            switch (blockType)
-            {
-                case BlockTypes.Empty:
-                    break;
-
-                case BlockTypes.Extension:
-                    ProcessExtensions(ref curFrame, tempBuf);
-                    break;
-
-                case BlockTypes.ImageDescriptor:
-                    ProcessImageDescriptor(ref curFrame, tempBuf);
-                    _fileStream.SkipBlocks(tempBuf);
-                    break;
-
-                case BlockTypes.Trailer:
-                    _frames.RemoveAt(_frames.Count - 1);
-                    terminate = true;
-                    break;
-
-                default:
-                    _fileStream.SkipBlocks(tempBuf);
-                    break;
-            }
-
-            // Break the loop when the stream is not valid anymore.
-            if (_fileStream.Position >= _fileStream.Length & terminate == false)
-                throw new InvalidProgramException("Reach the end of the filestream without trailer block.");
-        } while (!terminate);
-
-        ArrayPool<byte>.Shared.Return(tempBuf);
-    }
-
-    /// <summary>
-    /// Parses GIF Image Descriptor Block.
-    /// </summary>
-    private void ProcessImageDescriptor(ref int curFrame, byte[] tempBuf)
-    {
-        var str = _fileStream;
-        var currentFrame = _frames[curFrame];
-
-        // Parse frame dimensions.
-        var frameX = str.ReadUShortS(tempBuf);
-        var frameY = str.ReadUShortS(tempBuf);
-        var frameW = str.ReadUShortS(tempBuf);
-        var frameH = str.ReadUShortS(tempBuf);
-
-        frameW = (ushort)Math.Min(frameW, _gifDimensions.Width - frameX);
-        frameH = (ushort)Math.Min(frameH, _gifDimensions.Height - frameY);
-
-        currentFrame.Dimensions = new GifRect(frameX, frameY, frameW, frameH);
-
-        // Unpack interlace and lct info.
-        var packed = str.ReadByteS(tempBuf);
-        currentFrame.IsInterlaced = (packed & 0x40) != 0;
-        currentFrame.IsLocalColorTableUsed = (packed & 0x80) != 0;
-        currentFrame.LocalColorTableSize = (int)Math.Pow(2, (packed & 0x07) + 1);
-
-        if (currentFrame.IsLocalColorTableUsed)
-            currentFrame.LocalColorTable =
-                ProcessColorTable(ref str, tempBuf, currentFrame.LocalColorTableSize);
-
-        currentFrame.LzwMinCodeSize = str.ReadByteS(tempBuf);
-        currentFrame.LzwStreamPosition = str.Position;
-
-        curFrame += 1;
-        _frames.Add(new GifFrame());
-    }
-
-    /// <summary>
-    /// Parses GIF Extension Blocks.
-    /// </summary>
-    private void ProcessExtensions(ref int curFrame, byte[] tempBuf)
-    {
-        var extType = (ExtensionType)_fileStream.ReadByteS(tempBuf);
-
-        switch (extType)
-        {
-            case ExtensionType.GraphicsControl:
-
-                _fileStream.ReadBlock(tempBuf);
-                var currentFrame = _frames[curFrame];
-                var packed = tempBuf[0];
-
-                currentFrame.FrameDisposalMethod = (FrameDisposal)((packed & 0x1c) >> 2);
-
-                if (currentFrame.FrameDisposalMethod != FrameDisposal.Restore
-                    && currentFrame.FrameDisposalMethod != FrameDisposal.Background)
-                    currentFrame.ShouldBackup = true;
-
-                currentFrame.HasTransparency = (packed & 1) != 0;
-
-                currentFrame.FrameDelay =
-                    TimeSpan.FromMilliseconds(SpanToShort(tempBuf.AsSpan(1)) * 10);
-
-                if (currentFrame.FrameDelay <= s_frameDelayThreshold)
-                    currentFrame.FrameDelay = s_frameDelayDefault;
-
-                currentFrame.TransparentColorIndex = tempBuf[3];
-                break;
-
-            case ExtensionType.Application:
-                var blockLen = _fileStream.ReadBlock(tempBuf);
-                var _ = tempBuf.AsSpan(0, blockLen);
-                var blockHeader = tempBuf.AsSpan(0, s_netscapeMagic.Length);
-
-                if (blockHeader.SequenceEqual(s_netscapeMagic.Span))
-                {
-                    var count = 1;
-
-                    while (count > 0)
-                        count = _fileStream.ReadBlock(tempBuf);
-
-                    var iterationCount = SpanToShort(tempBuf.AsSpan(1));
-
-                    if (Header != null)
-                        Header.Iterations = iterationCount;
-                }
-                else
-                    _fileStream.SkipBlocks(tempBuf);
-
-                break;
-
-            default:
-                _fileStream.SkipBlocks(tempBuf);
-                break;
-        }
-    }
-}
diff --git a/Avalonia.Labs.Gif/Decoding/GifFrame.cs b/Avalonia.Labs.Gif/Decoding/GifFrame.cs
deleted file mode 100644
index e10cbb6..0000000
--- a/Avalonia.Labs.Gif/Decoding/GifFrame.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-
-namespace Avalonia.Labs.Gif.Decoding;
-
-internal class GifFrame
-{
-    public bool HasTransparency, IsInterlaced, IsLocalColorTableUsed;
-    public byte TransparentColorIndex;
-    public int LzwMinCodeSize, LocalColorTableSize;
-    public long LzwStreamPosition;
-    public TimeSpan FrameDelay;
-    public FrameDisposal FrameDisposalMethod;
-    public bool ShouldBackup;
-    public GifRect Dimensions;
-    public GifColor[]? LocalColorTable;
-}
diff --git a/Avalonia.Labs.Gif/Decoding/GifHeader.cs b/Avalonia.Labs.Gif/Decoding/GifHeader.cs
deleted file mode 100644
index 69ae294..0000000
--- a/Avalonia.Labs.Gif/Decoding/GifHeader.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Licensed under the MIT License.
-// Copyright (C) 2018 Jumar A. Macato, All Rights Reserved.
-
-namespace Avalonia.Labs.Gif.Decoding;
-
-internal class GifHeader
-{
-    public long HeaderSize;
-    internal int Iterations = -1;
-    public GifRepeatBehavior? IterationCount;
-    public GifRect Dimensions;
-    public GifColor[]? GlobalColorTable;
-}
diff --git a/Avalonia.Labs.Gif/Decoding/GifRect.cs b/Avalonia.Labs.Gif/Decoding/GifRect.cs
deleted file mode 100644
index d4d6f81..0000000
--- a/Avalonia.Labs.Gif/Decoding/GifRect.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-namespace Avalonia.Labs.Gif.Decoding;
-
-internal readonly struct GifRect
-{
-    public int X { get; }
-    public int Y { get; }
-    public int Width { get; }
-    public int Height { get; }
-    public int TotalPixels { get; }
-
-    public GifRect(int x, int y, int width, int height)
-    {
-        X = x;
-        Y = y;
-        Width = width;
-        Height = height;
-        TotalPixels = width * height;
-    }
-
-    public static bool operator ==(GifRect a, GifRect b)
-    {
-        return a.X == b.X &&
-               a.Y == b.Y &&
-               a.Width == b.Width &&
-               a.Height == b.Height;
-    }
-
-    public static bool operator !=(GifRect a, GifRect b)
-    {
-        return !(a == b);
-    }
-
-    public override bool Equals(object? obj)
-    {
-        if (obj == null || GetType() != obj.GetType())
-            return false;
-
-        return this == (GifRect)obj;
-    }
-
-    public override int GetHashCode()
-    {
-        return X.GetHashCode() ^ Y.GetHashCode() | Width.GetHashCode() ^ Height.GetHashCode();
-    }
-}
diff --git a/Avalonia.Labs.Gif/Decoding/GifRepeatBehavior.cs b/Avalonia.Labs.Gif/Decoding/GifRepeatBehavior.cs
deleted file mode 100644
index a607995..0000000
--- a/Avalonia.Labs.Gif/Decoding/GifRepeatBehavior.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Avalonia.Labs.Gif.Decoding;
-
-internal class GifRepeatBehavior
-{
-    public bool LoopForever { get; set; }
-    public int? Count { get; set; }
-}
diff --git a/Avalonia.Labs.Gif/Decoding/InvalidGifStreamException.cs b/Avalonia.Labs.Gif/Decoding/InvalidGifStreamException.cs
deleted file mode 100644
index bc434ab..0000000
--- a/Avalonia.Labs.Gif/Decoding/InvalidGifStreamException.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Licensed under the MIT License.
-// Copyright (C) 2018 Jumar A. Macato, All Rights Reserved.
-
-using System;
-
-namespace Avalonia.Labs.Gif.Decoding;
-
-[Serializable]
-internal sealed class InvalidGifStreamException(string message) : Exception(message);
diff --git a/Avalonia.Labs.Gif/Decoding/LzwDecompressionException.cs b/Avalonia.Labs.Gif/Decoding/LzwDecompressionException.cs
deleted file mode 100644
index e380e73..0000000
--- a/Avalonia.Labs.Gif/Decoding/LzwDecompressionException.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Licensed under the MIT License.
-// Copyright (C) 2018 Jumar A. Macato, All Rights Reserved.
-
-using System;
-
-namespace Avalonia.Labs.Gif.Decoding;
-
-[Serializable]
-internal class LzwDecompressionException : Exception { }
diff --git a/Avalonia.Labs.Gif/Extensions/StreamExtensions.cs b/Avalonia.Labs.Gif/Extensions/StreamExtensions.cs
deleted file mode 100644
index 1cbae59..0000000
--- a/Avalonia.Labs.Gif/Extensions/StreamExtensions.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using System;
-using System.IO;
-using System.Runtime.CompilerServices;
-using Avalonia.Labs.Gif.Decoding;
-
-namespace Avalonia.Labs.Gif.Extensions;
-
-internal static class StreamExtensions
-{
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static ushort SpanToShort(Span<byte> b) => (ushort)(b[0] | (b[1] << 8));
-
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static void Skip(this Stream stream, long count)
-    {
-        stream.Position += count;
-    }
-
-    /// <summary>
-    /// Read a Gif block from stream while advancing the position.
-    /// </summary>
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static int ReadBlock(this Stream stream, byte[] tempBuf)
-    {
-        _ = stream.Read(tempBuf, 0, 1);
-
-        var blockLength = (int)tempBuf[0];
-
-        if (blockLength > 0)
-            _ = stream.Read(tempBuf, 0, blockLength);
-
-        // Guard against infinite loop.
-        if (stream.Position >= stream.Length)
-            throw new InvalidGifStreamException("Reach the end of the filestream without trailer block.");
-
-        return blockLength;
-    }
-
-    /// <summary>
-    /// Skips GIF blocks until it encounters an empty block.
-    /// </summary>
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static void SkipBlocks(this Stream stream, byte[] tempBuf)
-    {
-        int blockLength;
-        do
-        {
-            _ = stream.Read(tempBuf, 0, 1);
-
-            blockLength = tempBuf[0];
-            stream.Position += blockLength;
-
-            // Guard against infinite loop.
-            if (stream.Position >= stream.Length)
-                throw new InvalidGifStreamException("Reach the end of the filestream without trailer block.");
-        } while (blockLength > 0);
-    }
-
-    /// <summary>
-    /// Read a <see cref="ushort"/> from stream by providing a temporary buffer.
-    /// </summary>
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static ushort ReadUShortS(this Stream stream, byte[] tempBuf)
-    {
-        _ = stream.Read(tempBuf, 0, 2);
-        return SpanToShort(tempBuf);
-    }
-
-    /// <summary>
-    /// Read a <see cref="ushort"/> from stream by providing a temporary buffer.
-    /// </summary>
-    [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public static byte ReadByteS(this Stream stream, byte[] tempBuf)
-    {
-        _ = stream.Read(tempBuf, 0, 1);
-        var finalVal = tempBuf[0];
-        return finalVal;
-    }
-}
diff --git a/Avalonia.Labs.Gif/GifCompositionCustomVisualHandler.cs b/Avalonia.Labs.Gif/GifCompositionCustomVisualHandler.cs
deleted file mode 100644
index 3a27021..0000000
--- a/Avalonia.Labs.Gif/GifCompositionCustomVisualHandler.cs
+++ /dev/null
@@ -1,128 +0,0 @@
-using System;
-using Avalonia.Media;
-using Avalonia.Rendering.Composition;
-
-namespace Avalonia.Labs.Gif;
-
-internal class GifCompositionCustomVisualHandler : CompositionCustomVisualHandler
-{
-    private bool _running;
-    private Stretch? _stretch;
-    private StretchDirection? _stretchDirection;
-    private Size _GifSize;
-    private readonly object _sync = new();
-    private bool _isDisposed;
-    private GifInstance? _gifInstance;
-
-    private TimeSpan _animationElapsed;
-    private TimeSpan _lastServerTime;
-
-    public override void OnMessage(object message)
-    {
-        if (message is not GifDrawPayload msg)
-        {
-            return;
-        }
-
-        switch (msg)
-        {
-            case
-            {
-                HandlerCommand: HandlerCommand.Start, Source: { } uri, IterationCount: { } iteration,
-                Stretch: { } st, StretchDirection: { } sd
-            }:
-            {
-                _gifInstance = new GifInstance(uri);
-
-                _gifInstance.IterationCount = iteration;
-
-                _lastServerTime = CompositionNow;
-                _GifSize = _gifInstance.GifPixelSize.ToSize(1);
-                _running = true;
-                _stretch = st;
-                _stretchDirection = sd;
-                RegisterForNextAnimationFrameUpdate();
-                break;
-            }
-            case
-            {
-                HandlerCommand: HandlerCommand.Update, Stretch: { } st, IterationCount: { } iteration,
-                StretchDirection: { } sd
-            }:
-            {
-                _stretch = st;
-                _stretchDirection = sd;
-                if (_gifInstance != null)
-                    _gifInstance.IterationCount = iteration;
-                RegisterForNextAnimationFrameUpdate();
-                break;
-            }
-            case { HandlerCommand: HandlerCommand.Stop }:
-            {
-                _running = false;
-                break;
-            }
-            case { HandlerCommand: HandlerCommand.Dispose }:
-            {
-                DisposeImpl();
-                break;
-            }
-        }
-    }
-
-    public override void OnAnimationFrameUpdate()
-    {
-        if (!_running || _isDisposed)
-            return;
-
-        Invalidate();
-        RegisterForNextAnimationFrameUpdate();
-    }
-
-    public override void OnRender(ImmediateDrawingContext context)
-    {
-        lock (_sync)
-        {
-            if (_stretch is not { } st
-                || _stretchDirection is not { } sd
-                || _gifInstance is null
-                || _isDisposed
-                || !_running)
-            {
-                return;
-            }
-
-            _animationElapsed += CompositionNow - _lastServerTime;
-            _lastServerTime = CompositionNow;
-
-            var bounds = GetRenderBounds().Size;
-            var viewPort = new Rect(bounds);
-
-            var scale = st.CalculateScaling(bounds, _GifSize, sd);
-            var scaledSize = _GifSize * scale;
-            var destRect = viewPort
-                .CenterRect(new Rect(scaledSize))
-                .Intersect(viewPort);
-
-            var bitmap = _gifInstance.ProcessFrameTime(_animationElapsed);
-            if (bitmap is not null)
-            {
-                context.DrawBitmap(bitmap, new Rect(_gifInstance.GifPixelSize.ToSize(1)),
-                    destRect);
-            }
-        }
-    }
-
-    private void DisposeImpl()
-    {
-        lock (_sync)
-        {
-            if (_isDisposed) return;
-            _isDisposed = true;
-            _gifInstance?.Dispose();
-            _animationElapsed = TimeSpan.Zero;
-            _lastServerTime = TimeSpan.Zero;
-            _running = false;
-        }
-    }
-}
diff --git a/Avalonia.Labs.Gif/GifDrawPayload.cs b/Avalonia.Labs.Gif/GifDrawPayload.cs
deleted file mode 100644
index b80149f..0000000
--- a/Avalonia.Labs.Gif/GifDrawPayload.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-using Avalonia.Animation;
-using Avalonia.Media;
-
-namespace Avalonia.Labs.Gif;
-
-internal record struct GifDrawPayload(
-    HandlerCommand HandlerCommand,
-    Uri? Source = default,
-    Size? GifSize = default,
-    Size? Size = default,
-    Stretch? Stretch = default,
-    StretchDirection? StretchDirection = default,
-    IterationCount? IterationCount = default);
\ No newline at end of file
diff --git a/Avalonia.Labs.Gif/GifImage.cs b/Avalonia.Labs.Gif/GifImage.cs
deleted file mode 100644
index f060406..0000000
--- a/Avalonia.Labs.Gif/GifImage.cs
+++ /dev/null
@@ -1,237 +0,0 @@
-using System;
-using System.IO;
-using System.Numerics;
-using System.Threading;
-using Avalonia.Animation;
-using Avalonia.Controls;
-using Avalonia.Labs.Gif.Decoding;
-using Avalonia.Media;
-using Avalonia.Platform;
-using Avalonia.Rendering.Composition;
-
-namespace Avalonia.Labs.Gif;
-
-/// <summary>
-/// A control that presents GIF animations.
-/// </summary>
-public class GifImage : Control
-{
-    private CompositionCustomVisual? _customVisual;
-
-    private double _gifWidth, _gifHeight;
-
-    /// <summary>
-    /// Defines the <see cref="Source"/> property.
-    /// </summary>
-    public static readonly StyledProperty<Uri> SourceProperty =
-        AvaloniaProperty.Register<GifImage, Uri>(nameof(Source));
- 
-    /// <summary>
-    /// Defines the <see cref="IterationCount"/> property.
-    /// </summary>
-    public static readonly StyledProperty<IterationCount> IterationCountProperty =
-        AvaloniaProperty.Register<GifImage, IterationCount>(nameof(IterationCount), IterationCount.Infinite);
-
-    /// <summary>
-    /// Defines the <see cref="StretchDirection"/> property.
-    /// </summary>
-    public static readonly StyledProperty<StretchDirection> StretchDirectionProperty =
-        AvaloniaProperty.Register<GifImage, StretchDirection>(nameof(StretchDirection));
-
-    /// <summary>
-    /// Defines the <see cref="Stretch"/> property.
-    /// </summary>
-    public static readonly StyledProperty<Stretch> StretchProperty =
-        AvaloniaProperty.Register<GifImage, Stretch>(nameof(Stretch));
-
-    /// <summary>
-    /// Gets or sets the uri pointing to the GIF image resource
-    /// </summary>
-    public Uri Source
-    {
-        get => GetValue(SourceProperty);
-        set => SetValue(SourceProperty, value);
-    }
-
-    /// <summary>
-    /// Gets or sets a value controlling how the image will be stretched.
-    /// </summary>
-    public Stretch Stretch
-    {
-        get => GetValue(StretchProperty);
-        set => SetValue(StretchProperty, value);
-    }
-
-    /// <summary>
-    /// Gets or sets a value controlling in what direction the image will be stretched.
-    /// </summary>
-    public StretchDirection StretchDirection
-    {
-        get => GetValue(StretchDirectionProperty);
-        set => SetValue(StretchDirectionProperty, value);
-    }
-
-    /// <summary>
-    /// Gets or sets the amount in which the GIF image loops.
-    /// </summary>
-    public IterationCount IterationCount
-    {
-        get => GetValue(IterationCountProperty);
-        set => SetValue(IterationCountProperty, value);
-    }
-
-    static GifImage()
-    {
-        AffectsRender<GifImage>(SourceProperty,
-            StretchProperty,
-            StretchDirectionProperty,
-            WidthProperty,
-            HeightProperty);
-
-        AffectsMeasure<GifImage>(SourceProperty,
-            StretchProperty,
-            StretchDirectionProperty,
-            WidthProperty,
-            HeightProperty);
-    }
-
-    private Size GetGifSize()
-    {
-        return new Size(_gifWidth, _gifHeight);
-    }
-
-    /// <summary>
-    /// Measures the control.
-    /// </summary>
-    /// <param name="availableSize">The available size.</param>
-    /// <returns>The desired size of the control.</returns>
-    protected override Size MeasureOverride(Size availableSize)
-    {
-        return Stretch.CalculateSize(availableSize, GetGifSize(), StretchDirection);
-    }
-
-    /// <inheritdoc/>
-    protected override Size ArrangeOverride(Size finalSize)
-    {
-        var sourceSize = GetGifSize();
-        var result = Stretch.CalculateSize(finalSize, sourceSize);
-        return result;
-    }
-
-    /// <inheritdoc />
-    protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
-    {
-        base.OnAttachedToVisualTree(e);
-
-        InitializeGif();
-    }
-
-    /// <inheritdoc /> 
-    protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
-    {
-        base.OnPropertyChanged(change);
-        var avProp = change.Property;
-
-        if (avProp == SourceProperty)
-        {
-            InitializeGif();
-        }
-
-        if ((avProp == SourceProperty ||
-             avProp == StretchProperty ||
-             avProp == StretchDirectionProperty ||
-             avProp == IterationCountProperty) && _customVisual is not null)
-        {
-            _customVisual.SendHandlerMessage(
-                new GifDrawPayload(
-                    HandlerCommand.Update,
-                    null,
-                    GetGifSize(),
-                    Bounds.Size,
-                    Stretch,
-                    StretchDirection,
-                    IterationCount));
-        }
-    }
-
-    private void InitializeGif()
-    {
-        Stop();
-        DisposeImpl();
-
-        var elemVisual = ElementComposition.GetElementVisual(this);
-        var compositor = elemVisual?.Compositor;
-
-        if (compositor is null)
-        {
-            return;
-        }
-
-        _customVisual = compositor.CreateCustomVisual(new GifCompositionCustomVisualHandler());
-
-        ElementComposition.SetElementChildVisual(this, _customVisual);
-
-        LayoutUpdated += OnLayoutUpdated;
-
-        _customVisual.Size = new Vector2((float)Bounds.Size.Width, (float)Bounds.Size.Height);
-
-        using var stream = AssetLoader.Open(Source);
-        using var tempGifDecoder = new GifDecoder(stream, CancellationToken.None);
-        _gifHeight = tempGifDecoder.Size.Height;
-        _gifWidth = tempGifDecoder.Size.Width;
-
-        _customVisual?.SendHandlerMessage(
-            new GifDrawPayload(
-                HandlerCommand.Start,
-                Source,
-                GetGifSize(),
-                Bounds.Size,
-                Stretch,
-                StretchDirection,
-                IterationCount));
-
-        InvalidateVisual();
-    }
-
-    /// <inheritdoc />
-    protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
-    {
-        base.OnDetachedFromVisualTree(e);
-        LayoutUpdated -= OnLayoutUpdated;
-
-        Stop();
-        DisposeImpl();
-    }
-
-
-    private void OnLayoutUpdated(object? sender, EventArgs e)
-    {
-        if (_customVisual == null)
-        {
-            return;
-        }
-
-        _customVisual.Size = new Vector2((float)Bounds.Size.Width, (float)Bounds.Size.Height);
-
-        _customVisual.SendHandlerMessage(
-            new GifDrawPayload(
-                HandlerCommand.Update,
-                null,
-                GetGifSize(),
-                Bounds.Size,
-                Stretch,
-                StretchDirection,
-                IterationCount));
-    }
-
-    private void Stop()
-    {
-        _customVisual?.SendHandlerMessage(new GifDrawPayload(HandlerCommand.Stop));
-    }
-
-    private void DisposeImpl()
-    {
-        _customVisual?.SendHandlerMessage(new GifDrawPayload(HandlerCommand.Dispose));
-        _customVisual = null;
-    }
-}
diff --git a/Avalonia.Labs.Gif/GifInstance.cs b/Avalonia.Labs.Gif/GifInstance.cs
deleted file mode 100644
index 05fed9e..0000000
--- a/Avalonia.Labs.Gif/GifInstance.cs
+++ /dev/null
@@ -1,128 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using Avalonia.Animation;
-using Avalonia.Labs.Gif.Decoding;
-using Avalonia.Media.Imaging;
-using Avalonia.Platform;
-
-namespace Avalonia.Labs.Gif;
-
-internal class GifInstance : IDisposable
-{
-    public IterationCount IterationCount { get; set; }
-    private readonly GifDecoder _gifDecoder;
-    private readonly WriteableBitmap? _targetBitmap;
-    private TimeSpan _totalTime;
-    private readonly List<TimeSpan>? _frameTimes;
-    private uint _iterationCount;
-    private int _currentFrameIndex;
-
-    private CancellationTokenSource CurrentCts { get; }
-
-    internal GifInstance(object newValue) : this(newValue switch
-    {
-        Stream s => s, 
-        _ => throw new InvalidDataException("Unsupported source object")
-    })
-    {
-    }
-    
-    public GifInstance(Uri uri) : this(AssetLoader.Open(uri))
-    {
-    }
-
-    private GifInstance(Stream currentStream)
-    {
-        if (!currentStream.CanSeek)
-            throw new InvalidDataException("The provided stream is not seekable.");
-
-        if (!currentStream.CanRead)
-            throw new InvalidOperationException("Can't read the stream provided.");
-
-        currentStream.Seek(0, SeekOrigin.Begin);
-
-        CurrentCts = new CancellationTokenSource();
-
-        _gifDecoder = new GifDecoder(currentStream, CurrentCts.Token);
-
-        if (_gifDecoder.Header is null)
-            return;
-
-        var pixSize = new PixelSize(_gifDecoder.Header.Dimensions.Width, _gifDecoder.Header.Dimensions.Height);
-
-        _targetBitmap = new WriteableBitmap(pixSize, new Vector(96, 96), PixelFormat.Bgra8888, AlphaFormat.Opaque);
-        GifPixelSize = pixSize;
-
-        _totalTime = TimeSpan.Zero;
-
-        _frameTimes = _gifDecoder._frames.Select(frame =>
-        {
-            _totalTime = _totalTime.Add(frame.FrameDelay);
-            return _totalTime;
-        }).ToList();
-
-        _gifDecoder.RenderFrame(0, _targetBitmap);
-    }
-
-    public PixelSize GifPixelSize { get; }
-    private bool _isDisposed;
-
-    public void Dispose()
-    {
-        if (_isDisposed) return;
-
-        GC.SuppressFinalize(this);
-
-        _isDisposed = true;
-        CurrentCts.Cancel();
-        _targetBitmap?.Dispose();
-    }
-
-    public WriteableBitmap? ProcessFrameTime(TimeSpan elapsed)
-    {
-        if (!IterationCount.IsInfinite && _iterationCount > IterationCount.Value)
-        {
-            return null;
-        }
-
-        if (CurrentCts.IsCancellationRequested)
-        {
-            return null;
-        }
-
-        if (_frameTimes is null)
-            return null;
-
-        var totalTicks = _totalTime.Ticks;
-
-        if (totalTicks == 0)
-        {
-            return ProcessFrameIndex(0);
-        }
-
-
-        var elapsedTicks = elapsed.Ticks;
-        var timeModulus = TimeSpan.FromTicks(elapsedTicks % totalTicks);
-        var targetFrame = _frameTimes.FirstOrDefault(x => timeModulus < x);
-        var currentFrame = _frameTimes.IndexOf(targetFrame);
-        if (currentFrame == -1) currentFrame = 0;
-
-        if (_currentFrameIndex == currentFrame)
-            return _targetBitmap;
-
-        _iterationCount = (uint)(elapsedTicks / totalTicks);
-
-        return ProcessFrameIndex(currentFrame);
-    }
-
-    private WriteableBitmap? ProcessFrameIndex(int frameIndex)
-    {
-        _gifDecoder.RenderFrame(frameIndex, _targetBitmap);
-        _currentFrameIndex = frameIndex;
-
-        return _targetBitmap;
-    }
-}
diff --git a/Avalonia.Labs.Gif/HandlerCommand.cs b/Avalonia.Labs.Gif/HandlerCommand.cs
deleted file mode 100644
index 3227730..0000000
--- a/Avalonia.Labs.Gif/HandlerCommand.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Avalonia.Labs.Gif;
-
-internal enum HandlerCommand
-{
-    Start,
-    Stop,
-    Update,
-    Dispose
-}
\ No newline at end of file
diff --git a/Blacklight.Desktop/Blacklight.Desktop.csproj b/Blacklight.Desktop/Blacklight.Desktop.csproj
index aeb91b8..c9947ee 100644
--- a/Blacklight.Desktop/Blacklight.Desktop.csproj
+++ b/Blacklight.Desktop/Blacklight.Desktop.csproj
@@ -21,5 +21,9 @@
     <ItemGroup>
         <ProjectReference Include="..\Blacklight\Blacklight.csproj" />
     </ItemGroup>
+    
+    <PropertyGroup>
+        <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+    </PropertyGroup>
 
 </Project>
diff --git a/Blacklight.Desktop/Properties/AssemblyInfo.cs b/Blacklight.Desktop/Properties/AssemblyInfo.cs
index ce09e15..6352926 100644
--- a/Blacklight.Desktop/Properties/AssemblyInfo.cs
+++ b/Blacklight.Desktop/Properties/AssemblyInfo.cs
@@ -2,4 +2,5 @@
 
 [assembly: AssemblyVersion("0.0.0.0")]
 [assembly: AssemblyFileVersion("0.0.0.0")]
-[assembly: AssemblyInformationalVersion("0.0.0.0")]
\ No newline at end of file
+[assembly: AssemblyInformationalVersion("0.0.0.0")]
+[assembly: AssemblyCompany("015")]
\ No newline at end of file
diff --git a/Blacklight.sln b/Blacklight.sln
index de94322..84453fd 100644
--- a/Blacklight.sln
+++ b/Blacklight.sln
@@ -6,8 +6,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blacklight.Desktop", "Black
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lightquark.NET", "Lightquark.NET\Lightquark.NET.csproj", "{354D4E75-A2CE-46D0-BB81-778ADA819951}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Labs.Gif", "Avalonia.Labs.Gif\Avalonia.Labs.Gif.csproj", "{354D4E75-A2CE-46D0-BB81-778ADADA9951}"
-EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -26,7 +24,5 @@ Global
 		{354D4E75-A2CE-46D0-BB81-778ADA819951}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{354D4E75-A2CE-46D0-BB81-778ADA819951}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{354D4E75-A2CE-46D0-BB81-778ADA819951}.Release|Any CPU.Build.0 = Release|Any CPU
-		{354D4E75-A2CE-46D0-BB81-778ADADA9951}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{354D4E75-A2CE-46D0-BB81-778ADADA9951}.Debug|Any CPU.Build.0 = Debug|Any CPU
 	EndGlobalSection
 EndGlobal
diff --git a/Blacklight/Blacklight.csproj b/Blacklight/Blacklight.csproj
index f1de522..a0cadd8 100644
--- a/Blacklight/Blacklight.csproj
+++ b/Blacklight/Blacklight.csproj
@@ -14,6 +14,7 @@
     <ItemGroup>
         <PackageReference Include="Avalonia" Version="11.2.5" />
         <PackageReference Include="Avalonia.HtmlRenderer" Version="11.0.0" />
+        <PackageReference Include="Avalonia.Labs.Gif" Version="11.2.0" />
         <PackageReference Include="Avalonia.Svg.Skia" Version="11.2.0.2" />
         <PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.5" />
         <PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.5" />
@@ -42,7 +43,6 @@
 
 
     <ItemGroup>
-      <ProjectReference Include="..\Avalonia.Labs.Gif\Avalonia.Labs.Gif.csproj" />
       <ProjectReference Include="..\Lightquark.NET\Lightquark.NET.csproj" />
     </ItemGroup>
 </Project>
-- 
GitLab