[File] [PATCH] of Magdir/fonts for Windows font *.fnt

Jörg Jenderek joerg.jen.der.ek at gmx.net
Mon Feb 1 23:34:25 UTC 2021


Hello,

some days ago just for interest i inspect the FONT sub directory on
my Windows systems. Such samples with FON file name extension are
Windows fonts.

According to documentation the new executable DLL format is just a
container for Windows FNT fonts.

Unfortunately i only find 1 dedicated FNT sample. That was
SAMPLE.FNT. The other examples are generated from related FON
examples. I use Joel Toivonen font editor Fony.exe to load FON sample
and save the fonts as FNT format with version 2. I also use a hex
editor to look inside FON samples and tried to extract with help of
the dd command the embedded FNT samples. I also use Bert Huijbin
FONTEDIT.EXE to save fonts as FNT examples. I also use Simon
Tatham python fonts tools mkwinfont to generate some FNT samples
especially with version 3 from FD text font descriptions.


When running file command on such font samples and other test samples
i get an output like:

abydos.ico:        MS Windows icon resource - 5 icons,
		   32x32, 32 bits/pixel, 48x48, 32 bits/pixel
batman_c.pi2:      data
Bodoni Bd BT.fnt:  data
CYRILC.fnt:        data
devgem7.pi3:       data
ebrima-3props.fnt: data
ega80woa.fnt:      Intel ia64 COFF object file,
		   no line number info, not stripped, 4207 sections,
		   symbol offset=0x6f432029, 1769109872 symbols,
		   optional header size 26727
pal4-a.tga:        Targa image data - Map (12) - RLE 127 x 64 x 8
pal4.tga:          Targa image data - Map (256) 127 x 64 x 8 - top
SAMPLE.FNT:        data
svgafix.fnt:       Intel ia64 COFF object file,
		   no line number info, not stripped, 4627 sections,
		   symbol offset=0x6f432029, 1769109872 symbols,
		   optional header size 26727
tektite.fnt:       data

For comparison reason i run the file format identification utility
TrID ( See https://mark0.net/soft-trid-e.html).
Luckily TrID tool identifies such fonts as "Windows Font resource".
This list the used file name extension and with -v option the related
URL pointing to used file format information (See appended
fnt_trid.txt.gz)
The FNT Font File Format is described inside the Windows 1.03
Programmer's Reference found as windows-1.03-sdk-prgref-1986.pdf.
That is mentioned on FNT (Windows Font) page on file formats archive
team web site. That is now expressed inside Magdir/fonts by comment
lines like:
# URL:	http://fileformats.archiveteam.org/wiki/FNT_(Windows_Font)
# Reference:	http://www.os2museum.com/files/docs/win10sdk/
# windows-1.03-sdk-prgref-1986.pdf

Unfortunately the FNT has no real characteristic magic pattern. The
only unique non-nil pattern is the dfVersion value. So i encapsulate
the displaying part inside the sub function fnt-font. That displays
Windows fnt font information like font name, pixel sizes, dpi,
copyright message. This function starts like:
 0	name		fnt-font
 >1		ubyte	x		Windows font, version %u
To show a user defined font mime type and file name extension for
these font i add more lines inside Magdir/fonts afterwards like:
 !:mime	font/x-ms-fnt
 !:ext	fnt

For debugging purpose the two byte little endian dfVersion could be
shown by line like
 >0		uleshort	x		\b, 0x%x dfVersion
According to documentation valid values are 0100H, 0200H or 0300H.

Then the file size is stored as a 4 byte little endian value dfSize.
Since a font can contain a maximum of 255 characters and a few bytes
are required per character description, this size is usually in the
thousands ( example values are like 1034 2316  2697 3951 4207 5592
8285 9246 10272). Since the file header alone is more than 100 bytes,
the size of a theoretically minimal FNT file with only one character
is larger than 100. This information is shown by line like
 >2		ulelong		x		\b, %u bytes

At offset 105 the offset of the font (face) name string is stored as
4 byte little endian integer dfFace. Because such information is of
technical interest and not wanted by "normal" users" i add the
displaying magic line as comment line like:
 #>105		ulelong		x		\b, 0x%x dfFace
But i use that offset to show the stored font name (like Courier
Fixedsys MS\400Sans\400Serif Small\040Fonts System Terminal Tektite)
by line like:
 >(105.l)	string		x		%s

Many values inside FNT examples are stored as 2 byte little endian
integer. So in theory a maximal unsigned value of 65535 could be
stored. But we see that many short values like width and height of
the characters ( dfPixWidth and  dfPixHeight are low like 0 3 6 8 12
13 16 20). These dimensions are shown by lines like:
 >86		uleshort	x		%ux
 >88		uleshort	x		\b%u

At offset 66 the type of font file is stored as 2 byte little endian
value dfType.
For a vector font file the first bit of low-order byte is 1, where as
for bitmap (raster) font file this bit is 0. This information is
shown by lines like:
 #>66		uleshort	x		\b, %x dfType
 >66		uleshort	&0x0001		vector
 >66		uleshort	^0x0001		bitmap

In the version 3 header contains 31 extra bytes. There at offset 118
flags, which define the format of the Glyph bitmap is stored
as 4 byte little endian integer dfFlags. So show that additional font
information by lines like:
 >0		ubeshort	>2
 #>>118		ulelong		x		\b, 0x%x dfFlags
 >>118		ulelong		&0x00000001	\b, fixed
 >>118		ulelong		&0x00000002	\b, proportional
 >>118		ulelong		&0x00000004	\b, ABC fixed
 >>118		ulelong		&0x00000008	\b, ABC proportional
 >>118		ulelong		&0x00000010	\b, 1 color
 >>118		ulelong		&0x00000020	\b, 16 color
 >>118		ulelong		&0x00000040	\b, 256 color
 >>118		ulelong		&0x00000080	\b, RGB color

At offset 6 a copyright string dfCopyright with 60 bytes is stored.
For many examples this string looks like "Copyright (C) Microsoft
Corp 1991.  All rights reserved." or "(c) Copyright Bitstream Inc.
1984. All rights reserved." If this string is short then the
remaining bytes of string are often padded with nil bytes.
When i use the HB Font editor i can leave this string filled empty
(all bytes nil) like for example "Bodoni Bd BT.fnt" or can use a 59
byte string. Or for some version 1 snuz fonts like CYRILC.fnt,
GOTHGRT.fnt and GREEKP.fnt the message string is padded at the end
with space characters. So show that copy right message by line like:
 >6	       string		>\037		"%.60s"

Before calling sub routine fnt-font i must do some checks. To skip MS
Windows ICOns and some ISO 9660 CD-ROM images i check for valid low
version value dfVersion in range 1-3 by lines like
 0		ubeshort	<4
 >0		ubeshort	>0
To skip GEM Image data and DEGAS bitmap *.pi2 *.pi3 i look for valid
low dfItalic value by additional line like:
 >>80		ubyte		<2
To skip Targa image pal4.tga by looking for valid high file size
instead 1 i add additional line like:
 >>>2		ulelong		>119
To skip Targa image pal4-a.tga by looking for valid low file size
instead 201326601 is use additional lines like
 >>>>2		ulelong		<201326601
 >>>>>0	use		fnt-font

After applying the above mentioned modifications by patch
file-5.39-fonts-fnt.diff, then i get a more precise output with -k
option like:

abydos.ico:        MS Windows icon resource - 5 icons,
		   32x32, 32 bits/pixel, 48x48, 32 bits/pixel
batman_c.pi2:      data
Bodoni Bd BT.fnt:  Windows font, version 3, 5429 bytes
       	  	   Bodoni Bd BT 0x13 bitmap, 96x96 dpi,
		   proportional, 1 color
CYRILC.fnt:        Windows font, version 1, 5216 bytes
		   Hershey Cyrillic Complex 0x32 vector, 3x2 dpi
		   "snuz fonts"
devgem7.pi3:       data
ebrima-3props.fnt: Windows font, version 3, 6865 bytes
		   Ebrima 0x17 bitmap, 96x96 dpi
		   "HB Fonteditor",
		   italic, underline, strikeout, proportional
ega80woa.fnt:      Intel ia64 COFF object file,
		   no line number info, not stripped, 4207 sections,
		   symbol offset=0x6f432029, 1769109872 symbols,
		   optional header size 26727
		   Windows font, version 2, 4207 bytes
		   Terminal 8x12 bitmap, 96x72 dpi
		   "(c) Copyright Bitstream Inc. 1984.
		   All rights reserved."
pal4-a.tga:        Targa image data - Map (12) - RLE 127 x 64 x 8
pal4.tga:          Targa image data - Map (256) 127 x 64 x 8 - top
SAMPLE.FNT:        Windows font, version 3, 4763 bytes
		   Tester 8x12 bitmap, 12x12 dpi
		   "Microsoft Corporation Inc", fixed
svgafix.fnt:       Intel ia64 COFF object file,
		   no line number info, not stripped, 4627 sections,
		   symbol offset=0x6f432029, 1769109872 symbols,
		   optional header size 26727
		   Windows font, version 2, 4627 bytes
		   Fixedsys 8x16 bitmap, 96x96 dpi
		   "(c) Copyright Bitstream Inc. 1984.
		   All rights reserved."
tektite.fnt:       Windows font, version 3, 9408 bytes
		   Tektite 9x15 bitmap, 100x100 dpi
		   "Portions copyright 1991,1993,1998
		   clySmic Software.", fixed

I hope my diff file can be applied in future version of
file utility.

With best wishes
Jörg Jenderek
--
Jörg Jenderek




















-------------- next part --------------
--- file-5.39/magic/Magdir/fonts.old	2020-05-31 10:34:40 +0000
+++ file-5.39/magic/Magdir/fonts	2021-02-01 15:18:46 +0000
@@ -129,4 +129,162 @@
 4098	string		DOSFONT		DOSFONT2 encrypted font data
 
+# From:		Joerg Jenderek
+# URL:		http://fileformats.archiveteam.org/wiki/FNT_(Windows_Font)
+# Reference:	http://www.os2museum.com/files/docs/win10sdk/windows-1.03-sdk-prgref-1986.pdf
+# Note:		verified by `python dewinfont -o SAMPLE.FD SAMPLE.FNT`
+# check for valid low version value dfVersion in range 1-3
+0		ubeshort	<4
+# skip MS Windows ICOns and some ISO 9660 CD-ROM images
+>0		ubeshort	>0
+# skip GEM Image data and DEGAS bitmap *.pi2 *.pi3 by looking for valid dfItalic value
+>>80		ubyte		<2
+# skip Targa image pal4.tga by looking for valid high file size instead 1
+>>>2		ulelong		>119
+# skip Targa image pal4-a.tga by looking for valid low file size instead 201326601
+>>>>2		ulelong		<201326601
+>>>>>0	use		fnt-font
+#	display Windows fnt font information like font name, pixel sizes, dpi, copyright message
+0	name		fnt-font
+# FontDirEntry
+>1		ubyte	x		Windows font, version %u
+# dfVersion; the version of the file: 0100H 0200H or 0300H
+#>0		uleshort	x		\b, 0x%x dfVersion
+!:mime	font/x-ms-fnt
+!:ext	fnt
+# dfSize; the total file size in bytes like: 1034 2316 2697 3951 4207 5592 8285 9246 10272
+>2		ulelong		x		\b, %u bytes
+# face name like: Courier Fixedsys MS\400Sans\400Serif Small\040Fonts System Terminal Tektite
+>(105.l)	string		x		%s
+# dfPixWidth; for vector fonts, specifies the width of the grid on which the font was digitized
+# For raster fonts, if dfPixWidth is nonzero, it represents the width forall the characters in the bitmap
+# if it is zero, the font has variable width characters whose widths are specified in the dfCharTable array
+>86		uleshort	x		%ux
+# dfPixHeight; height of the character bitmap (raster fonts), or the height of the grid on which a vector font was digitized like: 3 6 8 12 13 16 20 
+>88		uleshort	x		\b%u
+>66		uleshort	&0x0001		vector
+>66		uleshort	^0x0001		bitmap
+# dfHorizRes; specifying the nominal horizontal resolution (dots-per-inch) at which this character set was digitized
+>72		uleshort	x		\b, %ux
+# dfVertRes; specifying the nominal vertical resolution (dots-per-inch) at which this character set was digitized like: 48 72 96 120
+>70		uleshort	x		\b%u dpi
+# dfWeight; weight of the characters in the character definition data, on a scale of 1 to 1000 like: 400 700
+# A dfWeight of 400 specifies a regular weight
+#>83		uleshort	!400		\b, %u dfWeight
+# dfCopyright; 60 bytes specifying copyright information like: Copyright (C) Microsoft Corp 1991.  All rights reserved.
+# But can be nul when created by Fony.exe from TTF like "Bodoni Bd BT.fnt" or
+# space char instead nul at end like in version 1 snuz fonts CYRILC.fnt GREEKP.fnt GOTHGRT.fnt
+>6	       string		>\037		"%.60s"
+# dfType; the type of font file
+# If the low-order bit of the word is 0, it is a bitmap (rastor) font file. If the low-order bit is 1 , it is a vector font file
+# The second bit is reserved and must be zero.
+# If no bits follow in the file and the bits are located in memory at a fixed address specified in dfBitsOffset, the third bit is set to 1; otherwise, the bit is set to 0
+# The high-order bit of the low byte is set if the font was realized by a device. The remaining bits in the low byte are reserved and set to zero
+#>66		uleshort	x		\b, %x dfType
+>66		uleshort	&0x0004		\b, fixed address
+# The high byte is reserved for device use and will always be set to zero for GDI-realized standard fonts.
+# Physical fonts with the high-order bit of the low byte set may use this byte to describe themselves.
+>66		uleshort	&0x0080		\b, device
+>>66		uleshort&0xFF00	x		0x%x
+# dfPoints; the nominal point size at which this character set looks best like: 2 4 8 9 10 12
+#>68		uleshort	x		\b, %u dfPoints
+# dfAscent; the distance from the top of a character definition cell to the baseline of the typographical font like: 2 5 7 10 11 13 16
+#>74		uleshort	x		\b, %u dfAscent
+# dfInternalLeading; specifies the amount of leading inside the bounds set by dfPixHeight. Accent marks may occur in this area. This may be zero at the designer's option
+# like: 0 1 3 4
+#>76		uleshort	>0		\b, %u dfInternalLeading
+# dfExternalLeading; specifies the amount of extra leading that the designer requests the application add between rows like: 0 1
+#>78		uleshort	>0		\b, %u dfExternalLeading
+# dfItalic; specifying whether or not the character definition data represent an italic font. The low-order bit is 1 if the flag is set. All the other bits are 0.
+>80		ubyte		=1		\b, italic
+# dfUnderline; specifying whether or not the character definition data represent an underlined font. The low-order bit is 1 if the flag is set. All the other bits are 0
+>81		ubyte		=1		\b, underline
+# dfStrikeOut; specifying whether or not the character definition data represent a struckout font. The low-order bit is 1 if the flag is set. All the other bits are 0
+>82		ubyte		=1		\b, strikeout
+# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wmf/0d0b32ac-a836-4bd2-a112-b6000a1b4fc9
+# dfCharSet; the character set defined by this font like: 0 134 136 161 162 204 222 255
+#>85		ubyte		x		\b, %u dfCharSet
+# dfPitchAndFamily; Specifies the pitch and font family. The low bit is set if the font is variable pitch.
+#>90		ubyte		>0		\b, 0x%x dfPitchAndFamily
+# The high four bits give the family name of the font. 
+# FF_DONTCARE (0<<4)	Don't care or don't know.
+# FF_ROMAN (1<<4)	Proportionally spaced fonts with serifs
+# FF_SWISS (2<<4)	Proportionally spaced fonts without serifs
+# FF_MODERN (3<<4)	Fixed-pitch fonts.
+# FF_SCRIPT (4<<4)	Cursive, etc.
+# FF_DECORATIVE (5<<4)	Old English, etc.
+# dfAvgWidth; the width of characters in the font. For fixed-pitch fonts, this is the same as dfPixWidth.
+# For variable-pitch fonts, this is the width of the character X like: 2 4 8 9 11 15 16 20
+#>91		uleshort	x		\b, %u dfAvgWidth
+# dfMaxWidth; the maximum pixel width of any character in the font like: 2 4 8 9 14 16 17 33 40
+# For fixed-pitch fonts, this is simply dfPixWidth.
+#>93		uleshort	x		\b, %u dfMaxWidth
+# dfFirstChar; the first character code defined by this font. Character definitions are stored only for the characters actually present in a font.
+#>95		ubyte		>0		\b, %u dfFirstChar
+# dfLastChar; the last character code defined by this font. Note that all the characters with codes between dfFirstChar and dfLastChar must be present in the font
+#>96		ubyte		<255		\b, %u dfLastChar
+# dfDefaultChar; the character to substitute whenever a string contains a character out of the range.
+# The character is given relative to dfFirstChar so that dfDefaultChar is the actual value of the character, less dfFirstChar.
+# The dfDefaultChar should indicate a special character that is not a space.
+#>97		ubyte		!0		\b, %u dfDefaultChar
+# dfBreakChar; the character that will define word breaks. This character defines word breaks for word wrapping and word spacing justification.
+# The character is given relative to dfFirstChar so that dfBreakChar is the actual value of the character, less that of dfFirstChar.
+# The dfBreakChar is normally (32 - dfFirstChar), which is an ASCII space.
+#>98		ubyte		!32		\b, %u dfBreakChar
+# dfWidthBytes; number of bytes in each row of the bitmap. This is always even, so that the rows start on WORD boundaries. For vector fonts, this field has no meaning
+# like: 42 128 185 189 224 247 252 254 268 508 509 517 659 1544
+#>99		uleshort	x		\b, %u dfWidthBytes
+# dfDevice; the offset in the file to the string giving the device name. For a generic font, this value is zero.
+# like: 0
+#>101		ulelong		>0		\b, 0x%x dfDevice
+# dfFace; the offset in the file to the null-terminated string that names the face like: 0x694 0x1294 0x20b4 0x24b8 0xf9fa
+#>105		ulelong		x		\b, 0x%x dfFace
+# dfBitsPointer; absolute machine address of the bitmap. This is set by GDI at load time. The dfBitsPointer is guaranteed to be even.
+# like: 0
+>109		ulelong		!0		\b, 0x%x dfBitsPointer
+# dfBitsOffset; the offset in the file to the beginning of the bitmap information. If the 04H bit in the dfType is set, then dfBitsOffset is an absolute address
+# like: 0x3fa 0x3fe x3fe0x43a 0x472 0x47a 0x658 0x69a
+#>113		ulelong		x		\b, 0x%x dfBitsOffset
+# only for valid low version value 1
+>0		ubeshort	<2
+# dfCharOffset; For proportionally spaced raster fonts, the offset from the start of each bitmap row for each character in the set. 
+# like: 0x0 0x100 0x300 0x400 0x800 0x900 0xb00 0x7e00
+#>>117		uleshort	x		\b, 0x%x dfCharOffset
+# discrepancy documentation for version 2
+# https://jeffpar.github.io/kbarchive/kb/065/Q65123/
+# 31 extra bytes in the version 3 header
+>0		ubeshort	>2
+# dfReserved; 1 byte, only used for word alignment like: 0
+#>>117		ubyte		!0		\b, %u dfReserved
+# dfFlags; the bits flags, which are additionalflags that define the format of the Glyph bitmap
+#>>118		ulelong		x		\b, 0x%x dfFlags
+# DFF_FIXED; font is fixed pitch
+>>118		ulelong		&0x00000001	\b, fixed
+# DFF_PROPORTIONAL; font is proportional pitch
+>>118		ulelong		&0x00000002	\b, proportional
+# DFF_ABCFIXED; font is an ABC fixed font
+>>118		ulelong		&0x00000004	\b, ABC fixed
+# DFF_ABCPROPORTIONAL; font is an ABC proportional font
+>>118		ulelong		&0x00000008	\b, ABC proportional
+# DFF_1COLOR; font is one color
+>>118		ulelong		&0x00000010	\b, 1 color
+# DFF_16COLOR; font is 16 color
+>>118		ulelong		&0x00000020	\b, 16 color
+# DFF_256COLOR; font is 256 color
+>>118		ulelong		&0x00000040	\b, 256 color
+# DFF_RGBCOLOR; font is RGB color
+>>118		ulelong		&0x00000080	\b, RGB color
+# dfAspace; the global A space, if any. The dfAspace is the distance from the current position to the left edge of the bitmap.
+>>122		uleshort	>0		\b, %u dfAspace
+# dfBspace; the global B space, if any. The dfBspace is the width of the character.
+>>124		uleshort	>0		\b, %u dfBspace
+# dfCspace; the global C space, if any. The dfCspace is the distance from the right edge of the bitmap to the new current position
+>>126		uleshort	>0		\b, %u dfCspace
+# dfColorPointer; 4 bytes specifying the offset to the color table for color fonts, if any
+>>128		ulelong		>0		\b, 0x%x dfColorPointer
+# dfReserved1; 16 bytes, not used like 0 for version 3
+#>>132		ulequad		!0		\b, 0x%llx dfReserved1
+# dfCharTable
+#>>148		ubequad		>0		\b, dfCharTable 0x%llx...
+
 # From: Joerg Jenderek
 # URL: http://fileformats.archiveteam.org/wiki/GEM_bitmap_font
-------------- next part --------------
A non-text attachment was scrubbed...
Name: fnt_trid.txt.gz
Type: application/x-gzip
Size: 1330 bytes
Desc: not available
URL: <https://mailman.astron.com/pipermail/file/attachments/20210202/8c7955b6/attachment.bin>


More information about the File mailing list