]> git.sur5r.net Git - glabels/blob - src/label-ellipse.c
Imported Upstream version 3.0.0
[glabels] / src / label-ellipse.c
1 /*
2  *  label-ellipse.c
3  *  Copyright (C) 2001-2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of gLabels.
6  *
7  *  gLabels is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  gLabels is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with gLabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "label-ellipse.h"
22
23 #include <glib/gi18n.h>
24 #include <glib.h>
25 #include <math.h>
26
27 #include "cairo-ellipse-path.h"
28
29 #include "debug.h"
30
31 /*========================================================*/
32 /* Private macros and constants.                          */
33 /*========================================================*/
34
35 /*========================================================*/
36 /* Private types.                                         */
37 /*========================================================*/
38
39 struct _glLabelEllipsePrivate {
40         gdouble          line_width;
41         glColorNode     *line_color_node;
42         glColorNode     *fill_color_node;
43 };
44
45 /*========================================================*/
46 /* Private globals.                                       */
47 /*========================================================*/
48
49 /*========================================================*/
50 /* Private function prototypes.                           */
51 /*========================================================*/
52
53 static void    gl_label_ellipse_finalize  (GObject           *object);
54
55 static void    copy                       (glLabelObject     *dst_object,
56                                            glLabelObject     *src_object);
57
58 static void    set_fill_color             (glLabelObject     *object,
59                                            glColorNode       *fill_color_node,
60                                            gboolean           checkpoint);
61
62 static void    set_line_color             (glLabelObject     *object,
63                                            glColorNode       *line_color_node,
64                                            gboolean           checkpoint);
65
66 static void    set_line_width             (glLabelObject     *object,
67                                            gdouble            line_width,
68                                            gboolean           checkpoint);
69
70 static glColorNode*   get_fill_color      (glLabelObject     *object);
71
72 static glColorNode*   get_line_color      (glLabelObject     *object);
73
74 static gdouble get_line_width             (glLabelObject     *object);
75
76 static void    draw_object                (glLabelObject     *object,
77                                            cairo_t           *cr,
78                                            gboolean           screen_flag,
79                                            glMergeRecord     *record);
80
81 static void    draw_shadow                (glLabelObject     *object,
82                                            cairo_t           *cr,
83                                            gboolean           screen_flag,
84                                            glMergeRecord     *record);
85
86 static gboolean object_at                 (glLabelObject     *object,
87                                            cairo_t           *cr,
88                                            gdouble            x_pixels,
89                                            gdouble            y_pixels);
90
91
92 /*****************************************************************************/
93 /* Boilerplate object stuff.                                                 */
94 /*****************************************************************************/
95 G_DEFINE_TYPE (glLabelEllipse, gl_label_ellipse, GL_TYPE_LABEL_OBJECT)
96
97
98 static void
99 gl_label_ellipse_class_init (glLabelEllipseClass *class)
100 {
101         GObjectClass       *object_class       = G_OBJECT_CLASS (class);
102         glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
103
104         gl_label_ellipse_parent_class = g_type_class_peek_parent (class);
105
106         label_object_class->copy           = copy;
107         label_object_class->set_fill_color = set_fill_color;
108         label_object_class->set_line_color = set_line_color;
109         label_object_class->set_line_width = set_line_width;
110         label_object_class->get_fill_color = get_fill_color;
111         label_object_class->get_line_color = get_line_color;
112         label_object_class->get_line_width = get_line_width;
113         label_object_class->draw_object    = draw_object;
114         label_object_class->draw_shadow    = draw_shadow;
115         label_object_class->object_at      = object_at;
116
117         object_class->finalize = gl_label_ellipse_finalize;
118 }
119
120
121 static void
122 gl_label_ellipse_init (glLabelEllipse *lellipse)
123 {
124         lellipse->priv = g_new0 (glLabelEllipsePrivate, 1);
125 }
126
127
128 static void
129 gl_label_ellipse_finalize (GObject *object)
130 {
131         glLabelEllipse *lellipse = GL_LABEL_ELLIPSE (object);
132
133         g_return_if_fail (object && GL_IS_LABEL_ELLIPSE (object));
134
135         gl_color_node_free (&(lellipse->priv->line_color_node));
136         gl_color_node_free (&(lellipse->priv->fill_color_node));
137         g_free (lellipse->priv);
138
139         G_OBJECT_CLASS (gl_label_ellipse_parent_class)->finalize (object);
140 }
141
142
143 /*****************************************************************************/
144 /* NEW label "ellipse" object.                                               */
145 /*****************************************************************************/
146 GObject *
147 gl_label_ellipse_new (glLabel *label,
148                       gboolean checkpoint)
149 {
150         glLabelEllipse      *lellipse;
151         glColorNode         *fill_color_node;
152         glColorNode         *line_color_node;
153
154         lellipse = g_object_new (gl_label_ellipse_get_type(), NULL);
155
156         if (label != NULL)
157         {
158                 if ( checkpoint )
159                 {
160                         gl_label_checkpoint (label, _("Create ellipse object"));
161                 }
162
163                 fill_color_node = gl_color_node_new_default ();
164                 line_color_node = gl_color_node_new_default ();
165
166                 line_color_node->color = gl_label_get_default_line_color(label);
167                 fill_color_node->color = gl_label_get_default_fill_color(label);
168
169                 lellipse->priv->line_width      = gl_label_get_default_line_width(label);
170                 lellipse->priv->line_color_node = line_color_node;
171                 lellipse->priv->fill_color_node = fill_color_node;
172
173                 gl_label_add_object (label, GL_LABEL_OBJECT (lellipse));
174                 gl_label_object_set_parent (GL_LABEL_OBJECT (lellipse), label);
175         }
176
177         return G_OBJECT (lellipse);
178 }
179
180
181 /*****************************************************************************/
182 /* Copy object contents.                                                     */
183 /*****************************************************************************/
184 static void
185 copy (glLabelObject *dst_object,
186       glLabelObject *src_object)
187 {
188         glLabelEllipse *lellipse     = (glLabelEllipse *)src_object;
189         glLabelEllipse *new_lellipse = (glLabelEllipse *)dst_object;
190         gdouble         line_width;
191         glColorNode    *line_color_node;
192         glColorNode    *fill_color_node;
193
194         gl_debug (DEBUG_LABEL, "START");
195
196         g_return_if_fail (lellipse && GL_IS_LABEL_ELLIPSE (lellipse));
197         g_return_if_fail (new_lellipse && GL_IS_LABEL_ELLIPSE (new_lellipse));
198
199         line_width = get_line_width (src_object);
200         line_color_node = get_line_color (src_object);
201         fill_color_node = get_fill_color (src_object);
202
203         set_line_width (dst_object, line_width, FALSE);
204         set_line_color (dst_object, line_color_node, FALSE);
205         set_fill_color (dst_object, fill_color_node, FALSE);
206
207         gl_color_node_free (&line_color_node);
208         gl_color_node_free (&fill_color_node);
209         
210         gl_debug (DEBUG_LABEL, "END");
211 }
212
213
214 /*---------------------------------------------------------------------------*/
215 /* PRIVATE.  Set fill color method.                                          */
216 /*---------------------------------------------------------------------------*/
217 static void
218 set_fill_color (glLabelObject *object,
219                 glColorNode   *fill_color_node,
220                 gboolean       checkpoint)
221 {
222         glLabelEllipse *lellipse = (glLabelEllipse *)object;
223         glLabel        *label;
224
225         g_return_if_fail (lellipse && GL_IS_LABEL_ELLIPSE (lellipse));
226
227         if (!gl_color_node_equal (lellipse->priv->fill_color_node, fill_color_node))
228         {
229                 if ( checkpoint )
230                 {
231                         label = gl_label_object_get_parent (GL_LABEL_OBJECT (lellipse));
232                         gl_label_checkpoint (label, _("Fill color"));
233                 }
234
235                 gl_color_node_free (&(lellipse->priv->fill_color_node));
236                 lellipse->priv->fill_color_node = gl_color_node_dup (fill_color_node);
237
238                 gl_label_object_emit_changed (GL_LABEL_OBJECT(lellipse));
239         }       
240 }
241
242
243 /*---------------------------------------------------------------------------*/
244 /* PRIVATE.  Set line color method.                                          */
245 /*---------------------------------------------------------------------------*/
246 static void
247 set_line_color (glLabelObject *object,
248                 glColorNode   *line_color_node,
249                 gboolean       checkpoint)
250 {
251         glLabelEllipse *lellipse = (glLabelEllipse *)object;
252         glLabel        *label;
253
254         g_return_if_fail (lellipse && GL_IS_LABEL_ELLIPSE (lellipse));
255
256         if ( !gl_color_node_equal (lellipse->priv->line_color_node, line_color_node) )
257         {
258                 if ( checkpoint )
259                 {
260                         label = gl_label_object_get_parent (GL_LABEL_OBJECT (lellipse));
261                         gl_label_checkpoint (label, _("Line color"));
262                 }
263
264                 gl_color_node_free (&(lellipse->priv->line_color_node));
265                 lellipse->priv->line_color_node = gl_color_node_dup (line_color_node);
266                 
267                 gl_label_object_emit_changed (GL_LABEL_OBJECT(lellipse));
268         }
269 }
270
271
272 /*---------------------------------------------------------------------------*/
273 /* PRIVATE.  Set line width method.                                          */
274 /*---------------------------------------------------------------------------*/
275 static void
276 set_line_width (glLabelObject *object,
277                 gdouble        line_width,
278                 gboolean       checkpoint)
279 {
280         glLabelEllipse *lellipse = (glLabelEllipse *)object;
281         glLabel        *label;
282
283         g_return_if_fail (lellipse && GL_IS_LABEL_ELLIPSE (lellipse));
284
285         if ( lellipse->priv->line_width != line_width )
286         {
287                 if ( checkpoint )
288                 {
289                         label = gl_label_object_get_parent (GL_LABEL_OBJECT (lellipse));
290                         gl_label_checkpoint (label, _("Line width"));
291                 }
292
293                 lellipse->priv->line_width = line_width;
294                 gl_label_object_emit_changed (GL_LABEL_OBJECT(lellipse));
295         }
296 }
297
298
299 /*---------------------------------------------------------------------------*/
300 /* PRIVATE.  Get fill color method.                                          */
301 /*---------------------------------------------------------------------------*/
302 static gdouble
303 get_line_width (glLabelObject *object)
304 {
305         glLabelEllipse *lellipse = (glLabelEllipse *)object;
306
307         g_return_val_if_fail (lellipse && GL_IS_LABEL_ELLIPSE (lellipse), 0.0);
308
309         return lellipse->priv->line_width;
310 }
311
312
313 /*---------------------------------------------------------------------------*/
314 /* PRIVATE.  Get line color method.                                          */
315 /*---------------------------------------------------------------------------*/
316 static glColorNode*
317 get_line_color (glLabelObject *object)
318 {
319         glLabelEllipse *lellipse = (glLabelEllipse *)object;
320
321         g_return_val_if_fail (lellipse && GL_IS_LABEL_ELLIPSE (lellipse), 0);
322
323         return gl_color_node_dup (lellipse->priv->line_color_node);
324 }
325
326
327 /*---------------------------------------------------------------------------*/
328 /* PRIVATE.  Get line width method.                                          */
329 /*---------------------------------------------------------------------------*/
330 static glColorNode*
331 get_fill_color (glLabelObject *object)
332 {
333         glLabelEllipse *lellipse = (glLabelEllipse *)object;
334
335         g_return_val_if_fail (lellipse && GL_IS_LABEL_ELLIPSE (lellipse), 0);
336
337         return gl_color_node_dup (lellipse->priv->fill_color_node);
338 }
339
340
341 /*****************************************************************************/
342 /* Draw object method.                                                       */
343 /*****************************************************************************/
344 static void
345 draw_object (glLabelObject *object,
346              cairo_t       *cr,
347              gboolean       screen_flag,
348              glMergeRecord *record)
349 {
350         gdouble        w, h;
351         gdouble        line_width;
352         glColorNode   *line_color_node;
353         glColorNode   *fill_color_node;
354         guint          line_color;
355         guint          fill_color;
356
357         gl_debug (DEBUG_LABEL, "START");
358
359         gl_label_object_get_size (object, &w, &h);
360
361         line_width = gl_label_object_get_line_width (object);
362         
363         line_color_node = gl_label_object_get_line_color (object);
364         fill_color_node = gl_label_object_get_fill_color (object);
365         line_color = gl_color_node_expand (line_color_node, record);
366         fill_color = gl_color_node_expand (fill_color_node, record);
367         if (line_color_node->field_flag && screen_flag)
368         {
369                 line_color = GL_COLOR_MERGE_DEFAULT;
370         }
371         if (fill_color_node->field_flag && screen_flag)
372         {
373                 fill_color = GL_COLOR_FILL_MERGE_DEFAULT;
374         }
375
376
377         gl_cairo_ellipse_path (cr, w/2, h/2);
378
379         /* Paint fill color */
380         cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (fill_color));
381         cairo_fill_preserve (cr);
382
383         /* Draw outline */
384         cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (line_color));
385         cairo_set_line_width (cr, line_width);
386         cairo_stroke (cr);
387
388         gl_color_node_free (&line_color_node);
389         gl_color_node_free (&fill_color_node);
390
391         gl_debug (DEBUG_LABEL, "END");
392 }
393
394
395 /*****************************************************************************/
396 /* Draw shadow method.                                                       */
397 /*****************************************************************************/
398 static void
399 draw_shadow (glLabelObject *object,
400              cairo_t       *cr,
401              gboolean       screen_flag,
402              glMergeRecord *record)
403 {
404         gdouble        w, h;
405         gdouble        line_width;
406         glColorNode   *line_color_node;
407         glColorNode   *fill_color_node;
408         guint          line_color;
409         guint          fill_color;
410         glColorNode   *shadow_color_node;
411         guint          shadow_color;
412         gdouble        shadow_opacity;
413
414         gl_debug (DEBUG_LABEL, "START");
415
416         cairo_save (cr);
417
418         gl_label_object_get_size (object, &w, &h);
419
420         line_width = gl_label_object_get_line_width (object);
421         
422         line_color_node = gl_label_object_get_line_color (object);
423         fill_color_node = gl_label_object_get_fill_color (object);
424         line_color = gl_color_node_expand (line_color_node, record);
425         fill_color = gl_color_node_expand (fill_color_node, record);
426         if (line_color_node->field_flag && screen_flag)
427         {
428                 line_color = GL_COLOR_MERGE_DEFAULT;
429         }
430         if (fill_color_node->field_flag && screen_flag)
431         {
432                 fill_color = GL_COLOR_FILL_MERGE_DEFAULT;
433         }
434
435         shadow_color_node = gl_label_object_get_shadow_color (object);
436         shadow_color = gl_color_node_expand (shadow_color_node, record);
437         if (shadow_color_node->field_flag && screen_flag)
438         {
439                 shadow_color = GL_COLOR_SHADOW_MERGE_DEFAULT;
440         }
441         shadow_opacity = gl_label_object_get_shadow_opacity (object);
442         shadow_color = gl_color_set_opacity (shadow_color, shadow_opacity);
443         
444
445         cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (shadow_color));
446
447         if ( GL_COLOR_F_ALPHA (fill_color) )
448         {
449                 if ( GL_COLOR_F_ALPHA (line_color) )
450                 {
451                         /* Has FILL and OUTLINE: adjust size to account for line width. */
452                         cairo_translate (cr, -line_width/2, -line_width/2);
453                         gl_cairo_ellipse_path (cr, (w+line_width)/2, (h+line_width)/2);
454
455                 }
456                 else
457                 {
458                         /* Has FILL but no OUTLINE. */
459                         gl_cairo_ellipse_path (cr, w/2, h/2);
460                 }
461
462                 /* Draw shadow */
463                 cairo_fill (cr);
464         }
465         else
466         {
467                 if ( GL_COLOR_F_ALPHA (line_color) )
468                 {
469                         /* Has only OUTLINE. */
470                         gl_cairo_ellipse_path (cr, w/2, h/2);
471
472                         /* Draw shadow of outline */
473                         cairo_set_line_width (cr, line_width);
474                         cairo_stroke (cr);
475                 }
476         }
477
478
479         gl_color_node_free (&line_color_node);
480         gl_color_node_free (&fill_color_node);
481         gl_color_node_free (&shadow_color_node);
482
483         cairo_restore (cr);
484
485         gl_debug (DEBUG_LABEL, "END");
486 }
487
488
489 /*****************************************************************************/
490 /* Is object at coordinates?                                                 */
491 /*****************************************************************************/
492 static gboolean
493 object_at (glLabelObject *object,
494            cairo_t       *cr,
495            gdouble        x,
496            gdouble        y)
497 {
498         gdouble           w, h;
499         gdouble           line_width;
500
501         gl_label_object_get_size (object, &w, &h);
502
503         cairo_new_path (cr);
504         gl_cairo_ellipse_path (cr, w/2, h/2);
505
506         if (cairo_in_fill (cr, x, y))
507         {
508                 return TRUE;
509         }
510
511         line_width = gl_label_object_get_line_width (object);
512         cairo_set_line_width (cr, line_width);
513         if (cairo_in_stroke (cr, x, y))
514         {
515                 return TRUE;
516         }
517
518         return FALSE;
519 }
520
521
522
523
524 /*
525  * Local Variables:       -- emacs
526  * mode: C                -- emacs
527  * c-basic-offset: 8      -- emacs
528  * tab-width: 8           -- emacs
529  * indent-tabs-mode: nil  -- emacs
530  * End:                   -- emacs
531  */