CompositionProToolkit v0.4.6 released

Another update to CompositionProToolkit this week with couple of feature additions to ImageFrame and some bug fixes.

ImageFrame

Optimized Shadow

ImageFrame now provides a new dependency property called OptimizeShadow which allows multiple ImageFrame instances to share the same DropShadow instance. You can set this property to True when you are displaying several ImageFrame instances within a single container and each ImageFrame instance has shadow enabled. This will reduce the memory footprint.

Dependency Property Type Description Default Value
OptimizeShadow Boolean Indicates whether the ImageFrame should use a shared shadow object to display the shadow. False

IDisposable

ImageFrame now implements the IDisposable interface and thus provides a Dispose method to free up resources. ImageFrame internally uses several Composition objects which must be disposed to optimize the memory usage within your app.

Guidelines for effectively disposing ImageFrame

Consider a scenario where you are displaying several ImageFrame instances in a GridView within a page. When the app navigates away from the page, then you must dispose the ImageFrame instances like this

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    foreach (var imgFrame in ItemGridView.GetDescendantsOfType())
    {
        imgFrame.Dispose();
    }    
    VisualTreeHelper.DisconnectChildrenRecursive(ItemGridView);
    ItemGridView.ItemsSource = null;
    ItemGridView.Items?.Clear();

    base.OnNavigatedFrom(e);
}

Frosted Glass Effect Brush

A new extension method CreateFrostedGlassBrush has been added to Compositor which, as the name suggests, allows you to create a custom shaped brush which gives a frosted glass effect. The main difference between this method and the CreateMaskedBackdropBrush is that when you apply the FrostedGlassBrush to a visual with a DropShadow, it will look better, whereas with the MaskedBackdropBrush, the shadow will darken the visual.

FrostedGlassEffect.png

You can obtain the mask from the FrostedGlass effect brush, to apply to the DropShadow, in the following way

var roundRectGeometry = CanvasGeometry.CreateRoundedRectangle(_generator.Device, 
    0, 0, _width, _height, 25, 25);
var maskSurface = _generator.CreateMaskSurface(visual.Size.ToSize(),
     roundRectGeometry);
var frostedBrush = _compositor.CreateFrostedGlassBrush(maskSurface,
     Colors.AntiqueWhite, 30f, _backdropBrush);

var shadow = _compositor.CreateDropShadow();
shadow.Opacity = 0.5f;
shadow.Color = Colors.Black;
shadow.Offset = new Vector3(10, 10, 0);
shadow.BlurRadius = 15;

// Apply the mask to the shadow
shadow.Mask = frostedBrush.GetSourceParameter("mask");

visual.Brush = frostedBrush;
visual.Shadow = shadow;

The FrostedGlass effect brush was inspired from this blog post.

The latest source code is available in GitHub and the NuGet package is available here.

CompositionProToolkit v0.4.5 released!

The past few releases were mostly dedicated to refactoring and ImageFrame. CompositionProToolkit v0.4.5 continues the tradition and brings in new additions to code and a few new features to the ImageFrame control.

CompositionProToolkit.Expressions

cpte_banner.png

Well, this task was pending for a long time! CompositionExpressionToolkit code now has been merged into CompositionProToolkit under the CompositionProToolkit.Expressions namespace. If you have not used the CompositionExpressionToolkit project before you can find out more more details about CompositionProToolkit.Expressions here.

ImageFrame

In this release, ImageFrame has got a few feature modifications and additions.

ImageFrame Source

The Source property of ImageFrame is of now of type object and it can accept the following types

  • Uri
  • String (from which a Uri can be successfully created)
  • StorageFile
  • IRandomAccessStream

Image Caching

Image caching is permanently enabled now. ImageFrame will internally cache the objects provided to Source property. The cache is located in the temporary folder of the application using the ImageFrame.

As a result, the following property has been deprecated and removed from ImageFrame

  • UseImageCache

You can clear the cache anytime you want by using the following code

await ImageCache.ClearCacheAsync();

ImageFrame Transitions

CPTT_1.gif

ImageFrame provides several transition animations while displaying the newly loaded image. You can configure which animation to run by setting the TransitionMode property of the imageFrame.

Dependency Property Type Description Default Value
TransitionMode TransitionModeType Indicates the type of transition animation to employ for displaying an image after it has been loaded. TransitionModeType.FadeIn

TransitionMode property can be set to any of the following values defined in the TransitionModeType enumeration

  • FadeIn – The newly loaded image fades into view.
  • SlideLeft – The newly loaded image slides into view from the right side of the ImageFrame and moves left.
  • SlideRight – The newly loaded image slides into view from the left side of the ImageFrame and moves right.
  • SlideUp – The newly loaded image slides into view from the bottom of the ImageFrame and moves up.
  • SlideDown – The newly loaded image slides into view from the top of the ImageFrame and moves down.
  • ZoomIn – The newly loaded image zooms into view from the center of the ImageFrame.

ImageFrame Placeholder

The ShowPlaceholder property is now set to True by default.

Latest source code is available in GitHub and Nuget package is available here.

CompositionProToolkit v0.4.4 released

Though CompositionProToolkit v0.4.4 was initially planned to be a small update aimed at fixing bugs and improving the user experience of the CompositionImageFrame, it turned out to be a larger update, ultimately requiring one of the oldest class in CompositionProToolkit to be refactored. Midway between the first phase of refactoring, I came up with another idea which led to the whole refactored code being discarded. I had to restart the refactoring from scratch and the final code appears to be much more streamlined than it was earlier. Another reason for refactoring was to shorten the names of the classes. Adding Composition to each of the classes resulted in very long names (CompositionSurfaceImageOptions for example).

Unfortunately, this refactoring led to some breaking changes again! But let me assure you, the pains that you will take to accommodate these breaking changes in your existing code will save a lot of headaches in the future.

Without much ado, let us delve into the details.

Breaking Changes

ICompositionMask

Of late, due to ever increasing requirements, I was adding more features to ICompositionMask which resulted in the class getting bloated. This class was playing a dual role – One, as the building block for creating a CompositionMaskBrush to render custom shaped visuals. Two, as the building block for creating a CompositionSurfaceBrush for rendering custom shaped geometries onto visuals.

Addition of new capabilities in ICompositionMask also introduced several flags in order to differentiate the two behaviors. It was high time to split them into two three interfaces –

  • IRenderSurface – This interface acts as the base interface for interfaces which render to the ICompositionSurface. It mainly contains references to an ICompositionGenerator object and an ICompositionSurface object which are the core objects required for rendering any geometry or image onto a ICompositionSurface.
  • IMaskSurface – This interface is used for rendering custom shaped geometries onto ICompositionSurface so that they can be useds as masks on Composition Visuals.
  • IGeometrySurface – This interface is used for rendering custom shaped geometries onto ICompositionSurface.

Both IMaskSurface and IGeometrySurface derive from IRenderSurface. Here is the interface hierarchy

RenderSurfaces

ICompositionSurfaceImage

If you look at the interface hierarchy image above, you will notice a fourth interface mentioned there – IImageSurface. It is actually the ICompositionSurfaceImage interface which has been refactored.

CompositionGenerator

CompositionGenerator‘s CreateMask APIs have been refactored into separate APIs for creating the three different types of render surfaces

IMaskSurface CreateMaskSurface(Size size, CanvasGeometry geometry);
IGeometrySurface CreateGeometrySurface(Size size, CanvasGeometry geometry, 
    Color foregroundColor);
IGeometrySurface CreateGeometrySurface(Size size, CanvasGeometry geometry, 
    Color foregroundColor, Color backgroundColor);
IGeometrySurface CreateGeometrySurface(Size size, CanvasGeometry geometry, 
    ICanvasBrush foregroundBrush);
IGeometrySurface CreateGeometrySurface(Size size, CanvasGeometry geometry, 
    ICanvasBrush foregroundBrush, ICanvasBrush backgroundBrush);
IGeometrySurface CreateGeometrySurface(Size size, CanvasGeometry geometry, 
    ICanvasBrush foregroundBrush, Color backgroundColor);
IGeometrySurface CreateGeometrySurface(Size size, CanvasGeometry geometry, 
    Color foregroundColor, ICanvasBrush backgroundBrush);
Task CreateImageSurfaceAsync(Uri uri, Size size, 
    ImageSurfaceOptions options);

CompositionImageFrame

CompositionImageFrame has been renamed to ImageFrame.

CompositionSurfaceImageOptions

The class with the longest name in CompositionProToolkit has now been renamed to ImageSurfaceOptions.

What’s new in CompositionProToolkit v0.4.4?

ImageFrame has been refactored with a better logical workflow. It has resulted in a better user experience. If you do not provide a definite Width and Height values to the ImageFrame, it will now size itself based on the loaded image and the parent control hosting the ImageFrame.

A new property RenderFast has been added to ImageFrame which gives you the option to turn off the animations which are used while rendering the image. This property is set to False by default. You can turn it on in scenarios where the Source property of the ImageFrame is being rapidly updated. For example, consider a ListBox containing numerous ImageFrames which is being scrolled very fast.

Property Type Description Default value
RenderFast Boolean Indicates whether the animations need to be switched off if the ImageFrame is being used in scenarios where it is being rapidly updated with new Source. False

NOTE: Do not confuse the RenderFast property with the RenderOptimized property. The former is used to turn off the animations during rendering, while the latter is used to reduces the memory footprint of the ImageFrame.

The latest source is available in GitHub and the Nuget package is available here.

CompositionProToolkit v0.4.3 released!

Another busy week and I feel thrilled to announce the release of CompositionProToolkit v0.4.3. It mainly contains feature additions to CompositionImageFrame and some minor refactoring (no breaking changes!). Let’s delve into the details.

CompositionGeneratorFactory

CompositionGeneratorFactory APIs have been simplified further. Now there are two ways to obtain the CompositionGenerator – by providing a Compositor or by providing a CompositionGraphicDevice.

public static ICompositionGenerator GetCompositionGenerator(Compositor compositor,
    bool useSharedCanvasDevice = true, bool useSoftwareRenderer = false);
public static ICompositionGenerator GetCompositionGenerator(
    CompositionGraphicsDevice graphicsDevice);

The first API also has couple of optional parameters

  • useSharedCanvasDevice – indicates whether the CompositionGenerator should use a shared CanvasDevice or creates a new one.
  • useSoftwareRenderer – this parameter is provided as a argument when creating a new CanvasDevice (i.e. when usedSharedCanvasDevice is false).

ICompositionMask

Two new APIs have been added in ICompositionMask class which allow the redraw of the mask with a new Color or ICanvasBrush.

void Redraw(ICanvasBrush brush);
void Redraw(Color color);

CompositionImageFrame

CompositionImageFrame has received most attention in this release. Two of the most requested features – Placeholder and Image Caching, have now been incorporated into CompositionImageFrame. Also now whenever the AlignX or AlignY changes, the image animates to its new location.

When the image is being (cached and) loaded, the placeholder shows a progress bar which indicates the load progress.

Placeholder_progress

The following new properties have been added to CompositionImageFrame to configure the Placeholder and the Image Cache features.

Property Type Description Default value
ShowPlaceHolder Boolean Indicates whether the placeholder needs to be displayed during image load or when no image is loaded in the CompositionImageFrame. False
PlaceholderBackground Color Indicates the background color of the Placeholder. Colors.Black
PlaceholderColor Color Indicates the color with which the rendered placeholder geometry should be filled RGB(192, 192, 192)
UseImageCache Boolean Indicates whether the images should be cached before rendering them. True

CPT_8_1.gif

Using CompositionImageFrame with FilePicker

If you have a CompostionImageFrame control in you application and your want to use the FilePicker to select an image file to be displayed on the CompostionImageFrame, then you must do the following

var picker = new Windows.Storage.Pickers.FileOpenPicker
{
    ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail,
    SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary
};
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".png");
var file = await picker.PickSingleFileAsync();
ImageFrame.Source = await ImageCache.GetCachedUriAsync(file);

Since the CompositionImageFrame‘s Source property expects a Uri, while the FilePicker provides a StorageFile. So in order to obtain a Uri from the StorageFile, you must first cache it using the ImageCache.GetCachedUriAsync() method.

The latest source code is available in GitHub and NuGet package is available here.

CompositionProToolkit v0.4.2 released


Well, the last week has been pretty busy – learning little more details about the Composition APIs, major refactoring of the CompositionProToolkit code, breaking changes and adding new features and controls. The hard work finally paid off. I am excited to announce the release of CompositionProToolkit v0.4.2. Let’s see, in detail, what this new version contains.

Breaking Changes

First and foremost, you would like to know what will not work if you move to version 0.4.2. After digging deeper into the various classes within the Windows.UI.Composition namespace, I realized that before introducing new features and controls, it was high time I refactored my code. Thus I began – optimizing various classes, removing lot of redundant Task.Run(…)* encapsulations. As a result, many APIs which were earlier asynchronous are now synchronous (you no longer need to await them!). The main advantages are improved execution speed and more robust code.🙂

Here are some of the classes whose APIs have changed. If you are using them within their code you will have to update them to the new API calls.

CompositionGeneratorFactory

CompositionGeneratorFactory no longer requires a sharedLock parameter while obtaining the CompositionGenerator. The lock is now managed internally within each CompositionSurfaceImage. Since this was an optional argument in the GetCompositionGenerator API, if you were not providing this argument in your code the your code need not be changed.

v0.4.1

public static ICompositionGenerator GetCompositionGenerator(Compositor compositor, 
    CompositionGraphicsDevice graphicsDevice=null, object sharedLock=null);

v0.4.2

public static ICompositionGenerator GetCompositionGenerator(Compositor compositor, 
    CompositionGraphicsDevice graphicsDevice=null);

ICompositionMask

All the asynchronous APIs in ICompositionMask class have been refactored into synchronous APIs.

v0.4.1

Task RedrawAsync();
Task RedrawAsync(Geometry.CanvasGeometry geometry);
Task RedrawAsync(Size size, Geometry.CanvasGeometry geometry);
Task RedrawAsync(Size size, Geometry.CanvasGeometry geometry, ICanvasBrush brush);
Task RedrawAsync(Size size, Geometry.CanvasGeometry geometry, Color color);
Task ResizeAsync(Size size);

v0.4.2

void Redraw();
void Redraw(Geometry.CanvasGeometry geometry);
void Redraw(Size size, Geometry.CanvasGeometry geometry);
void Redraw(Size size, Geometry.CanvasGeometry geometry, ICanvasBrush brush);
void Redraw(Size size, Geometry.CanvasGeometry geometry, Color color);
void Resize(Size size);

ICompositionSurfaceImage

A few of the asynchronous APIs in ICompositionSurfaceImage class have been refactored into synchronous APIs.

v0.4.1

Task RedrawAsync(CompositionSurfaceImageOptions options);
Task ResizeAsync(Size size);
Task ResizeAsync(Size size, CompositionSurfaceImageOptions options);

v0.4.2

void Redraw(CompositionSurfaceImageOptions options);
void Resize(Size size);
void Resize(Size size, CompositionSurfaceImageOptions options);

ICompositionGenerator

All the asynchronous APIs in ICompositionGenerator related to creating of ICompositionMask and visual Reflection have been refactored into synchronous APIs.

v0.4.1

Task CreateMaskAsync(Size size, CanvasGeometry geometry);
Task CreateMaskAsync(Size size, CanvasGeometry geometry, ICanvasBrush brush);
Task CreateMaskAsync(Size size, CanvasGeometry geometry, Color color);
Task CreateReflectionAsync(ContainerVisual visual, float reflectionDistance, 
    float reflectionLength, ReflectionLocation location);

v0.4.2

ICompositionMask CreateMask(Size size, CanvasGeometry geometry);
ICompositionMask CreateMask(Size size, CanvasGeometry geometry, ICanvasBrush brush);
ICompositionMask CreateMask(Size size, CanvasGeometry geometry, Color color);
void CreateReflection(ContainerVisual visual, float reflectionDistance, 
    float reflectionLength, ReflectionLocation location));

So what’s new in v0.4.2?

Now that we are done with the breaking changes, let’s look what all new features and controls have been added to CompositionProToolkit v0.4.2.

CompositionSurfaceImageOptions

CompositionSurfaceImageOptions now has an additional property AutoResize which can be set to False when you are trying to render a large image onto the CompositionSurfaceImage as a thumbnail. This will optimize memory usage.

Property Type Description Default value
AutoResize Boolean Specifies whether the CompositionSurfaceImage should resize itself automatically to match the loaded image size. When set to True, the Stretch, HorizontalAlignment and VerticalAlignment options are ignored. False

CompositionImageFrame

CompositionImageFrame now provides a fade in animation while transitioning from one image to another. It also supports rounded corners and display of shadows which can be configured easily. It also allows an option to optimize the rendering of the image. This is useful for scenarios where you are trying to render a large image to a smaller size, for example thumbnails.

CPT6.gif

The following new properties have been added to CompositionImageFrame

Property Type Description Default value
CornerRadius CornerRadius Indicates the corner radius of the the ImageFrame. The image will be rendered with rounded corners. (0, 0, 0, 0)
DisplayShadow Boolean Indicates whether the shadow for this image should be displayed. False
RenderOptimized Boolean Indicates whether optimization must be used to render the image.Set this property to True if the CompositionImageFrame is very small compared to the actual image size. This will optimize memory usage. False
ShadowBlurRadius Double Specifies the Blur radius of the shadow. 0.0
ShadowColor Color Specifies the color of the shadow. Transparent
ShadowOffsetX Double Specifies the horizontal offset of the shadow. 0.0
ShadowOffsetY Double Specifies the vertical offset of the shadow. 0.0
ShadowOpacity Double Specifies the opacity of the shadow. 1
TransitionDuration Double Indicates the duration of the crossfade animation while transitioning from one image to another. 700ms

FluidBanner

FluidBanner is now a part of the CompositionProToolkit. It now internally uses CompositionSurfaceImage to host the images. It provides the following properties which can be used to customize the FluidBanner.

Dependency Property Type Description Default Value
AlignX AlignmentX Indicates how the image is positioned horizontally in the FluidBanner items. Center
AlignY AlignmentY Indicates how the image is positioned vertically in the FluidBanner items. Center
DecodeHeight int The height, in pixels, that the images are decoded to. (Optional) 0
DecodeWidth int The width, in pixels, that the images are decoded to. (Optional) 0
ItemBackground Color The background color of each item in the FluidBanner Black
ItemGap double The gap between adjacent items in the banner. 30
ItemsSource IEnumerable<Uri> The collection of Uris of images to be shown in the FluidBanner null
Padding Thickness The padding inside the FluidBanner Thickness(0)
Stretch Stretch Indicates how the image is resized to fill its allocated space within each FluidBanner item. Uniform

The latest source code is available in GitHub. The Nuget package is available here

CompositionProToolkit v0.4.1 released

Compared to the large number of features in CompositionProToolkit v0.4, version 0.4.1 incorporates the CompositionImageFrame control and code optimizations.

If you want to know more about the new features added to CompositionProToolkit v0.4 check my previous post.

CompositionImageFrame

CompositionImageFrame is a control which can be used for displaying images. It encapsulates a CompositionSurfaceImage object which is used for loading and rendering the images. It also supports Pointer interactions and raises events accordingly.

In order to configure the rendering of the image, CompositionImageFrame has the following properties

Dependency Property Type Description Default Value
AlignX AlignmentX Specifies how the image is positioned horizontally in the CompositionImageFrame. AlignmentX.Center
AlignY AlignmentY Specifies how the image is positioned vertically in the CompositionImageFrame. AlignmentY.Center
FrameBackground Color Specifies the background color of the CompositionImageFrame to fill the area where image is not rendered. Colors.Black
Interpolation CanvasImageInterpolation Specifies the interpolation used for rendering the image. HighQualityCubic
Source Uri Specifies the Uri of the image to be loaded into the CompositionImageFrame. null
Stretch Stretch Specifies how the image is resized to fill its allocated space in the CompositionImageFrame. Uniform

CompositionImageFrame raises the following events

  • ImageOpened – when the image has been successfully loaded from the Uri and rendered.
  • ImageFailed – when there is an error loading the image from the Uri.

CompositionProToolkit v0.4.1 is now available in NuGet. Source code is available in GitHub.

If you want to see the various controls and features of CompositionProToolkit in action, check out the SampleGallery project in GitHub.

CompositionProToolkit v0.4 Released!

I am thrilled to announce that CompositionProToolkit v0.4 is now released. It brings a few breaking changes and new features that will help you use the Composition APIs more efficiently. In this blog I will be talking in detail about them.

Breaking Changes

First, let me tell you about the breaking changes incorporated in CompositionProToolkit v0.4

  • ICompositionMaskGenerator has been renamed to ICompositionGenerator – you will now be using this interface to generate many other objects apart from ICompositionMask. (More on that later!)
  • ICompositionMaskGeneratorInternal has been renamed to ICompositionGeneratorInternal – this will not break any of your code as it is an internal class.
  • CompositionMaskGenerator has been renamed to CompositionGenerator – another internal class which implements the ICompositionGenerator and the ICompositionGeneratorInternal interfaces.
  • CompositionMaskFactory has been renamed to CompositionGeneratorFactory – You will be using this class to obtain the instance of ICompositionGenerator.
    • GetCompositionMaskGenerator API has been renamed to GetCompositionGenerator – The parameters of this API remain the same.
public static ICompositionGenerator GetCompositionGenerator(Compositor compositor,     
    CompositionGraphicsDevice graphicsDevice = null, object sharedLock = null)

Now that we are done with the breaking changes, lets discuss the new features that have been added to CompositionProToolkit.

Creating a ICompositionMask using ICanvasBrush

ICompositionGenerator now provides the following additional API to create a ICompositionMask using an ICanvasBrush or its derivatives like CanvasImageBrush, CanvasLinearGradientBrush, CanvasRadialGradientBrush and CanvasSolidColorBrush.

Task<ICompositionMask> CreateMaskAsync(Size size, CanvasGeometry geometry, ICanvasBrush brush);

ICompositionSurfaceImage

ICompositionSurfaceImage is an interface which encapsulates a CompositionDrawingSurface onto which an image can be loaded by providing a Uri. You can then use the CompositionDrawingSurface to create a CompositionSurfaceBrush which can be applied to any Visual.

SurfaceImage.png

ICompositionGenerator provides the following API which allows you to create a CompositionSurfaceImage

Task<ICompositionSurfaceImage> CreateSurfaceImageAsync(Uri uri, Size size, 
    CompositionSurfaceImageOptions options);

This API requires the Uri of the image to be loaded, the size of the CompositionDrawingSurface (usually the same size as the Visual on which it is finally applied) and the CompositionSurfaceImageOptions.

CompositionSurfaceImageOptions

The CompositionSurfaceImageOptions class encapsulates a set of properties which influence the rendering of the image on the CompositionSurfaceImage. The following table shows the list of these properties.

Property Type Description Possible Values
Stretch Stretch Describes how image is resized to fill its allocated space. None,
Uniform,
Fill,
UniformToFill
HorizontalAlignment AlignmentX Describes how image is positioned horizontally. Left,
Center,
Right
VerticalAlignment AlignmentY Describes how image is positioned vertically. Top,
Center,
Bottom
Opacity float Specifies the opacity of the rendered image. 0 - 1f inclusive
Interpolation CanvasImageInterpolation Specifies the interpolation used to render the image. NearestNeighbor, Linear,
Cubic,
MultiSampleLinear,
Anisotropic,
HighQualityCubic
SurfaceBackgroundColor Color Specifies the color which will be used to fill the surface before rendering the image. All possible values that can be created.

Here is how the image is aligned on the Visual’s surface based on the HorizontalAlignment and VerticalAlignment properties

Alignment

The area on the Visual’s surface, which is not covered by the rendered image, will be filled with the color specified by the SurfaceBackgroundColor property

Example

The following example shows how you can load an image onto a Visual

var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
var generator = CompositionGeneratorFactory.GetCompositionGenerator(compositor);

var visual = compositor.CreateSpriteVisual();
visual.Size = new Vector2(this.ActualWidth.Single(), this.ActualHeight.Single());
visual.Offset = Vector3.Zero;

var options = new CompositionSurfaceImageOptions(Stretch.Uniform, AlignmentX.Center,
    AlignmentY.Center, 0.9f, CanvasImageInterpolation.Cubic)
    {
        SurfaceBackgroundColor = Colors.Maroon
    };

var surfaceImage =
    await generator.CreateSurfaceImageAsync(new Uri("ms-appx:///Assets/Images/Image3.jpg"), 
          visual.Size.ToSize(), options);

visual.Brush = compositor.CreateSurfaceBrush(_surfaceImage.Surface);

Once you create a CompositionSurfaceBrush from the ICompositionSurfaceImage and apply it to a Visual, you can use the following ICompositionSurfaceImage APIs to resize, provide a new Uri or change the rendering options

Task RedrawAsync();

Task RedrawAsync(CompositionSurfaceImageOptions options);

Task RedrawAsync(Uri uri, CompositionSurfaceImageOptions options);

Task RedrawAsync(Uri uri, Size size, CompositionSurfaceImageOptions options);

Task ResizeAsync(Size size);

Task ResizeAsync(Size size, CompositionSurfaceImageOptions options);

Once you call any of the above methods, the Visual’s brush is also updated.

Visual Reflection

A new API has been added to CompositionProToolkit which allows you to create the reflection of any Visual.

Task CreateReflectionAsync(ContainerVisual visual, float reflectionDistance = 0f,
    float reflectionLength = 0.7f, ReflectionLocation location = ReflectionLocation.Bottom);

The parameters required for this API are

  • visual – A ContainerVisual whose reflection has to be created.
  • reflectionDistance – The distance between the visual and its reflection.
  • reflectionLength – The normalized length (0 – 1f, inclusive) of the visual that must be visible in the reflection. Default value is 0.7f.
  • location – Specifies the location of the reflection with respect to the visual – Bottom, Top, Left or Right. Default value is ReflectionLocation.Bottom.

ReflectionLocation.png

This API will create a reflection even if an effect is applied to the Visual.

ReflectionWithEffect.png

If the visual has multiple other visuals in its visual tree, then the entire visual tree is reflected.

ReflectionMultipleVisuals.png

Other Changes

With the Anniversary Release of Windows 10, CompositionProToolkit project has migrated to Windows SDK 14393. Also it now requires CompositionExpressionToolkit v0.2.4 or higher, and Win2d v1.19 or higher (this is added automatically when you add a NuGet reference to CompositionProToolkit).

The source code is available in GitHub and the NuGet library is available here.