[xiph-commits] r14011 - trunk/sushivision
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Thu Oct 18 07:32:31 PDT 2007
Author: xiphmont
Date: 2007-10-18 07:32:30 -0700 (Thu, 18 Oct 2007)
New Revision: 14011
Added:
trunk/sushivision/panelmenu.c
Modified:
trunk/sushivision/panel.c
trunk/sushivision/panel.h
trunk/sushivision/plane-2d.c
trunk/sushivision/plane-bg.c
trunk/sushivision/spinner.c
trunk/sushivision/spinner.h
trunk/sushivision/sushivision.h
trunk/sushivision/toplevel.c
Log:
More work in progress
Modified: trunk/sushivision/panel.c
===================================================================
--- trunk/sushivision/panel.c 2007-10-18 07:39:37 UTC (rev 14010)
+++ trunk/sushivision/panel.c 2007-10-18 14:32:30 UTC (rev 14011)
@@ -112,10 +112,6 @@
return pl->c.data_work(pl, p);
}
-#define STATUS_IDLE 0
-#define STATUS_BUSY 1
-#define STATUS_WORKING 2
-
static int plane_loop(sv_panel_t *p, int *next,
int(*function)(_sv_plane_t *,
sv_panel_t *)){
@@ -161,9 +157,8 @@
// recomute setup
// plane recompute calls will do nothing if recomputation is not
- // required. Even if computation not required, will still request
- // an image resize; the image resize code will later noop if there's
- // no need to resize either.
+ // required. Even if computation not required, may still request
+ // an image resize/resample
if(p->recompute_pending){
p->recompute_pending=0;
p->comp_serialno++;
@@ -174,7 +169,7 @@
p->bgrender=0;
p->image_next_plane=0;
- bg->c.recompute_setup(p->bg, p);
+ bg_recompute_setup(p);
for(i=0;i<p->planes;i++)
p->plane_list[i]->c.recompute_setup(p->plane_list[i], p);
@@ -192,15 +187,22 @@
serialno = p->comp_serialno;
- // image resize
+ // bg/image resize
+ // image resizes assume bg resize has completed
+ if(p->bg_resize){
+ status = bg_resize(p);
+ if(status == STATUS_WORKING) return done_working(p);
+ if(status == STATUS_BUSY) return done_busy(p);
+ p->bg_resize=0;
+ }
- // again, each plane checks to see if a resize is really necessary. If not, does nothing.
+ // image resize
if(p->image_resize){
status = plane_loop(p,&p->image_next_plane,image_resize);
if(status == STATUS_WORKING) return done_working(p);
if(status == STATUS_IDLE){
p->image_resize = 0;
- p->bgrender = 1;
+ p->bg_render = 1;
}
}
@@ -230,7 +232,7 @@
if(p->bg_render){
if(bg_render(p) == STATUS_IDLE){
p->expose=1;
- p->bgrender=0;
+ p->bg_render=0;
}
return done_working(p);
}
@@ -260,7 +262,10 @@
if(p->map_render){
status = plane_loop(p,&p->image_next_plane,image_work);
if(status == STATUS_WORKING) return done_working(p);
- if(status == STATUS_IDLE) p->map_render = 0;
+ if(status == STATUS_IDLE){
+ p->map_render = 0;
+ p->bg_render = 1;
+ }
}
// computation work
@@ -269,707 +274,6 @@
return done_idle(p);
}
-
-
-static int _sv_plane2d_compute_one(){
-
-}
-
-static int _sv_plane2d_map_one(){
-
-}
-
-// work order: resize/fast scale -> compute -> plane_render -> composite
-
-// enter unlocked
-static void _sv_planez_compute_line(sv_panel_t *p,
- _sv_plane2d_t *z,
-
- int serialno,
-
- int dw,
- int y,
- int x_d,
- _sv_scalespace_t sxi,
- double *dim_vals,
- _sv_bythread_cache_2d_t *c){
-
- _sv_panel2d_t *p2 = p->subtype->p2;
- int i,j;
-
- /* cache access is unlocked because the cache is private to this
- worker thread */
-
- for(j=0;j<dw;j++){
- double *fout = c->fout;
- sv_func_t **f = p2->used_function_list;
- int *obj_y_off = p2->y_fout_offset;
- int *onum = p2->y_obj_to_panel;
-
- /* by function */
- dim_vals[x_d] = _sv_scalespace_value(&sxi,j);
- for(i=0;i<p2->used_functions;i++){
- (*f)->callback(dim_vals,fout);
- fout += (*f)->outputs;
- f++;
- }
-
- /* process function output by plane type/objective */
- /* 2d panels currently only care about the Y output value */
-
- /* slider map */
- for(i=0;i<p2->y_obj_num;i++){
- float val = (float)_sv_slider_val_to_del(p2->range_scales[*onum++], c->fout[*obj_y_off++]);
- if(isnan(val)){
- c->y_map[i][j] = -1;
- }else{
- if(val<0)val=0;
- if(val>1)val=1;
- c->y_map[i][j] = rint(val * (256.f*256.f*256.f));
- }
- }
- }
-
- gdk_lock ();
- if(p->private->plot_serialno == serialno){
- for(j=0;j<p2->y_obj_num;j++){
- int *d = p2->y_map[j] + y*dw;
- int *td = c->y_map[j];
-
- memcpy(d,td,dw*sizeof(*d));
-
- }
- }
- gdk_unlock ();
-}
-
-// call with lock
-static void _sv_panel2d_clear_pane(sv_panel_t *p){
-
- _sv_panel2d_t *p2 = p->subtype->p2;
- int pw = p2->x.pixels;
- int ph = p2->y.pixels;
- int i;
- _sv_plot_t *plot = PLOT(p->private->graph);
-
- for(i=0;i<p2->y_obj_num;i++){
- // map is freed and nulled to avoid triggering a fast-scale on an empty data pane
- if(p2->y_map[i])
- free(p2->y_map[i]);
- p2->y_map[i]=NULL;
-
- // free y_planes so that initial remap doesn't waste time on mix
- // op; they are recreated during remap at the point the y_todo
- // vector indicates something to do
- if(p2->y_planes[i])
- free(p2->y_planes[i]);
- p2->y_planes[i] = NULL;
-
- // work vector is merely cleared
- memset(p2->y_planetodo[i], 0, ph*sizeof(**p2->y_planetodo));
- }
-
- // clear the background surface
- if(plot->datarect)
- memset(plot->datarect, 0, ph*pw*sizeof(*plot->datarect));
-
- // the bg is not marked to be refreshed; computation setup will do
- // that as part of the fast_scale, even if the fast_scale is
- // short-circuited to a noop.
-}
-
-typedef struct{
- double x;
- double y;
- double z;
-} compute_result;
-
-// used by the legend code. this lets us get away with having only a mapped display pane
-// call with lock
-static void _sv_panel2d_compute_point(sv_panel_t *p,sv_obj_t *o, double x, double y, compute_result *out){
- double dim_vals[_sv_dimensions];
- int i,j;
- int pflag=0;
- int eflag=0;
-
- // fill in dimensions
- int x_d = p->private->x_d->number;
- int y_d = p->private->y_d->number;
-
- for(i=0;i<_sv_dimensions;i++){
- sv_dim_t *dim = _sv_dimension_list[i];
- dim_vals[i]=dim->val;
- }
-
- gdk_unlock ();
-
- dim_vals[x_d] = x;
- dim_vals[y_d] = y;
-
- *out = (compute_result){NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN};
-
- // compute
- for(i=0;i<_sv_functions;i++){
- sv_func_t *f = _sv_function_list[i];
- int compflag = 0;
- double fout[f->outputs];
- double val;
-
- // compute and demultiplex output
- for(j=0;j<o->outputs;j++){
- if(o->function_map[j] == i){
-
- if(!compflag) f->callback(dim_vals,fout);
- compflag = 1;
-
- val = fout[o->output_map[j]];
- switch(o->output_types[j]){
- case 'X':
- out->x = val;
- break;
- case 'Y':
- out->y = val;
- break;
- case 'Z':
- out->z = val;
- break;
- case 'E':
- if(eflag)
- out->e2 = val;
- else
- out->e1 = val;
- eflag = 1;
- break;
- case 'P':
- if(pflag)
- out->p2 = val;
- else
- out->p1 = val;
- pflag = 1;
- break;
- case 'M':
- out->m = val;
- break;
- }
- }
- }
- }
- gdk_lock ();
-
-}
-
-/* functions that perform actual graphical rendering */
-
-static float _sv_panel2d_resample_helpers_init(_sv_scalespace_t *to, _sv_scalespace_t *from,
- unsigned char *delA, unsigned char *delB,
- int *posA, int *posB,
- int xymul){
- int i;
- int dw = from->pixels;
- int pw = to->pixels;
-
- long scalenum = _sv_scalespace_scalenum(to,from);
- long scaleden = _sv_scalespace_scaleden(to,from);
- long del = _sv_scalespace_scaleoff(to,from);
- int bin = del / scaleden;
- del -= bin * scaleden;
- int discscale = (scaleden>scalenum?scalenum:scaleden);
- int total = xymul*scalenum/discscale;
-
- for(i=0;i<pw;i++){
- long del2 = del + scalenum;
- int sizeceil = (del2 + scaleden - 1)/ scaleden; // ceiling
- int sizefloor = del2 / scaleden;
-
- while(bin<0 && del2>scaleden){
- bin++;
- del = 0;
- del2 -= scaleden;
- sizeceil--;
- }
-
- if(del2 > scaleden && bin>=0 && bin<dw){
- int rem = total;
-
- delA[i] = ((xymul * (scaleden - del)) + (discscale>>1)) / discscale;
- posA[i] = bin;
- rem -= delA[i];
- rem -= xymul*(sizeceil-2);
-
- while(bin+sizeceil>dw){
- sizeceil--;
- del2=0;
- }
-
- del2 %= scaleden;
- if(rem<0){
- delA[i] += rem;
- delB[i] = 0;
- }else{
- delB[i] = rem; // don't leak
- }
- posB[i] = bin+sizeceil;
-
- }else{
- if(bin<0 || bin>=dw){
- delA[i] = 0;
- posA[i] = 0;
- delB[i] = 0;
- posB[i] = 0;
- }else{
- delA[i] = xymul;
- posA[i] = bin;
- delB[i] = 0;
- posB[i] = bin+1;
- if(del2 == scaleden)del2=0;
- }
- }
-
- bin += sizefloor;
- del = del2;
- }
- return (float)xymul/total;
-}
-
-/* x resample helpers are put in the per-thread cache because locking it would
- be relatively expensive. */
-// call while locked
-static void _sv_panel2d_resample_helpers_manage_x(sv_panel_t *p, _sv_bythread_cache_2d_t *c){
- _sv_panel2d_t *p2 = p->subtype->p2;
- if(p->private->plot_serialno != c->serialno){
- int pw = p2->x.pixels;
- c->serialno = p->private->plot_serialno;
-
- if(c->xdelA)
- free(c->xdelA);
- if(c->xdelB)
- free(c->xdelB);
- if(c->xnumA)
- free(c->xnumA);
- if(c->xnumB)
- free(c->xnumB);
-
- c->xdelA = calloc(pw,sizeof(*c->xdelA));
- c->xdelB = calloc(pw,sizeof(*c->xdelB));
- c->xnumA = calloc(pw,sizeof(*c->xnumA));
- c->xnumB = calloc(pw,sizeof(*c->xnumB));
- c->xscalemul = _sv_panel2d_resample_helpers_init(&p2->x, &p2->x_v, c->xdelA, c->xdelB, c->xnumA, c->xnumB, 17);
- }
-}
-
-/* y resample is in the panel struct as per-row access is already locked */
-// call while locked
-static void _sv_panel2d_resample_helpers_manage_y(sv_panel_t *p){
- _sv_panel2d_t *p2 = p->subtype->p2;
- if(p->private->plot_serialno != p2->resample_serialno){
- int ph = p2->y.pixels;
- p2->resample_serialno = p->private->plot_serialno;
-
- if(p2->ydelA)
- free(p2->ydelA);
- if(p2->ydelB)
- free(p2->ydelB);
- if(p2->ynumA)
- free(p2->ynumA);
- if(p2->ynumB)
- free(p2->ynumB);
-
- p2->ydelA = calloc(ph,sizeof(*p2->ydelA));
- p2->ydelB = calloc(ph,sizeof(*p2->ydelB));
- p2->ynumA = calloc(ph,sizeof(*p2->ynumA));
- p2->ynumB = calloc(ph,sizeof(*p2->ynumB));
- p2->yscalemul = _sv_panel2d_resample_helpers_init(&p2->y, &p2->y_v, p2->ydelA, p2->ydelB, p2->ynumA, p2->ynumB, 15);
- }
-}
-
-static inline void _sv_panel2d_mapping_calc( void (*m)(int,int, _sv_lcolor_t *),
- int low,
- float range,
- int in,
- int alpha,
- int mul,
- _sv_lcolor_t *outc){
- if(mul && in>=alpha){
- int val = rint((in - low) * range);
- if(val<0)val=0;
- if(val>65536)val=65536;
- m(val,mul,outc);
- }
-}
-
-/* the data rectangle is data width/height mapped deltas. we render
- and subsample at the same time. */
-/* return: -1 == abort
- 0 == more work to be done in this plane
- 1 == plane fully dispatched (possibly not complete) */
-
-/* enter with lock */
-static int _sv_panel2d_resample_render_y_plane_line(sv_panel_t *p, _sv_bythread_cache_2d_t *c,
- int plot_serialno, int map_serialno, int y_no){
-
- _sv_panel2d_t *p2 = p->subtype->p2;
- int objnum = p2->y_obj_to_panel[y_no];
- int *in_data = p2->y_map[y_no];
- int ph = p2->y.pixels;
-
- if(!in_data || !c){
- p->private->map_complete_count -= ph;
- return 1;
- }
-
- unsigned char *todo = p2->y_planetodo[y_no];
- int i = p2->y_next_line;
- int j;
-
- /* find a row that needs to be updated */
- while(i<ph && !todo[i]){
- p->private->map_complete_count--;
- p2->y_next_line++;
- i++;
- }
-
- if(i == ph) return 1;
-
- p2->y_next_line++;
-
- /* row [i] needs to be updated; marshal */
- _sv_mapping_t *map = p2->mappings+objnum;
- void (*mapfunc)(int,int, _sv_lcolor_t *) = map->mapfunc;
- int ol_alpha = rint(p2->alphadel[y_no] * 16777216.f);
- _sv_ucolor_t *panel = p2->y_planes[y_no];
- int ol_low = rint(map->low * 16777216.f);
- float ol_range = map->i_range * (1.f/256.f);
-
- int pw = p2->x.pixels;
- int dw = p2->x_v.pixels;
- int dh = p2->y_v.pixels;
- _sv_ccolor_t work[pw];
-
- if(!panel)
- panel = p2->y_planes[y_no] = calloc(pw*ph, sizeof(**p2->y_planes));
-
- if(ph!=dh || pw!=dw){
- /* resampled row computation; may involve multiple data rows */
-
- _sv_panel2d_resample_helpers_manage_y(p);
- _sv_panel2d_resample_helpers_manage_x(p,c);
-
- float idel = p2->yscalemul * c->xscalemul;
-
- /* by column */
- int ydelA=p2->ydelA[i];
- int ydelB=p2->ydelB[i];
- int ystart=p2->ynumA[i];
- int yend=p2->ynumB[i];
- int lh = yend - ystart;
- int data[lh*dw];
-
- memcpy(data,in_data+ystart*dw,sizeof(data));
-
- gdk_unlock();
-
- unsigned char *xdelA = c->xdelA;
- unsigned char *xdelB = c->xdelB;
- int *xnumA = c->xnumA;
- int *xnumB = c->xnumB;
-
- /* by panel col */
- for(j=0;j<pw;j++){
-
- _sv_lcolor_t out = (_sv_lcolor_t){0,0,0,0};
- int xstart = xnumA[j];
- int xend = xnumB[j];
- int dx = xstart;
- int xA = xdelA[j];
- int xB = xdelB[j];
- int y = ystart;
-
- // first line
- if(y<yend){
- if(dx<xend)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx++], ol_alpha, ydelA*xA, &out);
-
- for(; dx < xend-1; dx++)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx], ol_alpha, ydelA*17, &out);
-
- if(dx<xend)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx], ol_alpha, ydelA*xB, &out);
- y++;
- }
-
- // mid lines
- for(;y<yend-1;y++){
- dx = xstart += dw;
- xend += dw;
- if(dx<xend)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx++], ol_alpha, 15*xA, &out);
-
- for(; dx < xend-1; dx++)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx], ol_alpha, 255, &out);
-
- if(dx<xend)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx], ol_alpha, 15*xB, &out);
- }
-
- // last line
- if(y<yend){
- dx = xstart += dw;
- xend += dw;
- if(dx<xend)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx++], ol_alpha, ydelB*xA, &out);
-
- for(; dx < xend-1; dx++)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx], ol_alpha, ydelB*17, &out);
-
- if(dx<xend)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx], ol_alpha, ydelB*xB, &out);
- }
-
- work[j].a = (u_int32_t)(out.a*idel);
- work[j].r = (u_int32_t)(out.r*idel);
- work[j].g = (u_int32_t)(out.g*idel);
- work[j].b = (u_int32_t)(out.b*idel);
-
- }
-
- }else{
- /* non-resampling render */
-
- int data[dw];
- memcpy(data,in_data+i*dw,sizeof(data));
- gdk_unlock();
-
- for(j=0;j<pw;j++){
-
- _sv_lcolor_t out = (_sv_lcolor_t){0,0,0,0};
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[j], ol_alpha, 255, &out);
-
- work[j].a = (u_int32_t)(out.a);
- work[j].r = (u_int32_t)(out.r);
- work[j].g = (u_int32_t)(out.g);
- work[j].b = (u_int32_t)(out.b);
- }
- }
-
- gdk_lock ();
- if(plot_serialno != p->private->plot_serialno ||
- map_serialno != p->private->map_serialno)
- return -1;
- memcpy(panel+i*pw,work,sizeof(work));
- p2->bg_todo[i] = 1;
- p2->y_planetodo[y_no][i] = 0;
-
- // must be last; it indicates completion
- p->private->map_complete_count--;
- return 0;
-}
-
-static void render_checks(_sv_ucolor_t *c, int w, int y){
- /* default checked background */
- /* 16x16 'mid-checks' */
- int x,j;
-
- int phase = (y>>4)&1;
- for(x=0;x<w;){
- u_int32_t phaseval = 0xff505050UL;
- if(phase) phaseval = 0xff808080UL;
- for(j=0;j<16 && x<w;j++,x++)
- c[x].u = phaseval;
- phase=!phase;
- }
-}
-
-// enter with lock
-static int _sv_panel2d_render_bg_line(sv_panel_t *p, int plot_serialno, int map_serialno){
- _sv_panel2d_t *p2 = p->subtype->p2;
- _sv_plot_t *plot = PLOT(p->private->graph);
- if(plot_serialno != p->private->plot_serialno ||
- map_serialno != p->private->map_serialno) return -1;
-
- int ph = p2->y.pixels;
- int pw = p2->x.pixels;
- unsigned char *todo = p2->bg_todo;
- int i = p2->bg_next_line,j;
- _sv_ucolor_t work_bg[pw];
- _sv_ucolor_t work_pl[pw];
- int bgmode = p->private->bg_type;
-
- /* find a row that needs to be updated */
- while(i<ph && !todo[i]){
- p->private->map_complete_count--;
- p2->bg_next_line++;
- i++;
- }
-
- if(i == ph)
- goto done;
-
- if(i < p2->bg_first_line) p2->bg_first_line = i;
- if(i+1 > p2->bg_last_line) p2->bg_last_line = i+1;
- p2->bg_next_line++;
-
- /* gray background checks */
- gdk_unlock();
-
- switch(bgmode){
- case SV_BG_WHITE:
- for(j=0;j<pw;j++)
- work_bg[j].u = 0xffffffffU;
- break;
- case SV_BG_BLACK:
- for(j=0;j<pw;j++)
- work_bg[j].u = 0xff000000U;
- break;
- default:
- render_checks(work_bg,pw,i);
- break;
- }
-
- /* by objective */
- for(j=0;j<p->objectives;j++){
- int o_ynum = p2->y_obj_from_panel[j];
-
- gdk_lock();
- if(plot_serialno != p->private->plot_serialno ||
- map_serialno != p->private->map_serialno) return -1;
-
- /**** mix Y plane */
-
- if(p2->y_planes[o_ynum]){
- int x;
- _sv_ucolor_t (*mixfunc)(_sv_ucolor_t,_sv_ucolor_t) = p2->mappings[j].mixfunc;
- _sv_ucolor_t *rect = p2->y_planes[o_ynum] + i*pw;
- memcpy(work_pl,rect,sizeof(work_pl));
-
- gdk_unlock();
- for(x=0;x<pw;x++)
- work_bg[x] = mixfunc(work_pl[x],work_bg[x]);
- }else
- gdk_unlock();
-
- /**** mix Z plane */
-
- /**** mix vector plane */
-
- }
-
- gdk_lock();
- if(plot_serialno != p->private->plot_serialno ||
- map_serialno != p->private->map_serialno) return -1;
-
- // rendered a line, get it on the screen */
-
- memcpy(plot->datarect+pw*i, work_bg, sizeof(work_bg));
-
- p->private->map_complete_count--;
-
- done:
- if(p->private->map_complete_count)
- return 1; // not done yet
-
- return 0;
-}
-
-static void _sv_panel2d_mark_map_full(sv_panel_t *p);
-
-// enter with lock; returns zero if thread should sleep / get distracted
-static int _sv_panel2d_remap(sv_panel_t *p, _sv_bythread_cache_2d_t *thread_cache){
- _sv_panel2d_t *p2 = p->subtype->p2;
- _sv_plot_t *plot = PLOT(p->private->graph);
-
- if(!plot) goto abort;
- int ph = plot->y.pixels;
- int pw = plot->x.pixels;
-
- int plot_serialno = p->private->plot_serialno;
- int map_serialno = p->private->map_serialno;
-
- /* brand new remap indicated by the generic progress indicator being set to 0 */
- if(p->private->map_progress_count == 0){
-
- p->private->map_progress_count = 1; // 'in progress'
- p->private->map_complete_count = p2->y_obj_num * ph; // count down to 0; 0 indicates completion
-
- // set up Y plane rendering
- p2->y_next_plane = 0;
- p2->y_next_line = 0;
-
- // bg mix
- p2->bg_next_line = 0;
- p2->bg_first_line = ph;
- p2->bg_last_line = 0;
-
- if(!p2->partial_remap)
- _sv_panel2d_mark_map_full(p);
- }
-
- /* by plane, by line; each plane renders independently */
- /* Y planes */
- if(p2->y_planetodo){
- if(p2->y_next_plane < p2->y_obj_num){
- int status = _sv_panel2d_resample_render_y_plane_line(p, thread_cache,
- plot_serialno, map_serialno,
- p2->y_next_plane);
- if(status == -1) goto abort;
- if(status == 1){
- p2->y_next_plane++;
- p2->y_next_line = 0;
- }
- return 1;
- }
- }else{
- p->private->map_complete_count = 0;
- }
-
- /* renders have been completely dispatched, but are they complete? */
- /* the below is effectively a a thread join */
- if(p2->bg_next_line == 0){
-
- // join still needs to complete....
- if(p->private->map_complete_count){
- // nonzero complete count, not finished. returning zero will cause
- // this worker thread to sleep or go on to do other things.
- return 0;
- }else{
- // zero complete count, the planes are done; we can begin
- // background render. At least one thread is guaranteed to get
- // here, which is enough; we can now wake the others [if they were
- // asleep] and have them look for work here. */
- p->private->map_complete_count = ph; // [ph] lines to render in bg plane
- p2->bg_next_line = 0;
-
- _sv_wake_workers();
- }
- }
-
- /* mix new background, again line by line */
- if(p2->bg_next_line < ph){
- int status = _sv_panel2d_render_bg_line(p, plot_serialno, map_serialno);
- if(status == -1) goto abort;
- if(p->private->map_complete_count)return status;
- }else
- return 0; // nothing left to dispatch
-
- // entirely finished.
-
- // remap completed; flush background to screen
- _sv_plot_expose_request_partial (plot,0,p2->bg_first_line,
- pw,p2->bg_last_line - p2->bg_first_line);
- gdk_flush();
-
- // clean bg todo list
- memset(p2->bg_todo,0,ph*sizeof(*p2->bg_todo));
-
- // clear 'panel in progress' flag
- p2->partial_remap = 0;
- _sv_panel_clean_map(p);
- return 0;
-
- abort:
- // reset progress to 'start over'
- return 1;
-}
-
// looks like a cop-out but is actually the correct thing to do; the
// data *must* be WYSIWYG from panel display.
static void _sv_panel2d_print_bg(sv_panel_t *p, cairo_t *c){
@@ -1050,73 +354,6 @@
}
-// call while locked
-static void _sv_panel2d_mark_map_plane(sv_panel_t *p, int onum, int y, int z, int v){
- _sv_panel2d_t *p2 = p->subtype->p2;
- int ph = p2->y.pixels;
-
- if(y && p2->y_planetodo){
- int y_no = p2->y_obj_from_panel[onum];
- if(y_no>=0 && p2->y_planetodo[y_no])
- memset(p2->y_planetodo[y_no],1,ph * sizeof(**p2->y_planetodo));
- }
- p2->partial_remap = 1;
-}
-
-// call while locked
-static void _sv_panel2d_mark_map_line_y(sv_panel_t *p, int line){
- // determine all panel lines this y data line affects
- _sv_panel2d_t *p2 = p->subtype->p2;
- int ph = p2->y.pixels;
- int pw = p2->x.pixels;
- int dw = p2->x_v.pixels;
- int dh = p2->y_v.pixels;
- int i,j;
-
- p2->partial_remap = 1;
-
- if(ph!=dh || pw!=dw){
- /* resampled row computation; may involve multiple data rows */
- if(p2->y_planetodo){
- _sv_panel2d_resample_helpers_manage_y(p);
-
- for(i=0;i<ph;i++)
- if(p2->ynumA[i]<=line &&
- p2->ynumB[i]>line){
-
- for(j=0;j<p2->y_obj_num;j++)
- if(p2->y_planetodo[j])
- p2->y_planetodo[j][i]=1;
- }
- }
- }else{
- if(p2->y_planetodo)
- if(line>=0 && line<ph)
- for(j=0;j<p2->y_obj_num;j++)
- if(p2->y_planetodo[j])
- p2->y_planetodo[j][line]=1;
- }
-}
-
-// call while locked
-static void _sv_panel2d_mark_map_full(sv_panel_t *p){
- _sv_panel2d_t *p2 = p->subtype->p2;
- int ph = p2->y.pixels;
- int i,j;
-
- p2->partial_remap = 1;
-
- if(p2->y_planetodo){
- for(j=0;j<p2->y_obj_num;j++){
- if(p2->y_planetodo[j]){
- for(i=0;i<ph;i++){
- p2->y_planetodo[j][i]=1;
- }
- }
- }
- }
-}
-
// enter with lock
static void _sv_panel2d_update_legend(sv_panel_t *p){
_sv_panel2d_t *p2 = p->subtype->p2;
@@ -1304,177 +541,6 @@
return y<<1;
}
-// assumes data is locked
-static void _sv_panel2d_fast_scale_x(_sv_spinner_t *sp,
- int *data,
- int w,
- int h,
- _sv_scalespace_t new,
- _sv_scalespace_t old){
- int x,y;
- int work[w];
- int mapbase[w];
- int mapdel[w];
- double old_w = old.pixels;
- double new_w = new.pixels;
-
- double old_lo = _sv_scalespace_value(&old,0);
- double old_hi = _sv_scalespace_value(&old,old_w);
- double new_lo = _sv_scalespace_value(&new,0);
- double new_hi = _sv_scalespace_value(&new,new_w);
- double newscale = (new_hi-new_lo)/new_w;
- double oldscale = old_w/(old_hi-old_lo);
- for(x=0;x<w;x++){
- double xval = (x)*newscale+new_lo;
- double map = ((xval-old_lo)*oldscale);
- int base = (int)floor(map);
- int del = rint((map - floor(map))*64.f);
- /* hack to overwhelm roundoff error; this is inside a purely
- temporary cosmetic approximation anyway*/
- if(base>0 && del==0){
- mapbase[x]=base-1;
- mapdel[x]=64;
- }else{
- mapbase[x]=base;
- mapdel[x]=del;
- }
- }
-
- for(y=0;y<h;y++){
- int *data_line = data+y*w;
- _sv_spinner_set_busy(sp);
- for(x=0;x<w;x++){
- if(mapbase[x]<0 || mapbase[x]>=(w-1)){
- work[x]=-1;
- }else{
- int base = mapbase[x];
- int A = data_line[base];
- int B = data_line[base+1];
- if(A<0 || B<0)
- work[x]=-1;
- else
- work[x]= A + (((B - A)*mapdel[x])>>6);
-
- }
- }
- memcpy(data_line,work,w*(sizeof(*work)));
- }
-}
-
-static void _sv_panel2d_fast_scale_y(_sv_spinner_t *sp,
- int *olddata,
- int *newdata,
- int oldw,
- int neww,
- _sv_scalespace_t new,
- _sv_scalespace_t old){
- int x,y;
- int w = (oldw<neww?oldw:neww);
-
- int old_h = old.pixels;
- int new_h = new.pixels;
-
- int mapbase[new_h];
- int mapdel[new_h];
-
- double old_lo = _sv_scalespace_value(&old,0);
- double old_hi = _sv_scalespace_value(&old,(double)old_h);
- double new_lo = _sv_scalespace_value(&new,0);
- double new_hi = _sv_scalespace_value(&new,(double)new_h);
- double newscale = (new_hi-new_lo)/new_h;
- double oldscale = old_h/(old_hi-old_lo);
-
- for(y=0;y<new_h;y++){
- double yval = (y)*newscale+new_lo;
- double map = ((yval-old_lo)*oldscale);
- int base = (int)floor(map);
- int del = rint((map - floor(map))*64.);
- /* hack to overwhelm roundoff error; this is inside a purely
- temporary cosmetic approximation anyway */
- if(base>0 && del==0){
- mapbase[y]=base-1;
- mapdel[y]=64;
- }else{
- mapbase[y]=base;
- mapdel[y]=del;
- }
- }
-
-
- for(y=0;y<new_h;y++){
- int base = mapbase[y];
- int *new_column = &newdata[y*neww];
- _sv_spinner_set_busy(sp);
-
- if(base<0 || base>=(old_h-1)){
- for(x=0;x<w;x++)
- new_column[x] = -1;
- }else{
- int del = mapdel[y];
- int *old_column = &olddata[base*oldw];
-
- for(x=0;x<w;x++){
- int A = old_column[x];
- int B = old_column[x+oldw];
- if(A<0 || B<0)
- new_column[x]=-1;
- else
- new_column[x]= A + (((B-A)*del)>>6);
- }
- }
- }
-}
-
-static void _sv_panel2d_fast_scale(_sv_spinner_t *sp,
- int *newdata,
- _sv_scalespace_t xnew,
- _sv_scalespace_t ynew,
- int *olddata,
- _sv_scalespace_t xold,
- _sv_scalespace_t yold){
-
- int new_w = xnew.pixels;
- int new_h = ynew.pixels;
- int old_w = xold.pixels;
- int old_h = yold.pixels;
-
- if(new_w > old_w){
- _sv_panel2d_fast_scale_y(sp,olddata,newdata,old_w,new_w,ynew,yold);
- _sv_panel2d_fast_scale_x(sp,newdata,new_w,new_h,xnew,xold);
- }else{
- _sv_panel2d_fast_scale_x(sp,olddata,old_w,old_h,xnew,xold);
- _sv_panel2d_fast_scale_y(sp,olddata,newdata,old_w,new_w,ynew,yold);
- }
-}
-
-// call only from main gtk thread
-static void _sv_panel2d_mark_recompute(sv_panel_t *p){
- if(!p->private->realized) return;
- _sv_plot_t *plot = PLOT(p->private->graph);
-
- if(plot && GTK_WIDGET_REALIZED(GTK_WIDGET(plot))){
- _sv_panel_dirty_plot(p);
- }
-}
-
-static void _sv_panel2d_update_crosshairs(sv_panel_t *p){
- _sv_plot_t *plot = PLOT(p->private->graph);
- double x=0,y=0;
- int i;
-
- for(i=0;i<p->dimensions;i++){
- sv_dim_t *d = p->dimension_list[i].d;
- if(d == p->private->x_d)
- x = d->val;
- if(d == p->private->y_d)
- y = d->val;
-
- }
-
- _sv_plot_set_crosshairs(plot,x,y);
- _sv_panel_dirty_legend(p);
-}
-
static void _sv_panel2d_center_callback(sv_dim_list_t *dptr){
sv_dim_t *d = dptr->d;
sv_panel_t *p = dptr->p;
@@ -1580,45 +646,6 @@
_sv_panel_update_menus(p);
}
-void _sv_panel2d_maintain_cache(sv_panel_t *p, _sv_bythread_cache_2d_t *c, int w){
- _sv_panel2d_t *p2 = p->subtype->p2;
-
- /* toplevel initialization */
- if(c->fout == 0){
- int i,count=0;
-
- /* allocate output temporary buffer */
- for(i=0;i<p2->used_functions;i++){
- int fnum = p2->used_function_list[i]->number;
- sv_func_t *f = _sv_function_list[fnum];
- count += f->outputs;
- }
- c->fout = calloc(count, sizeof(*c->fout));
-
- /* objective line buffer index */
- c->y_map = calloc(p2->y_obj_num,sizeof(*c->y_map));
- for(i=0;i<p2->y_obj_num;i++)
- c->y_map[i] = calloc(w,sizeof(**c->y_map));
- c->storage_width = w;
- }
-
- /* anytime the data width changes */
- if(c->storage_width != w){
- int i;
- c->storage_width = w;
-
- for(i=0;i<p2->y_obj_num;i++)
- c->y_map[i] = realloc(c->y_map[i],w*sizeof(**c->y_map));
-
- }
-}
-
-
-// subtype entry point for plot remaps; lock held
-static int _sv_panel2d_map_redraw(sv_panel_t *p, _sv_bythread_cache_t *c){
- return _sv_panel2d_remap(p,&c->p2);
-}
-
// subtype entry point for legend redraws; lock held
static int _sv_panel2d_legend_redraw(sv_panel_t *p){
_sv_plot_t *plot = PLOT(p->private->graph);
@@ -1636,190 +663,6 @@
return 1;
}
-// subtype entry point for recomputation; lock held
-static int _sv_panel2d_compute(sv_panel_t *p,
- _sv_bythread_cache_t *c){
-
- _sv_panel2d_t *p2 = p->subtype->p2;
- _sv_plot_t *plot;
-
- int pw,ph,dw,dh,i,d;
- int serialno;
- double x_min, x_max;
- double y_min, y_max;
- int x_d=-1, y_d=-1;
- _sv_scalespace_t sx,sx_v,sx_i;
- _sv_scalespace_t sy,sy_v,sy_i;
-
- plot = PLOT(p->private->graph);
- pw = plot->x.pixels;
- ph = plot->y.pixels;
-
- x_d = p->private->x_d->number;
- y_d = p->private->y_d->number;
-
- // beginning of computation init
- if(p->private->plot_progress_count==0){
- int remapflag = 0;
-
- _sv_scalespace_t old_x = p2->x;
- _sv_scalespace_t old_y = p2->y;
- _sv_scalespace_t old_xv = p2->x_v;
- _sv_scalespace_t old_yv = p2->y_v;
-
- // generate new scales
- _sv_dim_scales(p->private->x_d,
- p->private->x_d->bracket[0],
- p->private->x_d->bracket[1],
- pw,pw * p->private->oversample_n / p->private->oversample_d,
- plot->scalespacing,
- p->private->x_d->legend,
- &sx,
- &sx_v,
- &sx_i);
- _sv_dim_scales(p->private->y_d,
- p->private->y_d->bracket[1],
- p->private->y_d->bracket[0],
- ph,ph * p->private->oversample_n / p->private->oversample_d,
- plot->scalespacing,
- p->private->y_d->legend,
- &sy,
- &sy_v,
- &sy_i);
-
- p2->x = sx;
- p2->x_v = sx_v;
- p2->x_i = sx_i;
- p2->y = sy;
- p2->y_v = sy_v;
- p2->y_i = sy_i;
-
- plot->x = sx;
- plot->y = sy;
- plot->x_v = sx_v;
- plot->y_v = sy_v;
-
- p->private->plot_progress_count++;
- p->private->plot_serialno++; // we're about to free the old data rectangles
-
- // realloc/fast scale the current data contents if appropriate
- if(memcmp(&sx_v,&old_xv,sizeof(sx_v)) || memcmp(&sy_v,&old_yv,sizeof(sy_v))){
-
- // maintain data planes
- for(i=0;i<p2->y_obj_num;i++){
- // allocate new storage
- int *newmap = calloc(sx_v.pixels*sy_v.pixels,sizeof(*newmap));
- int *oldmap = p2->y_map[i];
- int j;
-
- for(j=0;j<sx_v.pixels*sy_v.pixels;j++)
- newmap[j]=-1;
-
- // zoom scale data in map planes as placeholder for render
- if(oldmap){
- _sv_panel2d_fast_scale(p->private->spinner,newmap, sx_v, sy_v,
- oldmap,old_xv, old_yv);
- free(oldmap);
- }
- p2->y_map[i] = newmap;
- }
- remapflag = 1;
- }
-
- // realloc render planes if appropriate
- if(memcmp(&sx,&old_x,sizeof(sx)) || memcmp(&sy,&old_y,sizeof(sy))){
- for(i=0;i<p2->y_obj_num;i++){
-
- // y planes
- if(p2->y_planes[i])
- free(p2->y_planes[i]);
- p2->y_planes[i] = calloc(sx.pixels*sy.pixels,sizeof(**p2->y_planes));
-
- // todo lists
- if(p2->y_planetodo[i])
- free(p2->y_planetodo[i]);
- p2->y_planetodo[i] = calloc(sy.pixels,sizeof(**p2->y_planetodo));
-
- }
-
- if(p2->bg_todo)
- free(p2->bg_todo);
- p2->bg_todo=calloc(ph,sizeof(*p2->bg_todo));
-
- remapflag = 1;
- }
-
- if(remapflag){
- _sv_panel2d_mark_map_full(p);
- _sv_panel_dirty_map(p);
-
- gdk_unlock ();
- _sv_plot_draw_scales(plot); // this should happen outside lock
- gdk_lock ();
- }
-
- _sv_map_set_throttle_time(p); // swallow the first 'throttled' remap which would only be a single line;
-
- return 1;
- }else{
- sx = p2->x;
- sx_v = p2->x_v;
- sx_i = p2->x_i;
- sy = p2->y;
- sy_v = p2->y_v;
- sy_i = p2->y_i;
- serialno = p->private->plot_serialno;
- }
-
- dw = sx_v.pixels;
- dh = sy_v.pixels;
-
- if(p->private->plot_progress_count>dh) return 0;
-
- _sv_panel2d_maintain_cache(p,&c->p2,dw);
-
- d = p->dimensions;
-
- /* render using local dimension array; several threads will be
- computing objectives */
- double dim_vals[_sv_dimensions];
- int y = _v_swizzle(p->private->plot_progress_count-1,dh);
- p->private->plot_progress_count++;
-
- x_min = _sv_scalespace_value(&p2->x_i,0);
- x_max = _sv_scalespace_value(&p2->x_i,dw);
-
- y_min = _sv_scalespace_value(&p2->y_i,0);
- y_max = _sv_scalespace_value(&p2->y_i,dh);
-
- // Initialize local dimension value array
- for(i=0;i<_sv_dimensions;i++){
- sv_dim_t *dim = _sv_dimension_list[i];
- dim_vals[i]=dim->val;
- }
-
- /* unlock for computation */
- gdk_unlock ();
-
- dim_vals[y_d]=_sv_scalespace_value(&sy_i, y);
- _sv_panel2d_compute_line(p, serialno, dw, y, x_d, sx_i, dim_vals, &c->p2);
-
- gdk_lock ();
-
- if(p->private->plot_serialno == serialno){
- p->private->plot_complete_count++;
- _sv_panel2d_mark_map_line_y(p,y);
- if(p->private->plot_complete_count>=dh){
- _sv_panel_dirty_map(p);
- _sv_panel_dirty_legend(p);
- _sv_panel_clean_plot(p);
- }else
- _sv_panel_dirty_map_throttled(p);
- }
-
- return 1;
-}
-
// only called for resize events
static void _sv_panel2d_recompute_callback(void *ptr){
sv_panel_t *p = (sv_panel_t *)ptr;
@@ -2170,14 +1013,155 @@
return warn;
}
-sv_panel_t *sv_panel_new_2d(int number,
- char *name,
- char *objectivelist,
- char *dimensionlist,
- unsigned flags){
+
+void _sv_panel_realize(sv_panel_t *p){
+ if(p && !p->private->realized){
+ p->private->realize(p);
+
+ g_signal_connect (G_OBJECT (p->private->toplevel), "key-press-event",
+ G_CALLBACK (panel_keypress), p);
+ gtk_window_set_title (GTK_WINDOW (p->private->toplevel), p->name);
+
+ p->private->realized=1;
+
+ // generic things that happen in all panel realizations...
+
+ // text black or white in the plot?
+ decide_text_inv(p);
+ p->private->popmenu = _gtk_menu_new_twocol(p->private->toplevel, menu, p);
+ _sv_panel_update_menus(p);
+
+ }
+}
+
+int sv_panel_background(int number,
+ enum sv_background bg){
+
+ if(number<0){
+ fprintf(stderr,"sv_panel_background: Panel number must be >= 0\n");
+ return -EINVAL;
+ }
+
+ if(number>_sv_panels || !_sv_panel_list[number]){
+ fprintf(stderr,"sv_panel_background: Panel number %d does not exist\n",number);
+ return -EINVAL;
+ }
+ sv_panel_t *p = _sv_panel_list[number];
+ return set_background(p,bg);
+}
+
+sv_panel_t *_sv_panel(char *name){
+ int i;
+
+ if(name == NULL || name == 0 || !strcmp(name,"")){
+ return (sv_panel_t *)pthread_getspecific(_sv_panel_key);
+ }
+
+ for(i=0;i<_sv_panels;i++){
+ sv_panel_t *p=_sv_panel_list[i];
+ if(p && p->name && !strcmp(name,p->name)){
+ pthread_setspecific(_sv_panel_key, (void *)p);
+ return p;
+ }
+ }
+ return NULL;
+}
+
+int sv_panel(char *name){
+ sv_panel_t *p = _sv_panel(name);
+ if(p)return 0;
+ return -EINVAL;
+}
+
+sv_panel_t *sv_panel_new(char *name,
+ char *objlist,
+ char *dimlist){
+
+ sv_panel_t *p = NULL;
+ int number;
+ sv_token *decl = _sv_tokenize_declparam(name);
+ sv_tokenlist *dim_tokens = NULL;
+ sv_tokenlist *obj_tokens = NULL;
int i,j;
- sv_panel_t *p = _sv_panel_new(number,name,objectivelist,dimensionlist,flags);
+
+ if(!decl){
+ fprintf(stderr,"sushivision: Unable to parse panel declaration \"%s\".\n",name);
+ goto err;
+ }
+
+ // panel and panel list manipulation must be locked
+ gdk_threads_enter();
+ pthread_rwlock_wrlock(panellist_m);
+
+ if(_sv_panels == 0){
+ number=0;
+ _sv_panel_list = calloc (number+1,sizeof(*_sv_panel_list));
+ _sv_panels=1;
+ }else{
+ for(number=0;number<_sv_panels;number++)
+ if(!_sv_panel_list[number])break;
+ if(number==_sv_panels){
+ _sv_panels=number+1;
+ _sv_panel_list = realloc (_sv_panel_list,_sv_panels * sizeof(*_sv_panel_list));
+ }
+ }
+
+ p = _sv_panel_list[number] = calloc(1, sizeof(**_sv_panel_list));
+ p->name = strdup(decl->name);
+ p->legend = strdup(decl->label);
+ p->number = number;
+ p->spinner = _sv_spinner_new();
+
+ // parse and sanity check the maps
+ i=0;
+ obj_tokens = _sv_tokenize_namelist(objectivelist);
+ p->objectives = obj_tokens->n;
+ p->objective_list = malloc(p->objectives*sizeof(*p->objective_list));
+ for(i=0;i<p->objectives;i++){
+ char *name = obj_tokens->list[i]->name;
+ p->objective_list[i].o = _sv_obj(name);
+ p->objective_list[i].p = p;
+ }
+
+ i=0;
+ dim_tokens = _sv_tokenize_namelist(dimensionlist);
+ p->dimensions = dim_tokens->n;
+ p->dimension_list = malloc(p->dimensions*sizeof(*p->dimension_list));
+ for(i=0;i<p->dimensions;i++){
+ char *name = dim_tokens->list[i]->name;
+ sv_dim_t *d = sv_dim(name);
+
+ if(!d){
+ fprintf(stderr,"Panel %d (\"%s\"): Dimension \"%s\" does not exist\n",
+ number,p->name,name);
+ errno = -EINVAL;
+ //XXX leak
+ return NULL;
+ }
+
+ if(!d->scale){
+ fprintf(stderr,"Panel %d (\"%s\"): Dimension \"%s\" has a NULL scale\n",
+ number,p->name,name);
+ errno = -EINVAL;
+ //XXX leak
+ return NULL;
+ }
+
+ p->dimension_list[i].d = d;
+ p->dimension_list[i].p = p;
+ }
+
+ _sv_tokenlist_free(obj_tokens);
+ _sv_tokenlist_free(dim_tokens);
+ return p;
+}
+
+
+
+
+
+
if(!p)return NULL;
_sv_panel2d_t *p2 = calloc(1, sizeof(*p2));
@@ -2294,122 +1278,8 @@
}
-void _sv_panel_realize(sv_panel_t *p){
- if(p && !p->private->realized){
- p->private->realize(p);
- g_signal_connect (G_OBJECT (p->private->toplevel), "key-press-event",
- G_CALLBACK (panel_keypress), p);
- gtk_window_set_title (GTK_WINDOW (p->private->toplevel), p->name);
- p->private->realized=1;
-
- // generic things that happen in all panel realizations...
-
- // text black or white in the plot?
- decide_text_inv(p);
- p->private->popmenu = _gtk_menu_new_twocol(p->private->toplevel, menu, p);
- _sv_panel_update_menus(p);
-
- }
-}
-
-int sv_panel_background(int number,
- enum sv_background bg){
-
- if(number<0){
- fprintf(stderr,"sv_panel_background: Panel number must be >= 0\n");
- return -EINVAL;
- }
-
- if(number>_sv_panels || !_sv_panel_list[number]){
- fprintf(stderr,"sv_panel_background: Panel number %d does not exist\n",number);
- return -EINVAL;
- }
-
- sv_panel_t *p = _sv_panel_list[number];
- return set_background(p,bg);
-}
-
-sv_panel_t *sv_panel_new(char *decl,
- char *objlist,
- char *dimlist){
-
- sv_panel_t *p;
- sv_tokenlist *dim_tokens;
- sv_tokenlist *obj_tokens;
- int i;
-
-
- if(number<_sv_panels){
- if(_sv_panel_list[number]!=NULL){
- fprintf(stderr,"Panel number %d already exists\n",number);
- errno = -EINVAL;
- return NULL;
- }
- }else{
- if(_sv_panels == 0){
- _sv_panel_list = calloc (number+1,sizeof(*_sv_panel_list));
- }else{
- _sv_panel_list = realloc (_sv_panel_list,(number+1) * sizeof(*_sv_panel_list));
- memset(_sv_panel_list + _sv_panels, 0, sizeof(*_sv_panel_list)*(number+1 - _sv_panels));
- }
- _sv_panels = number+1;
- }
-
- p = _sv_panel_list[number] = calloc(1, sizeof(**_sv_panel_list));
-
- p->number = number;
- p->name = strdup(name);
- p->flags = flags;
- p->private = calloc(1, sizeof(*p->private));
- p->private->spinner = _sv_spinner_new();
- p->private->def_oversample_n = p->private->oversample_n = 1;
- p->private->def_oversample_d = p->private->oversample_d = 1;
-
- i=0;
- obj_tokens = _sv_tokenize_namelist(objectivelist);
- p->objectives = obj_tokens->n;
- p->objective_list = malloc(p->objectives*sizeof(*p->objective_list));
- for(i=0;i<p->objectives;i++){
- char *name = obj_tokens->list[i]->name;
- p->objective_list[i].o = _sv_obj(name);
- p->objective_list[i].p = p;
- }
-
- i=0;
- dim_tokens = _sv_tokenize_namelist(dimensionlist);
- p->dimensions = dim_tokens->n;
- p->dimension_list = malloc(p->dimensions*sizeof(*p->dimension_list));
- for(i=0;i<p->dimensions;i++){
- char *name = dim_tokens->list[i]->name;
- sv_dim_t *d = sv_dim(name);
-
- if(!d){
- fprintf(stderr,"Panel %d (\"%s\"): Dimension \"%s\" does not exist\n",
- number,p->name,name);
- errno = -EINVAL;
- //XXX leak
- return NULL;
- }
-
- if(!d->scale){
- fprintf(stderr,"Panel %d (\"%s\"): Dimension \"%s\" has a NULL scale\n",
- number,p->name,name);
- errno = -EINVAL;
- //XXX leak
- return NULL;
- }
-
- p->dimension_list[i].d = d;
- p->dimension_list[i].p = p;
- }
-
- _sv_tokenlist_free(obj_tokens);
- _sv_tokenlist_free(dim_tokens);
- return p;
-}
-
void _sv_panel_undo_log(sv_panel_t *p, _sv_panel_undo_t *u){
u->cross_mode = PLOT(p->private->graph)->cross_active;
u->legend_mode = PLOT(p->private->graph)->legend_active;
@@ -2551,15 +1421,3 @@
return 0;
}
-sv_dim_t *sv_panel_get_axis(sv_panel_t *p, char axis){
- switch(axis){
-
- case 'x': case 'X':
- return p->private->x_d;
-
- case 'y': case 'Y':
- return p->private->y_d;
- }
-
- return NULL;
-}
Modified: trunk/sushivision/panel.h
===================================================================
--- trunk/sushivision/panel.h 2007-10-18 07:39:37 UTC (rev 14010)
+++ trunk/sushivision/panel.h 2007-10-18 14:32:30 UTC (rev 14011)
@@ -19,6 +19,10 @@
*
*/
+#define STATUS_IDLE 0
+#define STATUS_BUSY 1
+#define STATUS_WORKING 2
+
struct sv_panel {
pthread_rwlock_t panel_m;
pthread_mutex_t status_m;
@@ -57,6 +61,7 @@
// UI objects
GtkWidget *obj_table;
GtkWidget *dim_table;
+ sv_spinner_t *spinner;
//sv_dimwidget_t *dw;
//sv_objwidget_t *ow;
Added: trunk/sushivision/panelmenu.c
===================================================================
--- trunk/sushivision/panelmenu.c (rev 0)
+++ trunk/sushivision/panelmenu.c 2007-10-18 14:32:30 UTC (rev 14011)
@@ -0,0 +1,636 @@
+/*
+ *
+ * sushivision copyright (C) 2006-2007 Monty <monty at xiph.org>
+ *
+ * sushivision is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * sushivision is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with sushivision; see the file COPYING. If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <errno.h>
+#include <math.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <cairo-ft.h>
+#include "internal.h"
+
+static void wrap_exit(sv_panel_t *dummy, GtkWidget *dummyw);
+static void wrap_bg(sv_panel_t *p, GtkWidget *w);
+static void wrap_grid(sv_panel_t *p, GtkWidget *w);
+static void wrap_text(sv_panel_t *p, GtkWidget *w);
+static void wrap_res(sv_panel_t *p, GtkWidget *w);
+static void wrap_load(sv_panel_t *p, GtkWidget *dummy);
+static void wrap_save(sv_panel_t *p, GtkWidget *dummy);
+static void wrap_print(sv_panel_t *p, GtkWidget *dummy);
+static void wrap_undo_up(sv_panel_t *p, GtkWidget *dummy);
+static void wrap_undo_down(sv_panel_t *p, GtkWidget *dummy);
+static void wrap_legend(sv_panel_t *p, GtkWidget *dummy);
+static void wrap_escape(sv_panel_t *p, GtkWidget *dummy);
+static void wrap_enter(sv_panel_t *p, GtkWidget *dummy);
+
+static sv_propmap_t *bgmap[]={
+ &(sv_propmap_t){"white","#ffffff", "[<i>b</i>]",NULL,wrap_bg},
+ &(sv_propmap_t){"gray","#a0a0a0", "[<i>b</i>]",NULL,wrap_bg},
+ &(sv_propmap_t){"blue","#000060", "[<i>b</i>]",NULL,wrap_bg},
+ &(sv_propmap_t){"black","#000000", "[<i>b</i>]",NULL,wrap_bg},
+ &(sv_propmap_t){"checks","checks", "[<i>b</i>]",NULL,wrap_bg},
+ NULL
+};
+
+static sv_propmap_t *gridmap[]={
+ &(sv_propmap_t){"light","#e6e6e6", "[<i>g</i>]",NULL,wrap_grid},
+ &(sv_propmap_t){"normal","#b4b4b4", "[<i>g</i>]",NULL,wrap_grid},
+ &(sv_propmap_t){"dark","#181818", "[<i>g</i>]",NULL,wrap_grid},
+ &(sv_propmap_t){"tics","tics", "[<i>g</i>]",NULL,wrap_grid},
+ &(sv_propmap_t){"none","none", "[<i>g</i>]",NULL,wrap_grid},
+ NULL
+};
+
+static _sv_propmap_t *textmap[]={
+ &(sv_propmap_t){"dark","#000000", "[<i>t</i>]",NULL,wrap_text},
+ &(sv_propmap_t){"light","#ffffff", "[<i>t</i>]",NULL,wrap_text},
+ NULL
+};
+
+static _sv_propmap_t *legendmap[]={
+ &(_sv_propmap_t){"none","none", NULL,NULL,NULL},
+ &(_sv_propmap_t){"shadowed","shadowed", NULL,NULL,NULL},
+ &(_sv_propmap_t){"boxed","boxed", NULL,NULL,NULL},
+ NULL
+};
+
+static _sv_propmap_t *menu[]={
+ &(_sv_propmap_t){"Open",0,"[<i>o</i>]",NULL,wrap_load},
+ &(_sv_propmap_t){"Save",0,"[<i>s</i>]",NULL,wrap_save},
+ &(_sv_propmap_t){"Print/Export",0,"[<i>p</i>]",NULL,wrap_print},
+
+ &(_sv_propmap_t){"",0,NULL,NULL,NULL},
+
+ &(_sv_propmap_t){"Undo",0,"[<i>bksp</i>]",NULL,wrap_undo_down},
+ &(_sv_propmap_t){"Redo",0,"[<i>space</i>]",NULL,wrap_undo_up},
+ &(_sv_propmap_t){"Start zoom box",0,"[<i>enter</i>]",NULL,wrap_enter},
+ &(_sv_propmap_t){"Clear selection",0,"[<i>escape</i>]",NULL,wrap_escape},
+ &(_sv_propmap_t){"Toggle Legend",0,"[<i>l</i>]",NULL,wrap_legend},
+
+ &(_sv_propmap_t){"",9,NULL,NULL,NULL},
+
+ &(_sv_propmap_t){"Background",0,"...",bgmap,NULL},
+ &(_sv_propmap_t){"Text color",0,"...",textmap,NULL},
+ &(_sv_propmap_t){"Grid mode",0,"...",gridmap,NULL},
+ &(_sv_propmap_t){"Sampling",0,"...",resmap,NULL},
+
+ &(_sv_propmap_t){"",0,NULL,NULL,NULL},
+
+ &(_sv_propmap_t){"Quit",0,"[<i>q</i>]",NULL,wrap_exit},
+
+ NULL
+};
+
+static void decide_text_inv(sv_panel_t *p){
+ if(p->private->graph){
+ _sv_plot_t *plot = PLOT(p->private->graph);
+ if(p->private->bg_type == SV_BG_WHITE)
+ _sv_plot_set_bg_invert(plot,_SV_PLOT_TEXT_DARK);
+ else
+ _sv_plot_set_bg_invert(plot,_SV_PLOT_TEXT_LIGHT);
+ }
+}
+
+static void recompute_if_running(sv_panel_t *p){
+ if(p->private->realized && p->private->graph)
+ _sv_panel_recompute(p);
+}
+
+static void redraw_if_running(sv_panel_t *p){
+ if(p->private->realized && p->private->graph){
+ _sv_plot_draw_scales(PLOT(p->private->graph));
+ _sv_panel_dirty_map(p);
+ _sv_panel_dirty_legend(p);
+ }
+}
+
+static void refg_if_running(sv_panel_t *p){
+ if(p->private->realized && p->private->graph){
+ _sv_plot_draw_scales(PLOT(p->private->graph));
+ _sv_panel_dirty_legend(p);
+ }
+}
+
+static void wrap_exit(sv_panel_t *dummy, GtkWidget *dummyw){
+ _sv_clean_exit();
+}
+
+// precipitated actions perform undo push
+static void wrap_enter(sv_panel_t *p, GtkWidget *dummy){
+ _sv_plot_do_enter(PLOT(p->private->graph));
+}
+
+static void wrap_escape(sv_panel_t *p, GtkWidget *dummy){
+ _sv_undo_push();
+ _sv_undo_suspend();
+
+ _sv_plot_set_crossactive(PLOT(p->private->graph),0);
+ _sv_panel_dirty_legend(p);
+
+ _sv_undo_resume();
+}
+
+static void wrap_legend(sv_panel_t *p, GtkWidget *dummy){
+ _sv_undo_push();
+ _sv_undo_suspend();
+
+ _sv_plot_toggle_legend(PLOT(p->private->graph));
+ _sv_panel_dirty_legend(p);
+
+ _sv_undo_resume();
+}
+
+static void set_grid(sv_panel_t *p, int mode){
+ _sv_undo_push();
+ _sv_undo_suspend();
+
+ _sv_plot_set_grid(PLOT(p->private->graph),mode);
+ _sv_panel_update_menus(p);
+ refg_if_running(p);
+
+ _sv_undo_resume();
+}
+
+static void wrap_grid(sv_panel_t *p, GtkWidget *w){
+ int pos = _gtk_menu_item_position(w);
+ set_grid(p, gridmap[pos]->value);
+}
+
+static int set_background(sv_panel_t *p,
+ enum sv_background bg){
+
+ sv_panel_internal_t *pi = p->private;
+
+ _sv_undo_push();
+ _sv_undo_suspend();
+
+ pi->bg_type = bg;
+
+ decide_text_inv(p);
+ set_grid(p,_SV_PLOT_GRID_NORMAL);
+ redraw_if_running(p);
+ _sv_panel_update_menus(p);
+
+ _sv_undo_resume();
+ return 0;
+}
+
+static void wrap_bg(sv_panel_t *p, GtkWidget *w){
+ int pos = _gtk_menu_item_position(w);
+ set_background(p, bgmap[pos]->value);
+}
+
+static void cycle_bg(sv_panel_t *p){
+ int menupos = _sv_propmap_pos(bgmap, p->private->bg_type) + 1;
+ if(bgmap[menupos] == NULL) menupos = 0;
+ set_background(p, bgmap[menupos]->value);
+}
+
+static void cycleB_bg(sv_panel_t *p){
+ int menupos = _sv_propmap_pos(bgmap, p->private->bg_type) - 1;
+ if(menupos<0) menupos = _sv_propmap_last(bgmap);
+ set_background(p, bgmap[menupos]->value);
+}
+
+static void set_text(sv_panel_t *p, int mode){
+ _sv_undo_push();
+ _sv_undo_suspend();
+
+ _sv_plot_set_bg_invert(PLOT(p->private->graph),mode);
+ _sv_panel_update_menus(p);
+ refg_if_running(p);
+
+ _sv_undo_resume();
+}
+
+static void wrap_text(sv_panel_t *p, GtkWidget *w){
+ int pos = _gtk_menu_item_position(w);
+ set_text(p, textmap[pos]->value);
+}
+
+static void cycle_text(sv_panel_t *p){
+ int menupos = _sv_propmap_pos(textmap, PLOT(p->private->graph)->bg_inv) + 1;
+ if(textmap[menupos] == NULL) menupos = 0;
+ set_text(p, textmap[menupos]->value);
+}
+
+static void cycle_grid(sv_panel_t *p){
+ int menupos = _sv_propmap_pos(gridmap, PLOT(p->private->graph)->grid_mode) + 1;
+ if(gridmap[menupos] == NULL) menupos = 0;
+ set_grid(p, gridmap[menupos]->value);
+}
+static void cycleB_grid(sv_panel_t *p){
+ int menupos = _sv_propmap_pos(gridmap, PLOT(p->private->graph)->grid_mode) - 1;
+ if(menupos<0) menupos = _sv_propmap_last(gridmap);
+ set_grid(p, gridmap[menupos]->value);
+}
+
+static void res_set(sv_panel_t *p, int n, int d){
+ if(n != p->private->oversample_n ||
+ d != p->private->oversample_d){
+
+ _sv_undo_push();
+ _sv_undo_suspend();
+
+ p->private->oversample_n = n;
+ p->private->oversample_d = d;
+ _sv_panel_update_menus(p);
+ recompute_if_running(p);
+
+ _sv_undo_resume();
+ }
+}
+
+// a little different; the menu value is not the internal setting
+static void res_set_pos(sv_panel_t *p, int pos){
+ p->private->menu_cursamp = pos;
+ switch(pos){
+ case RES_DEF:
+ res_set(p,p->private->def_oversample_n,p->private->def_oversample_d);
+ break;
+ case RES_1_32:
+ res_set(p,1,32);
+ break;
+ case RES_1_16:
+ res_set(p,1,16);
+ break;
+ case RES_1_8:
+ res_set(p,1,8);
+ break;
+ case RES_1_4:
+ res_set(p,1,4);
+ break;
+ case RES_1_2:
+ res_set(p,1,2);
+ break;
+ case RES_1_1:
+ res_set(p,1,1);
+ break;
+ case RES_2_1:
+ res_set(p,2,1);
+ break;
+ case RES_4_1:
+ res_set(p,4,1);
+ break;
+ }
+}
+
+static void wrap_res(sv_panel_t *p, GtkWidget *w){
+ int pos = _gtk_menu_item_position(w);
+ res_set_pos(p, resmap[pos]->value);
+}
+
+static void cycle_res(sv_panel_t *p){
+ int menupos = _sv_propmap_pos(resmap, p->private->menu_cursamp) + 1;
+ if(resmap[menupos] == NULL) menupos = 0;
+ res_set_pos(p, resmap[menupos]->value);
+}
+
+static void cycleB_res(sv_panel_t *p){
+ int menupos = _sv_propmap_pos(resmap, p->private->menu_cursamp) - 1;
+ if(menupos<0) menupos = _sv_propmap_last(resmap);
+ res_set_pos(p, resmap[menupos]->value);
+}
+
+static GtkPrintSettings *printset=NULL;
+static void _begin_print_handler (GtkPrintOperation *op,
+ GtkPrintContext *context,
+ gpointer dummy){
+
+ gtk_print_operation_set_n_pages(op,1);
+
+}
+
+static void _print_handler(GtkPrintOperation *operation,
+ GtkPrintContext *context,
+ gint page_nr,
+ gpointer user_data){
+
+ cairo_t *c;
+ gdouble w, h;
+ sv_panel_t *p = (sv_panel_t *)user_data;
+
+ c = gtk_print_context_get_cairo_context (context);
+ w = gtk_print_context_get_width (context);
+ h = gtk_print_context_get_height (context);
+
+ p->private->print_action(p,c,w,h);
+}
+
+static void _sv_panel_print(sv_panel_t *p, GtkWidget *dummy){
+ GtkPrintOperation *op = gtk_print_operation_new ();
+
+ if (printset != NULL)
+ gtk_print_operation_set_print_settings (op, printset);
+
+ g_signal_connect (op, "begin-print",
+ G_CALLBACK (_begin_print_handler), p);
+ g_signal_connect (op, "draw-page",
+ G_CALLBACK (_print_handler), p);
+
+ GError *err;
+ GtkPrintOperationResult ret = gtk_print_operation_run (op,GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+ NULL,&err);
+
+ if (ret == GTK_PRINT_OPERATION_RESULT_ERROR) {
+ GtkWidget *error_dialog = gtk_message_dialog_new (NULL,0,GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "Error printing file:\n%s",
+ err->message);
+ g_signal_connect (error_dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_widget_show (error_dialog);
+ g_error_free (err);
+ }else if (ret == GTK_PRINT_OPERATION_RESULT_APPLY){
+ if (printset != NULL)
+ g_object_unref (printset);
+ printset = g_object_ref (gtk_print_operation_get_print_settings (op));
+ }
+ g_object_unref (op);
+}
+
+static void wrap_undo_down(sv_panel_t *p, GtkWidget *dummy){
+ _sv_undo_down();
+}
+static void wrap_undo_up(sv_panel_t *p, GtkWidget *dummy){
+ _sv_undo_up();
+}
+
+static void wrap_save(sv_panel_t *p, GtkWidget *dummy){
+ GtkWidget *dialog = gtk_file_chooser_dialog_new ("Save",
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+ gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), _sv_cwdname, NULL);
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), _sv_dirname);
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), _sv_filebase);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT){
+ if(_sv_filebase)free(_sv_filebase);
+ if(_sv_filename)free(_sv_filename);
+ if(_sv_dirname)free(_sv_dirname);
+
+ _sv_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ _sv_dirname = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
+ _sv_filebase = g_path_get_basename(_sv_filename);
+ _sv_main_save();
+ }
+
+ gtk_widget_destroy (dialog);
+
+}
+
+static void wrap_load(sv_panel_t *p, GtkWidget *dummy){
+ GtkWidget *dialog = gtk_file_chooser_dialog_new ("Open",
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), _sv_cwdname, NULL);
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), _sv_dirname);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT){
+ char *temp_filebase = _sv_filebase;
+ char *temp_filename = _sv_filename;
+ char *temp_dirname = _sv_dirname;
+ _sv_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ _sv_dirname = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
+ _sv_filebase = g_path_get_basename(_sv_filename);
+
+ if(_sv_main_load()){
+ // error
+ GtkWidget *dialog;
+ if(errno == -EINVAL){
+ dialog = gtk_message_dialog_new (NULL,0,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "Error parsing file '%s'",
+ _sv_filename);
+ }else{
+ dialog = gtk_message_dialog_new (NULL,0,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "Error opening file '%s': %s",
+ _sv_filename, strerror (errno));
+ }
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ free(_sv_filebase);
+ free(_sv_filename);
+ free(_sv_dirname);
+
+ _sv_filebase = temp_filebase;
+ _sv_filename = temp_filename;
+ _sv_dirname = temp_dirname;
+
+ }else{
+ free(temp_filebase);
+ free(temp_filename);
+ free(temp_dirname);
+ }
+ }
+
+ gtk_widget_destroy (dialog);
+
+}
+
+void _sv_panel_update_menus(sv_panel_t *p){
+
+ // is undo active?
+ if(!_sv_undo_stack ||
+ !_sv_undo_level){
+ gtk_widget_set_sensitive(_gtk_menu_get_item(GTK_MENU(p->private->popmenu),4),FALSE);
+ }else{
+ gtk_widget_set_sensitive(_gtk_menu_get_item(GTK_MENU(p->private->popmenu),4),TRUE);
+ }
+
+ // is redo active?
+ if(!_sv_undo_stack ||
+ !_sv_undo_stack[_sv_undo_level] ||
+ !_sv_undo_stack[_sv_undo_level+1]){
+ gtk_widget_set_sensitive(_gtk_menu_get_item(GTK_MENU(p->private->popmenu),5),FALSE);
+ }else{
+ gtk_widget_set_sensitive(_gtk_menu_get_item(GTK_MENU(p->private->popmenu),5),TRUE);
+ }
+
+ // are we starting or enacting a zoom box?
+ if(p->private->oldbox_active){
+ _gtk_menu_alter_item_label(GTK_MENU(p->private->popmenu),6,"Zoom to box");
+ }else{
+ _gtk_menu_alter_item_label(GTK_MENU(p->private->popmenu),6,"Start zoom box");
+ }
+
+ // make sure menu reflects plot configuration
+ _gtk_menu_alter_item_right(GTK_MENU(p->private->popmenu),
+ _sv_propmap_label_pos(menu,"Background"),
+ bgmap[_sv_propmap_pos(bgmap,p->private->bg_type)]->left);
+
+ _gtk_menu_alter_item_right(GTK_MENU(p->private->popmenu),
+ _sv_propmap_label_pos(menu,"Text color"),
+ textmap[_sv_propmap_pos(textmap,PLOT(p->private->graph)->bg_inv)]->left);
+
+ _gtk_menu_alter_item_right(GTK_MENU(p->private->popmenu),
+ _sv_propmap_label_pos(menu,"Grid mode"),
+ gridmap[_sv_propmap_pos(gridmap,PLOT(p->private->graph)->grid_mode)]->left);
+ {
+ char buffer[80];
+ snprintf(buffer,60,"%d:%d",p->private->oversample_n,p->private->oversample_d);
+ if(p->private->def_oversample_n == p->private->oversample_n &&
+ p->private->def_oversample_d == p->private->oversample_d)
+ strcat(buffer," (default)");
+ _gtk_menu_alter_item_right(GTK_MENU(p->private->popmenu),
+ _sv_propmap_label_pos(menu,"Sampling"),buffer);
+ }
+}
+
+static gboolean panel_keypress(GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer in){
+ sv_panel_t *p = (sv_panel_t *)in;
+ // sv_panel2d_t *p2 = (sv_panel2d_t *)p->internal;
+
+ // check if the widget with focus is an Entry
+ GtkWidget *focused = gtk_window_get_focus(GTK_WINDOW(widget));
+ int entryp = (focused?GTK_IS_ENTRY(focused):0);
+
+ // don't swallow modified keypresses
+ if(event->state&GDK_MOD1_MASK) return FALSE;
+ if(event->state&GDK_CONTROL_MASK)return FALSE;
+
+ switch(event->keyval){
+ case GDK_Home:case GDK_KP_Begin:
+ case GDK_End:case GDK_KP_End:
+ case GDK_Up:case GDK_KP_Up:
+ case GDK_Down:case GDK_KP_Down:
+ case GDK_Left:case GDK_KP_Left:
+ case GDK_Right:case GDK_KP_Right:
+ case GDK_minus:case GDK_KP_Subtract:
+ case GDK_plus:case GDK_KP_Add:
+ case GDK_period:case GDK_KP_Decimal:
+ case GDK_0:case GDK_KP_0:
+ case GDK_1:case GDK_KP_1:
+ case GDK_2:case GDK_KP_2:
+ case GDK_3:case GDK_KP_3:
+ case GDK_4:case GDK_KP_4:
+ case GDK_5:case GDK_KP_5:
+ case GDK_6:case GDK_KP_6:
+ case GDK_7:case GDK_KP_7:
+ case GDK_8:case GDK_KP_8:
+ case GDK_9:case GDK_KP_9:
+ case GDK_Tab:case GDK_KP_Tab:
+ case GDK_ISO_Left_Tab:
+ case GDK_Delete:case GDK_KP_Delete:
+ case GDK_Insert:case GDK_KP_Insert:
+ return FALSE;
+ }
+
+ if(entryp){
+ // we still filter, but differently
+ switch(event->keyval){
+ case GDK_BackSpace:
+ case GDK_e:case GDK_E:
+ case GDK_Return:case GDK_ISO_Enter:
+ return FALSE;
+ }
+ }
+
+ /* non-control keypresses */
+ switch(event->keyval){
+ case GDK_b:
+ cycle_bg(p);
+ return TRUE;
+ case GDK_B:
+ cycleB_bg(p);
+ return TRUE;
+ case GDK_t:case GDK_T:
+ cycle_text(p);
+ return TRUE;
+ case GDK_g:
+ cycle_grid(p);
+ return TRUE;
+ case GDK_G:
+ cycleB_grid(p);
+ return TRUE;
+ case GDK_m:
+ cycle_res(p);
+ return TRUE;
+ case GDK_M:
+ cycleB_res(p);
+ return TRUE;
+
+ case GDK_s:
+ wrap_save(p,NULL);
+ return TRUE;
+ case GDK_o:
+ wrap_load(p,NULL);
+ return TRUE;
+
+ case GDK_Escape:
+ wrap_escape(p,NULL);
+ return TRUE;
+
+ case GDK_Return:case GDK_ISO_Enter:
+ wrap_enter(p,NULL);
+ return TRUE;
+
+ case GDK_Q:
+ case GDK_q:
+ // quit
+ _sv_clean_exit();
+ return TRUE;
+
+ case GDK_BackSpace:
+ // undo
+ _sv_undo_down();
+ return TRUE;
+
+ case GDK_r:
+ case GDK_space:
+ // redo/forward
+ _sv_undo_up();
+ return TRUE;
+
+ case GDK_p:
+ _sv_panel_print(p,NULL);
+ return TRUE;
+
+ case GDK_l:
+ wrap_legend(p,NULL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
Modified: trunk/sushivision/plane-2d.c
===================================================================
--- trunk/sushivision/plane-2d.c 2007-10-18 07:39:37 UTC (rev 14010)
+++ trunk/sushivision/plane-2d.c 2007-10-18 14:32:30 UTC (rev 14011)
@@ -417,13 +417,12 @@
return flag;
}
-int _sv_plane_resize_check(sv_plane_t *in){
+int _sv_plane_resample_setup_common(sv_plane_t *in){
sv_plane_common_t *c = &pl->c;
sv_panel_t *p = c->panel;
- int w = p->bg->image_x->pixels;
- int h = p->bg->image_y->pixels;
-
- if(c->image_x.pixels != w || c->image_y.pixels != y) return 1;
+
+ if(_sv_scalecmp(&c->image_x,&p->bg->image_x) ||
+ _sv_scalecmp(&c->image_y,&p->bg->image_y)) return 1;
return 0;
}
@@ -445,7 +444,7 @@
// plane of a fixed size data set requires a rerender, but not a
// recompute)
- flag|=_sv_plane_resize_check(in);
+ flag|=_sv_plane_resample_setup_common(in);
if(flag){
pl->image_serialno++;
@@ -669,7 +668,7 @@
swapp(&ynumB,&pl->resample_ynumB);
pl->resample_xscalemul = xscalemul;
pl->resample_yscalemul = yscalemul;
-
+ bg_rerender_full(p);
pl->image_task = 4;
pl->image_outstanding=0;
}
@@ -883,8 +882,8 @@
//pthread_mutex_lock(pl->status_m);
if(p->comp_serialno == serialno){
- pl->data_x = p->bg->data_x;
- pl->data_y = p->bg->data_y;
+ pl->data_x = pl->pending_data_x;
+ pl->data_y = pl->pending_data_y;
pl->data_task = 4;
pl->data_outstanding=0;
map = pl->map;
@@ -914,7 +913,8 @@
int mapno = pl->image_serialno;
int i;
sv_ucolor_t work[w];
-
+
+ if(pl->image_task == 5 && pl->image_outstanding) return STATUS_BUSY;
if(pl->image_task != 4) return STATUS_IDLE;
do{
@@ -937,19 +937,14 @@
if(pl->image_serialno == mapno){
pl->image_outstanding--;
- p->bg->image_flags[i] = 1;
- if(pl->image_task == 5) // idled while we were working; bg render is waiting for us
- p->bg_render = 1;
+ bg_rerender_line(p,i);
}
-
return STATUS_WORKING;
}
}while(i!=last);
-
+
pl->image_task = 5;
- if(!pl->image_outstanding)
- p->bg_render = 1;
-
+ if(pl->image_outstanding) return STATUS_BUSY;
return STATUS_IDLE;
}
@@ -1012,15 +1007,13 @@
// if this is a 'slave' plane in the computation chain, return idle;
// some other plane is doing the calculation for us.
+
if(pl->c.share_prev)return STATUS_IDLE;
- if(pl->data_task != 4)return STATUS_IDLE;
- if(next >= pl->data_y.pixels){
- // not the same thing as completion; a computation may yet be
- // outstanding. Simply mark this plane so that there are no
- // further dispatch attempts
- pl->data_task = 5;
- return STATUS_IDLE;
- }
+ if(pl->data_task == 4)
+ if(next >= pl->data_y.pixels)
+ pl->data_task = 5;
+ if(pl->data_task == 5 && pl->data_outstanding) return STATUS_BUSY;
+ if(pl->data_task != 4) return STATUS_IDLE;
pl->data_next++;
// marshal iterators, dimension value vectors
Modified: trunk/sushivision/plane-bg.c
===================================================================
--- trunk/sushivision/plane-bg.c 2007-10-18 07:39:37 UTC (rev 14010)
+++ trunk/sushivision/plane-bg.c 2007-10-18 14:32:30 UTC (rev 14011)
@@ -32,525 +32,73 @@
#include <cairo-ft.h>
#include "internal.h"
-// called from worker thread
-static void recompute_setup(sv_plane2d_t *pl, sv_panel_t *p,
- sv_dim_data_t *payload, int dims){
-
- pl->image_serialno++;
+// the background 'plane' is handled a little differently from the
+// other planes, as alot of non-generalizable panel rendering also
+// happens in this module. For this reason, the bg plane doesn't
+// bother with functions embedded in the plane struct. They're simply
+// called directly by the panel code.
+
+void bg_recompute_setup(sv_panel_t *p){
+ sv_planebg_t *pl = p->bg;
+
pl->image_x = _sv_dim_panelscale(payload + x_dim, p->w, 0);
pl->image_y = _sv_dim_panelscale(payload + y_dim, p->h, 1);
+ pl->image_task = 0;
}
+void bg_resize(sv_panel_t *p){
+ sv_planebg_t *pl = p->bg;
-// called from worker thread
-static int image_work(sv_plane2d_t *pl, sv_panel_t *p){
+ if(pl->image_status_size != p->h){
+ unsigned char *n=NULL;
+ unsigned char *o=NULL;
+ int serialno = p->comp_serialno;
-
-}
-
-// called from worker thread
-static int data_work(sv_plane2d_t *pl, sv_panel_t *p){
-
-
-}
-
-// called from GTK/API
-static void plane_remap(sv_plane2d_t *pl, sv_panel_t *p){
-
-
-}
-
-sv_plane_t *sv_plane2d_new(){
-
-
-}
-
-
-
-
-
-// enter unlocked
-static void _sv_planez_compute_line(sv_panel_t *p,
- _sv_plane2d_t *z,
-
- int serialno,
-
- int dw,
- int y,
- int x_d,
- _sv_scalespace_t sxi,
- double *dim_vals,
- _sv_bythread_cache_2d_t *c){
-
- _sv_panel2d_t *p2 = p->subtype->p2;
- int i,j;
-
- /* cache access is unlocked because the cache is private to this
- worker thread */
-
- for(j=0;j<dw;j++){
- double *fout = c->fout;
- sv_func_t **f = p2->used_function_list;
- int *obj_y_off = p2->y_fout_offset;
- int *onum = p2->y_obj_to_panel;
-
- /* by function */
- dim_vals[x_d] = _sv_scalespace_value(&sxi,j);
- for(i=0;i<p2->used_functions;i++){
- (*f)->callback(dim_vals,fout);
- fout += (*f)->outputs;
- f++;
+ pthread_mutex_unlock(pl->status_m);
+ n = calloc(p->h,sizeof(*n));
+ pthread_mutex_lock(pl->status_m);
+ if(serialno == p->comp_serialno){
+ o = pl->image_status;
+ pl->image_status = n;
+ n = NULL;
}
-
- /* process function output by plane type/objective */
- /* 2d panels currently only care about the Y output value */
-
- /* slider map */
- for(i=0;i<p2->y_obj_num;i++){
- float val = (float)_sv_slider_val_to_del(p2->range_scales[*onum++], c->fout[*obj_y_off++]);
- if(isnan(val)){
- c->y_map[i][j] = -1;
- }else{
- if(val<0)val=0;
- if(val>1)val=1;
- c->y_map[i][j] = rint(val * (256.f*256.f*256.f));
- }
- }
+ pthread_mutex_unlock(pl->status_m);
+ if(n)free(n);
+ if(o)free(o);
+ pthread_mutex_lock(pl->status_m);
+ return STATUS_WORKING;
}
- gdk_lock ();
- if(p->private->plot_serialno == serialno){
- for(j=0;j<p2->y_obj_num;j++){
- int *d = p2->y_map[j] + y*dw;
- int *td = c->y_map[j];
-
- memcpy(d,td,dw*sizeof(*d));
-
- }
- }
- gdk_unlock ();
+ return STATUS_IDLE;
}
-// call with lock
-static void _sv_panel2d_clear_pane(sv_panel_t *p){
+int bg_legend(sv_panel_t *p){
- _sv_panel2d_t *p2 = p->subtype->p2;
- int pw = p2->x.pixels;
- int ph = p2->y.pixels;
- int i;
- _sv_plot_t *plot = PLOT(p->private->graph);
-
- for(i=0;i<p2->y_obj_num;i++){
- // map is freed and nulled to avoid triggering a fast-scale on an empty data pane
- if(p2->y_map[i])
- free(p2->y_map[i]);
- p2->y_map[i]=NULL;
- // free y_planes so that initial remap doesn't waste time on mix
- // op; they are recreated during remap at the point the y_todo
- // vector indicates something to do
- if(p2->y_planes[i])
- free(p2->y_planes[i]);
- p2->y_planes[i] = NULL;
-
- // work vector is merely cleared
- memset(p2->y_planetodo[i], 0, ph*sizeof(**p2->y_planetodo));
- }
-
- // clear the background surface
- if(plot->datarect)
- memset(plot->datarect, 0, ph*pw*sizeof(*plot->datarect));
-
- // the bg is not marked to be refreshed; computation setup will do
- // that as part of the fast_scale, even if the fast_scale is
- // short-circuited to a noop.
}
-typedef struct{
- double x;
- double y;
- double z;
-} compute_result;
+int bg_scale(sv_panel_t *p){
+ gdk_unlock ();
+ _sv_plot_draw_scales(plot); // this should happen outside lock
+ gdk_lock ();
-// used by the legend code. this lets us get away with having only a mapped display pane
-// call with lock
-static void _sv_panel2d_compute_point(sv_panel_t *p,sv_obj_t *o, double x, double y, compute_result *out){
- double dim_vals[_sv_dimensions];
- int i,j;
- int pflag=0;
- int eflag=0;
- // fill in dimensions
- int x_d = p->private->x_d->number;
- int y_d = p->private->y_d->number;
-
- for(i=0;i<_sv_dimensions;i++){
- sv_dim_t *dim = _sv_dimension_list[i];
- dim_vals[i]=dim->val;
- }
-
- gdk_unlock ();
-
- dim_vals[x_d] = x;
- dim_vals[y_d] = y;
-
- *out = (compute_result){NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN};
-
- // compute
- for(i=0;i<_sv_functions;i++){
- sv_func_t *f = _sv_function_list[i];
- int compflag = 0;
- double fout[f->outputs];
- double val;
-
- // compute and demultiplex output
- for(j=0;j<o->outputs;j++){
- if(o->function_map[j] == i){
-
- if(!compflag) f->callback(dim_vals,fout);
- compflag = 1;
-
- val = fout[o->output_map[j]];
- switch(o->output_types[j]){
- case 'X':
- out->x = val;
- break;
- case 'Y':
- out->y = val;
- break;
- case 'Z':
- out->z = val;
- break;
- case 'E':
- if(eflag)
- out->e2 = val;
- else
- out->e1 = val;
- eflag = 1;
- break;
- case 'P':
- if(pflag)
- out->p2 = val;
- else
- out->p1 = val;
- pflag = 1;
- break;
- case 'M':
- out->m = val;
- break;
- }
- }
- }
- }
- gdk_lock ();
-
}
-/* functions that perform actual graphical rendering */
+int bg_render(sv_panel_t *p){
-static float _sv_panel2d_resample_helpers_init(_sv_scalespace_t *to, _sv_scalespace_t *from,
- unsigned char *delA, unsigned char *delB,
- int *posA, int *posB,
- int xymul){
- int i;
- int dw = from->pixels;
- int pw = to->pixels;
- long scalenum = _sv_scalespace_scalenum(to,from);
- long scaleden = _sv_scalespace_scaleden(to,from);
- long del = _sv_scalespace_scaleoff(to,from);
- int bin = del / scaleden;
- del -= bin * scaleden;
- int discscale = (scaleden>scalenum?scalenum:scaleden);
- int total = xymul*scalenum/discscale;
-
- for(i=0;i<pw;i++){
- long del2 = del + scalenum;
- int sizeceil = (del2 + scaleden - 1)/ scaleden; // ceiling
- int sizefloor = del2 / scaleden;
-
- while(bin<0 && del2>scaleden){
- bin++;
- del = 0;
- del2 -= scaleden;
- sizeceil--;
- }
-
- if(del2 > scaleden && bin>=0 && bin<dw){
- int rem = total;
-
- delA[i] = ((xymul * (scaleden - del)) + (discscale>>1)) / discscale;
- posA[i] = bin;
- rem -= delA[i];
- rem -= xymul*(sizeceil-2);
-
- while(bin+sizeceil>dw){
- sizeceil--;
- del2=0;
- }
-
- del2 %= scaleden;
- if(rem<0){
- delA[i] += rem;
- delB[i] = 0;
- }else{
- delB[i] = rem; // don't leak
- }
- posB[i] = bin+sizeceil;
-
- }else{
- if(bin<0 || bin>=dw){
- delA[i] = 0;
- posA[i] = 0;
- delB[i] = 0;
- posB[i] = 0;
- }else{
- delA[i] = xymul;
- posA[i] = bin;
- delB[i] = 0;
- posB[i] = bin+1;
- if(del2 == scaleden)del2=0;
- }
- }
-
- bin += sizefloor;
- del = del2;
- }
- return (float)xymul/total;
}
-/* x resample helpers are put in the per-thread cache because locking it would
- be relatively expensive. */
-// call while locked
-static void _sv_panel2d_resample_helpers_manage_x(sv_panel_t *p, _sv_bythread_cache_2d_t *c){
- _sv_panel2d_t *p2 = p->subtype->p2;
- if(p->private->plot_serialno != c->serialno){
- int pw = p2->x.pixels;
- c->serialno = p->private->plot_serialno;
+int bg_expose(sv_panel_t *p){
- if(c->xdelA)
- free(c->xdelA);
- if(c->xdelB)
- free(c->xdelB);
- if(c->xnumA)
- free(c->xnumA);
- if(c->xnumB)
- free(c->xnumB);
-
- c->xdelA = calloc(pw,sizeof(*c->xdelA));
- c->xdelB = calloc(pw,sizeof(*c->xdelB));
- c->xnumA = calloc(pw,sizeof(*c->xnumA));
- c->xnumB = calloc(pw,sizeof(*c->xnumB));
- c->xscalemul = _sv_panel2d_resample_helpers_init(&p2->x, &p2->x_v, c->xdelA, c->xdelB, c->xnumA, c->xnumB, 17);
- }
-}
-/* y resample is in the panel struct as per-row access is already locked */
-// call while locked
-static void _sv_panel2d_resample_helpers_manage_y(sv_panel_t *p){
- _sv_panel2d_t *p2 = p->subtype->p2;
- if(p->private->plot_serialno != p2->resample_serialno){
- int ph = p2->y.pixels;
- p2->resample_serialno = p->private->plot_serialno;
-
- if(p2->ydelA)
- free(p2->ydelA);
- if(p2->ydelB)
- free(p2->ydelB);
- if(p2->ynumA)
- free(p2->ynumA);
- if(p2->ynumB)
- free(p2->ynumB);
-
- p2->ydelA = calloc(ph,sizeof(*p2->ydelA));
- p2->ydelB = calloc(ph,sizeof(*p2->ydelB));
- p2->ynumA = calloc(ph,sizeof(*p2->ynumA));
- p2->ynumB = calloc(ph,sizeof(*p2->ynumB));
- p2->yscalemul = _sv_panel2d_resample_helpers_init(&p2->y, &p2->y_v, p2->ydelA, p2->ydelB, p2->ynumA, p2->ynumB, 15);
- }
}
-static inline void _sv_panel2d_mapping_calc( void (*m)(int,int, _sv_lcolor_t *),
- int low,
- float range,
- int in,
- int alpha,
- int mul,
- _sv_lcolor_t *outc){
- if(mul && in>=alpha){
- int val = rint((in - low) * range);
- if(val<0)val=0;
- if(val>65536)val=65536;
- m(val,mul,outc);
- }
-}
+sv_planebg_t *sv_planebg_new(sv_panel_t *p){
-/* the data rectangle is data width/height mapped deltas. we render
- and subsample at the same time. */
-/* return: -1 == abort
- 0 == more work to be done in this plane
- 1 == plane fully dispatched (possibly not complete) */
-/* enter with lock */
-static int _sv_panel2d_resample_render_y_plane_line(sv_panel_t *p, _sv_bythread_cache_2d_t *c,
- int plot_serialno, int map_serialno, int y_no){
-
- _sv_panel2d_t *p2 = p->subtype->p2;
- int objnum = p2->y_obj_to_panel[y_no];
- int *in_data = p2->y_map[y_no];
- int ph = p2->y.pixels;
-
- if(!in_data || !c){
- p->private->map_complete_count -= ph;
- return 1;
- }
-
- unsigned char *todo = p2->y_planetodo[y_no];
- int i = p2->y_next_line;
- int j;
-
- /* find a row that needs to be updated */
- while(i<ph && !todo[i]){
- p->private->map_complete_count--;
- p2->y_next_line++;
- i++;
- }
-
- if(i == ph) return 1;
-
- p2->y_next_line++;
-
- /* row [i] needs to be updated; marshal */
- _sv_mapping_t *map = p2->mappings+objnum;
- void (*mapfunc)(int,int, _sv_lcolor_t *) = map->mapfunc;
- int ol_alpha = rint(p2->alphadel[y_no] * 16777216.f);
- _sv_ucolor_t *panel = p2->y_planes[y_no];
- int ol_low = rint(map->low * 16777216.f);
- float ol_range = map->i_range * (1.f/256.f);
-
- int pw = p2->x.pixels;
- int dw = p2->x_v.pixels;
- int dh = p2->y_v.pixels;
- _sv_ccolor_t work[pw];
-
- if(!panel)
- panel = p2->y_planes[y_no] = calloc(pw*ph, sizeof(**p2->y_planes));
-
- if(ph!=dh || pw!=dw){
- /* resampled row computation; may involve multiple data rows */
-
- _sv_panel2d_resample_helpers_manage_y(p);
- _sv_panel2d_resample_helpers_manage_x(p,c);
-
- float idel = p2->yscalemul * c->xscalemul;
-
- /* by column */
- int ydelA=p2->ydelA[i];
- int ydelB=p2->ydelB[i];
- int ystart=p2->ynumA[i];
- int yend=p2->ynumB[i];
- int lh = yend - ystart;
- int data[lh*dw];
-
- memcpy(data,in_data+ystart*dw,sizeof(data));
-
- gdk_unlock();
-
- unsigned char *xdelA = c->xdelA;
- unsigned char *xdelB = c->xdelB;
- int *xnumA = c->xnumA;
- int *xnumB = c->xnumB;
-
- /* by panel col */
- for(j=0;j<pw;j++){
-
- _sv_lcolor_t out = (_sv_lcolor_t){0,0,0,0};
- int xstart = xnumA[j];
- int xend = xnumB[j];
- int dx = xstart;
- int xA = xdelA[j];
- int xB = xdelB[j];
- int y = ystart;
-
- // first line
- if(y<yend){
- if(dx<xend)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx++], ol_alpha, ydelA*xA, &out);
-
- for(; dx < xend-1; dx++)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx], ol_alpha, ydelA*17, &out);
-
- if(dx<xend)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx], ol_alpha, ydelA*xB, &out);
- y++;
- }
-
- // mid lines
- for(;y<yend-1;y++){
- dx = xstart += dw;
- xend += dw;
- if(dx<xend)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx++], ol_alpha, 15*xA, &out);
-
- for(; dx < xend-1; dx++)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx], ol_alpha, 255, &out);
-
- if(dx<xend)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx], ol_alpha, 15*xB, &out);
- }
-
- // last line
- if(y<yend){
- dx = xstart += dw;
- xend += dw;
- if(dx<xend)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx++], ol_alpha, ydelB*xA, &out);
-
- for(; dx < xend-1; dx++)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx], ol_alpha, ydelB*17, &out);
-
- if(dx<xend)
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[dx], ol_alpha, ydelB*xB, &out);
- }
-
- work[j].a = (u_int32_t)(out.a*idel);
- work[j].r = (u_int32_t)(out.r*idel);
- work[j].g = (u_int32_t)(out.g*idel);
- work[j].b = (u_int32_t)(out.b*idel);
-
- }
-
- }else{
- /* non-resampling render */
-
- int data[dw];
- memcpy(data,in_data+i*dw,sizeof(data));
- gdk_unlock();
-
- for(j=0;j<pw;j++){
-
- _sv_lcolor_t out = (_sv_lcolor_t){0,0,0,0};
- _sv_panel2d_mapping_calc(mapfunc, ol_low, ol_range, data[j], ol_alpha, 255, &out);
-
- work[j].a = (u_int32_t)(out.a);
- work[j].r = (u_int32_t)(out.r);
- work[j].g = (u_int32_t)(out.g);
- work[j].b = (u_int32_t)(out.b);
- }
- }
-
- gdk_lock ();
- if(plot_serialno != p->private->plot_serialno ||
- map_serialno != p->private->map_serialno)
- return -1;
- memcpy(panel+i*pw,work,sizeof(work));
- p2->bg_todo[i] = 1;
- p2->y_planetodo[y_no][i] = 0;
-
- // must be last; it indicates completion
- p->private->map_complete_count--;
- return 0;
}
static void render_checks(_sv_ucolor_t *c, int w, int y){
@@ -659,253 +207,7 @@
return 0;
}
-static void _sv_panel2d_mark_map_full(sv_panel_t *p);
-// enter with lock; returns zero if thread should sleep / get distracted
-static int _sv_panel2d_remap(sv_panel_t *p, _sv_bythread_cache_2d_t *thread_cache){
- _sv_panel2d_t *p2 = p->subtype->p2;
- _sv_plot_t *plot = PLOT(p->private->graph);
-
- if(!plot) goto abort;
- int ph = plot->y.pixels;
- int pw = plot->x.pixels;
-
- int plot_serialno = p->private->plot_serialno;
- int map_serialno = p->private->map_serialno;
-
- /* brand new remap indicated by the generic progress indicator being set to 0 */
- if(p->private->map_progress_count == 0){
-
- p->private->map_progress_count = 1; // 'in progress'
- p->private->map_complete_count = p2->y_obj_num * ph; // count down to 0; 0 indicates completion
-
- // set up Y plane rendering
- p2->y_next_plane = 0;
- p2->y_next_line = 0;
-
- // bg mix
- p2->bg_next_line = 0;
- p2->bg_first_line = ph;
- p2->bg_last_line = 0;
-
- if(!p2->partial_remap)
- _sv_panel2d_mark_map_full(p);
- }
-
- /* by plane, by line; each plane renders independently */
- /* Y planes */
- if(p2->y_planetodo){
- if(p2->y_next_plane < p2->y_obj_num){
- int status = _sv_panel2d_resample_render_y_plane_line(p, thread_cache,
- plot_serialno, map_serialno,
- p2->y_next_plane);
- if(status == -1) goto abort;
- if(status == 1){
- p2->y_next_plane++;
- p2->y_next_line = 0;
- }
- return 1;
- }
- }else{
- p->private->map_complete_count = 0;
- }
-
- /* renders have been completely dispatched, but are they complete? */
- /* the below is effectively a a thread join */
- if(p2->bg_next_line == 0){
-
- // join still needs to complete....
- if(p->private->map_complete_count){
- // nonzero complete count, not finished. returning zero will cause
- // this worker thread to sleep or go on to do other things.
- return 0;
- }else{
- // zero complete count, the planes are done; we can begin
- // background render. At least one thread is guaranteed to get
- // here, which is enough; we can now wake the others [if they were
- // asleep] and have them look for work here. */
- p->private->map_complete_count = ph; // [ph] lines to render in bg plane
- p2->bg_next_line = 0;
-
- _sv_wake_workers();
- }
- }
-
- /* mix new background, again line by line */
- if(p2->bg_next_line < ph){
- int status = _sv_panel2d_render_bg_line(p, plot_serialno, map_serialno);
- if(status == -1) goto abort;
- if(p->private->map_complete_count)return status;
- }else
- return 0; // nothing left to dispatch
-
- // entirely finished.
-
- // remap completed; flush background to screen
- _sv_plot_expose_request_partial (plot,0,p2->bg_first_line,
- pw,p2->bg_last_line - p2->bg_first_line);
- gdk_flush();
-
- // clean bg todo list
- memset(p2->bg_todo,0,ph*sizeof(*p2->bg_todo));
-
- // clear 'panel in progress' flag
- p2->partial_remap = 0;
- _sv_panel_clean_map(p);
- return 0;
-
- abort:
- // reset progress to 'start over'
- return 1;
-}
-
-// looks like a cop-out but is actually the correct thing to do; the
-// data *must* be WYSIWYG from panel display.
-static void _sv_panel2d_print_bg(sv_panel_t *p, cairo_t *c){
- _sv_plot_t *plot = PLOT(p->private->graph);
-
- if(!plot) return;
-
- cairo_pattern_t *pattern = cairo_pattern_create_for_surface(plot->back);
- cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);
- cairo_set_source(c,pattern);
- cairo_paint(c);
-
- cairo_pattern_destroy(pattern);
-}
-
-static void _sv_panel2d_print(sv_panel_t *p, cairo_t *c, int w, int h){
- _sv_panel2d_t *p2 = p->subtype->p2;
- _sv_plot_t *plot = PLOT(p->private->graph);
- double pw = p->private->graph->allocation.width;
- double ph = p->private->graph->allocation.height;
- double scale;
- int i;
- double maxlabelw=0;
- double y;
-
- if(w/pw < h/ph)
- scale = w/pw;
- else
- scale = h/ph;
-
- cairo_matrix_t m;
- cairo_save(c);
- cairo_get_matrix(c,&m);
- cairo_matrix_scale(&m,scale,scale);
- cairo_set_matrix(c,&m);
-
- _sv_plot_print(plot, c, ph*scale, (void(*)(void *, cairo_t *))_sv_panel2d_print_bg, p);
- cairo_restore(c);
-
- // find extents widths for objective scale labels
- cairo_set_font_size(c,10);
- for(i=0;i<p->objectives;i++){
- cairo_text_extents_t ex;
- sv_obj_t *o = p->objective_list[i].o;
- cairo_text_extents(c, o->name, &ex);
- if(ex.width > maxlabelw) maxlabelw=ex.width;
- }
-
-
- y = ph * scale + 10;
-
- for(i=0;i<p->objectives;i++){
- sv_obj_t *o = p->objective_list[i].o;
- _sv_slider_t *s = p2->range_scales[i];
-
- // get scale height
- double labelh = _sv_slider_print_height(s);
- cairo_text_extents_t ex;
- cairo_text_extents (c, o->name, &ex);
-
- int lx = maxlabelw - ex.width;
- int ly = labelh/2 + ex.height/2;
-
- // print objective labels
- cairo_set_source_rgb(c,0.,0.,0.);
- cairo_move_to (c, lx,ly+y);
- cairo_show_text (c, o->name);
-
- // draw slider
- // set translation
- cairo_save(c);
- cairo_translate (c, maxlabelw + 10, y);
- _sv_slider_print(s, c, pw*scale - maxlabelw - 10, labelh);
- cairo_restore(c);
-
- y += labelh;
- }
-
-}
-
-// call while locked
-static void _sv_panel2d_mark_map_plane(sv_panel_t *p, int onum, int y, int z, int v){
- _sv_panel2d_t *p2 = p->subtype->p2;
- int ph = p2->y.pixels;
-
- if(y && p2->y_planetodo){
- int y_no = p2->y_obj_from_panel[onum];
- if(y_no>=0 && p2->y_planetodo[y_no])
- memset(p2->y_planetodo[y_no],1,ph * sizeof(**p2->y_planetodo));
- }
- p2->partial_remap = 1;
-}
-
-// call while locked
-static void _sv_panel2d_mark_map_line_y(sv_panel_t *p, int line){
- // determine all panel lines this y data line affects
- _sv_panel2d_t *p2 = p->subtype->p2;
- int ph = p2->y.pixels;
- int pw = p2->x.pixels;
- int dw = p2->x_v.pixels;
- int dh = p2->y_v.pixels;
- int i,j;
-
- p2->partial_remap = 1;
-
- if(ph!=dh || pw!=dw){
- /* resampled row computation; may involve multiple data rows */
- if(p2->y_planetodo){
- _sv_panel2d_resample_helpers_manage_y(p);
-
- for(i=0;i<ph;i++)
- if(p2->ynumA[i]<=line &&
- p2->ynumB[i]>line){
-
- for(j=0;j<p2->y_obj_num;j++)
- if(p2->y_planetodo[j])
- p2->y_planetodo[j][i]=1;
- }
- }
- }else{
- if(p2->y_planetodo)
- if(line>=0 && line<ph)
- for(j=0;j<p2->y_obj_num;j++)
- if(p2->y_planetodo[j])
- p2->y_planetodo[j][line]=1;
- }
-}
-
-// call while locked
-static void _sv_panel2d_mark_map_full(sv_panel_t *p){
- _sv_panel2d_t *p2 = p->subtype->p2;
- int ph = p2->y.pixels;
- int i,j;
-
- p2->partial_remap = 1;
-
- if(p2->y_planetodo){
- for(j=0;j<p2->y_obj_num;j++){
- if(p2->y_planetodo[j]){
- for(i=0;i<ph;i++){
- p2->y_planetodo[j][i]=1;
- }
- }
- }
- }
-}
-
// enter with lock
static void _sv_panel2d_update_legend(sv_panel_t *p){
_sv_panel2d_t *p2 = p->subtype->p2;
@@ -962,452 +264,6 @@
}
}
-static void _sv_panel2d_mapchange_callback(GtkWidget *w,gpointer in){
- sv_obj_list_t *optr = (sv_obj_list_t *)in;
- //sv_obj_t *o = optr->o;
- sv_panel_t *p = optr->p;
- _sv_panel2d_t *p2 = p->subtype->p2;
- int onum = optr - p->objective_list;
-
- _sv_undo_push();
- _sv_undo_suspend();
-
- _sv_mapping_set_func(&p2->mappings[onum],gtk_combo_box_get_active(GTK_COMBO_BOX(w)));
-
- //redraw the map slider
- _sv_slider_set_gradient(p2->range_scales[onum], &p2->mappings[onum]);
-
- // in the event the mapping active state changed
- _sv_panel_dirty_legend(p);
-
- //redraw the plot
- _sv_panel2d_mark_map_plane(p,onum,1,0,0);
- _sv_panel_dirty_map(p);
- _sv_undo_resume();
-}
-
-static void _sv_panel2d_map_callback(void *in,int buttonstate){
- sv_obj_list_t *optr = (sv_obj_list_t *)in;
- //sv_obj_t *o = optr->o;
- sv_panel_t *p = optr->p;
- _sv_panel2d_t *p2 = p->subtype->p2;
- int onum = optr - p->objective_list;
-
- if(buttonstate == 0){
- _sv_undo_push();
- _sv_undo_suspend();
- }
-
- // recache alpha del */
- p2->alphadel[onum] =
- _sv_slider_val_to_del(p2->range_scales[onum],
- _sv_slider_get_value(p2->range_scales[onum],1));
-
- // redraw the plot on motion
- if(buttonstate == 1){
- _sv_panel2d_mark_map_plane(p,onum,1,0,0);
- _sv_panel_dirty_map(p);
- }
- if(buttonstate == 2)
- _sv_undo_resume();
-}
-
-static void _sv_panel2d_update_xysel(sv_panel_t *p){
- _sv_panel2d_t *p2 = p->subtype->p2;
- int i;
- // update which x/y buttons are pressable */
- // enable/disable dimension slider thumbs
-
- for(i=0;i<p->dimensions;i++){
- if(p2->dim_xb[i] &&
- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p2->dim_xb[i]))){
- // make the y insensitive
- if(p2->dim_yb[i])
- _gtk_widget_set_sensitive_fixup(p2->dim_yb[i],FALSE);
-
- // set the x dim flag
- p->private->x_d = p->dimension_list[i].d;
- p2->x_scale = p->private->dim_scales[i];
- p2->x_dnum = i;
- }else{
- // if there is a y, make it sensitive
- if(p2->dim_yb[i])
- _gtk_widget_set_sensitive_fixup(p2->dim_yb[i],TRUE);
- }
- if(p2->dim_yb[i] &&
- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p2->dim_yb[i]))){
- // make the x insensitive
- if(p2->dim_xb[i])
- _gtk_widget_set_sensitive_fixup(p2->dim_xb[i],FALSE);
-
- // set the y dim
- p->private->y_d = p->dimension_list[i].d;
- p2->y_scale = p->private->dim_scales[i];
- p2->y_dnum = i;
- }else{
- // if there is a x, make it sensitive
- if(p2->dim_xb[i])
- _gtk_widget_set_sensitive_fixup(p2->dim_xb[i],TRUE);
- }
- if((p2->dim_xb[i] &&
- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p2->dim_xb[i]))) ||
- (p2->dim_yb[i] &&
- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p2->dim_yb[i])))){
- // make all thumbs visible
- _sv_dim_widget_set_thumb_active(p->private->dim_scales[i],0,1);
- _sv_dim_widget_set_thumb_active(p->private->dim_scales[i],2,1);
- }else{
- // make bracket thumbs invisible */
- _sv_dim_widget_set_thumb_active(p->private->dim_scales[i],0,0);
- _sv_dim_widget_set_thumb_active(p->private->dim_scales[i],2,0);
- }
- }
-}
-
-static int _v_swizzle(int y, int height){
- int yy = height >> 5;
- if(y < yy)
- return (y<<5)+31;
-
- y -= yy;
- yy = (height+16) >> 5;
- if(y < yy)
- return (y<<5)+15;
-
- y -= yy;
- yy = (height+8) >> 4;
- if(y < yy)
- return (y<<4)+7;
-
- y -= yy;
- yy = (height+4) >> 3;
- if(y < yy)
- return (y<<3)+3;
-
- y -= yy;
- yy = (height+2) >> 2;
- if(y < yy)
- return (y<<2)+1;
-
- y -= yy;
- return y<<1;
-}
-
-// assumes data is locked
-static void _sv_panel2d_fast_scale_x(_sv_spinner_t *sp,
- int *data,
- int w,
- int h,
- _sv_scalespace_t new,
- _sv_scalespace_t old){
- int x,y;
- int work[w];
- int mapbase[w];
- int mapdel[w];
- double old_w = old.pixels;
- double new_w = new.pixels;
-
- double old_lo = _sv_scalespace_value(&old,0);
- double old_hi = _sv_scalespace_value(&old,old_w);
- double new_lo = _sv_scalespace_value(&new,0);
- double new_hi = _sv_scalespace_value(&new,new_w);
- double newscale = (new_hi-new_lo)/new_w;
- double oldscale = old_w/(old_hi-old_lo);
- for(x=0;x<w;x++){
- double xval = (x)*newscale+new_lo;
- double map = ((xval-old_lo)*oldscale);
- int base = (int)floor(map);
- int del = rint((map - floor(map))*64.f);
- /* hack to overwhelm roundoff error; this is inside a purely
- temporary cosmetic approximation anyway*/
- if(base>0 && del==0){
- mapbase[x]=base-1;
- mapdel[x]=64;
- }else{
- mapbase[x]=base;
- mapdel[x]=del;
- }
- }
-
- for(y=0;y<h;y++){
- int *data_line = data+y*w;
- _sv_spinner_set_busy(sp);
- for(x=0;x<w;x++){
- if(mapbase[x]<0 || mapbase[x]>=(w-1)){
- work[x]=-1;
- }else{
- int base = mapbase[x];
- int A = data_line[base];
- int B = data_line[base+1];
- if(A<0 || B<0)
- work[x]=-1;
- else
- work[x]= A + (((B - A)*mapdel[x])>>6);
-
- }
- }
- memcpy(data_line,work,w*(sizeof(*work)));
- }
-}
-
-static void _sv_panel2d_fast_scale_y(_sv_spinner_t *sp,
- int *olddata,
- int *newdata,
- int oldw,
- int neww,
- _sv_scalespace_t new,
- _sv_scalespace_t old){
- int x,y;
- int w = (oldw<neww?oldw:neww);
-
- int old_h = old.pixels;
- int new_h = new.pixels;
-
- int mapbase[new_h];
- int mapdel[new_h];
-
- double old_lo = _sv_scalespace_value(&old,0);
- double old_hi = _sv_scalespace_value(&old,(double)old_h);
- double new_lo = _sv_scalespace_value(&new,0);
- double new_hi = _sv_scalespace_value(&new,(double)new_h);
- double newscale = (new_hi-new_lo)/new_h;
- double oldscale = old_h/(old_hi-old_lo);
-
- for(y=0;y<new_h;y++){
- double yval = (y)*newscale+new_lo;
- double map = ((yval-old_lo)*oldscale);
- int base = (int)floor(map);
- int del = rint((map - floor(map))*64.);
- /* hack to overwhelm roundoff error; this is inside a purely
- temporary cosmetic approximation anyway */
- if(base>0 && del==0){
- mapbase[y]=base-1;
- mapdel[y]=64;
- }else{
- mapbase[y]=base;
- mapdel[y]=del;
- }
- }
-
-
- for(y=0;y<new_h;y++){
- int base = mapbase[y];
- int *new_column = &newdata[y*neww];
- _sv_spinner_set_busy(sp);
-
- if(base<0 || base>=(old_h-1)){
- for(x=0;x<w;x++)
- new_column[x] = -1;
- }else{
- int del = mapdel[y];
- int *old_column = &olddata[base*oldw];
-
- for(x=0;x<w;x++){
- int A = old_column[x];
- int B = old_column[x+oldw];
- if(A<0 || B<0)
- new_column[x]=-1;
- else
- new_column[x]= A + (((B-A)*del)>>6);
- }
- }
- }
-}
-
-static void _sv_panel2d_fast_scale(_sv_spinner_t *sp,
- int *newdata,
- _sv_scalespace_t xnew,
- _sv_scalespace_t ynew,
- int *olddata,
- _sv_scalespace_t xold,
- _sv_scalespace_t yold){
-
- int new_w = xnew.pixels;
- int new_h = ynew.pixels;
- int old_w = xold.pixels;
- int old_h = yold.pixels;
-
- if(new_w > old_w){
- _sv_panel2d_fast_scale_y(sp,olddata,newdata,old_w,new_w,ynew,yold);
- _sv_panel2d_fast_scale_x(sp,newdata,new_w,new_h,xnew,xold);
- }else{
- _sv_panel2d_fast_scale_x(sp,olddata,old_w,old_h,xnew,xold);
- _sv_panel2d_fast_scale_y(sp,olddata,newdata,old_w,new_w,ynew,yold);
- }
-}
-
-// call only from main gtk thread
-static void _sv_panel2d_mark_recompute(sv_panel_t *p){
- if(!p->private->realized) return;
- _sv_plot_t *plot = PLOT(p->private->graph);
-
- if(plot && GTK_WIDGET_REALIZED(GTK_WIDGET(plot))){
- _sv_panel_dirty_plot(p);
- }
-}
-
-static void _sv_panel2d_update_crosshairs(sv_panel_t *p){
- _sv_plot_t *plot = PLOT(p->private->graph);
- double x=0,y=0;
- int i;
-
- for(i=0;i<p->dimensions;i++){
- sv_dim_t *d = p->dimension_list[i].d;
- if(d == p->private->x_d)
- x = d->val;
- if(d == p->private->y_d)
- y = d->val;
-
- }
-
- _sv_plot_set_crosshairs(plot,x,y);
- _sv_panel_dirty_legend(p);
-}
-
-static void _sv_panel2d_center_callback(sv_dim_list_t *dptr){
- sv_dim_t *d = dptr->d;
- sv_panel_t *p = dptr->p;
- int axisp = (d == p->private->x_d || d == p->private->y_d);
-
- if(!axisp){
- // mid slider of a non-axis dimension changed, rerender
- _sv_panel2d_mark_recompute(p);
- }else{
- // mid slider of an axis dimension changed, move crosshairs
- _sv_panel2d_update_crosshairs(p);
- }
-}
-
-static void _sv_panel2d_bracket_callback(sv_dim_list_t *dptr){
- sv_dim_t *d = dptr->d;
- sv_panel_t *p = dptr->p;
- int axisp = (d == p->private->x_d || d == p->private->y_d);
-
- if(axisp)
- _sv_panel2d_mark_recompute(p);
-
-}
-
-static void _sv_panel2d_dimchange_callback(GtkWidget *button,gpointer in){
- sv_panel_t *p = (sv_panel_t *)in;
-
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))){
-
- _sv_undo_push();
- _sv_undo_suspend();
-
- _sv_plot_unset_box(PLOT(p->private->graph));
- _sv_panel2d_update_xysel(p);
-
- _sv_panel2d_clear_pane(p);
- _sv_panel2d_mark_recompute(p);
- _sv_panel2d_update_crosshairs(p);
-
- _sv_undo_resume();
- }
-}
-
-static void _sv_panel2d_crosshairs_callback(sv_panel_t *p){
- double x=PLOT(p->private->graph)->selx;
- double y=PLOT(p->private->graph)->sely;
- int i;
-
- _sv_undo_push();
- _sv_undo_suspend();
-
- //plot_snap_crosshairs(PLOT(p->private->graph));
-
- for(i=0;i<p->dimensions;i++){
- sv_dim_t *d = p->dimension_list[i].d;
- if(d == p->private->x_d){
- _sv_dim_widget_set_thumb(p->private->dim_scales[i],1,x);
- }
-
- if(d == p->private->y_d){
- _sv_dim_widget_set_thumb(p->private->dim_scales[i],1,y);
- }
-
- p->private->oldbox_active = 0;
- }
-
- // dimension setting might have enforced granularity restrictions;
- // have the display reflect that
- x = p->private->x_d->val;
- y = p->private->y_d->val;
-
- _sv_plot_set_crosshairs(PLOT(p->private->graph),x,y);
-
- _sv_panel_dirty_legend(p);
- _sv_undo_resume();
-}
-
-static void _sv_panel2d_box_callback(void *in, int state){
- sv_panel_t *p = (sv_panel_t *)in;
- _sv_panel2d_t *p2 = p->subtype->p2;
- _sv_plot_t *plot = PLOT(p->private->graph);
-
- switch(state){
- case 0: // box set
- _sv_undo_push();
- _sv_plot_box_vals(plot,p2->oldbox);
- p->private->oldbox_active = plot->box_active;
- break;
- case 1: // box activate
- _sv_undo_push();
- _sv_undo_suspend();
-
- _sv_panel2d_crosshairs_callback(p);
-
- _sv_dim_widget_set_thumb(p2->x_scale,0,p2->oldbox[0]);
- _sv_dim_widget_set_thumb(p2->x_scale,2,p2->oldbox[1]);
- _sv_dim_widget_set_thumb(p2->y_scale,0,p2->oldbox[2]);
- _sv_dim_widget_set_thumb(p2->y_scale,2,p2->oldbox[3]);
- p->private->oldbox_active = 0;
- _sv_undo_resume();
- break;
- }
- _sv_panel_update_menus(p);
-}
-
-void _sv_panel2d_maintain_cache(sv_panel_t *p, _sv_bythread_cache_2d_t *c, int w){
- _sv_panel2d_t *p2 = p->subtype->p2;
-
- /* toplevel initialization */
- if(c->fout == 0){
- int i,count=0;
-
- /* allocate output temporary buffer */
- for(i=0;i<p2->used_functions;i++){
- int fnum = p2->used_function_list[i]->number;
- sv_func_t *f = _sv_function_list[fnum];
- count += f->outputs;
- }
- c->fout = calloc(count, sizeof(*c->fout));
-
- /* objective line buffer index */
- c->y_map = calloc(p2->y_obj_num,sizeof(*c->y_map));
- for(i=0;i<p2->y_obj_num;i++)
- c->y_map[i] = calloc(w,sizeof(**c->y_map));
- c->storage_width = w;
- }
-
- /* anytime the data width changes */
- if(c->storage_width != w){
- int i;
- c->storage_width = w;
-
- for(i=0;i<p2->y_obj_num;i++)
- c->y_map[i] = realloc(c->y_map[i],w*sizeof(**c->y_map));
-
- }
-}
-
-
-// subtype entry point for plot remaps; lock held
-static int _sv_panel2d_map_redraw(sv_panel_t *p, _sv_bythread_cache_t *c){
- return _sv_panel2d_remap(p,&c->p2);
-}
-
// subtype entry point for legend redraws; lock held
static int _sv_panel2d_legend_redraw(sv_panel_t *p){
_sv_plot_t *plot = PLOT(p->private->graph);
@@ -1425,659 +281,3 @@
return 1;
}
-// subtype entry point for recomputation; lock held
-static int _sv_panel2d_compute(sv_panel_t *p,
- _sv_bythread_cache_t *c){
-
- _sv_panel2d_t *p2 = p->subtype->p2;
- _sv_plot_t *plot;
-
- int pw,ph,dw,dh,i,d;
- int serialno;
- double x_min, x_max;
- double y_min, y_max;
- int x_d=-1, y_d=-1;
- _sv_scalespace_t sx,sx_v,sx_i;
- _sv_scalespace_t sy,sy_v,sy_i;
-
- plot = PLOT(p->private->graph);
- pw = plot->x.pixels;
- ph = plot->y.pixels;
-
- x_d = p->private->x_d->number;
- y_d = p->private->y_d->number;
-
- // beginning of computation init
- if(p->private->plot_progress_count==0){
- int remapflag = 0;
-
- _sv_scalespace_t old_x = p2->x;
- _sv_scalespace_t old_y = p2->y;
- _sv_scalespace_t old_xv = p2->x_v;
- _sv_scalespace_t old_yv = p2->y_v;
-
- // generate new scales
- _sv_dim_scales(p->private->x_d,
- p->private->x_d->bracket[0],
- p->private->x_d->bracket[1],
- pw,pw * p->private->oversample_n / p->private->oversample_d,
- plot->scalespacing,
- p->private->x_d->legend,
- &sx,
- &sx_v,
- &sx_i);
- _sv_dim_scales(p->private->y_d,
- p->private->y_d->bracket[1],
- p->private->y_d->bracket[0],
- ph,ph * p->private->oversample_n / p->private->oversample_d,
- plot->scalespacing,
- p->private->y_d->legend,
- &sy,
- &sy_v,
- &sy_i);
-
- p2->x = sx;
- p2->x_v = sx_v;
- p2->x_i = sx_i;
- p2->y = sy;
- p2->y_v = sy_v;
- p2->y_i = sy_i;
-
- plot->x = sx;
- plot->y = sy;
- plot->x_v = sx_v;
- plot->y_v = sy_v;
-
- p->private->plot_progress_count++;
- p->private->plot_serialno++; // we're about to free the old data rectangles
-
- // realloc/fast scale the current data contents if appropriate
- if(memcmp(&sx_v,&old_xv,sizeof(sx_v)) || memcmp(&sy_v,&old_yv,sizeof(sy_v))){
-
- // maintain data planes
- for(i=0;i<p2->y_obj_num;i++){
- // allocate new storage
- int *newmap = calloc(sx_v.pixels*sy_v.pixels,sizeof(*newmap));
- int *oldmap = p2->y_map[i];
- int j;
-
- for(j=0;j<sx_v.pixels*sy_v.pixels;j++)
- newmap[j]=-1;
-
- // zoom scale data in map planes as placeholder for render
- if(oldmap){
- _sv_panel2d_fast_scale(p->private->spinner,newmap, sx_v, sy_v,
- oldmap,old_xv, old_yv);
- free(oldmap);
- }
- p2->y_map[i] = newmap;
- }
- remapflag = 1;
- }
-
- // realloc render planes if appropriate
- if(memcmp(&sx,&old_x,sizeof(sx)) || memcmp(&sy,&old_y,sizeof(sy))){
- for(i=0;i<p2->y_obj_num;i++){
-
- // y planes
- if(p2->y_planes[i])
- free(p2->y_planes[i]);
- p2->y_planes[i] = calloc(sx.pixels*sy.pixels,sizeof(**p2->y_planes));
-
- // todo lists
- if(p2->y_planetodo[i])
- free(p2->y_planetodo[i]);
- p2->y_planetodo[i] = calloc(sy.pixels,sizeof(**p2->y_planetodo));
-
- }
-
- if(p2->bg_todo)
- free(p2->bg_todo);
- p2->bg_todo=calloc(ph,sizeof(*p2->bg_todo));
-
- remapflag = 1;
- }
-
- if(remapflag){
- _sv_panel2d_mark_map_full(p);
- _sv_panel_dirty_map(p);
-
- gdk_unlock ();
- _sv_plot_draw_scales(plot); // this should happen outside lock
- gdk_lock ();
- }
-
- _sv_map_set_throttle_time(p); // swallow the first 'throttled' remap which would only be a single line;
-
- return 1;
- }else{
- sx = p2->x;
- sx_v = p2->x_v;
- sx_i = p2->x_i;
- sy = p2->y;
- sy_v = p2->y_v;
- sy_i = p2->y_i;
- serialno = p->private->plot_serialno;
- }
-
- dw = sx_v.pixels;
- dh = sy_v.pixels;
-
- if(p->private->plot_progress_count>dh) return 0;
-
- _sv_panel2d_maintain_cache(p,&c->p2,dw);
-
- d = p->dimensions;
-
- /* render using local dimension array; several threads will be
- computing objectives */
- double dim_vals[_sv_dimensions];
- int y = _v_swizzle(p->private->plot_progress_count-1,dh);
- p->private->plot_progress_count++;
-
- x_min = _sv_scalespace_value(&p2->x_i,0);
- x_max = _sv_scalespace_value(&p2->x_i,dw);
-
- y_min = _sv_scalespace_value(&p2->y_i,0);
- y_max = _sv_scalespace_value(&p2->y_i,dh);
-
- // Initialize local dimension value array
- for(i=0;i<_sv_dimensions;i++){
- sv_dim_t *dim = _sv_dimension_list[i];
- dim_vals[i]=dim->val;
- }
-
- /* unlock for computation */
- gdk_unlock ();
-
- dim_vals[y_d]=_sv_scalespace_value(&sy_i, y);
- _sv_panel2d_compute_line(p, serialno, dw, y, x_d, sx_i, dim_vals, &c->p2);
-
- gdk_lock ();
-
- if(p->private->plot_serialno == serialno){
- p->private->plot_complete_count++;
- _sv_panel2d_mark_map_line_y(p,y);
- if(p->private->plot_complete_count>=dh){
- _sv_panel_dirty_map(p);
- _sv_panel_dirty_legend(p);
- _sv_panel_clean_plot(p);
- }else
- _sv_panel_dirty_map_throttled(p);
- }
-
- return 1;
-}
-
-// only called for resize events
-static void _sv_panel2d_recompute_callback(void *ptr){
- sv_panel_t *p = (sv_panel_t *)ptr;
- int i;
-
- gdk_lock ();
- _sv_panel2d_mark_recompute(p);
- _sv_panel2d_compute(p,NULL); // initial scale setup
-
- // temporary: blank background to checks
- _sv_plot_t *plot = PLOT(p->private->graph);
- int pw = plot->x.pixels;
- int ph = plot->y.pixels;
- for(i=0;i<ph;i++)
- render_checks((_sv_ucolor_t *)plot->datarect+pw*i, pw, i);
-
- gdk_unlock();
-}
-
-static void _sv_panel2d_undo_log(_sv_panel_undo_t *u, sv_panel_t *p){
- _sv_panel2d_t *p2 = p->subtype->p2;
- int i;
-
- // alloc fields as necessary
-
- if(!u->mappings)
- u->mappings = calloc(p->objectives,sizeof(*u->mappings));
- if(!u->scale_vals[0])
- u->scale_vals[0] = calloc(p->objectives,sizeof(**u->scale_vals));
- if(!u->scale_vals[1])
- u->scale_vals[1] = calloc(p->objectives,sizeof(**u->scale_vals));
- if(!u->scale_vals[2])
- u->scale_vals[2] = calloc(p->objectives,sizeof(**u->scale_vals));
-
- // populate undo
- for(i=0;i<p->objectives;i++){
- u->mappings[i] = p2->mappings[i].mapnum;
- u->scale_vals[0][i] = _sv_slider_get_value(p2->range_scales[i],0);
- u->scale_vals[1][i] = _sv_slider_get_value(p2->range_scales[i],1);
- u->scale_vals[2][i] = _sv_slider_get_value(p2->range_scales[i],2);
- }
-
- u->x_d = p2->x_dnum;
- u->y_d = p2->y_dnum;
- u->box[0] = p2->oldbox[0];
- u->box[1] = p2->oldbox[1];
- u->box[2] = p2->oldbox[2];
- u->box[3] = p2->oldbox[3];
- u->box_active = p->private->oldbox_active;
-}
-
-static void _sv_panel2d_undo_restore(_sv_panel_undo_t *u, sv_panel_t *p){
- _sv_panel2d_t *p2 = p->subtype->p2;
- _sv_plot_t *plot = PLOT(p->private->graph);
- int i;
-
- // go in through widgets
- for(i=0;i<p->objectives;i++){
- gtk_combo_box_set_active(GTK_COMBO_BOX(p2->range_pulldowns[i]),u->mappings[i]);
- _sv_slider_set_value(p2->range_scales[i],0,u->scale_vals[0][i]);
- _sv_slider_set_value(p2->range_scales[i],1,u->scale_vals[1][i]);
- _sv_slider_set_value(p2->range_scales[i],2,u->scale_vals[2][i]);
- }
-
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p2->dim_xb[u->x_d]),TRUE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p2->dim_yb[u->y_d]),TRUE);
-
- _sv_panel2d_update_xysel(p);
-
- if(u->box_active){
- p2->oldbox[0] = u->box[0];
- p2->oldbox[1] = u->box[1];
- p2->oldbox[2] = u->box[2];
- p2->oldbox[3] = u->box[3];
- _sv_plot_box_set(plot,u->box);
- p->private->oldbox_active = 1;
- }else{
- _sv_plot_unset_box(plot);
- p->private->oldbox_active = 0;
- }
-}
-
-static void _sv_panel2d_realize(sv_panel_t *p){
- _sv_panel2d_t *p2 = p->subtype->p2;
- int i;
-
- _sv_undo_suspend();
-
- p->private->toplevel = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- g_signal_connect_swapped (G_OBJECT (p->private->toplevel), "delete-event",
- G_CALLBACK (_sv_clean_exit), (void *)SIGINT);
-
- // add border to sides with hbox/padding
- GtkWidget *borderbox = gtk_hbox_new(0,0);
- gtk_container_add (GTK_CONTAINER (p->private->toplevel), borderbox);
-
- // main layout vbox
- p->private->topbox = gtk_vbox_new(0,0);
- gtk_box_pack_start(GTK_BOX(borderbox), p->private->topbox, 1,1,4);
- gtk_container_set_border_width (GTK_CONTAINER (p->private->toplevel), 1);
-
- /* spinner, top bar */
- {
- GtkWidget *hbox = gtk_hbox_new(0,0);
- gtk_box_pack_start(GTK_BOX(p->private->topbox), hbox, 0,0,0);
- gtk_box_pack_end(GTK_BOX(hbox),GTK_WIDGET(p->private->spinner),0,0,0);
- }
-
- /* plotbox, graph */
- {
- p->private->graph = GTK_WIDGET(_sv_plot_new(_sv_panel2d_recompute_callback,p,
- (void *)(void *)_sv_panel2d_crosshairs_callback,p,
- _sv_panel2d_box_callback,p,0));
- p->private->plotbox = p->private->graph;
- gtk_box_pack_start(GTK_BOX(p->private->topbox), p->private->plotbox, 1,1,2);
- }
-
- /* obj box */
- {
- p2->obj_table = gtk_table_new(p->objectives, 5, 0);
- gtk_box_pack_start(GTK_BOX(p->private->topbox), p2->obj_table, 0,0,1);
-
- /* objective sliders */
- p2->range_scales = calloc(p->objectives,sizeof(*p2->range_scales));
- p2->range_pulldowns = calloc(p->objectives,sizeof(*p2->range_pulldowns));
- p2->alphadel = calloc(p->objectives,sizeof(*p2->alphadel));
- p2->mappings = calloc(p->objectives,sizeof(*p2->mappings));
- for(i=0;i<p->objectives;i++){
- GtkWidget **sl = calloc(3,sizeof(*sl));
- sv_obj_t *o = p->objective_list[i].o;
- int lo = o->scale->val_list[0];
- int hi = o->scale->val_list[o->scale->vals-1];
-
- /* label */
- GtkWidget *label = gtk_label_new(o->name);
- gtk_misc_set_alignment(GTK_MISC(label),1.,.5);
- gtk_table_attach(GTK_TABLE(p2->obj_table),label,0,1,i,i+1,
- GTK_FILL,0,8,0);
-
- /* mapping pulldown */
- {
- GtkWidget *menu=_gtk_combo_box_new_markup();
- int j;
- for(j=0;j<_sv_mapping_names();j++)
- gtk_combo_box_append_text (GTK_COMBO_BOX (menu), _sv_mapping_name(j));
- gtk_combo_box_set_active(GTK_COMBO_BOX(menu),0);
- g_signal_connect (G_OBJECT (menu), "changed",
- G_CALLBACK (_sv_panel2d_mapchange_callback), p->objective_list+i);
- gtk_table_attach(GTK_TABLE(p2->obj_table),menu,4,5,i,i+1,
- GTK_SHRINK,GTK_SHRINK,0,0);
- p2->range_pulldowns[i] = menu;
- }
-
- /* the range mapping slices/slider */
- sl[0] = _sv_slice_new(_sv_panel2d_map_callback,p->objective_list+i);
- sl[1] = _sv_slice_new(_sv_panel2d_map_callback,p->objective_list+i);
- sl[2] = _sv_slice_new(_sv_panel2d_map_callback,p->objective_list+i);
-
- gtk_table_attach(GTK_TABLE(p2->obj_table),sl[0],1,2,i,i+1,
- GTK_EXPAND|GTK_FILL,0,0,0);
- gtk_table_attach(GTK_TABLE(p2->obj_table),sl[1],2,3,i,i+1,
- GTK_EXPAND|GTK_FILL,0,0,0);
- gtk_table_attach(GTK_TABLE(p2->obj_table),sl[2],3,4,i,i+1,
- GTK_EXPAND|GTK_FILL,0,0,0);
- p2->range_scales[i] = _sv_slider_new((_sv_slice_t **)sl,3,o->scale->label_list,o->scale->val_list,
- o->scale->vals,_SV_SLIDER_FLAG_INDEPENDENT_MIDDLE);
- gtk_table_set_col_spacing(GTK_TABLE(p2->obj_table),3,5);
-
- _sv_slice_thumb_set((_sv_slice_t *)sl[0],lo);
- _sv_slice_thumb_set((_sv_slice_t *)sl[1],lo);
- _sv_slice_thumb_set((_sv_slice_t *)sl[2],hi);
- _sv_mapping_setup(&p2->mappings[i],0.,1.,0);
- _sv_slider_set_gradient(p2->range_scales[i], &p2->mappings[i]);
- }
- }
-
- /* dims */
- {
- p2->dim_table = gtk_table_new(p->dimensions,4,0);
- gtk_box_pack_start(GTK_BOX(p->private->topbox), p2->dim_table, 0,0,4);
-
- GtkWidget *first_x = NULL;
- GtkWidget *first_y = NULL;
- GtkWidget *pressed_y = NULL;
- p->private->dim_scales = calloc(p->dimensions,sizeof(*p->private->dim_scales));
- p2->dim_xb = calloc(p->dimensions,sizeof(*p2->dim_xb));
- p2->dim_yb = calloc(p->dimensions,sizeof(*p2->dim_yb));
-
- for(i=0;i<p->dimensions;i++){
- sv_dim_t *d = p->dimension_list[i].d;
-
- /* label */
- GtkWidget *label = gtk_label_new(d->legend);
- gtk_misc_set_alignment(GTK_MISC(label),1.,.5);
- gtk_table_attach(GTK_TABLE(p2->dim_table),label,0,1,i,i+1,
- GTK_FILL,0,5,0);
-
- /* x/y radio buttons */
- if(!(d->flags & SV_DIM_NO_X)){
- if(first_x)
- p2->dim_xb[i] = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(first_x),"X");
- else{
- first_x = p2->dim_xb[i] = gtk_radio_button_new_with_label(NULL,"X");
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p2->dim_xb[i]),TRUE);
- }
- gtk_table_attach(GTK_TABLE(p2->dim_table),p2->dim_xb[i],1,2,i,i+1,
- GTK_SHRINK,0,3,0);
- }
-
- if(!(d->flags & SV_DIM_NO_Y)){
- if(first_y)
- p2->dim_yb[i] = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(first_y),"Y");
- else
- first_y = p2->dim_yb[i] = gtk_radio_button_new_with_label(NULL,"Y");
- if(!pressed_y && p2->dim_xb[i]!=first_x){
- pressed_y = p2->dim_yb[i];
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p2->dim_yb[i]),TRUE);
- }
- gtk_table_attach(GTK_TABLE(p2->dim_table),p2->dim_yb[i],2,3,i,i+1,
- GTK_SHRINK,0,3,0);
- }
-
- p->private->dim_scales[i] =
- _sv_dim_widget_new(p->dimension_list+i,_sv_panel2d_center_callback,_sv_panel2d_bracket_callback);
-
- gtk_table_attach(GTK_TABLE(p2->dim_table),
- p->private->dim_scales[i]->t,
- 3,4,i,i+1,
- GTK_EXPAND|GTK_FILL,0,0,0);
-
- }
- for(i=0;i<p->dimensions;i++){
- if(p2->dim_xb[i])
- g_signal_connect (G_OBJECT (p2->dim_xb[i]), "toggled",
- G_CALLBACK (_sv_panel2d_dimchange_callback), p);
- if(p2->dim_yb[i])
- g_signal_connect (G_OBJECT (p2->dim_yb[i]), "toggled",
- G_CALLBACK (_sv_panel2d_dimchange_callback), p);
- }
- }
-
- _sv_panel2d_update_xysel(p);
-
- gtk_widget_realize(p->private->toplevel);
- gtk_widget_realize(p->private->graph);
- gtk_widget_realize(GTK_WIDGET(p->private->spinner));
- gtk_widget_show_all(p->private->toplevel);
- _sv_panel2d_update_xysel(p); // yes, this was already done; however,
- // gtk clobbered the event setup on the
- // insensitive buttons when it realized
- // them. This call will restore them.
-
- _sv_undo_resume();
-}
-
-static int _sv_panel2d_save(sv_panel_t *p, xmlNodePtr pn){
- _sv_panel2d_t *p2 = p->subtype->p2;
- int ret=0,i;
-
- xmlNodePtr n;
-
- xmlNewProp(pn, (xmlChar *)"type", (xmlChar *)"2d");
-
- // box
- if(p->private->oldbox_active){
- xmlNodePtr boxn = xmlNewChild(pn, NULL, (xmlChar *) "box", NULL);
- _xmlNewPropF(boxn, "x1", p2->oldbox[0]);
- _xmlNewPropF(boxn, "x2", p2->oldbox[1]);
- _xmlNewPropF(boxn, "y1", p2->oldbox[2]);
- _xmlNewPropF(boxn, "y2", p2->oldbox[3]);
- }
-
- // objective map settings
- for(i=0;i<p->objectives;i++){
- sv_obj_t *o = p->objective_list[i].o;
- xmlNodePtr on = xmlNewChild(pn, NULL, (xmlChar *) "objective", NULL);
- _xmlNewPropI(on, "position", i);
- _xmlNewPropI(on, "number", o->number);
- _xmlNewPropS(on, "name", o->name);
- _xmlNewPropS(on, "type", o->output_types);
-
- // right now Y is the only type; the below is Y-specific
- n = xmlNewChild(on, NULL, (xmlChar *) "y-map", NULL);
- _xmlNewPropS(n, "color", _sv_mapping_name(p2->mappings[i].mapnum));
- _xmlNewPropF(n, "low-bracket", _sv_slider_get_value(p2->range_scales[i],0));
- _xmlNewPropF(n, "alpha", _sv_slider_get_value(p2->range_scales[i],1));
- _xmlNewPropF(n, "high-bracket", _sv_slider_get_value(p2->range_scales[i],2));
- }
-
- // x/y dim selection
- n = xmlNewChild(pn, NULL, (xmlChar *) "axes", NULL);
- _xmlNewPropI(n, "xpos", p2->x_dnum);
- _xmlNewPropI(n, "ypos", p2->y_dnum);
-
- return ret;
-}
-
-int _sv_panel2d_load(sv_panel_t *p,
- _sv_panel_undo_t *u,
- xmlNodePtr pn,
- int warn){
- int i;
-
- // check type
- _xmlCheckPropS(pn,"type","2d", "Panel %d type mismatch in save file.",p->number,&warn);
-
- // box
- u->box_active = 0;
- _xmlGetChildPropFPreserve(pn, "box", "x1", &u->box[0]);
- _xmlGetChildPropFPreserve(pn, "box", "x2", &u->box[1]);
- _xmlGetChildPropFPreserve(pn, "box", "y1", &u->box[2]);
- _xmlGetChildPropFPreserve(pn, "box", "y2", &u->box[3]);
-
- xmlNodePtr n = _xmlGetChildS(pn, "box", NULL, NULL);
- if(n){
- u->box_active = 1;
- xmlFree(n);
- }
-
- // objective map settings
- for(i=0;i<p->objectives;i++){
- sv_obj_t *o = p->objective_list[i].o;
- xmlNodePtr on = _xmlGetChildI(pn, "objective", "position", i);
- if(!on){
- _sv_first_load_warning(&warn);
- fprintf(stderr,"No save data found for panel %d objective \"%s\".\n",p->number, o->name);
- }else{
- // check name, type
- _xmlCheckPropS(on,"name",o->name, "Objectve position %d name mismatch in save file.",i,&warn);
- _xmlCheckPropS(on,"type",o->output_types, "Objectve position %d type mismatch in save file.",i,&warn);
-
- // right now Y is the only type; the below is Y-specific
- // load maptype, values
- _xmlGetChildPropFPreserve(on, "y-map", "low-bracket", &u->scale_vals[0][i]);
- _xmlGetChildPropFPreserve(on, "y-map", "alpha", &u->scale_vals[1][i]);
- _xmlGetChildPropFPreserve(on, "y-map", "high-bracket", &u->scale_vals[2][i]);
- _xmlGetChildMap(on, "y-map", "color", _sv_mapping_map(), &u->mappings[i],
- "Panel %d objective unknown mapping setting", p->number, &warn);
-
- xmlFreeNode(on);
- }
- }
-
- // x/y dim selection
- _xmlGetChildPropIPreserve(pn, "axes", "xpos", &u->x_d);
- _xmlGetChildPropI(pn, "axes", "ypos", &u->y_d);
-
- return warn;
-}
-
-sv_panel_t *sv_panel_new_2d(int number,
- char *name,
- char *objectivelist,
- char *dimensionlist,
- unsigned flags){
-
- int i,j;
- sv_panel_t *p = _sv_panel_new(number,name,objectivelist,dimensionlist,flags);
- if(!p)return NULL;
-
- _sv_panel2d_t *p2 = calloc(1, sizeof(*p2));
- int fout_offsets[_sv_functions];
-
- p->subtype =
- calloc(1, sizeof(*p->subtype)); /* the union is alloced not
- embedded as its internal
- structure must be hidden */
- p->subtype->p2 = p2;
- p->type = SV_PANEL_2D;
- p->private->bg_type = SV_BG_CHECKS;
-
- // verify all the objectives have scales
- for(i=0;i<p->objectives;i++){
- if(!p->objective_list[i].o->scale){
- fprintf(stderr,"All objectives in a 2d panel must have a scale\n");
- errno = -EINVAL;
- return NULL;
- }
- }
-
- p->private->realize = _sv_panel2d_realize;
- p->private->map_action = _sv_panel2d_map_redraw;
- p->private->legend_action = _sv_panel2d_legend_redraw;
- p->private->compute_action = _sv_panel2d_compute;
- p->private->request_compute = _sv_panel2d_mark_recompute;
- p->private->crosshair_action = _sv_panel2d_crosshairs_callback;
- p->private->print_action = _sv_panel2d_print;
- p->private->undo_log = _sv_panel2d_undo_log;
- p->private->undo_restore = _sv_panel2d_undo_restore;
- p->private->save_action = _sv_panel2d_save;
- p->private->load_action = _sv_panel2d_load;
-
- /* set up helper data structures for rendering */
-
- /* determine which functions are actually needed; if it's referenced
- by an objective, it's used. Precache them in dense form. */
- {
- int fn = _sv_functions;
- int used[fn],count=0,offcount=0;
- memset(used,0,sizeof(used));
- memset(fout_offsets,-1,sizeof(fout_offsets));
-
- for(i=0;i<p->objectives;i++){
- sv_obj_t *o = p->objective_list[i].o;
- for(j=0;j<o->outputs;j++)
- used[o->function_map[j]]=1;
- }
-
- for(i=0;i<fn;i++)
- if(used[i]){
- sv_func_t *f = _sv_function_list[i];
- fout_offsets[i] = offcount;
- offcount += f->outputs;
- count++;
- }
-
- p2->used_functions = count;
- p2->used_function_list = calloc(count, sizeof(*p2->used_function_list));
-
- for(count=0,i=0;i<fn;i++)
- if(used[i]){
- p2->used_function_list[count]=_sv_function_list[i];
- count++;
- }
- }
-
- /* set up computation/render helpers for Y planes */
-
- /* set up Y object mapping index */
- {
- int yobj_count = 0;
-
- for(i=0;i<p->objectives;i++){
- sv_obj_t *o = p->objective_list[i].o;
- if(o->private->y_func) yobj_count++;
- }
-
- p2->y_obj_num = yobj_count;
- p2->y_obj_list = calloc(yobj_count, sizeof(*p2->y_obj_list));
- p2->y_obj_to_panel = calloc(yobj_count, sizeof(*p2->y_obj_to_panel));
- p2->y_obj_from_panel = calloc(p->objectives, sizeof(*p2->y_obj_from_panel));
-
- yobj_count=0;
- for(i=0;i<p->objectives;i++){
- sv_obj_t *o = p->objective_list[i].o;
- if(o->private->y_func){
- p2->y_obj_list[yobj_count] = o;
- p2->y_obj_to_panel[yobj_count] = i;
- p2->y_obj_from_panel[i] = yobj_count;
- yobj_count++;
- }else
- p2->y_obj_from_panel[i] = -1;
-
- }
- }
-
- /* set up function Y output value demultiplex helper */
- {
- p2->y_fout_offset = calloc(p2->y_obj_num, sizeof(*p2->y_fout_offset));
- for(i=0;i<p2->y_obj_num;i++){
- sv_obj_t *o = p2->y_obj_list[i];
- int funcnum = o->private->y_func->number;
- p2->y_fout_offset[i] = fout_offsets[funcnum] + o->private->y_fout;
- }
- }
-
- p2->y_map = calloc(p2->y_obj_num,sizeof(*p2->y_map));
- p2->y_planetodo = calloc(p2->y_obj_num,sizeof(*p2->y_planetodo));
- p2->y_planes = calloc(p2->y_obj_num,sizeof(*p2->y_planes));
-
- return p;
-}
Modified: trunk/sushivision/spinner.c
===================================================================
--- trunk/sushivision/spinner.c 2007-10-18 07:39:37 UTC (rev 14010)
+++ trunk/sushivision/spinner.c 2007-10-18 14:32:30 UTC (rev 14011)
@@ -94,10 +94,12 @@
}
static gint _sv_spinner_expose (GtkWidget *widget,
- GdkEventExpose *event){
+ GdkEventExpose *event){
if (GTK_WIDGET_REALIZED (widget)){
_sv_spinner_t *sp = SPINNER (widget);
+ pthread_mutex_lock(spinner->spinner_m);
int frame = (sp->busy?sp->busy_count+1:0);
+ pthread_mutex_unlock(spinner->spinner_m);
// blit to window
if(sp->b && sp->b[frame]){
@@ -219,42 +221,49 @@
return spinner_type;
}
-_sv_spinner_t *_sv_spinner_new (){
+static void *spinthread(sv_spinner_t *spinner){
+ pthread_mutex_lock(spinner->spinner_m);
+ while(p->busy_pending){
+ pthread_mutex_unlock(spinner->spinner_m);
+ gdk_threads_enter();
+ _sv_spinner_expose(GTK_WIDGET(p),NULL);
+ gdk_threads_leave();
+ usleep(100000);
+ pthread_mutex_lock(spinner->spinner_m);
+ p->busy_count++;
+ if(p->busy_count>7)
+ p->busy_count=0;
+ }
+
+ spinner->busy=0;
+ pthread_mutex_unlock(spinner->spinner_m);
+ _sv_spinner_expose(GTK_WIDGET(p),NULL);
+ return 0;
+}
+
+sv_spinner_t *_sv_spinner_new (){
GtkWidget *g = GTK_WIDGET (g_object_new (SPINNER_TYPE, NULL));
- _sv_spinner_t *p = SPINNER (g);
+ sv_spinner_t *p = SPINNER (g);
+ p->spinner_m = PTHREAD_MUTEX_INITIALIZER;
return p;
}
void _sv_spinner_set_busy(_sv_spinner_t *p){
- struct timeval now;
- int test;
-
if(!p)return;
-
- gettimeofday(&now,NULL);
-
+ pthread_mutex_lock(spinner->spinner_m);
if(!p->busy){
+ pthread_t dummy;
p->busy=1;
- p->last = now;
- _sv_spinner_expose(GTK_WIDGET(p),NULL); // do it now
- }else{
-
- test = (now.tv_sec - p->last.tv_sec)*1000 + (now.tv_usec - p->last.tv_usec)/1000;
- if(test>100) {
-
- p->busy_count++;
-
- if(p->busy_count>7)
- p->busy_count=0;
- p->last = now;
- _sv_spinner_expose(GTK_WIDGET(p),NULL); // do it now
- }
+ p->busy_pending=1;
+ pthread_create(&dummy, NULL, &spinthread, NULL);
}
+ pthread_mutex_unlock(spinner->spinner_m);
}
void _sv_spinner_set_idle(_sv_spinner_t *p){
if(!p)return;
- p->busy=0;
- _sv_spinner_expose(GTK_WIDGET(p),NULL); // do it now
+ pthread_mutex_lock(spinner->spinner_m);
+ p->busy_pending=0;
+ pthread_mutex_unlock(spinner->spinner_m);
}
Modified: trunk/sushivision/spinner.h
===================================================================
--- trunk/sushivision/spinner.h 2007-10-18 07:39:37 UTC (rev 14010)
+++ trunk/sushivision/spinner.h 2007-10-18 14:32:30 UTC (rev 14011)
@@ -24,18 +24,18 @@
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <sys/types.h>
-#include <sys/time.h>
+#include <unistd.h>
G_BEGIN_DECLS
#define SPINNER_TYPE (_sv_spinner_get_type ())
-#define SPINNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPINNER_TYPE, _sv_spinner_t))
-#define SPINNER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPINNER_TYPE, _sv_spinner_class_t))
+#define SPINNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPINNER_TYPE, sv_spinner_t))
+#define SPINNER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPINNER_TYPE, sv_spinner_class_t))
#define IS_SPINNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPINNER_TYPE))
#define IS_SPINNER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPINNER_TYPE))
-typedef struct _sv_spinner _sv_spinner_t;
-typedef struct _sv_spinner_class _sv_spinner_class_t;
+typedef struct _sv_spinner sv_spinner_t;
+typedef struct _sv_spinner_class sv_spinner_class_t;
struct _sv_spinner{
GtkWidget w;
@@ -43,13 +43,14 @@
cairo_surface_t *b[9];
int busy;
+ int busy_pending;
int busy_count;
- struct timeval last;
+ pthread_mutex_t spinner_m;
};
struct _sv_spinner_class{
GtkWidgetClass parent_class;
- void (*spinner) (_sv_spinner_t *m);
+ void (*spinner) (sv_spinner_t *m);
};
GType _sv_spinner_get_type (void);
@@ -58,5 +59,5 @@
G_END_DECLS
// the widget subclass half
-void _sv_spinner_set_busy(_sv_spinner_t *p);
-void _sv_spinner_set_idle(_sv_spinner_t *p);
+void _sv_spinner_set_busy(sv_spinner_t *p);
+void _sv_spinner_set_idle(ssv_spinner_t *p);
Modified: trunk/sushivision/sushivision.h
===================================================================
--- trunk/sushivision/sushivision.h 2007-10-18 07:39:37 UTC (rev 14010)
+++ trunk/sushivision/sushivision.h 2007-10-18 14:32:30 UTC (rev 14011)
@@ -33,7 +33,7 @@
extern int sv_wake(void);
extern int sv_join(void);
extern int sv_suspend(int);
-extern int sv_unsuspend(void);
+extern int sv_resume(void);
extern int sv_save(char *filename);
extern int sv_load(char *filename);
Modified: trunk/sushivision/toplevel.c
===================================================================
--- trunk/sushivision/toplevel.c 2007-10-18 07:39:37 UTC (rev 14010)
+++ trunk/sushivision/toplevel.c 2007-10-18 14:32:30 UTC (rev 14011)
@@ -64,9 +64,12 @@
// mutex condm is only for protecting the worker condvar
static pthread_mutex_t worker_condm = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t worker_cond = PTHREAD_COND_INITIALIZER;
-static sig_atomic_t sv_exiting=0;
+static pthread_cond_t idle_cond = PTHREAD_COND_INITIALIZER;
+static sig_atomic_t _sv_exiting=0;
+static sig_atomic_t _sv_running=0;
static int wake_pending = 0;
-static int num_threads;
+static int idling = 0;
+static int num_threads=0;
static int num_proccies(){
FILE *f = fopen("/proc/cpuinfo","r");
@@ -91,20 +94,26 @@
static void *worker_thread(void *dummy){
while(1){
int i,flag=0;
- if(sv_exiting)break;
-
- pthread_rwlock_rdlock(panellist_m);
- for(i=0;i<_sv_panels;i++){
- sv_panel_t *p = _sv_panel_list[i];
-
- if(sv_exiting)break;
+ if(_sv_exiting)break;
+ if(_sv_running){
+ pthread_rwlock_rdlock(panellist_m);
+ for(i=0;i<_sv_panels;i++){
+ sv_panel_t *p = _sv_panel_list[i];
+ int ret;
- if(p){
- int ret = _sv_panel_work(p);
- if(ret == STATUS_WORKING){
- flag = 1;
- sv_wake(); // result of this completion might have
- // generated more work
+ if(_sv_exiting)break;
+ if(!_sv_running)break;
+
+ if(p){
+ _sv_spinner_set_busy(p->spinner);
+ ret = _sv_panel_work(p);
+ if(ret == STATUS_WORKING){
+ flag = 1;
+ sv_wake(); // result of this completion might have
+ // generated more work
+ }
+ if(ret == STATUS_IDLE)
+ _sv_spinner_set_idle(p->spinner);
}
}
}
@@ -112,9 +121,12 @@
// nothing to do, wait
pthread_mutex_lock(&worker_condm);
+ idling++;
+ pthread_cond_signal(&idle_cond);
while(!wake_pending)
pthread_cond_wait(&worker_cond,&worker_condm);
-
+
+ idling--;
wake_pending--;
pthread_mutex_unlock(&worker_condm);
}
@@ -127,15 +139,6 @@
return _SUSHI_GTKRC_STRING;
}
-static void _sv_realize_all(void){
- int i;
- for(i=0;i<_sv_panels;i++)
- _sv_panel_realize(_sv_panel_list[i]);
- for(i=0;i<_sv_panels;i++)
- if(_sv_panel_list[i])
- _sv_panel_list[i]->private->request_compute(_sv_panel_list[i]);
-}
-
char *_sv_appname = NULL;
char *_sv_filename = NULL;
char *_sv_filebase = NULL;
@@ -205,8 +208,8 @@
pthread_create(&dummy, NULL, &worker_thread,NULL);
}
- // event thread for panels in the event the app we're injected into
- // has no gtk main loop
+ // eventloop for panels (in the event we're injected into an app
+ // with no gtk main loop; multiple such loops can coexist)
{
pthread_t dummy;
return pthread_create(&dummy, NULL, &event_thread,NULL);
@@ -216,7 +219,7 @@
}
int sv_join(void){
- while(!sv_exiting){
+ while(!_sv_exiting){
pthread_mutex_lock(&worker_condm);
pthread_cond_wait(&worker_cond,&worker_condm);
pthread_mutex_unlock(&worker_condm);
@@ -225,15 +228,18 @@
}
int sv_wake(void){
- pthread_mutex_lock(&worker_condm);
- wake_pending = num_threads;
- pthread_cond_broadcast(&worker_cond);
- pthread_mutex_unlock(&worker_condm);
+ if(_sv_running){
+ pthread_mutex_lock(&worker_condm);
+ wake_pending = num_threads;
+ pthread_cond_broadcast(&worker_cond);
+ pthread_mutex_unlock(&worker_condm);
+ }
return 0;
}
int sv_exit(void){
- sv_exiting = 1;
+ _sv_exiting = 1;
+ _sv_running = 1;
sv_wake();
gdk_threads_enter();
@@ -245,6 +251,24 @@
return 0;
}
+int sv_suspend(int block){
+ _sv_running=0;
+ if(block){
+ // block until all worker threads idle
+ while(idling < num_threads){
+ pthread_mutex_lock(&worker_condm);
+ pthread_cond_wait(&idle_cond,&worker_condm);
+ pthread_mutex_unlock(&worker_condm);
+ }
+ }
+ return 0;
+}
+
+int sv_resume(void){
+ _sv_running=1;
+ sv_wake();
+}
+
void _sv_first_load_warning(int *warn){
if(!*warn)
fprintf(stderr,"\nWARNING: The data file to be opened is not a perfect match to\n"
@@ -279,14 +303,24 @@
}
int sv_save(char *filename){
- xmlDocPtr doc = NULL;
- xmlNodePtr root_node = NULL;
int i, ret=0;
+ int fd;
LIBXML_TEST_VERSION;
- doc = xmlNewDoc((xmlChar *)"1.0");
- root_node = xmlNewNode(NULL, (xmlChar *)_sv_appname);
+ fd = open(_sv_filename, O_RDWR|O_CREAT, 0660);
+ if(fd<0){
+ ret = 1;
+ goto done;
+ }
+
+ gdk_threads_enter();
+
+ xmlSaveCtxtPtr xmlptr =
+ xmlSaveToFd (fd, "UTF-8", XML_SAVE_FORMAT);
+
+ xmlDocPtr doc = xmlNewDoc((xmlChar *)"1.0");
+ xmlNodePtr root_node = xmlNewNode(NULL, (xmlChar *)_sv_appname);
xmlDocSetRootElement(doc, root_node);
// dimension values are independent of panel
@@ -299,13 +333,21 @@
for(i=0;i<_sv_panels;i++)
ret|=_sv_panel_save(_sv_panel_list[i], root_node);
- ret|=xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1);
+ if(xmlSaveDoc(xmlptr,doc)<0)
+ ret=1;
+ if(xmlSaveClose(xmlptr)<0)
+ ret=1;
+
+ close(fd);
+
if(ret==0) set_internal_filename(filename);
-
+
xmlFreeDoc(doc);
xmlCleanupParser();
+ gdk_threads_leave();
+ done:
return ret;
}
@@ -318,38 +360,23 @@
LIBXML_TEST_VERSION;
fd = open(_sv_filename, O_RDONLY);
- if(fd<0){
- GtkWidget *dialog = gtk_message_dialog_new (NULL,0,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- "Error opening file '%s': %s",
- _sv_filename, strerror (errno));
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- return 1;
- }
+ if(fd<0) return 1;
doc = xmlReadFd(fd, NULL, NULL, 0);
close(fd);
if (doc == NULL) {
- GtkWidget *dialog = gtk_message_dialog_new (NULL,0,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- "Error parsing file '%s'",
- _sv_filename);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
errno = -EINVAL;
return 1;
}
-
+
root = xmlDocGetRootElement(doc);
-
+
// piggyback off undo (as it already goes through the trouble of
// doing correct unrolling, which can be tricky)
// if this instance has an undo stack, pop it all, then log current state into it
+ gdk_threads_enter();
_sv_undo_level=0;
_sv_undo_log();
@@ -370,7 +397,7 @@
}
}
}
-
+
// load panels
for(i=0;i<_sv_panels;i++){
sv_panel_t *p = _sv_panel_list[i];
@@ -403,15 +430,17 @@
node = node->next;
}
+ if(ret==0) set_internal_filename(filename);
+
// effect the loaded values
_sv_undo_suspend();
_sv_undo_restore();
_sv_undo_resume();
+ gdk_threads_leave();
xmlFreeDoc(doc);
xmlCleanupParser();
- if(ret==0) set_internal_filename(filename);
return 0;
}
More information about the commits
mailing list