# canvas

A window you draw into every frame, on the GPU: Direct2D shapes, DirectWrite text, WIC pictures. For apps that
should look like nothing else and move at the screen's refresh rate (Anarch Explorer is built on it). Windows only.

```
basher install canvas
```

```python
import canvas

w = canvas.window("Hi", 900, 600)
while canvas.frame(w):                       # waits for the screen's next refresh, then starts a frame
    canvas.clear(w, "#0b0b0d")
    canvas.drag_area(w, 0, 0, canvas.width(w), 40)   # the window has no title bar: say where it drags
    canvas.glow(w, 40, 60, 240, 140, "#e1162b", 16, 24)
    canvas.rect(w, 40, 60, 240, 140, "#1b1b20", 16)
    canvas.text(w, "Hello", 40, 60, 240, 140, 28, "#ffffff", True, align="center")
    if canvas.clicked(w) or canvas.pressed(w, "escape"):
        canvas.close(w)
```

Build with `basher build app.bsh --windowed`. Coordinates are 96-dpi pixels (floats), scaled to the screen.
Colors are `"#rgb"`, `"#rrggbb"` or `"#rrggbbaa"`.

| group | functions |
|---|---|
| window | `window(title, width=900, height=600, min_width=320, min_height=240)`, `frame(w) -> bool`, `running`, `close`, `width`, `height`, `time`, `dt` (seconds since the last frame), `frame_ms` (CPU time of the last frame's drawing), `set_title`, `minimize`, `maximize` (toggles), `is_maximized`, `drag_area(w, x, y, width, height)`, `no_drag(...)` (holes for your own buttons), `cursor(w, "arrow"\|"hand"\|"ibeam"\|"sizewe"\|"wait")` |
| shapes | `clear(w, color)`, `rect(w, x, y, width, height, color, radius=0)`, `outline(..., radius=0, thickness=1)`, `gradient(..., color1, color2, vertical=True, radius=0)`, `glow(..., color, radius=0, spread=16)` (soft shadow/glow), `circle(w, x, y, r, color)`, `ring(..., thickness=1)`, `line(w, x1, y1, x2, y2, color, thickness=1)` |
| state | `clip(w, x, y, width, height)` / `unclip(w)`, `opacity(w, alpha)` (everything after it), `transform(w, dx, dy, scale=1)`, `mix(color1, color2, t) -> str` |
| text | `text(w, text, x, y, width, height, size=14, color="#ffffff", bold=False, align="left", valign="center", font="", wrap=False)` (one line ends in "…" when it doesn't fit; color emoji work), `text_width(text, size=14, bold=False, font="")`, `has_font(name)` |
| pictures | `image(path, max_size=512) -> int` (0 = not a picture), `image_width`, `image_height`, `draw_image(w, image, x, y, width, height, alpha=1)`, `free_image` |
| input | `mouse_x`, `mouse_y` (-1 outside), `mouse_down(w, button="left")`, `clicked` (pressed this frame), `released`, `double_clicked`, `wheel` (notches, + = away from you), `pressed(w, key)` (this frame, with repeats), `key_down(w, key)`, `typed(w) -> str`. Keys: `"a"`-`"z"`, `"0"`-`"9"`, `"enter"`, `"escape"`, `"backspace"`, `"tab"`, `"space"`, `"delete"`, arrows `"left"`..., `"home"`, `"end"`, `"pageup"`, `"pagedown"`, `"f1"`-`"f12"`, `"shift"`, `"ctrl"`, `"alt"` |
| headless | `headless()` (or `BASHER_CANVAS_HEADLESS=1`), `is_headless()`, `sim_mouse(w, x, y, down=False, button="left")`, `sim_click(w, x, y, button="left", twice=False)`, `sim_wheel`, `sim_key`, `sim_hold(w, key, on=True)`, `sim_type`, `sim_resize`, `screenshot(w, path) -> bool` (PNG), `pixel(w, x, y) -> "#rrggbb"` |

Headless: no window at all; frames are drawn into a bitmap (on the CPU, so slower than a real window), time moves
exactly 1/60 s per frame, input comes from `sim_*`, and `screenshot` saves what's drawn. Tests run this way, so
nothing shows on the screen. A `close()` in the middle of a frame lets that frame finish; the next `frame()` returns False.

Example: `examples/hello.bsh` (a card that follows the mouse, eased).
