~jamespharaoh/ubuntu/oneiric/unity/fix-for-880672

« back to all changes in this revision

Viewing changes to .pc/debian-changes-4.10.2-0ubuntu2/plugins/unityshell/src/DashStyle.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2011-08-26 18:21:49 UTC
  • Revision ID: james.westby@ubuntu.com-20110826182149-c0ifremjok82210p
Tags: 4.10.2-0ubuntu2
* Backported some fixes from trunk:
  - build fix for armel (lp: #834576)
  - dnd from the application lens to the launcher work
  - small screen dash improvements

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2011 Canonical Ltd
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License version 3 as
 
6
 * published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Authored by: Mirco Müller <mirco.mueller@canonical.com
 
17
 */
 
18
 
 
19
#include <math.h>
 
20
#include <glib.h>
 
21
#include <gdk/gdk.h>
 
22
#include <gtk/gtk.h>
 
23
#include <pango/pango.h>
 
24
#include <json-glib/json-glib.h>
 
25
 
 
26
#include "DashStyle.h"
 
27
#include "config.h"
 
28
 
 
29
#define DASH_WIDGETS_FILE DATADIR"/unity/themes/dash-widgets.json"
 
30
 
 
31
namespace unity
 
32
{
 
33
  bool DashStyle::ReadColorSingle (JsonNode*    root,
 
34
                                   const gchar* nodeName,
 
35
                                   const gchar* memberName,
 
36
                                   double*      color)
 
37
  {
 
38
  JsonObject* object = NULL;
 
39
  JsonNode*   node   = NULL;
 
40
 
 
41
    if (!root || !nodeName || !memberName || !color)
 
42
      return false;
 
43
 
 
44
    object = json_node_get_object (root);
 
45
    node   = json_object_get_member (object, nodeName);
 
46
    object = json_node_get_object (node);
 
47
 
 
48
    const gchar* string = NULL;
 
49
    PangoColor   col    = {0, 0, 0};
 
50
 
 
51
    string = json_object_get_string_member (object, memberName);
 
52
    pango_color_parse (&col, string);
 
53
    color[R] = (double) col.red   / (double) 0xffff;
 
54
    color[G] = (double) col.green / (double) 0xffff;
 
55
    color[B] = (double) col.blue  / (double) 0xffff;
 
56
 
 
57
    return true;
 
58
  }
 
59
 
 
60
  bool DashStyle::ReadColorArray (JsonNode*    root,
 
61
                                  const gchar* nodeName,
 
62
                                  const gchar* memberName,
 
63
                                  double colors[][CHANNELS])
 
64
  {
 
65
  JsonObject*  object = NULL;
 
66
  JsonNode*    node   = NULL;
 
67
    JsonArray*   array  = NULL;
 
68
    unsigned int i      = 0;
 
69
 
 
70
    if (!root || !nodeName || !memberName || !colors)
 
71
      return false;
 
72
 
 
73
    object = json_node_get_object (root);
 
74
    node   = json_object_get_member (object, nodeName);
 
75
    object = json_node_get_object (node);
 
76
    array  = json_object_get_array_member (object, memberName);
 
77
 
 
78
    for (i = 0; i < json_array_get_length (array); i++)
 
79
    {
 
80
      const gchar* string = NULL;
 
81
      PangoColor   color  = {0, 0, 0};
 
82
      string = json_array_get_string_element (array, i);
 
83
      pango_color_parse (&color, string);
 
84
      colors[i][R] = (double) color.red   / (double) 0xffff;
 
85
      colors[i][G] = (double) color.green / (double) 0xffff;
 
86
      colors[i][B] = (double) color.blue  / (double) 0xffff;
 
87
    }
 
88
 
 
89
    return true;
 
90
  }
 
91
 
 
92
  bool DashStyle::ReadDoubleSingle (JsonNode*    root,
 
93
                                    const gchar* nodeName,
 
94
                                    const gchar* memberName,
 
95
                                    double*      value)
 
96
  {
 
97
  JsonObject* object = NULL;
 
98
  JsonNode*   node   = NULL;
 
99
 
 
100
    if (!root || !nodeName || !memberName || !value)
 
101
      return false;
 
102
 
 
103
    object = json_node_get_object (root);
 
104
    node   = json_object_get_member (object, nodeName);
 
105
    object = json_node_get_object (node);
 
106
 
 
107
    *value = json_object_get_double_member (object, memberName);
 
108
 
 
109
    return true;
 
110
  }
 
111
 
 
112
  bool DashStyle::ReadDoubleArray (JsonNode*    root,
 
113
                                   const gchar* nodeName,
 
114
                                   const gchar* memberName,
 
115
                                   double*      values)
 
116
  {
 
117
  JsonObject*  object = NULL;
 
118
  JsonNode*    node   = NULL;
 
119
    JsonArray*   array  = NULL;
 
120
    unsigned int i      = 0;
 
121
 
 
122
    if (!root || !nodeName || !memberName || !values)
 
123
      return false;
 
124
 
 
125
    object = json_node_get_object (root);
 
126
    node   = json_object_get_member (object, nodeName);
 
127
    object = json_node_get_object (node);
 
128
    array  = json_object_get_array_member (object, memberName);
 
129
 
 
130
    for (i = 0; i < json_array_get_length (array); i++)
 
131
      values[i] = json_array_get_double_element (array, i);
 
132
 
 
133
    return true;
 
134
  }
 
135
 
 
136
  bool DashStyle::ReadIntSingle (JsonNode*    root,
 
137
                                 const gchar* nodeName,
 
138
                                 const gchar* memberName,
 
139
                                 int*         value)
 
140
  {
 
141
  JsonObject* object = NULL;
 
142
  JsonNode*   node   = NULL;
 
143
 
 
144
    if (!root || !nodeName || !memberName || !value)
 
145
      return false;
 
146
 
 
147
    object = json_node_get_object (root);
 
148
    node   = json_object_get_member (object, nodeName);
 
149
    object = json_node_get_object (node);
 
150
 
 
151
    *value = json_object_get_int_member (object, memberName);
 
152
 
 
153
    return true;
 
154
  }
 
155
 
 
156
  bool DashStyle::ReadIntArray (JsonNode*    root,
 
157
                                const gchar* nodeName,
 
158
                                const gchar* memberName,
 
159
                                int*         values)
 
160
  {
 
161
  JsonObject*  object = NULL;
 
162
  JsonNode*    node   = NULL;
 
163
    JsonArray*   array  = NULL;
 
164
    unsigned int i      = 0;
 
165
 
 
166
    if (!root || !nodeName || !memberName || !values)
 
167
      return false;
 
168
 
 
169
    object = json_node_get_object (root);
 
170
    node   = json_object_get_member (object, nodeName);
 
171
    object = json_node_get_object (node);
 
172
    array  = json_object_get_array_member (object, memberName);
 
173
 
 
174
    for (i = 0; i < json_array_get_length (array); i++)
 
175
      values[i] = json_array_get_int_element (array, i);
 
176
 
 
177
    return true;
 
178
  }
 
179
 
 
180
  bool DashStyle::ReadModeSingle (JsonNode*    root,
 
181
                                  const gchar* nodeName,
 
182
                                  const gchar* memberName,
 
183
                                  BlendMode*   mode)
 
184
  {
 
185
  JsonObject*  object = NULL;
 
186
  JsonNode*    node   = NULL;
 
187
    const gchar* string = NULL;
 
188
 
 
189
    if (!root || !nodeName || !memberName || !mode)
 
190
      return false;
 
191
 
 
192
    object = json_node_get_object (root);
 
193
    node   = json_object_get_member (object, nodeName);
 
194
    object = json_node_get_object (node);
 
195
 
 
196
    string = json_object_get_string_member (object, memberName);
 
197
    if (!g_strcmp0 (string, "normal"))
 
198
      *mode = BLEND_MODE_NORMAL ;
 
199
 
 
200
    if (!g_strcmp0 (string, "multiply"))
 
201
      *mode = BLEND_MODE_MULTIPLY ;
 
202
 
 
203
    if (!g_strcmp0 (string, "screen"))
 
204
      *mode = BLEND_MODE_SCREEN ;
 
205
 
 
206
    return true;
 
207
  }
 
208
 
 
209
  bool DashStyle::ReadModeArray (JsonNode*    root,
 
210
                                 const gchar* nodeName,
 
211
                                 const gchar* memberName,
 
212
                                 BlendMode*   modes)
 
213
  {
 
214
  JsonObject*  object = NULL;
 
215
  JsonNode*    node   = NULL;
 
216
    JsonArray*   array  = NULL;
 
217
  unsigned int i      = 0;
 
218
 
 
219
    if (!root || !nodeName || !memberName || !modes)
 
220
      return false;
 
221
 
 
222
    object = json_node_get_object (root);
 
223
    node   = json_object_get_member (object, nodeName);
 
224
    object = json_node_get_object (node);
 
225
    array  = json_object_get_array_member (object, memberName);
 
226
 
 
227
    for (i = 0; i < json_array_get_length (array); i++)
 
228
    {
 
229
      const gchar* string = NULL;
 
230
 
 
231
      string = json_array_get_string_element (array, i);
 
232
 
 
233
      if (!g_strcmp0 (string, "normal"))
 
234
        modes[i] = BLEND_MODE_NORMAL;
 
235
 
 
236
      if (!g_strcmp0 (string, "multiply"))
 
237
        modes[i] = BLEND_MODE_MULTIPLY;
 
238
 
 
239
      if (!g_strcmp0 (string, "screen"))
 
240
        modes[i] = BLEND_MODE_SCREEN;
 
241
  }
 
242
 
 
243
    return true;
 
244
  }
 
245
 
 
246
  bool DashStyle::ReadWeightSingle (JsonNode*    root,
 
247
                                    const gchar* nodeName,
 
248
                                    const gchar* memberName,
 
249
                                    FontWeight*  weight)
 
250
  {
 
251
  JsonObject*  object = NULL;
 
252
  JsonNode*    node   = NULL;
 
253
    const gchar* string = NULL;
 
254
 
 
255
    if (!root || !nodeName || !memberName || !weight)
 
256
      return false;
 
257
 
 
258
    object = json_node_get_object (root);
 
259
    node   = json_object_get_member (object, nodeName);
 
260
    object = json_node_get_object (node);
 
261
 
 
262
    string = json_object_get_string_member (object, memberName);
 
263
    if (!g_strcmp0 (string, "light"))
 
264
      *weight = FONT_WEIGHT_LIGHT;
 
265
 
 
266
    if (!g_strcmp0 (string, "regular"))
 
267
      *weight = FONT_WEIGHT_REGULAR;
 
268
 
 
269
    if (!g_strcmp0 (string, "bold"))
 
270
      *weight = FONT_WEIGHT_BOLD;
 
271
 
 
272
    return true;
 
273
  }
 
274
 
 
275
  bool DashStyle::ReadWeightArray (JsonNode*    root,
 
276
                                   const gchar* nodeName,
 
277
                                   const gchar* memberName,
 
278
                                   FontWeight*  weights)
 
279
  {
 
280
  JsonObject*  object = NULL;
 
281
  JsonNode*    node   = NULL;
 
282
    JsonArray*   array  = NULL;
 
283
  unsigned int i      = 0;
 
284
 
 
285
    if (!root || !nodeName || !memberName || !weights)
 
286
      return false;
 
287
 
 
288
    object = json_node_get_object (root);
 
289
    node   = json_object_get_member (object, nodeName);
 
290
    object = json_node_get_object (node);
 
291
    array  = json_object_get_array_member (object, memberName);
 
292
 
 
293
    for (i = 0; i < json_array_get_length (array); i++)
 
294
    {
 
295
      const gchar* string = NULL;
 
296
 
 
297
      string = json_array_get_string_element (array, i);
 
298
 
 
299
      if (!g_strcmp0 (string, "light"))
 
300
        weights[i] = FONT_WEIGHT_LIGHT;
 
301
 
 
302
      if (!g_strcmp0 (string, "regular"))
 
303
        weights[i] = FONT_WEIGHT_REGULAR;
 
304
 
 
305
      if (!g_strcmp0 (string, "bold"))
 
306
        weights[i] = FONT_WEIGHT_BOLD;
 
307
  }
 
308
 
 
309
    return true;
 
310
  }
 
311
 
 
312
  DashStyle::DashStyle ()
 
313
  {
 
314
    JsonParser*  parser = NULL;
 
315
    GError*      error  = NULL;
 
316
    gboolean     result = FALSE;
 
317
    JsonNode*    root   = NULL;
 
318
 
 
319
  g_type_init ();
 
320
 
 
321
    parser = json_parser_new ();
 
322
    result = json_parser_load_from_file (parser, DASH_WIDGETS_FILE, &error);
 
323
    if (!result)
 
324
    {
 
325
      g_object_unref (parser);
 
326
      g_warning ("Failure: %s", error->message);
 
327
      g_error_free (error);
 
328
      UseDefaultValues ();
 
329
 
 
330
    return;
 
331
    }
 
332
 
 
333
    root = json_parser_get_root (parser); // not ref'ed
 
334
 
 
335
    if (JSON_NODE_TYPE (root) != JSON_NODE_OBJECT)
 
336
    {
 
337
      g_warning ("Root node is not an object, fail.  It's an: %s",
 
338
                 json_node_type_name (root));
 
339
      g_object_unref (parser);
 
340
      UseDefaultValues ();
 
341
      return;
 
342
    }
 
343
 
 
344
    // button-label
 
345
    ReadDoubleArray (root,
 
346
                     "button-label",
 
347
                     "border-opacity",
 
348
                     _buttonLabelBorderOpacity);
 
349
 
 
350
    ReadColorArray (root,
 
351
                    "button-label",
 
352
                    "border-color",
 
353
                    _buttonLabelBorderColor);
 
354
 
 
355
    ReadDoubleArray (root,
 
356
                     "button-label",
 
357
                     "border-size",
 
358
                     _buttonLabelBorderSize);
 
359
 
 
360
    ReadDoubleSingle (root,
 
361
                      "button-label",
 
362
                      "text-size",
 
363
                      &_buttonLabelTextSize);
 
364
 
 
365
    ReadColorArray (root,
 
366
                    "button-label",
 
367
                    "text-color",
 
368
                    _buttonLabelTextColor);
 
369
 
 
370
    ReadDoubleArray (root,
 
371
                     "button-label",
 
372
                     "text-opacity",
 
373
                     _buttonLabelTextOpacity);
 
374
 
 
375
    ReadColorArray (root,
 
376
                    "button-label",
 
377
                    "fill-color",
 
378
                    _buttonLabelFillColor);
 
379
 
 
380
    ReadDoubleArray (root,
 
381
                     "button-label",
 
382
                     "fill-opacity",
 
383
                     _buttonLabelFillOpacity);
 
384
 
 
385
    ReadDoubleArray (root,
 
386
                     "button-label",
 
387
                     "overlay-opacity",
 
388
                     _buttonLabelOverlayOpacity);
 
389
 
 
390
    ReadModeArray (root,
 
391
                   "button-label",
 
392
                   "overlay-mode",
 
393
                   _buttonLabelOverlayMode);
 
394
 
 
395
    ReadIntArray (root,
 
396
                  "button-label",
 
397
                  "blur-size",
 
398
                  _buttonLabelBlurSize);
 
399
 
 
400
    // regular-text
 
401
    ReadColorSingle (root,
 
402
                     "regular-text",
 
403
                     "text-color",
 
404
                     _regularTextColor);
 
405
 
 
406
    ReadDoubleSingle (root,
 
407
                      "regular-text",
 
408
                      "text-opacity",
 
409
                      &_regularTextOpacity);
 
410
 
 
411
    ReadDoubleSingle (root,
 
412
                      "regular-text",
 
413
                      "text-size",
 
414
                      &_regularTextSize);
 
415
 
 
416
    ReadModeSingle (root,
 
417
                    "regular-text",
 
418
                    "text-mode",
 
419
                    &_regularTextMode);
 
420
 
 
421
    ReadWeightSingle (root,
 
422
                      "regular-text",
 
423
                      "text-weight",
 
424
                      &_regularTextWeight);
 
425
 
 
426
    // separator
 
427
    ReadDoubleSingle (root,
 
428
                      "separator",
 
429
                      "size",
 
430
                      &_separatorSize);
 
431
 
 
432
    ReadColorSingle (root,
 
433
                     "separator",
 
434
                     "color",
 
435
                     _separatorColor);
 
436
 
 
437
    ReadDoubleSingle (root,
 
438
                      "separator",
 
439
                      "opacity",
 
440
                      &_separatorOpacity);
 
441
 
 
442
    ReadDoubleSingle (root,
 
443
                      "separator",
 
444
                      "overlay-opacity",
 
445
                      &_separatorOverlayOpacity);
 
446
 
 
447
    ReadModeSingle (root,
 
448
                    "separator",
 
449
                    "overlay-mode",
 
450
                    &_separatorOverlayMode);
 
451
 
 
452
    ReadIntSingle (root,
 
453
                   "separator",
 
454
                   "blur-size",
 
455
                   &_separatorBlurSize);
 
456
 
 
457
    g_object_unref (parser);
 
458
 
 
459
    // create fallback font-options
 
460
  _defaultFontOptions = NULL;
 
461
    _defaultFontOptions = cairo_font_options_create ();
 
462
    if (cairo_font_options_status (_defaultFontOptions) == CAIRO_STATUS_SUCCESS)
 
463
    {
 
464
      cairo_font_options_set_antialias (_defaultFontOptions,
 
465
                                        CAIRO_ANTIALIAS_GRAY);
 
466
                                        //CAIRO_ANTIALIAS_SUBPIXEL);
 
467
      cairo_font_options_set_subpixel_order (_defaultFontOptions,
 
468
                                             CAIRO_SUBPIXEL_ORDER_RGB);
 
469
      cairo_font_options_set_hint_style (_defaultFontOptions,
 
470
                                         CAIRO_HINT_STYLE_SLIGHT);
 
471
      cairo_font_options_set_hint_metrics (_defaultFontOptions,
 
472
                                           CAIRO_HINT_METRICS_ON);
 
473
  }
 
474
  }
 
475
 
 
476
  DashStyle::~DashStyle ()
 
477
  {
 
478
  if (cairo_font_options_status (_defaultFontOptions) == CAIRO_STATUS_SUCCESS)
 
479
      cairo_font_options_destroy (_defaultFontOptions);
 
480
  }
 
481
 
 
482
  DashStyle* DashStyle::GetDefault()
 
483
  {
 
484
    //FIXME - replace with a nice C++ singleton method
 
485
    static DashStyle* default_loader = NULL;
 
486
 
 
487
    if (G_UNLIKELY(!default_loader))
 
488
      default_loader = new DashStyle();
 
489
 
 
490
    return default_loader;
 
491
  }
 
492
 
 
493
  static inline double
 
494
  _align (double val)
 
495
  {
 
496
    double fract = val - (int) val;
 
497
 
 
498
    if (fract != 0.5f)
 
499
      return (double) ((int) val + 0.5f);
 
500
    else
 
501
      return val;
 
502
  }
 
503
 
 
504
  void
 
505
  DashStyle::RoundedRect (cairo_t* cr,
 
506
                          double   aspect,
 
507
                          double   x,
 
508
                          double   y,
 
509
                          double   cornerRadius,
 
510
                          double   width,
 
511
                          double   height,
 
512
                          bool     align)
 
513
  {
 
514
    // sanity check
 
515
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS &&
 
516
        cairo_surface_get_type (cairo_get_target (cr)) != CAIRO_SURFACE_TYPE_IMAGE)
 
517
      return;
 
518
 
 
519
    double radius = cornerRadius / aspect;
 
520
 
 
521
    if (align)
 
522
    {
 
523
      // top-left, right of the corner
 
524
      cairo_move_to (cr, _align (x + radius), _align (y));
 
525
 
 
526
      // top-right, left of the corner
 
527
      cairo_line_to (cr, _align (x + width - radius), _align (y));
 
528
 
 
529
      // top-right, below the corner
 
530
      cairo_arc (cr,
 
531
                 _align (x + width - radius),
 
532
                 _align (y + radius),
 
533
                 radius,
 
534
                 -90.0f * G_PI / 180.0f,
 
535
                 0.0f * G_PI / 180.0f);
 
536
 
 
537
      // bottom-right, above the corner
 
538
      cairo_line_to (cr, _align (x + width), _align (y + height - radius));
 
539
 
 
540
      // bottom-right, left of the corner
 
541
      cairo_arc (cr,
 
542
                 _align (x + width - radius),
 
543
                 _align (y + height - radius),
 
544
                 radius,
 
545
                 0.0f * G_PI / 180.0f,
 
546
                 90.0f * G_PI / 180.0f);
 
547
 
 
548
      // bottom-left, right of the corner
 
549
      cairo_line_to (cr, _align (x + radius), _align (y + height));
 
550
 
 
551
      // bottom-left, above the corner
 
552
      cairo_arc (cr,
 
553
                 _align (x + radius),
 
554
                 _align (y + height - radius),
 
555
                 radius,
 
556
                 90.0f * G_PI / 180.0f,
 
557
                 180.0f * G_PI / 180.0f);
 
558
 
 
559
      // top-left, right of the corner
 
560
      cairo_arc (cr,
 
561
                 _align (x + radius),
 
562
                 _align (y + radius),
 
563
                 radius,
 
564
                 180.0f * G_PI / 180.0f,
 
565
                 270.0f * G_PI / 180.0f);
 
566
    }
 
567
    else
 
568
    {
 
569
      // top-left, right of the corner
 
570
      cairo_move_to (cr, x + radius, y);
 
571
 
 
572
      // top-right, left of the corner
 
573
      cairo_line_to (cr, x + width - radius, y);
 
574
 
 
575
      // top-right, below the corner
 
576
      cairo_arc (cr,
 
577
                 x + width - radius,
 
578
                 y + radius,
 
579
                 radius,
 
580
                 -90.0f * G_PI / 180.0f,
 
581
                 0.0f * G_PI / 180.0f);
 
582
 
 
583
      // bottom-right, above the corner
 
584
      cairo_line_to (cr, x + width, y + height - radius);
 
585
 
 
586
      // bottom-right, left of the corner
 
587
      cairo_arc (cr,
 
588
                 x + width - radius,
 
589
                 y + height - radius,
 
590
                 radius,
 
591
                 0.0f * G_PI / 180.0f,
 
592
                 90.0f * G_PI / 180.0f);
 
593
 
 
594
      // bottom-left, right of the corner
 
595
      cairo_line_to (cr, x + radius, y + height);
 
596
 
 
597
      // bottom-left, above the corner
 
598
      cairo_arc (cr,
 
599
                 x + radius,
 
600
                 y + height - radius,
 
601
                 radius,
 
602
                 90.0f * G_PI / 180.0f,
 
603
                 180.0f * G_PI / 180.0f);
 
604
 
 
605
      // top-left, right of the corner
 
606
      cairo_arc (cr,
 
607
                 x + radius,
 
608
                 y + radius,
 
609
                 radius,
 
610
                 180.0f * G_PI / 180.0f,
 
611
                 270.0f * G_PI / 180.0f);
 
612
    }
 
613
  }
 
614
 
 
615
  static inline void _blurinner (guchar* pixel,
 
616
                                 gint*   zR,
 
617
                                 gint*   zG,
 
618
                                 gint*   zB,
 
619
                                 gint*   zA,
 
620
                                 gint    alpha,
 
621
                                 gint    aprec,
 
622
                                 gint    zprec)
 
623
  {
 
624
    gint   r;
 
625
    gint   g;
 
626
    gint   b;
 
627
    guchar a;
 
628
 
 
629
    r = *pixel;
 
630
    g = *(pixel + 1);
 
631
    b = *(pixel + 2);
 
632
    a = *(pixel + 3);
 
633
 
 
634
    *zR += (alpha * ((r << zprec) - *zR)) >> aprec;
 
635
    *zG += (alpha * ((g << zprec) - *zG)) >> aprec;
 
636
    *zB += (alpha * ((b << zprec) - *zB)) >> aprec;
 
637
    *zA += (alpha * ((a << zprec) - *zA)) >> aprec;
 
638
 
 
639
    *pixel       = *zR >> zprec;
 
640
    *(pixel + 1) = *zG >> zprec;
 
641
    *(pixel + 2) = *zB >> zprec;
 
642
    *(pixel + 3) = *zA >> zprec;
 
643
  }
 
644
 
 
645
  static inline void _blurrow (guchar* pixels,
 
646
                               gint    width,
 
647
                               gint    height,
 
648
                               gint    channels,
 
649
                               gint    line,
 
650
                               gint    alpha,
 
651
                               gint    aprec,
 
652
                               gint    zprec)
 
653
  {
 
654
    gint    zR;
 
655
    gint    zG;
 
656
    gint    zB;
 
657
    gint    zA;
 
658
    gint    index;
 
659
    guchar* scanline;
 
660
 
 
661
    scanline = &(pixels[line * width * channels]);
 
662
 
 
663
    zR = *scanline << zprec;
 
664
    zG = *(scanline + 1) << zprec;
 
665
    zB = *(scanline + 2) << zprec;
 
666
    zA = *(scanline + 3) << zprec;
 
667
 
 
668
    for (index = 0; index < width; index ++)
 
669
      _blurinner (&scanline[index * channels], &zR, &zG, &zB, &zA, alpha, aprec,
 
670
      zprec);
 
671
 
 
672
    for (index = width - 2; index >= 0; index--)
 
673
      _blurinner (&scanline[index * channels], &zR, &zG, &zB, &zA, alpha, aprec,
 
674
      zprec);
 
675
  }
 
676
 
 
677
  static inline void _blurcol (guchar* pixels,
 
678
                               gint    width,
 
679
                               gint    height,
 
680
                               gint    channels,
 
681
                               gint    x,
 
682
                               gint    alpha,
 
683
                               gint    aprec,
 
684
                               gint    zprec)
 
685
  {
 
686
    gint zR;
 
687
    gint zG;
 
688
    gint zB;
 
689
    gint zA;
 
690
    gint index;
 
691
    guchar* ptr;
 
692
 
 
693
    ptr = pixels;
 
694
 
 
695
    ptr += x * channels;
 
696
 
 
697
    zR = *((guchar*) ptr    ) << zprec;
 
698
    zG = *((guchar*) ptr + 1) << zprec;
 
699
    zB = *((guchar*) ptr + 2) << zprec;
 
700
    zA = *((guchar*) ptr + 3) << zprec;
 
701
 
 
702
    for (index = width; index < (height - 1) * width; index += width)
 
703
      _blurinner ((guchar*) &ptr[index * channels], &zR, &zG, &zB, &zA, alpha,
 
704
      aprec, zprec);
 
705
 
 
706
    for (index = (height - 2) * width; index >= 0; index -= width)
 
707
      _blurinner ((guchar*) &ptr[index * channels], &zR, &zG, &zB, &zA, alpha,
 
708
      aprec, zprec);
 
709
  }
 
710
 
 
711
  //
 
712
  // pixels   image-data
 
713
  // width    image-width
 
714
  // height   image-height
 
715
  // channels image-channels
 
716
  //
 
717
  // in-place blur of image 'img' with kernel of approximate radius 'radius'
 
718
  //
 
719
  // blurs with two sided exponential impulse response
 
720
  //
 
721
  // aprec = precision of alpha parameter in fixed-point format 0.aprec
 
722
  //
 
723
  // zprec = precision of state parameters zR,zG,zB and zA in fp format 8.zprec
 
724
  //
 
725
  void _expblur (guchar* pixels,
 
726
                 gint    width,
 
727
                 gint    height,
 
728
                 gint    channels,
 
729
                 gint    radius,
 
730
                 gint    aprec,
 
731
                 gint    zprec)
 
732
  {
 
733
    gint alpha;
 
734
    gint row = 0;
 
735
    gint col = 0;
 
736
 
 
737
    if (radius < 1)
 
738
      return;
 
739
 
 
740
    // calculate the alpha such that 90% of
 
741
    // the kernel is within the radius.
 
742
    // (Kernel extends to infinity)
 
743
    alpha = (gint) ((1 << aprec) * (1.0f - expf (-2.3f / (radius + 1.f))));
 
744
 
 
745
    for (; row < height; row++)
 
746
      _blurrow (pixels, width, height, channels, row, alpha, aprec, zprec);
 
747
 
 
748
    for(; col < width; col++)
 
749
      _blurcol (pixels, width, height, channels, col, alpha, aprec, zprec);
 
750
 
 
751
    return;
 
752
  }
 
753
 
 
754
  void DashStyle::Blur (cairo_t* cr, int size)
 
755
  {
 
756
    // sanity check
 
757
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS &&
 
758
        cairo_surface_get_type (cairo_get_target (cr)) != CAIRO_SURFACE_TYPE_IMAGE)
 
759
      return;
 
760
 
 
761
    cairo_surface_t* surface;
 
762
    guchar*          pixels;
 
763
    guint            width;
 
764
    guint            height;
 
765
    cairo_format_t   format;
 
766
 
 
767
    surface = cairo_get_target (cr);
 
768
 
 
769
    // before we mess with the surface execute any pending drawing
 
770
    cairo_surface_flush (surface);
 
771
 
 
772
    pixels = cairo_image_surface_get_data (surface);
 
773
    width  = cairo_image_surface_get_width (surface);
 
774
    height = cairo_image_surface_get_height (surface);
 
775
    format = cairo_image_surface_get_format (surface);
 
776
 
 
777
    switch (format)
 
778
    {
 
779
      case CAIRO_FORMAT_ARGB32:
 
780
        _expblur (pixels, width, height, 4, size, 16, 7);
 
781
      break;
 
782
 
 
783
      case CAIRO_FORMAT_RGB24:
 
784
        _expblur (pixels, width, height, 3, size, 16, 7);
 
785
      break;
 
786
 
 
787
      case CAIRO_FORMAT_A8:
 
788
        _expblur (pixels, width, height, 1, size, 16, 7);
 
789
      break;
 
790
 
 
791
      default :
 
792
        // do nothing
 
793
      break;
 
794
    }
 
795
 
 
796
    // inform cairo we altered the surfaces contents
 
797
    cairo_surface_mark_dirty (surface);
 
798
  }
 
799
 
 
800
  void DashStyle::Star (cairo_t* cr, double size)
 
801
  {
 
802
    double outter[5][2] = {{0.0, 0.0},
 
803
                           {0.0, 0.0},
 
804
                           {0.0, 0.0},
 
805
                           {0.0, 0.0},
 
806
                           {0.0, 0.0}};
 
807
    double inner[5][2]  = {{0.0, 0.0},
 
808
                           {0.0, 0.0},
 
809
                           {0.0, 0.0},
 
810
                           {0.0, 0.0},
 
811
                           {0.0, 0.0}};
 
812
    double angle[5]     = {-90.0, -18.0, 54.0, 126.0, 198.0};
 
813
    double outterRadius = size;
 
814
    double innerRadius  = size/2.0;
 
815
 
 
816
    for (int i = 0; i < 5; i++)
 
817
    {
 
818
      outter[i][0] = outterRadius * cos (angle[i] * M_PI / 180.0);
 
819
      outter[i][1] = outterRadius * sin (angle[i] * M_PI / 180.0);
 
820
      inner[i][0]  = innerRadius * cos ((angle[i] + 36.0) * M_PI / 180.0);
 
821
      inner[i][1]  = innerRadius * sin ((angle[i] + 36.0) * M_PI / 180.0);
 
822
    }
 
823
 
 
824
    cairo_move_to (cr, outter[0][0], outter[0][1]);
 
825
    cairo_line_to (cr, inner[0][0], inner[0][1]);
 
826
    cairo_line_to (cr, outter[1][0], outter[1][1]);
 
827
    cairo_line_to (cr, inner[1][0], inner[1][1]);
 
828
    cairo_line_to (cr, outter[2][0], outter[2][1]);
 
829
    cairo_line_to (cr, inner[2][0], inner[2][1]);
 
830
    cairo_line_to (cr, outter[3][0], outter[3][1]);
 
831
    cairo_line_to (cr, inner[3][0], inner[3][1]);
 
832
    cairo_line_to (cr, outter[4][0], outter[4][1]);
 
833
    cairo_line_to (cr, inner[4][0], inner[4][1]);
 
834
  cairo_close_path (cr);
 
835
  }
 
836
 
 
837
  void DashStyle::UseDefaultValues ()
 
838
  {
 
839
    // button-label
 
840
    _buttonLabelBorderColor[nux::NUX_STATE_NORMAL][R]      = 0.53;
 
841
    _buttonLabelBorderColor[nux::NUX_STATE_NORMAL][G]      = 1.0;
 
842
    _buttonLabelBorderColor[nux::NUX_STATE_NORMAL][B]      = 0.66;
 
843
    _buttonLabelBorderColor[nux::NUX_STATE_ACTIVE][R]      = 1.0;
 
844
    _buttonLabelBorderColor[nux::NUX_STATE_ACTIVE][G]      = 1.0;
 
845
    _buttonLabelBorderColor[nux::NUX_STATE_ACTIVE][B]      = 1.0;
 
846
    _buttonLabelBorderColor[nux::NUX_STATE_PRELIGHT][R]    = 0.06;
 
847
    _buttonLabelBorderColor[nux::NUX_STATE_PRELIGHT][G]    = 0.13;
 
848
    _buttonLabelBorderColor[nux::NUX_STATE_PRELIGHT][B]    = 1.0;
 
849
    _buttonLabelBorderColor[nux::NUX_STATE_SELECTED][R]    = 0.07;
 
850
    _buttonLabelBorderColor[nux::NUX_STATE_SELECTED][G]    = 0.2;
 
851
    _buttonLabelBorderColor[nux::NUX_STATE_SELECTED][B]    = 0.33;
 
852
    _buttonLabelBorderColor[nux::NUX_STATE_INSENSITIVE][R] = 0.39;
 
853
    _buttonLabelBorderColor[nux::NUX_STATE_INSENSITIVE][G] = 0.26;
 
854
    _buttonLabelBorderColor[nux::NUX_STATE_INSENSITIVE][B] = 0.12;
 
855
 
 
856
    _buttonLabelBorderOpacity[nux::NUX_STATE_NORMAL]       = 0.5;
 
857
    _buttonLabelBorderOpacity[nux::NUX_STATE_ACTIVE]       = 0.8;
 
858
    _buttonLabelBorderOpacity[nux::NUX_STATE_PRELIGHT]     = 0.5;
 
859
    _buttonLabelBorderOpacity[nux::NUX_STATE_SELECTED]     = 0.5;
 
860
    _buttonLabelBorderOpacity[nux::NUX_STATE_INSENSITIVE]  = 0.5;
 
861
 
 
862
    _buttonLabelBorderSize[nux::NUX_STATE_NORMAL]          = 0.5;
 
863
    _buttonLabelBorderSize[nux::NUX_STATE_ACTIVE]          = 2.0;
 
864
    _buttonLabelBorderSize[nux::NUX_STATE_PRELIGHT]        = 0.5;
 
865
    _buttonLabelBorderSize[nux::NUX_STATE_SELECTED]        = 0.5;
 
866
    _buttonLabelBorderSize[nux::NUX_STATE_INSENSITIVE]     = 0.5;
 
867
 
 
868
 
 
869
    _buttonLabelTextSize                                   = 1.0;
 
870
 
 
871
    _buttonLabelTextColor[nux::NUX_STATE_NORMAL][R]        = 1.0;
 
872
    _buttonLabelTextColor[nux::NUX_STATE_NORMAL][G]        = 1.0;
 
873
    _buttonLabelTextColor[nux::NUX_STATE_NORMAL][B]        = 1.0;
 
874
    _buttonLabelTextColor[nux::NUX_STATE_ACTIVE][R]        = 0.0;
 
875
    _buttonLabelTextColor[nux::NUX_STATE_ACTIVE][G]        = 0.0;
 
876
    _buttonLabelTextColor[nux::NUX_STATE_ACTIVE][B]        = 0.0;
 
877
    _buttonLabelTextColor[nux::NUX_STATE_PRELIGHT][R]      = 1.0;
 
878
    _buttonLabelTextColor[nux::NUX_STATE_PRELIGHT][G]      = 1.0;
 
879
    _buttonLabelTextColor[nux::NUX_STATE_PRELIGHT][B]      = 1.0;
 
880
    _buttonLabelTextColor[nux::NUX_STATE_SELECTED][R]      = 1.0;
 
881
    _buttonLabelTextColor[nux::NUX_STATE_SELECTED][G]      = 1.0;
 
882
    _buttonLabelTextColor[nux::NUX_STATE_SELECTED][B]      = 1.0;
 
883
    _buttonLabelTextColor[nux::NUX_STATE_INSENSITIVE][R]   = 1.0;
 
884
    _buttonLabelTextColor[nux::NUX_STATE_INSENSITIVE][G]   = 1.0;
 
885
    _buttonLabelTextColor[nux::NUX_STATE_INSENSITIVE][B]   = 1.0;
 
886
 
 
887
    _buttonLabelTextOpacity[nux::NUX_STATE_NORMAL]         = 1.0;
 
888
    _buttonLabelTextOpacity[nux::NUX_STATE_ACTIVE]         = 1.0;
 
889
    _buttonLabelTextOpacity[nux::NUX_STATE_PRELIGHT]       = 1.0;
 
890
    _buttonLabelTextOpacity[nux::NUX_STATE_SELECTED]       = 1.0;
 
891
    _buttonLabelTextOpacity[nux::NUX_STATE_INSENSITIVE]    = 1.0;
 
892
 
 
893
    _buttonLabelFillColor[nux::NUX_STATE_NORMAL][R]        = 0.0;
 
894
    _buttonLabelFillColor[nux::NUX_STATE_NORMAL][G]        = 0.0;
 
895
    _buttonLabelFillColor[nux::NUX_STATE_NORMAL][B]        = 0.0;
 
896
    _buttonLabelFillColor[nux::NUX_STATE_ACTIVE][R]        = 0.0;
 
897
    _buttonLabelFillColor[nux::NUX_STATE_ACTIVE][G]        = 0.0;
 
898
    _buttonLabelFillColor[nux::NUX_STATE_ACTIVE][B]        = 0.0;
 
899
    _buttonLabelFillColor[nux::NUX_STATE_PRELIGHT][R]      = 0.0;
 
900
    _buttonLabelFillColor[nux::NUX_STATE_PRELIGHT][G]      = 0.0;
 
901
    _buttonLabelFillColor[nux::NUX_STATE_PRELIGHT][B]      = 0.0;
 
902
    _buttonLabelFillColor[nux::NUX_STATE_SELECTED][R]      = 0.0;
 
903
    _buttonLabelFillColor[nux::NUX_STATE_SELECTED][G]      = 0.0;
 
904
    _buttonLabelFillColor[nux::NUX_STATE_SELECTED][B]      = 0.0;
 
905
    _buttonLabelFillColor[nux::NUX_STATE_INSENSITIVE][R]   = 0.0;
 
906
    _buttonLabelFillColor[nux::NUX_STATE_INSENSITIVE][G]   = 0.0;
 
907
    _buttonLabelFillColor[nux::NUX_STATE_INSENSITIVE][B]   = 0.0;
 
908
 
 
909
    _buttonLabelFillOpacity[nux::NUX_STATE_NORMAL]         = 0.0;
 
910
    _buttonLabelFillOpacity[nux::NUX_STATE_ACTIVE]         = 0.0;
 
911
    _buttonLabelFillOpacity[nux::NUX_STATE_PRELIGHT]       = 0.0;
 
912
    _buttonLabelFillOpacity[nux::NUX_STATE_SELECTED]       = 0.0;
 
913
    _buttonLabelFillOpacity[nux::NUX_STATE_INSENSITIVE]    = 0.0;
 
914
 
 
915
    _buttonLabelOverlayOpacity[nux::NUX_STATE_NORMAL]      = 0.0;
 
916
    _buttonLabelOverlayOpacity[nux::NUX_STATE_ACTIVE]      = 0.3;
 
917
    _buttonLabelOverlayOpacity[nux::NUX_STATE_PRELIGHT]    = 0.0;
 
918
    _buttonLabelOverlayOpacity[nux::NUX_STATE_SELECTED]    = 0.0;
 
919
    _buttonLabelOverlayOpacity[nux::NUX_STATE_INSENSITIVE] = 0.0;
 
920
 
 
921
    _buttonLabelOverlayMode[nux::NUX_STATE_NORMAL]         = BLEND_MODE_NORMAL;
 
922
    _buttonLabelOverlayMode[nux::NUX_STATE_ACTIVE]         = BLEND_MODE_NORMAL;
 
923
    _buttonLabelOverlayMode[nux::NUX_STATE_PRELIGHT]       = BLEND_MODE_NORMAL;
 
924
    _buttonLabelOverlayMode[nux::NUX_STATE_SELECTED]       = BLEND_MODE_NORMAL;
 
925
    _buttonLabelOverlayMode[nux::NUX_STATE_INSENSITIVE]    = BLEND_MODE_NORMAL;
 
926
 
 
927
    _buttonLabelBlurSize[nux::NUX_STATE_NORMAL]            = 0;
 
928
    _buttonLabelBlurSize[nux::NUX_STATE_ACTIVE]            = 5;
 
929
    _buttonLabelBlurSize[nux::NUX_STATE_PRELIGHT]          = 0;
 
930
    _buttonLabelBlurSize[nux::NUX_STATE_SELECTED]          = 0;
 
931
    _buttonLabelBlurSize[nux::NUX_STATE_INSENSITIVE]       = 0;
 
932
 
 
933
    // regular-text
 
934
    _regularTextColor[R]   = 1.0;
 
935
    _regularTextColor[G]   = 1.0;
 
936
    _regularTextColor[B]   = 1.0;
 
937
    _regularTextOpacity    = 1.0;
 
938
    _regularTextSize       = 13.0;
 
939
    _regularTextMode       = BLEND_MODE_NORMAL;
 
940
    _regularTextWeight     = FONT_WEIGHT_LIGHT;
 
941
 
 
942
    // separator
 
943
    _separatorSize           = 1.0;
 
944
    _separatorColor[R]       = 1.0;
 
945
    _separatorColor[G]       = 1.0;
 
946
    _separatorColor[B]       = 1.0;
 
947
    _separatorOpacity        = 0.15;
 
948
    _separatorOverlayOpacity = 0.47;
 
949
    _separatorOverlayMode    = BLEND_MODE_NORMAL;
 
950
    _separatorBlurSize       = 6;
 
951
  }
 
952
 
 
953
  void DashStyle::ArrowPath (cairo_t* cr, Arrow arrow)
 
954
  {
 
955
    double x  = 0.0;
 
956
    double y  = 0.0;
 
957
    double w  = cairo_image_surface_get_width (cairo_get_target (cr));
 
958
    double h  = cairo_image_surface_get_height (cairo_get_target (cr));
 
959
    /*double xt = 0.0;
 
960
    double yt = 0.0;*/
 
961
 
 
962
  // the real shape from the SVG
 
963
    // 3.5/1.5, 20.5/22.5, (17x21)
 
964
  /*xt = 16.25;
 
965
  yt = 9.028;
 
966
    cairo_move_to (cr, xt, yt);
 
967
    cairo_curve_to (cr, xt - 1.511, yt - 1.006, xt - 3.019, yt - 1.971, xt - 4.527, yt - 2.897);
 
968
    xt -= 4.527;
 
969
    yt -= 2.897
 
970
    cairo_curve_to (cr, 10.213, 5.2, 8.743, 4.335, 7.313, 3.532);
 
971
    cairo_curve_to (cr, 8.743, 4.335, 4.613, 2.051, 3.5, 1.5);
 
972
    cairo_rel_line_to (cr, 0.0, 21.0);
 
973
    cairo_rel_curve_to (cr, 1.164, -0.552, 2.461, -1.229, 3.892, -2.032);
 
974
    cairo_rel_curve_to (cr, 1.431, -0.803, 2.9, -1.682, 4.409, -2.634);
 
975
    cairo_rel_curve_to (cr, 1.51, -0.953, 3.004, -1.932, 4.488, -2.937);
 
976
    cairo_rel_curve_to (cr, 1.481, -1.002, 2.887, -1.981, 4.211, -2.935);
 
977
    cairo_curve_to (cr, 19.176, 11.009, 17.759, 10.03, 16.25, 9.028);
 
978
    cairo_close_path (cr);*/
 
979
 
 
980
    if (arrow == ARROW_LEFT || arrow == ARROW_BOTH)
 
981
    {
 
982
      x = 1.0;
 
983
      y = h / 2.0 - 3.5;
 
984
      cairo_move_to (cr, _align (x), _align (y));
 
985
      cairo_line_to (cr, _align (x + 5.0), _align (y + 3.5));
 
986
      cairo_line_to (cr, _align (x), _align (y + 7.0));
 
987
      cairo_close_path (cr);
 
988
  }
 
989
 
 
990
    if (arrow == ARROW_RIGHT || arrow == ARROW_BOTH)
 
991
    {
 
992
      x = w - 1.0;
 
993
      y = h / 2.0 - 3.5;
 
994
      cairo_move_to (cr, _align (x), _align (y));
 
995
      cairo_line_to (cr, _align (x - 5.0), _align (y + 3.5));
 
996
      cairo_line_to (cr, _align (x), _align (y + 7.0));
 
997
      cairo_close_path (cr);
 
998
  }
 
999
  }
 
1000
 
 
1001
  void DashStyle::ButtonOutlinePath (cairo_t* cr, bool align)
 
1002
  {
 
1003
    double x  = 2.0;
 
1004
    double y  = 2.0;
 
1005
    double w  = cairo_image_surface_get_width (cairo_get_target (cr)) - 4.0;
 
1006
    double h  = cairo_image_surface_get_height (cairo_get_target (cr)) - 4.0;
 
1007
    double xt = 0.0;
 
1008
    double yt = 0.0;
 
1009
 
 
1010
  // - these absolute values are the "cost" of getting only a SVG from design
 
1011
  // and not a generic formular how to approximate the curve-shape, thus
 
1012
  // the smallest possible button-size is 22.18x24.0
 
1013
  double width  = w - 22.18;
 
1014
  double height = h - 24.0;
 
1015
 
 
1016
    xt = x + width + 22.18;
 
1017
  yt = y + 12.0;
 
1018
 
 
1019
    if (align)
 
1020
    {
 
1021
    // top right
 
1022
      cairo_move_to (cr, _align(xt), _align(yt));
 
1023
      cairo_curve_to (cr, _align(xt - 0.103),
 
1024
                          _align(yt - 4.355),
 
1025
                          _align(xt - 1.037),
 
1026
                          _align(yt - 7.444),
 
1027
                          _align(xt - 2.811),
 
1028
                          _align(yt - 9.267));
 
1029
      xt -= 2.811;
 
1030
      yt -= 9.267;
 
1031
      cairo_curve_to (cr, _align (xt - 1.722),
 
1032
                          _align (yt - 1.823),
 
1033
                          _align (xt - 4.531),
 
1034
                          _align (yt - 2.735),
 
1035
                          _align (xt - 8.28),
 
1036
                          _align (yt - 2.735));
 
1037
      xt -= 8.28;
 
1038
      yt -= 2.735;
 
1039
 
 
1040
    // top
 
1041
      cairo_line_to (cr, _align (xt - width), _align (yt));
 
1042
      xt -= width;
 
1043
 
 
1044
    // top left
 
1045
      cairo_curve_to (cr, _align (xt - 3.748),
 
1046
                          _align (yt),
 
1047
                          _align (xt - 6.507),
 
1048
                          _align (yt + 0.912),
 
1049
                          _align (xt - 8.279),
 
1050
                          _align (yt + 2.735));
 
1051
      xt -= 8.279;
 
1052
      yt += 2.735;
 
1053
      cairo_curve_to (cr, _align (xt - 1.773),
 
1054
                          _align (yt + 1.822),
 
1055
                          _align (xt - 2.708),
 
1056
                          _align (yt + 4.911),
 
1057
                          _align (xt - 2.811),
 
1058
                          _align (yt + 9.267));
 
1059
      xt -= 2.811;
 
1060
      yt += 9.267;
 
1061
 
 
1062
    // left
 
1063
      cairo_line_to (cr, _align (xt), _align (yt + height));
 
1064
      yt += height;
 
1065
 
 
1066
    // bottom left
 
1067
      cairo_curve_to (cr, _align (xt + 0.103),
 
1068
                          _align (yt + 4.355),
 
1069
                          _align (xt + 1.037),
 
1070
                          _align (yt + 7.444),
 
1071
                          _align (xt + 2.811),
 
1072
                          _align (yt + 9.267));
 
1073
      xt += 2.811;
 
1074
      yt += 9.267;
 
1075
      cairo_curve_to (cr, _align (xt + 1.772),
 
1076
                          _align (yt + 1.823),
 
1077
                          _align (xt + 4.531),
 
1078
                          _align (yt + 2.735),
 
1079
                          _align (xt + 8.28),
 
1080
                          _align (yt + 2.735));
 
1081
      xt += 8.28;
 
1082
      yt += 2.735;
 
1083
 
 
1084
    // bottom
 
1085
      cairo_line_to (cr, _align (xt + width), _align (yt));
 
1086
      xt += width;
 
1087
 
 
1088
    // bottom right
 
1089
      cairo_curve_to (cr, _align (xt + 3.748),
 
1090
                          _align (yt),
 
1091
                          _align (xt + 6.507),
 
1092
                          _align (yt - 0.912),
 
1093
                          _align (xt + 8.279),
 
1094
                          _align (yt - 2.735));
 
1095
      xt += 8.279;
 
1096
      yt -= 2.735;
 
1097
      cairo_curve_to (cr, _align (xt + 1.773),
 
1098
                          _align (yt - 1.822),
 
1099
                          _align (xt + 2.708),
 
1100
                          _align (yt - 4.911),
 
1101
                          _align (xt + 2.811),
 
1102
                          _align (yt - 9.267));
 
1103
    }
 
1104
    else
 
1105
    {
 
1106
      // top right
 
1107
      cairo_move_to (cr, x + width + 22.18, y + 12.0);
 
1108
      cairo_rel_curve_to (cr, -0.103, -4.355, -1.037, -7.444, -2.811, -9.267);
 
1109
      cairo_rel_curve_to (cr, -1.722, -1.823, -4.531, -2.735, -8.28, -2.735);
 
1110
 
 
1111
      // top
 
1112
      cairo_rel_line_to (cr, -width, 0.0);
 
1113
 
 
1114
      // top left
 
1115
      cairo_rel_curve_to (cr, -3.748, 0.0, -6.507, 0.912, -8.279, 2.735);
 
1116
      cairo_rel_curve_to (cr, -1.773, 1.822, -2.708, 4.911, -2.811, 9.267);
 
1117
 
 
1118
      // left
 
1119
      cairo_rel_line_to (cr, 0.0, height);
 
1120
 
 
1121
      // bottom left
 
1122
      cairo_rel_curve_to (cr, 0.103, 4.355, 1.037, 7.444, 2.811, 9.267);
 
1123
      cairo_rel_curve_to (cr, 1.772, 1.823, 4.531, 2.735, 8.28, 2.735);
 
1124
 
 
1125
      // bottom
 
1126
      cairo_rel_line_to (cr, width, 0.0);
 
1127
 
 
1128
      // bottom right
 
1129
      cairo_rel_curve_to (cr, 3.748, 0.0, 6.507, -0.912, 8.279, -2.735);
 
1130
      cairo_rel_curve_to (cr, 1.773, -1.822, 2.708, -4.911, 2.811, -9.267);
 
1131
    }
 
1132
 
 
1133
  // right
 
1134
    cairo_close_path (cr);
 
1135
  }
 
1136
 
 
1137
  void DashStyle::RoundedRectSegment (cairo_t*   cr,
 
1138
                                      double     aspect,
 
1139
                                      double     x,
 
1140
                                      double     y,
 
1141
                                      double     cornerRadius,
 
1142
                                      double     width,
 
1143
                                      double     height,
 
1144
                                      Segment    segment,
 
1145
                                      Arrow      arrow, 
 
1146
                                      nux::State state)
 
1147
  {
 
1148
    double radius = cornerRadius / aspect;
 
1149
    double arrow_w = radius / 1.5;
 
1150
    double arrow_h = radius / 2.0;
 
1151
 
 
1152
    switch (segment)
 
1153
    {
 
1154
      case SEGMENT_LEFT:
 
1155
        // top-left, right of the corner
 
1156
        cairo_move_to (cr, x + radius, y);
 
1157
 
 
1158
        // top-right
 
1159
        cairo_line_to (cr, x + width, y);
 
1160
 
 
1161
        if (arrow == ARROW_RIGHT && state == nux::NUX_STATE_ACTIVE)
 
1162
                {
 
1163
          cairo_line_to (cr, x + width,           y + height / 2.0 - arrow_h);
 
1164
          cairo_line_to (cr, x + width - arrow_w, y + height / 2.0);
 
1165
          cairo_line_to (cr, x + width,           y + height / 2.0 + arrow_h);
 
1166
                }
 
1167
 
 
1168
        // bottom-right
 
1169
        cairo_line_to (cr, x + width, y + height);
 
1170
 
 
1171
        // bottom-left, right of the corner
 
1172
        cairo_line_to (cr, x + radius, y + height);
 
1173
 
 
1174
        // bottom-left, above the corner
 
1175
        cairo_arc (cr,
 
1176
                   x + radius,
 
1177
                   y + height - radius,
 
1178
                   radius,
 
1179
                   90.0f * G_PI / 180.0f,
 
1180
                   180.0f * G_PI / 180.0f);
 
1181
 
 
1182
        // top-left, right of the corner
 
1183
        cairo_arc (cr,
 
1184
                   x + radius,
 
1185
                   y + radius,
 
1186
                   radius,
 
1187
                   180.0f * G_PI / 180.0f,
 
1188
                   270.0f * G_PI / 180.0f);
 
1189
      break;
 
1190
 
 
1191
      case SEGMENT_MIDDLE:
 
1192
        // top-left
 
1193
        cairo_move_to (cr, x, y);
 
1194
 
 
1195
        // top-right
 
1196
        cairo_line_to (cr, x + width, y);
 
1197
 
 
1198
        if ((arrow == ARROW_RIGHT || arrow == ARROW_BOTH) && state == nux::NUX_STATE_ACTIVE)
 
1199
                {
 
1200
          cairo_line_to (cr, x + width,           y + height / 2.0 - arrow_h);
 
1201
          cairo_line_to (cr, x + width - arrow_w, y + height / 2.0);
 
1202
          cairo_line_to (cr, x + width,           y + height / 2.0 + arrow_h);
 
1203
                }
 
1204
 
 
1205
        // bottom-right
 
1206
        cairo_line_to (cr, x + width, y + height);
 
1207
 
 
1208
        // bottom-left
 
1209
        cairo_line_to (cr, x, y + height);
 
1210
 
 
1211
        if ((arrow == ARROW_LEFT || arrow == ARROW_BOTH) && state == nux::NUX_STATE_ACTIVE)
 
1212
                {
 
1213
          cairo_line_to (cr, x,           y + height / 2.0 + arrow_h);
 
1214
          cairo_line_to (cr, x + arrow_w, y + height / 2.0);
 
1215
          cairo_line_to (cr, x,           y + height / 2.0 - arrow_h);
 
1216
                }
 
1217
 
 
1218
        // back to top-left
 
1219
        cairo_close_path (cr);
 
1220
      break;
 
1221
 
 
1222
      case SEGMENT_RIGHT:
 
1223
        // top-left, right of the corner
 
1224
        cairo_move_to (cr, x, y);
 
1225
 
 
1226
        // top-right, left of the corner
 
1227
        cairo_line_to (cr, x + width - radius, y);
 
1228
 
 
1229
        // top-right, below the corner
 
1230
        cairo_arc (cr,
 
1231
                   x + width - radius,
 
1232
                   y + radius,
 
1233
                   radius,
 
1234
                   -90.0f * G_PI / 180.0f,
 
1235
                   0.0f * G_PI / 180.0f);
 
1236
 
 
1237
        // bottom-right, above the corner
 
1238
        cairo_line_to (cr, x + width, y + height - radius);
 
1239
 
 
1240
        // bottom-right, left of the corner
 
1241
        cairo_arc (cr,
 
1242
                   x + width - radius,
 
1243
                   y + height - radius,
 
1244
                   radius,
 
1245
                   0.0f * G_PI / 180.0f,
 
1246
                   90.0f * G_PI / 180.0f);
 
1247
 
 
1248
        // bottom-left
 
1249
        cairo_line_to (cr, x, y + height);
 
1250
 
 
1251
        if (arrow == ARROW_LEFT && state == nux::NUX_STATE_ACTIVE)
 
1252
                {
 
1253
          cairo_line_to (cr, x,           y + height / 2.0 + arrow_h);
 
1254
          cairo_line_to (cr, x + arrow_w, y + height / 2.0);
 
1255
          cairo_line_to (cr, x,           y + height / 2.0 - arrow_h);
 
1256
                }
 
1257
 
 
1258
        // back to top-left
 
1259
        cairo_close_path (cr);
 
1260
      break;
 
1261
    }
 
1262
  }
 
1263
 
 
1264
  void DashStyle::ButtonOutlinePathSegment (cairo_t* cr, Segment segment)
 
1265
  {
 
1266
    double   x  = 0.0;
 
1267
    double   y  = 2.0;
 
1268
    double   w  = cairo_image_surface_get_width (cairo_get_target (cr));
 
1269
    double   h  = cairo_image_surface_get_height (cairo_get_target (cr)) - 4.0;
 
1270
    double   xt = 0.0;
 
1271
    double   yt = 0.0;
 
1272
 
 
1273
    // - these absolute values are the "cost" of getting only a SVG from design
 
1274
    // and not a generic formular how to approximate the curve-shape, thus
 
1275
    // the smallest possible button-size is 22.18x24.0
 
1276
    double width  = w - 22.18;
 
1277
    double height = h - 24.0;
 
1278
 
 
1279
    xt = x + width + 22.18;
 
1280
    yt = y + 12.0;
 
1281
 
 
1282
    switch (segment)
 
1283
    {
 
1284
      case SEGMENT_LEFT:
 
1285
        yt -= (9.267 + 2.735);
 
1286
        cairo_move_to (cr, _align (xt), _align (yt));
 
1287
        xt -= (2.811 + 8.28);
 
1288
 
 
1289
        // top
 
1290
        cairo_line_to (cr, _align (xt - width), _align (yt));
 
1291
        xt -= width;
 
1292
 
 
1293
        // top left
 
1294
        cairo_curve_to (cr, _align (xt - 3.748),
 
1295
                            _align (yt),
 
1296
                            _align (xt - 6.507),
 
1297
                            _align (yt + 0.912),
 
1298
                            _align (xt - 8.279),
 
1299
                            _align (yt + 2.735));
 
1300
        xt -= 8.279;
 
1301
        yt += 2.735;
 
1302
        cairo_curve_to (cr, _align (xt - 1.773),
 
1303
                            _align (yt + 1.822),
 
1304
                            _align (xt - 2.708),
 
1305
                            _align (yt + 4.911),
 
1306
                            _align (xt - 2.811),
 
1307
                            _align (yt + 9.267));
 
1308
        xt -= 2.811;
 
1309
        yt += 9.267;
 
1310
 
 
1311
        // left
 
1312
        cairo_line_to (cr, _align (xt), _align (yt + height));
 
1313
        yt += height;
 
1314
 
 
1315
        // bottom left
 
1316
        cairo_curve_to (cr, _align (xt + 0.103),
 
1317
                            _align (yt + 4.355),
 
1318
                            _align (xt + 1.037),
 
1319
                            _align (yt + 7.444),
 
1320
                            _align (xt + 2.811),
 
1321
                            _align (yt + 9.267));
 
1322
        xt += 2.811;
 
1323
        yt += 9.267;
 
1324
        cairo_curve_to (cr, _align (xt + 1.772),
 
1325
                            _align (yt + 1.823),
 
1326
                            _align (xt + 4.531),
 
1327
                            _align (yt + 2.735),
 
1328
                            _align (xt + 8.28),
 
1329
                            _align (yt + 2.735));
 
1330
        xt += 8.28 + width + 8.279 + 2.811;
 
1331
        yt += 2.735;
 
1332
 
 
1333
        // bottom
 
1334
        cairo_line_to (cr, _align (xt), _align (yt));
 
1335
 
 
1336
        cairo_close_path (cr);
 
1337
      break;
 
1338
 
 
1339
      case SEGMENT_MIDDLE:
 
1340
        yt -= (9.267 + 2.735);
 
1341
        cairo_move_to (cr, _align (xt), _align (yt));
 
1342
        xt -= (2.811 + 8.28);
 
1343
 
 
1344
        // top
 
1345
        cairo_line_to (cr, _align (xt - width - 8.279 - 2.811), _align (yt));
 
1346
 
 
1347
        // top left
 
1348
        xt -= width;
 
1349
        xt -= 8.279;
 
1350
        yt += 2.735;
 
1351
        xt -= 2.811;
 
1352
        yt += 9.267 + height + 2.735 + 9.267;
 
1353
 
 
1354
        // left
 
1355
        cairo_line_to (cr, _align (xt), _align (yt));
 
1356
 
 
1357
        // bottom left
 
1358
        xt += 2.811;
 
1359
        xt += 8.28 + width + 8.279 + 2.811;
 
1360
        // bottom
 
1361
        cairo_line_to (cr, _align (xt), _align (yt));
 
1362
 
 
1363
        cairo_close_path (cr);
 
1364
      break;
 
1365
 
 
1366
      case SEGMENT_RIGHT:
 
1367
        // top right
 
1368
        cairo_move_to (cr, _align(xt), _align(yt));
 
1369
        cairo_curve_to (cr, _align(xt - 0.103),
 
1370
                            _align(yt - 4.355),
 
1371
                            _align(xt - 1.037),
 
1372
                            _align(yt - 7.444),
 
1373
                            _align(xt - 2.811),
 
1374
                            _align(yt - 9.267));
 
1375
        xt -= 2.811;
 
1376
        yt -= 9.267;
 
1377
        cairo_curve_to (cr, _align (xt - 1.722),
 
1378
                            _align (yt - 1.823),
 
1379
                            _align (xt - 4.531),
 
1380
                            _align (yt - 2.735),
 
1381
                            _align (xt - 8.28),
 
1382
                            _align (yt - 2.735));
 
1383
        xt -= (8.28 + width + 8.279 + 2.811);
 
1384
        yt -= 2.735;
 
1385
 
 
1386
        // top
 
1387
        cairo_line_to (cr, _align (xt), _align (yt));
 
1388
 
 
1389
        // left
 
1390
        yt += 9.267 + 2.735 + height + 2.735 + 9.267;
 
1391
        cairo_line_to (cr, _align (xt), _align (yt));
 
1392
 
 
1393
        // bottom left
 
1394
        xt += 2.811 + 8.28;
 
1395
 
 
1396
        // bottom
 
1397
        cairo_line_to (cr, _align (xt + width), _align (yt));
 
1398
        xt += width;
 
1399
 
 
1400
        // bottom right
 
1401
        cairo_curve_to (cr, _align (xt + 3.748),
 
1402
                            _align (yt),
 
1403
                            _align (xt + 6.507),
 
1404
                            _align (yt - 0.912),
 
1405
                            _align (xt + 8.279),
 
1406
                            _align (yt - 2.735));
 
1407
        xt += 8.279;
 
1408
        yt -= 2.735;
 
1409
        cairo_curve_to (cr, _align (xt + 1.773),
 
1410
                            _align (yt - 1.822),
 
1411
                            _align (xt + 2.708),
 
1412
                            _align (yt - 4.911),
 
1413
                            _align (xt + 2.811),
 
1414
                            _align (yt - 9.267));
 
1415
 
 
1416
        cairo_close_path (cr);
 
1417
      break;
 
1418
    }
 
1419
  }
 
1420
 
 
1421
  void DashStyle::GetTextExtents (int& width,
 
1422
                                  int& height,
 
1423
                                  int  maxWidth,
 
1424
                                  int  maxHeight,
 
1425
                                  const std::string text)
 
1426
  {
 
1427
    cairo_surface_t*      surface  = NULL;
 
1428
    cairo_t*              cr       = NULL;
 
1429
    PangoLayout*          layout   = NULL;
 
1430
    PangoFontDescription* desc     = NULL;
 
1431
    PangoContext*         pangoCtx = NULL;
 
1432
    PangoRectangle        inkRect  = {0, 0, 0, 0};
 
1433
    int                   dpi      = 0;
 
1434
    char*                 fontName = NULL;
 
1435
    GdkScreen*            screen   = gdk_screen_get_default();  // is not ref'ed
 
1436
    GtkSettings*          settings = gtk_settings_get_default();// is not ref'ed
 
1437
 
 
1438
    surface = cairo_image_surface_create(CAIRO_FORMAT_A1, 1, 1);
 
1439
    cr = cairo_create(surface);
 
1440
    if (!screen)
 
1441
      cairo_set_font_options(cr, _defaultFontOptions);
 
1442
    else
 
1443
      cairo_set_font_options(cr, gdk_screen_get_font_options(screen));
 
1444
    layout = pango_cairo_create_layout(cr);
 
1445
 
 
1446
    g_object_get(settings, "gtk-font-name", &fontName, NULL);
 
1447
    if (!fontName)
 
1448
      desc = pango_font_description_from_string("Sans 10");
 
1449
    else
 
1450
    {
 
1451
      desc = pango_font_description_from_string(fontName);
 
1452
    g_free (fontName);
 
1453
    }
 
1454
 
 
1455
    pango_layout_set_font_description(layout, desc);
 
1456
    pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
 
1457
    pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
 
1458
    pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
 
1459
 
 
1460
    pango_layout_set_markup(layout, text.c_str(), -1);
 
1461
    pango_layout_set_height(layout, maxHeight);
 
1462
    pango_layout_set_width(layout, maxWidth * PANGO_SCALE);
 
1463
 
 
1464
    pangoCtx = pango_layout_get_context(layout);  // is not ref'ed
 
1465
 
 
1466
    if (!screen)
 
1467
      pango_cairo_context_set_font_options(pangoCtx, _defaultFontOptions);
 
1468
  else
 
1469
      pango_cairo_context_set_font_options(pangoCtx,
 
1470
                                           gdk_screen_get_font_options(screen));
 
1471
 
 
1472
    g_object_get(settings, "gtk-xft-dpi", &dpi, NULL);
 
1473
    if (dpi == -1)
 
1474
    {
 
1475
      // use some default DPI-value
 
1476
      pango_cairo_context_set_resolution(pangoCtx, 96.0f);
 
1477
    }
 
1478
    else
 
1479
    {
 
1480
      pango_cairo_context_set_resolution(pangoCtx,
 
1481
                                         (float) dpi / (float) PANGO_SCALE);
 
1482
    }
 
1483
    pango_layout_context_changed(layout);
 
1484
    pango_layout_get_extents(layout, &inkRect, NULL);
 
1485
 
 
1486
    width  = inkRect.width / PANGO_SCALE;
 
1487
    height = inkRect.height / PANGO_SCALE;
 
1488
 
 
1489
    // clean up
 
1490
    pango_font_description_free(desc);
 
1491
    g_object_unref(layout);
 
1492
    cairo_destroy(cr);
 
1493
    cairo_surface_destroy(surface);
 
1494
  }
 
1495
 
 
1496
  void DashStyle::Text (cairo_t*    cr,
 
1497
                        double      size,
 
1498
                        double*     color,
 
1499
                        double      opacity,
 
1500
                        std::string label)
 
1501
  {
 
1502
    double                x          = 0.0;
 
1503
    double                y          = 0.0;
 
1504
    int                   w          = 0;
 
1505
    int                   h          = 0;
 
1506
    PangoLayout*          layout     = NULL;
 
1507
    PangoFontDescription* desc       = NULL;
 
1508
    PangoContext*         pangoCtx   = NULL;
 
1509
    int                   dpi        = 0;
 
1510
    GdkScreen*            screen     = gdk_screen_get_default();   // not ref'ed
 
1511
    GtkSettings*          settings   = gtk_settings_get_default(); // not ref'ed
 
1512
    gchar*                fontName   = NULL;
 
1513
 
 
1514
    w = cairo_image_surface_get_width (cairo_get_target (cr));
 
1515
    h = cairo_image_surface_get_height (cairo_get_target (cr));
 
1516
 
 
1517
    if (!screen)
 
1518
      cairo_set_font_options(cr, _defaultFontOptions);
 
1519
    else
 
1520
      cairo_set_font_options(cr, gdk_screen_get_font_options(screen));
 
1521
    layout = pango_cairo_create_layout(cr);
 
1522
 
 
1523
    g_object_get(settings, "gtk-font-name", &fontName, NULL);
 
1524
    if (!fontName)
 
1525
      desc = pango_font_description_from_string("Sans 10");
 
1526
    else
 
1527
      desc = pango_font_description_from_string(fontName);
 
1528
 
 
1529
    PangoWeight weight;
 
1530
    switch (_regularTextWeight)
 
1531
    {
 
1532
      case FONT_WEIGHT_REGULAR:
 
1533
        weight = PANGO_WEIGHT_NORMAL;
 
1534
      break;
 
1535
 
 
1536
      case FONT_WEIGHT_LIGHT:
 
1537
        weight = PANGO_WEIGHT_LIGHT;
 
1538
      break;
 
1539
 
 
1540
      case FONT_WEIGHT_BOLD:
 
1541
        weight = PANGO_WEIGHT_BOLD;
 
1542
      break;
 
1543
    }
 
1544
    pango_font_description_set_weight(desc, weight);
 
1545
 
 
1546
    pango_layout_set_font_description(layout, desc);
 
1547
    pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
 
1548
    pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
 
1549
 
 
1550
    pango_layout_set_markup(layout, label.c_str(), -1);
 
1551
    pango_layout_set_width(layout, w * PANGO_SCALE);
 
1552
 
 
1553
    pango_layout_set_height(layout, h);
 
1554
    pangoCtx = pango_layout_get_context(layout);  // is not ref'ed
 
1555
 
 
1556
    if (!screen)
 
1557
      pango_cairo_context_set_font_options(pangoCtx, _defaultFontOptions);
 
1558
    else
 
1559
      pango_cairo_context_set_font_options(pangoCtx,
 
1560
                                           gdk_screen_get_font_options(screen));
 
1561
 
 
1562
    g_object_get(settings, "gtk-xft-dpi", &dpi, NULL);
 
1563
    if (dpi == -1)
 
1564
    {
 
1565
      // use some default DPI-value
 
1566
      pango_cairo_context_set_resolution(pangoCtx, 96.0f);
 
1567
    }
 
1568
    else
 
1569
    {
 
1570
      pango_cairo_context_set_resolution(pangoCtx,
 
1571
                                         (float) dpi / (float) PANGO_SCALE);
 
1572
    }
 
1573
 
 
1574
    cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
 
1575
    cairo_set_source_rgba (cr, color[R], color[G], color[B], opacity);
 
1576
    pango_layout_context_changed(layout);
 
1577
        PangoRectangle ink = {0, 0, 0, 0};
 
1578
    PangoRectangle log = {0, 0, 0, 0};
 
1579
    pango_layout_get_extents (layout, &ink, &log);
 
1580
        x = ((double) w - pango_units_to_double (ink.width)) / 2.0;
 
1581
    y = ((double) h - pango_units_to_double (log.height)) / 2.0;
 
1582
    cairo_move_to (cr, x, y);
 
1583
    pango_cairo_show_layout(cr, layout);
 
1584
 
 
1585
    // clean up
 
1586
    pango_font_description_free(desc);
 
1587
    g_object_unref(layout);
 
1588
    g_free(fontName);
 
1589
  }
 
1590
 
 
1591
  cairo_operator_t DashStyle::SetBlendMode (cairo_t* cr, BlendMode mode)
 
1592
  {
 
1593
    // sanity checks
 
1594
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
 
1595
      return CAIRO_OPERATOR_OVER;
 
1596
 
 
1597
    cairo_operator_t old;
 
1598
 
 
1599
    old = cairo_get_operator (cr);
 
1600
 
 
1601
    if (mode == BLEND_MODE_NORMAL)
 
1602
      cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
 
1603
 
 
1604
    if (mode == BLEND_MODE_MULTIPLY)
 
1605
      cairo_set_operator (cr, CAIRO_OPERATOR_MULTIPLY);
 
1606
 
 
1607
    if (mode == BLEND_MODE_SCREEN)
 
1608
      cairo_set_operator (cr, CAIRO_OPERATOR_SCREEN);
 
1609
 
 
1610
    return old;
 
1611
  }
 
1612
 
 
1613
  void DashStyle::DrawOverlay (cairo_t*  cr,
 
1614
                               double    opacity,
 
1615
                               BlendMode mode,
 
1616
                               int       blurSize)
 
1617
  {
 
1618
    // sanity checks
 
1619
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS ||
 
1620
        opacity <= 0.0                            ||
 
1621
        blurSize <= 0)
 
1622
      return;
 
1623
 
 
1624
    cairo_surface_t*     target     = NULL;
 
1625
    const unsigned char* data       = NULL;
 
1626
    int                  width      = 0;
 
1627
    int                  height     = 0;
 
1628
    int                  stride     = 0;
 
1629
    cairo_format_t       format     = CAIRO_FORMAT_INVALID;
 
1630
    unsigned char*       buffer     = NULL;
 
1631
    cairo_surface_t*     surface    = NULL;
 
1632
    cairo_t*             blurred_cr = NULL;
 
1633
    cairo_operator_t     old        = CAIRO_OPERATOR_CLEAR;
 
1634
 
 
1635
    // aquire info about image-surface
 
1636
    target = cairo_get_target (cr);
 
1637
    data   = cairo_image_surface_get_data (target);
 
1638
    width  = cairo_image_surface_get_width (target);
 
1639
    height = cairo_image_surface_get_height (target);
 
1640
    stride = cairo_image_surface_get_stride (target);
 
1641
    format = cairo_image_surface_get_format (target);
 
1642
 
 
1643
    // get buffer
 
1644
    buffer = (unsigned char*) calloc (1, height * stride);
 
1645
    if (!buffer)
 
1646
      return;
 
1647
 
 
1648
    // copy initial image-surface
 
1649
    memcpy (buffer, data, height * stride);
 
1650
    surface = cairo_image_surface_create_for_data (buffer, 
 
1651
                                                   format,
 
1652
                                                   width,
 
1653
                                                   height,
 
1654
                                                   stride);
 
1655
    if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
 
1656
    {
 
1657
      cairo_surface_destroy (surface);
 
1658
      free (buffer);
 
1659
      return;
 
1660
    }
 
1661
 
 
1662
    // prepare context
 
1663
    blurred_cr = cairo_create (surface);
 
1664
    if (cairo_status (blurred_cr) != CAIRO_STATUS_SUCCESS)
 
1665
    {
 
1666
      cairo_destroy (blurred_cr);
 
1667
      cairo_surface_destroy (surface);
 
1668
      free (buffer);
 
1669
      return;
 
1670
    }
 
1671
 
 
1672
    // blur and blend overlay onto initial image-surface
 
1673
    Blur (blurred_cr, blurSize);
 
1674
    //cairo_surface_write_to_png (surface, "/tmp/overlay-surface.png");
 
1675
    cairo_set_source_surface (cr, surface, 0.0, 0.0);
 
1676
    old = SetBlendMode (cr, mode);
 
1677
    cairo_paint_with_alpha (cr, opacity);
 
1678
 
 
1679
    // clean up
 
1680
    cairo_destroy (blurred_cr);
 
1681
    cairo_surface_destroy (surface);
 
1682
    free (buffer);
 
1683
    cairo_set_operator (cr, old);
 
1684
  }
 
1685
 
 
1686
  bool DashStyle::Button (cairo_t* cr, nux::State state, std::string label)
 
1687
  {
 
1688
  // sanity checks
 
1689
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
 
1690
      return false;
 
1691
 
 
1692
    if (cairo_surface_get_type (cairo_get_target (cr)) != CAIRO_SURFACE_TYPE_IMAGE)
 
1693
      return false;
 
1694
 
 
1695
    //ButtonOutlinePath (cr, true);
 
1696
    double w = cairo_image_surface_get_width (cairo_get_target (cr));
 
1697
    double h = cairo_image_surface_get_height (cairo_get_target (cr));
 
1698
    RoundedRect (cr,
 
1699
                 1.0,
 
1700
                 2.0,
 
1701
                 2.0,
 
1702
                 h / 4.0,
 
1703
                 w - 4.0,
 
1704
                 h - 4.0,
 
1705
                 true);
 
1706
 
 
1707
    if (_buttonLabelFillOpacity[state] != 0.0)
 
1708
    {
 
1709
      cairo_set_source_rgba (cr,
 
1710
                             _buttonLabelFillColor[state][R],
 
1711
                             _buttonLabelFillColor[state][G],
 
1712
                             _buttonLabelFillColor[state][B],
 
1713
                             _buttonLabelFillOpacity[state]);
 
1714
      cairo_fill_preserve (cr);
 
1715
    }
 
1716
    cairo_set_source_rgba (cr,
 
1717
                           _buttonLabelBorderColor[state][R],
 
1718
                           _buttonLabelBorderColor[state][G],
 
1719
                           _buttonLabelBorderColor[state][B],
 
1720
                           _buttonLabelBorderOpacity[state]);
 
1721
    cairo_set_line_width (cr, _buttonLabelBorderSize[state]);
 
1722
    cairo_stroke (cr);
 
1723
    Text (cr,
 
1724
        _buttonLabelTextSize,
 
1725
        _buttonLabelTextColor[state],
 
1726
        _buttonLabelTextOpacity[state],
 
1727
        label);
 
1728
 
 
1729
    return true;
 
1730
  }
 
1731
 
 
1732
  bool DashStyle::StarEmpty (cairo_t* cr, nux::State state)
 
1733
  {
 
1734
  // sanity checks
 
1735
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
 
1736
      return false;
 
1737
 
 
1738
    if (cairo_surface_get_type (cairo_get_target (cr)) != CAIRO_SURFACE_TYPE_IMAGE)
 
1739
      return false;
 
1740
 
 
1741
    double w = cairo_image_surface_get_width (cairo_get_target (cr));
 
1742
    double h = cairo_image_surface_get_height (cairo_get_target (cr));
 
1743
    double radius = .85 * h / 2.0;
 
1744
 
 
1745
  cairo_save (cr);
 
1746
    cairo_translate (cr, w / 2.0, h / 2.0);
 
1747
    Star (cr, radius);
 
1748
  cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.2);
 
1749
    cairo_fill_preserve (cr);
 
1750
  cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
 
1751
    cairo_stroke (cr);
 
1752
  cairo_restore (cr);
 
1753
 
 
1754
  return true;
 
1755
  }
 
1756
 
 
1757
  bool DashStyle::StarHalf (cairo_t* cr, nux::State state)
 
1758
  {
 
1759
  // sanity checks
 
1760
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
 
1761
      return false;
 
1762
 
 
1763
    if (cairo_surface_get_type (cairo_get_target (cr)) != CAIRO_SURFACE_TYPE_IMAGE)
 
1764
      return false;
 
1765
 
 
1766
    double w = cairo_image_surface_get_width (cairo_get_target (cr));
 
1767
    double h = cairo_image_surface_get_height (cairo_get_target (cr));
 
1768
    double radius = .85 * h / 2.0;
 
1769
 
 
1770
  cairo_pattern_t* pattern = NULL;
 
1771
    pattern = cairo_pattern_create_linear (0.0, 0.0, w, 0.0);
 
1772
  cairo_pattern_add_color_stop_rgba (pattern, 0.0,        1.0, 1.0, 1.0, 1.0);
 
1773
    cairo_pattern_add_color_stop_rgba (pattern,  .5,        1.0, 1.0, 1.0, 1.0);
 
1774
    cairo_pattern_add_color_stop_rgba (pattern,  .5 + 0.01, 1.0, 1.0, 1.0, 0.2);
 
1775
    cairo_pattern_add_color_stop_rgba (pattern, 1.0,        1.0, 1.0, 1.0, 0.2);
 
1776
  cairo_set_source (cr, pattern);
 
1777
 
 
1778
  cairo_save (cr);
 
1779
    cairo_translate (cr, w / 2.0, h / 2.0);
 
1780
    Star (cr, radius);
 
1781
  cairo_fill_preserve (cr);
 
1782
    cairo_pattern_destroy (pattern);
 
1783
  cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
 
1784
    cairo_stroke (cr);
 
1785
  cairo_restore (cr);
 
1786
 
 
1787
  return true;
 
1788
  }
 
1789
 
 
1790
  bool DashStyle::StarFull (cairo_t* cr, nux::State state)
 
1791
  {
 
1792
  // sanity checks
 
1793
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
 
1794
      return false;
 
1795
 
 
1796
    if (cairo_surface_get_type (cairo_get_target (cr)) != CAIRO_SURFACE_TYPE_IMAGE)
 
1797
      return false;
 
1798
 
 
1799
    double w = cairo_image_surface_get_width (cairo_get_target (cr));
 
1800
    double h = cairo_image_surface_get_height (cairo_get_target (cr));
 
1801
    double radius = .85 * h / 2.0;
 
1802
 
 
1803
  cairo_save (cr);
 
1804
    cairo_translate (cr, w / 2.0, h / 2.0);
 
1805
    Star (cr, radius);
 
1806
  cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
 
1807
    cairo_fill_preserve (cr);
 
1808
  cairo_stroke (cr); // to make sure it's as "large" as the empty and half ones
 
1809
  cairo_restore (cr);
 
1810
 
 
1811
  return true;
 
1812
  }
 
1813
 
 
1814
  bool DashStyle::MultiRangeSegment (cairo_t*    cr,
 
1815
                                     nux::State  state,
 
1816
                                     std::string label,
 
1817
                                     Arrow       arrow,
 
1818
                                     Segment     segment)
 
1819
  {
 
1820
  // sanity checks
 
1821
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
 
1822
      return false;
 
1823
 
 
1824
    if (cairo_surface_get_type (cairo_get_target (cr)) != CAIRO_SURFACE_TYPE_IMAGE)
 
1825
      return false;
 
1826
 
 
1827
    //ButtonOutlinePathSegment (cr, segment);
 
1828
    double   x  = 0.0;
 
1829
    double   y  = 2.0;
 
1830
    double   w  = cairo_image_surface_get_width (cairo_get_target (cr));
 
1831
    double   h  = cairo_image_surface_get_height (cairo_get_target (cr)) - 4.0;
 
1832
 
 
1833
        if (segment == SEGMENT_LEFT)
 
1834
        {
 
1835
      x = 2.0;
 
1836
      w -= 2.0;
 
1837
        }
 
1838
 
 
1839
        if (segment == SEGMENT_RIGHT)
 
1840
        {
 
1841
      w -= 2.0;
 
1842
        }
 
1843
 
 
1844
    RoundedRectSegment (cr,
 
1845
                        1.0,
 
1846
                        x,
 
1847
                        y,
 
1848
                        h / 4.0,
 
1849
                        w,
 
1850
                        h,
 
1851
                        segment,
 
1852
                        arrow,
 
1853
                        state);
 
1854
 
 
1855
    if (_buttonLabelFillOpacity[state] != 0.0)
 
1856
    {
 
1857
      cairo_set_source_rgba (cr,
 
1858
                             _buttonLabelFillColor[state][R],
 
1859
                             _buttonLabelFillColor[state][G],
 
1860
                             _buttonLabelFillColor[state][B],
 
1861
                             _buttonLabelFillOpacity[state]);
 
1862
      cairo_fill_preserve (cr);
 
1863
    }
 
1864
    cairo_set_source_rgba (cr,
 
1865
                           _buttonLabelBorderColor[state][R],
 
1866
                           _buttonLabelBorderColor[state][G],
 
1867
                           _buttonLabelBorderColor[state][B],
 
1868
                           _buttonLabelBorderOpacity[state]);
 
1869
    cairo_set_line_width (cr, _buttonLabelBorderSize[state]);
 
1870
    cairo_stroke (cr);
 
1871
    Text (cr,
 
1872
        _buttonLabelTextSize,
 
1873
        _buttonLabelTextColor[state],
 
1874
        _buttonLabelTextOpacity[state],
 
1875
        label);
 
1876
 
 
1877
    return true;
 
1878
  }
 
1879
 
 
1880
  bool DashStyle::TrackViewNumber (cairo_t*    cr,
 
1881
                                   nux::State  state,
 
1882
                                   std::string trackNumber)
 
1883
  {
 
1884
  // sanity checks
 
1885
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
 
1886
      return false;
 
1887
 
 
1888
    if (cairo_surface_get_type (cairo_get_target (cr)) != CAIRO_SURFACE_TYPE_IMAGE)
 
1889
      return false;
 
1890
 
 
1891
    return true;
 
1892
  }
 
1893
 
 
1894
  bool DashStyle::TrackViewPlay (cairo_t*   cr,
 
1895
                                 nux::State state)
 
1896
  {
 
1897
  // sanity checks
 
1898
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
 
1899
      return false;
 
1900
 
 
1901
    if (cairo_surface_get_type (cairo_get_target (cr)) != CAIRO_SURFACE_TYPE_IMAGE)
 
1902
      return false;
 
1903
 
 
1904
    return true;
 
1905
  }
 
1906
 
 
1907
  bool DashStyle::TrackViewPause (cairo_t*   cr,
 
1908
                                  nux::State state)
 
1909
  {
 
1910
  // sanity checks
 
1911
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
 
1912
      return false;
 
1913
 
 
1914
    if (cairo_surface_get_type (cairo_get_target (cr)) != CAIRO_SURFACE_TYPE_IMAGE)
 
1915
      return false;
 
1916
 
 
1917
    return true;
 
1918
  }
 
1919
 
 
1920
  bool DashStyle::TrackViewProgress (cairo_t* cr)
 
1921
  {
 
1922
  // sanity checks
 
1923
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
 
1924
      return false;
 
1925
 
 
1926
    if (cairo_surface_get_type (cairo_get_target (cr)) != CAIRO_SURFACE_TYPE_IMAGE)
 
1927
      return false;
 
1928
 
 
1929
    return true;
 
1930
  }
 
1931
 
 
1932
  bool DashStyle::SeparatorVert (cairo_t* cr)
 
1933
  {
 
1934
    // sanity checks
 
1935
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
 
1936
      return false;
 
1937
 
 
1938
    if (cairo_surface_get_type (cairo_get_target (cr)) != CAIRO_SURFACE_TYPE_IMAGE)
 
1939
      return false;
 
1940
 
 
1941
    double w = cairo_image_surface_get_width (cairo_get_target (cr));
 
1942
    double h = cairo_image_surface_get_height (cairo_get_target (cr));
 
1943
    double x = w / 2.0;
 
1944
    double y = 2.0;
 
1945
 
 
1946
    cairo_set_line_width (cr, _separatorSize);
 
1947
    cairo_set_source_rgba (cr,
 
1948
                           _separatorColor[R],
 
1949
                           _separatorColor[G],
 
1950
                           _separatorColor[B],
 
1951
                           _separatorOpacity);
 
1952
    cairo_move_to (cr, _align (x), _align (y));
 
1953
    cairo_line_to (cr, _align (x), _align (h - 4.0));
 
1954
    cairo_stroke (cr);
 
1955
 
 
1956
    DrawOverlay (cr,
 
1957
                 _separatorOverlayOpacity,
 
1958
                 _separatorOverlayMode,
 
1959
                 _separatorBlurSize);
 
1960
 
 
1961
    return true;
 
1962
  }
 
1963
 
 
1964
  bool DashStyle::SeparatorHoriz (cairo_t* cr)
 
1965
  {
 
1966
    // sanity checks
 
1967
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
 
1968
      return false;
 
1969
 
 
1970
    if (cairo_surface_get_type (cairo_get_target (cr)) != CAIRO_SURFACE_TYPE_IMAGE)
 
1971
      return false;
 
1972
 
 
1973
    double w = cairo_image_surface_get_width (cairo_get_target (cr));
 
1974
    double h = cairo_image_surface_get_height (cairo_get_target (cr));
 
1975
    double x = 2.0;
 
1976
    double y = h / 2.0;
 
1977
 
 
1978
    cairo_set_line_width (cr, _separatorSize);
 
1979
    cairo_set_source_rgba (cr,
 
1980
                           _separatorColor[R],
 
1981
                           _separatorColor[G],
 
1982
                           _separatorColor[B],
 
1983
                           _separatorOpacity);
 
1984
    cairo_move_to (cr, _align (x), _align (y));
 
1985
    cairo_line_to (cr, _align (w - 4.0), _align (y));
 
1986
    cairo_stroke (cr);
 
1987
 
 
1988
    DrawOverlay (cr,
 
1989
                 _separatorOverlayOpacity,
 
1990
                 _separatorOverlayMode,
 
1991
                 _separatorBlurSize);
 
1992
 
 
1993
    return true;
 
1994
  }
 
1995
}