Browse Source
Conflicts: src/Avalonia.Visuals/Platform/IRenderTarget.cs src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs src/Gtk/Avalonia.Cairo/Media/DrawingContext.cs src/Gtk/Avalonia.Cairo/Media/ImageBrushImpl.cs src/Shared/RenderHelpers/TileBrushImplHelper.cs src/Skia/Avalonia.Skia/BitmapImpl.cs src/Skia/Avalonia.Skia/DrawingContextImpl.cs src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs src/Windows/Avalonia.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs src/Windows/Avalonia.Direct2D1/RenderTarget.cs src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs src/Windows/Avalonia.Win32/Win32Platform.cs tests/Avalonia.UnitTests/TestServices.cs tests/Avalonia.Visuals.UnitTests/VisualTests.cs tests/Avalonia.Visuals.UnitTests/VisualTree/VisualExtensionsTests_GetVisualsAt.csscenegraph-after-breakage
22 changed files with 41 additions and 420 deletions
@ -1,55 +0,0 @@ |
|||||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|
||||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
||||
|
|
||||
using System; |
|
||||
using Cairo; |
|
||||
using Avalonia.Cairo.Media.Imaging; |
|
||||
using Avalonia.Layout; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Platform; |
|
||||
using Avalonia.Rendering; |
|
||||
using Avalonia.RenderHelpers; |
|
||||
|
|
||||
namespace Avalonia.Cairo.Media |
|
||||
{ |
|
||||
internal static class TileBrushes |
|
||||
{ |
|
||||
public static SurfacePattern CreateTileBrush(ITileBrush brush, Size targetSize) |
|
||||
{ |
|
||||
var helper = new TileBrushImplHelper(brush, targetSize); |
|
||||
if (!helper.IsValid) |
|
||||
return null; |
|
||||
|
|
||||
using (var intermediate = new ImageSurface(Format.ARGB32, (int)helper.IntermediateSize.Width, (int)helper.IntermediateSize.Height)) |
|
||||
using (var ctx = new RenderTarget(intermediate).CreateDrawingContext()) |
|
||||
{ |
|
||||
helper.DrawIntermediate(ctx); |
|
||||
|
|
||||
var result = new SurfacePattern(intermediate); |
|
||||
|
|
||||
if ((brush.TileMode & TileMode.FlipXY) != 0) |
|
||||
{ |
|
||||
// TODO: Currently always FlipXY as that's all cairo supports natively.
|
|
||||
// Support separate FlipX and FlipY by drawing flipped images to intermediate
|
|
||||
// surface.
|
|
||||
result.Extend = Extend.Reflect; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
result.Extend = Extend.Repeat; |
|
||||
} |
|
||||
|
|
||||
if (brush.TileMode != TileMode.None) |
|
||||
{ |
|
||||
var matrix = result.Matrix; |
|
||||
matrix.InitTranslate(-helper.DestinationRect.X, -helper.DestinationRect.Y); |
|
||||
result.Matrix = matrix; |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
} |
|
||||
@ -1,15 +0,0 @@ |
|||||
using System; |
|
||||
using Avalonia.Media; |
|
||||
using global::Cairo; |
|
||||
|
|
||||
namespace Avalonia.Cairo.Media |
|
||||
{ |
|
||||
public class VisualBrushImpl : BrushImpl |
|
||||
{ |
|
||||
public VisualBrushImpl(IVisualBrush brush, Size destinationSize) |
|
||||
{ |
|
||||
this.PlatformBrush = TileBrushes.CreateTileBrush(brush, destinationSize); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@ -1,213 +0,0 @@ |
|||||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|
||||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
||||
|
|
||||
using Avalonia.Controls; |
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.Rendering; |
|
||||
using Avalonia.VisualTree; |
|
||||
|
|
||||
namespace Avalonia.RenderHelpers |
|
||||
{ |
|
||||
internal class TileBrushImplHelper |
|
||||
{ |
|
||||
public Size IntermediateSize { get; } |
|
||||
public Rect DestinationRect { get; } |
|
||||
private readonly TileMode _tileMode; |
|
||||
private readonly Rect _sourceRect; |
|
||||
private readonly Vector _scale; |
|
||||
private readonly Vector _translate; |
|
||||
private readonly Size _imageSize; |
|
||||
private readonly IVisualBrush _visualBrush; |
|
||||
private readonly IImageBrush _imageBrush; |
|
||||
private readonly Matrix _transform; |
|
||||
private readonly Rect _drawRect; |
|
||||
|
|
||||
public bool IsValid { get; } |
|
||||
|
|
||||
public TileBrushImplHelper(ITileBrush brush, Size targetSize) |
|
||||
{ |
|
||||
_imageBrush = brush as IImageBrush; |
|
||||
_visualBrush = brush as IVisualBrush; |
|
||||
if (_imageBrush != null) |
|
||||
{ |
|
||||
if (_imageBrush.Source == null) |
|
||||
return; |
|
||||
_imageSize = new Size(_imageBrush.Source.PixelWidth, _imageBrush.Source.PixelHeight); |
|
||||
IsValid = true; |
|
||||
} |
|
||||
else if (_visualBrush != null) |
|
||||
{ |
|
||||
var control = _visualBrush.Visual as IControl; |
|
||||
|
|
||||
if (control != null) |
|
||||
{ |
|
||||
EnsureInitialized(control); |
|
||||
_imageSize = control.Bounds.Size; |
|
||||
IsValid = true; |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
return; |
|
||||
|
|
||||
_tileMode = brush.TileMode; |
|
||||
_sourceRect = brush.SourceRect.ToPixels(_imageSize); |
|
||||
DestinationRect = brush.DestinationRect.ToPixels(targetSize); |
|
||||
_scale = brush.Stretch.CalculateScaling(DestinationRect.Size, _sourceRect.Size); |
|
||||
_translate = CalculateTranslate(brush, _sourceRect, DestinationRect, _scale); |
|
||||
IntermediateSize = CalculateIntermediateSize(_tileMode, targetSize, DestinationRect.Size); |
|
||||
_transform = CalculateIntermediateTransform( |
|
||||
_tileMode, |
|
||||
_sourceRect, |
|
||||
DestinationRect, |
|
||||
_scale, |
|
||||
_translate, |
|
||||
out _drawRect); |
|
||||
} |
|
||||
|
|
||||
public bool NeedsIntermediateSurface |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
if (_imageBrush == null) |
|
||||
return true; |
|
||||
if (_transform != Matrix.Identity) |
|
||||
return true; |
|
||||
if (_sourceRect.Position != default(Point)) |
|
||||
return true; |
|
||||
if ((int) _sourceRect.Width != _imageBrush.Source.PixelWidth || |
|
||||
(int) _sourceRect.Height != _imageBrush.Source.PixelHeight) |
|
||||
return true; |
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public T GetDirect<T>() => (T) _imageBrush?.Source.PlatformImpl; |
|
||||
|
|
||||
public void DrawIntermediate(DrawingContext ctx) |
|
||||
{ |
|
||||
using (ctx.PushClip(_drawRect)) |
|
||||
using (ctx.PushPostTransform(_transform)) |
|
||||
{ |
|
||||
if (_imageBrush != null) |
|
||||
{ |
|
||||
var bmpRc = new Rect(0, 0, _imageBrush.Source.PixelWidth, _imageBrush.Source.PixelHeight); |
|
||||
ctx.DrawImage(_imageBrush.Source, 1, bmpRc, bmpRc); |
|
||||
} |
|
||||
else if (_visualBrush != null) |
|
||||
{ |
|
||||
using (ctx.PushPostTransform(Matrix.CreateTranslation(-_visualBrush.Visual.Bounds.Position))) |
|
||||
{ |
|
||||
ImmediateRenderer.Render(_visualBrush.Visual, ctx); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Calculates a translate based on an <see cref="ITileBrush"/>, a source and destination
|
|
||||
/// rectangle and a scale.
|
|
||||
/// </summary>
|
|
||||
/// <param name="brush">The brush.</param>
|
|
||||
/// <param name="sourceRect">The source rectangle.</param>
|
|
||||
/// <param name="destinationRect">The destination rectangle.</param>
|
|
||||
/// <param name="scale">The _scale factor.</param>
|
|
||||
/// <returns>A vector with the X and Y _translate.</returns>
|
|
||||
|
|
||||
public static Vector CalculateTranslate( |
|
||||
ITileBrush brush, |
|
||||
Rect sourceRect, |
|
||||
Rect destinationRect, |
|
||||
Vector scale) |
|
||||
{ |
|
||||
var x = 0.0; |
|
||||
var y = 0.0; |
|
||||
var size = sourceRect.Size*scale; |
|
||||
|
|
||||
switch (brush.AlignmentX) |
|
||||
{ |
|
||||
case AlignmentX.Center: |
|
||||
x += (destinationRect.Width - size.Width)/2; |
|
||||
break; |
|
||||
case AlignmentX.Right: |
|
||||
x += destinationRect.Width - size.Width; |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
switch (brush.AlignmentY) |
|
||||
{ |
|
||||
case AlignmentY.Center: |
|
||||
y += (destinationRect.Height - size.Height)/2; |
|
||||
break; |
|
||||
case AlignmentY.Bottom: |
|
||||
y += destinationRect.Height - size.Height; |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
return new Vector(x, y); |
|
||||
} |
|
||||
|
|
||||
public static Matrix CalculateIntermediateTransform( |
|
||||
TileMode tileMode, |
|
||||
Rect sourceRect, |
|
||||
Rect destinationRect, |
|
||||
Vector scale, |
|
||||
Vector translate, |
|
||||
out Rect drawRect) |
|
||||
{ |
|
||||
var transform = Matrix.CreateTranslation(-sourceRect.Position)* |
|
||||
Matrix.CreateScale(scale)* |
|
||||
Matrix.CreateTranslation(translate); |
|
||||
Rect dr; |
|
||||
|
|
||||
if (tileMode == TileMode.None) |
|
||||
{ |
|
||||
dr = destinationRect; |
|
||||
transform *= Matrix.CreateTranslation(destinationRect.Position); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
dr = new Rect(destinationRect.Size); |
|
||||
} |
|
||||
|
|
||||
drawRect = dr; |
|
||||
|
|
||||
return transform; |
|
||||
} |
|
||||
|
|
||||
public static void EnsureInitialized(IVisual visual) |
|
||||
{ |
|
||||
var control = visual as IControl; |
|
||||
|
|
||||
if (control != null) |
|
||||
{ |
|
||||
foreach (var i in control.GetSelfAndVisualDescendents()) |
|
||||
{ |
|
||||
var c = i as IControl; |
|
||||
|
|
||||
if (c?.IsInitialized == false) |
|
||||
{ |
|
||||
var init = c as ISupportInitialize; |
|
||||
|
|
||||
if (init != null) |
|
||||
{ |
|
||||
init.BeginInit(); |
|
||||
init.EndInit(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (!control.IsArrangeValid) |
|
||||
{ |
|
||||
control.Measure(Size.Infinity); |
|
||||
control.Arrange(new Rect(control.DesiredSize)); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private static Size CalculateIntermediateSize( |
|
||||
TileMode tileMode, |
|
||||
Size targetSize, |
|
||||
Size destinationSize) => tileMode == TileMode.None ? targetSize : destinationSize; |
|
||||
} |
|
||||
} |
|
||||
@ -1,78 +0,0 @@ |
|||||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|
||||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
||||
|
|
||||
using Avalonia.Media; |
|
||||
using Avalonia.RenderHelpers; |
|
||||
using SharpDX.Direct2D1; |
|
||||
|
|
||||
namespace Avalonia.Direct2D1.Media |
|
||||
{ |
|
||||
public sealed class TileBrushImpl : BrushImpl |
|
||||
{ |
|
||||
public TileBrushImpl( |
|
||||
ITileBrush brush, |
|
||||
SharpDX.Direct2D1.RenderTarget target, |
|
||||
Size targetSize) |
|
||||
{ |
|
||||
var helper = new TileBrushImplHelper(brush, targetSize); |
|
||||
if (!helper.IsValid) |
|
||||
return; |
|
||||
|
|
||||
using (var intermediate = new BitmapRenderTarget(target, CompatibleRenderTargetOptions.None, helper.IntermediateSize.ToSharpDX())) |
|
||||
{ |
|
||||
using (var ctx = new RenderTarget(intermediate).CreateDrawingContext()) |
|
||||
{ |
|
||||
intermediate.Clear(null); |
|
||||
helper.DrawIntermediate(ctx); |
|
||||
} |
|
||||
|
|
||||
PlatformBrush = new BitmapBrush( |
|
||||
target, |
|
||||
intermediate.Bitmap, |
|
||||
GetBitmapBrushProperties(brush), |
|
||||
GetBrushProperties(brush, helper.DestinationRect)); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private static BrushProperties GetBrushProperties(ITileBrush brush, Rect destinationRect) |
|
||||
{ |
|
||||
var tileTransform = |
|
||||
brush.TileMode != TileMode.None ? |
|
||||
Matrix.CreateTranslation(destinationRect.X, destinationRect.Y) : |
|
||||
Matrix.Identity; |
|
||||
|
|
||||
return new BrushProperties |
|
||||
{ |
|
||||
Opacity = (float)brush.Opacity, |
|
||||
Transform = tileTransform.ToDirect2D(), |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
private static BitmapBrushProperties GetBitmapBrushProperties(ITileBrush brush) |
|
||||
{ |
|
||||
var tileMode = brush.TileMode; |
|
||||
|
|
||||
return new BitmapBrushProperties |
|
||||
{ |
|
||||
ExtendModeX = GetExtendModeX(tileMode), |
|
||||
ExtendModeY = GetExtendModeY(tileMode), |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
private static ExtendMode GetExtendModeX(TileMode tileMode) |
|
||||
{ |
|
||||
return (tileMode & TileMode.FlipX) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap; |
|
||||
} |
|
||||
|
|
||||
private static ExtendMode GetExtendModeY(TileMode tileMode) |
|
||||
{ |
|
||||
return (tileMode & TileMode.FlipY) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap; |
|
||||
} |
|
||||
|
|
||||
public override void Dispose() |
|
||||
{ |
|
||||
((BitmapBrush)PlatformBrush)?.Bitmap.Dispose(); |
|
||||
base.Dispose(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue