335 lines
8.6 KiB
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;
|
|
}
|