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.

2037 lines
60 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: pffobj.cxx
  3. *
  4. * Non-inline methods for physical font file objects.
  5. *
  6. * Copyright (c) 1991-1999 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.hxx"
  9. extern PW32PROCESS gpidSpool;
  10. // Define the global PFT semaphore. This must be held to access any of the
  11. // physical font information.
  12. #if DBG
  13. extern FLONG gflFontDebug;
  14. #endif
  15. extern "C" void FreeFileView(PFONTFILEVIEW *ppfv, ULONG cFiles);
  16. extern "C" ULONG ComputeFileviewCheckSum(PVOID, ULONG);
  17. ULONG ComputeFileviewCheckSum(PVOID pvView, ULONG cjView)
  18. {
  19. ULONG sum;
  20. PULONG pulCur,pulEnd;
  21. pulCur = (PULONG) pvView;
  22. __try
  23. {
  24. for (sum = 0, pulEnd = pulCur + cjView / sizeof(ULONG); pulCur < pulEnd; pulCur += 1)
  25. {
  26. sum += 256 * sum + *pulCur;
  27. }
  28. }
  29. __except (EXCEPTION_EXECUTE_HANDLER)
  30. {
  31. WARNING("win32k: exception while computing font check sum\n");
  32. sum = 0; // oh well, not very unique.
  33. }
  34. return ( sum < 2 ) ? 2 : sum; // 0 is reserved for device fonts
  35. // 1 is reserved for TYPE1 fonts
  36. }
  37. PFFMEMOBJ::PFFMEMOBJ(
  38. PFF *pPFFCloned,
  39. FLONG fl, // indicates if a permanent font
  40. FLONG flEmbed, // embedding flag
  41. PFT *pPFTParent // contains this pff
  42. )
  43. {
  44. if ( pPFF = (PFF *) PALLOCMEM((size_t)pPFFCloned->sizeofThis, 'ffpG'))
  45. {
  46. RtlCopyMemory((PBYTE) pPFF, (PBYTE) pPFFCloned, offsetof(PFF,aulData));
  47. pPFF->pPFFPrev = 0;
  48. pPFF->pPFFNext = 0;
  49. // Wet the implicit stuff.
  50. pPFF->cFonts = 0; // faces not loaded into table yet
  51. pPFF->cRFONT = 0; // nothing realized from this file yet
  52. pPFF->flState = fl;
  53. pPFF->pfhFace = 0;
  54. pPFF->pfhFamily = 0;
  55. pPFF->pfhUFI = 0;
  56. pPFF->prfntList = 0; // initialize to NULL list
  57. pPFF->pPFT = pPFTParent;
  58. pPFF->pPvtDataHead = NULL; // initialize to NULL link list
  59. // loaded with FR_PRIVATE, FR_PRIVATE | FR_NOT_ENUM, FRW_EMB_PID, FRW_EMB_TID
  60. // the load count (cPirvate or cNotEnum) is initialized in PvtData structure per process
  61. if (flEmbed & (FR_PRIVATE | FRW_EMB_PID | FRW_EMB_TID))
  62. {
  63. pPFF->cLoaded = 0;
  64. pPFF->cNotEnum = 0;
  65. bAddPvtData(flEmbed);
  66. }
  67. // file is loaded as NOT_ENUM only
  68. else if ( flEmbed & FR_NOT_ENUM )
  69. {
  70. pPFF->cLoaded = 0;
  71. pPFF->cNotEnum = 1;
  72. }
  73. // file is loaded as public
  74. else
  75. {
  76. pPFF->cLoaded = 1;
  77. pPFF->cNotEnum = 0;
  78. }
  79. // Mark this PFF as cloned
  80. pPFFCloned->pPFFClone = pPFF;
  81. pPFF->pPFFClone = pPFFCloned;
  82. }
  83. else
  84. {
  85. WARNING("invalid PFFMEMOBJ\n");
  86. }
  87. }
  88. /******************************Public*Routine******************************\
  89. * PFFMEMOBJ::PFFMEMOBJ
  90. *
  91. * Constructor for default sized physical font file memory object.
  92. *
  93. * cFonts = # fonts in file or device
  94. * pwsz = pointer to upper case Unicode string containing the full
  95. * path to the font file. This pointer is set to zero, by
  96. * default for fonts loaded from a device.
  97. *
  98. * History:
  99. * Thu 01-Sep-1994 06:29:47 by Kirk Olynyk [kirko]
  100. * Put the size calculation logic in the constructor thereby modularizing
  101. * and shrinking the code.
  102. * Tue 09-Nov-1993 -by- Patrick Haluptzok [patrickh]
  103. * Remove from handle manager
  104. * 02-Jan-1991 -by- Gilman Wong [gilmanw]
  105. * Wrote it.
  106. \**************************************************************************/
  107. PFFMEMOBJ::PFFMEMOBJ(
  108. unsigned cFonts // number of fonts in file|device
  109. , PWSZ pwsz // if font file this is an upper case path
  110. , ULONG cwc // number of characters in the mul path above
  111. , ULONG cFiles // number of files
  112. , DESIGNVECTOR *pdv // design vector, only present for mm instances
  113. , ULONG cjDV // size of design vector
  114. , HFF hffFontFile // IFI driver's handle to file
  115. , HDEV hdevDevice // physical device handle
  116. , DHPDEV dhpdevDevice // driver's pdev handle
  117. , PFT *pPFTParent // contains this pff
  118. , FLONG fl // indicates if a permanent font
  119. , FLONG flEmbed // embedding flag
  120. , PFNTCHECKSUM pFntCheckSum
  121. , PFONTFILEVIEW *ppfv // ptr to FILEVIEW structure
  122. , PUNIVERSAL_FONT_ID pufi // ptr to original UFI used in remote printing
  123. )
  124. {
  125. ULONG size = offsetof(PFF,aulData) + cFonts * sizeof(PFE*);
  126. ULONG dpDV = 0;
  127. ULONG dpPathName = 0;
  128. ASSERTGDI(hdevDevice, "PFFMEMOBJ passed NULL hdevDevice\n");
  129. ASSERTGDI(pFntCheckSum, "pFntCheckSum is NULL\n");
  130. fs = 0;
  131. if (pwsz)
  132. {
  133. dpPathName = size;
  134. size += ALIGN4(cwc*sizeof(WCHAR));
  135. }
  136. if (cjDV)
  137. {
  138. dpDV = size;
  139. size += cjDV;
  140. }
  141. if (pPFF = (PFF *) PALLOCMEM(size, 'ffpG'))
  142. {
  143. pPFF->sizeofThis = size;
  144. pPFF->pPFFPrev = 0;
  145. pPFF->pPFFNext = 0;
  146. pPFF->hff = hffFontFile;
  147. pPFF->hdev = hdevDevice;
  148. pPFF->dhpdev = dhpdevDevice;
  149. pPFF->pPFT = pPFTParent;
  150. pPFF->cFiles = cFiles;
  151. pPFF->cwc = cwc;
  152. if (cwc)
  153. {
  154. pPFF->pwszPathname_ = (PWSZ)((BYTE *)pPFF + dpPathName);
  155. RtlCopyMemory(pPFF->pwszPathname_, pwsz, cwc * sizeof(WCHAR));
  156. }
  157. else
  158. {
  159. pPFF->pwszPathname_ = 0;
  160. }
  161. pPFF->cjDV_ = cjDV;
  162. if (cjDV)
  163. {
  164. pPFF->pdv_ = (DESIGNVECTOR *)((BYTE *)pPFF + dpDV);
  165. RtlCopyMemory(pPFF->pdv_, pdv, cjDV);
  166. }
  167. else
  168. {
  169. pPFF->pdv_ = NULL;
  170. }
  171. pPFF->ppfv = ppfv;
  172. // Wet the implicit stuff.
  173. pPFF->cFonts = 0; // faces not loaded into table yet
  174. pPFF->cRFONT = 0; // nothing realized from this file yet
  175. pPFF->flState = fl;
  176. pPFF->pfhFace = 0;
  177. pPFF->pfhFamily = 0;
  178. pPFF->pfhUFI = 0;
  179. pPFF->prfntList = 0; // initialize to NULL list
  180. pPFF->pPvtDataHead = NULL; // initialize to NULL link list
  181. // loaded with FR_PRIVATE, FR_PRIVATE | FR_NOT_ENUM, FRW_EMB_PID, FRW_EMB_TID
  182. // the load count (cPirvate or cNotEnum) is initialized in PvtData structure per process
  183. if (flEmbed & (FR_PRIVATE | FRW_EMB_PID | FRW_EMB_TID))
  184. {
  185. pPFF->cLoaded = 0;
  186. pPFF->cNotEnum = 0;
  187. bAddPvtData(flEmbed);
  188. }
  189. // file is loaded as NOT_ENUM only
  190. else if ( flEmbed & FR_NOT_ENUM )
  191. {
  192. pPFF->cLoaded = 0;
  193. pPFF->cNotEnum = 1;
  194. }
  195. // file is loaded as public
  196. else
  197. {
  198. pPFF->cLoaded = 1;
  199. pPFF->cNotEnum = 0;
  200. }
  201. // Mark this PFF as not cloned
  202. pPFF->pPFFClone = NULL;
  203. pPFF->ulCheckSum = 0; // for device fonts it is zero
  204. if(pufi != NULL)
  205. {
  206. pPFF->ulCheckSum = pufi->CheckSum;
  207. }
  208. else
  209. {
  210. if (ppfv != NULL)
  211. {
  212. pPFF->ulCheckSum = pFntCheckSum->ulCheckSum;
  213. if (!pPFF->ulCheckSum)
  214. {
  215. // not in the boot, or could not find it in the ttfcache for some reason
  216. // Now compute the UFI
  217. KeAttachProcess(PsGetProcessPcb(gpepCSRSS));
  218. for (ULONG iFile = 0; iFile < cFiles; iFile ++)
  219. {
  220. pPFF->ulCheckSum += ComputeFileviewCheckSum(ppfv[iFile]->fv.pvViewFD, ppfv[iFile]->fv.cjView);
  221. }
  222. KeDetachProcess();
  223. PutFNTCacheCheckSum(pFntCheckSum->ulFastCheckSum, pPFF->ulCheckSum);
  224. }
  225. ASSERTGDI(pPFF->ulCheckSum, "pPFF->ulCheckSum must not be zero\n");
  226. if (pPFF->cjDV_)
  227. {
  228. pPFF->ulCheckSum += ComputeFileviewCheckSum(pdv, cjDV);
  229. }
  230. }
  231. #if 0
  232. // do it old way, and compare values in DBG mode
  233. if (ppfv != NULL)
  234. {
  235. ULONG ulCheckSumTest = 0;
  236. // Now compute the UFI
  237. KeAttachProcess(PsGetProcessPcb(gpepCSRSS));
  238. for (ULONG iFile = 0; iFile < cFiles; iFile ++)
  239. {
  240. ulCheckSumTest += ComputeFileviewCheckSum(ppfv[iFile]->fv.pvViewFD, ppfv[iFile]->fv.cjView);
  241. }
  242. KeDetachProcess();
  243. if (pPFF->cjDV_)
  244. {
  245. ulCheckSumTest += ComputeFileviewCheckSum(pdv, cjDV);
  246. }
  247. if (ulCheckSumTest != pPFF->ulCheckSum)
  248. {
  249. DbgPrint(" TrueType font cache failed, if you see these message \n");
  250. DbgPrint(" Please contact YungT or NTFonts \n");
  251. DbgPrint(" it is ok to hit 'g' \n");
  252. DbgBreakPoint();
  253. }
  254. }
  255. #endif
  256. }
  257. }
  258. else
  259. {
  260. WARNING("invalid PFFMEMOBJ\n");
  261. }
  262. }
  263. /******************************Public*Routine******************************\
  264. * PFFMEMOBJ::~PFFMEMOBJ()
  265. *
  266. * Destructor for physical font file memory object.
  267. *
  268. * History:
  269. * Tue 09-Nov-1993 -by- Patrick Haluptzok [patrickh]
  270. * Remove from handle manager
  271. *
  272. * 02-Jan-1991 -by- Gilman Wong [gilmanw]
  273. * Wrote it.
  274. \**************************************************************************/
  275. PFFMEMOBJ::~PFFMEMOBJ()
  276. {
  277. if ((fs & PFFMO_KEEPIT) == 0)
  278. {
  279. if (pPFF)
  280. {
  281. VFREEMEM(pPFF);
  282. }
  283. }
  284. }
  285. /******************************Public*Routine******************************\
  286. * BOOL PFFOBJ::bCreatePFEC(ULONG cFonts)
  287. *
  288. * Create the handle of PFE collect, a object to reduce the consumption of object handle
  289. *
  290. * Returns:
  291. * TRUE means we create successfully
  292. *
  293. * History:
  294. *
  295. * 2-June-1996 -by- Yung-Jen Tony Tsai [YungT]
  296. * Wrote it.
  297. \**************************************************************************/
  298. BOOL PFFOBJ::bCreatePFEC(ULONG cFonts)
  299. {
  300. BOOL bRet = FALSE;
  301. ASSERTGDI(cFonts, "PFFOBJ::bCreateHPFE cFonts is zero \n");
  302. pPFF->pPFEC = (PFEC *) HmgAlloc(sizeof(PFEC), PFE_TYPE, HMGR_ALLOC_ALT_LOCK | HMGR_MAKE_PUBLIC);
  303. if (pPFF->pPFEC)
  304. {
  305. pPFF->pPFEC->pvPFE = (PVOID) PALLOCMEM(SZ_PFE(gcfsCharSetTable) * cFonts, 'efpG');
  306. pPFF->pPFEC->cjPFE = SZ_PFE(gcfsCharSetTable);
  307. if (pPFF->pPFEC->pvPFE)
  308. bRet = TRUE;
  309. else
  310. {
  311. HmgFree((HOBJ)pPFF->pPFEC->hGet());
  312. pPFF->pPFEC = NULL;
  313. }
  314. }
  315. return bRet;
  316. }
  317. /******************************Public*Routine******************************\
  318. * VOID PFFOBJ::vDeletePFEC(PVOID *ppvPFE)
  319. *
  320. * Delete the handle of PFE collect, a object to reduce the consumption of object handle
  321. *
  322. * Returns:
  323. * None
  324. *
  325. * History:
  326. *
  327. * 2-June-1996 -by- Yung-Jen Tony Tsai [YungT]
  328. * Wrote it.
  329. \**************************************************************************/
  330. VOID PFFOBJ::vDeletePFEC(PVOID *ppvPFE)
  331. {
  332. *ppvPFE = NULL;
  333. if (pPFF->pPFEC != NULL)
  334. {
  335. *ppvPFE = pPFF->pPFEC->pvPFE;
  336. HmgFree((HOBJ)pPFF->pPFEC->hGet());
  337. pPFF->pPFEC = NULL;
  338. }
  339. }
  340. /******************************Public*Routine******************************\
  341. * PFFOBJ::bAddHash
  342. *
  343. * Adds the PFF and all its PFEs to the font hashing table. The font
  344. * hashing tabled modified is in the PFT if a font driver managed font;
  345. * otherwise, the font hashing table is in the PFF itself.
  346. *
  347. * The caller should hold the ghsemPublicPFT while calling this function.
  348. *
  349. * Returns:
  350. * TRUE if successful, FALSE otherwise.
  351. *
  352. * History:
  353. * 11-Mar-1993 -by- Gilman Wong [gilmanw]
  354. * Wrote it.
  355. \**************************************************************************/
  356. BOOL PFFOBJ::bAddHash(BOOL bEUDC)
  357. {
  358. // Caller must hold the ghsemPublicPFT semaphore to protect access to
  359. // the hash tables.
  360. //
  361. // Add the entry to the appropriate font hash tables
  362. //
  363. FONTHASH **ppfhFace, **ppfhFamily,**ppfhUFI;
  364. if (!bDeviceFonts())
  365. {
  366. //
  367. // Hash tables for the font driver loaded fonts exist off of
  368. // the font table.
  369. //
  370. PUBLIC_PFTOBJ pfto( bInPrivatePFT() ? gpPFTPrivate : gpPFTPublic );
  371. ASSERTGDI(pfto.bValid(),"PFFOBJ::vAddHash -- invalid Public PFTOBJ\n");
  372. ppfhFace = &(pfto.pPFT->pfhFace);
  373. ppfhFamily = &(pfto.pPFT->pfhFamily);
  374. ppfhUFI = &(pfto.pPFT->pfhUFI);
  375. //
  376. // If this is a TrueType font, increment the count.
  377. //
  378. if ( pPFF->hdev == (HDEV) gppdevTrueType )
  379. {
  380. gcTrueTypeFonts++; // protected by ghsemPublicPFT
  381. }
  382. }
  383. else
  384. {
  385. //
  386. // Hash tables for device fonts exist off of the PFF that
  387. // encapsulates them.
  388. //
  389. #if DBG
  390. if (gflFontDebug & DEBUG_FONTTABLE)
  391. {
  392. RIP("\n\n[kirko] PFFMEMOBJ::vAddHash -- Adding to the Driver's font hash table\n\n");
  393. }
  394. #endif
  395. ppfhFace = &pPFF->pfhFace;
  396. ppfhFamily = &pPFF->pfhFamily;
  397. ppfhUFI = &pPFF->pfhUFI;
  398. }
  399. //
  400. // Now that we have figured out where the tables are, add the PFEs to them.
  401. //
  402. FHOBJ fhoFamily(ppfhFamily);
  403. FHOBJ fhoFace(ppfhFace);
  404. FHOBJ fhoUFI(ppfhUFI);
  405. ASSERTGDI(fhoFamily.bValid(), "bAddHashPFFOBJ(): fhoFamily not valid\n");
  406. ASSERTGDI(fhoFace.bValid(), "bAddHashPFFOBJ(): fhoFace not valid\n");
  407. ASSERTGDI(fhoUFI.bValid(), "bAddHashPFFOBJ(): fhoUFI not valid\n");
  408. if (! (fhoUFI.bValid() && fhoFamily.bValid() && fhoFace.bValid()))
  409. return FALSE;
  410. for (COUNT c = 0; c < pPFF->cFonts; c++)
  411. {
  412. PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]);
  413. ASSERTGDI(pfeo.bValid(), "bAddHashPFFOBJ(): bad HPFE\n");
  414. if(!fhoUFI.bInsert(pfeo) )
  415. {
  416. WARNING("PFFOBJ::bAddHash -- fhoUFI.bInsert failed\n");
  417. return FALSE;
  418. }
  419. // If we only need to add it to the UFI hash table (we need to add it there
  420. // so that the remote printing code can request the bits of it needs to).
  421. if(bEUDC)
  422. {
  423. continue;
  424. }
  425. if (!fhoFamily.bInsert(pfeo))
  426. {
  427. WARNING("PFFOBJ::bAddHash -- fhoFamily.bInsert failed\n");
  428. return FALSE;
  429. }
  430. #if DBG
  431. if (gflFontDebug & DEBUG_FONTTABLE)
  432. {
  433. DbgPrint("PFFMEMOBJ::vAddHash(\"%ws\")\n",pfeo.pwszFamilyName());
  434. }
  435. // Need level 2 checking to see this.
  436. if (gflFontDebug & DEBUG_FONTTABLE_EXTRA)
  437. {
  438. fhoFamily.vPrint((VPRINT) DbgPrint);
  439. }
  440. #endif
  441. #if DBG
  442. if (gflFontDebug & DEBUG_FONTTABLE)
  443. {
  444. UNIVERSAL_FONT_ID ufi;
  445. pfeo.vUFI(&ufi);
  446. DbgPrint("PFFMEMOBJ::vAddHash(\"%x\")\n",ufi.CheckSum);
  447. }
  448. // Need level 2 checking to see this.
  449. if (gflFontDebug & DEBUG_FONTTABLE_EXTRA)
  450. {
  451. fhoUFI.vPrint((VPRINT) DbgPrint);
  452. }
  453. #endif
  454. if(!fhoFace.bInsert(pfeo))
  455. {
  456. WARNING("PFFMEMOBJ::vAddHash -- fhoFace.bInsert failed\n");
  457. return FALSE;
  458. }
  459. #if DBG
  460. if (gflFontDebug & DEBUG_FONTTABLE)
  461. {
  462. DbgPrint("gdisrv!PFFMEMOBJ::vAddHash(\"%ws\")\n",pfeo.pwszFaceName());
  463. }
  464. if (gflFontDebug & DEBUG_FONTTABLE_EXTRA)
  465. {
  466. fhoFace.vPrint((VPRINT) DbgPrint);
  467. }
  468. #endif
  469. }
  470. return TRUE;
  471. }
  472. /******************************Public*Routine******************************\
  473. * PFFOBJ::vRemoveHash
  474. *
  475. * Removes the PFF and all its PFEs from the font hashing table, preventing
  476. * the font from being enumerated or mapped.
  477. *
  478. * The caller should hold the ghsemPublicPFT while calling this function.
  479. *
  480. * History:
  481. * 10-Mar-1993 -by- Gilman Wong [gilmanw]
  482. * Wrote it.
  483. \**************************************************************************/
  484. VOID PFFOBJ::vRemoveHash ()
  485. {
  486. // Caller must hold the ghsemPublicPFT semaphore to protect access to
  487. // the hash tables.
  488. if (bDeviceFonts())
  489. {
  490. //
  491. // Hash tables for device fonts exist off of the PFF that
  492. // encapsulates the device fonts. Font driver loaded fonts
  493. // are handled later while deleting the PFEs.
  494. //
  495. //
  496. // Kill the entire table for the device. No more processing
  497. // of font hash table stuff is necssary for device fonts
  498. // after we leave this scope.
  499. //
  500. FHOBJ fhoFace(&(pPFF->pfhFace));
  501. if (fhoFace.bValid())
  502. {
  503. fhoFace.vFree();
  504. }
  505. FHOBJ fhoFamily(&(pPFF->pfhFamily));
  506. if (fhoFamily.bValid())
  507. {
  508. fhoFamily.vFree();
  509. }
  510. FHOBJ fhoUFI(&(pPFF->pfhUFI));
  511. if (fhoUFI.bValid())
  512. {
  513. fhoUFI.vFree();
  514. }
  515. }
  516. else
  517. {
  518. PUBLIC_PFTOBJ pfto( bInPrivatePFT() ? gpPFTPrivate : gpPFTPublic );
  519. ASSERTGDI(pfto.bValid(),"vRemoveHashPFFOBJ(): invalid PFTOBJ\n");
  520. //
  521. // Hash tables for the font driver managed fonts exist off of
  522. // the font table (PFT).
  523. //
  524. FHOBJ fhoFace(&(pfto.pPFT->pfhFace));
  525. FHOBJ fhoFamily(&(pfto.pPFT->pfhFamily));
  526. FHOBJ fhoUFI(&(pfto.pPFT->pfhUFI));
  527. for (COUNT c = 0; c < pPFF->cFonts; c++)
  528. {
  529. PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]);
  530. ASSERTGDI(pfeo.bValid(), "vRemoveHashPFFOBJ(): bad HPFE\n");
  531. //
  532. // Remove PFE from hash tables.
  533. //
  534. if( !pfeo.bEUDC() )
  535. {
  536. // EUDC fonts arent added to these two tables
  537. if (fhoFace.bValid())
  538. fhoFace.vDelete(pfeo);
  539. if (fhoFamily.bValid())
  540. fhoFamily.vDelete(pfeo);
  541. }
  542. if (fhoUFI.bValid())
  543. fhoUFI.vDelete(pfeo);
  544. #if DBG
  545. if (gflFontDebug & DEBUG_FONTTABLE)
  546. {
  547. DbgPrint("gdisrv!vRemoveHashPFFOBJ() hpfe 0x%lx (\"%ws\")\n",
  548. pfeo.ppfeGet(), pfeo.pwszFamilyName());
  549. }
  550. // Need level 2 checking to see this extra detail.
  551. if (gflFontDebug & DEBUG_FONTTABLE_EXTRA)
  552. {
  553. fhoFamily.vPrint((VPRINT) DbgPrint);
  554. }
  555. #endif
  556. }
  557. //
  558. // If this is a TrueType font, decrement the count.
  559. //
  560. if ( pPFF->hdev == (HDEV) gppdevTrueType )
  561. {
  562. gcTrueTypeFonts--; // protected by ghsemPublicPFT
  563. }
  564. }
  565. }
  566. /******************************Public*Routine******************************\
  567. *
  568. * BOOL PFFOBJ::bPermanent()
  569. *
  570. *
  571. * Effects:
  572. *
  573. * Warnings:
  574. *
  575. * History:
  576. * 06-Dec-1993 -by- Bodin Dresevic [BodinD]
  577. * Wrote it.
  578. \**************************************************************************/
  579. BOOL PFFOBJ::bPermanent()
  580. {
  581. // in the new version of the code every remote font is flagged at
  582. // AddFontResourceTime. The difference in behavior from 3.51
  583. // is that now fonts added by the applicaitons, if local, will not
  584. // be removed at log on time.
  585. if (pPFF->flState & PFF_STATE_NETREMOTE_FONT)
  586. return FALSE;
  587. else
  588. return TRUE;
  589. }
  590. /******************************Public*Routine******************************\
  591. * PFFOBJ::vPFFC_Delete
  592. *
  593. * Deletes the PFF and its PFEs. Information needed to call the driver
  594. * to unload the font file and release driver allocated data is stored
  595. * in the PFFCLEANUP structure. The PFFCLEANUP structure is allocated
  596. * within this routine. It is the caller's responsibility to release
  597. * the PFFCLEANUP structure (calling vCleanupFontFile() calls the drivers
  598. * AND releases the structure).
  599. *
  600. * Changed so that it does not return a pointer to a PFFCLEANUP
  601. * structure. Instead, it takes a pointer to a PFFCLEANUP
  602. * structure as an argument. Thus, the caller must allocate
  603. * and free the memory to the PFFCLEANUP structure. [dchinn 11/24/98]
  604. *
  605. * Returns:
  606. * void. The contents of the PFFCLEANUP structure passed in will be altered
  607. * as appropriate.
  608. *
  609. * History:
  610. * 10-Mar-1993 -by- Gilman Wong [gilmanw]
  611. * Wrote it.
  612. \**************************************************************************/
  613. VOID PFFOBJ::vPFFC_Delete(PFFCLEANUP *pPFFC)
  614. {
  615. PVOID pvPFE;
  616. TRACE_FONT(("Entering PFFOBJ::vPFFC_Delete()\n\tpPFF=%-#x\n", pPFF));
  617. // check to see if a NULL pointer to a PFFCLEANUP structure was passed in
  618. ASSERTGDI(pPFFC, "vPFFC_Delete(): passed in a NULL\n");
  619. vDeletePFEC(&pvPFE);
  620. //
  621. // Delete all the PFE entries.
  622. //
  623. for (COUNT c = 0; c < pPFF->cFonts; c++)
  624. {
  625. PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]);
  626. ASSERTGDI(pfeo.bValid(), "vPFFC_DeletePFFOBJ(): bad HPFE (device font)\n");
  627. //
  628. // Delete the PFE. The vDelete function will copy the driver allocated
  629. // resource information from the PFE into the PFECLEANUP structure.
  630. // We will call DrvFree for these resources later (when we're not under
  631. // semaphore).
  632. //
  633. pfeo.vDelete();
  634. }
  635. //
  636. // Save stuff about the PFF also.
  637. //
  638. pPFFC->hff = pPFF->hff;
  639. pPFFC->hdev = pPFF->hdev;
  640. pPFFC->pPFFClone = pPFF->pPFFClone;
  641. //
  642. // Free object memory and invalidate pointer.
  643. //
  644. TRACE_FONT(("Freeing pPFF=%-#x\n",pPFF));
  645. // If this was a remote font then we must delete the memory for the file.
  646. // If this is a normal font then we must still delete the view.
  647. if (!pPFF->pPFFClone)
  648. {
  649. if (pPFF->ppfv && pPFF->cFiles)
  650. {
  651. FreeFileView(pPFF->ppfv, pPFF->cFiles);
  652. }
  653. }
  654. else
  655. {
  656. // We release the pPFFClone.
  657. pPFF->pPFFClone->pPFFClone = NULL;
  658. }
  659. if (pvPFE)
  660. VFREEMEM(pvPFE);
  661. VFREEMEM(pPFF);
  662. pPFF = 0;
  663. TRACE_FONT(("Exiting PFFOBJ::vPFFC_Delete\n\treturn value = %x\n", pPFFC));
  664. return;
  665. }
  666. /******************************Public*Routine******************************\
  667. * PFFOBJ::vPFFC_DeleteAndCleanup
  668. *
  669. * This function creates a pointer to a PFFCLEANUP structure, calls vPFFC_Delete(),
  670. * and then calls vCleanupFontFile(). This is the recommended way to handle
  671. * unloading a font file, because it avoids the possibility (when a font file
  672. * contains fewer than CFONTS_PFFCLEANUP fonts) that under a Hydra scenario
  673. * it will fail to free up all the memory.
  674. *
  675. * (The old way of doing the cleanup was to call vPFFC_Delete() and then
  676. * vCleanupFontFile(). However, the old vPFFC_Delete() allocated a PFFCLEANUP
  677. * structure. If that allocation failed, then the rest of the cleanup would
  678. * not occur, and so memory would leak from a Hydra session. This new way of
  679. * doing the cleanup does not allocate memory from the heap. Instead, it allocates
  680. * it on the stack.)
  681. *
  682. * If for some reason the two calls (vPFFC_Delete() and vCleanupFontFile() ) need
  683. * to be done separately (for example, if one of the calls is protected by a
  684. * semaphore), then one must wrap code similar to that below around the two calls.
  685. *
  686. * Returns:
  687. * void.
  688. *
  689. * History:
  690. * 24-Nov-1998 -by- Donald Chinn [dchinn]
  691. * Wrote it.
  692. \**************************************************************************/
  693. VOID PFFOBJ::vPFFC_DeleteAndCleanup()
  694. {
  695. PFFCLEANUP pffc;
  696. // now call vPFFC_Delete() and vCleanupFontFile()
  697. vPFFC_Delete (&pffc);
  698. vCleanupFontFile (&pffc);
  699. }
  700. /******************************Public*Routine******************************\
  701. * BOOL PFFOBJ::bDeleteLoadRef ()
  702. *
  703. * Remove a load reference. Caller must hold the ghsemPublicPFT semaphore.
  704. *
  705. * Returns:
  706. * TRUE if caller should delete, FALSE if caller shouldn't delete.
  707. *
  708. * History:
  709. * 23-Feb-1991 -by- Gilman Wong [gilmanw]
  710. * Wrote it.
  711. \**************************************************************************/
  712. BOOL PFFOBJ::bDeleteLoadRef(ULONG fl, PVTDATA *pPvtData, BOOL *pbWrongFlags)
  713. {
  714. // ghsemPublicPFT protects the ref counts (cLoaded and cRFONT). Caller
  715. // must grab the semaphore before calling this function.
  716. // Decrement the load count. Must prevent underflow. Who knows if some
  717. // app might not randomly go around doing extra RemoveFont calls. Isn't
  718. // it too bad that we have to run APPS on our nice clean OS? :-)
  719. BOOL bRet = FALSE;
  720. *pbWrongFlags = FALSE;
  721. TRACE_FONT(("Enterning PFFOBJ::bDeleteLoadRef\n"
  722. "\tpPFF=%-#x\n"
  723. "\tcLoaded=%d\n",
  724. "\tcNotEnum=%d\n",pPFF ,pPFF->cLoaded ,pPFF->cNotEnum));
  725. // Embedded/Private fonts
  726. if (bInPrivatePFT())
  727. {
  728. ASSERTGDI(pPvtData, "bDeleteLoadRef: pPvtData is NULL\n");
  729. if (pPvtData == NULL)
  730. {
  731. return bRet;
  732. }
  733. // called by cleanup routine when the process terminates
  734. if (fl == FRW_PVT_CLEANUP)
  735. {
  736. pPvtData->cPrivate = 0;
  737. pPvtData->cNotEnum = 0;
  738. }
  739. // decreament cNotEnum for Embedded or FR_NOT_ENUM set font
  740. else if (fl & (FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID | FR_PRINT_EMB_FONT))
  741. {
  742. if (pPvtData->fl & fl)
  743. {
  744. if ( pPvtData->cNotEnum )
  745. {
  746. pPvtData->cNotEnum--;
  747. if (fl == FR_PRINT_EMB_FONT)
  748. {
  749. pPvtData->fl &= ~FR_PRINT_EMB_FONT;
  750. }
  751. }
  752. }
  753. else
  754. {
  755. *pbWrongFlags = TRUE;
  756. }
  757. }
  758. // decreament cPrivate for FR_PRIVATE set only font
  759. else
  760. {
  761. if (pPvtData->fl & fl)
  762. {
  763. if ( pPvtData->cPrivate )
  764. {
  765. pPvtData->cPrivate--;
  766. }
  767. else
  768. {
  769. *pbWrongFlags = TRUE;
  770. }
  771. }
  772. }
  773. // Remove the PvtData block if both cPrivate and cNotEnum counts are zero.
  774. if ((pPvtData->cPrivate | pPvtData->cNotEnum) == 0)
  775. {
  776. bRemovePvtData(pPvtData);
  777. }
  778. // Mark it to Ready2Die if the PvtData list is NULL.
  779. if (pPvtDataHeadGet() == NULL)
  780. {
  781. ASSERTGDI( (pPFF->cLoaded | pPFF->cNotEnum) == 0, "win32k!bDeleteLoadRef(): global (cLoaded | cNotEnum) in private PFF is not 0\n");
  782. vKill();
  783. bRet = TRUE;
  784. }
  785. }
  786. else
  787. {
  788. // remove a public font
  789. if (fl == 0)
  790. {
  791. if (pPFF->cLoaded)
  792. {
  793. pPFF->cLoaded--;
  794. }
  795. }
  796. // remove a FR_NOT_ENUM font in the public PFT
  797. else
  798. {
  799. ASSERTGDI(fl == FR_NOT_ENUM, "win32k!bDeletLoadRef(): attempt to delete a font in public PFT with fl!=FR_NOT_ENUM \n");
  800. if (pPFF->cNotEnum)
  801. {
  802. pPFF->cNotEnum--;
  803. }
  804. }
  805. if ((pPFF->cLoaded | pPFF->cNotEnum) == 0)
  806. {
  807. ASSERTGDI(pPFF->pPvtDataHead == NULL, "win32k!bDeleteLoadRef(): pPvtDataHead in public PFF is not NULL\n");
  808. vKill(); // mark as "dead"
  809. bRet = TRUE;
  810. }
  811. }
  812. TRACE_FONT(("Exiting PFFOBJ::bDeleteLoadRef\n\treturn value = %d\n",bRet));
  813. return( bRet );
  814. }
  815. /******************************Public*Routine******************************\
  816. * BOOL PFFOBJ::bDeleteRFONTRef ()
  817. *
  818. * Destroy the PFF physical font file object (message from a RFONT).
  819. *
  820. * Conditions that need to be met before deletion:
  821. *
  822. * must delete all RFONTs before PFF can be deleted (cRFONT must be zero)
  823. * must delete all PFEs before deleting PFF
  824. *
  825. * After decrementing the cRFONT:
  826. *
  827. * If cRFONT != 0 OR flState != PFF_STATE_READY2DIE, just exit.
  828. *
  829. * If cRFONT == 0 and flState == PFF_STATE_READY2DIE, delete the PFF.
  830. *
  831. * Note:
  832. * This function has the side effect of decrementing the RFONT count.
  833. *
  834. * Returns:
  835. * TRUE if successful, FALSE if error occurs (which means PFF still lives!)
  836. *
  837. * Warning:
  838. * This should only be called from RFONTOBJ::bDelete()
  839. *
  840. * History:
  841. * 23-Feb-1991 -by- Gilman Wong [gilmanw]
  842. * Wrote it.
  843. \**************************************************************************/
  844. BOOL PFFOBJ::bDeleteRFONTRef()
  845. {
  846. PFFCLEANUP pffc;
  847. BOOL bCleanUp = FALSE;
  848. {
  849. // Need to stabilize table to access cRFONT and to modify font table.
  850. SEMOBJ so(ghsemPublicPFT);
  851. // Decrement the RFONT count.
  852. ASSERTGDI(pPFF->cRFONT > 0,"bDeleteRFONTRefPFFOBJ(): bad ref count in PFF\n");
  853. pPFF->cRFONT--;
  854. // If load count is zero and no more RFONTs for this PFF, OK to delete.
  855. if ( (pPFF->cLoaded == 0) && (pPFF->cNotEnum == 0) && (pPFF->pPvtDataHead == NULL) && (pPFF->cRFONT == 0) )
  856. {
  857. // If the load count is zero, the PFF is already out of the PFT.
  858. // It is now safe to delete the PFF.
  859. vPFFC_Delete(&pffc);
  860. bCleanUp = TRUE;
  861. }
  862. }
  863. // Call the driver outside of the semaphore.
  864. if (bCleanUp)
  865. vCleanupFontFile(&pffc); // function can handle NULL case
  866. return TRUE;
  867. }
  868. /******************************Public*Routine******************************\
  869. * vKill
  870. *
  871. * Puts the PFF and its PFEs to death. In other words, the PFF and PFEs are
  872. * put in a dead state that prevents them from being mapped to or enumerated.
  873. * It also means that the font file is in a state in which the system wants
  874. * to delete it (load count is zero), but the deletion is delayed because
  875. * RFONTs still exist which reference this PFF.
  876. *
  877. * History:
  878. * 29-May-1992 -by- Gilman Wong [gilmanw]
  879. * Wrote it.
  880. \**************************************************************************/
  881. VOID PFFOBJ::vKill()
  882. {
  883. // Put into a dead state if not already there.
  884. TRACE_FONT(("Entering PFFOBJ::vKill\n\tpPFF=%-#x\n", pPFF));
  885. if ( !bDead() )
  886. {
  887. // Set state.
  888. pPFF->flState |= PFF_STATE_READY2DIE;
  889. // Run the list of PFEs and set each to death.
  890. for (COUNT c = 0; c < pPFF->cFonts; c++)
  891. {
  892. PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]);
  893. if (pfeo.bValid())
  894. {
  895. // Mark PFE as dead state.
  896. pfeo.vKill();
  897. }
  898. else
  899. {
  900. WARNING("vDiePFFOBJ(): cannot make PFEOBJ\n");
  901. }
  902. }
  903. }
  904. TRACE_FONT(("Exiting PFFOBJ::vKill\n"));
  905. }
  906. /******************************Public*Routine******************************\
  907. * vRevive
  908. *
  909. * Restores the PFF and its PFEs to life. In other words, the states are
  910. * cleared so that the PFF and PFEs are available for mapping and enumeration.
  911. *
  912. * History:
  913. * 29-May-1992 -by- Gilman Wong [gilmanw]
  914. * Wrote it.
  915. \**************************************************************************/
  916. VOID PFFOBJ::vRevive ()
  917. {
  918. // If dead, then revive.
  919. if ( bDead() )
  920. {
  921. // Reset state.
  922. pPFF->flState &= ~PFF_STATE_READY2DIE;
  923. // Run the list of PFEs and revive each one.
  924. for (COUNT c = 0; c < pPFF->cFonts; c++)
  925. {
  926. PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]);
  927. if (pfeo.bValid())
  928. {
  929. // Mark PFE as dead state.
  930. pfeo.vRevive();
  931. }
  932. else
  933. {
  934. WARNING("vRevivePFFOBJ(): cannot make PFEOBJ\n");
  935. }
  936. }
  937. }
  938. }
  939. /******************************Public*Routine******************************\
  940. * BOOL PFFMEMOBJ::bLoadFontFileTable
  941. *
  942. * Creates a PFE for each of the faces in a font file and loads the IFI
  943. * metrics and mapping tables into each of the PFEs. The font file is
  944. * uniquely identified by the driver, hoDriver, and IFI font file handle,
  945. * hff, stored in the PFF object. However, rather than hitting the handle
  946. * manager an extra time, a PFDEVOBJ is passed into this function.
  947. *
  948. * After all the PFE entries are added, the font files pathname is added
  949. * to the end of the data buffer.
  950. *
  951. * It is assumed that the PFF ahpfe table has enough room for cFontsToLoad
  952. * new HPFE handles as well as the font files pathname.
  953. *
  954. * Returns:
  955. * TRUE if successful, FALSE if error.
  956. *
  957. * History:
  958. * 16-Jan-1991 -by- Gilman Wong [gilmanw]
  959. * Wrote it.
  960. \**************************************************************************/
  961. BOOL PFFMEMOBJ::bLoadFontFileTable (
  962. PWSZ pwszPathname, // upper case
  963. COUNT cFontsToLoad,
  964. HANDLE hdc,
  965. PUNIVERSAL_FONT_ID pufi
  966. #ifdef FE_SB
  967. ,PEUDCLOAD pEudcLoadData
  968. #endif
  969. )
  970. {
  971. ULONG iFont; // font face index
  972. // Create PFE's for each of the fonts in the font file.
  973. // (Note: iFont indices for IFI fonts are 1-based, not 0-based)
  974. PDEVOBJ ppdo(hdev());
  975. if (!bCreatePFEC(cFontsToLoad))
  976. return FALSE;
  977. for (iFont = 1; iFont <= cFontsToLoad; iFont++)
  978. {
  979. FD_GLYPHSET *pfdg;
  980. PIFIMETRICS pifi; // storage for the pointer to ifi
  981. ULONG_PTR idMetrics;
  982. // Grab the IFIMETRICS pointer.
  983. if ( (pifi = ppdo.QueryFont(
  984. pPFF->dhpdev,
  985. pPFF->hff,
  986. iFont,
  987. &idMetrics)) == (PIFIMETRICS) NULL )
  988. {
  989. WARNING("bLoadFontFileTablePFFMEMOBJ(): error getting metrics\n");
  990. return (FALSE);
  991. }
  992. // Put into a new PFE.
  993. #ifdef FE_SB
  994. BOOL bRet = TRUE;
  995. if( bReadyToInitializeFontAssocDefault )
  996. {
  997. // This should be Base font, not be EUDC.
  998. //
  999. if ( pEudcLoadData == NULL )
  1000. {
  1001. // check this base font should be RE-load as default linked font ?
  1002. // if so, the pathname for this font will be registerd as default linked font.
  1003. bRet = FindDefaultLinkedFontEntry(
  1004. (const WCHAR *)(((BYTE*) pifi) + pifi->dpwszFamilyName),pwszPathname);
  1005. }
  1006. }
  1007. if (!bRet || !bAddEntry(iFont, NULL, 0, pifi, idMetrics, (HANDLE)0, pufi, pEudcLoadData))
  1008. {
  1009. // Failed to get the FD_GLYPHSET information. The entry is
  1010. // partially valid (IFIMETRICS), so lets invalidate the good part.
  1011. if (PPFNVALID(ppdo,Free))
  1012. {
  1013. ppdo.Free(pifi, idMetrics);
  1014. }
  1015. WARNING("bLoadFontFileTablePFFMEMOBJ(): error getting glyphset\n");
  1016. return (FALSE);
  1017. }
  1018. #endif
  1019. }
  1020. return (TRUE);
  1021. }
  1022. /*************************Public*Routine**************************\
  1023. * BOOL bExtendGlyphset
  1024. * Check the glyph set returned by the printer driver. Tack on the
  1025. * f0xx unicode range if missing for symbol font.
  1026. *
  1027. * History:
  1028. * Oct-10-97 Xudong Wu [TessieW]
  1029. * Wrote it.
  1030. *
  1031. \*****************************************************************/
  1032. BOOL bExtendGlyphSet(FD_GLYPHSET **ppfdgIn, FD_GLYPHSET **ppfdgOut)
  1033. {
  1034. WCHAR awch[256], *pwsz = awch, wcLow, wcHigh;
  1035. UCHAR ach[256];
  1036. USHORT AnsiCodePage, OemCodePage;
  1037. INT cjWChar, cjChar;
  1038. ULONG cjSize, iRun, jRun, i, j;
  1039. FD_GLYPHSET *pfdgNew, *pfdg;
  1040. ULONG cRuns;
  1041. BOOL bRet = FALSE, bNeedExt = FALSE;
  1042. pfdg = *ppfdgIn;
  1043. cRuns = pfdg->cRuns;
  1044. if (cRuns == 0)
  1045. {
  1046. WARNING("bExtendGlyphSet - empty glyphset\n");
  1047. return FALSE;
  1048. }
  1049. wcLow = pfdg->awcrun[0].wcLow;
  1050. wcHigh = pfdg->awcrun[cRuns-1].wcLow + (WCHAR)pfdg->awcrun[cRuns-1].cGlyphs - 1 ;
  1051. // mixing CP_SYMBOL mapping
  1052. // e0 is the number of glyphs in f020-f0ff range in symbol CP
  1053. // We shall extend the glypset if [f020,f0ff] does not intersect any
  1054. // of the runs specified in the old pfdg. We check that by making sure that
  1055. // [f020,f0ff] is entirely contained in the complement of the old glyphset.
  1056. if (pfdg->cGlyphsSupported <= 256)
  1057. {
  1058. if ((wcHigh < 0xf020) || (wcLow > 0xf0ff))
  1059. {
  1060. bNeedExt = TRUE;
  1061. }
  1062. else
  1063. {
  1064. // bNeedExt = FALSE; // already initialized
  1065. for (iRun = 0; iRun < (cRuns - 1); iRun++)
  1066. {
  1067. wcLow = pfdg->awcrun[iRun].wcLow + pfdg->awcrun[iRun].cGlyphs - 1;
  1068. wcHigh = pfdg->awcrun[iRun+1].wcLow;
  1069. if ((wcLow < 0xf020) && (wcHigh > 0xf0ff))
  1070. {
  1071. bNeedExt = TRUE;
  1072. break;
  1073. }
  1074. }
  1075. }
  1076. }
  1077. if (bNeedExt)
  1078. {
  1079. cjSize = SZ_GLYPHSET(cRuns + 1, pfdg->cGlyphsSupported + 0x00e0);
  1080. pfdgNew = (FD_GLYPHSET*) PALLOCMEM(cjSize,'slgG');
  1081. if (pfdgNew)
  1082. {
  1083. HGLYPH *phgS, *phgD;
  1084. cjWChar = sizeof(WCHAR) * pfdg->cGlyphsSupported;
  1085. cjChar = 256;
  1086. for (iRun = 0; iRun < cRuns; iRun++)
  1087. {
  1088. for (i = 0; i < pfdg->awcrun[iRun].cGlyphs; i++)
  1089. {
  1090. *pwsz++ = pfdg->awcrun[iRun].wcLow + (WCHAR)i;
  1091. }
  1092. }
  1093. RtlGetDefaultCodePage(&AnsiCodePage, &OemCodePage);
  1094. if(IS_ANY_DBCS_CODEPAGE(AnsiCodePage))
  1095. {
  1096. AnsiCodePage = 1252;
  1097. }
  1098. if(EngWideCharToMultiByte(AnsiCodePage, awch, cjWChar, (CHAR*)ach, cjChar) == -1)
  1099. {
  1100. VFREEMEM(pfdgNew);
  1101. return bRet;
  1102. }
  1103. pfdgNew->cjThis = cjSize;
  1104. pfdgNew->flAccel = pfdg->flAccel | GS_EXTENDED;
  1105. pfdgNew->cGlyphsSupported = pfdg->cGlyphsSupported + 0x00e0;
  1106. pfdgNew->cRuns = cRuns + 1;
  1107. phgS = phgD = (HGLYPH*) &pfdgNew->awcrun[cRuns+1];
  1108. for ( iRun = 0;
  1109. (iRun < cRuns) && (pfdg->awcrun[iRun].wcLow < 0xf020);
  1110. iRun++)
  1111. {
  1112. pfdgNew->awcrun[iRun].wcLow = pfdg->awcrun[iRun].wcLow;
  1113. pfdgNew->awcrun[iRun].cGlyphs = pfdg->awcrun[iRun].cGlyphs;
  1114. pfdgNew->awcrun[iRun].phg = phgD;
  1115. RtlCopyMemory(phgD, pfdg->awcrun[iRun].phg,
  1116. sizeof(HGLYPH) * pfdg->awcrun[iRun].cGlyphs);
  1117. phgD += pfdg->awcrun[iRun].cGlyphs;
  1118. }
  1119. // fill in the f0xx range
  1120. pfdgNew->awcrun[iRun].wcLow = 0xf020;
  1121. pfdgNew->awcrun[iRun].cGlyphs = 0x00e0;
  1122. pfdgNew->awcrun[iRun].phg = phgD;
  1123. RtlZeroMemory((PVOID)phgD, 0x00e0 * sizeof(HGLYPH));
  1124. j = 0;
  1125. for (jRun = 0; jRun < cRuns; jRun++)
  1126. {
  1127. for (i = 0; i < pfdg->awcrun[jRun].cGlyphs; i++)
  1128. {
  1129. if (ach[j] >= 0x20)
  1130. {
  1131. phgD[ach[j] - 0x20] = pfdg->awcrun[jRun].phg[i];
  1132. }
  1133. j++;
  1134. }
  1135. }
  1136. phgD += 0x00e0;
  1137. for (; iRun < cRuns; iRun++)
  1138. {
  1139. pfdgNew->awcrun[iRun+1].wcLow = pfdg->awcrun[iRun].wcLow;
  1140. pfdgNew->awcrun[iRun+1].cGlyphs = pfdg->awcrun[iRun].cGlyphs;
  1141. pfdgNew->awcrun[iRun+1].phg = phgD;
  1142. RtlCopyMemory(phgD,
  1143. pfdg->awcrun[iRun].phg,
  1144. sizeof(HGLYPH) * pfdg->awcrun[iRun].cGlyphs);
  1145. phgD += pfdg->awcrun[iRun].cGlyphs;
  1146. }
  1147. *ppfdgOut = pfdgNew;
  1148. bRet = TRUE;
  1149. }
  1150. else
  1151. {
  1152. WARNING("bExtentGlyphSet(): failed to allocate pGlyphset\n");
  1153. }
  1154. }
  1155. return bRet;
  1156. }
  1157. /******************************Public*Routine******************************\
  1158. * BOOL PFFMEMOBJ::bLoadDeviceFontTable (
  1159. *
  1160. * Creates a PFE object for each device font and stores the IFIMETRICS and
  1161. * FD_MAPPINGS (UNICODE->HGLYPH) structures of that font. The device is
  1162. * identified by the pair (ppdo, dhpdev). There are cFonts number of device
  1163. * fonts to load.
  1164. *
  1165. * Note:
  1166. * It is assumed that there is enough storage in the PFF for the number
  1167. * of device fonts requested.
  1168. *
  1169. * History:
  1170. * 18-Mar-1991 -by- Gilman Wong [gilmanw]
  1171. * Wrote it.
  1172. \**************************************************************************/
  1173. BOOL
  1174. PFFMEMOBJ::bLoadDeviceFontTable (
  1175. PDEVOBJ *ppdo // physical device
  1176. )
  1177. {
  1178. ULONG iFont; // font face index
  1179. ULONG cFonts = ppdo->cFonts();
  1180. BOOL bUMPD = ppdo->bUMPD();
  1181. BOOL bRet = FALSE;
  1182. PIFIMETRICS pifi; // pointer to font's IFIMETRICS
  1183. FD_GLYPHSET *pfdg; // pointer to font's GLYPHSETs
  1184. ULONG_PTR idifi; // driver id's
  1185. ULONG_PTR idfdg;
  1186. if (cFonts)
  1187. {
  1188. if (!bCreatePFEC(cFonts))
  1189. return bRet;
  1190. //
  1191. // If the device has some fonts, allocate two FONTHASH strcutures
  1192. // and save the addresses of the tables on the PFF
  1193. //
  1194. FHMEMOBJ fhmoFace( &pPFF->pfhFace, FHT_FACE , cFonts);
  1195. FHMEMOBJ fhmoFamily(&pPFF->pfhFamily, FHT_FAMILY, cFonts);
  1196. FHMEMOBJ fhmoUFI(&pPFF->pfhUFI, FHT_UFI, cFonts);
  1197. }
  1198. // Create PFE's for each of the fonts in the font file
  1199. // (Note: iFont indices for device fonts are 1-based, not 0-based)
  1200. for (iFont = 1; iFont<=cFonts; iFont++)
  1201. {
  1202. // Set as NULL before we start to allocate ifi and fd_glyphset
  1203. pfdg = NULL;
  1204. pifi = NULL;
  1205. // Get pointer to metrics
  1206. if (( pifi = ppdo->QueryFont(pPFF->dhpdev, 0, iFont, &idifi )) == NULL )
  1207. {
  1208. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  1209. #if DBG
  1210. DbgPrint("gdisrv!PFFMEMOBJ::bLoadDeviceFontTable(): error getting metrics \
  1211. for iFace = %ld\n", iFont);
  1212. #endif
  1213. goto CleanUp;
  1214. }
  1215. // Get pointer to the UNICODE->HGLYPH mappings
  1216. if (bUMPD)
  1217. {
  1218. pfdg = NULL;
  1219. }
  1220. else
  1221. {
  1222. if ( (pfdg = (FD_GLYPHSET *) ppdo->QueryFontTree(
  1223. pPFF->dhpdev,
  1224. 0,
  1225. iFont,
  1226. QFT_GLYPHSET,
  1227. &idfdg)) == NULL )
  1228. {
  1229. // Failed to get the FD_GLYPHSET information. The entry is
  1230. // partially valid (IFIMETRICS), so lets invalidate the good part.
  1231. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  1232. goto CleanUp;
  1233. }
  1234. // extend the glyph set,
  1235. // it may not contain [f020,f0ff] range for the older drivers
  1236. if (pifi->jWinCharSet == SYMBOL_CHARSET)
  1237. {
  1238. FD_GLYPHSET *pfdgNew = NULL;
  1239. if (bExtendGlyphSet(&pfdg, &pfdgNew))
  1240. {
  1241. if (PPFNVALID(*ppdo,Free))
  1242. {
  1243. ppdo->Free(pfdg, idfdg);
  1244. }
  1245. pfdg = pfdgNew;
  1246. }
  1247. }
  1248. }
  1249. // Put into a new PFE
  1250. // add entry logs error
  1251. if (bAddEntry(iFont, pfdg, idfdg, pifi, idifi,(HANDLE)0,NULL) == FALSE)
  1252. {
  1253. WARNING("bLoadDeviceFontTable():adding PFE\n");
  1254. goto CleanUp;
  1255. }
  1256. }
  1257. bRet = TRUE;
  1258. CleanUp:
  1259. if (!bRet)
  1260. {
  1261. // Free font hash
  1262. FHOBJ fhoFace(&(pPFF->pfhFace));
  1263. if (fhoFace.bValid())
  1264. {
  1265. fhoFace.vFree();
  1266. }
  1267. FHOBJ fhoFamily(&(pPFF->pfhFamily));
  1268. if (fhoFamily.bValid())
  1269. {
  1270. fhoFamily.vFree();
  1271. }
  1272. FHOBJ fhoUFI(&(pPFF->pfhUFI));
  1273. if (fhoUFI.bValid())
  1274. {
  1275. fhoUFI.vFree();
  1276. }
  1277. // Free pfdg
  1278. if ( (pifi != NULL) &&
  1279. (pifi->jWinCharSet == SYMBOL_CHARSET) &&
  1280. (pfdg != NULL) &&
  1281. (pfdg->flAccel & GS_EXTENDED))
  1282. {
  1283. VFREEMEM(pfdg);
  1284. }
  1285. else
  1286. {
  1287. if ((pfdg != NULL) && PPFNVALID(*ppdo,Free))
  1288. {
  1289. ppdo->Free(pfdg, idfdg);
  1290. }
  1291. }
  1292. // Free pifi
  1293. if (pifi)
  1294. {
  1295. if (PPFNVALID(*ppdo,Free))
  1296. {
  1297. ppdo->Free(pifi, idifi);
  1298. }
  1299. }
  1300. }
  1301. return bRet;
  1302. }
  1303. /******************************Public*Routine******************************\
  1304. * BOOL PFFMEMOBJ::bAddEntry *
  1305. * *
  1306. * This function creates a new physical font entry object and adds it to the*
  1307. * end of the table. The iFont parameter identifies the font within this *
  1308. * file. The cjSize and pjMetrics identify a buffer containing face *
  1309. * information including the IFI metrics and the mapping structures *
  1310. * (defining the UNICODE->HGLYPH mapping). *
  1311. * *
  1312. * Returns FALSE if the function fails. *
  1313. * *
  1314. * History: *
  1315. * 02-Jan-1991 -by- Gilman Wong [gilmanw] *
  1316. * Wrote it. *
  1317. \**************************************************************************/
  1318. BOOL PFFMEMOBJ::bAddEntry
  1319. (
  1320. ULONG iFont, // index of the font (IFI or device)
  1321. FD_GLYPHSET *pfdg, // pointer to UNICODE->HGLYPH map
  1322. ULONG_PTR idfdg, // driver id for FD_GLYPHSET
  1323. PIFIMETRICS pifi, // pointer to IFIMETRICS
  1324. ULONG_PTR idifi, // driver id for IFIMETRICS
  1325. HANDLE hdc, // handle of DC if this is a remote font
  1326. PUNIVERSAL_FONT_ID pufi, // used when adding remote fonts
  1327. PEUDCLOAD pEudcLoadData // pointer to EUDCLOAD
  1328. )
  1329. {
  1330. // Allocate memory for a new PFE
  1331. PFECOBJ pfeco(pPFF->pPFEC);
  1332. PFEMEMOBJ pfemo(pfeco.GetPFE(iFont));
  1333. // Validate new object, hmgr logs error if needed
  1334. if (!pfemo.bValid())
  1335. return (FALSE);
  1336. // Initialize the new PFE
  1337. #ifdef FE_SB
  1338. BOOL bEUDC = ( pEudcLoadData != NULL );
  1339. PPFE *pppfeEUDC = ((bEUDC) ? pEudcLoadData->pppfeData : NULL);
  1340. if( !pfemo.bInit(pPFFGet(), iFont, pfdg, idfdg, pifi, idifi, bDeviceFonts(), pufi, bEUDC ))
  1341. {
  1342. return(FALSE);
  1343. }
  1344. if( bEUDC )
  1345. {
  1346. //
  1347. // This font file is loaded as EUDC font.
  1348. //
  1349. if( pEudcLoadData->LinkedFace == NULL )
  1350. {
  1351. //
  1352. // No face name is specified.
  1353. //
  1354. switch( iFont )
  1355. {
  1356. case 1:
  1357. pppfeEUDC[PFE_NORMAL] = pfemo.ppfeGet();
  1358. pppfeEUDC[PFE_VERTICAL] = pppfeEUDC[PFE_NORMAL];
  1359. break;
  1360. case 2:
  1361. //
  1362. // if more than one face name the second face must be an @face
  1363. //
  1364. if( pfemo.pwszFaceName()[0] == (WCHAR) '@' )
  1365. {
  1366. pppfeEUDC[PFE_VERTICAL] = pfemo.ppfeGet();
  1367. #if DBG
  1368. if( gflEUDCDebug & (DEBUG_FONTLINK_LOAD|DEBUG_FONTLINK_INIT) )
  1369. {
  1370. DbgPrint("EUDC font has vertical face %ws %x\n",
  1371. pfemo.pwszFaceName(), pppfeEUDC[PFE_VERTICAL] );
  1372. }
  1373. #endif
  1374. }
  1375. else
  1376. {
  1377. WARNING("bAddEntryPFFMEMOBJ -- second face not a @face.\n");
  1378. }
  1379. break;
  1380. default:
  1381. WARNING("bAddEntryPFFMEMOBJ -- too many faces in EUDC font.\n");
  1382. }
  1383. }
  1384. else
  1385. {
  1386. if( iFont == 1 )
  1387. {
  1388. //
  1389. // link first face as default, because this font file might not
  1390. // contains user's specified face name, but the user want to link
  1391. // this font file. I don't know which is better link it as default
  1392. // or fail link.
  1393. //
  1394. pppfeEUDC[PFE_NORMAL] = pfemo.ppfeGet();
  1395. pppfeEUDC[PFE_VERTICAL] = pppfeEUDC[PFE_NORMAL];
  1396. }
  1397. else
  1398. {
  1399. ULONG iPfeOffset = PFE_NORMAL;
  1400. PWSTR pwszEudcFace = pfemo.pwszFaceName();
  1401. //
  1402. // Is this a vertical face ?
  1403. //
  1404. if( pwszEudcFace[0] == (WCHAR) '@' )
  1405. {
  1406. iPfeOffset = PFE_VERTICAL;
  1407. }
  1408. //
  1409. // Is this a face that we want ?
  1410. //
  1411. if( pfemo.bCheckFamilyName(pEudcLoadData->LinkedFace,1) )
  1412. {
  1413. //
  1414. // Yes....., keep it.
  1415. //
  1416. pppfeEUDC[iPfeOffset] = pfemo.ppfeGet();
  1417. //
  1418. // if this is a PFE for Normal face, also keep it for Vertical face.
  1419. // after this, this value might be over-written by CORRRCT vertical
  1420. // face's PFE.
  1421. //
  1422. // NOTE :
  1423. // This code assume Normal face come faster than Vertical face...
  1424. //
  1425. if( iPfeOffset == PFE_NORMAL )
  1426. pppfeEUDC[PFE_VERTICAL] = pfemo.ppfeGet();
  1427. }
  1428. }
  1429. }
  1430. // mark the FaceNameEUDC pfe list as NULL
  1431. pfemo.vSetLinkedFontEntry( NULL );
  1432. }
  1433. else
  1434. {
  1435. PWSZ pwszAlias = NULL;
  1436. BOOL bIsFamilyNameAlias = FALSE;
  1437. PFLENTRY pFlEntry = NULL;
  1438. // Here we see if there is an EUDC font for this family name.
  1439. pwszAlias = pfemo.pwszFamilyNameAlias(&bIsFamilyNameAlias);
  1440. pFlEntry = FindBaseFontEntry(pwszAlias);
  1441. if (!pFlEntry && bIsFamilyNameAlias)
  1442. {
  1443. pwszAlias += (wcslen(pwszAlias) + 1);
  1444. if (bIsFamilyNameAlias)
  1445. {
  1446. pFlEntry = FindBaseFontEntry(pwszAlias);
  1447. }
  1448. }
  1449. if( pFlEntry != NULL )
  1450. {
  1451. //
  1452. // set eudc list..
  1453. //
  1454. pfemo.vSetLinkedFontEntry( pFlEntry );
  1455. #if DBG
  1456. if( gflEUDCDebug & DEBUG_FACENAME_EUDC )
  1457. {
  1458. PLIST_ENTRY p = pfemo.pGetLinkedFontList()->Flink;
  1459. DbgPrint("Found FaceName EUDC for %ws is ",pfemo.pwszFamilyName());
  1460. while( p != &(pFlEntry->linkedFontListHead) )
  1461. {
  1462. PPFEDATA ppfeData = CONTAINING_RECORD(p,PFEDATA,linkedFontList);
  1463. PFEOBJ pfeo( ppfeData->appfe[PFE_NORMAL] );
  1464. PFFOBJ pffo( pfeo.pPFF() );
  1465. DbgPrint(" %ws ",pffo.pwszPathname());
  1466. p = p->Flink;
  1467. }
  1468. DbgPrint("\n");
  1469. }
  1470. #endif
  1471. }
  1472. else
  1473. {
  1474. // mark the FaceNameEUDC pfe as NULL
  1475. pfemo.vSetLinkedFontEntry( NULL );
  1476. }
  1477. }
  1478. #endif
  1479. // Put PFE pointer into the PFF's table
  1480. ((PFE **) (pPFF->aulData))[pPFF->cFonts++] = pfemo.ppfeGet();
  1481. return (TRUE);
  1482. }
  1483. #if DBG
  1484. /******************************Public*Routine******************************\
  1485. * VOID PFFOBJ::vDump ()
  1486. *
  1487. * Debugging code.
  1488. *
  1489. * History:
  1490. * Thu 02-Apr-1992 12:10:28 by Kirk Olynyk [kirko]
  1491. * DbgPrint supports %ws
  1492. *
  1493. * 25-Feb-1991 -by- Gilman Wong [gilmanw]
  1494. * Wrote it.
  1495. \**************************************************************************/
  1496. VOID PFFOBJ::vDump ()
  1497. {
  1498. DbgPrint("\nContents of PFF, pPFF = 0x%lx\n", pPFFGet());
  1499. if (*(WCHAR *)pwszPathname())
  1500. {
  1501. DbgPrint("Filename = %ws\n", pwszPathname());
  1502. }
  1503. DbgPrint("flState = 0x%lx\n", pPFF->flState);
  1504. DbgPrint("cLoaded = %ld\n", pPFF->cLoaded);
  1505. DbgPrint("cNotEnum = %ld\n", pPFF->cNotEnum);
  1506. DbgPrint("pPvtDataHead = 0x%lx\n", pPFF->pPvtDataHead);
  1507. DbgPrint("cRFONT = %ld\n", pPFF->cRFONT);
  1508. DbgPrint("hff = 0x%lx\n", pPFF->hff);
  1509. DbgPrint("cFonts = %ld\n", pPFF->cFonts);
  1510. DbgPrint("HPFE table\n");
  1511. for (ULONG i=0; i<pPFF->cFonts; i++)
  1512. DbgPrint(" 0x%lx\n", ((PFE **) (pPFF->aulData))[i]);
  1513. DbgPrint("\n");
  1514. }
  1515. #endif
  1516. /******************************Public*Routine******************************\
  1517. * vCleanupFontFile
  1518. *
  1519. * Parses the PFFCLEANUP structure and calls the driver to release
  1520. * its resources and to unload the font file.
  1521. *
  1522. * History:
  1523. * 10-Mar-1993 -by- Gilman Wong [gilmanw]
  1524. * Wrote it.
  1525. \**************************************************************************/
  1526. VOID vCleanupFontFile(PFFCLEANUP *pPFFC)
  1527. {
  1528. // Create PDEV user object so we can call driver functions.
  1529. PDEVOBJ pdo(pPFFC->hdev);
  1530. //
  1531. // If font driver loaded font, call to unload font file.
  1532. //
  1533. if (pPFFC->hff != HFF_INVALID && pPFFC->pPFFClone == NULL)
  1534. {
  1535. BOOL bOK = pdo.UnloadFontFile( pPFFC->hff );
  1536. ASSERTGDI(bOK, "PFFOBJ::vCleanupFontFile(): DrvUnloadFontFile failed\n");
  1537. #if DBG
  1538. if(bOK == -1){
  1539. RIP("PFFOBJ::vCleanupFontFile(): DrvUnloadFontFile failed2\n");
  1540. }
  1541. #endif
  1542. }
  1543. }
  1544. /******************************Public*Routine******************************\
  1545. * pPvtDataMatch() *
  1546. * *
  1547. * Search for existing PvtData for the current process *
  1548. * *
  1549. * Return *
  1550. * if found, return the address of the pPvtData block *
  1551. * *
  1552. * otherwise, return NULL
  1553. * *
  1554. * History: *
  1555. * 11-Aug-1996 -by- Xudong Wu [TessieW] *
  1556. * Wrote it. *
  1557. \**************************************************************************/
  1558. PVTDATA *PFFOBJ::pPvtDataMatch()
  1559. {
  1560. PVTDATA *pPvtDataCur;
  1561. for (pPvtDataCur = pPvtDataHeadGet();
  1562. pPvtDataCur;
  1563. pPvtDataCur = pPvtDataCur->pPvtDataNext)
  1564. {
  1565. if ((pPvtDataCur->fl & FRW_EMB_TID) && (pPvtDataCur->dwID == (DWORD) W32GetCurrentTID()))
  1566. {
  1567. break;
  1568. }
  1569. if (pPvtDataCur->dwID == (DWORD) W32GetCurrentPID())
  1570. {
  1571. break;
  1572. }
  1573. // spooler has the right of using any fonts
  1574. if ((gpidSpool == (PW32PROCESS)W32GetCurrentProcess()) &&
  1575. (pPvtDataCur->fl & FR_PRINT_EMB_FONT))
  1576. break;
  1577. }
  1578. return (pPvtDataCur);
  1579. }
  1580. /******************************Public*Routine******************************\
  1581. * bAddPvtData(ULONG flEmbed) *
  1582. * *
  1583. * Add PvtData data block to the tail of pPvtDataHead link list *
  1584. * *
  1585. * Return FALSE if function fails *
  1586. * *
  1587. * History: *
  1588. * 11-Aug-1996 -by- Xudong Wu [TessieW] *
  1589. * Wrote it. *
  1590. \**************************************************************************/
  1591. BOOL PFFOBJ::bAddPvtData(ULONG flEmbed)
  1592. {
  1593. PVTDATA *pPvtData;
  1594. // Search for the existing PvtData block for the current process
  1595. pPvtData = pPvtDataMatch();
  1596. // PvtData exists for the calling process
  1597. if (pPvtData)
  1598. {
  1599. if (flEmbed & (FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID))
  1600. {
  1601. pPvtData->cNotEnum++;
  1602. }
  1603. else
  1604. {
  1605. pPvtData->cPrivate++;
  1606. }
  1607. pPvtData->fl |= flEmbed & (FR_PRIVATE | FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID);
  1608. return TRUE;
  1609. }
  1610. // no PvtData exists for the current process
  1611. else
  1612. {
  1613. if (pPvtData = (PVTDATA *) PALLOCMEM(sizeof(PVTDATA), 'pvtG'))
  1614. {
  1615. pPvtData->fl = flEmbed & (FR_PRIVATE | FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID);
  1616. // Embedded fonts can't be enumed, so we set cNotEnum to 1
  1617. if (flEmbed & (FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID))
  1618. {
  1619. pPvtData->cPrivate = 0;
  1620. pPvtData->cNotEnum = 1;
  1621. }
  1622. else
  1623. {
  1624. pPvtData->cPrivate = 1;
  1625. pPvtData->cNotEnum = 0;
  1626. }
  1627. pPvtData->dwID = (flEmbed & FRW_EMB_TID) ? (DWORD)W32GetCurrentTID() : (DWORD)W32GetCurrentPID() ;
  1628. pPvtData->pPvtDataNext = pPFF->pPvtDataHead;
  1629. pPFF->pPvtDataHead = pPvtData;
  1630. return TRUE;
  1631. }
  1632. else
  1633. {
  1634. WARNING("PFFOBJ::bAddPvtData(): memory allocation failed\n");
  1635. return FALSE;
  1636. }
  1637. }
  1638. }
  1639. /******************************Public*Routine******************************\
  1640. * bRemovePvtData(PVTDATA *pPvtData) *
  1641. * *
  1642. * Rmove the PvtData data block from the pPvtDataHead link list *
  1643. * *
  1644. * Return FALSE if function fails *
  1645. * *
  1646. * History: *
  1647. * 27-Set-1996 -by- Xudong Wu [TessieW] *
  1648. * Wrote it. *
  1649. \**************************************************************************/
  1650. BOOL PFFOBJ::bRemovePvtData(PVTDATA *pPvtData)
  1651. {
  1652. PVTDATA *pPrev, *pCur;
  1653. pPrev = pPvtDataHeadGet();
  1654. if (!pPrev)
  1655. {
  1656. WARNING("PFFOBJ::bRemovePvtData: try to remove PvtData block from NULL list\n");
  1657. return FALSE;
  1658. }
  1659. // remove the PvtData block from the head of the list
  1660. if ( pPrev == pPvtData)
  1661. {
  1662. pPFF->pPvtDataHead = pPvtData->pPvtDataNext;
  1663. VFREEMEM(pPvtData);
  1664. return TRUE;
  1665. }
  1666. while (pCur = pPrev->pPvtDataNext)
  1667. {
  1668. if (pCur == pPvtData)
  1669. {
  1670. pPrev->pPvtDataNext = pPvtData->pPvtDataNext;
  1671. VFREEMEM(pPvtData);
  1672. return TRUE;
  1673. }
  1674. pPrev = pCur;
  1675. }
  1676. return FALSE;
  1677. }