libxputty  0.1
A damn tiny abstraction Layer to create X11 window/widgets with cairo surfaces
xmeter_private.c
Go to the documentation of this file.
1 /*
2  * 0BSD
3  *
4  * BSD Zero Clause License
5  *
6  * Copyright (c) 2019 Hermann Meyer
7  *
8  * Permission to use, copy, modify, and/or distribute this software for any
9  * purpose with or without fee is hereby granted.
10 
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  *
19  */
20 
21 
22 #include "xmeter_private.h"
23 
24 
25 void _draw_vmeter_scale(void *w_, void* user_data) {
26  Widget_t *w = (Widget_t*)w_;
27  XWindowAttributes attrs;
28  XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
29  int rect_width = attrs.width;
30  int rect_height = attrs.height;
31  double x0 = 0;
32  double y0 = 0;
33 
34  int db_points[] = { -50, -40, -30, -20, -15, -10, -6, -3, 0, 3 };
35  //int db_points[] = { -50, -40, -30, -20, -10, -3, 0, 4 };
36  char buf[32];
37 
38  cairo_set_font_size (w->crb, (float)rect_width/2);
39  cairo_set_source_rgb(w->crb, 0.8, 0.8, 0.8);
40 
41  for (unsigned int i = 0; i < sizeof (db_points)/sizeof (db_points[0]); ++i)
42  {
43  float fraction = _log_meter((double)db_points[i]);
44  cairo_move_to (w->crb, 0,y0+rect_height - (rect_height * fraction));
45  cairo_line_to (w->crb, x0+rect_width-3 ,y0+rect_height - (rect_height * fraction));
46  if (i<6)
47  {
48  snprintf (buf, sizeof (buf), "%d", db_points[i]);
49  cairo_move_to (w->crb, x0+rect_width*0.1,y0+rect_height - (rect_height * fraction)-3);
50  }
51  else if (i<8)
52  {
53  snprintf (buf, sizeof (buf), "%d", db_points[i]);
54  cairo_move_to (w->crb, x0+rect_width*0.2,y0+rect_height - (rect_height * fraction)-3);
55  }
56  else
57  {
58  snprintf (buf, sizeof (buf), " %d", db_points[i]);
59  cairo_move_to (w->crb, x0+rect_width*0.21,y0+rect_height - (rect_height * fraction)-3);
60  }
61  cairo_show_text (w->crb, buf);
62  }
63 
64  cairo_set_source_rgb(w->crb, 0.6, 0.6, 0.6);
65  cairo_set_line_width(w->crb, 2.0);
66  cairo_stroke(w->crb);
67 }
68 
69 void _draw_hmeter_scale(void *w_, void* user_data) {
70  Widget_t *w = (Widget_t*)w_;
71  XWindowAttributes attrs;
72  XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
73  int rect_width = attrs.width;
74  int rect_height = attrs.height;
75  double x0 = 0;
76  double y0 = 0;
77 
78  int db_points[] = { -50, -40, -30, -20, -15, -10, -6, -3, 0, 3 };
79  char buf[32];
80 
81  cairo_set_font_size (w->crb, (float)rect_height/2);
82  cairo_set_source_rgba(w->crb, 0.6, 0.6, 0.6, 0.6);
83 
84  for (unsigned int i = 0; i < sizeof (db_points)/sizeof (db_points[0]); ++i)
85  {
86  float fraction = _log_meter(db_points[i]);
87  //cairo_set_source_rgb (w->crb,0.32 + 0.22*i/2,0.5 + 0.1*i/2, 0.1);
88 
89  cairo_move_to (w->crb, x0+(rect_width * fraction),y0+rect_height*0.1);
90  cairo_line_to (w->crb, x0+(rect_width * fraction) ,y0+rect_height*0.6);
91  if (i<6)
92  {
93  snprintf (buf, sizeof (buf), "%d", db_points[i]);
94  cairo_move_to (w->crb, x0+(rect_width * fraction)+3,y0+rect_height);
95  }
96  else
97  {
98  snprintf (buf, sizeof (buf), " %d", db_points[i]);
99  cairo_move_to (w->crb, x0+(rect_width * fraction)+3,y0+rect_height );
100  }
101  cairo_show_text (w->crb, buf);
102  }
103 
104  cairo_set_source_rgba(w->crb, 0.6, 0.6, 0.6, 0.6);
105  cairo_set_line_width(w->crb, 1.5);
106  cairo_stroke(w->crb);
107 }
108 
109 float _log_meter (float db) {
110  float def = 0.0f; /* Meter deflection %age */
111 
112  if (db < -70.0f) {
113  def = 0.0f;
114  } else if (db < -60.0f) {
115  def = (db + 70.0f) * 0.25f;
116  } else if (db < -50.0f) {
117  def = (db + 60.0f) * 0.5f + 2.5f;
118  } else if (db < -40.0f) {
119  def = (db + 50.0f) * 0.75f + 7.5f;
120  } else if (db < -30.0f) {
121  def = (db + 40.0f) * 1.5f + 15.0f;
122  } else if (db < -20.0f) {
123  def = (db + 30.0f) * 2.0f + 30.0f;
124  } else if (db < 6.0f) {
125  def = (db + 20.0f) * 2.5f + 50.0f;
126  } else {
127  def = 115.0f;
128  }
129 
130  /* 115 is the deflection %age that would be
131  when db=6.0. this is an arbitrary
132  endpoint for our scaling.
133  */
134 
135  return def/115.0f;
136 }
137 
138 void _create_vertical_meter_image(Widget_t *w, int width, int height) {
139  w->image = cairo_surface_create_similar (w->surface,
140  CAIRO_CONTENT_COLOR_ALPHA, width*2, height);
141  cairo_t *cri = cairo_create (w->image);
142 
143  cairo_rectangle(cri,0.0, 0.0, width, height);
145  cairo_fill(cri);
146 
147  cairo_rectangle(cri,width, 0.0, width, height);
149  cairo_fill(cri);
150 
151  cairo_pattern_t *pat = cairo_pattern_create_linear (0, 0, 0.0, height);
152  cairo_pattern_add_color_stop_rgba(pat, 1.0, 0.1, 0.5, 0.1, 0.4);
153  cairo_pattern_add_color_stop_rgba(pat, 0.2, 0.4, 0.4, 0.1, 0.4);
154  cairo_pattern_add_color_stop_rgba(pat, 0.0, 0.5, 0.0, 0.0, 0.4);
155  cairo_set_source(cri, pat);
156 
157  int c = (width)/2 ;
158  int ci = c-2;
159 
160  int i = 1;
161  int j = 1;
162  for(;i<height-3;) {
163  for(;j<width;) {
164  cairo_rectangle(cri,j,i,ci,2);
165  cairo_fill(cri);
166  j +=c;
167  }
168  i +=3;
169  j = 1;
170  }
171 
172  cairo_pattern_destroy (pat);
173  pat = cairo_pattern_create_linear (0, 0, 0.0, height);
174  cairo_pattern_add_color_stop_rgba(pat, 1.0, 0.1, 0.5, 0.1, 1);
175  cairo_pattern_add_color_stop_rgba(pat, 0.2, 0.4, 0.4, 0.1, 1);
176  cairo_pattern_add_color_stop_rgba(pat, 0.0, 0.5, 0.0, 0.0, 1);
177  cairo_set_source(cri, pat);
178  i = 1;
179  j = 1;
180  for(;i<height-3;) {
181  for(;j<width;) {
182  cairo_rectangle(cri,width+j,i,ci,2);
183  cairo_fill(cri);
184  j +=c;
185  }
186  i +=3;
187  j = 1;
188  }
189 
190  cairo_pattern_destroy (pat);
191  cairo_destroy(cri);
192 }
193 
194 void _create_horizontal_meter_image(Widget_t *w, int width, int height) {
195  w->image = cairo_surface_create_similar (w->surface,
196  CAIRO_CONTENT_COLOR_ALPHA, width, height*2);
197  cairo_t *cri = cairo_create (w->image);
198 
199  cairo_rectangle(cri,0.0, 0.0, width, height);
201  cairo_fill(cri);
202 
203  cairo_rectangle(cri, 0.0, height, width, height);
205  cairo_fill(cri);
206 
207  cairo_pattern_t *pat = cairo_pattern_create_linear (0, 0, width, 0.0);
208  cairo_pattern_add_color_stop_rgba(pat, 0.0, 0.1, 0.5, 0.1, 0.4);
209  cairo_pattern_add_color_stop_rgba(pat, 0.8, 0.4, 0.4, 0.1, 0.4);
210  cairo_pattern_add_color_stop_rgba(pat, 1.0, 0.5, 0.0, 0.0, 0.4);
211  cairo_set_source(cri, pat);
212 
213  int c = (height)/2 ;
214  int ci = c-2;
215 
216  int i = 1;
217  int j = 1;
218  for(;i<width;) {
219  for(;j<height;) {
220  cairo_rectangle(cri,i,j,2,ci);
221  cairo_fill(cri);
222  j +=c;
223  }
224  i +=3;
225  j = 1;
226  }
227 
228  cairo_pattern_destroy (pat);
229  pat = cairo_pattern_create_linear (0, 0, width, 0.0);
230  cairo_pattern_add_color_stop_rgba(pat, 0.0, 0.1, 0.5, 0.1, 1);
231  cairo_pattern_add_color_stop_rgba(pat, 0.8, 0.4, 0.4, 0.1, 1);
232  cairo_pattern_add_color_stop_rgba(pat, 1.0, 0.5, 0.0, 0.0, 1);
233  cairo_set_source(cri, pat);
234  i = 1;
235  j = 1;
236  for(;i<width;) {
237  for(;j<height;) {
238  cairo_rectangle(cri,i,height+j,2,ci);
239  cairo_fill(cri);
240  j +=c;
241  }
242  i +=3;
243  j = 1;
244  }
245 
246  cairo_pattern_destroy (pat);
247  cairo_destroy(cri);
248 }
249 
250 void _draw_v_meter(void *w_, void* user_data) {
251  Widget_t *w = (Widget_t*)w_;
252 
253  int width = cairo_xlib_surface_get_width(w->image);
254  int height = cairo_xlib_surface_get_height(w->image);
255  double meterstate = _log_meter(adj_get_value(w->adj_y));
256  double oldstate = _log_meter(w->adj_y->start_value);
257  widget_set_scale(w);
258  cairo_set_source_surface (w->crb, w->image, 0, 0);
259  cairo_rectangle(w->crb,0, 0, width/2, height);
260  cairo_fill(w->crb);
261  cairo_set_source_surface (w->crb, w->image, -width/2, 0);
262  cairo_rectangle(w->crb, 0, height, width/2, -height*meterstate);
263  cairo_fill(w->crb);
264 
265  cairo_rectangle(w->crb, 0, height-height*oldstate, width/2, 3);
266  cairo_fill(w->crb);
268 }
269 
270 void _draw_h_meter(void *w_, void* user_data) {
271  Widget_t *w = (Widget_t*)w_;
272 
273  int width = cairo_xlib_surface_get_width(w->image);
274  int height = cairo_xlib_surface_get_height(w->image);
275  double meterstate = _log_meter(adj_get_value(w->adj_x));
276  double oldstate = _log_meter(w->adj_x->start_value);
277  widget_set_scale(w);
278  cairo_set_source_surface (w->crb, w->image, 0, 0);
279  cairo_rectangle(w->crb,0, 0, width, height/2);
280  cairo_fill(w->crb);
281  cairo_set_source_surface (w->crb, w->image, 0, -height/2);
282  cairo_rectangle(w->crb, 0, 0, width*meterstate, height/2);
283  cairo_fill(w->crb);
284 
285  cairo_rectangle(w->crb,(width*oldstate)-3, 0, 3, height/2);
286  cairo_fill(w->crb);
287 
289 }
_log_meter
float _log_meter(float db)
_log_meter - logaritmic meter deflection
Definition: xmeter_private.c:109
xmeter_private.h
Widget_t::image
cairo_surface_t * image
Definition: xwidget.h:320
use_shadow_color_scheme
void use_shadow_color_scheme(Widget_t *w, Color_state st)
use_shadow_color_scheme - use shadow Colors to paint on Widget_t
Definition: xcolor.c:206
widget_set_scale
void widget_set_scale(Widget_t *w)
widget_set_scale - set scaling mode to scale a image surface to the size of the Widget_t surface
Definition: xwidget.c:141
adj_get_value
float adj_get_value(Adjustment_t *adj)
adj_get_value - get the current value of the Adjustment_t
Definition: xadjustment.c:154
_create_vertical_meter_image
void _create_vertical_meter_image(Widget_t *w, int width, int height)
_create_vertical_meter_image - internal draw the meter image to the cairo image surface
Definition: xmeter_private.c:138
_create_horizontal_meter_image
void _create_horizontal_meter_image(Widget_t *w, int width, int height)
_create_horizontal_meter_image - internal draw the meter image to the cairo image surface
Definition: xmeter_private.c:194
Widget_t::crb
cairo_t * crb
Definition: xwidget.h:318
_draw_vmeter_scale
void _draw_vmeter_scale(void *w_, void *user_data)
_draw_meter_scale - draw a meter scale beside the meter widget
Definition: xmeter_private.c:25
Widget_t::app
Xputty * app
Definition: xwidget.h:300
Xputty::dpy
Display * dpy
Definition: xputty.h:181
Widget_t::widget
Window widget
Definition: xwidget.h:302
Widget_t
Widget_t - struct to hold the basic Widget_t info.
Definition: xwidget.h:298
NORMAL_
@ NORMAL_
Definition: xcolor.h:39
_draw_hmeter_scale
void _draw_hmeter_scale(void *w_, void *user_data)
_draw_hmeter_scale - draw a hmeter scale beside the meter widget
Definition: xmeter_private.c:69
widget_reset_scale
void widget_reset_scale(Widget_t *w)
widget_reset_scale - used to reset scaling mode after a image surface is drawn to the Widget_t surfac...
Definition: xwidget.c:137
Widget_t::surface
cairo_surface_t * surface
Definition: xwidget.h:312
Widget_t::adj_y
Adjustment_t * adj_y
Definition: xwidget.h:332
Adjustment_t::start_value
float start_value
Definition: xadjustment.h:94
Widget_t::adj_x
Adjustment_t * adj_x
Definition: xwidget.h:330
_draw_v_meter
void _draw_v_meter(void *w_, void *user_data)
_draw_v_meter - internal draw the meter to the buffer
Definition: xmeter_private.c:250
_draw_h_meter
void _draw_h_meter(void *w_, void *user_data)
_draw_h_meter - internal draw the meter to the buffer
Definition: xmeter_private.c:270