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

📄 generators.c

📁 miniucgui1.30版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** $Id: generators.c,v 1.8 2003/09/04 06:02:53 weiym Exp $**** generators.c: general line, circle, ellipse, arc generators.**** Copyright (C) 2003 Feynman Software** Copyright (C) 2001 ~ 2002 Wei Yongming.**** The line clipping algorithm comes from GGI.** Copyright (C) 1998 Alexander Larsson <alla@lysator.liu.se>**** The line generator comes from MicroWindows.** Copyright (C) 1999 Greg Haerr <greg@censoft.com>**** All other generators come from Allegro by Shawn Hargreaves and others. ** Thank for their great work and good license.**** "Allegro is a gift-software"**** Current maintainer: Wei Yongming.**** Create date: 2001/10/12, derived from original draw.c*//*** 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*//*** TODO:*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "common.h"#include "minigui.h"#include "gdi.h"#include "fixedmath.h"/* Line clipper *//*  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.*/#define OC_LEFT 1#define OC_RIGHT 2#define OC_TOP 4#define OC_BOTTOM 8/* Outcodes:+-> x|       |      | V  0101 | 0100 | 0110y ---------------------   0001 | 0000 | 0010  ---------------------   1001 | 1000 | 1010        |      |  */#define outcode(code, xx, yy) \{\  code = 0;\ if (xx < cliprc->left)\    code |= OC_LEFT;\  else if (xx >= cliprc->right)\    code |= OC_RIGHT;\  if (yy < cliprc->top)\    code |= OC_TOP;\  else if (yy >= cliprc->bottom)\    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;}BOOL GUIAPI LineClipper (const RECT* cliprc, int *_x0, int *_y0, int *_x1, int *_y1){    int first, last, code;    int x0, y0, x1, y1;    int x, y;    int dx, dy;    int xmajor;    int slope;        if (*_x0 == *_x1 && *_y0 == *_y1) { /* a pixel*/        return PtInRect (cliprc, *_x0, *_y0);    }    else if (*_x0 == *_x1) { /* a vertical line */        int sy, ey;        if (*_y1 > *_y0) {            sy = *_y0;            ey = *_y1;        }        else {            sy = *_y1;            ey = *_y0;        }        if ( (*_x0 >= cliprc->right) || (sy >= cliprc->bottom) ||                     (*_x0 < cliprc->left) || (ey < cliprc->top) )            return FALSE;        if ( (*_x0 >= cliprc->left) && (sy >= cliprc->top) &&                     (*_x0 < cliprc->right) && (ey < cliprc->bottom) )            return TRUE;                            if (sy < cliprc->top)            sy = cliprc->top;        if (ey >= cliprc->bottom)            ey = cliprc->bottom - 1;        if (ey < sy)            return FALSE;        *_y0 = sy;        *_y1 = ey;        return TRUE;    }    else if (*_y0 == *_y1) { /* a horizontal line */        int sx, ex;        if (*_x1 > *_x0) {            sx = *_x0;            ex = *_x1;        }        else {            sx = *_x1;            ex = *_x0;        }        if ( (sx >= cliprc->right) || (*_y0 >= cliprc->bottom) ||                     (ex < cliprc->left) || (*_y0 < cliprc->top) )            return FALSE;        if ( (sx >= cliprc->left) && (*_y0 >= cliprc->top) &&                     (ex < cliprc->right) && (*_y0 < cliprc->bottom) )            return TRUE;                            if (sx < cliprc->left)            sx = cliprc->left;        if (ex >= cliprc->right)            ex = cliprc->right - 1;        if (ex < sx)            return FALSE;        *_x0 = sx;        *_x1 = ex;        return TRUE;    }    first = 0;    last = 0;    outcode (first, *_x0, *_y0);    outcode (last, *_x1, *_y1);    if ((first | last) == 0) {        return TRUE; /* Trivially accepted! */    }    if ((first & last) != 0) {        return FALSE; /* 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));      while (TRUE) {        code = first;        if (first == 0)            code = last;        if (code & OC_LEFT) {            x = cliprc->left;            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 = cliprc->right - 1;            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 = cliprc->top;            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 = cliprc->bottom - 1;            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) {            x0 = x;            y0 = y;            outcode (first, x0, y0);        } else {            x1 = x;            y1 = y;            last = code;            outcode (last, x1, y1);        }            if ((first & last) != 0) {            return FALSE; /* Trivially rejected! */        }        if ((first | last) == 0) {            *_x0 = x0; *_y0 = y0;            *_x1 = x1; *_y1 = y1;            return TRUE; /* Trivially accepted! */        }    }}/* Breshenham line generator */void GUIAPI LineGenerator (void* context, int x1, int y1, int x2, int y2, CB_LINE cb){    int xdelta;     /* width of rectangle around line */    int ydelta;     /* height of rectangle around line */    int xinc;       /* increment for moving x coordinate */    int yinc;       /* increment for moving y coordinate */    int rem;        /* current remainder */        cb (context, 0, 0);    if (x1 == x2 && y1 == y2) { /* a pixel */        return;    }    else if (x1 == x2) { /* a vertical line */        int dir = (y2 > y1) ? 1 : -1;        do {            cb (context, 0, dir);            y1 += dir;        } while (y1 != y2);        return;    }    else if (y1 == y2) { /* a horizontal line */        int dir = (x2 > x1) ? 1 : -1;        do {            cb (context, dir, 0);            x1 += dir;        } while (x1 != x2);        return;    }    xdelta = x2 - x1;    ydelta = y2 - y1;    if (xdelta < 0) xdelta = -xdelta;    if (ydelta < 0) ydelta = -ydelta;    xinc = (x2 > x1) ? 1 : -1;    yinc = (y2 > y1) ? 1 : -1;    if (xdelta >= ydelta) {        rem = xdelta >> 1;        while (x1 != x2) {            x1 += xinc;            rem += ydelta;            if (rem >= xdelta) {                rem -= xdelta;                y1 += yinc;                cb (context, xinc, yinc);            }            else                cb (context, xinc, 0);        }    } else {        rem = ydelta >> 1;        while (y1 != y2) {            y1 += yinc;            rem += xdelta;            if (rem >= ydelta) {                rem -= ydelta;                x1 += xinc;                cb (context, xinc, yinc);            }            else                cb (context, 0, yinc);

⌨️ 快捷键说明

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