/* Object oriented interface to C graphics library. This version suitable for interfacing to Modula 2. For demo of this see file MIX_MOD.MOD */ #include #include #include #define ErrUnknownAdapter 1 #define ErrFewerColors 2 #define PI 3.141592554 int GraphErr; short GWindow::CurrentMode=_DEFAULTMODE; static struct videoconfig far vc; GWindow *GWindow::activewindow=0; GWindow::GWindow() { } GWindow::GWindow(GCoord X1,GCoord Y1,GCoord X2,GCoord Y2,int ColsReq) { ok=0; PreviousMode=CurrentMode; if (CurrentMode==_DEFAULTMODE) { short BestMode=_DEFAULTMODE; _getvideoconfig(&vc); switch (vc.adapter) { case _VGA: BestMode=ColsReq>16?_MRES256COLOR:_VRES16COLOR; if (ColsReq>256) GraphErr=ErrFewerColors; break; case _EGA: BestMode=_ERESCOLOR; if (ColsReq>16) GraphErr=ErrFewerColors; break; case _CGA: BestMode=ColsReq>2?_MRES4COLOR:_HRESBW; if (ColsReq>4) GraphErr=ErrFewerColors; break; case _HGC: BestMode=_HERCMONO; if (ColsReq>2) GraphErr=ErrFewerColors; break; default: GraphErr=ErrUnknownAdapter; return; } if (BestMode!=_DEFAULTMODE) { _setvideomode(BestMode); _getvideoconfig(&vc); // This info is needed by those who come after CurrentMode=BestMode; } } NumColors=vc.numcolors; ReSize(X1,Y1,X2,Y2); CurrentColor=NumColors-1; CurrentBackColor=0; ok=1; } void GWindow::ReSize(GCoord X1,GCoord Y1,GCoord X2,GCoord Y2) { XScale=vc.numxpixels; YScale=vc.numypixels; XL=XReal(X1); XR=XReal(X2); YT=YReal(Y1); YB=YReal(Y2); XScale=(vc.numxpixels*long(X2-X1))/1024; YScale=(vc.numypixels*long(Y2-Y1))/1024; activewindow=0; } GWindow::~GWindow() { ok=0; if (PreviousMode!=CurrentMode) // NB This assumes modes nest cleanly _setvideomode(PreviousMode); } void GWindow::AffixColor(int Col,int BkCol) { static int CurBackCol=-1; /* NB Setting background color is quite dear so avoid if poss */ int FC=Col==-1?CurrentColor:Col; _setcolor(FC%NumColors); _settextcolor(FC); FC=(Col==-1?CurrentBackColor:BkCol)%NumColors; if (FC!=CurBackCol) _setbkcolor(CurBackCol=FC); activewindow=this; } void GWindow::Plot(GCoord x,GCoord y,int Col) { if (activewindow!=this) { AffixColor(Col,-1); _setcliprgn(XL,YT,XR,YB); } _setpixel(XPhys(x),YPhys(y)); } int GWindow::Point(GCoord x,GCoord y) { if (activewindow!=this) _setcliprgn(XL,YT,XR,YB); return _getpixel(XPhys(x),YPhys(y)); } void GWindow::Fill(GCoord x,GCoord y,int Bound,char Flood) { if (activewindow!=this) { AffixColor(-1,-1); _setcliprgn(XL,YT,XR,YB); } int Col=(Bound==-1?CurrentColor:Bound)%NumColors; if (Flood) _floodfill(XPhys(x),YPhys(y),Col); else _stackfill(XPhys(x),YPhys(y),Col); } void GWindow::SetColor(int Col,int BkCol) { if (Col>0) CurrentColor=Col; if (BkCol>0) CurrentBackColor=BkCol; if (activewindow==this) AffixColor(-1,-1); } void GWindow::Clear(int BkCol) { AffixColor(-1,BkCol); _setviewport(XL,YT,XR,YB); _clearscreen(_GVIEWPORT); _setviewport(0,0,XR,YB); _setcliprgn(XL,YT,XR,YB); // Reset origin but correct clipping } void GWindow::Rectangle(GCoord Left,GCoord Top,GCoord Width,GCoord Height,int Fill) { AffixColor(-1,-1); _setcliprgn(XL,YT,XR,YB); _rectangle(Fill?_GFILLINTERIOR:_GBORDER, XPhys(Left),YPhys(Top),XPhys(Left+Width),YPhys(Top+Height)); } void GWindow::Polygon(short nsides,GCoord px[],GCoord py[],int Fill) { if (activewindow!=this) { AffixColor(-1,-1); _setcliprgn(XL,YT,XR,YB); } GCoord *nx=new GCoord[nsides]; GCoord *ny=new GCoord[nsides]; short n=nsides; while (nsides--) { nx[nsides]=XPhys(px[nsides]); ny[nsides]=YPhys(py[nsides]); } _polygon(Fill?_GFILLINTERIOR:_GBORDER,n,nx,ny); delete [] nx; delete [] ny; } void GWindow::Ellipse(GCoord X,GCoord Y,GCoord Major,GCoord Minor,int Fill) { AffixColor(-1,-1); _setcliprgn(XL,YT,XR,YB); _ellipse(Fill?_GFILLINTERIOR:_GBORDER, XPhys(X-Major),YPhys(Y-Minor),XPhys(X+Major),YPhys(Y+Minor)); } void GWindow::Line(GCoord X1,GCoord Y1,GCoord X2,GCoord Y2,int Col) { Plot(X1,Y1,Col); // This sets colors and clipping region for me _lineto(XPhys(X2),YPhys(Y2)); } void GWindow::VectorFromAngle(int Angle,GCoord &X,GCoord &Y) { double RA=Angle*PI/180.0; X=1024.0*cos(RA); Y=-1024.0*sin(RA); } /* Draw a proportion of an ellipse from starting position and subtended angle StartAngle to EndAngle. The angle measurements are in degrees and measured from the first quadrant */ void GWindow::ArcServer(GCoord X,GCoord Y,GCoord Major,GCoord Minor,int StartAngle,int EndAngle,char pie,int Fill) { GCoord StartX,StartY,EndX,EndY; VectorFromAngle(StartAngle,StartX,StartY); VectorFromAngle(EndAngle,EndX,EndY); AffixColor(-1,-1); _setcliprgn(XL,YT,XR,YB); // GCoord p1[8]={XPhys(X-Major),YPhys(Y-Minor),XPhys(X+Major),YPhys(Y+Minor), // XPhys(X+StartX),YPhys(Y+StartY),XPhys(X+EndX),YPhys(Y+EndY)}; if (pie) _pie(Fill?_GFILLINTERIOR:_GBORDER, XPhys(X-Major),YPhys(Y-Minor),XPhys(X+Major),YPhys(Y+Minor), StartX,StartY,EndX,EndY); else _arc(XPhys(X-Major),YPhys(Y-Minor),XPhys(X+Major),YPhys(Y+Minor), XReal(StartX),YReal(StartY),XReal(EndX),YReal(EndY)); /* if (pie) _pie(Fill?_GFILLINTERIOR:_GBORDER,p1[0],p1[1],p1[2],p1[3],p1[4],p1[5], p1[6],p1[7]); else _arc(p1[0],p1[1],p1[2],p1[3],p1[4],p1[5],p1[6],p1[7]);*/ } void GWindow::EllipticArc(GCoord X,GCoord Y,GCoord Major,GCoord Minor,int StartAngle,int EndAngle) { ArcServer(X,Y,Major,Minor,StartAngle,EndAngle,0,0); } void GWindow::EllipticPie(GCoord X,GCoord Y,GCoord Major,GCoord Minor,int StartAngle,int EndAngle,int Fill) { ArcServer(X,Y,Major,Minor,StartAngle,EndAngle,1,Fill); } void GWindow::Cuboid(GCoord X,GCoord Y,GCoord Width,GCoord Height,GCoord Depth, int Top,int Fill) { AffixColor(-1,-1); _setcliprgn(XL,YT,XR,YB); _cube(Fill?_GFILLINTERIOR:_GBORDER,Top?_GTOP:_GNOTOP, XPhys(X),YPhys(Y),XPhys(X+Width),YPhys(Y+Height),XReal(Depth)); } void GWindow::CursorPosition(GCoord x,GCoord y) { /* This procedure is a bit of a swiz as only character position resolution exists!!! */ int rx=int((XPhys(x)*(long)vc.numtextcols)/vc.numxpixels); int ry=int((YPhys(y)*(long)vc.numtextrows)/vc.numypixels); _settextwindow(1,1,vc.numtextrows,vc.numtextcols); _settextposition(ry+1,rx+1); AffixColor(-1,-1); } int GWindow::CharWidth() { return 1+int(1024L*vc.numxpixels / ((XR-XL)*vc.numtextcols)); } int GWindow::CharHeight() { return 1+int(1024L*vc.numypixels / ((YB-YT)*vc.numtextrows)); }