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

📄 graf.c

📁 MSC TURBO-C图形库
💻 C
字号:
/*
 * grafix --- graf.c
 *
 * graphics interface
 *
 * Written 4/87 by Scott Snyder (ssnyder@romeo.caltech.edu or @citromeo.bitnet)
 *
 * 5/29/87 sss - fixed bug in box() and allow for different memory models
 *
 */

#include "macros.h"
#include "graf.h"
#include "grafsys.h"
#include <dos.h>

#define int_video   0x10
#define video_point 0x0c
#define ega_altsel  0x12
#define egaalt_info 0x10

/* utility macros */

#define swap(a, b) {int _tmp; _tmp=a; a=b; b=_tmp;}
#define inrange(a, x, b) ((a)<=(x) && (x)<=(b))
#define clipto(x, lo, hi) { \
  if (x < lo)               \
    x = lo;                 \
  else if (x > hi)          \
    x = hi;                 \
}

/*****************************************************************************
 *                            variable definitions                           *
 *****************************************************************************/

unsigned NEAR g_card;		/* graphics card we're using */
unsigned NEAR g_display;	/* type of display we're using */

g_obj far * NEAR g_drawbuf;	/* graphics drawing buffer */
g_obj far * NEAR g_physbuf;	/* physical screen address */
g_obj far * NEAR g_virtbuf;	/* virtual buffer address  */
unsigned NEAR g_colormax;	/* maximum color value     */
unsigned NEAR g_xsize, NEAR g_ysize; /* physical size of screen */
unsigned NEAR g_xchsize, NEAR g_ychsize; /* size of screen in characters */
unsigned NEAR g_xor;		/* xor mode flag */
unsigned NEAR g_bufflg;		/* buffered mode flag */
unsigned NEAR g_pages;		/* number of pagse available */
unsigned NEAR g_curpage;	/* page currently visible */

int NEAR g_xcliplo, NEAR g_xcliphi; /* clipping boundaries */
int NEAR g_ycliplo, NEAR g_ycliphi;

float NEAR g_aspect;		/* aspect ratio */

/*****************************************************************************
 *                       interfaces to graphics drivers                      *
 *****************************************************************************/

/************************* calls for internal use only ***********************/

STATIC void nocl_regfill(x1, y1, x2, y2, c)
unsigned x1, y1, x2, y2, c;
{
  switch(g_card) {
    case (CGA): CGA_regfill(x1, y1, x2, y2, c); break;
    case (EGA): EGA_regfill(x1, y1, x2, y2, c); break;
  }
}

STATIC void nocl_point(x, y, c)
unsigned x, y, c;
{
  switch(g_card) {
    case (CGA): CGA_point(x, y, c); break;
    case (EGA): EGA_point(x, y, c); break;
  }
}

STATIC void nocl_line(x1, y1, x2, y2, c)
unsigned x1, y1, x2, y2, c;
{
  switch(g_card) {
    case (CGA): CGA_line(x1, y1, x2, y2, c); break;
    case (EGA): EGA_line(x1, y1, x2, y2, c); break;
  }
}

STATIC void write_pix(x1, y1, x2, y2, c)
int x1, y1, x2, y2;
unsigned c;
{
  switch(g_card) {
    case (CGA): CGA_write_pix(x1, y1, x2, y2, c); break;
    case (EGA): EGA_write_pix(x1, y1, x2, y2, c); break;
  }
}

/* set up for plotting mucho points */

STATIC void point_set(c)
unsigned c;
{
  switch(g_card) {
    case (CGA): CGA_point_set(c); break;
    case (EGA): EGA_point_set(c); break;
  }
}

STATIC void point_res()
{
  switch(g_card) {
    case (CGA): CGA_point_res(); break;
    case (EGA): EGA_point_res(); break;
  }
}

/******************** calls safe for anyone to use **************************/

void g_clearall(c)
unsigned c;
{
  switch(g_card) {
    case (CGA): CGA_clearall(c); break;
    case (EGA): EGA_clearall(c); break;
  }
}

void g_show()
{
  switch(g_card) {
    case (CGA): CGA_show(); break;
    case (EGA): EGA_show(); break;
  }
}

void g_setback(c)
unsigned c;
{
  switch(g_card) {
    case (CGA): CGA_setback(c); break;
    case (EGA): EGA_setback(c); break;
  }
}

void g_setpal(pallette, value)
unsigned pallette, value;
{
  switch(g_card) {
    case (CGA): CGA_setpal(pallette, value); break;
    case (EGA): EGA_setpal(pallette, value); break;
  }
}

/* g_open also sets clipping boundaries to the physical screen size */
/* and initializes other things... */

void g_open(mode)
unsigned mode;
{
  switch(g_card) {
    case (CGA): CGA_gopen(mode); break;
    case (EGA): EGA_gopen(mode); break;
  }
  g_xcliplo = 0;
  g_ycliplo = 0;
  g_xcliphi = g_xsize-1;
  g_ycliphi = g_ysize-1;

  g_xor = g_bufflg = 0;

/* set g_drawbuf to something appropriately */

  g_setbuf(g_bufflg);
}

void g_close()
{
  switch(g_card) {
    case (CGA): CGA_gclose(); break;
    case (EGA): EGA_gclose(); break;
  }
}

void g_writech(row, col, ch, c, page)
unsigned row, col, c;
char ch;
int page;
{
  switch(g_card) {
    case (CGA): CGA_writech(row, col, ch, c, page); break;
    case (EGA): EGA_writech(row, col, ch, c, page); break;
  }
}

/***************************************************************************
 *                    graphics drawing and control routines                *
 ***************************************************************************/

/* fill a region with the specified color */

void g_regfill(x1, y1, x2, y2, c)
int x1, y1, x2, y2;
unsigned c;
{
  if (x1 > x2)
    swap(x1, x2);
  if (y1 > y2)
    swap(y1, y2);

  if (x1 < g_xcliplo)
    x1 = g_xcliplo;
  else if (x1 > g_xcliphi)
    return;

  if (x2 < g_xcliplo)
    return;
  else if (x2 > g_xcliphi)
    x2 = g_xcliphi;

  if (y1 < g_ycliplo)
    y1 = g_ycliplo;
  else if (y1 > g_ycliphi)
    return;

  if (y2 < g_ycliplo)
    return;
  else if (y2 > g_ycliphi)
    y2 = g_ycliphi;

  nocl_regfill(x1, y1, x2, y2, c);
}

/* plot a point */

void g_point(x, y, c)
int x, y;
unsigned c;
{
  if (inrange(g_xcliplo, x, g_xcliphi) &&
      inrange(g_ycliplo, y, g_ycliphi))
    nocl_point(x, y, c);
}

/* routine to clip one endpoint of a line */

STATIC int clipln(x1,y1,xc,yc,x2,y2)
int x1,y1,x2,y2,*xc,*yc;
{
  int delx,dely,xx,yy;
 
  if (x1 >= g_xcliplo && x1 <= g_xcliphi &&
      y1 >= g_ycliplo && y1 <= g_ycliphi) {
    *xc=x1; *yc=y1;
     return(1);
  }
  dely=y2-y1;
  delx=x2-x1;
  if (y1 > g_ycliphi || y1 < g_ycliplo) {
    if (dely == 0)
      return(0);
    if (y1 > g_ycliphi) {
      if (dely > 0 || y2 > g_ycliphi) return (0);
      yy=g_ycliphi;
    }
    else {
      if (dely < 0 || y2 < g_ycliplo) return(0);
      yy=g_ycliplo;
    }
    xx=(float)(yy-y1)*delx/dely+x1;
    if (xx >= g_xcliplo && xx <= g_xcliphi) {
      *xc=xx; *yc=yy;
      return(1);
    }
  }
  if (x1 > g_xcliphi || x1 < g_xcliplo) {
    if (delx == 0)
      return(0);
    if (x1 > g_xcliphi) {
      if (delx > 0 || x2 > g_xcliphi) return(0);
      xx=g_xcliphi;
    }
    else {
      if (delx < 0 || x2 < g_xcliplo) return(0);
      xx=g_xcliplo;
    }
    yy=(float)(xx-x1)*dely/delx+y1;
    if (yy >= g_ycliplo && yy <= g_ycliphi) {
      *xc=xx; *yc=yy;
      return(1);
    }
  }
  return(0);
}
 
/* draw a clipped line */
 
void g_line(x1,y1,x2,y2,c)
int x1,y1,x2,y2;
unsigned c;
{
  if (clipln(x1,y1,&x1,&y1,x2,y2) &&
      clipln(x2,y2,&x2,&y2,x1,y1)) {
    nocl_line(x1,y1,x2,y2,c);
  }
}

/* draw an ellipse with aspect aspect and half-major axis length r_sum_m */
/* from a routine by Tim Hogan in Dr. Dobb's Journal May '85 p. 40       */

void g_ellipse(x, y, r_sub_m, aspect, c)
int x,y,r_sub_m;
unsigned c;
float aspect;
{
  long alpha, beta, two_alpha, four_alpha, two_beta, four_beta, d;
  int row, col, two_x, two_y, rel_x, rel_y;
  double square_aspect;

  if (aspect < 0.004) aspect = 0.004;

  square_aspect = aspect*aspect;

  if (aspect < 1.0) {
    alpha = (long)r_sub_m * (long)r_sub_m;
    beta = alpha * square_aspect;
    row = y + r_sub_m*aspect;
  }
  else {
    beta = (long)r_sub_m * (long)r_sub_m;
    alpha = beta / square_aspect;
    row = y + r_sub_m;
  }

  if (alpha == 0L) alpha = 1L;
  if (beta  == 0L) beta  = 1L;

  col = x;
  two_x = x<<1;
  two_y = y<<1;
  rel_y = row-y;
  two_alpha  = alpha<<1;
  four_alpha = alpha<<2;
  two_beta   =  beta<<1;
  four_beta  =  beta<<2;

  d = two_alpha*((long)(rel_y-1)*rel_y) + alpha + two_beta*(1-alpha);

  point_set(c);			/* set up for point plotting */

  while (alpha*(rel_y = row-y) > beta*(rel_x = col-x)) {
    write_pix(col, row, two_x-col, two_y-row, c);
    if (d>=0) {
      d += four_alpha*(1-rel_y);
      row--;
    }
    d += two_beta*(3+(rel_x<<1));
    col++;
  }

  d = two_beta * ((long)rel_x * (rel_x+1)) + two_alpha*((long)rel_y*(rel_y-2)+1) +
      beta*(1-two_alpha);

  while ((rel_y = row-y) + 1) {
    write_pix(col, row, two_x-col, two_y-row, c);
    if (d<=0) {
      d += four_beta*(1+col-x);
      col++;
    }
    d += two_alpha*(3-(rel_y<<1));
    row--;
  }
  point_res();				/* reset the graphics device */
}

/* draw a circle */

void g_circle(x, y, r, c)
int x, y, r;
unsigned c;
{
  g_ellipse(x, y, r, g_aspect, c);
}

/* draw a box */

void g_box(x1, y1, x2, y2, c)
int x1, y1, x2, y2;
unsigned c;
{
  g_line(x1, y1, x2, y1, c);
  g_line(x2, y1, x2, y2, c);
  g_line(x2, y2, x1, y2, c);
  g_line(x1, y2, x1, y1, c);
}

/* set xor mode */

void g_setxor(flag)
unsigned flag;
{
  g_xor = flag;
}

/* set clipping boundaries */

void g_setclip(x1, y1, x2, y2)
int x1, y1, x2, y2;
{
  if (x1 > x2)
    swap(x1, x2);
  if (y1 > y2)
    swap(y1, y2);

  clipto(x1, 0, g_xsize-1);
  clipto(x2, 0, g_xsize-1);
  clipto(y1, 0, g_ysize-1);
  clipto(y2, 0, g_ysize-1);

  g_xcliplo = x1;
  g_xcliphi = x2;
  g_ycliplo = y1;
  g_ycliphi = y2;
}

/* clear screen within clipping boundaries */

void g_clear(c)
unsigned c;
{
  nocl_regfill(g_xcliplo, g_ycliplo, g_xcliphi, g_ycliphi, c);
}

/* set buffered mode flag and initialize drawbuf appropriately */

void g_setbuf(flag)
unsigned flag;
{
  g_bufflg = flag;
  if (flag)
    g_drawbuf = g_virtbuf;
  else
    g_drawbuf = g_physbuf;
}

/* initialize graphics system */

void g_init(card, display)
unsigned card;
unsigned display;			/* ignored if card = 0 */
{
  unsigned swt;
  union REGS inregs, outregs;

/* try to get EGA information. if we have enough memory for 2 hi-res
   pages, then say we have an EGA. if not, or if the card does not
   respond, assume we have a CGA. if argument is nonzero however, force
   result to that.
*/

  if (card == 0) {
    inregs.h.ah = ega_altsel;
    inregs.h.bl = egaalt_info;
    int86(int_video, &inregs, &outregs);
    if (outregs.h.bl != 3) {              /* not valid | mem. < 256k */
      g_card = CGA;
      g_display = CD;
    }
    else {
      g_card = EGA;

  /* now look at the adapter switch settings (in cl) and try to figure
     out what sort of display is attached */

      swt = outregs.h.cl & 0x0e;
      swt = (swt >= 6 ? swt-6 : swt);
      if (swt == 4)
        g_display = MO;
      else if (swt == 2)
        g_display = EN;
      else if (swt == 0)
        g_display = CD;
      else
        g_display = CD;
    }
  }
  else {
    g_card = card;
    g_display = display;
  }

  g_xor = 0;
  g_bufflg = 0;
  g_xcliplo = g_xcliplo = g_ycliphi = g_ycliplo = 0;
}

/* write a string tty style with color c at row, col */

void g_writestr(row, col, s, c, page)
unsigned row, col;
unsigned c;
char *s;
int page;
{
  while (*s) {
    if (col >= g_xchsize) {	/* do wrapping */
      col = 0;
      row++;
    }
    if (row >= g_ychsize) 	/* abort if we run out of screen */
      return;
    if (*s == '\012')		/* newline */
      col = g_xchsize;		/* force a wrap next time around */
    else if (*s == '\015')	/* ignore any carriage returns (for compat) */
      ;
    else {
      g_writech (row, col, *s, c, page);
      col++;
    }
    s++;
  }
}

/* get information about physical graphics device */

void g_info(p)
struct g_info *p;
{
  p->card     = g_card;
  p->display  = g_display;
  p->xsize    = g_xsize;
  p->ysize    = g_ysize;
  p->colormax = g_colormax;
  p->pages    = g_pages;
  p->curpage  = g_curpage;
  p->xchsize  = g_xchsize;
  p->ychsize  = g_ychsize;
}

⌨️ 快捷键说明

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