home *** CD-ROM | disk | FTP | other *** search
/ C++ Games Programming / CPPGAMES.ISO / fgl / fglight / manuals.arj / USER06.DOC < prev    next >
Text File  |  1995-02-06  |  71KB  |  1,535 lines

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