Painting
By overriding paint or paintForeground you can get functionality similar to CustomPaint:

class MyBoxyDelegate extends BoxyDelegate {
@override
Size layout() => const Size(32, 32);
@override
void paint() {
canvas.drawRect(
Offset.zero & render.size,
Paint()..color = Colors.blue,
);
}
}
The paint and paintForeground methods are the same, but paintForeground is called after paintChildren.
Painting children
We can customize the way children are painted by overriding paintChildren, this is useful if you want to change their paint order for example:

class MyWidget extends StatelessWidget {
const MyWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return CustomBoxy(
delegate: MyBoxyDelegate(),
children: [
Container(
color: Colors.blue,
width: 48,
height: 48,
),
Container(
color: Colors.red,
width: 96,
height: 48,
),
],
);
}
}
class MyBoxyDelegate extends BoxyDelegate {
@override
void paintChildren() {
children[1].paint();
children[0].paint();
}
}
Note that the canvas is still available, so we can use paintChildren to paint things between children:

class MyBoxyDelegate extends BoxyDelegate {
@override
void paintChildren() {
children[1].paint();
canvas.save();
canvas.drawCircle(
// Unlike the paint method, the canvas of paintChildren is not transformed
// into the local coordinate space, so we need to offset by paintOffset.
paintOffset + const Offset(48, 24),
16,
Paint()..color = Colors.white,
);
canvas.restore();
children[0].paint();
}
}