BUTTERFLY
Code
 
 

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. 
 

GRAPHICS_PORT_SYSTEM.HPP



/**************************************************************************
* File:    grahpics_port_system.hpp                                       *
* Author:  Walt Davis                                                     *
* Version: 3.04A                                                          *
*                                                                         *
* Description:                                                            *
*    For description click here.                                          *
***************************************************************************/
#include <graphics.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include "gpsys.hpp"

#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

 
GLOBAL.HPP



/**************************************************************************
* File:    globals.hpp                                                    *
* Author:  Walt Davis                                                     *
* Version: 3.04A                                                          *
*                                                                         *
* Description:                                                            *
*    For description click here.                                          *
***************************************************************************/
#include <GLOBAL.HPP>
#include <MATH.H>
#include <IOSTREAM.H>
#include <IOMANIP.H>

#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

 
TRANSFORMER.HPP



/**************************************************************************
* File:    transformer.hpp                                                *
* Author:  Walt Davis                                                     *
* Version: 3.04A                                                          *
*                                                                         *
* Description:                                                            *
*    For description click here.                                          *
***************************************************************************/
#ifndef __GLOBOL_HPP
    #include <GLOBAL.HPP>
#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



/**************************************************************************
* File:    graphic_object_class.hpp                                       *
* Author:  Walt Davis                                                     *
* Version: 3.04A                                                          *
*                                                                         *
* Description:                                                            *
*    For description click here.                                          *
***************************************************************************/
#ifndef __GLOBAL_HPP
    #include <GLOBAL.HPP>
#endif

#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



/**************************************************************************
* File:    graphic_object.hpp                                             *
* Author:  Walt Davis                                                     *
* Version: 3.04A                                                          *
*                                                                         *
* Description:                                                            *
*    For description click here.                                          *
***************************************************************************/
#ifndef __GRAPCLAS_HPP
    #include <GRAPCLAS.HPP>
#endif

#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 {};