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 }