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.

1123 lines
33 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. makentf.c
  5. Abstract:
  6. Utility to convert AFM file(s) to NTF file.
  7. Environment:
  8. Windows NT PostScript driver.
  9. Revision History:
  10. 02/16/98 -ksuzuki-
  11. Added OCF font support.
  12. 09/08/97 -ksuzuki-
  13. Added code to look for PSFAMILY.DAT file from the directory where
  14. makentf is invoked.
  15. 09/16/96 -PPeng-
  16. Add the fucntion to write PS Encoding vectors out - for debugging and
  17. create PS Encoding Arrays as PScript resource files.
  18. 09/16/96 -slam-
  19. Created.
  20. mm/dd/yy -author-
  21. description
  22. --*/
  23. #include <windows.h>
  24. #include "lib.h"
  25. #include "ppd.h"
  26. #include "pslib.h"
  27. #include "afm2ntm.h"
  28. #include "cjkfonts.h"
  29. #include "writentf.h"
  30. //
  31. // Globals
  32. //
  33. HINSTANCE ghInstance;
  34. PUPSCODEPT UnicodetoPs;
  35. PTBL pFamilyTbl;
  36. PSTR pAFMCharacterSetString;
  37. PSTR Adobe_Japan1_0 = "Adobe-Japan1-0\n";
  38. DWORD dwLastErr;
  39. PSTR pAFMFileName = NULL;
  40. BOOL bVerbose = FALSE;
  41. BOOL bOptimize = FALSE;
  42. // Number of auxiliary character set. Its cheif
  43. // purpose is to support 83pv.
  44. #define NUM_AUX_CS 1
  45. // This macro is used to see whether the argument
  46. // matches the differential between CS_SHIFTJIS
  47. // and CS_WEST_MAX.
  48. #define IS_CS_SHIFTJIS(delta) \
  49. ((delta) == (CS_SHIFTJIS - CS_WEST_MAX))
  50. //
  51. // Prototype
  52. //
  53. BOOL
  54. WritePSEncodings(
  55. IN PWSTR pwszFileName,
  56. IN WINCPTOPS *CPtoPSList,
  57. IN DWORD dwPages
  58. );
  59. BOOL NeedBuildMoreNTM(
  60. PBYTE pAFM
  61. );
  62. void __cdecl
  63. main(
  64. int argc,
  65. char **argv
  66. )
  67. /*++
  68. Routine Description:
  69. Makentf takes four steps to create a .NTF file.
  70. Step 1: Initialization.
  71. Step 2: Convert AFM(s) to NTM(s).
  72. Step 3: Write GLYPHSETDATA(s) and NTM(s) to a .NTF file.
  73. Step 4: Clean up.
  74. Arguments:
  75. argc - The path of and arguments given to this program.
  76. argv - The number of elements pointed to by argc.
  77. Return Value:
  78. None.
  79. --*/
  80. {
  81. WCHAR wstrNTFFile[MAX_PATH];
  82. WCHAR wstrAFMFile[MAX_PATH];
  83. WCHAR wstrDATFile[MAX_PATH];
  84. WCHAR DatFilePath[MAX_PATH];
  85. PNTM *aPNTM;
  86. PNTM pNTM;
  87. PGLYPHSETDATA *aGlyphSets;
  88. PWINCODEPAGE *aWinCodePages;
  89. PWINCODEPAGE pAllWinCodePages[CS_MAX];
  90. PUPSCODEPT pFontChars;
  91. CHSETSUPPORT flCsupFont, flCsupGlyphSet, flCsupMatch, flCsupAll;
  92. ULONG cNumNTM, cSizeNTM, ulLength, nUnicodeChars;
  93. PULONG *aUniPsTbl;
  94. LONG lMatch, lMatchAll;
  95. PBYTE pAFM;
  96. FLONG flCurCset, flLastCset;
  97. ULONG cNumGlyphSets, cSizeGlyphSets;
  98. DWORD ulFileSize;
  99. PBYTE pFamDatFile;
  100. PBYTE pCMaps[CMAPS_PER_COL];
  101. HANDLE hmodule, hModCMaps[CMAPS_PER_COL];
  102. USHORT cNTMCurFont;
  103. INT nArgcOffset;
  104. LONG c;
  105. ULONG i, j;
  106. BOOL bIs90mspFont;
  107. BOOL bIsKSCmsHWFont;
  108. //////////////////////////////////////////////////////////////////////////
  109. //
  110. // Step 1: Initialization.
  111. //
  112. //////////////////////////////////////////////////////////////////////////
  113. //
  114. // Check if there are enough parameters.
  115. //
  116. if (argc == 1)
  117. {
  118. printf("MakeNTF usage:\n");
  119. printf("1. MakeNTF [-v] [-o] <NTF> <AFMs>\n");
  120. printf(" Create an NTF file from AFM files.\n");
  121. printf(" -v: verbose (print various info)\n");
  122. printf(" -o: optimize (write glyphset only referenced)\n");
  123. printf("\n");
  124. printf("2. MakeNTF <PSEncodingNameList>\n");
  125. printf(" Generate PS encoding name list.\n");
  126. return;
  127. }
  128. wstrNTFFile[0] = 0;
  129. if (argc == 2)
  130. {
  131. ulLength = strlen(argv[1]) + 1;
  132. MULTIBYTETOUNICODE(wstrNTFFile,
  133. ulLength*sizeof(WCHAR),
  134. NULL,
  135. argv[1],
  136. ulLength);
  137. WritePSEncodings(wstrNTFFile, &aPStoCP[0], CS_MAX);
  138. return;
  139. }
  140. else
  141. {
  142. nArgcOffset = 0;
  143. for (i = 1; i <= 2; i++)
  144. {
  145. if (!strcmp(argv[i], "-v"))
  146. {
  147. bVerbose = TRUE;
  148. nArgcOffset++;
  149. }
  150. if (!strcmp(argv[i], "-o"))
  151. {
  152. bOptimize = TRUE;
  153. nArgcOffset++;
  154. }
  155. }
  156. }
  157. if (bVerbose) printf("%%%%[Begin MakeNTF]%%%%\n\n");
  158. //
  159. // Initiliaze variables that relate to memory allocation.
  160. //
  161. aPNTM = NULL;
  162. aGlyphSets = NULL;
  163. pFamilyTbl = NULL;
  164. UnicodetoPs = NULL;
  165. aUniPsTbl = NULL;
  166. aWinCodePages = NULL;
  167. cNumNTM = cSizeNTM = 0;
  168. cNumGlyphSets = cSizeGlyphSets = 0;
  169. //
  170. // Initialize Glyphset counter, list of all possible Windows charsets.
  171. //
  172. for (i =0; i < CS_MAX; i++)
  173. {
  174. pAllWinCodePages[i] = &aStdCPList[i];
  175. }
  176. //
  177. // Create a copy of the Unicode->PS char mapping table and sort it
  178. // in Unicode point order.
  179. //
  180. if ((UnicodetoPs =
  181. (PUPSCODEPT) MemAllocZ((size_t) sizeof(UPSCODEPT) * NUM_PS_CHARS))
  182. == NULL)
  183. {
  184. dwLastErr = GetLastError();
  185. ERR(("makentf - main: malloc for UnicodetoPs (%ld)\n", dwLastErr));
  186. return;
  187. }
  188. memcpy(UnicodetoPs, PstoUnicode, (size_t) sizeof(UPSCODEPT) * NUM_PS_CHARS);
  189. qsort(UnicodetoPs,
  190. (size_t) NUM_PS_CHARS,
  191. (size_t) sizeof(UPSCODEPT),
  192. CmpUniCodePts);
  193. //
  194. // Build complete path name for PS family DAT file.
  195. //
  196. GetCurrentDirectory(MAX_PATH, DatFilePath);
  197. StringCchCatW(DatFilePath, CCHOF(DatFilePath), DatFileName);
  198. //
  199. // Open PS font family .DAT file and build the font family table.
  200. //
  201. if (!(hmodule = MapFileIntoMemory(DatFilePath, &pFamDatFile, &ulFileSize)))
  202. {
  203. //
  204. // One more try: look for it from the directory where makentf is
  205. // invoked (or from the root directory).
  206. //
  207. DECLSPEC_IMPORT LPWSTR* APIENTRY CommandLineToArgvW(LPCWSTR, int*);
  208. LPWSTR p, pLast, *pCmdLine;
  209. int nArgc;
  210. pCmdLine = CommandLineToArgvW(GetCommandLineW(), &nArgc);
  211. if (pCmdLine == NULL)
  212. {
  213. dwLastErr = GetLastError();
  214. ERR(("makentf - main: CommandLineToArgvW (%ld)\n", dwLastErr));
  215. UnmapFileFromMemory(hmodule);
  216. goto CLEAN_UP;
  217. }
  218. StringCchCopyW(DatFilePath, CCHOF(DatFilePath), pCmdLine[0]);
  219. GlobalFree(pCmdLine);
  220. p = pLast = DatFilePath;
  221. while ((p = wcsstr(p, L"\\")) != NULL)
  222. {
  223. pLast = p;
  224. p += 2;
  225. }
  226. StringCchCopyW(pLast, CCHOF(DatFilePath) - (pLast - DatFilePath), DatFileName);
  227. hmodule = MapFileIntoMemory(DatFilePath, &pFamDatFile, &ulFileSize);
  228. if (!hmodule)
  229. {
  230. dwLastErr = GetLastError();
  231. ERR(("makentf - main: can't open PSFAMILY.DAT file (%ld)\n", dwLastErr));
  232. UnmapFileFromMemory(hmodule);
  233. goto CLEAN_UP;
  234. }
  235. }
  236. BuildPSFamilyTable(pFamDatFile, &pFamilyTbl, ulFileSize);
  237. UnmapFileFromMemory(hmodule);
  238. //
  239. // Allocate memory to store NTM pointers.
  240. //
  241. // We quadruple the number of the arguments of this program to get the
  242. // number of NTM pointer. This is because
  243. //
  244. // 1) we need four NTM pointers maximum (two for H and V plus two for J
  245. // 90ms and 83pv) for a CJK AFM, but,
  246. // 2) we don't know at this time that how many of CJK AFMs we are going
  247. // to process.
  248. //
  249. // Since we're only allocating pointers here it's usually OK to quadruple
  250. // the number of the arguments and use it as the number of NTM pointers
  251. // we need. (Don't forget to subtract two - one for the name of this
  252. // program and the other for the target NTM file name - from the number
  253. // of the arguments prior to quadruple.)
  254. //
  255. // Add 90msp-RKSJ support. we need 2 more NTFs - H and V for 90msp.
  256. // So I change the estimation number from 4 to 6. Jack 3/15/2000
  257. // aPNTM = MemAllocZ(((argc - 2 - nArgcOffset) * 4) * sizeof(PNTM));
  258. aPNTM = MemAllocZ(((argc - 2 - nArgcOffset) * 6) * sizeof(PNTM));
  259. if (aPNTM == NULL)
  260. {
  261. dwLastErr = GetLastError();
  262. ERR(("makentf - main: malloc for aPNTM (%ld)\n", dwLastErr));
  263. goto CLEAN_UP;
  264. }
  265. //
  266. // Allocate memory to store pointers to Glyphset related data. We don't
  267. // know how many Glyphsets we will need - but we know it will be at most
  268. // equal to the number of character sets we support, although this will
  269. // probably never occur. Since we're only allocating ptrs here we'll go
  270. // ahead and alloc the max. Don't forget an extra entry for the Unicode
  271. // GLYPHSET data.
  272. //
  273. i = CS_WEST_MAX + (CS_MAX - CS_WEST_MAX + NUM_AUX_CS) * 2;
  274. if ((aGlyphSets = MemAllocZ(i * sizeof(PGLYPHSETDATA))) == NULL)
  275. {
  276. dwLastErr = GetLastError();
  277. ERR(("makentf - main: malloc for aGlyphSets (%ld)\n", dwLastErr));
  278. goto CLEAN_UP;
  279. }
  280. if ((aUniPsTbl = MemAllocZ(i * sizeof(PULONG))) == NULL)
  281. {
  282. dwLastErr = GetLastError();
  283. ERR(("makentf - main: malloc for aUniPsTbl (%ld)\n", dwLastErr));
  284. goto CLEAN_UP;
  285. }
  286. if ((aWinCodePages = MemAllocZ(i * sizeof(PWINCODEPAGE))) == NULL)
  287. {
  288. dwLastErr = GetLastError();
  289. ERR(("makentf - main: malloc for aWinCodePages (%ld)\n", dwLastErr));
  290. goto CLEAN_UP;
  291. }
  292. //
  293. // Precreate Western GLYPHSETs.
  294. // Note that this for loop assumes that the enum numbers from CS_228 to
  295. // CS_WEST_MAX are in ascending order incrementally.
  296. //
  297. if (bVerbose && !bOptimize) printf("%%%%[Begin Precreate Western Glyphsets]%%%%\n\n");
  298. for (i = CS_228; i < CS_WEST_MAX; i++, cNumGlyphSets++)
  299. {
  300. aWinCodePages[cNumGlyphSets] = &aStdCPList[i];
  301. CreateGlyphSets(&aGlyphSets[cNumGlyphSets],
  302. aWinCodePages[cNumGlyphSets],
  303. &aUniPsTbl[cNumGlyphSets]);
  304. cSizeGlyphSets += aGlyphSets[cNumGlyphSets]->dwSize;
  305. }
  306. if (bVerbose && !bOptimize) printf("%%%%[End Precreate Western Glyphsets]%%%%\n\n");
  307. //////////////////////////////////////////////////////////////////////////
  308. //
  309. // Step 2: Convert AFM(s) to NTM(s).
  310. //
  311. //////////////////////////////////////////////////////////////////////////
  312. if (bVerbose) printf("%%%%[Begin Covert AFM to NTM]%%%%\n\n");
  313. for (i = 2 + nArgcOffset; i < (ULONG)argc; i++)
  314. {
  315. //
  316. // Get AFM filename.
  317. //
  318. ulLength = strlen(argv[i]) + 1;
  319. MULTIBYTETOUNICODE(wstrAFMFile,
  320. ulLength*sizeof(WCHAR),
  321. NULL,
  322. argv[i],
  323. ulLength);
  324. //
  325. // Map AFM file into memory.
  326. //
  327. if (!(hmodule = MapFileIntoMemory(wstrAFMFile, &pAFM, NULL)))
  328. {
  329. dwLastErr = GetLastError();
  330. ERR(("makentf - main: MapFileIntoMemory (%ld)\n", dwLastErr));
  331. goto CLEAN_UP;
  332. }
  333. pAFMFileName = argv[i];
  334. bIs90mspFont = FALSE;
  335. bIsKSCmsHWFont = FALSE;
  336. //
  337. // Initialization of pAFMCharacterSet must be done here
  338. // *before* CREATE_OCF_DATA_FROM_CID_DATA tag. The cheif
  339. // purpose of the initialization here is to support
  340. // OCF/83pv font.
  341. //
  342. pAFMCharacterSetString = FindAFMToken(pAFM, PS_CHARSET_TOK);
  343. CREATE_OCF_DATA_FROM_CID_DATA:
  344. //
  345. // Determine which charsets this font supports. To find that,
  346. // we use the following variables.
  347. //
  348. // flCsupFont: Combination of charset of the target font
  349. // flCsupGlyphSet: Charset of the target font's glyphset
  350. // lMatch: Index corresponding to CHSETSUPPORT, or -1
  351. // flCsupMatch: Combination of charset of a closest font, or 0
  352. //
  353. flCsupFont = GetAFMCharSetSupport(pAFM, &flCsupGlyphSet);
  354. CREATE_90MSP_RKSJ_NTM:
  355. CREATE_KSCMS_HW_NTM:
  356. lMatch = -1;
  357. flCsupMatch = 0;
  358. if (flCsupGlyphSet == CS_NOCHARSET)
  359. {
  360. //
  361. // Determine if the current font matches any of the codepages
  362. // we have created so far.
  363. //
  364. lMatch = FindClosestCodePage(aWinCodePages,
  365. cNumGlyphSets,
  366. flCsupFont,
  367. &flCsupMatch);
  368. }
  369. else
  370. {
  371. if (flCsupGlyphSet == CS_228)
  372. lMatch = 0;
  373. else if (flCsupGlyphSet == CS_314)
  374. lMatch = 1;
  375. flCsupMatch = flCsupFont;
  376. }
  377. if ((flCsupGlyphSet == CS_NOCHARSET)
  378. &&
  379. ((lMatch == -1) || ((flCsupMatch & flCsupFont) != flCsupFont)))
  380. {
  381. //
  382. // Either:
  383. // We haven't created a charset which could be used to represent
  384. // this font so far.
  385. // -or-
  386. // We know this font supports at least 1 of the charsets we have
  387. // created, but there might be a better match in the list of all
  388. // possible charsets.
  389. //
  390. lMatchAll = FindClosestCodePage(pAllWinCodePages,
  391. CS_MAX,
  392. flCsupFont,
  393. &flCsupAll);
  394. if ((flCsupAll == flCsupFont)
  395. || (flCsupAll & flCsupFont) > (flCsupMatch & flCsupFont))
  396. {
  397. //
  398. // Found a better match in a codepage which has not yet
  399. // been created.
  400. //
  401. lMatch = lMatchAll;
  402. //
  403. // Create a GLYPHSETDATA struct for this codepage and add
  404. // it to the list of those we've created so far.
  405. //
  406. aWinCodePages[cNumGlyphSets] = &aStdCPList[lMatch];
  407. //
  408. // Determine if this is a CJK font.
  409. //
  410. if (lMatch < CS_WEST_MAX)
  411. {
  412. //
  413. // Western font.
  414. //
  415. CreateGlyphSets(&aGlyphSets[cNumGlyphSets],
  416. aWinCodePages[cNumGlyphSets],
  417. &aUniPsTbl[cNumGlyphSets]);
  418. cSizeGlyphSets += aGlyphSets[cNumGlyphSets]->dwSize;
  419. //
  420. // Glyphset for this font is the one we just created.
  421. //
  422. lMatch = cNumGlyphSets;
  423. cNumGlyphSets += 1;
  424. }
  425. else
  426. {
  427. //
  428. // CJK font.
  429. //
  430. // Map the CMap files on memory first.
  431. //
  432. j = (ULONG)lMatch - CS_WEST_MAX;
  433. for (c = 0; c < CMAPS_PER_COL; c++)
  434. {
  435. hModCMaps[c] = MapFileIntoMemory(CjkFnameTbl[j][c],
  436. &pCMaps[c], NULL);
  437. if (hModCMaps[c] == NULL)
  438. {
  439. while (--c >= 0)
  440. {
  441. UnmapFileFromMemory(hModCMaps[c]);
  442. }
  443. dwLastErr = GetLastError();
  444. ERR(("makentf - main: MapFileIntoMemory (%ld)\n", dwLastErr));
  445. goto CLEAN_UP;
  446. }
  447. }
  448. //
  449. // Since we're creating 2 GLYPHSETs (H and V variants)
  450. // Create 2 codepage entries which point to the same
  451. // Win codepage.
  452. //
  453. aWinCodePages[cNumGlyphSets + 1] = &aStdCPList[lMatch];
  454. //
  455. // Use the CMap files to create the new GLYPHSETs.
  456. //
  457. CreateCJKGlyphSets(&pCMaps[0],
  458. &pCMaps[2],
  459. &aGlyphSets[cNumGlyphSets],
  460. aWinCodePages[cNumGlyphSets],
  461. &aUniPsTbl[cNumGlyphSets]);
  462. //
  463. // Unmap the CMap files.
  464. //
  465. for (c = 0; c < CMAPS_PER_COL; c++)
  466. {
  467. UnmapFileFromMemory(hModCMaps[c]);
  468. }
  469. //
  470. // We've created both an H and V GLYPHSET.
  471. //
  472. cSizeGlyphSets += aGlyphSets[cNumGlyphSets]->dwSize;
  473. cSizeGlyphSets += aGlyphSets[cNumGlyphSets + 1]->dwSize;
  474. //
  475. // Glyphsets for this font are the ones we just created.
  476. //
  477. lMatch = cNumGlyphSets;
  478. cNumGlyphSets += 2;
  479. }
  480. }
  481. }
  482. //
  483. // Determine number of NTMs to be created for this font.
  484. //
  485. cNTMCurFont =
  486. (aWinCodePages[lMatch]->pCsetList[0] < CS_WEST_MAX) ? 1 : 2;
  487. do
  488. {
  489. //
  490. // Generate NTM from AFM.
  491. //
  492. aPNTM[cNumNTM] = AFMToNTM(pAFM,
  493. aGlyphSets[lMatch],
  494. aUniPsTbl[lMatch],
  495. ((flCsupGlyphSet != CS_NOCHARSET) ? &flCsupFont : NULL),
  496. ((flCsupFont & CS_CJK) ? TRUE : FALSE),
  497. bIs90mspFont | bIsKSCmsHWFont);
  498. if (aPNTM[cNumNTM] != NULL)
  499. {
  500. //
  501. // Put the NTMs into a data array for WriteNTF.
  502. //
  503. cSizeNTM += NTM_GET_SIZE(aPNTM[cNumNTM]);
  504. cNumNTM++;
  505. }
  506. else
  507. {
  508. ERR(("makentf - main: AFMToNTM failed to create NTM:%s\n", argv[i]));
  509. }
  510. cNTMCurFont--;
  511. lMatch++;
  512. } while (cNTMCurFont);
  513. //
  514. // 90msp font support. jjia 3/16/2000
  515. //
  516. if (flCsupFont == CSUP(CS_SHIFTJIS))
  517. {
  518. if (NeedBuildMoreNTM(pAFM))
  519. {
  520. flCsupFont = CSUP(CS_SHIFTJISP);
  521. bIs90mspFont = TRUE;
  522. goto CREATE_90MSP_RKSJ_NTM; // here we go again!
  523. }
  524. }
  525. bIs90mspFont = FALSE;
  526. if (flCsupFont == CSUP(CS_HANGEUL))
  527. {
  528. if (NeedBuildMoreNTM(pAFM))
  529. {
  530. flCsupFont = CSUP(CS_HANGEULHW);
  531. bIsKSCmsHWFont = TRUE;
  532. goto CREATE_KSCMS_HW_NTM; // here we go again!
  533. }
  534. }
  535. bIsKSCmsHWFont = FALSE;
  536. //
  537. // OCF/83pv font support. Create OCF glyphset and NTM data from
  538. // CID AFM file.
  539. //
  540. if ((flCsupFont == CSUP(CS_SHIFTJIS)) ||
  541. (flCsupFont == CSUP(CS_SHIFTJISP)))
  542. {
  543. pAFMCharacterSetString = Adobe_Japan1_0;
  544. goto CREATE_OCF_DATA_FROM_CID_DATA; // here we go again!
  545. }
  546. UnmapFileFromMemory(hmodule);
  547. }
  548. if (bVerbose) printf("%%%%[End Convert AFM to NTM]%%%%\n\n");
  549. //
  550. // Create Unicode GLYPHSET. This glyphset is created here since we don't
  551. // want any NTMs to reference this glyphset.
  552. //
  553. if (bVerbose && !bOptimize) printf("%%%%[Begin Create Unicode glyphset]%%%%\n\n");
  554. CreateGlyphSets(&aGlyphSets[cNumGlyphSets],
  555. &UnicodePage,
  556. &aUniPsTbl[cNumGlyphSets]);
  557. cSizeGlyphSets += aGlyphSets[cNumGlyphSets]->dwSize;
  558. cNumGlyphSets++;
  559. if (bVerbose && !bOptimize) printf("%%%%[End Create Unicode glyphset]%%%%\n\n");
  560. //////////////////////////////////////////////////////////////////////////
  561. //
  562. // Step 3: Write GLYPHSETDATA(s) and NTM(s) to a .NTF file.
  563. //
  564. //////////////////////////////////////////////////////////////////////////
  565. if (bVerbose) printf("%%%%[Begin Write NTF]%%%%\n\n");
  566. ulLength = strlen(argv[1 + nArgcOffset]) + 1;
  567. MULTIBYTETOUNICODE(
  568. wstrNTFFile,
  569. ulLength*sizeof(WCHAR),
  570. NULL,
  571. argv[1 + nArgcOffset],
  572. ulLength);
  573. if (!WriteNTF(wstrNTFFile,
  574. cNumGlyphSets,
  575. cSizeGlyphSets,
  576. aGlyphSets,
  577. cNumNTM,
  578. cSizeNTM,
  579. aPNTM
  580. ))
  581. {
  582. ERR(("makentf: main - Can't write .NTF file\n"));
  583. }
  584. if (bVerbose) printf("%%%%[End Write NTF]%%%%\n\n");
  585. //////////////////////////////////////////////////////////////////////////
  586. //
  587. // Step 4: Clean up.
  588. //
  589. //////////////////////////////////////////////////////////////////////////
  590. CLEAN_UP:
  591. for (i = 0; i < cNumNTM; i++)
  592. {
  593. MemFree(aPNTM[i]);
  594. }
  595. for (i = 0; i < cNumGlyphSets; i++)
  596. {
  597. MemFree(aGlyphSets[i]);
  598. if (aUniPsTbl[i] != NULL)
  599. {
  600. //
  601. // Could have a null ptr if this is a Pi Font.
  602. //
  603. MemFree(aUniPsTbl[i]);
  604. }
  605. }
  606. MemFree(aPNTM ? aPNTM : NULL);
  607. MemFree(aGlyphSets ? aGlyphSets : NULL);
  608. MemFree(pFamilyTbl ? pFamilyTbl : NULL);
  609. MemFree(UnicodetoPs ? UnicodetoPs : NULL);
  610. MemFree(aUniPsTbl ? aUniPsTbl : NULL);
  611. MemFree(aWinCodePages ? aWinCodePages : NULL);
  612. if (bVerbose) printf("%%%%[End MakeNTF]%%%%\n\n");
  613. }
  614. //
  615. // Formating functions - copied from PScript\Output.c
  616. //
  617. INT
  618. OPVsprintf(
  619. OUT LPSTR buf,
  620. IN LPCSTR fmtstr,
  621. IN va_list arglist
  622. )
  623. /*++
  624. Routine Description:
  625. Takes a pointer to an argument list, then formats and writes
  626. the given data to the memory pointed to by buffer.
  627. Arguments:
  628. buf Storage location for output
  629. fmtstr Format specification
  630. arglist Pointer to list of arguments
  631. Return Value:
  632. Return the number of characters written, not including
  633. the terminating null character, or a negative value if
  634. an output error occurs.
  635. [Note:]
  636. This is NOT a full implementation of "vsprintf" as found
  637. in the C runtime library. Specifically, the only form of
  638. format specification allowed is %type, where "type" can
  639. be one of the following characters:
  640. d INT signed decimal integer
  641. l LONG signed decimal integer
  642. u ULONG unsigned decimal integer
  643. s CHAR* character string
  644. c CHAR character
  645. x,X DWORD hex number (emits at least two digits, uppercase)
  646. b BOOL boolean (true or false)
  647. f LONG 24.8 fixed-pointed number
  648. o CHAR octal number
  649. --*/
  650. {
  651. LPSTR ptr = buf;
  652. ASSERT(buf && fmtstr);
  653. while (*fmtstr != NUL) {
  654. if (*fmtstr != '%') {
  655. // Normal character
  656. *ptr++ = *fmtstr++;
  657. } else {
  658. // Format specification
  659. switch (*++fmtstr) {
  660. case 'd': // signed decimal integer
  661. _ltoa((LONG) va_arg(arglist, INT), ptr, 10);
  662. ptr += strlen(ptr);
  663. break;
  664. case 'l': // signed decimal integer
  665. _ltoa(va_arg(arglist, LONG), ptr, 10);
  666. ptr += strlen(ptr);
  667. break;
  668. case 'u': // unsigned decimal integer
  669. _ultoa(va_arg(arglist, ULONG), ptr, 10);
  670. ptr += strlen(ptr);
  671. break;
  672. case 's': // character string
  673. { LPSTR s = va_arg(arglist, LPSTR);
  674. while (*s)
  675. *ptr++ = *s++;
  676. }
  677. break;
  678. case 'c': // character
  679. *ptr++ = va_arg(arglist, CHAR);
  680. break;
  681. case 'x':
  682. case 'X': // hexdecimal number
  683. { ULONG ul = va_arg(arglist, ULONG);
  684. INT ndigits = 8;
  685. while (ndigits > 2 && ((ul >> (ndigits-1)*4) & 0xf) == 0)
  686. ndigits--;
  687. while (ndigits-- > 0)
  688. *ptr++ = HexDigit(ul >> ndigits*4);
  689. }
  690. break;
  691. case 'o':
  692. { CHAR ch = va_arg(arglist, CHAR);
  693. *ptr++ = (char)((ch & 0xC0) >> 6) + (char)'0';
  694. *ptr++ = (char)((ch & 0x38) >> 3) + (char)'0';
  695. *ptr++ = (char)(ch & 0x07) + (char)'0';
  696. }
  697. break;
  698. case 'b': // boolean
  699. StringCchCopyA(ptr, (size_t)((ptr - buf)/sizeof(CHAR)), (va_arg(arglist, BOOL)) ? "true" : "false");
  700. ptr += strlen(ptr);
  701. break;
  702. case 'f': // 24.8 fixed-pointed number
  703. {
  704. LONG l = va_arg(arglist, LONG);
  705. ULONG ul, scale;
  706. // sign character
  707. if (l < 0) {
  708. *ptr++ = '-';
  709. ul = -l;
  710. } else
  711. ul = l;
  712. // integer portion
  713. _ultoa(ul >> 8, ptr, 10);
  714. ptr += strlen(ptr);
  715. // fraction
  716. ul &= 0xff;
  717. if (ul != 0) {
  718. // We output a maximum of 3 digits after the
  719. // decimal point, but we'll compute to the 5th
  720. // decimal point and round it to 3rd.
  721. ul = ((ul*100000 >> 8) + 50) / 100;
  722. scale = 100;
  723. *ptr++ = '.';
  724. do {
  725. *ptr++ = (CHAR) (ul/scale + '0');
  726. ul %= scale;
  727. scale /= 10;
  728. } while (scale != 0 && ul != 0) ;
  729. }
  730. }
  731. break;
  732. default:
  733. if (*fmtstr != NUL)
  734. *ptr++ = *fmtstr;
  735. else {
  736. ERR(("Invalid format specification\n"));
  737. fmtstr--;
  738. }
  739. break;
  740. }
  741. // Skip the type characterr
  742. fmtstr++;
  743. }
  744. }
  745. *ptr = NUL;
  746. return (INT)(ptr - buf);
  747. }
  748. INT
  749. OPSprintf(
  750. OUT LPSTR buf,
  751. IN LPCSTR fmtstr,
  752. IN ...
  753. )
  754. {
  755. va_list arglist;
  756. INT iRc;
  757. va_start(arglist, fmtstr);
  758. iRc = OPVsprintf(buf, fmtstr, arglist);
  759. va_end(arglist);
  760. return iRc;
  761. }
  762. int __cdecl compareWinCpt(const void *elem1, const void *elem2)
  763. {
  764. PWINCPT p1;
  765. PWINCPT p2;
  766. p1 = (PWINCPT)elem1;
  767. p2 = (PWINCPT)elem2;
  768. if (p1->usWinCpt == p2->usWinCpt)
  769. return(0);
  770. else if (p1->usWinCpt < p2->usWinCpt)
  771. return(-1);
  772. else
  773. return(1);
  774. }
  775. VOID
  776. SortWinCPT(
  777. IN OUT WINCPT *pSortedWinCpts,
  778. IN WINCPTOPS *pCPtoPS
  779. )
  780. {
  781. // pSortedWinCpts must point to a buffer big enough sizeof(WINCPT)* MAX_CSET_CHARS)
  782. memcpy(pSortedWinCpts, &(pCPtoPS->aWinCpts), sizeof(WINCPT)* MAX_CSET_CHARS);
  783. qsort(pSortedWinCpts, pCPtoPS->ulChCnt, sizeof(WINCPT), compareWinCpt);
  784. }
  785. //
  786. // This function reads a list of CP to PS Name tables and writes an Text file
  787. // with the corresponding PostScript Encoding arrays
  788. // Need to run this whenever we changed the Mapping tables
  789. //
  790. // Format:
  791. // 10 20 30 40
  792. // 1234567890123456789012345678901234567890
  793. // CodePage = dddd (name)
  794. // /name_up_to_32 % XX
  795. //
  796. BOOL
  797. WritePSEncodings(
  798. IN PWSTR pwszFileName,
  799. IN WINCPTOPS *CPtoPSList,
  800. IN DWORD dwPages
  801. )
  802. {
  803. HANDLE hFile;
  804. ULONG i, j, k, l;
  805. WINCPTOPS *pCPtoPS;
  806. WINCPT sortedWinCpts[MAX_CSET_CHARS]; // maxiaml 255 chars
  807. char buffer[256];
  808. DWORD dwLen, ulByteWritten;
  809. hFile = CreateFile(pwszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
  810. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  811. if (hFile == INVALID_HANDLE_VALUE)
  812. {
  813. ERR(("WritePSEncodings:CreateFile\n"));
  814. return(FALSE);
  815. }
  816. for (i = 0; i < dwPages; i++)
  817. {
  818. pCPtoPS = CPtoPSList + i;
  819. dwLen = OPSprintf(buffer, "\n\n CodePage = %d (%s)\n",
  820. pCPtoPS->usACP, pCPtoPS->pGSName);
  821. if (!WriteFile(hFile, buffer, dwLen, (LPDWORD)&ulByteWritten, (LPOVERLAPPED)NULL)
  822. || ulByteWritten != dwLen)
  823. {
  824. ERR(("WritePSEncodings:WriteFile\n"));
  825. CloseHandle(hFile);
  826. return(FALSE);
  827. }
  828. SortWinCPT(&(sortedWinCpts[0]), pCPtoPS);
  829. k = sortedWinCpts[0].usWinCpt;
  830. for (j = 0; j < pCPtoPS->ulChCnt; j++, k++)
  831. {
  832. while (k < sortedWinCpts[j].usWinCpt)
  833. {
  834. dwLen = OPSprintf(buffer, " %% %X\n", k);
  835. if (!WriteFile(hFile, buffer, dwLen, (LPDWORD)&ulByteWritten, (LPOVERLAPPED)NULL)
  836. || ulByteWritten != dwLen)
  837. {
  838. ERR(("WritePSEncodings:WriteFile\n"));
  839. CloseHandle(hFile);
  840. return(FALSE);
  841. }
  842. k++;
  843. }
  844. dwLen = OPSprintf(buffer, " %% %X\n", sortedWinCpts[j].usWinCpt);
  845. strncpy(buffer, "/", 1);
  846. l = strlen(sortedWinCpts[j].pPsName);
  847. strncpy(buffer + 1, sortedWinCpts[j].pPsName, l);
  848. if (!WriteFile(hFile, buffer, dwLen, (LPDWORD)&ulByteWritten, (LPOVERLAPPED)NULL)
  849. || ulByteWritten != dwLen)
  850. {
  851. ERR(("WritePSEncodings:WriteFile\n"));
  852. CloseHandle(hFile);
  853. return(FALSE);
  854. }
  855. }
  856. }
  857. CloseHandle(hFile);
  858. return(TRUE);
  859. }
  860. //
  861. // This causes the error message to show up in your command window
  862. // instead of the kernel debugger window.
  863. //
  864. ULONG _cdecl
  865. DbgPrint(
  866. PCSTR pstrFormat,
  867. ...
  868. )
  869. {
  870. va_list ap;
  871. va_start(ap, pstrFormat);
  872. vprintf(pstrFormat, ap);
  873. va_end(ap);
  874. return 0;
  875. }
  876. VOID
  877. DbgBreakPoint(
  878. VOID
  879. )
  880. {
  881. exit(-1);
  882. }
  883. BOOL NeedBuildMoreNTM(
  884. PBYTE pAFM
  885. )
  886. {
  887. PPSFAMILYINFO pFamilyInfo;
  888. PSZ pszFontName;
  889. pFamilyInfo = NULL;
  890. pszFontName = FindAFMToken(pAFM, PS_FONT_NAME_TOK);
  891. if (NULL ==pszFontName) return FALSE;
  892. pFamilyInfo = (PPSFAMILYINFO) bsearch(pszFontName,
  893. (PBYTE) (((PPSFAMILYINFO) (pFamilyTbl->pTbl))[0].pFontName),
  894. pFamilyTbl->usNumEntries,
  895. sizeof(PSFAMILYINFO),
  896. StrCmp);
  897. if (pFamilyInfo)
  898. {
  899. if (pFamilyInfo->usPitch != DEFAULT_PITCH)
  900. return TRUE;
  901. if (pFamilyInfo > ((PPSFAMILYINFO) (pFamilyTbl->pTbl)))
  902. {
  903. pFamilyInfo = pFamilyInfo - 1;
  904. if (!StrCmp(pFamilyInfo->pFontName, pszFontName) &&
  905. (pFamilyInfo->usPitch != DEFAULT_PITCH))
  906. return TRUE;
  907. }
  908. pFamilyInfo = pFamilyInfo + 1;
  909. if (pFamilyInfo <
  910. (((PPSFAMILYINFO) (pFamilyTbl->pTbl)) + pFamilyTbl->usNumEntries))
  911. {
  912. pFamilyInfo = pFamilyInfo + 1;
  913. if (!StrCmp(pFamilyInfo->pFontName, pszFontName) &&
  914. (pFamilyInfo->usPitch != DEFAULT_PITCH))
  915. return TRUE;
  916. }
  917. }
  918. return FALSE;
  919. }