/// <summary>
        /// Called before the System.Windows.UIElement.Tap event occurs.
        /// </summary>
        /// <param name="e">Event data for the event.</param>
        protected override void OnTap(GestureEventArgs e)
        {
            if (State != EPubReader.State.Normal)
            {
                return;
            }

            Point p = e.GetPosition(this);

            // check anchor rects
            if (_currentIecIndex > DefaultCurrentLocation && Book.ItemElementsContainers[_currentIecIndex].Pages.Count > 0)
            {
                AnchorRect anchorRect = Book.ItemElementsContainers[_currentIecIndex].Pages[_currentPageIndex].AnchorRects.Where(ar => ar.Rect.Contains(p)).FirstOrDefault();
                if (anchorRect != null)
                {
                    if (anchorRect.Href.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || anchorRect.Href.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
                    {
                        try
                        {
                            new WebBrowserTask()
                            {
                                Uri = new Uri(anchorRect.Href)
                            }.Show();
                        }
                        catch { }
                    }
                    else if (anchorRect.Href.StartsWith("mailto:", StringComparison.OrdinalIgnoreCase))
                    {
                        try
                        {
                            new EmailComposeTask()
                            {
                                To = anchorRect.Href.Substring(7) // substring "mailto:"
                            }.Show();
                        }
                        catch { }
                    }
                    else
                    {
                        Navigate(anchorRect.Href);
                    }

                    e.Handled = true;
                }
            }

            if (!e.Handled && p.X <= ActualWidth / 3 && CurrentLocation > 0)
            {
                // previous page
                PreviousPage();

                e.Handled = true;
            }
            else if (!e.Handled && p.X >= ActualWidth * 2 / 3 && CurrentLocation < FurthestLocation - 1)
            {
                // next page
                NextPage();

                e.Handled = true;
            }
            else
            {
                base.OnTap(e);
            }
        }
        private void RenderText(ItemElementsContainer iec, int currentLocation, ref Page page, ref double top, Elements.BaseElement element)
        {
            Elements.Text textElement = (Elements.Text)element;

            string value = "  " + textElement.Value;

            TextBlock tb = ExtractTextBlock(ref page, top);

            double prevTextBlockActualHeight = tb.ActualHeight;

            tb.Inlines.Add(CreateRun(textElement, value));
            double textBlockActualHeight = tb.ActualHeight - prevTextBlockActualHeight;

            // check if fits (in most cases it will pass, because of short paragraphs)
            if (top + textBlockActualHeight > page.Content.Height)
            {
                // remove inline
                tb.Inlines.RemoveAt(tb.Inlines.Count - 1);

                int      idx   = 1;
                string[] parts = value.Split(' ');

                while (true)
                {
                    string text = StringJoin(' ', parts, idx);
                    prevTextBlockActualHeight = tb.ActualHeight;
                    tb.Inlines.Add(CreateRun(textElement, text));
                    textBlockActualHeight = tb.ActualHeight - prevTextBlockActualHeight;
                    if (top + textBlockActualHeight > page.Content.Height)
                    {
                        // remove inline
                        tb.Inlines.RemoveAt(tb.Inlines.Count - 1);

                        // push prev text
                        // it could be empty if nothing fits
                        string prevText = null;
                        if (idx > 1)
                        {
                            prevText = StringJoin(' ', parts, idx - 1);

                            tb.Inlines.Add(CreateRun(textElement, prevText));
                        }

                        PushPage(iec, ref page, currentLocation, ref top);

                        // render rest of text
                        if (idx > 1)
                        {
                            textElement.Value = value.Substring(prevText.Length);
                        }
                        else
                        {
                            textElement.Value = value;
                        }

                        RenderText(iec, currentLocation, ref page, ref top, element);

                        break;
                    }
                    else
                    {
                        // remove inline
                        tb.Inlines.RemoveAt(tb.Inlines.Count - 1);
                    }

                    idx++;
                }
            }
            else
            {
                // create anchor rect if href isn't null
                if (!String.IsNullOrEmpty(textElement.Href))
                {
                    AnchorRect anchorRect = new AnchorRect();
                    anchorRect.Href = textElement.Href;
                    anchorRect.Rect = new Rect(
                        _ePubViewer.ContentMargin.Left,
                        (textBlockActualHeight == 0) ? top - _ePubViewer.LineHeight : top,
                        _ePubViewer.ContentSize.Width,
                        (textBlockActualHeight == 0) ? _ePubViewer.LineHeight : textBlockActualHeight);

                    page.AnchorRects.Add(anchorRect);
                }

                top += textBlockActualHeight;
            }
        }