' SSOT-V2 Signature: This class/file follows the SSOT-V2 architecture.
Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.General
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Rendering

    ''' <summary>
    ''' Soft capsule / chip component chrome renderer.
    ''' Component Chrome owns compact capsule skins; Surface Material remains generic and
    ''' never registers chip-specific materials.
    ''' </summary>
    Friend NotInheritable Class MASSoftChipChromePainter
        Implements IDisposable

#Region "Fields"

        Private _disposed As Boolean

        Private ReadOnly _chipFill As New SKPaint With {
            .IsAntialias = True,
            .IsDither = False,
            .Style = SKPaintStyle.Fill
        }

        Private ReadOnly _chipFx As New SKPaint With {
            .IsAntialias = True,
            .IsDither = True,
            .Style = SKPaintStyle.Fill
        }

        Private ReadOnly _chipBevel As New SKPaint With {
            .IsAntialias = True,
            .IsDither = False,
            .Style = SKPaintStyle.Stroke,
            .StrokeCap = SKStrokeCap.Round
        }

        Private _chipLastW As Integer = -1
        Private _chipLastH As Integer = -1
        Private _chipLastDpi100 As Integer = -1

        Private _chipLastTop As SKColor = Nothing
        Private _chipLastBot As SKColor = Nothing
        Private _chipLastMidT1000 As Integer = -1

        Private _chipLastTopA As Integer = -1
        Private _chipLastMidA As Integer = -1
        Private _chipLastBotA As Integer = -1

        Private _chipBodyShader As SKShader = Nothing

        Private _sheenShader As SKShader
        Private _vignetteShader As SKShader
        Private _edgeHighlightShader As SKShader
        Private _innerShadeShader As SKShader

        Private _fxLastW As Integer = -1
        Private _fxLastH As Integer = -1
        Private _fxLastDpi100 As Integer = -1
        Private _fxLastTop As SKColor
        Private _fxLastBot As SKColor

#End Region

#Region "Specs / Recipes"

        Friend Structure MASSoftChipChromeSpec
            Friend Top As SKColor
            Friend Bot As SKColor
            Friend MidT As Single
            Friend TopAlpha As Byte
            Friend MidAlpha As Byte
            Friend BotAlpha As Byte
        End Structure

        Friend Structure MASSoftChipChromeFxSpec
            Friend WashColor As SKColor
            Friend WashAlpha As Byte

            Friend InnerGlossColor As SKColor
            Friend InnerGlossAlpha As Byte
            Friend InnerGlossFadeT As Single

            Friend InnerInsetMul As Single
            Friend InnerRadMul As Single
        End Structure

        Private Structure SoftChipFxRecipe
            Friend EdgeHiA As Byte
            Friend SheenA As Byte
            Friend ShadeA As Byte
            Friend VignetteA As Byte

            Friend EdgeMixT As Single
            Friend SheenMixT As Single
            Friend ShadeMixT As Single

            Friend EdgeFadeStop As Single
            Friend SheenMid0 As Single
            Friend SheenMid1 As Single
            Friend SheenMid2 As Single
            Friend ShadeStart As Single

            Friend VignetteCenterYMul As Single
            Friend VignetteRadiusMul As Single
        End Structure

#End Region

#Region "Dispose"

        Public Sub Dispose() Implements IDisposable.Dispose
            If _disposed Then Return
            _disposed = True

            SafeDisposePaint(_chipFill)
            SafeDisposePaint(_chipFx)
            SafeDisposePaint(_chipBevel)

            MASVisualPrimitivesPainter.DisposeShader(_chipBodyShader)
            MASVisualPrimitivesPainter.DisposeShader(_sheenShader)
            MASVisualPrimitivesPainter.DisposeShader(_vignetteShader)
            MASVisualPrimitivesPainter.DisposeShader(_edgeHighlightShader)
            MASVisualPrimitivesPainter.DisposeShader(_innerShadeShader)
        End Sub

#End Region

#Region "Public entry points"

        Friend Sub DrawSoftChipChromeBody(canvas As SKCanvas,
                                                 ctx As MASThemeContext,
                                                 r As SKRect,
                                                 radius As Single,
                                                 dpi As Single,
                                                 spec As MASSoftChipChromeSpec)

            If _disposed OrElse canvas Is Nothing Then Return
            If r.Width <= 1 OrElse r.Height <= 1 Then Return

            dpi = PixelSnap.SafeDpi(dpi)
            radius = PixelSnap.SafeRadius(radius)

            EnsureSoftChipChromeCache(r, dpi, spec)
            EnsureSoftChipFxCache(r, dpi, spec)

            Dim materialBodyDrawn As Boolean =
                MASSurfaceMaterialComponentGateway.TryDrawSelectorChromeMaterialBody(
                    canvas:=canvas,
                    ctx:=ctx,
                    boundsPx:=r,
                    materialKey:=MASSurfaceMaterialIds.Auto,
                    dpi:=dpi,
                    cornerRadiusPx:=radius,
                    opacity:=1.0F,
                    surfaceStrengthLevel:=3,
                    frameStrength:=MASSurfaceFrameStrength.Level3)

            MASVisualPrimitivesPainter.WithTranslatedLocalRect(
                canvas,
                r,
                Sub(lr As SKRect)
                    MASVisualPrimitivesPainter.WithClipRoundRect(
                        canvas,
                        lr,
                        radius,
                        Sub()
                            If Not materialBodyDrawn Then DrawSoftChipBaseGradient(canvas, lr, radius)
                            DrawSoftChipSheenFx(canvas, lr)
                            DrawSoftChipVignetteFx(canvas, lr)
                            DrawSoftChipTopMicroBevel(canvas, lr, radius, dpi)
                        End Sub)
                End Sub)
        End Sub


        Friend Sub DrawSoftChipChromeFx(canvas As SKCanvas,
                                          r As SKRect,
                                          radius As Single,
                                          dpi As Single,
                                          spec As MASSoftChipChromeSpec)

            Dim fxSpec As New MASSoftChipChromeFxSpec With {
                .WashColor = SKColors.Transparent,
                .WashAlpha = 0,
                .InnerGlossColor = SKColors.White,
                .InnerGlossAlpha = 0,
                .InnerGlossFadeT = 0.42F,
                .InnerInsetMul = 0.08F,
                .InnerRadMul = 0.82F
            }

            DrawSoftChipChromeFx(canvas, r, radius, dpi, spec, fxSpec)
        End Sub

        Friend Sub DrawSoftChipChromeFx(canvas As SKCanvas,
                                          r As SKRect,
                                          radius As Single,
                                          dpi As Single,
                                          spec As MASSoftChipChromeSpec,
                                          fxSpec As MASSoftChipChromeFxSpec)

            If _disposed Then Return
            If canvas Is Nothing Then Return
            If r.IsEmpty Then Return
            If radius < 0 Then radius = 0

            dpi = PixelSnap.SafeDpi(dpi)
            radius = PixelSnap.SafeRadius(radius)

            EnsureSoftChipFxCache(r, dpi, spec)

            MASVisualPrimitivesPainter.WithClipRoundRect(
                canvas,
                r,
                radius,
                Sub()
                    PrepareChipFxPaint(SKBlendMode.SrcOver)
                    _chipFx.Shader = _edgeHighlightShader
                    canvas.DrawRoundRect(r, radius, radius, _chipFx)

                    PrepareChipFxPaint(SKBlendMode.Screen)
                    _chipFx.Shader = _sheenShader
                    If _sheenShader IsNot Nothing Then
                        canvas.DrawRoundRect(r, radius, radius, _chipFx)
                    End If

                    PrepareChipFxPaint(SKBlendMode.Multiply)
                    _chipFx.Shader = _innerShadeShader
                    canvas.DrawRoundRect(r, radius, radius, _chipFx)

                    _chipFx.Shader = Nothing
                    _chipFx.BlendMode = SKBlendMode.SrcOver
                End Sub)

            DrawSoftChipCustomWashFx(canvas, r, radius, fxSpec)
            DrawSoftChipCustomInnerGlossFx(canvas, r, radius, fxSpec)
        End Sub

        Friend Shared Function BuildSoftChipChromeSpec(appTheme As IMASAppTheme,
                                                         surfaceTheme As IMASFoundationSurfaceTheme,
                                                         Optional midT As Single = 0.55F,
                                                         Optional topA As Byte = 165,
                                                         Optional midA As Byte = 145,
                                                         Optional botA As Byte = 165) As MASSoftChipChromeSpec

            Dim resolvedSurface As IMASFoundationSurfaceTheme =
                If(surfaceTheme, If(appTheme Is Nothing, Nothing, MASAppThemeContracts.Foundation(appTheme).Surface))

            If resolvedSurface Is Nothing Then
                Throw New InvalidOperationException("IMASFoundationSurfaceTheme is required.")
            End If

            Dim fam As CommonEnums.SurfaceFamily = CommonEnums.SurfaceFamily.Chip
            Dim intensity As MASVisualEffectIntensityProfiles.AcrylicSurfaceIntensityProfile =
                MASVisualEffectIntensityProfiles.ResolveAcrylic(fam)

            Dim top As SKColor = resolvedSurface.SurfaceTop
            Dim mid As SKColor = resolvedSurface.SurfaceMid
            Dim bot As SKColor = resolvedSurface.SurfaceBot

            If intensity.TopBandEmphasis > 0.0F Then
                top = ColorMath.Mix(top, SKColors.White, intensity.TopBandEmphasis * 0.055F)
                mid = ColorMath.Mix(mid, SKColors.White, intensity.TopBandEmphasis * 0.024F)
            End If

            If intensity.BottomAnchorStrength > 0.0F Then
                bot = ColorMath.Mix(
                    bot,
                    ColorMath.TowardBlack(bot, 0.18F),
                    intensity.BottomAnchorStrength * 0.16F
                )
            End If

            Dim resolvedMidT As Single = MASVisualPrimitivesPainter.SanitizeUnitSingle(midT, 0.55F)

            Return New MASSoftChipChromeSpec With {
                .Top = ColorMath.Mix(top, mid, 0.16F),
                .Bot = ColorMath.Mix(bot, mid, 0.1F),
                .MidT = resolvedMidT,
                .TopAlpha = topA,
                .MidAlpha = midA,
                .BotAlpha = botA
            }
        End Function

        Friend Shared Function BuildSoftChipChromeSpec(top As SKColor,
                                                         bot As SKColor,
                                                         midT As Single,
                                                         topA As Byte,
                                                         midA As Byte,
                                                         botA As Byte) As MASSoftChipChromeSpec

            Dim t As Single = MASVisualPrimitivesPainter.SanitizeUnitSingle(midT, 0.5F)

            Return New MASSoftChipChromeSpec With {
                .Top = top,
                .Bot = bot,
                .MidT = t,
                .TopAlpha = topA,
                .MidAlpha = midA,
                .BotAlpha = botA
            }
        End Function

#End Region

#Region "Cache"

        Private Sub EnsureSoftChipChromeCache(r As SKRect,
                                                dpi As Single,
                                                spec As MASSoftChipChromeSpec)

            Dim sizeKey As MASVisualPrimitivesPainter.SizeDpiKey =
                MASVisualPrimitivesPainter.BuildSizeDpiKey(r, dpi)

            Dim midT As Single = MASVisualPrimitivesPainter.SanitizeUnitSingle(spec.MidT, 0.5F)
            Dim midT1000 As Integer = CInt(Math.Round(midT * 1000.0F))

            Dim lastSizeKey As New MASVisualPrimitivesPainter.SizeDpiKey With {
                .W = _chipLastW,
                .H = _chipLastH,
                .Dpi100 = _chipLastDpi100
            }

            Dim need As Boolean =
                (_chipBodyShader Is Nothing) OrElse
                (Not MASVisualPrimitivesPainter.SizeDpiKeyEquals(sizeKey, lastSizeKey)) OrElse
                spec.Top <> _chipLastTop OrElse
                spec.Bot <> _chipLastBot OrElse
                midT1000 <> _chipLastMidT1000 OrElse
                CInt(spec.TopAlpha) <> _chipLastTopA OrElse
                CInt(spec.MidAlpha) <> _chipLastMidA OrElse
                CInt(spec.BotAlpha) <> _chipLastBotA

            If Not need Then Return

            MASVisualPrimitivesPainter.DisposeShader(_chipBodyShader)

            Dim midRgb As SKColor = ColorMath.WithAlpha(ColorMath.Mix(spec.Top, spec.Bot, midT), 255)

            Dim c0 As SKColor = MASVisualPrimitivesPainter.WithAlphaByte(spec.Top, spec.TopAlpha)
            Dim c1 As SKColor = MASVisualPrimitivesPainter.WithAlphaByte(midRgb, spec.MidAlpha)
            Dim c2 As SKColor = MASVisualPrimitivesPainter.WithAlphaByte(spec.Bot, spec.BotAlpha)

            _chipBodyShader = SKShader.CreateLinearGradient(
                New SKPoint(0.0F, 0.0F),
                New SKPoint(0.0F, CSng(sizeKey.H)),
                New SKColor() {c0, c1, c2},
                New Single() {0.0F, midT, 1.0F},
                SKShaderTileMode.Clamp
            )

            _chipLastW = sizeKey.W
            _chipLastH = sizeKey.H
            _chipLastDpi100 = sizeKey.Dpi100

            _chipLastTop = spec.Top
            _chipLastBot = spec.Bot
            _chipLastMidT1000 = midT1000

            _chipLastTopA = CInt(spec.TopAlpha)
            _chipLastMidA = CInt(spec.MidAlpha)
            _chipLastBotA = CInt(spec.BotAlpha)
        End Sub

        Private Sub EnsureSoftChipFxCache(r As SKRect,
                                          dpi As Single,
                                          spec As MASSoftChipChromeSpec)

            Dim sizeKey As MASVisualPrimitivesPainter.SizeDpiKey =
                MASVisualPrimitivesPainter.BuildSizeDpiKey(r, dpi)

            Dim lastSizeKey As New MASVisualPrimitivesPainter.SizeDpiKey With {
                .W = _fxLastW,
                .H = _fxLastH,
                .Dpi100 = _fxLastDpi100
            }

            Dim need As Boolean =
                (_sheenShader Is Nothing) OrElse
                (_edgeHighlightShader Is Nothing) OrElse
                (_innerShadeShader Is Nothing) OrElse
                (Not MASVisualPrimitivesPainter.SizeDpiKeyEquals(sizeKey, lastSizeKey)) OrElse
                (spec.Top <> _fxLastTop) OrElse
                (spec.Bot <> _fxLastBot)

            If Not need Then Return

            MASVisualPrimitivesPainter.DisposeShader(_sheenShader)
            MASVisualPrimitivesPainter.DisposeShader(_edgeHighlightShader)
            MASVisualPrimitivesPainter.DisposeShader(_innerShadeShader)
            MASVisualPrimitivesPainter.DisposeShader(_vignetteShader)
            _vignetteShader = Nothing

            Dim topTint As New SKColor(spec.Top.Red, spec.Top.Green, spec.Top.Blue, 255)
            Dim botTint As New SKColor(spec.Bot.Red, spec.Bot.Green, spec.Bot.Blue, 255)

            Dim recipe As SoftChipFxRecipe = ResolveSoftChipFxRecipe()

            _edgeHighlightShader = SKShader.CreateLinearGradient(
                New SKPoint(0.0F, 0.0F),
                New SKPoint(0.0F, CSng(sizeKey.H)),
                New SKColor() {
                    ColorMath.WithAlpha(ColorMath.Mix(SKColors.White, topTint, recipe.EdgeMixT), recipe.EdgeHiA),
                    SKColors.Transparent
                },
                New Single() {0.0F, recipe.EdgeFadeStop},
                SKShaderTileMode.Clamp
            )

            If recipe.SheenA > 0 Then
                _sheenShader = SKShader.CreateLinearGradient(
                    New SKPoint(0.0F, 0.0F),
                    New SKPoint(0.0F, CSng(sizeKey.H)),
                    New SKColor() {
                        SKColors.Transparent,
                        ColorMath.WithAlpha(ColorMath.Mix(SKColors.White, topTint, recipe.SheenMixT + 0.02F), CByte(Math.Max(0, CInt(recipe.SheenA) - 10))),
                        ColorMath.WithAlpha(ColorMath.Mix(SKColors.White, topTint, recipe.SheenMixT), recipe.SheenA),
                        SKColors.Transparent
                    },
                    New Single() {recipe.SheenMid0, recipe.SheenMid1, recipe.SheenMid2, 0.85F},
                    SKShaderTileMode.Clamp
                )
            Else
                _sheenShader = Nothing
            End If

            _innerShadeShader = SKShader.CreateLinearGradient(
                New SKPoint(0.0F, 0.0F),
                New SKPoint(0.0F, CSng(sizeKey.H)),
                New SKColor() {
                    SKColors.Transparent,
                    ColorMath.WithAlpha(ColorMath.Mix(botTint, SKColors.Black, recipe.ShadeMixT), recipe.ShadeA)
                },
                New Single() {recipe.ShadeStart, 1.0F},
                SKShaderTileMode.Clamp
            )

            If recipe.VignetteA > 0 Then
                _vignetteShader = SKShader.CreateRadialGradient(
                    New SKPoint(CSng(sizeKey.W) * 0.5F, CSng(sizeKey.H) * recipe.VignetteCenterYMul),
                    Math.Max(CSng(sizeKey.W), CSng(sizeKey.H)) * recipe.VignetteRadiusMul,
                    New SKColor() {
                        SKColors.Transparent,
                        ColorMath.WithAlpha(
                            ColorMath.Mix(botTint, SKColors.Black, 0.08F + ((recipe.ShadeMixT - 0.06F) * 0.8333333F)),
                            recipe.VignetteA)
                    },
                    New Single() {0.72F, 1.0F},
                    SKShaderTileMode.Clamp
                )
            End If

            _fxLastW = sizeKey.W
            _fxLastH = sizeKey.H
            _fxLastDpi100 = sizeKey.Dpi100
            _fxLastTop = spec.Top
            _fxLastBot = spec.Bot
        End Sub

#End Region

#Region "Recipe"

        Private Shared Function ResolveSoftChipFxRecipe() As SoftChipFxRecipe
            Dim fam As CommonEnums.SurfaceFamily = CommonEnums.SurfaceFamily.Chip

            Dim intensity As MASVisualEffectIntensityProfiles.AcrylicSurfaceIntensityProfile =
                MASVisualEffectIntensityProfiles.ResolveAcrylic(fam)

            Return New SoftChipFxRecipe With {
                .EdgeHiA = CByte(Math.Max(0, Math.Min(255, CInt(Math.Round(18.0F + (intensity.TopBandEmphasis * 24.0F) + (intensity.TopBandEmphasis * 10.0F)))))),
                .SheenA = If(intensity.UseTopSheen,
                             CByte(Math.Max(0, Math.Min(255, CInt(Math.Round(12.0F + (intensity.SheenStrength * 30.0F)))))),
                             CByte(0)),
                .ShadeA = CByte(Math.Max(0, Math.Min(255, CInt(Math.Round(5.0F + (intensity.BottomAnchorStrength * 12.0F)))))),
                .VignetteA = CByte(Math.Max(0, Math.Min(255, CInt(Math.Round(4.0F + (intensity.BottomAnchorStrength * 9.0F)))))),
                .EdgeMixT = 0.035F + (intensity.TopBandEmphasis * 0.05F),
                .SheenMixT = 0.03F + (intensity.SheenStrength * 0.045F),
                .ShadeMixT = 0.065F + (intensity.BottomAnchorStrength * 0.065F),
                .EdgeFadeStop = Math.Max(0.1F, Math.Min(0.32F, 0.15F + (intensity.TopBandEmphasis * 0.07F))),
                .SheenMid0 = 0.08F,
                .SheenMid1 = Math.Max(0.22F, Math.Min(0.46F, 0.28F + ((intensity.SheenHeightMul - 0.78F) * 0.12F))),
                .SheenMid2 = 0.0F,
                .ShadeStart = Math.Max(0.68F, Math.Min(0.9F, 0.81F - (intensity.BottomAnchorStrength * 0.07F))),
                .VignetteCenterYMul = 0.48F,
                .VignetteRadiusMul = 0.8F
            }
        End Function

#End Region

#Region "Chrome layers"

        Private Sub DrawSoftChipBaseGradient(canvas As SKCanvas,
                                             localRect As SKRect,
                                             radius As Single)

            _chipFill.Shader = _chipBodyShader
            _chipFill.BlendMode = SKBlendMode.SrcOver
            canvas.DrawRoundRect(localRect, radius, radius, _chipFill)
            _chipFill.Shader = Nothing
        End Sub

        Private Sub DrawSoftChipSheenFx(canvas As SKCanvas,
                                        localRect As SKRect)

            If _sheenShader Is Nothing Then Return

            _chipFx.Shader = _sheenShader
            _chipFx.BlendMode = SKBlendMode.SoftLight
            canvas.DrawRect(localRect, _chipFx)
            _chipFx.Shader = Nothing
            _chipFx.BlendMode = SKBlendMode.SrcOver
        End Sub

        Private Sub DrawSoftChipVignetteFx(canvas As SKCanvas,
                                           localRect As SKRect)

            If _vignetteShader Is Nothing Then Return

            _chipFx.Shader = _vignetteShader
            _chipFx.BlendMode = SKBlendMode.SrcOver
            canvas.DrawRect(localRect, _chipFx)
            _chipFx.Shader = Nothing
        End Sub

        Private Sub DrawSoftChipTopMicroBevel(canvas As SKCanvas,
                                              localRect As SKRect,
                                              radius As Single,
                                              dpi As Single)

            Dim w As Single =
    Math.Max(SurfaceTokens.FxRingStroke * dpi,
             SurfaceTokens.FxRingMinStrokePx)
            Dim y As Single = Math.Max(w / 2.0F, dpi)

            _chipBevel.StrokeWidth = w
            _chipBevel.Color = ColorMath.WithAlpha(SKColors.White, CByte(30))
            canvas.DrawLine(localRect.Left + (radius * 0.55F), y, localRect.Right - (radius * 0.55F), y, _chipBevel)
        End Sub

        Private Sub DrawSoftChipCustomWashFx(canvas As SKCanvas,
                                             r As SKRect,
                                             radius As Single,
                                             fxSpec As MASSoftChipChromeFxSpec)

            If canvas Is Nothing Then Return
            If r.Width <= 1.0F OrElse r.Height <= 1.0F Then Return
            If fxSpec.WashAlpha = 0 Then Return
            If fxSpec.WashColor.Alpha = 0 AndAlso
               fxSpec.WashColor.Red = 0 AndAlso
               fxSpec.WashColor.Green = 0 AndAlso
               fxSpec.WashColor.Blue = 0 Then Return

            Using sh As SKShader = SKShader.CreateLinearGradient(
                New SKPoint(r.Left, r.Top),
                New SKPoint(r.Left, r.Bottom),
                New SKColor() {
                    ColorMath.WithAlpha(fxSpec.WashColor, fxSpec.WashAlpha),
                    ColorMath.WithAlpha(fxSpec.WashColor, CByte(Math.Max(0, CInt(fxSpec.WashAlpha) \ 2))),
                    SKColors.Transparent
                },
                New Single() {0.0F, 0.42F, 1.0F},
                SKShaderTileMode.Clamp)

                PrepareChipFxPaint(SKBlendMode.SoftLight)
                _chipFx.Shader = sh

                MASVisualPrimitivesPainter.WithClipRoundRect(
                    canvas,
                    r,
                    radius,
                    Sub()
                        canvas.DrawRoundRect(r, radius, radius, _chipFx)
                    End Sub)

                _chipFx.Shader = Nothing
                _chipFx.BlendMode = SKBlendMode.SrcOver
            End Using
        End Sub

        Private Sub DrawSoftChipCustomInnerGlossFx(canvas As SKCanvas,
                                                   r As SKRect,
                                                   radius As Single,
                                                   fxSpec As MASSoftChipChromeFxSpec)

            If canvas Is Nothing Then Return
            If r.Width <= 1.0F OrElse r.Height <= 1.0F Then Return
            If fxSpec.InnerGlossAlpha = 0 Then Return

            Dim fadeT As Single = MASVisualPrimitivesPainter.Clamp01(fxSpec.InnerGlossFadeT)
            If fadeT < 0.12F Then fadeT = 0.12F

            Dim insetMul As Single = Math.Max(0.0F, fxSpec.InnerInsetMul)
            Dim radMul As Single = Math.Max(0.0F, fxSpec.InnerRadMul)

            Dim insetPx As Single = Math.Max(1.0F, radius * Math.Max(0.02F, insetMul))
            Dim innerR As SKRect = PixelSnap.InsetAll(r, insetPx)

            If innerR.Width <= 2.0F OrElse innerR.Height <= 2.0F Then Return

            Dim innerRadius As Single =
                Math.Max(0.0F, Math.Min(innerR.Height / 2.0F, radius * Math.Max(0.1F, radMul)))
            innerRadius = PixelSnap.SafeRadius(innerRadius)

            Dim glossH As Single = Math.Max(1.0F, Math.Min(innerR.Height * 0.14F, 4.0F))
            Dim glossR As New SKRect(
                innerR.Left,
                innerR.Top,
                innerR.Right,
                Math.Min(innerR.Bottom, innerR.Top + glossH)
            )

            Dim a0Base As Integer = CInt(fxSpec.InnerGlossAlpha)
            Dim a0 As Byte = CByte(Math.Max(0, Math.Min(255, CInt(Math.Round(a0Base * 0.38F)))))
            Dim a1 As Byte = CByte(Math.Max(0, Math.Min(255, CInt(Math.Round(a0 * 0.35F)))))

            Using sh As SKShader = SKShader.CreateLinearGradient(
                New SKPoint(glossR.Left, glossR.Top),
                New SKPoint(glossR.Left, glossR.Bottom),
                New SKColor() {
                    ColorMath.WithAlpha(fxSpec.InnerGlossColor, a0),
                    ColorMath.WithAlpha(fxSpec.InnerGlossColor, a1),
                    SKColors.Transparent
                },
                New Single() {0.0F, Math.Min(0.22F, fadeT), 1.0F},
                SKShaderTileMode.Clamp)

                PrepareChipFxPaint(SKBlendMode.SoftLight)
                _chipFx.Shader = sh

                MASVisualPrimitivesPainter.WithClipRoundRect(
                    canvas,
                    innerR,
                    innerRadius,
                    Sub()
                        canvas.DrawRect(glossR, _chipFx)
                    End Sub)

                _chipFx.Shader = Nothing
                _chipFx.BlendMode = SKBlendMode.SrcOver
            End Using
        End Sub

#End Region

#Region "Helpers"

        Private Sub PrepareChipFxPaint(Optional blendMode As SKBlendMode = SKBlendMode.SrcOver)
            _chipFx.IsAntialias = True
            _chipFx.IsDither = True
            _chipFx.Style = SKPaintStyle.Fill
            _chipFx.Color = SKColors.White
            _chipFx.Shader = Nothing
            _chipFx.ImageFilter = Nothing
            _chipFx.BlendMode = blendMode
        End Sub

        Private Shared Sub SafeDisposePaint(p As SKPaint)
            If p Is Nothing Then Return
            Try
                p.Dispose()
            Catch masCaughtException1 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowRenderFallback(masCaughtException1)
            End Try
        End Sub

#End Region

    End Class

End Namespace
