Пример #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);
        }
Пример #2
0
        public PdfSourceRect RectOnCanvas(PdfSourceRect pageRect, PdfViewerController.Viewport viewport)
        {
            PdfSourceRect rect   = viewport.Rectangle.GetSourceRect(viewport.ZoomFactor);
            double        left   = Double.IsNaN(this.left) ? rect.dX : (this.left + pageRect.dX);
            double        top    = (Double.IsNaN(this.top) || this.top == -32768) ? pageRect.dY : (pageRect.dBottom - this.top);
            double        width  = Double.IsNaN(this.right) ? rect.dRight - left : this.right - left;
            double        height = Double.IsNaN(this.bottom) ? (rect.dBottom - top) : (this.bottom - top);

            return(new PdfSourceRect(left, top, Math.Max(width, 0.0), Math.Max(height, 0.0)));
        }
Пример #3
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);
        }
Пример #4
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);
        }
Пример #5
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");
        }
Пример #6
0
 private PdfTargetRect GetTargetRect(PdfSourceRect pageRect, PdfViewerController.Viewport viewport)
 {
     return(GetTargetRect(null, pageRect, viewport));
 }
Пример #7
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);
        }
Пример #8
0
        // source and targetrects may be empty! (due to crops with pages etc.)
        public PdfDrawRequest Draw(int width, int height, Resolution resolution, int rotation, IDictionary <int, PdfSourceRect> pageRects, PdfViewerController.Viewport viewport)
        {
            IList <KeyValuePair <int, PdfSourceRect> > newPageRects = new List <KeyValuePair <int, PdfSourceRect> >();

            foreach (int key in pageRects.Keys)
            {
                int newKey;
                if (key - 1 < _pageOrder.Count)
                {
                    newKey = _pageOrder[key - 1];
                }
                else
                {
                    continue;
                }

                if (newKey > document.PageCount)
                {
                    continue;
                }
                newPageRects.Add(new KeyValuePair <int, PdfSourceRect>(newKey, pageRects[key]));
            }

            PdfDrawRequest request = new PdfDrawRequest(new DrawArgs(width, height, resolution, rotation, newPageRects, viewport));

            if (lastDrawRequest == null)
            {
                requestQueue.Add(request);
            }
            else
            {
                requestQueue.Replace(lastDrawRequest, request);
            }
            lastDrawRequest = request;
            //add new draw request
            return(request);
        }
Пример #9
0
 public DrawArgs(int bitmapWidth, int bitmapHeight, Resolution resolution, int rotation, IList <KeyValuePair <int, PdfSourceRect> > pageRects, PdfViewerController.Viewport viewport)
 {
     this.bitmapWidth  = bitmapWidth;
     this.bitmapHeight = bitmapHeight;
     this.resolution   = resolution;
     this.rotation     = rotation;
     this.pageRects    = pageRects;
     this.viewport     = viewport;
 }