DVX_GUI/tools/mkicon.c

486 lines
13 KiB
C

// mkicon.c -- Generate simple 32x32 BMP icons for DVX apps
//
// Usage: mkicon <output.bmp> <type>
// Types: clock, notepad, cpanel, dvxdemo, imgview
//
// Generates recognizable pixel-art icons at 32x32 24-bit BMP.
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#define W 32
#define H 32
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 pixel(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++) {
pixel(x, y, r, g, b);
}
}
}
static void circle(int cx, int cy, int radius, uint8_t r, uint8_t g, uint8_t b) {
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
pixel(cx + x, cy + 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++) {
pixel(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++) {
pixel(x, y, r, g, b);
}
}
// No-icon placeholder: grey square with red diagonal X
static void iconNoIcon(void) {
clear(192, 192, 192);
// Border
rect(0, 0, 32, 1, 128, 128, 128);
rect(0, 31, 32, 1, 128, 128, 128);
rect(0, 0, 1, 32, 128, 128, 128);
rect(31, 0, 1, 32, 128, 128, 128);
// Red X (two diagonal lines, 2px thick)
for (int i = 4; i < 28; i++) {
pixel(i, i, 200, 40, 40);
pixel(i + 1, i, 200, 40, 40);
pixel(31 - i, i, 200, 40, 40);
pixel(30 - i, i, 200, 40, 40);
}
// "?" in the center
for (int x = 13; x <= 18; x++) { pixel(x, 8, 80, 80, 80); }
pixel(19, 9, 80, 80, 80);
pixel(19, 10, 80, 80, 80);
for (int x = 15; x <= 18; x++) { pixel(x, 11, 80, 80, 80); }
pixel(15, 12, 80, 80, 80);
pixel(15, 13, 80, 80, 80);
pixel(15, 15, 80, 80, 80);
pixel(16, 15, 80, 80, 80);
}
// Clock icon: circle with hands
static void iconClock(void) {
clear(192, 192, 192);
circle(15, 15, 13, 255, 255, 255);
circle(15, 15, 12, 240, 240, 255);
// Rim
for (int a = 0; a < 360; a++) {
double rad = a * 3.14159265 / 180.0;
int x = 15 + (int)(13.0 * __builtin_cos(rad));
int y = 15 + (int)(13.0 * __builtin_sin(rad));
pixel(x, y, 0, 0, 128);
}
// Hour marks
for (int i = 0; i < 12; i++) {
double rad = i * 30.0 * 3.14159265 / 180.0;
int x = 15 + (int)(11.0 * __builtin_cos(rad));
int y = 15 + (int)(11.0 * __builtin_sin(rad));
pixel(x, y, 0, 0, 128);
}
// Hour hand (pointing ~10 o'clock)
vline(15, 7, 8, 0, 0, 128);
// Minute hand (pointing ~2 o'clock)
for (int i = 0; i < 10; i++) {
pixel(15 + i * 2 / 3, 15 - i * 2 / 3, 0, 0, 200);
}
// Center dot
pixel(15, 15, 200, 0, 0);
}
// Notepad icon: page with lines
static void iconNotepad(void) {
clear(192, 192, 192);
rect(6, 3, 20, 26, 255, 255, 240);
// Border
hline(6, 3, 20, 0, 0, 0);
hline(6, 28, 20, 0, 0, 0);
vline(6, 3, 26, 0, 0, 0);
vline(25, 3, 26, 0, 0, 0);
// Folded corner
for (int i = 0; i < 5; i++) {
hline(21 + i, 3 + i, 5 - i, 200, 200, 180);
}
// Text lines
for (int i = 0; i < 7; i++) {
int lineW = (i == 3) ? 12 : (i == 6) ? 8 : 16;
hline(9, 8 + i * 3, lineW, 0, 0, 128);
}
}
// Control Panel icon: gear/wrench
static void iconCpanel(void) {
clear(192, 192, 192);
// Gear body
circle(15, 15, 8, 128, 128, 128);
circle(15, 15, 5, 192, 192, 192);
// Gear teeth (N/S/E/W and diagonals)
rect(13, 2, 5, 4, 128, 128, 128);
rect(13, 26, 5, 4, 128, 128, 128);
rect(2, 13, 4, 5, 128, 128, 128);
rect(26, 13, 4, 5, 128, 128, 128);
rect(4, 4, 4, 4, 128, 128, 128);
rect(24, 4, 4, 4, 128, 128, 128);
rect(4, 24, 4, 4, 128, 128, 128);
rect(24, 24, 4, 4, 128, 128, 128);
// Inner circle (hole)
circle(15, 15, 3, 64, 64, 64);
}
// DVX Demo icon: colorful diamond
static void iconDvxdemo(void) {
clear(192, 192, 192);
// Diamond shape with color gradient
for (int y = 0; y < 16; y++) {
int hw = y + 1;
for (int x = -hw; x <= hw; x++) {
int px = 15 + x;
int py = 2 + y;
uint8_t r = (uint8_t)(128 + y * 8);
uint8_t g = (uint8_t)(64 + (hw - (x < 0 ? -x : x)) * 8);
uint8_t b = (uint8_t)(200 - y * 4);
pixel(px, py, r, g, b);
}
}
for (int y = 0; y < 14; y++) {
int hw = 14 - y;
for (int x = -hw; x <= hw; x++) {
int px = 15 + x;
int py = 18 + y;
uint8_t r = (uint8_t)(255 - y * 8);
uint8_t g = (uint8_t)(128 - y * 4);
uint8_t b = (uint8_t)(100 + y * 8);
pixel(px, py, r, g, b);
}
}
}
// Image Viewer icon: landscape in a frame
static void iconImgview(void) {
clear(192, 192, 192);
// Frame
rect(3, 5, 26, 22, 100, 80, 60);
rect(5, 7, 22, 18, 135, 200, 235);
// Sun
circle(21, 11, 3, 255, 220, 50);
// Mountain
for (int y = 0; y < 10; y++) {
int w = y * 2 + 1;
hline(15 - y, 15 + y, w, 80, 140, 80);
}
// Ground
rect(5, 22, 22, 3, 60, 120, 60);
}
// DVX BASIC icon: code brackets with "B" letterform
static void iconBasic(void) {
clear(192, 192, 192);
// Blue background rectangle (code editor feel)
rect(2, 2, 28, 28, 0, 0, 128);
// Left bracket {
vline(6, 6, 20, 255, 255, 0);
hline(7, 6, 3, 255, 255, 0);
hline(7, 25, 3, 255, 255, 0);
hline(4, 15, 2, 255, 255, 0);
pixel(5, 14, 255, 255, 0);
pixel(5, 16, 255, 255, 0);
// "B" letter in white (bold, centered)
// Vertical stroke
vline(14, 7, 18, 255, 255, 255);
// Top horizontal
hline(14, 7, 7, 255, 255, 255);
hline(14, 8, 7, 255, 255, 255);
// Middle horizontal
hline(14, 15, 7, 255, 255, 255);
hline(14, 16, 7, 255, 255, 255);
// Bottom horizontal
hline(14, 23, 7, 255, 255, 255);
hline(14, 24, 7, 255, 255, 255);
// Right curves of B (top bump)
vline(21, 8, 7, 255, 255, 255);
pixel(20, 8, 255, 255, 255);
pixel(20, 14, 255, 255, 255);
// Right curves of B (bottom bump)
vline(21, 17, 6, 255, 255, 255);
pixel(20, 17, 255, 255, 255);
pixel(20, 23, 255, 255, 255);
// Right bracket }
vline(25, 6, 20, 255, 255, 0);
hline(22, 6, 3, 255, 255, 0);
hline(22, 25, 3, 255, 255, 0);
hline(26, 15, 2, 255, 255, 0);
pixel(26, 14, 255, 255, 0);
pixel(26, 16, 255, 255, 0);
}
static void iconHelp(void) {
// Blue book with white "?" on it
clear(192, 192, 192);
// Book body (blue)
rect(6, 4, 20, 24, 0, 0, 180);
// Book spine (darker blue)
rect(6, 4, 3, 24, 0, 0, 130);
// Book pages (white edge)
vline(25, 5, 22, 255, 255, 255);
// Question mark in white
// Top curve
hline(14, 9, 5, 255, 255, 255);
pixel(13, 10, 255, 255, 255);
pixel(19, 10, 255, 255, 255);
pixel(19, 11, 255, 255, 255);
pixel(18, 12, 255, 255, 255);
pixel(17, 13, 255, 255, 255);
// Stem
pixel(16, 14, 255, 255, 255);
pixel(16, 15, 255, 255, 255);
pixel(16, 16, 255, 255, 255);
// Dot
pixel(16, 19, 255, 255, 255);
pixel(16, 20, 255, 255, 255);
}
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));
// BMP header
header[0] = 'B';
header[1] = 'M';
*(int32_t *)&header[2] = fileSize;
*(int32_t *)&header[10] = 54;
// DIB header
*(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);
// BMP rows are bottom-to-top
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);
}
// Icon editor: pixel grid with pencil drawing a pixel
static void iconIconEd(void) {
clear(220, 220, 220);
// Draw a 5x5 grid of colored pixels (the "canvas")
int gx = 3;
int gy = 3;
int cs = 5;
// Grid lines
for (int i = 0; i <= 5; i++) {
hline(gx, gy + i * cs, 5 * cs + 1, 160, 160, 160);
vline(gx + i * cs, gy, 5 * cs + 1, 160, 160, 160);
}
// Some colored pixels in the grid
rect(gx + 1, gy + 1, cs - 1, cs - 1, 255, 0, 0);
rect(gx + cs + 1, gy + 1, cs - 1, cs - 1, 0, 0, 255);
rect(gx + 1, gy + cs + 1, cs - 1, cs - 1, 0, 180, 0);
rect(gx + cs + 1, gy + cs + 1, cs - 1, cs - 1, 255, 255, 0);
rect(gx + 2*cs+1, gy + 2*cs+1, cs - 1, cs - 1, 255, 128, 0);
rect(gx + 3*cs+1, gy + 1, cs - 1, cs - 1, 128, 0, 255);
// Pencil (diagonal, bottom-right area)
for (int i = 0; i < 12; i++) {
pixel(18 + i, 28 - i, 230, 200, 80);
pixel(19 + i, 28 - i, 230, 200, 80);
pixel(18 + i, 29 - i, 230, 200, 80);
}
// Pencil tip
pixel(17, 29, 40, 40, 40);
pixel(17, 30, 40, 40, 40);
pixel(18, 30, 40, 40, 40);
// Eraser end
pixel(29, 17, 240, 150, 150);
pixel(30, 16, 240, 150, 150);
pixel(30, 17, 240, 150, 150);
pixel(29, 16, 240, 150, 150);
// Border
rect(0, 0, 32, 1, 128, 128, 128);
rect(0, 31, 32, 1, 128, 128, 128);
rect(0, 0, 1, 32, 128, 128, 128);
rect(31, 0, 1, 32, 128, 128, 128);
}
// Resource editor: box with stacked resource entries
static void iconResedit(void) {
clear(220, 220, 220);
// Outer box (document frame)
rect(3, 2, 26, 28, 255, 255, 255);
rect(3, 2, 26, 1, 80, 80, 80);
rect(3, 29, 26, 1, 80, 80, 80);
rect(3, 2, 1, 28, 80, 80, 80);
rect(28, 2, 1, 28, 80, 80, 80);
// Title bar
rect(4, 3, 24, 4, 0, 0, 128);
// Resource entry rows (alternating light shading)
rect(4, 8, 24, 4, 240, 240, 255);
rect(4, 12, 24, 1, 180, 180, 200);
rect(4, 13, 24, 4, 255, 255, 255);
rect(4, 17, 24, 1, 180, 180, 200);
rect(4, 18, 24, 4, 240, 240, 255);
rect(4, 22, 24, 1, 180, 180, 200);
rect(4, 23, 24, 4, 255, 255, 255);
// Type indicator colored dots in each row
circle(8, 10, 1, 0, 160, 0); // icon (green)
circle(8, 15, 1, 0, 0, 200); // text (blue)
circle(8, 20, 1, 200, 0, 0); // binary (red)
circle(8, 25, 1, 0, 0, 200); // text (blue)
// Short "name" bars in each row
rect(11, 9, 10, 2, 60, 60, 60);
rect(11, 14, 14, 2, 60, 60, 60);
rect(11, 19, 8, 2, 60, 60, 60);
rect(11, 24, 12, 2, 60, 60, 60);
// Border
rect(0, 0, 32, 1, 128, 128, 128);
rect(0, 31, 32, 1, 128, 128, 128);
rect(0, 0, 1, 32, 128, 128, 128);
rect(31, 0, 1, 32, 128, 128, 128);
}
int main(int argc, char **argv) {
if (argc < 3) {
fprintf(stderr, "Usage: mkicon <output.bmp> <type>\n");
fprintf(stderr, "Types: noicon, clock, notepad, cpanel, dvxdemo, imgview, basic, help, iconed, resedit\n");
return 1;
}
const char *path = argv[1];
const char *type = argv[2];
if (strcmp(type, "noicon") == 0) {
iconNoIcon();
} else if (strcmp(type, "clock") == 0) {
iconClock();
} else if (strcmp(type, "notepad") == 0) {
iconNotepad();
} else if (strcmp(type, "cpanel") == 0) {
iconCpanel();
} else if (strcmp(type, "dvxdemo") == 0) {
iconDvxdemo();
} else if (strcmp(type, "basic") == 0) {
iconBasic();
} else if (strcmp(type, "imgview") == 0) {
iconImgview();
} else if (strcmp(type, "help") == 0) {
iconHelp();
} else if (strcmp(type, "iconed") == 0) {
iconIconEd();
} else if (strcmp(type, "resedit") == 0) {
iconResedit();
} else {
fprintf(stderr, "Unknown icon type: %s\n", type);
return 1;
}
writeBmp(path);
printf("Generated %s (%s)\n", path, type);
return 0;
}