An extension of the midpoint circle algorithm for arbitrary integer diameters.

TODO: Add touch support.

Every pixel drawn exactly once. For odd diameters, the origin of the circle at a pixel defined by cx and cy is the center of that pixel; for even diameters it's the top-left corner of that pixel instead. Assumes non-negative diameters. The parameters for p were revealed to me in a dream.

1. Circle

function pixel(x, y);

function oddcircle(cx, cy, r) {
	if (r == 0) {
		pixel(cx, cy);
		return;
	}
	
	let x = 1;
	let y = -r;
	let p = -r + 4;
	
	pixel(cx, cy - r);
	pixel(cx, cy + r);
	pixel(cx - r, cy);
	pixel(cx + r, cy);
	
	while (x <= -y) {
		pixel(cx + x, cy + y);
		pixel(cx - y, cy + x);
		pixel(cx + y, cy - x);
		pixel(cx - x, cy - y);
		
		if (x <= -y - 1) {
			pixel(cx + y, cy + x);
			pixel(cx - x, cy + y);
			pixel(cx + x, cy - y);
			pixel(cx - y, cy - x);
		}
		
		if (p > 0) {
			y += 1;
			p += 2*y - 1;
		}
		
		x += 1;
		p += 2*x + 1;
	}
}

function evencircle(cx, cy, r) {
	if (r == 0) return;
	
	let x = 0;
	let y = -r;
	let p = -2*r + 5;
	
	while (x < -y) {
		pixel(cx + x,     cy + y);
		pixel(cx - y - 1, cy + x);
		pixel(cx + y,     cy - x - 1);
		pixel(cx - x - 1, cy - y - 1);
		
		if (x < -y - 1) {
			pixel(cx + y,     cy + x);
			pixel(cx - x - 1, cy + y);
			pixel(cx + x,     cy - y - 1);
			pixel(cx - y - 1, cy - x - 1);
		}
		
		if (p > 0) {
			y += 1;
			p += 4*y;
		}
		
		x += 1;
		p += 4*x + 4;
	}
}

function circle(cx, cy, d) {
	(d&1 ? oddcircle : evencircle)(cx, cy, d>>1);
}

2. Disk (filled circle)

The algorithm for drawing a circle can be adjusted to fill the circle instead:

function horizline(x1, x2, y) {
	for (let x = x1; x <= x2; x++) pixel(x, y);
}

function oddcircle(cx, cy, r) {
	// ...
	horizline(cx - r, cx + r, cy);
	
	while (x <= -y) {
		horizline(cx + y, cx - y, cy - x);
		horizline(cx + y, cx - y, cy + x);
		
		if (p > 0) {
			if (x <= -y - 1) {
				horizline(cx - x, cx + x, cy - y);
				horizline(cx - x, cx + x, cy + y);
			}
			// ...

function evencircle(cx, cy, r) {
	// ...
	while (x < -y) {
		horizline(cx + y, cx - y - 1, cy - x - 1);
		horizline(cx + y, cx - y - 1, cy + x);
		
		if (p > 0) {
			if (x < -y - 1) {
				horizline(cx - x - 1, cx + x, cy - y - 1);
				horizline(cx - x - 1, cx + x, cy + y);
			}
			// ...