sav

Sorting Algorithms Visualized
Index Commits Files Refs README LICENSE
drw.c (6690B)
   1 #include "drw.h"
   2 
   3 static status_t drw_status_bar_fetch_text(Drw *, SAV *);
   4 static void drw_text(Drw *drw, const char *text, int x, int y);
   5 
   6 static char* const sort_status_str[STATUS_MAX] = {
   7     "READY",
   8     "SORTING",
   9     "PAUSED",
  10     "SORTED",
  11     "STOPPED"
  12 };
  13 
  14 static char* const algo_sel_str[ALGORITHMS_COUNT + 1] = {
  15     /* "bubble sort]", */
  16     "bubble sort]",
  17     "insertion sort]",
  18     "merge sort]",
  19     "quick sort]",
  20     "shell sort]",
  21     "selection sort]",
  22     "heap sort]",
  23     "sort not set]"
  24 };
  25 
  26 void drw_element_color(Drw *drw, int x, int y, int h, unsigned int col) {
  27     SDL_Rect rect;
  28 
  29     rect.x = x + drw->x_border; /* bottom left + x */
  30     rect.y = y - drw->y_border; /* bottom */
  31     rect.w = RECT_WIDTH; /* fixed width */
  32     rect.h = -h;
  33 
  34     SDL_SetRenderDrawColor(drw->rend, UNHEX(col));
  35     SDL_RenderFillRect(drw->rend, &rect);
  36     /* printf("INFO: color: #%02X%02X%02X%02X\n", UNHEX(col)); */
  37 
  38     /* Simulate shadows around rectangles */
  39     SDL_SetRenderDrawColor(drw->rend, UNHEX(0x000000FF));
  40     SDL_RenderDrawLine(drw->rend,
  41                         x + drw->x_border + RECT_WIDTH - 1, y - drw->y_border - 1,
  42                         x + drw->x_border + RECT_WIDTH - 1, y - drw->y_border - h);
  43 }
  44 
  45 void drw_array_graph(Drw *drw, SAV *sav) {
  46     int x;
  47 
  48     size_t i;
  49     for(i = x = 0; i < sav->arr->len; i++, x += RECT_WIDTH) {
  50         if(i == sav->sel) drw_element_color(drw, x, drw->h, sav->arr->v[i], SEL_COLOR);
  51         else if(i == sav->cmp) drw_element_color(drw, x, drw->h, sav->arr->v[i], CMP_COLOR);
  52         else drw_element_color(drw, x, drw->h, sav->arr->v[i], NORM_COLOR);
  53     }
  54 }
  55 
  56 static status_t drw_status_bar_fetch_text(Drw *drw, SAV *sav) {
  57     if(drw->bar_text == NULL) return ERROR_NULL_POINTER;
  58 
  59     if(sav->status == WELCOME) {
  60         snprintf(drw->bar_text, drw->bar_text_len - 2,
  61                 "  Welcome to sorting algorithms visualized  [%s] [%-15s  press SPACE to start sorting",
  62                 shuffle_t_str[sav->arr->shuffle_sel], algo_sel_str[sav->sort_algo]);
  63     }
  64     else if(sav->status == START) {
  65         snprintf(drw->bar_text, drw->bar_text_len - 2,
  66                 "  %-8s  [%s] [%-15s  press SPACE to start sorting", sort_status_str[OK],
  67                 shuffle_t_str[sav->arr->shuffle_sel], algo_sel_str[sav->sort_algo]);
  68     }
  69     else if(sav->status == RUN) {
  70         if(sav->sort_status == PAUSE)
  71             snprintf(drw->bar_text, drw->bar_text_len - 2,
  72                     "  %-8s  [%s] [%-15s  L:%ld C:%ld S:%ld",
  73                     sort_status_str[sav->sort_status],
  74                     shuffle_t_str[sav->arr->shuffle_sel], algo_sel_str[sav->sort_algo],
  75                     sav->arr->len, sav->cmps, sav->swps);
  76         else if(sav->sort_status == SORTED)
  77             snprintf(drw->bar_text, drw->bar_text_len - 2,
  78                     "  %-8s  [%s] [%-15s  L:%ld C:%ld S:%ld, done in %lds, extra storage used: %ldbytes",
  79                     sort_status_str[sav->sort_status],
  80                     shuffle_t_str[sav->arr->shuffle_sel], algo_sel_str[sav->sort_algo],
  81                     sav->arr->len, sav->cmps, sav->swps, (sav->tf - sav->ti), sav->B_used);
  82         else if(sav->sort_status == RUN)
  83             snprintf(drw->bar_text, drw->bar_text_len - 2,
  84                     "  %-8s  [%s] [%-15s  L:%ld C:%ld S:%ld", sort_status_str[sav->sort_status],
  85                     shuffle_t_str[sav->arr->shuffle_sel], algo_sel_str[sav->sort_algo],
  86                     sav->arr->len, sav->cmps, sav->swps);
  87     }
  88     else snprintf(drw->bar_text, drw->bar_text_len - 2, "  Exiting ..... ");
  89 
  90     return OK;
  91 }
  92 
  93 static void drw_text(Drw *drw, const char *text, int x, int y) {
  94     SDL_Surface *text_surface;
  95     SDL_Texture *text_texture;
  96     static SDL_Color text_color;
  97 
  98     text_color.r = (char)(FONT_COLOR >> 16) & 0xFF;
  99     text_color.g = (char)(FONT_COLOR >> 8) & 0xFF;
 100     text_color.b = (char)(FONT_COLOR) & 0xFF;
 101 
 102     /* TODO: UNICODE support? */
 103     /* drw->text_surface = TTF_RenderText_Blended(drw->font, text, drw->text_color); */
 104     /* drw->text_surface = TTF_RenderUNICODE_Blended(drw->font, text, drw->text_color); */
 105     text_surface = TTF_RenderUTF8_Blended(drw->font, text, text_color);
 106     text_texture = SDL_CreateTextureFromSurface(drw->rend, text_surface);
 107 
 108     drw->bar_text_rect.x = 10 + x;
 109     drw->bar_text_rect.y = drw->h - FONT_SIZE - 5;
 110     drw->bar_text_rect.w = text_surface->w;
 111     drw->bar_text_rect.h = text_surface->h;
 112 
 113     SDL_RenderCopy(drw->rend, text_texture, NULL, &drw->bar_text_rect);
 114     SDL_DestroyTexture(text_texture);
 115     SDL_FreeSurface(text_surface);
 116 }
 117 
 118 status_t drw_status_bar(Drw *drw, SAV *sav) {
 119     status_t st;
 120     SDL_Rect rect;
 121 
 122     rect.x = BAR_BORDER; /* top left + x */
 123     rect.y = drw->h - BAR_BORDER; /* top left + y, (y < 0) */
 124     rect.w = drw->w - (2 * BAR_BORDER); /* fixed width */
 125     rect.h = -BAR_HEIGHT;
 126 
 127     /* TODO: Make a variable to store statusbar background color */
 128     SDL_SetRenderDrawColor(drw->rend, UNHEX(0x000000FF)); /* RGBA */
 129     SDL_RenderFillRect(drw->rend, &rect);
 130 
 131     if((st = drw_status_bar_fetch_text(drw, sav)) != OK) return st;
 132 
 133     drw_text(drw, drw->bar_text, 0, drw->h - FONT_SIZE - 5);
 134     memset(drw->bar_text, 0, sizeof(char) * drw->bar_text_len);
 135 
 136     return OK;
 137 }
 138 
 139 status_t drw_update_frame(Drw *drw, SAV *sav) {
 140     if(!drw || !sav) return ERROR_NULL_POINTER;
 141 
 142     SDL_SetRenderDrawColor(drw->rend, 29, 28, 28, 0);
 143     SDL_RenderClear(drw->rend);
 144 
 145     drw_array_graph(drw, sav);
 146     drw_status_bar(drw, sav);
 147     SDL_RenderPresent(drw->rend);
 148 
 149     return OK;
 150 }
 151 
 152 status_t drw_create(Drw **drw) {
 153     TTF_Font *font = NULL;
 154     status_t st;
 155 
 156     if(((*drw) = (Drw *)malloc(sizeof(Drw))) == NULL)
 157         return ERROR_MEMORY_ALLOC;
 158 
 159     memset(*drw, 0, sizeof(Drw));
 160 
 161     if((st = SDL_setup(&(*drw)->win, &(*drw)->rend)) != OK)
 162         return st;
 163 
 164     font = TTF_OpenFont(FONT_NAME, FONT_SIZE);
 165     if(font == NULL)
 166         return ERROR_TTF_OPENING_FONT;
 167 
 168     int min_w, min_h;
 169 
 170     /* compute the window minimum size */
 171     min_w = ((ARR_LEN * RECT_WIDTH) + (2 * X_BORDER));
 172     min_h = ((ARR_MAX) + (2 * Y_BORDER) + TOP_BORDER);
 173 
 174     SDL_SetWindowMinimumSize((*drw)->win, min_w, min_h);
 175     /* SDL_SetWindowMaximumSize(*win, min_w, min_h); */
 176 
 177     (*drw)->font = font;
 178     (*drw)->x_border = X_BORDER;
 179     (*drw)->y_border = Y_BORDER;
 180 
 181     SDL_GetWindowSize((*drw)->win, &((*drw)->w), &((*drw)->h));
 182 
 183     (*drw)->bar_rect.x = BAR_BORDER; /* top left + x */
 184     (*drw)->bar_rect.y = (*drw)->h - BAR_BORDER; /* top left + y, (y < 0) */
 185     (*drw)->bar_rect.w = (*drw)->w - (2 * BAR_BORDER); /* fixed width */
 186     (*drw)->bar_rect.h = -BAR_HEIGHT;
 187 
 188     /* sometimes SDL_GetWindowSize() fails */
 189     if((*drw)->w < WIN_MIN_W)
 190         (*drw)->w = WIN_MIN_W;
 191     else if((*drw)->h < WIN_MIN_H)
 192         (*drw)->h = WIN_MIN_H;
 193 
 194     {
 195         int w_text, h_text;
 196         TTF_SizeText(font,
 197                 "SORTED [XXXXXXXXXXXXXXXXXXXXX] done in XXX.Xs, L: XXXXX,\
 198                 C: XXXXXX, S: XXXXXX, I: XXXXXX, storage used: XXXXXX Bytes",
 199                 &w_text, &h_text);
 200 
 201         (*drw)->bar_text_len = w_text;
 202     }
 203 
 204 
 205     (*drw)->bar_text = (char *)malloc(sizeof(char) * (*drw)->bar_text_len);
 206     if((*drw)->bar_text == NULL) return ERROR_MEMORY_ALLOC;
 207 
 208     return OK;
 209 }
 210 
 211 void drw_destroy(Drw *drw) {
 212     if(drw == NULL) return;
 213 
 214     TTF_CloseFont(drw->font);
 215     SDL_cleanup(drw->win, drw->rend);
 216     free(drw->bar_text);
 217     free(drw);
 218 }