1/* { dg-do compile } */ 2/* { dg-options "-O2 -ftree-tail-merge" } */ 3typedef int BoxCoordinate; 4typedef int BoxDimension; 5const BoxDimension X = 0; 6const BoxDimension Y = 1; 7const BoxDimension NDimensions = 2; 8class BoxPoint { 9 BoxCoordinate point[NDimensions]; 10public: 11 bool isValid() const; 12 void operator += (const BoxPoint& p) { 13 if (isValid() && p.isValid()) { 14 point[X] += p.point[X]; 15 } 16 } 17 const BoxCoordinate& operator [] (const BoxDimension& dimension) const { 18 return point[dimension]; 19 } 20}; 21class BoxRegion { 22public: 23 BoxCoordinate& origin(BoxDimension d) const; 24 BoxCoordinate& space(BoxDimension d) const; 25}; 26inline bool operator <= (const BoxPoint& p, const BoxRegion& r) { 27 for (BoxDimension d = X; 28 d <= Y; 29 d++) if (p[d] < r.origin(d) || p[d] >= r.origin(d) + r.space(d)) 30return false; 31 return true; 32} 33typedef struct _WidgetRec *Widget; 34struct GraphGC { 35 BoxPoint offsetIfSelected; 36}; 37class GraphNode; 38class GraphEdge { 39public: 40 GraphNode *from() const; 41 GraphNode *to() const; 42}; 43class LineGraphEdge: public GraphEdge { 44protected: 45 virtual void drawLine(Widget w, const GraphGC& gc) const; 46 void _print(const GraphGC &gc) const; 47}; 48class ArcGraphEdge: public LineGraphEdge { 49 static bool center(const BoxPoint& p1, const BoxPoint& p2, 50 const BoxPoint& p3, double& x, double& y); 51 void makeLine(Widget w, const GraphGC& gc) const; 52}; 53class GraphNode { 54public: 55 bool& selected(); 56 GraphEdge *firstTo() const; 57 GraphEdge *nextTo(GraphEdge *ref) const; 58 virtual const BoxPoint& pos() const = 0; 59 virtual const BoxRegion& region(const GraphGC& gc) const = 0; 60 virtual bool isHint() const; 61}; 62class PosGraphNode: public GraphNode { }; 63class RegionGraphNode: public PosGraphNode { }; 64class HintGraphNode: public RegionGraphNode { }; 65void ArcGraphEdge::makeLine(Widget w, const GraphGC& gc) const { 66 HintGraphNode *arc_hint = 0; 67 RegionGraphNode *arc_from = 0; 68 RegionGraphNode *arc_to = 0; 69 bool make_arc = true; 70 if (from()->isHint() && to()->isHint()) { 71 make_arc = false; 72 } 73 else if (from()->isHint() && from()->firstTo() != 0) { 74 if (arc_hint == 0 || arc_from == 0 || arc_to == 0 75 || arc_hint->nextTo(arc_hint->firstTo()) != 0) { 76 make_arc = false; 77 } 78 } 79 if (!make_arc) { 80 if (w != 0) LineGraphEdge::drawLine(w, gc); 81 else LineGraphEdge::_print(gc); 82 return; 83 } 84 BoxPoint pos_from = arc_from->pos(); 85 BoxRegion region_from = arc_from->region(gc); 86 BoxPoint pos_to = arc_to->pos(); 87 BoxRegion region_to = arc_to->region(gc); 88 BoxPoint pos_hint = arc_hint->pos(); 89 if (arc_hint->selected()) { 90 pos_hint += gc.offsetIfSelected; 91 } 92 if (pos_hint <= region_from || pos_hint <= region_to) { 93 return; 94 } 95 double cx, cy; 96 bool ok = center(pos_from, pos_hint, pos_to, cx, cy); 97 if (!ok) { 98 if (w != 0) LineGraphEdge::drawLine(w, gc); 99 else LineGraphEdge::_print(gc); 100 } 101} 102