DVX_GUI/tools/mktbicon.c

335 lines
8.6 KiB
C

// mktbicon.c -- Generate 16x16 BMP toolbar icons for DVX BASIC IDE
//
// Usage: mktbicon <output.bmp> <type>
// Types: open, save, run, stop, code, design
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#define W 16
#define H 16
static uint8_t pixels[H][W][3]; // BGR
static void clear(uint8_t r, uint8_t g, uint8_t b) {
for (int y = 0; y < H; y++) {
for (int x = 0; x < W; x++) {
pixels[y][x][0] = b;
pixels[y][x][1] = g;
pixels[y][x][2] = r;
}
}
}
static void px(int x, int y, uint8_t r, uint8_t g, uint8_t b) {
if (x >= 0 && x < W && y >= 0 && y < H) {
pixels[y][x][0] = b;
pixels[y][x][1] = g;
pixels[y][x][2] = r;
}
}
static void rect(int x0, int y0, int w, int h, uint8_t r, uint8_t g, uint8_t b) {
for (int y = y0; y < y0 + h && y < H; y++) {
for (int x = x0; x < x0 + w && x < W; x++) {
px(x, y, r, g, b);
}
}
}
static void hline(int x0, int y, int w, uint8_t r, uint8_t g, uint8_t b) {
for (int x = x0; x < x0 + w; x++) {
px(x, y, r, g, b);
}
}
static void vline(int x, int y0, int h, uint8_t r, uint8_t g, uint8_t b) {
for (int y = y0; y < y0 + h; y++) {
px(x, y, r, g, b);
}
}
static void outline(int x0, int y0, int w, int h, uint8_t r, uint8_t g, uint8_t b) {
hline(x0, y0, w, r, g, b);
hline(x0, y0 + h - 1, w, r, g, b);
vline(x0, y0, h, r, g, b);
vline(x0 + w - 1, y0, h, r, g, b);
}
// Open: folder icon (yellow folder with tab)
static void iconOpen(void) {
clear(192, 192, 192);
// Folder body
rect(1, 5, 14, 9, 220, 180, 50);
outline(1, 5, 14, 9, 160, 120, 20);
// Folder tab
rect(2, 3, 5, 3, 220, 180, 50);
hline(2, 3, 5, 160, 120, 20);
vline(2, 3, 2, 160, 120, 20);
vline(6, 3, 2, 160, 120, 20);
// Front flap (lighter)
rect(2, 7, 12, 6, 240, 210, 80);
hline(2, 7, 12, 160, 120, 20);
}
// Save: floppy disk icon (blue disk)
static void iconSave(void) {
clear(192, 192, 192);
// Disk body
rect(2, 1, 12, 14, 60, 60, 160);
outline(2, 1, 12, 14, 30, 30, 100);
// Metal slider (silver top)
rect(5, 1, 6, 5, 200, 200, 200);
outline(5, 1, 6, 5, 120, 120, 120);
// Slot in metal
rect(7, 2, 2, 3, 60, 60, 160);
// Label (white bottom)
rect(4, 9, 8, 5, 240, 240, 240);
outline(4, 9, 8, 5, 120, 120, 120);
// Lines on label
hline(5, 11, 6, 160, 160, 160);
hline(5, 12, 6, 160, 160, 160);
}
// Run: green play triangle
static void iconRun(void) {
clear(192, 192, 192);
// Play triangle pointing right
for (int y = 0; y < 12; y++) {
int w = (y < 6) ? y + 1 : 12 - y;
hline(4, 2 + y, w, 0, 160, 0);
}
// Darker outline on top and bottom edges
for (int y = 0; y < 12; y++) {
int w = (y < 6) ? y + 1 : 12 - y;
px(4, 2 + y, 0, 100, 0);
px(4 + w - 1, 2 + y, 0, 100, 0);
}
}
// Stop: red square
static void iconStop(void) {
clear(192, 192, 192);
rect(3, 3, 10, 10, 200, 40, 40);
outline(3, 3, 10, 10, 140, 20, 20);
}
// Code: text/code icon (page with angle brackets)
static void iconCode(void) {
clear(192, 192, 192);
// Page
rect(3, 1, 10, 14, 255, 255, 255);
outline(3, 1, 10, 14, 80, 80, 80);
// Dog-ear fold
rect(10, 1, 3, 3, 192, 192, 192);
hline(10, 3, 3, 80, 80, 80);
vline(10, 1, 3, 80, 80, 80);
px(10, 1, 80, 80, 80);
px(11, 2, 80, 80, 80);
px(12, 3, 80, 80, 80);
// "<" bracket
px(5, 6, 0, 0, 180);
px(4, 7, 0, 0, 180);
px(5, 8, 0, 0, 180);
// ">" bracket
px(9, 6, 0, 0, 180);
px(10, 7, 0, 0, 180);
px(9, 8, 0, 0, 180);
// "/" between
px(8, 5, 0, 0, 180);
px(7, 7, 0, 0, 180);
px(6, 9, 0, 0, 180);
// Text lines
hline(5, 11, 6, 160, 160, 160);
hline(5, 13, 4, 160, 160, 160);
}
// Design: form/window with grid dots
static void iconDesign(void) {
clear(192, 192, 192);
// Window frame
rect(1, 1, 14, 14, 255, 255, 255);
outline(1, 1, 14, 14, 0, 0, 128);
// Title bar
rect(2, 2, 12, 3, 0, 0, 128);
// Grid dots
for (int y = 7; y < 14; y += 2) {
for (int x = 3; x < 14; x += 2) {
px(x, y, 160, 160, 160);
}
}
// Small widget rectangle in the form
rect(4, 8, 6, 3, 192, 192, 192);
outline(4, 8, 6, 3, 80, 80, 80);
}
// Debug: bug icon with magnifying glass
static void iconDebug(void) {
clear(192, 192, 192);
// Bug body
rect(5, 4, 6, 8, 60, 160, 60);
outline(5, 4, 6, 8, 0, 100, 0);
// Bug head
rect(6, 2, 4, 3, 60, 160, 60);
outline(6, 2, 4, 3, 0, 100, 0);
// Antennae
px(6, 1, 0, 100, 0); px(5, 0, 0, 100, 0);
px(9, 1, 0, 100, 0); px(10, 0, 0, 100, 0);
// Legs
px(4, 6, 0, 100, 0); px(3, 5, 0, 100, 0);
px(4, 8, 0, 100, 0); px(3, 8, 0, 100, 0);
px(4, 10, 0, 100, 0); px(3, 11, 0, 100, 0);
px(11, 6, 0, 100, 0); px(12, 5, 0, 100, 0);
px(11, 8, 0, 100, 0); px(12, 8, 0, 100, 0);
px(11, 10, 0, 100, 0); px(12, 11, 0, 100, 0);
}
// Step Into: arrow pointing down into a line
static void iconStepInto(void) {
clear(192, 192, 192);
// Vertical arrow shaft
vline(8, 2, 8, 0, 0, 180);
// Arrow head
hline(6, 10, 5, 0, 0, 180);
hline(7, 11, 3, 0, 0, 180);
px(8, 12, 0, 0, 180);
// Horizontal line (code line)
hline(3, 14, 10, 80, 80, 80);
}
// Step Over: arrow curving over a line
static void iconStepOver(void) {
clear(192, 192, 192);
// Arc over
hline(4, 3, 8, 0, 0, 180);
vline(3, 4, 3, 0, 0, 180);
vline(12, 4, 5, 0, 0, 180);
px(4, 3, 0, 0, 180);
px(11, 3, 0, 0, 180);
// Arrow head pointing down
hline(10, 9, 5, 0, 0, 180);
hline(11, 10, 3, 0, 0, 180);
px(12, 11, 0, 0, 180);
// Code line
hline(3, 14, 10, 80, 80, 80);
}
// Step Out: arrow pointing up out of a bracket
static void iconStepOut(void) {
clear(192, 192, 192);
// Vertical arrow shaft going up
vline(8, 2, 8, 0, 0, 180);
// Arrow head pointing up
hline(6, 4, 5, 0, 0, 180);
hline(7, 3, 3, 0, 0, 180);
px(8, 2, 0, 0, 180);
// Bracket (representing the function)
vline(4, 10, 4, 80, 80, 80);
hline(4, 10, 3, 80, 80, 80);
hline(4, 13, 3, 80, 80, 80);
vline(11, 10, 4, 80, 80, 80);
hline(9, 10, 3, 80, 80, 80);
hline(9, 13, 3, 80, 80, 80);
}
// Run to Cursor: arrow pointing right to a cursor line
static void iconRunToCursor(void) {
clear(192, 192, 192);
// Horizontal arrow
hline(2, 7, 8, 0, 0, 180);
// Arrow head
vline(10, 5, 5, 0, 0, 180);
vline(11, 6, 3, 0, 0, 180);
px(12, 7, 0, 0, 180);
// Cursor (text cursor line)
vline(14, 3, 10, 200, 0, 0);
}
static void writeBmp(const char *path) {
int32_t rowPad = (4 - (W * 3) % 4) % 4;
int32_t rowSize = W * 3 + rowPad;
int32_t dataSize = rowSize * H;
int32_t fileSize = 54 + dataSize;
uint8_t header[54];
memset(header, 0, sizeof(header));
header[0] = 'B';
header[1] = 'M';
*(int32_t *)&header[2] = fileSize;
*(int32_t *)&header[10] = 54;
*(int32_t *)&header[14] = 40;
*(int32_t *)&header[18] = W;
*(int32_t *)&header[22] = H;
*(int16_t *)&header[26] = 1;
*(int16_t *)&header[28] = 24;
*(int32_t *)&header[34] = dataSize;
FILE *f = fopen(path, "wb");
if (!f) {
fprintf(stderr, "Cannot write: %s\n", path);
return;
}
fwrite(header, 1, 54, f);
uint8_t pad[3] = {0};
for (int y = H - 1; y >= 0; y--) {
fwrite(pixels[y], 1, W * 3, f);
if (rowPad > 0) {
fwrite(pad, 1, rowPad, f);
}
}
fclose(f);
}
int main(int argc, char **argv) {
if (argc < 3) {
fprintf(stderr, "Usage: mktbicon <output.bmp> <type>\n");
fprintf(stderr, "Types: open, save, run, stop, code, design\n");
return 1;
}
const char *path = argv[1];
const char *type = argv[2];
if (strcmp(type, "open") == 0) { iconOpen(); }
else if (strcmp(type, "save") == 0) { iconSave(); }
else if (strcmp(type, "run") == 0) { iconRun(); }
else if (strcmp(type, "stop") == 0) { iconStop(); }
else if (strcmp(type, "code") == 0) { iconCode(); }
else if (strcmp(type, "design") == 0) { iconDesign(); }
else if (strcmp(type, "debug") == 0) { iconDebug(); }
else if (strcmp(type, "stepinto") == 0) { iconStepInto(); }
else if (strcmp(type, "stepover") == 0) { iconStepOver(); }
else if (strcmp(type, "stepout") == 0) { iconStepOut(); }
else if (strcmp(type, "runtocur") == 0) { iconRunToCursor(); }
else {
fprintf(stderr, "Unknown icon type: %s\n", type);
return 1;
}
writeBmp(path);
printf("Generated %s (%s)\n", path, type);
return 0;
}