Browse Source

Introduce RenderOptions.RequiresFullOpacityHandling

pull/12572/head
Benedikt Stebner 3 years ago
parent
commit
4b5c680a26
  1. 45
      src/Avalonia.Base/Media/RenderOptions.cs
  2. 28
      src/Skia/Avalonia.Skia/DrawingContextImpl.cs

45
src/Avalonia.Base/Media/RenderOptions.cs

@ -8,12 +8,13 @@ namespace Avalonia.Media
public EdgeMode EdgeMode { get; init; } public EdgeMode EdgeMode { get; init; }
public TextRenderingMode TextRenderingMode { get; init; } public TextRenderingMode TextRenderingMode { get; init; }
public BitmapBlendingMode BitmapBlendingMode { get; init; } public BitmapBlendingMode BitmapBlendingMode { get; init; }
public bool? RequiresFullOpacityHandling { get; init; }
/// <summary> /// <summary>
/// Gets the value of the BitmapInterpolationMode attached property for a visual. /// Gets the value of the BitmapInterpolationMode attached property for a visual.
/// </summary> /// </summary>
/// <param name="visual">The control.</param> /// <param name="visual">The control.</param>
/// <returns>The control's left coordinate.</returns> /// <returns>The value.</returns>
public static BitmapInterpolationMode GetBitmapInterpolationMode(Visual visual) public static BitmapInterpolationMode GetBitmapInterpolationMode(Visual visual)
{ {
return visual.RenderOptions.BitmapInterpolationMode; return visual.RenderOptions.BitmapInterpolationMode;
@ -23,7 +24,7 @@ namespace Avalonia.Media
/// Sets the value of the BitmapInterpolationMode attached property for a visual. /// Sets the value of the BitmapInterpolationMode attached property for a visual.
/// </summary> /// </summary>
/// <param name="visual">The control.</param> /// <param name="visual">The control.</param>
/// <param name="value">The left value.</param> /// <param name="value">The value.</param>
public static void SetBitmapInterpolationMode(Visual visual, BitmapInterpolationMode value) public static void SetBitmapInterpolationMode(Visual visual, BitmapInterpolationMode value)
{ {
visual.RenderOptions = visual.RenderOptions with { BitmapInterpolationMode = value }; visual.RenderOptions = visual.RenderOptions with { BitmapInterpolationMode = value };
@ -33,7 +34,7 @@ namespace Avalonia.Media
/// Gets the value of the BitmapBlendingMode attached property for a visual. /// Gets the value of the BitmapBlendingMode attached property for a visual.
/// </summary> /// </summary>
/// <param name="visual">The control.</param> /// <param name="visual">The control.</param>
/// <returns>The control's left coordinate.</returns> /// <returns>The value.</returns>
public static BitmapBlendingMode GetBitmapBlendingMode(Visual visual) public static BitmapBlendingMode GetBitmapBlendingMode(Visual visual)
{ {
return visual.RenderOptions.BitmapBlendingMode; return visual.RenderOptions.BitmapBlendingMode;
@ -53,7 +54,7 @@ namespace Avalonia.Media
/// Gets the value of the EdgeMode attached property for a visual. /// Gets the value of the EdgeMode attached property for a visual.
/// </summary> /// </summary>
/// <param name="visual">The control.</param> /// <param name="visual">The control.</param>
/// <returns>The control's left coordinate.</returns> /// <returns>The value.</returns>
public static EdgeMode GetEdgeMode(Visual visual) public static EdgeMode GetEdgeMode(Visual visual)
{ {
return visual.RenderOptions.EdgeMode; return visual.RenderOptions.EdgeMode;
@ -63,7 +64,7 @@ namespace Avalonia.Media
/// Sets the value of the EdgeMode attached property for a visual. /// Sets the value of the EdgeMode attached property for a visual.
/// </summary> /// </summary>
/// <param name="visual">The control.</param> /// <param name="visual">The control.</param>
/// <param name="value">The left value.</param> /// <param name="value">The value.</param>
public static void SetEdgeMode(Visual visual, EdgeMode value) public static void SetEdgeMode(Visual visual, EdgeMode value)
{ {
visual.RenderOptions = visual.RenderOptions with { EdgeMode = value }; visual.RenderOptions = visual.RenderOptions with { EdgeMode = value };
@ -73,7 +74,7 @@ namespace Avalonia.Media
/// Gets the value of the TextRenderingMode attached property for a visual. /// Gets the value of the TextRenderingMode attached property for a visual.
/// </summary> /// </summary>
/// <param name="visual">The control.</param> /// <param name="visual">The control.</param>
/// <returns>The control's left coordinate.</returns> /// <returns>The value.</returns>
public static TextRenderingMode GetTextRenderingMode(Visual visual) public static TextRenderingMode GetTextRenderingMode(Visual visual)
{ {
return visual.RenderOptions.TextRenderingMode; return visual.RenderOptions.TextRenderingMode;
@ -83,12 +84,32 @@ namespace Avalonia.Media
/// Sets the value of the TextRenderingMode attached property for a visual. /// Sets the value of the TextRenderingMode attached property for a visual.
/// </summary> /// </summary>
/// <param name="visual">The control.</param> /// <param name="visual">The control.</param>
/// <param name="value">The left value.</param> /// <param name="value">The value.</param>
public static void SetTextRenderingMode(Visual visual, TextRenderingMode value) public static void SetTextRenderingMode(Visual visual, TextRenderingMode value)
{ {
visual.RenderOptions = visual.RenderOptions with { TextRenderingMode = value }; visual.RenderOptions = visual.RenderOptions with { TextRenderingMode = value };
} }
/// <summary>
/// Gets the value of the RequiresFullOpacityHandling attached property for a visual.
/// </summary>
/// <param name="visual">The control.</param>
/// <returns>The value.</returns>
public static bool? GetRequiresFullOpacityHandling(Visual visual)
{
return visual.RenderOptions.RequiresFullOpacityHandling;
}
/// <summary>
/// Sets the value of the RequiresFullOpacityHandling attached property for a visual.
/// </summary>
/// <param name="visual">The control.</param>
/// <param name="value">The value.</param>
public static void SetRequiresFullOpacityHandling(Visual visual, bool? value)
{
visual.RenderOptions = visual.RenderOptions with { RequiresFullOpacityHandling = value };
}
public RenderOptions MergeWith(RenderOptions other) public RenderOptions MergeWith(RenderOptions other)
{ {
var bitmapInterpolationMode = BitmapInterpolationMode; var bitmapInterpolationMode = BitmapInterpolationMode;
@ -119,12 +140,20 @@ namespace Avalonia.Media
bitmapBlendingMode = other.BitmapBlendingMode; bitmapBlendingMode = other.BitmapBlendingMode;
} }
var requiresFullOpacityHandling = RequiresFullOpacityHandling;
if (requiresFullOpacityHandling == null)
{
requiresFullOpacityHandling = other.RequiresFullOpacityHandling;
}
return new RenderOptions return new RenderOptions
{ {
BitmapInterpolationMode = bitmapInterpolationMode, BitmapInterpolationMode = bitmapInterpolationMode,
EdgeMode = edgeMode, EdgeMode = edgeMode,
TextRenderingMode = textRenderingMode, TextRenderingMode = textRenderingMode,
BitmapBlendingMode = bitmapBlendingMode BitmapBlendingMode = bitmapBlendingMode,
RequiresFullOpacityHandling = requiresFullOpacityHandling
}; };
} }
} }

28
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@ -189,7 +189,8 @@ namespace Avalonia.Skia
var d = destRect.ToSKRect(); var d = destRect.ToSKRect();
var paint = SKPaintCache.Shared.Get(); var paint = SKPaintCache.Shared.Get();
paint.Color = new SKColor(255, 255, 255, (byte)(255 * opacity * (_useOpacitySaveLayer ? 1 : _currentOpacity)));
paint.Color = new SKColor(255, 255, 255, (byte)(255 * opacity * currentOpacity));
paint.FilterQuality = RenderOptions.BitmapInterpolationMode.ToSKFilterQuality(); paint.FilterQuality = RenderOptions.BitmapInterpolationMode.ToSKFilterQuality();
paint.BlendMode = RenderOptions.BitmapBlendingMode.ToSKBlendMode(); paint.BlendMode = RenderOptions.BitmapBlendingMode.ToSKBlendMode();
@ -375,7 +376,7 @@ namespace Avalonia.Skia
{ {
if (boxShadow != default && !boxShadow.IsInset) if (boxShadow != default && !boxShadow.IsInset)
{ {
using (var shadow = BoxShadowFilter.Create(_boxShadowPaint, boxShadow, _useOpacitySaveLayer ? 1 : _currentOpacity)) using (var shadow = BoxShadowFilter.Create(_boxShadowPaint, boxShadow, _currentOpacity))
{ {
var spread = (float)boxShadow.Spread; var spread = (float)boxShadow.Spread;
if (boxShadow.IsInset) if (boxShadow.IsInset)
@ -432,7 +433,7 @@ namespace Avalonia.Skia
{ {
if (boxShadow != default && boxShadow.IsInset) if (boxShadow != default && boxShadow.IsInset)
{ {
using (var shadow = BoxShadowFilter.Create(_boxShadowPaint, boxShadow, _useOpacitySaveLayer ? 1 : _currentOpacity)) using (var shadow = BoxShadowFilter.Create(_boxShadowPaint, boxShadow, currentOpacity))
{ {
var spread = (float)boxShadow.Spread; var spread = (float)boxShadow.Spread;
var offsetX = (float)boxShadow.OffsetX; var offsetX = (float)boxShadow.OffsetX;
@ -592,8 +593,16 @@ namespace Avalonia.Skia
{ {
CheckLease(); CheckLease();
if(_useOpacitySaveLayer) _opacityStack.Push(_currentOpacity);
var useOpacitySaveLayer = _useOpacitySaveLayer || RenderOptions.RequiresFullOpacityHandling == true;
if (useOpacitySaveLayer)
{ {
opacity = _currentOpacity * opacity; //Take current multiplied opacity
_currentOpacity = 1; //Opacity is applied via layering
if (bounds.HasValue) if (bounds.HasValue)
{ {
var rect = bounds.Value.ToSKRect(); var rect = bounds.Value.ToSKRect();
@ -606,7 +615,6 @@ namespace Avalonia.Skia
} }
else else
{ {
_opacityStack.Push(_currentOpacity);
_currentOpacity *= opacity; _currentOpacity *= opacity;
} }
} }
@ -616,14 +624,14 @@ namespace Avalonia.Skia
{ {
CheckLease(); CheckLease();
if(_useOpacitySaveLayer) var useOpacitySaveLayer = _useOpacitySaveLayer || RenderOptions.RequiresFullOpacityHandling == true;
if (useOpacitySaveLayer)
{ {
Canvas.Restore(); Canvas.Restore();
} }
else
{ _currentOpacity = _opacityStack.Pop();
_currentOpacity = _opacityStack.Pop();
}
} }
/// <inheritdoc /> /// <inheritdoc />

Loading…
Cancel
Save