]> git.siccegge.de Git - frida/frida.git/blob - src/gui/widgets/CFGScene.cxx
Make requestNewFunction pass a signal
[frida/frida.git] / src / gui / widgets / CFGScene.cxx
1 #include "CFGScene.hxx"
2
3 void CFGScene::drawBackground(QPainter* painter, const QRectF & rect) {
4 QGraphicsScene::drawBackground(painter, rect);
5
6 spaceWidgets();
7
8 for (BasicBlockWidget * widget : widgets) {
9 QPointF kopf = widget->getEntry();
10 painter->setPen(QColor(0x00, 0xff, 0x00, 0xff));
11 painter->drawLine(kopf, kopf - QPointF(0, 20));
12
13 auto tails = widget->getExits();
14 auto next = widget->getNext();
15 if (NULL != next[0]) {
16 if (NULL != next[1]) {
17 painter->setPen(QColor(0xff, 0x00, 0x00, 0xff));
18 painter->drawLine(std::get<0>(tails), std::get<0>(tails) + QPointF(0, 20));
19 drawLine(painter, widget, next[1], -1);
20
21 painter->setPen(QColor(0x00, 0xff, 0x00, 0xff));
22 painter->drawLine(std::get<2>(tails), std::get<2>(tails) + QPointF(0, 20));
23 drawLine(painter, widget, next[0], 1);
24 } else {
25 painter->setPen(QColor(0x00, 0x00, 0x00, 0xff));
26 painter->drawLine(std::get<1>(tails), std::get<1>(tails) + QPointF(0, 20));
27 drawLine(painter, widget, next[0], 0);
28 }
29 }
30 }
31 }
32
33 /* Forward edges: Forward (downward) edges are just drawn straight
34 * down and then to the right side
35 * Backward edges: Consider the smallest rectangle that contains both,
36 * source and destination block. Draw the edge along
37 * the shorter side of that rectangle
38 */
39 void CFGScene::drawLine(QPainter* painter, BasicBlockWidget * from, BasicBlockWidget * to, int8_t side) {
40 QPointF from_p = from->getExits()[side+1] + QPointF(0, 20);
41 QPointF to_p = to->getEntry() - QPointF(0, 20);
42 if ((to_p - from_p).y() > 0) {
43 /* Forward Edge */
44 QPointF angle1(from_p + QPointF(0, (to_p - from_p).y()));
45 painter->drawLine(from_p, angle1);
46 painter->drawLine(angle1, to_p);
47 } else {
48 /* Backward Edge */
49 QRectF from_r(from->boundingRect()), to_r(to->boundingRect());
50 from_r.moveTo(from->scenePos());
51 to_r.moveTo(to->scenePos());
52 QRectF bound = from_r | to_r;
53 if (std::abs(bound.right() - from_p.x()) > std::abs(bound.left() - to_p.x())) {
54 /* we go left */
55 QPointF middle1 = from_p + QPointF(bound.left() - from_p.x() - 20, 0);
56 QPointF middle2 = to_p + QPointF(bound.left() - to_p.x() - 20, 0);
57
58 painter->drawLine(from_p, middle1);
59 painter->drawLine(middle1, middle2);
60 painter->drawLine(middle2, to_p);
61 } else {
62 /* we go right */
63 QPointF middle1 = from_p - QPointF(from_p.x() - bound.right() - 20, 0);
64 QPointF middle2 = to_p - QPointF(to_p.x() - bound.right() - 20, 0);
65
66 painter->drawLine(from_p, middle1);
67 painter->drawLine(middle1, middle2);
68 painter->drawLine(middle2, to_p);
69 }
70 }
71 }
72
73 void CFGScene::spaceWidgets() {
74 bool changed = false;
75
76 /* While some BasicBlockWidget overlaps with a direct predecessor,
77 * move that widget down one step. Move each widget at most once
78 * per iteration so that widgets with severall incoming edges
79 * don't outrun these with less -- preserving order by address
80 * where appropriate.
81 */
82 do {
83 changed = false;
84 for (BasicBlockWidget * widget : widgets) {
85 QPointF out(std::get<0>(widget->getExits()));
86 BasicBlockWidget ** next = widget->getNext();
87
88 if (NULL != next[0]
89 && (next[0]->getEntry() - widget->getEntry()).y() > 0
90 && (next[0]->getEntry() - out).y() < 50) {
91 widget->moveBy(0, -3);
92 changed = true;
93 } else if (NULL != next[1]
94 && (next[1]->getEntry() - widget->getEntry()).y() > 0
95 && (next[1]->getEntry() - out).y() < 50) {
96 widget->moveBy(0, -3);
97 changed = true;
98 }
99 }
100 } while (changed);
101
102 /* If there are still BasicBlockWidgets overlapping (BasicBlocks
103 * that don't have a direct edge) spread them sideways.
104 */
105 for (BasicBlockWidget * widget : widgets) {
106 QRectF relevantRect = widget->boundingRect();
107 relevantRect.moveTo(widget->scenePos());
108 relevantRect.adjust(-20, -20, 20, 20);
109 for (QGraphicsItem * item : items(relevantRect)) {
110 if (item == widget) continue;
111 if (std::find(widgets.begin(), widgets.end(), item) == widgets.end()) continue;
112 QRectF itemrect = item->boundingRect();
113 itemrect.moveTo(item->scenePos());
114 while (relevantRect.intersects(itemrect)) {
115 if (widget->scenePos().x() > item->scenePos().x()) {
116 widget->moveBy(3, 0);
117 relevantRect.moveTo(widget->scenePos());
118 } else {
119 item->moveBy(3, 0);
120 itemrect.moveTo(item->scenePos());
121 }
122 }
123 }
124 }
125 }
126
127 void CFGScene::highlightBlock(BasicBlockWidget* block) {
128 QGraphicsView* view = *(views().begin());
129 if (highlightedBlock) {
130 highlightedBlock->setColor(highlightedBlock->defaultColor);
131 update(highlightedBlock->boundingRect());
132 }
133 highlightedBlock = block;
134 view->centerOn(block);
135 block->setColor(block->highlightColor);
136 update(block->boundingRect());
137 }