Kite

canvas

! Low-level drawing, into a <canvas>. ! ! HTML and CSS describe a document, and a document is described rather than ! drawn. This is the other door: a chart, a game or a visualisation knows ! where its own marks go, and needs to put them there without describing ! anything first. ! ! It is a named surface over the drawing calls, not a graphics library. ! Every function here is one of the calls a renderer implements, or something ! assembled from them — and where a shape cannot be assembled, it is absent ! rather than approximated. There is no line, no path and no polygon, because ! the boundary has no line, path or polygon and faking one out of rectangles ! would produce something that looked wrong on every backend in a different ! way. What is here is exact everywhere. ! ! Coordinates are floats, with the origin at the top left of the surface. ! Colours are 0xRRGGBB. ! ! ``kite ignore ! use std/canvas ! ! fn chart(x: float, y: float, w: float, h: float) { ! canvas.fill(x, y, w, h, 0x101216) ! canvas.circle(x + w / 2.0, y + h / 2.0, 40.0, 0x3b82f6) ! } ! ` ! ! **The surface is the host's, and there is one.** These calls are compiler ! builtins that go to whatever surface the runtime supplies, so a program ! cannot yet say *which* <canvas> it is drawing into. Choosing one means ! passing a dom.Element` through to the drawing builtins, which is a change ! to the boundary rather than to this file.

fill

pub fn fill(x: float, y: float, w: float, h: float, colour: int)

A filled rectangle.

rounded

pub fn rounded(x: float, y: float, w: float, h: float, radius: float, colour: int)

A filled rectangle with rounded corners.

The radius is clamped by the renderer to half the shorter side, so a radius larger than the box gives a stadium rather than an error.

circle

pub fn circle(cx: float, cy: float, radius: float, colour: int)

A circle centred on (cx, cy).

A rounded rectangle as wide as it is tall, with the radius at half the side — which is a circle exactly, on every backend, because that is the case the clamp in rrect was already handling.

ring

pub fn ring(x: float, y: float, w: float, h: float, radius: float, width: float, colour: int)

The ring between a box and the same box inset by width — a border, drawn without filling the middle.

This is what makes an outline independent of a fill: the two are separate calls, so an outlined shape does not have to paint its own interior in whatever colour it happens to be sitting on.

circle_ring

pub fn circle_ring(cx: float, cy: float, radius: float, width: float, colour: int)

The ring of a circle: an outlined circle of the given stroke width.

text

pub fn text(x: float, y: float, body: str, colour: int)

A run of text, with (x, y) at the top left of its line box.

One run on one line: this draws what it is given and does not wrap. Wrapping is a measurement rather than a drawing decision, and nothing here does it: [width_of] and text.break_opportunities are the two halves it would be written from.

font

pub fn font(size: float, weight: int)

Select the size and weight that subsequent text is drawn and measured in.

Measurement follows the same selection, which is what keeps a caller's own layout arithmetic agreeing with what appears.

width_of

pub fn width_of(body: str) -> float

How wide a run is in the font currently selected.

line_height

pub fn line_height() -> float

How tall one line is in the font currently selected: ascent plus descent plus leading.

image

pub fn image(x: float, y: float, w: float, h: float, src: str)

A picture, fitted into the box without distorting it.

src is whatever the host can resolve — a URL, a path, a data: URI. A backend that has not loaded it yet draws nothing and asks to be called again when it has; a backend that cannot draw pictures at all records that one goes here.

clip

pub fn clip(x: float, y: float, w: float, h: float)

Confine everything drawn until [unclip] to a rectangle.

Clips nest, and every one has to be closed. Nothing closes one for you: a caller that clips and returns leaves everything drawn afterwards confined to a box it has forgotten about.

unclip

pub fn unclip()

alpha

pub fn alpha(a: float)

Draw everything after this at a of full opacity, from 0.0 to 1.0.

It applies until it is set back. A caller that sets it and returns leaves every later mark translucent, which is a bug that shows up somewhere else entirely — so set it back explicitly.

opaque

pub fn opaque()