home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c034 / 4.ddi / SOURCE / TURTLE.C$ / TURTLE.bin
Encoding:
Text File  |  1989-12-12  |  13.1 KB  |  450 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.             cvuInc = 12;
  103.             tc.ccv = tc.cci = 125; /* ???????? ??bbbbbb ??gggggg ??rrrrrr */
  104.             break;
  105.         case _ERESCOLOR:
  106.             if( vc->memory == 64 )
  107.             {
  108.                 cvuInc = 32;
  109.                 tc.ccv = 16;       /* ???????? ??????Bb ??????Gg ??????Rr */
  110.                 tc.cci = 4;
  111.                 break;
  112.             } /* Else fall through */
  113.         case _VRES16COLOR:
  114.             cvuInc = 16;
  115.             tc.ccv = 64;           /* ???????? ??????bb ??????gg ??????rr */
  116.             tc.cci = 16;
  117.             break;
  118.         case _MRES4COLOR:
  119.         case _MRESNOCOLOR:
  120.             cvuInc = 32;
  121.             tc.ccv = 16;           /* ???????? ??????Bb ??????Gg ??????Rr */
  122.             tc.cci = 4;
  123.             break;
  124.         case _MRES16COLOR:
  125.         case _HRES16COLOR:
  126.             cvuInc = 32;
  127.             tc.cci = tc.ccv = 16;  /* ???????? ??????Bb ??????Gg ??????Rr */
  128.             break;
  129.     }
  130.  
  131.     /* Fill palette arrays. */
  132.     for( i = 0, cvuBlue = 0; cvuBlue < 64; cvuBlue += cvuInc )
  133.         for( cvuGreen = 0; cvuGreen < 64; cvuGreen += cvuInc )
  134.             for( cvuRed = 0; cvuRed < 64; cvuRed += cvuInc )
  135.                 {
  136.                     cvlColors[i] = RGB( cvuRed, cvuGreen, cvuBlue );
  137.                     /* Special case of 6 bits for 16 colors (RGBI).
  138.                      * If both bits are on for any color, intensity is set.
  139.                      * If one bit is set for a color, that color is on.
  140.                      */
  141.                     if( cvuInc == 32 )
  142.                         cvlColors[i + 8] = cvlColors[i] | (cvlColors[i] >> 1);
  143.                     i++;
  144.                 }
  145.     cvlColors[tc.ccv - 1] = _BRIGHTWHITE;
  146.     NextColorValue( DEFAULT );
  147.     return Home();
  148. }
  149.  
  150. /* Home - Resets turtle defaults. This function can be called if you have
  151.  * not changed the video mode, but you want to put the turtle back in
  152.  * the center of the window and restore all defaults. For example, you can
  153.  * change the absolute window corners and then call it to set a new
  154.  * turtle window.
  155.  *
  156.  * Params: None
  157.  *
  158.  * Return: 0 if fail, 1 if success
  159.  *
  160.  * Uses:   tc
  161.  */
  162. short Home()
  163. {
  164.     struct _wxycoord xy1, xy2;
  165.  
  166.     _setviewport( tc.xsLeft, tc.ysTop, tc.xsRight, tc.ysBot );
  167.  
  168.     /* Set the window based on screen height 1000 and width based on
  169.      * aspect ratio.
  170.      */
  171.     tc.yMax = 500.0;
  172.     tc.xMax = tc.yMax * tc.yxRatio;
  173.     if( !_setwindow( FALSE, -tc.xMax, -tc.yMax, tc.xMax, tc.yMax ) )
  174.         return 0;
  175.  
  176.     /* Calculate the unit size of 1 pixel using Y axis. */
  177.     xy1 = _getwindowcoord( 1, 1 );
  178.     xy2 = _getwindowcoord( 1, 2 );
  179.     tc.yUnit = xy2.wy - xy1.wy;
  180.  
  181.     /* Set defaults for current pixel, angle, pen state and fill state. */
  182.     tc.xCur = tc.yCur = 0.0;
  183.     _moveto_w( tc.xCur, tc.yCur );
  184.     TurnTo( 0 );
  185.     PenDown( TRUE );
  186.     SetFill( FALSE );
  187.  
  188.     /* Make white the last color index and set pen and border to it. */
  189.     _remappalette( WHITE, _BRIGHTWHITE );
  190.     BorderColor( WHITE );
  191.     PenColor( WHITE );
  192.     _setbkcolor( _BLACK );
  193.     return 1;
  194. }
  195.  
  196. /* PenDown - Sets the visibility of the pen used by Move and MoveTo. The
  197.  * state can be TRUE (visible), FALSE (invisible), or DEFAULT (return
  198.  * current without changing).
  199.  *
  200.  * Params: fPenDown
  201.  *
  202.  * Return: current pen state
  203.  *
  204.  * Uses:   tc
  205.  */
  206. int PenDown( int fPenDown )
  207. {
  208.     switch( fPenDown )
  209.     {
  210.         case DEFAULT:
  211.             break;
  212.         case FALSE:
  213.             tc.fPenDown = FALSE;
  214.             break;
  215.         default:
  216.             tc.fPenDown = TRUE;
  217.             break;
  218.     }
  219.     return tc.fPenDown;
  220. }
  221.  
  222. /* SetFill - Determines the state of filling figures such as Rectangle,
  223.  * Circle, and Ellipse. State can be TRUE (fill inside), FALSE (border
  224.  * only), or DEFAULT (return current fill state).
  225.  *
  226.  * Params: fFill
  227.  *
  228.  * Return: current fill state
  229.  *
  230.  * Uses:   tc
  231.  */
  232. short SetFill( short fFill )
  233. {
  234.     switch( fFill )
  235.     {
  236.         case DEFAULT:
  237.             break;
  238.         case _GBORDER:
  239.         case FALSE:
  240.             tc.fFill = _GBORDER;
  241.             break;
  242.         default:
  243.             tc.fFill = _GFILLINTERIOR;
  244.             break;
  245.     }
  246.     return tc.fFill;
  247. }
  248.  
  249. /* PenColor - Sets the color index of the pen.
  250.  *
  251.  * Params: ciCur - any color index of DEFAULT to return without changing
  252.  *
  253.  * Return: current pen color index
  254.  *
  255.  * Uses:   tc
  256.  */
  257. short PenColor( short ciCur )
  258. {
  259.     if( ciCur != DEFAULT )
  260.         _setcolor( tc.ciCur = ciCur );
  261.     return tc.ciCur;
  262. }
  263.  
  264. /* BorderColor - Sets the color index of the border that will be recognized
  265.  * by fills.
  266.  *
  267.  * Params: ciBorder - any color index of DEFAULT to return without changing
  268.  *
  269.  * Return: current border color index
  270.  *
  271.  * Uses:   tc
  272.  */
  273. short BorderColor( short border )
  274. {
  275.     if( border != DEFAULT )
  276.         tc.ciBorder = border;
  277.     return tc.ciBorder;
  278. }
  279.  
  280. /* Turn - Sets a new direction relative to the current direction.
  281.  *
  282.  * Params: angCur - a positive (clockwise) or negative (counterclockwise)
  283.  *           angle in degrees
  284.  *
  285.  * Return: new current absolute angle
  286.  *
  287.  * Uses:   tc
  288.  */
  289. short Turn( short angCur )
  290. {
  291.     return( tc.angCur = ((tc.angCur + angCur) % CIRCUMFERENCE) );
  292. }
  293.  
  294. /* TurnTo - Sets a new absolute direction.
  295.  *
  296.  * Params: angCur - a positive (clockwise) or negative (counterclockwise)
  297.  *           angle in degrees (0 points to 12 o'clock)
  298.  *
  299.  * Return: new current absolute angle
  300.  *
  301.  * Uses:   tc
  302.  */
  303. short TurnTo( short angCur )
  304. {
  305.     if( angCur < 0 )
  306.         return( tc.angCur = 360 - (angCur % CIRCUMFERENCE) );
  307.     else
  308.         return( tc.angCur = angCur % CIRCUMFERENCE );
  309. }
  310.  
  311. /* Move - Moves from the current position in the current direction for a
  312.  * specified distance. A line is drawn if the pen is down. The current
  313.  * position is reset to the destination.
  314.  *
  315.  * Params: dxy - difference between current xy and new xy
  316.  *
  317.  * Return: 0 if new position is off screen, nonzero if on screen
  318.  *
  319.  * Uses:   tc
  320.  */
  321. short Move( double dxy )
  322. {
  323.     double dx, dy;          /* Differences of X and Y */
  324.     double angT;
  325.  
  326.     /* Calculate new X and Y positions. */
  327.     angT = (tc.angCur - 90) * (PI / HALFCIRCUMFERENCE);
  328.     dx = dxy * cos( angT );
  329.     dy = dxy * sin( angT );
  330.  
  331.     /* Move, drawing if pen down, then update position */
  332.     if( tc.fPenDown )
  333.         _lineto_w( tc.xCur + dx, tc.yCur + dy );
  334.     else
  335.         _moveto_w( tc.xCur + dx, tc.yCur + dy );
  336.     tc.xCur += dx;
  337.     tc.yCur += dy;
  338.     return OnScreen();
  339. }
  340.  
  341. /* MoveTo - Moves from the current position to a specified position. A
  342.  * line is drawn if the pen is down. The current position is reset to the
  343.  * destination. The current direction is not changed.
  344.  *
  345.  * Params: x and y - destination position
  346.  *
  347.  * Return: 0 if new position is off screen, nonzero if on screen
  348.  *
  349.  * Uses:   tc
  350.  */
  351. short MoveTo( double x, double y )
  352. {
  353.     if( tc.fPenDown )
  354.         _lineto_w( x, y );
  355.     else
  356.         _moveto_w( x, y );
  357.     tc.xCur = x;
  358.     tc.yCur = y;
  359.     return OnScreen();
  360. }
  361.  
  362. /* Poly - Draws a polygon.
  363.  *
  364.  * Params: cSide - count of polygon sides
  365.  *         dxySide - distance of each side
  366.  *
  367.  * Return: 0 if any part of polygon is off screen, nonzero if on screen
  368.  */
  369. short Poly( int cSide, double dxySide )
  370. {
  371.     short i, angT, fPen, ret = TRUE;
  372.  
  373.     /* Make sure pen is down (restore pen state when done). */
  374.     fPen = PenDown( TRUE );
  375.  
  376.     /* Calculate angle, then draw each side. */
  377.     angT = 360 / cSide;
  378.     for( i = 1; i <= cSide; i++ )
  379.     {
  380.         ret = Move( dxySide ) && ret;
  381.         Turn( angT );
  382.     }
  383.     PenDown( fPen );
  384.     return ret;
  385. }
  386.  
  387. /* NextColorIndex - Rotate to next color index. First attribute (normally
  388.  * background) and last attribute (white) are skipped.
  389.  *
  390.  * Params: ciCur - Specify DEFAULT to use color index from last call,
  391.  *           or specify a new color to rotate from
  392.  *
  393.  * Return: rotated color index
  394.  *
  395.  * Uses:   tc
  396.  */
  397. short NextColorIndex( short ciCur )
  398. {
  399.     static short ciPrev = 0;    /* Static to retain index between calls */
  400.  
  401.     /* Assign new current if given. */
  402.     if( ciCur != DEFAULT )
  403.         ciPrev = ciCur;
  404.  
  405.     /* Toggle for two-color modes, rotate for multi-color modes. */
  406.     if( tc.cci == 2 )
  407.         return( ciPrev = !ciPrev );
  408.     else
  409.         return( ciPrev = (++ciPrev % (tc.cci - 1)) );
  410. }
  411.  
  412. /* NextColorValue - Rotate to next color value for adapters (EGA
  413.  * and higher) that support remappable palettes.
  414.  *
  415.  * Params: fAction - DEFAULT (rotate all) or LIMITED (rotate first 14 only)
  416.  *
  417.  * Return: None
  418.  *
  419.  * Uses:   tc
  420.  */
  421. void NextColorValue( int fAction )
  422. {
  423.     static int icvCur = 1;  /* Current index into color value array */
  424.     static int ciCur = 1;   /* Current color index                  */
  425.     int icvT;               /* Temporary index into color values    */
  426.     int i;
  427.  
  428.     /* Ignore modes with no palette values. */
  429.     if( !tc.fPalette || !tc.ccv )
  430.         return;
  431.  
  432.     /* Increment and rotate color value index. */
  433.     icvT = (++icvCur % (tc.ccv - 2)) + 1;
  434.  
  435.  
  436.     /* DEFAULT - Remap all color indexes, 14 at a time. For most modes,
  437.      * this is all the indexes  except first and last. For 256-color
  438.      * mode, rotating all available indexes would be too slow.
  439.      */
  440.     if( fAction == DEFAULT )
  441.         for( i = 1; i <= 14; i++ )
  442.             _remappalette( (ciCur++ % (tc.cci - 2)) + 1,
  443.                            cvlColors[(icvT++ % (tc.ccv - 2)) + 1] );
  444.  
  445.     /* LIMITED - Rotate only the first 14 color indexes. */
  446.     else
  447.         for( i = 1; i <= 14; i++ )
  448.             _remappalette( i, cvlColors[(icvT++ % (tc.ccv - 1)) + 1] );
  449. }
  450.