#include "util.h" #include #include #include #include size_t read_from_stdin(void **buffer) { size_t len = 0; ssize_t r; size_t step = 4096; /* Arbitrary value of 4 KiB */ void *p; errno = 0; /* clear errno */ for(*buffer = NULL; (*buffer = realloc((p = *buffer), len + step)); len += (size_t)r) { if((r = read(STDIN_FILENO, (uint8_t *)*buffer + len, step)) == -1) { perror(NULL); break; } else if (r == 0) { break; } } /* realloc(3) leaves old buffer allocated in case of error */ if(*buffer == NULL && p != NULL) { int save = errno; free(p); errno = save; len = 0; } return len; } TTF_Font *load_font(const char *font_spec) { int font_size; char *font_name; /* figure out font size from name, or default to 24 */ char *sep = strchr(font_spec, ':'); if(sep) { font_name = strndup(font_spec, sep - font_spec); font_size = strtol(sep+1, NULL, 10); } else { font_name = strdup(font_spec); font_size = 24; } FcConfig *cfg = FcInitLoadConfigAndFonts(); FcPattern *pattern = FcNameParse((const FcChar8*)font_name); FcConfigSubstitute(cfg, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); TTF_Font *ret = NULL; FcResult result = FcResultNoMatch; FcPattern* font = FcFontMatch(cfg, pattern, &result); if (font) { FcChar8 *path = NULL; if (FcPatternGetString(font, FC_FILE, 0, &path) == FcResultMatch) { ret = TTF_OpenFont((char*)path, font_size); } FcPatternDestroy(font); } FcPatternDestroy(pattern); FcConfigDestroy(cfg); free(font_name); return ret; } SDL_Texture *create_chequered(SDL_Renderer *renderer) { SDL_RendererInfo ri; SDL_GetRendererInfo(renderer, &ri); int width = 512; int height = 512; if(ri.max_texture_width != 0 && ri.max_texture_width < width) { width = ri.max_texture_width; } if(ri.max_texture_height != 0 && ri.max_texture_height < height) { height = ri.max_texture_height; } const int box_size = 16; /* Create a chequered texture */ const unsigned char l = 196; const unsigned char d = 96; size_t pixels_len = 3 * width * height; unsigned char *pixels = malloc(pixels_len); for(int y = 0; y < height; y++) { for(int x = 0; x < width; x += box_size) { unsigned char color = l; if(((x/box_size) % 2 == 0) ^ ((y/box_size) % 2 == 0)) { color = d; } memset(pixels + 3 * x + 3 * width * y, color, 3 * box_size); } } SDL_Texture *ret = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STATIC, width, height); SDL_UpdateTexture(ret, NULL, pixels, 3 * width); free(pixels); return ret; } void imv_printf(SDL_Renderer *renderer, TTF_Font *font, int x, int y, SDL_Color *fg, SDL_Color *bg, const char *fmt, ...) { char line[512]; va_list args; va_start(args, fmt); vsnprintf(line, sizeof(line), fmt, args); SDL_Surface *surf = TTF_RenderUTF8_Blended(font, &line[0], *fg); SDL_Texture *tex = SDL_CreateTextureFromSurface(renderer, surf); SDL_Rect tex_rect = {0,0,0,0}; SDL_QueryTexture(tex, NULL, NULL, &tex_rect.w, &tex_rect.h); tex_rect.x = x; tex_rect.y = y; /* draw bg if wanted */ if(bg->a > 0) { SDL_SetRenderDrawColor(renderer, bg->r, bg->g, bg->b, bg->a); SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); SDL_RenderFillRect(renderer, &tex_rect); } SDL_RenderCopy(renderer, tex, NULL, &tex_rect); SDL_DestroyTexture(tex); SDL_FreeSurface(surf); va_end(args); } /* vim:set ts=2 sts=2 sw=2 et: */