tomwalters@0: /* tomwalters@0: Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989 tomwalters@0: =========================================================================== tomwalters@0: tomwalters@0: Permission to use, copy, modify, and distribute this software without fee tomwalters@0: is hereby granted for research purposes, provided that this copyright tomwalters@0: notice appears in all copies and in all supporting documentation, and that tomwalters@0: the software is not redistributed for any fee (except for a nominal shipping tomwalters@0: charge). Anyone wanting to incorporate all or part of this software in a tomwalters@0: commercial product must obtain a license from the Medical Research Council. tomwalters@0: tomwalters@0: The MRC makes no representations about the suitability of this tomwalters@0: software for any purpose. It is provided "as is" without express or implied tomwalters@0: warranty. tomwalters@0: tomwalters@0: THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING tomwalters@0: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE tomwalters@0: A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY tomwalters@0: DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN tomwalters@0: AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF tomwalters@0: OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. tomwalters@0: */ tomwalters@0: tomwalters@0: /* tomwalters@0: draw.c tomwalters@0: ====== tomwalters@0: tomwalters@0: basic interface between file format and windows content tomwalters@0: tomwalters@0: */ tomwalters@0: tomwalters@0: /* Added the field nwid in the '_draw_state' object. AJD 17-3-95 */ tomwalters@0: tomwalters@0: #include tomwalters@0: tomwalters@0: #include "windows.h" tomwalters@0: #include "stitch.h" tomwalters@0: #include "source.h" tomwalters@0: #include "draw.h" tomwalters@0: #include "ops.h" tomwalters@0: tomwalters@0: #ifndef lint tomwalters@0: static char *draw_sccs_id = "@(#)draw.c 1.15 John Holdsworth (MRC-APU) 6/6/91" ; tomwalters@0: #endif tomwalters@0: tomwalters@0: /* maximum buffer size for segmentation of drawing */ tomwalters@0: tomwalters@0: #if defined( PC ) || defined( THINK_C ) tomwalters@0: #define MAX_BUFFER (1l<<14) tomwalters@0: #else tomwalters@0: #define MAX_BUFFER (1l<<16) tomwalters@0: #endif tomwalters@0: tomwalters@0: /* globale variable for display paramters */ tomwalters@0: tomwalters@0: double drawHeadroom = 0.0 ; tomwalters@0: double drawTilt = 0.0 ; tomwalters@0: double drawDepth = 0.0 ; tomwalters@0: double drawDistance = 0.5 ; tomwalters@0: double drawOverlap = 0.0 ; tomwalters@0: tomwalters@0: /* tomwalters@0: tomwalters@0: this mess is worth a comment tomwalters@0: tomwalters@0: I'd like to apologise for the moras of scaling parameters for display tomwalters@0: .. the price of backward compatability. tomwalters@0: tomwalters@0: Originally you could tillt the diaply to give the sensation of depth, tomwalters@0: then the display parameters where changed to min, max and overlap. tomwalters@0: The result is the combination of the two. At least the new interface tomwalters@0: is a bit cleaner from the outside. tomwalters@0: tomwalters@0: There is also the complication of segmented drawing across and down tomwalters@0: the screen. All in all this needs to be rewritten! tomwalters@0: tomwalters@0: From the outside though it's interface is reasonably clean however. tomwalters@0: tomwalters@0: if framewidth > 1 then it's a 2d image per frame. If not then its tomwalters@0: a multiplexed file. tomwalters@0: tomwalters@0: */ tomwalters@0: tomwalters@0: tomwalters@0: void draw_frame( state, frame ) tomwalters@0: struct _draw_state *state ; tomwalters@0: short *frame ; tomwalters@0: { tomwalters@0: double sintheta = sin( drawTilt / 45. * atan( 1. ) ) ; tomwalters@0: double scale = ( 100. - drawHeadroom ) / 100. / ( drawDistance / ( drawDistance + sintheta ) ) ; tomwalters@0: double height = Height( state->window ) * ( 1. - drawHeadroom / 100. ) ; tomwalters@0: double overscale, rowscale, origin ; tomwalters@0: int row ; tomwalters@0: tomwalters@0: for( row=state->frameheight-1 ; row >= 0 ; row-- ) { tomwalters@0: tomwalters@0: rowscale = drawDistance / ( drawDistance + sintheta * ( row + 0.5 ) / state->frameheight ) ; tomwalters@0: overscale = 1. / ( ( state->frameheight - 1. ) * ( 1. - drawOverlap ) + 1. ) ; tomwalters@0: origin = row * height * overscale * ( 1. - drawOverlap ) + tomwalters@0: ( 0. - state->min ) / ( state->max - state->min ) * Height( state->window ) * overscale ; tomwalters@0: tomwalters@0: if( state->framewidth > 1 ) tomwalters@0: Function( state->window, frame+row*state->framewidth, state->framewidth, 1, origin * rowscale * scale, ( state->max - state->min ) / overscale / rowscale ) ; tomwalters@0: else tomwalters@0: if( state->colnumber == 0 ) tomwalters@0: Segment( state->window, frame+row, state->colsegment, state->frameheight, origin * rowscale * scale, ( state->max - state->min ) / overscale / rowscale, state->colnumber, (int) state->frames ) ; tomwalters@0: else tomwalters@0: Segment( state->window, frame+row-state->frameheight, state->colsegment+1, state->frameheight, origin * rowscale * scale, ( state->max - state->min ) / overscale / rowscale, state->colnumber-1, (int) state->frames ) ; tomwalters@0: } tomwalters@0: tomwalters@0: return ; tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: static void draw_callback( state, bytes, buffer ) tomwalters@0: struct _draw_state *state ; tomwalters@0: ByteCount *bytes ; tomwalters@0: short *buffer ; tomwalters@0: { tomwalters@0: int first = state->colnumber == 0 ; tomwalters@0: tomwalters@0: if( state->framewidth > 1 ) { tomwalters@0: state->rowsegment = *bytes / sizeof ( short ) / state->framewidth ; tomwalters@0: if( state->rowsegment > state->frameheight - state->rownumber ) tomwalters@0: state->rowsegment = state->frameheight - state->rownumber ; tomwalters@0: } tomwalters@0: else { tomwalters@0: state->colsegment = *bytes / sizeof ( short ) / state->frameheight ; tomwalters@0: if( state->colsegment > state->frames - state->colnumber ) tomwalters@0: state->colsegment = state->frames - state->colnumber ; tomwalters@0: } tomwalters@0: tomwalters@0: if( first ) tomwalters@0: ++state->framenumber ; tomwalters@0: tomwalters@0: if( *bytes != 0 ) tomwalters@0: state->interceptor( state, buffer, first ) ; tomwalters@0: tomwalters@0: if( state->framewidth > 1 ) tomwalters@0: state->rownumber = ( state->rownumber + state->rowsegment ) % state->frameheight ; tomwalters@0: else tomwalters@0: state->colnumber = ( state->colnumber + state->colsegment ) % state->frames ; tomwalters@0: tomwalters@0: } tomwalters@0: tomwalters@0: Source SourceDraw( source, min, max, window, framewidth, frameheight, nwid, frames, interceptor, drawer ) tomwalters@0: Source source ; tomwalters@0: int min, max ; tomwalters@0: WindowObject window ; tomwalters@0: int framewidth, frameheight ; tomwalters@0: int nwid; tomwalters@0: long frames ; tomwalters@0: void (*interceptor)() ; tomwalters@0: void (*drawer)() ; tomwalters@0: { tomwalters@0: DeclareNew( struct _draw_state *, state ) ; tomwalters@0: int segsize ; tomwalters@0: tomwalters@0: state->min = min ; tomwalters@0: state->max = max ; tomwalters@0: tomwalters@0: state->source = source ; tomwalters@0: state->window = window ; tomwalters@0: tomwalters@0: state->frameheight = frameheight ; tomwalters@0: state->framewidth = framewidth ; tomwalters@0: state->nwid = nwid ; tomwalters@0: state->frames = frames ; tomwalters@0: tomwalters@0: state->framenumber = 0 ; tomwalters@0: tomwalters@0: state->colnumber = 0 ; tomwalters@0: state->rownumber = 0 ; tomwalters@0: tomwalters@0: state->colsegment = framewidth ; tomwalters@0: state->rowsegment = frameheight ; tomwalters@0: tomwalters@0: state->interceptor = interceptor ; tomwalters@0: state->drawer = drawer ; tomwalters@0: tomwalters@0: source = NewTappingSource( state, draw_callback, stitch_free, source, "draw.c drawing" ) ; tomwalters@0: tomwalters@0: if( state->framewidth == 1 ) { tomwalters@0: tomwalters@0: segsize = MAX_BUFFER / frameheight / sizeof ( short ) - 1 ; tomwalters@0: tomwalters@0: if( segsize > frames ) tomwalters@0: segsize = frames ; tomwalters@0: else tomwalters@0: source = NewRetainingSource( source, frameheight * sizeof ( short ) ) ; tomwalters@0: tomwalters@0: source = NewBlockingSource( source, frameheight * sizeof ( short ) * segsize ) ; tomwalters@0: } tomwalters@0: tomwalters@0: return ( source ) ; tomwalters@0: } tomwalters@0: tomwalters@0: static Source DrawEither( window, source, min, max, framepoints, nwid, frames, drawer, row_flag ) tomwalters@0: WindowObject window ; tomwalters@0: Source source ; tomwalters@0: int min, max ; tomwalters@0: int framepoints, frames, nwid ; tomwalters@0: int row_flag ; tomwalters@0: void (*drawer)() ; tomwalters@0: { tomwalters@0: void (*draw_routine)() = drawer ; tomwalters@0: tomwalters@0: if( draw_routine == (void ( * )()) 0 ) tomwalters@0: draw_routine = draw_frame ; tomwalters@0: tomwalters@0: return ( SourceDraw( source, min, max, window, 1, framepoints, nwid, (long) frames, draw_routine, draw_routine ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: Source drawAcross( window, source, min, max, framepoints, nwid, frames, drawer ) tomwalters@0: WindowObject window ; tomwalters@0: Source source ; tomwalters@0: int min, max ; tomwalters@0: int framepoints, frames ; tomwalters@0: void (*drawer)() ; tomwalters@0: { tomwalters@0: return ( DrawEither( window, source, min, max, framepoints, nwid, frames, drawer, 0 ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: Source drawDown( window, source, min, max, framepoints, nwid, frames, drawer ) tomwalters@0: WindowObject window ; tomwalters@0: Source source ; tomwalters@0: int min, max ; tomwalters@0: int framepoints, frames ; tomwalters@0: void (*drawer)() ; tomwalters@0: { tomwalters@0: return ( DrawEither( window, source, min, max, framepoints, nwid, frames, drawer, 1 ) ) ; tomwalters@0: } tomwalters@0: