Impeller is a 2D vector graphics renderer used in Flutter. Impeller can also be used standalone (without flutter) with its C API. This crate provides a safe rust wrapper around the C API (and also the raw bindings).
- draw 2D shapes like paths (lines/curvies), rectangles, circles, etc.
- draw AND layout text.
- draw effects like blurs, shadows, color blending etc.
- clipping using any shape.
- UI libraries are the best use-case.
- 2D games? easy to embed Impeller into any opengl/vk/metal app.
The docs and examples of this crate are good enough for really basic drawing (eg: drawing a rect). But this is nowhere enough for real world usage. They will tell you how to use a object, but now why or where you would use this.
For example, pretty much NONE of the enums are documented. We will slowly improve the situation, but until then, the below resources should help cover the gaps. Most rust item docs will also contain direct links to their counterparts in dart/skiasharp/react-native-skia.
Impeller is actually designed for dart/flutter, so, it is the best place to find documentation. Most of the object and function names are same in rust/dart, so you can easily translate the docs from dart to rust. eg: StrokeCap Enum.
Some names are different though. DisplayListBuilder is the combination of PictureRecorder and Canvas items in dart. DisplayList is Picture in dart.
It also has the best explanation for BlendMode with lots of pictures.
One jpeg screenshot is worth a thousand words of text documentation. - Albert Einstein
Technically, this is documenting Skia. But both Impeller and Skia have such a large overlap in terminology, design and functionality that a lot of learning transfers over seamlessly.
It also provides a lot of images showing the different options (eg: MaskFilters Blur).
Again, skia. But lots of guide-level docs for people who are starting out with Vector graphics.
- Blazingly? Fast - It is used in Flutter, so, you know it will be maintained and improved continuously. The focus is also on consistency to keep everything running smooth.
- Great text rendering AND layout - The rust ecosystem is severely lacking when it comes to text. Impeller should cover most of your needs.
- Simple Object Model: The object model is very simple and takes like 5 minutes to learn. see Object Model
- Easy to Embed - Any (opengl/vk/mtl)-based app/game can embed Impeller in less than 10 lines.
- Fast compilation - The only bottleneck is network speed to download the prebuilt libs.
And even that can be amortized with the
cache_libsfeature. see Features - Easy Bindings - The C API is really easy and allows us to "auto-generate" bindings. So, if we are trying to generate lua or wasm bindings, this is a huge QoL feature.
- Impeller is written in C++ and we do not support building from source. We use pre-built static/shared libraries instead.
- No support for d3d and no fallback software renderer.
- No powerful features like custom shaders. use Skia-rs instead.
- As the bindings are not widely used yet, we may still have some bugs.
For libraries who are just "using" the API, all you need to do is just use the crate with no features.
The final binary/executable should enable the prebuilt_libs feature to download the prebuilt libraries from github releases and link them.
NOTE: We use curl to download and tar (or unzip on linux) to extract the archives. linux, mac and windows (10+) will have these by default.
prebuilt_libs- Downloads the prebuilt libraries from github releases and links them to your project.static_link- If enabled, we will link static libraries. only available on linux/windows. All other platforms will need to use shared libraries or provide their own (see Custom Linking).debug_static_link- If enabled, we will use the unstripped static libs with debug info (useful for debugging). only available on linux/windows just likestatic_link.cache_libs- If enabled, we will cache the prebuilt-libs in.impeller_cachedirectory inside your project directory (parent dir oftarget). Add/.impeller_cacheto.gitignore, if you enable this feature.- You can customize cache directory path with
IMPELLER_CACHE_DIRenv variable. And also use this to provide your own custom built libs. - caching avoids redownloading after
cargo cleansaving bandwidth and this in turns also makes the builds faster. - You also get to inspect the downloaded archives in the cache to debug any errors.
- You can customize cache directory path with
I try to keep the bindings sound, but graphics programming is just really really unsafe. Especially around the handling of context/surface lifetimes.
Objects like textures/contexts are inherently linked to platform resources (like openGL context or vulkan device). So, they must ALL be destroyed before you destroy the underlying window or opengl context. That is the sole reason creating them is unsafe.
When you want to link in your own custom impeller library:
- Enable
cache_libsfeature to make it use libraries from a cached directory. - set
IMPELLER_CACHE_DIRenvironment variable to manually set the location of the cache directory. - Inside that directory, create
targetos_targetarch(eg:linux_x64) directory for dynamic libs andtargetos_targetarch_static_profile(eg:linux_x64_static_release) directory for static libs. - depending on the features
static_linkanddebug_static_linkyou might need to createtargetos_targetarch_static_debugdirectory, build script will search for dynamic libs or release static libs or debug static libs (useful for debugging).