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.

1405 lines
39 KiB

  1. /*++
  2. Copyright (c) 1996 - 1999 Microsoft Corporation
  3. Module Name:
  4. fminit.c
  5. Abstract:
  6. Font Module: device font intialization modules.
  7. Environment:
  8. Windows NT Unidrv driver
  9. Revision History:
  10. 11/28/96 -ganeshp-
  11. Created
  12. --*/
  13. #include "font.h"
  14. //
  15. // Forward declarations
  16. //
  17. INT
  18. IFontID2Index( FONTPDEV *pFontPDev,
  19. int iID
  20. );
  21. VOID
  22. VLoadDeviceFontsResDLLs(
  23. PDEV *pPDev
  24. );
  25. DWORD
  26. CopyMemoryRLE(
  27. PVOID pvData,
  28. PBYTE pubSrc,
  29. DWORD dwSize
  30. );
  31. //
  32. // Functions
  33. //
  34. INT
  35. IInitDeviceFonts (
  36. PDEV *pPDev
  37. )
  38. /*++
  39. Routine Description:
  40. Doing the actual grovelling around for font data. We have a bit
  41. array of available fonts (created above), so we use that as the
  42. basis of filling in the rest of the information.
  43. Arguments:
  44. pPDev Pointer to PDEV
  45. Return Value:
  46. The number of fonts available.
  47. Note:
  48. 11-27-96: Created it -ganeshp-
  49. --*/
  50. {
  51. INT iIndex; // Loop index
  52. INT cBIFonts; // Fonts built in to mini-driver
  53. INT cXFonts = 0; // Non-minidriver font count
  54. INT cFonts; // Total number of fonts
  55. //TODEL BOOL bExpand; Set when font derivatives are available.
  56. FONTMAP *pfm; // Create this data
  57. PFONTPDEV pFontPDev = pPDev->pFontPDev;
  58. //
  59. // So how many fonts do we have? Count them so that we can allocate
  60. // storage for the array of FONTMAPs.
  61. //
  62. cBIFonts = pFontPDev->iDevFontsCt;
  63. if (!pFontPDev->hUFFFile)
  64. #ifdef KERNEL_MODE
  65. pFontPDev->hUFFFile = FIOpenFontFile(pPDev->devobj.hPrinter, pPDev->devobj.hEngine, NULL);
  66. #else
  67. pFontPDev->hUFFFile = FIOpenFontFile(pPDev->devobj.hPrinter, NULL);
  68. #endif
  69. if (pFontPDev->hUFFFile)
  70. cXFonts = FIGetNumFonts(pFontPDev->hUFFFile);
  71. else
  72. cXFonts = 0;
  73. pFontPDev->iSoftFontsCt = cXFonts;
  74. //
  75. // Allocate enough memory to hold font map table.
  76. //
  77. cFonts = cBIFonts + cXFonts;
  78. pfm = (FONTMAP *)MemAllocZ( cFonts * SIZEOFDEVPFM() );
  79. if( pfm == 0 )
  80. {
  81. //
  82. // Failed to allocate memory
  83. //
  84. cFonts = cBIFonts = cXFonts = 0;
  85. ERR(("Failed to allocate memory"));
  86. }
  87. else
  88. {
  89. pFontPDev->pFontMap = pfm;
  90. //
  91. // Select the first font as the default font, just in case the
  92. // value is not initialised in the loop below.
  93. //
  94. pFontPDev->pFMDefault = pfm;
  95. //
  96. // Continue only if there are device fonts.
  97. //
  98. if( cFonts )
  99. {
  100. //
  101. // Initialize the default font: we always do this now, as it is
  102. // required to return the default font at DrvEnablePDEV time,
  103. // and it is also simpler for us.
  104. //
  105. iIndex = IFontID2Index( pFontPDev, pFontPDev->dwDefaultFont );
  106. if( iIndex >= 0 && iIndex < cFonts )
  107. {
  108. // Found the default font ID, so now set up details
  109. pfm = (PFONTMAP)( (PBYTE)pFontPDev->pFontMap
  110. + SIZEOFDEVPFM() * iIndex);
  111. //
  112. // Index returned by IFontID2Index is 0 based. So no need to
  113. // Convert it to 0 based.
  114. // BFillinDeviceFM assumes it to be 0 based.
  115. //
  116. if( BFillinDeviceFM( pPDev, pfm, iIndex) )
  117. {
  118. pFontPDev->pFMDefault = pfm;
  119. }
  120. else
  121. {
  122. WARNING(("BFillinDeviceFM Fails\n"));
  123. cFonts = cBIFonts = cXFonts = 0;
  124. }
  125. }
  126. else
  127. WARNING(("No Default Font Using first as default\n"));
  128. //
  129. // Fill in some default font sensitive numbers!
  130. //
  131. pfm->flFlags |= FM_DEFAULT;
  132. //
  133. // Set the size of the default font
  134. //
  135. if (pfm->pIFIMet)
  136. {
  137. pPDev->ptDefaultFont.y = ((IFIMETRICS *)pfm->pIFIMet)->fwdWinAscender/2;
  138. pPDev->ptDefaultFont.x = ((IFIMETRICS *)pfm->pIFIMet)->fwdAveCharWidth;
  139. }
  140. else
  141. {
  142. ERR(("Bad IFI Metrics Pointer\n"));
  143. cFonts = cBIFonts = cXFonts = 0;
  144. }
  145. }
  146. }
  147. //
  148. // Check for error condition. If an error has occured set devfont to 0
  149. //
  150. if (!cFonts)
  151. {
  152. pFontPDev->iDevFontsCt =
  153. pFontPDev->iDevResFontsCt =
  154. pFontPDev->iSoftFontsCt = 0;
  155. }
  156. //
  157. // Now load any alternate resource DLLs from where device font has to be
  158. // loaded. This is necessary now because snapshot will be unloaded after
  159. // DrvEnablePDev and WinResData.pUIInfo will be invalid. Because of this
  160. // DLL load will fail.
  161. //
  162. VLoadDeviceFontsResDLLs(pPDev);
  163. pPDev->iFonts = cFonts; /* As many as we got */
  164. return cFonts;
  165. }
  166. BOOL
  167. BFillinDeviceFM(
  168. PDEV *pPDev,
  169. FONTMAP *pfm,
  170. int iIndex
  171. )
  172. /*++
  173. Routine Description:
  174. Fill in (most) of the FONTMAP structure passed in. The data is
  175. obtained from either the minidriver resources or from from the
  176. font installer file. The only part we do not set is the NTRLE
  177. data, as that is a little more complex.
  178. Arguments:
  179. pPDev - Pointer to PDEV.
  180. pfm - The FONTMAP structure to fill in
  181. iIndex - The 0 based index of the font to fill in
  182. Return Value:
  183. TRUE - for success
  184. FALSE - for failure
  185. Note:
  186. 12-04-96: Created it -ganeshp-
  187. --*/
  188. {
  189. PFONTPDEV pFontPDev; /* More specific data */
  190. PFONTMAP_DEV pfmdev;
  191. RES_ELEM ResElem; /* For manipulating resource data */
  192. pFontPDev = pPDev->pFontPDev;
  193. pfm->dwSignature = FONTMAP_ID;
  194. pfm->dwSize = sizeof(FONTMAP);
  195. pfm->dwFontType = FMTYPE_DEVICE;
  196. pfm->pSubFM = (PFONTMAP_DEV)(pfm+1);
  197. pfmdev = pfm->pSubFM;
  198. /*
  199. * Activity depends upon whether we have an internal or
  200. * external font. Externals are softfonts, other than GDI downloaded.
  201. */
  202. if( iIndex < pFontPDev->iDevFontsCt )
  203. {
  204. DWORD dwFont; /* Convert index to resource number */
  205. /* Get the font ID for this index */
  206. dwFont = pFontPDev->FontList.pdwList[iIndex];
  207. //
  208. // Check the Font Format of the resource. The new font IFI is stored
  209. // with RC_UFM tag. The old one was stored using RC_FONT.
  210. //
  211. if( BGetWinRes( &(pPDev->WinResData), (PQUALNAMEEX)&dwFont, RC_FONT, &ResElem ) )
  212. {
  213. pfm->flFlags |= FM_IFIVER40;
  214. if( !BGetOldFontInfo( pfm, ResElem.pvResData ) )
  215. return FALSE;
  216. }
  217. else
  218. if(BGetWinRes( &(pPDev->WinResData),(PQUALNAMEEX)&dwFont,RC_UFM,&ResElem) )
  219. {
  220. if ( !BGetNewFontInfo(pfm, ResElem.pvResData) )
  221. return FALSE;
  222. if (pPDev->bTTY)
  223. ((FONTMAP_DEV*)pfm->pSubFM)->ulCodepage = pFontPDev->dwTTYCodePage;
  224. }
  225. else
  226. {
  227. ERR(("Can't Load the font data for res_id= %d\n", dwFont));
  228. return FALSE;
  229. }
  230. //
  231. // Create the data we need. Unidrv5 only supports NT specific data.
  232. //
  233. pfmdev->dwResID = dwFont;
  234. }
  235. else
  236. {
  237. INT iFont = iIndex - pFontPDev->iDevFontsCt;
  238. /*
  239. * This must be an external font, so we need to call the
  240. * code that understands how external font files are built.
  241. */
  242. if( !BFMSetupXF( pfm, pPDev, iFont ) )
  243. return FALSE;
  244. pfmdev->dwResID = iFont;
  245. }
  246. /*
  247. * If needed, scale the numbers to fit the desired resolution.
  248. */
  249. if( !BIFIScale( pfm, pPDev->ptGrxRes.x, pPDev->ptGrxRes.y ) )
  250. return FALSE;
  251. /*
  252. * Miscellaneous FM fields that can now be filled in.
  253. */
  254. pfm->wFirstChar = ((IFIMETRICS *)pfm->pIFIMet)->wcFirstChar;
  255. pfm->wLastChar = ((IFIMETRICS *)pfm->pIFIMet)->wcLastChar;
  256. /*
  257. * If this is an outline font, then mark it as scalable. This
  258. * piece of information is required at font selection time.
  259. */
  260. if (((IFIMETRICS *)pfm->pIFIMet)->flInfo & (FM_INFO_ISOTROPIC_SCALING_ONLY|FM_INFO_ANISOTROPIC_SCALING_ONLY|FM_INFO_ARB_XFORMS))
  261. pfm->flFlags |= FM_SCALABLE;
  262. /*
  263. * Select the translation table for this font. If it is zero,
  264. * then use the default translation table, contained in ModelData.
  265. */
  266. if( pfmdev->sCTTid == 0 )
  267. pfmdev->sCTTid = (SHORT)pFontPDev->sDefCTT;
  268. /*
  269. * Some printers output the character with the cursor positioned
  270. * at the baseline, others with it located at the top of the
  271. * character cell. We store the needed offset in the FONTMAP
  272. * data, to simplify life during output. The data returned by
  273. * DrvQueryFontData is relative to the baseline. For baseline
  274. * based fonts, we need do nothing. For top of cell fonts,
  275. * the fwdWinAscender value needs to be SUBTRACTED from the Y position
  276. * to determine the glyph's location on the page.
  277. */
  278. //
  279. // Set for non-scalable font
  280. // This value has to be scaled for scalable device font.
  281. //
  282. if( !(pFontPDev->flFlags & FDV_ALIGN_BASELINE) )
  283. pfm->syAdj = -((IFIMETRICS *)(pfm->pIFIMet))->fwdWinAscender;
  284. else
  285. pfm->syAdj = 0; /* There is none */
  286. /*
  287. * Dot matrix printers also do funny things with double high
  288. * characters. To handle this, the GPC spec contains a move
  289. * amount to add to the Y position before printing with these
  290. * characters. There is also the adjustment for position
  291. * movement after printing.
  292. */
  293. pfmdev->sYAdjust = (SHORT)(pfmdev->sYAdjust * pPDev->ptGrxRes.y / pfm->wYRes);
  294. pfmdev->sYMoved = (SHORT)(pfmdev->sYMoved * pPDev->ptGrxRes.y / pfm->wYRes);
  295. //
  296. // Funciton pointer initialization.
  297. //
  298. pfm->pfnDownloadFontHeader = NULL;
  299. pfm->pfnDownloadGlyph = NULL;
  300. pfm->pfnCheckCondition = NULL;
  301. //
  302. // PCL-XL hack
  303. //
  304. if (pPDev->ePersonality == kPCLXL)
  305. {
  306. pfm->pfnGlyphOut = DwOutputGlyphCallback;
  307. pfm->pfnSelectFont = BSelectFontCallback;
  308. pfm->pfnDeSelectFont = BDeselectFontCallback;
  309. }
  310. else
  311. if( pfm->flFlags & FM_IFIVER40 )
  312. {
  313. pfm->pfnGlyphOut = BRLEOutputGlyph;
  314. pfm->pfnSelectFont = BRLESelectFont;
  315. pfm->pfnDeSelectFont = BRLEDeselectFont;
  316. }
  317. else
  318. {
  319. pfm->pfnGlyphOut = BGTTOutputGlyph;
  320. pfm->pfnSelectFont = BGTTSelectFont;
  321. pfm->pfnDeSelectFont = BGTTDeselectFont;
  322. }
  323. if (pfm->flFlags & FM_SOFTFONT)
  324. {
  325. pfm->pfnSelectFont = BSelectTrueTypeBMP;
  326. }
  327. if (pPDev->pOemHookInfo)
  328. {
  329. if (pPDev->pOemHookInfo[EP_OEMOutputCharStr].pfnHook)
  330. {
  331. pfm->pfnGlyphOut = DwOutputGlyphCallback;
  332. }
  333. if (pPDev->pOemHookInfo[EP_OEMSendFontCmd].pfnHook)
  334. {
  335. pfm->pfnSelectFont = BSelectFontCallback;
  336. pfm->pfnDeSelectFont = BDeselectFontCallback;
  337. }
  338. }
  339. if (pfm->flFlags & FM_SCALABLE)
  340. {
  341. switch (pfmdev->wDevFontType)
  342. {
  343. case DF_TYPE_HPINTELLIFONT:
  344. case DF_TYPE_TRUETYPE:
  345. pfmdev->pfnDevSelFont = BSelectPCLScalableFont;
  346. break;
  347. case DF_TYPE_PST1:
  348. pfmdev->pfnDevSelFont = BSelectPPDSScalableFont;
  349. break;
  350. case DF_TYPE_CAPSL:
  351. pfmdev->pfnDevSelFont = BSelectCapslScalableFont;
  352. break;
  353. }
  354. }
  355. else
  356. {
  357. pfmdev->pfnDevSelFont = BSelectNonScalableFont;
  358. }
  359. //
  360. // Get Glyph data (RLE/GTT)
  361. //
  362. VFillinGlyphData( pPDev, pfm );
  363. return TRUE;
  364. }
  365. BOOL
  366. BFMSetupXF(
  367. FONTMAP *pfm,
  368. PDEV *pPDev,
  369. INT iIndex
  370. )
  371. /*++
  372. Routine Description:
  373. Function to setup the FONTMAP data for an external font. We take the
  374. next entry in the file, which is presumed to have been rewound
  375. before we start being called.
  376. Arguments:
  377. pfm - Pointer to FONTMAP.
  378. pPDev - Pointer to PDEV.
  379. iIndex - Index of the font.
  380. Return Value:
  381. TRUE - for success
  382. FALSE - for EOF
  383. Note:
  384. 12-05-96: Created it -ganeshp-
  385. --*/
  386. {
  387. FONTPDEV *pFontPDev = pPDev->pFontPDev;
  388. UFF_FONTDIRECTORY *pFontDir;
  389. DATA_HEADER *pDataHeader;
  390. FONTMAP_DEV *pFMSub;
  391. BOOL bRet;
  392. //
  393. // Not much to do. We basically need to convert the offsets in
  394. // the FONTMAP in the file (mapped into memory) into absolute
  395. // addresses so that the remainder of the driver is ignorant of
  396. // We also set some flags to make it clear
  397. // what type of font and memory we are.
  398. //
  399. if (!(pDataHeader = FIGetFontData(pFontPDev->hUFFFile, iIndex)))
  400. {
  401. ERR(( "FIGetFontData returns FALSE!!\n" ));
  402. return FALSE;
  403. }
  404. pFMSub = pfm->pSubFM;
  405. if (pFontDir = FIGetFontDir(pFontPDev->hUFFFile))
  406. {
  407. pFMSub->pFontDir = pFontDir + iIndex;
  408. }
  409. //
  410. // Check if this is a cartridge font and set flag
  411. //
  412. if (!pFMSub->pFontDir->offCartridgeName)
  413. pfm->flFlags |= FM_SOFTFONT;
  414. pfm->flFlags |= FM_EXTERNAL;
  415. switch (pDataHeader->dwSignature)
  416. {
  417. case DATA_IFI_SIG:
  418. pfm->flFlags |= FM_GLYVER40 | FM_IFIVER40;
  419. BGetOldFontInfo(pfm, (PBYTE)pDataHeader + pDataHeader->wSize);
  420. bRet = TRUE;
  421. break;
  422. case DATA_UFM_SIG:
  423. BGetNewFontInfo(pfm, (PBYTE)pDataHeader + pDataHeader->wSize);
  424. bRet = TRUE;
  425. break;
  426. default:
  427. bRet = FALSE;
  428. break;
  429. }
  430. return bRet;
  431. }
  432. //
  433. // Misc functions
  434. //
  435. #define XSCALE( x ) (x) = (FWORD)((( x ) * xdpi + iXDiv / 2) / iXDiv)
  436. #define YSCALE( y ) (y) = (FWORD)((( y ) * ydpi + iYDiv / 2) / iYDiv)
  437. #define YSCALENEG( y ) (y) = (FWORD)((( y ) * ydpi - iYDiv / 2) / iYDiv)
  438. BOOL
  439. BIFIScale(
  440. FONTMAP *pfm,
  441. INT xdpi,
  442. INT ydpi
  443. )
  444. /*++
  445. Routine Description:
  446. Scale the IFIMETRICS fields to match the device resolution. The
  447. IFIMETRICS are created using the device's master units, which
  448. may not correspond with the resolution desired this time around.
  449. If they are different, then we adjust. May also need to allocate
  450. memory, because resource data cannot be written to.
  451. Arguments:
  452. pfm - Pointer to FONTMAP.
  453. xdpi - Selcted X Graphics Resolution.
  454. ydpi - Selcted Y Graphics Resolution.
  455. Return Value:
  456. TRUE - for success
  457. FALSE - for failure
  458. Note:
  459. 12-05-96: Created it -ganeshp-
  460. --*/
  461. {
  462. IFIMETRICS *pIFI;
  463. int iXDiv, iYDiv; /* Used in scaling */
  464. pIFI = pfm->pIFIMet;
  465. if (NULL == pIFI)
  466. {
  467. return FALSE;
  468. }
  469. if( (int)pfm->wXRes != xdpi || (int)pfm->wYRes != ydpi )
  470. {
  471. /* Need to scale, so need memory to create writeable version */
  472. BYTE *pbMem; /* For convenience */
  473. if( pfm->flFlags & FM_IFIRES )
  474. {
  475. /*
  476. * The data is in a resource, so we need to do something
  477. * civilised: copy the data to memory that can be written.
  478. */
  479. if( pbMem = MemAllocZ( pIFI->cjThis ) )
  480. {
  481. /* Got the memory, so copy it and off we go */
  482. CopyMemory( pbMem, (BYTE *)pIFI, pIFI->cjThis );
  483. pIFI = (IFIMETRICS *)pbMem;
  484. pfm->pIFIMet = pIFI;
  485. pfm->flFlags &= ~FM_IFIRES; /* No longer */
  486. }
  487. else
  488. return FALSE;
  489. }
  490. if( (int)pfm->wXRes != xdpi )
  491. {
  492. /* Adjust the X values, as required */
  493. if( !(iXDiv = pfm->wXRes) )
  494. iXDiv = xdpi; /* Better than div by 0 */
  495. XSCALE( pIFI->fwdMaxCharInc );
  496. XSCALE( pIFI->fwdAveCharWidth );
  497. XSCALE( pIFI->fwdSubscriptXSize );
  498. XSCALE( pIFI->fwdSubscriptXOffset );
  499. XSCALE( pIFI->fwdSuperscriptXSize );
  500. XSCALE( pIFI->fwdSuperscriptXOffset );
  501. XSCALE( pIFI->ptlAspect.x );
  502. XSCALE( pIFI->rclFontBox.left );
  503. XSCALE( pIFI->rclFontBox.right );
  504. if (pIFI->dpFontSim)
  505. {
  506. PTRDIFF dpTmp;
  507. FONTDIFF* pFontDiff;
  508. FONTSIM* pFontSim;
  509. pFontSim = (FONTSIM*) ((PBYTE) pIFI + pIFI->dpFontSim);
  510. if (dpTmp = pFontSim->dpBold)
  511. {
  512. pFontDiff = (FONTDIFF*)((PBYTE)pFontSim + dpTmp);
  513. XSCALE( pFontDiff->fwdMaxCharInc );
  514. XSCALE( pFontDiff->fwdAveCharWidth );
  515. }
  516. if (dpTmp = pFontSim->dpItalic)
  517. {
  518. pFontDiff = (FONTDIFF*)((PBYTE)pFontSim + dpTmp);
  519. XSCALE( pFontDiff->fwdMaxCharInc );
  520. XSCALE( pFontDiff->fwdAveCharWidth );
  521. }
  522. if (dpTmp = pFontSim->dpBoldItalic)
  523. {
  524. pFontDiff = (FONTDIFF*)((PBYTE)pFontSim + dpTmp);
  525. XSCALE( pFontDiff->fwdMaxCharInc );
  526. XSCALE( pFontDiff->fwdAveCharWidth );
  527. }
  528. }
  529. }
  530. if( (int)pfm->wYRes != ydpi )
  531. {
  532. /*
  533. * Note that some of these numbers are negative, and so
  534. * we need to round them correctly - i.e. subtract the rounding
  535. * factor to move the value further from 0.
  536. */
  537. int iPixHeight;
  538. if( !(iYDiv = pfm->wYRes) )
  539. iYDiv = ydpi;
  540. /* Adjust the Y values, as required */
  541. /*
  542. * NOTE: simply scaling will NOT produce the same values
  543. * as Win 3.1 This is because of what gets rounded. Win 3.1
  544. * does not have the WinDescender field, but calculates it
  545. * from dfPixHeight and dfAscent AFTER THESE HAVE BEEN SCALED
  546. * (INCLUDING ROUNDING!!). To emulate that, we calculate
  547. * the dfPixHeight value, then scale that and dfAscent to
  548. * allow us to "properly" calculate WinDescender. This stuff
  549. * is needed for Win 3.1 compatability!
  550. */
  551. YSCALE( pIFI->fwdUnitsPerEm );
  552. iPixHeight = pIFI->fwdWinAscender + pIFI->fwdWinDescender;
  553. YSCALE( iPixHeight );
  554. YSCALE( pIFI->fwdWinAscender );
  555. pIFI->fwdWinDescender = iPixHeight - pIFI->fwdWinAscender;
  556. YSCALE( pIFI->fwdMacAscender );
  557. pIFI->fwdMacDescender = -pIFI->fwdWinDescender;
  558. YSCALE( pIFI->fwdMacLineGap );
  559. YSCALE( pIFI->fwdTypoAscender );
  560. YSCALE( pIFI->fwdTypoDescender );
  561. YSCALE( pIFI->fwdTypoLineGap);
  562. YSCALE( pIFI->fwdCapHeight );
  563. YSCALE( pIFI->fwdXHeight );
  564. YSCALE( pIFI->fwdSubscriptYSize );
  565. YSCALENEG( pIFI->fwdSubscriptYOffset );
  566. YSCALE( pIFI->fwdSuperscriptYSize );
  567. YSCALE( pIFI->fwdSuperscriptYOffset );
  568. YSCALE( pIFI->fwdUnderscoreSize );
  569. if( pIFI->fwdUnderscoreSize == 0 )
  570. pIFI->fwdUnderscoreSize = 1; /* In case it vanishes */
  571. YSCALENEG( pIFI->fwdUnderscorePosition );
  572. if( pIFI->fwdUnderscorePosition == 0 )
  573. pIFI->fwdUnderscorePosition = -1;
  574. YSCALE( pIFI->fwdStrikeoutSize );
  575. if( pIFI->fwdStrikeoutSize == 0 )
  576. pIFI->fwdStrikeoutSize = 1; /* In case it vanishes */
  577. YSCALE( pIFI->fwdStrikeoutPosition );
  578. YSCALE( pIFI->ptlAspect.y );
  579. YSCALE( pIFI->rclFontBox.top );
  580. YSCALE( pIFI->rclFontBox.bottom );
  581. #undef XSCALE
  582. #undef YSCALE
  583. #undef YSCALENEG
  584. }
  585. }
  586. return TRUE;
  587. }
  588. HANDLE
  589. HLoadUniResDll(PDEV *pPDev)
  590. {
  591. PWSTR pwstrTmp, pwstrResFileName, pwstrDrvName;
  592. HANDLE hHandle = NULL;
  593. HRESULT hr = S_FALSE;
  594. SIZE_T cchBuf = 0;
  595. if (pPDev->pDriverInfo3)
  596. pwstrDrvName = pPDev->pDriverInfo3->pDriverPath;
  597. else
  598. return NULL;
  599. cchBuf = 1 + wcslen(pwstrDrvName);
  600. pwstrResFileName = MemAlloc( cchBuf * sizeof(WCHAR));
  601. if (pwstrResFileName == NULL)
  602. return NULL;
  603. hr = StringCchCopy ( pwstrResFileName, cchBuf, pwstrDrvName);
  604. if ( SUCCEEDED (hr) )
  605. {
  606. #ifdef WINNT_40
  607. if (!(pwstrTmp = wcsstr(pwstrResFileName, TEXT("UNIDRV4.DLL"))))
  608. #else
  609. if (!(pwstrTmp = wcsstr(pwstrResFileName, TEXT("UNIDRV.DLL"))))
  610. #endif
  611. {
  612. MemFree(pwstrResFileName);
  613. return NULL;
  614. }
  615. *pwstrTmp = UNICODE_NULL;
  616. hr = StringCchCat ( pwstrResFileName, cchBuf, TEXT("unires.dll"));
  617. if ( SUCCEEDED (hr) )
  618. {
  619. hHandle = EngLoadModule(pwstrResFileName);
  620. #ifdef DBG
  621. if (!hHandle)
  622. {
  623. ERR(("UNIDRV: Failed to load UNIRES.DLL\n"));
  624. }
  625. #endif
  626. }
  627. } // if StringCchCopy succeeds.
  628. MemFree(pwstrResFileName);
  629. return hHandle;
  630. }
  631. VOID
  632. VFillinGlyphData(
  633. PDEV *pPDev,
  634. FONTMAP *pfm
  635. )
  636. /*++
  637. Routine Description:
  638. Provide the RLE data required for this font. Basically look to see
  639. if some other font has this RLE data already loaded; if so, then
  640. point to that and return. Otherwise, load the resource etc.
  641. Arguments:
  642. pPDev - Pointer to PDEV.
  643. pfm - The FONTMAP whose Gyphy Translation data is required
  644. Return Value:
  645. Nothing
  646. Note:
  647. 12-05-96: Created it -ganeshp-
  648. --*/
  649. {
  650. int iIndex; /* Scan the existing array */
  651. short sCurVal; /* Speedier access */
  652. BOOL bSymbol;
  653. DWORD dwCurVal;
  654. PQUALNAMEEX pQualName = (PQUALNAMEEX)&dwCurVal;
  655. PVOID pvData; /* The FD_GLYPHSET format we want */
  656. FONTMAP *pfmIndex; /* Speedy scanning of existing list */
  657. FONTMAP_DEV *pfmdev, *pfmdevIndex;
  658. FONTPDEV *pFontPDev; /* More specialised data */
  659. TRACE(\nUniFont!VFillinGlyphData:START);
  660. pvData = NULL; /* In case Nothing we can do! */
  661. pfmdev = pfm->pSubFM;
  662. bSymbol = IS_SYMBOL_CHARSET(pfm);
  663. /*
  664. * First step is to look through the existing FONTMAP array, and
  665. * if we find one with the same sCTTid and same format as us, use it!
  666. * Otherwise,we need to load the resource and do it the hard way!
  667. */
  668. pFontPDev = pPDev->pFontPDev;
  669. if (pfm->flFlags & FM_EXTERNAL)
  670. {
  671. sCurVal = pfmdev->pFontDir->sGlyphID;
  672. }
  673. else
  674. {
  675. //
  676. // Minidriver Resource case.
  677. // RLE/GTT file must be in the same DLL as IFI/UFM is.
  678. //
  679. //
  680. // Convert the resource ID to fully qualied ID. The format is
  681. // OptionID.ResFeatureID.ResourceID. Get the option and feature ID from
  682. // fontmap dwRes
  683. //
  684. pQualName->wResourceID = sCurVal = pfmdev->sCTTid;
  685. pQualName->bFeatureID = pfmdev->QualName.bFeatureID;
  686. pQualName->bOptionID = pfmdev->QualName.bOptionID;
  687. }
  688. pfmIndex = pFontPDev->pFontMap;
  689. for( iIndex = 0;
  690. iIndex < pPDev->iFonts;
  691. ++iIndex, pfmIndex = (PFONTMAP)((PBYTE)pfmIndex + SIZEOFDEVPFM()) )
  692. {
  693. pfmdevIndex = (PFONTMAP_DEV) pfmIndex->pSubFM;
  694. if( (pfmdevIndex &&
  695. pfmdevIndex->pvNTGlyph) &&
  696. pfmIndex->pIFIMet &&
  697. (pfmdevIndex->sCTTid == sCurVal) &&
  698. ((pfmIndex->flFlags & FM_IFIVER40) ==
  699. (pfm->flFlags & FM_IFIVER40)) &&
  700. ((pfmIndex->flFlags & FM_EXTERNAL) ==
  701. (pfm->flFlags & FM_EXTERNAL)) &&
  702. pfm->pIFIMet->jWinCharSet ==
  703. pfmIndex->pIFIMet->jWinCharSet )
  704. {
  705. //
  706. // Found it, so use that address!!
  707. //
  708. pfmdev->pvNTGlyph = pfmdevIndex->pvNTGlyph;
  709. //
  710. //Mark the flag for Glyph Data Format.
  711. //
  712. if (pfmIndex->flFlags & FM_GLYVER40)
  713. pfm->flFlags |= FM_GLYVER40;
  714. if (bSymbol)
  715. {
  716. pfm->wLastChar = SYMBOL_END;
  717. if (!(pfm->flFlags & FM_IFIRES))
  718. pfm->pIFIMet->wcLastChar = SYMBOL_END;
  719. }
  720. TRACE(Using a Already Loaded Translation Table.)
  721. PRINTVAL((pfm->flFlags & FM_GLYVER40), 0X%x);
  722. PRINTVAL((pfm->flFlags & FM_IFIVER40), 0X%x);
  723. TRACE(UniFont!VFillinGlyphData:END\n);
  724. return;
  725. }
  726. }
  727. /*
  728. * Do it the hard way - load the resource, convert as needed etc.
  729. */
  730. if( sCurVal < 0 )
  731. {
  732. /* Use Predefined resource */
  733. DWORD dwSize; /* Data size of resource */
  734. int iRCType;
  735. HMODULE hUniResDLL;
  736. BYTE *pb;
  737. if (!pPDev->hUniResDLL)
  738. pPDev->hUniResDLL = HLoadUniResDll(pPDev);
  739. hUniResDLL = pPDev->hUniResDLL;
  740. /*
  741. * These are resources we have, so we need to use
  742. * the normal resource mechanism to get the data.
  743. */
  744. ASSERTMSG( hUniResDLL,("UNIDRV!vFillinGlyphData - Null Module handle \n"));
  745. //VERBOSE(("Using prdefined Glyph Data for Font res_id = %d!!!\n",pfmdev->dwResID));
  746. PRINTVAL( (LONG)sCurVal, %ld );
  747. //
  748. // Load the old format RLE if the font format is NT40.
  749. // Otherwise, New Format PreDefined Glyph Data.
  750. //
  751. if ( hUniResDLL )
  752. {
  753. if (pfm->flFlags & FM_IFIVER40)
  754. {
  755. iRCType = RC_TRANSTAB;
  756. }
  757. else
  758. {
  759. iRCType = RC_GTT;
  760. }
  761. pb = EngFindResource( hUniResDLL, (-sCurVal), iRCType, &dwSize );
  762. if( pb )
  763. {
  764. if (pfm->flFlags & FM_IFIVER40)
  765. {
  766. NT_RLE_res *pntrle_res = (NT_RLE_res*)pb;
  767. dwSize = sizeof(NT_RLE) +
  768. (pntrle_res->fdg_cRuns - 1) * sizeof(WCRUN) +
  769. pntrle_res->cjThis - pntrle_res->fdg_wcrun_awcrun[0].dwOffset_phg;
  770. if( !(pvData = (VOID *)MemAllocZ( dwSize )) ||
  771. dwSize != CopyMemoryRLE( pvData, pb, dwSize ) )
  772. {
  773. MemFree(pvData);
  774. pvData = NULL;
  775. ERR(("\n!!!UniFont!VFillinGlyphData:MemAllocZ Failed.\
  776. \nFontID = %d,Name = %ws,CTTid = %d\n\n",pfmdev->dwResID,\
  777. (PBYTE)pfm->pIFIMet + pfm->pIFIMet->dpwszFaceName,(-sCurVal)));
  778. }
  779. pfm->flFlags |= FM_GLYVER40;
  780. }
  781. else
  782. {
  783. if( pvData = (VOID *)MemAllocZ( dwSize ) )
  784. CopyMemory( pvData, pb, dwSize );
  785. else
  786. {
  787. ERR(("\n!!!UniFont!VFillinGlyphData:MemAllocZ Failed.\
  788. \nFontID = %d,Name = %ws,CTTid = %d\n\n",pfmdev->dwResID,\
  789. (PBYTE)pfm->pIFIMet + pfm->pIFIMet->dpwszFaceName,(-sCurVal)));
  790. }
  791. }
  792. /* This One wil be freed when done */
  793. pfm->flFlags |= FM_FREE_GLYDATA;
  794. }
  795. else
  796. {
  797. ERR(("\n!!!UniFont!VFillinGlyphData:EngFindResource Failed\n"));
  798. }
  799. }
  800. }
  801. else if( pfm->flFlags & FM_EXTERNAL)
  802. {
  803. PDATA_HEADER pDataHeader;
  804. pDataHeader = FIGetGlyphData(pFontPDev->hUFFFile, sCurVal);
  805. if (pDataHeader)
  806. pvData = (PBYTE)pDataHeader + pDataHeader->wSize;
  807. }
  808. else
  809. {
  810. /* Use Minidriver Resources */
  811. RES_ELEM re; /* Resource summary */
  812. /*
  813. * First step: locate the resource, then grab some
  814. * memory for it, copy data across.The minidriver trans
  815. * table can be in two formats. NT 4.0 resource uses
  816. * RC_TRANSTAB tag and the new one uses RC_GTT tag. So
  817. * try using both of the and set the flFlag accordingly.
  818. * If FM_GLYVER40 is off that means the resource is new
  819. * format and On means old format.
  820. */
  821. if ( BGetWinRes( &(pPDev->WinResData), pQualName, RC_GTT, &re ) )
  822. {
  823. pvData = re.pvResData;
  824. //VERBOSE(("Using New Format Glyph Data for Font res_id = %d!!!\n",pfmdev->dwResID));
  825. }
  826. else if( BGetWinRes( &(pPDev->WinResData), pQualName, RC_TRANSTAB, &re ) )
  827. {
  828. NT_RLE_res *pntrle_res = (NT_RLE_res*)re.pvResData;
  829. DWORD dwSize = sizeof(NT_RLE) +
  830. (pntrle_res->fdg_cRuns - 1) * sizeof(WCRUN) +
  831. pntrle_res->cjThis - pntrle_res->fdg_wcrun_awcrun[0].dwOffset_phg;
  832. if( !(pvData = (VOID *)MemAllocZ( dwSize )) ||
  833. dwSize != CopyMemoryRLE( pvData, (PBYTE)pntrle_res, dwSize ) )
  834. {
  835. MemFree(pvData);
  836. pvData = NULL;
  837. ERR(("\n!!!UniFont!VFillinGlyphData:MemAllocZ Failed.\
  838. \nFontID = %d,Name = %ws,CTTid = %d\n\n",pfmdev->dwResID,\
  839. (PBYTE)pfm->pIFIMet + pfm->pIFIMet->dpwszFaceName,(-sCurVal)));
  840. }
  841. if (pvData)
  842. {
  843. pfm->flFlags |= FM_FREE_GLYDATA;
  844. }
  845. pfm->flFlags |= FM_GLYVER40;
  846. //VERBOSE(("Using Old Format Glyph Data for Font res_id = %d!!!\n",pfmdev->dwResID));
  847. }
  848. else
  849. pvData = NULL; /* No translation data! */
  850. }
  851. if( pvData == NULL )
  852. {
  853. /*
  854. * Presume this to mean that no translation is required.
  855. * We build a special RLE table for this, to make life
  856. * easier for us.
  857. */
  858. //VERBOSE(("No specific Glyph Data for Font res_id = %d!!!\n",pfmdev->dwResID));
  859. if (pfm->flFlags & FM_IFIVER40)
  860. {
  861. pvData = PNTRLE1To1(bSymbol, 0x20, 0xff );
  862. pfm->flFlags |= FM_GLYVER40;
  863. TRACE(\tUsing OLD Format default Translation);
  864. }
  865. else //New Format
  866. {
  867. pvData = PNTGTT1To1(pfmdev->ulCodepage, bSymbol, 0x20, 0xff);
  868. TRACE(\tUsing NEW Format default Translation);
  869. }
  870. if (pvData)
  871. {
  872. pfm->flFlags |= FM_FREE_GLYDATA; /* This one will be freed when done */
  873. if (bSymbol)
  874. {
  875. pfm->wLastChar = SYMBOL_END;
  876. if (!(pfm->flFlags & FM_IFIRES))
  877. pfm->pIFIMet->wcLastChar = SYMBOL_END;
  878. }
  879. }
  880. else
  881. WARNING(("vFillInRLE - pvData was NULL\n"));
  882. }
  883. PRINTVAL((pfm->flFlags & FM_GLYVER40), 0X%x);
  884. PRINTVAL((pfm->flFlags & FM_IFIVER40), 0X%x);
  885. pfmdev->pvNTGlyph = pvData; /* Save it for posterity */
  886. TRACE(UniFont!VFillinGlyphData:END\n);
  887. return ;
  888. }
  889. INT
  890. IFontID2Index(
  891. FONTPDEV *pFontPDev,
  892. int iID
  893. )
  894. /*++
  895. Routine Description:
  896. Turns the given font ID into an index into the resource data. The
  897. Font ID is a sequential number, starting at 1, which the engine
  898. uses to reference our fonts.
  899. Arguments:
  900. pFontPDev For Access to device font resID list.
  901. iID The font resource ID whose index is required
  902. Return Value:
  903. 0 based font index, else -1 on error.
  904. Note:
  905. 11-27-96: Created it -ganeshp-
  906. --*/
  907. {
  908. int iFontIndex;
  909. /*
  910. * Just go through the font list. When a match is found return the index.
  911. */
  912. for( iFontIndex = 0; iFontIndex < pFontPDev->iDevFontsCt; iFontIndex++)
  913. {
  914. if( pFontPDev->FontList.pdwList[iFontIndex] == (DWORD)iID)
  915. {
  916. //
  917. // This function returns 0 based font index.
  918. //
  919. return iFontIndex;
  920. }
  921. }
  922. /*
  923. * We get here when we fail to match the desired ID. This should
  924. * never happen!
  925. */
  926. return -1;
  927. }
  928. VOID
  929. VLoadDeviceFontsResDLLs(
  930. PDEV *pPDev
  931. )
  932. /*++
  933. Routine Description:
  934. This routine loads all the DLLs which has device fonts. This is needed as
  935. snapshot is unloaded after DrvEnablePDEV. So in Drv Calls for font query
  936. pPDev->UIInfo will be NULL and BGetWinRes will fail.
  937. Arguments:
  938. pPDev - Pointer to PDEV.
  939. Return Value:
  940. None
  941. Note:
  942. 11-06-98: Created it -ganeshp-
  943. --*/
  944. {
  945. INT iFontIndex;
  946. DWORD dwFontResID;
  947. PQUALNAMEEX pQualifiedID;
  948. FONTPDEV *pFontPDev;
  949. RES_ELEM ResElem;
  950. pFontPDev = pPDev->pFontPDev;
  951. pQualifiedID = (PQUALNAMEEX)&dwFontResID;
  952. /*
  953. * Just go through the font list and load each one of them if they are
  954. * from other resource DLL.
  955. */
  956. for( iFontIndex = 0; iFontIndex < pFontPDev->iDevFontsCt; iFontIndex++)
  957. {
  958. dwFontResID = pFontPDev->FontList.pdwList[iFontIndex];
  959. //
  960. // Check if this font is from root resource DLL. If yes then goto
  961. // next one.
  962. //
  963. if (pQualifiedID->bFeatureID == 0 && (pQualifiedID->bOptionID & 0x7f) == 0)
  964. continue;
  965. else
  966. {
  967. //
  968. // This font is not from root resource DLL so load it. We don't need
  969. // to look for error as we are only interested in loading the DLL.
  970. //
  971. BGetWinRes( &(pPDev->WinResData), (PQUALNAMEEX)&dwFontResID, RC_FONT, &ResElem );
  972. }
  973. }
  974. }
  975. DWORD
  976. CopyMemoryRLE(
  977. PVOID pvData,
  978. PBYTE pubSrc,
  979. DWORD dwSize)
  980. {
  981. NT_RLE_res *pntrle_res;
  982. NT_RLE *pntrle;
  983. HGLYPH *pHGlyph;
  984. DWORD dwOutSize = 0;
  985. DWORD dwRestOfData;
  986. DWORD dwSubtractNT_RLE_Header;
  987. ULONG ulI;
  988. if (pvData == NULL ||
  989. pubSrc == NULL )
  990. return 0;
  991. pntrle_res = (NT_RLE_res*)pubSrc;
  992. pntrle = (NT_RLE*)pvData;
  993. //
  994. // Copy first 12 bytes.
  995. // struct {
  996. // WORD wType;
  997. // BYTE bMagic0;
  998. // BYTE bMagic1;
  999. // DWORD cjThis;
  1000. // WORD wchFirst;
  1001. // WORD wchLast;
  1002. //
  1003. if (dwSize < dwOutSize + 12)
  1004. {
  1005. ERR(("UNIDRV!CopyMemoryRLE: dwSize < 12\n"));
  1006. return 0;
  1007. }
  1008. CopyMemory(pntrle, pntrle_res, 12);
  1009. dwOutSize += offsetof(NT_RLE, fdg);
  1010. //
  1011. // FD_GLYPHSET
  1012. // On IA64 machine, a padding DWORD is inserted before FD_GLYPHSET.
  1013. //
  1014. if (dwSize < dwOutSize + sizeof(FD_GLYPHSET) - sizeof(WCRUN))
  1015. {
  1016. ERR(("UNIDRV!CopyMemoryRLE: dwSize < sizeof(NT_RLE)\n"));
  1017. return 0;
  1018. }
  1019. pntrle->fdg.cjThis = offsetof(FD_GLYPHSET, awcrun) +
  1020. pntrle_res->fdg_cRuns * sizeof(WCRUN);
  1021. pntrle->fdg.flAccel = pntrle_res->fdg_flAccel;
  1022. pntrle->fdg.cGlyphsSupported = pntrle_res->fdg_cGlyphSupported;
  1023. pntrle->fdg.cRuns = pntrle_res->fdg_cRuns;
  1024. dwOutSize += sizeof(FD_GLYPHSET) - sizeof(WCRUN);
  1025. pHGlyph = (HGLYPH*)((PBYTE)pntrle + sizeof(NT_RLE) +
  1026. (pntrle_res->fdg_cRuns - 1) * sizeof(WCRUN));
  1027. //
  1028. // WCRUN
  1029. //
  1030. if (dwSize < dwOutSize + sizeof(WCRUN) * pntrle_res->fdg_cRuns)
  1031. {
  1032. ERR(("UNIDRV!CopyMemoryRLE: dwSize < sizeof(WCRUN)\n"));
  1033. return 0;
  1034. }
  1035. dwOutSize += sizeof(WCRUN) * pntrle_res->fdg_cRuns;
  1036. //
  1037. // NT_RLE bug workaround.
  1038. // Some of *.RLE files have an offset from the top of NT_RLE to HGLYPH array in FD_GLYPHSET.WCRUN.phg.
  1039. // phg needs to have an offset from the top of FD_GLYPHSET to HGLYPH array.
  1040. //
  1041. // Check if the offset to the last HGLYPH is larger than the whole size of memory allocation.
  1042. // If it is, it means the offset is from the top of NT_RLE. We need to subtract offsetof(NT_RLE< fdg),
  1043. // the size of NT_RLE header.
  1044. //
  1045. if (pntrle_res->fdg_wcrun_awcrun[pntrle_res->fdg_cRuns - 1].dwOffset_phg +
  1046. sizeof(HGLYPH) * (pntrle_res->fdg_wcrun_awcrun[pntrle_res->fdg_cRuns - 1].cGlyphs - 1)
  1047. >= dwSize - offsetof(NT_RLE, fdg))
  1048. {
  1049. dwSubtractNT_RLE_Header = offsetof(NT_RLE, fdg);
  1050. }
  1051. else
  1052. {
  1053. dwSubtractNT_RLE_Header = 0;
  1054. }
  1055. //
  1056. // IA64 fix. WCRUN has the pointer to HGLYPH. The size of pointer is 8 on IA64 or 4 on X86.
  1057. // We need to adjust phg, depending on the platform.
  1058. // The padding DWORD before FD_GLYPHSET don't have to be considered. phg has an offset from top of FD_GLYPHSET
  1059. // to the HGLYPH array.
  1060. //
  1061. for (ulI = 0; ulI < pntrle_res->fdg_cRuns; ulI ++)
  1062. {
  1063. pntrle->fdg.awcrun[ulI].wcLow = pntrle_res->fdg_wcrun_awcrun[ulI].wcLow;
  1064. pntrle->fdg.awcrun[ulI].cGlyphs = pntrle_res->fdg_wcrun_awcrun[ulI].cGlyphs;
  1065. pntrle->fdg.awcrun[ulI].phg = (HGLYPH*)IntToPtr(pntrle_res->fdg_wcrun_awcrun[ulI].dwOffset_phg +
  1066. pntrle_res->fdg_cRuns * (sizeof(HGLYPH*) - sizeof(DWORD)) - dwSubtractNT_RLE_Header);
  1067. }
  1068. //
  1069. // HGLYPH and offset data
  1070. //
  1071. if (dwSize < dwOutSize + sizeof(HGLYPH) * pntrle_res->fdg_cGlyphSupported)
  1072. {
  1073. ERR(("UNIDRV!CopyMemoryRLE: dwSize < HGLYLH array\n"));
  1074. return 0;
  1075. }
  1076. if (dwSubtractNT_RLE_Header)
  1077. {
  1078. dwRestOfData = pntrle_res->cjThis - offsetof(NT_RLE_res, fdg_wcrun_awcrun) - pntrle_res->fdg_wcrun_awcrun[0].dwOffset_phg;
  1079. }
  1080. else
  1081. {
  1082. dwRestOfData = pntrle_res->cjThis - pntrle_res->fdg_wcrun_awcrun[0].dwOffset_phg;
  1083. }
  1084. dwOutSize += dwRestOfData;
  1085. CopyMemory(pHGlyph, (PBYTE)pntrle_res + pntrle_res->fdg_wcrun_awcrun[0].dwOffset_phg, dwRestOfData);
  1086. if (pntrle_res->wType == RLE_LI_OFFSET)
  1087. {
  1088. WORD wDiff = (WORD)(pntrle_res->fdg_cRuns * (sizeof(HGLYPH*) - sizeof(DWORD)));
  1089. for (ulI = 0; ulI < pntrle_res->fdg_cGlyphSupported; ulI++, pHGlyph++)
  1090. {
  1091. ((RLI*)pHGlyph)->wOffset += wDiff;
  1092. }
  1093. }
  1094. return dwOutSize;
  1095. }