roo_e/thirdparty/grx249/doc/tex/grx2_0.tex
2022-05-16 17:59:47 -05:00

2516 lines
96 KiB
TeX
Raw Blame History

@ifnottex
@node Top, A User Manual For GRX2, ,
@comment node-name, next,previous, up
@center @majorheading GRX 2.4.9 User's Manual
@center @chapheading A 2D graphics library for DOS, Linux, X11 and Win32
@end ifnottex
@center Based on the original doc written by: Csaba Biegl on August 10, 1992
@center Updated by: Mariano Alvarez Fernandez on August 17, 2000
@center Last update: July 10, 2012
@unnumbered Abstract
@strong{GRX} is a 2D graphics library originaly written by
Csaba Biegl for DJ Delorie's DOS port of the GCC compiler. Now it support
a big range of platforms, the main four are: DOS (DJGPPv2), Linux console,
X11 and Win32 (Mingw). On DOS it supports VGA, EGA and VESA compliant cards.
On Linux console it uses svgalib or the framebuffer. On X11 it must work on
any X11R5 (or later). From the 2.4 version, GRX comes with a Win32 driver.
The framebuffer Linux console driver was new in 2.4.2. From 2.4.7 there is a
support for x86_64 bits Linux machines and a support for an SDL driver
on MingW and X11. On MingW and X11 it runs on a window with the original
driver, and either full screen or on a window with the SDL driver.
@menu
* A User Manual For GRX2::
@end menu
@c -----------------------------------------------------------------------------
@node A User Manual For GRX2, Hello world, Top, Top
@unnumbered GRX2 User's Manual
@menu
* Top::
* Hello world::
* Data types and function declarations::
* Setting the graphics driver::
* Setting video modes::
* Graphics contexts::
* Context use::
* Color management::
* Portable use of a few colors::
* Graphics primitives::
* Non-clipping graphics primitives::
* Customized line drawing::
* Pattern filled graphics primitives::
* Patterned line drawing::
* Image manipulation::
* Text drawing::
* Drawing in user coordinates::
* Graphics cursors::
* Keyboard input::
* Mouse event handling::
* Writing/reading PNM graphics files::
* Writing/reading PNG graphics files::
* Writing/reading JPEG graphics files::
* Miscellaneous functions::
* BGI interface::
* Pascal interface::
* References::
@end menu
@c -----------------------------------------------------------------------------
@node Hello world, Data types and function declarations, A User Manual For GRX2, A User Manual For GRX2
@unnumberedsec Hello world
The next program draws a double frame around the screen and writes "Hello, GRX
world" centered. Then it waits after a key is pressed.
@example
#include <string.h>
#include <grx20.h>
#include <grxkeys.h>
int main()
@{
char *message = "Hello, GRX world";
int x, y;
GrTextOption grt;
GrSetMode( GR_default_graphics );
grt.txo_font = &GrDefaultFont;
grt.txo_fgcolor.v = GrWhite();
grt.txo_bgcolor.v = GrBlack();
grt.txo_direct = GR_TEXT_RIGHT;
grt.txo_xalign = GR_ALIGN_CENTER;
grt.txo_yalign = GR_ALIGN_CENTER;
grt.txo_chrtype = GR_BYTE_TEXT;
GrBox( 0,0,GrMaxX(),GrMaxY(),GrWhite() );
GrBox( 4,4,GrMaxX()-4,GrMaxY()-4,GrWhite() );
x = GrMaxX()/2;
y = GrMaxY()/2;
GrDrawString( message,strlen( message ),x,y,&grt );
GrKeyRead();
return 0;
@}
@end example
How to compile the hello world (assuming the GRX library was
previously installed)
@example
DJGPP: gcc -o hellogrx.exe hellogrx.c -lgrx20
Mingw: gcc -o hellogrx.exe hellogrx.c -lgrx20 -mwindows
X11 : gcc -o hellogrx hellogrx.c -D__XWIN__ -I/usr/X11R6/include
-lgrx20X -L/usr/X11R6/lib -lX11
Linux: gcc -o hellogrx hellogrx.c -lgrx20 -lvga
For the SDL driver:
Mingw: gcc -o hellogrx.exe hellogrx.c -lgrx20S -lSDL
X11 : gcc -o hellogrx hellogrx.c -D__XWIN__ -I/usr/X11R6/include
-lgrx20S -lSDL -lpthread -L/usr/X11R6/lib -lX11
For x86_64 systems add -m32 or -m64 for 32/64 bits executables
and replace /lib by /lib64 or /lib32 as needed
@end example
@c -----------------------------------------------------------------------------
@node Data types and function declarations, Setting the graphics driver, Hello world, A User Manual For GRX2
@unnumberedsec Data types and function declarations
All public data structures and graphics primitives meant for usage by the
application program are declared/prototyped in the header files (in the
'include' sub-directory):
@example
* grdriver.h graphics driver format specifications
* grfontdv.h format of a font when loaded into memory
* grx20.h drawing-related structures and functions
* grxkeys.h platform independent key definitions
User programs normally only include @strong{include/grx20.h} and @strong{include/grxkeys.h}
@end example
@c -----------------------------------------------------------------------------
@node Setting the graphics driver, Setting video modes, Data types and function declarations, A User Manual For GRX2
@unnumberedsec Setting the graphics driver
The graphics driver is normally set by the final user by the environment
variable GRX20DRV, but a program can set it using:
@example
int GrSetDriver(char *drvspec);
@end example
The drvspec string has the same format as the environment variable:
@example
<driver> gw <width> gh <height> nc <colors>
@end example
Available drivers are for:
@example
* DOS => herc, stdvga, stdega, et4000, cl5426, mach64, ati28800, s3, VESA, memory
* Linux => svgalib, linuxfb, memory
* X11 => xwin, memory
* Win32 => win32, memory
* SDL (Win32 and X11) => sdl::fs, sdl::ww, memory
@end example
The xwin and win32 drivers are windowed.
The SDL driver on the same systems can be either fullscreen (::fs) or windowed (::ww).
The optionals gw, gh and nc parameters set the desired default graphics mode.
Normal values for 'nc' are 2, 16, 256, 64K and 16M. The current driver name can
be obtained from:
@example
GrCurrentVideoDriver()->name
@end example
@c -----------------------------------------------------------------------------
@node Setting video modes, Graphics contexts, Setting the graphics driver, A User Manual For GRX2
@unnumberedsec Setting video modes
Before a program can do any graphics drawing it has to configure the graphics
driver for the desired graphics mode. It is done with the GrSetMode function as
follows:
@example
int GrSetMode(int which,...);
@end example
On succes it returns non-zero (TRUE). The which parameter can be one of the
following constants, declared in grx20.h:
@example
typedef enum _GR_graphicsModes @{
GR_80_25_text,
GR_default_text,
GR_width_height_text,
GR_biggest_text,
GR_320_200_graphics,
GR_default_graphics,
GR_width_height_graphics,
GR_biggest_noninterlaced_graphics,
GR_biggest_graphics,
GR_width_height_color_graphics,
GR_width_height_color_text,
GR_custom_graphics,
GR_width_height_bpp_graphics,
GR_width_height_bpp_text,
GR_custom_bpp_graphics,
GR_NC_80_25_text,
GR_NC_default_text,
GR_NC_width_height_text,
GR_NC_biggest_text,
GR_NC_320_200_graphics,
GR_NC_default_graphics,
GR_NC_width_height_graphics,
GR_NC_biggest_noninterlaced_graphics,
GR_NC_biggest_graphics,
GR_NC_width_height_color_graphics,
GR_NC_width_height_color_text,
GR_NC_custom_graphics,
GR_NC_width_height_bpp_graphics,
GR_NC_width_height_bpp_text,
GR_NC_custom_bpp_graphics,
@} GrGraphicsMode;
@end example
The GR_width_height_text and GR_width_height_graphics modes require the two
size arguments: int width and int height.
The GR_width_height_color_graphics and GR_width_height_color_text modes
require three arguments: int width, int height and GrColor colors.
The GR_width_height_bpp_graphics and GR_width_height_bpp_text modes require
three arguments: int width, int height and int bpp (bits per plane instead
number of colors).
The GR_custom_graphics and GR_custom_bpp_graphics modes require five
arguments: int width, int height, GrColor colors or int bpp, int vx and int vy.
Using this modes you can set a virtual screen of vx by vy size.
A call with any other mode does not require any arguments.
The GR_NC_... modes are equivalent to the GR_.. ones, but they don't clear the
video memory.
Graphics drivers can provide info of the supported graphics modes, use the
next code skeleton to colect the data:
@example
@{
GrFrameMode fm;
const GrVideoMode *mp;
for(fm =GR_firstGraphicsFrameMode; fm <= GR_lastGraphicsFrameMode; fm++) @{
mp = GrFirstVideoMode(fm);
while( mp != NULL ) @{
..
.. use the mp info
..
mp = GrNextVideoMode(mp))
@}
@}
@}
@end example
Don't worry if you don't understand it, normal user programs don't need to
know about FrameModes. The GrVideoMode structure has the following fields:
@example
typedef struct _GR_videoMode GrVideoMode;
struct _GR_videoMode @{
char present; /* is it really available? */
char bpp; /* log2 of # of colors */
short width,height; /* video mode geometry */
short mode; /* BIOS mode number (if any) */
int lineoffset; /* scan line length */
int privdata; /* driver can use it for anything */
struct _GR_videoModeExt *extinfo; /* extra info (maybe shared) */
@};
@end example
The width, height and bpp members are the useful information if you are
interested in set modes other than the GR_default_graphics.
A user-defined function can be invoked every time the video mode is changed
(i.e. GrSetMode is called). This function should not take any parameters and
don't return any value. It can be installed (for all subsequent GrSetMode calls)
with the:
@example
void GrSetModeHook(void (*hookfunc)(void));
@end example
function. The current graphics mode (one of the valid mode argument values for
GrSetMode) can be obtained with the:
@example
GrGraphicsMode GrCurrentMode(void);
@end example
function, while the type of the installed graphics adapter can be determined
with the:
@example
GrVideoAdapter GrAdapterType(void);
@end example
function. GrAdapterType returns the type of the adapter as one of the following
symbolic constants (defined in grx20.h):
@example
typedef enum _GR_videoAdapters @{
GR_UNKNOWN = (-1), /* not known (before driver set) */
GR_VGA, /* VGA adapter */
GR_EGA, /* EGA adapter */
GR_HERC, /* Hercules mono adapter */
GR_8514A, /* 8514A or compatible */
GR_S3, /* S3 graphics accelerator */
GR_XWIN, /* X11 driver */
GR_WIN32, /* WIN32 driver */
GR_LNXFB, /* Linux framebuffer */
GR_SDL, /* SDL driver */
GR_MEM /* memory only driver */
@} GrVideoAdapter;
@end example
Note that the VESA driver return GR_VGA here.
@c -----------------------------------------------------------------------------
@node Graphics contexts, Context use, Setting video modes, A User Manual For GRX2
@unnumberedsec Graphics contexts
The library supports a set of drawing regions called contexts (the GrContext
structure). These can be in video memory or in system memory. Contexts in system
memory always have the same memory organization as the video memory. When
GrSetMode is called, a default context is created which maps to the whole
graphics screen. Contexts are described by the GrContext data structure:
@example
typedef struct _GR_context GrContext;
struct _GR_context @{
struct _GR_frame gc_frame; /* frame buffer info */
struct _GR_context *gc_root; /* context which owns frame */
int gc_xmax; /* max X coord (width - 1) */
int gc_ymax; /* max Y coord (height - 1) */
int gc_xoffset; /* X offset from root's base */
int gc_yoffset; /* Y offset from root's base */
int gc_xcliplo; /* low X clipping limit */
int gc_ycliplo; /* low Y clipping limit */
int gc_xcliphi; /* high X clipping limit */
int gc_ycliphi; /* high Y clipping limit */
int gc_usrxbase; /* user window min X coordinate */
int gc_usrybase; /* user window min Y coordinate */
int gc_usrwidth; /* user window width */
int gc_usrheight; /* user window height */
# define gc_baseaddr gc_frame.gf_baseaddr
# define gc_selector gc_frame.gf_selector
# define gc_onscreen gc_frame.gf_onscreen
# define gc_memflags gc_frame.gf_memflags
# define gc_lineoffset gc_frame.gf_lineoffset
# define gc_driver gc_frame.gf_driver
@};
@end example
The following four functions return information about the layout of and memory
occupied by a graphics context of size width by height in the current graphics
mode (as set up by GrSetMode):
@example
int GrLineOffset(int width);
int GrNumPlanes(void);
long GrPlaneSize(int w,int h);
long GrContextSize(int w,int h);
@end example
GrLineOffset always returns the offset between successive pixel rows of the
context in bytes. GrNumPlanes returns the number of bitmap planes in the current
graphics mode. GrContextSize calculates the total amount of memory needed by a
context, while GrPlaneSize calculates the size of a bitplane in the context. The
function:
@example
GrContext *GrCreateContext(int w,int h,char far *memory[4],GrContext *where);
@end example
can be used to create a new context in system memory. The NULL pointer is also
accepted as the value of the memory and where arguments, in this case the
library allocates the necessary amount of memory internally. It is a general
convention in the library that functions returning pointers to any GRX
specific data structure have a last argument (most of the time named where in
the prototypes) which can be used to pass the address of the data structure
which should be filled with the result. If this where pointer has the value of
NULL, then the library allocates space for the data structure internally.
The memory argument is really a 4 pointer array, each pointer must point to
space to handle GrPlaneSize(w,h) bytes, really only GrNumPlanes() pointers must
be malloced, the rest can be NULL. Nevertheless the normal use (see below) is
@example
gc = GrCreateContext(w,h,NULL,NULL);
@end example
so yo don't need to care about.
The function:
@example
GrContext *GrCreateSubContext(int x1,int y1,int x2,int y2,
const GrContext *parent,GrContext *where);
@end example
creates a new sub-context which maps to a part of an existing context. The
coordinate arguments (x1 through y2) are interpreted relative to the parent
context's limits. Pixel addressing is zero-based even in sub-contexts, i.e. the
address of the top left pixel is (0,0) even in a sub-context which has been
mapped onto the interior of its parent context.
Sub-contexts can be resized, but not their parents (i.e. anything returned by
GrCreateContext or set up by GrSetMode cannot be resized -- because this could
lead to irrecoverable "loss" of drawing memory. The following function can be
used for this purpose:
@example
void GrResizeSubContext(GrContext *context,int x1,int y1,int x2,int y2);
@end example
The current context structure is stored in a static location in the library.
(For efficiency reasons -- it is used quite frequently, and this way no pointer
dereferencing is necessary.) The context stores all relevant information about
the video organization, coordinate limits, etc... The current context can be set
with the:
@example
void GrSetContext(const GrContext *context);
@end example
function. This function will reset the current context to the full graphics
screen if it is passed the NULL pointer as argument. The value of the current
context can be saved into a GrContext structure pointed to by where using:
@example
GrContext *GrSaveContext(GrContext *where);
@end example
(Again, if where is NULL, the library allocates the space.) The next two
functions:
@example
const GrContext *GrCurrentContext(void);
const GrContext *GrScreenContext(void);
@end example
return the current context and the screen context respectively. Contexts can be
destroyed with:
@example
void GrDestroyContext(GrContext *context);
@end example
This function will free the memory occupied by the context only if it was
allocated originally by the library. The next three functions set up and query
the clipping limits associated with the current context:
@example
void GrSetClipBox(int x1,int y1,int x2,int y2);
void GrGetClipBox(int *x1p,int *y1p,int *x2p,int *y2p);
void GrResetClipBox(void);
@end example
GrResetClipBox sets the clipping limits to the limits of context. These are
the limits set up initially when a context is created. There are three similar
functions to sets/gets the clipping limits of any context:
@example
void GrSetClipBoxC(GrContext *c,int x1,int y1,int x2,int y2);
void GrGetClipBoxC(const GrContext *c,int *x1p,int *y1p,int *x2p,int *y2p);
void GrResetClipBoxC(GrContext *c);
@end example
The limits of the current context can be obtained using the following
functions:
@example
int GrMaxX(void);
int GrMaxY(void);
int GrSizeX(void);
int GrSizeY(void);
@end example
The Max functions return the biggest valid coordinate, while the Size
functions return a value one higher. The limits of the graphics screen
(regardless of the current context) can be obtained with:
@example
int GrScreenX(void);
int GrScreenY(void);
@end example
If you had set a virtual screen (using a custom graphics mode), the limits of
the virtual screen can be fetched with:
@example
int GrVirtualX(void);
int GrVirtualY(void);
@end example
The routine:
@example
int GrScreenIsVirtual(void);
@end example
returns non zero if a virtual screen is set. The rectangle showed in the real
screen can be set with:
@example
int GrSetViewport(int xpos,int ypos);
@end example
and the current viewport position can be obtained by:
@example
int GrViewportX(void);
int GrViewportY(void);
@end example
@c -----------------------------------------------------------------------------
@node Context use, Color management, Graphics contexts, A User Manual For GRX2
@unnumberedsec Context use
Here is a example of normal context use:
@example
GrContext *grc;
if( (grc = GrCreateContext( w,h,NULL,NULL )) == NULL )@{
...process the error
@}
else @{
GrSetContext( grc );
...do some drawing
...and probably bitblt to the screen context
GrSetContext( NULL ); /* the screen context! */
GrDestroyContext( grc );
@}
@end example
But if you have a GrContext variable (not a pointer) you want to use (probably
because is static to some routines) you can do:
@example
static GrContext grc; /* not a pointer!! */
if( GrCreateContext( w,h,NULL,&grc )) == NULL ) @{
...process the error
@}
else @{
GrSetContext( &grc );
...do some drawing
...and probably bitblt to the screen context
GrSetContext( NULL ); /* the screen context! */
GrDestroyContext( &grc );
@}
@end example
Note that GrDestoryContext knows if grc was automatically malloced or not!!
Only if you don't want GrCreateContext use malloc at all, you must allocate
the memory buffers and pass it to GrCreateContext.
Using GrCreateSubContext is the same, except it doesn't need the buffer,
because it uses the parent buffer.
See the @strong{test/winclip.c} and @strong{test/wintest.c} examples.
@c -----------------------------------------------------------------------------
@node Color management, Portable use of a few colors, Context use, A User Manual For GRX2
@unnumberedsec Color management
GRX defines the type GrColor for color variables. GrColor it's a 32 bits
integer. The 8 left bits are reserved for the write mode (see below). The 24
bits right are the color value.
The library supports two models for color management. In the 'indirect' (or
color table) model, color values are indices to a color table. The color table
slots will be allocated with the highest resolution supported by the hardware
(EGA: 2 bits, VGA: 6 bits) with respect to the component color intensities. In
the 'direct' (or RGB) model, color values map directly into component color
intensities with non-overlapping bitfields of the color index representing the
component colors.
Color table model is supported until 256 color modes. The RGB model is
supported in 256 color and up color modes.
In RGB model the color index map to component color intensities depend on the
video mode set, so it can't be assumed the component color bitfields (but if you
are curious check the GrColorInfo global structure in grx20.h).
After the first GrSetMode call two colors are always defined: black and white.
The color values of these two colors are returned by the functions:
@example
GrColor GrBlack(void);
GrColor GrWhite(void);
@end example
GrBlack() is guaranteed to be 0.
The library supports five write modes (a write mode descibes the operation
between the actual bit color and the one to be set): write, XOR, logical OR,
logical AND and IMAGE. These can be selected with OR-ing the color value with
one of the following constants declared in grx20.h :
@example
#define GrWRITE 0UL /* write color */
#define GrXOR 0x01000000UL /* to "XOR" any color to the screen */
#define GrOR 0x02000000UL /* to "OR" to the screen */
#define GrAND 0x03000000UL /* to "AND" to the screen */
#define GrIMAGE 0x04000000UL /* blit: write, except given color */
@end example
The GrIMAGE write mode only works with the bitblt function.
By convention, the no-op color is obtained by combining color value 0 (black)
with the XOR operation. This no-op color has been defined in grx20.h as:
@example
#define GrNOCOLOR (GrXOR | 0) /* GrNOCOLOR is used for "no" color */
@end example
The write mode part and the color value part of a GrColor variable can be
obtained OR-ing it with one of the following constants declared in grx20.h:
@example
#define GrCVALUEMASK 0x00ffffffUL /* color value mask */
#define GrCMODEMASK 0xff000000UL /* color operation mask */
@end example
The number of colors in the current graphics mode is returned by the:
@example
GrColor GrNumColors(void);
@end example
function, while the number of unused, available color can be obtained by
calling:
@example
GrColor GrNumFreeColors(void);
@end example
Colors can be allocated with the:
@example
GrColor GrAllocColor(int r,int g,int b);
GrColor GrAllocColor2(long hcolor);
@end example
functions (component intensities can range from 0 to 255,
hcolor must be in 0xRRGGBB format), or with the:
@example
GrColor GrAllocCell(void);
@end example
function. In the second case the component intensities of the returned color can
be set with:
@example
void GrSetColor(GrColor color,int r,int g,int b);
@end example
In the color table model both Alloc functions return GrNOCOLOR if there are no
more free colors available. In the RGB model GrNumFreeColors returns 0 and
GrAllocCell always returns GrNOCOLOR, as colors returned by GrAllocCell are
meant to be changed -- what is not supposed to be done in RGB mode. Also note
that GrAllocColor operates much more efficiently in RGB mode, and that it never
returns GrNOCOLOR in this case.
Color table entries can be freed (when not in RGB mode) by calling:
@example
void GrFreeColor(GrColor color);
@end example
The component intensities of any color can be queried using one of this function:
@example
void GrQueryColor(GrColor c,int *r,int *g,int *b);
void GrQueryColor2(GrColor c,long *hcolor);
@end example
Initially the color system is in color table (indirect) model if there are 256
or less colors. 256 color modes can be put into the RGB model by calling:
@example
void GrSetRGBcolorMode(void);
@end example
The color system can be reset (i.e. put back into color table model if
possible, all colors freed except for black and white) by calling:
@example
void GrResetColors(void);
@end example
The function:
@example
void GrRefreshColors(void);
@end example
reloads the currently allocated color values into the video hardware. This
function is not needed in typical applications, unless the display adapter is
programmed directly by the application.
This functions:
@example
GrColor GrAllocColorID(int r,int g,int b);
GrColor GrAllocColor2ID(long hcolor);
void GrQueryColorID(GrColor c,int *r,int *g,int *b);
void GrQueryColor2ID(GrColor c,long *hcolor);
@end example
are inlined versions (except if you compile GRX with GRX_SKIP_INLINES defined)
to be used in the RGB model (in the color table model they call the normal
routines).
See the @strong{test/rgbtest.c} and @strong{test/colorops.c} examples.
@c -----------------------------------------------------------------------------
@node Portable use of a few colors, Graphics primitives, Color management, A User Manual For GRX2
@unnumberedsec Portable use of a few colors
People that only want to use a few colors find the GRX color handling a bit
confusing, but it gives the power to manage a lot of color deeps and two color
models. Here are some guidelines to easily use the famous 16 ega colors in GRX
programs. We need this GRX function:
@example
GrColor *GrAllocEgaColors(void);
@end example
it returns a 16 GrColor array with the 16 ega colors alloced (really it's a
trivial function, read the source src/setup/colorega.c). We can use a
construction like that:
First, in your C code make a global pointer, and init it after set the
graphics mode:
@example
GrColor *egacolors;
....
int your_setup_function( ... )
@{
...
GrSetMode( ... )
...
egacolors = GrAllocEgaColors();
...
@}
@end example
Next, add this to your main include file:
@example
extern GrColor *egacolors;
#define BLACK egacolors[0]
#define BLUE egacolors[1]
#define GREEN egacolors[2]
#define CYAN egacolors[3]
#define RED egacolors[4]
#define MAGENTA egacolors[5]
#define BROWN egacolors[6]
#define LIGHTGRAY egacolors[7]
#define DARKGRAY egacolors[8]
#define LIGHTBLUE egacolors[9]
#define LIGHTGREEN egacolors[10]
#define LIGHTCYAN egacolors[11]
#define LIGHTRED egacolors[12]
#define LIGHTMAGENTA egacolors[13]
#define YELLOW egacolors[14]
#define WHITE egacolors[15]
@end example
Now you can use the defined colors in your code. Note that if you are in color
table model in a 16 color mode, you have exhausted the color table. Note too
that this don't work to initialize static variables with a color, because
egacolors is not initialized.
@c -----------------------------------------------------------------------------
@node Graphics primitives, Non-clipping graphics primitives, Portable use of a few colors, A User Manual For GRX2
@unnumberedsec Graphics primitives
The screen, the current context or the current clip box can be cleared (i.e.
set to a desired background color) by using one of the following three
functions:
@example
void GrClearScreen(GrColor bg);
void GrClearContext(GrColor bg);
void GrClearClipBox(GrColor bg);
@end example
Any context can be cleared using this function:
@example
void GrClearContextC(GrContext *ctx, GrColor bg);
@end example
Thanks to the special GrColor definition, you can do more than simple clear
with this functions, by example with:
@example
GrClearScreen( GrWhite()|GrXOR );
@end example
the graphics screen is negativized, do it again and the screen is restored.
The following line drawing graphics primitives are supported by the library:
@example
void GrPlot(int x,int y,GrColor c);
void GrLine(int x1,int y1,int x2,int y2,GrColor c);
void GrHLine(int x1,int x2,int y,GrColor c);
void GrVLine(int x,int y1,int y2,GrColor c);
void GrBox(int x1,int y1,int x2,int y2,GrColor c);
void GrCircle(int xc,int yc,int r,GrColor c);
void GrEllipse(int xc,int yc,int xa,int ya,GrColor c);
void GrCircleArc(int xc,int yc,int r,int start,int end,int style,GrColor c);
void GrEllipseArc(int xc,int yc,int xa,int ya,
int start,int end,int style,GrColor c);
void GrPolyLine(int numpts,int points[][2],GrColor c);
void GrPolygon(int numpts,int points[][2],GrColor c);
@end example
All primitives operate on the current graphics context. The last argument of
these functions is always the color to use for the drawing. The HLine and VLine
primitives are for drawing horizontal and vertical lines. They have been
included in the library because they are more efficient than the general line
drawing provided by GrLine. The ellipse primitives can only draw ellipses with
their major axis parallel with either the X or Y coordinate axis. They take the
half X and Y axis length in the xa and ya arguments. The arc (circle and
ellipse) drawing functions take the start and end angles in tenths of degrees
(i.e. meaningful range: 0 ... 3600). The angles are interpreted
counter-clockwise starting from the positive X axis. The style argument can be
one of this defines from grx20.h:
@example
#define GR_ARC_STYLE_OPEN 0
#define GR_ARC_STYLE_CLOSE1 1
#define GR_ARC_STYLE_CLOSE2 2
@end example
GR_ARC_STYLE_OPEN draws only the arc, GR_ARC_STYLE_CLOSE1 closes the arc with
a line between his start and end point, GR_ARC_STYLE_CLOSE1 draws the typical
cake slice. This routine:
@example
void GrLastArcCoords(int *xs,int *ys,int *xe,int *ye,int *xc,int *yc);
@end example
can be used to retrieve the start, end, and center points used by the last arc
drawing functions.
See the @strong{test/circtest.c} and @strong{test/arctest.c} examples.
The polyline and polygon primitives take the address of an n by 2 coordinate
array. The X values should be stored in the elements with 0 second index, and
the Y values in the elements with a second index value of 1. Coordinate arrays
passed to the polygon primitive can either contain or omit the closing edge of
the polygon -- the primitive will append it to the list if it is missing.
See the @strong{test/polytest.c} example.
Because calculating the arc points it's a very time consuming operation, there
are two functions to pre-calculate the points, that can be used next with
polyline and polygon primitives:
@example
int GrGenerateEllipse(int xc,int yc,int xa,int ya,
int points[GR_MAX_ELLIPSE_POINTS][2]);
int GrGenerateEllipseArc(int xc,int yc,int xa,int ya,int start,int end,
int points[GR_MAX_ELLIPSE_POINTS][2]);
@end example
The following filled primitives are available:
@example
void GrFilledBox(int x1,int y1,int x2,int y2,GrColor c);
void GrFramedBox(int x1,int y1,int x2,int y2,int wdt,const GrFBoxColors *c);
void GrFilledCircle(int xc,int yc,int r,GrColor c);
void GrFilledEllipse(int xc,int yc,int xa,int ya,GrColor c);
void GrFilledCircleArc(int xc,int yc,int r,
int start,int end,int style,GrColor c);
void GrFilledEllipseArc(int xc,int yc,int xa,int ya,
int start,int end,int style,GrColor c);
void GrFilledPolygon(int numpts,int points[][2],GrColor c);
void GrFilledConvexPolygon(int numpts,int points[][2],GrColor c);
@end example
Similarly to the line drawing, all of the above primitives operate on the
current graphics context. The GrFramedBox primitive can be used to draw
motif-like shaded boxes and "ordinary" framed boxes as well. The x1 through y2
coordinates specify the interior of the box, the border is outside this area,
wdt pixels wide. The primitive uses five different colors for the interior and
four borders of the box which are specified in the GrFBoxColors structure:
@example
typedef struct @{
GrColor fbx_intcolor;
GrColor fbx_topcolor;
GrColor fbx_rightcolor;
GrColor fbx_bottomcolor;
GrColor fbx_leftcolor;
@} GrFBoxColors;
@end example
The GrFilledConvexPolygon primitive can be used to fill convex polygons. It
can also be used to fill some concave polygons whose boundaries do not intersect
any horizontal scan line more than twice. All other concave polygons have to be
filled with the (somewhat less efficient) GrFilledPolygon primitive. This
primitive can also be used to fill several disjoint non<6F>overlapping polygons in
a single operation.
The function:
@example
void GrFloodFill(int x, int y, GrColor border, GrColor c);
@end example
flood-fills the area bounded by the color border using x, y like the starting
point.
Floodspill is a color replacer, replacing color A with color B.
This is quite useful for highlighting a selected item in a list, or changing
a selected color(s) in a multi colored area.
@example
void GrFloodSpill(int x1, int y1, int x2, int y2,
GrColor old_c, GrColor new_c)
@end example
replaces old color with new color in the rectangle bounded by x1, y1, x2, y2.
@example
void GrFloodSpillC(GrContext *ctx, int x1, int y1, int x2, int y2,
GrColor old_c, GrColor new_c)
@end example
as above but in the specified context.
@example
void GrFloodSpill2(int x1, int y1, int x2, int y2,
GrColor old_c1, GrColor new_c1,
GrColor old_c2, GrColor new_c2)
@end example
replaces 2 colors, a one stop shop for highlighting a selection in a list.
@example
void GrFloodSpillC2(GrContext *ctx, int x1, int y1, int x2, int y2,
GrColor old_c1, GrColor new_c1,
GrColor old_c2, GrColor new_c2)
@end example
as above but in the specified context.
The current color value of any pixel in the current context can be obtained
with:
@example
GrColor GrPixel(int x,int y);
@end example
and:
@example
GrColor GrPixelC(GrContext *c,int x,int y);
@end example
do the same for any context.
Rectangular areas can be transferred within a context or between contexts by
calling:
@example
void GrBitBlt(GrContext *dest,int x,int y,GrContext *source,
int x1,int y1,int x2,int y2,GrColor op);
@end example
x, y is the position in the destination context, and x1, y1, x2, y2 the area
from the source context to be transfered. The op argument should be one of
supported color write modes (GrWRITE, GrXOR, GrOR, GrAND, GrIMAGE), it will
control how the pixels from the source context are combined with the pixels in
the destination context (the GrIMAGE op must be ored with the color value to be
handled as transparent). If either the source or the destination context
argument is the NULL pointer then the current context is used for that argument.
See the @strong{test/blittest.c} example.
A efficient form to get/put pixels from/to a context can be achieved using the
next functions:
@example
const GrColor *GrGetScanline(int x1,int x2,int yy);
const GrColor *GrGetScanlineC(GrContext *ctx,int x1,int x2,int yy);
void GrPutScanline(int x1,int x2,int yy,const GrColor *c, GrColor op);
@end example
The Get functions return a pointer to a static GrColor pixel array (or NULL if
they fail) with the color values of a row (yy) segment (x1 to x2). GrGetScanline
uses the current context. GrGestScanlineC uses the context ctx (that can be NULL
to refer to the current context). Note that the output is only valid until the
next GRX call.
GrPutScanline puts the GrColor pixel array c on the yy row segmet defined by
x1 to x2 in the current context using the op operation. op can be any of
GrWRITE, GrXOR, GrOR, GrAND or GrIMAGE. Data in c must fit GrCVALUEMASK
otherwise the results are implementation dependend. So you can't supply
operation code with the pixel data!.
@c -----------------------------------------------------------------------------
@node Non-clipping graphics primitives, Customized line drawing, Graphics primitives, A User Manual For GRX2
@unnumberedsec Non-clipping graphics primitives
There is a non-clipping version of some of the elementary primitives. These
are somewhat more efficient than the regular versions. These are to be used only
in situations when it is absolutely certain that no drawing will be performed
beyond the boundaries of the current context. Otherwise the program will almost
certainly crash! The reason for including these functions is that they are
somewhat more efficient than the regular, clipping versions. ALSO NOTE: These
function do not check for conflicts with the mouse cursor. (See the explanation
about the mouse cursor handling later in this document.) The list of the
supported non-clipping primitives:
@example
void GrPlotNC(int x,int y,GrColor c);
void GrLineNC(int x1,int y1,int x2,int y2,GrColor c);
void GrHLineNC(int x1,int x2,int y,GrColor c);
void GrVLineNC(int x,int y1,int y2,GrColor c);
void GrBoxNC(int x1,int y1,int x2,int y2,GrColor c);
void GrFilledBoxNC(int x1,int y1,int x2,int y2,GrColor c);
void GrFramedBoxNC(int x1,int y1,int x2,int y2,int wdt,const GrFBoxColors *c);
void grbitbltNC(GrContext *dst,int x,int y,GrContext *src,
int x1,int y1,int x2,int y2,GrColor op);
GrColor GrPixelNC(int x,int y);
GrColor GrPixelCNC(GrContext *c,int x,int y);
@end example
@c -----------------------------------------------------------------------------
@node Customized line drawing, Pattern filled graphics primitives, Non-clipping graphics primitives, A User Manual For GRX2
@unnumberedsec Customized line drawing
The basic line drawing graphics primitives described previously always draw
continuous lines which are one pixel wide. There is another group of line
drawing functions which can be used to draw wide and/or patterned lines. These
functions have similar parameter passing conventions as the basic ones with one
difference: instead of the color value a pointer to a structure of type
GrLineOption has to be passed to them. The definition of the GrLineOption
structure:
@example
typedef struct @{
GrColor lno_color; /* color used to draw line */
int lno_width; /* width of the line */
int lno_pattlen; /* length of the dash pattern */
unsigned char *lno_dashpat; /* draw/nodraw pattern */
@} GrLineOption;
@end example
The lno_pattlen structure element should be equal to the number of alternating
draw -- no draw section length values in the array pointed to by the lno_dashpat
element. The dash pattern array is assumed to begin with a drawn section. If the
pattern length is equal to zero a continuous line is drawn.
Example, a white line 3 bits wide (thick) and pattern 6 bits draw, 4 bits nodraw:
@example
GrLineOption mylineop;
...
mylineop.lno_color = GrWhite();
mylineop.lno_width = 3;
mylineop.lno_pattlen = 2;
mylineop.lno_dashpat = "\x06\x04";
@end example
The available custom line drawing primitives:
@example
void GrCustomLine(int x1,int y1,int x2,int y2,const GrLineOption *o);
void GrCustomBox(int x1,int y1,int x2,int y2,const GrLineOption *o);
void GrCustomCircle(int xc,int yc,int r,const GrLineOption *o);
void GrCustomEllipse(int xc,int yc,int xa,int ya,const GrLineOption *o);
void GrCustomCircleArc(int xc,int yc,int r,
int start,int end,int style,const GrLineOption *o);
void GrCustomEllipseArc(int xc,int yc,int xa,int ya,
int start,int end,int style,const GrLineOption *o);
void GrCustomPolyLine(int numpts,int points[][2],const GrLineOption *o);
void GrCustomPolygon(int numpts,int points[][2],const GrLineOption *o);
@end example
See the @strong{test/linetest.c} example.
@c -----------------------------------------------------------------------------
@node Pattern filled graphics primitives, Patterned line drawing, Customized line drawing, A User Manual For GRX2
@unnumberedsec Pattern filled graphics primitives
The library also supports a pattern filled version of the basic filled
primitives described above. These functions have similar parameter passing
conventions as the basic ones with one difference: instead of the color value a
pointer to an union of type 'GrPattern' has to be passed to them. The GrPattern
union can contain either a bitmap or a pixmap fill pattern. The first integer
slot in the union determines which type it is. Bitmap fill patterns are
rectangular arrays of bits, each set bit representing the foreground color of
the fill operation, and each zero bit representing the background. Both the
foreground and background colors can be combined with any of the supported
logical operations. Bitmap fill patterns have one restriction: their width must
be eight pixels. Pixmap fill patterns are very similar to contexts. The relevant
structure declarations (from grx20.h):
@example
/*
* BITMAP: a mode independent way to specify a fill pattern of two
* colors. It is always 8 pixels wide (1 byte per scan line), its
* height is user-defined. SET THE TYPE FLAG TO ZERO!!!
*/
typedef struct _GR_bitmap @{
int bmp_ispixmap; /* type flag for pattern union */
int bmp_height; /* bitmap height */
char *bmp_data; /* pointer to the bit pattern */
GrColor bmp_fgcolor; /* foreground color for fill */
GrColor bmp_bgcolor; /* background color for fill */
int bmp_memflags; /* set if dynamically allocated */
@} GrBitmap;
/*
* PIXMAP: a fill pattern stored in a layout identical to the video RAM
* for filling using 'bitblt'-s. It is mode dependent, typically one
* of the library functions is used to build it. KEEP THE TYPE FLAG
* NONZERO!!!
*/
typedef struct _GR_pixmap @{
int pxp_ispixmap; /* type flag for pattern union */
int pxp_width; /* pixmap width (in pixels) */
int pxp_height; /* pixmap height (in pixels) */
GrColor pxp_oper; /* bitblt mode (SET, OR, XOR, AND, IMAGE) */
struct _GR_frame pxp_source; /* source context for fill */
@} GrPixmap;
/*
* Fill pattern union -- can either be a bitmap or a pixmap
*/
typedef union _GR_pattern @{
int gp_ispixmap; /* nonzero for pixmaps */
GrBitmap gp_bitmap; /* fill bitmap */
GrPixmap gp_pixmap; /* fill pixmap */
@} GrPattern;
@end example
This define group (from grx20.h) help to acces the GrPattern menbers:
@example
#define gp_bmp_data gp_bitmap.bmp_data
#define gp_bmp_height gp_bitmap.bmp_height
#define gp_bmp_fgcolor gp_bitmap.bmp_fgcolor
#define gp_bmp_bgcolor gp_bitmap.bmp_bgcolor
#define gp_pxp_width gp_pixmap.pxp_width
#define gp_pxp_height gp_pixmap.pxp_height
#define gp_pxp_oper gp_pixmap.pxp_oper
#define gp_pxp_source gp_pixmap.pxp_source
@end example
Bitmap patterns can be easily built from initialized character arrays and
static structures by the C compiler, thus no special support is included in the
library for creating them. The only action required from the application program
might be changing the foreground and background colors as needed. Pixmap
patterns are more difficult to build as they replicate the layout of the video
memory which changes for different video modes. For this reason the library
provides three functions to create pixmap patterns in a mode-independent way:
@example
GrPattern *GrBuildPixmap(const char *pixels,int w,int h,const GrColorTableP colors);
GrPattern *GrBuildPixmapFromBits(const char *bits,int w,int h,
GrColor fgc,GrColor bgc);
GrPattern *GrConvertToPixmap(GrContext *src);
@end example
GrBuildPixmap build a pixmap from a two dimensional (w by h) array of
characters. The elements in this array are used as indices into the color table
specified with the argument colors. (This means that pixmaps created this way
can use at most 256 colors.) The color table pointer:
@example
typedef GrColor *GrColorTableP;
@end example
should point to an array of integers with the first element being the number of
colors in the table and the color values themselves starting with the second
element. NOTE: any color modifiers (GrXOR, GrOR, GrAND) OR-ed to the elements of
the color table are ignored.
The GrBuildPixmapFromBits function builds a pixmap fill pattern from bitmap
data. It is useful if the width of the bitmap pattern is not eight as such
bitmap patterns can not be used to build a GrBitmap structure.
The GrConvertToPixmap function converts a graphics context to a pixmap fill
pattern. It is useful when the pattern can be created with graphics drawing
operations. NOTE: the pixmap pattern and the original context share the drawing
RAM, thus if the context is redrawn the fill pattern changes as well. Fill
patterns which were built by library routines can be destroyed when no longer
needed (i.e. the space occupied by them can be freed) by calling:
@example
void GrDestroyPattern(GrPattern *p);
@end example
NOTE: when pixmap fill patterns converted from contexts are destroyed, the
drawing RAM is not freed. It is freed when the original context is destroyed.
Fill patterns built by the application have to be destroyed by the application
as well (if this is needed).
The list of supported pattern filled graphics primitives is shown below. These
functions are very similar to their solid filled counterparts, only their last
argument is different:
@example
void GrPatternFilledPlot(int x,int y,GrPattern *p);
void GrPatternFilledLine(int x1,int y1,int x2,int y2,GrPattern *p);
void GrPatternFilledBox(int x1,int y1,int x2,int y2,GrPattern *p);
void GrPatternFilledCircle(int xc,int yc,int r,GrPattern *p);
void GrPatternFilledEllipse(int xc,int yc,int xa,int ya,GrPattern *p);
void GrPatternFilledCircleArc(int xc,int yc,int r,int start,int end,
int style,GrPattern *p);
void GrPatternFilledEllipseArc(int xc,int yc,int xa,int ya,int start,int end,
int style,GrPattern *p);
void GrPatternFilledConvexPolygon(int numpts,int points[][2],GrPattern *p);
void GrPatternFilledPolygon(int numpts,int points[][2],GrPattern *p);
void GrPatternFloodFill(int x, int y, GrColor border, GrPattern *p);
@end example
Strictly speaking the plot and line functions in the above group are not
filled, but they have been included here for convenience.
@c -----------------------------------------------------------------------------
@node Patterned line drawing, Image manipulation, Pattern filled graphics primitives, A User Manual For GRX2
@unnumberedsec Patterned line drawing
The custom line drawing functions introduced above also have a version when
the drawn sections can be filled with a (pixmap or bitmap) fill pattern. To
achieve this these functions must be passed both a custom line drawing option
(GrLineOption structure) and a fill pattern (GrPattern union). These two have
been combined into the GrLinePattern structure:
@example
typedef struct @{
GrPattern *lnp_pattern; /* fill pattern */
GrLineOption *lnp_option; /* width + dash pattern */
@} GrLinePattern;
@end example
All patterned line drawing functions take a pointer to this structure as their
last argument. The list of available functions:
@example
void GrPatternedLine(int x1,int y1,int x2,int y2,GrLinePattern *lp);
void GrPatternedBox(int x1,int y1,int x2,int y2,GrLinePattern *lp);
void GrPatternedCircle(int xc,int yc,int r,GrLinePattern *lp);
void GrPatternedEllipse(int xc,int yc,int xa,int ya,GrLinePattern *lp);
void GrPatternedCircleArc(int xc,int yc,int r,int start,int end,
int style,GrLinePattern *lp);
void GrPatternedEllipseArc(int xc,int yc,int xa,int ya,int start,int end,
int style,GrLinePattern *lp);
void GrPatternedPolyLine(int numpts,int points[][2],GrLinePattern *lp);
void GrPatternedPolygon(int numpts,int points[][2],GrLinePattern *lp);
@end example
@c -----------------------------------------------------------------------------
@node Image manipulation, Text drawing, Patterned line drawing, A User Manual For GRX2
@unnumberedsec Image manipulation
GRX defines the GrImage type like a GrPixmap synonym:
@example
#define GrImage GrPixmap
@end example
nevertheless the GrImage type enforces the image character of this object, so
for compatibility with future GRX versions use the next functions if you need to
convert between GrImage and GrPixmap objects:
@example
GrImage *GrImageFromPattern(GrPattern *p);
GrPattern *GrPatternFromImage(GrImage *p);
@end example
the GrImageFromPattern function returns NULL if the GrPattern given is not a
GrPixmap.
Like pixmaps patterns images are dependent of the actual video mode set. So
the library provides functions to create images in a mode-independent way:
@example
GrImage *GrImageBuild(const char *pixels,int w,int h,const GrColorTableP colors);
GrImage *GrImageFromContext(GrContext *c);
@end example
these functions work like the GrBuildPixmap and GrConvertToPixmap ones.
Remember: the image and the original context share the drawing RAM.
There are a number of functions to display all or part of an image in the
current context:
@example
void GrImageDisplay(int x,int y, GrImage *i);
void GrImageDisplayExt(int x1,int y1,int x2,int y2, GrImage *i);
void GrImageFilledBoxAlign(int xo,int yo,int x1,int y1,int x2,int y2,
GrImage *p);
void GrImageHLineAlign(int xo,int yo,int x,int y,int width,GrImage *p);
void GrImagePlotAlign(int xo,int yo,int x,int y,GrImage *p);
@end example
GrImageDisplay display the whole image using x, y like the upper left corner
in the current context. GrImageDisplayExt display as much as it can (repiting
the image if necesary) in the rectangle defined by x1, y1 and x2, y2.
GrImageFilledBoxAlign is a most general funtion (really the later two call it)
display as much as it can in the defined rectangle using xo, yo like the align
point, it is the virtual point in the destination context (it doesn't need to be
into the rectangle) with that the upper left image corner is aligned.
GrImageHLineAlign and GrImagePlotAlign display a row segment or a point of the
image at x y position using the xo, yo allign point.
The most usefull image funtions are these:
@example
GrImage *GrImageInverse(GrImage *p,int flag);
GrImage *GrImageStretch(GrImage *p,int nwidth,int nheight);
@end example
GrImageInverse creates a new image object, flipping p left-right or top-down
as indicated by flag that can be:
@example
#define GR_IMAGE_INVERSE_LR 0x01 /* inverse left right */
#define GR_IMAGE_INVERSE_TD 0x02 /* inverse top down */
@end example
GrImageStretch creates a new image stretching p to nwidth by nheight.
To destroy a image objet when you don't need it any more use:
@example
void GrImageDestroy(GrImage *i);
@end example
See the @strong{test/imgtest.c} example.
@c -----------------------------------------------------------------------------
@node Text drawing, Drawing in user coordinates, Image manipulation, A User Manual For GRX2
@unnumberedsec Text drawing
The library supports loadable fonts. When in memory they are bit-mapped (i.e.
not scalable!) fonts. A driver design allow GRX to load different font formats,
the last GRX release come with drivers to load the GRX own font format and the
BGI Borland format for all platforms supported, the X11 version can load X11
fonts too.
The GRX distribution come with a font collection in the GRX own format. Some
of these fonts were converted from VGA fonts. These fonts have all 256
characters from the PC-437 codepage. Some additional fonts were converted from
fonts in the MIT X11 distribution. Most of these are ISO-8859-1 coded. Fonts
also have family names. The following font families are included:
@example
Font file name Family Description
pc<W>x<H>[t].fnt pc VGA font, fixed
xm<W>x<H>[b][i].fnt X_misc X11, fixed, miscellaneous group
char<H>[b][i].fnt char X11, proportional, charter family
cour<H>[b][i].fnt cour X11, fixed, courier
helve<H>[b][i].fnt helve X11, proportional, helvetica
lucb<H>[b][i].fnt lucb X11, proportional, lucida bright
lucs<H>[b][i].fnt lucs X11, proportional, lucida sans serif
luct<H>[b][i].fnt luct X11, fixed, lucida typewriter
ncen<H>[b][i].fnt ncen X11, proportional, new century schoolbook
symb<H>.fnt symbol X11, proportional, greek letters, symbols
tms<H>[b][i].fnt times X11, proportional, times
@end example
In the font names <W> means the font width, <H> the font height. Many font
families have bold and/or italic variants. The files containing these fonts
contain a 'b' and/or 'i' character in their name just before the extension.
Additionally, the strings "_bold" and/or "_ital" are appended to the font family
names. Some of the pc VGA fonts come in thin formats also, these are denoted by
a 't' in their file names and the string "_thin" in their family names.
The GrFont structure hold a font in memory. A number of 'pc' fonts are
built-in to the library and don't need to be loaded:
@example
extern GrFont GrFont_PC6x8;
extern GrFont GrFont_PC8x8;
extern GrFont GrFont_PC8x14;
extern GrFont GrFont_PC8x16;
@end example
Other fonts must be loaded with the GrLoadFont function. If the font file name
starts with any path separator character or character sequence (':', '/' or '\')
then it is loaded from the specified directory, otherwise the library try load
the font first from the current directory and next from the default font path.
The font path can be set up with the GrSetFontPath function. If the font path is
not set then the value of the 'GRXFONT' environment variable is used as the font
path. If GrLoadFont is called again with the name of an already loaded font then
it will return a pointer to the result of the first loading. Font loading
routines return NULL if the font was not found. When not needed any more, fonts
can be unloaded (i.e. the storage occupied by them freed) by calling
GrUnloadFont.
The prototype declarations for these functions:
@example
GrFont *GrLoadFont(char *name);
void GrUnloadFont(GrFont *font);
void GrSetFontPath(char *path_list);
@end example
Using these functions:
@example
GrFont *GrLoadConvertedFont(char *name,int cvt,int w,int h,
int minch,int maxch);
GrFont *GrBuildConvertedFont(const GrFont *from,int cvt,int w,int h,
int minch,int maxch);
@end example
a new font can be generated from a file font or a font in memory, the 'cvt'
argument direct the conversion or-ing the desired operations from these defines:
@example
/*
* Font conversion flags for 'GrLoadConvertedFont'. OR them as desired.
*/
#define GR_FONTCVT_NONE 0 /* no conversion */
#define GR_FONTCVT_SKIPCHARS 1 /* load only selected characters */
#define GR_FONTCVT_RESIZE 2 /* resize the font */
#define GR_FONTCVT_ITALICIZE 4 /* tilt font for "italic" look */
#define GR_FONTCVT_BOLDIFY 8 /* make a "bold"(er) font */
#define GR_FONTCVT_FIXIFY 16 /* convert prop. font to fixed wdt */
#define GR_FONTCVT_PROPORTION 32 /* convert fixed font to prop. wdt */
@end example
GR_FONTCVT_SKIPCHARS needs 'minch' and 'maxch' arguments.
GR_FONTCVT_RESIZE needs 'w' and 'h' arguments.
The function:
@example
void GrDumpFnaFont(const GrFont *f, char *fileName);
@end example
writes a font to an ascii font file, so it can be quickly edited with a text
editor. For a description of the ascii font format, see the fna.txt file.
The function:
@example
void GrDumpFont(const GrFont *f,char *CsymbolName,char *fileName);
@end example
writes a font to a C source code file, so it can be compiled and linked with a
user program. GrDumpFont would not normally be used in a release program because
its purpose is to produce source code. When the source code is compiled and
linked into a program distributing the font file with the program in not
necessary, avoiding the possibility of the font file being deleted or corrupted.
You can use the premade fnt2c.c program (see the source, it's so simple) to
dump a selected font to source code, by example:
@example
fnt2c helv15 myhelv15 myhelv15.c
@end example
Next, if this line is included in your main include file:
@example
extern GrFont myhelv15
@end example
and "myhelv15.c" compiled and linked with your project, you can use 'myhelv15'
in every place a GrFont is required.
This simple function:
@example
void GrTextXY(int x,int y,char *text,GrColor fg,GrColor bg);
@end example
draw text in the current context in the standard direction, using the
GrDefaultFont (mapped in the grx20.h file to the GrFont_PC8x14 font) with x, y
like the upper left corner and the foreground and background colors given (note
that bg equal to GrNOCOLOR make the background transparent).
For other functions the GrTextOption structure specifies how to draw a
character string:
@example
typedef struct _GR_textOption @{ /* text drawing option structure */
struct _GR_font *txo_font; /* font to be used */
union _GR_textColor txo_fgcolor; /* foreground color */
union _GR_textColor txo_bgcolor; /* background color */
char txo_chrtype; /* character type (see above) */
char txo_direct; /* direction (see above) */
char txo_xalign; /* X alignment (see above) */
char txo_yalign; /* Y alignment (see above) */
@} GrTextOption;
typedef union _GR_textColor @{ /* text color union */
GrColor v; /* color value for "direct" text */
GrColorTableP p; /* color table for attribute text */
@} GrTextColor;
@end example
The text can be rotated in increments of 90 degrees (txo_direct), alignments
can be set in both directions (txo_xalign and txo_yalign), and separate fore and
background colors can be specified. The accepted text direction values:
@example
#define GR_TEXT_RIGHT 0 /* normal */
#define GR_TEXT_DOWN 1 /* downward */
#define GR_TEXT_LEFT 2 /* upside down, right to left */
#define GR_TEXT_UP 3 /* upward */
#define GR_TEXT_DEFAULT GR_TEXT_RIGHT
@end example
The accepted horizontal and vertical alignment option values:
@example
#define GR_ALIGN_LEFT 0 /* X only */
#define GR_ALIGN_TOP 0 /* Y only */
#define GR_ALIGN_CENTER 1 /* X, Y */
#define GR_ALIGN_RIGHT 2 /* X only */
#define GR_ALIGN_BOTTOM 2 /* Y only */
#define GR_ALIGN_BASELINE 3 /* Y only */
#define GR_ALIGN_DEFAULT GR_ALIGN_LEFT
@end example
Text strings can be of three different types: one character per byte (i.e. the
usual C character string, this is the default), one character per 16-bit word
(suitable for fonts with a large number of characters), and a PC-style
character-attribute pair. In the last case the GrTextOption structure must
contain a pointer to a color table of size 16 (fg color bits in attrib) or 8 (bg
color bits). (The color table format is explained in more detail in the previous
section explaining the methods to build fill patterns.) The supported text
types:
@example
#define GR_BYTE_TEXT 0 /* one byte per character */
#define GR_WORD_TEXT 1 /* two bytes per character */
#define GR_ATTR_TEXT 2 /* chr w/ PC style attribute byte */
@end example
The PC-style attribute text uses the same layout (first byte: character,
second: attributes) and bitfields as the text mode screen on the PC. The only
difference is that the 'blink' bit is not supported (it would be very time
consuming -- the PC text mode does it with hardware support). This bit is used
instead to control the underlined display of characters. For convenience the
following attribute manipulation macros have been declared in grx20.h:
@example
#define GR_BUILD_ATTR(fg,bg,ul) \
(((fg) & 15) | (((bg) & 7) << 4) | ((ul) ? 128 : 0))
#define GR_ATTR_FGCOLOR(attr) (((attr) ) & 15)
#define GR_ATTR_BGCOLOR(attr) (((attr) >> 4) & 7)
#define GR_ATTR_UNDERLINE(attr) (((attr) ) & 128)
@end example
Text strings of the types GR_BYTE_TEXT and GR_WORD_TEXT can also be drawn
underlined. This is controlled by OR-ing the constant GR_UNDERLINE_TEXT to the
foreground color value:
@example
#define GR_UNDERLINE_TEXT (GrXOR << 4)
@end example
After the application initializes a text option structure with the desired
values it can call one of the following two text drawing functions:
@example
void GrDrawChar(int chr,int x,int y,const GrTextOption *opt);
void GrDrawString(void *text,int length,int x,int y,const GrTextOption *opt);
@end example
NOTE: text drawing is fastest when it is drawn in the 'normal' direction, and
the character does not have to be clipped. It this case the library can use the
appropriate low-level video RAM access routine, while in any other case the text
is drawn pixel-by-pixel by the higher-level code.
There are pattern filed versions too:
@example
void GrPatternDrawChar(int chr,int x,int y,const GrTextOption *opt,GrPattern *p);
void GrPatternDrawString(void *text,int length,int x,int y,const GrTextOption *opt,
GrPattern *p);
void GrPatternDrawStringExt(void *text,int length,int x,int y,
const GrTextOption *opt,GrPattern *p);
@end example
The size of a font, a character or a text string can be obtained by calling
one of the following functions. These functions also take into consideration the
text direction specified in the text option structure passed to them.
@example
int GrFontCharPresent(const GrFont *font,int chr);
int GrFontCharWidth(const GrFont *font,int chr);
int GrFontCharHeight(const GrFont *font,int chr);
int GrFontCharBmpRowSize(const GrFont *font,int chr);
int GrFontCharBitmapSize(const GrFont *font,int chr);
int GrFontStringWidth(const GrFont *font,void *text,int len,int type);
int GrFontStringHeight(const GrFont *font,void *text,int len,int type);
int GrProportionalTextWidth(const GrFont *font,void *text,int len,int type);
int GrCharWidth(int chr,const GrTextOption *opt);
int GrCharHeight(int chr,const GrTextOption *opt);
void GrCharSize(int chr,const GrTextOption *opt,int *w,int *h);
int GrStringWidth(void *text,int length,const GrTextOption *opt);
int GrStringHeight(void *text,int length,const GrTextOption *opt);
void GrStringSize(void *text,int length,const GrTextOption *opt,int *w,int *h);
@end example
The GrTextRegion structure and its associated functions can be used to
implement a fast (as much as possible in graphics modes) rectangular text window
using a fixed font. Clipping for such windows is done in character size
increments instead of pixels (i.e. no partial characters are drawn). Only fixed
fonts can be used in their natural size. GrDumpText will cache the code of the
drawn characters in the buffer pointed to by the 'backup' slot (if it is
non-NULL) and will draw a character only if the previously drawn character in
that grid element is different.
This can speed up text scrolling significantly in graphics modes. The
supported text types are the same as above.
@example
typedef struct @{ /* fixed font text window desc. */
struct _GR_font *txr_font; /* font to be used */
union _GR_textColor txr_fgcolor; /* foreground color */
union _GR_textColor txr_bgcolor; /* background color */
void *txr_buffer; /* pointer to text buffer */
void *txr_backup; /* optional backup buffer */
int txr_width; /* width of area in chars */
int txr_height; /* height of area in chars */
int txr_lineoffset; /* offset in buffer(s) between rows */
int txr_xpos; /* upper left corner X coordinate */
int txr_ypos; /* upper left corner Y coordinate */
char txr_chrtype; /* character type (see above) */
@} GrTextRegion;
void GrDumpChar(int chr,int col,int row,const GrTextRegion *r);
void GrDumpText(int col,int row,int wdt,int hgt,const GrTextRegion *r);
void GrDumpTextRegion(const GrTextRegion *r);
@end example
The GrDumpTextRegion function outputs the whole text region, while GrDumpText
draws only a user-specified part of it. GrDumpChar updates the character in the
buffer at the specified location with the new character passed to it as argument
and then draws the new character on the screen as well. With these functions you
can simulate a text mode window, write chars directly to the txr_buffer and call
GrDumpTextRegion when you want to update the window (or GrDumpText if you know
the area to update is small).
See the @strong{test/fonttest.c} example.
@c -----------------------------------------------------------------------------
@node Drawing in user coordinates, Graphics cursors, Text drawing, A User Manual For GRX2
@unnumberedsec Drawing in user coordinates
There is a second set of the graphics primitives which operates in user
coordinates. Every context has a user to screen coordinate mapping associated
with it. An application specifies the user window by calling the GrSetUserWindow
function.
@example
void GrSetUserWindow(int x1,int y1,int x2,int y2);
@end example
A call to this function it in fact specifies the virtual coordinate limits
which will be mapped onto the current context regardless of the size of the
context. For example, the call:
@example
GrSetUserWindow(0,0,11999,8999);
@end example
tells the library that the program will perform its drawing operations in a
coordinate system X:0...11999 (width = 12000) and Y:0...8999 (height = 9000).
This coordinate range will be mapped onto the total area of the current context.
The virtual coordinate system can also be shifted. For example:
@example
GrSetUserWindow(5000,2000,16999,10999);
@end example
The user coordinates can even be used to turn the usual left-handed coordinate
system (0:0 corresponds to the upper left corner) to a right handed one (0:0
corresponds to the bottom left corner) by calling:
@example
GrSetUserWindow(0,8999,11999,0);
@end example
The library also provides three utility functions for the query of the current
user coordinate limits and for converting user coordinates to screen coordinates
and vice versa.
@example
void GrGetUserWindow(int *x1,int *y1,int *x2,int *y2);
void GrGetScreenCoord(int *x,int *y);
void GrGetUserCoord(int *x,int *y);
@end example
If an application wants to take advantage of the user to screen coordinate
mapping it has to use the user coordinate version of the graphics primitives.
These have exactly the same parameter passing conventions as their screen
coordinate counterparts. NOTE: the user coordinate system is not initialized by
the library! The application has to set up its coordinate mapping before calling
any of the use coordinate drawing functions -- otherwise the program will almost
certainly exit (in a quite ungraceful fashion) with a 'division by zero' error.
The list of supported user coordinate drawing functions:
@example
void GrUsrPlot(int x,int y,GrColor c);
void GrUsrLine(int x1,int y1,int x2,int y2,GrColor c);
void GrUsrHLine(int x1,int x2,int y,GrColor c);
void GrUsrVLine(int x,int y1,int y2,GrColor c);
void GrUsrBox(int x1,int y1,int x2,int y2,GrColor c);
void GrUsrFilledBox(int x1,int y1,int x2,int y2,GrColor c);
void GrUsrFramedBox(int x1,int y1,int x2,int y2,int wdt,GrFBoxColors *c);
void GrUsrCircle(int xc,int yc,int r,GrColor c);
void GrUsrEllipse(int xc,int yc,int xa,int ya,GrColor c);
void GrUsrCircleArc(int xc,int yc,int r,int start,int end,
int style,GrColor c);
void GrUsrEllipseArc(int xc,int yc,int xa,int ya,int start,int end,
int style,GrColor c);
void GrUsrFilledCircle(int xc,int yc,int r,GrColor c);
void GrUsrFilledEllipse(int xc,int yc,int xa,int ya,GrColor c);
void GrUsrFilledCircleArc(int xc,int yc,int r,int start,int end,
int style,GrColor c);
void GrUsrFilledEllipseArc(int xc,int yc,int xa,int ya,int start,int end,
int style,GrColor c);
void GrUsrPolyLine(int numpts,int points[][2],GrColor c);
void GrUsrPolygon(int numpts,int points[][2],GrColor c);
void GrUsrFilledConvexPolygon(int numpts,int points[][2],GrColor c);
void GrUsrFilledPolygon(int numpts,int points[][2],GrColor c);
void GrUsrFloodFill(int x, int y, GrColor border, GrColor c);
GrColor GrUsrPixel(int x,int y);
GrColor GrUsrPixelC(GrContext *c,int x,int y);
void GrUsrCustomLine(int x1,int y1,int x2,int y2,const GrLineOption *o);
void GrUsrCustomBox(int x1,int y1,int x2,int y2,const GrLineOption *o);
void GrUsrCustomCircle(int xc,int yc,int r,const GrLineOption *o);
void GrUsrCustomEllipse(int xc,int yc,int xa,int ya,const GrLineOption *o);
void GrUsrCustomCircleArc(int xc,int yc,int r,int start,int end,
int style,const GrLineOption *o);
void GrUsrCustomEllipseArc(int xc,int yc,int xa,int ya,int start,int end,
int style,const GrLineOption *o);
void GrUsrCustomPolyLine(int numpts,int points[][2],const GrLineOption *o);
void GrUsrCustomPolygon(int numpts,int points[][2],const GrLineOption *o);
void GrUsrPatternedLine(int x1,int y1,int x2,int y2,GrLinePattern *lp);
void GrUsrPatternedBox(int x1,int y1,int x2,int y2,GrLinePattern *lp);
void GrUsrPatternedCircle(int xc,int yc,int r,GrLinePattern *lp);
void GrUsrPatternedEllipse(int xc,int yc,int xa,int ya,GrLinePattern *lp);
void GrUsrPatternedCircleArc(int xc,int yc,int r,int start,int end,
int style,GrLinePattern *lp);
void GrUsrPatternedEllipseArc(int xc,int yc,int xa,int ya,int start,int end,
int style,GrLinePattern *lp);
void GrUsrPatternedPolyLine(int numpts,int points[][2],GrLinePattern *lp);
void GrUsrPatternedPolygon(int numpts,int points[][2],GrLinePattern *lp);
void GrUsrPatternFilledPlot(int x,int y,GrPattern *p);
void GrUsrPatternFilledLine(int x1,int y1,int x2,int y2,GrPattern *p);
void GrUsrPatternFilledBox(int x1,int y1,int x2,int y2,GrPattern *p);
void GrUsrPatternFilledCircle(int xc,int yc,int r,GrPattern *p);
void GrUsrPatternFilledEllipse(int xc,int yc,int xa,int ya,GrPattern *p);
void GrUsrPatternFilledCircleArc(int xc,int yc,int r,int start,int end,int style,GrPattern *p);
void GrUsrPatternFilledEllipseArc(int xc,int yc,int xa,int ya,int start,int end,int style,GrPattern *p);
void GrUsrPatternFilledConvexPolygon(int numpts,int points[][2],GrPattern *p);
void GrUsrPatternFilledPolygon(int numpts,int points[][2],GrPattern *p);
void GrUsrPatternFloodFill(int x, int y, GrColor border, GrPattern *p);
void GrUsrDrawChar(int chr,int x,int y,const GrTextOption *opt);
void GrUsrDrawString(char *text,int length,int x,int y,const GrTextOption *opt);
void GrUsrTextXY(int x,int y,char *text,GrColor fg,GrColor bg);
@end example
@c -----------------------------------------------------------------------------
@node Graphics cursors, Keyboard input, Drawing in user coordinates, A User Manual For GRX2
@unnumberedsec Graphics cursors
The library provides support for the creation and usage of an unlimited number
of graphics cursors. An application can use these cursors for any purpose.
Cursors always save the area they occupy before they are drawn. When moved or
erased they restore this area. As a general rule of thumb, an application should
erase a cursor before making changes to an area it occupies and redraw the
cursor after finishing the drawing. Cursors are created with the GrBuildCursor
function:
@example
GrCursor *GrBuildCursor(char far *pixels,int pitch,int w,int h,
int xo,int yo,const GrColorTableP c);
@end example
The pixels, w (=width), h (=height) and c (= color table) arguments are
similar to the arguments of the pixmap building library function GrBuildPixmap
(see that paragraph for a more detailed explanation.), but with two differences.
First, is not assumed that the pixels data is w x h sized, the pitch argument
set the offset between rows. Second, the pixmap data is interpreted slightly
differently, any pixel with value zero is taken as a "transparent" pixel, i.e.
the background will show through the cursor pattern at that pixel. A pixmap data
byte with value = 1 will refer to the first color in the table, and so on.
The xo (= X offset) and yo (= Y offset) arguments specify the position (from
the top left corner of the cursor pattern) of the cursor's "hot point".
The GrCursor data structure:
@example
typedef struct _GR_cursor @{
struct _GR_context work; /* work areas (4) */
int xcord,ycord; /* cursor position on screen */
int xsize,ysize; /* cursor size */
int xoffs,yoffs; /* LU corner to hot point offset */
int xwork,ywork; /* save/work area sizes */
int xwpos,ywpos; /* save/work area position on screen */
int displayed; /* set if displayed */
@} GrCursor;
@end example
is typically not used (i.e. read or changed) by the application program, it
should just pass pointers to these structures to the appropriate library
functions. Other cursor manipulation functions:
@example
void GrDisplayCursor(GrCursor *cursor);
void GrEraseCursor(GrCursor *cursor);
void GrMoveCursor(GrCursor *cursor,int x,int y);
void GrDestroyCursor(GrCursor *cursor);
@end example
See the @strong{test/curstest.c} example.
@c -----------------------------------------------------------------------------
@node Keyboard input, Mouse event handling, Graphics cursors, A User Manual For GRX2
@unnumberedsec Keyboard input
GRX can handle platform independant key input. The file grxkeys.h defines the
keys to be used in the user's program. This is an extract:
@example
#define GrKey_Control_A 0x0001
#define GrKey_Control_B 0x0002
#define GrKey_Control_C 0x0003
...
#define GrKey_A 0x0041
#define GrKey_B 0x0042
#define GrKey_C 0x0043
...
#define GrKey_F1 0x013b
#define GrKey_F2 0x013c
#define GrKey_F3 0x013d
...
#define GrKey_Alt_F1 0x0168
#define GrKey_Alt_F2 0x0169
#define GrKey_Alt_F3 0x016a
@end example
But you can be confident that the standard ASCII is right maped.
The GrKeyType type is defined to store keycodes:
@example
typedef unsigned short GrKeyType;
@end example
This function:
@example
int GrKeyPressed(void);
@end example
returns non zero if there are any keycode waiting, that can be read with:
@example
GrKeyType GrKeyRead(void);
@end example
The function:
@example
int GrKeyStat(void);
@end example
returns a keyboard status word, or-ing it with the next defines it can be known
the status of some special keys:
@example
#define GR_KB_RIGHTSHIFT 0x01 /* right shift key depressed */
#define GR_KB_LEFTSHIFT 0x02 /* left shift key depressed */
#define GR_KB_CTRL 0x04 /* CTRL depressed */
#define GR_KB_ALT 0x08 /* ALT depressed */
#define GR_KB_SCROLLOCK 0x10 /* SCROLL LOCK active */
#define GR_KB_NUMLOCK 0x20 /* NUM LOCK active */
#define GR_KB_CAPSLOCK 0x40 /* CAPS LOCK active */
#define GR_KB_INSERT 0x80 /* INSERT state active */
#define GR_KB_SHIFT (GR_KB_LEFTSHIFT | GR_KB_RIGHTSHIFT)
@end example
See the @strong{test/keys.c} example.
@c -----------------------------------------------------------------------------
@node Mouse event handling, Writing/reading PNM graphics files, Keyboard input, A User Manual For GRX2
@unnumberedsec Mouse event handling
All mouse services need the presence of a mouse. An application can test
whether a mouse is available by calling the function:
@example
int GrMouseDetect(void);
@end example
which will return zero if no mouse (or mouse driver) is present, non-zero
otherwise. The mouse must be initialized by calling one (and only one) of these
functions:
@example
void GrMouseInit(void);
void GrMouseInitN(int queue_size);
@end example
GrMouseInit sets a event queue (see below) size to GR_M_QUEU_SIZE (128). A
user supply event queue size can be set calling GrMouseInitN instead.
It is a good practice to call GrMouseUnInit before exiting the program. This
will restore any interrupt vectors hooked by the program to their original
values.
@example
void GrMouseUnInit(void);
@end example
The mouse can be controlled with the following functions:
@example
void GrMouseSetSpeed(int spmult,int spdiv);
void GrMouseSetAccel(int thresh,int accel);
void GrMouseSetLimits(int x1,int y1,int x2,int y2);
void GrMouseGetLimits(int *x1,int *y1,int *x2,int *y2);
void GrMouseWarp(int x,int y);
@end example
The library calculates the mouse position only from the mouse mickey counters.
(To avoid the limit and 'rounding to the next multiple of eight' problem with
some mouse driver when it finds itself in a graphics mode unknown to it.) The
parameters to the GrMouseSetSpeed function specify how coordinate changes are
obtained from mickey counter changes, multipling by spmult and dividing by
spdiv. In high resolution graphics modes the value of one just works fine, in
low resolution modes (320x200 or similar) it is best set the spdiv to two or
three. (Of course, it also depends on the sensitivity the mouse.) The
GrMouseSetAccel function is used to control the ballistic effect: if a mouse
coordinate changes between two samplings by more than the thresh parameter, the
change is multiplied by the accel parameter. NOTE: some mouse drivers perform
similar calculations before reporting the coordinates in mickeys. In this case
the acceleration done by the library will be additional to the one already
performed by the mouse driver. The limits of the mouse movement can be set
(passed limits will be clipped to the screen) with GrMouseSetLimits (default is
the whole screen) and the current limits can be obtained with GrMouseGetLimits.
GrMouseWarp sets the mouse cursor to the specified position.
As typical mouse drivers do not know how to draw mouse cursors in high
resolution graphics modes, the mouse cursor is drawn by the library. The mouse
cursor can be set with:
@example
void GrMouseSetCursor(GrCursor *cursor);
void GrMouseSetColors(GrColor fg,GrColor bg);
@end example
GrMouseSetColors uses an internal arrow pattern, the color fg will be used as
the interior of it and bg will be the border. The current mouse cursor can be
obtained with:
@example
GrCursor *GrMouseGetCursor(void);
@end example
The mouse cursor can be displayed/erased with:
@example
void GrMouseDisplayCursor(void);
void GrMouseEraseCursor(void);
@end example
The mouse cursor can be left permanently displayed. All graphics primitives
except for the few non-clipping functions check for conflicts with the mouse
cursor and erase it before the drawing if necessary. Of course, it may be more
efficient to erase the cursor manually before a long drawing sequence and redraw
it after completion. The library provides an alternative pair of calls for this
purpose which will erase the cursor only if it interferes with the drawing:
@example
int GrMouseBlock(GrContext *c,int x1,int y1,int x2,int y2);
void GrMouseUnBlock(int return_value_from_GrMouseBlock);
@end example
GrMouseBlock should be passed the context in which the drawing will take place
(the usual convention of NULL meaning the current context is supported) and the
limits of the affected area. It will erase the cursor only if it interferes with
the drawing. When the drawing is finished GrMouseUnBlock must be called with the
argument returned by GrMouseBlock.
The status of the mouse cursor can be obtained with calling
GrMouseCursorIsDisplayed. This function will return non-zero if the cursor is
displayed, zero if it is erased.
@example
int GrMouseCursorIsDisplayed(void);
@end example
The library supports (beside the simple cursor drawing) three types of
"rubberband" attached to the mouse cursor. The GrMouseSetCursorMode function is
used to select the cursor drawing mode.
@example
void GrMouseSetCursorMode(int mode,...);
@end example
The parameter mode can have the following values:
@example
#define GR_M_CUR_NORMAL 0 /* MOUSE CURSOR modes: just the cursor */
#define GR_M_CUR_RUBBER 1 /* rect. rubber band (XOR-d to the screen) */
#define GR_M_CUR_LINE 2 /* line attached to the cursor */
#define GR_M_CUR_BOX 3 /* rectangular box dragged by the cursor */
@end example
GrMouseSetCursorMode takes different parameters depending on the cursor
drawing mode selected. The accepted call formats are:
@example
GrMouseSetCursorMode(M_CUR_NORMAL);
GrMouseSetCursorMode(M_CUR_RUBBER,xanchor,yanchor,GrColor);
GrMouseSetCursorMode(M_CUR_LINE,xanchor,yanchor,GrColor);
GrMouseSetCursorMode(M_CUR_BOX,dx1,dy1,dx2,dy2,GrColor);
@end example
The anchor parameters for the rubberband and rubberline modes specify a fixed
screen location to which the other corner of the primitive is bound. The dx1
through dy2 parameters define the offsets of the corners of the dragged box from
the hotpoint of the mouse cursor. The color value passed is always XOR-ed to the
screen, i.e. if an application wants the rubberband to appear in a given color
on a given background then it has to pass the XOR of these two colors to
GrMouseSetCursorMode.
The GrMouseGetEvent function is used to obtain the next mouse or keyboard
event. It takes a flag with various bits encoding the type of event needed. It
returns the event in a GrMouseEvent structure. The relevant declarations from
grx20.h:
@example
void GrMouseGetEvent(int flags,GrMouseEvent *event);
typedef struct _GR_mouseEvent @{ /* mouse event buffer structure */
int flags; /* event type flags (see above) */
int x,y; /* mouse coordinates */
int buttons; /* mouse button state */
int key; /* key code from keyboard */
int kbstat; /* keybd status (ALT, CTRL, etc..) */
long dtime; /* time since last event (msec) */
@} GrMouseEvent;
@end example
The event structure has been extended with a keyboard status word (thus a
program can check for combinations like ALT-<left mousebutton press>) and a time
stamp which can be used to check for double clicks, etc... The following macros
have been defined in grx20.h to help in creating the control flag for
GrMouseGetEvent and decoding the various bits in the event structure:
@example
#define GR_M_MOTION 0x001 /* mouse event flag bits */
#define GR_M_LEFT_DOWN 0x002
#define GR_M_LEFT_UP 0x004
#define GR_M_RIGHT_DOWN 0x008
#define GR_M_RIGHT_UP 0x010
#define GR_M_MIDDLE_DOWN 0x020
#define GR_M_MIDDLE_UP 0x040
#define GR_M_BUTTON_DOWN (GR_M_LEFT_DOWN | GR_M_MIDDLE_DOWN | \
GR_M_RIGHT_DOWN | GR_M_P4_DOWN | GR_M_P5_DOWN)
#define GR_M_BUTTON_UP (GR_M_LEFT_UP | GR_M_MIDDLE_UP | \
GR_M_RIGHT_UP | GR_M_P4_UP | GR_M_P5_UP)
#define GR_M_BUTTON_CHANGE (GR_M_BUTTON_UP | GR_M_BUTTON_DOWN )
#define GR_M_LEFT 0x01 /* mouse button index bits */
#define GR_M_RIGHT 0x02
#define GR_M_MIDDLE 0x04
#define GR_M_P4 0x08 /* wheel rolls up */
#define GR_M_P5 0x10 /* wheel rolls down */
#define GR_M_KEYPRESS 0x080 /* other event flag bits */
#define GR_M_POLL 0x100
#define GR_M_NOPAINT 0x200
#define GR_COMMAND 0x1000
#define GR_M_EVENT (GR_M_MOTION | GR_M_KEYPRESS | \
GR_M_BUTTON_CHANGE | GR_COMMAND)
@end example
GrMouseGetEvent will display the mouse cursor if it was previously erased and
the GR_M_NOPAINT bit is not set in the flag passed to it. In this case it will
also erase the cursor after an event has been obtained.
GrMouseGetEvent block until a event is produced, except if the GR_M_POLL bit
is set in the flag passed to it.
Another version of GetEvent:
@example
void GrMouseGetEventT(int flags,GrMouseEvent *event,long timout_msecs);
@end example
can be istructed to wait timout_msec for the presence of an event. Note that
event->dtime is only valid if any event occured (event->flags != 0) otherwise
it's set as -1. Additionally event timing is real world time even in X11 &&
Linux.
If there are one or more events waiting the function:
@example
int GrMousePendingEvent(void);
@end example
returns non-zero value.
The generation of mouse and keyboard events can be individually enabled or
disabled (by passing a non-zero or zero, respectively, value in the
corresponding enable_XX parameter) by calling:
@example
void GrMouseEventEnable(int enable_kb,int enable_ms);
@end example
Note that GrMouseInit set both by default. If you want to use
GrMouseGetEvent and GrKeyRead at the same time, a call to
GrMouseEventEnable( 0,1 ) is needed before input process.
See the @strong{test/mousetst.c} example.
@node Writing/reading PNM graphics files, Writing/reading PNG graphics files,Mouse event handling , A User Manual For GRX2
@unnumberedsec Writing/reading PNM graphics files
GRX includes functions to load/save a context from/to a PNM file.
PNM is a group of simple graphics formats from the
@uref{http://netpbm.sourceforge.net, NetPbm}
distribution. NetPbm can convert from/to PNM lots of graphics formats,
and apply some transformations to PNM files.
(Note. You don't need the NetPbm distribution to use this functions).
There are six PNM formats:
@example
P1 text PBM (bitmap)
P2 text PGM (gray scale)
P3 text PPM (real color)
P4 binary PBM (bitmap)
P5 binary PGM (gray scale)
P6 binary PPM (real color)
@end example
GRX can handle the binary formats only (get the NetPbm distribution if you
need convert text to binary formats).
To save a context in a PNM file you have three functions:
@example
int GrSaveContextToPbm( GrContext *grc, char *pbmfn, char *docn );
int GrSaveContextToPgm( GrContext *grc, char *pgmfn, char *docn );
int GrSaveContextToPpm( GrContext *grc, char *ppmfn, char *docn );
@end example
they work both in RGB and palette modes, grc must be a pointer to the context to
be saved, if it is NULL the current context is saved; p-mfn is the file name to
be created and docn is an optional text comment to be written in the file, it
can be NULL. Three functions return 0 on succes and -1 on error.
GrSaveContextToPbm dumps a context in a PBM file (bitmap). If the pixel color
isn't Black it asumes White.
GrSaveContextToPgm dumps a context in a PGM file (gray scale). The colors are
quantized to gray scale using .299r + .587g + .114b.
GrSaveContextToPpm dumps a context in a PPM file (real color).
To load a PNM file in a context you must use:
@example
int GrLoadContextFromPnm( GrContext *grc, char *pnmfn );
@end example
it support reading PBM, PGM and PPM binary files. grc must be a pointer to the
context to be written, if it is NULL the current context is used; p-mfn is the
file name to be read. If context dimensions are lesser than pnm dimensions, the
function loads as much as it can. If color mode is not in RGB mode, the routine
allocates as much colors as it can. The function returns 0 on succes and -1 on
error.
To query the file format, width and height of a PNM file you can use:
@example
int GrQueryPnm( char *ppmfn, int *width, int *height, int *maxval );
@end example
pnmfn is the name of pnm file; width returns the pnm width; height returns the
pnm height; maxval returns the max color component value. The function returns 1
to 6 on success (the PNM format) or -1 on error.
The two next functions:
@example
int GrLoadContextFromPnmBuffer( GrContext *grc, const char *pnmbuf );
int GrQueryPnmBuffer( const char *pnmbuf, int *width, int *height, int *maxval );
@end example
work like GrLoadContextFromPnm and
GrQueryPnmBuffer, but they get his input from a buffer instead
of a file. This way, pnm files can be embeded in a program (using the
bin2c program by example).
@node Writing/reading PNG graphics files, Writing/reading JPEG graphics files, Writing/reading PNM graphics files, A User Manual For GRX2
@unnumberedsec Writing/reading PNG graphics files
GRX includes functions to load/save a context
from/to a png file. But note, for this purpose it needs the
@uref{http://www.libpng.org/pub/png/libpng.html, libpng} library,
and to enable the png support before make the GRX lib.
Use next function to save a context in a PNG file:
@example
int GrSaveContextToPng( GrContext *grc, char *pngfn );
@end example
it works both in RGB and palette modes, grc must be
a pointer to the context to be saved, if it is NULL the current context is
saved; pngfn is the file name to be created.
The function returns 0 on succes and -1 on error.
To load a PNG file in a context you must use:
@example
int GrLoadContextFromPng( GrContext *grc, char *pngfn, int use_alpha );
@end example
grc must be a pointer to the context to be written, if it
is NULL the current context is used; pngfn is the file name
to be read; set use_alpha to 1 if you want to use the image
alpha channel (if available). If context dimensions are lesser than png
dimensions, the function loads as much as it can. If color mode is not
in RGB mode, the routine allocates as much colors as it can. The function
returns 0 on succes and -1 on error.
To query the width and height of a PNG file you can use:
@example
int GrQueryPng( char *pngfn, int *width, int *height );
@end example
pngfn is the name of png file; width returns the
png width; height returns the png height.
The function returns 0 on success or -1 on error.
The function:
@example
int GrPngSupport( void );
@end example
returns 1 if there is png support in the library, 0 otherwise. If there is
not support for png, dummy functions are added to the library, returning
error (-1) ever.
@node Writing/reading JPEG graphics files, Miscellaneous functions, Writing/reading PNG graphics files, A User Manual For GRX2
@unnumberedsec Writing/reading PNG graphics files
GRX includes functions to load/save a context
from/to a jpeg file. But note, for this purpose it needs the
@uref{http://www.ijg.org, libjpeg} library,
and to enable the jpeg support before make the GRX lib.
Use next function to save a context in a JPEG file:
@example
int GrSaveContextToJpeg( GrContext *grc, char *jpegfn, int quality );
@end example
it works both in RGB and palette modes, grc must be
a pointer to the context to be saved, if it is NULL the current context is
saved; jpegfn is the file name to be created;
quality is a number between 1 and 100 to drive the compression
quality, use higher values for better quality (and bigger files), you can
use 75 as a standard value, normally a value between 50 and 95 is good.
The function returns 0 on succes and -1 on error.
This function saves a context in a grayscale JPEG file:
@example
int GrSaveContextToGrayJpeg( GrContext *grc, char *jpegfn, int quality );
@end example
parameters and return codes are like in GrSaveContextToJpeg.
The colors are quantized to gray scale using .299r + .587g + .114b.
To load a JPEG file in a context you must use:
@example
int GrLoadContextFromJpeg( GrContext *grc, char *jpegfn, int scale );
@end example
grc must be a pointer to the context to be written, if it
is NULL the current context is used; jpegfn is the file name
to be read; set scale to 1, 2, 4 or 8 to reduce the loaded
image to 1/1, 1/2, 1/4 or 1/8. If context dimensions are lesser than jpeg
dimensions, the function loads as much as it can. If color mode is not
in RGB mode, the routine allocates as much colors as it can. The function
returns 0 on succes and -1 on error.
To query the width and height of a JPEG file you can use:
@example
int GrQueryJpeg( char *jpegfn, int *width, int *height );
@end example
jpegfn is the name of jpeg file; width returns the
jpeg width; height returns the jpeg height.
The function returns 0 on success or -1 on error.
The function:
@example
int GrJpegSupport( void );
@end example
returns 1 if there is jpeg support in the library, 0 otherwise. If there is
not support for jpeg, dummy functions are added to the library, returning
error (-1) ever.
@node Miscellaneous functions, BGI interface, Writing/reading JPEG graphics files, A User Manual For GRX2
@unnumberedsec Miscellaneous functions
Here we will describe some miscellaneous functions.
@example
unsigned GrGetLibraryVersion(void);
@end example
GrGetLibraryVersion returns the GRX version API, like a hexadecimal coded
number. By example 0x0241 means 2.4.1 Because grx20.h defines the
GRX_VERSION_API macro, you can check if both, the library and the
include file, are in the same version using
if(GrGetLibraryVersion() == GRX_VERSION_API )
@example
unsigned GrGetLibrarySystem(void);
@end example
This functions returns a unsigned integer identifing the system you are
working in. grx20.h defines some macros you can use:
@example
/* these are the supported configurations: */
#define GRX_VERSION_TCC_8086_DOS 1 /* also works with BCC */
#define GRX_VERSION_GCC_386_DJGPP 2 /* DJGPP v2 */
#define GRX_VERSION_GCC_386_LINUX 3 /* the real stuff */
#define GRX_VERSION_GENERIC_X11 4 /* generic X11 version */
#define GRX_VERSION_WATCOM_DOS4GW 5 /* GS - Watcom C++ 11.0 32 Bit
#define GRX_VERSION_GCC_386_WIN32 7 /* WIN32 using Mingw32 */
#define GRX_VERSION_MSC_386_WIN32 8 /* WIN32 using MS-VC */
#define GRX_VERSION_GCC_386_CYG32 9 /* WIN32 using CYGWIN */
#define GRX_VERSION_GCC_386_X11 10 /* X11 version */
#define GRX_VERSION_GCC_X86_64_LINUX 11 /* console framebuffer 64 */
#define GRX_VERSION_GCC_X86_64_X11 12 /* X11 version 64 */
@end example
Note. On Linux, GrGetLibrarySystem returns GRX_VERSION_GCC_386_LINUX even in the
X11 version.
@example
void GrSetWindowTitle(char *title);
@end example
GrSetWindowTitle sets the main window title in the X11 an Win32 versions. It
doesn't do nothing in the DOS and Linux-SvgaLib versions.
@example
void GrSleep(int msec);
@end example
This function stops the program execution for msec miliseconds.
@example
long GrMsecTime( void );
@end example
This function gives the current time with millisecond resolution
@example
void GrFlush( void );
@end example
This funnction flushes the graphics window. Not dummy because useful only on
X11 when switching between graphics and console windows open simultaneously.
@example
GrContext *GrCreateFrameContext(GrFrameMode md,int w,int h,
char far *memory[4],GrContext *where);
@end example
This function is like GrCreateContext, except that you can specify any valid
memory frame mode, not only the Screen associated frame mode. It can be used for
special purposes (see GrBitBlt1bpp for an example).
@example
void GrBitBlt1bpp(GrContext *dst,int dx,int dy,GrContext *src,
int x1,int y1,int x2,int y2,GrColor fg,GrColor bg);
@end example
This special function does a bitblt from a 1bpp context (a bitmap really),
using fg and bg like the color+opcode when bit=1 and bit=0 respectively. Here is
an example:
@example
pContext = GrCreateFrameContext(GR_frameRAM1, sizex, sizey, NULL, NULL);
/* draw something (black and white) into the bitmap */
GrSetContext(pContext);
GrClearContext( GrBlack() );
GrLine(0, 0, sizex-1, sizey-1, GrWhite());
GrLine(0, sizey-1, sizex-1, 0, GrWhite());
/* Put the bitmap into the screen */
GrSetContext(NULL);
fcolor = GrAllocColor( 255,0,0 );
bcolor = GrAllocColor( 0,0,255 );
GrBitBlt1bpp(NULL,x,y,pContext,0,0,sizex-1,sizey-1,fcolor,bcolor);
@end example
@c -----------------------------------------------------------------------------
@node BGI interface, Pascal interface, Miscellaneous functions, A User Manual For GRX2
@unnumberedsec BGI interface
From the 2.3.1 version, GRX includes the BCC2GRX library created by Hartmut
Schirmer. The BCC2GRX was created to allow users of GRX to compile graphics
programs written for Borland-C++ and Turbo-C graphics interface. BCC2GRX is not
a convenient platform to develop new BGI programs. Of course you should use
native GRX interface in such cases!
Read the readme.bgi file for more info.
@c -----------------------------------------------------------------------------
@node Pascal interface, References, BGI interface, A User Manual For GRX2
@unnumberedsec Pascal interface
The Pascal (gpc) support is produced by two unit files @strong{pascal/grx.pas}
and @strong{pascal/bgi/graph.pas} which are the Pascal translations of the C
header files @strong{include/grx20.h + include/grxkeys.h}
and @strong{include/libbcc.h}.
Compilation of the examples and installation of the header files is allowed
by setting INCLUDE_GPC_SUPPORT=y in makedef.grx.
The unit files contain at the beginning instructions to load the required
libraries (libgrx20..., depending on the system) and addon libraries
(e.g. libpng).
You can uncomment manually the addons you want.
You can also use the configure script which does that automatically,
together with editing the makedefs.grx file.
By default they are installed in a @strong{units} directory below the
INSTALLDIR directory. But you can put them where you like.
@c -----------------------------------------------------------------------------
@node References, , Pascal interface, A User Manual For GRX2
@unnumberedsec References
@multitable {MGRX site (fork from GRX)----}{----http://www.libpng.org/pub/png/libpng.html}
@item Official GRX site
@tab @uref{http://grx.gnu.de}
@item GRX mailing list archive
@tab @uref{http://grx.gnu.de/archive/grx/en/}
@item MGRX site (fork from GRX)
@tab @uref{http://mgrx.fgrim.com}
@item NetPbm distribution
@tab @uref{http://netpbm.sourceforge.net}
@item PNG library
@tab @uref{http://www.libpng.org/pub/png/libpng.html}
@item JPEG library
@tab @uref{http://www.ijg.org}
@item TIFF library
@tab @uref{http://www.remotesensing.org/libtiff/}
@end multitable
@c -----------------------------------------------------------------------------