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.