private static Vector CalculateTranslate( VisualBrush 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 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)); } }
public VisualBrushImpl( VisualBrush brush, RenderTarget target, Size targetSize) { var visual = brush.Visual; var layoutable = visual as ILayoutable; if (layoutable?.IsArrangeValid == false) { layoutable.Measure(Size.Infinity); layoutable.Arrange(new Rect(layoutable.DesiredSize)); } var sourceRect = brush.SourceRect.ToPixels(layoutable.Bounds.Size); var destinationRect = brush.DestinationRect.ToPixels(targetSize); var bitmapSize = brush.TileMode == TileMode.None ? targetSize : destinationRect.Size; var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size); var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale); var options = CompatibleRenderTargetOptions.None; using (var brt = new BitmapRenderTarget(target, options, bitmapSize.ToSharpDX())) { var renderer = new Renderer(brt); var transform = Matrix.CreateTranslation(-sourceRect.Position) * Matrix.CreateScale(scale) * Matrix.CreateTranslation(translate); Rect drawRect; if (brush.TileMode == TileMode.None) { drawRect = destinationRect; transform *= Matrix.CreateTranslation(destinationRect.Position); } else { drawRect = new Rect(0, 0, destinationRect.Width, destinationRect.Height); } renderer.Render(visual, null, transform, drawRect); var result = new BitmapBrush(brt, brt.Bitmap); result.ExtendModeX = (brush.TileMode & TileMode.FlipX) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap; result.ExtendModeY = (brush.TileMode & TileMode.FlipY) != 0 ? ExtendMode.Mirror : ExtendMode.Wrap; if (brush.TileMode != TileMode.None) { result.Transform = SharpDX.Matrix3x2.Translation( (float)destinationRect.X, (float)destinationRect.Y); } PlatformBrush = result; } }
public static SurfacePattern CreateVisualBrush(VisualBrush brush, Size targetSize) { var visual = brush.Visual; if (visual == null) { return null; } var layoutable = visual as ILayoutable; if (layoutable?.IsArrangeValid == false) { layoutable.Measure(Size.Infinity); layoutable.Arrange(new Rect(layoutable.DesiredSize)); } // TODO: This is directly ported from Direct2D and could probably be made more // efficient on cairo by taking advantage of the fact that cairo has Extend.None. 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); using (var intermediate = new ImageSurface(Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height)) using (var context = new Context(intermediate)) { Rect drawRect; var transform = CalculateIntermediateTransform( tileMode, sourceRect, destinationRect, scale, translate, out drawRect); var renderer = new Renderer(intermediate); context.Rectangle(drawRect.ToCairo()); context.Clip(); context.Transform(transform.ToCairo()); renderer.Render(visual, new PlatformHandle(IntPtr.Zero, "RTB"), transform, drawRect); 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(-destinationRect.X, -destinationRect.Y); result.Matrix = matrix; } return result; } }
public VisualBrushImpl( VisualBrush brush, 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 Renderer(intermediate); renderer.Render(visual, null, transform, drawRect); this.PlatformBrush = new BitmapBrush( target, intermediate.Bitmap, GetBitmapBrushProperties(brush), GetBrushProperties(brush, destinationRect)); } //var sourceRect = brush.SourceRect.ToPixels(layoutable.Bounds.Size); //var destinationRect = brush.DestinationRect.ToPixels(targetSize); //var bitmapSize = brush.TileMode == TileMode.None ? targetSize : destinationRect.Size; //var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size); //var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale); //var options = CompatibleRenderTargetOptions.None; //using (var brt = new BitmapRenderTarget(target, options, bitmapSize.ToSharpDX())) //{ // var renderer = new Renderer(brt); // var transform = Matrix.CreateTranslation(-sourceRect.Position) * // Matrix.CreateScale(scale) * // Matrix.CreateTranslation(translate); // Rect drawRect; // if (brush.TileMode == TileMode.None) // { // drawRect = destinationRect; // transform *= Matrix.CreateTranslation(destinationRect.Position); // } // else // { // drawRect = new Rect(0, 0, destinationRect.Width, destinationRect.Height); // } // renderer.Render(visual, null, transform, drawRect); // var result = new BitmapBrush(brt, brt.Bitmap); // result.ExtendModeX = GetExtendModeX(brush.TileMode); // result.ExtendModeY = GetExtendModeY(brush.TileMode); // if (brush.TileMode != TileMode.None) // { // result.Transform = SharpDX.Matrix3x2.Translation( // (float)destinationRect.X, // (float)destinationRect.Y); // } // PlatformBrush = result; //} }