blendend

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

Requirements

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.3"}
  ]
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:

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))

Gallery

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