home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / animutil / fastgfx / fg303b / manuals.arj / USER06.DOC < prev    next >
Encoding:
Text File  |  1993-10-02  |  67.2 KB  |  1,632 lines

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