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.

2084 lines
60 KiB

  1. /*++
  2. Copyright (c) 1996-1997 Microsoft Corporation
  3. Module Name:
  4. pfmconv.c
  5. Abstract:
  6. Windows NT utilities to handle new font format
  7. Environment:
  8. Windows NT Universal printer driver
  9. Revision History:
  10. 10/31/96 -eigos-
  11. Created it.
  12. --*/
  13. #include "precomp.h"
  14. //
  15. // Internal macros
  16. //
  17. #define DRIVERINFO_VERSION_WIN31 0x0100
  18. #define DRIVERINFO_VERSION_SIMULATE 0x0150
  19. #define DRIVERINFO_VERSION 0x0200
  20. #define FONT_SIM_NO_ITALIC 1
  21. #define FONT_SIM_NO_BOLD 2
  22. #define FONT_SIM_DJ_BOLD 4
  23. //
  24. // HP DeskJet permutation flags
  25. //
  26. #define HALF_PITCH 0x01
  27. #define DOUBLE_PITCH 0x02
  28. #define HALF_HEIGHT 0x04
  29. #define MAKE_BOLD 0x08
  30. #define BASE_BOLD_MASK 0x30
  31. #define BASE_BOLD_SHIFT 4
  32. #define BASE_BOLD_ADD_0 0x00
  33. #define BASE_BOLD_ADD_1 0x10
  34. #define BASE_BOLD_ADD_2 0x20
  35. #define BASE_BOLD_ADD_3 0x30
  36. // 6/6/97 yasuho: Some PFM have -1 value in wPrivateData.
  37. #define DO_DJFONTSIMBOLD(pFInData) ((pFInData->DI.wPrivateData != 0xFFFF) && (pFInData->DI.wPrivateData & MAKE_BOLD))
  38. #define DO_FONTSIM(pFInData) \
  39. (((pFInData)->DI.sVersion == DRIVERINFO_VERSION_WIN31) || \
  40. ((pFInData)->DI.sVersion == DRIVERINFO_VERSION_SIMULATE) || \
  41. IS_DBCSCHARSET((pFInData)->PFMH.dfCharSet) )
  42. #define DWORD_ALIGN(p) ((((ULONG)(p)) + 3) & ~3)
  43. #define IS_DBCSCTTTYPE(sCTT) \
  44. ( ((sCTT) == CTT_JIS78) \
  45. || ((sCTT) == CTT_JIS78_ANK) \
  46. || ((sCTT) == CTT_JIS83) \
  47. || ((sCTT) == CTT_JIS83_ANK) \
  48. || ((sCTT) == CTT_NS86) \
  49. || ((sCTT) == CTT_TCA) \
  50. || ((sCTT) == CTT_BIG5) \
  51. || ((sCTT) == CTT_ISC))
  52. #define CTT_TYPE_TO_CHARSET(sCTT) \
  53. (((sCTT) == CTT_JIS78) ? SHIFTJIS_CHARSET : \
  54. (((sCTT) == CTT_JIS78_ANK) ? SHIFTJIS_CHARSET : \
  55. (((sCTT) == CTT_JIS83) ? SHIFTJIS_CHARSET : \
  56. (((sCTT) == CTT_JIS83_ANK) ? SHIFTJIS_CHARSET : \
  57. (((sCTT) == CTT_NS86) ? CHINESEBIG5_CHARSET : \
  58. (((sCTT) == CTT_TCA) ? CHINESEBIG5_CHARSET : \
  59. (((sCTT) == CTT_BIG5) ? CHINESEBIG5_CHARSET : \
  60. (((sCTT) == CTT_ISC) ? HANGEUL_CHARSET : 1))))))))
  61. #define OUTPUT_VERBOSE 0x00000001
  62. #define BBITS 8
  63. #define DWBITS (BBITS * sizeof( DWORD ))
  64. #define DW_MASK (DWBITS - 1)
  65. //
  66. // Definitions
  67. //
  68. extern DWORD gdwOutputFlags;
  69. typedef VOID (*VPRINT) (char*,...);
  70. //
  71. // Internal function prorotypes
  72. //
  73. BOOL BCreateWidthTable( IN HANDLE, IN PWORD, IN WORD, IN WORD, IN PSHORT, OUT PWIDTHTABLE *, OUT PDWORD);
  74. BOOL BCreateKernData( IN HANDLE, IN w3KERNPAIR*, IN DWORD, OUT PKERNDATA*, OUT PDWORD);
  75. WORD WGetGlyphHandle(PUNI_GLYPHSETDATA, WORD);
  76. PUNI_GLYPHSETDATA PGetDefaultGlyphset( IN HANDLE, IN WORD, IN WORD, IN DWORD);
  77. LONG LCtt2Cc(IN SHORT, IN SHORT);
  78. //
  79. //
  80. // PFM file handling functions
  81. //
  82. //
  83. BOOL
  84. BFontInfoToIFIMetric(
  85. IN HANDLE hHeap,
  86. IN FONTIN *pFInData,
  87. IN PWSTR pwstrUniqNm,
  88. IN DWORD dwCodePageOfFacenameConv,
  89. IN OUT PIFIMETRICS *ppIFI,
  90. IN OUT PDWORD pdwSize,
  91. IN DWORD dwFlags)
  92. /*++
  93. Routine Description:
  94. Convert the Win 3.1 format PFM data to NT's IFIMETRICS. This is
  95. typically done before the minidrivers are built, so that they
  96. can include IFIMETRICS, and thus have less work to do at run time.
  97. Arguments:
  98. pFInData - Font data info for conversion
  99. pwstrUniqNm - Unique name component
  100. Return Value:
  101. TRUE if successfull, otherwise FALSE.
  102. --*/
  103. {
  104. FONTSIM *pFontSim;
  105. FONTDIFF *pfdiffBold = 0, *pfdiffItalic = 0, *pfdiffBoldItalic = 0;
  106. PIFIEXTRA pIFIExtra;
  107. FWORD fwdExternalLeading;
  108. INT icWChar; /* Number of WCHARS to add */
  109. INT icbAlloc; /* Number of bytes to allocate */
  110. INT iI; /* Loop index */
  111. INT iCount; /* Number of characters in Win 3.1 font */
  112. WCHAR *pwchTmp; /* For string manipulations */
  113. WCHAR awcAttrib[ 256 ]; /* Generate attributes + BYTE -> WCHAR */
  114. BYTE abyte[ 256 ]; /* Used (with above) to get wcLastChar etc */
  115. WORD fsFontSim = 0;
  116. INT cFontDiff;
  117. UINT uiCodePage;
  118. CHARSETINFO ci;
  119. //
  120. // Calculate the size of three face names buffer
  121. //
  122. icWChar = 3 * strlen( pFInData->pBase + pFInData->PFMH.dfFace );
  123. //
  124. // Produce the desired attributes: Italic, Bold, Light etc.
  125. // This is largely guesswork, and there should be a better method.
  126. // Write out an empty string
  127. //
  128. awcAttrib[ 0 ] = L'\0';
  129. awcAttrib[ 1 ] = L'\0';
  130. if( pFInData->PFMH.dfItalic )
  131. {
  132. StringCchCatW( awcAttrib, CCHOF(awcAttrib), L" Italic" );
  133. }
  134. if( pFInData->PFMH.dfWeight >= 700 )
  135. {
  136. StringCchCatW( awcAttrib, CCHOF(awcAttrib), L" Bold" );
  137. }
  138. else if( pFInData->PFMH.dfWeight < 200 )
  139. {
  140. StringCchCatW( awcAttrib, CCHOF(awcAttrib), L" Light" );
  141. }
  142. //
  143. // The attribute string appears in 3 entries of IFIMETRICS, so
  144. // calculate how much storage this will take. NOTE THAT THE LEADING
  145. // CHAR IN awcAttrib is NOT placed in the style name field, so we
  146. // subtract one in the following formula to account for this.
  147. //
  148. if( awcAttrib[ 0 ] )
  149. {
  150. icWChar += 3 * wcslen( awcAttrib ) - 1;
  151. }
  152. //
  153. // Should be printer name
  154. //
  155. icWChar += wcslen( pwstrUniqNm ) + 1;
  156. //
  157. // Terminating nulls
  158. //
  159. icWChar += 4;
  160. //
  161. // Total size of IFIMETRICS structure
  162. //
  163. icbAlloc = DWORD_ALIGN(sizeof( IFIMETRICS ) + sizeof( WCHAR ) * icWChar);
  164. //
  165. // For HeskJet font.
  166. //
  167. if (DO_DJFONTSIMBOLD(pFInData))
  168. {
  169. fsFontSim |= FONT_SIM_DJ_BOLD;
  170. icbAlloc = DWORD_ALIGN(icbAlloc) +
  171. DWORD_ALIGN(sizeof(FONTSIM)) +
  172. DWORD_ALIGN(sizeof(FONTDIFF));
  173. }
  174. else
  175. //
  176. // For CJK font.
  177. // Judge which font simulation to be enabled, then allocate the
  178. // necessary storage.
  179. //
  180. if (DO_FONTSIM(pFInData) || pFInData->dwFlags & FLAG_FONTSIM)
  181. {
  182. cFontDiff = 4;
  183. //
  184. // Decide which attribute should be diabled. We won't simulate
  185. // if the user does not desires it. We won't italicize in case
  186. // it is an italic font, etc.
  187. //
  188. if ( pFInData->PFMH.dfItalic || (pFInData->DI.fCaps & DF_NOITALIC))
  189. {
  190. fsFontSim |= FONT_SIM_NO_ITALIC;
  191. cFontDiff /= 2;
  192. }
  193. if( pFInData->PFMH.dfWeight >= 700 || (pFInData->DI.fCaps & DF_NO_BOLD))
  194. {
  195. fsFontSim |= FONT_SIM_NO_BOLD;
  196. cFontDiff /= 2;
  197. }
  198. cFontDiff--;
  199. if ( cFontDiff > 0)
  200. {
  201. icbAlloc = DWORD_ALIGN(icbAlloc);
  202. icbAlloc += (DWORD_ALIGN(sizeof(FONTSIM)) +
  203. cFontDiff * DWORD_ALIGN(sizeof(FONTDIFF)));
  204. }
  205. }
  206. #if DBG
  207. DbgPrint( "cFontDiff = %d", cFontDiff);
  208. #endif
  209. //
  210. // IFIEXTRA
  211. //
  212. // Fill out IFIEXTRA.cig.
  213. //
  214. icbAlloc += sizeof(IFIEXTRA);
  215. //
  216. // Allocate memory
  217. //
  218. *ppIFI = (IFIMETRICS *)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, icbAlloc);
  219. *pdwSize = icbAlloc;
  220. if (NULL == *ppIFI)
  221. {
  222. return FALSE;
  223. }
  224. (*ppIFI)->cjThis = icbAlloc;
  225. (*ppIFI)->cjIfiExtra = 0;
  226. //
  227. // The family name: straight from the FaceName - no choice??
  228. //
  229. // -IFIMETRICS memory image-
  230. // IFIMETRICS
  231. // IFIEXTRA
  232. // FamilyName
  233. // StyleName
  234. // FaceName
  235. // UniqueName
  236. //
  237. pIFIExtra = (PIFIEXTRA)(*ppIFI + 1);
  238. pIFIExtra->dpFontSig = 0;
  239. pIFIExtra->cig = pFInData->PFMH.dfLastChar -
  240. pFInData->PFMH.dfFirstChar + 1;
  241. pIFIExtra->dpDesignVector = 0;
  242. pIFIExtra->dpAxesInfoW = 0;
  243. pwchTmp = (WCHAR*)((PBYTE)(*ppIFI + 1) + sizeof(IFIEXTRA));
  244. (*ppIFI)->dpwszFamilyName = (PTRDIFF)((BYTE *)pwchTmp - (BYTE *)(*ppIFI));
  245. if (dwCodePageOfFacenameConv)
  246. uiCodePage = dwCodePageOfFacenameConv;
  247. else
  248. uiCodePage = UlCharsetToCodePage(pFInData->PFMH.dfCharSet);
  249. DwCopyStringToUnicodeString( uiCodePage,
  250. pFInData->pBase + pFInData->PFMH.dfFace,
  251. pwchTmp,
  252. icWChar);
  253. pwchTmp += wcslen( pwchTmp ) + 1;
  254. icWChar -= wcslen( pwchTmp ) + 1;
  255. //
  256. // Now the face name: we add bold, italic etc to family name
  257. //
  258. (*ppIFI)->dpwszFaceName = (PTRDIFF)((BYTE *)pwchTmp - (BYTE *)(*ppIFI));
  259. DwCopyStringToUnicodeString( uiCodePage,
  260. pFInData->pBase + pFInData->PFMH.dfFace,
  261. pwchTmp,
  262. icWChar);
  263. StringCchCatW( pwchTmp, icWChar, awcAttrib );
  264. //
  265. // Now the unique name - well, sort of, anyway
  266. //
  267. icWChar -= (wcslen( pwchTmp ) + 1);
  268. pwchTmp += wcslen( pwchTmp ) + 1; /* Skip what we just put in */
  269. (*ppIFI)->dpwszUniqueName = (PTRDIFF)((BYTE *)pwchTmp - (BYTE *)(*ppIFI));
  270. StringCchCopyW( pwchTmp, icWChar, pwstrUniqNm ); /* Append printer name for uniqueness */
  271. StringCchCatW( pwchTmp, icWChar, L" " );
  272. StringCchCatW( pwchTmp, icWChar, (PWSTR)((BYTE *)(*ppIFI) + (*ppIFI)->dpwszFaceName) );
  273. /* Onto the attributes only component */
  274. icWChar -= (wcslen( pwchTmp ) + 1);
  275. pwchTmp += wcslen( pwchTmp ) + 1; /* Skip what we just put in */
  276. (*ppIFI)->dpwszStyleName = (PTRDIFF)((BYTE *)pwchTmp - (BYTE *)(*ppIFI));
  277. StringCchCatW( pwchTmp, icWChar, &awcAttrib[ 1 ] );
  278. #if DBG
  279. /*
  280. * Check on a few memory sizes: JUST IN CASE.....
  281. */
  282. if( (wcslen( awcAttrib ) * sizeof( WCHAR )) >= sizeof( awcAttrib ) )
  283. {
  284. DbgPrint( "BFontInfoToIFIMetrics: STACK CORRUPTED BY awcAttrib" );
  285. HeapFree(hHeap, 0, (LPSTR)(*ppIFI) ); /* No memory leaks */
  286. return FALSE;
  287. }
  288. if( ((BYTE *)(pwchTmp + wcslen( pwchTmp ) + 1)) > ((BYTE *)(*ppIFI) + icbAlloc) )
  289. {
  290. DbgPrint( "BFontInfoToIFIMetrics: IFIMETRICS overflow: Wrote to 0x%lx, allocated to 0x%lx\n",
  291. ((BYTE *)(pwchTmp + wcslen( pwchTmp ) + 1)),
  292. ((BYTE *)(*ppIFI) + icbAlloc) );
  293. HeapFree(hHeap, 0, (LPSTR)(*ppIFI) ); /* No memory leaks */
  294. return 0;
  295. }
  296. #endif
  297. pwchTmp += wcslen( pwchTmp ) + 1; /* Skip what we just put in */
  298. //
  299. // For HeskJet font.
  300. //
  301. if (fsFontSim & FONT_SIM_DJ_BOLD)
  302. {
  303. pFontSim = (FONTSIM *)pwchTmp;
  304. (*ppIFI)->dpFontSim = (PTRDIFF)((BYTE *)pFontSim - (BYTE *)(*ppIFI) );
  305. pFontSim->dpBold = DWORD_ALIGN(sizeof(FONTSIM));
  306. pfdiffBold = (FONTDIFF *)((BYTE *)pFontSim + pFontSim->dpBold);
  307. pFontSim->dpItalic = 0;
  308. pFontSim->dpBoldItalic = 0;
  309. }
  310. else
  311. if ((DO_FONTSIM( pFInData ) || pFInData->dwFlags & FLAG_FONTSIM) && cFontDiff > 0)
  312. //
  313. // For CJK font.
  314. // Judge which font simulation to be enabled, then allocate the
  315. // necessary storage.
  316. //
  317. {
  318. PTRDIFF dpTmp;
  319. // n.b.: FONTSIM, FONTDIFF have to be dword-aligned
  320. // pFontSim = (FONTSIM *)PtrToUlong(pwchTmp);
  321. pFontSim = (FONTSIM *)pwchTmp;
  322. (*ppIFI)->dpFontSim = (PTRDIFF)((BYTE *)pFontSim - (BYTE *)(*ppIFI) );
  323. dpTmp = DWORD_ALIGN(sizeof(FONTSIM));
  324. if (!(fsFontSim & FONT_SIM_NO_BOLD))
  325. {
  326. pFontSim->dpBold = dpTmp;
  327. pfdiffBold = (FONTDIFF *)((BYTE *)pFontSim + dpTmp);
  328. dpTmp += DWORD_ALIGN(sizeof(FONTDIFF));
  329. if (!(fsFontSim & FONT_SIM_NO_ITALIC))
  330. {
  331. pFontSim->dpBoldItalic = dpTmp;
  332. pfdiffBoldItalic = (FONTDIFF *)((BYTE *)pFontSim + dpTmp);
  333. dpTmp += DWORD_ALIGN(sizeof(FONTDIFF));
  334. }
  335. }
  336. else
  337. if (!(fsFontSim & FONT_SIM_NO_ITALIC))
  338. {
  339. pFontSim->dpItalic = dpTmp;
  340. pfdiffItalic = (FONTDIFF *)((BYTE *)pFontSim + dpTmp);
  341. dpTmp += DWORD_ALIGN(sizeof(FONTDIFF));
  342. }
  343. pwchTmp = (WCHAR *)((BYTE *)pFontSim + dpTmp);
  344. }
  345. // check again...
  346. if ((BYTE *)(pwchTmp) > ((BYTE *)(*ppIFI) + icbAlloc))
  347. {
  348. #if DBG
  349. DbgPrint( "BFontInfoToIFIMetrics: IFIMETRICS overflow: Wrote to 0x%lx, allocated to 0x%lx\n",
  350. ((BYTE *)pwchTmp),
  351. ((BYTE *)(*ppIFI) + icbAlloc) );
  352. #endif
  353. HeapFree( hHeap, 0, (LPSTR)(*ppIFI) ); /* No memory leaks */
  354. return 0;
  355. }
  356. {
  357. int i;
  358. (*ppIFI)->lEmbedId = 0;
  359. (*ppIFI)->lItalicAngle = 0;
  360. (*ppIFI)->lCharBias = 0;
  361. (*ppIFI)->dpCharSets = 0; // no multiple charsets in rasdd fonts
  362. }
  363. (*ppIFI)->jWinCharSet = (BYTE)pFInData->PFMH.dfCharSet;
  364. //
  365. // If FE Ctt table is used, this overrides what defined in charset
  366. //
  367. if (IS_DBCSCTTTYPE(-(pFInData->DI.sTransTab)))
  368. {
  369. (*ppIFI)->jWinCharSet = CTT_TYPE_TO_CHARSET(-(pFInData->DI.sTransTab));
  370. }
  371. if( pFInData->PFMH.dfPixWidth )
  372. {
  373. (*ppIFI)->jWinPitchAndFamily |= FIXED_PITCH;
  374. (*ppIFI)->flInfo |= (FM_INFO_CONSTANT_WIDTH | FM_INFO_OPTICALLY_FIXED_PITCH);
  375. if(IS_DBCSCHARSET((*ppIFI)->jWinCharSet))
  376. {
  377. // it is too strict to call a DBCS font "fixed pitch" since it has
  378. // both halfwidth glyphs and fullwidth glyphs.
  379. (*ppIFI)->flInfo &= ~FM_INFO_CONSTANT_WIDTH;
  380. (*ppIFI)->flInfo |= (FM_INFO_OPTICALLY_FIXED_PITCH |
  381. FM_INFO_DBCS_FIXED_PITCH);
  382. }
  383. }
  384. else
  385. {
  386. (*ppIFI)->jWinPitchAndFamily |= VARIABLE_PITCH;
  387. if(IS_DBCSCHARSET((*ppIFI)->jWinCharSet))
  388. {
  389. // DBCS glyphs are always fixed pitch even if the SBCS part is
  390. // variable pitch.
  391. (*ppIFI)->flInfo |= FM_INFO_DBCS_FIXED_PITCH;
  392. }
  393. }
  394. (*ppIFI)->jWinPitchAndFamily |= (((BYTE) pFInData->PFMH.dfPitchAndFamily) & 0xf0);
  395. (*ppIFI)->usWinWeight = (USHORT)pFInData->PFMH.dfWeight;
  396. //
  397. // IFIMETRICS::flInfo
  398. //
  399. (*ppIFI)->flInfo |=
  400. FM_INFO_TECH_BITMAP |
  401. FM_INFO_1BPP |
  402. FM_INFO_INTEGER_WIDTH |
  403. FM_INFO_NOT_CONTIGUOUS |
  404. FM_INFO_RIGHT_HANDED;
  405. /*
  406. * A scalable font? This happens when there is EXTTEXTMETRIC data,
  407. * and that data has a min size different to the max size.
  408. */
  409. if( pFInData->pETM &&
  410. pFInData->pETM->emMinScale != pFInData->pETM->emMaxScale )
  411. {
  412. (*ppIFI)->flInfo |= FM_INFO_ISOTROPIC_SCALING_ONLY;
  413. (*ppIFI)->fwdUnitsPerEm = pFInData->pETM->emMasterUnits;
  414. }
  415. else
  416. {
  417. (*ppIFI)->fwdUnitsPerEm =
  418. (FWORD) (pFInData->PFMH.dfPixHeight - pFInData->PFMH.dfInternalLeading);
  419. }
  420. #ifndef PFM2UFM_SCALING_ANISOTROPIC
  421. #define PFM2UFM_SCALING_ANISOTROPIC 1
  422. #endif
  423. #ifndef PFM2UFM_SCALING_ARB_XFORMS
  424. #define PFM2UFM_SCALING_ARB_XFORMS 2
  425. #endif
  426. if ((*ppIFI)->flInfo & FM_INFO_ISOTROPIC_SCALING_ONLY) {
  427. // Allow forcing non-standard scaling only if the
  428. // font is already scalable.
  429. if ((dwFlags & PFM2UFM_SCALING_ANISOTROPIC)) {
  430. (*ppIFI)->flInfo &= ~FM_INFO_ISOTROPIC_SCALING_ONLY;
  431. (*ppIFI)->flInfo |= FM_INFO_ANISOTROPIC_SCALING_ONLY;
  432. (*ppIFI)->flInfo &= ~FM_INFO_ARB_XFORMS;
  433. }
  434. else if ((dwFlags & PFM2UFM_SCALING_ARB_XFORMS)) {
  435. (*ppIFI)->flInfo &= ~FM_INFO_ISOTROPIC_SCALING_ONLY;
  436. (*ppIFI)->flInfo &= ~FM_INFO_ANISOTROPIC_SCALING_ONLY;
  437. (*ppIFI)->flInfo |= FM_INFO_ARB_XFORMS;
  438. }
  439. }
  440. (*ppIFI)->fsSelection =
  441. ((pFInData->PFMH.dfItalic ) ? FM_SEL_ITALIC : 0) |
  442. ((pFInData->PFMH.dfUnderline ) ? FM_SEL_UNDERSCORE : 0) |
  443. ((pFInData->PFMH.dfStrikeOut ) ? FM_SEL_STRIKEOUT : 0) |
  444. ((pFInData->PFMH.dfWeight >= FW_BOLD ) ? FM_SEL_BOLD : 0) ;
  445. (*ppIFI)->fsType = FM_NO_EMBEDDING;
  446. (*ppIFI)->fwdLowestPPEm = 1;
  447. /*
  448. * Calculate fwdWinAscender, fwdWinDescender, fwdAveCharWidth, and
  449. * fwdMaxCharInc assuming a bitmap where 1 font unit equals one
  450. * pixel unit
  451. */
  452. (*ppIFI)->fwdWinAscender = (FWORD)pFInData->PFMH.dfAscent;
  453. (*ppIFI)->fwdWinDescender =
  454. (FWORD)pFInData->PFMH.dfPixHeight - (*ppIFI)->fwdWinAscender;
  455. (*ppIFI)->fwdMaxCharInc = (FWORD)pFInData->PFMH.dfMaxWidth;
  456. (*ppIFI)->fwdAveCharWidth = (FWORD)pFInData->PFMH.dfAvgWidth;
  457. fwdExternalLeading = (FWORD)pFInData->PFMH.dfExternalLeading;
  458. //
  459. // If the font was scalable, then the answers must be scaled up
  460. // !!! HELP HELP HELP - if a font is scalable in this sense, then
  461. // does it support arbitrary transforms? [kirko]
  462. //
  463. if( (*ppIFI)->flInfo & (FM_INFO_ISOTROPIC_SCALING_ONLY |
  464. FM_INFO_ANISOTROPIC_SCALING_ONLY |
  465. FM_INFO_ARB_XFORMS))
  466. {
  467. /*
  468. * This is a scalable font: because there is Extended Text Metric
  469. * information available, and this says that the min and max
  470. * scale sizes are different: thus it is scalable! This test is
  471. * lifted directly from the Win 3.1 driver.
  472. */
  473. int iMU, iRel; /* Adjustment factors */
  474. iMU = pFInData->pETM->emMasterUnits;
  475. iRel = pFInData->PFMH.dfPixHeight;
  476. (*ppIFI)->fwdWinAscender = ((*ppIFI)->fwdWinAscender * iMU) / iRel;
  477. (*ppIFI)->fwdWinDescender = ((*ppIFI)->fwdWinDescender * iMU) / iRel;
  478. (*ppIFI)->fwdMaxCharInc = ((*ppIFI)->fwdMaxCharInc * iMU) / iRel;
  479. (*ppIFI)->fwdAveCharWidth = ((*ppIFI)->fwdAveCharWidth * iMU) / iRel;
  480. fwdExternalLeading = (fwdExternalLeading * iMU) / iRel;
  481. }
  482. (*ppIFI)->fwdMacAscender = (*ppIFI)->fwdWinAscender;
  483. (*ppIFI)->fwdMacDescender = - (*ppIFI)->fwdWinDescender;
  484. (*ppIFI)->fwdMacLineGap = fwdExternalLeading;
  485. (*ppIFI)->fwdTypoAscender = (*ppIFI)->fwdMacAscender;
  486. (*ppIFI)->fwdTypoDescender = (*ppIFI)->fwdMacDescender;
  487. (*ppIFI)->fwdTypoLineGap = (*ppIFI)->fwdMacLineGap;
  488. // for Windows 3.1J compatibility
  489. if(IS_DBCSCHARSET((*ppIFI)->jWinCharSet))
  490. {
  491. (*ppIFI)->fwdMacLineGap = 0;
  492. (*ppIFI)->fwdTypoLineGap = 0;
  493. }
  494. if( pFInData->pETM )
  495. {
  496. /*
  497. * Zero is a legitimate default for these. If 0, gdisrv
  498. * chooses some default values.
  499. */
  500. (*ppIFI)->fwdCapHeight = pFInData->pETM->emCapHeight;
  501. (*ppIFI)->fwdXHeight = pFInData->pETM->emXHeight;
  502. (*ppIFI)->fwdSubscriptYSize = pFInData->pETM->emSubScriptSize;
  503. (*ppIFI)->fwdSubscriptYOffset = pFInData->pETM->emSubScript;
  504. (*ppIFI)->fwdSuperscriptYSize = pFInData->pETM->emSuperScriptSize;
  505. (*ppIFI)->fwdSuperscriptYOffset = pFInData->pETM->emSuperScript;
  506. (*ppIFI)->fwdUnderscoreSize = pFInData->pETM->emUnderlineWidth;
  507. (*ppIFI)->fwdUnderscorePosition = pFInData->pETM->emUnderlineOffset;
  508. (*ppIFI)->fwdStrikeoutSize = pFInData->pETM->emStrikeOutWidth;
  509. (*ppIFI)->fwdStrikeoutPosition = pFInData->pETM->emStrikeOutOffset;
  510. }
  511. else
  512. {
  513. /* No additional information, so do some calculations */
  514. (*ppIFI)->fwdSubscriptYSize = (*ppIFI)->fwdWinAscender/4;
  515. (*ppIFI)->fwdSubscriptYOffset = -((*ppIFI)->fwdWinAscender/4);
  516. (*ppIFI)->fwdSuperscriptYSize = (*ppIFI)->fwdWinAscender/4;
  517. (*ppIFI)->fwdSuperscriptYOffset = (3 * (*ppIFI)->fwdWinAscender)/4;
  518. (*ppIFI)->fwdUnderscoreSize = (*ppIFI)->fwdWinAscender / 12;
  519. if( (*ppIFI)->fwdUnderscoreSize < 1 )
  520. (*ppIFI)->fwdUnderscoreSize = 1;
  521. (*ppIFI)->fwdUnderscorePosition = -pFInData->DI.sUnderLinePos;
  522. (*ppIFI)->fwdStrikeoutSize = (*ppIFI)->fwdUnderscoreSize;
  523. (*ppIFI)->fwdStrikeoutPosition = (FWORD)pFInData->DI.sStrikeThruPos;
  524. if( (*ppIFI)->fwdStrikeoutPosition < 1 )
  525. (*ppIFI)->fwdStrikeoutPosition = ((*ppIFI)->fwdWinAscender + 2) / 3;
  526. }
  527. (*ppIFI)->fwdSubscriptXSize = (*ppIFI)->fwdAveCharWidth/4;
  528. (*ppIFI)->fwdSubscriptXOffset = (3 * (*ppIFI)->fwdAveCharWidth)/4;
  529. (*ppIFI)->fwdSuperscriptXSize = (*ppIFI)->fwdAveCharWidth/4;
  530. (*ppIFI)->fwdSuperscriptXOffset = (3 * (*ppIFI)->fwdAveCharWidth)/4;
  531. (*ppIFI)->chFirstChar = pFInData->PFMH.dfFirstChar;
  532. (*ppIFI)->chLastChar = pFInData->PFMH.dfLastChar;
  533. //
  534. // We now do the conversion of these to Unicode. We presume the
  535. // input is in the ANSI code page, and call the NLS converion
  536. // functions to generate proper Unicode values.
  537. //
  538. iCount = pFInData->PFMH.dfLastChar - pFInData->PFMH.dfFirstChar + 1;
  539. for( iI = 0; iI < iCount; ++iI )
  540. abyte[ iI ] = iI + pFInData->PFMH.dfFirstChar;
  541. DwCopyStringToUnicodeString( uiCodePage,
  542. abyte,
  543. awcAttrib,
  544. iCount);
  545. //
  546. // Now fill in the IFIMETRICS WCHAR fields.
  547. //
  548. (*ppIFI)->wcFirstChar = 0xffff;
  549. (*ppIFI)->wcLastChar = 0;
  550. //
  551. // Look for the first and last
  552. //
  553. for( iI = 0; iI < iCount; ++iI )
  554. {
  555. if( (*ppIFI)->wcFirstChar > awcAttrib[ iI ] )
  556. (*ppIFI)->wcFirstChar = awcAttrib[ iI ];
  557. if( (*ppIFI)->wcLastChar < awcAttrib[ iI ] )
  558. (*ppIFI)->wcLastChar = awcAttrib[ iI ];
  559. }
  560. (*ppIFI)->wcDefaultChar = awcAttrib[ pFInData->PFMH.dfDefaultChar ];
  561. (*ppIFI)->wcBreakChar = awcAttrib[ pFInData->PFMH.dfBreakChar ];
  562. (*ppIFI)->chDefaultChar = pFInData->PFMH.dfDefaultChar + pFInData->PFMH.dfFirstChar;
  563. (*ppIFI)->chBreakChar = pFInData->PFMH.dfBreakChar + pFInData->PFMH.dfFirstChar;
  564. if( pFInData->PFMH.dfItalic )
  565. {
  566. //
  567. // tan (17.5 degrees) = .3153
  568. //
  569. (*ppIFI)->ptlCaret.x = 3153;
  570. (*ppIFI)->ptlCaret.y = 10000;
  571. }
  572. else
  573. {
  574. (*ppIFI)->ptlCaret.x = 0;
  575. (*ppIFI)->ptlCaret.y = 1;
  576. }
  577. (*ppIFI)->ptlBaseline.x = 1;
  578. (*ppIFI)->ptlBaseline.y = 0;
  579. (*ppIFI)->ptlAspect.x = pFInData->PFMH.dfHorizRes;
  580. (*ppIFI)->ptlAspect.y = pFInData->PFMH.dfVertRes;
  581. (*ppIFI)->rclFontBox.left = 0;
  582. (*ppIFI)->rclFontBox.top = (LONG) (*ppIFI)->fwdWinAscender;
  583. (*ppIFI)->rclFontBox.right = (LONG) (*ppIFI)->fwdMaxCharInc;
  584. (*ppIFI)->rclFontBox.bottom = - (LONG) (*ppIFI)->fwdWinDescender;
  585. (*ppIFI)->achVendId[0] = 'U';
  586. (*ppIFI)->achVendId[1] = 'n';
  587. (*ppIFI)->achVendId[2] = 'k';
  588. (*ppIFI)->achVendId[3] = 'n';
  589. (*ppIFI)->cKerningPairs = 0;
  590. (*ppIFI)->ulPanoseCulture = FM_PANOSE_CULTURE_LATIN;
  591. (*ppIFI)->panose.bFamilyType = PAN_ANY;
  592. (*ppIFI)->panose.bSerifStyle = PAN_ANY;
  593. if(pFInData->PFMH.dfWeight >= FW_BOLD)
  594. {
  595. (*ppIFI)->panose.bWeight = PAN_WEIGHT_BOLD;
  596. }
  597. else if (pFInData->PFMH.dfWeight > FW_EXTRALIGHT)
  598. {
  599. (*ppIFI)->panose.bWeight = PAN_WEIGHT_MEDIUM;
  600. }
  601. else
  602. {
  603. (*ppIFI)->panose.bWeight = PAN_WEIGHT_LIGHT;
  604. }
  605. (*ppIFI)->panose.bProportion = PAN_ANY;
  606. (*ppIFI)->panose.bContrast = PAN_ANY;
  607. (*ppIFI)->panose.bStrokeVariation = PAN_ANY;
  608. (*ppIFI)->panose.bArmStyle = PAN_ANY;
  609. (*ppIFI)->panose.bLetterform = PAN_ANY;
  610. (*ppIFI)->panose.bMidline = PAN_ANY;
  611. (*ppIFI)->panose.bXHeight = PAN_ANY;
  612. if (fsFontSim & FONT_SIM_DJ_BOLD)
  613. {
  614. FONTDIFF FontDiff;
  615. SHORT sAddBold;
  616. FontDiff.jReserved1 = 0;
  617. FontDiff.jReserved2 = 0;
  618. FontDiff.jReserved3 = 0;
  619. FontDiff.bWeight = (*ppIFI)->panose.bWeight;
  620. FontDiff.usWinWeight = (*ppIFI)->usWinWeight;
  621. FontDiff.fsSelection = (*ppIFI)->fsSelection;
  622. FontDiff.fwdAveCharWidth = (*ppIFI)->fwdAveCharWidth;
  623. FontDiff.fwdMaxCharInc = (*ppIFI)->fwdMaxCharInc;
  624. FontDiff.ptlCaret = (*ppIFI)->ptlCaret;
  625. if (pfdiffBold)
  626. {
  627. sAddBold = (pFInData->DI.wPrivateData & BASE_BOLD_MASK) >>
  628. BASE_BOLD_SHIFT;
  629. *pfdiffBold = FontDiff;
  630. pfdiffBold->bWeight = PAN_WEIGHT_BOLD;
  631. pfdiffBold->fsSelection |= FM_SEL_BOLD;
  632. pfdiffBold->usWinWeight = FW_BOLD;
  633. pfdiffBold->fwdAveCharWidth += sAddBold;
  634. pfdiffBold->fwdMaxCharInc += sAddBold;
  635. }
  636. }
  637. else
  638. if ( (DO_FONTSIM( pFInData ) || pFInData->dwFlags & FLAG_FONTSIM) &&
  639. cFontDiff > 0 )
  640. {
  641. FONTDIFF FontDiff;
  642. FontDiff.jReserved1 = 0;
  643. FontDiff.jReserved2 = 0;
  644. FontDiff.jReserved3 = 0;
  645. FontDiff.bWeight = (*ppIFI)->panose.bWeight;
  646. FontDiff.usWinWeight = (*ppIFI)->usWinWeight;
  647. FontDiff.fsSelection = (*ppIFI)->fsSelection;
  648. FontDiff.fwdAveCharWidth = (*ppIFI)->fwdAveCharWidth;
  649. FontDiff.fwdMaxCharInc = (*ppIFI)->fwdMaxCharInc;
  650. FontDiff.ptlCaret = (*ppIFI)->ptlCaret;
  651. if (pfdiffBold)
  652. {
  653. *pfdiffBold = FontDiff;
  654. pfdiffBold->bWeight = PAN_WEIGHT_BOLD;
  655. pfdiffBold->fsSelection |= FM_SEL_BOLD;
  656. pfdiffBold->usWinWeight = FW_BOLD;
  657. pfdiffBold->fwdAveCharWidth += 1;
  658. pfdiffBold->fwdMaxCharInc += 1;
  659. }
  660. if (pfdiffItalic)
  661. {
  662. *pfdiffItalic = FontDiff;
  663. pfdiffItalic->fsSelection |= FM_SEL_ITALIC;
  664. pfdiffItalic->ptlCaret.x = 1;
  665. pfdiffItalic->ptlCaret.y = 2;
  666. }
  667. if (pfdiffBoldItalic)
  668. {
  669. *pfdiffBoldItalic = FontDiff;
  670. pfdiffBoldItalic->bWeight = PAN_WEIGHT_BOLD;
  671. pfdiffBoldItalic->fsSelection |= (FM_SEL_BOLD | FM_SEL_ITALIC);
  672. pfdiffBoldItalic->usWinWeight = FW_BOLD;
  673. pfdiffBoldItalic->fwdAveCharWidth += 1;
  674. pfdiffBoldItalic->fwdMaxCharInc += 1;
  675. pfdiffBoldItalic->ptlCaret.x = 1;
  676. pfdiffBoldItalic->ptlCaret.y = 2;
  677. }
  678. }
  679. return TRUE;
  680. }
  681. BOOL
  682. BGetFontSelFromPFM(
  683. HANDLE hHeap,
  684. FONTIN *pFInData, // Access to font info, aligned
  685. BOOL bSelect,
  686. CMDSTRING *pCmdStr)
  687. {
  688. LOCD locd; // From originating data
  689. CD *pCD, **ppCDTrg;
  690. if (bSelect)
  691. {
  692. locd = pFInData->DI.locdSelect;
  693. ppCDTrg = &pFInData->pCDSelectFont;
  694. }
  695. else
  696. {
  697. locd = pFInData->DI.locdUnSelect;
  698. ppCDTrg = &pFInData->pCDUnSelectFont;
  699. }
  700. if( locd != 0xFFFFFFFF) // NOOCD
  701. {
  702. DWORD dwSize;
  703. pCD = (CD *)(pFInData->pBase + locd);
  704. //
  705. // The data pointed at by pCD may not be aligned, so we copy
  706. // it into a local structure. This local structure then allows
  707. // us to determine how big the CD really is (using it's length field),
  708. // so then we can allocate storage and copy as required.
  709. //
  710. //
  711. // Allocate storage area in the heap
  712. //
  713. dwSize = pCD->wLength;
  714. pCmdStr->pCmdString = (PBYTE)HeapAlloc( hHeap,
  715. 0,
  716. (dwSize + 3) & ~0x3 );
  717. if (NULL == pCmdStr->pCmdString)
  718. //
  719. // Check if HeapAlloc succeeded.
  720. //
  721. return FALSE;
  722. pCmdStr->dwSize = dwSize;
  723. CopyMemory((PBYTE)pCmdStr->pCmdString, (PBYTE)(pCD + 1), dwSize);
  724. *ppCDTrg = pCD;
  725. return TRUE;
  726. }
  727. pCmdStr->dwSize = 0;
  728. return FALSE;
  729. }
  730. BOOL
  731. BAlignPFM(
  732. FONTIN *pFInData) // Has ALL we need!
  733. /*++
  734. Routine Description:
  735. Convert the non-aligned windows format data into a properly
  736. aligned structure for our use. Only some of the data is converted
  737. here, since we are mostly interested in extracting the addresses
  738. contained in these structures.
  739. Arguments:
  740. pFInData - pointer to FONTIN
  741. Return Value:
  742. TRUE if successfull, otherwise fail to convert.
  743. --*/
  744. {
  745. BYTE *pb; /* Miscellaneous operations */
  746. res_PFMHEADER *pPFM; /* The resource data format */
  747. res_PFMEXTENSION *pR_PFME; /* Resource data PFMEXT format */
  748. /*
  749. * Align the PFMHEADER structure.
  750. */
  751. pPFM = (res_PFMHEADER *)pFInData->pBase;
  752. pFInData->PFMH.dfType = pPFM->dfType;
  753. pFInData->PFMH.dfPoints = pPFM->dfPoints;
  754. pFInData->PFMH.dfVertRes = pPFM->dfVertRes;
  755. pFInData->PFMH.dfHorizRes = pPFM->dfHorizRes;
  756. pFInData->PFMH.dfAscent = pPFM->dfAscent;
  757. pFInData->PFMH.dfInternalLeading = pPFM->dfInternalLeading;
  758. pFInData->PFMH.dfExternalLeading = pPFM->dfExternalLeading;
  759. pFInData->PFMH.dfItalic = pPFM->dfItalic;
  760. pFInData->PFMH.dfUnderline = pPFM->dfUnderline;
  761. pFInData->PFMH.dfStrikeOut = pPFM->dfStrikeOut;
  762. pFInData->PFMH.dfWeight = DwAlign2( pPFM->b_dfWeight );
  763. pFInData->PFMH.dfCharSet = pPFM->dfCharSet;
  764. pFInData->PFMH.dfPixWidth = pPFM->dfPixWidth;
  765. pFInData->PFMH.dfPixHeight = pPFM->dfPixHeight;
  766. pFInData->PFMH.dfPitchAndFamily = pPFM->dfPitchAndFamily;
  767. pFInData->PFMH.dfAvgWidth = DwAlign2( pPFM->b_dfAvgWidth );
  768. pFInData->PFMH.dfMaxWidth = DwAlign2( pPFM->b_dfMaxWidth );
  769. pFInData->PFMH.dfFirstChar = pPFM->dfFirstChar;
  770. pFInData->PFMH.dfLastChar = pPFM->dfLastChar;
  771. pFInData->PFMH.dfDefaultChar = pPFM->dfDefaultChar;
  772. pFInData->PFMH.dfBreakChar = pPFM->dfBreakChar;
  773. pFInData->PFMH.dfWidthBytes = DwAlign2( pPFM->b_dfWidthBytes );
  774. pFInData->PFMH.dfDevice = DwAlign4( pPFM->b_dfDevice );
  775. pFInData->PFMH.dfFace = DwAlign4( pPFM->b_dfFace );
  776. pFInData->PFMH.dfBitsPointer = DwAlign4( pPFM->b_dfBitsPointer );
  777. pFInData->PFMH.dfBitsOffset = DwAlign4( pPFM->b_dfBitsOffset );
  778. /*
  779. * The PFMEXTENSION follows the PFMHEADER structure plus any width
  780. * table info. The width table will be present if the PFMHEADER has
  781. * a zero width dfPixWidth. If present, adjust the extension address.
  782. */
  783. pb = pFInData->pBase + sizeof( res_PFMHEADER ); /* Size in resource data */
  784. if( pFInData->PFMH.dfPixWidth == 0 )
  785. {
  786. pb += (pFInData->PFMH.dfLastChar - pFInData->PFMH.dfFirstChar + 2) *
  787. sizeof( short );
  788. }
  789. pR_PFME = (res_PFMEXTENSION *)pb;
  790. //
  791. // Now convert the extended PFM data.
  792. //
  793. pFInData->PFMExt.dfSizeFields = pR_PFME->dfSizeFields;
  794. pFInData->PFMExt.dfExtMetricsOffset = DwAlign4( pR_PFME->b_dfExtMetricsOffset );
  795. pFInData->PFMExt.dfExtentTable = DwAlign4( pR_PFME->b_dfExtentTable );
  796. pFInData->PFMExt.dfOriginTable = DwAlign4( pR_PFME->b_dfOriginTable );
  797. pFInData->PFMExt.dfPairKernTable = DwAlign4( pR_PFME->b_dfPairKernTable );
  798. pFInData->PFMExt.dfTrackKernTable = DwAlign4( pR_PFME->b_dfTrackKernTable );
  799. pFInData->PFMExt.dfDriverInfo = DwAlign4( pR_PFME->b_dfDriverInfo );
  800. pFInData->PFMExt.dfReserved = DwAlign4( pR_PFME->b_dfReserved );
  801. CopyMemory( &pFInData->DI,
  802. pFInData->pBase + pFInData->PFMExt.dfDriverInfo,
  803. sizeof( DRIVERINFO ) );
  804. //
  805. // Also need to fill in the address of the EXTTEXTMETRIC. This
  806. // is obtained from the extended PFM data that we just converted!
  807. //
  808. if( pFInData->PFMExt.dfExtMetricsOffset )
  809. {
  810. //
  811. // This structure is only an array of shorts, so there is
  812. // no alignment problem. However, the data itself is not
  813. // necessarily aligned in the resource!
  814. //
  815. int cbSize;
  816. BYTE *pbIn; /* Source of data to shift */
  817. pbIn = pFInData->pBase + pFInData->PFMExt.dfExtMetricsOffset;
  818. cbSize = DwAlign2( pbIn );
  819. if( cbSize == sizeof( EXTTEXTMETRIC ) )
  820. {
  821. /* Simply copy it! */
  822. CopyMemory( pFInData->pETM, pbIn, cbSize );
  823. }
  824. else
  825. {
  826. pFInData->pETM = NULL; /* Not our size, so best not use it */
  827. }
  828. }
  829. else
  830. {
  831. pFInData->pETM = NULL; /* Is non-zero when passed in */
  832. }
  833. return TRUE;
  834. }
  835. BOOL
  836. BGetWidthVectorFromPFM(
  837. HANDLE hHeap,
  838. FONTIN *pFInData, // Details of the current font
  839. PSHORT *ppWidth,
  840. PDWORD pdwSize)
  841. {
  842. //
  843. // For debugging code, verify that we have a width table! Then,
  844. // allocate memory and copy into it.
  845. //
  846. int icbSize; // Number of bytes required
  847. if( pFInData->PFMH.dfPixWidth )
  848. {
  849. ERR(( "BGetWidthVectorFromPFM called for FIXED PITCH FONT\n" ));
  850. return FALSE;
  851. }
  852. //
  853. // There are LastChar - FirstChar width entries, plus the default
  854. // char. And the widths are shorts.
  855. //
  856. icbSize = (pFInData->PFMH.dfLastChar - pFInData->PFMH.dfFirstChar + 2) *
  857. sizeof( short );
  858. *ppWidth = (PSHORT) HeapAlloc( hHeap, 0, icbSize );
  859. *pdwSize = icbSize;
  860. //
  861. // If this is a bitmap font, then use the width table, but use
  862. // the extent table (in PFMEXTENSION area) as these are ready to
  863. // to scale.
  864. //
  865. if( *ppWidth )
  866. {
  867. BYTE *pb;
  868. if( pFInData->pETM &&
  869. pFInData->pETM->emMinScale != pFInData->pETM->emMaxScale &&
  870. pFInData->PFMExt.dfExtentTable )
  871. {
  872. //
  873. // Scalable, so use the extent table
  874. //
  875. pb = pFInData->pBase + pFInData->PFMExt.dfExtentTable;
  876. }
  877. else
  878. {
  879. //
  880. // Not scalable
  881. //
  882. pb = pFInData->pBase + sizeof( res_PFMHEADER );
  883. }
  884. CopyMemory( *ppWidth, pb, icbSize );
  885. }
  886. else
  887. {
  888. ERR(( "GetWidthVec(): HeapAlloc( %ld ) fails\n", icbSize ));
  889. return FALSE;
  890. }
  891. return TRUE;
  892. }
  893. BOOL
  894. BGetKerningPairFromPFM(
  895. HANDLE hHeap,
  896. FONTIN *pFInData,
  897. w3KERNPAIR **ppSrcKernPair)
  898. {
  899. if (pFInData->PFMExt.dfPairKernTable)
  900. {
  901. *ppSrcKernPair = (w3KERNPAIR*)(pFInData->pBase + pFInData->PFMExt.dfPairKernTable);
  902. return TRUE;
  903. }
  904. return FALSE;
  905. }
  906. LONG
  907. LCtt2Cc(
  908. IN SHORT sTransTable,
  909. IN SHORT sCharSet)
  910. {
  911. LONG lRet;
  912. if (sTransTable > 0)
  913. {
  914. lRet = (LONG)sTransTable;
  915. }
  916. else
  917. {
  918. switch (sTransTable)
  919. {
  920. case CTT_CP437:
  921. case CTT_CP850:
  922. case CTT_CP863:
  923. lRet = (LONG)sTransTable;
  924. break;
  925. case CTT_BIG5:
  926. lRet = (LONG)CC_BIG5;
  927. break;
  928. case CTT_ISC:
  929. lRet = (LONG)CC_ISC;
  930. break;
  931. case CTT_JIS78:
  932. case CTT_JIS83:
  933. lRet = (LONG)CC_JIS;
  934. break;
  935. case CTT_JIS78_ANK:
  936. case CTT_JIS83_ANK:
  937. lRet = (LONG)CC_JIS_ANK;
  938. break;
  939. case CTT_NS86:
  940. lRet = (LONG)CC_NS86;
  941. break;
  942. case CTT_TCA:
  943. lRet = (LONG)CC_TCA;
  944. break;
  945. default:
  946. switch (sCharSet)
  947. {
  948. case SHIFTJIS_CHARSET:
  949. lRet = CC_SJIS;
  950. break;
  951. case HANGEUL_CHARSET:
  952. lRet = CC_WANSUNG;
  953. break;
  954. case GB2312_CHARSET:
  955. lRet = CC_GB2312;
  956. break;
  957. case CHINESEBIG5_CHARSET:
  958. lRet = CC_BIG5;
  959. break;
  960. default:
  961. lRet = 0;
  962. break;
  963. }
  964. break;
  965. }
  966. }
  967. return lRet;
  968. }
  969. WORD
  970. WGetGlyphHandle(
  971. PUNI_GLYPHSETDATA pGlyph,
  972. WORD wUnicode)
  973. {
  974. PGLYPHRUN pGlyphRun;
  975. DWORD dwI;
  976. WORD wGlyphHandle;
  977. BOOL bFound;
  978. pGlyphRun = (PGLYPHRUN)((PBYTE)pGlyph + pGlyph->loRunOffset);
  979. wGlyphHandle = 0;
  980. bFound = FALSE;
  981. for (dwI = 0; dwI < pGlyph->dwRunCount; dwI ++)
  982. {
  983. if (pGlyphRun->wcLow <= wUnicode &&
  984. wUnicode < pGlyphRun->wcLow + pGlyphRun->wGlyphCount)
  985. {
  986. //
  987. // Glyph handle starting from ONE!
  988. //
  989. wGlyphHandle += wUnicode - pGlyphRun->wcLow + 1;
  990. bFound = TRUE;
  991. break;
  992. }
  993. wGlyphHandle += pGlyphRun->wGlyphCount;
  994. pGlyphRun++;
  995. }
  996. if (!bFound)
  997. {
  998. //
  999. // Couldn't find.
  1000. //
  1001. wGlyphHandle = 0;
  1002. }
  1003. return wGlyphHandle;
  1004. }
  1005. BOOL
  1006. BCreateWidthTable(
  1007. IN HANDLE hHeap,
  1008. IN PWORD pwGlyphHandleVector,
  1009. IN WORD wFirst,
  1010. IN WORD wLast,
  1011. IN PSHORT psWidthVectorSrc,
  1012. OUT PWIDTHTABLE *ppWidthTable,
  1013. OUT PDWORD pdwWidthTableSize)
  1014. {
  1015. struct {
  1016. WORD wGlyphHandle;
  1017. WORD wCharCode;
  1018. } GlyphHandleVectorTrg[256];
  1019. PWIDTHRUN pWidthRun;
  1020. DWORD loWidthTableOffset;
  1021. PWORD pWidth;
  1022. WORD wI, wJ;
  1023. WORD wHandle, wMiniHandle, wMiniHandleId, wRunCount;
  1024. //
  1025. // Sort in the order of Glyph Handle.
  1026. // Simple sort
  1027. // Basically it's not necessary to think about a performance.
  1028. //
  1029. // pwGlyphHandleVector 0 -> glyph handle of character code wFirst
  1030. // 1 -> glyph handle of character code wFirst + 1
  1031. // 2 -> glyph handle of character code wFirst + 2
  1032. // ...
  1033. //
  1034. // GlyphHandleVectorTrg 0 -> minimum glyph handle
  1035. // 1 -> second minimum glyph handle
  1036. // 2 -> third minimum glyph handle
  1037. //
  1038. for (wJ = 0; wJ <= wLast - wFirst; wJ++)
  1039. {
  1040. wMiniHandle = 0xFFFF;
  1041. wMiniHandleId = wFirst;
  1042. for (wI = wFirst ; wI <= wLast; wI++)
  1043. {
  1044. if (wMiniHandle > pwGlyphHandleVector[wI])
  1045. {
  1046. wMiniHandle = pwGlyphHandleVector[wI];
  1047. wMiniHandleId = wI;
  1048. }
  1049. }
  1050. pwGlyphHandleVector[wMiniHandleId] = 0xFFFF;
  1051. GlyphHandleVectorTrg[wJ].wGlyphHandle = wMiniHandle;
  1052. GlyphHandleVectorTrg[wJ].wCharCode = wMiniHandleId;
  1053. }
  1054. //
  1055. // Count Width run
  1056. //
  1057. wHandle = GlyphHandleVectorTrg[0].wGlyphHandle;
  1058. wRunCount = 1;
  1059. for (wI = 1; wI < wLast - wFirst + 1 ; wI++)
  1060. {
  1061. if (++wHandle != GlyphHandleVectorTrg[wI].wGlyphHandle)
  1062. {
  1063. wHandle = GlyphHandleVectorTrg[wI].wGlyphHandle;
  1064. wRunCount ++;
  1065. }
  1066. }
  1067. //
  1068. // Allocate WIDTHTABLE buffer
  1069. //
  1070. *pdwWidthTableSize = sizeof(WIDTHTABLE) +
  1071. (wRunCount - 1) * sizeof(WIDTHRUN) +
  1072. sizeof(SHORT) * wLast + 1 - wFirst;
  1073. *ppWidthTable = HeapAlloc(hHeap,
  1074. 0,
  1075. *pdwWidthTableSize);
  1076. if (!*ppWidthTable)
  1077. {
  1078. *pdwWidthTableSize = 0;
  1079. return FALSE;
  1080. }
  1081. //
  1082. // Fill in a WIDTHTABLE
  1083. //
  1084. (*ppWidthTable)->dwSize = sizeof(WIDTHTABLE) +
  1085. sizeof(WIDTHRUN) * (wRunCount - 1) +
  1086. sizeof(SHORT) * (wLast + 1 - wFirst);
  1087. (*ppWidthTable)->dwRunNum = wRunCount;
  1088. loWidthTableOffset = sizeof(WIDTHTABLE) +
  1089. (wRunCount - 1) * sizeof(WIDTHRUN);
  1090. pWidth = (PWORD)((PBYTE)*ppWidthTable + loWidthTableOffset);
  1091. pWidthRun = (*ppWidthTable)->WidthRun;
  1092. wHandle =
  1093. pWidthRun[0].wStartGlyph = GlyphHandleVectorTrg[0].wGlyphHandle;
  1094. pWidthRun[0].loCharWidthOffset = loWidthTableOffset;
  1095. pWidthRun[0].wGlyphCount = 1;
  1096. wJ = 1;
  1097. wI = 0;
  1098. while (wI < wRunCount)
  1099. {
  1100. while (GlyphHandleVectorTrg[wJ].wGlyphHandle == ++wHandle)
  1101. {
  1102. pWidthRun[wI].wGlyphCount ++;
  1103. wJ ++;
  1104. };
  1105. wI++;
  1106. wHandle =
  1107. pWidthRun[wI].wStartGlyph = GlyphHandleVectorTrg[wJ].wGlyphHandle;
  1108. pWidthRun[wI].loCharWidthOffset = loWidthTableOffset;
  1109. pWidthRun[wI].wGlyphCount = 1;
  1110. loWidthTableOffset += sizeof(SHORT) *
  1111. pWidthRun[wI].wGlyphCount;
  1112. wJ ++;
  1113. }
  1114. for (wI = 0; wI < wLast + 1 - wFirst; wI ++)
  1115. {
  1116. pWidth[wI] = psWidthVectorSrc[GlyphHandleVectorTrg[wI].wCharCode-wFirst];
  1117. }
  1118. return TRUE;
  1119. }
  1120. BOOL
  1121. BCreateKernData(
  1122. HANDLE hHeap,
  1123. w3KERNPAIR *pKernPair,
  1124. DWORD dwCodePage,
  1125. PKERNDATA *ppKernData,
  1126. PDWORD pdwKernDataSize)
  1127. {
  1128. FD_KERNINGPAIR *pDstKernPair;
  1129. DWORD dwNumOfKernPair;
  1130. DWORD dwI, dwJ, dwId;
  1131. WORD wUnicode[2];
  1132. WCHAR wcMiniSecond, wcMiniFirst;
  1133. BYTE ubMultiByte[2];
  1134. BOOL bFound;
  1135. //
  1136. // Count kerning pairs
  1137. //
  1138. dwNumOfKernPair = 0;
  1139. while( pKernPair[dwNumOfKernPair].kpPair.each[0] != 0 &&
  1140. pKernPair[dwNumOfKernPair].kpPair.each[1] != 0 )
  1141. {
  1142. dwNumOfKernPair ++;
  1143. }
  1144. if (!dwNumOfKernPair)
  1145. {
  1146. *pdwKernDataSize = 0;
  1147. *ppKernData = NULL;
  1148. return TRUE;
  1149. }
  1150. //
  1151. // Allocate memory
  1152. //
  1153. *pdwKernDataSize = sizeof(FD_KERNINGPAIR) * dwNumOfKernPair;
  1154. pDstKernPair = HeapAlloc(hHeap,
  1155. HEAP_ZERO_MEMORY,
  1156. *pdwKernDataSize);
  1157. if (!pDstKernPair)
  1158. {
  1159. HeapDestroy(hHeap);
  1160. return FALSE;
  1161. }
  1162. //
  1163. // Convert kerning pair table from character code base to unicode base.
  1164. //
  1165. for (dwI = 0; dwI < dwNumOfKernPair; dwI ++)
  1166. {
  1167. ubMultiByte[0] = (BYTE)pKernPair->kpPair.each[0];
  1168. ubMultiByte[1] = (BYTE)pKernPair->kpPair.each[1];
  1169. MultiByteToWideChar(dwCodePage,
  1170. 0,
  1171. (LPCSTR)ubMultiByte,
  1172. 2,
  1173. (LPWSTR)wUnicode,
  1174. 2);
  1175. pDstKernPair[dwI].wcFirst = wUnicode[0];
  1176. pDstKernPair[dwI].wcSecond = wUnicode[1];
  1177. pDstKernPair[dwI].fwdKern = pKernPair->kpKernAmount;
  1178. pKernPair++;
  1179. }
  1180. //
  1181. // Sort kerning pair table.
  1182. // An extra FD_KERNPAIR is allocated for the NULL sentinel
  1183. // (built into KERNDATA size)- it is zero'd by the HeapAlloc
  1184. //
  1185. *pdwKernDataSize += sizeof(KERNDATA);
  1186. (*ppKernData) = HeapAlloc(hHeap,
  1187. HEAP_ZERO_MEMORY,
  1188. *pdwKernDataSize);
  1189. if (*ppKernData == NULL)
  1190. {
  1191. HeapDestroy(hHeap);
  1192. return FALSE;
  1193. }
  1194. //
  1195. // Fill the final format of kerning pair.
  1196. //
  1197. (*ppKernData)->dwSize = *pdwKernDataSize;
  1198. (*ppKernData)->dwKernPairNum = dwNumOfKernPair;
  1199. for (dwI = 0; dwI < dwNumOfKernPair; dwI ++)
  1200. {
  1201. wcMiniSecond = 0xFFFF;
  1202. wcMiniFirst = 0xFFFF;
  1203. dwId = 0xFFFF;
  1204. bFound = FALSE;
  1205. for (dwJ = 0; dwJ < dwNumOfKernPair; dwJ ++)
  1206. {
  1207. if (pDstKernPair[dwJ].wcSecond < wcMiniSecond)
  1208. {
  1209. wcMiniSecond = pDstKernPair[dwJ].wcSecond;
  1210. wcMiniFirst = pDstKernPair[dwJ].wcFirst;
  1211. dwId = dwJ;
  1212. bFound = TRUE;
  1213. }
  1214. else
  1215. if (pDstKernPair[dwJ].wcSecond == wcMiniSecond)
  1216. {
  1217. if (pDstKernPair[dwJ].wcFirst < wcMiniFirst)
  1218. {
  1219. wcMiniFirst = pDstKernPair[dwJ].wcFirst;
  1220. dwId = dwJ;
  1221. bFound = TRUE;
  1222. }
  1223. }
  1224. }
  1225. if (bFound)
  1226. {
  1227. (*ppKernData)->KernPair[dwI].wcFirst = wcMiniFirst;
  1228. (*ppKernData)->KernPair[dwI].wcSecond = wcMiniSecond;
  1229. (*ppKernData)->KernPair[dwI].fwdKern =
  1230. pDstKernPair[dwId].fwdKern;
  1231. pDstKernPair[dwId].wcSecond = 0xFFFF;
  1232. pDstKernPair[dwId].wcFirst = 0xFFFF;
  1233. }
  1234. }
  1235. return TRUE;
  1236. }
  1237. BOOL
  1238. BConvertPFM2UFM(
  1239. HANDLE hHeap,
  1240. PBYTE pPFMData,
  1241. PUNI_GLYPHSETDATA pGlyph,
  1242. DWORD dwCodePage,
  1243. PFONTMISC pMiscData,
  1244. PFONTIN pFInData,
  1245. INT iGTTID,
  1246. PFONTOUT pFOutData,
  1247. DWORD dwFlags)
  1248. {
  1249. DWORD dwOffset;
  1250. DWORD dwI;
  1251. SHORT sWidthVectorSrc[256];
  1252. WORD awMtoUniDst[256];
  1253. WORD awGlyphHandle[256];
  1254. BYTE aubMultiByte[256];
  1255. //
  1256. // Zero out the header structure. This means we can ignore any
  1257. // irrelevant fields, which will then have the value 0, which is
  1258. // the value for not used.
  1259. //
  1260. pFInData->pBase = pPFMData;
  1261. if ( !BAlignPFM( pFInData))
  1262. {
  1263. SetLastError(ERROR_INVALID_PARAMETER);
  1264. return FALSE;
  1265. }
  1266. //
  1267. // dwCodePage has to be same as pGlyph->loCodePageInfo->dwCodePage.
  1268. //
  1269. if (pGlyph && pGlyph->loCodePageOffset)
  1270. {
  1271. dwCodePage = ((PUNI_CODEPAGEINFO)((PBYTE)pGlyph +
  1272. pGlyph->loCodePageOffset))->dwCodePage;
  1273. }
  1274. else
  1275. {
  1276. pGlyph = PGetDefaultGlyphset(hHeap,
  1277. (WORD)pFInData->PFMH.dfFirstChar,
  1278. (WORD)pFInData->PFMH.dfLastChar,
  1279. dwCodePage);
  1280. }
  1281. if (NULL == pGlyph)
  1282. {
  1283. SetLastError(ERROR_INVALID_PARAMETER);
  1284. return FALSE;
  1285. }
  1286. //
  1287. // Fill in IFIMETRICS
  1288. //
  1289. if ( !BFontInfoToIFIMetric(hHeap,
  1290. pFInData,
  1291. pMiscData->pwstrUniqName,
  1292. pFInData->dwCodePageOfFacenameConv,
  1293. &pFOutData->pIFI,
  1294. &pFOutData->dwIFISize,
  1295. dwFlags))
  1296. {
  1297. SetLastError(ERROR_INVALID_PARAMETER);
  1298. return FALSE;
  1299. }
  1300. if (BGetKerningPairFromPFM(hHeap, pFInData, &pFInData->pKernPair))
  1301. {
  1302. if (!BCreateKernData(hHeap,
  1303. pFInData->pKernPair,
  1304. dwCodePage,
  1305. &pFOutData->pKernData,
  1306. &pFOutData->dwKernDataSize))
  1307. {
  1308. SetLastError(ERROR_INVALID_PARAMETER);
  1309. return FALSE;
  1310. }
  1311. pFOutData->pIFI->cKerningPairs = pFOutData->pKernData->dwKernPairNum;
  1312. }
  1313. else
  1314. {
  1315. pFOutData->dwKernDataSize = 0;
  1316. pFOutData->pKernData = NULL;
  1317. }
  1318. BGetFontSelFromPFM(hHeap, pFInData, TRUE, &pFOutData->SelectFont);
  1319. BGetFontSelFromPFM(hHeap, pFInData, FALSE, &pFOutData->UnSelectFont);
  1320. if( pFInData->PFMH.dfPixWidth == 0 &&
  1321. BGetWidthVectorFromPFM(hHeap,
  1322. pFInData,
  1323. &(pFInData->psWidthTable),
  1324. &(pFInData->dwWidthTableSize)))
  1325. {
  1326. for (dwI = 0; dwI < 256; dwI++)
  1327. {
  1328. aubMultiByte[dwI] = (BYTE)dwI;
  1329. }
  1330. MultiByteToWideChar(dwCodePage,
  1331. 0,
  1332. (LPCSTR)aubMultiByte,
  1333. 256,
  1334. (LPWSTR)awMtoUniDst,
  1335. 256 );
  1336. //
  1337. // Glyph handle base
  1338. //
  1339. for (dwI = (DWORD)pFInData->PFMH.dfFirstChar;
  1340. dwI <= (DWORD)pFInData->PFMH.dfLastChar;
  1341. dwI ++)
  1342. {
  1343. awGlyphHandle[dwI] = WGetGlyphHandle(pGlyph, awMtoUniDst[dwI]);
  1344. }
  1345. if (!BCreateWidthTable(hHeap,
  1346. awGlyphHandle,
  1347. (WORD)pFInData->PFMH.dfFirstChar,
  1348. (WORD)pFInData->PFMH.dfLastChar,
  1349. pFInData->psWidthTable,
  1350. &pFOutData->pWidthTable,
  1351. &pFOutData->dwWidthTableSize))
  1352. {
  1353. SetLastError(ERROR_INVALID_PARAMETER);
  1354. return FALSE;
  1355. }
  1356. }
  1357. else
  1358. {
  1359. pFOutData->dwWidthTableSize = 0;
  1360. pFOutData->pWidthTable = NULL;
  1361. }
  1362. //
  1363. // Fill in UNIFM
  1364. //
  1365. // Fix the ETM pointer, instead oi leaving it uninitialized.
  1366. pFOutData -> pETM = pFInData -> pETM;
  1367. pFOutData->UniHdr.dwSize = sizeof(UNIFM_HDR) +
  1368. DWORD_ALIGN(sizeof(UNIDRVINFO) +
  1369. pFOutData->SelectFont.dwSize +
  1370. pFOutData->UnSelectFont.dwSize) +
  1371. pFOutData->dwIFISize +
  1372. !!pFOutData -> pETM * sizeof(EXTTEXTMETRIC) +
  1373. pFOutData->dwWidthTableSize +
  1374. pFOutData->dwKernDataSize;
  1375. pFOutData->UniHdr.dwVersion = UNIFM_VERSION_1_0;
  1376. pFOutData->UniHdr.ulDefaultCodepage = dwCodePage;
  1377. pFOutData->UniHdr.lGlyphSetDataRCID = iGTTID;
  1378. pFOutData->UniHdr.loUnidrvInfo = sizeof(UNIFM_HDR);
  1379. pFOutData->UniHdr.loIFIMetrics = pFOutData->UniHdr.loUnidrvInfo +
  1380. DWORD_ALIGN(sizeof(UNIDRVINFO) +
  1381. pFOutData->SelectFont.dwSize +
  1382. pFOutData->UnSelectFont.dwSize);
  1383. dwOffset = pFOutData->UniHdr.loIFIMetrics + pFOutData->dwIFISize;
  1384. if (pFOutData->pETM)
  1385. {
  1386. pFOutData->UniHdr.loExtTextMetric = dwOffset;
  1387. dwOffset += sizeof(EXTTEXTMETRIC);
  1388. }
  1389. else
  1390. {
  1391. pFOutData->UniHdr.loExtTextMetric = 0;
  1392. }
  1393. if (pFOutData->dwWidthTableSize && pFOutData->pWidthTable)
  1394. {
  1395. pFOutData->UniHdr.loWidthTable = dwOffset;
  1396. dwOffset += pFOutData->dwWidthTableSize;
  1397. }
  1398. else
  1399. {
  1400. pFOutData->UniHdr.loWidthTable = 0;
  1401. }
  1402. if (pFOutData->dwKernDataSize && pFOutData->pKernData)
  1403. {
  1404. pFOutData->UniHdr.loKernPair = dwOffset;
  1405. }
  1406. else
  1407. {
  1408. pFOutData->UniHdr.loKernPair = 0;
  1409. }
  1410. memset(pFOutData->UniHdr.dwReserved, 0, sizeof pFOutData->UniHdr.dwReserved);
  1411. //
  1412. // Fill in DRIVERINFO
  1413. //
  1414. pFOutData->UnidrvInfo.dwSize = DWORD_ALIGN(sizeof(UNIDRVINFO) +
  1415. pFOutData->SelectFont.dwSize +
  1416. pFOutData->UnSelectFont.dwSize);
  1417. pFOutData->UnidrvInfo.flGenFlags = 0;
  1418. pFOutData->UnidrvInfo.wType = pFInData->DI.wFontType;
  1419. pFOutData->UnidrvInfo.fCaps = pFInData->DI.fCaps;
  1420. pFOutData->UnidrvInfo.wXRes = pFInData->PFMH.dfHorizRes;
  1421. pFOutData->UnidrvInfo.wYRes = pFInData->PFMH.dfVertRes;
  1422. pFOutData->UnidrvInfo.sYAdjust = pFInData->DI.sYAdjust;
  1423. pFOutData->UnidrvInfo.sYMoved = pFInData->DI.sYMoved;
  1424. pFOutData->UnidrvInfo.sShift = pFInData->DI.sShift;
  1425. pFOutData->UnidrvInfo.wPrivateData = pFInData->DI.wPrivateData;
  1426. if (pFOutData->pIFI->flInfo & (FM_INFO_ISOTROPIC_SCALING_ONLY |
  1427. FM_INFO_ANISOTROPIC_SCALING_ONLY |
  1428. FM_INFO_ARB_XFORMS) )
  1429. {
  1430. pFOutData->UnidrvInfo.flGenFlags |= UFM_SCALABLE;
  1431. }
  1432. dwOffset = sizeof(UNIDRVINFO);
  1433. if (pFOutData->SelectFont.dwSize != 0)
  1434. {
  1435. pFOutData->UnidrvInfo.SelectFont.loOffset = dwOffset;
  1436. pFOutData->UnidrvInfo.SelectFont.dwCount = pFOutData->SelectFont.dwSize;
  1437. dwOffset += pFOutData->SelectFont.dwSize;
  1438. }
  1439. else
  1440. {
  1441. pFOutData->UnidrvInfo.SelectFont.loOffset = (DWORD)0;
  1442. pFOutData->UnidrvInfo.SelectFont.dwCount = (DWORD)0;
  1443. }
  1444. if (pFOutData->UnSelectFont.dwSize != 0)
  1445. {
  1446. pFOutData->UnidrvInfo.UnSelectFont.loOffset = dwOffset;
  1447. pFOutData->UnidrvInfo.UnSelectFont.dwCount = pFOutData->UnSelectFont.dwSize;
  1448. dwOffset += pFOutData->UnSelectFont.dwSize;
  1449. }
  1450. else
  1451. {
  1452. pFOutData->UnidrvInfo.UnSelectFont.loOffset = (DWORD)0;
  1453. pFOutData->UnidrvInfo.UnSelectFont.dwCount = (DWORD)0;
  1454. }
  1455. memset(pFOutData->UnidrvInfo.wReserved, 0, sizeof pFOutData->UnidrvInfo.wReserved);
  1456. return TRUE;
  1457. }
  1458. PUNI_GLYPHSETDATA
  1459. PGetDefaultGlyphset(
  1460. IN HANDLE hHeap,
  1461. IN WORD wFirstChar,
  1462. IN WORD wLastChar,
  1463. IN DWORD dwCodePage)
  1464. {
  1465. PUNI_GLYPHSETDATA pGlyphSetData;
  1466. PGLYPHRUN pGlyphRun, pGlyphRunTmp;
  1467. DWORD dwcbBits, *pdwBits, dwNumOfRuns;
  1468. WORD wI, wNumOfHandle;
  1469. WCHAR awchUnicode[256], wchMax, wchMin;
  1470. BYTE aubAnsi[256];
  1471. BOOL bInRun;
  1472. DWORD dwGTTLen;
  1473. #ifdef BUILD_FULL_GTT
  1474. PUNI_CODEPAGEINFO pCPInfo;
  1475. PMAPTABLE pMap;
  1476. PTRANSDATA pTrans;
  1477. int i, j, k, m ;
  1478. WORD wUnicode ;
  1479. #endif
  1480. wNumOfHandle = wLastChar - wFirstChar + 1;
  1481. for( wI = wFirstChar; wI <= wLastChar; ++wI )
  1482. {
  1483. aubAnsi[wI - wFirstChar] = (BYTE)wI;
  1484. }
  1485. if( ! MultiByteToWideChar(dwCodePage,
  1486. 0,
  1487. aubAnsi,
  1488. wNumOfHandle,
  1489. awchUnicode,
  1490. wNumOfHandle))
  1491. {
  1492. return NULL;
  1493. }
  1494. //
  1495. // Get min and max Unicode value
  1496. // Find the largest Unicode value, then allocate storage to allow us
  1497. // to create a bit array of valid unicode points. Then we can
  1498. // examine this to determine the number of runs.
  1499. //
  1500. for( wchMax = 0, wchMin = 0xffff, wI = 0; wI < wNumOfHandle; ++wI )
  1501. {
  1502. if( awchUnicode[ wI ] > wchMax )
  1503. wchMax = awchUnicode[ wI ];
  1504. if( awchUnicode[ wI ] < wchMin )
  1505. wchMin = awchUnicode[ wI ];
  1506. }
  1507. //
  1508. // Create Unicode bits table from CTT.
  1509. // Note that the expression 1 + wchMax IS correct. This comes about
  1510. // from using these values as indices into the bit array, and that
  1511. // this is essentially 1 based.
  1512. //
  1513. dwcbBits = (1 + wchMax + DWBITS - 1) / DWBITS * sizeof( DWORD );
  1514. if( !(pdwBits = (DWORD *)HeapAlloc( hHeap, 0, dwcbBits )) )
  1515. {
  1516. return FALSE; /* Nothing going */
  1517. }
  1518. ZeroMemory( pdwBits, dwcbBits );
  1519. //
  1520. // Set bits in this array corresponding to Unicode code points
  1521. //
  1522. for( wI = 0; wI < wNumOfHandle; ++wI )
  1523. {
  1524. pdwBits[ awchUnicode[ wI ] / DWBITS ]
  1525. |= (1 << (awchUnicode[ wI ] & DW_MASK));
  1526. }
  1527. //
  1528. // Count the number of run.
  1529. //
  1530. //
  1531. // Now we can examine the number of runs required. For starters,
  1532. // we stop a run whenever a hole is discovered in the array of 1
  1533. // bits we just created. Later we MIGHT consider being a little
  1534. // less pedantic.
  1535. //
  1536. bInRun = FALSE;
  1537. dwNumOfRuns = 0;
  1538. for( wI = 0; wI <= wchMax; ++wI )
  1539. {
  1540. if( pdwBits[ wI / DWBITS ] & (1 << (wI & DW_MASK)) )
  1541. {
  1542. /* Not in a run: is this the end of one? */
  1543. if( !bInRun )
  1544. {
  1545. /* It's time to start one */
  1546. bInRun = TRUE;
  1547. ++dwNumOfRuns;
  1548. }
  1549. }
  1550. else
  1551. {
  1552. if( bInRun )
  1553. {
  1554. /* Not any more! */
  1555. bInRun = FALSE;
  1556. }
  1557. }
  1558. }
  1559. //
  1560. // 7. Allocate memory for GTT and begin to fill in its header.
  1561. //
  1562. dwGTTLen = sizeof(UNI_GLYPHSETDATA) + dwNumOfRuns * sizeof(GLYPHRUN) ;
  1563. #ifdef BUILD_FULL_GTT
  1564. dwGTTLen += sizeof(UNI_CODEPAGEINFO) + sizeof(MAPTABLE)
  1565. + sizeof(TRANSDATA) * (wNumOfHandle - 1) ;
  1566. #endif
  1567. if( !(pGlyphSetData = (PUNI_GLYPHSETDATA)HeapAlloc(hHeap,
  1568. HEAP_ZERO_MEMORY,
  1569. dwGTTLen )) )
  1570. {
  1571. return FALSE;
  1572. }
  1573. #ifdef BUILD_FULL_GTT
  1574. pGlyphSetData->dwSize = dwGTTLen ;
  1575. pGlyphSetData->dwVersion = UNI_GLYPHSETDATA_VERSION_1_0 ;
  1576. pGlyphSetData->lPredefinedID = CC_NOPRECNV ;
  1577. pGlyphSetData->dwGlyphCount = wNumOfHandle ;
  1578. #endif
  1579. pGlyphSetData->dwRunCount = dwNumOfRuns;
  1580. pGlyphSetData->loRunOffset = sizeof(UNI_GLYPHSETDATA);
  1581. pGlyphRun = pGlyphRunTmp = (PGLYPHRUN)(pGlyphSetData + 1);
  1582. //
  1583. // 8. Create GLYPHRUN
  1584. //
  1585. bInRun = FALSE;
  1586. for (wI = 0; wI <= wchMax; wI ++)
  1587. {
  1588. if (pdwBits[ wI/ DWBITS ] & (1 << (wI & DW_MASK)) )
  1589. {
  1590. if (!bInRun)
  1591. {
  1592. bInRun = TRUE;
  1593. pGlyphRun->wcLow = wI;
  1594. pGlyphRun->wGlyphCount = 1;
  1595. }
  1596. else
  1597. {
  1598. pGlyphRun->wGlyphCount++;
  1599. }
  1600. }
  1601. else
  1602. {
  1603. if (bInRun)
  1604. {
  1605. bInRun = FALSE;
  1606. pGlyphRun++;
  1607. }
  1608. }
  1609. }
  1610. //
  1611. // 9. Create CODEPAGEINFO and set related GTT header fields.
  1612. //
  1613. #ifdef BUILD_FULL_GTT
  1614. pGlyphSetData->dwCodePageCount = 1 ;
  1615. pGlyphSetData->loCodePageOffset = pGlyphSetData->loRunOffset
  1616. + dwNumOfRuns * sizeof(GLYPHRUN) ;
  1617. pCPInfo = (PUNI_CODEPAGEINFO)
  1618. ((UINT_PTR) pGlyphSetData + pGlyphSetData->loCodePageOffset) ;
  1619. pCPInfo->dwCodePage = dwCodePage ;
  1620. pCPInfo->SelectSymbolSet.dwCount = pCPInfo->SelectSymbolSet.loOffset = 0 ;
  1621. pCPInfo->UnSelectSymbolSet.dwCount = pCPInfo->UnSelectSymbolSet.loOffset = 0 ;
  1622. //
  1623. // 10. Create MAPTABLE and set related GTT header fields.
  1624. //
  1625. pGlyphSetData->loMapTableOffset = pGlyphSetData->loCodePageOffset +
  1626. sizeof(UNI_CODEPAGEINFO) ;
  1627. pMap = (PMAPTABLE) ((UINT_PTR) pGlyphSetData + pGlyphSetData->loMapTableOffset) ;
  1628. pMap->dwSize = sizeof(MAPTABLE) + sizeof(TRANSDATA) * (wNumOfHandle - 1) ;
  1629. pMap->dwGlyphNum = wNumOfHandle ;
  1630. pTrans = (PTRANSDATA) &(pMap->Trans[0]) ;
  1631. pGlyphRun = pGlyphRunTmp ;
  1632. for (i = m = 0 ; i <= (int) pGlyphSetData->dwRunCount ; i++, pGlyphRun++) {
  1633. for (j = 0 ; j <= pGlyphRun->wGlyphCount ; j ++) {
  1634. wUnicode = pGlyphRun->wcLow + j ;
  1635. for (k = 0 ; k <= 255 ; k ++)
  1636. if (wUnicode == awchUnicode[k])
  1637. break ;
  1638. ASSERT(k < 256) ;
  1639. pTrans->uCode.ubCode = aubAnsi[k] ;
  1640. pTrans->ubCodePageID = 0 ;
  1641. pTrans->ubType = MTYPE_DIRECT ;
  1642. pTrans++;
  1643. } ;
  1644. m += pGlyphRun->wGlyphCount ;
  1645. } ;
  1646. ASSERT(m != wNumOfHandle) ;
  1647. #endif
  1648. return pGlyphSetData;
  1649. }