buehler / flutter_pdfium

Native library bindings for the PDFium library to be used in Flutter.
https://pub.dev/packages/flutter_pdfium
Apache License 2.0
0 stars 0 forks source link

Building/Running example app fails on windows platform #3

Closed timmaffett closed 2 weeks ago

timmaffett commented 2 weeks ago

I was attempting to view/run the example. The steps I followed did not allow me to view/run the example: (using vscode environment, windows platform, running on android emulator, and i am on the master branch of flutter) (I just RE-did these steps to verify (fresh git clone, etc.) - the error still occurs)

I cloned the repo git clone https://github.com/buehler/flutter_pdfium.git flutter pub get (in root or package) select example\main.dart (and select run without debugging) And the build process goes and errors out because ../lib/flutter_pdfium.dart:6:8: Error: Error when reading '../lib/src/pdfium.dart': The system cannot find the path specified.

The lib/src/pdfium.dart is not found - so it did not get generated by podspec or cmake commands.

Full output of build in vscode:

Resolving dependencies... Downloading packages... collection 1.18.0 (1.19.0 available) material_color_utilities 0.11.1 (0.12.0 available) Got dependencies! 2 packages have newer versions incompatible with dependency constraints. Try flutter pub outdated for more information. Launching lib\main.dart on sdk gphone x86 in debug mode... ../lib/flutter_pdfium.dart:6:8: Error: Error when reading '../lib/src/pdfium.dart': The system cannot find the path specified.

import 'src/pdfium.dart'; ^ ../lib/flutter_pdfium.dart:8:1: Error: Error when reading '../lib/src/pdfium.dart': The system cannot find the path specified.

export 'src/pdfium.dart'; ^ lib/main.dart:34:8: Error: Type 'Pdfium' not found. late Pdfium pdfium; ^^^^^^ lib/main.dart:35:3: Error: Type 'FPDF_DOCUMENT' not found. FPDF_DOCUMENT? document; ^^^^^^^^^^^^^ ../lib/flutter_pdfium.dart:13:1: Error: Type 'Pdfium' not found. Pdfium createInitializedLibrary() { ^^^^^^ lib/main.dart:34:8: Error: 'Pdfium' isn't a type. late Pdfium pdfium; ^^^^^^ lib/main.dart:35:3: Error: 'FPDF_DOCUMENT' isn't a type. FPDF_DOCUMENT? document; ^^^^^^^^^^^^^ lib/main.dart:120:33: Error: 'FSSIZEF' isn't a type. final sizePointer = arena(); ^^^^^^^^^ lib/main.dart:123:31: Error: The property 'ref' is defined in multiple extensions for 'Pointer' and neither is more specific.

FAILURE: Build failed with an exception.

BUILD FAILED in 1m 49s Error: Gradle task assembleDebug failed with exit code 1

Exited (1).

buehler commented 2 weeks ago

ah ok, I know what you mean.

So the thing is, that the pdfium bindings are generated during my build steps (seen in github workflow files).

So, if you want to use them, you can do the following:

this will download the package from pub.dev which contains the built sources that you search and during the build process the cmake file will make sure that the dll and lib files are downloaded CMakeLists.txt.

But good point to update the docs to show how to use the package from pub dev and how to use it when it is cloned. Because when you clone the library, you need to generate the sources and headers and stuff.

What I meant by "have a look at the example" was: look at the example for reference on how to use the lib.

buehler commented 2 weeks ago

Alright, I updated the readme, you should be able to follow the provided steps there. Either install the package from pub.dev (where all the sources are pre-generated) or use the local development information to create the headers locally.

timmaffett commented 2 weeks ago

Thank you @buehler I was successfully able to build the example app by following these steps: 1) flutter create ... a new example flutter project 2) Copy the contents of example\lib\main.dart and replace the main.dart in the newly created example project 3) Create a top level assets directory and copy the example\assets\sample.pdf to this directory 4) Add the

  assets:
    - assets/

to the pubspec.yaml file to include the assets directory.

I was then able to run the new project and see the example in android emulator.

(@buehler I include these details more for new users than for you (obviously))

Unfortunately (for me) without an example of actually rendering pdf pages to the screen I will not have the time to invest in using this within my project. It all looks very promising though!

Thanks for the time you have spent creating this package - and I found that reading your thesis in the sample.pdf was very interesting.

buehler commented 2 weeks ago

Thank you <3

Regarding the usage of the lib, I'm currently developing an addition to this lib that builds upon the built lib headers.

This can then be used to render pages of a pdf. While still under development, you can find an example on how to render a page here:

https://github.com/buehler/flutter_easy_pdfium

Just published it for you. With the following components and parts (the rest is available in the github repo) you should be able to create an image of a page. Otherwise, don't hesitate to ask ;)

Key components:

Loading a PDF from memory

```dart // document.dart static Future fromMemory(Uint8List data, [String? password]) => pdfWorker.compute(() { final document = using((arena) { final dataPointer = arena(data.length); for (var i = 0; i < data.length; i++) { dataPointer[i] = data[i]; } final voidPointer = dataPointer.cast(); return pdfium().LoadMemDocument(voidPointer, data.length, (password ?? '').toNativeUtf8().cast()); }, malloc); if (document == ffi.nullptr) { throw getLastLibraryError(); } return Document._(document); }); ```

Load Page in a document

```dart // page.dart Future loadPage(FPDF_DOCUMENT document, int index) => pdfWorker.compute(() { final page = pdfium().LoadPage(document, index); if (page == ffi.nullptr) { throw getLastLibraryError(); } return Page._(page); }); ```

Render and generate an image

```dart // page.dart Future renderImage( {Color backgroundColor = const Color.fromARGB(255, 255, 255, 255), bool grayscale = false, bool renderAnnotations = false, PageRenderRotation rotation = PageRenderRotation.rotate0, double scale = 1.0}) async { assert(scale > 0.0, 'Scale must be greater than 0.0'); var flags = _renderDefaultFlags; if (grayscale) { flags = flags | FPDF_GRAYSCALE; } if (renderAnnotations) { flags = flags | FPDF_ANNOT; } final scaledSize = pixelSize * scale; final scaledWidth = scaledSize.width.round(); final scaledHeight = scaledSize.height.round(); final data = await pdfWorker.compute(() { final bitmapPointer = pdfium().Bitmap_Create(scaledWidth, scaledHeight, 1); pdfium().Bitmap_FillRect(bitmapPointer, 0, 0, scaledWidth, scaledHeight, backgroundColor.value); pdfium().RenderPageBitmap(bitmapPointer, _pointer, 0, 0, scaledWidth, scaledHeight, rotation.index, flags); final stride = pdfium().Bitmap_GetStride(bitmapPointer); final bitmapData = pdfium() .Bitmap_GetBuffer(bitmapPointer) .cast() .asTypedList(scaledHeight * stride); final buffer = bitmapData.toList(growable: false); pdfium().Bitmap_Destroy(bitmapPointer); return buffer; }); final buffer = await ui.ImmutableBuffer.fromUint8List(Uint8List.fromList(data)); final descriptor = ui.ImageDescriptor.raw( buffer, width: scaledWidth, height: scaledHeight, pixelFormat: ui.PixelFormat.bgra8888, ); final codec = await descriptor.instantiateCodec(); final frameInfo = await codec.getNextFrame(); return frameInfo.image; } ```

timmaffett commented 2 weeks ago

@buehler Thanks! And thanks publishing the new higher level package and example.

I am finding that app.locator.dart and app.router.dart are missing from the example for the new repo..

I will try to work around that in the mean time.

buehler commented 2 weeks ago

No worries :-)

These files are generated by "fluorflow". To create them in the example app, just run dart run build_runner build

timmaffett commented 2 weeks ago

I added build_runner to pubspec.yaml

dev_dependencies:
  build_runner: ^2.4.8
timmaffett commented 2 weeks ago

(my mistake, build_runner: ^2.0.0 was already in the example directories pubspec.yaml, ran build runner and everything made correctly.

timmaffett commented 2 weeks ago

I am sure you are working through all this but I wanted to let you know what I experience running the example app. Windows, flutter master branch, android flutter emulator. I clock 'Load PDF' and then on that page I click the 'Load PDF' button. After this exception I can navigate around the app but the buttons no longer do anything or produce any exceptions.

Connecting to VM Service at ws://127.0.0.1:63146/NQpvV-h69Dk=/ws
Connected to the VM Service.
I/OpenGLRenderer( 7003): Davey! duration=709ms; Flags=1, IntendedVsync=87958706195464, Vsync=87958806195460, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=87958817947500, AnimationStart=87958818009600, PerformTraversalsStart=87958818096600, DrawStart=87958911819900, SyncQueued=87958926302100, SyncStart=87958957964600, IssueDrawCommandsStart=87959068517700, SwapBuffers=87959338164200, FrameCompleted=87959447792700, DequeueBufferDuration=79702300, QueueBufferDuration=3806100, GpuCompleted=72904454231491230, 
E/flutter ( 7003): [ERROR:flutter/runtime/dart_isolate.cc(1291)] Unhandled exception:
E/flutter ( 7003): PDFiumException: No error
E/flutter ( 7003): #0      loadPage.<anonymous closure> (package:flutter_easy_pdfium/src/pdf/page.dart:113:9)
E/flutter ( 7003): #1      PdfWorker._workerEntry.<anonymous closure> (package:flutter_easy_pdfium/src/utils/isolate.dart:31:42)
E/flutter ( 7003): #2      _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)
E/flutter ( 7003): #3      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:365:11)
E/flutter ( 7003): #4      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:297:7)
timmaffett commented 2 weeks ago

When I re-ran the app in the debugger everything worked fine (pdf loaded and displayed). I may have clicked the load button TWICE in the above case where the crash occurred. Perhaps the loading code getting triggered twice causes the exception (There is no de-bouncing protection on the viewModel.loadDocument call ).

timmaffett commented 2 weeks ago

@buehler Pressing the load button twice always results in an exception or full crash out of app.