Skip to content

P5

P5 is a Processing / p5.js-style drawing DSL. It wraps FmrbGfx internally and lets you draw shapes in a p5 style with stateful fill / stroke / translate / rotate and more. P5 is built into picoruby-fmrb-app, so no additional require is needed.

Usage

class MyApp < FmrbApp
  def on_create
    @p5 = P5.new(@gfx)
  end

  def on_update
    @p5.background(P5::BLACK)
    @p5.fill(P5::RED)
    @p5.no_stroke
    @p5.rect(10, 10, 60, 40)
    @p5.present
    33
  end
end

MyApp.new.start

Construction

P5.new(gfx)

Argument: FmrbApp#@gfx (a FmrbGfx instance). Store it in your subclass as @p5 = P5.new(@gfx).

Screen

Method Purpose
width Canvas width
height Canvas height
background(color) Fill the entire screen with color
present (alias: commit) Apply the frame to the screen

Color Constants

Mirrors of FmrbGfx::* (RGB332).

P5::BLACK / WHITE / RED / GREEN / BLUE / YELLOW / CYAN / MAGENTA / GRAY

Custom colors can be specified with P5#color(r, g, b) (which calls FmrbGfx.rgb_to_332 internally) or directly as an RGB332 integer.

Drawing State

Method Purpose
fill(color) / no_fill Fill color / disable fill
stroke(color) / no_stroke Stroke color / disable stroke
stroke_weight(w) Stroke width (>1 is implemented with parallel lines)
blend_mode(mode) Blend mode (see below)

Blend Mode

Constants provided: P5::REPLACE / P5::ADD / P5::XOR / P5::SUBTRACT / P5::MULTIPLY / P5::SCREEN.

Blend mode limitations

The backend only supports REPLACE / ADD / XOR, and these only take effect on rectangle fills (rect(), background()). Other shapes and SUBTRACT / MULTIPLY / SCREEN fall back to REPLACE behavior.

Basic Shapes

Method Signature
point(x, y) Single pixel (uses stroke color)
line(x0, y0, x1, y1) Line
rect(x, y, w, h) Rectangle (fill + stroke)
circle(cx, cy, r) Circle
ellipse(cx, cy, rx, ry) Ellipse
triangle(x0, y0, x1, y1, x2, y2) Triangle
arc(cx, cy, r, start, stop) Arc (angles in radians)
bezier(x1, y1, x2, y2, x3, y3, x4, y4) Cubic Bezier (subdivided into 20 line segments)
curve(x1, y1, x2, y2, x3, y3, x4, y4) Catmull-Rom spline

Arc mode

The p5.js OPEN / CHORD / PIE modes are not supported. Arcs are always drawn as a combination of pie shape (fill_arc) and outer ring (draw_arc).

Affine Transforms

Uses the same post-multiply composition as p5.js / Processing (M' = M * op). translate(tx, ty); rotate(theta); rect(-30,-20,60,40) produces the standard behavior of rotating around the local origin after translation.

Method Purpose
translate(tx, ty) Translation
rotate(angle) Rotation (radians)
scale(sx, sy = sx) Scaling
push_matrix / pop_matrix Save / restore the matrix
reset_matrix Reset to the identity matrix

When the matrix contains only translations, a fast path is used. When rotation or scaling is involved, it switches to a slower path with triangle decomposition.

Text

Method Purpose
text_font(font, wide_font = nil) Switch font. :default / :ja, 8 / :ja, 12
text_color(color) Text color
text_align(h, v = :top) Alignment. h: :left / :center / :right, v: :top / :center / :bottom
text_leading(pixels) Line spacing (state only; \n is not supported)
text_width(str) Drawing width of a string (assumes fixed-width)
text(str, x, y) Draw text

For Japanese fonts, see FmrbGfx > Japanese Text.

@p5.text_font(:ja, 12)
@p5.text_color(P5::BLACK)
@p5.text_align(:center, :center)
@p5.text("こんにちは", @p5.width / 2, @p5.height / 2)

Image

Method Purpose
image(image_id, x, y, scale_x = 1.0, scale_y = 0.0) Draw an image obtained via FmrbGfx#create_image_from_file. When scale_y = 0.0, it uses the same value as scale_x
image_masked(image_id, mask_data, x, y, w, h) Draw with a 1bpp mask

Pixel Operations

Method Purpose
set_pixel(x, y, color) Direct pixel write
get_pixel(x, y) Read back a pixel (slow due to round-trip to WROVER side)

get_pixel cost

get_pixel is a synchronous UART call that flushes all unsent drawing commands, reads on the WROVER side, and returns the result. Each pixel retrieval takes several milliseconds, so avoid calling it in loops. Maintaining a local 2D array of drawing state is much faster than per-pixel reads.

Example

class P5Spinner < FmrbApp
  def on_create
    @p5 = P5.new(@gfx)
    @angle = 0.0
  end

  def on_update
    @p5.background(P5::BLACK)
    cx = @p5.width / 2
    cy = @p5.height / 2

    @p5.push_matrix
    @p5.translate(cx, cy)
    @p5.rotate(@angle)
    @p5.fill(P5::CYAN)
    @p5.no_stroke
    @p5.rect(-20, -20, 40, 40)
    @p5.pop_matrix

    @p5.present
    @angle += 0.1
    33
  end
end

P5Spinner.new.start

A sample that switches between features (basic shapes / affine transforms / Bezier / text / arcs / blend / get_pixel) is available in /app/demo/p5_test.app.rb.

  • FmrbGfx -- The internal wrapper. Accessible via P5#@gfx
  • Sprite -- Lower-level drawing and performance-oriented API
  • Examples -- Demo app list including p5_test