Published 2025-10-13

| Version | MacOS | Linux | Windows | Release date |
|---|---|---|---|---|
| 7.0.2 | - | - | - | 2010-12-10 |
| 8.0.2 | X | - | - | 2010-12-10 |
| 9.0.2 | - | X | - | 2013-12-17 |
| 10.0.0 | X | X | - | 2022-09-01 |
| Version | MacOS | Linux | Windows |
|---|---|---|---|
| 5.4.p2 | X | X | X |
| Version | MacOS | Linux | Windows |
|---|---|---|---|
| 8.0.2 | X | - | - |
| 9.0.2 | - | X | - |
| 10.0.0 | X | X | - |
| Version | MacOS | Linux | Windows |
|---|---|---|---|
| 5.4.p2 | - | - | - |
Versions without licenses only work with small (max. 10 pages) documents when using the pcos functions due to 'evaluation mode' of the PDFlib 10 and/or PLOP libraries. Seems like it is time to upgrade. See the 'PLOP' section below.
No need to install anything (anymore). The so/dylib/dll is loaded from pkg_pdflib resources.
In your project's pubspec.yaml add:
dependencies:
pkg_pdflib:
path: ../pkg_pdflib
In your code add:
import 'package:pkg_pdflib/pkg_pdflib.dart';
Be sure to install 'Visual C++ Redistributable Packages' first otherwise you will get an error 126 while loading the dll.
final PdflibWrapper pdflib = PdflibWrapper()
..set_option(
r'logging={filename=test/assets/debug_wrapper.log remove}');
final PdiScope scope = PdiScope(pdflib: pdflib);
if (scope.doOpen()) {
final PdiDocument document = scope.getDocument();
if (document.doOpen(File("test.pdf")) {
expect(document.isOpen(), true);
expect(document.isOnlyBasicInfoAvailable(), false);
expect(document.isLinearized(), false);
expect(document.isTagged(), false);
expect(document.isTopDown(), false);
expect(document.getHandle(), 0);
// ... do other stuff
document.doClose();
}
scope.doClose();
}
pdflib.delete();
final PdflibWrapper pdflib = PdflibWrapper();
final Pdflib root = Pdflib(
comment: r'Just a basic pdf generator test',
logging: true,
gridsize: Units.mm2pt(10),
showgrid: true,
children: [
Document(
intermediate: r'intermediate_generator_test.pdf',
filename: "generator_test_${pdflib.actualVersion}.pdf",
children: [
Page(
width: Units.mm2pt(210).toString(),
height: Units.mm2pt(297).toString(),
options: r'topdown=false',
children: [
Annotation(
llx: "(5 + 5) * points_per_mm",
lly: "17 * points_per_mm",
urx: Units.mm2pt(20),
ury: Units.mm2pt(7),
annotationType: AnnotationType.Text,
name: r'annotation_0',
title: r'annotation 0 title',
children: [
Cdata(r'test annotation 0 text'),
],
),
],
),
],
)
],
);
root.doValidate();
final GetIt getIt = GetIt.instance;
getIt.pushNewScope(
init: (final getIt) {
getIt.registerSingleton(
ScriptController(
pdflib: pdflib,
root: root,
),
);
},
dispose: () {},
);
await getIt.get<ScriptController>().doPlay();
getIt.popScope();
pdflib.delete();
You'll see that this document structuring is very similar to building a Flutter UI with widgets.
To 'run' the 'script' (eg. build the PDF file), you have to supply a controller through depencency-injection in the current scope with GetIt. We then 'get' the controller and call it's doPlay method. When done the controller is popped and the pdflib instance should be deleted to free up resources.
When object properties are dynamic it is possible to assign them in the following ways:
Annotation(llx: 10.0); // 10 pt
Annotation(llx: 10.0 * (1.0 / (25.4 / 72.0))); // 10 mm
Annotation(llx: Units.mm2pt(10.0); // 10 mm
Annotation(llx: myvar); // something
Annotation(llx: "$left * points_per_mm"); // 'left' mm
Note: point and points_per_mm are pre-defined constants.
Annotation(llx: "10 * points_per_mm");
Note: point and points_per_mm are pre-defined constants.
Annotation(llx: (final controller, final context) {
return ScriptableVariable(ctx: context)
.getDouble("textflow_someTextframe_x1 + (10 * points_per_mm)");
},
);
Note: point and points_per_mm are pre-defined constants. textflow_someTextframe_x1 is the lower-left-x value of a named Textflow() somewhere on the page.
Hint: Put a debug break-point in the callback function to see which key/values are available in the context parameter.
PLOP = PDF Linearization, Optimization, Protection.
Interfacing with the PDFlib < 10.0.0-beta1 java libraries via the ffigen generated dart code resulted in crashes on the following three functions:
It was determined that PDFlib 10.0.0-beta1 will work, and also, that the PLOP library provides the same three functions that would not crash.
So, in order to get things working for the lower (deprecated) PDFlib libraries, the PLOP functions are used for PDFlib versions that would otherwise crash. The PdflibWrapper class takes care of that.
Caveat: This package currently only works with small (max. 10 pages) documents when using the pcos functions due to 'evaluation mode' of the PDFlib 10 and/or PLOP libraries. Seems like it is time to upgrade.
Just run hh generate.
Use the method above (generate script).
Put one of the entries below in your pubspec.yaml.
# https://hkubota.wordpress.com/2021/10/16/dart-and-ffi-and-ffigen/
# unless the headers change, this should be done only once.
# 1. enable 1 (one) ffi section below
# 2. run 'flutter pub run ffigen'
# 3. disable the ffi section.
#ffigen:
# name: NativeLibrary
# description: pdflib_8_0_2
# output: 'lib/src/pdflib/pdflib_8_0_2.dart'
# headers:
# entry-points:
# - 'headers/pdflib_8_0_2.h'
#ffigen:
# name: NativeLibrary
# description: pdflib_9_0_2
# output: 'lib/src/pdflib/pdflib_9_0_2.dart'
# headers:
# entry-points:
# - 'headers/pdflib_9_0_2.h'
#ffigen:
# name: NativeLibrary
# description: pdflib_10_0_0
# output: 'lib/src/pdflib/pdflib_10_0_0.dart'
# headers:
# entry-points:
# - 'headers/pdflib_10_0_0p1.h'
#ffigen:
# name: NativeLibrary
# description: pdflib_10_0_1
# output: 'lib/src/pdflib/pdflib_10_0_1.dart'
# headers:
# entry-points:
# - 'headers/pdflib_10_0_1.h'
#ffigen:
# name: NativeLibrary
# description: windows pdflib for dll
# llvm-path:
# - '/usr/lib/llvm-12/lib/libclang.so'
# output: 'lib/src/pdflib/pdflibdl_windows_10_0_0.dart'
# headers:
# entry-points:
# - 'headers/windows/10_0_0/pdflibdl.h'
#ffigen:
# name: NativeLibrary
# description: windows pdflib for dll
# llvm-path:
# - '/usr/lib/llvm-12/lib/libclang.so'
# output: 'lib/src/pdflib/pdflibdl_windows_10_0_1.dart'
# headers:
# entry-points:
# - 'headers/windows/10_0_1/pdflibdl.h'
#ffigen:
# name: NativeLibrary
# description: plop_5_4_2
# output: 'lib/src/plop/plop_5_4_2.dart'
# headers:
# entry-points:
# - 'headers/ploplib_5_4_2.h'
#ffigen:
# name: NativeLibrary
# description: plop_5_5_0
# output: 'lib/src/plop/plop_5_5_0.dart'
# headers:
# entry-points:
# - 'headers/ploplib_5_5_0.h'
metadata field on Document token.create_textflow handle.silence-enum-warning: true to ffigen configurations.MergePdf, honour orientation, strip cloneboxes=true if needed.BoxPlacement::toPdfRect.IControllerDispatcher and IControllerListener are now async.ITaskDispatcher and ITaskListener are now async.ScriptableVariable due to missing matchbox index.TokenFactory anymore.errorPolicy parameter to PdflibWrapper.PdflibWrapper now has ErrorPolicy parameter.Type and SubType to BlockDim structure.Templatepdf token.async abort status.ScriptController can now only be create by calling the async ScriptController.create function that synchronizes access to IToken.tokenFactory.ScriptController.doPlay method now synchronizes access to IToken.tokenFactory.get_it dependency.fontoutline={{alias}={path}} options.flutter/assets in pubspec.yaml.PdflibWrapper::getFontsAvailableReportPdflibWrapper::isFontAvailablePdflibWrapper::searchPathscollection dependency.optional dependency.expression dependency.quiver dependency.tp_expressions dependency.int is not a subtype of double in token/rectangle, image, pdf (mainly caused by json generated from a web-application, because js makes an int of double values without fraction (1.0 becomes 1)).pdflib binaries.flutter_test to pure-dart test.async constructs.tool/ffi_generate.dart to generate the api.pdflib 10.0.1 and plop 5.5.0.pdflib 10.0.0 and plop 5.4.2 since we do not have a license upgrade (yet).await unawaited futures.unawaited.flutter references, making this package pure dart.flutter because of pkg_pdflib_flutter.Color from RgbColorParserMixin in preparation for a flutter-less (pure dart) pkg_pdflib (so we can use it in a console app)._Pdflib::_findBinFolder.PdfMediaInfo.kPdflibCompatibilityVersion constant.test/Schapkaarten_002.pdf to 50.toPrecision.XHtmlHandler.searchpath with spaces.await doPlay/onBegin/onEnd.Templatetext when no textoptions were given.GeneratorRunner now implements IAbortProvider.print statements for logging.mergepdf for a 50% speed gain.generator/tokens/Document. You should always clean your output folder before creating new pdf files to prevent accidental overwrites and thus losing data by generating a file twice.set_option('searchpath=$path') contained a - character. Changed to set_option('searchpath={$path}').toPNG (uses flutter foundation).toPNG (uses flutter foundation).VeraMono to default fonts.ffi.Int32 to ffi.Int.ffi.ffi.Int8 to ffi.Char.volatile keyword from plop_5_4_2.h.CHANGELOG.md.generator_test.verbose flag on PdiDocument to prevent/enable debug printing.finals due to new linter rules.fonts to bin and include in asset resources.fonts folder to searchpath.Mergepdf now takes the test flag from the controller.IToken.children is now a List&amp;amp;amp;amp;amp;amp;amp;amp;lt;IToken&amp;amp;amp;amp;amp;amp;amp;amp;gt; not List&amp;amp;amp;amp;amp;amp;amp;amp;lt;dynamic&amp;amp;amp;amp;amp;amp;amp;amp;gt;.IAbortProvider.pkg_pdflib resources. No need to bundle them via XCode anymore.Start- and EndPage events (also when pages are merged with Mergepdf).orientation to Mergepdf that will rotate all pages to the specified orientation if needed.TokenValidation mixin to pkg_pdflib_tokens.tp_open_file.file_picker to 5.0.0.ffi to 2.0.1