1 /*
2 * Copyright (C) 2017-2019 Robin Gareus <robin@gareus.org>
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 as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include <math.h> // M_PI
20 #include <assert.h>
21 #include <algorithm> // std:min
22
23 #include "gtkmm2ext/colors.h"
24 #include "gtkmm2ext/rgb_macros.h"
25 #include "widgets/ardour_icon.h"
26
27 using namespace ArdourWidgets::ArdourIcon;
28
29 /* general style info:
30 *
31 * - geometry: icons should be centered, spanning
32 * wh = std::min (width * .5, height *.5) * .55;
33 *
34 * - all shapes should have a contrasting outline
35 * (usually white foreground, black outline)
36 */
37
38 #define DEFAULT_LINE_WIDTH ceil (std::min (width, height) * .035)
39
40 #define OUTLINEWIDTH 1.5 // px
41
42 #define VECTORICONSTROKEFILL(fillalpha) \
43 cairo_set_line_width (cr, OUTLINEWIDTH); \
44 cairo_set_source_rgba (cr, 0, 0, 0, 1.0); \
45 cairo_stroke_preserve (cr); \
46 cairo_set_source_rgba (cr, 1, 1, 1, (fillalpha)); \
47 cairo_fill (cr);
48
49 #define VECTORICONSTROKEOUTLINE(LW, color) \
50 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); \
51 cairo_set_line_width (cr, (LW) + OUTLINEWIDTH); \
52 ardour_icon_set_source_inv_rgba (cr, color); \
53 cairo_stroke_preserve (cr); \
54 Gtkmm2ext::set_source_rgba (cr, color); \
55 cairo_set_line_width (cr, (LW)); \
56 cairo_stroke (cr);
57
58 #define VECTORICONSTROKE(LW, color) \
59 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); \
60 Gtkmm2ext::set_source_rgba (cr, color); \
61 cairo_set_line_width (cr, (LW)); \
62 cairo_stroke (cr);
63
64
65 /** inverse color */
ardour_icon_set_source_inv_rgba(cairo_t * cr,uint32_t color)66 static void ardour_icon_set_source_inv_rgba (cairo_t *cr, uint32_t color)
67 {
68 cairo_set_source_rgba (cr,
69 1.0 - ((color >> 24) & 0xff) / 255.0,
70 1.0 - ((color >> 16) & 0xff) / 255.0,
71 1.0 - ((color >> 8) & 0xff) / 255.0,
72 ((color >> 0) & 0xff) / 255.0
73 );
74 }
75
76 /*****************************************************************************
77 * Tool Icons.
78 * Foreground is always white, compatible with small un-blurred rendering.
79 */
80
81 /** internal edit icon */
icon_tool_content(cairo_t * cr,const int width,const int height)82 static void icon_tool_content (cairo_t *cr, const int width, const int height) {
83 #define EM_POINT(X,Y) round (x + (X) * em) + .5, round (y + (Y) * em) + .5
84
85 const double x = width * .5;
86 const double y = height * .5;
87 const double em = std::min (x, y) * .1; // 1px at 20x20
88
89 // draw dot outlines (control-points)
90 cairo_move_to (cr, EM_POINT(-6.0, 0.0));
91 cairo_close_path (cr);
92 cairo_move_to (cr, EM_POINT(-2.5, 4.0));
93 cairo_close_path (cr);
94 cairo_move_to (cr, EM_POINT( 5.0, -5.0));
95 cairo_close_path (cr);
96
97 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
98 ardour_icon_set_source_inv_rgba (cr, 0xffffffff);
99 cairo_set_line_width (cr, 3 * em + OUTLINEWIDTH);
100 cairo_stroke (cr);
101
102 // "midi note" lines
103 cairo_move_to (cr, EM_POINT(-7.0, -5.0));
104 cairo_line_to (cr, EM_POINT( 0.0, -5.0));
105
106 cairo_move_to (cr, EM_POINT( 2.0, 4.0));
107 cairo_line_to (cr, EM_POINT( 6.0, 4.0));
108
109 // automation line (connect control-points)
110 cairo_move_to (cr, EM_POINT(-6.0, 0.0));
111 cairo_line_to (cr, EM_POINT(-2.5, 4.0));
112 cairo_line_to (cr, EM_POINT( 5.0, -5.0));
113
114 cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
115 VECTORICONSTROKEOUTLINE(1 * em, 0xffffffff);
116
117 // remove automation line outline at control-points
118 cairo_move_to (cr, EM_POINT(-6.0, 0.0));
119 cairo_close_path (cr);
120 cairo_move_to (cr, EM_POINT(-2.5, 4.0));
121 cairo_close_path (cr);
122 cairo_move_to (cr, EM_POINT( 5.0, -5.0));
123 cairo_close_path (cr);
124
125 Gtkmm2ext::set_source_rgba (cr, 0xffffffff);
126 cairo_set_line_width (cr, 3 * em);
127 cairo_stroke (cr);
128 #undef EM_POINT
129 }
130
131 /** range tool |<->| */
icon_tool_range(cairo_t * cr,const int width,const int height)132 static void icon_tool_range (cairo_t *cr, const int width, const int height)
133 {
134 const double x = width * .5;
135 const double y = height * .5;
136 const double wh = std::min (x, y) * .55;
137 const double ar = wh * .6; // arrow
138
139 const double bw = ceil (wh) - .5;
140 const double y0 = ceil (y);
141 const double ym = rint (y0 - wh * .1) + .5; // arrow-horizontal; slightly to the top, on a px
142 const double x0 = rint (x) - bw; // left arrow tip
143 const double x1 = rint (x) + bw; // right arrow tip
144
145 // left and right box
146 cairo_move_to (cr, x0, y0 - bw);
147 cairo_line_to (cr, x0, y0 + bw);
148 cairo_move_to (cr, x1, y0 - bw);
149 cairo_line_to (cr, x1, y0 + bw);
150
151 // arrows
152 cairo_move_to (cr, x0 + ar, ym - ar);
153 cairo_line_to (cr, x0 + .5, ym);
154 cairo_line_to (cr, x0 + ar, ym + ar);
155
156 cairo_move_to (cr, x1 - ar, ym - ar);
157 cairo_line_to (cr, x1 - .5, ym);
158 cairo_line_to (cr, x1 - ar, ym + ar);
159
160 // line connecting the arrows
161 cairo_move_to (cr, x0, ym);
162 cairo_line_to (cr, x1, ym);
163 VECTORICONSTROKEOUTLINE(DEFAULT_LINE_WIDTH, 0xffffffff);
164 }
165
166 /** Grab/Object tool - 6x8em "hand", with 'em' wide index finger. */
icon_tool_grab(cairo_t * cr,const int width,const int height)167 static void icon_tool_grab (cairo_t *cr, const int width, const int height)
168 {
169 const double x = width * .5;
170 const double y = height * .5;
171 const double em = std::min (x, y) * .15; // 1.5px at 20x20
172
173 #define EM_POINT(X,Y) x + (X) * em, y + (Y) * em
174
175 // wrist
176 cairo_move_to (cr, EM_POINT( 2.0, 4.0));
177 cairo_line_to (cr, EM_POINT(-1.5, 4.0));
178 cairo_line_to (cr, EM_POINT(-2.5, 2.0));
179 // thumb
180 cairo_line_to (cr, EM_POINT(-3.0, 1.0));
181
182 // index finger
183 cairo_line_to (cr, EM_POINT(-2.0, 0.0));
184 cairo_line_to (cr, EM_POINT(-2.1, -4.0));
185 cairo_line_to (cr, EM_POINT(-1.5, -4.5));
186 cairo_line_to (cr, EM_POINT(-1.1, -4.0));
187 cairo_line_to (cr, EM_POINT(-1.0, 0.1));
188
189 // middle finger knuckle
190 cairo_line_to (cr, EM_POINT(-0.6, 0.3));
191 cairo_line_to (cr, EM_POINT(-0.3, 0.0));
192 cairo_line_to (cr, EM_POINT(-0.2, -0.2));
193 cairo_line_to (cr, EM_POINT( 0.1, -0.3));
194 cairo_line_to (cr, EM_POINT( 0.4, -0.2));
195 cairo_line_to (cr, EM_POINT( 0.5, 0.1));
196
197 // ring finger knuckle
198 cairo_line_to (cr, EM_POINT( 0.8, 0.4));
199 cairo_line_to (cr, EM_POINT( 1.1, 0.2));
200 cairo_line_to (cr, EM_POINT( 1.2, 0.0));
201 cairo_line_to (cr, EM_POINT( 1.5, -0.1));
202 cairo_line_to (cr, EM_POINT( 1.8, 0.0));
203 cairo_line_to (cr, EM_POINT( 1.9, 0.4));
204
205 // pinky
206 cairo_line_to (cr, EM_POINT( 2.0, 0.6));
207 cairo_line_to (cr, EM_POINT( 2.4, 0.4));
208 cairo_line_to (cr, EM_POINT( 2.8, 0.5));
209 cairo_line_to (cr, EM_POINT( 3.0, 1.0));
210
211 // wrist
212 cairo_line_to (cr, EM_POINT( 3.0, 1.5));
213 cairo_line_to (cr, EM_POINT( 2.0, 4.0));
214
215 cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
216 cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
217 VECTORICONSTROKEFILL(1.0);
218 #undef EM_POINT
219 }
220
221 /** cut icon - scissors */
icon_tool_cut(cairo_t * cr,const int width,const int height)222 static void icon_tool_cut (cairo_t *cr, const int width, const int height)
223 {
224 const double x = width * .5;
225 const double y = height * .5;
226 const double em = std::min (x, y) * .1; // 1px at 20x20
227
228 #define EM_POINT(X,Y) x + (X) * em, y + (Y) * em
229
230 cairo_save (cr);
231 cairo_translate (cr, EM_POINT(4, -3));
232 cairo_scale (cr, 1.6, 1.0); // ellipse
233 cairo_arc (cr, 0., 0., 1.5 * em, 0., 2 * M_PI);
234 cairo_restore (cr);
235
236 cairo_move_to (cr, EM_POINT(-6.0, 2.5));
237 cairo_line_to (cr, EM_POINT( 5.5, -2.0));
238
239 cairo_move_to (cr, EM_POINT(-6.0, -2.5));
240 cairo_line_to (cr, EM_POINT( 5.5, 2.0));
241
242 cairo_save (cr);
243 cairo_translate (cr, EM_POINT(4, 3));
244 cairo_scale (cr, 1.6, 1.0); // ellipse
245 cairo_arc (cr, 0., 0., 1.5 * em, 0., 2 * M_PI);
246 cairo_restore (cr);
247
248 cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
249 cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
250
251 VECTORICONSTROKEOUTLINE (1.5 * em, 0xffffffff);
252 #undef EM_POINT
253 }
254
255 /** time stretch icon */
icon_tool_stretch(cairo_t * cr,const int width,const int height)256 static void icon_tool_stretch (cairo_t *cr, const int width, const int height)
257 {
258 const double x = width * .5;
259 const double y = height * .5;
260 const double wh = std::min (x, y) * .55;
261
262 const double y0 = ceil (y);
263 const double bw = rint (wh);
264 const double lw = rint (wh / 3.0) / 2.0;
265 const double x0 = rint (x + lw) + .5;
266
267 // box indication region
268 cairo_rectangle (cr, x0 - lw - bw - .5, y0 - bw, lw + bw, 2 * bw);
269 VECTORICONSTROKEFILL (0.75);
270
271 cairo_set_line_width (cr, 1.0);
272
273 // inside/left arrow
274 cairo_move_to (cr, x0, y);
275 cairo_line_to (cr, x0 - lw * 2, y);
276 cairo_line_to (cr, x0 - lw * 2, y - lw * 3.5);
277 cairo_line_to (cr, x0 - lw * 6, y);
278 cairo_line_to (cr, x0 - lw * 2, y + lw * 3.5);
279 cairo_line_to (cr, x0 - lw * 2, y);
280
281 cairo_set_source_rgba (cr, 0, 0, 0, .5);
282 cairo_stroke_preserve (cr);
283 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
284 cairo_fill (cr);
285
286 // outside/right arrow
287 cairo_move_to (cr, x0, y);
288 cairo_line_to (cr, x0 + lw * 2, y);
289 cairo_line_to (cr, x0 + lw * 2, y - lw * 4);
290 cairo_line_to (cr, x0 + lw * 6, y);
291 cairo_line_to (cr, x0 + lw * 2, y + lw * 4);
292 cairo_line_to (cr, x0 + lw * 2, y);
293
294 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
295 cairo_stroke_preserve (cr);
296 cairo_set_source_rgba (cr, 1, 1, 1, 1.0);
297 cairo_fill (cr);
298 }
299
300 /** audition - small speaker with sound-waves*/
icon_tool_audition(cairo_t * cr,const int width,const int height)301 static void icon_tool_audition (cairo_t *cr, const int width, const int height)
302 {
303 const double x = width * .5;
304 const double y = height * .5;
305 const double em = std::min (x, y) * .1; // 1px at 20x20
306
307 #define EM_POINT(X,Y) x + (X) * em, y + (Y) * em
308
309 cairo_move_to (cr, EM_POINT(-7.0, -2.0));
310 cairo_line_to (cr, EM_POINT(-7.0, 2.0));
311 cairo_line_to (cr, EM_POINT(-6.0, 3.0));
312 cairo_line_to (cr, EM_POINT(-3.0, 3.0));
313 cairo_line_to (cr, EM_POINT( 2.0, 6.0));
314 cairo_line_to (cr, EM_POINT( 2.0, -6.0));
315 cairo_line_to (cr, EM_POINT(-3.0, -3.0));
316 cairo_line_to (cr, EM_POINT(-6.0, -3.0));
317 cairo_close_path (cr);
318
319 cairo_pattern_t *speaker;
320 speaker = cairo_pattern_create_linear (EM_POINT(0, -3.0), EM_POINT(0, 3.0));
321 cairo_pattern_add_color_stop_rgba (speaker, 0.0, 0.8, 0.8, 0.8, 1.0);
322 cairo_pattern_add_color_stop_rgba (speaker, 0.25, 1.0, 1.0, 1.0, 1.0);
323 cairo_pattern_add_color_stop_rgba (speaker, 1.0, 0.6, 0.6, 0.6, 1.0);
324
325 cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
326 cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
327 cairo_set_line_width (cr, 1.5);
328 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
329 cairo_stroke_preserve (cr);
330 cairo_set_source (cr, speaker);
331 cairo_fill (cr);
332 cairo_pattern_destroy (speaker);
333
334 // TODO use a slight curve
335 cairo_move_to (cr, EM_POINT(-3.0, -3.0));
336 cairo_line_to (cr, EM_POINT(-3.5, 0.0));
337 cairo_line_to (cr, EM_POINT(-3.0, 3.0));
338 cairo_set_source_rgba (cr, 0, 0, 0, 0.7);
339 cairo_set_line_width (cr, 1.0);
340 cairo_stroke (cr);
341
342 cairo_save (cr);
343 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
344 cairo_set_source_rgba (cr, 1, 1, 1, 1);
345
346 cairo_translate (cr, EM_POINT (4.0, 0));
347 cairo_scale (cr, 0.8, 1.25); // ellipse
348
349 cairo_arc (cr, 0, 0, 4 * em, -.5 * M_PI, .5 * M_PI);
350 cairo_set_line_width (cr, .8 * em);
351 cairo_stroke (cr);
352
353 cairo_arc (cr, 0, 0, 2 * em, -.5 * M_PI, .5 * M_PI);
354 cairo_set_line_width (cr, .5 * em);
355 cairo_stroke (cr);
356 cairo_restore (cr);
357 #undef EM_POINT
358 }
359
360 /** pen top-left to bottom right */
icon_tool_draw(cairo_t * cr,const int width,const int height)361 static void icon_tool_draw (cairo_t *cr, const int width, const int height)
362 {
363 const double x = width * .5;
364 const double y = height * .5;
365 const double em = std::min (x, y) * .1; // 1px at 20x20
366
367 #define EM_POINT(X,Y) x + (X) * em, y + (Y) * em
368
369 // pen [6,-5] to [-3, 3]
370 // y = -8 * x / 9 + 1/3
371
372 // top-right end
373 cairo_move_to (cr, EM_POINT( 5.0, -6.11));
374 cairo_line_to (cr, EM_POINT( 6.4, -5.35)); // todo round properly.
375 cairo_line_to (cr, EM_POINT( 7.0, -3.88));
376
377 // bottom-left w/tip
378 cairo_line_to (cr, EM_POINT(-2.0, 4.11));
379 cairo_line_to (cr, EM_POINT(-6.0, 5.66)); // pen tip
380 cairo_line_to (cr, EM_POINT(-4.0, 1.88));
381 cairo_close_path (cr);
382
383 cairo_pattern_t *pen;
384 pen = cairo_pattern_create_linear (EM_POINT(-3.0, -6.0), EM_POINT(6.0, 4.0));
385 cairo_pattern_add_color_stop_rgba (pen, 0.4, 0.6, 0.6, 0.6, 1.0);
386 cairo_pattern_add_color_stop_rgba (pen, 0.5, 1.0, 1.0, 1.0, 1.0);
387 cairo_pattern_add_color_stop_rgba (pen, 0.6, 0.1, 0.1, 0.1, 1.0);
388
389 cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
390 cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
391 cairo_set_line_width (cr, em + .5);
392 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
393 cairo_stroke_preserve (cr);
394 cairo_set_source (cr, pen);
395 cairo_fill (cr);
396
397 // separate the tip
398 cairo_move_to (cr, EM_POINT(-2.0, 4.11));
399 cairo_line_to (cr, EM_POINT(-3.0, 2.8)); // slight curve [-3,3]
400 cairo_line_to (cr, EM_POINT(-4.0, 2.0));
401 cairo_set_line_width (cr, OUTLINEWIDTH);
402 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
403 cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
404 cairo_stroke (cr);
405
406 // pen tip
407 cairo_move_to (cr, EM_POINT(-5.0, 3.9));
408 cairo_line_to (cr, EM_POINT(-6.0, 5.66));
409 cairo_line_to (cr, EM_POINT(-4.1, 4.9));
410 cairo_close_path (cr);
411 cairo_set_source_rgba (cr, 0, 0, 0, 0.7);
412 cairo_set_line_width (cr, em);
413 cairo_stroke_preserve (cr);
414 cairo_fill (cr);
415
416 cairo_pattern_destroy (pen);
417 #undef EM_POINT
418 }
419
420 /** Toolbar icon - Time Axis View reduce height */
icon_tav_shrink(cairo_t * cr,const int width,const int height)421 static void icon_tav_shrink (cairo_t *cr, const int width, const int height)
422 {
423 const double x = width * .5;
424 const double y = height * .5;
425 const double wh = std::min (x, y) * .66;
426 const double ar = std::min (x, y) * .15;
427 const double tri = .7 * (wh - ar);
428
429 cairo_rectangle (cr, x - wh, y - ar, 2 * wh, 2 * ar);
430 VECTORICONSTROKEFILL(.75);
431
432 cairo_set_line_width (cr, 1.0);
433
434 cairo_move_to (cr, x, y - ar - 0.5);
435 cairo_line_to (cr, x - tri, y - wh + 0.5);
436 cairo_line_to (cr, x + tri, y - wh + 0.5);
437 cairo_close_path (cr);
438
439 cairo_set_source_rgba (cr, 1, 1, 1, .75);
440 cairo_stroke_preserve (cr);
441 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
442 cairo_fill (cr);
443
444 cairo_move_to (cr, x, y + ar + 0.5);
445 cairo_line_to (cr, x - tri, y + wh - 0.5);
446 cairo_line_to (cr, x + tri, y + wh - 0.5);
447 cairo_close_path (cr);
448
449 cairo_set_source_rgba (cr, 1, 1, 1, .75);
450 cairo_stroke_preserve (cr);
451 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
452 cairo_fill (cr);
453 }
454
455 /** Toolbar icon - Time Axis View increase height */
icon_tav_expand(cairo_t * cr,const int width,const int height)456 static void icon_tav_expand (cairo_t *cr, const int width, const int height)
457 {
458 const double x = width * .5;
459 const double y = height * .5;
460 const double wh = std::min (x, y) * .66;
461 const double ar = std::min (x, y) * .15;
462 const double tri = .7 * (wh - ar);
463
464 cairo_rectangle (cr, x - wh, y - wh, 2 * wh, 2 * wh);
465 VECTORICONSTROKEFILL(.75);
466
467 cairo_set_line_width (cr, 1.0);
468
469 cairo_move_to (cr, x, y - wh + 0.5);
470 cairo_line_to (cr, x - tri, y - ar - 0.5);
471 cairo_line_to (cr, x + tri, y - ar - 0.5);
472 cairo_close_path (cr);
473
474 cairo_set_source_rgba (cr, 1, 1, 1, .5);
475 cairo_stroke_preserve (cr);
476 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
477 cairo_fill (cr);
478
479 cairo_move_to (cr, x , y + wh - 0.5);
480 cairo_line_to (cr, x - tri, y + ar + 0.5);
481 cairo_line_to (cr, x + tri, y + ar + 0.5);
482 cairo_close_path (cr);
483
484 cairo_set_source_rgba (cr, 1, 1, 1, .5);
485 cairo_stroke_preserve (cr);
486 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
487 cairo_fill (cr);
488 }
489
490 /*****************************************************************************
491 * Record enable (transport & track header).
492 *
493 * hardcoded "red" #f46f6f
494 */
495
496 /** standard rec-enable circle */
icon_rec_enable(cairo_t * cr,const int width,const int height,const Gtkmm2ext::ActiveState state)497 static void icon_rec_enable (cairo_t *cr, const int width, const int height, const Gtkmm2ext::ActiveState state)
498 {
499 const double x = width * .5;
500 const double y = height * .5;
501 const double r = std::min (x, y) * .55;
502 cairo_arc (cr, x, y, r, 0, 2 * M_PI);
503 if (state == Gtkmm2ext::ExplicitActive) {
504 cairo_set_source_rgba (cr, 1.0, .1, .1, 1.0);
505 }
506 else if (state == Gtkmm2ext::ImplicitActive) {
507 cairo_set_source_rgba (cr, .9, .3, .3, 1.0);
508 }
509 else {
510 cairo_set_source_rgba (cr, .4, .3, .3, 1.0);
511 }
512 cairo_fill_preserve (cr);
513 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.8); // outline
514 cairo_set_line_width (cr, 1);
515 cairo_stroke (cr);
516 }
517
518 /*****************************************************************************
519 * Transport buttons, foreground is always white
520 */
521
522 /** stop square box */
icon_transport_stop(cairo_t * cr,const int width,const int height)523 static void icon_transport_stop (cairo_t *cr, const int width, const int height)
524 {
525 const int wh = std::min (width, height);
526 cairo_rectangle (cr,
527 (width - wh) * .5 + wh * .225,
528 (height - wh) * .5 + wh * .225,
529 wh * .55, wh * .55);
530 VECTORICONSTROKEFILL(0.9); // small 'shine'
531 }
532
533 /** play triangle */
icon_transport_play(cairo_t * cr,const int width,const int height)534 static void icon_transport_play (cairo_t *cr, const int width, const int height)
535 {
536 const int wh = std::min (width, height) * .5;
537 const double y = height * .5;
538 const double x = width * .5;
539
540 const double tri = ceil (.577 * wh); // 1/sqrt(3)
541
542 cairo_move_to (cr, x + wh * .5, y);
543 cairo_line_to (cr, x - wh * .5, y - tri);
544 cairo_line_to (cr, x - wh * .5, y + tri);
545 cairo_close_path (cr);
546
547 VECTORICONSTROKEFILL(0.9);
548 }
549
550 /** Midi Panic "!" */
icon_transport_panic(cairo_t * cr,const int width,const int height)551 static void icon_transport_panic (cairo_t *cr, const int width, const int height)
552 {
553 const int wh = ceil (std::min (width, height) * .1) - .5;
554 const double xc = rint (width * .5);
555 const double yh = std::min (width, height);
556 const double y0 = (height - yh) * .5;
557 cairo_rectangle (cr,
558 xc - wh, y0 + yh *.12,
559 wh * 2, yh *.48);
560 VECTORICONSTROKEFILL(0.9);
561
562 cairo_arc (cr, xc, y0 + yh *.78, wh, 0, 2 * M_PI);
563 VECTORICONSTROKEFILL(0.9);
564 }
565
566 /** various combinations of lines and triangles "|>|", ">|" "|>" */
icon_transport_ck(cairo_t * cr,const enum ArdourWidgets::ArdourIcon::Icon icon,const int width,const int height)567 static void icon_transport_ck (cairo_t *cr,
568 const enum ArdourWidgets::ArdourIcon::Icon icon,
569 const int width, const int height)
570 {
571 // small play triangle
572 int wh = std::min (width, height);
573 const double y = height * .5;
574 const double x = width * .5;
575 wh *= .18;
576 const double tri = ceil (.577 * wh * 2); // 1/sqrt(3)
577
578 const float ln = std::min (width, height) * .07;
579
580 if (icon == TransportStart || icon == TransportRange) {
581 cairo_rectangle (cr,
582 x - wh - ln, y - tri * 1.7,
583 ln * 2, tri * 3.4);
584
585 VECTORICONSTROKEFILL(1.0);
586 }
587
588 if (icon == TransportEnd || icon == TransportRange) {
589 cairo_rectangle (cr,
590 x + wh - ln, y - tri * 1.7,
591 ln * 2, tri * 3.4);
592
593 VECTORICONSTROKEFILL(1.0);
594 }
595
596 if (icon == TransportStart) {
597 cairo_move_to (cr, x - wh, y);
598 cairo_line_to (cr, x + wh, y - tri);
599 cairo_line_to (cr, x + wh, y + tri);
600 } else {
601 cairo_move_to (cr, x + wh, y);
602 cairo_line_to (cr, x - wh, y - tri);
603 cairo_line_to (cr, x - wh, y + tri);
604 }
605
606 cairo_close_path (cr);
607 VECTORICONSTROKEFILL(1.0);
608 }
609
610 /** loop spiral */
icon_transport_loop(cairo_t * cr,const int width,const int height)611 static void icon_transport_loop (cairo_t *cr, const int width, const int height)
612 {
613 const double x = width * .5;
614 const double y = height * .5;
615 const double r = std::min (x, y);
616
617 cairo_arc (cr, x, y, r * .58, 0, 2 * M_PI);
618 cairo_arc_negative (cr, x, y, r * .30, 2 * M_PI, 0);
619
620 VECTORICONSTROKEFILL (1.0);
621
622 #define ARCARROW(rad, ang) \
623 x + (rad) * sin ((ang) * 2.0 * M_PI), y + (rad) * cos ((ang) * 2.0 * M_PI)
624
625 cairo_move_to (cr, ARCARROW(r * .30, .72));
626 cairo_line_to (cr, ARCARROW(r * .11, .72));
627 cairo_line_to (cr, ARCARROW(r * .55, .60));
628 cairo_line_to (cr, ARCARROW(r * .74, .72));
629 cairo_line_to (cr, ARCARROW(r * .58, .72));
630
631 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
632 cairo_stroke_preserve (cr);
633 cairo_close_path (cr);
634 cairo_set_source_rgba (cr, 1, 1, 1, 1.0);
635 cairo_fill (cr);
636 #undef ARCARROW
637 }
638
639 /** de-construct thorwil's metronom */
icon_transport_metronom(cairo_t * cr,const int width,const int height)640 static void icon_transport_metronom (cairo_t *cr, const int width, const int height)
641 {
642 const double x = width * .5;
643 const double y = height * .5;
644 const double wh = .95 * std::min (x, y);
645 const double h = wh * .80;
646 const double w = wh * .55;
647 const double lw = w * .34;
648
649 cairo_rectangle (cr,
650 x - w * .7, y + h * .25,
651 w * 1.4, lw);
652
653 VECTORICONSTROKEFILL(1.0);
654
655 cairo_move_to (cr, x - w, y + h);
656 cairo_line_to (cr, x + w, y + h);
657 cairo_line_to (cr, x + w * .35, y - h);
658 cairo_line_to (cr, x - w * .35, y - h);
659 cairo_line_to (cr, x - w, y + h);
660
661 cairo_move_to (cr, x - w + lw, y + h -lw);
662 cairo_line_to (cr, x - w * .35 + lw, y - h + lw);
663 cairo_line_to (cr, x + w * .35 - lw, y - h + lw);
664 cairo_line_to (cr, x + w - lw, y + h -lw);
665 cairo_line_to (cr, x - w + lw, y + h -lw);
666
667 VECTORICONSTROKEFILL(1.0);
668
669 // Pendulum
670 // ddx = .70 w = .75 * .5 wh = .375 wh
671 // ddy = .75 h - lw = .75 * .8 wh - wh .5 * .2 = .5 wh
672 // ang = (ddx/ddy):
673 // -> angle = atan (ang) = atan (375 / .5) ~= 36deg
674 const double dx = lw * .2; // 1 - cos(tan^-1(ang))
675 const double dy = lw * .4; // 1 - sin(tan^-1(ang))
676 cairo_move_to (cr, x - w * .3 , y + h * .25 + lw * .5);
677 cairo_line_to (cr, x - w + dx , y - h + lw + dy);
678 cairo_line_to (cr, x - w + lw , y - h + lw);
679 cairo_line_to (cr, x - w * .3 + lw, y + h * .25 + lw * .5);
680 cairo_close_path (cr);
681
682 VECTORICONSTROKEFILL(1.0);
683
684 cairo_rectangle (cr,
685 x - w * .7, y + h * .25,
686 w * 1.4, lw);
687 cairo_fill (cr);
688 }
689
690 /*****************************************************************************
691 * Zoom: In "+", Out "-" and Full "[]"
692 */
icon_zoom(cairo_t * cr,const enum ArdourWidgets::ArdourIcon::Icon icon,const int width,const int height,const uint32_t fg_color)693 static void icon_zoom (cairo_t *cr, const enum ArdourWidgets::ArdourIcon::Icon icon, const int width, const int height, const uint32_t fg_color)
694 {
695 const double x = width * .5;
696 const double y = height * .5;
697 const double r = std::min (x, y) * .7;
698 const double wh = std::min (x, y) * .45;
699
700 // draw handle first
701 #define LINE45DEG(rad) \
702 x + r * (rad) * .707, y + r * (rad) * .707 // sin(45deg) = cos(45deg) = .707
703 cairo_move_to (cr, LINE45DEG(.9));
704 cairo_line_to (cr, LINE45DEG(1.3));
705 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
706 cairo_set_line_width (cr, 3.0);
707 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
708 cairo_stroke (cr);
709 #undef LINE45DEG
710
711 // lens
712 Gtkmm2ext::set_source_rgba (cr, fg_color);
713 cairo_arc (cr, x, y, r, 0, 2 * M_PI);
714 cairo_fill_preserve (cr);
715
716 // add a lens gradient
717 cairo_pattern_t *lens;
718 lens = cairo_pattern_create_radial (x - r, y - r, r * .5, x - r, y - r, r * 2);
719 cairo_pattern_add_color_stop_rgba (lens, 0, 1, 1, 1, .4);
720 cairo_pattern_add_color_stop_rgba (lens, 1, 0, 0, 0, .4);
721 cairo_set_source (cr, lens);
722 cairo_fill_preserve (cr);
723 cairo_pattern_destroy (lens);
724
725 // outline
726 cairo_set_line_width (cr, 1.5);
727 //ardour_icon_set_source_inv_rgba (cr, fg_color); // alpha
728 cairo_set_source_rgba (cr, .0, .0, .0, .8);
729 cairo_stroke (cr);
730
731 // add "+", "-" or "[]"
732 cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
733 cairo_set_line_width (cr, .5 + DEFAULT_LINE_WIDTH);
734 ardour_icon_set_source_inv_rgba (cr, fg_color);
735
736 if (icon == ZoomIn || icon == ZoomOut) {
737 cairo_move_to (cr, x - wh, y);
738 cairo_line_to (cr, x + wh, y);
739 cairo_stroke (cr);
740 }
741 if (icon == ZoomIn) {
742 cairo_move_to (cr, x, y - wh);
743 cairo_line_to (cr, x, y + wh);
744 cairo_stroke (cr);
745 }
746 if (icon == ZoomFull) {
747 const double br0 = std::min (x, y) * .1;
748 const double br1 = std::min (x, y) * .3;
749 const double bry = std::min (x, y) * .3;
750 cairo_move_to (cr, x - br0, y - bry);
751 cairo_line_to (cr, x - br1, y - bry);
752 cairo_line_to (cr, x - br1, y + bry);
753 cairo_line_to (cr, x - br0, y + bry);
754 cairo_stroke (cr);
755
756 cairo_move_to (cr, x + br0, y - bry);
757 cairo_line_to (cr, x + br1, y - bry);
758 cairo_line_to (cr, x + br1, y + bry);
759 cairo_line_to (cr, x + br0, y + bry);
760 cairo_stroke (cr);
761 }
762 }
763
764 /** Toolbar icon - Mixbus Zoom Expand, rotated TimeAxisExpand */
icon_zoom_expand(cairo_t * cr,const int width,const int height)765 static void icon_zoom_expand (cairo_t *cr, const int width, const int height)
766 {
767 const double x = width * .5;
768 const double y = height * .5;
769 const double wh = std::min (x, y) * .66;
770 const double ar = std::min (x, y) * .15;
771 const double tri = .7 * (wh - ar);
772
773 cairo_rectangle (cr, x - wh, y - wh, 2 * wh, 2 * wh);
774 VECTORICONSTROKEFILL(.75);
775
776 cairo_set_line_width (cr, 1.0);
777
778 cairo_move_to (cr, x - wh + 0.5, y);
779 cairo_line_to (cr, x - ar - 0.5, y - tri);
780 cairo_line_to (cr, x - ar - 0.5, y + tri);
781 cairo_close_path (cr);
782
783 cairo_set_source_rgba (cr, 1, 1, 1, .5);
784 cairo_stroke_preserve (cr);
785 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
786 cairo_fill (cr);
787
788 cairo_move_to (cr, x + wh - 0.5, y);
789 cairo_line_to (cr, x + ar + 0.5, y - tri);
790 cairo_line_to (cr, x + ar + 0.5, y + tri);
791 cairo_close_path (cr);
792
793 cairo_set_source_rgba (cr, 1, 1, 1, .5);
794 cairo_stroke_preserve (cr);
795 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
796 cairo_fill (cr);
797 }
798
799 /*****************************************************************************
800 * Misc buttons
801 */
802
803 /** "close" - "X" , no outline */
icon_close_cross(cairo_t * cr,const int width,const int height,const uint32_t fg_color)804 static void icon_close_cross (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
805 {
806 const double x = width * .5;
807 const double y = height * .5;
808 const double o = .5 + std::min (x, y) * .4;
809 Gtkmm2ext::set_source_rgba (cr, fg_color);
810 cairo_set_line_width (cr, DEFAULT_LINE_WIDTH);
811 cairo_move_to (cr, x-o, y-o);
812 cairo_line_to (cr, x+o, y+o);
813 cairo_move_to (cr, x+o, y-o);
814 cairo_line_to (cr, x-o, y+o);
815 cairo_stroke (cr);
816 }
817
818 /** "hide" strike through eye */
icon_hide_eye(cairo_t * cr,const int width,const int height,const uint32_t fg_color)819 static void icon_hide_eye (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
820 {
821 const double x = width * .5;
822 const double y = height * .5;
823 const double wh = std::min (x, y);
824
825 const double r = .2 * wh;
826 const double o = .60 * wh;
827 const double dx = .75 * wh;
828 const double dy = .65 * wh;
829
830 cairo_move_to (cr, x - dx, y);
831 cairo_curve_to (cr, x, y + dy, x, y + dy, x + dx, y);
832 cairo_curve_to (cr, x, y - dy, x, y - dy, x - dx, y);
833 VECTORICONSTROKE (DEFAULT_LINE_WIDTH, fg_color);
834
835 cairo_arc (cr, x, y, r, 0, 2 * M_PI);
836 //cairo_fill (cr);
837 VECTORICONSTROKE (DEFAULT_LINE_WIDTH, fg_color);
838
839 cairo_move_to (cr, x - o, y + o);
840 cairo_line_to (cr, x + o, y - o);
841 VECTORICONSTROKEOUTLINE (DEFAULT_LINE_WIDTH, fg_color);
842 }
843
844 /** slim "<" */
icon_scroll_left(cairo_t * cr,const int width,const int height,const uint32_t fg_color)845 static void icon_scroll_left (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
846 {
847 const double x = width * .5;
848 const double y = height * .5;
849 const double wh = std::min (x, y);
850
851 const double tri1 = .2 * wh;
852 const double tri2 = .4 * wh;
853
854 cairo_move_to (cr, x + tri1, y - tri2);
855 cairo_line_to (cr, x - tri2, y);
856 cairo_line_to (cr, x + tri1, y + tri2);
857 VECTORICONSTROKE (DEFAULT_LINE_WIDTH, fg_color);
858 }
859
860 /** slim ">" */
icon_scroll_right(cairo_t * cr,const int width,const int height,const uint32_t fg_color)861 static void icon_scroll_right (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
862 {
863
864 const double x = width * .5;
865 const double y = height * .5;
866 const double wh = std::min (x, y);
867
868 const double tri1 = .2 * wh;
869 const double tri2 = .4 * wh;
870
871 cairo_move_to (cr, x - tri1, y - tri2);
872 cairo_line_to (cr, x + tri2, y);
873 cairo_line_to (cr, x - tri1, y + tri2);
874 VECTORICONSTROKE (DEFAULT_LINE_WIDTH, fg_color);
875 }
876
877 /** "<" */
icon_nudge_left(cairo_t * cr,const int width,const int height,const uint32_t fg_color)878 static void icon_nudge_left (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
879 {
880 const double x = width * .5;
881 const double y = height * .5;
882 const double wh = std::min (x, y);
883
884 const double tri_x = .3 * wh;
885 const double tri_y = .6 * wh;
886
887 cairo_move_to (cr, x + tri_x, y - tri_y);
888 cairo_line_to (cr, x - tri_x, y);
889 cairo_line_to (cr, x + tri_x, y + tri_y);
890 VECTORICONSTROKEOUTLINE(.5 + DEFAULT_LINE_WIDTH, fg_color);
891 }
892
893 /** ">" */
icon_nudge_right(cairo_t * cr,const int width,const int height,const uint32_t fg_color)894 static void icon_nudge_right (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
895 {
896
897 const double x = width * .5;
898 const double y = height * .5;
899 const double wh = std::min (x, y);
900
901 const double tri_x = .3 * wh;
902 const double tri_y = .6 * wh;
903
904 cairo_move_to (cr, x - tri_x, y - tri_y);
905 cairo_line_to (cr, x + tri_x, y);
906 cairo_line_to (cr, x - tri_x, y + tri_y);
907 VECTORICONSTROKEOUTLINE(.5 + DEFAULT_LINE_WIDTH, fg_color);
908
909 }
910
icon_plus_sign(cairo_t * cr,const int width,const int height,const uint32_t fg_color)911 static void icon_plus_sign (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
912 {
913 const double lw = DEFAULT_LINE_WIDTH;
914 const double lc = fmod (lw * .5, 1.0);
915 const double xc = rint (width * .5) - lc;
916 const double yc = rint (height * .5) - lc;
917 const double ln = rint (std::min (width, height) * .2);
918
919 cairo_rectangle (cr, xc - lw * .5, yc - ln, lw, ln * 2);
920 cairo_rectangle (cr, xc - ln, yc - lw * .5, ln * 2, lw);
921
922 Gtkmm2ext::set_source_rgba (cr, fg_color);
923 cairo_fill (cr);
924 }
925
icon_shaded_plus_sign(cairo_t * cr,const int width,const int height,const uint32_t fg_color)926 static void icon_shaded_plus_sign (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
927 {
928 const double lw = std::min (10., ceil (std::min (width, height) * .035));
929 const double ln = std::min (57., rint (std::min (width, height) * .2));
930 const double lc = fmod (lw * .5, 1.0);
931 const double xc = rint (width * .5) - lc;
932 const double yc = rint (height * .5) - lc;
933
934 cairo_rectangle (cr, xc - lw * .5, yc - ln, lw, ln * 2);
935 cairo_rectangle (cr, xc - ln, yc - lw * .5, ln * 2, lw);
936
937 int alpha = lw == 1 ? 0x80 : 0x20;
938 Gtkmm2ext::set_source_rgba (cr, (fg_color & 0xffffff00) | alpha);
939 cairo_fill (cr);
940 }
941
942 /** mixer strip narrow/wide */
icon_strip_width(cairo_t * cr,const int width,const int height,const uint32_t fg_color)943 static void icon_strip_width (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
944 {
945 const double lw = DEFAULT_LINE_WIDTH;
946 const double xm = rint (width * .5) - lw * .5;
947 const double ym = rint (height * .5) - lw * .5;
948
949 const double dx = ceil (width * .3);
950 const double dy = ceil (height * .25);
951
952 const double x0 = xm - dx;
953 const double x1 = xm + dx;
954 const double y0 = ym - dy;
955 const double y1 = ym + dy;
956
957 const double arx = width * .15;
958 const double ary = height * .15;
959
960 Gtkmm2ext::set_source_rgba (cr, fg_color);
961 cairo_set_line_width (cr, lw);
962
963 // left + right
964 cairo_move_to (cr, x0, y0);
965 cairo_line_to (cr, x0, y1);
966 cairo_move_to (cr, x1, y0);
967 cairo_line_to (cr, x1, y1);
968
969 // horiz center line
970 cairo_move_to (cr, x0, ym);
971 cairo_line_to (cr, x1, ym);
972
973 // arrow left
974 cairo_move_to (cr, x0, ym);
975 cairo_rel_line_to (cr, arx, -ary);
976 cairo_move_to (cr, x0, ym);
977 cairo_rel_line_to (cr, arx, ary);
978
979 // arrow right
980 cairo_move_to (cr, x1, ym);
981 cairo_rel_line_to (cr, -arx, -ary);
982 cairo_move_to (cr, x1, ym);
983 cairo_rel_line_to (cr, -arx, ary);
984 cairo_stroke (cr);
985 }
986
987 /** 5-pin DIN MIDI socket */
icon_din_midi(cairo_t * cr,const int width,const int height,const uint32_t fg_color)988 static void icon_din_midi (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
989 {
990 const double x = width * .5;
991 const double y = height * .5;
992 const double r = std::min (x, y) * .75;
993 Gtkmm2ext::set_source_rgba (cr, fg_color);
994 cairo_set_line_width (cr, ceil (r * .05));
995 cairo_arc (cr, x, y, r, .57 * M_PI, 2.43 * M_PI);
996 cairo_stroke (cr);
997
998 // pins equally spaced 45deg
999 cairo_arc (cr, x, y * 0.5, r * .15, 0, 2 * M_PI);
1000 cairo_fill (cr);
1001 cairo_arc (cr, x * 0.5, y, r * .15, 0, 2 * M_PI);
1002 cairo_fill (cr);
1003 cairo_arc (cr, x * 1.5, y, r * .15, 0, 2 * M_PI);
1004 cairo_fill (cr);
1005 // .5 + .5 * .5 * sin(45deg), 1.5 - .5 * .5 * cos(45deg)
1006 cairo_arc (cr, x * 0.677, y * .677, r * .15, 0, 2 * M_PI);
1007 cairo_fill (cr);
1008 cairo_arc (cr, x * 1.323, y * .677, r * .15, 0, 2 * M_PI);
1009 cairo_fill (cr);
1010
1011 // bottom notch
1012 cairo_arc (cr, x, y+r, r * .26, 1.05 * M_PI, 1.95 * M_PI);
1013 cairo_stroke (cr);
1014 }
1015
1016 /*****************************************************************************
1017 * Plugin Window Buttons
1018 */
1019
icon_add_sign(cairo_t * cr,const int width,const int height,const uint32_t fg_color)1020 static void icon_add_sign (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
1021 {
1022 const double lw = DEFAULT_LINE_WIDTH;
1023 const double lc = fmod (lw * .5, 1.0);
1024 const double xc = rint (width * .5) - lc;
1025 const double yc = rint (height * .5) - lc;
1026 const double ln = rint (std::min (width, height) * .3);
1027
1028 cairo_rectangle (cr, xc - lw * .5, yc - ln, lw, ln * 2);
1029 cairo_rectangle (cr, xc - ln, yc - lw * .5, ln * 2, lw);
1030
1031 Gtkmm2ext::set_source_rgba (cr, fg_color);
1032 cairo_fill (cr);
1033 }
1034
icon_no_parking(cairo_t * cr,const int width,const int height,const uint32_t fg_color)1035 static void icon_no_parking (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
1036 {
1037 const double x = width * .5;
1038 const double y = height * .5;
1039 const double r = std::min (x, y) * .6;
1040 const double rl = .7 * r;
1041 cairo_arc (cr, x, y, r, 0, 2. * M_PI);
1042 cairo_move_to (cr, x - rl, y - rl);
1043 cairo_line_to (cr, x + rl, y + rl);
1044 VECTORICONSTROKE (DEFAULT_LINE_WIDTH, fg_color);
1045 }
1046
icon_save_arrow_box(cairo_t * cr,const int width,const int height,const uint32_t fg_color)1047 static void icon_save_arrow_box (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
1048 {
1049 const double x = width * .5;
1050 const double y = height * .5;
1051
1052 const double lw = DEFAULT_LINE_WIDTH;
1053 const double lc = fmod (lw * .5, 1.0);
1054
1055 const double x0 = rint (x) - lc;
1056 const double y0 = rint (y + std::min (x, y) * .05) - lc;
1057 const double o0 = std::min (x, y) * .35;
1058 const double ww = rint (std::min (x, y) * .55);
1059 const double hh = rint (std::min (x, y) * .45);
1060 const double ar = .5 + std::min (x, y) * .1;
1061
1062 /* box open at top middle */
1063 cairo_move_to (cr, x0 - o0, y0 - hh);
1064 cairo_line_to (cr, x0 - ww, y0 - hh);
1065 cairo_line_to (cr, x0 - ww, y0 + hh);
1066 cairo_line_to (cr, x0 + ww, y0 + hh);
1067 cairo_line_to (cr, x0 + ww, y0 - hh);
1068 cairo_line_to (cr, x0 + o0, y0 - hh);
1069 VECTORICONSTROKE (lw, fg_color);
1070
1071 /* downward arrow into the box */
1072 cairo_move_to (cr, x0, y0 - ar);
1073 cairo_line_to (cr, x0 - ar, y0 - ar);
1074 cairo_line_to (cr, x0, y0);
1075 cairo_line_to (cr, x0 + ar, y0 - ar);
1076 cairo_line_to (cr, x0, y0 - ar);
1077 cairo_line_to (cr, x0, y0 - ww - ar);
1078 VECTORICONSTROKE (lw, fg_color);
1079 }
1080
icon_list_browse(cairo_t * cr,const int width,const int height,const uint32_t fg_color)1081 static void icon_list_browse (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
1082 {
1083 const double x = width * .5;
1084 const double y = height * .5;
1085 const double d = std::min (x, y) * .5;
1086 const double r = std::min (x, y) * .1;
1087 const double l = std::min (x, y) * .2;
1088 const double lw = DEFAULT_LINE_WIDTH;
1089
1090 Gtkmm2ext::set_source_rgba (cr, fg_color);
1091 cairo_arc (cr, x-d, y-d, r, 0, 2. * M_PI);
1092 cairo_fill (cr);
1093 cairo_arc (cr, x-d, y, r, 0, 2. * M_PI);
1094 cairo_fill (cr);
1095 cairo_arc (cr, x-d, y+d, r, 0, 2. * M_PI);
1096 cairo_fill (cr);
1097
1098 cairo_move_to (cr, x - l, rint (y - d) + .5);
1099 cairo_line_to (cr, x + d, rint (y - d) + .5);
1100 cairo_move_to (cr, x - l, rint (y) + .5);
1101 cairo_line_to (cr, x + d, rint (y) + .5);
1102 cairo_move_to (cr, x - l, rint (y + d) + .5);
1103 cairo_line_to (cr, x + d, rint (y + d) + .5);
1104 VECTORICONSTROKE(lw, fg_color);
1105 }
1106
icon_on_off(cairo_t * cr,const int width,const int height,const uint32_t fg_color)1107 static void icon_on_off (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
1108 {
1109 const double x = width * .5;
1110 const double y = height * .5;
1111 const double r = std::min (x, y) * .65;
1112 const double lw = DEFAULT_LINE_WIDTH;
1113 const double lc = fmod (lw * .5, 1.0);
1114 const double x0 = rint (x) - lc;
1115
1116 cairo_arc (cr, x0, y, r, -.3 * M_PI, 1.3 * M_PI);
1117 cairo_move_to (cr, x0, y - r);
1118 cairo_line_to (cr, x0, y);
1119 VECTORICONSTROKE (lw, fg_color);
1120 }
1121
icon_bypass(cairo_t * cr,const int width,const int height,const uint32_t fg_color)1122 static void icon_bypass (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
1123 {
1124 const double x = width * .5;
1125 const double y = height * .5;
1126 const double y0 = height * .6;
1127 const double r = std::min (x, y) * .75;
1128 const double o = std::min (x, y) * .275;
1129 const double pt = DEFAULT_LINE_WIDTH;
1130
1131 const double dashes[] = { 1, pt };
1132 cairo_set_dash (cr, dashes, 2, 0);
1133 cairo_move_to (cr, x - r, y0);
1134 cairo_line_to (cr, x + r, y0);
1135 VECTORICONSTROKE(pt * .8, fg_color);
1136 cairo_set_dash (cr, 0, 0, 0);
1137
1138 cairo_move_to (cr, x - o, y0 - o);
1139 cairo_line_to (cr, x + o, y0 + o);
1140 cairo_move_to (cr, x + o, y0 - o);
1141 cairo_line_to (cr, x - o, y0 + o);
1142 VECTORICONSTROKE(pt * .8, fg_color);
1143
1144 cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
1145 cairo_arc (cr, x, y0, r, 0, 0);
1146 cairo_arc (cr, x, y0, r *.8, 1.92 * M_PI, 1.92 * M_PI);
1147 cairo_arc (cr, x, y0, r * 1.17, 1.92 * M_PI, 1.92 * M_PI);
1148 cairo_close_path (cr);
1149 cairo_arc_negative (cr, x, y0, r, 0, M_PI);
1150 VECTORICONSTROKE(pt, fg_color);
1151 }
1152
icon_reset_knob(cairo_t * cr,const int width,const int height,const uint32_t fg_color)1153 static void icon_reset_knob (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
1154 {
1155 const double x = width * .5;
1156 const double y = height * .5;
1157 const double r0 = std::min (x, y) * .3;
1158 const double r1 = std::min (x, y) * .65;
1159 const double ar = std::min (x, y) * .25;
1160 const double lw = DEFAULT_LINE_WIDTH;
1161 const double lc = fmod (lw * .5, 1.0);
1162 const double x0 = rint (x) - lc;
1163
1164 cairo_arc (cr, x0, y, r0, 0, 2. * M_PI);
1165 cairo_move_to (cr, x0, y - r0);
1166 cairo_line_to (cr, x0, y);
1167 VECTORICONSTROKE(lw, fg_color);
1168
1169 /* outer ring w/CCW arrow */
1170 cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
1171 cairo_arc (cr, x0, y, r1, -.25 * M_PI, -.25 * M_PI);
1172 cairo_rel_line_to (cr, 0, ar);
1173 cairo_rel_line_to (cr, ar, -ar);
1174 cairo_arc (cr, x0, y, r1, -.25 * M_PI, -.25 * M_PI);
1175 cairo_arc (cr, x0, y, r1, -.25 * M_PI, 1.50 * M_PI);
1176 VECTORICONSTROKE(lw, fg_color);
1177 }
1178
icon_config_wheel(cairo_t * cr,const int width,const int height,const uint32_t fg_color,int arrow)1179 static void icon_config_wheel (cairo_t *cr, const int width, const int height, const uint32_t fg_color, int arrow)
1180 {
1181 const double x = width * .5;
1182 const double y = height * .5;
1183 const double r0 = std::min (x, y) * .3;
1184 const double r1 = std::min (x, y) * .55;
1185 const double r2 = std::min (x, y) * .70;
1186 const double ar = std::min (x, y) * .25;
1187 const double lw = DEFAULT_LINE_WIDTH;
1188
1189 for (int i = 0; i < 8; ++i) {
1190 double ang0 = i * 2.0 * M_PI / 8.0;
1191 double ang1 = (i + 1) * 2.0 * M_PI / 8.0;
1192 double angm = 2.0 * M_PI / 48.0;
1193 double angd = 2.0 * M_PI / 64.0;
1194
1195 cairo_arc (cr, x, y, r2, ang0 - angm, ang0 + angm);
1196 cairo_arc (cr, x, y, r1, ang0 + angm + angd, ang1 - angm - angd);
1197 }
1198 cairo_close_path (cr);
1199 VECTORICONSTROKE(lw, fg_color);
1200
1201 cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
1202 if (arrow == 0) {
1203 cairo_arc (cr, x, y, r0, 0, 2.0 * M_PI);
1204 } else if (arrow > 0) {
1205 /* clockwise pointing arrow */
1206 cairo_arc (cr, x, y, r0, 1.9 * M_PI, 1.9 * M_PI);
1207 cairo_rel_line_to (cr, 0, -ar);
1208 cairo_rel_line_to (cr, -ar, ar);
1209 cairo_arc (cr, x, y, r0, 1.9 * M_PI, 1.9 * M_PI);
1210 cairo_arc_negative (cr, x, y, r0, 1.9 * M_PI, .5 * M_PI);
1211 } else {
1212 /* counterclockwise arrow */
1213 cairo_arc (cr, x, y, r0, 1.1 * M_PI, 1.1 * M_PI);
1214 cairo_rel_line_to (cr, 0, -ar);
1215 cairo_rel_line_to (cr, ar, ar);
1216 cairo_arc (cr, x, y, r0, 1.1 * M_PI, 1.1 * M_PI);
1217 cairo_arc (cr, x, y, r0, 1.1 * M_PI, .5 * M_PI);
1218 }
1219 VECTORICONSTROKE(lw, fg_color);
1220 }
1221
icon_pcb_via(cairo_t * cr,const int width,const int height,const uint32_t fg_color)1222 static void icon_pcb_via (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
1223 {
1224 const double x = ceil (width * .5) - .5;
1225 const double y = ceil (height * .5) - .5;
1226
1227 const double d = rint (std::min (x, y) * .5);
1228 const double r = std::min (x, y) * .16;
1229 const double p = std::min (x, y) * .1;
1230
1231 cairo_arc_negative (cr, x+d, y+d, r, 1.15 * M_PI, -.85 * M_PI);
1232 cairo_arc (cr, x+d, y+d, d * 1.12, 1.15 * M_PI, 1.15 * M_PI);
1233
1234 cairo_arc (cr, x-d, y-d, d * 1.12, 0.15 * M_PI, .15 * M_PI);
1235 cairo_arc (cr, x-d, y-d, r, 0.15 * M_PI, 2.5 * M_PI);
1236
1237 cairo_arc (cr, x-d, y-d, r, .5 * M_PI, .5 * M_PI);
1238 cairo_arc (cr, x-d, y+d, r, -.5 * M_PI, 1.5 * M_PI);
1239 VECTORICONSTROKE (p, fg_color);
1240
1241 cairo_arc (cr, x+d, y-d, r, -.5 * M_PI, 1.5 * M_PI);
1242 VECTORICONSTROKE (p, fg_color);
1243 }
1244
icon_latency_clock(cairo_t * cr,const int width,const int height,const uint32_t fg_color)1245 static void icon_latency_clock (cairo_t *cr, const int width, const int height, const uint32_t fg_color)
1246 {
1247 const double x = width * .5;
1248 const double y = height * .5;
1249 const double y0 = std::min (x, y) * .4;
1250 const double r0 = std::min (x, y) * .1;
1251 const double r1 = std::min (x, y) * .5;
1252 const double r2 = std::min (x, y) * .66;
1253
1254 const double lw = DEFAULT_LINE_WIDTH;
1255 const double lc = fmod (lw * .5, 1.0);
1256 const double x0 = rint (x) - lc;
1257
1258 cairo_move_to (cr, x0, y - y0);
1259 cairo_arc (cr, x0, y, r2, -.5 * M_PI, 1.25 * M_PI);
1260 VECTORICONSTROKE(lw, fg_color);
1261
1262 cairo_arc (cr, x0, y, r0, -.4 * M_PI , .9 * M_PI);
1263 cairo_arc (cr, x0, y, r1, 1.25 * M_PI, 1.25 * M_PI);
1264 cairo_arc (cr, x0, y, r0, -.4 * M_PI, -.4 * M_PI);
1265 cairo_close_path (cr);
1266 cairo_fill (cr);
1267 }
1268
1269 /*****************************************************************************/
1270
1271 bool
render(cairo_t * cr,const enum ArdourWidgets::ArdourIcon::Icon icon,const int width,const int height,const Gtkmm2ext::ActiveState state,const uint32_t fg_color)1272 ArdourWidgets::ArdourIcon::render (cairo_t *cr,
1273 const enum ArdourWidgets::ArdourIcon::Icon icon,
1274 const int width, const int height,
1275 const Gtkmm2ext::ActiveState state,
1276 const uint32_t fg_color)
1277 {
1278 bool rv = true;
1279 cairo_save (cr);
1280
1281 if (width < 6 || height < 6) {
1282 return false;
1283 }
1284
1285 switch (icon) {
1286 case TransportStop:
1287 icon_transport_stop (cr, width, height);
1288 break;
1289 case TransportPlay:
1290 icon_transport_play (cr, width, height);
1291 break;
1292 case TransportLoop:
1293 icon_transport_loop (cr, width, height);
1294 break;
1295 case TransportMetronom:
1296 icon_transport_metronom (cr, width, height);
1297 break;
1298 case TransportPanic:
1299 icon_transport_panic (cr, width, height);
1300 break;
1301 case TransportStart:
1302 /* fallthrough */
1303 case TransportEnd:
1304 /* fallthrough */
1305 case TransportRange:
1306 icon_transport_ck (cr, icon, width, height);
1307 break;
1308 case RecButton:
1309 icon_rec_enable (cr, width, height, state);
1310 break;
1311 case CloseCross:
1312 icon_close_cross (cr, width, height, fg_color);
1313 break;
1314 case HideEye:
1315 icon_hide_eye (cr, width, height, fg_color);
1316 break;
1317 case PlusSign:
1318 icon_plus_sign (cr, width, height, fg_color);
1319 break;
1320 case ShadedPlusSign:
1321 icon_shaded_plus_sign (cr, width, height, fg_color);
1322 break;
1323 case StripWidth:
1324 icon_strip_width (cr, width, height, fg_color);
1325 break;
1326 case DinMidi:
1327 icon_din_midi (cr, width, height, fg_color);
1328 break;
1329 case ScrollLeft:
1330 icon_scroll_left (cr, width, height, fg_color);
1331 break;
1332 case ScrollRight:
1333 icon_scroll_right (cr, width, height, fg_color);
1334 break;
1335 case NudgeLeft:
1336 icon_nudge_left (cr, width, height, fg_color);
1337 break;
1338 case NudgeRight:
1339 icon_nudge_right (cr, width, height, fg_color);
1340 break;
1341 case ZoomIn:
1342 /* fallthrough */
1343 case ZoomOut:
1344 /* fallthrough */
1345 case ZoomFull:
1346 icon_zoom (cr, icon, width, height, fg_color);
1347 break;
1348 case ZoomExpand:
1349 icon_zoom_expand (cr, width, height);
1350 break;
1351 case TimeAxisShrink:
1352 icon_tav_shrink (cr, width, height);
1353 break;
1354 case TimeAxisExpand:
1355 icon_tav_expand (cr, width, height);
1356 break;
1357 case ToolRange:
1358 /* similar to icon_strip_width() but with outline */
1359 icon_tool_range (cr, width, height);
1360 break;
1361 case ToolGrab:
1362 icon_tool_grab (cr, width, height);
1363 break;
1364 case ToolCut:
1365 icon_tool_cut (cr, width, height);
1366 break;
1367 case ToolStretch:
1368 icon_tool_stretch (cr, width, height);
1369 break;
1370 case ToolAudition:
1371 icon_tool_audition (cr, width, height);
1372 break;
1373 case ToolDraw:
1374 icon_tool_draw (cr, width, height);
1375 break;
1376 case ToolContent:
1377 icon_tool_content (cr, width, height);
1378 break;
1379 case PsetAdd:
1380 icon_add_sign (cr, width, height, fg_color);
1381 break;
1382 case PsetSave:
1383 icon_save_arrow_box (cr, width, height, fg_color);
1384 break;
1385 case PsetDelete:
1386 icon_no_parking (cr, width, height, fg_color);
1387 break;
1388 case PsetBrowse:
1389 icon_list_browse (cr, width, height, fg_color);
1390 break;
1391 case PluginReset:
1392 icon_reset_knob (cr, width, height, fg_color);
1393 break;
1394 case PluginBypass:
1395 icon_bypass (cr, width, height, fg_color);
1396 break;
1397 case PluginPinout:
1398 icon_pcb_via (cr, width, height, fg_color);
1399 break;
1400 case Config: /* unused */
1401 icon_config_wheel (cr, width, height, fg_color, 0);
1402 break;
1403 case ConfigReset: /* unused */
1404 icon_config_wheel (cr, width, height, fg_color, -1);
1405 break;
1406 case PowerOnOff: /* unused */
1407 icon_on_off (cr, width, height, fg_color);
1408 break;
1409 case LatencyClock: /* unused */
1410 icon_latency_clock (cr, width, height, fg_color);
1411 break;
1412 case NoIcon:
1413 rv = false;
1414 break;
1415 }
1416 cairo_restore (cr);
1417 return rv;
1418 }
1419
1420 bool
expose(GdkEventExpose * ev,Gtk::Widget * w,const enum ArdourIcon::Icon icon)1421 ArdourWidgets::ArdourIcon::expose (GdkEventExpose* ev, Gtk::Widget* w, const enum ArdourIcon::Icon icon)
1422 {
1423 Glib::RefPtr<Gdk::Window> win (w->get_window());
1424 cairo_t* cr = gdk_cairo_create (win->gobj());
1425 gdk_cairo_rectangle (cr, &ev->area);
1426 cairo_clip (cr);
1427
1428 Glib::RefPtr<Gtk::Style> style = w->get_style();
1429 Gdk::Color fg (style->get_fg (Gtk::STATE_NORMAL));
1430
1431 ArdourIcon::render (cr, icon, win->get_width (), win->get_height (), Gtkmm2ext::ExplicitActive,
1432 RGBA_TO_UINT (fg.get_red() / 255., fg.get_green() / 255, fg.get_blue() / 255, 255));
1433 cairo_destroy (cr);
1434
1435 return true;
1436 }
1437