home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / 3DTOSHI2.ZIP / mpgfx / source / gfxgraf.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  53.5 KB  |  2,171 lines

  1.  
  2. // gfxgraf.cpp
  3. //
  4. // Copyright (c) 1995 by Toshiaki Tsuji, all rights reserved.
  5.  
  6. #include "stdgfx.h"
  7. #include "gfxgraf.h"
  8. #include "lgfxdib.h"
  9. #include <math.h>
  10.  
  11. POLYGON::POLYGON ()
  12.   {
  13.     NumPoints = 0;
  14.     Points = NULL;  
  15.   }; // End of Constructor for POLYGON
  16.  
  17. POLYGON::~POLYGON ()
  18.   {
  19.     DestroyPoints ();  
  20.   }; // End of Destructor for POLYGON
  21.  
  22. VOID POLYGON::CreatePoints ( LONG Num )
  23.   {
  24.     DestroyPoints ();
  25.     Points = new XYPOINT [Num];
  26.     NumPoints = Num;  
  27.   }; // End of CreatePoints for POLYGON
  28.  
  29. VOID POLYGON::DestroyPoints ()
  30.   {
  31.     if (Points!=NULL)
  32.       delete Points;
  33.     Points = NULL;
  34.     NumPoints = 0;    
  35.   }; // End of DestroyPoints for POLYGON
  36.  
  37. EDGETABLE::EDGETABLE ()
  38.   {
  39.   } // End of Constructor for EDGETABLE
  40.  
  41. EDGETABLE::~EDGETABLE ()
  42.   {
  43.   } // End of Destructor for EDGETABLE
  44.  
  45. //*************************************************
  46. //
  47. // Graphics Class
  48. //
  49. //*************************************************
  50.  
  51. POLYGON *Poly1 = NULL;
  52. POLYGON *Poly2 = NULL;
  53. XYPOINT *Left = NULL;
  54. XYPOINT *Right = NULL;
  55.  
  56. GRAFIX Grafix;
  57.  
  58. GRAFIX::GRAFIX () : DCIClass ()
  59.   {
  60.     Init ();
  61.     MagH = MagV = DivH = DivV = 1;
  62.     Poly1->CreatePoints ( 50 );
  63.     Poly2->CreatePoints ( 50 );
  64.   } // End of Constructor for GRAFIX
  65.  
  66. GRAFIX::~GRAFIX ()
  67.   {
  68.     DeInit ();
  69.   } // End of Destructor for GRAFIX
  70.  
  71. BOOLEAN GRAFIX::Init ()
  72.   {
  73.     DisplayDriver = NULL;
  74.     Poly1 = new POLYGON ();
  75.     Poly2 = new POLYGON ();
  76.     Left = new XYPOINT [768];
  77.     Right = new XYPOINT [768];
  78.  
  79.     return TRUE;
  80.   } // End of Init for GRAFIX
  81.  
  82. VOID GRAFIX::DeInit ()
  83.   {
  84.     if (DisplayDriver!=NULL)
  85.       delete DisplayDriver;
  86.     DisplayDriver = NULL;
  87.  
  88.     if (Poly1!=NULL)
  89.       delete Poly1;
  90.     Poly1 = NULL;
  91.  
  92.     if (Poly2!=NULL)
  93.       delete Poly2;
  94.     Poly2 = NULL;
  95.  
  96.     if (Left!=NULL)
  97.       delete Left;
  98.     Left = NULL;
  99.  
  100.     if (Right!=NULL)
  101.       delete Right;
  102.     Right = NULL;
  103.   } // End of DeInit for GRAFIX
  104.  
  105. BOOLEAN GRAFIX::SetDisplay ( DISPLAYDATA *Data )
  106.   {
  107.     BOOLEAN Result;
  108.     if (Data==NULL)
  109.       {
  110.         return FAILURE;  
  111.       } // End if
  112.     if (DisplayDriver!=NULL)
  113.       {
  114.         delete DisplayDriver;
  115.         DisplayDriver = NULL;  
  116.       } // End if
  117.       
  118.     #if defined (__FORWINDOWS__)
  119.       #if defined (__FORGDK__)
  120.         if (Data->UseDirectDraw)
  121.           DisplayDriver = new DDRAWDRIVER ();
  122.         else  
  123.           DisplayDriver = new GDIDRIVER ();
  124.       #else    
  125.         DisplayDriver = new GDIDRIVER ();        
  126.       #endif
  127.       
  128.       if (DisplayDriver==NULL)
  129.         {
  130.           Error.SetError ( ERR_NOMEMORY );
  131.           return FAILURE;
  132.         } // End if
  133.       Result = DisplayDriver->SetUp ( Data );
  134.       return Result;
  135.     #elif defined (__FOROS2__)
  136.       DisplayDriver = new GPIDRIVER ();
  137.       if (DisplayDriver==NULL)
  138.         {
  139.           Error.SetError ( ERR_NOMEMORY );
  140.           return FAILURE;
  141.         } // End if
  142.       Result = DisplayDriver->SetUp ( Data );
  143.       return Result;
  144.     #elif defined (__FORDOS__)
  145.       MODEINFO ModeInfo;
  146.  
  147.       ModeInfo = ModeTable[Data->Mode];
  148.       if (ModeInfo.IsSVGA==TRUE)
  149.         {
  150.           DisplayDriver = new VESADRIVER ();
  151.           if (DisplayDriver==NULL)
  152.             {
  153.               Error.SetError ( ERR_NOMEMORY );
  154.               return FAILURE;
  155.             } // End if
  156.           Result = DisplayDriver->SetUp ( Data );
  157.         } // End if
  158.       else
  159.         {
  160.           DisplayDriver = new VGADRIVER ();
  161.           if (DisplayDriver==NULL)
  162.             {
  163.               Error.SetError ( ERR_NOMEMORY );
  164.               return FAILURE;
  165.             } // End if
  166.           Result = DisplayDriver->SetUp ( Data );
  167.         } // End else
  168.       return Result;
  169.     #elif defined (__FORUNIX__)
  170.       DisplayDriver = new XWINDRIVER ();
  171.       if (DisplayDriver==NULL)
  172.         {
  173.           Error.SetError ( ERR_NOMEMORY );
  174.           return FAILURE;
  175.         } // End if
  176.       Result = DisplayDriver->SetUp ( Data );
  177.       return Result;
  178.     #endif    
  179.   } // End of SetDisplay for GRAFIX
  180.  
  181. VOID GRAFIX::ResetDisplay ()
  182.   {
  183.     if (DisplayDriver==NULL)
  184.       return;
  185.  
  186.     DisplayDriver->Reset ();
  187.   } // End of ResetDisplay for GRAFIX
  188.  
  189. VOID GRAFIX::SetScaleFactor ( LONG MH, LONG DH, LONG MV, LONG DV )
  190.   {
  191.     if (MH>=0)  
  192.       MagH = MH;
  193.     else
  194.       MagH = 1;      
  195.     if (DH>=0)  
  196.       DivH = DH;
  197.     else
  198.       DivH = 1;
  199.  
  200.     if (MV>=0)  
  201.       MagV = MV;
  202.     else
  203.       MagV = 1;      
  204.     if (DV>=0)  
  205.       DivV = DV;
  206.     else
  207.       DivV = 1;  
  208.       
  209.     if (DisplayDriver!=NULL)
  210.       DisplayDriver->SetScaleFactor ( MagH, DivH, MagV, DivV );
  211.   } // End of SetScaleFactor for GRAFIX
  212.   
  213. VOID GRAFIX::ClearDisplay ( HDISPLAY hDisplay, LONG Color )
  214.   {
  215.     if (DisplayDriver==NULL)
  216.       return;
  217.  
  218.     DisplayDriver->Clear ( hDisplay, Color );
  219.   } // End of ClearDisplay for GRAFIX
  220.  
  221. VOID GRAFIX::WaitForRetrace ( LONG Count )
  222.   {      
  223.     #if defined (__FORDOS__)
  224.       WaitForRetraceMany ( Count );
  225.     #else
  226.       if (Count)
  227.         {}
  228.     #endif  
  229.   } // End of WaitForRetrace for GRAFIX
  230.  
  231. VOID GRAFIX::WaitForRetrace ()
  232.   {
  233.     #if defined (__FORDOS__)
  234.       WaitForRetraceOnce ();
  235.     #endif  
  236.   } // End of WaitForRetrace for GRAFIX
  237.  
  238. VOID GRAFIX::WaitForRetraceEnd ()
  239.   {
  240.     #if defined (__FORDOS__)
  241.       WaitForRetraceTerminate ();
  242.     #endif  
  243.   } // End of WaitForRetrace for GRAFIX
  244.  
  245. VOID GRAFIX::CopyImage ( IMAGE *Src, LONG Sx, LONG Sy, LONG Wd, LONG Ht,
  246.                          IMAGE *Dest, LONG Cx, LONG Cy )
  247.   {
  248.     if ((Src==NULL)||(Dest==NULL))
  249.       return;
  250.  
  251.     if ((Wd==0)||(Ht==0))
  252.       return;
  253.     
  254.     RECTANGLE ViewPort;
  255.     ViewPort.x1 = 0;
  256.     ViewPort.y1 = 0;
  257.     ViewPort.x2 = Src->GetWidth()-1;
  258.     ViewPort.y2 = Src->GetHeight()-1;
  259.  
  260.     if (ClipRect ( &ViewPort, &Sx, &Sy, &Wd, &Ht )==FALSE)
  261.       return;
  262.  
  263.     ViewPort = Dest->GetViewPort ();
  264.     if (ClipDest ( &ViewPort, &Sx, &Sy, &Wd, &Ht, &Cx, &Cy )==FALSE)
  265.       return;
  266.  
  267.     INT i;
  268.  
  269.     BYTE *SrcBuffer;
  270.     BYTE *DestBuffer;
  271.  
  272.     SrcBuffer = Src->SetOffset ( Sx, Sy );
  273.     DestBuffer = Dest->SetOffset ( Cx, Cy );
  274.  
  275.     if (Src->Transparent<0)
  276.       {
  277.         for (i=0;i<Ht;i++)
  278.           {
  279.             memcpy ( DestBuffer, SrcBuffer, Wd );
  280.             SrcBuffer = Src->GetNextRow ( ROW_DOWN );
  281.             DestBuffer = Dest->GetNextRow ( ROW_DOWN );
  282.           } // End for
  283.       } // End if
  284.     else
  285.       {
  286.         for (i=0;i<Ht;i++)
  287.           {
  288.             TransBlt256To256 ( DestBuffer, SrcBuffer, Wd, (BYTE)Src->Transparent );
  289.             SrcBuffer = Src->GetNextRow ( ROW_DOWN );
  290.             DestBuffer = Dest->GetNextRow ( ROW_DOWN );
  291.           } // End for
  292.       } // End else
  293.   } // End of CopyImage for GRAFIX
  294.  
  295. VOID GRAFIX::ScaleImage ( IMAGE *Src, LONG Sx, LONG Sy, LONG Wd, LONG Ht,
  296.                           IMAGE *Dest, LONG Cx, LONG Cy )
  297.   {
  298.     if ((Src==NULL)||(Dest==NULL))
  299.       return;
  300.  
  301.     if ((Wd==0)||(Ht==0))
  302.       return;
  303.       
  304.     RECTANGLE ViewPort;
  305.     LONG DWd,DHt;
  306.  
  307.     ViewPort.x1 = 0;
  308.     ViewPort.y1 = 0;
  309.     ViewPort.x2 = Src->GetWidth()-1;
  310.     ViewPort.y2 = Src->GetHeight()-1;
  311.  
  312.     if (ClipRect ( &ViewPort, &Sx, &Sy, &Wd, &Ht )==FALSE)
  313.       return;
  314.  
  315.     DWd = (MagH*Wd)/DivH;
  316.     DHt = (MagV*Ht)/DivV;
  317.     
  318.     ViewPort = Dest->GetViewPort ();
  319.     if (ClipDest ( &ViewPort, &Sx, &Sy, &DWd, &DHt, &Cx, &Cy )==FALSE)
  320.       return;
  321.  
  322.     INT i;
  323.  
  324.     BYTE *SrcBuffer;
  325.     BYTE *DestBuffer;
  326.  
  327.     SrcBuffer = Src->SetOffset ( Sx, Sy );
  328.     DestBuffer = Dest->SetOffset ( Cx, Cy );
  329.  
  330.     WORD Error = 0;
  331.     DWORD AddError = (((LONG)DivH<<16)/MagH);
  332.  
  333.     if (Src->Transparent<0)
  334.       {
  335.         for (i=0;i<DHt;i++)
  336.           {
  337.             ScaleBlt256To256 ( DestBuffer, SrcBuffer, DWd, Error, AddError );
  338.             SrcBuffer = Src->SetOffset ( Sx, Sy+(i*DivV)/MagV );
  339.             DestBuffer = Dest->GetNextRow ( ROW_DOWN );
  340.           } // End for
  341.       } // End if
  342.     else
  343.       {
  344.         for (i=0;i<DHt;i++)
  345.           {
  346.             TransBlt256To256 ( DestBuffer, SrcBuffer, Wd, (BYTE)Src->Transparent );
  347.             SrcBuffer = Src->GetNextRow ( ROW_DOWN );
  348.             DestBuffer = Dest->GetNextRow ( ROW_DOWN );
  349.           } // End for
  350.       } // End else
  351.   } // End of ScaleImage for GRAFIX
  352.                             
  353. VOID GRAFIX::AdjustImageSize ( IMAGE *Image, LONG Wd, LONG Ht )
  354.   {
  355.     IMAGE *TempImage;
  356.  
  357.     if ((Image->GetWidth()==Wd)&&(Image->GetHeight()==Ht))
  358.       return;
  359.       
  360.     SetScaleFactor ( 1, 1, 1, 1 );
  361.     TempImage = new IMAGE ( Image->GetDirection () );
  362.     if (TempImage->Create ( Image->GetFormat (), Image->GetWidth(), Image->GetHeight() )==FAILURE)
  363.       {
  364.         delete TempImage;  
  365.         return;
  366.       } // End if  
  367.  
  368.     CopyImage ( Image, 0, 0, Image->GetWidth(), Image->GetHeight(),
  369.                 TempImage, 0, 0 );
  370.  
  371.     if (Image->Create ( TempImage->GetFormat(), Wd, Ht )==FAILURE)
  372.       {
  373.         delete TempImage;
  374.         return;  
  375.       } // End if
  376.       
  377.     SetScaleFactor ( Wd, TempImage->GetWidth(), Ht, TempImage->GetHeight() );
  378.     ScaleImage ( TempImage, 0, 0, TempImage->GetWidth(), TempImage->GetHeight(),
  379.                  Image, 0, 0 ); 
  380.     SetScaleFactor ( 1, 1, 1, 1 );
  381.     delete TempImage;
  382.   } // End of AdjustImageSize for GRAFIX
  383.  
  384. VOID GRAFIX::DisplayImage ( HDISPLAY hDisplay, IMAGE *Image, LONG Sx, LONG Sy,
  385.                             LONG Wd, LONG Ht, LONG Cx, LONG Cy )
  386.   {
  387.     if (DisplayDriver==NULL)
  388.       return;
  389.  
  390.     if ((Wd==0)||(Ht==0))
  391.       return;
  392.       
  393.     RECTANGLE ViewPort;
  394.     LONG DWd,DHt;
  395.  
  396.     ViewPort.x1 = 0;
  397.     ViewPort.y1 = 0;
  398.     ViewPort.x2 = Image->GetWidth()-1;
  399.     ViewPort.y2 = Image->GetHeight()-1;
  400.     if (ClipRect ( &ViewPort, &Sx, &Sy, &Wd, &Ht )==FALSE)
  401.       return;
  402.  
  403.     DWd = (MagH*Wd)/DivH;
  404.     DHt = (MagV*Ht)/DivV;
  405.  
  406.     ViewPort.x1 = 0;
  407.     ViewPort.y1 = 0;
  408.     ViewPort.x2 = DisplayDriver->GetWidth ( hDisplay );
  409.     ViewPort.y2 = DisplayDriver->GetHeight ( hDisplay );
  410.  
  411.     if (ClipDest ( &ViewPort, &Sx, &Sy, &DWd, &DHt, &Cx, &Cy )==FALSE)
  412.       return;
  413.  
  414.     DisplayDriver->DisplayImage ( Image, Sx, Sy, Wd, Ht, hDisplay, Cx, Cy, DWd, DHt );
  415.   } // End of DisplayImage for GRAFIX
  416.  
  417. INT GRAFIX::GetImageFileType ( FILEHANDLE f )
  418.   {
  419.     CHAR Ch;
  420.     CHAR ID[8];
  421.  
  422.     // Check for PCX
  423.     File.Seek ( f, 0, FROM_BEGIN );
  424.     Ch = (CHAR)File.GetCh ( f );
  425.     if (Ch==0x0A)
  426.       {
  427.         return PCXFILE;
  428.       } // End if
  429.  
  430.     // Check for BMP
  431.     File.Seek ( f, 0, FROM_BEGIN );
  432.     File.Read ( f, ID, 2 );
  433.     if (strncmp(ID,"BM",2)==0)
  434.       {
  435.         return BMPFILE;
  436.       } // End if
  437.  
  438.     // Check for GIF
  439.     File.Seek ( f, 0, FROM_BEGIN );
  440.     File.Read ( f, ID, 3 );
  441.     if (strncmp(ID,"GIF",3)==0)
  442.       {
  443.         File.Read ( f, ID, 3 );
  444.         if ((strncmp(ID,"87a",3)==0)||(strncmp(ID,"89a",3)==0))
  445.           {
  446.             return GIFFILE;
  447.           } // End if
  448.       } // End if
  449.  
  450.     return UNKNOWN;
  451.   } // End of GetImageFileType for GRAFIX
  452.  
  453. BOOLEAN GRAFIX::ClipRect ( RECTANGLE *ViewPort, LONG *Sx, LONG *Sy, LONG *Wd, LONG *Ht )
  454.   {
  455.     LONG StartX,StartY,EndX,EndY;
  456.  
  457.     StartX = *Sx;
  458.     StartY = *Sy;
  459.     EndX = *Sx+*Wd-1;
  460.     EndY = *Sy+*Ht-1;
  461.  
  462.     if (StartX<ViewPort->x1)
  463.       StartX = ViewPort->x1;
  464.     else if (StartX>ViewPort->x2)
  465.       return FAILURE;
  466.  
  467.     if (StartY<ViewPort->y1)
  468.       StartY = ViewPort->y1;
  469.     else if (StartY>ViewPort->y2)
  470.       return FAILURE;
  471.  
  472.     if (EndX<ViewPort->x1)
  473.       return FAILURE;
  474.     else if (EndX>ViewPort->x2)
  475.       EndX = ViewPort->x2;
  476.  
  477.     if (EndY<ViewPort->y1)
  478.       return FAILURE;
  479.     else if (EndY>ViewPort->y2)
  480.       EndY = ViewPort->y2;
  481.  
  482.     *Wd = EndX-StartX+1;
  483.     *Ht = EndY-StartY+1;
  484.     *Sx = StartX;
  485.     *Sy = StartY;
  486.  
  487.     return SUCCESS;
  488.   } // End of ClipRect for GRAFIX
  489.  
  490. BOOLEAN GRAFIX::ClipDest ( RECTANGLE *ViewPort, LONG *Sx, LONG *Sy, LONG *Wd, LONG *Ht,
  491.                            LONG *Cx, LONG *Cy )
  492.   {
  493.     LONG StartX,StartY,EndX,EndY;
  494.  
  495.     StartX = *Cx;
  496.     StartY = *Cy;
  497.     EndX = *Cx+*Wd-1;
  498.     EndY = *Cy+*Ht-1;
  499.  
  500.     if (StartX<ViewPort->x1)
  501.       StartX = ViewPort->x1;
  502.     else if (StartX>ViewPort->x2)
  503.       return FAILURE;
  504.  
  505.     if (StartY<ViewPort->y1)
  506.       StartY = ViewPort->y1;
  507.     else if (StartY>ViewPort->y2)
  508.       return FAILURE;
  509.  
  510.     if (EndX<ViewPort->x1)
  511.       return FAILURE;
  512.     else if (EndX>ViewPort->x2)
  513.       EndX = ViewPort->x2;
  514.  
  515.     if (EndY<ViewPort->y1)
  516.       return FAILURE;
  517.     else if (EndY>ViewPort->y2)
  518.       EndY = ViewPort->y2;
  519.  
  520.     *Wd = EndX-StartX+1;
  521.     *Ht = EndY-StartY+1;
  522.     *Sx += StartX-*Cx;
  523.     *Sy += StartY-*Cy;
  524.     *Cx = StartX;
  525.     *Cy = StartY;
  526.  
  527.     return SUCCESS;
  528.   } // End of ClipDest for GRAFIX
  529.  
  530. VOID GRAFIX::FindIntersect ( XYPOINT *In, XYPOINT *Out, XYPOINT *I,
  531.                              RECTANGLE ViewPort, LONG Code )
  532.   {
  533.     double Ratio;
  534.     switch (Code)
  535.       {
  536.         case 0 : // Top  
  537.           Ratio = (double)(ViewPort.y1-Out->y)/(In->y-Out->y);
  538.           I->x = (LONG)((In->x-Out->x)*Ratio + Out->x);
  539.           I->y = ViewPort.y1;
  540.           break;
  541.         case 1 : // Left
  542.           Ratio = (double)(ViewPort.x1-Out->x)/(In->x-Out->x);
  543.           I->x = ViewPort.x1;
  544.           I->y = (LONG)((In->y-Out->y)*Ratio + Out->y);
  545.           break;
  546.         case 2 : // Bottom  
  547.           Ratio = (double)(ViewPort.y2-Out->y)/(In->y-Out->y);
  548.           I->x = (LONG)((In->x-Out->x)*Ratio + Out->x);
  549.           I->y = ViewPort.y2;
  550.           break;
  551.         case 3 : // Right
  552.           Ratio = (double)(ViewPort.x2-Out->x)/(In->x-Out->x);
  553.           I->x = ViewPort.x2;
  554.           I->y = (LONG)((In->y-Out->y)*Ratio + Out->y);
  555.           break;
  556.       } // End if
  557.     I->u = (LONG)((In->u-Out->u)*Ratio + Out->u);  
  558.     I->v = (LONG)((In->v-Out->v)*Ratio + Out->v);  
  559.   } // End of FindIntersect for GRAFIX
  560.                                
  561. VOID GRAFIX::ClipPolygon ( POLYGON *SrcPoly, POLYGON *ClipPoly,
  562.                            RECTANGLE ViewPort )
  563.   {
  564.     LONG NumPoints;
  565.     LONG Count;
  566.     LONG i;
  567.     XYPOINT P1,P2,I;    
  568.     
  569.     // Clip for Top
  570.     NumPoints = SrcPoly->NumPoints;
  571.     Count = 0;
  572.     
  573.     P1 = SrcPoly->Points[NumPoints-1];
  574.     for (i=0;i<NumPoints;i++)
  575.       {
  576.         P2 = SrcPoly->Points[i];
  577.         if (P1.y>=ViewPort.y1)
  578.           {
  579.             if (P2.y>=ViewPort.y1)
  580.               {
  581.                 Poly1->Points[Count++] = P2;  
  582.               } // End if
  583.             else
  584.               {
  585.                 FindIntersect ( &P1, &P2, &I, ViewPort, 0 );
  586.                 Poly1->Points[Count++] = I;  
  587.               } // End else  
  588.           } // End if
  589.         else
  590.           {
  591.             if (P2.y>=ViewPort.y1)
  592.               {
  593.                 FindIntersect ( &P2, &P1, &I, ViewPort, 0 );
  594.                 Poly1->Points[Count++] = I;  
  595.                 Poly1->Points[Count++] = P2;  
  596.               } // End if
  597.           } // End if
  598.         P1 = P2;  
  599.       } // End for
  600.     
  601.     // Clip for Left
  602.     NumPoints = Count;
  603.     Count = 0;
  604.     
  605.     P1 = Poly1->Points[NumPoints-1];
  606.     for (i=0;i<NumPoints;i++)
  607.       {
  608.         P2 = Poly1->Points[i];
  609.         if (P1.x>=ViewPort.x1)
  610.           {
  611.             if (P2.x>=ViewPort.x1)
  612.               {
  613.                 Poly2->Points[Count++] = P2;  
  614.               } // End if
  615.             else
  616.               {
  617.                 FindIntersect ( &P1, &P2, &I, ViewPort, 1 );
  618.                 Poly2->Points[Count++] = I;  
  619.               } // End else  
  620.           } // End if
  621.         else
  622.           {
  623.             if (P2.x>=ViewPort.x1)
  624.               {
  625.                 FindIntersect ( &P2, &P1, &I, ViewPort, 1 );
  626.                 Poly2->Points[Count++] = I;  
  627.                 Poly2->Points[Count++] = P2;  
  628.               } // End if
  629.           } // End if
  630.         P1 = P2;  
  631.       } // End for
  632.       
  633.     // Clip for Bottom
  634.     NumPoints = Count;
  635.     Count = 0;
  636.     
  637.     P1 = Poly2->Points[NumPoints-1];
  638.     for (i=0;i<NumPoints;i++)
  639.       {
  640.         P2 = Poly2->Points[i];
  641.         if (P1.y<=ViewPort.y2)
  642.           {
  643.             if (P2.y<=ViewPort.y2)
  644.               {
  645.                 Poly1->Points[Count++] = P2;  
  646.               } // End if
  647.             else
  648.               {
  649.                 FindIntersect ( &P1, &P2, &I, ViewPort, 2 );
  650.                 Poly1->Points[Count++] = I;  
  651.               } // End else  
  652.           } // End if
  653.         else
  654.           {
  655.             if (P2.y<=ViewPort.y2)
  656.               {
  657.                 FindIntersect ( &P2, &P1, &I, ViewPort, 2 );
  658.                 Poly1->Points[Count++] = I;  
  659.                 Poly1->Points[Count++] = P2;  
  660.               } // End if
  661.           } // End if
  662.         P1 = P2;  
  663.       } // End for
  664.       
  665.     // Clip for Right
  666.     NumPoints = Count;
  667.     Count = 0;
  668.     
  669.     P1 = Poly1->Points[NumPoints-1];
  670.     for (i=0;i<NumPoints;i++)
  671.       {
  672.         P2 = Poly1->Points[i];
  673.         if (P1.x<=ViewPort.x2)
  674.           {
  675.             if (P2.x<=ViewPort.x2)
  676.               {
  677.                 Poly2->Points[Count++] = P2;  
  678.               } // End if
  679.             else
  680.               {
  681.                 FindIntersect ( &P1, &P2, &I, ViewPort, 3 );
  682.                 Poly2->Points[Count++] = I;  
  683.               } // End else  
  684.           } // End if
  685.         else
  686.           {
  687.             if (P2.x<=ViewPort.x2)
  688.               {
  689.                 FindIntersect ( &P2, &P1, &I, ViewPort, 3 );
  690.                 Poly2->Points[Count++] = I;  
  691.                 Poly2->Points[Count++] = P2;  
  692.               } // End if
  693.           } // End if
  694.         P1 = P2;  
  695.       } // End for
  696.  
  697.     NumPoints = Count;
  698.     
  699.     ClipPoly->CreatePoints ( NumPoints );
  700.     for (i=0;i<NumPoints;i++)
  701.       {
  702.         ClipPoly->Points[i] = Poly2->Points[i];  
  703.       } // End for        
  704.   } // End of ClipPolygon for GRAFIX
  705.  
  706. VOID GRAFIX::DrawPolygon ( IMAGE *Dest, POLYGON *Poly )
  707.   {
  708.     INT i;
  709.     for (i=0;i<Poly->NumPoints-2;i++)
  710.       {
  711.         DrawLine ( Dest, Poly->Points[i].x, Poly->Points[i].y,
  712.                    Poly->Points[i+1].x, Poly->Points[i+1].y );
  713.       } // End for
  714.       
  715.     DrawLine ( Dest, Poly->Points[i].x, Poly->Points[i].y,
  716.                Poly->Points[0].x, Poly->Points[0].y );
  717.   } // End of DrawPolygon for GRAFIX
  718.  
  719. VOID GRAFIX::CreateEdgeTable ( POLYGON *Poly, EDGETABLE *EdgeTable )
  720.   {
  721.     INT i;
  722.     LONG Hi,HiP,Lo,LoP;
  723.     LONG NumPoints;
  724.     XYPOINT *Points;
  725.     
  726.     Points = Poly->Points;
  727.  
  728.     HiP = LoP = 0;
  729.     Hi = Lo = Points[0].y;
  730.     
  731.     NumPoints = Poly->NumPoints;
  732.     
  733.     for (i=1;i<NumPoints;i++)
  734.       {
  735.         if (Hi>Points[i].y)
  736.           {
  737.             Hi = Points[i].y;
  738.             HiP = i;
  739.           } // End if  
  740.         else if (Lo<Points[i].y)
  741.           {
  742.             Lo = Points[i].y;
  743.             LoP = i;
  744.           } // End if  
  745.       } // End for
  746.  
  747.     LONG CurP,NextP;
  748.     XYPOINT *Edge1,*Edge2;
  749.  
  750.     EdgeTable->Top = Hi;
  751.     EdgeTable->Height = Lo-Hi+1;
  752.     Edge1 = Left;
  753.     Edge2 = Right;
  754.  
  755.     LONG Sx,Ex;
  756.     LONG Sy,Ey;
  757.     LONG Su,Eu;
  758.     LONG Sv,Ev;
  759.     LONG Row;
  760.     double CurX;
  761.     double CurU,CurV;
  762.     double Slope;
  763.     double Du,Dv;
  764.     
  765.     // Get Counter Clockwise edges
  766.     CurP = HiP;
  767.     NextP = CurP-1;
  768.     if (NextP<0)
  769.       NextP = NumPoints-1;
  770.  
  771.     Row = 0;  
  772.     while (Row<EdgeTable->Height)
  773.       {
  774.         Sx = Points[CurP].x;  
  775.         Sy = Points[CurP].y;  
  776.         Ex = Points[NextP].x;  
  777.         Ey = Points[NextP].y;
  778.         Su = Points[CurP].u;  
  779.         Sv = Points[CurP].v;  
  780.         Eu = Points[NextP].u;  
  781.         Ev = Points[NextP].v;
  782.         
  783.         if ((Sx==Ex)&&(Sy==Ey))
  784.           {
  785.             CurP = NextP;
  786.             if (CurP==LoP)
  787.               break;
  788.             NextP = CurP-1;
  789.             if (NextP<0)
  790.               NextP = NumPoints-1;          
  791.             continue;
  792.           } // End if
  793.  
  794.         double Ratio;
  795.         Ratio = (double)1/(Ey-Sy+1);
  796.         Slope = (double)(Ex-Sx)*Ratio;
  797.         Du = (double)(Eu-Su)*Ratio;
  798.         Dv = (double)(Ev-Sv)*Ratio;
  799.         CurX = Sx;
  800.         CurU = Su;
  801.         CurV = Sv;
  802.         for (i=0;i<(Ey-Sy+1);i++)
  803.           {
  804.             CurX += Slope;
  805.             CurU += Du;
  806.             CurV += Dv;
  807.             Edge1[Row].x = (LONG)CurX;
  808.             Edge1[Row].u = (LONG)CurU;
  809.             Edge1[Row++].v = (LONG)CurV;
  810.           } // End for
  811.         CurP = NextP;
  812.         NextP = CurP-1;
  813.         if (NextP<0)
  814.           NextP = NumPoints-1;          
  815.       } // End while
  816.  
  817.     if (Row<EdgeTable->Height)
  818.       EdgeTable->Height = Row;
  819.     
  820.     // Get Clockwise edges
  821.     CurP = HiP;
  822.     NextP = CurP+1;
  823.     if (NextP>=NumPoints)
  824.       NextP = 0;
  825.  
  826.     Row = 0;  
  827.     while (Row<EdgeTable->Height)
  828.       {
  829.         Sx = Points[CurP].x;  
  830.         Sy = Points[CurP].y;  
  831.         Ex = Points[NextP].x;  
  832.         Ey = Points[NextP].y;
  833.         Su = Points[CurP].u;  
  834.         Sv = Points[CurP].v;  
  835.         Eu = Points[NextP].u;  
  836.         Ev = Points[NextP].v;
  837.         
  838.         if ((Sx==Ex)&&(Sy==Ey))
  839.           {
  840.             CurP = NextP;
  841.             if (CurP==LoP)
  842.               break;
  843.             NextP = CurP+1;
  844.             if (NextP>=NumPoints)
  845.               NextP = 0;          
  846.             continue;
  847.           } // End if
  848.  
  849.         double Ratio;
  850.         Ratio = (double)1/(Ey-Sy+1);
  851.         Slope = (double)(Ex-Sx)*Ratio;
  852.         Du = (double)(Eu-Su)*Ratio;
  853.         Dv = (double)(Ev-Sv)*Ratio;
  854.         CurX = Sx;
  855.         CurU = Su;
  856.         CurV = Sv;
  857.         
  858.         for (i=0;i<(Ey-Sy+1);i++)
  859.           {
  860.             CurX += Slope;
  861.             CurU += Du;
  862.             CurV += Dv;
  863.             Edge2[Row].x = (LONG)CurX;
  864.             Edge2[Row].u = (LONG)CurU;
  865.             Edge2[Row++].v = (LONG)CurV;
  866.           } // End for
  867.         CurP = NextP;
  868.         NextP = CurP+1;
  869.         if (NextP>=NumPoints)
  870.           NextP = 0;          
  871.       } // End while
  872.  
  873.     if (Row<EdgeTable->Height)
  874.       EdgeTable->Height = Row;
  875.     
  876.     // Determine which one is right or left
  877.     for (i=0;i<EdgeTable->Height;i++)
  878.       {
  879.         if (Edge1[i].x>Edge2[i].x)
  880.           {
  881.             SwapValue ( &Edge1, &Edge2 );
  882.             break;  
  883.           } // End if
  884.         else if (Edge1[i].x<Edge2[i].x)
  885.           break;
  886.       } // End for
  887.  
  888.     EdgeTable->Left = Edge1;  
  889.     EdgeTable->Right = Edge2;
  890.   } // End of CreateEdgeTable for GRAFIX
  891.   
  892. VOID GRAFIX::FillPolygon ( IMAGE *Dest, POLYGON *Poly )
  893.   {
  894.     RECTANGLE ViewPort;
  895.     POLYGON *ClipPoly;
  896.     EDGETABLE *EdgeTable;
  897.  
  898.     EdgeTable = new EDGETABLE ();    
  899.     ClipPoly = new POLYGON ();
  900.     ViewPort = Dest->GetViewPort ();
  901.     ClipPolygon ( Poly, ClipPoly, ViewPort );
  902.     
  903.     if (ClipPoly->NumPoints>2)
  904.       {
  905.         CreateEdgeTable ( ClipPoly, EdgeTable );
  906.         LONG i;
  907.         LONG x1,x2;
  908.         LONG Wd;
  909.         BYTE *DestOffset;
  910.         DestOffset = Dest->SetOffset ( 0, EdgeTable->Top );
  911.         for (i=0;i<EdgeTable->Height;i++)
  912.           {
  913.             x1 = EdgeTable->Left[i].x;  
  914.             x2 = EdgeTable->Right[i].x;
  915.             Wd = x2-x1+1;
  916.             memset ( DestOffset+x1, BGColor, Wd );
  917.             DestOffset = Dest->GetNextRow ( ROW_DOWN );
  918.           } // End for
  919.       } // End if
  920.       
  921.     delete EdgeTable;
  922.     delete ClipPoly;
  923.   } // End of FillPolygon for GRAFIX
  924.  
  925. VOID GRAFIX::RotateImage ( IMAGE *Src, LONG Sx, LONG Sy, LONG Wd, LONG Ht,
  926.                            LONG CenterX, LONG CenterY, float Angle,
  927.                            IMAGE *Dest, LONG Cx, LONG Cy )
  928.   {
  929.     if ((Src==NULL)||(Dest==NULL))
  930.       return;
  931.  
  932.     if ((Wd==0)||(Ht==0))
  933.       return;
  934.       
  935.     RECTANGLE ViewPort;
  936.  
  937.     ViewPort.x1 = 0;
  938.     ViewPort.y1 = 0;
  939.     ViewPort.x2 = Src->GetWidth()-1;
  940.     ViewPort.y2 = Src->GetHeight()-1;
  941.  
  942.     if (ClipRect ( &ViewPort, &Sx, &Sy, &Wd, &Ht )==FALSE)
  943.       return;
  944.  
  945.     POLYGON *Poly,*ClipPoly;
  946.     
  947.     Poly = new POLYGON ();
  948.     ClipPoly = new POLYGON ();
  949.  
  950.     double Sz,Cz;
  951.     Angle = (float)((Angle*6.281) / 360);
  952.     Sz = sin ( Angle );
  953.     Cz = cos ( Angle );
  954.  
  955.     double ScaleX,ScaleY;
  956.  
  957.     ScaleX = (double)MagH/DivH;
  958.     ScaleY = (double)MagV/DivV;
  959.         
  960.     Poly->CreatePoints ( 4 );
  961.     Poly->Points[0].x = Sx-CenterX; Poly->Points[0].y = Sy-CenterY;
  962.     Poly->Points[1].x = Sx-CenterX; Poly->Points[1].y = Sy-CenterY+Ht;
  963.     Poly->Points[2].x = Sx-CenterX+Wd; Poly->Points[2].y = Sy-CenterY+Ht;
  964.     Poly->Points[3].x = Sx-CenterX+Wd; Poly->Points[3].y = Sy-CenterY;
  965.  
  966.     Poly->Points[0].u = Sx<<16; Poly->Points[0].v = Sy<<16;    
  967.     Poly->Points[1].u = Sx<<16; Poly->Points[1].v = (Sy+Ht-1)<<16;    
  968.     Poly->Points[2].u = (Sx+Wd-1)<<16; Poly->Points[2].v = (Sy+Ht-1)<<16;    
  969.     Poly->Points[3].u = (Sx+Wd-1)<<16; Poly->Points[3].v = Sy<<16;
  970.  
  971.     LONG x,y;
  972.     INT i;
  973.     for (i=0;i<4;i++)
  974.       {
  975.         x = (LONG)(Poly->Points[i].x * ScaleX);  
  976.         y = (LONG)(Poly->Points[i].y * ScaleY);
  977.         Poly->Points[i].x = (LONG)(x*Cz - y*Sz + Cx);
  978.         Poly->Points[i].y = (LONG)(x*Sz + y*Cz + Cy);
  979.       } // End for
  980.  
  981.     ViewPort = Dest->GetViewPort ();
  982.     
  983.     ClipPolygon ( Poly, ClipPoly, ViewPort );
  984.  
  985.     EDGETABLE *EdgeTable;   
  986.     EdgeTable = new EDGETABLE ();
  987.  
  988.     LONG SrcWd = Src->GetBytesPerRow ();
  989.     BYTE *SrcBuffer = Src->GetBuffer ();
  990.     
  991.     if (ClipPoly->NumPoints>2)
  992.       {
  993.         CreateEdgeTable ( ClipPoly, EdgeTable );  
  994.         LONG x1,x2;
  995.         LONG U1,U2,Du;
  996.         LONG V1,V2,Dv;
  997.         LONG DWd;
  998.         BYTE *DestBuffer;
  999.         
  1000.         DestBuffer = Dest->SetOffset ( 0, EdgeTable->Top );
  1001.         for (i=0;i<EdgeTable->Height;i++)
  1002.           {
  1003.             x1 = EdgeTable->Left[i].x;  
  1004.             x2 = EdgeTable->Right[i].x;
  1005.             U1 = EdgeTable->Left[i].u;  
  1006.             U2 = EdgeTable->Right[i].u;
  1007.             V1 = EdgeTable->Left[i].v;  
  1008.             V2 = EdgeTable->Right[i].v;
  1009.             DWd = x2-x1+1;
  1010.             if (DWd<=0)
  1011.               {
  1012.                 DestBuffer = Dest->GetNextRow ( ROW_DOWN );
  1013.                 continue;
  1014.               } // End if
  1015.  
  1016.             Du = (U2-U1)/DWd;
  1017.             Dv = (V2-V1)/DWd;
  1018.             INT j;
  1019.             DestBuffer += x1;
  1020.             for (j=0;j<DWd;j++)
  1021.               {
  1022.                 LONG SrcOffset;
  1023.                 SrcOffset = (V1>>16)*SrcWd+(U1>>16);
  1024.                 *DestBuffer = *(SrcBuffer+SrcOffset);
  1025.                 DestBuffer++;
  1026.                 U1 += Du;
  1027.                 V1 += Dv;
  1028.               } // End for
  1029.             DestBuffer = Dest->GetNextRow ( ROW_DOWN );
  1030.           } // End for
  1031.       } // End if       
  1032.     
  1033.     delete EdgeTable;
  1034.     delete Poly;
  1035.     delete ClipPoly;
  1036.   } // End of RotateImage for GRAFIX
  1037.                            
  1038. VOID GRAFIX::ConvertImage ( IMAGE *Image, COLORTABLE *MatchTable )
  1039.   {
  1040.     LONG i,j;
  1041.     BYTE *Buffer;
  1042.     BYTE *Table;
  1043.  
  1044.     Table = MatchTable->GetTable ();
  1045.     if (Table==NULL)
  1046.       return;
  1047.  
  1048.     for (i=0;i<Image->GetHeight();i++)
  1049.       {
  1050.         Buffer = Image->SetOffset ( 0, i );
  1051.         for (j=0;j<Image->GetWidth();j++)
  1052.           {
  1053.             LONG Color;
  1054.             Color = Buffer[j];
  1055.             Buffer[j] = Table[Color];  
  1056.           } // End for  
  1057.       } // End for  
  1058.   } // End of ConvertImage for GRAFIX
  1059.  
  1060. BOOLEAN GRAFIX::LoadImage ( STRING FileName, IMAGE *Image, RGBPALETTE *Pal )
  1061.   {
  1062.     IMAGEFILETOOL *ImageTool;
  1063.     INT FileType;
  1064.     FILEHANDLE f;
  1065.     BOOLEAN Result;
  1066.  
  1067.     f = File.Open ( FileName, OPEN_READ | OPEN_BINARY );
  1068.     if (f==NULL)
  1069.       {
  1070.         Error.SetError ( ERR_FILEIO );
  1071.         return FAILURE;
  1072.       } // End if  
  1073.  
  1074.     FileType = GetImageFileType ( f );
  1075.     switch (FileType)
  1076.       {
  1077.         case PCXFILE :
  1078.           ImageTool = new PCXFILETOOL ( f );
  1079.           break;
  1080.         case BMPFILE :
  1081.           ImageTool = new BMPFILETOOL ( f );
  1082.           break;
  1083.         case GIFFILE :
  1084.           ImageTool = new GIFFILETOOL ( f );
  1085.           break;
  1086.         default :
  1087.           ImageTool = NULL;
  1088.           break;
  1089.       } // End switch
  1090.  
  1091.     if (ImageTool==NULL)
  1092.       {
  1093.         Error.SetError ( ERR_NOMEMORY );
  1094.         File.Close ( f );
  1095.         return FAILURE;
  1096.       } // End if
  1097.  
  1098.     Result = ImageTool->LoadImage ( Image, Pal );
  1099.     if (Result==FAILURE)
  1100.       {
  1101.         Error.SetError ( ERR_NOVALID );
  1102.       } // End if
  1103.  
  1104.     File.Close ( f );
  1105.     if (Result)
  1106.       {}
  1107.     return Result;
  1108.   } // End of LoadImage for GRAFIX
  1109.  
  1110. BOOLEAN GRAFIX::SaveImage ( STRING FileName, SHORT ImageType, IMAGE *Image,
  1111.                             LONG Sx, LONG Sy, LONG Wd, LONG Ht, RGBPALETTE *Pal )
  1112.   {
  1113.     IMAGEFILETOOL *ImageTool;
  1114.     FILEHANDLE f;
  1115.  
  1116.     f = File.Open ( FileName, OPEN_WRITE | OPEN_BINARY );
  1117.     if (f==NULL)
  1118.       return FAILURE;
  1119.  
  1120.     switch (ImageType)
  1121.       {
  1122.         case PCXFILE :
  1123.           ImageTool = new PCXFILETOOL ( f );
  1124.           break;
  1125.         case BMPFILE :
  1126.           ImageTool = new BMPFILETOOL ( f );
  1127.           break;
  1128.         case GIFFILE :
  1129.           ImageTool = new GIFFILETOOL ( f );
  1130.           break;
  1131.         default :
  1132.           ImageTool = NULL;
  1133.           break;
  1134.       } // End switch
  1135.  
  1136.     if (ImageTool==NULL)
  1137.       {
  1138.         File.Close ( f );
  1139.         return FAILURE;
  1140.       } // End if
  1141.  
  1142.     BOOLEAN Ok;
  1143.     RECTANGLE ViewPort;
  1144.  
  1145.     ViewPort = Image->GetViewPort ();
  1146.  
  1147.     Ok = ClipRect ( &ViewPort, &Sx, &Sy, &Wd, &Ht );
  1148.     if (!Ok)
  1149.       {
  1150.         File.Close ( f );
  1151.         return FAILURE;
  1152.       } // End if
  1153.  
  1154.     Ok = ImageTool->SaveImage ( Image, Sx, Sy, Wd, Ht, Pal );
  1155.     if (!Ok)
  1156.       {
  1157.         File.Close ( f );
  1158.         return FAILURE;
  1159.       } // End if
  1160.     File.Close ( f );
  1161.     return SUCCESS;
  1162.   } // End of SaveImage for GRAFIX
  1163.  
  1164. VOID GRAFIX::PlayFLIC ( FLICFILE *Flic, RECTANGLE Region, LONG Cx, LONG Cy,
  1165.                         LONG StartFrame, LONG EndFrame, LONG Flags, FLICCallback Callback )
  1166.   {
  1167.     if (DisplayDriver==NULL)
  1168.       return;
  1169.  
  1170.     if (Flic==NULL)
  1171.       return;
  1172.  
  1173.     LONG Sx,Sy,Wd,Ht;
  1174.     LONG NumFrames;
  1175.     BOOLEAN PalChange;
  1176.     IMAGE *Image;
  1177.  
  1178.     Sx = Region.x1;
  1179.     Sy = Region.y1;
  1180.     Wd = Region.x2-Region.x1+1;
  1181.     Ht = Region.y2-Region.y1+1;
  1182.     
  1183.     Image = Flic->GetImage ();
  1184.     HDISPLAY hDisplay = Flic->GetDisplay ();
  1185.     
  1186.     if (Flags&FLIC_NEXT)
  1187.       {
  1188.         Flic->PlayFrame ( TRUE );
  1189.         PalChange = Flic->IsPalChanged ();
  1190.         if (PalChange)
  1191.           {
  1192.             SetPalette ( hDisplay, Flic->GetPalette() );
  1193.             Flic->PalProcessed ();
  1194.           } // End if
  1195.         DisplayImage ( hDisplay, Image, Sx, Sy, Wd, Ht, Cx, Cy );
  1196.         return;  
  1197.       } // End if
  1198.       
  1199.     if (Flags&FLIC_NOADVANCE)
  1200.       {
  1201.         Flic->PlayFrame ( FALSE );
  1202.         PalChange = Flic->IsPalChanged ();
  1203.         if (PalChange)
  1204.           {
  1205.             SetPalette ( hDisplay, Flic->GetPalette() );
  1206.             Flic->PalProcessed ();
  1207.           } // End if
  1208.         DisplayImage ( hDisplay, Image, Sx, Sy, Wd, Ht, Cx, Cy );
  1209.         return;  
  1210.       } // End if
  1211.       
  1212.     NumFrames = Flic->GetNumFrames ();
  1213.     if (NumFrames==0)
  1214.       return;
  1215.      
  1216.     if (Flags&FLIC_ALL)
  1217.       {
  1218.         StartFrame = 0;
  1219.         EndFrame = NumFrames-1;  
  1220.       } // End if
  1221.     else
  1222.       {
  1223.         if (StartFrame>=NumFrames)
  1224.           return;  
  1225.         if (EndFrame>=NumFrames)
  1226.           EndFrame = EndFrame%NumFrames;
  1227.       } // End else  
  1228.       
  1229.     LONG LoopCount=0;
  1230.     LONG Speed;
  1231.  
  1232.     Speed = Flic->Speed;
  1233.     if (Speed==FLIC_SPEED_DEFAULT)
  1234.       {
  1235.         if (Flic->IsFLCFile()!=TRUE)
  1236.           Speed = Flic->GetDefaultSpeed ();
  1237.         else
  1238.           Speed = 1;  
  1239.       } // End if
  1240.  
  1241.          if (Speed)
  1242.            {} 
  1243.     BOOLEAN Done=FALSE;
  1244.  
  1245.     Flic->SetFrame ( StartFrame );
  1246.     
  1247.     while (!Done)
  1248.       {
  1249.         Flic->PlayFrame ( TRUE );
  1250.         PalChange = Flic->IsPalChanged ();
  1251.         if (PalChange)
  1252.           {
  1253.             SetPalette ( hDisplay, Flic->GetPalette() );
  1254.             Flic->PalProcessed ();
  1255.           } // End if
  1256.               
  1257.         #if defined (__FORDOS__)
  1258.           WaitForRetrace ( Speed );
  1259.         #endif
  1260.           
  1261.         DisplayImage ( hDisplay, Image, Sx, Sy, Wd, Ht, Cx, Cy );
  1262.         if (Callback!=NULL)
  1263.           Done = Callback ( Flic );
  1264.             
  1265.         if (Flic->GetFrame ()>EndFrame)
  1266.           {
  1267.             if (Flags&FLIC_LOOP)
  1268.               {  
  1269.                 Flic->SetFrame ( StartFrame );
  1270.                 LoopCount++;
  1271.                 if (Flic->Loop>=0)
  1272.                   {
  1273.                     if (LoopCount>=Flic->Loop)
  1274.                       Done = TRUE;  
  1275.                   } // End if
  1276.               } // End if
  1277.             else
  1278.               Done = TRUE;      
  1279.           } // End if    
  1280.       } // End while
  1281.   } // End of PlayFLIC for GRAFIX
  1282.  
  1283. VOID GRAFIX::SetPalette ( HDISPLAY hDisplay, RGBPALETTE *Pal )
  1284.   {
  1285.     if (DisplayDriver==NULL)
  1286.       return;
  1287.     DisplayDriver->SetPalette ( hDisplay, Pal );
  1288.   } // End of SetPalette for GRAFIX
  1289.  
  1290. VOID GRAFIX::GetPalette ( HDISPLAY hDisplay, RGBPALETTE *Pal )
  1291.   {
  1292.     if (DisplayDriver==NULL)
  1293.       return;
  1294.     DisplayDriver->GetPalette ( hDisplay, Pal );
  1295.   } // End of GetPalette for GRAFIX
  1296.  
  1297. VOID GRAFIX::ClearPalette ( HDISPLAY hDisplay, BYTE R, BYTE G, BYTE B )
  1298.   {
  1299.     RGBPALETTE *Pal;
  1300.     RGBCOLOR *Entry;
  1301.     
  1302.     Pal = new RGBPALETTE ();
  1303.     if (Pal==NULL)
  1304.       return;
  1305.     Entry = Pal->GetEntry ();
  1306.  
  1307.     INT i;
  1308.     for (i=0;i<256;i++)
  1309.       {
  1310.         Entry[i].Red = R;  
  1311.         Entry[i].Green = G;  
  1312.         Entry[i].Blue = B;  
  1313.       } // End for
  1314.     SetPalette ( hDisplay, Pal );  
  1315.     delete Pal;  
  1316.   } // End of ClearPalette for GRAFIX
  1317.  
  1318. VOID GRAFIX::FadePalette ( HDISPLAY hDisplay, RGBPALETTE *Pal,
  1319.                            LONG Direction, LONG NumSteps )
  1320.   {
  1321.     RGBCOLOR OldEntry[256];
  1322.     RGBCOLOR *Entry;
  1323.     INT i,j;
  1324.  
  1325.     if (NumSteps==0)
  1326.       return;
  1327.  
  1328.     Entry = Pal->GetEntry ();
  1329.     for (i=0;i<256;i++)
  1330.       {
  1331.         OldEntry[i].Red = Entry[i].Red;
  1332.         OldEntry[i].Green = Entry[i].Green;
  1333.         OldEntry[i].Blue = Entry[i].Blue;
  1334.       } // End for
  1335.  
  1336.     double StepRatio;
  1337.     double Ratio;
  1338.     StepRatio = (double)1/NumSteps;
  1339.  
  1340.     if (Direction==PAL_FADE_IN)
  1341.       {
  1342.         for (i=0;i<NumSteps;i++)
  1343.           {
  1344.             Ratio = StepRatio*i;
  1345.             for (j=0;j<256;j++)
  1346.               {
  1347.                 Entry[j].Red = (BYTE)(Ratio*OldEntry[j].Red);
  1348.                 Entry[j].Green = (BYTE)(Ratio*OldEntry[j].Green);
  1349.                 Entry[j].Blue = (BYTE)(Ratio*OldEntry[j].Blue);
  1350.               } // End for
  1351.             WaitForRetrace ();
  1352.             SetPalette ( hDisplay, Pal );
  1353.           } // End for
  1354.       } // End if
  1355.     else
  1356.       {
  1357.         for (i=NumSteps-1;i>=0;i--)
  1358.           {
  1359.             Ratio = StepRatio*i;
  1360.             for (j=0;j<256;j++)
  1361.               {
  1362.                 Entry[j].Red = (BYTE)(Ratio*OldEntry[j].Red);
  1363.                 Entry[j].Green = (BYTE)(Ratio*OldEntry[j].Green);
  1364.                 Entry[j].Blue = (BYTE)(Ratio*OldEntry[j].Blue);
  1365.               } // End for
  1366.             WaitForRetrace ();
  1367.             SetPalette ( hDisplay, Pal );
  1368.           } // End for
  1369.       } // End else
  1370.  
  1371.     for (i=0;i<256;i++)
  1372.       {
  1373.         Entry[i].Red = OldEntry[i].Red;
  1374.         Entry[i].Green = OldEntry[i].Green;
  1375.         Entry[i].Blue = OldEntry[i].Blue;
  1376.       } // End for
  1377.   } // End of FadePalette for GRAFIX
  1378.  
  1379. BOOLEAN GRAFIX::SavePalette ( STRING FileName, RGBPALETTE *Pal, LONG PalFormat )
  1380.   {
  1381.     FILEHANDLE f;
  1382.  
  1383.     if (Pal==NULL)
  1384.       return FAILURE;
  1385.  
  1386.     if (PalFormat==PAL_MSWIN)
  1387.       {
  1388.         f = File.Open ( FileName, OPEN_WRITE | OPEN_BINARY );
  1389.         if (f==NULL)
  1390.           return FAILURE;
  1391.  
  1392.         CHAR Str[4];
  1393.         DWORD Size;
  1394.  
  1395.         strncpy ( Str, "RIFF", 4 );
  1396.         if (File.Write ( f, Str, 4 )==FALSE)
  1397.           {
  1398.             File.Close ( f );
  1399.             return FAILURE;
  1400.           } // End if
  1401.  
  1402.         Size = 1040;
  1403.         if (File.Write ( f, &Size, 4 )==FALSE)
  1404.           {
  1405.             File.Close ( f );
  1406.             return FAILURE;
  1407.           } // End if
  1408.  
  1409.         strncpy ( Str, "PAL ", 4 );
  1410.         if (File.Write ( f, Str, 4 )==FALSE)
  1411.           {
  1412.             File.Close ( f );
  1413.             return FAILURE;
  1414.           } // End if
  1415.  
  1416.         strncpy ( Str, "data", 4 );
  1417.         if (File.Write ( f, Str, 4 )==FALSE)
  1418.           {
  1419.             File.Close ( f );
  1420.             return FAILURE;
  1421.           } // End if
  1422.  
  1423.         Size = 4+4*256;
  1424.         if (File.Write ( f, &Size, 4 )==FALSE)
  1425.           {
  1426.             File.Close ( f );
  1427.             return FAILURE;
  1428.           } // End if
  1429.  
  1430.         SHORT Version;
  1431.         SHORT NumEntries;
  1432.  
  1433.         Version = 0x0300;
  1434.         if (File.Write ( f, &Version, 2 )==FALSE)
  1435.           {
  1436.             File.Close ( f );
  1437.             return FAILURE;
  1438.           } // End if
  1439.  
  1440.         NumEntries = 256;
  1441.         if (File.Write ( f, &NumEntries, 2 )==FALSE)
  1442.           {
  1443.             File.Close ( f );
  1444.             return FAILURE;
  1445.           } // End if
  1446.  
  1447.         RGBCOLOR *Entry;
  1448.  
  1449.         Entry = Pal->GetEntry ();
  1450.  
  1451.         INT i;
  1452.         BYTE Flags;
  1453.         for (i=0;i<256;i++)
  1454.           {
  1455.             File.Write ( f, &(Entry[i].Red), 1 );
  1456.             File.Write ( f, &(Entry[i].Green), 1 );
  1457.             File.Write ( f, &(Entry[i].Blue), 1 );
  1458.             File.Write ( f, &(Flags), 1 );
  1459.           } // End for
  1460.  
  1461.         File.Close ( f );
  1462.         return SUCCESS;
  1463.       } // End if
  1464.     else if (PalFormat==PAL_PSP)
  1465.       {
  1466.         f = File.Open ( FileName, OPEN_WRITE );
  1467.         if (f==NULL)
  1468.           return FAILURE;
  1469.  
  1470.         fprintf ( f, "JASC-PAL\n" );
  1471.         fprintf ( f, "0100\n" );
  1472.         fprintf ( f, "256\n" );
  1473.  
  1474.         RGBCOLOR *Entry;
  1475.         Entry = Pal->GetEntry ();
  1476.  
  1477.         INT i;
  1478.         for (i=0;i<256;i++)
  1479.           {
  1480.             fprintf ( f, "%d %d %d\n", Entry[i].Red,
  1481.                                        Entry[i].Green,
  1482.                                        Entry[i].Blue );
  1483.           } // End for
  1484.  
  1485.         File.Close ( f );
  1486.         return SUCCESS;
  1487.       } // End else if
  1488.     else     
  1489.       {
  1490.         return FAILURE;
  1491.       } // End else
  1492.   } // End of SavePalette for GRAFIX
  1493.  
  1494. BOOLEAN GRAFIX::LoadPalette ( STRING FileName, RGBPALETTE *Pal )
  1495.   {
  1496.     FILEHANDLE f;
  1497.     if (Pal==NULL)
  1498.       return FAILURE;
  1499.  
  1500.     f = File.Open ( FileName, OPEN_READ | OPEN_BINARY );
  1501.     if (f==NULL)
  1502.       return FAILURE;
  1503.  
  1504.     CHAR Str[4];
  1505.     DWORD Size;
  1506.  
  1507.     // Check format first
  1508.     CHAR ID[8];
  1509.     LONG Format;
  1510.  
  1511.     if (File.Read ( f, ID, 8 )==FALSE)
  1512.       {
  1513.         File.Close ( f );
  1514.         return FAILURE;
  1515.       } // End if
  1516.     if (strncmp (ID, "RIFF", 4)==0)
  1517.       {
  1518.         Format = PAL_MSWIN;
  1519.       } // End if
  1520.     else if (strncmp ( ID, "JASC-PAL", 8 )==0)
  1521.       {
  1522.         Format = PAL_PSP;
  1523.       } // End else if
  1524.     else
  1525.       {
  1526.         File.Close ( f );
  1527.         return FAILURE;
  1528.       } // End else
  1529.  
  1530.     // Go back to first byte
  1531.     File.Seek ( f, 0, FROM_BEGIN );
  1532.  
  1533.     if (Format==PAL_MSWIN)
  1534.       {
  1535.         if (File.Read ( f, Str, 4 )==FALSE)
  1536.           {
  1537.             File.Close ( f );
  1538.             return FAILURE;
  1539.           } // End if
  1540.         if (strncmp (Str, "RIFF", 4)!=0)
  1541.           {
  1542.             File.Close ( f );
  1543.             return FAILURE;
  1544.           } // End if
  1545.  
  1546.         if (File.Read ( f, &Size, 4 )==FALSE)
  1547.           {
  1548.             File.Close ( f );
  1549.             return FAILURE;
  1550.           } // End if
  1551.  
  1552.         if (File.Read ( f, Str, 4 )==FALSE)
  1553.           {
  1554.             File.Close ( f );
  1555.             return FAILURE;
  1556.           } // End if
  1557.         if (strncmp (Str, "PAL ", 4)!=0)
  1558.           {
  1559.             File.Close ( f );
  1560.             return FAILURE;
  1561.           } // End if
  1562.  
  1563.         if (File.Read ( f, Str, 4 )==FALSE)
  1564.           {
  1565.             File.Close ( f );
  1566.             return FAILURE;
  1567.           } // End if
  1568.         if (strncmp (Str, "data", 4)!=0)
  1569.           {
  1570.             File.Close ( f );
  1571.             return FAILURE;
  1572.           } // End if
  1573.  
  1574.         if (File.Read ( f, &Size, 4 )==FALSE)
  1575.           {
  1576.             File.Close ( f );
  1577.             return FAILURE;
  1578.           } // End if
  1579.  
  1580.         SHORT Version;
  1581.         SHORT NumEntries;
  1582.  
  1583.         if (File.Read ( f, &Version, 2 )==FALSE)
  1584.           {
  1585.             File.Close ( f );
  1586.             return FAILURE;
  1587.           } // End if
  1588.  
  1589.         if (File.Read ( f, &NumEntries, 2 )==FALSE)
  1590.           {
  1591.             File.Close ( f );
  1592.             return FAILURE;
  1593.           } // End if
  1594.  
  1595.         #if defined (__MSBFIRST__)
  1596.           SwapWord ( (WORD*)NumEntries );
  1597.         #endif 
  1598.  
  1599.         RGBCOLOR *Entry;
  1600.  
  1601.         Entry = Pal->GetEntry ();
  1602.  
  1603.         INT i;
  1604.         BYTE Flags;
  1605.  
  1606.         for (i=0;i<NumEntries;i++)
  1607.           {
  1608.             File.Read ( f, &(Entry[i].Red), 1 );
  1609.             File.Read ( f, &(Entry[i].Green), 1 );
  1610.             File.Read ( f, &(Entry[i].Blue), 1 );
  1611.             File.Read ( f, &(Flags), 1 );
  1612.           } // End for
  1613.  
  1614.         File.Close ( f );
  1615.         return SUCCESS;
  1616.       } // End if
  1617.     else if (Format==PAL_PSP)
  1618.       {
  1619.         CHAR VerStr[8];
  1620.         CHAR PalStr[8];
  1621.         INT Num;
  1622.         INT Red,Green,Blue;
  1623.  
  1624.         fscanf ( f, "%s\n", PalStr );
  1625.         fscanf ( f, "%s\n", VerStr );
  1626.         fscanf ( f, "%d\n", &Num );
  1627.  
  1628.         RGBCOLOR *Entry;
  1629.         Entry = Pal->GetEntry ();
  1630.  
  1631.         if (Entry==NULL)
  1632.           {
  1633.             File.Close ( f );
  1634.             return FAILURE;
  1635.           } // End if
  1636.           
  1637.         INT i;
  1638.         for (i=0;i<Num;i++)
  1639.           {
  1640.             fscanf ( f, "%d %d %d\n", &Red, &Green, &Blue );
  1641.             Entry[i].Red = (BYTE)Red;
  1642.             Entry[i].Green = (BYTE)Green;
  1643.             Entry[i].Blue = (BYTE)Blue;
  1644.           } // End for
  1645.         File.Close ( f );
  1646.         return SUCCESS;  
  1647.       } // End else if
  1648.     File.Close ( f );
  1649.     return FAILURE;
  1650.   } // End of LoadPalette for GRAFIX
  1651.  
  1652. LONG GRAFIX::GetWidth ( HDISPLAY hDisplay )
  1653.   {
  1654.     if (DisplayDriver==NULL)
  1655.       return 0;
  1656.     return DisplayDriver->GetWidth ( hDisplay );
  1657.   } // End of GetWidth for GRAFIX
  1658.  
  1659. LONG GRAFIX::GetHeight ( HDISPLAY hDisplay )
  1660.   {
  1661.     if (DisplayDriver==NULL)
  1662.       return 0;
  1663.     return DisplayDriver->GetHeight ( hDisplay );
  1664.   } // End of GetHeight for GRAFIX
  1665.  
  1666. LONG GRAFIX::GetCode ( RECTANGLE Rect, LONG x, LONG y )
  1667.   {
  1668.     // 4 bits are use.
  1669.     // From most significant bit Top, Bottom, Right, Left.
  1670.  
  1671.     INT Code;
  1672.  
  1673.     Code = 0;
  1674.     if (y<Rect.y1)
  1675.       Code |= (1<<3);
  1676.     else if (y>Rect.y2)
  1677.       Code |= (1<<2);
  1678.  
  1679.     if (x<Rect.x1)
  1680.       Code |= (1<<0);
  1681.     else if (x>Rect.x2)
  1682.       Code |= (1<<1);
  1683.  
  1684.     return Code;
  1685.   } // End of GetCode for GRAFIX
  1686.  
  1687. BOOLEAN GRAFIX::ClipLine ( RECTANGLE Rect, LONG *x1, LONG *y1, LONG *x2, LONG *y2 )
  1688.   {
  1689.     LONG Code1,Code2;
  1690.  
  1691.     LONG Code;
  1692.  
  1693.     BOOLEAN Done=FALSE;
  1694.  
  1695.     Code1 = GetCode ( Rect, *x1, *y1 );
  1696.     Code2 = GetCode ( Rect, *x2, *y2 );
  1697.  
  1698.     INT x, y;
  1699.  
  1700.     while (!Done)
  1701.       {
  1702.         if ((Code1|Code2)==0)
  1703.           return TRUE;
  1704.         if (Code1&Code2)
  1705.           return FALSE;
  1706.  
  1707.         if (Code1)
  1708.           Code = Code1;
  1709.         else
  1710.           Code = Code2;
  1711.  
  1712.         if (Code&(1<<3)) // Clip against top
  1713.           {
  1714.             x = *x1 + ((*x2-*x1)*(Rect.y1-*y1) / (*y2-*y1));
  1715.             y = Rect.y1;
  1716.           } // End if
  1717.         else if (Code&(1<<2)) // Clip against bottom
  1718.           {
  1719.             x = *x1 + ((*x2-*x1)*(Rect.y2-*y1) / (*y2-*y1));
  1720.             y = Rect.y2;
  1721.           } // End if
  1722.         else if (Code&(1<<1)) // Clip against right
  1723.           {
  1724.             y = *y1 + ((*y2-*y1)*(Rect.x2-*x1) / (*x2-*x1));
  1725.             x = Rect.x2;
  1726.           } // End if
  1727.         else if (Code&(1<<0)) // Clip against left
  1728.           {
  1729.             y = *y1 + ((*y2-*y1)*(Rect.x1-*x1) / (*x2-*x1));
  1730.             x = Rect.x1;
  1731.           } // End if
  1732.  
  1733.         if (Code==Code1)
  1734.           {
  1735.             *x1 = x;
  1736.             *y1 = y;
  1737.             Code1 = GetCode ( Rect, *x1, *y1 );
  1738.           } // End if
  1739.         else
  1740.           {
  1741.             *x2 = x;
  1742.             *y2 = y;
  1743.             Code2 = GetCode ( Rect, *x1, *y1 );
  1744.           } // End if
  1745.       } // End while
  1746.     return FALSE;
  1747.   } // End of ClipLine for GRAFIX
  1748.  
  1749. VOID GRAFIX::DrawPixel ( IMAGE *Dest, LONG x, LONG y )
  1750.   {
  1751.     RECTANGLE ViewPort;
  1752.  
  1753.     ViewPort = Dest->GetViewPort ();
  1754.     if ((x<ViewPort.x1)||(y<ViewPort.y1)||(x>ViewPort.x2)||(y>ViewPort.y2))
  1755.       return;
  1756.  
  1757.     BYTE *Buffer;
  1758.     Buffer = Dest->SetOffset ( x, y );
  1759.     *Buffer = (BYTE)FGColor;
  1760.   } // End of DrawPixel for GRAFIX
  1761.  
  1762. VOID GRAFIX::DrawPixel ( HDISPLAY hDisplay, LONG x, LONG y )
  1763.   {
  1764.     if (DisplayDriver==NULL)
  1765.       return;
  1766.  
  1767.     DisplayDriver->DrawPixel ( hDisplay, x, y, FGColor );
  1768.   } // End of DrawPixel for GRAFIX
  1769.  
  1770. VOID GRAFIX::DrawLine ( IMAGE *Dest, LONG x1, LONG y1, LONG x2, LONG y2 )
  1771.   {
  1772.     BOOLEAN Ok;
  1773.     RECTANGLE ViewPort;
  1774.  
  1775.     ViewPort = Dest->GetViewPort ();
  1776.  
  1777.     Ok = ClipLine ( ViewPort, &x1, &y1, &x2, &y2 );
  1778.     if (!Ok)
  1779.       return;
  1780.  
  1781.     if (y1>y2)
  1782.       {                   
  1783.         #ifndef __FORVISUAL__
  1784.           SwapValue ( &y1, &y2 );
  1785.           SwapValue ( &x1, &x2 );
  1786.         #endif  
  1787.       } // End if
  1788.  
  1789.     INT Dx, Dy;
  1790.     INT AddX;
  1791.     INT Len;
  1792.  
  1793.     if (x2<x1)
  1794.       {
  1795.         AddX = -1;
  1796.       } // End if
  1797.     else
  1798.       AddX = 1;
  1799.  
  1800.     Dx = abs(x2-x1);
  1801.     Dy = abs(y2-y1);
  1802.  
  1803.     Len = MaxValue ( Dx, Dy ) + 1;
  1804.  
  1805.     BYTE *Buffer;
  1806.  
  1807.     Buffer = Dest->SetOffset ( 0, y1 );
  1808.  
  1809.     COLOR Color = FGColor;
  1810.     INT i;
  1811.     DWORD Error=0;
  1812.  
  1813.     DWORD x;
  1814.  
  1815.     if (Dy==0)
  1816.       {
  1817.         x = MinValue ( x1, x2 );
  1818.         int i;
  1819.         Buffer+=x;
  1820.         for (i=0;i<Len;i++)
  1821.           Buffer[i] = (BYTE)Color;
  1822.         //memset ( Buffer+x, Color, Len );
  1823.       } // End if
  1824.     else
  1825.       {
  1826.         x = x1;
  1827.         if (Dx>Dy)
  1828.           {
  1829.             for (i=0;i<Len;i++)
  1830.               {
  1831.                 Buffer[x] = (BYTE)Color;
  1832.                 Error += (DWORD)Dy;
  1833.                 if (Error>=(DWORD)Dx)
  1834.                   {
  1835.                     Buffer = Dest->GetNextRow ( ROW_DOWN );
  1836.                     Error -= (DWORD)Dx;
  1837.                   } // End Error
  1838.                 x += AddX;
  1839.               } // End for
  1840.           } // End if
  1841.         else
  1842.           {
  1843.             for (i=0;i<Len;i++)
  1844.               {
  1845.                 Buffer[x] = (BYTE)Color;
  1846.                 Error += (DWORD)Dx;
  1847.                 if (Error>=(DWORD)Dy)
  1848.                   {
  1849.                     x += AddX;
  1850.                     Error -= (DWORD)Dy;
  1851.                   } // End Error
  1852.                 Buffer = Dest->GetNextRow ( ROW_DOWN );
  1853.               } // End for
  1854.           } // End else
  1855.       } // End else
  1856.   } // End of DrawLine for GRAGIX
  1857.  
  1858. VOID GRAFIX::DrawLine ( HDISPLAY hDisplay, LONG x1, LONG y1, LONG x2, LONG y2 )
  1859.   {
  1860.     if (DisplayDriver==NULL)
  1861.       return;
  1862.  
  1863.     RECTANGLE ViewPort;
  1864.     ViewPort.x1 = 0;
  1865.     ViewPort.y1 = 0;
  1866.     ViewPort.x2 = DisplayDriver->GetWidth( hDisplay )-1;
  1867.     ViewPort.y2 = DisplayDriver->GetHeight( hDisplay )-1;
  1868.  
  1869.     BOOLEAN Ok = ClipLine ( ViewPort, &x1, &y1, &x2, &y2 );
  1870.     if (!Ok)
  1871.       return;
  1872.  
  1873.     if (y1>y2)
  1874.       {
  1875.         SwapValue ( &y1, &y2 );
  1876.         SwapValue ( &x1, &x2 );
  1877.       } // End if
  1878.  
  1879.     COLOR Color = FGColor;
  1880.     DisplayDriver->DrawLine ( hDisplay, x1, y1, x2, y2, Color );
  1881.   } // End of DrawLine for GRAFIX
  1882.  
  1883. VOID GRAFIX::DrawRect ( IMAGE *Dest, LONG x1, LONG y1, LONG x2, LONG y2 )
  1884.   {
  1885.     DrawLine ( Dest, x1, y2, x2, y2 );
  1886.     DrawLine ( Dest, x1, y1, x2, y1 );
  1887.     DrawLine ( Dest, x1, y1, x1, y2 );
  1888.     DrawLine ( Dest, x2, y1, x2, y2 );
  1889.   } // End of DrawRect for GRAFIX
  1890.  
  1891. VOID GRAFIX::DrawRect ( HDISPLAY hDisplay, LONG x1, LONG y1, LONG x2, LONG y2 )
  1892.   {
  1893.     if (DisplayDriver==NULL)
  1894.       return;
  1895.  
  1896.     RECTANGLE ViewPort;
  1897.     ViewPort.x1 = 0;
  1898.     ViewPort.y1 = 0;
  1899.     ViewPort.x2 = DisplayDriver->GetWidth( hDisplay )-1;
  1900.     ViewPort.y2 = DisplayDriver->GetHeight( hDisplay )-1;
  1901.  
  1902.     if (y1>y2)
  1903.       {
  1904.         SwapValue ( &y1, &y2 );
  1905.         SwapValue ( &x1, &x2 );
  1906.       } // End if
  1907.  
  1908.     LONG Wd,Ht;
  1909.     Wd = x2-x1+1;
  1910.     Ht = y2-y1+1;
  1911.  
  1912.     BOOLEAN Ok = ClipRect ( &ViewPort, &x1, &y1, &Wd, &Ht );
  1913.     if (!Ok)
  1914.       return;
  1915.  
  1916.     x2 = x1+Wd-1;
  1917.     y2 = y1+Ht-1;
  1918.  
  1919.     DisplayDriver->DrawRect ( hDisplay, x1, y1, x2, y2, FGColor );
  1920.   } // End of DrawRect for GRAFIX
  1921.  
  1922. VOID GRAFIX::FillRect ( IMAGE *Dest, LONG x1, LONG y1, LONG x2, LONG y2 )
  1923.   {
  1924.     if (DisplayDriver==NULL)
  1925.       return;
  1926.  
  1927.     RECTANGLE ViewPort;
  1928.     ViewPort = Dest->GetViewPort ();
  1929.  
  1930.     if (y1>y2)
  1931.       {
  1932.         SwapValue ( &y1, &y2 );
  1933.         SwapValue ( &x1, &x2 );
  1934.       } // End if
  1935.  
  1936.     LONG Wd,Ht;
  1937.     Wd = x2-x1+1;
  1938.     Ht = y2-y1+1;
  1939.  
  1940.     BOOLEAN Ok = ClipRect ( &ViewPort, &x1, &y1, &Wd, &Ht );
  1941.     if (!Ok)
  1942.       return;
  1943.  
  1944.     x2 = x1+Wd-1;
  1945.     y2 = y1+Ht-1;
  1946.  
  1947.     INT i;
  1948.     BYTE *Buffer;
  1949.  
  1950.     Buffer = Dest->SetOffset ( x1, y1 );
  1951.  
  1952.     for (i=0;i<Ht;i++)
  1953.       {
  1954.         memset ( Buffer, BGColor, Wd );
  1955.         Buffer = Dest->GetNextRow ( ROW_DOWN );
  1956.       } // End for
  1957.   } // End of FillRect for GRAFIX
  1958.  
  1959. VOID GRAFIX::FillRect ( HDISPLAY hDisplay, LONG x1, LONG y1, LONG x2, LONG y2 )
  1960.   {
  1961.     if (DisplayDriver==NULL)
  1962.       return;
  1963.  
  1964.     RECTANGLE ViewPort;
  1965.     ViewPort.x1 = 0;
  1966.     ViewPort.y1 = 0;
  1967.     ViewPort.x2 = DisplayDriver->GetWidth( hDisplay )-1;
  1968.     ViewPort.y2 = DisplayDriver->GetHeight( hDisplay )-1;
  1969.  
  1970.     if (y1>y2)
  1971.       {
  1972.         SwapValue ( &y1, &y2 );
  1973.         SwapValue ( &x1, &x2 );
  1974.       } // End if
  1975.  
  1976.     LONG Wd,Ht;
  1977.     Wd = x2-x1+1;
  1978.     Ht = y2-y1+1;
  1979.  
  1980.     BOOLEAN Ok = ClipRect ( &ViewPort, &x1, &y1, &Wd, &Ht );
  1981.     if (!Ok)
  1982.       return;
  1983.  
  1984.     x2 = x1+Wd-1;
  1985.     y2 = y1+Ht-1;
  1986.  
  1987.     DisplayDriver->FillRect ( hDisplay, x1, y1, x2, y2, BGColor );
  1988.   } // End of FillRect for GRAFIX
  1989.  
  1990. VOID GRAFIX::DrawEllipsePoint ( IMAGE *Dest, LONG Cx, LONG Cy, LONG x, LONG y )
  1991.   {
  1992.     INT Dx,Dy;
  1993.  
  1994.     Dx = x - Cx;
  1995.     Dy = Cy - y;
  1996.  
  1997.     DrawPixel ( Dest, Cx+Dx, Cy-Dy );
  1998.     DrawPixel ( Dest, Cx+Dx, Cy+Dy );
  1999.     DrawPixel ( Dest, Cx-Dx, Cy-Dy );
  2000.     DrawPixel ( Dest, Cx-Dx, Cy+Dy );
  2001.   } // End of DrawEllipsePoints for GRAFIX
  2002.  
  2003. VOID GRAFIX::DrawEllipse ( IMAGE *Dest, LONG Cx, LONG Cy, LONG Rx, LONG Ry )
  2004.   {
  2005.     LONG RsqX,RsqY;
  2006.     LONG RsqXY;
  2007.     LONG X2,Y2;
  2008.     LONG x,y;
  2009.     LONG MidTest;
  2010.  
  2011.     if ((Rx==0)||(Ry==0))
  2012.       return;
  2013.  
  2014.     RsqX = Rx*Rx;
  2015.     RsqY = Ry*Ry;
  2016.     RsqXY = RsqX*RsqY;
  2017.     x = 0;
  2018.     y = Ry;
  2019.  
  2020.     // Midtest = a^2*x^2 + b^2*y^2 - a^2*b^2
  2021.     DrawEllipsePoint ( Dest, Cx, Cy, x+Cx,
  2022.                        Cy-y );
  2023.  
  2024.     Y2 = y*y;
  2025.     while ((x*RsqY)<=(y*RsqX))
  2026.       {
  2027.         x++;
  2028.         X2 = x*x;
  2029.         MidTest = RsqY*X2+RsqX*Y2 - RsqXY;
  2030.         if (MidTest>=0)
  2031.           {
  2032.             y--;
  2033.             Y2 = y*y;
  2034.           } // End if
  2035.         DrawEllipsePoint ( Dest, Cx, Cy, x+Cx,
  2036.                            Cy-y );
  2037.       } // End while
  2038.  
  2039.     while (y>=0)
  2040.       {
  2041.         y--;
  2042.         Y2 = y*y;
  2043.         MidTest = RsqY*X2+RsqX*Y2 - RsqXY;
  2044.         if (MidTest<0)
  2045.           {
  2046.             x++;
  2047.             X2 = x*x;
  2048.           } // End if
  2049.         DrawEllipsePoint ( Dest, Cx, Cy, x+Cx,
  2050.                            Cy-y );
  2051.       } // End while
  2052.   } // End of DrawEllipse for GRAFIX
  2053.  
  2054. VOID GRAFIX::DrawEllipse ( HDISPLAY hDisplay, LONG Cx, LONG Cy, LONG Rx, LONG Ry )
  2055.   {
  2056.     if (DisplayDriver==NULL)
  2057.       return;
  2058.     DisplayDriver->DrawEllipse ( hDisplay, Cx, Cy, Rx, Ry, FGColor );
  2059.   } // End of DrawEllipse for GRAFIX
  2060.  
  2061. VOID GRAFIX::DrawHorizLine ( IMAGE *Dest, LONG x1, LONG x2, LONG y )
  2062.   {
  2063.     RECTANGLE ViewPort;
  2064.  
  2065.     ViewPort = Dest->GetViewPort ();
  2066.  
  2067.     if (x1>x2)
  2068.       SwapValue ( &x1, &x2 );
  2069.  
  2070.     if (x1<ViewPort.x1)
  2071.       x1 = ViewPort.x1;
  2072.     else if (x1>ViewPort.x2)
  2073.       return;
  2074.  
  2075.     if (x2<ViewPort.x1)
  2076.       return;
  2077.     else if (x2>ViewPort.x2)
  2078.       x2 = ViewPort.x2;
  2079.  
  2080.     if (y<ViewPort.y1)
  2081.       y = ViewPort.y1;
  2082.     else if (y>ViewPort.y2)
  2083.       return;
  2084.  
  2085.     INT Wd;
  2086.  
  2087.     Wd = x2 - x1 + 1;
  2088.  
  2089.     BYTE *Buffer = Dest->SetOffset ( x1, y );
  2090.  
  2091.     memset ( Buffer, BGColor, Wd );
  2092.   } // End of DrawHorizLine for GRAFIX
  2093.  
  2094. VOID GRAFIX::FillEllipsePoint ( IMAGE *Dest, LONG Cx, LONG Cy, LONG x, LONG y )
  2095.   {
  2096.     INT Dx,Dy;
  2097.  
  2098.     Dx = x - Cx;
  2099.     Dy = Cy - y;
  2100.  
  2101.     DrawHorizLine ( Dest, Cx-Dx, Cx+Dx, Cy-Dy );
  2102.     DrawHorizLine ( Dest, Cx-Dx, Cx+Dx, Cy+Dy );
  2103.   } // End of FillEllipsePoints for GRAFIX
  2104.  
  2105. VOID GRAFIX::FillEllipse ( IMAGE *Dest, LONG Cx, LONG Cy, LONG Rx, LONG Ry )
  2106.   {
  2107.     LONG RsqX,RsqY;
  2108.     LONG RsqXY;
  2109.     LONG X2,Y2;
  2110.     LONG x,y;
  2111.     LONG MidTest;
  2112.  
  2113.     if ((Rx==0)||(Ry==0))
  2114.       return;
  2115.  
  2116.     RsqX = Rx*Rx;
  2117.     RsqY = Ry*Ry;
  2118.     RsqXY = RsqX*RsqY;
  2119.     x = 0;
  2120.     y = Ry;
  2121.  
  2122.     // Midtest = a^2*x^2 + b^2*y^2 - a^2*b^2
  2123.     FillEllipsePoint ( Dest, Cx, Cy, x+Cx,
  2124.                        Cy-y );
  2125.  
  2126.     Y2 = y*y;
  2127.     while ((x*RsqY)<=(y*RsqX))
  2128.       {
  2129.         x++;
  2130.         X2 = x*x;
  2131.         MidTest = RsqY*X2+RsqX*Y2 - RsqXY;
  2132.         if (MidTest>=0)
  2133.           {
  2134.             y--;
  2135.             Y2 = y*y;
  2136.           } // End if
  2137.         FillEllipsePoint ( Dest, Cx, Cy, x+Cx,
  2138.                            Cy-y );
  2139.       } // End while
  2140.  
  2141.     while (y>=0)
  2142.       {
  2143.         y--;
  2144.         Y2 = y*y;
  2145.         MidTest = RsqY*X2+RsqX*Y2 - RsqXY;
  2146.         if (MidTest<0)
  2147.           {
  2148.             x++;
  2149.             X2 = x*x;
  2150.           } // End if
  2151.         FillEllipsePoint ( Dest, Cx, Cy, x+Cx,
  2152.                            Cy-y );
  2153.       } // End while
  2154.   } // End of FillEllipse for GRAFIX
  2155.  
  2156. VOID GRAFIX::FillEllipse ( HDISPLAY hDisplay, LONG Cx, LONG Cy, LONG Rx, LONG Ry )
  2157.   {
  2158.     if (DisplayDriver==NULL)
  2159.       return;
  2160.     DisplayDriver->FillEllipse ( hDisplay, Cx, Cy, Rx, Ry, BGColor );
  2161.   } // End of FillEllipse for GRAFIX
  2162.  
  2163. VOID GRAFIX::DrawText ( HDISPLAY hDisplay, STRING Text, LONG x, LONG y )
  2164.   {
  2165.     if (DisplayDriver==NULL)
  2166.       return;
  2167.     DisplayDriver->DrawText ( hDisplay, Text, x, y, FGColor );
  2168.   } // End of DrawText for GRAFIX
  2169.  
  2170.  
  2171.