flabbet 1 рік тому
батько
коміт
243d8212ac
44 змінених файлів з 0 додано та 1902 видалено
  1. 0 15
      src/AvaloniaGif/AvaloniaGif.csproj
  2. 0 10
      src/AvaloniaGif/BgWorkerCommand.cs
  3. 0 12
      src/AvaloniaGif/BgWorkerState.cs
  4. 0 10
      src/AvaloniaGif/Decoding/BlockTypes.cs
  5. 0 8
      src/AvaloniaGif/Decoding/ExtensionType.cs
  6. 0 10
      src/AvaloniaGif/Decoding/FrameDisposal.cs
  7. 0 36
      src/AvaloniaGif/Decoding/GifColor.cs
  8. 0 658
      src/AvaloniaGif/Decoding/GifDecoder.cs
  9. 0 17
      src/AvaloniaGif/Decoding/GifFrame.cs
  10. 0 19
      src/AvaloniaGif/Decoding/GifHeader.cs
  11. 0 45
      src/AvaloniaGif/Decoding/GifRect.cs
  12. 0 8
      src/AvaloniaGif/Decoding/GifRepeatBehavior.cs
  13. 0 28
      src/AvaloniaGif/Decoding/InvalidGifStreamException.cs
  14. 0 28
      src/AvaloniaGif/Decoding/LzwDecompressionException.cs
  15. 0 82
      src/AvaloniaGif/Extensions/StreamExtensions.cs
  16. 0 228
      src/AvaloniaGif/GifImage.cs
  17. 0 154
      src/AvaloniaGif/GifInstance.cs
  18. 0 25
      src/AvaloniaGif/InvalidGifStreamException.cs
  19. 0 13
      src/PixiEditor.Common/PixiEditor.Common.csproj
  20. BIN
      src/PixiEditor.Extensions.Wasm/build/win-x64/PixiEditor.Extensions.MSPackageBuilder.dll
  21. 0 8
      src/PixiEditorTests/ApplicationCollection.cs
  22. 0 12
      src/PixiEditorTests/ApplicationFixture.cs
  23. 0 56
      src/PixiEditorTests/PixiEditorTests.csproj
  24. 0 11
      src/SampleExtension.LayoutBuilder/ButtonTextElement.cs
  25. 0 23
      src/SampleExtension.LayoutBuilder/ButtonTextElementState.cs
  26. 0 25
      src/SampleExtension.LayoutBuilder/SampleExtension.LayoutBuilder.csproj
  27. 0 22
      src/SampleExtension.LayoutBuilder/SampleExtension.cs
  28. 0 30
      src/SampleExtension.LayoutBuilder/extension.json
  29. 0 3
      src/SampleExtension/Localization/en.json
  30. 0 3
      src/SampleExtension/Localization/pixiLang.json
  31. 0 27
      src/SampleExtension/SampleExtension.cs
  32. 0 27
      src/SampleExtension/SampleExtension.csproj
  33. 0 20
      src/SampleExtension/TestPaletteDataSource.cs
  34. 0 44
      src/SampleExtension/extension.json
  35. 0 21
      src/WasmRuntimeTest/ConsoleLogger.cs
  36. 0 5
      src/WasmRuntimeTest/Program.cs
  37. 0 15
      src/WasmRuntimeTest/WasmRuntimeTest.csproj
  38. 0 11
      src/WasmSampleExtension/ButtonTextElement.cs
  39. 0 21
      src/WasmSampleExtension/ButtonTextElementState.cs
  40. 0 9
      src/WasmSampleExtension/Program.cs
  41. 0 36
      src/WasmSampleExtension/SampleExtension.cs
  42. 0 25
      src/WasmSampleExtension/WasmSampleExtension.csproj
  43. 0 30
      src/WasmSampleExtension/extension.json
  44. 0 12
      src/WasmSampleExtension/nuget.config

+ 0 - 15
src/AvaloniaGif/AvaloniaGif.csproj

@@ -1,15 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-	<PropertyGroup>
-		<TargetFramework>netstandard2.1</TargetFramework>
-		<LangVersion>latest</LangVersion> 
-		<AllowUnsafeBlocks>true</AllowUnsafeBlocks> 
-		<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
-  </PropertyGroup>
-  <ItemGroup>
-    <InternalsVisibleTo Include="AvaloniaGif.Test" />
-  </ItemGroup>
-  <ItemGroup>
-    <PackageReference Include="Avalonia" Version="11.0.0-preview7" />
-  </ItemGroup>
-
-</Project>

+ 0 - 10
src/AvaloniaGif/BgWorkerCommand.cs

@@ -1,10 +0,0 @@
-namespace AvaloniaGif
-{
-    internal enum BgWorkerCommand
-    {
-        Null,
-        Play,
-        Pause,
-        Dispose
-    }
-}

+ 0 - 12
src/AvaloniaGif/BgWorkerState.cs

@@ -1,12 +0,0 @@
-namespace AvaloniaGif
-{
-    internal enum BgWorkerState
-    {
-        Null,
-        Start,
-        Running,
-        Paused,
-        Complete,
-        Dispose
-    }
-}

+ 0 - 10
src/AvaloniaGif/Decoding/BlockTypes.cs

@@ -1,10 +0,0 @@
-namespace AvaloniaGif.Decoding
-{
-    internal enum BlockTypes
-    {
-        EMPTY = 0,
-        EXTENSION = 0x21,
-        IMAGE_DESCRIPTOR = 0x2C,
-        TRAILER = 0x3B,
-    }
-}

+ 0 - 8
src/AvaloniaGif/Decoding/ExtensionType.cs

@@ -1,8 +0,0 @@
-namespace AvaloniaGif.Decoding
-{
-    internal enum ExtensionType
-    {
-        GRAPHICS_CONTROL = 0xF9,
-        APPLICATION = 0xFF
-    }
-}

+ 0 - 10
src/AvaloniaGif/Decoding/FrameDisposal.cs

@@ -1,10 +0,0 @@
-namespace AvaloniaGif.Decoding
-{
-    public enum FrameDisposal
-    {
-        Unknown = 0,
-        Leave = 1,
-        Background = 2,
-        Restore = 3
-    }
-}

+ 0 - 36
src/AvaloniaGif/Decoding/GifColor.cs

@@ -1,36 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace AvaloniaGif
-{
-    [StructLayout(LayoutKind.Explicit)]
-    public 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;
-        }
-    }
-}

+ 0 - 658
src/AvaloniaGif/Decoding/GifDecoder.cs

@@ -1,658 +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;
-using Avalonia.Media.Imaging;
-using static AvaloniaGif.Extensions.StreamExtensions;
-
-namespace AvaloniaGif.Decoding
-{
-    public sealed class GifDecoder : IDisposable
-    {
-        private static readonly ReadOnlyMemory<byte> G87AMagic
-            = Encoding.ASCII.GetBytes("GIF87a").AsMemory();
-
-        private static readonly ReadOnlyMemory<byte> G89AMagic
-            = Encoding.ASCII.GetBytes("GIF89a").AsMemory();
-
-        private static readonly ReadOnlyMemory<byte> NetscapeMagic
-            = Encoding.ASCII.GetBytes("NETSCAPE2.0").AsMemory();
-
-        private static readonly TimeSpan FrameDelayThreshold = TimeSpan.FromMilliseconds(10);
-        private static readonly TimeSpan FrameDelayDefault = TimeSpan.FromMilliseconds(100);
-        private static readonly GifColor TransparentColor = new(0, 0, 0, 0);
-        private static readonly int MaxTempBuf = 768;
-        private static readonly int MaxStackSize = 4096;
-        private static readonly int MaxBits = 4097;
-
-        private readonly Stream _fileStream;
-        private readonly CancellationToken _currentCtsToken;
-        private readonly bool _hasFrameBackups;
-
-        private int _gctSize, _bgIndex, _prevFrame = -1, _backupFrame = -1;
-        private bool _gctUsed;
-
-        private GifRect _gifDimensions;
-
-        // private ulong _globalColorTable;
-        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; }
-
-        public readonly List<GifFrame> Frames = new();
-
-        public PixelSize Size => new PixelSize(Header.Dimensions.Width, Header.Dimensions.Height);
-
-        public GifDecoder(Stream fileStream, CancellationToken currentCtsToken)
-        {
-            _fileStream = fileStream;
-            _currentCtsToken = currentCtsToken;
-
-            ProcessHeaderData();
-            ProcessFrameData();
-
-            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 PixCoord(int x, int y) => x + (y * _gifDimensions.Width);
-
-        static readonly (int Start, int Step)[] Pass =
-        {
-            (0, 8),
-            (4, 8),
-            (2, 4),
-            (1, 2)
-        };
-
-        private void ClearImage()
-        {
-            Array.Fill(_bitmapBackBuffer, TransparentColor);
-            //ClearArea(_gifDimensions);
-
-            _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)
-        {
-            var tmpB = ArrayPool<byte>.Shared.Rent(MaxTempBuf);
-
-            var curFrame = Frames[idx];
-            DecompressFrameToIndexBuffer(curFrame, _indexBuf, tmpB);
-
-            if (_hasFrameBackups & curFrame.ShouldBackup)
-            {
-                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.GlobarColorTable;
-
-            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)
-            {
-                for (var i = 0; i < 4; i++)
-                {
-                    var curPass = Pass[i];
-                    var y = curPass.Start;
-                    while (y < cH)
-                    {
-                        DrawRow(y);
-                        y += curPass.Step;
-                    }
-                }
-            }
-            else
-            {
-                for (var i = 0; i < cH; i++)
-                    DrawRow(i);
-            }
-
-            //for (var row = 0; row < cH; row++)
-            void DrawRow(int row)
-            {
-                // Get the starting point of the current row on frame's index stream.
-                var indexOffset = row * cW;
-
-                // Get the target backbuffer offset from the frames coords.
-                var targetOffset = PixCoord(cX, row + cY);
-                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)
-        {
-            for (var y = 0; y < area.Height; y++)
-            {
-                var targetOffset = PixCoord(area.X, y + area.Y);
-                for (var x = 0; x < area.Width; x++)
-                    _bitmapBackBuffer[targetOffset + x] = TransparentColor;
-            }
-        }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private void DecompressFrameToIndexBuffer(GifFrame curFrame, Span<byte> indexSpan, byte[] tempBuf)
-        {
-            _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)
-                                ThrowException();
-                        }
-
-                        while (code >= clear)
-                        {
-                            if (code >= MaxBits || code == _prefixBuf[code])
-                                ThrowException();
-
-                            _pixelStack[top++] = _suffixBuf[code];
-                            code = _prefixBuf[code];
-
-                            if (top == MaxBits)
-                                ThrowException();
-                        }
-
-                        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
-
-            void ThrowException() => 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(G87AMagic[..3].Span))
-                throw new InvalidGifStreamException("Not a GIF stream.");
-
-            if (!(tempBuf[..6].SequenceEqual(G87AMagic.Span) |
-                  tempBuf[..6].SequenceEqual(G89AMagic.Span)))
-                throw new InvalidGifStreamException("Unsupported GIF Version: " +
-                                                    Encoding.ASCII.GetString(tempBuf[..6].ToArray()));
-
-            ProcessScreenDescriptor(tmpB);
-
-            Header = new GifHeader
-            {
-                Dimensions = _gifDimensions,
-                HasGlobalColorTable = _gctUsed,
-                // GlobalColorTableCacheID = _globalColorTable,
-                GlobarColorTable = ProcessColorTable(ref str, tmpB, _gctSize),
-                GlobalColorTableSize = _gctSize,
-                BackgroundColorIndex = _bgIndex,
-                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);
-            _bgIndex = _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;
-
-            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.IMAGE_DESCRIPTOR:
-                        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.GRAPHICS_CONTROL:
-
-                    _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 <= FrameDelayThreshold)
-                        currentFrame.FrameDelay = FrameDelayDefault;
-
-                    currentFrame.TransparentColorIndex = tempBuf[3];
-                    break;
-
-                case ExtensionType.APPLICATION:
-                    var blockLen = _fileStream.ReadBlock(tempBuf);
-                    var _ = tempBuf.AsSpan(0, blockLen);
-                    var blockHeader = tempBuf.AsSpan(0, NetscapeMagic.Length);
-
-                    if (blockHeader.SequenceEqual(NetscapeMagic.Span))
-                    {
-                        var count = 1;
-
-                        while (count > 0)
-                            count = _fileStream.ReadBlock(tempBuf);
-
-                        var iterationCount = SpanToShort(tempBuf.AsSpan(1));
-
-                        Header.Iterations = iterationCount;
-                    }
-                    else
-                        _fileStream.SkipBlocks(tempBuf);
-
-                    break;
-
-                default:
-                    _fileStream.SkipBlocks(tempBuf);
-                    break;
-            }
-        }
-    }
-}

+ 0 - 17
src/AvaloniaGif/Decoding/GifFrame.cs

@@ -1,17 +0,0 @@
-using System;
-
-namespace AvaloniaGif.Decoding
-{
-    public 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;
-    }
-}

+ 0 - 19
src/AvaloniaGif/Decoding/GifHeader.cs

@@ -1,19 +0,0 @@
-// Licensed under the MIT License.
-// Copyright (C) 2018 Jumar A. Macato, All Rights Reserved.
-
-namespace AvaloniaGif.Decoding
-{
-    public class GifHeader
-    {
-        public bool HasGlobalColorTable;
-        public int GlobalColorTableSize;
-        public ulong GlobalColorTableCacheID;
-        public int BackgroundColorIndex;
-        public long HeaderSize;
-        internal int Iterations = -1;
-        public GifRepeatBehavior IterationCount;
-        public GifRect Dimensions;
-        private GifColor[] _globarColorTable;
-        public GifColor[] GlobarColorTable;
-    }
-}

+ 0 - 45
src/AvaloniaGif/Decoding/GifRect.cs

@@ -1,45 +0,0 @@
-namespace AvaloniaGif.Decoding
-{
-    public 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();
-        }
-    }
-}

+ 0 - 8
src/AvaloniaGif/Decoding/GifRepeatBehavior.cs

@@ -1,8 +0,0 @@
-namespace AvaloniaGif.Decoding
-{
-    public class GifRepeatBehavior
-    {
-        public bool LoopForever { get; set; }
-        public int? Count { get; set; }
-    }
-}

+ 0 - 28
src/AvaloniaGif/Decoding/InvalidGifStreamException.cs

@@ -1,28 +0,0 @@
-// Licensed under the MIT License.
-// Copyright (C) 2018 Jumar A. Macato, All Rights Reserved.
-
-using System;
-using System.Runtime.Serialization;
-
-namespace AvaloniaGif.Decoding
-{
-    [Serializable]
-    public class InvalidGifStreamException : Exception
-    {
-        public InvalidGifStreamException()
-        {
-        }
-
-        public InvalidGifStreamException(string message) : base(message)
-        {
-        }
-
-        public InvalidGifStreamException(string message, Exception innerException) : base(message, innerException)
-        {
-        }
-
-        protected InvalidGifStreamException(SerializationInfo info, StreamingContext context) : base(info, context)
-        {
-        }
-    }
-}

+ 0 - 28
src/AvaloniaGif/Decoding/LzwDecompressionException.cs

@@ -1,28 +0,0 @@
-// Licensed under the MIT License.
-// Copyright (C) 2018 Jumar A. Macato, All Rights Reserved.
-
-using System;
-using System.Runtime.Serialization;
-
-namespace AvaloniaGif.Decoding
-{
-    [Serializable]
-    public class LzwDecompressionException : Exception
-    {
-        public LzwDecompressionException()
-        {
-        }
-
-        public LzwDecompressionException(string message) : base(message)
-        {
-        }
-
-        public LzwDecompressionException(string message, Exception innerException) : base(message, innerException)
-        {
-        }
-
-        protected LzwDecompressionException(SerializationInfo info, StreamingContext context) : base(info, context)
-        {
-        }
-    }
-}

+ 0 - 82
src/AvaloniaGif/Extensions/StreamExtensions.cs

@@ -1,82 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Runtime.CompilerServices;
-
-namespace AvaloniaGif.Extensions
-{
-    [DebuggerStepThrough]
-    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;
-        }
-    }
-}

+ 0 - 228
src/AvaloniaGif/GifImage.cs

@@ -1,228 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.IO;
-using Avalonia;
-using Avalonia.Animation;
-using Avalonia.Controls;
-using Avalonia.Media;
-using Avalonia.Media.Imaging;
-using Avalonia.Threading;
-
-namespace AvaloniaGif
-{
-    public class GifImage : Control
-    {
-        public static readonly StyledProperty<string> SourceUriRawProperty =
-            AvaloniaProperty.Register<GifImage, string>("SourceUriRaw");
-
-        public static readonly StyledProperty<Uri> SourceUriProperty =
-            AvaloniaProperty.Register<GifImage, Uri>("SourceUri");
-
-        public static readonly StyledProperty<Stream> SourceStreamProperty =
-            AvaloniaProperty.Register<GifImage, Stream>("SourceStream");
-
-        public static readonly StyledProperty<IterationCount> IterationCountProperty =
-            AvaloniaProperty.Register<GifImage, IterationCount>("IterationCount", IterationCount.Infinite);
-
-        private GifInstance gifInstance;
-
-        public static readonly StyledProperty<bool> AutoStartProperty =
-            AvaloniaProperty.Register<GifImage, bool>("AutoStart");
-
-        public static readonly StyledProperty<StretchDirection> StretchDirectionProperty =
-            AvaloniaProperty.Register<GifImage, StretchDirection>("StretchDirection");
-
-        public static readonly StyledProperty<Stretch> StretchProperty =
-            AvaloniaProperty.Register<GifImage, Stretch>("Stretch");
-
-        private RenderTargetBitmap backingRTB;
-        private bool _hasNewSource;
-        private object? _newSource;
-        private Stopwatch _stopwatch;
-
-        static GifImage()
-        {
-            SourceUriRawProperty.Changed.Subscribe(SourceChanged);
-            SourceUriProperty.Changed.Subscribe(SourceChanged);
-            SourceStreamProperty.Changed.Subscribe(SourceChanged);
-            IterationCountProperty.Changed.Subscribe(IterationCountChanged);
-            AutoStartProperty.Changed.Subscribe(AutoStartChanged);
-            AffectsRender<GifImage>(SourceStreamProperty, SourceUriProperty, SourceUriRawProperty, StretchProperty);
-            AffectsArrange<GifImage>(SourceStreamProperty, SourceUriProperty, SourceUriRawProperty, StretchProperty);
-            AffectsMeasure<GifImage>(SourceStreamProperty, SourceUriProperty, SourceUriRawProperty, StretchProperty);
-        }
-
-        public string SourceUriRaw
-        {
-            get => GetValue(SourceUriRawProperty);
-            set => SetValue(SourceUriRawProperty, value);
-        }
-
-        public Uri SourceUri
-        {
-            get => GetValue(SourceUriProperty);
-            set => SetValue(SourceUriProperty, value);
-        }
-
-        public Stream SourceStream
-        {
-            get => GetValue(SourceStreamProperty);
-            set => SetValue(SourceStreamProperty, value);
-        }
-
-        public IterationCount IterationCount
-        {
-            get => GetValue(IterationCountProperty);
-            set => SetValue(IterationCountProperty, value);
-        }
-
-        public bool AutoStart
-        {
-            get => GetValue(AutoStartProperty);
-            set => SetValue(AutoStartProperty, value);
-        }
-
-        public StretchDirection StretchDirection
-        {
-            get => GetValue(StretchDirectionProperty);
-            set => SetValue(StretchDirectionProperty, value);
-        }
-
-        public Stretch Stretch
-        {
-            get => GetValue(StretchProperty);
-            set => SetValue(StretchProperty, value);
-        }
-
-        private static void AutoStartChanged(AvaloniaPropertyChangedEventArgs e)
-        {
-            var image = e.Sender as GifImage;
-            if (image == null)
-                return;
-        }
-
-        private static void IterationCountChanged(AvaloniaPropertyChangedEventArgs e)
-        {
-            var image = e.Sender as GifImage;
-            if (image is null || e.NewValue is not IterationCount iterationCount)
-                return;
-
-            image.IterationCount = iterationCount;
-        }
-
-        public override void Render(DrawingContext context)
-        {
-            Dispatcher.UIThread.Post(InvalidateMeasure, DispatcherPriority.Background);
-            Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
-            
-            if (_hasNewSource)
-            {
-                StopAndDispose();
-                gifInstance = new GifInstance(_newSource);
-                gifInstance.IterationCount = IterationCount;
-                backingRTB = new RenderTargetBitmap(gifInstance.GifPixelSize, new Vector(96, 96));
-                _hasNewSource = false;
-
-                _stopwatch ??= new Stopwatch();
-                _stopwatch.Reset();
-
-
-                return;
-            }
-
-            if (gifInstance is null || (gifInstance.CurrentCts?.IsCancellationRequested ?? true))
-            {
-                return;
-            }
-
-            if (!_stopwatch.IsRunning)
-            {
-                _stopwatch.Start();
-            }
-
-            var currentFrame = gifInstance.ProcessFrameTime(_stopwatch.Elapsed);
-
-            if (currentFrame is { } source && backingRTB is { })
-            {
-                using var ctx = backingRTB.CreateDrawingContext();
-                var ts = new Rect(source.Size);
-                ctx.DrawBitmap(source.PlatformImpl, 1, ts, ts);
-            }
-
-            if (backingRTB is not null && Bounds.Width > 0 && Bounds.Height > 0)
-            {
-                var viewPort = new Rect(Bounds.Size);
-                var sourceSize = backingRTB.Size;
-
-                var scale = Stretch.CalculateScaling(Bounds.Size, sourceSize, StretchDirection);
-                var scaledSize = sourceSize * scale;
-                var destRect = viewPort
-                    .CenterRect(new Rect(scaledSize))
-                    .Intersect(viewPort);
-
-                var sourceRect = new Rect(sourceSize)
-                    .CenterRect(new Rect(destRect.Size / scale));
-
-                var interpolationMode = RenderOptions.GetBitmapInterpolationMode(this);
-
-                context.DrawImage(backingRTB, sourceRect, destRect, interpolationMode);
-            }
-        }
-
-        /// <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)
-        {
-            var source = backingRTB;
-            var result = new Size();
-
-            if (source != null)
-            {
-                result = Stretch.CalculateSize(availableSize, source.Size, StretchDirection);
-            }
-
-            return result;
-        }
-
-        /// <inheritdoc/>
-        protected override Size ArrangeOverride(Size finalSize)
-        {
-            var source = backingRTB;
-
-            if (source != null)
-            {
-                var sourceSize = source.Size;
-                var result = Stretch.CalculateSize(finalSize, sourceSize);
-                return result;
-            }
-
-            return new Size();
-        }
-
-        public void StopAndDispose()
-        {
-            gifInstance?.Dispose();
-            backingRTB?.Dispose();
-        }
-
-        private static void SourceChanged(AvaloniaPropertyChangedEventArgs e)
-        {
-            var image = e.Sender as GifImage;
-
-            if (image == null)
-                return;
-
-            if (e.NewValue is null)
-            {
-                return;
-            }
-
-            image._hasNewSource = true;
-            image._newSource = e.NewValue;
-            Dispatcher.UIThread.Post(image.InvalidateVisual, DispatcherPriority.Background);
-        }
-    }
-}

+ 0 - 154
src/AvaloniaGif/GifInstance.cs

@@ -1,154 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using Avalonia;
-using Avalonia.Animation;
-using Avalonia.Media.Imaging;
-using Avalonia.Platform;
-using AvaloniaGif.Decoding;
-using JetBrains.Annotations;
-
-namespace AvaloniaGif
-{
-    public class GifInstance : IDisposable
-    {
-        public IterationCount IterationCount { get; set; }
-        public bool AutoStart { get; private set; } = true;
-        private readonly GifDecoder _gifDecoder;
-        private readonly WriteableBitmap _targetBitmap;
-        private TimeSpan _totalTime;
-        private readonly List<TimeSpan> _frameTimes;
-        private uint _iterationCount;
-        private int _currentFrameIndex;
-        private readonly List<ulong> _colorTableIdList;
-
-        public CancellationTokenSource CurrentCts { get; }
-
-        internal GifInstance(object newValue) : this(newValue switch
-        {
-            Stream s => s,
-            Uri u => GetStreamFromUri(u),
-            string str => GetStreamFromString(str),
-            _ => throw new InvalidDataException("Unsupported source object")
-        })
-        { }
-
-        public GifInstance(string uri) : this(GetStreamFromString(uri))
-        { }
-
-        public GifInstance(Uri uri) : this(GetStreamFromUri(uri))
-        { }
-
-        public 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);
-            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);
-
-            // Save the color table cache ID's to refresh them on cache while
-            // // the image is either stopped/paused.
-            // _colorTableIdList = _gifDecoder.Frames
-            //     .Where(p => p.IsLocalColorTableUsed)
-            //     .Select(p => p.LocalColorTableCacheID)
-            //     .ToList();
-
-            // if (_gifDecoder.Header.HasGlobalColorTable)
-            //     _colorTableIdList.Add(_gifDecoder.Header.GlobalColorTableCacheID);
-        }
-
-        private static Stream GetStreamFromString(string str)
-        {
-            if (!Uri.TryCreate(str, UriKind.RelativeOrAbsolute, out var res))
-            {
-                throw new InvalidCastException("The string provided can't be converted to URI.");
-            }
-
-            return GetStreamFromUri(res);
-        }
-
-        private static Stream GetStreamFromUri(Uri uri)
-        {
-            var uriString = uri.OriginalString.Trim();
-
-            if (!uriString.StartsWith("resm") && !uriString.StartsWith("avares"))
-                throw new InvalidDataException(
-                    "The URI provided is not currently supported.");
-
-            var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>();
-
-            if (assetLocator is null)
-                throw new InvalidDataException(
-                    "The resource URI was not found in the current assembly.");
-
-            return assetLocator.Open(uri);
-        }
-
-        public int GifFrameCount => _frameTimes.Count;
-
-        public PixelSize GifPixelSize { get; }
-
-        public void Dispose()
-        {
-            CurrentCts.Cancel();
-            _targetBitmap?.Dispose();
-        }
-
-        public WriteableBitmap ProcessFrameTime(TimeSpan stopwatchElapsed)
-        {
-            if (!IterationCount.IsInfinite && _iterationCount > IterationCount.Value)
-            {
-                return null;
-            }
-
-            if (CurrentCts.IsCancellationRequested)
-            {
-                return null;
-            }
-
-            var elapsedTicks = stopwatchElapsed.Ticks;
-            var timeModulus = TimeSpan.FromTicks(elapsedTicks % _totalTime.Ticks);
-            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 / _totalTime.Ticks);
-
-            return ProcessFrameIndex(currentFrame);
-        }
-
-        internal WriteableBitmap ProcessFrameIndex(int frameIndex)
-        {
-            _gifDecoder.RenderFrame(frameIndex, _targetBitmap);
-            _currentFrameIndex = frameIndex;
-
-            return _targetBitmap;
-        }
-    }
-}

+ 0 - 25
src/AvaloniaGif/InvalidGifStreamException.cs

@@ -1,25 +0,0 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace AvaloniaGif
-{
-    [Serializable]
-    internal class InvalidGifStreamException : Exception
-    {
-        public InvalidGifStreamException()
-        {
-        }
-
-        public InvalidGifStreamException(string message) : base(message)
-        {
-        }
-
-        public InvalidGifStreamException(string message, Exception innerException) : base(message, innerException)
-        {
-        }
-
-        protected InvalidGifStreamException(SerializationInfo info, StreamingContext context) : base(info, context)
-        {
-        }
-    }
-}

+ 0 - 13
src/PixiEditor.Common/PixiEditor.Common.csproj

@@ -1,13 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <TargetFramework>net8.0</TargetFramework>
-        <ImplicitUsings>enable</ImplicitUsings>
-        <Nullable>enable</Nullable>
-    </PropertyGroup>
-
-    <ItemGroup>
-      <Folder Include="Exceptions\" />
-    </ItemGroup>
-
-</Project>

BIN
src/PixiEditor.Extensions.Wasm/build/win-x64/PixiEditor.Extensions.MSPackageBuilder.dll


+ 0 - 8
src/PixiEditorTests/ApplicationCollection.cs

@@ -1,8 +0,0 @@
-using Xunit;
-
-namespace PixiEditorTests;
-
-[CollectionDefinition("Application collection")]
-public class ApplicationCollection : ICollectionFixture<ApplicationFixture>
-{
-}

+ 0 - 12
src/PixiEditorTests/ApplicationFixture.cs

@@ -1,12 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-
-namespace PixiEditorTests;
-
-[ExcludeFromCodeCoverage]
-public class ApplicationFixture
-{
-    public ApplicationFixture()
-    {
-
-    }
-}

+ 0 - 56
src/PixiEditorTests/PixiEditorTests.csproj

@@ -1,56 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>net8.0-windows</TargetFramework>
-
-    <IsPackable>false</IsPackable>
-
-    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
-
-    <Platforms>AnyCPU;x64;x86</Platforms>
-
-    <Configurations>Debug;Release;Steam;DevRelease</Configurations>
-  </PropertyGroup>
-
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
-    <DebugType>full</DebugType>
-    <DebugSymbols>true</DebugSymbols>
-  </PropertyGroup>
-
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
-    <DebugType>full</DebugType>
-    <DebugSymbols>true</DebugSymbols>
-  </PropertyGroup>
-
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <DebugType>full</DebugType>
-    <DebugSymbols>true</DebugSymbols>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <None Remove="ModelsTests\IO\CorruptedFile.xaml" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.2">
-      <PrivateAssets>all</PrivateAssets>
-      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
-    </PackageReference>
-    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
-    <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
-    <PackageReference Include="OpenCover" Version="4.7.1221" />
-    <PackageReference Include="xunit" Version="2.4.1" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
-      <PrivateAssets>all</PrivateAssets>
-      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
-    </PackageReference>
-    <PackageReference Include="Xunit.StaFact" Version="1.1.11" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <ProjectReference Include="..\PixiEditor.UpdateModule\PixiEditor.UpdateModule.csproj" />
-    <ProjectReference Include="..\PixiEditor\PixiEditor.csproj" />
-  </ItemGroup>
-
-</Project>

+ 0 - 11
src/SampleExtension.LayoutBuilder/ButtonTextElement.cs

@@ -1,11 +0,0 @@
-using PixiEditor.Extensions.FlyUI.Elements;
-
-namespace SampleExtension.LayoutBuilder;
-
-public class ButtonTextElement : StatefulElement<ButtonTextElementState>
-{
-    public override ButtonTextElementState CreateState()
-    {
-        return new();
-    }
-}

+ 0 - 23
src/SampleExtension.LayoutBuilder/ButtonTextElementState.cs

@@ -1,23 +0,0 @@
-using Avalonia.Controls;
-using PixiEditor.Extensions.CommonApi.FlyUI.Events;
-using PixiEditor.Extensions.FlyUI.Elements;
-using Button = PixiEditor.Extensions.FlyUI.Elements.Button;
-
-namespace SampleExtension.LayoutBuilder;
-
-public class ButtonTextElementState : State
-{
-    public int ClickedTimes { get; private set; } = 0;
-
-    public override LayoutElement BuildElement()
-    {
-        return new Button(
-            onClick: OnClick,
-            child: new Text($"Cassd: {ClickedTimes}"));
-    }
-
-    private void OnClick(ElementEventArgs args)
-    {
-        SetState(() => ClickedTimes++);
-    }
-}

+ 0 - 25
src/SampleExtension.LayoutBuilder/SampleExtension.LayoutBuilder.csproj

@@ -1,25 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <TargetFramework>net8.0</TargetFramework>
-        <ImplicitUsings>enable</ImplicitUsings>
-        <Nullable>enable</Nullable>
-      <OutputPath>..\PixiEditor.AvaloniaUI.Desktop\bin\Debug\net8.0\Extensions\SampleExtension.LayoutBuilder</OutputPath>
-      <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
-    </PropertyGroup>
-
-    <ItemGroup>
-      <ProjectReference Include="..\PixiEditor.Extensions\PixiEditor.Extensions.csproj" />
-    </ItemGroup>
-
-    <ItemGroup>
-      <Content Update="extension.json">
-        <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-      </Content>
-      <None Remove="extension.json" />
-      <Content Include="extension.json">
-        <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-      </Content>
-    </ItemGroup>
-
-</Project>

+ 0 - 22
src/SampleExtension.LayoutBuilder/SampleExtension.cs

@@ -1,22 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Layout;
-using Avalonia.Media;
-using PixiEditor.Extensions;
-using PixiEditor.Extensions.FlyUI.Elements;
-
-namespace SampleExtension.LayoutBuilder;
-
-public class SampleExtension : Extension
-{
-    protected override void OnLoaded()
-    {
-    }
-
-    protected override void OnInitialized()
-    {
-        Layout layout = new Layout(
-            body: new ButtonTextElement());
-
-        Api.Windowing.CreatePopupWindow("Test layout builder", layout.BuildNative()).Show();
-    }
-}

+ 0 - 30
src/SampleExtension.LayoutBuilder/extension.json

@@ -1,30 +0,0 @@
-{
-  "displayName": "Sample Extension 2",
-  "uniqueName": "yourCompany.Samples.SampleExtension2",
-  "description": "Sample extension of LayoutBuilder for PixiEditor",
-  "version": "1.0.0",
-  "author": {
-    "name": "PixiEditor",
-    "email": "[email protected]",
-    "website": "https://pixieditor.net"
-  },
-  "publisher": {
-    "name": "PixiEditor",
-    "email": "[email protected]",
-    "website": "https://pixieditor.net"
-  },
-  "contributors": [
-    {
-      "name": "flabbet",
-      "email": "[email protected]",
-      "website": "https://github.com/flabbet"
-    },
-    {
-      "name": "CPK"
-    }
-  ],
-  "license": "MIT",
-  "categories": [
-    "Extension"
-  ]
-}

+ 0 - 3
src/SampleExtension/Localization/en.json

@@ -1,3 +0,0 @@
-{
-  "SE:DATA_SOURCE_NAME": "Sample Extension"
-}

+ 0 - 3
src/SampleExtension/Localization/pixiLang.json

@@ -1,3 +0,0 @@
-{
-  "NEW_FILE": "New PixiFile"
-}

+ 0 - 27
src/SampleExtension/SampleExtension.cs

@@ -1,27 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Layout;
-using Avalonia.Media;
-using PixiEditor.Extensions;
-using PixiEditor.Extensions.CommonApi.Windowing;
-
-namespace SampleExtension;
-
-public class SampleExtension : Extension
-{
-    protected override void OnLoaded()
-    {
-    }
-
-    protected override void OnInitialized()
-    {
-        var popup = Api.Windowing.CreatePopupWindow("Hello World!", new TextBlock
-        {
-            Text = "Hello World!", Foreground = Brushes.White,
-            HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center
-        });
-        Api.PaletteProvider.RegisterDataSource(new TestPaletteDataSource());
-        popup.ShowDialog();
-
-        Api.Windowing.GetWindow(WindowType.PalettesBrowser).Show();
-    }
-}

+ 0 - 27
src/SampleExtension/SampleExtension.csproj

@@ -1,27 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <TargetFramework>net8.0</TargetFramework>
-        <ImplicitUsings>enable</ImplicitUsings>
-        <Nullable>enable</Nullable>
-      <OutputPath>..\PixiEditor.AvaloniaUI.Desktop\bin\Debug\net8.0\Extensions\SampleExtension</OutputPath>
-      <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
-    </PropertyGroup>
-
-    <ItemGroup>
-      <ProjectReference Include="..\PixiEditor.Extensions\PixiEditor.Extensions.csproj" />
-    </ItemGroup>
-
-    <ItemGroup>
-      <None Remove="package.json" />
-      <Content Include="extension.json">
-        <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-      </Content>
-    </ItemGroup>
-
-  <ItemGroup>
-    <Content Include="Localization\**">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </Content>
-  </ItemGroup>
-</Project>

+ 0 - 20
src/SampleExtension/TestPaletteDataSource.cs

@@ -1,20 +0,0 @@
-using PixiEditor.Extensions.Palettes;
-
-namespace SampleExtension;
-
-public class TestPaletteDataSource : PaletteListDataSource
-{
-    private List<ExtensionPalette> palettes = new();
-
-    public TestPaletteDataSource() : base("SE:DATA_SOURCE_NAME") // SE: prefix (Sample Extension:) helps to avoid key collisions with other extensions
-    {
-        palettes.Add(new ExtensionPalette("Test Palette", new List<PaletteColor> { PaletteColor.Black, PaletteColor.White, }, this));
-    }
-
-    public override Task<List<IPalette>> FetchPaletteList(int startIndex, int items, FilteringSettings filtering)
-    {
-        if(startIndex >= palettes.Count) return Task.FromResult(new List<IPalette>());
-
-        return Task.FromResult(palettes.Skip(startIndex).Take(items).Where(filtering.Filter).Cast<IPalette>().ToList());
-    }
-}

+ 0 - 44
src/SampleExtension/extension.json

@@ -1,44 +0,0 @@
-{
-  "displayName": "Sample Extension 1",
-  "uniqueName": "yourCompany.Samples.SampleExtension",
-  "description": "Sample extension for PixiEditor",
-  "version": "1.0.0",
-  "localization": {
-    "Languages": [
-      {
-        "name": "English",
-        "code": "en",
-        "localeFileName": "Localization/en.json"
-      },
-      {
-        "name": "PixiLang",
-        "code": "px",
-        "localeFileName": "Localization/pixiLang.json"
-      }
-    ]
-  },
-  "author": {
-    "name": "PixiEditor",
-    "email": "[email protected]",
-    "website": "https://pixieditor.net"
-  },
-  "publisher": {
-    "name": "PixiEditor",
-    "email": "[email protected]",
-    "website": "https://pixieditor.net"
-  },
-  "contributors": [
-    {
-      "name": "flabbet",
-      "email": "[email protected]",
-      "website": "https://github.com/flabbet"
-    },
-    {
-      "name": "CPK"
-    }
-  ],
-  "license": "MIT",
-  "categories": [
-    "Extension"
-  ]
-}

+ 0 - 21
src/WasmRuntimeTest/ConsoleLogger.cs

@@ -1,21 +0,0 @@
-using PixiEditor.Extensions.Wasm.Api;
-
-namespace WasmRuntimeTest;
-
-public class ConsoleLogger : ILogger
-{
-    public void Log(string message)
-    {
-        Console.WriteLine(message);
-    }
-
-    public void LogError(string message)
-    {
-        Log(message);
-    }
-
-    public void LogWarning(string message)
-    {
-        Log(message);
-    }
-}

+ 0 - 5
src/WasmRuntimeTest/Program.cs

@@ -1,5 +0,0 @@
-using PixiEditor.Extensions.Wasm;
-using PixiEditor.WasmRuntime;
-
-WasmRuntime runtime = new WasmRuntime();
-runtime.LoadModule(@"C:\Git\PixiEditor\src\WasmSampleExtension\bin\Debug\net8.0\WasmSampleExtension.wasm");

+ 0 - 15
src/WasmRuntimeTest/WasmRuntimeTest.csproj

@@ -1,15 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <OutputType>Exe</OutputType>
-        <TargetFramework>net8.0</TargetFramework>
-        <ImplicitUsings>enable</ImplicitUsings>
-        <Nullable>enable</Nullable>
-    </PropertyGroup>
-
-    <ItemGroup>
-      <ProjectReference Include="..\PixiEditor.Extensions.Wasm\PixiEditor.Extensions.Wasm.csproj" />
-      <ProjectReference Include="..\PixiEditor.WasmRuntime\PixiEditor.WasmRuntime.csproj" />
-    </ItemGroup>
-
-</Project>

+ 0 - 11
src/WasmSampleExtension/ButtonTextElement.cs

@@ -1,11 +0,0 @@
-using PixiEditor.Extensions.Wasm.Api.FlyUI;
-
-namespace WasmSampleExtension;
-
-public class ButtonTextElement : StatefulElement<ButtonTextElementState>
-{
-    public override ButtonTextElementState CreateState()
-    {
-        return new();
-    }
-}

+ 0 - 21
src/WasmSampleExtension/ButtonTextElementState.cs

@@ -1,21 +0,0 @@
-using PixiEditor.Extensions.CommonApi.FlyUI.Events;
-using PixiEditor.Extensions.Wasm.Api.FlyUI;
-
-namespace WasmSampleExtension;
-
-public class ButtonTextElementState : State
-{
-    public int ClickedTimes { get; private set; } = 0;
-
-    public override LayoutElement BuildElement()
-    {
-        return new Button(
-            onClick: OnClick,
-            child: new Text($"Clicked: {ClickedTimes} times"));
-    }
-
-    private void OnClick(ElementEventArgs args)
-    {
-        SetState(() => ClickedTimes++);
-    }
-}

+ 0 - 9
src/WasmSampleExtension/Program.cs

@@ -1,9 +0,0 @@
-namespace WasmSampleExtension;
-
-public static class Program
-{
-    public static void Main(string[] args)
-    {
-
-    }
-}

+ 0 - 36
src/WasmSampleExtension/SampleExtension.cs

@@ -1,36 +0,0 @@
-using System;
-using PixiEditor.Extensions.Wasm;
-using PixiEditor.Extensions.Wasm.Api.FlyUI;
-
-namespace WasmSampleExtension;
-
-public class SampleExtension : WasmExtension
-{
-    public override void OnLoaded()
-    {
-        Api.Logger.Log("WASM SampleExtension loaded!");
-    }
-
-    public override void OnInitialized()
-    {
-        Api.Logger.Log("WASM SampleExtension initialized!");
-
-        Layout layout = new Layout(
-            new Center(
-                child: new ButtonTextElement()
-                )
-            );
-
-        var window = Api.WindowProvider.CreatePopupWindow("WASM SampleExtension", layout);
-        window.Width = 200;
-        window.Height = 200;
-        window.CanResize = false;
-        window.CanMinimize = false;
-        var showTask = window.ShowDialog();
-        showTask.Completed += result =>
-        {
-            Api.Logger.Log($"Show task completed: {result}");
-        };
-    }
-}
-

+ 0 - 25
src/WasmSampleExtension/WasmSampleExtension.csproj

@@ -1,25 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
-    <RuntimeIdentifier>wasi-wasm</RuntimeIdentifier>
-    <OutputType>Exe</OutputType>
-    <PublishTrimmed>true</PublishTrimmed>
-    <WasmSingleFileBundle>true</WasmSingleFileBundle>
-    <OutputPath>..\PixiEditor.AvaloniaUI.Desktop\bin\Debug\net8.0\Extensions</OutputPath>
-  </PropertyGroup>
-
-  <Import Project="..\PixiEditor.Extensions.Wasm\build\PixiEditor.Extensions.Wasm.targets"/>
-  <Import Project="..\PixiEditor.Extensions.Wasm\build\PixiEditor.Extensions.Wasm.props"/>
-
-  <ItemGroup>
-    <ProjectReference Include="..\PixiEditor.Extensions.Wasm\PixiEditor.Extensions.Wasm.csproj" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <None Remove="extension.json" />
-    <Content Include="extension.json">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </Content>
-  </ItemGroup>
-</Project>

+ 0 - 30
src/WasmSampleExtension/extension.json

@@ -1,30 +0,0 @@
-{
-  "displayName": "Sample Extension 2 - WASM",
-  "uniqueName": "yourCompany.Samples.WasmSampleExtension",
-  "description": "Sample WASM extension for PixiEditor",
-  "version": "1.0.0",
-  "author": {
-    "name": "PixiEditor",
-    "email": "[email protected]",
-    "website": "https://pixieditor.net"
-  },
-  "publisher": {
-    "name": "PixiEditor",
-    "email": "[email protected]",
-    "website": "https://pixieditor.net"
-  },
-  "contributors": [
-    {
-      "name": "flabbet",
-      "email": "[email protected]",
-      "website": "https://github.com/flabbet"
-    },
-    {
-      "name": "CPK"
-    }
-  ],
-  "license": "MIT",
-  "categories": [
-    "Extension"
-  ]
-}

+ 0 - 12
src/WasmSampleExtension/nuget.config

@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-  <config>
-    <add key="globalPackagesFolder" value=".packages" />
-  </config>
-  <packageSources>
-    <!--To inherit the global NuGet package sources remove the <clear/> line below -->
-    <clear />
-    <add key="dotnet-experimental" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json" />
-    <add key="nuget" value="https://api.nuget.org/v3/index.json" />
-  </packageSources>
-</configuration>