Add Russian translation provided by Валерий Крувялис <valkru@mail.ru>
[xiph-mirror.git] / sushivision / plane-bg.c
blob80c6f462fa4c7f3c64e0e53baefb72d16ecca42e
1 /*
3 * sushivision copyright (C) 2006-2007 Monty <monty@xiph.org>
5 * sushivision 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, or (at your option)
8 * any later version.
9 *
10 * sushivision 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.
15 * You should have received a copy of the GNU General Public License
16 * along with sushivision; see the file COPYING. If not, write to the
17 * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 #define _GNU_SOURCE
23 #include <string.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <math.h>
28 #include <signal.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <gtk/gtk.h>
32 #include <cairo-ft.h>
33 #include "internal.h"
35 // the background 'plane' is handled a little differently from the
36 // other planes. The bg plane doesn't bother with functions embedded
37 // in the plane struct. They're simply called directly by the panel
38 // code.
40 void bg_recompute_setup(sv_panel_t *p){
41 sv_planebg_t *pl = p->bg;
43 pl->image_x = _sv_dim_panelscale(payload + x_dim, p->w, 0);
44 pl->image_y = _sv_dim_panelscale(payload + y_dim, p->h, 1);
45 pl->image_task = 0;
46 pl->expose_top = -1;
47 pl->expose_bottom = -1;
50 void bg_resize(sv_panel_t *p){
51 sv_planebg_t *pl = p->bg;
53 if(pl->image_status_size != p->h){
54 unsigned char *n=NULL;
55 unsigned char *o=NULL;
56 int serialno = p->comp_serialno;
58 pthread_mutex_unlock(pl->status_m);
59 n = calloc(p->h,sizeof(*n));
60 pthread_mutex_lock(pl->status_m);
61 if(serialno == p->comp_serialno){
62 o = pl->image_status;
63 pl->image_status = n;
64 n = NULL;
66 pthread_mutex_unlock(pl->status_m);
67 if(n)free(n);
68 if(o)free(o);
69 pthread_mutex_lock(pl->status_m);
70 return STATUS_WORKING;
73 return STATUS_IDLE;
76 int bg_legend(sv_panel_t *p){
77 sv_planebg_t *bg = &p->bg;
78 sv_plot_t *plot = p->plot;
79 int serialno = p->legend_serialno;
81 if(plot){
82 int i,j;
83 char buffer[320];
84 int depth = 0;
86 pthread_mutex_unlock(p->status_m);
87 _sv_plot_legend_clear(plot);
88 pthread_mutex_lock(p->status_m);
89 if(serialno != p->legend_serialno)return STATUS_WORKING;
91 // potentially add each dimension to the legend; add axis
92 // dimensions only if crosshairs are active
94 // display decimal precision relative to display scales
95 if(3-_sv_scalespace_decimal_exponent(&bg->image_x) > depth)
96 depth = 3-_sv_scalespace_decimal_exponent(&bg->image_x);
97 if(3-_sv_scalespace_decimal_exponent(&bg->image_y) > depth)
98 depth = 3-_sv_scalespace_decimal_exponent(&bg->image_y);
99 for(i=0;i<p->dimensions;i++){
100 sv_dim_data_t *d = p->dim_data+i;
101 int flag=0;
102 for(j=0;j<p->axes;j++)
103 if(p->axis_dims[j] != i &&
104 (j<=2 || !p->cross_active)){
105 flag=1;
106 break;
109 if(!flag){
110 snprintf(buffer,320,"%s = %+.*f",
111 d->legend,
112 depth,
113 d->val);
114 pthread_mutex_unlock(p->status_m);
115 _sv_plot_legend_add(plot,buffer);
116 pthread_mutex_lock(p->status_m);
117 if(serialno != p->legend_serialno)return STATUS_WORKING;
121 // add each active objective plane to the legend
122 // choose the value under the crosshairs
123 if(plot->cross_active){
124 // ask each plane for entries...
125 int firstflag=0;
126 for(i=0;i<p->planes;i++){
127 int retflag=p->plane_list[i]->legend(p->plane_list[i],buffer,320);
128 pthread_mutex_unlock(p->status_m);
129 if(retflag && !firstflag)
130 _sv_plot_legend_add(plot,NULL);
131 firstflag|=retflag;
132 _sv_plot_legend_add(plot,buffer);
133 pthread_mutex_lock(p->status_m);
134 if(serialno != p->legend_serialno)return STATUS_WORKING;
139 pthread_mutex_unlock(p->status_m);
140 _sv_plot_draw_legend(plot);
141 pthread_mutex_lock(p->status_m);
142 if(serialno != p->legend_serialno)return STATUS_WORKING;
144 return STATUS_IDLE;
147 int bg_scale(sv_panel_t *p){
148 pthread_mutex_unlock(p->status_m);
149 _sv_plot_draw_scales(p->graph);
150 pthread_mutex_lock(p->status_m);
153 static void render_checks(sv_ucolor_t *c, int w, int y){
154 /* default checked background */
155 /* 16x16 'mid-checks' */
156 int x,j;
158 int phase = (y>>4)&1;
159 for(x=0;x<w;){
160 u_int32_t phaseval = 0xff505050UL;
161 if(phase) phaseval = 0xff808080UL;
162 for(j=0;j<16 && x<w;j++,x++)
163 c[x].u = phaseval;
164 phase=!phase;
168 int bg_render(sv_panel_t *p){
169 sv_planebg_t *bg = &p->bg;
170 sv_plot_t *plot = p->plot;
171 int serialno = p->compute_serialno;
172 int w = p->w,y;
173 int h = p->h;
174 sv_ucolor_t line[w];
176 int bgtype=0;
177 double r;
178 double g;
179 double b;
181 if(bg->bg[0]=='#' && strlen(bg->bg)==7){
182 bgtype=1;
183 r = (toupper(bg->bg[1])-65)*.0625 + (toupper(bg->bg[2])-65)*.00390625;
184 g = (toupper(bg->bg[3])-65)*.0625 + (toupper(bg->bg[4])-65)*.00390625;
185 b = (toupper(bg->bg[5])-65)*.0625 + (toupper(bg->bg[6])-65)*.00390625;
188 // look for a line that needs love
190 y = bg->image_nextline;
191 bg->image_nextline++;
192 if(bg->image_nextline>=h)bg->image_nextline=0;
194 if(bg->image_flags[y]){
195 sv_scalespace_t ix = bg->image_x;
196 sv_scalespace_t iy = bg->image_y;
198 // render this line
199 bg->image_flags[i]=0;
200 bg->image_outstanding++;
202 pthread_mutex_unlock(p->status_m);
204 // bg renders a line at a time primarily as a concession to the 2d panels.
205 if(bgtype==0){
206 render_checks(line,w,y);
207 }else{
208 u_int32_t val = 0xff000000 | (r<<16) | (g<<8) | (b);
209 for(i=0;i<w;i++)line[i]=val;
212 // grab line from panels in order. Mix using plane native mix function
213 for(i=0;i<p->planes;i++){
214 sv_ucolor_t *mix(sv_ucolor_t, sv_ucolor_t) = p->plane_list[i]->c.mix;
215 sv_ucolor_t *pline = p->plane_list[i]->c.image[y*w]l
216 for(j=0;j<w;j++)
217 line[j] = mix(pline[j],line[j]);
220 pthread_mutex_lock(pl->status_m);
222 if(p->compute_serialno == serialno){
223 bg->image_outstanding--;
225 plot_write_line(p->plot,line);
227 //invalidate rectangle for expose
228 if(bg->expose_top == -1 || bg->expose_top > y)
229 bg->expose_top=y;
230 if(bg->expose_bottom == -1 || bg->expose_bottom < y)
231 bg->expose_bottom=y;
233 return STATUS_WORKING;
235 }while(i!=last);
237 if(bg->image_outstanding) return STATUS_BUSY;
238 return STATUS_IDLE;
241 int bg_expose(sv_panel_t *p){
242 sv_planebg_t *bg = &p->bg;
243 if(pl->expose_top != -1){
244 GdkRectangle r;
245 r.y = bg->expose_top;
246 r.h = bg->expose_bottom - bg->expose_top+1;
247 rx = 0;
248 r.w = p->w;
250 pl->expose_top = -1;
251 pl->expose_bottom = -1;
252 pthread_mutex_unlock(p->status_m);
254 // the only place worker thread should ever touch the GDK lock
255 gdk_threads_enter();
256 gdk_invalidate_rectangle(GTK_WIDGET(p->plot),&r,FALSE);
257 gdk_threads_leave();
261 return STATUS_IDLE;
264 sv_planebg_t *sv_planebg_new(sv_panel_t *p){
265 sv_planebg_t *ret = calloc(1, sizeof(*ret));
267 ret->panel=p;
268 ret->bg = strdup("checks");
269 return(ret);