blendend

View Source

blendend brings Blend2D's fast, high-quality 2D vector renderer to Elixir. It gives you crisp antialiased shapes, gradients, text, and blending through an Elixir API that calls Blend2D directly via NIFs. The project is still evolving.

blendend logo

Features

  • Canvas API: fill/stroke shapes, work with paths, transforms, and compositing.
  • Text handling and layout: load fonts, measure text, and draw crisp glyphs.
  • Gradients, patterns, blur effects, and masks.
  • Expressive drawing DSL and macros for comfortable sketching.
  • Headless rendering for charts/reports (matplotlib AGG–style) and generative art (p5.js–style).
  • Built for speed via Blend2D.

Requirements

  • The latest Blend2D built and installed on your system.
  • A C++ toolchain (a C++ compiler + cmake).

Quick build of Blend2D (tested only on Linux):

git clone https://github.com/blend2d/blend2d
cd blend2d
git clone https://github.com/asmjit/asmjit 3rdparty/asmjit
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install

Install in your project

def deps do
  [
    {:blendend, "~> 0.1.0"}
  ]
end

Then:

mix deps.get
mix compile

Quick start

blendend is meant to feel like a sketchbook: open a canvas, put shapes here and there, get pixels back. The Blendend.Draw macros keep things terse so you can focus on shapes and color rather than boilerplate.

Below, we draw a single white line and write it to disk. Change the block to add circles, text, gradients, or any of the other helpers in Blendend.Draw.

use Blendend.Draw

draw 200, 200, "priv/basic_line.png" do
  line 0, 100, 200, 100, stroke: rgb(255, 255, 255)
end

Roadmap

Most of Blend2D's functionality is exposed. Remaining work:

  • Multi-threaded drawing pipelines are not supported yet; rendering runs single-threaded for now.
  • Gradient transformations and extend modes are planned so gradients can be positioned and repeated more flexibly.
  • More documentation and examples (the blendend_playground covers many cases).

Playground

For a richer starting point, clone the blendend_playground repo and run it to browse and tweak the bundled examples in the browser.

Overview

In blendend you describe colors, gradients, shapes, shadows, and transforms directly; the DSL aims to stay declarative and keep style local to each shape.

Colors

hsv(0, 1.0, 1.0)        # gives red
hsv(0, 1.0, 1.0, 0)     # fully transparent
rgb(255, 255, 0)        # yellow
rgb(255, 255, 0, 150)   # shaded yellow

Gradient

grad2 =
  linear_gradient 0, 0, 0, 200 do
    add_stop(0.0, rgb(255, 0, 0))
    add_stop(0.5, rgb(0, 255, 0))
    add_stop(1.0, rgb(0, 0, 255))
  end

box(0, 0, 100, 200, fill: grad2)

Colors change gradually in a box.

Transformation

# Calculate transformation
 m =
  matrix do
    translate(100, 100)
    rotate(:math.pi() / 4)
  end

# Construct a path
path p1 do
  move_to 0.0, 0.0
  line_to 100.0, 100.0
end
  
# Apply transformation. 
with_transform m do
  stroke_path p1, stroke: rgb(0, 0, 0), stroke_width: 5.0    
end

# Decorate with shadow.
shadow_path(p1, 10.0, 8.0, 15.0, fill: rgb(250, 0, 0, 150))
Vector tracing
Vector tiger head with dynamic strokes
Blur effect
Layered flower waves with blur
Color blending
Grid of gradients with burn blend
Path flattening
iex with noisy outlines
Glyph Bounds
Glyph bounds

Licenses

  • This project is released under the MIT License (see LICENSE).
  • blend2d is licensed under the zlib license.
  • priv/fonts/Alegreya-Regular.otf is distributed under the SIL Open Font License.
  • The burn grid demo and flower waves (which are available in blendend_playground) are adapted from takawo's original p5.js sketch (https://openprocessing.org/user/6533) and shared under the Creative Commons BY-NC-SA 3.0 license (https://creativecommons.org/licenses/by-nc-sa/3.0/).