2 Copyright (C) 2009 Paul Davis
3 Copyright (C) 2015 Robin Gareus <robin@gareus.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include <math.h> // M_PI
22 #include <algorithm> // std:min
23 #include "gtkmm2ext/ardour_icon.h"
25 using namespace Gtkmm2ext::ArdourIcon;
27 // from libs/canvas/utils.cc and canvas/types.h: typedef uint32_t Color;
28 static void ardour_icon_set_source_rgba (cairo_t *cr, uint32_t color)
30 cairo_set_source_rgba (cr,
31 ((color >> 24) & 0xff) / 255.0,
32 ((color >> 16) & 0xff) / 255.0,
33 ((color >> 8) & 0xff) / 255.0,
34 ((color >> 0) & 0xff) / 255.0
38 static void ardour_icon_set_source_inv_rgba (cairo_t *cr, uint32_t color)
40 cairo_set_source_rgba (cr,
41 1.0 - ((color >> 24) & 0xff) / 255.0,
42 1.0 - ((color >> 16) & 0xff) / 255.0,
43 1.0 - ((color >> 8) & 0xff) / 255.0,
44 ((color >> 0) & 0xff) / 255.0
49 Gtkmm2ext::ArdourIcon::render (cairo_t *cr,
50 const enum Gtkmm2ext::ArdourIcon::Icon icon,
51 const int width, const int height,
52 const Gtkmm2ext::ActiveState state,
53 const uint32_t fg_color)
56 #define VECTORICONSTROKEFILL(fillalpha) \
57 cairo_set_line_width(cr, 1.5); \
58 cairo_set_source_rgba (cr, 0, 0, 0, 1.0); \
59 cairo_stroke_preserve(cr); \
60 cairo_set_source_rgba (cr, 1, 1, 1, (fillalpha)); \
63 #define VECTORICONSTROKEOUTLINE(LW, color) \
64 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); \
65 cairo_set_line_width(cr, (LW) + 1.5); \
66 ardour_icon_set_source_inv_rgba (cr, color); \
67 cairo_stroke_preserve(cr); \
68 ardour_icon_set_source_rgba (cr, color); \
69 cairo_set_line_width(cr, (LW)); \
76 const double x = width * .5;
77 const double y = height * .5;
78 const double r = std::min(x, y) * .6;
79 const double slit = .11 * M_PI;
81 cairo_translate(cr, x, y);
83 cairo_arc (cr, 0, 0, r, 0, 2 * M_PI);
84 if (state == Gtkmm2ext::ExplicitActive) {
85 cairo_set_source_rgba (cr, .95, .1, .1, 1.);
87 cairo_set_source_rgba (cr, .95, .44, .44, 1.); // #f46f6f
89 cairo_fill_preserve(cr);
90 cairo_set_source_rgba (cr, .0, .0, .0, .5);
91 cairo_set_line_width(cr, 1);
95 cairo_set_source_rgba (cr, .15, .07, .07, 1.0);
97 cairo_rotate (cr, -.5 * M_PI);
98 cairo_move_to(cr, 0, 0);
99 cairo_arc (cr, 0, 0, r *.85, -slit, slit);
100 cairo_line_to(cr, 0, 0);
101 cairo_close_path(cr);
104 cairo_rotate (cr, 2. * M_PI / 3.);
106 cairo_move_to(cr, 0, 0);
107 cairo_arc (cr, 0, 0, r *.85, -slit, slit);
108 cairo_line_to(cr, 0, 0);
109 cairo_close_path(cr);
112 cairo_rotate (cr, 2. * M_PI / 3.);
113 cairo_move_to(cr, 0, 0);
114 cairo_arc (cr, 0, 0, r *.85, -slit, slit);
115 cairo_line_to(cr, 0, 0);
116 cairo_close_path(cr);
121 cairo_arc (cr, 0, 0, r * .3, 0, 2 * M_PI);
122 if (state == Gtkmm2ext::ExplicitActive)
123 cairo_set_source_rgba (cr, .95, .1, .1, 1.);
125 cairo_set_source_rgba (cr, .95, .44, .44, 1.); // #f46f6f
127 cairo_set_source_rgba (cr, .0, .0, .0, 1.0);
128 cairo_arc (cr, 0, 0, r *.15, 0, 2 * M_PI); // hole in the middle
136 const double x = width * .5;
137 const double y = height * .5;
138 const double r = std::min(x, y) * .55;
139 cairo_arc (cr, x, y, r, 0, 2 * M_PI);
140 if (state == Gtkmm2ext::ExplicitActive)
141 cairo_set_source_rgba (cr, .95, .1, .1, 1.);
143 cairo_set_source_rgba (cr, .95, .44, .44, 1.); // #f46f6f
144 cairo_fill_preserve(cr);
145 cairo_set_source_rgba (cr, .0, .0, .0, .8);
146 cairo_set_line_width(cr, 1);
152 const double x = width * .5;
153 const double y = height * .5;
154 const double o = .5 + std::min(x, y) * .4;
155 ardour_icon_set_source_rgba (cr, fg_color);
156 cairo_set_line_width(cr, 1);
157 cairo_move_to(cr, x-o, y-o);
158 cairo_line_to(cr, x+o, y+o);
159 cairo_move_to(cr, x+o, y-o);
160 cairo_line_to(cr, x-o, y+o);
166 const double x0 = width * .2;
167 const double x1 = width * .8;
169 const double y0 = height * .25;
170 const double y1= height * .75;
172 const double ym= height * .5;
175 const double xa0= height * .39;
176 const double xa1= height * .61;
177 const double ya0= height * .35;
178 const double ya1= height * .65;
180 ardour_icon_set_source_rgba (cr, fg_color);
181 cairo_set_line_width(cr, 1);
184 cairo_move_to(cr, x0, y0);
185 cairo_line_to(cr, x0, y1);
186 cairo_move_to(cr, x1, y0);
187 cairo_line_to(cr, x1, y1);
190 cairo_move_to(cr, x0, ym);
191 cairo_line_to(cr, x1, ym);
194 cairo_move_to(cr, x0, ym);
195 cairo_line_to(cr, xa0, ya0);
196 cairo_move_to(cr, x0, ym);
197 cairo_line_to(cr, xa0, ya1);
200 cairo_move_to(cr, x1, ym);
201 cairo_line_to(cr, xa1, ya0);
202 cairo_move_to(cr, x1, ym);
203 cairo_line_to(cr, xa1, ya1);
209 const double x = width * .5;
210 const double y = height * .5;
211 const double r = std::min(x, y) * .75;
212 ardour_icon_set_source_rgba (cr, fg_color);
213 cairo_set_line_width(cr, 1);
214 cairo_arc (cr, x, y, r, .57 * M_PI, 2.43 * M_PI);
217 // pins equally spaced 45deg
218 cairo_arc (cr, x, y * 0.5, r * .15, 0, 2 * M_PI);
220 cairo_arc (cr, x * 0.5, y, r * .15, 0, 2 * M_PI);
222 cairo_arc (cr, x * 1.5, y, r * .15, 0, 2 * M_PI);
224 // .5 + .5 * .5 * sin(45deg), 1.5 - .5 * .5 * cos(45deg)
225 cairo_arc (cr, x * 0.677, y * .677, r * .15, 0, 2 * M_PI);
227 cairo_arc (cr, x * 1.323, y * .677, r * .15, 0, 2 * M_PI);
231 cairo_arc (cr, x, y+r, r * .26, 1.05 * M_PI, 1.95 * M_PI);
237 const int wh = std::min (width, height);
239 (width - wh) * .5 + wh * .25,
240 (height - wh) * .5 + wh * .25,
243 VECTORICONSTROKEFILL(0.8);
248 const int wh = std::min (width, height) * .5;
249 const double y = height * .5;
250 const double x = width - wh;
252 const float tri = ceil(.577 * wh); // 1/sqrt(3)
254 cairo_move_to (cr, x + wh * .5, y);
255 cairo_line_to (cr, x - wh * .5, y - tri);
256 cairo_line_to (cr, x - wh * .5, y + tri);
257 cairo_close_path (cr);
259 VECTORICONSTROKEFILL(0.8);
264 const int wh = std::min (width, height) * .1;
265 const double xc = width * .5;
266 const double yh = height;
270 VECTORICONSTROKEFILL(0.8);
272 cairo_arc (cr, xc, yh *.75, wh, 0, 2 * M_PI);
273 VECTORICONSTROKEFILL(0.8);
280 // small play triangle
281 int wh = std::min (width, height);
282 const double y = height * .5;
283 const double x = width - wh * .5;
285 const float tri = ceil(.577 * wh * 2); // 1/sqrt(3)
287 const float ln = std::min (width, height) * .07;
289 if (icon == TransportStart || icon == TransportRange) {
291 x - wh - ln, y - tri * 1.7,
294 VECTORICONSTROKEFILL(1.0);
297 if (icon == TransportEnd || icon == TransportRange) {
299 x + wh - ln, y - tri * 1.7,
302 VECTORICONSTROKEFILL(1.0);
305 if (icon == TransportStart) {
306 cairo_move_to (cr, x - wh, y);
307 cairo_line_to (cr, x + wh, y - tri);
308 cairo_line_to (cr, x + wh, y + tri);
310 cairo_move_to (cr, x + wh, y);
311 cairo_line_to (cr, x - wh, y - tri);
312 cairo_line_to (cr, x - wh, y + tri);
315 cairo_close_path (cr);
316 VECTORICONSTROKEFILL(1.0);
321 const double x = width * .5;
322 const double y = height * .5;
323 const double r = std::min(x, y);
325 cairo_arc (cr, x, y, r * .62, 0, 2 * M_PI);
326 cairo_arc_negative (cr, x, y, r * .35, 2 * M_PI, 0);
328 VECTORICONSTROKEFILL(1.0);
329 #define ARCARROW(rad, ang) \
330 x + (rad) * sin((ang) * 2.0 * M_PI), y + (rad) * cos((ang) * 2.0 * M_PI)
332 cairo_move_to (cr, ARCARROW(r * .35, .72));
333 cairo_line_to (cr, ARCARROW(r * .15, .72));
334 cairo_line_to (cr, ARCARROW(r * .56, .60));
335 cairo_line_to (cr, ARCARROW(r * .75, .72));
336 cairo_line_to (cr, ARCARROW(r * .62, .72));
338 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
339 cairo_stroke_preserve(cr);
340 cairo_close_path (cr);
341 cairo_set_source_rgba (cr, 1, 1, 1, 1.0);
346 case TransportMetronom:
348 const double x = width * .5;
349 const double y = height * .5;
350 const double wh = std::min(x, y);
351 const double h = wh * .85;
352 const double w = wh * .55;
353 const double lw = w * .34;
356 x - w * .7, y + h * .25,
359 VECTORICONSTROKEFILL(1.0);
361 cairo_move_to (cr, x - w, y + h);
362 cairo_line_to (cr, x + w, y + h);
363 cairo_line_to (cr, x + w * .35, y - h);
364 cairo_line_to (cr, x - w * .35, y - h);
365 cairo_line_to (cr, x - w, y + h);
367 cairo_move_to (cr, x - w + lw, y + h -lw);
368 cairo_line_to (cr, x - w * .35 + lw, y - h + lw);
369 cairo_line_to (cr, x + w * .35 - lw, y - h + lw);
370 cairo_line_to (cr, x + w - lw, y + h -lw);
371 cairo_line_to (cr, x - w + lw, y + h -lw);
373 VECTORICONSTROKEFILL(1.0);
375 // ddx = .70 w = .75 * .5 wh = .375 wh
376 // ddy = .75 h - lw = .75 * .8 wh - wh .5 * .2 = .5 wh
378 // -> angle = atan (ang) = atan (375 / .5) ~= 36deg
379 const double dx = lw * .2; // 1 - cos(tan^-1(ang))
380 const double dy = lw * .4; // 1 - sin(tan^-1(ang))
381 cairo_move_to (cr, x - w * .3 , y + h * .25 + lw * .5);
382 cairo_line_to (cr, x - w + dx , y - h + lw + dy);
383 cairo_line_to (cr, x - w + lw , y - h + lw);
384 cairo_line_to (cr, x - w * .3 + lw, y + h * .25 + lw * .5);
385 cairo_close_path (cr);
387 VECTORICONSTROKEFILL(1.0);
390 x - w * .7, y + h * .25,
397 const double x = width * .5;
398 const double y = height * .5;
399 const double wh = std::min (x, y);
401 const double tri_x = .3 * wh;
402 const double tri_y = .6 * wh;
404 cairo_move_to (cr, x + tri_x, y - tri_y);
405 cairo_line_to (cr, x - tri_x, y);
406 cairo_line_to (cr, x + tri_x, y + tri_y);
407 VECTORICONSTROKEOUTLINE(1.5, fg_color);
413 const double x = width * .5;
414 const double y = height * .5;
415 const double wh = std::min (x, y);
417 const double tri_x = .3 * wh;
418 const double tri_y = .6 * wh;
420 cairo_move_to (cr, x - tri_x, y - tri_y);
421 cairo_line_to (cr, x + tri_x, y);
422 cairo_line_to (cr, x - tri_x, y + tri_y);
423 VECTORICONSTROKEOUTLINE(1.5, fg_color);
431 const double x = width * .5;
432 const double y = height * .5;
433 const double r = std::min (x, y) * .7;
434 const double wh = std::min (x, y) * .45;
437 #define LINE45DEG(rad) \
438 x + r * (rad) * .707, y + r * (rad) * .707 // sin(45deg) = cos(45deg) = .707
439 cairo_move_to (cr, LINE45DEG(.9));
440 cairo_line_to (cr, LINE45DEG(1.3));
441 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
442 cairo_set_line_width (cr, 3.0);
443 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
448 ardour_icon_set_source_rgba (cr, fg_color);
449 cairo_arc (cr, x, y, r, 0, 2 * M_PI);
450 cairo_fill_preserve (cr);
452 // add a lens gradient
453 cairo_pattern_t *lens;
454 lens = cairo_pattern_create_radial (x - r, y - r, r * .5, x - r, y - r, r * 2);
455 cairo_pattern_add_color_stop_rgba (lens, 0, 1, 1, 1, .4);
456 cairo_pattern_add_color_stop_rgba (lens, 1, 0, 0, 0, .4);
457 cairo_set_source (cr, lens);
458 cairo_fill_preserve (cr);
459 cairo_pattern_destroy (lens);
462 cairo_set_line_width (cr, 1.5);
463 //ardour_icon_set_source_inv_rgba (cr, fg_color); // alpha
464 cairo_set_source_rgba (cr, .0, .0, .0, .8);
467 // add "+", "-" or "[]"
468 cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
469 cairo_set_line_width (cr, 1.5);
470 ardour_icon_set_source_inv_rgba (cr, fg_color);
472 if (icon == ZoomIn || icon == ZoomOut) {
473 cairo_move_to (cr, x - wh, y);
474 cairo_line_to (cr, x + wh, y);
477 if (icon == ZoomIn) {
478 cairo_move_to (cr, x, y - wh);
479 cairo_line_to (cr, x, y + wh);
482 if (icon == ZoomFull) {
483 const double br0 = std::min (x, y) * .1;
484 const double br1 = std::min (x, y) * .3;
485 const double bry = std::min (x, y) * .3;
486 cairo_move_to (cr, x - br0, y - bry);
487 cairo_line_to (cr, x - br1, y - bry);
488 cairo_line_to (cr, x - br1, y + bry);
489 cairo_line_to (cr, x - br0, y + bry);
492 cairo_move_to (cr, x + br0, y - bry);
493 cairo_line_to (cr, x + br1, y - bry);
494 cairo_line_to (cr, x + br1, y + bry);
495 cairo_line_to (cr, x + br0, y + bry);
502 const double x = width * .5;
503 const double y = height * .5;
504 const double wh = std::min (x, y) * .66;
505 const double ar = std::min (x, y) * .15;
506 const double tri = .7 * (wh - ar);
508 cairo_rectangle (cr, x - wh, y - ar, 2 * wh, 2 * ar);
509 VECTORICONSTROKEFILL(.75);
511 cairo_set_line_width(cr, 1.0);
513 cairo_move_to (cr, x, y - ar - 0.5);
514 cairo_line_to (cr, x - tri, y - wh + 0.5);
515 cairo_line_to (cr, x + tri, y - wh + 0.5);
516 cairo_close_path (cr);
518 cairo_set_source_rgba (cr, 1, 1, 1, .75);
519 cairo_stroke_preserve(cr);
520 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
523 cairo_move_to (cr, x, y + ar + 0.5);
524 cairo_line_to (cr, x - tri, y + wh - 0.5);
525 cairo_line_to (cr, x + tri, y + wh - 0.5);
526 cairo_close_path (cr);
528 cairo_set_source_rgba (cr, 1, 1, 1, .75);
529 cairo_stroke_preserve(cr);
530 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
536 const double x = width * .5;
537 const double y = height * .5;
538 const double wh = std::min (x, y) * .66;
539 const double ar = std::min (x, y) * .15;
540 const double tri = .7 * (wh - ar);
542 cairo_rectangle (cr, x - wh, y - wh, 2 * wh, 2 * wh);
543 VECTORICONSTROKEFILL(.75);
545 cairo_set_line_width(cr, 1.0);
547 cairo_move_to (cr, x, y - wh + 0.5);
548 cairo_line_to (cr, x - tri, y - ar - 0.5);
549 cairo_line_to (cr, x + tri, y - ar - 0.5);
550 cairo_close_path (cr);
552 cairo_set_source_rgba (cr, 1, 1, 1, .5);
553 cairo_stroke_preserve(cr);
554 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
557 cairo_move_to (cr, x , y + wh - 0.5);
558 cairo_line_to (cr, x - tri, y + ar + 0.5);
559 cairo_line_to (cr, x + tri, y + ar + 0.5);
560 cairo_close_path (cr);
562 cairo_set_source_rgba (cr, 1, 1, 1, .5);
563 cairo_stroke_preserve(cr);
564 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
570 const double x = width * .5;
571 const double y = height * .5;
572 const double wh = std::min (x, y) * .6;
573 const double lw = wh / 6.0; // line width (1px with 20x20 button)
574 const double ar = wh * .5; // arrow
575 const double ym = rint (y - wh * .1) + .5; // slightly to the top, on a px
577 const double x0 = x - wh;
578 const double x1 = x + wh;
585 VECTORICONSTROKEFILL(1.0);
592 VECTORICONSTROKEFILL(1.0);
596 // don't draw outline inside the boxes
597 cairo_rectangle (cr, x0, y - wh,
602 cairo_move_to (cr, x0 + ar, ym - ar);
603 cairo_line_to (cr, x0, ym);
604 cairo_line_to (cr, x0 + ar, ym + ar);
606 cairo_move_to (cr, x1 - ar, ym - ar);
607 cairo_line_to (cr, x1, ym);
608 cairo_line_to (cr, x1 - ar, ym + ar);
610 cairo_move_to (cr, x0, ym);
611 cairo_line_to (cr, x1, ym);
612 VECTORICONSTROKEOUTLINE(lw, 0xffffffff);
619 const double x = width * .5;
620 const double y = height * .5;
621 const double em = std::min (x, y) * .15; // 3px at 20x20
623 // 6x8em hand, with 'em' wide index finger.
624 #define EM_POINT(X,Y) \
625 x + (X) * em, y + (Y) * em
628 cairo_move_to (cr, EM_POINT( 2.0, 4.0));
629 cairo_line_to (cr, EM_POINT(-1.5, 4.0));
630 cairo_line_to (cr, EM_POINT(-2.5, 2.0));
632 cairo_line_to (cr, EM_POINT(-3.0, 1.0));
635 cairo_line_to (cr, EM_POINT(-2.0, 0.0));
636 cairo_line_to (cr, EM_POINT(-2.1, -4.0));
637 cairo_line_to (cr, EM_POINT(-1.5, -4.5));
638 cairo_line_to (cr, EM_POINT(-1.1, -4.0));
639 cairo_line_to (cr, EM_POINT(-1.0, 0.1));
641 // middle finger knuckle
642 cairo_line_to (cr, EM_POINT(-0.8, 0.0));
643 cairo_line_to (cr, EM_POINT( 0.3, -0.4));
644 cairo_line_to (cr, EM_POINT( 0.4, -0.6));
645 cairo_line_to (cr, EM_POINT( 0.5, -0.4));
646 cairo_line_to (cr, EM_POINT( 0.5, 0.1));
648 // ring finger knuckle
649 cairo_line_to (cr, EM_POINT( 1.0, 0.2));
650 cairo_line_to (cr, EM_POINT( 1.4, -0.3));
651 cairo_line_to (cr, EM_POINT( 1.5, -0.5));
652 cairo_line_to (cr, EM_POINT( 1.6, -0.3));
653 cairo_line_to (cr, EM_POINT( 1.6, 0.3));
656 cairo_line_to (cr, EM_POINT( 2.0, 0.5));
657 cairo_line_to (cr, EM_POINT( 2.5, 0.1));
658 cairo_line_to (cr, EM_POINT( 2.6, 0.0));
659 cairo_line_to (cr, EM_POINT( 2.7, 0.1));
660 cairo_line_to (cr, EM_POINT( 3.0, 1.0));
663 cairo_line_to (cr, EM_POINT( 3.0, 1.5));
664 cairo_line_to (cr, EM_POINT( 2.0, 4.0));
666 cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
667 cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
668 VECTORICONSTROKEFILL(1.0);
673 } // end switch (icon)
675 #undef VECTORICONSTROKEFILL
676 #undef VECTORICONSTROKEOUTLINE