<commit_before>﻿using System;
using Avalonia.Media;
using Avalonia.Platform;

namespace Avalonia.Controls.Utils
{
    internal class BorderRenderHelper
    {
        private bool _useComplexRendering;
        private bool? _backendSupportsIndividualCorners;
        private StreamGeometry _backgroundGeometryCache;
        private StreamGeometry _borderGeometryCache;
        private Size _size;
        private Thickness _borderThickness;
        private CornerRadius _cornerRadius;
        private bool _initialized;

        void Update(Size finalSize, Thickness borderThickness, CornerRadius cornerRadius)
        {
            _backendSupportsIndividualCorners ??= AvaloniaLocator.Current.GetService<IPlatformRenderInterface>()
                .SupportsIndividualRoundRects;
            _size = finalSize;
            _borderThickness = borderThickness;
            _cornerRadius = cornerRadius;
            _initialized = true;

            if (borderThickness.IsUniform && (cornerRadius.IsUniform || _backendSupportsIndividualCorners == true))
            {
                _backgroundGeometryCache = null;
                _borderGeometryCache = null;
                _useComplexRendering = false;
            }
            else
            {
                _useComplexRendering = true;

                var boundRect = new Rect(finalSize);
                var innerRect = boundRect.Deflate(borderThickness);
                BorderGeometryKeypoints backgroundKeypoints = null;
                StreamGeometry backgroundGeometry = null;

                if (innerRect.Width != 0 && innerRect.Height != 0)
                {
                    backgroundGeometry = new StreamGeometry();
                    backgroundKeypoints = new BorderGeometryKeypoints(innerRect, borderThickness, cornerRadius, true);

                    using (var ctx = backgroundGeometry.Open())
                    {
                        CreateGeometry(ctx, innerRect, backgroundKeypoints);
                    }

                    _backgroundGeometryCache = backgroundGeometry;
                }
                else
                {
                    _backgroundGeometryCache = null;
                }

                if (boundRect.Width != 0 && innerRect.Height != 0)
                {
                    var borderGeometryKeypoints = new BorderGeometryKeypoints(boundRect, borderThickness, cornerRadius, false);
                    var borderGeometry = new StreamGeometry();

                    using (var ctx = borderGeometry.Open())
                    {
                        CreateGeometry(ctx, boundRect, borderGeometryKeypoints);

                        if (backgroundGeometry != null)
                        {
                            CreateGeometry(ctx, innerRect, backgroundKeypoints);
                        }
                    }

                    _borderGeometryCache = borderGeometry;
                }
                else
                {
                    _borderGeometryCache = null;
                }
            }
        }

        public void Render(DrawingContext context,
            Size finalSize, Thickness borderThickness, CornerRadius cornerRadius,
            IBrush background, IBrush borderBrush, BoxShadows boxShadows)
        {
            if (_size != finalSize
                || _borderThickness != borderThickness
                || _cornerRadius != cornerRadius
                || !_initialized)
                Update(finalSize, borderThickness, cornerRadius);
            RenderCore(context, background, borderBrush, boxShadows);
        }

        void RenderCore(DrawingContext context, IBrush background, IBrush borderBrush, BoxShadows boxShadows)
        {
            if (_useComplexRendering)
            {
                var backgroundGeometry = _backgroundGeometryCache;
                if (backgroundGeometry != null)
                {
                    context.DrawGeometry(background, null, backgroundGeometry);
                }

                var borderGeometry = _borderGeometryCache;
                if (borderGeometry != null)
                {
                    context.DrawGeometry(borderBrush, null, borderGeometry);
                }
            }
            else
            {
                var borderThickness = _borderThickness.Top;
                IPen pen = null;

                if (borderThickness > 0)
                {
                    pen = new Pen(borderBrush, borderThickness);
                }

                var rrect = new RoundedRect(new Rect(_size), _cornerRadius.TopLeft, _cornerRadius.TopRight,
                    _cornerRadius.BottomRight, _cornerRadius.BottomLeft);
                if (Math.Abs(borderThickness) > double.Epsilon)
                {
                    rrect = rrect.Deflate(borderThickness * 0.5, borderThickness * 0.5);
                }

                context.PlatformImpl.DrawRectangle(background, pen, rrect, boxShadows);
            }
        }

        private static void CreateGeometry(StreamGeometryContext context, Rect boundRect, BorderGeometryKeypoints keypoints)
        {<commit_msg>Restore pre-BoxShadow rect deflation behavior<commit_after>﻿using System;
using Avalonia.Media;
using Avalonia.Platform;

namespace Avalonia.Controls.Utils
{
    internal class BorderRenderHelper
    {
        private bool _useComplexRendering;
        private bool? _backendSupportsIndividualCorners;
        private StreamGeometry _backgroundGeometryCache;
        private StreamGeometry _borderGeometryCache;
        private Size _size;
        private Thickness _borderThickness;
        private CornerRadius _cornerRadius;
        private bool _initialized;

        void Update(Size finalSize, Thickness borderThickness, CornerRadius cornerRadius)
        {
            _backendSupportsIndividualCorners ??= AvaloniaLocator.Current.GetService<IPlatformRenderInterface>()
                .SupportsIndividualRoundRects;
            _size = finalSize;
            _borderThickness = borderThickness;
            _cornerRadius = cornerRadius;
            _initialized = true;

            if (borderThickness.IsUniform && (cornerRadius.IsUniform || _backendSupportsIndividualCorners == true))
            {
                _backgroundGeometryCache = null;
                _borderGeometryCache = null;
                _useComplexRendering = false;
            }
            else
            {
                _useComplexRendering = true;

                var boundRect = new Rect(finalSize);
                var innerRect = boundRect.Deflate(borderThickness);
                BorderGeometryKeypoints backgroundKeypoints = null;
                StreamGeometry backgroundGeometry = null;

                if (innerRect.Width != 0 && innerRect.Height != 0)
                {
                    backgroundGeometry = new StreamGeometry();
                    backgroundKeypoints = new BorderGeometryKeypoints(innerRect, borderThickness, cornerRadius, true);

                    using (var ctx = backgroundGeometry.Open())
                    {
                        CreateGeometry(ctx, innerRect, backgroundKeypoints);
                    }

                    _backgroundGeometryCache = backgroundGeometry;
                }
                else
                {
                    _backgroundGeometryCache = null;
                }

                if (boundRect.Width != 0 && innerRect.Height != 0)
                {
                    var borderGeometryKeypoints = new BorderGeometryKeypoints(boundRect, borderThickness, cornerRadius, false);
                    var borderGeometry = new StreamGeometry();

                    using (var ctx = borderGeometry.Open())
                    {
                        CreateGeometry(ctx, boundRect, borderGeometryKeypoints);

                        if (backgroundGeometry != null)
                        {
                            CreateGeometry(ctx, innerRect, backgroundKeypoints);
                        }
                    }

                    _borderGeometryCache = borderGeometry;
                }
                else
                {
                    _borderGeometryCache = null;
                }
            }
        }

        public void Render(DrawingContext context,
            Size finalSize, Thickness borderThickness, CornerRadius cornerRadius,
            IBrush background, IBrush borderBrush, BoxShadows boxShadows)
        {
            if (_size != finalSize
                || _borderThickness != borderThickness
                || _cornerRadius != cornerRadius
                || !_initialized)
                Update(finalSize, borderThickness, cornerRadius);
            RenderCore(context, background, borderBrush, boxShadows);
        }

        void RenderCore(DrawingContext context, IBrush background, IBrush borderBrush, BoxShadows boxShadows)
        {
            if (_useComplexRendering)
            {
                var backgroundGeometry = _backgroundGeometryCache;
                if (backgroundGeometry != null)
                {
                    context.DrawGeometry(background, null, backgroundGeometry);
                }

                var borderGeometry = _borderGeometryCache;
                if (borderGeometry != null)
                {
                    context.DrawGeometry(borderBrush, null, borderGeometry);
                }
            }
            else
            {
                var borderThickness = _borderThickness.Top;
                IPen pen = null;

                if (borderThickness > 0)
                {
                    pen = new Pen(borderBrush, borderThickness);
                }

                var rect = new Rect(_size);
                if (Math.Abs(borderThickness) > double.Epsilon)
                    rect.Deflate(borderThickness * 0.5);
                var rrect = new RoundedRect(rect, _cornerRadius.TopLeft, _cornerRadius.TopRight,
                    _cornerRadius.BottomRight, _cornerRadius.BottomLeft);

                context.PlatformImpl.DrawRectangle(background, pen, rrect, boxShadows);
            }
        }

        private static void CreateGeometry(StreamGeometryContext context, Rect boundRect, BorderGeometryKeypoints keypoints)
        {
{'fraction_non_alphanumeric': 0.061578998731336, 'fraction_numerical': 0.0015614326144237339, 'mean_word_length': 1.5581627558662008, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5038071', 'n_tokens_mistral': 2476, 'n_tokens_neox': 2158, 'n_words': 492}