]> git.cworth.org Git - wordgame/blob - demo-item.c
Add a 3D "etched" effect to the lettering.
[wordgame] / demo-item.c
1 /*
2  * GooCanvas Demo. Copyright (C) 2006 Damon Chaplin.
3  * Released under the GNU LGPL license. See COPYING for details.
4  *
5  * demo-item.c - a simple demo item.
6  */
7 #include <math.h>
8
9 #include "goocanvas.h"
10 #include "demo-item.h"
11
12 /* Use the GLib convenience macro to define the type. GooDemoItem is the
13    class struct, goo_demo_item is the function prefix, and our class is a
14    subclass of GOO_TYPE_CANVAS_ITEM_SIMPLE. */
15 G_DEFINE_TYPE (GooDemoItem, goo_demo_item, GOO_TYPE_CANVAS_ITEM_SIMPLE)
16
17 /* The standard object initialization function. */
18     static void
19 goo_demo_item_init (GooDemoItem *demo_item)
20 {
21     demo_item->size = 0.0;
22 }
23
24 void
25 goo_demo_item_move_to (GooCanvasItem    *item,
26                        gdouble           x,
27                        gdouble           y)
28 {
29     cairo_matrix_t matrix;
30
31     cairo_matrix_init_translate (&matrix, x, y);
32     goo_canvas_item_set_transform (item, &matrix);
33 }
34
35 /* The convenience function to create new items. This should start with a 
36    parent argument and end with a variable list of object properties to fit
37    in with the standard canvas items. */
38 GooCanvasItem*
39 goo_demo_item_new (GooCanvasItem      *parent,
40                    gdouble             x,
41                    gdouble             y,
42                    gdouble             size,
43                    char                letter,
44                    ...)
45 {
46     GooCanvasItem *item;
47     GooDemoItem *demo_item;
48     const char *first_property;
49     va_list var_args;
50
51     item = g_object_new (GOO_TYPE_DEMO_ITEM, NULL);
52
53     demo_item = (GooDemoItem*) item;
54     demo_item->size = size;
55     demo_item->letter = letter;
56
57     va_start (var_args, letter);
58     first_property = va_arg (var_args, char*);
59     if (first_property)
60         g_object_set_valist ((GObject*) item, first_property, var_args);
61     va_end (var_args);
62
63     if (parent)
64     {
65         goo_canvas_item_add_child (parent, item, -1);
66         g_object_unref (item);
67     }
68
69     goo_demo_item_move_to (item, x, y);
70
71     return item;
72 }
73
74 /* The update method. This is called when the canvas is initially shown and
75    also whenever the object is updated and needs to change its size and/or
76    shape. It should calculate its new bounds, storing them in simple->bounds,
77    and it should convert these to device coordinates. */
78 static void
79 goo_demo_item_update  (GooCanvasItemSimple *simple,
80                        cairo_t             *cr)
81 {
82     GooDemoItem *demo_item = (GooDemoItem*) simple;
83
84     /* Compute the new bounds. */
85     simple->bounds.x1 = 0;
86     simple->bounds.y1 = 0;
87     simple->bounds.x2 = demo_item->size;
88     simple->bounds.y2 = demo_item->size;
89
90     /* Convert to device coordinates. */
91     goo_canvas_item_simple_user_bounds_to_device (simple, cr, &simple->bounds);
92 }
93
94 /* The paint method. This should draw the item on the given cairo_t, using
95    the item's own coordinate space. */
96 static void
97 goo_demo_item_paint (GooCanvasItemSimple *simple,
98                      cairo_t             *cr,
99                      GooCanvasBounds     *bounds)
100 {
101     GooDemoItem *item = (GooDemoItem*) simple;
102     cairo_pattern_t *gradient;
103     cairo_text_extents_t extents;
104     int rad = (int) (item->size / 2);
105     int cx = item->size / 2;
106     int cy = cx;
107     int tx, ty;
108     double spot_angle = M_PI / 4.0;
109     double spot_rad = rad / 2.0;
110     char string[2];
111
112     cairo_save (cr);
113
114     gradient = cairo_pattern_create_radial (cx - spot_rad * cos (spot_angle),
115                                             cy - spot_rad * sin (spot_angle),
116                                             0.0,
117                                             cx - spot_rad * cos (spot_angle),
118                                             cy - spot_rad * sin (spot_angle),
119                                             rad + spot_rad);
120     cairo_pattern_add_color_stop_rgb (gradient, 0.0, 1.0, 1.0, 1.0);
121     cairo_pattern_add_color_stop_rgb (gradient, 1.0, 0.33, 0.33, 0.33);
122
123     cairo_set_source (cr, gradient);
124
125     cairo_arc (cr,
126                cx, cy,
127                rad, 0, 2 * M_PI);
128
129     cairo_fill (cr);
130
131     cairo_select_font_face (cr, "mono",
132                             CAIRO_FONT_SLANT_NORMAL,
133                             CAIRO_FONT_WEIGHT_BOLD);
134     cairo_set_font_size (cr, 1.8 * rad);
135
136     string[0] = item->letter;
137     string[1] = '\0';
138     cairo_text_extents (cr, string, &extents);
139     tx = cx - extents.width / 2 - extents.x_bearing;
140     ty = cy - extents.height / 2 - extents.y_bearing;
141
142     cairo_set_source_rgb (cr, 0.7, 0.7, 0.7);
143     cairo_move_to (cr, tx + 1, ty + 1);
144     cairo_show_text (cr, string);
145                 
146     cairo_set_source_rgb (cr, 0.33, 0.33, 0.33);
147     cairo_move_to (cr, tx - 1, ty - 1);
148     cairo_show_text (cr, string);
149
150     cairo_set_source_rgb (cr, 0.2, 0.3, 0.8);
151     cairo_move_to (cr, tx, ty);
152     cairo_show_text (cr, string);
153
154     cairo_restore (cr);
155 }
156
157 /* Hit detection. This should check if the given coordinate (in the item's
158    coordinate space) is within the item. If it is it should return the item,
159    otherwise it should return NULL. */
160 static GooCanvasItem*
161 goo_demo_item_get_item_at (GooCanvasItemSimple *simple,
162                            gdouble              x,
163                            gdouble              y,
164                            cairo_t             *cr,
165                            gboolean             is_pointer_event)
166 {
167     GooDemoItem *demo_item = (GooDemoItem*) simple;
168
169     if (x < 0 || (x > demo_item->size)
170         || y < 0 || (y > demo_item->size))
171         return NULL;
172
173     return (GooCanvasItem*) simple;
174 }
175
176 /* The class initialization function. Here we set the class' update(), paint()
177    and get_item_at() methods. */
178 static void
179 goo_demo_item_class_init (GooDemoItemClass *klass)
180 {
181     GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass*) klass;
182
183     simple_class->update        = goo_demo_item_update;
184     simple_class->paint         = goo_demo_item_paint;
185     simple_class->get_item_at   = goo_demo_item_get_item_at;
186 }