/// <summary> /// Constructor /// </summary> /// <param name="generator">ICompositionMaskGeneratorInternal object</param> /// <param name="surfaceBitmap">The CanvasBitmap whose alpha values will be used to create the Mask.</param> /// <param name="size">Size of the IImageMaskSurface</param> /// <param name="padding">The padding between the IImageMaskSurface outer bounds and the bounds of the area where /// the mask, created from the loaded image's alpha values, should be rendered.</param> /// <param name="options">The image's resize, alignment options and blur radius in the allocated space.</param> public ImageMaskSurface(ICompositionGeneratorInternal generator, CanvasBitmap surfaceBitmap, Size size, Thickness padding, ImageSurfaceOptions options) { _generator = generator ?? throw new ArgumentNullException(nameof(generator), "CompositionGenerator cannot be null!"); _surfaceLock = new object(); // Create the Surface of the IImageMaskSurface _surface = _generator.CreateDrawingSurface(_surfaceLock, size); Size = _surface?.Size ?? new Size(0, 0); _uri = null; _raiseLoadCompletedEvent = false; if (surfaceBitmap != null) { _canvasBitmap = CanvasBitmap.CreateFromBytes(_generator.Device, surfaceBitmap.GetPixelBytes(), (int)surfaceBitmap.Bounds.Width, (int)surfaceBitmap.Bounds.Height, surfaceBitmap.Format); } // Set the mask padding MaskPadding = padding; // Set the image options Options = options; // Subscribe to DeviceReplaced event _generator.DeviceReplaced += OnDeviceReplaced; }
/// <summary> /// Handles the DeviceReplaced event /// </summary> /// <param name="sender">Sender</param> /// <param name="e">object</param> private void OnDeviceReplaced(object sender, object e) { // Recreate the GaussianMaskSurface _surface = _generator.CreateDrawingSurface(_surfaceLock, Size); // Redraw the mask surface RedrawSurface(); }
public void Dispose() { if (_surface != null) { _surface.Dispose(); _surface = null; } if (_brush != null) { _brush.Dispose(); _brush = null; } _drawer = null; //ImageLoader.Instance.UnregisterSurface(this); }
public async void PrepareEntranceEffect() { Compositor compositor = ElementCompositionPreview.GetElementVisual(BasePageObject).Compositor; Vector2 windowSize = new Vector2((float)Window.Current.Bounds.Width, (float)Window.Current.Bounds.Height); //1.创建ContainerVisual实例填充背景色和图片; //2.设置中心缩放 ContainerVisual cv = compositor.CreateContainerVisual(); cv.Size = windowSize; cv.CenterPoint = new Vector3(windowSize.X, windowSize.Y, 0) * 0.5f; ElementCompositionPreview.SetElementChildVisual(BasePageObject, cv); //创建sprite的背景色为APP的主题色 SpriteVisual backgroundSprite = compositor.CreateSpriteVisual(); backgroundSprite.Size = windowSize; backgroundSprite.Brush = compositor.CreateColorBrush((Color)Application.Current.Resources["SystemAccentColor"]); cv.Children.InsertAtBottom(backgroundSprite); //创建包含初始屏图像的sprite的尺寸和位置 CompositionDrawingSurface surface = await SurfaceLoader.LoadFromUri(new Uri("ms-appx:///Assets/SplashScreen.png")); SpriteVisual imageSprite = compositor.CreateSpriteVisual(); imageSprite.Brush = compositor.CreateSurfaceBrush(surface); imageSprite.Offset = new Vector3((float)SplashScreenRect.X, (float)SplashScreenRect.Y, 0f); imageSprite.Size = new Vector2((float)SplashScreenRect.Width, (float)SplashScreenRect.Height); cv.Children.InsertAtTop(imageSprite); }
public DebugBitmapDialog(string title, CanvasBitmap bitmap) { this.InitializeComponent(); Title = title; RootGrid.Width = bitmap.Size.Width; RootGrid.Height = bitmap.Size.Height; var compositor = Window.Current.Compositor; var visual = compositor.CreateSpriteVisual(); visual.RelativeSizeAdjustment = Vector2.One; var brush = compositor.CreateSurfaceBrush(); brush.Stretch = CompositionStretch.Uniform; brush.BitmapInterpolationMode = CompositionBitmapInterpolationMode.NearestNeighbor; brush.HorizontalAlignmentRatio = 0.5f; brush.VerticalAlignmentRatio = 0.5f; visual.Brush = brush; var surfaceFactory = SurfaceFactory.GetSharedSurfaceFactoryForCompositor(compositor); _surface = surfaceFactory.CreateSurface(bitmap.Size); SurfaceUtilities.FillSurfaceWithDirect3DSurface(surfaceFactory, _surface, bitmap); brush.Surface = _surface; _bitmap = bitmap; ElementCompositionPreview.SetElementChildVisual(RootGrid, visual); }
public Screenshot() { _canvasDevice = new CanvasDevice(); _compositionGraphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice( Window.Current.Compositor, _canvasDevice); _compositor = Window.Current.Compositor; _surface = _compositionGraphicsDevice.CreateDrawingSurface( new Size(400, 400), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied); // This is the only value that currently works with // the composition APIs. //var visual = _compositor.CreateSpriteVisual(); //visual.RelativeSizeAdjustment = Vector2.One; //var brush = _compositor.CreateSurfaceBrush(_surface); //brush.HorizontalAlignmentRatio = 0.5f; //brush.VerticalAlignmentRatio = 0.5f; //brush.Stretch = CompositionStretch.Uniform; //visual.Brush = brush; //ElementCompositionPreview.SetElementChildVisual(this, visual); }
#pragma warning disable 1998 public async Task Draw(CompositionGraphicsDevice device, Object drawingLock, CompositionDrawingSurface surface, Size size) { using (var ds = CanvasComposition.CreateDrawingSession(surface)) { ds.Clear(Colors.Transparent); ds.FillCircle(new Vector2(_radius, _radius), _radius, _color); } }
private void Setup() { _canvasDevice = new CanvasDevice(); _compositionGraphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice( Windows.UI.Xaml.Window.Current.Compositor, _canvasDevice); _compositor = Windows.UI.Xaml.Window.Current.Compositor; _surface = _compositionGraphicsDevice.CreateDrawingSurface( new Windows.Foundation.Size(400, 400), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied); // This is the only value that currently works with // the composition APIs. var visual = _compositor.CreateSpriteVisual(); visual.RelativeSizeAdjustment = Vector2.One; var brush = _compositor.CreateSurfaceBrush(_surface); brush.HorizontalAlignmentRatio = 0.5f; brush.VerticalAlignmentRatio = 0.5f; brush.Stretch = CompositionStretch.Uniform; visual.Brush = brush; ElementCompositionPreview.SetElementChildVisual(this, visual); StartCaptureInternal(MainPage.targetcap); }
protected override void UpdateSpriteVisual(SpriteVisual spriteVisual, CompositionDrawingSurface drawingSurface) { var maskSurfaceBrush = Compositor.CreateSurfaceBrush(DrawingSurface); _maskBrush.Mask = maskSurfaceBrush; spriteVisual.Brush = _maskBrush; }
public void Dispose() { _surface.Dispose(); _imageLoader.DeviceReplacedEvent -= OnDeviceReplaced; _surface = null; _imageLoader = null; }
protected override void OnDisconnected() { if (CompositionBrush != null) { IsConnected = false; canvasDevice.Dispose(); canvasDevice = null; graphicsDevice.Dispose(); graphicsDevice = null; surfaceBrush1.Dispose(); surfaceBrush1 = null; surfaceBrush2.Dispose(); surfaceBrush2 = null; surface1.Dispose(); surface1 = null; surface2.Dispose(); surface2 = null; Source1Animation.Dispose(); Source1Animation = null; Source2Animation.Dispose(); Source2Animation = null; colorBrush1.Dispose(); colorBrush1 = null; colorBrush2.Dispose(); colorBrush2 = null; CompositionBrush.Dispose(); CompositionBrush = null; } }
private async Task <CompositionBrush> ShadowMask(UIElement uiElement, Compositor compositor) { CompositionBrush compositionBrush; switch (uiElement) { case Shape shape: compositionBrush = shape.GetAlphaMask(); break; case TextBlock textBlock: compositionBrush = textBlock.GetAlphaMask(); break; case Image image: compositionBrush = image.GetAlphaMask(); break; default: CompositionDrawingSurface drawingSurface = await CompositionDrawingSurfaceFacade2.GetCompositionDrawingSurface(uiElement, compositor); compositionBrush = compositor.CreateSurfaceBrush(drawingSurface); break; } return(compositionBrush); }
private CompositionDrawingSurface SampleImageColor(CanvasBitmap bitmap, CompositionGraphicsDevice device, Size sizeTarget) { // Extract the color to tint the blur with Color predominantColor = ExtractPredominantColor(bitmap.GetPixelColors(), bitmap.Size); Size sizeSource = bitmap.Size; if (sizeTarget.IsEmpty) { sizeTarget = sizeSource; } // Create a heavily blurred version of the image GaussianBlurEffect blurEffect = new GaussianBlurEffect() { Source = bitmap, BlurAmount = 20.0f }; CompositionDrawingSurface surface = device.CreateDrawingSurface(sizeTarget, DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied); using (var ds = CanvasComposition.CreateDrawingSession(surface)) { Rect destination = new Rect(0, 0, sizeTarget.Width, sizeTarget.Height); ds.FillRectangle(destination, predominantColor); ds.DrawImage(blurEffect, destination, new Rect(0, 0, sizeSource.Width, sizeSource.Height), .6f); } return(surface); }
private static async Task <CompositionDrawingSurface> GetCompositionDrawingSurface(Compositor compositor, RenderTargetBitmap renderTargetBitmap) { IBuffer pixels = await renderTargetBitmap.GetPixelsAsync(); using (var canvasDevice = new CanvasDevice()) using (CompositionGraphicsDevice graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, canvasDevice)) { float dpi = DisplayInformation.GetForCurrentView().LogicalDpi; using (var canvasBitmap = CanvasBitmap.CreateFromBytes(canvasDevice, pixels.ToArray(), renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight, DirectXPixelFormat.B8G8R8A8UIntNormalized, dpi)) { CompositionDrawingSurface surface = graphicsDevice.CreateDrawingSurface( new Size(renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied); using (CanvasDrawingSession session = CanvasComposition.CreateDrawingSession(surface)) { session.DrawImage(canvasBitmap, 0, 0, new Rect(0, 0, canvasBitmap.Size.Width, canvasBitmap.Size.Height)); } return(surface); } } }
CompositionDrawingSurface ApplyBlurEffect(CanvasBitmap bitmap, Windows.UI.Composition.CompositionGraphicsDevice device, Size sizeTarget) { GaussianBlurEffect blurEffect = new GaussianBlurEffect() { Source = bitmap, BlurAmount = 20.0f, BorderMode = EffectBorderMode.Hard, }; float fDownsample = .3f; Size sizeSource = bitmap.Size; if (sizeTarget == Size.Empty) { sizeTarget = sizeSource; } sizeTarget = new Size(sizeTarget.Width * fDownsample, sizeTarget.Height * fDownsample); CompositionDrawingSurface blurSurface = device.CreateDrawingSurface(sizeTarget, DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied); using (var ds = CanvasComposition.CreateDrawingSession(blurSurface)) { Rect destination = new Rect(0, 0, sizeTarget.Width, sizeTarget.Height); ds.Clear(Windows.UI.Color.FromArgb(255, 255, 255, 255)); ds.DrawImage(blurEffect, destination, new Rect(0, 0, sizeSource.Width, sizeSource.Height)); } return(blurSurface); }
void CreateDrawingSurface(global::Windows.Foundation.Size drawSize) { _drawingSurface = _graphicsDevice.CreateDrawingSurface( drawSize, DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied); }
public async void PrepareEntranceEffect() { try { Compositor BaseCompositor = ElementCompositionPreview.GetElementVisual(BasePage).Compositor; Vector2 WindowSize = new Vector2(Convert.ToSingle(Window.Current.Bounds.Width), Convert.ToSingle(Window.Current.Bounds.Height)); ContainerVisual Visual = BaseCompositor.CreateContainerVisual(); Visual.Size = WindowSize; Visual.CenterPoint = new Vector3(WindowSize.X, WindowSize.Y, 0) * 0.5f; ElementCompositionPreview.SetElementChildVisual(BasePage, Visual); SpriteVisual BackgroundSprite = BaseCompositor.CreateSpriteVisual(); BackgroundSprite.Size = WindowSize; BackgroundSprite.Brush = BaseCompositor.CreateColorBrush((Color)Application.Current.Resources["SystemAccentColor"]); Visual.Children.InsertAtBottom(BackgroundSprite); CompositionDrawingSurface ImageDrawingSurface = await SurfaceLoader.LoadFromUri(new Uri("ms-appx:///Assets/SplashScreen.png")); SpriteVisual ImageSprite = BaseCompositor.CreateSpriteVisual(); ImageSprite.Brush = BaseCompositor.CreateSurfaceBrush(ImageDrawingSurface); ImageSprite.Offset = new Vector3(Convert.ToSingle(SplashScreenRect.X), Convert.ToSingle(SplashScreenRect.Y), 0f); ImageSprite.Size = new Vector2(Convert.ToSingle(SplashScreenRect.Width), Convert.ToSingle(SplashScreenRect.Height)); Visual.Children.InsertAtTop(ImageSprite); } catch (Exception ex) { Debug.WriteLine($"Error in PrepareEntranceEffect, message:{ex.Message}"); } }
/// <summary> /// Redraws the mask surface with the given size and geometry /// </summary> /// <param name="surface">CompositionDrawingSurface</param> /// <param name="size">Size ofthe Mask Surface</param> /// <param name="geometry">Geometry of the Mask Surface</param> /// <returns>Task</returns> public Task RedrawMaskSurfaceAsync(CompositionDrawingSurface surface, Size size, CanvasGeometry geometry) { return(Task.Run(() => { // // Since the drawing is done asynchronously and multiple threads could // be trying to get access to the device/surface at the same time, we need // to do any device/surface work under a lock. // lock (_drawingLock) { // Render the mask to the surface using (var session = CanvasComposition.CreateDrawingSession(surface)) { // If the geometry is not null then fill the geometry area // with white. The rest of the area on the surface will be transparent. // When this mask is applied to a visual, only the area that is white // will be visible. if (geometry != null) { session.Clear(Colors.Transparent); session.FillGeometry(geometry, Colors.White); } else { // If the geometry is null, then the entire mask should be filled white // so that the masked visual can be seen completely. session.Clear(Colors.White); } } } })); }
private async void ApplyEffect(CompositionImage image) { Task <CompositionDrawingSurface> task = null; // If we've requested a load time effect input, kick it off now if (_currentTechnique.LoadTimeEffectHandler != null) { task = SurfaceLoader.LoadFromUri(image.Source, Size.Empty, _currentTechnique.LoadTimeEffectHandler); } // Create the new brush, set the inputs and set it on the image CompositionEffectBrush brush = _currentTechnique.CreateBrush(); brush.SetSourceParameter("ImageSource", image.SurfaceBrush); image.Brush = brush; // If we've got an active task, wait for it to finish if (task != null) { CompositionDrawingSurface effectSurface = await task; // Set the effect surface as input brush.SetSourceParameter("EffectSource", _compositor.CreateSurfaceBrush(effectSurface)); } }
public ManagedSurface(CompositionDrawingSurface surface) { Debug.Assert(surface != null); _surface = surface; ImageLoader.Instance.RegisterSurface(this); }
public void DrawIntoSurface(CompositionDrawingSurface surface, DrawingCallback callback) { lock (_drawingLock) { callback(surface, _graphicsDevice); } }
private void BackgroundImage_FirstOpened(object sender, RoutedEventArgs e) { // Image loaded, let's show the content this.Opacity = 1; // Show the content now that we should have something. ScalarKeyFrameAnimation fadeInAnimation = _compositor.CreateScalarKeyFrameAnimation(); fadeInAnimation.InsertKeyFrame(0, 0); fadeInAnimation.InsertKeyFrame(1, 1); fadeInAnimation.Duration = TimeSpan.FromMilliseconds(1000); BackgroundImage.SpriteVisual.StartAnimation("Opacity", fadeInAnimation); ElementCompositionPreview.GetElementVisual(ImageList).StartAnimation("Opacity", fadeInAnimation); // Start a slow UV scale to create movement in the background image Vector2KeyFrameAnimation scaleAnimation = _compositor.CreateVector2KeyFrameAnimation(); scaleAnimation.InsertKeyFrame(0, new Vector2(1.1f, 1.1f)); scaleAnimation.InsertKeyFrame(.5f, new Vector2(2.0f, 2.0f)); scaleAnimation.InsertKeyFrame(1, new Vector2(1.1f, 1.1f)); scaleAnimation.Duration = TimeSpan.FromMilliseconds(40000); scaleAnimation.IterationBehavior = AnimationIterationBehavior.Forever; CompositionDrawingSurface surface = (CompositionDrawingSurface)BackgroundImage.SurfaceBrush.Surface; BackgroundImage.SurfaceBrush.CenterPoint = new Vector2((float)surface.Size.Width, (float)surface.Size.Height) * .5f; BackgroundImage.SurfaceBrush.StartAnimation("Scale", scaleAnimation); // Start the animation of the cross-fade brush so they're in sync _previousSurfaceBrush = _compositor.CreateSurfaceBrush(); _previousSurfaceBrush.StartAnimation("Scale", scaleAnimation); BackgroundImage.ImageOpened -= BackgroundImage_FirstOpened; }
private async Task InitControl() { // // Create the sperical normal map. The normals will give the appearance of a sphere, and the alpha channel is used // for masking off the rectangular edges. // //CompositionDrawingSurface normalMap = await SurfaceLoader.LoadFromUri(new Uri("ms-appx:///X.UI.Composition.Assets/SphericalWithMask.png")); CompositionDrawingSurface normalMap = await SurfaceLoader.LoadFromUri(new Uri("ms-appx:///X.UI.Composition.Assets/BeveledEdges.jpg")); _circleNormalsBrush = _compositor.CreateSurfaceBrush(normalMap); _circleNormalsBrush.Stretch = CompositionStretch.Fill; // // Create the flat normal map with beveled edges. This should give the appearance of slanting of the surface along // the edges, flat in the middle. // normalMap = await SurfaceLoader.LoadFromUri(new Uri("ms-appx:///X.UI.Composition.Assets/BeveledEdges.jpg")); _flatNormalsBrush = _compositor.CreateSurfaceBrush(normalMap); _flatNormalsBrush.Stretch = CompositionStretch.Fill; // Update the effect brushes now that the normal maps are available. UpdateEffectBrush(); }
/// <summary> /// Handles the DeviceReplaced event /// </summary> /// <param name="sender">Sender</param> /// <param name="e">object</param> private void OnDeviceReplaced(object sender, object e) { // Recreate the GeometrySurface _surface = _generator.CreateDrawingSurface(_surfaceLock, Size); // Redraw the GeometrySurface RedrawSurfaceInternal(); }
public async Task Draw(CompositionGraphicsDevice device, Object drawingLock, CompositionDrawingSurface surface, Size size) { using (var ds = CanvasComposition.CreateDrawingSession(surface)) { ds.Clear(_backgroundColor); ds.DrawText(_text, new Rect(0, 0, surface.Size.Width, surface.Size.Height), _textColor, _textFormat); } }
private CompositionSurfaceBrush CreateBrushFromAsset(SoftwareBitmap softwareBitmap, out Size size) { CompositionDrawingSurface surface = ImageLoader.Instance.LoadFromSoftwareBitmap(softwareBitmap, Size.Empty, null).Surface; size = surface.Size; return(m_compositor.CreateSurfaceBrush(surface)); }
private CompositionSurfaceBrush CreateBrushFromAsset(string name, out Size size) { CompositionDrawingSurface surface = ImageLoader.Instance.LoadFromUri(new Uri("ms-appx:///Assets/" + name)).Surface; size = surface.Size; return(m_compositor.CreateSurfaceBrush(surface)); }
public async Task DrawSurface(CompositionDrawingSurface surface, Uri uri, Size size) { var canvasDevice = CanvasComposition.GetCanvasDevice(_graphicsDevice); using (var canvasBitmap = await CanvasBitmap.LoadAsync(canvasDevice, uri)) { var bitmapSize = canvasBitmap.Size; // // Because the drawing is done asynchronously and multiple threads could // be trying to get access to the device/surface at the same time, we need // to do any device/surface work under a lock. // lock (_drawingLock) { Size surfaceSize = size; if (surfaceSize.IsEmpty) { // Resize the surface to the size of the image CanvasComposition.Resize(surface, bitmapSize); surfaceSize = bitmapSize; } // Draw the image to the surface using (var session = CanvasComposition.CreateDrawingSession(surface)) { session.Clear(Windows.UI.Color.FromArgb(0, 0, 0, 0)); session.DrawImage(canvasBitmap, new Rect(0, 0, surfaceSize.Width, surfaceSize.Height), new Rect(0, 0, bitmapSize.Width, bitmapSize.Height)); } } } }
/// <summary> /// Handles the DeviceReplaced event /// </summary> /// <param name="sender">Sender</param> /// <param name="e">object</param> private async void OnDeviceReplaced(object sender, object e) { // Recreate the ImageSurface _surface = _generator.CreateDrawingSurface(_surfaceLock, Size); // Reload the SurfaceImage await RedrawSurfaceImageInternalAsync(); }
// This animation has constant duration, speedy changes depending on the distance // between sourceElement and targetElement. public async Task StartAnimation2(FrameworkElement sourceElement, FrameworkElement targetElement) { Point point = sourceElement.TransformToVisual(_rootElement).TransformPoint(new Point(0, 0)); CompositionDrawingSurface surface = await CompositionDrawingSurfaceFacade1.GetCompositionDrawingSurface(sourceElement, _compositor); SpriteVisual spriteVisual = _compositor.CreateSpriteVisual(); spriteVisual.Brush = _compositor.CreateSurfaceBrush(surface); spriteVisual.Size = new Vector2((float)surface.Size.Width, (float)surface.Size.Height); spriteVisual.Offset = new Vector3((float)point.X, (float)point.Y, 0f); _containerVisual.Children.InsertAtBottom(spriteVisual); Vector3 targetOffset = GetTargetOffset(targetElement); Vector3KeyFrameAnimation offsetAnimation = _compositor.CreateVector3KeyFrameAnimation(); Vector2 targetSize = GetTargetSize(targetElement); Vector2KeyFrameAnimation sizeAnimation = _compositor.CreateVector2KeyFrameAnimation(); var newWidth = (float)(sourceElement.ActualWidth * 1.3); var newHeight = (float)(sourceElement.ActualHeight * 1.3); var newX = (float)(point.X - (newWidth - sourceElement.ActualWidth) / 2); var newY = (float)(point.Y - (newHeight - sourceElement.ActualHeight) / 2); double sizeDurationInMs = 250; double distance = Math.Sqrt(Math.Pow(targetOffset.X - newX, 2) + Math.Pow(targetOffset.Y - newY, 2)); double offsetDurationInMs = distance / 2; double animationDurationInMs = sizeDurationInMs + offsetDurationInMs; sizeAnimation.Duration = TimeSpan.FromMilliseconds(animationDurationInMs); offsetAnimation.Duration = TimeSpan.FromMilliseconds(animationDurationInMs); SetAnimationDefautls(offsetAnimation); SetAnimationDefautls(sizeAnimation); var normalizedProgressKey0 = (float)(sizeDurationInMs / animationDurationInMs); offsetAnimation.InsertKeyFrame(normalizedProgressKey0, new Vector3(newX, newY, 0f)); sizeAnimation.InsertKeyFrame(normalizedProgressKey0, new Vector2(newWidth, newHeight)); const float normalizedProgressKey1 = 1f; offsetAnimation.InsertKeyFrame(normalizedProgressKey1, targetOffset, _compositor.CreateLinearEasingFunction()); sizeAnimation.InsertKeyFrame(normalizedProgressKey1, targetSize, _compositor.CreateLinearEasingFunction()); CompositionScopedBatch myScopedBatch = _compositor.CreateScopedBatch(CompositionBatchTypes.Animation); var batchCompletitionAwaiter = new BatchCompletitionAwaiter(myScopedBatch); spriteVisual.StartAnimation("Offset", offsetAnimation); spriteVisual.StartAnimation("Size", sizeAnimation); myScopedBatch.End(); await batchCompletitionAwaiter.Completed(); myScopedBatch.Dispose(); spriteVisual.Dispose(); surface.Dispose(); offsetAnimation.Dispose(); sizeAnimation.Dispose(); }
public ManagedSurface(IImageLoaderInternal imageLoader, Uri uri, Size size) { _imageLoader = imageLoader; _uri = uri; _surface = _imageLoader.CreateSurface(size); _imageLoader.DeviceReplacedEvent += OnDeviceReplaced; }
public DrawingSurfaceRenderer(Compositor compositor, CompositionGraphicsDevice compositionGraphicsDevice) { drawingSurfaceVisual = compositor.CreateSpriteVisual(); drawingSurface = compositionGraphicsDevice.CreateDrawingSurface(new Size(256, 256), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied); drawingSurfaceVisual.Brush = compositor.CreateSurfaceBrush(drawingSurface); DrawDrawingSurface(); compositionGraphicsDevice.RenderingDeviceReplaced += CompositionGraphicsDevice_RenderingDeviceReplaced; }
public CircleSurface(IImageLoaderInternal imageLoader, float radius, Color color) { _imageLoader = imageLoader; _radius = radius; _color = color; _surface = _imageLoader.CreateSurface(new Size(radius * 2, radius * 2)); _imageLoader.DeviceReplacedEvent += OnDeviceReplaced; }
private void ReleaseContent() { if (_surface != null) { _surface.Dispose(); _surface = null; } if (_effectSurface != null) { _effectSurface.Dispose(); _effectSurface = null; } if (_effectBrush != null) { _effectBrush.Dispose(); _effectBrush = null; } }
/// <summary> /// Disposes the resources used by the MaskSurface /// </summary> public void Dispose() { _surface?.Dispose(); _geometry?.Dispose(); if (_generator != null) _generator.DeviceReplaced -= OnDeviceReplaced; _surface = null; _generator = null; _geometry = null; }
public void DrawIntoSurface(CompositionDrawingSurface surface, DrawingCallback callback) { lock(_drawingLock) { callback(surface, _graphicsDevice); } }
public void ResizeSurface(CompositionDrawingSurface surface, Size size) { if (!size.IsEmpty) { lock(_drawingLock) { CanvasComposition.Resize(surface, size); } } }
public async void SetEffectBrush(CompositionEffectBrush brush) { // Release previous brush if set if (_effectBrush != null) { _effectBrush.Dispose(); _effectBrush = null; } if (_effectSurface != null) { _effectSurface.Dispose(); _effectSurface = null; } _effectBrush = brush; // Set the new brush if (_sprite != null) { // Release current brush if (_sprite.Brush != null) { _sprite.Brush.Dispose(); } if (_surface != null) { // If the effect brush is cleared, create a surface brush if (_effectBrush == null) { _sprite.Brush = _compositor.CreateSurfaceBrush(_surface); } else { _effectBrush.SetSourceParameter("ImageSource", _compositor.CreateSurfaceBrush(_surface)); if (_loadEffectDelegate != null) { _effectSurface = await SurfaceLoader.LoadFromUri(_uri, Size.Empty, _loadEffectDelegate); _effectBrush.SetSourceParameter("EffectSource", _compositor.CreateSurfaceBrush(_effectSurface)); } _sprite.Brush = _effectBrush; } } } }
/// <summary> /// Constructor /// </summary> /// <param name="generator">ICompositionMaskGeneratorInternal object</param> /// <param name="size">Size of the MaskSurface</param> /// <param name="geometry">Geometry of the MaskSurface</param> public MaskSurface(ICompositionGeneratorInternal generator, Size size, CanvasGeometry geometry) { if (generator == null) throw new ArgumentNullException(nameof(generator), "CompositionGenerator cannot be null!"); _generator = generator; _surfaceLock = new object(); _geometry = geometry; // Create Mask Surface _surface = _generator.CreateDrawingSurface(_surfaceLock, size); // Set the size Size = _surface?.Size ?? new Size(0, 0); // Subscribe to DeviceReplaced event _generator.DeviceReplaced += OnDeviceReplaced; }
/// <summary> /// Handles the DeviceReplaced event /// </summary> /// <param name="sender">Sender</param> /// <param name="e">object</param> private void OnDeviceReplaced(object sender, object e) { // Recreate the MaskSurface _surface = _generator.CreateDrawingSurface(_surfaceLock, Size); // Redraw the mask surface RedrawSurfaceInternal(); }
private void ReleaseSurface() { if (_surface != null) { // If no one has asked to share, dispose it to free the memory if (!_sharedSurface) { _surface.Dispose(); _surfaceBrush.Surface = null; } _surface = null; } }
private async void LoadSurface() { // If we're clearing out the content, return if (_uri == null) { ReleaseSurface(); return; } try { // Start a timer to enable the placeholder image if requested if (_surface == null && _placeholderDelay >= TimeSpan.Zero) { _timer = new DispatcherTimer(); _timer.Interval = _placeholderDelay; _timer.Tick += Timer_Tick; _timer.Start(); } // Load the image asynchronously CompositionDrawingSurface surface = await SurfaceLoader.LoadFromUri(_uri, Size.Empty, _loadEffectDelegate); if (_surface != null) { ReleaseSurface(); } _surface = surface; // The surface has changed, so we need to re-measure with the new surface dimensions InvalidateMeasure(); // Async operations may take a while. If we've unloaded, return now. if (_unloaded) { ReleaseSurface(); return; } // Update the brush UpdateBrush(); // Success, fire the Opened event if (ImageOpened != null) { ImageOpened(this, null); } // // If we created the loading placeholder, now that the image has loaded // cross-fade it out. // if (_sprite != null && _sprite.Children.Count > 0) { Debug.Assert(_timer == null); StartCrossFade(); } else if (_timer != null) { // We didn't end up loading the placeholder, so just stop the timer _timer.Stop(); _timer = null; } } catch (FileNotFoundException) { if (ImageFailed != null) { ImageFailed(this, null); } } }
/// <summary> /// Resizes the Mask Surface to the given size /// </summary> /// <param name="surfaceLock">The object to lock to prevent multiple threads /// from accessing the surface at the same time.</param> /// <param name="surface">CompositionDrawingSurface</param> /// <param name="size">New size of the Mask Surface</param> public void ResizeDrawingSurface(object surfaceLock, CompositionDrawingSurface surface, Size size) { // Cannot resize to Size.Empty. Will throw exception! if (size.IsEmpty) return; // Ensuring that the size contains positive values size.Width = Math.Max(0, size.Width); size.Height = Math.Max(0, size.Height); // // Since multiple threads could be trying to get access to the device/surface // at the same time, we need to do any device/surface work under a lock. // lock (surfaceLock) { CanvasComposition.Resize(surface, size); } }
/// <summary> /// Redraws the MaskSurface with the given size and geometry /// </summary> /// <param name="surfaceLock">The object to lock to prevent multiple threads /// from accessing the surface at the same time.</param> /// <param name="surface">CompositionDrawingSurface</param> /// <param name="size">Size ofthe MaskSurface</param> /// <param name="geometry">Geometry of the MaskSurface</param> public void RedrawMaskSurface(object surfaceLock, CompositionDrawingSurface surface, Size size, CanvasGeometry geometry) { // If the surface is not created, create it if (surface == null) { surface = CreateDrawingSurface(surfaceLock, size); } // No need to render if the width and/or height of the surface is zero if (surface.Size.Width.IsZero() || surface.Size.Height.IsZero()) return; // // Since multiple threads could be trying to get access to the device/surface // at the same time, we need to do any device/surface work under a lock. // lock (surfaceLock) { // Render the mask to the surface using (var session = CanvasComposition.CreateDrawingSession(surface)) { if (geometry != null) { // If the geometry is not null then fill the geometry area // with the White color. The rest of the area on the surface will be transparent. // When this mask is applied to a visual, only the area that is white will be visible. session.Clear(Colors.Transparent); session.FillGeometry(geometry, Colors.White); } else { // If the geometry is null, then the entire mask should be filled the // the given color. If the color is white, then the masked visual will be seen completely. session.FillRectangle(0, 0, size.Width.Single(), size.Height.Single(), Colors.White); } } } }
public void Dispose() { _surface.Dispose(); _imageLoader.DeviceReplacedEvent -= OnDeviceReplaced; _surface = null; _imageLoader = null; _uri = null; }
/// <summary> /// Constructor /// </summary> /// <param name="generator">ICompositionMaskGeneratorInternal object</param> /// <param name="uri">Uri of the image to be loaded onto the SurfaceImage.</param> /// <param name="size">Size of the SurfaceImage</param> /// <param name="options">Describes the image's resize and alignment options in the allocated space.</param> public ImageSurface(ICompositionGeneratorInternal generator, Uri uri, Size size, ImageSurfaceOptions options) { if (generator == null) throw new ArgumentNullException(nameof(generator), "CompositionGenerator cannot be null!"); _generator = generator; _surfaceLock = new object(); // Create the Surface of the SurfaceImage _surface = _generator.CreateDrawingSurface(_surfaceLock, size); Size = _surface?.Size ?? new Size(0, 0); _uri = uri; _canvasBitmap = null; // Set the image options Options = options; // Subscribe to DeviceReplaced event _generator.DeviceReplaced += OnDeviceReplaced; }
private async void OnUriChanged() { if (_uri == null) { ReleaseContent(); return; } _surface = await SurfaceLoader.LoadFromUri(_uri); if (_loadEffectDelegate != null) { _effectSurface = await SurfaceLoader.LoadFromUri(_uri, Size.Empty, _loadEffectDelegate); } // Async operations may take a while. If we've unloaded, return now. if (_unloaded) { ReleaseContent(); return; } // Apply stretching policy ApplyStretchingPolicy(new Size(ActualWidth, ActualHeight)); if (_effectBrush == null) { CompositionSurfaceBrush brush = (CompositionSurfaceBrush)_sprite.Brush; if (brush != null) { brush.Surface = _surface; } else { _sprite.Brush = _compositor.CreateSurfaceBrush(_surface); } } else { _effectBrush.SetSourceParameter("ImageSource", _compositor.CreateSurfaceBrush(_surface)); if (_effectSurface != null) { _effectBrush.SetSourceParameter("EffectSource", _compositor.CreateSurfaceBrush(_effectSurface)); } _sprite.Brush = _effectBrush; } }
/// <summary> /// Disposes the resources used by the SurfaceImage /// </summary> public void Dispose() { _surface?.Dispose(); if (_generator != null) _generator.DeviceReplaced -= OnDeviceReplaced; _canvasBitmap?.Dispose(); _canvasBitmap = null; _surface = null; _generator = null; _uri = null; Options = null; }
/// <summary> /// Renders the CanvasBitmap on the CompositionDrawingSurface based on the given options. /// </summary> /// <param name="surfaceLock">The object to lock to prevent multiple threads /// from accessing the surface at the same time.</param> /// <param name="surface">CompositionDrawingSurface on which the CanvasBitmap has to be rendered.</param> /// <param name="canvasBitmap">CanvasBitmap created by loading the image from the Uri</param> /// <param name="options">Describes the image's resize and alignment options in the allocated space.</param> private static void RenderBitmap(object surfaceLock, CompositionDrawingSurface surface, CanvasBitmap canvasBitmap, ImageSurfaceOptions options) { var surfaceSize = surface.Size; // If the canvasBitmap is null, then just fill the surface with the SurfaceBackgroundColor if (canvasBitmap == null) { // No need to render if the width and/or height of the surface is zero if (surfaceSize.IsEmpty || surfaceSize.Width.IsZero() || surfaceSize.Height.IsZero()) return; // // Since multiple threads could be trying to get access to the device/surface // at the same time, we need to do any device/surface work under a lock. // lock (surfaceLock) { using (var session = CanvasComposition.CreateDrawingSession(surface)) { // Clear the surface with the SurfaceBackgroundColor session.Clear(options.SurfaceBackgroundColor); } // No need to proceed further return; } } // // Since multiple threads could be trying to get access to the device/surface // at the same time, we need to do any device/surface work under a lock. // lock (surfaceLock) { // Is AutoResize Enabled? if (options.AutoResize) { // If AutoResize is allowed and the canvasBitmap size and surface size are // not matching then resize the surface to match the canvasBitmap size. // // NOTE: HorizontalAlignment, Vertical Alignment and Stretch will be // handled by the CompositionSurfaceBrush created using this surface. // if (canvasBitmap.Size != surfaceSize) { // Resize the surface CanvasComposition.Resize(surface, canvasBitmap.Size); surfaceSize = canvasBitmap.Size; } // No need to render if the width and/or height of the surface is zero if (surfaceSize.IsEmpty || surface.Size.Width.IsZero() || surface.Size.Height.IsZero()) return; // Draw the image to the surface using (var session = CanvasComposition.CreateDrawingSession(surface)) { // Render the image session.DrawImage(canvasBitmap, // CanvasBitmap new Rect(0, 0, surfaceSize.Width, surfaceSize.Height), // Target Rectangle new Rect(0, 0, canvasBitmap.Size.Width, canvasBitmap.Size.Height), // Source Rectangle options.Opacity, // Opacity options.Interpolation); // Interpolation } } else { // No need to render if the width and/or height of the surface is zero if (surfaceSize.IsEmpty || surface.Size.Width.IsZero() || surface.Size.Height.IsZero()) return; var bitmapSize = canvasBitmap.Size; var sourceWidth = bitmapSize.Width; var sourceHeight = bitmapSize.Height; var ratio = sourceWidth / sourceHeight; var targetWidth = 0d; var targetHeight = 0d; var left = 0d; var top = 0d; // Stretch Mode switch (options.Stretch) { case Stretch.None: targetWidth = sourceWidth; targetHeight = sourceHeight; break; case Stretch.Fill: targetWidth = surfaceSize.Width; targetHeight = surfaceSize.Height; break; case Stretch.Uniform: // If width is greater than height if (ratio > 1.0) { targetHeight = Math.Min(surfaceSize.Width / ratio, surfaceSize.Height); targetWidth = targetHeight * ratio; } else { targetWidth = Math.Min(surfaceSize.Height * ratio, surfaceSize.Width); targetHeight = targetWidth / ratio; } break; case Stretch.UniformToFill: // If width is greater than height if (ratio > 1.0) { targetHeight = Math.Max(surfaceSize.Width / ratio, surfaceSize.Height); targetWidth = targetHeight * ratio; } else { targetWidth = Math.Max(surfaceSize.Height * ratio, surfaceSize.Width); targetHeight = targetWidth / ratio; } break; } // Horizontal Alignment switch (options.HorizontalAlignment) { case AlignmentX.Left: left = 0; break; case AlignmentX.Center: left = (surfaceSize.Width - targetWidth) / 2.0; break; case AlignmentX.Right: left = surfaceSize.Width - targetWidth; break; } // Vertical Alignment switch (options.VerticalAlignment) { case AlignmentY.Top: top = 0; break; case AlignmentY.Center: top = (surfaceSize.Height - targetHeight) / 2.0; break; case AlignmentY.Bottom: top = surfaceSize.Height - targetHeight; break; } // Draw the image to the surface using (var session = CanvasComposition.CreateDrawingSession(surface)) { // Clear the surface with the SurfaceBackgroundColor session.Clear(options.SurfaceBackgroundColor); // Render the image session.DrawImage(canvasBitmap, // CanvasBitmap new Rect(left, top, targetWidth, targetHeight), // Target Rectangle new Rect(0, 0, sourceWidth, sourceHeight), // Source Rectangle options.Opacity, // Opacity options.Interpolation); // Interpolation } } } }
public override async Task<CompositionDrawingSurface> LoadResources() { var graphicsEffect = new ArithmeticCompositeEffect { Name = "Arithmetic", Source1 = new CompositionEffectSourceParameter("ImageSource"), Source1Amount = .1f, Source2 = new Transform2DEffect { Name = "LightMapTransform", Source = new CompositionEffectSourceParameter("LightMap") }, Source2Amount = 0, MultiplyAmount = 1 }; _effectFactory = _compositor.CreateEffectFactory(graphicsEffect, new[] { "LightMapTransform.TransformMatrix" }); // Create the image _lightMap = await SurfaceLoader.LoadFromUri(new Uri("ms-appx:///Samples/SDK 10586/PointerEnterEffects/pointmap.jpg")); // Create the animations CubicBezierEasingFunction easeIn = _compositor.CreateCubicBezierEasingFunction(new Vector2(0.0f, 0.51f), new Vector2(1.0f, 0.51f)); _enterAnimation = _compositor.CreateScalarKeyFrameAnimation(); _enterAnimation.InsertKeyFrame(0.33f, 1.25f, easeIn); _enterAnimation.InsertKeyFrame(0.66f, 0.75f, easeIn); _enterAnimation.InsertKeyFrame(1.0f, 1.0f, easeIn); _enterAnimation.Duration = TimeSpan.FromMilliseconds(5000); _enterAnimation.IterationBehavior = AnimationIterationBehavior.Forever; _exitAnimation = _compositor.CreateVector2KeyFrameAnimation(); _exitAnimation.InsertKeyFrame(1.0f, new Vector2(0, 0)); _exitAnimation.Duration = TimeSpan.FromMilliseconds(750); _exitAnimation.IterationBehavior = AnimationIterationBehavior.Count; _exitAnimation.IterationCount = 1; _transformExpression = _compositor.CreateExpressionAnimation("Matrix3x2(props.Scale, 0, 0, props.Scale, props.CenterPointOffset.X * (1-props.Scale) + (props.Translate.X * props.CenterPointOffset.X * 2), props.CenterPointOffset.Y * (1-props.Scale) + (props.Translate.Y * props.CenterPointOffset.Y * 2))"); return null; }
/// <summary> /// Constructor /// </summary> /// <param name="generator">ICompositionMaskGeneratorInternal object</param> /// <param name="size">Size of the GeometrySurface</param> /// <param name="geometry">Geometry of the GeometrySurface</param> /// <param name="foregroundColor">Fill color of the geometry</param> /// <param name="backgroundColor">Brush to fill the GeometrySurface background surface which is /// not covered by the geometry</param> public GeometrySurface(ICompositionGeneratorInternal generator, Size size, CanvasGeometry geometry, Color foregroundColor, Color backgroundColor) { if (generator == null) throw new ArgumentNullException(nameof(generator), "CompositionGenerator cannot be null!"); _generator = generator; _surfaceLock = new object(); _geometry = geometry; _foregroundBrush = new CanvasSolidColorBrush(_generator.Device, foregroundColor); _backgroundBrush = new CanvasSolidColorBrush(_generator.Device, backgroundColor); // Create GeometrySurface _surface = _generator.CreateDrawingSurface(_surfaceLock, size); // Set the size Size = _surface?.Size ?? new Size(0, 0); // Subscribe to DeviceReplaced event _generator.DeviceReplaced += OnDeviceReplaced; }
/// <summary> /// Resizes the ImageSurface to the given size and redraws the ImageSurface /// by rendering the canvasBitmap onto the surface. /// </summary> /// <param name="surfaceLock">The object to lock to prevent multiple threads /// from accessing the surface at the same time.</param> /// <param name="surface">CompositionDrawingSurface</param> /// <param name="options">Describes the image's resize and alignment options in the allocated space.</param> /// <param name="canvasBitmap">The CanvasBitmap on which the image is loaded.</param> public void RedrawImageSurface(object surfaceLock, CompositionDrawingSurface surface, ImageSurfaceOptions options, CanvasBitmap canvasBitmap) { // Render the image to the surface RenderBitmap(surfaceLock, surface, canvasBitmap, options); }
/// <summary> /// Resizes the ImageSurface with the given size and redraws the ImageSurface by loading /// image from the new Uri. /// </summary> /// <param name="surfaceLock">The object to lock to prevent multiple threads /// from accessing the surface at the same time.</param> /// <param name="surface">CompositionDrawingSurface</param> /// <param name="uri">Uri of the image to be loaded onto the SurfaceImage.</param> /// <param name="options">Describes the image's resize and alignment options in the allocated space.</param> /// <param name="canvasBitmap">The CanvasBitmap on which the image is loaded.</param> /// <returns>CanvasBitmap</returns> public async Task<CanvasBitmap> RedrawImageSurfaceAsync(object surfaceLock, CompositionDrawingSurface surface, Uri uri, ImageSurfaceOptions options, CanvasBitmap canvasBitmap) { if ((canvasBitmap == null) && (uri != null)) { try { canvasBitmap = await CanvasBitmap.LoadAsync(_canvasDevice, uri); } catch (IOException) { // Do nothing here as RenderBitmap method will fill the surface // with options.SurfaceBackgroundColor as the image failed to load // from Uri } } // Render the image to the surface RenderBitmap(surfaceLock, surface, canvasBitmap, options); return canvasBitmap; }
/// <summary> /// Redraws the GeometrySurface with the given size, geometry, foreground brush and background brush /// </summary> /// <param name="surfaceLock">The object to lock to prevent multiple threads /// from accessing the surface at the same time.</param> /// <param name="surface">CompositionDrawingSurface</param> /// <param name="size">Size ofthe GeometrySurface</param> /// <param name="geometry">Geometry of the GeometrySurface</param> /// <param name="foregroundBrush">The brush with which the geometry has to be filled</param> /// <param name="backgroundBrush">The brush with which the GeometrySurface background has to be filled</param> public void RedrawGeometrySurface(object surfaceLock, CompositionDrawingSurface surface, Size size, CanvasGeometry geometry, ICanvasBrush foregroundBrush, ICanvasBrush backgroundBrush) { // If the surface is not created, create it if (surface == null) { surface = CreateDrawingSurface(surfaceLock, size); } // No need to render if the width and/or height of the surface is zero if (surface.Size.Width.IsZero() || surface.Size.Height.IsZero()) return; // // Since multiple threads could be trying to get access to the device/surface // at the same time, we need to do any device/surface work under a lock. // lock (surfaceLock) { // Render the mask to the surface using (var session = CanvasComposition.CreateDrawingSession(surface)) { // First fill the background var brush = backgroundBrush as CanvasSolidColorBrush; if (brush != null) { // If the backgroundBrush is a SolideColorBrush then use the Clear() // method to fill the surface with background color. It is faster. // Clear the surface with the background color session.Clear(brush.Color); } else { // Fill the surface with the background brush. session.FillRectangle(0, 0, size.Width.Single(), size.Height.Single(), backgroundBrush); } // If the geometry is not null then fill the geometry area with the foreground brush. if (geometry != null) { session.FillGeometry(geometry, foregroundBrush); } } } }
public override async Task<CompositionDrawingSurface> LoadResources() { var graphicsEffect = new ArithmeticCompositeEffect { Name = "Arithmetic", Source1 = new CompositionEffectSourceParameter("ImageSource"), Source1Amount = .25f, Source2 = new Transform2DEffect { Name = "LightMapTransform", Source = new CompositionEffectSourceParameter("LightMap") }, Source2Amount = 0, MultiplyAmount = 1 }; _effectFactory = _compositor.CreateEffectFactory(graphicsEffect, new[] { "LightMapTransform.TransformMatrix" }); // Create the image _lightMap = await SurfaceLoader.LoadFromUri(new Uri("ms-appx:///Samples/SDK 10586/PointerEnterEffects/conemap.jpg")); // Create the animations float sweep = (float)Math.PI / 10f; float fullCircle = (float)Math.PI * -2f; _enterAnimation = _compositor.CreateScalarKeyFrameAnimation(); _enterAnimation.InsertKeyFrame(0.1f, fullCircle); _enterAnimation.InsertKeyFrame(0.4f, fullCircle + sweep); _enterAnimation.InsertKeyFrame(0.8f, fullCircle - sweep); _enterAnimation.InsertKeyFrame(1.0f, fullCircle); _enterAnimation.Duration = TimeSpan.FromMilliseconds(4500); _enterAnimation.IterationBehavior = AnimationIterationBehavior.Count; _enterAnimation.IterationCount = 1; _exitAnimation = _compositor.CreateScalarKeyFrameAnimation(); _exitAnimation.InsertKeyFrame(1.0f, 0f); _exitAnimation.Duration = TimeSpan.FromMilliseconds(1000); _exitAnimation.IterationBehavior = AnimationIterationBehavior.Count; _exitAnimation.IterationCount = 1; _transformExpression = _compositor.CreateExpressionAnimation("Matrix3x2.CreateFromTranslation(-props.CenterPointOffset) * Matrix3x2(cos(props.Rotation) * props.Scale, sin(props.Rotation), -sin(props.Rotation), cos(props.Rotation) * props.Scale, 0, 0) * Matrix3x2.CreateFromTranslation(props.CenterPointOffset + props.Translate)"); return null; }