Make Analyzer UI require instance-access
[calf.git] / src / drawingutils.cpp
blob10c17b24fc31096debba98da8a2670d90918e3f7
1 /* Calf DSP Library
2 * A few useful drawing funcitons
3 * Copyright (C) 2007-2015 Krzysztof Foltman, Torben Hohn, Markus Schmidt
4 * and others
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 #include "calf/drawingutils.h"
23 #include <cstring>
24 #include <algorithm>
25 #include <math.h>
28 void display_background(GtkWidget *widget, cairo_t* c, int x, int y, int sx, int sy, int ox, int oy, float radius, float bevel, float brightness, int shadow, float lights, float dull)
30 float br = brightness * 0.5 + 0.5;
32 if (!c) {
33 GdkWindow *window = widget->window;
34 c = gdk_cairo_create(GDK_DRAWABLE(window));
37 float r, g, b;
38 get_bg_color(widget, NULL, &r, &g, &b);
40 create_rectangle(c, x, y, sx + ox * 2, sy + oy * 2, radius);
41 cairo_set_source_rgb (c, r, g, b);
42 cairo_fill(c);
43 draw_bevel(c, x, y, sx + ox * 2, sy + oy * 2, radius, bevel);
45 // inner screen
46 get_base_color(widget, NULL, &r, &g, &b);
47 cairo_pattern_t *pt = cairo_pattern_create_linear(x + ox, y + oy, x + ox, y + sy);
48 cairo_pattern_add_color_stop_rgb(pt, 0.0, br * r * 0.75, br * g * 0.75, br * b * 0.75);
49 cairo_pattern_add_color_stop_rgb(pt, 1.0, br * r, br * g, br * b);
50 cairo_set_source (c, pt);
51 cairo_rectangle(c, x + ox, y + oy, sx, sy);
52 cairo_fill(c);
53 cairo_pattern_destroy(pt);
55 if (shadow) {
56 // top shadow
57 pt = cairo_pattern_create_linear(x + ox, y + oy, x + ox, y + oy + shadow);
58 cairo_pattern_add_color_stop_rgba(pt, 0.0, 0,0,0,0.6);
59 cairo_pattern_add_color_stop_rgba(pt, 1.0, 0,0,0,0);
60 cairo_set_source (c, pt);
61 cairo_rectangle(c, x + ox, y + oy, sx, shadow);
62 cairo_fill(c);
63 cairo_pattern_destroy(pt);
65 // left shadow
66 pt = cairo_pattern_create_linear(x + ox, y + oy, x + ox + (float)shadow * 0.7, y + oy);
67 cairo_pattern_add_color_stop_rgba(pt, 0.0, 0,0,0,0.3);
68 cairo_pattern_add_color_stop_rgba(pt, 1.0, 0,0,0,0);
69 cairo_set_source (c, pt);
70 cairo_rectangle(c, x + ox, y + oy, (float)shadow * 0.7, sy);
71 cairo_fill(c);
72 cairo_pattern_destroy(pt);
74 // right shadow
75 pt = cairo_pattern_create_linear(float(x + ox + sx) - (float)shadow * 0.7, y + oy, x + ox + sx, y + oy);
76 cairo_pattern_add_color_stop_rgba(pt, 0.0, 0,0,0,0);
77 cairo_pattern_add_color_stop_rgba(pt, 1.0, 0,0,0,0.3);
78 cairo_set_source (c, pt);
79 cairo_rectangle(c, x + ox + sx - (float)shadow * 0.7, y + oy, (float)shadow * 0.7, sy);
80 cairo_fill(c);
81 cairo_pattern_destroy(pt);
84 if(dull) {
85 pt = cairo_pattern_create_linear(x + ox, y + oy, x + ox + sx, y + oy);
86 cairo_pattern_add_color_stop_rgba(pt, 0.0, 0,0,0,dull);
87 cairo_pattern_add_color_stop_rgba(pt, 0.5, 0,0,0,0);
88 cairo_pattern_add_color_stop_rgba(pt, 1.0, 0,0,0,dull);
89 cairo_set_source (c, pt);
90 cairo_rectangle(c, x + ox, y + oy, sx, sy);
91 cairo_fill(c);
92 cairo_pattern_destroy(pt);
95 if(lights > 0) {
96 // light sources
97 int div = 1;
98 while(sx / div > 300)
99 div += 1;
100 float w = float(sx) / float(div);
101 cairo_rectangle(c, x + ox, y + oy, sx, sy);
102 for(int i = 0; i < div; i ++) {
103 cairo_pattern_t *pt = cairo_pattern_create_radial(
104 x + ox + w * i + w / 2.f, y + oy, 1,
105 x + ox + w * i + w / 2.f, std::min(w / 2.0 + y + oy, y + oy + sy * 0.25) - 1, w / 2.f);
106 cairo_pattern_add_color_stop_rgba (pt, 0, r * 1.8, g * 1.8, b * 1.8, lights);
107 cairo_pattern_add_color_stop_rgba (pt, 1, r, g, b, 0);
108 cairo_set_source (c, pt);
109 cairo_fill_preserve(c);
110 pt = cairo_pattern_create_radial(
111 x + ox + w * i + w / 2.f, y + oy + sy, 1,
112 x + ox + w * i + w / 2.f, std::max(sy - w / 2.0 + y + oy, y + oy + sy * 0.75) + 1, w / 2.f);
113 cairo_pattern_add_color_stop_rgba (pt, 0, r * 1.8, g * 1.8, b * 1.8, lights);
114 cairo_pattern_add_color_stop_rgba (pt, 1, r, g, b, 0);
115 cairo_set_source (c, pt);
116 cairo_fill_preserve(c);
117 cairo_pattern_destroy(pt);
120 cairo_new_path(c);
123 void draw_rect (GtkWidget * widget, const gchar * type, GtkStateType * state, gint x, gint y, gint width, gint height, float rad, float bevel) {
124 cairo_t * cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
125 float r, g, b;
126 get_color(widget, type, state, &r, &g, &b);
127 create_rectangle(cr, x, y, width, height, rad);
128 cairo_set_source_rgb(cr, r, g, b);
129 cairo_fill(cr);
131 if (bevel)
132 draw_bevel(cr, x, y, width, height, rad, bevel);
134 cairo_destroy(cr);
136 void _draw_inset (cairo_t * cr, gint x, gint y, gint width, gint height, float rad, gint depth) {
137 cairo_pattern_t *pat = cairo_pattern_create_linear (x, y, x, y + height);
138 cairo_pattern_add_color_stop_rgba(pat, 0.0, 0.0, 0.0, 0.0, 0.33);
139 cairo_pattern_add_color_stop_rgba(pat, 1.0, 1.0, 1.0, 1.0, 0.1);
140 cairo_set_source(cr, pat);
141 create_rectangle(cr, x-depth*0.5, y-depth, width+depth, height+2*depth, rad);
142 cairo_fill(cr);
144 void draw_inset (GtkWidget * widget, gint x, gint y, gint width, gint height, float rad, gint depth) {
145 cairo_t * cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
146 _draw_inset(cr, x, y, width, height, rad, depth);
147 cairo_destroy(cr);
149 void _draw_glass (cairo_t *cr, gint x, gint y, gint width, gint height, float rad) {
150 cairo_pattern_t *pat = cairo_pattern_create_linear (x, y, x, y + 3);
151 cairo_pattern_add_color_stop_rgba(pat, 0.0, 0.0, 0.0, 0.0, 0.5);
152 cairo_pattern_add_color_stop_rgba(pat, 1.0, 0.0, 0.0, 0.0, 0.0);
153 cairo_set_source(cr, pat);
154 create_rectangle(cr, x, y, width, height, rad);
155 cairo_fill(cr);
157 void draw_glass (GtkWidget * widget, gint x, gint y, gint width, gint height, float rad) {
158 cairo_t * cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
159 _draw_glass(cr, x, y, width, height, rad);
160 cairo_destroy(cr);
163 void get_bg_color (GtkWidget * widget, GtkStateType * state, float * r, float * g, float * b) {
164 get_color(widget, "bg", state, r, g, b);
166 void get_fg_color (GtkWidget * widget, GtkStateType * state, float * r, float * g, float * b) {
167 get_color(widget, "fg", state, r, g, b);
169 void get_base_color (GtkWidget * widget, GtkStateType * state, float * r, float * g, float * b) {
170 get_color(widget, "base", state, r, g, b);
172 void get_text_color (GtkWidget * widget, GtkStateType * state, float * r, float * g, float * b) {
173 get_color(widget, "text", state, r, g, b);
175 void get_color (GtkWidget * widget, const gchar * type, GtkStateType * state, float * r, float * g, float * b) {
176 GdkColor color;
177 GtkStyle * style = gtk_widget_get_style (widget);
178 if (style != NULL) {
179 GtkStateType s;
180 if (state)
181 s = *state;
182 else
183 s = gtk_widget_get_state(widget);
184 color = style->bg[s];
185 if (!strcmp(type, "bg"))
186 color = style->bg[s];
187 if (!strcmp(type, "fg"))
188 color = style->fg[s];
189 if (!strcmp(type, "base"))
190 color = style->base[s];
191 if (!strcmp(type, "text"))
192 color = style->text[s];
193 *r = float(color.red) / 65535;
194 *g = float(color.green) / 65535;
195 *b = float(color.blue) / 65535;
199 void clip_context (GtkWidget * widget, cairo_t * cr, GdkRegion *region) {
200 GdkRegion *reg = gdk_region_rectangle(&widget->allocation);
201 if (region)
202 gdk_region_intersect(reg, region);
203 gdk_cairo_region(cr, reg);
204 cairo_clip (cr);
207 void create_rectangle (cairo_t * cr, gint x, gint y, gint width, gint height, float rad) {
208 if (rad == 0) {
209 cairo_rectangle(cr, x, y, width, height);
210 return;
212 //cairo_move_to(cr,x+rad,y); // Move to A
213 //cairo_line_to(cr,x+width-rad,y); // Straight line to B
214 //cairo_curve_to(cr,x+width,y,x+width,y,x+width,y+rad); // Curve to C, Control points are both at Q
215 //cairo_line_to(cr,x+width,y+height-rad); // Move to D
216 //cairo_curve_to(cr,x+width,y+height,x+width,y+height,x+width-rad,y+height); // Curve to E
217 //cairo_line_to(cr,x+rad,y+height); // Line to F
218 //cairo_curve_to(cr,x,y+height,x,y+height,x,y+height-rad); // Curve to G
219 //cairo_line_to(cr,x,y+rad); // Line to H
220 //cairo_curve_to(cr,x,y,x,y,x+rad,y); // Curve to A
221 // top left
222 cairo_move_to(cr, x, y + rad);
223 cairo_arc (cr, x + rad, y + rad, rad, 1 * M_PI, 1.5 * M_PI);
224 // top
225 cairo_line_to(cr, x + width - rad, y);
226 // top right
227 cairo_arc (cr, x + width - rad, y + rad, rad, 1.5 * M_PI, 2 * M_PI);
228 // right
229 cairo_line_to(cr, x + width, y + height - rad);
230 // bottom right
231 cairo_arc (cr, x + width - rad, y + height - rad, rad, 0 * M_PI, 0.5 * M_PI);
232 // bottom
233 cairo_line_to(cr, x + rad, y + height);
234 // bottom left
235 cairo_arc (cr, x + rad, y + height - rad, rad, 0.5 * M_PI, 1 * M_PI);
236 // left
237 cairo_line_to(cr, x, y + rad);
241 void draw_bevel (cairo_t * cr, gint x, gint y, gint width, gint height, float rad, float bevel) {
242 if (bevel == 0)
243 return;
244 cairo_save(cr);
245 create_rectangle(cr, x, y, width, height, rad);
246 cairo_pattern_t * pat;
247 if (bevel > 0)
248 pat = cairo_pattern_create_linear (x, y, x, y + height);
249 else
250 pat = cairo_pattern_create_linear (x, y + height, x, y);
251 if (bevel < 0) bevel *= -1;
252 cairo_pattern_add_color_stop_rgba(pat, 0.0, 1.0, 1.0, 1.0, bevel / 2);
253 cairo_pattern_add_color_stop_rgba(pat, 1.0, 0.0, 0.0, 0.0, bevel);
254 cairo_set_source(cr, pat);
255 cairo_set_operator(cr, CAIRO_OPERATOR_SOFT_LIGHT);
256 cairo_fill_preserve(cr);
257 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
258 cairo_fill(cr);
259 cairo_pattern_destroy (pat);
260 cairo_restore(cr);