l1ellips.c

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

C
1,123
字号
/****************************************************************************
*
*                            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:  High level ellipse drawing routines.
*
****************************************************************************/


#include "gdefn.h"
#include "ellinfo.h"
#include "rotate.h"
#if !defined( _DEFAULT_WINDOWS )
  #include "dotfunc.h"
#endif


#define _is_odd( q )    ( ( q & 1 ) != 0 )
#define _is_even( q )   ( ( q & 1 ) == 0 )


#if defined( _DEFAULT_WINDOWS )

extern float            sqrtf( float );
#pragma aux             sqrtf "*_";


static struct xycoord   Cal_Coord( float, float, float, float );

#else

static struct line_entry    VectA;
static struct line_entry    VectB;
static struct ellipse_info  EllInfo;


static void             FastPlot( short x, short y, short q );
static void             SlowPlot( short x, short y, short q );
static void             ArcPlot( short x, short y, short q );
static void             EllFill( short x, short y, short q );
static void             ArcFill( short x, short y, short q );
static void             InitLineMasks( short x1, short y1, short x2, short y2 );
static void             HollowArc( short x1, short y1, short x2, short y2, short a, short b );
static void             FilledArc( short x1, short y1, short x2, short y2, short a, short b );
#endif


void _L1Ellipse( short fill, short x1, short y1, short x2, short y2 )
//===================================================================

{
    short               clip1;
    short               clip2;
#if defined( _DEFAULT_WINDOWS )
    WPI_PRES            dc;
    HBITMAP             bm;
    HBRUSH              brush;
    HBRUSH              old_brush;
    HPEN                pen;
    HPEN                old_pen;
    HRGN                temprgn;
    WPI_COLOUR          color;
    WPI_RECT            clip_rect;
    short               t;
    short               clipy1, clipy2;
#endif

    clip1 = _L1OutCode( x1, y1 );       // check for clipping
    clip2 = _L1OutCode( x2, y2 );
    if( clip1 & clip2 ) {
        _ErrorStatus = _GRNOOUTPUT;
        return;                         // trivially outside so quit
    }
#if defined( _DEFAULT_WINDOWS )
    dc = _Mem_dc;

// Do the clippings
    temprgn = _ClipRgn;
    clipy1 = _wpi_cvth_y( _CurrState->clip_def.ymin, _GetPresHeight() );
    clipy2 = _wpi_cvth_y( _CurrState->clip_def.ymax + 1, _GetPresHeight() );

    _wpi_setintwrectvalues( &clip_rect,
                           _CurrState->clip_def.xmin,
                           clipy1,
                           _CurrState->clip_def.xmax + 1,
                           clipy2 );
    _ClipRgn = _wpi_createrectrgn( dc, &clip_rect );
    _wpi_getclipbox( dc, &clip_rect);
    _wpi_selectcliprgn( dc, _ClipRgn );
    _wpi_deletecliprgn( dc, temprgn );

// Set up before drawing
    color = _Col2RGB( _CurrColor );

    if( fill == _GFILLINTERIOR ) {
        // there is not border for filled objects, so set the pen to null
        pen = _wpi_createpen( PS_NULL, 0, color );

        // Check if there is a fill mask
        if( _HaveMask == 0 ) {
            brush = _wpi_createsolidbrush( color );
        } else {
            // if a mask is defined, convert it to bitmap
            bm = _Mask2Bitmap( dc, &_FillMask );
            brush = _wpi_createpatternbrush( bm );
        }

    } else {
        // Just draw the frame
        pen = _MyCreatePen( color );

        // make sure the background can still be seen
        brush = _wpi_createnullbrush();
    }

    old_pen = _wpi_selectpen( dc, pen );
    old_brush = _wpi_selectbrush( dc, brush );
    if( y1 > y2 ){
        t = y1;
        y1 = y2;
        y2 = t;
    }
    y1 = _wpi_cvth_y( y1, _GetPresHeight() );
    y2 = _wpi_cvth_y( y2, _GetPresHeight() );
#if defined( __OS2__ )
    _wpi_ellipse( dc, x1, y1-1, x2, y2 );
#else
    _wpi_ellipse( dc, x1, y1, x2, y2 );
#endif

// Clean up afterwards
    _wpi_getoldbrush( dc, old_brush );
    if( fill == _GFILLINTERIOR ){
        _wpi_deletebrush( brush );
    } else {
        _wpi_deletenullbrush( brush );
    }

    if( _HaveMask != 0 ) {
        _wpi_deletebitmap( bm );
    }

    _wpi_getoldpen( dc, old_pen );
    _wpi_deletepen( pen );


    temprgn = _ClipRgn;
    _ClipRgn = _wpi_createrectrgn( dc, &clip_rect );
    _wpi_selectcliprgn( dc, _ClipRgn );
    _wpi_deletecliprgn( dc, temprgn );

// Make sure we update the window
    _MyInvalidate( x1, y1, x2, y2 );
    _RefreshWindow();
#else
    _StartDevice();
    EllInfo.x_reflect = x1 + x2;        // need to reflect to use symmetry
    EllInfo.y_reflect = y1 + y2;
    if( fill == _GFILLINTERIOR ) {
        EllInfo.prev_y = -1;            // no previous line
        _L0Ellipse( x1, y1, x2, y2, EllFill );
    } else {
        if( clip1 == clip2 && _LineStyle == 0xffff ) {
            // no clipping and solid line
            _L0Ellipse( x1, y1, x2, y2, FastPlot );
        } else {
            InitLineMasks( x1, y1, x2, y2 );
            _L0Ellipse( x1, y1, x2, y2, SlowPlot );
        }
    }
    _ResetDevice();
#endif
}


#if !defined( _DEFAULT_WINDOWS )

static void FastPlot( short x, short y, short q )
//===============================================

// plot the ellipse point (x,y)

{
    void                (*setup )( short, short, short );
    put_dot_fn near     *putdot;
    gr_device _FARD     *dev_ptr;

    dev_ptr = _CurrState->deviceptr;
    setup = dev_ptr->setup;
    putdot = dev_ptr->plot[ _PlotAct ];
    if( q == 4 ) {  // all quadrants
        ( *setup )( x,                     y,                     _CurrColor );
        ( *putdot )( _Screen.mem, _Screen.colour, _Screen.mask );
        ( *setup )( EllInfo.x_reflect - x, y,                     _CurrColor );
        ( *putdot )( _Screen.mem, _Screen.colour, _Screen.mask );
        ( *setup )( EllInfo.x_reflect - x, EllInfo.y_reflect - y, _CurrColor );
        ( *putdot )( _Screen.mem, _Screen.colour, _Screen.mask );
        ( *setup )( x,                     EllInfo.y_reflect - y, _CurrColor );
        ( *putdot )( _Screen.mem, _Screen.colour, _Screen.mask );
    } else {
        if( q == 1 || q == 2 ) {
            x = EllInfo.x_reflect - x;
        }
        if( q == 2 || q == 3 ) {
            y = EllInfo.y_reflect - y;
        }
        ( *setup )( x, y, _CurrColor );
        ( *putdot )( _Screen.mem, _Screen.colour, _Screen.mask );
    }
}


static void PutDot( int x, int y, int q )
//=======================================

{
    void                (*setup )( short, short, short );
    put_dot_fn near     *putdot;
    gr_device _FARD     *dev_ptr;

    if( _L1OutCode( x, y ) == 0 ) {     // inside viewport
        if( EllInfo.line_mask[ q ] & 1 ) {  // check for line style
            dev_ptr = _CurrState->deviceptr;
            setup = dev_ptr->setup;
            putdot = dev_ptr->plot[ _PlotAct ];
            ( *setup )( x, y, _CurrColor );
            ( *putdot )( _Screen.mem, _Screen.colour, _Screen.mask );
        }
    }
}


static void SlowPlot( short x, short y, short q )
//===============================================

// plot the ellipse point (x,y) taking into account the line style
// and the clipping region

{
    short               inc;
    short               x1;
    short               y1;

    if( q == 4 ) {  // do all the quadrants
        q = 0;      // start with 0
        inc = 1;
    } else {
        inc = 4;
    }
    for( ; q <= 3; q += inc ) {
        if( q == 1 || q == 2 ) {
            x1 = EllInfo.x_reflect - x;
        } else {
            x1 = x;
        }
        if( q == 2 || q == 3 ) {
            y1 = EllInfo.y_reflect - y;
        } else {
            y1 = y;
        }
        if( q == 0 || q == 2 ) {
            EllInfo.line_mask[ q ] = _wrol( EllInfo.line_mask[ q ], 1 );
        } else {
            EllInfo.line_mask[ q ] = _wror( EllInfo.line_mask[ q ], 1 );
        }
        PutDot( x1, y1, q );
    }
}


#define NumPts  EllInfo.prev_y
#define XAxis   EllInfo.x_reflect
#define YAxis   EllInfo.y_reflect


static void CountPlot( short x, short y, short q )
//================================================

{
    x = x;
    y = y;
    if( q == 4 ) {      // count points drawn in each quadrant
        ++NumPts;
    } else if( q == 0 ) {
        XAxis = 1;
    } else if( q == 1 ) {
        YAxis = 1;
    }
}


static void DummyPlot( int x, int y, int q )
//==========================================

{
    x = x;
    y = y;
    q = q;
}


static void InitLineMasks( short x1, short y1, short x2, short y2 )
//=================================================================

// To adjust the line style mask properly, we need to know how
// many points will be drawn by the ellipse drawing algorithm.
// To determine this, call the algorithm with a dummy routine that
// counts the points.

{
    short               amount;

    NumPts = 0;
    _L0Ellipse( x1, y1, x2, y2, CountPlot );    // count the points
    amount = 2*NumPts + XAxis + YAxis;
    EllInfo.line_mask[ 0 ] = _LineStyle;
    EllInfo.line_mask[ 1 ] = _wrol( _LineStyle, ( amount + 1 ) & 0x0f );
    EllInfo.line_mask[ 2 ] = _wrol( _LineStyle, ( amount ) & 0x0f );
    EllInfo.line_mask[ 3 ] = _wrol( _LineStyle, ( 2 * amount + 1 ) & 0x0f );
    EllInfo.x_reflect = x1 + x2;    // need to be reset
    EllInfo.y_reflect = y1 + y2;
}


static void EllFill( short x, short y, short q )
//==============================================

// given the ellipse point (x,y), fill the ellipse

{
    short               xl;
    short               y2;

    if( q == 0 || q == 4 ) {    // only plot if quadrant 0 or all
        if( EllInfo.prev_y != y ) {     // and only if y has changed
            xl = EllInfo.x_reflect - x;  // reflected point is x1 + ( x2 - x )
            _L1ClipFill( xl, x, y );
            y2 = EllInfo.y_reflect - y;
            if( y2 != y ) {
                _L1ClipFill( xl, x, y2 );
            }
            EllInfo.prev_y = y;
        }
    }
}


static short Quadrant( short x, short y, short x_width, short y_width )
//=====================================================================

// return the quadrant (0..3) containing the point (x,y)
// Note: x and y cannot both be 0
// A point on the x-axis will be in either quadrant 0 or 3 depending

⌨️ 快捷键说明

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