mypaint_ffi
A Flutter FFI plugin that wraps libmypaint to paint MyPaint brush strokes onto a pixel surface.
Android only. This plugin builds libmypaint from source with the Android NDK and exposes it through
dart:ffi. No iOS, macOS, Windows, Linux, or web support is provided.
Features
- Paint brush strokes with pressure and tilt onto a fixed-size RGBA surface.
- Load MyPaint
.mybbrushes from JSON strings. - Set brush base values (radius, hardness, opacity, eraser, …) and color.
- Render the surface to a
ui.Image, converting only the dirty region each frame for performance.
Project structure
src: The native glue (mypaint_ffi.c/mypaint_ffi.h), built intolibmypaint_ffi.sobysrc/CMakeLists.txt.src/third_party: libmypaint, json-c and mypaint-brushes as git submodules, pinned to known-good commits.src/libmypaint_shim: libmypaint'sconfig.hand pre-generated*-gen.hheaders, kept here (not in the submodule) because libmypaint's own.gitignoreexcludes them.lib: The Dart API (mypaint_ffi.dart) and the hand-writtendart:ffibindings (mypaint_ffi_bindings_generated.dart).android: The Gradle/NDK build that compiles the native library and bundles it into the app's APK.example: A small painting app demonstrating the plugin.
Bindings
The native API surface is small, so the dart:ffi bindings in
lib/mypaint_ffi_bindings_generated.dart are maintained by hand rather than
generated with package:ffigen (which would require a host LLVM/libclang
install). When you change src/mypaint_ffi.h, update those bindings to match.
Usage
final engine = BrushEngine(
surface: MyPaintSurface(width, height),
brush: Brush()..loadFromString(mybJson)..setColor(0, 0, 0),
);
engine.surface.beginAtomic();
engine.strokeTo(x, y, pressure: 0.8);
engine.surface.endAtomic();
final ui.Image image = await engine.surface.toImage();
See example/lib/main.dart for a full painting screen, including a brush
picker over the bundled MyPaint brush sets.
Building
Clone with submodules
The libmypaint, json-c and mypaint-brushes sources live in src/third_party as
git submodules, so clone recursively:
git clone --recursive https://github.com/dima-xd/mypaint_ffi.git
If you already cloned without --recursive, pull the submodules in:
git submodule update --init --recursive
To update the vendored sources to their latest upstream commits later:
git submodule update --remote
Build
The native library is built automatically by the Android Gradle plugin when you
run the app; no manual step is required. The build is driven by
android/build.gradle, which invokes CMake (src/CMakeLists.txt) with the
Android NDK for each target ABI. To build the example app:
cd example
flutter run # or: flutter build apk
Libraries
- mypaint_ffi
- Dart wrapper around libmypaint for Flutter.
- mypaint_ffi_bindings_generated