Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1035 lines
27 KiB

  1. #include <dos.h>
  2. #include <share.h>
  3. #include <stddef.h>
  4. #include <malloc.h>
  5. #include <string.h>
  6. #include <mytypes.h>
  7. #include <misclib.h>
  8. #include <displib.h>
  9. #include "bootfont.h"
  10. //
  11. // The following structures and constants are used in font files:
  12. // DOS image header
  13. // OS/2 image header
  14. // OS/2 executable resource information structure
  15. // OS/2 executable resource name information structure
  16. //
  17. typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
  18. USHORT e_magic; // Magic number
  19. USHORT e_cblp; // Bytes on last page of file
  20. USHORT e_cp; // Pages in file
  21. USHORT e_crlc; // Relocations
  22. USHORT e_cparhdr; // Size of header in paragraphs
  23. USHORT e_minalloc; // Minimum extra paragraphs needed
  24. USHORT e_maxalloc; // Maximum extra paragraphs needed
  25. USHORT e_ss; // Initial (relative) SS value
  26. USHORT e_sp; // Initial SP value
  27. USHORT e_csum; // Checksum
  28. USHORT e_ip; // Initial IP value
  29. USHORT e_cs; // Initial (relative) CS value
  30. USHORT e_lfarlc; // File address of relocation table
  31. USHORT e_ovno; // Overlay number
  32. USHORT e_res[4]; // Reserved words
  33. USHORT e_oemid; // OEM identifier (for e_oeminfo)
  34. USHORT e_oeminfo; // OEM information; e_oemid specific
  35. USHORT e_res2[10]; // Reserved words
  36. ULONG e_lfanew; // File address of new exe header
  37. } IMAGE_DOS_HEADER;
  38. #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
  39. typedef struct _IMAGE_OS2_HEADER { // OS/2 .EXE header
  40. USHORT ne_magic; // Magic number
  41. CHAR ne_ver; // Version number
  42. CHAR ne_rev; // Revision number
  43. USHORT ne_enttab; // Offset of Entry Table
  44. USHORT ne_cbenttab; // Number of bytes in Entry Table
  45. long ne_crc; // Checksum of whole file
  46. USHORT ne_flags; // Flag word
  47. USHORT ne_autodata; // Automatic data segment number
  48. USHORT ne_heap; // Initial heap allocation
  49. USHORT ne_stack; // Initial stack allocation
  50. long ne_csip; // Initial CS:IP setting
  51. long ne_sssp; // Initial SS:SP setting
  52. USHORT ne_cseg; // Count of file segments
  53. USHORT ne_cmod; // Entries in Module Reference Table
  54. USHORT ne_cbnrestab; // Size of non-resident name table
  55. USHORT ne_segtab; // Offset of Segment Table
  56. USHORT ne_rsrctab; // Offset of Resource Table
  57. USHORT ne_restab; // Offset of resident name table
  58. USHORT ne_modtab; // Offset of Module Reference Table
  59. USHORT ne_imptab; // Offset of Imported Names Table
  60. long ne_nrestab; // Offset of Non-resident Names Table
  61. USHORT ne_cmovent; // Count of movable entries
  62. USHORT ne_align; // Segment alignment shift count
  63. USHORT ne_cres; // Count of resource segments
  64. UCHAR ne_exetyp; // Target Operating system
  65. UCHAR ne_flagsothers; // Other .EXE flags
  66. USHORT ne_pretthunks; // offset to return thunks
  67. USHORT ne_psegrefbytes; // offset to segment ref. bytes
  68. USHORT ne_swaparea; // Minimum code swap area size
  69. USHORT ne_expver; // Expected Windows version number
  70. } IMAGE_OS2_HEADER;
  71. #define IMAGE_OS2_SIGNATURE 0x454E // NE
  72. typedef struct _RESOURCE_TYPE_INFORMATION {
  73. USHORT Ident;
  74. USHORT Number;
  75. long Proc;
  76. } RESOURCE_TYPE_INFORMATION;
  77. #define FONT_DIRECTORY 0x8007
  78. #define FONT_RESOURCE 0x8008
  79. typedef struct _RESOURCE_NAME_INFORMATION {
  80. USHORT Offset;
  81. USHORT Length;
  82. USHORT Flags;
  83. USHORT Ident;
  84. USHORT Handle;
  85. USHORT Usage;
  86. } RESOURCE_NAME_INFORMATION;
  87. #pragma pack(1)
  88. typedef struct _OEM_FONT_FILE_HEADER {
  89. USHORT Version;
  90. ULONG FileSize;
  91. UCHAR Copyright[60];
  92. USHORT Type;
  93. USHORT Points;
  94. USHORT VerticalResolution;
  95. USHORT HorizontalResolution;
  96. USHORT Ascent;
  97. USHORT InternalLeading;
  98. USHORT ExternalLeading;
  99. UCHAR Italic;
  100. UCHAR Underline;
  101. UCHAR StrikeOut;
  102. USHORT Weight;
  103. UCHAR CharacterSet;
  104. USHORT PixelWidth;
  105. USHORT PixelHeight;
  106. UCHAR Family;
  107. USHORT AverageWidth;
  108. USHORT MaximumWidth;
  109. UCHAR FirstCharacter;
  110. UCHAR LastCharacter;
  111. UCHAR DefaultCharacter;
  112. UCHAR BreakCharacter;
  113. USHORT WidthInBytes;
  114. ULONG Device;
  115. ULONG Face;
  116. ULONG BitsPointer;
  117. ULONG BitsOffset;
  118. UCHAR Filler;
  119. } OEM_FONT_FILE_HEADER;
  120. #pragma pack()
  121. #define OEM_FONT_VERSION 0x200
  122. #define OEM_FONT_TYPE 0
  123. #define OEM_FONT_CHARACTER_SET 255
  124. #define OEM_FONT_FAMILY (3 << 4)
  125. #define FONT_WIDTH 8
  126. typedef struct _FONT_CHAR {
  127. USHORT Width;
  128. USHORT Offset;
  129. } FONT_CHAR;
  130. union {
  131. IMAGE_DOS_HEADER DosHeader;
  132. IMAGE_OS2_HEADER Os2Header;
  133. OEM_FONT_FILE_HEADER FontHeader;
  134. RESOURCE_TYPE_INFORMATION ResourceType;
  135. RESOURCE_NAME_INFORMATION ResourceName;
  136. BOOTFONTBIN_HEADER BfbHeader;
  137. } FontHeaders;
  138. FONT_CHAR *FontCharMap;
  139. BYTE *FontCharData;
  140. unsigned FontDataBaseOffset;
  141. BYTE GlyphHeight;
  142. BYTE FontFirstChar,FontLastChar,FontDefaultChar;
  143. BYTE TopPad,BottomPad;
  144. unsigned BootfontFileHandle = (unsigned)(-1);
  145. UCHAR PendingLeadByte;
  146. unsigned SbcsCharCount;
  147. unsigned DbcsCharCount;
  148. ULONG SbcsFileOffset;
  149. ULONG DbcsFileOffset;
  150. #define DBCS_FIRST_LEAD 0x81
  151. #define DBCS_LAST_LEAD 0xfe
  152. #define DBCS_FIRST_TRAIL 0x40
  153. #define DBCS_LAST_TRAIL 0xfe
  154. //
  155. // HACK: the only place this lib is used is with enduser,
  156. // which already has the table of bit values we want.
  157. // Save the 8 bytes and use them.
  158. //
  159. extern BYTE BitValue[8];
  160. BYTE LeadByteTable[128/8]; // 128 bits
  161. unsigned *DbcsCharOrdinalOffsetTable;
  162. unsigned *SbcsCharOrdinalOffsetTable;
  163. unsigned *FontCacheTable;
  164. BYTE *FontCache;
  165. unsigned NextCacheSlot;
  166. #define FONT_CACHE_CAPACITY 750
  167. BOOL
  168. LoadBootfontBin(
  169. IN unsigned FileHandle,
  170. IN ULONG FileSize
  171. );
  172. VOID
  173. UnloadBootfontBin(
  174. VOID
  175. );
  176. VOID
  177. FontWriteBfbChar(
  178. IN UCHAR c,
  179. IN USHORT x,
  180. IN USHORT y,
  181. IN BYTE ForegroundPixelValue,
  182. IN BYTE BackgroundPixelValue
  183. );
  184. BOOL
  185. _far
  186. FontLoadAndInit(
  187. IN FPCHAR Filename
  188. )
  189. {
  190. BOOL b;
  191. ULONG FileSize;
  192. unsigned FileHandle;
  193. unsigned Count;
  194. int ScaleFactor;
  195. unsigned Offset,TableEndOffset;
  196. FONT_CHAR *map;
  197. unsigned hi,lo;
  198. FPVOID data;
  199. b = FALSE;
  200. //
  201. // Open the file and determine its size.
  202. //
  203. if(_dos_open(Filename,SH_DENYWR,&FileHandle)) {
  204. goto c0;
  205. }
  206. if(((FileSize = DosSeek(FileHandle,0,DOSSEEK_END)) == -1)
  207. || DosSeek(FileHandle,0,DOSSEEK_START)) {
  208. goto c1;
  209. }
  210. //
  211. // Read the DOS header.
  212. //
  213. if(_dos_read(FileHandle,&FontHeaders.DosHeader,sizeof(IMAGE_DOS_HEADER),&Count)
  214. || (Count != sizeof(IMAGE_DOS_HEADER))) {
  215. goto c1;
  216. }
  217. //
  218. // Special check for bootfont.bin-style font.
  219. //
  220. if(((BOOTFONTBIN_HEADER *)&FontHeaders.DosHeader)->Signature == BOOTFONTBIN_SIGNATURE) {
  221. return(LoadBootfontBin(FileHandle,FileSize));
  222. }
  223. //
  224. // Cap file size to something reasonable (and that fits in a
  225. // 16 bit value).
  226. //
  227. if(FileSize > 60000) {
  228. goto c1;
  229. }
  230. //
  231. // Basic header check.
  232. //
  233. if((FontHeaders.DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
  234. || (FontHeaders.DosHeader.e_lfanew < sizeof(IMAGE_DOS_HEADER))) {
  235. goto c1;
  236. }
  237. //
  238. // Retrieve some info from the dos header before overwriting it.
  239. //
  240. Offset = (unsigned)FontHeaders.DosHeader.e_lfanew;
  241. //
  242. // Read the OS/2 header and make sure the resource table exists.
  243. //
  244. if((DosSeek(FileHandle,FontHeaders.DosHeader.e_lfanew,DOSSEEK_START) != FontHeaders.DosHeader.e_lfanew)
  245. || _dos_read(FileHandle,&FontHeaders.Os2Header,sizeof(IMAGE_OS2_HEADER),&Count)
  246. || (Count != sizeof(IMAGE_OS2_HEADER))
  247. || (FontHeaders.Os2Header.ne_magic != IMAGE_OS2_SIGNATURE)
  248. || (FontHeaders.Os2Header.ne_restab > 65535L)
  249. || (FontHeaders.Os2Header.ne_rsrctab > 65535L)
  250. || !(FontHeaders.Os2Header.ne_restab - FontHeaders.Os2Header.ne_rsrctab)) {
  251. goto c1;
  252. }
  253. //
  254. // Search for font resource.
  255. //
  256. TableEndOffset = Offset;
  257. Offset += (unsigned)FontHeaders.Os2Header.ne_rsrctab;
  258. TableEndOffset += (unsigned)FontHeaders.Os2Header.ne_restab;
  259. if((DosSeek(FileHandle,Offset,DOSSEEK_START) != Offset)
  260. || _dos_read(FileHandle,&ScaleFactor,2,&Count)
  261. || (Count != 2)) {
  262. goto c1;
  263. }
  264. Offset += 2; // skip scale factor
  265. FontHeaders.ResourceType.Ident = 0;
  266. while(Offset < TableEndOffset) {
  267. if((DosSeek(FileHandle,Offset,DOSSEEK_START) != Offset)
  268. || _dos_read(FileHandle,&FontHeaders.ResourceType,sizeof(RESOURCE_TYPE_INFORMATION),&Count)
  269. || (Count != sizeof(RESOURCE_TYPE_INFORMATION))) {
  270. goto c1;
  271. }
  272. if(FontHeaders.ResourceType.Ident == FONT_RESOURCE) {
  273. break;
  274. }
  275. Offset += sizeof(RESOURCE_TYPE_INFORMATION)
  276. + (FontHeaders.ResourceType.Number * sizeof(RESOURCE_NAME_INFORMATION));
  277. }
  278. if(FontHeaders.ResourceType.Ident != FONT_RESOURCE) {
  279. goto c1;
  280. }
  281. //
  282. // Get to resource name information.
  283. //
  284. Offset += sizeof(RESOURCE_TYPE_INFORMATION);
  285. if((DosSeek(FileHandle,Offset,DOSSEEK_START) != Offset)
  286. || _dos_read(FileHandle,&FontHeaders.ResourceName,sizeof(RESOURCE_NAME_INFORMATION),&Count)
  287. || (Count != sizeof(RESOURCE_NAME_INFORMATION))) {
  288. goto c1;
  289. }
  290. //
  291. // Read the oem font file header and validate it. We don't read the
  292. // table map in this part, we read that later.
  293. //
  294. Offset = FontHeaders.ResourceName.Offset << ScaleFactor;
  295. if((DosSeek(FileHandle,Offset,DOSSEEK_START) != Offset)
  296. || _dos_read(FileHandle,&FontHeaders,sizeof(OEM_FONT_FILE_HEADER),&Count)
  297. || (Count != sizeof(OEM_FONT_FILE_HEADER))
  298. || (FontHeaders.FontHeader.Version != OEM_FONT_VERSION)
  299. || (FontHeaders.FontHeader.Type != OEM_FONT_TYPE)
  300. || FontHeaders.FontHeader.Italic
  301. || FontHeaders.FontHeader.Underline
  302. || FontHeaders.FontHeader.StrikeOut
  303. || (FontHeaders.FontHeader.CharacterSet != OEM_FONT_CHARACTER_SET)
  304. || (FontHeaders.FontHeader.Family != OEM_FONT_FAMILY)
  305. || (FontHeaders.FontHeader.PixelWidth != FONT_WIDTH)
  306. || (FontHeaders.FontHeader.PixelHeight > 16 )) {
  307. goto c1;
  308. }
  309. //
  310. // Allocate memory for the mapping table and read it in.
  311. //
  312. FileSize = (FontHeaders.FontHeader.LastCharacter - FontHeaders.FontHeader.FirstCharacter) + 1;
  313. map = malloc((unsigned)FileSize * sizeof(FONT_CHAR));
  314. if(!map) {
  315. goto c1;
  316. }
  317. if(_dos_read(FileHandle,map,(unsigned)FileSize*sizeof(FONT_CHAR),&Count)
  318. || (Count != ((unsigned)FileSize*sizeof(FONT_CHAR)))) {
  319. goto c2;
  320. }
  321. //
  322. // Find the lowest and highest offsets to determine where the file data is.
  323. //
  324. hi = 0;
  325. lo = (unsigned)(-1);
  326. for(Count=0; Count<(unsigned)FileSize; Count++) {
  327. if(map[Count].Offset < lo) {
  328. lo = map[Count].Offset;
  329. }
  330. if(map[Count].Offset > hi) {
  331. hi = map[Count].Offset;
  332. }
  333. }
  334. FileSize = (unsigned)((hi - lo) + FontHeaders.FontHeader.PixelHeight);
  335. data = malloc((unsigned)FileSize);
  336. if(!data) {
  337. goto c2;
  338. }
  339. Offset += lo;
  340. if((DosSeek(FileHandle,Offset,DOSSEEK_START) != Offset)
  341. || _dos_read(FileHandle,data,(unsigned)FileSize,&Count)
  342. || (Count != (unsigned)FileSize)) {
  343. goto c3;
  344. }
  345. if(FontCharMap) {
  346. free(FontCharMap);
  347. }
  348. FontCharMap = map;
  349. if(FontCharData) {
  350. free(FontCharData);
  351. }
  352. FontCharData = data;
  353. FontDataBaseOffset = lo;
  354. GlyphHeight = (BYTE)FontHeaders.FontHeader.PixelHeight;
  355. FontFirstChar = FontHeaders.FontHeader.FirstCharacter;
  356. FontLastChar = FontHeaders.FontHeader.LastCharacter;
  357. FontDefaultChar = FontHeaders.FontHeader.DefaultCharacter;
  358. TopPad = 1;
  359. BottomPad = 1;
  360. if(BootfontFileHandle != (unsigned)(-1)) {
  361. UnloadBootfontBin();
  362. }
  363. b = TRUE;
  364. c3:
  365. if(!b) {
  366. free(data);
  367. }
  368. c2:
  369. if(!b) {
  370. free(map);
  371. }
  372. c1:
  373. _dos_close(FileHandle);
  374. c0:
  375. return(b);
  376. }
  377. BOOL
  378. LoadBootfontBin(
  379. IN unsigned FileHandle,
  380. IN ULONG FileSize
  381. )
  382. /*++
  383. Routine Description:
  384. This routine loads and initializes a font file in NT setup's
  385. bootfont.bin format.
  386. Arguments:
  387. FileHandle - supplies DOS file handle of file.
  388. FileSize - supplies size of file in bytes.
  389. Return Value:
  390. Boolean value indicating outcome. If TRUE, the file handle
  391. will be left open. If FALSE the file handle will have been closed.
  392. --*/
  393. {
  394. BOOL b;
  395. unsigned Count;
  396. unsigned i;
  397. unsigned MaxChars,CharsLeft;
  398. unsigned BytesPerChar;
  399. unsigned index;
  400. unsigned ordinal;
  401. unsigned nextslot;
  402. FPBYTE p;
  403. FPBYTE ScratchBuffer;
  404. unsigned *Table1,*Table2,*Table3;
  405. BYTE *cache;
  406. unsigned CacheOrd;
  407. b = FALSE;
  408. //
  409. // Rewind the file and read the header.
  410. //
  411. if(DosSeek(FileHandle,0,DOSSEEK_START)
  412. || _dos_read(FileHandle,&FontHeaders.BfbHeader,sizeof(BOOTFONTBIN_HEADER),&Count)
  413. || (Count != sizeof(BOOTFONTBIN_HEADER))) {
  414. goto c1;
  415. }
  416. //
  417. // Basic checks.
  418. //
  419. if((FontHeaders.BfbHeader.CharacterImageSbcsWidth != FONT_WIDTH)
  420. || (FontHeaders.BfbHeader.CharacterImageDbcsWidth != (2*FONT_WIDTH))) {
  421. goto c1;
  422. }
  423. //
  424. // Make sure the DBCS table looks good. No ranges can be in ASCII range,
  425. // the ranges must be legal (ie, end greater than start), and the table
  426. // must be terminated with a pair of 0s.
  427. //
  428. for(Count=0;
  429. FontHeaders.BfbHeader.DbcsLeadTable[Count]
  430. && FontHeaders.BfbHeader.DbcsLeadTable[Count+1]
  431. && (Count < (2*MAX_DBCS_RANGE));
  432. Count+=2) {
  433. if((FontHeaders.BfbHeader.DbcsLeadTable[Count] < DBCS_FIRST_LEAD)
  434. || (FontHeaders.BfbHeader.DbcsLeadTable[Count+1] < DBCS_FIRST_LEAD)
  435. || (FontHeaders.BfbHeader.DbcsLeadTable[Count] > DBCS_LAST_LEAD)
  436. || (FontHeaders.BfbHeader.DbcsLeadTable[Count+1] > DBCS_LAST_LEAD)
  437. || (FontHeaders.BfbHeader.DbcsLeadTable[Count] > FontHeaders.BfbHeader.DbcsLeadTable[Count+1])) {
  438. goto c1;
  439. }
  440. }
  441. if(FontHeaders.BfbHeader.DbcsLeadTable[Count]
  442. || FontHeaders.BfbHeader.DbcsLeadTable[Count+1]) {
  443. goto c1;
  444. }
  445. //
  446. // Now we build a table of characters and offset numbers
  447. // into the file, indexed by character value. The theoretical
  448. // maximum number of DBCS chars is when all of 81-fe are leads and
  449. // each of 40-fe are trails for each lead byte; 7e * bf = 5e02 (24066)
  450. // separate DBCS characters. (Actually 7f is not a valid trail byte but
  451. // that only shaves 126 chars off the total, which not worth the headache.)
  452. // Each character requires 2 bytes for an ordinal number in the font file,
  453. // which gives a theoretical maximum table size of bc04 bytes. Mercifully
  454. // this is much less than the malloc max of ffe8 bytes.
  455. //
  456. // We do something similar for the SBCS case also.
  457. //
  458. #define TABLE1_SIZE (2*(((DBCS_LAST_LEAD-DBCS_FIRST_LEAD)+1) * ((DBCS_LAST_TRAIL-DBCS_FIRST_TRAIL)+1)))
  459. #define TABLE2_SIZE (2*255)
  460. #define TABLE3_SIZE (2*(FontHeaders.BfbHeader.NumSbcsChars + FontHeaders.BfbHeader.NumDbcsChars))
  461. Table1 = malloc(TABLE1_SIZE);
  462. if(!Table1) {
  463. goto c1;
  464. }
  465. Table2 = malloc(TABLE2_SIZE);
  466. if(!Table2) {
  467. goto c2;
  468. }
  469. Table3 = malloc(TABLE3_SIZE);
  470. if(!Table3) {
  471. goto c3;
  472. }
  473. //
  474. // Each slot in the font cache is a 2 byte header indicating the ordinal
  475. // value of the character cached in the slot, and then the bits that
  476. // make up the glyph. Entries are sized for double-byte chars even though
  477. // this wastes space for the single-byte case.
  478. //
  479. cache = malloc(FONT_CACHE_CAPACITY * (FontHeaders.BfbHeader.CharacterImageHeight+2) * 2);
  480. if(!cache) {
  481. goto c4;
  482. }
  483. memset(Table1,0,TABLE1_SIZE);
  484. memset(Table2,0,TABLE2_SIZE);
  485. memset(Table3,0xff,TABLE3_SIZE);
  486. if(DosSeek(FileHandle,FontHeaders.BfbHeader.DbcsOffset,DOSSEEK_START) != FontHeaders.BfbHeader.DbcsOffset) {
  487. goto c5;
  488. }
  489. #define SCRATCH_SIZE 18000 // exactly 1000 chars in typical case
  490. ScratchBuffer = malloc(SCRATCH_SIZE);
  491. if(!ScratchBuffer) {
  492. goto c5;
  493. }
  494. //
  495. // Build an offset table for sbcs chars.
  496. // There are a max of 255 SBCS chars (1-255).
  497. //
  498. BytesPerChar = (FontHeaders.BfbHeader.CharacterImageHeight)+1;
  499. if(DosSeek(FileHandle,FontHeaders.BfbHeader.SbcsOffset,DOSSEEK_START) != FontHeaders.BfbHeader.SbcsOffset) {
  500. free(ScratchBuffer);
  501. goto c5;
  502. }
  503. MaxChars = SCRATCH_SIZE / BytesPerChar;
  504. CharsLeft = FontHeaders.BfbHeader.NumSbcsChars;
  505. ordinal = 0;
  506. CacheOrd = 0;
  507. while(CharsLeft) {
  508. Count = CharsLeft;
  509. if(Count > MaxChars) {
  510. Count = MaxChars;
  511. }
  512. if(_dos_read(FileHandle,ScratchBuffer,Count*BytesPerChar,&i)
  513. || (i != (Count*BytesPerChar))) {
  514. free(ScratchBuffer);
  515. goto c5;
  516. }
  517. CharsLeft -= Count;
  518. for(p=ScratchBuffer,i=0; i<Count; i++,p+=BytesPerChar,ordinal++) {
  519. if(!p[0]) {
  520. //
  521. // Invalid value, skip this character
  522. //
  523. continue;
  524. }
  525. index = (unsigned)p[0] - 1;
  526. Table2[index] = ordinal;
  527. //
  528. // Cache most chars in the ascii range.
  529. //
  530. if((p[0] >= ' ') && (p[0] <= 'z')) {
  531. *(unsigned *)&cache[2*BytesPerChar*CacheOrd] = ordinal;
  532. memmove(cache+(2*BytesPerChar*CacheOrd)+2,&p[1],BytesPerChar-1);
  533. Table3[ordinal] = CacheOrd++;
  534. }
  535. }
  536. }
  537. nextslot = CacheOrd;
  538. BytesPerChar = (FontHeaders.BfbHeader.CharacterImageHeight*2)+2;
  539. MaxChars = SCRATCH_SIZE / BytesPerChar;
  540. CharsLeft = FontHeaders.BfbHeader.NumDbcsChars;
  541. ordinal = 0;
  542. while(CharsLeft) {
  543. Count = CharsLeft;
  544. if(Count > MaxChars) {
  545. Count = MaxChars;
  546. }
  547. if(_dos_read(FileHandle,ScratchBuffer,Count*BytesPerChar,&i)
  548. || (i != (Count*BytesPerChar))) {
  549. free(ScratchBuffer);
  550. goto c5;
  551. }
  552. CharsLeft -= Count;
  553. for(p=ScratchBuffer,i=0; i<Count; i++,p+=BytesPerChar,ordinal++) {
  554. if((p[0] < DBCS_FIRST_LEAD) || (p[0] > DBCS_LAST_LEAD)
  555. || (p[1] < DBCS_FIRST_TRAIL) || (p[1] > DBCS_LAST_TRAIL)) {
  556. //
  557. // Invalid DBCS value, skip this character
  558. //
  559. continue;
  560. }
  561. index = (unsigned)(p[0] - DBCS_FIRST_LEAD);
  562. index <<= 8;
  563. index |= p[1] - DBCS_FIRST_TRAIL;
  564. index -= (unsigned)(p[0] - DBCS_FIRST_LEAD) * (DBCS_FIRST_TRAIL + (255-DBCS_LAST_TRAIL));
  565. Table1[index] = ordinal;
  566. //
  567. // Cache first n chars that fit in the cache
  568. //
  569. if(CacheOrd < FONT_CACHE_CAPACITY) {
  570. *(unsigned *)&cache[CacheOrd*BytesPerChar] = ordinal+FontHeaders.BfbHeader.NumSbcsChars;
  571. memmove(cache+(CacheOrd*BytesPerChar)+2,&p[2],BytesPerChar-2);
  572. Table3[ordinal+FontHeaders.BfbHeader.NumSbcsChars] = CacheOrd++;
  573. }
  574. }
  575. }
  576. free(ScratchBuffer);
  577. //
  578. // Everything looks good. Set up globals.
  579. //
  580. memset(LeadByteTable,0,sizeof(LeadByteTable));
  581. for(Count=0;
  582. FontHeaders.BfbHeader.DbcsLeadTable[Count]
  583. && FontHeaders.BfbHeader.DbcsLeadTable[Count+1];
  584. Count+=2) {
  585. for(i = FontHeaders.BfbHeader.DbcsLeadTable[Count];
  586. i <= FontHeaders.BfbHeader.DbcsLeadTable[Count+1];
  587. i++) {
  588. LeadByteTable[(i-128)/8] |= BitValue[(i-128)%8];
  589. }
  590. }
  591. SbcsCharCount = FontHeaders.BfbHeader.NumSbcsChars;
  592. DbcsCharCount = FontHeaders.BfbHeader.NumDbcsChars;
  593. GlyphHeight = FontHeaders.BfbHeader.CharacterImageHeight;
  594. TopPad = FontHeaders.BfbHeader.CharacterTopPad;
  595. BottomPad = FontHeaders.BfbHeader.CharacterBottomPad;
  596. SbcsFileOffset = FontHeaders.BfbHeader.SbcsOffset;
  597. DbcsFileOffset = FontHeaders.BfbHeader.DbcsOffset;
  598. if(BootfontFileHandle != (unsigned)(-1)) {
  599. UnloadBootfontBin();
  600. }
  601. DbcsCharOrdinalOffsetTable = Table1;
  602. SbcsCharOrdinalOffsetTable = Table2;
  603. FontCacheTable = Table3;
  604. FontCache = cache;
  605. NextCacheSlot = nextslot;
  606. BootfontFileHandle = FileHandle;
  607. if(FontCharMap) {
  608. free(FontCharMap);
  609. FontCharMap = NULL;
  610. }
  611. if(FontCharData) {
  612. free(FontCharData);
  613. FontCharData = NULL;
  614. }
  615. b = TRUE;
  616. c5:
  617. if(!b) {
  618. free(cache);
  619. }
  620. c4:
  621. if(!b) {
  622. free(Table3);
  623. }
  624. c3:
  625. if(!b) {
  626. free(Table2);
  627. }
  628. c2:
  629. if(!b) {
  630. free(Table1);
  631. }
  632. c1:
  633. if(!b) {
  634. _dos_close(FileHandle);
  635. }
  636. return(b);
  637. }
  638. VOID
  639. UnloadBootfontBin(
  640. VOID
  641. )
  642. {
  643. _dos_close(BootfontFileHandle);
  644. BootfontFileHandle = (unsigned)(-1);
  645. PendingLeadByte = 0;
  646. free(DbcsCharOrdinalOffsetTable);
  647. free(SbcsCharOrdinalOffsetTable);
  648. free(FontCacheTable);
  649. free(FontCache);
  650. DbcsCharOrdinalOffsetTable = NULL;
  651. SbcsCharOrdinalOffsetTable = NULL;
  652. FontCacheTable = NULL;
  653. FontCache = NULL;
  654. }
  655. VOID
  656. _far
  657. FontGetInfo(
  658. OUT FPBYTE Width,
  659. OUT FPBYTE Height
  660. )
  661. {
  662. *Width = FONT_WIDTH;
  663. *Height = GlyphHeight + TopPad + BottomPad;
  664. }
  665. VOID
  666. _far
  667. FontWriteChar(
  668. IN UCHAR c,
  669. IN USHORT x,
  670. IN USHORT y,
  671. IN BYTE ForegroundPixelValue,
  672. IN BYTE BackgroundPixelValue
  673. )
  674. {
  675. BYTE PixelMap[2];
  676. if(BootfontFileHandle != (unsigned)(-1)) {
  677. //
  678. // Use bootfont.bin method
  679. //
  680. FontWriteBfbChar(c,x,y,ForegroundPixelValue,BackgroundPixelValue);
  681. return;
  682. }
  683. PixelMap[0] = BackgroundPixelValue;
  684. PixelMap[1] = ForegroundPixelValue;
  685. if((c < FontFirstChar) || (c > FontLastChar)) {
  686. c = FontDefaultChar;
  687. }
  688. //
  689. // Pad if necessary by filling in background
  690. //
  691. if(BackgroundPixelValue < VGAPIX_TRANSPARENT) {
  692. if(TopPad) {
  693. VgaClearRegion(x,y,FONT_WIDTH,TopPad,BackgroundPixelValue);
  694. }
  695. if(BottomPad) {
  696. VgaClearRegion(x,y+TopPad+GlyphHeight,FONT_WIDTH,BottomPad,BackgroundPixelValue);
  697. }
  698. }
  699. VgaBitBlt(
  700. x,
  701. y + TopPad,
  702. FONT_WIDTH,
  703. GlyphHeight,
  704. 1,
  705. FALSE,
  706. PixelMap,
  707. FontCharData + (FontCharMap[c-FontFirstChar].Offset - FontDataBaseOffset)
  708. );
  709. }
  710. VOID
  711. _far
  712. FontWriteString(
  713. IN UCHAR *String,
  714. IN USHORT x,
  715. IN USHORT y,
  716. IN BYTE ForegroundPixelValue,
  717. IN BYTE BackgroundPixelValue
  718. )
  719. {
  720. for( ; *String; String++) {
  721. FontWriteChar(*String,x,y,ForegroundPixelValue,BackgroundPixelValue);
  722. x += FONT_WIDTH;
  723. }
  724. PendingLeadByte = 0;
  725. }
  726. VOID
  727. FontWriteBfbChar(
  728. IN UCHAR c,
  729. IN USHORT x,
  730. IN USHORT y,
  731. IN BYTE ForegroundPixelValue,
  732. IN BYTE BackgroundPixelValue
  733. )
  734. {
  735. unsigned scale;
  736. unsigned index;
  737. unsigned Ordinal;
  738. unsigned i,read;
  739. ULONG FileOffset = 0;
  740. FPBYTE Glyph = NULL;
  741. BYTE PixelMap[2];
  742. FPBYTE p;
  743. if(PendingLeadByte) {
  744. //
  745. // Got second half of DBCS character. Render now.
  746. //
  747. index = (unsigned)(PendingLeadByte - DBCS_FIRST_LEAD);
  748. index <<= 8;
  749. index |= c - DBCS_FIRST_TRAIL;
  750. index -= (unsigned)(PendingLeadByte - DBCS_FIRST_LEAD) * (DBCS_FIRST_TRAIL + (255-DBCS_LAST_TRAIL));
  751. PendingLeadByte = 0;
  752. Ordinal = DbcsCharOrdinalOffsetTable[index];
  753. //
  754. // Is this character cached?
  755. //
  756. if(FontCacheTable[Ordinal+SbcsCharCount] == (unsigned)(-1)) {
  757. //
  758. // No, need to cache it.
  759. //
  760. FileOffset = ((ULONG)Ordinal * ((2 * GlyphHeight) + 2)) + DbcsFileOffset + 2;
  761. } else {
  762. //
  763. // Yes, get glyph.
  764. //
  765. Glyph = FontCache + (((2 * GlyphHeight) + 2) * FontCacheTable[Ordinal+SbcsCharCount]) + 2;
  766. }
  767. Ordinal += SbcsCharCount;
  768. x -= FONT_WIDTH;
  769. scale = 2;
  770. } else {
  771. //
  772. // See if DBCS char or a lead byte
  773. //
  774. if((c >= DBCS_FIRST_LEAD) && (LeadByteTable[(c-128)/8] & BitValue[(c-128)%8])) {
  775. PendingLeadByte = c;
  776. return;
  777. }
  778. //
  779. // SBCS char.
  780. //
  781. Ordinal = SbcsCharOrdinalOffsetTable[c-1];
  782. //
  783. // Is this character cached?
  784. //
  785. if(FontCacheTable[Ordinal] == (unsigned)(-1)) {
  786. //
  787. // No, need to cache it.
  788. //
  789. FileOffset = ((ULONG)Ordinal * (GlyphHeight + 1)) + SbcsFileOffset + 1;
  790. } else {
  791. //
  792. // Yes, get glyph
  793. //
  794. Glyph = FontCache + (((2 * GlyphHeight) + 2) * FontCacheTable[Ordinal]) + 2;
  795. }
  796. scale = 1;
  797. }
  798. if(FileOffset) {
  799. //
  800. // Pull the character in from the file.
  801. //
  802. Glyph = NULL;
  803. if(DosSeek(BootfontFileHandle,FileOffset,DOSSEEK_START) == FileOffset) {
  804. //
  805. // Point at the entry in the font cache where we're going
  806. // to stick the glyph.
  807. //
  808. p = FontCache + (NextCacheSlot * ((2 * GlyphHeight) + 2));
  809. //
  810. // Invalidate the caching for the character currently
  811. // cached in the slot we're going to overwrite. If the read
  812. // fails halfway through, the glyph may be trashed anyway,
  813. // so we do it before we know if the read succeeds.
  814. //
  815. FontCacheTable[*(unsigned *)p] = (unsigned)(-1);
  816. i = _dos_read(BootfontFileHandle,p+2,scale*GlyphHeight,&read);
  817. if(!i && (read == (scale * GlyphHeight))) {
  818. *(unsigned *)p = Ordinal;
  819. Glyph = p+2;
  820. FontCacheTable[Ordinal] = NextCacheSlot++;
  821. if(NextCacheSlot == FONT_CACHE_CAPACITY) {
  822. NextCacheSlot = 0;
  823. }
  824. }
  825. }
  826. }
  827. if(Glyph) {
  828. //
  829. // Pad if necessary by filling in background
  830. //
  831. if(BackgroundPixelValue < VGAPIX_TRANSPARENT) {
  832. if(TopPad) {
  833. VgaClearRegion(x,y,scale*FONT_WIDTH,TopPad,BackgroundPixelValue);
  834. }
  835. if(BottomPad) {
  836. VgaClearRegion(x,y+TopPad+GlyphHeight,scale*FONT_WIDTH,BottomPad,BackgroundPixelValue);
  837. }
  838. }
  839. PixelMap[0] = BackgroundPixelValue;
  840. PixelMap[1] = ForegroundPixelValue;
  841. VgaBitBlt(
  842. x,
  843. y + TopPad,
  844. scale*FONT_WIDTH,
  845. GlyphHeight,
  846. scale,
  847. FALSE,
  848. PixelMap,
  849. Glyph
  850. );
  851. } else {
  852. //
  853. // Put a block up there.
  854. //
  855. VgaClearRegion(x,y,scale*FONT_WIDTH,TopPad+BottomPad+GlyphHeight,ForegroundPixelValue);
  856. }
  857. }