New rack rack-ears
[calf.git] / src / drawingutils.cpp
blob7246248ff81c2b56390d7cc5e5cb031ec5dfd20f
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>
27 void display_background(GtkWidget *widget, cairo_t* c, int x, int y, int sx, int sy, int ox, int oy, float brightness, int shadow, float lights, float dull)
29 float br = brightness * 0.5 + 0.5;
31 if (!c) {
32 GdkWindow *window = widget->window;
33 c = gdk_cairo_create(GDK_DRAWABLE(window));
36 // outer frame (black)
37 int pad = 0;
39 //cairo_rectangle(
40 //c, pad + x, pad + y, sx + ox * 2 - pad * 2, sy + oy * 2 - pad * 2);
41 //cairo_set_source_rgb(c, 0, 0, 0);
42 //cairo_fill(c);
44 // black light effect
45 float r, g, b;
46 get_bg_color(widget, NULL, &r, &g, &b);
48 pad = 0;
49 create_rectangle(
50 c, pad + x, pad + y, sx + ox * 2 - pad * 2, sy + oy * 2 - pad * 2, 0);
51 cairo_pattern_t *pat2 = cairo_pattern_create_linear (
52 x, y, x, y + sy + oy * 2 - pad * 2);
53 cairo_pattern_add_color_stop_rgba (pat2, 0, r*1.111, g*1.111, b*1.111, 1);
54 cairo_pattern_add_color_stop_rgba (pat2, 1, r*0.82, g*0.82, b*0.82, 1);
55 //cairo_pattern_add_color_stop_rgba (pat2, 0.33, 0.05, 0.05, 0.05, 1);
56 //cairo_pattern_add_color_stop_rgba (pat2, 0.5, 0, 0, 0, 1);
57 cairo_set_source (c, pat2);
58 cairo_fill(c);
59 cairo_pattern_destroy(pat2);
61 //cairo_rectangle(c, x + ox - 1, y + oy - 1, sx + 2, sy + 2);
62 //cairo_set_source_rgb (c, 0, 0, 0);
63 //cairo_fill(c);
65 // inner yellowish screen
66 get_base_color(widget, NULL, &r, &g, &b);
67 cairo_pattern_t *pt = cairo_pattern_create_linear(x + ox, y + oy, x + ox, y + sy);
68 cairo_pattern_add_color_stop_rgb(pt, 0.0, br * r * 0.75, br * g * 0.75, br * b * 0.75);
69 cairo_pattern_add_color_stop_rgb(pt, 1.0, br * r, br * g, br * b);
70 cairo_set_source (c, pt);
71 cairo_rectangle(c, x + ox, y + oy, sx, sy);
72 cairo_fill(c);
73 cairo_pattern_destroy(pt);
75 if (shadow) {
76 // top shadow
77 pt = cairo_pattern_create_linear(x + ox, y + oy, x + ox, y + oy + shadow);
78 cairo_pattern_add_color_stop_rgba(pt, 0.0, 0,0,0,0.6);
79 cairo_pattern_add_color_stop_rgba(pt, 1.0, 0,0,0,0);
80 cairo_set_source (c, pt);
81 cairo_rectangle(c, x + ox, y + oy, sx, shadow);
82 cairo_fill(c);
83 cairo_pattern_destroy(pt);
85 // left shadow
86 pt = cairo_pattern_create_linear(x + ox, y + oy, x + ox + (float)shadow * 0.7, y + oy);
87 cairo_pattern_add_color_stop_rgba(pt, 0.0, 0,0,0,0.3);
88 cairo_pattern_add_color_stop_rgba(pt, 1.0, 0,0,0,0);
89 cairo_set_source (c, pt);
90 cairo_rectangle(c, x + ox, y + oy, (float)shadow * 0.7, sy);
91 cairo_fill(c);
92 cairo_pattern_destroy(pt);
94 // right shadow
95 pt = cairo_pattern_create_linear(x + ox + sx - (float)shadow * 0.7, y + oy, x + ox + sx, y + oy);
96 cairo_pattern_add_color_stop_rgba(pt, 0.0, 0,0,0,0);
97 cairo_pattern_add_color_stop_rgba(pt, 1.0, 0,0,0,0.3);
98 cairo_set_source (c, pt);
99 cairo_rectangle(c, x + ox + sx - (float)shadow * 0.7, y + oy, (float)shadow * 0.7, sy);
100 cairo_fill(c);
101 cairo_pattern_destroy(pt);
104 if(dull) {
105 // left dull
106 pt = cairo_pattern_create_linear(x + ox, y + oy, x + ox + sx / 2, y + oy);
107 cairo_pattern_add_color_stop_rgba(pt, 0.0, 0,0,0,dull);
108 cairo_pattern_add_color_stop_rgba(pt, 1.0, 0,0,0,0);
109 cairo_set_source (c, pt);
110 cairo_rectangle(c, x + ox, y + oy, sx / 2, sy);
111 cairo_fill(c);
112 cairo_pattern_destroy(pt);
114 // right dull
115 pt = cairo_pattern_create_linear(x + ox + sx / 2, y + oy, x + ox + sx, y + oy);
116 cairo_pattern_add_color_stop_rgba(pt, 0.0, 0,0,0,0);
117 cairo_pattern_add_color_stop_rgba(pt, 1.0, 0,0,0,dull);
118 cairo_set_source (c, pt);
119 cairo_rectangle(c, x + ox + sx / 2, y + oy, sx / 2, sy);
120 cairo_fill(c);
121 cairo_pattern_destroy(pt);
124 if(lights > 0) {
125 // light sources
126 int div = 1;
127 while(sx / div > 300)
128 div += 1;
129 float w = float(sx) / float(div);
130 cairo_rectangle(c, x + ox, y + oy, sx, sy);
131 for(int i = 0; i < div; i ++) {
132 cairo_pattern_t *pt = cairo_pattern_create_radial(
133 x + ox + w * i + w / 2.f, y + oy, 1,
134 x + ox + w * i + w / 2.f, std::min(w / 2.0 + y + oy, y + oy + sy * 0.25) - 1, w / 2.f);
135 cairo_pattern_add_color_stop_rgba (pt, 0, r * 1.8, g * 1.8, b * 1.8, lights);
136 cairo_pattern_add_color_stop_rgba (pt, 1, r, g, b, 0);
137 cairo_set_source (c, pt);
138 cairo_fill_preserve(c);
139 pt = cairo_pattern_create_radial(
140 x + ox + w * i + w / 2.f, y + oy + sy, 1,
141 x + ox + w * i + w / 2.f, std::max(sy - w / 2.0 + y + oy, y + oy + sy * 0.75) + 1, w / 2.f);
142 cairo_pattern_add_color_stop_rgba (pt, 0, r * 1.8, g * 1.8, b * 1.8, lights);
143 cairo_pattern_add_color_stop_rgba (pt, 1, r, g, b, 0);
144 cairo_set_source (c, pt);
145 cairo_fill_preserve(c);
146 cairo_pattern_destroy(pt);
151 void draw_rect (GtkWidget * widget, const gchar * type, GtkStateType * state, gint x, gint y, gint width, gint height, gint rad, float bevel) {
152 cairo_t * cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
153 float r, g, b;
154 get_color(widget, type, state, &r, &g, &b);
155 create_rectangle(cr, x, y, width, height, rad);
156 cairo_set_source_rgb(cr, r, g, b);
157 cairo_fill(cr);
159 if (bevel)
160 draw_bevel(cr, x, y, width, height, rad, bevel);
162 cairo_destroy(cr);
164 void _draw_inset (cairo_t * cr, gint x, gint y, gint width, gint height, gint rad, gint depth) {
165 cairo_pattern_t *pat = cairo_pattern_create_linear (x, y, x, y + height);
166 cairo_pattern_add_color_stop_rgba(pat, 0.0, 0.0, 0.0, 0.0, 0.33);
167 cairo_pattern_add_color_stop_rgba(pat, 1.0, 1.0, 1.0, 1.0, 0.1);
168 cairo_set_source(cr, pat);
169 create_rectangle(cr, x-depth*0.5, y-depth, width+depth, height+2*depth, rad);
170 cairo_fill(cr);
172 void draw_inset (GtkWidget * widget, gint x, gint y, gint width, gint height, gint rad, gint depth) {
173 cairo_t * cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
174 _draw_inset(cr, x, y, width, height, rad, depth);
175 cairo_destroy(cr);
177 void _draw_glass (cairo_t *cr, gint x, gint y, gint width, gint height, gint rad) {
178 cairo_pattern_t *pat = cairo_pattern_create_linear (x, y, x, y + 3);
179 cairo_pattern_add_color_stop_rgba(pat, 0.0, 0.0, 0.0, 0.0, 0.5);
180 cairo_pattern_add_color_stop_rgba(pat, 1.0, 0.0, 0.0, 0.0, 0.0);
181 cairo_set_source(cr, pat);
182 create_rectangle(cr, x, y, width, height, rad);
183 cairo_fill(cr);
185 void draw_glass (GtkWidget * widget, gint x, gint y, gint width, gint height, gint rad) {
186 cairo_t * cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
187 _draw_glass(cr, x, y, width, height, rad);
188 cairo_destroy(cr);
191 void get_bg_color (GtkWidget * widget, GtkStateType * state, float * r, float * g, float * b) {
192 get_color(widget, "bg", state, r, g, b);
194 void get_fg_color (GtkWidget * widget, GtkStateType * state, float * r, float * g, float * b) {
195 get_color(widget, "fg", state, r, g, b);
197 void get_base_color (GtkWidget * widget, GtkStateType * state, float * r, float * g, float * b) {
198 get_color(widget, "base", state, r, g, b);
200 void get_text_color (GtkWidget * widget, GtkStateType * state, float * r, float * g, float * b) {
201 get_color(widget, "text", state, r, g, b);
203 void get_color (GtkWidget * widget, const gchar * type, GtkStateType * state, float * r, float * g, float * b) {
204 GdkColor color;
205 GtkStyle * style = gtk_widget_get_style (widget);
206 if (style != NULL) {
207 GtkStateType s;
208 if (state)
209 s = *state;
210 else
211 s = gtk_widget_get_state(widget);
212 color = style->bg[s];
213 if (!strcmp(type, "bg"))
214 color = style->bg[s];
215 if (!strcmp(type, "fg"))
216 color = style->fg[s];
217 if (!strcmp(type, "base"))
218 color = style->base[s];
219 if (!strcmp(type, "text"))
220 color = style->text[s];
221 *r = float(color.red) / 65535;
222 *g = float(color.green) / 65535;
223 *b = float(color.blue) / 65535;
227 void clip_context (GtkWidget * widget, cairo_t * cr, GdkRegion *region) {
228 GdkRegion *reg = gdk_region_rectangle(&widget->allocation);
229 if (region)
230 gdk_region_intersect(reg, region);
231 gdk_cairo_region(cr, reg);
232 cairo_clip (cr);
235 void create_rectangle (cairo_t * cr, gint x, gint y, gint width, gint height, gint rad) {
236 if (rad == 0) {
237 cairo_rectangle(cr, x, y, width, height);
238 return;
240 cairo_move_to(cr,x+rad,y); // Move to A
241 cairo_line_to(cr,x+width-rad,y); // Straight line to B
242 cairo_curve_to(cr,x+width,y,x+width,y,x+width,y+rad); // Curve to C, Control points are both at Q
243 cairo_line_to(cr,x+width,y+height-rad); // Move to D
244 cairo_curve_to(cr,x+width,y+height,x+width,y+height,x+width-rad,y+height); // Curve to E
245 cairo_line_to(cr,x+rad,y+height); // Line to F
246 cairo_curve_to(cr,x,y+height,x,y+height,x,y+height-rad); // Curve to G
247 cairo_line_to(cr,x,y+rad); // Line to H
248 cairo_curve_to(cr,x,y,x,y,x+rad,y); // Curve to A
251 void draw_bevel (cairo_t * cr, gint x, gint y, gint width, gint height, gint rad, float bevel) {
252 if (bevel == 0)
253 return;
254 cairo_save(cr);
255 create_rectangle(cr, x, y, width, height, rad);
256 cairo_pattern_t * pat;
257 if (bevel > 0)
258 pat = cairo_pattern_create_linear (x, y, x, y + height);
259 else
260 pat = cairo_pattern_create_linear (x, y + height, x, y);
261 cairo_pattern_add_color_stop_rgba(pat, 0.0, 1.0, 1.0, 1.0, bevel / 2);
262 cairo_pattern_add_color_stop_rgba(pat, 1.0, 0.0, 0.0, 0.0, bevel);
263 cairo_set_source(cr, pat);
264 cairo_set_operator(cr, CAIRO_OPERATOR_SOFT_LIGHT);
265 cairo_fill_preserve(cr);
266 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
267 cairo_fill(cr);
268 cairo_pattern_destroy (pat);
269 cairo_restore(cr);