Example #1
0
        public static void DrawQuests(SKCanvas c, BaseBundle icon)
        {
            using SKPaint paint = new SKPaint
                  {
                      IsAntialias   = true,
                      FilterQuality = SKFilterQuality.High,
                      TextSize      = 27,
                      Color         = SKColors.White,
                      TextAlign     = SKTextAlign.Left,
                      Typeface      = Text.TypeFaces.BundleDisplayNameTypeface
                  };

            int y = icon.HeaderHeight + 50;

            foreach (Quest q in icon.Quests)
            {
                DrawQuestBackground(c, icon, y, true);

                paint.TextSize    = 27;
                paint.ImageFilter = null;
                paint.Color       = SKColors.White;
                paint.TextAlign   = SKTextAlign.Left;
                paint.Typeface    = Text.TypeFaces.BundleDisplayNameTypeface;
                if (!string.IsNullOrEmpty(q.Description))
                {
                    if ((ELanguage)Properties.Settings.Default.AssetsLanguage == ELanguage.Arabic)
                    {
                        SKShaper shaper = new SKShaper(paint.Typeface);
                        float    shapedTextWidth;

                        while (true)
                        {
                            SKShaper.Result shapedText = shaper.Shape(q.Description, paint);
                            shapedTextWidth = shapedText.Points[^ 1].X + paint.TextSize / 2f;
Example #2
0
        /// <summary>
        /// Gets a <see cref="SKPaint"/> containing information needed to render text.
        /// </summary>
        /// <remarks>
        /// This modifies and returns the local <see cref="paint"/> instance.
        /// </remarks>
        /// <param name="fontFamily">The font family.</param>
        /// <param name="fontSize">The font size.</param>
        /// <param name="fontWeight">The font weight.</param>
        /// <param name="shaper">The font shaper.</param>
        /// <returns>The paint.</returns>
        private SKPaint GetTextPaint(string fontFamily, double fontSize, double fontWeight, out SKShaper shaper)
        {
            var fontDescriptor = new FontDescriptor(fontFamily, fontWeight);

            if (!this.typefaceCache.TryGetValue(fontDescriptor, out var typeface))
            {
                typeface = SKTypeface.FromFamilyName(fontFamily, new SKFontStyle((int)fontWeight, (int)SKFontStyleWidth.Normal, SKFontStyleSlant.Upright));
                this.typefaceCache.Add(fontDescriptor, typeface);
            }

            if (this.UseTextShaping)
            {
                if (!this.shaperCache.TryGetValue(fontDescriptor, out shaper))
                {
                    shaper = new SKShaper(typeface);
                    this.shaperCache.Add(fontDescriptor, shaper);
                }
            }
            else
            {
                shaper = null;
            }

            this.paint.Typeface     = typeface;
            this.paint.TextSize     = this.Convert(fontSize);
            this.paint.IsAntialias  = true;
            this.paint.Style        = SKPaintStyle.Fill;
            this.paint.HintingLevel = this.RendersToScreen ? SKPaintHinting.Full : SKPaintHinting.NoHinting;
            this.paint.SubpixelText = this.RendersToScreen;
            return(this.paint);
        }
Example #3
0
        /// <summary>
        /// Measures text using the specified <see cref="SKShaper"/> and <see cref="SKPaint"/>.
        /// </summary>
        /// <param name="text">The text to measure.</param>
        /// <param name="shaper">The text shaper.</param>
        /// <param name="paint">The paint.</param>
        /// <returns>The width of the text when rendered using the specified shaper and paint.</returns>
        private float MeasureText(string text, SKShaper shaper, SKPaint paint)
        {
            if (!this.UseTextShaping)
            {
                return(paint.MeasureText(text));
            }

            // we have to get a bit creative here as SKShaper does not offer a direct overload for this.
            // see also https://github.com/mono/SkiaSharp/blob/master/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz.Shared/SKShaper.cs
            using var buffer = new HarfBuzzSharp.Buffer();
            switch (paint.TextEncoding)
            {
            case SKTextEncoding.Utf8:
                buffer.AddUtf8(text);
                break;

            case SKTextEncoding.Utf16:
                buffer.AddUtf16(text);
                break;

            case SKTextEncoding.Utf32:
                buffer.AddUtf32(text);
                break;

            default:
                throw new NotSupportedException("TextEncoding is not supported.");
            }

            buffer.GuessSegmentProperties();
            shaper.Shape(buffer, paint);
            return(buffer.GlyphPositions.Sum(gp => gp.XAdvance) * paint.TextSize / 512);
        }
Example #4
0
        public void DrawShapedTextExtensionMethodDraws()
        {
            using (var bitmap = new SKBitmap(new SKImageInfo(512, 512)))
                using (var canvas = new SKCanvas(bitmap))
                    using (var tf = SKTypeface.FromFile(Path.Combine(PathToFonts, "content-font.ttf")))
                        using (var shaper = new SKShaper(tf))
                            using (var paint = new SKPaint {
                                IsAntialias = true, TextSize = 64, Typeface = tf
                            })
                            {
                                canvas.Clear(SKColors.White);

                                canvas.DrawShapedText(shaper, "متن", 100, 200, paint);

                                canvas.Flush();

                                Assert.Equal(SKColors.Black, bitmap.GetPixel(110, 210));
                                Assert.Equal(SKColors.Black, bitmap.GetPixel(127, 196));
                                Assert.Equal(SKColors.Black, bitmap.GetPixel(142, 197));
                                Assert.Equal(SKColors.Black, bitmap.GetPixel(155, 195));
                                Assert.Equal(SKColors.Black, bitmap.GetPixel(131, 181));
                                Assert.Equal(SKColors.White, bitmap.GetPixel(155, 190));
                                Assert.Equal(SKColors.White, bitmap.GetPixel(110, 200));
                            }
        }
Example #5
0
        public void ShapeTest()
        {
            using var bmp    = new Bitmap(600, 400);
            using var canvas = new SKCanvas(bmp.skBitmap);

            using var typeface = SKFontManager.Default.MatchCharacter('中');
            using var paint    = new SKPaint();
            paint.IsAntialias  = true;
            paint.TextEncoding = SKTextEncoding.Utf16;
            paint.TextSize     = 30;
            paint.Color        = new SKColor(255, 0, 0, 255);
            paint.Style        = SKPaintStyle.Fill;
            paint.Typeface     = typeface;
            var src = "Hello Future! 你好,未来!";

            canvas.DrawText(src, 0, 100, paint);

            using var shaper = new SKShaper(typeface);
            paint.TextAlign  = SKTextAlign.Right;
            //paint.TextEncoding = SKTextEncoding.GlyphId; //Not implemented
            canvas.DrawShapedText(shaper, src, 0, 200, paint);

            using var fs = File.OpenWrite("A_document.jpg");
            bmp.Save(fs, ImageFormat.Jpeg);
        }
Example #6
0
        public static SKPoint[] MeasureCharacters(string text, SKTypeface font, int fontSize, float xOffset = 0, float yOffset = 0)
        {
            using var paint  = SkiaTextExtensions.CreateTextPaint(font, fontSize, SKColors.Black);
            using var shaper = new SKShaper(font);

            var result = shaper.Shape(text, xOffset, yOffset, paint);

            return(result.Points);
        }
        protected void DrawLabels(SKCanvas canvas, SKPoint[] points, SKSize itemSize, int height, float footerHeight)
        {
            for (int i = 0; i < this.Entries.Count(); i++)
            {
                var entry = this.Entries.ElementAt(i);
                var point = points[i];

                if (!string.IsNullOrEmpty(entry.Label))
                {
                    using (var paint = new SKPaint())
                    {
                        paint.TextSize    = this.LabelTextSize;
                        paint.IsAntialias = true;
                        paint.Color       = entry.TextColor;
                        paint.IsStroke    = false;

                        var bounds = new SKRect();
                        var text   = entry.Label;
                        paint.MeasureText(text, ref bounds);

                        if (bounds.Width > itemSize.Width)
                        {
                            text = text.Substring(0, Math.Min(3, text.Length));
                            paint.MeasureText(text, ref bounds);
                        }

                        if (bounds.Width > itemSize.Width)
                        {
                            text = text.Substring(0, Math.Min(1, text.Length));
                            paint.MeasureText(text, ref bounds);
                        }

                        //canvas.DrawText("asdf", point.X - (bounds.Width / 2), height - this.Margin + (this.LabelTextSize / 2), paint);

                        using (var tf = SKFontManager.Default.MatchCharacter('م'))
                            using (var shaper = new SKShaper(tf))
                                using (var paint1 = new SKPaint {
                                    TextSize = 30, Typeface = tf
                                })
                                {
                                    //canvas.Clear(SKColors.White);
                                    //canvas.DrawShapedText(shaper, "سلام", 100, 200, paint1);
                                    paint.Typeface = tf;
                                    var balanceValue = 35;
                                    canvas.DrawShapedText(shaper, text, point.X - (bounds.Width / 2) - balanceValue, height - this.Margin + (this.LabelTextSize / 2) - balanceValue, paint);
                                }
                    }
                }
            }
        }
Example #8
0
        public void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
        {
            try
            {
                SKImageInfo info     = args.Info;
                SKSurface   surface  = args.Surface;
                SKCanvas    canvas   = surface.Canvas;
                Assembly    assembly = GetType().GetTypeInfo().Assembly;

                if (_saveBitmap == null)
                {
                    _saveBitmap = new SKBitmap(info.Width, info.Height);
                }

                SKBitmap bitmap = new SKBitmap(Math.Max(_saveBitmap.Width, info.Width),
                                               Math.Max(_saveBitmap.Height, info.Height));

                float x = info.Width / 3;
                float y = (float)(info.Height / 1.5);

                using (SKCanvas c = new SKCanvas(bitmap))
                {
                    foreach (SKPath p in _completedPaths)
                    {
                        c.DrawPath(p, paint);
                    }

                    foreach (SKPath p in _inProgressPaths.Values)
                    {
                        c.DrawPath(p, paint);
                    }
                }

                canvas.Clear();
                canvas.DrawBitmap(bitmap, 0, 0);

                var emoji   = _vm.Image;
                int exEmoji = 0x1f600;

                paint.Typeface = SKFontManager.CreateDefault().MatchCharacter(exEmoji);
                paint.TextSize = 210.0f;

                var tf     = SKFontManager.CreateDefault().MatchCharacter(exEmoji);
                var shaper = new SKShaper(tf);
                canvas.DrawShapedText(shaper, emoji, x, y, paint);
            }
            catch { }
        }
        protected override void OnDrawSample(SKCanvas canvas, int width, int height)
        {
            canvas.DrawColor(SKColors.White);

            using var tf          = SKFontManager.Default.MatchCharacter('م') ?? SKTypeface.FromStream(SampleMedia.Fonts.EmbeddedFont);
            using var paint       = new SKPaint { IsAntialias = true, TextSize = 64 };
            using var arabicPaint = new SKPaint { IsAntialias = true, TextSize = 64, Typeface = tf };

            // unshaped
            canvas.DrawText("Unshaped:", 100, 100, paint);
            canvas.DrawText("مرحبا بالعالم", 100, 180, arabicPaint);

            // shaped
            using var shaper = new SKShaper(tf);
            canvas.DrawText("Shaped:", 100, 300, paint);
            canvas.DrawShapedText(shaper, "مرحبا بالعالم", 100, 380, arabicPaint);
        }
Example #10
0
        public void Draw(SKCanvas c)
        {
            c.DrawRect(new SKRect(0, 0, Width, Height),
                       new SKPaint
            {
                IsAntialias   = true,
                FilterQuality = SKFilterQuality.High,
                Shader        = SKShader.CreateLinearGradient(
                    new SKPoint(Width / 2, Height),
                    new SKPoint(Width, Height / 4),
                    new SKColor[2] {
                    SKColor.Parse("01369C"), SKColor.Parse("1273C8")
                },
                    SKShaderTileMode.Clamp)
            });

            int     textSize  = 45;
            SKPaint namePaint = new SKPaint
            {
                IsAntialias   = true,
                FilterQuality = SKFilterQuality.High,
                Typeface      = Text.TypeFaces.DisplayNameTypeface,
                TextSize      = textSize,
                Color         = SKColors.White,
                TextAlign     = SKTextAlign.Left
            };
            SKPaint optionPaint = new SKPaint
            {
                IsAntialias   = true,
                FilterQuality = SKFilterQuality.High,
                Typeface      = Text.TypeFaces.DisplayNameTypeface,
                TextSize      = 20,
                Color         = SKColor.Parse("EEFFFF"),
                TextAlign     = SKTextAlign.Left
            };

            if ((ELanguage)Properties.Settings.Default.AssetsLanguage == ELanguage.Arabic)
            {
                SKShaper shaper = new SKShaper(namePaint.Typeface);
                float    shapedTextWidth;

                while (true)
                {
                    SKShaper.Result shapedText = shaper.Shape(OptionDisplayName, namePaint);
                    shapedTextWidth = shapedText.Points[^ 1].X + namePaint.TextSize / 2f;
Example #11
0
        public void CorrectlyShapesArabicScript()
        {
            var clusters   = new uint[] { 4, 2, 0 };
            var codepoints = new uint[] { 629, 668, 891 };
            var points     = new SKPoint[] { new SKPoint(0, 0), new SKPoint(28.375f, 0), new SKPoint(42.125f, 0) };

            using (var tf = SKTypeface.FromFile(Path.Combine(PathToFonts, "content-font.ttf")))
                using (var shaper = new SKShaper(tf))
                    using (var paint = new SKPaint {
                        IsAntialias = true, TextSize = 64, Typeface = tf
                    })
                    {
                        var result = shaper.Shape("متن", paint);

                        Assert.Equal(clusters, result.Clusters);
                        Assert.Equal(codepoints, result.Codepoints);
                        Assert.Equal(points, result.Points);
                    }
        }
Example #12
0
        public static void DrawCenteredMultilineText(SKCanvas canvas, string text, int maxLineCount, int size, int margin, ETextSide side, SKRect area, SKPaint paint)
        {
            float       lineHeight = paint.TextSize * 1.2f;
            List <Line> lines      = SplitLines(text, paint, area.Width - margin);

            if (lines == null)
            {
                return;
            }
            if (lines.Count <= maxLineCount)
            {
                maxLineCount = lines.Count;
            }

            float    height = maxLineCount * lineHeight;
            float    y      = area.MidY - height / 2;
            SKShaper shaper = (ELanguage)Settings.Default.AssetsLanguage == ELanguage.Arabic ? new SKShaper(paint.Typeface) : null;

            for (int i = 0; i < maxLineCount; i++)
            {
                Line line = lines[i];

                y += lineHeight;
                float x = side switch
                {
                    ETextSide.Center => area.MidX - line.Width / 2,
                    ETextSide.Right => size - margin - line.Width,
                    ETextSide.Left => margin,
                    _ => area.MidX - line.Width / 2
                };

                string lineText = line.Value.TrimEnd();

                if (shaper == null)
                {
                    canvas.DrawText(lineText, x, y, paint);
                }
                else
                {
                    if (side == ETextSide.Center)
                    {
                        SKShaper.Result shapedText      = shaper.Shape(lineText, paint);
                        float           shapedTextWidth = shapedText.Points[^ 1].X + paint.TextSize / 2f;
Example #13
0
        public void DrawShapedTextExtensionMethodDraws()
        {
            using (var surface = SKSurface.Create(new SKImageInfo(512, 512)))
                using (var tf = SKTypeface.FromFile(Path.Combine(PathToFonts, "content-font.ttf")))
                    using (var shaper = new SKShaper(tf))
                        using (var paint = new SKPaint {
                            IsAntialias = true, TextSize = 64, Typeface = tf
                        })
                        {
                            surface.Canvas.Clear(SKColors.White);

                            surface.Canvas.DrawShapedText(shaper, "متن", 100, 200, paint);

                            surface.Canvas.Flush();

                            using (var img = surface.Snapshot())
                                using (var data = img.Encode(SKEncodedImageFormat.Png, 100))
                                    using (var stream = File.OpenWrite(Path.Combine(PathToImages, "test.png")))
                                    {
                                        data.AsStream().CopyTo(stream);
                                    }
                        }
        }
Example #14
0
        private void DrawHeaderText(SKCanvas c)
        {
            using SKPaint paint = new SKPaint
                  {
                      IsAntialias   = true,
                      FilterQuality = SKFilterQuality.High,
                      Typeface      = Text.TypeFaces.BundleDisplayNameTypeface,
                      TextSize      = 50,
                      Color         = SKColors.White,
                      TextAlign     = SKTextAlign.Left,
                  };

            string text = DisplayName.ToUpper();
            int    x    = 300;

            if ((ELanguage)Properties.Settings.Default.AssetsLanguage == ELanguage.Arabic)
            {
                SKShaper shaper = new SKShaper(paint.Typeface);
                float    shapedTextWidth;

                while (true)
                {
                    SKShaper.Result shapedText = shaper.Shape(text, paint);
                    shapedTextWidth = shapedText.Points[^ 1].X + paint.TextSize / 2f;
Example #15
0
        public static async Task Run(
            [QueueTrigger("create-hero")] KeyValuePair <string, string> hf,
            [Blob("heroimages")] CloudBlobContainer heroContainer,
            [Blob("hashflags")] CloudBlobContainer hashflagsContainer,
            [Queue("tweet")] ICollector <KeyValuePair <string, string> > tweetCollector,
            ILogger log)
        {
            log.LogInformation($"Function executed at: {DateTime.Now}");

            var hashtag = '#' + hf.Key;

            var textSize = GetAdjustedFont(hashtag);
            var info     = new SKImageInfo(ImageWidth, ImageHeight);

            using var surface = SKSurface.Create(info);
            var canvas = surface.Canvas;

            canvas.Clear(SKColors.White);

            #region hashtag

            var typefaces = hf.Key.Select(character => SKFontManager.CreateDefault().MatchCharacter(FontFamily, character)).ToList();

            using var tf = typefaces.FirstOrDefault(t => t.FamilyName != FontFamily) ??
                           SKTypeface.FromFamilyName(FontFamily);
            using var shaper = new SKShaper(tf);

            var paint = new SKPaint
            {
                IsAntialias = true,
                Color       = new SKColor(29, 161, 242),
                TextSize    = textSize,
                Typeface    = tf
            };

            var bounds = new SKRect();
            paint.MeasureText(hashtag, ref bounds);
            var point = GetPoint(hashtag, bounds.Height, bounds.Width);
            canvas.DrawShapedText(shaper, hashtag, point.X, point.Y, paint);

            #endregion

            #region hashflag

            await using var stream = new MemoryStream();
            await hashflagsContainer.GetBlockBlobReference(hf.Value).DownloadToStreamAsync(stream);

            stream.Seek(0, SeekOrigin.Begin);
            var hashflagImage = SKBitmap.Decode(stream);

            var x = IsRtl(hashtag) ? point.X - HashflagSize - 10 : point.X + bounds.Width + 10;
            var y = (ImageHeight - HashflagSize) / 2;

            canvas.DrawBitmap(hashflagImage, x, y);
            #endregion

            #region watermark

            paint = new SKPaint
            {
                Color       = new SKColor(20, 23, 26, 127),
                TextSize    = 18,
                IsAntialias = true,
                Typeface    = tf
            };
            canvas.DrawShapedText(shaper, "@HashflagArchive", 900, 575, paint);

            #endregion

            canvas.Flush();
            await heroContainer.CreateIfNotExistsAsync();

            var heroBlob = heroContainer.GetBlockBlobReference(hf.Key);
            heroBlob.Properties.ContentType = "image/png";
            await heroBlob.UploadFromStreamAsync(ToStream(surface));

            tweetCollector.Add(hf);
        }
Example #16
0
        public static void DrawCaptionLabels(this SKCanvas canvas, string label, SKColor labelColor, bool labelIsUnicode, char unicodeLang, string value, SKColor valueColor, float textSize, SKPoint point, SKTextAlign horizontalAlignment, SKTypeface typeface, out SKRect totalBounds)
        {
            var hasLabel      = !string.IsNullOrEmpty(label);
            var hasValueLabel = !string.IsNullOrEmpty(value);

            totalBounds = new SKRect();

            if (hasLabel || hasValueLabel)
            {
                var hasOffset     = hasLabel && hasValueLabel;
                var captionMargin = textSize * 0.60f;
                var space         = hasOffset ? captionMargin : 0;

                if (hasLabel)
                {
                    using (var paint = new SKPaint
                    {
                        TextSize = textSize,
                        IsAntialias = true,
                        Color = labelColor,
                        IsStroke = false,
                        TextAlign = horizontalAlignment,
                        Typeface = typeface
                    })
                    {
                        var bounds = new SKRect();
                        var text   = label;
                        paint.MeasureText(text, ref bounds);

                        var y = point.Y - ((bounds.Top + bounds.Bottom) / 2) - space;

                        if (labelIsUnicode)
                        {
                            using (var tf = SKFontManager.Default.MatchCharacter(unicodeLang))
                                using (var shaper = new SKShaper(tf))
                                {
                                    canvas.DrawShapedText(shaper, text, 0, 0, paint);
                                }
                        }
                        else
                        {
                            canvas.DrawText(text, point.X, y, paint);
                        }

                        var labelBounds = GetAbsolutePositionRect(point.X, y, bounds, horizontalAlignment);
                        totalBounds = labelBounds.Standardized;
                    }
                }

                if (hasValueLabel)
                {
                    using (var paint = new SKPaint()
                    {
                        TextSize = textSize,
                        IsAntialias = true,
                        FakeBoldText = true,
                        Color = valueColor,
                        IsStroke = false,
                        TextAlign = horizontalAlignment,
                        Typeface = typeface
                    })
                    {
                        var bounds = new SKRect();
                        var text   = value;
                        paint.MeasureText(text, ref bounds);

                        var y = point.Y - ((bounds.Top + bounds.Bottom) / 2) + space;

                        canvas.DrawText(text, point.X, y, paint);

                        var valueBounds = GetAbsolutePositionRect(point.X, y, bounds, horizontalAlignment);

                        if (totalBounds.IsEmpty)
                        {
                            totalBounds = valueBounds;
                        }
                        else
                        {
                            totalBounds.Union(valueBounds);
                        }
                    }
                }
            }
        }
Example #17
0
        public static void DrawCaptionLabels(this SKCanvas canvas, string label, SKColor labelColor, string value, SKColor valueColor, float textSize, SKPoint point, SKTextAlign horizontalAlignment)
        {
            var hasLabel      = !string.IsNullOrEmpty(label);
            var hasValueLabel = !string.IsNullOrEmpty(value);

            if (hasLabel || hasValueLabel)
            {
                var hasOffset     = hasLabel && hasValueLabel;
                var captionMargin = textSize * 0.60f;
                var space         = hasOffset ? captionMargin : 0;

                if (hasLabel)
                {
                    using (var paint = new SKPaint()
                    {
                        TextSize = textSize,
                        IsAntialias = true,
                        Color = labelColor,
                        IsStroke = false,
                        //TextAlign = horizontalAlignment,
                    })
                    {
                        var bounds = new SKRect();
                        var text   = label;
                        paint.MeasureText(text, ref bounds);

                        var y = point.Y - ((bounds.Top + bounds.Bottom) / 2) - space;


                        //canvas.DrawText(text, point.X, y, paint);

                        using (var tf = SKFontManager.Default.MatchCharacter('م'))
                            using (var shaper = new SKShaper(tf))
                                using (var paint1 = new SKPaint {
                                    TextSize = 30, Typeface = tf
                                })
                                {
                                    //canvas.Clear(SKColors.White);
                                    //canvas.DrawShapedText(shaper, "سلام", 100, 200, paint1);
                                    paint.Typeface = tf;
                                    var balaceValue = 0;
                                    if (horizontalAlignment == SKTextAlign.Right)
                                    {
                                        if (text.Length <= 5)
                                        {
                                            balaceValue = 60;
                                        }
                                        else
                                        {
                                            var factor = (System.Math.Abs(text.Length - 5));
                                            balaceValue = factor * 10 + 90;
                                        }
                                    }
                                    canvas.DrawShapedText(shaper, text, point.X - balaceValue, y, paint);
                                }
                    }
                }

                if (hasValueLabel)
                {
                    using (var paint = new SKPaint()
                    {
                        TextSize = textSize,
                        IsAntialias = true,
                        FakeBoldText = true,
                        Color = valueColor,
                        IsStroke = false,
                        TextAlign = horizontalAlignment,
                    })
                    {
                        var bounds = new SKRect();
                        var text   = value;
                        paint.MeasureText(text, ref bounds);

                        var y = point.Y - ((bounds.Top + bounds.Bottom) / 2) + space;

                        canvas.DrawText(text, point.X, y, paint);
                    }
                }
            }
        }
Example #18
0
        public SKData DrawHistogram(string referenceName, int zoom, int chunk)
        {
            var refer = _service._references.FirstOrDefault(r => r.Name == referenceName);

            if (chunk == 0 && zoom == 10)
            {
                LoadReference(referenceName);
            }

            using var surface     = SKSurface.Create(new SKImageInfo(refer.Length * zoom, 220));
            using SKCanvas canvas = surface.Canvas;

            canvas.Clear();

            using SKPaint paint = new SKPaint
                  {
                      Style       = SKPaintStyle.StrokeAndFill,
                      Color       = SKColors.Blue,
                      StrokeWidth = 1
                  };

            using SKPaint linePaint = new SKPaint
                  {
                      Style       = SKPaintStyle.Stroke,
                      Color       = SKColors.Black,
                      StrokeWidth = 1
                  };

            using SKPaint dashPaint = new SKPaint
                  {
                      Style       = SKPaintStyle.Stroke,
                      Color       = SKColors.Black,
                      StrokeWidth = 1,
                      PathEffect  = SKPathEffect.CreateDash(new[] { 20f, 5f }, 0)
                  };

            var histData = _service._histograms[refer.Name];

            var scale = (float)(100 / histData.Average());

            for (int i = 0; i < refer.Length; i++)
            {
                canvas.DrawRect(i * zoom + 5, 200 - (histData[i] * scale), zoom, histData[i] * scale, paint);
            }

            canvas.DrawLine(5, 0, 5, 200, linePaint);
            canvas.DrawLine(5, 199, refer.Length * zoom, 199, linePaint);

            var average = (int)(Math.Round(histData.Average()));

            canvas.DrawLine(5, average * scale, refer.Length * zoom, average * scale, dashPaint);

            using SKPaint textPaint = new SKPaint
                  {
                      Style        = SKPaintStyle.StrokeAndFill,
                      Color        = SKColors.Black,
                      StrokeWidth  = 1,
                      TextSize     = 20,
                      Typeface     = SKTypeface.FromFamilyName("Courier New"),
                      SubpixelText = true
                  };
            canvas.DrawText(average.ToString(), 6, average * scale - 2, textPaint);

            var cnt = textPaint.MeasureText("ACGT");

            if (zoom == 10)
            {
                textPaint.TextSize = textPaint.TextSize * 40 / cnt;
                var shaper = new SKShaper(SKTypeface.FromFamilyName("Courier New"));

                canvas.DrawShapedText(shaper, reference, 5, 215, textPaint);
            }

            var      width  = (chunk + 1) * WIDTH * zoom > refer.Length * zoom ? refer.Length * zoom % WIDTH : WIDTH;
            SKPixmap pixmap = surface.Snapshot().Subset(SKRectI.Create(chunk * WIDTH, 0, width, canvas.DeviceClipBounds.Height)).PeekPixels();

            var options = new SKWebpEncoderOptions(SKWebpEncoderCompression.Lossless, 100);

            return(pixmap.Encode(options));
        }