예제 #1
0
        private void RenderLine(ItemElementsContainer iec, int currentLocation, ref Page page, ref double top)
        {
            // check if line fits
            if (top + Elements.Line.Height + (2 * Elements.BaseElement.Margin) > page.Content.Height)
            {
                PushPage(iec, ref page, currentLocation, ref top);
            }

            Rectangle rectangle = new Rectangle();

            rectangle.Height = Elements.Line.Height;
            rectangle.Stroke = new SolidColorBrush(Colors.Red);

            Binding binding = new Binding("Foreground");

            binding.Source = _ePubViewer;
            BindingOperations.SetBinding(rectangle, Rectangle.FillProperty, binding);
            BindingOperations.SetBinding(rectangle, Rectangle.StrokeProperty, binding);

            top += Elements.BaseElement.Margin; // top margin

            rectangle.SetValue(Canvas.TopProperty, top);

            page.Content.Children.Add(rectangle);

            top += Elements.Line.Height + Elements.BaseElement.Margin; // height and bottom margin
        }
예제 #2
0
        private void ShowCurrentLocation()
        {
            if (_contentCanvas != null && Book != null && CurrentLocation > DefaultCurrentLocation)
            {
                // search for location within ItemElementsContainers
                for (int i = 0; i < Book.ItemElementsContainers.Count; i++)
                {
                    ItemElementsContainer iec = Book.ItemElementsContainers[i];
                    if (iec.StartLocation <= CurrentLocation && iec.EndLocation >= CurrentLocation)
                    {
                        if (iec.Pages.Count == 0)
                        {
                            ShowProgress();

                            ThreadPool.QueueUserWorkItem((object state) =>
                            {
                                Dispatcher.BeginInvoke(() =>
                                {
                                    _renderer.Render(iec);
                                    HideProgress();
                                    ShowCurrentPage(iec, i);
                                });
                            });

                            break;
                        }
                        else
                        {
                            ShowCurrentPage(iec, i);
                        }
                    }
                }
            }
        }
예제 #3
0
 private void PushPage(ItemElementsContainer iec, ref Page page, int location, ref double top)
 {
     // update end location on page
     page.EndLocation = location;
     // add page to list
     iec.Pages.Add(page);
     // create new page
     page = CreatePage(location + 1);
     // update top
     top = 0;
 }
예제 #4
0
        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;
            }
        }
예제 #5
0
        /// <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
        }
예제 #6
0
        private void ShowCurrentPage(ItemElementsContainer iec, int iecIndex)
        {
            // find page
            for (int i = 0; i < iec.Pages.Count; i++)
            {
                Page p = iec.Pages[i];
                if (p.StartLocation <= CurrentLocation && p.EndLocation >= CurrentLocation)
                {
                    _currentIecIndex  = iecIndex;
                    _currentPageIndex = i;

                    // fill content
                    _contentCanvas.Children.Clear();
                    _contentCanvas.Children.Add(p.Content);
                    // exit
                    return;
                }
            }
        }
예제 #7
0
        private void RenderBreak(ItemElementsContainer iec, int currentLocation, ref Page page, ref double top)
        {
            // don't add break at begining
            if (page.Content.Children.Count == 0)
            {
                return;
            }

            // measure
            if (top + _ePubViewer.LineHeight > page.Content.Height)
            {
                // push page and create new one
                PushPage(iec, ref page, currentLocation, ref top);
                //we don't render break at begging, so we can return now
            }
            else
            {
                TextBlock tb = ExtractTextBlock(ref page, top);
                tb.Inlines.Add(new LineBreak());

                top += _ePubViewer.LineHeight;
            }
        }
예제 #8
0
        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;
            }
        }
예제 #9
0
        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;
        }