1 /* gcc -Wall -g $(pkg-config --cflags --libs gtk+-2.0 cairo) olpc-boot.c -o olpc-boot */
18 typedef struct _anim_stage {
23 anim_stage_t timeline[] = {
28 { 1.0, ANIM_SPIN_DONE },
29 { 1.0, ANIM_OUTLINE },
34 typedef struct _state {
35 GtkWidget *drawing_area;
37 anim_state_t anim_state;
40 typedef struct _color {
46 #define HEX_COLOR(r,g,b) {(r) / 255.0, (g) / 255.0, (b) / 255.0}
48 color_t background[2] = {
49 HEX_COLOR (0x75, 0x75, 0x75),
50 HEX_COLOR (0xdb, 0xdc, 0xdf)
53 color_t xo_green = HEX_COLOR (0x4f, 0xff, 0x12);
54 color_t xo_black = HEX_COLOR (0x30, 0x30, 0x30);
55 color_t dot_gray = HEX_COLOR (0xe5, 0xe5, 0xe5);
56 color_t ring_white = HEX_COLOR (0xf1, 0xf1, 0xf1);
58 #define LERP(a,b,t) ((a) + (t) * ((b) - (a)))
59 #define LERP_COLORS(c0, c1, t) LERP((c0).r, (c1).r, (t)), \
60 LERP((c0).g, (c1).g, (t)), \
61 LERP((c0).b, (c1).b, (t))
64 set_color (cairo_t *cr, color_t *color)
66 cairo_set_source_rgb (cr, color->r, color->g, color->b);
69 #define XO_HEAD_CENTER_X 320
70 #define XO_HEAD_CENTER_Y 211.5
71 #define XO_HEAD_RADIUS 12.25
72 #define XO_BODY_CENTER_X 320
73 #define XO_BODY_CENTER_Y 250
74 #define XO_BODY_DELTA 20.5
75 #define XO_BODY_LINE_WIDTH 12.25
76 #define XO_OUTLINE_EXTRA 2.5
77 #define XO_OUTLINE_SHRINK 1.1
78 #define XO_DOTS_CENTER_X 320
79 #define XO_DOTS_CENTER_Y 240
80 #define XO_DOTS_POSITION_RADIUS 112.5
81 #define XO_DOTS_DOT_RADIUS 5.5
82 #define XO_DOTS_NUM_DOTS 30
83 #define XO_RING_CENTER_X 320
84 #define XO_RING_CENTER_Y 240
85 #define XO_RING_INNER_RADIUS 63
86 #define XO_RING_OUTER_RADIUS 118
89 draw_head (cairo_t *cr, double extra)
94 XO_HEAD_RADIUS + extra,
100 draw_body (cairo_t *cr, double extra)
103 XO_BODY_CENTER_X - XO_BODY_DELTA,
104 XO_BODY_CENTER_Y - XO_BODY_DELTA);
105 cairo_rel_line_to (cr, XO_BODY_DELTA, XO_BODY_DELTA);
106 cairo_rel_line_to (cr, XO_BODY_DELTA, -XO_BODY_DELTA);
108 XO_BODY_CENTER_X - XO_BODY_DELTA,
109 XO_BODY_CENTER_Y + XO_BODY_DELTA);
110 cairo_rel_line_to (cr, XO_BODY_DELTA, -XO_BODY_DELTA);
111 cairo_rel_line_to (cr, XO_BODY_DELTA, XO_BODY_DELTA);
112 cairo_set_line_width (cr, XO_BODY_LINE_WIDTH + 2 * extra);
113 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
118 draw_dots (cairo_t *cr)
124 set_color (cr, &dot_gray);
126 cairo_translate (cr, XO_DOTS_CENTER_X, XO_DOTS_CENTER_Y);
127 cairo_rotate (cr, - M_PI_2);
129 for (i = 0; i < XO_DOTS_NUM_DOTS; i++) {
131 XO_DOTS_POSITION_RADIUS, 0,
135 cairo_rotate (cr, 2 * M_PI / XO_DOTS_NUM_DOTS);
142 draw_ring (cairo_t *cr)
149 XO_RING_INNER_RADIUS,
154 XO_RING_OUTER_RADIUS,
156 set_color (cr, &ring_white);
158 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
165 xoboot_expose_event (GtkWidget *widget,
166 GdkEventExpose *event,
169 state_t *state = closure;
170 anim_state_t anim_state = state->anim_state;
174 cr = gdk_cairo_create (widget->window);
176 if (anim_state < ANIM_FADE)
177 set_color (cr, &background[0]);
179 set_color (cr, &background[1]);
183 if (anim_state == ANIM_BLANK)
187 if (anim_state >= ANIM_OUTLINE) {
188 set_color (cr, &xo_black);
189 draw_head (cr, XO_OUTLINE_EXTRA);
190 draw_body (cr, XO_OUTLINE_EXTRA);
191 shrink = - XO_OUTLINE_SHRINK;
194 set_color (cr, &xo_green);
196 draw_head (cr, shrink);
197 if (anim_state == ANIM_HEAD)
200 draw_body (cr, shrink);
201 if (anim_state == ANIM_BODY)
204 if (anim_state < ANIM_FADE)
216 create_window (state_t *state)
219 GtkWidget *drawing_area;
221 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
222 gtk_window_set_title (GTK_WINDOW (window), "OLPC Boot Animation Demo");
224 g_signal_connect (window, "destroy",
225 G_CALLBACK (gtk_main_quit), &window);
227 drawing_area = gtk_drawing_area_new ();
229 /* We want to force 640x480 to emulate the OLPC display */
230 gtk_widget_set_size_request (drawing_area, 640, 480);
232 gtk_container_add (GTK_CONTAINER (window), drawing_area);
234 g_signal_connect (drawing_area, "expose_event",
235 G_CALLBACK (xoboot_expose_event), state);
241 timeout_callback (gpointer closure)
243 state_t *state = closure;
246 if (state->anim_state > ANIM_DONE)
247 state->anim_state = ANIM_DONE;
249 gtk_widget_queue_draw (state->drawing_area);
255 main (int argc, char *argv[])
259 gtk_init (&argc, &argv);
261 state.drawing_area = create_window (&state);
262 state.progress = 0.0;
263 state.anim_state = 0;
265 gtk_widget_show_all (gtk_widget_get_toplevel (state.drawing_area));
267 g_timeout_add (1000, timeout_callback, &state);