home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c031 / 4.ddi / SAMPLES / GRAPHICS / TURTLE.C$ / TURTLE
Encoding:
Text File  |  1992-02-27  |  13.4 KB  |  459 lines

  1. /* TURTLE - Module of functions to implement turtle graphics. Turtle graphics
  2.  * is a model for specifying relative movements of an imaginary pointer whose
  3.  * direction, color, visibility, and other attributes are given default
  4.  * values using turtle functions. To use the turtle module, include TURTLE.H
  5.  * in your program. The following functions (many defined as macros)
  6.  * are public :
  7.  *
  8.  *   InitTurtle      - Initiate turtle graphics
  9.  *   Home            - Reset turtle defaults
  10.  *   PenDown         - Set pen visibility
  11.  *   SetFill         - Set fill state
  12.  *   PenColor        - Set pen color index
  13.  *   BorderColor     - Set border color index
  14.  *   Turn            - Set direction relative to current
  15.  *   TurnTo          - Set absolute direction
  16.  *   Move            - Move in current direction
  17.  *   MoveTo          - Move to absolute location
  18.  *   Poly            - Draw a polygon
  19.  *   Circle          - Draw a circle with center at current location
  20.  *   Ellipse         - Draw an ellipse with center at current location
  21.  *   Rectangle       - Draw a rectangle with center at current location
  22.  *   ImageSize       - Get size of rectangle with top-left origin
  23.  *   GetImage        - Get rectangular image with top-left origin
  24.  *   PutImage        - Put rectangular image with top-left origin
  25.  *   FillIn          - Fill from the current location to border
  26.  *   NextColorIndex  - Rotate to next color index
  27.  *   NextColorValue  - Rotate to next color value
  28.  *   OnScreen        - Report whether current location is on screen
  29.  *   RGB             - Combine Red, Green, and Blue elements of color value
  30.  *
  31.  * The TURTLE structure, the "tc" global variable (having TURTLE type), and
  32.  * "vlColors" variable are defined. However, these are not normally used
  33.  * directly by the programmer.
  34.  */
  35.  
  36. #include <graph.h>
  37. #include <math.h>
  38. #include <string.h>
  39. #include "turtle.h"
  40.  
  41. #define PI       3.141593
  42.  
  43. long cvlColors[256];            /* Array of long color values              */
  44.  
  45. TURTLE tc = { 1.39 };    /* Initial aspect - adjust for your screen */
  46.  
  47. /* InitTurtle - Initializes all turtle defaults. This function should be
  48.  * called at least once (after _setvideomode and _getvideoconfig) and
  49.  * additionally after any change to a new graphics mode.
  50.  *
  51.  * Params: vc - pointer to videoconfig structure
  52.  *
  53.  * Return: 0 if fail, 1 if success
  54.  *
  55.  * Uses:   tc structure variable cvlColors array
  56.  */
  57. short InitTurtle( struct videoconfig *vc )
  58. {
  59.     int i;
  60.     unsigned cvuInc, cvuRed, cvuGreen, cvuBlue; /* Unsigned portions of */
  61.     static int mode = -1;                       /*   color values       */
  62.  
  63.     /* Terminate if not graphics mode. */
  64.     if( !vc->numxpixels )
  65.         return 0;
  66.  
  67.     /* If mode has changed, set window coordinates. */
  68.     if( mode != vc->mode )
  69.     {
  70.         mode = vc->mode;
  71.         tc.xsLeft = tc.ysTop = 0;
  72.         tc.xsRight = vc->numxpixels - 1;
  73.         tc.ysBot = vc->numypixels - 1;
  74.     }
  75.  
  76.     /* Set palette flag. */
  77.     switch( vc->adapter )
  78.     {
  79.         case _MDPA:
  80.         case _CGA:
  81.         case _OCGA:
  82.         case _HGC:
  83.             tc.fPalette = FALSE;
  84.             break;
  85.         default:
  86.             tc.fPalette = TRUE;
  87.             break;
  88.     }
  89.  
  90.     /* Set palette defaults. */
  91.     switch( vc->mode )
  92.     {
  93.         case _HRESBW:
  94.         case _HERCMONO:
  95.         case _ERESNOCOLOR:
  96.         case _ORESCOLOR:
  97.         case _VRES2COLOR:
  98.             tc.ccv = 0;
  99.             tc.cci = 2;
  100.             return Home();
  101.         case _MRES256COLOR:        /* Active bits in this order:          */
  102.         case _ORES256COLOR:
  103.         case _VRES256COLOR:
  104.         case _SRES256COLOR:
  105.         case _XRES256COLOR:
  106.         case _ZRES256COLOR:
  107.             cvuInc = 12;
  108.             tc.ccv = tc.cci = 125; /* ???????? ??bbbbbb ??gggggg ??rrrrrr */
  109.             break;
  110.         case _ERESCOLOR:
  111.             if( vc->memory == 64 )
  112.             {
  113.                 cvuInc = 32;
  114.                 tc.ccv = 16;       /* ???????? ??????Bb ??????Gg ??????Rr */
  115.                 tc.cci = 4;
  116.                 break;
  117.             } /* Else fall through */
  118.         case _VRES16COLOR:
  119.         case _SRES16COLOR:
  120.         case _XRES16COLOR:
  121.         case _ZRES16COLOR:
  122.             cvuInc = 16;
  123.             tc.ccv = 64;           /* ???????? ??????bb ??????gg ??????rr */
  124.             tc.cci = 16;
  125.             break;
  126.         case _MRES4COLOR:
  127.         case _MRESNOCOLOR:
  128.             cvuInc = 32;
  129.             tc.ccv = 16;           /* ???????? ??????Bb ??????Gg ??????Rr */
  130.             tc.cci = 4;
  131.             break;
  132.         case _MRES16COLOR:
  133.         case _HRES16COLOR:
  134.             cvuInc = 32;
  135.             tc.cci = tc.ccv = 16;  /* ???????? ??????Bb ??????Gg ??????Rr */
  136.             break;
  137.     }
  138.  
  139.     /* Fill palette arrays. */
  140.     for( i = 0, cvuBlue = 0; cvuBlue < 64; cvuBlue += cvuInc )
  141.         for( cvuGreen = 0; cvuGreen < 64; cvuGreen += cvuInc )
  142.             for( cvuRed = 0; cvuRed < 64; cvuRed += cvuInc )
  143.                 {
  144.                     cvlColors[i] = RGB( cvuRed, cvuGreen, cvuBlue );
  145.                     /* Special case of 6 bits for 16 colors (RGBI).
  146.                      * If both bits are on for any color, intensity is set.
  147.                      * If one bit is set for a color, that color is on.
  148.                      */
  149.                     if( cvuInc == 32 )
  150.                         cvlColors[i + 8] = cvlColors[i] | (cvlColors[i] >> 1);
  151.                     i++;
  152.                 }
  153.     cvlColors[tc.ccv - 1] = _BRIGHTWHITE;
  154.     NextColorValue( DEFAULT );
  155.     return Home();
  156. }
  157.  
  158. /* Home - Resets turtle defaults. This function can be called if you have
  159.  * not changed the video mode, but you want to put the turtle back in
  160.  * the center of the window and restore all defaults. For example, you can
  161.  * change the absolute window corners and then call it to set a new
  162.  * turtle window.
  163.  *
  164.  * Params: None
  165.  *
  166.  * Return: 0 if fail, 1 if success
  167.  *
  168.  * Uses:   tc
  169.  */
  170. short Home()
  171. {
  172.     struct _wxycoord xy1, xy2;
  173.  
  174.     _setviewport( tc.xsLeft, tc.ysTop, tc.xsRight, tc.ysBot );
  175.  
  176.     /* Set the window based on screen height 1000 and width based on
  177.      * aspect ratio.
  178.      */
  179.     tc.yMax = 500.0;
  180.     tc.xMax = tc.yMax * tc.yxRatio;
  181.     if( !_setwindow( FALSE, -tc.xMax, -tc.yMax, tc.xMax, tc.yMax ) )
  182.         return 0;
  183.  
  184.     /* Calculate the unit size of 1 pixel using Y axis. */
  185.     xy1 = _getwindowcoord( 1, 1 );
  186.     xy2 = _getwindowcoord( 1, 2 );
  187.     tc.yUnit = xy2.wy - xy1.wy;
  188.  
  189.     /* Set defaults for current pixel, angle, pen state and fill state. */
  190.     tc.xCur = tc.yCur = 0.0;
  191.     _moveto_w( tc.xCur, tc.yCur );
  192.     TurnTo( 0 );
  193.     PenDown( TRUE );
  194.     SetFill( FALSE );
  195.  
  196.     /* Make white the last color index and set pen and border to it. */
  197.     _remappalette( WHITE, _BRIGHTWHITE );
  198.     BorderColor( WHITE );
  199.     PenColor( WHITE );
  200.     _setbkcolor( _BLACK );
  201.     return 1;
  202. }
  203.  
  204. /* PenDown - Sets the visibility of the pen used by Move and MoveTo. The
  205.  * state can be TRUE (visible), FALSE (invisible), or DEFAULT (return
  206.  * current without changing).
  207.  *
  208.  * Params: fPenDown
  209.  *
  210.  * Return: current pen state
  211.  *
  212.  * Uses:   tc
  213.  */
  214. int PenDown( int fPenDown )
  215. {
  216.     switch( fPenDown )
  217.     {
  218.         case DEFAULT:
  219.             break;
  220.         case FALSE:
  221.             tc.fPenDown = FALSE;
  222.             break;
  223.         default:
  224.             tc.fPenDown = TRUE;
  225.             break;
  226.     }
  227.     return tc.fPenDown;
  228. }
  229.  
  230. /* SetFill - Determines the state of filling figures such as Rectangle,
  231.  * Circle, and Ellipse. State can be TRUE (fill inside), FALSE (border
  232.  * only), or DEFAULT (return current fill state).
  233.  *
  234.  * Params: fFill
  235.  *
  236.  * Return: current fill state
  237.  *
  238.  * Uses:   tc
  239.  */
  240. short SetFill( short fFill )
  241. {
  242.     switch( fFill )
  243.     {
  244.         case DEFAULT:
  245.             break;
  246.         case _GBORDER:
  247.         case FALSE:
  248.             tc.fFill = _GBORDER;
  249.             break;
  250.         default:
  251.             tc.fFill = _GFILLINTERIOR;
  252.             break;
  253.     }
  254.     return tc.fFill;
  255. }
  256.  
  257. /* PenColor - Sets the color index of the pen.
  258.  *
  259.  * Params: ciCur - any color index of DEFAULT to return without changing
  260.  *
  261.  * Return: current pen color index
  262.  *
  263.  * Uses:   tc
  264.  */
  265. short PenColor( short ciCur )
  266. {
  267.     if( ciCur != DEFAULT )
  268.         _setcolor( tc.ciCur = ciCur );
  269.     return tc.ciCur;
  270. }
  271.  
  272. /* BorderColor - Sets the color index of the border that will be recognized
  273.  * by fills.
  274.  *
  275.  * Params: ciBorder - any color index of DEFAULT to return without changing
  276.  *
  277.  * Return: current border color index
  278.  *
  279.  * Uses:   tc
  280.  */
  281. short BorderColor( short border )
  282. {
  283.     if( border != DEFAULT )
  284.         tc.ciBorder = border;
  285.     return tc.ciBorder;
  286. }
  287.  
  288. /* Turn - Sets a new direction relative to the current direction.
  289.  *
  290.  * Params: angCur - a positive (clockwise) or negative (counterclockwise)
  291.  *           angle in degrees
  292.  *
  293.  * Return: new current absolute angle
  294.  *
  295.  * Uses:   tc
  296.  */
  297. short Turn( short angCur )
  298. {
  299.     return( tc.angCur = ((tc.angCur + angCur) % CIRCUMFERENCE) );
  300. }
  301.  
  302. /* TurnTo - Sets a new absolute direction.
  303.  *
  304.  * Params: angCur - a positive (clockwise) or negative (counterclockwise)
  305.  *           angle in degrees (0 points to 12 o'clock)
  306.  *
  307.  * Return: new current absolute angle
  308.  *
  309.  * Uses:   tc
  310.  */
  311. short TurnTo( short angCur )
  312. {
  313.     if( angCur < 0 )
  314.         return( tc.angCur = 360 - (angCur % CIRCUMFERENCE) );
  315.     else
  316.         return( tc.angCur = angCur % CIRCUMFERENCE );
  317. }
  318.  
  319. /* Move - Moves from the current position in the current direction for a
  320.  * specified distance. A line is drawn if the pen is down. The current
  321.  * position is reset to the destination.
  322.  *
  323.  * Params: dxy - difference between current xy and new xy
  324.  *
  325.  * Return: 0 if new position is off screen, nonzero if on screen
  326.  *
  327.  * Uses:   tc
  328.  */
  329. short Move( double dxy )
  330. {
  331.     double dx, dy;          /* Differences of X and Y */
  332.     double angT;
  333.  
  334.     /* Calculate new X and Y positions. */
  335.     angT = (tc.angCur - 90) * (PI / HALFCIRCUMFERENCE);
  336.     dx = dxy * cos( angT );
  337.     dy = dxy * sin( angT );
  338.  
  339.     /* Move, drawing if pen down, then update position */
  340.     if( tc.fPenDown )
  341.         _lineto_w( tc.xCur + dx, tc.yCur + dy );
  342.     else
  343.         _moveto_w( tc.xCur + dx, tc.yCur + dy );
  344.     tc.xCur += dx;
  345.     tc.yCur += dy;
  346.     return OnScreen();
  347. }
  348.  
  349. /* MoveTo - Moves from the current position to a specified position. A
  350.  * line is drawn if the pen is down. The current position is reset to the
  351.  * destination. The current direction is not changed.
  352.  *
  353.  * Params: x and y - destination position
  354.  *
  355.  * Return: 0 if new position is off screen, nonzero if on screen
  356.  *
  357.  * Uses:   tc
  358.  */
  359. short MoveTo( double x, double y )
  360. {
  361.     if( tc.fPenDown )
  362.         _lineto_w( x, y );
  363.     else
  364.         _moveto_w( x, y );
  365.     tc.xCur = x;
  366.     tc.yCur = y;
  367.     return OnScreen();
  368. }
  369.  
  370. /* Poly - Draws a polygon.
  371.  *
  372.  * Params: cSide - count of polygon sides
  373.  *         dxySide - distance of each side
  374.  *
  375.  * Return: 0 if any part of polygon is off screen, nonzero if on screen
  376.  */
  377. short Poly( int cSide, double dxySide )
  378. {
  379.     short i, angT;
  380.     int fPen, ret = TRUE;
  381.  
  382.     /* Make sure pen is down (restore pen state when done). */
  383.     fPen = PenDown( TRUE );
  384.  
  385.     /* Calculate angle, then draw each side. */
  386.     angT = 360 / cSide;
  387.     for( i = 1; i <= cSide; i++ )
  388.     {
  389.         ret = Move( dxySide ) && ret;
  390.         Turn( angT );
  391.     }
  392.     PenDown( fPen );
  393.     return ret;
  394. }
  395.  
  396. /* NextColorIndex - Rotate to next color index. First attribute (normally
  397.  * background) and last attribute (white) are skipped.
  398.  *
  399.  * Params: ciCur - Specify DEFAULT to use color index from last call,
  400.  *           or specify a new color to rotate from
  401.  *
  402.  * Return: rotated color index
  403.  *
  404.  * Uses:   tc
  405.  */
  406. short NextColorIndex( short ciCur )
  407. {
  408.     static short ciPrev = 0;    /* Static to retain index between calls */
  409.  
  410.     /* Assign new current if given. */
  411.     if( ciCur != DEFAULT )
  412.         ciPrev = ciCur;
  413.  
  414.     /* Toggle for two-color modes, rotate for multi-color modes. */
  415.     if( tc.cci == 2 )
  416.         return( ciPrev = !ciPrev );
  417.     else
  418.         return( ciPrev = (++ciPrev % (tc.cci - 1)) );
  419. }
  420.  
  421. /* NextColorValue - Rotate to next color value for adapters (EGA
  422.  * and higher) that support remappable palettes.
  423.  *
  424.  * Params: fAction - DEFAULT (rotate all) or LIMITED (rotate first 14 only)
  425.  *
  426.  * Return: None
  427.  *
  428.  * Uses:   tc
  429.  */
  430. void NextColorValue( int fAction )
  431. {
  432.     static unsigned icvCur = 1; /* Current index into color value array */
  433.     static unsigned ciCur = 1;  /* Current color index                  */
  434.     unsigned icvT;              /* Temporary index into color values    */
  435.     int i;
  436.  
  437.     /* Ignore modes with no palette values. */
  438.     if( !tc.fPalette || !tc.ccv )
  439.         return;
  440.  
  441.     /* Increment and rotate color value index. */
  442.     icvT = (++icvCur % (tc.ccv - 2)) + 1;
  443.  
  444.  
  445.     /* DEFAULT - Remap all color indexes, 14 at a time. For most modes,
  446.      * this is all the indexes  except first and last. For 256-color
  447.      * mode, rotating all available indexes would be too slow.
  448.      */
  449.     if( fAction == DEFAULT )
  450.         for( i = 1; i <= 14; i++ )
  451.             _remappalette( (ciCur++ % (tc.cci - 2)) + 1,
  452.                            cvlColors[(icvT++ % (tc.ccv - 2)) + 1] );
  453.  
  454.     /* LIMITED - Rotate only the first 14 color indexes. */
  455.     else
  456.         for( i = 1; i <= 14; i++ )
  457.             _remappalette( i, cvlColors[(icvT++ % (tc.ccv - 1)) + 1] );
  458. }
  459.