Move sources into src/ and runtime files into data/.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
pepaskopec-blip 2026-09-17 17:00:57 +02:00
commit c2a632c7d6
36 changed files with 0 additions and 0 deletions

467
src/icons.c Normal file
View file

@ -0,0 +1,467 @@
#include "maturita.h"
/* Vector icons drawn with cairo so they never depend on the system
* icon theme (which is missing on some installs). */
void draw_check_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
Rgb c = color_from_hex(app_theme.on_accent);
(void)area;
(void)data;
cairo_set_source_rgb(cr, c.r, c.g, c.b);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
cairo_set_line_width(cr, width * 0.16);
cairo_move_to(cr, width * 0.24, height * 0.56);
cairo_line_to(cr, width * 0.43, height * 0.74);
cairo_line_to(cr, width * 0.78, height * 0.30);
cairo_stroke(cr);
}
/* Paint a padlock centred in the size x size box with top-left (x0,y0). */
void lock_paint(cairo_t *cr, double x0, double y0, double size,
const Rgb *c) {
double sl = MAX(1.6, size * 0.13); /* shackle stroke width */
double bw = size * 0.60; /* body width */
double bh = size * 0.44; /* body height */
double cx = x0 + size / 2.0;
double body_top = y0 + size - bh - size * 0.04;
double bx = cx - bw / 2.0;
double r = bw / 2.0 - sl / 2.0; /* shackle arc radius */
cairo_set_source_rgb(cr, c->r, c->g, c->b);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
cairo_set_line_width(cr, sl);
cairo_new_path(cr);
cairo_arc(cr, cx, body_top, r, G_PI, 2.0 * G_PI);
cairo_stroke(cr);
cairo_new_path(cr);
cairo_rectangle(cr, bx, body_top, bw, bh);
cairo_fill(cr);
cairo_new_path(cr);
cairo_arc(cr, cx, body_top + bh * 0.42, size * 0.07, 0.0, 2.0 * G_PI);
{
Rgb hole = color_from_hex(app_theme.crust);
cairo_set_source_rgb(cr, hole.r, hole.g, hole.b);
}
cairo_fill(cr);
}
void draw_lock_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
Rgb c = color_from_hex(app_theme.overlay);
(void)area;
(void)data;
lock_paint(cr, 0.0, 0.0, MIN(width, height), &c);
}
/* Wireless icon: three upward arcs that fan out from a base dot. */
void draw_wifi_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
const double s = MIN(width, height);
const double cx = width / 2.0;
const double cy = height * 0.68;
const double dot_r = s * 0.06;
const double radii[3] = {s * 0.15, s * 0.27, s * 0.39};
const double phi = 0.75;
/* Keep the icon legible on the accent-gradient bubble while giving it a
* hint of the active theme: blend the contrasting on-accent colour a
* little way towards the palette's middle accent. */
const Rgb c = mix_rgb(color_from_hex(app_theme.on_accent),
color_from_hex(app_theme.accent2), 0.22);
(void)area;
(void)data;
cairo_set_source_rgb(cr, c.r, c.g, c.b);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
cairo_set_line_width(cr, MAX(1.5, s * 0.07));
for (int i = 0; i < 3; i++) {
double r = radii[i];
cairo_new_path(cr);
cairo_arc(cr, cx, cy, r, -G_PI / 2.0 - phi, -G_PI / 2.0 + phi);
cairo_stroke(cr);
}
cairo_new_path(cr);
cairo_arc(cr, cx, cy, dot_r, 0.0, 2.0 * G_PI);
cairo_fill(cr);
}
/* CPU / chip icon for Technické vybavení. */
void draw_chip_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
const double s = MIN(width, height);
const double cx = width / 2.0;
const double cy = height / 2.0;
const double body = s * 0.42;
const double pin_len = s * 0.12;
const double pin_w = s * 0.055;
const Rgb c = mix_rgb(color_from_hex(app_theme.on_accent),
color_from_hex(app_theme.accent2), 0.22);
(void)area;
(void)data;
cairo_set_source_rgb(cr, c.r, c.g, c.b);
cairo_rectangle(cr, cx - body / 2.0, cy - body / 2.0, body, body);
cairo_fill(cr);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
cairo_set_line_width(cr, pin_w);
for (int i = 0; i < 4; i++) {
double t = (i + 0.5) / 4.0;
double x = cx - body / 2.0 + t * body;
double y = cy - body / 2.0 + t * body;
cairo_move_to(cr, x, cy - body / 2.0);
cairo_line_to(cr, x, cy - body / 2.0 - pin_len);
cairo_move_to(cr, x, cy + body / 2.0);
cairo_line_to(cr, x, cy + body / 2.0 + pin_len);
cairo_move_to(cr, cx - body / 2.0, y);
cairo_line_to(cr, cx - body / 2.0 - pin_len, y);
cairo_move_to(cr, cx + body / 2.0, y);
cairo_line_to(cr, cx + body / 2.0 + pin_len, y);
}
cairo_stroke(cr);
{
Rgb hole = color_from_hex(app_theme.crust);
double core = body * 0.34;
cairo_set_source_rgb(cr, hole.r, hole.g, hole.b);
cairo_rectangle(cr, cx - core / 2.0, cy - core / 2.0, core, core);
cairo_fill(cr);
}
}
/* Open book glyph, painted in the given colour. */
static void book_paint(cairo_t *cr, int width, int height, Rgb c) {
const double w = width;
const double h = height;
const double mid = w * 0.5;
const double gap = w * 0.045; /* spine gap so the pages read apart */
const double lmid = mid - gap;
const double rmid = mid + gap;
const double left = w * 0.13;
const double right = w * 0.87;
const double top = h * 0.24;
const double bot = h * 0.80;
cairo_set_source_rgb(cr, c.r, c.g, c.b);
cairo_new_path(cr);
cairo_move_to(cr, lmid, top);
cairo_curve_to(cr, w * 0.40, top - h * 0.07,
w * 0.24, top - h * 0.02, left, top + h * 0.07);
cairo_line_to(cr, left, bot - h * 0.05);
cairo_curve_to(cr, w * 0.24, bot - h * 0.11,
w * 0.40, bot - h * 0.05, lmid, bot);
cairo_close_path(cr);
cairo_fill(cr);
cairo_new_path(cr);
cairo_move_to(cr, rmid, top);
cairo_curve_to(cr, w * 0.60, top - h * 0.07,
w * 0.76, top - h * 0.02, right, top + h * 0.07);
cairo_line_to(cr, right, bot - h * 0.05);
cairo_curve_to(cr, w * 0.76, bot - h * 0.11,
w * 0.60, bot - h * 0.05, rmid, bot);
cairo_close_path(cr);
cairo_fill(cr);
}
/* Open book icon – used on light surfaces (cards, section headers). */
void draw_book_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
const Rgb c = mix_rgb(color_from_hex(app_theme.accent2),
color_from_hex(app_theme.accent3), 0.35);
(void)area;
(void)data;
book_paint(cr, width, height, c);
}
/* Open book icon for the accent-gradient roadmap bubbles: uses the
* contrasting on-accent colour so it stays visible on the gradient. */
void draw_book_badge_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
const Rgb c = mix_rgb(color_from_hex(app_theme.on_accent),
color_from_hex(app_theme.accent2), 0.22);
(void)area;
(void)data;
book_paint(cr, width, height, c);
}
/* Question mark in a circle – quiz. */
void draw_quiz_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
const Rgb c = color_from_hex(app_theme.accent);
PangoLayout *layout;
PangoFontDescription *fd;
int tw, th;
(void)area;
(void)data;
cairo_set_source_rgb(cr, c.r, c.g, c.b);
layout = pango_cairo_create_layout(cr);
fd = pango_font_description_new();
pango_font_description_set_weight(fd, PANGO_WEIGHT_HEAVY);
pango_font_description_set_absolute_size(
fd, MIN(width, height) * 1.05 * PANGO_SCALE);
pango_layout_set_font_description(layout, fd);
pango_layout_set_text(layout, "?", -1);
pango_layout_get_pixel_size(layout, &tw, &th);
cairo_move_to(cr, (width - tw) / 2.0, (height - th) / 2.0);
pango_cairo_show_layout(cr, layout);
pango_font_description_free(fd);
g_object_unref(layout);
}
/* Two opposing arrows – ordering / drag & drop. */
void draw_order_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
const double w = width;
const double h = height;
const Rgb c = color_from_hex(app_theme.success2);
(void)area;
(void)data;
cairo_set_source_rgb(cr, c.r, c.g, c.b);
cairo_set_line_width(cr, MAX(1.6, MIN(w, h) * 0.11));
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
cairo_new_path(cr);
cairo_move_to(cr, w * 0.36, h * 0.80);
cairo_line_to(cr, w * 0.36, h * 0.24);
cairo_move_to(cr, w * 0.22, h * 0.40);
cairo_line_to(cr, w * 0.36, h * 0.24);
cairo_line_to(cr, w * 0.50, h * 0.40);
cairo_stroke(cr);
cairo_new_path(cr);
cairo_move_to(cr, w * 0.64, h * 0.20);
cairo_line_to(cr, w * 0.64, h * 0.76);
cairo_move_to(cr, w * 0.50, h * 0.60);
cairo_line_to(cr, w * 0.64, h * 0.76);
cairo_line_to(cr, w * 0.78, h * 0.60);
cairo_stroke(cr);
}
/* Globe – the world / superpowers. */
void draw_globe_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
const double cx = width / 2.0;
const double cy = height / 2.0;
const double r = MIN(width, height) * 0.36;
const Rgb c = color_from_hex(app_theme.accent2);
(void)area;
(void)data;
cairo_set_source_rgb(cr, c.r, c.g, c.b);
cairo_set_line_width(cr, MAX(1.4, r * 0.13));
cairo_new_path(cr);
cairo_arc(cr, cx, cy, r, 0.0, 2.0 * G_PI);
cairo_stroke(cr);
cairo_save(cr);
cairo_translate(cr, cx, cy);
cairo_scale(cr, 0.52, 1.0);
cairo_new_path(cr);
cairo_arc(cr, 0.0, 0.0, r, 0.0, 2.0 * G_PI);
cairo_stroke(cr);
cairo_restore(cr);
cairo_new_path(cr);
cairo_move_to(cr, cx - r, cy);
cairo_line_to(cr, cx + r, cy);
cairo_move_to(cr, cx - r * 0.86, cy - r * 0.52);
cairo_line_to(cr, cx + r * 0.86, cy - r * 0.52);
cairo_move_to(cr, cx - r * 0.86, cy + r * 0.52);
cairo_line_to(cr, cx + r * 0.86, cy + r * 0.52);
cairo_stroke(cr);
}
/* Two people – characters. */
void draw_people_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
const Rgb c = color_from_hex(app_theme.accent3);
(void)area;
(void)data;
cairo_set_source_rgb(cr, c.r, c.g, c.b);
cairo_new_path(cr);
cairo_arc(cr, width * 0.38, height * 0.36, width * 0.15,
0.0, 2.0 * G_PI);
cairo_fill(cr);
cairo_new_path(cr);
cairo_arc(cr, width * 0.38, height * 1.02, width * 0.30,
G_PI, 2.0 * G_PI);
cairo_fill(cr);
cairo_new_path(cr);
cairo_arc(cr, width * 0.67, height * 0.42, width * 0.13,
0.0, 2.0 * G_PI);
cairo_fill(cr);
cairo_new_path(cr);
cairo_arc(cr, width * 0.67, height * 1.06, width * 0.27,
G_PI, 2.0 * G_PI);
cairo_fill(cr);
}
/* Light bulb – key terms / ideas. */
void draw_bulb_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
const double cx = width / 2.0;
const double r = MIN(width, height) * 0.30;
const double cy = height * 0.40;
const Rgb c = color_from_hex(app_theme.warning);
(void)area;
(void)data;
cairo_set_source_rgb(cr, c.r, c.g, c.b);
cairo_new_path(cr);
cairo_arc(cr, cx, cy, r, 0.0, 2.0 * G_PI);
cairo_fill(cr);
cairo_new_path(cr);
cairo_rectangle(cr, cx - r * 0.45, cy + r * 0.72,
r * 0.90, r * 0.66);
cairo_fill(cr);
cairo_new_path(cr);
cairo_arc(cr, cx, cy + r * 1.72, r * 0.52, 0.0, G_PI);
cairo_fill(cr);
}
void draw_back_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
const double size = 15.0; /* fixed logical icon size */
const double stroke = 1.8;
double ox = (width - size) / 2.0;
double oy = (height - size) / 2.0;
GtkWidget *parent = gtk_widget_get_parent(GTK_WIDGET(area));
GdkRGBA color;
(void)data;
gtk_style_context_get_color(gtk_widget_get_style_context(parent), &color);
cairo_set_source_rgb(cr, color.red, color.green, color.blue);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
cairo_set_line_width(cr, stroke);
cairo_move_to(cr, ox + size * 0.72, oy + size * 0.24);
cairo_line_to(cr, ox + size * 0.30, oy + size * 0.50);
cairo_line_to(cr, ox + size * 0.72, oy + size * 0.76);
cairo_stroke(cr);
}
void draw_settings_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
const int teeth = 8;
const double size = 16.0;
double cx = width / 2.0;
double cy = height / 2.0;
double r_outer = size * 0.48;
double r_inner = size * 0.34;
double r_hole = size * 0.16;
double tooth_half = G_PI / (double)teeth;
GtkWidget *color_w = data ? GTK_WIDGET(data)
: gtk_widget_get_parent(GTK_WIDGET(area));
GdkRGBA color;
int i;
gtk_style_context_get_color(gtk_widget_get_style_context(color_w), &color);
cairo_set_source_rgb(cr, color.red, color.green, color.blue);
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_new_path(cr);
for (i = 0; i < teeth; i++) {
double a = -G_PI / 2.0 + (2.0 * G_PI * (double)i) / (double)teeth;
double a0 = a - tooth_half * 0.55;
double a1 = a - tooth_half * 0.28;
double a2 = a + tooth_half * 0.28;
double a3 = a + tooth_half * 0.55;
if (i == 0)
cairo_move_to(cr, cx + cos(a0) * r_inner, cy + sin(a0) * r_inner);
else
cairo_line_to(cr, cx + cos(a0) * r_inner, cy + sin(a0) * r_inner);
cairo_line_to(cr, cx + cos(a1) * r_outer, cy + sin(a1) * r_outer);
cairo_line_to(cr, cx + cos(a2) * r_outer, cy + sin(a2) * r_outer);
cairo_line_to(cr, cx + cos(a3) * r_inner, cy + sin(a3) * r_inner);
}
cairo_close_path(cr);
cairo_new_sub_path(cr);
cairo_arc(cr, cx, cy, r_hole, 0.0, 2.0 * G_PI);
cairo_fill(cr);
}
void draw_stats_icon(GtkDrawingArea *area, cairo_t *cr,
int width, int height, gpointer data) {
GtkWidget *color_w = data ? GTK_WIDGET(data)
: gtk_widget_get_parent(GTK_WIDGET(area));
GdkRGBA color;
const double bar_w = 3.2;
const double gap = 2.6;
const double total_w = 3.0 * bar_w + 2.0 * gap;
const double heights[3] = {0.42, 0.72, 1.0};
double base_x = (width - total_w) / 2.0;
double base_y = height * 0.82;
double max_h = height * 0.58;
int i;
(void)area;
gtk_style_context_get_color(gtk_widget_get_style_context(color_w), &color);
cairo_set_source_rgb(cr, color.red, color.green, color.blue);
cairo_set_line_width(cr, 1.5);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
for (i = 0; i < 3; i++) {
double x = base_x + (double)i * (bar_w + gap);
double h = max_h * heights[i];
double y = base_y - h;
double r = 1.2;
cairo_new_sub_path(cr);
cairo_arc(cr, x + r, y + r, r, G_PI, 1.5 * G_PI);
cairo_arc(cr, x + bar_w - r, y + r, r, 1.5 * G_PI, 2.0 * G_PI);
cairo_line_to(cr, x + bar_w, base_y);
cairo_line_to(cr, x, base_y);
cairo_close_path(cr);
cairo_fill(cr);
}
}
GtkWidget *icon_area_new(GtkDrawingAreaDrawFunc fn,
double r, double g, double b, int px) {
Rgb *col = g_new(Rgb, 1);
GtkWidget *d = gtk_drawing_area_new();
col->r = r;
col->g = g;
col->b = b;
gtk_widget_set_size_request(d, px, px);
gtk_widget_set_halign(d, GTK_ALIGN_CENTER);
gtk_widget_set_valign(d, GTK_ALIGN_CENTER);
gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(d), fn,
col, (GDestroyNotify)g_free);
return d;
}