dart_pdf_editor 1.1.0
dart_pdf_editor: ^1.1.0 copied to clipboard
Flutter PDF viewer and editor rendered natively in Dart — zooming viewer, text selection and search, annotation authoring, form filling, signatures, and page management. No platform plugins.

dart_pdf_editor #
A Flutter PDF viewer and editor rendered natively in Dart, with no platform views or native PDF libraries. The same code runs on iOS, Android, macOS, Windows, Linux, and the web.

Two drop-in widgets carry the whole UI — give them bytes and bounded space, and everything in the screenshot above (search, page navigation, panels, tools, undo/redo, save) is wired up:
import 'package:dart_pdf_editor/dart_pdf_editor.dart';
// A complete PDF editor
PdfEditorView(
bytes: pdfBytes,
onSave: (bytes) => /* write the file */,
)
// A view-only reader
PdfReader(bytes: pdfBytes)
Both follow the ambient Material Theme (dark mode included), persist
user preferences on the device, and pare down with feature flags:
PdfEditorView(
bytes: pdfBytes,
features: const PdfEditorFeatures(
propertiesPanel: false,
flatten: false,
tools: {PdfEditTool.select, PdfEditTool.ink, PdfEditTool.freeText},
),
toolbarTrailing: [
(context, editing, viewer) => IconButton(
icon: const Icon(Icons.cloud_upload_outlined),
tooltip: 'Publish',
onPressed: () => publish(editing.bytes),
),
],
)
Try the live demo of the example app on Flutter web, with a built-in feature showcase document.
Built on the pure-Dart
dart-pdf suite: pdf_cos
(file syntax) ← pdf_document (document semantics + editing) ←
pdf_graphics (interpreter + fonts) ← dart_pdf_editor (Flutter widgets).
Performance #
Pure Dart, and fast: on a real-world corpus (49 files / 245 pages of CAD drawings, scans, reports, and forms) the parse + content-stream interpreter is ~1.5× faster than PDFium — the C++ engine Chrome uses — at 13.6 ms/page vs 20.6 ms/page (scale 2). Full Flutter rasterization is 53.7 ms/page (2.6× PDFium); that remaining gap is image decoding and GPU raster, not the interpreter.
| engine | ms/page | vs PDFium |
|---|---|---|
| dart-pdf interpret (pure Dart) | 13.6 | 1.52× faster |
| PDFium (open + rasterize) | 20.6 | 1.00× |
| dart-pdf render (full Flutter raster) | 53.7 | 2.60× slower |
Numbers and methodology — including reproducible harnesses that diff
dart-pdf against PDFium file-by-file — are in
benchmark/.
Viewing #
- Zooming/panning viewer with fit-page and fit-width modes, deep-zoom detail rendering past the raster caps, and exact scroll metrics on long mixed-size documents.
- Smooth fast scrolling on heavy documents: pages flying past show low-res previews (filled in by a background prerender) instead of blank paper, and full rendering resumes the moment scrolling settles.
- Text selection (mouse, and touch with selection handles), full-text search with a results panel, link navigation, outlines.
- Theming via
PdfViewerTheme, dark mode, arbitrary page colors, and a hide-all-annotations toggle.
Editing #
Every edit is an incremental save: undo/redo is built in, and revisions are byte prefixes of one buffer.
- Annotation tools: highlight/underline/strikeout/squiggly, ink with stylus pressure and spline smoothing, shapes, free text with in-place editing, notes, stamps (including custom saved stamps), and a saved ink signature.
- Direct manipulation: select (single, marquee, ⌘A), move, resize, and rotate with live appearance previews, plus a slicing circle eraser, copy/cut/paste, z-order, restyling, and a context menu with host-extensible entries (right-click, or long-press on touch).
- Forms: fill text/checkbox/radio/choice fields in place, set button
images, and administer fields (add, rename, retype, delete, flatten).
Fields are highlighted with a translucent wash by default
(
PdfViewer.highlightFormFields). - Panels: thumbnail sidebar with drag-reorder, annotation sidebar with search and multi-select, properties panel, and search results panel, all resizable and persisted.
- Permissions:
/Fread-only and locked flags are honored, and acanEditAnnotationpredicate implements policies like "users may only edit their own annotations" in one line. - Sync: an
annotationChangesfeed plusapplyRemoteChangefor wiring annotations to a collaborative store (Firestore, websockets, etc.).
Composing your own UI #
PdfEditorView and PdfReader are assembled from public parts —
PdfViewer, PdfEditingController, PdfEditingToolbar, the panels —
so apps wanting custom chrome can wire those directly:
import 'package:pdf_document/pdf_document.dart';
import 'package:dart_pdf_editor/dart_pdf_editor.dart';
// Just the viewer
PdfViewer(document: PdfDocument.open(bytes));
// Your own editor layout
final editing = PdfEditingController(bytes);
final viewer = PdfViewerController();
ListenableBuilder(
listenable: editing,
builder: (context, _) => Column(children: [
Expanded(
child: PdfViewer(
document: editing.document, // rebuild with each revision
controller: viewer,
editing: editing,
),
),
PdfEditingToolbar(controller: editing, viewerController: viewer),
]),
);
// Saving
final Uint8List saved = editing.bytes;
The example app is a thin shell over PdfEditorView (with a
toggle that swaps in PdfReader) plus the app-side concerns: file
open/save dialogs, theme mode, and Flutter overlays pinned onto PDF
pages. It runs on all six platforms.
Under the hood #
Encrypted files (RC4/AES-128/AES-256, encrypt-on-write), digital
signature validation, the full shading and blend-mode set, ICC color,
CCITT/JBIG2/JPEG 2000 images, and lenient parsing of broken real-world
files, with conformance pinned against the Ghent Output Suite and the
PDF.js test corpus. Checked-in PDF.js visual comparisons are available at
../../test_corpora/pdfjs/_renders/README.md.