fitIcon function

String fitIcon(
  1. MorphIconData input,
  2. Object viewBox, [
  3. double grid = 24
])

Re-grids an icon drawn on viewBox onto the shared grid (24 by default), centred and preserving aspect ratio — the SVG xMidYMid meet rule.

Both endpoints of a morph must live on the same coordinate space. Lucide and Tabler already draw on 24×24; packs on 20 (Heroicons solid) or 32 (Carbon) do not, and mixing them unfitted makes Procrustes read the scale/offset gap as rotation. Apply once at module scope (not per render) and pass the resulting d anywhere an icon is accepted.

viewBox accepts a num, a String ("0 0 32 32" or "0,0,32,32") or a List<num> of four values.

Implementation

String fitIcon(MorphIconData input, Object viewBox, [double grid = 24]) {
  final (minX, minY, w, h) = _parseViewBox(viewBox);
  final s = math.min(grid / w, grid / h);
  final tx = (grid - w * s) / 2 - minX * s;
  final ty = (grid - h * s) / 2 - minY * s;
  final paths = iconToCubics(input);
  for (final path in paths) {
    final pts = path.pts;
    for (var i = 0; i < pts.length; i += 2) {
      pts[i] = pts[i] * s + tx;
      pts[i + 1] = pts[i + 1] * s + ty;
    }
  }
  return cubicsToPathD(paths);
}