// Expects icons-master/ to contain the contents of https://github.com/elementary/icons. // You can find the license for the elementary Icon pack in "res/Icons/elementary Icons License.txt". // The utility produces "res/Icons/elementary Icons.icon_pack". This is a pre-parsed format of the SVG files. #include #include #include #include #include #define NANOSVG_IMPLEMENTATION #include "nanosvg.h" #include "stb_ds.h" void BlendPixel(uint32_t *a, uint32_t b, bool c) {} #define EsCRTsqrtf sqrtf #define EsAssert assert #define EsHeapAllocate(x, y) ((y) ? calloc(1, (x)) : malloc((x))) #define EsHeapFree free #define EsCRTfabsf fabsf #define EsCRTfmodf fmodf #define EsCRTisnanf isnan #define EsCRTfloorf floorf #define AbsoluteFloat fabsf #define EsCRTatan2f atan2f #define EsCRTsinf sinf #define EsCRTcosf cosf #define EsCRTacosf acosf #define EsCRTceilf ceilf #define ES_INFINITY INFINITY #define IN_DESIGNER #include "../desktop/renderer.cpp" const char *metadataFiles[] = { "COPYING", "README.md", }; uint32_t checkShape = 0x12, checkPath = 0x34, zero = 0; void OutputPaint(NSVGpaint paint, FILE *pack) { fwrite(&paint.type, 1, sizeof(char), pack); if (paint.type == NSVG_PAINT_COLOR) { fwrite(&paint.color, 1, sizeof(unsigned int), pack); } else if (paint.type == NSVG_PAINT_LINEAR_GRADIENT || paint.type == NSVG_PAINT_RADIAL_GRADIENT) { fwrite(&paint.gradient->xform, 1, 6 * sizeof(float), pack); { char spread = 0; if (paint.gradient->spread == NSVG_SPREAD_PAD) { spread = RAST_REPEAT_CLAMP; } else if (paint.gradient->spread == NSVG_SPREAD_REFLECT) { spread = RAST_REPEAT_MIRROR; } else if (paint.gradient->spread == NSVG_SPREAD_REPEAT) { spread = RAST_REPEAT_NORMAL; } fwrite(&spread, 1, sizeof(char), pack); } fwrite(&paint.gradient->fx, 1, sizeof(float), pack); fwrite(&paint.gradient->fy, 1, sizeof(float), pack); fwrite(&paint.gradient->nstops, 1, sizeof(int), pack); for (int i = 0; i < paint.gradient->nstops; i++) { fwrite(&paint.gradient->stops[i].color, 1, sizeof(unsigned int), pack); fwrite(&paint.gradient->stops[i].offset, 1, sizeof(float), pack); } } } void OutputPath(NSVGpath *path, FILE *pack) { next:; fwrite(&checkPath, 1, sizeof(uint8_t), pack); fwrite(&path->npts, 1, sizeof(int), pack); fwrite(&path->closed, 1, sizeof(char), pack); for (int i = 0; i < path->npts; i++) { fwrite(&path->pts[i * 2 + 0], 1, sizeof(float), pack); fwrite(&path->pts[i * 2 + 1], 1, sizeof(float), pack); } path = path->next; if (path) goto next; else fwrite(&zero, 1, sizeof(uint8_t), pack); } void OutputShape(NSVGshape *shape, FILE *pack) { next:; if (!shape) { fwrite(&zero, 1, sizeof(uint8_t), pack); return; } if (shape->flags & NSVG_FLAGS_VISIBLE) { fwrite(&checkShape, 1, sizeof(uint8_t), pack); fwrite(&shape->opacity, 1, sizeof(float), pack); fwrite(&shape->strokeWidth, 1, sizeof(float), pack); fwrite(&shape->strokeDashOffset, 1, sizeof(float), pack); fwrite(&shape->strokeDashArray, 1, 8 * sizeof(float), pack); fwrite(&shape->strokeDashCount, 1, sizeof(char), pack); { char join = 0; if (shape->strokeLineJoin == NSVG_JOIN_MITER) { join = RAST_LINE_JOIN_MITER; } else if (shape->strokeLineJoin == NSVG_JOIN_ROUND) { join = RAST_LINE_JOIN_ROUND; } else if (shape->strokeLineJoin == NSVG_JOIN_BEVEL) { join = RAST_LINE_JOIN_MITER; shape->miterLimit = 0; } fwrite(&join, 1, sizeof(char), pack); } { char cap = 0; if (shape->strokeLineCap == NSVG_CAP_BUTT) { cap = RAST_LINE_CAP_FLAT; } else if (shape->strokeLineCap == NSVG_CAP_ROUND) { cap = RAST_LINE_CAP_ROUND; } else if (shape->strokeLineCap == NSVG_CAP_SQUARE) { cap = RAST_LINE_CAP_SQUARE; } fwrite(&cap, 1, sizeof(char), pack); } fwrite(&shape->miterLimit, 1, sizeof(float), pack); fwrite(&shape->fillRule, 1, sizeof(char), pack); OutputPaint(shape->fill, pack); OutputPaint(shape->stroke, pack); OutputPath(shape->paths, pack); } shape = shape->next; goto next; } void OutputImage(NSVGimage *image, FILE *pack) { fwrite(&image->width, 1, sizeof(float), pack); fwrite(&image->height, 1, sizeof(float), pack); OutputShape(image->shapes, pack); } char buffer[65536]; typedef struct Icon { char group[128], name[128]; bool metadata; } Icon; void GenerateMainIconPack() { Icon *icons = NULL; { FILE *f = fopen("desktop/icons.header", "wb"); fprintf(f, "%s", "inttype EsStandardIcon enum none { // Taken from the elementary icon pack, see res/Icons for license.\n\tES_ICON_NONE\n"); fclose(f); } { system("find bin/icons-master/ -name *.svg -type f | grep -v cursors | awk -F '/' 'BEGIN { OFS=\" \" } { print $3, $5 }' | awk -F '.' '{ print $1 }'" " | tr '-' '_' | grep -v '_rtl' | tr '_' '-' | sort -u > icons.txt"); system("awk -F ' ' 'BEGIN { OFS=\"\" } { print \"\tES_ICON_\", $2 }' icons.txt | tr '[:lower:]' '[:upper:]'" " | tr '+-' '__' >> desktop/icons.header"); system("echo '}' >> desktop/icons.header"); FILE *iconList = fopen("icons.txt", "rb"); Icon icon = {}; while (fscanf(iconList, "%s %s\n", icon.group, icon.name) == 2) { arrput(icons, icon); } fclose(iconList); system("rm icons.txt"); for (uintptr_t i = 0; i < sizeof(metadataFiles) / sizeof(metadataFiles[0]); i++) { icon.metadata = true; strcpy(icon.name, metadataFiles[i]); arrput(icons, icon); } } FILE *pack = fopen("res/Themes/elementary Icons.dat", "wb"); uint32_t zero = 0; uint32_t count = arrlen(icons); fwrite(&count, 1, sizeof(uint32_t), pack); for (int i = 0; i < arrlen(icons); i++) fwrite(&zero, 1, sizeof(uint32_t), pack); int total = 0; for (int i = 0; i < arrlen(icons); i++) { Icon *icon = icons + i; uint32_t offset = ftell(pack); fseek(pack, (i + 1) * sizeof(uint32_t), SEEK_SET); fwrite(&offset, 1, sizeof(uint32_t), pack); fseek(pack, offset, SEEK_SET); if (icon->metadata) { sprintf(buffer, "bin/icons-master/%s", icon->name); FILE *f = fopen(buffer, "rb"); fwrite(buffer, 1, fread(buffer, 1, 65536, f), pack); fclose(f); } else { printf("%s %s\n", icon->group, icon->name); uint32_t variants[] = { 1 /* Symbolic */, 16, 21, 24, 32, 48, 64, 128, 1 | 0x8000, 16 | 0x8000, 21 | 0x8000, 24 | 0x8000, 32 | 0x8000, 48 | 0x8000, 64 | 0x8000, 128 | 0x8000 }; for (uint32_t i = 0; i < sizeof(variants) / sizeof(variants[0]); i++) { if ((variants[i] & 0x7FFF) != 1) { sprintf(buffer, "bin/icons-master/%s/%d/%s%s.svg", icon->group, variants[i] & 0x7FFF, icon->name, (variants[i] & 0x8000) ? "-rtl" : ""); } else { sprintf(buffer, "bin/icons-master/%s/symbolic/%s%s.svg", icon->group, icon->name, (variants[i] & 0x8000) ? "-rtl" : ""); } NSVGimage *image = nsvgParseFromFile(buffer, "px", 96.0f); if (image) { printf("\t%s\n", buffer); total++; fwrite(&variants[i], 1, sizeof(uint32_t), pack); uint32_t skip = ftell(pack); fwrite(&zero, 1, sizeof(uint32_t), pack); OutputImage(image, pack); nsvgDelete(image); uint32_t restore = ftell(pack); fseek(pack, skip, SEEK_SET); fwrite(&restore, 1, sizeof(uint32_t), pack); fseek(pack, restore, SEEK_SET); } else { // printf("\tcould not find %s\n", buffer); } } fwrite(&zero, 1, sizeof(uint32_t), pack); } } fclose(pack); printf("total = %d\n", total); } int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } if (0 == strcmp(argv[1], "generate-main-icon-pack")) { GenerateMainIconPack(); } else if (0 == strcmp(argv[1], "convert")) { if (argc != 4) { fprintf(stderr, "Usage: %s convert \n", argv[0]); return 1; } NSVGimage *image = nsvgParseFromFile(argv[2], "px", 96.0f); FILE *f = fopen(argv[3], "wb"); if (!image) { fprintf(stderr, "Error: Could not access/parse file '%s'.\n", argv[2]); return 1; } if (!f) { fprintf(stderr, "Error: Could not access/parse file '%s'.\n", argv[3]); return 1; } OutputImage(image, f); } return 0; }