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.

4987 lines
146 KiB

  1. /*++
  2. Copyright (c) 1996 Adobe Systems Incorporated
  3. Copyright (c) 1996 Microsoft Corporation
  4. Module Name:
  5. afm2ntm.c
  6. Abstract:
  7. Convert AFM to NTM.
  8. Environment:
  9. Windows NT PostScript driver: makentf utility.
  10. Revision History:
  11. 09/11/97 -ksuzuki-
  12. Added code to support localized menu name, fixed pitch CJK font, and
  13. two IFIMETRICS.
  14. 12/11/96 -rkiesler-
  15. Wrote functions.
  16. 09/16/96 -slam-
  17. Created initial framework.
  18. --*/
  19. #include "lib.h"
  20. #include "ppd.h"
  21. #include "pslib.h"
  22. #include "psglyph.h"
  23. #include "afm2ntm.h"
  24. #include "cjkfonts.h"
  25. #include "winfont.h"
  26. //
  27. // Extarnals
  28. //
  29. extern PSTR pAFMFileName;
  30. extern BOOL bVerbose;
  31. extern BOOL bOptimize;
  32. VOID
  33. SortWinCPT(
  34. IN OUT WINCPT *pSortedWinCpts,
  35. IN WINCPTOPS *pCPtoPS
  36. );
  37. //
  38. // Globals.
  39. //
  40. #define NUM_DPCHARSET 16
  41. PUPSCODEPT pPsNames;
  42. BOOL isSymbolCharSet=FALSE;
  43. //
  44. // The purpose of the NTMSIZEINFO and IFIMETRICSSIZEINFO structures is
  45. // to hold aligned size of each structure element.
  46. //
  47. typedef struct _NTMSIZEINFO
  48. {
  49. int nSize;
  50. int nFontNameSize;
  51. int nDisplayNameSize;
  52. int nGlyphSetNameSize;
  53. int nCharWidthSize;
  54. int nKernPairSize;
  55. int nCharDefSize;
  56. int nTotalSize;
  57. }
  58. NTMSIZEINFO;
  59. typedef struct _IFIMETRICSSIZEINFO
  60. {
  61. int nSize;
  62. int nIfiExtraSize;
  63. int nFamilyNameSize;
  64. int nStyleNameSize;
  65. int nFaceNameSize;
  66. int nUniqueNameSize;
  67. int nFontSimSize;
  68. int nBoldSize;
  69. int nItalicSize;
  70. int nBoldItalicSize;
  71. int nCharSetSize;
  72. int nTotalSize;
  73. }
  74. IFIMETRICSSIZEINFO;
  75. #define INIT_NTMSIZEINFO(nsi) \
  76. {\
  77. (nsi).nSize = -1;\
  78. (nsi).nFontNameSize = -1;\
  79. (nsi).nDisplayNameSize = -1;\
  80. (nsi).nGlyphSetNameSize = -1;\
  81. (nsi).nCharWidthSize = -1;\
  82. (nsi).nKernPairSize = -1;\
  83. (nsi).nCharDefSize = -1;\
  84. (nsi).nTotalSize = -1;\
  85. };
  86. #define INIT_IFIMETRICSSIZEINFO(isi) \
  87. {\
  88. (isi).nSize = -1;\
  89. (isi).nIfiExtraSize = -1;\
  90. (isi).nFamilyNameSize = -1;\
  91. (isi).nStyleNameSize = -1;\
  92. (isi).nFaceNameSize = -1;\
  93. (isi).nUniqueNameSize = -1;\
  94. (isi).nFontSimSize = -1;\
  95. (isi).nBoldSize = -1;\
  96. (isi).nItalicSize = -1;\
  97. (isi).nBoldItalicSize = -1;\
  98. (isi).nCharSetSize = -1;\
  99. (isi).nTotalSize = -1;\
  100. };
  101. #define GET_NTMTOTALSIZE(nsi) \
  102. {\
  103. if ((nsi).nSize == -1 \
  104. || (nsi).nFontNameSize == -1 \
  105. || (nsi).nDisplayNameSize == -1 \
  106. || (nsi).nGlyphSetNameSize == -1 \
  107. || (nsi).nCharWidthSize == -1 \
  108. || (nsi).nKernPairSize == -1 \
  109. || (nsi).nCharDefSize == -1)\
  110. {\
  111. ERR(("makentf - afm2ntm: GET_NTMTOTALSIZE\n"));\
  112. }\
  113. (nsi).nTotalSize = (nsi).nSize \
  114. + (nsi).nFontNameSize \
  115. + (nsi).nDisplayNameSize \
  116. + (nsi).nGlyphSetNameSize \
  117. + (nsi).nCharWidthSize \
  118. + (nsi).nKernPairSize \
  119. + (nsi).nCharDefSize;\
  120. };
  121. #define GET_IFIMETRICSTOTALSIZE(isi) \
  122. {\
  123. if ((isi).nSize == -1 \
  124. || (isi).nIfiExtraSize == -1 \
  125. || (isi).nFamilyNameSize == -1 \
  126. || (isi).nStyleNameSize == -1 \
  127. || (isi).nFaceNameSize == -1 \
  128. || (isi).nUniqueNameSize == -1 \
  129. || (isi).nFontSimSize == -1 \
  130. || (isi).nBoldSize == -1 \
  131. || (isi).nItalicSize == -1 \
  132. || (isi).nBoldItalicSize == -1 \
  133. || (isi).nCharSetSize == -1)\
  134. {\
  135. ERR(("makentf - afm2ntm: GET_IFIMETRICSTOTALSIZE\n"));\
  136. }\
  137. (isi).nTotalSize = (isi).nSize \
  138. + (isi).nIfiExtraSize \
  139. + (isi).nFamilyNameSize \
  140. + (isi).nStyleNameSize \
  141. + (isi).nFaceNameSize \
  142. + (isi).nUniqueNameSize \
  143. + (isi).nFontSimSize \
  144. + (isi).nBoldSize \
  145. + (isi).nItalicSize \
  146. + (isi).nBoldItalicSize \
  147. + (isi).nCharSetSize;\
  148. };
  149. #define FREE_AFMTONTM_MEMORY \
  150. {\
  151. if (pNameStr2 != pNameStr) MemFree(pNameStr2);\
  152. MemFree(pNameStr);\
  153. MemFree(pFontChars);\
  154. MemFree(pCharDefTbl);\
  155. };
  156. PNTM
  157. AFMToNTM(
  158. PBYTE pAFM,
  159. PGLYPHSETDATA pGlyphSetData,
  160. PULONG pUniPs,
  161. CHSETSUPPORT *pCharSet,
  162. BOOL bIsCJKFont,
  163. BOOL bIsPitchChanged
  164. )
  165. /*++
  166. Routine Description:
  167. Convert AFM to NTM.
  168. Arguments:
  169. pAFM - pointer to memory mapped AFM file.
  170. pGlyphSetData - pointer to the GLYPHSETDATA struct which represents
  171. this font's preferred charset.
  172. pUniPs - Points to a table which maps 0-based Glyph Indices of chars
  173. in the GLYPHRUNS of the GLYPHSETDATA struct for this font to indices
  174. into the UnicodetoPs structure which maps Unicode points to PS char
  175. information. This mapping array is created by the CreateGlyphSets
  176. function defined in this module.
  177. Return Value:
  178. NULL => error
  179. otherwise => ptr to a NTM.
  180. --*/
  181. {
  182. USHORT multiCharSet=0;
  183. IFIEXTRA *pifiEx;
  184. PBYTE pChMetrics, pToken, pChWidthTok, pCharDefTbl, pby;
  185. CHSETSUPPORT chSets;
  186. PSZ pszGlyphSetName, pszFontName, pszFamilyName, pszEngFamilyName;
  187. int cGlyphSetNameLen, cFontNameLen, cFamilyNameLen, cEngFamilyNameLen;
  188. int cNameStrLen, wcNameStrLen, cNameStr2Len, wcNameStr2Len, chCnt;
  189. PNTM pNTM;
  190. PIFIMETRICS pifi, pifi2;
  191. PWIDTHRUN pWidthRuns;
  192. SHORT sIntLeading, sAscent, sExternalLeading;
  193. ULONG ulNTMSize, ulIFISize, ulIFISize2;
  194. ULONG ulChCnt, ulCharDefTbl, ulKernPairs, ulAliases;
  195. ETMINFO EtmInfo;
  196. PPSFAMILYINFO pFamilyInfo;
  197. RECT rcBBox;
  198. LPPANOSE ppanose;
  199. PGLYPHRUN pGlyphRun;
  200. PSTR pNameStr, pNameStr2;
  201. FD_KERNINGPAIR *pKernPairs;
  202. PPSCHARMETRICS pFontChars;
  203. BOOLEAN bIsVGlyphSet, bIsMSFaceName, bIsFixedPitch, bIsItalic, bIsBold;
  204. USHORT jWinCharSet;
  205. CHARSETINFO csi;
  206. char szStyleName[64], szUniqueID[32];
  207. int i, j;
  208. BOOL bRightFamilyInfo = TRUE;
  209. NTMSIZEINFO nsi;
  210. IFIMETRICSSIZEINFO isi;
  211. VERBOSE(("Entering AFMToNTM...\n"));
  212. INIT_NTMSIZEINFO(nsi);
  213. INIT_IFIMETRICSSIZEINFO(isi);
  214. pNTM = NULL;
  215. pFontChars = NULL;
  216. pCharDefTbl = NULL;
  217. pNameStr = pNameStr2 = NULL;
  218. szStyleName[0] = szUniqueID[0] = '\0';
  219. if (bVerbose) printf("AFM file name:%s\n", pAFMFileName);
  220. //////////////////////////////////////////////////////////////////////////
  221. //
  222. // We support two kinds of CJK AFM files: Adobe CID font AFM or
  223. // clone PS font AFM. Adobe CID font AFM always has the following
  224. // key-value pairs.
  225. //
  226. // FontName Ryumin-Light
  227. // CharacterSet Adobe-Japan1-1 (or others except 'Adobe-Japan1-0')
  228. // IsCIDFont true (must be there)
  229. //
  230. // Note that the FontName value does not include encoding name.
  231. // Just font family name only.
  232. //
  233. // Clone PS font AFM has the following special key-value pairs.
  234. //
  235. // FontName RicohKaisho
  236. // CharacterSet Adobe-Japan1-0
  237. // IsCIDFont false (or must not be there)
  238. //
  239. // The FontName value of clone PS font AFM shouldn't include encoding
  240. // name neither, the CharacterSet value is 'Adobe-Japan1-0' for J, and
  241. // IsCIDFont key should not be specified or must be 'false'.
  242. //
  243. //////////////////////////////////////////////////////////////////////////
  244. //
  245. // Find which glyphset we are dealing with.
  246. //
  247. bIsVGlyphSet = IsVGlyphSet(pGlyphSetData);
  248. pszGlyphSetName = (PSTR)MK_PTR(pGlyphSetData, dwGlyphSetNameOffset);
  249. cGlyphSetNameLen = strlen(pszGlyphSetName);
  250. if (bOptimize)
  251. {
  252. //
  253. // Set referense mark if optimization option is specified. This mark is
  254. // checked later by the WriteNTF function to exclude unreferenced
  255. // glyphset data when writing to an NTF file.
  256. //
  257. pGlyphSetData->dwReserved[0] = 1;
  258. }
  259. //
  260. // Save number of chars defined in the font.
  261. // Get ptr to AFM char metrics, then the current
  262. // pos should be the character count field.
  263. //
  264. pToken = FindAFMToken(pAFM, PS_CH_METRICS_TOK);
  265. if (pToken == NULL) // Fixed bug 354007
  266. {
  267. ERR(("makentf - afm2ntm: CH Metrics missing\n"));
  268. return NULL;
  269. }
  270. for (i = 0; i < (int) StrLen(pToken); i++)
  271. {
  272. if (!IS_NUM(&pToken[i]))
  273. {
  274. ERR(("makentf - afm2ntm: CH Metrics is not a number\n"));
  275. return NULL;
  276. }
  277. }
  278. chCnt = atoi(pToken);
  279. //
  280. // Get number of GLYPHs from GlyphsetData. We'll need to use define
  281. // char width table entries and char defined entries for all
  282. // possible glyphs in the glyphset, even those that are not defined
  283. // in this particular font.
  284. //
  285. ulChCnt = pGlyphSetData->dwGlyphCount;
  286. //
  287. // Alloc memory for an array of PSCHARMETRICS structs, one for each char
  288. // in the font, and build the table of char metrics.
  289. //
  290. if ((pFontChars =
  291. (PPSCHARMETRICS)
  292. MemAllocZ((size_t) chCnt * sizeof(PSCHARMETRICS))) == NULL)
  293. {
  294. ERR(("makentf - afm2ntm: malloc\n"));
  295. return NULL;
  296. }
  297. //
  298. // Alloc memory for the IsCharDefined table, an array of bits which
  299. // indicate which chars in the GLYPHSET are defined in this font.
  300. //
  301. ulCharDefTbl = ((ulChCnt + 7) / 8) * sizeof (BYTE);
  302. if ((pCharDefTbl = (PBYTE)MemAllocZ((size_t)ulCharDefTbl)) == NULL)
  303. {
  304. ERR(("makentf - afm2ntm: malloc\n"));
  305. MemFree(pFontChars);
  306. return NULL;
  307. }
  308. //
  309. // Build table of PSCHARMETRICS info.
  310. //
  311. if (!BuildPSCharMetrics(pAFM, pUniPs, pFontChars, pCharDefTbl, ulChCnt))
  312. {
  313. ERR(("makentf - afm2ntm: BuildPSCharMetrics\n"));
  314. MemFree(pFontChars);
  315. MemFree(pCharDefTbl);
  316. return NULL;
  317. }
  318. //
  319. // Get font name from AFM and use it to obtain the MS family name
  320. // from the table in memory.
  321. //
  322. pszEngFamilyName = NULL;
  323. cEngFamilyNameLen = 0;
  324. pFamilyInfo = NULL;
  325. pszFontName = FindAFMToken(pAFM, PS_FONT_NAME_TOK);
  326. if (pszFontName == NULL) // Fixed bug 354007
  327. {
  328. ERR(("makentf - afm2ntm: Font Name Missing\n"));
  329. FREE_AFMTONTM_MEMORY;
  330. return NULL;
  331. }
  332. for (cFontNameLen = 0; !EOL(&pszFontName[cFontNameLen]); cFontNameLen++);
  333. pFamilyInfo = (PPSFAMILYINFO) bsearch(pszFontName,
  334. (PBYTE) (((PPSFAMILYINFO) (pFamilyTbl->pTbl))[0].pFontName),
  335. pFamilyTbl->usNumEntries,
  336. sizeof(PSFAMILYINFO),
  337. StrCmp);
  338. if (bIsMSFaceName = (pFamilyInfo != NULL))
  339. {
  340. bRightFamilyInfo = TRUE;
  341. if (bIsPitchChanged && (pFamilyInfo->usPitch == DEFAULT_PITCH))
  342. {
  343. bRightFamilyInfo = FALSE;
  344. if (pFamilyInfo > ((PPSFAMILYINFO) (pFamilyTbl->pTbl)))
  345. {
  346. pFamilyInfo = pFamilyInfo - 1;
  347. if (!StrCmp(pFamilyInfo->pFontName, pszFontName) &&
  348. (pFamilyInfo->usPitch != DEFAULT_PITCH ))
  349. bRightFamilyInfo = TRUE;
  350. }
  351. if (bRightFamilyInfo == FALSE)
  352. {
  353. pFamilyInfo = pFamilyInfo + 1;
  354. if (pFamilyInfo <
  355. (((PPSFAMILYINFO) (pFamilyTbl->pTbl)) + pFamilyTbl->usNumEntries))
  356. {
  357. pFamilyInfo = pFamilyInfo + 1;
  358. if (!StrCmp(pFamilyInfo->pFontName, pszFontName) &&
  359. (pFamilyInfo->usPitch != DEFAULT_PITCH))
  360. bRightFamilyInfo = TRUE;
  361. }
  362. }
  363. }
  364. else if (!bIsPitchChanged && (pFamilyInfo->usPitch != DEFAULT_PITCH))
  365. {
  366. bRightFamilyInfo = FALSE;
  367. if (pFamilyInfo > ((PPSFAMILYINFO) (pFamilyTbl->pTbl)))
  368. {
  369. pFamilyInfo = pFamilyInfo - 1;
  370. if (!StrCmp(pFamilyInfo->pFontName, pszFontName) &&
  371. (pFamilyInfo->usPitch == DEFAULT_PITCH))
  372. bRightFamilyInfo = TRUE;
  373. }
  374. if (bRightFamilyInfo == FALSE)
  375. {
  376. pFamilyInfo = pFamilyInfo + 1;
  377. if (pFamilyInfo <
  378. (((PPSFAMILYINFO) (pFamilyTbl->pTbl)) + pFamilyTbl->usNumEntries))
  379. {
  380. pFamilyInfo = pFamilyInfo + 1;
  381. if (!StrCmp(pFamilyInfo->pFontName, pszFontName) &&
  382. (pFamilyInfo->usPitch == DEFAULT_PITCH))
  383. bRightFamilyInfo = TRUE;
  384. }
  385. }
  386. }
  387. }
  388. if (bIsMSFaceName && (bRightFamilyInfo == TRUE))
  389. {
  390. pszFamilyName = pFamilyInfo->FamilyKey.pName;
  391. cFamilyNameLen = strlen(pszFamilyName);
  392. pszEngFamilyName = pFamilyInfo->pEngFamilyName;
  393. cEngFamilyNameLen = strlen(pszEngFamilyName);
  394. if (!cEngFamilyNameLen) pszEngFamilyName = NULL;
  395. }
  396. else if ((pszFamilyName =
  397. FindAFMToken(pAFM, PS_FONT_FAMILY_NAME_TOK)) != NULL)
  398. {
  399. for (cFamilyNameLen = 0; !EOL(&pszFamilyName[cFamilyNameLen]); cFamilyNameLen++);
  400. }
  401. else
  402. {
  403. pszFamilyName = pszFontName;
  404. cFamilyNameLen = cFontNameLen;
  405. }
  406. if (bVerbose)
  407. {
  408. printf("MSFaceName%sfound:", bIsMSFaceName ? " " : " not ");
  409. printf("%s\n", bIsMSFaceName ? pszFamilyName : "n/a");
  410. printf("MSFaceName length:%d\n", bIsMSFaceName ? cFamilyNameLen : -1);
  411. printf("This is a %s font.\n", bIsVGlyphSet ? "vertical" : "horizontal");
  412. }
  413. //
  414. // Predetermine if this font supports multiple charsets.
  415. //
  416. if (pCharSet)
  417. {
  418. if (CSET_SUPPORT(*pCharSet, CS_ANSI))
  419. multiCharSet++;
  420. if (CSET_SUPPORT(*pCharSet, CS_EASTEUROPE))
  421. multiCharSet++;
  422. if (CSET_SUPPORT(*pCharSet, CS_RUSSIAN))
  423. multiCharSet++;
  424. if (CSET_SUPPORT(*pCharSet, CS_GREEK))
  425. multiCharSet++;
  426. if (CSET_SUPPORT(*pCharSet, CS_TURKISH))
  427. multiCharSet++;
  428. if (CSET_SUPPORT(*pCharSet, CS_HEBREW))
  429. multiCharSet++;
  430. if (CSET_SUPPORT(*pCharSet, CS_ARABIC))
  431. multiCharSet++;
  432. if (CSET_SUPPORT(*pCharSet, CS_BALTIC))
  433. multiCharSet++;
  434. if (CSET_SUPPORT(*pCharSet, CS_SYMBOL))
  435. multiCharSet++;
  436. //
  437. // Save Windows Codepage id. Just use the id stored in the first
  438. // CODEPAGEINFO in the GLYPHSETDATA for this font.
  439. //
  440. // The order of this check is important since jWinCharSet
  441. // should match the first dpCharSets array if it exists.
  442. //
  443. if (CSET_SUPPORT(*pCharSet, CS_ANSI))
  444. jWinCharSet = ANSI_CHARSET;
  445. else if (CSET_SUPPORT(*pCharSet, CS_EASTEUROPE))
  446. jWinCharSet = EASTEUROPE_CHARSET;
  447. else if (CSET_SUPPORT(*pCharSet, CS_RUSSIAN))
  448. jWinCharSet = RUSSIAN_CHARSET;
  449. else if (CSET_SUPPORT(*pCharSet, CS_GREEK))
  450. jWinCharSet = GREEK_CHARSET;
  451. else if (CSET_SUPPORT(*pCharSet, CS_TURKISH))
  452. jWinCharSet = TURKISH_CHARSET;
  453. else if (CSET_SUPPORT(*pCharSet, CS_HEBREW))
  454. jWinCharSet = HEBREW_CHARSET;
  455. else if (CSET_SUPPORT(*pCharSet, CS_ARABIC))
  456. jWinCharSet = ARABIC_CHARSET;
  457. else if (CSET_SUPPORT(*pCharSet, CS_BALTIC))
  458. jWinCharSet = BALTIC_CHARSET;
  459. else if (CSET_SUPPORT(*pCharSet, CS_SYMBOL))
  460. jWinCharSet = SYMBOL_CHARSET;
  461. }
  462. else
  463. {
  464. PCODEPAGEINFO cpi = (PCODEPAGEINFO)MK_PTR(pGlyphSetData, dwCodePageOffset);
  465. jWinCharSet = (USHORT)(cpi->dwWinCharset & 0xffff);
  466. }
  467. //
  468. // Get codepage info for the MultiByteToWideChar function calls.
  469. //
  470. // We want to translate a string into a readable one, not into a symbolic
  471. // one, so that we use ANSI charset when dealing with SYMBOL charset.
  472. //
  473. if (jWinCharSet == SYMBOL_CHARSET)
  474. {
  475. DWORD dwTmp = ANSI_CHARSET;
  476. if (!TranslateCharsetInfo(&dwTmp, &csi, TCI_SRCCHARSET))
  477. csi.ciACP = CP_ACP;
  478. }
  479. else if (!TranslateCharsetInfo((DWORD FAR*)jWinCharSet, &csi, TCI_SRCCHARSET))
  480. csi.ciACP = CP_ACP;
  481. //////////////////////////////////////////////////////////////////////////
  482. //
  483. // Get the size of each element of NTM structure
  484. //
  485. //////////////////////////////////////////////////////////////////////////
  486. //
  487. // Sizes known so far.
  488. //
  489. nsi.nSize = ALIGN4(sizeof (NTM));
  490. nsi.nGlyphSetNameSize = ALIGN4(cGlyphSetNameLen + 1);
  491. nsi.nCharDefSize = ALIGN4(ulCharDefTbl);
  492. //
  493. // Size of the font name. Glyphset name is required for CJK font.
  494. //
  495. nsi.nFontNameSize = ALIGN4(cFontNameLen + 1);
  496. if (bIsCJKFont)
  497. {
  498. nsi.nFontNameSize += nsi.nGlyphSetNameSize;
  499. }
  500. //
  501. // Size of the display name. Use pszFamilyName regardless of
  502. // Roman, C, J, and K fonts. Add one for '@' if it's CJK
  503. // vertical font.
  504. //
  505. i = cFamilyNameLen + 1;
  506. if (bIsCJKFont && bIsVGlyphSet) i++;
  507. nsi.nDisplayNameSize = ALIGN4(i);
  508. //
  509. // Determine if font is fixed pitch.
  510. //
  511. bIsFixedPitch = FALSE;
  512. if (bIsCJKFont)
  513. {
  514. bIsFixedPitch = IsCJKFixedPitchEncoding(pGlyphSetData);
  515. }
  516. else if ((pToken = FindAFMToken(pAFM, PS_PITCH_TOK)) != NULL)
  517. {
  518. if (!StrCmp(pToken, "true"))
  519. {
  520. //
  521. // This is a fixed pitch font.
  522. //
  523. bIsFixedPitch = !StrCmp(pToken, "true");
  524. }
  525. }
  526. if (bIsFixedPitch)
  527. {
  528. nsi.nCharWidthSize = 0;
  529. }
  530. else
  531. {
  532. //
  533. // Proportional font. Determine number of WIDTHRUNs for this font.
  534. //
  535. // Fix bug 240339, jjia, 8/3/98
  536. nsi.nCharWidthSize =
  537. GetAFMCharWidths(pAFM, NULL, pFontChars, pUniPs,
  538. pGlyphSetData->dwGlyphCount, NULL, NULL);
  539. }
  540. //
  541. // Determine if there is the pair kerning info for this font.
  542. //
  543. if (ulKernPairs = GetAFMKernPairs(pAFM, NULL, pGlyphSetData))
  544. {
  545. //
  546. // Account for size of kern pairs.
  547. //
  548. nsi.nKernPairSize = ALIGN4((ulKernPairs + 1) * sizeof(FD_KERNINGPAIR));
  549. }
  550. else
  551. {
  552. nsi.nKernPairSize = 0;
  553. }
  554. //////////////////////////////////////////////////////////////////////////
  555. //
  556. // Get the size of each element of IFIMETRICS structure
  557. //
  558. //////////////////////////////////////////////////////////////////////////
  559. isi.nSize = ALIGN4(sizeof (IFIMETRICS));
  560. //
  561. // From AdobePS5-NT4 5.1, make the size of NT4 IFIEXTRA same as the one
  562. // of NT5 or later versions. NT4 IFIEXTRA size is 16 and NT5 IFIEXTRA
  563. // size is 24.
  564. //
  565. if (sizeof (IFIEXTRA) <= 16)
  566. isi.nIfiExtraSize = 24;
  567. else
  568. isi.nIfiExtraSize = ALIGN4(sizeof (IFIEXTRA));
  569. //
  570. // For Roman we provide single IFIMETRICS, but we provide two IFIMETRICS
  571. // for CJK. Font family name element of the first IFIMETRICS begins with
  572. // a menu name in English then localized one. Font family name element of
  573. // the second IFIMETRICS begins with a localized menu name then English
  574. // one. We use pNameStr and pNameStr2 for the English and localized menu
  575. // names respectively.
  576. //
  577. // Prepare pNameStr. Account for encoding name if we are dealing with
  578. // CJK font.
  579. //
  580. i = 0;
  581. if (bIsCJKFont)
  582. {
  583. if (bIsVGlyphSet)
  584. {
  585. //
  586. // V GS, account for preceding '@' char.
  587. //
  588. i++;
  589. }
  590. if (pszEngFamilyName)
  591. {
  592. //
  593. // IFIMetrics English menu name = [@]fontname
  594. //
  595. if ((pNameStr = (PSTR) MemAllocZ(i + cEngFamilyNameLen + 1)) == NULL)
  596. {
  597. ERR(("makentf - afm2ntm: malloc\n"));
  598. FREE_AFMTONTM_MEMORY;
  599. return NULL;
  600. }
  601. if (i) pNameStr[0] = '@';
  602. memcpy(&(pNameStr[i]), pszEngFamilyName, cEngFamilyNameLen);
  603. i += cEngFamilyNameLen;
  604. }
  605. else
  606. {
  607. int cGsNameLen;
  608. //
  609. // IFIMetrics English menu name = [@]fontname + GS name string,
  610. // but it does not end with '-H' or '-V'.
  611. //
  612. cGsNameLen = cGlyphSetNameLen - 2;
  613. if ((pNameStr = (PSTR) MemAllocZ(i + cFontNameLen + cGsNameLen + 1)) == NULL)
  614. {
  615. ERR(("makentf - afm2ntm: malloc\n"));
  616. FREE_AFMTONTM_MEMORY;
  617. return NULL;
  618. }
  619. if (i) pNameStr[0] = '@';
  620. memcpy(&(pNameStr[i]), pszFontName, cFontNameLen);
  621. memcpy(&(pNameStr[i + cFontNameLen]), pszGlyphSetName, cGsNameLen);
  622. i += cFontNameLen + cGsNameLen;
  623. }
  624. }
  625. else
  626. {
  627. if ((pNameStr = (PSTR) MemAllocZ(cFamilyNameLen + 1)) == NULL)
  628. {
  629. ERR(("makentf - afm2ntm: malloc\n"));
  630. FREE_AFMTONTM_MEMORY;
  631. return NULL;
  632. }
  633. memcpy(pNameStr, pszFamilyName, cFamilyNameLen);
  634. i += cFamilyNameLen;
  635. }
  636. pNameStr[i] = '\0';
  637. cNameStrLen = strlen(pNameStr);
  638. wcNameStrLen = MultiByteToWideChar(csi.ciACP, 0,
  639. pNameStr, cNameStrLen, 0, 0);
  640. if (!wcNameStrLen)
  641. {
  642. ERR(("makentf - afm2ntm: MultiByteToWideChar\n"));
  643. FREE_AFMTONTM_MEMORY;
  644. return NULL;
  645. }
  646. //
  647. // Prepair pNameStr2. This if for CJK font only. If MS face name
  648. // is not available, use same name as pNameStr.
  649. //
  650. pNameStr2 = NULL;
  651. cNameStr2Len = wcNameStr2Len = 0;
  652. if (bIsCJKFont)
  653. {
  654. if (bIsMSFaceName)
  655. {
  656. //
  657. // If we are dealing with V encoding, its MS menu name can not be
  658. // found in psfamily.dat so that add '@' to make it a V menu name.
  659. //
  660. i = bIsVGlyphSet ? 1 : 0;
  661. if ((pNameStr2 = (PSTR)MemAllocZ(i + cFamilyNameLen + 1)) == NULL)
  662. {
  663. ERR(("makentf - afm2ntm: malloc\n"));
  664. FREE_AFMTONTM_MEMORY;
  665. return NULL;
  666. }
  667. if (i) pNameStr2[0] = '@';
  668. memcpy(&(pNameStr2[i]), pszFamilyName, cFamilyNameLen);
  669. pNameStr2[i + cFamilyNameLen] = '\0';
  670. }
  671. else
  672. {
  673. pNameStr2 = pNameStr;
  674. }
  675. cNameStr2Len = strlen(pNameStr2);
  676. wcNameStr2Len = MultiByteToWideChar(csi.ciACP, 0,
  677. pNameStr2, cNameStr2Len, 0, 0);
  678. if (!wcNameStr2Len)
  679. {
  680. ERR(("makentf - afm2ntm: MultiByteToWideChar\n"));
  681. FREE_AFMTONTM_MEMORY;
  682. return NULL;
  683. }
  684. }
  685. if (bVerbose)
  686. {
  687. printf("Font menu name in English:%s\n", pNameStr);
  688. printf("Localized Font menu name%savailable:", pNameStr2 ? " " : " not ");
  689. printf("%s\n", pNameStr2 ? pNameStr2 : "n/a");
  690. }
  691. //
  692. // WIN31 COMPATABILITY! Check to see if this face name has aliases.
  693. // if it does, then we need to set the FM_INFO_FAMILY_EQUIV bit of
  694. // pTmpIFI->flInfo, and fill in an array of family aliases. Note that
  695. // the cjGetFamilyAliases function gives us the number in Unicode size.
  696. //
  697. isi.nFamilyNameSize = ALIGN4(cjGetFamilyAliases(NULL, pNameStr, 0));
  698. if (pNameStr2)
  699. {
  700. //
  701. // We add one more face name. Thus, set FM_INFO_FAMILY_EQUIV bit
  702. // (later) and add two, instead of one, for the two-null terminators.
  703. //
  704. isi.nFamilyNameSize += ALIGN4((wcNameStr2Len + 2) * sizeof (WCHAR));
  705. }
  706. //
  707. // Account for size of Adobe PS font name. This is zero because it
  708. // shares the face name for Win3.1 compatibility.
  709. //
  710. isi.nFaceNameSize = 0;
  711. //
  712. // Account for the sizes of the style and unique names in Unicode string.
  713. //
  714. // Style name: conbine Weight and ' Italic' if non-zero ItalicAngle values
  715. // is present.
  716. //
  717. // Unique name: convert UniqueID value into Unicode string. If UniqueID
  718. // is not found, leave the name blank.
  719. //
  720. pToken = FindAFMToken(pAFM, PS_WEIGHT_TOK);
  721. if (pToken == NULL)
  722. {
  723. ERR(("makentf - afm2ntm: Weight value missing\n"));
  724. FREE_AFMTONTM_MEMORY;
  725. return NULL;
  726. }
  727. AFM2NTMStrCpy(szStyleName, CCHOF(szStyleName), pToken);
  728. pToken = FindAFMToken(pAFM, PS_ITALIC_TOK);
  729. if (pToken)
  730. {
  731. if (atoi(pToken) > 0)
  732. StringCchCatA(szStyleName, CCHOF(szStyleName), " Italic");
  733. }
  734. isi.nStyleNameSize = ALIGN4((strlen(szStyleName) + 1) * 2);
  735. pToken = FindUniqueID(pAFM);
  736. if (pToken)
  737. {
  738. AFM2NTMStrCpy(szUniqueID, CCHOF(szUniqueID), pToken);
  739. isi.nUniqueNameSize = ALIGN4((strlen(szUniqueID) + 1) * 2);
  740. }
  741. else
  742. isi.nUniqueNameSize = 0;
  743. //
  744. // If font doesn't support (Italics OR Bold), reserve additional memory
  745. // at end of IFIMETRICS for structures required to do Italics simulation.
  746. //
  747. bIsItalic = FALSE;
  748. bIsBold = FALSE;
  749. j = bIsCJKFont ? 1 : 0;
  750. if ((pToken = FindAFMToken(pAFM, PS_ITALIC_TOK)) != NULL)
  751. {
  752. if ( StrCmp(pToken, "0") && StrCmp(pToken, "0.0") )
  753. bIsItalic = TRUE;
  754. }
  755. if ((pToken = FindAFMToken(pAFM, PS_WEIGHT_TOK)) != NULL)
  756. {
  757. for (i = 0; i < WeightKeyTbl[j].usNumEntries; i++)
  758. {
  759. if (!StrCmp(pToken, (PBYTE)(((PKEY) (WeightKeyTbl[j].pTbl))[i].pName)))
  760. {
  761. if ((((PKEY) (WeightKeyTbl[j].pTbl))[i].usValue) == FW_BOLD)
  762. {
  763. bIsBold = TRUE;
  764. }
  765. break;
  766. }
  767. }
  768. }
  769. // Reserve space for dpFontSim
  770. if (!bIsBold || !bIsItalic)
  771. isi.nFontSimSize = ALIGN4(sizeof(FONTSIM));
  772. else
  773. isi.nFontSimSize = 0;
  774. // Reserve space for dpBold
  775. if (!bIsBold)
  776. isi.nBoldSize = ALIGN4(sizeof(FONTDIFF));
  777. else
  778. isi.nBoldSize = 0;
  779. // Reserve space for dpItalic
  780. if (!bIsItalic)
  781. isi.nItalicSize = ALIGN4(sizeof(FONTDIFF));
  782. else
  783. isi.nItalicSize = 0;
  784. // Reserve space for dpBoldItalic
  785. if (!bIsBold || !bIsItalic)
  786. isi.nBoldItalicSize = ALIGN4(sizeof(FONTDIFF));
  787. else
  788. isi.nBoldItalicSize = 0;
  789. // Determine if this font supports multiple char sets.
  790. if (pCharSet)
  791. {
  792. if (multiCharSet > 1)
  793. isi.nCharSetSize = ALIGN4(NUM_DPCHARSET);
  794. else
  795. isi.nCharSetSize = 0;
  796. }
  797. else
  798. {
  799. isi.nCharSetSize = 0;
  800. }
  801. //////////////////////////////////////////////////////////////////////////
  802. //
  803. // Allocate memory for NTM, IFIMETRICS, and strings. We provide
  804. // the secondary IFIMETRICS and strings if we are dealing with
  805. // CJK font.
  806. //
  807. //////////////////////////////////////////////////////////////////////////
  808. GET_NTMTOTALSIZE(nsi);
  809. ulNTMSize = (ULONG)nsi.nTotalSize;
  810. GET_IFIMETRICSTOTALSIZE(isi);
  811. ulIFISize = (ULONG)isi.nTotalSize;
  812. ulIFISize2 = bIsCJKFont ? ulIFISize * 2 : ulIFISize;
  813. pNTM = (PNTM) MemAllocZ((size_t)(ulNTMSize + ulIFISize2));
  814. if (pNTM == NULL)
  815. {
  816. ERR(("makentf - afm2ntm: malloc\n"));
  817. FREE_AFMTONTM_MEMORY;
  818. return NULL;
  819. }
  820. //////////////////////////////////////////////////////////////////////////
  821. //
  822. // Construct NTM structure
  823. //
  824. //////////////////////////////////////////////////////////////////////////
  825. pNTM->dwSize = ulNTMSize + ulIFISize2;
  826. pNTM->dwVersion = NTM_VERSION;
  827. pNTM->dwFlags = 0;
  828. //
  829. // Store the font name.
  830. //
  831. pNTM->dwFontNameOffset = ALIGN4(sizeof(NTM));
  832. pby = (PBYTE)MK_PTR(pNTM, dwFontNameOffset);
  833. memcpy(pby, pszFontName, cFontNameLen);
  834. pby += cFontNameLen;
  835. if (bIsCJKFont)
  836. {
  837. //
  838. // Append glyphset name string to the font name.
  839. //
  840. memcpy(pby, pszGlyphSetName, cGlyphSetNameLen);
  841. pby += cGlyphSetNameLen;
  842. }
  843. *pby = '\0';
  844. //
  845. // Store the display name.
  846. //
  847. pNTM->dwDisplayNameOffset = pNTM->dwFontNameOffset
  848. + (DWORD)nsi.nFontNameSize;
  849. pby = (PBYTE)MK_PTR(pNTM, dwDisplayNameOffset);
  850. if (bIsCJKFont && bIsVGlyphSet) *pby++ = '@';
  851. memcpy(pby, pszFamilyName, cFamilyNameLen);
  852. *(pby + cFamilyNameLen) = '\0';
  853. //
  854. // Get PS font version from AFM and store in NTM.
  855. //
  856. pToken = FindAFMToken(pAFM, PS_FONT_VERSION_TOK);
  857. if (pToken == NULL) // Fixed bug 354007
  858. {
  859. ERR(("makentf - afm2ntm: Font Version value missing\n"));
  860. FREE_AFMTONTM_MEMORY;
  861. return NULL;
  862. }
  863. pNTM->dwFontVersion = atoi(pToken) << 16 | atoi(&pToken[4]);
  864. //
  865. // Get the name string of the GLYPHSETDATA associated with this font
  866. // and store it in NTM.
  867. //
  868. pNTM->dwGlyphSetNameOffset = pNTM->dwDisplayNameOffset
  869. + (DWORD)nsi.nDisplayNameSize;
  870. StringCchCopyA((PBYTE)MK_PTR(pNTM, dwGlyphSetNameOffset), nsi.nGlyphSetNameSize, pszGlyphSetName);
  871. //
  872. // Store the count of Glyphs.
  873. //
  874. pNTM->dwGlyphCount = ulChCnt;
  875. //
  876. // Calculate offset, create ptr to IFIMETRICS.
  877. //
  878. pNTM->dwIFIMetricsOffset = ulNTMSize;
  879. pifi = (PIFIMETRICS) MK_PTR(pNTM, dwIFIMetricsOffset);
  880. //
  881. // Calculate offset, create ptr to the secondly IFIMETRICS if necessary.
  882. //
  883. if (bIsCJKFont)
  884. {
  885. pNTM->dwIFIMetricsOffset2 = ulNTMSize + ulIFISize;
  886. pifi2 = (PIFIMETRICS)MK_PTR(pNTM, dwIFIMetricsOffset2);
  887. }
  888. else
  889. {
  890. pNTM->dwIFIMetricsOffset2 = 0;
  891. pifi2 = NULL;
  892. }
  893. //
  894. // For both Fixed and Prop fonts, we need to get the ETMInfo.
  895. // (Fix bug 211966, PPeng, 6-6-97)
  896. //
  897. GetAFMETM(pAFM, pFontChars, &EtmInfo);
  898. //
  899. // According to AFM spec, if a 'CharWidth' token is found in AFM, the
  900. // font must be fixed pitch.
  901. //
  902. if (bIsFixedPitch)
  903. {
  904. //
  905. // This is a fixed pitch font. Get the AvgWidth - which is anyone's width
  906. //
  907. pNTM->dwDefaultCharWidth = 0;
  908. pNTM->dwCharWidthCount = 0;
  909. pNTM->dwCharWidthOffset = 0;
  910. //
  911. // We just get a reasonable number from the AFM different from zero.
  912. // This number is used in computing font transfroms.
  913. //
  914. if ((pToken = FindAFMToken(pAFM, PS_CH_METRICS_TOK)) != NULL)
  915. {
  916. //
  917. // Get width of first char defined in AFM and use as
  918. // average width.
  919. //
  920. NEXT_TOKEN(pToken);
  921. pChWidthTok = FindAFMToken(pToken, PS_CH_WIDTH_TOK);
  922. if (pChWidthTok == NULL)
  923. {
  924. pChWidthTok = FindAFMToken(pToken, PS_CH_WIDTH0_TOK);
  925. }
  926. if (pChWidthTok != NULL)
  927. {
  928. pToken = pChWidthTok;
  929. pifi->fwdAveCharWidth =
  930. pifi->fwdMaxCharInc = (FWORD)atoi(pToken);
  931. }
  932. }
  933. pifi->fwdMaxCharInc = pifi->fwdAveCharWidth ;
  934. if (bIsCJKFont)
  935. {
  936. // DCR: couldn't divide by 2 simply for C and K.
  937. pifi->fwdAveCharWidth /= 2;
  938. }
  939. ASSERTMSG(pifi->fwdAveCharWidth, ("PSCRIPT: pifi->fwdAveCharWidth == 0\n"));
  940. }
  941. else
  942. {
  943. //
  944. // Proportional font. Generate WIDTHRUNs.
  945. //
  946. pNTM->dwCharWidthOffset = pNTM->dwGlyphSetNameOffset
  947. + (DWORD)nsi.nGlyphSetNameSize;
  948. pWidthRuns = (PWIDTHRUN) MK_PTR(pNTM, dwCharWidthOffset);
  949. pNTM->dwCharWidthCount = GetAFMCharWidths(pAFM,
  950. &pWidthRuns,
  951. pFontChars,
  952. pUniPs,
  953. pGlyphSetData->dwGlyphCount,
  954. &pifi->fwdAveCharWidth,
  955. &pifi->fwdMaxCharInc);
  956. // Fix bug 240339, jjia, 8/3/98
  957. if (pWidthRuns[0].dwCharWidth == WIDTHRUN_COMPLEX)
  958. {
  959. pWidthRuns[0].dwCharWidth = WIDTHRUN_COMPLEX +
  960. sizeof(WIDTHRUN);
  961. }
  962. }
  963. //
  964. // For both Prop and Fixed fonts
  965. // (Fix bug 210314, PPeng, 6-10-97)
  966. //
  967. pNTM->dwDefaultCharWidth = pifi->fwdAveCharWidth;
  968. //
  969. // Construct kerning pairs.
  970. //
  971. if (ulKernPairs)
  972. {
  973. //
  974. // Fill NTM with kern pair data.
  975. //
  976. pNTM->dwKernPairOffset = pNTM->dwGlyphSetNameOffset
  977. + (DWORD)nsi.nGlyphSetNameSize
  978. + (DWORD)nsi.nCharWidthSize;
  979. pKernPairs = (FD_KERNINGPAIR *) MK_PTR(pNTM, dwKernPairOffset);
  980. pNTM->dwKernPairCount = GetAFMKernPairs(pAFM, pKernPairs, pGlyphSetData);
  981. }
  982. else
  983. {
  984. //
  985. // No pair kerning info for this font.
  986. //
  987. pNTM->dwKernPairCount = 0;
  988. pNTM->dwKernPairOffset = 0;
  989. }
  990. //
  991. // Store the CharDefined tbl.
  992. //
  993. pNTM->dwCharDefFlagOffset = pNTM->dwGlyphSetNameOffset
  994. + (DWORD)nsi.nGlyphSetNameSize
  995. + (DWORD)nsi.nCharWidthSize
  996. + (DWORD)nsi.nKernPairSize;
  997. memcpy((PBYTE) MK_PTR(pNTM, dwCharDefFlagOffset), pCharDefTbl, ulCharDefTbl);
  998. //
  999. // Get font character set from AFM and store in NTM
  1000. //
  1001. pToken = pAFMCharacterSetString;
  1002. if (pToken != NULL)
  1003. {
  1004. if (StrCmp(pToken, PS_STANDARD_CHARSET_TOK) == 0)
  1005. pNTM->dwCharSet = CHARSET_STANDARD;
  1006. else if (StrCmp(pToken, PS_SPECIAL_CHARSET_TOK) == 0)
  1007. pNTM->dwCharSet = CHARSET_SPECIAL;
  1008. else if (StrCmp(pToken, PS_EXTENDED_CHARSET_TOK) == 0)
  1009. pNTM->dwCharSet = CHARSET_EXTENDED;
  1010. else
  1011. pNTM->dwCharSet = CHARSET_UNKNOWN;
  1012. }
  1013. //
  1014. // Save the codepage of the font if there is only one of it is used for
  1015. // the font.
  1016. //
  1017. if (pGlyphSetData->dwCodePageCount == 1)
  1018. pNTM->dwCodePage = ((PCODEPAGEINFO)MK_PTR(pGlyphSetData, dwCodePageOffset))->dwCodePage;
  1019. else
  1020. pNTM->dwCodePage = 0;
  1021. //
  1022. // Cleare the reserved area.
  1023. //
  1024. pNTM->dwReserved[0] =
  1025. pNTM->dwReserved[1] =
  1026. pNTM->dwReserved[2] = 0;
  1027. //////////////////////////////////////////////////////////////////////////
  1028. //
  1029. // Construct IFIMETRICS structure
  1030. //
  1031. //////////////////////////////////////////////////////////////////////////
  1032. pifi->cjThis = ulIFISize;
  1033. pifi->cjIfiExtra = isi.nIfiExtraSize;
  1034. pifi->lEmbedId = 0; // only useful for tt fonts
  1035. pifi->lCharBias = 0; // only useful for tt fonts
  1036. pifi->flInfo = FM_INFO_ARB_XFORMS |
  1037. FM_INFO_NOT_CONTIGUOUS |
  1038. FM_INFO_TECH_OUTLINE_NOT_TRUETYPE |
  1039. FM_INFO_1BPP |
  1040. FM_INFO_RIGHT_HANDED;
  1041. //
  1042. // Everything in IFIEXTRA is leave blank for now.
  1043. // Only the number of glyphs is filled in.
  1044. //
  1045. pifiEx = (PIFIEXTRA)((PBYTE)pifi + isi.nSize);
  1046. pifiEx->cig = pGlyphSetData->dwGlyphCount;
  1047. //
  1048. // Store font family name to IFIMETRICS. Copy font name aliases too if any.
  1049. // Note that this routine also converts the appropriate family name str to
  1050. // unicode prior to storing it in IFIMETRICS.
  1051. //
  1052. pifi->dpwszFamilyName = (PTRDIFF)(isi.nSize + isi.nIfiExtraSize);
  1053. ulAliases = cjGetFamilyAliases(pifi, pNameStr, csi.ciACP);
  1054. //
  1055. // Adjust ulAliases to the first null terminator if FM_INFO_FAMILY_EQUIV
  1056. // bit is set.
  1057. //
  1058. if (pifi->flInfo & FM_INFO_FAMILY_EQUIV)
  1059. ulAliases -= sizeof (WCHAR);
  1060. if (pNameStr2)
  1061. {
  1062. pifi->flInfo |= FM_INFO_FAMILY_EQUIV;
  1063. pby = (PBYTE)MK_PTR(pifi, dpwszFamilyName) + ulAliases;
  1064. MultiByteToWideChar(csi.ciACP, 0,
  1065. pNameStr2, cNameStr2Len,
  1066. (PWSTR)pby, wcNameStr2Len);
  1067. pby += wcNameStr2Len * sizeof (WCHAR);
  1068. //
  1069. // Terminate with two WCHAR nulls.
  1070. //
  1071. *((PWSTR)pby) = (WCHAR)'\0';
  1072. pby += sizeof (WCHAR);
  1073. *((PWSTR)pby) = (WCHAR)'\0';
  1074. pby += sizeof (WCHAR);
  1075. }
  1076. //
  1077. // Face name shares the family name/aliases for Win3.1 compatibility.
  1078. //
  1079. pifi->dpwszFaceName = pifi->dpwszFamilyName;
  1080. //
  1081. // Store style and unique names. Style name has to be available but
  1082. // unique name may not be available.
  1083. //
  1084. pifi->dpwszStyleName = pifi->dpwszFamilyName + (PTRDIFF)isi.nFamilyNameSize;
  1085. pby = (PBYTE)MK_PTR(pifi, dpwszStyleName);
  1086. MULTIBYTETOUNICODE((LPWSTR)pby, isi.nStyleNameSize, NULL, szStyleName, strlen(szStyleName));
  1087. if (isi.nUniqueNameSize)
  1088. {
  1089. pifi->dpwszUniqueName = pifi->dpwszStyleName + (PTRDIFF)isi.nStyleNameSize;
  1090. pby = (PBYTE)MK_PTR(pifi, dpwszUniqueName);
  1091. MULTIBYTETOUNICODE((LPWSTR)pby, isi.nUniqueNameSize, NULL, szUniqueID, strlen(szUniqueID));
  1092. }
  1093. else
  1094. {
  1095. pifi->dpwszUniqueName = pifi->dpwszStyleName + isi.nStyleNameSize - sizeof (WCHAR);
  1096. }
  1097. //
  1098. // Save Windows characterset.
  1099. //
  1100. pifi->jWinCharSet = (BYTE)jWinCharSet;
  1101. //
  1102. // Store the font's family type flags.
  1103. //
  1104. if (pFamilyInfo != NULL)
  1105. {
  1106. pifi->jWinPitchAndFamily = (BYTE) pFamilyInfo->FamilyKey.usValue & 0xff;
  1107. }
  1108. else
  1109. {
  1110. pifi->jWinPitchAndFamily = FF_SWISS;
  1111. }
  1112. //
  1113. // Set pitch flags.
  1114. //
  1115. if (bIsFixedPitch)
  1116. {
  1117. pifi->jWinPitchAndFamily |= FIXED_PITCH;
  1118. pifi->flInfo |= FM_INFO_OPTICALLY_FIXED_PITCH;
  1119. if (!bIsCJKFont)
  1120. pifi->flInfo |= FM_INFO_CONSTANT_WIDTH;
  1121. else
  1122. pifi->flInfo |= FM_INFO_DBCS_FIXED_PITCH;
  1123. }
  1124. else
  1125. {
  1126. pifi->jWinPitchAndFamily |= VARIABLE_PITCH;
  1127. }
  1128. //
  1129. // Get weight from AFM key.
  1130. //
  1131. pifi->usWinWeight = FW_NORMAL;
  1132. pifi->fsSelection = 0;
  1133. j = bIsCJKFont ? 1 : 0;
  1134. if ((pToken = FindAFMToken(pAFM, PS_WEIGHT_TOK)) != NULL)
  1135. for (i = 0; i < WeightKeyTbl[j].usNumEntries; i++)
  1136. {
  1137. if (!StrCmp(pToken, (PBYTE) (((PKEY) (WeightKeyTbl[j].pTbl))[i].pName)))
  1138. {
  1139. pifi->usWinWeight = (((PKEY) (WeightKeyTbl[j].pTbl))[i].usValue);
  1140. if (pifi->usWinWeight == FW_BOLD)
  1141. {
  1142. pifi->fsSelection = FM_SEL_BOLD;
  1143. }
  1144. break;
  1145. }
  1146. }
  1147. //
  1148. // Is this really how to set font selection flags?
  1149. // AFMtoPFM converter treats angle as a float, but etm.etmslant
  1150. // field is a short.
  1151. //
  1152. //
  1153. // Set Italic sel flag if necessary.
  1154. //
  1155. if ((pToken = FindAFMToken(pAFM, PS_ITALIC_TOK)) != NULL)
  1156. pNTM->etm.etmSlant = (SHORT)atoi(pToken);
  1157. if (pNTM->etm.etmSlant)
  1158. {
  1159. pifi->fsSelection |= FM_SEL_ITALIC;
  1160. }
  1161. #if 0
  1162. //
  1163. // DCR: so, what are we gonna do with this?
  1164. //
  1165. FSHORT fsSelection = 0;
  1166. //
  1167. // Excerpts from bodind's code. Not sure if we need this
  1168. // useful.
  1169. //
  1170. if (pjPFM[OFF_Underline])
  1171. fsSelection |= FM_SEL_UNDERSCORE;
  1172. if (pjPFM[OFF_StrikeOut])
  1173. fsSelection |= FM_SEL_STRIKEOUT;
  1174. if (READ_WORD(&pjPFM[OFF_Weight]) > FW_NORMAL)
  1175. fsSelection |= FM_SEL_BOLD;
  1176. #endif
  1177. pifi->fsType = FM_NO_EMBEDDING;
  1178. pifi->fwdUnitsPerEm = EM; // hardcoded for type 1 fonts
  1179. //
  1180. // Use FontBBox2 if found. Otherwise, use FontBBox. FontBBox2 is
  1181. // the bounding box values of the characters not the union of all
  1182. // the characters described in the AFM file but the characters
  1183. // actually used in a specific character set such as 90ms.
  1184. //
  1185. if (((pToken = FindAFMToken(pAFM, PS_FONT_BBOX2_TOK)) == NULL) &&
  1186. ((pToken = FindAFMToken(pAFM, PS_FONT_BBOX_TOK)) == NULL))
  1187. {
  1188. ERR(("makentf - afm2ntm: FontBBox not found\n"));
  1189. FREE_AFMTONTM_MEMORY;
  1190. return NULL;
  1191. }
  1192. //
  1193. // Save font bounding box.
  1194. //
  1195. PARSE_RECT(pToken, rcBBox);
  1196. sIntLeading = (SHORT) (rcBBox.top - rcBBox.bottom) - EM;
  1197. if (sIntLeading < 0)
  1198. sIntLeading = 0;
  1199. sAscent = (USHORT) rcBBox.top & 0xffff;
  1200. pifi->fwdWinAscender = sAscent;
  1201. //
  1202. // Poof! Magic Metrics...
  1203. //
  1204. sExternalLeading = 196;
  1205. // see pfm.c, win31 sources, this computation
  1206. // produces quantity that is >= |rcBBox.bottom|
  1207. pifi->fwdWinDescender = EM - sAscent + sIntLeading;
  1208. pifi->fwdMacAscender = sAscent;
  1209. pifi->fwdMacDescender = -pifi->fwdWinDescender;
  1210. pifi->fwdMacLineGap = (FWORD) sExternalLeading - sIntLeading;
  1211. if (pifi->fwdMacLineGap < 0)
  1212. pifi->fwdMacLineGap = 0;
  1213. pifi->fwdTypoAscender = pifi->fwdMacAscender;
  1214. pifi->fwdTypoDescender = pifi->fwdMacDescender;
  1215. pifi->fwdTypoLineGap = pifi->fwdMacLineGap;
  1216. if (pifi->fwdAveCharWidth > pifi->fwdMaxCharInc)
  1217. {
  1218. //
  1219. // fix the bug in the header if there is one,
  1220. // We do not want to change AveCharWidht, it is used for
  1221. // computing font xforms, Max is used for nothing as fas as I know.
  1222. //
  1223. pifi->fwdMaxCharInc = pifi->fwdAveCharWidth;
  1224. }
  1225. //
  1226. // Create EXTTEXTMETRICs. Poof! More magic.
  1227. //
  1228. pNTM->etm.etmSize = sizeof(EXTTEXTMETRIC);
  1229. pNTM->etm.etmCapHeight = EtmInfo.etmCapHeight;
  1230. pNTM->etm.etmXHeight = EtmInfo.etmXHeight;
  1231. pNTM->etm.etmLowerCaseAscent = EtmInfo.etmLowerCaseAscent;
  1232. pNTM->etm.etmLowerCaseDescent = EtmInfo.etmLowerCaseDescent;
  1233. pNTM->etm.etmPointSize = 12 * 20; /* Nominal point size = 12 */
  1234. pNTM->etm.etmOrientation = 0;
  1235. pNTM->etm.etmMasterHeight = 1000;
  1236. pNTM->etm.etmMinScale = 3;
  1237. pNTM->etm.etmMaxScale = 1000;
  1238. pNTM->etm.etmMasterUnits = 1000;
  1239. if ((pToken = FindAFMToken(pAFM, PS_UNDERLINE_POS_TOK)) != NULL)
  1240. pNTM->etm.etmUnderlineOffset = (SHORT)atoi(pToken);
  1241. if ((pToken = FindAFMToken(pAFM, PS_UNDERLINE_THICK_TOK)) != NULL)
  1242. pNTM->etm.etmUnderlineWidth = (SHORT)atoi(pToken);
  1243. pNTM->etm.etmSuperScript = -500;
  1244. pNTM->etm.etmSubScript = 250;
  1245. pNTM->etm.etmSuperScriptSize = 500;
  1246. pNTM->etm.etmSubScriptSize = 500;
  1247. pNTM->etm.etmDoubleUpperUnderlineOffset = pNTM->etm.etmUnderlineOffset / 2;
  1248. pNTM->etm.etmDoubleLowerUnderlineOffset = pNTM->etm.etmUnderlineOffset;
  1249. pNTM->etm.etmDoubleUpperUnderlineWidth = // same as LowerUnderlineWidth
  1250. pNTM->etm.etmDoubleLowerUnderlineWidth = pNTM->etm.etmUnderlineWidth / 2;
  1251. pNTM->etm.etmStrikeOutOffset = 500;
  1252. pNTM->etm.etmStrikeOutWidth = 50; // ATM sets it to 50 (also all PFMs have 50)
  1253. pNTM->etm.etmNKernPairs = (USHORT) ulKernPairs & 0xffff;
  1254. //
  1255. // No track kerning. This mimics the behavior of old AFM->PFM utility.
  1256. //
  1257. pNTM->etm.etmNKernTracks = 0;
  1258. //
  1259. // SuperScripts and Subscripts come from etm:
  1260. //
  1261. pifi->fwdSubscriptXSize = // same as YSize
  1262. pifi->fwdSubscriptYSize = pNTM->etm.etmSubScriptSize;
  1263. pifi->fwdSubscriptXOffset = 0;
  1264. pifi->fwdSubscriptYOffset = pNTM->etm.etmSubScript;
  1265. pifi->fwdSuperscriptXSize = // same as YSize
  1266. pifi->fwdSuperscriptYSize = pNTM->etm.etmSuperScriptSize;
  1267. pifi->fwdSuperscriptXOffset = 0;
  1268. pifi->fwdSuperscriptYOffset = pNTM->etm.etmSuperScript;
  1269. pifi->fwdUnderscoreSize = pNTM->etm.etmUnderlineWidth;
  1270. //
  1271. // fwdUnderscorePosition is typically negative - AFM may have negative value already
  1272. //
  1273. if (pNTM->etm.etmUnderlineOffset <0)
  1274. pifi->fwdUnderscorePosition = -pNTM->etm.etmUnderlineOffset;
  1275. else
  1276. pifi->fwdUnderscorePosition = pNTM->etm.etmUnderlineOffset;
  1277. // Make it compatible with ATM. Fix bug Adobe #211202
  1278. pifi->fwdUnderscorePosition = -(pifi->fwdUnderscorePosition -
  1279. pifi->fwdUnderscoreSize / 2);
  1280. pifi->fwdStrikeoutSize = pNTM->etm.etmStrikeOutWidth;
  1281. //
  1282. // This is what KentSe was using to position strikeout and it looked good [bodind]
  1283. // Instead we could have used etmStrikeoutOffset (usually equal to 500) which
  1284. // was too big.
  1285. //
  1286. // Make it compatible with ATM. Fix bug Adobe #211202
  1287. // pifi->fwdStrikeoutPosition = ((LONG)pNTM->etm.etmLowerCaseAscent / 2);
  1288. if (pNTM->etm.etmCapHeight != 0)
  1289. pifi->fwdStrikeoutPosition = (pNTM->etm.etmCapHeight - pifi->fwdUnderscoreSize) / 2;
  1290. else
  1291. pifi->fwdStrikeoutPosition = (pNTM->etm.etmXHeight - pifi->fwdUnderscoreSize) / 2;
  1292. pifi->fwdLowestPPEm = pNTM->etm.etmMinScale;
  1293. //
  1294. // Per bodind, Win 3.1 values for first, last, break and default char can
  1295. // be hardcoded.
  1296. //
  1297. pifi->chFirstChar = 0x20;
  1298. pifi->chLastChar = 0xff;
  1299. if (!bIsCJKFont)
  1300. {
  1301. pifi->chBreakChar = 0x20;
  1302. // The following line of code should work, however, there seems to be
  1303. // a bug in afm -> pfm conversion utility which makes
  1304. // DefaultChar == 0x20 instead of 149 - 20 (for bullet).
  1305. // pifi->chDefaultChar = pjPFM[OFF_DefaultChar] + pjPFM[OFF_FirstChar];
  1306. // Therefore, instead, I will use 149 which seems to work for all fonts.
  1307. pifi->chDefaultChar = 149;
  1308. }
  1309. else
  1310. {
  1311. pifi->chBreakChar =
  1312. pifi->chDefaultChar = 0x00;
  1313. }
  1314. //
  1315. // Get Unicode values for first and last char from GLYPHSETDATA. We
  1316. // should do this on a per GLYPHSETDATA basis rather than a per font
  1317. // basis, but the calculations are so simple just do it on the fly,
  1318. // rather than dragging first and last char around with the
  1319. // GLYPHSETDATA.
  1320. //
  1321. pGlyphRun = (PGLYPHRUN) MK_PTR(pGlyphSetData, dwRunOffset);
  1322. pifi->wcFirstChar = pGlyphRun->wcLow;
  1323. (ULONG_PTR) pGlyphRun += (pGlyphSetData->dwRunCount - 1) * sizeof(GLYPHRUN);
  1324. pifi->wcLastChar = pGlyphRun->wcLow + pGlyphRun->wGlyphCount - 1;
  1325. MultiByteToWideChar(csi.ciACP, 0,
  1326. &pifi->chDefaultChar, 1,
  1327. &pifi->wcDefaultChar, sizeof(WCHAR));
  1328. MultiByteToWideChar(csi.ciACP, 0,
  1329. &pifi->chBreakChar, 1,
  1330. &pifi->wcBreakChar, sizeof(WCHAR));
  1331. pifi->fwdCapHeight = pNTM->etm.etmCapHeight;
  1332. pifi->fwdXHeight = pNTM->etm.etmXHeight;
  1333. // All the fonts that this font driver will see are to be rendered left
  1334. // to right
  1335. pifi->ptlBaseline.x = 1;
  1336. pifi->ptlBaseline.y = 0;
  1337. pifi->ptlAspect.y = 300;
  1338. pifi->ptlAspect.x = 300;
  1339. // italic angle from etm.
  1340. pifi->lItalicAngle = pNTM->etm.etmSlant;
  1341. if (pifi->lItalicAngle == 0)
  1342. {
  1343. // The base class of font is not italicized,
  1344. pifi->ptlCaret.x = 0;
  1345. pifi->ptlCaret.y = 1;
  1346. }
  1347. else
  1348. {
  1349. // ptlCaret.x = -sin(lItalicAngle);
  1350. // ptlCaret.y = cos(lItalicAngle);
  1351. //!!! until I figure out the fast way to get sin and cos I cheat: [bodind]
  1352. pifi->ptlCaret.x = 1;
  1353. pifi->ptlCaret.y = 3;
  1354. }
  1355. //!!! The font box; This is bogus, this info is not in .pfm file!!! [bodind]
  1356. //!!! but I suppose that this info is not too useful anyway, it is nowhere
  1357. //!!! used in the engine or elsewhere in the ps driver.
  1358. //!!! left and right are bogus, top and bottom make sense.
  1359. pifi->rclFontBox.left = 0; // bogus
  1360. pifi->rclFontBox.top = (LONG) pifi->fwdTypoAscender; // correct
  1361. pifi->rclFontBox.right = (LONG) pifi->fwdMaxCharInc; // bogus
  1362. pifi->rclFontBox.bottom = (LONG) pifi->fwdTypoDescender; // correct
  1363. // achVendorId, unknown, don't bother figure it out from copyright msg
  1364. pifi->achVendId[0] = 'U';
  1365. pifi->achVendId[1] = 'n';
  1366. pifi->achVendId[2] = 'k';
  1367. pifi->achVendId[3] = 'n';
  1368. pifi->cKerningPairs = ulKernPairs;
  1369. // Panose
  1370. pifi->ulPanoseCulture = FM_PANOSE_CULTURE_LATIN;
  1371. ppanose = &(pifi->panose);
  1372. ppanose->bFamilyType = PAN_ANY;
  1373. ppanose->bSerifStyle =
  1374. ((pifi->jWinPitchAndFamily & 0xf0) == FF_SWISS) ?
  1375. PAN_SERIF_NORMAL_SANS : PAN_ANY;
  1376. ppanose->bWeight = (BYTE) WINWT_TO_PANWT(pifi->usWinWeight);
  1377. ppanose->bProportion = (pifi->jWinPitchAndFamily & FIXED_PITCH) ?
  1378. PAN_PROP_MONOSPACED : PAN_ANY;
  1379. ppanose->bContrast = PAN_ANY;
  1380. ppanose->bStrokeVariation = PAN_ANY;
  1381. ppanose->bArmStyle = PAN_ANY;
  1382. ppanose->bLetterform = PAN_ANY;
  1383. ppanose->bMidline = PAN_ANY;
  1384. ppanose->bXHeight = PAN_ANY;
  1385. // If the font is not italic or Not-Bold, the driver can simulate it
  1386. // Set the dpBold, dpItalic, and dpBoldItalic correctly, PPeng, 6-3-1997
  1387. // Depends on AFM, we need to set some of the sim structure:
  1388. // Normal - need dpBold, dpItalic, and dpBoldItalic
  1389. // Bold - need dpItalic
  1390. // Italic - need dpBoldItalic
  1391. // BoldItalic - Nothing
  1392. // Don't move code around !!
  1393. // At this point, bIsBold and bIsItalic should be set already
  1394. // Don't move code around !!
  1395. if (!bIsBold || !bIsItalic)
  1396. {
  1397. FONTSIM *pFontSim;
  1398. FONTDIFF *pFontDiff;
  1399. FONTDIFF FontDiff;
  1400. // Preset temporary FontDiff structure
  1401. FontDiff.jReserved1 = 0;
  1402. FontDiff.jReserved2 = 0;
  1403. FontDiff.jReserved3 = 0;
  1404. FontDiff.bWeight = pifi->panose.bWeight;
  1405. FontDiff.usWinWeight = pifi->usWinWeight;
  1406. FontDiff.fsSelection = pifi->fsSelection;
  1407. FontDiff.fwdAveCharWidth = pifi->fwdAveCharWidth;
  1408. FontDiff.fwdMaxCharInc = pifi->fwdMaxCharInc;
  1409. FontDiff.ptlCaret = pifi->ptlCaret;
  1410. // Initialize FONTSIM structure
  1411. pifi->dpFontSim = pifi->dpwszStyleName + (PTRDIFF)(isi.nStyleNameSize + isi.nUniqueNameSize);
  1412. pFontSim = (FONTSIM *) MK_PTR(pifi, dpFontSim);
  1413. pFontSim->dpBold = pFontSim->dpBoldItalic = pFontSim->dpItalic = 0;
  1414. // Notice the FontDiff data are arranged right after FontSim
  1415. // in the following order: dpBold, dpItalic, dpBoldItalic
  1416. if (!bIsBold)
  1417. {
  1418. // Right after FontSim.
  1419. pFontSim->dpBold = ALIGN4(sizeof(FONTSIM));
  1420. pFontDiff = (FONTDIFF *) MK_PTR(pFontSim, dpBold);
  1421. *pFontDiff = FontDiff;
  1422. pFontDiff->bWeight = PAN_WEIGHT_BOLD;
  1423. pFontDiff->fsSelection |= FM_SEL_BOLD;
  1424. pFontDiff->usWinWeight = FW_BOLD;
  1425. pFontDiff->fwdAveCharWidth += 1;
  1426. pFontDiff->fwdMaxCharInc += 1;
  1427. // if already Italic, CANNOT Un-italic it
  1428. if (bIsItalic)
  1429. {
  1430. pFontDiff->ptlCaret.x = 1;
  1431. pFontDiff->ptlCaret.y = 3;
  1432. }
  1433. else
  1434. {
  1435. pFontDiff->ptlCaret.x = 0;
  1436. pFontDiff->ptlCaret.y = 1;
  1437. }
  1438. }
  1439. if (!bIsItalic)
  1440. {
  1441. if (pFontSim->dpBold)
  1442. {
  1443. // Right after FontDiff for dpBold, or...
  1444. pFontSim->dpItalic = pFontSim->dpBold + ALIGN4(sizeof(FONTDIFF));
  1445. }
  1446. else
  1447. {
  1448. // ...right after FontSim.
  1449. pFontSim->dpItalic = ALIGN4(sizeof(FONTSIM));
  1450. }
  1451. pFontDiff = (FONTDIFF *) MK_PTR(pFontSim, dpItalic);
  1452. *pFontDiff = FontDiff;
  1453. pFontDiff->fsSelection |= FM_SEL_ITALIC;
  1454. // Italic angle is approximately 18 degree
  1455. pFontDiff->ptlCaret.x = 1;
  1456. pFontDiff->ptlCaret.y = 3;
  1457. }
  1458. // Make BoldItalic simulation if necessary - besides dpBold or dpItalic
  1459. if (!bIsItalic || !bIsBold)
  1460. {
  1461. if (pFontSim->dpItalic)
  1462. {
  1463. // Right after FontDiff for dpItalic, or...
  1464. pFontSim->dpBoldItalic = pFontSim->dpItalic + ALIGN4(sizeof(FONTDIFF));
  1465. }
  1466. else if (pFontSim->dpBold)
  1467. {
  1468. // ...right after FontDiff for dpBold if dpItalic is not set, or...
  1469. pFontSim->dpBoldItalic = pFontSim->dpBold + ALIGN4(sizeof(FONTDIFF));
  1470. }
  1471. else
  1472. {
  1473. // ...right after FontSim if none of other two is set.
  1474. pFontSim->dpBoldItalic = ALIGN4(sizeof(FONTSIM));
  1475. }
  1476. pFontDiff = (FONTDIFF *) MK_PTR(pFontSim, dpBoldItalic);
  1477. *pFontDiff = FontDiff;
  1478. pFontDiff->bWeight = PAN_WEIGHT_BOLD;
  1479. pFontDiff->fsSelection |= (FM_SEL_BOLD | FM_SEL_ITALIC);
  1480. pFontDiff->usWinWeight = FW_BOLD;
  1481. pFontDiff->fwdAveCharWidth += 1;
  1482. pFontDiff->fwdMaxCharInc += 1;
  1483. // Italic angle is approximately 18 degree
  1484. pFontDiff->ptlCaret.x = 1;
  1485. pFontDiff->ptlCaret.y = 3;
  1486. }
  1487. }
  1488. else
  1489. pifi->dpFontSim = 0;
  1490. if (multiCharSet > 1)
  1491. {
  1492. PBYTE pDpCharSet;
  1493. pifi->dpCharSets = ulIFISize - ALIGN4(NUM_DPCHARSET);
  1494. pDpCharSet = (BYTE *)MK_PTR(pifi, dpCharSets);
  1495. // The order of this check is important since jWinCharSet
  1496. // should match the first dpCharSets array if it exists.
  1497. i = 0;
  1498. if (CSET_SUPPORT(*pCharSet, CS_ANSI))
  1499. pDpCharSet[i++] = ANSI_CHARSET;
  1500. if (CSET_SUPPORT(*pCharSet, CS_EASTEUROPE))
  1501. pDpCharSet[i++] = EASTEUROPE_CHARSET;
  1502. if (CSET_SUPPORT(*pCharSet, CS_RUSSIAN))
  1503. pDpCharSet[i++] = RUSSIAN_CHARSET;
  1504. if (CSET_SUPPORT(*pCharSet, CS_GREEK))
  1505. pDpCharSet[i++] = GREEK_CHARSET;
  1506. if (CSET_SUPPORT(*pCharSet, CS_TURKISH))
  1507. pDpCharSet[i++] = TURKISH_CHARSET;
  1508. if (CSET_SUPPORT(*pCharSet, CS_HEBREW))
  1509. pDpCharSet[i++] = HEBREW_CHARSET;
  1510. if (CSET_SUPPORT(*pCharSet, CS_ARABIC))
  1511. pDpCharSet[i++] = ARABIC_CHARSET;
  1512. if (CSET_SUPPORT(*pCharSet, CS_BALTIC))
  1513. pDpCharSet[i++] = BALTIC_CHARSET;
  1514. if (CSET_SUPPORT(*pCharSet, CS_SYMBOL))
  1515. pDpCharSet[i++] = SYMBOL_CHARSET;
  1516. while (i < 16)
  1517. pDpCharSet[i++] = DEFAULT_CHARSET;
  1518. }
  1519. else
  1520. pifi->dpCharSets = 0; // no multiple charsets in ps fonts
  1521. //
  1522. // Copy the first IFIMETRICS to the secondly if necessary, and then
  1523. // switch English and localized font menu names.
  1524. //
  1525. if (bIsCJKFont)
  1526. {
  1527. ASSERT(pifi2 != NULL);
  1528. memcpy(pifi2, pifi, isi.nTotalSize);
  1529. pifi2->flInfo &= ~FM_INFO_FAMILY_EQUIV;
  1530. ulAliases = cjGetFamilyAliases(pifi2, pNameStr2, csi.ciACP);
  1531. if (pifi2->flInfo & FM_INFO_FAMILY_EQUIV)
  1532. ulAliases -= sizeof (WCHAR);
  1533. pifi2->flInfo |= FM_INFO_FAMILY_EQUIV;
  1534. pby = (PBYTE)MK_PTR(pifi2, dpwszFamilyName) + ulAliases;
  1535. MultiByteToWideChar(csi.ciACP, 0,
  1536. pNameStr, cNameStrLen,
  1537. (PWSTR)pby, wcNameStrLen);
  1538. pby += wcNameStrLen * sizeof (WCHAR);
  1539. //
  1540. // Terminate with two WCHAR nulls.
  1541. //
  1542. *((PWSTR)pby) = (WCHAR)'\0';
  1543. pby += sizeof (WCHAR);
  1544. *((PWSTR)pby) = (WCHAR)'\0';
  1545. pby += sizeof (WCHAR);
  1546. //
  1547. // Face name shares the family name/aliases for Win3.1 compatibility.
  1548. //
  1549. pifi2->dpwszFaceName = pifi2->dpwszFamilyName;
  1550. #if 1
  1551. //
  1552. // We now support style and unique names too.
  1553. //
  1554. pifi2->dpwszStyleName = pifi2->dpwszFamilyName + (PTRDIFF)isi.nFamilyNameSize;
  1555. pby = (PBYTE)MK_PTR(pifi2, dpwszStyleName);
  1556. MULTIBYTETOUNICODE((LPWSTR)pby, isi.nStyleNameSize, NULL, szStyleName, strlen(szStyleName));
  1557. if (isi.nUniqueNameSize)
  1558. {
  1559. pifi2->dpwszUniqueName = pifi2->dpwszStyleName + (PTRDIFF)isi.nStyleNameSize;
  1560. pby = (PBYTE)MK_PTR(pifi2, dpwszUniqueName);
  1561. MULTIBYTETOUNICODE((LPWSTR)pby, isi.nUniqueNameSize, NULL, szUniqueID, strlen(szUniqueID));
  1562. }
  1563. else
  1564. {
  1565. pifi2->dpwszUniqueName = pifi2->dpwszStyleName + isi.nStyleNameSize - sizeof (WCHAR);
  1566. }
  1567. #else
  1568. //
  1569. // These names don't exist, so point to the NULL char.
  1570. // This is too for Win3.1 compatibility.
  1571. //
  1572. pifi2->dpwszStyleName = pifi2->dpwszFamilyName + ulAliases - sizeof (WCHAR);
  1573. pifi2->dpwszUniqueName = pifi2->dpwszStyleName;
  1574. #endif
  1575. #ifdef FORCE_2NDIFIMETRICS_FIRST
  1576. {
  1577. DWORD dw = pNTM->dwIFIMetricsOffset;
  1578. pNTM->dwIFIMetricsOffset = pNTM->dwIFIMetricsOffset2;
  1579. pNTM->dwIFIMetricsOffset2 = dw;
  1580. }
  1581. #endif
  1582. }
  1583. if (bVerbose)
  1584. {
  1585. printf("NTM:dwFontNameOffset:%s\n", (PSZ)MK_PTR(pNTM, dwFontNameOffset));
  1586. printf("NTM:dwDisplayNameOffset:%s\n", (PSZ)MK_PTR(pNTM, dwDisplayNameOffset));
  1587. printf("NTM:dwGlyphSetNameOffset:%s\n", (PSZ)MK_PTR(pNTM, dwGlyphSetNameOffset));
  1588. printf("NTM:dwGlyphCount:%ld\n", pNTM->dwGlyphCount);
  1589. printf("NTM:dwCharWidthCount:%ld\n", pNTM->dwCharWidthCount);
  1590. printf("NTM:dwDefaultCharWidth:%ld\n", pNTM->dwDefaultCharWidth);
  1591. printf("NTM:dwCharSet:%ld\n", pNTM->dwCharSet);
  1592. printf("NTM:dwCodePage:%ld\n", pNTM->dwCodePage);
  1593. pifi = (PIFIMETRICS)MK_PTR(pNTM, dwIFIMetricsOffset);
  1594. printf("IFIMETRICS:dpwszFamilyName:%S\n", (LPWSTR)MK_PTR(pifi, dpwszFamilyName));
  1595. printf("IFIMETRICS:dpwszStyleName:%S\n", (LPWSTR)MK_PTR(pifi, dpwszStyleName));
  1596. printf("IFIMETRICS:dpwszFaceName:%S\n", (LPWSTR)MK_PTR(pifi, dpwszFaceName));
  1597. printf("IFIMETRICS:dpwszUniqueName:%S\n", (LPWSTR)MK_PTR(pifi, dpwszUniqueName));
  1598. printf("IFIMETRICS:jWinCharSet:%d\n", (WORD)pifi->jWinCharSet);
  1599. printf("IFIMETRICS:jWinPitchAndFamily:%02X\n", (WORD)pifi->jWinPitchAndFamily);
  1600. printf("IFIMETRICS:usWinWeight:%d\n", (int)pifi->usWinWeight);
  1601. printf("IFIMETRICS:flInfo:%08lX\n", pifi->flInfo);
  1602. printf("IFIMETRICS:fsSelection:%04X\n", (WORD)pifi->fsSelection);
  1603. printf("IFIMETRICS:fsType:%04X\n", (WORD)pifi->fsType);
  1604. printf("IFIMETRICS:fwdUnitsPerEm:%d\n", (int)pifi->fwdUnitsPerEm);
  1605. printf("IFIMETRICS:fwdLowestPPEm:%d\n", (int)pifi->fwdLowestPPEm);
  1606. printf("IFIMETRICS:fwdWinAscender:%d\n", (int)pifi->fwdWinAscender);
  1607. printf("IFIMETRICS:fwdWinDescender:%d\n", (int)pifi->fwdWinDescender);
  1608. printf("IFIMETRICS:fwdMacAscender:%d\n", (int)pifi->fwdMacAscender);
  1609. printf("IFIMETRICS:fwdMacDescender:%d\n", (int)pifi->fwdMacDescender);
  1610. printf("IFIMETRICS:fwdMacLineGap:%d\n", (int)pifi->fwdMacLineGap);
  1611. printf("IFIMETRICS:fwdTypoAscender:%d\n", (int)pifi->fwdTypoAscender);
  1612. printf("IFIMETRICS:fwdTypoDescender:%d\n", (int)pifi->fwdTypoDescender);
  1613. printf("IFIMETRICS:fwdTypoLineGap:%d\n", (int)pifi->fwdTypoLineGap);
  1614. printf("IFIMETRICS:fwdAveCharWidth:%d\n", (int)pifi->fwdAveCharWidth);
  1615. printf("IFIMETRICS:fwdMaxCharInc:%d\n", (int)pifi->fwdMaxCharInc);
  1616. printf("IFIMETRICS:fwdCapHeight:%d\n", (int)pifi->fwdCapHeight);
  1617. printf("IFIMETRICS:fwdXHeight:%d\n", (int)pifi->fwdXHeight);
  1618. printf("IFIMETRICS:fwdSubscriptXSize:%d\n", (int)pifi->fwdSubscriptXSize);
  1619. printf("IFIMETRICS:fwdSubscriptYSize:%d\n", (int)pifi->fwdSubscriptYSize);
  1620. printf("IFIMETRICS:fwdSubscriptXOffset:%d\n", (int)pifi->fwdSubscriptXOffset);
  1621. printf("IFIMETRICS:fwdSubscriptYOffset:%d\n", (int)pifi->fwdSubscriptYOffset);
  1622. printf("IFIMETRICS:fwdSuperscriptXSize:%d\n", (int)pifi->fwdSuperscriptXSize);
  1623. printf("IFIMETRICS:fwdSuperscriptYSize:%d\n", (int)pifi->fwdSuperscriptYSize);
  1624. printf("IFIMETRICS:fwdSuperscriptXOffset:%d\n", (int)pifi->fwdSuperscriptXOffset);
  1625. printf("IFIMETRICS:fwdSuperscriptYOffset:%d\n", (int)pifi->fwdSuperscriptYOffset);
  1626. printf("IFIMETRICS:fwdUnderscoreSize:%d\n", (int)pifi->fwdUnderscoreSize);
  1627. printf("IFIMETRICS:fwdUnderscorePosition:%d\n", (int)pifi->fwdUnderscorePosition);
  1628. printf("IFIMETRICS:fwdStrikeoutSize:%d\n", (int)pifi->fwdStrikeoutSize);
  1629. printf("IFIMETRICS:fwdStrikeoutPosition:%d\n", (int)pifi->fwdStrikeoutPosition);
  1630. printf("IFIMETRICS:chFirstChar:%02X\n", (WORD)pifi->chFirstChar);
  1631. printf("IFIMETRICS:chLastChar:%02X\n", (WORD)pifi->chLastChar);
  1632. printf("IFIMETRICS:chDefaultChar:%02X\n", (WORD)pifi->chDefaultChar);
  1633. printf("IFIMETRICS:chBreakChar:%02X\n", (WORD)pifi->chBreakChar);
  1634. printf("IFIMETRICS:ptlBaseline:(%ld, %ld)\n", pifi->ptlBaseline.x, pifi->ptlBaseline.y);
  1635. printf("IFIMETRICS:ptlAspect:(%ld, %ld)\n", pifi->ptlAspect.x, pifi->ptlAspect.y);
  1636. printf("IFIMETRICS:ptlCaret:(%ld, %ld)\n", pifi->ptlCaret.x, pifi->ptlCaret.y);
  1637. printf("IFIMETRICS:rclFontBox:(%ld, %ld, %ld, %ld)\n",
  1638. pifi->rclFontBox.left, pifi->rclFontBox.top,
  1639. pifi->rclFontBox.right, pifi->rclFontBox.bottom);
  1640. if (pifi->dpFontSim)
  1641. {
  1642. FONTSIM* pFontSim = (FONTSIM*)MK_PTR(pifi, dpFontSim);
  1643. if (pFontSim->dpBold)
  1644. printf("FONTSIM:Bold\n");
  1645. if (pFontSim->dpItalic)
  1646. printf("FONTSIM:Italic\n");
  1647. if (pFontSim->dpBoldItalic)
  1648. printf("FONTSIM:BoldItalic\n");
  1649. }
  1650. printf("GLYPHSETDATA:dwFlags:%08X\n", pGlyphSetData->dwFlags);
  1651. printf("GLYPHSETDATA:dwGlyphSetNameOffset:%s\n",
  1652. (PSZ)MK_PTR(pGlyphSetData, dwGlyphSetNameOffset));
  1653. printf("GLYPHSETDATA:dwGlyphCount:%ld\n", pGlyphSetData->dwGlyphCount);
  1654. printf("GLYPHSETDATA:dwRunCount:%ld\n", pGlyphSetData->dwRunCount);
  1655. printf("GLYPHSETDATA:dwCodePageCount:%ld\n", pGlyphSetData->dwCodePageCount);
  1656. {
  1657. DWORD dw;
  1658. PCODEPAGEINFO pcpi = (PCODEPAGEINFO)MK_PTR(pGlyphSetData, dwCodePageOffset);
  1659. for (dw = 1; dw <= pGlyphSetData->dwCodePageCount; dw++)
  1660. {
  1661. printf("CODEPAGEINFO#%ld:dwCodePage:%ld\n", dw, pcpi->dwCodePage);
  1662. printf("CODEPAGEINFO#%ld:dwWinCharset:%ld\n", dw, pcpi->dwWinCharset);
  1663. printf("CODEPAGEINFO#%ld:dwEncodingNameOffset:%s\n",
  1664. dw, (PSZ)MK_PTR(pcpi, dwEncodingNameOffset));
  1665. pcpi++;
  1666. }
  1667. }
  1668. printf("\n");
  1669. }
  1670. //////////////////////////////////////////////////////////////////
  1671. //
  1672. // Free strings and char metrics info.
  1673. //
  1674. //////////////////////////////////////////////////////////////////
  1675. FREE_AFMTONTM_MEMORY;
  1676. return(pNTM);
  1677. }
  1678. PBYTE
  1679. FindAFMToken(
  1680. PBYTE pAFM,
  1681. PSZ pszToken
  1682. )
  1683. /*++
  1684. Routine Description:
  1685. Finds an AFM token in a memory mapped AFM file stream.
  1686. Arguments:
  1687. pAFM - pointer to memory mapped AFM file.
  1688. pszToken - pointer to null-term string containing token to search for
  1689. Return Value:
  1690. NULL => error
  1691. otherwise => ptr to token's value. This is defined as the first non-blank
  1692. char after the token name. If EOL(FindAfmToken(pAFM, pszToken)) then
  1693. pszToken was found but it has no value (e.g. EndCharMetrics).
  1694. --*/
  1695. {
  1696. PBYTE pCurToken;
  1697. int i;
  1698. VERBOSE(("Entering FindAFMToken... %s\n", pszToken));
  1699. while (TRUE)
  1700. {
  1701. PARSE_TOKEN(pAFM, pCurToken);
  1702. if (!(StrCmp(pCurToken, PS_COMMENT_TOK)))
  1703. {
  1704. NEXT_LINE(pAFM);
  1705. }
  1706. else
  1707. {
  1708. for (i = 0; i < MAX_TOKENS; i++)
  1709. {
  1710. if (!(StrCmp(pCurToken, pszToken)))
  1711. {
  1712. return(pAFM);
  1713. }
  1714. else if (!(StrCmp(pCurToken, PS_EOF_TOK)))
  1715. {
  1716. return NULL;
  1717. }
  1718. }
  1719. NEXT_TOKEN(pAFM);
  1720. }
  1721. }
  1722. return NULL;
  1723. }
  1724. CHSETSUPPORT
  1725. GetAFMCharSetSupport(
  1726. PBYTE pAFM,
  1727. CHSETSUPPORT *pGlyphSet
  1728. )
  1729. /*++
  1730. Routine Description:
  1731. Given a ptr to a memory mapped AFM, determine which Windows charset(s)
  1732. it supports.
  1733. Arguments:
  1734. pAFMetrx - pointer to CharMetrics in a memory mapped AFM file.
  1735. Return Value:
  1736. Contains bit fields which indicate which csets are supported. Use
  1737. CS_SUP(CS_xxx) macro to determine if a particular cset is supported.
  1738. --*/
  1739. {
  1740. PBYTE pToken;
  1741. USHORT i, chCnt;
  1742. CHSETSUPPORT flCsetSupport;
  1743. PBYTE pAFMMetrx;
  1744. isSymbolCharSet = FALSE;
  1745. *pGlyphSet = CS_NOCHARSET;
  1746. //
  1747. // Check to see if this is a CJK font.
  1748. //
  1749. if ((flCsetSupport = IsCJKFont(pAFM)))
  1750. {
  1751. return(flCsetSupport);
  1752. }
  1753. pToken = pAFMCharacterSetString;
  1754. if (pToken != NULL)
  1755. {
  1756. if (StrCmp(pToken, PS_STANDARD_CHARSET_TOK) == 0)
  1757. *pGlyphSet = CS_228;
  1758. else
  1759. *pGlyphSet = CS_314;
  1760. }
  1761. else
  1762. *pGlyphSet = CS_228;
  1763. //
  1764. // Check to see if a EncodingScheme token in the AFM file. If so, check
  1765. // if this is a standard encoding font or a Pi (Symbol) font.
  1766. //
  1767. if ((pToken = FindAFMToken(pAFM, PS_ENCODING_TOK)) != NULL)
  1768. {
  1769. if (StrCmp(pToken, PS_STANDARD_ENCODING) == 0)
  1770. {
  1771. return(CSUP(CS_ANSI));
  1772. }
  1773. }
  1774. //
  1775. // Find the beginning of the char metrics.
  1776. //
  1777. pAFMMetrx = FindAFMToken(pAFM, PS_CH_METRICS_TOK);
  1778. if (pAFMMetrx == NULL) // Fixed bug 354007
  1779. {
  1780. *pGlyphSet = CS_NOCHARSET;
  1781. ERR(("makentf - invalid StartCharMetrics\n"));
  1782. return(CS_NOCHARSET);
  1783. }
  1784. //
  1785. // Current pos should be the character count field.
  1786. //
  1787. for (i = 0; i < StrLen(pAFMMetrx); i++)
  1788. {
  1789. if (!IS_NUM(&pAFMMetrx[i]))
  1790. {
  1791. *pGlyphSet = CS_NOCHARSET;
  1792. ERR(("makentf - invalid StartCharMetrics\n"));
  1793. return(CS_NOCHARSET);
  1794. }
  1795. }
  1796. chCnt = (USHORT)atoi(pAFMMetrx);
  1797. (ULONG_PTR) pAFMMetrx += i;
  1798. //
  1799. // Process each char.
  1800. //
  1801. flCsetSupport = 0;
  1802. i = 0;
  1803. do
  1804. {
  1805. PARSE_TOKEN(pAFMMetrx, pToken);
  1806. if (StrCmp(pToken, PS_CH_NAME_TOK) == 0)
  1807. {
  1808. if (StrCmp(pAFMMetrx, PS_CH_NAME_EASTEUROPE) == 0)
  1809. flCsetSupport |= CSUP(CS_EASTEUROPE);
  1810. else if (StrCmp(pAFMMetrx, PS_CH_NAME_RUSSIAN) == 0)
  1811. flCsetSupport |= CSUP(CS_RUSSIAN);
  1812. else if (StrCmp(pAFMMetrx, PS_CH_NAME_ANSI) == 0)
  1813. flCsetSupport |= CSUP(CS_ANSI);
  1814. else if (StrCmp(pAFMMetrx, PS_CH_NAME_GREEK) == 0)
  1815. flCsetSupport |= CSUP(CS_GREEK);
  1816. else if (StrCmp(pAFMMetrx, PS_CH_NAME_TURKISH) == 0)
  1817. flCsetSupport |= CSUP(CS_TURKISH);
  1818. else if (StrCmp(pAFMMetrx, PS_CH_NAME_HEBREW) == 0)
  1819. flCsetSupport |= CSUP(CS_HEBREW);
  1820. else if (StrCmp(pAFMMetrx, PS_CH_NAME_ARABIC) == 0)
  1821. flCsetSupport |= CSUP(CS_ARABIC);
  1822. else if (StrCmp(pAFMMetrx, PS_CH_NAME_BALTIC) == 0)
  1823. flCsetSupport |= CSUP(CS_BALTIC);
  1824. i++;
  1825. }
  1826. else if (StrCmp(pToken, PS_EOF_TOK) == 0)
  1827. {
  1828. break;
  1829. }
  1830. NEXT_TOKEN(pAFMMetrx);
  1831. } while (i < chCnt);
  1832. //
  1833. // Assume symbol if none of the other char set is supported.
  1834. //
  1835. if (flCsetSupport == 0)
  1836. {
  1837. *pGlyphSet = CS_NOCHARSET;
  1838. flCsetSupport = CSUP(CS_SYMBOL);
  1839. isSymbolCharSet = TRUE;
  1840. }
  1841. return flCsetSupport;
  1842. }
  1843. int __cdecl
  1844. StrCmp(
  1845. const VOID *str1,
  1846. const VOID *str2
  1847. )
  1848. /*++
  1849. Routine Description:
  1850. Compare two strings which are terminated by either a null char or a
  1851. space.
  1852. Arguments:
  1853. str1, str2 - Strings to compare.
  1854. Return Value:
  1855. -1 => str1 < str2
  1856. 1 => str1 > str2
  1857. 0 => str1 = str2
  1858. --*/
  1859. {
  1860. PBYTE s1 = (PBYTE) str1, s2 = (PBYTE) str2;
  1861. // Error case, just return less then.
  1862. if ((s1 == NULL) || (s2 == NULL))
  1863. return(-1);
  1864. while (!IS_WHTSPACE(s1) && !IS_WHTSPACE(s2))
  1865. {
  1866. if (*s1 < *s2)
  1867. {
  1868. return(-1);
  1869. }
  1870. else if (*s1 > *s2)
  1871. {
  1872. return(1);
  1873. }
  1874. s1++;
  1875. s2++;
  1876. }
  1877. //
  1878. // Strings must be same length to be an exact match.
  1879. //
  1880. if (IS_WHTSPACE(s1) && IS_WHTSPACE(s2))
  1881. {
  1882. return(0);
  1883. }
  1884. else if (IS_WHTSPACE(s1))
  1885. // else if ((*s1 == ' ') || (*s1 == '\0'))
  1886. {
  1887. //
  1888. // s1 is shorter, so is lower in collating sequence than s2.
  1889. //
  1890. return(-1);
  1891. }
  1892. else
  1893. //
  1894. // s2 is shorter, so is lower in collating sequence than s1.
  1895. //
  1896. return(1);
  1897. }
  1898. size_t
  1899. StrLen(
  1900. PBYTE pString
  1901. )
  1902. {
  1903. ULONG i;
  1904. //
  1905. // Scan for next space, ';' token seperator, or end of line.
  1906. //
  1907. for (i = 0; !EOL(&pString[i]); i++)
  1908. if(pString[i] == ';' || pString[i] == ' ')
  1909. break;
  1910. return(i);
  1911. }
  1912. int
  1913. AFM2NTMStrCpy(
  1914. const VOID *str1,
  1915. size_t cchDest,
  1916. const VOID *str2
  1917. )
  1918. /*++
  1919. Routine Description:
  1920. Copies str2 to str1. Strings may be terminated by either a null char or a
  1921. space.
  1922. Arguments:
  1923. str2 - source string
  1924. str1 - dest string
  1925. cchDest - size (in chars) of the dest buffer
  1926. Return Value:
  1927. Number of bychars copied
  1928. --*/
  1929. {
  1930. PBYTE s1 = (PBYTE) str1, s2 = (PBYTE) str2;
  1931. ULONG n = 0;
  1932. if (cchDest > 0)
  1933. {
  1934. while (!IS_WHTSPACE(&s2[n]) && (cchDest > 0))
  1935. {
  1936. s1[n] = s2[n++];
  1937. cchDest--;
  1938. }
  1939. if (cchDest == 0)
  1940. {
  1941. //
  1942. // In this case n must be the original cchDest
  1943. // value, so we have to truncate the dest string.
  1944. //
  1945. n--;
  1946. }
  1947. s1[n] = '\0';
  1948. }
  1949. return(n);
  1950. }
  1951. static int __cdecl
  1952. StrPos(
  1953. const PBYTE str1,
  1954. CHAR c
  1955. )
  1956. /*++
  1957. Routine Description:
  1958. Retuns index of char c in str1. String may be terminated by either a
  1959. CR/LF, or a ':'.
  1960. Arguments:
  1961. str1 - string to search
  1962. c - search char
  1963. Return Value:
  1964. Index of c in str1, or -1 if not found
  1965. --*/
  1966. {
  1967. ULONG i = 0;
  1968. while (!EOL(&str1[i]))
  1969. {
  1970. if (str1[i++] == c)
  1971. return(i - 1);
  1972. }
  1973. return(-1);
  1974. }
  1975. int __cdecl
  1976. CmpUniCodePts(
  1977. const VOID *p1,
  1978. const VOID *p2
  1979. )
  1980. /*++
  1981. Routine Description:
  1982. Compares the Unicode char code field of two UPSCODEPT structs.
  1983. Arguments:
  1984. p1, p2 - Strings to compare.
  1985. Return Value:
  1986. -1 => p1 < p2
  1987. 1 => p1 > p2
  1988. 0 => p1 = p2
  1989. --*/
  1990. {
  1991. PUPSCODEPT ptr1 = (PUPSCODEPT) p1, ptr2 = (PUPSCODEPT) p2;
  1992. //
  1993. // Compare Unicode code point fields.
  1994. //
  1995. if (ptr1->wcUnicodeid > ptr2->wcUnicodeid)
  1996. return(1);
  1997. else if (ptr1->wcUnicodeid < ptr2->wcUnicodeid)
  1998. return(-1);
  1999. else
  2000. return(0);
  2001. }
  2002. static int __cdecl
  2003. CmpUnicodePsNames(
  2004. const VOID *p1,
  2005. const VOID *p2
  2006. )
  2007. /*++
  2008. Routine Description:
  2009. Compares two strings. This routine is meant to be used only for looking
  2010. up a char name key in an array of UPSCODEPT structs.
  2011. Arguments:
  2012. p1 - a null or whitespace terminated string.
  2013. p2 - points to a UPSCODEPT struct.
  2014. Return Value:
  2015. -1 => p1 < p2
  2016. 1 => p1 > p2
  2017. 0 => p1 = p2
  2018. --*/
  2019. {
  2020. PBYTE ptr1 = (PBYTE) p1;
  2021. PUPSCODEPT ptr2 = (PUPSCODEPT) p2;
  2022. //
  2023. // Compare name fields.
  2024. //
  2025. return (StrCmp(ptr1, ptr2->pPsName));
  2026. }
  2027. static int __cdecl
  2028. CmpPsChars(
  2029. const VOID *p1,
  2030. const VOID *p2
  2031. )
  2032. /*++
  2033. Routine Description:
  2034. Compares a null or space terminated string to the pPsName string field
  2035. of a PSCHARMETRICS struct.
  2036. Arguments:
  2037. p1 - a null or whitespace terminated string.
  2038. p2 - points to a PSCHARMETRICS struct.
  2039. Return Value:
  2040. -1 => p1 < p2
  2041. 1 => p1 > p2
  2042. 0 => p1 = p2
  2043. --*/
  2044. {
  2045. PBYTE ptr1 = (PBYTE) p1;
  2046. PPSCHARMETRICS ptr2 = (PPSCHARMETRICS) p2;
  2047. //
  2048. // Compare name fields.
  2049. //
  2050. return (StrCmp(ptr1, ptr2->pPsName));
  2051. }
  2052. static int __cdecl
  2053. CmpPsNameWinCpt(
  2054. const VOID *p1,
  2055. const VOID *p2
  2056. )
  2057. /*++
  2058. Routine Description:
  2059. Compares a null or space terminated string to the pPsName string field
  2060. of a WINCPT struct.
  2061. Arguments:
  2062. p1 - a null or whitespace terminated string.
  2063. p2 - points to a WINCPT struct.
  2064. Return Value:
  2065. -1 => p1 < p2
  2066. 1 => p1 > p2
  2067. 0 => p1 = p2
  2068. --*/
  2069. {
  2070. PBYTE ptr1 = (PBYTE) p1;
  2071. PWINCPT ptr2 = (PWINCPT) p2;
  2072. //
  2073. // Compare name fields.
  2074. //
  2075. return(StrCmp(ptr1, ptr2->pPsName));
  2076. }
  2077. static int __cdecl
  2078. CmpKernPairs(
  2079. const VOID *p1,
  2080. const VOID *p2
  2081. )
  2082. /*++
  2083. Routine Description:
  2084. Compares 2 FD_KERNINGPAIR structs according to a key = wcSecond << 16 +
  2085. wcFirst.
  2086. Arguments:
  2087. p1, p2 - ptrs to FD_KERNINGPAIRS to compare.
  2088. Return Value:
  2089. -1 => p1 < p2
  2090. 1 => p1 > p2
  2091. 0 => p1 = p2
  2092. --*/
  2093. {
  2094. FD_KERNINGPAIR *ptr1 = (FD_KERNINGPAIR *) p1;
  2095. FD_KERNINGPAIR *ptr2 = (FD_KERNINGPAIR *) p2;
  2096. ULONG key1, key2;
  2097. //
  2098. // Compute key for each kern pair.
  2099. //
  2100. key1 = (ptr1->wcSecond << 16) + ptr1->wcFirst;
  2101. key2 = (ptr2->wcSecond << 16) + ptr2->wcFirst;
  2102. if (key1 > key2)
  2103. {
  2104. return(1);
  2105. }
  2106. else if (key2 > key1)
  2107. {
  2108. return(-1);
  2109. }
  2110. else
  2111. {
  2112. return(0);
  2113. }
  2114. }
  2115. int __cdecl
  2116. CmpGlyphRuns(
  2117. const VOID *p1,
  2118. const VOID *p2
  2119. )
  2120. /*++
  2121. Routine Description:
  2122. Compares the starting Unicode point of two GLYPHRUN structs.
  2123. Arguments:
  2124. p1, p2 - GLYPHRUNs to compare.
  2125. Return Value:
  2126. -1 => p1 < p2
  2127. 1 => p1 > p2
  2128. 0 => p1 = p2
  2129. --*/
  2130. {
  2131. PGLYPHRUN ptr1 = (PGLYPHRUN) p1, ptr2 = (PGLYPHRUN) p2;
  2132. //
  2133. // Compare Unicode code point fields.
  2134. //
  2135. if (ptr1->wcLow > ptr2->wcLow)
  2136. return(1);
  2137. else if (ptr1->wcLow < ptr2->wcLow)
  2138. return(-1);
  2139. else
  2140. return(0);
  2141. }
  2142. ULONG
  2143. CreateGlyphSets(
  2144. PGLYPHSETDATA *pGlyphSet,
  2145. PWINCODEPAGE pWinCodePage,
  2146. PULONG *pUniPs
  2147. )
  2148. /*++
  2149. Routine Description:
  2150. Create a GLYPHSETDATA data structure, which maps Unicode pts to Windows
  2151. codepage/codepoints.
  2152. Arguments:
  2153. pGlyphSet - A PGLYPHSETDATA pointer which upon successful
  2154. completion contains the address of the newly allocated GLYPHSETDATA
  2155. struct.
  2156. pWinCodePage - a pointer to a windows code page info struct
  2157. used to create the GLYPHSETDATA struct.
  2158. pUniPs - Upon successful completion, -> a table which maps 0-based Glyph
  2159. Indices of chars in the GLYPHRUNS of the GLYPHSETDATA struct for this
  2160. charset to indices into the UnicodetoPs structure which maps Unicode
  2161. points to PS char information.
  2162. Return Value:
  2163. NULL => error
  2164. Otherwise total size of all GLYPHSETDATAs and related structs which are
  2165. created.
  2166. --*/
  2167. {
  2168. int i, j;
  2169. ULONG c;
  2170. int cRuns;
  2171. int cChars;
  2172. int cCharRun;
  2173. WCHAR wcLast;
  2174. WCHAR wcRunStrt;
  2175. PGLYPHSETDATA pGlyphSetData;
  2176. PGLYPHRUN pGlyphRuns;
  2177. ULONG ulSize;
  2178. PVOID pMapTable;
  2179. PWINCPT pWinCpt;
  2180. PCODEPAGEINFO pCodePageInfo;
  2181. BOOLEAN bFound, bIsPiFont;
  2182. DWORD dwEncodingNameOffset;
  2183. DWORD dwGSNameSize, dwCodePageInfoSize, dwCPIGSNameSize, dwGlyphRunSize;
  2184. BOOL bSingleCodePage;
  2185. bSingleCodePage = (pWinCodePage->usNumBaseCsets == 1) ? TRUE : FALSE;
  2186. ulSize = 0;
  2187. cChars = cRuns = i = 0;
  2188. if ((bIsPiFont = pWinCodePage->pCsetList[0] == CS_SYMBOL))
  2189. {
  2190. //
  2191. // This is a symbol font. We takes care of PS char codes from 0x20 to
  2192. // 0xff. We also map PS char codes to a single run in the Unicode
  2193. // private range.
  2194. //
  2195. cChars = (256 - 32) + 256;
  2196. cRuns = 1 * 2;
  2197. bSingleCodePage = FALSE;
  2198. VERBOSE(("Pi Font"));
  2199. }
  2200. else
  2201. {
  2202. //
  2203. // Process all unicode code pts. to determine the number of Unicode
  2204. // point runs present in this windows codepage.
  2205. //
  2206. do
  2207. {
  2208. //
  2209. // Proceed until the starting codepoint of next run is found.
  2210. //
  2211. // for (j = 0; j < pWinCodePage->usNumBaseCsets &&
  2212. // i < NUM_PS_CHARS;
  2213. // j++)
  2214. // if (CSET_SUPPORT(UnicodetoPs[i].flCharSets, pWinCodePage->pCsetList[j]))
  2215. // break;
  2216. // else
  2217. // i++;
  2218. //
  2219. bFound = FALSE;
  2220. for (; i < NUM_PS_CHARS; i++)
  2221. {
  2222. for (j = 0; j < pWinCodePage->usNumBaseCsets; j++)
  2223. {
  2224. if (CSET_SUPPORT(UnicodetoPs[i].flCharSets, pWinCodePage->pCsetList[j]))
  2225. {
  2226. bFound = TRUE;
  2227. break;
  2228. }
  2229. }
  2230. if (bFound)
  2231. break;
  2232. }
  2233. //
  2234. // Check to see if we've scanned all Unicode points.
  2235. //
  2236. if (i == NUM_PS_CHARS)
  2237. break;
  2238. //
  2239. // Start a new run.
  2240. //
  2241. cCharRun = 0;
  2242. wcRunStrt = UnicodetoPs[i].wcUnicodeid;
  2243. //
  2244. // Chars are only part of the run if they are supported
  2245. // in the current charset.
  2246. //
  2247. while (i < NUM_PS_CHARS &&
  2248. UnicodetoPs[i].wcUnicodeid == wcRunStrt + cCharRun)
  2249. {
  2250. for (j = 0; j < pWinCodePage->usNumBaseCsets; j++)
  2251. {
  2252. if (CSET_SUPPORT(UnicodetoPs[i].flCharSets, pWinCodePage->pCsetList[j]))
  2253. {
  2254. cCharRun++;
  2255. break;
  2256. }
  2257. }
  2258. i++;
  2259. }
  2260. if (cCharRun)
  2261. {
  2262. cChars += cCharRun;
  2263. cRuns++;
  2264. }
  2265. } while (i < NUM_PS_CHARS);
  2266. }
  2267. //
  2268. // Compute the total amount of memory required for the GLYPHSETDATA array
  2269. // and all other related data. We need
  2270. // 1. one CODEPAGEINFO struct for each base charset supported by this font,
  2271. // 2. one GLYPHRUN struct for each run, and
  2272. // 3. four bytes per char to store codepage and codepoint or two bytes per
  2273. // char to store only codepoint for the mapping table.
  2274. //
  2275. dwGSNameSize = ALIGN4(strlen(pWinCodePage->pszCPname) + 1);
  2276. dwCodePageInfoSize = ALIGN4(pWinCodePage->usNumBaseCsets * sizeof (CODEPAGEINFO));
  2277. dwGlyphRunSize = ALIGN4(cRuns * sizeof (GLYPHRUN));
  2278. ulSize = ALIGN4(sizeof(GLYPHSETDATA))
  2279. + dwGSNameSize
  2280. + dwCodePageInfoSize
  2281. + dwGlyphRunSize;
  2282. //
  2283. // Account for the size of the mapping table.
  2284. //
  2285. ulSize += bSingleCodePage ? ALIGN4((cChars * sizeof (WORD))) : (cChars * sizeof (DWORD));
  2286. //
  2287. // Account for the size of CODEPAGE name strings found in CODEPAGEINFO
  2288. // struct(s).
  2289. //
  2290. for (dwCPIGSNameSize = 0, j = 0; j < pWinCodePage->usNumBaseCsets; j++)
  2291. {
  2292. dwCPIGSNameSize += ALIGN4(strlen(aPStoCP[pWinCodePage->pCsetList[j]].pGSName) + 1);
  2293. }
  2294. ulSize += dwCPIGSNameSize;
  2295. //
  2296. // Allocate memory for the GLYPHSETDATA struct.
  2297. //
  2298. if ((pGlyphSetData = (PGLYPHSETDATA) MemAllocZ((size_t) ulSize)) == NULL)
  2299. {
  2300. ERR(("makentf - CreateGlyphSets: malloc\n"));
  2301. return(FALSE);
  2302. }
  2303. //
  2304. // Allocate an array of ULONGs to store the index of each char into
  2305. // the Unicode->Ps translation table.
  2306. //
  2307. if (!bIsPiFont)
  2308. {
  2309. if ((*pUniPs = (PULONG) MemAllocZ((size_t)(cChars * sizeof(ULONG)))) == NULL)
  2310. {
  2311. ERR(("makentf - CreateGlyphSets: malloc\n"));
  2312. return(FALSE);
  2313. }
  2314. }
  2315. //
  2316. // Init GLYPHSETDATA fields.
  2317. //
  2318. pGlyphSetData->dwSize = ulSize;
  2319. pGlyphSetData->dwVersion = GLYPHSETDATA_VERSION;
  2320. pGlyphSetData->dwFlags = 0;
  2321. pGlyphSetData->dwGlyphSetNameOffset = ALIGN4(sizeof(GLYPHSETDATA));
  2322. pGlyphSetData->dwGlyphCount = cChars;
  2323. pGlyphSetData->dwCodePageCount = pWinCodePage->usNumBaseCsets;
  2324. pGlyphSetData->dwCodePageOffset = pGlyphSetData->dwGlyphSetNameOffset + dwGSNameSize;
  2325. pGlyphSetData->dwRunCount = cRuns;
  2326. pGlyphSetData->dwRunOffset = pGlyphSetData->dwCodePageOffset + dwCodePageInfoSize + dwCPIGSNameSize;
  2327. pGlyphSetData->dwMappingTableOffset = pGlyphSetData->dwRunOffset + dwGlyphRunSize;
  2328. //
  2329. // Set the mapping table type flag to dwFlags field.
  2330. //
  2331. pGlyphSetData->dwFlags |= bSingleCodePage ? GSD_MTT_WCC : GSD_MTT_DWCPCC;
  2332. //
  2333. // Store code page name
  2334. //
  2335. StringCchCopyA((PSZ) MK_PTR(pGlyphSetData, dwGlyphSetNameOffset), dwGSNameSize, pWinCodePage->pszCPname);
  2336. //
  2337. // Initialize a CODEPAGEINFO struct for each base charset supported
  2338. // by this font.
  2339. //
  2340. pCodePageInfo = (PCODEPAGEINFO) MK_PTR(pGlyphSetData, dwCodePageOffset);
  2341. dwEncodingNameOffset = dwCodePageInfoSize;
  2342. for (j = 0; j < pWinCodePage->usNumBaseCsets; j++, pCodePageInfo++)
  2343. {
  2344. //
  2345. // Save CODEPAGEINFO. We don't use PS encoding vectors.
  2346. //
  2347. pCodePageInfo->dwCodePage = aPStoCP[pWinCodePage->pCsetList[j]].usACP;
  2348. pCodePageInfo->dwWinCharset = (DWORD)aPStoCP[pWinCodePage->pCsetList[j]].jWinCharset;
  2349. pCodePageInfo->dwEncodingNameOffset = dwEncodingNameOffset;
  2350. pCodePageInfo->dwEncodingVectorDataSize = 0;
  2351. pCodePageInfo->dwEncodingVectorDataOffset = 0;
  2352. //
  2353. // Copy codepage name string to end of array of CODEPAGEINFOs.
  2354. //
  2355. StringCchCopyA((PBYTE)MK_PTR(pCodePageInfo, dwEncodingNameOffset),
  2356. ALIGN4(strlen(aPStoCP[pWinCodePage->pCsetList[j]].pGSName) + 1),
  2357. aPStoCP[pWinCodePage->pCsetList[j]].pGSName);
  2358. //
  2359. // Adjust the offset to the codepage name for the next CODEPAGINFO structure
  2360. //
  2361. dwEncodingNameOffset -= ALIGN4(sizeof (CODEPAGEINFO));
  2362. dwEncodingNameOffset += ALIGN4(strlen((PBYTE)MK_PTR(pCodePageInfo, dwEncodingNameOffset)) + 1);
  2363. }
  2364. //
  2365. // Init ptr to the mapping table.
  2366. //
  2367. pGlyphRuns = GSD_GET_GLYPHRUN(pGlyphSetData);
  2368. pMapTable = GSD_GET_MAPPINGTABLE(pGlyphSetData);
  2369. //
  2370. // Make another pass through the Unicode points to initialize the Unicode
  2371. // runs and gi->codepage/codept mapping array for this codepage.
  2372. //
  2373. cRuns = 0;
  2374. if (bIsPiFont)
  2375. {
  2376. //
  2377. // Glyphset for Pi fonts has 1 run of 256 minus 0x20(it's 0x1f
  2378. // actually) chars over the Unicode private range.
  2379. //
  2380. pGlyphRuns[cRuns].wcLow = NOTDEF1F;
  2381. pGlyphRuns[cRuns].wGlyphCount = 256 - NOTDEF1F;
  2382. pGlyphRuns[cRuns + 1].wcLow = UNICODE_PRV_STRT;
  2383. pGlyphRuns[cRuns + 1].wGlyphCount = 256;
  2384. //
  2385. // We know that Pi fonts support only single encoding, but we also
  2386. // provide the mapping table for Unicode range f000...f0ff, which
  2387. // is mapped to PS code point 00...ff.
  2388. //
  2389. for (i = 0; i < 256 - NOTDEF1F; i++)
  2390. {
  2391. ((DWORD*)pMapTable)[i] =
  2392. aPStoCP[pWinCodePage->pCsetList[0]].usACP << 16 | (i + NOTDEF1F);
  2393. }
  2394. for (i = 0; i < 256; i++)
  2395. {
  2396. ((DWORD*)pMapTable)[i + 256 - NOTDEF1F] =
  2397. aPStoCP[pWinCodePage->pCsetList[0]].usACP << 16 | i;
  2398. }
  2399. }
  2400. else
  2401. {
  2402. cChars = i = 0;
  2403. do
  2404. {
  2405. //
  2406. // Proceed until the starting codepoint of next run is found.
  2407. //
  2408. // for (j = 0; j < pWinCodePage->usNumBaseCsets &&
  2409. // i < NUM_PS_CHARS;
  2410. // j++)
  2411. // if (CSET_SUPPORT(UnicodetoPs[i].flCharSets, pWinCodePage->pCsetList[j]))
  2412. // break;
  2413. // else
  2414. // i++;
  2415. //
  2416. bFound = FALSE;
  2417. for (; i < NUM_PS_CHARS; i++)
  2418. {
  2419. for (j = 0; j < pWinCodePage->usNumBaseCsets; j++)
  2420. {
  2421. if (CSET_SUPPORT(UnicodetoPs[i].flCharSets, pWinCodePage->pCsetList[j]))
  2422. {
  2423. bFound = TRUE;
  2424. break;
  2425. }
  2426. }
  2427. if (bFound)
  2428. break;
  2429. }
  2430. //
  2431. // Check to see if we've scanned all Unicode points.
  2432. //
  2433. if (i == NUM_PS_CHARS)
  2434. break;
  2435. //
  2436. // Start a new run.
  2437. //
  2438. cCharRun = 0;
  2439. wcRunStrt = UnicodetoPs[i].wcUnicodeid;
  2440. //
  2441. // Chars are only part of the run if they are supported
  2442. // in the current charset.
  2443. //
  2444. while (i < NUM_PS_CHARS &&
  2445. UnicodetoPs[i].wcUnicodeid == wcRunStrt + cCharRun)
  2446. {
  2447. for (j = 0, bFound = FALSE;
  2448. j < pWinCodePage->usNumBaseCsets && !bFound; j++)
  2449. {
  2450. if (CSET_SUPPORT(UnicodetoPs[i].flCharSets, pWinCodePage->pCsetList[j]))
  2451. {
  2452. if (((pWinCpt =
  2453. (PWINCPT) bsearch(UnicodetoPs[i].pPsName,
  2454. aPStoCP[pWinCodePage->pCsetList[j]].aWinCpts,
  2455. aPStoCP[pWinCodePage->pCsetList[j]].ulChCnt,
  2456. sizeof(WINCPT),
  2457. CmpPsNameWinCpt))
  2458. != NULL))
  2459. {
  2460. //
  2461. // Found a corresponding PS char in the current
  2462. // windows codepage. Save it in the mapping table.
  2463. //
  2464. if (bSingleCodePage)
  2465. {
  2466. ((WORD*)pMapTable)[cChars] = pWinCpt->usWinCpt;
  2467. }
  2468. else
  2469. {
  2470. ((DWORD*)pMapTable)[cChars] =
  2471. aPStoCP[pWinCodePage->pCsetList[j]].usACP << 16 | pWinCpt->usWinCpt;
  2472. }
  2473. bFound = TRUE;
  2474. }
  2475. else if (j == (pWinCodePage->usNumBaseCsets - 1))
  2476. {
  2477. //
  2478. // Corresponding PS char was not found. Use Win
  2479. // codept 0 as .notdef char and base codepage.
  2480. //
  2481. if (bSingleCodePage)
  2482. ((WORD*)pMapTable)[cChars] = 0;
  2483. else
  2484. ((DWORD*)pMapTable)[cChars] =
  2485. aPStoCP[pWinCodePage->pCsetList[0]].usACP << 16;
  2486. bFound = TRUE;
  2487. }
  2488. //
  2489. // If char is present in this codepage, save index in
  2490. // Unicode->Ps table.
  2491. //
  2492. if (bFound)
  2493. {
  2494. (*pUniPs)[cChars] = i;
  2495. cChars++;
  2496. cCharRun++;
  2497. }
  2498. }
  2499. }
  2500. i++;
  2501. }
  2502. if (cCharRun)
  2503. {
  2504. pGlyphRuns[cRuns].wcLow = wcRunStrt;
  2505. pGlyphRuns[cRuns].wGlyphCount = (WORD)cCharRun;
  2506. cRuns++;
  2507. }
  2508. } while (i < NUM_PS_CHARS);
  2509. }
  2510. //
  2511. // Return success.
  2512. //
  2513. *pGlyphSet = pGlyphSetData;
  2514. if (bVerbose && !bOptimize)
  2515. {
  2516. printf("GLYPHSETDATA:dwFlags:%08X\n", pGlyphSetData->dwFlags);
  2517. printf("GLYPHSETDATA:dwGlyphSetNameOffset:%s\n",
  2518. (PSZ)MK_PTR(pGlyphSetData, dwGlyphSetNameOffset));
  2519. printf("GLYPHSETDATA:dwGlyphCount:%ld\n", pGlyphSetData->dwGlyphCount);
  2520. printf("GLYPHSETDATA:dwRunCount:%ld\n", pGlyphSetData->dwRunCount);
  2521. printf("GLYPHSETDATA:dwCodePageCount:%ld\n", pGlyphSetData->dwCodePageCount);
  2522. {
  2523. DWORD dw;
  2524. PCODEPAGEINFO pcpi = (PCODEPAGEINFO)MK_PTR(pGlyphSetData, dwCodePageOffset);
  2525. for (dw = 1; dw <= pGlyphSetData->dwCodePageCount; dw++)
  2526. {
  2527. printf("CODEPAGEINFO#%ld:dwCodePage:%ld\n", dw, pcpi->dwCodePage);
  2528. printf("CODEPAGEINFO#%ld:dwWinCharset:%ld\n", dw, pcpi->dwWinCharset);
  2529. printf("CODEPAGEINFO#%ld:dwEncodingNameOffset:%s\n",
  2530. dw, (PSZ)MK_PTR(pcpi, dwEncodingNameOffset));
  2531. pcpi++;
  2532. }
  2533. }
  2534. if (bIsPiFont)
  2535. {
  2536. printf("(Single codepage with dwFlags bit 0 cleared.)\n");
  2537. printf("(Special for Symbol glyphset)\n");
  2538. }
  2539. printf("\n");
  2540. }
  2541. return(ulSize);
  2542. }
  2543. LONG
  2544. FindClosestCodePage(
  2545. PWINCODEPAGE *pWinCodePages,
  2546. ULONG ulNumCodePages,
  2547. CHSETSUPPORT chSets,
  2548. PCHSETSUPPORT pchCsupMatch
  2549. )
  2550. /*++
  2551. Routine Description:
  2552. Given a list of ptrs to WINCODEPAGE structs, determine which WINCODEPAGE's
  2553. component charsets best match the charsets value in chSets.
  2554. Arguments:
  2555. pWinCodePages - List of PWINCODEPAGES.
  2556. ulNumCodePages - Number of entries in pWinCodePages
  2557. chSets - CHSETSUPPORT value which indicates which standard charsets
  2558. are supported by this font.
  2559. pchCsupMatch - Pointer to a CHSETSUPPORT variable which returns the
  2560. supported charsets of the code page which most closely matches the
  2561. chSets value. If no matching codepages are found, the value will be 0.
  2562. Return Value:
  2563. -1 => no matching Codepages were found.
  2564. Otherwise this is the index in pWinCodePages of the "best match" codepage.
  2565. --*/
  2566. {
  2567. ULONG c;
  2568. LONG j;
  2569. LONG cpMatch;
  2570. LONG nCurCsets, nLastCsets;
  2571. FLONG flCurCset;
  2572. cpMatch = -1;
  2573. //
  2574. // Scan the list of Windows codepages.
  2575. //
  2576. for (c = 0, nLastCsets = 0; c < ulNumCodePages; c++)
  2577. {
  2578. //
  2579. // Hack..Hack! If this is the Unicode codepage, ignore it as
  2580. // no NTMs should reference it!
  2581. //
  2582. if (strcmp(pWinCodePages[c]->pszCPname, UNICODE_GS_NAME))
  2583. {
  2584. nCurCsets = flCurCset = 0;
  2585. //
  2586. // Determine which charsets in the current codepage are
  2587. // a match for those supported by the current font.
  2588. //
  2589. for (j = 0; j < pWinCodePages[c]->usNumBaseCsets; j++)
  2590. {
  2591. if (CSET_SUPPORT(chSets, pWinCodePages[c]->pCsetList[j]))
  2592. {
  2593. nCurCsets++;
  2594. }
  2595. flCurCset |= CSUP(pWinCodePages[c]->pCsetList[j]);
  2596. }
  2597. if (flCurCset == (FLONG) chSets)
  2598. {
  2599. //
  2600. // Found a charset which supports ALL of the font's charsets.
  2601. //
  2602. cpMatch = (LONG) c;
  2603. *pchCsupMatch = flCurCset;
  2604. break;
  2605. }
  2606. else if (nCurCsets > nLastCsets)
  2607. {
  2608. //
  2609. // This Windows codepage is the maximal match so far.
  2610. //
  2611. nLastCsets = nCurCsets;
  2612. cpMatch = (LONG) c;
  2613. *pchCsupMatch = flCurCset;
  2614. }
  2615. }
  2616. }
  2617. return(cpMatch);
  2618. }
  2619. ULONG
  2620. GetAFMCharWidths(
  2621. PBYTE pAFM,
  2622. PWIDTHRUN *pWidthRuns,
  2623. PPSCHARMETRICS pFontChars,
  2624. PULONG pUniPs,
  2625. ULONG ulChCnt,
  2626. PUSHORT pusAvgCharWidth,
  2627. PUSHORT pusMaxCharWidth
  2628. )
  2629. /*++
  2630. Routine Description:
  2631. Given a memory mapped AFM file ptr and a ptr to a which maps glyph indices
  2632. to UPSCODEPT Unicode->Ps translation structs, fill memory with a list of
  2633. WIDTHRUN structs which provide char width information.
  2634. Arguments:
  2635. pAFM - Pointer to memory mapped AFM file.
  2636. pWidthRuns - If NULL, this is a size request and the function returns the
  2637. total size in bytes of all WIDTHRUN structs required for this font.
  2638. Otherwise the ptr is assumed to point to a buffer large enough to
  2639. hold the number of required WIDTHRUNs.
  2640. pFontChars - pointer a table of PS font char metrics info previously
  2641. created by calling the BuildPSCharMetrics function. This array contains
  2642. per char metric information.
  2643. pUniPs - Points to a table which maps 0-based Glyph Indices of chars
  2644. in the GLYPHRUNS of the GLYPHSETDATA struct for this font to indices
  2645. into the UnicodetoPs structure which maps Unicode points to PS char
  2646. information. This mapping array is created by the CreateGlyphSet function
  2647. defined in this module.
  2648. ulChCnt - Number of chars in the GLYPHSET for this font. This most likely
  2649. is not the same as the number of chars defined in the font's AFM.
  2650. pulAvgCharWidth - pts to a USHORT used to return the average char
  2651. width of the font. If NULL the average char width is not returned.
  2652. pulMaxCharWidth - pts to a USHORT used to return the max char
  2653. width of the font. If NULL the max char width is not returned.
  2654. Return Value:
  2655. 0 => error.
  2656. Otherwise returns number of WIDTHRUN structs required for this font.
  2657. --*/
  2658. {
  2659. ULONG i, j, curChar;
  2660. int cRuns, cRealRuns;
  2661. int cChars;
  2662. int cCharRun;
  2663. ULONG firstCharWidth;
  2664. ULONG curCharWidth;
  2665. ULONG notdefwidth;
  2666. WCHAR wcRunStrt;
  2667. USHORT chCnt;
  2668. PBYTE pToken;
  2669. PBYTE pChMet;
  2670. PPSCHARMETRICS pCurChar;
  2671. BOOLEAN bIsPiFont, bIsCJKFont;
  2672. CHAR ch;
  2673. BYTE CharNameBuffer[32];
  2674. PBYTE pChName;
  2675. // fix bug 240339, jjia, 8/3/98
  2676. BOOLEAN bWidthRunComplex;
  2677. PWORD pWidthArray;
  2678. // Fixed bug Adobe #367195.
  2679. // In this program, when handling PiFont, we always assume the first character
  2680. // in the CharMetrics is a space (32) char. However, some special font such as
  2681. // HoeflerText-Ornaments does not follow this rule. the 1st char in the font is 9,
  2682. // the 2ed char is 32. Added this flag to handle this kind of fonts.
  2683. BOOLEAN bTwoSpace = FALSE;
  2684. //
  2685. // Determine if this is a Pi or CJK font.
  2686. //
  2687. bIsPiFont = IsPiFont(pAFM);
  2688. bIsCJKFont = (IsCJKFont(pAFM) != 0);
  2689. //
  2690. // Get ptr to AFM char metrics.
  2691. //
  2692. pChMet = FindAFMToken(pAFM, PS_CH_METRICS_TOK);
  2693. if (pChMet == NULL) // Fixed bug 354007
  2694. return (FALSE);
  2695. //
  2696. // Current pos should be the character count field.
  2697. //
  2698. for (i = 0; i < (int) StrLen(pChMet); i++)
  2699. {
  2700. if (!IS_NUM(&pChMet[i]))
  2701. {
  2702. return(FALSE);
  2703. }
  2704. }
  2705. chCnt = (USHORT)atoi(pChMet);
  2706. (ULONG_PTR) pChMet += i;
  2707. //
  2708. // If requested, make a pass through the PS Char Metrics to determine
  2709. // the max char width.
  2710. //
  2711. if (pusMaxCharWidth != NULL)
  2712. {
  2713. *pusMaxCharWidth = 0;
  2714. for (i = 0; i < chCnt; i++)
  2715. {
  2716. if (pFontChars[i].chWidth > *pusMaxCharWidth)
  2717. {
  2718. *pusMaxCharWidth = (USHORT) pFontChars[i].chWidth & 0xffff;
  2719. }
  2720. }
  2721. }
  2722. //
  2723. // Search for .notdef char in list of PS chars, get .notdef char width.
  2724. //
  2725. if (bIsPiFont)
  2726. {
  2727. notdefwidth = pFontChars[0].chWidth;
  2728. }
  2729. else if ((pCurChar = (PPSCHARMETRICS) bsearch("space",
  2730. pFontChars[0].pPsName,
  2731. (size_t) chCnt,
  2732. sizeof(PSCHARMETRICS),
  2733. strcmp)) != NULL)
  2734. notdefwidth = pCurChar->chWidth;
  2735. else
  2736. notdefwidth = 0;
  2737. //
  2738. // If average width was requested, process string of sample chars 1
  2739. // at a time to compute average char width.
  2740. // DCR --: Assume the sample is western alphabetic + space.
  2741. // Need to fix this for non-western fonts !!!.
  2742. //
  2743. if (pusAvgCharWidth != NULL)
  2744. {
  2745. LONG lWidth, count; // a long to prevent OverFlow
  2746. WINCPTOPS *pCPtoPS;
  2747. WINCPT sortedWinCpts[MAX_CSET_CHARS]; // maxiaml 255 chars
  2748. CHSETSUPPORT flCsupGlyphSet;
  2749. ULONG k;
  2750. BYTE *pSampleStr;
  2751. //
  2752. // Determine which charsets this font supports.
  2753. //
  2754. (VOID)GetAFMCharSetSupport(pAFM, &flCsupGlyphSet);
  2755. if (flCsupGlyphSet == CS_228 || flCsupGlyphSet == CS_314)
  2756. {
  2757. pCPtoPS = &aPStoCP[CS_228];
  2758. }
  2759. else
  2760. {
  2761. // default - use the ANSI code page table
  2762. pCPtoPS = &aPStoCP[CS_ANSI];
  2763. }
  2764. SortWinCPT(&(sortedWinCpts[0]), pCPtoPS);
  2765. lWidth = 0;
  2766. count = 0;
  2767. k = 0x20; // start from FirstChar !!
  2768. for (i = 0; i < pCPtoPS->ulChCnt && k <= 0xFF; i++, k++)
  2769. {
  2770. pCurChar = NULL;
  2771. if (bIsPiFont)
  2772. {
  2773. if (i<chCnt)
  2774. pCurChar = &(pFontChars[ i ]);
  2775. // We don't need Not-Encoded characters in a PiFont.
  2776. if (pCurChar && strcmp(pCurChar->pPsName, "-1") == 0 )
  2777. pCurChar = NULL;
  2778. }
  2779. else
  2780. {
  2781. // sortedWinCpts is sorted by usWinCpt, so skip UP to what we want
  2782. while (k > sortedWinCpts[i].usWinCpt && i < pCPtoPS->ulChCnt )
  2783. {
  2784. i++;
  2785. }
  2786. // Take notdef chars in the 0x20 to 0xff range - gaps
  2787. while (k < sortedWinCpts[i].usWinCpt && k <= 0xFF )
  2788. {
  2789. k++;
  2790. lWidth += notdefwidth;
  2791. count++;
  2792. }
  2793. pSampleStr = NULL;
  2794. if (k == sortedWinCpts[i].usWinCpt)
  2795. pSampleStr = sortedWinCpts[i].pPsName;
  2796. if (pSampleStr == NULL)
  2797. continue;
  2798. pCurChar = (PPSCHARMETRICS) bsearch(pSampleStr,
  2799. pFontChars[0].pPsName,
  2800. (size_t) chCnt,
  2801. sizeof(PSCHARMETRICS),
  2802. strcmp);
  2803. }
  2804. if (pCurChar != NULL && pCurChar->pPsName && pCurChar->pPsName[0] != 0 &&
  2805. pCurChar->chWidth > 0)
  2806. {
  2807. lWidth += (LONG) pCurChar->chWidth;
  2808. count++;
  2809. }
  2810. else
  2811. {
  2812. lWidth += notdefwidth;
  2813. count++;
  2814. }
  2815. }
  2816. if (count)
  2817. lWidth = (lWidth + count/2)/count;
  2818. if (lWidth == 0)
  2819. {
  2820. lWidth = 0 ;
  2821. // This is a buggy font. Or CJK font!!!
  2822. // In this case we must come up with the reasonable number different from
  2823. // zero. This number is used in computing font trasfroms.
  2824. for (i = 0; i <= chCnt; i++)
  2825. lWidth += (LONG) (pFontChars[i].chWidth & 0xffff);
  2826. lWidth = (lWidth + chCnt / 2) / chCnt ;
  2827. // ASSERTMSG(*pusAvgCharWidth, ("PSCRIPT: pifi->fwdAveCharWidth == 0\n"));
  2828. }
  2829. // Now assign it to the original (short) width
  2830. *pusAvgCharWidth = (FWORD) lWidth;
  2831. if (*pusAvgCharWidth == 0 || (bIsCJKFont && *pusAvgCharWidth < EM))
  2832. {
  2833. *pusAvgCharWidth = EM;
  2834. }
  2835. if (bIsCJKFont)
  2836. {
  2837. // DCR: couldn't divide by 2 simply for C and K.
  2838. *pusAvgCharWidth = *pusAvgCharWidth / 2;
  2839. }
  2840. }
  2841. //
  2842. // Determine the amount of memory required for the WIDTHRUNS which cover
  2843. // all possible points in the font's charset.
  2844. //
  2845. i = cRuns = 0;
  2846. if (bIsPiFont)
  2847. {
  2848. curChar = 1;
  2849. if (atoi(pFontChars[i].pPsName) == (BYTE) ' ')
  2850. {
  2851. curCharWidth = pFontChars[i].chWidth;
  2852. }
  2853. else
  2854. {
  2855. // Fixed bug Adobe #367195
  2856. if (atoi(pFontChars[i + 1].pPsName) == (BYTE) ' ')
  2857. bTwoSpace = TRUE;
  2858. curCharWidth = notdefwidth;
  2859. }
  2860. }
  2861. else
  2862. {
  2863. //
  2864. // Setup ptr to "char name" based on whether this is a
  2865. // western or CJK font.
  2866. //
  2867. if (bIsCJKFont)
  2868. {
  2869. _ultoa(pUniPs[i], CharNameBuffer, 10);
  2870. pChName = CharNameBuffer;
  2871. }
  2872. else
  2873. {
  2874. pChName = UnicodetoPs[pUniPs[i]].pPsName;
  2875. }
  2876. if ((pCurChar = (PPSCHARMETRICS) bsearch(pChName,
  2877. pFontChars,
  2878. (size_t) chCnt,
  2879. sizeof(PSCHARMETRICS),
  2880. CmpPsChars)) == NULL)
  2881. {
  2882. curCharWidth = notdefwidth;
  2883. }
  2884. else
  2885. {
  2886. curCharWidth = pCurChar->chWidth;
  2887. }
  2888. }
  2889. do
  2890. {
  2891. //
  2892. // Start new run.
  2893. //
  2894. cCharRun = 1;
  2895. wcRunStrt = (USHORT) (i & 0xffff);
  2896. for (firstCharWidth = curCharWidth, i++; i < ulChCnt; i++)
  2897. {
  2898. if (bIsPiFont)
  2899. {
  2900. if (curChar < chCnt)
  2901. {
  2902. // Fixed bug Adobe #367185
  2903. if ((bTwoSpace) &&
  2904. ((ULONG) atoi(pFontChars[curChar].pPsName) == (i - 1 + (BYTE) ' ')))
  2905. {
  2906. curCharWidth = pFontChars[curChar].chWidth;
  2907. curChar++;
  2908. }
  2909. else if ((!bTwoSpace) &&
  2910. ((ULONG) atoi(pFontChars[curChar].pPsName) == (i + (BYTE) ' ')))
  2911. {
  2912. curCharWidth = pFontChars[curChar].chWidth;
  2913. curChar++;
  2914. }
  2915. else
  2916. {
  2917. curCharWidth = notdefwidth;
  2918. }
  2919. }
  2920. else
  2921. {
  2922. curCharWidth = notdefwidth;
  2923. }
  2924. }
  2925. else
  2926. {
  2927. //
  2928. // Setup ptr to "char name" based on whether this is a
  2929. // western or CJK font.
  2930. //
  2931. if (bIsCJKFont)
  2932. {
  2933. _ultoa(pUniPs[i], CharNameBuffer, 10);
  2934. pChName = CharNameBuffer;
  2935. }
  2936. else
  2937. {
  2938. pChName = UnicodetoPs[pUniPs[i]].pPsName;
  2939. }
  2940. if((pCurChar = (PPSCHARMETRICS) bsearch(pChName,
  2941. pFontChars,
  2942. (size_t) chCnt,
  2943. sizeof(PSCHARMETRICS),
  2944. CmpPsChars)) != NULL)
  2945. {
  2946. curCharWidth = pCurChar->chWidth;
  2947. }
  2948. else
  2949. {
  2950. curCharWidth = notdefwidth;
  2951. }
  2952. }
  2953. if ((curCharWidth == firstCharWidth) &&
  2954. ((SHORT) i == (wcRunStrt + cCharRun)))
  2955. {
  2956. cCharRun++;
  2957. }
  2958. else
  2959. {
  2960. break;
  2961. }
  2962. }
  2963. cRuns++;
  2964. } while (i < ulChCnt);
  2965. // Fix bug 240339, jjia, 8/3/98
  2966. if ((cRuns * sizeof(WIDTHRUN)) >
  2967. (ulChCnt * sizeof(WORD) + sizeof(WIDTHRUN)))
  2968. bWidthRunComplex = TRUE;
  2969. else
  2970. bWidthRunComplex = FALSE;
  2971. if (pWidthRuns == NULL)
  2972. {
  2973. //
  2974. // Return number of WIDTHRUNs only.
  2975. //
  2976. if (!bIsPiFont)
  2977. {
  2978. // Fix bug 240339, jjia, 8/3/98
  2979. if (bWidthRunComplex)
  2980. return (ALIGN4(ulChCnt * sizeof(WORD) + sizeof(WIDTHRUN)));
  2981. else
  2982. return (ALIGN4(cRuns * sizeof(WIDTHRUN)));
  2983. }
  2984. else
  2985. {
  2986. //
  2987. // Hack to support 2 Unicode runs.
  2988. //
  2989. return (ALIGN4(cRuns * 2 * sizeof(WIDTHRUN)));
  2990. }
  2991. }
  2992. //
  2993. // Create the list of WIDTHRUNs.
  2994. //
  2995. cRealRuns = cRuns;
  2996. i = cRuns = 0;
  2997. // Fix bug 240339, jjia, 8/3/98
  2998. if (bWidthRunComplex && (!bIsPiFont))
  2999. {
  3000. (*pWidthRuns)[0].wStartGlyph = (WORD) (i & 0xffff);
  3001. (*pWidthRuns)[0].dwCharWidth = WIDTHRUN_COMPLEX;
  3002. (*pWidthRuns)[0].wGlyphCount = (WORD)ulChCnt;
  3003. cRuns = 1;
  3004. pWidthArray = (PWORD)&(*pWidthRuns)[1];
  3005. for (; i < ulChCnt; i++)
  3006. {
  3007. if (bIsCJKFont)
  3008. {
  3009. _ultoa(pUniPs[i], CharNameBuffer, 10);
  3010. pChName = CharNameBuffer;
  3011. }
  3012. else
  3013. {
  3014. pChName = UnicodetoPs[pUniPs[i]].pPsName;
  3015. }
  3016. if((pCurChar = (PPSCHARMETRICS) bsearch(pChName,
  3017. pFontChars,
  3018. (size_t) chCnt,
  3019. sizeof(PSCHARMETRICS),
  3020. CmpPsChars)) == NULL)
  3021. {
  3022. //
  3023. // Char is not defined in this font.
  3024. //
  3025. pWidthArray[i] = (WORD)notdefwidth;
  3026. }
  3027. else
  3028. {
  3029. //
  3030. // Char is defined in this font.
  3031. //
  3032. pWidthArray[i] = (WORD)(pCurChar->chWidth);
  3033. }
  3034. }
  3035. return (cRuns);
  3036. }
  3037. if (bIsPiFont)
  3038. {
  3039. curChar = 1;
  3040. if (atoi(pFontChars[i].pPsName) == (BYTE) ' ')
  3041. {
  3042. curCharWidth = pFontChars[i].chWidth;
  3043. }
  3044. else
  3045. {
  3046. // Fixed bug Adobe #367195
  3047. if (atoi(pFontChars[i + 1].pPsName) == (BYTE) ' ')
  3048. bTwoSpace = TRUE;
  3049. curCharWidth = notdefwidth;
  3050. }
  3051. }
  3052. else
  3053. {
  3054. //
  3055. // Setup ptr to "char name" based on whether this is a
  3056. // western or CJK font.
  3057. //
  3058. if (bIsCJKFont)
  3059. {
  3060. _ultoa(pUniPs[i], CharNameBuffer, 10);
  3061. pChName = CharNameBuffer;
  3062. }
  3063. else
  3064. {
  3065. pChName = UnicodetoPs[pUniPs[i]].pPsName;
  3066. }
  3067. if ((pCurChar = (PPSCHARMETRICS) bsearch(pChName,
  3068. pFontChars,
  3069. (size_t) chCnt,
  3070. sizeof(PSCHARMETRICS),
  3071. CmpPsChars)) != NULL)
  3072. {
  3073. curCharWidth = pCurChar->chWidth;
  3074. }
  3075. else
  3076. {
  3077. curCharWidth = notdefwidth;
  3078. }
  3079. }
  3080. do
  3081. {
  3082. //
  3083. // Start new run.
  3084. //
  3085. cCharRun = 1;
  3086. wcRunStrt = (USHORT) (i & 0xffff);
  3087. for (firstCharWidth = curCharWidth, i++; i < ulChCnt; i++)
  3088. {
  3089. if (bIsPiFont)
  3090. {
  3091. if (curChar < chCnt)
  3092. {
  3093. // Fixed bug Adobe #367185
  3094. if ((bTwoSpace) &&
  3095. ((ULONG) atoi(pFontChars[curChar].pPsName) == (i - 1 + (BYTE) ' ')))
  3096. {
  3097. curCharWidth = pFontChars[curChar].chWidth;
  3098. curChar++;
  3099. }
  3100. else if ((!bTwoSpace) &&
  3101. ((ULONG) atoi(pFontChars[curChar].pPsName) == (i + (BYTE) ' ')))
  3102. {
  3103. curCharWidth = pFontChars[curChar].chWidth;
  3104. curChar++;
  3105. }
  3106. else
  3107. {
  3108. curCharWidth = notdefwidth;
  3109. }
  3110. }
  3111. else
  3112. {
  3113. curCharWidth = notdefwidth;
  3114. }
  3115. }
  3116. else
  3117. {
  3118. //
  3119. // Setup ptr to "char name" based on whether this is a
  3120. // western or CJK font.
  3121. //
  3122. if (bIsCJKFont)
  3123. {
  3124. _ultoa(pUniPs[i], CharNameBuffer, 10);
  3125. pChName = CharNameBuffer;
  3126. }
  3127. else
  3128. {
  3129. pChName = UnicodetoPs[pUniPs[i]].pPsName;
  3130. }
  3131. if((pCurChar = (PPSCHARMETRICS) bsearch(pChName,
  3132. pFontChars,
  3133. (size_t) chCnt,
  3134. sizeof(PSCHARMETRICS),
  3135. CmpPsChars)) == NULL)
  3136. {
  3137. //
  3138. // Char is not defined in this font.
  3139. //
  3140. curCharWidth = notdefwidth;
  3141. }
  3142. else
  3143. {
  3144. //
  3145. // Char is defined in this font.
  3146. //
  3147. curCharWidth = pCurChar->chWidth;
  3148. }
  3149. }
  3150. if ((curCharWidth == firstCharWidth) &&
  3151. ((SHORT) i == (wcRunStrt + cCharRun)))
  3152. {
  3153. cCharRun++;
  3154. }
  3155. else
  3156. {
  3157. break;
  3158. }
  3159. }
  3160. (*pWidthRuns)[cRuns].wStartGlyph = wcRunStrt;
  3161. (*pWidthRuns)[cRuns].dwCharWidth = firstCharWidth;
  3162. (*pWidthRuns)[cRuns].wGlyphCount = (WORD)cCharRun;
  3163. if (bIsPiFont)
  3164. {
  3165. //
  3166. // Hack to support 2 unicode runs.
  3167. //
  3168. (*pWidthRuns)[cRuns + cRealRuns].wStartGlyph = wcRunStrt;
  3169. (*pWidthRuns)[cRuns + cRealRuns].dwCharWidth = firstCharWidth;
  3170. (*pWidthRuns)[cRuns + cRealRuns].wGlyphCount = (WORD)cCharRun;
  3171. }
  3172. cRuns++;
  3173. } while (cRuns < cRealRuns);
  3174. if (bIsPiFont)
  3175. {
  3176. return(cRuns * 2);
  3177. }
  3178. else
  3179. {
  3180. return(cRuns);
  3181. }
  3182. }
  3183. ULONG
  3184. GetAFMETM(
  3185. PBYTE pAFM,
  3186. PPSCHARMETRICS pFontChars,
  3187. PETMINFO pEtmInfo
  3188. )
  3189. /*++
  3190. Routine Description:
  3191. Given a memory mapped AFM file ptr and a ptr to a which maps glyph indices
  3192. to UPSCODEPT Unicode->Ps translation structs, fill memory with a list of
  3193. WIDTHRUN structs which provide char width information.
  3194. Arguments:
  3195. pAFM - Pointer to memory mapped AFM file.
  3196. pFontChars - pointer a table of PS font char metrics info previously
  3197. created by calling the BuildPSCharMetrics function. This array contains
  3198. per char metric information.
  3199. pulEtmInfo - pts to an ETMINFO struct used to return EXTEXTMETRIC
  3200. info which must be derived from the AFM char metrics. If NULL the
  3201. structure is not returned.
  3202. Return Value:
  3203. 0 => error.
  3204. 1 => success
  3205. --*/
  3206. {
  3207. ULONG i;
  3208. USHORT chCnt;
  3209. PPSCHARMETRICS pCurChar;
  3210. BOOLEAN bIsPiFont;
  3211. CHSETSUPPORT csIsCJKFont;
  3212. PBYTE pChMet;
  3213. PSTR pCJKCapH, pCJKx;
  3214. //
  3215. // Determine if this is a Pi or CJK font.
  3216. //
  3217. bIsPiFont = IsPiFont(pAFM);
  3218. csIsCJKFont = IsCJKFont(pAFM);
  3219. //
  3220. // Get ptr to AFM char metrics.
  3221. //
  3222. pChMet = FindAFMToken(pAFM, PS_CH_METRICS_TOK);
  3223. if (pChMet == NULL) // Fixed bug 354007
  3224. return (FALSE);
  3225. //
  3226. // Current pos should be the character count field.
  3227. //
  3228. for (i = 0; i < (int) StrLen(pChMet); i++)
  3229. {
  3230. if (!IS_NUM(&pChMet[i]))
  3231. {
  3232. return(FALSE);
  3233. }
  3234. }
  3235. chCnt = (USHORT)atoi(pChMet);
  3236. (ULONG_PTR) pChMet += i;
  3237. //
  3238. // Get EXTEXTMETRIC info if requested.
  3239. //
  3240. if (pEtmInfo != NULL)
  3241. {
  3242. if (bIsPiFont)
  3243. {
  3244. //
  3245. // For Pi Fonts, chars are indexed by char code.
  3246. //
  3247. if ((BYTE) CAP_HEIGHT_CH - (BYTE) ' ' < chCnt)
  3248. pCurChar = &(pFontChars[(BYTE) CAP_HEIGHT_CH - (BYTE) ' ']);
  3249. else
  3250. pCurChar = NULL; // default to 0 CapHeight
  3251. }
  3252. else
  3253. {
  3254. if (!csIsCJKFont)
  3255. {
  3256. pCurChar = (PPSCHARMETRICS) bsearch(CAP_HEIGHT_CHAR,
  3257. pFontChars[0].pPsName,
  3258. (size_t) chCnt,
  3259. sizeof(PSCHARMETRICS),
  3260. strcmp);
  3261. }
  3262. else
  3263. {
  3264. // We need CID of "H" in CJK
  3265. if (csIsCJKFont & (CSUP(CS_CHINESEBIG5) | CSUP(CS_GB2312)))
  3266. pCJKCapH = "853";
  3267. else if (csIsCJKFont & (CSUP(CS_SHIFTJIS) | CSUP(CS_SHIFTJIS83)))
  3268. pCJKCapH = "271";
  3269. else if (csIsCJKFont & (CSUP(CS_HANGEUL) | CSUP(CS_JOHAB)))
  3270. pCJKCapH = "8134";
  3271. else
  3272. pCJKCapH = CAP_HEIGHT_CHAR;
  3273. pCurChar = (PPSCHARMETRICS) bsearch(pCJKCapH,
  3274. pFontChars[0].pPsName,
  3275. (size_t) chCnt,
  3276. sizeof(PSCHARMETRICS),
  3277. strcmp);
  3278. }
  3279. }
  3280. if (pCurChar != NULL)
  3281. {
  3282. pEtmInfo->etmCapHeight = (USHORT) pCurChar->rcChBBox.top & 0xffff;
  3283. }
  3284. else
  3285. {
  3286. pEtmInfo->etmCapHeight = 0;
  3287. }
  3288. if (bIsPiFont)
  3289. {
  3290. //
  3291. // For Pi Fonts, chars are indexed by char code.
  3292. //
  3293. if ((BYTE) X_HEIGHT_CH - (BYTE) ' ' < chCnt)
  3294. pCurChar = &(pFontChars[(BYTE) X_HEIGHT_CH - (BYTE) ' ']);
  3295. else
  3296. pCurChar = NULL; // default to 0
  3297. }
  3298. else
  3299. {
  3300. if (!csIsCJKFont)
  3301. {
  3302. pCurChar = (PPSCHARMETRICS) bsearch(X_HEIGHT_CHAR,
  3303. pFontChars[0].pPsName,
  3304. (size_t) chCnt,
  3305. sizeof(PSCHARMETRICS),
  3306. strcmp);
  3307. }
  3308. else
  3309. {
  3310. // We need CID of "x" in CJK
  3311. if (csIsCJKFont & (CSUP(CS_CHINESEBIG5) | CSUP(CS_GB2312)))
  3312. pCJKx = "901";
  3313. else if (csIsCJKFont & (CSUP(CS_SHIFTJIS) | CSUP(CS_SHIFTJIS83)))
  3314. pCJKx = "319";
  3315. else if (csIsCJKFont & (CSUP(CS_HANGEUL) | CSUP(CS_JOHAB)))
  3316. pCJKx = "8182";
  3317. else
  3318. pCJKx = X_HEIGHT_CHAR;
  3319. pCurChar = (PPSCHARMETRICS) bsearch(pCJKx,
  3320. pFontChars[0].pPsName,
  3321. (size_t) chCnt,
  3322. sizeof(PSCHARMETRICS),
  3323. strcmp);
  3324. }
  3325. }
  3326. if (pCurChar != NULL)
  3327. {
  3328. pEtmInfo->etmXHeight = (USHORT) pCurChar->rcChBBox.top & 0xffff;
  3329. }
  3330. else
  3331. {
  3332. pEtmInfo->etmXHeight = 0;
  3333. }
  3334. if (bIsPiFont)
  3335. {
  3336. //
  3337. // For Pi Fonts, chars are indexed by char code.
  3338. //
  3339. if ((BYTE) LWR_ASCENT_CH - (BYTE) ' ' < chCnt)
  3340. pCurChar = &(pFontChars[(BYTE) LWR_ASCENT_CH - (BYTE) ' ']);
  3341. else
  3342. pCurChar = NULL; // default to 0
  3343. }
  3344. else
  3345. {
  3346. pCurChar = (PPSCHARMETRICS) bsearch(LWR_ASCENT_CHAR,
  3347. pFontChars[0].pPsName,
  3348. (size_t) chCnt,
  3349. sizeof(PSCHARMETRICS),
  3350. strcmp);
  3351. }
  3352. if (pCurChar != NULL)
  3353. {
  3354. pEtmInfo->etmLowerCaseAscent = (USHORT) pCurChar->rcChBBox.top & 0xffff;
  3355. }
  3356. else
  3357. {
  3358. pEtmInfo->etmLowerCaseAscent = 0;
  3359. }
  3360. if (bIsPiFont)
  3361. {
  3362. //
  3363. // For Pi Fonts, chars are indexed by char code.
  3364. //
  3365. if ((BYTE) LWR_DESCENT_CH - (BYTE) ' ' < chCnt)
  3366. pCurChar = &(pFontChars[(BYTE) LWR_DESCENT_CH - (BYTE) ' ']);
  3367. else
  3368. pCurChar = NULL; // default to 0
  3369. }
  3370. else
  3371. {
  3372. pCurChar = (PPSCHARMETRICS) bsearch(LWR_DESCENT_CHAR,
  3373. pFontChars[0].pPsName,
  3374. (size_t) chCnt,
  3375. sizeof(PSCHARMETRICS),
  3376. strcmp);
  3377. }
  3378. if (pCurChar != NULL)
  3379. {
  3380. pEtmInfo->etmLowerCaseDescent = (USHORT) pCurChar->rcChBBox.bottom & 0xffff;
  3381. }
  3382. else
  3383. {
  3384. pEtmInfo->etmLowerCaseDescent = 0;
  3385. }
  3386. }
  3387. return TRUE;
  3388. }
  3389. ULONG
  3390. GetAFMKernPairs(
  3391. PBYTE pAFM,
  3392. FD_KERNINGPAIR *pKernPairs,
  3393. PGLYPHSETDATA pGlyphSetData
  3394. )
  3395. /*++
  3396. Routine Description:
  3397. Given a memory mapped AFM file ptr and a ptr to a GLYPHSETDATA which
  3398. describes the supported charset for the font, fill memory with a list of
  3399. FD_KERNINGPAIR structs which provide pair kerning information.
  3400. Arguments:
  3401. pAFM - Pointer to memory mapped AFM file.
  3402. pKernPairs - If NULL, this is a size request and the function returns the
  3403. total size in bytes of all FD_KERNINGPAIR structs required for this font.
  3404. Otherwise the ptr is assumed to point to a buffer large enough to
  3405. hold the number of required FD_KERNINGPAIRs.
  3406. pGlyphSetData - Points to a GLYPHSETDATA structure which describes the
  3407. Unicode->code point mappings for the charset to be used with this font.
  3408. Return Value:
  3409. 0 => no kerning.
  3410. Otherwise returns number of FD_KERNINGPAIR structs required for this font.
  3411. --*/
  3412. {
  3413. PBYTE pKernData;
  3414. PBYTE pToken;
  3415. PUPSCODEPT pKernStrtChar, pKernEndChar;
  3416. PGLYPHRUN pGlyphRuns;
  3417. ULONG i, cMaxKernPairs, cKernPairs;
  3418. BOOLEAN bFound;
  3419. //
  3420. // for the time being, no kerning for Pi or CJK fonts.
  3421. //
  3422. if (IsPiFont(pAFM) || IsCJKFont(pAFM))
  3423. {
  3424. return(FALSE);
  3425. }
  3426. //
  3427. // Is there kerning info for this font?
  3428. //
  3429. if ((pKernData = FindAFMToken(pAFM, PS_KERN_DATA_TOK)) == NULL)
  3430. {
  3431. //
  3432. // There is no kerning info for this font.
  3433. //
  3434. return(FALSE);
  3435. }
  3436. //
  3437. // Get ptr to AFM kerning data.
  3438. //
  3439. if ((pKernData = FindAFMToken(pAFM, PS_NUM_KERN_PAIRS_TOK)) == NULL)
  3440. {
  3441. //
  3442. // There is no kerning info for this font.
  3443. //
  3444. return(FALSE);
  3445. }
  3446. //
  3447. // Current pos should be the kern pair count field.
  3448. //
  3449. for (i = 0; i < (int) StrLen(pKernData); i++)
  3450. {
  3451. if (!IS_NUM(&pKernData[i]))
  3452. {
  3453. return(FALSE);
  3454. }
  3455. }
  3456. cMaxKernPairs = atoi(pKernData);
  3457. NEXT_LINE(pKernData);
  3458. cKernPairs = 0;
  3459. pGlyphRuns = (PGLYPHRUN) (MK_PTR(pGlyphSetData, dwRunOffset));
  3460. //
  3461. // Get the kern pairs from the AFM.
  3462. //
  3463. do
  3464. {
  3465. PARSE_TOKEN(pKernData, pToken);
  3466. if (!StrCmp(pToken, PS_KERN_PAIR_TOK))
  3467. {
  3468. //
  3469. // Kern pair token found. Get Unicode id for start and end
  3470. // chars. Determine if these chars are supported in the
  3471. // charset to be used with the current font.
  3472. //
  3473. if((pKernStrtChar = (PUPSCODEPT) bsearch(pKernData,
  3474. PstoUnicode,
  3475. (size_t) NUM_PS_CHARS,
  3476. sizeof(UPSCODEPT),
  3477. CmpUnicodePsNames)) == NULL)
  3478. {
  3479. //
  3480. // No Unicode code pt for this char.
  3481. //
  3482. break;
  3483. }
  3484. //
  3485. // Determine if the char is present in the Unicode runs for
  3486. // this glyphset.
  3487. //
  3488. bFound = FALSE;
  3489. for (i = 0; i < pGlyphSetData->dwRunCount &&
  3490. pKernStrtChar->wcUnicodeid >= pGlyphRuns[i].wcLow &&
  3491. !bFound;
  3492. i++)
  3493. {
  3494. bFound =
  3495. pKernStrtChar->wcUnicodeid <
  3496. pGlyphRuns[i].wcLow + pGlyphRuns[i].wGlyphCount;
  3497. }
  3498. if (!bFound)
  3499. {
  3500. //
  3501. // Char is not supported, so ignore this kern pair.
  3502. //
  3503. NEXT_LINE(pKernData);
  3504. break;
  3505. }
  3506. //
  3507. // Get the 2nd char in the kern pair.
  3508. //
  3509. PARSE_TOKEN(pKernData, pToken);
  3510. //
  3511. // Determine if the 2nd char is supported in this charset.
  3512. //
  3513. if((pKernEndChar = (PUPSCODEPT) bsearch(pKernData,
  3514. PstoUnicode,
  3515. (size_t) NUM_PS_CHARS,
  3516. sizeof(UPSCODEPT),
  3517. CmpUnicodePsNames)) == NULL)
  3518. {
  3519. //
  3520. // No Unicode code pt for this char.
  3521. //
  3522. break;
  3523. }
  3524. //
  3525. // Determine if the char is present in the Unicode runs for
  3526. // this glyphset.
  3527. //
  3528. bFound = FALSE;
  3529. for (i = 0; i < pGlyphSetData->dwRunCount &&
  3530. pKernEndChar->wcUnicodeid >= pGlyphRuns[i].wcLow &&
  3531. !bFound;
  3532. i++)
  3533. {
  3534. bFound =
  3535. pKernEndChar->wcUnicodeid <
  3536. pGlyphRuns[i].wcLow + pGlyphRuns[i].wGlyphCount;
  3537. }
  3538. if (!bFound)
  3539. {
  3540. //
  3541. // Char is not supported, so ignore this kern pair.
  3542. //
  3543. NEXT_LINE(pKernData);
  3544. break;
  3545. }
  3546. //
  3547. // Account for another kern pair.
  3548. //
  3549. if (pKernPairs != NULL)
  3550. {
  3551. pKernPairs[cKernPairs].wcFirst = pKernStrtChar->wcUnicodeid;
  3552. pKernPairs[cKernPairs].wcSecond = pKernEndChar->wcUnicodeid;
  3553. PARSE_TOKEN(pKernData, pToken);
  3554. pKernPairs[cKernPairs].fwdKern = (FWORD)atoi(pKernData);
  3555. }
  3556. cKernPairs++;
  3557. }
  3558. else if (!StrCmp(pToken, PS_EOF_TOK) ||
  3559. !StrCmp(pToken, PS_END_KERN_PAIRS_TOK))
  3560. {
  3561. break;
  3562. }
  3563. NEXT_TOKEN(pKernData);
  3564. } while (cKernPairs < cMaxKernPairs);
  3565. if (pKernPairs != NULL)
  3566. {
  3567. //
  3568. // Sort kerning pairs by key = wcSecond << 16 + wcFIrst.
  3569. //
  3570. qsort(pKernPairs, (size_t) cKernPairs, (size_t) sizeof(FD_KERNINGPAIR),
  3571. CmpKernPairs);
  3572. //
  3573. // Array of kerning pairs is terminated by a FD_KERNINGPAIR with
  3574. // all fields set to 0.
  3575. //
  3576. pKernPairs[cKernPairs].wcFirst = 0;
  3577. pKernPairs[cKernPairs].wcSecond = 0;
  3578. pKernPairs[cKernPairs].fwdKern = 0;
  3579. }
  3580. return(cKernPairs);
  3581. }
  3582. ULONG
  3583. BuildPSFamilyTable(
  3584. PBYTE pDatFile,
  3585. PTBL *pPsFamilyTbl,
  3586. ULONG ulFileSize
  3587. )
  3588. /*++
  3589. Routine Description:
  3590. Builds a table of PSFAMILYINFO structs from a text file of font info.
  3591. The table is sorted in family name sequence. See the file PSFAMILY.DAT
  3592. for info on the input file format.
  3593. Arguments:
  3594. pDatFile - Ptr to memory mapped file image of .DAT file.
  3595. pPsFamilyTbl - Ptr to memory to contain a ptr to a table of PSFAMILYINFO
  3596. structs, which will be sorted in sFamilyName order.
  3597. ulFileSize - size in bytes of memory mapped file stream.
  3598. Return Value:
  3599. Number of entries in newly created table pointed to by *pPsFamilyTbl.
  3600. 0 => error
  3601. --*/
  3602. {
  3603. USHORT cFams;
  3604. ULONG i, j;
  3605. CHAR pFamilyType[CHAR_NAME_LEN];
  3606. CHAR pPitchType[CHAR_NAME_LEN];
  3607. CHAR *pStartLine;
  3608. ULONG cNameSize, cEngFamilyNameSize;
  3609. ULONG cFamilyTypeSize, cFamilyNameSize;
  3610. ULONG cDelimiters;
  3611. PPSFAMILYINFO pPsFontFamMap;
  3612. //
  3613. // Make a pass through the file to determine number of families.
  3614. //
  3615. i = 0;
  3616. cFams = 0;
  3617. do
  3618. {
  3619. cDelimiters = 0;
  3620. //
  3621. // Skip leading whitespace.
  3622. //
  3623. while (IS_WHTSPACE(&pDatFile[i]) && i < ulFileSize)
  3624. i++;
  3625. //
  3626. // We're at start of new line. If this is a comment, skip
  3627. // this line.
  3628. //
  3629. if (IS_COMMENT(&pDatFile[i]))
  3630. while (i <= ulFileSize && !EOL(&pDatFile[i]))
  3631. i++;
  3632. while (!EOL(&pDatFile[i]) && i < ulFileSize)
  3633. {
  3634. //
  3635. // Search for lines with 3 ':' delimiters.
  3636. //
  3637. if (pDatFile[i++] == ':')
  3638. {
  3639. cDelimiters++;
  3640. }
  3641. }
  3642. if (cDelimiters >= 3)
  3643. {
  3644. //
  3645. // Found another family name mapping.
  3646. //
  3647. cFams++;
  3648. }
  3649. } while (i < ulFileSize);
  3650. //
  3651. // Allocate memory for family info table.
  3652. //
  3653. if ((*pPsFamilyTbl =
  3654. (PTBL) MemAllocZ((size_t) (cFams * sizeof(PSFAMILYINFO)) + sizeof(TBL))) == NULL)
  3655. return(FALSE);
  3656. (*pPsFamilyTbl)->pTbl = (PVOID) ((ULONG_PTR) *pPsFamilyTbl + sizeof(TBL));
  3657. pPsFontFamMap = (PPSFAMILYINFO) ((*pPsFamilyTbl)->pTbl);
  3658. //
  3659. // Parse file again, building table of PSFAMILYINFOs.
  3660. //
  3661. i = 0;
  3662. cFams = 0;
  3663. do
  3664. {
  3665. //
  3666. // Skip leading whitespace.
  3667. //
  3668. while (IS_WHTSPACE(&pDatFile[i]) && i < ulFileSize)
  3669. i++;
  3670. //
  3671. // We're at start of new line. If this is a comment, skip
  3672. // this line.
  3673. //
  3674. if (IS_COMMENT(&pDatFile[i]))
  3675. while (i <= ulFileSize && !EOL(&pDatFile[i]))
  3676. i++;
  3677. else
  3678. pStartLine = &pDatFile[i];
  3679. while (!EOL(&pDatFile[i]) && i < ulFileSize)
  3680. //
  3681. // Search for lines with 3 ':' delimiters.
  3682. //
  3683. if (pDatFile[i++] == ':')
  3684. {
  3685. //
  3686. // Check for English family name mapping.
  3687. //
  3688. if (pDatFile[i] == ':')
  3689. {
  3690. cEngFamilyNameSize = 0;
  3691. }
  3692. else if ((cEngFamilyNameSize = StrPos(&pDatFile[i], ':')) == -1)
  3693. {
  3694. //
  3695. // No more delimeters on this line, skip it.
  3696. //
  3697. i += StrLen(&pDatFile[i]);
  3698. break;
  3699. }
  3700. i += cEngFamilyNameSize + 1;
  3701. //
  3702. // Check for another family name mapping. If present, build
  3703. // a FAMILYINFO struct for it.
  3704. //
  3705. if ((cFamilyNameSize = StrPos(&pDatFile[i], ':')) == -1)
  3706. {
  3707. //
  3708. // No more delimeters on this line, skip it.
  3709. //
  3710. i += StrLen(&pDatFile[i]);
  3711. break;
  3712. }
  3713. i += cFamilyNameSize + 1;
  3714. //
  3715. // Check for font family type name
  3716. //
  3717. if ((cFamilyTypeSize = StrPos(&pDatFile[i], ':')) != -1)
  3718. {
  3719. i += cFamilyTypeSize + 1;
  3720. }
  3721. else
  3722. {
  3723. cFamilyTypeSize = 0;
  3724. }
  3725. //
  3726. // Make sure there are still chars for Win family type name
  3727. // or pitch name.
  3728. //
  3729. if (EOL(&pDatFile[i]) || i >= ulFileSize)
  3730. {
  3731. //
  3732. // Just ran out of file buffer.
  3733. //
  3734. break;
  3735. }
  3736. //
  3737. // Get the font and family names.
  3738. //
  3739. cNameSize = StrPos(pStartLine, ':');
  3740. memcpy(pPsFontFamMap[cFams].pFontName, pStartLine, cNameSize);
  3741. pPsFontFamMap[cFams].pFontName[cNameSize] = '\0';
  3742. pStartLine += cNameSize + 1;
  3743. if (cEngFamilyNameSize)
  3744. {
  3745. memcpy(pPsFontFamMap[cFams].pEngFamilyName, pStartLine, cEngFamilyNameSize);
  3746. pPsFontFamMap[cFams].pEngFamilyName[cEngFamilyNameSize] = '\0';
  3747. }
  3748. pStartLine += cEngFamilyNameSize + 1;
  3749. memcpy(pPsFontFamMap[cFams].FamilyKey.pName, pStartLine, cFamilyNameSize);
  3750. pPsFontFamMap[cFams].FamilyKey.pName[cFamilyNameSize] = '\0';
  3751. // if cFamilyTypeSize != 0, means there must be a pitch name
  3752. if (cFamilyTypeSize)
  3753. {
  3754. pStartLine += cFamilyNameSize + 1;
  3755. memcpy(pFamilyType, pStartLine, cFamilyTypeSize);
  3756. pFamilyType[cFamilyTypeSize] = '\0';
  3757. AFM2NTMStrCpy(pPitchType, CCHOF(pPitchType), &pDatFile[i]);
  3758. i += strlen(pPitchType);
  3759. }
  3760. else
  3761. {
  3762. //
  3763. // Get Win family type name (e.g. Swiss, Roman, etc.). Store
  3764. // appropriate family type value in the FAMILYINFO.
  3765. //
  3766. AFM2NTMStrCpy(pFamilyType, CCHOF(pFamilyType), &pDatFile[i]);
  3767. i += strlen(pFamilyType);
  3768. }
  3769. //
  3770. // Search for family type in table. Default is FF_DONTCARE.
  3771. //
  3772. pPsFontFamMap[cFams].FamilyKey.usValue = FF_DONTCARE;
  3773. for (j = 0; j < FamilyKeyTbl.usNumEntries; j++)
  3774. {
  3775. if (!strcmp(pFamilyType, ((PKEY) (FamilyKeyTbl.pTbl))[j].pName))
  3776. {
  3777. pPsFontFamMap[cFams].FamilyKey.usValue = ((PKEY) (FamilyKeyTbl.pTbl))[j].usValue;
  3778. break;
  3779. }
  3780. }
  3781. //
  3782. // Search for family type in table. Default is FF_DONTCARE.
  3783. //
  3784. pPsFontFamMap[cFams].usPitch = DEFAULT_PITCH;
  3785. if (cFamilyTypeSize)
  3786. {
  3787. for (j = 0; j < PitchKeyTbl.usNumEntries; j++)
  3788. {
  3789. if (!strcmp(pPitchType, ((PKEY) (PitchKeyTbl.pTbl))[j].pName))
  3790. {
  3791. pPsFontFamMap[cFams].usPitch = ((PKEY) (PitchKeyTbl.pTbl))[j].usValue;
  3792. break;
  3793. }
  3794. }
  3795. }
  3796. cFams++;
  3797. }
  3798. } while (i < ulFileSize);
  3799. (*pPsFamilyTbl)->usNumEntries = cFams;
  3800. //
  3801. // Sort FAMILYINFO table in font name order.
  3802. //
  3803. qsort(&(pPsFontFamMap[0].pFontName), (size_t) cFams,
  3804. (size_t) sizeof(PSFAMILYINFO), strcmp);
  3805. return(cFams);
  3806. }
  3807. ULONG
  3808. BuildPSCharMetrics(
  3809. PBYTE pAFM,
  3810. PULONG pUniPs,
  3811. PPSCHARMETRICS pFontChars,
  3812. PBYTE pCharDefTbl,
  3813. ULONG cGlyphSetChars
  3814. )
  3815. /*++
  3816. Routine Description:
  3817. Builds a array of bit flags used to determine if a particular char is
  3818. defined for a given font.
  3819. Arguments:
  3820. pAFM - Ptr to memory mapped file image of .AFM file.
  3821. pUniPs - Points to a table which maps 0-based Glyph Indices of chars
  3822. in the GLYPHRUNS of the GLYPHSETDATA struct for this font to indices
  3823. into the UnicodetoPs structure which maps Unicode points to PS char
  3824. information. This mapping array is created by the CreateGlyphSet function
  3825. defined in this module.
  3826. pFontChars - Ptr to memory to contains an array of PSCHARMETRICS structs,
  3827. which contains PS char name, and char width info for each char defined
  3828. in the font's AFM. The amount of memory required in bytes is
  3829. sizeof(PSCHARMETRICS) * num of chars in the font.
  3830. pCharDefTbl - Ptr to memory of size ((cGlyphSetChars + 7) /8)) bytes,
  3831. will contain bit flags indicating if a char is supported in the given font.
  3832. cGlyphSetChars - Number of chars in the GLYPHSET for this font. This
  3833. most likely is NOT the same as the number of chars defined in the
  3834. font's AFM.
  3835. Return Value:
  3836. TRUE => success
  3837. FALSE => error
  3838. --*/
  3839. {
  3840. ULONG i, j;
  3841. PBYTE pChMet, pToken;
  3842. USHORT chCnt;
  3843. ULONG curCharWidth;
  3844. PBYTE pCharNameTok;
  3845. BOOLEAN bIsPiFont, bIsCJKFont;
  3846. BYTE CharNameBuffer[32];
  3847. PBYTE pChName;
  3848. //
  3849. // Is this is a symbol font, the char "names" will actually be the
  3850. // default char codes in the AFM.
  3851. //
  3852. if (bIsPiFont = IsPiFont(pAFM))
  3853. {
  3854. pCharNameTok = PS_CH_CODE_TOK;
  3855. }
  3856. else
  3857. {
  3858. pCharNameTok = PS_CH_NAME_TOK;
  3859. }
  3860. bIsCJKFont = (IsCJKFont(pAFM) != 0);
  3861. //
  3862. // Check validity of output pointers.
  3863. //
  3864. if (pFontChars == NULL || pCharDefTbl == NULL)
  3865. {
  3866. return(FALSE);
  3867. }
  3868. //
  3869. // Get ptr to AFM char metrics.
  3870. //
  3871. pChMet = FindAFMToken(pAFM, PS_CH_METRICS_TOK);
  3872. if (pChMet == NULL) // Fixed bug 354007
  3873. return (FALSE);
  3874. //
  3875. // Current pos should be the character count field.
  3876. //
  3877. for (i = 0; i < (int) StrLen(pChMet); i++)
  3878. {
  3879. if (!IS_NUM(&pChMet[i]))
  3880. {
  3881. return(FALSE);
  3882. }
  3883. }
  3884. chCnt = (USHORT)atoi(pChMet);
  3885. (ULONG_PTR) pChMet += i;
  3886. //
  3887. // Make a pass through the AFM Char Metrics, creating an array of
  3888. // PSCHARMETRICS structs.
  3889. //
  3890. i = 0;
  3891. do
  3892. {
  3893. PARSE_TOKEN(pChMet, pToken);
  3894. if (!StrCmp(pToken, PS_CH_WIDTH_TOK) ||
  3895. !StrCmp(pToken, PS_CH_WIDTH0_TOK))
  3896. {
  3897. pFontChars[i].chWidth = atoi(pChMet);
  3898. }
  3899. if (!StrCmp(pToken, pCharNameTok))
  3900. {
  3901. AFM2NTMStrCpy(pFontChars[i].pPsName, CCHOF(pFontChars[i].pPsName), pChMet);
  3902. }
  3903. if (!StrCmp(pToken, PS_CH_BBOX_TOK))
  3904. {
  3905. //
  3906. // Save char bounding box.
  3907. //
  3908. PARSE_RECT(pChMet, pFontChars[i].rcChBBox);
  3909. i++;
  3910. }
  3911. else if (!StrCmp(pToken, PS_EOF_TOK))
  3912. {
  3913. break;
  3914. }
  3915. NEXT_TOKEN(pChMet);
  3916. } while (i < chCnt);
  3917. //
  3918. // Sort the list of PSCHARMETRICSs in PS Name sequence. If this is
  3919. // a Pi font, chars are already sorted in CC order.
  3920. //
  3921. if (!bIsPiFont)
  3922. {
  3923. qsort(pFontChars, (size_t) chCnt, (size_t) sizeof(PSCHARMETRICS),
  3924. CmpPsChars);
  3925. }
  3926. //
  3927. // Build array of bit flags which indicate whether each char in the
  3928. // GLYPHSETDATA is actually defined in the AFM.
  3929. //
  3930. for (i = 0; i < ((cGlyphSetChars + 7) / 8); i++)
  3931. {
  3932. pCharDefTbl[i] = 0;
  3933. }
  3934. for (i = 0; i < cGlyphSetChars; i++)
  3935. {
  3936. if (bIsPiFont)
  3937. {
  3938. //
  3939. // Make the first char (0x1f:'.notdef1f') undefined.
  3940. //
  3941. if (i == 0)
  3942. continue;
  3943. //
  3944. // Char is defined unless there are < 256 chars in the font.
  3945. //
  3946. if (i < chCnt)
  3947. DEFINE_CHAR(i, pCharDefTbl);
  3948. else
  3949. break;
  3950. }
  3951. else
  3952. {
  3953. //
  3954. // Setup ptr to "char name" based on whether this is a
  3955. // western or CJK font.
  3956. //
  3957. if (bIsCJKFont)
  3958. {
  3959. // Make CID 0 undefined glyph.
  3960. if (pUniPs[i] == 0)
  3961. continue;
  3962. _ultoa(pUniPs[i], CharNameBuffer, 10);
  3963. pChName = CharNameBuffer;
  3964. }
  3965. else
  3966. {
  3967. pChName = UnicodetoPs[pUniPs[i]].pPsName;
  3968. }
  3969. if (((PPSCHARMETRICS) bsearch(pChName,
  3970. pFontChars,
  3971. (size_t) chCnt,
  3972. sizeof(PSCHARMETRICS),
  3973. CmpPsChars)) != NULL)
  3974. {
  3975. //
  3976. // Char is defined in this font.
  3977. //
  3978. DEFINE_CHAR(i, pCharDefTbl);
  3979. }
  3980. }
  3981. }
  3982. return(TRUE);
  3983. }
  3984. ULONG
  3985. cjGetFamilyAliases(
  3986. IFIMETRICS *pifi,
  3987. PSTR pstr,
  3988. UINT cp
  3989. )
  3990. /*++
  3991. Routine Description:
  3992. Fill in the family name of the IFIMETRICS structure.
  3993. Arguments:
  3994. pifi - Ptr to IFIMETRICS. If NULL, return size of family alias strings
  3995. only.
  3996. pstr - Ptr to null terminated Font Menu Name string.
  3997. cp - Codepage value.
  3998. Return Value:
  3999. ?
  4000. --*/
  4001. {
  4002. PSTR *pTable;
  4003. PWSTR pwstr;
  4004. DWORD cWchars, cw;
  4005. ULONG ulLength;
  4006. // assume no alias table found.
  4007. pTable = (PSTR *)(NULL);
  4008. // This is a hardcoded Win31 Hack that we need to be compatible
  4009. // with since some apps have hardcoded font names.
  4010. if (!(strcmp(pstr, "Times")))
  4011. pTable = TimesAlias;
  4012. else if (!(strcmp(pstr, "Helvetica")))
  4013. pTable = HelveticaAlias;
  4014. #if 0
  4015. // Disabled due to bug #259664 fix
  4016. else if (!(strcmp(pstr, "Courier")))
  4017. pTable = CourierAlias;
  4018. #endif
  4019. else if (!(strcmp(pstr, "Helvetica Narrow")))
  4020. pTable = HelveticaNarrowAlias;
  4021. else if (!(strcmp(pstr, "Palatino")))
  4022. pTable = PalatinoAlias;
  4023. else if (!(strcmp(pstr, "Bookman")))
  4024. pTable = BookmanAlias;
  4025. else if (!(strcmp(pstr, "NewCenturySchlbk")))
  4026. pTable = NewCenturySBAlias;
  4027. else if (!(strcmp(pstr, "AvantGarde")))
  4028. pTable = AvantGardeAlias;
  4029. else if (!(strcmp(pstr, "ZapfChancery")))
  4030. pTable = ZapfChanceryAlias;
  4031. else if (!(strcmp(pstr, "ZapfDingbats")))
  4032. pTable = ZapfDingbatsAlias;
  4033. //
  4034. // If font name does not match any of the family alias names,
  4035. // use font name itself as IFIMETRICS family name.
  4036. //
  4037. if (pTable == NULL)
  4038. {
  4039. ulLength = strlen(pstr);
  4040. cWchars = MultiByteToWideChar(cp, 0, pstr, ulLength, 0, 0);
  4041. if (pifi != NULL)
  4042. {
  4043. pwstr = (PWSTR)MK_PTR(pifi, dpwszFamilyName);
  4044. MultiByteToWideChar(cp, 0, pstr, ulLength, pwstr, cWchars);
  4045. pwstr[cWchars]= (WCHAR)'\0';
  4046. }
  4047. return((cWchars + 1) * sizeof (WCHAR));
  4048. }
  4049. //
  4050. // A family alias name match was found.
  4051. //
  4052. if (pifi != NULL)
  4053. {
  4054. //
  4055. // This call is a request to actually copy the string table.
  4056. //
  4057. pwstr = (PWSTR)MK_PTR(pifi, dpwszFamilyName);
  4058. pifi->flInfo |= FM_INFO_FAMILY_EQUIV;
  4059. }
  4060. cWchars = 0;
  4061. while (*pTable)
  4062. {
  4063. ulLength = strlen(*pTable);
  4064. cw = MultiByteToWideChar(cp, 0, *pTable, ulLength, 0, 0);
  4065. if (pifi != NULL)
  4066. {
  4067. MultiByteToWideChar(cp, 0, *pTable, ulLength, &pwstr[cWchars], cw);
  4068. pwstr[cWchars + cw] = (WCHAR)'\0';
  4069. }
  4070. cWchars += cw + 1;
  4071. pTable++;
  4072. }
  4073. if (pifi != NULL)
  4074. {
  4075. //
  4076. // Add terminator to end of string array.
  4077. //
  4078. pwstr[cWchars] = (WCHAR)'\0';
  4079. }
  4080. return((cWchars + 1) * sizeof(WCHAR));
  4081. }
  4082. PBYTE
  4083. FindStringToken(
  4084. PBYTE pPSFile,
  4085. PBYTE pToken
  4086. )
  4087. /*++
  4088. Routine Description:
  4089. Find the first occurrence of pToken occurring in the stream pPSFile.
  4090. pToken is terminated by the first occurrence of a space or NULL char.
  4091. Arguments:
  4092. pPSFile - Ptr to memory mapped file stream to search.
  4093. pToken - Ptr to string token to search for.
  4094. Return Value:
  4095. !=NULL => ptr to first occurence of pToken
  4096. ==NULL => token not found
  4097. --*/
  4098. {
  4099. while (TRUE)
  4100. {
  4101. while (IS_WHTSPACE(pPSFile) && !EOL(pPSFile))
  4102. {
  4103. pPSFile++;
  4104. }
  4105. if (!StrCmp(pPSFile, DSC_EOF_TOK))
  4106. {
  4107. break;
  4108. }
  4109. else if (!StrCmp(pPSFile, pToken))
  4110. {
  4111. return(pPSFile);
  4112. }
  4113. else
  4114. {
  4115. pPSFile += StrLen(pPSFile) + 1;
  4116. }
  4117. }
  4118. return(FALSE);
  4119. }
  4120. BOOLEAN
  4121. AsciiToHex(
  4122. PBYTE pStr,
  4123. PUSHORT pNum
  4124. )
  4125. /*++
  4126. Routine Description:
  4127. Treat the the space or null terminated input string as a series of hex
  4128. digits convert it to a USHORT.
  4129. Arguments:
  4130. pStr - Ptr to string to convert.
  4131. pNum - Ptr to variable which returns numeric value.
  4132. Return Value:
  4133. TRUE => String converted
  4134. FALSE => String could not be converted
  4135. --*/
  4136. {
  4137. USHORT usHexNum, ulDigit;
  4138. CHAR curChar;
  4139. usHexNum = 0;
  4140. while (!EOL(pStr) && !IS_HEX_DIGIT(pStr))
  4141. {
  4142. pStr++;
  4143. }
  4144. for( ; IS_HEX_DIGIT(pStr); pStr++);
  4145. ulDigit = 1;
  4146. for (pStr--; IS_HEX_DIGIT(pStr) && !EOL(pStr) && ulDigit; pStr--)
  4147. {
  4148. if (IS_NUM(pStr))
  4149. {
  4150. usHexNum += (*pStr - '0') * ulDigit;
  4151. }
  4152. else
  4153. {
  4154. curChar = (CHAR)toupper(*pStr);
  4155. usHexNum += ((curChar - 'A') + 10) * ulDigit;
  4156. }
  4157. ulDigit <<= 4;
  4158. }
  4159. if (usHexNum)
  4160. {
  4161. *pNum = usHexNum;
  4162. return(TRUE);
  4163. }
  4164. else
  4165. {
  4166. return(FALSE);
  4167. }
  4168. }
  4169. BOOLEAN
  4170. IsPiFont(
  4171. PBYTE pAFM
  4172. )
  4173. /*++
  4174. Routine Description:
  4175. Determine if the font represented by the passed AFM is a font which
  4176. uses the Symbol charset.
  4177. Arguments:
  4178. pAFM - Ptr to AFM.
  4179. Return Value:
  4180. TRUE => Font is PI font, uses "Symbol" Glyphset
  4181. FALSE => Font not PI font
  4182. --*/
  4183. {
  4184. // This routine used to do a lot more. Should change
  4185. // to a macro later.
  4186. return((BOOLEAN)isSymbolCharSet);
  4187. }
  4188. BOOLEAN
  4189. IsCJKFixedPitchEncoding(
  4190. PGLYPHSETDATA pGlyphSetData
  4191. )
  4192. /*++
  4193. Routine Description:
  4194. Determine if the encoding is the one for fixed pitch font.
  4195. Arguments:
  4196. pGlyphSetData - Ptr to GLYPHSETDATA
  4197. Return Value:
  4198. TRUE => Fixed pitch font's encoding
  4199. FALSE => Proportional font's encoding
  4200. --*/
  4201. {
  4202. BOOLEAN bResult;
  4203. char* pszGlyphSetName;
  4204. char** pszPropCjkGsName;
  4205. bResult = TRUE;
  4206. pszGlyphSetName = (char*)MK_PTR(pGlyphSetData, dwGlyphSetNameOffset);
  4207. for (pszPropCjkGsName = PropCjkGsNames; *pszPropCjkGsName; pszPropCjkGsName++)
  4208. {
  4209. if (!strcmp(pszGlyphSetName, *pszPropCjkGsName))
  4210. {
  4211. bResult = FALSE;
  4212. break;
  4213. }
  4214. }
  4215. return bResult;
  4216. }
  4217. PBYTE
  4218. FindUniqueID(
  4219. PBYTE pAFM
  4220. )
  4221. /*++
  4222. Routine Description:
  4223. Finds UniqueID token in a memory mapped AFM file stream.
  4224. UniqueID is assumed on 'Comment UniqueID' line.
  4225. Arguments:
  4226. pAFM - pointer to memory mapped AFM file.
  4227. Return Value:
  4228. NULL => error
  4229. otherwise => ptr to UniqueID value.
  4230. --*/
  4231. {
  4232. PBYTE pCurToken;
  4233. while (TRUE)
  4234. {
  4235. PARSE_TOKEN(pAFM, pCurToken);
  4236. if (!StrCmp(pCurToken, PS_COMMENT_TOK))
  4237. {
  4238. if (!StrCmp(pAFM, "UniqueID"))
  4239. {
  4240. pAFM += 8;
  4241. while (IS_WHTSPACE(pAFM)) pAFM++;
  4242. return pAFM;
  4243. }
  4244. }
  4245. else if (!StrCmp(pCurToken, PS_EOF_TOK))
  4246. {
  4247. return NULL;
  4248. }
  4249. NEXT_LINE(pAFM);
  4250. }
  4251. return NULL;
  4252. }