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); }
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); }
public PdfSourceRect GetPageRect(int pageNumber) { CalculateCanvas(); PdfSourceRect rect = documentManager.GetPageRectGuess(pageNumber); return(rect); }
private void PageCacheParametrizationChanger(PdfSourceRect rect, PageCacheParams oldParam, PageCacheParams newParam) { if ((newParam.rotation - oldParam.rotation) % 180 != 0) { rect.RotateSize(); } }
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); }
private void PageCacheFirstLoadParametrizer(PdfSourceRect rect, PageCacheParams param) { if (param.rotation % 180 != 0) { rect.RotateSize(); } }
/// <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); } } }
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); }
/// <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; }
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; }
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); }
/// <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); } }
//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); }
/// <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(); }
// 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"); }
private PdfTargetRect GetTargetRect(PdfSourceRect pageRect, PdfViewerController.Viewport viewport) { return(GetTargetRect(null, pageRect, viewport)); }
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); }
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; }
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 }
/// <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); }
private bool PageCacheEquator(PdfSourceRect rect1, PdfSourceRect rect2) { return(rect1.Equals(rect2)); }