Beispiel #1
0
 /// <summary>
 /// Extracts source from anchor.
 /// </summary>
 /// <param name="htmlNode"></param>
 /// <param name="element"></param>
 private static void ExtractHref(HtmlNode htmlNode, ref Elements.BaseElement element)
 {
     if (htmlNode.Attributes.Contains("href"))
     {
         ((Elements.Text)element).Href = htmlNode.Attributes["href"].Value;
     }
 }
Beispiel #2
0
        /// <summary>
        /// Extracts identifier from nodes (for table of contents linkng).
        /// </summary>
        /// <param name="htmlNode"></param>
        /// <param name="element"></param>
        private static void ExtractId(HtmlNode htmlNode, ref Elements.BaseElement element)
        {
            if (htmlNode.Attributes.Contains("id"))
            {
                element.Identifiers.Add(htmlNode.Attributes["id"].Value);
            }

            // we have to also extract id's from parents
            if (htmlNode.ParentNode != null)
            {
                ExtractId(htmlNode.ParentNode, ref element);
            }
        }
        private void Navigate(string src)
        {
            // extract href / id
            string itemHref, id;

            if (src.StartsWith("#", StringComparison.OrdinalIgnoreCase))
            {
                itemHref = String.Empty;
                id       = src.Substring(1);
            }
            else if (src.Contains('#'))
            {
                itemHref = src.Substring(0, src.IndexOf('#'));
                id       = src.Substring(src.IndexOf('#') + 1);
            }
            else
            {
                itemHref = src;
                id       = String.Empty;
            }

            // remove directiories from href
            itemHref = GetFileName(itemHref);

            // find location
            int loc = 0;

            for (int i = 0; i < Book.ItemElementsContainers.Count; i++)
            {
                ItemElementsContainer iec = Book.ItemElementsContainers[i];
                for (int j = 0; j < iec.Elements.Count; j++)
                {
                    Elements.BaseElement element = iec.Elements[j];
                    if (
                        (String.IsNullOrEmpty(itemHref) || GetFileName(iec.Item.Href).Equals(itemHref, StringComparison.OrdinalIgnoreCase))
                        &&
                        (String.IsNullOrEmpty(id) || (!String.IsNullOrEmpty(id) && element.Identifiers.Contains(id)))
                        )
                    {
                        // change state (from TOC view)
                        State = EPubReader.State.Normal;
                        // set location
                        CurrentLocation = loc + j;
                        // exit
                        return;
                    }
                }

                loc += iec.Elements.Count;
            }
        }
        /// <summary>
        /// Render item elements container
        /// </summary>
        /// <param name="iec"></param>
        internal void Render(ItemElementsContainer iec)
        {
#if DEBUG
            Stopwatch sw = new Stopwatch();
            sw.Start();
#endif
            int currentLocation = iec.StartLocation;

            Page   page = CreatePage(currentLocation);
            double top  = 0;

            for (int i = 0; i < iec.Elements.Count; i++)
            {
                Elements.BaseElement element = iec.Elements[i];

                if (element is Elements.Break)
                {
                    RenderBreak(iec, currentLocation, ref page, ref top);
                }
                else if (element is Elements.Image)
                {
                    RenderImage(iec, currentLocation, ref page, ref top, element);
                }
                else if (element is Elements.Line)
                {
                    RenderLine(iec, currentLocation, ref page, ref top);
                }
                else if (element is Elements.Text)
                {
                    RenderText(iec, currentLocation, ref page, ref top, element);
                }

                if (i < iec.Elements.Count - 1)
                {
                    currentLocation++;
                }
            }

            // we push page even doesnt have any content
            page.EndLocation = currentLocation;
            // add page to list
            iec.Pages.Add(page);

#if DEBUG
            sw.Stop();
            Debug.WriteLine(String.Format(CultureInfo.InvariantCulture, "Information: EPubReader.Renderer.Render(\"{1}\") - Executed in {0} ms", sw.ElapsedMilliseconds.ToString(CultureInfo.InvariantCulture), iec.Item.Href));
#endif
        }
        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;
            }
        }
        private void RenderImage(ItemElementsContainer iec, int currentLocation, ref Page page, ref double top, Elements.BaseElement element)
        {
            Elements.Image imageElement = (Elements.Image)element;

            // create UI element
            Image image = new Image();

            image.Tag = imageElement;

            Binding binding = new Binding("Tag");

            binding.RelativeSource     = new RelativeSource(RelativeSourceMode.Self);
            binding.Converter          = new Converters.IsolatedStorageFileToImageSourceConverter();
            binding.ConverterParameter = _ePubViewer.Book;
            BindingOperations.SetBinding(image, Image.SourceProperty, binding);

            // check size of image (it it's larger then entire space)
            if (imageElement.Width + image.Margin.Left + image.Margin.Right > page.Content.Width
                ||
                imageElement.Height + image.Margin.Top + image.Margin.Bottom > page.Content.Height)
            {
                // image bigger then size of control
                if (page.Content.Children.Count > 0)
                {
                    PushPage(iec, ref page, currentLocation, ref top);
                }

                // count new width / height
                double widthRatio  = (double)imageElement.Width / page.Content.Width;
                double heightRatio = (double)imageElement.Height / page.Content.Height;
                double ratio       = Math.Max(widthRatio, heightRatio);
                image.Width  = (int)((double)imageElement.Width / ratio);
                image.Height = (int)((double)imageElement.Height / ratio);

                image.Stretch = Stretch.Uniform;

                image.SetValue(Canvas.TopProperty, top);

                page.Content.Children.Add(image);
            }
            else
            {
                // image smaller then size of control

                // try fit current page
                if (top + imageElement.Height + image.Margin.Top + image.Margin.Bottom > page.Content.Height)
                {
                    PushPage(iec, ref page, currentLocation, ref top);
                }

                image.Width  = imageElement.Width;
                image.Height = imageElement.Height;

                image.Stretch = Stretch.None;

                image.SetValue(Canvas.TopProperty, top);

                page.Content.Children.Add(image);
            }

            top += image.Height + image.Margin.Top + image.Margin.Bottom;
        }