Hi, about fonts and user cooridnates, the end is coming :-)
* 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:
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
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:
extern GrFont GrFont_PC6x8; extern GrFont GrFont_PC8x8; extern GrFont GrFont_PC8x14; extern GrFont GrFont_PC8x16;
Other fonts must be loaded with the 'GrLoadFont' function. If the font file name starts with any path separator character or character sequence ('<drive letter>:', '/' 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:
GrFont *GrLoadFont(char *name); void GrUnloadFont(GrFont *font); void GrSetFontPath(char *path_list);
Using these functions:
GrFont *GrLoadConvertedFont(char *name,int cvt,int w,int h, int minch,int maxch); GrFont *GrBuildConvertedFont(GrFont *from,int cvt,int w,int h, int minch,int maxch);
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:
/* * 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 */
'GR_FONTCVT_SKIPCHARS' needs 'minch' and 'maxch' arguments. 'GR_FONTCVT_RESIZE' needs 'w' and 'h' arguments.
The function:
void GrDumpFont(GrFont *f,char *CsymbolName,char *fileName);
write a font to file like C code, so it can be linked with a user program.
This simple function:
void GrTextXY(int x,int y,char *text,GrColor fg,GrColor bg);
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 'GrBlack() | GrAND' make the background transparent).
For other functions the 'GrTextOption' structure specifies how to draw a character string:
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;
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:
#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
The accepted horizontal and vertical alignment option values:
#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
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:
#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 */
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":
#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)
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:
#define GR_UNDERLINE_TEXT (GrXOR << 4)
After the application initializes a text option structure with the desired values it can call one of the following two text drawing functions:
void GrDrawChar(int chr,int x,int y,GrTextOption *opt); void GrDrawString(void *text,int length,int x,int y,GrTextOption *opt);
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 too pattern filed versions:
void GrPatternDrawChar(int chr,int x,int y,GrTextOption *opt,GrPattern *p); void GrPatternDrawString(void *text,int length,int x,int y,GrTextOption *opt, GrPattern *p); void GrPatternDrawStringExt(void *text,int length,int x,int y, GrTextOption *opt,GrPattern *p);
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.
int GrFontCharPresent(GrFont *font,int chr); int GrFontCharWidth(GrFont *font,int chr); int GrFontCharHeight(GrFont *font,int chr); int GrFontCharBmpRowSize(GrFont *font,int chr); int GrFontCharBitmapSize(GrFont *font,int chr); int GrFontStringWidth(GrFont *font,void *text,int len,int type); int GrFontStringHeight(GrFont *font,void *text,int len,int type); int GrProportionalTextWidth(GrFont *font,void *text,int len,int type);
int GrCharWidth(int chr,GrTextOption *opt); int GrCharHeight(int chr,GrTextOption *opt); void GrCharSize(int chr,GrTextOption *opt,int *w,int *h); int GrStringWidth(void *text,int length,GrTextOption *opt); int GrStringHeight(void *text,int length,GrTextOption *opt); void GrStringSize(void *text,int length,GrTextOption *opt,int *w,int *h);
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.
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,GrTextRegion *r); void GrDumpText(int col,int row,int wdt,int hgt,GrTextRegion *r); void GrDumpTextRegion(GrTextRegion *r);
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).
* 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.
void GrSetUserWindow(int x1,int y1,int x2,int y2);
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:
GrSetUserWindow(0,0,11999,8999);
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:
GrSetUserWindow(5000,2000,16999,10999);
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:
GrSetUserWindow(0,8999,11999,0);
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.
void GrGetUserWindow(int *x1,int *y1,int *x2,int *y2); void GrGetScreenCoord(int *x,int *y); void GrGetUserCoord(int *x,int *y);
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:
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,GrLineOption *o); void GrUsrCustomBox(int x1,int y1,int x2,int y2,GrLineOption *o); void GrUsrCustomCircle(int xc,int yc,int r,GrLineOption *o); void GrUsrCustomEllipse(int xc,int yc,int xa,int ya,GrLineOption *o); void GrUsrCustomCircleArc(int xc,int yc,int r,int start,int end, int style,GrLineOption *o); void GrUsrCustomEllipseArc(int xc,int yc,int xa,int ya,int start,int end, int style,GrLineOption *o); void GrUsrCustomPolyLine(int numpts,int points[][2],GrLineOption *o); void GrUsrCustomPolygon(int numpts,int points[][2],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,GrTextOption *opt); void GrUsrDrawString(char *text,int length,int x,int y,GrTextOption *opt); void GrUsrTextXY(int x,int y,char *text,GrColor fg,GrColor bg);