Operator SDK
Build MIDI processing and UI modes for the Operator device
Loading...
Searching...
No Matches
draw.h File Reference

Convenience wrappers over the display draw API (opt-in, header-only). More...

#include <cstdint>
#include <operator_sdk/abi/mode_api.h>

Namespaces

namespace  op
 Root namespace for the Operator SDK.
namespace  op::draw
 Screen drawing primitives for mode UIs: rectangles, text, and bitmaps.

Functions

void op::draw::draw_rect (int x, int y, int w, int h)
 Draw a 1px rectangle outline.
void op::draw::fill_rect (int x, int y, int w, int h, bool on)
 Fill or clear a rectangle.
void op::draw::draw_text (int x, int y, const char *text)
 Draw a NUL-terminated string in the standard 5x7 font.
void op::draw::draw_text_large (int x, int y, const char *text)
 Draw a NUL-terminated string in the large 8x12 font.
void op::draw::draw_bitmap (int x, int y, const uint8_t *data, int w, int h)
 Blit a 1bpp bitmap.
void op::draw::set_pixel (int x, int y, bool on)
 Plot or clear a single pixel.

Detailed Description

Convenience wrappers over the display draw API (opt-in, header-only).

Include on demand. This header is deliberately not pulled in by the umbrella operator_sdk.h.

Why this exists

The raw display entries on OperatorApi (draw_rect, fill_rect, draw_text, draw_text_large, draw_bitmap, set_pixel) take uint16_t coordinate and dimension parameters. In mode UI code a coordinate is almost always an expression (y + 8, x - 2, origin + span_w / 2), and C++ integer promotion makes every such expression a 32-bit int. Passing an int to a uint16_t parameter is a narrowing conversion, so you would end up writing static_cast<uint16_t>(y + 8) at every single call-site adding unnecessary noise.

These wrappers take int for every coordinate/dimension parameter and forward to the matching raw op::api->... entry, performing the narrowing once, in one audited place (detail::u16). The result is behaviorally identical to the per-call-site cast. On the Cortex-M33 the arithmetic runs in 32-bit registers regardless, and the only narrowing is the store into the 16-bit ABI parameter, which happens either way.

Coordinates

The screen is 128x64, so valid coordinates are small: x in [0, 127] and y in [0, 63]. Each argument is truncated to the uint16_t the draw ABI uses, exactly as static_cast<uint16_t>(expr) would, so every in-range draw is lossless. The firmware also bounds-checks and no-ops off-screen pixels.

The ABI itself is unchanged: mode_api.h still declares uint16_t parameters. The raw op::api->... pointers remain fully usable, and these wrappers are pure supplements.

Usage

...
op::draw::draw_text(kLabelX, y + 2, label); // no cast
op::draw::fill_rect(x - 2, y + 8, 5, 1, /*on=*/true); // no cast
Convenience wrappers over the display draw API (opt-in, header-only).
void fill_rect(int x, int y, int w, int h, bool on)
Fill or clear a rectangle.
Definition draw.h:90