l1fillar.c

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

C
542
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "gdefn.h"
#if !defined( _DEFAULT_WINDOWS )
#include <malloc.h>
#include "stkavail.h"


struct seg_entry {
    struct line_entry   line;
    short               end_pt;
    struct seg_entry    *link;
    short               delete;
};


static short            NumMinima;
static short            *MinList;
static struct seg_entry *LineList;
static struct seg_entry *FreeList;
static int              StackSize;
static char *           Stack;


static short NextPoint( short i, short dir, short n,
                        struct xycoord _WCI86FAR *points )
//===================================================

//  Find the next point after i, which has a different y value.

{
    short               p;
    short               y;

    y = points[ i ].ycoord;
    for( p = i + dir;; p += dir  ) {
        if( p == n ) {  // p %= n
            p = 0;
        } else if ( p < 0 ) {
            p = n - 1;
        }
        if( p == i ) {      // back to the start
            break;
        }
        if( points[ p ].ycoord != y ) {
            break;
        }
    }
    return( p );
}


static void CalcMinima( short n, struct xycoord _WCI86FAR *points )
//============================================================

//  Detect and store away all of the minimas. Sort the minima's
//  by y value.

{
    short               curr_y;
    short               i;
    short               j;
    short               start;
    short               next;
    short               prev;
    short               min;

    NumMinima = 0;
    start = NextPoint( 0, 1, n, points );
    i = start;
    do {
        next = NextPoint( i, 1, n, points );
        prev = NextPoint( i, -1, n, points );
        curr_y = points[ i ].ycoord;
        if( points[ prev ].ycoord > curr_y && points[ next ].ycoord > curr_y ) {
            // found a minima, add to min list, sort by y value
            if( ( NumMinima + 1 ) * sizeof( short ) > StackSize ) {
                _ErrorStatus = _GRINSUFFICIENTMEMORY;   // need room for 1 more
                NumMinima = 0;  // signal error
                return;
            }
            for( min = 0; min < NumMinima; ++min ) {
                if( curr_y < points[ MinList[ min ] ].ycoord ) {
                    // shift rest of list up
                    for( j = NumMinima; j > min; --j ) {
                        MinList[ j ] = MinList[ j - 1 ];
                    }
                    break;
                }
            }
            MinList[ min ] = i;
            ++NumMinima;
        }
        i = next;
    } while( next != start );
    if( NumMinima == 0 ) {
        _ErrorStatus = _GRINVALIDPARAMETER;     // no minima found
    }
}


static void OrderLines( void )
//======================

//  Order the line segments by x value.

{
    struct seg_entry    *curr;
    struct seg_entry    *next;
    struct seg_entry    *prev;
    char                swap;
    struct seg_entry    temp;   // dummy entry for start of list

    temp.link = LineList;   // place start of list in dummy so that
    do {                    // we can do swaps more easily
        swap = 0;
        prev = &temp;
        for( ;; ) {
            curr = prev->link;
            if( curr == NULL ) {
                break;
            }
            next = curr->link;
            if( next == NULL ) {
                break;
            }
            if( curr->line.curr_x > next->line.curr_x ) {
                prev->link = next;
                curr->link = next->link;
                next->link = curr;
                swap = 1;
            }
            prev = curr;
        }
    } while( swap );
    LineList = temp.link;       // reload start of list
}


static short AddLine( short p1, short p2, struct xycoord _WCI86FAR *points )
//=====================================================================

{
    struct seg_entry    *segment;

    segment = FreeList;         // get element from free list
    if( segment == NULL ) {
        _ErrorStatus = _GRINSUFFICIENTMEMORY;
        return( FALSE );
    }
    FreeList = FreeList->link;
    _LineInit( points[ p1 ].xcoord, points[ p1 ].ycoord,
               points[ p2 ].xcoord, points[ p2 ].ycoord, &segment->line );
    segment->end_pt = p2;
    segment->delete = FALSE;
    segment->link = LineList;
    LineList = segment;
    return( TRUE );
}


static short AddMinima( short y, short n, struct xycoord _WCI86FAR *points )
//=====================================================================

{
    short               p;
    short               prev;
    short               next;
    short               p2;

    p = MinList[ 0 ];
    for( ;; ) {
        prev = NextPoint( p, -1, n, points );
        p2 = prev + 1;
        if( p2 == n ) {
            p2 = 0;
        }
        if( !AddLine( p2, prev, points ) ) {
            return( FALSE );
        }
        next = NextPoint( p, 1, n, points );
        p2 = next - 1;
        if( p2 < 0 ) {
            p2 = n - 1;
        }
        if( !AddLine( p2, next, points ) ) {
            return( FALSE );
        }
        --NumMinima;
        if( NumMinima == 0 ) {
            break;
        }
        ++MinList;              // advance list
        p = MinList[ 0 ];
        if( points[ p ].ycoord != y ) {     // check for more on this line
            break;
        }
    }
    OrderLines();
    return( TRUE );
}


static void ExtendLines( short y, short n, struct xycoord _WCI86FAR *points )
//======================================================================

//  Replace line segments ending at the current y value with their
//  upward extension.

{
    struct seg_entry    *line;
    short               p;
    short               p1;
    short               p2;
    short               end_x;
    short               old_left;
    short               old_right;

    for( line = LineList; line != NULL; line = line->link ) {
        p = line->end_pt;
        if( points[ p ].ycoord == y ) {
            // current line ends at this point, so make sure the
            // line doesn't extend past the ending x value
            end_x = points[ p ].xcoord;
            if( line->line.sdx > 0 ) {
                line->line.right_x = end_x;
            } else {
                line->line.left_x = end_x;
            }
            p2 = NextPoint( p, -1, n, points );
            if( points[ p2 ].ycoord > y ) {
                p1 = p2 + 1;
                if( p1 == n ) {
                    p1 = 0;
                }
            } else {
                p2 = NextPoint( p, 1, n, points );
                if( points[ p2 ].ycoord > y ) {
                    p1 = p2 - 1;
                    if( p1 < 0 ) {
                        p1 = n - 1;

⌨️ 快捷键说明

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