Beispiel #1
0
        internal void DrawMarker(SvgMarker svgMarker, SvgVisualElement pOwner, SKPoint pMarkerPoint, float fAngle)
        {
            var markerElement = GetMarkerElement(svgMarker);

            if (markerElement == null)
            {
                return;
            }

            var skMarkerMatrix = SKMatrix.MakeIdentity();

            var skMatrixMarkerPoint = SKMatrix.MakeTranslation(pMarkerPoint.X, pMarkerPoint.Y);

            SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixMarkerPoint);

            var skMatrixAngle = SKMatrix.MakeRotationDegrees(svgMarker.Orient.IsAuto ? fAngle : svgMarker.Orient.Angle);

            SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixAngle);

            var strokeWidth = pOwner.StrokeWidth.ToDeviceValue(null, UnitRenderingType.Other, svgMarker);

            var   refX         = svgMarker.RefX.ToDeviceValue(null, UnitRenderingType.Horizontal, svgMarker);
            var   refY         = svgMarker.RefY.ToDeviceValue(null, UnitRenderingType.Horizontal, svgMarker);
            float markerWidth  = svgMarker.MarkerWidth;
            float markerHeight = svgMarker.MarkerHeight;
            float viewBoxToMarkerUnitsScaleX = 1f;
            float viewBoxToMarkerUnitsScaleY = 1f;

            switch (svgMarker.MarkerUnits)
            {
            case SvgMarkerUnits.StrokeWidth:
            {
                var skMatrixStrokeWidth = SKMatrix.MakeScale(strokeWidth, strokeWidth);
                SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixStrokeWidth);

                var viewBoxWidth  = svgMarker.ViewBox.Width;
                var viewBoxHeight = svgMarker.ViewBox.Height;

                var scaleFactorWidth  = (viewBoxWidth <= 0) ? 1 : (markerWidth / viewBoxWidth);
                var scaleFactorHeight = (viewBoxHeight <= 0) ? 1 : (markerHeight / viewBoxHeight);

                viewBoxToMarkerUnitsScaleX = Math.Min(scaleFactorWidth, scaleFactorHeight);
                viewBoxToMarkerUnitsScaleY = Math.Min(scaleFactorWidth, scaleFactorHeight);

                var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX * viewBoxToMarkerUnitsScaleX, -refY * viewBoxToMarkerUnitsScaleY);
                SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY);

                var skMatrixScaleXY = SKMatrix.MakeScale(viewBoxToMarkerUnitsScaleX, viewBoxToMarkerUnitsScaleY);
                SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixScaleXY);
            }
            break;

            case SvgMarkerUnits.UserSpaceOnUse:
            {
                var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX, -refY);
                SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY);
            }
            break;
            }

            _skCanvas.Save();

            var skMatrix = SkiaUtil.GetSKMatrix(svgMarker.Transforms);

            SKMatrix.PreConcat(ref skMatrix, ref skMarkerMatrix);
            SetTransform(skMatrix);
            SetClipPath(svgMarker, _disposable);

            var skPaintOpacity = SetOpacity(svgMarker, _disposable);

            var skPaintFilter = SetFilter(svgMarker, _disposable);

            switch (svgMarker.Overflow)
            {
            case SvgOverflow.Auto:
            case SvgOverflow.Visible:
            case SvgOverflow.Inherit:
                break;

            default:
                var skClipRect = SKRect.Create(
                    svgMarker.ViewBox.MinX,
                    svgMarker.ViewBox.MinY,
                    markerWidth / viewBoxToMarkerUnitsScaleX,
                    markerHeight / viewBoxToMarkerUnitsScaleY);
                _skCanvas.ClipRect(skClipRect, SKClipOperation.Intersect);
                break;
            }

            Draw(markerElement, true);

            if (skPaintFilter != null)
            {
                _skCanvas.Restore();
            }

            if (skPaintOpacity != null)
            {
                _skCanvas.Restore();
            }

            _skCanvas.Restore();
        }
Beispiel #2
0
        public void DrawImage(SvgImage svgImage, bool ignoreDisplay)
        {
            if (!CanDraw(svgImage, ignoreDisplay))
            {
                return;
            }

            float width    = svgImage.Width.ToDeviceValue(null, UnitRenderingType.Horizontal, svgImage);
            float height   = svgImage.Height.ToDeviceValue(null, UnitRenderingType.Vertical, svgImage);
            var   location = svgImage.Location.ToDeviceValue(null, svgImage);

            if (width <= 0f || height <= 0f || svgImage.Href == null)
            {
                return;
            }

            var image       = SkiaUtil.GetImage(svgImage, svgImage.Href);
            var skImage     = image as SKImage;
            var svgFragment = image as SvgFragment;

            if (skImage == null && svgFragment == null)
            {
                return;
            }

            if (skImage != null)
            {
                _disposable.Add(skImage);
            }

            SKRect srcRect = default;

            if (skImage != null)
            {
                srcRect = SKRect.Create(0f, 0f, skImage.Width, skImage.Height);
            }

            if (svgFragment != null)
            {
                var skSize = SkiaUtil.GetDimensions(svgFragment);
                srcRect = SKRect.Create(0f, 0f, skSize.Width, skSize.Height);
            }

            var destClip = SKRect.Create(location.X, location.Y, width, height);
            var destRect = destClip;

            var aspectRatio = svgImage.AspectRatio;

            if (aspectRatio.Align != SvgPreserveAspectRatio.none)
            {
                var fScaleX = destClip.Width / srcRect.Width;
                var fScaleY = destClip.Height / srcRect.Height;
                var xOffset = 0f;
                var yOffset = 0f;

                if (aspectRatio.Slice)
                {
                    fScaleX = Math.Max(fScaleX, fScaleY);
                    fScaleY = Math.Max(fScaleX, fScaleY);
                }
                else
                {
                    fScaleX = Math.Min(fScaleX, fScaleY);
                    fScaleY = Math.Min(fScaleX, fScaleY);
                }

                switch (aspectRatio.Align)
                {
                case SvgPreserveAspectRatio.xMinYMin:
                    break;

                case SvgPreserveAspectRatio.xMidYMin:
                    xOffset = (destClip.Width - srcRect.Width * fScaleX) / 2;
                    break;

                case SvgPreserveAspectRatio.xMaxYMin:
                    xOffset = (destClip.Width - srcRect.Width * fScaleX);
                    break;

                case SvgPreserveAspectRatio.xMinYMid:
                    yOffset = (destClip.Height - srcRect.Height * fScaleY) / 2;
                    break;

                case SvgPreserveAspectRatio.xMidYMid:
                    xOffset = (destClip.Width - srcRect.Width * fScaleX) / 2;
                    yOffset = (destClip.Height - srcRect.Height * fScaleY) / 2;
                    break;

                case SvgPreserveAspectRatio.xMaxYMid:
                    xOffset = (destClip.Width - srcRect.Width * fScaleX);
                    yOffset = (destClip.Height - srcRect.Height * fScaleY) / 2;
                    break;

                case SvgPreserveAspectRatio.xMinYMax:
                    yOffset = (destClip.Height - srcRect.Height * fScaleY);
                    break;

                case SvgPreserveAspectRatio.xMidYMax:
                    xOffset = (destClip.Width - srcRect.Width * fScaleX) / 2;
                    yOffset = (destClip.Height - srcRect.Height * fScaleY);
                    break;

                case SvgPreserveAspectRatio.xMaxYMax:
                    xOffset = (destClip.Width - srcRect.Width * fScaleX);
                    yOffset = (destClip.Height - srcRect.Height * fScaleY);
                    break;
                }

                destRect = SKRect.Create(
                    destClip.Left + xOffset, destClip.Top + yOffset,
                    srcRect.Width * fScaleX, srcRect.Height * fScaleY);
            }

            _skCanvas.Save();

            var skMatrix = SkiaUtil.GetSKMatrix(svgImage.Transforms);

            SetTransform(skMatrix);
            SetClipPath(svgImage, _disposable);

            var skPaintOpacity = SetOpacity(svgImage, _disposable);

            var skPaintFilter = SetFilter(svgImage, _disposable);

            _skCanvas.ClipRect(destClip, SKClipOperation.Intersect);

            SetClip(svgImage, destClip);

            if (skImage != null)
            {
                _skCanvas.DrawImage(skImage, srcRect, destRect);
            }

            if (svgFragment != null)
            {
                _skCanvas.Save();

                float dx = destRect.Left;
                float dy = destRect.Top;
                float sx = destRect.Width / srcRect.Width;
                float sy = destRect.Height / srcRect.Height;
                var   skTranslationMatrix = SKMatrix.MakeTranslation(dx, dy);
                var   skScaleMatrix       = SKMatrix.MakeScale(sx, sy);
                SKMatrix.PreConcat(ref skTranslationMatrix, ref skScaleMatrix);
                SetTransform(skTranslationMatrix);

                DrawFragment(svgFragment, ignoreDisplay);

                _skCanvas.Restore();
            }

            if (skPaintFilter != null)
            {
                _skCanvas.Restore();
            }

            if (skPaintOpacity != null)
            {
                _skCanvas.Restore();
            }

            _skCanvas.Restore();
        }
Beispiel #3
0
        private PaintWrapper CreatePaint(IBrush brush, Size targetSize)
        {
            SKPaint paint = new SKPaint();
            var     rv    = new PaintWrapper(paint);

            paint.IsStroke = false;

            // TODO: SkiaSharp does not contain alpha yet!
            double opacity = brush.Opacity * _currentOpacity;

            //paint.SetAlpha(paint.GetAlpha() * opacity);
            paint.IsAntialias = true;

            SKColor color = new SKColor(255, 255, 255, 255);

            var solid = brush as SolidColorBrush;

            if (solid != null)
            {
                color = solid.Color.ToSKColor();
            }

            paint.Color = (new SKColor(color.Red, color.Green, color.Blue, (byte)(color.Alpha * opacity)));
            if (solid != null)
            {
                return(rv);
            }


            var gradient = brush as GradientBrush;

            if (gradient != null)
            {
                var tileMode    = gradient.SpreadMethod.ToSKShaderTileMode();
                var stopColors  = gradient.GradientStops.Select(s => s.Color.ToSKColor()).ToArray();
                var stopOffsets = gradient.GradientStops.Select(s => (float)s.Offset).ToArray();

                var linearGradient = brush as LinearGradientBrush;
                if (linearGradient != null)
                {
                    var start = linearGradient.StartPoint.ToPixels(targetSize).ToSKPoint();
                    var end   = linearGradient.EndPoint.ToPixels(targetSize).ToSKPoint();

                    // would be nice to cache these shaders possibly?
                    var shader = SKShader.CreateLinearGradient(start, end, stopColors, stopOffsets, tileMode);
                    paint.Shader = shader;
                    shader.Dispose();
                }
                else
                {
                    var radialGradient = brush as RadialGradientBrush;
                    if (radialGradient != null)
                    {
                        var center = radialGradient.Center.ToPixels(targetSize).ToSKPoint();
                        var radius = (float)radialGradient.Radius;

                        // TODO: There is no SetAlpha in SkiaSharp
                        //paint.setAlpha(128);

                        // would be nice to cache these shaders possibly?
                        var shader = SKShader.CreateRadialGradient(center, radius, stopColors, stopOffsets, tileMode);
                        paint.Shader = shader;
                        shader.Dispose();
                    }
                }

                return(rv);
            }

            var tileBrush = brush as TileBrush;

            if (tileBrush != null)
            {
                var helper = new TileBrushImplHelper(tileBrush, targetSize);
                var bitmap = new BitmapImpl((int)helper.IntermediateSize.Width, (int)helper.IntermediateSize.Height);
                rv.AddDisposable(bitmap);
                using (var ctx = bitmap.CreateDrawingContext())
                    helper.DrawIntermediate(ctx);
                SKMatrix         translation = SKMatrix.MakeTranslation(-(float)helper.DestinationRect.X, -(float)helper.DestinationRect.Y);
                SKShaderTileMode tileX       =
                    tileBrush.TileMode == TileMode.None
                        ? SKShaderTileMode.Clamp
                        : tileBrush.TileMode == TileMode.FlipX || tileBrush.TileMode == TileMode.FlipXY
                            ? SKShaderTileMode.Mirror
                            : SKShaderTileMode.Repeat;

                SKShaderTileMode tileY =
                    tileBrush.TileMode == TileMode.None
                        ? SKShaderTileMode.Clamp
                        : tileBrush.TileMode == TileMode.FlipY || tileBrush.TileMode == TileMode.FlipXY
                            ? SKShaderTileMode.Mirror
                            : SKShaderTileMode.Repeat;
                paint.Shader = SKShader.CreateBitmap(bitmap.Bitmap, tileX, tileY, translation);
                paint.Shader.Dispose();
            }

            return(rv);
        }
Beispiel #4
0
        public ImageDrawable(SvgImage svgImage, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None)
            : base(svgImage, root, parent)
        {
            IgnoreAttributes = ignoreAttributes;
            IsDrawable       = CanDraw(svgImage, IgnoreAttributes) && HasFeatures(svgImage, IgnoreAttributes);

            if (!IsDrawable)
            {
                return;
            }

            float width    = svgImage.Width.ToDeviceValue(UnitRenderingType.Horizontal, svgImage, skOwnerBounds);
            float height   = svgImage.Height.ToDeviceValue(UnitRenderingType.Vertical, svgImage, skOwnerBounds);
            float x        = svgImage.Location.X.ToDeviceValue(UnitRenderingType.Horizontal, svgImage, skOwnerBounds);
            float y        = svgImage.Location.Y.ToDeviceValue(UnitRenderingType.Vertical, svgImage, skOwnerBounds);
            var   location = new SKPoint(x, y);

            if (width <= 0f || height <= 0f || svgImage.Href == null)
            {
                IsDrawable = false;
                return;
            }

            // TODO: Check for image recursive references.
            //if (SkiaUtil.HasRecursiveReference(svgImage, (e) => e.Href))
            //{
            //    _canDraw = false;
            //    return;
            //}

            var image       = SvgImageExtensions.GetImage(svgImage.Href, svgImage.OwnerDocument);
            var skImage     = image as SKImage;
            var svgFragment = image as SvgFragment;

            if (skImage == null && svgFragment == null)
            {
                IsDrawable = false;
                return;
            }

            if (skImage != null)
            {
                _disposable.Add(skImage);
            }

            SrcRect = default;

            if (skImage != null)
            {
                SrcRect = SKRect.Create(0f, 0f, skImage.Width, skImage.Height);
            }

            if (svgFragment != null)
            {
                var skSize = SvgExtensions.GetDimensions(svgFragment);
                SrcRect = SKRect.Create(0f, 0f, skSize.Width, skSize.Height);
            }

            var destClip = SKRect.Create(location.X, location.Y, width, height);

            var aspectRatio = svgImage.AspectRatio;

            if (aspectRatio.Align != SvgPreserveAspectRatio.none)
            {
                var fScaleX = destClip.Width / SrcRect.Width;
                var fScaleY = destClip.Height / SrcRect.Height;
                var xOffset = 0f;
                var yOffset = 0f;

                if (aspectRatio.Slice)
                {
                    fScaleX = Math.Max(fScaleX, fScaleY);
                    fScaleY = Math.Max(fScaleX, fScaleY);
                }
                else
                {
                    fScaleX = Math.Min(fScaleX, fScaleY);
                    fScaleY = Math.Min(fScaleX, fScaleY);
                }

                switch (aspectRatio.Align)
                {
                case SvgPreserveAspectRatio.xMinYMin:
                    break;

                case SvgPreserveAspectRatio.xMidYMin:
                    xOffset = (destClip.Width - SrcRect.Width * fScaleX) / 2;
                    break;

                case SvgPreserveAspectRatio.xMaxYMin:
                    xOffset = (destClip.Width - SrcRect.Width * fScaleX);
                    break;

                case SvgPreserveAspectRatio.xMinYMid:
                    yOffset = (destClip.Height - SrcRect.Height * fScaleY) / 2;
                    break;

                case SvgPreserveAspectRatio.xMidYMid:
                    xOffset = (destClip.Width - SrcRect.Width * fScaleX) / 2;
                    yOffset = (destClip.Height - SrcRect.Height * fScaleY) / 2;
                    break;

                case SvgPreserveAspectRatio.xMaxYMid:
                    xOffset = (destClip.Width - SrcRect.Width * fScaleX);
                    yOffset = (destClip.Height - SrcRect.Height * fScaleY) / 2;
                    break;

                case SvgPreserveAspectRatio.xMinYMax:
                    yOffset = (destClip.Height - SrcRect.Height * fScaleY);
                    break;

                case SvgPreserveAspectRatio.xMidYMax:
                    xOffset = (destClip.Width - SrcRect.Width * fScaleX) / 2;
                    yOffset = (destClip.Height - SrcRect.Height * fScaleY);
                    break;

                case SvgPreserveAspectRatio.xMaxYMax:
                    xOffset = (destClip.Width - SrcRect.Width * fScaleX);
                    yOffset = (destClip.Height - SrcRect.Height * fScaleY);
                    break;
                }

                DestRect = SKRect.Create(
                    destClip.Left + xOffset,
                    destClip.Top + yOffset,
                    SrcRect.Width * fScaleX,
                    SrcRect.Height * fScaleY);
            }
            else
            {
                DestRect = destClip;
            }

            Clip = destClip;

            var skClipRect = SvgClippingExtensions.GetClipRect(svgImage, destClip);

            if (skClipRect != null)
            {
                Clip = skClipRect;
            }

            if (skImage != null)
            {
                Image = skImage;
            }

            if (svgFragment != null)
            {
                FragmentDrawable = new FragmentDrawable(svgFragment, skOwnerBounds, root, this, ignoreAttributes);
                _disposable.Add(FragmentDrawable);
            }

            IsAntialias = SvgPaintingExtensions.IsAntialias(svgImage);

            if (Image != null)
            {
                TransformedBounds = DestRect;
            }

            if (FragmentDrawable != null)
            {
                //_skBounds = _fragmentDrawable._skBounds;
                TransformedBounds = DestRect;
            }

            Transform         = SvgTransformsExtensions.ToSKMatrix(svgImage.Transforms);
            FragmentTransform = SKMatrix.MakeIdentity();
            if (FragmentDrawable != null)
            {
                float dx = DestRect.Left;
                float dy = DestRect.Top;
                float sx = DestRect.Width / SrcRect.Width;
                float sy = DestRect.Height / SrcRect.Height;
                var   skTranslationMatrix = SKMatrix.MakeTranslation(dx, dy);
                var   skScaleMatrix       = SKMatrix.MakeScale(sx, sy);
                SKMatrix.PreConcat(ref FragmentTransform, ref skTranslationMatrix);
                SKMatrix.PreConcat(ref FragmentTransform, ref skScaleMatrix);
            }

            Fill   = null;
            Stroke = null;

            // TODO: Transform _skBounds using _skMatrix.
            SKMatrix.MapRect(ref Transform, out TransformedBounds, ref TransformedBounds);
        }
Beispiel #5
0
 public static SKMatrix Translate(this SKMatrix m, float dx, float dy)
 {
     return(m.Concat(SKMatrix.MakeTranslation(dx, dy)));
 }
Beispiel #6
0
        void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
        {
            SKImageInfo info    = args.Info;
            SKSurface   surface = args.Surface;
            SKCanvas    canvas  = surface.Canvas;

            canvas.Clear();

            float x = (info.Width - monkeyBitmap.Width) / 2;
            float y = info.Height - monkeyBitmap.Height;

            // Draw monkey bitmap
            if (step >= 1)
            {
                canvas.DrawBitmap(monkeyBitmap, x, y);
            }

            // Draw matte to exclude monkey's surroundings
            if (step >= 2)
            {
                using (SKPaint paint = new SKPaint())
                {
                    paint.BlendMode = SKBlendMode.DstIn;
                    canvas.DrawBitmap(matteBitmap, x, y, paint);
                }
            }

            const float sidewalkHeight = 80;
            SKRect      rect           = new SKRect(info.Rect.Left, info.Rect.Bottom - sidewalkHeight,
                                                    info.Rect.Right, info.Rect.Bottom);

            // Draw gravel sidewalk for monkey to sit on
            if (step >= 3)
            {
                using (SKPaint paint = new SKPaint())
                {
                    paint.Shader = SKShader.CreateCompose(
                        SKShader.CreateColor(SKColors.SandyBrown),
                        SKShader.CreatePerlinNoiseTurbulence(0.1f, 0.3f, 1, 9));

                    paint.BlendMode = SKBlendMode.DstOver;
                    canvas.DrawRect(rect, paint);
                }
            }

            // Draw bitmap tiled brick wall behind monkey
            if (step >= 4)
            {
                using (SKPaint paint = new SKPaint())
                {
                    SKBitmap bitmap  = BrickWallTile;
                    float    yAdjust = (info.Height - sidewalkHeight) % bitmap.Height;

                    paint.Shader = SKShader.CreateBitmap(bitmap,
                                                         SKShaderTileMode.Repeat,
                                                         SKShaderTileMode.Repeat,
                                                         SKMatrix.MakeTranslation(0, yAdjust));
                    paint.BlendMode = SKBlendMode.DstOver;
                    canvas.DrawRect(info.Rect, paint);
                }
            }
        }
Beispiel #7
0
        internal PaintWrapper CreatePaint(IBrush brush, Size targetSize)
        {
            SKPaint paint = new SKPaint();
            var     rv    = new PaintWrapper(paint);

            paint.IsStroke = false;


            double opacity = brush.Opacity * _currentOpacity;

            paint.IsAntialias = true;

            var solid = brush as ISolidColorBrush;

            if (solid != null)
            {
                paint.Color = new SKColor(solid.Color.R, solid.Color.G, solid.Color.B, (byte)(solid.Color.A * opacity));
                return(rv);
            }
            paint.Color = (new SKColor(255, 255, 255, (byte)(255 * opacity)));

            var gradient = brush as IGradientBrush;

            if (gradient != null)
            {
                var tileMode    = gradient.SpreadMethod.ToSKShaderTileMode();
                var stopColors  = gradient.GradientStops.Select(s => s.Color.ToSKColor()).ToArray();
                var stopOffsets = gradient.GradientStops.Select(s => (float)s.Offset).ToArray();

                var linearGradient = brush as ILinearGradientBrush;
                if (linearGradient != null)
                {
                    var start = linearGradient.StartPoint.ToPixels(targetSize).ToSKPoint();
                    var end   = linearGradient.EndPoint.ToPixels(targetSize).ToSKPoint();

                    // would be nice to cache these shaders possibly?
                    using (var shader = SKShader.CreateLinearGradient(start, end, stopColors, stopOffsets, tileMode))
                        paint.Shader = shader;
                }
                else
                {
                    var radialGradient = brush as IRadialGradientBrush;
                    if (radialGradient != null)
                    {
                        var center = radialGradient.Center.ToPixels(targetSize).ToSKPoint();
                        var radius = (float)radialGradient.Radius;

                        // TODO: There is no SetAlpha in SkiaSharp
                        //paint.setAlpha(128);

                        // would be nice to cache these shaders possibly?
                        using (var shader = SKShader.CreateRadialGradient(center, radius, stopColors, stopOffsets, tileMode))
                            paint.Shader = shader;
                    }
                }

                return(rv);
            }

            var tileBrush      = brush as ITileBrush;
            var visualBrush    = brush as IVisualBrush;
            var tileBrushImage = default(BitmapImpl);

            if (visualBrush != null)
            {
                if (_visualBrushRenderer != null)
                {
                    var intermediateSize = _visualBrushRenderer.GetRenderTargetSize(visualBrush);

                    if (intermediateSize.Width >= 1 && intermediateSize.Height >= 1)
                    {
                        var intermediate = new BitmapImpl((int)intermediateSize.Width, (int)intermediateSize.Height, _dpi);

                        using (var ctx = intermediate.CreateDrawingContext(_visualBrushRenderer))
                        {
                            ctx.Clear(Colors.Transparent);
                            _visualBrushRenderer.RenderVisualBrush(ctx, visualBrush);
                        }

                        rv.AddDisposable(tileBrushImage);
                        tileBrushImage = intermediate;
                    }
                }
                else
                {
                    throw new NotSupportedException("No IVisualBrushRenderer was supplied to DrawingContextImpl.");
                }
            }
            else
            {
                tileBrushImage = (BitmapImpl)((tileBrush as IImageBrush)?.Source?.PlatformImpl);
            }

            if (tileBrush != null && tileBrushImage != null)
            {
                var calc   = new TileBrushCalculator(tileBrush, new Size(tileBrushImage.PixelWidth, tileBrushImage.PixelHeight), targetSize);
                var bitmap = new BitmapImpl((int)calc.IntermediateSize.Width, (int)calc.IntermediateSize.Height, _dpi);
                rv.AddDisposable(bitmap);
                using (var context = bitmap.CreateDrawingContext(null))
                {
                    var rect = new Rect(0, 0, tileBrushImage.PixelWidth, tileBrushImage.PixelHeight);

                    context.Clear(Colors.Transparent);
                    context.PushClip(calc.IntermediateClip);
                    context.Transform = calc.IntermediateTransform;
                    context.DrawImage(tileBrushImage, 1, rect, rect);
                    context.PopClip();
                }

                SKMatrix         translation = SKMatrix.MakeTranslation(-(float)calc.DestinationRect.X, -(float)calc.DestinationRect.Y);
                SKShaderTileMode tileX       =
                    tileBrush.TileMode == TileMode.None
                        ? SKShaderTileMode.Clamp
                        : tileBrush.TileMode == TileMode.FlipX || tileBrush.TileMode == TileMode.FlipXY
                            ? SKShaderTileMode.Mirror
                            : SKShaderTileMode.Repeat;

                SKShaderTileMode tileY =
                    tileBrush.TileMode == TileMode.None
                        ? SKShaderTileMode.Clamp
                        : tileBrush.TileMode == TileMode.FlipY || tileBrush.TileMode == TileMode.FlipXY
                            ? SKShaderTileMode.Mirror
                            : SKShaderTileMode.Repeat;
                using (var shader = SKShader.CreateBitmap(bitmap.Bitmap, tileX, tileY, translation))
                    paint.Shader = shader;
            }

            return(rv);
        }
Beispiel #8
0
        private void ReadElement(XElement e, SKCanvas canvas, SKPaint stroke, SKPaint fill)
        {
            if (e.Attribute("display")?.Value == "none")
            {
                return;
            }

            // transform matrix
            var transform = ReadTransform(e.Attribute("transform")?.Value ?? string.Empty);

            canvas.Save();
            canvas.Concat(ref transform);

            // clip-path
            var clipPath = ReadClipPath(e.Attribute("clip-path")?.Value ?? string.Empty);

            if (clipPath != null)
            {
                canvas.ClipPath(clipPath);
            }

            // SVG element
            var elementName = e.Name.LocalName;
            var isGroup     = elementName == "g";

            // read style
            var style = ReadPaints(e, ref stroke, ref fill, isGroup);

            // parse elements
            switch (elementName)
            {
            case "image":
            {
                var image = ReadImage(e);
                if (image.Bytes != null)
                {
                    using (var bitmap = SKBitmap.Decode(image.Bytes))
                    {
                        if (bitmap != null)
                        {
                            canvas.DrawBitmap(bitmap, image.Rect);
                        }
                    }
                }
                break;
            }

            case "text":
                if (stroke != null || fill != null)
                {
                    var spans = ReadText(e, stroke?.Clone(), fill?.Clone());
                    if (spans.Any())
                    {
                        canvas.DrawText(spans);
                    }
                }
                break;

            case "rect":
            case "ellipse":
            case "circle":
            case "path":
            case "polygon":
            case "polyline":
            case "line":
                if (stroke != null || fill != null)
                {
                    var elementPath = ReadElement(e);
                    if (elementPath != null)
                    {
                        if (fill != null)
                        {
                            canvas.DrawPath(elementPath, fill);
                        }
                        if (stroke != null)
                        {
                            canvas.DrawPath(elementPath, stroke);
                        }
                    }
                }
                break;

            case "g":
                if (e.HasElements)
                {
                    // get current group opacity
                    float groupOpacity = ReadOpacity(style);
                    if (groupOpacity != 1.0f)
                    {
                        var opacity      = (byte)(255 * groupOpacity);
                        var opacityPaint = new SKPaint {
                            Color = SKColors.Black.WithAlpha(opacity)
                        };

                        // apply the opacity
                        canvas.SaveLayer(opacityPaint);
                    }

                    foreach (var gElement in e.Elements())
                    {
                        ReadElement(gElement, canvas, stroke?.Clone(), fill?.Clone());
                    }

                    // restore state
                    if (groupOpacity != 1.0f)
                    {
                        canvas.Restore();
                    }
                }
                break;

            case "use":
                if (e.HasAttributes)
                {
                    var href = ReadHref(e);
                    if (href != null)
                    {
                        // TODO: copy/process other attributes

                        var x            = ReadNumber(e.Attribute("x"));
                        var y            = ReadNumber(e.Attribute("y"));
                        var useTransform = SKMatrix.MakeTranslation(x, y);

                        canvas.Save();
                        canvas.Concat(ref useTransform);

                        ReadElement(href, canvas, stroke?.Clone(), fill?.Clone());

                        canvas.Restore();
                    }
                }
                break;

            case "switch":
                if (e.HasElements)
                {
                    foreach (var ee in e.Elements())
                    {
                        var requiredFeatures   = ee.Attribute("requiredFeatures");
                        var requiredExtensions = ee.Attribute("requiredExtensions");
                        var systemLanguage     = ee.Attribute("systemLanguage");

                        // TODO: evaluate requiredFeatures, requiredExtensions and systemLanguage
                        var isVisible =
                            requiredFeatures == null &&
                            requiredExtensions == null &&
                            systemLanguage == null;

                        if (isVisible)
                        {
                            ReadElement(ee, canvas, stroke?.Clone(), fill?.Clone());
                        }
                    }
                }
                break;

            case "defs":
            case "title":
            case "desc":
            case "description":
                // already read earlier
                break;

            default:
                LogOrThrow($"SVG element '{elementName}' is not supported");
                break;
            }

            // restore matrix
            canvas.Restore();
        }
Beispiel #9
0
        public MarkerDrawable(SvgMarker svgMarker, SvgVisualElement pOwner, SKPoint pMarkerPoint, float fAngle, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None)
            : base(svgMarker, root, parent)
        {
            IgnoreAttributes = Attributes.Display | ignoreAttributes;
            IsDrawable       = true;

            if (!IsDrawable)
            {
                return;
            }

            var markerElement = GetMarkerElement(svgMarker);

            if (markerElement == null)
            {
                IsDrawable = false;
                return;
            }

            var skMarkerMatrix = SKMatrix.MakeIdentity();

            var skMatrixMarkerPoint = SKMatrix.MakeTranslation(pMarkerPoint.X, pMarkerPoint.Y);

            SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixMarkerPoint);

            var skMatrixAngle = SKMatrix.MakeRotationDegrees(svgMarker.Orient.IsAuto ? fAngle : svgMarker.Orient.Angle);

            SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixAngle);

            var strokeWidth = pOwner.StrokeWidth.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds);

            var   refX         = svgMarker.RefX.ToDeviceValue(UnitRenderingType.Horizontal, svgMarker, skOwnerBounds);
            var   refY         = svgMarker.RefY.ToDeviceValue(UnitRenderingType.Vertical, svgMarker, skOwnerBounds);
            float markerWidth  = svgMarker.MarkerWidth.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds);
            float markerHeight = svgMarker.MarkerHeight.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds);
            float viewBoxToMarkerUnitsScaleX = 1f;
            float viewBoxToMarkerUnitsScaleY = 1f;

            switch (svgMarker.MarkerUnits)
            {
            case SvgMarkerUnits.StrokeWidth:
            {
                var skMatrixStrokeWidth = SKMatrix.MakeScale(strokeWidth, strokeWidth);
                SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixStrokeWidth);

                var viewBoxWidth  = svgMarker.ViewBox.Width;
                var viewBoxHeight = svgMarker.ViewBox.Height;

                var scaleFactorWidth  = (viewBoxWidth <= 0) ? 1 : (markerWidth / viewBoxWidth);
                var scaleFactorHeight = (viewBoxHeight <= 0) ? 1 : (markerHeight / viewBoxHeight);

                viewBoxToMarkerUnitsScaleX = Math.Min(scaleFactorWidth, scaleFactorHeight);
                viewBoxToMarkerUnitsScaleY = Math.Min(scaleFactorWidth, scaleFactorHeight);

                var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX * viewBoxToMarkerUnitsScaleX, -refY * viewBoxToMarkerUnitsScaleY);
                SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY);

                var skMatrixScaleXY = SKMatrix.MakeScale(viewBoxToMarkerUnitsScaleX, viewBoxToMarkerUnitsScaleY);
                SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixScaleXY);
            }
            break;

            case SvgMarkerUnits.UserSpaceOnUse:
            {
                var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX, -refY);
                SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY);
            }
            break;
            }

            switch (svgMarker.Overflow)
            {
            case SvgOverflow.Auto:
            case SvgOverflow.Visible:
            case SvgOverflow.Inherit:
                break;

            default:
                MarkerClipRect = SKRect.Create(
                    svgMarker.ViewBox.MinX,
                    svgMarker.ViewBox.MinY,
                    markerWidth / viewBoxToMarkerUnitsScaleX,
                    markerHeight / viewBoxToMarkerUnitsScaleY);
                break;
            }

            var drawable = DrawableFactory.Create(markerElement, skOwnerBounds, root, this, Attributes.Display);

            if (drawable != null)
            {
                MarkerElementDrawable = drawable;
                _disposable.Add(MarkerElementDrawable);
            }
            else
            {
                IsDrawable = false;
                return;
            }

            IsAntialias = SvgPaintingExtensions.IsAntialias(svgMarker);

            TransformedBounds = MarkerElementDrawable.TransformedBounds;

            Transform = SvgTransformsExtensions.ToSKMatrix(svgMarker.Transforms);
            SKMatrix.PreConcat(ref Transform, ref skMarkerMatrix);

            Fill   = null;
            Stroke = null;

            // TODO: Transform _skBounds using _skMatrix.
            SKMatrix.MapRect(ref Transform, out TransformedBounds, ref TransformedBounds);
        }
        void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
        {
            SKImageInfo info    = args.Info;
            SKSurface   surface = args.Surface;
            SKCanvas    canvas  = surface.Canvas;

            canvas.Clear();

            string strName   = Apartment.Name;
            string strRating = Apartment.RatesAverage?.ToString();

            // Create an SKPaint object to display the text
            SKPaint textPaint = new SKPaint
            {
                Typeface = SKTypeface.FromFamilyName("Brandon_reg"),
                Color    = SKColors.Black
            };

            // Adjust TextSize property so text is 90% of screen width
            textPaint.TextSize = 0.05f * info.Width;

            // Find the text bounds
            SKRect textBounds = new SKRect();

            textPaint.MeasureText(strName, ref textBounds);

            // Calculate offsets to center the text on the screen
            float xTextName = 0.1f * info.Width;
            float yTextName = info.Height / 2 - textBounds.MidY;

            float yTextRating = yTextName + 1.2f * textBounds.Height;


            // And draw the text


            float xCenter = info.Width / 2;
            float yCenter = info.Height / 2;

            // Translate center to origin
            SKMatrix matrix = SKMatrix.MakeTranslation(-xCenter, -yCenter);

            // Use 3D matrix for 3D rotations and perspective
            SKMatrix44 matrix44 = SKMatrix44.CreateIdentity();

            matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(1, 0, 0, angle));


            SKMatrix44 perspectiveMatrix = SKMatrix44.CreateIdentity();

            perspectiveMatrix[3, 2] = -1 / (float)2000;
            matrix44.PostConcat(perspectiveMatrix);

            // Concatenate with 2D matrix
            SKMatrix.PostConcat(ref matrix, matrix44.Matrix);

            // Translate back to center
            SKMatrix.PostConcat(ref matrix,
                                SKMatrix.MakeTranslation(xCenter, yCenter));

            // Set the matrix and display the bitmap
            canvas.SetMatrix(matrix);

            // Create a new SKRect object for the frame around the text
            SKRect frameRect = SKRect.Create(0.05f * info.Width, 0, 0.9f * info.Width, info.Height);

            // Create an SKPaint object to display the frame
            SKPaint framePaint = new SKPaint
            {
                Style       = SKPaintStyle.Stroke,
                StrokeWidth = 5,
                Color       = SKColors.Blue
            };

            SKPaint rectanglePaint = new SKPaint
            {
                Color = SKColors.Beige
            };

            // Draw one frame
            canvas.DrawRoundRect(frameRect, 20, 20, rectanglePaint);

            canvas.DrawText(strName, xTextName, yTextName, textPaint);
            canvas.DrawText($"{strRating}", xTextName, yTextRating, textPaint);


            if (bitmap != null)
            {
                var pictureFrame = SKRect.Create(info.Width * (float)0.7, 0, info.Width * (float)0.25, info.Height);

                float xBitmap = (float)0.8 * info.Width;
                float yBitmap = 0;

                canvas.DrawBitmap(bitmap, pictureFrame);
            }
        }
        private void OnTouchEffectAction(object sender, TouchTracking.TouchActionEventArgs args)
        {
            Point   pt    = args.Location;
            SKPoint point =
                new SKPoint((float)(view.CanvasSize.Width * pt.X / view.Width),
                            (float)(view.CanvasSize.Height * pt.Y / view.Height));


            switch (args.Type)
            {
            case TouchActionType.Pressed:
                if (!touchDictionary.ContainsKey(args.Id))
                {
                    touchDictionary.Add(args.Id, point);
                }
                //SetPixelsValue(args, view);

                break;

            case TouchActionType.Moved:
                if (touchDictionary.ContainsKey(args.Id))
                {
                    if (touchDictionary.Count == 1)
                    {
                        long[] keys = new long[touchDictionary.Count];
                        touchDictionary.Keys.CopyTo(keys, 0);

                        // Find index of non-moving (pivot) finger
                        int pivotIndex = (keys[0] == args.Id) ? 1 : 0;

                        // Get the three points involved in the transform
                        // SKPoint pivotPoint = touchDictionary[keys[pivotIndex]];
                        SKPoint prevPoint = touchDictionary[args.Id];
                        SKPoint newPoint  = point;

                        SKPoint delta = newPoint - prevPoint;      // new_p = newPoint; old_p = prevPoint;

                        SKMatrix.PostConcat(ref matrix, SKMatrix.MakeTranslation(delta.X, delta.Y));
                        touchDictionary[args.Id] = point;
                    }
                    else if (touchDictionary.Count >= 2)
                    {
                        // Copy two dictionary keys into array
                        long[] keys = new long[touchDictionary.Count];
                        touchDictionary.Keys.CopyTo(keys, 0);

                        int pivotIndex = (keys[0] == args.Id) ? 1 : 0;

                        SKPoint pivotPoint = touchDictionary[keys[pivotIndex]];
                        SKPoint prevPoint  = touchDictionary[args.Id];
                        SKPoint newPoint   = point;

                        double distance    = Math.Sqrt(Math.Pow(Math.Abs(pivotPoint.X - newPoint.X), 2) + Math.Pow(Math.Abs(pivotPoint.Y - newPoint.Y), 2));
                        double oldDistance = Math.Sqrt(Math.Pow(Math.Abs(pivotPoint.X - prevPoint.X), 2) + Math.Pow(Math.Abs(pivotPoint.Y - prevPoint.Y), 2));

                        double differentDistance = distance / oldDistance;

                        SKPoint centerPoint = new SKPoint()
                        {
                            X = (newPoint.X + pivotPoint.X) / 2,
                            Y = (newPoint.Y + pivotPoint.Y) / 2
                        };


                        SKPoint oldCenterPoint = new SKPoint()
                        {
                            X = (prevPoint.X + pivotPoint.X) / 2,
                            Y = (prevPoint.Y + pivotPoint.Y) / 2
                        };


                        SKMatrix translationMatrix = SKMatrix.CreateTranslation((centerPoint.X - oldCenterPoint.X) /*/matrix.ScaleX*/, (centerPoint.Y - oldCenterPoint.Y) /*/ matrix.ScaleX*/);
                        SKMatrix scaleMatrix       = SKMatrix.Identity;

                        if (!(matrix.ScaleX > 8 && differentDistance > 1))
                        {
                            scaleMatrix = SKMatrix.CreateScale((float)differentDistance, (float)differentDistance, centerPoint.X, centerPoint.Y /* pivotPoint.X, pivotPoint.Y*/);
                        }

                        SKMatrix.PostConcat(ref matrix, scaleMatrix);       // NEW "PostContact() DOES NOT WORKING CORRECTLY!!!"
                        SKMatrix.PostConcat(ref matrix, translationMatrix);


                        touchDictionary[args.Id] = point;
                    }
                }
                break;

            case TouchActionType.Released:
            case TouchActionType.Cancelled:

                if (touchDictionary.ContainsKey(args.Id))
                {
                    touchDictionary.Remove(args.Id);
                }

                break;
            }

            this.view.InvalidateSurface();
        }
Beispiel #12
0
        public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException("Folder");
            }

            if (Path == null || !Enabled || !Children.Any(c => c.Enabled))
            {
                return;
            }

            // No need to render if at the end of the timeline
            if (TimelinePosition > TimelineLength)
            {
                return;
            }

            if (_folderBitmap == null)
            {
                _folderBitmap = new SKBitmap(new SKImageInfo((int)Path.Bounds.Width, (int)Path.Bounds.Height));
            }
            else if (_folderBitmap.Info.Width != (int)Path.Bounds.Width || _folderBitmap.Info.Height != (int)Path.Bounds.Height)
            {
                _folderBitmap.Dispose();
                _folderBitmap = new SKBitmap(new SKImageInfo((int)Path.Bounds.Width, (int)Path.Bounds.Height));
            }

            using SKPath folderPath     = new SKPath(Path);
            using SKCanvas folderCanvas = new SKCanvas(_folderBitmap);
            using SKPaint folderPaint   = new SKPaint();
            folderCanvas.Clear();

            folderPath.Transform(SKMatrix.MakeTranslation(folderPath.Bounds.Left * -1, folderPath.Bounds.Top * -1));

            SKPoint targetLocation = Path.Bounds.Location;

            if (Parent is Folder parentFolder)
            {
                targetLocation -= parentFolder.Path.Bounds.Location;
            }

            canvas.Save();

            using SKPath clipPath = new SKPath(folderPath);
            clipPath.Transform(SKMatrix.MakeTranslation(targetLocation.X, targetLocation.Y));
            canvas.ClipPath(clipPath);

            foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled))
            {
                baseLayerEffect.PreProcess(folderCanvas, _folderBitmap.Info, folderPath, folderPaint);
            }

            // No point rendering if the alpha was set to zero by one of the effects
            if (folderPaint.Color.Alpha == 0)
            {
                return;
            }

            // Iterate the children in reverse because the first layer must be rendered last to end up on top
            for (int index = Children.Count - 1; index > -1; index--)
            {
                folderCanvas.Save();
                ProfileElement profileElement = Children[index];
                profileElement.Render(deltaTime, folderCanvas, _folderBitmap.Info);
                folderCanvas.Restore();
            }

            // If required, apply the opacity override of the module to the root folder
            if (IsRootFolder && Profile.Module.OpacityOverride < 1)
            {
                double multiplier = Easings.SineEaseInOut(Profile.Module.OpacityOverride);
                folderPaint.Color = folderPaint.Color.WithAlpha((byte)(folderPaint.Color.Alpha * multiplier));
            }

            foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled))
            {
                baseLayerEffect.PostProcess(canvas, canvasInfo, folderPath, folderPaint);
            }
            canvas.DrawBitmap(_folderBitmap, targetLocation, folderPaint);

            canvas.Restore();
        }
        private void FolderCanvas_PaintSurface(object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs e)
        {
            SKImageInfo info    = e.Info;
            SKSurface   surface = e.Surface;
            SKCanvas    canvas  = surface.Canvas;

            canvas.Clear();


            float scaleFactor = 0.67f;
            float density     = scaleFactor * info.Size.Height / (float)this.Height;


            canvas.Save();

            using (SKPath backPath = SKPath.ParseSvgPathData(
                       "M87.909,9.917V4.02A4.032,4.032,0,0,0,83.889,0H23.72A4.032,4.032,0,0,0,19.7,4.02v5.9H13.338a4.529,4.529,0,0,0-3.822,4.02l.27,112.7a3.954,3.954,0,0,0,3.951,4.024H167.344a3.963,3.963,0,0,0,3.97-4.011l-.6-112.71a4.092,4.092,0,0,0-4.07-4.02Z"))
            {
                backPath.Transform(SKMatrix.MakeScale(density, density));
                backPath.GetTightBounds(out var backPathTightBounds);
                var translateXBackPath = info.Width * 0.5f - backPathTightBounds.MidX;
                var translateYbackPath = info.Height - backPathTightBounds.Bottom - 20f;
                canvas.Translate(translateXBackPath, translateYbackPath);
                fillPaint.Shader = SKShader.CreateLinearGradient(
                    new SKPoint(info.Width * 0.5f, 0),
                    new SKPoint(info.Width * 0.5f, info.Height),
                    new SKColor[] { SKColor.Parse(Color1), SKColor.Parse(Color2), SKColor.Parse(Color2) },
                    new float[] { 0, 0.37f, 1 },
                    SKShaderTileMode.Clamp
                    );
                canvas.DrawPath(backPath, fillPaint);
            }

            canvas.Restore();

            canvas.Save();
            using (SKPath backFilePath = SKPath.ParseSvgPathData("M174.079,150.908H29.155l-.4-114.144H174.481Z"))
            {
                backFilePath.Transform(SKMatrix.MakeScale(density, density));
                backFilePath.GetTightBounds(out var backFilePathTightBounds);
                var translateXBackFilePath = info.Width * 0.5f - backFilePathTightBounds.MidX;
                var translateYbackFilePath = info.Height - backFilePathTightBounds.Bottom - 20f;
                canvas.Translate(translateXBackFilePath, translateYbackFilePath);
                fillPaint.Shader = SKShader.CreateLinearGradient(
                    new SKPoint(info.Width * 0.5f, 0),
                    new SKPoint(info.Width * 0.5f, info.Height),
                    new SKColor[] { SKColor.Parse("#e6e6e6"), SKColor.Parse("#e8e8e8"), SKColor.Parse("#f0f0f0"), SKColor.Parse("#f2f2f2") },
                    new float[] { 0, 0.633f, 0.949f, 1 },
                    SKShaderTileMode.Clamp
                    );
                canvas.DrawPath(backFilePath, fillPaint);
            }
            canvas.Restore();

            canvas.Save();
            using (SKPath frontFilePath = SKPath.ParseSvgPathData("M170.491,158.681H25.567L22.753,49.764H173.3Z"))
            {
                frontFilePath.Transform(SKMatrix.MakeScale(density, density));
                frontFilePath.GetTightBounds(out var frontFilePathTightBounds);
                var translateXFrontFilePath = info.Width * 0.5f - frontFilePathTightBounds.MidX;
                var translateYFrontFilePath = info.Height - frontFilePathTightBounds.Bottom - 20f;
                canvas.Translate(translateXFrontFilePath, translateYFrontFilePath);
                fillPaint.Shader = SKShader.CreateLinearGradient(
                    new SKPoint(info.Width * 0.5f, 0),
                    new SKPoint(info.Width * 0.5f, info.Height),
                    new SKColor[] { SKColor.Parse("#cccccc"), SKColor.Parse("#cecece"), SKColor.Parse("#d6d6d6"), SKColor.Parse("#e3e3e3"), SKColor.Parse("#f6f6f6"), SKColor.Parse("#ffffff") },
                    new float[] { 0, 0.427f, 0.64f, 0.806f, 0.947f, 1 },
                    SKShaderTileMode.Clamp
                    );
                canvas.DrawPath(frontFilePath, fillPaint);
            }
            canvas.Restore();

            canvas.Save();
            using (SKPath frontPath = SKPath.ParseSvgPathData("M165.433,164.917a4.106,4.106,0,0,1-4.089,4.011H7.735a4.578,4.578,0,0,1-4.325-4.292L0,68.019A3.948,3.948,0,0,1,3.95,64H164.895a3.948,3.948,0,0,1,3.95,4.02Z"))
            {
                frontPath.Transform(SKMatrix.MakeScale(density, density));
                frontPath.GetTightBounds(out var frontPathTightBounds);

                fillPaint.Shader = SKShader.CreateLinearGradient(
                    new SKPoint(info.Width * 0.5f, 0),
                    new SKPoint(info.Width * 0.5f, info.Height),
                    new SKColor[] { SKColor.Parse(Color3), SKColor.Parse(Color4), SKColor.Parse(Color5), SKColor.Parse(Color6) },
                    new float[] { 0, 0.595f, 0.957f, 1 },
                    SKShaderTileMode.Clamp
                    );

                SKMatrix   matrix   = SKMatrix.MakeTranslation(-frontPathTightBounds.Right, -frontPathTightBounds.Bottom);
                SKMatrix44 matrix44 = SKMatrix44.CreateIdentity();
                matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(1, 0, 0, -FrontPathDegree));
                matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 1, 0, -0.5f * FrontPathDegree));
                matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 0, 1, 0));
                SKMatrix.PostConcat(ref matrix, matrix44.Matrix);
                SKMatrix.PostConcat(ref matrix, SKMatrix.MakeTranslation(frontPathTightBounds.Right, frontPathTightBounds.Bottom));
                canvas.SetMatrix(matrix);

                var translateXFrontPath = info.Width * 0.5f - frontPathTightBounds.MidX;
                var translateYFrontPath = info.Height - frontPathTightBounds.Bottom - 20f;
                canvas.Translate(translateXFrontPath, translateYFrontPath);
                canvas.DrawPath(frontPath, fillPaint);
            }
            canvas.Restore();
        }
Beispiel #14
0
        public void DrawUse(SvgUse svgUse, bool ignoreDisplay)
        {
            if (!CanDraw(svgUse, ignoreDisplay))
            {
                return;
            }

            var svgVisualElement = SkiaUtil.GetReference <SvgVisualElement>(svgUse, svgUse.ReferencedElement);

            if (svgVisualElement == null || SkiaUtil.HasRecursiveReference(svgUse))
            {
                return;
            }

            float x = svgUse.X.ToDeviceValue(null, UnitRenderingType.Horizontal, svgUse);
            float y = svgUse.Y.ToDeviceValue(null, UnitRenderingType.Vertical, svgUse);
            var   skMatrixTranslateXY = SKMatrix.MakeTranslation(x, y);
            var   skMatrix            = SkiaUtil.GetSKMatrix(svgUse.Transforms);

            SKMatrix.PreConcat(ref skMatrix, ref skMatrixTranslateXY);

            var ew = svgUse.Width.ToDeviceValue(null, UnitRenderingType.Horizontal, svgUse);
            var eh = svgUse.Height.ToDeviceValue(null, UnitRenderingType.Vertical, svgUse);

            if (ew > 0 && eh > 0)
            {
                var _attributes = svgVisualElement.GetType().GetField("_attributes", BindingFlags.NonPublic | BindingFlags.Instance);
                if (_attributes != null)
                {
                    var attributes = _attributes.GetValue(svgVisualElement) as SvgAttributeCollection;
                    if (attributes != null)
                    {
                        var viewBox = attributes.GetAttribute <SvgViewBox>("viewBox");
                        if (viewBox != SvgViewBox.Empty && Math.Abs(ew - viewBox.Width) > float.Epsilon && Math.Abs(eh - viewBox.Height) > float.Epsilon)
                        {
                            var sw = ew / viewBox.Width;
                            var sh = eh / viewBox.Height;

                            var skMatrixTranslateSWSH = SKMatrix.MakeTranslation(sw, sh);
                            SKMatrix.PreConcat(ref skMatrix, ref skMatrixTranslateSWSH);
                        }
                    }
                }
            }

            var originalParent = svgUse.Parent;
            var useParent      = svgUse.GetType().GetField("_parent", BindingFlags.NonPublic | BindingFlags.Instance);

            if (useParent != null)
            {
                useParent.SetValue(svgVisualElement, svgUse);
            }

            svgVisualElement.InvalidateChildPaths();

            _skCanvas.Save();

            SetTransform(skMatrix);
            SetClipPath(svgUse, _disposable);

            var skPaintOpacity = SetOpacity(svgUse, _disposable);

            var skPaintFilter = SetFilter(svgUse, _disposable);

            if (svgVisualElement is SvgSymbol svgSymbol)
            {
                DrawSymbol(svgSymbol, ignoreDisplay);
            }
            else
            {
                Draw(svgVisualElement, ignoreDisplay);
            }

            if (skPaintFilter != null)
            {
                _skCanvas.Restore();
            }

            if (skPaintOpacity != null)
            {
                _skCanvas.Restore();
            }

            _skCanvas.Restore();

            if (useParent != null)
            {
                useParent.SetValue(svgVisualElement, originalParent);
            }
        }
Beispiel #15
0
        public UseDrawable(SvgUse svgUse, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None)
            : base(svgUse, root, parent)
        {
            IgnoreAttributes = ignoreAttributes;
            IsDrawable       = CanDraw(svgUse, IgnoreAttributes) && HasFeatures(svgUse, IgnoreAttributes);

            if (!IsDrawable)
            {
                return;
            }

            if (SvgExtensions.HasRecursiveReference(svgUse, (e) => e.ReferencedElement, new HashSet <Uri>()))
            {
                IsDrawable = false;
                return;
            }

            var svgReferencedElement = SvgExtensions.GetReference <SvgElement>(svgUse, svgUse.ReferencedElement);

            if (svgReferencedElement == null)
            {
                IsDrawable = false;
                return;
            }

            float x      = svgUse.X.ToDeviceValue(UnitRenderingType.Horizontal, svgUse, skOwnerBounds);
            float y      = svgUse.Y.ToDeviceValue(UnitRenderingType.Vertical, svgUse, skOwnerBounds);
            float width  = svgUse.Width.ToDeviceValue(UnitRenderingType.Horizontal, svgUse, skOwnerBounds);
            float height = svgUse.Height.ToDeviceValue(UnitRenderingType.Vertical, svgUse, skOwnerBounds);

            if (width <= 0f)
            {
                width = new SvgUnit(SvgUnitType.Percentage, 100f).ToDeviceValue(UnitRenderingType.Horizontal, svgUse, skOwnerBounds);
            }

            if (height <= 0f)
            {
                height = new SvgUnit(SvgUnitType.Percentage, 100f).ToDeviceValue(UnitRenderingType.Vertical, svgUse, skOwnerBounds);
            }

            var originalReferencedElementParent = svgReferencedElement.Parent;
            var referencedElementParent         = default(FieldInfo);

            try
            {
                referencedElementParent = svgReferencedElement.GetType().GetField("_parent", BindingFlags.NonPublic | BindingFlags.Instance);
                if (referencedElementParent != null)
                {
                    referencedElementParent.SetValue(svgReferencedElement, svgUse);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                Debug.WriteLine(ex.StackTrace);
            }

            svgReferencedElement.InvalidateChildPaths();

            if (svgReferencedElement is SvgSymbol svgSymbol)
            {
                ReferencedDrawable = new SymbolDrawable(svgSymbol, x, y, width, height, skOwnerBounds, root, this, ignoreAttributes);
                _disposable.Add(ReferencedDrawable);
            }
            else
            {
                var drawable = DrawableFactory.Create(svgReferencedElement, skOwnerBounds, root, this, ignoreAttributes);
                if (drawable != null)
                {
                    ReferencedDrawable = drawable;
                    _disposable.Add(ReferencedDrawable);
                }
                else
                {
                    IsDrawable = false;
                    return;
                }
            }

            IsAntialias = SvgPaintingExtensions.IsAntialias(svgUse);

            TransformedBounds = ReferencedDrawable.TransformedBounds;

            Transform = SvgTransformsExtensions.ToSKMatrix(svgUse.Transforms);
            if (!(svgReferencedElement is SvgSymbol))
            {
                var skMatrixTranslateXY = SKMatrix.MakeTranslation(x, y);
                SKMatrix.PreConcat(ref Transform, ref skMatrixTranslateXY);
            }

            Fill   = null;
            Stroke = null;

            // TODO: Transform _skBounds using _skMatrix.
            SKMatrix.MapRect(ref Transform, out TransformedBounds, ref TransformedBounds);

            try
            {
                if (referencedElementParent != null)
                {
                    referencedElementParent.SetValue(svgReferencedElement, originalReferencedElementParent);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                Debug.WriteLine(ex.StackTrace);
            }
        }
Beispiel #16
0
        private SKMatrix ReadTransform(string raw)
        {
            var t = SKMatrix.MakeIdentity();

            if (string.IsNullOrWhiteSpace(raw))
            {
                return(t);
            }

            var calls = raw.Trim().Split(new[] { ')' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var c in calls)
            {
                var args = c.Split(new[] { '(', ',', ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                var nt   = SKMatrix.MakeIdentity();
                switch (args[0])
                {
                case "matrix":
                    if (args.Length == 7)
                    {
                        nt.Values = new float[]
                        {
                            ReadNumber(args[1]), ReadNumber(args[3]), ReadNumber(args[5]),
                            ReadNumber(args[2]), ReadNumber(args[4]), ReadNumber(args[6]),
                            0, 0, 1
                        };
                    }
                    else
                    {
                        LogOrThrow($"Matrices are expected to have 6 elements, this one has {args.Length - 1}");
                    }
                    break;

                case "translate":
                    if (args.Length >= 3)
                    {
                        nt = SKMatrix.MakeTranslation(ReadNumber(args[1]), ReadNumber(args[2]));
                    }
                    else if (args.Length >= 2)
                    {
                        nt = SKMatrix.MakeTranslation(ReadNumber(args[1]), 0);
                    }
                    break;

                case "scale":
                    if (args.Length >= 3)
                    {
                        nt = SKMatrix.MakeScale(ReadNumber(args[1]), ReadNumber(args[2]));
                    }
                    else if (args.Length >= 2)
                    {
                        var sx = ReadNumber(args[1]);
                        nt = SKMatrix.MakeScale(sx, sx);
                    }
                    break;

                case "rotate":
                    var a = ReadNumber(args[1]);
                    if (args.Length >= 4)
                    {
                        var x  = ReadNumber(args[2]);
                        var y  = ReadNumber(args[3]);
                        var t1 = SKMatrix.MakeTranslation(x, y);
                        var t2 = SKMatrix.MakeRotationDegrees(a);
                        var t3 = SKMatrix.MakeTranslation(-x, -y);
                        SKMatrix.Concat(ref nt, ref t1, ref t2);
                        SKMatrix.Concat(ref nt, ref nt, ref t3);
                    }
                    else
                    {
                        nt = SKMatrix.MakeRotationDegrees(a);
                    }
                    break;

                default:
                    LogOrThrow($"Can't transform {args[0]}");
                    break;
                }
                SKMatrix.Concat(ref t, ref t, ref nt);
            }

            return(t);
        }
Beispiel #17
0
        private void ReadElement(XElement e, SKCanvas canvas, SKPaint stroke, SKPaint fill)
        {
            // transform matrix
            var transform = ReadTransform(e.Attribute("transform")?.Value ?? string.Empty);

            canvas.Save();
            canvas.Concat(ref transform);

            // SVG element
            var elementName = e.Name.LocalName;
            var isGroup     = elementName == "g";

            // read style
            var style = ReadPaints(e, ref stroke, ref fill, isGroup);

            // parse elements
            switch (elementName)
            {
            case "text":
                if (stroke != null || fill != null)
                {
                    ReadText(e, canvas, stroke?.Clone(), fill?.Clone());
                }
                break;

            case "rect":
                if (stroke != null || fill != null)
                {
                    var x      = ReadNumber(e.Attribute("x"));
                    var y      = ReadNumber(e.Attribute("y"));
                    var width  = ReadNumber(e.Attribute("width"));
                    var height = ReadNumber(e.Attribute("height"));
                    var rx     = ReadNumber(e.Attribute("rx"));
                    var ry     = ReadNumber(e.Attribute("ry"));
                    var rect   = SKRect.Create(x, y, width, height);
                    if (rx > 0 || ry > 0)
                    {
                        if (fill != null)
                        {
                            canvas.DrawRoundRect(rect, rx, ry, fill);
                        }
                        if (stroke != null)
                        {
                            canvas.DrawRoundRect(rect, rx, ry, stroke);
                        }
                    }
                    else
                    {
                        if (fill != null)
                        {
                            canvas.DrawRect(rect, fill);
                        }
                        if (stroke != null)
                        {
                            canvas.DrawRect(rect, stroke);
                        }
                    }
                }
                break;

            case "ellipse":
                if (stroke != null || fill != null)
                {
                    var cx = ReadNumber(e.Attribute("cx"));
                    var cy = ReadNumber(e.Attribute("cy"));
                    var rx = ReadNumber(e.Attribute("rx"));
                    var ry = ReadNumber(e.Attribute("ry"));
                    if (fill != null)
                    {
                        canvas.DrawOval(cx, cy, rx, ry, fill);
                    }
                    if (stroke != null)
                    {
                        canvas.DrawOval(cx, cy, rx, ry, stroke);
                    }
                }
                break;

            case "circle":
                if (stroke != null || fill != null)
                {
                    var cx = ReadNumber(e.Attribute("cx"));
                    var cy = ReadNumber(e.Attribute("cy"));
                    var rr = ReadNumber(e.Attribute("r"));
                    if (fill != null)
                    {
                        canvas.DrawCircle(cx, cy, rr, fill);
                    }
                    if (stroke != null)
                    {
                        canvas.DrawCircle(cx, cy, rr, stroke);
                    }
                }
                break;

            case "path":
                if (stroke != null || fill != null)
                {
                    var d = e.Attribute("d")?.Value;
                    if (!string.IsNullOrWhiteSpace(d))
                    {
                        var path = SKPath.ParseSvgPathData(d);
                        if (fill != null)
                        {
                            canvas.DrawPath(path, fill);
                        }
                        if (stroke != null)
                        {
                            canvas.DrawPath(path, stroke);
                        }
                    }
                }
                break;

            case "polygon":
            case "polyline":
                if (stroke != null || fill != null)
                {
                    var close = elementName == "polygon";
                    var p     = e.Attribute("points")?.Value;
                    if (!string.IsNullOrWhiteSpace(p))
                    {
                        var path = ReadPolyPath(p, close);
                        if (fill != null)
                        {
                            canvas.DrawPath(path, fill);
                        }
                        if (stroke != null)
                        {
                            canvas.DrawPath(path, stroke);
                        }
                    }
                }
                break;

            case "g":
                if (e.HasElements)
                {
                    // get current group opacity
                    float groupOpacity = ReadOpacity(style);
                    if (groupOpacity != 1.0f)
                    {
                        var opacity      = (byte)(255 * groupOpacity);
                        var opacityPaint = new SKPaint {
                            Color = SKColors.Black.WithAlpha(opacity)
                        };

                        // apply the opacity
                        canvas.SaveLayer(opacityPaint);
                    }

                    foreach (var gElement in e.Elements())
                    {
                        ReadElement(gElement, canvas, stroke?.Clone(), fill?.Clone());
                    }

                    // restore state
                    if (groupOpacity != 1.0f)
                    {
                        canvas.Restore();
                    }
                }
                break;

            case "use":
                if (e.HasAttributes)
                {
                    var href = ReadHref(e);
                    if (href != null)
                    {
                        // TODO: copy/process other attributes

                        var x            = ReadNumber(e.Attribute("x"));
                        var y            = ReadNumber(e.Attribute("y"));
                        var useTransform = SKMatrix.MakeTranslation(x, y);

                        canvas.Save();
                        canvas.Concat(ref useTransform);

                        ReadElement(href, canvas, stroke?.Clone(), fill?.Clone());

                        canvas.Restore();
                    }
                }
                break;

            case "line":
                if (stroke != null)
                {
                    var x1 = ReadNumber(e.Attribute("x1"));
                    var x2 = ReadNumber(e.Attribute("x2"));
                    var y1 = ReadNumber(e.Attribute("y1"));
                    var y2 = ReadNumber(e.Attribute("y2"));
                    canvas.DrawLine(x1, y1, x2, y2, stroke);
                }
                break;

            case "switch":
                if (e.HasElements)
                {
                    foreach (var ee in e.Elements())
                    {
                        var requiredFeatures   = ee.Attribute("requiredFeatures");
                        var requiredExtensions = ee.Attribute("requiredExtensions");
                        var systemLanguage     = ee.Attribute("systemLanguage");

                        // TODO: evaluate requiredFeatures, requiredExtensions and systemLanguage
                        var isVisible =
                            requiredFeatures == null &&
                            requiredExtensions == null &&
                            systemLanguage == null;

                        if (isVisible)
                        {
                            ReadElement(ee, canvas, stroke?.Clone(), fill?.Clone());
                        }
                    }
                }
                break;

            case "defs":
            case "title":
            case "desc":
            case "description":
                // already read earlier
                break;

            default:
                LogOrThrow($"SVG element '{elementName}' is not supported");
                break;
            }

            // restore matrix
            canvas.Restore();
        }
        public static SKMatrix ToSKMatrix(this SvgTransformCollection svgTransformCollection)
        {
            var skMatrixTotal = SKMatrix.MakeIdentity();

            if (svgTransformCollection == null)
            {
                return(skMatrixTotal);
            }

            foreach (var svgTransform in svgTransformCollection)
            {
                switch (svgTransform)
                {
                case SvgMatrix svgMatrix:
                {
                    var skMatrix = svgMatrix.ToSKMatrix();
                    skMatrixTotal = skMatrixTotal.PreConcat(skMatrix);
                }
                break;

                case SvgRotate svgRotate:
                {
                    var skMatrixRotate = SKMatrix.MakeRotationDegrees(svgRotate.Angle, svgRotate.CenterX, svgRotate.CenterY);
                    skMatrixTotal = skMatrixTotal.PreConcat(skMatrixRotate);
                }
                break;

                case SvgScale svgScale:
                {
                    var skMatrixScale = SKMatrix.MakeScale(svgScale.X, svgScale.Y);
                    skMatrixTotal = skMatrixTotal.PreConcat(skMatrixScale);
                }
                break;

                case SvgShear svgShear:
                {
                    // Not in the svg specification.
                }
                break;

                case SvgSkew svgSkew:
                {
                    float sx           = (float)Math.Tan(Math.PI * svgSkew.AngleX / 180);
                    float sy           = (float)Math.Tan(Math.PI * svgSkew.AngleY / 180);
                    var   skMatrixSkew = SKMatrix.MakeSkew(sx, sy);
                    skMatrixTotal = skMatrixTotal.PreConcat(skMatrixSkew);
                }
                break;

                case SvgTranslate svgTranslate:
                {
                    var skMatrixTranslate = SKMatrix.MakeTranslation(svgTranslate.X, svgTranslate.Y);
                    skMatrixTotal = skMatrixTotal.PreConcat(skMatrixTranslate);
                }
                break;

                default:
                    break;
                }
            }

            return(skMatrixTotal);
        }
Beispiel #19
0
        public MaskDrawable(SvgMask svgMask, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None)
            : base(svgMask, root, parent)
        {
            IgnoreAttributes = ignoreAttributes;
            IsDrawable       = true;

            if (!IsDrawable)
            {
                return;
            }
            var   maskUnits        = svgMask.MaskUnits;
            var   maskContentUnits = svgMask.MaskContentUnits;
            var   xUnit            = svgMask.X;
            var   yUnit            = svgMask.Y;
            var   widthUnit        = svgMask.Width;
            var   heightUnit       = svgMask.Height;
            float x      = xUnit.ToDeviceValue(UnitRenderingType.Horizontal, svgMask, skOwnerBounds);
            float y      = yUnit.ToDeviceValue(UnitRenderingType.Vertical, svgMask, skOwnerBounds);
            float width  = widthUnit.ToDeviceValue(UnitRenderingType.Horizontal, svgMask, skOwnerBounds);
            float height = heightUnit.ToDeviceValue(UnitRenderingType.Vertical, svgMask, skOwnerBounds);

            if (width <= 0 || height <= 0)
            {
                IsDrawable = false;
                return;
            }

            if (maskUnits == SvgCoordinateUnits.ObjectBoundingBox)
            {
                if (xUnit.Type != SvgUnitType.Percentage)
                {
                    x *= skOwnerBounds.Width;
                }

                if (yUnit.Type != SvgUnitType.Percentage)
                {
                    y *= skOwnerBounds.Height;
                }

                if (widthUnit.Type != SvgUnitType.Percentage)
                {
                    width *= skOwnerBounds.Width;
                }

                if (heightUnit.Type != SvgUnitType.Percentage)
                {
                    height *= skOwnerBounds.Height;
                }

                x += skOwnerBounds.Left;
                y += skOwnerBounds.Top;
            }

            SKRect skRectTransformed = SKRect.Create(x, y, width, height);

            var skMatrix = SKMatrix.MakeIdentity();

            if (maskContentUnits == SvgCoordinateUnits.ObjectBoundingBox)
            {
                var skBoundsTranslateTransform = SKMatrix.MakeTranslation(skOwnerBounds.Left, skOwnerBounds.Top);
                SKMatrix.PreConcat(ref skMatrix, ref skBoundsTranslateTransform);

                var skBoundsScaleTransform = SKMatrix.MakeScale(skOwnerBounds.Width, skOwnerBounds.Height);
                SKMatrix.PreConcat(ref skMatrix, ref skBoundsScaleTransform);
            }

            CreateChildren(svgMask, skOwnerBounds, root, this, ignoreAttributes);

            Overflow = skRectTransformed;

            IsAntialias = SvgPaintingExtensions.IsAntialias(svgMask);

            TransformedBounds = skRectTransformed;

            Transform = skMatrix;

            Fill   = null;
            Stroke = null;

            // TODO: Transform _skBounds using _skMatrix.
            SKMatrix.MapRect(ref Transform, out TransformedBounds, ref TransformedBounds);
        }