espresso3389 / flutter_pdf_render

A Flutter package, which renders PDF pages.
https://pub.dev/packages/pdf_render
MIT License
108 stars 71 forks source link

Performance issues on PdfViewer with highly detailed pdf #104

Closed ynnob closed 1 month ago

ynnob commented 1 year ago

Hey! First of all I would like to thank you for the great package!

Enviroment:

Before using your package i rendered the pdf as an image and draw it on a canvas. This caused problems because mobile devices are very limited when it comes to large images. We process large scaled floor plans and similar plans of structures. These can be very detailed so the images often exceed 10000x10000 pixels which caused the app to crash. OOM Exceptions could only be avoided by limiting the decoded image to something like 8000x8000 pixels. But there was no real good way to calculate the amount of pixels the phone can handle.

On top of the displayed floor plan i use a canvas to draw marker on user defined locations. Therefore we used a InteractiveViewer to scale the canvas.

Problem:

Based on the problem and existing implementation with InteractiveViewer i decided to use your PdfViewer. This allowed me to reuse existing code for the InteractiveViewer. At this point everything is working as expected. I can open these large pdf files and zoom/pan. This works great for text-pdf's and pdf's with simple structures even if they are really really big. The performance problem seems to occur on pdfs with a lot of objects and it starts to stutter/lag while beeing redrawn after zoom/pan.

I have already ruled out that my canvas has an impact on the performance.

Test Scenario:

Load the attached pdf (source) PDF: MUSTERPLAN_Bestand_G02.pdf

Zoom in on the pdf and pan around like if your looking for something. When your _realSizeOverlayUpdateBufferDuration of 100ms is reached and the area is repainted while you try to pan or zoom the thread seems blocked. I'm not sure if it's the calculation of the area to be drawn or the time it takes to redraw it. Either a non-asynchronous method or the drawing itself blocks the application.

  1. Do you have any idea how to solve this problem? Or should I try to use the PdfDocumentLoader and implement my own InteractiveViewer and a custom redraw logic of the zoomed area somehow?

  2. Is there a way to only render specific pages while using the PdfViewer?

Current Implementation

    return SizedBox(
      child: PdfViewer.openFile(
        viewModel.currentPresentationData!.path!,
        viewerController: viewModel.pdfController,
        params: PdfViewerParams(
          minScale: 0.8,
          maxScale: 50,
          onViewerControllerInitialized: (page) {
            Rect viewRect = page.viewRect;
            Rect? skizzeRect = page.getPageRect(1);
            if (skizzeRect != null) {

              // check if panorama pdf
              if (skizzeRect.width > skizzeRect.height) {
                // calculate to move center
                double yTranslate = (viewRect.height - skizzeRect.height) / 2;
                viewModel.pdfController.value.setEntry(1, 3, yTranslate);
              }
            }

            // init scale for canvas elements
            viewModel.updateScale();
          },
          onInteractionUpdate: (ScaleUpdateDetails details) {
            // this informs the custom painter so we can custom scale elements
            viewModel.updateScale();
          },
          boundaryMargin: const EdgeInsets.all(double.infinity),
          buildPagePlaceholder: (context, pageNumber, pageRect) => const LoadingIndicator(),
          buildPageOverlay: (context, pageNumber, pageRect) {
            if (pageNumber == 1) {
              return GestureDetector(
                  onTapDown: (details) => viewModel.onTap(details, pageRect),
                  child: RepaintBoundary(
                      child: CustomPaint(
                    size: Size.infinite,
                    painter: CustomPainter(),
                  )));
            }

            return const Padding(
              padding: EdgeInsets.all(10.0),
              child: Text(
                "Multiple pages not supported!",
                style: TextStyle(color: ZisColor.red, fontSize: 8),
              ),
            );
          },
        ),
      ),
    );
myselfuser1 commented 1 year ago

This will help https://www.youtube.com/watch?v=gAUVz0U7eyA

ynnob commented 1 month ago

Closing this since this package is mostyl "deprecated". The author of this package moved on to a better implementation using PDFium https://github.com/espresso3389/pdfrx which seems to be the future.