/// <summary>
        /// Creates a waveform image from a description's audio file. Uses the description.Waveform
        /// property to obtain the data for the waveform.
        /// </summary>
        /// <param name="description">Description to create waveform for.</param>
        /// <param name="bounds">Size of the image to create.</param>
        /// <param name="canvasWidth">The width of the canvas that will contain this image.</param>
        /// <returns>A bitmap of the description's waveform.</returns>
        public static RenderTargetBitmap CreateDescriptionWaveForm(Description description, Rect bounds,
            double canvasWidth)
        {
            if (bounds.Width <= 1 || bounds.Height <= 1)
                return null;

            if (description.Waveform == null)
                description.GenerateWaveForm();

            var drawingVisual = new DrawingVisual();

            using (var dc = drawingVisual.RenderOpen())
            {
                var data = description.Waveform.Data;

                double samplesPerPixel = Math.Max(data.Count / canvasWidth, 1);
                double middle = bounds.Height / 2;
                double yscale = middle;

                double samplesPerSecond = (description.Waveform.Header.SampleRate *
                    (description.Waveform.Header.BlockAlign / (double)description.Waveform.SampleRatio));

                var waveformLineGroup = new GeometryGroup();

                int endPixel = (int)bounds.Width;

                for (int pixel = 0; pixel <= endPixel; pixel++)
                {
                    double offsetTime = (description.Duration / (bounds.Width * Milliseconds.PerSecond))
                        * pixel;
                    double sampleStart = Math.Max(samplesPerSecond * offsetTime, 0);

                    if (sampleStart + samplesPerPixel < data.Count)
                    {
                        var range = data.GetRange((int)sampleStart, (int)samplesPerPixel);

                        double max = (double)range.Max() / short.MaxValue;
                        double min = (double)range.Min() / short.MaxValue;

                        waveformLineGroup.Children.Add(new LineGeometry
                        {
                            StartPoint = new Point(pixel, middle + max * yscale),
                            EndPoint = new Point(pixel, middle + min * yscale),
                        });
                    }
                }

                waveformLineGroup.Freeze();
                dc.DrawGeometry(Brushes.Black, LinePen, waveformLineGroup);
            }

            var bitmap = new RenderTargetBitmap((int)bounds.Width, (int)bounds.Height, DefaultDpi,
                DefaultDpi, PixelFormats.Pbgra32);
            bitmap.Render(drawingVisual);
            bitmap.Freeze();

            description.WaveformImage = bitmap;

            return bitmap;
        }
        private static UIElement VisualizeVectors(Point[] points, Vector[] vectors, double[] radii)
        {
            Contract.Requires(points.Length == vectors.Length);
            var n = points.Length;

            var geometryGroup = new GeometryGroup
            {
                Children = new GeometryCollection(
                    from i in Enumerable.Range(0, n)
                    let pc = points[i]
                    let pleft = pc - radii[i] * vectors[i]
                    let pright = pc + radii[i] * vectors[i]
                    from p in new Point[] { pleft, pright }
                    select new LineGeometry { StartPoint = pc, EndPoint = p }
                ),
            };
            geometryGroup.Freeze();

            return new Path { Data = geometryGroup, Stroke = Brushes.Blue, StrokeThickness = 1, };
        }
        private static UIElement VisualizeMatch(Point[] left, Point[] right)
        {
            Contract.Requires(left.Length == right.Length);
            int n = left.Length;

            var geometry = new GeometryGroup();
            for (int i = 0; i < n; ++i)
            {
                var l = left[i];
                var r = right[i];
                geometry.Children.Add(new EllipseGeometry(l, 2, 2));
                geometry.Children.Add(new EllipseGeometry(r, 2, 2));
                geometry.Children.Add(new LineGeometry(l, r));
            }
            geometry.Freeze();

            return new Path
            {
                Stroke = Brushes.Blue,
                Fill = new SolidColorBrush { Color = Colors.Blue, Opacity = 0.2 },
                Data = geometry,
            };
        }
Пример #4
0
        /// <summary>
        /// Draw the hatches and the transparent area where isn't covering the elements.
        /// </summary>
        /// <param name="drawingContext"></param>
        private void DrawBackgound(DrawingContext drawingContext)
        {
            PathGeometry hatchGeometry = null;
            Geometry rectGeometry = null;

            int count = _elementsBounds.Count;
            if ( count != 0 )
            {
                // Create a union collection of the element regions.
                for ( int i = 0; i < count; i++ )
                {
                    Rect hatchRect = _elementsBounds[i];

                    if ( hatchRect.IsEmpty )
                    {
                        continue;
                    }

                    hatchRect.Inflate(HatchBorderMargin / 2, HatchBorderMargin / 2);

                    if ( hatchGeometry == null )
                    {
                        PathFigure path = new PathFigure();
                        path.StartPoint = new Point(hatchRect.Left, hatchRect.Top);

                        PathSegmentCollection segments = new PathSegmentCollection();
                        
                        PathSegment line = new LineSegment(new Point(hatchRect.Right, hatchRect.Top), true); 
                        line.Freeze();
                        segments.Add(line);
                        
                        line = new LineSegment(new Point(hatchRect.Right, hatchRect.Bottom), true); 
                        line.Freeze();
                        segments.Add(line);

                        line = new LineSegment(new Point(hatchRect.Left, hatchRect.Bottom), true);
                        line.Freeze();
                        segments.Add(line);

                        line = new LineSegment(new Point(hatchRect.Left, hatchRect.Top), true);
                        line.Freeze();
                        segments.Add(line);

                        segments.Freeze();
                        path.Segments = segments;

                        path.IsClosed = true;
                        path.Freeze();

                        hatchGeometry = new PathGeometry();
                        hatchGeometry.Figures.Add(path);
                    }
                    else
                    {
                        rectGeometry = new RectangleGeometry(hatchRect);
                        rectGeometry.Freeze();

                        hatchGeometry = Geometry.Combine(hatchGeometry, rectGeometry, GeometryCombineMode.Union, null);
                    }
                }
            }

            // Then, create a region which equals to "SelectionFrame - element1 bounds - element2 bounds - ..."
            GeometryGroup backgroundGeometry = new GeometryGroup( );
            GeometryCollection geometryCollection = new GeometryCollection();

            // Add the entile rectanlge to the group.
            rectGeometry = new RectangleGeometry(new Rect(0, 0, RenderSize.Width, RenderSize.Height));
            rectGeometry.Freeze();
            geometryCollection.Add(rectGeometry);

            // Add the union of the element rectangles. Then the group will do oddeven operation.
            Geometry outlineGeometry = null;

            if ( hatchGeometry != null )
            {
                hatchGeometry.Freeze();

                outlineGeometry = hatchGeometry.GetOutlinedPathGeometry();
                outlineGeometry.Freeze();
                if ( count == 1 && ((InkCanvasInnerCanvas)AdornedElement).InkCanvas.GetSelectedStrokes().Count == 0 )
                {
                    geometryCollection.Add(outlineGeometry);
                }
            }

            geometryCollection.Freeze();
            backgroundGeometry.Children = geometryCollection;
            backgroundGeometry.Freeze();

            // Then, draw the region which may contain holes so that the elements cannot be covered.
            // After that, the underneath elements can receive the messages.
#if DEBUG_OUTPUT
            // Draw the debug feedback
            drawingContext.DrawGeometry(new SolidColorBrush(Color.FromArgb(128, 255, 255, 0)), null, backgroundGeometry);
#else
            drawingContext.DrawGeometry(Brushes.Transparent, null, backgroundGeometry);
#endif

            // At last, draw the hatch borders
            if ( outlineGeometry != null )
            {
                drawingContext.DrawGeometry(null, _hatchPen, outlineGeometry);
            }
        }
Пример #5
0
        public void CreateDotChartGeometry(ICollection dt, double _maxData, double chartHeight, double chartWidth)
        {
            _children.Clear();
            stopWatch.Restart();

            var barWidth = SetBarWidth(dt.Count, chartWidth);
            var ellipses = new GeometryGroup();

            // For each row in the datasource
            double centerX = _axis_start;
            foreach (var el in dt)
            {
                // Calculate bar value.
                var height = Convert.ToDouble(el) * (chartHeight - _axis_start) / _maxData;
                centerX += barWidth;
                ellipses.Children.Add(
                    new EllipseGeometry(new Point(centerX, chartHeight - height - _axis_start), 1, 1)
                    );
            }
            ellipses.Freeze();

            var visual = new DrawingVisual();
            using (var dc = visual.RenderOpen())
            {
                dc.DrawGeometry(null, _chartPen, ellipses);
                stopWatch.Stop();

                var elapsedTime = String.Format("{0} - {1} - {2}", MethodBase.GetCurrentMethod().Name, dt.Count, stopWatch.ElapsedTicks);

                dc.DrawText(
                    new FormattedText(elapsedTime, CultureInfo.InvariantCulture, FlowDirection.LeftToRight, new Typeface("Verdana"),
                                      12, Brushes.LightGreen), new Point(10, 10));

            }
            _children.Add(visual);
        }
Пример #6
0
        /// <summary>
        /// Draws the waveform for the current window of sound and adds it to the AudioCanvas.
        /// </summary>
        public void DrawWaveForm()
        {
            if (_viewModel == null || _viewModel.Waveform == null || Width == 0 || VisibleWidth == 0
                || _viewModel.Player.CurrentState == LiveDescribeVideoStates.VideoNotLoaded)
            {
                ResetImageOnCanvas(_waveformImage);
                return;
            }

            var data = _viewModel.Waveform.Data;
            double samplesPerPixel = Math.Max(data.Count / Width, 1);
            double middle = ActualHeight / 2;
            double yscale = middle;

            int ratio = _viewModel.Waveform.Header.Channels == 2 ? 40 : 80;
            double samplesPerSecond =
                (_viewModel.Waveform.Header.SampleRate * (_viewModel.Waveform.Header.BlockAlign / (double)ratio));

            var waveformLineGroup = new GeometryGroup();

            double absMin = 0;

            int endPixel = (int)VisibleX + (int)VisibleWidth;

            for (int pixel = (int)VisibleX; pixel <= endPixel; pixel++)
            {
                double offsetTime = (VideoDurationMsec / (Width * Milliseconds.PerSecond))
                    * pixel;
                double sampleStart = samplesPerSecond * offsetTime;

                if (sampleStart + samplesPerPixel < data.Count)
                {
                    var range = data.GetRange((int)sampleStart, (int)samplesPerPixel);

                    double max = (double)range.Max() / short.MaxValue;
                    double min = (double)range.Min() / short.MaxValue;

                    waveformLineGroup.Children.Add(new LineGeometry
                    {
                        StartPoint = new Point(pixel, middle + max * yscale),
                        EndPoint = new Point(pixel, middle + min * yscale),
                    });

                    absMin = Math.Min(absMin, min);
                }
            }

            waveformLineGroup.Freeze();

            var dv = new DrawingVisual();
            using (var drawingContext = dv.RenderOpen())
            {
                drawingContext.DrawGeometry(Brushes.Black, LinePen, waveformLineGroup);
            }

            DisplayVisualOnCanvas(_waveformImage, dv, middle + absMin * yscale);
        }
Пример #7
0
 internal static Geometry MarkersAsGeometry(Curve curve, MatrixTransform graphToCanvas, MarkersType markersType, double markersSize)
 {
     double xScale = graphToCanvas.Matrix.M11;
     double xOffset = graphToCanvas.Matrix.OffsetX;
     double yScale = graphToCanvas.Matrix.M22;
     double yOffset = graphToCanvas.Matrix.OffsetY;
     GeometryGroup markers = new GeometryGroup();
     double width = Math.Abs(markersSize);
     double height = Math.Abs(markersSize);
     Geometry markerGeometry = LegendMarkerGeometry(markersType, markersSize);
     if (markerGeometry == null) return null;
     markerGeometry.Freeze();
     for (int i = 0; i < curve.xTransformed.Length; ++i)
     {
         if (!curve.includeMarker[i]) continue;
         double xCanvas = curve.xTransformed[i] * xScale + xOffset;
         double yCanvas = curve.yTransformed[i] * yScale + yOffset;
         Geometry newMarker = markerGeometry.Clone();
         newMarker.Transform = new TranslateTransform(xCanvas, yCanvas);
         markers.Children.Add(newMarker);
     }
     markers.Freeze();
     return markers;
 }
        private UIElement VisualizePoints(Point[] point)
        {
            var path = new Path();
            path.Stroke = Brushes.Blue;
            path.StrokeThickness = 1;
            path.Fill = new SolidColorBrush { Color = Colors.Blue, Opacity = 0.2 };

            var geometry = new GeometryGroup();
            foreach (var pnt in point.Skip(1).Take(point.Length - 2))
                geometry.Children.Add(new EllipseGeometry(pnt, 2, 2));

            geometry.Children.Add(new EllipseGeometry(point[0], 5, 5));
            geometry.Children.Add(new EllipseGeometry(point[point.Length - 1], 5, 5));

            geometry.Freeze();
            path.Data = geometry;

            return path;
        }
Пример #9
0
        private void renderColumns(List<int> columns, Brush brush, Image image)
        {
            GeometryGroup group = new GeometryGroup();
            group.Children.Add(new RectangleGeometry(new Rect(0, 0, 0, 0)));
            renderColumnsForLines(group, columns, _view.TextViewLines);
            group.Freeze();

            Drawing drawing = new GeometryDrawing(brush, _emptyPen, group);
            drawing.Freeze();

            DrawingImage drawingImage = new DrawingImage(drawing);
            drawingImage.Freeze();

            image.Source = drawingImage;

            Canvas.SetLeft(image, _view.ViewportLeft + group.Bounds.Left);
            Canvas.SetTop(image, _view.ViewportTop + group.Bounds.Top);
        }
Пример #10
0
        public void Show(Message message)
        {
            var query = from entry in message.Attachments where entry.Score.HasValue select entry.Score.Value;
            bool isRecyclable = true;

            if (query.Any())
            {
                List<double> scoreList = query.ToList();

                this.maxScore = scoreList.Max<double>();
                this.minScore = scoreList.Min<double>();
                this.isReversed = false;
                bool isAvailable = false;

                for (int i = 0; i < scoreList.Count - 1; i++)
                {
                    if (scoreList[i] != scoreList[i + 1])
                    {
                        isAvailable = true;

                        break;
                    }
                }

                if (isAvailable)
                {
                    int counter = 0;

                    for (int i = 0; i < scoreList.Count - 1; i++)
                    {
                        if (scoreList[i] >= scoreList[i + 1])
                        {
                            counter++;
                        }
                    }

                    if (counter == scoreList.Count - 1)
                    {
                        this.isReversed = true;
                    }
                }

                if (this.isReversed)
                {
                    this.thresholdScore = this.nextThresholdScore = this.minScore;
                }
                else
                {
                    this.thresholdScore = this.nextThresholdScore = this.maxScore;
                }
            }

            this.messageCollection.Add(message);

            if (this.messageCollection.Count > this.maxHistory)
            {
                List<Message> messageList = this.messageCollection.ToList();

                for (int i = 0; i < messageList.Count - this.maxHistory; i++)
                {
                    Message m = messageList[i];
                    Size size1 = GetBalloonSize(m);
                    double height = 0;

                    foreach (object o in m)
                    {
                        Entry entry = o as Entry;

                        if (entry != null)
                        {
                            Size size2 = GetInspectorSize(entry);

                            if (size2.Height > height)
                            {
                                height = size2.Height;
                            }
                        }
                    }

                    if (m.HasAttachments)
                    {
                        double h = m.Attachments.Max<Entry, double>(entry => GetInspectorSize(entry).Height);

                        if (h > height)
                        {
                            height = h;
                        }
                    }

                    if (height > 0)
                    {
                        height -= 11;
                    }

                    if (size1.Width * this.maxScale == this.LayoutRoot.Width && (size1.Height + height) * this.maxScale == this.LayoutRoot.Height)
                    {
                        isRecyclable = false;

                        break;
                    }
                }

                messageList.RemoveRange(0, messageList.Count - this.maxHistory);

                this.messageCollection.Clear();

                messageList.ForEach(delegate (Message m)
                {
                    this.messageCollection.Add(m);
                });
            }

            if (this.messageCollection.Count - 1 >= 0)
            {
                this.historyPoint = new Nullable<int>(this.messageCollection.Count - 1);
            }

            Size balloonSize = GetBalloonSize(message, ref this.messageIsScrollable);
            double maxHeight = 0;

            foreach (object o in message)
            {
                Entry entry = o as Entry;

                if (entry != null)
                {
                    Size size = GetInspectorSize(entry);

                    if (size.Height > maxHeight)
                    {
                        maxHeight = size.Height;
                    }
                }
            }

            if (message.HasAttachments)
            {
                double height = message.Attachments.Max<Entry, double>(entry => GetInspectorSize(entry).Height);

                if (height > maxHeight)
                {
                    maxHeight = height;
                }
            }

            if (maxHeight > 0)
            {
                maxHeight -= 11;
            }

            Size maxSize = new Size(balloonSize.Width, balloonSize.Height + maxHeight);

            if (isRecyclable && this.LayoutRoot.Width >= maxSize.Width * this.maxScale && this.LayoutRoot.Height >= maxSize.Height * this.maxScale)
            {
                maxSize.Width = this.LayoutRoot.Width;
                maxSize.Height = this.LayoutRoot.Height;
            }
            else
            {
                foreach (Message m in from m in this.messageCollection where m != message select m)
                {
                    Size size1 = GetBalloonSize(m);
                    double height = 0;

                    foreach (object o in m)
                    {
                        Entry entry = o as Entry;

                        if (entry != null)
                        {
                            Size size2 = GetInspectorSize(entry);

                            if (size2.Height > height)
                            {
                                height = size2.Height;
                            }
                        }
                    }

                    if (m.HasAttachments)
                    {
                        double h = m.Attachments.Max<Entry, double>(entry => GetInspectorSize(entry).Height);

                        if (h > height)
                        {
                            height = h;
                        }
                    }

                    if (height > 0)
                    {
                        height -= 11;
                    }

                    if (size1.Width > maxSize.Width)
                    {
                        maxSize.Width = size1.Width;
                    }

                    if (size1.Height + height > maxSize.Height)
                    {
                        maxSize.Height = size1.Height + height;
                    }
                }

                maxSize.Width = maxSize.Width * this.maxScale;
                maxSize.Height = maxSize.Height * this.maxScale;
            }

            this.sourceSize = this.targetSize = balloonSize;
            this.targetOpacity = 1;
            this.targetScaleX = this.targetScaleY = 1;

            Geometry roundedRectangleGeometry = CreateRoundedRectangleGeometry(new Rect(0, 0, this.sourceSize.Width, this.sourceSize.Height - 11 + 4), 8, 8);
            Geometry balloonGeometry = CreateBalloonGeometry(new Rect(4, 4, this.sourceSize.Width - 4 * 2, this.sourceSize.Height - 4), 8 * 3 / 4, 8 * 3 / 4);
            Geometry highlightGeometry = CreateHighlightGeometry(new Rect(0, 0, this.sourceSize.Width, this.baseHeaderHeight + 8), 8, 8);
            Geometry highlightLineGeometry = CreateHighlightLineGeometry(new Rect(0, 0, this.sourceSize.Width, 8), 8, 8);

            if (roundedRectangleGeometry.CanFreeze)
            {
                roundedRectangleGeometry.Freeze();
            }

            if (balloonGeometry.CanFreeze)
            {
                balloonGeometry.Freeze();
            }

            if (highlightGeometry.CanFreeze)
            {
                highlightGeometry.Freeze();
            }

            if (highlightLineGeometry.CanFreeze)
            {
                highlightLineGeometry.Freeze();
            }

            GeometryGroup geometryGroup = new GeometryGroup();

            geometryGroup.FillRule = FillRule.Nonzero;
            geometryGroup.Children.Add(roundedRectangleGeometry);
            geometryGroup.Children.Add(balloonGeometry);

            if (geometryGroup.CanFreeze)
            {
                geometryGroup.Freeze();
            }

            RadialGradientBrush radialGradientBrush = new RadialGradientBrush();
            GradientStop gradientStop1 = new GradientStop(Color.FromArgb(Byte.MaxValue, Byte.MaxValue, Byte.MaxValue, Byte.MaxValue), 0);
            GradientStop gradientStop2 = new GradientStop(Color.FromArgb(Byte.MaxValue, 0, 0, 0), 1);

            radialGradientBrush.GradientOrigin = new Point(0.5, 0);
            radialGradientBrush.Center = new Point(0.5, 0);
            radialGradientBrush.RadiusX = 0.5;
            radialGradientBrush.RadiusY = this.sourceSize.Width / 2 < this.sourceSize.Height - this.baseFooterHeight ? this.sourceSize.Width / 2 / this.sourceSize.Height : (this.sourceSize.Height - this.baseFooterHeight) / this.sourceSize.Height;
            radialGradientBrush.Opacity = 0.1;
            radialGradientBrush.GradientStops.Add(gradientStop1);
            radialGradientBrush.GradientStops.Add(gradientStop2);

            if (radialGradientBrush.CanFreeze)
            {
                radialGradientBrush.Freeze();
            }

            this.Width = this.LayoutRoot.Width = maxSize.Width;
            this.Height = this.LayoutRoot.Height = maxSize.Height;
            this.OuterPath.Width = roundedRectangleGeometry.Bounds.Right;
            this.OuterPath.Height = roundedRectangleGeometry.Bounds.Bottom;
            this.OuterPath.Data = roundedRectangleGeometry;
            this.InnerPath.Width = balloonGeometry.Bounds.Right;
            this.InnerPath.Height = balloonGeometry.Bounds.Bottom;
            this.InnerPath.Data = balloonGeometry;
            this.OverlayPath.Width = geometryGroup.Bounds.Right;
            this.OverlayPath.Height = geometryGroup.Bounds.Bottom;
            this.OverlayPath.Data = geometryGroup;
            this.OverlayPath.Fill = radialGradientBrush;
            this.HighlightPath.Width = highlightGeometry.Bounds.Right;
            this.HighlightPath.Height = highlightGeometry.Bounds.Bottom;
            this.HighlightPath.Data = highlightGeometry;
            this.HighlightLinePath.Width = highlightLineGeometry.Bounds.Right;
            this.HighlightLinePath.Height = highlightLineGeometry.Bounds.Bottom;
            this.HighlightLinePath.Data = highlightLineGeometry;
            this.Canvas.Width = this.sourceSize.Width;
            this.Canvas.Height = this.sourceSize.Height;
            this.ScaleTransform.CenterX = this.sourceSize.Width / 2;
            this.ScaleTransform.CenterY = this.sourceSize.Height;

            Canvas.SetLeft(this.Canvas, (maxSize.Width - this.sourceSize.Width) / 2);
            Canvas.SetTop(this.Canvas, maxSize.Height - this.sourceSize.Height);
            Canvas.SetLeft(this.FilterImage, this.sourceSize.Width - 14);
            Canvas.SetLeft(this.ScrollImage, this.sourceSize.Width - 14);
            Canvas.SetLeft(this.CloseImage, this.sourceSize.Width - 17);
            Canvas.SetLeft(this.BackImage, this.sourceSize.Width - 30);
            Canvas.SetLeft(this.UpImage, this.sourceSize.Width - 17);
            Canvas.SetTop(this.UpImage, this.sourceSize.Height - 32);
            Canvas.SetLeft(this.DownImage, this.sourceSize.Width - 17);
            Canvas.SetTop(this.DownImage, this.sourceSize.Height - 21);

            Show();
        }
Пример #11
0
        private void OnRendering(object sender, EventArgs e)
        {
            TimeSpan ts = ((RenderingEventArgs)e).RenderingTime;
            double frameRate = 1000 / (ts - this.lastRenderingTime).TotalMilliseconds;

            if (frameRate <= this.frameRate)
            {
                this.lastRenderingTime = ts;

                if (frameRate >= 1)
                {
                    int limit = (int)Math.Round(this.frameRate);

                    this.frameRateList.Add(frameRate > this.frameRate / 10 ? frameRate : this.frameRate / 10);

                    if (this.frameRateList.Count > limit)
                    {
                        this.frameRateList.RemoveRange(0, this.frameRateList.Count - limit);
                    }

                    if (this.IsVisible)
                    {
                        double averageFrameRate = this.frameRateList.Average();
                        bool isReady = this.isReady;

                        if (this.messageCollection.Count > 0 && this.historyPoint.HasValue && this.historyPoint.Value < this.messageCollection.Count && this.targetSize.Width == this.Canvas.Width && this.targetSize.Height == this.Canvas.Height && this.inspectorFadeStep == null && this.inspectorEntry != this.nextInspectorEntry && this.nextInspectorEntry == null)
                        {
                            Size size = GetBalloonSize(this.messageCollection[this.historyPoint.Value], ref this.messageIsScrollable);

                            this.inspectorEntry = this.nextInspectorEntry;

                            if (size.Width != this.targetSize.Width || size.Height != this.targetSize.Height)
                            {
                                this.targetSize = size;

                                if (this.targetSize.Width != this.Canvas.Width || this.targetSize.Height != this.Canvas.Height)
                                {
                                    this.sourceSize.Width = this.Canvas.Width;
                                    this.sourceSize.Height = this.Canvas.Height;
                                    this.resizeStep = 0;
                                }
                            }
                        }

                        if (this.messageCollection.Count > 0 && this.nextHistoryPoint.HasValue && this.nextHistoryPoint.Value < this.messageCollection.Count && !this.isReady && this.targetSize.Width == this.Canvas.Width && this.targetSize.Height == this.Canvas.Height)
                        {
                            Message message = this.messageCollection[this.nextHistoryPoint.Value];

                            this.historyPoint = this.nextHistoryPoint;
                            this.nextHistoryPoint = null;

                            var query = from entry in message.Attachments where entry.Score.HasValue select entry.Score.Value;

                            if (query.Any())
                            {
                                List<double> scoreList = query.ToList();

                                this.maxScore = scoreList.Max<double>();
                                this.minScore = scoreList.Min<double>();
                                this.isReversed = false;
                                bool enable = false;

                                for (int i = 0; i < scoreList.Count - 1; i++)
                                {
                                    if (scoreList[i] != scoreList[i + 1])
                                    {
                                        enable = true;

                                        break;
                                    }
                                }

                                if (enable)
                                {
                                    int counter = 0;

                                    for (int i = 0; i < scoreList.Count - 1; i++)
                                    {
                                        if (scoreList[i] >= scoreList[i + 1])
                                        {
                                            counter++;
                                        }
                                    }

                                    if (counter == scoreList.Count - 1)
                                    {
                                        this.isReversed = true;
                                    }
                                }

                                if (this.isReversed)
                                {
                                    this.thresholdScore = this.nextThresholdScore = this.minScore;
                                }
                                else
                                {
                                    this.thresholdScore = this.nextThresholdScore = this.maxScore;
                                }
                            }

                            Size size = GetBalloonSize(message, ref this.messageIsScrollable);

                            if (size.Width != this.targetSize.Width || size.Height != this.targetSize.Height)
                            {
                                this.targetSize = size;

                                if (this.targetSize.Width != this.Canvas.Width || this.targetSize.Height != this.Canvas.Height)
                                {
                                    this.sourceSize.Width = this.Canvas.Width;
                                    this.sourceSize.Height = this.Canvas.Height;
                                    this.resizeStep = 0;
                                }
                            }
                        }

                        if (this.sourceOpacity == this.targetOpacity && this.targetOpacity > 0 && this.sourceScaleX == this.targetScaleX && this.targetScaleX > 0 && this.sourceScaleY == this.targetScaleY && this.targetScaleY > 0)
                        {
                            if (this.targetSize.Width == this.Canvas.Width && this.targetSize.Height == this.Canvas.Height)
                            {
                                this.isReady = true;
                            }
                        }
                        else
                        {
                            this.popupStep += 1 / (averageFrameRate / 2);

                            if (this.popupStep >= 1)
                            {
                                this.popupStep = 1;
                                this.Canvas.Opacity = this.sourceOpacity = this.targetOpacity;
                                this.ScaleTransform.ScaleX = this.sourceScaleX = this.targetScaleX;
                                this.ScaleTransform.ScaleY = this.sourceScaleY = this.targetScaleY;
                            }
                            else
                            {
                                if (this.targetOpacity > this.sourceOpacity)
                                {
                                    this.Canvas.Opacity = this.sourceOpacity + (this.targetOpacity - this.sourceOpacity) * Math.Sin((this.popupStep > 0.5 ? 0.5 : this.popupStep) * Math.PI);
                                }
                                else if (this.targetOpacity < this.sourceOpacity)
                                {
                                    this.Canvas.Opacity = this.targetOpacity + (this.sourceOpacity - this.targetOpacity) * Math.Cos(this.popupStep / 2 * Math.PI);
                                }

                                if (this.targetScaleX > this.sourceScaleX || this.targetScaleY > this.sourceScaleY)
                                {
                                    if (this.popupStep > 0.5)
                                    {
                                        this.ScaleTransform.ScaleX = this.targetScaleX + (this.targetScaleX * this.maxScale - this.targetScaleX) * Math.Sin(this.popupStep * Math.PI);
                                        this.ScaleTransform.ScaleY = this.targetScaleY + (this.targetScaleY * this.maxScale - this.targetScaleY) * Math.Sin(this.popupStep * Math.PI);
                                    }
                                    else
                                    {
                                        this.ScaleTransform.ScaleX = this.sourceScaleX + (this.targetScaleX * this.maxScale - this.sourceScaleX) * Math.Sin(this.popupStep * Math.PI);
                                        this.ScaleTransform.ScaleY = this.sourceScaleY + (this.targetScaleY * this.maxScale - this.sourceScaleY) * Math.Sin(this.popupStep * Math.PI);
                                    }
                                }
                                else if (this.targetScaleX < this.sourceScaleX || this.targetScaleY < this.sourceScaleY)
                                {
                                    this.ScaleTransform.ScaleX = this.targetScaleX + (this.sourceScaleX - this.targetScaleX) * Math.Cos(this.popupStep / 2 * Math.PI);
                                    this.ScaleTransform.ScaleY = this.targetScaleY + (this.sourceScaleY - this.targetScaleY) * Math.Cos(this.popupStep / 2 * Math.PI);
                                }
                            }
                        }

                        if (this.isReady)
                        {
                            if (this.messageCollection.Count > 0 && this.historyPoint.HasValue && this.historyPoint.Value < this.messageCollection.Count)
                            {
                                Lazy<List<Point>> inlinePointList = new Lazy<List<Point>>(() =>
                                {
                                    Point location = new Point(0, 0);
                                    bool isBreaked = true;
                                    List<Point> pointList = new List<Point>();
                                    bool isReseted = true;

                                    foreach (object o in this.messageCollection[this.historyPoint.Value])
                                    {
                                        string inline = o as string;
                                        Brush brush = this.textBrush;
                                        Dictionary<int, int> dictionary = new Dictionary<int, int>();
                                        StringBuilder lineStringBuilder = new StringBuilder();

                                        if (inline == null)
                                        {
                                            Entry entry = o as Entry;

                                            if (entry == null)
                                            {
                                                inline = o.ToString();
                                            }
                                            else
                                            {
                                                inline = entry.Title;
                                                brush = this.linkBrush;
                                            }
                                        }

                                        foreach (System.Text.RegularExpressions.Match match in System.Text.RegularExpressions.Regex.Matches(inline, @"[\p{IsBasicLatin}-[\s]]+\s?"))
                                        {
                                            dictionary.Add(match.Index, match.Length);
                                        }

                                        for (int i = 0; i < inline.Length; i++)
                                        {
                                            int length;

                                            if (dictionary.TryGetValue(i, out length) && location.X + Math.Ceiling(new FormattedText(String.Concat(lineStringBuilder.ToString(), inline.Substring(i, length)), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush).WidthIncludingTrailingWhitespace) > this.maxMessageSize.Width && !isReseted)
                                            {
                                                if (lineStringBuilder.Length > 0)
                                                {
                                                    pointList.Add(new Point(location.X + Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush).WidthIncludingTrailingWhitespace), location.Y));
                                                }

                                                lineStringBuilder.Clear();
                                                location.X = 0;
                                                location.Y += this.lineHeight;
                                                isBreaked = true;
                                            }

                                            lineStringBuilder.Append(inline[i]);

                                            if (lineStringBuilder.ToString().EndsWith(Environment.NewLine, StringComparison.Ordinal))
                                            {
                                                lineStringBuilder.Remove(lineStringBuilder.ToString().LastIndexOf(Environment.NewLine, StringComparison.Ordinal), Environment.NewLine.Length);

                                                if (lineStringBuilder.Length > 0)
                                                {
                                                    pointList.Add(new Point(location.X + Math.Ceiling(new FormattedText(lineStringBuilder.ToString().Substring(0, lineStringBuilder.Length), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush).WidthIncludingTrailingWhitespace), location.Y));
                                                    lineStringBuilder.Remove(0, lineStringBuilder.Length);
                                                }
                                                else
                                                {
                                                    pointList.Add(location);
                                                }

                                                pointList.Add(new Point(Double.NaN, location.Y));
                                                location.X = 0;
                                                location.Y += this.lineHeight;
                                                isBreaked = true;
                                                isReseted = true;
                                            }
                                            else
                                            {
                                                if (location.X + Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush).WidthIncludingTrailingWhitespace) > this.maxMessageSize.Width)
                                                {
                                                    if (lineStringBuilder.Length - 1 > 0)
                                                    {
                                                        pointList.Add(new Point(location.X + Math.Ceiling(new FormattedText(lineStringBuilder.ToString().Substring(0, lineStringBuilder.Length - 1), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush).WidthIncludingTrailingWhitespace), location.Y));
                                                        lineStringBuilder.Remove(0, lineStringBuilder.Length - 1);
                                                    }
                                                    else
                                                    {
                                                        pointList.Add(location);
                                                    }

                                                    location.X = 0;
                                                    location.Y += this.lineHeight;
                                                    isBreaked = true;
                                                    isReseted = true;
                                                }
                                                else
                                                {
                                                    isReseted = false;
                                                }
                                            }
                                        }

                                        if (lineStringBuilder.Length > 0)
                                        {
                                            location.X += Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush).WidthIncludingTrailingWhitespace);
                                            pointList.Add(location);
                                            isBreaked = false;
                                            isReseted = false;
                                        }
                                    }

                                    if (isBreaked)
                                    {
                                        pointList.Add(location);
                                    }

                                    return pointList;
                                });
                                bool isTyped = (isReady && this.nextHistoryPoint.HasValue ? this.messageCollection[this.historyPoint.Value].Cast<object>() : this.messageCollection[this.historyPoint.Value].Cast<object>().Concat(new object[] { null })).SequenceEqual(this.inlineList.Cast<object>());
                                bool isFragmented = false;
                                bool isScrolled = false;
                                int paddingLines = 0;
                                bool waitRequired = false;
                                bool updateLayoutRequired = false;

                                if (isReady && this.nextHistoryPoint.HasValue && this.targetMessageLength != 0 && this.embedColorStepDictionary.Count == 0)
                                {
                                    this.targetMessageLength = 0;
                                    this.messageTypeTimer.Interval = TimeSpan.FromSeconds(1 / this.messageCollection[this.historyPoint.Value].Speed / 2);
                                    this.messageTypeTimer.Start();
                                }
                                else if ((!isReady || !this.nextHistoryPoint.HasValue) && this.targetMessageLength != this.messageCollection[this.historyPoint.Value].Text.Length)
                                {
                                    this.targetMessageLength = this.messageCollection[this.historyPoint.Value].Text.Length;
                                    this.messageTypeTimer.Interval = TimeSpan.FromSeconds(1 / this.messageCollection[this.historyPoint.Value].Speed);
                                    this.messageTypeTimer.Start();
                                }

                                if (this.sourceScrollPosition == this.targetScrollPosition)
                                {
                                    Nullable<double> totalSelectedPosition = null;

                                    if (this.selectedPositionQueue.Count > 0)
                                    {
                                        double position = 0;

                                        do
                                        {
                                            position += this.selectedPositionQueue.Dequeue();
                                        } while (this.selectedPositionQueue.Count > 0);

                                        totalSelectedPosition = new Nullable<double>(position);
                                    }

                                    if (totalSelectedPosition.HasValue || this.scrollQueue.Count > 0)
                                    {
                                        int messageLines = inlinePointList.Value.Aggregate<Point, HashSet<double>>(new HashSet<double>(), (hashSet, point) =>
                                        {
                                            if (!hashSet.Contains(point.Y))
                                            {
                                                hashSet.Add(point.Y);
                                            }

                                            return hashSet;
                                        }).Count;
                                        int maxLines = messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count < this.numberOfLines ? messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count : this.numberOfLines;
                                        double position = this.targetScrollPosition;
                                        bool isCountable = false;

                                        while (this.scrollQueue.Count > 0)
                                        {
                                            this.targetScrollPosition += this.scrollQueue.Dequeue();
                                        }

                                        if (this.selectedPosition.HasValue && totalSelectedPosition.HasValue && (this.selectedPosition.Value + totalSelectedPosition.Value < 0 || this.targetScrollPosition >= messageLines + Math.Floor(this.selectedPosition.Value + totalSelectedPosition.Value + 1) || this.targetScrollPosition + maxLines < messageLines + Math.Floor(this.selectedPosition.Value + totalSelectedPosition.Value + 1)))
                                        {
                                            this.targetScrollPosition += totalSelectedPosition.Value;
                                        }

                                        if (this.targetScrollPosition < 0)
                                        {
                                            this.targetScrollPosition = 0;
                                        }
                                        else if (this.targetScrollPosition + maxLines > messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count)
                                        {
                                            this.targetScrollPosition = messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count - maxLines;

                                            if (position == this.targetScrollPosition && this.messageCollection[this.historyPoint.Value].HasAttachments)
                                            {
                                                isCountable = true;
                                            }
                                        }

                                        if (this.selectedPosition.HasValue)
                                        {
                                            double lines = totalSelectedPosition.HasValue ? this.selectedPosition.Value + totalSelectedPosition.Value : this.selectedPosition.Value;

                                            if (this.targetScrollPosition - messageLines > Math.Floor(lines))
                                            {
                                                lines = this.targetScrollPosition - messageLines;
                                            }
                                            else if (Math.Floor(lines) > this.targetScrollPosition - messageLines + maxLines - 1)
                                            {
                                                lines = this.targetScrollPosition - messageLines + maxLines - 1;
                                            }

                                            if (this.selectedPosition.Value == lines)
                                            {
                                                if (isCountable && Math.Floor(this.selectedPosition.Value) == this.messageCollection[this.historyPoint.Value].Attachments.Count - 1 && this.counterScrollStep == null)
                                                {
                                                    this.counterScrollStep = new Nullable<double>(0);
                                                }
                                            }
                                            else
                                            {
                                                this.selectedIndex = new Nullable<int>((int)Math.Floor(this.selectedPosition.Value));

                                                if (lines < 0)
                                                {
                                                    this.selectedPosition = new Nullable<double>(0);
                                                }
                                                else if (lines >= this.messageCollection[this.historyPoint.Value].Attachments.Count)
                                                {
                                                    this.selectedPosition = new Nullable<double>(this.messageCollection[this.historyPoint.Value].Attachments.Count - 1);
                                                }
                                                else
                                                {
                                                    this.selectedPosition = new Nullable<double>(lines);
                                                }
                                            }
                                        }
                                        else if (isCountable && this.counterScrollStep == null)
                                        {
                                            this.counterScrollStep = new Nullable<double>(0);
                                        }

                                        if (this.targetScrollPosition - this.sourceScrollPosition > 0)
                                        {
                                            this.scrollIndexStep = 0;
                                            isFragmented = true;
                                        }
                                        else if (this.targetScrollPosition - this.sourceScrollPosition < 0)
                                        {
                                            this.scrollIndexStep = 1;
                                            isFragmented = true;
                                        }
                                    }
                                }

                                if (this.sourceScrollPosition > this.targetScrollPosition)
                                {
                                    this.scrollIndexStep -= 1 / (averageFrameRate / 4);

                                    if (this.scrollIndexStep <= 0)
                                    {
                                        this.scrollIndexStep = 0;
                                        this.sourceScrollPosition = this.targetScrollPosition;
                                        isFragmented = true;
                                    }

                                    isScrolled = true;
                                }
                                else if (this.sourceScrollPosition < this.targetScrollPosition)
                                {
                                    this.scrollIndexStep += 1 / (averageFrameRate / 4);

                                    if (this.scrollIndexStep >= 1)
                                    {
                                        this.scrollIndexStep = 1;
                                        this.sourceScrollPosition = this.targetScrollPosition;
                                        isFragmented = true;
                                    }

                                    isScrolled = true;
                                }

                                if (this.sourceScrollPosition != this.targetScrollPosition)
                                {
                                    paddingLines = (int)Math.Ceiling(Math.Abs(this.targetScrollPosition - this.sourceScrollPosition));
                                }
                                else if (Math.Floor(this.targetScrollPosition) != Math.Ceiling(this.targetScrollPosition))
                                {
                                    paddingLines = (int)Math.Ceiling(Math.Ceiling(this.targetScrollPosition) - Math.Floor(this.targetScrollPosition));
                                }

                                if (this.counterScrollStep.HasValue)
                                {
                                    this.counterScrollStep += 1 / (averageFrameRate / 2);

                                    if (this.counterScrollStep >= 1)
                                    {
                                        this.counterScrollStep = null;
                                    }
                                }

                                if (isFragmented || !isTyped || isReady && this.nextHistoryPoint.HasValue || this.embedColorStepDictionary.Values.Any(step => isReady && this.nextHistoryPoint.HasValue && step > 0 || (!isReady || !this.nextHistoryPoint.HasValue) && step < 1) || this.embedIsScrollableHashSet.Count > 0 || this.embedScrollStepDictionary.Count > 0 || this.hoverEmbeddedIndex.HasValue && this.embedIsScrollableHashSet.Count == 0 && this.embedScrollStepDictionary.Count == 0)
                                {
                                    List<char> charList = new List<char>();
                                    Random random = new Random(Environment.TickCount);
                                    StringBuilder randomStringBuilder = new StringBuilder();
                                    string text = this.messageCollection[this.historyPoint.Value].Text.Replace(Environment.NewLine, String.Empty);
                                    int minScrollIndex = (int)Math.Floor(Math.Min(this.sourceScrollPosition, this.targetScrollPosition));
                                    int messageLines = inlinePointList.Value.Aggregate<Point, HashSet<double>>(new HashSet<double>(), (hs, point) =>
                                    {
                                        if (!hs.Contains(point.Y))
                                        {
                                            hs.Add(point.Y);
                                        }

                                        return hs;
                                    }).Count;
                                    double totalMessageHeight = (messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count) * this.lineHeight;
                                    int maxLines = messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count < this.numberOfLines ? messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count : this.numberOfLines;
                                    int usedLines = messageLines - minScrollIndex;
                                    Point baseLocation = new Point(0, -this.lineHeight * Math.Min(minScrollIndex, messageLines));
                                    Point location = new Point(0, 0);
                                    bool isReseted = true;
                                    int inlineIndex1 = 0;
                                    int inlineIndex2 = 0;
                                    int canvasIndex = 0;
                                    HashSet<UIElement> hashSet = new HashSet<UIElement>();

                                    if (usedLines > maxLines)
                                    {
                                        usedLines = maxLines;
                                    }
                                    else if (usedLines < 0)
                                    {
                                        usedLines = 0;
                                    }

                                    int actualLines = usedLines + this.messageCollection[this.historyPoint.Value].Attachments.Count;

                                    if (actualLines > maxLines)
                                    {
                                        actualLines = maxLines;
                                    }

                                    for (int i = 0; i < text.Length; i++)
                                    {
                                        if (!charList.Contains(text[i]) && !Char.IsWhiteSpace(text[i]))
                                        {
                                            charList.Add(text[i]);
                                        }
                                    }

                                    for (int i = 0; i < this.randomMessageLength; i++)
                                    {
                                        if (this.messageCollection[this.historyPoint.Value].Text.IndexOf(Environment.NewLine, i, StringComparison.Ordinal) == i)
                                        {
                                            randomStringBuilder.Append(Environment.NewLine);
                                            i += Environment.NewLine.Length - 1;
                                        }
                                        else if (charList.Count > 0)
                                        {
                                            randomStringBuilder.Append(charList[random.Next(charList.Count)]);
                                        }
                                    }

                                    if (isFragmented || (!isTyped || isReady && this.nextHistoryPoint.HasValue))
                                    {
                                        int index = 0;
                                        StringBuilder stringBuilder = new StringBuilder();

                                        this.inlineList.Clear();

                                        if (!isTyped && (!isReady || !this.nextHistoryPoint.HasValue))
                                        {
                                            waitRequired = true;
                                        }

                                        foreach (object o in this.messageCollection[this.historyPoint.Value])
                                        {
                                            string s = o as string;

                                            if (s == null)
                                            {
                                                Entry entry = o as Entry;

                                                if (entry == null)
                                                {
                                                    s = o.ToString();
                                                }
                                                else
                                                {
                                                    s = entry.Title;
                                                }
                                            }

                                            if (s != null)
                                            {
                                                if (index + s.Length > this.messageBuffer.Length)
                                                {
                                                    if (this.messageBuffer.Length > index)
                                                    {
                                                        stringBuilder.Append(this.messageBuffer.ToString().Substring(index, this.messageBuffer.Length - index));
                                                    }

                                                    waitRequired = false;

                                                    break;
                                                }
                                                else
                                                {
                                                    this.inlineList.Add(o);
                                                }

                                                index += s.Length;
                                            }
                                        }

                                        if (randomStringBuilder.Length > this.messageBuffer.Length)
                                        {
                                            stringBuilder.Append(randomStringBuilder.ToString().Substring(this.messageBuffer.Length, randomStringBuilder.Length - this.messageBuffer.Length));
                                            waitRequired = false;
                                        }

                                        if (stringBuilder.Length > 0)
                                        {
                                            this.inlineList.Add(stringBuilder);
                                        }

                                        if (!isReady || !this.nextHistoryPoint.HasValue)
                                        {
                                            this.inlineList.Add(null);
                                        }
                                    }

                                    this.ScrollCanvas.Width = this.MessageCanvas.Width = this.maxMessageSize.Width;
                                    this.ScrollCanvas.Height = this.lineHeight * actualLines;
                                    this.MessageCanvas.Height = this.lineHeight * (this.counterScrollStep.HasValue ? actualLines + paddingLines + 1 : actualLines + paddingLines);

                                    foreach (object obj in this.inlineList)
                                    {
                                        string inline = null;
                                        Entry entry = null;
                                        Brush brush = this.textBrush;
                                        Nullable<double> scrollStep = null;
                                        bool isMutable = false;

                                        if (obj is string)
                                        {
                                            inline = (string)obj;
                                        }
                                        else if (obj is Entry)
                                        {
                                            bool isScrollable = false;
                                            double step1;
                                            double step2;

                                            entry = (Entry)obj;
                                            inline = entry.Title;

                                            if (this.embedIsScrollableHashSet.Contains(inlineIndex1))
                                            {
                                                isScrollable = true;
                                                this.embedIsScrollableHashSet.Remove(inlineIndex1);
                                            }

                                            if (this.embedScrollStepDictionary.TryGetValue(inlineIndex1, out step1))
                                            {
                                                if (step1 == 1 && isScrollable)
                                                {
                                                    step1 = 0;
                                                }

                                                step1 += 1 / (averageFrameRate / 2);

                                                if (step1 >= 1)
                                                {
                                                    if (this.hoverEmbeddedIndex.HasValue && this.hoverEmbeddedIndex.Value == inlineIndex1)
                                                    {
                                                        scrollStep = new Nullable<double>(1);
                                                        this.embedScrollStepDictionary[inlineIndex1] = 1;
                                                    }
                                                    else
                                                    {
                                                        this.embedScrollStepDictionary.Remove(inlineIndex1);
                                                    }
                                                }
                                                else
                                                {
                                                    scrollStep = new Nullable<double>(step1);
                                                    this.embedScrollStepDictionary[inlineIndex1] = step1;
                                                }
                                            }
                                            else if (((this.hoverEmbeddedIndex.HasValue && this.hoverEmbeddedIndex.Value == inlineIndex1) || isScrollable))
                                            {
                                                double step = 1 / (averageFrameRate / 2);

                                                if (step >= 1)
                                                {
                                                    if (this.hoverEmbeddedIndex.HasValue && this.hoverEmbeddedIndex.Value == inlineIndex1)
                                                    {
                                                        scrollStep = new Nullable<double>(1);
                                                        this.embedScrollStepDictionary.Add(inlineIndex1, 1);
                                                    }
                                                }
                                                else
                                                {
                                                    scrollStep = new Nullable<double>(step);
                                                    this.embedScrollStepDictionary.Add(inlineIndex1, step);
                                                }
                                            }

                                            if (this.embedColorStepDictionary.TryGetValue(inlineIndex1, out step2))
                                            {
                                                if (isReady && this.nextHistoryPoint.HasValue)
                                                {
                                                    if (!this.embedScrollStepDictionary.ContainsKey(inlineIndex1))
                                                    {
                                                        step2 -= 1 / (averageFrameRate / 4);
                                                    }

                                                    if (step2 <= 0)
                                                    {
                                                        entry = null;
                                                        isMutable = true;
                                                        this.embedColorStepDictionary.Remove(inlineIndex1);
                                                    }
                                                    else if (step2 < 1)
                                                    {
                                                        brush = new SolidColorBrush(Color.FromArgb((byte)(this.textColor.A + (this.linkColor.A - this.textColor.A) * Math.Sin(step2 / 2 * Math.PI)), (byte)(this.textColor.R + (this.linkColor.R - this.textColor.R) * Math.Sin(step2 / 2 * Math.PI)), (byte)(this.textColor.G + (this.linkColor.G - this.textColor.G) * Math.Sin(step2 / 2 * Math.PI)), (byte)(this.textColor.B + (this.linkColor.B - this.textColor.B) * Math.Sin(step2 / 2 * Math.PI))));

                                                        if (brush.CanFreeze)
                                                        {
                                                            brush.Freeze();
                                                        }

                                                        isMutable = true;
                                                        this.embedColorStepDictionary[inlineIndex1] = step2;
                                                    }
                                                    else
                                                    {
                                                        brush = this.linkBrush;
                                                    }
                                                }
                                                else if (step2 < 1)
                                                {
                                                    step2 += 1 / (averageFrameRate / 4);

                                                    if (step2 >= 1)
                                                    {
                                                        brush = this.linkBrush;
                                                        isMutable = true;
                                                        this.embedColorStepDictionary[inlineIndex1] = 1;
                                                    }
                                                    else
                                                    {
                                                        brush = new SolidColorBrush(Color.FromArgb((byte)(this.textColor.A + (this.linkColor.A - this.textColor.A) * Math.Sin(step2 / 2 * Math.PI)), (byte)(this.textColor.R + (this.linkColor.R - this.textColor.R) * Math.Sin(step2 / 2 * Math.PI)), (byte)(this.textColor.G + (this.linkColor.G - this.textColor.G) * Math.Sin(step2 / 2 * Math.PI)), (byte)(this.textColor.B + (this.linkColor.B - this.textColor.B) * Math.Sin(step2 / 2 * Math.PI))));

                                                        if (brush.CanFreeze)
                                                        {
                                                            brush.Freeze();
                                                        }

                                                        isMutable = true;
                                                        this.embedColorStepDictionary[inlineIndex1] = step2;
                                                    }
                                                }
                                                else
                                                {
                                                    brush = this.linkBrush;
                                                }
                                            }
                                            else
                                            {
                                                entry = null;
                                                isMutable = true;

                                                if (!isReady || !this.nextHistoryPoint.HasValue)
                                                {
                                                    this.embedColorStepDictionary.Add(inlineIndex1, 0);
                                                }
                                            }
                                        }
                                        else if (obj is StringBuilder)
                                        {
                                            inline = ((StringBuilder)obj).ToString();
                                            isMutable = true;
                                        }

                                        if (inline != null)
                                        {
                                            List<KeyValuePair<Point, FormattedText>> list = new List<KeyValuePair<Point, FormattedText>>();
                                            Dictionary<int, int> dictionary = new Dictionary<int, int>();
                                            StringBuilder lineStringBuilder = new StringBuilder();
                                            Nullable<double> maxY = null;

                                            if (this.messageCollection[this.historyPoint.Value].Cast<object>().Any(o => o == obj))
                                            {
                                                foreach (System.Text.RegularExpressions.Match match in System.Text.RegularExpressions.Regex.Matches(inline, @"[\p{IsBasicLatin}-[\s]]+\s?"))
                                                {
                                                    dictionary.Add(match.Index, match.Length);
                                                }
                                            }
                                            else
                                            {
                                                int breaks = 0;
                                                int i = -1;
                                                int j = 0;

                                                for (int k = 0; k < inline.Length; k++)
                                                {
                                                    if (inline.IndexOf(Environment.NewLine, k, StringComparison.Ordinal) == k)
                                                    {
                                                        breaks++;
                                                        k += Environment.NewLine.Length - 1;
                                                    }
                                                }

                                                while ((i = inlinePointList.Value.FindIndex(i + 1, delegate (Point point)
                                                {
                                                    return Double.IsNaN(point.X) && point.Y >= location.Y;
                                                })) >= 0)
                                                {
                                                    if (j == breaks)
                                                    {
                                                        maxY = new Nullable<double>(inlinePointList.Value[i].Y + this.lineHeight);

                                                        break;
                                                    }

                                                    j++;
                                                }

                                                if (maxY == null)
                                                {
                                                    maxY = new Nullable<double>(inlinePointList.Value.Max(point => point.Y) + this.lineHeight);
                                                }
                                            }

                                            for (int i = 0; i < inline.Length; i++)
                                            {
                                                int length;

                                                if (dictionary.TryGetValue(i, out length) && ((maxY.HasValue ? location.Y + this.lineHeight < maxY.Value : true) ? location.X + Math.Ceiling(new FormattedText(String.Concat(lineStringBuilder.ToString(), inline.Substring(i, length)), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush).WidthIncludingTrailingWhitespace) > inlinePointList.Value.Aggregate<Point, double>(0, (width, point) =>
                                                {
                                                    if (point.X > width && point.Y == location.Y)
                                                    {
                                                        return point.X;
                                                    }

                                                    return width;
                                                }) : location.X + Math.Ceiling(new FormattedText(String.Concat(lineStringBuilder.ToString(), inline.Substring(i, length)), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush).WidthIncludingTrailingWhitespace) > this.maxMessageSize.Width) && !isReseted)
                                                {
                                                    if (lineStringBuilder.Length > 0)
                                                    {
                                                        list.Add(new KeyValuePair<Point, FormattedText>(location, new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush)));
                                                    }

                                                    lineStringBuilder.Clear();
                                                    location.X = 0;
                                                    location.Y += this.lineHeight;
                                                }

                                                lineStringBuilder.Append(inline[i]);

                                                if (lineStringBuilder.ToString().EndsWith(Environment.NewLine, StringComparison.Ordinal))
                                                {
                                                    lineStringBuilder.Remove(lineStringBuilder.ToString().LastIndexOf(Environment.NewLine, StringComparison.Ordinal), Environment.NewLine.Length);

                                                    if (lineStringBuilder.Length > 0)
                                                    {
                                                        list.Add(new KeyValuePair<Point, FormattedText>(location, new FormattedText(lineStringBuilder.ToString().Substring(0, lineStringBuilder.Length), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush)));
                                                        lineStringBuilder.Remove(0, lineStringBuilder.Length);
                                                    }

                                                    location.X = 0;
                                                    location.Y += this.lineHeight;
                                                    isReseted = true;
                                                }
                                                else if (((maxY.HasValue ? location.Y + this.lineHeight < maxY.Value : true) ? location.X + Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush).WidthIncludingTrailingWhitespace) > inlinePointList.Value.Aggregate<Point, double>(0, (width, point) =>
                                                {
                                                    if (point.X > width && point.Y == location.Y)
                                                    {
                                                        return point.X;
                                                    }

                                                    return width;
                                                }) : location.X + Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush).WidthIncludingTrailingWhitespace) > this.maxMessageSize.Width))
                                                {
                                                    if (lineStringBuilder.Length - 1 > 0)
                                                    {
                                                        list.Add(new KeyValuePair<Point, FormattedText>(location, new FormattedText(lineStringBuilder.ToString().Substring(0, lineStringBuilder.Length - 1), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush)));
                                                        lineStringBuilder.Remove(0, lineStringBuilder.Length - 1);
                                                    }

                                                    location.X = 0;
                                                    location.Y += this.lineHeight;
                                                    isReseted = true;
                                                }
                                                else
                                                {
                                                    isReseted = false;
                                                }
                                            }

                                            if (lineStringBuilder.Length > 0 && (maxY.HasValue ? location.Y < maxY.Value : true))
                                            {
                                                FormattedText formattedText = new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush);

                                                list.Add(new KeyValuePair<Point, FormattedText>(location, formattedText));
                                                location.X += Math.Ceiling(formattedText.WidthIncludingTrailingWhitespace);
                                                isReseted = false;
                                            }

                                            for (int i = 0; i < list.Count; i++, inlineIndex2++)
                                            {
                                                int lineNumber = (int)Math.Floor((list[i].Key.Y + this.lineHeight) / this.lineHeight) - 1;

                                                if (minScrollIndex <= lineNumber && lineNumber < minScrollIndex + usedLines + paddingLines)
                                                {
                                                    if (entry == null)
                                                    {
                                                        int key = isMutable ? -inlineIndex2 - 1 : inlineIndex2;
                                                        Image image;

                                                        if (this.cachedInlineImageDictionary.TryGetValue(key, out image))
                                                        {
                                                            double width = Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing);
                                                            double height = list[i].Value.OverhangAfter > 0 ? list[i].Value.Height + list[i].Value.OverhangAfter : list[i].Value.Height;
                                                            DrawingGroup dg = new DrawingGroup();
                                                            DrawingContext dc = dg.Open();

                                                            dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, width, height));
                                                            dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                            dc.Close();

                                                            DrawingImage di = new DrawingImage(dg);

                                                            if (di.CanFreeze)
                                                            {
                                                                di.Freeze();
                                                            }

                                                            image.Source = di;
                                                            image.Width = width;
                                                            image.Height = height;

                                                            Canvas canvas = image.Parent as Canvas;

                                                            if (canvas != null)
                                                            {
                                                                canvas.Margin = new Thickness(Math.Floor(list[i].Value.OverhangLeading), (this.lineHeight - list[i].Value.Height) / 2, 0, 0);
                                                                canvas.Width = width;
                                                                canvas.Height = height;

                                                                Canvas.SetLeft(canvas, baseLocation.X + list[i].Key.X);
                                                                Canvas.SetTop(canvas, baseLocation.Y + list[i].Key.Y);

                                                                hashSet.Add(canvas);
                                                            }
                                                        }
                                                        else
                                                        {
                                                            double width = Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing);
                                                            double height = list[i].Value.OverhangAfter > 0 ? list[i].Value.Height + list[i].Value.OverhangAfter : list[i].Value.Height;
                                                            Canvas canvas = new Canvas();
                                                            DropShadowEffect dropShadowEffect = new DropShadowEffect();
                                                            DrawingGroup dg = new DrawingGroup();
                                                            DrawingContext dc = dg.Open();

                                                            dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, width, height));
                                                            dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                            dc.Close();

                                                            dropShadowEffect.Color = Math.Max(Math.Max(this.textColor.R, this.textColor.G), this.textColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;
                                                            dropShadowEffect.BlurRadius = 1;
                                                            dropShadowEffect.Direction = 270;
                                                            dropShadowEffect.ShadowDepth = 1;
                                                            dropShadowEffect.Opacity = 0.5;

                                                            if (dropShadowEffect.CanFreeze)
                                                            {
                                                                dropShadowEffect.Freeze();
                                                            }

                                                            canvas.HorizontalAlignment = HorizontalAlignment.Left;
                                                            canvas.VerticalAlignment = VerticalAlignment.Top;
                                                            canvas.Margin = new Thickness(Math.Floor(list[i].Value.OverhangLeading), (this.lineHeight - list[i].Value.Height) / 2, 0, 0);
                                                            canvas.Background = Brushes.Transparent;
                                                            canvas.Width = width;
                                                            canvas.Height = height;
                                                            canvas.Effect = dropShadowEffect;

                                                            this.MessageCanvas.Children.Insert(canvasIndex, canvas);

                                                            Canvas.SetLeft(canvas, baseLocation.X + list[i].Key.X);
                                                            Canvas.SetTop(canvas, baseLocation.Y + list[i].Key.Y);

                                                            DrawingImage di = new DrawingImage(dg);

                                                            if (di.CanFreeze)
                                                            {
                                                                di.Freeze();
                                                            }

                                                            image = new Image();
                                                            image.HorizontalAlignment = HorizontalAlignment.Left;
                                                            image.VerticalAlignment = VerticalAlignment.Top;
                                                            image.Source = di;
                                                            image.Stretch = Stretch.None;
                                                            image.Width = width;
                                                            image.Height = height;

                                                            RenderOptions.SetClearTypeHint(image, ClearTypeHint.Enabled);

                                                            canvas.Children.Add(image);

                                                            Canvas.SetLeft(image, 0);
                                                            Canvas.SetTop(image, 0);

                                                            this.cachedInlineImageDictionary.Add(key, image);

                                                            hashSet.Add(canvas);
                                                            updateLayoutRequired = true;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        Image image;

                                                        if (this.cachedInlineImageDictionary.TryGetValue(inlineIndex2, out image))
                                                        {
                                                            if (isMutable)
                                                            {
                                                                double width1 = Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing);
                                                                double width2 = list[i].Value.WidthIncludingTrailingWhitespace > list[i].Value.Width ? Math.Ceiling(list[i].Value.WidthIncludingTrailingWhitespace) - Math.Floor(list[i].Value.OverhangLeading) : list[i].Value.OverhangTrailing < 0 ? Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing) : Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading);
                                                                double maxWidth = width2;
                                                                double height = list[i].Value.OverhangAfter > 0 ? list[i].Value.Height + list[i].Value.OverhangAfter : list[i].Value.Height;
                                                                StringBuilder sb = new StringBuilder();
                                                                DrawingGroup dg = new DrawingGroup();
                                                                DrawingContext dc = dg.Open();

                                                                for (int j = i + 1; j < list.Count; j++)
                                                                {
                                                                    sb.Append(list[j].Value.Text);
                                                                }

                                                                for (int j = 0; j < i; j++)
                                                                {
                                                                    sb.Append(list[j].Value.Text);
                                                                }

                                                                if (sb.Length > 0)
                                                                {
                                                                    FormattedText ft = new FormattedText(sb.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush);

                                                                    height = Math.Max(height, ft.OverhangAfter > 0 ? ft.Height + ft.OverhangAfter : ft.Height);

                                                                    if (ft.WidthIncludingTrailingWhitespace > ft.Width)
                                                                    {
                                                                        if (ft.OverhangLeading < 0)
                                                                        {
                                                                            maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace) - Math.Floor(ft.OverhangLeading);

                                                                            dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                            dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                            dc.DrawText(ft, new Point(width2 - Math.Floor(ft.OverhangLeading), 0));
                                                                        }
                                                                        else
                                                                        {
                                                                            maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace);

                                                                            dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                            dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                            dc.DrawText(ft, new Point(width2, 0));
                                                                        }
                                                                    }
                                                                    else
                                                                    {
                                                                        double width3 = Math.Ceiling(ft.Width);

                                                                        if (ft.OverhangLeading < 0)
                                                                        {
                                                                            width3 -= Math.Floor(ft.OverhangLeading);

                                                                            if (ft.OverhangTrailing < 0)
                                                                            {
                                                                                width3 -= Math.Floor(ft.OverhangTrailing);
                                                                            }

                                                                            maxWidth += width3;

                                                                            dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                            dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                            dc.DrawText(ft, new Point(width2 - Math.Floor(ft.OverhangLeading), 0));
                                                                        }
                                                                        else
                                                                        {
                                                                            if (ft.OverhangTrailing < 0)
                                                                            {
                                                                                width3 -= Math.Floor(ft.OverhangTrailing);
                                                                            }

                                                                            maxWidth += width3;

                                                                            dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                            dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                            dc.DrawText(ft, new Point(width2, 0));
                                                                        }
                                                                    }
                                                                }
                                                                else
                                                                {
                                                                    dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                    dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                }

                                                                dc.DrawText(list[i].Value, new Point(maxWidth - Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                dc.Close();

                                                                DrawingImage di = new DrawingImage(dg);

                                                                if (di.CanFreeze)
                                                                {
                                                                    di.Freeze();
                                                                }

                                                                image.Source = di;
                                                                image.Width = maxWidth + width1;
                                                                image.Height = height;

                                                                TranslateTransform translateTransform = image.RenderTransform as TranslateTransform;

                                                                if (translateTransform != null)
                                                                {
                                                                    translateTransform.X = scrollStep.HasValue ? -maxWidth * Math.Sin(scrollStep.Value / 2 * Math.PI) : 0;
                                                                }

                                                                Canvas canvas = image.Parent as Canvas;

                                                                if (canvas != null)
                                                                {
                                                                    canvas.Margin = new Thickness(Math.Floor(list[i].Value.OverhangLeading), (this.lineHeight - list[i].Value.Height) / 2, 0, 0);
                                                                    canvas.Width = width1;
                                                                    canvas.Height = height;

                                                                    Canvas.SetLeft(canvas, baseLocation.X + list[i].Key.X);
                                                                    Canvas.SetTop(canvas, baseLocation.Y + list[i].Key.Y);

                                                                    hashSet.Add(canvas);
                                                                }
                                                            }
                                                            else
                                                            {
                                                                TranslateTransform translateTransform = image.RenderTransform as TranslateTransform;

                                                                if (translateTransform != null)
                                                                {
                                                                    if (scrollStep.HasValue)
                                                                    {
                                                                        double width = list[i].Value.WidthIncludingTrailingWhitespace > list[i].Value.Width ? Math.Ceiling(list[i].Value.WidthIncludingTrailingWhitespace) - Math.Floor(list[i].Value.OverhangLeading) : list[i].Value.OverhangTrailing < 0 ? Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing) : Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading);
                                                                        double maxWidth = width;
                                                                        StringBuilder sb = new StringBuilder();

                                                                        for (int j = i + 1; j < list.Count; j++)
                                                                        {
                                                                            sb.Append(list[j].Value.Text);
                                                                        }

                                                                        for (int j = 0; j < i; j++)
                                                                        {
                                                                            sb.Append(list[j].Value.Text);
                                                                        }

                                                                        if (sb.Length > 0)
                                                                        {
                                                                            FormattedText ft = new FormattedText(sb.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush);

                                                                            if (ft.WidthIncludingTrailingWhitespace > ft.Width)
                                                                            {
                                                                                if (ft.OverhangLeading < 0)
                                                                                {
                                                                                    maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace) - Math.Floor(ft.OverhangLeading);
                                                                                }
                                                                                else
                                                                                {
                                                                                    maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace);
                                                                                }
                                                                            }
                                                                            else
                                                                            {
                                                                                double w = Math.Ceiling(ft.Width);

                                                                                if (ft.OverhangLeading < 0)
                                                                                {
                                                                                    w -= Math.Floor(ft.OverhangLeading);

                                                                                    if (ft.OverhangTrailing < 0)
                                                                                    {
                                                                                        w -= Math.Floor(ft.OverhangTrailing);
                                                                                    }

                                                                                    maxWidth += w;
                                                                                }
                                                                                else
                                                                                {
                                                                                    if (ft.OverhangTrailing < 0)
                                                                                    {
                                                                                        w -= Math.Floor(ft.OverhangTrailing);
                                                                                    }

                                                                                    maxWidth += w;
                                                                                }
                                                                            }
                                                                        }

                                                                        translateTransform.X = -maxWidth * Math.Sin(scrollStep.Value / 2 * Math.PI);
                                                                    }
                                                                    else
                                                                    {
                                                                        translateTransform.X = 0;
                                                                    }
                                                                }

                                                                Canvas canvas = image.Parent as Canvas;

                                                                if (canvas != null)
                                                                {
                                                                    Canvas.SetLeft(canvas, baseLocation.X + list[i].Key.X);
                                                                    Canvas.SetTop(canvas, baseLocation.Y + list[i].Key.Y);

                                                                    hashSet.Add(canvas);
                                                                }
                                                            }
                                                        }
                                                        else
                                                        {
                                                            int index = inlineIndex1;
                                                            double width1 = Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing);
                                                            double width2 = list[i].Value.WidthIncludingTrailingWhitespace > list[i].Value.Width ? Math.Ceiling(list[i].Value.WidthIncludingTrailingWhitespace) - Math.Floor(list[i].Value.OverhangLeading) : list[i].Value.OverhangTrailing < 0 ? Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing) : Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading);
                                                            double maxWidth = width2;
                                                            double height = list[i].Value.OverhangAfter > 0 ? list[i].Value.Height + list[i].Value.OverhangAfter : list[i].Value.Height;
                                                            StringBuilder sb = new StringBuilder();
                                                            Canvas canvas = new Canvas();
                                                            DropShadowEffect dropShadowEffect = new DropShadowEffect();
                                                            DrawingGroup dg = new DrawingGroup();
                                                            DrawingContext dc = dg.Open();

                                                            for (int j = i + 1; j < list.Count; j++)
                                                            {
                                                                sb.Append(list[j].Value.Text);
                                                            }

                                                            for (int j = 0; j < i; j++)
                                                            {
                                                                sb.Append(list[j].Value.Text);
                                                            }

                                                            if (sb.Length > 0)
                                                            {
                                                                FormattedText ft = new FormattedText(sb.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, brush);

                                                                height = Math.Max(height, ft.OverhangAfter > 0 ? ft.Height + ft.OverhangAfter : ft.Height);

                                                                if (ft.WidthIncludingTrailingWhitespace > ft.Width)
                                                                {
                                                                    if (ft.OverhangLeading < 0)
                                                                    {
                                                                        maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace) - Math.Floor(ft.OverhangLeading);

                                                                        dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                        dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                        dc.DrawText(ft, new Point(width2 - Math.Floor(ft.OverhangLeading), 0));
                                                                    }
                                                                    else
                                                                    {
                                                                        maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace);

                                                                        dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                        dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                        dc.DrawText(ft, new Point(width2, 0));
                                                                    }
                                                                }
                                                                else
                                                                {
                                                                    double width3 = Math.Ceiling(ft.Width);

                                                                    if (ft.OverhangLeading < 0)
                                                                    {
                                                                        width3 -= Math.Floor(ft.OverhangLeading);

                                                                        if (ft.OverhangTrailing < 0)
                                                                        {
                                                                            width3 -= Math.Floor(ft.OverhangTrailing);
                                                                        }

                                                                        maxWidth += width3;

                                                                        dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                        dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                        dc.DrawText(ft, new Point(width2 - Math.Floor(ft.OverhangLeading), 0));
                                                                    }
                                                                    else
                                                                    {
                                                                        if (ft.OverhangTrailing < 0)
                                                                        {
                                                                            width3 -= Math.Floor(ft.OverhangTrailing);
                                                                        }

                                                                        maxWidth += width3;

                                                                        dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                        dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                        dc.DrawText(ft, new Point(width2, 0));
                                                                    }
                                                                }
                                                            }
                                                            else
                                                            {
                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                            }

                                                            dc.DrawText(list[i].Value, new Point(maxWidth - Math.Floor(list[i].Value.OverhangLeading), 0));
                                                            dc.Close();

                                                            dropShadowEffect.Color = Math.Max(Math.Max(this.textColor.R, this.textColor.G), this.textColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;
                                                            dropShadowEffect.BlurRadius = 1;
                                                            dropShadowEffect.Direction = 270;
                                                            dropShadowEffect.ShadowDepth = 1;
                                                            dropShadowEffect.Opacity = 0.5;

                                                            if (dropShadowEffect.CanFreeze)
                                                            {
                                                                dropShadowEffect.Freeze();
                                                            }

                                                            canvas = new Canvas();
                                                            canvas.HorizontalAlignment = HorizontalAlignment.Left;
                                                            canvas.VerticalAlignment = VerticalAlignment.Top;
                                                            canvas.Margin = new Thickness(Math.Floor(list[i].Value.OverhangLeading), (this.lineHeight - list[i].Value.Height) / 2, 0, 0);
                                                            canvas.Background = Brushes.Transparent;
                                                            canvas.ClipToBounds = true;
                                                            canvas.Width = width1;
                                                            canvas.Height = height;
                                                            canvas.Effect = dropShadowEffect;

                                                            this.MessageCanvas.Children.Insert(canvasIndex, canvas);

                                                            Canvas.SetLeft(canvas, baseLocation.X + list[i].Key.X);
                                                            Canvas.SetTop(canvas, baseLocation.Y + list[i].Key.Y);

                                                            DrawingImage di = new DrawingImage(dg);

                                                            if (di.CanFreeze)
                                                            {
                                                                di.Freeze();
                                                            }

                                                            image = new Image();
                                                            image.HorizontalAlignment = HorizontalAlignment.Left;
                                                            image.VerticalAlignment = VerticalAlignment.Top;
                                                            image.Source = di;
                                                            image.Stretch = Stretch.None;
                                                            image.Width = maxWidth + width1;
                                                            image.Height = height;
                                                            image.RenderTransform = new TranslateTransform(scrollStep.HasValue ? -maxWidth * Math.Sin(scrollStep.Value / 2 * Math.PI) : 0, 0);
                                                            image.MouseEnter += new MouseEventHandler(delegate
                                                            {
                                                                this.hoverEmbeddedIndex = new Nullable<int>(index);
                                                            });
                                                            image.MouseLeave += new MouseEventHandler(delegate
                                                            {
                                                                this.hoverEmbeddedIndex = null;
                                                            });
                                                            image.MouseLeftButtonUp += new MouseButtonEventHandler(delegate (object s, MouseButtonEventArgs mbea)
                                                            {
                                                                if (this.hoverEmbeddedIndex.HasValue && !this.embedIsScrollableHashSet.Contains(this.hoverEmbeddedIndex.Value))
                                                                {
                                                                    this.embedIsScrollableHashSet.Add(this.hoverEmbeddedIndex.Value);
                                                                }

                                                                if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                                                                {
                                                                    if (entry.Resource == null)
                                                                    {
                                                                        Script.Instance.Search(entry.Title);
                                                                    }
                                                                    else
                                                                    {
                                                                        Task.Factory.StartNew(delegate (object state)
                                                                        {
                                                                            System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo((string)state));
                                                                        }, entry.Resource.ToString());
                                                                    }
                                                                }
                                                                else
                                                                {
                                                                    this.previousInspectorEntry = this.inspectorEntry;
                                                                    this.nextInspectorEntry = (Entry)entry.Clone();
                                                                }

                                                                mbea.Handled = true;
                                                            });

                                                            RenderOptions.SetClearTypeHint(image, ClearTypeHint.Enabled);

                                                            canvas.Children.Add(image);

                                                            Canvas.SetLeft(image, 0);
                                                            Canvas.SetTop(image, 0);

                                                            this.cachedInlineImageDictionary.Add(inlineIndex2, image);

                                                            hashSet.Add(canvas);
                                                            updateLayoutRequired = true;
                                                        }
                                                    }

                                                    canvasIndex++;
                                                }
                                            }
                                        }

                                        inlineIndex1++;
                                    }

                                    foreach (KeyValuePair<int, Canvas> kvp in (from kvp in this.cachedInlineImageDictionary let canvas = kvp.Value.Parent as Canvas where canvas != null && !hashSet.Contains(canvas) select new KeyValuePair<int, Canvas>(kvp.Key, canvas)).ToArray())
                                    {
                                        this.MessageCanvas.Children.Remove(kvp.Value);
                                        this.cachedInlineImageDictionary.Remove(kvp.Key);
                                    }
                                }

                                if (this.messageCollection[this.historyPoint.Value].HasAttachments)
                                {
                                    waitRequired = false;

                                    if ((isTyped || isReady && this.nextHistoryPoint.HasValue) && (isFragmented || isReady && this.nextHistoryPoint.HasValue && this.attachmentFadeStepDictionary.Values.Any(step => step > 0) || this.attachmentFadeStepDictionary.Count == 0 || this.attachmentFadeStepDictionary.Values.Any(step => step < 1) || this.messageCollection[this.historyPoint.Value].Attachments.Where((entry, i) =>
                                    {
                                        double fadeStep;

                                        if (this.attachmentFadeStepDictionary.TryGetValue(i, out fadeStep) && fadeStep > 0)
                                        {
                                            bool maskRequired = false;
                                            double enableStep;

                                            if (this.sourceScrollPosition == this.targetScrollPosition && this.selectedIndex.HasValue && this.selectedPosition.HasValue && this.selectedIndex.Value != (int)Math.Floor(this.selectedPosition.Value) && i == (int)Math.Floor(this.selectedPosition.Value))
                                            {
                                                return true;
                                            }

                                            if (!entry.ReadOnly)
                                            {
                                                if (this.attachmentEnableStepDictionary.TryGetValue(i, out enableStep))
                                                {
                                                    if (entry.Enabled)
                                                    {
                                                        return true;
                                                    }
                                                    else if (enableStep < 1)
                                                    {
                                                        return true;
                                                    }
                                                }
                                                else if (!entry.Enabled)
                                                {
                                                    return true;
                                                }
                                            }

                                            if (entry.Score.HasValue)
                                            {
                                                if (this.isReversed && entry.Score.Value < this.thresholdScore || !this.isReversed && entry.Score.Value > this.thresholdScore)
                                                {
                                                    double filterStep;

                                                    if (this.attachmentFilterStepDictionary.TryGetValue(i, out filterStep))
                                                    {
                                                        if (filterStep < 1)
                                                        {
                                                            return true;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        return true;
                                                    }
                                                }
                                                else if (this.attachmentFilterStepDictionary.ContainsKey(i))
                                                {
                                                    return true;
                                                }
                                            }

                                            if (!this.attachmentsAreHover && this.selectedPosition.HasValue && i != (int)Math.Floor(this.selectedPosition.Value))
                                            {
                                                maskRequired = true;
                                            }

                                            if (maskRequired)
                                            {
                                                double highlightStep;

                                                if (this.attachmentHighlightStepDictionary.TryGetValue(i, out highlightStep))
                                                {
                                                    if (highlightStep < 1)
                                                    {
                                                        return true;
                                                    }
                                                }
                                                else
                                                {
                                                    return true;
                                                }
                                            }
                                            else if (this.attachmentHighlightStepDictionary.ContainsKey(i))
                                            {
                                                return true;
                                            }
                                        }

                                        return false;
                                    }).Any() || !this.attachmentsAreHover && this.selectedPosition.HasValue && this.attachmentHighlightStepDictionary.Count == 0 || this.attachmentImageLoadingStepDictionary.Count > 0 || this.attachmentImagePopupStepDictionary.Count > 0 || this.attachmentIsScrollableHashSet.Count > 0 || this.attachmentScrollStepDictionary.Count > 0 || this.hoverIndex.HasValue && this.attachmentIsScrollableHashSet.Count == 0 && this.attachmentScrollStepDictionary.Count == 0))
                                    {
                                        const int leftMargin = 25;
                                        const int rightMargin = 3;
                                        int minScrollIndex = (int)Math.Floor(Math.Min(this.sourceScrollPosition, this.targetScrollPosition));
                                        int messageLines = inlinePointList.Value.Aggregate<Point, HashSet<double>>(new HashSet<double>(), (hs, point) =>
                                        {
                                            if (!hs.Contains(point.Y))
                                            {
                                                hs.Add(point.Y);
                                            }

                                            return hs;
                                        }).Count;
                                        double totalMessageHeight = (messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count) * this.lineHeight;
                                        int maxLines = messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count < this.numberOfLines ? messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count : this.numberOfLines;
                                        int usedLines = messageLines - minScrollIndex;

                                        if (usedLines < 0)
                                        {
                                            usedLines = 0;
                                        }

                                        int actualLines = usedLines + this.messageCollection[this.historyPoint.Value].Attachments.Count;

                                        if (actualLines > maxLines)
                                        {
                                            actualLines = maxLines;
                                        }

                                        bool isVisible = messageLines - minScrollIndex - actualLines - paddingLines < 0;
                                        Rect nextRect = new Rect(leftMargin, minScrollIndex <= messageLines ? this.lineHeight * usedLines : 0, this.maxMessageSize.Width - (leftMargin + rightMargin), this.lineHeight);
                                        int offset = minScrollIndex - messageLines;
                                        int length = maxLines - usedLines + paddingLines;
                                        bool imageIsUpdating = false;
                                        bool isImcomplete = false;
                                        int canvasIndex = this.cachedInlineImageDictionary.Count;
                                        HashSet<UIElement> hashSet = new HashSet<UIElement>();

                                        if (offset < 0)
                                        {
                                            offset = 0;
                                        }

                                        this.ScrollCanvas.Width = this.MessageCanvas.Width = this.maxMessageSize.Width;
                                        this.ScrollCanvas.Height = this.lineHeight * actualLines;
                                        this.MessageCanvas.Height = this.lineHeight * (this.counterScrollStep.HasValue ? actualLines + paddingLines + 1 : actualLines + paddingLines);

                                        for (int i = 0; i < this.messageCollection[this.historyPoint.Value].Attachments.Count; i++)
                                        {
                                            double fadeStep;

                                            if (isVisible && i < offset + length)
                                            {
                                                bool isStepping = false;

                                                if (i > 0)
                                                {
                                                    double step;

                                                    if (this.attachmentFadeStepDictionary.TryGetValue(i - 1, out step) && Math.Sin(step / 2 * Math.PI) >= 0.5)
                                                    {
                                                        isStepping = true;
                                                    }
                                                }
                                                else if (i == 0)
                                                {
                                                    isStepping = true;
                                                }

                                                if (this.attachmentFadeStepDictionary.TryGetValue(i, out fadeStep))
                                                {
                                                    if (isReady && this.nextHistoryPoint.HasValue)
                                                    {
                                                        fadeStep -= 1 / (averageFrameRate / 4);

                                                        if (fadeStep < 0)
                                                        {
                                                            fadeStep = 0;
                                                        }

                                                        this.attachmentFadeStepDictionary[i] = fadeStep;
                                                    }
                                                    else if (fadeStep < 1 && isStepping)
                                                    {
                                                        fadeStep += 1 / (averageFrameRate / 4);

                                                        if (fadeStep >= 1 || i < offset)
                                                        {
                                                            fadeStep = 1;
                                                            waitRequired = true;
                                                        }
                                                        else
                                                        {
                                                            isImcomplete = true;
                                                        }

                                                        this.attachmentFadeStepDictionary[i] = fadeStep;
                                                    }
                                                }
                                                else if (isStepping)
                                                {
                                                    fadeStep = 1 / (averageFrameRate / 4);

                                                    if (fadeStep >= 1 || i < offset)
                                                    {
                                                        fadeStep = 1;
                                                        waitRequired = true;
                                                    }
                                                    else
                                                    {
                                                        isImcomplete = true;
                                                    }

                                                    this.attachmentFadeStepDictionary.Add(i, fadeStep);
                                                }
                                                else
                                                {
                                                    this.attachmentFadeStepDictionary.Add(i, 0);
                                                }
                                            }
                                            else if (this.attachmentFadeStepDictionary.TryGetValue(i, out fadeStep) && isReady && this.nextHistoryPoint.HasValue)
                                            {
                                                fadeStep -= 1 / (averageFrameRate / 4);

                                                if (fadeStep < 0)
                                                {
                                                    fadeStep = 0;
                                                }

                                                this.attachmentFadeStepDictionary[i] = fadeStep;
                                            }

                                            if (fadeStep > 0)
                                            {
                                                Entry attachmentEntry = this.messageCollection[this.historyPoint.Value].Attachments[i];
                                                double opacity = 1;
                                                double enableStep;
                                                bool isLoading = false;
                                                double slideStep = 0;
                                                bool slideStepIsUpdated = false;
                                                double loadStep = 0;
                                                bool isHover = this.hoverIndex.HasValue && this.hoverIndex.Value == i;
                                                double popupStep = 0;
                                                bool popupStepIsUpdated = false;
                                                bool isScrollable = false;
                                                double scrollStep1;
                                                Nullable<double> scrollStep2 = null;

                                                if (this.sourceScrollPosition == this.targetScrollPosition && this.selectedIndex.HasValue && this.selectedPosition.HasValue && this.selectedIndex.Value != (int)Math.Floor(this.selectedPosition.Value) && i == (int)Math.Floor(this.selectedPosition.Value))
                                                {
                                                    this.selectedIndex = new Nullable<int>((int)Math.Floor(this.selectedPosition.Value));
                                                    this.previousInspectorEntry = this.inspectorEntry;
                                                    this.nextInspectorEntry = (Entry)this.messageCollection[this.historyPoint.Value].Attachments[(int)Math.Floor(this.selectedPosition.Value)].Clone();
                                                }

                                                if (!attachmentEntry.ReadOnly)
                                                {
                                                    if (this.attachmentEnableStepDictionary.TryGetValue(i, out enableStep))
                                                    {
                                                        if (attachmentEntry.Enabled)
                                                        {
                                                            enableStep -= 1 / (averageFrameRate / 4);

                                                            if (enableStep <= 0)
                                                            {
                                                                enableStep = 0;
                                                                this.attachmentEnableStepDictionary.Remove(i);
                                                            }
                                                            else
                                                            {
                                                                this.attachmentEnableStepDictionary[i] = enableStep;
                                                            }
                                                        }
                                                        else
                                                        {
                                                            if (enableStep < 1)
                                                            {
                                                                enableStep += 1 / (averageFrameRate / 4);

                                                                if (enableStep > 1)
                                                                {
                                                                    enableStep = 1;
                                                                }

                                                                this.attachmentEnableStepDictionary[i] = enableStep;
                                                            }
                                                        }

                                                        opacity = (opacity * 50d / 100d) + (opacity * 50d / 100d) * Math.Cos(enableStep / 2 * Math.PI);
                                                    }
                                                    else if (!attachmentEntry.Enabled)
                                                    {
                                                        enableStep = 1 / (averageFrameRate / 4);

                                                        if (enableStep > 1)
                                                        {
                                                            enableStep = 1;
                                                        }

                                                        this.attachmentEnableStepDictionary[i] = enableStep;
                                                        opacity = (opacity * 50d / 100d) + (opacity * 50d / 100d) * Math.Cos(enableStep / 2 * Math.PI);
                                                    }
                                                }

                                                if (attachmentEntry.Score.HasValue)
                                                {
                                                    if (this.isReversed && attachmentEntry.Score.Value < this.thresholdScore || !this.isReversed && attachmentEntry.Score.Value > this.thresholdScore)
                                                    {
                                                        double filterStep;

                                                        if (!this.attachmentFilterStepDictionary.TryGetValue(i, out filterStep))
                                                        {
                                                            this.attachmentFilterStepDictionary.Add(i, 0);
                                                        }

                                                        if (filterStep < 1)
                                                        {
                                                            filterStep += 1 / (averageFrameRate / 4);

                                                            if (filterStep > 1)
                                                            {
                                                                filterStep = 1;
                                                            }

                                                            this.attachmentFilterStepDictionary[i] = filterStep;
                                                        }

                                                        opacity = (opacity * 75d / 100d) + (opacity * 25d / 100d) * Math.Cos(filterStep / 2 * Math.PI);
                                                    }
                                                    else
                                                    {
                                                        double filterStep;

                                                        if (this.attachmentFilterStepDictionary.TryGetValue(i, out filterStep))
                                                        {
                                                            if (filterStep > 0)
                                                            {
                                                                filterStep -= 1 / (averageFrameRate / 4);

                                                                if (filterStep <= 0)
                                                                {
                                                                    filterStep = 0;
                                                                    this.attachmentFilterStepDictionary.Remove(i);
                                                                }
                                                                else
                                                                {
                                                                    this.attachmentFilterStepDictionary[i] = filterStep;
                                                                }
                                                            }

                                                            opacity = (opacity * 75d / 100d) + (opacity * 25d / 100d) * Math.Cos(filterStep / 2 * Math.PI);
                                                        }
                                                    }
                                                }

                                                if (!this.attachmentsAreHover && this.selectedPosition.HasValue && (int)Math.Floor(this.selectedPosition.Value) != i)
                                                {
                                                    double highlightStep;

                                                    if (!this.attachmentHighlightStepDictionary.TryGetValue(i, out highlightStep))
                                                    {
                                                        this.attachmentHighlightStepDictionary.Add(i, 0);
                                                    }

                                                    if (highlightStep < 1)
                                                    {
                                                        highlightStep += 1 / (averageFrameRate / 2);

                                                        if (highlightStep > 1)
                                                        {
                                                            highlightStep = 1;
                                                        }

                                                        this.attachmentHighlightStepDictionary[i] = highlightStep;
                                                    }

                                                    opacity = (opacity * 75d / 100d) + (opacity * 25d / 100d) * Math.Cos(highlightStep / 2 * Math.PI);
                                                }
                                                else
                                                {
                                                    double highlightStep;

                                                    if (this.attachmentHighlightStepDictionary.TryGetValue(i, out highlightStep))
                                                    {
                                                        if (highlightStep > 0)
                                                        {
                                                            highlightStep -= 1 / (averageFrameRate / 2);

                                                            if (highlightStep <= 0)
                                                            {
                                                                highlightStep = 0;
                                                                this.attachmentHighlightStepDictionary.Remove(i);
                                                            }
                                                            else
                                                            {
                                                                this.attachmentHighlightStepDictionary[i] = highlightStep;
                                                            }
                                                        }

                                                        opacity = (opacity * 75d / 100d) + (opacity * 25d / 100d) * Math.Cos(highlightStep / 2 * Math.PI);
                                                    }
                                                }

                                                opacity = opacity * Math.Sin(fadeStep / 2 * Math.PI);

                                                if (i >= offset)
                                                {
                                                    if (attachmentEntry.Image == null)
                                                    {
                                                        attachmentEntry.NextImage();
                                                    }

                                                    if (attachmentEntry.Image != null && !imageIsUpdating)
                                                    {
                                                        if (!this.imageDictionary.ContainsKey(attachmentEntry.Image))
                                                        {
                                                            if (!this.imageUriHashSet.Contains(attachmentEntry.Image))
                                                            {
                                                                this.imageUriHashSet.Add(attachmentEntry.Image);

                                                                UpdateImage(attachmentEntry.Image, false);
                                                            }

                                                            imageIsUpdating = true;
                                                        }
                                                    }
                                                }

                                                if (attachmentEntry.Image != null)
                                                {
                                                    BitmapImage bitmapImage;
                                                    BitmapImage previousBitmapImage;

                                                    if (this.imageDictionary.TryGetValue(attachmentEntry.Image, out bitmapImage))
                                                    {
                                                        if (this.attachmentImageDictionary.TryGetValue(i, out previousBitmapImage) && bitmapImage != previousBitmapImage && this.attachmentImageSlideStepDictionary.TryGetValue(i, out slideStep) && slideStep == 1)
                                                        {
                                                            this.attachmentImageSlideStepDictionary[i] = 0;
                                                        }
                                                    }
                                                    else if (this.attachmentImageDictionary.TryGetValue(i, out previousBitmapImage))
                                                    {
                                                        bitmapImage = previousBitmapImage;
                                                    }

                                                    if (bitmapImage == null)
                                                    {
                                                        isLoading = true;
                                                    }
                                                    else
                                                    {
                                                        if (!this.attachmentImageSlideStepDictionary.TryGetValue(i, out slideStep))
                                                        {
                                                            this.attachmentImageSlideStepDictionary.Add(i, 0);
                                                        }

                                                        if (slideStep < 1)
                                                        {
                                                            slideStep += 1 / (averageFrameRate / 2);

                                                            if (slideStep >= 1)
                                                            {
                                                                slideStep = 1;

                                                                if (bitmapImage != previousBitmapImage)
                                                                {
                                                                    if (this.attachmentImageDictionary.ContainsKey(i))
                                                                    {
                                                                        this.attachmentImageDictionary[i] = bitmapImage;
                                                                    }
                                                                    else
                                                                    {
                                                                        this.attachmentImageDictionary.Add(i, bitmapImage);
                                                                    }
                                                                }
                                                            }
                                                            else
                                                            {
                                                                isLoading = true;
                                                            }

                                                            this.attachmentImageSlideStepDictionary[i] = slideStep;
                                                            slideStepIsUpdated = true;
                                                        }
                                                    }
                                                }

                                                if (isLoading)
                                                {
                                                    if (this.attachmentImageLoadingStepDictionary.TryGetValue(i, out loadStep))
                                                    {
                                                        loadStep += 1 / (averageFrameRate / 2);

                                                        if (loadStep >= 1)
                                                        {
                                                            loadStep = 0;
                                                        }

                                                        this.attachmentImageLoadingStepDictionary[i] = loadStep;
                                                    }
                                                    else
                                                    {
                                                        this.attachmentImageLoadingStepDictionary.Add(i, 0);
                                                    }
                                                }
                                                else if (this.attachmentImageLoadingStepDictionary.ContainsKey(i))
                                                {
                                                    this.attachmentImageLoadingStepDictionary.Remove(i);
                                                }

                                                if (isHover)
                                                {
                                                    if (!this.attachmentImagePopupStepDictionary.TryGetValue(i, out popupStep))
                                                    {
                                                        this.attachmentImagePopupStepDictionary.Add(i, 0);
                                                    }

                                                    if (popupStep < 1)
                                                    {
                                                        popupStep += 1 / (averageFrameRate / 4);

                                                        if (popupStep > 1)
                                                        {
                                                            popupStep = 1;
                                                        }

                                                        this.attachmentImagePopupStepDictionary[i] = popupStep;
                                                        popupStepIsUpdated = true;
                                                    }
                                                }
                                                else if (this.attachmentImagePopupStepDictionary.TryGetValue(i, out popupStep))
                                                {
                                                    popupStep -= 1 / (averageFrameRate / 4);

                                                    if (popupStep > 0)
                                                    {
                                                        this.attachmentImagePopupStepDictionary[i] = popupStep;
                                                    }
                                                    else
                                                    {
                                                        popupStep = 0;
                                                        this.attachmentImagePopupStepDictionary.Remove(i);
                                                    }

                                                    popupStepIsUpdated = true;
                                                }

                                                if (this.attachmentIsScrollableHashSet.Contains(i))
                                                {
                                                    isScrollable = true;
                                                    this.attachmentIsScrollableHashSet.Remove(i);
                                                }

                                                if (this.attachmentScrollStepDictionary.TryGetValue(i, out scrollStep1))
                                                {
                                                    if (scrollStep1 == 1 && isScrollable)
                                                    {
                                                        scrollStep1 = 0;
                                                    }

                                                    scrollStep1 += 1 / (averageFrameRate / 2);

                                                    if (scrollStep1 >= 1)
                                                    {
                                                        if (isHover)
                                                        {
                                                            scrollStep2 = new Nullable<double>(1);
                                                            this.attachmentScrollStepDictionary[i] = 1;
                                                        }
                                                        else
                                                        {
                                                            this.attachmentScrollStepDictionary.Remove(i);
                                                        }
                                                    }
                                                    else
                                                    {
                                                        scrollStep2 = new Nullable<double>(scrollStep1);
                                                        this.attachmentScrollStepDictionary[i] = scrollStep1;
                                                    }
                                                }
                                                else if (isHover || isScrollable)
                                                {
                                                    scrollStep1 = 1 / (averageFrameRate / 2);

                                                    if (scrollStep1 >= 1)
                                                    {
                                                        if (isHover)
                                                        {
                                                            scrollStep2 = new Nullable<double>(1);
                                                            this.attachmentScrollStepDictionary.Add(i, 1);
                                                        }
                                                    }
                                                    else
                                                    {
                                                        scrollStep2 = new Nullable<double>(scrollStep1);
                                                        this.attachmentScrollStepDictionary.Add(i, scrollStep1);
                                                    }
                                                }

                                                if (offset <= i && i < offset + length)
                                                {
                                                    Image attachmentThumbnailImage;
                                                    Size imageSize = new Size(8, 8);
                                                    double popupMargin = Math.Round(((this.lineHeight - imageSize.Height) / 2 < 4 ? (this.lineHeight - imageSize.Height) / 2 : 4) * Math.Sin(popupStep / 2 * Math.PI));
                                                    Rect imageRect = new Rect(nextRect.X - (imageSize.Width + 9) - popupMargin, nextRect.Y + (nextRect.Height - imageSize.Height) / 2 - popupMargin, imageSize.Width + popupMargin * 2, imageSize.Height + popupMargin * 2);

                                                    if (!String.IsNullOrEmpty(String.IsNullOrEmpty(attachmentEntry.Title) && attachmentEntry.Resource != null ? attachmentEntry.Resource.ToString() : attachmentEntry.Title))
                                                    {
                                                        Image attachmentTextImage;

                                                        if (this.cachedAttachmentTextImageDictionary.TryGetValue(i, out attachmentTextImage))
                                                        {
                                                            Canvas attachmentCanvas = attachmentTextImage.Parent as Canvas;

                                                            if (attachmentCanvas != null)
                                                            {
                                                                TranslateTransform translateTransform = attachmentTextImage.RenderTransform as TranslateTransform;

                                                                if (translateTransform != null)
                                                                {
                                                                    FormattedText formattedText = new FormattedText(String.IsNullOrEmpty(attachmentEntry.Title) && attachmentEntry.Resource != null ? attachmentEntry.Resource.ToString() : attachmentEntry.Title, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                                    translateTransform.X = scrollStep2.HasValue ? -(formattedText.WidthIncludingTrailingWhitespace > formattedText.Width ? Math.Ceiling(formattedText.WidthIncludingTrailingWhitespace) - Math.Floor(formattedText.OverhangLeading) : formattedText.OverhangTrailing < 0 ? Math.Ceiling(formattedText.Width) - Math.Floor(formattedText.OverhangLeading) - Math.Floor(formattedText.OverhangTrailing) : Math.Ceiling(formattedText.Width) - Math.Floor(formattedText.OverhangLeading)) * Math.Sin(scrollStep2.Value / 2 * Math.PI) : 0;
                                                                }

                                                                attachmentCanvas.Opacity = opacity;

                                                                Canvas.SetLeft(attachmentCanvas, nextRect.X);
                                                                Canvas.SetTop(attachmentCanvas, nextRect.Y);

                                                                hashSet.Add(attachmentCanvas);
                                                            }
                                                        }
                                                        else
                                                        {
                                                            int index = i;
                                                            FormattedText formattedText = new FormattedText(String.IsNullOrEmpty(attachmentEntry.Title) && attachmentEntry.Resource != null ? attachmentEntry.Resource.ToString() : attachmentEntry.Title, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);
                                                            double width1 = formattedText.WidthIncludingTrailingWhitespace > formattedText.Width ? Math.Ceiling(formattedText.WidthIncludingTrailingWhitespace) - Math.Floor(formattedText.OverhangLeading) : formattedText.OverhangTrailing < 0 ? Math.Ceiling(formattedText.Width) - Math.Floor(formattedText.OverhangLeading) - Math.Floor(formattedText.OverhangTrailing) : Math.Ceiling(formattedText.Width) - Math.Floor(formattedText.OverhangLeading);
                                                            double width2 = Math.Ceiling(formattedText.Width) - Math.Floor(formattedText.OverhangLeading) - Math.Floor(formattedText.OverhangTrailing);
                                                            double height = formattedText.OverhangAfter > 0 ? formattedText.Height + formattedText.OverhangAfter : formattedText.Height;
                                                            Canvas attachmentCanvas = new Canvas();
                                                            DropShadowEffect dropShadowEffect = new DropShadowEffect();
                                                            DrawingGroup dg = new DrawingGroup();
                                                            DrawingContext dc = dg.Open();

                                                            dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, width1 + width2, height));
                                                            dc.DrawText(formattedText, new Point(-Math.Floor(formattedText.OverhangLeading), 0));
                                                            dc.DrawText(formattedText, new Point(width1 - Math.Floor(formattedText.OverhangLeading), 0));
                                                            dc.Close();

                                                            dropShadowEffect.Color = Math.Max(Math.Max(this.textColor.R, this.textColor.G), this.textColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;
                                                            dropShadowEffect.BlurRadius = 1;
                                                            dropShadowEffect.Direction = 270;
                                                            dropShadowEffect.ShadowDepth = 1;
                                                            dropShadowEffect.Opacity = 0.5;

                                                            if (dropShadowEffect.CanFreeze)
                                                            {
                                                                dropShadowEffect.Freeze();
                                                            }

                                                            attachmentCanvas.HorizontalAlignment = HorizontalAlignment.Left;
                                                            attachmentCanvas.VerticalAlignment = VerticalAlignment.Top;
                                                            attachmentCanvas.Margin = new Thickness(Math.Floor(formattedText.OverhangLeading), (nextRect.Height - formattedText.Height) / 2, 0, 0);
                                                            attachmentCanvas.Background = Brushes.Transparent;
                                                            attachmentCanvas.ClipToBounds = true;
                                                            attachmentCanvas.Width = width2 > nextRect.Width ? nextRect.Width : width2;
                                                            attachmentCanvas.Height = height;
                                                            attachmentCanvas.Opacity = opacity;
                                                            attachmentCanvas.Effect = dropShadowEffect;

                                                            this.MessageCanvas.Children.Insert(canvasIndex, attachmentCanvas);

                                                            Canvas.SetLeft(attachmentCanvas, nextRect.X);
                                                            Canvas.SetTop(attachmentCanvas, nextRect.Y);

                                                            DrawingImage di = new DrawingImage(dg);

                                                            if (di.CanFreeze)
                                                            {
                                                                di.Freeze();
                                                            }

                                                            attachmentTextImage = new Image();
                                                            attachmentTextImage.HorizontalAlignment = HorizontalAlignment.Left;
                                                            attachmentTextImage.VerticalAlignment = VerticalAlignment.Top;
                                                            attachmentTextImage.Source = di;
                                                            attachmentTextImage.Stretch = Stretch.None;
                                                            attachmentTextImage.Width = width1 + width2;
                                                            attachmentTextImage.Height = height;
                                                            attachmentTextImage.RenderTransform = new TranslateTransform(scrollStep2.HasValue ? -width1 * Math.Sin(scrollStep2.Value / 2 * Math.PI) : 0, 0);
                                                            attachmentTextImage.MouseEnter += new MouseEventHandler(delegate
                                                            {
                                                                this.hoverIndex = new Nullable<int>(index);
                                                            });
                                                            attachmentTextImage.MouseLeave += new MouseEventHandler(delegate
                                                            {
                                                                this.hoverIndex = null;
                                                            });
                                                            attachmentTextImage.MouseLeftButtonUp += new MouseButtonEventHandler(delegate (object s, MouseButtonEventArgs mbea)
                                                            {
                                                                if (this.hoverIndex.HasValue && !this.attachmentIsScrollableHashSet.Contains(this.hoverIndex.Value))
                                                                {
                                                                    this.attachmentIsScrollableHashSet.Add(this.hoverIndex.Value);
                                                                }

                                                                if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                                                                {
                                                                    if (attachmentEntry.Resource != null)
                                                                    {
                                                                        Task.Factory.StartNew(delegate (object state)
                                                                        {
                                                                            System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo((string)state));
                                                                        }, attachmentEntry.Resource.ToString());
                                                                    }
                                                                    else if (!String.IsNullOrEmpty(attachmentEntry.Title))
                                                                    {
                                                                        if (attachmentEntry.ReadOnly)
                                                                        {
                                                                            Script.Instance.Search(attachmentEntry.Title);
                                                                        }
                                                                        else
                                                                        {
                                                                            if (attachmentEntry.Enabled)
                                                                            {
                                                                                foreach (object o in this.messageCollection[this.historyPoint.Value])
                                                                                {
                                                                                    Entry e1 = o as Entry;

                                                                                    if (e1 != null)
                                                                                    {
                                                                                        string term = e1.Title;
                                                                                        string attribute = attachmentEntry.Title;
                                                                                        bool isNewWord = true;
                                                                                        List<Word> wordList = new List<Word>();

                                                                                        foreach (Word word in from word in Script.Instance.Words where word.Name.Equals(term) select word)
                                                                                        {
                                                                                            if (this.messageCollection[this.historyPoint.Value].Attachments.Any(e2 => word.Attributes.Contains(e2.Title)) && !word.Attributes.Contains(attribute))
                                                                                            {
                                                                                                word.Attributes.Add(attribute);
                                                                                            }

                                                                                            if (!word.HasAttributes)
                                                                                            {
                                                                                                wordList.Add(word);
                                                                                            }

                                                                                            isNewWord = false;
                                                                                        }

                                                                                        if (isNewWord)
                                                                                        {
                                                                                            Word newWord = new Word();

                                                                                            newWord.Name = term;
                                                                                            newWord.Attributes.Add(attribute);

                                                                                            Script.Instance.Words.Add(newWord);
                                                                                        }

                                                                                        wordList.ForEach(delegate (Word word)
                                                                                        {
                                                                                            Script.Instance.Words.Remove(word);
                                                                                        });
                                                                                    }
                                                                                }

                                                                                attachmentEntry.Enabled = false;
                                                                            }
                                                                            else
                                                                            {
                                                                                foreach (object o in this.messageCollection[this.historyPoint.Value])
                                                                                {
                                                                                    Entry e1 = o as Entry;

                                                                                    if (e1 != null)
                                                                                    {
                                                                                        string term = e1.Title;
                                                                                        string attribute = attachmentEntry.Title;
                                                                                        bool isNewWord = true;
                                                                                        List<Word> wordList = new List<Word>();

                                                                                        foreach (Word word in from word in Script.Instance.Words where word.Name.Equals(term) select word)
                                                                                        {
                                                                                            if (this.messageCollection[this.historyPoint.Value].Attachments.Any(e2 => word.Attributes.Contains(e2.Title)))
                                                                                            {
                                                                                                word.Attributes.Remove(attribute);
                                                                                            }

                                                                                            if (!word.HasAttributes)
                                                                                            {
                                                                                                wordList.Add(word);
                                                                                            }

                                                                                            isNewWord = false;
                                                                                        }

                                                                                        if (isNewWord)
                                                                                        {
                                                                                            Word newWord = new Word();

                                                                                            newWord.Name = term;
                                                                                            newWord.Attributes.Add(attribute);

                                                                                            Script.Instance.Words.Add(newWord);
                                                                                        }

                                                                                        wordList.ForEach(delegate (Word word)
                                                                                        {
                                                                                            Script.Instance.Words.Remove(word);
                                                                                        });
                                                                                    }
                                                                                }

                                                                                attachmentEntry.Enabled = true;
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                                else
                                                                {
                                                                    this.selectedIndex = index;
                                                                    this.selectedPosition = new Nullable<double>(index);
                                                                    this.previousInspectorEntry = this.inspectorEntry;
                                                                    this.nextInspectorEntry = (Entry)attachmentEntry.Clone();
                                                                }

                                                                mbea.Handled = true;
                                                            });

                                                            RenderOptions.SetClearTypeHint(attachmentTextImage, ClearTypeHint.Enabled);

                                                            attachmentCanvas.Children.Add(attachmentTextImage);

                                                            Canvas.SetLeft(attachmentTextImage, 0);
                                                            Canvas.SetTop(attachmentTextImage, 0);

                                                            this.cachedAttachmentTextImageDictionary.Add(i, attachmentTextImage);
                                                            hashSet.Add(attachmentCanvas);
                                                            updateLayoutRequired = true;
                                                        }

                                                        canvasIndex++;
                                                    }

                                                    if (this.cachedAttachmentThumbnailImageDictionary.TryGetValue(i, out attachmentThumbnailImage))
                                                    {
                                                        if (attachmentEntry.Image == null)
                                                        {
                                                            if (attachmentThumbnailImage.Source == null || popupStepIsUpdated)
                                                            {
                                                                Pen pen = new Pen(Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White, 1);
                                                                DrawingGroup dg = new DrawingGroup();
                                                                DrawingContext dc = dg.Open();
                                                                GeometryGroup gg = new GeometryGroup();
                                                                GuidelineSet gs1 = new GuidelineSet();
                                                                GuidelineSet gs2 = new GuidelineSet();

                                                                gg.FillRule = FillRule.Nonzero;
                                                                gg.Children.Add(new LineGeometry(new Point(pen.Thickness / 2, pen.Thickness / 2), new Point(imageRect.Width - pen.Thickness / 2, imageRect.Height - pen.Thickness / 2)));
                                                                gg.Children.Add(new LineGeometry(new Point(pen.Thickness / 2, imageRect.Height - pen.Thickness / 2), new Point(imageRect.Width - pen.Thickness / 2, pen.Thickness / 2)));

                                                                gs1.GuidelinesX.Add(0);
                                                                gs1.GuidelinesX.Add(imageRect.Width);
                                                                gs1.GuidelinesY.Add(0);
                                                                gs1.GuidelinesY.Add(imageRect.Height);

                                                                dc.PushGuidelineSet(gs1);
                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                dc.DrawGeometry(null, pen, gg);
                                                                dc.DrawRectangle(null, pen, new Rect(pen.Thickness / 2, pen.Thickness / 2, imageRect.Width - pen.Thickness, imageRect.Height - pen.Thickness));
                                                                dc.Close();

                                                                gs2.GuidelinesX.Add(dg.Bounds.X);
                                                                gs2.GuidelinesX.Add(dg.Bounds.X + Math.Ceiling(dg.Bounds.Width));
                                                                gs2.GuidelinesY.Add(dg.Bounds.Y);
                                                                gs2.GuidelinesY.Add(dg.Bounds.Y + Math.Ceiling(dg.Bounds.Height) + Math.Ceiling((nextRect.Height - imageRect.Height) / 2 - Math.Floor((nextRect.Height - imageRect.Height) / 2)));

                                                                dg.GuidelineSet = gs2;
                                                                dg.Children.Add(new GeometryDrawing(Brushes.Transparent, null, new RectangleGeometry(new Rect(dg.Bounds.X, dg.Bounds.Y, Math.Ceiling(dg.Bounds.Width), Math.Ceiling(dg.Bounds.Height) + Math.Ceiling((nextRect.Height - imageRect.Height) / 2 - Math.Floor((nextRect.Height - imageRect.Height) / 2))))));

                                                                DrawingImage di = new DrawingImage(dg);

                                                                if (di.CanFreeze)
                                                                {
                                                                    di.Freeze();
                                                                }

                                                                attachmentThumbnailImage.Source = di;
                                                                attachmentThumbnailImage.Width = Math.Ceiling(dg.Bounds.Width);
                                                                attachmentThumbnailImage.Height = Math.Ceiling(dg.Bounds.Height) + Math.Ceiling((nextRect.Height - imageRect.Height) / 2 - Math.Floor((nextRect.Height - imageRect.Height) / 2));
                                                            }
                                                        }
                                                        else
                                                        {
                                                            if (attachmentThumbnailImage.Source == null || slideStepIsUpdated || isLoading || popupStepIsUpdated)
                                                            {
                                                                BitmapImage attachedBitmapImage;
                                                                BitmapImage previousAttachedBitmapImage;
                                                                Pen pen = new Pen(Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White, 1);
                                                                DrawingGroup dg = new DrawingGroup();
                                                                DrawingContext dc = dg.Open();
                                                                GeometryGroup gg = new GeometryGroup();
                                                                GuidelineSet gs1 = new GuidelineSet();
                                                                GuidelineSet gs2 = new GuidelineSet();

                                                                gs1.GuidelinesX.Add(0);
                                                                gs1.GuidelinesX.Add(imageRect.Width);
                                                                gs1.GuidelinesY.Add(0);
                                                                gs1.GuidelinesY.Add(imageRect.Height);

                                                                dc.PushGuidelineSet(gs1);

                                                                if (this.imageDictionary.TryGetValue(attachmentEntry.Image, out attachedBitmapImage))
                                                                {
                                                                    if (this.attachmentImageDictionary.TryGetValue(i, out previousAttachedBitmapImage) && attachedBitmapImage == null)
                                                                    {
                                                                        attachedBitmapImage = previousAttachedBitmapImage;
                                                                    }
                                                                }
                                                                else if (this.attachmentImageDictionary.TryGetValue(i, out previousAttachedBitmapImage))
                                                                {
                                                                    attachedBitmapImage = previousAttachedBitmapImage;
                                                                }

                                                                if (attachedBitmapImage == previousAttachedBitmapImage && attachedBitmapImage != null)
                                                                {
                                                                    ImageBrush imageBrush = new ImageBrush(attachedBitmapImage);

                                                                    imageBrush.TileMode = TileMode.None;
                                                                    imageBrush.Stretch = Stretch.Fill;
                                                                    imageBrush.ViewboxUnits = BrushMappingMode.Absolute;
                                                                    imageBrush.Viewbox = new Rect(attachedBitmapImage.Width > attachedBitmapImage.Height ? (attachedBitmapImage.Width - attachedBitmapImage.Height) / 2 : 0, attachedBitmapImage.Width > attachedBitmapImage.Height ? 0 : (attachedBitmapImage.Height - attachedBitmapImage.Width) / 2, attachedBitmapImage.Width > attachedBitmapImage.Height ? attachedBitmapImage.Height : attachedBitmapImage.Width, attachedBitmapImage.Width > attachedBitmapImage.Height ? attachedBitmapImage.Height : attachedBitmapImage.Width);
                                                                    imageBrush.AlignmentX = AlignmentX.Left;
                                                                    imageBrush.AlignmentY = AlignmentY.Top;

                                                                    dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                    dc.DrawRectangle(imageBrush, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                }
                                                                else
                                                                {
                                                                    if (previousAttachedBitmapImage == null)
                                                                    {
                                                                        dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                        dc.PushTransform(new TranslateTransform(-loadStep * 20, 0));
                                                                        dc.PushClip(new RectangleGeometry(new Rect(loadStep * 20, 0, imageRect.Width, imageRect.Height)));
                                                                        dc.DrawRectangle(CreateStripeBrush(new SolidColorBrush(Color.FromArgb((byte)(Colors.Black.A * 10 / 100), Colors.Black.R, Colors.Black.G, Colors.Black.B)), new Size(20, 20)), null, new Rect(0, 0, imageRect.Width + 20, imageRect.Height));
                                                                        dc.Pop();
                                                                        dc.Pop();
                                                                    }
                                                                    else
                                                                    {
                                                                        ImageBrush previousImageBrush = new ImageBrush(previousAttachedBitmapImage);

                                                                        previousImageBrush.TileMode = TileMode.None;
                                                                        previousImageBrush.Stretch = Stretch.Fill;
                                                                        previousImageBrush.ViewboxUnits = BrushMappingMode.Absolute;
                                                                        previousImageBrush.Viewbox = new Rect(previousAttachedBitmapImage.Width > previousAttachedBitmapImage.Height ? (previousAttachedBitmapImage.Width - previousAttachedBitmapImage.Height) / 2 : 0, previousAttachedBitmapImage.Width > previousAttachedBitmapImage.Height ? 0 : (previousAttachedBitmapImage.Height - previousAttachedBitmapImage.Width) / 2, previousAttachedBitmapImage.Width > previousAttachedBitmapImage.Height ? previousAttachedBitmapImage.Height : previousAttachedBitmapImage.Width, previousAttachedBitmapImage.Width > previousAttachedBitmapImage.Height ? previousAttachedBitmapImage.Height : previousAttachedBitmapImage.Width);
                                                                        previousImageBrush.AlignmentX = AlignmentX.Left;
                                                                        previousImageBrush.AlignmentY = AlignmentY.Top;

                                                                        dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                        dc.DrawRectangle(previousImageBrush, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                    }

                                                                    if (attachedBitmapImage != null)
                                                                    {
                                                                        double step = Math.Sin(slideStep / 2 * Math.PI);
                                                                        StreamGeometry streamGeometry = new StreamGeometry();

                                                                        streamGeometry.FillRule = FillRule.Nonzero;

                                                                        using (StreamGeometryContext streamGeometryContext = streamGeometry.Open())
                                                                        {
                                                                            streamGeometryContext.BeginFigure(new Point(0, 0), true, true);

                                                                            if (step <= 0.5)
                                                                            {
                                                                                streamGeometryContext.LineTo(new Point(imageRect.Width * step / 0.5, 0), true, false);
                                                                                streamGeometryContext.LineTo(new Point(0, imageRect.Height * step / 0.5), true, false);
                                                                            }
                                                                            else
                                                                            {
                                                                                streamGeometryContext.LineTo(new Point(imageRect.Width, 0), true, false);
                                                                                streamGeometryContext.LineTo(new Point(imageRect.Width, imageRect.Height * (step - 0.5) / 0.5), true, false);
                                                                                streamGeometryContext.LineTo(new Point(imageRect.Width * (step - 0.5) / 0.5, imageRect.Height), true, false);
                                                                                streamGeometryContext.LineTo(new Point(0, imageRect.Height), true, false);
                                                                            }
                                                                        }

                                                                        ImageBrush imageBrush = new ImageBrush(attachedBitmapImage);

                                                                        imageBrush.TileMode = TileMode.None;
                                                                        imageBrush.Stretch = Stretch.Fill;
                                                                        imageBrush.ViewboxUnits = BrushMappingMode.Absolute;
                                                                        imageBrush.Viewbox = new Rect(attachedBitmapImage.Width > attachedBitmapImage.Height ? (attachedBitmapImage.Width - attachedBitmapImage.Height) / 2 : 0, attachedBitmapImage.Width > attachedBitmapImage.Height ? 0 : (attachedBitmapImage.Height - attachedBitmapImage.Width) / 2, attachedBitmapImage.Width > attachedBitmapImage.Height ? attachedBitmapImage.Height : attachedBitmapImage.Width, attachedBitmapImage.Width > attachedBitmapImage.Height ? attachedBitmapImage.Height : attachedBitmapImage.Width);
                                                                        imageBrush.AlignmentX = AlignmentX.Left;
                                                                        imageBrush.AlignmentY = AlignmentY.Top;

                                                                        dc.PushClip(streamGeometry);
                                                                        dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                        dc.DrawRectangle(imageBrush, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                        dc.Pop();
                                                                    }
                                                                }

                                                                dc.DrawRectangle(null, pen, new Rect(pen.Thickness / 2, pen.Thickness / 2, imageRect.Width - pen.Thickness, imageRect.Height - pen.Thickness));
                                                                dc.Close();

                                                                gs2.GuidelinesX.Add(dg.Bounds.X);
                                                                gs2.GuidelinesX.Add(dg.Bounds.X + Math.Ceiling(dg.Bounds.Width));
                                                                gs2.GuidelinesY.Add(dg.Bounds.Y);
                                                                gs2.GuidelinesY.Add(dg.Bounds.Y + Math.Ceiling(dg.Bounds.Height) + Math.Ceiling((nextRect.Height - imageRect.Height) / 2 - Math.Floor((nextRect.Height - imageRect.Height) / 2)));

                                                                dg.GuidelineSet = gs2;
                                                                dg.Children.Add(new GeometryDrawing(Brushes.Transparent, null, new RectangleGeometry(new Rect(dg.Bounds.X, dg.Bounds.Y, Math.Ceiling(dg.Bounds.Width), Math.Ceiling(dg.Bounds.Height) + Math.Ceiling((nextRect.Height - imageRect.Height) / 2 - Math.Floor((nextRect.Height - imageRect.Height) / 2))))));

                                                                DrawingImage di = new DrawingImage(dg);

                                                                if (di.CanFreeze)
                                                                {
                                                                    di.Freeze();
                                                                }

                                                                attachmentThumbnailImage.Source = di;
                                                                attachmentThumbnailImage.Width = Math.Ceiling(dg.Bounds.Width);
                                                                attachmentThumbnailImage.Height = Math.Ceiling(dg.Bounds.Height) + Math.Ceiling((nextRect.Height - imageRect.Height) / 2 - Math.Floor((nextRect.Height - imageRect.Height) / 2));
                                                            }
                                                        }

                                                        attachmentThumbnailImage.Opacity = opacity;

                                                        Canvas.SetLeft(attachmentThumbnailImage, imageRect.X);
                                                        Canvas.SetTop(attachmentThumbnailImage, imageRect.Y);

                                                        hashSet.Add(attachmentThumbnailImage);
                                                    }
                                                    else
                                                    {
                                                        int index = i;
                                                        Pen pen = new Pen(Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White, 1);
                                                        DrawingGroup dg = new DrawingGroup();
                                                        DrawingContext dc = dg.Open();
                                                        GuidelineSet gs1 = new GuidelineSet();
                                                        GuidelineSet gs2 = new GuidelineSet();

                                                        if (attachmentEntry.Image == null)
                                                        {
                                                            GeometryGroup gg = new GeometryGroup();

                                                            gg.FillRule = FillRule.Nonzero;
                                                            gg.Children.Add(new LineGeometry(new Point(pen.Thickness / 2, pen.Thickness / 2), new Point(imageRect.Width - pen.Thickness / 2, imageRect.Height - pen.Thickness / 2)));
                                                            gg.Children.Add(new LineGeometry(new Point(pen.Thickness / 2, imageRect.Height - pen.Thickness / 2), new Point(imageRect.Width - pen.Thickness / 2, pen.Thickness / 2)));

                                                            gs1.GuidelinesX.Add(0);
                                                            gs1.GuidelinesX.Add(imageRect.Width);
                                                            gs1.GuidelinesY.Add(0);
                                                            gs1.GuidelinesY.Add(imageRect.Height);

                                                            dc.PushGuidelineSet(gs1);
                                                            dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                            dc.DrawGeometry(null, pen, gg);
                                                            dc.DrawRectangle(null, pen, new Rect(pen.Thickness / 2, pen.Thickness / 2, imageRect.Width - pen.Thickness, imageRect.Height - pen.Thickness));
                                                            dc.Close();

                                                            gs2.GuidelinesX.Add(dg.Bounds.X);
                                                            gs2.GuidelinesX.Add(dg.Bounds.X + Math.Ceiling(dg.Bounds.Width));
                                                            gs2.GuidelinesY.Add(dg.Bounds.Y);
                                                            gs2.GuidelinesY.Add(dg.Bounds.Y + Math.Ceiling(dg.Bounds.Height) + Math.Ceiling((nextRect.Height - imageRect.Height) / 2 - Math.Floor((nextRect.Height - imageRect.Height) / 2)));

                                                            dg.GuidelineSet = gs2;
                                                            dg.Children.Add(new GeometryDrawing(Brushes.Transparent, null, new RectangleGeometry(new Rect(dg.Bounds.X, dg.Bounds.Y, Math.Ceiling(dg.Bounds.Width), Math.Ceiling(dg.Bounds.Height) + Math.Ceiling((nextRect.Height - imageRect.Height) / 2 - Math.Floor((nextRect.Height - imageRect.Height) / 2))))));
                                                        }
                                                        else
                                                        {
                                                            BitmapImage attachedBitmapImage;
                                                            BitmapImage previousAttachedBitmapImage;

                                                            gs1.GuidelinesX.Add(0);
                                                            gs1.GuidelinesX.Add(imageRect.Width);
                                                            gs1.GuidelinesY.Add(0);
                                                            gs1.GuidelinesY.Add(imageRect.Height);

                                                            dc.PushGuidelineSet(gs1);

                                                            if (this.imageDictionary.TryGetValue(attachmentEntry.Image, out attachedBitmapImage))
                                                            {
                                                                if (this.attachmentImageDictionary.TryGetValue(i, out previousAttachedBitmapImage) && attachedBitmapImage == null)
                                                                {
                                                                    attachedBitmapImage = previousAttachedBitmapImage;
                                                                }
                                                            }
                                                            else if (this.attachmentImageDictionary.TryGetValue(i, out previousAttachedBitmapImage))
                                                            {
                                                                attachedBitmapImage = previousAttachedBitmapImage;
                                                            }

                                                            if (attachedBitmapImage == previousAttachedBitmapImage && attachedBitmapImage != null)
                                                            {
                                                                ImageBrush imageBrush = new ImageBrush(attachedBitmapImage);

                                                                imageBrush.TileMode = TileMode.None;
                                                                imageBrush.Stretch = Stretch.Fill;
                                                                imageBrush.ViewboxUnits = BrushMappingMode.Absolute;
                                                                imageBrush.Viewbox = new Rect(attachedBitmapImage.Width > attachedBitmapImage.Height ? (attachedBitmapImage.Width - attachedBitmapImage.Height) / 2 : 0, attachedBitmapImage.Width > attachedBitmapImage.Height ? 0 : (attachedBitmapImage.Height - attachedBitmapImage.Width) / 2, attachedBitmapImage.Width > attachedBitmapImage.Height ? attachedBitmapImage.Height : attachedBitmapImage.Width, attachedBitmapImage.Width > attachedBitmapImage.Height ? attachedBitmapImage.Height : attachedBitmapImage.Width);
                                                                imageBrush.AlignmentX = AlignmentX.Left;
                                                                imageBrush.AlignmentY = AlignmentY.Top;

                                                                dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                dc.DrawRectangle(imageBrush, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                            }
                                                            else
                                                            {
                                                                if (previousAttachedBitmapImage == null)
                                                                {
                                                                    dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                    dc.PushTransform(new TranslateTransform(-loadStep * 20, 0));
                                                                    dc.PushClip(new RectangleGeometry(new Rect(loadStep * 20, 0, imageRect.Width, imageRect.Height)));
                                                                    dc.DrawRectangle(CreateStripeBrush(new SolidColorBrush(Color.FromArgb((byte)(Colors.Black.A * 10 / 100), Colors.Black.R, Colors.Black.G, Colors.Black.B)), new Size(20, 20)), null, new Rect(0, 0, imageRect.Width + 20, imageRect.Height));
                                                                    dc.Pop();
                                                                    dc.Pop();
                                                                }
                                                                else
                                                                {
                                                                    ImageBrush previousImageBrush = new ImageBrush(previousAttachedBitmapImage);

                                                                    previousImageBrush.TileMode = TileMode.None;
                                                                    previousImageBrush.Stretch = Stretch.Fill;
                                                                    previousImageBrush.ViewboxUnits = BrushMappingMode.Absolute;
                                                                    previousImageBrush.Viewbox = new Rect(previousAttachedBitmapImage.Width > previousAttachedBitmapImage.Height ? (previousAttachedBitmapImage.Width - previousAttachedBitmapImage.Height) / 2 : 0, previousAttachedBitmapImage.Width > previousAttachedBitmapImage.Height ? 0 : (previousAttachedBitmapImage.Height - previousAttachedBitmapImage.Width) / 2, previousAttachedBitmapImage.Width > previousAttachedBitmapImage.Height ? previousAttachedBitmapImage.Height : previousAttachedBitmapImage.Width, previousAttachedBitmapImage.Width > previousAttachedBitmapImage.Height ? previousAttachedBitmapImage.Height : previousAttachedBitmapImage.Width);
                                                                    previousImageBrush.AlignmentX = AlignmentX.Left;
                                                                    previousImageBrush.AlignmentY = AlignmentY.Top;

                                                                    dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                    dc.DrawRectangle(previousImageBrush, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                }

                                                                if (attachedBitmapImage != null)
                                                                {
                                                                    double step = Math.Sin(slideStep / 2 * Math.PI);
                                                                    StreamGeometry streamGeometry = new StreamGeometry();

                                                                    streamGeometry.FillRule = FillRule.Nonzero;

                                                                    using (StreamGeometryContext streamGeometryContext = streamGeometry.Open())
                                                                    {
                                                                        streamGeometryContext.BeginFigure(new Point(0, 0), true, true);

                                                                        if (step <= 0.5)
                                                                        {
                                                                            streamGeometryContext.LineTo(new Point(imageRect.Width * step / 0.5, 0), true, false);
                                                                            streamGeometryContext.LineTo(new Point(0, imageRect.Height * step / 0.5), true, false);
                                                                        }
                                                                        else
                                                                        {
                                                                            streamGeometryContext.LineTo(new Point(imageRect.Width, 0), true, false);
                                                                            streamGeometryContext.LineTo(new Point(imageRect.Width, imageRect.Height * (step - 0.5) / 0.5), true, false);
                                                                            streamGeometryContext.LineTo(new Point(imageRect.Width * (step - 0.5) / 0.5, imageRect.Height), true, false);
                                                                            streamGeometryContext.LineTo(new Point(0, imageRect.Height), true, false);
                                                                        }
                                                                    }

                                                                    ImageBrush imageBrush = new ImageBrush(attachedBitmapImage);

                                                                    imageBrush.TileMode = TileMode.None;
                                                                    imageBrush.Stretch = Stretch.Fill;
                                                                    imageBrush.ViewboxUnits = BrushMappingMode.Absolute;
                                                                    imageBrush.Viewbox = new Rect(attachedBitmapImage.Width > attachedBitmapImage.Height ? (attachedBitmapImage.Width - attachedBitmapImage.Height) / 2 : 0, attachedBitmapImage.Width > attachedBitmapImage.Height ? 0 : (attachedBitmapImage.Height - attachedBitmapImage.Width) / 2, attachedBitmapImage.Width > attachedBitmapImage.Height ? attachedBitmapImage.Height : attachedBitmapImage.Width, attachedBitmapImage.Width > attachedBitmapImage.Height ? attachedBitmapImage.Height : attachedBitmapImage.Width);
                                                                    imageBrush.AlignmentX = AlignmentX.Left;
                                                                    imageBrush.AlignmentY = AlignmentY.Top;

                                                                    dc.PushClip(streamGeometry);
                                                                    dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                    dc.DrawRectangle(imageBrush, null, new Rect(0, 0, imageRect.Width, imageRect.Height));
                                                                    dc.Pop();
                                                                }
                                                            }

                                                            dc.DrawRectangle(null, pen, new Rect(pen.Thickness / 2, pen.Thickness / 2, imageRect.Width - pen.Thickness, imageRect.Height - pen.Thickness));
                                                            dc.Close();

                                                            gs2.GuidelinesX.Add(dg.Bounds.X);
                                                            gs2.GuidelinesX.Add(dg.Bounds.X + Math.Ceiling(dg.Bounds.Width));
                                                            gs2.GuidelinesY.Add(dg.Bounds.Y);
                                                            gs2.GuidelinesY.Add(dg.Bounds.Y + Math.Ceiling(dg.Bounds.Height) + Math.Ceiling((nextRect.Height - imageRect.Height) / 2 - Math.Floor((nextRect.Height - imageRect.Height) / 2)));

                                                            dg.GuidelineSet = gs2;
                                                            dg.Children.Add(new GeometryDrawing(Brushes.Transparent, null, new RectangleGeometry(new Rect(dg.Bounds.X, dg.Bounds.Y, Math.Ceiling(dg.Bounds.Width), Math.Ceiling(dg.Bounds.Height) + Math.Ceiling((nextRect.Height - imageRect.Height) / 2 - Math.Floor((nextRect.Height - imageRect.Height) / 2))))));
                                                        }

                                                        DrawingImage di = new DrawingImage(dg);

                                                        if (di.CanFreeze)
                                                        {
                                                            di.Freeze();
                                                        }

                                                        attachmentThumbnailImage = new Image();
                                                        attachmentThumbnailImage.HorizontalAlignment = HorizontalAlignment.Left;
                                                        attachmentThumbnailImage.VerticalAlignment = VerticalAlignment.Top;
                                                        attachmentThumbnailImage.Stretch = Stretch.None;
                                                        attachmentThumbnailImage.Source = di;
                                                        attachmentThumbnailImage.Width = Math.Ceiling(dg.Bounds.Width);
                                                        attachmentThumbnailImage.Height = Math.Ceiling(dg.Bounds.Height) + Math.Ceiling((nextRect.Height - imageRect.Height) / 2 - Math.Floor((nextRect.Height - imageRect.Height) / 2));
                                                        attachmentThumbnailImage.Opacity = opacity;
                                                        attachmentThumbnailImage.MouseEnter += new MouseEventHandler(delegate
                                                        {
                                                            this.hoverIndex = new Nullable<int>(index);
                                                        });
                                                        attachmentThumbnailImage.MouseLeave += new MouseEventHandler(delegate
                                                        {
                                                            this.hoverIndex = null;
                                                        });
                                                        attachmentThumbnailImage.MouseLeftButtonUp += new MouseButtonEventHandler(delegate (object s, MouseButtonEventArgs mbea)
                                                        {
                                                            if (this.hoverIndex.HasValue && !this.attachmentIsScrollableHashSet.Contains(this.hoverIndex.Value))
                                                            {
                                                                this.attachmentIsScrollableHashSet.Add(this.hoverIndex.Value);
                                                            }

                                                            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                                                            {
                                                                if (attachmentEntry.Resource != null)
                                                                {
                                                                    Task.Factory.StartNew(delegate (object state)
                                                                    {
                                                                        System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo((string)state));
                                                                    }, attachmentEntry.Resource.ToString());
                                                                }
                                                                else if (!String.IsNullOrEmpty(attachmentEntry.Title))
                                                                {
                                                                    if (attachmentEntry.ReadOnly)
                                                                    {
                                                                        Script.Instance.Search(attachmentEntry.Title);
                                                                    }
                                                                    else
                                                                    {
                                                                        if (attachmentEntry.Enabled)
                                                                        {
                                                                            foreach (object o in this.messageCollection[this.historyPoint.Value])
                                                                            {
                                                                                Entry e1 = o as Entry;

                                                                                if (e1 != null)
                                                                                {
                                                                                    string term = e1.Title;
                                                                                    string attribute = attachmentEntry.Title;
                                                                                    bool isNewWord = true;
                                                                                    List<Word> wordList = new List<Word>();

                                                                                    foreach (Word word in from word in Script.Instance.Words where word.Name.Equals(term) select word)
                                                                                    {
                                                                                        if (this.messageCollection[this.historyPoint.Value].Attachments.Any(e2 => word.Attributes.Contains(e2.Title)) && !word.Attributes.Contains(attribute))
                                                                                        {
                                                                                            word.Attributes.Add(attribute);
                                                                                        }

                                                                                        if (!word.HasAttributes)
                                                                                        {
                                                                                            wordList.Add(word);
                                                                                        }

                                                                                        isNewWord = false;
                                                                                    }

                                                                                    if (isNewWord)
                                                                                    {
                                                                                        Word newWord = new Word();

                                                                                        newWord.Name = term;
                                                                                        newWord.Attributes.Add(attribute);

                                                                                        Script.Instance.Words.Add(newWord);
                                                                                    }

                                                                                    wordList.ForEach(delegate (Word word)
                                                                                    {
                                                                                        Script.Instance.Words.Remove(word);
                                                                                    });
                                                                                }
                                                                            }

                                                                            attachmentEntry.Enabled = false;
                                                                        }
                                                                        else
                                                                        {
                                                                            foreach (object o in this.messageCollection[this.historyPoint.Value])
                                                                            {
                                                                                Entry e1 = o as Entry;

                                                                                if (e1 != null)
                                                                                {
                                                                                    string term = e1.Title;
                                                                                    string attribute = attachmentEntry.Title;
                                                                                    bool isNewWord = true;
                                                                                    List<Word> wordList = new List<Word>();

                                                                                    foreach (Word word in from word in Script.Instance.Words where word.Name.Equals(term) select word)
                                                                                    {
                                                                                        if (this.messageCollection[this.historyPoint.Value].Attachments.Any(e2 => word.Attributes.Contains(e2.Title)))
                                                                                        {
                                                                                            word.Attributes.Remove(attribute);
                                                                                        }

                                                                                        if (!word.HasAttributes)
                                                                                        {
                                                                                            wordList.Add(word);
                                                                                        }

                                                                                        isNewWord = false;
                                                                                    }

                                                                                    if (isNewWord)
                                                                                    {
                                                                                        Word newWord = new Word();

                                                                                        newWord.Name = term;
                                                                                        newWord.Attributes.Add(attribute);

                                                                                        Script.Instance.Words.Add(newWord);
                                                                                    }

                                                                                    wordList.ForEach(delegate (Word word)
                                                                                    {
                                                                                        Script.Instance.Words.Remove(word);
                                                                                    });
                                                                                }
                                                                            }

                                                                            attachmentEntry.Enabled = true;
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                            else
                                                            {
                                                                this.selectedIndex = index;
                                                                this.selectedPosition = new Nullable<double>(index);
                                                                this.previousInspectorEntry = this.inspectorEntry;
                                                                this.nextInspectorEntry = (Entry)attachmentEntry.Clone();
                                                            }

                                                            mbea.Handled = true;
                                                        });

                                                        PresentationSource presentationSource = PresentationSource.FromVisual(this);

                                                        if (presentationSource != null && presentationSource.CompositionTarget != null && presentationSource.CompositionTarget.TransformToDevice.M11 == 1.0 && presentationSource.CompositionTarget.TransformToDevice.M22 == 1.0)
                                                        {
                                                            RenderOptions.SetEdgeMode(attachmentThumbnailImage, EdgeMode.Aliased);
                                                        }

                                                        this.MessageCanvas.Children.Insert(canvasIndex, attachmentThumbnailImage);

                                                        Canvas.SetLeft(attachmentThumbnailImage, imageRect.X);
                                                        Canvas.SetTop(attachmentThumbnailImage, imageRect.Y);

                                                        this.cachedAttachmentThumbnailImageDictionary.Add(i, attachmentThumbnailImage);
                                                        hashSet.Add(attachmentThumbnailImage);
                                                        updateLayoutRequired = true;
                                                    }

                                                    nextRect.Y += this.lineHeight;
                                                    canvasIndex++;
                                                }
                                            }
                                            else if (offset <= i && i < offset + length)
                                            {
                                                nextRect.Y += this.lineHeight;
                                            }
                                        }

                                        if (isImcomplete)
                                        {
                                            if (waitRequired)
                                            {
                                                waitRequired = false;
                                            }
                                        }
                                        else
                                        {
                                            waitRequired = true;
                                        }

                                        foreach (KeyValuePair<int, Image> kvp in (from kvp in this.cachedAttachmentThumbnailImageDictionary where !hashSet.Contains(kvp.Value) select kvp).ToArray())
                                        {
                                            this.MessageCanvas.Children.Remove(kvp.Value);
                                            this.cachedAttachmentThumbnailImageDictionary.Remove(kvp.Key);
                                        }

                                        foreach (KeyValuePair<int, Canvas> kvp in (from kvp in this.cachedAttachmentTextImageDictionary let canvas = kvp.Value.Parent as Canvas where canvas != null && !hashSet.Contains(kvp.Value.Parent) select new KeyValuePair<int, Canvas>(kvp.Key, canvas)).ToArray())
                                        {
                                            this.MessageCanvas.Children.Remove(kvp.Value);
                                            this.cachedAttachmentTextImageDictionary.Remove(kvp.Key);
                                        }
                                    }
                                }

                                if (this.counterScrollStep.HasValue && this.cachedCounterCanvas == null || this.counterScrollStep == null && this.cachedCounterCanvas != null)
                                {
                                    int minScrollIndex = (int)Math.Floor(Math.Min(this.sourceScrollPosition, this.targetScrollPosition));
                                    int messageLines = inlinePointList.Value.Aggregate<Point, HashSet<double>>(new HashSet<double>(), (hashSet, point) =>
                                    {
                                        if (!hashSet.Contains(point.Y))
                                        {
                                            hashSet.Add(point.Y);
                                        }

                                        return hashSet;
                                    }).Count;
                                    int maxLines = messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count < this.numberOfLines ? messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count : this.numberOfLines;
                                    int usedLines = messageLines - minScrollIndex;

                                    if (usedLines < 0)
                                    {
                                        usedLines = 0;
                                    }

                                    int actualLines = usedLines + this.messageCollection[this.historyPoint.Value].Attachments.Count;

                                    if (actualLines > maxLines)
                                    {
                                        actualLines = maxLines;
                                    }

                                    this.ScrollCanvas.Width = this.MessageCanvas.Width = this.maxMessageSize.Width;
                                    this.ScrollCanvas.Height = this.lineHeight * actualLines;
                                    this.MessageCanvas.Height = this.lineHeight * (this.counterScrollStep.HasValue ? actualLines + paddingLines + 1 : actualLines + paddingLines);

                                    if (this.cachedCounterCanvas == null)
                                    {
                                        FormattedText formattedText = new FormattedText(this.messageCollection[this.historyPoint.Value].Attachments.Count.ToString(System.Globalization.CultureInfo.CurrentCulture), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.textBrush);
                                        double width = Math.Ceiling(formattedText.Width) - Math.Floor(formattedText.OverhangLeading) - Math.Floor(formattedText.OverhangTrailing);
                                        double height = formattedText.OverhangAfter > 0 ? formattedText.Height + formattedText.OverhangAfter : formattedText.Height;
                                        DropShadowEffect dropShadowEffect = new DropShadowEffect();
                                        Image image = new Image();
                                        DrawingGroup dg = new DrawingGroup();
                                        DrawingContext dc = dg.Open();

                                        dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, width, height));
                                        dc.DrawText(formattedText, new Point(-Math.Floor(formattedText.OverhangLeading), 0));
                                        dc.Close();

                                        DrawingImage di = new DrawingImage(dg);

                                        if (di.CanFreeze)
                                        {
                                            di.Freeze();
                                        }

                                        image.HorizontalAlignment = HorizontalAlignment.Left;
                                        image.VerticalAlignment = VerticalAlignment.Top;
                                        image.Source = di;
                                        image.Stretch = Stretch.None;
                                        image.Width = width;
                                        image.Height = height;

                                        RenderOptions.SetClearTypeHint(image, ClearTypeHint.Enabled);

                                        dropShadowEffect.Color = Math.Max(Math.Max(this.textColor.R, this.textColor.G), this.textColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;
                                        dropShadowEffect.BlurRadius = 1;
                                        dropShadowEffect.Direction = 270;
                                        dropShadowEffect.ShadowDepth = 1;
                                        dropShadowEffect.Opacity = 0.5;

                                        if (dropShadowEffect.CanFreeze)
                                        {
                                            dropShadowEffect.Freeze();
                                        }

                                        this.cachedCounterCanvas = new Canvas();
                                        this.cachedCounterCanvas.HorizontalAlignment = HorizontalAlignment.Left;
                                        this.cachedCounterCanvas.VerticalAlignment = VerticalAlignment.Top;
                                        this.cachedCounterCanvas.Background = Brushes.Transparent;
                                        this.cachedCounterCanvas.Width = width;
                                        this.cachedCounterCanvas.Height = height;
                                        this.cachedCounterCanvas.Effect = dropShadowEffect;
                                        this.cachedCounterCanvas.Children.Add(image);

                                        Canvas.SetLeft(image, 0);
                                        Canvas.SetTop(image, 0);

                                        this.MessageCanvas.Children.Add(this.cachedCounterCanvas);

                                        Canvas.SetLeft(this.cachedCounterCanvas, (this.Canvas.Width - this.cachedCounterCanvas.Width) / 2 - Canvas.GetLeft(this.ScrollCanvas) + Math.Floor(formattedText.OverhangLeading));
                                        Canvas.SetTop(this.cachedCounterCanvas, this.lineHeight * (actualLines + paddingLines) + (this.lineHeight - formattedText.Height) / 2);
                                    }
                                    else
                                    {
                                        this.MessageCanvas.Children.Remove(this.cachedCounterCanvas);
                                        this.cachedCounterCanvas = null;
                                    }

                                    updateLayoutRequired = true;
                                }

                                if (paddingLines > 0)
                                {
                                    if (this.sourceScrollPosition > this.targetScrollPosition)
                                    {
                                        this.TranslateTransform.Y = -Math.Floor(this.counterScrollStep.HasValue ? this.lineHeight * paddingLines * ((this.targetScrollPosition - Math.Floor(this.targetScrollPosition)) / paddingLines) + this.lineHeight * paddingLines * (Math.Abs(this.targetScrollPosition - this.sourceScrollPosition) / paddingLines) * this.scrollIndexStep + this.lineHeight * Math.Sin(this.counterScrollStep.Value * Math.PI) : this.lineHeight * paddingLines * ((this.targetScrollPosition - Math.Floor(this.targetScrollPosition)) / paddingLines) + this.lineHeight * paddingLines * (Math.Abs(this.targetScrollPosition - this.sourceScrollPosition) / paddingLines) * this.scrollIndexStep);
                                    }
                                    else
                                    {
                                        this.TranslateTransform.Y = -Math.Floor(this.counterScrollStep.HasValue ? this.lineHeight * paddingLines * ((this.sourceScrollPosition - Math.Floor(this.sourceScrollPosition)) / paddingLines) + this.lineHeight * paddingLines * (Math.Abs(this.targetScrollPosition - this.sourceScrollPosition) / paddingLines) * this.scrollIndexStep + this.lineHeight * Math.Sin(this.counterScrollStep.Value * Math.PI) : this.lineHeight * paddingLines * ((this.sourceScrollPosition - Math.Floor(this.sourceScrollPosition)) / paddingLines) + this.lineHeight * paddingLines * (Math.Abs(this.targetScrollPosition - this.sourceScrollPosition) / paddingLines) * this.scrollIndexStep);
                                    }
                                }
                                else
                                {
                                    this.TranslateTransform.Y = this.counterScrollStep.HasValue ? -Math.Floor(this.lineHeight * Math.Sin(this.counterScrollStep.Value * Math.PI)) : 0;
                                }

                                if (isReady && this.nextHistoryPoint.HasValue)
                                {
                                    if (this.filterStep.HasValue)
                                    {
                                        this.filterStep -= 1 / (averageFrameRate / 4);

                                        if (this.filterStep <= 0)
                                        {
                                            this.filterStep = null;
                                            this.FilterImage.Visibility = Visibility.Collapsed;
                                            this.FilterImage.Width = this.FilterImage.Height = Double.NaN;
                                            this.FilterImage.Source = null;
                                            this.FilterImage.Opacity = 0;
                                        }
                                        else
                                        {
                                            this.FilterImage.Opacity = Math.Sin(this.filterStep.Value / 2 * Math.PI);
                                        }
                                    }

                                    if (this.scrollStep.HasValue)
                                    {
                                        this.scrollStep -= 1 / (averageFrameRate / 4);

                                        if (this.scrollStep <= 0)
                                        {
                                            this.scrollStep = null;
                                            this.ScrollImage.Visibility = Visibility.Collapsed;
                                            this.ScrollImage.Width = this.ScrollImage.Height = Double.NaN;
                                            this.ScrollImage.Source = null;
                                            this.ScrollImage.Opacity = 0;
                                        }
                                        else
                                        {
                                            this.ScrollImage.Opacity = Math.Sin(this.scrollStep.Value / 2 * Math.PI);
                                        }
                                    }
                                }
                                else
                                {
                                    if (this.enableFilter)
                                    {
                                        if (this.filterStep == null)
                                        {
                                            this.filterStep = new Nullable<double>(0);
                                            this.FilterImage.Visibility = Visibility.Visible;
                                            this.FilterImage.Opacity = Math.Sin(this.filterStep.Value / 2 * Math.PI);
                                        }

                                        if (this.filterStep < 1)
                                        {
                                            this.filterStep += 1 / (averageFrameRate / 4);

                                            if (this.filterStep >= 1)
                                            {
                                                this.filterStep = 1;
                                                this.FilterImage.Opacity = 1;
                                            }
                                            else
                                            {
                                                this.FilterImage.Opacity = Math.Sin(this.filterStep.Value / 2 * Math.PI);
                                            }
                                        }
                                    }
                                    else if (this.filterStep.HasValue)
                                    {
                                        this.filterStep -= 1 / (averageFrameRate / 4);

                                        if (this.filterStep <= 0)
                                        {
                                            this.filterStep = null;
                                            this.FilterImage.Visibility = Visibility.Collapsed;
                                            this.FilterImage.Width = this.FilterImage.Height = Double.NaN;
                                            this.FilterImage.Source = null;
                                            this.FilterImage.Opacity = 0;
                                        }
                                        else
                                        {
                                            this.FilterImage.Opacity = Math.Sin(this.filterStep.Value / 2 * Math.PI);
                                        }
                                    }

                                    if (this.messageIsScrollable)
                                    {
                                        if (this.enableFilter)
                                        {
                                            if (this.scrollStep.HasValue)
                                            {
                                                this.scrollStep -= 1 / (averageFrameRate / 4);

                                                if (this.scrollStep <= 0)
                                                {
                                                    this.scrollStep = null;
                                                    this.ScrollImage.Visibility = Visibility.Collapsed;
                                                    this.ScrollImage.Width = this.ScrollImage.Height = Double.NaN;
                                                    this.ScrollImage.Source = null;
                                                    this.ScrollImage.Opacity = 0;
                                                }
                                                else
                                                {
                                                    this.ScrollImage.Opacity = Math.Sin(this.scrollStep.Value / 2 * Math.PI);
                                                }
                                            }
                                        }
                                        else
                                        {
                                            if (this.scrollStep == null)
                                            {
                                                this.scrollStep = new Nullable<double>(0);
                                                this.ScrollImage.Visibility = Visibility.Visible;
                                                this.ScrollImage.Opacity = Math.Sin(this.scrollStep.Value / 2 * Math.PI);
                                            }

                                            if (this.scrollStep < 1)
                                            {
                                                this.scrollStep += 1 / (averageFrameRate / 4);

                                                if (this.scrollStep >= 1)
                                                {
                                                    this.scrollStep = 1;
                                                    this.ScrollImage.Opacity = 1;
                                                }
                                                else
                                                {
                                                    this.ScrollImage.Opacity = Math.Sin(this.scrollStep.Value / 2 * Math.PI);
                                                }
                                            }
                                        }
                                    }
                                    else if (this.scrollStep.HasValue)
                                    {
                                        this.scrollStep -= 1 / (averageFrameRate / 4);

                                        if (this.scrollStep <= 0)
                                        {
                                            this.scrollStep = null;
                                            this.ScrollImage.Visibility = Visibility.Collapsed;
                                            this.ScrollImage.Width = this.ScrollImage.Height = Double.NaN;
                                            this.ScrollImage.Source = null;
                                            this.ScrollImage.Opacity = 0;
                                        }
                                        else
                                        {
                                            this.ScrollImage.Opacity = Math.Sin(this.scrollStep.Value / 2 * Math.PI);
                                        }
                                    }
                                }

                                if (this.enableFilter && this.filterStep.HasValue)
                                {
                                    if (this.previousThresholdScore == this.thresholdScore && this.thresholdQueue.Count > 0)
                                    {
                                        do
                                        {
                                            this.thresholdScore += this.thresholdQueue.Dequeue();
                                        } while (this.thresholdQueue.Count > 0);
                                    }

                                    if (this.previousThresholdScore != this.thresholdScore || this.FilterImage.Source == null)
                                    {
                                        int messageLines = inlinePointList.Value.Aggregate<Point, HashSet<double>>(new HashSet<double>(), (hashSet, point) =>
                                        {
                                            if (!hashSet.Contains(point.Y))
                                            {
                                                hashSet.Add(point.Y);
                                            }

                                            return hashSet;
                                        }).Count;
                                        double totalMessageHeight = this.lineHeight * (messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count);
                                        int maxLines = messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count < this.numberOfLines ? messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count : this.numberOfLines;
                                        int usedLines = messageLines - (int)Math.Floor(Math.Min(this.sourceScrollPosition, this.targetScrollPosition));
                                        int maxVisibleLines = this.numberOfLines;
                                        double maxVisibleHeight = 0;

                                        if (usedLines < 0)
                                        {
                                            usedLines = 0;
                                        }

                                        int actualLines = usedLines + this.messageCollection[this.historyPoint.Value].Attachments.Count;

                                        if (actualLines > maxLines)
                                        {
                                            actualLines = maxLines;
                                        }

                                        double height = this.lineHeight * actualLines;

                                        if (this.Canvas.Height - this.baseFooterHeight < Canvas.GetTop(this.ScrollCanvas) + height)
                                        {
                                            height = this.Canvas.Height - this.baseFooterHeight - Canvas.GetTop(this.ScrollCanvas);
                                        }

                                        height -= 14;

                                        if (height > 0)
                                        {
                                            maxVisibleHeight = height;
                                        }

                                        if (this.previousThresholdScore != this.thresholdScore)
                                        {
                                            this.thresholdScoreStep += 1 / (averageFrameRate / 4);

                                            if (this.thresholdScoreStep >= 1)
                                            {
                                                this.thresholdScoreStep = 0;
                                                this.previousThresholdScore = this.thresholdScore;
                                            }
                                        }

                                        Size blockSize = new Size(3, maxVisibleHeight);
                                        Rect sourceRect = new Rect(Canvas.GetLeft(this.FilterImage), Canvas.GetTop(this.FilterImage) + (blockSize.Height - 1) * (this.previousThresholdScore - this.minScore) / (this.maxScore - this.minScore), blockSize.Width, 1);
                                        Rect targetRect = new Rect(Canvas.GetLeft(this.FilterImage), Canvas.GetTop(this.FilterImage) + (blockSize.Height - 1) * (this.thresholdScore - this.minScore) / (this.maxScore - this.minScore), blockSize.Width, 1);
                                        Color color = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;
                                        GeometryGroup gg = new GeometryGroup();
                                        DrawingGroup dg = new DrawingGroup();
                                        DrawingContext dc = dg.Open();
                                        GuidelineSet gs1 = new GuidelineSet();

                                        gs1.GuidelinesX.Add(0);
                                        gs1.GuidelinesX.Add(blockSize.Width);
                                        gs1.GuidelinesY.Add(0);
                                        gs1.GuidelinesY.Add(blockSize.Height);

                                        dc.PushGuidelineSet(gs1);
                                        dc.DrawRectangle(CreateStripeBrush(new SolidColorBrush(Color.FromArgb((byte)(color.A * 25 / 100), color.R, color.G, color.B)), new Size(3, 3)), null, new Rect(0, 0, blockSize.Width, blockSize.Height));
                                        dc.Pop();

                                        if (this.maxScore - this.minScore != 0)
                                        {
                                            Rect filterOverlayRect = new Rect(new Point(0, sourceRect.Y - Canvas.GetTop(this.FilterImage)), sourceRect.Size);
                                            GuidelineSet gs2 = new GuidelineSet();

                                            filterOverlayRect.Y += (targetRect.Y - sourceRect.Y) * this.thresholdScoreStep;

                                            gs2.GuidelinesX.Add(filterOverlayRect.X);
                                            gs2.GuidelinesX.Add(filterOverlayRect.Width);
                                            gs2.GuidelinesY.Add(filterOverlayRect.Y);
                                            gs2.GuidelinesY.Add(filterOverlayRect.Height);

                                            dc.PushGuidelineSet(gs2);
                                            dc.DrawRectangle(Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White, null, filterOverlayRect);
                                        }

                                        dc.Close();

                                        DrawingImage di = new DrawingImage(dg);

                                        if (di.CanFreeze)
                                        {
                                            di.Freeze();
                                        }

                                        this.FilterImage.Source = di;
                                        this.FilterImage.Width = blockSize.Width;
                                        this.FilterImage.Height = blockSize.Height;
                                    }
                                }

                                if ((isScrolled || this.ScrollImage.Source == null) && this.scrollStep.HasValue)
                                {
                                    int messageLines = inlinePointList.Value.Aggregate<Point, HashSet<double>>(new HashSet<double>(), (hashSet, point) =>
                                    {
                                        if (!hashSet.Contains(point.Y))
                                        {
                                            hashSet.Add(point.Y);
                                        }

                                        return hashSet;
                                    }).Count;
                                    double totalMessageHeight = (messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count) * this.lineHeight;
                                    int maxLines = messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count < this.numberOfLines ? messageLines + this.messageCollection[this.historyPoint.Value].Attachments.Count : this.numberOfLines;
                                    int usedLines = messageLines - (int)Math.Floor(Math.Min(this.sourceScrollPosition, this.targetScrollPosition));
                                    int maxVisibleLines = this.numberOfLines;
                                    double maxVisibleHeight = 0;

                                    if (usedLines < 0)
                                    {
                                        usedLines = 0;
                                    }

                                    int actualLines = usedLines + this.messageCollection[this.historyPoint.Value].Attachments.Count;

                                    if (actualLines > maxLines)
                                    {
                                        actualLines = maxLines;
                                    }

                                    double height = this.lineHeight * actualLines;

                                    if (this.Canvas.Height - this.baseFooterHeight < Canvas.GetTop(this.ScrollCanvas) + height)
                                    {
                                        height = this.Canvas.Height - this.baseFooterHeight - Canvas.GetTop(this.ScrollCanvas);
                                    }

                                    height -= 14;

                                    if (height > 0)
                                    {
                                        maxVisibleHeight = height;
                                    }

                                    double y = this.baseHeaderHeight + 2;
                                    double previousY = y;
                                    Size size = new Size(3, maxVisibleHeight);
                                    double remainingHeight = 0;

                                    if (this.messageCollection[this.historyPoint.Value].HasAttachments)
                                    {
                                        messageLines += this.messageCollection[this.historyPoint.Value].Attachments.Count;
                                    }

                                    if (messageLines > maxVisibleLines)
                                    {
                                        size.Height = size.Height * maxVisibleLines / messageLines;
                                        remainingHeight = maxVisibleHeight - size.Height;

                                        if (this.targetScrollPosition >= 0)
                                        {
                                            y += remainingHeight * this.targetScrollPosition / (messageLines - maxVisibleLines);
                                            previousY += remainingHeight * this.sourceScrollPosition / (messageLines - maxVisibleLines);
                                        }
                                    }

                                    if (this.ScrollImage.Source == null)
                                    {
                                        GeometryGroup gg = new GeometryGroup();
                                        GuidelineSet gs = new GuidelineSet();
                                        DrawingGroup dg = new DrawingGroup();
                                        DrawingContext dc = dg.Open();

                                        gs.GuidelinesX.Add(0);
                                        gs.GuidelinesX.Add(size.Width);
                                        gs.GuidelinesY.Add(0);
                                        gs.GuidelinesY.Add(size.Height);

                                        dc.PushGuidelineSet(gs);
                                        dc.DrawRectangle(Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White, null, new Rect(0, 0, size.Width, size.Height));
                                        dc.Close();

                                        DrawingImage di = new DrawingImage(dg);

                                        if (di.CanFreeze)
                                        {
                                            di.Freeze();
                                        }

                                        this.ScrollImage.Source = di;
                                        this.ScrollImage.Width = size.Width;
                                        this.ScrollImage.Height = size.Height;
                                    }

                                    Canvas.SetTop(this.ScrollImage, Math.Min(previousY, y) + Math.Abs(y - previousY) * this.scrollIndexStep);
                                }

                                if (updateLayoutRequired)
                                {
                                    this.MessageCanvas.UpdateLayout();
                                }

                                if (isReady && this.nextHistoryPoint.HasValue && this.liftStep.HasValue)
                                {
                                    this.liftStep -= 1 / (averageFrameRate / 4);

                                    if (this.liftStep <= 0)
                                    {
                                        this.liftStep = null;
                                        this.upBlinkStep = this.downBlinkStep = 0;
                                        this.UpImage.Visibility = this.DownImage.Visibility = Visibility.Collapsed;
                                        this.UpImage.Source = this.DownImage.Source = null;
                                        this.UpImage.Opacity = this.DownImage.Opacity = 0;
                                    }
                                    else
                                    {
                                        this.UpImage.Opacity = this.DownImage.Opacity = Math.Sin(this.liftStep.Value / 2 * Math.PI);
                                    }
                                }
                                else if (!isReady || !this.nextHistoryPoint.HasValue)
                                {
                                    if (this.filterStep.HasValue || this.scrollStep.HasValue || this.selectedPosition.HasValue)
                                    {
                                        if (this.liftStep == null)
                                        {
                                            this.liftStep = new Nullable<double>(0);
                                            this.UpImage.Visibility = this.DownImage.Visibility = Visibility.Visible;
                                            this.UpImage.Opacity = this.DownImage.Opacity = Math.Sin(this.liftStep.Value / 2 * Math.PI);
                                        }

                                        if (this.liftStep < 1)
                                        {
                                            this.liftStep += 1 / (averageFrameRate / 4);

                                            if (this.liftStep >= 1)
                                            {
                                                this.liftStep = 1;
                                                this.UpImage.Opacity = this.DownImage.Opacity = 1;
                                            }
                                            else
                                            {
                                                this.UpImage.Opacity = this.DownImage.Opacity = Math.Sin(this.liftStep.Value / 2 * Math.PI);
                                            }
                                        }
                                    }
                                    else if (this.liftStep.HasValue)
                                    {
                                        this.liftStep -= 1 / (averageFrameRate / 4);

                                        if (this.liftStep <= 0)
                                        {
                                            this.liftStep = null;
                                            this.upBlinkStep = this.downBlinkStep = 0;
                                            this.UpImage.Visibility = this.DownImage.Visibility = Visibility.Collapsed;
                                            this.UpImage.Source = this.DownImage.Source = null;
                                            this.UpImage.Opacity = this.DownImage.Opacity = 0;
                                        }
                                        else
                                        {
                                            this.UpImage.Opacity = this.DownImage.Opacity = Math.Sin(this.liftStep.Value / 2 * Math.PI);
                                        }
                                    }
                                }

                                if (this.liftStep.HasValue && (this.upIsHover || this.upBlinkStep > 0 || this.UpImage.Source == null))
                                {
                                    Pen pen = new Pen();

                                    if (this.upIsHover || this.upBlinkStep > 0)
                                    {
                                        this.upBlinkStep += 1 / (averageFrameRate / 2);

                                        if (this.upBlinkStep >= 1)
                                        {
                                            this.upBlinkStep = 0;
                                            pen.Brush = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White;
                                        }
                                        else
                                        {
                                            Color color = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;

                                            pen.Brush = new SolidColorBrush(Color.FromArgb((byte)(color.A + (this.linkColor.A - color.A) * Math.Sin(this.upBlinkStep * Math.PI)), (byte)(color.R + (this.linkColor.R - color.R) * Math.Sin(this.upBlinkStep * Math.PI)), (byte)(color.G + (this.linkColor.G - color.G) * Math.Sin(this.upBlinkStep * Math.PI)), (byte)(color.B + (this.linkColor.B - color.B) * Math.Sin(this.upBlinkStep * Math.PI))));
                                        }
                                    }
                                    else
                                    {
                                        pen.Brush = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White;
                                    }

                                    pen.Thickness = 2;
                                    pen.StartLineCap = PenLineCap.Square;
                                    pen.EndLineCap = PenLineCap.Square;

                                    DrawingGroup upDrawingGroup = new DrawingGroup();
                                    GuidelineSet upGuidelineSet = new GuidelineSet();

                                    upDrawingGroup.Children.Add(new GeometryDrawing(null, pen, CreateUpGeometry(new Rect(0, 0, 6, 3))));

                                    upGuidelineSet.GuidelinesX.Add(upDrawingGroup.Bounds.X);
                                    upGuidelineSet.GuidelinesX.Add(upDrawingGroup.Bounds.X + Math.Ceiling(upDrawingGroup.Bounds.Width));
                                    upGuidelineSet.GuidelinesY.Add(upDrawingGroup.Bounds.Y);
                                    upGuidelineSet.GuidelinesY.Add(upDrawingGroup.Bounds.Y + Math.Ceiling(upDrawingGroup.Bounds.Height));

                                    upDrawingGroup.GuidelineSet = upGuidelineSet;
                                    upDrawingGroup.Children.Add(new GeometryDrawing(Brushes.Transparent, null, new RectangleGeometry(new Rect(upDrawingGroup.Bounds.X, upDrawingGroup.Bounds.Y, Math.Ceiling(upDrawingGroup.Bounds.Width), Math.Ceiling(upDrawingGroup.Bounds.Height)))));

                                    DrawingImage upDrawingImage = new DrawingImage(upDrawingGroup);

                                    if (upDrawingImage.CanFreeze)
                                    {
                                        upDrawingImage.Freeze();
                                    }

                                    this.UpImage.Source = upDrawingImage;
                                    this.UpImage.Width = Math.Ceiling(upDrawingGroup.Bounds.Width);
                                    this.UpImage.Height = Math.Ceiling(upDrawingGroup.Bounds.Height);
                                }

                                if (this.liftStep.HasValue && (this.downIsHover || this.downBlinkStep > 0 || this.DownImage.Source == null))
                                {
                                    Pen pen = new Pen();

                                    if (this.downIsHover || this.downBlinkStep > 0)
                                    {
                                        this.downBlinkStep += 1 / (averageFrameRate / 2);

                                        if (this.downBlinkStep >= 1)
                                        {
                                            this.downBlinkStep = 0;
                                            pen.Brush = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White;
                                        }
                                        else
                                        {
                                            Color color = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;

                                            pen.Brush = new SolidColorBrush(Color.FromArgb((byte)(color.A + (this.linkColor.A - color.A) * Math.Sin(this.downBlinkStep * Math.PI)), (byte)(color.R + (this.linkColor.R - color.R) * Math.Sin(this.downBlinkStep * Math.PI)), (byte)(color.G + (this.linkColor.G - color.G) * Math.Sin(this.downBlinkStep * Math.PI)), (byte)(color.B + (this.linkColor.B - color.B) * Math.Sin(this.downBlinkStep * Math.PI))));
                                        }
                                    }
                                    else
                                    {
                                        pen.Brush = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White;
                                    }

                                    pen.Thickness = 2;
                                    pen.StartLineCap = PenLineCap.Square;
                                    pen.EndLineCap = PenLineCap.Square;

                                    DrawingGroup downDrawingGroup = new DrawingGroup();
                                    GuidelineSet downGuidelineSet = new GuidelineSet();

                                    downDrawingGroup.Children.Add(new GeometryDrawing(null, pen, CreateDownGeometry(new Rect(0, 0, 6, 3))));

                                    downGuidelineSet.GuidelinesX.Add(downDrawingGroup.Bounds.X);
                                    downGuidelineSet.GuidelinesX.Add(downDrawingGroup.Bounds.X + Math.Ceiling(downDrawingGroup.Bounds.Width));
                                    downGuidelineSet.GuidelinesY.Add(downDrawingGroup.Bounds.Y);
                                    downGuidelineSet.GuidelinesY.Add(downDrawingGroup.Bounds.Y + Math.Ceiling(downDrawingGroup.Bounds.Height));

                                    downDrawingGroup.GuidelineSet = downGuidelineSet;
                                    downDrawingGroup.Children.Add(new GeometryDrawing(Brushes.Transparent, null, new RectangleGeometry(new Rect(downDrawingGroup.Bounds.X, downDrawingGroup.Bounds.Y, Math.Ceiling(downDrawingGroup.Bounds.Width), Math.Ceiling(downDrawingGroup.Bounds.Height)))));

                                    DrawingImage downDrawingImage = new DrawingImage(downDrawingGroup);

                                    if (downDrawingImage.CanFreeze)
                                    {
                                        downDrawingImage.Freeze();
                                    }

                                    this.DownImage.Source = downDrawingImage;
                                    this.DownImage.Width = Math.Ceiling(downDrawingGroup.Bounds.Width);
                                    this.DownImage.Height = Math.Ceiling(downDrawingGroup.Bounds.Height);
                                }

                                if (this.targetSize.Width == this.Canvas.Width && this.targetSize.Height == this.Canvas.Height && this.inspectorFadeStep == null && this.inspectorEntry != this.nextInspectorEntry && this.nextInspectorEntry != null)
                                {
                                    Size size = GetBalloonSize(this.messageCollection[this.historyPoint.Value], ref this.messageIsScrollable);

                                    this.inspectorEntry = this.nextInspectorEntry;

                                    size.Height += GetInspectorSize(this.inspectorEntry).Height - 12;

                                    if (size.Width != this.targetSize.Width || size.Height != this.targetSize.Height)
                                    {
                                        this.targetSize = size;

                                        if (this.targetSize.Width != this.Canvas.Width || this.targetSize.Height != this.Canvas.Height)
                                        {
                                            this.sourceSize.Width = this.Canvas.Width;
                                            this.sourceSize.Height = this.Canvas.Height;
                                            this.resizeStep = 0;
                                        }
                                    }
                                }

                                if (this.targetSize.Width == this.Canvas.Width && this.targetSize.Height == this.Canvas.Height)
                                {
                                    if (this.inspectorEntry == this.nextInspectorEntry && this.inspectorEntry != null)
                                    {
                                        if (this.inspectorFadeStep == null)
                                        {
                                            if (this.inspectorEntry.Image == null)
                                            {
                                                this.inspectorEntry.NextImage();
                                            }

                                            if (this.inspectorEntry.Image != null)
                                            {
                                                if (!this.imageDictionary.ContainsKey(this.inspectorEntry.Image) && !this.imageUriHashSet.Contains(this.inspectorEntry.Image))
                                                {
                                                    this.imageUriHashSet.Add(this.inspectorEntry.Image);

                                                    UpdateImage(this.inspectorEntry.Image, false);
                                                }

                                                this.imageUriQueue.Enqueue(this.inspectorEntry.Image);
                                            }

                                            if (this.inspectorEntry.HasMultipleImages)
                                            {
                                                this.switchTimer.Start();
                                            }
                                            else
                                            {
                                                const double space = 10;
                                                double x = 0;

                                                foreach (string tag in this.inspectorEntry.Tags)
                                                {
                                                    Dictionary<int, int> dictionary = new Dictionary<int, int>();
                                                    StringBuilder lineStringBuilder = new StringBuilder();

                                                    foreach (System.Text.RegularExpressions.Match match in System.Text.RegularExpressions.Regex.Matches(tag, @"[\p{IsBasicLatin}-[\s]]+\s?"))
                                                    {
                                                        dictionary.Add(match.Index, match.Length);
                                                    }

                                                    if (x + space + Math.Ceiling(new FormattedText(tag, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace) > this.baseWidth - 74 && x != 0)
                                                    {
                                                        this.switchTimer.Start();

                                                        break;
                                                    }

                                                    for (int i = 0; i < tag.Length; i++)
                                                    {
                                                        int length;

                                                        if (dictionary.TryGetValue(i, out length) && x + space + Math.Ceiling(new FormattedText(String.Concat(lineStringBuilder.ToString(), tag.Substring(i, length)), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace) > this.baseWidth - 74 && lineStringBuilder.Length > 0)
                                                        {
                                                            this.switchTimer.Start();

                                                            break;
                                                        }

                                                        lineStringBuilder.Append(tag[i]);

                                                        if (lineStringBuilder.ToString().EndsWith(Environment.NewLine, StringComparison.Ordinal))
                                                        {
                                                            this.switchTimer.Start();

                                                            break;
                                                        }
                                                        else if (lineStringBuilder.Length > 0 && x + space + Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace) > this.baseWidth - 74)
                                                        {
                                                            this.switchTimer.Start();

                                                            break;
                                                        }
                                                    }

                                                    if (this.switchTimer.IsEnabled)
                                                    {
                                                        break;
                                                    }

                                                    if (lineStringBuilder.Length > 0)
                                                    {
                                                        x += space + Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace);
                                                    }
                                                }
                                            }

                                            this.inspectorFadeStep = new Nullable<double>(0);
                                            this.InspectorCanvas.Visibility = this.InspectorImage.Visibility = Visibility.Visible;
                                            this.InspectorCanvas.Opacity = this.InspectorImage.Opacity = Math.Sin(this.inspectorFadeStep.Value / 2 * Math.PI);
                                        }

                                        if (this.inspectorFadeStep < 1)
                                        {
                                            this.inspectorFadeStep += 1 / (averageFrameRate / 4);

                                            if (this.inspectorFadeStep >= 1)
                                            {
                                                this.inspectorFadeStep = 1;
                                                this.InspectorCanvas.Opacity = this.InspectorImage.Opacity = 1;
                                            }
                                            else
                                            {
                                                this.InspectorCanvas.Opacity = this.InspectorImage.Opacity = Math.Sin(this.inspectorFadeStep.Value / 2 * Math.PI);
                                            }
                                        }
                                    }
                                    else if (this.inspectorEntry != this.nextInspectorEntry && this.inspectorFadeStep.HasValue)
                                    {
                                        this.inspectorFadeStep -= 1 / (averageFrameRate / 4);

                                        if (this.inspectorFadeStep <= 0)
                                        {
                                            this.titleIsHover = subtitleIsHover = this.imageIsHover = this.authorIsHover = false;
                                            this.hoverTagIndex = null;
                                            this.imageLoadStep = 0;
                                            this.imageSlideStep = 0;
                                            this.imagePopupStep = 0;
                                            this.imageBlinkStep = 0;
                                            this.imageUriQueue.Clear();
                                            this.imageUri = null;
                                            this.cachedBitmapImage = null;
                                            this.titleScrollStep = null;
                                            this.subtitleScrollStep = null;
                                            this.authorScrollStep = null;
                                            this.tagScrollStepDictionary.Clear();
                                            this.titleIsScrollable = false;
                                            this.subtitleIsScrollable = false;
                                            this.authorIsScrollable = false;
                                            this.tagIsScrollableHashSet.Clear();
                                            this.circulationQueue.Clear();
                                            this.previousCirculationIndex = 0;
                                            this.nextCirculationIndex = 0;
                                            this.circulationStep = 0;
                                            this.mouseDownPosition = null;
                                            this.cachedTitleImageDictionary.Clear();
                                            this.cachedSubtitleImageDictionary.Clear();
                                            this.cachedAuthorImageDictionary.Clear();
                                            this.cachedTagImageDictionary.Clear();
                                            this.inspectorFadeStep = null;
                                            this.InspectorCanvas.Visibility = this.InspectorImage.Visibility = Visibility.Collapsed;
                                            this.InspectorCanvas.Width = this.InspectorCanvas.Height = this.InspectorImage.Width = this.InspectorImage.Height = Double.NaN;
                                            this.InspectorImage.Source = null;
                                            this.InspectorCanvas.Background = null;
                                            this.InspectorCanvas.Opacity = this.InspectorImage.Opacity = 0;
                                            this.InspectorCanvas.Children.Clear();
                                            this.switchTimer.Stop();
                                        }
                                        else
                                        {
                                            this.InspectorCanvas.Opacity = this.InspectorImage.Opacity = Math.Sin(this.inspectorFadeStep.Value / 2 * Math.PI);
                                        }
                                    }
                                }

                                if (this.inspectorEntry != null && this.inspectorFadeStep.HasValue)
                                {
                                    bool isCirculating = false;
                                    bool isSliding = false;
                                    bool isLoading = false;
                                    bool isPopupping = false;
                                    bool isBlinking = false;
                                    BitmapImage bitmapImage;

                                    if (this.previousCirculationIndex == this.nextCirculationIndex && this.circulationQueue.Count > 0)
                                    {
                                        do
                                        {
                                            this.nextCirculationIndex += this.circulationQueue.Dequeue();
                                        } while (this.circulationQueue.Count > 0);

                                        if (this.nextCirculationIndex < 0)
                                        {
                                            this.nextCirculationIndex = 0;
                                        }
                                        else
                                        {
                                            const double space = 10;
                                            double x = 0;
                                            int lines = 0;

                                            foreach (string tag in this.inspectorEntry.Tags)
                                            {
                                                Dictionary<int, int> dictionary = new Dictionary<int, int>();
                                                FormattedText formattedText = new FormattedText(tag, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);
                                                StringBuilder lineStringBuilder = new StringBuilder();

                                                foreach (System.Text.RegularExpressions.Match match in System.Text.RegularExpressions.Regex.Matches(tag, @"[\p{IsBasicLatin}-[\s]]+\s?"))
                                                {
                                                    dictionary.Add(match.Index, match.Length);
                                                }

                                                for (int i = 0; i < tag.Length; i++)
                                                {
                                                    int length;

                                                    if (dictionary.TryGetValue(i, out length) && x + space + Math.Ceiling(new FormattedText(String.Concat(lineStringBuilder.ToString(), tag.Substring(i, length)), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace) > this.baseWidth - 74)
                                                    {
                                                        lineStringBuilder.Clear();
                                                        x = 0;
                                                        lines++;
                                                    }

                                                    lineStringBuilder.Append(tag[i]);

                                                    if (lineStringBuilder.ToString().EndsWith(Environment.NewLine, StringComparison.Ordinal))
                                                    {
                                                        lineStringBuilder.Remove(lineStringBuilder.ToString().LastIndexOf(Environment.NewLine, StringComparison.Ordinal), Environment.NewLine.Length);

                                                        if (lineStringBuilder.Length > 0)
                                                        {
                                                            lineStringBuilder.Remove(0, lineStringBuilder.Length);
                                                        }

                                                        x = 0;
                                                        lines++;
                                                    }
                                                    else if (lineStringBuilder.Length > 0 && x + space + Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace) > this.baseWidth - 74)
                                                    {
                                                        if (lineStringBuilder.Length - 1 > 0)
                                                        {
                                                            lineStringBuilder.Remove(0, lineStringBuilder.Length - 1);
                                                        }

                                                        x = 0;
                                                        lines++;
                                                    }
                                                }

                                                if (lineStringBuilder.Length > 0)
                                                {
                                                    double width = space + Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace);

                                                    if (x + width > this.baseWidth - 74)
                                                    {
                                                        x = width;
                                                        lines++;
                                                    }
                                                    else
                                                    {
                                                        x += width;
                                                    }
                                                }
                                            }

                                            if (this.nextCirculationIndex > lines)
                                            {
                                                this.nextCirculationIndex = 0;
                                            }
                                        }
                                    }

                                    if (this.previousCirculationIndex != this.nextCirculationIndex)
                                    {
                                        this.circulationStep += 1 / (averageFrameRate / 2);

                                        if (this.circulationStep >= 1)
                                        {
                                            this.circulationStep = 0;
                                            this.previousCirculationIndex = this.nextCirculationIndex;
                                        }

                                        isCirculating = true;
                                    }

                                    if (this.inspectorEntry == this.nextInspectorEntry)
                                    {
                                        if (this.imageUriQueue.Count > 0 && (this.imageSlideStep == 0 || this.imageSlideStep == 1))
                                        {
                                            this.imageUri = this.imageUriQueue.Dequeue();
                                            this.imageSlideStep = 0;
                                        }

                                        if (this.imageUri == null)
                                        {
                                            bitmapImage = null;

                                            if (this.cachedBitmapImage != null && this.imagePopupStep > 0)
                                            {
                                                this.imagePopupStep -= 1 / (averageFrameRate / 4);

                                                if (this.imagePopupStep < 0)
                                                {
                                                    this.imagePopupStep = 0;
                                                }

                                                isSliding = true;
                                            }
                                        }
                                        else if (this.imageDictionary.TryGetValue(this.imageUri, out bitmapImage))
                                        {
                                            if (this.cachedBitmapImage != bitmapImage)
                                            {
                                                if (this.imagePopupStep > 0)
                                                {
                                                    this.imagePopupStep -= 1 / (averageFrameRate / 4);

                                                    if (this.imagePopupStep < 0)
                                                    {
                                                        this.imagePopupStep = 0;
                                                    }

                                                    isSliding = true;
                                                }
                                                else if (this.imagePopupStep == 0 && bitmapImage != null)
                                                {
                                                    this.imageSlideStep += 1 / (averageFrameRate / 2);

                                                    if (this.imageSlideStep >= 1)
                                                    {
                                                        this.imageSlideStep = 1;
                                                        this.cachedBitmapImage = bitmapImage;
                                                    }
                                                    else
                                                    {
                                                        isLoading = true;
                                                    }

                                                    isSliding = true;
                                                }
                                            }
                                        }
                                        else if (this.cachedBitmapImage != null && this.imagePopupStep > 0)
                                        {
                                            this.imagePopupStep -= 1 / (averageFrameRate / 4);

                                            if (this.imagePopupStep < 0)
                                            {
                                                this.imagePopupStep = 0;
                                            }

                                            isSliding = true;
                                        }
                                    }
                                    else
                                    {
                                        bitmapImage = null;

                                        if (this.cachedBitmapImage != null && this.imagePopupStep > 0)
                                        {
                                            this.imagePopupStep -= 1 / (averageFrameRate / 4);

                                            if (this.imagePopupStep < 0)
                                            {
                                                this.imagePopupStep = 0;
                                            }

                                            isSliding = true;
                                        }
                                    }

                                    isPopupping = isSliding;

                                    if (!isSliding && bitmapImage != null)
                                    {
                                        if (this.imageIsHover)
                                        {
                                            if (this.imagePopupStep < 1)
                                            {
                                                this.imagePopupStep += 1 / (averageFrameRate / 4);

                                                if (this.imagePopupStep > 1)
                                                {
                                                    this.imagePopupStep = 1;
                                                }

                                                isPopupping = true;
                                            }
                                        }
                                        else
                                        {
                                            if (this.imagePopupStep > 0)
                                            {
                                                this.imagePopupStep -= 1 / (averageFrameRate / 4);

                                                if (this.imagePopupStep < 0)
                                                {
                                                    this.imagePopupStep = 0;
                                                }

                                                isPopupping = true;
                                            }
                                        }
                                    }

                                    if (this.imageSlideStep < 1 && this.imageUri != null)
                                    {
                                        isLoading = true;
                                    }

                                    if (isLoading)
                                    {
                                        this.imageLoadStep += 1 / (averageFrameRate / 2);

                                        if (this.imageLoadStep >= 1)
                                        {
                                            this.imageLoadStep = 0;
                                        }
                                    }

                                    if (!(this.imageUri == null && bitmapImage == null && this.cachedBitmapImage == null) && this.imageIsHover && this.inspectorEntry.HasMultipleImages || this.imageBlinkStep > 0)
                                    {
                                        this.imageBlinkStep += 1 / (averageFrameRate / 2);

                                        if (this.imageBlinkStep >= 1)
                                        {
                                            this.imageBlinkStep = 0;
                                        }

                                        isBlinking = true;
                                    }

                                    if (this.InspectorCanvas.Children.Count == 0 || isSliding)
                                    {
                                        const double radiusX = 5;
                                        const double radiusY = 5;
                                        Rect imageRect = new Rect(8, 0, 32, 32);
                                        Size size = new Size(this.baseWidth - 12, this.Canvas.Height - Canvas.GetTop(this.ScrollCanvas) - this.ScrollCanvas.Height - this.baseFooterHeight + 12);
                                        SolidColorBrush brush = new SolidColorBrush(Color.FromArgb((byte)(Colors.Black.A * 25 / 100), Colors.Black.R, Colors.Black.G, Colors.Black.B));
                                        DrawingGroup dg = new DrawingGroup();
                                        GuidelineSet gs = new GuidelineSet();

                                        gs.GuidelinesX.Add(0);
                                        gs.GuidelinesX.Add(3);
                                        gs.GuidelinesY.Add(0);
                                        gs.GuidelinesY.Add(3);

                                        dg.GuidelineSet = gs;
                                        dg.Children.Add(new GeometryDrawing(brush, null, new RectangleGeometry(new Rect(0, 0, 1, 1))));
                                        dg.Children.Add(new GeometryDrawing(brush, null, new RectangleGeometry(new Rect(2, 1, 1, 1))));
                                        dg.Children.Add(new GeometryDrawing(brush, null, new RectangleGeometry(new Rect(1, 2, 1, 1))));

                                        PresentationSource presentationSource = PresentationSource.FromVisual(this);

                                        if (presentationSource != null && presentationSource.CompositionTarget != null && presentationSource.CompositionTarget.TransformToDevice.M11 == 1.0 && presentationSource.CompositionTarget.TransformToDevice.M22 == 1.0)
                                        {
                                            RenderOptions.SetEdgeMode(dg, EdgeMode.Aliased);
                                        }

                                        DrawingBrush drawingBrush = new DrawingBrush(dg);

                                        drawingBrush.TileMode = TileMode.Tile;
                                        drawingBrush.ViewportUnits = BrushMappingMode.Absolute;
                                        drawingBrush.Viewport = new Rect(0, 0, 3, 3);
                                        drawingBrush.Stretch = Stretch.None;

                                        if (drawingBrush.CanFreeze)
                                        {
                                            drawingBrush.Freeze();
                                        }

                                        double step = Math.Sin(this.imageSlideStep / 2 * Math.PI);
                                        StreamGeometry streamGeometry = new StreamGeometry();

                                        streamGeometry.FillRule = FillRule.Nonzero;

                                        using (StreamGeometryContext streamGeometryContext = streamGeometry.Open())
                                        {
                                            streamGeometryContext.BeginFigure(new Point(0, imageRect.Height / 2), true, true);
                                            streamGeometryContext.LineTo(new Point(imageRect.X, imageRect.Height / 2), true, false);
                                            streamGeometryContext.LineTo(new Point(imageRect.X, imageRect.Height / 2 * step), true, false);
                                            streamGeometryContext.LineTo(new Point(imageRect.X + imageRect.Width, imageRect.Height / 2 * step), true, false);
                                            streamGeometryContext.LineTo(new Point(imageRect.X + imageRect.Width, imageRect.Height / 2), true, false);
                                            streamGeometryContext.LineTo(new Point(size.Width, imageRect.Height / 2), true, false);
                                            streamGeometryContext.LineTo(new Point(size.Width, size.Height - radiusY), true, false);
                                            streamGeometryContext.QuadraticBezierTo(new Point(size.Width, size.Height), new Point(size.Width - radiusX, size.Height), true, false);
                                            streamGeometryContext.LineTo(new Point(radiusX, size.Height), true, false);
                                            streamGeometryContext.QuadraticBezierTo(new Point(0, size.Height), new Point(0, size.Height - radiusY), true, false);
                                        }

                                        if (streamGeometry.CanFreeze)
                                        {
                                            streamGeometry.Freeze();
                                        }

                                        this.InspectorCanvas.Background = drawingBrush;
                                        this.InspectorCanvas.Width = size.Width;
                                        this.InspectorCanvas.Height = size.Height;
                                        this.InspectorCanvas.Clip = streamGeometry;

                                        Canvas.SetLeft(this.InspectorCanvas, Canvas.GetLeft(this.ScrollCanvas) - 4);
                                        Canvas.SetTop(this.InspectorCanvas, Canvas.GetTop(this.ScrollCanvas) + this.ScrollCanvas.Height);
                                    }

                                    if (this.InspectorCanvas.Children.Count == 0 || this.titleIsHover && !this.titleIsScrollable && this.titleScrollStep == null || this.titleIsScrollable || this.titleScrollStep.HasValue || this.subtitleIsHover && !this.subtitleIsScrollable && this.subtitleScrollStep == null || this.subtitleIsScrollable || this.subtitleScrollStep.HasValue || this.authorIsHover && !this.authorIsScrollable && this.authorScrollStep == null || this.authorIsScrollable || this.authorScrollStep.HasValue || isCirculating || this.hoverTagIndex.HasValue && this.tagIsScrollableHashSet.Count == 0 && this.tagScrollStepDictionary.Count == 0 || this.tagIsScrollableHashSet.Count > 0 || this.tagScrollStepDictionary.Count > 0)
                                    {
                                        const double space = 10;
                                        Rect imageRect = new Rect(8, 0, 32, 32);
                                        Size iconSize = new Size(6, 6);
                                        double baseY = imageRect.Height / 2;
                                        Point offsetPoint = new Point(16 + imageRect.Width, baseY);
                                        Point nextPoint = new Point(0, 0);
                                        string title = String.IsNullOrEmpty(this.inspectorEntry.Title) && this.inspectorEntry.Resource != null ? this.inspectorEntry.Resource.ToString() : this.inspectorEntry.Title;
                                        bool isEmpty = this.InspectorCanvas.Children.Count == 0;
                                        Size size = new Size(this.baseWidth - 12, this.Canvas.Height - Canvas.GetTop(this.ScrollCanvas) - this.ScrollCanvas.Height - this.baseFooterHeight + 12);
                                        double textWidth = size.Width - 30 - imageRect.Width;

                                        if (!String.IsNullOrEmpty(title))
                                        {
                                            List<KeyValuePair<double, FormattedText>> list = new List<KeyValuePair<double, FormattedText>>();
                                            Size textBlockSize = new Size(0, 0);
                                            bool isReseted = true;
                                            double y = 0;
                                            Dictionary<int, int> dictionary = new Dictionary<int, int>();
                                            StringBuilder lineStringBuilder = new StringBuilder();
                                            bool isBreaked = false;
                                            double titleWidth = this.inspectorEntry.HasSimilarEntries ? size.Width - 30 - imageRect.Width - (space - iconSize.Width) / 2 - iconSize.Width : size.Width - 30 - imageRect.Width;

                                            foreach (System.Text.RegularExpressions.Match match in System.Text.RegularExpressions.Regex.Matches(title, @"[\p{IsBasicLatin}-[\s]]+\s?"))
                                            {
                                                dictionary.Add(match.Index, match.Length);
                                            }

                                            for (int i = 0; i < title.Length; i++)
                                            {
                                                int length;

                                                if (dictionary.TryGetValue(i, out length) && Math.Ceiling(new FormattedText(String.Concat(lineStringBuilder.ToString(), title.Substring(i, length)), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace) > titleWidth && !isReseted)
                                                {
                                                    if (lineStringBuilder.Length > 0)
                                                    {
                                                        FormattedText formattedText = new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                        list.Add(new KeyValuePair<double, FormattedText>(y, formattedText));

                                                        if (Math.Ceiling(formattedText.WidthIncludingTrailingWhitespace) > textBlockSize.Width)
                                                        {
                                                            textBlockSize.Width = Math.Ceiling(formattedText.WidthIncludingTrailingWhitespace);
                                                        }
                                                    }

                                                    textBlockSize.Height += this.lineHeight;
                                                    lineStringBuilder.Clear();
                                                    y += lineHeight;
                                                    isBreaked = true;
                                                }

                                                lineStringBuilder.Append(title[i]);

                                                if (lineStringBuilder.ToString().EndsWith(Environment.NewLine, StringComparison.Ordinal))
                                                {
                                                    lineStringBuilder.Remove(lineStringBuilder.ToString().LastIndexOf(Environment.NewLine, StringComparison.Ordinal), Environment.NewLine.Length);

                                                    if (lineStringBuilder.Length > 0)
                                                    {
                                                        FormattedText formattedText = new FormattedText(lineStringBuilder.ToString().Substring(0, lineStringBuilder.Length), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                        list.Add(new KeyValuePair<double, FormattedText>(y, formattedText));

                                                        if (Math.Ceiling(formattedText.WidthIncludingTrailingWhitespace) > textBlockSize.Width)
                                                        {
                                                            textBlockSize.Width = Math.Ceiling(formattedText.WidthIncludingTrailingWhitespace);
                                                        }

                                                        lineStringBuilder.Remove(0, lineStringBuilder.Length);
                                                    }

                                                    textBlockSize.Height += this.lineHeight;
                                                    isReseted = true;
                                                    y += lineHeight;
                                                    isBreaked = true;
                                                }
                                                else if (Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace) > titleWidth)
                                                {
                                                    if (lineStringBuilder.Length - 1 > 0)
                                                    {
                                                        FormattedText formattedText = new FormattedText(lineStringBuilder.ToString().Substring(0, lineStringBuilder.Length - 1), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                        list.Add(new KeyValuePair<double, FormattedText>(y, formattedText));

                                                        if (Math.Ceiling(formattedText.WidthIncludingTrailingWhitespace) > textBlockSize.Width)
                                                        {
                                                            textBlockSize.Width = Math.Ceiling(formattedText.WidthIncludingTrailingWhitespace);
                                                        }

                                                        lineStringBuilder.Remove(0, lineStringBuilder.Length - 1);
                                                    }

                                                    textBlockSize.Height += this.lineHeight;
                                                    isReseted = true;
                                                    y += lineHeight;
                                                    isBreaked = true;
                                                }
                                                else
                                                {
                                                    isReseted = false;
                                                }
                                            }

                                            if (lineStringBuilder.Length > 0)
                                            {
                                                FormattedText formattedText = new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                list.Add(new KeyValuePair<double, FormattedText>(y, formattedText));

                                                if (Math.Ceiling(formattedText.WidthIncludingTrailingWhitespace) > textBlockSize.Width)
                                                {
                                                    textBlockSize.Width = Math.Ceiling(formattedText.WidthIncludingTrailingWhitespace);
                                                }

                                                textBlockSize.Height += this.lineHeight;
                                                isBreaked = false;
                                            }

                                            if (isBreaked)
                                            {
                                                textBlockSize.Height += this.lineHeight;
                                            }

                                            if (this.titleScrollStep.HasValue)
                                            {
                                                double step = this.titleScrollStep.Value;

                                                if (step == 1 && this.titleIsScrollable)
                                                {
                                                    step = 0;
                                                }

                                                step += 1 / (averageFrameRate / 2);

                                                if (step >= 1)
                                                {
                                                    if (this.titleIsHover)
                                                    {
                                                        this.titleScrollStep = 1;
                                                    }
                                                    else
                                                    {
                                                        this.titleScrollStep = null;
                                                    }
                                                }
                                                else
                                                {
                                                    this.titleScrollStep = step;
                                                }
                                            }
                                            else if (this.titleIsHover || this.titleIsScrollable)
                                            {
                                                double step = 1 / (averageFrameRate / 2);

                                                if (step >= 1)
                                                {
                                                    if (this.titleIsHover)
                                                    {
                                                        this.titleScrollStep = new Nullable<double>(1);
                                                    }
                                                }
                                                else
                                                {
                                                    this.titleScrollStep = new Nullable<double>(step);
                                                }
                                            }

                                            if (this.titleIsScrollable)
                                            {
                                                this.titleIsScrollable = false;
                                            }

                                            for (int i = 0; i < list.Count; i++)
                                            {
                                                Image image;

                                                if (this.cachedTitleImageDictionary.TryGetValue(i, out image))
                                                {
                                                    TranslateTransform translateTransform = image.RenderTransform as TranslateTransform;

                                                    if (translateTransform != null)
                                                    {
                                                        if (this.titleScrollStep.HasValue)
                                                        {
                                                            double maxWidth = list[i].Value.WidthIncludingTrailingWhitespace > list[i].Value.Width ? Math.Ceiling(list[i].Value.WidthIncludingTrailingWhitespace) - Math.Floor(list[i].Value.OverhangLeading) : list[i].Value.OverhangTrailing < 0 ? Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing) : Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading);
                                                            StringBuilder sb = new StringBuilder();

                                                            for (int j = i + 1; j < list.Count; j++)
                                                            {
                                                                sb.Append(list[j].Value.Text);
                                                            }

                                                            for (int j = 0; j < i; j++)
                                                            {
                                                                sb.Append(list[j].Value.Text);
                                                            }

                                                            if (sb.Length > 0)
                                                            {
                                                                FormattedText ft = new FormattedText(sb.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                                if (ft.WidthIncludingTrailingWhitespace > ft.Width)
                                                                {
                                                                    double w = Math.Ceiling(ft.WidthIncludingTrailingWhitespace);

                                                                    if (ft.OverhangLeading < 0)
                                                                    {
                                                                        w -= Math.Floor(ft.OverhangLeading);
                                                                    }

                                                                    maxWidth += w;
                                                                }
                                                                else
                                                                {
                                                                    double w = Math.Ceiling(ft.Width);

                                                                    if (ft.OverhangLeading < 0)
                                                                    {
                                                                        w -= Math.Floor(ft.OverhangLeading);
                                                                    }

                                                                    if (ft.OverhangTrailing < 0)
                                                                    {
                                                                        w -= Math.Floor(ft.OverhangTrailing);
                                                                    }

                                                                    maxWidth += w;
                                                                }
                                                            }

                                                            translateTransform.X = -maxWidth * Math.Sin(this.titleScrollStep.Value / 2 * Math.PI);
                                                        }
                                                        else
                                                        {
                                                            translateTransform.X = 0;
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    double width1 = Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing);
                                                    double width2 = list[i].Value.WidthIncludingTrailingWhitespace > list[i].Value.Width ? Math.Ceiling(list[i].Value.WidthIncludingTrailingWhitespace) - Math.Floor(list[i].Value.OverhangLeading) : list[i].Value.OverhangTrailing < 0 ? Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing) : Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading);
                                                    double maxWidth = width2;
                                                    double height = list[i].Value.OverhangAfter > 0 ? list[i].Value.Height + list[i].Value.OverhangAfter : list[i].Value.Height;
                                                    Canvas canvas = new Canvas();
                                                    DropShadowEffect dropShadowEffect = new DropShadowEffect();
                                                    StringBuilder sb = new StringBuilder();
                                                    DrawingGroup dg = new DrawingGroup();
                                                    DrawingContext dc = dg.Open();

                                                    for (int j = i + 1; j < list.Count; j++)
                                                    {
                                                        sb.Append(list[j].Value.Text);
                                                    }

                                                    for (int j = 0; j < i; j++)
                                                    {
                                                        sb.Append(list[j].Value.Text);
                                                    }

                                                    if (sb.Length > 0)
                                                    {
                                                        FormattedText ft = new FormattedText(sb.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                        height = Math.Max(height, ft.OverhangAfter > 0 ? ft.Height + ft.OverhangAfter : ft.Height);

                                                        if (ft.WidthIncludingTrailingWhitespace > ft.Width)
                                                        {
                                                            if (ft.OverhangLeading < 0)
                                                            {
                                                                maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace) - Math.Floor(ft.OverhangLeading);

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2 - Math.Floor(ft.OverhangLeading), 0));
                                                            }
                                                            else
                                                            {
                                                                maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace);

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2, 0));
                                                            }
                                                        }
                                                        else
                                                        {
                                                            double width3 = Math.Ceiling(ft.Width);

                                                            if (ft.OverhangLeading < 0)
                                                            {
                                                                width3 -= Math.Floor(ft.OverhangLeading);

                                                                if (ft.OverhangTrailing < 0)
                                                                {
                                                                    width3 -= Math.Floor(ft.OverhangTrailing);
                                                                }

                                                                maxWidth += width3;

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2 - Math.Floor(ft.OverhangLeading), 0));
                                                            }
                                                            else
                                                            {
                                                                if (ft.OverhangTrailing < 0)
                                                                {
                                                                    width3 -= Math.Floor(ft.OverhangTrailing);
                                                                }

                                                                maxWidth += width3;

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2, 0));
                                                            }
                                                        }
                                                    }
                                                    else
                                                    {
                                                        dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                        dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                    }

                                                    dc.DrawText(list[i].Value, new Point(maxWidth - Math.Floor(list[i].Value.OverhangLeading), 0));
                                                    dc.Close();

                                                    dropShadowEffect.Color = Math.Max(Math.Max(this.textColor.R, this.textColor.G), this.textColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;
                                                    dropShadowEffect.BlurRadius = 1;
                                                    dropShadowEffect.Direction = 270;
                                                    dropShadowEffect.ShadowDepth = 1;
                                                    dropShadowEffect.Opacity = 0.5;

                                                    if (dropShadowEffect.CanFreeze)
                                                    {
                                                        dropShadowEffect.Freeze();
                                                    }

                                                    canvas.HorizontalAlignment = HorizontalAlignment.Left;
                                                    canvas.VerticalAlignment = VerticalAlignment.Top;
                                                    canvas.Margin = new Thickness(Math.Floor(list[i].Value.OverhangLeading), (this.lineHeight - list[i].Value.Height) / 2, 0, 0);
                                                    canvas.Background = Brushes.Transparent;
                                                    canvas.ClipToBounds = true;
                                                    canvas.Width = width1;
                                                    canvas.Height = height;
                                                    canvas.Effect = dropShadowEffect;

                                                    this.InspectorCanvas.Children.Add(canvas);

                                                    Canvas.SetLeft(canvas, offsetPoint.X + nextPoint.X);
                                                    Canvas.SetTop(canvas, offsetPoint.Y + nextPoint.Y + list[i].Key);

                                                    DrawingImage di = new DrawingImage(dg);

                                                    if (di.CanFreeze)
                                                    {
                                                        di.Freeze();
                                                    }

                                                    image = new Image();
                                                    image.HorizontalAlignment = HorizontalAlignment.Left;
                                                    image.VerticalAlignment = VerticalAlignment.Top;
                                                    image.Source = di;
                                                    image.Stretch = Stretch.None;
                                                    image.Width = maxWidth + width1;
                                                    image.Height = height;
                                                    image.RenderTransform = new TranslateTransform(0, 0);
                                                    image.MouseEnter += new MouseEventHandler(delegate
                                                    {
                                                        this.titleIsHover = true;
                                                    });
                                                    image.MouseLeave += new MouseEventHandler(delegate
                                                    {
                                                        this.titleIsHover = false;
                                                    });
                                                    image.MouseLeftButtonUp += new MouseButtonEventHandler(delegate (object s, MouseButtonEventArgs mbea)
                                                    {
                                                        if (this.titleIsHover)
                                                        {
                                                            this.titleIsScrollable = true;
                                                        }

                                                        if (!String.IsNullOrEmpty(this.inspectorEntry.Title))
                                                        {
                                                            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                                                            {
                                                                if (this.inspectorEntry.HasSimilarEntries)
                                                                {
                                                                    Script.Instance.Suggest(this.inspectorEntry.Title, this.inspectorEntry.SimilarEntries);
                                                                }
                                                                else if (this.inspectorEntry.Resource == null)
                                                                {
                                                                    Script.Instance.Learn(this.inspectorEntry.Title);
                                                                }
                                                            }
                                                            else
                                                            {
                                                                if (this.inspectorEntry.Resource == null)
                                                                {
                                                                    Script.Instance.Search(this.inspectorEntry.Title);
                                                                }
                                                                else
                                                                {
                                                                    Task.Factory.StartNew(delegate (object state)
                                                                    {
                                                                        System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo((string)state));
                                                                    }, this.inspectorEntry.Resource.ToString());
                                                                }
                                                            }
                                                        }

                                                        mbea.Handled = true;
                                                    });

                                                    RenderOptions.SetClearTypeHint(image, ClearTypeHint.Enabled);

                                                    canvas.Children.Add(image);

                                                    Canvas.SetLeft(image, 0);
                                                    Canvas.SetTop(image, 0);

                                                    this.cachedTitleImageDictionary.Add(i, image);
                                                }
                                            }

                                            if (this.inspectorEntry.HasSimilarEntries && isEmpty)
                                            {
                                                Image plusImage = new Image();
                                                Pen pen = new Pen(Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White, 2);
                                                DrawingGroup plusDrawingGroup = new DrawingGroup();
                                                GuidelineSet plusGuidelineSet = new GuidelineSet();

                                                pen.StartLineCap = PenLineCap.Square;
                                                pen.EndLineCap = PenLineCap.Square;

                                                plusDrawingGroup.Children.Add(new GeometryDrawing(null, pen, CreatePlusGeometry(new Rect(0, 0, iconSize.Width, iconSize.Height))));

                                                plusGuidelineSet.GuidelinesX.Add(plusDrawingGroup.Bounds.X);
                                                plusGuidelineSet.GuidelinesX.Add(plusDrawingGroup.Bounds.X + Math.Ceiling(plusDrawingGroup.Bounds.Width));
                                                plusGuidelineSet.GuidelinesY.Add(plusDrawingGroup.Bounds.Y);
                                                plusGuidelineSet.GuidelinesY.Add(plusDrawingGroup.Bounds.Y + Math.Ceiling(plusDrawingGroup.Bounds.Height));

                                                plusDrawingGroup.GuidelineSet = plusGuidelineSet;
                                                plusDrawingGroup.Children.Add(new GeometryDrawing(Brushes.Transparent, null, new RectangleGeometry(new Rect(plusDrawingGroup.Bounds.X, plusDrawingGroup.Bounds.Y, Math.Ceiling(plusDrawingGroup.Bounds.Width), Math.Ceiling(plusDrawingGroup.Bounds.Height)))));

                                                DrawingImage plusDrawingImage = new DrawingImage(plusDrawingGroup);

                                                if (plusDrawingImage.CanFreeze)
                                                {
                                                    plusDrawingImage.Freeze();
                                                }

                                                plusImage.HorizontalAlignment = HorizontalAlignment.Left;
                                                plusImage.VerticalAlignment = VerticalAlignment.Top;
                                                plusImage.Source = plusDrawingImage;
                                                plusImage.Stretch = Stretch.None;
                                                plusImage.Width = Math.Ceiling(plusDrawingGroup.Bounds.Width);
                                                plusImage.Height = Math.Ceiling(plusDrawingGroup.Bounds.Height);

                                                PresentationSource presentationSource = PresentationSource.FromVisual(this);

                                                if (presentationSource != null && presentationSource.CompositionTarget != null && presentationSource.CompositionTarget.TransformToDevice.M11 == 1.0 && presentationSource.CompositionTarget.TransformToDevice.M22 == 1.0)
                                                {
                                                    RenderOptions.SetEdgeMode(plusImage, EdgeMode.Aliased);
                                                }

                                                this.InspectorCanvas.Children.Add(plusImage);

                                                Canvas.SetLeft(plusImage, offsetPoint.X + nextPoint.X + textBlockSize.Width + (space - iconSize.Width) / 2);
                                                Canvas.SetTop(plusImage, offsetPoint.Y + nextPoint.Y + (this.lineHeight - iconSize.Height) / 2);
                                            }

                                            nextPoint.Y += textBlockSize.Height;
                                        }

                                        if (this.inspectorEntry.Resource != null && this.inspectorEntry.Resource.IsAbsoluteUri)
                                        {
                                            string authority = this.inspectorEntry.Resource.Authority;
                                            List<FormattedText> list = new List<FormattedText>();
                                            StringBuilder lineStringBuilder = new StringBuilder();

                                            for (int i = 0; i < authority.Length; i++)
                                            {
                                                int safeLineLength = lineStringBuilder.Length;

                                                lineStringBuilder.Append(authority[i]);

                                                if (Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace) > textWidth && safeLineLength > 0)
                                                {
                                                    list.Add(new FormattedText(lineStringBuilder.ToString().Substring(0, safeLineLength), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush));
                                                    lineStringBuilder.Remove(0, safeLineLength);
                                                }
                                            }

                                            if (lineStringBuilder.Length > 0)
                                            {
                                                list.Add(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush));
                                            }

                                            if (this.subtitleScrollStep.HasValue)
                                            {
                                                double step = this.subtitleScrollStep.Value;

                                                if (step == 1 && this.subtitleIsScrollable)
                                                {
                                                    step = 0;
                                                }

                                                step += 1 / (averageFrameRate / 2);

                                                if (step >= 1)
                                                {
                                                    if (this.subtitleIsHover)
                                                    {
                                                        this.subtitleScrollStep = 1;
                                                    }
                                                    else
                                                    {
                                                        this.subtitleScrollStep = null;
                                                    }
                                                }
                                                else
                                                {
                                                    this.subtitleScrollStep = step;
                                                }
                                            }
                                            else if (this.subtitleIsHover || this.subtitleIsScrollable)
                                            {
                                                double step = 1 / (averageFrameRate / 2);

                                                if (step >= 1)
                                                {
                                                    if (this.subtitleIsHover)
                                                    {
                                                        this.subtitleScrollStep = new Nullable<double>(1);
                                                    }
                                                }
                                                else
                                                {
                                                    this.subtitleScrollStep = new Nullable<double>(step);
                                                }
                                            }

                                            if (this.subtitleIsScrollable)
                                            {
                                                this.subtitleIsScrollable = false;
                                            }

                                            for (int i = 0; i < list.Count; i++)
                                            {
                                                Image image;

                                                if (this.cachedSubtitleImageDictionary.TryGetValue(i, out image))
                                                {
                                                    TranslateTransform translateTransform = image.RenderTransform as TranslateTransform;

                                                    if (translateTransform != null)
                                                    {
                                                        if (this.subtitleScrollStep.HasValue)
                                                        {
                                                            double maxWidth = list[i].WidthIncludingTrailingWhitespace > list[i].Width ? Math.Ceiling(list[i].WidthIncludingTrailingWhitespace) - Math.Floor(list[i].OverhangLeading) : list[i].OverhangTrailing < 0 ? Math.Ceiling(list[i].Width) - Math.Floor(list[i].OverhangLeading) - Math.Floor(list[i].OverhangTrailing) : Math.Ceiling(list[i].Width) - Math.Floor(list[i].OverhangLeading);
                                                            StringBuilder sb = new StringBuilder();

                                                            for (int j = i + 1; j < list.Count; j++)
                                                            {
                                                                sb.Append(list[j].Text);
                                                            }

                                                            for (int j = 0; j < i; j++)
                                                            {
                                                                sb.Append(list[j].Text);
                                                            }

                                                            if (sb.Length > 0)
                                                            {
                                                                FormattedText ft = new FormattedText(sb.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                                if (ft.WidthIncludingTrailingWhitespace > ft.Width)
                                                                {
                                                                    double w = Math.Ceiling(ft.WidthIncludingTrailingWhitespace);

                                                                    if (ft.OverhangLeading < 0)
                                                                    {
                                                                        w -= Math.Floor(ft.OverhangLeading);
                                                                    }

                                                                    maxWidth += w;
                                                                }
                                                                else
                                                                {
                                                                    double w = Math.Ceiling(ft.Width);

                                                                    if (ft.OverhangLeading < 0)
                                                                    {
                                                                        w -= Math.Floor(ft.OverhangLeading);
                                                                    }

                                                                    if (ft.OverhangTrailing < 0)
                                                                    {
                                                                        w -= Math.Floor(ft.OverhangTrailing);
                                                                    }

                                                                    maxWidth += w;
                                                                }
                                                            }

                                                            translateTransform.X = -maxWidth * Math.Sin(this.subtitleScrollStep.Value / 2 * Math.PI);
                                                        }
                                                        else
                                                        {
                                                            translateTransform.X = 0;
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    double width1 = Math.Ceiling(list[i].Width) - Math.Floor(list[i].OverhangLeading) - Math.Floor(list[i].OverhangTrailing);
                                                    double width2 = list[i].WidthIncludingTrailingWhitespace > list[i].Width ? Math.Ceiling(list[i].WidthIncludingTrailingWhitespace) - Math.Floor(list[i].OverhangLeading) : list[i].OverhangTrailing < 0 ? Math.Ceiling(list[i].Width) - Math.Floor(list[i].OverhangLeading) - Math.Floor(list[i].OverhangTrailing) : Math.Ceiling(list[i].Width) - Math.Floor(list[i].OverhangLeading);
                                                    double maxWidth = width2;
                                                    double height = list[i].OverhangAfter > 0 ? list[i].Height + list[i].OverhangAfter : list[i].Height;
                                                    Canvas canvas = new Canvas();
                                                    DropShadowEffect dropShadowEffect = new DropShadowEffect();
                                                    StringBuilder sb = new StringBuilder();
                                                    DrawingGroup dg = new DrawingGroup();
                                                    DrawingContext dc = dg.Open();

                                                    for (int j = i + 1; j < list.Count; j++)
                                                    {
                                                        sb.Append(list[j].Text);
                                                    }

                                                    for (int j = 0; j < i; j++)
                                                    {
                                                        sb.Append(list[j].Text);
                                                    }

                                                    if (sb.Length > 0)
                                                    {
                                                        FormattedText ft = new FormattedText(sb.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                        height = Math.Max(height, ft.OverhangAfter > 0 ? ft.Height + ft.OverhangAfter : ft.Height);

                                                        if (ft.WidthIncludingTrailingWhitespace > ft.Width)
                                                        {
                                                            if (ft.OverhangLeading < 0)
                                                            {
                                                                maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace) - Math.Floor(ft.OverhangLeading);

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                dc.DrawText(list[i], new Point(-Math.Floor(list[i].OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2 - Math.Floor(ft.OverhangLeading), 0));
                                                            }
                                                            else
                                                            {
                                                                maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace);

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                dc.DrawText(list[i], new Point(-Math.Floor(list[i].OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2, 0));
                                                            }
                                                        }
                                                        else
                                                        {
                                                            double width3 = Math.Ceiling(ft.Width);

                                                            if (ft.OverhangLeading < 0)
                                                            {
                                                                width3 -= Math.Floor(ft.OverhangLeading);

                                                                if (ft.OverhangTrailing < 0)
                                                                {
                                                                    width3 -= Math.Floor(ft.OverhangTrailing);
                                                                }

                                                                maxWidth += width3;

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                dc.DrawText(list[i], new Point(-Math.Floor(list[i].OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2 - Math.Floor(ft.OverhangLeading), 0));
                                                            }
                                                            else
                                                            {
                                                                if (ft.OverhangTrailing < 0)
                                                                {
                                                                    width3 -= Math.Floor(ft.OverhangTrailing);
                                                                }

                                                                maxWidth += width3;

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                dc.DrawText(list[i], new Point(-Math.Floor(list[i].OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2, 0));
                                                            }
                                                        }
                                                    }
                                                    else
                                                    {
                                                        dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                        dc.DrawText(list[i], new Point(-Math.Floor(list[i].OverhangLeading), 0));
                                                    }

                                                    dc.DrawText(list[i], new Point(maxWidth - Math.Floor(list[i].OverhangLeading), 0));
                                                    dc.Close();

                                                    dropShadowEffect.Color = Math.Max(Math.Max(this.textColor.R, this.textColor.G), this.textColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;
                                                    dropShadowEffect.BlurRadius = 1;
                                                    dropShadowEffect.Direction = 270;
                                                    dropShadowEffect.ShadowDepth = 1;
                                                    dropShadowEffect.Opacity = 0.5;

                                                    if (dropShadowEffect.CanFreeze)
                                                    {
                                                        dropShadowEffect.Freeze();
                                                    }

                                                    canvas.HorizontalAlignment = HorizontalAlignment.Left;
                                                    canvas.VerticalAlignment = VerticalAlignment.Top;
                                                    canvas.Margin = new Thickness(Math.Floor(list[i].OverhangLeading), (this.lineHeight - list[i].Height) / 2, 0, 0);
                                                    canvas.Background = Brushes.Transparent;
                                                    canvas.ClipToBounds = true;
                                                    canvas.Width = width1;
                                                    canvas.Height = height;
                                                    canvas.Effect = dropShadowEffect;

                                                    this.InspectorCanvas.Children.Add(canvas);

                                                    Canvas.SetLeft(canvas, offsetPoint.X + nextPoint.X);
                                                    Canvas.SetTop(canvas, offsetPoint.Y + nextPoint.Y);

                                                    DrawingImage di = new DrawingImage(dg);

                                                    if (di.CanFreeze)
                                                    {
                                                        di.Freeze();
                                                    }

                                                    image = new Image();
                                                    image.HorizontalAlignment = HorizontalAlignment.Left;
                                                    image.VerticalAlignment = VerticalAlignment.Top;
                                                    image.Source = di;
                                                    image.Stretch = Stretch.None;
                                                    image.Width = maxWidth + width1;
                                                    image.Height = height;
                                                    image.RenderTransform = new TranslateTransform(0, 0);
                                                    image.MouseEnter += new MouseEventHandler(delegate
                                                    {
                                                        this.subtitleIsHover = true;
                                                    });
                                                    image.MouseLeave += new MouseEventHandler(delegate
                                                    {
                                                        this.subtitleIsHover = false;
                                                    });
                                                    image.MouseLeftButtonUp += new MouseButtonEventHandler(delegate (object s, MouseButtonEventArgs mbea)
                                                    {
                                                        if (this.subtitleIsHover)
                                                        {
                                                            this.subtitleIsScrollable = true;
                                                        }

                                                        Task.Factory.StartNew(delegate (object state)
                                                        {
                                                            System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo((string)state));
                                                        }, this.inspectorEntry.Resource.GetLeftPart(UriPartial.Authority).ToString());

                                                        mbea.Handled = true;
                                                    });

                                                    RenderOptions.SetClearTypeHint(image, ClearTypeHint.Enabled);

                                                    canvas.Children.Add(image);

                                                    Canvas.SetLeft(image, 0);
                                                    Canvas.SetTop(image, 0);

                                                    this.cachedSubtitleImageDictionary.Add(i, image);
                                                }

                                                nextPoint.Y += this.lineHeight;
                                            }
                                        }

                                        if (!String.IsNullOrEmpty(this.inspectorEntry.Author))
                                        {
                                            List<KeyValuePair<double, FormattedText>> list = new List<KeyValuePair<double, FormattedText>>();
                                            Dictionary<int, int> dictionary = new Dictionary<int, int>();
                                            double y = 0;
                                            double height1 = 0;
                                            StringBuilder lineStringBuilder = new StringBuilder();
                                            bool isBreaked = false;

                                            foreach (System.Text.RegularExpressions.Match match in System.Text.RegularExpressions.Regex.Matches(this.inspectorEntry.Author, @"[\p{IsBasicLatin}-[\s]]+\s?"))
                                            {
                                                dictionary.Add(match.Index, match.Length);
                                            }

                                            for (int i = 0; i < this.inspectorEntry.Author.Length; i++)
                                            {
                                                int length;

                                                if (dictionary.TryGetValue(i, out length) && Math.Ceiling(new FormattedText(String.Concat(lineStringBuilder.ToString(), this.inspectorEntry.Author.Substring(i, length)), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace) > textWidth)
                                                {
                                                    if (lineStringBuilder.Length > 0)
                                                    {
                                                        list.Add(new KeyValuePair<double, FormattedText>(y, new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush)));
                                                    }

                                                    lineStringBuilder.Clear();
                                                    y += this.lineHeight;
                                                    height1 += this.lineHeight;
                                                    isBreaked = true;
                                                }

                                                lineStringBuilder.Append(this.inspectorEntry.Author[i]);

                                                if (lineStringBuilder.ToString().EndsWith(Environment.NewLine, StringComparison.Ordinal))
                                                {
                                                    lineStringBuilder.Remove(lineStringBuilder.ToString().LastIndexOf(Environment.NewLine, StringComparison.Ordinal), Environment.NewLine.Length);

                                                    if (lineStringBuilder.Length > 0)
                                                    {
                                                        list.Add(new KeyValuePair<double, FormattedText>(y, new FormattedText(lineStringBuilder.ToString().Substring(0, lineStringBuilder.Length), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush)));
                                                        lineStringBuilder.Remove(0, lineStringBuilder.Length);
                                                    }

                                                    y += this.lineHeight;
                                                    height1 += this.lineHeight;
                                                    isBreaked = true;
                                                }
                                                else if (lineStringBuilder.Length > 0 && Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace) > textWidth)
                                                {
                                                    if (lineStringBuilder.Length - 1 > 0)
                                                    {
                                                        list.Add(new KeyValuePair<double, FormattedText>(y, new FormattedText(lineStringBuilder.ToString().Substring(0, lineStringBuilder.Length - 1), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush)));
                                                        lineStringBuilder.Remove(0, lineStringBuilder.Length - 1);
                                                    }

                                                    y += this.lineHeight;
                                                    height1 += this.lineHeight;
                                                    isBreaked = true;
                                                }
                                            }

                                            if (lineStringBuilder.Length > 0)
                                            {
                                                list.Add(new KeyValuePair<double, FormattedText>(y, new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush)));
                                                height1 += this.lineHeight;
                                                isBreaked = false;
                                            }

                                            if (isBreaked)
                                            {
                                                height1 += this.lineHeight;
                                            }

                                            if (this.authorScrollStep.HasValue)
                                            {
                                                double step = this.authorScrollStep.Value;

                                                if (step == 1 && this.authorIsScrollable)
                                                {
                                                    step = 0;
                                                }

                                                step += 1 / (averageFrameRate / 2);

                                                if (step >= 1)
                                                {
                                                    if (this.authorIsHover)
                                                    {
                                                        this.authorScrollStep = 1;
                                                    }
                                                    else
                                                    {
                                                        this.authorScrollStep = null;
                                                    }
                                                }
                                                else
                                                {
                                                    this.authorScrollStep = step;
                                                }
                                            }
                                            else if (this.authorIsHover || this.authorIsScrollable)
                                            {
                                                double step = 1 / (averageFrameRate / 2);

                                                if (step >= 1)
                                                {
                                                    if (this.authorIsHover)
                                                    {
                                                        this.authorScrollStep = new Nullable<double>(1);
                                                    }
                                                }
                                                else
                                                {
                                                    this.authorScrollStep = new Nullable<double>(step);
                                                }
                                            }

                                            if (this.authorIsScrollable)
                                            {
                                                this.authorIsScrollable = false;
                                            }

                                            for (int i = 0; i < list.Count; i++)
                                            {
                                                Image image;

                                                if (this.cachedAuthorImageDictionary.TryGetValue(i, out image))
                                                {
                                                    TranslateTransform translateTransform = image.RenderTransform as TranslateTransform;

                                                    if (translateTransform != null)
                                                    {
                                                        if (this.authorScrollStep.HasValue)
                                                        {
                                                            double maxWidth = list[i].Value.WidthIncludingTrailingWhitespace > list[i].Value.Width ? Math.Ceiling(list[i].Value.WidthIncludingTrailingWhitespace) - Math.Floor(list[i].Value.OverhangLeading) : list[i].Value.OverhangTrailing < 0 ? Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing) : Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading);
                                                            StringBuilder sb = new StringBuilder();

                                                            for (int j = i + 1; j < list.Count; j++)
                                                            {
                                                                sb.Append(list[j].Value.Text);
                                                            }

                                                            for (int j = 0; j < i; j++)
                                                            {
                                                                sb.Append(list[j].Value.Text);
                                                            }

                                                            if (sb.Length > 0)
                                                            {
                                                                FormattedText ft = new FormattedText(sb.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                                if (ft.WidthIncludingTrailingWhitespace > ft.Width)
                                                                {
                                                                    double w = Math.Ceiling(ft.WidthIncludingTrailingWhitespace);

                                                                    if (ft.OverhangLeading < 0)
                                                                    {
                                                                        w -= Math.Floor(ft.OverhangLeading);
                                                                    }

                                                                    maxWidth += w;
                                                                }
                                                                else
                                                                {
                                                                    double w = Math.Ceiling(ft.Width);

                                                                    if (ft.OverhangLeading < 0)
                                                                    {
                                                                        w -= Math.Floor(ft.OverhangLeading);
                                                                    }

                                                                    if (ft.OverhangTrailing < 0)
                                                                    {
                                                                        w -= Math.Floor(ft.OverhangTrailing);
                                                                    }

                                                                    maxWidth += w;
                                                                }
                                                            }

                                                            translateTransform.X = -maxWidth * Math.Sin(this.authorScrollStep.Value / 2 * Math.PI);
                                                        }
                                                        else
                                                        {
                                                            translateTransform.X = 0;
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    double width1 = Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing);
                                                    double width2 = list[i].Value.WidthIncludingTrailingWhitespace > list[i].Value.Width ? Math.Ceiling(list[i].Value.WidthIncludingTrailingWhitespace) - Math.Floor(list[i].Value.OverhangLeading) : list[i].Value.OverhangTrailing < 0 ? Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing) : Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading);
                                                    double maxWidth = width2;
                                                    double height2 = list[i].Value.OverhangAfter > 0 ? list[i].Value.Height + list[i].Value.OverhangAfter : list[i].Value.Height;
                                                    Canvas canvas = new Canvas();
                                                    DropShadowEffect dropShadowEffect = new DropShadowEffect();
                                                    StringBuilder sb = new StringBuilder();
                                                    DrawingGroup dg = new DrawingGroup();
                                                    DrawingContext dc = dg.Open();

                                                    for (int j = i + 1; j < list.Count; j++)
                                                    {
                                                        sb.Append(list[j].Value.Text);
                                                    }

                                                    for (int j = 0; j < i; j++)
                                                    {
                                                        sb.Append(list[j].Value.Text);
                                                    }

                                                    if (sb.Length > 0)
                                                    {
                                                        FormattedText ft = new FormattedText(sb.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                        height2 = Math.Max(height2, ft.OverhangAfter > 0 ? ft.Height + ft.OverhangAfter : ft.Height);

                                                        if (ft.WidthIncludingTrailingWhitespace > ft.Width)
                                                        {
                                                            if (ft.OverhangLeading < 0)
                                                            {
                                                                maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace) - Math.Floor(ft.OverhangLeading);

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height2));
                                                                dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2 - Math.Floor(ft.OverhangLeading), 0));
                                                            }
                                                            else
                                                            {
                                                                maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace);

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height2));
                                                                dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2, 0));
                                                            }
                                                        }
                                                        else
                                                        {
                                                            double width3 = Math.Ceiling(ft.Width);

                                                            if (ft.OverhangLeading < 0)
                                                            {
                                                                width3 -= Math.Floor(ft.OverhangLeading);

                                                                if (ft.OverhangTrailing < 0)
                                                                {
                                                                    width3 -= Math.Floor(ft.OverhangTrailing);
                                                                }

                                                                maxWidth += width3;

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height2));
                                                                dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2 - Math.Floor(ft.OverhangLeading), 0));
                                                            }
                                                            else
                                                            {
                                                                if (ft.OverhangTrailing < 0)
                                                                {
                                                                    width3 -= Math.Floor(ft.OverhangTrailing);
                                                                }

                                                                maxWidth += width3;

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height2));
                                                                dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2, 0));
                                                            }
                                                        }
                                                    }
                                                    else
                                                    {
                                                        dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height2));
                                                        dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                    }

                                                    dc.DrawText(list[i].Value, new Point(maxWidth - Math.Floor(list[i].Value.OverhangLeading), 0));
                                                    dc.Close();

                                                    dropShadowEffect.Color = Math.Max(Math.Max(this.textColor.R, this.textColor.G), this.textColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;
                                                    dropShadowEffect.BlurRadius = 1;
                                                    dropShadowEffect.Direction = 270;
                                                    dropShadowEffect.ShadowDepth = 1;
                                                    dropShadowEffect.Opacity = 0.5;

                                                    if (dropShadowEffect.CanFreeze)
                                                    {
                                                        dropShadowEffect.Freeze();
                                                    }

                                                    canvas.HorizontalAlignment = HorizontalAlignment.Left;
                                                    canvas.VerticalAlignment = VerticalAlignment.Top;
                                                    canvas.Margin = new Thickness(Math.Floor(list[i].Value.OverhangLeading), (this.lineHeight - list[i].Value.Height) / 2, 0, 0);
                                                    canvas.Background = Brushes.Transparent;
                                                    canvas.ClipToBounds = true;
                                                    canvas.Width = width1;
                                                    canvas.Height = height2;
                                                    canvas.Effect = dropShadowEffect;

                                                    this.InspectorCanvas.Children.Add(canvas);

                                                    Canvas.SetLeft(canvas, offsetPoint.X + nextPoint.X);
                                                    Canvas.SetTop(canvas, offsetPoint.Y + nextPoint.Y + list[i].Key);

                                                    DrawingImage di = new DrawingImage(dg);

                                                    if (di.CanFreeze)
                                                    {
                                                        di.Freeze();
                                                    }

                                                    image = new Image();
                                                    image.HorizontalAlignment = HorizontalAlignment.Left;
                                                    image.VerticalAlignment = VerticalAlignment.Top;
                                                    image.Source = di;
                                                    image.Stretch = Stretch.None;
                                                    image.Width = maxWidth + width1;
                                                    image.Height = height2;
                                                    image.RenderTransform = new TranslateTransform(0, 0);
                                                    image.MouseEnter += new MouseEventHandler(delegate
                                                    {
                                                        this.authorIsHover = true;
                                                    });
                                                    image.MouseLeave += new MouseEventHandler(delegate
                                                    {
                                                        this.authorIsHover = false;
                                                    });
                                                    image.MouseLeftButtonUp += new MouseButtonEventHandler(delegate (object s, MouseButtonEventArgs mbea)
                                                    {
                                                        if (this.authorIsHover)
                                                        {
                                                            this.authorIsScrollable = true;
                                                        }

                                                        Script.Instance.Search(this.inspectorEntry.Author);

                                                        mbea.Handled = true;
                                                    });

                                                    RenderOptions.SetClearTypeHint(image, ClearTypeHint.Enabled);

                                                    canvas.Children.Add(image);

                                                    Canvas.SetLeft(image, 0);
                                                    Canvas.SetTop(image, 0);

                                                    this.cachedAuthorImageDictionary.Add(i, image);
                                                }
                                            }

                                            nextPoint.Y += height1;
                                        }

                                        if (this.inspectorEntry.Modified.Ticks > 0)
                                        {
                                            string modified = this.inspectorEntry.Modified.ToString("G", System.Globalization.CultureInfo.CurrentCulture);
                                            List<FormattedText> list = new List<FormattedText>();
                                            Dictionary<int, int> dictionary = new Dictionary<int, int>();
                                            StringBuilder lineStringBuilder = new StringBuilder();

                                            foreach (System.Text.RegularExpressions.Match match in System.Text.RegularExpressions.Regex.Matches(modified, @"\S+\s?"))
                                            {
                                                dictionary.Add(match.Index, match.Length);
                                            }

                                            for (int i = 0; i < modified.Length; i++)
                                            {
                                                int length;

                                                if (dictionary.TryGetValue(i, out length) && Math.Ceiling(new FormattedText(String.Concat(lineStringBuilder.ToString(), modified.Substring(i, length)), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.textBrush).WidthIncludingTrailingWhitespace) > textWidth)
                                                {
                                                    if (lineStringBuilder.Length > 0)
                                                    {
                                                        list.Add(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.textBrush));
                                                    }

                                                    lineStringBuilder.Clear();
                                                }

                                                int safeLineLength = lineStringBuilder.Length;

                                                lineStringBuilder.Append(modified[i]);

                                                if (Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.textBrush).WidthIncludingTrailingWhitespace) > textWidth && safeLineLength > 0)
                                                {
                                                    list.Add(new FormattedText(lineStringBuilder.ToString().Substring(0, safeLineLength), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.textBrush));
                                                    lineStringBuilder.Remove(0, safeLineLength);
                                                }
                                            }

                                            if (lineStringBuilder.Length > 0)
                                            {
                                                list.Add(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.textBrush));
                                            }

                                            list.ForEach(delegate (FormattedText formattedText)
                                            {
                                                if (isEmpty)
                                                {
                                                    double width = Math.Ceiling(formattedText.Width) - Math.Floor(formattedText.OverhangLeading) - Math.Floor(formattedText.OverhangTrailing);
                                                    double height = formattedText.OverhangAfter > 0 ? formattedText.Height + formattedText.OverhangAfter : formattedText.Height;
                                                    Canvas canvas = new Canvas();
                                                    DropShadowEffect dropShadowEffect = new DropShadowEffect();
                                                    Image image = new Image();
                                                    DrawingGroup dg = new DrawingGroup();
                                                    DrawingContext dc = dg.Open();

                                                    dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, width, height));
                                                    dc.DrawText(formattedText, new Point(-Math.Floor(formattedText.OverhangLeading), 0));
                                                    dc.Close();

                                                    dropShadowEffect.Color = Math.Max(Math.Max(this.textColor.R, this.textColor.G), this.textColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;
                                                    dropShadowEffect.BlurRadius = 1;
                                                    dropShadowEffect.Direction = 270;
                                                    dropShadowEffect.ShadowDepth = 1;
                                                    dropShadowEffect.Opacity = 0.5;

                                                    if (dropShadowEffect.CanFreeze)
                                                    {
                                                        dropShadowEffect.Freeze();
                                                    }

                                                    canvas.HorizontalAlignment = HorizontalAlignment.Left;
                                                    canvas.VerticalAlignment = VerticalAlignment.Top;
                                                    canvas.Margin = new Thickness(Math.Floor(formattedText.OverhangLeading), (this.lineHeight - formattedText.Height) / 2, 0, 0);
                                                    canvas.Background = Brushes.Transparent;
                                                    canvas.Width = width;
                                                    canvas.Height = height;
                                                    canvas.Effect = dropShadowEffect;
                                                    canvas.Children.Add(image);

                                                    this.InspectorCanvas.Children.Add(canvas);

                                                    Canvas.SetLeft(canvas, offsetPoint.X + nextPoint.X);
                                                    Canvas.SetTop(canvas, offsetPoint.Y + nextPoint.Y);

                                                    DrawingImage di = new DrawingImage(dg);

                                                    if (di.CanFreeze)
                                                    {
                                                        di.Freeze();
                                                    }

                                                    image.HorizontalAlignment = HorizontalAlignment.Left;
                                                    image.VerticalAlignment = VerticalAlignment.Top;
                                                    image.Source = di;
                                                    image.Stretch = Stretch.None;
                                                    image.Width = width;
                                                    image.Height = height;

                                                    RenderOptions.SetClearTypeHint(image, ClearTypeHint.Enabled);

                                                    Canvas.SetLeft(image, 0);
                                                    Canvas.SetTop(image, 0);
                                                }

                                                nextPoint.Y += this.lineHeight;
                                            });
                                        }

                                        if (this.inspectorEntry.Score.HasValue)
                                        {
                                            string score = this.inspectorEntry.Score.Value.ToString("F3", System.Globalization.CultureInfo.CurrentCulture);
                                            List<FormattedText> list = new List<FormattedText>();
                                            StringBuilder lineStringBuilder = new StringBuilder();
                                            bool isFirst = true;

                                            for (int i = 0; i < score.Length; i++)
                                            {
                                                int safeLineLength = lineStringBuilder.Length;

                                                lineStringBuilder.Append(score[i]);

                                                if (space + Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.textBrush).WidthIncludingTrailingWhitespace) > textWidth && safeLineLength > 0)
                                                {
                                                    list.Add(new FormattedText(lineStringBuilder.ToString().Substring(0, safeLineLength), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.textBrush));
                                                    lineStringBuilder.Remove(0, safeLineLength);
                                                }
                                            }

                                            if (lineStringBuilder.Length > 0)
                                            {
                                                list.Add(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.textBrush));
                                            }

                                            list.ForEach(delegate (FormattedText formattedText)
                                            {
                                                if (isEmpty)
                                                {
                                                    double width = Math.Ceiling(formattedText.Width) - Math.Floor(formattedText.OverhangLeading) - Math.Floor(formattedText.OverhangTrailing);
                                                    double height = formattedText.OverhangAfter > 0 ? formattedText.Height + formattedText.OverhangAfter : formattedText.Height;
                                                    Canvas canvas = new Canvas();
                                                    DropShadowEffect dropShadowEffect = new DropShadowEffect();
                                                    Image image = new Image();
                                                    DrawingGroup dg = new DrawingGroup();
                                                    DrawingContext dc = dg.Open();

                                                    dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, width, height));
                                                    dc.DrawText(formattedText, new Point(-Math.Floor(formattedText.OverhangLeading), 0));
                                                    dc.Close();

                                                    dropShadowEffect.Color = Math.Max(Math.Max(this.textColor.R, this.textColor.G), this.textColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;
                                                    dropShadowEffect.BlurRadius = 1;
                                                    dropShadowEffect.Direction = 270;
                                                    dropShadowEffect.ShadowDepth = 1;
                                                    dropShadowEffect.Opacity = 0.5;

                                                    if (dropShadowEffect.CanFreeze)
                                                    {
                                                        dropShadowEffect.Freeze();
                                                    }

                                                    canvas.HorizontalAlignment = HorizontalAlignment.Left;
                                                    canvas.VerticalAlignment = VerticalAlignment.Top;
                                                    canvas.Margin = new Thickness(Math.Floor(formattedText.OverhangLeading), (this.lineHeight - formattedText.Height) / 2, 0, 0);
                                                    canvas.Background = Brushes.Transparent;
                                                    canvas.Width = width;
                                                    canvas.Height = height;
                                                    canvas.Effect = dropShadowEffect;

                                                    this.InspectorCanvas.Children.Add(canvas);

                                                    Canvas.SetLeft(canvas, offsetPoint.X + nextPoint.X + space / 2);
                                                    Canvas.SetTop(canvas, offsetPoint.Y + nextPoint.Y);

                                                    DrawingImage di = new DrawingImage(dg);

                                                    if (di.CanFreeze)
                                                    {
                                                        di.Freeze();
                                                    }

                                                    image.HorizontalAlignment = HorizontalAlignment.Left;
                                                    image.VerticalAlignment = VerticalAlignment.Top;
                                                    image.Source = di;
                                                    image.Stretch = Stretch.None;
                                                    image.Width = width;
                                                    image.Height = height;

                                                    RenderOptions.SetClearTypeHint(image, ClearTypeHint.Enabled);

                                                    canvas.Children.Add(image);

                                                    Canvas.SetLeft(image, 0);
                                                    Canvas.SetTop(image, 0);

                                                    if (isFirst)
                                                    {
                                                        Rectangle rectangle = new Rectangle();
                                                        Rect blockRect = new Rect(offsetPoint.X + nextPoint.X, offsetPoint.Y + nextPoint.Y + (this.lineHeight - 3) / 2, 3, 3);

                                                        rectangle.CacheMode = new BitmapCache(1);
                                                        rectangle.HorizontalAlignment = HorizontalAlignment.Left;
                                                        rectangle.VerticalAlignment = VerticalAlignment.Top;
                                                        rectangle.Fill = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White;
                                                        rectangle.Width = blockRect.Width;
                                                        rectangle.Height = blockRect.Height;

                                                        PresentationSource presentationSource = PresentationSource.FromVisual(this);

                                                        if (presentationSource != null && presentationSource.CompositionTarget != null && presentationSource.CompositionTarget.TransformToDevice.M11 == 1.0 && presentationSource.CompositionTarget.TransformToDevice.M22 == 1.0)
                                                        {
                                                            RenderOptions.SetEdgeMode(rectangle, EdgeMode.Aliased);
                                                        }

                                                        this.InspectorCanvas.Children.Add(rectangle);

                                                        Canvas.SetLeft(rectangle, blockRect.X);
                                                        Canvas.SetTop(rectangle, blockRect.Y);

                                                        isFirst = false;
                                                    }
                                                }

                                                nextPoint.Y += this.lineHeight;
                                            });
                                        }

                                        for (int tagIndex = 0, innerTagIndex = 0, lines = 0, canvasIndex = this.InspectorCanvas.Children.Count - this.cachedTagImageDictionary.Count; tagIndex < this.inspectorEntry.Tags.Count; tagIndex++)
                                        {
                                            string tag = this.inspectorEntry.Tags[tagIndex];
                                            List<KeyValuePair<double, FormattedText>> list = new List<KeyValuePair<double, FormattedText>>();
                                            Dictionary<int, int> dictionary = new Dictionary<int, int>();
                                            StringBuilder lineStringBuilder = new StringBuilder();
                                            bool isScrollable = false;
                                            double step;
                                            Nullable<double> scrollStep = null;

                                            foreach (System.Text.RegularExpressions.Match match in System.Text.RegularExpressions.Regex.Matches(tag, @"[\p{IsBasicLatin}-[\s]]+\s?"))
                                            {
                                                dictionary.Add(match.Index, match.Length);
                                            }

                                            if (nextPoint.X + space + Math.Ceiling(new FormattedText(tag, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace) > textWidth && nextPoint.X != 0)
                                            {
                                                nextPoint.X = 0;
                                                lines++;
                                            }

                                            for (int i = 0; i < tag.Length; i++)
                                            {
                                                int length;

                                                if (dictionary.TryGetValue(i, out length) && nextPoint.X + space + Math.Ceiling(new FormattedText(String.Concat(lineStringBuilder.ToString(), tag.Substring(i, length)), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace) > textWidth)
                                                {
                                                    if (lineStringBuilder.Length > 0)
                                                    {
                                                        list.Add(new KeyValuePair<double, FormattedText>(nextPoint.X, new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush)));
                                                    }

                                                    lineStringBuilder.Clear();
                                                    nextPoint.X = 0;
                                                }

                                                lineStringBuilder.Append(tag[i]);

                                                if (lineStringBuilder.ToString().EndsWith(Environment.NewLine, StringComparison.Ordinal))
                                                {
                                                    lineStringBuilder.Remove(lineStringBuilder.ToString().LastIndexOf(Environment.NewLine, StringComparison.Ordinal), Environment.NewLine.Length);

                                                    if (lineStringBuilder.Length > 0)
                                                    {
                                                        list.Add(new KeyValuePair<double, FormattedText>(nextPoint.X, new FormattedText(lineStringBuilder.ToString().Substring(0, lineStringBuilder.Length), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush)));
                                                        lineStringBuilder.Remove(0, lineStringBuilder.Length);
                                                    }

                                                    nextPoint.X = 0;
                                                }
                                                else if (lineStringBuilder.Length > 0 && nextPoint.X + space + Math.Ceiling(new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush).WidthIncludingTrailingWhitespace) > textWidth)
                                                {
                                                    if (lineStringBuilder.Length - 1 > 0)
                                                    {
                                                        list.Add(new KeyValuePair<double, FormattedText>(nextPoint.X, new FormattedText(lineStringBuilder.ToString().Substring(0, lineStringBuilder.Length - 1), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush)));
                                                        lineStringBuilder.Remove(0, lineStringBuilder.Length - 1);
                                                    }

                                                    nextPoint.X = 0;
                                                }
                                            }

                                            if (lineStringBuilder.Length > 0)
                                            {
                                                FormattedText formattedText = new FormattedText(lineStringBuilder.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                list.Add(new KeyValuePair<double, FormattedText>(nextPoint.X, formattedText));
                                                nextPoint.X += space + Math.Ceiling(formattedText.WidthIncludingTrailingWhitespace);
                                            }

                                            if (this.tagIsScrollableHashSet.Contains(tagIndex))
                                            {
                                                isScrollable = true;
                                                this.tagIsScrollableHashSet.Remove(tagIndex);
                                            }

                                            if (this.tagScrollStepDictionary.TryGetValue(tagIndex, out step))
                                            {
                                                if (step == 1 && isScrollable)
                                                {
                                                    step = 0;
                                                }

                                                step += 1 / (averageFrameRate / 2);

                                                if (step >= 1)
                                                {
                                                    if (this.hoverTagIndex.HasValue && this.hoverTagIndex.Value == tagIndex)
                                                    {
                                                        scrollStep = new Nullable<double>(1);
                                                        this.tagScrollStepDictionary[tagIndex] = 1;
                                                    }
                                                    else
                                                    {
                                                        this.tagScrollStepDictionary.Remove(tagIndex);
                                                    }
                                                }
                                                else
                                                {
                                                    scrollStep = new Nullable<double>(step);
                                                    this.tagScrollStepDictionary[tagIndex] = step;
                                                }
                                            }
                                            else if (this.hoverTagIndex.HasValue && this.hoverTagIndex.Value == tagIndex || isScrollable)
                                            {
                                                step = 1 / (averageFrameRate / 2);

                                                if (step >= 1)
                                                {
                                                    if (this.hoverTagIndex.HasValue && this.hoverTagIndex.Value == tagIndex)
                                                    {
                                                        scrollStep = new Nullable<double>(1);
                                                        this.tagScrollStepDictionary.Add(tagIndex, 1);
                                                    }
                                                }
                                                else
                                                {
                                                    scrollStep = new Nullable<double>(step);
                                                    this.tagScrollStepDictionary.Add(tagIndex, step);
                                                }
                                            }

                                            for (int i = 0; i < list.Count; i++)
                                            {
                                                Image image;

                                                if (this.cachedTagImageDictionary.TryGetValue(innerTagIndex, out image))
                                                {
                                                    if (Math.Min(this.previousCirculationIndex, this.nextCirculationIndex) <= lines && lines <= Math.Max(this.previousCirculationIndex, this.nextCirculationIndex))
                                                    {
                                                        TranslateTransform translateTransform1 = image.RenderTransform as TranslateTransform;

                                                        if (translateTransform1 != null)
                                                        {
                                                            if (scrollStep.HasValue)
                                                            {
                                                                double maxWidth = list[i].Value.WidthIncludingTrailingWhitespace > list[i].Value.Width ? Math.Ceiling(list[i].Value.WidthIncludingTrailingWhitespace) - Math.Floor(list[i].Value.OverhangLeading) : list[i].Value.OverhangTrailing < 0 ? Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing) : Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading);
                                                                StringBuilder sb = new StringBuilder();

                                                                for (int j = i + 1; j < list.Count; j++)
                                                                {
                                                                    sb.Append(list[j].Value.Text);
                                                                }

                                                                for (int j = 0; j < i; j++)
                                                                {
                                                                    sb.Append(list[j].Value.Text);
                                                                }

                                                                if (sb.Length > 0)
                                                                {
                                                                    FormattedText ft = new FormattedText(sb.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                                    if (ft.WidthIncludingTrailingWhitespace > ft.Width)
                                                                    {
                                                                        double w = Math.Ceiling(ft.WidthIncludingTrailingWhitespace);

                                                                        if (ft.OverhangLeading < 0)
                                                                        {
                                                                            w -= Math.Floor(ft.OverhangLeading);
                                                                        }

                                                                        maxWidth += w;
                                                                    }
                                                                    else
                                                                    {
                                                                        double w = Math.Ceiling(ft.Width);

                                                                        if (ft.OverhangLeading < 0)
                                                                        {
                                                                            w -= Math.Floor(ft.OverhangLeading);
                                                                        }

                                                                        if (ft.OverhangTrailing < 0)
                                                                        {
                                                                            w -= Math.Floor(ft.OverhangTrailing);
                                                                        }

                                                                        maxWidth += w;
                                                                    }
                                                                }

                                                                translateTransform1.X = -maxWidth * Math.Sin(scrollStep.Value / 2 * Math.PI);
                                                            }
                                                            else
                                                            {
                                                                translateTransform1.X = 0;
                                                            }
                                                        }

                                                        Canvas canvas1 = image.Parent as Canvas;

                                                        if (canvas1 != null)
                                                        {
                                                            Canvas canvas2 = canvas1.Parent as Canvas;

                                                            if (canvas2 != null)
                                                            {
                                                                if (isCirculating)
                                                                {
                                                                    double y = 0;

                                                                    if (Math.Min(this.previousCirculationIndex, this.nextCirculationIndex) <= lines && lines <= Math.Max(this.previousCirculationIndex, this.nextCirculationIndex))
                                                                    {
                                                                        if (this.previousCirculationIndex < this.nextCirculationIndex)
                                                                        {
                                                                            y = (lines - Math.Min(this.previousCirculationIndex, this.nextCirculationIndex)) * this.lineHeight - (Math.Max(this.previousCirculationIndex, this.nextCirculationIndex) - Math.Min(this.previousCirculationIndex, this.nextCirculationIndex)) * this.lineHeight * Math.Sin(this.circulationStep / 2 * Math.PI);
                                                                        }
                                                                        else if (this.previousCirculationIndex > this.nextCirculationIndex)
                                                                        {
                                                                            y = (lines - Math.Min(this.previousCirculationIndex, this.nextCirculationIndex)) * this.lineHeight - (Math.Max(this.previousCirculationIndex, this.nextCirculationIndex) - Math.Min(this.previousCirculationIndex, this.nextCirculationIndex)) * this.lineHeight * Math.Cos(this.circulationStep / 2 * Math.PI);
                                                                        }
                                                                    }

                                                                    TranslateTransform translateTransform2 = canvas2.RenderTransform as TranslateTransform;

                                                                    if (translateTransform2 != null)
                                                                    {
                                                                        translateTransform2.Y = y;
                                                                    }
                                                                }
                                                            }
                                                        }

                                                        canvasIndex++;
                                                    }
                                                    else
                                                    {
                                                        Canvas canvas1 = image.Parent as Canvas;

                                                        if (canvas1 != null)
                                                        {
                                                            Canvas canvas2 = canvas1.Parent as Canvas;

                                                            if (canvas2 != null)
                                                            {
                                                                Canvas canvas3 = canvas2.Parent as Canvas;

                                                                if (canvas3 != null)
                                                                {
                                                                    this.InspectorCanvas.Children.Remove(canvas3);
                                                                }
                                                            }
                                                        }

                                                        this.cachedTagImageDictionary.Remove(innerTagIndex);
                                                    }
                                                }
                                                else if (Math.Min(this.previousCirculationIndex, this.nextCirculationIndex) <= lines && lines <= Math.Max(this.previousCirculationIndex, this.nextCirculationIndex))
                                                {
                                                    int index = tagIndex;
                                                    double width1 = Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing);
                                                    double width2 = list[i].Value.WidthIncludingTrailingWhitespace > list[i].Value.Width ? Math.Ceiling(list[i].Value.WidthIncludingTrailingWhitespace) - Math.Floor(list[i].Value.OverhangLeading) : list[i].Value.OverhangTrailing < 0 ? Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading) - Math.Floor(list[i].Value.OverhangTrailing) : Math.Ceiling(list[i].Value.Width) - Math.Floor(list[i].Value.OverhangLeading);
                                                    double maxWidth = width2;
                                                    double height = list[i].Value.OverhangAfter > 0 ? list[i].Value.Height + list[i].Value.OverhangAfter : list[i].Value.Height;
                                                    double y = 0;
                                                    Canvas canvas1 = new Canvas();
                                                    Canvas canvas2 = new Canvas();
                                                    Canvas canvas3 = new Canvas();
                                                    DropShadowEffect dropShadowEffect = new DropShadowEffect();
                                                    Rectangle rectangle = new Rectangle();
                                                    StringBuilder sb = new StringBuilder();
                                                    DrawingGroup dg = new DrawingGroup();
                                                    DrawingContext dc = dg.Open();

                                                    for (int j = i + 1; j < list.Count; j++)
                                                    {
                                                        sb.Append(list[j].Value.Text);
                                                    }

                                                    for (int j = 0; j < i; j++)
                                                    {
                                                        sb.Append(list[j].Value.Text);
                                                    }

                                                    if (sb.Length > 0)
                                                    {
                                                        FormattedText ft = new FormattedText(sb.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.linkBrush);

                                                        height = Math.Max(height, ft.OverhangAfter > 0 ? ft.Height + ft.OverhangAfter : ft.Height);

                                                        if (ft.WidthIncludingTrailingWhitespace > ft.Width)
                                                        {
                                                            if (ft.OverhangLeading < 0)
                                                            {
                                                                maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace) - Math.Floor(ft.OverhangLeading);

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2 - Math.Floor(ft.OverhangLeading), 0));
                                                            }
                                                            else
                                                            {
                                                                maxWidth += Math.Ceiling(ft.WidthIncludingTrailingWhitespace);

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2, 0));
                                                            }
                                                        }
                                                        else
                                                        {
                                                            double width3 = Math.Ceiling(ft.Width);

                                                            if (ft.OverhangLeading < 0)
                                                            {
                                                                width3 -= Math.Floor(ft.OverhangLeading);

                                                                if (ft.OverhangTrailing < 0)
                                                                {
                                                                    width3 -= Math.Floor(ft.OverhangTrailing);
                                                                }

                                                                maxWidth += width3;

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2 - Math.Floor(ft.OverhangLeading), 0));
                                                            }
                                                            else
                                                            {
                                                                if (ft.OverhangTrailing < 0)
                                                                {
                                                                    width3 -= Math.Floor(ft.OverhangTrailing);
                                                                }

                                                                maxWidth += width3;

                                                                dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                                dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                                dc.DrawText(ft, new Point(width2, 0));
                                                            }
                                                        }
                                                    }
                                                    else
                                                    {
                                                        dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, maxWidth + width1, height));
                                                        dc.DrawText(list[i].Value, new Point(-Math.Floor(list[i].Value.OverhangLeading), 0));
                                                    }

                                                    dc.DrawText(list[i].Value, new Point(maxWidth - Math.Floor(list[i].Value.OverhangLeading), 0));
                                                    dc.Close();

                                                    canvas3.HorizontalAlignment = HorizontalAlignment.Left;
                                                    canvas3.VerticalAlignment = VerticalAlignment.Top;
                                                    canvas3.Background = Brushes.Transparent;
                                                    canvas3.ClipToBounds = true;
                                                    canvas3.Width = space + Math.Floor(list[i].Value.OverhangLeading) + width1;
                                                    canvas3.Height = this.lineHeight;

                                                    this.InspectorCanvas.Children.Insert(canvasIndex, canvas3);

                                                    Canvas.SetLeft(canvas3, offsetPoint.X + list[i].Key);
                                                    Canvas.SetTop(canvas3, offsetPoint.Y + nextPoint.Y);

                                                    if (Math.Min(this.previousCirculationIndex, this.nextCirculationIndex) <= lines && lines <= Math.Max(this.previousCirculationIndex, this.nextCirculationIndex))
                                                    {
                                                        if (this.previousCirculationIndex < this.nextCirculationIndex)
                                                        {
                                                            y = (lines - Math.Min(this.previousCirculationIndex, this.nextCirculationIndex)) * this.lineHeight - (Math.Max(this.previousCirculationIndex, this.nextCirculationIndex) - Math.Min(this.previousCirculationIndex, this.nextCirculationIndex)) * this.lineHeight * Math.Sin(this.circulationStep / 2 * Math.PI);
                                                        }
                                                        else if (this.previousCirculationIndex > this.nextCirculationIndex)
                                                        {
                                                            y = (lines - Math.Min(this.previousCirculationIndex, this.nextCirculationIndex)) * this.lineHeight - (Math.Max(this.previousCirculationIndex, this.nextCirculationIndex) - Math.Min(this.previousCirculationIndex, this.nextCirculationIndex)) * this.lineHeight * Math.Cos(this.circulationStep / 2 * Math.PI);
                                                        }
                                                    }

                                                    canvas2.HorizontalAlignment = HorizontalAlignment.Left;
                                                    canvas2.VerticalAlignment = VerticalAlignment.Top;
                                                    canvas2.Background = Brushes.Transparent;
                                                    canvas2.Width = width1;
                                                    canvas2.Height = height;
                                                    canvas2.RenderTransform = new TranslateTransform(0, y);

                                                    canvas3.Children.Add(canvas2);

                                                    Canvas.SetLeft(canvas2, 0);
                                                    Canvas.SetTop(canvas2, 0);

                                                    dropShadowEffect.Color = Math.Max(Math.Max(this.textColor.R, this.textColor.G), this.textColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;
                                                    dropShadowEffect.BlurRadius = 1;
                                                    dropShadowEffect.Direction = 270;
                                                    dropShadowEffect.ShadowDepth = 1;
                                                    dropShadowEffect.Opacity = 0.5;

                                                    if (dropShadowEffect.CanFreeze)
                                                    {
                                                        dropShadowEffect.Freeze();
                                                    }

                                                    canvas1.HorizontalAlignment = HorizontalAlignment.Left;
                                                    canvas1.VerticalAlignment = VerticalAlignment.Top;
                                                    canvas1.Margin = new Thickness(Math.Floor(list[i].Value.OverhangLeading), (this.lineHeight - list[i].Value.Height) / 2, 0, 0);
                                                    canvas1.Background = Brushes.Transparent;
                                                    canvas1.ClipToBounds = true;
                                                    canvas1.Width = width1;
                                                    canvas1.Height = height;
                                                    canvas1.Effect = dropShadowEffect;

                                                    canvas2.Children.Add(canvas1);

                                                    Canvas.SetLeft(canvas1, space / 2);
                                                    Canvas.SetTop(canvas1, 0);

                                                    DrawingImage di = new DrawingImage(dg);

                                                    if (di.CanFreeze)
                                                    {
                                                        di.Freeze();
                                                    }

                                                    image = new Image();
                                                    image.HorizontalAlignment = HorizontalAlignment.Left;
                                                    image.VerticalAlignment = VerticalAlignment.Top;
                                                    image.Source = di;
                                                    image.Stretch = Stretch.None;
                                                    image.Width = maxWidth + width1;
                                                    image.Height = height;
                                                    image.RenderTransform = new TranslateTransform(0, 0);
                                                    image.MouseEnter += new MouseEventHandler(delegate
                                                    {
                                                        this.hoverTagIndex = new Nullable<int>(index);

                                                        if (lines > 0)
                                                        {
                                                            this.switchTimer.Stop();
                                                        }
                                                    });
                                                    image.MouseLeave += new MouseEventHandler(delegate
                                                    {
                                                        this.hoverTagIndex = null;

                                                        if (lines > 0)
                                                        {
                                                            this.switchTimer.Start();
                                                        }
                                                    });
                                                    image.MouseLeftButtonDown += new MouseButtonEventHandler(delegate (object s, MouseButtonEventArgs mbea)
                                                    {
                                                        if (lines > 0)
                                                        {
                                                            this.mouseDownPosition = new Nullable<Point>(PointToScreen(mbea.GetPosition(this)));

                                                            image.CaptureMouse();
                                                        }
                                                    });
                                                    image.MouseLeftButtonUp += new MouseButtonEventHandler(delegate (object s, MouseButtonEventArgs mbea)
                                                    {
                                                        if (this.mouseDownPosition.HasValue)
                                                        {
                                                            Point point = PointToScreen(mbea.GetPosition(this));

                                                            if (Math.Sign(point.Y - this.mouseDownPosition.Value.Y) > 0)
                                                            {
                                                                this.circulationQueue.Enqueue(-1);
                                                            }
                                                            else if (Math.Sign(point.Y - this.mouseDownPosition.Value.Y) < 0)
                                                            {
                                                                this.circulationQueue.Enqueue(1);
                                                            }

                                                            this.mouseDownPosition = null;
                                                        }

                                                        if (image.IsMouseCaptured)
                                                        {
                                                            image.ReleaseMouseCapture();
                                                        }

                                                        if (this.hoverTagIndex.HasValue)
                                                        {
                                                            if (!this.tagIsScrollableHashSet.Contains(this.hoverTagIndex.Value))
                                                            {
                                                                this.tagIsScrollableHashSet.Add(this.hoverTagIndex.Value);
                                                            }

                                                            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                                                            {
                                                                Script.Instance.Learn(tag);
                                                            }
                                                            else
                                                            {
                                                                Script.Instance.Search(tag);
                                                            }
                                                        }

                                                        mbea.Handled = true;
                                                    });

                                                    RenderOptions.SetClearTypeHint(image, ClearTypeHint.Enabled);

                                                    canvas1.Children.Add(image);

                                                    Canvas.SetLeft(image, 0);
                                                    Canvas.SetTop(image, 0);

                                                    if (i == 0)
                                                    {
                                                        Rect blockRect = new Rect(0, (this.lineHeight - 3) / 2, 3, 3);

                                                        rectangle.CacheMode = new BitmapCache(1);
                                                        rectangle.HorizontalAlignment = HorizontalAlignment.Left;
                                                        rectangle.VerticalAlignment = VerticalAlignment.Top;
                                                        rectangle.Fill = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White;
                                                        rectangle.Width = blockRect.Width;
                                                        rectangle.Height = blockRect.Height;

                                                        PresentationSource presentationSource = PresentationSource.FromVisual(this);

                                                        if (presentationSource != null && presentationSource.CompositionTarget != null && presentationSource.CompositionTarget.TransformToDevice.M11 == 1.0 && presentationSource.CompositionTarget.TransformToDevice.M22 == 1.0)
                                                        {
                                                            RenderOptions.SetEdgeMode(rectangle, EdgeMode.Aliased);
                                                        }

                                                        canvas2.Children.Add(rectangle);

                                                        Canvas.SetLeft(rectangle, blockRect.X);
                                                        Canvas.SetTop(rectangle, blockRect.Y);
                                                    }

                                                    this.cachedTagImageDictionary.Add(innerTagIndex, image);
                                                    canvasIndex++;
                                                }

                                                if (i != list.Count - 1)
                                                {
                                                    lines++;
                                                }

                                                innerTagIndex++;
                                            }
                                        }

                                        if (isEmpty)
                                        {
                                            this.InspectorCanvas.UpdateLayout();
                                        }
                                    }

                                    if (this.InspectorImage.Source == null || isLoading || isSliding || isPopupping || isBlinking)
                                    {
                                        Size imageSize = new Size(32, 32);

                                        if (this.imageUri == null && this.cachedBitmapImage == null)
                                        {
                                            Pen pen = new Pen(Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White, 1);
                                            DrawingGroup dg = new DrawingGroup();
                                            DrawingContext dc = dg.Open();
                                            GeometryGroup gg = new GeometryGroup();
                                            GuidelineSet gs1 = new GuidelineSet();
                                            GuidelineSet gs2 = new GuidelineSet();

                                            gg.FillRule = FillRule.Nonzero;
                                            gg.Children.Add(new LineGeometry(new Point(pen.Thickness / 2, pen.Thickness / 2), new Point(imageSize.Width - pen.Thickness / 2, imageSize.Height - pen.Thickness / 2)));
                                            gg.Children.Add(new LineGeometry(new Point(pen.Thickness / 2, imageSize.Height - pen.Thickness / 2), new Point(imageSize.Width - pen.Thickness / 2, pen.Thickness / 2)));

                                            gs1.GuidelinesX.Add(0);
                                            gs1.GuidelinesX.Add(imageSize.Width);
                                            gs1.GuidelinesY.Add(0);
                                            gs1.GuidelinesY.Add(imageSize.Height);

                                            dc.PushGuidelineSet(gs1);
                                            dc.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, imageSize.Width, imageSize.Height));
                                            dc.DrawGeometry(null, pen, gg);
                                            dc.DrawRectangle(null, pen, new Rect(pen.Thickness / 2, pen.Thickness / 2, imageSize.Width - pen.Thickness, imageSize.Height - pen.Thickness));
                                            dc.Close();

                                            gs2.GuidelinesX.Add(dg.Bounds.X);
                                            gs2.GuidelinesX.Add(dg.Bounds.X + Math.Ceiling(dg.Bounds.Width));
                                            gs2.GuidelinesY.Add(dg.Bounds.Y);
                                            gs2.GuidelinesY.Add(dg.Bounds.Y + Math.Ceiling(dg.Bounds.Height));

                                            dg.GuidelineSet = gs2;
                                            dg.Children.Add(new GeometryDrawing(Brushes.Transparent, null, new RectangleGeometry(new Rect(dg.Bounds.X, dg.Bounds.Y, Math.Ceiling(dg.Bounds.Width), Math.Ceiling(dg.Bounds.Height)))));

                                            DrawingImage di = new DrawingImage(dg);

                                            if (di.CanFreeze)
                                            {
                                                di.Freeze();
                                            }

                                            this.InspectorImage.Source = di;
                                            this.InspectorImage.Width = Math.Ceiling(dg.Bounds.Width);
                                            this.InspectorImage.Height = Math.Ceiling(dg.Bounds.Height);

                                            Canvas.SetLeft(this.InspectorImage, Canvas.GetLeft(this.InspectorCanvas) + 8);
                                            Canvas.SetTop(this.InspectorImage, Canvas.GetTop(this.InspectorCanvas));
                                        }
                                        else if (this.imagePopupStep > 0 && this.cachedBitmapImage != null)
                                        {
                                            double thickness = 1;
                                            Pen pen = new Pen();
                                            ImageBrush previousImageBrush = new ImageBrush(this.cachedBitmapImage);
                                            DrawingGroup dg = new DrawingGroup();
                                            DrawingContext dc = dg.Open();
                                            GeometryGroup gg = new GeometryGroup();
                                            GuidelineSet gs1 = new GuidelineSet();
                                            GuidelineSet gs2 = new GuidelineSet();
                                            double step = Math.Sin(this.imagePopupStep / 2 * Math.PI);

                                            pen.Thickness = thickness;

                                            if (this.imageBlinkStep > 0)
                                            {
                                                Color color = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;

                                                pen.Brush = new SolidColorBrush(Color.FromArgb((byte)(color.A + (this.linkColor.A - color.A) * Math.Sin(this.imageBlinkStep * Math.PI)), (byte)(color.R + (this.linkColor.R - color.R) * Math.Sin(this.imageBlinkStep * Math.PI)), (byte)(color.G + (this.linkColor.G - color.G) * Math.Sin(this.imageBlinkStep * Math.PI)), (byte)(color.B + (this.linkColor.B - color.B) * Math.Sin(this.imageBlinkStep * Math.PI))));
                                            }
                                            else
                                            {
                                                pen.Brush = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White;
                                            }

                                            Point imageLocation = new Point(Canvas.GetLeft(this.InspectorCanvas) + 8, Canvas.GetTop(this.InspectorCanvas));
                                            Rect drawableRect = new Rect(imageLocation.X, this.baseHeaderHeight, this.Canvas.Width - imageLocation.X * 2, this.Canvas.Height - this.baseHeaderHeight - this.baseFooterHeight);
                                            Size popupImageSize = new Size(this.cachedBitmapImage.Width, this.cachedBitmapImage.Height);

                                            if ((Canvas.GetTop(this.InspectorCanvas) + imageSize.Height) > (drawableRect.Y + drawableRect.Height))
                                            {
                                                drawableRect.Height += (Canvas.GetTop(this.InspectorCanvas) + imageSize.Height) - (drawableRect.Y + drawableRect.Height);
                                            }

                                            if (this.cachedBitmapImage.Width > drawableRect.Width || this.cachedBitmapImage.Height > drawableRect.Height)
                                            {
                                                if (this.cachedBitmapImage.Width > this.cachedBitmapImage.Height)
                                                {
                                                    popupImageSize.Width = drawableRect.Width;
                                                    popupImageSize.Height = drawableRect.Width * this.cachedBitmapImage.PixelHeight / this.cachedBitmapImage.PixelWidth;

                                                    if (popupImageSize.Height > drawableRect.Height)
                                                    {
                                                        popupImageSize.Width = drawableRect.Height * this.cachedBitmapImage.PixelWidth / this.cachedBitmapImage.PixelHeight;
                                                        popupImageSize.Height = drawableRect.Height;
                                                    }
                                                }
                                                else
                                                {
                                                    popupImageSize.Width = drawableRect.Height * this.cachedBitmapImage.PixelWidth / this.cachedBitmapImage.PixelHeight;
                                                    popupImageSize.Height = drawableRect.Height;

                                                    if (popupImageSize.Width > drawableRect.Width)
                                                    {
                                                        popupImageSize.Width = drawableRect.Width;
                                                        popupImageSize.Height = drawableRect.Width * this.cachedBitmapImage.PixelHeight / this.cachedBitmapImage.PixelWidth;
                                                    }
                                                }
                                            }

                                            Rect popupImageRect = new Rect(drawableRect.X, imageLocation.Y - (popupImageSize.Height - imageSize.Height) / 2, popupImageSize.Width, popupImageSize.Height);

                                            if (popupImageRect.Y < Canvas.GetTop(this.ScrollCanvas))
                                            {
                                                popupImageRect.Y += Canvas.GetTop(this.ScrollCanvas) - popupImageRect.Y;
                                            }
                                            else if (popupImageRect.Y + popupImageRect.Height > drawableRect.Y + drawableRect.Height)
                                            {
                                                popupImageRect.Y -= (popupImageRect.Y + popupImageRect.Height) - (drawableRect.Y + drawableRect.Height);
                                            }

                                            popupImageRect = new Rect(imageLocation.X + (popupImageRect.X - imageLocation.X) * step, imageLocation.Y + (popupImageRect.Y - imageLocation.Y) * step, imageSize.Width + (popupImageRect.Width - imageSize.Width) * step, imageSize.Height + (popupImageRect.Height - imageSize.Height) * step);

                                            gs1.GuidelinesX.Add(0);
                                            gs1.GuidelinesX.Add(popupImageRect.Width);
                                            gs1.GuidelinesY.Add(0);
                                            gs1.GuidelinesY.Add(popupImageRect.Height);

                                            previousImageBrush.TileMode = TileMode.None;
                                            previousImageBrush.Stretch = Stretch.Fill;
                                            previousImageBrush.ViewboxUnits = BrushMappingMode.Absolute;
                                            previousImageBrush.Viewbox = new Rect(this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? (this.cachedBitmapImage.Width - this.cachedBitmapImage.Height) / 2 - (this.cachedBitmapImage.Width - this.cachedBitmapImage.Height) / 2 * step : 0, this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? 0 : (this.cachedBitmapImage.Height - this.cachedBitmapImage.Width) / 2 - (this.cachedBitmapImage.Height - this.cachedBitmapImage.Width) / 2 * step, this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? this.cachedBitmapImage.Height + (this.cachedBitmapImage.Width - this.cachedBitmapImage.Height) * step : this.cachedBitmapImage.Width, this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? this.cachedBitmapImage.Height : this.cachedBitmapImage.Width + (this.cachedBitmapImage.Height - this.cachedBitmapImage.Width) * step);
                                            previousImageBrush.AlignmentX = AlignmentX.Left;
                                            previousImageBrush.AlignmentY = AlignmentY.Top;

                                            dc.PushGuidelineSet(gs1);
                                            dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, popupImageRect.Width, popupImageRect.Height));
                                            dc.DrawRectangle(previousImageBrush, null, new Rect(0, 0, popupImageRect.Width, popupImageRect.Height));
                                            dc.DrawRectangle(null, pen, new Rect(thickness / 2, thickness / 2, popupImageRect.Width - thickness, popupImageRect.Height - thickness));
                                            dc.Close();

                                            gs2.GuidelinesX.Add(dg.Bounds.X);
                                            gs2.GuidelinesX.Add(dg.Bounds.X + Math.Ceiling(dg.Bounds.Width));
                                            gs2.GuidelinesY.Add(dg.Bounds.Y);
                                            gs2.GuidelinesY.Add(dg.Bounds.Y + Math.Ceiling(dg.Bounds.Height));

                                            dg.GuidelineSet = gs2;
                                            dg.Children.Add(new GeometryDrawing(Brushes.Transparent, null, new RectangleGeometry(new Rect(dg.Bounds.X, dg.Bounds.Y, Math.Ceiling(dg.Bounds.Width), Math.Ceiling(dg.Bounds.Height)))));

                                            DrawingImage di = new DrawingImage(dg);

                                            if (di.CanFreeze)
                                            {
                                                di.Freeze();
                                            }

                                            this.InspectorImage.Source = di;
                                            this.InspectorImage.Width = Math.Ceiling(dg.Bounds.Width);
                                            this.InspectorImage.Height = Math.Ceiling(dg.Bounds.Height);

                                            Canvas.SetLeft(this.InspectorImage, popupImageRect.X);
                                            Canvas.SetTop(this.InspectorImage, popupImageRect.Y);
                                        }
                                        else
                                        {
                                            double thickness = 1;
                                            Pen pen = new Pen();
                                            DrawingGroup dg = new DrawingGroup();
                                            DrawingContext dc = dg.Open();
                                            GeometryGroup gg = new GeometryGroup();
                                            GuidelineSet gs = new GuidelineSet();
                                            GuidelineSet gs2 = new GuidelineSet();

                                            pen.Thickness = thickness;

                                            if (this.imageBlinkStep > 0)
                                            {
                                                Color color = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;

                                                pen.Brush = new SolidColorBrush(Color.FromArgb((byte)(color.A + (this.linkColor.A - color.A) * Math.Sin(this.imageBlinkStep * Math.PI)), (byte)(color.R + (this.linkColor.R - color.R) * Math.Sin(this.imageBlinkStep * Math.PI)), (byte)(color.G + (this.linkColor.G - color.G) * Math.Sin(this.imageBlinkStep * Math.PI)), (byte)(color.B + (this.linkColor.B - color.B) * Math.Sin(this.imageBlinkStep * Math.PI))));
                                            }
                                            else
                                            {
                                                pen.Brush = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White;
                                            }

                                            gs.GuidelinesX.Add(0);
                                            gs.GuidelinesX.Add(imageSize.Width);
                                            gs.GuidelinesY.Add(0);
                                            gs.GuidelinesY.Add(imageSize.Height);

                                            dc.PushGuidelineSet(gs);

                                            if (this.imageUri == null)
                                            {
                                                if (this.cachedBitmapImage == null)
                                                {
                                                    dc.PushTransform(new TranslateTransform(-this.imageLoadStep * 20, 0));
                                                    dc.PushClip(new RectangleGeometry(new Rect(this.imageLoadStep * 20, 0, imageSize.Width, imageSize.Height)));
                                                    dc.DrawRectangle(CreateStripeBrush(new SolidColorBrush(Color.FromArgb((byte)(Colors.Black.A * 10 / 100), Colors.Black.R, Colors.Black.G, Colors.Black.B)), new Size(20, 20)), null, new Rect(0, 0, imageSize.Width + 20, imageSize.Height));
                                                    dc.Pop();
                                                    dc.Pop();
                                                }
                                                else
                                                {
                                                    ImageBrush imageBrush = new ImageBrush(this.cachedBitmapImage);

                                                    imageBrush.TileMode = TileMode.None;
                                                    imageBrush.Stretch = Stretch.Fill;
                                                    imageBrush.ViewboxUnits = BrushMappingMode.Absolute;
                                                    imageBrush.Viewbox = new Rect(this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? (this.cachedBitmapImage.Width - this.cachedBitmapImage.Height) / 2 : 0, this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? 0 : (this.cachedBitmapImage.Height - this.cachedBitmapImage.Width) / 2, this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? this.cachedBitmapImage.Height : this.cachedBitmapImage.Width, this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? this.cachedBitmapImage.Height : this.cachedBitmapImage.Width);
                                                    imageBrush.AlignmentX = AlignmentX.Left;
                                                    imageBrush.AlignmentY = AlignmentY.Top;

                                                    dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, imageSize.Width, imageSize.Height));
                                                    dc.DrawRectangle(imageBrush, null, new Rect(0, 0, imageSize.Width, imageSize.Height));
                                                }
                                            }
                                            else
                                            {
                                                BitmapImage bi;

                                                if (this.imageDictionary.TryGetValue(this.imageUri, out bi))
                                                {
                                                    if (bi == this.cachedBitmapImage && bi != null)
                                                    {
                                                        ImageBrush imageBrush = new ImageBrush(bi);

                                                        imageBrush.TileMode = TileMode.None;
                                                        imageBrush.Stretch = Stretch.Fill;
                                                        imageBrush.ViewboxUnits = BrushMappingMode.Absolute;
                                                        imageBrush.Viewbox = new Rect(bi.Width > bi.Height ? (bi.Width - bi.Height) / 2 : 0, bi.Width > bi.Height ? 0 : (bi.Height - bi.Width) / 2, bi.Width > bi.Height ? bi.Height : bi.Width, bi.Width > bi.Height ? bi.Height : bi.Width);
                                                        imageBrush.AlignmentX = AlignmentX.Left;
                                                        imageBrush.AlignmentY = AlignmentY.Top;

                                                        dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, imageSize.Width, imageSize.Height));
                                                        dc.DrawRectangle(imageBrush, null, new Rect(0, 0, imageSize.Width, imageSize.Height));
                                                    }
                                                    else
                                                    {
                                                        if (this.cachedBitmapImage == null)
                                                        {
                                                            dc.PushTransform(new TranslateTransform(-this.imageLoadStep * 20, 0));
                                                            dc.PushClip(new RectangleGeometry(new Rect(this.imageLoadStep * 20, 0, imageSize.Width, imageSize.Height)));
                                                            dc.DrawRectangle(CreateStripeBrush(new SolidColorBrush(Color.FromArgb((byte)(Colors.Black.A * 10 / 100), Colors.Black.R, Colors.Black.G, Colors.Black.B)), new Size(20, 20)), null, new Rect(0, 0, imageSize.Width + 20, imageSize.Height));
                                                            dc.Pop();
                                                            dc.Pop();
                                                        }
                                                        else
                                                        {
                                                            ImageBrush imageBrush = new ImageBrush(this.cachedBitmapImage);

                                                            imageBrush.TileMode = TileMode.None;
                                                            imageBrush.Stretch = Stretch.Fill;
                                                            imageBrush.ViewboxUnits = BrushMappingMode.Absolute;
                                                            imageBrush.Viewbox = new Rect(this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? (this.cachedBitmapImage.Width - this.cachedBitmapImage.Height) / 2 : 0, this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? 0 : (this.cachedBitmapImage.Height - this.cachedBitmapImage.Width) / 2, this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? this.cachedBitmapImage.Height : this.cachedBitmapImage.Width, this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? this.cachedBitmapImage.Height : this.cachedBitmapImage.Width);
                                                            imageBrush.AlignmentX = AlignmentX.Left;
                                                            imageBrush.AlignmentY = AlignmentY.Top;

                                                            dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, imageSize.Width, imageSize.Height));
                                                            dc.DrawRectangle(imageBrush, null, new Rect(0, 0, imageSize.Width, imageSize.Height));
                                                        }

                                                        if (bi != null)
                                                        {
                                                            double step = Math.Sin(this.imageSlideStep / 2 * Math.PI);
                                                            StreamGeometry streamGeometry = new StreamGeometry();

                                                            streamGeometry.FillRule = FillRule.Nonzero;

                                                            using (StreamGeometryContext streamGeometryContext = streamGeometry.Open())
                                                            {
                                                                streamGeometryContext.BeginFigure(new Point(0, 0), true, true);

                                                                if (step <= 0.5)
                                                                {
                                                                    streamGeometryContext.LineTo(new Point(imageSize.Width * step / 0.5, 0), true, false);
                                                                    streamGeometryContext.LineTo(new Point(0, imageSize.Height * step / 0.5), true, false);
                                                                }
                                                                else
                                                                {
                                                                    streamGeometryContext.LineTo(new Point(imageSize.Width, 0), true, false);
                                                                    streamGeometryContext.LineTo(new Point(imageSize.Width, imageSize.Height * (step - 0.5) / 0.5), true, false);
                                                                    streamGeometryContext.LineTo(new Point(imageSize.Width * (step - 0.5) / 0.5, imageSize.Height), true, false);
                                                                    streamGeometryContext.LineTo(new Point(0, imageSize.Height), true, false);
                                                                }
                                                            }

                                                            ImageBrush imageBrush = new ImageBrush(bi);

                                                            imageBrush.TileMode = TileMode.None;
                                                            imageBrush.Stretch = Stretch.Fill;
                                                            imageBrush.ViewboxUnits = BrushMappingMode.Absolute;
                                                            imageBrush.Viewbox = new Rect(bi.Width > bi.Height ? (bi.Width - bi.Height) / 2 : 0, bi.Width > bi.Height ? 0 : (bi.Height - bi.Width) / 2, bi.Width > bi.Height ? bi.Height : bi.Width, bi.Width > bi.Height ? bi.Height : bi.Width);
                                                            imageBrush.AlignmentX = AlignmentX.Left;
                                                            imageBrush.AlignmentY = AlignmentY.Top;

                                                            dc.PushClip(streamGeometry);
                                                            dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, imageSize.Width, imageSize.Height));
                                                            dc.DrawRectangle(imageBrush, null, new Rect(0, 0, imageSize.Width, imageSize.Height));
                                                            dc.Pop();
                                                        }
                                                    }
                                                }
                                                else if (this.cachedBitmapImage == null)
                                                {
                                                    dc.PushTransform(new TranslateTransform(-this.imageLoadStep * 20, 0));
                                                    dc.PushClip(new RectangleGeometry(new Rect(this.imageLoadStep * 20, 0, imageSize.Width, imageSize.Height)));
                                                    dc.DrawRectangle(CreateStripeBrush(new SolidColorBrush(Color.FromArgb((byte)(Colors.Black.A * 10 / 100), Colors.Black.R, Colors.Black.G, Colors.Black.B)), new Size(20, 20)), null, new Rect(0, 0, imageSize.Width + 20, imageSize.Height));
                                                    dc.Pop();
                                                    dc.Pop();
                                                }
                                                else
                                                {
                                                    ImageBrush imageBrush = new ImageBrush(this.cachedBitmapImage);

                                                    imageBrush.TileMode = TileMode.None;
                                                    imageBrush.Stretch = Stretch.Fill;
                                                    imageBrush.ViewboxUnits = BrushMappingMode.Absolute;
                                                    imageBrush.Viewbox = new Rect(this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? (this.cachedBitmapImage.Width - this.cachedBitmapImage.Height) / 2 : 0, this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? 0 : (this.cachedBitmapImage.Height - this.cachedBitmapImage.Width) / 2, this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? this.cachedBitmapImage.Height : this.cachedBitmapImage.Width, this.cachedBitmapImage.Width > this.cachedBitmapImage.Height ? this.cachedBitmapImage.Height : this.cachedBitmapImage.Width);
                                                    imageBrush.AlignmentX = AlignmentX.Left;
                                                    imageBrush.AlignmentY = AlignmentY.Top;

                                                    dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, imageSize.Width, imageSize.Height));
                                                    dc.DrawRectangle(imageBrush, null, new Rect(0, 0, imageSize.Width, imageSize.Height));
                                                }
                                            }

                                            dc.DrawRectangle(null, pen, new Rect(thickness / 2, thickness / 2, imageSize.Width - thickness, imageSize.Height - thickness));
                                            dc.Close();

                                            gs2.GuidelinesX.Add(dg.Bounds.X);
                                            gs2.GuidelinesX.Add(dg.Bounds.X + Math.Ceiling(dg.Bounds.Width));
                                            gs2.GuidelinesY.Add(dg.Bounds.Y);
                                            gs2.GuidelinesY.Add(dg.Bounds.Y + Math.Ceiling(dg.Bounds.Height));

                                            dg.GuidelineSet = gs2;
                                            dg.Children.Add(new GeometryDrawing(Brushes.Transparent, null, new RectangleGeometry(new Rect(dg.Bounds.X, dg.Bounds.Y, Math.Ceiling(dg.Bounds.Width), Math.Ceiling(dg.Bounds.Height)))));

                                            DrawingImage di = new DrawingImage(dg);

                                            if (di.CanFreeze)
                                            {
                                                di.Freeze();
                                            }

                                            this.InspectorImage.Source = di;
                                            this.InspectorImage.Width = Math.Ceiling(dg.Bounds.Width);
                                            this.InspectorImage.Height = Math.Ceiling(dg.Bounds.Height);

                                            Canvas.SetLeft(this.InspectorImage, Canvas.GetLeft(this.InspectorCanvas) + 8);
                                            Canvas.SetTop(this.InspectorImage, Canvas.GetTop(this.InspectorCanvas));
                                        }
                                    }
                                }

                                if (isReady && this.nextHistoryPoint.HasValue && this.inlineList.Count == 0 && this.messageBuffer.Length == 0 && this.randomMessageLength == 0 && this.attachmentFadeStepDictionary.Values.All(step => step == 0) && this.filterStep == null && this.scrollStep == null && this.liftStep == null && this.counterScrollStep == null && this.inspectorEntry == null)
                                {
                                    this.isReady = false;
                                    this.hoverEmbeddedIndex = null;
                                    this.enableFilter = false;
                                    this.minScore = 0;
                                    this.maxScore = 0;
                                    this.thresholdQueue.Clear();
                                    this.thresholdScore = 0;
                                    this.previousThresholdScore = 0;
                                    this.nextThresholdScore = 0;
                                    this.thresholdScoreStep = 0;
                                    this.isReversed = false;
                                    this.scrollQueue.Clear();
                                    this.selectedPositionQueue.Clear();
                                    this.sourceScrollPosition = this.targetScrollPosition = 0;
                                    this.scrollIndexStep = 0;
                                    this.hoverIndex = null;
                                    this.selectedIndex = null;
                                    this.selectedPosition = null;
                                    this.embedColorStepDictionary.Clear();
                                    this.embedScrollStepDictionary.Clear();
                                    this.embedIsScrollableHashSet.Clear();
                                    this.attachmentFadeStepDictionary.Clear();
                                    this.attachmentImageLoadingStepDictionary.Clear();
                                    this.attachmentImageSlideStepDictionary.Clear();
                                    this.attachmentImagePopupStepDictionary.Clear();
                                    this.attachmentHighlightStepDictionary.Clear();
                                    this.attachmentEnableStepDictionary.Clear();
                                    this.attachmentFilterStepDictionary.Clear();
                                    this.attachmentScrollStepDictionary.Clear();
                                    this.attachmentIsScrollableHashSet.Clear();
                                    this.attachmentImageDictionary.Clear();
                                    this.cachedInlineImageDictionary.Clear();
                                    this.cachedAttachmentThumbnailImageDictionary.Clear();
                                    this.cachedAttachmentTextImageDictionary.Clear();
                                    this.imageDictionary.Clear();
                                    this.imageUriHashSet.Clear();
                                    this.TranslateTransform.X = this.TranslateTransform.Y = 0;
                                    this.ScrollCanvas.Width = this.ScrollCanvas.Height = Double.NaN;
                                    this.MessageCanvas.Width = this.MessageCanvas.Height = Double.NaN;
                                    this.waitTimer.Stop();
                                    this.messageTypeTimer.Stop();
                                }

                                if (waitRequired && !this.isPinned && this.targetOpacity > 0 && this.targetScaleX > 0 && this.targetScaleY > 0 && !this.waitTimer.IsEnabled)
                                {
                                    this.waitTimer.Interval = this.messageCollection[this.historyPoint.Value].Duration;
                                    this.waitTimer.Start();
                                }
                            }
                            else if (!this.isPinned && this.targetOpacity > 0 && this.targetScaleX > 0 && this.targetScaleY > 0 && !this.waitTimer.IsEnabled)
                            {
                                this.waitTimer.Interval = TimeSpan.Zero;
                                this.waitTimer.Start();
                            }
                        }

                        if (this.targetSize.Width != this.Canvas.Width || this.targetSize.Height != this.Canvas.Height)
                        {
                            Size newClientSize = new Size(this.Canvas.Width, this.Canvas.Height);

                            this.resizeStep += 1 / (averageFrameRate / 4);

                            if (this.resizeStep >= 1)
                            {
                                this.resizeStep = 1;

                                if (newClientSize.Width != this.targetSize.Width || newClientSize.Height != this.targetSize.Height)
                                {
                                    newClientSize = this.targetSize;
                                }
                            }
                            else
                            {
                                double step = Math.Sin(this.resizeStep / 2 * Math.PI);

                                newClientSize.Width = this.sourceSize.Width + Math.Ceiling((this.targetSize.Width - this.sourceSize.Width) * step);
                                newClientSize.Height = this.sourceSize.Height + Math.Ceiling((this.targetSize.Height - this.sourceSize.Height) * step);
                            }

                            Geometry roundedRectangleGeometry = CreateRoundedRectangleGeometry(new Rect(0, 0, newClientSize.Width, newClientSize.Height - 11 + 4), 8, 8);
                            Geometry balloonGeometry = CreateBalloonGeometry(new Rect(4, 4, newClientSize.Width - 4 * 2, newClientSize.Height - 4), 8 * 3 / 4, 8 * 3 / 4);
                            Geometry highlightGeometry = CreateHighlightGeometry(new Rect(0, 0, newClientSize.Width, this.baseHeaderHeight + 8), 8, 8);
                            Geometry highlightLineGeometry = CreateHighlightLineGeometry(new Rect(0, 0, newClientSize.Width, 8), 8, 8);

                            if (roundedRectangleGeometry.CanFreeze)
                            {
                                roundedRectangleGeometry.Freeze();
                            }

                            if (balloonGeometry.CanFreeze)
                            {
                                balloonGeometry.Freeze();
                            }

                            if (highlightGeometry.CanFreeze)
                            {
                                highlightGeometry.Freeze();
                            }

                            if (highlightLineGeometry.CanFreeze)
                            {
                                highlightLineGeometry.Freeze();
                            }

                            GeometryGroup geometryGroup = new GeometryGroup();

                            geometryGroup.FillRule = FillRule.Nonzero;
                            geometryGroup.Children.Add(roundedRectangleGeometry);
                            geometryGroup.Children.Add(balloonGeometry);

                            if (geometryGroup.CanFreeze)
                            {
                                geometryGroup.Freeze();
                            }

                            RadialGradientBrush radialGradientBrush = new RadialGradientBrush();
                            GradientStop gradientStop1 = new GradientStop(Color.FromArgb(Byte.MaxValue, Byte.MaxValue, Byte.MaxValue, Byte.MaxValue), 0);
                            GradientStop gradientStop2 = new GradientStop(Color.FromArgb(Byte.MaxValue, 0, 0, 0), 1);

                            radialGradientBrush.GradientOrigin = new Point(0.5, 0);
                            radialGradientBrush.Center = new Point(0.5, 0);
                            radialGradientBrush.RadiusX = 0.5;
                            radialGradientBrush.RadiusY = this.sourceSize.Width / 2 < this.sourceSize.Height - this.baseFooterHeight ? this.sourceSize.Width / 2 / this.sourceSize.Height : (this.sourceSize.Height - this.baseFooterHeight) / this.sourceSize.Height;
                            radialGradientBrush.Opacity = 0.1;
                            radialGradientBrush.GradientStops.Add(gradientStop1);
                            radialGradientBrush.GradientStops.Add(gradientStop2);

                            if (radialGradientBrush.CanFreeze)
                            {
                                radialGradientBrush.Freeze();
                            }

                            this.OuterPath.Width = roundedRectangleGeometry.Bounds.Right;
                            this.OuterPath.Height = roundedRectangleGeometry.Bounds.Bottom;
                            this.OuterPath.Data = roundedRectangleGeometry;
                            this.InnerPath.Width = balloonGeometry.Bounds.Right;
                            this.InnerPath.Height = balloonGeometry.Bounds.Bottom;
                            this.InnerPath.Data = balloonGeometry;
                            this.OverlayPath.Width = geometryGroup.Bounds.Right;
                            this.OverlayPath.Height = geometryGroup.Bounds.Bottom;
                            this.OverlayPath.Data = geometryGroup;
                            this.OverlayPath.Fill = radialGradientBrush;
                            this.HighlightPath.Width = highlightGeometry.Bounds.Right;
                            this.HighlightPath.Height = highlightGeometry.Bounds.Bottom;
                            this.HighlightPath.Data = highlightGeometry;
                            this.HighlightLinePath.Width = highlightLineGeometry.Bounds.Right;
                            this.HighlightLinePath.Height = highlightLineGeometry.Bounds.Bottom;
                            this.HighlightLinePath.Data = highlightLineGeometry;
                            this.Canvas.Width = newClientSize.Width;
                            this.Canvas.Height = newClientSize.Height;
                            this.ScaleTransform.CenterX = newClientSize.Width / 2;
                            this.ScaleTransform.CenterY = newClientSize.Height;

                            Canvas.SetLeft(this.Canvas, (this.LayoutRoot.Width - newClientSize.Width) / 2);
                            Canvas.SetTop(this.Canvas, this.LayoutRoot.Height - newClientSize.Height);
                            Canvas.SetLeft(this.FilterImage, newClientSize.Width - 14);
                            Canvas.SetLeft(this.ScrollImage, newClientSize.Width - 14);
                            Canvas.SetLeft(this.CloseImage, newClientSize.Width - 17);
                            Canvas.SetLeft(this.BackImage, newClientSize.Width - 30);
                            Canvas.SetLeft(this.UpImage, newClientSize.Width - 17);
                            Canvas.SetTop(this.UpImage, newClientSize.Height - 32);
                            Canvas.SetLeft(this.DownImage, newClientSize.Width - 17);
                            Canvas.SetTop(this.DownImage, newClientSize.Height - 21);
                        }

                        if (this.backIsHover || this.backBlinkStep > 0 || this.BackImage.Source == null)
                        {
                            Pen pen = new Pen();

                            if (this.backIsHover || this.backBlinkStep > 0)
                            {
                                this.backBlinkStep += 1 / (averageFrameRate / 2);

                                if (this.backBlinkStep >= 1)
                                {
                                    this.backBlinkStep = 0;
                                    pen.Brush = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White;
                                }
                                else
                                {
                                    Color color = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;

                                    pen.Brush = new SolidColorBrush(Color.FromArgb((byte)(color.A + (this.linkColor.A - color.A) * Math.Sin(this.backBlinkStep * Math.PI)), (byte)(color.R + (this.linkColor.R - color.R) * Math.Sin(this.backBlinkStep * Math.PI)), (byte)(color.G + (this.linkColor.G - color.G) * Math.Sin(this.backBlinkStep * Math.PI)), (byte)(color.B + (this.linkColor.B - color.B) * Math.Sin(this.backBlinkStep * Math.PI))));
                                }
                            }
                            else
                            {
                                pen.Brush = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White;
                            }

                            pen.Thickness = 2;
                            pen.StartLineCap = PenLineCap.Square;
                            pen.EndLineCap = PenLineCap.Square;

                            DrawingGroup backDrawingGroup = new DrawingGroup();
                            GuidelineSet backGuidelineSet = new GuidelineSet();

                            backDrawingGroup.Children.Add(new GeometryDrawing(null, pen, CreateBackGeometry(new Rect(0, 0, 6, 7))));

                            backGuidelineSet.GuidelinesX.Add(backDrawingGroup.Bounds.X);
                            backGuidelineSet.GuidelinesX.Add(backDrawingGroup.Bounds.X + Math.Ceiling(backDrawingGroup.Bounds.Width));
                            backGuidelineSet.GuidelinesY.Add(backDrawingGroup.Bounds.Y);
                            backGuidelineSet.GuidelinesY.Add(backDrawingGroup.Bounds.Y + Math.Ceiling(backDrawingGroup.Bounds.Height));

                            backDrawingGroup.GuidelineSet = backGuidelineSet;
                            backDrawingGroup.Children.Add(new GeometryDrawing(Brushes.Transparent, null, new RectangleGeometry(new Rect(backDrawingGroup.Bounds.X, backDrawingGroup.Bounds.Y, Math.Ceiling(backDrawingGroup.Bounds.Width), Math.Ceiling(backDrawingGroup.Bounds.Height)))));

                            DrawingImage backDrawingImage = new DrawingImage(backDrawingGroup);

                            if (backDrawingImage.CanFreeze)
                            {
                                backDrawingImage.Freeze();
                            }

                            this.BackImage.Source = backDrawingImage;
                            this.BackImage.Width = Math.Ceiling(backDrawingGroup.Bounds.Width);
                            this.BackImage.Height = Math.Ceiling(backDrawingGroup.Bounds.Height);
                        }

                        if (this.closeIsHover || this.closeBlinkStep > 0 || this.CloseImage.Source == null)
                        {
                            Pen pen = new Pen();

                            if (this.closeIsHover || this.closeBlinkStep > 0)
                            {
                                this.closeBlinkStep += 1 / (averageFrameRate / 2);

                                if (this.closeBlinkStep >= 1)
                                {
                                    this.closeBlinkStep = 0;
                                    pen.Brush = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White;
                                }
                                else
                                {
                                    Color color1 = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Colors.Black : Colors.White;
                                    Color color2 = Color.FromArgb(Byte.MaxValue, 204, 0, 0);

                                    pen.Brush = new SolidColorBrush(Color.FromArgb(Byte.MaxValue, (byte)(color1.R + (color2.R - color1.R) * Math.Sin(this.closeBlinkStep * Math.PI)), (byte)(color1.G + (color2.G - color1.G) * Math.Sin(this.closeBlinkStep * Math.PI)), (byte)(color1.B + (color2.B - color1.B) * Math.Sin(this.closeBlinkStep * Math.PI))));
                                }
                            }
                            else
                            {
                                pen.Brush = Math.Max(Math.Max(this.backgroundColor.R, this.backgroundColor.G), this.backgroundColor.B) > Byte.MaxValue / 2 ? Brushes.Black : Brushes.White;
                            }

                            pen.Thickness = 2;
                            pen.StartLineCap = PenLineCap.Square;
                            pen.EndLineCap = PenLineCap.Square;

                            DrawingGroup closeDrawingGroup = new DrawingGroup();
                            GuidelineSet closeGuidelineSet = new GuidelineSet();

                            closeDrawingGroup.Children.Add(new GeometryDrawing(null, pen, CreateCloseGeometry(new Rect(0, 0, 6, 6))));

                            closeGuidelineSet.GuidelinesX.Add(closeDrawingGroup.Bounds.X);
                            closeGuidelineSet.GuidelinesX.Add(closeDrawingGroup.Bounds.X + Math.Ceiling(closeDrawingGroup.Bounds.Width));
                            closeGuidelineSet.GuidelinesY.Add(closeDrawingGroup.Bounds.Y);
                            closeGuidelineSet.GuidelinesY.Add(closeDrawingGroup.Bounds.Y + Math.Ceiling(closeDrawingGroup.Bounds.Height));

                            closeDrawingGroup.GuidelineSet = closeGuidelineSet;
                            closeDrawingGroup.Children.Add(new GeometryDrawing(Brushes.Transparent, null, new RectangleGeometry(new Rect(closeDrawingGroup.Bounds.X, closeDrawingGroup.Bounds.Y, Math.Ceiling(closeDrawingGroup.Bounds.Width), Math.Ceiling(closeDrawingGroup.Bounds.Height)))));

                            DrawingImage closeDrawingImage = new DrawingImage(closeDrawingGroup);

                            if (closeDrawingImage.CanFreeze)
                            {
                                closeDrawingImage.Freeze();
                            }

                            this.CloseImage.Source = closeDrawingImage;
                            this.CloseImage.Width = Math.Ceiling(closeDrawingGroup.Bounds.Width);
                            this.CloseImage.Height = Math.Ceiling(closeDrawingGroup.Bounds.Height);
                        }

                        if (this.Canvas.Opacity == 0 && this.Canvas.Opacity == this.targetOpacity)
                        {
                            Hide();
                        }
                    }
                }
            }
        }
Пример #12
0
        protected virtual Geometry GetDefiningGeometry()
        {
            bool isStartVisible = IsStartVisible;
            bool isEndVisible = IsEndVisible;

            double radius = Radius;
            double thickness = GetThickness();

            double sx = X1;
            double sy = Y1;
            double ex = X2;
            double ey = Y2;

            double zet = LineUtil.Zet(sx, sy, ex, ey);
            double width = LineUtil.Width(radius, thickness, zet);
            double height = LineUtil.Height(radius, thickness, zet);

            bool shortenStart = GetShortenStart(this);
            bool shortenEnd = GetShortenEnd(this);
            bool isStartIO = GetStartIO();
            bool isEndIO = GetEndIO();

            // shorten start
            if (isStartIO == true && isEndIO == false && shortenStart == true)
            {
                if (Math.Round(sy, 1) == Math.Round(ey, 1))
                    sx = ex - ShortenLineSize;
            }

            // shorten end
            if (isStartIO == false && isEndIO == true && shortenEnd == true)
            {
                if (Math.Round(sy, 1) == Math.Round(ey, 1))
                    ex = sx + ShortenLineSize;
            }

            // get ellipse position
            IPoint ellipseStart = LineUtil.EllipseStart(sx, sy, width, height, isStartVisible);
            IPoint ellipseEnd = LineUtil.EllipseEnd(ex, ey, width, height, isEndVisible);

            // get line position
            IPoint lineStart = LineUtil.LineStart(sx, sy, width, height, isStartVisible);
            IPoint lineEnd = LineUtil.LineEnd(ex, ey, width, height, isEndVisible);

            var g = new GeometryGroup() { FillRule = FillRule.Nonzero };

            if (isStartVisible == true)
            {
                var startEllipse = new EllipseGeometry(
                    new Point(ellipseStart.X, ellipseStart.Y),
                    radius, radius);

                g.Children.Add(startEllipse);
            }

            if (isEndVisible == true)
            {
                var endEllipse = new EllipseGeometry(
                    new Point(ellipseEnd.X, ellipseEnd.Y),
                    radius, radius);

                g.Children.Add(endEllipse);
            }

            var line = new LineGeometry(
                new Point(lineStart.X, lineStart.Y),
                new Point(lineEnd.X, lineEnd.Y));

            g.Children.Add(line);

            g.Freeze();
            return g;
        }