surfaceGeometryProperties function

Map<String, dynamic> surfaceGeometryProperties(
  1. LayoutNode node
)

Rendering/geometry projection only. Grid rings remain the stored authority; materialized width/height and node transforms are not recomputed on load.

Implementation

Map<String, dynamic> surfaceGeometryProperties(LayoutNode node) {
  final surface = node.surface;
  if (node.kind != 'table' || surface == null) return node.properties;
  final result = <String, dynamic>{...node.properties};
  switch (surface['type']) {
    case 'rect':
      result['shape'] = 'rect';
    case 'circle':
      result['shape'] = 'circle';
    case 'grid':
      bool validRing(Object? raw) =>
          raw is List &&
          raw.every(
            (p) =>
                p is List &&
                p.length == 2 &&
                p.every((v) => v is num && v.isFinite),
          );
      if (surface['moduleSize'] is! num ||
          !(surface['moduleSize'] as num).isFinite ||
          !validRing(surface['outer']) ||
          surface['holes'] is! List ||
          !(surface['holes'] as List).every(validRing)) {
        return node.properties;
      }
      final module = (surface['moduleSize'] as num).toDouble();
      List<List<double>> ring(List raw) => [
        for (final point in raw)
          [
            (point[0] as num) * module - node.width / 2,
            (point[1] as num) * module - node.height / 2,
          ],
      ];
      result.addAll({
        'shape': 'polygon',
        'points': ring(surface['outer'] as List),
        'holes': [
          for (final hole in surface['holes'] as List) ring(hole as List),
        ],
      });
  }
  return frozenMap(result);
}