Compare commits

...

8 Commits
master ... pie

Author SHA1 Message Date
pancake 283544dbfd Full rewrite of the pie algorithm 2024-03-25 17:25:17 +01:00
pancake 1c5f42999d better pie algo 2024-03-25 17:04:31 +01:00
pancake 1b6a903ff1
Update libr/core/cmd_help.inc.c 2024-03-22 23:25:46 +01:00
pancake a9e20cbb88
Update libr/core/cmd_help.inc.c 2024-03-22 18:54:59 +01:00
pancake 535489c984 ji 2024-03-22 18:35:01 +01:00
pancake f8e40b1abf hardcoded 2024-03-22 17:49:48 +01:00
pancake 0145f2f418 asjdfkl 2024-03-22 17:39:04 +01:00
pancake 1e8663fb78 Add colors and improve the pie chart rendering a bit ##print 2024-03-22 17:34:07 +01:00
4 changed files with 158 additions and 79 deletions

View File

@ -265,7 +265,7 @@ static RCoreHelpMessage help_msg_question_e = {
"?eg", " 10 20", "move cursor to column 10, row 20",
"?ef", " text", "echo text with thin ascii art frame around",
"?en", " nonl", "echo message without ending newline",
"?ep", " 10 20 30", "draw a pie char with given portion sizes",
"?ep", " 10 20,ten twe", "render pie chart with portions and (e hex.cols for size)",
"?es", " msg", "speak message using the text-to-speech program (e cfg.tts)",
"?et", " msg", "change terminal title",
NULL
@ -1337,17 +1337,36 @@ static int cmd_help(void *data, const char *input) {
break;
case 'p':
{
char *word, *str = strdup (input + 2);
char *word, *str = strdup (r_str_trim_head_ro (input + 2));
char *legend = strchr (str, ',');
RList *llist = NULL;
if (legend) {
*legend = 0;
r_str_trim (legend + 1);
llist = r_str_split_list (strdup (legend + 1), " ", 0);
}
r_str_trim (str);
RList *list = r_str_split_list (str, " ", 0);
ut64 *nums = calloc (sizeof (ut64), r_list_length (list));
int *nums = calloc (sizeof (ut64), r_list_length (list));
char **text = calloc (sizeof (char *), r_list_length (list));
int i = 0;
r_list_foreach (list, iter, word) {
nums[i] = r_num_math (core->num, word);
i++;
}
int j = 0;
r_list_foreach (llist, iter, word) {
if (j >= i) {
break;
}
text[j] = word;
j++;
}
int size = r_config_get_i (core->config, "hex.cols");
r_print_pie (core->print, nums, r_list_length (list), size);
r_print_pie (core->print, r_list_length (list), nums, (const char**)text, size);
free (text);
r_list_free (list);
r_list_free (llist);
}
break;
case ' ': {

View File

@ -459,12 +459,12 @@ static RCoreHelpMessage help_msg_piE = {
"Usage:", "piE[q]", " # print esil of N bytes",
"piE", "", "print esil of the instructions found in N bytes",
"piEq", "", "same as above but without displaying the instruction address",
// "piej", "", "same but in JSON format",
// "piEj", "", "same but in JSON format",
NULL
};
static RCoreHelpMessage help_msg_pie = {
"Usage:", "pie[fq]", " # print esil of N instructions",
"Usage:", "pie[bqf]", " # print esil of N instructions",
"pie", "", "print esil of N instructions",
"pieb", "", "alias for `pie $Fi`",
"pieq", "", "same as above but hiding the offset",

View File

@ -283,7 +283,7 @@ R_API void r_print_init_rowoffsets(RPrint *p);
R_API ut32 r_print_rowoff(RPrint *p, int i);
R_API void r_print_set_rowoff(RPrint *p, int i, ut32 offset, bool overwrite);
R_API int r_print_row_at_off(RPrint *p, ut32 offset);
R_API int r_print_pie(RPrint *p, ut64 *values, int nvalues, int size);
R_API void r_print_pie(RPrint *p, int nvalues, int *values, const char **text, int size);
R_API void r_print_graphline(RPrint *print, const ut8 *buf, size_t len);
// WIP

View File

@ -1,93 +1,153 @@
/* radare2 - LGPL - Copyright 2018-2021 - pancake */
/* radare2 - LGPL - Copyright 2018-2024 - pancake */
#include <r_util.h>
#include <r_util/r_print.h>
#include <math.h>
#define PI 3.1415
#define O out[x + (y * size)]
#define USE_SINCOS 0
// TODO: add support for colors
// TODO: better rounding ascii art
// TODO: add support for xy_factor
#if 1
#define A(c) out[(x+half) + ((y+half) * (half*2))] = c
#else
printf ("%c%c", c, c);
#endif
static void drawSectorLine(char *out, int size, int percent) {
int i, x, y;
double A = (percent)*PI / 50;
double foo = 0.1;
for (i = (size - 1) / 2; i < (size - 3); i++) {
x = y = (size - 1) / 2;
x += (int)(cos (A) * foo + 1);
y += (int)(sin (A) * foo + 1);
foo += 1.1;
O = '.';
static void drawPieChart(char *out, int diameter, int numSlices, int sliceSizes[], const char **text) {
int totalDegrees = 0;
char sliceChars[] = "0123456789";
int sliceCharCount = sizeof (sliceChars) / sizeof (sliceChars[0]);
int radius = diameter / 2;
int x, y, i;
// Calculate the start and end angle for each slice
int sliceAngles[11]; // max slices is 10
sliceAngles[0] = 0; // Starting angle for the first slice
for (i = 0; i < numSlices; i++) {
totalDegrees += (int)(360.0 * sliceSizes[i] / 100.0);
sliceAngles[i+1] = totalDegrees;
// printf ("%d\n", totalDegrees);
}
// Add the remaining slice if the sum of parts don't cover the whole pie
if (totalDegrees < 360) {
numSlices++;
sliceAngles[numSlices] = 360;
}
int half = radius;
// Draw the pie chart
for (y = -radius; y <= radius; y++) {
for (x = -radius; x <= radius; x++) {
double distance = sqrt (x * x + y * y);
// Check if the current point is within the circle
if (distance < radius) {
double angle = atan2(y, x) * 180 / PI;
if (angle < 0) {
angle += 360;
}
int sliceIndex = -1;
for (i = 0; i < numSlices; i++) {
if (angle >= sliceAngles[i] && angle < sliceAngles[i+1]) {
sliceIndex = i;
break;
}
}
if (sliceIndex != -1) {
const char ch = sliceChars[sliceIndex % sliceCharCount];
A (ch);
// printf ("%c%c", ch, ch);
} else {
A (' ');
// printf (" "); // Should not happen, but just in case
}
} else {
A (' ');
// printf (" ");
}
}
// printf ("\n");
}
}
R_API int r_print_pie(RPrint *p, ut64 *values, int nvalues, int size) {
R_API void r_print_pie(R_NULLABLE RPrint *p, int nvalues, int *values, const char **text, int size) {
if (size < 1) {
R_LOG_WARN ("No one cant eat such smol pie");
return;
}
if (nvalues > 9) {
R_LOG_WARN ("Cant render more than 10 portions in a pie chart");
nvalues = 9;
}
ut8 *nv = calloc (nvalues, sizeof (ut8));
char *out = calloc (size, size);
char *out = calloc (size, size * size);
drawPieChart (out, size, nvalues, values, text);
const bool use_colors = p? p->flags & R_PRINT_FLAGS_COLOR: false;
const char *fg_colors[10] = {
Color_GREEN,
Color_RED,
Color_BLUE,
Color_MAGENTA,
Color_CYAN,
Color_YELLOW,
Color_WHITE,
Color_GREEN,
Color_RED,
Color_YELLOW,
};
const char *bg_colors[10] = {
Color_BGGREEN,
Color_BGRED,
Color_BGBLUE,
Color_BGMAGENTA,
Color_BGCYAN,
Color_BGYELLOW,
Color_BGWHITE,
Color_BGGREEN,
Color_BGRED,
Color_BGYELLOW,
};
const char *leg[20] = {0};
int i, x, y;
if (nv && out) {
ut64 total = 0;
for (i = 0; i < nvalues; i++) {
total += values[i];
for (i = 0; i < 20; i++) {
leg[i] = "??";
}
for (i = 0; i < nvalues;i++) {
if (text[i]) {
leg[i] = text[i];
}
total /= 100;
if (total < 1) {
total = 1;
}
for (i = 0; i < nvalues; i++) {
nv[i] = values[i] / total;
}
for (x = 0; x < size; x++) {
for (y = 0; y < size; y++) {
O = ' ';
}
}
#if USE_SINCOS
float a = 0.0;
int s = size / 2;
while (a < 2 * PI) {
x = s * cos (a) + (size / 2);
y = s * sin (a) + (size / 2);
O = '.';
a += 0.1;
}
#else
int radius = (size - 1) / 2;
// draw portions
for (x = 0; x <= 2 * radius; x++) {
for (y = 0; y <= 2 * radius; y++) {
double distance = sqrt ((double)(x - radius) * (x - radius) + (y - radius) * (y - radius));
O = (distance > radius - 0.5 && distance < radius + 0.5) ? 'x' : ' ';
}
}
#endif
int amount = 0;
for (i = 0; i < nvalues; i++) {
drawSectorLine (out, size, nv[i] + amount);
amount += nv[i];
}
/// render
if (p && p->cb_printf) {
}
int legend_idx = 0;
if (nv && out && p && p->cb_printf) {
for (y = 0; y < size; y++) {
for (x = 0; x < size; x++) {
for (y = 0; y < size; y++) {
p->cb_printf ("%c%c", O, O);
const char ch = out[x + (y * size)];
if (use_colors && isdigit (ch)) {
const int index = ch - '0';
p->cb_printf ("%s··"Color_RESET, fg_colors[index]);
} else {
p->cb_printf ("%c%c", ch, ch);
}
p->cb_printf ("\n");
}
if (y > 0 && legend_idx < nvalues) {
if (y % 2) {
if (leg[legend_idx]) {
if (use_colors) {
p->cb_printf (" %s "Color_RESET" - %s",
bg_colors[legend_idx], leg[legend_idx]);
} else {
p->cb_printf (" %c%c - %s",
'0' + legend_idx,
'0' + legend_idx,
leg[legend_idx]);
}
}
legend_idx++;
}
}
p->cb_printf ("\n");
}
p->cb_printf ("\n");
}
free (out);
free (nv);
return 0;
}
#if 0
main() {
ut64 v[] = { 10, 20, 30, 40 };
r_print_pie (NULL, &v, 4, 20);
}
#endif