Ejemplo n.º 1
0
        private PdfSourceRect GetSourceRect(PdfSourceRect rectOnPage, PdfSourceRect pageRect,
                                            PdfViewerController.Viewport viewport)
        {
            PdfSourceRect pageSubRect;

            if (rectOnPage == null)
            {
                pageSubRect = pageRect;
            }
            else
            {
                pageSubRect = rectOnPage.Clone();
                pageSubRect.Offset(pageRect.dX,
                                   pageRect
                                   .dY); //yes we have to translate forth and back to ensure that viewport clipping is always done in the exact same manner (rounding errors!)
            }
            PdfSourceRect sourceRect =
                pageSubRect.intersectDouble(viewport.Rectangle.GetSourceRect(viewport.ZoomFactor));

            // translate sourcePdfRect, to be relative to page instead of relative to the canvas
            sourceRect.Offset(-pageRect.dX, -pageRect.dY);
            // translate origin from top/left to bottom/left
            sourceRect.dY = pageRect.dHeight - sourceRect.dBottom;
            return(sourceRect);
        }
Ejemplo n.º 2
0
        private PdfSourceRect GetSourceFromTargetRect(PdfTargetRect targetRect, PdfSourceRect pageRect,
                                                      PdfViewerController.Viewport viewport)
        {
            PdfTargetRect targetClone = targetRect.Clone();

            targetClone.Offset(viewport.Rectangle.iX, viewport.Rectangle.iY);
            PdfSourceRect sourceRect = targetClone.GetSourceRect(viewport.ZoomFactor);

            sourceRect.Offset(-pageRect.dX, -pageRect.dY);
            sourceRect.dY = pageRect.dHeight - sourceRect.dBottom;
            return(sourceRect);
        }
Ejemplo n.º 3
0
        // source and targetrects may be empty! (due to crops with pages etc.)
        public void Draw(WriteableBitmap bitmap, int rotation, IList <KeyValuePair <int, PdfSourceRect> > pageRectsDict,
                         PdfViewerController.Viewport viewport)
        {
            Logger.LogInfo("Drawing bitmap");
            if (!isOpen)
            {
                throw new PdfNoFileOpenedException();
            }

            IList <PdfSourceRect> sourceRects        = new List <PdfSourceRect>();
            IList <PdfTargetRect> targetRects        = new List <PdfTargetRect>();
            IList <int>           visiblePages       = new List <int>();
            IList <int>           pages              = new List <int>(); //The list of pagenumbers for each s/t rect that needs to be drawn
            IList <int>           newPages           = new List <int>(); //pages that are completely new drawn and nothing is reused
            IList <PdfSourceRect> pageRects          = new List <PdfSourceRect>();
            IList <PdfSourceRect> visibleRectOnPages = new List <PdfSourceRect>();

            reusedTargetRects = new List <PdfTargetRect>();

            foreach (KeyValuePair <int, PdfSourceRect> keyValuePair in pageRectsDict)
            {
                PdfSourceRect pageRect = keyValuePair.Value;
                int           page     = keyValuePair.Key;
                if (!visiblePages.Contains(page))
                {
                    visiblePages.Add(page);
                }
                // crop the page with viewport  //Note that the size of the resulting rectangle may vary depending on viewport/pageRect offsets, due to rounding issues
                //PdfSourceRect visibleRectOnPage = pageRect.intersectDouble(viewport.Rectangle.GetSourceRect(viewport.ZoomFactor));
                PdfTargetRect visibleTargetRect = pageRect.GetTargetRect(viewport.ZoomFactor)
                                                  .intersectInt(viewport.Rectangle);
                PdfSourceRect visibleRectOnPage = visibleTargetRect.GetSourceRect(viewport.ZoomFactor);
                visibleRectOnPage.Offset(-pageRect.dX, -pageRect.dY);
                bool insertedRectanglesToDraw = false;
                if (lastBitmap != null && lastRotation == rotation &&
                    Math.Abs(lastViewport.ZoomFactor / viewport.ZoomFactor - 1.0) < 0.01)
                {
                    insertedRectanglesToDraw = CalculateSourceTargetRects(bitmap, rotation, page, pageRect, pages,
                                                                          sourceRects, targetRects, visibleRectOnPage, viewport);
                }
                if (!insertedRectanglesToDraw)
                {
                    //i just have to do the same thing in here as calculateSourceTargetRects would do
                    PdfTargetRect targetRect = GetTargetRect(visibleRectOnPage, pageRect, viewport);
                    sourceRects.Add(GetSourceFromTargetRect(targetRect, pageRect, viewport));
                    targetRects.Add(targetRect);
                    pages.Add(page);
                    newPages.Add(page);
                }
                pageRects.Add(pageRect);
                visibleRectOnPages.Add(visibleRectOnPage);
            }

            int drewThisManyTimes = 0;

            //DebugLogger.Log("Started drawing of pages " + string.Join(",", pages.Select(i => i.ToString()).ToArray()));
            for (int i = 0; i < pages.Count; i++)
            {
                int           p = pages[i];
                PdfSourceRect s = sourceRects[i];
                PdfTargetRect t = targetRects[i];

                //The target may be so small, that we cant see it or it can be horizontally shifted out of the viewport
                if (t.IsEmpty)
                {
                    continue;
                }

                //draw the content of the sourcerectangle in the pdf to the targetRectangle on the viewer bitmap
                bitmap.Lock();

                Logger.LogInfo("Drawing page " + p + " targetRect=" + t.ToString());

                PdfViewerDraw(documentHandle, p, bitmap.PixelWidth, bitmap.PixelHeight, bitmap.BackBuffer, rotation,
                              t.iX, t.iY, t.iWidth, t.iHeight,
                              s.dX, s.dY, s.dWidth, s.dHeight, TPdfViewerModelPixelOrder.ePdfViewerModelPixelOrderBGRA);
                drewThisManyTimes++;
                Logger.LogInfo("Finished drawing page " + p);

                bitmap.AddDirtyRect(t.GetInt32Rect());
                bitmap.Unlock();
            }

            lastBitmap             = bitmap;
            lastVisiblePages       = visiblePages;
            lastPageRects          = pageRects;
            lastRotation           = rotation;
            lastViewport           = viewport;
            lastVisibleRectOnPages = visibleRectOnPages;
            //DebugLogger.Log("Finished drawing of pages " + string.Join(",", pages.Select(i => i.ToString()).ToArray()));
            //visualizeDraw(bitmap.Clone(), rotation, pages, sourceRects, targetRects, newPages);
            Logger.LogInfo("Drew bitmap using " + drewThisManyTimes + " native calls");
        }
Ejemplo n.º 4
0
        private void CalculateCanvas()
        {
            if (canvasDirty == TCanvasDirtyness.Clean)
            {
                return;
            }

            int start = 1, end = PageCount;

            //If we are in a mode which doesnt show all pages, we only need to go through the shown ones
            if (!PdfUtils.PageLayoutScrollingEnabled(PageLayoutMode))
            {
                switch (PdfUtils.HorizontalPagePosition(PageLayoutMode, PageNo))
                {
                case -1:
                {
                    start = PageNo;
                    end   = Math.Min(PageNo + 1, end);      //because PageNo + 1 doesn't necessarily exist in this case
                    break;
                }

                case 0:
                {
                    start = PageNo;
                    end   = PageNo;
                    break;
                }

                case 1:
                {
                    start = PageNo - 1;         //pageNo-1 always exists in this case
                    end   = PageNo;
                    break;
                }
                }
            }

            int           changedPage       = int.MaxValue;
            PdfSourceRect oldCanvasRect     = _canvasRect.Clone();
            bool          entireCanvasDirty = (canvasDirty == TCanvasDirtyness.CanvasDirty);

            canvasDirty = TCanvasDirtyness.Clean;
            if (entireCanvasDirty)
            {
                _canvasRect.dWidth = 0.0;
                _canvasRect.dX     = 0.0;
            }
            double offset                   = 0.0;
            int    page                     = entireCanvasDirty ? start : Math.Max(start, GetNextRelevantPage(start, end));

            for (; page <= end; page++)
            {
                PdfSourceRect rect = null;
                if (pagesToLoadExactly.Remove(page))
                {
                    Logger.LogInfo("page " + page + " was loaded exactly");
                    //load page exactly
                    rect = documentManager.GetPageRect(page);
                }
                else
                {
                    rect = documentManager.GetPageRectGuess(page);
                }
                int nPage;
                lock (newlyLoadedPagesLock)
                {
                    nPage = newlyLoadedPages.FirstOrDefault(number => number >= start && number <= end);
                }
                if (!entireCanvasDirty && nPage > 1 && nPage < page)
                {
                    //maybe the getting of pages has getted a page before this one (due to predictionAlgorithm). In this case, consider this page first
                    page = nPage;
                    rect = documentManager.GetPageRectGuess(page);
                }

                bool removed = false;
                lock (newlyLoadedPagesLock)
                {
                    removed = newlyLoadedPages.Remove(page);
                }
                if (removed || entireCanvasDirty)//If the page is newly loaded, calculate its position exactly. Also if the entire canvas is dirty, calculate always
                {
                    changedPage = Math.Min(changedPage, page);
                    //position the page newly, knowing that its the first time we know its exact size
                    switch (PdfUtils.HorizontalPagePosition(PageLayoutMode, page))
                    {
                    case 0:
                    {
                        //place 1 page
                        rect.dCenterX = 0.0;
                        rect.dY       = GetPreviousBottom(page, start, end) + _borderSize;
                        if (rect.dX - _borderSize < _canvasRect.dX)
                        {
                            _canvasRect.dWidth += _canvasRect.dX - (rect.dX - _borderSize);
                            _canvasRect.dX      = rect.dX - _borderSize;
                        }
                        if (rect.dRight + _borderSize > _canvasRect.dRight)
                        {
                            _canvasRect.dWidth += rect.dRight + _borderSize - _canvasRect.dRight;
                        }
                        offset = rect.dBottom + _borderSize - GetNextTop(page, start, end);
                        break;
                    }

                    case -1:
                    {
                        //place left page
                        rect.dRight = 0.0 - _borderSize / 2.0;
                        rect.dY     = Math.Max(GetPreviousBottom(page, start, end), GetPreviousBottom(page - 1, start, end)) + _borderSize;
                        if (rect.dX - _borderSize < _canvasRect.dX)
                        {
                            _canvasRect.dWidth += _canvasRect.dX - (rect.dX - _borderSize);
                            _canvasRect.dX      = rect.dX - _borderSize;
                        }
                        offset = rect.dY - GetNextTop(page, start, end);
                        break;
                    }

                    default:
                    {
                        //place right page
                        rect.dX = 0.0 + _borderSize / 2.0;
                        rect.dY = documentManager.GetPageRectGuess(page - 1).dY;
                        if (rect.dRight + _borderSize > _canvasRect.dRight)
                        {
                            _canvasRect.dWidth += rect.dRight + _borderSize - _canvasRect.dRight;
                        }
                        offset = Math.Max(GetPreviousBottom(page, start, end), rect.dBottom) + _borderSize - GetNextTop(page, start, end);
                        break;
                    }
                    }
                }
                else
                {
                    //Only pages that are not newly loaded make it here. Adjust their offset
                    if (offset == 0.0)
                    {
                        //if there is no offset, we dont need to do anything until we hit a page that needs to be loaded anew
                        page = GetNextRelevantPage(start, end);
                        if (page == int.MaxValue)
                        {
                            break;//there is no more page to load -> stop iterating through pages
                        }
                        page--;
                        continue;
                    }
                    rect.Offset(0.0, offset);
                }
            }//end for-loop
            //we have loaded and positioned all pages, now we only need to resize the canvas
            lock (newlyLoadedPagesLock)
            {
                if (newlyLoadedPages.Count == 0 && pagesToLoadExactly.Count == 0)
                {
                    canvasDirty = TCanvasDirtyness.Clean;
                }
            }
            if (PdfUtils.HorizontalPagePosition(PageLayoutMode, end) == -1)
            {
                offset = documentManager.GetPageRectGuess(end).dBottom + _borderSize - _canvasRect.dBottom;
            }
            if (offset != 0.0)
            {
                _canvasRect.dHeight += offset;
                CanvasRectChanged(oldCanvasRect, _canvasRect, changedPage);
            }
            return;
        }