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 + -
显示快捷键?