Copyright © 1995 Walt Davis
http://www.waltdavis.net
GRAPHICS_PORT_SYSTEM.HPP
This is the windowing system graphics platform. This code needs to be completely reworked. Nevertheless, it served as an excellent platform for the testing of an object oriented graphics framework. It's heavily used by GraphicObjectClass. The graphics primitives in GraphicObjectClass do not use the graphics primitives provided by the windowing system; instead, they use the data structures and have been hardcoded. The windowing system primitives and functions can still be used in conjunction with the object oriented system, but the window initialization functions have to be used in order for the object oriented system to work. |
GLOBAL.HPP
Global definition file. Defines basic coordinate concepts and constants. |
TRANSFORMER.HPP
Transformer objects have two uses: 1) to translate a graphic object’s coordinate system into the coordinate system of another graphic object during an attachment, and 2) standard graphic object transformations. Attachment transformation are implicitly carried out by library code during an attachment. Standard transformation are explicitly carried out by library users via public member functions. If reset() is never used then the transformations will build on one another in the order sequenced. |
GRAPHIC_OBJECT_CLASS.HPP
The GraphicObjectClass is metaclass data type that defines the basic graphics structure of all graphic object types. It acts as a template defining the graphics capability of all graphic objects. Meteclass is a SmallTalk term. The C++ language does not provided a true metaclass type specifier; nevertheless, a metaclass can be mimicked via constructors, virtual functions, and static data members. Static data members are the key element. This is because the static data member is used globally across all instances of an object derived from the metaclass. A metaclass establishes a type of class, not a class type. |
GRAPHIC_OBJECT.HPP
GraphiObject is the center point at which everything needed for a fully functional graphic object comes together. And unfortunately the point at which problems start to show. The virtual inheritance insures single copies of GraphicObjectClass and Extent in objects derived from two base class GraphicObjects. Virtual creates a pointer to the inherited class instead of encoding the inherited class’s genetic makeup directly into the derived class’s genetic makeup. The inherited class Object should also be virtual; however, I was unable to compile the code when using the virtual qualifier. Object is taken from Borlands Object Class Library and is used to promote the weak type checking needed to implement the container technology used by Borland. |
GRAPHIC_ARRAY.HPP
GraphicArray is a graphic object that has been given the ability to contain other graphic objects in the form of a dynamic array. It allows the building of complex scenes. Each graphic object that it contains goes through a coordinate system translation into the container graphic object’s coordinate system via an attachment. The containment functionality is inherited from Borlands Array class type. Because I use Array to provide containment, I had to create GraphicObject using Object as a base class. Borlands Object Class Library container establishes containment by casting contained objects, in the form of a pointer, back to Object. |
#ifndef __GLOBAL_HPP
#include <GLOBAL.HPP>
#endif
#if !defined(OFF)
#define OFF 0
#define ON 1
#endif
#if !defined(__GRAPHICS_H)
#include <graphics.h>
#endif
#if !defined(__GPSYS_HPP)
#define __GPSYS_HPP "video display Graphics
Port System by Walt Davis"
#define GPTITLELEN 40
#define Horiz(p) _PORT[p].Horiz
#define Vert(p) _PORT[p].Vert
#define XYScale(p) _PORT[p].XYScale
/* The following absolute space mapping macros
are redundent. The functionality of
these macros could easilly be built into
a single Transformer, one for each window. */
#define AX(p,x) Horiz(p)+((_PORT[p].Window.CenterX+x)*XYScale(p))
// horizontal mapping
#define AY(p,y) Vert(p)-((_PORT[p].Window.CenterY+y)*XYScale(p))
// vertical mapping
#define SCALE(p,n)
(n*0.5*XYScale(p))-0.5
// magnitude mapping
#define NX(p,x) _PORT[p].ViewWidth*x
// normalized device coordinates
#define NY(p,y) _PORT[p].ViewHeight*y
// normalized device coordinates
typedef enum {GPok,
GPsys_init,
GPsys_access,
GPsys_mapping,
GPport_init,
GPport_not_active,
GPwindow_size,
GPport_invalid,
GPview,
GPwindow} GPSYSTEMRSLT; // exception handling
typedef struct {int x,y;} PIXEL;
// device coordinate vector
typedef struct {float x,y;} VEC2;
// 2D absolute coordinate vector
typedef struct {float x,y,z;} VEC3; // 3D absolute
coordinate vector
typedef struct {char Title[GPTITLELEN+1]; //
border title
char FontType;
// border title font type
char FontSize;
// border title font size
char FontColor;
// border title font color
char LineStyle;
// border line style
unsigned LineUPattern; // border user defined bit pattern
char LineThickness; // border line
thickness
char LineColor;
// border line color
char Draw;} BORDER; // border draw
(TRUE,FALSE)
typedef struct {float Left;
// view left device x coordinate
float Top; // view
top device y coordinate
float Right; // view right device
x coordinate
float Bot; // view
bottom device y coordinate
char FillColor; // view fill color
char Fill; // fill
view (TRUE,FALSE)
char Clip;} VIEW; // clip view (TRUE/FALSE)
typedef struct {float Size;
// window size
float CenterX; //
absolute X coordinate of window origin
float CenterY;} WINDOW; // absolute Y coordinate of window origin
typedef struct {char Color;
// axis color
int LabelInc; // axis label
increment
char DrawLabel; // draw labels (TRUE,FALSE)
char DrawAxis;} AXIS; // draw axis (TRUE,FALSE)
typedef struct {char Initilized;
// port initilized (TRUE/FALSE)
char Active;
// port active (TRUE/FALSE)
char DrawColor;
// port draw color
float AX;
// current port absolute X coordinate
float AY;
// current port absolute Y coordinate
int DX;
// current port device X coordinate
int DY;
// current port device Y coordinate
float NX;
// current port normalized x coordinate
float NY;
// current port normalixed y coordinate
int ViewWidth;
// port view width
int ViewHeight;
// port view height
float WindowWidth; // port window
width
float WindowHeight; // port window
height
float Horiz;
// port horizontal scaling component
float Vert;
// port vertical scaling component
float XYScale;
// port horizontal and vertical scaling factor
BORDER Boarder;
// port border
VIEW View;
// port view
WINDOW Window;
// port window
AXIS Axis;} GRAPHICSPORT; // port axis
extern char _GP_SYS_INIT;
// system initilized
extern mapping _GP_MAPPING;
// absolute mapping on or off
extern int
_MAX_PORT;
// total number of graphics ports
extern int
_MAX_POLY;
// largest possible polygon size
extern access _GP_ACCESS;
// direct or indirect
extern char _CURRENT_GP;
// current graphics port
extern GPSYSTEMRSLT _LAST_RESULT;
// result of last GP system function
extern GRAPHICSPORT *_PORT;
// graphics port array
extern PIXEL *_POLY_BUFFER;
// global integer polygon buffer
extern int
_MAXX;
// max X coordinate of display device
extern int
_MAXY;
// max Y coordinate of display device
extern int
_NX,_NY;
// current Borland normalized X and Y coordinates
void InitGPSystem (int maxport,int maxpoly,int
gdriver,int gmode,char *path);
void InitGP (int port,BORDER border,VIEW view,WINDOW
window,AXIS axis);
void SelectGP (int port);
void SelectAllGP (void);
void FreeGP (int port);
void FreeAllGP (void);
void SetGPAccess (access aNew);
void SetGPMapping (int map);
void SetCurrentGP (int port);
void SetGPBoarder (int port,BORDER border);
void SetGPView (int port,VIEW view);
void SetGPAxis (int port,AXIS axis);
void SetGPTitle (int port,char *title);
void SetGPClipping (int port,int clip);
void SetGPDrawColor (int port,int color);
void SetGP (int port);
void GetGPSysStatus (access *aCurrent,mapping
mCurrent);
int GetGPResult (void);
int GetMaxGP (void);
int GetMaxGPPoly (void);
void GetGPBoarder (int port,BORDER *border);
void GetGPView (int port,VIEW *view);
void GetGPViewWH (int port,int *width,int *height);
void GetGPWindowWH (int port,int *width,int
*height);
int GetGPWindowSize (int port);
void GetGPAxis (int port,AXIS *axis);
int GetGPDrawColor (int port);
void GetGPCurrentAXY (int port,float *x,float
*y);
void GetGPCurrentDXY (int port,int *x,int *y);
void MoveGPWindow (int port,float x,float y);
void SizeGPWindow (int port,float size);
int IsGPInitilized (int port);
int IsGPActive (int port);
void PaintGP (int port);
void PaintActiveGP (void);
void PaintGPBoarder (int port);
void PaintGPAxis (int port);
void PaintxyGPText (int port,float x,float y,char
*str);
void EraseGP (int port);
void EraseActiveGP (void);
void FillGP (int port,int color);
void SetDrawColor (int color);
void Erase (void);
void Fill (int port,int color);
void OutTextXY (int x,int y,char *string);
void MoveTo (float x,float y);
void MoveTo (VEC2 pt);
void PlotPoint (float x,float y);
void PlotPoint (VEC2 pt);
void DrawLine (float x1,float y1,float x2,float
y2);
void DrawLine (VEC2 pt1,VEC2 pt2);
void LineTo (float x,float y);
void LineTo (VEC2 pt);
void DrawPoly (int n,VEC2 pts[]);
void FillPoly (int n,VEC2 pts[]);
void EndGPSystem(void);
#endif
#ifndef __MATH_H
#include <MATH.H>
#endif
#ifndef __GLOBOL_HPP
#define __GLOBOL_HPP
#define real float // defines the
type of real numbers used
#define MATSIZE 3 // only
need a 3x3 matrix for 2D transformations
extern real PIE;
typedef enum {FALSE=0,TRUE} flag;
typedef enum {ABSOLUTE,NORMALIZED,DEVICE} mapping;
// specifies type coordinate system
typedef enum {CURRENT,ACTIVE,TERMINAL} access;
// specifies graphics port access type
typedef enum {CLOCKWISE,COUNTER_CLOCKWISE} rotation;
// specifies direction of rotation
/* forward declarations */
struct Point;
// defines a 2D point
struct Matrix;
// defines a linear matrix
struct Extent;
// defines the extent of a graphic object
class Transformer;
// defines a 2D transformation matrix
class GraphicObjectClass;
// defines a metaclass graphic object class type
class GraphicObject;
// defines the abstract class type graphic object
class GraphicArray;
// defines a graphic object array container type
/* line mid point calculations */
real MidPoint(real,real);
Point MidPoint(Point&,Point&);
/* The following abstract types are struct declared classes. The struct type specifier is used to signify a data structure used as a class having only public members and not overloading the default constructor. The greatest advantage of such structures is that they can be initialized using array initialization syntax. This style of initialization is provided by the default constructor (which performs a bitwise memory copy of objects). */
struct Point // a 2D point
{
real x;
real y;
Point operator*(const
Matrix&); // column vector to matrix multiplication
};
struct Matrix // linear matrix used for
transformations
{
real mat[MATSIZE][MATSIZE];
Matrix operator*(const Matrix&); // matrix multiplication
void Con (real rConst);
// initialize matrix with a constant value
void Identity (void);
// initialize matrix to identity form
void PrintMat (void);
// print matrix to stdout in matrix form
};
struct Extent // defines the rectangular
region space occupied by a graphic object
{
Point pTopLeft;
// upper left hand corner of boundary
Point pTopRight;
// upper right hand corner of boundary
Point pBotRight;
// lower right hand corner of boundary
Point pBotLeft;
// lower left hand corner of boundary
Point
ExtentCenter
(void);
// returns center point of extent
Point ExtentCenterLeft
(void);
// returns left hander center point of extent
Point ExtentCenterRight
(void);
// returns right hand center point of extent
Point ExtentCenterTop
(void);
// returns top center point of extent
Point ExtentCenterBot
(void);
// returns bottom center point of extent
Point ExtentTopLeft
(void) {return pTopLeft;}; // returns upper left hand corner
point of extent
Point ExtentTopRight
(void) {return pTopRight;}; // returns upper right hand corner point of
extent
Point ExtentBotLeft
(void) {return pBotLeft;}; // returns lower left hand corner
point of extent
Point ExtentBotRight
(void) {return pBotRight;}; // returns bottom left hand corner point of
extent
real ExtentWidth (void)
{return (fabs(pTopRight.x)-fabs(pTopLeft.x));}; // returns extent
width
real ExtentHeight (void)
{return (fabs(pTopRight.y)-fabs(pBotLeft.y));}; // returns extent height
};
#endif
#ifndef __TFORMER_HPP
#define __TFORMER_HPP
class Transformer
{
public:
Transformer(void); //
calls Reset()
void SetArbPoint (real,real);
// Sets the arbitrary point of transformation. All transformations except
for
// Translate() use the arbitrary point as a point of relativity.
void PrintTformer (void)
{mTformer.PrintMat();}; // prints the
transformation matrix to stdout
flag IsLockedTformer
(void) {return fLockedTformer;}; // locks out execution of transformations
void TformerLockOn (void)
{fLockedTformer = TRUE;};
void TformerLockOff
(void) {fLockedTformer = FALSE;};
virtual void Reset(void); // resets the transformation matrix to default values, not effected by lock.
Transformer& operator=(const
Transformer&);
// copies contents of transformation matrix only
virtual Transformer
operator*(const Transformer&); // transformer multiplication
/* Transformation
routines */
virtual void Translate (real,real);
virtual void Scale (real,real);
virtual void Rotate (rotation,real);
virtual void Yshear (real);
virtual void Xshear (real);
virtual void ReflectX (void) {Scale( 1,-1);};
virtual void ReflectY (void) {Scale(-1, 1);};
virtual void ReflectXY (void) {Scale(-1,-1);};
/* To transform a
point according to the current transformation matrix */
void Transform(Point& pNew) {pNew = pNew * mTformer;};
protected:
Matrix mTformer;
// transformations Matrix
real
aX;
// y component of arbitrary Point of transformation
real
aY;
// x component of arbitrary Point of transformation
flag fLockedTformer;
// transformation execution lockout
};
#endif
GRAPHIC_OBJECT_CLASS.HPP
#ifndef __TFORMER_HPP
#include <TFORMER.HPP>
#endif
#ifndef __GRACLASS_HPP
#define __GRACLASS_HPP
/* The following was a last minute addition. The identifier name should be GraphicsPortTransformer and not WindowTransformer. It defines an array of transformers, one for each graphics port, limited to 4 at this point. This functionality allows a single graphic object to be viewed through different transformations without having to be transformed. One example would be the ability to simultaneously draw a single graphic object in several different rotations, say 4, without having to instantiate 4 separate instances, separately rotate each, and then individually draw them in separate graphics port. */
extern Transformer WindowTransformer[4];
class GraphicObjectClass : public
Transformer
{
friend class GraphicArray; // This friendship
is needed because GraphicArray redefines the Draw() function and
// needs access to the private members of GraphicObjectClass that are
used
to make
// Draw() function properly.
public:
GraphicObjectClass(void);
void DrawOn (void) {fDraw
= TRUE;}; // turns drawing of the graphic object on
void DrawOff(void) {fDraw
= FALSE;}; // turns drawing of the graphic object off
virtual void Draw(void);
// Draw is a wrapper function that draws the substance of a graphic
object. Its design is
// to remove the responsible of certain overhead from a developer,
mainly
the entering and
// exiting of space.
protected:
/* The following protected member functions
are used by the developer or library provider to create new graphic objects
having drawable substance. */
/* Here are the graphics primitives used to define the substance. These functions have dynamic functionality that reflects the current graphics port access setting. They also act as wrapper functions by calling a pointer to function variable type */
void SetDrawColor (int nC) {CDC = nC;};
void MoveTo (Point& p) {CGP = p;};
void MoveTo (real,real);
void PlotPoint (Point& p) {(*pfPoint)(*this,p);};
void PlotPoint (real,real);
void DrawLine (Point& pB,Point& pE)
{(*pfLine)(*this,pB,pE);};
void DrawLine (real,real,real,real);
void LineTo (Point& p) {(*pfLineTo)(*this,p);};
void LineTo (real,real);
void DrawPoly (int n,Point aPts[]) {(*pfDrawPoly)(*this,n,aPts);};
void FillPoly (int n,Point aPts[]) {(*pfFillPoly)(*this,n,aPts);};
/* this is where the graphics primitive calls are placed */
virtual void Substance(void) = 0;
private:
/* The following private data handles all the graphics overhead.
This overhead consists of the saving and restoring of graphics information,
and loading of the graphics primitive pointer functions. These pointer
to function variables contain the addresses of the current access set of
graphics primitives. This provides an excellent speed hit that would otherwise
be lost by having a single set of generic graphics primitives that check
for the current graphics port access setting. */
flag fDraw; // drawing execution lockout
/* Following is the graphics information that is saved and then restored upon execution of draw() */
static struct viewporttype viewinfo; // previous viewport info
static int tmpc; // previous color info
static int cx; // previous device
x-position
static int cy; // previous device
y-position
static flag fInitDP; // are drawing primitives
initialized
static access CAS; // current access
status
static int CDC;
// current drawing color
static Point CGP; // current
graphics position
static int iGP;
// graphics port index
/* The following variables are used to transform the point parameters of the graphics primitives. This allows the original setup coordinates (those point coordinates passed to the graphics primitives) to be retained; thus, not physically changed by transformation of the graphic object upon calculating actual coordinates. */
static Point pTmp; // transformations
static Point p1Tmp; // transformations
static Point p2Tmp; // transformations
/* Following are the pointer to function address variables. These point to the current graphics port access set of graphics primitives and are invoked by execution of the graphics primitive wrapper functions found in the private declaration section of this class definition. */
static void (*pfPoint)(const GraphicObjectClass&,const
Point&);
static void (*pfLine)(const GraphicObjectClass&,const
Point&,const Point&);
static void (*pfLineTo)(const GraphicObjectClass&,const
Point&);
static void (*pfDrawPoly)(const GraphicObjectClass&,int
n,Point aPts[]);
static void (*pfFillPoly)(const GraphicObjectClass&,int
n,Point aPts[]);
/* Following are the graphics port access sets of graphics primitives. Unlike the other static members of this class these functions absolutely have to be static. This is because C++ member functions have a different calling convention than normal C functions. In fact, because of name mangling normal C functions under C++ linkage also have a different calling convention. The name mangling uses strict type checking of formal arguments. Nevertheless, member functions use an implicit pointer which indicates the address of the object in which to perform the function. Thus, when taking the address of a member function you get the function address and not the objects address. Remember, the objects address is implied (built into the calling mechanism). */
/* these are the current access graphics port set of graphics primitives */
static void ActivePoint(const GraphicObjectClass&,const
Point&);
static void ActiveLine(const GraphicObjectClass&,const
Point&,const Point&);
static void ActiveLineTo(const GraphicObjectClass&,const
Point&);
static void ActiveDrawPoly(const GraphicObjectClass&,int
n,Point aPts[]);
static void ActiveFillPoly(const GraphicObjectClass&,int
n,Point aPts[]);
// current access set goes here
// display access set goes here
void EnterSpace (void); // save graphics information
void ExitSpace (void); // restore graphics
information
void LoadActiveDP(void); // load the correct
set of graphics primitives
};
#endif
GRAPHIC_OPBJECT.HPP
#ifndef __OBJECT_H
#include <OBJECT.H>
#endif
#ifndef __GRAPOBJE_HPP
#define __GRAPOBJE_HPP
class GraphicObject : virtual public
GraphicObjectClass,
public Object,
virtual private Extent
{
friend class GraphicArray; // This friendship
with GraphicArray is needed during attachments. During an attachment
// GraphicArray needs to check/update fAttached, goParent, and execute
// UpdateParentExtent().
public:
GraphicObject(Extent
&,char *str = "NO NAME");
virtual ~GraphicObject(void);
GraphicObject& YourParentPlease
(void) {return *goParent;};
char *YourNamePlease(void)
{return sName;};
flag IsAttached (void)
{return fAttached;};
void SetExtent (Extent&);
// this function needs some fixing up
virtual void Reset(void);
// this function is questionable --is it OK to reset an attached object.
/* At this point the transformation functions that where inherited from GraphicObjectClass must be redefined. This is because we are no longer just transforming the transformation matrix in Transformer. Now we must also transform and update the graphic object extent, and if attached to a parent graphic object then update its extent to reflect changes in the child’s extent. */
virtual void Translate
(real,real);
virtual void Scale (real,real);
virtual void Rotate
(rotation,real);
virtual void ReflectX
(void);
virtual void ReflectY
(void);
virtual void ReflectXY
(void);
virtual void Yshear
(real);
virtual void Xshear
(real);
/* The following functions where inherited from Extent. Because Extent was privately inherited these functions must be promoted to public access. I used private inheritance to keep users of GraphicObject types from accidentally changing the extent. If such a change was allowed then the extent would not properly reflect transformations of the graphic object. */
Extent::ExtentCenter;
Extent::ExtentCenterLeft;
Extent::ExtentCenterRight;
Extent::ExtentCenterTop;
Extent::ExtentCenterBot;
Extent::ExtentTopLeft;
Extent::ExtentTopRight;
Extent::ExtentBotLeft;
Extent::ExtentBotRight;
Extent::ExtentWidth;
Extent::ExtentHeight;
/* The following stuff was inherited from Borlands Object class, Its mostly stuff that I never planned to use. Nevertheless, several pure virtual functions had to be defined in order to remove the abstraction from Object. */
virtual classType isA() const {};