diff options
-rw-r--r-- | src/gtkext/graph/cluster.c | 118 |
1 files changed, 115 insertions, 3 deletions
diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c index 4f39b28..8f584b9 100644 --- a/src/gtkext/graph/cluster.c +++ b/src/gtkext/graph/cluster.c @@ -231,6 +231,9 @@ static void dispatch_x_graph_rank(const graph_rank_t *); /* Réorganise au besoin les liens entrants un ensemble de blocs. */ static void sort_graph_rank_incoming_links(graph_rank_t *); +/* Réordonne les blocs de départ de boucle d'un ensemble. */ +static void reorder_graph_rank_loop_blocks(graph_rank_t *); + /* Décale vers la droite un ensemble de blocs basiques. */ static void offset_x_graph_rank(graph_rank_t *, gint); @@ -335,6 +338,9 @@ static void g_graph_cluster_sort_incoming_links(GGraphCluster *); /* Retrouve l'indice d'un lien entrant donné pour un bloc. */ static size_t g_graph_cluster_find_incoming_link(const GGraphCluster *, const leaving_link_t *); +/* Réordonne les blocs de départ de boucle au mieux. */ +static void g_graph_cluster_reorder_loop_blocks(GGraphCluster *); + /* Décale vers la droite un ensemble de blocs basiques. */ static void g_graph_cluster_offset_x(GGraphCluster *, gint); @@ -1491,6 +1497,70 @@ static void sort_graph_rank_incoming_links(graph_rank_t *grank) /****************************************************************************** * * * Paramètres : grank = ensemble de blocs de même rang à actualiser. * +* * +* Description : Réordonne les blocs de départ de boucle d'un ensemble. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void reorder_graph_rank_loop_blocks(graph_rank_t *grank) +{ + size_t i; /* Boucle de parcours #1 */ + size_t k; /* Boucle de parcours #2 */ + GGraphCluster *tmp; /* Stockage temporaire */ + + for (i = 0; i < grank->count; i++) + g_graph_cluster_reorder_loop_blocks(grank->clusters[i]); + + if (grank->count > 1) + { + /* Placement des départs de boucle à gauche ! */ + + for (i = 0; i < grank->vspaces.left_count; i++) + { + tmp = grank->vspaces.left[i]->from->owner; + + for (k = 0; k < grank->count; k++) + if (grank->clusters[k] == tmp) + break; + + assert(k < grank->count); + + memmove(&grank->clusters[1], &grank->clusters[0], k * sizeof(GGraphCluster *)); + + grank->clusters[0] = tmp; + + } + + /* Placement des départs de boucle à droite ! */ + + for (i = 0; i < grank->vspaces.right_count; i++) + { + tmp = grank->vspaces.right[i]->from->owner; + + for (k = 0; k < grank->count; k++) + if (grank->clusters[k] == tmp) + break; + + assert(k < grank->count); + + memmove(&grank->clusters[k], &grank->clusters[k + 1], (grank->count - k - 1) * sizeof(GGraphCluster *)); + + grank->clusters[grank->count - 1] = tmp; + + } + + } + +} + + +/****************************************************************************** +* * +* Paramètres : grank = ensemble de blocs de même rang à actualiser. * * offset = décalage à appliquer. * * * * Description : Décale vers la droite un ensemble de blocs basiques. * @@ -2297,6 +2367,28 @@ static size_t g_graph_cluster_find_incoming_link(const GGraphCluster *cluster, c /****************************************************************************** * * * Paramètres : cluster = graphique de blocs à actualiser. * +* * +* Description : Réordonne les blocs de départ de boucle au mieux. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_graph_cluster_reorder_loop_blocks(GGraphCluster *cluster) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < cluster->ranks_count; i++) + reorder_graph_rank_loop_blocks(&cluster->ranks[i]); + +} + + +/****************************************************************************** +* * +* Paramètres : cluster = graphique de blocs à actualiser. * * offset = décalage à appliquer. * * * * Description : Décale vers la droite un ensemble de blocs basiques. * @@ -3174,17 +3266,37 @@ GGraphCluster *bootstrap_graph_cluster(GLoadedBinary *binary, const GBlockList * * Cette consigne est valable pour les liens de boucle également, dont * l'origine est toujours dans un bloc inférieur au bloc de destination. * Le premier étant traité après le second, cela oblige à appeler - * g_graph_cluster_dispatch_x() deux fois donc, car on ne peut effectuer - * le tri des liens au début de cette fonction comme c'était fait - * dans les premières versions du code. + * g_graph_cluster_dispatch_x() au moins deux fois donc, car on ne peut + * effectuer le tri des liens au début de cette fonction comme c'était + * fait dans les premières versions du code. */ g_graph_cluster_sort_incoming_links(result); + /** + * Même s'ils ne sont pas encore entièrement tracés, les liens de boucle + * voient désormais leurs positions d'arrivée et de départ définies. + * + * On sait si lesdits liens partent vers la gauche ou la droite. + * + * On est donc en mesure de réorganiser latéralement les blocs + * pour tirer les traits horizontaux au plus court ! + */ + + g_graph_cluster_reset_allocation(result); + + g_graph_cluster_reorder_loop_blocks(result); + + /** + * Placement horizontal définitif. + */ + g_graph_cluster_reset_allocation(result); g_graph_cluster_dispatch_x(result); + g_graph_cluster_sort_incoming_links(result); + /* Réajustement vers la droite */ g_graph_cluster_compute_needed_alloc(result, &needed); |