Esempio n. 1
0
        public void CanDrawRoundRectDifference()
        {
            using var outer = new SKRoundRect(SKRect.Create(50, 50, 200, 200), 20);
            using var inner = new SKRoundRect(SKRect.Create(100, 100, 100, 100), 20);

            using var paint = new SKPaint();

            SKColor[] diff;
            using (var bmp = new SKBitmap(new SKImageInfo(300, 300)))
                using (var canvas = new SKCanvas(bmp))
                {
                    canvas.Clear(SKColors.Transparent);
                    canvas.DrawRoundRectDifference(outer, inner, paint);

                    diff = bmp.Pixels;
                }

            SKColor[] paths;
            using (var bmp = new SKBitmap(new SKImageInfo(300, 300)))
                using (var canvas = new SKCanvas(bmp))
                    using (var path = new SKPath())
                    {
                        canvas.Clear(SKColors.Transparent);

                        path.AddRoundRect(outer);
                        path.AddRoundRect(inner);
                        path.FillType = SKPathFillType.EvenOdd;

                        canvas.DrawPath(path, paint);

                        paths = bmp.Pixels;
                    }

            Assert.Equal(paths, diff);
        }
Esempio n. 2
0
        /// <inheritdoc />
        public void DrawRectangle(IBrush brush, IPen pen, RoundedRect rect, BoxShadows boxShadows = default)
        {
            if (rect.Rect.Height <= 0 || rect.Rect.Width <= 0)
            {
                return;
            }
            // Arbitrary chosen values
            // On OSX Skia breaks OpenGL context when asked to draw, e. g. (0, 0, 623, 6666600) rect
            if (rect.Rect.Height > 8192 || rect.Rect.Width > 8192)
            {
                boxShadows = default;
            }

            var rc            = rect.Rect.ToSKRect();
            var isRounded     = rect.IsRounded;
            var needRoundRect = rect.IsRounded || (boxShadows.HasInsetShadows);

            using var skRoundRect = needRoundRect ? new SKRoundRect() : null;
            if (needRoundRect)
            {
                skRoundRect.SetRectRadii(rc,
                                         new[]
                {
                    rect.RadiiTopLeft.ToSKPoint(), rect.RadiiTopRight.ToSKPoint(),
                    rect.RadiiBottomRight.ToSKPoint(), rect.RadiiBottomLeft.ToSKPoint(),
                });
            }

            foreach (var boxShadow in boxShadows)
            {
                if (!boxShadow.IsEmpty && !boxShadow.IsInset)
                {
                    using (var shadow = BoxShadowFilter.Create(_boxShadowPaint, boxShadow, _currentOpacity))
                    {
                        var spread = (float)boxShadow.Spread;
                        if (boxShadow.IsInset)
                        {
                            spread = -spread;
                        }

                        Canvas.Save();
                        if (isRounded)
                        {
                            using var shadowRect = new SKRoundRect(skRoundRect);
                            if (spread != 0)
                            {
                                shadowRect.Inflate(spread, spread);
                            }
                            Canvas.ClipRoundRect(skRoundRect,
                                                 shadow.ClipOperation, true);

                            var oldTransform = Transform;
                            Transform = oldTransform * Matrix.CreateTranslation(boxShadow.OffsetX, boxShadow.OffsetY);
                            Canvas.DrawRoundRect(shadowRect, shadow.Paint);
                            Transform = oldTransform;
                        }
                        else
                        {
                            var shadowRect = rc;
                            if (spread != 0)
                            {
                                shadowRect.Inflate(spread, spread);
                            }
                            Canvas.ClipRect(rc, shadow.ClipOperation);
                            var oldTransform = Transform;
                            Transform = oldTransform * Matrix.CreateTranslation(boxShadow.OffsetX, boxShadow.OffsetY);
                            Canvas.DrawRect(shadowRect, shadow.Paint);
                            Transform = oldTransform;
                        }

                        Canvas.Restore();
                    }
                }
            }

            if (brush != null)
            {
                using (var paint = CreatePaint(_fillPaint, brush, rect.Rect.Size))
                {
                    if (isRounded)
                    {
                        Canvas.DrawRoundRect(skRoundRect, paint.Paint);
                    }
                    else
                    {
                        Canvas.DrawRect(rc, paint.Paint);
                    }
                }
            }

            foreach (var boxShadow in boxShadows)
            {
                if (!boxShadow.IsEmpty && boxShadow.IsInset)
                {
                    using (var shadow = BoxShadowFilter.Create(_boxShadowPaint, boxShadow, _currentOpacity))
                    {
                        var spread    = (float)boxShadow.Spread;
                        var offsetX   = (float)boxShadow.OffsetX;
                        var offsetY   = (float)boxShadow.OffsetY;
                        var outerRect = AreaCastingShadowInHole(rc, (float)boxShadow.Blur, spread, offsetX, offsetY);

                        Canvas.Save();
                        using var shadowRect = new SKRoundRect(skRoundRect);
                        if (spread != 0)
                        {
                            shadowRect.Deflate(spread, spread);
                        }
                        Canvas.ClipRoundRect(skRoundRect,
                                             shadow.ClipOperation, true);

                        var oldTransform = Transform;
                        Transform = oldTransform * Matrix.CreateTranslation(boxShadow.OffsetX, boxShadow.OffsetY);
                        using (var outerRRect = new SKRoundRect(outerRect))
                            Canvas.DrawRoundRectDifference(outerRRect, shadowRect, shadow.Paint);
                        Transform = oldTransform;
                        Canvas.Restore();
                    }
                }
            }

            if (pen?.Brush != null)
            {
                using (var paint = CreatePaint(_strokePaint, pen, rect.Rect.Size))
                {
                    if (isRounded)
                    {
                        Canvas.DrawRoundRect(skRoundRect, paint.Paint);
                    }
                    else
                    {
                        Canvas.DrawRect(rc, paint.Paint);
                    }
                }
            }
        }