fit method

ShapeElement fit(
  1. ShapeElement source,
  2. Map<String, double> bands
)

Fits authored bounds to intrinsic requirements before publication.

Implementation

ShapeElement fit(ShapeElement source, Map<String, double> bands) {
  if (isEmpty) return source;
  for (var pass = 0; pass < 12; pass++) {
    final contents = resolve(source, bands);
    var dx = 0.0, dy = 0.0;
    for (final content in contents) {
      final layer = definition.expandedLayers
          .whereType<ShapeContentLayerDefinition>()
          .firstWhere((layer) => layer.slotId == content.slotId);
      final region = layer.bounds.resolve(source, textHeights: bands);
      final frame = source.frame;
      final wider = layer.bounds.resolve(
        source.copyWith(
          frame: DiagramRect.fromLTWH(
            frame.left,
            frame.top,
            frame.width + 1,
            frame.height,
          ),
        ),
        textHeights: bands,
      );
      final taller = layer.bounds.resolve(
        source.copyWith(
          frame: DiagramRect.fromLTWH(
            frame.left,
            frame.top,
            frame.width,
            frame.height + 1,
          ),
        ),
        textHeights: bands,
      );
      final widthDeficit = content.requiredSize.width - region.width;
      final heightDeficit = content.requiredSize.height - region.height;
      if (widthDeficit > .01) {
        if (wider.width <= region.width) {
          throw ArgumentError('Content region must allow width growth');
        }
        dx = math.max(dx, widthDeficit / (wider.width - region.width));
      }
      if (heightDeficit > .01) {
        if (taller.height <= region.height) {
          throw ArgumentError('Content region must allow height growth');
        }
        dy = math.max(dy, heightDeficit / (taller.height - region.height));
      }
    }
    if (dx < .01 && dy < .01) return source;
    source = source.copyWith(
      frame: DiagramRect.fromLTWH(
        source.frame.left,
        source.frame.top,
        source.frame.width + dx,
        source.frame.height + dy,
      ),
    );
  }
  throw StateError('Content region fitting did not converge');
}