l1paint.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 575 行 · 第 1/2 页

C
575
字号
                do {
                    left_scan = right_scan;
                    right_scan = PaintRight( left_scan, y, stop_color, border_flag );
                    if( right_scan == left_scan ) { /* nothing was painted  */
                        right_scan += 1;                /* skip over hole   */
                    } else {                    /* something was painted    */
                        if( left_scan != cutoff ) {     /* Check for a hole */
                            if( left_edge <= cutoff ) {
                                success += AddEntry( y, cutoff, left_edge,
                                                     direction, max_frames,
                                                     &stack_count, stack );
                            }
                            left_edge = left_scan + 1;  /* adjust left edge */
                        }
                        cutoff = right_scan;        /* adjust stop pixel    */
                    }
                } while( right_scan < right_edge );
            }
            /* Check for a hole to the right    */
            if( right_scan >= right_edge + 2 ) {
                success += AddEntry( y, right_scan, right_edge + 2, -direction,
                                     max_frames, &stack_count, stack );
            }
            stack[0].direction = direction;         /* load new endpoints   */
            stack[0].left = left_edge;              /* after scan           */
            stack[0].right = cutoff;
            stack[0].ypos = y;
            if( left_edge > cutoff )        /* right most point on boundary */
                break;
        } while( StackCompare( stack, &stack_count ) );
        /* We are done with the previous frame so we have to load   */
        /* another one.     */
        do {
            if( stack_count == 0 ) {        /* no more frames to process    */
                _ResetDevice();
                return( !success );             /* flip flag - 0 was true   */
            }
            /* Make the last frame the active frame.    */
            memcpy( &stack[0], &stack[ stack_count ], sizeof( struct frame ) );
            stack_count -= 1;
        } while( !StackCompare( stack, &stack_count ) );
    }
#endif
}


#if !defined( _DEFAULT_WINDOWS )

static char CheckIfOut( short left_edge, short right_edge, short y )
/*==================================================================

    Returns true if TRUE if point is out of viewport or
    left_edge > right_edge. */

{
    if( left_edge > right_edge ) return( TRUE );
    if( _CurrState->clip.xmin > left_edge ) return( TRUE );
    if( left_edge > _CurrState->clip.xmax ) return( TRUE );
    if( _CurrState->clip.ymin > y ) return( TRUE );
    if( y > _CurrState->clip.ymax ) return( TRUE );
    return( FALSE );
}


static short PaintLeft( short x, short y, short stop_color, short border_flag )
/*=============================================================================

    Paint left of starting pixel (x,y) using current color and fill
    style. Return the new left pixel.   */

{
    short               xleft;
    /* pointer to scan function */
    short SCAN_FUNC     (near *scan)( char far *, int, int, int, int, int );
    gr_device _FARD     *dev_ptr;
    short               len;

#if defined( __MEDIUM__ ) || defined( __LARGE__ )
    if( _flood_is_visited( x, y ) ) {
        return( x );
    }
#endif
    dev_ptr = _CurrState->deviceptr;
    ( *dev_ptr->setup )( x, y, stop_color );
    scan = dev_ptr->scanleft;

    if( x >= _CurrState->clip.xmin ) {
        xleft = ( *scan )( _Screen.mem, _Screen.colour, x, _Screen.mask,
                       border_flag, _CurrState->clip.xmin );
    } else {
        xleft = x + 1;
    }
    len = x - xleft + 1;
    _L1Fill( xleft, y, len );
    _flood_visit( xleft, y, len );
    return( xleft );
}


static short PaintRight( short x, short y, short stop_color, short border_flag )
/*==============================================================================

    Paint right of starting pixel (x,y) using current color and fill
    style. Since we don't want to plot the initial pixel twice, move x
    by one to the right before plotting. Return the new left pixel. */

{
    short               xright;
    /* pointer to scan function */
    short SCAN_FUNC     (near *scan)( char far *, int, int, int, int, int );
    gr_device _FARD     *dev_ptr;
    short               len;

    x += 1;                                 /* don't plot first pixel twice */
#if defined( __MEDIUM__ ) || defined( __LARGE__ )
    if( _flood_is_visited( x, y ) ) {
        return( x - 1 );
    }
#endif
    dev_ptr = _CurrState->deviceptr;
    ( *dev_ptr->setup )( x, y, stop_color );
    scan = dev_ptr->scanright;

    if( x <= _CurrState->clip.xmax ){
        xright = ( *scan )( _Screen.mem, _Screen.colour, x, _Screen.mask,
                       border_flag, _CurrState->clip.xmax );
    } else {
        xright = x - 1;
    }
    len = xright - x + 1;
    _L1Fill( x, y, len );
    _flood_visit( x, y, len );
    return( xright );
}


static void swap( unsigned k, struct frame *stack )
/*=================================================

    Swap frame k with frame 0. Frame k is now the active frame. */

{
    short           length;
    struct frame    temp;

    length = sizeof( struct frame );
    memcpy( &temp, &stack[0], length );
    memcpy( &stack[0], &stack[k], length );
    memcpy( &stack[k], &temp, length );
}


static short AddEntry( short ypos, short right, short left, short direction,
/*==================*/ unsigned max_frames, unsigned *stack_count,
                       struct frame *stack )

/*  Add an entry to the stack. Quit if out of stack space.  */

{
    if( *stack_count == max_frames ) {          /* stack is full    */
        _ErrorStatus = _GRINSUFFICIENTMEMORY;
        return( TRUE );
    }
    *stack_count += 1;                          /* append to stack  */
    stack[ *stack_count ].left = left;
    stack[ *stack_count ].right = right;
    stack[ *stack_count ].ypos = ypos;
    stack[ *stack_count ].direction = direction;
    return( FALSE );
}


static char StackCompare( struct frame * stack, unsigned *stack_count )
/*=====================================================================

    Perform intersections, unions with entries already on the stack.
    Return with FALSE if entry completely cancelled or TRUE otherwise.  */

{
    short           startover;
    unsigned        count;
    unsigned        smallest;
    unsigned        curr;
    short           temp;

    if( *stack_count == 0 ) {                   /* nothing on the stack */
        stack[0].ypos += stack[0].direction;    /* go to next line in same  */
        return( TRUE );                         /* direction    */
    }
    do {
        /* Find shortest of the first TUNING non-active frames on the
           stack and the active frame.  */
        startover = FALSE;
        count = *stack_count;
        if( count > TUNING ) {
            count = TUNING;
        }
        smallest = 0;           /* assume smallest frame is the active one  */
        for( curr = 1; curr <= count; curr++ ) {
            if( stack[ curr ].right - stack[ curr ].left <
                stack[ smallest ].right - stack[ smallest ].left ) {
                smallest = curr;
            }
        }
        /* Interchange the smallest frame and the active frame. */
        if( smallest != 0 ) {
            swap( smallest, stack );
        }

        /* Check entries with opposite direction and same y */

        stack[0].ypos += stack[0].direction;        /* go to new line   */
        count = *stack_count;
        for( curr = 1; curr <= count; curr++ ) {
            if( stack[0].ypos == stack[ curr ].ypos &&
                stack[0].direction != stack[ curr ].direction ) {
                if( stack[0].left - 1 <= stack[ curr ].right    /* overlap? */
                    && stack[0].right + 1 >= stack[ curr ].left ) {
                    if( stack[0].right + 1 >= stack[ curr ].right ) {
                        temp = stack[0].left;
                        stack[0].left = stack[ curr ].right + 2;
                        if( temp + 1 < stack[ curr ].left ) {
                            stack[ curr ].right = stack[ curr ].left - 2;
                            stack[ curr ].left = temp - 1;
                            stack[ curr ].direction = stack[0].direction;
                            stack[ curr ].ypos -= stack[0].direction;
                        } else {
                            stack[ curr ].right = temp - 2;
                        }
                    } else {
                        temp = stack[ curr ].left;
                        stack[ curr ].left = stack[0].right + 2;
                        if( temp + 1 < stack[0].left ) {
                            stack[0].right = stack[0].left - 2;
                            stack[0].left = temp;
                            stack[0].direction = stack[ curr ].direction;
                            startover = TRUE;
                            break;
                        }
                        stack[0].right = temp - 2;
                    }
                    if( stack[0].left > stack[0].right ) {
                        return( NotValidFrame( curr, stack_count, stack ) );
                    }
                }
            }
        }
    } while ( startover );

    /* Check entries with same direction and same y */
    count = *stack_count;
    for( curr = 1; curr <= count; curr++ ) {
        if( stack[0].ypos == stack[ curr ].ypos &&
            stack[0].direction == stack[ curr ].direction ) {
            if( stack[0].left - 1 <= stack[ curr ].right &&     /* overlap? */
                stack[0].right + 1 >= stack[ curr ].left ) {
                if( stack[0].right - 1 <= stack[ curr ].right ) {
                    stack[0].right = stack[ curr ].left - 2;
                }
                if( stack[0].left + 1 >= stack[ curr ].left ) {
                    stack[0].left = stack[ curr ].right + 2;
                }
                if( stack[0].left > stack[0].right ) {
                    return( NotValidFrame( curr, stack_count, stack ) );
                }
            }
        }
    }
    return( TRUE );
}


static char NotValidFrame( unsigned curr, unsigned *stack_count,
/*======================*/ struct frame *stack )

/*  If the current frame is no longer valid then replace it by the last one.*/

{
    if( stack[ curr ].left > stack[ curr ].right ) {
        memcpy( &stack[ curr ], &stack[ *stack_count ], sizeof( struct frame ) );
        *stack_count -= 1;
    }
    return( FALSE );                /* signal no direction  */
}

#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?