CustomVisualHandler.cs 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. using Avalonia;
  2. using Avalonia.Logging;
  3. using Avalonia.Media;
  4. using Avalonia.Rendering.Composition;
  5. namespace PicView.Avalonia.AnimatedImage;
  6. public class CustomVisualHandler : CompositionCustomVisualHandler
  7. {
  8. private TimeSpan _animationElapsed;
  9. private TimeSpan? _lastServerTime;
  10. private IGifInstance? _currentInstance;
  11. private bool _running;
  12. public static readonly object StopMessage = new(),
  13. StartMessage = new();
  14. public override void OnMessage(object message)
  15. {
  16. if (message == StartMessage)
  17. {
  18. _running = true;
  19. _lastServerTime = null;
  20. RegisterForNextAnimationFrameUpdate();
  21. }
  22. else if (message == StopMessage)
  23. {
  24. _running = false;
  25. }
  26. else if (message is IGifInstance instance)
  27. {
  28. _currentInstance?.Dispose();
  29. _currentInstance = instance;
  30. }
  31. }
  32. public override void OnAnimationFrameUpdate()
  33. {
  34. if (!_running)
  35. return;
  36. Invalidate();
  37. RegisterForNextAnimationFrameUpdate();
  38. }
  39. public override void OnRender(ImmediateDrawingContext drawingContext)
  40. {
  41. if (_running)
  42. {
  43. if (_lastServerTime.HasValue)
  44. _animationElapsed += (CompositionNow - _lastServerTime.Value);
  45. _lastServerTime = CompositionNow;
  46. }
  47. try
  48. {
  49. if (_currentInstance is null || _currentInstance.IsDisposed)
  50. return;
  51. var bitmap = _currentInstance.ProcessFrameTime(_animationElapsed);
  52. if (bitmap is not null)
  53. {
  54. drawingContext.DrawBitmap(
  55. bitmap,
  56. new Rect(_currentInstance.GifPixelSize.ToSize(1)),
  57. GetRenderBounds()
  58. );
  59. }
  60. }
  61. catch (Exception e)
  62. {
  63. Logger.Sink?.Log(LogEventLevel.Error, "GifImage Renderer ", this, e.ToString());
  64. }
  65. }
  66. }