Example #1
0
        public async Task <DataResolverResult> Resolve(string identifier, TaskParameter parameters, CancellationToken token)
        {
            ImageSource source = parameters.Source;

            if (!string.IsNullOrWhiteSpace(parameters.LoadingPlaceholderPath) && parameters.LoadingPlaceholderPath == identifier)
            {
                source = parameters.LoadingPlaceholderSource;
            }
            else if (!string.IsNullOrWhiteSpace(parameters.ErrorPlaceholderPath) && parameters.ErrorPlaceholderPath == identifier)
            {
                source = parameters.ErrorPlaceholderSource;
            }

            var resolvedData = await(Configuration.DataResolverFactory ?? new DataResolverFactory())
                               .GetResolver(identifier, source, parameters, Configuration)
                               .Resolve(identifier, parameters, token).ConfigureAwait(false);

            if (resolvedData?.Stream == null)
            {
                throw new FileNotFoundException(identifier);
            }

            var svg = new SKSvg()
            {
                ThrowOnUnsupportedElement = false,
            };
            SKPicture picture;

            if (ReplaceStringMap == null || ReplaceStringMap.Count == 0)
            {
                using (var svgStream = resolvedData.Stream)
                {
                    picture = svg.Load(svgStream);
                }
            }
            else
            {
                using (var svgStream = resolvedData.Stream)
                    using (var reader = new StreamReader(svgStream))
                    {
                        var inputString = await reader.ReadToEndAsync();

                        foreach (var map in ReplaceStringMap
                                 .Where(v => v.Key.StartsWith("regex:")))
                        {
                            inputString = Regex.Replace(inputString, map.Key.Substring(6), map.Value);
                        }

                        var builder = new StringBuilder(inputString);

                        foreach (var map in ReplaceStringMap
                                 .Where(v => !v.Key.StartsWith("regex:", StringComparison.OrdinalIgnoreCase)))
                        {
                            builder.Replace(map.Key, map.Value);
                        }

                        using (var svgFinalStream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString())))
                        {
                            picture = svg.Load(svgFinalStream);
                        }
                    }
            }

            double sizeX = 0;
            double sizeY = 0;

            if (VectorWidth <= 0 && VectorHeight <= 0)
            {
                if (picture.CullRect.Width > 0)
                {
                    sizeX = picture.CullRect.Width;
                }
                else
                {
                    sizeX = 300;
                }

                if (picture.CullRect.Height > 0)
                {
                    sizeY = picture.CullRect.Height;
                }
                else
                {
                    sizeY = 300;
                }
            }
            else if (VectorWidth > 0 && VectorHeight > 0)
            {
                sizeX = VectorWidth;
                sizeY = VectorHeight;
            }
            else if (VectorWidth > 0)
            {
                sizeX = VectorWidth;
                sizeY = (VectorWidth / picture.CullRect.Width) * picture.CullRect.Height;
            }
            else
            {
                sizeX = (VectorHeight / picture.CullRect.Height) * picture.CullRect.Width;
                sizeY = VectorHeight;
            }

            if (UseDipUnits)
            {
                sizeX = sizeX.DpToPixels();
                sizeY = sizeY.DpToPixels();
            }

            resolvedData.ImageInformation.SetType(ImageInformation.ImageType.SVG);

            using (var bitmap = new SKBitmap(new SKImageInfo((int)sizeX, (int)sizeY)))
                using (var canvas = new SKCanvas(bitmap))
                    using (var paint = new SKPaint())
                    {
                        canvas.Clear(SKColors.Transparent);
                        float scaleX = (float)sizeX / picture.CullRect.Width;
                        float scaleY = (float)sizeY / picture.CullRect.Height;
                        var   matrix = SKMatrix.MakeScale(scaleX, scaleY);
                        canvas.DrawPicture(picture, ref matrix, paint);
                        canvas.Flush();
#if __IOS__
                        var     info = bitmap.Info;
                        CGImage cgImage;
                        IntPtr  size;
                        using (var provider = new CGDataProvider(bitmap.GetPixels(out size), size.ToInt32()))
                            using (var colorSpace = CGColorSpace.CreateDeviceRGB())
                                using (cgImage = new CGImage(info.Width, info.Height, 8, info.BitsPerPixel, info.RowBytes,
                                                             colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big,
                                                             provider, null, false, CGColorRenderingIntent.Default))
                                {
                                    IDecodedImage <object> container = new DecodedImage <object>()
                                    {
                                        Image = new UIImage(cgImage),
                                    };
                                    return(new DataResolverResult(container, resolvedData.LoadingResult, resolvedData.ImageInformation));
                                }
#elif __MACOS__
                        var     info = bitmap.Info;
                        CGImage cgImage;
                        IntPtr  size;
                        using (var provider = new CGDataProvider(bitmap.GetPixels(out size), size.ToInt32()))
                            using (var colorSpace = CGColorSpace.CreateDeviceRGB())
                                using (cgImage = new CGImage(info.Width, info.Height, 8, info.BitsPerPixel, info.RowBytes,
                                                             colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big,
                                                             provider, null, false, CGColorRenderingIntent.Default))
                                {
                                    IDecodedImage <object> container = new DecodedImage <object>()
                                    {
                                        Image = new NSImage(cgImage, CGSize.Empty),
                                    };
                                    return(new DataResolverResult(container, resolvedData.LoadingResult, resolvedData.ImageInformation));
                                }
#elif __ANDROID__
                        using (var skiaPixmap = bitmap.PeekPixels())
                        {
                            var info = skiaPixmap.Info;

                            // destination values
                            var config  = Bitmap.Config.Argb8888;
                            var dstInfo = new SKImageInfo(info.Width, info.Height);

                            // try keep the pixel format if we can
                            switch (info.ColorType)
                            {
                            case SKColorType.Alpha8:
                                config            = Bitmap.Config.Alpha8;
                                dstInfo.ColorType = SKColorType.Alpha8;
                                break;

                            case SKColorType.Rgb565:
                                config            = Bitmap.Config.Rgb565;
                                dstInfo.ColorType = SKColorType.Rgb565;
                                dstInfo.AlphaType = SKAlphaType.Opaque;
                                break;

                            case SKColorType.Argb4444:
                                config            = Bitmap.Config.Argb4444;
                                dstInfo.ColorType = SKColorType.Argb4444;
                                break;
                            }

                            // destination bitmap
                            var bmp = Bitmap.CreateBitmap(info.Width, info.Height, config);
                            var ptr = bmp.LockPixels();

                            // copy
                            var success = skiaPixmap.ReadPixels(dstInfo, ptr, dstInfo.RowBytes);

                            // confirm
                            bmp.UnlockPixels();
                            if (!success)
                            {
                                bmp.Recycle();
                                bmp.Dispose();
                                bmp = null;
                            }

                            IDecodedImage <object> container = new DecodedImage <object>()
                            {
                                Image = bmp,
                            };
                            return(new DataResolverResult(container, resolvedData.LoadingResult, resolvedData.ImageInformation));
                        }
#elif __WINDOWS__
                        if (parameters.Transformations == null || parameters.Transformations.Count == 0)
                        {
                            WriteableBitmap writeableBitmap = null;

                            await Configuration.MainThreadDispatcher.PostAsync(async() =>
                            {
                                using (var skiaImage = SKImage.FromPixels(bitmap.PeekPixels()))
                                {
                                    var info        = new SKImageInfo(skiaImage.Width, skiaImage.Height);
                                    writeableBitmap = new WriteableBitmap(info.Width, info.Height);

                                    var buffer = writeableBitmap.PixelBuffer as IBufferByteAccess;
                                    if (buffer == null)
                                    {
                                        throw new InvalidCastException("Unable to convert WriteableBitmap.PixelBuffer to IBufferByteAccess.");
                                    }

                                    IntPtr ptr;
                                    var hr = buffer.Buffer(out ptr);
                                    if (hr < 0)
                                    {
                                        throw new InvalidCastException("Unable to retrieve pixel address from WriteableBitmap.PixelBuffer.");
                                    }

                                    using (var pixmap = new SKPixmap(info, ptr))
                                    {
                                        skiaImage.ReadPixels(pixmap, 0, 0);
                                    }
                                    writeableBitmap.Invalidate();
                                }
                            });

                            IDecodedImage <object> container = new DecodedImage <object>()
                            {
                                Image = writeableBitmap,
                            };
                            return(new DataResolverResult(container, resolvedData.LoadingResult, resolvedData.ImageInformation));
                        }
#endif
                        lock (_encodingLock)
                        {
                            using (var image = SKImage.FromBitmap(bitmap))
                                //using (var data = image.Encode(SKImageEncodeFormat.Png, 100))  //TODO disabled because of https://github.com/mono/SkiaSharp/issues/285
                                using (var data = image.Encode())
                                {
                                    var stream = new MemoryStream();
                                    data.SaveTo(stream);
                                    stream.Position = 0;
                                    return(new DataResolverResult(stream, resolvedData.LoadingResult, resolvedData.ImageInformation));
                                }
                        }
                    }
        }
        public async Task <DataResolverResult> Resolve(string identifier, TaskParameter parameters, CancellationToken token)
        {
            var source = parameters.Source;

            if (!string.IsNullOrWhiteSpace(parameters.LoadingPlaceholderPath) && parameters.LoadingPlaceholderPath == identifier)
            {
                source = parameters.LoadingPlaceholderSource;
            }
            else if (!string.IsNullOrWhiteSpace(parameters.ErrorPlaceholderPath) && parameters.ErrorPlaceholderPath == identifier)
            {
                source = parameters.ErrorPlaceholderSource;
            }

            var resolvedData = await(Configuration.DataResolverFactory ?? new DataResolverFactory())
                               .GetResolver(identifier, source, parameters, Configuration)
                               .Resolve(identifier, parameters, token).ConfigureAwait(false);

            if (resolvedData?.Stream == null)
            {
                throw new FileNotFoundException(identifier);
            }

            var svg = new SKSvg()
            {
                ThrowOnUnsupportedElement = false,
            };
            SKPicture picture;

            if (ReplaceStringMap == null || ReplaceStringMap.Count == 0)
            {
                using (var svgStream = resolvedData.Stream)
                {
                    picture = svg.Load(svgStream);
                }
            }
            else
            {
                using (var svgStream = resolvedData.Stream)
                    using (var reader = new StreamReader(svgStream))
                    {
                        var inputString = await reader.ReadToEndAsync();

                        foreach (var map in ReplaceStringMap
                                 .Where(v => v.Key.StartsWith("regex:", StringComparison.OrdinalIgnoreCase)))
                        {
                            inputString = Regex.Replace(inputString, map.Key.Substring(6), map.Value);
                        }

                        var builder = new StringBuilder(inputString);

                        foreach (var map in ReplaceStringMap
                                 .Where(v => !v.Key.StartsWith("regex:", StringComparison.OrdinalIgnoreCase)))
                        {
                            builder.Replace(map.Key, map.Value);
                        }

                        using (var svgFinalStream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString())))
                        {
                            picture = svg.Load(svgFinalStream);
                        }
                    }
            }

            double sizeX = VectorWidth;
            double sizeY = VectorHeight;

            if (UseDipUnits)
            {
                sizeX = VectorWidth.DpToPixels();
                sizeY = VectorHeight.DpToPixels();
            }

            if (sizeX <= 0 && sizeY <= 0)
            {
                if (picture.CullRect.Width > 0)
                {
                    sizeX = picture.CullRect.Width;
                }
                else
                {
                    sizeX = 400;
                }

                if (picture.CullRect.Height > 0)
                {
                    sizeY = picture.CullRect.Height;
                }
                else
                {
                    sizeY = 400;
                }
            }
            else if (sizeX > 0 && sizeY <= 0)
            {
                sizeY = (int)(sizeX / picture.CullRect.Width * picture.CullRect.Height);
            }
            else if (sizeX <= 0 && sizeY > 0)
            {
                sizeX = (int)(sizeY / picture.CullRect.Height * picture.CullRect.Width);
            }

            resolvedData.ImageInformation.SetType(ImageInformation.ImageType.SVG);

            using (var bitmap = new SKBitmap(new SKImageInfo((int)sizeX, (int)sizeY)))
                using (var canvas = new SKCanvas(bitmap))
                    using (var paint = new SKPaint())
                    {
                        canvas.Clear(SKColors.Transparent);
                        var scaleX = (float)sizeX / picture.CullRect.Width;
                        var scaleY = (float)sizeY / picture.CullRect.Height;
                        var matrix = SKMatrix.MakeScale(scaleX, scaleY);
                        canvas.DrawPicture(picture, ref matrix, paint);
                        canvas.Flush();

                        return(await Decode(picture, bitmap, resolvedData).ConfigureAwait(false));
                    }
        }
        public async Task <DataResolverResult> Resolve(string identifier, TaskParameter parameters, CancellationToken token)
        {
            ImageSource source = parameters.Source;

            if (!string.IsNullOrWhiteSpace(parameters.LoadingPlaceholderPath) && parameters.LoadingPlaceholderPath == identifier)
            {
                source = parameters.LoadingPlaceholderSource;
            }
            else if (!string.IsNullOrWhiteSpace(parameters.ErrorPlaceholderPath) && parameters.ErrorPlaceholderPath == identifier)
            {
                source = parameters.ErrorPlaceholderSource;
            }

            var resolvedData = await(Configuration.DataResolverFactory ?? new DataResolverFactory())
                               .GetResolver(identifier, source, parameters, Configuration)
                               .Resolve(identifier, parameters, token).ConfigureAwait(false);

            if (resolvedData?.Stream == null)
            {
                throw new FileNotFoundException(identifier);
            }

            var svg = new SKSvg()
            {
                ThrowOnUnsupportedElement = false,
            };
            SKPicture picture;

            if (ReplaceStringMap == null || ReplaceStringMap.Count == 0)
            {
                using (var svgStream = resolvedData.Stream)
                {
                    picture = svg.Load(svgStream);
                }
            }
            else
            {
                using (var svgStream = resolvedData.Stream)
                    using (var reader = new StreamReader(svgStream))
                    {
                        var inputString = await reader.ReadToEndAsync();

                        foreach (var map in ReplaceStringMap
                                 .Where(v => v.Key.StartsWith("regex:")))
                        {
                            inputString = Regex.Replace(inputString, map.Key.Substring(0, 6), map.Value);
                        }

                        var builder = new StringBuilder(inputString);

                        foreach (var map in ReplaceStringMap
                                 .Where(v => !v.Key.StartsWith("regex:", StringComparison.OrdinalIgnoreCase)))
                        {
                            builder.Replace(map.Key, map.Value);
                        }

                        using (var svgFinalStream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString())))
                        {
                            picture = svg.Load(svgFinalStream);
                        }
                    }
            }

            double sizeX = 0;
            double sizeY = 0;

            if (VectorWidth <= 0 && VectorHeight <= 0)
            {
                if (picture.CullRect.Width > 0)
                {
                    sizeX = picture.CullRect.Width;
                }
                else
                {
                    sizeX = 300;
                }

                if (picture.CullRect.Height > 0)
                {
                    sizeY = picture.CullRect.Height;
                }
                else
                {
                    sizeY = 300;
                }
            }
            else if (VectorWidth > 0 && VectorHeight > 0)
            {
                sizeX = VectorWidth;
                sizeY = VectorHeight;
            }
            else if (VectorWidth > 0)
            {
                sizeX = VectorWidth;
                sizeY = (VectorWidth / picture.CullRect.Width) * picture.CullRect.Height;
            }
            else
            {
                sizeX = (VectorHeight / picture.CullRect.Height) * picture.CullRect.Width;
                sizeY = VectorHeight;
            }

            if (UseDipUnits)
            {
                sizeX = sizeX.DpToPixels();
                sizeY = sizeY.DpToPixels();
            }

            lock (_encodingLock)
            {
                using (var bitmap = new SKBitmap(new SKImageInfo((int)sizeX, (int)sizeY)))
                    //using (var bitmap = new SKBitmap((int)sizeX, (int)sizeY))
                    using (var canvas = new SKCanvas(bitmap))
                        using (var paint = new SKPaint())
                        {
                            canvas.Clear(SKColors.Transparent);
                            float scaleX = (float)sizeX / picture.CullRect.Width;
                            float scaleY = (float)sizeY / picture.CullRect.Height;
                            var   matrix = SKMatrix.MakeScale(scaleX, scaleY);

                            canvas.DrawPicture(picture, ref matrix, paint);
                            canvas.Flush();

                            using (var image = SKImage.FromBitmap(bitmap))
                                //using (var data = image.Encode(SKImageEncodeFormat.Png, 100))  //TODO disabled because of https://github.com/mono/SkiaSharp/issues/285
                                using (var data = image.Encode())
                                {
                                    var stream = new MemoryStream();
                                    data.SaveTo(stream);
                                    stream.Position = 0;
                                    resolvedData.ImageInformation.SetType(ImageInformation.ImageType.SVG);
                                    return(new DataResolverResult(stream, resolvedData.LoadingResult, resolvedData.ImageInformation));
                                }
                        }
            }
        }
        public async Task <Tuple <Stream, LoadingResult, ImageInformation> > Resolve(string identifier, TaskParameter parameters, CancellationToken token)
        {
            ImageSource source = parameters.Source;

            if (!string.IsNullOrWhiteSpace(parameters.LoadingPlaceholderPath) && parameters.LoadingPlaceholderPath == identifier)
            {
                source = parameters.LoadingPlaceholderSource;
            }
            else if (!string.IsNullOrWhiteSpace(parameters.ErrorPlaceholderPath) && parameters.ErrorPlaceholderPath == identifier)
            {
                source = parameters.ErrorPlaceholderSource;
            }

            var resolvedData = await(Configuration.DataResolverFactory ?? new DataResolverFactory())
                               .GetResolver(identifier, source, parameters, Configuration)
                               .Resolve(identifier, parameters, token).ConfigureAwait(false);

            if (resolvedData?.Item1 == null)
            {
                throw new FileNotFoundException(identifier);
            }

            var svg = new SKSvg()
            {
                ThrowOnUnsupportedElement = false,
            };
            SKPicture picture;

            using (var svgStream = resolvedData.Item1)
            {
                picture = svg.Load(resolvedData?.Item1);
            }

            float sizeX = 0;
            float sizeY = 0;

            if (VectorWidth == 0 && VectorHeight == 0)
            {
                if (picture.CullRect.Width > 0)
                {
                    sizeX = picture.CullRect.Width;
                }
                else
                {
                    sizeX = 300;
                }

                if (picture.CullRect.Height > 0)
                {
                    sizeY = picture.CullRect.Height;
                }
                else
                {
                    sizeY = 300;
                }
            }
            else if (VectorWidth > 0 && VectorHeight > 0)
            {
                sizeX = VectorWidth;
                sizeY = VectorHeight;
            }
            else if (VectorWidth > 0)
            {
                sizeX = VectorWidth;
                sizeY = (VectorWidth / picture.CullRect.Width) * picture.CullRect.Height;
            }
            else
            {
                sizeX = (VectorHeight / picture.CullRect.Height) * picture.CullRect.Width;
                sizeY = VectorHeight;
            }

            using (var bitmap = new SKBitmap((int)sizeX, (int)sizeY))
                using (var canvas = new SKCanvas(bitmap))
                    using (var paint = new SKPaint())
                    {
                        canvas.Clear(SKColors.Transparent);
                        float scaleX = sizeX / picture.CullRect.Width;
                        float scaleY = sizeY / picture.CullRect.Height;
                        var   matrix = SKMatrix.MakeScale(scaleX, scaleY);

                        canvas.DrawPicture(picture, ref matrix, paint);
                        canvas.Flush();

                        using (var image = SKImage.FromBitmap(bitmap))
                            using (var data = image.Encode(SKImageEncodeFormat.Png, 80))
                            {
                                var stream = new MemoryStream();
                                data.SaveTo(stream);
                                stream.Position = 0;
                                //var stream = data?.AsStream();
                                return(new Tuple <Stream, LoadingResult, ImageInformation>(stream, resolvedData.Item2, resolvedData.Item3));
                            }
                    }
        }