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.
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
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‘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 has been renamed to ImageFrame.
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.
||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.