Leaked source code of windows server 2003
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.

1307 lines
40 KiB

  1. /*************************** Module Header **********************************
  2. * pfm2ifi
  3. * Program to read Windows 3.1 PFM format data and convert to NT's
  4. * IFIMETRICS data. Note that since IFIMETRICS is somewhat more
  5. * elaborate than PFM data, some of the values are best guesses.
  6. * These are made on the basis of educated guesses.
  7. *
  8. * Copyright (C) 1992, Microsoft Corporation
  9. *
  10. ****************************************************************************/
  11. #include "StdAfx.h"
  12. #if (_WIN32_WINNT < 0x0500)
  13. typedef unsigned long DESIGNVECTOR;
  14. #endif
  15. #include <winddi.h>
  16. #include <win30def.h>
  17. #include <uni16gpc.h>
  18. #include <uni16res.h>
  19. #include "raslib.h"
  20. #include "fontinst.h"
  21. #undef DBG
  22. #define ALIAS_EXT "._al" /* The extension on an alias file */
  23. /* Function prototypes */
  24. char **ppcGetAlias( HANDLE, const char * );
  25. PBYTE MapFileA( LPCSTR, DWORD * );
  26. BOOL bValidatePFM( BYTE *, DWORD );
  27. CD *GetFontSel(HANDLE hHeap, FONTDAT *pFDat, int bSelect) {
  28. LOCD locd; /* From originating data */
  29. CD *pCD;
  30. CD *pCDOut; /* Copy data to here */
  31. locd = bSelect ? pFDat->DI.locdSelect : pFDat->DI.locdUnSelect;
  32. if( locd != -1 ) // (NOOCD extended to a long)
  33. {
  34. int size;
  35. CD cdTmp; /* For alignment problems */
  36. pCD = (CD *)(pFDat->pBase + locd);
  37. /*
  38. * The data pointed at by pCD may not be aligned, so we copy
  39. * it into a local structure. This local structure then allows
  40. * us to determine how big the CD really is (using it's length field),
  41. * so then we can allocate storage and copy as required.
  42. */
  43. memcpy( &cdTmp, (LPSTR)pCD, sizeof(CD) );
  44. /* Allocate storage area in the heap */
  45. size = cdTmp.wLength + sizeof(CD);
  46. pCDOut = (CD *)HeapAlloc( hHeap, 0, (size + 1) & ~0x1 );
  47. //raid 43535
  48. if (pCDOut == NULL){
  49. return 0;
  50. }
  51. memcpy( pCDOut, (BYTE *)pCD, size );
  52. return pCDOut;
  53. }
  54. return 0;
  55. }
  56. short *GetWidthVector(HANDLE hHeap, FONTDAT *pFDat) {
  57. /*
  58. * For debugging code, verify that we have a width table! Then,
  59. * allocate memory and copy into it.
  60. */
  61. short *pus; /* Destination address */
  62. int cb; /* Number of bytes required */
  63. /*
  64. * There are LastChar - FirstChar width entries, plus the default
  65. * char. And the widths are shorts.
  66. */
  67. cb = (pFDat->PFMH.dfLastChar - pFDat->PFMH.dfFirstChar + 2) * sizeof( short );
  68. pus = (short *)HeapAlloc( hHeap, 0, cb );
  69. /*
  70. * If this is a bitmap font, then use the width table, but use
  71. * the extent table (in PFMEXTENSION area) as these are ready to
  72. * to scale.
  73. */
  74. if( pus )
  75. {
  76. BYTE *pb;
  77. if( pFDat->pETM &&
  78. pFDat->pETM->emMinScale != pFDat->pETM->emMaxScale &&
  79. pFDat->PFMExt.dfExtentTable )
  80. {
  81. /* Scalable, so use the extent table */
  82. pb = pFDat->pBase + pFDat->PFMExt.dfExtentTable;
  83. }
  84. else
  85. {
  86. /* Not scalable. */
  87. pb = pFDat->pBase + sizeof( res_PFMHEADER );
  88. }
  89. memcpy( pus, pb, cb );
  90. }
  91. return pus;
  92. }
  93. static void ConvFontRes(register FONTDAT *pFDat) {
  94. BYTE *pb; /* Miscellaneous operations */
  95. res_PFMHEADER *pPFM; /* The resource data format */
  96. res_PFMEXTENSION *pR_PFME; /* Resource data PFMEXT format */
  97. /*
  98. * Align the PFMHEADER structure.
  99. */
  100. pPFM = (res_PFMHEADER *)pFDat->pBase;
  101. pFDat->PFMH.dfType = pPFM->dfType;
  102. pFDat->PFMH.dfPoints = pPFM->dfPoints;
  103. pFDat->PFMH.dfVertRes = pPFM->dfVertRes;
  104. pFDat->PFMH.dfHorizRes = pPFM->dfHorizRes;
  105. pFDat->PFMH.dfAscent = pPFM->dfAscent;
  106. pFDat->PFMH.dfInternalLeading = pPFM->dfInternalLeading;
  107. pFDat->PFMH.dfExternalLeading = pPFM->dfExternalLeading;
  108. pFDat->PFMH.dfItalic = pPFM->dfItalic;
  109. pFDat->PFMH.dfUnderline = pPFM->dfUnderline;
  110. pFDat->PFMH.dfStrikeOut = pPFM->dfStrikeOut;
  111. pFDat->PFMH.dfWeight = DwAlign2( pPFM->b_dfWeight );
  112. pFDat->PFMH.dfCharSet = pPFM->dfCharSet;
  113. pFDat->PFMH.dfPixWidth = pPFM->dfPixWidth;
  114. pFDat->PFMH.dfPixHeight = pPFM->dfPixHeight;
  115. pFDat->PFMH.dfPitchAndFamily = pPFM->dfPitchAndFamily;
  116. pFDat->PFMH.dfAvgWidth = DwAlign2( pPFM->b_dfAvgWidth );
  117. pFDat->PFMH.dfMaxWidth = DwAlign2( pPFM->b_dfMaxWidth );
  118. pFDat->PFMH.dfFirstChar = pPFM->dfFirstChar;
  119. pFDat->PFMH.dfLastChar = pPFM->dfLastChar;
  120. pFDat->PFMH.dfDefaultChar = pPFM->dfDefaultChar;
  121. pFDat->PFMH.dfBreakChar = pPFM->dfBreakChar;
  122. pFDat->PFMH.dfWidthBytes = DwAlign2( pPFM->b_dfWidthBytes );
  123. pFDat->PFMH.dfDevice = DwAlign4( pPFM->b_dfDevice );
  124. pFDat->PFMH.dfFace = DwAlign4( pPFM->b_dfFace );
  125. pFDat->PFMH.dfBitsPointer = DwAlign4( pPFM->b_dfBitsPointer );
  126. pFDat->PFMH.dfBitsOffset = DwAlign4( pPFM->b_dfBitsOffset );
  127. /*
  128. * The PFMEXTENSION follows the PFMHEADER structure plus any width
  129. * table info. The width table will be present if the PFMHEADER has
  130. * a zero width dfPixWidth. If present, adjust the extension address.
  131. */
  132. pb = pFDat->pBase + sizeof( res_PFMHEADER ); /* Size in resource data */
  133. if( pFDat->PFMH.dfPixWidth == 0 )
  134. pb += (pFDat->PFMH.dfLastChar - pFDat->PFMH.dfFirstChar + 2) * sizeof( short );
  135. pR_PFME = (res_PFMEXTENSION *)pb;
  136. /*
  137. * Now convert the extended PFM data.
  138. */
  139. pFDat->PFMExt.dfSizeFields = pR_PFME->dfSizeFields;
  140. pFDat->PFMExt.dfExtMetricsOffset = DwAlign4( pR_PFME->b_dfExtMetricsOffset );
  141. pFDat->PFMExt.dfExtentTable = DwAlign4( pR_PFME->b_dfExtentTable );
  142. pFDat->PFMExt.dfOriginTable = DwAlign4( pR_PFME->b_dfOriginTable );
  143. pFDat->PFMExt.dfPairKernTable = DwAlign4( pR_PFME->b_dfPairKernTable );
  144. pFDat->PFMExt.dfTrackKernTable = DwAlign4( pR_PFME->b_dfTrackKernTable );
  145. pFDat->PFMExt.dfDriverInfo = DwAlign4( pR_PFME->b_dfDriverInfo );
  146. pFDat->PFMExt.dfReserved = DwAlign4( pR_PFME->b_dfReserved );
  147. memcpy( &pFDat->DI, pFDat->pBase + pFDat->PFMExt.dfDriverInfo,
  148. sizeof( DRIVERINFO ) );
  149. /*
  150. * Also need to fill in the address of the EXTTEXTMETRIC. This
  151. * is obtained from the extended PFM data that we just converted!
  152. */
  153. if( pFDat->PFMExt.dfExtMetricsOffset )
  154. {
  155. /*
  156. * This structure is only an array of shorts, so there is
  157. * no alignment problem. However, the data itself is not
  158. * necessarily aligned in the resource!
  159. */
  160. int cbSize;
  161. BYTE *pbIn; /* Source of data to shift */
  162. pbIn = pFDat->pBase + pFDat->PFMExt.dfExtMetricsOffset;
  163. cbSize = DwAlign2( pbIn );
  164. if( cbSize == sizeof( EXTTEXTMETRIC ) )
  165. {
  166. /* Simply copy it! */
  167. memcpy( pFDat->pETM, pbIn, cbSize );
  168. }
  169. else
  170. pFDat->pETM = NULL; /* Not our size, so best not use it */
  171. }
  172. else
  173. pFDat->pETM = NULL; /* Is non-zero when passed in */
  174. return;
  175. }
  176. BOOL ConvertPFMToIFI(LPCTSTR lpstrPFM, LPCTSTR lpstrIFI,
  177. LPCTSTR lpstrUniq) {
  178. int cWidth; /* Number of entries in width table */
  179. HANDLE hheap; /* Handle to heap for storage */
  180. HANDLE hOut; /* The output file */
  181. DWORD dwSize; /* Size of input file */
  182. char **ppcAliasList; /* The alias list of names, if present */
  183. PWSTR pwstrUniqNm; /* Unique name */
  184. IFIMETRICS *pIFI;
  185. CD *pCDSel; /* Font selection command descriptor */
  186. CD *pCDDesel; /* Deselection - typically not required */
  187. FI_DATA fid; /* Keep track of stuff in the file */
  188. FONTDAT FDat; /* Converted form of data */
  189. EXTTEXTMETRIC etm; /* Additional data on this font */
  190. INT bPrint = 0;
  191. char acMessage[100];
  192. /*
  193. * Create us a heap, since all the functions we steal from rasdd
  194. * require that we pass a heap handle!
  195. */
  196. if( !(hheap = HeapCreate(HEAP_NO_SERIALIZE, 10 * 1024, 256 * 1024 ))) {
  197. /* Not too good! */
  198. wsprintf(acMessage, _T("HeapCreate() fails in pfm2ifi") ) ;
  199. MessageBox(NULL, acMessage, NULL, MB_OK);
  200. return FALSE;
  201. }
  202. cWidth = strlen(lpstrUniq);
  203. if ( !(pwstrUniqNm = (PWSTR)HeapAlloc( hheap, 0, (cWidth + 1) * sizeof( WCHAR ) ) ) ){
  204. wsprintf(acMessage, "HeapAlloc() fails in pfm2ifi" );
  205. MessageBox(NULL, acMessage, NULL, MB_OK);
  206. return FALSE;
  207. }
  208. MultiByteToWideChar( CP_ACP, 0, lpstrUniq, cWidth, pwstrUniqNm, cWidth );
  209. *(pwstrUniqNm + cWidth) = 0;
  210. /*
  211. * Zero out the header structure. This means we can ignore any
  212. * irrelevant fields, which will then have the value 0, which is
  213. * the value for not used.
  214. */
  215. memset( &fid, 0, sizeof( fid ) );
  216. memset( &FDat, 0, sizeof( FONTDAT ) );
  217. /*
  218. * First step is to open the input file - this is done via MapFileA.
  219. * We then pass the returned address around to various functions
  220. * which do the conversion to something we understand.
  221. */
  222. if( !(FDat.pBase = MapFileA( lpstrPFM, &dwSize))) {
  223. wsprintf(acMessage, "Cannot open input file: %s", lpstrPFM);
  224. MessageBox(NULL, acMessage, NULL, MB_OK);
  225. return FALSE;
  226. }
  227. /*
  228. * Do some validation on the input file.
  229. */
  230. if (!bValidatePFM( FDat.pBase, dwSize)) {
  231. wsprintf(acMessage, "%s is not a valid PFM file", lpstrPFM);
  232. return FALSE;
  233. }
  234. /*
  235. * If there is a file with the same name as the input file, BUT with
  236. * an extension of ._al, this is presumed to be an alias file. An
  237. * alias file consists of a set of alias names for this font. The
  238. * reason is that font names have not been very consistent, so we
  239. * provide aliases to the font mapper, thus maintaining the format
  240. * information for old documents.
  241. * The file format is one alias per input line. Names which
  242. * are duplicates of the name in the PFM file will be ignored.
  243. */
  244. ppcAliasList = ppcGetAlias(hheap, lpstrPFM);
  245. FDat.pETM = &etm; /* Important for scalable fonts */
  246. /*
  247. * Create the output file.
  248. */
  249. hOut = CreateFile( lpstrIFI, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  250. FILE_ATTRIBUTE_NORMAL, 0);
  251. if( hOut == (HANDLE)-1) {
  252. wsprintf(acMessage, "Could not create output file '%s'", lpstrIFI);
  253. MessageBox(NULL, acMessage, NULL, MB_OK);
  254. return FALSE;
  255. }
  256. /*
  257. * Now have the data, so civilise it: alignment etc.
  258. */
  259. ConvFontRes( &FDat );
  260. fid.fCaps = FDat.DI.fCaps;
  261. fid.wFontType = FDat.DI.wFontType; /* Device FOnt Type */
  262. fid.wPrivateData = FDat.DI.wPrivateData;
  263. fid.sYAdjust = FDat.DI.sYAdjust;
  264. fid.sYMoved = FDat.DI.sYMoved;
  265. fid.wXRes = FDat.PFMH.dfHorizRes;
  266. fid.wYRes = FDat.PFMH.dfVertRes;
  267. /*
  268. * Convert the font metrics. Note that the last two parameters are
  269. * chosen with the understanding of how this function does its scaling.
  270. * Any changes to that method will require changes here too!!!
  271. */
  272. pIFI = FontInfoToIFIMetric( &FDat, hheap, pwstrUniqNm, ppcAliasList );
  273. fid.dsIFIMet.pvData = pIFI;
  274. if (fid.dsIFIMet.pvData == 0) {
  275. /* Should not happen! */
  276. MessageBox(NULL, "Could not create IFIMETRICS", NULL, MB_OK);
  277. return FALSE;
  278. }
  279. fid.dsIFIMet.cBytes = pIFI->cjThis;
  280. /*
  281. * Also need to record which CTT is used for this font. When the
  282. * resource is loaded, this is turned into the address of the
  283. * corresponding CTT, which is a resource somewhere else in the
  284. * mini-driver, or in rasdd.
  285. */
  286. fid.dsCTT.cBytes = FDat.DI.sTransTab;
  287. /*
  288. * Note that IFIMETRICS is only WORD aligned. However, since the
  289. * following data only requires WORD alignment, we can ignore any
  290. * lack of DWORD alignment.
  291. */
  292. /*
  293. * If there is a width vector, now is the time to extract it.
  294. * There is one if dfPixWidth field in the PFM data is zero.
  295. */
  296. if( FDat.PFMH.dfPixWidth == 0 &&
  297. (fid.dsWidthTab.pvData = GetWidthVector( hheap, &FDat )) )
  298. {
  299. cWidth = pIFI->chLastChar - pIFI->chFirstChar + 1;
  300. fid.dsWidthTab.cBytes = cWidth * sizeof( short );
  301. }
  302. else
  303. fid.dsWidthTab.cBytes = 0;
  304. /*
  305. * Finally, the font selection/deselection strings. These are
  306. * byte strings, sent directly to the printer. Typically there
  307. * is no deselection string. These require WORD alignment, and
  308. * the GetFontSel function will round the size to that requirement.
  309. * Since we follow the width tables, WORD alignment is guaranteed.
  310. */
  311. if( pCDSel = GetFontSel( hheap, &FDat, 1 ) )
  312. {
  313. /* Have a selection string, so update the red tape etc. */
  314. fid.dsSel.cBytes = (int)HeapSize( hheap, 0, (LPSTR)pCDSel );
  315. fid.dsSel.pvData = pCDSel;
  316. }
  317. if( pCDDesel = GetFontSel( hheap, &FDat, 0 ) )
  318. {
  319. /* Also have a deselection string, so record its presence */
  320. fid.dsDesel.cBytes = (int)HeapSize( hheap, 0, (LPSTR)pCDDesel );
  321. fid.dsDesel.pvData = pCDDesel;
  322. }
  323. if( FDat.pETM == NULL )
  324. {
  325. fid.dsETM.pvData = NULL;
  326. fid.dsETM.cBytes = 0;
  327. }
  328. else
  329. {
  330. fid.dsETM.pvData = (VOID*) &etm;
  331. fid.dsETM.cBytes = sizeof(etm);
  332. }
  333. /*
  334. * Time to write the output file.
  335. */
  336. if( iWriteFDH( hOut, &fid ) < 0 )
  337. MessageBox(NULL, "CANNOT WRITE OUTPUT FILE", NULL, MB_OK);
  338. /* All done, so clean up and away */
  339. UnmapViewOfFile( FDat.pBase ); /* Input no longer needed */
  340. HeapDestroy(hheap); /* Probably not needed */
  341. CloseHandle(hOut); // Really, this would be a good idea!
  342. return TRUE;
  343. }
  344. /*
  345. * An ASCII based copy of KentSe's mapfile function.
  346. */
  347. /************************** Function Header *********************************
  348. * PVOID MapFileA( psz, pdwSize )
  349. *
  350. * Returns a pointer to the mapped file defined by psz.
  351. *
  352. * Parameters:
  353. * psz ASCII string containing fully qualified pathname of the
  354. * file to map.
  355. *
  356. * Returns:
  357. * Pointer to mapped memory if success, NULL if error.
  358. *
  359. * NOTE: UnmapViewOfFile will have to be called by the user at some
  360. * point to free up this allocation.
  361. *
  362. * History:
  363. * 11:32 on Tue 29 Jun 1993 -by- Lindsay Harris [lindsayh]
  364. * Return the size of the file too.
  365. *
  366. * 05-Nov-1991 -by- Kent Settle [kentse]
  367. * Wrote it.
  368. ***************************************************************************/
  369. PBYTE
  370. MapFileA(LPCSTR psz, PDWORD pdwSize) {
  371. void *pv;
  372. HANDLE hFile, hFileMap;
  373. BY_HANDLE_FILE_INFORMATION x;
  374. /*
  375. * First open the file. This is required to do the mapping, but
  376. * it also allows us to find the size, which is used for validating
  377. * that we have something resembling a PFM file.
  378. */
  379. hFile = CreateFileA(psz, GENERIC_READ, FILE_SHARE_READ,
  380. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  381. NULL );
  382. if( hFile == INVALID_HANDLE_VALUE )
  383. {
  384. printf( "MapFileA: CreateFileA( %s ) failed.\n", psz );
  385. return NULL;
  386. }
  387. /*
  388. * Find the size of the file now, and set it in the caller's area.
  389. */
  390. if( GetFileInformationByHandle( hFile, &x ) )
  391. *pdwSize = x.nFileSizeLow;
  392. else
  393. *pdwSize = 0;
  394. // create the mapping object.
  395. if( !(hFileMap = CreateFileMappingA( hFile, NULL, PAGE_READONLY,
  396. 0, 0, NULL )) )
  397. {
  398. printf( "MapFileA: CreateFileMapping failed.\n" );
  399. return NULL;
  400. }
  401. // get the pointer mapped to the desired file.
  402. if( !(pv = MapViewOfFile( hFileMap, FILE_MAP_READ, 0, 0, 0 )) )
  403. {
  404. printf( "MapFileA: MapViewOfFile failed.\n" );
  405. return NULL;
  406. }
  407. // now that we have our pointer, we can close the file and the
  408. // mapping object.
  409. if( !CloseHandle( hFileMap ) )
  410. printf( "MapFileA: CloseHandle( hFileMap ) failed.\n" );
  411. if( !CloseHandle( hFile ) )
  412. printf( "MapFileA: CloseHandle( hFile ) failed.\n" );
  413. return (PBYTE) pv;
  414. }
  415. /************************** Function Header *******************************
  416. * bValidatePFM
  417. * Look at a memory mapped PFM file, and see if it seems reasonable.
  418. *
  419. * RETURNS:
  420. * TRUE if OK, else FALSE
  421. *
  422. * HISTORY:
  423. * 12:22 on Tue 29 Jun 1993 -by- Lindsay Harris [lindsayh]
  424. * First version to improve usability of pfm2ifi.
  425. *
  426. **************************************************************************/
  427. BOOL
  428. bValidatePFM( PBYTE pBase, DWORD dwSize ) {
  429. DWORD dwOffset; /* Calculate offset of interest as we go */
  430. res_PFMHEADER *rpfm; /* In Win 3.1 format, UNALIGNED!! */
  431. res_PFMEXTENSION *rpfme; /* Final access to offset to DRIVERINFO */
  432. DRIVERINFO di; /* The actual DRIVERINFO data! */
  433. /*
  434. * First piece of sanity checking is the size! It must be at least
  435. * as large as a PFMHEADER structure plus a DRIVERINFO structure.
  436. */
  437. if( dwSize < (sizeof( res_PFMHEADER ) + (sizeof( DRIVERINFO ) ) +
  438. sizeof( res_PFMEXTENSION )) )
  439. {
  440. return FALSE;
  441. }
  442. /*
  443. * Step along to find the DRIVERINFO structure, as this contains
  444. * some identifying information that we match to look for legitimacy.
  445. */
  446. rpfm = (res_PFMHEADER *)pBase; /* Looking for fixed pitch */
  447. dwOffset = sizeof( res_PFMHEADER );
  448. if( rpfm->dfPixWidth == 0 )
  449. {
  450. /* Proportionally spaced, so allow for the width table too! */
  451. dwOffset += (rpfm->dfLastChar - rpfm->dfFirstChar + 2) * sizeof( short );
  452. }
  453. rpfme = (res_PFMEXTENSION *)(pBase + dwOffset);
  454. /* Next is the PFMEXTENSION data */
  455. dwOffset += sizeof( res_PFMEXTENSION );
  456. if( dwOffset >= dwSize )
  457. {
  458. return FALSE;
  459. }
  460. dwOffset = DwAlign4( rpfme->b_dfDriverInfo );
  461. if( (dwOffset + sizeof( DRIVERINFO )) > dwSize )
  462. {
  463. return FALSE;
  464. }
  465. /*
  466. * A memcpy is used because this data is typically not aigned. Ugh!
  467. */
  468. memcpy( &di, pBase + dwOffset, sizeof( di ) );
  469. if( di.sVersion > DRIVERINFO_VERSION )
  470. {
  471. return FALSE;
  472. }
  473. return TRUE;
  474. }
  475. /************************** Function Header *******************************
  476. * ppcGetAlias
  477. * Return a pointer to an array of pointers to aliases for the given
  478. * font name.
  479. *
  480. * RETURNS:
  481. * Pointer to pointer to aliases; 0 on error.
  482. *
  483. * HISTORY:
  484. * 10:02 on Fri 28 May 1993 -by- Lindsay Harris [lindsayh]
  485. * First version.
  486. *
  487. ***************************************************************************/
  488. char **
  489. ppcGetAlias( HANDLE hheap, LPCSTR pcFile ) {
  490. char *pcAlias; /* The name of the alias file */
  491. char *pcTmp; /* Temporary stuffing around */
  492. char *pcTmp2; /* Yet more temporary stuffing around */
  493. char **ppcRet; /* The return value */
  494. FILE *fAlias; /* The alias file, if there */
  495. ppcRet = (char **)0;
  496. /* The 5 is for the terminating NUL plus the characters "._al" */
  497. pcAlias = (char *)HeapAlloc( hheap, 0, strlen( pcFile ) + 5 );
  498. if( pcAlias )
  499. {
  500. /* Generate the file name, try to open it */
  501. strcpy( pcAlias, pcFile );
  502. if( !(pcTmp = strrchr( pcAlias, '\\' )) )
  503. {
  504. /* No \ in name - is there a /? */
  505. if( !(pcTmp = strrchr( pcAlias, '/' )) )
  506. {
  507. /* Must be a simple name, so point at the start of it */
  508. pcTmp = pcAlias;
  509. }
  510. }
  511. /*
  512. * Now pcTmp points at the start of the last component of the
  513. * file name. IF this contains a '.', then overwrite whatever
  514. * follows by our extension, otherwise add our extension to the end.
  515. */
  516. if( !(pcTmp2 = strrchr( pcTmp, '.' )) )
  517. pcTmp2 = pcTmp + strlen( pcTmp );
  518. strcpy( pcTmp2, ALIAS_EXT );
  519. fAlias = fopen( pcAlias, "r" );
  520. HeapFree( hheap, 0, (LPSTR)pcAlias ); /* No longer used */
  521. if( fAlias )
  522. {
  523. /*
  524. * First, read the file to count how many lines there are.
  525. * Thus we can allocate the storage for the array of pointers.
  526. */
  527. char acLine[ 256 ]; /* For reading the input line */
  528. int iNum; /* Count the number of lines! */
  529. int iIndex; /* Stepping through input */
  530. iNum = 0;
  531. while( fgets( acLine, sizeof( acLine ), fAlias ) )
  532. ++iNum;
  533. if( iNum )
  534. {
  535. /* Some data available, so allocate pointer and off we go */
  536. ++iNum;
  537. ppcRet = (char **)HeapAlloc( hheap, 0, iNum * sizeof( char * ) );
  538. if( ppcRet )
  539. {
  540. iIndex = 0;
  541. rewind( fAlias ); /* Back to the start */
  542. while( iIndex < iNum &&
  543. fgets( acLine, sizeof( acLine ), fAlias ) )
  544. {
  545. /*
  546. * Do a little editing - delete leading space,
  547. * trailing space + control characters.
  548. */
  549. pcTmp = acLine;
  550. while( *pcTmp &&
  551. (!isprint( *pcTmp ) || isspace( *pcTmp )) )
  552. ++pcTmp;
  553. /* Filter out the ending stuff too! */
  554. pcTmp2 = pcTmp + strlen( pcTmp );
  555. while( pcTmp2 > pcTmp &&
  556. (!isprint( *pcTmp2 ) || isspace( *pcTmp2 )) )
  557. {
  558. /*
  559. * Zap it, then onto the previous char. NOTE
  560. * that this is not the best solution, but it
  561. * is convenient.
  562. */
  563. *pcTmp2-- = '\0'; /* Zap the end */
  564. }
  565. ppcRet[ iIndex ] = (PSTR) HeapAlloc( hheap, 0,
  566. strlen( pcTmp ) + 1 );
  567. if( ppcRet[ iIndex ] )
  568. {
  569. /* Copy input to new buffer */
  570. strcpy( ppcRet[ iIndex ], pcTmp );
  571. ++iIndex; /* Next output slot */
  572. }
  573. }
  574. ppcRet[ iIndex ] = NULL;
  575. }
  576. }
  577. }
  578. }
  579. return ppcRet;
  580. }
  581. /************************* Function Header ********************************
  582. * strcpy2WChar
  583. * Convert a char * string to a WCHAR string. Basically this means
  584. * converting each input character to 16 bits by zero extending it.
  585. *
  586. * RETURNS:
  587. * Value of first parameter.
  588. *
  589. * HISTORY:
  590. * 12:35 on Thu 18 Mar 1993 -by- Lindsay Harris [lindsayh]
  591. * Use the correct conversion method to Unicode.
  592. *
  593. * 09:36 on Thu 07 Mar 1991 -by- Lindsay Harris [lindsayh]
  594. * Created it.
  595. *
  596. **************************************************************************/
  597. static PWSTR strcpy2WChar(PWSTR pWCHOut, LPSTR lpstr) {
  598. /*
  599. * Put buffering around the NLS function that does all this stuff.
  600. */
  601. int cchIn; /* Number of input chars */
  602. cchIn = strlen( lpstr ) + 1;
  603. MultiByteToWideChar( CP_ACP, 0, lpstr, cchIn, pWCHOut, cchIn );
  604. return pWCHOut;
  605. }
  606. /*************************** Function Header *****************************
  607. * FontInfoToIFIMetric
  608. * Convert the Win 3.1 format PFM data to NT's IFIMETRICS. This is
  609. * typically done before the minidrivers are built, so that they
  610. * can include IFIMETRICS, and thus have less work to do at run time.
  611. *
  612. * RETURNS:
  613. * IFIMETRICS structure, allocated from heap; NULL on error
  614. *
  615. * HISTORY:
  616. * 13:58 on Fri 28 May 1993 -by- Lindsay Harris [lindsayh]
  617. * Goes back a long way, I am now adding the aliasing code.
  618. *
  619. **************************************************************************/
  620. IFIMETRICS *
  621. FontInfoToIFIMetric(FONTDAT *pFDat, HANDLE hheap, PWSTR pwstrUniqNm,
  622. char **ppcAliasList) {
  623. register IFIMETRICS *pIFI;
  624. FWORD fwdExternalLeading;
  625. int cWC; /* Number of WCHARS to add */
  626. int cbAlloc; /* Number of bytes to allocate */
  627. int iI; /* Loop index */
  628. int iCount; /* Number of characters in Win 3.1 font */
  629. int cAlias; /* Number of aliases we have found */
  630. WCHAR *pwch; /* For string manipulations */
  631. WCHAR awcAttrib[ 256 ]; /* Generate attributes + BYTE -> WCHAR */
  632. BYTE abyte[ 256 ]; /* Used (with above) to get wcLastChar etc */
  633. /*
  634. * First step is to determine the length of the WCHAR strings
  635. * that are placed at the end of the IFIMETRICS, since we need
  636. * to include these in our storage allocation.
  637. *
  638. * There may also be an alias list. If so, we need to include
  639. * that in our calculation. We have a NULL terminated array
  640. * of pointers to the aliases, one of which is most likely the
  641. * name in the Win 3.1 format data.
  642. */
  643. cWC = 0;
  644. cAlias = 0; /* No aliases is the default */
  645. if( ppcAliasList )
  646. {
  647. /* There are aliases - count them and determine their size */
  648. char *pc;
  649. iI = 0;
  650. while( pc = ppcAliasList[ iI ] )
  651. {
  652. if( strcmp( pc, (LPCSTR) pFDat->pBase + pFDat->PFMH.dfFace ) )
  653. {
  654. /* Not a match, so add this one in too! */
  655. cWC += strlen( pc ) + 1; /* Terminating NUL */
  656. ++cAlias;
  657. }
  658. ++iI;
  659. }
  660. ++cWC; /* There is an extra NUL to terminate the list */
  661. }
  662. cWC += 3 * strlen( (LPCSTR) pFDat->pBase + pFDat->PFMH.dfFace ); /* Base name */
  663. /*
  664. * Produce the desired attributes: Italic, Bold, Light etc.
  665. * This is largely guesswork, and there should be a better method.
  666. */
  667. awcAttrib[ 0 ] = L'\0';
  668. awcAttrib[ 1 ] = L'\0'; /* Write out an empty string */
  669. if( pFDat->PFMH.dfItalic )
  670. wcscat( awcAttrib, L" Italic" );
  671. if( pFDat->PFMH.dfWeight >= 700 )
  672. wcscat( awcAttrib, L" Bold" );
  673. else
  674. {
  675. if( pFDat->PFMH.dfWeight < 200 )
  676. wcscat( awcAttrib, L" Light" );
  677. }
  678. /*
  679. * The attribute string appears in 3 entries of IFIMETRICS, so
  680. * calculate how much storage this will take. NOTE THAT THE LEADING
  681. * CHAR IN awcAttrib is NOT placed in the style name field, so we
  682. * subtract one in the following formula to account for this.
  683. */
  684. if( awcAttrib[ 0 ] )
  685. cWC += 3 * wcslen( awcAttrib ) - 1;
  686. cWC += wcslen( pwstrUniqNm ) + 1; /* SHOULD BE PRINTER NAME */
  687. cWC += 4; /* Terminating nulls */
  688. cbAlloc = sizeof( IFIMETRICS ) + sizeof( WCHAR ) * cWC;
  689. pIFI = (IFIMETRICS *)HeapAlloc( hheap, 0, cbAlloc );
  690. // raid 43536 prefix
  691. if (pIFI == NULL){
  692. return FALSE;
  693. }
  694. ZeroMemory( pIFI, cbAlloc ); /* In case we miss something */
  695. pIFI->cjThis = cbAlloc; /* Everything */
  696. pIFI->cjIfiExtra = 0; // Correct for all pre 4.0
  697. /* The family name: straight from the FaceName - no choice?? */
  698. pwch = (WCHAR *)(pIFI + 1); /* At the end of the structure */
  699. pIFI->dpwszFamilyName = (unsigned)((BYTE *)pwch - (BYTE *)pIFI);
  700. strcpy2WChar( pwch, (LPSTR) pFDat->pBase + pFDat->PFMH.dfFace ); /* Base name */
  701. pwch += wcslen( pwch ) + 1; /* Skip what we just put in */
  702. /*
  703. * Append the alias list to the end of this, if there is an alias list.
  704. */
  705. if( cAlias )
  706. {
  707. /* Found some aliases - add them on. */
  708. char *pc;
  709. cAlias = 0;
  710. while( pc = ppcAliasList[ cAlias ] )
  711. {
  712. if( strcmp( pc, (LPCSTR) pFDat->pBase + pFDat->PFMH.dfFace ) )
  713. {
  714. /* Not a match, so add this one in too! */
  715. strcpy2WChar( pwch, pc );
  716. pwch += wcslen( pwch ) + 1; /* Next slot to fill */
  717. }
  718. ++cAlias;
  719. }
  720. /*
  721. * The list is terminated with a double NUL.
  722. */
  723. *pwch++ = L'\0';
  724. }
  725. /* Now the face name: we add bold, italic etc to family name */
  726. pIFI->dpwszFaceName = (unsigned)((BYTE *)pwch - (BYTE *)pIFI);
  727. strcpy2WChar( pwch, (LPSTR) pFDat->pBase + pFDat->PFMH.dfFace ); /* Base name */
  728. wcscat( pwch, awcAttrib );
  729. /* Now the unique name - well, sort of, anyway */
  730. pwch += wcslen( pwch ) + 1; /* Skip what we just put in */
  731. pIFI->dpwszUniqueName = (unsigned)((BYTE *)pwch - (BYTE *)pIFI);
  732. wcscpy( pwch, pwstrUniqNm ); /* Append printer name for uniqueness */
  733. wcscat( pwch, L" " );
  734. wcscat( pwch, (PWSTR)((BYTE *)pIFI + pIFI->dpwszFaceName) );
  735. /* Onto the attributes only component */
  736. pwch += wcslen( pwch ) + 1; /* Skip what we just put in */
  737. pIFI->dpwszStyleName = (unsigned)((BYTE *)pwch - (BYTE *)pIFI);
  738. wcscat( pwch, &awcAttrib[ 1 ] );
  739. #if DBG
  740. /*
  741. * Check on a few memory sizes: JUST IN CASE.....
  742. */
  743. if( (wcslen( awcAttrib ) * sizeof( WCHAR )) >= sizeof( awcAttrib ) )
  744. {
  745. DbgPrint( "Rasdd!pfm2ifi: STACK CORRUPTED BY awcAttrib" );
  746. HeapFree( hheap, 0, (LPSTR)pIFI ); /* No memory leaks */
  747. return 0;
  748. }
  749. if( ((BYTE *)(pwch + wcslen( pwch ) + 1)) > ((BYTE *)pIFI + cbAlloc) )
  750. {
  751. DbgPrint( "Rasdd!pfm2ifi: IFIMETRICS overflow: Wrote to 0x%lx, allocated to 0x%lx\n",
  752. ((BYTE *)(pwch + wcslen( pwch ) + 1)),
  753. ((BYTE *)pIFI + cbAlloc) );
  754. HeapFree( hheap, 0, (LPSTR)pIFI ); /* No memory leaks */
  755. return 0;
  756. }
  757. #endif
  758. pIFI->dpFontSim = 0;
  759. {
  760. //int i;
  761. pIFI->lEmbedId = 0;
  762. pIFI->lItalicAngle = 0;
  763. pIFI->lCharBias = 0;
  764. /*for (i=0;i<IFI_RESERVED;i++)
  765. pIFI->alReserved[i] = 0;*/
  766. pIFI->dpCharSets=0;
  767. }
  768. pIFI->jWinCharSet = (BYTE)pFDat->PFMH.dfCharSet;
  769. if( pFDat->PFMH.dfPixWidth )
  770. {
  771. pIFI->jWinPitchAndFamily |= FIXED_PITCH;
  772. pIFI->flInfo |= (FM_INFO_CONSTANT_WIDTH | FM_INFO_OPTICALLY_FIXED_PITCH);
  773. }
  774. else
  775. pIFI->jWinPitchAndFamily |= VARIABLE_PITCH;
  776. pIFI->jWinPitchAndFamily |= (((BYTE) pFDat->PFMH.dfPitchAndFamily) & 0xf0);
  777. pIFI->usWinWeight = (USHORT)pFDat->PFMH.dfWeight;
  778. //
  779. // IFIMETRICS::flInfo
  780. //
  781. pIFI->flInfo |=
  782. FM_INFO_TECH_BITMAP |
  783. FM_INFO_1BPP |
  784. FM_INFO_INTEGER_WIDTH |
  785. FM_INFO_NOT_CONTIGUOUS |
  786. FM_INFO_RIGHT_HANDED;
  787. /* Set the alias bit, if we have added an alias! */
  788. if( cAlias )
  789. pIFI->flInfo |= FM_INFO_FAMILY_EQUIV;
  790. /*
  791. * A scalable font? This happens when there is EXTTEXTMETRIC data,
  792. * and that data has a min size different to the max size.
  793. */
  794. if( pFDat->pETM && (pFDat->pETM->emMinScale != pFDat->pETM->emMaxScale) )
  795. {
  796. pIFI->flInfo |= FM_INFO_ISOTROPIC_SCALING_ONLY;
  797. pIFI->fwdUnitsPerEm = pFDat->pETM->emMasterUnits;
  798. }
  799. else
  800. {
  801. pIFI->fwdUnitsPerEm =
  802. (FWORD) (pFDat->PFMH.dfPixHeight - pFDat->PFMH.dfInternalLeading);
  803. }
  804. pIFI->fsSelection =
  805. ((pFDat->PFMH.dfItalic ) ? FM_SEL_ITALIC : 0) |
  806. ((pFDat->PFMH.dfUnderline ) ? FM_SEL_UNDERSCORE : 0) |
  807. ((pFDat->PFMH.dfStrikeOut ) ? FM_SEL_STRIKEOUT : 0) |
  808. ((pFDat->PFMH.dfWeight >= FW_BOLD ) ? FM_SEL_BOLD : 0) ;
  809. pIFI->fsType = FM_NO_EMBEDDING;
  810. pIFI->fwdLowestPPEm = 1;
  811. /*
  812. * Calculate fwdWinAscender, fwdWinDescender, fwdAveCharWidth, and
  813. * fwdMaxCharInc assuming a bitmap where 1 font unit equals one
  814. * pixel unit
  815. */
  816. pIFI->fwdWinAscender = (FWORD)pFDat->PFMH.dfAscent;
  817. pIFI->fwdWinDescender =
  818. (FWORD)pFDat->PFMH.dfPixHeight - pIFI->fwdWinAscender;
  819. pIFI->fwdMaxCharInc = (FWORD)pFDat->PFMH.dfMaxWidth;
  820. pIFI->fwdAveCharWidth = (FWORD)pFDat->PFMH.dfAvgWidth;
  821. fwdExternalLeading = (FWORD)pFDat->PFMH.dfExternalLeading;
  822. //
  823. // If the font was scalable, then the answers must be scaled up
  824. // !!! HELP HELP HELP - if a font is scalable in this sense, then
  825. // does it support arbitrary transforms? [kirko]
  826. //
  827. if( pIFI->flInfo & (FM_INFO_ISOTROPIC_SCALING_ONLY|FM_INFO_ANISOTROPIC_SCALING_ONLY|FM_INFO_ARB_XFORMS))
  828. {
  829. /*
  830. * This is a scalable font: because there is Extended Text Metric
  831. * information available, and this says that the min and max
  832. * scale sizes are different: thus it is scalable! This test is
  833. * lifted directly from the Win 3.1 driver.
  834. */
  835. int iMU, iRel; /* Adjustment factors */
  836. iMU = pFDat->pETM->emMasterUnits;
  837. iRel = pFDat->PFMH.dfPixHeight;
  838. pIFI->fwdWinAscender = (pIFI->fwdWinAscender * iMU) / iRel;
  839. pIFI->fwdWinDescender = (pIFI->fwdWinDescender * iMU) / iRel;
  840. pIFI->fwdMaxCharInc = (pIFI->fwdMaxCharInc * iMU) / iRel;
  841. pIFI->fwdAveCharWidth = (pIFI->fwdAveCharWidth * iMU) / iRel;
  842. fwdExternalLeading = (fwdExternalLeading * iMU) / iRel;
  843. }
  844. pIFI->fwdMacAscender = pIFI->fwdWinAscender;
  845. pIFI->fwdMacDescender = - pIFI->fwdWinDescender;
  846. pIFI->fwdMacLineGap = fwdExternalLeading;
  847. pIFI->fwdTypoAscender = pIFI->fwdMacAscender;
  848. pIFI->fwdTypoDescender = pIFI->fwdMacDescender;
  849. pIFI->fwdTypoLineGap = pIFI->fwdMacLineGap;
  850. if( pFDat->pETM )
  851. {
  852. /*
  853. * Zero is a legitimate default for these. If 0, gdisrv
  854. * chooses some default values.
  855. */
  856. pIFI->fwdCapHeight = pFDat->pETM->emCapHeight;
  857. pIFI->fwdXHeight = pFDat->pETM->emXHeight;
  858. pIFI->fwdSubscriptYSize = pFDat->pETM->emSubScriptSize;
  859. pIFI->fwdSubscriptYOffset = pFDat->pETM->emSubScript;
  860. pIFI->fwdSuperscriptYSize = pFDat->pETM->emSuperScriptSize;
  861. pIFI->fwdSuperscriptYOffset = pFDat->pETM->emSuperScript;
  862. pIFI->fwdUnderscoreSize = pFDat->pETM->emUnderlineWidth;
  863. pIFI->fwdUnderscorePosition = pFDat->pETM->emUnderlineOffset;
  864. pIFI->fwdStrikeoutSize = pFDat->pETM->emStrikeOutWidth;
  865. pIFI->fwdStrikeoutPosition = pFDat->pETM->emStrikeOutOffset;
  866. }
  867. else
  868. {
  869. /* No additional information, so do some calculations */
  870. pIFI->fwdSubscriptYSize = pIFI->fwdWinAscender/4;
  871. pIFI->fwdSubscriptYOffset = -(pIFI->fwdWinAscender/4);
  872. pIFI->fwdSuperscriptYSize = pIFI->fwdWinAscender/4;
  873. pIFI->fwdSuperscriptYOffset = (3 * pIFI->fwdWinAscender)/4;
  874. pIFI->fwdUnderscoreSize = pIFI->fwdWinAscender / 12;
  875. if( pIFI->fwdUnderscoreSize < 1 )
  876. pIFI->fwdUnderscoreSize = 1;
  877. pIFI->fwdUnderscorePosition = -pFDat->DI.sUnderLinePos;
  878. pIFI->fwdStrikeoutSize = pIFI->fwdUnderscoreSize;
  879. pIFI->fwdStrikeoutPosition = (FWORD)pFDat->DI.sStrikeThruPos;
  880. if( pIFI->fwdStrikeoutPosition < 1 )
  881. pIFI->fwdStrikeoutPosition = (pIFI->fwdWinAscender + 2) / 3;
  882. }
  883. pIFI->fwdSubscriptXSize = pIFI->fwdAveCharWidth/4;
  884. pIFI->fwdSubscriptXOffset = (3 * pIFI->fwdAveCharWidth)/4;
  885. pIFI->fwdSuperscriptXSize = pIFI->fwdAveCharWidth/4;
  886. pIFI->fwdSuperscriptXOffset = (3 * pIFI->fwdAveCharWidth)/4;
  887. pIFI->chFirstChar = pFDat->PFMH.dfFirstChar;
  888. pIFI->chLastChar = pFDat->PFMH.dfLastChar;
  889. /*
  890. * We now do the conversion of these to Unicode. We presume the
  891. * input is in the ANSI code page, and call the NLS converion
  892. * functions to generate proper Unicode values.
  893. */
  894. iCount = pFDat->PFMH.dfLastChar - pFDat->PFMH.dfFirstChar + 1;
  895. for( iI = 0; iI < iCount; ++iI )
  896. abyte[ iI ] = iI + pFDat->PFMH.dfFirstChar;
  897. MultiByteToWideChar( CP_ACP, 0, (LPCSTR) abyte, iCount, awcAttrib, iCount );
  898. /*
  899. * Now fill in the IFIMETRICS WCHAR fields.
  900. */
  901. pIFI->wcFirstChar = 0xffff;
  902. pIFI->wcLastChar = 0;
  903. /* Look for the first and last */
  904. for( iI = 0; iI < iCount; ++iI )
  905. {
  906. if( pIFI->wcFirstChar > awcAttrib[ iI ] )
  907. pIFI->wcFirstChar = awcAttrib[ iI ];
  908. if( pIFI->wcLastChar < awcAttrib[ iI ] )
  909. pIFI->wcLastChar = awcAttrib[ iI ];
  910. }
  911. pIFI->wcDefaultChar = awcAttrib[ pFDat->PFMH.dfDefaultChar ];
  912. pIFI->wcBreakChar = awcAttrib[ pFDat->PFMH.dfBreakChar ];
  913. pIFI->chDefaultChar = pFDat->PFMH.dfDefaultChar + pFDat->PFMH.dfFirstChar;
  914. pIFI->chBreakChar = pFDat->PFMH.dfBreakChar + pFDat->PFMH.dfFirstChar;
  915. if( pFDat->PFMH.dfItalic )
  916. {
  917. //
  918. // tan (17.5 degrees) = .3153
  919. //
  920. pIFI->ptlCaret.x = 3153;
  921. pIFI->ptlCaret.y = 10000;
  922. }
  923. else
  924. {
  925. pIFI->ptlCaret.x = 0;
  926. pIFI->ptlCaret.y = 1;
  927. }
  928. pIFI->ptlBaseline.x = 1;
  929. pIFI->ptlBaseline.y = 0;
  930. pIFI->ptlAspect.x = pFDat->PFMH.dfHorizRes;
  931. pIFI->ptlAspect.y = pFDat->PFMH.dfVertRes;
  932. pIFI->rclFontBox.left = 0;
  933. pIFI->rclFontBox.top = (LONG) pIFI->fwdWinAscender;
  934. pIFI->rclFontBox.right = (LONG) pIFI->fwdMaxCharInc;
  935. pIFI->rclFontBox.bottom = - (LONG) pIFI->fwdWinDescender;
  936. pIFI->achVendId[0] = 'U';
  937. pIFI->achVendId[1] = 'n';
  938. pIFI->achVendId[2] = 'k';
  939. pIFI->achVendId[3] = 'n';
  940. pIFI->cKerningPairs = 0;
  941. pIFI->ulPanoseCulture = FM_PANOSE_CULTURE_LATIN;
  942. pIFI->panose.bFamilyType = PAN_ANY;
  943. pIFI->panose.bSerifStyle = PAN_ANY;
  944. if(pFDat->PFMH.dfWeight >= FW_BOLD)
  945. {
  946. pIFI->panose.bWeight = PAN_WEIGHT_BOLD;
  947. }
  948. else if (pFDat->PFMH.dfWeight > FW_EXTRALIGHT)
  949. {
  950. pIFI->panose.bWeight = PAN_WEIGHT_MEDIUM;
  951. }
  952. else
  953. {
  954. pIFI->panose.bWeight = PAN_WEIGHT_LIGHT;
  955. }
  956. pIFI->panose.bProportion = PAN_ANY;
  957. pIFI->panose.bContrast = PAN_ANY;
  958. pIFI->panose.bStrokeVariation = PAN_ANY;
  959. pIFI->panose.bArmStyle = PAN_ANY;
  960. pIFI->panose.bLetterform = PAN_ANY;
  961. pIFI->panose.bMidline = PAN_ANY;
  962. pIFI->panose.bXHeight = PAN_ANY;
  963. return pIFI;
  964. }