Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Graph edges improvements #10325

Merged
merged 4 commits into from Jun 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions libr/core/cmd_anal.c
Expand Up @@ -5999,8 +5999,10 @@ static void cmd_anal_graph(RCore *core, const char *input) {
case 'k':
case 'w':
case ' ': {
core->graph->is_callgraph = true;
ut64 addr = input[2] ? r_num_math (core->num, input + 2) : core->offset;
r_core_cmdf (core, "ag-; .agr* %"PFMT64d"; agg%c;", addr, input[1]);
core->graph->is_callgraph = false;
break;
}
case '*': {
Expand Down Expand Up @@ -6028,7 +6030,9 @@ static void cmd_anal_graph(RCore *core, const char *input) {
case 'w':
case ' ':
case 0: {
core->graph->is_callgraph = true;
r_core_cmdf (core, "ag-; .agR*; agg%c;", input[1]);
core->graph->is_callgraph = false;
break;
}
case '*': {
Expand Down
83 changes: 50 additions & 33 deletions libr/core/graph.c
Expand Up @@ -190,7 +190,7 @@ static char *get_title(ut64 addr) {

static int agraph_refresh(struct agraph_refresh_data *grd);

static void update_node_dimension(const RGraph *g, int is_mini, int zoom) {
static void update_node_dimension(const RGraph *g, int is_mini, int zoom, int edgemode, bool callgraph, int layout) {
const RList *nodes = r_graph_get_nodes (g);
RGraphNode *gn;
RListIter *it;
Expand All @@ -217,6 +217,16 @@ static void update_node_dimension(const RGraph *g, int is_mini, int zoom) {
/* scale node by zoom */
n->w = R_MAX (MIN_NODE_WIDTH, (n->w * zoom) / 100);
n->h = R_MAX (MIN_NODE_HEIGHT, (n->h * zoom) / 100);

if (edgemode == 2 && !callgraph) {
if (!layout) {
n->w = R_MAX (n->w, (r_list_length (n->gnode->out_nodes)*2 + 1) + R_EDGES_X_INC * 2);
n->w = R_MAX (n->w, (r_list_length (n->gnode->in_nodes)*2 + 1) + R_EDGES_X_INC * 2);
} else {
n->h = R_MAX (n->h, (r_list_length (n->gnode->out_nodes) + 1) + R_EDGES_X_INC);
n->h = R_MAX (n->h, (r_list_length (n->gnode->in_nodes) + 1) + R_EDGES_X_INC);
}
}
}
}
}
Expand Down Expand Up @@ -1695,7 +1705,7 @@ void backedge_info (RAGraph *g) {
}

int nth = get_nth (g, a, b);
int xinc = 4 + 2 * (nth + 1);
int xinc = R_EDGES_X_INC + 2 * (nth + 1);

int ax = g->layout == 0 ? a->x + xinc : a->y + (a->h / 2) + nth;
int bx = g->layout == 0 ? b->x + xinc : b->y + (b->h / 2) + nth;
Expand Down Expand Up @@ -2541,18 +2551,20 @@ static int find_ascii_edge(const AEdge *a, const AEdge *b) {
}
#endif

static int get_nth (const RAGraph *g, RANode *src, RANode *dst) {
static int get_edge_number (const RAGraph *g, RANode *src, RANode *dst, bool outgoing) {
RListIter *itn;
RGraphNode *gv;
int cur_nth = 0;
int nth = 0;
RANode *v;

if (src->is_dummy) {
if (outgoing && src->is_dummy) {
RANode *in = (RANode *) (((RGraphNode *)r_list_first ((src->gnode)->in_nodes))->data);
cur_nth = get_nth (g, in, src);
cur_nth = get_edge_number (g, in, src, outgoing);
} else {
const RList *neighbours = r_graph_get_neighbours (g->graph, src->gnode);
const RList *neighbours = outgoing
? r_graph_get_neighbours (g->graph, src->gnode)
: r_graph_innodes (g->graph, dst->gnode);
const int exit_edges = r_list_length (neighbours);
graph_foreach_anode (neighbours, itn, gv, v) {
cur_nth = nth;
Expand All @@ -2561,7 +2573,9 @@ static int get_nth (const RAGraph *g, RANode *src, RANode *dst) {
} else if (exit_edges == 1) {
cur_nth = -1;
}
if (gv->idx == (dst->gnode)->idx) {
if (outgoing && gv->idx == (dst->gnode)->idx) {
break;
} else if (!outgoing && gv->idx == (src->gnode)->idx) {
break;
}
nth++;
Expand All @@ -2570,6 +2584,10 @@ static int get_nth (const RAGraph *g, RANode *src, RANode *dst) {
return cur_nth;
}

static int get_nth (const RAGraph *g, RANode *src, RANode *dst) {
return get_edge_number (g, src, dst, true);
}

struct tmplayer {
int layer;
int edgectr;
Expand Down Expand Up @@ -2616,8 +2634,8 @@ static void agraph_print_edges_simple(RAGraph *g) {

if (n2->is_dummy) {
r_cons_canvas_line (g->can,
n2->x, n2->y - 1,
n2->x, n2->y + n2->h, &style);
n2->x + sx2, n2->y - 1,
n2->x + sx2, n2->y + n2->h, &style);
}
}
}
Expand All @@ -2631,7 +2649,7 @@ static void agraph_print_edges(RAGraph *g) {
agraph_print_edges_simple (g);
return;
}
int nth;
int out_nth, in_nth;
RListIter *itn, *itm, *ito;
RCanvasLineStyle style = {0};
const RList *nodes = r_graph_get_nodes (g->graph);
Expand All @@ -2646,7 +2664,7 @@ static void agraph_print_edges(RAGraph *g) {
const RGraphNode *gb;
RANode *b;
const RList *neighbours = r_graph_get_neighbours (g->graph, ga);
int ax, ay, bx, by, xinc;
int ax, ay, bx, by, a_x_inc, b_x_inc;
tl = tm = NULL;

r_list_foreach (lyr, ito, tl) {
Expand Down Expand Up @@ -2688,19 +2706,16 @@ static void agraph_print_edges(RAGraph *g) {
}
}


bool many = r_list_length (neighbours) > 2;
graph_foreach_anode (neighbours, itn, gb, b) {
int is_first = true;
if (a->is_dummy) {
RANode *in = (RANode *) (((RGraphNode *)r_list_first (ga->in_nodes))->data);
nth = get_nth (g, in, a);
} else {
nth = get_nth (g, a, b);
}
out_nth = get_edge_number (g, a, b, true);
in_nth = get_edge_number (g, a, b, false);

if (many) {
style.color = LINE_UNCJMP;
} else {
switch (nth) {
switch (out_nth) {
case 0:
style.color = LINE_TRUE;
break;
Expand All @@ -2716,22 +2731,23 @@ static void agraph_print_edges(RAGraph *g) {
}
}

xinc = 4 + 2 * (nth + 1);

ax = a->is_dummy ? a->x : (a->x + xinc);
ay = a->y + a->h;

bx = b->is_dummy ? b->x : (b->x + xinc);
by = b->y - 1;

switch (g->layout) {
case 0:
default:
style.symbol = a->is_dummy ? LINE_NOSYM_VERT : style.color;

if (!a->is_dummy && is_first && nth == 0 && bx > ax) {
xinc += 4;
ax += 4;
a_x_inc = R_EDGES_X_INC + 2 * (out_nth + 1);
b_x_inc = R_EDGES_X_INC + 2 * (in_nth + 1);

ax = a->is_dummy ? a->x : (a->x + a->w - a_x_inc);
ay = a->y + a->h;

bx = b->is_dummy ? b->x : (b->x + b_x_inc);
by = b->y - 1;

if (!a->is_dummy && itn == neighbours->head && out_nth == 0 && bx > ax) {
a_x_inc += 4;
ax -= 4;
}
if (a->h < a->layer_height) {
r_cons_canvas_line (g->can, ax, ay, ax, ay + a->layer_height - a->h, &style);
Expand Down Expand Up @@ -2763,9 +2779,9 @@ static void agraph_print_edges(RAGraph *g) {
case 1:
style.symbol = a->is_dummy ? LINE_NOSYM_HORIZ : style.color;
ax = a->x + a->w;
ay = a->is_dummy ? a->y : a->y + (a->h / 2) + nth;
ay = a->is_dummy ? a->y : a->y + R_EDGES_X_INC + out_nth;
bx = b->x - 1;
by = b->is_dummy ? b->y : b->y + (b->h / 2) + nth;
by = b->is_dummy ? b->y : b->y + R_EDGES_X_INC + out_nth;
if (a->w < a->layer_width) {
r_cons_canvas_line_square_defined (g->can, ax, ay, a->x + a->layer_width, ay, &style, 0, false);
ax = a->x + a->layer_width;
Expand Down Expand Up @@ -3038,7 +3054,7 @@ static int check_changes(RAGraph *g, int is_interactive,
agraph_update_title (g, fcn);
}
if (g->need_update_dim || g->need_reload_nodes || !is_interactive) {
update_node_dimension (g->graph, is_mini (g), g->zoom);
update_node_dimension (g->graph, is_mini (g), g->zoom, g->edgemode, g->is_callgraph, g->layout);
}
if (g->need_set_layout || g->need_reload_nodes || !is_interactive) {
agraph_set_layout (g, is_interactive);
Expand Down Expand Up @@ -3823,6 +3839,7 @@ R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int
}
r_config_set_i (core->config, "graph.edges", e);
g->edgemode = e;
g->need_update_dim = true;
get_bbupdate (g, core, fcn);
}
break;
Expand Down
2 changes: 2 additions & 0 deletions libr/include/r_cons.h
Expand Up @@ -762,6 +762,8 @@ R_API const char* r_cons_get_rune(const ut8 ch);
#define R_LINE_BUFSIZE 4096
#define R_LINE_HISTSIZE 256

#define R_EDGES_X_INC 4

typedef struct r_line_hist_t {
char **data;
int size;
Expand Down