Compare commits
8 Commits
Author | SHA1 | Date |
---|---|---|
pancake | 283544dbfd | |
pancake | 1c5f42999d | |
pancake | 1b6a903ff1 | |
pancake | a9e20cbb88 | |
pancake | 535489c984 | |
pancake | f8e40b1abf | |
pancake | 0145f2f418 | |
pancake | 1e8663fb78 |
|
@ -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 ' ': {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
204
libr/util/pie.c
204
libr/util/pie.c
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue