Ejemplo n.º 1
0
        public PdfSourceRect GetUnionRectangleWithNeighbour(int pageNumber)
        {
            CalculateCanvas();
            PdfSourceRect pageRect = documentManager.GetPageRectGuess(pageNumber);
            PdfSourceRect pageRect2;

            if (PdfUtils.HorizontalPagePosition(PageLayoutMode, pageNumber) == 1)
            {
                pageRect2 = documentManager.GetPageRectGuess(pageNumber - 1);
                pageRect  = pageRect.unionDouble(pageRect2);
            }
            else if (PdfUtils.HorizontalPagePosition(PageLayoutMode, pageNumber) == -1 && pageNumber + 1 < PageCount)
            {
                //unify with right neighbour if it exists
                pageRect2 = documentManager.GetPageRectGuess(pageNumber + 1);
                pageRect  = pageRect.unionDouble(pageRect2);
            }
            else
            {
                pageRect = pageRect.Clone();
            }
            pageRect.dX      -= BorderSize;
            pageRect.dWidth  += 2.0 * BorderSize;
            pageRect.dY      -= BorderSize;
            pageRect.dHeight += 2.0 * BorderSize;

            return(pageRect);
        }
Ejemplo n.º 2
0
        public IList <PdfTextFragment> GetTextWithinRegion(PdfSourceRect markedRect, int firstPage, int lastPage)
        {
            IList <PdfTextFragment> containedFragments = new List <PdfTextFragment>();
            IList <int>             pageRange          = Enumerable.Range(firstPage, lastPage - firstPage + 1).ToList();

            //intersect the markedRect with the textFragments (transformed to canvas coordinates)
            foreach (int page in pageRange)
            {
                IList <PdfTextFragment> textFragments;
                try
                {
                    textFragments = documentManager.GetTextFragments(page);
                }
                catch (PdfRequestCanceledException)
                {
                    continue;
                }
                foreach (PdfTextFragment frag in textFragments)
                {
                    PdfSourceRect rectOnCanvas = frag.RectOnUnrotatedPage.CalculateRectOnCanvas(GetPageRect(page), Rotation);
                    if (markedRect.IsEmpty || rectOnCanvas.intersectsDouble(markedRect))
                    {
                        containedFragments.Add(frag);
                    }
                }
            }
            return(containedFragments);
        }
Ejemplo n.º 3
0
        public PdfSourceRect GetPageRect(int pageNumber)
        {
            CalculateCanvas();
            PdfSourceRect rect = documentManager.GetPageRectGuess(pageNumber);

            return(rect);
        }
Ejemplo n.º 4
0
 private void PageCacheParametrizationChanger(PdfSourceRect rect, PageCacheParams oldParam, PageCacheParams newParam)
 {
     if ((newParam.rotation - oldParam.rotation) % 180 != 0)
     {
         rect.RotateSize();
     }
 }
Ejemplo n.º 5
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.º 6
0
 private void PageCacheFirstLoadParametrizer(PdfSourceRect rect, PageCacheParams param)
 {
     if (param.rotation % 180 != 0)
     {
         rect.RotateSize();
     }
 }
Ejemplo n.º 7
0
        /// <summary>
        /// Draws the bounding boxes of all selected and moving annotations
        /// </summary>
        /// <param name="dc"></param>
        /// <param name="selectedAnnotationsPen"></param>
        /// <param name="movingAnnotationsPen"></param>
        private void OnRenderSelectedAnnotations(DrawingContext dc, Pen selectedAnnotationsPen, Pen movingAnnotationsPen)
        {
            foreach (PdfAnnotation annot in selectedAnnotations)
            {
                PdfSourceRect rectOnPage = new PdfSourceRect(annot.Rect[0], annot.Rect[1], annot.Rect[2] - annot.Rect[0], annot.Rect[3] - annot.Rect[1]);

                Rect rectWin = controller.TransformRectPageToViewportWinRect(rectOnPage, annot.PageNr);

                dc.DrawRectangle(null, selectedAnnotationsPen, rectWin);
            }

            if (movingAnnotations)
            {
                dc.DrawLine(movingAnnotationsPen, annotationPoints[0], lastMousePosition);

                double deltaX = lastMousePosition.X - annotationPoints[0].X;
                double deltaY = lastMousePosition.Y - annotationPoints[0].Y;

                foreach (PdfAnnotation annot in selectedAnnotations)
                {
                    PdfSourceRect rectOnPage = new PdfSourceRect(annot.Rect[0], annot.Rect[1], annot.Rect[2] - annot.Rect[0], annot.Rect[3] - annot.Rect[1]);

                    Rect rectWin = controller.TransformRectPageToViewportWinRect(rectOnPage, annot.PageNr);

                    rectWin.X += deltaX;
                    rectWin.Y += deltaY;

                    dc.DrawRectangle(null, movingAnnotationsPen, rectWin);
                }
            }
        }
Ejemplo n.º 8
0
        public PdfSourceRect GetPageRect(int pageNo)
        {
            if (!isOpen)
            {
                throw new PdfNoFileOpenedException();
            }
            Logger.LogInfo("Loading pageRectangle from source");
            double width      = 0;
            double height     = 0;
            IntPtr pageHandle = PdfViewerGetPageRect(documentHandle, pageNo, ref width, ref height);

            if (pageHandle.ToInt64() == 0)
            {
                throw new PdfViewerException(String.Format("Could not access page %i", pageNo));
            }
            PdfSourceRect rect     = new PdfSourceRect(0.0, 0.0, width, height);
            int           rotation = PdfViewerGetRotation(documentHandle, pageNo) + 360;

            if (rotation % 180 != 0)
            {
                rect.RotateSize();
            }

            Logger.LogInfo("Loaded pageRectangles from source");
            return(rect);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Checks whether the bounding rectangle of this annotation is intersected by a rectangle.
        /// If OnIntersect is false the markedRect has to completly contain the bounding rectangle.
        /// </summary>
        /// <param name="markedRect"></param>
        /// <param name="onIntersect"></param>
        /// <returns></returns>
        public bool ContainsOrIntersectsWithRect(PdfSourceRect markedRect, bool onIntersect)
        {
            PdfSourceRect annotRect = new PdfSourceRect(Rect[0], Rect[1], Rect[2] - Rect[0], Rect[3] - Rect[1]);

            if (onIntersect)
            {
                return(markedRect.intersectsDouble(annotRect));
            }
            return(markedRect.contains(annotRect));
        }
 public ThumbnailCacheArgs(bool loadPageRect, int rotation, PdfSourceRect sourceRect, int thumbnailWidth, int thumbnailHeight, int page, Resolution resolution)
 {
     this.loadPageRect    = loadPageRect;
     this.rotation        = rotation;
     this.sourceRect      = sourceRect;
     this.thumbnailWidth  = thumbnailWidth;
     this.thumbnailHeight = thumbnailHeight;
     this.page            = page;
     this.resolution      = resolution;
 }
Ejemplo n.º 11
0
 public PdfCanvas(IPdfControllerCallbackManager controller)
 {
     Rotation           = 0;
     _canvasRect        = new PdfSourceRect();
     documentManager    = new PdfDocumentManagerMultithreaded(controller);
     pagesToLoadExactly = new SortedSet <int>();
     newlyLoadedPages   = new SortedSet <int>();
     this.controller    = controller;
     controller.VisiblePageRangeChanged += OnVisiblePageRangeChanged;
     documentManager.PageRectLoaded     += OnPageLoaded;
 }
Ejemplo n.º 12
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.º 13
0
        /// <summary>
        /// Transforms the marked rectangle to page coordinates and reloads the annotations on this page
        /// </summary>
        /// <param name="rectOnCanvas"></param>
        private void HandleMarkedRectangleOnCanvas(PdfSourceRect rectOnCanvas)
        {
            if (MouseMode != TMouseMode.eMouseMarkMode)
            {
                return;
            }

            selectedRectOnPage = controller.TransformRectOnCanvasToOnPage(rectOnCanvas, out int pageNr);

            if (selectedRectOnPage != null && pageNr > 0)
            {
                controller.LoadAllAnnotationsOnPage(pageNr);
            }
        }
Ejemplo n.º 14
0
        //we ought to ensure, that the size of the resulting target rect is independent of the viewport offset
        //the problem is, that sometimes the rectOnPage is not entirely within the viewport and it thus gets cropped a bit by one of the viewports, yielding inconsistent size
        private PdfTargetRect GetTargetRect(PdfSourceRect rectOnPage, PdfSourceRect pageRect,
                                            PdfViewerController.Viewport viewport)
        {
            PdfSourceRect pageSubRect;

            if (rectOnPage == null)
            {
                pageSubRect = pageRect;
            }
            else
            {
                pageSubRect = rectOnPage.Clone();
                pageSubRect.Offset(pageRect.dX, pageRect.dY);
            }
            PdfTargetRect targetRect = pageSubRect.GetTargetRect(viewport.ZoomFactor);

            targetRect = targetRect.intersectInt(viewport.Rectangle);
            targetRect.Offset(-viewport.Rectangle.iX, -viewport.Rectangle.iY);
            //Subtract the offset of the viewportPdfRectangle on the Canvas. This way we get coordinats in relation to the viewport
            return(targetRect);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Updates the selected annotations with the provided annotation list
        /// </summary>
        /// <param name="annots"></param>
        private void OnAnnotationsChangedEventHandler(IList <PdfAnnotation> annots)
        {
            if (selectedRectOnPage != null)
            {
                IList <PdfAnnotation> markedAnnotations;

                if (selectedAnnotations != null && selectedAnnotations.Count > 0)
                {
                    //already annotations selected
                    markedAnnotations = annots?.Where(annot => selectedAnnotations.Any(selAnnot => selAnnot.GetHandleAsLong() == annot.GetHandleAsLong())).ToList();
                }
                else
                {
                    //no annotations selected
                    markedAnnotations = annots?.Where(annot => annot.ContainsOrIntersectsWithRect(selectedRectOnPage, AnnotationMarkingOnIntersect)).ToList <PdfAnnotation>();
                }

                if (markedAnnotations != null)
                {
                    if (markedAnnotations.Count > 0)
                    {
                        if (MouseMode == TMouseMode.eMouseMarkMode)
                        {
                            selectedAnnotations = markedAnnotations;
                        }
                        else
                        {
                            selectedRectOnPage = null;
                        }
                    }
                    else
                    {
                        selectedAnnotations.Clear();
                    }
                }
            }

            InvalidateVisual();
        }
Ejemplo n.º 16
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.º 17
0
 private PdfTargetRect GetTargetRect(PdfSourceRect pageRect, PdfViewerController.Viewport viewport)
 {
     return(GetTargetRect(null, pageRect, viewport));
 }
Ejemplo n.º 18
0
        private PdfTextFragment FindNearestTextFragment(PdfSourcePoint location, List <PdfTextFragment> haystack, PdfSourceRect pageRect)
        {
            /* To use This, you have to invert y axis of if-checks
             * int needle = haystack.Count / 2; //the fragment we currently look at
             * int start = 0;
             * int end = haystack.Count - 1;
             * while (true)
             * {
             *  PdfSourceRect rect = haystack[needle].RectOnUnrotatedPage;
             *
             *  if (location.dY < rect.dY)
             *      end = haystack.IndexOf(haystack[needle].LastOnLine);
             *  else if (location.dY > rect.dBottom)
             *      start = haystack.IndexOf(haystack[needle].FirstOnLine);
             *  else
             *  {
             *      start = haystack.IndexOf(haystack[needle].FirstOnLine);
             *      end = haystack.IndexOf(haystack[needle].LastOnLine);
             *      break;
             *  }
             *  int s = haystack.IndexOf(haystack[start].LastOnLine) + 1;
             *  int t = haystack.IndexOf(haystack[end].FirstOnLine) - 1;
             *  if (s > t)
             *      break;
             *  needle = (t - s) / 2 + s;
             * }
             * //there are only two ways to reach this:
             * // * haystack[needle] is on the correct line (and thus [start,end] interval describes this one line
             * // * [start,end] interval spans 2 lines or less
             * haystack = haystack.GetRange(start, end - start + 1);
             */
            //figure out the closest one
            double          minDist     = double.MaxValue;
            PdfTextFragment minDistFrag = null;

            foreach (PdfTextFragment frag in haystack)
            {
                double dist = frag.RectOnUnrotatedPage.ShortestDistanceSquared(location);
                if (dist < minDist)
                {
                    minDist     = dist;
                    minDistFrag = frag;
                }
            }
            return(minDistFrag);
        }
Ejemplo n.º 19
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;
        }
Ejemplo n.º 20
0
        public void Search(string toSearch, int startPage, int startIndex)
        {
            if (toSearch == null || toSearch.Length == 0)
            {
                SearchCompleted(null);
                return;
            }
            //Console.WriteLine(String.Format("Searching \"{0}\" on page {1} index {2}", toSearch, startPage, startIndex));
            bool repeatedSearch = String.Compare(lastSearchString, toSearch) == 0;

            lastSearchString = toSearch;
            if (repeatedSearch)
            {
                //offset the startindex to not get the same result again
                startIndex += previous ? -1 : 1;
            }
            else
            {
                if (!useRegex)
                {
                    toSearch = Regex.Replace(toSearch, "\\\\ ", " "); // make literal white space characters to whitespaces ("\ " to  " ")
                    toSearch = Regex.Escape(toSearch);                //escape regex literals ("." to "\.")
                }
                toSearch = Regex.Replace(toSearch, "\\\\ ", " ");     // make literal white space characters to whitespaces ("\ " to  " ")
                toSearch = Regex.Replace(toSearch, "\\s+", "\\s+");   //make any positive number of whitespaces match any other positive number of whitespaces (YES, this line DOES do something)
                RegexOptions regexOptions = RegexOptions.Singleline;
                if (!matchCase)
                {
                    regexOptions = regexOptions | RegexOptions.IgnoreCase;
                }
                regex      = new Regex(toSearch, regexOptions);
                startIndex = previous ? int.MaxValue : 0; //TODO later i will maybe want to start searching from specific location, instead from start of page

                matchesCache.Clear();
            }

            bool firstTime = true;//marks the first time we visit the startPage, if we visit it a second time, we have not found anything

            //iterate through pages that have to be loaded
            for (int currentPage = startPage; ; currentPage += previous ? -1 : 1)
            {
                if (currentPage > canvas.PageCount)
                {
                    if (!wrap)
                    {
                        //We have not found anything and reached the end
                        SearchCompleted(null);
                        return;
                    }
                    //We have reached the end of the document -> continue at beginning
                    currentPage = 1;
                    startIndex  = 0;
                }
                else if (currentPage <= 0)
                {
                    if (!wrap)
                    {
                        //We have not found anything backwards and reached the beginning
                        SearchCompleted(null);
                        return;
                    }
                    //We have reached the beginning of the document -> continue at end
                    currentPage = canvas.PageCount;
                    startIndex  = int.MaxValue;
                }

                //load textfragments
                StringBuilder searchableText = new StringBuilder("");
                for (int page = currentPage; page <= canvas.PageCount && page < currentPage + maxNumberOfPagesPreloaded; page++)
                {
                    try
                    {
                        loadPage(page);
                    }
                    catch (PdfNoFileOpenedException)
                    {
                        //the file is not open anymore
                        SearchCompleted(null);
                        return;
                    }
                    searchableText.Append(searchableTextCache[page]);
                }

                if (!matchesCache.ContainsKey(currentPage))
                {
                    // we need to search for matches on this page, as they are not in cache yet
                    MatchCollection matches = regex.Matches(searchableText.ToString());
                    matchesCache.Add(currentPage, new List <Match>());
                    foreach (Match match in matches)
                    {
                        if (match.Index < searchableTextCache[currentPage].Length)
                        {
                            matchesCache[currentPage].Add(match);
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                //find the next match we are interested in starting from startIndex
                Match nextMatch = null;
                foreach (Match match in matchesCache[currentPage])
                {
                    if (!previous)
                    {
                        if (match.Index >= startIndex && (nextMatch == null || match.Index < nextMatch.Index))
                        {
                            nextMatch = match;
                        }
                    }
                    else
                    {
                        if (match.Index <= startIndex && (nextMatch == null || match.Index > nextMatch.Index))
                        {
                            nextMatch = match;
                        }
                    }
                }

                if (nextMatch == null)
                {
                    //no match on this page, go to next (or previous) page

                    //special case if we have checked the entire document and reached the startPage again and still not found anything: give up.
                    if (currentPage == startPage)
                    {
                        if (!firstTime)
                        {
                            //if we are on startPage for the second time, we have found nothing and should stop looking
                            SearchCompleted(null);
                            return;
                        }
                        firstTime = false;
                    }
                    //the startIndex is not valid if we are not on the first page
                    startIndex = previous ? int.MaxValue : 0;
                    continue;
                }
                else
                {
                    //We found a match: we have to translate our match to textfragments for highlighting

                    //create the empty lists for the textRects, that will be highlighted
                    Dictionary <int, IList <PdfSourceRect> > textRects = new Dictionary <int, IList <PdfSourceRect> >();
                    textRects.Add(currentPage, new List <PdfSourceRect>());

                    int fragmentIndex           = 0;
                    int page                    = currentPage;
                    int previousPagesTextLength = 0; //the length of all text on previous pages (this is used to offset the index to be relative to page instead of currentPage)

                    //iterate over textfragments and extract their textRects
                    while (textFragmentIndexDict.ContainsKey(page))
                    {
                        PdfTextFragment fragment = null;
                        //offset the fragmentIndex to be relative to page for getting correct fragment
                        fragment = textFragmentIndexDict[page][fragmentIndex - previousPagesTextLength];

                        int startSubIndex = 0;                    //index of start of match in relation to firstTextFragment
                        int endSubIndex   = fragment.Text.Length; //index of end of match in relation to firstTextFragment

                        if (nextMatch.Index > fragmentIndex + fragment.Text.Length)
                        {
                            //we have not found the region with the match yet
                            //carry on with next fragment
                        }
                        else if (nextMatch.Index + nextMatch.Length < fragmentIndex)
                        {
                            //We have passed the fragment already and can end searching
                            break;
                        }
                        else
                        {
                            //we are looking at a fragment that is intersecting with the match
                            if (fragmentIndex < nextMatch.Index)
                            {
                                //the match starts in the middle of this textfragment
                                startSubIndex = nextMatch.Index - fragmentIndex;
                            }
                            if (fragmentIndex + fragment.Text.Length > nextMatch.Index + nextMatch.Length)
                            {
                                //the match ends before the end of the fragment
                                endSubIndex = nextMatch.Index + nextMatch.Length - fragmentIndex;
                            }
                            PdfSourceRect rect = null;
                            if (startSubIndex == 0 && endSubIndex == fragment.Text.Length)
                            {
                                rect = fragment.RectOnUnrotatedPage;
                            }
                            else
                            {
                                //rect = canvas.DocumentManager.RequestTextFragmentSubRect(fragment, startSubIndex, endSubIndex - startSubIndex).Wait();
                                rect = fragment.GetRectOnUnrotatedPage(startSubIndex, endSubIndex);
                            }
                            textRects[page].Add(rect);
                        }

                        //increment index and if necessary page
                        fragmentIndex += fragment.Text.Length + 1;
                        if (!textFragmentIndexDict[page].ContainsKey(fragmentIndex - previousPagesTextLength))
                        {
                            if (page == canvas.PageCount)
                            {
                                //we reached the end of the document: end here
                                break;
                            }
                            else
                            {
                                //There are no more fragments on page: go to the next page
                                previousPagesTextLength += searchableTextCache[page].Length;
                                page++;
                                textRects.Add(page, new List <PdfSourceRect>());
                            }
                        }
                    }//end of iteration over textFragments
                    SearchCompleted(new SearchResult(currentPage, textRects, nextMatch.Index, nextMatch.Value));
                    //Console.WriteLine(String.Format("Found match on page {0} with index {1}", currentPage, nextMatch.Index));
                    return;
                }

                /*
                 * if (!previous)
                 *  startIndex = 0;
                 * else
                 *  startIndex = int.MaxValue;*/
            }//end for all pages
        }
Ejemplo n.º 21
0
        /// <returns>Whether the page has been drawn or queued to lists for drawing. Returns false if no valid information about previous drawRequest</returns>
        private bool CalculateSourceTargetRects(WriteableBitmap bitmap, int rotation, int page, PdfSourceRect pageRect,
                                                IList <int> pages, IList <PdfSourceRect> sourceRects, IList <PdfTargetRect> targetRects,
                                                PdfSourceRect visibleRectOnPage, PdfViewerController.Viewport viewport)
        {
            if (!lastVisiblePages.Contains(page) || visibleRectOnPage.IsEmpty)
            {
                return(false);
            }

            int           lastIndex = lastVisiblePages.IndexOf(page);
            PdfSourceRect reusableRectOnPage = lastVisibleRectOnPages[lastIndex].intersectDouble(visibleRectOnPage);
            PdfTargetRect reusableTargetRect, reusableTargetRectOnLastBitmap;

            while (true)
            {
                reusableTargetRect             = GetTargetRect(reusableRectOnPage, pageRect, viewport);
                reusableTargetRectOnLastBitmap =
                    GetTargetRect(reusableRectOnPage, lastPageRects[lastIndex], lastViewport);
                if (reusableTargetRectOnLastBitmap.IsEmpty)
                {
                    return(false); //if we cant reuse anything, there is nothing to do
                }
                if (reusableTargetRect.iWidth != reusableTargetRectOnLastBitmap.iWidth ||
                    reusableTargetRect.iHeight != reusableTargetRectOnLastBitmap.iHeight)
                {
                    //Console.WriteLine("Inconsistent reusableTargetRect sizes: {0} vs. {1}  and  {2} vs. {3}", reusableTargetRect.iWidth, reusableTargetRectOnLastBitmap.iWidth, reusableTargetRect.iHeight, reusableTargetRectOnLastBitmap.iHeight);
                    reusableRectOnPage.Shrink(0.99);
                }
                else
                {
                    break;
                }
            }

            reusedTargetRects.Add(reusableTargetRect);

            //calculate the area to copy
            int bytesPerPixel = (lastBitmap.Format.BitsPerPixel + 7) / 8;
            int stride        = reusableTargetRectOnLastBitmap.iWidth * bytesPerPixel;

            byte[] pixels     = new byte[reusableTargetRectOnLastBitmap.iWidth * reusableTargetRectOnLastBitmap.iHeight *
                                         bytesPerPixel];

            //read from last bitmap
            lastBitmap.CopyPixels(reusableTargetRectOnLastBitmap.GetInt32Rect(), pixels, stride,
                                  0); //(lastBitmap.PixelWidth * (reusableTargetRectOnLastBitmap.iY - 1) + reusableTargetRectOnLastBitmap.iX - 1) * bytesPerPixel);

            //write to new bitmap
            bitmap.Lock();
            bitmap.WritePixels(reusableTargetRect.GetInt32Rect(), pixels, stride, 0);
            bitmap.AddDirtyRect(reusableTargetRect.GetInt32Rect());
            bitmap.Unlock();

            //calculate rects that need to be drawn newly
            IList <PdfTargetRect> targetDifs = GetTargetRect(pageRect, viewport).subtractRect(reusableTargetRect);

            for (int i = 0; i < 4; i++)
            {
                PdfTargetRect targetRect = targetDifs[i];
                if (targetRect.IsEmpty)
                {
                    continue;
                }
                PdfSourceRect sourceRect = GetSourceFromTargetRect(targetRect, pageRect, viewport);
                targetRects.Add(targetRect);
                sourceRects.Add(sourceRect);
                pages.Add(page);
            }
            return(true);
        }
Ejemplo n.º 22
0
 private bool PageCacheEquator(PdfSourceRect rect1, PdfSourceRect rect2)
 {
     return(rect1.Equals(rect2));
 }