windows-nt/Source/XPSP1/NT/base/ntsetup/mpk/displib/font.c
2020-09-26 16:20:57 +08:00

1036 lines
27 KiB
C

#include <dos.h>
#include <share.h>
#include <stddef.h>
#include <malloc.h>
#include <string.h>
#include <mytypes.h>
#include <misclib.h>
#include <displib.h>
#include "bootfont.h"
//
// The following structures and constants are used in font files:
// DOS image header
// OS/2 image header
// OS/2 executable resource information structure
// OS/2 executable resource name information structure
//
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
USHORT e_magic; // Magic number
USHORT e_cblp; // Bytes on last page of file
USHORT e_cp; // Pages in file
USHORT e_crlc; // Relocations
USHORT e_cparhdr; // Size of header in paragraphs
USHORT e_minalloc; // Minimum extra paragraphs needed
USHORT e_maxalloc; // Maximum extra paragraphs needed
USHORT e_ss; // Initial (relative) SS value
USHORT e_sp; // Initial SP value
USHORT e_csum; // Checksum
USHORT e_ip; // Initial IP value
USHORT e_cs; // Initial (relative) CS value
USHORT e_lfarlc; // File address of relocation table
USHORT e_ovno; // Overlay number
USHORT e_res[4]; // Reserved words
USHORT e_oemid; // OEM identifier (for e_oeminfo)
USHORT e_oeminfo; // OEM information; e_oemid specific
USHORT e_res2[10]; // Reserved words
ULONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER;
#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
typedef struct _IMAGE_OS2_HEADER { // OS/2 .EXE header
USHORT ne_magic; // Magic number
CHAR ne_ver; // Version number
CHAR ne_rev; // Revision number
USHORT ne_enttab; // Offset of Entry Table
USHORT ne_cbenttab; // Number of bytes in Entry Table
long ne_crc; // Checksum of whole file
USHORT ne_flags; // Flag word
USHORT ne_autodata; // Automatic data segment number
USHORT ne_heap; // Initial heap allocation
USHORT ne_stack; // Initial stack allocation
long ne_csip; // Initial CS:IP setting
long ne_sssp; // Initial SS:SP setting
USHORT ne_cseg; // Count of file segments
USHORT ne_cmod; // Entries in Module Reference Table
USHORT ne_cbnrestab; // Size of non-resident name table
USHORT ne_segtab; // Offset of Segment Table
USHORT ne_rsrctab; // Offset of Resource Table
USHORT ne_restab; // Offset of resident name table
USHORT ne_modtab; // Offset of Module Reference Table
USHORT ne_imptab; // Offset of Imported Names Table
long ne_nrestab; // Offset of Non-resident Names Table
USHORT ne_cmovent; // Count of movable entries
USHORT ne_align; // Segment alignment shift count
USHORT ne_cres; // Count of resource segments
UCHAR ne_exetyp; // Target Operating system
UCHAR ne_flagsothers; // Other .EXE flags
USHORT ne_pretthunks; // offset to return thunks
USHORT ne_psegrefbytes; // offset to segment ref. bytes
USHORT ne_swaparea; // Minimum code swap area size
USHORT ne_expver; // Expected Windows version number
} IMAGE_OS2_HEADER;
#define IMAGE_OS2_SIGNATURE 0x454E // NE
typedef struct _RESOURCE_TYPE_INFORMATION {
USHORT Ident;
USHORT Number;
long Proc;
} RESOURCE_TYPE_INFORMATION;
#define FONT_DIRECTORY 0x8007
#define FONT_RESOURCE 0x8008
typedef struct _RESOURCE_NAME_INFORMATION {
USHORT Offset;
USHORT Length;
USHORT Flags;
USHORT Ident;
USHORT Handle;
USHORT Usage;
} RESOURCE_NAME_INFORMATION;
#pragma pack(1)
typedef struct _OEM_FONT_FILE_HEADER {
USHORT Version;
ULONG FileSize;
UCHAR Copyright[60];
USHORT Type;
USHORT Points;
USHORT VerticalResolution;
USHORT HorizontalResolution;
USHORT Ascent;
USHORT InternalLeading;
USHORT ExternalLeading;
UCHAR Italic;
UCHAR Underline;
UCHAR StrikeOut;
USHORT Weight;
UCHAR CharacterSet;
USHORT PixelWidth;
USHORT PixelHeight;
UCHAR Family;
USHORT AverageWidth;
USHORT MaximumWidth;
UCHAR FirstCharacter;
UCHAR LastCharacter;
UCHAR DefaultCharacter;
UCHAR BreakCharacter;
USHORT WidthInBytes;
ULONG Device;
ULONG Face;
ULONG BitsPointer;
ULONG BitsOffset;
UCHAR Filler;
} OEM_FONT_FILE_HEADER;
#pragma pack()
#define OEM_FONT_VERSION 0x200
#define OEM_FONT_TYPE 0
#define OEM_FONT_CHARACTER_SET 255
#define OEM_FONT_FAMILY (3 << 4)
#define FONT_WIDTH 8
typedef struct _FONT_CHAR {
USHORT Width;
USHORT Offset;
} FONT_CHAR;
union {
IMAGE_DOS_HEADER DosHeader;
IMAGE_OS2_HEADER Os2Header;
OEM_FONT_FILE_HEADER FontHeader;
RESOURCE_TYPE_INFORMATION ResourceType;
RESOURCE_NAME_INFORMATION ResourceName;
BOOTFONTBIN_HEADER BfbHeader;
} FontHeaders;
FONT_CHAR *FontCharMap;
BYTE *FontCharData;
unsigned FontDataBaseOffset;
BYTE GlyphHeight;
BYTE FontFirstChar,FontLastChar,FontDefaultChar;
BYTE TopPad,BottomPad;
unsigned BootfontFileHandle = (unsigned)(-1);
UCHAR PendingLeadByte;
unsigned SbcsCharCount;
unsigned DbcsCharCount;
ULONG SbcsFileOffset;
ULONG DbcsFileOffset;
#define DBCS_FIRST_LEAD 0x81
#define DBCS_LAST_LEAD 0xfe
#define DBCS_FIRST_TRAIL 0x40
#define DBCS_LAST_TRAIL 0xfe
//
// HACK: the only place this lib is used is with enduser,
// which already has the table of bit values we want.
// Save the 8 bytes and use them.
//
extern BYTE BitValue[8];
BYTE LeadByteTable[128/8]; // 128 bits
unsigned *DbcsCharOrdinalOffsetTable;
unsigned *SbcsCharOrdinalOffsetTable;
unsigned *FontCacheTable;
BYTE *FontCache;
unsigned NextCacheSlot;
#define FONT_CACHE_CAPACITY 750
BOOL
LoadBootfontBin(
IN unsigned FileHandle,
IN ULONG FileSize
);
VOID
UnloadBootfontBin(
VOID
);
VOID
FontWriteBfbChar(
IN UCHAR c,
IN USHORT x,
IN USHORT y,
IN BYTE ForegroundPixelValue,
IN BYTE BackgroundPixelValue
);
BOOL
_far
FontLoadAndInit(
IN FPCHAR Filename
)
{
BOOL b;
ULONG FileSize;
unsigned FileHandle;
unsigned Count;
int ScaleFactor;
unsigned Offset,TableEndOffset;
FONT_CHAR *map;
unsigned hi,lo;
FPVOID data;
b = FALSE;
//
// Open the file and determine its size.
//
if(_dos_open(Filename,SH_DENYWR,&FileHandle)) {
goto c0;
}
if(((FileSize = DosSeek(FileHandle,0,DOSSEEK_END)) == -1)
|| DosSeek(FileHandle,0,DOSSEEK_START)) {
goto c1;
}
//
// Read the DOS header.
//
if(_dos_read(FileHandle,&FontHeaders.DosHeader,sizeof(IMAGE_DOS_HEADER),&Count)
|| (Count != sizeof(IMAGE_DOS_HEADER))) {
goto c1;
}
//
// Special check for bootfont.bin-style font.
//
if(((BOOTFONTBIN_HEADER *)&FontHeaders.DosHeader)->Signature == BOOTFONTBIN_SIGNATURE) {
return(LoadBootfontBin(FileHandle,FileSize));
}
//
// Cap file size to something reasonable (and that fits in a
// 16 bit value).
//
if(FileSize > 60000) {
goto c1;
}
//
// Basic header check.
//
if((FontHeaders.DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
|| (FontHeaders.DosHeader.e_lfanew < sizeof(IMAGE_DOS_HEADER))) {
goto c1;
}
//
// Retrieve some info from the dos header before overwriting it.
//
Offset = (unsigned)FontHeaders.DosHeader.e_lfanew;
//
// Read the OS/2 header and make sure the resource table exists.
//
if((DosSeek(FileHandle,FontHeaders.DosHeader.e_lfanew,DOSSEEK_START) != FontHeaders.DosHeader.e_lfanew)
|| _dos_read(FileHandle,&FontHeaders.Os2Header,sizeof(IMAGE_OS2_HEADER),&Count)
|| (Count != sizeof(IMAGE_OS2_HEADER))
|| (FontHeaders.Os2Header.ne_magic != IMAGE_OS2_SIGNATURE)
|| (FontHeaders.Os2Header.ne_restab > 65535L)
|| (FontHeaders.Os2Header.ne_rsrctab > 65535L)
|| !(FontHeaders.Os2Header.ne_restab - FontHeaders.Os2Header.ne_rsrctab)) {
goto c1;
}
//
// Search for font resource.
//
TableEndOffset = Offset;
Offset += (unsigned)FontHeaders.Os2Header.ne_rsrctab;
TableEndOffset += (unsigned)FontHeaders.Os2Header.ne_restab;
if((DosSeek(FileHandle,Offset,DOSSEEK_START) != Offset)
|| _dos_read(FileHandle,&ScaleFactor,2,&Count)
|| (Count != 2)) {
goto c1;
}
Offset += 2; // skip scale factor
FontHeaders.ResourceType.Ident = 0;
while(Offset < TableEndOffset) {
if((DosSeek(FileHandle,Offset,DOSSEEK_START) != Offset)
|| _dos_read(FileHandle,&FontHeaders.ResourceType,sizeof(RESOURCE_TYPE_INFORMATION),&Count)
|| (Count != sizeof(RESOURCE_TYPE_INFORMATION))) {
goto c1;
}
if(FontHeaders.ResourceType.Ident == FONT_RESOURCE) {
break;
}
Offset += sizeof(RESOURCE_TYPE_INFORMATION)
+ (FontHeaders.ResourceType.Number * sizeof(RESOURCE_NAME_INFORMATION));
}
if(FontHeaders.ResourceType.Ident != FONT_RESOURCE) {
goto c1;
}
//
// Get to resource name information.
//
Offset += sizeof(RESOURCE_TYPE_INFORMATION);
if((DosSeek(FileHandle,Offset,DOSSEEK_START) != Offset)
|| _dos_read(FileHandle,&FontHeaders.ResourceName,sizeof(RESOURCE_NAME_INFORMATION),&Count)
|| (Count != sizeof(RESOURCE_NAME_INFORMATION))) {
goto c1;
}
//
// Read the oem font file header and validate it. We don't read the
// table map in this part, we read that later.
//
Offset = FontHeaders.ResourceName.Offset << ScaleFactor;
if((DosSeek(FileHandle,Offset,DOSSEEK_START) != Offset)
|| _dos_read(FileHandle,&FontHeaders,sizeof(OEM_FONT_FILE_HEADER),&Count)
|| (Count != sizeof(OEM_FONT_FILE_HEADER))
|| (FontHeaders.FontHeader.Version != OEM_FONT_VERSION)
|| (FontHeaders.FontHeader.Type != OEM_FONT_TYPE)
|| FontHeaders.FontHeader.Italic
|| FontHeaders.FontHeader.Underline
|| FontHeaders.FontHeader.StrikeOut
|| (FontHeaders.FontHeader.CharacterSet != OEM_FONT_CHARACTER_SET)
|| (FontHeaders.FontHeader.Family != OEM_FONT_FAMILY)
|| (FontHeaders.FontHeader.PixelWidth != FONT_WIDTH)
|| (FontHeaders.FontHeader.PixelHeight > 16 )) {
goto c1;
}
//
// Allocate memory for the mapping table and read it in.
//
FileSize = (FontHeaders.FontHeader.LastCharacter - FontHeaders.FontHeader.FirstCharacter) + 1;
map = malloc((unsigned)FileSize * sizeof(FONT_CHAR));
if(!map) {
goto c1;
}
if(_dos_read(FileHandle,map,(unsigned)FileSize*sizeof(FONT_CHAR),&Count)
|| (Count != ((unsigned)FileSize*sizeof(FONT_CHAR)))) {
goto c2;
}
//
// Find the lowest and highest offsets to determine where the file data is.
//
hi = 0;
lo = (unsigned)(-1);
for(Count=0; Count<(unsigned)FileSize; Count++) {
if(map[Count].Offset < lo) {
lo = map[Count].Offset;
}
if(map[Count].Offset > hi) {
hi = map[Count].Offset;
}
}
FileSize = (unsigned)((hi - lo) + FontHeaders.FontHeader.PixelHeight);
data = malloc((unsigned)FileSize);
if(!data) {
goto c2;
}
Offset += lo;
if((DosSeek(FileHandle,Offset,DOSSEEK_START) != Offset)
|| _dos_read(FileHandle,data,(unsigned)FileSize,&Count)
|| (Count != (unsigned)FileSize)) {
goto c3;
}
if(FontCharMap) {
free(FontCharMap);
}
FontCharMap = map;
if(FontCharData) {
free(FontCharData);
}
FontCharData = data;
FontDataBaseOffset = lo;
GlyphHeight = (BYTE)FontHeaders.FontHeader.PixelHeight;
FontFirstChar = FontHeaders.FontHeader.FirstCharacter;
FontLastChar = FontHeaders.FontHeader.LastCharacter;
FontDefaultChar = FontHeaders.FontHeader.DefaultCharacter;
TopPad = 1;
BottomPad = 1;
if(BootfontFileHandle != (unsigned)(-1)) {
UnloadBootfontBin();
}
b = TRUE;
c3:
if(!b) {
free(data);
}
c2:
if(!b) {
free(map);
}
c1:
_dos_close(FileHandle);
c0:
return(b);
}
BOOL
LoadBootfontBin(
IN unsigned FileHandle,
IN ULONG FileSize
)
/*++
Routine Description:
This routine loads and initializes a font file in NT setup's
bootfont.bin format.
Arguments:
FileHandle - supplies DOS file handle of file.
FileSize - supplies size of file in bytes.
Return Value:
Boolean value indicating outcome. If TRUE, the file handle
will be left open. If FALSE the file handle will have been closed.
--*/
{
BOOL b;
unsigned Count;
unsigned i;
unsigned MaxChars,CharsLeft;
unsigned BytesPerChar;
unsigned index;
unsigned ordinal;
unsigned nextslot;
FPBYTE p;
FPBYTE ScratchBuffer;
unsigned *Table1,*Table2,*Table3;
BYTE *cache;
unsigned CacheOrd;
b = FALSE;
//
// Rewind the file and read the header.
//
if(DosSeek(FileHandle,0,DOSSEEK_START)
|| _dos_read(FileHandle,&FontHeaders.BfbHeader,sizeof(BOOTFONTBIN_HEADER),&Count)
|| (Count != sizeof(BOOTFONTBIN_HEADER))) {
goto c1;
}
//
// Basic checks.
//
if((FontHeaders.BfbHeader.CharacterImageSbcsWidth != FONT_WIDTH)
|| (FontHeaders.BfbHeader.CharacterImageDbcsWidth != (2*FONT_WIDTH))) {
goto c1;
}
//
// Make sure the DBCS table looks good. No ranges can be in ASCII range,
// the ranges must be legal (ie, end greater than start), and the table
// must be terminated with a pair of 0s.
//
for(Count=0;
FontHeaders.BfbHeader.DbcsLeadTable[Count]
&& FontHeaders.BfbHeader.DbcsLeadTable[Count+1]
&& (Count < (2*MAX_DBCS_RANGE));
Count+=2) {
if((FontHeaders.BfbHeader.DbcsLeadTable[Count] < DBCS_FIRST_LEAD)
|| (FontHeaders.BfbHeader.DbcsLeadTable[Count+1] < DBCS_FIRST_LEAD)
|| (FontHeaders.BfbHeader.DbcsLeadTable[Count] > DBCS_LAST_LEAD)
|| (FontHeaders.BfbHeader.DbcsLeadTable[Count+1] > DBCS_LAST_LEAD)
|| (FontHeaders.BfbHeader.DbcsLeadTable[Count] > FontHeaders.BfbHeader.DbcsLeadTable[Count+1])) {
goto c1;
}
}
if(FontHeaders.BfbHeader.DbcsLeadTable[Count]
|| FontHeaders.BfbHeader.DbcsLeadTable[Count+1]) {
goto c1;
}
//
// Now we build a table of characters and offset numbers
// into the file, indexed by character value. The theoretical
// maximum number of DBCS chars is when all of 81-fe are leads and
// each of 40-fe are trails for each lead byte; 7e * bf = 5e02 (24066)
// separate DBCS characters. (Actually 7f is not a valid trail byte but
// that only shaves 126 chars off the total, which not worth the headache.)
// Each character requires 2 bytes for an ordinal number in the font file,
// which gives a theoretical maximum table size of bc04 bytes. Mercifully
// this is much less than the malloc max of ffe8 bytes.
//
// We do something similar for the SBCS case also.
//
#define TABLE1_SIZE (2*(((DBCS_LAST_LEAD-DBCS_FIRST_LEAD)+1) * ((DBCS_LAST_TRAIL-DBCS_FIRST_TRAIL)+1)))
#define TABLE2_SIZE (2*255)
#define TABLE3_SIZE (2*(FontHeaders.BfbHeader.NumSbcsChars + FontHeaders.BfbHeader.NumDbcsChars))
Table1 = malloc(TABLE1_SIZE);
if(!Table1) {
goto c1;
}
Table2 = malloc(TABLE2_SIZE);
if(!Table2) {
goto c2;
}
Table3 = malloc(TABLE3_SIZE);
if(!Table3) {
goto c3;
}
//
// Each slot in the font cache is a 2 byte header indicating the ordinal
// value of the character cached in the slot, and then the bits that
// make up the glyph. Entries are sized for double-byte chars even though
// this wastes space for the single-byte case.
//
cache = malloc(FONT_CACHE_CAPACITY * (FontHeaders.BfbHeader.CharacterImageHeight+2) * 2);
if(!cache) {
goto c4;
}
memset(Table1,0,TABLE1_SIZE);
memset(Table2,0,TABLE2_SIZE);
memset(Table3,0xff,TABLE3_SIZE);
if(DosSeek(FileHandle,FontHeaders.BfbHeader.DbcsOffset,DOSSEEK_START) != FontHeaders.BfbHeader.DbcsOffset) {
goto c5;
}
#define SCRATCH_SIZE 18000 // exactly 1000 chars in typical case
ScratchBuffer = malloc(SCRATCH_SIZE);
if(!ScratchBuffer) {
goto c5;
}
//
// Build an offset table for sbcs chars.
// There are a max of 255 SBCS chars (1-255).
//
BytesPerChar = (FontHeaders.BfbHeader.CharacterImageHeight)+1;
if(DosSeek(FileHandle,FontHeaders.BfbHeader.SbcsOffset,DOSSEEK_START) != FontHeaders.BfbHeader.SbcsOffset) {
free(ScratchBuffer);
goto c5;
}
MaxChars = SCRATCH_SIZE / BytesPerChar;
CharsLeft = FontHeaders.BfbHeader.NumSbcsChars;
ordinal = 0;
CacheOrd = 0;
while(CharsLeft) {
Count = CharsLeft;
if(Count > MaxChars) {
Count = MaxChars;
}
if(_dos_read(FileHandle,ScratchBuffer,Count*BytesPerChar,&i)
|| (i != (Count*BytesPerChar))) {
free(ScratchBuffer);
goto c5;
}
CharsLeft -= Count;
for(p=ScratchBuffer,i=0; i<Count; i++,p+=BytesPerChar,ordinal++) {
if(!p[0]) {
//
// Invalid value, skip this character
//
continue;
}
index = (unsigned)p[0] - 1;
Table2[index] = ordinal;
//
// Cache most chars in the ascii range.
//
if((p[0] >= ' ') && (p[0] <= 'z')) {
*(unsigned *)&cache[2*BytesPerChar*CacheOrd] = ordinal;
memmove(cache+(2*BytesPerChar*CacheOrd)+2,&p[1],BytesPerChar-1);
Table3[ordinal] = CacheOrd++;
}
}
}
nextslot = CacheOrd;
BytesPerChar = (FontHeaders.BfbHeader.CharacterImageHeight*2)+2;
MaxChars = SCRATCH_SIZE / BytesPerChar;
CharsLeft = FontHeaders.BfbHeader.NumDbcsChars;
ordinal = 0;
while(CharsLeft) {
Count = CharsLeft;
if(Count > MaxChars) {
Count = MaxChars;
}
if(_dos_read(FileHandle,ScratchBuffer,Count*BytesPerChar,&i)
|| (i != (Count*BytesPerChar))) {
free(ScratchBuffer);
goto c5;
}
CharsLeft -= Count;
for(p=ScratchBuffer,i=0; i<Count; i++,p+=BytesPerChar,ordinal++) {
if((p[0] < DBCS_FIRST_LEAD) || (p[0] > DBCS_LAST_LEAD)
|| (p[1] < DBCS_FIRST_TRAIL) || (p[1] > DBCS_LAST_TRAIL)) {
//
// Invalid DBCS value, skip this character
//
continue;
}
index = (unsigned)(p[0] - DBCS_FIRST_LEAD);
index <<= 8;
index |= p[1] - DBCS_FIRST_TRAIL;
index -= (unsigned)(p[0] - DBCS_FIRST_LEAD) * (DBCS_FIRST_TRAIL + (255-DBCS_LAST_TRAIL));
Table1[index] = ordinal;
//
// Cache first n chars that fit in the cache
//
if(CacheOrd < FONT_CACHE_CAPACITY) {
*(unsigned *)&cache[CacheOrd*BytesPerChar] = ordinal+FontHeaders.BfbHeader.NumSbcsChars;
memmove(cache+(CacheOrd*BytesPerChar)+2,&p[2],BytesPerChar-2);
Table3[ordinal+FontHeaders.BfbHeader.NumSbcsChars] = CacheOrd++;
}
}
}
free(ScratchBuffer);
//
// Everything looks good. Set up globals.
//
memset(LeadByteTable,0,sizeof(LeadByteTable));
for(Count=0;
FontHeaders.BfbHeader.DbcsLeadTable[Count]
&& FontHeaders.BfbHeader.DbcsLeadTable[Count+1];
Count+=2) {
for(i = FontHeaders.BfbHeader.DbcsLeadTable[Count];
i <= FontHeaders.BfbHeader.DbcsLeadTable[Count+1];
i++) {
LeadByteTable[(i-128)/8] |= BitValue[(i-128)%8];
}
}
SbcsCharCount = FontHeaders.BfbHeader.NumSbcsChars;
DbcsCharCount = FontHeaders.BfbHeader.NumDbcsChars;
GlyphHeight = FontHeaders.BfbHeader.CharacterImageHeight;
TopPad = FontHeaders.BfbHeader.CharacterTopPad;
BottomPad = FontHeaders.BfbHeader.CharacterBottomPad;
SbcsFileOffset = FontHeaders.BfbHeader.SbcsOffset;
DbcsFileOffset = FontHeaders.BfbHeader.DbcsOffset;
if(BootfontFileHandle != (unsigned)(-1)) {
UnloadBootfontBin();
}
DbcsCharOrdinalOffsetTable = Table1;
SbcsCharOrdinalOffsetTable = Table2;
FontCacheTable = Table3;
FontCache = cache;
NextCacheSlot = nextslot;
BootfontFileHandle = FileHandle;
if(FontCharMap) {
free(FontCharMap);
FontCharMap = NULL;
}
if(FontCharData) {
free(FontCharData);
FontCharData = NULL;
}
b = TRUE;
c5:
if(!b) {
free(cache);
}
c4:
if(!b) {
free(Table3);
}
c3:
if(!b) {
free(Table2);
}
c2:
if(!b) {
free(Table1);
}
c1:
if(!b) {
_dos_close(FileHandle);
}
return(b);
}
VOID
UnloadBootfontBin(
VOID
)
{
_dos_close(BootfontFileHandle);
BootfontFileHandle = (unsigned)(-1);
PendingLeadByte = 0;
free(DbcsCharOrdinalOffsetTable);
free(SbcsCharOrdinalOffsetTable);
free(FontCacheTable);
free(FontCache);
DbcsCharOrdinalOffsetTable = NULL;
SbcsCharOrdinalOffsetTable = NULL;
FontCacheTable = NULL;
FontCache = NULL;
}
VOID
_far
FontGetInfo(
OUT FPBYTE Width,
OUT FPBYTE Height
)
{
*Width = FONT_WIDTH;
*Height = GlyphHeight + TopPad + BottomPad;
}
VOID
_far
FontWriteChar(
IN UCHAR c,
IN USHORT x,
IN USHORT y,
IN BYTE ForegroundPixelValue,
IN BYTE BackgroundPixelValue
)
{
BYTE PixelMap[2];
if(BootfontFileHandle != (unsigned)(-1)) {
//
// Use bootfont.bin method
//
FontWriteBfbChar(c,x,y,ForegroundPixelValue,BackgroundPixelValue);
return;
}
PixelMap[0] = BackgroundPixelValue;
PixelMap[1] = ForegroundPixelValue;
if((c < FontFirstChar) || (c > FontLastChar)) {
c = FontDefaultChar;
}
//
// Pad if necessary by filling in background
//
if(BackgroundPixelValue < VGAPIX_TRANSPARENT) {
if(TopPad) {
VgaClearRegion(x,y,FONT_WIDTH,TopPad,BackgroundPixelValue);
}
if(BottomPad) {
VgaClearRegion(x,y+TopPad+GlyphHeight,FONT_WIDTH,BottomPad,BackgroundPixelValue);
}
}
VgaBitBlt(
x,
y + TopPad,
FONT_WIDTH,
GlyphHeight,
1,
FALSE,
PixelMap,
FontCharData + (FontCharMap[c-FontFirstChar].Offset - FontDataBaseOffset)
);
}
VOID
_far
FontWriteString(
IN UCHAR *String,
IN USHORT x,
IN USHORT y,
IN BYTE ForegroundPixelValue,
IN BYTE BackgroundPixelValue
)
{
for( ; *String; String++) {
FontWriteChar(*String,x,y,ForegroundPixelValue,BackgroundPixelValue);
x += FONT_WIDTH;
}
PendingLeadByte = 0;
}
VOID
FontWriteBfbChar(
IN UCHAR c,
IN USHORT x,
IN USHORT y,
IN BYTE ForegroundPixelValue,
IN BYTE BackgroundPixelValue
)
{
unsigned scale;
unsigned index;
unsigned Ordinal;
unsigned i,read;
ULONG FileOffset = 0;
FPBYTE Glyph = NULL;
BYTE PixelMap[2];
FPBYTE p;
if(PendingLeadByte) {
//
// Got second half of DBCS character. Render now.
//
index = (unsigned)(PendingLeadByte - DBCS_FIRST_LEAD);
index <<= 8;
index |= c - DBCS_FIRST_TRAIL;
index -= (unsigned)(PendingLeadByte - DBCS_FIRST_LEAD) * (DBCS_FIRST_TRAIL + (255-DBCS_LAST_TRAIL));
PendingLeadByte = 0;
Ordinal = DbcsCharOrdinalOffsetTable[index];
//
// Is this character cached?
//
if(FontCacheTable[Ordinal+SbcsCharCount] == (unsigned)(-1)) {
//
// No, need to cache it.
//
FileOffset = ((ULONG)Ordinal * ((2 * GlyphHeight) + 2)) + DbcsFileOffset + 2;
} else {
//
// Yes, get glyph.
//
Glyph = FontCache + (((2 * GlyphHeight) + 2) * FontCacheTable[Ordinal+SbcsCharCount]) + 2;
}
Ordinal += SbcsCharCount;
x -= FONT_WIDTH;
scale = 2;
} else {
//
// See if DBCS char or a lead byte
//
if((c >= DBCS_FIRST_LEAD) && (LeadByteTable[(c-128)/8] & BitValue[(c-128)%8])) {
PendingLeadByte = c;
return;
}
//
// SBCS char.
//
Ordinal = SbcsCharOrdinalOffsetTable[c-1];
//
// Is this character cached?
//
if(FontCacheTable[Ordinal] == (unsigned)(-1)) {
//
// No, need to cache it.
//
FileOffset = ((ULONG)Ordinal * (GlyphHeight + 1)) + SbcsFileOffset + 1;
} else {
//
// Yes, get glyph
//
Glyph = FontCache + (((2 * GlyphHeight) + 2) * FontCacheTable[Ordinal]) + 2;
}
scale = 1;
}
if(FileOffset) {
//
// Pull the character in from the file.
//
Glyph = NULL;
if(DosSeek(BootfontFileHandle,FileOffset,DOSSEEK_START) == FileOffset) {
//
// Point at the entry in the font cache where we're going
// to stick the glyph.
//
p = FontCache + (NextCacheSlot * ((2 * GlyphHeight) + 2));
//
// Invalidate the caching for the character currently
// cached in the slot we're going to overwrite. If the read
// fails halfway through, the glyph may be trashed anyway,
// so we do it before we know if the read succeeds.
//
FontCacheTable[*(unsigned *)p] = (unsigned)(-1);
i = _dos_read(BootfontFileHandle,p+2,scale*GlyphHeight,&read);
if(!i && (read == (scale * GlyphHeight))) {
*(unsigned *)p = Ordinal;
Glyph = p+2;
FontCacheTable[Ordinal] = NextCacheSlot++;
if(NextCacheSlot == FONT_CACHE_CAPACITY) {
NextCacheSlot = 0;
}
}
}
}
if(Glyph) {
//
// Pad if necessary by filling in background
//
if(BackgroundPixelValue < VGAPIX_TRANSPARENT) {
if(TopPad) {
VgaClearRegion(x,y,scale*FONT_WIDTH,TopPad,BackgroundPixelValue);
}
if(BottomPad) {
VgaClearRegion(x,y+TopPad+GlyphHeight,scale*FONT_WIDTH,BottomPad,BackgroundPixelValue);
}
}
PixelMap[0] = BackgroundPixelValue;
PixelMap[1] = ForegroundPixelValue;
VgaBitBlt(
x,
y + TopPad,
scale*FONT_WIDTH,
GlyphHeight,
scale,
FALSE,
PixelMap,
Glyph
);
} else {
//
// Put a block up there.
//
VgaClearRegion(x,y,scale*FONT_WIDTH,TopPad+BottomPad+GlyphHeight,ForegroundPixelValue);
}
}