public void Tile_NoStretch_BottomRightQuarterSource_CenterQuarterDest() { var result = new TileBrushCalculator( TileMode.Tile, Stretch.None, AlignmentX.Center, AlignmentY.Center, new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative), new RelativeRect(0.25, 0.25, 0.5, 0.5, RelativeUnit.Relative), new Size(800, 800), new Size(400, 400)); var b = new VisualBrush { TileMode = TileMode.Tile, Stretch = Stretch.None, SourceRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative), DestinationRect = new RelativeRect(0.25, 0.25, 0.5, 0.5, RelativeUnit.Relative), Visual = new Border { Width = 400, Height = 400 }, }; Assert.True(result.NeedsIntermediate); Assert.Equal(new Rect(400, 400, 400, 400), result.SourceRect); Assert.Equal(new Rect(100, 100, 200, 200), result.DestinationRect); Assert.Equal(new Size(200, 200), result.IntermediateSize); Assert.Equal(new Rect(0, 0, 200, 200), result.IntermediateClip); Assert.Equal(Matrix.CreateTranslation(-500, -500), result.IntermediateTransform); }
/// <summary> /// Configure paint wrapper for using tile brush. /// </summary> /// <param name="paintWrapper">Paint wrapper.</param> /// <param name="targetSize">Target size.</param> /// <param name="tileBrush">Tile brush to use.</param> /// <param name="tileBrushImage">Tile brush image.</param> private void ConfigureTileBrush(ref PaintWrapper paintWrapper, Size targetSize, ITileBrush tileBrush, IDrawableBitmapImpl tileBrushImage) { var calc = new TileBrushCalculator(tileBrush, tileBrushImage.PixelSize.ToSizeWithDpi(_dpi), targetSize); var intermediate = CreateRenderTarget(calc.IntermediateSize); paintWrapper.AddDisposable(intermediate); using (var context = intermediate.CreateDrawingContext(null)) { var sourceRect = new Rect(tileBrushImage.PixelSize.ToSizeWithDpi(96)); var targetRect = new Rect(tileBrushImage.PixelSize.ToSizeWithDpi(_dpi)); context.Clear(Colors.Transparent); context.PushClip(calc.IntermediateClip); context.Transform = calc.IntermediateTransform; context.DrawBitmap( RefCountable.CreateUnownedNotClonable(tileBrushImage), 1, sourceRect, targetRect, tileBrush.BitmapInterpolationMode); context.PopClip(); } var tileTransform = tileBrush.TileMode != TileMode.None ? SKMatrix.CreateTranslation(-(float)calc.DestinationRect.X, -(float)calc.DestinationRect.Y) : SKMatrix.CreateIdentity(); SKShaderTileMode tileX = tileBrush.TileMode == TileMode.None ? SKShaderTileMode.Clamp : tileBrush.TileMode == TileMode.FlipX || tileBrush.TileMode == TileMode.FlipXY ? SKShaderTileMode.Mirror : SKShaderTileMode.Repeat; SKShaderTileMode tileY = tileBrush.TileMode == TileMode.None ? SKShaderTileMode.Clamp : tileBrush.TileMode == TileMode.FlipY || tileBrush.TileMode == TileMode.FlipXY ? SKShaderTileMode.Mirror : SKShaderTileMode.Repeat; var image = intermediate.SnapshotImage(); paintWrapper.AddDisposable(image); var paintTransform = default(SKMatrix); SKMatrix.Concat( ref paintTransform, tileTransform, SKMatrix.CreateScale((float)(96.0 / _dpi.X), (float)(96.0 / _dpi.Y))); using (var shader = image.ToShader(tileX, tileY, paintTransform)) { paintWrapper.Paint.Shader = shader; } }
private BitmapRenderTarget RenderIntermediate( SharpDX.Direct2D1.RenderTarget target, BitmapImpl bitmap, TileBrushCalculator calc) { var result = new BitmapRenderTarget( target, CompatibleRenderTargetOptions.None, calc.IntermediateSize.ToSharpDX()); using (var context = new RenderTarget(result).CreateDrawingContext(null)) { var dpi = new Vector(target.DotsPerInch.Width, target.DotsPerInch.Height); var rect = new Rect(bitmap.PixelSize.ToSizeWithDpi(dpi)); context.Clear(Colors.Transparent); context.PushClip(calc.IntermediateClip); context.Transform = calc.IntermediateTransform; context.DrawBitmap(RefCountable.CreateUnownedNotClonable(bitmap), 1, rect, rect, _bitmapInterpolationMode); context.PopClip(); } return(result); }
public ImageBrushImpl( ITileBrush brush, SharpDX.Direct2D1.RenderTarget target, BitmapImpl bitmap, Size targetSize) { var dpi = new Vector(target.DotsPerInch.Width, target.DotsPerInch.Height); var calc = new TileBrushCalculator(brush, bitmap.PixelSize.ToSizeWithDpi(dpi), targetSize); if (!calc.NeedsIntermediate) { _bitmap = bitmap.GetDirect2DBitmap(target); PlatformBrush = new BitmapBrush( target, _bitmap.Value, GetBitmapBrushProperties(brush), GetBrushProperties(brush, calc.DestinationRect)); } else { using (var intermediate = RenderIntermediate(target, bitmap, calc)) { PlatformBrush = new BitmapBrush( target, intermediate.Bitmap, GetBitmapBrushProperties(brush), GetBrushProperties(brush, calc.DestinationRect)); } } _bitmapInterpolationMode = brush.BitmapInterpolationMode; }
public ImageBrushImpl( ITileBrush brush, SharpDX.Direct2D1.RenderTarget target, BitmapImpl bitmap, Size targetSize) { var calc = new TileBrushCalculator(brush, new Size(bitmap.PixelWidth, bitmap.PixelHeight), targetSize); if (!calc.NeedsIntermediate) { PlatformBrush = new BitmapBrush( target, bitmap.GetDirect2DBitmap(target), GetBitmapBrushProperties(brush), GetBrushProperties(brush, calc.DestinationRect)); } else { using (var intermediate = RenderIntermediate(target, bitmap, calc)) { PlatformBrush = new BitmapBrush( target, intermediate.Bitmap, GetBitmapBrushProperties(brush), GetBrushProperties(brush, calc.DestinationRect)); } } }
/// <summary> /// Configure paint wrapper for using tile brush. /// </summary> /// <param name="paintWrapper">Paint wrapper.</param> /// <param name="targetSize">Target size.</param> /// <param name="tileBrush">Tile brush to use.</param> /// <param name="tileBrushImage">Tile brush image.</param> /// <param name="interpolationMode">The bitmap interpolation mode.</param> private void ConfigureTileBrush(ref PaintWrapper paintWrapper, Size targetSize, ITileBrush tileBrush, IDrawableBitmapImpl tileBrushImage) { var calc = new TileBrushCalculator(tileBrush, new Size(tileBrushImage.PixelWidth, tileBrushImage.PixelHeight), targetSize); var intermediate = CreateRenderTarget( (int)calc.IntermediateSize.Width, (int)calc.IntermediateSize.Height, _dpi); paintWrapper.AddDisposable(intermediate); using (var context = intermediate.CreateDrawingContext(null)) { var rect = new Rect(0, 0, tileBrushImage.PixelWidth, tileBrushImage.PixelHeight); context.Clear(Colors.Transparent); context.PushClip(calc.IntermediateClip); context.Transform = calc.IntermediateTransform; context.DrawImage(RefCountable.CreateUnownedNotClonable(tileBrushImage), 1, rect, rect, tileBrush.BitmapInterpolationMode); context.PopClip(); } var tileTransform = tileBrush.TileMode != TileMode.None ? SKMatrix.MakeTranslation(-(float)calc.DestinationRect.X, -(float)calc.DestinationRect.Y) : SKMatrix.MakeIdentity(); SKShaderTileMode tileX = tileBrush.TileMode == TileMode.None ? SKShaderTileMode.Clamp : tileBrush.TileMode == TileMode.FlipX || tileBrush.TileMode == TileMode.FlipXY ? SKShaderTileMode.Mirror : SKShaderTileMode.Repeat; SKShaderTileMode tileY = tileBrush.TileMode == TileMode.None ? SKShaderTileMode.Clamp : tileBrush.TileMode == TileMode.FlipY || tileBrush.TileMode == TileMode.FlipXY ? SKShaderTileMode.Mirror : SKShaderTileMode.Repeat; var image = intermediate.SnapshotImage(); paintWrapper.AddDisposable(image); using (var shader = image.ToShader(tileX, tileY, tileTransform)) { paintWrapper.Paint.Shader = shader; } }
public void NoTile_Fill_1x() { var result = new TileBrushCalculator( TileMode.None, Stretch.Fill, AlignmentX.Center, AlignmentY.Center, RelativeRect.Fill, RelativeRect.Fill, new Size(100, 100), new Size(100, 100)); Assert.False(result.NeedsIntermediate); Assert.Equal(new Rect(0, 0, 100, 100), result.SourceRect); Assert.Equal(new Rect(0, 0, 100, 100), result.DestinationRect); }
public void NoTile_Fill_2x() { var result = new TileBrushCalculator( TileMode.None, Stretch.Fill, AlignmentX.Center, AlignmentY.Center, RelativeRect.Fill, RelativeRect.Fill, new Size(100, 100), new Size(200, 200)); // TODO: This doesn't need an intermediate render target. Assert.True(result.NeedsIntermediate); Assert.Equal(new Rect(0, 0, 100, 100), result.SourceRect); Assert.Equal(new Rect(0, 0, 200, 200), result.DestinationRect); }
public void NoTile_Uniform_CenterVert() { var result = new TileBrushCalculator( TileMode.None, Stretch.Uniform, AlignmentX.Center, AlignmentY.Center, RelativeRect.Fill, RelativeRect.Fill, new Size(100, 100), new Size(100, 200)); Assert.True(result.NeedsIntermediate); Assert.Equal(new Rect(0, 0, 100, 100), result.SourceRect); Assert.Equal(new Rect(0, 0, 100, 200), result.DestinationRect); Assert.Equal(new Size(100, 200), result.IntermediateSize); Assert.Equal(Matrix.CreateTranslation(0, 50), result.IntermediateTransform); }
public ImageBrushImpl( ITileBrush brush, IBitmapImpl bitmap, Size targetSize) { var calc = new TileBrushCalculator(brush, new Size(bitmap.PixelWidth, bitmap.PixelHeight), targetSize); using (var intermediate = new ImageSurface(Format.ARGB32, (int)calc.IntermediateSize.Width, (int)calc.IntermediateSize.Height)) { using (var context = new RenderTarget(intermediate).CreateDrawingContext(null)) { var rect = new Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight); context.Clear(Colors.Transparent); context.PushClip(calc.IntermediateClip); context.Transform = calc.IntermediateTransform; context.DrawImage(bitmap, 1, rect, rect); context.PopClip(); } 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(-calc.DestinationRect.X, -calc.DestinationRect.Y); result.Matrix = matrix; } PlatformBrush = result; } }
public void NoTile_NoStretch_BottomRightQuarterDest() { var result = new TileBrushCalculator( TileMode.None, Stretch.None, AlignmentX.Center, AlignmentY.Center, RelativeRect.Fill, new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative), new Size(800, 800), new Size(400, 400)); Assert.True(result.NeedsIntermediate); Assert.Equal(new Rect(0, 0, 800, 800), result.SourceRect); Assert.Equal(new Rect(200, 200, 200, 200), result.DestinationRect); Assert.Equal(new Size(400, 400), result.IntermediateSize); Assert.Equal(new Rect(200, 200, 200, 200), result.IntermediateClip); Assert.Equal(Matrix.CreateTranslation(-100, -100), result.IntermediateTransform); }
private BitmapRenderTarget RenderIntermediate( SharpDX.Direct2D1.RenderTarget target, BitmapImpl bitmap, TileBrushCalculator calc) { var result = new BitmapRenderTarget( target, CompatibleRenderTargetOptions.None, calc.IntermediateSize.ToSharpDX()); using (var context = new RenderTarget(result).CreateDrawingContext(null)) { var rect = new Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight); context.Clear(Colors.Transparent); context.PushClip(calc.IntermediateClip); context.Transform = calc.IntermediateTransform; context.DrawImage(bitmap, 1, rect, rect); context.PopClip(); } return(result); }
internal PaintWrapper CreatePaint(IBrush brush, Size targetSize) { SKPaint paint = new SKPaint(); var rv = new PaintWrapper(paint); paint.IsStroke = false; double opacity = brush.Opacity * _currentOpacity; paint.IsAntialias = true; var solid = brush as ISolidColorBrush; if (solid != null) { paint.Color = new SKColor(solid.Color.R, solid.Color.G, solid.Color.B, (byte)(solid.Color.A * opacity)); return(rv); } paint.Color = (new SKColor(255, 255, 255, (byte)(255 * opacity))); var gradient = brush as IGradientBrush; if (gradient != null) { var tileMode = gradient.SpreadMethod.ToSKShaderTileMode(); var stopColors = gradient.GradientStops.Select(s => s.Color.ToSKColor()).ToArray(); var stopOffsets = gradient.GradientStops.Select(s => (float)s.Offset).ToArray(); var linearGradient = brush as ILinearGradientBrush; if (linearGradient != null) { var start = linearGradient.StartPoint.ToPixels(targetSize).ToSKPoint(); var end = linearGradient.EndPoint.ToPixels(targetSize).ToSKPoint(); // would be nice to cache these shaders possibly? using (var shader = SKShader.CreateLinearGradient(start, end, stopColors, stopOffsets, tileMode)) paint.Shader = shader; } else { var radialGradient = brush as IRadialGradientBrush; if (radialGradient != null) { var center = radialGradient.Center.ToPixels(targetSize).ToSKPoint(); var radius = (float)radialGradient.Radius; // TODO: There is no SetAlpha in SkiaSharp //paint.setAlpha(128); // would be nice to cache these shaders possibly? using (var shader = SKShader.CreateRadialGradient(center, radius, stopColors, stopOffsets, tileMode)) paint.Shader = shader; } } return(rv); } var tileBrush = brush as ITileBrush; var visualBrush = brush as IVisualBrush; var tileBrushImage = default(BitmapImpl); if (visualBrush != null) { if (_visualBrushRenderer != null) { var intermediateSize = _visualBrushRenderer.GetRenderTargetSize(visualBrush); if (intermediateSize.Width >= 1 && intermediateSize.Height >= 1) { var intermediate = new BitmapImpl((int)intermediateSize.Width, (int)intermediateSize.Height); using (var ctx = intermediate.CreateDrawingContext(_visualBrushRenderer)) { ctx.Clear(Colors.Transparent); _visualBrushRenderer.RenderVisualBrush(ctx, visualBrush); } rv.AddDisposable(tileBrushImage); tileBrushImage = intermediate; } } else { throw new NotSupportedException("No IVisualBrushRenderer was supplied to DrawingContextImpl."); } } else { tileBrushImage = (BitmapImpl)((tileBrush as IImageBrush)?.Source?.PlatformImpl); } if (tileBrush != null && tileBrushImage != null) { var calc = new TileBrushCalculator(tileBrush, new Size(tileBrushImage.PixelWidth, tileBrushImage.PixelHeight), targetSize); var bitmap = new BitmapImpl((int)calc.IntermediateSize.Width, (int)calc.IntermediateSize.Height); rv.AddDisposable(bitmap); using (var context = bitmap.CreateDrawingContext(null)) { var rect = new Rect(0, 0, tileBrushImage.PixelWidth, tileBrushImage.PixelHeight); context.Clear(Colors.Transparent); context.PushClip(calc.IntermediateClip); context.Transform = calc.IntermediateTransform; context.DrawImage(tileBrushImage, 1, rect, rect); context.PopClip(); } SKMatrix translation = SKMatrix.MakeTranslation(-(float)calc.DestinationRect.X, -(float)calc.DestinationRect.Y); SKShaderTileMode tileX = tileBrush.TileMode == TileMode.None ? SKShaderTileMode.Clamp : tileBrush.TileMode == TileMode.FlipX || tileBrush.TileMode == TileMode.FlipXY ? SKShaderTileMode.Mirror : SKShaderTileMode.Repeat; SKShaderTileMode tileY = tileBrush.TileMode == TileMode.None ? SKShaderTileMode.Clamp : tileBrush.TileMode == TileMode.FlipY || tileBrush.TileMode == TileMode.FlipXY ? SKShaderTileMode.Mirror : SKShaderTileMode.Repeat; using (var shader = SKShader.CreateBitmap(bitmap.Bitmap, tileX, tileY, translation)) paint.Shader = shader; } return(rv); }