import '../../core/settings.mjs';
import '../../color.mjs';
import '../../constants.mjs';
import '../../extensions.mjs';
import { SHAPES } from '../../math/const.mjs';
import { Point } from '../../math/Point.mjs';
import '../../math/groupD8.mjs';
import '../../math/Transform.mjs';
import '../../runner.mjs';
import '../../ticker/settings.mjs';
import '../../ticker/const.mjs';
import '../../ticker/Ticker.mjs';
import '../../ticker/TickerPlugin.mjs';
import '../../utils/settings.mjs';
import '../../utils/is_mobile/index.mjs';
import '../../utils/color/premultiply.mjs';
import '../../utils/media/BoundingBox.mjs';
import '../../core/autoDetectRenderer.mjs';
import '../../core/background/BackgroundSystem.mjs';
import '../../core/batch/BatchRenderer.mjs';
import '../../core/shader/Program.mjs';
import '../../core/batch/BatchSystem.mjs';
import '../../core/context/ContextSystem.mjs';
import '../../core/filters/Filter.mjs';
import '../../core/filters/FilterSystem.mjs';
import '../../core/textures/BaseTexture.mjs';
import '../../core/framebuffer/FramebufferSystem.mjs';
import '../../core/framebuffer/MultisampleSystem.mjs';
import '../../core/geometry/BufferSystem.mjs';
import '../../core/geometry/GeometrySystem.mjs';
import '../../core/mask/MaskSystem.mjs';
import '../../core/mask/ScissorSystem.mjs';
import '../../core/mask/StencilSystem.mjs';
import '../../core/plugin/PluginSystem.mjs';
import '../../core/projection/ProjectionSystem.mjs';
import '../../core/render/ObjectRendererSystem.mjs';
import '../../core/Renderer.mjs';
import '../../core/renderTexture/GenerateTextureSystem.mjs';
import '../../core/renderTexture/RenderTexturePool.mjs';
import '../../core/renderTexture/RenderTextureSystem.mjs';
import '../../core/shader/ShaderSystem.mjs';
import '../../core/startup/StartupSystem.mjs';
import '../../core/state/StateSystem.mjs';
import '../../core/textures/TextureGCSystem.mjs';
import '../../core/textures/TextureSystem.mjs';
import '../../core/transformFeedback/TransformFeedbackSystem.mjs';
import '../../core/view/ViewSystem.mjs';
import '../../core/textures/resources/index.mjs';
import { LINE_CAP, LINE_JOIN, curves } from '../const.mjs';

function square(x, y, nx, ny, innerWeight, outerWeight, clockwise, verts) {
  const ix = x - nx * innerWeight;
  const iy = y - ny * innerWeight;
  const ox = x + nx * outerWeight;
  const oy = y + ny * outerWeight;
  let exx;
  let eyy;
  if (clockwise) {
    exx = ny;
    eyy = -nx;
  } else {
    exx = -ny;
    eyy = nx;
  }
  const eix = ix + exx;
  const eiy = iy + eyy;
  const eox = ox + exx;
  const eoy = oy + eyy;
  verts.push(eix, eiy, eox, eoy);
  return 2;
}
function round(cx, cy, sx, sy, ex, ey, verts, clockwise) {
  const cx2p0x = sx - cx;
  const cy2p0y = sy - cy;
  let angle0 = Math.atan2(cx2p0x, cy2p0y);
  let angle1 = Math.atan2(ex - cx, ey - cy);
  if (clockwise && angle0 < angle1) {
    angle0 += Math.PI * 2;
  } else if (!clockwise && angle0 > angle1) {
    angle1 += Math.PI * 2;
  }
  let startAngle = angle0;
  const angleDiff = angle1 - angle0;
  const absAngleDiff = Math.abs(angleDiff);
  const radius = Math.sqrt(cx2p0x * cx2p0x + cy2p0y * cy2p0y);
  const segCount = (15 * absAngleDiff * Math.sqrt(radius) / Math.PI >> 0) + 1;
  const angleInc = angleDiff / segCount;
  startAngle += angleInc;
  if (clockwise) {
    verts.push(cx, cy, sx, sy);
    for (let i = 1, angle = startAngle; i < segCount; i++, angle += angleInc) {
      verts.push(cx, cy, cx + Math.sin(angle) * radius, cy + Math.cos(angle) * radius);
    }
    verts.push(cx, cy, ex, ey);
  } else {
    verts.push(sx, sy, cx, cy);
    for (let i = 1, angle = startAngle; i < segCount; i++, angle += angleInc) {
      verts.push(cx + Math.sin(angle) * radius, cy + Math.cos(angle) * radius, cx, cy);
    }
    verts.push(ex, ey, cx, cy);
  }
  return segCount * 2;
}
function buildNonNativeLine(graphicsData, graphicsGeometry) {
  const shape = graphicsData.shape;
  let points = graphicsData.points || shape.points.slice();
  const eps = graphicsGeometry.closePointEps;
  if (points.length === 0) {
    return;
  }
  const style = graphicsData.lineStyle;
  const firstPoint = new Point(points[0], points[1]);
  const lastPoint = new Point(points[points.length - 2], points[points.length - 1]);
  const closedShape = shape.type !== SHAPES.POLY || shape.closeStroke;
  const closedPath = Math.abs(firstPoint.x - lastPoint.x) < eps && Math.abs(firstPoint.y - lastPoint.y) < eps;
  if (closedShape) {
    points = points.slice();
    if (closedPath) {
      points.pop();
      points.pop();
      lastPoint.set(points[points.length - 2], points[points.length - 1]);
    }
    const midPointX = (firstPoint.x + lastPoint.x) * 0.5;
    const midPointY = (lastPoint.y + firstPoint.y) * 0.5;
    points.unshift(midPointX, midPointY);
    points.push(midPointX, midPointY);
  }
  const verts = graphicsGeometry.points;
  const length = points.length / 2;
  let indexCount = points.length;
  const indexStart = verts.length / 2;
  const width = style.width / 2;
  const widthSquared = width * width;
  const miterLimitSquared = style.miterLimit * style.miterLimit;
  let x0 = points[0];
  let y0 = points[1];
  let x1 = points[2];
  let y1 = points[3];
  let x2 = 0;
  let y2 = 0;
  let perpx = -(y0 - y1);
  let perpy = x0 - x1;
  let perp1x = 0;
  let perp1y = 0;
  let dist = Math.sqrt(perpx * perpx + perpy * perpy);
  perpx /= dist;
  perpy /= dist;
  perpx *= width;
  perpy *= width;
  const ratio = style.alignment;
  const innerWeight = (1 - ratio) * 2;
  const outerWeight = ratio * 2;
  if (!closedShape) {
    if (style.cap === LINE_CAP.ROUND) {
      indexCount += round(x0 - perpx * (innerWeight - outerWeight) * 0.5, y0 - perpy * (innerWeight - outerWeight) * 0.5, x0 - perpx * innerWeight, y0 - perpy * innerWeight, x0 + perpx * outerWeight, y0 + perpy * outerWeight, verts, true) + 2;
    } else if (style.cap === LINE_CAP.SQUARE) {
      indexCount += square(x0, y0, perpx, perpy, innerWeight, outerWeight, true, verts);
    }
  }
  verts.push(x0 - perpx * innerWeight, y0 - perpy * innerWeight, x0 + perpx * outerWeight, y0 + perpy * outerWeight);
  for (let i = 1; i < length - 1; ++i) {
    x0 = points[(i - 1) * 2];
    y0 = points[(i - 1) * 2 + 1];
    x1 = points[i * 2];
    y1 = points[i * 2 + 1];
    x2 = points[(i + 1) * 2];
    y2 = points[(i + 1) * 2 + 1];
    perpx = -(y0 - y1);
    perpy = x0 - x1;
    dist = Math.sqrt(perpx * perpx + perpy * perpy);
    perpx /= dist;
    perpy /= dist;
    perpx *= width;
    perpy *= width;
    perp1x = -(y1 - y2);
    perp1y = x1 - x2;
    dist = Math.sqrt(perp1x * perp1x + perp1y * perp1y);
    perp1x /= dist;
    perp1y /= dist;
    perp1x *= width;
    perp1y *= width;
    const dx0 = x1 - x0;
    const dy0 = y0 - y1;
    const dx1 = x1 - x2;
    const dy1 = y2 - y1;
    const dot = dx0 * dx1 + dy0 * dy1;
    const cross = dy0 * dx1 - dy1 * dx0;
    const clockwise = cross < 0;
    if (Math.abs(cross) < 1e-3 * Math.abs(dot)) {
      verts.push(x1 - perpx * innerWeight, y1 - perpy * innerWeight, x1 + perpx * outerWeight, y1 + perpy * outerWeight);
      if (dot >= 0) {
        if (style.join === LINE_JOIN.ROUND) {
          indexCount += round(x1, y1, x1 - perpx * innerWeight, y1 - perpy * innerWeight, x1 - perp1x * innerWeight, y1 - perp1y * innerWeight, verts, false) + 4;
        } else {
          indexCount += 2;
        }
        verts.push(x1 - perp1x * outerWeight, y1 - perp1y * outerWeight, x1 + perp1x * innerWeight, y1 + perp1y * innerWeight);
      }
      continue;
    }
    const c1 = (-perpx + x0) * (-perpy + y1) - (-perpx + x1) * (-perpy + y0);
    const c2 = (-perp1x + x2) * (-perp1y + y1) - (-perp1x + x1) * (-perp1y + y2);
    const px = (dx0 * c2 - dx1 * c1) / cross;
    const py = (dy1 * c1 - dy0 * c2) / cross;
    const pdist = (px - x1) * (px - x1) + (py - y1) * (py - y1);
    const imx = x1 + (px - x1) * innerWeight;
    const imy = y1 + (py - y1) * innerWeight;
    const omx = x1 - (px - x1) * outerWeight;
    const omy = y1 - (py - y1) * outerWeight;
    const smallerInsideSegmentSq = Math.min(dx0 * dx0 + dy0 * dy0, dx1 * dx1 + dy1 * dy1);
    const insideWeight = clockwise ? innerWeight : outerWeight;
    const smallerInsideDiagonalSq = smallerInsideSegmentSq + insideWeight * insideWeight * widthSquared;
    const insideMiterOk = pdist <= smallerInsideDiagonalSq;
    let join = style.join;
    if (join === LINE_JOIN.MITER && pdist / widthSquared > miterLimitSquared) {
      join = LINE_JOIN.BEVEL;
    }
    if (insideMiterOk) {
      switch (join) {
        case LINE_JOIN.MITER: {
          verts.push(imx, imy, omx, omy);
          break;
        }
        case LINE_JOIN.BEVEL: {
          if (clockwise) {
            verts.push(
              imx,
              imy,
              // inner miter point
              x1 + perpx * outerWeight,
              y1 + perpy * outerWeight,
              // first segment's outer vertex
              imx,
              imy,
              // inner miter point
              x1 + perp1x * outerWeight,
              y1 + perp1y * outerWeight
            );
          } else {
            verts.push(
              x1 - perpx * innerWeight,
              y1 - perpy * innerWeight,
              // first segment's inner vertex
              omx,
              omy,
              // outer miter point
              x1 - perp1x * innerWeight,
              y1 - perp1y * innerWeight,
              // second segment's outer vertex
              omx,
              omy
            );
          }
          indexCount += 2;
          break;
        }
        case LINE_JOIN.ROUND: {
          if (clockwise) {
            verts.push(imx, imy, x1 + perpx * outerWeight, y1 + perpy * outerWeight);
            indexCount += round(x1, y1, x1 + perpx * outerWeight, y1 + perpy * outerWeight, x1 + perp1x * outerWeight, y1 + perp1y * outerWeight, verts, true) + 4;
            verts.push(imx, imy, x1 + perp1x * outerWeight, y1 + perp1y * outerWeight);
          } else {
            verts.push(x1 - perpx * innerWeight, y1 - perpy * innerWeight, omx, omy);
            indexCount += round(x1, y1, x1 - perpx * innerWeight, y1 - perpy * innerWeight, x1 - perp1x * innerWeight, y1 - perp1y * innerWeight, verts, false) + 4;
            verts.push(x1 - perp1x * innerWeight, y1 - perp1y * innerWeight, omx, omy);
          }
          break;
        }
      }
    } else {
      verts.push(
        x1 - perpx * innerWeight,
        y1 - perpy * innerWeight,
        // first segment's inner vertex
        x1 + perpx * outerWeight,
        y1 + perpy * outerWeight
      );
      switch (join) {
        case LINE_JOIN.MITER: {
          if (clockwise) {
            verts.push(
              omx,
              omy,
              // inner miter point
              omx,
              omy
            );
          } else {
            verts.push(
              imx,
              imy,
              // outer miter point
              imx,
              imy
            );
          }
          indexCount += 2;
          break;
        }
        case LINE_JOIN.ROUND: {
          if (clockwise) {
            indexCount += round(x1, y1, x1 + perpx * outerWeight, y1 + perpy * outerWeight, x1 + perp1x * outerWeight, y1 + perp1y * outerWeight, verts, true) + 2;
          } else {
            indexCount += round(x1, y1, x1 - perpx * innerWeight, y1 - perpy * innerWeight, x1 - perp1x * innerWeight, y1 - perp1y * innerWeight, verts, false) + 2;
          }
          break;
        }
      }
      verts.push(
        x1 - perp1x * innerWeight,
        y1 - perp1y * innerWeight,
        // second segment's inner vertex
        x1 + perp1x * outerWeight,
        y1 + perp1y * outerWeight
      );
      indexCount += 2;
    }
  }
  x0 = points[(length - 2) * 2];
  y0 = points[(length - 2) * 2 + 1];
  x1 = points[(length - 1) * 2];
  y1 = points[(length - 1) * 2 + 1];
  perpx = -(y0 - y1);
  perpy = x0 - x1;
  dist = Math.sqrt(perpx * perpx + perpy * perpy);
  perpx /= dist;
  perpy /= dist;
  perpx *= width;
  perpy *= width;
  verts.push(x1 - perpx * innerWeight, y1 - perpy * innerWeight, x1 + perpx * outerWeight, y1 + perpy * outerWeight);
  if (!closedShape) {
    if (style.cap === LINE_CAP.ROUND) {
      indexCount += round(x1 - perpx * (innerWeight - outerWeight) * 0.5, y1 - perpy * (innerWeight - outerWeight) * 0.5, x1 - perpx * innerWeight, y1 - perpy * innerWeight, x1 + perpx * outerWeight, y1 + perpy * outerWeight, verts, false) + 2;
    } else if (style.cap === LINE_CAP.SQUARE) {
      indexCount += square(x1, y1, perpx, perpy, innerWeight, outerWeight, false, verts);
    }
  }
  const indices = graphicsGeometry.indices;
  const eps2 = curves.epsilon * curves.epsilon;
  for (let i = indexStart; i < indexCount + indexStart - 2; ++i) {
    x0 = verts[i * 2];
    y0 = verts[i * 2 + 1];
    x1 = verts[(i + 1) * 2];
    y1 = verts[(i + 1) * 2 + 1];
    x2 = verts[(i + 2) * 2];
    y2 = verts[(i + 2) * 2 + 1];
    if (Math.abs(x0 * (y1 - y2) + x1 * (y2 - y0) + x2 * (y0 - y1)) < eps2) {
      continue;
    }
    indices.push(i, i + 1, i + 2);
  }
}
function buildNativeLine(graphicsData, graphicsGeometry) {
  let i = 0;
  const shape = graphicsData.shape;
  const points = graphicsData.points || shape.points;
  const closedShape = shape.type !== SHAPES.POLY || shape.closeStroke;
  if (points.length === 0)
    return;
  const verts = graphicsGeometry.points;
  const indices = graphicsGeometry.indices;
  const length = points.length / 2;
  const startIndex = verts.length / 2;
  let currentIndex = startIndex;
  verts.push(points[0], points[1]);
  for (i = 1; i < length; i++) {
    verts.push(points[i * 2], points[i * 2 + 1]);
    indices.push(currentIndex, currentIndex + 1);
    currentIndex++;
  }
  if (closedShape) {
    indices.push(currentIndex, startIndex);
  }
}
function buildLine(graphicsData, graphicsGeometry) {
  if (graphicsData.lineStyle.native) {
    buildNativeLine(graphicsData, graphicsGeometry);
  } else {
    buildNonNativeLine(graphicsData, graphicsGeometry);
  }
}

export { buildLine };
//# sourceMappingURL=buildLine.mjs.map
