1 /* gcc -Wall -g $(pkg-config --cflags --libs gtk+-2.0 cairo) olpc-boot.c -o olpc-boot */
18 typedef struct _timeline {
24 timeline_t timeline[] = {
25 { 0.5, ANIM_BLANK, 0.0},
26 { 1.0, ANIM_HEAD, 0.0},
27 { 2.0, ANIM_BODY, 0.0},
28 { 7.0, ANIM_SPIN, 6.0},
29 { 1.0, ANIM_SPIN_DONE, 0.0},
30 { 1.0, ANIM_OUTLINE, 0.0},
31 { 1.0, ANIM_FADE, 0.5},
35 typedef struct _state {
36 GtkWidget *drawing_area;
38 anim_stage_t anim_stage;
41 typedef struct _color {
47 #define HEX_COLOR(r,g,b) {(r) / 255.0, (g) / 255.0, (b) / 255.0}
49 color_t background[2] = {
50 HEX_COLOR (0x75, 0x75, 0x75),
51 HEX_COLOR (0xdb, 0xdc, 0xdf)
54 color_t xo_green = HEX_COLOR (0x4f, 0xff, 0x12);
55 color_t xo_black = HEX_COLOR (0x30, 0x30, 0x30);
56 color_t dot_gray = HEX_COLOR (0xe5, 0xe5, 0xe5);
57 color_t ring_white = HEX_COLOR (0xf1, 0xf1, 0xf1);
59 #define LERP(a,b,t) ((a) + (t) * ((b) - (a)))
60 #define LERP_COLORS(c0, c1, t) LERP((c0).r, (c1).r, (t)), \
61 LERP((c0).g, (c1).g, (t)), \
62 LERP((c0).b, (c1).b, (t))
65 set_color (cairo_t *cr, color_t *color)
67 cairo_set_source_rgb (cr, color->r, color->g, color->b);
70 #define XO_HEAD_CENTER_X 320
71 #define XO_HEAD_CENTER_Y 211.5
72 #define XO_HEAD_RADIUS 12.25
73 #define XO_BODY_CENTER_X 320
74 #define XO_BODY_CENTER_Y 250
75 #define XO_BODY_DELTA 20.5
76 #define XO_BODY_LINE_WIDTH 12.25
77 #define XO_OUTLINE_EXTRA 2.5
78 #define XO_OUTLINE_SHRINK 1.1
79 #define XO_DOTS_CENTER_X 320
80 #define XO_DOTS_CENTER_Y 240
81 #define XO_DOTS_POSITION_RADIUS 112.5
82 #define XO_DOTS_DOT_RADIUS 5.5
83 #define XO_DOTS_NUM_DOTS 30
84 #define XO_RING_CENTER_X 320
85 #define XO_RING_CENTER_Y 240
86 #define XO_RING_INNER_RADIUS 63
87 #define XO_RING_OUTER_RADIUS 118
90 draw_head (cairo_t *cr, double extra)
95 XO_HEAD_RADIUS + extra,
101 draw_body (cairo_t *cr, double extra)
104 XO_BODY_CENTER_X - XO_BODY_DELTA,
105 XO_BODY_CENTER_Y - XO_BODY_DELTA);
106 cairo_rel_line_to (cr, XO_BODY_DELTA, XO_BODY_DELTA);
107 cairo_rel_line_to (cr, XO_BODY_DELTA, -XO_BODY_DELTA);
109 XO_BODY_CENTER_X - XO_BODY_DELTA,
110 XO_BODY_CENTER_Y + XO_BODY_DELTA);
111 cairo_rel_line_to (cr, XO_BODY_DELTA, -XO_BODY_DELTA);
112 cairo_rel_line_to (cr, XO_BODY_DELTA, XO_BODY_DELTA);
113 cairo_set_line_width (cr, XO_BODY_LINE_WIDTH + 2 * extra);
114 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
119 draw_dots (cairo_t *cr)
125 set_color (cr, &dot_gray);
127 cairo_translate (cr, XO_DOTS_CENTER_X, XO_DOTS_CENTER_Y);
128 cairo_rotate (cr, - M_PI_2);
130 for (i = 0; i < XO_DOTS_NUM_DOTS; i++) {
132 XO_DOTS_POSITION_RADIUS, 0,
136 cairo_rotate (cr, 2 * M_PI / XO_DOTS_NUM_DOTS);
143 draw_ring (cairo_t *cr)
150 XO_RING_INNER_RADIUS,
155 XO_RING_OUTER_RADIUS,
157 set_color (cr, &ring_white);
159 cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
166 xoboot_expose_event (GtkWidget *widget,
167 GdkEventExpose *event,
170 state_t *state = closure;
171 anim_stage_t anim_stage = state->anim_stage;
175 cr = gdk_cairo_create (widget->window);
177 if (anim_stage < ANIM_FADE)
178 set_color (cr, &background[0]);
180 set_color (cr, &background[1]);
184 if (anim_stage == ANIM_BLANK)
188 if (anim_stage >= ANIM_OUTLINE) {
189 set_color (cr, &xo_black);
190 draw_head (cr, XO_OUTLINE_EXTRA);
191 draw_body (cr, XO_OUTLINE_EXTRA);
192 shrink = - XO_OUTLINE_SHRINK;
195 set_color (cr, &xo_green);
197 draw_head (cr, shrink);
198 if (anim_stage == ANIM_HEAD)
201 draw_body (cr, shrink);
202 if (anim_stage == ANIM_BODY)
205 if (anim_stage < ANIM_FADE)
217 create_window (state_t *state)
220 GtkWidget *drawing_area;
222 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
223 gtk_window_set_title (GTK_WINDOW (window), "OLPC Boot Animation Demo");
225 g_signal_connect (window, "destroy",
226 G_CALLBACK (gtk_main_quit), &window);
228 drawing_area = gtk_drawing_area_new ();
230 /* We want to force 640x480 to emulate the OLPC display */
231 gtk_widget_set_size_request (drawing_area, 640, 480);
233 gtk_container_add (GTK_CONTAINER (window), drawing_area);
235 g_signal_connect (drawing_area, "expose_event",
236 G_CALLBACK (xoboot_expose_event), state);
242 timeline_advance (gpointer closure)
244 state_t *state = closure;
246 if (state->anim_stage == ANIM_DONE)
250 gtk_widget_queue_draw (state->drawing_area);
256 main (int argc, char *argv[])
260 gtk_init (&argc, &argv);
262 state.drawing_area = create_window (&state);
263 state.progress = 0.0;
264 state.anim_stage = 0;
266 gtk_widget_show_all (gtk_widget_get_toplevel (state.drawing_area));
268 g_timeout_add (1000, timeline_advance, &state);