NOOP, amend 3173246 comments and whitespace
[ardour.git] / libs / gtkmm2ext / ardour_icon.cc
1 /*
2     Copyright (C) 2009 Paul Davis
3     Copyright (C) 2015 Robin Gareus <robin@gareus.org>
4
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.
9
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.
14
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.
18
19 */
20
21 #include <math.h> // M_PI
22 #include <algorithm> // std:min
23 #include "gtkmm2ext/ardour_icon.h"
24
25 // from libs/canvas/utils.cc and  canvas/types.h: typedef uint32_t Color;
26 static void ardour_canvas_set_source_rgba (cairo_t *cr, uint32_t color)
27 {
28         cairo_set_source_rgba (cr,
29                         ((color >> 24) & 0xff) / 255.0,
30                         ((color >> 16) & 0xff) / 255.0,
31                         ((color >>  8) & 0xff) / 255.0,
32                         ((color >>  0) & 0xff) / 255.0
33                         );
34 }
35
36 bool
37 Gtkmm2ext::ArdourIcon::render (cairo_t *cr,
38                                const enum Gtkmm2ext::ArdourIcon::Icon icon,
39                                const int width, const int height,
40                                const Gtkmm2ext::ActiveState state,
41                                const uint32_t fg_color)
42 {
43
44 #define VECTORICONSTROKEFILL(fillalpha) \
45         cairo_set_line_width(cr, 1.5); \
46         cairo_set_source_rgba (cr, 0, 0, 0, 1.0); \
47         cairo_stroke_preserve(cr); \
48         cairo_set_source_rgba (cr, 1, 1, 1, (fillalpha)); \
49         cairo_fill(cr);
50
51 #define VECTORICONSTROKEOUTLINE() \
52         cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); \
53         cairo_set_line_width(cr, 3.0); \
54         cairo_set_source_rgba (cr, 0, 0, 0, 1.0); \
55         cairo_stroke_preserve(cr); \
56         ardour_canvas_set_source_rgba (cr, fg_color); \
57         cairo_set_line_width(cr, 1.5);  \
58         cairo_stroke(cr);
59
60         switch (icon) {
61
62         case Gtkmm2ext::ArdourIcon::RecTapeMode:
63         {
64                 const double x = width * .5;
65                 const double y = height * .5;
66                 const double r = std::min(x, y) * .6;
67                 const double slit = .11 * M_PI;
68                 cairo_save(cr);
69                 cairo_translate(cr, x, y);
70
71                 cairo_arc (cr, 0, 0, r, 0, 2 * M_PI);
72                 if (state == Gtkmm2ext::ExplicitActive) {
73                         cairo_set_source_rgba (cr, .95, .1, .1, 1.);
74                 } else {
75                         cairo_set_source_rgba (cr, .95, .44, .44, 1.); // #f46f6f
76                 }
77                 cairo_fill_preserve(cr);
78                 cairo_set_source_rgba (cr, .0, .0, .0, .5);
79                 cairo_set_line_width(cr, 1);
80                 cairo_stroke(cr);
81
82                 cairo_save(cr);
83                 cairo_set_source_rgba (cr, .15, .07, .07, 1.0);
84
85                 cairo_rotate (cr, -.5 * M_PI);
86                 cairo_move_to(cr, 0, 0);
87                 cairo_arc (cr, 0, 0, r *.85, -slit, slit);
88                 cairo_line_to(cr, 0, 0);
89                 cairo_close_path(cr);
90
91                 cairo_fill(cr);
92                 cairo_rotate (cr, 2. * M_PI / 3.);
93
94                 cairo_move_to(cr, 0, 0);
95                 cairo_arc (cr, 0, 0, r *.85, -slit, slit);
96                 cairo_line_to(cr, 0, 0);
97                 cairo_close_path(cr);
98                 cairo_fill(cr);
99
100                 cairo_rotate (cr, 2. * M_PI / 3.);
101                 cairo_move_to(cr, 0, 0);
102                 cairo_arc (cr, 0, 0, r *.85, -slit, slit);
103                 cairo_line_to(cr, 0, 0);
104                 cairo_close_path(cr);
105                 cairo_fill(cr);
106
107                 cairo_restore(cr);
108
109                 cairo_arc (cr, 0, 0, r * .3, 0, 2 * M_PI);
110                 if (state == Gtkmm2ext::ExplicitActive)
111                         cairo_set_source_rgba (cr, .95, .1, .1, 1.);
112                 else
113                         cairo_set_source_rgba (cr, .95, .44, .44, 1.); // #f46f6f
114                 cairo_fill(cr);
115                 cairo_set_source_rgba (cr, .0, .0, .0, 1.0);
116                 cairo_arc (cr, 0, 0, r *.15, 0, 2 * M_PI); // hole in the middle
117                 cairo_fill(cr);
118
119                 cairo_restore(cr);
120         }
121         break;
122         case Gtkmm2ext::ArdourIcon::RecButton:
123         {
124                 const double x = width * .5;
125                 const double y = height * .5;
126                 const double r = std::min(x, y) * .55;
127                 cairo_arc (cr, x, y, r, 0, 2 * M_PI);
128                 if (state == Gtkmm2ext::ExplicitActive)
129                         cairo_set_source_rgba (cr, .95, .1, .1, 1.);
130                 else
131                         cairo_set_source_rgba (cr, .95, .44, .44, 1.); // #f46f6f
132                 cairo_fill_preserve(cr);
133                 cairo_set_source_rgba (cr, .0, .0, .0, .8);
134                 cairo_set_line_width(cr, 1);
135                 cairo_stroke(cr);
136         }
137         break;
138         case Gtkmm2ext::ArdourIcon::CloseCross:
139         {
140                 const double x = width * .5;
141                 const double y = height * .5;
142                 const double o = .5 + std::min(x, y) * .4;
143                 ardour_canvas_set_source_rgba (cr, fg_color);
144                 cairo_set_line_width(cr, 1);
145                 cairo_move_to(cr, x-o, y-o);
146                 cairo_line_to(cr, x+o, y+o);
147                 cairo_move_to(cr, x+o, y-o);
148                 cairo_line_to(cr, x-o, y+o);
149                 cairo_stroke(cr);
150         }
151         break;
152         case Gtkmm2ext::ArdourIcon::StripWidth:
153         {
154                 const double x0 = width  * .2;
155                 const double x1 = width  * .8;
156
157                 const double y0 = height * .25;
158                 const double y1= height  * .75;
159
160                 const double ym= height  * .5;
161
162                 // arrow
163                 const double xa0= height  * .39;
164                 const double xa1= height  * .61;
165                 const double ya0= height  * .35;
166                 const double ya1= height  * .65;
167
168                 ardour_canvas_set_source_rgba (cr, fg_color);
169                 cairo_set_line_width(cr, 1);
170
171                 // left + right
172                 cairo_move_to(cr, x0, y0);
173                 cairo_line_to(cr, x0, y1);
174                 cairo_move_to(cr, x1, y0);
175                 cairo_line_to(cr, x1, y1);
176
177                 // horiz center line
178                 cairo_move_to(cr, x0, ym);
179                 cairo_line_to(cr, x1, ym);
180
181                 // arrow left
182                 cairo_move_to(cr,  x0, ym);
183                 cairo_line_to(cr, xa0, ya0);
184                 cairo_move_to(cr,  x0, ym);
185                 cairo_line_to(cr, xa0, ya1);
186
187                 // arrow right
188                 cairo_move_to(cr,  x1,  ym);
189                 cairo_line_to(cr, xa1, ya0);
190                 cairo_move_to(cr,  x1,  ym);
191                 cairo_line_to(cr, xa1, ya1);
192                 cairo_stroke(cr);
193         }
194         break;
195         case Gtkmm2ext::ArdourIcon::DinMidi:
196         {
197                 const double x = width * .5;
198                 const double y = height * .5;
199                 const double r = std::min(x, y) * .75;
200                 ardour_canvas_set_source_rgba (cr, fg_color);
201                 cairo_set_line_width(cr, 1);
202                 cairo_arc (cr, x, y, r, .57 * M_PI, 2.43 * M_PI);
203                 cairo_stroke(cr);
204
205                 // pins equally spaced 45deg
206                 cairo_arc (cr, x, y * 0.5, r * .15, 0, 2 * M_PI);
207                 cairo_fill(cr);
208                 cairo_arc (cr, x * 0.5, y, r * .15, 0, 2 * M_PI);
209                 cairo_fill(cr);
210                 cairo_arc (cr, x * 1.5, y, r * .15, 0, 2 * M_PI);
211                 cairo_fill(cr);
212                 //  .5 + .5 * .5 * sin(45deg),  1.5 - .5 * .5 * cos(45deg)
213                 cairo_arc (cr, x * 0.677, y * .677, r * .15, 0, 2 * M_PI);
214                 cairo_fill(cr);
215                 cairo_arc (cr, x * 1.323, y * .677, r * .15, 0, 2 * M_PI);
216                 cairo_fill(cr);
217
218                 // bottom notch
219                 cairo_arc (cr, x, y+r, r * .26, 1.05 * M_PI, 1.95 * M_PI);
220                 cairo_stroke(cr);
221         }
222         break;
223         case Gtkmm2ext::ArdourIcon::TransportStop:
224         {
225                 const int wh = std::min (width, height);
226                 cairo_rectangle (cr,
227                                 (width - wh) * .5 + wh * .25,
228                                 (height - wh) * .5 + wh * .25,
229                                 wh * .5, wh * .5);
230
231                 VECTORICONSTROKEFILL(0.8);
232         }
233         break;
234         case Gtkmm2ext::ArdourIcon::TransportPlay:
235         {
236                 const int wh = std::min (width, height) * .5;
237                 const double y = height * .5;
238                 const double x = width - wh;
239
240                 const float tri = ceil(.577 * wh); // 1/sqrt(3)
241
242                 cairo_move_to (cr,  x + wh * .5, y);
243                 cairo_line_to (cr,  x - wh * .5, y - tri);
244                 cairo_line_to (cr,  x - wh * .5, y + tri);
245                 cairo_close_path (cr);
246
247                 VECTORICONSTROKEFILL(0.8);
248         }
249         break;
250         case Gtkmm2ext::ArdourIcon::TransportPanic:
251         {
252                 const int wh = std::min (width, height) * .1;
253                 const double xc = width * .5;
254                 const double yh = height;
255                 cairo_rectangle (cr,
256                                 xc - wh, yh *.19,
257                                 wh * 2,  yh *.41);
258                 VECTORICONSTROKEFILL(0.8);
259
260                 cairo_arc (cr, xc, yh *.75, wh, 0, 2 * M_PI);
261                 VECTORICONSTROKEFILL(0.8);
262         }
263         break;
264         case Gtkmm2ext::ArdourIcon::TransportStart:
265         case Gtkmm2ext::ArdourIcon::TransportEnd:
266         case Gtkmm2ext::ArdourIcon::TransportRange:
267         {
268                 // small play triangle
269                 int wh = std::min (width, height);
270                 const double y = height * .5;
271                 const double x = width - wh * .5;
272                 wh *= .18;
273                 const float tri = ceil(.577 * wh * 2); // 1/sqrt(3)
274
275                 const float ln = std::min (width, height) * .07;
276
277                 if (icon == Gtkmm2ext::ArdourIcon::TransportStart || icon == Gtkmm2ext::ArdourIcon::TransportRange) {
278                         cairo_rectangle (cr,
279                                         x - wh - ln, y  - tri * 1.7,
280                                         ln * 2,  tri * 3.4);
281
282                         VECTORICONSTROKEFILL(1.0);
283                 }
284
285                 if (icon == Gtkmm2ext::ArdourIcon::TransportEnd || icon == Gtkmm2ext::ArdourIcon::TransportRange) {
286                         cairo_rectangle (cr,
287                                         x + wh - ln, y  - tri * 1.7,
288                                         ln * 2,  tri * 3.4);
289
290                         VECTORICONSTROKEFILL(1.0);
291                 }
292
293                 if (icon == Gtkmm2ext::ArdourIcon::TransportStart) {
294                         cairo_move_to (cr,  x - wh, y);
295                         cairo_line_to (cr,  x + wh, y - tri);
296                         cairo_line_to (cr,  x + wh, y + tri);
297                 } else {
298                         cairo_move_to (cr,  x + wh, y);
299                         cairo_line_to (cr,  x - wh, y - tri);
300                         cairo_line_to (cr,  x - wh, y + tri);
301                 }
302
303                 cairo_close_path (cr);
304                 VECTORICONSTROKEFILL(1.0);
305         }
306         break;
307         case Gtkmm2ext::ArdourIcon::TransportLoop:
308         {
309                 const double x = width * .5;
310                 const double y = height * .5;
311                 const double r = std::min(x, y);
312
313                 cairo_arc          (cr, x, y, r * .62, 0, 2 * M_PI);
314                 cairo_arc_negative (cr, x, y, r * .35, 2 * M_PI, 0);
315
316                 VECTORICONSTROKEFILL(1.0);
317 #define ARCARROW(rad, ang) \
318                 x + (rad) * sin((ang) * 2.0 * M_PI), y + (rad) * cos((ang) * 2.0 * M_PI)
319
320                 cairo_move_to (cr, ARCARROW(r * .35, .72));
321                 cairo_line_to (cr, ARCARROW(r * .15, .72));
322                 cairo_line_to (cr, ARCARROW(r * .56, .60));
323                 cairo_line_to (cr, ARCARROW(r * .75, .72));
324                 cairo_line_to (cr, ARCARROW(r * .62, .72));
325
326                 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
327                 cairo_stroke_preserve(cr);
328                 cairo_close_path (cr);
329                 cairo_set_source_rgba (cr, 1, 1, 1, 1.0);
330                 cairo_fill(cr);
331 #undef ARCARROW
332         }
333         break;
334         case Gtkmm2ext::ArdourIcon::TransportMetronom:
335         {
336                 const double x  = width * .5;
337                 const double y  = height * .5;
338                 const double wh = std::min(x, y);
339                 const double h  = wh * .85;
340                 const double w  = wh * .55;
341                 const double lw = w  * .34;
342
343                 cairo_rectangle (cr,
344                                 x - w * .7, y + h * .25,
345                                 w * 1.4, lw);
346
347                 VECTORICONSTROKEFILL(1.0);
348
349                 cairo_move_to (cr,  x - w,       y + h);
350                 cairo_line_to (cr,  x + w,       y + h);
351                 cairo_line_to (cr,  x + w * .35, y - h);
352                 cairo_line_to (cr,  x - w * .35, y - h);
353                 cairo_line_to (cr,  x - w,       y + h);
354
355                 cairo_move_to (cr,  x - w + lw,       y + h -lw);
356                 cairo_line_to (cr,  x - w * .35 + lw, y - h + lw);
357                 cairo_line_to (cr,  x + w * .35 - lw, y - h + lw);
358                 cairo_line_to (cr,  x + w - lw,       y + h -lw);
359                 cairo_line_to (cr,  x - w + lw,       y + h -lw);
360
361                 VECTORICONSTROKEFILL(1.0);
362
363                 // ddx = .70 w      = .75 * .5 wh              = .375 wh
364                 // ddy = .75 h - lw = .75 * .8 wh - wh .5 * .2 = .5 wh
365                 // ang = (ddx/ddy):
366                 // -> angle = atan (ang) = atan (375 / .5) ~= 36deg
367                 const double dx = lw * .2;  // 1 - cos(tan^-1(ang))
368                 const double dy = lw * .4;  // 1 - sin(tan^-1(ang))
369                 cairo_move_to (cr,  x - w * .3     , y + h * .25 + lw * .5);
370                 cairo_line_to (cr,  x - w + dx     , y - h + lw + dy);
371                 cairo_line_to (cr,  x - w + lw     , y - h + lw);
372                 cairo_line_to (cr,  x - w * .3 + lw, y + h * .25 + lw * .5);
373                 cairo_close_path (cr);
374
375                 VECTORICONSTROKEFILL(1.0);
376
377                 cairo_rectangle (cr,
378                                 x - w * .7, y + h * .25,
379                                 w * 1.4, lw);
380                 cairo_fill(cr);
381         }
382         break;
383         case Gtkmm2ext::ArdourIcon::NudgeLeft:
384         {
385                 const double x = width * .5;
386                 const double y = height * .5;
387                 const double wh = std::min (x, y);
388
389                 const double tri_x = .3 * wh;
390                 const double tri_y = .6 * wh;
391
392                 cairo_move_to (cr, x + tri_x, y - tri_y);
393                 cairo_line_to (cr, x - tri_x, y);
394                 cairo_line_to (cr, x + tri_x, y + tri_y);
395                 VECTORICONSTROKEOUTLINE();
396         }
397         break;
398         case Gtkmm2ext::ArdourIcon::NudgeRight:
399         {
400
401                 const double x = width * .5;
402                 const double y = height * .5;
403                 const double wh = std::min (x, y);
404
405                 const double tri_x = .3 * wh;
406                 const double tri_y = .6 * wh;
407
408                 cairo_move_to (cr, x - tri_x, y - tri_y);
409                 cairo_line_to (cr, x + tri_x, y);
410                 cairo_line_to (cr, x - tri_x, y + tri_y);
411                 VECTORICONSTROKEOUTLINE();
412
413         }
414         break;
415         default:
416                 return false;
417         } // end case(icon)
418
419 #undef VECTORICONSTROKEFILL
420 #undef VECTORICONSTROKEOUTLINE
421         return true;
422 }