Fastgraph (tm) User's Guide Copyright (c) 1991 All Rights Reserved Ted Gruber Software PO Box 13408 Las Vegas, NV 89112 (702) 735-1980 Copyright (c) 1991 by Ted Gruber Software. All rights reserved. This publication and its associated software are sold without warranties, either expressed or implied, regarding their merchantability or fitness for any particular application or purpose. The information in this publication is subject to change without notice and does not represent a commitment on the part of Ted Gruber Software. In no event shall Ted Gruber Software be liable for any loss of profit or any other commercial damage, including but not limited to special, incidental, consequential, or other damages resulting from the use of or the inability to use this product, even if Ted Gruber Software has been notified of the possibility of such damages. First Printing, June 1991 Fastgraph version 2.00 Fastgraph/Light version 1.00 DFI is a registered trademark of Diamond Flower Electric Instrument Co., Inc. Fastgraph and Fastgraph/Light are trademarks of Ted Gruber Software. Hercules is a trademark of Hercules Computer Technology. IBM, IBM PC, IBM PC/XT, IBM PC/AT, PS/2, PCjr, and PC-DOS are registered trademarks of International Business Machines, Inc. Logitech is a trademark of LOGITECH, Inc. Microsoft, Microsoft Mouse, and MS-DOS are registered trademarks of Microsoft Corporation. QuickBASIC and QuickC are trademarks of Microsoft Corporation. Tandy is a registered trademark of Tandy Corporation. Turbo C is a registered trademark of Borland International, Inc. All other brand and product names mentioned in this publication are trademarks or registered trademarks of their respective holders. T a b l e o f C o n t e n t s Chapter 1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 What is Fastgraph? . . . . . . . . . . . . . . . . . . . . . . . . . 2 Fastgraph/Light . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Prerequisite Knowledge . . . . . . . . . . . . . . . . . . . . . . . 2 Supported Compilers . . . . . . . . . . . . . . . . . . . . . . . . 3 Installing Fastgraph . . . . . . . . . . . . . . . . . . . . . . . . 3 Fastgraph Naming Conventions . . . . . . . . . . . . . . . . . . . . 4 Compilation and Linking . . . . . . . . . . . . . . . . . . . . . . 5 Microsoft C . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Microsoft QuickC . . . . . . . . . . . . . . . . . . . . . . . 6 Turbo C . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Microsoft QuickBASIC . . . . . . . . . . . . . . . . . . . . . 9 Microsoft FORTRAN . . . . . . . . . . . . . . . . . . . . . . . 11 Fastgraph/Light Video Driver . . . . . . . . . . . . . . . . . . . . 12 Chapter 2 PC and PS/2 Video Modes . . . . . . . . . . . . . . . . . . . . . . . . . 15 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Text Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Graphics Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Chapter 3 Initializing the Video Environment . . . . . . . . . . . . . . . . . . . 27 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Establishing a Text Mode . . . . . . . . . . . . . . . . . . . . . . 28 Establishing a Graphics Mode . . . . . . . . . . . . . . . . . . . . 31 Summary of Video Initialization Routines . . . . . . . . . . . . . . 34 Chapter 4 Coordinate Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Character Space . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Screen Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 World Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Conversion Routines . . . . . . . . . . . . . . . . . . . . . . . . 41 Summary of Coordinate Routines . . . . . . . . . . . . . . . . . . . 42 Chapter 5 The Use of Color . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 Text Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 Color Modes . . . . . . . . . . . . . . . . . . . . . . . . . . 44 Monochrome Mode . . . . . . . . . . . . . . . . . . . . . . . . 45 Graphics Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 CGA Color Modes . . . . . . . . . . . . . . . . . . . . . . . . 47 CGA Two-Color Mode . . . . . . . . . . . . . . . . . . . . . . 48 Tandy and PCjr Modes . . . . . . . . . . . . . . . . . . . . . 49 Hercules Mode . . . . . . . . . . . . . . . . . . . . . . . . . 50 Hercules Low-Resolution Mode . . . . . . . . . . . . . . . . . 51 EGA 200-Line Modes . . . . . . . . . . . . . . . . . . . . . . 52 EGA Monochrome Mode . . . . . . . . . . . . . . . . . . . . . . 54 EGA Enhanced Mode . . . . . . . . . . . . . . . . . . . . . . . 55 VGA and MCGA Two-Color Mode . . . . . . . . . . . . . . . . . . 57 VGA 16-Color Mode . . . . . . . . . . . . . . . . . . . . . . . 59 VGA and MCGA 256-Color Modes . . . . . . . . . . . . . . . . . 60 Defining All Palette Registers . . . . . . . . . . . . . . . . . . . 62 Virtual Colors . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 A Multiple-Mode Example . . . . . . . . . . . . . . . . . . . . . . 65 Summary of Color-Related Routines . . . . . . . . . . . . . . . . . 67 Chapter 6 Graphics Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 Clearing the Screen . . . . . . . . . . . . . . . . . . . . . . . . 70 Clipping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 The Graphics Cursor . . . . . . . . . . . . . . . . . . . . . . . . 73 Solid Lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Dashed Lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Polygons, Circles, and Ellipses . . . . . . . . . . . . . . . . . . 77 Solid Rectangles . . . . . . . . . . . . . . . . . . . . . . . . . . 80 Dithered Rectangles . . . . . . . . . . . . . . . . . . . . . . . . 81 Region Fill . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Summary of Fundamental Graphics Routines . . . . . . . . . . . . . . 89 Chapter 7 Character Display Routines . . . . . . . . . . . . . . . . . . . . . . . 93 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Character Space . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Hardware Characters . . . . . . . . . . . . . . . . . . . . . . . . 95 Conversion Routines . . . . . . . . . . . . . . . . . . . . . . . . 100 Software Characters . . . . . . . . . . . . . . . . . . . . . . . . 101 Bit-Mapped Characters . . . . . . . . . . . . . . . . . . . . . . . 107 Summary of Character Display Routines . . . . . . . . . . . . . . . 107 Chapter 8 Video Page Management . . . . . . . . . . . . . . . . . . . . . . . . . . 109 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 Physical Pages and Virtual Pages . . . . . . . . . . . . . . . . . . 110 Pages With Special Meanings . . . . . . . . . . . . . . . . . . . . 111 Some Simple Examples . . . . . . . . . . . . . . . . . . . . . . . . 111 Text Cursors . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Obtaining Video Page Information . . . . . . . . . . . . . . . . . . 119 Considerations for Virtual Pages . . . . . . . . . . . . . . . . . . 120 Summary of Video Page Management Routines . . . . . . . . . . . . . 120 Chapter 9 Images and Image Management . . . . . . . . . . . . . . . . . . . . . . . 121 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 Mode-Independent Bit-Mapped Images . . . . . . . . . . . . . . . . . 122 Mode-Specific Bit-Mapped Images . . . . . . . . . . . . . . . . . . 126 Regular Images . . . . . . . . . . . . . . . . . . . . . . . . 127 Clipped Images . . . . . . . . . . . . . . . . . . . . . . . . 134 Reversed Images . . . . . . . . . . . . . . . . . . . . . . . . 135 Reversed Clipped Images . . . . . . . . . . . . . . . . . . . . 135 Some Examples . . . . . . . . . . . . . . . . . . . . . . . . . 135 Pixel Run Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Display Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . 144 Masking Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 Retrieving Images . . . . . . . . . . . . . . . . . . . . . . . . . 153 Byte Boundaries . . . . . . . . . . . . . . . . . . . . . . . . . . 158 Image Transfer Routines . . . . . . . . . . . . . . . . . . . . . . 159 Summary of Image Display Routines . . . . . . . . . . . . . . . . . 167 Chapter 10 Animation Techniques . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 Simple Animation . . . . . . . . . . . . . . . . . . . . . . . . . . 170 XOR Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 Static Frame Animation . . . . . . . . . . . . . . . . . . . . . . . 173 Dynamic Frame Animation . . . . . . . . . . . . . . . . . . . . . . 176 Page Flipping . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Summary of Animation Techniques . . . . . . . . . . . . . . . . . . 179 Chapter 11 Special Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 Screen Dissolving . . . . . . . . . . . . . . . . . . . . . . . . . 182 Scrolling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 Changing the Screen Origin . . . . . . . . . . . . . . . . . . . . . 187 Summary of Special Effects Routines . . . . . . . . . . . . . . . . 188 Chapter 12 Input Device Support . . . . . . . . . . . . . . . . . . . . . . . . . . 191 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192 Keyboard Support . . . . . . . . . . . . . . . . . . . . . . . . . . 192 Reading Keystrokes . . . . . . . . . . . . . . . . . . . . . . 194 Testing and Setting Key States . . . . . . . . . . . . . . . . 196 Mouse Support . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Initializing the Mouse . . . . . . . . . . . . . . . . . . . . 197 Controlling the Mouse Cursor . . . . . . . . . . . . . . . . . 198 Reporting the Mouse Status . . . . . . . . . . . . . . . . . . 200 Defining the Mouse Cursor . . . . . . . . . . . . . . . . . . . 202 Joystick Support . . . . . . . . . . . . . . . . . . . . . . . . . . 210 Initializing Joysticks . . . . . . . . . . . . . . . . . . . . 210 Reporting Joystick Status . . . . . . . . . . . . . . . . . . . 211 Keyboard Emulation . . . . . . . . . . . . . . . . . . . . . . 213 Special Joystick Considerations . . . . . . . . . . . . . . . . 214 Summary of Input Routines . . . . . . . . . . . . . . . . . . . . . 214 Chapter 13 Sound Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 Sound Sources . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 Synchronous Sound . . . . . . . . . . . . . . . . . . . . . . . . . 218 Asynchronous Sound . . . . . . . . . . . . . . . . . . . . . . . . . 223 Summary of Sound Routines . . . . . . . . . . . . . . . . . . . . . 228 Chapter 14 Program Timing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 Real-Time Routines . . . . . . . . . . . . . . . . . . . . . . . . . 230 Routines Dependent on the System Speed . . . . . . . . . . . . . . . 231 Summary of Timing Routines . . . . . . . . . . . . . . . . . . . . . 233 Chapter 15 Miscellaneous Routines . . . . . . . . . . . . . . . . . . . . . . . . . 235 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 Determining Available Memory . . . . . . . . . . . . . . . . . . . . 236 Choosing the Video Memory Update Function . . . . . . . . . . . . . 237 Summary of Miscellaneous Routines . . . . . . . . . . . . . . . . . 238 Appendix A Fastgraph Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 SNAPSHOT Utility . . . . . . . . . . . . . . . . . . . . . . . . . . 240 CLIP Utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 CONVERT Utility . . . . . . . . . . . . . . . . . . . . . . . . . . 243 Appendix B Using Fastgraph from Assembly Language . . . . . . . . . . . . . . . . . 245 Appendix C Interrupts and Fastgraph . . . . . . . . . . . . . . . . . . . . . . . . 249 Interrupts Used by Fastgraph . . . . . . . . . . . . . . . . . . . . 250 Extending the Time-of-Day Interrupt . . . . . . . . . . . . . . . . 250 Appendix D Contents of the Compiler-Specific Libraries . . . . . . . . . . . . . . . 253 Chapter 1 Introduction 2 Fastgraph User's Guide What is Fastgraph? Fastgraph is a library of more than 150 highly-optimized routines that are callable from high-level and assembly language programs running under the MS-DOS or PC-DOS operating systems. This collection of routines provides a programmer with proven, powerful tools to take command of the PC and PS/2 video environment. In addition to its video support, Fastgraph also contains routines to perform keyboard, mouse, and joystick control, as well as music and sound capabilities. Fastgraph is an ideal development tool for entertainment and educational software, presentation graphics products, scientific and engineering applications, CAD/CAM, animation, or just about any application that requires robust graphics. As its name implies, the most notable feature of Fastgraph is its speed. Virtually all of Fastgraph is written in 8086 assembly language, and each routine has been optimized by hand to provide maximum performance. Fastgraph supports all of the standard text and graphics video modes used by the IBM PC (PC, PC/XT, and PC/AT) and PS/2 families and compatible systems. In addition, Fastgraph provides support for a commonly used video mode for the Tandy 1000 series computers and the PCjr. Even though the graphics mode of the Hercules Graphics Card is not an IBM standard, its popularity has made it a de facto standard, and for this reason Fastgraph also supports it. A complete discussion of all of Fastgraph's supported video modes appears in the next chapter. Fastgraph/Light Fastgraph/Light is a subset of Fastgraph. It includes all of Fastgraph's features except the redefinable world space coordinate system and the routines pertaining to software characters. Programs created using Fastgraph/Light are 100% source code compatible with Fastgraph. The most important difference between Fastgraph/Light and Fastgraph is the method of running a program created with the two products. With Fastgraph, any of its routines used in your program are linked directly into the resulting .EXE file. With Fastgraph/Light, however, this is not the case. Instead, the Fastgraph/Light routines provide an interface to an external driver, called the Fastgraph/Light Video Driver, which must be loaded separately before running programs that call any Fastgraph/Light routines. A further discussion of this driver begins on page 12. In this document, and in the accompanying Fastgraph Reference Manual, references to Fastgraph also apply to Fastgraph/Light unless stated otherwise. Prerequisite Knowledge Fastgraph is a programming tool, which means programmers are its intended audience. For this reason, the Fastgraph User's Guide and the accompanying Fastgraph Reference Manual assume you have a knowledge of programming. Virtually all of the examples in these two references are written in the C programming language, so a knowledge of C would be especially helpful. However, the examples intentionally avoid using any of Chapter 1: Introduction 3 C's features that might not be readily apparent to a programmer unfamiliar with C. Additionally, a knowledge of converting numbers between binary, decimal, and hexadecimal is assumed. Supported Compilers You can use Fastgraph with any compilers or assemblers that use the same calling and naming conventions as the small, medium, or large memory models of the supported compilers. Mixed language programming is allowed to the extent it is supported by the language translators and linker being used. The following compilers are supported at this time: Microsoft C (version 5.0 or later) Microsoft QuickC (version 1.01 or later) Borland's Turbo C (version 2.0 or later) Microsoft QuickBASIC (version 4.0 or later) Microsoft FORTRAN (version 4.0 or later) The listed version numbers are the compiler versions under which Fastgraph was developed and tested. Fastgraph may or may not work with earlier versions of these compilers. The use of Fastgraph from assembly language programs is addressed in Appendix B. Installing Fastgraph This section explains how to use the INSTALL program to load Fastgraph (or Fastgraph/Light) and its related files on a hard disk. The installation program lets you select the compilers and memory models you wish to use with Fastgraph. It also gives you the opportunity to load many example Fastgraph programs specific to the compilers you choose. Before you start the installation, you should use the DOS commands COPY or DISKCOPY to make working copies of the distribution disks (refer to your DOS reference manual if you are not familiar with these commands). Once you have created the working copies, store the original disks in a safe place. Install Fastgraph from the working copies you just created. For simplicity, we'll assume you are installing Fastgraph from the diskette drive A: to the hard drive C:, but you can of course use any available drives. The Fastgraph distribution disk labeled "Installation and Utilities" contains Fastgraph's INSTALL program. Place this disk in the A: drive, make A: your current drive, and enter the command INSTALL, as shown below. C> A: A> INSTALL From this point, just follow the directions on each screen. At any time, you can press the Esc key to abort the installation. 4 Fastgraph User's Guide You can install support for additional compilers or memory models at any time. If you choose to do this, you should use the command INSTALL /L to avoid copying the files common to all compilers and memory models. Fastgraph Naming Conventions The names of all Fastgraph routines begin with the three characters "fg_". This prefix helps identify Fastgraph routines within a program, and it also reduces the possibility of name conflicts that might otherwise occur between Fastgraph and other third party libraries. Because QuickBASIC does not permit underscores in identifiers, the QuickBASIC versions of Fastgraph routines begin with the two characters "FG". For example, the fg_version routine is named FGversion in the QuickBASIC libraries. All subsequent references to Fastgraph routines in this manual and the accompanying Fastgraph Reference Manual will use the fg_ naming convention instead of the QuickBASIC names. Chapter 1: Introduction 5 Compilation and Linking To build an executable (.EXE) file for a program that uses Fastgraph routines, first compile or assemble the program using the small, medium, or large memory model. This step produces an object (.OBJ) file, which is then linked with Fastgraph and any other object libraries to produce an executable file. The following sections show the simplest compilation and linking procedures for each of the supported compilers. Example 1-1 is a C program that uses the Fastgraph routine fg_version to display the version number for your copy of Fastgraph (QuickBASIC and FORTRAN versions of this program are presented in the sections that discuss those compilers). If you loaded the example programs when you installed Fastgraph, the file \FG\EXAMPLES\01-01.C contains the source code for this program. You can use example 1-1 to test the compilation and linking process for the memory models and compilers you'll be using with Fastgraph. Example 1-1. #include #include main() { int major; int minor; fg_version(&major,&minor); printf("This is version %d.%2.2d of Fastgraph.\n",major,minor); } The file FASTGRAF.H contains the C function prototypes for each Fastgraph routine. It should reside in the directory where the compiler normally searches for other .H files. For the Microsoft C or QuickC compilers, FASTGRAF.H can instead reside in any of the directories specified by the INCLUDE environment variable. Microsoft C Microsoft C programs are compiled and linked by entering a CL command at the DOS command prompt. The format of the CL command for compiling a program and linking it with Fastgraph is CL /link [] [/E] where: specifies the compiler memory model you'll be using. It must be either /AS (for the small model), /AM (for the medium model), or /AL (for the large model). 6 Fastgraph User's Guide is the name of the file containing your program. It may include a path specification. is the name of a standard Fastgraph/Light or Fastgraph library. For Fastgraph/Light, the library name is FGLS (for the small model), FGLM (for the medium model), or FGLL (for the large model). For Fastgraph, the library name is FGS (for the small model), FGM (for the medium model), or FGL (for the large model). is the name of an optional compiler-specific extended Fastgraph library. You need to specify an extended library name only if your program calls any of the Fastgraph routines listed in Appendix D. The extended library name is FGMSCS (for the small model), FGMSCM (for the medium model), or FGMSCL (for the large model). Fastgraph/Light does not use extended libraries. The /E linker option is not required but will produce a smaller .EXE file if specified. For example, to compile the program 01-01.C under the medium memory model and then link it with Fastgraph, you could use the following CL command: CL /AM 01-01.C /link FGM FGMSCM /E Although we specified the extended library name FGMSCM on the command line, we didn't need to in this example because the program doesn't call any of the compiler-specific Fastgraph routines listed in Appendix D. If you were using Fastgraph/Light instead of Fastgraph, the CL command would be: CL /AM 01-01.C /link FGLM /E For more information about memory models or other compilation and linking options, please refer to the Microsoft C Optimizing Compiler User's Guide, published by Microsoft Corporation. Microsoft QuickC Microsoft QuickC allows you to compile and link a program directly from the DOS command line, or from within its programming environment. To use Fastgraph from QuickC's programming environment, just specify the quick library name FGQC when starting QuickC, as shown below. QC /lFGQC If you are using Fastgraph/Light, use the library name FGLQC instead of FGQC. Chapter 1: Introduction 7 You can also compile and link a QuickC program from the DOS command line using the QCL command. The format of the QCL command for compiling a program and linking it with Fastgraph is QCL /link [] [/E] where: specifies the compiler memory model you'll be using. It must be either /AS (for the small model), /AM (for the medium model), or /AL (for the large model). is the name of the file containing your program. It may include a path specification. is the name of a standard Fastgraph/Light or Fastgraph library. For Fastgraph/Light, the library name is FGLS (for the small model), FGLM (for the medium model), or FGLL (for the large model). For Fastgraph, the library name is FGS (for the small model), FGM (for the medium model), or FGL (for the large model). is the name of an optional compiler-specific extended Fastgraph library. You need to specify an extended library name only if your program calls any of the Fastgraph routines listed in Appendix D. The extended library name is FGMSCS (for the small model), FGMSCM (for the medium model), or FGMSCL (for the large model). Fastgraph/Light does not use extended libraries. The /E linker option is not required but will produce a smaller .EXE file if specified. For example, to compile the program 01-01.C under the medium memory model and then link it with Fastgraph, you could use the following QCL command: QCL /AM 01-01.C /link FGM FGMSCM /E Although we specified the extended library name FGMSCM on the command line, we didn't need to in this example because the program doesn't call any of the compiler-specific Fastgraph routines listed in Appendix D. If you were using Fastgraph/Light instead of Fastgraph, the QCL command would be: QCL /AM 01-01.C /link FGLM /E 8 Fastgraph User's Guide For more information about memory models or other compilation and linking options, please refer to the Microsoft QuickC Compiler Programmer's Guide, published by Microsoft Corporation. Turbo C Turbo C allows you to compile and link a program directly from the DOS command line, or from within its integrated development environment. To use Fastgraph from Turbo C's integrated development environment, you must make sure the compiler options match one of Fastgraph's available memory models (small, medium, or large), and then create a project file that links with the corresponding Fastgraph libraries (as listed below). You can also compile and link a Turbo C program from the DOS command line using the TCC command. The format of the TCC command for compiling a program and linking it with Fastgraph is TCC [] where: specifies the compiler memory model you'll be using. It must be either -ms (for the small model), -mm (for the medium model), or -ml (for the large model). is the name of the file containing your program. It may include a path specification. is the name of a standard Fastgraph/Light or Fastgraph library. For Fastgraph/Light, the library name is FGLS.LIB (for the small model), FGLM.LIB (for the medium model), or FGLL.LIB (for the large model). For Fastgraph, the library name is FGS.LIB (for the small model), FGM.LIB (for the medium model), or FGL.LIB (for the large model). is the name of an optional compiler-specific extended Fastgraph library. You need to specify an extended library name only if your program calls any of the Fastgraph routines listed in Appendix D. The extended library name is FGTCS.LIB (for the small model), FGTCM.LIB (for the medium model), or FGTCL.LIB (for the large model). Fastgraph/Light does not use extended libraries. For example, to compile the program 01-01.C under the medium memory model and then link it with Fastgraph, you could use the following TCC command: TCC -mm 01-01.C FGM.LIB FGTCM.LIB Chapter 1: Introduction 9 Although we specified the extended library name FGTCM.LIB on the command line, we didn't need to in this example because the program doesn't call any of the compiler-specific Fastgraph routines listed in Appendix D. If you were using Fastgraph/Light instead of Fastgraph, the TCC command would be: TCC -mm 01-01.C FGLM.LIB For more information about memory models or other compilation and linking options, please refer to the Turbo C User's Guide and the Turbo C Reference Guide, both published by Borland International. Microsoft QuickBASIC Example 1-2 is a QuickBASIC program that uses the Fastgraph routine FGversion to display the version number for your copy of Fastgraph. If you loaded the example programs when you installed Fastgraph, the file \FG\EXAMPLES\01-02.BAS contains the source code for this program. You can use example 1-2 to test the QuickBASIC compilation and linking process for Fastgraph. Example 1-2. REM $INCLUDE: 'fastgraf.bi' DEFINT A-Z FGversion Major, Minor Version! = Major + Minor*0.01 PRINT USING "This is version #.## of Fastgraph."; Version! END You must include the DECLARE commands in the file FASTGRAF.BI at the beginning of each QuickBASIC module. This file should reside in the directory where the compiler normally searches for other .BI files, or in any of the directories specified by the INCLUDE environment variable. The DECLARE commands in this file automatically provide the calling convention and naming convention for each Fastgraph routine. In addition, they relieve the QuickBASIC programmer of distinguishing arguments passed by value from those passed by reference. Microsoft QuickBASIC allows you to compile and link a program directly from the DOS command line, or from within its programming environment. To use Fastgraph from QuickBASIC's programming environment, just specify the quick library name FGQB when starting QuickBASIC, as shown below. QB /lFGQB If you are using Fastgraph/Light, use the library name FGLQB instead of FGQB. 10 Fastgraph User's Guide You can also compile and link a QuickBASIC program from the DOS command line using the BC and LINK commands. The format of these commands for compiling a program and linking it with Fastgraph is BC ; LINK [/E] ,,NUL, where: is the name of the file containing your program. It may include a path specification. is the name of the object file produced by the BC command. By default, this will be the same as , but with an extension of .OBJ rather than .BAS. is the name of the standard Fastgraph/Light or Fastgraph library. For Fastgraph/Light, the library name is FGLQB. For Fastgraph, the library name is FGQB. QuickBASIC does not use extended Fastgraph libraries. The /E linker option is not required but will produce a smaller .EXE file if specified. For example, to compile the program 01-02.BAS and then link it with Fastgraph, you could use the following commands: BC 01-02.BAS; LINK /E 01-02.OBJ,,NUL,FGQB If you were using Fastgraph/Light instead of Fastgraph, the commands would be: BC 01-02.BAS; LINK /E 01-02.OBJ,,NUL,FGLQB For more information about other compilation and linking options, please refer to the Microsoft QuickBASIC: Programming in BASIC manual, published by Microsoft Corporation. All of the remaining example programs in the Fastgraph User's Guide are written in the C programming language. However, when you install Fastgraph for Microsoft QuickBASIC, the installation procedure copies QuickBASIC versions of the example programs to the \FG\EXAMPLES directory. Chapter 1: Introduction 11 Microsoft FORTRAN Example 1-3 is a FORTRAN program that uses the Fastgraph routine fg_version to display the version number for your copy of Fastgraph. If you loaded the example programs when you installed Fastgraph, the file \FG\EXAMPLES\01-03.FOR contains the source code for this program. You can use example 1-3 to test the FORTRAN compilation and linking process for the memory models you'll be using with Fastgraph. Example 1-3. $INCLUDE: '\FG\INTRFACE.FOR' PROGRAM MAIN INTEGER*2 MAJOR INTEGER*2 MINOR CALL FG_VERSION (MAJOR, MINOR) WRITE (6,10) MAJOR, MINOR 10 FORMAT (' This is version ', I1, '.', I2.2, ' of Fastgraph.') STOP ' ' END You must include the INTERFACE statements in the file INTRFACE.FOR at the beginning of your program (this file should reside in the \FG directory). The INTERFACE statements in this file automatically provide the calling convention and naming convention for each Fastgraph routine. In addition, they relieve the FORTRAN programmer of distinguishing arguments passed by value from those passed by reference. Microsoft FORTRAN programs are compiled and linked by entering an FL command at the DOS command prompt. The format of the FL command for compiling a program and linking it with Fastgraph is FL /FPi /4I2 /4Nt /link [] [/E] where: specifies the compiler memory model you'll be using. It must be either /AM (for the medium model) or /AL (for the large model). Microsoft FORTRAN does not support the small model. is the name of the file containing your program. It may include a path specification. 12 Fastgraph User's Guide is the name of a standard Fastgraph/Light or Fastgraph library. For Fastgraph/Light, the library name is FGLM (for the medium model) or FGLL (for the large model). For Fastgraph, the library name is FGM (for the medium model) or FGL (for the large model). is the name of an optional compiler-specific extended Fastgraph library. You need to specify an extended library name only if your program calls any of the Fastgraph routines listed in Appendix D. The extended library name is FGMSFM (for the medium model) or FGMSFL (for the large model). Fastgraph/Light does not use extended libraries. The /E linker option is not required but will produce a smaller .EXE file if specified. For example, to compile the program 01-03.FOR under the medium memory model and then link it with Fastgraph, you could use the following FL command: FL /FPi /4I2 /4Nt /AM 01-03.FOR /link FGM FGMSFM /E Although we specified the extended library name FGMSFM on the command line, we didn't need to in this example because the program doesn't call any of the compiler-specific Fastgraph routines listed in Appendix D. If you were using Fastgraph/Light instead of Fastgraph, the FL command would be: FL /FPi /4I2 /4Nt /AM 01-03.FOR /link FGLM /E For more information about memory models or other compilation and linking options, please refer to the Microsoft FORTRAN Optimizing Compiler User's Guide, published by Microsoft Corporation. All of the remaining example programs in the Fastgraph User's Guide are written in the C programming language. However, when you install Fastgraph for the Microsoft FORTRAN compiler, the installation procedure copies FORTRAN versions of the example programs to the \FG\EXAMPLES directory. Fastgraph/Light Video Driver As mentioned earlier, running any program created with Fastgraph/Light requires an external program called the Fastgraph/Light Video Driver. The video driver is a terminate and stay resident program (TSR) that provides an interface between your program and Fastgraph. Once loaded, the video driver uses about 60,000 bytes of conventional memory. To load the video driver, enter the command FGDRIVER at the DOS command prompt (assuming FGDRIVER.EXE is in the current directory, or the \FG directory is in your DOS path specification). The driver will display a message indicating whether or not it was loaded successfully. After you load Chapter 1: Introduction 13 the driver, just run a program created with Fastgraph/Light as would run any other program. If you try running a program that uses Fastgraph/Light without first loading the video driver, the message "Fastgraph/Light video driver not installed" will appear. You don't need to load the driver before running each program, just once per system boot (in fact, the driver will display an "already loaded" message if you try to load it more than once). If you want to unload the video driver, just enter FGDRIVER /U at the DOS command prompt. The unload operation will work completely only if the video driver was the last TSR loaded. If it wasn't the last TSR, the driver will still unload, but the memory it uses will not be released back to DOS. 14 Fastgraph User's Guide Chapter 2 PC and PS/2 Video Modes 16 Fastgraph User's Guide Overview In the PC and PS/2 worlds, the method by which information appears on the computer's display screen is determined by the video mode currently in effect. The video modes have different resolutions, different character or pixel attributes, different video memory structures, and other inherent hardware differences. However, you do not need an in-depth knowledge of these video internals, because Fastgraph handles the necessary details. The PC and PS/2 video modes may be separated into two major classes: text modes and graphics modes. In text modes, the display screen is divided into character cells. There are 25 rows and either 40 or 80 columns of cells, and in each cell we can store any of the 256 characters in the IBM PC character set. Each character has an associated attribute that determines such things as its foreground color, its background color, and whether or not the character blinks. In graphics modes, the display screen is divided into picture elements, or pixels. Depending on the video mode, the number of pixel rows ranges between 200 and 480, while the number of columns ranges between 320 and 720. Each pixel has an associated value that determines the color of the pixel. The number of character cells or pixels available is called the resolution of the screen. The display adapter (graphics card) and the video display (monitor) connected to it determine the video modes available on a given system. The following table summarizes the characteristics of the PC and PS/2 video modes that Fastgraph supports. Mode No. of Supported Supported Number Type Resolution Colors Adapters Displays 0 Text 40 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 1 Text 40 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 2 Text 80 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 3 Text 80 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 4 Graphics 320 x 200 4 CGA,EGA,VGA,MCGA RGB,ECD,VGA 5 Graphics 320 x 200 4 CGA,EGA,VGA,MCGA RGB,ECD,VGA 6 Graphics 640 x 200 2/16 CGA,EGA,VGA,MCGA RGB,ECD,VGA 7 Text 80 x 25 b/w MDA,HGC,EGA,VGA Monochrome,ECD,VGA 9 Graphics 320 x 200 16 Tandy 1000,PCjr RGB 11 Graphics 720 x 348 b/w HGC Monochrome 12 Graphics 320 x 200 b/w HGC Monochrome 13 Graphics 320 x 200 16 EGA,VGA RGB,ECD,VGA 14 Graphics 640 x 200 16 EGA,VGA RGB,ECD,VGA 15 Graphics 640 x 350 b/w EGA,VGA Monochrome,VGA 16 Graphics 640 x 350 16/64 EGA,VGA ECD,VGA 17 Graphics 640 x 480 2/256K VGA,MCGA VGA 18 Graphics 640 x 480 16/256K VGA VGA 19 Graphics 320 x 200 256/256K VGA,MCGA VGA 20 Graphics 320 x 200 256/256K VGA VGA 21 Graphics 320 x 400 256/256K VGA VGA Some notes about the format and abbreviations used in this table are in order. A single value in the "number of colors" column refers to the number of colors available in that video mode. In text modes, a pair of numbers such as 16/8 means each displayed character can have one of 16 foreground Chapter 2: PC and PS/2 Video Modes 17 colors and one of 8 background colors. In graphics modes, a pair of numbers such as 16/64 means 16 colors can be displayed simultaneously from a collection, or palette, of 64. The "b/w" listed in the monochrome modes stands for "black and white". Characters or pixels in these video modes do not really have associated colors but instead have display attributes such as blinking or different intensities. The meanings of the abbreviations in the "supported adapters" and "supported displays" columns are: CGA Color Graphics Adapter ECD Enhanced Color Display EGA Enhanced Graphics Adapter HGC Hercules Graphics Card MCGA Multi-Color Graphics Array MDA Monochrome Display Adapter RGB Red-Green-Blue Color Display VGA Video Graphics Array The use of the term "VGA" in the "supported display" column refers to any analog display, such as a VGA or Multisync monitor. The IBM PS/2 family does not have an adapter and display combination per se. Instead, the video hardware used in these systems is called the video subsystem. The Model 25 and Model 30 have an MCGA-based video subsystem, while other models have a VGA-based video subsystem. This rest of this chapter will provide an overview of the most important features and restrictions of each video mode. The first section will discuss the text modes, while the following section will discuss the graphics modes. Text Modes There are five text video modes in the IBM PC and PS/2 family. Four of these modes (0, 1, 2, and 3) are designed for color displays, while the remaining mode (7) is designed for monochrome displays. All of the text modes were introduced with the original IBM PC. In text modes, the screen is divided into character cells. There are two bytes of video memory associated with each character cell -- one byte for the character's ASCII value, and another for the character's display attribute. The amount of video memory required to store one screen of information (called a video page) is thus number_of_columns x number_of_rows x 2 All text modes use 25 rows, so for the 40-column modes (0 and 1) the size of a video page is 2,000 bytes, and for the 80-column modes (2, 3, and 7) the size of a video page is 4,000 bytes. Mode No. of Supported Supported Number Resolution Colors Adapters Displays 0 40 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 1 40 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 18 Fastgraph User's Guide 2 80 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 3 80 x 25 16/8 CGA,EGA,VGA,MCGA RGB,ECD,VGA 7 80 x 25 b/w MDA,HGC,EGA,VGA Monochrome,ECD,VGA The remainder of this section will describe the text video modes in more detail. Mode 0 Mode 0 is a 40-column by 25-row color text mode. It is often referred to as a colorless mode since it was designed to be used with composite or television monitors (as opposed to RGB monitors). When used with these types of monitors, the available 16 "colors" appear as distinct shades of gray. When used with an RGB monitor, mode 0 is identical in all respects to mode 1. There are eight pages of video memory available in mode 0; each occupies 2,000 bytes. The use of composite or television monitors as PC video displays has virtually disappeared today. As a result, mode 0 is used infrequently. Mode 1 Mode 1 is a 40-column by 25-row color text mode. It is supported across all video adapter and color display combinations in the PC and PS/2 families. Characters displayed in mode 1 have an associated display attribute that defines the character's foreground color, its background color, and whether or not it blinks. Sixteen foreground colors and eight background colors are available. There are eight pages of video memory available in mode 1; each occupies 2,000 bytes. Mode 2 Mode 2 is an 80-column by 25-row color text mode. Like mode 0, it is often referred to as a colorless mode since it was designed to be used with composite or television monitors (as opposed to RGB monitors). When used with these types of monitors, the available 16 "colors" appear as distinct shades of gray. When used with an RGB monitor, mode 2 is identical in all respects to mode 3. There are four pages of video memory available in mode 2; each occupies 4,000 bytes. The use of composite or television monitors as PC video displays has virtually disappeared today. As a result, mode 2 is used infrequently. Mode 3 Mode 3 is an 80-column by 25-row color text mode. It is the default video mode for systems that use any type of color display. This mode is supported across all video adapter and color display combinations in the PC and PS/2 families. Characters displayed in mode 3 have an associated display attribute that defines the character's foreground color, its background color, and whether or not it blinks. Sixteen foreground colors and eight background colors are available. There are four pages of video memory available in mode 3; each occupies 4,000 bytes. Chapter 2: PC and PS/2 Video Modes 19 Mode 7 Mode 7 is the 80-column by 25-row monochrome text mode. It is the default video mode for systems that use a monochrome display. To use this mode, you must have a Monochrome Display Adapter (MDA), Hercules Graphics Card (HGC), or an Enhanced Graphics Adapter (EGA) connected to a monochrome display. Most VGA display adapters also provide an emulation mode that allows you to use mode 7 with analog displays. Characters displayed in mode 7 have an associated display attribute that defines whether the character is invisible, normal, bold, underlined, reversed, blinking, or a combination of these. There is a single 4,000-byte page of video memory available in mode 7, but Fastgraph allows you to allocate random-access memory (RAM) to provide up to 15 virtual video pages in this mode. Graphics Modes There are 13 standard graphics video modes available in the IBM PC and PS/2 family. Fastgraph provides support for 11 of the 13 modes (modes 8 and 10, which are specific to the PCjr and Tandy 1000 systems, are not supported). In addition to these 13 modes, Fastgraph supports two video modes for the Hercules Graphics Card (modes 11 and 12), and two added VGA modes (modes 20 and 21). Modes 4, 5, and 6 are designed to be used with the Color Graphics Adapter (CGA) and for this reason are called the native CGA modes. They were the only graphics modes available with the original IBM PC. Newer graphics adapters (EGA, VGA, and MCGA) can emulate the CGA, which means that the CGA graphics modes are available on any PC or PS/2 system equipped with a color display. Mode No. of Supported Supported Number Resolution Colors Adapters Displays 4 320 x 200 4 CGA,EGA,VGA,MCGA RGB,ECD,VGA 5 320 x 200 4 CGA,EGA,VGA,MCGA RGB,ECD,VGA 6 640 x 200 2/16 CGA,EGA,VGA,MCGA RGB,ECD,VGA Modes 8, 9, and 10 are only available on the PCjr and Tandy 1000 series computers (these systems also support modes 4, 5, and 6). Modes 8 and 10 are not widely used, and for this reason Fastgraph does not support them. Mode No. of Supported Supported Number Resolution Colors Adapters Displays 8 160 x 200 16 Tandy 1000,PCjr RGB 9 320 x 200 16 Tandy 1000,PCjr RGB 10 640 x 200 4 Tandy 1000,PCjr RGB Modes 11 and 12 are used with the Hercules Graphics Card (HGC) and a monochrome display. As such, they are not true IBM video modes, but because of the popularity of the HGC, Fastgraph provides support for this adapter. 20 Fastgraph User's Guide IBM has not defined video modes with numbers 11 and 12. Should they choose to do so in the future, Fastgraph's Hercules video mode numbers would likely change. Mode No. of Supported Supported Number Resolution Colors Adapters Displays 11 720 x 348 b/w HGC Monochrome 12 320 x 200 b/w HGC Monochrome Modes 13 through 16 were introduced with the Enhanced Graphics Adapter (EGA) and for this reason are called the native EGA modes. The VGA also provides support for these modes, but the MCGA does not. The original IBM EGA only contained 64K bytes of video memory, but memory could be added in 64K increments to fully populate the adapter with 256K bytes of video memory. As other manufacturers developed EGA cards, they generally included 256K bytes of video memory as a standard feature. Mode No. of Supported Supported Number Resolution Colors Adapters Displays 13 320 x 200 16 EGA,VGA RGB,ECD,VGA 14 640 x 200 16 EGA,VGA RGB,ECD,VGA 15 640 x 350 b/w EGA,VGA Monochrome,VGA 16 640 x 350 16/64 EGA,VGA ECD,VGA Modes 17, 18, and 19 were introduced with the MCGA and VGA video subsystems of the IBM PS/2 computers. Since the introduction of the PS/2, other manufacturers have developed VGA cards that can be used with the PC family. The VGA supports all three of these modes, but the MCGA does not support mode 18. Mode 20 is a special VGA version of mode 19, while mode 21 uses scan doubling to acheive a 400-line VGA display. These are not true IBM video modes, and should IBM define video modes 20 or 21 in the future, Fastgraph's numbers for these video modes would likely change. Mode No. of Supported Supported Number Resolution Colors Adapters Displays 17 640 x 480 2/256K VGA,MCGA VGA 18 640 x 480 16/256K VGA VGA 19 320 x 200 256/256K VGA,MCGA VGA 20 320 x 200 256/256K VGA VGA 21 320 x 400 256/256K VGA VGA Chapter 2: PC and PS/2 Video Modes 21 The remainder of this section will describe the graphics video modes in more detail. Mode 4 Mode 4 is a CGA graphics mode with a resolution of 320 horizontal pixels by 200 vertical pixels. Each pixel can assume one of four colors (the available colors are determined by which one of six palettes has been selected), so each pixel requires two bits of video memory. This means that each byte of video memory represents four pixels. Hence, the amount of video memory required to store one full screen of information is 320 rows x 200 columns ---------------------- = 16,000 bytes 4 pixels per byte which is the amount of video memory on a true CGA. This means that only a single video page is available in mode 4, but Fastgraph allows you to allocate random-access memory (RAM) to provide up to 15 virtual video pages in this mode. Mode 5 Mode 5 is the colorless analog of mode 4. It was designed to be used with composite or television monitors (as opposed to RGB monitors). When used with these types of monitors, the four colors appear as distinct shades of gray. When used with an RGB monitor, mode 5 is essentially identical to mode 4. The use of composite or television monitors as PC video displays has virtually disappeared today. As a result, mode 5 is used infrequently. Mode 6 Mode 6 is a CGA graphics mode with a resolution of 640 horizontal pixels by 200 vertical pixels. Each pixel can assume two states -- on or off. The color in which the "on" pixels appear can be selected from a palette of 16 available colors. Each pixel thus requires one bit of video memory, which means that each byte of video memory represents eight pixels. Hence, the amount of video memory required to store one full screen of information is 640 rows x 200 columns ---------------------- = 16,000 bytes 8 pixels per byte which is the amount of video memory on a true CGA. This means that only a single video page is available in mode 6, but Fastgraph allows you to allocate random-access memory (RAM) to provide up to 15 virtual video pages in this mode. Mode 9 Mode 9 is a Tandy 1000 and PCjr graphics mode with a resolution of 320 horizontal pixels by 200 vertical pixels. Each pixel can assume one of 16 colors, so each pixel requires four bits of video memory. This means that each byte of video memory represents two pixels. Hence, the amount of video memory required to store one full screen of information is 22 Fastgraph User's Guide 320 rows x 200 columns ---------------------- = 32,000 bytes 2 pixels per byte The Tandy 1000 and PCjr use standard random-access memory (RAM) as video memory. When you select mode 9, the ROM BIOS allocates 32,000 bytes of RAM which is then treated as a single page of video memory. Fastgraph allows you to allocate additional RAM to provide up to 15 virtual video pages in this mode. Mode 11 Mode 11 is a true Hercules graphics mode with a resolution of 720 horizontal pixels by 348 vertical pixels. Each pixel can assume two states -- on or off. Each pixel thus requires one bit of video memory, which means that each byte of video memory represents eight pixels. Hence, the amount of video memory required to store one full screen of information is 720 rows x 348 columns ---------------------- = 31,320 bytes 8 pixels per byte which is just less than half the 64K bytes of video memory on a Hercules Graphics Card. In other words, two video pages are available in mode 11. Fastgraph allows you to allocate random-access memory (RAM) to provide up to 14 virtual video pages in this mode. Mode 12 Mode 12 is a software-simulated Hercules graphics mode with an effective resolution of 320 horizontal pixels by 200 vertical pixels. Its purpose is to provide a resolution that is available with all of the other display adapters. As in mode 11, two video pages are available, but Fastgraph allows you to allocate random-access memory (RAM) to provide up to 14 virtual video pages in this mode. This mode converts all coordinates from the 320 by 200 space (called virtual coordinates) into the 720 by 348 coordinate system (called physical coordinates). It does this by using two physical pixels for each virtual pixel and scan doubling the odd-numbered virtual rows. Finally, offsets are added to the resulting physical coordinates to center the image area on the display. This creates an image area bounded horizontally by the physical coordinates 40 and 679 and vertically by the physical coordinates 24 and 323. Mode 13 Mode 13 is an EGA color graphics mode with a resolution of 320 horizontal pixels by 200 vertical pixels. Each pixel can assume one of 16 colors, so each pixel requires four bits of video memory. This means that each byte of video memory represents two pixels. Hence, the amount of video memory required to store one full screen of information is 320 rows x 200 columns ---------------------- = 32,000 bytes 2 pixels per byte Chapter 2: PC and PS/2 Video Modes 23 which is 1/8 the 256K bytes of video memory on a fully-populated EGA. In other words, eight video pages are available in mode 13. Mode 14 Mode 14 is an EGA color graphics mode with a resolution of 640 horizontal pixels by 200 vertical pixels. Each pixel can assume one of 16 colors, so each pixel requires four bits of video memory. This means that each byte of video memory represents two pixels. Hence, the amount of video memory required to store one full screen of information is 640 rows x 200 columns ---------------------- = 64,000 bytes 2 pixels per byte which is 1/4 the 256K bytes of video memory on a fully-populated EGA. In other words, four video pages are available in mode 14. Mode 15 Mode 15 is an EGA monochrome graphics mode with a resolution of 640 horizontal pixels by 350 vertical pixels. Each pixel can assume one of 4 display attributes, so each pixel requires two bits of video memory. This means that each byte of video memory represents four pixels. Hence, the amount of video memory required to store one full screen of information is 640 rows x 350 columns ---------------------- = 56,000 bytes 4 pixels per byte which is less than 1/4 the 256K bytes of video memory on a fully-populated EGA. However, mode 15 disables two of the EGA's four bit planes, which effectively reduces the EGA's video memory to a maximum of 128K bytes. In other words, two video pages are available in mode 15. Mode 16 Mode 16 is an EGA color graphics mode with a resolution of 640 horizontal pixels by 350 vertical pixels. Each pixel can assume one of 16 colors (the 16 colors can be selected from a palette of 64 colors), so each pixel requires four bits of video memory. This means that each byte of video memory represents two pixels. Hence, the amount of video memory required to store one full screen of information is 640 rows x 350 columns ---------------------- = 112,000 bytes 2 pixels per byte which is less than 1/2 the 256K bytes of video memory on a fully-populated EGA. In other words, two video pages are available in mode 16. Mode 17 Mode 17 is a VGA and MCGA graphics mode with a resolution of 640 horizontal pixels by 480 vertical pixels. Each pixel can assume two states -- on or off. The color in which the "on" and "off" pixels appear can be selected from a palette of 262,144 available colors. Each pixel thus 24 Fastgraph User's Guide requires one bit of video memory, which means that each byte of video memory represents eight pixels. Hence, the amount of video memory required to store one full screen of information is 640 rows x 480 columns ---------------------- = 38,400 bytes 8 pixels per byte which is 60% of the 64K bytes of video memory on a true MCGA. This means that only a single video page is available in mode 17. Mode 18 Mode 18 is a native VGA color graphics mode with a resolution of 640 horizontal pixels by 480 vertical pixels. Each pixel can assume one of 16 colors (the 16 colors can be selected from a palette of 262,144 colors), so each pixel requires four bits of video memory. This means that each byte of video memory represents two pixels. Hence, the amount of video memory required to store one full screen of information is 640 rows x 480 columns ---------------------- = 153,600 bytes 2 pixels per byte which is 60% of the 256K bytes of video memory on a standard VGA. This means that only a single video page is available in mode 18. Mode 19 Mode 19 is a VGA and MCGA color graphics mode with a resolution of 320 horizontal pixels by 200 vertical pixels. Each pixel can assume one of 256 colors (the 256 colors can be selected from a palette of 262,144 colors), so each pixel requires eight bits of video memory. This means that each byte of video memory represents one pixel. Hence, the amount of video memory required to store one full screen of information is 320 rows x 200 columns ---------------------- = 64,000 bytes 1 pixel per byte which is the amount of video memory on a true MCGA. This means that only a single video page is available in mode 19, but Fastgraph allows you to allocate random-access memory (RAM) to provide up to 15 virtual video pages in this mode. Mode 20 Mode 20 is a VGA color graphics mode with a resolution of 320 horizontal pixels by 200 vertical pixels. Each pixel can assume one of 256 colors (the 256 colors can be selected from a palette of 262,144 colors), so each pixel requires eight bits of video memory. This means that each byte of video memory represents one pixel. Hence, the amount of video memory required to store one full screen of information is 320 rows x 200 columns ---------------------- = 64,000 bytes 1 pixel per byte Chapter 2: PC and PS/2 Video Modes 25 which is 1/4 the 256K bytes of video memory on a standard VGA. In other words, four video pages are available in mode 20. Mode 21 Mode 21 is a VGA color graphics mode with a resolution of 320 horizontal pixels by 400 vertical pixels. Each pixel can assume one of 256 colors (the 256 colors can be selected from a palette of 262,144 colors), so each pixel requires eight bits of video memory. This means that each byte of video memory represents one pixel. Hence, the amount of video memory required to store one full screen of information is 320 rows x 400 columns ---------------------- = 128,000 bytes 1 pixel per byte which is 1/2 the 256K bytes of video memory on a standard VGA. In other words, two video pages are available in mode 21. 26 Fastgraph User's Guide Chapter 3 Initializing the Video Environment 28 Fastgraph User's Guide Overview Before Fastgraph can perform any text or graphics video operations, you must select a video mode in which your program will run. An important part of this selection depends on whether your program will run in a text mode, a graphics mode, or both. This chapter discusses the necessary video initialization for each case. Establishing a Text Mode When you write a program that only uses text modes, you must determine if the program will run on monochrome systems, color systems, or both. In general, there is no reason to exclude one type of system, because the additional programming required to support both is rather trivial. The Fastgraph routine fg_setmode establishes a video mode and initializes all of Fastgraph's internal parameters for that mode. This routine has a single integer argument whose value is a video mode number between 0 and 21. Its value can also be -1, which tells Fastgraph to use the current video mode. Specifying an fg_setmode argument of -1 is often useful in programs that only use text video modes. When you establish a text video mode, the ROM BIOS text cursor is made visible, and this is often undesirable. The Fastgraph routine fg_cursor controls the visibility of the text cursor. The fg_cursor routine has a single integer argument that specifies the cursor visibility. If its value is 0, the cursor is made invisible; if its value is 1, the cursor is made visible. At this point, an example may help to clarify things. The following program shows how to initialize Fastgraph for the 80-column color text mode (mode 3) and turn off the text mode cursor. It uses two Fastgraph routines that we have not yet discussed, fg_setcolor and fg_text. These routines will be discussed in later sections of this document. For now, it should suffice to know the call to fg_setcolor makes subsequent text appear in bright white, and the call to fg_text displays the characters passed to it. Example 3-1. main() { fg_setmode(3); fg_cursor(0); fg_setcolor(15); fg_text("Hello, world.",13); } If you run example 3-1, notice the text displayed by the program appears in the upper left corner of the screen. On the line below this, the DOS prompt appears, waiting for your next DOS command. Furthermore, if your system uses the ANSI.SYS driver to set screen attributes (such as with Norton's SA program), you should also notice only the DOS prompt appears in Chapter 3: Initializing the Video Environment 29 the colors defined by the screen attributes -- the rest of the screen is blank. A more graceful return to DOS is needed. In example 3-2, we'll use the Fastgraph routine fg_reset. This routine erases the screen, and if the ANSI.SYS driver is loaded, fg_reset also restores any previously set screen attributes. We've also included a call to the Fastgraph routine fg_waitkey to wait for a keystroke before exiting. If we didn't do this, we would never see the program's output. Example 3-2. main() { fg_setmode(3); fg_cursor(0); fg_setcolor(15); fg_text("Hello, world.",13); fg_waitkey(); fg_reset(); } Since examples 3-1 and 3-2 specifically used video mode 3, they would not work on a monochrome system. Ideally we would like to use fg_setmode(3) for color systems and fg_setmode(7) for monochrome systems. To do this, we need a way to determine whether the program is being run on a color system or on a monochrome system. The next example illustrates an easy way to accomplish this. Example 3-3 uses the Fastgraph routine fg_testmode to determine if the user's system will support the video mode number specified as its first argument (the second argument is the number of video pages required, which will be 1 for all of the examples in this section). The fg_testmode routine returns a value of 1 (as its function value) if the requested video mode can be used, and it returns 0 if not. The program first sees if an 80-column color text mode is available (mode 3), and if so, it selects that mode. If the color mode is not available, it checks if the monochrome text mode is available (mode 7), and if so, it chooses the monochrome mode. If neither mode is available, then the program assumes the user's system has a 40-column display, issues a message indicating the program requires an 80-column display, and then exits. Example 3-3. main() { int old_mode; old_mode = fg_getmode(); if (fg_testmode(3,1)) fg_setmode(3); 30 Fastgraph User's Guide else if (fg_testmode(7,1)) fg_setmode(7); else { printf("This program requires\n"); printf("an 80-column display.\n"); exit(); } fg_cursor(0); fg_setcolor(15); fg_text("Hello, world.",13); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Example 3-3 also illustrates another useful procedure. It is recommended, especially in graphics modes, to restore the original video mode and screen attributes before a program returns to DOS. We've already seen how the fg_reset routine restores the screen attributes, but how do we restore the original video mode? The Fastgraph routine fg_getmode returns the current video mode as its function value. If we call fg_getmode before calling fg_setmode, we can use the return value from fg_getmode and again call fg_setmode before the program exits. You can also use another Fastgraph routine, fg_bestmode, to determine if a video mode with a specific resolution is available on the user's system. The fg_bestmode routine requires three integer arguments: a horizontal resolution, a vertical resolution, and the number of video pages required. As its function value, fg_bestmode returns the video mode number that offers the most capabilities for the resolution and number of pages requested. It returns a value of -1 if no available video mode offers the requested criteria. For example, if we require an 80 by 25 text mode, we can use the function call fg_bestmode(80,25,1) to pick the "best" video mode available that offers this capability. In text modes, the term best means to give preference to a color text mode over a monochrome text mode. Example 3-4 performs the same function as example 3-3, but it uses fg_bestmode rather than fg_testmode. Example 3-4. main() { int old_mode; int new_mode; old_mode = fg_getmode(); new_mode = fg_bestmode(80,25,1); if (new_mode < 0) { Chapter 3: Initializing the Video Environment 31 printf("This program requires\n"); printf("an 80-column display.\n"); exit(); } fg_setmode(new_mode); fg_cursor(0); fg_setcolor(15); fg_text("Hello, world.",13); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Establishing a Graphics Mode The steps for establishing a graphics mode are similar to establishing a text mode. However, there are more restrictions since some systems may not support all of the graphics video modes. For example, a program could not run in mode 13 on a CGA system, nor could a program run in mode 9 on anything except a Tandy 1000 or PCjr system. Example 3-5 shows the recommended techniques for writing an EGA-specific program. The program in this example uses mode 16, the 640 x 350 EGA mode that requires an Enhanced Color Display (ECD). It uses the Fastgraph routine fg_egacheck to determine if an EGA and ECD are present. The fg_egacheck routine returns a value of 0 if an EGA is not found, or if there is an EGA but no ECD. If an EGA and ECD are found, it returns a positive integer indicating the number of 64K-byte increments of video memory on the EGA. Since mode 16 requires 112,000 bytes of video memory for a single video page, there must be at least 128K bytes of video memory on the EGA to run this program. Hence we must verify that fg_egacheck returns a value of at least 2. Example 3-5. main() { int mode; if (fg_egacheck() < 2) { printf("This program requires an Enhanced Graphics Adapter\n"); printf("(EGA) and an Enhanced Color Display (ECD).\n"); exit(); } mode = fg_getmode(); fg_setmode(16); fg_setcolor(15); fg_text("Hello, world.",13); 32 Fastgraph User's Guide fg_waitkey(); fg_setmode(mode); fg_reset(); } For graphics programs, it may suffice to write a program to run in a specific video mode, but it is often more desirable to write a program that will run in any of several video modes. This is especially true for commercial products, since they should run on as many different video configurations as possible. Fastgraph includes a routine named fg_automode that determines the graphics video mode that offers the most functionality for the user's video hardware configuration. For example, the Tandy 1000 series computers support all three CGA modes (4, 5, and 6) and the 320 by 200 16-color Tandy 1000 mode (9). Of these modes, mode 9 offers the most features from a graphics standpoint, so fg_automode will return a value of 9 when run on a Tandy 1000 computer. The following table summarizes the video mode numbers returned by fg_automode for given adapter-display combinations. display adapter mono RGB ECD VGA MDA 7 0 7 7 HGC 11 0 0 11 CGA 0 4 0 0 EGA 15 13 16 0 VGA 17 17 17 18 MCGA 17 17 17 19 Tandy 7 9 0 0 PCjr 7 9 0 0 Example 3-6 shows how to use fg_automode to determine the "best" graphics mode for the user's video hardware. In graphics modes, the term best means the highest resolution, followed by the number of available colors. The program displays a message that includes the selected video mode number. Example 3-6. main() { int old_mode; int new_mode; char string[4]; old_mode = fg_getmode(); new_mode = fg_automode(); fg_setmode(new_mode); fg_setcolor(15); Chapter 3: Initializing the Video Environment 33 fg_text("I'm running in mode ",20); sprintf(string,"%d.",new_mode); fg_text(string,3); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } For simple programs such as example 3-6, different screen resolutions may not be an issue. However, in more complex graphics programs it is often desirable to write a program for a fixed screen resolution. A common practice is to develop graphics programs to run in modes 4 (for CGA), 9 (Tandy 1000 or PCjr), 12 (Hercules), 13 (EGA or VGA), and 19 (MCGA). The reason for selecting these five modes is they all use the same 320 by 200 resolution and will run on any IBM PC or PS/2 with graphics capabilities. Example 3-7 performs the same function as example 3-6, but it uses the fg_bestmode routine instead of fg_automode to restrict the program to 320 by 200 graphics modes. For this resolution, the fg_bestmode routine will first check the availability of mode 19, followed by modes 13, 9, 4, and 12. If fg_bestmode determines no 320 by 200 graphics mode is available (indicated by a return value of -1), the program prints an informational message and exits. Otherwise it selects the video mode fg_bestmode proposes and continues. Example 3-7. main() { int old_mode; int new_mode; char string[4]; old_mode = fg_getmode(); new_mode = fg_bestmode(320,200,1); if (new_mode < 0) { printf("This program requires a 320 by 200 graphics mode.\n"); exit(); } fg_setmode(new_mode); fg_setcolor(15); fg_text("I'm running in mode ",20); sprintf(string,"%d.",new_mode); fg_text(string,3); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } 34 Fastgraph User's Guide If your program will not support all PC and PS/2 video modes with the same resolution (for example, it will run in some but not all of the 320 by 200 graphics modes), you may want to consider using the fg_testmode routine instead of fg_bestmode to check for available video modes. You may also want to use fg_testmode to change the video mode precedence used by fg_bestmode. For example, mode 13 (EGA) is faster than mode 19 (MCGA), so you may want to consider giving EGA precedence over MCGA, especially if your program does not use more than 16 colors. Example 3-8 is similar to example 3-7, but it will only run in the 320 by 200 EGA, MCGA, and CGA graphics modes (video modes 13, 19, and 4 respectively). The program uses fg_testmode to select its video mode. Note the order of calls to fg_testmode gives EGA precedence over MCGA, and MCGA precedence over CGA. Example 3-8. main() { int old_mode; char string[4]; old_mode = fg_getmode(); if (fg_testmode(13,1)) fg_setmode(13); else if (fg_testmode(19,1)) fg_setmode(19); else if (fg_testmode(4,1)) fg_setmode(4); else { printf("This program requires an EGA, MCGA, or CGA.\n"); exit(); } fg_setcolor(15); fg_text("I'm running in mode ",20); sprintf(string,"%d.",getmode()); fg_text(string,3); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Summary of Video Initialization Routines This section summarizes the functional descriptions of the Fastgraph routines presented in this chapter. More detailed information about these routines, including their arguments and return values, may be found in the Fastgraph Reference Manual. Chapter 3: Initializing the Video Environment 35 FG_AUTOMODE determines the graphics video mode that offers the most features for the user's display and adapter configuration. The value it returns helps determine a suitable value to pass to the fg_setmode routine. FG_BESTMODE is similar to fg_automode, but it excludes video modes that do not offer the specified resolution and video page requirements. FG_CURSOR makes the text mode cursor visible or invisible. This routine has no effect when used in a graphics mode. FG_EGACHECK returns information about the active EGA or VGA adapter and display. It is useful in checking if the adapter has enough memory to run an EGA-specific program. FG_GETMODE returns the current video mode. It is typically one of the first Fastgraph routines called in a program. The value returned by fg_getmode can be retained to restore the original video mode when a program transfers control back to DOS. FG_RESET is generally the last Fastgraph routine called in a program. It only functions in text video modes. When the ANSI.SYS driver is not loaded, fg_reset merely erases the screen. When ANSI.SYS is loaded, fg_reset also restores any previously set screen attributes. FG_SETMODE establishes a video mode and initializes Fastgraph's internal parameters for that video mode. It must be called before any Fastgraph routine that performs video output. A program can call fg_setmode as many times as needed to switch between different video modes. FG_TESTMODE determines whether or not a specified video mode (with a given number of video pages) is available on the user's system. 36 Fastgraph User's Guide Chapter 4 Coordinate Systems 38 Fastgraph User's Guide Overview Fastgraph uses three coordinate systems to perform text and graphics output. These coordinate systems are character space, screen space, and world space. The world space coordinate system is not available with Fastgraph/Light. Character Space The coordinate system used for displaying characters is called character space. Fastgraph uses character space for displaying characters in both text and graphics video modes. It can be thought of as a grid of rows and columns, with each cell in the grid holding one character. Each cell is identified by its unique (row,column) integer coordinates. The rows and columns are numbered starting at zero; the origin is always the upper left corner of the screen. For example, in the 80-column by 25-row text modes (2, 3, and 7), the (row,column) coordinates of the screen corners are shown in the following diagram. (0,0) (0,79) (24,0) (24,79) The number of rows and columns depends on the video mode, as shown in the following table. For graphics modes, the table also includes the width and height in pixels of a character cell. Mode No. of No. of Char. Char. Number Columns Rows Width Height 0 40 25 1 40 25 2 80 25 3 80 25 4 40 25 8 8 5 40 25 8 8 6 80 25 8 8 7 80 25 9 40 25 8 8 11 80 25 9 14 12 40 25 8 8 13 40 25 8 8 14 80 25 8 8 15 80 25 8 14 16 80 25 8 14 17 80 30 8 16 18 80 30 8 16 19 40 25 8 8 20 40 25 8 8 21 40 50 8 8 Chapter 4: Coordinate Systems 39 Fastgraph includes two routines, fg_getmaxx and fg_getmaxy, that respectively return the maximum column and row numbers in text modes. Example 4-1 demonstrates these two routines in a text mode. The program uses fg_getmaxx and fg_getmaxy to obtain the maximum column and row numbers in mode 3. It then displays these values (79 and 24). Example 4-1. main() { int max_col; int max_row; int mode; mode = fg_getmode(); fg_setmode(3); max_col = fg_getmaxx(); max_row = fg_getmaxy(); fg_setmode(mode); fg_reset(); printf("Last col = %d\n",max_col); printf("Last row = %d\n",max_row); } Screen Space Screen space is one of two available coordinate systems in graphics modes. It uses the physical device coordinates. Screen space can be thought of as a grid of rows and columns, with each unit in the grid holding one pixel. Each pixel is identified by its unique (x,y) integer coordinates. The rows and columns are numbered starting at zero; the origin is always the upper left corner of the screen. For example, in the 320 by 200 graphics modes, the (x,y) coordinates of the screen corners are shown in the following diagram. (0,0) (319,0) (0,199) (319,199) The Fastgraph routines fg_getmaxx and fg_getmaxy return the maximum x and y screen coordinates when used in graphics modes, as shown in example 4-2. The program uses fg_getmaxx and fg_getmaxy to obtain the maximum x and y coordinates in the standard CGA four-color graphics mode (mode 4). It then displays these values (319 and 199). Example 4-2. 40 Fastgraph User's Guide main() { int maxx; int maxy; int mode; mode = fg_getmode(); fg_setmode(4); maxx = fg_getmaxx(); maxy = fg_getmaxy(); fg_setmode(mode); fg_reset(); printf("(%d,%d)\n",maxx,maxy); } World Space World space is the other available coordinate system in graphics modes. It utilizes user-defined floating point coordinates. Fastgraph translates world space coordinates into physical device coordinates (screen space), and because of this it is somewhat slower than using screen space. World space can be thought of as a standard cartesian plane extending from the lower left corner of the screen. Any program that uses world space coordinates must first initialize Fastgraph's internal world space parameters. The Fastgraph routine fg_initw is provided for this purpose. The fg_initw routine has no arguments and must be called before any other routine that uses world space coordinates. The next step in using world space is to use the Fastgraph routine fg_setworld to define the world space coordinates of the screen edges. The fg_setworld routine has four floating-point arguments -- the minimum x coordinate (left edge), the maximum x coordinate (right edge), the minimum y coordinate (bottom edge), and the maximum y coordinate (top edge). For example, if you define the world space coordinates with the statement fg_setworld(-10.0,10.0,0.0,2.5); the (x,y) coordinates of the screen corners would be defined as shown in the following diagram. (-10.0,2.5) (10.0,2.5) (-10.0,0.0) (10.0,0.0) Fastgraph includes a routine fg_getworld that returns the world space extremes as defined in the most recent call to fg_setworld. Chapter 4: Coordinate Systems 41 Example 4-3 uses fg_setworld and fg_getworld to illustrate an interesting application of world space. This program calls another routine named redraw (not shown) that erases the screen and draws a certain image using world space coordinates. The program draws the image, waits for a keystroke, reduces the world space by a factor of two in each direction, and then draws the image again. This produces a zoom effect in which the image appears twice as large as it was originally. Example 4-3. main() { int new_mode, old_mode; double xmin, xmax, ymin, ymax; old_mode = fg_getmode(); new_mode = fg_automode(); if (new_mode == 0) { printf("This program requires graphics.\n"); exit(); } fg_setmode(new_mode); fg_initw(); fg_setworld(0.0,40.0,0.0,30.0); redraw(); fg_waitkey(); fg_getworld(&xmin,&xmax,&ymin,&ymax); fg_setworld(0.0,xmax*0.5,0.0,ymax*0.5); redraw(); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Conversion Routines It is often necessary to convert coordinates between character space, screen space, and world space. Fastgraph includes eight conversion routines, four for x coordinates and four for y coordinates, to perform such conversions. All of these routines return the translated coordinate as the function value. The fg_xalpha and fg_yalpha routines convert screen space coordinates to character space. The fg_xalpha routine converts a screen space x coordinate to the character space column that contains the coordinate. Similarly, the fg_yalpha routine converts a screen space y coordinate to the character space row that contains the coordinate. The fg_xconvert and fg_yconvert routines convert character space coordinates to screen space. The fg_xconvert routine converts a character 42 Fastgraph User's Guide space column to the screen space coordinate of its leftmost pixel. Similarly, the fg_yconvert routine converts a character space row to the screen space coordinate of its top (lowest-numbered) pixel. The fg_xscreen and fg_yscreen routines convert world space coordinates to screen space. The fg_xscreen routine translates x coordinates, while the fg_yscreen routine translates y coordinates. Conversely, the fg_xworld and fg_yworld routines convert screen space coordinates to world space. The fg_xworld routine translates x coordinates, while the fg_yworld routine translates y coordinates. Summary of Coordinate Routines This section summarizes the functional descriptions of the Fastgraph routines presented in this chapter. More detailed information about these routines, including their arguments and return values, may be found in the Fastgraph Reference Manual. FG_GETMAXX returns the maximum x coordinate in screen space when used in a graphics mode. It returns the maximum column number in character space when used in a text mode. FG_GETMAXY returns the maximum y coordinate in screen space when used in a graphics mode. It returns the maximum row number in character space when used in a text mode. FG_GETWORLD returns the current world space limits, as defined in the most recent call to fg_setworld. FG_INITW initializes Fastgraph's internal parameters for world space. This routine must be called once, before any other routine that uses world coordinates. FG_SETWORLD defines the world space coordinates that correspond to the physical edges of the screen. FG_XALPHA and FG_YALPHA convert screen space coordinates to character space. FG_XCONVERT and FG_YCONVERT convert character space coordinates to screen space. FG_XSCREEN and FG_YSCREEN convert world space coordinates to screen space. FG_XWORLD and FG_YWORLD convert screen space coordinates to world space. Chapter 5 The Use of Color 44 Fastgraph User's Guide Overview The use of color is an important part of any text or graphics application. This chapter explains color as it applies to text and graphics modes. It also describes palettes and video DAC registers for the graphics video modes that offer this functionality. Finally, an explanation of Fastgraph's virtual colors is provided. Text Modes The term color is not really correct in text modes because each character cell has an associated attribute that controls the character's appearance in that cell. The meaning of the attribute differs for color and monochrome text modes. Color Modes In color text modes (modes 0, 1, 2, and 3), the attribute determines a character's foreground color (the color of the character itself), its background color (the color of that part of the character cell not covered by the character), and whether or not it blinks. Sixteen foreground colors (numbered 0 to 15) are available, but only eight background colors (numbered 0 to 7) are available. The colors assigned to these values are listed in the following table. number color number color 0 black 8 gray 1 blue 9 light blue 2 green 10 light green 3 cyan 11 light cyan 4 red 12 light red 5 magenta 13 light magenta 6 brown 14 yellow 7 white 15 bright white At first it may seem the numbers have been arbitrarily assigned to the colors. Upon further inspection, however, it becomes apparent this is not the case. Each of the color numbers is a four bit quantity of the form IRGB, with I representing the intensity, R the red component, G the green component, and B the blue component. If the corresponding bit is 1, it means the intensity or color component is set. For example, normal red would be represented by the IRGB bit pattern 0100, which is 4 decimal, the color number for red. The fg_setattr routine defines the current text attribute. Once fg_setattr is called, Fastgraph displays all subsequent text using that attribute. The first argument of fg_setattr defines the foreground color, Chapter 5: The Use of Color 45 which must be an integer between 0 and 15. Its second argument defines the background color, which must be between 0 and 7. Its third argument determines if the foreground color blinks (1 means it blinks, 0 means it does not). For example, the statement fg_setattr(14,1,0); specifies subsequent text will be displayed with a yellow foreground (14) on a blue background (1) and will not blink (0). Another Fastgraph routine, fg_setcolor, can also be used to define text attributes. The fg_setcolor routine packs the three values passed to fg_setattr into a single argument, as shown below. bits attribute 0-3 foreground color 4-6 background color 7 blinking For example, calling fg_setcolor with an argument of 30 (1E hex) is equivalent to calling fg_setattr with arguments of 14, 1, and 0. The Fastgraph routine fg_getcolor returns the current text attribute, as defined in the most recent call to fg_setattr or fg_setcolor. The fg_getcolor routine has no arguments and returns the attribute as its function value. The returned value is encoded using the same scheme for passing a text attribute to the fg_setcolor routine. Monochrome Mode In the monochrome text mode (mode 7), colors are obviously not available. The attribute instead determines whether a character is invisible, normal, bold, reversed, or certain combinations of these. The following table shows the values assigned to the available display characteristics. foreground background characteristic 0 0 invisible 0 7 reversed 1 0 underlined 7 0 normal 9 0 underlined bold 15 0 bold Additionally, you can turn blinking on or off for each of these combinations. Any combination of foreground and background values not listed in the above table produces a normal display characteristic. 46 Fastgraph User's Guide As in the color modes, the Fastgraph routines fg_setattr and fg_setcolor define the current text attribute. For example, the statement fg_setattr(0,7,1); specifies subsequent text will be displayed in reverse video (0,7) and will blink (1). The same attribute could be defined by calling fg_setcolor with an argument of 240 (F0 hex). The fg_getcolor routine is also available and works as it does in the color text modes. Graphics Modes In graphics modes, each pixel has an associated color value that determines the color in which the pixel is displayed. The number of available colors depends on the video mode. Some of the graphics modes also have palette registers or video DAC registers to provide additional color capabilities. The example programs presented in this section show the use of color in specific graphics video modes. The following subsections will discuss the use of color in each of the graphics video modes. In these discussions, there will be several references to a group of colors called the standard color set. This is a set of 16 colors common to many of the graphics video modes (and also to the color text modes). The colors in the standard color set are listed in the following table. number color number color 0 black 8 gray 1 blue 9 light blue 2 green 10 light green 3 cyan 11 light cyan 4 red 12 light red 5 magenta 13 light magenta 6 brown 14 yellow 7 white 15 bright white At this point it is important to understand the difference between the terms color number and color value. Color number refers to the number that defines a color in the standard color set (for example, green is color number 2). Color value refers to the actual value of a pixel in video memory, which ultimately determines the color in which that pixel is displayed. The color value is sometimes just called the color. In each of the graphics modes, video memory is zeroed when the fg_setmode routine is called. This means all pixels are initially set to color value 0, which by default is black. For this reason, color value 0 is often called the background color in graphics video modes. Chapter 5: The Use of Color 47 The Fastgraph routine fg_setcolor defines the color in which subsequent graphics operations are performed. This color is called the current color. Depending on the video mode, the current color can reference a color value (in CGA and Hercules graphics modes), a palette register (in Tandy, EGA, and VGA graphics modes), or a video DAC register (in 256-color modes). The fg_setcolor routine takes a single integer argument that specifies the color. When fg_setmode is called, it sets the current color to 0. The Fastgraph routine fg_getcolor returns the current color, as defined in the most recent call to fg_setcolor. The fg_getcolor routine has no arguments and returns the current color as its function value. CGA Color Modes The CGA color modes (modes 4 and 5) have six sets of available colors, called palettes, numbered 0 to 5. Each palette consists of four colors, numbered 0 to 3. In each palette, the background color (color value 0) can be selected from the standard color set, but the other 3 colors are fixed. The following table shows the fixed colors assigned to each palette. palette 0 palette 1 palette 2 color 1 light green light cyan light cyan color 2 light red light magenta light red color 3 yellow bright white bright white palette 3 palette 4 palette 5 color 1 green cyan cyan color 2 red magenta red color 3 brown white white Palette 1, with a black background, is the default palette when you select mode 4. Palette 2, with a black background, is the default palette when you select mode 5. The CGA color modes have a border area called the overscan between the addressable pixel space and the physical edges of the screen. The overscan area is always displayed in the background color, regardless of which CGA palette is used. In CGA color modes, the fg_setcolor routine defines the current color by referencing one of the four color values. The fg_palette routine selects one of the six palettes and defines the background color for that palette. The first argument of the fg_palette routine is an integer between 0 and 5 that specifies the palette number. The second argument is an integer between 0 and 15 that defines the background color, using the color numbers in the standard color set. Example 5-1 demonstrates the use of the fg_palette and fg_setcolor routines in mode 4. After establishing the video mode, the program selects palette 0 and makes the background color blue (color number 1). It then makes color 3 in palette 0 (yellow) the current color and displays the word "Hello". Finally, it restores the original video mode and screen attributes before returning to DOS. 48 Fastgraph User's Guide Example 5-1. main() { int mode; mode = fg_getmode(); fg_setmode(4); fg_palette(0,1); fg_setcolor(3); fg_text("Hello",5); fg_waitkey(); fg_setmode(mode); fg_reset(); } CGA Two-Color Mode The CGA two-color mode (mode 6) has a fixed background color (color value 0) and a user-definable foreground color (color value 1). The background color is always black. The foreground color is bright white by default, but it can be changed to any of the colors in the standard color set. It should be mentioned that changing the foreground color works on true CGA adapters, but there are very few EGA and VGA adapters that correctly implement changing the foreground color in their mode 6 emulation. In mode 6, the fg_setcolor routine defines the current color by referencing one of the two color values. The fg_palette routine defines the actual foreground color (that is, the color of pixels whose color value is 1). To be consistent with the other graphics modes, the fg_palette routine has two arguments, but the first one is not used. The second argument is an integer between 0 and 15 that defines the foreground color, using the color numbers in the standard color set. Example 5-2 demonstrates the use of the fg_palette and fg_setcolor routines in mode 6. After establishing the video mode, the program makes the foreground color yellow (color number 14). It then makes color 1 the current color and displays the word "Hello". Finally, it restores the original video mode and screen attributes before returning to DOS. Example 5-2. main() { int mode; mode = fg_getmode(); fg_setmode(6); fg_palette(0,14); fg_setcolor(1); fg_text("Hello",5); Chapter 5: The Use of Color 49 fg_waitkey(); fg_setmode(mode); fg_reset(); } Tandy and PCjr Modes The supported Tandy 1000 or PCjr graphics mode (mode 9) has 16 color values, numbered 0 to 15. Each color value references one of 16 user- definable palette registers, often simply called palettes, also numbered 0 to 15. The values assigned to the palette registers determine the colors in which pixels are displayed. For example, if you assign palette register 2 the value for red, then pixels whose color value is 2 will be red. Each palette can assume one of the 16 colors in the standard color set. By default, the values assigned to the 16 palettes correspond to the identically numbered colors in the standard color set. In other words, palette 0 is assigned the value for black, palette 1 is assigned the value for blue, and so forth. In mode 9, the fg_setcolor routine defines the current color by referencing one of the 16 palette registers. The fg_palette routine defines the actual color assigned to a specific palette register. The first argument of the fg_palette routine is an integer between 0 and 15 that specifies the palette number. The second argument is an integer between 0 and 15 that defines the palette value (the color assigned to the palette), using the color numbers in the standard color set. You can also use the Fastgraph routine fg_setrgb to define the color assigned to a specific palette register. Whereas the fg_palette routine does this using a color number from the standard color set, fg_setrgb defines a palette register using red, green, and blue color components plus an intensity component. The first argument of the fg_setrgb routine is an integer between 0 and 15 that specifies the palette register number. The remaining three arguments are each integers between -1 and 1 that respectively specify the red, green, and blue color components for that palette register. The meanings of the color components are: -1 = color bit and intensity bit are set 0 = color bit is reset 1 = color bit is set Since there is only one intensity bit in mode 9 color values, specifying -1 for any of the RGB color components produces an intense color. For example, the color light cyan is color number 11 in the standard color set, and it is produced by combining green and blue and setting the intensity bit. This means any of these four statements fg_palette(1,11); fg_setrgb(1,0,-1,1); fg_setrgb(1,0,1,-1); fg_setrgb(1,0,-1,-1); 50 Fastgraph User's Guide could be used to define palette register 1 as light cyan in mode 9. Example 5-3 demonstrates the use of the fg_palette and fg_setcolor routines in mode 9. After establishing the video mode, the program defines palette 0 to be blue (1) and palette 1 to be yellow (14). Note that defining palette 0 changes the background color. It then makes color 1 the current color and displays the word "Hello". After waiting for a keystroke, the program changes the color of "Hello" by changing palette 1 to bright white (15). Finally, it restores the original video mode and screen attributes before returning to DOS. Example 5-3. main() { int mode; mode = fg_getmode(); fg_setmode(9); fg_palette(0,1); fg_palette(1,14); fg_setcolor(1); fg_text("Hello",5); fg_waitkey(); fg_palette(1,15); fg_waitkey(); fg_setmode(mode); fg_reset(); } Hercules Mode The Hercules graphics mode (mode 11) has a fixed background color (color value 0) and a fixed foreground color (color value 1). The background color is always black, and the foreground color is dependent on the monochrome display being used (typically, it is green, amber, or white). The fg_setcolor routine defines the current color value by referencing one of the two color values. The fg_palette routine has no effect in mode 11. Example 5-4 demonstrates the use of the fg_setcolor routine in mode 11. After establishing the video mode, the program makes color 1 the current color and displays the word "Hello". It then restores the original video mode and screen attributes before returning to DOS. Example 5-4. main() { Chapter 5: The Use of Color 51 int mode; mode = fg_getmode(); fg_setmode(11); fg_setcolor(1); fg_text("Hello",5); fg_waitkey(); fg_setmode(mode); fg_reset(); } Hercules Low-Resolution Mode The Hercules low-resolution graphics mode (mode 12) has four color values, numbered 0 to 3. The background color is always black, colors 1 and 2 are half intensity, and color 3 is full intensity. Colors 1 and 2 both produce normal intensity colors, but they do so with different pixel patterns -- color 1 turns on the odd-numbered physical pixels, while color 2 turns on the even-numbered physical pixels. The appearance of colors 1 to 3 is dependent on the monochrome display being used (typically, it is green, amber, or white). The fg_setcolor routine defines the current color value by referencing one of the four color values. The fg_palette routine has no effect in mode 12. Example 5-5 demonstrates the use of the fg_setcolor routine in mode 12. After establishing the video mode, the program makes color 3 the current color and displays the word "Hello". It then restores the original video mode and screen attributes before returning to DOS. Example 5-5. main() { int mode; mode = fg_getmode(); fg_setmode(12); fg_setcolor(3); fg_text("Hello",5); fg_waitkey(); fg_setmode(mode); fg_reset(); } 52 Fastgraph User's Guide EGA 200-Line Modes The 200-line EGA graphics modes (modes 13 and 14) have 16 color values, numbered 0 to 15. Each color value references one of 16 user-definable palette registers, often simply called palettes, also numbered 0 to 15. The values assigned to the palette registers determine the colors in which pixels are displayed. For example, if you assign palette register 2 the value for red, then pixels whose color value is 2 will be red. Each palette can assume one of the 16 colors in the standard color set. By default, the values assigned to the 16 palettes correspond to the identically numbered colors in the standard color set. In other words, palette 0 is assigned the value for black, palette 1 is assigned the value for blue, and so forth. In modes 13 and 14, the fg_setcolor routine defines the current color by referencing one of 16 available palette registers. The fg_palette routine defines the actual color assigned to a specific palette register. The first argument of the fg_palette routine is an integer between 0 and 15 that specifies the palette number. The second argument is an integer that defines the palette value (the color assigned to the palette). Although the actual colors are taken from the standard color set, the binary structure of a palette value is different from the IRGB format used in the standard color set. In modes 13 and 14, the binary structure of a palette value is IxRGB; bit 3 is ignored. The mode 13 and mode 14 palette values that correspond to the standard color set are thus: value color value color 0 black 16 gray 1 blue 17 light blue 2 green 18 light green 3 cyan 19 light cyan 4 red 20 light red 5 magenta 21 light magenta 6 brown 22 yellow 7 white 23 bright white You can also use the Fastgraph routine fg_setrgb to define the color assigned to a specific palette register. Whereas the fg_palette routine does this using a color number from the standard color set, fg_setrgb defines a palette register using red, green, and blue color components, plus an intensity component. The first argument of the fg_setrgb routine is an integer between 0 and 15 that specifies the palette register number. The remaining three arguments are each integers between -1 and 1 that respectively specify the red, green, and blue color components for that palette register. The meanings of the color components are: Chapter 5: The Use of Color 53 -1 = color bit and intensity bit are set 0 = color bit is reset 1 = color bit is set Since there is only one intensity bit in mode 13 and 14 color values, specifying -1 for any of the RGB color components produces an intense color. For example, the color light cyan is represented by the color value 19, and it is produced by combining green and blue and setting the intensity bit. This means any of these four statements fg_palette(1,19); fg_setrgb(1,0,-1,1); fg_setrgb(1,0,1,-1); fg_setrgb(1,0,-1,-1); could be used to define palette register 1 as light cyan in modes 13 and 14. The Fastgraph routine fg_setcolor defines the color value (that is, the palette number) in which subsequent graphics operations are performed. The fg_setcolor routine takes a single integer argument that specifies this color. When fg_setmode is called, it sets the color value to 0. The Fastgraph routine fg_getcolor returns the current color value, as defined in the most recent call to fg_setcolor. The fg_getcolor routine has no arguments and returns the current color as the function value. Example 5-6 demonstrates the use of the fg_palette and fg_setcolor routines in mode 13. After establishing the video mode, the program defines palette 0 to be blue (1) and palette 1 to be yellow (22). Note that defining palette 0 changes the background color. It then makes color 1 the current color and displays the word "Hello". After waiting for a keystroke, the program changes the color of "Hello" by changing palette 1 to bright white (23). Finally, it restores the original video mode and screen attributes before returning to DOS. Example 5-6. main() { int mode; mode = fg_getmode(); fg_setmode(13); fg_palette(0,1); fg_palette(1,22); fg_setcolor(1); fg_text("Hello",5); fg_waitkey(); fg_palette(1,23); fg_waitkey(); fg_setmode(mode); fg_reset(); } 54 Fastgraph User's Guide EGA Monochrome Mode The EGA monochrome graphics mode (mode 15) assigns display attributes to its four color values, numbered 0 to 3. Each color value references one of four user-definable palette registers, often simply called palettes, numbered 0, 1, 4, and 5. This numbering scheme might seem rather strange at first, but it results from the disabling of two of the four video memory bit planes in mode 15. The values assigned to the palette registers determine the pixel display attribute. For example, if you assign palette register 1 the value for bold, then pixels whose value is 1 will be bold. In mode 15, the fg_setcolor routine defines the current color (actually, a display attribute) by referencing one of the four palette registers. The fg_palette routine defines the actual display attribute assigned to a specific palette register. The first argument of the fg_palette routine is an integer that specifies the palette number. The second argument is an integer that defines the palette value (the display attribute assigned to the palette). For each palette register, the following table shows the default palette value and its associated display attribute. palette palette display number value attribute 0 0 invisible 1 8 normal 4 24 bold 5 24 bold Example 5-7 demonstrates the use of the fg_palette and fg_setcolor routines in mode 15. After establishing the video mode, the program makes color 4 (actually, palette 4, which is bold by default) the current color and displays the word "Hello". After waiting for a keystroke, the program changes the display attribute of "Hello" by changing palette 4 to normal intensity (palette value 8). Finally, it restores the original video mode and screen attributes before returning to DOS. Example 5-7. main() { int mode; mode = fg_getmode(); fg_setmode(15); fg_setcolor(4); fg_text("Hello",5); fg_waitkey(); fg_palette(4,8); Chapter 5: The Use of Color 55 fg_waitkey(); fg_setmode(mode); fg_reset(); } EGA Enhanced Mode The EGA enhanced graphics mode (mode 16) has 16 color values, numbered 0 to 15. Each color value references one of 16 user-definable palette registers, often simply called palettes, also numbered 0 to 15. The values assigned to the palette registers determine the colors in which pixels are displayed. For example, if you assign palette register 2 the value for red, then pixels whose color value is 2 will be red. Each palette can assume one of 64 available colors. By default, the values assigned to the 16 palettes correspond to the identically numbered colors in the standard color set. In other words, palette 0 is assigned the value for black, palette 1 is assigned the value for blue, and so forth. There are a few EGA-compatible adapters that do not properly assign the default colors to the 16 palette registers, so it is a good practice to do this explicitly in mode 16. In mode 16, the fg_setcolor routine defines the current color value by referencing one of the 16 palette registers. The fg_palette routine defines the actual color assigned to a specific palette register. The first argument of the fg_palette routine is an integer between 0 and 15 that specifies the palette number. The second argument is an integer that defines the palette value (the color assigned to the palette). The binary structure of a palette value is different from the IRGB format used in the standard color set. In mode 16, the binary structure of a palette value is a 6-bit quantity of the form rgbRGB, where the lower case letters represent the low intensity (1/3 intensity) color components, and the upper case letters represent the normal intensity (2/3 intensity) color components. The mode 16 palette values that correspond to the standard color set are: value color value color 0 black 56 gray 1 blue 57 light blue 2 green 58 light green 3 cyan 59 light cyan 4 red 60 light red 5 magenta 61 light magenta 20 brown 62 yellow 7 white 63 bright white The normal intensity components in mode 16 produce the same normal intensity colors as in other 16-color graphics modes. Similarly, combining 56 Fastgraph User's Guide the low and normal intensities in mode 16 produces the high intensity colors of the other modes. The only exception to this is for the default brown, which is formed from the bit pattern 010100 (20 decimal). This value produces a more true brown than the value 6 decimal, which is really an olive green. The palette values used in mode 16 are 6-bit quantities, which means there are 64 different colors available in mode 16. This group of 64 colors consists of the 16 colors in the standard color set plus 48 additional colors that are not available in any of the other EGA modes. However, because the EGA palette registers hold 4-bit quantities, only 16 of these colors can be displayed at the same time. In other words, the EGA enhanced mode provides the capability of displaying 16 simultaneous colors from a group of 64. You can also use the Fastgraph routine fg_setrgb to define the color assigned to a specific palette register. Whereas the fg_palette routine does this using a value between 0 and 63, fg_setrgb defines a palette register using red, green, and blue color components. The first argument of the fg_setrgb routine is an integer between 0 and 15 that specifies the palette register number. The remaining three arguments are each integers between 0 and 3 that respectively specify the intensities in thirds of the red, green, and blue color components for that palette register. For example, the color cyan is represented by the value 3 in the above table, and it is produced by combining normal intensity (2/3 intensity) green and blue. This means either of the statements fg_palette(1,3); fg_setrgb(1,0,2,2); could be used to define palette register 1 as cyan. Example 5-8 demonstrates the use of the fg_palette and fg_setcolor routines in mode 16. It uses the Fastgraph routine fg_rect (discussed in the next chapter) to draw rectangles of a specified size. After establishing the video mode, the program uses a for loop to draw 16 equal-size rectangles, one in each of the 16 color values. In the same loop, the program uses the fg_palette routine to change each palette to black. The while loop that follows performs four iterations. The first iteration changes palette 0 to 0, palette 1 to 1, and so forth. Hence, the 16 rectangles appear in the palette values 0 to 15. The rectangles remain in these colors until is key is pressed to begin the next iteration. The second iteration changes palette 0 to 16, palette 1 to 17, and so forth. This makes the 16 rectangles appear in the palette values 16 to 31. Iterations three and four are similar, so the overall effect of the program is to display all 64 colors, 16 at a time. Finally, the program restores the original video mode and screen attributes before returning to DOS. Example 5-8. #define COLORS 16 #define WIDTH 40 main() { int base; Chapter 5: The Use of Color 57 int color; int minx, maxx; int mode; mode = fg_getmode(); fg_setmode(16); base = 0; minx = 0; maxx = WIDTH - 1; for (color = 0; color < COLORS; color++) { fg_palette(color,0); fg_setcolor(color); fg_rect(minx,maxx,0,349); minx = maxx + 1; maxx = maxx + WIDTH; } while (base < COLORS*4) { for (color = 0; color < COLORS; color++) fg_palette(color,base+color); base += COLORS; fg_waitkey(); } fg_setmode(mode); fg_reset(); } VGA and MCGA Two-Color Mode The VGA and MCGA high-resolution two-color mode (mode 17) has a background color (color value 0) and a foreground color (color value 1). Each color value references one of two user-definable palette registers, often simply called palettes, also numbered 0 and 1. Each palette register in turn references one of 16 user-definable 18-bit video DAC registers, numbered 0 to 15. The values assigned to the palette registers and video DAC registers determine the colors in which pixels are displayed. For example, if palette register 1 contains the value 3, and video DAC register 3 contains the color value for red, then pixels whose color value is 1 (that is, the foreground pixels) will be red. By default, palette register 0 references video DAC register 0, and palette register 1 references video DAC register 1. In addition, video DAC register 0 initially contains the color value for black, while the other 15 video DAC registers (1 through 15) contain the color value for bright white. This means background pixels (color value 0) are black by default, while foreground pixels (color value 1) are bright white. The 18-bit video DAC values consist of three 6-bit red, green, and blue color components. Hence, each color component is an integer between 0 and 63; increasing values produce more intense colors. The default color components for DAC register 0 are red=0, blue=0, and green=0, which produces black. The default values for the other DAC registers are red=63, blue=63, 58 Fastgraph User's Guide and green=63, which produces bright white. Because the video DAC registers are 18 bits long, each DAC can specify one of 262,144 (218) colors. However, because the palette registers hold 1-bit quantities, only two of these colors can be displayed at the same time. In other words, mode 17 provides the capability of displaying two simultaneous colors from a group of 262,144. In mode 17, the fg_setcolor routine defines the current color by referencing one of the two palette registers. The fg_palette routine defines the value of a palette register by referencing one of the 16 video DAC registers. That is, the fg_palette routine specifies the video DAC register that a palette register references. The first argument of the fg_palette routine is either 0 or 1 and specifies the palette number. The second argument is an integer between 0 and 15 that specifies the video DAC register for that palette. The Fastgraph routine fg_setrgb defines the value of a video DAC register in mode 17. The first argument of the fg_setrgb routine is an integer between 0 and 15 that specifies the DAC register number. The remaining three arguments are each integers between 0 and 63 that respectively specify the red, green, and blue color components for that DAC register. Example 5-9 demonstrates the use of the fg_palette, fg_setrgb, and fg_setcolor routines in mode 17. After establishing the video mode, the program defines DAC register 0 to be blue (red=0, green=0, blue=42) and DAC register 1 to be yellow (red=63, green=63, blue=21). Note that defining DAC register 0 changes the background color because palette 0 references DAC register 0. The program then makes color 1 the current color (palette 1 still references DAC register 1) and displays the word "Hello" in yellow. After waiting for a keystroke, the program changes the color of "Hello" by making palette 1 reference DAC register 15 (which still contains its default value, bright white). Finally, it restores the original video mode and screen attributes before returning to DOS. Example 5-9. main() { int mode; mode = fg_getmode(); fg_setmode(17); fg_setrgb(0,0,0,42); fg_setrgb(1,63,63,21); fg_setcolor(1); fg_text("Hello",5); fg_waitkey(); fg_palette(1,15); fg_waitkey(); fg_setmode(mode); fg_reset(); } Chapter 5: The Use of Color 59 VGA 16-Color Mode The VGA high-resolution two-color mode (mode 18) has 16 color values, numbered 0 to 15. Each color value references one of 16 user-definable palette registers, often simply called palettes, also numbered 0 to 15. Each palette register in turn references one of 16 user-definable 18-bit video DAC registers, likewise numbered 0 to 15. The values assigned to the palette registers and video DAC registers determine the colors in which pixels are displayed. For example, if palette register 1 contains the value 3, and video DAC register 3 contains the color value for red, then pixels whose color value is 1 will be red. By default, each of the 16 palette registers references the video DAC register of the same number. In addition, the 16 video DAC registers respectively contain the color values for the 16 colors in the standard color set. The 18-bit video DAC values consist of three 6-bit red, green, and blue color components. Hence, each color component is an integer between 0 and 63; increasing values produce more intense colors. The default RGB color components for the 16 video DAC registers are: DAC R G B color DAC R G B color 0 0 0 0 black 8 21 21 21 gray 1 0 0 42 blue 9 21 21 63 light blue 2 0 42 0 green 10 21 63 21 light green 3 0 42 42 cyan 11 21 63 63 light cyan 4 42 0 0 red 12 63 21 21 light red 5 42 0 42 magenta 13 63 21 63 light magenta 6 42 21 0 brown 14 63 63 21 yellow 7 42 42 42 white 15 63 63 63 bright white Because the video DAC registers are 18 bits long, each DAC can specify one of 262,144 (218) colors. However, because the palette registers hold 4-bit quantities, only 16 of these colors can be displayed at the same time. In other words, mode 18 provides the capability of displaying 16 simultaneous colors from a group of 262,144. In mode 18, the fg_setcolor, fg_palette, and fg_setrgb routines function exactly as in mode 17 with one exception: there are 16 palette registers instead of just two. Example 5-9 on page 58 demonstrates the use of these routines in mode 17, but it would also work in mode 18 if that video mode number were specified in the call to fg_setmode. 60 Fastgraph User's Guide VGA and MCGA 256-Color Modes The VGA and MCGA 256-color modes (modes 19, 20, and 21) have 256 color values, numbered 0 to 255. Each color value directly references one of 256 user-definable 18-bit video DAC registers, also numbered 0 to 255. The values assigned to the video DAC registers determine the colors in which pixels are displayed. For example, if video DAC register 3 contains the color value for red, then pixels whose color value is 3 will be red. By default, the first 16 video DAC registers (0 to 15) contain the color values for the standard color set. The next 16 DAC registers (16 to 31) contain the color values for a gray scale of gradually increasing intensity. The next 216 DAC registers (32 to 247) contain three groups of 72 colors each, with the first group (32 to 103) at high intensity, the second group (104 to 175) at moderate intensity, and the third group (176 to 247) at low intensity. Each group consists of three ranges of decreasing saturation (increasing whiteness), with each range varying in hue from blue to red to green. Finally, the last 8 DAC registers (248 to 255) alternate between black and bright white. This information is summarized in the following table. DACs default color values 0 to 15 standard color set 16 to 31 gray scale of gradually increasing intensity 32 to 55 high saturation, high intensity colors 56 to 79 moderate saturation, high intensity colors 80 to 103 low saturation, high intensity colors 104 to 127 high saturation, moderate intensity colors 128 to 151 moderate saturation, moderate intensity colors 152 to 175 low saturation, moderate intensity colors 176 to 199 high saturation, low intensity colors 200 to 223 moderate saturation, low intensity colors 224 to 247 low saturation, low intensity colors 248 to 255 alternate between black and bright white The 18-bit video DAC values consist of three 6-bit red, green, and blue color components. Hence, each color component is an integer between 0 and 63; increasing values produce more intense colors. Because the video DAC registers are 18 bits long, each DAC can specify one of 262,144 (218) colors. However, because the color values are 8-bit quantities, only 256 of these colors can be displayed at the same time. In other words, modes 19, 20, and 21 provide the capability of displaying 256 simultaneous colors from a group of 262,144. Chapter 5: The Use of Color 61 In the VGA and MCGA 256-color video modes, the fg_setcolor routine defines the current color by referencing on of the 256 video DAC registers. The fg_setrgb routine defines the actual color of a video DAC register. The first argument of the fg_setrgb routine is an integer between 0 and 15 that specifies the DAC register number. The remaining three arguments are each integers between 0 and 63 that respectively specify the red, green, and blue color components for that DAC register. Another Fastgraph routine, fg_getrgb, returns the color components for a specified DAC register. Its arguments are the same as for fg_setrgb, except the last three arguments (the return values) are passed by reference rather than by value. You can also the Fastgraph routine fg_palette to define the value of a video DAC register in modes 19, 20, and 21. The first argument of the fg_palette routine is an integer between 0 and 255 that specifies the DAC register number. The second argument is an integer between 0 and 63 that specifies the color value for that video DAC register, using the same 64 values as in the EGA enhanced mode (mode 16). Example 5-10 demonstrates the use of the fg_setcolor routine in mode 19. The program uses the Fastgraph routine fg_rect to draw vertical lines. After establishing the video mode, the program uses a for loop to draw 256 vertical lines, one in each of the 256 colors (using the default DAC values). Finally, the program restores the original video mode and screen attributes before returning to DOS. Example 5-10. #define COLORS 256 main() { int base; int color; int mode; int x; mode = fg_getmode(); fg_setmode(19); x = 32; for (color = 0; color < COLORS; color++) { fg_setcolor(color); fg_rect(x,x,0,199); x++; } fg_waitkey(); fg_setmode(mode); fg_reset(); } 62 Fastgraph User's Guide Example 5-11. main() { int old_mode; int red, green, blue; old_mode = fg_getmode(); fg_setmode(19); fg_setcolor(103); fg_text("Hello",5); fg_waitfor(18); fg_getrgb(103,&red,&green,&blue); while (red+green+blue > 0) { if (red > 0) red--; if (green > 0) green--; if (blue > 0) blue--; fg_setrgb(103,red,green,blue); fg_waitfor(1); } fg_setmode(old_mode); fg_reset(); } Example 5-11 shows an interesting effect available in VGA and MCGA modes. The program uses the Fastgraph routine fg_waitfor (discussed in chapter 14) to delay the program's execution. After establishing the video mode, the program displays the word "Hello" in color 103, which by default is a pastel blue. It then uses the Fastgraph routine fg_getrgb to retrieve the color components for this color. The while loop gradually decreases the color components until all three components are zero, which makes the word "Hello" smoothly fade to black. Finally, the program restores the original video mode and screen attributes before returning to DOS. You could extend the program in example 5-11 to fade many colors simultaneously. This is an attractive way of turning an image into a blank screen. Note that example 5-11 would also work in video modes 17 and 18 as long as you just use the first 16 video DAC registers. Defining All Palette Registers Fastgraph includes a routine fg_palettes that defines all 16 palette registers in modes 9, 13, 14, 16, and 18. You can also use the fg_palettes routine to define the first 16 video DAC registers in modes 19, 20, and 21. It has no effect in other video modes. Using fg_palettes is considerably faster than calling the fg_palette routine 16 times. The argument to the fg_palettes routine is a 16-element integer array that contains the color values assigned respectively to palette registers (or video DAC registers) 0 to 15. Example 5-12 demonstrates how to zero the palette registers (that is, change them all to black) in mode 13. Chapter 5: The Use of Color 63 Example 5-12. int zeroes[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; main() { int mode; mode = fg_getmode(); fg_setmode(13); fg_palettes(zeroes); fg_setmode(mode); fg_reset(); } Of course, as example 5-12 is written, it appears to do nothing more than blank the screen. Its purpose is just to show an example of the fg_palettes routine. Virtual Colors By this time it should be apparent the use of color is rather specific to each graphics video mode. One of the most obvious differences is the number of available colors in each mode; it ranges from 2 to 256. By available colors, we mean the number of colors that can be displayed simultaneously. To simplify programming in graphics modes, Fastgraph provides 256 virtual colors. The virtual colors are used in the graphics video modes having fewer than 256 available colors. Virtual colors allow you to use 256 color indices in all graphics modes, even if a particular mode does not have 256 available colors. When you establish a video mode with the fg_setmode routine, Fastgraph initializes all of the virtual color indices. It does this by replicating the video mode's color values through the 256 virtual color indices. For example, the CGA color modes (4 and 5) have four color values, numbered 0 through 3. In these modes, the fg_setmode routine initializes color indices 0, 4, 8, ... , 252 to 0; color indices 1, 5, 9, ... , 253 to 1; color indices 2, 6, 10, ... , 254 to 2; and color indices 3, 7, 11, ... , 255 to 3. Similarly, in 16-color graphics modes the color indices 0, 16, 32, ... , 240 are set to 0, and so forth. An analysis of the color value sequences reveals an often useful feature: by default, virtual color 0 is black and virtual color 15 is white or bright white in all graphics video modes. It is thus possible to write a multiple-mode program using the same color indices for each graphics mode. For example, a program that contains the statement fg_setcolor(5) would produce subsequent graphics in color 5 (magenta by default) when running in a 16-color graphics mode. It would produce subsequent graphics in color 1 (light cyan by default) when running in a CGA color mode. This is because 1 is the default value assigned to virtual color index 5 in the CGA color modes. 64 Fastgraph User's Guide The fg_setmode routine establishes default values for the 256 virtual color indices, but it might be desirable to assign other available colors to them. Going back to the discussion in the previous paragraph, color number 2 is light magenta in the default CGA mode 4 palette. It might make more sense if the color value 2 were assigned to virtual color index 5, as this would make the graphics drawn in color 5 the same color in mode 4 as in other color modes. The Fastgraph routine fg_defcolor is provided for this purpose. The fg_defcolor routine assigns a color value to a virtual color index. It has two arguments: the first specifies the virtual color index (between 0 and 255), and the second specifies the color value (between 0 and the number of available colors in the current video mode). For example, the statement fg_defcolor(5,2); would assign the color value 2 to the color index 5. Another Fastgraph routine, fg_getindex, returns the current value assigned to a specified color index. After executing the above call to fg_defcolor, the statement color = fg_getindex(5); would store the value 2 (the current value of color index 5) in the integer variable color. It is important to understand the difference between virtual colors and palette registers. Modifying the value of a palette register changes the color of all pixels already drawn using that palette. Modifying a virtual color index does not do this; it only specifies any graphics drawn in that color from this point on will appear in the new color. Example 5-13 demonstrates the use of virtual colors in mode 4. After establishing the video mode, the program uses the fg_defcolor routine to define virtual color indices 0 and 255 to be 1, which by default is light cyan in mode 4. It then draws characters using color indices 0, 1, and 255, and in each case the characters appear in light cyan. Finally, the program restores the original video mode and screen attributes before returning to DOS. Example 5-13. main() { int mode; mode = fg_getmode(); fg_setmode(4); fg_defcolor(0,1); fg_defcolor(255,1); fg_setcolor(0); fg_text("0",1); fg_setcolor(1); fg_text(" 1",2); fg_setcolor(255); fg_text(" 255",4); fg_waitkey(); Chapter 5: The Use of Color 65 fg_setmode(mode); fg_reset(); } A Multiple-Mode Example Even though the color capabilities differ considerably between the supported video modes, Fastgraph makes it easy to write a program that runs in many video modes. This section will present an example of such a program. Example 5-14 illustrates a program that will run in any of Fastgraph's supported video modes. The program first asks for the video mode number, checks if the mode number is valid, and then checks if the requested mode is available on the user's system. After doing this, the program establishes the video mode and performs its mode-specific code. It then displays a brief message that includes the video mode number in which the program is running. This information remains on the screen until a key is pressed, at which time the program restores the original video mode and screen attributes before returning to DOS. Example 5-14. main() { int mode, old_mode; char string[5]; /* Ask for the video mode number */ printf("Which video mode? "); scanf("%d",&mode); /* Make sure the entered value is valid */ if (mode < 0 || mode > 21) { printf("%d is not a valid video mode number.\n",mode); exit(); } /* Make sure the requested video mode is available */ if (fg_testmode(mode,1) == 0) { printf("Mode %d is not available on this system.\n",mode); exit(); } /* Establish the video mode */ old_mode = fg_getmode(); fg_setmode(mode); /* Perform mode-specific initializations */ if (mode <= 3 || mode == 7) /* text modes */ fg_cursor(0); else if (mode == 4 || mode == 5) { /* CGA color modes */ fg_palette(0,0); fg_defcolor(14,3); 66 Fastgraph User's Guide } else if (mode == 6) { /* CGA two-color mode */ fg_palette(0,14); fg_defcolor(14,1); } else if (mode == 11) /* Hercules mode */ fg_defcolor(14,1); else if (mode == 12) /* Hercules low-res mode */ fg_defcolor(14,3); else if (mode == 17) { /* VGA two-color mode */ fg_palette(1,14); fg_setrgb(14,63,63,21); fg_defcolor(14,1); } /* Display a message that includes the video mode number */ fg_setcolor(14); fg_text("I'm running in mode ",20); sprintf(string,"%d. ",mode); fg_text(string,3); /* Wait for a keystroke */ fg_waitkey(); /* Restore the original video mode and screen attributes */ fg_setmode(old_mode); fg_reset(); } Example 5-14 displays its message in yellow for those video modes that offer color. In monochrome video modes, it displays the message in normal intensity. The program uses virtual color 14, which by default is yellow in many video modes; the mode-specific code in example 5-14 makes color 14 yellow in other video modes. In text video modes (modes 0 to 3 and 7), the program uses the fg_cursor routine to make the cursor invisible. In CGA color modes (modes 4 and 5), the program uses the fg_palette routine to select a CGA palette that contains yellow as color 3 and then uses fg_defcolor to assign color 3 to virtual color 14. In CGA two-color mode (mode 6), the program uses the fg_palette routine to make color 1 yellow and then uses fg_defcolor to assign color 1 to virtual color 14. In the Hercules modes (modes 11 and 12), the program uses the fg_defcolor routine to assign the value for normal intensity pixels to color 14. In VGA two-color mode (mode 17), the program uses the fg_palette routine to assign video DAC register 14 to palette register 1. It then defines video DAC register 14 to be yellow with the fg_setrgb routine and finally uses fg_defcolor to assign color 1 (that is, palette register 1) to virtual color 14. In all of the other video modes, color 14 is yellow by default. Chapter 5: The Use of Color 67 Summary of Color-Related Routines This section summarizes the functional descriptions of the Fastgraph routines presented in this chapter. More detailed information about these routines, including their arguments and return values, may be found in the Fastgraph Reference Manual. FG_DEFCOLOR assigns a color value to a virtual color index. This routine is only meaningful in the graphics video modes that have fewer than 256 available colors. FG_GETCOLOR returns the current text attribute (in text modes) or color index (in graphics modes), as specified in the most recent call to fg_setattr or fg_setcolor. FG_GETINDEX returns the color value assigned to a specified virtual color index. In text modes and in graphics modes that have 256 available colors, this routine returns the value passed to it. FG_GETRGB returns the red, green, and blue color components for a specified video DAC register. This routine is only meaningful in VGA and MCGA graphics modes. FG_PALETTE has different functions depending on the current graphics video mode. For the CGA four-color modes, it establishes the current palette (of six available) and defines the background color for that palette. In the CGA two-color mode, it defines the foreground color. For the Tandy/PCjr, EGA, and VGA graphics modes, it defines the value of a single palette register. For the 256-color MCGA and VGA graphics modes, it defines the value of a single video DAC register. The fg_palette routine has no effect in text modes or Hercules graphics modes. FG_PALETTES defines all 16 palette registers (in Tandy/PCjr, EGA, and VGA graphics modes), or the first 16 video DAC registers (in 256-color MCGA and VGA graphics modes). The fg_palettes routine has no effect in text modes, CGA graphics modes, or Hercules graphics modes. FG_SETATTR establishes the current text attribute in text video modes. This routine has no effect in graphics modes. FG_SETCOLOR establishes the current color index (which may be a virtual color index in graphics modes). In text modes, the fg_setcolor routine provides an alternate method of establishing the current text attribute. FG_SETRGB defines the value of a single palette register (in Tandy/PCjr and EGA graphics modes) or video DAC register (in VGA and MCGA modes) by specifying its red, green, and blue color components. The fg_setrgb routine has no effect in text modes, CGA graphics modes, or Hercules graphics modes. 68 Fastgraph User's Guide Chapter 6 Graphics Fundamentals 70 Fastgraph User's Guide Overview This chapter describes Fastgraph's fundamental graphics routines, sometimes called graphics primitives. These routines perform such functions as clearing the screen, drawing points, drawing solid and dashed lines, drawing closed shapes (polygons, circles, and ellipses), drawing rectangles (solid and dithered), and filling arbitrary regions. Most of these routines have no effect in text video modes, but there are a few exceptions, and they will be noted in the descriptions of those routines. Clearing the Screen The Fastgraph routine fg_erase clears the entire screen in any video mode. In text modes, fg_erase clears the screen by storing a space character (ASCII 32) with a gray foreground attribute in each character cell. In graphics modes, fg_erase clears the screen by setting each pixel to zero. This of course causes each pixel to be displayed its background color. The fg_erase routine has no arguments. Clipping The suppression of graphics outside a pre-defined area is called clipping. Many of Fastgraph's graphics-oriented routines provide clipping, either automatically or through a special version of the routine. Fastgraph includes two routines, fg_setclip and fg_setclipw, to define a rectangular clipping region. The fg_setclip routine defines the clipping region in screen space, while the fg_setclipw routine performs the same function in world space. Each routine takes four arguments: the minimum x, the maximum x, the minimum y, and the maximum y coordinate of the clipping region. The arguments are integer quantities for fg_setclip and floating point quantities for fg_setclipw. For example, the statement fg_setclip(0,159,0,99); would define the upper left quadrant of the screen as the clipping region in a 320 by 200 graphics mode. An implicit clipping region equal to the entire screen is defined as part of the fg_setmode routine's initializations. Clipping is not supported for text modes. Points The Fastgraph routine fg_point provides the most fundamental graphics operation -- setting a pixel to a specified color. The fg_point routine has two integer arguments. The first specifies the pixel's x coordinate, and the second its y coordinate. The pixel is drawn using the current color value, as specified in the most recent call to fg_setcolor. There is also a world space version of this routine, fg_pointw, that uses floating point arguments. Another Fastgraph routine is available for reading a pixel's color value. The fg_getpixel routine has two integer arguments that specify the Chapter 6: Graphics Fundamentals 71 (x,y) coordinates for the pixel of interest. There is no world space version of the fg_getpixel routine, but you can obtain a pixel's color value in world space by applying the fg_xscreen and fg_yscreen functions to the world space coordinates and passing the resulting values to fg_getpixel. Example 6-1 uses the fg_point routine to draw 100 random points in random colors. It also uses the fg_getpixel routine to insure no two points are adjacent. The program establishes a graphics video mode with the fg_automode and fg_setmode routines. Next, it determines the maximum color value for the selected video mode; note if we used virtual colors (color indices above the maximum color value), some of the colors would be the background color and would thus produce invisible points. The main part of the program is a while loop that first generates a random pair of (x,y) screen coordinates. It then calls the fg_getpixel routine to check the pixels at (x,y) and the eight adjacent positions. If none of these pixels are set, the program generates a random color value and draws a point in that color. After doing this 100 times, the program waits for a keystroke, restores the original video mode and screen attributes, and then returns to DOS. Example 6-1. main() { int area; int color, old_color; int left; int max_color, max_x, max_y; int new_mode, old_mode; int x, y; old_mode = fg_getmode(); new_mode = fg_automode(); fg_setmode(new_mode); if (new_mode == 4) max_color = 3; else if (new_mode == 11 || new_mode == 17) max_color = 1; 72 Fastgraph User's Guide else if (new_mode == 19) max_color = 255; else max_color = 15; left = 100; max_x = fg_getmaxx() - 1; max_y = fg_getmaxy() - 1; while (left > 0) { x = random(1,max_x); y = random(1,max_y); area = fg_getpixel(x-1,y-1) + fg_getpixel(x,y-1) + fg_getpixel(x+1,y-1) + fg_getpixel(x-1,y) + fg_getpixel(x,y) + fg_getpixel(x+1,y) + fg_getpixel(x-1,y+1) + fg_getpixel(x,y+1) + fg_getpixel(x+1,y+1); if (area == 0) { color = random(1,max_color); fg_setcolor(color); fg_point(x,y); left--; } } fg_waitkey(); fg_setmode(old_mode); fg_reset(); } random(min,max) int min, max; { return((rand() % (max - min + 1)) + min); } Chapter 6: Graphics Fundamentals 73 The Graphics Cursor Many of Fastgraph's graphics routines depend on the position of the graphics cursor as a reference point. For example, Fastgraph includes routines to draw lines from the graphics cursor position to a specified position, and the image display routines discussed in chapter 9 display or retrieve an image relative to the graphics cursor position. The graphics cursor is not a cursor in the true sense; it is simply a pair of (x,y) coordinates with a special meaning. The fg_setmode routine sets the graphics cursor position to the screen space coordinates (0,0), and the fg_initw routine sets it to the world space coordinates (0.0,0.0). Fastgraph includes four routines for changing the graphics cursor position. The fg_move routine sets it to an absolute screen space position, while the fg_movew routine sets it to an absolute world space position. The fg_moverel routine sets the graphics cursor position to a screen space position relative to its current position. The fg_moverw routine does the same in world space. Each of these routines has two arguments that specify the (x,y) coordinates of the new position. For the screen space routines, the arguments are integer quantities. For the world space routines, the arguments are floating point quantities. You can obtain the screen space coordinates of the graphics cursor position with the fg_getxpos and fg_getypos routines. These routines have no arguments and respectively return the x and y coordinates of the graphics cursor position as the function value. To obtain the world space coordinates of the graphics cursor position, you can apply the fg_xworld and fg_yworld functions to the return values of fg_getxpos and fg_getypos. 74 Fastgraph User's Guide Solid Lines Fastgraph includes four routines for drawing solid lines. All four routines draw lines in the current color value (as determined by the most recent call to fg_setcolor) and observe the clipping limits. The fg_draw routine draws a line from the current graphics cursor position to an absolute screen space position, while the fg_draww routine draws a line to an absolute world space position. The fg_drawrel routine draws a line from the current graphics cursor position to a screen space position relative to it. The fg_drawrw routine does the same in world space. Each of these routines has two arguments that specify the (x,y) coordinates of the destination position. For the screen space routines, the arguments are integer quantities. For the world space routines, the arguments are floating point quantities. In either case the destination position becomes the new graphics cursor position. This makes it possible to draw connected lines without calling a graphics cursor movement routine between successive calls to a line drawing routine. Examples 6-2 and 6-3 each draw a pair of crossed lines that divide the screen into quadrants. Example 6-2 does this using the fg_move and fg_draw routines, while example 6-3 uses the fg_moverel and fg_drawrel routines. Both examples draw the lines in bright white, the default for color 15 in all graphics video modes. Example 6-2. Example 6-3. main() main() { { int max_x, max_y; int max_x, max_y; int mid_x, mid_y; int mid_x, mid_y; int new_mode, old_mode; int new_mode, old_mode; old_mode = fg_getmode(); old_mode = fg_getmode(); new_mode = fg_automode(); new_mode = fg_automode(); fg_setmode(new_mode); fg_setmode(new_mode); max_x = fg_getmaxx(); max_x = fg_getmaxx(); max_y = fg_getmaxy(); max_y = fg_getmaxy(); mid_x = max_x / 2; mid_x = max_x / 2; mid_y = max_y / 2; mid_y = max_y / 2; fg_setcolor(15); fg_setcolor(15); fg_move(mid_x,0); fg_move(mid_x,0); fg_draw(mid_x,max_y); fg_drawrel(0,max_y); fg_move(0,mid_y); fg_moverel(-mid_x,-mid_y); fg_draw(max_x,mid_y); fg_drawrel(max_x,0); fg_waitkey(); fg_waitkey(); fg_setmode(old_mode); fg_setmode(old_mode); fg_reset(); fg_reset(); } } Chapter 6: Graphics Fundamentals 75 Examples 6-4 and 6-5 are variations of example 6-2. Example 6-4 uses world space rather than screen space to draw the crossed lines. Example 6-5 is identical to example 6-2 except it defines a clipping area to restrict drawing to the upper left quadrant of the screen. The clipping suppresses the right half of the horizontal line and the lower half of the vertical line. Example 6-4. Example 6-5. main() main() { { int new_mode, old_mode; int max_x, max_y; int mid_x, mid_y; old_mode = fg_getmode(); int new_mode, old_mode; new_mode = fg_automode(); fg_setmode(new_mode); old_mode = fg_getmode(); fg_initw(); new_mode = fg_automode(); fg_setworld(-10.0,10.0,-10.0,10.0); fg_setmode(new_mode); fg_setcolor(15); max_x = fg_getmaxx(); fg_movew(0.0,10.0); max_y = fg_getmaxy(); fg_draww(0.0,-10.0); mid_x = max_x / 2; fg_movew(-10.0,0.0); mid_y = max_y / 2; fg_draww(10.0,0.0); fg_setclip(0,mid_x,0,mid_y); fg_waitkey(); fg_setcolor(15); fg_setmode(old_mode); fg_move(mid_x,0); fg_reset(); fg_draw(mid_x,max_y); } fg_move(0,mid_y); fg_draw(max_x,mid_y); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } 76 Fastgraph User's Guide Dashed Lines Fastgraph includes four routines for drawing dashed lines. All four routines draw lines in the current color value (as determined by the most recent call to fg_setcolor) and observe the clipping limits. The fg_dash routine draws a dashed line from the current graphics cursor position to an absolute screen space position, while the fg_dashw routine draws a dashed line to an absolute world space position. The fg_dashrel routine draws a dashed line from the current graphics cursor position to a screen space position relative to it. The fg_dashrw routine does the same in world space. Each of these routines has three arguments. The first two specify the (x,y) coordinates of the destination position. For the screen space routines, these arguments are integer quantities. For the world space routines, these arguments are floating point quantities. The third argument is a 16-bit pattern that defines the appearance of the dashed line. Bits that are set in the pattern produce the visible part of the line, while bits that are reset produce the invisible part. This pattern is repeated as necessary to draw the entire line. For example, the pattern value 3333 hex would produce a dashed line with the first two pixels off, the next two on, the next two off, and so forth. Similarly, the pattern value FFFF hex would produce a solid line. The destination position passed to any of the dashed line routines becomes the new graphics cursor position. This makes it possible to draw connected dashed lines without calling a graphics cursor movement routine between successive calls to a line drawing routine. Example 6-6 draws a pair of crossed dashed lines that divide the screen into quadrants. It does this using the fg_move and fg_dash routines and draws the lines in bright white, the default for color 15 in all graphics video modes. The dash pattern for each line is 3333 hex, which alternates two pixels off and on. Example 6-6. main() { int max_x, max_y; int mid_x, mid_y; int new_mode, old_mode; old_mode = fg_getmode(); Chapter 6: Graphics Fundamentals 77 new_mode = fg_automode(); fg_setmode(new_mode); max_x = fg_getmaxx(); max_y = fg_getmaxy(); mid_x = max_x / 2; mid_y = max_y / 2; fg_setcolor(15); fg_move(mid_x,0); fg_dash(mid_x,max_y,0x3333); fg_move(0,mid_y); fg_dash(max_x,mid_y,0x3333); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Polygons, Circles, and Ellipses Fastgraph includes routines for drawing three types of closed shapes: polygons, circles, and ellipses. Both screen space and world space versions of these routines are available. All of the routines for drawing closed shapes observe the clipping limits. The fg_polygon routine draws an unfilled polygon in screen space. Fg_polygon requires an array of integer x coordinates as its first argument, and an array of integer y coordinates as its second argument. Each (x,y) coordinate pair from the two arrays is treated as a polygon vertex. In other words, the x coordinate of the first polygon vertex is the first element of the x coordinate array, and the y coordinate of the first vertex is the first element of the y coordinate array. Similarly, the second elements of each array define the second vertex, and so forth. The third argument for fg_polygon is an integer quantity that specifies the number of elements in the two coordinate arrays. Another routine, fg_polygonw, draws an unfilled polygon in world space. The fg_polygonw routine is identical to the fg_polygon routine, except its x and y coordinate arrays must contain floating point values instead of integers. The drawing of the polygon begins at the graphics cursor position. The routine then draws a solid line in the current color to the first vertex, then to the second vertex, and continues in this manner up to the last vertex. If necessary, fg_polygon and fg_polygonw draw a line connecting the last vertex and the original graphics cursor position. This last operation closes the polygon and effectively leaves the graphics cursor position unchanged. Example 6-7 illustrates the use of the fg_polygon routine in the EGA monochrome or enhanced modes (mode 15 and 16). The program exits if neither of these video modes are available. 78 Fastgraph User's Guide Example 6-7. #define VERTICES 10 int x[] = {200,300,400,400,300,240,160,160,200,200}; int y[] = {100, 80,100,220,320,320,240,200,160,160}; main() { int old_mode; old_mode = fg_getmode(); if (fg_testmode(16,1)) fg_setmode(16); else if (fg_testmode(15,1)) fg_setmode(15); else { printf("This program requires a 640 x 350 "); printf("EGA graphics mode.\n"); exit(); } fg_setcolor(1); fg_polygon(x,y,VERTICES); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } The fg_circle routine draws an unfilled circle in screen space, centered at the graphics cursor position, using the current color. The routine's only argument specifies the circle's radius in horizontal screen space units. Another routine, fg_circlew, draws an unfilled circle where the radius is measured in horizontal world space units. Both routines leave the graphics cursor position unchanged. The fg_ellipse routine draws an unfilled ellipse in screen space, centered at the graphics cursor position, using the current color. The routine requires two arguments that respectively specify the length of its horizontal and vertical semi-axes. In other words, the first argument is the absolute distance from the center of the ellipse to its horizontal extremity, and the second argument is the absolute distance from the center of the ellipse to its vertical extremity. Another routine, fg_ellipsew, draws an unfilled ellipse in world space. Both routines leave the graphics cursor position unchanged. Example 6-8 illustrates the use of the fg_circlew and fg_ellipsew routines. The program first uses the fg_automode routine to propose a graphics video mode and then uses the fg_setmode routine to select that video mode. It then makes color 15 the current color, which by default is bright white in all color graphics modes and "on" in the monochrome graphics modes. Next, it establishes a 200-unit by 200-unit world space coordinate system. The program then uses fg_ellipsew to draw an ellipse and fg_circlew to draw a circle, both centered at the middle of the screen (which is the origin of our Chapter 6: Graphics Fundamentals 79 world space coordinate system). The circle has a radius of 1/16 the width of the screen (12.5 horizontal world space units), and the ellipse is horizontally inscribed within the circle. Example 6-9 illustrates the use of the fg_circle and fg_ellipse routines. It is functionally identical to the program of example 6-8, but it uses screen space rather than world space coordinates to draw the circle and ellipse. Note the arguments to the fg_circle and fg_ellipse routines are dependent on the maximum x and y coordinates of the selected video mode. If we didn't compute these arguments in this manner, the actual size of the circle and ellipse would be proportional to the pixel resolution of the video mode. No such dependency exists when using world space, but we pay a price for this feature in slightly slower execution speed. Example 6-8. Example 6-9. main() main() { { int old_mode; int mid_x, mid_y; int old_mode; old_mode = fg_getmode(); int x,y; fg_setmode(fg_automode()); fg_setcolor(15); old_mode = fg_getmode(); fg_setmode(fg_automode()); fg_initw(); fg_setcolor(15); fg_setworld(-100.0,100.0,-100.0,100.0); mid_x = fg_getmaxx() / 2; fg_movew(0.0,0.0); mid_y = fg_getmaxy() / 2; fg_ellipsew(12.5,12.5); x = mid_x / 8; fg_circlew(12.5); y = mid_y / 8; fg_waitkey(); fg_move(mid_x,mid_y); fg_ellipse(x,y); fg_setmode(old_mode); fg_circle(x); fg_reset(); } fg_waitkey(); fg_setmode(old_mode); fg_reset(); } 80 Fastgraph User's Guide Solid Rectangles Fastgraph includes four routines for drawing solid rectangles, two for screen space and two for world space, with and without clipping. None of these routines affect the graphics cursor position. The fg_rect routine draws a solid rectangle in screen space, without regard to the clipping limits, using the current color. Fg_rect requires four integer arguments that respectively define the minimum x, maximum x, minimum y, and maximum y screen space coordinates of the rectangle. The minimum coordinates must be less than or equal to the maximum coordinates, or else the results are unpredictable. The fg_clprect routine is identical in all respects to the fg_rect routine, except it observes the clipping limits. The world space versions of the solid rectangle drawing routines are fg_rectw and fg_clprectw. Like fg_rect and fg_clprect, they require four arguments that define the extremes of the rectangle, but the arguments are floating point world space coordinates. You can also use the fg_rect routine in text modes. When used in a text mode, fg_rect expects its four arguments to be expressed in character space (that is, rows and columns) rather than screen space. This means the four arguments respectively specify the minimum column, maximum column, minimum row, and maximum row of the rectangle. Fastgraph constructs the rectangle by storing the solid block character (ASCII decimal value 219) in each character cell comprising the rectangle. The rectangle is drawn using the current character attribute, but because the solid block character occupies the entire character cell, the background component of the attribute is essentially meaningless. Example 6-10 demonstrates the use of the fg_rect routine by drawing 200 random-size rectangles in random colors. The program first uses the fg_automode routine to propose a graphics video mode and then uses the fg_setmode routine to select that video mode. Next, it determines the horizontal and vertical screen resolution for the selected video mode, using the fg_getmaxx and fg_getmaxy routines. The main part of the program is a for loop that generates a random rectangle in each iteration. Inside the loop, the C library function rand is used to randomly generate the extremes of the rectangle. If necessary, the program then exchanges the coordinates to make the minimum coordinates less than or equal to the maximum coordinates. Finally, it again uses rand to generate a random color number between 0 and 15, and then draws the rectangle in that color. After drawing Chapter 6: Graphics Fundamentals 81 all 200 rectangles, the program restores the original video mode and screen attributes before returning to DOS. Example 6-10. #define RECTANGLES 200 #define SWAP(a,b,temp) { temp = a; a = b; b = temp; } main() { int i; int minx, maxx, miny, maxy; int old_mode; int temp; int xres, yres; old_mode = fg_getmode(); fg_setmode(fg_automode()); xres = fg_getmaxx() + 1; yres = fg_getmaxy() + 1; for (i = 0; i < RECTANGLES; i++) { minx = rand() % xres; maxx = rand() % xres; miny = rand() % yres; maxy = rand() % yres; if (minx > maxx) SWAP(minx,maxx,temp); if (miny > maxy) SWAP(miny,maxy,temp); fg_setcolor(rand()%16); fg_rect(minx,maxx,miny,maxy); } fg_setmode(old_mode); fg_reset(); } Dithered Rectangles The process of alternating different color pixels across a region of the display area is called dithering. This technique is especially useful in the graphics modes with few colors, such as CGA and Hercules modes, because you can simulate additional colors through effective uses of dithering. Fastgraph includes two routines for drawing dithered rectangles, one for screen space and one for world space. Neither routine observes the clipping limits, nor do they affect the graphics cursor position. The fg_drect routine draws a dithered rectangle in screen space. Like the fg_rect routine, fg_drect requires four integer arguments that respectively define the minimum x, maximum x, minimum y, and maximum y screen space coordinates of the rectangle. The minimum coordinates must be less than or equal to the maximum coordinates, or else the results are unpredictable. However, fg_drect also requires a fifth argument that defines 82 Fastgraph User's Guide the dithering matrix, which in turn determines the pixel pattern used to build the dithered rectangle. The size and format of the dithering matrix are dependent on the video mode. The world space version of the dithered rectangle drawing routine is fg_drectw. Like fg_drect, it requires four arguments that define the extremes of the rectangle, and a fifth argument that defines the dithering matrix. As mentioned earlier, the size and format of the dithering matrix are dependent on the video mode. The dithering matrix is a four byte array in all video modes except the 256 color graphics modes (modes 19, 20, and 21), where it is an eight byte array. This array contains a pixel pattern that fg_drect or fg_drectw replicates across the rectangle's area. The structure of the dithering matrix closely mimics the structure of video memory in each graphics mode. The remainder of this section will present some simple mode-specific examples to illustrate the structure of the dithering matrix in the different graphics modes. Suppose we would like to produce a "checkerboard" of light blue and bright white pixels. That is, in a given row of a rectangle, consecutive pixels will alternate between these two colors. Additionally, the pattern for adjacent rows will be shifted such that there will always be a bright white pixel above and below a light blue pixel, and vice versa. Hence this pixel pattern would look something like B W B W W B W B B W B W W B W B where each B represents a light blue pixel, and each W represents a bright white pixel. The following examples describe the dithering matrix that could be used to produce such a pixel pattern in each graphics mode. CGA Four-Color Graphics Modes The CGA four-color graphics modes (modes 4 and 5) use a four-byte dithering matrix that Fastgraph treats as a four-row by one-column array. Since each pixel in modes 4 and 5 requires two bits of video memory, each byte of the dithering matrix holds four pixels. Thus the pixel representation of the dithering matrix would appear as shown below on the left; its translation to numeric values appears on the right. [3] B W B W [3] 01 11 01 11 [2] W B W B [2] 11 01 11 01 [1] B W B W [1] 01 11 01 11 [0] W B W B [0] 11 01 11 01 Because modes 4 and 5 do not offer a light blue color, we've used light cyan (color value 1 in palette 1) to approximate light blue. The B pixels thus translate to color value 1, or 01 binary. Bright white is available as color Chapter 6: Graphics Fundamentals 83 value 3 in palette 1, so the W pixels translate to color value 3, or 11 binary. The hexadecimal equivalent of the binary value 11011101 (for array elements [0] and [2]) is DD, and the hexadecimal equivalent of the binary value 01110111 (for array elements [1] and [3]) is 77. As shown in example 6-11, these are precisely the values assigned to the elements of the dithering matrix. Example 6-11 uses mode 4 to display a 50-pixel by 50-pixel dithered rectangle in the upper left corner of the screen. The dithering matrix represents the blue and white checkerboard pattern discussed in the preceding paragraph. Example 6-11. main() { char matrix[4]; int old_mode; old_mode = fg_getmode(); fg_setmode(4); matrix[0] = matrix[2] = 0xDD; matrix[1] = matrix[3] = 0x77; fg_drect(0,49,0,49,matrix); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } CGA Two-Color Graphics Mode The CGA two-color graphics mode (mode 6) uses a four-byte dithering matrix that Fastgraph treats as a four-row by one-column array, as in the other four-color CGA modes. However, each pixel in mode 6 only requires one bit of video memory, so each byte of the dithering matrix holds eight pixels. Thus the pixel representation of the dithering matrix would appear as shown below on the left; its translation to numeric values appears on the right. [3] B W B W B W B W [3] 0 1 0 1 0 1 0 1 [2] W B W B W B W B [2] 1 0 1 0 1 0 1 0 [1] B W B W B W B W [1] 0 1 0 1 0 1 0 1 [0] W B W B W B W B [0] 1 0 1 0 1 0 1 0 Mode 6 obviously does not offer a light blue color, so we've used black (color value 0) in its place. The B pixels thus translate to color value 0. Bright white is available as color value 1, so the W pixels translate to color value 1. The hexadecimal equivalent of the binary value 10101010 (for array elements [0] and [2]) is AA, and the hexadecimal equivalent of the 84 Fastgraph User's Guide binary value 01010101 (for array elements [1] and [3]) is 55. Thus, to make example 6-11 run in mode 6, we only need to change the fg_setmode argument from 4 to 6 and change the dithering matrix values as shown below. matrix[0] = matrix[2] = 0xAA; matrix[1] = matrix[3] = 0x55; Tandy/PCjr 16-Color Graphics Mode The Tandy/PCjr 16-color graphics mode (mode 9) also uses a four-byte dithering matrix that Fastgraph treats as a four-row by one-column array. Each pixel in mode 9 requires four bits of video memory, so each byte of the dithering matrix only holds two pixels. Thus the pixel representation of the dithering matrix would appear as shown below on the left; its translation to numeric values appears on the right. [3] B W [3] 1001 1111 [2] W B [2] 1111 1001 [1] B W [1] 1001 1111 [0] W B [0] 1111 1001 The B pixels translate to color value 9 (light blue), or 1001 binary, and the W pixels translate to color value 15 (bright white), or 1111 binary. The hexadecimal equivalent of the binary value 11111001 (for array elements [0] and [2]) is F9, and the hexadecimal equivalent of the binary value 10011111 (for array elements [1] and [3]) is 9F. Thus, to make example 6-11 run in mode 9, we only need to change the fg_setmode argument from 4 to 9 and change the dithering matrix values as shown below. matrix[0] = matrix[2] = 0xF9; matrix[1] = matrix[3] = 0x9F; Hercules Graphics Mode The size and format of the dithering matrix in the Hercules graphics mode (mode 11) is identical to that of the CGA two-color mode (mode 6). Please refer to page 83 for a discussion of mode 6 dithering. Hercules Low-Resolution Graphics Mode The size and format of the dithering matrix in the Hercules low- resolution graphics mode (mode 12) is identical to that of the CGA four-color modes (modes 4 and 5). As far as our checkerboard example goes, we'll use black (color value 0) in place of light blue, and bold (color value 3) instead of bright white. Thus the B pixels translate to 00 binary, while the W pixels translate to 11 binary. The hexadecimal equivalent of the binary value 11001100 (for array elements [0] and [2]) is CC, and the hexadecimal equivalent of the binary value 00110011 (for array elements [1] and [3]) is Chapter 6: Graphics Fundamentals 85 33. Thus, to make example 6-11 run in mode 12, we only need to change the fg_setmode argument from 4 to 12 and change the dithering matrix values as shown below. matrix[0] = matrix[2] = 0xCC; matrix[1] = matrix[3] = 0x33; EGA and VGA Graphics Modes The native EGA and VGA graphics modes (modes 13 through 18) use a four- byte dithering matrix that Fastgraph treats as a four-row by one-column array. Unlike the other graphics modes, which allow you to store pixels of several colors in the dithering matrix, the EGA and VGA modes treat the dithering matrix as a bit map for a specific color. Since each color in the dither pattern must be stored in a separate bit map (that is, in a separate dithering matrix), it is necessary to call fg_drect once for each color. Furthermore, you must use the fg_setcolor routine before each call to fg_drect to define the color used with the dithering matrix. In all of the EGA and VGA graphics modes, each byte of the dithering matrix is a bit map that represents eight pixels. Using our familiar checkerboard example, the pixel representation of the dithering matrix would appear as shown below. [3] B W B W B W B W [2] W B W B W B W B [1] B W B W B W B W [0] W B W B W B W B Translating this pattern to numeric values is simple. Just construct one dithering matrix for each color in the pattern (there are two colors in this example), where pixels of the current color translate to 1, and other pixels translate to 0. Following our example, the translation for the B pixels appears below on the left, while the translation for the W pixels appears on the right. [3] 1 0 1 0 1 0 1 0 [3] 0 1 0 1 0 1 0 1 [2] 0 1 0 1 0 1 0 1 [2] 1 0 1 0 1 0 1 0 [1] 1 0 1 0 1 0 1 0 [1] 0 1 0 1 0 1 0 1 [0] 0 1 0 1 0 1 0 1 [0] 1 0 1 0 1 0 1 0 The hexadecimal equivalent of the binary value 01010101 is 55, and the hexadecimal equivalent of the binary value 10101010 is AA. As shown in example 6-12, these are precisely the values assigned to the elements of the dithering matrices. 86 Fastgraph User's Guide Example 6-12 uses mode 13 to display our light blue and bright white checkerboard pattern. Note it is necessary to call fg_drect twice -- once for the light blue pixels (color value 9), and again for the bright white pixels (color value 15). Note also how fg_setcolor is used before each call to fg_drect to define the color of the pixels fg_drect will display. Example 6-12. main() { char matrix[4]; int old_mode; old_mode = fg_getmode(); fg_setmode(13); matrix[0] = matrix[2] = 0x55; matrix[1] = matrix[3] = 0xAA; fg_setcolor(9); fg_drect(0,49,0,49,matrix); matrix[0] = matrix[2] = 0xAA; matrix[1] = matrix[3] = 0x55; fg_setcolor(15); fg_drect(0,49,0,49,matrix); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } MCGA and VGA 256-Color Graphics Modes The MCGA and VGA 256-color graphics modes (modes 19, 20, and 21) use an eight-byte dithering matrix that Fastgraph treats as a four-row by two-column array. Each pixel in modes 19, 20, and 21 requires eight bits of video memory, so each byte of the dithering matrix only holds a single pixel. We therefore need the two column dithering matrix to produce any type of dither pattern. The pixel representation of the dithering matrix would appear as shown below on the left; its translation to numeric values appears on the right. [6] B W [7] [6] 9 15 [7] [4] W B [5] [4] 15 9 [5] [2] B W [3] [2] 9 15 [3] [0] W B [1] [0] 15 9 [1] Chapter 6: Graphics Fundamentals 87 The B pixels translate to color value 9 (light blue), and the W pixels translate to color value 15 (bright white). Example 6-13 uses mode 19 to draw our light blue and bright white checkerboard pattern. Example 6-13. main() { char matrix[8]; int old_mode; old_mode = fg_getmode(); fg_setmode(19); matrix[0] = matrix[3] = matrix[4] = matrix[7] = 15; matrix[1] = matrix[2] = matrix[5] = matrix[6] = 9; fg_drect(0,49,0,49,matrix); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Closing Remarks There are two other important items pertaining to the fg_drect and fg_drectw routines. These items apply regardless of which graphics video mode is being used. First, the dithering matrix may not contain virtual color values. That is, the pixel color values stored in the dithering matrix must be between 0 and the maximum color value for the current video mode. If any color value is redefined using the fg_defcolor routine, Fastgraph always ignores the redefinition and instead uses the actual color value. Note this does not apply to palette registers or video DAC registers, because in these cases we are redefining the color associated with a color value and not the color value itself. Second, Fastgraph aligns the dithering matrix to specific pixel rows. Fastgraph draws the dithered rectangle starting with the pixel row specified by the rectangle's lower limit (the maximum y coordinate for fg_drect, or the minimum y coordinate for fg_drectw) and proceeds upward until reaching the rectangle's upper limit. In all cases the dithering matrix used by fg_drect and fg_drectw contains four rows. If we let r represent the pixel row corresponding to the rectangle's lower limit, then the first row used in the dithering matrix is r modulo 4 (assuming the dithering matrix rows are numbered 0 to 3). This alignment enables you to use the same dithering matrix in multiple calls to fg_drect and fg_drectw for building an object of adjacent dithered rectangles (for example, an L-shaped area) and still have the dither pattern match where the rectangles intersect. 88 Fastgraph User's Guide Region Fill Fastgraph includes routines for filling arbitrary regions. The fg_paint routine fills a region with the current color value by specifying a screen space point in the region's interior. The fg_paintw routine likewise fills a region, but it requires the interior point to be expressed in world space. Neither routine changes the graphics cursor position. Each of these routines has two arguments that specify the (x,y) coordinates of the interior point. For the fg_paint routine, the arguments are integer quantities. For the fg_paintw routine, they are floating point quantities. The region being filled must be a closed polygon whose boundary color is different from that of the specified interior point. The region may contain holes (interior areas that will not be filled). Fastgraph fills the region by changing every interior pixel whose color is the same as the specified interior point, to the current color. If the interior point is already the current color, the region fill routines do nothing. It is important to note the screen edges are not considered polygon boundaries, and filling an open polygon will cause the fg_paint and fg_paintw routines to behave unpredictably. Example 6-14 illustrates a simple use of the fg_paint routine in a 320 by 200 graphics mode. The program uses fg_bestmode to select an available video mode (if no 320 by 200 graphics mode is available, the program exits). After establishing the selected video mode, the program uses the fg_move and fg_drawrel routines to draw a hollow rectangle in color 10 and a hollow diamond in color 9. The diamond is drawn in the middle of the rectangle, thus making it a hole with respect to the rectangle. The program leaves these shapes on the screen until a key is pressed. At that time, it calls the fg_paint routine to fill that part of the rectangle outside the diamond with color 10. After waiting for another keystroke, the program again uses fg_paint to fill the interior of the diamond with color 15. Finally, the program waits for another keystroke, restores the original video mode and screen attributes, and returns to DOS. Example 6-14. main() { int old_mode, new_mode; new_mode = fg_bestmode(320,200,1); if (new_mode < 0) { printf("This program requires a 320 x 200 "); printf("graphics mode.\n"); exit(); } old_mode = fg_getmode(); fg_setmode(new_mode); fg_setcolor(10); fg_move(100,50); Chapter 6: Graphics Fundamentals 89 fg_drawrel(120,0); fg_drawrel(0,100); fg_drawrel(-120,0); fg_drawrel(0,-100); fg_setcolor(9); fg_move(160,80); fg_drawrel(30,20); fg_drawrel(-30,20); fg_drawrel(-30,-20); fg_drawrel(30,-20); fg_waitkey(); fg_setcolor(10); fg_paint(160,70); fg_waitkey(); fg_setcolor(15); fg_paint(160,100); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Summary of Fundamental Graphics Routines This section summarizes the functional descriptions of the Fastgraph routines presented in this chapter. More detailed information about these routines, including their arguments and return values, may be found in the Fastgraph Reference Manual. FG_CIRCLE draws an unfilled circle in screen space. The circle is centered at the graphics cursor position. FG_CIRCLEW draws an unfilled circle in world space. The circle is centered at the graphics cursor position. FG_CLPRECT draws a solid (filled) rectangle in screen space, with respect to the clipping region. FG_CLPRECTW draws a solid (filled) rectangle in world space, with respect to the clipping region. FG_DASH draws a dashed line from the graphics cursor position to an absolute screen space position. It also makes the destination position the new graphics cursor position. FG_DASHREL draws a dashed line from the graphics cursor position to a screen space position relative to it. It also makes the destination position the new graphics cursor position. FG_DASHRW draws a dashed line from the graphics cursor position to a world space position relative to it. It also makes the destination position the new graphics cursor position. 90 Fastgraph User's Guide FG_DASHW draws a dashed line from the graphics cursor position to an absolute world space position. It also makes the destination position the new graphics cursor position. FG_DRAW draws a solid line from the graphics cursor position to an absolute screen space position. It also makes the destination position the new graphics cursor position. FG_DRAWREL draws a solid line from the graphics cursor position to a screen space position relative to it. It also makes the destination position the new graphics cursor position. FG_DRAWRW draws a solid line from the graphics cursor position to a world space position relative to it. It also makes the destination position the new graphics cursor position. FG_DRAWW draws a solid line from the graphics cursor position to an absolute world space position. It also makes the destination position the new graphics cursor position. FG_DRECT draws a dithered rectangle in screen space, without regard to the clipping region. The rectangle's dither pattern is defined through a dithering matrix whose format is dependent on the video mode being used. FG_DRECTW draws a dithered rectangle in world space, without regard to the clipping region. The rectangle's dither pattern is defined through a dithering matrix whose format is dependent on the video mode being used. FG_ELLIPSE draws an unfilled ellipse in screen space. The ellipse is centered at the graphics cursor position, and its size is determined by the specified lengths of the semi-axes. FG_ELLIPSEW draws an unfilled ellipse in world space. The ellipse is centered at the graphics cursor position, and its size is determined by the specified lengths of the semi-axes. FG_ERASE clears the screen in either text or graphics modes. FG_GETPIXEL returns the color value of a specified pixel. FG_GETXPOS returns the screen space x coordinate of the graphics cursor position. FG_GETYPOS returns the screen space y coordinate of the graphics cursor position. FG_MOVE establishes the graphics cursor position at an absolute screen space point. FG_MOVEREL establishes the graphics cursor position at a screen space point relative to the current position. FG_MOVERW establishes the graphics cursor position at a world space point relative to the current position. FG_MOVEW establishes the graphics cursor position at an absolute world space point. Chapter 6: Graphics Fundamentals 91 FG_PAINT fills an arbitrary closed region with the current color value. The region is defined by specifying a screen space point within its interior. FG_PAINTW fills an arbitrary closed region with the current color value. The region is defined by specifying a world space point within its interior. FG_POINT draws a point (that is, displays a pixel) in screen space. FG_POINTW draws a point in world space. FG_POLYGON draws an unfilled polygon in screen space, using two coordinate arrays to define the polygon vertices. The drawing of the polygon begins at the graphics cursor position, through the vertices defined by the coordinate arrays, and finally back to the original cursor position if necessary. FG_POLYGONW draws an unfilled polygon in world space. It is identical to the fg_polygon routine, except the coordinate arrays contain world space values. FG_RECT draws a solid (filled) rectangle in screen space or character space, without regard to the clipping region. FG_RECTW draws a solid (filled) rectangle in world space, without regard to the clipping region. FG_SETCLIP defines the clipping region in screen space. The clipping region is a rectangular area outside of which graphics are suppressed. FG_SETCLIPW defines the clipping region in world space. 92 Fastgraph User's Guide Chapter 7 Character Display Routines 94 Fastgraph User's Guide Overview An important part of any program is the capability to display text or other characters on the screen. Fastgraph supports two character sets: the hardware or BIOS character set available with each video mode, and Fastgraph's own software character set for graphics video modes. Fastgraph/Light does not support the software character set. We'll begin this chapter with a review of character space, and then discuss the specifics about hardware and software characters. At the end of the chapter, we'll briefly explain how to implement bit-mapped characters into a program. To simplify things, the example programs presented in this chapter are mode-specific examples, and no testing is done to check if the video mode is available on the user's system. Character Space The coordinate system used for displaying hardware characters is called character space. It is the only coordinate system available in text video modes, but it is a supplementary coordinate system you can use with either screen space or world space in graphics video modes. Character space can be thought of as a grid of rows and columns, with each cell in the grid holding one character. Each cell is identified by its unique (row,column) integer coordinates. The rows and columns are numbered starting at zero; the origin is always the upper left corner of the screen. For example, in the 80-column by 25-row video modes, the (row,column) coordinates of the screen corners are shown in the following diagram. (0,0) (0,79) (24,0) (24,79) The number of rows and columns depends on the video mode, as shown in the following table. For graphics modes, the table also includes the width and height in pixels of a character cell. Chapter 7: Character Display Routines 95 Mode No. of No. of Char. Char. Number Columns Rows Width Height 0 40 25 1 40 25 2 80 25 3 80 25 4 40 25 8 8 5 40 25 8 8 6 80 25 8 8 7 80 25 9 40 25 8 8 11 80 25 9 14 12 40 25 8 8 13 40 25 8 8 14 80 25 8 8 15 80 25 8 14 16 80 25 8 14 17 80 30 8 16 18 80 30 8 16 19 40 25 8 8 20 40 25 8 8 21 40 50 8 8 Hardware Characters Hardware characters are available in all of Fastgraph's supported video modes. As explained in chapter 5, text mode characters have a display attribute that defines their foreground color, their background color, and whether or not they blink. Graphics mode characters appear in a single color, as determined by the current color index. Chapter 5 also explained how Fastgraph's fg_setattr and fg_setcolor routines define the attribute or color index in which subsequent hardware characters appear. It is obviously important to define the color or attribute for hardware characters, but it is equally important to define their location on the screen. Fastgraph draws hardware characters at the position defined by the text cursor. Like the graphics cursor, the text cursor is not a cursor in the true sense, but is simply a pair of character space (row,column) coordinates with a special meaning. The fg_setmode routine sets the text cursor position to the character space coordinates (0,0), which of course is the upper left corner of the screen.1 The Fastgraph routine fg_locate changes the text cursor position. It has two integer arguments that specify the (row,column) character space coordinates of the new position. The row values must be between 0 and 24, except in the 30-row VGA graphics modes (modes 17 and 18) where they must be between 0 and 29. The column values must be between 0 and 39 for 40-column video modes, or between 0 and 79 for 80-column modes. ____________________ 1 In reality there are 16 text cursors, one for each video page. The setmode routine initializes each text cursor position to (0,0). The next chapter describes this in more detail. 96 Fastgraph User's Guide The fg_text routine is Fastgraph's fundamental character display routine. It displays a string of hardware characters, starting at the text cursor position, using the current color attribute (for text modes) or color index (for graphics modes). If the string reaches the last column in a row, fg_text will wrap the string to the first column of the next row. Additionally, fg_text leaves the cursor one column to the right of the last character displayed (or the first column of the next row if the last character appears at the end of a row). This feature makes it possible for successive calls to fg_text to display adjacent strings. The first argument for the fg_text routine is a character string of arbitrary length, and the second argument is an integer value that specifies the number of characters to display from that string. Example 7-1 illustrates the use of the fg_locate and fg_text routines in the 80 by 25 color text mode (mode 3). After establishing the video mode and making the BIOS cursor invisible, the program displays four strings with different attributes. The attributes are selected using the fg_setattr routine, and the strings are displayed by the fg_text routine. The first string appears in yellow (attributes 14,0,0) in the upper left corner of the screen; the fg_locate routine is not necessary because (0,0) is the default text cursor position established by fg_setmode. The second string appears in light green (10,0,0) one space to the right of the first string. Its position relies on the fact fg_text sets the new text cursor position one space to the right of the last character displayed (following the "w" of "yellow" in this case). The leading space in " green" leaves a space between the first and second strings. Similarly, the third string appears in blinking light red (12,0,1) one space to the right of the second string. The program then uses the fg_locate routine to move the text cursor to the lower left corner of the screen and displays the "Press any key" string. This string is displayed with a light red foreground against a gray background (12,7,0). The extra spaces surrounding the string extend the background color one character position to the left and right and make the string more visually appealing. Finally, once you press any key, the program restores the original video mode and screen attributes before returning to DOS. Example 7-1. main() { int old_mode; old_mode = fg_getmode(); fg_setmode(3); fg_cursor(0); fg_setattr(14,0,0); fg_text("yellow",6); fg_setattr(10,0,0); fg_text(" green",6); fg_setattr(12,0,1); fg_text(" blinking",9); Chapter 7: Character Display Routines 97 fg_setattr(12,7,0); fg_locate(24,0); fg_text(" Press any key. ",16); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } The fg_where routine retrieves the text cursor position in its two integer arguments. This routine is not used as frequently as the fg_locate and fg_text routines because more often than not your program will know the text cursor position implicitly, or you'll know in advance the locations at which text will be displayed. The fg_where routine takes two integer arguments passed as pointers (that is, by reference), and these two arguments respectively receive the text cursor's current row and column position. Example 7-2 produces the same results as example 7-1, but it does so a bit differently. It uses its own routine, put_string, to display a string at a specified row and column. The put_string routine simply calls fg_locate to establish the text cursor position and then calls fg_text to display the string. Note the use of the C library function strlen to determine the string length passed to the fg_text routine. Example 7-2 also uses the fg_where routine to retrieve the new text cursor positions, which are then passed to the put_string routine. Example 7-2. main() { int old_mode; int row, column; old_mode = fg_getmode(); fg_setmode(3); fg_cursor(0); fg_setattr(14,0,0); put_string("yellow",0,0); fg_setattr(10,0,0); fg_where(&row,&column); put_string("green",row,column+1); fg_setattr(12,0,1); fg_where(&row,&column); put_string("blinking",row,column+1); fg_setattr(12,7,0); put_string(" Press any key. ",24,0); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } 98 Fastgraph User's Guide put_string(string,row,column) char *string; int row, column; { fg_locate(row,column); fg_text(string,strlen(string)); return(0); } Sometimes you may wish to change the display attribute of existing text, such as when creating a shadow around the edges of a pop-up window. The Fastgraph routine fg_chgattr performs this function. It applies the current text display attribute (as defined in the most recent call to fg_setattr or fg_setcolor) to a given number of characters, starting at the text cursor position. It leaves the text cursor one column to the right of the last character changed (or the first column of the next row if the last character is at the end of a row). The fg_chgattr routine's argument specifies the number of characters to change. This routine has no effect in graphics video modes. The Fastgraph routine fg_chgtext performs somewhat the opposite function of fg_chgattr. It displays new text but uses the display attributes already assigned to the character cells where the text will appear. The fg_chgtext routine takes the same two arguments as the fg_text routine, displays the characters starting at the text cursor position, and leaves the cursor one column to the right of the last character displayed. Like fg_chgattr, fg_chgtext has no effect in graphics video modes. Example 7-3 illustrates the fg_chgattr and fg_chgtext routines. It runs in the 80-column color text mode (mode 3), but if we change the fg_setmode argument it would also run in the monochrome text mode (mode 7). The program first displays the word "hello" in the upper left corner of the screen, using a gray foreground and black background attribute. After waiting for a keystroke, the program calls fg_chgattr to make the word "hello" appear in reverse video (that is, a black foreground and gray background attribute). After a second keystroke, the program uses fg_chgtext to change the "h" of "hello" to upper case. Following this, the program returns to DOS. Example 7-3. main() { int old_mode; old_mode = fg_getmode(); fg_setmode(3); fg_cursor(0); fg_setattr(7,0,0); fg_text("hello",5); fg_waitkey(); fg_locate(0,0); fg_setattr(0,7,0); fg_chgattr(5); fg_waitkey(); Chapter 7: Character Display Routines 99 fg_locate(0,0); fg_chgtext("H",1); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Displaying hardware characters in graphics video modes is quite different than doing so in text modes, although we use the same Fastgraph routines in both cases. Example 7-4 is similar to example 7-1, but it runs in the EGA enhanced graphics mode (mode 16) instead of a text mode. In graphics modes, the fg_cursor routine has no effect, so we have omitted it from the program. Furthermore, characters cannot be displayed with a blinking attribute, so we have likewise omitted the blinking characters (we could simulate blinking by repetitively displaying and erasing them, but that is beyond the scope of this example). Because graphics mode characters only have a foreground color, we had to simulate the gray background of the "Press any key" string by first drawing a rectangle where that string appears. The differences between examples 7-4 and 7-1 hold for any graphics video mode, not just mode 16. Example 7-4. main() { int old_mode; old_mode = fg_getmode(); fg_setmode(16); fg_setcolor(14); fg_text("yellow",6); fg_setcolor(10); fg_text(" green",6); fg_setcolor(7); fg_rect(0,127,336,349); fg_setcolor(12); fg_locate(24,0); fg_text(" Press any key. ",16); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Example 7-5 demonstrates a side effect that occurs when displaying characters in graphics modes. This example uses the MCGA graphics mode (mode 19) and displays two character strings at the same location. If we were to do this in a text mode, the first string would disappear once we displayed the second string. In graphics modes, however, the portions of the first string not covered by characters from the second string are still visible. The reason for this may not be apparent at first, but remember when we 100 Fastgraph User's Guide display characters in graphics modes, we aren't really displaying characters but merely a pixel representation of the characters. Fastgraph has no way to distinguish such pixels from any other pixels. Example 7-5. main() { int old_mode; old_mode = fg_getmode(); fg_setmode(19); fg_setcolor(14); fg_text("yellow",6); fg_locate(0,0); fg_setcolor(10); fg_text(" green",6); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } To avoid this problem, the recommended procedure for displaying characters in graphics modes is to first erase the area where the text will appear. The easiest way to do this is to use the fg_rect routine to draw a rectangle in the background color. In example 7-5, we could do this by inserting the statements fg_setcolor(0); fg_rect(0,47,0,7); immediately before the call to fg_locate. The parameters passed to the fg_rect routine represent the 48 by 8 pixel region that corresponds to the first six character cells of row 0 in the 320 by 200 graphics modes. Conversion Routines We have already mentioned Fastgraph includes routines for converting coordinates between character space and screen space (see page 41). In this section, we will review these routines and then present an example that uses some of them. The fg_xalpha and fg_yalpha routines convert screen space coordinates to character space. The fg_xalpha routine converts a screen space x coordinate to the character space column that contains the coordinate. Similarly, the fg_yalpha routine converts a screen space y coordinate to the character space row that contains the coordinate. The fg_xconvert and fg_yconvert routines convert character space coordinates to screen space. The fg_xconvert routine converts a character space column to the screen space coordinate of its leftmost pixel. Chapter 7: Character Display Routines 101 Similarly, the fg_yconvert routine converts a character space row to the screen space coordinate of its top (lowest-numbered) pixel. On page 99, example 7-4 demonstrated how to display characters in a graphics mode. Because characters do not have a background color in graphics modes, example 7-4 used the fg_rect routine to simulate a background color by drawing a gray rectangle before displaying the text. It was necessary to determine the screen coordinates of the character cells so we could pass the correct parameters to fg_rect. By using the fg_xconvert and fg_yconvert routines, we can let Fastgraph calculate the required screen coordinates. This method has the additional benefit of working in any graphics mode, whereas the coordinates passed to fg_rect in example 7-4 would only work properly in a 640 by 350 graphics mode. Example 7-6 shows how we could extend example 7-4 to use the fg_xconvert and fg_yconvert routines. Example 7-6. main() { int old_mode; int minx, maxx, miny, maxy; fg_old_mode = fg_getmode(); fg_setmode(16); fg_setcolor(14); fg_text("yellow",6); fg_setcolor(10); fg_text(" green",6); fg_setcolor(7); minx = fg_xconvert(0); maxx = fg_xconvert(16) - 1; miny = fg_yconvert(24); maxy = fg_yconvert(25) - 1; fg_rect(minx,maxx,miny,maxy); fg_setcolor(12); fg_locate(24,0); fg_text(" Press any key. ",16); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Software Characters Software characters, also called stroke characters or vector characters in other literature, are only are available in graphics video modes. Unlike the fixed-size hardware characters, you can display software characters in any size, at any angle, and at any position. In addition, software characters are proportionally spaced. However, software characters take considerably longer to draw than do hardware characters. 102 Fastgraph User's Guide Fastgraph includes two software character fonts, called the primary font and the alternate font. The primary font contains upper and lower case letters, numbers, punctuation, and most of the other printable ASCII characters. The alternate font contains upper and lower case Greek letters and other mathematical and scientific symbols. The Fastgraph routine fg_swchar displays a string of software characters in the current color index (as defined by the most recent call to fg_setcolor). The string may contain any characters from the primary font, the alternate font, or both. You can display the characters left justified, centered, or right justified relative to the graphics cursor position. Just as the fg_text routine updates the text cursor position, fg_swchar sets the graphics cursor position just to the right of the last character drawn. The characters are clipped according to the current clipping region. In addition to the characters, the string passed to fg_swchar may also contain operators for switching fonts, underlining, subscripting, or superscripting characters. Because fg_swchar internally uses world space coordinates, you must call the fg_initw routine at some point in your program before the first call to fg_swchar. You must also establish a world space coordinate system with the fg_setworld routine. The fg_swchar routine has three arguments. The first argument is the character string to display. The second argument is an integer value that specifies the number of characters in the string, including any characters used as special operators. The third argument is an integer value that determines the position of the string relative to the graphics cursor position. If this value is negative, the lower left corner of the first character will be at the graphics cursor position. If it is positive, the lower right corner of the last character will be at the graphics cursor position. If it is zero, the string will be horizontally centered at the graphics cursor position. The size of software characters is determined by the values passed to the fg_setsize, fg_setsizew, and fg_setratio routines. The fg_setsize routine has a single integer argument that defines the height of software characters in screen space units, while the fg_setsizew routine has a single floating point argument that defines the height in world space units. If neither of these routines is called, Fastgraph will use its default character height of one world space unit. The fg_setratio routine has a single floating point argument that defines the aspect ratio for software characters. The aspect ratio is the ratio of character width to character height. For example, an aspect ratio of 2.0 means characters are twice as wide as they are high. If the fg_setratio routine is not called, Fastgraph uses its default aspect ratio of 1. Example 7-7 displays both of the software character fonts. The program uses the enhanced EGA graphics mode (mode 16), but it could run in any graphics mode by changing the fg_setmode argument. After establishing the video mode, the program calls the fg_initw routine to initialize Fastgraph's world space parameters; this is required since the software character drawing routines internally use world space coordinates. The next statement is a call to fg_setworld that establishes a world space coordinate system with 0.01 world space units per pixel. Following this is a call to fg_setsizew that defines the character height as 0.21 world space units, or 21 pixels. Note we could have instead used the fg_setsize routine here with an integer argument of 21. Chapter 7: Character Display Routines 103 The next part of the program draws the characters in the primary font on the upper half of the screen. After doing this, the program draws the alternate font characters on the lower half. In each case it does this with the fg_swchar routine. By default, the string passed to fg_swchar will produce characters from the primary font. However, you can insert a back slash character (\) in the string to toggle between the two fonts. Don't forget the C language applies a special meaning to the back slash character within strings, so you must use two consecutive back slashes to insert a single back slash in the string. Example 7-7. main() { int old_mode; old_mode = fg_getmode(); fg_setmode(16); fg_initw(); fg_setworld(0.0,6.39,0.0,3.49); fg_setsizew(0.21); fg_setcolor(15); fg_locate(0,26); fg_text("Software characters - font 1",28); fg_setcolor(10); fg_movew(0.0,3.1); fg_swchar("ABCDEFGHIJKLMNOPQRSTUVWXYZ",26,-1); fg_movew(0.0,2.8); fg_swchar("abcdefghijklmnopqrstuvwxyz",26,-1); fg_movew(0.0,2.5); fg_swchar("0123456789",10,-1); fg_movew(0.0,2.2); fg_swchar("!\"#$%&'()*+,-./:;<=>?[]^`{|}~",29,-1); fg_setcolor(15); fg_locate(12,26); fg_text("Software characters - font 2",28); fg_setcolor(10); fg_movew(0.0,1.4); fg_swchar("\\ABCDEFGHIJKLMNOPRSTUWXYZ",25,-1); fg_movew(0.0,1.1); fg_swchar("\\abcdefghijklmnoprstuwxyz",25,-1); fg_movew(0.0,0.4); fg_swchar("\\012345678#$%&()*+/<=>?[]{}",27,-1); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Example 7-7 displays all characters in each font. If you compare the primary font strings with the alternate font strings, you'll see the 104 Fastgraph User's Guide alternate font contains fewer characters. For example, the letters Q and V (either upper or lower case) have no corresponding character in the alternate font. You might have also noticed the primary font does not support the full printable ASCII character set. Any character in a string passed to the fg_swchar routine that does not have a corresponding character in the current font will display a blank character. In addition to the font selection operator (the back slash character), fg_swchar recognizes three other operators. The superscript operator is a back slash followed by a caret (\^). It causes the next character to appear as a superscript. Similarly, the subscript operator is a back slash followed by a lower case v (\v); it causes the next character to appear as a subscript. The size of superscripted and subscripted characters is one half the height of the other characters. The underline operator is the underscore character (_). It causes all subsequent characters in the string to be underlined until another underscore character is found, or until the end of the string. When using these operators, be sure to include them as part of the string length count passed to fg_swchar. Example 7-8 illustrates the use of the font selection, superscript, subscript, and underline operators with the fg_swchar routine. Again, because the back slash character has a special meaning to the C programming language, we must use two consecutive back slashes to represent a single back slash within the string. The program displays four strings: cosýo + sinýo = 1 H2O U232 One word is underlined. The theta symbol (o) in the first string is produced by displaying the character "h" in the alternate font. Note another font selection operator (\) appears immediately after the "h" to revert to the primary font. The first string also includes superscript operators (\^) to display the exponents in the equation. The second string includes a single subscripted character, while the third string shows how to display three consecutive subscripted characters. Finally, the fourth string illustrates how to underline characters. Note example 7-8 also uses the fg_setratio routine. The first three strings are drawn with an aspect ratio of 2, making them twice as wide as they are high. The fourth string is drawn with an aspect ratio of 1 (Fastgraph's default aspect ratio for software characters), so the character height is the same as the character width. Also, the strings are centered instead of left justified as in the previous example. Example 7-8. main() { int old_mode; old_mode = fg_getmode(); fg_setmode(16); fg_setcolor(10); fg_initw(); Chapter 7: Character Display Routines 105 fg_setworld(0.0,6.39,0.0,3.49); fg_setratio(2.0); fg_setsizew(0.21); fg_movew(3.2,3.0); fg_swchar("cos\\^2\\h\\ + sin\\^2\\h\\ = 1",25,0); fg_movew(3.2,2.0); fg_swchar("H\\v2O U\\v2\\v3\\v2",18,0); fg_movew(3.2,1.0); fg_setratio(1.0); fg_swchar("One _word_ is underlined.",25,0); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } The fg_setangle routine defines the angle or orientation at which software characters are displayed. Its only argument is a floating point value that specifies the angle, measured in degrees counterclockwise from the positive x axis. If a program draws software characters before calling fg_setangle, Fastgraph will use its default angle of zero degrees (that is, the characters will be oriented horizontally). In most programs, the alternate font is not needed. However, if you use the fg_swchar routine, Fastgraph will include the definitions of these characters in your program's data segment. To prevent wasting this space, Fastgraph includes the fg_swtext routine. The fg_swtext routine is identical in all respects to the fg_swchar routine, except it does not include the alternate font. Since the font selection operator does not apply when using fg_swtext, the routine simply ignores it. You should only use fg_swtext if do not use fg_swchar. If you use both routines, your program will still work correctly, but its data segment will contain a duplicate copy of the primary font definitions. Example 7-9 demonstrates the use of the fg_setangle and fg_swtext routines. The program draws a series of strings of the form "nnn degrees", where nnn is a multiple of 15, radiating from the screen center. Each string appears at the specified angle. For example, the string "15 degrees" is drawn at an angle of 15 degrees. Example 7-9. main() { char string[24]; int angle; int old_mode; old_mode = fg_getmode(); fg_setmode(16); fg_setcolor(10); fg_initw(); 106 Fastgraph User's Guide fg_setworld(0.0,6.39,0.0,3.49); fg_setsizew(0.21); for (angle = 0; angle < 360; angle += 15) { fg_movew(3.2,1.75); fg_setangle((double)angle); sprintf(string," %3d degrees",angle); fg_swtext(string,16,-1); } fg_waitkey(); fg_setmode(old_mode); fg_reset(); } The final routine pertaining to software characters is fg_swlength, which returns the length of a specified string of software characters in world space units. The length is returned as the routine's floating point function value. The fg_swlength routine has two arguments -- a string of software characters, and an integer value specifying the number of characters in the string. As with fg_swchar and fg_swtext, the count includes any of the special operator characters. Example 7-10 demonstrates a typical use of the fg_swlength routine. The program displays the string "hello there." in light green against a gray background in the middle of the screen. As in our previous software character examples, the program uses mode 16 and first performs the necessary initializations to use software characters. Following this, the program uses the fg_swlength routine to compute the length in world space units of the string. Note we have added blank characters to each end of the string passed to fg_swlength; this increases the length of the actual string and will effectively give the gray rectangle an extended border on its left and right sides. The string length returned by fg_swlength is multiplied by 0.5, giving the distance from the middle of the screen to either side of the rectangle. The program then uses this value to compute the minimum and maximum x coordinates passed to fg_rectw. After drawing the gray rectangle, the program uses fg_swtext to draw the string of software characters in the middle of the screen. It then waits for a keystroke before restoring the original video mode and screen attributes and returning to DOS. Example 7-10. main() { int old_mode; double half; double fg_swlength(); old_mode = fg_getmode(); fg_setmode(16); fg_initw(); fg_setworld(0.0,6.39,0.0,3.49); fg_setsizew(0.21); fg_setcolor(7); Chapter 7: Character Display Routines 107 half = fg_swlength(" Hello there. ",14) * 0.5; fg_rectw(3.2-half,3.2+half,1.6,1.9); fg_setcolor(10); fg_movew(3.2,1.65); fg_swtext("Hello there.",12,0); fg_waitkey(); fg_setmode(old_mode); fg_reset(); } Bit-Mapped Characters Bit-mapped characters combine the properties of hardware and software characters. They are a fixed size, as hardware characters are, but they can be positioned anywhere instead of just in character cells. Because they are not scalable, they do not require floating point arithmetic, and therefore they are much faster to display than software characters. Fastgraph makes no special provision for bit-mapped characters because it treats them as if they were any other bit-mapped image. For example, to use a five-pixel by five-pixel bit-mapped font, you can construct characters as shown below and then store these representations in an image array. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * The image display routines fg_drawmap and fg_drwimage, discussed in chapter 9, could then be used to display specific characters from the image array. Summary of Character Display Routines This section summarizes the functional descriptions of the Fastgraph routines presented in this chapter. More detailed information about these routines, including their arguments and return values, may be found in the Fastgraph Reference Manual. FG_CHGATTR applies the current text display attribute to a given number of characters, starting at the text cursor position. This routine leaves the text cursor one column to the right of the last character changed (or the first column of the next row if the last character is at the end of a row). It has no effect in graphics video modes. FG_CHGTEXT displays a string of hardware characters, starting at the text cursor position, using the existing text display attributes. This routine leaves the text cursor one column to the right of the last character displayed (or the first column of the next row if the last character is at the end of a row). It has no effect in graphics video modes. 108 Fastgraph User's Guide FG_LOCATE changes the text cursor position for the active video page.' FG_SETANGLE defines the angle or orientation at which software characters are displayed. The angle is measured in degrees counterclockwise from the positive x axis. FG_SETATTR establishes the current text display attribute in text video modes. This routine has no effect in graphics video modes. FG_SETCOLOR establishes the current color index (which may be a virtual color index in graphics modes). In text modes, the fg_setcolor routine provides an alternate method of establishing the current text display attribute. FG_SETRATIO defines the aspect ratio for software characters. The aspect ratio is the ratio of character width to character height. FG_SETSIZE defines the height of software characters in screen space units. FG_SETSIZEW defines the height of software characters in world space units. FG_SWCHAR displays a string of software characters using the current color index. The string may be left justified, centered, or right justified relative to the graphics cursor position. The string passed to fg_swchar may contain special operators that allow switching between fonts, underlining, superscripting, or subscripting. This routine has no effect in text video modes. FG_SWLENGTH returns the length in world space units of a string of software characters. FG_SWTEXT is a scaled down version of the fg_swchar routine. It does not include the alternate font character definitions and thus requires less memory than fg_swchar. FG_TEXT displays a string of hardware characters, starting at the text cursor position, using the current color attribute (for text modes) or color index (for graphics modes). This routine leaves the text cursor one column to the right of the last character displayed (or the first column of the next row if the last character is at the end of a row). FG_WHERE retrieves the row and column numbers of the text cursor position. FG_XALPHA and FG_YALPHA convert screen space coordinates to character space. FG_XCONVERT and FG_YCONVERT convert character space coordinates to screen space.