home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the DOOM Programming Gurus / Tricks_of_the_Doom_Programming_Gurus.iso / bonus / editors / deth / source / gfx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-01  |  15.6 KB  |  639 lines

  1. /*
  2.    Doom Editor Utility, by Brendon Wyber and RaphaĆ«l Quinet.
  3.    
  4.    You are allowed to use any parts of this code in another program, as
  5.    long as you give credits to the authors in the documentation and in
  6.    the program itself.  Read the file README.1ST for more information.
  7.    
  8.    This program comes with absolutely no warranty.
  9.    
  10.    GFX.C - Graphics routines.
  11.    */
  12.  
  13. /* the includes */
  14. #include "deu.h"
  15. #include <math.h>
  16. #include <dos.h>
  17.  
  18. #define BCabs(x)        ((x < 0) ? -(x) : (x))
  19.  
  20. BCINT Palette[32];
  21.  
  22. /* if your graphics driver doesn't like circles, draw squares instead */
  23.  
  24. void circle_or_square( int x, int y, int r)
  25. {
  26.     if(square_circles) {
  27.     line( x - r, y - r, x - r, y + r);
  28.     line( x - r, y + r, x + r, y + r);
  29.     line( x + r, y + r, x + r, y - r);
  30.     line( x + r, y - r, x - r, y - r);
  31.     }
  32.     else
  33.     circle(x, y, r);
  34. }
  35.  
  36.  
  37. #define BGI_PATH "."
  38.  
  39. /* the global variables */
  40. BCINT GfxMode = 0;        /* graphics mode number, or 0 for text */
  41. /* 1 = 320x200, 2 = 640x480, 3 = 800x600, 4 = 1024x768 */
  42. /* positive = 16 colors, negative = 256 colors */
  43. BCINT OrigX;                /* the X origin */
  44. BCINT OrigY;                /* the Y origin */
  45. float Scale;                /* the scale value */
  46. BCINT PointerX;                /* X position of pointer */
  47. BCINT PointerY;                /* Y position of pointer */
  48. BCINT ScrMaxX;                /* maximum X screen coord */
  49. BCINT ScrMaxY;                /* maximum Y screen coord */
  50. BCINT ScrCenterX;        /* X coord of screen center */
  51. BCINT ScrCenterY;        /* Y coord of screen center */
  52.  
  53.  
  54. #if defined(__GNUC__)
  55. static int res[5][3] = {{640,480,16},{320,200,256},{640,480,256},
  56.                 {800,600,256},{1024,768,256}};
  57. #endif
  58.  
  59.  
  60. /*
  61.    initialise the graphics display
  62.    */
  63.  
  64. void InitGfx()
  65. {
  66.     static Bool firsttime = TRUE;
  67.     static int  gdriver;
  68.     static int  gmode;
  69.     int         errorcode = grNoInitGraph;
  70.     
  71.     printf( "Switching to graphics mode...\n");
  72.     
  73. #if defined(__TURBOC__)
  74.     
  75.     if (firsttime) {
  76.     if (VideoMode > 0) {
  77.         gdriver = installuserdriver( BGIDriver, NULL);
  78.         gmode = VideoMode;
  79.         initgraph( &gdriver, &gmode, BGI_PATH);
  80.         errorcode = graphresult();
  81.     }
  82.     if (errorcode != grOk) {
  83.         gdriver = VGA;
  84.         gmode = VGAHI;
  85.     }
  86.     }
  87.     if (gdriver == VGA || !firsttime) {
  88.     initgraph( &gdriver, &gmode, BGI_PATH);
  89.     errorcode = graphresult();
  90.     if (errorcode != grOk)
  91.         ProgError( "graphics error: %s", grapherrormsg( errorcode));
  92.     }
  93.     if (gdriver == VGA)
  94.     GfxMode = 2; /* 640x480x16 */
  95.     else {
  96.     GfxMode = -gmode; /* 640x480x256, 800x600x256, or 1024x768x256 */
  97.     SetDoomPalette( 0);
  98.     }
  99.     
  100. #elif defined(__GNUC__)
  101.     
  102.     FakeCursor = FALSE;
  103.     
  104.     if (VideoMode < 0 || VideoMode > 4)
  105.     VideoMode = 0;
  106.     set_BGI_mode_whc( &gdriver, &gmode, res[VideoMode][0], res[VideoMode][1], res[VideoMode][2]);
  107.     initgraph( &gdriver, &gmode, BGI_PATH);
  108.     errorcode = graphresult();
  109.     if(errorcode != grOk)
  110.     ProgError( "graphics error: %s", grapherrormsg( errorcode));
  111.     
  112.     if (VideoMode == 0)
  113.     GfxMode = 2; /* 640x480x16 */
  114.     else {
  115.     GfxMode = -VideoMode; /* 640x480x256, 800x600x256, or 1024x768x256 */
  116.     SetDoomPalette( 0);
  117.     }
  118. #endif
  119.     
  120.     setlinestyle( 0, 0, 1);
  121.     setbkcolor( TranslateToGameColor( BLACK));
  122.     settextstyle( 0, 0, 1);
  123.     firsttime = FALSE;
  124.     ScrMaxX = getmaxx();
  125.     ScrMaxY = getmaxy();
  126.     ScrCenterX = ScrMaxX / 2;
  127.     ScrCenterY = ScrMaxY / 2;
  128. }
  129.  
  130.  
  131.  
  132. /*
  133.    terminate the graphics display
  134.    */
  135.  
  136. void TermGfx()
  137. {
  138.     if (GfxMode) {
  139.     closegraph();
  140.     GfxMode = 0;
  141.     }
  142. }
  143.  
  144.  
  145.  
  146. /*
  147.    switch from VGA 16 colours to VGA 256 colours
  148.    */
  149.  
  150. Bool SwitchToVGA256()
  151. {
  152.     static int gdriver = -1;
  153.     int gmode, errorcode;
  154.     
  155. #if defined(__TURBOC__)
  156.     
  157.     if (GfxMode > 0 && gdriver != VGA) /* if 16 colors and not failed before */ {
  158.     if (gdriver == -1) {
  159.         gdriver = installuserdriver( "VGA256", NULL);
  160.         errorcode = graphresult();
  161.     }
  162.     closegraph();
  163.     gmode = 0;
  164.     initgraph( &gdriver, &gmode, BGI_PATH);
  165.     errorcode = graphresult();
  166.     if (errorcode != grOk) {
  167.         /* failed for 256 colors - back to 16 colors */
  168.         gdriver = VGA;
  169.         gmode = VGAHI;
  170.         initgraph( &gdriver, &gmode, BGI_PATH);
  171.         errorcode = graphresult();
  172.     }
  173.         if (errorcode != grOk) /* shouldn't happen */
  174.         ProgError( "graphics error: %s", grapherrormsg( errorcode));
  175.         GfxMode = -1 /* 320x200x256 */;
  176.         SetDoomPalette( 0);
  177.         ScrMaxX = getmaxx();
  178.         ScrMaxY = getmaxy();
  179.         ScrCenterX = ScrMaxX / 2;
  180.         ScrCenterY = ScrMaxY / 2;
  181.         return TRUE;
  182.     }
  183.     
  184.     return FALSE;
  185.     }
  186.     
  187. #elif defined(__GNUC__)
  188.  
  189. if (GfxMode > 0) {
  190.     closegraph();
  191.     set_BGI_mode_whc( &gdriver, &gmode, res[1][0], res[1][1], res[1][2]);
  192.     initgraph( &gdriver, &gmode, BGI_PATH);
  193.     errorcode = graphresult();
  194.     if(errorcode != grOk) {
  195.     /* failed for 256 colors - back to 16 colors */
  196.     set_BGI_mode_whc( &gdriver, &gmode, res[0][0], res[0][1], res[0][2]);
  197.     initgraph( &gdriver, &gmode, BGI_PATH);
  198.     errorcode = graphresult();
  199.     }
  200.     
  201.     
  202.     if (errorcode != grOk) /* shouldn't happen */
  203.     ProgError( "graphics error: %s", grapherrormsg( errorcode));
  204.     GfxMode = -1 /* 320x200x256 */;
  205.     SetDoomPalette( 0);
  206.     ScrMaxX = getmaxx();
  207.     ScrMaxY = getmaxy();
  208.     ScrCenterX = ScrMaxX / 2;
  209.     ScrCenterY = ScrMaxY / 2;
  210.     return TRUE;
  211. }
  212.  
  213. return FALSE;
  214. }
  215. #endif
  216.  
  217.  
  218. /*
  219.    switch from VGA 256 colours to VGA 16 colours
  220.    */
  221.  
  222. Bool SwitchToVGA16()
  223. {
  224.     if (GfxMode == -1) { /* switch only if we are in 320x200x256 colors */ 
  225. #if defined(__TURBOC__)
  226.     int gdriver, gmode, errorcode;
  227.     
  228.     closegraph();
  229.     gdriver = VGA;
  230.     gmode = VGAHI;
  231.     initgraph( &gdriver, &gmode, BGI_PATH);
  232.     errorcode = graphresult();
  233.     if (errorcode != grOk) /* shouldn't happen */
  234.         ProgError( "graphics error: %s", grapherrormsg( errorcode));
  235.     GfxMode = 2; /* 640x480x16 */
  236.     ScrMaxX = getmaxx();
  237.     ScrMaxY = getmaxy();
  238.     ScrCenterX = ScrMaxX / 2;
  239.     ScrCenterY = ScrMaxY / 2;
  240.     
  241. #elif defined(__GNUC__)
  242.     TermGfx();    /* This is a hack, I just didn't have the time to */
  243.     InitGfx();    /* find out why "the other way" didn't work ... */
  244.     CheckMouseDriver();
  245.     if (UseMouse)
  246.         ShowMousePointer();
  247. #endif
  248.     
  249.     return TRUE;
  250.     }
  251.     return FALSE;
  252. }
  253.  
  254.  
  255.  
  256. /*
  257.    clear the screen
  258.    */
  259.  
  260. void ClearScreen()
  261. {
  262.     cleardevice();
  263. }
  264.  
  265. /*
  266.    clear the map screen
  267.    */
  268.  
  269.  
  270.  
  271.  
  272. /*AJB*/
  273. void ClearMapScreen( BCINT maxy)
  274. {
  275.     setviewport(0, 17, ScrMaxX, ScrMaxY - maxy, FALSE);
  276.     clearviewport();
  277.     setviewport(0, 0, ScrMaxX, ScrMaxY, FALSE);
  278. }
  279.  
  280.  
  281.  
  282. /*
  283.    set the current drawing color
  284.    */
  285.  
  286. void SetColor( BCINT color)
  287. {
  288.     if (GfxMode < 0)
  289.     setcolor( TranslateToGameColor(color));
  290.     else
  291.     setcolor( color);
  292. }
  293.  
  294.  
  295.  
  296. /*
  297.    draw a line on the screen from map coords
  298.    */
  299.  
  300. void DrawMapLine( BCINT mapXstart, BCINT mapYstart, BCINT mapXend, BCINT mapYend)
  301. {
  302.     line( SCREENX( mapXstart), SCREENY( mapYstart), SCREENX( mapXend), SCREENY( mapYend));
  303. }
  304.  
  305.  
  306.  
  307. /*
  308.    draw a circle on the screen from map coords
  309.    */
  310.  
  311. void DrawMapCircle( BCINT mapXcenter, BCINT mapYcenter, BCINT mapRadius)
  312. {
  313.     circle( SCREENX( mapXcenter), SCREENY( mapYcenter), (int) (mapRadius * Scale));
  314. }
  315.  
  316.  
  317.  
  318. /*
  319.    draw an arrow on the screen from map coords
  320. */
  321.  
  322. void DrawMapVector( BCINT mapXstart, BCINT mapYstart, BCINT mapXend, BCINT mapYend)
  323. {
  324.    BCINT  scrXstart = SCREENX( mapXstart);
  325.    BCINT  scrYstart = SCREENY( mapYstart);
  326.    BCINT  scrXend   = SCREENX( mapXend);
  327.    BCINT  scrYend   = SCREENY( mapYend);
  328.    double r         = hypot( (double) (scrXstart - scrXend), (double) (scrYstart - scrYend));
  329.    BCINT  scrXoff   = (r >= 1.0) ? (BCINT) ((scrXstart - scrXend) * 4.0 / r * Scale) : 0;
  330.    BCINT  scrYoff   = (r >= 1.0) ? (BCINT) ((scrYstart - scrYend) * 4.0 / r * Scale) : 0;
  331.  
  332.    line( scrXstart, scrYstart, scrXend, scrYend);
  333.    scrXstart = scrXend + 2 * scrXoff;
  334.    scrYstart = scrYend + 2 * scrYoff;
  335.    line( scrXstart - scrYoff, scrYstart + scrXoff, scrXend, scrYend);
  336.    line( scrXstart + scrYoff, scrYstart - scrXoff, scrXend, scrYend);
  337. /*
  338.    line( scrXstart - scrYoff, scrYstart + scrXoff, scrXend + scrXoff, scrYend + scrYoff);
  339.    line( scrXstart + scrYoff, scrYstart - scrXoff, scrXend + scrXoff, scrYend + scrYoff);
  340. */
  341. }
  342.  
  343.  
  344.  
  345. /*
  346.    draw an arrow on the screen from map coords and angle (0 - 65535)
  347. */
  348.  
  349. void DrawMapArrow( BCINT mapXstart, BCINT mapYstart, UBCINT angle)
  350. {
  351.    BCINT  mapXend   = mapXstart + (BCINT) (50 * cos(angle / 10430.37835));
  352.    BCINT  mapYend   = mapYstart + (BCINT) (50 * sin(angle / 10430.37835));
  353.    BCINT  scrXstart = SCREENX( mapXstart);
  354.    BCINT  scrYstart = SCREENY( mapYstart);
  355.    BCINT  scrXend   = SCREENX( mapXend);
  356.    BCINT  scrYend   = SCREENY( mapYend);
  357.    double r         = hypot( scrXstart - scrXend, scrYstart - scrYend);
  358.    BCINT  scrXoff   = (r >= 1.0) ? (BCINT) ((scrXstart - scrXend) * 4.0 / r * Scale) : 0;
  359.    BCINT  scrYoff   = (r >= 1.0) ? (BCINT) ((scrYstart - scrYend) * 4.0 / r * Scale) : 0;
  360.  
  361.    line( scrXstart, scrYstart, scrXend, scrYend);
  362.    scrXstart = scrXend + 2 * scrXoff;
  363.    scrYstart = scrYend + 2 * scrYoff;
  364.    line( scrXstart - scrYoff, scrYstart + scrXoff, scrXend, scrYend);
  365.    line( scrXstart + scrYoff, scrYstart - scrXoff, scrXend, scrYend);
  366. }
  367.  
  368.  
  369. /*
  370.    draw a line on the screen from screen coords
  371.    */
  372.  
  373. void DrawScreenLine( BCINT Xstart, BCINT Ystart, BCINT Xend, BCINT Yend)
  374. {
  375.     line( Xstart, Ystart, Xend, Yend);
  376. }
  377.  
  378.  
  379.  
  380. /*
  381.    draw a filled in box on the screen from screen coords
  382.    */
  383.  
  384. void DrawScreenBox( BCINT Xstart, BCINT Ystart, BCINT Xend, BCINT Yend)
  385. {
  386.     setfillstyle( 1, getcolor());
  387.     bar( Xstart, Ystart, Xend, Yend);
  388. }
  389.  
  390.  
  391.  
  392. /*
  393.    draw a filled-in 3D-box on the screen from screen coords
  394.    */
  395.  
  396. void DrawScreenBox3D( BCINT Xstart, BCINT Ystart, BCINT Xend, BCINT Yend)
  397. {
  398.     setfillstyle( 1, TranslateToGameColor(DARKGRAY));
  399.     bar( Xstart + 1, Ystart + 1, Xend - 1, Yend - 1);
  400.     SetColor(DARKERGRAY);
  401.     line( Xstart, Yend, Xend, Yend);
  402.     line( Xend, Ystart, Xend, Yend);
  403.     /*if (Xend - Xstart > 20 && Yend - Ystart > 20) {
  404.     line( Xstart + 1, Yend - 1, Xend - 1, Yend - 1);
  405.     line( Xend - 1, Ystart + 1, Xend - 1, Yend - 1);
  406.     SetColor(LIGHTGRAY);
  407.     line( Xstart + 1, Ystart + 1, Xstart + 1, Yend - 1);
  408.     line( Xstart + 1, Ystart + 1, Xend - 1, Ystart + 1);
  409.     }*/
  410.     SetColor(LIGHTGRAY);
  411.     line( Xstart, Ystart, Xend, Ystart);
  412.     line( Xstart, Ystart, Xstart, Yend);
  413.     SetColor( BLACK);
  414. }
  415.  
  416.  
  417.  
  418. /*
  419.    draw a hollow 3D-box on the screen from screen coords
  420.    */
  421.  
  422. void DrawScreenBoxHollow( BCINT Xstart, BCINT Ystart, BCINT Xend, BCINT Yend)
  423. {
  424.     setfillstyle( 1, TranslateToGameColor( BLACK));
  425.     bar( Xstart + 1, Ystart + 1, Xend - 1, Yend - 1);
  426.     SetColor(LIGHTGRAY);
  427.     line( Xstart, Yend, Xend, Yend);
  428.     line( Xend, Ystart, Xend, Yend);
  429.     if (Xend - Xstart > 20 && Yend - Ystart > 20) {
  430.     line( Xstart + 1, Yend - 1, Xend - 1, Yend - 1);
  431.     line( Xend - 1, Ystart + 1, Xend - 1, Yend - 1);
  432.     SetColor(DARKERGRAY);
  433.     line( Xstart + 1, Ystart + 1, Xstart + 1, Yend - 1);
  434.     line( Xstart + 1, Ystart + 1, Xend - 1, Ystart + 1);
  435.     }
  436.     SetColor(DARKERGRAY);
  437.     line( Xstart, Ystart, Xend, Ystart);
  438.     line( Xstart, Ystart, Xstart, Yend);
  439.     SetColor(LIGHTGRAY);
  440. }
  441.  
  442.  
  443.  
  444. /*
  445.    draw a meter bar on the screen from screen coords (in a hollow box); max. value = 1.0
  446.    */
  447.  
  448. void DrawScreenMeter( BCINT Xstart, BCINT Ystart, BCINT Xend, BCINT Yend, float value)
  449. {
  450.     if (value < 0.0)
  451.     value = 0.0;
  452.     if (value > 1.0)
  453.     value = 1.0;
  454.     setfillstyle( 1, TranslateToGameColor( BLACK));
  455.     bar( Xstart + 1 + (BCINT) ((Xend - Xstart - 2) * value), Ystart + 1, Xend - 1, Yend - 1);
  456.     setfillstyle( 1, TranslateToGameColor( LIGHTGREEN));
  457.     bar( Xstart + 1, Ystart + 1, Xstart + 1 + (BCINT) ((Xend - Xstart - 2) * value), Yend - 1);
  458. }
  459.  
  460.  
  461.  
  462. /*
  463.    write text to the screen
  464.    */
  465.  
  466. void DrawScreenText( BCINT Xstart, BCINT Ystart, char *msg, ...)
  467. {
  468.     static BCINT lastX;
  469.     static BCINT lastY;
  470.     char temp[ 120];
  471.     va_list args;
  472.     
  473.     va_start( args, msg);
  474.     vsprintf( temp, msg, args);
  475.     va_end( args);
  476.     if (Xstart < 0)
  477.     Xstart = lastX;
  478.     if (Ystart < 0)
  479.     Ystart = lastY;
  480.     outtextxy( Xstart, Ystart, temp);
  481.     lastX = Xstart;
  482.     lastY = Ystart + 10;  /* or textheight("W") ? */
  483. }
  484.  
  485.  
  486.  
  487. /*
  488.    draw (or erase) the pointer if we aren't using the mouse
  489.    */
  490.  
  491. void DrawPointer( Bool rulers)
  492. {
  493.     BCINT r;
  494.     
  495.     /* use XOR mode : drawing the pointer twice erases it */
  496.     setwritemode( XOR_PUT);
  497.     /* draw the pointer */
  498.     if ( rulers) {
  499.     SetColor( MAGENTA);
  500.     r = (BCINT) (512 * Scale);
  501.     circle_or_square( PointerX, PointerY, r);
  502.     r >>= 1;
  503.     circle_or_square( PointerX, PointerY, r);
  504.     r >>= 1;
  505.     circle_or_square( PointerX, PointerY, r);
  506.     r >>= 1;
  507.     circle_or_square( PointerX, PointerY, r);
  508.     r = (BCINT) (1024 * Scale);
  509.     line( PointerX - r, PointerY, PointerX + r, PointerY);
  510.     line( PointerX, PointerY - r, PointerX, PointerY + r);
  511.     }
  512.     else {
  513.     SetColor( YELLOW);
  514.     line( PointerX - 15, PointerY - 13, PointerX + 15, PointerY + 13);
  515.     line( PointerX - 15, PointerY + 13, PointerX + 15, PointerY - 13);
  516.     }
  517.     /* restore normal write mode */
  518.     setwritemode( COPY_PUT);
  519. }
  520.  
  521.  
  522.  
  523. /*
  524.    load one "playpal" palette and change all palette colours
  525.    */
  526.  
  527. void SetDoomPalette( BCINT playpalnum)
  528. {
  529.     MDirPtr             dir;
  530.     unsigned char huge *dpal;
  531.     BCINT                 n;
  532.     
  533.     if (playpalnum < 0 && playpalnum > 13)
  534.     return;
  535.     dir = FindMasterDir( MasterDir, "PLAYPAL");
  536.     if (dir) {
  537.     dpal = (unsigned char*)GetFarMemory( 768 * sizeof( char));
  538.     BasicWadSeek( dir->wadfile, dir->dir.start);
  539.     for (n = 0; n <= playpalnum; n++)
  540.         BasicWadRead( dir->wadfile, dpal, 768L);
  541.     
  542. #if defined(__GNUC__)
  543.     
  544.     GrResetColors();
  545.     for(n=0;n<254;n++)
  546.         GrAllocCell();
  547.     
  548.     for(n=0;n<256;n++)
  549.         GrSetColor(n,dpal[3*n],dpal[3*n+1],dpal[3*n+2]);
  550.     
  551. #elif defined(__TURBOC__)
  552.     
  553.     for (n = 0; n < 768; n++)
  554.         dpal[ n] /= 4;
  555.     
  556.     _AX = 0x1012;
  557.     _BX = 0;
  558.     _CX = 256;
  559.     _ES = FP_SEG( dpal);
  560.     _DX = FP_OFF( dpal);
  561.     __int__( 0x10);
  562.     
  563. #endif
  564.     
  565.     FreeFarMemory( dpal );
  566.     }
  567. }
  568.  
  569.  
  570.  
  571. /*
  572.    translate a standard color to Doom palette 0 (approx.)
  573.    */
  574.  
  575. BCINT TranslateToGameColor( BCINT color)
  576. {
  577.     return Palette[color];
  578. }
  579.  
  580.  
  581.  
  582. /*
  583.    translate (dx, dy) into an integer angle value (0-65535)
  584.    */
  585.  
  586. UBCINT ComputeAngle( BCINT dx, BCINT dy)
  587. {
  588.     return (UBCINT) (atan2( (double) dy, (double) dx) * 10430.37835 + 0.5);
  589.     /* Yes, I know this function could be in another file, but */
  590.     /* this is the only source file that includes <math.h>...  */
  591. }
  592.  
  593.  
  594.  
  595. /*
  596.    compute the distance from (0, 0) to (dx, dy)
  597.    */
  598.  
  599. UBCINT ComputeDist( BCINT dx, BCINT dy)
  600. {
  601.     return (UBCINT) (hypot( (double) dx, (double) dy) + 0.5);
  602.     /* Yes, I know this function could be in another file, but */
  603.     /* this is the only source file that includes <math.h>...  */
  604. }
  605.  
  606.  
  607.  
  608. /*
  609.    insert the vertices of a new polygon
  610.    */
  611.  
  612. void InsertPolygonVertices( BCINT centerx, BCINT centery, BCINT sides, BCINT radius)
  613. {
  614.     BCINT n;
  615.     
  616.     for (n = 0; n < sides; n++)
  617.     InsertObject( OBJ_VERTEXES, -1, centerx + (BCINT) ((double) radius * cos( 6.28 * (double) n / (double) sides)), centery + (BCINT) ((double) radius * sin( 6.2832 * (double) n / (double) sides)));
  618.     /* Yes, I know... etc. */
  619. }
  620.  
  621.  
  622.  
  623. /*
  624.    move (x, y) to a new position: rotate and scale around (0, 0)
  625.    */
  626.  
  627. void RotateAndScaleCoords( BCINT *x, BCINT *y, double angle, double scale)
  628. {
  629.     double r, theta;
  630.     
  631.     r = hypot( (double) *x, (double) *y);
  632.     theta = atan2( (double) *y, (double) *x);
  633.     *x = (BCINT) (r * scale * cos( theta + angle) + 0.5);
  634.     *y = (BCINT) (r * scale * sin( theta + angle) + 0.5);
  635.     /* Yes, I know... etc. */
  636. }
  637.  
  638. /* end of file */
  639.