Skip to content

Latest commit

 

History

History
276 lines (184 loc) · 8 KB

File metadata and controls

276 lines (184 loc) · 8 KB

P5 Drawing Library

P5 is a drawing library inspired by Processing and p5.js. It wraps DVI::Graphics with a stateful API for fill/stroke colors, coordinate transforms, blend modes, and text layout.

Ruby API

Module: P5

P5 provides a high-level drawing API on top of DVI::Graphics. Creating a P5 instance switches the display to graphics mode and initializes drawing state (fill white, stroke white, 8x8 font, identity transform).

require "p5"
p5 = P5.new
p5.background(0x00)
p5.fill(p5.color(200, 0, 0))
p5.stroke(0xFF)
p5.circle(160, 120, 50)
p5.text_font(DVI::Graphics::FONT_MPLUS_12)
p5.text("Hello!", 10, 10)
p5.commit

P5.new

Creates a new P5 instance and switches to graphics mode.

P5#width -> Integer

Returns the current framebuffer width in pixels (640 or 320).

P5#height -> Integer

Returns the current framebuffer height in pixels (480 or 240).

P5#background(color)

Fills the entire framebuffer with the given RGB332 color.

P5#commit

Waits for VBlank and copies the back buffer to the front buffer for display. Call this once per frame after all drawing is complete.

P5#fill(color)

Sets the fill color for subsequent shape drawing and enables fill.

P5#no_fill

Disables fill for subsequent shape drawing.

P5#stroke(color)

Sets the stroke (outline) color for subsequent shape drawing and enables stroke.

P5#no_stroke

Disables stroke for subsequent shape drawing.

P5#stroke_weight(w)

Sets the stroke thickness in pixels. Affects line, triangle outlines, and thick lines. Negative values are clamped to 0.

P5#blend_mode(mode)

Sets the pixel compositing mode. Available modes:

Constant Effect
P5::REPLACE Overwrite (default)
P5::ADD Saturating add per channel
P5::SUBTRACT Saturating subtract per channel
P5::MULTIPLY Multiply per channel
P5::SCREEN Screen blend per channel

P5#alpha(value)

Sets alpha blend mode with the given opacity (0-255, clamped). Switches to alpha blending automatically.

P5#text_font(font, wide_font = nil)

Sets the font for text rendering. Pass a second font for CJK (wide) character support via Unicode-to-JIS lookup.

P5#text_color(color)

Sets the color for text rendering.

P5#text_align(horizontal, vertical = :top)

Sets text alignment. Horizontal: :left, :center, :right. Vertical: :top, :center, :bottom.

P5#text_leading(pixels)

Sets extra line spacing in pixels (added to font glyph height).

P5#text_width(str) -> Integer

Returns the pixel width of a string rendered with the current font.

P5#point(x, y)

Draws a single pixel at (x, y) using the stroke color.

P5#line(x0, y0, x1, y1)

Draws a line from (x0, y0) to (x1, y1) using the stroke color.

P5#rect(x, y, w, h)

Draws a rectangle at (x, y) with size (w, h). Fills with fill color, outlines with stroke color. Under rotation, decomposed into two triangles.

P5#circle(cx, cy, r)

Draws a circle centered at (cx, cy) with radius r. Under non-uniform scale, rendered as an ellipse.

P5#ellipse(cx, cy, rx, ry)

Draws an ellipse centered at (cx, cy) with radii (rx, ry).

P5#triangle(x0, y0, x1, y1, x2, y2)

Draws a triangle with the given vertices.

P5#arc(cx, cy, r, start_angle, stop_angle)

Draws a pie-slice arc centered at (cx, cy) with radius r. Angles are in radians (0 = right, PI/2 = down). Rendered as a triangle fan in C using hardware sinf/cosf.

P5#bezier(x1, y1, x2, y2, x3, y3, x4, y4)

Draws a cubic bezier curve from (x1, y1) to (x4, y4) with control points (x2, y2) and (x3, y3). Rendered as 20 line segments.

P5#curve(x1, y1, x2, y2, x3, y3, x4, y4)

Draws a Catmull-Rom spline through (x2, y2) to (x3, y3), shaped by (x1, y1) and (x4, y4). Rendered as 20 line segments.

P5#text(str, x, y)

Draws a UTF-8 string at (x, y). Position is adjusted by text_align. Coordinate transforms apply to the position (translation only for text).

P5#translate(tx, ty)

Translates the coordinate system by (tx, ty).

P5#rotate(angle)

Rotates the coordinate system by angle (in radians).

P5#scale(sx, sy = sx)

Scales the coordinate system. Pass one argument for uniform scale.

P5#push_matrix

Saves the current transform matrix to the stack. The stack is capped at P5::MATRIX_STACK_MAX (32) entries and raises if exceeded, to catch unbalanced push/pop loops before they exhaust memory.

P5#pop_matrix

Restores the transform matrix from the stack.

P5#reset_matrix

Resets the transform matrix to identity.

P5#color(r, g, b) -> Integer

Converts RGB values (0-255) to an RGB332 color byte.

P5#image(data, x, y, w, h)

Blits an RGB332 image (byte string) at position (x, y).

Architecture

State Management

P5 holds all drawing state as Ruby instance variables. The C layer (DVI::Graphics) is stateless: every drawing function receives the framebuffer pointer, width, height, and color as arguments. The only C-side state is the blend mode (global, set via dvi_graphics_set_blend_mode).

Coordinate Transforms

Transforms are implemented entirely in Ruby using a 2x3 affine matrix. Drawing functions check translate_only? for a fast path (integer addition only) and fall back to full matrix multiplication for rotation and scale.

For rotated rectangles, the four corners are transformed and rendered as two fill_triangle calls plus four line segments. For scaled circles, the matrix scale factors are extracted and the circle is rendered as an ellipse via fill_ellipse.

Double Buffering

At 640x480, the back buffer is in PSRAM (307 KB). At 320x240, the back buffer uses the second half of the SRAM framebuffer (76.8 KB), providing fast SRAM-to-SRAM copies. commit waits for VBlank, then copies the back buffer to the front buffer.

Blend Pipeline

Drawing functions dispatch to REPLACE-only or blend-aware paths. The REPLACE path uses fill_span (inlined to memset) and plot_pixel (direct store). The blend path uses blend_span with per-mode optimized loops that pre-extract constant source channels outside the pixel loop.

Source Files

File Description
rootfs/lib/p5.rb P5 Ruby class
dvi_graphics_draw.c Shape primitives (rect, circle, ellipse, triangle, arc, line)
dvi_graphics_text.c Text rendering and measurement
dvi_graphics_draw.h C drawing API declarations
dvi.c Ruby bindings for DVI::Graphics

References

  • Processing: Creative coding environment (original inspiration)
  • p5.js: JavaScript port of Processing