| /* { dg-do compile } */ |
| /* { dg-options "-O2 -ftree-tail-merge" } */ |
| typedef int BoxCoordinate; |
| typedef int BoxDimension; |
| const BoxDimension X = 0; |
| const BoxDimension Y = 1; |
| const BoxDimension NDimensions = 2; |
| class BoxPoint { |
| BoxCoordinate point[NDimensions]; |
| public: |
| bool isValid() const; |
| void operator += (const BoxPoint& p) { |
| if (isValid() && p.isValid()) { |
| point[X] += p.point[X]; |
| } |
| } |
| const BoxCoordinate& operator [] (const BoxDimension& dimension) const { |
| return point[dimension]; |
| } |
| }; |
| class BoxRegion { |
| public: |
| BoxCoordinate& origin(BoxDimension d) const; |
| BoxCoordinate& space(BoxDimension d) const; |
| }; |
| inline bool operator <= (const BoxPoint& p, const BoxRegion& r) { |
| for (BoxDimension d = X; |
| d <= Y; |
| d++) if (p[d] < r.origin(d) || p[d] >= r.origin(d) + r.space(d)) |
| return false; |
| return true; |
| } |
| typedef struct _WidgetRec *Widget; |
| struct GraphGC { |
| BoxPoint offsetIfSelected; |
| }; |
| class GraphNode; |
| class GraphEdge { |
| public: |
| GraphNode *from() const; |
| GraphNode *to() const; |
| }; |
| class LineGraphEdge: public GraphEdge { |
| protected: |
| virtual void drawLine(Widget w, const GraphGC& gc) const; |
| void _print(const GraphGC &gc) const; |
| }; |
| class ArcGraphEdge: public LineGraphEdge { |
| static bool center(const BoxPoint& p1, const BoxPoint& p2, |
| const BoxPoint& p3, double& x, double& y); |
| void makeLine(Widget w, const GraphGC& gc) const; |
| }; |
| class GraphNode { |
| public: |
| bool& selected(); |
| GraphEdge *firstTo() const; |
| GraphEdge *nextTo(GraphEdge *ref) const; |
| virtual const BoxPoint& pos() const = 0; |
| virtual const BoxRegion& region(const GraphGC& gc) const = 0; |
| virtual bool isHint() const; |
| }; |
| class PosGraphNode: public GraphNode { }; |
| class RegionGraphNode: public PosGraphNode { }; |
| class HintGraphNode: public RegionGraphNode { }; |
| void ArcGraphEdge::makeLine(Widget w, const GraphGC& gc) const { |
| HintGraphNode *arc_hint = 0; |
| RegionGraphNode *arc_from = 0; |
| RegionGraphNode *arc_to = 0; |
| bool make_arc = true; |
| if (from()->isHint() && to()->isHint()) { |
| make_arc = false; |
| } |
| else if (from()->isHint() && from()->firstTo() != 0) { |
| if (arc_hint == 0 || arc_from == 0 || arc_to == 0 |
| || arc_hint->nextTo(arc_hint->firstTo()) != 0) { |
| make_arc = false; |
| } |
| } |
| if (!make_arc) { |
| if (w != 0) LineGraphEdge::drawLine(w, gc); |
| else LineGraphEdge::_print(gc); |
| return; |
| } |
| BoxPoint pos_from = arc_from->pos(); |
| BoxRegion region_from = arc_from->region(gc); |
| BoxPoint pos_to = arc_to->pos(); |
| BoxRegion region_to = arc_to->region(gc); |
| BoxPoint pos_hint = arc_hint->pos(); |
| if (arc_hint->selected()) { |
| pos_hint += gc.offsetIfSelected; |
| } |
| if (pos_hint <= region_from || pos_hint <= region_to) { |
| return; |
| } |
| double cx, cy; |
| bool ok = center(pos_from, pos_hint, pos_to, cx, cy); |
| if (!ok) { |
| if (w != 0) LineGraphEdge::drawLine(w, gc); |
| else LineGraphEdge::_print(gc); |
| } |
| } |