maturita.c/icons.c

467 lines
16 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}