9 changed files with 227 additions and 245 deletions
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects> |
|||
<HasSharedItems>true</HasSharedItems> |
|||
<SharedGUID>3c4c0cb4-0c0f-4450-a37b-148c84ff905f</SharedGUID> |
|||
</PropertyGroup> |
|||
<PropertyGroup Label="Configuration"> |
|||
<Import_RootNamespace>Perspex.RenderHelpers</Import_RootNamespace> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<Compile Include="$(MSBuildThisFileDirectory)TileBrushImplHelper.cs" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
@ -0,0 +1,13 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>3c4c0cb4-0c0f-4450-a37b-148c84ff905f</ProjectGuid> |
|||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion> |
|||
</PropertyGroup> |
|||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
|||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" /> |
|||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" /> |
|||
<PropertyGroup /> |
|||
<Import Project="RenderHelpers.projitems" Label="Shared" /> |
|||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" /> |
|||
</Project> |
|||
@ -0,0 +1,174 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Text; |
|||
using Perspex; |
|||
using Perspex.Media; |
|||
using Perspex.Rendering; |
|||
using Perspex.Layout; |
|||
|
|||
|
|||
namespace Perspex.RenderHelpers |
|||
{ |
|||
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 VisualBrush _visualBrush; |
|||
private readonly ImageBrush _imageBrush; |
|||
|
|||
public bool IsValid { get; } |
|||
|
|||
|
|||
public TileBrushImplHelper(TileBrush brush, Size targetSize) |
|||
{ |
|||
_imageBrush = brush as ImageBrush; |
|||
_visualBrush = brush as VisualBrush; |
|||
if (_imageBrush != null) |
|||
{ |
|||
if (_imageBrush.Source == null) |
|||
return; |
|||
_imageSize = new Size(_imageBrush.Source.PixelWidth, _imageBrush.Source.PixelHeight); |
|||
IsValid = true; |
|||
} |
|||
else if (_visualBrush != null) |
|||
{ |
|||
var visual = _visualBrush.Visual; |
|||
if (visual == null) |
|||
return; |
|||
var layoutable = visual as ILayoutable; |
|||
|
|||
if (layoutable?.IsArrangeValid == false) |
|||
{ |
|||
layoutable.Measure(Size.Infinity); |
|||
layoutable.Arrange(new Rect(layoutable.DesiredSize)); |
|||
} |
|||
//I have no idea why are we using layoutable after `as` cast, but it was in original VisualBrush code by @grokys
|
|||
_imageSize = layoutable.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); |
|||
} |
|||
|
|||
public void DrawIntermediate(DrawingContext ctx) |
|||
{ |
|||
Rect drawRect; |
|||
var transform = CalculateIntermediateTransform( |
|||
_tileMode, |
|||
_sourceRect, |
|||
DestinationRect, |
|||
_scale, |
|||
_translate, |
|||
out drawRect); |
|||
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) |
|||
{ |
|||
ctx.FillRectangle(Brushes.Black, new Rect(new Point(0, 0), IntermediateSize)); |
|||
ctx.Render(_visualBrush.Visual); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Calculates a _translate based on a <see cref="TileBrush"/>, 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( |
|||
TileBrush 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; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
static Size CalculateIntermediateSize( |
|||
TileMode tileMode, |
|||
Size targetSize, |
|||
Size destinationSize) => tileMode == TileMode.None ? targetSize : destinationSize; |
|||
|
|||
} |
|||
} |
|||
@ -1,94 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using Perspex.Media; |
|||
using SharpDX.Direct2D1; |
|||
|
|||
namespace Perspex.Direct2D1.Media |
|||
{ |
|||
public class ImageBrushImpl : TileBrushImpl |
|||
{ |
|||
public ImageBrushImpl( |
|||
ImageBrush brush, |
|||
SharpDX.Direct2D1.RenderTarget target, |
|||
Size targetSize) |
|||
{ |
|||
if (brush.Source == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var image = ((BitmapImpl)brush.Source.PlatformImpl).GetDirect2DBitmap(target); |
|||
var imageSize = new Size(brush.Source.PixelWidth, brush.Source.PixelHeight); |
|||
var tileMode = brush.TileMode; |
|||
var sourceRect = brush.SourceRect.ToPixels(imageSize); |
|||
var destinationRect = brush.DestinationRect.ToPixels(targetSize); |
|||
var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size); |
|||
var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale); |
|||
var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size); |
|||
var brtOpts = CompatibleRenderTargetOptions.None; |
|||
|
|||
// TODO: There are times where we don't need to draw an intermediate bitmap. Identify
|
|||
// them and directly use 'image' in those cases.
|
|||
using (var intermediate = new BitmapRenderTarget(target, brtOpts, intermediateSize)) |
|||
{ |
|||
Rect drawRect; |
|||
var transform = CalculateIntermediateTransform( |
|||
tileMode, |
|||
sourceRect, |
|||
destinationRect, |
|||
scale, |
|||
translate, |
|||
out drawRect); |
|||
|
|||
intermediate.BeginDraw(); |
|||
intermediate.PushAxisAlignedClip(drawRect.ToDirect2D(), AntialiasMode.Aliased); |
|||
intermediate.Transform = transform.ToDirect2D(); |
|||
intermediate.DrawBitmap(image, 1, BitmapInterpolationMode.Linear); |
|||
intermediate.PopAxisAlignedClip(); |
|||
intermediate.EndDraw(); |
|||
|
|||
this.PlatformBrush = new BitmapBrush( |
|||
target, |
|||
intermediate.Bitmap, |
|||
GetBitmapBrushProperties(brush), |
|||
GetBrushProperties(brush, destinationRect)); |
|||
} |
|||
} |
|||
|
|||
private BitmapBrush CreateDirectBrush( |
|||
ImageBrush brush, |
|||
SharpDX.Direct2D1.RenderTarget target, |
|||
Bitmap image, |
|||
Rect sourceRect, |
|||
Rect destinationRect) |
|||
{ |
|||
var tileMode = brush.TileMode; |
|||
var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size); |
|||
var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale); |
|||
var transform = Matrix.CreateTranslation(-sourceRect.Position) * |
|||
Matrix.CreateScale(scale) * |
|||
Matrix.CreateTranslation(translate); |
|||
|
|||
var opts = new BrushProperties |
|||
{ |
|||
Transform = transform.ToDirect2D(), |
|||
Opacity = (float)brush.Opacity, |
|||
}; |
|||
|
|||
var bitmapOpts = new BitmapBrushProperties |
|||
{ |
|||
ExtendModeX = GetExtendModeX(tileMode), |
|||
ExtendModeY = GetExtendModeY(tileMode), |
|||
}; |
|||
|
|||
return new BitmapBrush(target, image, bitmapOpts, opts); |
|||
} |
|||
|
|||
private BitmapBrush CreateIndirectBrush() |
|||
{ |
|||
throw new NotImplementedException(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,73 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using Perspex.Layout; |
|||
using Perspex.Media; |
|||
using Perspex.Rendering; |
|||
using SharpDX; |
|||
using SharpDX.Direct2D1; |
|||
|
|||
namespace Perspex.Direct2D1.Media |
|||
{ |
|||
public class VisualBrushImpl : TileBrushImpl |
|||
{ |
|||
public VisualBrushImpl( |
|||
VisualBrush brush, |
|||
SharpDX.Direct2D1.RenderTarget target, |
|||
Size targetSize) |
|||
{ |
|||
var visual = brush.Visual; |
|||
|
|||
if (visual == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var layoutable = visual as ILayoutable; |
|||
|
|||
if (layoutable?.IsArrangeValid == false) |
|||
{ |
|||
layoutable.Measure(Size.Infinity); |
|||
layoutable.Arrange(new Rect(layoutable.DesiredSize)); |
|||
} |
|||
|
|||
var tileMode = brush.TileMode; |
|||
var sourceRect = brush.SourceRect.ToPixels(layoutable.Bounds.Size); |
|||
var destinationRect = brush.DestinationRect.ToPixels(targetSize); |
|||
var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size); |
|||
var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale); |
|||
var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size); |
|||
var brtOpts = CompatibleRenderTargetOptions.None; |
|||
|
|||
// TODO: There are times where we don't need to draw an intermediate bitmap. Identify
|
|||
// them and directly use 'image' in those cases.
|
|||
using (var intermediate = new BitmapRenderTarget(target, brtOpts, intermediateSize)) |
|||
{ |
|||
Rect drawRect; |
|||
var transform = CalculateIntermediateTransform( |
|||
tileMode, |
|||
sourceRect, |
|||
destinationRect, |
|||
scale, |
|||
translate, |
|||
out drawRect); |
|||
var renderer = new RenderTarget(intermediate); |
|||
|
|||
using (var ctx = renderer.CreateDrawingContext()) |
|||
using (ctx.PushClip(drawRect)) |
|||
using (ctx.PushPostTransform(transform)) |
|||
{ |
|||
intermediate.Clear(new Color4(0)); |
|||
ctx.Render(visual); |
|||
} |
|||
|
|||
this.PlatformBrush = new BitmapBrush( |
|||
target, |
|||
intermediate.Bitmap, |
|||
GetBitmapBrushProperties(brush), |
|||
GetBrushProperties(brush, destinationRect)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue