// -*- c++ -*-


// PCF File Format from /xc/lib/font/bitmap/pcfread.c,pcfwrite.c


// miscellaneous definition ///////////////////////////////////////////////////

/* Type names are 'TypeSize_Endien'.
 *	name		Type		Size(bits)	Endien
 *	---------------	---------------	---------------	-------
 *	char8		char		8		none
 *	bool8		bool		8		none
 *	int32_little	int		32		big
 *	type32_little	type32		32		big
 *	format32_little	format32	32		big
 * etc.
 * In the *SECTION*, the endieness is determined by the format.byte
 */


enum type32 {
  PCF_PROPERTIES	= (1 << 0),
  PCF_ACCELERATORS	= (1 << 1),
  PCF_METRICS		= (1 << 2),
  PCF_BITMAPS		= (1 << 3),
  PCF_INK_METRICS	= (1 << 4),
  PCF_BDF_ENCODINGS	= (1 << 5),
  PCF_SWIDTHS		= (1 << 6),
  PCF_GLYPH_NAMES	= (1 << 7),
  PCF_BDF_ACCELERATORS	= (1 << 8),
};

struct format32 {
  uint32	format:24;	// format                                << 8
  uint32	dummy:2;	// = 0 padding                           << 6
  uint32	scan:2;		// bitmap scan unit is (1 << scan) bytes << 4
  uint32	bit:1;		// 0:LSBbit first, 1:MSBit first         << 3
  uint32	byte:1;		// 0:LSByte first, 1:MSByte first        << 2
  uint32	glyph:2;	// glyph pad is (1 << glyph) bytes       << 0
};
// format32.format is one of the followings
#define PCF_DEFAULT_FORMAT     0
#define PCF_INKBOUNDS          2
#define PCF_ACCEL_W_INKBOUNDS  1
#define PCF_COMPRESSED_METRICS 1

struct metric_t
{
  int16	leftSideBearing;
  int16	rightSideBearing;
  int16	characterWidth;
  int16	ascent;
  int16	descent;
  int16	attributes;
};
struct compressedMetric_t
{
  uint8	leftSideBearing;	// - 0x80 == metric_t.leftSideBearing
  uint8	rightSideBearing;	// - 0x80 == metric_t.rightSideBearing
  uint8	characterWidth;		// - 0x80 == metric_t.characterWidth
  uint8	ascent;			// - 0x80 == metric_t.ascent
  uint8	descent;		// - 0x80 == metric_t.descent
};

#define GLYPHPADOPTIONS 4	// 1, 2, 4, or 8

#define MAKE_CHARCODE(row,col)	(row * 256 + col)


// begining of the PCF file ///////////////////////////////////////////////////

// table of contents
char8[4]	version = { 'p', 'c', 'f', 1 };
int32_little	nTables;
struct table_t {	// sections
  type32_little	type;	// type of this section
  format32_little	format;	// format of this section
  int32_little	size;	// size of this section
  int32_little	offset;	// offset of this section from the begining of the file
}		tables[nTables];

/*** SECTION ***/
// properties section (tables[i].type = PCF_PROPERTIES)
format32_little	format; 	// format.id = PCF_DEFAULT_FORMAT
int32		nProps;
struct {
  int32		name;		// offset from &string[0]
  bool8		isStringProp;	// is this property is string ?
  int32		value;		// isStringProp ? offset from &string[0]
}		props[nProps];
byte8		dummy[3 - ((sizeof(props) + 3) % 4)];	// padding
int32		stringSize;
char8		string[stringSize];	// pointed by property_t.{name,value}

/*** SECTION ***/
// old accelerators section (tables[i].type = PCF_ACCELERATORS)
/* if PCF_BDF_ACCELERATORS section exists, this section is omitted. */
format32_little	format;		// format.id = PCF_DEFAULT_FORMAT
//				//              or PCF_ACCEL_W_INKBOUNDS
bool8		noOverlap;
bool8		constantMetrics;
bool8		terminalFont;
bool8		constantWidth;
bool8		inkInside;
bool8		inkMetrics;
bool8		drawDirection;
bool8		dummy;		// padding
int32		fontAscent;
int32		fontDescent;
int32		maxOverlap;
metric_t	minBounds;
metric_t	maxBounds;
#if format.id == PCF_ACCEL_W_INKBOUNDS
metric_t	ink_minBounds;
metric_t	ink_maxBounds;
#endif

/*** SECTION ***/
// metrics section (tables[i].type = PCF_METRICS)
format32_little	format;		// format.id = PCF_DEFAULT_FORMAT
//				//          or PCF_COMPRESSEDMETRICS
#if format.id == PCF_DEFAULT_FORMAT
int32		nMetrics;
metric_t	metrics[nMetrics];
#else
int16		nMetrics;
compressedMetric_t	cmetrics[nMetrics];
#end

/*** SECTION ***/
// bitmaps section (tables[i].type = PCF_BITMAPS)
format32_little	format;		// format.id = PCF_DEFAULT_FORMAT
int32		nBitmaps;	// == nMetrics
uint32		bitmapOffsets[nBitmaps];
uint32		bitmapSizes[GLYPHPADOPTIONS];
byte8		bitmaps[bitmapSizes[format.glyph]];
/* if (format.bit != THIS_MACHINE.bit)
 *   BitOrderInvert(bitmaps, sizeof(bitmaps));
 * if ((format.bit == format.byte) != 
 *     (THIS_MACHINE.bit == THIS_MACHINE.byte)) {
 *   switch (1 << (THIS_MACHINE.bit == THIS_MACHINE.byte ?
 *                 format.scan : THIS_MACHINE.scan)) {
 *     case 1: break;
 *     case 2: TwoByteSwap(bitmaps, sizeof(bitmaps)); break;
 *     case 4: FourByteSwap(bitmaps, sizeof(bitmaps)); break;
 *   }
 * } */
/* each line of the bitmaps is aligned by 1<<format.glyph bytes. */

/*** SECTION ***/
// ink metrics secion (tables[i].type = PCF_INK_METRICS)
/* this section may be omitted */
/* same as PCF_METRICS */

/*** SECTION ***/
// encodings section (tables[i].type = PCF_BDF_ENCODINGS)
format32_little	format;		// format.id = PCF_DEFAULT_FORMAT
int16		firstCol;
int16		lastCol;
int16		firstRow;
int16		lastRow;
int16		defaultCh;	// default char or NO_SUCH_CHAR (= -1)
int16		encodings[n];
/*            |0 firstCol  lastCol 255
 * row\column |v v         v       v
 * -----------+---------------------
 *         0->|
 *  firstRow->|A B C D E F G H
 *            |I J K L M N O P
 *            |Q R S T U V W X
 *   lastRow->|Y Z a b c d e f
 *       255->|
 *
 * The charcode MAKE_CHARCODE(firstCol, firstRow)'s metrics is metrics[B].
 * And, encodings = { B,C,D,E,F,G, J,K,L,M,N,O, R,S,T,U,V,W, Z,a,b,c,d,e, };
 * If Z == 0xffff, then the charcode MAKE_CHARCODE(firstCol, lastRow) does not
 * exist. */

/*** SECTION ***/
// swidths section (tables[i].type = PCF_SWIDTHS)
/* this section may be omitted */
format32_little	format;		// format.id = PCF_DEFAULT_FORMAT
int32		nSwidths;	// == nMetrics
int32		swidths[nSwidths];

/*** SECTION ***/
// glyph names section (tables[i].type = PCF_GLYPH_NAMES)
/* this section may be omitted */
format32_little	format;		// format.id = PCF_DEFAULT_FORMAT
int32		nGlyphNames;	// == nMetrics
int32		glyphNameOffsets[nGlyphNames];	// offset from &glyph_names[0]
int32		glyphNamesSize;
char8		glyphNames[glyphNamesSize];    // pointed by glyphNameOffsets[]

/*** SECTION ***/
// BDF style accelerators section (tables[i].type = PCF_BDF_ACCELERATORS)
/* if PCF_ACCELERATORS section exists, this section is omitted. */
/* same as PCF_ACCELERATORS */

// end of the PCF file ////////////////////////////////////////////////////////
