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

  1. Chapter 11
  2.  
  3.  
  4.  
  5.  
  6.  
  7. Block Transfer Routines
  8. 222   Fastgraph User's Guide
  9.  
  10. Overview
  11.  
  12.      The Fastgraph routines described in this chapter transfer rectangular
  13. blocks between areas of video memory (such routines are sometimes called Blit
  14. or BitBlt routines in other literature).  Block transfers are useful in many
  15. graphics applications, but they are especially important in animation.
  16. Fastgraph provides several types of block transfer routines, each optimized
  17. for its specific function.  This chapter will discuss these routines in
  18. detail.  The information presented here, combined with the video page and
  19. image management techniques described in the previous three chapters, will
  20. provide the tools we need for the animation techniques presented in the next
  21. chapter.
  22.  
  23.  
  24. Full Page Transfer
  25.  
  26.      Fastgraph's simplest block transfer routine is fg_copypage, which we
  27. introduced in Chapter 8.  The fg_copypage routine transfers the entire
  28. contents of one video page to another.  The first argument is the number of
  29. the source video page, and the second argument is the number of the
  30. destination video page.  The pages may be physical, virtual, or logical video
  31. pages.  If both the source and destination pages are logical pages, the pages
  32. must exist in the same type of memory.  For example, you cannot copy a
  33. logical page in extended memory to a logical page in conventional memory.
  34.  
  35.      Example 11-1 illustrates the use of the fg_copypage routine in a 320 by
  36. 200 color graphics mode.  The program displays the word "test" in the middle
  37. of the visual page (page 0) and then uses fg_allocate to create a virtual
  38. video page (page 1).  The virtual page is needed in case the program is
  39. running in a video mode with only one physical page.  Next, the program uses
  40. fg_copypage to transfer the visual page contents to page 1.  After waiting
  41. for a keystroke, the program erases the visual page, waits for another
  42. keystroke, and copies the contents of page 1 back to the visual page.  It
  43. then releases the virtual page and exits.
  44.  
  45.                                 Example 11-1.
  46.  
  47.                 #include <fastgraf.h>
  48.                 #include <stdio.h>
  49.                 #include <stdlib.h>
  50.                 void main(void);
  51.  
  52.                 void main()
  53.                 {
  54.                    int new_mode, old_mode;
  55.  
  56.                    new_mode = fg_bestmode(320,200,2);
  57.                    if (new_mode < 0 || new_mode == 12) {
  58.                       printf("This program requires a 320 ");
  59.                       printf("x 200 color graphics mode.\n");
  60.                       exit(1);
  61.                       }
  62.                    old_mode = fg_getmode();
  63.                    fg_setmode(new_mode);
  64.  
  65.                    fg_setcolor(7);
  66.                                     Chapter 11:  Block Transfer Routines   223
  67.  
  68.                    fg_rect(0,319,0,199);
  69.                    fg_setcolor(9);
  70.                    fg_locate(12,18);
  71.                    fg_text("test",4);
  72.                    fg_waitkey();
  73.  
  74.                    fg_allocate(1);
  75.                    fg_copypage(0,1);
  76.                    fg_erase();
  77.                    fg_waitkey();
  78.  
  79.                    fg_copypage(1,0);
  80.                    fg_waitkey();
  81.  
  82.                    fg_freepage(1);
  83.                    fg_setmode(old_mode);
  84.                    fg_reset();
  85.                 }
  86.  
  87.  
  88. Byte Boundaries
  89.  
  90.      Video memory, like standard random-access memory, is divided into units
  91. called bytes.  In text modes, each byte holds either a character or an
  92. attribute.  In graphics modes, each byte of video memory holds one or more
  93. horizontally contiguous pixels.  If two adjacent horizontal pixels are stored
  94. in different bytes, then we say a byte boundary exists between the two
  95. pixels.
  96.  
  97.      The number of pixels per byte depends on the video mode being used, so
  98. the location of the byte boundaries also depends on the video mode.  That is,
  99. a byte boundary in a CGA graphics mode is not necessarily a byte boundary in
  100. a VGA graphics mode.  The following table summarizes the number of pixels per
  101. byte of video memory and the byte boundary sequences for each supported
  102. graphics video mode.  Note that any horizontal coordinate whose value is a
  103. multiple of 8 is always a byte boundary, regardless of the video mode.
  104.  
  105.                   mode     pixels     horizontal coordinates
  106.                  number   per byte    of byte boundaries
  107.  
  108.                     4         4       0, 4,  8, 12, ... , 316
  109.                     5         4       0, 4,  8, 12, ... , 316
  110.                     6         8       0, 8, 16, 24, ... , 632
  111.                     9         2       0, 2,  4,  6, ... , 318
  112.                    11         8       0, 8, 16, 24, ... , 712
  113.                    12         4       0, 4,  8, 12, ... , 316
  114.                    13         8       0, 8, 16, 24, ... , 312
  115.                    14         8       0, 8, 16, 24, ... , 632
  116.                    15         8       0, 8, 16, 24, ... , 632
  117.                    16         8       0, 8, 16, 24, ... , 632
  118.                    17         8       0, 8, 16, 24, ... , 632
  119.                    18         8       0, 8, 16, 24, ... , 632
  120.                    19         1       0, 1,  2,  3, ... , 319
  121.                    20         1       0, 4,  8, 12, ... , 316
  122.                    21         1       0, 4,  8, 12, ... , 316
  123.                    22         1       0, 4,  8, 12, ... , 316
  124. 224   Fastgraph User's Guide
  125.                    23         1       0, 4,  8, 12, ... , 316
  126.                    24         1       0, 1,  2,  3, ... , 639
  127.                    25         1       0, 1,  2,  3, ... , 639
  128.                    26         1       0, 1,  2,  3, ... , 799
  129.                    27         1       0, 1,  2,  3, ... , 1023
  130.                    28         8       0, 8, 16, 24, ... , 792
  131.                    29         8       0, 8, 16, 24, ... , 1016
  132.  
  133.      Block transfer routines are often used in animation sequences requiring
  134. high-performance graphics, so these routines must be as efficient as
  135. possible.  To this end, Fastgraph will force their horizontal pixel
  136. coordinates to byte boundaries, which eliminates the need to process any
  137. pixels individually.  Fastgraph accomplishes this by reducing minimum
  138. horizontal coordinates to a byte boundary and extending maximum horizontal
  139. coordinates to the last pixel in a video memory byte.  Note that since we are
  140. talking about pixel coordinates and not character cells, the coordinate
  141. modification only occurs in graphics video modes.  Designing an application
  142. so that block transfers occur on byte boundaries might take additional
  143. planning, but it will be time well spent.
  144.  
  145.      An example might best help explain this important feature.  In the
  146. EGA/VGA/SVGA 16-color graphics modes (modes 13 to 18, 28, and 29),  byte
  147. boundaries occur at every eighth pixel.  Thus, when you use the block
  148. transfer routines in these modes, Fastgraph reduces minimum x coordinates to
  149. the next lower multiple of eight.  Similarly, it extends their maximum x
  150. coordinates to the next higher multiple of eight, less one pixel.  That is,
  151. if a minimum x coordinate is 10 and a maximum x coordinate is 30, Fastgraph
  152. will modify these values to 8 and 31 respectively.  If the x coordinates were
  153. originally 8 and 31, Fastgraph would leave them unchanged.
  154.  
  155.      In the MCGA and SVGA 256-color graphics modes (modes 19 and 24 to 27)
  156. each pixel occupies a separate byte of video memory, so Fastgraph does not
  157. need to modify horizontal coordinates.  However, in the XVGA graphics modes
  158. (modes 20 to 23), some coordinate modification might be needed.  The XVGA
  159. modes store four pixels at each video memory address, one in each of four bit
  160. planes.  The bit plane number for a pixel whose horizontal coordinate is x is
  161. given by the quantity x mod 4.  In XVGA modes, the source and destination
  162. minimum x coordinates must reference pixels in the same bit plane.  Put
  163. another way, the relation
  164.  
  165.                   xmin_source mod 4 = xmin_destination mod 4
  166.  
  167. must be true.  If it isn't, Fastgraph reduces the destination minimum x value
  168. to the same bit plane as the source minimum x value.
  169.  
  170.  
  171. Dual SVGA Banks
  172.  
  173.      Accessing video memory in SVGA graphics modes is controlled through a
  174. banking scheme that maps contiguous 64KB blocks of video memory into a
  175. segmented address space.  In other words, referencing a specific byte in
  176. video memory requires a bank number and an address within that bank.  Some
  177. SVGA chipsets provide separate read and write bank registers, while others
  178. perform both operations through the same bank register.
  179.  
  180.      If a chipset supports separate read and write banks, Fastgraph's block
  181. transfer routines can copy the source region directly to the destination
  182.                                     Chapter 11:  Block Transfer Routines   225
  183. region.  However, chipsets that employ a single bank register require that
  184. these routines copy the source region to an intermediate buffer and then copy
  185. the buffer contents to the destination.  This obviously makes a block
  186. transfer operation slower on single-bank chipsets.
  187.  
  188.  
  189. The "Hidden" Video Page
  190.  
  191.      Some of Fastgraph's block transfer routines reference a video page
  192. called the hidden page.  The Fastgraph routine fg_sethpage defines which
  193. video page will be used as the hidden page.  This routine takes as its only
  194. argument an integer value specifying the hidden page number.  If you are
  195. using a virtual video page for the hidden page, you must call the fg_sethpage
  196. routine after allocating that page.  There is also a routine named
  197. fg_gethpage that returns the hidden page number, as specified in the most
  198. recent call to fg_sethpage, as its function value.  The fg_gethpage routine
  199. takes no arguments.
  200.  
  201.  
  202. Saving and Restoring Blocks
  203.  
  204.      The next two block transfer routines we'll discuss are fg_save and
  205. fg_restore.  The fg_save routine transfers a rectangular region from the
  206. active video page (as defined in the most recent call to fg_setpage) to the
  207. same position on the hidden video page (as defined in the most recent call to
  208. fg_sethpage).  The fg_restore routine performs the complementary task -- it
  209. transfers a rectangular region from the hidden page to the active page.  Each
  210. of these routines requires four arguments that define the coordinates of the
  211. block to transfer, in the order minimum x, maximum x, minimum y, and maximum
  212. y.  In text modes, the coordinates are expressed as character space
  213. quantities (rows and columns).  In graphics modes, they are expressed as
  214. screen space values (pixels), with the x coordinates extended to byte
  215. boundaries if required.  There are also world space versions of these
  216. routines named fg_savew and fg_restorew available in graphics modes.
  217.  
  218.      Example 11-2 demonstrates the use of Fastgraph's fg_save, fg_restore,
  219. and fg_sethpage routines in an 80-column text video mode.  After establishing
  220. the video mode (note the calls to fg_testmode specify that two video pages
  221. are needed), the program fills the screen with text and then waits for a
  222. keystroke.  Following this, the program displays a small pop-up window
  223. prompting for another keystroke.  After waiting for the second keystroke, the
  224. program erases the pop-up window by restoring the original screen contents,
  225. and then waits for yet another keystroke before returning to DOS.  We'll
  226. present the program now, and afterward analyze it in detail.
  227.  
  228.                                 Example 11-2.
  229.  
  230.                 #include <fastgraf.h>
  231.                 #include <stdio.h>
  232.                 #include <stdlib.h>
  233.                 void main(void);
  234.  
  235.                 void main()
  236.                 {
  237.                    int row;
  238.                    int old_mode;
  239.                    char string[17];
  240. 226   Fastgraph User's Guide
  241.  
  242.  
  243.                    old_mode = fg_getmode();
  244.  
  245.                    if (fg_testmode(3,2))
  246.                       fg_setmode(3);
  247.                    else if (fg_testmode(7,2))
  248.                       fg_setmode(7);
  249.                    else {
  250.                       printf("This program requires\n");
  251.                       printf("an 80-column display.\n");
  252.                       exit(1);
  253.                       }
  254.  
  255.                    fg_cursor(0);
  256.                    fg_setattr(9,7,0);
  257.  
  258.                    for (row = 0; row < 25; row++) {
  259.                       sprintf(string," This is row %2d ",row);
  260.                       fg_locate(row,0);
  261.                       fg_text(string,16);
  262.                       fg_text(string,16);
  263.                       fg_text(string,16);
  264.                       fg_text(string,16);
  265.                       fg_text(string,16);
  266.                       }
  267.                    fg_waitkey();
  268.  
  269.                    fg_allocate(1);
  270.                    fg_sethpage(1);
  271.                    fg_save(32,47,11,13);
  272.                    fg_setcolor(1);
  273.                    fg_rect(32,47,11,13);
  274.                    fg_setattr(15,1,0);
  275.                    fg_locate(12,33);
  276.                    fg_text("Press any key.",14);
  277.                    fg_waitkey();
  278.  
  279.                    fg_restore(32,47,11,13);
  280.                    fg_waitkey();
  281.  
  282.                    fg_freepage(1);
  283.                    fg_setmode(old_mode);
  284.                    fg_reset();
  285.                 }
  286.  
  287.      Example 11-2 first establishes the video mode and uses the fg_cursor
  288. routine to make the BIOS cursor invisible.  It then executes a for loop that
  289. fills each row of the screen with the phrase "This is row n", where n is the
  290. row number (between 0 and 24).  Next, the program uses the fg_allocate
  291. routine to create video page 1 as a virtual video page.  This is needed in
  292. case the program is running in mode 7, which has only one true page (if the
  293. program is running in mode 3, the call to fg_allocate has no effect).  The
  294. program then makes page 1 the hidden page by calling the fg_sethpage routine.
  295.  
  296.      After setting up the hidden video page, but before displaying the pop-up
  297. window, example 11-2 uses the fg_save routine to save the current contents of
  298.                                     Chapter 11:  Block Transfer Routines   227
  299. the area that the pop-up window will replace.  The fg_save routine copies
  300. this region to the hidden page.  The program then displays the pop-up window
  301. in the middle of the screen and leaves it there until a key is pressed.
  302. Following this, the program uses the fg_restore routine to replace the pop-up
  303. window with the original contents of that region.  This effectively erases
  304. the pop-up window and restores the original screen.  The program then waits
  305. for another keystroke, after which it releases the virtual page and returns
  306. to DOS.
  307.  
  308.      The next example, 11-3, is similar to example 11-2, but it runs in a 320
  309. by 200 color graphics mode instead of a text mode.  The main differences
  310. between this program and example 11-2 are the use of 40-column text and the
  311. use of screen space coordinates instead of character space coordinates in the
  312. calls to fg_save, fg_restore, and fg_rect.  Note that the call to fg_allocate
  313. creates a virtual page if the program is running in modes 4, 9, or 19.  In
  314. modes 13 and 20, which respectively have four and eight physical pages,
  315. fg_allocate does nothing.
  316.  
  317.                                 Example 11-3.
  318.  
  319.               #include <fastgraf.h>
  320.               #include <stdio.h>
  321.               #include <stdlib.h>
  322.               void main(void);
  323.  
  324.               void main()
  325.               {
  326.                  int row;
  327.                  int new_mode, old_mode;
  328.                  char string[21];
  329.  
  330.                  new_mode = fg_bestmode(320,200,2);
  331.                  if (new_mode < 0 || new_mode == 12) {
  332.                     printf("This program requires a 320 ");
  333.                     printf("x 200 color graphics mode.\n");
  334.                     exit(1);
  335.                     }
  336.                  old_mode = fg_getmode();
  337.                  fg_setmode(new_mode);
  338.  
  339.                  fg_setcolor(7);
  340.                  fg_rect(0,319,0,199);
  341.                  fg_setcolor(9);
  342.  
  343.                  for (row = 0; row < 25; row++) {
  344.                     sprintf(string,"   This is row %2d   ",row);
  345.                     fg_locate(row,0);
  346.                     fg_text(string,20);
  347.                     fg_text(string,20);
  348.                     }
  349.                  fg_waitkey();
  350.  
  351.                  fg_allocate(1);
  352.                  fg_sethpage(1);
  353.                  fg_save(96,223,88,111);
  354.                  fg_setcolor(1);
  355.                  fg_rect(96,223,88,111);
  356. 228   Fastgraph User's Guide
  357.  
  358.                  fg_setcolor(15);
  359.                  fg_locate(12,13);
  360.                  fg_text("Press any key.",14);
  361.                  fg_waitkey();
  362.  
  363.                  fg_restore(96,223,88,111);
  364.                  fg_waitkey();
  365.  
  366.                  fg_freepage(1);
  367.                  fg_setmode(old_mode);
  368.                  fg_reset();
  369.               }
  370.  
  371.  
  372.  
  373. A More General Block Transfer Routine
  374.  
  375.      The fg_save and fg_restore routines each copy a rectangular region from
  376. one video page to the same position on another video page.  What if you need
  377. to copy the region to a different position on another video page, or copy it
  378. elsewhere on the same video page?  Fastgraph provides a more general block
  379. transfer routine named fg_transfer.  The fg_transfer routine copies a
  380. rectangular region on any video page to any position on any video page.  Like
  381. fg_save and fg_restore, the fg_transfer routine works in text and graphics
  382. video modes.  In graphics modes, fg_transfer extends its x coordinates to
  383. byte boundaries if necessary.
  384.  
  385.      The fg_transfer routine requires eight integer arguments.  The first
  386. four arguments define the region to copy, in the same order as expected by
  387. fg_save and fg_restore.  The next two arguments define the lower left corner
  388. of the block destination, while the final two arguments respectively specify
  389. the source and destination video page numbers.  In short, fg_transfer copies
  390. the specified region from the source page to the specified position on the
  391. destination page.
  392.  
  393.      Example 11-4 is the same as example 11-2, but it uses fg_transfer rather
  394. than fg_save and fg_restore.  We have arbitrarily chosen to copy the region
  395. overwritten by the pop-up window to the lower left corner of the hidden page
  396. (page 1).  When we copy this region back to the visual page, we copy from the
  397. lower left corner of the hidden page back to the original position on the
  398. visual page (page 0).  This sequence is shown in the following diagram.
  399.  
  400.              (11,32)    (11,47)               (22,0)     (22,15)
  401.                                 first call
  402.                This is row 11   ------------>   This is row 11
  403.                This is row 12                   This is row 12
  404.                This is row 13   <------------   This is row 13
  405.                                   second call
  406.              (13,32)    (13,47)               (24,0)     (24,15)
  407.  
  408.                 visual page (0)                  hidden page (1)
  409.  
  410. To copy one region to a new position and then back to its original position,
  411. note how we make the fifth and sixth arguments in the first call to
  412. fg_transfer the same values as the first and fourth arguments in the second
  413. call.  Similarly, the fifth and sixth arguments in the second call must be
  414.                                     Chapter 11:  Block Transfer Routines   229
  415. the same as the first and fourth arguments in the first call.  With all that
  416. out of the way, here is example 11-4.
  417.  
  418.                                 Example 11-4.
  419.  
  420.                 #include <fastgraf.h>
  421.                 #include <stdio.h>
  422.                 #include <stdlib.h>
  423.                 void main(void);
  424.  
  425.                 void main()
  426.                 {
  427.                    int row;
  428.                    int old_mode;
  429.                    char string[17];
  430.  
  431.                    old_mode = fg_getmode();
  432.                    if (fg_testmode(3,2))
  433.                       fg_setmode(3);
  434.                    else if (fg_testmode(7,2))
  435.                       fg_setmode(7);
  436.                    else {
  437.                       printf("This program requires\n");
  438.                       printf("an 80-column display.\n");
  439.                       exit(1);
  440.                       }
  441.  
  442.                    fg_cursor(0);
  443.                    fg_setattr(9,7,0);
  444.  
  445.                    for (row = 0; row < 25; row++) {
  446.                       sprintf(string," This is row %2d ",row);
  447.                       fg_locate(row,0);
  448.                       fg_text(string,16);
  449.                       fg_text(string,16);
  450.                       fg_text(string,16);
  451.                       fg_text(string,16);
  452.                       fg_text(string,16);
  453.                       }
  454.                    fg_waitkey();
  455.  
  456.                    fg_allocate(1);
  457.                    fg_transfer(32,47,11,13,0,24,0,1);
  458.                    fg_setcolor(1);
  459.                    fg_rect(32,47,11,13);
  460.                    fg_setattr(15,1,0);
  461.                    fg_locate(12,33);
  462.                    fg_text("Press any key.",14);
  463.                    fg_waitkey();
  464.  
  465.                    fg_transfer(0,15,22,24,32,13,1,0);
  466.                    fg_fg_waitkey();
  467.  
  468.                    fg_freepage(1);
  469.                    fg_setmode(old_mode);
  470.                    fg_reset();
  471.                 }
  472. 230   Fastgraph User's Guide
  473.  
  474.      Example 11-5 illustrates another use of the fg_transfer routine.  This
  475. example is functionally identical to example 10-10, but it uses fg_transfer
  476. instead of fg_getmap and fg_drawmap.  With the fg_transfer routine, we
  477. eliminate the calls to fg_getmap and fg_drawmap, the two calls to fg_move,
  478. and the 32-byte array needed to retrieve the block.  As an added bonus, using
  479. fg_transfer is much faster than the technique of example 10-10, although we
  480. probably won't notice this gain with such a small block.
  481.  
  482.      The block copied in example 11-5 is one row of four characters, so its
  483. width in screen space is 32 pixels and its height is 8 pixels.  Because the
  484. block is in the upper left corner of the screen, the block boundaries are
  485. xmin=0, xmax=31, ymin=0, and ymax=7.  We want to move the block one-half
  486. character cell (4 pixels) to the right and one row (8 pixels) down, so our
  487. destination coordinates are x=4 (xmin+4) and y=15 (ymax+8).  Note how the
  488. program restricts itself to modes 19 and 20 to insure the block copy is not
  489. affected by byte boundaries.  Also, we are copying the block from one
  490. position to another on the visual page, so both the source and destination
  491. pages are 0.
  492.  
  493.                                 Example 11-5.
  494.  
  495.                  #include <fastgraf.h>
  496.                  #include <stdio.h>
  497.                  #include <stdlib.h>
  498.                  void main(void);
  499.  
  500.                  void main()
  501.                  {
  502.                     int old_mode, new_mode;
  503.  
  504.                     new_mode = fg_bestmode(320,200,1);
  505.                     if (new_mode < 19) {
  506.                        printf("This program requires a ");
  507.                        printf("256-color graphics mode.\n");
  508.                        exit(1);
  509.                        }
  510.  
  511.                     old_mode = fg_getmode();
  512.                     fg_setmode(new_mode);
  513.  
  514.                     fg_setcolor(9);
  515.                     fg_text("text",4);
  516.                     fg_waitkey();
  517.  
  518.                     fg_transfer(0,31,0,7,4,15,0,0);
  519.                     fg_waitkey();
  520.  
  521.                     fg_setmode(old_mode);
  522.                     fg_reset();
  523.                  }
  524.  
  525.  
  526.      Example 11-6 shows yet another application of the fg_transfer routine in
  527. a graphics video mode.  The program displays a rectangle in the upper left
  528.                                     Chapter 11:  Block Transfer Routines   231
  529.  
  530. quadrant of the screen and then centers the word "quadrant" inside the
  531. rectangle.  After waiting for a keystroke, the program uses fg_transfer to
  532. first copy the upper left quadrant to the upper right quadrant.  It then uses
  533. fg_transfer again to copy the upper half of the screen to the lower half.
  534. The result of this is the screen being filled with what was originally in the
  535. upper left quadrant.
  536.  
  537.                                 Example 11-6.
  538.  
  539.                 #include <fastgraf.h>
  540.                 #include <stdio.h>
  541.                 #include <stdlib.h>
  542.                 void main(void);
  543.  
  544.                 void main()
  545.                 {
  546.                    int new_mode, old_mode;
  547.  
  548.                    new_mode = fg_bestmode(320,200,1);
  549.                    if (new_mode < 0 || new_mode == 12) {
  550.                       printf("This program requires a 320 ");
  551.                       printf("x 200 color graphics mode.\n");
  552.                       exit(1);
  553.                       }
  554.                    old_mode = fg_getmode();
  555.                    fg_setmode(new_mode);
  556.  
  557.                    fg_setcolor(7);
  558.                    fg_rect(0,159,0,99);
  559.                    fg_setcolor(9);
  560.                    fg_locate(6,6);
  561.                    fg_text("quadrant",8);
  562.                    fg_waitkey();
  563.  
  564.                    fg_transfer(0,159,0,99,160, 99,0,0);
  565.                    fg_transfer(0,319,0,99,  0,199,0,0);
  566.                    fg_waitkey();
  567.  
  568.                    fg_setmode(old_mode);
  569.                    fg_reset();
  570.                 }
  571.  
  572.  
  573.  
  574. Blocks with Transparent Colors
  575.  
  576.      The final routines pertaining to block transfer are fg_tcxfer,
  577. fg_tcmask, and fg_tcdefine.  The fg_tcxfer routine is similar to fg_transfer
  578. in that it copies a rectangular region from one position to another, but
  579. fg_tcxfer allows you to treat one or more colors as transparent (the name
  580. fg_tcxfer stands for transparent color transfer).  In other words, any pixel
  581. whose color value is defined to be transparent is not copied to the
  582. destination area.  The fg_tcxfer routine's arguments are the same as for the
  583. fg_transfer routine, but fg_tcxfer has no effect in text video modes.
  584. Because fg_tcxfer must examine the color of individual pixels, it is not
  585. nearly as fast as fg_transfer.
  586. 232   Fastgraph User's Guide
  587.  
  588.      You can use either fg_tcmask or fg_tcdefine to define which colors are
  589. considered transparent in subsequent calls to fg_tcxfer.  The fg_tcmask
  590. routine's argument is an integer bit mask (specifically, a 16-bit mask) where
  591. each bit indicates whether or not the color is transparent.  For example, if
  592. bit 0 (the rightmost bit) is set in the mask, then color 0 will be
  593. transparent; if bit 0 is reset, color 0 will not be transparent.  Because the
  594. bit mask size is 16 bits, only the first 16 color values may be defined as
  595. transparent using fg_tcmask.
  596.  
  597.      Example 11-7 illustrates the use of the fg_tcxfer and fg_tcmask
  598. routines.  This program is similar to example 11-6, except the color of the
  599. word "quadrant" (color 9) is defined to be transparent, and fg_tcxfer is used
  600. in place of fg_transfer.  Because color 9 maps to color 1 in the CGA four-
  601. color graphics mode (mode 4), we must define both colors 1 and 9 to be
  602. transparent (remember, fg_tcmask considers actual color values transparent,
  603. not color indices).  The bit mask passed to fg_tcmask thus will be 0000 0010
  604. 0000 0010 binary, or 0202 hex.  This causes the word "quadrant" to appear in
  605. the background color (color 0) instead of color 9 in the upper right, lower
  606. left, and lower right quadrants.
  607.  
  608.                                 Example 11-7.
  609.  
  610.                 #include <fastgraf.h>
  611.                 #include <stdio.h>
  612.                 #include <stdlib.h>
  613.                 void main(void);
  614.  
  615.                 void main()
  616.                 {
  617.                    int new_mode, old_mode;
  618.  
  619.                    new_mode = fg_bestmode(320,200,1);
  620.                    if (new_mode < 0 || new_mode == 12) {
  621.                       printf("This program requires a 320 ");
  622.                       printf("x 200 color graphics mode.\n");
  623.                       exit(1);
  624.                       }
  625.                    old_mode = fg_getmode();
  626.                    fg_setmode(new_mode);
  627.  
  628.                    fg_setcolor(7);
  629.                    fg_rect(0,159,0,99);
  630.                    fg_setcolor(9);
  631.                    fg_locate(6,6);
  632.                    fg_text("quadrant",8);
  633.                    fg_waitkey();
  634.  
  635.                    fg_tcmask(0x0202);
  636.                    fg_tcxfer(0,159,0,99,160, 99,0,0);
  637.                    fg_tcxfer(0,319,0,99,  0,199,0,0);
  638.                    fg_waitkey();
  639.  
  640.                    fg_setmode(old_mode);
  641.                    fg_reset();
  642.                 }
  643.  
  644.                                     Chapter 11:  Block Transfer Routines   233
  645.  
  646.      The fg_tcdefine routine expects two integer arguments -- one defining
  647. the color number (between 0 and 255) and another defining the transparency
  648. state associated with that color.  If the state is zero, the specified color
  649. will be opaque (non-transparent).  If it is any other value, the color will
  650. be transparent.  In the previous example, we could use fg_tcdefine instead of
  651. fg_tcmask to make colors 1 and 9 transparent by replacing the call to
  652. fg_tcmask with the following:
  653.  
  654.                               fg_tcdefine(1,1);
  655.                               fg_tcdefine(9,1);
  656.  
  657. If you don't call fg_tcmask or fg_tcdefine, the fg_tcxfer routine considers
  658. no colors transparent.
  659.  
  660.  
  661. Transferring Blocks to and from Conventional Memory
  662.  
  663.      The final two block transfer routines we'll discuss are fg_getblock and
  664. fg_putblock.  The fg_getblock routine transfers a rectangular region from the
  665. active video page to a buffer (you can use fg_imagesiz to determine the
  666. buffer size needed to store the block).  The fg_putblock routine transfers a
  667. block previously retrieved with fg_getblock to the active page.  While these
  668. two routines are faster than fg_getimage and fg_putimage, they are not as
  669. fast as fg_restore, fg_save, and fg_transfer.
  670.  
  671.      Each of these routines requires five arguments.  The first is the
  672. address of the buffer that will receive or that contains the block.  The
  673. remaining four arguments define the position of the block on the active page,
  674. in the order minimum x, maximum x, minimum y, and maximum y.  In text modes,
  675. the coordinates are expressed as character space quantities (rows and
  676. columns).  In graphics modes, they are expressed as screen space values
  677. (pixels), with the x coordinates extended to byte boundaries if required.
  678.  
  679.      Note that both fg_getblock and fg_putblock expect the buffer address to
  680. be passed by far reference except in QuickBASIC.  This means Pascal programs
  681. must use the GetMem procedure to allocate storage for the buffer, as this is
  682. the only way to pass something by far reference in Pascal.  Regardless of
  683. which compiler you're using, the maximum size of a block is 64K bytes.
  684.  
  685.      Example 11-8 is similar to example 11-5 and shows fg_getblock and
  686. fg_putblock in action in a 320 by 200 graphics mode.  The program displays
  687. the word "text" and retrieves it into a 32 by 8 pixel block.  After a
  688. keystroke, it displays the block 8 pixels below and 8 pixels to the right of
  689. its original position.  The size of the buffer was chosen to be 256 bytes to
  690. accommodate the largest size required for a 32 by 8 block (which occurs in
  691. the 256-color graphics modes).  Note also how the source and destination
  692. horizontal block extremes were chosen for byte boundary alignment in case
  693. fg_bestmode selected a 16-color graphics mode.
  694.  
  695.                                 Example 11-8.
  696.  
  697.                 #include <fastgraf.h>
  698.                 #include <stdio.h>
  699.                 #include <stdlib.h>
  700.                 void main(void);
  701.  
  702. 234   Fastgraph User's Guide
  703.  
  704.  
  705.                 char far buffer[256];
  706.  
  707.                 void main()
  708.                 {
  709.                    int old_mode, new_mode;
  710.  
  711.                    new_mode = fg_bestmode(320,200,1);
  712.                    if (new_mode < 0 || new_mode == 12) {
  713.                       printf("This program requires a 320 ");
  714.                       printf("x 200 color graphics mode.\n");
  715.                       exit(1);
  716.                       }
  717.  
  718.                    old_mode = fg_getmode();
  719.                    fg_setmode(new_mode);
  720.  
  721.                    fg_setcolor(9);
  722.                    fg_text("text",4);
  723.                    fg_getblock(buffer,0,31,0,7);
  724.                    fg_waitkey();
  725.  
  726.                    fg_putblock(buffer,8,39,8,15);
  727.                    fg_waitkey();
  728.  
  729.                    fg_setmode(old_mode);
  730.                    fg_reset();
  731.                 }
  732.  
  733.  
  734. Summary of Block Transfer Routines
  735.  
  736.      This section summarizes the functional descriptions of the Fastgraph
  737. routines presented in this chapter.  More detailed information about these
  738. routines, including their arguments and return values, may be found in the
  739. Fastgraph Reference Manual.
  740.  
  741.      For all block transfer routines, Fastgraph extends the horizontal pixel
  742. coordinates to a byte boundary when the routines are used in a graphics video
  743. mode.
  744.  
  745.      FG_COPYPAGE transfers the contents of one video page to another.  The
  746. pages may be physical, virtual, or logical video pages.  If both pages are
  747. logical pages, they must exist in the same type of memory.
  748.  
  749.      FG_GETBLOCK retrieves the block (for later display with fg_putblock) at
  750. the specified position on the active video page.  In text modes, the block
  751. extremes are defined in character space; in graphics modes, they are defined
  752. in screen space.
  753.  
  754.      FG_GETHPAGE returns the hidden page number, as defined in the most
  755. recent call to fg_sethpage.
  756.  
  757.      FG_PUTBLOCK displays the block (previously obtained with fg_getblock) at
  758. the specified position on the active video page.  In text modes, the block
  759.                                     Chapter 11:  Block Transfer Routines   235
  760.  
  761. extremes are defined in character space; in graphics modes, they are defined
  762. in screen space.
  763.  
  764.      FG_RESTORE copies a block from the hidden video page to the same
  765. position on the active video page.
  766.  
  767.      FG_RESTOREW is the same as fg_restore, but the block extremes are
  768. specified as world space coordinates.
  769.  
  770.      FG_SAVE copies a block from the active video page to the same position
  771. on the hidden video page.
  772.  
  773.      FG_SAVEW is the same as fg_save, but the block extremes are specified as
  774. world space coordinates.
  775.  
  776.      FG_SETHPAGE defines the hidden video page (used by fg_restore,
  777. fg_restorew, fg_save, and fg_savew).
  778.  
  779.      FG_TCDEFINE defines the transparent attribute of a color index for use
  780. with the fg_tcxfer routine.  This routine has no effect when used in a text
  781. video mode.
  782.  
  783.      FG_TCMASK defines which of the first 16 colors the fg_tcxfer routine
  784. will consider transparent.  This routine has no effect when used in a text
  785. video mode.
  786.  
  787.      FG_TCXFER copies a block from any position on any video page to any
  788. position on any video page, excluding any pixels whose color value is
  789. transparent.  This routine has no effect when used in a text video mode.
  790.  
  791.      FG_TRANSFER copies a block from any position on any video page to any
  792. position on any video page.  It is Fastgraph's most general block transfer
  793. routine.
  794. 236   Fastgraph User's Guide