Blendend.Draw (blendend v0.2.0)

View Source

This module contains macros for writing blendend drawings as Elixir code.

You typically use this module in a script, IEx, or a web playground and then drive everything through draw/2 or draw/3:

use Blendend.Draw

draw 400, 300, "priv/rect.png" do
  rect 40.0, 40.0, 320.0, 220.0, fill: rgb(255, 255, 255)
end

What draw/... does

A draw/2 or draw/3 call:

  • creates a new Blendend.Canvas of the given size
  • stores it as the current canvas in the calling process,
  • executes a block, where helpers like rect/..., circle/..., text...
  • finally encodes the image via: Blendend.Canvas.to_png_base64/1. (draw/2) Blendend.Canvas.save/2. (draw/3) The return value is whatever Blendend.Canvas.to_png_base64/1 returns (usually {:ok, base64}), which makes it easy to give to a web UI: Examples:
    {:ok, b64} = draw 400, 300 do
               # ...
               end
    
    "data:image/png;base64," <> b64
    # usable as <img src="data:image/png;base64,#{b64}">
    This makes the Blendend.Draw especially convenient for HTTP-streaming setups where we regenerate PNGs on demand.

Process-local state

The current canvas is stored in the process dictionary. Nested draw/2 in the same process will overwrite the previous state.

Shape API

Shape helpers (rect/4, circle/3, polygon/2, etc.) default to filling. Use fill: color/gradient/pattern to set the fill. To stroke instead, pass mode: :stroke or supply stroke-specific options (:stroke with a color/gradient/pattern, plus :stroke_width, :stroke_cap, etc.).

Summary

Functions

Draws a stroked elliptical arc defined by center (cx, cy), radii (rx, ry), start angle, and sweep angle (radians).

Blur a path and composite it onto the current canvas. Wraps Blendend.Effects.blur_path/4; accepts blur options (e.g. :radius, :spread) and style overrides.

Draws a box given corners {x0, y0} and {x1, y1} (fill or stroke).

Draws multiple boxes from a list of {x0, y0, x1, y1} tuples (fill or stroke).

Draws a chord (closed arc) with center (cx, cy), radii (rx, ry), start angle, and sweep (radians).

Draws a circle centered at {cx, cy} with radius r (fill or stroke).

Clears the current canvas with the given options.

Build a conic gradient.

Top–level entry point for Blendend drawings.

Same as draw/3 but saves canvas in a png file.

Draws an ellipse centered at {cx, cy} with radii (rx, ry) (fill or stroke).

Fills a path on the current canvas.

Sets the fill rule for the current canvas (:non_zero or :even_odd).

Returns the current process-local canvas.

Creates a color from HSV components plus alpha (0–255).

Draws a stroked line segment from {x0, y0} to {x1, y1}.

Build a linear gradient.

Loads a font face from the given path and creates a font at the specified size.

Returns the identity matrix.

Build a Blendend.Matrix2D with a tiny DSL.

Creates a fresh Blendend.Path.t/0.

Build a Blendend.Path with a concise DSL.

Draws a pie slice with center (cx, cy), radii (rx, ry), start angle, and sweep (radians).

Draws a polygon (fill or stroke) from a list of {x, y} points.

Draws a stroked polyline from a list of {x, y} points.

Post-Rotates temporarily the current canvas angle (radians) around {cx, cy} while evaluating do block.

Post-Rotates temporarily the current canvas angle (radians) around {cx, cy} while evaluating do block.

Post-Translates temporarily the current canvas transform by {tx, ty} (pixels) for the duration of the block.

Draws a rectangle at {x, y} with width w and height h (fill or stroke).

Draws multiple rects from a list of {x, y, w, h} tuples (fill or stroke).

Draw a rectangle using its center point.

Creates an RGB color (0–255 channels, optional alpha).

Rotates the current canvas transform by angle (radians) around the origin.

Rotates temporarily the current canvas angle (radians) around {cx, cy} while evaluating do block.

Rotates the current canvas transform by angle (radians) around {cx, cy}.

Rotates temporarily the current canvas angle (radians) around {cx, cy} while evaluating do block.

Draws a rounded rectangle (x, y, w, h) with corner radii (rx, ry) (fill or stroke).

Scales the current canvas uniformly by s (both axes).

Scales temporarily the current canvas transform by {sx, sy} for the duration of the block.

Apply a soft shadow (blur + offset) for a path on the current canvas.

Skews the current canvas transform by {sx, sy} (radians) relative to the x/y axes.

Skews temporarily the current canvas by s on both axes (radians) for the duration of the block.

Strokes a path on the current canvas.

Draws UTF-8 text at the given position using a Blendend.Text.Font.

Translates the current canvas transform by {tx, ty} (pixels).

Translates temporarily the current canvas transform by {tx, ty} (pixels) for the duration of the block.

Draws a triangle, equilateral when given a center point and side length.

triangle(x0, y0, x1, y1, x2, y2) – triangle from explicit vertices. Same style opts as Blendend.Canvas.Fill.path/3 or Blendend.Canvas.Stroke.path/3.

Temporarily clip drawing to the rectangle {x, y, w, h} while executing the block.

Temporarily applies a transform to the current canvas while evaluating do block. That means any transform applied inside is rolled back when the block exits. This macro mirrors the typical save / apply / restore pattern

Functions

arc(cx, cy, rx, ry, start_angle, sweep_angle, opts \\ [])

(macro)

Draws a stroked elliptical arc defined by center (cx, cy), radii (rx, ry), start angle, and sweep angle (radians).

Style options match Blendend.Canvas.Stroke.path/3.

blur_path(path, sigma, opts \\ [])

Blur a path and composite it onto the current canvas. Wraps Blendend.Effects.blur_path/4; accepts blur options (e.g. :radius, :spread) and style overrides.

box(x0, y0, x1, y1, opts \\ [])

(macro)

Draws a box given corners {x0, y0} and {x1, y1} (fill or stroke).

Style options match the shape API (:fill/:stroke with color/gradient/pattern, :stroke_width, :comp_op, etc.).

box_array(boxes, opts \\ [])

(macro)

Draws multiple boxes from a list of {x0, y0, x1, y1} tuples (fill or stroke).

Style options match Blendend.Canvas.Fill.path/3 and Blendend.Canvas.Stroke.path/3.

chord(cx, cy, rx, ry, start_angle, sweep_angle, opts \\ [])

(macro)

Draws a chord (closed arc) with center (cx, cy), radii (rx, ry), start angle, and sweep (radians).

Style options match the shape API.

circle(cx, cy, r, opts \\ [])

(macro)

Draws a circle centered at {cx, cy} with radius r (fill or stroke).

Style options match the shape API.

clear(opts)

(macro)

Clears the current canvas with the given options.

Wraps Blendend.Canvas.clear/2; common options include fill: color/gradient/pattern.

conic_gradient(cx, cy, angle, list)

(macro)

Build a conic gradient.

conic_gradient cx, cy, angle do
  add_stop 0.0, rgb(255, 0, 0)
  add_stop 1.0, rgb(0, 255, 0)
end

draw(w, h, list)

(macro)

Top–level entry point for Blendend drawings.

draw/3 and draw/4 create a new Blendend.Canvas, make it the current canvas for the calling process, execute the given block, and finally encode the canvas as a PNG.

There are two forms:

  • draw width, height do ... end
  • draw width, height, "image.png" do ... end

Basic usage

The simple form creates a canvas, clears it, runs the block, and returns the result of Blendend.Canvas.to_png_base64/1:

iex> {:ok, png_b64} =
...>   draw 400, 300 do
...>     rect 40.0, 40.0, 320.0, 220.0,
...>       fill: rgb(255, 255, 255)
...>   end

Inside the block, other Draw helpers such as rect/5, circle/4, text/4, etc. implicitly use the current canvas via Blendend.Draw.get_canvas/0.

Process-local state

draw/... stores the current canvas in the process dictionary under private keys. This means:

  • the Draw state is scoped to the calling process, and
  • nested draw/... calls in the same process are not supported and will overwrite the previous state.

For typical usage this keeps the call sites concise while avoiding global mutable state.

draw(w, h, file, list)

(macro)

Same as draw/3 but saves canvas in a png file.

ellipse(cx, cy, rx, ry, opts \\ [])

(macro)

Draws an ellipse centered at {cx, cy} with radii (rx, ry) (fill or stroke).

Style options match the shape API.

fill_path(path, opts \\ [])

(macro)

Fills a path on the current canvas.

Style options mirror Blendend.Canvas.Fill.path/3 (:fill with color/gradient/pattern, plus :alpha, :comp_op, etc.).

fill_rule(rule)

(macro)

Sets the fill rule for the current canvas (:non_zero or :even_odd).

Wraps Blendend.Canvas.set_fill_rule/2.

font_create(face, size)

(macro)

Convenience macro for Blendend.Text.Font.create!/2.

font_face(path)

(macro)

Convenience macro for Blendend.Text.Face.load!/1.

get_canvas()

Returns the current process-local canvas.

Raises if no canvas is active (use draw/3 to establish one).

hsv(h, s, v, a \\ 255)

(macro)

Creates a color from HSV components plus alpha (0–255).

h in degrees (0–360), s and v as 0.0–1.0 floats, a as 0–255. Convenience for Blendend.Style.Color.from_hsv/4.

Forms:

  • hsv(h, s, v, a \ 255)

line(x0, y0, x1, y1, opts \\ [])

(macro)

Draws a stroked line segment from {x0, y0} to {x1, y1}.

Style options match Blendend.Canvas.Stroke.path/3 (:stroke, :stroke_width, :stroke_cap, etc.).

linear_gradient(x0, y0, x1, y1, list)

(macro)

Build a linear gradient.

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

load_font(path, size)

(macro)

Loads a font face from the given path and creates a font at the specified size.

Returns the font or raises on error.

matrix()

(macro)

Returns the identity matrix.

matrix(list)

(macro)

Build a Blendend.Matrix2D with a tiny DSL.

m =
  matrix do
    translate 40, 90
    rotate :math.pi() / 3
    skew 0.1, 0.0
    scale 1.2, 0.8
  end

Forms:

  • matrix() – returns identity
  • matrix do ... end – identity then applies DSL ops in order

path()

(macro)

Creates a fresh Blendend.Path.t/0.

path(list)

(macro)

Build a Blendend.Path with a concise DSL.

p =
  path do
    move_to 0, 0
    line_to 20, 0
    line_to 20, 10
  end

badge =
  path badge do
    add_round_rect(20, 20, 140, 80, 12, 12)
    add_circle(60, 60, 18)
    add_line(20, 20, 160, 100)
  end

Forms:

  • path do ... end – returns a new Blendend.Path with the given commands.
  • path name do ... end – same, but also binds the path to name in the caller.

What it does:

  • creates a fresh Blendend.Path (Path.new!)
  • rewrites DSL calls (move_to/2, line_to/2, add_*, etc.) to Blendend.Path.*!/… against that path (no reliance on var!/1)

path(var_ast, list)

(macro)

pie(cx, cy, rx, ry, start_angle, sweep_angle, opts \\ [])

(macro)

Draws a pie slice with center (cx, cy), radii (rx, ry), start angle, and sweep (radians).

Style options match the shape API.

polygon(points, opts \\ [])

(macro)

Draws a polygon (fill or stroke) from a list of {x, y} points.

Style options match Blendend.Canvas.Fill.path/3 and Blendend.Canvas.Stroke.path/3 (e.g. fill: color/gradient/pattern, stroke: color/gradient/pattern, :stroke_width, :comp_op).

polyline(points, opts \\ [])

(macro)

Draws a stroked polyline from a list of {x, y} points.

Style options match Blendend.Canvas.Stroke.path/3 (:stroke, :stroke_width, :stroke_cap, etc.).

post_rotate(angle, list)

(macro)

Post-Rotates temporarily the current canvas angle (radians) around {cx, cy} while evaluating do block.

post_rotate(angle, cx, cy, list)

(macro)

Post-Rotates temporarily the current canvas angle (radians) around {cx, cy} while evaluating do block.

post_translate(tx, ty, list)

(macro)

Post-Translates temporarily the current canvas transform by {tx, ty} (pixels) for the duration of the block.

radial_gradient(cx0, cy0, r0, cx1, cy1, r1, list)

(macro)

Build a radial gradient.

radial_gradient cx0, cy0, r0, cx1, cy1, r1 do
  add_stop 0.0, rgb(255, 255, 0)
  add_stop 1.0, rgb(0, 0, 0)
end

rect(x, y, w, h, opts \\ [])

(macro)

Draws a rectangle at {x, y} with width w and height h (fill or stroke).

Style options match the shape API.

rect_array(rects, opts \\ [])

(macro)

Draws multiple rects from a list of {x, y, w, h} tuples (fill or stroke).

Style options match Blendend.Canvas.Fill.path/3 and Blendend.Canvas.Stroke.path/3.

rect_center(cx, cy, w, h, opts \\ [])

(macro)

Draw a rectangle using its center point.

Mirrors p5.js rectMode(CENTER): (cx, cy) is the center; w/h are size.

rgb(atom)

(macro)

Creates an RGB color (0–255 channels, optional alpha).

Convenience for Blendend.Style.Color.rgb!/4.

Forms:

  • rgb(r, g, b, a \ 255)
  • rgb(:random) for an opaque random color

rgb(r, g, b, a \\ 255)

(macro)

rotate(angle)

(macro)

Rotates the current canvas transform by angle (radians) around the origin.

rotate(angle, list)

(macro)

Rotates temporarily the current canvas angle (radians) around {cx, cy} while evaluating do block.

rotate(angle, cx, cy)

(macro)

Rotates the current canvas transform by angle (radians) around {cx, cy}.

rotate(angle, cx, cy, list)

(macro)

Rotates temporarily the current canvas angle (radians) around {cx, cy} while evaluating do block.

round_rect(x, y, w, h, rx, ry, opts \\ [])

(macro)

Draws a rounded rectangle (x, y, w, h) with corner radii (rx, ry) (fill or stroke).

Style options match the shape API.

scale(sx, sy)

(macro)

Scales the current canvas uniformly by s (both axes).

scale(sx, sy, list)

(macro)

Scales temporarily the current canvas transform by {sx, sy} for the duration of the block.

shadow_path(path, dx, dy, sigma, opts \\ [])

Apply a soft shadow (blur + offset) for a path on the current canvas.

skew(kx, ky)

(macro)

Skews the current canvas transform by {sx, sy} (radians) relative to the x/y axes.

skew(kx, ky, list)

(macro)

Skews temporarily the current canvas by s on both axes (radians) for the duration of the block.

stroke_path(path, opts \\ [])

(macro)

Strokes a path on the current canvas.

Style options mirror Blendend.Canvas.Stroke.path/3 (:stroke with color/gradient/pattern, plus :stroke_width, caps/joins, :comp_op, etc.).

text(font, x, y, string, opts \\ [])

(macro)

Draws UTF-8 text at the given position using a Blendend.Text.Font.

Supports both fill and stroke modes (auto-detected via options or mode: :fill | :stroke). Common options: fill: color/gradient/pattern, stroke: color/gradient/pattern, stroke_width, stroke_cap, stroke_join, alpha (in fill mode), stroke_alpha, etc.

translate(tx, ty)

(macro)

Translates the current canvas transform by {tx, ty} (pixels).

translate(tx, ty, list)

(macro)

Translates temporarily the current canvas transform by {tx, ty} (pixels) for the duration of the block.

triangle(cx, cy, side, opts \\ [])

(macro)

Draws a triangle, equilateral when given a center point and side length.

triangle(cx, cy, side) – builds an equilateral triangle centered at {cx, cy}, pointing up, with edge length side.
Same style opts as Blendend.Canvas.Fill.path/3 or Blendend.Canvas.Stroke.path/3.

triangle(x0, y0, x1, y1, x2, y2, opts \\ [])

(macro)

triangle(x0, y0, x1, y1, x2, y2) – triangle from explicit vertices. Same style opts as Blendend.Canvas.Fill.path/3 or Blendend.Canvas.Stroke.path/3.

with_clip(x, y, w, h, list)

(macro)

Temporarily clip drawing to the rectangle {x, y, w, h} while executing the block.

This wraps Canvas.save_state/1, Canvas.Clip.to_rect/5, then restores state after the block (even if it raises).

with_transform(matrix_ast, list)

(macro)

Temporarily applies a transform to the current canvas while evaluating do block. That means any transform applied inside is rolled back when the block exits. This macro mirrors the typical save / apply / restore pattern:

  • saves the current context state (Canvas.save_state/1),
  • applies the given matrix via Canvas.apply_transform/2,
  • executes the body,
  • restores the previous state with Canvas.restore/1, even if an error is raised inside the block.

matrix_ast should evaluate to a Blendend.Matrix2D value.

Examples

 m = Blendend.Matrix2D.identity!()
     |> Blendend.Matrix2D.rotate!(:math.pi() / 4)

 with_transform m do
   text f, 80, 80, "Elixir is awesome!"
 end