/// <summary> /// Updates the state of the the ImageLoadEngine after loading an image /// </summary> private async void PostLoadImage() { switch (_engineState) { case ImageEngineState.Idle: // Do Nothing _scheduledObject = null; break; case ImageEngineState.Loading: // Loading is complete. No image pending load. _engineState = ImageEngineState.Idle; _scheduledObject = null; // Now that the load has completed, Invalidate the Measure InvalidateMeasure(); break; case ImageEngineState.Scheduled: // New image waiting in the pipeline to be rendered. _engineState = ImageEngineState.Loading; // Load the image await LoadImageAsync(_scheduledObject, _frameLayer.Size.ToSize()); break; } }
private void ClearImageFrame() { // Clear the progress in the Placeholder ProgressHandler(-1); if (RenderFast) { // Make the frameVisualContent transparent _frameContentVisual.Brush = _compositor.CreateColorBrush(Colors.Transparent); // Dispose the ImageSurface _imageSurface?.Dispose(); _imageSurface = null; // Engine is now idle _engineState = ImageEngineState.Idle; } else { _compositor.CreateScopedBatch(CompositionBatchTypes.Animation, () => { // Fade out the frameVisualContent _frameContentVisual.StartAnimation(() => _frameContentVisual.Opacity, _fadeOutAnimation); }, () => { // Make the frameVisualContent transparent _frameContentVisual.Brush = _compositor.CreateColorBrush(Colors.Transparent); //await _imageSurface.RedrawAsync(cachedUri, size, _imageOptions); _frameContentVisual.Opacity = 1; // Dispose the ImageSurface _imageSurface?.Dispose(); _imageSurface = null; // Engine is now idle _engineState = ImageEngineState.Idle; }); } }
/// <summary> /// Updates the state of the the ImageLoadEngine before loading an image /// </summary> private async void ScheduleNextLoad() { _scheduledObject = Source; switch (_engineState) { case ImageEngineState.Idle: _engineState = ImageEngineState.Loading; // Load the image await LoadImageAsync(_scheduledObject, _frameLayer.Size.ToSize()); break; case ImageEngineState.Loading: _engineState = ImageEngineState.Scheduled; break; case ImageEngineState.Scheduled: break; } }
/// <summary> /// Loads the Uri scheduled for load. If after loading there is another /// Uri scheduled it loads that and keeps on repeating this until there /// are no more Uris scheduled for load. /// </summary> /// <param name="objectToLoad">Object scheduled to be loaded in the ImageFrame</param> /// <param name="size">Size of the ImageSurface</param> /// <param name="isLoadingNext">Whether loading in the imageSurface or the /// nextImageSurface</param> /// <returns>Uri</returns> private async Task<Uri> LoadNextScheduledObject(object objectToLoad, Size size, bool isLoadingNext) { bool loadNext; Uri cachedUri; do { _currentObject = objectToLoad; cachedUri = await ImageCache.GetCachedUriAsync(objectToLoad, ProgressHandler); // Load the new uri if (isLoadingNext) { _nextImageSurface = await _generator.CreateImageSurfaceAsync(cachedUri, size, _imageOptions); } else { _imageSurface = await _generator.CreateImageSurfaceAsync(cachedUri, size, _imageOptions); } // Report 99% progress ProgressHandler(99); // Since the loading of the object takes some time, it could be possible // that a new object has been scheduled for load. In that case, discard // the current object and load the scheduled object if (_engineState == ImageEngineState.Scheduled) { loadNext = true; objectToLoad = _scheduledObject; _engineState = ImageEngineState.Loading; } else { loadNext = false; } } while (loadNext); return cachedUri; }
/// <summary> /// Handles the Arrange pass during Layout /// </summary> /// <param name="finalSize">Final Size of the control</param> /// <returns>Total size occupied by the Children</returns> protected override Size ArrangeOverride(Size finalSize) { // Taking into account the BorderThickness and Padding var borders = BorderThickness; var padding = Padding; var corners = CornerRadius; var borderSize = borders.CollapseThickness(); var paddingSize = padding.CollapseThickness(); // Calculate the Offset for the frameVisual var left = (borders.Left + padding.Left).Single(); var top = (borders.Top + padding.Top).Single(); // Calculate the Dimensions of the frameVisual var width = Math.Max(0, finalSize.Width - borderSize.Width - paddingSize.Width).Single(); var height = Math.Max(0, finalSize.Height - borderSize.Height - paddingSize.Height).Single(); // Set the Size and Offset of visuals in the ImageFrame var frameSize = new Vector2(width, height); _rootContainer.Size = frameSize; _frameLayer.Size = frameSize; _frameBackgroundVisual.Size = frameSize; _frameContentVisual.Size = frameSize; _placeholderContentVisual.Size = frameSize; _placeholderBackgroundVisual.Size = frameSize; _shadowVisual.Size = frameSize; _nextVisualContent.Size = frameSize; _rootContainer.Offset = new Vector3(left, top, 0); // Update the frameLayerMask in case the CornerRadius or // BorderThickness or Padding has changed var pathInfo = new CompositionPathInfo(corners, borders, padding, false); using (var geometry = CompositionGenerator.GenerateGeometry(_generator.Device, frameSize.ToSize(), pathInfo, Vector2.Zero)) { _frameLayerMask.Redraw(_frameLayer.Size.ToSize(), geometry); } // If the FrameBackground has changed since the last time it was // applied to the frameBackgroundVisual, then animate the brush's // color to the new color. var brush = _frameBackgroundVisual.Brush as CompositionColorBrush; if (brush != null) { if (!brush.Color.Equals(FrameBackground)) { // If we are rendering fast, then no need to animate. // Just set the final value. if (RenderFast) { brush.Color = FrameBackground; } else { _colorAnimation.InsertKeyFrame(1f, FrameBackground); brush.StartAnimation("Color", _colorAnimation); } } } // If the PlaceholderBackground has changed since the last time it was // applied to the _placeholderBackgroundVisual, then update the brush's // color to the new color. brush = _placeholderBackgroundVisual.Brush as CompositionColorBrush; if (brush != null) { if (!brush.Color.Equals(PlaceholderBackground)) { brush.Color = PlaceholderBackground; } } // Redraw the placeholder content with the latest placeholder color _placeholderContentMask.Redraw(PlaceholderColor, PlaceholderBackground); // Set the stretch property of placeholder content's brush according to its size if ((width > PlaceholderSize.Width) && (height > PlaceholderSize.Height)) { _placeholderContentBrush.Stretch = CompositionStretch.None; } else { _placeholderContentBrush.Stretch = CompositionStretch.Uniform; } // Update the imageOptions _imageOptions.Stretch = Stretch; _imageOptions.HorizontalAlignment = AlignX; _imageOptions.VerticalAlignment = AlignY; _imageOptions.Interpolation = Interpolation; _imageOptions.SurfaceBackgroundColor = Colors.Transparent; _imageOptions.AutoResize = !RenderOptimized; // If Source is valid then try loading/refreshing the ImageSurface if (Source != null) { if (_imageSurface != null) { // Resize the ImageSurface to the new size _imageSurface.Resize(frameSize.ToSize(), _imageOptions); // Update the surface brush based on the Stretch and Alignment options if (RenderFast) { // Use no animations to update alignment if we are rendering fast (_frameContentVisual.Brush as CompositionSurfaceBrush)?.UpdateSurfaceBrushOptions(Stretch, AlignX, AlignY); } else { // Update stretch and alignment using animation (_frameContentVisual.Brush as CompositionSurfaceBrush)?.UpdateSurfaceBrushOptions(Stretch, AlignX, AlignY, _alignXAnimation, _alignYAnimation); } } else { // Load the Source to the ImageSurface ScheduleNextLoad(); } } else { // If the frameContentVisual had any previous brush, fade it out if (_imageSurface == null) { // Make the frameVisualContent transparent _frameContentVisual.Brush = _compositor.CreateColorBrush(Colors.Transparent); DisplayPlaceHolder(); _engineState = ImageEngineState.Idle; } } // Handle shadow if (DisplayShadow) { // If OptimizeShadow is True then use the sharedShadow otherwise use the instance shadow var shadow = OptimizeShadow ? ShadowProvider.GetSharedShadow(_compositor) : (_shadow ?? (_shadow = _compositor.CreateDropShadow())); shadow.BlurRadius = ShadowBlurRadius.Single(); shadow.Color = ShadowColor; shadow.Offset = new Vector3(ShadowOffsetX.Single(), ShadowOffsetY.Single(), 0); shadow.Opacity = ShadowOpacity.Single(); shadow.Mask = _layerEffectBrush.GetSourceParameter("mask"); _shadowVisual.Shadow = shadow; } else { _shadowVisual.Shadow = null; } return base.ArrangeOverride(finalSize); }