11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciimport { GNode, MINIMUM_EDGE_SEPARATION, DEFAULT_NODE_BUBBLE_RADIUS } from "../src/node";
61cb0ef41Sopenharmony_ciimport { Graph } from "./graph";
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciconst BEZIER_CONSTANT = 0.3;
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciexport class Edge {
111cb0ef41Sopenharmony_ci  target: GNode;
121cb0ef41Sopenharmony_ci  source: GNode;
131cb0ef41Sopenharmony_ci  index: number;
141cb0ef41Sopenharmony_ci  type: string;
151cb0ef41Sopenharmony_ci  backEdgeNumber: number;
161cb0ef41Sopenharmony_ci  visible: boolean;
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci  constructor(target: GNode, index: number, source: GNode, type: string) {
191cb0ef41Sopenharmony_ci    this.target = target;
201cb0ef41Sopenharmony_ci    this.source = source;
211cb0ef41Sopenharmony_ci    this.index = index;
221cb0ef41Sopenharmony_ci    this.type = type;
231cb0ef41Sopenharmony_ci    this.backEdgeNumber = 0;
241cb0ef41Sopenharmony_ci    this.visible = false;
251cb0ef41Sopenharmony_ci  }
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci  stringID() {
281cb0ef41Sopenharmony_ci    return this.source.id + "," + this.index + "," + this.target.id;
291cb0ef41Sopenharmony_ci  }
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci  isVisible() {
321cb0ef41Sopenharmony_ci    return this.visible && this.source.visible && this.target.visible;
331cb0ef41Sopenharmony_ci  }
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  getInputHorizontalPosition(graph: Graph, showTypes: boolean) {
361cb0ef41Sopenharmony_ci    if (this.backEdgeNumber > 0) {
371cb0ef41Sopenharmony_ci      return graph.maxGraphNodeX + this.backEdgeNumber * MINIMUM_EDGE_SEPARATION;
381cb0ef41Sopenharmony_ci    }
391cb0ef41Sopenharmony_ci    const source = this.source;
401cb0ef41Sopenharmony_ci    const target = this.target;
411cb0ef41Sopenharmony_ci    const index = this.index;
421cb0ef41Sopenharmony_ci    const inputX = target.x + target.getInputX(index);
431cb0ef41Sopenharmony_ci    const inputApproach = target.getInputApproach(this.index);
441cb0ef41Sopenharmony_ci    const outputApproach = source.getOutputApproach(showTypes);
451cb0ef41Sopenharmony_ci    if (inputApproach > outputApproach) {
461cb0ef41Sopenharmony_ci      return inputX;
471cb0ef41Sopenharmony_ci    } else {
481cb0ef41Sopenharmony_ci      const inputOffset = MINIMUM_EDGE_SEPARATION * (index + 1);
491cb0ef41Sopenharmony_ci      return (target.x < source.x)
501cb0ef41Sopenharmony_ci        ? (target.x + target.getTotalNodeWidth() + inputOffset)
511cb0ef41Sopenharmony_ci        : (target.x - inputOffset);
521cb0ef41Sopenharmony_ci    }
531cb0ef41Sopenharmony_ci  }
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  generatePath(graph: Graph, showTypes: boolean) {
561cb0ef41Sopenharmony_ci    const target = this.target;
571cb0ef41Sopenharmony_ci    const source = this.source;
581cb0ef41Sopenharmony_ci    const inputX = target.x + target.getInputX(this.index);
591cb0ef41Sopenharmony_ci    const arrowheadHeight = 7;
601cb0ef41Sopenharmony_ci    const inputY = target.y - 2 * DEFAULT_NODE_BUBBLE_RADIUS - arrowheadHeight;
611cb0ef41Sopenharmony_ci    const outputX = source.x + source.getOutputX();
621cb0ef41Sopenharmony_ci    const outputY = source.y + source.getNodeHeight(showTypes) + DEFAULT_NODE_BUBBLE_RADIUS;
631cb0ef41Sopenharmony_ci    let inputApproach = target.getInputApproach(this.index);
641cb0ef41Sopenharmony_ci    const outputApproach = source.getOutputApproach(showTypes);
651cb0ef41Sopenharmony_ci    const horizontalPos = this.getInputHorizontalPosition(graph, showTypes);
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci    let result: string;
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci    if (inputY < outputY) {
701cb0ef41Sopenharmony_ci      result = `M ${outputX} ${outputY}
711cb0ef41Sopenharmony_ci                L ${outputX} ${outputApproach}
721cb0ef41Sopenharmony_ci                L ${horizontalPos} ${outputApproach}`;
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci      if (horizontalPos != inputX) {
751cb0ef41Sopenharmony_ci        result += `L ${horizontalPos} ${inputApproach}`;
761cb0ef41Sopenharmony_ci      } else {
771cb0ef41Sopenharmony_ci        if (inputApproach < outputApproach) {
781cb0ef41Sopenharmony_ci          inputApproach = outputApproach;
791cb0ef41Sopenharmony_ci        }
801cb0ef41Sopenharmony_ci      }
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci      result += `L ${inputX} ${inputApproach}
831cb0ef41Sopenharmony_ci                 L ${inputX} ${inputY}`;
841cb0ef41Sopenharmony_ci    } else {
851cb0ef41Sopenharmony_ci      const controlY = outputY + (inputY - outputY) * BEZIER_CONSTANT;
861cb0ef41Sopenharmony_ci      result = `M ${outputX} ${outputY}
871cb0ef41Sopenharmony_ci                C ${outputX} ${controlY},
881cb0ef41Sopenharmony_ci                  ${inputX} ${outputY},
891cb0ef41Sopenharmony_ci                  ${inputX} ${inputY}`;
901cb0ef41Sopenharmony_ci    }
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci    return result;
931cb0ef41Sopenharmony_ci  }
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  isBackEdge() {
961cb0ef41Sopenharmony_ci    return this.target.hasBackEdges() && (this.target.rank < this.source.rank);
971cb0ef41Sopenharmony_ci  }
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ciexport const edgeToStr = (e: Edge) => e.stringID();
102