private void ProcessImage(CommentImage image, string imageUrl, string originalUrl, ITextViewLine line, int lineNumber, SnapshotSpan span, double scale, string filepath)
        {
            try
            {
                var result = image.TrySet(
                    imageUrl,
                    originalUrl,
                    scale,
                    filepath,
                    out Exception imageLoadingException);

                // Position image and add as adornment
                if (imageLoadingException == null)
                {
                    AddAdorment(image, line, lineNumber, span);
                }
                else
                {
                    Images.TryRemove(lineNumber, out var commentImage);
                    commentImage.Dispose();

                    _errorTags.Add(
                        new TagSpan <ErrorTag>(
                            span,
                            new ErrorTag("Trouble loading image", GetErrorMessage(imageLoadingException))));
                }
            }
            catch (Exception ex)
            {
                ExceptionHandler.Notify(ex, true);
            }
        }
        private void CreateVisuals(ITextViewLine line, int lineNumber, string filepath)
        {
            try
            {
                var lineText = line.Extent.GetText();
                var lines    = lineText.Split(
                    new string[] { Environment.NewLine },
                    StringSplitOptions.RemoveEmptyEntries);
                // multiline mean a block of code is collapsed
                // do not display pics from the collapsed text
                if (lines.Length > 1)
                {
                    return;
                }
                var matchIndex = CommentImageParser.Match(_contentTypeName, lineText, out string matchedText);
                if (matchIndex >= 0)
                {
                    // Get coordinates of text
                    var start = line.Extent.Start.Position + matchIndex;
                    var end   = line.Start + (line.Extent.Length - 1);
                    var span  = new SnapshotSpan(_view.TextSnapshot, Span.FromBounds(start, end));

                    CommentImageParser.TryParse(
                        matchedText,
                        out string imageUrl, out double scale, out Exception xmlParseException);

                    if (xmlParseException != null)
                    {
                        CommentImage commentImage;
                        if (Images.TryRemove(lineNumber, out commentImage))
                        {
                            _layer.RemoveAdornment(commentImage);
                            commentImage.Dispose();
                        }

                        _errorTags.Add(
                            new TagSpan <ErrorTag>(
                                span,
                                new ErrorTag("XML parse error", GetErrorMessage(xmlParseException))));

                        return;
                    }

                    var          reload = false;
                    CommentImage image  = Images.AddOrUpdate(lineNumber, ln =>
                    {
                        reload = true;
                        return(new CommentImage(_variableExpander));
                    }, (ln, img) =>
                    {
                        if (img.OriginalUrl == imageUrl && img.Scale != scale)
                        {
                            // URL same but scale changed
                            img.Scale = scale;
                            reload    = true;
                        }
                        else if (img.OriginalUrl != imageUrl)
                        {
                            // URL different, must load from new source
                            reload = true;
                        }
                        return(img);
                    });

                    var originalUrl = imageUrl;
                    if (reload)
                    {
                        if (_processingUris.Contains(imageUrl))
                        {
                            return;
                        }

                        if (imageUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase))
                        {
                            if (ImageCache.Instance.TryGetValue(imageUrl, out string localPath))
                            {
                                imageUrl = localPath;
                            }
                            else
                            {
                                _processingUris.Add(imageUrl);
                                var       tempPath = Path.Combine(Path.GetTempPath(), Path.GetFileName(imageUrl));
                                WebClient client   = new WebClient();
                                client.DownloadDataCompleted += Client_DownloadDataCompleted;

                                _toaddImages.TryAdd(
                                    client,
                                    new ImageParameters()
                                {
                                    Uri        = imageUrl,
                                    LocalPath  = tempPath,
                                    Image      = image,
                                    Line       = line,
                                    LineNumber = lineNumber,
                                    Span       = span,
                                    Scale      = scale,
                                    Filepath   = filepath
                                });

                                client.DownloadDataAsync(new Uri(imageUrl));

                                return;
                            }
                        }
                    }

                    if (imageUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase))
                    {
                        if (ImageCache.Instance.TryGetValue(imageUrl, out string localPath))
                        {
                            imageUrl = localPath;
                        }
                    }
                    ProcessImage(image, imageUrl, originalUrl, line, lineNumber, span, scale, filepath);
                }
                else
                {
                    Images.TryRemove(lineNumber, out var commentImage);
                    commentImage.Dispose();
                }
            }
            catch (Exception ex)
            {
                ExceptionHandler.Notify(ex, true);
            }
        }