ImageBrushImpl.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System;
  4. using Avalonia.Media;
  5. using Avalonia.Rendering.Utilities;
  6. using Avalonia.Utilities;
  7. using SharpDX.Direct2D1;
  8. namespace Avalonia.Direct2D1.Media
  9. {
  10. public sealed class ImageBrushImpl : BrushImpl
  11. {
  12. OptionalDispose<Bitmap> _bitmap;
  13. public ImageBrushImpl(
  14. ITileBrush brush,
  15. SharpDX.Direct2D1.RenderTarget target,
  16. BitmapImpl bitmap,
  17. Size targetSize)
  18. {
  19. var calc = new TileBrushCalculator(brush, new Size(bitmap.PixelWidth, bitmap.PixelHeight), targetSize);
  20. if (!calc.NeedsIntermediate)
  21. {
  22. _bitmap = bitmap.GetDirect2DBitmap(target);
  23. PlatformBrush = new BitmapBrush(
  24. target,
  25. _bitmap.Value,
  26. GetBitmapBrushProperties(brush),
  27. GetBrushProperties(brush, calc.DestinationRect));
  28. }
  29. else
  30. {
  31. using (var intermediate = RenderIntermediate(target, bitmap, calc))
  32. {
  33. PlatformBrush = new BitmapBrush(
  34. target,
  35. intermediate.Bitmap,
  36. GetBitmapBrushProperties(brush),
  37. GetBrushProperties(brush, calc.DestinationRect));
  38. }
  39. }
  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(null))
  85. {
  86. var rect = new Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight);
  87. context.Clear(Colors.Transparent);
  88. context.PushClip(calc.IntermediateClip);
  89. context.Transform = calc.IntermediateTransform;
  90. context.DrawImage(RefCountable.CreateUnownedNotClonable(bitmap), 1, rect, rect);
  91. context.PopClip();
  92. }
  93. return result;
  94. }
  95. }
  96. }