export function reconcileViewBox()

in packages/cdk-graph-plugin-diagram/src/internal/utils/svg.ts [177:239]


export function reconcileViewBox(svg: svgson.INode): void {
  const viewBox = parseSvgViewBox(svg);
  if (viewBox == null || !viewBox.width || !viewBox.height) {
    throw new Error("Svg `viewBox` undefined or does not define dimensions");
  }

  // drop width/height to ensure only reconciled viewbox is used
  delete svg.attributes.width;
  delete svg.attributes.height;

  const container = getSvgRootContainer(svg);
  if (container == null) {
    return;
  }

  // let [x, y, width, height] = viewBox.split(" ").map((v) => parseFloat(v)) as [number, number, number, number];
  let scale = parseSvgTransformScale(container);
  if (scale == null) {
    return;
  }

  let scaledViewBox: SvgViewBox = {
    ...viewBox,
    width: viewBox.width * (scale[0] || 1),
    height: viewBox.height * (scale[1] || scale[0] || 1),
  };

  // Max allowed by sharp: https://github.com/lovell/sharp/blob/2c465282699432299c478ba00ab825e07d9bdab0/src/pipeline.cc#L288
  const MAX_SVG = 10000; // 32767 is max width & height in sharp, but capping at 10k for perf and downscale huge diagrams

  if (scaledViewBox.width && scaledViewBox.width > MAX_SVG) {
    const downscale = MAX_SVG / scaledViewBox.width;
    scaledViewBox = {
      ...scaledViewBox,
      width: scaledViewBox.width * downscale,
      height: scaledViewBox.height
        ? scaledViewBox.height * downscale
        : undefined,
    };
    if (scale[0]) scale[0] *= downscale;
    if (scale[1]) scale[1] *= downscale;
  }

  if (scaledViewBox.height && scaledViewBox.height > MAX_SVG) {
    const downscale = MAX_SVG / scaledViewBox.height;
    scaledViewBox = {
      ...scaledViewBox,
      height: scaledViewBox.height * downscale,
      width: scaledViewBox.width ? scaledViewBox.width * downscale : undefined,
    };
    if (scale[0]) scale[0] *= downscale;
    if (scale[1]) scale[1] *= downscale;
  }

  svg.attributes.viewBox = stringifySvgViewBox(scaledViewBox);
  if (scale[0] || scale[1]) {
    const _scale = scale.filter((v) => v != null && !isNaN(v)).join(" ");
    container.attributes.transform = container.attributes.transform.replace(
      CSS_TRANSFORM_SCALE,
      `scale(${_scale})`
    );
  }
}