Antialiased 2D vector drawing library in Rust for Android, Web, Desktop

Overview

nonaquad

Vector anti-aliased graphics renderer for Android, WASM, Desktop in Rust, using miniquad.

This library started as a port of NanoVG for miniquad. Use this library if you want to draw graphics for a quick experiment (game, paint app, etc.) or if you want to build other libraries on top (e.g. UI library.)

Notice

2022-02-18

I think this library is not good enough yet. I haven't worked on it for a while and not sure when I'll be able to again. I'm working on another app for note taking and wellbeing that I'd like to spend most of my time on.

I have a plan of making a very easy developer UI experience and interface for nona. However, at the moment I think it may be a mistake picking this library, unless you'd like to be a main contributor and help develop it further.

This said, please read below and see if any of the goals and ideas resonate with you:

Goals

  • small and fast executables for mobile, desktop and web.
  • safety
  • high-quality drawing: anti-aliasing in shaders, squircles, gradients, fast blur
  • 1-step or straight-forward build on all platforms
  • ease-of-use
  • minimal dependencies

Supported platforms - same as miniquad:

OS Platform
Windows OpenGl 3
Linux OpenGl 3
macOS OpenGL 3
iOS GLES 3
WASM WebGl1 - tested on ios safari, ff, chrome
Android GLES3

Not supported, but desirable platforms

  • Android, GLES2 - work in progress.
  • Metal

Example

Located in nonaquad/examples.

Start with: cargo run --example drawaa

nona.begin_path();
nona.rect((100.0, 100.0, 300.0, 300.0));
nona.fill_paint(nona::Gradient::Linear {
    start: (100, 100).into(),
    end: (400, 400).into(),
    start_color: nona::Color::rgb_i(0xAA, 0x6C, 0x39),
    end_color: nona::Color::rgb_i(0x88, 0x2D, 0x60),
});
nona.fill().unwrap();

let origin = (150.0, 140.0);
nona.begin_path();
nona.circle(origin, 64.0);
nona.move_to(origin);
nona.line_to((origin.0 + 300.0, origin.1 - 50.0));
nona.stroke_paint(nona::Color::rgba(1.0, 1.0, 0.0, 1.0));
nona.stroke_width(3.0);
nona.stroke().unwrap();

nona.end_frame().unwrap();

Screenshots

Screenshots produced from above example.

Windows

Windows

Web

WebGL

WASM size before size stripping 754KB. With basic stripping (see below) 391 KB

Android

APK size: 134KB

iOS

(not yet ready)

Building

Linux

# ubuntu system dependencies
apt install libx11-dev libxi-dev libgl1-mesa-dev

cargo run --example drawaa

Windows

# both MSVC and GNU target is supported:
rustup target add x86_64-pc-windows-msvc
# or
rustup target add x86_64-pc-windows-gnu 

cargo run --example drawaa

WASM

First time setup:

md examples
copy ./nonaquad/examples/index.html ./examples 
rustup target add wasm32-unknown-unknown
npm i -g simplehttpserver

Build and run:

cargo build --example drawaa --target wasm32-unknown-unknown --release
copy ".\target\wasm32-unknown-unknown\release\examples\drawaa.wasm" ".\examples\drawaa.wasm" /y

cd examples
simplehttpserver

Then open http://localhost:8000

To reduce WASM size further

  1. Install binaryen toolkit, then run:
wasm-opt.exe -Os -o drawaa.wasm drawaa.wasm
  1. Run cargo install twiggy and check out the twiggy docs: https://rustwasm.github.io/twiggy/. E.g. you can run twiggy top drawaa.wasm to see where size is used most.
  2. Set environment variable RUSTFLAGS="-C link-arg=--strip-debug". WARNING! This will remove debug info from all cargo build-s. Make sure to revert RUSTFLAGS to "" (empty) after. Twiggy will also not report function details if you strip debug info.
  3. Also check https://rustwasm.github.io/book/reference/code-size.html

Android

Recommended way to build for android is using Docker.
miniquad use slightly modifed version of cargo-apk

Note: on Windows if you see git error during cargo apk build --example drawaa, update your .git folder to be not read-only. See related Docker issue #6016

docker run --rm -v $(pwd)":/root/src" -w /root/src notfl3/cargo-apk cargo apk build --example drawaa
docker run -it -v %cd%":/root/src" -w /root/src notfl3/cargo-apk bash

APK file will be in target/android-artifacts/(debug|release)/apk

With feature "log-impl" enabled all log calls will be forwarded to adb console. No code modifications for Android required, everything just works.

iOS

See build example for miniquad

Roadmap

The goal of nonaquad is to have a stable, high-quality vector library on mobile, web, and desktop from the same source code.

I will use it as a building block for a general purpose cross-platform app framework.

Features

  • anti-aliased lines, circles, rect, rounded rect (signed distance field), curves
  • polygons - convex and concave
  • gradients
  • clipping
  • AA text
  • [Work in progress] image and textures
  • high-quality fast drop shadows and blur
  • gradients - high quality dithered
  • squircles

Architecture

This is how the pieces fit together:

Architecture

Contributing

See TODO-s in source code or anything else goes

License

MIT or APACHE at your convenience

You might also like...
An advanced image processing library for Rust.

ImageProc Maintainers: @chyh1990 Note: this project is under active depvelopment, API may change! imageproc is a advanced image proccessing library fo

Rust library to get image size and format without loading/decoding

imageinfo-rs Rust library to get image size and format without loading/decoding. The imageinfo don't get image format by file ext name, but infer by f

Image operation rust library

Image operation rust library

2D polyline/shape library for offsetting, combining, etc.

This project is a continuation of the C++ CavalierContours library rewritten in Rust with the goal of building out more functionality, better

resvg is an SVG rendering library.

resvg can be used as a Rust library, a C library and as a CLI application to render SVG files based on a static SVG Full 1.1 subset.

A linear algebra and mathematics library for computer graphics.

cgmath-rs A linear algebra and mathematics library for computer graphics. The library provides: vectors: Vector2, Vector3, Vector4 square matrices: Ma

ePaperify: Framebuffer/image pre-processing library for e-Paper displays

ePaperify: Framebuffer/image pre-processing library for e-Paper displays

Screen-capturer: A cross-platform screenshots library for MacOS、Windows、Linux(X11).

Screen-capturer: A cross-platform screenshots library for MacOS、Windows、Linux(X11).

Encoding and decoding images in Rust
Encoding and decoding images in Rust

Image Maintainers: @HeroicKatora, @fintelia How to contribute An Image Processing Library This crate provides basic image processing functions and met

Comments
  • Panic when drawing >222

    Panic when drawing >222

    A panic is thrown out if >222 iterations.

    for i in 0..223 {
                nona.begin_path();
                nona.circle(Point::new(i as f32, 0.), 32.);
                nona.fill_paint(Paint::from(nona::Color::rgb_i(255, 0,0)));
                nona.fill().unwrap();
    }
    
    thread 'main' panicked at 'assertion failed: size <= self.size', /home/sergey/.cargo/registry/src/github.com-1ecc6299db9ec823/miniquad-0.3.0-alpha.37/src/graphics.rs:1715:9
    stack backtrace:
       0: rust_begin_unwind
                 at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/std/src/panicking.rs:493:5
       1: core::panicking::panic_fmt
                 at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/panicking.rs:92:14
       2: core::panicking::panic
                 at /rustc/53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b/library/core/src/panicking.rs:50:5
       3: miniquad::graphics::Buffer::update
                 at /home/sergey/.cargo/registry/src/github.com-1ecc6299db9ec823/miniquad-0.3.0-alpha.37/src/graphics.rs:1715:9
       4: <nvg_miniquad::nvgimpl::Renderer as nona::renderer::Renderer>::flush
                 at ./nonaquad/src/nvgimpl.rs:720:9
       5: nona::context::Context<R>::end_frame
                 at ./nona/src/context.rs:522:9
       6: macroquad_vector_render::amain::{{closure}}
                 at ./src/main.rs:111:9
       7: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
                 at /home/sergey/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/mod.rs:80:19
       8: macroquad::exec::resume
                 at /home/sergey/.cargo/registry/src/github.com-1ecc6299db9ec823/macroquad-0.3.7/src/exec.rs:65:17
       9: <macroquad::Stage as miniquad::event::EventHandlerFree>::draw::{{closure}}
                 at /home/sergey/.cargo/registry/src/github.com-1ecc6299db9ec823/macroquad-0.3.7/src/lib.rs:584:24
      10: <macroquad::Stage as miniquad::event::EventHandlerFree>::draw::maybe_unwind
                 at /home/sergey/.cargo/registry/src/github.com-1ecc6299db9ec823/macroquad-0.3.7/src/lib.rs:575:21
      11: <macroquad::Stage as miniquad::event::EventHandlerFree>::draw
                 at /home/sergey/.cargo/registry/src/github.com-1ecc6299db9ec823/macroquad-0.3.7/src/lib.rs:580:26
      12: miniquad::frame
                 at /home/sergey/.cargo/registry/src/github.com-1ecc6299db9ec823/miniquad-0.3.0-alpha.37/src/lib.rs:272:5
      13: sapp_linux::_sapp_call_frame
                 at /home/sergey/.cargo/registry/src/github.com-1ecc6299db9ec823/sapp-linux-0.1.13/src/lib.rs:2627:13
      14: sapp_linux::_sapp_frame
                 at /home/sergey/.cargo/registry/src/github.com-1ecc6299db9ec823/sapp-linux-0.1.13/src/lib.rs:2639:5
      15: sapp_run
                 at /home/sergey/.cargo/registry/src/github.com-1ecc6299db9ec823/sapp-linux-0.1.13/src/lib.rs:2783:9
      16: miniquad::start
                 at /home/sergey/.cargo/registry/src/github.com-1ecc6299db9ec823/miniquad-0.3.0-alpha.37/src/lib.rs:433:14
      17: macroquad::Window::from_config
                 at /home/sergey/.cargo/registry/src/github.com-1ecc6299db9ec823/macroquad-0.3.7/src/lib.rs:652:9
      18: macroquad::Window::new
                 at /home/sergey/.cargo/registry/src/github.com-1ecc6299db9ec823/macroquad-0.3.7/src/lib.rs:641:9
      19: macroquad_vector_render::main
                 at ./src/main.rs:51:1
      20: core::ops::function::FnOnce::call_once
                 at /home/sergey/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
    note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
    
    
    opened by GeTechG 6
  • Do not store miniquad Context in nonaquad renderer

    Do not store miniquad Context in nonaquad renderer

    This change removes the ownership of miniquad::Context by nonaquad's renderer. This allows the integration of nona and nonaquad in other application as a canvas painting layer.

    See modified drawaa example for the largest API change.

    opened by smokku 3
  • Incorrect paths

    Incorrect paths

    Perhaps I'm doing something wrong, but for some reason the path is not correct.

    my Снимок экрана от 2021-08-26 01-07-49

    Actually, I wrote my own library for converting svg to commands, but I made the commands manually for you.

    code

    nona.move_to(nona::Point::new(1.7442753, 16.985759));
    nona.bezier_to(nona::Point::new(1.7442753, 16.985759),
                       nona::Point::new(-15.181887000000001, 82.239445),
                       nona::Point::new(-15.878773, 83.770915));
    nona.bezier_to(nona::Point::new(-16.575664, 85.302375),
                       nona::Point::new(167.51577, 84.85253300000001),
                       nona::Point::new(42.469333, 65.66409900000001));
    nona.bezier_to(nona::Point::new(11.052757, 60.84321100000001),
                       nona::Point::new(71.785288, 30.93693100000001),
                       nona::Point::new(71.785288, 30.93693100000001));
    

    inkscape Снимок экрана от 2021-08-26 01-08-32 test.svg.zip

    opened by GeTechG 1
  • upgrade to latest miniquad

    upgrade to latest miniquad

    The latest recommended version of miniquad 3.0-alpha has a couple of API changes that breaks nonaquad.

    Specifically, ShaderMeta.images field is no longer &'static [&'static str] but Vec<String>, and UniformBlockLayout.uniforms also went from &'static [(&'static str, UniformType)] to Vec<UniformDesc>, breaks the const shader::META structure.

    opened by joseluis 1
Owner
Nokola
Nokola
Artsy pixel image to vector graphics converter

inkdrop inkdrop is an artsy bitmap to vector converter. Command line interface The CLI binary is called inkdrop-cli and reads almost any image bitmap

Matthias Vogelgesang 62 Dec 26, 2022
Automated image compression for efficiently distributing images on the web.

Imager Apparently this project made it into the GitHub Archive Program. About Imager is a tool for automated image compression, and can competitively

Imager IO 487 Dec 25, 2022
Web-app that simulates different types of color blindness from a user-provided input image.

What is Dalted? Web-app that simulates different types of color blindness from a user-provided input image. Resources The color blindness simulation i

Jorge Carrasco 18 Dec 20, 2022
A Rust library for calculating perceptual hash values of images

img_hash Now builds on stable Rust! (But needs nightly to bench.) A library for getting perceptual hash values of images. Thanks to Dr. Neal Krawetz f

Austin Bonander 264 Dec 9, 2022
A simple steganography library written in rust

steganography A stable steganography library written in rust Crates.io Usage Add the following to the Cargo.toml in your project: [dependencies] stega

Teodor Voinea 79 Dec 9, 2022
Face detection library for the Rust programming language

Rustface SeetaFace detection library for the Rust programming language Example of demo program output SEETAFACE C++ – Github repository for the origin

Andrei Tomashpolskiy 323 Dec 27, 2022
A Simple-to-use, cross-platform Rust Webcam Capture Library

Cross Platform Rust Library for powerful Webcam Capture and Virtual Webcams

null 246 Jan 8, 2023
😱 Dead fast thumbnail library for browser and NodeJs! Built with Rust 🦀 and WebAssembly 🕸

thumbo-core ?? Dead fast thumbnail library for browser and NodeJs Built with Rust ?? & WebAssembly ?? ?? About thumbo-core is a thubnail library for b

Victor Aremu 12 Dec 2, 2022
Rust library for fast image resizing with using of SIMD instructions.

fast_image_resize Rust library for fast image resizing with using of SIMD instructions. CHANGELOG Supported pixel formats and available optimisations:

Kirill Kuzminykh 115 Jan 5, 2023
PNG decoding and encoding library in pure Rust

PNG Decoder/Encoder PNG decoder/encoder in pure Rust. It contains all features required to handle the entirety of the PngSuite by Willem van Schack. p

image-rs 247 Dec 25, 2022