⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 genfunc_clipline.c

📁 在ADS环境下MiniGUI的源码
💻 C
字号:
/*
** $Id: genfunc_clipline.c,v 1.4 2003/09/04 02:57:09 weiym Exp $
** 
** genfunc_clipline.c: 
**
** Copyright (C) 2003 Feynman Software.
** Copyright (C) 2000 Song Lixin
** Copyright (C) 1998 Alexander Larsson   [alla@lysator.liu.se]
*/

/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/*
** This is a line-clipper using the algorithm by cohen-sutherland.
**
** It is modified to do pixel-perfect clipping. This means that it
** will generate the same endpoints that would be drawn if an ordinary
** bresenham line-drawer where used and only visible pixels drawn.
**
** It can be used with a bresenham-like linedrawer if it is modified to
** start with a correct error-term.
*/

#include <stdio.h>
#include <stdlib.h>

#include "common.h"
#include "minigui.h"
#include "gal.h"
#include "native.h"

#define OC_LEFT 1
#define OC_RIGHT 2
#define OC_TOP 4
#define OC_BOTTOM 8

/* Outcodes:
+-> x
|       |      | 
V  0101 | 0100 | 0110
y ---------------------
   0001 | 0000 | 0010
  ---------------------
   1001 | 1000 | 1010
        |      | 
 */
#define outcode(code, xx, yy) \
{\
  code = 0;\
 if (xx < tempclipminx)\
    code |= OC_LEFT;\
  else if (xx > tempclipmaxx)\
    code |= OC_RIGHT;\
  if (yy < tempclipminy)\
    code |= OC_TOP;\
  else if (yy>tempclipmaxy)\
    code |= OC_BOTTOM;\
}

/*
  Calculates |_ a/b _| with mathematically correct floor
  */
static int FloorDiv(int a, int b)
{
	int floor;
	if (b>0) {
		if (a>0) {
			return a /b;
		} else {
			floor = -((-a)/b);
			if ((-a)%b != 0)
				floor--;
		}
		return floor;
	} else {
		if (a>0) {
			floor = -(a/(-b));
			if (a%(-b) != 0)
				floor--;
			return floor;
		} else {
			return (-a)/(-b);
		}
	}
}
/*
  Calculates |^ a/b ^| with mathamatically correct floor
  */
static int CeilDiv(int a,int b)
{
	if (b>0)
		return FloorDiv(a-1,b)+1;
	else
		return FloorDiv(-a-1,-b)+1;
}

int cs_clipline(PSD psd,int *_x0, int *_y0, int *_x1, int *_y1,
		       int *clip_first, int *clip_last)
{
	int first,last, code;
	int x0,y0,x1,y1;
	int x,y;
	int dx,dy;
	int xmajor;
	int slope;
	
	int tempclipminx,tempclipminy,tempclipmaxx,tempclipmaxy;
	if (psd->doclip) {
		tempclipminx = psd->clipminx;
		tempclipminy = psd->clipminy;
		tempclipmaxx = psd->clipmaxx;
		tempclipmaxy = psd->clipmaxy;
	} else {
		tempclipminx = 0;
		tempclipminy = 0;
		tempclipmaxx = psd->xres - 1;
		tempclipmaxy = psd->yres - 1;
	}	

	first = 0;
	last = 0;
	outcode(first,*_x0,*_y0);
	outcode(last,*_x1,*_y1);

	if ((first | last) == 0) {
		return CLIP_VISIBLE; /* Trivially accepted! */
	}
	if ((first & last) != 0) {
		return CLIP_INVISIBLE; /* Trivially rejected! */
	}

	x0=*_x0; y0=*_y0;
	x1=*_x1; y1=*_y1;

	dx = x1 - x0;
	dy = y1 - y0;
  
	xmajor = (abs(dx) > abs(dy));
	slope = ((dx>=0) && (dy>=0)) || ((dx<0) && (dy<0));
  
	for (;;) {
		code = first;
		if (first==0)
			code = last;

		if (code&OC_LEFT) {
			x = tempclipminx;
			if (xmajor) {
				y = *_y0 +  FloorDiv(dy*(x - *_x0)*2 + dx,
						      2*dx);
			} else {
				if (slope) {
					y = *_y0 + CeilDiv(dy*((x - *_x0)*2
							       - 1), 2*dx);
				} else {
					y = *_y0 + FloorDiv(dy*((x - *_x0)*2
								- 1), 2*dx);
				}
			}
		} else if (code&OC_RIGHT) {
			x = tempclipmaxx;
			if (xmajor) {
				y = *_y0 +  FloorDiv(dy*(x - *_x0)*2 + dx, 2*dx);
			} else {
				if (slope) {
					y = *_y0 + CeilDiv(dy*((x - *_x0)*2
							       + 1), 2*dx)-1;
				} else {
					y = *_y0 + FloorDiv(dy*((x - *_x0)*2
								+ 1), 2*dx)+1;
				}
			}
		} else if (code&OC_TOP) {
			y = tempclipminy;
			if (xmajor) {
				if (slope) {
					x = *_x0 + CeilDiv(dx*((y - *_y0)*2
							       - 1), 2*dy);
				} else {
					x = *_x0 + FloorDiv(dx*((y - *_y0)*2
								- 1), 2*dy);
				}
			} else {
				x = *_x0 +  FloorDiv( dx*(y - *_y0)*2 + dy,
						      2*dy);
			}
		} else { /* OC_BOTTOM */
			y = tempclipmaxy;
			if (xmajor) {
				if (slope) {
					x = *_x0 + CeilDiv(dx*((y - *_y0)*2
							       + 1), 2*dy)-1;
				} else {
					x = *_x0 + FloorDiv(dx*((y - *_y0)*2
								+ 1), 2*dy)+1;
				}
			} else {
				x = *_x0 +  FloorDiv(dx*(y - *_y0)*2 + dy,
						     2*dy);
			}
		}

		if (first!=0) {
			x0 = x;
			y0 = y;
			outcode(first,x0,y0);
			*clip_first = 1;
		} else {
			x1 = x;
			y1 = y;
			last = code;
			outcode(last,x1,y1);
			*clip_last = 1;
		}
    
		if ((first & last) != 0) {
			return CLIP_INVISIBLE; /* Trivially rejected! */
		}
		if ((first | last) == 0) {
			*_x0=x0; *_y0=y0;
			*_x1=x1; *_y1=y1;
			return CLIP_PARTIAL; /* Trivially accepted! */
		}
	}
}

⌨️ 快捷键说明

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