ImageBrushImpl.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. using Avalonia.Media;
  2. using Avalonia.Rendering.Utilities;
  3. using Avalonia.Utilities;
  4. using SharpDX.Direct2D1;
  5. namespace Avalonia.Direct2D1.Media
  6. {
  7. internal sealed class ImageBrushImpl : BrushImpl
  8. {
  9. private readonly OptionalDispose<Bitmap> _bitmap;
  10. private readonly Avalonia.Media.Imaging.BitmapInterpolationMode _bitmapInterpolationMode;
  11. public ImageBrushImpl(
  12. ITileBrush brush,
  13. SharpDX.Direct2D1.RenderTarget target,
  14. BitmapImpl bitmap,
  15. Size targetSize)
  16. {
  17. var dpi = new Vector(target.DotsPerInch.Width, target.DotsPerInch.Height);
  18. var calc = new TileBrushCalculator(brush, bitmap.PixelSize.ToSizeWithDpi(dpi), targetSize);
  19. if (!calc.NeedsIntermediate)
  20. {
  21. _bitmap = bitmap.GetDirect2DBitmap(target);
  22. PlatformBrush = new BitmapBrush(
  23. target,
  24. _bitmap.Value,
  25. GetBitmapBrushProperties(brush),
  26. GetBrushProperties(brush, calc.DestinationRect));
  27. }
  28. else
  29. {
  30. using (var intermediate = RenderIntermediate(target, bitmap, calc))
  31. {
  32. PlatformBrush = new BitmapBrush(
  33. target,
  34. intermediate.Bitmap,
  35. GetBitmapBrushProperties(brush),
  36. GetBrushProperties(brush, calc.DestinationRect));
  37. }
  38. }
  39. _bitmapInterpolationMode = brush.BitmapInterpolationMode;
  40. }
  41. public override void Dispose()
  42. {
  43. _bitmap.Dispose();
  44. base.Dispose();
  45. }
  46. private static BitmapBrushProperties GetBitmapBrushProperties(ITileBrush brush)
  47. {
  48. var tileMode = brush.TileMode;
  49. return new BitmapBrushProperties
  50. {
  51. ExtendModeX = GetExtendModeX(tileMode),
  52. ExtendModeY = GetExtendModeY(tileMode),
  53. };
  54. }
  55. private static BrushProperties GetBrushProperties(ITileBrush brush, Rect destinationRect)
  56. {
  57. var tileTransform =
  58. brush.TileMode != TileMode.None ?
  59. Matrix.CreateTranslation(destinationRect.X, destinationRect.Y) :
  60. Matrix.Identity;
  61. return new BrushProperties
  62. {
  63. Opacity = (float)brush.Opacity,
  64. Transform = tileTransform.ToDirect2D(),
  65. };
  66. }
  67. private static ExtendMode GetExtendModeX(TileMode tileMode)
  68. {
  69. return (tileMode & TileMode.FlipX) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap;
  70. }
  71. private static ExtendMode GetExtendModeY(TileMode tileMode)
  72. {
  73. return (tileMode & TileMode.FlipY) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap;
  74. }
  75. private BitmapRenderTarget RenderIntermediate(
  76. SharpDX.Direct2D1.RenderTarget target,
  77. BitmapImpl bitmap,
  78. TileBrushCalculator calc)
  79. {
  80. var result = new BitmapRenderTarget(
  81. target,
  82. CompatibleRenderTargetOptions.None,
  83. calc.IntermediateSize.ToSharpDX());
  84. using (var context = new RenderTarget(result).CreateDrawingContext())
  85. {
  86. var dpi = new Vector(target.DotsPerInch.Width, target.DotsPerInch.Height);
  87. var rect = new Rect(bitmap.PixelSize.ToSizeWithDpi(dpi));
  88. context.Clear(Colors.Transparent);
  89. context.PushClip(calc.IntermediateClip);
  90. context.Transform = calc.IntermediateTransform;
  91. context.DrawBitmap(RefCountable.CreateUnownedNotClonable(bitmap), 1, rect, rect, _bitmapInterpolationMode);
  92. context.PopClip();
  93. }
  94. return result;
  95. }
  96. }
  97. }