
QNX Windows Font Format Documentation.    Version 4.2   May,1994
========================================================================
This document describes the QNX Windows Font format as of QNX Windows 
Version 4.2.  (May 1994)
This format could possibly change in the future. QNX Software Systems
reserves the right to change this format as needed. However, we will make
the most effort possible to provide our customers with tools and
documentation in the event of a change.

===========================================================================
All font files MUST reside within directory /windows/fonts. The graphics
driver can ONLY read fonts that are contained in this path.

The Format Documentation consists of:

A. Font filename conventions
B. Font file structures
C. Layout of the file
D. Font Metrics
E. Support Tools

==========================================================================
A. Font filename conventions...
==========================================================================

The current versions of the graphics drivers loads fonts from /windows/fonts
You MUST put all windows fonts in this directory.
	The name of the fonts in /windows/fonts are representative of the type, 
	render format, pixel size and style.
	
    "cour.B18B"
      \   \ \\Style - Bold
       \   \ \Size - 18 pixel
        \   \Format - Bitmapped
         \Face - Courier

The following face names are reserved and should not be used for new fonts:
	PCterm - PC Terminal
	System - System
	oldeng - Old English
	cour   - Courier
	char   - Character
	helv   - Helvetica
	times  - Times Roman
	ncen   - New Century
	The face name may contain any valid filename characters except a dot(.).

Format must be "B" (Bitmapped). In the future other format types may be
supported.

Size may be anywhere from 1 to 127 and specifies the appearent pixel height
	of the font.  For example, the extent of "helv.B18N" is 22 pixels, however
	the font appears to be 18 pixels tall.
	
Currently supported font styles are:
	N  - normal or roman
	B  - bold
	I  - italics or oblique
	R  - reverse italics
	BI - bold italic
	BR - bold reverse italics


==========================================================================
B. Font file structures
==========================================================================
There are several structures that are used in the font layout. Here are
the manifests and definitions:

/* You should include this file in your font creation programs.
   I'll call it:  _g_font.h
 */
-------------- cut and paste in '_g_font.h' ------------------------------
/* _GR_FontStruct.Flags definitions		*/
#define _FONT_TypeMask			0x000F	/* Mask for font type 			*/
#define _FONT_Bitmapped			0x0000	/* Font type: Bitmapped			*/

#define _FONT_IndexPerChar		0x0100
#define _FONT_WidthPerChar		0x0200
#define _FONT_MetricPerChar		0x0400	/* Metrics and Width are exclusive */

#define	_FS_Italic				0x0001
#define	_FS_Oblique				0x0002
#define	_FS_RevItalic			0x0004
#define	_FS_Bold				0x0010

typedef struct {
	short				x, y;
} _PointStruct;

typedef struct {
	_PointStruct		Size;			/* Bytes per line == (Size.x+7)>>3	*/
	signed char			BaseLinePos;
	signed char			LeftBearing;
	int					Width;			
} _FontMetricStruct;

typedef struct {
	int					Status; 		/* For a file, MUST be set to 'QF' */
	unsigned			Flags;
	_PointStruct		Size;
	_PointStruct		Extent;
	unsigned			Spare1;
	unsigned			ImageOffset;	
	unsigned			BPChar;
	unsigned			WidthTabOffset;
	unsigned			Spare2[4];
	int					UnderLinePos;
	int					BaseLinePos;
	int					AsciiOffset;
	int					AsciiLength;
	unsigned			Spare3[2];
} _FontStruct;
--------------------------------- cut ---------------------------------------

Here are the details on the above structure members:

typedef struct {
	int				Status;			
		Font file signature, Must be set to 'QF'
	
	unsigned		Flags;			
		Encoding of font rendering type and information stored in the font file
											
	_PointStruct	Size;			
		For a proportional font, the size of the of the largest character image
			unless the font includes a metrics table
		For non-proportional fonts, the size of	all character images
											
	_PointStruct	Extent;
		For non-proportional fonts, the graphic area for all character images.
			The draw position will be advanced by Extent.x.
			
	unsigned		Spare1;
		Not used in font file, set to 0
		
	unsigned		ImageOffset;	
		if Flags & _FONT_IndexPerChar 
			offset of Image offset table		
		ELSE
			offset of first character image
										
	unsigned		BPChar;
		For non-proportional or fixed metric fonts, 
		 number of bytes per character image
					
	unsigned		WidthTabOffset;
		if Flags & _FONT_WidthPerChar
			offset of Width table
		if Flags & _FONT_MetricPerChar
			offset of Metrics table
		NOTE: _FONT_WidthPerChar and _FONT_MetricsPerChar are exclusive
										
	unsigned		Spare2[4];
		Not used in font file, set to 0
		
	int				UnderLinePos;
		Offset from top of character cell to where an underline would be drawn
		
	int				BaseLinePos;
		Offset from top of character cell to base line
		
	int				AsciiOffset;
		First character defined in font, this will be index 0 for all tables
		
	int				AsciiLength;
		Number of characters in font
		
	unsigned		Spare3[2];
		Not used in font file, set to 0
		
} _FontStruct;


typedef struct {
	short			x, y;
} _PointStruct;

Definitions used in the Flags field of _FontStruct
_FONT_TypeMask
	Mask used for font type
_FONT_Bitmapped
	Font type of Bitmapped

_FONT_IndexPerChar
	The ImageOffset points to a table of offsets (shorts), each offset in the
		table points to the corresponding character image
		
_FONT_WidthPerChar
	WidthTabOffset points to a table of character widths (shorts), each value
		in the table defines the proportional width of its corresponding
		character.
	
_FONT_MetricPerChar
	WidthTabOffset points to an array of _FontMetricStruct's, each entry
		defines the metrics of the corresponding character.
		NOTE: MetricPerChar and WidthPerChar are exclusive.
		

typedef struct {
	_PointStruct	Size;			
		Size of character image.  The bytes per line of the bitmap must be
			(Size.x + 7)>>3 and the total bytes for that character must be a
			minimum of "bytes per line" * Size.y.
	signed char		BaseLinePos;
		Offset from the top of the character image to the base line.  If this 
		value is positive, the top of the character is above the base line, if
		the value is negative, the top of the image will be below the base line.
	signed char		LeftBearing;
		Offset from the left of the character image to the draw position.  If
		this value is positive, the character will be drawn to the right of the
		draw position, and if it is negative, it will be drawn to the left.
	int				Width;			
		Number of pixels to advance the draw position.  This field should
			be 0 if the character does not exist in the font.
} _FontMetricStruct;


The following formats are currently in use...
* For the following examples, assume the declaration contains the headder from
	the font file: _FontStruct FS; 

Font type: bitmapped, non-proportional
    Flags: _FONT_Bitmapped
 Examples: PCterm.B12N, System.B11N
 
FS.Size - describes the size of every character image
FS.Extent - describes the extent of every character, this must be equal to 
	or larger then Size.
FS.ImageOffset - offset of first character image in font

A character image can be found with the following calculation...
 ("AsciiValue" - FS.AsciiOffset) * FS.BPChar + FS.ImageOffset

	 
Font type: Bitmapped, proportional with metrics
	Flags: _FONT_Bitmapped | _FONT_IndexPerChar | _FONT_MetricPerChar 
 Examples: cour.B12BI, helv.B24N, char.B64I, times.B8B
 
FS.Size - not used
FS.Extent - The extent of largest character in font.
FS.ImageOffset - points to a table of short offsets for each character image.
FS.WidthTabOffset - This points to an array of _FontMetricStruct's. The Metric's 
	table contains 1 entry per character in the font.

 
==========================================================================
C. Layout of the file
==========================================================================
Here is the layout of the font file:
In this example, FS is the _FontStruct structure variable and MS[256] is
the _FontMetricStruct structure variable array.

- the _FontStruct structure is ALWAYS first in the file (FS)

- FS.ImageOffset points to a file offset (0 is the start of file) where a
  table of short int (2 byte) offsets are located.
  There should be at least FS.AsciiLength members in this table.
  Each of the offsets in the table point to a file offset where the bitmap
  data for the character (as indexed in the table) is located.

- FS.WidthTabOffset points to a file offset (0 is start of file) where an
  array of _FontMetricStruct members are located.
  There should be at least FS.AsciiLength members in this table.

An example font file:

/windows/fonts/ABCterm010.B09N    
(Bitmapped, 9 points, Normal)

0000000: 46 51 00 05 07 00 08 00 07 00 09 00 00 00 30 07 FQ............0.
0000010: 09 00 30 03 00 00 00 00 00 00 00 00 07 00 07 00 ..0.............
0000020: 00 00 80 00 00 00 00 00 00 10 38 38 7c 38 38 10 ..........88|88.
0000030: 54 28 54 28 54 28 54 48 48 78 48 48 3c 08 08 08 T(T(T(THHxHH<...
0000040: 70 40 60 40 5c 10 18 10 10 38 40 40 38 38 24 38 p@`@\....8@@88$8
0000050: 24 24 40 40 40 78 3c 20 38 20 20 38 28 28 38 10 $$@@@x< 8  8((8.
0000060: 10 7c 10 10 7c 48 68 68 58 48 20 20 20 3c 48 48 .|..|HhhXH   <HH
0000070: 30 20 3c 08 08 08 08 10 10 10 70 70 10 10 10 10 0 <.......pp....
0000080: 10 1c 10 10 10 10 10 10 10 10 1c 10 10 10 7c 10 ..............|.
0000090: 10 10 10 10 00 7c 7c 7c 7c 10 10 10 1c 10 10 10 .....||||.......
00000a0: 10 10 10 10 10 70 10 10 10 10 10 10 10 10 7c 7c .....p........||
00000b0: 10 10 10 10 10 10 10 10 10 10 10 10 10 10 04 08 ................
00000c0: 20 40 20 08 04 7c 40 20 08 04 08 20 40 7c 7c 28  @ ..|@ ... @||(
00000d0: 28 28 28 04 08 7c 10 7c 20 40 18 24 20 78 20 38 (((..|.| @.$ x 8
00000e0: 6c 20 10 00 10 10 10 10 10 00 10 28 28 28 28 28 l .........(((((
00000f0: 7c 28 7c 28 28 10 38 50 38 14 38 10 24 54 28 10 |(|((.8P8.8.$T(.
0000100: 28 54 48 20 50 50 20 54 48 34 18 10 20 08 10 20 (TH PP TH4.. .. 
0000110: 20 20 10 08 20 10 08 08 08 10 20 44 28 7c 28 44   .. ..... D(|(D
0000120: 10 10 7c 10 10 18 10 20 7c 10 38 10 04 04 08 10 ..|.... |.8.....
0000130: 20 40 40 10 28 44 44 44 28 10 10 30 50 10 10 10  @@.(DDD(..0P...
0000140: 7c 38 44 04 18 20 40 7c 7c 04 08 18 04 44 38 08 |8D.. @||....D8.
0000150: 18 28 48 7c 08 08 7c 40 58 64 04 44 38 18 20 40 .(H|..|@Xd.D8. @
0000160: 58 64 44 38 7c 04 08 08 10 20 20 38 44 44 38 44 XdD8|....  8DD8D
0000170: 44 38 38 44 4c 34 04 08 30 10 38 10 00 10 38 10 D88DL4..0.8...8.
0000180: 10 38 10 00 18 10 20 04 08 10 20 10 08 04 7c 00 .8.... ... ...|.
0000190: 7c 40 20 10 08 10 20 40 38 44 08 10 10 00 10 38 |@ ... @8D.....8
00001a0: 44 4c 54 58 40 38 10 28 44 44 7c 44 44 78 24 24 DLTX@8.(DD|DDx$$
00001b0: 38 24 24 78 38 44 40 40 40 44 38 78 24 24 24 24 8$$x8D@@@D8x$$$$
00001c0: 24 78 7c 40 40 78 40 40 7c 7c 40 40 78 40 40 40 $x|@@x@@||@@x@@@
00001d0: 38 44 40 40 4c 44 38 44 44 44 7c 44 44 44 38 10 8D@@LD8DDD|DDD8.
00001e0: 10 10 10 10 38 1c 04 04 04 04 44 38 44 48 50 60 ....8.....D8DHP`
00001f0: 50 48 44 40 40 40 40 40 40 7c 44 44 6c 54 44 44 PHD@@@@@@|DDlTDD
0000200: 44 44 44 64 54 4c 44 44 38 44 44 44 44 44 38 78 DDDdTLDD8DDDDD8x
0000210: 44 44 78 40 40 40 38 44 44 44 44 54 38 04 78 44 DDx@@@8DDDDT8.xD
0000220: 44 78 50 48 44 38 44 40 38 04 44 38 7c 10 10 10 DxPHD8D@8.D8|...
0000230: 10 10 10 44 44 44 44 44 44 38 44 44 44 28 28 28 ...DDDDDD8DDD(((
0000240: 10 44 44 44 54 54 6c 44 44 44 28 10 28 44 44 44 .DDDTTlDDD(.(DDD
0000250: 44 28 10 10 10 10 7c 04 08 10 20 40 7c 38 20 20 D(....|... @|8  
0000260: 20 20 20 38 40 40 20 10 08 04 04 38 08 08 08 08    8@@ ....8....
0000270: 08 38 10 28 44 7c 30 10 08 38 04 3c 44 3c 40 40 .8.(D|0..8.<D<@@
0000280: 58 64 44 64 58 38 44 40 44 38 04 04 34 4c 44 4c XdDdX8D@D8..4LDL
0000290: 34 38 44 7c 40 38 18 24 20 78 20 20 20 34 48 30 48D|@8.$ x   4H0
00002a0: 40 38 44 38 40 40 58 64 44 44 44 10 00 30 10 10 @8D8@@XdDDD..0..
00002b0: 10 38 08 00 18 08 08 08 48 48 30 40 40 44 48 70 .8......HH0@@DHp
00002c0: 48 44 30 10 10 10 10 10 38 68 54 54 54 44 58 64 HD0.....8hTTTDXd
00002d0: 44 44 44 38 44 44 44 38 58 64 64 58 40 40 40 34 DDD8DDD8XddX@@@4
00002e0: 4c 4c 34 04 04 04 58 64 40 40 40 38 40 38 04 78 LL4...Xd@@@8@8.x
00002f0: 20 20 78 20 20 24 18 44 44 44 4c 34 44 44 28 28   x  $.DDDL4DD((
0000300: 10 44 44 54 54 28 44 28 10 28 44 44 44 4c 34 04 .DDTT(D(.(DDDL4.
0000310: 44 38 7c 08 10 20 7c 0c 10 08 30 08 10 0c 10 10 D8|.. |...0.....
0000320: 10 10 10 10 10 60 10 20 18 20 10 60 24 54 48 00 ............$TH.
0000330: 06 00 01 00 00 00 07 00 06 00 07 00 07 00 07 00 ................
0000340: 06 00 07 00 07 00 07 00 06 00 09 00 07 00 07 00 ................
0000350: 06 00 09 00 07 00 07 00 06 00 09 00 07 00 07 00 ................
0000360: 06 00 09 00 07 00 07 00 06 00 04 00 07 00 07 00 ................
0000370: 06 00 06 00 06 00 07 00 06 00 09 00 07 00 07 00 ................
0000380: 06 00 09 00 07 00 07 00 06 00 04 00 07 00 07 00 ................
0000390: 06 00 06 00 04 00 07 00 06 00 06 00 04 00 07 00 ................
00003a0: 06 00 04 00 07 00 07 00 06 00 09 00 07 00 07 00 ................
00003b0: 06 00 01 00 00 00 07 00 06 00 01 00 06 00 07 00 ................
00003c0: 06 00 01 00 04 00 07 00 06 00 01 00 02 00 07 00 ................
00003d0: 06 00 01 00 00 00 07 00 06 00 09 00 07 00 07 00 ................
00003e0: 06 00 09 00 07 00 07 00 06 00 04 00 07 00 07 00 ................
00003f0: 06 00 06 00 04 00 07 00 06 00 09 00 07 00 07 00 ................
0000400: 06 00 08 00 07 00 07 00 06 00 08 00 07 00 07 00 ................
0000410: 06 00 05 00 05 00 07 00 06 00 07 00 07 00 07 00 ................
0000420: 06 00 08 00 07 00 07 00 06 00 01 00 04 00 07 00 ................
0000430: 06 00 01 00 00 00 07 00 06 00 07 00 07 00 07 00 ................
0000440: 06 00 03 00 07 00 07 00 06 00 07 00 07 00 07 00 ................
0000450: 06 00 07 00 07 00 07 00 06 00 07 00 07 00 07 00 ................
0000460: 06 00 07 00 07 00 07 00 06 00 03 00 07 00 07 00 ................
0000470: 06 00 07 00 07 00 07 00 06 00 07 00 07 00 07 00 ................
0000480: 06 00 05 00 06 00 07 00 06 00 05 00 06 00 07 00 ................
0000490: 06 00 03 00 02 00 07 00 06 00 01 00 04 00 07 00 ................
00004a0: 06 00 03 00 02 00 07 00 06 00 07 00 07 00 07 00 ................
00004b0: 06 00 07 00 07 00 07 00 06 00 07 00 07 00 07 00 ................
*
0000500: 06 00 07 00 06 00 07 00 06 00 07 00 06 00 07 00 ................
0000510: 06 00 07 00 07 00 07 00 06 00 03 00 05 00 07 00 ................
0000520: 06 00 07 00 07 00 07 00 06 00 07 00 07 00 07 00 ................
*
00005b0: 06 00 07 00 07 00 07 00 06 00 08 00 07 00 07 00 ................
00005c0: 06 00 07 00 07 00 07 00 06 00 07 00 07 00 07 00 ................
*
0000620: 06 00 03 00 07 00 07 00 06 00 01 00 00 00 07 00 ................
0000630: 06 00 03 00 07 00 07 00 06 00 05 00 05 00 07 00 ................
0000640: 06 00 07 00 07 00 07 00 06 00 05 00 05 00 07 00 ................
*
0000660: 06 00 07 00 07 00 07 00 06 00 07 00 05 00 07 00 ................
0000670: 06 00 07 00 07 00 07 00 06 00 07 00 07 00 07 00 ................
0000680: 06 00 09 00 07 00 07 00 06 00 07 00 07 00 07 00 ................
0000690: 06 00 07 00 07 00 07 00 06 00 05 00 05 00 07 00 ................
00006a0: 06 00 05 00 05 00 07 00 06 00 05 00 05 00 07 00 ................
00006b0: 06 00 07 00 05 00 07 00 06 00 07 00 05 00 07 00 ................
00006c0: 06 00 05 00 05 00 07 00 06 00 05 00 05 00 07 00 ................
00006d0: 06 00 07 00 07 00 07 00 06 00 05 00 05 00 07 00 ................
00006e0: 06 00 05 00 05 00 07 00 06 00 05 00 05 00 07 00 ................
00006f0: 06 00 05 00 05 00 07 00 06 00 07 00 05 00 07 00 ................
0000700: 06 00 05 00 05 00 07 00 06 00 07 00 07 00 07 00 ................
0000710: 06 00 07 00 07 00 07 00 06 00 07 00 07 00 07 00 ................
0000720: 06 00 03 00 07 00 07 00 06 00 01 00 00 00 07 00 ................
0000730: 28 00 29 00 30 00 37 00 40 00 49 00 52 00 5b 00 (.).0.7.@.I.R.[.
0000740: 5f 00 65 00 6e 00 77 00 7b 00 81 00 87 00 8b 00 _.e.n.w.{.......
0000750: 94 00 95 00 96 00 97 00 98 00 99 00 a2 00 ab 00 ................
0000760: af 00 b5 00 be 00 c6 00 ce 00 d3 00 da 00 e2 00 ................
0000770: e3 00 e4 00 eb 00 ee 00 f5 00 fc 00 03 01 0a 01 ................
0000780: 0d 01 14 01 1b 01 20 01 25 01 28 01 29 01 2c 01 ...... .%.(.).,.
0000790: 33 01 3a 01 41 01 48 01 4f 01 56 01 5d 01 64 01 3.:.A.H.O.V.].d.
00007a0: 6b 01 72 01 79 01 80 01 87 01 8e 01 91 01 98 01 k.r.y...........
00007b0: 9f 01 a6 01 ad 01 b4 01 bb 01 c2 01 c9 01 d0 01 ................
00007c0: d7 01 de 01 e5 01 ec 01 f3 01 fa 01 01 02 08 02 ................
00007d0: 0f 02 16 02 1e 02 25 02 2c 02 33 02 3a 02 41 02 ......%.,.3.:.A.
00007e0: 48 02 4f 02 56 02 5d 02 64 02 6b 02 72 02 75 02 H.O.V.].d.k.r.u.
00007f0: 76 02 79 02 7e 02 85 02 8a 02 91 02 96 02 9d 02 v.y.............
0000800: a4 02 ab 02 b2 02 bb 02 c2 02 c9 02 ce 02 d3 02 ................
0000810: d8 02 df 02 e6 02 eb 02 f0 02 f7 02 fc 02 01 03 ................
0000820: 06 03 0b 03 12 03 17 03 1e 03 25 03 2c 03 2f 03 ..........%.,./.

Some notes on the above:

- examine the _FontStruct structure
  Note the ImageOffset:  730h
  Note the WidthTabOffset:  330h

  at 730h, is a table of AsciiLength short ints. Each short int points to
  a bitmap.
     ..  28h, 29h, 30h, 37h, 40h  etc..

  at 330h is an array of AsciiLength _FontMetricStruct members.

- Font files must be no more then 65535 bytes
- A font file may only define characters between 0 and 255, inclusive.

=============================================================================
D. QWindows Font Metrics  ( every . represents a pixel )
=============================================================================

Example 1:
           (a symbol character)

                    Size.x
            <------------------->
                                                      o = the draw position
       ^    .....................    ^
       |    .....................    |                LB = LeftBearing
       |    .......XXXXX.........    |                     (can be negative)
       |    ...........XXXX......    |
  |--> |    .............XXXXX...    |  Size.y        Width = offset in x to
  |    |    .XXXXXXXXXXXXXX......    |                        next draw 
  |    |    .XXXXXXXXXXXXXX......    |                        position.
  |    |_______o______XXXXX_______o_ | ____ baseline
  |         ..........XXXXX......    |
  |         ..........XXXXXXXXX..    v
  |
BaseLinePos

In this example:   Size.x = 21
                   Size.y = 10
                   BaseLinePos = 8
                   LeftBearing = -3
                   Width = 19

Number of bytes per line  = (Size.x + 7) >> 3  = 3  ( right padded with 0's )
Number of bytes in bitmap =  Size.y * (number of bytes per line)

NOTE: In the above example, the Size.x and Size.y of the character include
      blank pixels at the outside of the font. It is NOT necessary to include
      these blank spaces.
   
Therefore, a different way of approaching the same symbol is as follows:

Example 2:
           (a symbol character ... with no padding)

                  Size.x
             <--------------->
                                                      o = the draw position
            .....................     
            .....................                     LB = LeftBearing
       ^    .......XXXXX.........    ^                     (can be negative)
       |    ...........XXXX......    |
  |--> |    .............XXXXX...    |  Size.y        Width = offset in x to
  |    |    .XXXXXXXXXXXXXX......    |                        next draw 
  |    |    .XXXXXXXXXXXXXX......    |                        position.
  |    |_______o______XXXXX_______o_ | ____ baseline
  |         ..........XXXXX......    |
  |         ..........XXXXXXXXX..    v
  |
BaseLinePos

In this example:   Size.x = 18
                   Size.y =  8
                   BaseLinePos = 6
                   LeftBearing = -2
                   Width = 19

Number of bytes per line  = (Size.x + 7) >> 3  = 3  ( right padded with 0's )
Number of bytes in bitmap =  Size.y * (number of bytes per line)

=============================================================================
E. Support Tools
=============================================================================
/* there are several support programs that are useful in testing fonts:
   
  - a QNX Windows program called 'fontdemo' tests a font within QNX windows
  - a program called 'dispqwfont' displays information about a font file. 


/* Here's the source to 'dispqwfont': a simple program that will read a Qnx
   Windows font file and display the data to stdout (including bitmaps).

   It only works with files that have a Metric Table per character
   ( FS.Flags |= _FONT_MetricPerChar )
   Almost all Qnx Windows font files follow this format.

   It is provided as a simple tool to allow you to test your font files.
   (and examine existing font files)
 */

-------------------- cut and paste in 'dispqwfont.c' ----------------------
#ifdef __USAGE
%C	fontfile*
#endif

/* make the program with:
     cc dispqwfont.c -2 -ml -N20k -o dispqwfont
 */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdarg.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "_g_font.h"   /* this is the file described earlier */

#define SIZEOFCHAR  8

#define MAXBYTES 2048  /* probably should be higher .. max of a qwin bitmap */

/* Output file vars *********************************************************/

FILE *fp;

/* QWIN data ****************************************************************/

_FontStruct        FS;            /* header */
_FontMetricStruct  MS[256];       /* metric structure */
unsigned    char qw_map[MAXBYTES];/* the QWin bitmap data */

short int	ImageOffsetTab[256];

/****************************************************************************/

main(argc, argv)
int argc;
char *argv[];
{
int i = argc;

    while ( i-- > 1 ) {
       displayit( argv[i] );
       }
}

/****************************************************************************/

displayit(char *filename)
{
int i;
char tmp[50];
int c;
int ret;
int j, numbytes;

    memset(&MS, 0, sizeof(MS));
    memset(&FS, 0, sizeof(FS));
    memset(&ImageOffsetTab, 0, sizeof(ImageOffsetTab));

    fp = fopen(filename,"rqv");
    if ( fp == NULL ) exit(-1);

    ret=fread( &FS, sizeof(FS), 1, fp );
    if ( ret != 1 ) { printf("Error on fread\n"); exit(-1); }

    /* dump header */
    printf("FILE: %s   Status=%c%c  Flags=0x%x\n", filename,
            (FS.Status >> 8), (FS.Status & 0xff), FS.Flags);
    printf("Size.x= %d   Size.y= %d   Extent.x= %d   Extent.y= %d\n",
            FS.Size.x, FS.Size.y, FS.Extent.x, FS.Extent.y);
    printf("Offset to image table= 0x%x\n", FS.ImageOffset);
    printf("Bytes per char= %d   UnderLine=%d  BaseLine=%d\n",
            FS.BPChar, FS.UnderLinePos, FS.BaseLinePos);
    printf("Offset to metrics table= 0x%x\n", FS.WidthTabOffset);
    printf("Ascii offset= %d   Ascii Length= %d\n", FS.AsciiOffset,
            FS.AsciiLength);

    /* read metrics structures in */
    ret=fseek( fp, (long)FS.WidthTabOffset, SEEK_SET);
    if ( ret != 0 ) { printf("error on fseek\n"); exit(-1); }

    for ( i=0; i < FS.AsciiLength; i++ ) {
        ret=fread( &MS[i], sizeof(_FontMetricStruct), 1, fp );
        if ( ret != 1 ) { printf("Error on fread of metric struct #%d\n",i); exit(-1); }
        }

    /* read the image data */
    ret=fseek( fp, (long)FS.ImageOffset, SEEK_SET);
    if ( ret != 0 ) { printf("error on fseek\n"); exit(-1); }

    ret=fread( &ImageOffsetTab, sizeof(short int), FS.AsciiLength, fp );
    if ( ret != FS.AsciiLength ) { printf("Error on fread of imageoffsettab.\n"); exit(-1); }

    /* now get the bitmap data and display each char */
    for ( i=0; i < FS.AsciiLength; i++ ) {
        if ( ImageOffsetTab[i] != 0 && MS[i].Width != 0 ) {
           ret=fseek( fp, (long)ImageOffsetTab[i], SEEK_SET);
           if ( ret != 0 ) { 
              printf("error on fseek to imageoffsettab[%d]=%d\n",
                      i, ImageOffsetTab[i]);
              exit(-1);
              }
           /* read in    (MS[i].Size.x +7) >>3 * MS[i].Size.y  bytes */
           numbytes = ((MS[i].Size.x +7)>>3) * MS[i].Size.y;
           printf("reading %d bytes at %d\n", numbytes, ImageOffsetTab[i]);
           for ( j=0; j < numbytes; j++ ) {
               qw_map[j] = getc(fp);
               }
           printf("Font metrics for char # %d, ascii=%d\n", i, i+FS.AsciiOffset);
           printf("Metrics:  Size.x=%d  Size.y=%d  BaseLine=%d  Left=%d  Width=%d\n",
                 MS[i].Size.x, MS[i].Size.y, MS[i].BaseLinePos, MS[i].LeftBearing, MS[i].Width);
           display_bitmap("", qw_map, ((MS[i].Size.x + 7)>>3), MS[i].Size.y);
           }
        }
    fclose(fp);
}

/*****************************************************************************/

display_bitmap( char *dstr, char *bitmap, unsigned bytes_per_line, unsigned line_count )
{
int i, j;
char tmp[10];
int lcount = 1;

for ( i=0; i < (bytes_per_line * line_count); i++ ) {
    if ( !(i % bytes_per_line) ) {
       printf("\n%2u ",lcount++);
       }
    binary( bitmap[i], tmp );
    printf("%8.8s",tmp);
    }
printf("\n");
}

binary(char val, char *tmp)
{
char b[10];
int i;

    memset( b, 0, sizeof(b) );
    for ( i=0; i < SIZEOFCHAR; i++ ) {
        if ( val & 1 )
           b[SIZEOFCHAR-1-i] = '*';
        else
           b[SIZEOFCHAR-1-i] = ' ';
        val >>= 1;
        }
    strcpy(tmp, b);
}

