diff --git a/include/xbm.h b/include/xbm.h index 127545da..370f87b6 100644 --- a/include/xbm.h +++ b/include/xbm.h @@ -1,6 +1,8 @@ #ifndef XBM_H #define XBM_H +#include + enum token_type { TOKEN_NONE = 0, TOKEN_IDENT, @@ -20,7 +22,7 @@ struct token { * xbm_create_bitmap - parse xbm tokens and create pixmap * @tokens: token vector */ -void xbm_create_bitmap(struct token *tokens); +cairo_surface_t *xbm_create_bitmap(struct token *tokens); /** * tokenize - tokenize xbm file diff --git a/src/theme/xbm/parse.c b/src/theme/xbm/parse.c index 6951f256..0d5820e5 100644 --- a/src/theme/xbm/parse.c +++ b/src/theme/xbm/parse.c @@ -2,12 +2,35 @@ #include #include #include +#include +#include #include "buf.h" #include "xbm.h" +static unsigned char defaultcolor[] = { 127, 127, 127, 255 }; +static unsigned char background[] = { 255, 255, 255, 255 }; + +static uint32_t *pixmap; + +static void add_pixel(int position, unsigned char *rbga) +{ + pixmap[position] = (rbga[3] << 24) | (rbga[0] << 16) | (rbga[1] << 8) | + rbga[0]; +} + +static void init_pixmap(int w, int h) +{ + static bool has_run; + if (has_run) + return; + has_run = true; + pixmap = (uint32_t *)calloc(w * h, sizeof(uint32_t)); +} + static void process_bytes(int height, int width, struct token *tokens) { + init_pixmap(width, height); struct token *t = tokens; for (int row = 0; row < height; row++) { int byte = 1; @@ -20,31 +43,49 @@ static void process_bytes(int height, int width, struct token *tokens) return; int value = (int)strtol(t->name, NULL, 0); int bit = 1 << (col % 8); - if (value & bit) + if (value & bit) { + add_pixel(row * width + col, defaultcolor); printf("."); - else + } else { + add_pixel(row * width + col, background); printf(" "); + } } ++t; printf("\n"); } } -void xbm_create_bitmap(struct token *tokens) +cairo_surface_t *xbm_create_bitmap(struct token *tokens) { + cairo_surface_t *g_surface; int width = 0, height = 0; for (struct token *t = tokens; t->type; t++) { if (width && height) { if (t->type != TOKEN_INT) continue; process_bytes(width, height, t); - return; + goto out; } if (strstr(t->name, "width")) width = atoi((++t)->name); else if (strstr(t->name, "height")) height = atoi((++t)->name); } + +out: + g_surface = + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + if (!g_surface) { + fprintf(stderr, "no surface\n"); + return NULL; + } + unsigned char *surface_data = cairo_image_surface_get_data(g_surface); + cairo_surface_flush(g_surface); + memcpy(surface_data, pixmap, width * height * 4); + free(pixmap); + cairo_surface_mark_dirty(g_surface); + return g_surface; } char *xbm_read_file(const char *filename) diff --git a/tools/xbm/xbm-parse.c b/tools/xbm/xbm-parse.c index fc9b52d8..a3fcc162 100644 --- a/tools/xbm/xbm-parse.c +++ b/tools/xbm/xbm-parse.c @@ -18,6 +18,17 @@ int main(int argc, char **argv) tokens = xbm_tokenize(buffer); free(buffer); - xbm_create_bitmap(tokens); + cairo_surface_t *surface = xbm_create_bitmap(tokens); free(tokens); + + if (!surface) + fprintf(stderr, "no surface\n"); + char png_name[1024]; + snprintf(png_name, sizeof(png_name), "%s.png", argv[1]); + if (cairo_surface_write_to_png(surface, png_name)) { + fprintf(stderr, "cannot save png\n"); + exit(EXIT_FAILURE); + } + cairo_surface_destroy(surface); + exit(EXIT_SUCCESS); }