home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / c / fglb / user06.doc < prev    next >
Text File  |  1993-10-02  |  69KB  |  1,632 lines

  1. Chapter 6
  2.  
  3.  
  4.  
  5.  
  6.  
  7. Graphics Fundamentals
  8. 98   Fastgraph User's Guide
  9.  
  10.  
  11. Overview
  12.  
  13.      This chapter describes Fastgraph's fundamental graphics routines,
  14. sometimes called graphics primitives.  These routines perform such functions
  15. as clearing the screen, drawing points, drawing solid and dashed lines,
  16. drawing closed shapes (polygons, circles, and ellipses), drawing rectangles
  17. (solid, hollow, and dithered), and filling arbitrary regions.  Most of these
  18. routines have no effect in text video modes, but there are a few exceptions,
  19. and they will be noted in the descriptions of those routines.
  20.  
  21.  
  22. Clearing the Screen
  23.  
  24.      The Fastgraph routine fg_erase clears the entire screen in any video
  25. mode.  In text modes, fg_erase stores a space character (ASCII 32) with a
  26. gray foreground attribute in each character cell.  In graphics modes,
  27. fg_erase sets each pixel to zero.  This of course causes each pixel to be
  28. displayed its background color.  The fg_erase routine has no arguments.
  29.  
  30.      The fg_erase routine always sets the entire screen to the background
  31. color.  Another routine, fg_fillpage, fills the screen with the current
  32. color.  In text modes, fg_fillpage stores a solid block character (ASCII 219)
  33. with the current display attribute (as defined in the most recent call to
  34. fg_setcolor or fg_setattr).  In graphics modes, fg_fillpage sets each pixel
  35. to the current color (as defined in the most recent call to fg_setcolor).
  36. Like fg_erase, the fg_fillpage routine has no arguments.
  37.  
  38.  
  39. Clipping
  40.  
  41.      The suppression of graphics outside a pre-defined area is called
  42. clipping.  Many of Fastgraph's graphics-oriented routines provide clipping,
  43. either automatically or through a special version of the routine.
  44.  
  45.      Fastgraph includes two routines, fg_setclip and fg_setclipw, to define a
  46. rectangular clipping region.  The fg_setclip routine defines the clipping
  47. region in screen space, while the fg_setclipw routine performs the same
  48. function in world space.  Each routine takes four arguments:  the minimum x,
  49. the maximum x, the minimum y, and the maximum y coordinate of the clipping
  50. region.  The arguments are integer quantities for fg_setclip and floating
  51. point quantities for fg_setclipw.  For example, the statement
  52.  
  53.                            fg_setclip(0,159,0,99);
  54.  
  55. would define the upper left quadrant of the screen as the clipping region in
  56. a 320 by 200 graphics mode.
  57.  
  58.      An implicit clipping region equal to the entire screen is defined as
  59. part of the fg_setmode routine's initializations.  Clipping is not supported
  60. for text modes.
  61.                                         Chapter 6:  Graphics Fundamentals   99
  62.  
  63.  
  64. Points
  65.  
  66.      The Fastgraph routine fg_point provides the most basic graphics
  67. operation -- setting a pixel to a specified color.  The fg_point routine has
  68. two integer arguments.  The first specifies the pixel's x coordinate, and the
  69. second its y coordinate.  The pixel is drawn using the current color value,
  70. as specified in the most recent call to fg_setcolor.  There is also a world
  71. space version of this routine, fg_pointw, that uses floating point arguments.
  72.  
  73.      Another Fastgraph routine is available for reading a pixel's color
  74. value.  The fg_getpixel routine has two integer arguments that specify the
  75. (x,y) coordinates for the pixel of interest.  There is no world space version
  76. of the fg_getpixel routine, but you can obtain a pixel's color value in world
  77. space by applying the fg_xscreen and fg_yscreen functions to the world space
  78. coordinates and passing the resulting values to fg_getpixel.
  79.  
  80.      Example 6-1 uses the fg_point routine to draw 100 random points in
  81. random colors.  It also uses the fg_getpixel routine to insure no two points
  82. are adjacent.  The program establishes a graphics video mode with the
  83. fg_automode and fg_setmode routines.  Next, it determines the maximum color
  84. value for the selected video mode; note if we used virtual colors (color
  85. indices above the maximum color value), some of the colors would be the
  86. background color and would thus produce invisible points.  The main part of
  87. the program is a while loop that first generates a random pair of (x,y)
  88. screen coordinates.  It then calls the fg_getpixel routine to check the
  89. pixels at (x,y) and the eight adjacent positions.  If none of these pixels
  90. are set, the program generates a random color value and draws a point in that
  91. color.  After doing this 100 times, the program waits for a keystroke,
  92. restores the original video mode and screen attributes, and then returns to
  93. DOS.
  94.  
  95.                                  Example 6-1.
  96.  
  97.  
  98.   #include <fastgraf.h>
  99.  
  100.   #include <stdlib.h>
  101.  
  102.   void main(void);
  103.  
  104.  
  105.  
  106.   void main()
  107.  
  108.   {
  109.  
  110.      int area;
  111.  
  112.      int color, old_color;
  113.  
  114.      int left;
  115.  
  116.      int max_color, max_x, max_y;
  117.  
  118.      int new_mode, old_mode;
  119.  
  120. 100   Fastgraph User's Guide
  121.  
  122.      int x, y;
  123.  
  124.  
  125.  
  126.      old_mode = fg_getmode();
  127.  
  128.      new_mode = fg_automode();
  129.  
  130.      fg_setmode(new_mode);
  131.  
  132.  
  133.  
  134.      if (new_mode == 4)
  135.  
  136.         max_color = 3;
  137.  
  138.      else if (new_mode == 11 || new_mode == 17)
  139.  
  140.         max_color = 1;
  141.  
  142.      else if (new_mode == 19)
  143.  
  144.         max_color = 255;
  145.  
  146.      else
  147.  
  148.         max_color = 15;
  149.  
  150.  
  151.  
  152.      left = 100;
  153.  
  154.      max_x = fg_getmaxx() - 1;
  155.  
  156.      max_y = fg_getmaxy() - 1;
  157.  
  158.  
  159.  
  160.      while (left > 0) {
  161.  
  162.  
  163.  
  164.         x = rand() % max_x + 1;
  165.  
  166.         y = rand() % max_y + 1;
  167.  
  168.         area = fg_getpixel(x-1,y-1)+fg_getpixel(x,y-1)+fg_getpixel(x+1,y-1)
  169.              + fg_getpixel(x-1,y)  +fg_getpixel(x,y)  +fg_getpixel(x+1,y)
  170.              + fg_getpixel(x-1,y+1)+fg_getpixel(x,y+1)+fg_getpixel(x+1,y+1);
  171.  
  172.                                        Chapter 6:  Graphics Fundamentals   101
  173.  
  174.         if (area == 0) {
  175.  
  176.            color = rand() % max_color + 1;
  177.  
  178.            fg_setcolor(color);
  179.  
  180.            fg_point(x,y);
  181.  
  182.            left--;
  183.  
  184.            }
  185.  
  186.         }
  187.  
  188.  
  189.  
  190.      fg_waitkey();
  191.  
  192.  
  193.  
  194.      fg_setmode(old_mode);
  195.  
  196.      fg_reset();
  197.  
  198.   }
  199.  
  200.  
  201.  
  202.  
  203.      Sometimes you may want to display a pixel using an "exclusive or"
  204. operation (usually called XOR) to guarantee its visibility.  The color of a
  205. pixel drawn in XOR mode will be c xor p, where c is the current color and p
  206. is the color of the pixel already at that position.  This means the pixel's
  207. new color will be different from the background as long as the current color
  208. is not zero.  The Fastgraph routine fg_pointx displays a screen space pixel
  209. in XOR mode, while fg_pointxw does the same thing in world space.  Their
  210. respective parameters are the same as for fg_point and fg_pointw.
  211.  
  212.  
  213. The Graphics Cursor
  214.  
  215.      Many of Fastgraph's graphics routines depend on the position of the
  216. graphics cursor as a reference point.  For example, Fastgraph includes
  217. routines to draw lines from the graphics cursor position to a specified
  218. position, and the bit-mapped image display routines discussed in Chapter 10
  219. display or retrieve an image relative to the graphics cursor position.  The
  220. graphics cursor is not a cursor in the true sense; it is simply a pair of
  221. (x,y) coordinates with a special meaning.  The fg_setmode routine sets the
  222. graphics cursor position to the screen space coordinates (0,0), and the
  223. fg_initw routine sets it to the world space coordinates (0.0,0.0).
  224.  
  225.      Fastgraph includes four routines for changing the graphics cursor
  226. position.  The fg_move routine sets it to an absolute screen space position,
  227. while the fg_movew routine sets it to an absolute world space position.  The
  228. fg_moverel routine sets the graphics cursor position to a screen space
  229. position relative to its current position.  The fg_moverw routine does the
  230. same in world space.
  231. 102   Fastgraph User's Guide
  232.  
  233.  
  234.      Each of these routines has two arguments that specify the (x,y)
  235. coordinates of the new position.  For the screen space routines, the
  236. arguments are integer quantities.  For the world space routines, the
  237. arguments are floating point quantities.
  238.  
  239.      You can obtain the screen space coordinates of the graphics cursor
  240. position with the fg_getxpos and fg_getypos routines.  These routines have no
  241. arguments and respectively return the x and y coordinates of the graphics
  242. cursor position as the function value.  To obtain the world space coordinates
  243. of the graphics cursor position, you can apply the fg_xworld and fg_yworld
  244. functions to the return values of fg_getxpos and fg_getypos.
  245.  
  246.  
  247. Solid Lines
  248.  
  249.      Fastgraph includes eight routines for drawing solid lines.  All of them
  250. draw lines in the current color value and observe the clipping limits.  The
  251. fg_draw routine draws a line from the current graphics cursor position to an
  252. absolute screen space position, while fg_draww draws a line to an absolute
  253. world space position.  The fg_drawrel routine draws a line from the current
  254. graphics cursor position to a screen space position relative to it.  The
  255. fg_drawrw routine does the same in world space.  You can draw absolute lines
  256. in XOR mode with fg_drawx and relative XOR lines with fg_drawrelx, or with
  257. their world space counterparts fg_drawxw and fg_drawrxw.  XOR lines are often
  258. used when drawing cursors (such as cross hairs) or rubberband boxes to insure
  259. they are visible against colored backgrounds.  Another useful property of XOR
  260. lines is that drawing the same lines twice restores what was originally
  261. beneath the lines.
  262.  
  263.      Each of these routines has two arguments that specify the (x,y)
  264. coordinates of the destination position.  For the screen space routines, the
  265. arguments are integer quantities.  For the world space routines, the
  266. arguments are floating point quantities.  In either case the destination
  267. position becomes the new graphics cursor position.  This makes it possible to
  268. draw connected lines without calling a graphics cursor movement routine
  269. between successive calls to a line drawing routine.
  270.  
  271.      Examples 6-2 and 6-3 each draw a pair of crossed lines that divide the
  272. screen into quadrants.  Example 6-2 does this using the fg_move and fg_draw
  273. routines, while example 6-3 uses the fg_moverel and fg_drawrel routines.
  274. Both examples draw the lines in white, the default for color 15 in all
  275. graphics video modes.
  276.  
  277.               Example 6-2.                          Example 6-3.
  278.  
  279.      #include <fastgraf.h>                 #include <fastgraf.h>
  280.      void main(void);                      void main(void);
  281.  
  282.      void main()                           void main()
  283.      {                                     {
  284.         int max_x, max_y;                     int max_x, max_y;
  285.         int mid_x, mid_y;                     int mid_x, mid_y;
  286.         int new_mode, old_mode;               int new_mode, old_mode;
  287.  
  288.         old_mode = fg_getmode();              old_mode = fg_getmode();
  289.         new_mode = fg_automode();             new_mode = fg_automode();
  290.  
  291.                                        Chapter 6:  Graphics Fundamentals   103
  292.  
  293.         fg_setmode(new_mode);                 fg_setmode(new_mode);
  294.  
  295.         max_x = fg_getmaxx();                 max_x = fg_getmaxx();
  296.         max_y = fg_getmaxy();                 max_y = fg_getmaxy();
  297.         mid_x = max_x / 2;                    mid_x = max_x / 2;
  298.         mid_y = max_y / 2;                    mid_y = max_y / 2;
  299.  
  300.         fg_setcolor(15);                      fg_setcolor(15);
  301.         fg_move(mid_x,0);                     fg_move(mid_x,0);
  302.         fg_draw(mid_x,max_y);                 fg_drawrel(0,max_y);
  303.         fg_move(0,mid_y);                     fg_moverel(-mid_x,-mid_y);
  304.         fg_draw(max_x,mid_y);                 fg_drawrel(max_x,0);
  305.         fg_waitkey();                         fg_waitkey();
  306.  
  307.         fg_setmode(old_mode);                 fg_setmode(old_mode);
  308.         fg_reset();                           fg_reset();
  309.      }                                     }
  310.  
  311.  
  312.      Examples 6-4 and 6-5 are variations of example 6-2.  Example 6-4 uses
  313. world space rather than screen space to draw the crossed lines.  Example 6-5
  314. is the same as example 6-2 except it defines a clipping area to restrict
  315. drawing to the upper left quadrant of the screen.  The clipping suppresses
  316. the right half of the horizontal line and the lower half of the vertical
  317. line.
  318.  
  319.                Example 6-4.                           Example 6-5.
  320.  
  321.  
  322.  
  323.   #include <fastgraf.h>                     #include <fastgraf.h>
  324.  
  325.   void main(void);                          void main(void);
  326.  
  327.  
  328.  
  329.   void main()                               void main()
  330.  
  331.   {                                          {
  332.  
  333.      int new_mode, old_mode;                   int max_x, max_y;
  334.  
  335.                                                int mid_x, mid_y;
  336.  
  337.      old_mode = fg_getmode();                  int new_mode, old_mode;
  338.  
  339.      new_mode = fg_automode();
  340.  
  341.      fg_setmode(new_mode);                     old_mode = fg_getmode();
  342.  
  343.      fg_initw();                               new_mode = fg_automode();
  344.  
  345.      fg_setworld(-10.0,10.0,-10.0,10.0);       fg_setmode(new_mode);
  346.  
  347. 104   Fastgraph User's Guide
  348.  
  349.      fg_setcolor(15);                          max_x = fg_getmaxx();
  350.  
  351.      fg_movew(0.0,10.0);                       max_y = fg_getmaxy();
  352.  
  353.      fg_draww(0.0,-10.0);                      mid_x = max_x / 2;
  354.  
  355.      fg_movew(-10.0,0.0);                      mid_y = max_y / 2;
  356.  
  357.      fg_draww(10.0,0.0);
  358.  
  359.      fg_waitkey();                             fg_setclip(0,mid_x,0,mid_y);
  360.  
  361.  
  362.      fg_setmode(old_mode);                     fg_setcolor(15);
  363.  
  364.      fg_reset();                               fg_move(mid_x,0);
  365.  
  366.   }                                            fg_draw(mid_x,max_y);
  367.  
  368.                                                fg_move(0,mid_y);
  369.  
  370.                                                fg_draw(max_x,mid_y);
  371.  
  372.                                                fg_waitkey();
  373.  
  374.  
  375.  
  376.                                                fg_setmode(old_mode);
  377.  
  378.                                                fg_reset();
  379.  
  380.                                             }
  381.  
  382.  
  383.  
  384.  
  385.  
  386. Dashed Lines
  387.  
  388.      Fastgraph includes four routines for drawing dashed lines.  All of them
  389. draw lines in the current color value and observe the clipping limits.  The
  390. fg_dash routine draws a dashed line from the current graphics cursor position
  391. to an absolute screen space position, while fg_dashw draws a dashed line to
  392. an absolute world space position.  The fg_dashrel routine draws a dashed line
  393. from the current graphics cursor position to a screen space position relative
  394. to it.  The fg_dashrw routine does the same in world space.
  395.  
  396.      Each of these routines has three arguments.  The first two specify the
  397. (x,y) coordinates of the destination position.  For the screen space
  398. routines, these arguments are integer quantities.  For the world space
  399. routines, these arguments are floating point quantities.  The third argument
  400. is a 16-bit pattern that defines the appearance of the dashed line.  Bits
  401. that are set in the pattern produce the visible part of the line, while bits
  402. that are reset produce the invisible part.  This pattern is repeated as
  403. necessary to draw the entire line.  For example, the pattern value 3333 hex
  404. would produce a dashed line with the first two pixels off, the next two on,
  405.                                        Chapter 6:  Graphics Fundamentals   105
  406.  
  407. the next two off, and so forth.  Similarly, the pattern value FFFF hex would
  408. produce a solid line.
  409.  
  410.      The destination position passed to any of the dashed line routines
  411. becomes the new graphics cursor position.  This makes it possible to draw
  412. connected dashed lines without calling a graphics cursor movement routine
  413. between successive calls to a line drawing routine.
  414.  
  415.      Example 6-6 draws a pair of crossed dashed lines that divide the screen
  416. into quadrants.  It does this using the fg_move and fg_dash routines and
  417. draws the lines in white, the default for color 15 in all graphics video
  418. modes.  The dash pattern for each line is 3333 hex, which alternates two
  419. pixels off and on.
  420.  
  421.                                  Example 6-6.
  422.  
  423.                        #include <fastgraf.h>
  424.                        void main(void);
  425.  
  426.                        void main()
  427.                        {
  428.                           int max_x, max_y;
  429.                           int mid_x, mid_y;
  430.                           int new_mode, old_mode;
  431.  
  432.                           old_mode = fg_getmode();
  433.                           new_mode = fg_automode();
  434.                           fg_setmode(new_mode);
  435.  
  436.                           max_x = fg_getmaxx();
  437.                           max_y = fg_getmaxy();
  438.                           mid_x = max_x / 2;
  439.                           mid_y = max_y / 2;
  440.  
  441.                           fg_setcolor(15);
  442.                           fg_move(mid_x,0);
  443.                           fg_dash(mid_x,max_y,0x3333);
  444.                           fg_move(0,mid_y);
  445.                           fg_dash(max_x,mid_y,0x3333);
  446.                           fg_waitkey();
  447.  
  448.                           fg_setmode(old_mode);
  449.                           fg_reset();
  450.                        }
  451.  
  452.  
  453.  
  454. Polygons
  455.  
  456.      Fastgraph includes routines for drawing filled and unfilled polygons, as
  457. well as a routine for determining if a given point is inside a convex
  458. polygon.  All the polygon routines observe the clipping limits.
  459.  
  460.      The fg_polygon routine draws an unfilled polygon in screen space.
  461. Fg_polygon requires an array of integer x coordinates as its first argument,
  462. and an array of integer y coordinates as its second argument.  Each (x,y)
  463. coordinate pair from the two arrays is treated as a polygon vertex.  In other
  464. 106   Fastgraph User's Guide
  465.  
  466. words, the x coordinate of the first polygon vertex is the first element of
  467. the x coordinate array, and the y coordinate of the first vertex is the first
  468. element of the y coordinate array.  Similarly, the second elements of each
  469. array define the second vertex, and so forth.  The third argument for
  470. fg_polygon is an integer quantity that specifies the number of elements in
  471. the two coordinate arrays (that is, the number of polygon vertices).
  472.  
  473.      Another routine, fg_polygonw, draws an unfilled polygon in world space.
  474. The fg_polygonw routine is the same as the fg_polygon routine, except its x
  475. and y coordinate arrays must contain floating point values instead of
  476. integers.
  477.  
  478.      The polygon drawing begins at the first vertex specified in the
  479. coordinate arrays.  The polygon routines then draw a solid line to the second
  480. vertex, then to the third vertex, and continue in this manner through the
  481. last vertex.  If necessary, they then close the polygon by drawing a line
  482. connecting the last vertex and the first vertex.  Example 6-7 illustrates
  483. unfilled polygon drawing using the fg_polygon routine in the EGA monochrome
  484. or enhanced modes (modes 15 and 16).  The program exits if neither of these
  485. video modes are available.
  486.  
  487.                                  Example 6-7.
  488.  
  489.              #include <fastgraf.h>
  490.              #include <stdio.h>
  491.              #include <stdlib.h>
  492.              void main(void);
  493.  
  494.              #define VERTICES 10
  495.  
  496.              int x[] = {200,300,400,400,300,240,160,160,200,210};
  497.              int y[] = {100, 80,100,220,320,320,240,200,160,150};
  498.  
  499.              void main()
  500.              {
  501.                 int old_mode;
  502.  
  503.                 old_mode = fg_getmode();
  504.                 if (fg_testmode(16,1))
  505.                    fg_setmode(16);
  506.                 else if (fg_testmode(15,1))
  507.                    fg_setmode(15);
  508.                 else {
  509.                    printf("This program requires a 640 x 350 ");
  510.                    printf("EGA graphics mode.\n");
  511.                    exit(1);
  512.                    }
  513.  
  514.                 fg_setcolor(1);
  515.                 fg_polygon(x,y,VERTICES);
  516.                 fg_waitkey();
  517.  
  518.                 fg_setmode(old_mode);
  519.                 fg_reset();
  520.              }
  521.  
  522.                                        Chapter 6:  Graphics Fundamentals   107
  523.  
  524.      As shown in this example, the fg_polygon routine expects the x and y
  525. components defining the polygon vertices to be in separate arrays.  Another
  526. routine, fg_polyline, draws an unfilled polygon from polygon vertices in one
  527. integer array.  With fg_polyline, the first array element is the x component
  528. of the first vertex, the second element is the y component of the first
  529. vertex, the third element is the x component of the second vertex, and so
  530. forth.  The first fg_polyline argument is the vertex coordinate array of
  531. alternating x and y components, and the second argument specifies the number
  532. of vertices.  In other respects, fg_polyline is identical to fg_polygon.
  533.  
  534.      An additional feature available with fg_polyline but not fg_polygon is
  535. the ability to specify vertex offsets.  The fg_polyoff routine's two integer
  536. arguments respectively define offset values that are added to each
  537. fg_polyline vertex.  This makes it possible to define polygon vertices as
  538. relative values, that when combined with the offsets, determine the polygon's
  539. absolute position.
  540.  
  541.      Perhaps the most important polygon display routine is fg_polyfill, which
  542. displays a filled convex polygon in screen space (the polygon is filled with
  543. pixels of the current color).  Its first argument is a vertex array in the
  544. same format used by fg_polyline.  The next argument is a work array used
  545. internally.  The size of the work array must be at least twice the polygon
  546. height if defined as an integer array, or four times the polygon height if
  547. defined as a byte array.  The final argument specifies the number of polygon
  548. vertices.
  549.  
  550.      Example 6-8 illustrates the use of the fg_polyline, fg_polyoff, and
  551. fg_polyfill routines.  The program first draws an unfilled polygon, centered
  552. within the left half of the screen.  It then draws a filled version of the
  553. same polygon, centered within the right half of the screen.  In each case,
  554. the centering is accomplished by passing appropriate values to fg_polyoff.
  555. After waiting for a keystroke, the program establishes a clipping region in
  556. the lower right corner and redraws the filled polygon at the same position
  557. but in a different color.  This of course results in only a portion of the
  558. filled polygon being drawn.  Like example 6-7, this example requires a 640 by
  559. 350 graphics mode.
  560.  
  561.                                  Example 6-8.
  562.  
  563.           #include <fastgraf.h>
  564.           #include <stdio.h>
  565.           #include <stdlib.h>
  566.           void main(void);
  567.  
  568.           #define VERTICES 10
  569.  
  570.           int xy[] = {200,100, 300, 80, 400,100, 400,220, 300,320,
  571.                       240,320, 160,240, 160,200, 200,160, 210,150};
  572.           int work_array[700];
  573.  
  574.           void main()
  575.           {
  576.              int old_mode;
  577.  
  578.              old_mode = fg_getmode();
  579.              if (fg_testmode(16,1))
  580.                 fg_setmode(16);
  581.  
  582. 108   Fastgraph User's Guide
  583.  
  584.              else if (fg_testmode(15,1))
  585.                 fg_setmode(15);
  586.              else {
  587.                 printf("This program requires a 640 x 350 ");
  588.                 printf("EGA graphics mode.\n");
  589.                 exit(1);
  590.                 }
  591.  
  592.              fg_setcolor(1);
  593.              fg_polyoff(-120,-25);
  594.              fg_polyline(xy,VERTICES);
  595.              fg_polyoff(200,-25);
  596.              fg_polyfill(xy,work_array,VERTICES);
  597.              fg_waitkey();
  598.  
  599.              fg_setcolor(2);
  600.              fg_setclip(480,639,175,349);
  601.              fg_polyfill(xy,work_array,VERTICES);
  602.              fg_waitkey();
  603.  
  604.              fg_setmode(old_mode);
  605.              fg_reset();
  606.           }
  607.  
  608.  
  609.      The fg_polyfill routine fills convex polygons.  From Fastgraph's
  610. perspective, a polygon is convex if any horizontal line drawn through the
  611. polygon crosses the left edge exactly once and the right edge exactly once
  612. (excluding horizontal and zero-length edge segments).  Note that this
  613. definition includes shapes that are not convex in the traditional sense.  In
  614. addition, any non-convex polygon can be decomposed into two or more convex
  615. polygons.
  616.  
  617.      The filled convex polygon is a fundamental tool of three-dimensional
  618. computer graphics.  A common practice is to build an image or object from
  619. several adjacent or connecting polygons.  Such polygons typically overlap at
  620. one or more edges.  For instance, the coordinates defining the right edge of
  621. one polygon may also define the left edge of another polygon immediately to
  622. its right.  For an overall image to appear correct, its component polygons
  623. must fit together correctly.  The fg_polyfill routine applies the following
  624. rules to handle overlapping polygon edges:
  625.  
  626.           Points located exactly on non-horizontal edges are drawn
  627.           only if the polygon's interior is directly to the right.
  628.  
  629.           Points located exactly on horizontal edges are drawn only
  630.           if the polygon's interior is directly below them.
  631.  
  632.           A vertex is drawn only if all lines ending at that point
  633.           meet the above two conditions.
  634.  
  635. These three rules ensure that no pixel is drawn more than once when filling
  636. adjacent polygons.  However, they may not be suitable for displaying polygons
  637. that are not adjacent because some of the pixels on the polygon's edge will
  638. not be included.  If this is an issue, first draw the filled polygon with
  639. fg_polyfill, then draw an unfilled polygon having the same vertices with
  640. fg_polyline.
  641.                                        Chapter 6:  Graphics Fundamentals   109
  642.  
  643.  
  644.      The final Fastgraph routine relating to polygons is fg_inside, which
  645. checks if a specified point lies inside a convex polygon.  Its first argument
  646. is a vertex array in the same format used by fg_polyline and fg_polyfill.
  647. The second argument is the number of vertices in the polygon, while the last
  648. two arguments specify the screen space x and y coordinates of the point being
  649. tested.  The fg_inside function returns 1 if the point lies inside the
  650. polygon and 0 if not.  If the vertex array does not define a convex polygon,
  651. the return value is undefined.
  652.  
  653.  
  654. Circles and Ellipses
  655.  
  656.      Fastgraph includes routines for drawing filled and unfilled circles and
  657. ellipses.  Both screen space and world space versions of these routines are
  658. available, and all of them observe the clipping limits.
  659.  
  660.      The fg_circle routine draws an unfilled circle in screen space, centered
  661. at the graphics cursor position, using the current color.  The routine's only
  662. argument specifies the circle's radius in horizontal screen space units.
  663. Another routine, fg_circlew, draws an unfilled circle where the radius is
  664. measured in horizontal world space units.  The analogous routines for drawing
  665. filled circles are fg_circlef and fg_circlefw.  All four circle drawing
  666. routines leave the graphics cursor position unchanged.
  667.  
  668.      The fg_ellipse routine draws an unfilled ellipse in screen space,
  669. centered at the graphics cursor position, using the current color.  The
  670. routine requires two arguments that respectively specify the length of its
  671. horizontal and vertical semi-axes.  In other words, the first argument is the
  672. absolute distance from the center of the ellipse to its horizontal extremity,
  673. and the second argument is the absolute distance from the center to the
  674. vertical extremity.  Another routine, fg_ellipsew, draws an unfilled ellipse
  675. in world space.  The analogous routines for drawing filled ellipses are
  676. fg_ellipsef and fg_ellipsfw.  All four ellipse drawing routines leave the
  677. graphics cursor position unchanged.
  678.  
  679.      Example 6-9 illustrates the use of the fg_circlew and fg_ellipsew
  680. routines.  The program first uses the fg_automode routine to propose a
  681. graphics video mode and then uses the fg_setmode routine to select that video
  682. mode.  It then makes color 15 the current color, which by default is white in
  683. all color graphics modes and "on" in the monochrome graphics modes.  Next, it
  684. establishes a 200-unit by 200-unit world space coordinate system.  The
  685. program then uses fg_ellipsew to draw an ellipse and fg_circlew to draw a
  686. circle, both centered at the middle of the screen (which is the origin of our
  687. world space coordinate system).  The circle has a radius of 1/16 the width of
  688. the screen (12.5 horizontal world space units), and the ellipse is
  689. horizontally inscribed within the circle.
  690.  
  691.      Example 6-10 illustrates the use of the fg_circle and fg_ellipse
  692. routines.  It is functionally identical to example 6-9, but it uses screen
  693. space rather than world space coordinates to draw the circle and ellipse.
  694. Note the arguments to the fg_circle and fg_ellipse routines are dependent on
  695. the maximum x and y coordinates of the selected video mode.  If we didn't
  696. compute these arguments in this manner, the actual size of the circle and
  697. ellipse would be proportional to the pixel resolution of the video mode.  No
  698. such dependency exists when using world space, but we pay a price for this
  699. feature in slightly slower execution speed.
  700. 110   Fastgraph User's Guide
  701.  
  702.  
  703.                  Example 6-9.                              Example 6-10.
  704.  
  705.  
  706.  
  707.   #include <fastgraf.h>                        #include <fastgraf.h>
  708.  
  709.   void main(void);                             void main(void);
  710.  
  711.  
  712.  
  713.   void main()                                  void main()
  714.  
  715.   {                                            {
  716.  
  717.      int old_mode;                                int mid_x, mid_y;
  718.  
  719.                                                   int old_mode;
  720.  
  721.      old_mode = fg_getmode();                     int x,y;
  722.  
  723.      fg_setmode(fg_automode());
  724.  
  725.      fg_setcolor(15);                             old_mode = fg_getmode();
  726.  
  727.                                                   fg_setmode(fg_automode());
  728.  
  729.      fg_initw();                                  fg_setcolor(15);
  730.  
  731.      fg_setworld(-100.0,100.0,-100.0,100.0);
  732.  
  733.                                                   mid_x = fg_getmaxx() / 2;
  734.  
  735.      fg_movew(0.0,0.0);                           mid_y = fg_getmaxy() / 2;
  736.  
  737.      fg_ellipsew(12.5,12.5);                      x = mid_x / 8;
  738.  
  739.      fg_circlew(12.5);                            y = mid_y / 8;
  740.  
  741.      fg_waitkey();
  742.  
  743.                                                   fg_move(mid_x,mid_y);
  744.  
  745.      fg_setmode(old_mode);                        fg_ellipse(x,y);
  746.  
  747.      fg_reset();                                  fg_circle(x);
  748.  
  749.   }                                               fg_waitkey();
  750.  
  751.  
  752.  
  753.                                                   fg_setmode(old_mode);
  754.  
  755.                                                   fg_reset();
  756.  
  757.                                                }
  758.  
  759.                                        Chapter 6:  Graphics Fundamentals   111
  760.  
  761. Solid Rectangles
  762.  
  763.      Fastgraph includes four routines for drawing solid rectangles, two for
  764. screen space and two for world space, with and without clipping.  None of
  765. these routines affect the graphics cursor position.
  766.  
  767.      The fg_rect routine draws a solid rectangle in screen space, without
  768. regard to the clipping limits, using the current color.  Fg_rect requires
  769. four integer arguments that respectively define the minimum x, maximum x,
  770. minimum y, and maximum y screen space coordinates of the rectangle.  The
  771. minimum coordinates must be less than or equal to the maximum coordinates, or
  772. else the results are unpredictable.  The fg_clprect routine is identical in
  773. all respects to the fg_rect routine, except it observes the clipping limits.
  774.  
  775.      The world space versions of the solid rectangle drawing routines are
  776. fg_rectw and fg_clprectw.  Like fg_rect and fg_clprect, they require four
  777. arguments that define the extremes of the rectangle, but the arguments are
  778. floating point world space coordinates.
  779.  
  780.      You also can use fg_rect in text modes.  When used in a text mode,
  781. fg_rect expects its four arguments to be expressed in character space (that
  782. is, rows and columns) rather than screen space.  This means the four
  783. arguments respectively specify the minimum column, maximum column, minimum
  784. row, and maximum row of the rectangle.  Fastgraph constructs the rectangle by
  785. storing the solid block character (ASCII decimal value 219) in each character
  786. cell comprising the rectangle.  The rectangle is drawn using the current
  787. character attribute, but because the solid block character occupies the
  788. entire character cell, the background component of the attribute is
  789. essentially meaningless.
  790.  
  791.      Example 6-11 demonstrates the use of the fg_rect routine by drawing 200
  792. random-size rectangles in random colors.  The program first uses the
  793. fg_automode routine to propose a graphics video mode and then uses the
  794. fg_setmode routine to select that video mode.  Next, it determines the
  795. horizontal and vertical screen resolution for the selected video mode, using
  796. the fg_getmaxx and fg_getmaxy routines.  The main part of the program is a
  797. for loop that generates a random rectangle in each iteration.  Inside the
  798. loop, the C library function rand is used to generate the extremes of the
  799. rectangle.  If necessary, the program then exchanges the coordinates to make
  800. the minimum coordinates less than or equal to the maximum coordinates.
  801. Finally, it again uses rand to generate a random color number between 0 and
  802. 15, and then draws the rectangle in that color.  After drawing all 200
  803. rectangles, the program restores the original video mode and screen
  804. attributes before returning to DOS.
  805.  
  806.                                 Example 6-11.
  807.  
  808.             #include <fastgraf.h>
  809.             void main(void);
  810.  
  811.             #define RECTANGLES 200
  812.             #define SWAP(a,b,temp) { temp = a; a = b; b = temp; }
  813.  
  814. 112   Fastgraph User's Guide
  815.  
  816.             void main()
  817.             {
  818.                int i;
  819.                int minx, maxx, miny, maxy;
  820.                int old_mode;
  821.                int temp;
  822.                int xres, yres;
  823.  
  824.                old_mode = fg_getmode();
  825.                fg_setmode(fg_automode());
  826.  
  827.                xres = fg_getmaxx() + 1;
  828.                yres = fg_getmaxy() + 1;
  829.  
  830.                for (i = 0; i < RECTANGLES; i++) {
  831.                   minx = rand() % xres;
  832.                   maxx = rand() % xres;
  833.                   miny = rand() % yres;
  834.                   maxy = rand() % yres;
  835.                   if (minx > maxx)
  836.                      SWAP(minx,maxx,temp);
  837.                   if (miny > maxy)
  838.                      SWAP(miny,maxy,temp);
  839.                   fg_setcolor(rand()%16);
  840.                   fg_rect(minx,maxx,miny,maxy);
  841.                   }
  842.  
  843.                fg_setmode(old_mode);
  844.                fg_reset();
  845.             }
  846.  
  847.  
  848.  
  849. Unfilled Rectangles
  850.  
  851.      Fastgraph includes a routine for drawing unfilled rectangles.  The
  852. fg_box routine draws an unfilled rectangle in screen space, with regard to
  853. the clipping limits, using the current color.  The arguments to fg_box are
  854. the same as those for fg_rect.  The depth of the rectangle's edges is one
  855. pixel by default, but you can change the depth by calling fg_boxdepth.  The
  856. fg_boxdepth routine expects two arguments.  The first argument is the width
  857. of the rectangle's left and right sides, while the second is the height of
  858. its top and bottom sides.  Once you call fg_boxdepth, fg_box draws all
  859. unfilled rectangles using the depth values specified in the most recent call
  860. to fg_boxdepth.  Unlike fg_rect, the fg_box routine has no effect in text
  861. video modes.  The analogous world space routine is fg_boxw.
  862.  
  863.      Example 6-12 is the same as example 6-11, but it draws unfilled instead
  864. of solid rectangles.  The program uses fg_box to draw the each rectangle and
  865. fg_boxdepth to define the rectangle depth at three pixels in each direction.
  866. Note that you don't need to call fg_boxdepth for each rectangle if you want
  867. all of them to have the same depth.
  868.  
  869.                                 Example 6-12.
  870.  
  871.             #include <fastgraf.h>
  872.             void main(void);
  873.  
  874.                                        Chapter 6:  Graphics Fundamentals   113
  875.  
  876.  
  877.             #define RECTANGLES 200
  878.             #define SWAP(a,b,temp) { temp = a; a = b; b = temp; }
  879.  
  880.             void main()
  881.             {
  882.                int i;
  883.                int minx, maxx, miny, maxy;
  884.                int old_mode;
  885.                int temp;
  886.                int xres, yres;
  887.  
  888.                old_mode = fg_getmode();
  889.                fg_setmode(fg_automode());
  890.                fg_boxdepth(3,3);
  891.  
  892.                xres = fg_getmaxx() + 1;
  893.                yres = fg_getmaxy() + 1;
  894.  
  895.                for (i = 0; i < RECTANGLES; i++) {
  896.                   minx = rand() % xres;
  897.                   maxx = rand() % xres;
  898.                   miny = rand() % yres;
  899.                   maxy = rand() % yres;
  900.                   if (minx > maxx)
  901.                      SWAP(minx,maxx,temp);
  902.                   if (miny > maxy)
  903.                      SWAP(miny,maxy,temp);
  904.                   fg_setcolor(rand()%16);
  905.                   fg_box(minx,maxx,miny,maxy);
  906.                   }
  907.  
  908.                fg_setmode(old_mode);
  909.                fg_reset();
  910.             }
  911.  
  912.  
  913.      The fg_boxx and fg_boxxw routines are screen space and world space
  914. "exclusive or" versions of the box drawing routines.  They simplify
  915. displaying rubberband boxes (hollow rectangles that move in response to
  916. keystrokes or mouse movement) because drawing an object in XOR mode makes it
  917. appear, but drawing it again in the same position and in the same color
  918. restores what was under the object originally.  Given this useful property,
  919. here is an outline of what's necessary to draw a rubberband box:
  920.  
  921.    1.     Draw the box in its initial position with fg_boxx or
  922.           fg_boxxw.
  923.    2.     Wait for a user response that signifies box movement.
  924.    3.     Use fg_boxx or fg_boxxw to redraw the box in the same
  925.           position as in step 1.  This restores what was there
  926.           originally.
  927.    4.     Draw the box in its new position with fg_boxx or
  928.           fg_boxxw.
  929.    5.     Repeat steps 2, 3, and 4 until the box is no longer
  930.           needed.
  931. 114   Fastgraph User's Guide
  932.  
  933.      Example 6-13 shows a simple use of fg_boxx in the 320 by 200 MCGA/VGA
  934. 256-color mode (mode 19).  The program fills the left and right halves of the
  935. screen with different colors and then displays an XOR box the overlaps each
  936. half.  Even though the box is drawn in the same color as the right half, it
  937. is still visible because drawing something in an XOR mode (except in color 0)
  938. guarantees that it will be visible against its background.  After a
  939. keystroke, the program redraws the same box, which of course restores what
  940. was there in the first place.
  941.  
  942.                                 Example 6-13.
  943.  
  944.                          #include <fastgraf.h>
  945.                          void main(void);
  946.  
  947.                          void main()
  948.                          {
  949.                             int old_mode;
  950.  
  951.                             old_mode = fg_getmode();
  952.                             fg_setmode(19);
  953.                             fg_setcolor(9);
  954.                             fg_rect(0,159,0,199);
  955.                             fg_setcolor(15);
  956.                             fg_rect(160,319,0,199);
  957.                             fg_waitkey();
  958.  
  959.                             fg_boxx(80,239,50,149);
  960.                             fg_waitkey();
  961.                             fg_boxx(80,239,50,149);
  962.                             fg_waitkey();
  963.  
  964.                             fg_setmode(old_mode);
  965.                             fg_reset();
  966.                          }
  967.  
  968.  
  969.  
  970. Dithered Rectangles
  971.  
  972.      The process of alternating different color pixels across a region of the
  973. display area is called dithering.  This technique is especially useful in the
  974. graphics modes with few colors, such as CGA and Hercules modes, because you
  975. can simulate additional colors through effective uses of dithering.
  976. Fastgraph includes two routines for drawing dithered rectangles, one for
  977. screen space and one for world space.  Neither routine observes the clipping
  978. limits, nor do they affect the graphics cursor position.
  979.  
  980.      The fg_drect routine draws a dithered rectangle in screen space.  Like
  981. the fg_rect routine, fg_drect requires four integer arguments that
  982. respectively define the minimum x, maximum x, minimum y, and maximum y screen
  983. space coordinates of the rectangle.  The minimum coordinates must be less
  984. than or equal to the maximum coordinates, or else the results are
  985. unpredictable.  However, fg_drect also requires a fifth argument that defines
  986. the dithering matrix, which in turn determines the pixel pattern used to
  987. build the dithered rectangle.  The size and format of the dithering matrix
  988. are dependent on the video mode.
  989.                                        Chapter 6:  Graphics Fundamentals   115
  990.  
  991.      The world space version of the dithered rectangle drawing routine is
  992. fg_drectw.  Like fg_drect, it requires four arguments that define the
  993. extremes of the rectangle, and a fifth argument that defines the dithering
  994. matrix.
  995.  
  996.      As mentioned earlier, the size and format of the dithering matrix are
  997. dependent on the video mode.  The dithering matrix is a four byte array in
  998. all video modes except the 256 color graphics modes (modes 19 through 27),
  999. where it is an eight byte array.  This array contains a pixel pattern that
  1000. fg_drect or fg_drectw replicates across the rectangle's area.  The structure
  1001. of the dithering matrix closely mimics the structure of video memory in each
  1002. graphics mode.
  1003.  
  1004.      The remainder of this section will present some simple mode-specific
  1005. examples to illustrate the structure of the dithering matrix in the different
  1006. graphics modes.  Suppose we would like to produce a "checkerboard" of light
  1007. blue and white pixels.  That is, in a given row of a rectangle, consecutive
  1008. pixels will alternate between these two colors.  Additionally, the pattern
  1009. for adjacent rows will be shifted such that there will always be a white
  1010. pixel above and below a light blue pixel, and vice versa.  Hence this pixel
  1011. pattern would look something like
  1012.  
  1013.                                    B W B W
  1014.                                    W B W B
  1015.                                    B W B W
  1016.                                    W B W B
  1017.  
  1018. where each B represents a light blue pixel, and each W represents a white
  1019. pixel.  The following examples describe the dithering matrix that could be
  1020. used to produce such a pixel pattern in each graphics mode.
  1021.  
  1022. CGA Four-Color Graphics Modes
  1023.  
  1024.      The CGA four-color graphics modes (modes 4 and 5) use a four-byte
  1025. dithering matrix that Fastgraph treats as a four-row by one-column array.
  1026. Since each pixel in these modes requires two bits of video memory, each byte
  1027. of the dithering matrix holds four pixels.  Thus, the pixel representation of
  1028. the dithering matrix would appear as shown below on the left; its translation
  1029. to numeric values appears on the right.
  1030.  
  1031.  
  1032.                    [3]   B W B W       [3]   01 11 01 11
  1033.  
  1034.                    [2]   W B W B       [2]   11 01 11 01
  1035.  
  1036.                    [1]   B W B W       [1]   01 11 01 11
  1037.  
  1038.                    [0]   W B W B       [0]   11 01 11 01
  1039.  
  1040.  
  1041. Because these modes do not offer a light blue color, we've used light cyan
  1042. (color value 1 in palette 1) to approximate light blue.  The B pixels thus
  1043. translate to color value 1, or 01 binary.  White is available as color value
  1044. 3 in palette 1, so the W pixels translate to color value 3, or 11 binary.
  1045. The hexadecimal equivalent of the binary value 11011101 (for array elements
  1046. [0] and [2]) is DD, and the hexadecimal equivalent of the binary value
  1047. 01110111 (for array elements [1] and [3]) is 77.  As shown in example 6-12,
  1048. 116   Fastgraph User's Guide
  1049.  
  1050. these are precisely the values assigned to the elements of the dithering
  1051. matrix.
  1052.  
  1053.      Example 6-14 uses mode 4 to display a 50-pixel by 50-pixel dithered
  1054. rectangle in the upper left corner of the screen.  The dithering matrix
  1055. represents the blue and white checkerboard pattern discussed in the preceding
  1056. paragraph.
  1057.  
  1058.                                 Example 6-14.
  1059.  
  1060.                        #include <fastgraf.h>
  1061.                        void main(void);
  1062.  
  1063.                        void main()
  1064.                        {
  1065.                           char matrix[4];
  1066.                           int old_mode;
  1067.  
  1068.                           old_mode = fg_getmode();
  1069.                           fg_setmode(4);
  1070.  
  1071.                           matrix[0] = matrix[2] = 0xDD;
  1072.                           matrix[1] = matrix[3] = 0x77;
  1073.                           fg_drect(0,49,0,49,matrix);
  1074.                           fg_waitkey();
  1075.  
  1076.                           fg_setmode(old_mode);
  1077.                           fg_reset();
  1078.                        }
  1079.  
  1080.  
  1081. CGA Two-Color Graphics Mode
  1082.  
  1083.      The CGA two-color graphics mode (mode 6) uses a four-byte dithering
  1084. matrix that Fastgraph treats as a four-row by one-column array, as in the
  1085. other four-color CGA modes.  However, each pixel in this mode only requires
  1086. one bit of video memory, so each byte of the dithering matrix holds eight
  1087. pixels.  Thus, the pixel representation of the dithering matrix would appear
  1088. as shown below on the left; its translation to numeric values appears on the
  1089. right.
  1090.  
  1091.  
  1092.              [3]   B W B W B W B W       [3]   0 1 0 1 0 1 0 1
  1093.  
  1094.              [2]   W B W B W B W B       [2]   1 0 1 0 1 0 1 0
  1095.  
  1096.              [1]   B W B W B W B W       [1]   0 1 0 1 0 1 0 1
  1097.  
  1098.              [0]   W B W B W B W B       [0]   1 0 1 0 1 0 1 0
  1099.  
  1100.  
  1101. Mode 6 obviously does not offer a light blue color, so we've used black
  1102. (color value 0) in its place.  The B pixels thus translate to color value 0.
  1103. White is available as color value 1, so the W pixels translate to color value
  1104. 1.  The hexadecimal equivalent of the binary value 10101010 (for array
  1105. elements [0] and [2]) is AA, and the hexadecimal equivalent of the binary
  1106. value 01010101 (for array elements [1] and [3]) is 55.  Thus, to make example
  1107.                                        Chapter 6:  Graphics Fundamentals   117
  1108.  
  1109. 6-14 run in mode 6, we only need to change the fg_setmode argument from 4 to
  1110. 6 and change the dithering matrix values as shown below.
  1111.  
  1112.  
  1113.                         matrix[0] = matrix[2] = 0xAA;
  1114.                         matrix[1] = matrix[3] = 0x55;
  1115.  
  1116.  
  1117. Tandy/PCjr 16-Color Graphics Mode
  1118.  
  1119.      The Tandy/PCjr 16-color graphics mode (mode 9) also uses a four-byte
  1120. dithering matrix that Fastgraph treats as a four-row by one-column array.
  1121. Each pixel in this mode requires four bits of video memory, so each byte of
  1122. the dithering matrix only holds two pixels.  Thus, the pixel representation
  1123. of the dithering matrix would appear as shown below on the left; its
  1124. translation to numeric values appears on the right.
  1125.  
  1126.  
  1127.                       [3]   B W       [3]   1001 1111
  1128.  
  1129.                       [2]   W B       [2]   1111 1001
  1130.  
  1131.                       [1]   B W       [1]   1001 1111
  1132.  
  1133.                       [0]   W B       [0]   1111 1001
  1134.  
  1135.  
  1136. The B pixels translate to color value 9 (light blue), or 1001 binary, and the
  1137. W pixels translate to color value 15 (white), or 1111 binary.  The
  1138. hexadecimal equivalent of the binary value 11111001 (for array elements [0]
  1139. and [2]) is F9, and the hexadecimal equivalent of the binary value 10011111
  1140. (for array elements [1] and [3]) is 9F.  Thus, to make example 6-14 run in
  1141. mode 9, we only need to change the fg_setmode argument from 4 to 9 and change
  1142. the dithering matrix values as shown below.
  1143.  
  1144.  
  1145.                         matrix[0] = matrix[2] = 0xF9;
  1146.                         matrix[1] = matrix[3] = 0x9F;
  1147.  
  1148.  
  1149. Hercules Graphics Mode
  1150.  
  1151.      The size and format of the dithering matrix in the Hercules graphics
  1152. mode (mode 11) are the same as in the CGA two-color mode (mode 6).
  1153.  
  1154. Hercules Low-Resolution Graphics Mode
  1155.  
  1156.      The size and format of the dithering matrix in the Hercules low-
  1157. resolution graphics mode (mode 12) are the same as in the CGA four-color
  1158. modes (modes 4 and 5).  As far as our checkerboard example goes, we'll use
  1159. black (color value 0) in place of light blue, and bold (color value 3)
  1160. instead of white.  Thus, the B pixels translate to 00 binary, while the W
  1161. pixels translate to 11 binary.  The hexadecimal equivalent of the binary
  1162. value 11001100 (for array elements [0] and [2]) is CC, and the hexadecimal
  1163. equivalent of the binary value 00110011 (for array elements [1] and [3]) is
  1164. 33.  Thus, to make example 6-14 run in mode 12, we only need to change the
  1165. 118   Fastgraph User's Guide
  1166.  
  1167. fg_setmode argument from 4 to 12 and change the dithering matrix values as
  1168. shown below.
  1169.  
  1170.  
  1171.                         matrix[0] = matrix[2] = 0xCC;
  1172.                         matrix[1] = matrix[3] = 0x33;
  1173.  
  1174.  
  1175. EGA/VGA/SVGA 16-Color Graphics Modes
  1176.  
  1177.      The EGA/VGA/SVGA 16-color graphics modes (modes 13 through 18, 28, and
  1178. 29) use a four-byte dithering matrix that Fastgraph treats as a four-row by
  1179. one-column array.  Unlike the other graphics modes, which allow you to store
  1180. pixels of several colors in the dithering matrix, these modes treat the
  1181. dithering matrix as a bit map for a specific color.  Since each color in the
  1182. dither pattern must be stored in a separate bit map (that is, in a separate
  1183. dithering matrix), you must call fg_drect once for each color.  Furthermore,
  1184. you must use the fg_setcolor routine before each call to fg_drect to define
  1185. the color used with the dithering matrix.
  1186.  
  1187.      In all EGA/VGA/SVGA graphics modes, each byte of the dithering matrix is
  1188. a bit map that represents eight pixels.  Using our familiar checkerboard
  1189. example, the pixel representation of the dithering matrix would appear as
  1190. shown below.
  1191.  
  1192.  
  1193.                            [3]   B W B W B W B W
  1194.  
  1195.                            [2]   W B W B W B W B
  1196.  
  1197.                            [1]   B W B W B W B W
  1198.  
  1199.                            [0]   W B W B W B W B
  1200.  
  1201.  
  1202. Translating this pattern to numeric values is simple.  Just construct one
  1203. dithering matrix for each color in the pattern (there are two colors in this
  1204. example), where pixels of the current color translate to 1, and other pixels
  1205. translate to 0.  Following our example, the translation for the B pixels
  1206. appears below on the left, while the translation for the W pixels appears on
  1207. the right.
  1208.  
  1209.  
  1210.              [3]   1 0 1 0 1 0 1 0       [3]   0 1 0 1 0 1 0 1
  1211.  
  1212.              [2]   0 1 0 1 0 1 0 1       [2]   1 0 1 0 1 0 1 0
  1213.  
  1214.              [1]   1 0 1 0 1 0 1 0       [1]   0 1 0 1 0 1 0 1
  1215.  
  1216.              [0]   0 1 0 1 0 1 0 1       [0]   1 0 1 0 1 0 1 0
  1217.  
  1218.  
  1219. The hexadecimal equivalent of the binary value 01010101 is 55, and the
  1220. hexadecimal equivalent of the binary value 10101010 is AA.  As shown in
  1221. example 6-15, these are precisely the values assigned to the elements of the
  1222. dithering matrices.
  1223.                                        Chapter 6:  Graphics Fundamentals   119
  1224.  
  1225.      Example 6-15 uses mode 13 to display our light blue and white
  1226. checkerboard pattern.  Note you must call fg_drect twice -- once for the
  1227. light blue pixels (color value 9), and again for the white pixels (color
  1228. value 15).  Note also how fg_setcolor is used before each call to fg_drect to
  1229. define the color of the pixels fg_drect will display.
  1230.  
  1231.                                 Example 6-15.
  1232.  
  1233.                        #include <fastgraf.h>
  1234.                        void main(void);
  1235.  
  1236.                        void main()
  1237.                        {
  1238.                           char matrix[4];
  1239.                           int old_mode;
  1240.  
  1241.                           old_mode = fg_getmode();
  1242.                           fg_setmode(13);
  1243.  
  1244.                           matrix[0] = matrix[2] = 0x55;
  1245.                           matrix[1] = matrix[3] = 0xAA;
  1246.                           fg_setcolor(9);
  1247.                           fg_drect(0,49,0,49,matrix);
  1248.  
  1249.                           matrix[0] = matrix[2] = 0xAA;
  1250.                           matrix[1] = matrix[3] = 0x55;
  1251.                           fg_setcolor(15);
  1252.                           fg_drect(0,49,0,49,matrix);
  1253.                           fg_waitkey();
  1254.  
  1255.                           fg_setmode(old_mode);
  1256.                           fg_reset();
  1257.                        }
  1258.  
  1259.  
  1260. 256-Color Graphics Modes
  1261.  
  1262.      The 256-color graphics modes (modes 19 through 27) use an eight-byte
  1263. dithering matrix that Fastgraph treats as a four-row by two-column array.
  1264. Each pixel in these modes requires eight bits of video memory, so each byte
  1265. of the dithering matrix only holds a single pixel.  We therefore need the two
  1266. column dithering matrix to produce a meaningful dither pattern.  The pixel
  1267. representation of the dithering matrix would appear as shown below on the
  1268. left; its translation to numeric values appears on the right.
  1269.  
  1270.  
  1271.                     [6]   B   W   [7]     [6]    9   15   [7]
  1272.  
  1273.                     [4]   W   B   [5]     [4]   15    9   [5]
  1274.  
  1275.                     [2]   B   W   [3]     [2]    9   15   [3]
  1276.  
  1277.                     [0]   W   B   [1]     [0]   15    9   [1]
  1278.  
  1279. 120   Fastgraph User's Guide
  1280.  
  1281. The B pixels translate to color value 9 (light blue), and the W pixels
  1282. translate to color value 15 (white).  Example 6-16 uses mode 19 to draw our
  1283. light blue and white checkerboard pattern.
  1284.  
  1285.                                 Example 6-16.
  1286.  
  1287.             #include <fastgraf.h>
  1288.             void main(void);
  1289.  
  1290.             void main()
  1291.             {
  1292.                char matrix[8];
  1293.                int old_mode;
  1294.  
  1295.                old_mode = fg_getmode();
  1296.                fg_setmode(19);
  1297.  
  1298.                matrix[0] = matrix[3] = matrix[4] = matrix[7] = 15;
  1299.                matrix[1] = matrix[2] = matrix[5] = matrix[6] =  9;
  1300.                fg_drect(0,49,0,49,matrix);
  1301.                fg_waitkey();
  1302.  
  1303.                fg_setmode(old_mode);
  1304.                fg_reset();
  1305.             }
  1306.  
  1307.  
  1308. Closing Remarks
  1309.  
  1310.      There are two other important items pertaining to the fg_drect and
  1311. fg_drectw routines.  These items apply regardless of which graphics video
  1312. mode is being used.
  1313.  
  1314.      First, the dithering matrix may not contain virtual color values.  That
  1315. is, the pixel color values stored in the dithering matrix must be between 0
  1316. and the maximum color value for the current video mode.  If any color value
  1317. is redefined using the fg_defcolor routine, Fastgraph always ignores the
  1318. redefinition and instead uses the actual color value.  Note this does not
  1319. apply to palette registers or video DAC registers, because in these cases we
  1320. are redefining the color associated with a color value and not the color
  1321. value itself.
  1322.  
  1323.      Second, Fastgraph aligns the dithering matrix to specific pixel rows.
  1324. Fastgraph draws the dithered rectangle starting with the pixel row specified
  1325. by the rectangle's lower limit (the maximum y coordinate for fg_drect, or the
  1326. minimum y coordinate for fg_drectw) and proceeds upward until reaching the
  1327. rectangle's upper limit.  In all cases the dithering matrix used by fg_drect
  1328. and fg_drectw contains four rows.  If we let r represent the pixel row
  1329. corresponding to the rectangle's lower limit, then the first row used in the
  1330. dithering matrix is r modulo 4 (assuming the dithering matrix rows are
  1331. numbered 0 to 3).  This alignment enables you to use the same dithering
  1332. matrix in multiple calls to fg_drect and fg_drectw for building an object of
  1333. adjacent dithered rectangles (for example, an L-shaped area) and still have
  1334. the dither pattern match where the rectangles intersect.
  1335.                                        Chapter 6:  Graphics Fundamentals   121
  1336.  
  1337.  
  1338. Region Fill
  1339.  
  1340.      Fastgraph includes routines for filling arbitrary regions.  The fg_flood
  1341. and fg_paint routines fill a region with the current color value by
  1342. specifying a screen space point in the region's interior.  The fg_floodw and
  1343. fg_paintw routine also fill a region, but they require the interior point to
  1344. be expressed in world space.  All region fill routines have two arguments
  1345. that specify the (x,y) coordinates of the interior point.  For fg_flood and
  1346. fg_paint, the arguments are integer quantities.  For fg_floodw and fg_paintw,
  1347. they are floating point quantities.  None of them change the graphics cursor
  1348. position.  The difference between the "flood" and "paint" versions of these
  1349. routines is simple:  fg_flood and fg_floodw will not extend the region fill
  1350. beyond the clipping limits, while fg_paint and fg_paintw ignore the clipping
  1351. limits.  As a result, fg_paint and fg_paintw are significantly faster.
  1352.  
  1353.      The region being filled must be a closed polygon whose boundary color is
  1354. different from that of the specified interior point.  The region may contain
  1355. holes (interior areas that will not be filled).  Fastgraph fills the region
  1356. by changing every interior pixel whose color is the same as the specified
  1357. interior point, to the current color.  If the interior point is already the
  1358. current color, the region fill routines do nothing.  It is important to note
  1359. fg_paint and fg_paintw do not treat the screen edges as polygon boundaries.
  1360. Filling an open polygon will cause these routines to behave unpredictably.
  1361. This is not the case with fg_flood and fg_floodw as long as the clipping
  1362. limits are not beyond the screen edges.
  1363.  
  1364.      Example 6-17 illustrates a simple use of the fg_paint routine in a 320
  1365. by 200 graphics mode.  The program uses fg_bestmode to select an available
  1366. video mode (if no 320 by 200 graphics mode is available, the program exits).
  1367. After establishing the selected video mode, the program uses fg_move and
  1368. fg_drawrel to draw a hollow rectangle in color 10 and a hollow diamond in
  1369. color 9.  The diamond is drawn in the middle of the rectangle, thus making it
  1370. a hole with respect to the rectangle.  The program leaves these shapes on the
  1371. screen until a key is pressed.  At that time, it calls fg_paint to fill that
  1372. part of the rectangle outside the diamond with color 10.  After waiting for
  1373. another keystroke, the program again uses fg_paint to fill the interior of
  1374. the diamond with color 15.  Finally, the program waits for another keystroke,
  1375. restores the original video mode and screen attributes, and returns to DOS.
  1376.  
  1377.                                 Example 6-17.
  1378.  
  1379.              #include <fastgraf.h>
  1380.              #include <stdio.h>
  1381.              #include <stdlib.h>
  1382.              void main(void);
  1383.  
  1384.              void main()
  1385.              {
  1386.                 int old_mode, new_mode;
  1387.  
  1388.                 new_mode = fg_bestmode(320,200,1);
  1389.                 if (new_mode < 0) {
  1390.                    printf("This program requires a 320 x 200 ");
  1391.                    printf("graphics mode.\n");
  1392.                    exit(1);
  1393.                    }
  1394.  
  1395. 122   Fastgraph User's Guide
  1396.  
  1397.  
  1398.                 old_mode = fg_getmode();
  1399.                 fg_setmode(new_mode);
  1400.  
  1401.                 fg_setcolor(10);
  1402.                 fg_move(100,50);
  1403.                 fg_drawrel(120,0);
  1404.                 fg_drawrel(0,100);
  1405.                 fg_drawrel(-120,0);
  1406.                 fg_drawrel(0,-100);
  1407.  
  1408.                 fg_setcolor(9);
  1409.                 fg_move(160,80);
  1410.                 fg_drawrel(30,20);
  1411.                 fg_drawrel(-30,20);
  1412.                 fg_drawrel(-30,-20);
  1413.                 fg_drawrel(30,-20);
  1414.                 fg_waitkey();
  1415.  
  1416.                 fg_setcolor(10);
  1417.                 fg_paint(160,70);
  1418.                 fg_waitkey();
  1419.  
  1420.                 fg_setcolor(15);
  1421.                 fg_paint(160,100);
  1422.                 fg_waitkey();
  1423.  
  1424.                 fg_setmode(old_mode);
  1425.                 fg_reset();
  1426.              }
  1427.  
  1428.  
  1429.  
  1430. Summary of Fundamental Graphics Routines
  1431.  
  1432.      This section summarizes the functional descriptions of the Fastgraph
  1433. routines presented in this chapter.  More detailed information about these
  1434. routines, including their arguments and return values, may be found in the
  1435. Fastgraph Reference Manual.
  1436.  
  1437.      FG_BOX draws an unfilled rectangle in screen space, with respect to the
  1438. clipping region.  The width of the rectangle's edges is one pixel unless
  1439. changed with the fg_boxdepth routine.
  1440.  
  1441.      FG_BOXDEPTH defines the depth of rectangles drawn with the box display
  1442. routines.  The fg_setmode routine initializes the box depth to one pixel.
  1443.  
  1444.      FG_BOXW draws an unfilled rectangle in world space, with respect to the
  1445. clipping region.  The width of the rectangle's edges is one pixel unless
  1446. changed with the fg_boxdepth routine.
  1447.  
  1448.      FG_BOXX draws an unfilled rectangle in screen space, with respect to the
  1449. clipping region, in "exclusive or" mode.  The width of the rectangle's edges
  1450. is one pixel unless changed with the fg_boxdepth routine.
  1451.                                        Chapter 6:  Graphics Fundamentals   123
  1452.  
  1453.      FG_BOXXW draws an unfilled rectangle in world space, with respect to the
  1454. clipping region, in "exclusive or" mode.  The width of the rectangle's edges
  1455. is one pixel unless changed with the fg_boxdepth routine.
  1456.  
  1457.      FG_CIRCLE draws an unfilled circle in screen space.  The circle is
  1458. centered at the graphics cursor position.
  1459.  
  1460.      FG_CIRCLEF draws a filled circle in screen space.  The circle is
  1461. centered at the graphics cursor position.
  1462.  
  1463.      FG_CIRCLEFW draws a filled circle in world space.  The circle is
  1464. centered at the graphics cursor position.
  1465.  
  1466.      FG_CIRCLEW draws an unfilled circle in world space.  The circle is
  1467. centered at the graphics cursor position.
  1468.  
  1469.      FG_CLPRECT draws a solid (filled) rectangle in screen space, with
  1470. respect to the clipping region.
  1471.  
  1472.      FG_CLPRECTW draws a solid (filled) rectangle in world space, with
  1473. respect to the clipping region.
  1474.  
  1475.      FG_DASH draws a dashed line from the graphics cursor position to an
  1476. absolute screen space position.  It also makes the destination position the
  1477. new graphics cursor position.
  1478.  
  1479.      FG_DASHREL draws a dashed line from the graphics cursor position to a
  1480. screen space position relative to it.  It also makes the destination position
  1481. the new graphics cursor position.
  1482.  
  1483.      FG_DASHRW draws a dashed line from the graphics cursor position to a
  1484. world space position relative to it.  It also makes the destination position
  1485. the new graphics cursor position.
  1486.  
  1487.      FG_DASHW draws a dashed line from the graphics cursor position to an
  1488. absolute world space position.  It also makes the destination position the
  1489. new graphics cursor position.
  1490.  
  1491.      FG_DRAW draws a solid line from the graphics cursor position to an
  1492. absolute screen space position.  It also makes the destination position the
  1493. new graphics cursor position.
  1494.  
  1495.      FG_DRAWREL draws a solid line from the graphics cursor position to a
  1496. screen space position relative to it.  It also makes the destination position
  1497. the new graphics cursor position.
  1498.  
  1499.      FG_DRAWRELX draws a solid line in "exclusive or" mode from the graphics
  1500. cursor position to a screen space position relative to it.  It also makes the
  1501. destination position the new graphics cursor position.
  1502.  
  1503.      FG_DRAWRW draws a solid line from the graphics cursor position to a
  1504. world space position relative to it.  It also makes the destination position
  1505. the new graphics cursor position.
  1506.  
  1507.      FG_DRAWRXW draws a solid line in "exclusive or" mode from the graphics
  1508. cursor position to a world space position relative to it.  It also makes the
  1509. destination position the new graphics cursor position.
  1510. 124   Fastgraph User's Guide
  1511.  
  1512.  
  1513.      FG_DRAWW draws a solid line from the graphics cursor position to an
  1514. absolute world space position.  It also makes the destination position the
  1515. new graphics cursor position.
  1516.  
  1517.      FG_DRAWX draws a solid line in "exclusive or" mode from the graphics
  1518. cursor position to an absolute screen space position.  It also makes the
  1519. destination position the new graphics cursor position.
  1520.  
  1521.      FG_DRAWXW draws a solid line in "exclusive or" mode from the graphics
  1522. cursor position to an absolute world space position.  It also makes the
  1523. destination position the new graphics cursor position.
  1524.  
  1525.      FG_DRECT draws a dithered rectangle in screen space, without regard to
  1526. the clipping region.  The rectangle's dither pattern is defined through a
  1527. dithering matrix whose format is dependent on the video mode being used.
  1528.  
  1529.      FG_DRECTW draws a dithered rectangle in world space, without regard to
  1530. the clipping region.  The rectangle's dither pattern is defined through a
  1531. dithering matrix whose format is dependent on the video mode being used.
  1532.  
  1533.      FG_ELLIPSE draws an unfilled ellipse in screen space.  The ellipse is
  1534. centered at the graphics cursor position, and its size is determined by the
  1535. specified lengths of the semi-axes.
  1536.  
  1537.      FG_ELLIPSEF draws a filled ellipse in screen space.  The ellipse is
  1538. centered at the graphics cursor position, and its size is determined by the
  1539. specified lengths of the semi-axes.
  1540.  
  1541.      FG_ELLIPSEW draws an unfilled ellipse in world space.  The ellipse is
  1542. centered at the graphics cursor position, and its size is determined by the
  1543. specified lengths of the semi-axes.
  1544.  
  1545.      FG_ELLIPSFW draws a filled ellipse in world space.  The ellipse is
  1546. centered at the graphics cursor position, and its size is determined by the
  1547. specified lengths of the semi-axes.
  1548.  
  1549.      FG_ERASE clears the screen in either text or graphics modes.
  1550.  
  1551.      FG_FILLPAGE fills the screen with the current color in either text or
  1552. graphics modes.
  1553.  
  1554.      FG_FLOOD fills an arbitrary closed region with the current color value,
  1555. with respect to the clipping limits.  The region is defined by specifying a
  1556. screen space point within its interior.
  1557.  
  1558.      FG_FLOODW fills an arbitrary closed region with the current color value,
  1559. with respect to the clipping limits.  The region is defined by specifying a
  1560. world space point within its interior.
  1561.  
  1562.      FG_GETPIXEL returns the color value of a specified pixel.
  1563.  
  1564.      FG_GETXPOS returns the screen space x coordinate of the graphics cursor
  1565. position.
  1566.  
  1567.      FG_GETYPOS returns the screen space y coordinate of the graphics cursor
  1568. position.
  1569.                                        Chapter 6:  Graphics Fundamentals   125
  1570.  
  1571.  
  1572.      FG_INSIDE determines if the specified point is inside a given convex
  1573. polygon.
  1574.  
  1575.      FG_MOVE establishes the graphics cursor position at an absolute screen
  1576. space point.
  1577.  
  1578.      FG_MOVEREL establishes the graphics cursor position at a screen space
  1579. point relative to the current position.
  1580.  
  1581.      FG_MOVERW establishes the graphics cursor position at a world space
  1582. point relative to the current position.
  1583.  
  1584.      FG_MOVEW establishes the graphics cursor position at an absolute world
  1585. space point.
  1586.  
  1587.      FG_PAINT fills an arbitrary closed region with the current color value,
  1588. without respect to the clipping limits.  The region is defined by specifying
  1589. a screen space point within its interior.
  1590.  
  1591.      FG_PAINTW fills an arbitrary closed region with the current color value,
  1592. without respect to the clipping limits.  The region is defined by specifying
  1593. a world space point within its interior.
  1594.  
  1595.      FG_POINT draws a point (that is, displays a pixel) in screen space.
  1596.  
  1597.      FG_POINTW draws a point in world space.
  1598.  
  1599.      FG_POINTX draws a point in "exclusive or" mode in screen space.
  1600.  
  1601.      FG_POINTXW draws a point in "exclusive or" mode in world space.
  1602.  
  1603.      FG_POLYFILL draws a filled convex polygon in screen space.  The polygon
  1604. is closed if necessary.
  1605.  
  1606.      FG_POLYGON draws an unfilled polygon in screen space, using two
  1607. coordinate arrays to define the polygon vertices.  The polygon is closed if
  1608. necessary.
  1609.  
  1610.      FG_POLYGONW draws an unfilled polygon in world space.  It is the same as
  1611. the fg_polygon routine, except the coordinate arrays contain world space
  1612. values.
  1613.  
  1614.      FG_POLYLINE draws an unfilled polygon in screen space, using a single
  1615. coordinate array to define the polygon vertices.  The polygon is closed if
  1616. necessary.
  1617.  
  1618.      FG_POLYOFF defines the screen space offset applied to each vertex for
  1619. polygons drawn with fg_polyfill or fg_polyline.
  1620.  
  1621.      FG_RECT draws a solid (filled) rectangle in screen space or character
  1622. space, without regard to the clipping region.
  1623.  
  1624.      FG_RECTW draws a solid (filled) rectangle in world space, without regard
  1625. to the clipping region.
  1626. 126   Fastgraph User's Guide
  1627.  
  1628.      FG_SETCLIP defines the clipping region in screen space.  The clipping
  1629. region is a rectangular area outside of which graphics are suppressed.
  1630.  
  1631.      FG_SETCLIPW defines the clipping region in world space.
  1632.