sgraph.cpp

 /************************************************************************
SANDEEP'S GRAPHICS LIBRARY: VERSION 1.0
*************************************************************************
FEATURES
1)nearly all graphics primitives
2)mouse support
3)pallete manipulation
4)requires only Turbo c++ ver 3.0
5)Please read the readme file  */

//welocome to sandeep's graphicslibrary .In many source codes graphic functions
//using functons is used.In my version oop pattern is followed which has many
//significant advantages in terms of reusablity,structure etc bla bla bluff!
//Any errors and shortcommings are due my pigheadness ,which i will try to
//rectify if u email me my email adress s19@swissinfo.org Or sndpmathew@yahoo.co.in

#include<stdio.h>
#include<dos.h>
#include<conio.h>
#include<malloc.h>
#include<iostream.h>
#include<math.h>
#include<process.h>
#include<time.h>
#define pi 3.14
#define screen_width  320
#define screen_height 200
#define AR 1.90
char far *ptr_to_video_segment=(char far*)MK_FP(0xa000,0x0000);
struct RGB
{
unsigned char red,green,blue;
};
typedef RGB pallete[256];
class graph        //prerequisites
   //hexadecimal format
{                  //memory in pc
private:           //functions available in dos.h
int x;
int yx320;
int u;
int y;
int delta_x,delta_y,d,incr_same,incr_new,temp;
int xc,yc,height,width;
int xcord,ycord;
int x_position, y_position, de, delta_e, delta_se;
float i;
char far *ptr;
int count;
float xe,ye;
int x_count, y_count, x_incr;
int temp_color;
unsigned char *pointer_within_sprite ;
unsigned char far *video_mem_pointer;
double radian;
clock_t start,end;
RGB temporary;



public:
void em13h();//function for entering mode 13h
void tmode();//text mode
void putpixel(int x,int y,unsigned char col);//displaying pixel
unsigned char readpixel(int x,int y);//returns color value  given a point in screen
void mdelay();//for waiting till crt displaying is finished .for smooth aminations
void horl(int x1,int x2,int y,unsigned char col);//Drawing horizontonal line
void verl(int x,int y,int len,unsigned char col);//vertical lines
void line(int x1,int y1,int x2,int y2,unsigned char color);//arbitary line using bresham's line drawing algorithm
void box(int x1,int y1,int x2,int y2,unsigned char col );  //drawing box
void rectangle(int x1,int y1,int x2,int y2,unsigned char col ) //drawing rectangles

{
box( x1, y1, x2, y2, col );
}
void putsprite(int x,int y,unsigned char sprite[]); //getsprite method
void getsprite(int x1, int y1, int x2, int y2, unsigned char sprite[],
unsigned char transparent_color, unsigned char convert_0_to_color);   //displaying sprite

void arc(int cx, int cy, int xr, int yr, double start, double finish,unsigned char color);
void circle(int x,int y,int rad,unsigned char color);  //breshams circle drawing  method
void fillcircle(int x,int y,int rad,unsigned char color);
void ellipse(float x1,float y1,float a,float b,unsigned char col);//using the theory of parametric coordinates
void bar(int,int,int,int,unsigned char);
void setmode(int m);     //general procedure for setting the mode
void setpalleteregs(char arr[]);
void writedot(int x,int y,int palleteregno);
/*the following functions were tested but were found unstisfatory so please
modify them yourselves*/
char getkey(int *attr);
void button(int x1, int y1, int x2, int y2, int press=0);
void window(int x1, int y1, int x2, int y2);
void clearscreen()
{
bar(0,0,319,199,0);
}
void setbackground(unsigned char col)
{
bar(0,0,319,199,col);
}
void tdelay(int secs);//wait for a given time
void setRGB(int num,RGB pal);
void cycleup(pallete &p,int s,int e);
void cyclepallete(pallete &p);
void setpallete(pallete p);
void getdefaultpallete(pallete &p);
void cycledown(pallete &p,int s,int e);
void fadetob(pallete &p);
};
void graph::setmode(int m)
{
_AH=0;
_AL=m;
geninterrupt(0x10);
}                       //faster than using REGS structure
void graph::em13h()
{
_AH=0;                     //a 320 x 100 video mode
_AL=0x13;
geninterrupt(0x10);
}
void graph::tmode()
{
_AH=0;
_AL=0x03;
geninterrupt(0x13);
}
char graph::getkey(int *attr)
{
_AH=0x08;
_BH=0;
geninterrupt(0x10);
*attr=_BL;
return _AL;
}
void graph::putpixel(int x,int y,unsigned char col)
{

pokeb(0xa000,((y*320)+x),col);
}
unsigned char graph::readpixel(int x,int y)
{
return peekb(0xa000,((y*320)+x));
}
void graph::setpalleteregs(char arr[])
{
_AH=0x10;
_AL=0x02;
_ES=FP_SEG(arr);
_DX=FP_OFF(arr);
geninterrupt(0x10);
}
void graph::writedot(int x,int y,int palleteregno)
{
_AH=12;
_AL=palleteregno;
_BH=0;
_CX=x;
_DX=y;
geninterrupt(0x10);
}
void graph::mdelay()
{
while(inportb(0x3da)&0x008);
while(!(inportb(0x3da)&0x008));
}
void graph::horl(int x1,int x2,int y,unsigned char col)
{
yx320=(y<<8)+(y<<6);
for(x=x1;x<=x2;x++)
pokeb(0xa000,yx320+x,col);
}
void graph::verl(int y1,int y2,int x,unsigned char col)
{

for(u=y1;u<=y2;u++)
{
yx320=(u<<8)+(u<<6);    //bit shifing is faster than multiplication
pokeb(0xa000,yx320+x,col);
}
}
void graph::box(int x1,int x2,int y1,int y2,unsigned char col)
{       line(x1,y1,x2,y1,col);
line(x1,y1,x1,y2,col);
line(x1,y2,x2,y2,col);
line(x2,y1,x2,y2,col);

}
void graph::putsprite(int x,int y,unsigned char sprite[])
{

   pointer_within_sprite = sprite + 4;
   video_mem_pointer = ptr_to_video_segment +
(y << 8) + (y << 6) + x;

width = sprite[0] + (sprite[1] << 8);
height = sprite[2] + (sprite[3] << 8);
x_incr = 320 - width;

for (y_count = 0; y_count <= height - 1; y_count++) {
for (x_count = 0; x_count <= width - 1; x_count++) {
if (*pointer_within_sprite) /* If not a transparent pixel... */
*(video_mem_pointer) = *(pointer_within_sprite);

video_mem_pointer++;
pointer_within_sprite++;
}

video_mem_pointer += x_incr;   /* Jump down to next row, first
  column */
}
}

void graph::getsprite(int x1, int y1, int x2, int y2, unsigned char sprite[],
unsigned char transparent_color, unsigned char convert_0_to_color)
{


   pointer_within_sprite = sprite + 4;
   video_mem_pointer = ptr_to_video_segment +
(y1 << 8) + (y1 << 6) + x1;

width = x2 - x1 + 1;
height = y2 - y1 + 1;
x_incr = 320 - width;

sprite[0] = width & 0xFF;
sprite[1] = width >> 8;
sprite[2] = height & 0xFF;
sprite[3] = height >> 8;

for (y_count = 0; y_count <= height - 1; y_count++) {
for (x_count = 0; x_count <= width - 1; x_count++) {
temp_color = *(video_mem_pointer++);
if (temp_color == transparent_color)  /* If transparent... */
*(pointer_within_sprite++) = 0;
else if (temp_color)                  /* If not 0... */
*(pointer_within_sprite++) = temp_color;
else                                  /* If 0... */
*(pointer_within_sprite++) = convert_0_to_color;
}

video_mem_pointer += x_incr;
}
}
void graph::arc(int cx, int cy, int xr, int yr, double start, double finish,unsigned char color)
{

radian=start;
do
{
x=int(cos(radian)*xr)+cx;
y=int(sin(radian)*yr*AR)+cy;
putpixel(x,y,color);
radian+=0.005;
}while(radian <finish);
}
void graph::ellipse(float x1,float y1,float a,float b,unsigned char col)
{
for(count=0;count<=360;count++)
{
xe=x1+a*cos(count*pi/180);//using floting point numbers.
ye=y1+b*sin(count*pi/180);//i will implement a better algorithm later
putpixel((int)xe,(int)ye,col);
}
}

void graph::line(int x1,int y1,int x2,int y2,unsigned char color)
{

delta_x = x2 - x1;
delta_y = y2 - y1;

if (delta_x == 0) {
verl (x1, y1, y2, color);     /* For efficiency */
return;
} else if (delta_y == 0) {
horl (x1, y1, x2, color);   /* For efficiency */
return;
}

if (abs(delta_x) >= abs(delta_y)) {       /* if x is the major axis: */
if (x2 < x1) {                /* if coordinates are out of order */
temp = x2;
x2 = x1;
x1 = temp;
delta_x = -delta_x;

temp = y2;
y2 = y1;
y1 = temp;
delta_y = -delta_y;
}

if (y2 > y1) {              /* when it is decided to change y, y
   should be incremented */
incr_same = delta_y << 1;
d = incr_same - delta_x;
incr_new = (delta_y - delta_x) << 1;

y = y1;
for (x = x1; x <= x2; x++) {
if (d > 0) {
y++;                      /* increment y here */
d += incr_new;
}
else
d += incr_same;
putpixel (x, y, color);
}
}
else {                      /* when it is decided to change y, y
   should be decremented */
incr_same = delta_y << 1;
d = incr_same + delta_x;
incr_new = (delta_y + delta_x) << 1;

y = y1;
for (x = x1; x <= x2; x++) {
if (d < 0) {
y--;                      /* decrement y here */
d += incr_new;
}
else
d += incr_same;
putpixel (x, y, color);
}
}
}
else {                                    /* if y is the major axis: */
if (y2 < y1) {                /* if coordinates are out of order */
temp = y2;
y2 = y1;
y1 = temp;
delta_y = -delta_y;

temp = x2;
x2 = x1;
x1 = temp;
delta_x = -delta_x;
}

if (x2 > x1) {              /* when it is decided to change x, x
   should be incremented */
incr_same = delta_x << 1;
d = incr_same - delta_y;
incr_new = (delta_x - delta_y) << 1;

x = x1;
for (y = y1; y <= y2; y++) {
if (d > 0) {
x++;                        /* increment x here */
d += incr_new;
}
else
d += incr_same;
putpixel (x, y, color);
}
}
else {                      /* when it is decided to change x, x
   should be decremented */
incr_same = delta_x << 1;
d = incr_same + delta_y;
incr_new = (delta_x + delta_y) << 1;

x = x1;
for (y = y1; y <= y2; y++) {
if (d < 0) {
x--;                      /* decrement x here */
d += incr_new;
}
else
d += incr_same;
putpixel (x, y, color);
}
}
}
}
void graph::circle (int x, int y, int radius, unsigned char color)
{
/* Uses my (slight) alteration of the midpoint line algorithm. */



x_position = -1;
y_position = radius;
de = 1 - radius;
delta_e = -1;
delta_se = (-radius << 1) + 3;

while (y_position > x_position) {
delta_e += 2;
x_position++;

if (de < 0) {
de += delta_e;
delta_se += 2;
}
else {
de += delta_se;
delta_se += 4;
y_position--;
}

putpixel (x + x_position, y + y_position, color);
putpixel (x + y_position, y + x_position, color);
putpixel (x + y_position, y - x_position, color);
putpixel (x + x_position, y - y_position, color);

putpixel (x - x_position, y - y_position, color);
putpixel (x - y_position, y - x_position, color);
putpixel (x - y_position, y + x_position, color);
putpixel (x - x_position, y + y_position, color);
}
}
void graph::fillcircle(int x,int y,int rad,unsigned char color)
{
for(i=1;i<=rad;i=i+0.25)
circle(x,y,rad,color);
}
void graph::bar (int x1, int y1, int x2, int y2, unsigned char color)
{
  ptr = ptr_to_video_segment + (y1 << 8) + (y1 << 6) + x1;
x_incr = 320 - (x2 - x1) - 1;

for (y = y1; y <= y2; y++) {
for (x = x1; x <= x2; x++)
*(ptr++) = color;
ptr += x_incr;
}
}
void graph::button(int x1, int y1, int x2, int y2, int press)
{

if(press)
{
line(x1,y1,x2,y1,0);
line(x1,y1,x1,y2,0);
line(x1,y2,x2,y2,15);
line(x2,y1,x2,y2,15);
}
else
{
line(x1,y1,x2,y1,15);
line(x1,y1,x1,y2,15);
line(x1,y2,x2,y2,0);
line(x2,y1,x2,y2,0);
}

}

void graph::window(int x1, int y1, int x2, int y2)
{
button(x1,y1,x2,y2);
bar(x1+1, y1+1, x2-2, y1+15, 1);

button(x2-14,y1+2,x2-2,y1+14);
bar(x2-13, y1+3, x2-3, y1+13, 7); //CLOSE
line(x2-13,y1+4,x2-4,y1+12,1);
line(x2-12,y1+4,x2-3,y1+12,1);//
line(x2-4,y1+4,x2-13,y1+12,1);
line(x2-3,y1+4,x2-12,y1+12,1);//

button(x2-28,y1+2,x2-16,y1+14);
bar(x2-27, y1+3, x2-17, y1+13, 7); //MAXIMIZE
rectangle(x2-27,y1+4,x2-18,y1+12,1);
line(x2-26,y1+5,x2-19,y1+5,1);

button(x2-42,y1+2,x2-30,y1+14);
bar(x2-41, y1+3, x2-31, y1+13, 7); //MINIMIZE
line(x2-39,y1+10,x2-34,y1+10,1);
line(x2-39,y1+11,x2-34,y1+11,1);

}
void graph::tdelay(int secs)
{
start=clock();
do
{
end=clock();
}
while(((start-end)/CLK_TCK)<secs);
}
void graph::cycledown(pallete &p,int s,int e)
{
temporary=p[e];
for(x=e;x>=s;x++)
{
p[x]=p[x+1];
p[s]=temporary;
}
}
void graph::setRGB(int num,RGB pal)
{
outportb(0x3c8,num);
outportb(0x3c9,pal.red);
outportb(0x3c9,pal.green);
outportb(0x3c9,pal.blue);
}
void graph::cycleup(pallete &p,int s,int e)
{
temporary=p[s];
for(s=s;x<e;x++)
p[x]=p[x+1];
p[e]=temporary;
}
void graph::fadetob(pallete &p)
{
p[0].red++;
p[0].green++;
p[0].blue++;
}
void graph::cyclepallete(pallete &p)
{
temporary=p[0];
for(x=0;x<256;x++)
p[x]=p[x+1];
p[255]=temporary;
}
void graph::getdefaultpallete(pallete &p)
{
for(x=0;x<256;x++)
{
outportb(0x3c8,x);
p[x].red=inportb(0x3c9);
p[x].green=inportb(0x3c9);
p[x].blue=inportb(0x3c9);
}
}
void graph::setpallete(pallete p)
{
for(x=0;x<256;x++)
setRGB(x,p[x]);
}


//Sandeep's class to implement mouse functions

struct mouse
{

int button,x,y; //for storing button,x,y
int initmouse();      //checking
void showmouseptr();   //displaying
void restrictmouseptr(int x1,int y1,int x2,int y2); //restricts bet boundary
void getmousepos(int *button,int *x,int *y); //gets mouse position
void hidemouseptr();                               //hides mouse
/*misc functions*/
int mon(int x1,int y1,int x2,int y2);
int bp(int bn);
int brel(int bn);
};
int mouse::initmouse()
{
_AX=0;
geninterrupt(0x33);
return(_AX);
}
void mouse::showmouseptr()
{
_AX=1;
geninterrupt(0x33);
}
void mouse::hidemouseptr()
{
_AX=2;
geninterrupt(0x33);
}
void mouse::restrictmouseptr(int x1,int y1,int x2,int y2)
{
_AX=7;
_CX=x1;
_DX=x2;
geninterrupt(0x33);
_AX=8;
_CX=y1;
_DX=y2;
geninterrupt(0x33);
}
void mouse::getmousepos(int *button,int *x,int *y)
{
_AX=3;
geninterrupt(0x33);
*button=_BX;
*x=_CX;
*y=_DX;
}
int mouse::mon(int x1,int y1,int x2,int y2)
{
getmousepos(&button,&x,&y);
if(x>=x1&&y>=y1&&x<=x2&&y<=y2)return 1;
return 0;
}
int mouse::bp(int bn)
{
_AX=0x0005;
_BX=bn;
geninterrupt(0x33);
return _BX;
}
int mouse::brel(int bn)
{
_AX=0x0006;
_BX=bn;
return _BX;
}



Project Homepage: