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.

1753 lines
51 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: ufi.c
  3. *
  4. * Copyright (c) 1995-1999 Microsoft Corporation
  5. \**************************************************************************/
  6. #include "precomp.h"
  7. #pragma hdrstop
  8. FPCREATEFONTPACKAGE gfpCreateFontPackage= (FPCREATEFONTPACKAGE)NULL;
  9. FPMERGEFONTPACKAGE gfpMergeFontPackage = (FPMERGEFONTPACKAGE)NULL;
  10. ULONG gulMaxCig = 3000;
  11. #ifdef DBGSUBSET
  12. FLONG gflSubset = 0;
  13. #endif // DBGSUBSET
  14. /***********************************************************
  15. * BOOL bAddGlyphIndices(HDC, PUFIHASH, WCHAR, int, BOOL)
  16. *
  17. * Adds distinct glyph indices into UFI hash bucket
  18. *
  19. * History
  20. * Dec-13-96 Xudong Wu [tessiew]
  21. * Wrote it.
  22. *
  23. ************************************************************/
  24. #define MAX_STACK_STRING 80
  25. BOOL bAddGlyphIndices(HDC hdc, PUFIHASH pBucket, WCHAR *pwsz, int c, UINT flETO)
  26. {
  27. BOOL bDelta = pBucket->fs1 & FLUFI_DELTA;
  28. WCHAR *pwc=pwsz;
  29. WORD *pgi, *pgiTmp, *pgiEnd;
  30. PBYTE pb, pbDelta;
  31. WORD agi[MAX_STACK_STRING];
  32. BOOL bRet = FALSE;
  33. if (c && pwsz)
  34. {
  35. if (bDelta && (pBucket->u.ssi.pjDelta == NULL))
  36. {
  37. pBucket->u.ssi.cDeltaGlyphs = 0;
  38. pBucket->u.ssi.pjDelta = (PBYTE)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, pBucket->u.ssi.cjBits);
  39. if (pBucket->u.ssi.pjDelta == NULL)
  40. {
  41. WARNING("bAddGlyphIndices: unable to allocate mem for delta glyph indices\n");
  42. return FALSE;
  43. }
  44. }
  45. if (c > MAX_STACK_STRING)
  46. {
  47. pgi = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, c * sizeof(WORD));
  48. }
  49. else
  50. {
  51. pgi = agi;
  52. }
  53. if (pgi)
  54. {
  55. if (flETO & ETO_GLYPH_INDEX)
  56. {
  57. RtlCopyMemory((PBYTE)pgi, (PBYTE)pwsz, c*sizeof(WORD));
  58. }
  59. pgiTmp = pgi;
  60. if ((flETO & ETO_GLYPH_INDEX) ||
  61. (NtGdiGetGlyphIndicesWInternal(hdc, pwc, c, pgi, 0, TRUE) != GDI_ERROR))
  62. {
  63. for (pgiEnd = pgiTmp + c ; pgi < pgiEnd; pgi++)
  64. {
  65. BYTE jTmp;
  66. pb = pBucket->u.ssi.pjBits + (*pgi >> 3);
  67. pbDelta = pBucket->u.ssi.pjDelta + (*pgi >> 3);
  68. // map to the u.ssi.pjBits and u.ssi.pjDelta if bDelta
  69. jTmp = (BYTE)(1 << (*pgi & 7));
  70. if (!(*pb & jTmp))
  71. {
  72. *pb |= jTmp;
  73. pBucket->u.ssi.cGlyphsSoFar++;
  74. // if this gi is not found in pjBits, it certainly
  75. // will not be found in pjDelta
  76. if (bDelta)
  77. {
  78. ASSERTGDI((*pbDelta & jTmp) == 0,
  79. "pbDelta contains the gi\n");
  80. *pbDelta |= jTmp;
  81. pBucket->u.ssi.cDeltaGlyphs++;
  82. }
  83. }
  84. }
  85. bRet = TRUE;
  86. }
  87. if (pgiTmp != agi)
  88. LocalFree(pgiTmp);
  89. }
  90. #if DBG
  91. else
  92. {
  93. WARNING("bAddGlyphIndices unable to allocate mem for pgi\n");
  94. }
  95. #endif
  96. }
  97. else
  98. {
  99. bRet = TRUE;
  100. }
  101. return bRet;
  102. }
  103. /******************************************************************
  104. * BOOL bGetDistGlyphIndices(PUFIHASH, USHORT*, BOOL)
  105. *
  106. * Get distinct glyph indices from pjMemory in the ufi hash bucket
  107. * Reverse of bAddGlyphIndices
  108. * Clean up the u.ssi.pjDelta and u.ssi.cDeltaGlyphs before it return.
  109. *
  110. * History
  111. * Dec-17-96 Xudong Wu [tessiew]
  112. * Wrote it.
  113. *
  114. *******************************************************************/
  115. BOOL bGetDistGlyphIndices(PUFIHASH pBucket, USHORT *pusSubsetKeepList, BOOL bDelta)
  116. {
  117. ULONG ulBytes;
  118. PBYTE pb;
  119. USHORT gi, index;
  120. USHORT *pNextGlyph;
  121. ulBytes = pBucket->u.ssi.cjBits;
  122. pb = (bDelta ? pBucket->u.ssi.pjDelta : pBucket->u.ssi.pjBits);
  123. for(index = 0, pNextGlyph = pusSubsetKeepList; index < ulBytes; index++, pb++)
  124. {
  125. if (*pb)
  126. {
  127. gi = index << 3;
  128. if (*pb & 0x01)
  129. {
  130. *pNextGlyph ++= gi;
  131. }
  132. if (*pb & 0x02)
  133. {
  134. *pNextGlyph ++= gi+1;
  135. }
  136. if (*pb & 0x04)
  137. {
  138. *pNextGlyph ++= gi+2;
  139. }
  140. if (*pb & 0x08)
  141. {
  142. *pNextGlyph ++= gi+3;
  143. }
  144. if (*pb & 0x10)
  145. {
  146. *pNextGlyph ++= gi+4;
  147. }
  148. if (*pb & 0x20)
  149. {
  150. *pNextGlyph ++= gi+5;
  151. }
  152. if (*pb & 0x40)
  153. {
  154. *pNextGlyph ++= gi+6;
  155. }
  156. if (*pb & 0x80)
  157. {
  158. *pNextGlyph ++= gi+7;
  159. }
  160. }
  161. }
  162. return TRUE;
  163. }
  164. /********************************************************************************
  165. * BOOL bWriteUFItoDC(PUFIHASH*, PUNIVERSAL_FONT_ID, PUFIHASH, PVOID, ULONG)
  166. *
  167. * Write merge font image into the UFI hash table on the print server side.
  168. * pBucketIn == NULL, indicates a new font subsetting.
  169. * This is only called on print server
  170. *
  171. * History
  172. * Jan-28-1997 Xudong Wu [tessiew]
  173. * Wrote it.
  174. *
  175. *********************************************************************************/
  176. BOOL bWriteUFItoDC(
  177. PUFIHASH *ppHashBase,
  178. PUNIVERSAL_FONT_ID pufi,
  179. PUFIHASH pBucketIn,// NULL=>First page, else
  180. PVOID pvBuffer, // points to the merged font image preceeded with DOWNLOADFONTHEADER
  181. ULONG ulBytes
  182. )
  183. {
  184. PUFIHASH pBucket = pBucketIn;
  185. ULONG index, ulHeaderSize;
  186. ASSERTGDI(pvBuffer != NULL, "pWriteUFItoDC attempts to add an NULL ufi\n");
  187. // First page for font subset
  188. if (!pBucketIn)
  189. {
  190. index = UFI_HASH_VALUE(pufi) % UFI_HASH_SIZE;
  191. pBucket = LOCALALLOC (offsetof(UFIHASH,u.mvw) + sizeof(MERGEDVIEW));
  192. if (pBucket == NULL)
  193. {
  194. WARNING("pWriteUFItoDC: unable to allocate mem for glyph indices\n");
  195. return FALSE;
  196. }
  197. pBucket->ufi = *pufi;
  198. pBucket->pNext = ppHashBase[index];
  199. pBucket->fs1 = FLUFI_SERVER; // server side hash bucket
  200. ppHashBase[index] = pBucket;
  201. }
  202. else
  203. {
  204. // pjMemory contains the image of the font subsetted up unil
  205. // the page preceeding this one. Other info in pBucket is ok.
  206. LocalFree(pBucket->u.mvw.pjMem);
  207. }
  208. // pvBuffer includes the DOWNLOADFONTHEADER information
  209. pBucket->u.mvw.pjMem = (PBYTE)pvBuffer;
  210. pBucket->u.mvw.cjMem = ulBytes;
  211. return TRUE;
  212. }
  213. /**************************************************************************
  214. *
  215. * Adds an entry to the UFI hash table, this routine only executes
  216. * on a print client machine.
  217. *
  218. * History
  219. * Dec-16-96 Xudong Wu [tessiew]
  220. * Modify to return the bucket pointer.
  221. * 1-27-95 Gerrit van Wingerden [gerritv]
  222. * Wrote it.
  223. *
  224. ***************************************************************************/
  225. PUFIHASH pufihAddUFIEntry(
  226. PUFIHASH *ppHashBase,
  227. PUNIVERSAL_FONT_ID pufi,
  228. ULONG ulCig,
  229. FLONG fl,
  230. FLONG fs2)
  231. {
  232. PUFIHASH pBucket;
  233. ULONG index;
  234. ULONG cjGlyphBitfield = (ulCig + 7) / 8;
  235. index = UFI_HASH_VALUE(pufi) % UFI_HASH_SIZE;
  236. pBucket = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
  237. (fl & FL_UFI_SUBSET) ?
  238. (offsetof(UFIHASH,u.ssi) + sizeof(SSINFO) + cjGlyphBitfield) :
  239. offsetof(UFIHASH,u)
  240. );
  241. if (pBucket == NULL)
  242. {
  243. WARNING("pufihAddUFIEntry: unable to allocate mem for glyph indices\n");
  244. return NULL;
  245. }
  246. // these fields are always there
  247. pBucket->ufi = *pufi;
  248. pBucket->pNext = ppHashBase[index];
  249. pBucket->fs1 = 0;
  250. pBucket->fs2 = (FSHORT)fs2;
  251. ppHashBase[index] = pBucket;
  252. // these fields are there only for subsetting case
  253. if (fl & FL_UFI_SUBSET)
  254. {
  255. // all other fields are zero initialized by LocalAlloc
  256. ASSERTGDI (ulCig, "no font subsetting for ulCig == 0\n");
  257. pBucket->u.ssi.cjBits = cjGlyphBitfield; // bitfield size
  258. pBucket->u.ssi.pjBits = (PBYTE)pBucket + offsetof(UFIHASH,u.ssi) + sizeof(SSINFO);
  259. }
  260. return(pBucket);
  261. }
  262. /**************************************************************************
  263. *
  264. * Checks to see if an entry is in the UFI table.
  265. *
  266. * History
  267. * Dec-13-96 Xudong Wu [tessiew]
  268. * Changed its return value from BOOL to PUFIHASH.
  269. * 1-27-95 Gerrit van Wingerden [gerritv]
  270. * Wrote it.
  271. *
  272. ***************************************************************************/
  273. PUFIHASH pufihFindUFIEntry(PUFIHASH *ppHashBase, PUNIVERSAL_FONT_ID pufi, BOOL SubsetHashBase)
  274. {
  275. PUFIHASH pBucket;
  276. ULONG index;
  277. index = UFI_HASH_VALUE(pufi) % UFI_HASH_SIZE;
  278. pBucket = ppHashBase[index];
  279. if( pBucket == NULL )
  280. {
  281. return(NULL);
  282. }
  283. do
  284. {
  285. if (UFI_SAME_FILE(&pBucket->ufi,pufi))
  286. {
  287. if (SubsetHashBase)
  288. {
  289. if ((pBucket->ufi.Index -1)/2 == (pufi->Index -1)/2)
  290. {
  291. return (pBucket);
  292. }
  293. }
  294. else
  295. {
  296. return(pBucket);
  297. }
  298. }
  299. pBucket = pBucket->pNext;
  300. } while( pBucket != NULL );
  301. return(NULL);
  302. }
  303. /************************************************************
  304. * VOID vRemoveUFIEntry(PUFIHASH*, PUNIVERSAL_FONT_ID)
  305. *
  306. * Remove a UFI entry from the UFI hash list
  307. * Function returns TRUE if UFI doesn't exist in the table.
  308. * This is happening on the print client, typically when subsetter failed
  309. * we call this to remove the bucket from ppSubUFIHash table (and then later
  310. * add it to the ppUFIHash, ie hash table of fonts that are going to be shipped
  311. * over without subsetting.
  312. *
  313. * History
  314. * Feb-03-97 Xudong Wu [tessiew]
  315. * Wrote it.
  316. *
  317. ***************************************************************************/
  318. VOID vRemoveUFIEntry(PUFIHASH *ppHashBase, PUNIVERSAL_FONT_ID pufi)
  319. {
  320. PUFIHASH pBucket, pPrev;
  321. ULONG index;
  322. index = UFI_HASH_VALUE(pufi) % UFI_HASH_SIZE;
  323. pPrev = pBucket = ppHashBase[index];
  324. while(pBucket)
  325. {
  326. if (UFI_SAME_FILE(&pBucket->ufi, pufi) &&
  327. ((pBucket->ufi.Index - 1)/2 == (pufi->Index - 1)/2))
  328. {
  329. break;
  330. }
  331. else
  332. {
  333. pPrev = pBucket;
  334. pBucket = pBucket->pNext;
  335. }
  336. }
  337. if (pBucket != NULL)
  338. {
  339. if (pPrev == pBucket)
  340. {
  341. ppHashBase[index] = pBucket->pNext;
  342. }
  343. else
  344. {
  345. pPrev->pNext = pBucket->pNext;
  346. }
  347. // this is only happening for subsetting ufi hash list => u.ssi.pjDelta exists
  348. if (pBucket->u.ssi.pjDelta)
  349. {
  350. LocalFree(pBucket->u.ssi.pjDelta);
  351. }
  352. LocalFree(pBucket);
  353. }
  354. }
  355. /**************************************************************************
  356. * VOID vFreeUFIHashTable( PUFIHASH *ppHashTable )
  357. *
  358. * Frees all the memory allocated for the UFI has table.
  359. *
  360. * History
  361. * 1-27-95 Gerrit van Wingerden [gerritv]
  362. * Wrote it.
  363. *
  364. ***************************************************************************/
  365. VOID vFreeUFIHashTable(PUFIHASH *ppHashTable, FLONG fl)
  366. {
  367. PUFIHASH pBucket, *ppHashEnd, pBucketTmp, *ppTableBase;
  368. if( ppHashTable == NULL )
  369. {
  370. return;
  371. }
  372. ppTableBase = ppHashTable; // save ptr to the base so we can free it later
  373. // Next loop through the whole table looking for buckets lists
  374. for( ppHashEnd = ppHashTable + UFI_HASH_SIZE;
  375. ppHashTable < ppHashEnd;
  376. ppHashTable += 1 )
  377. {
  378. pBucket = *ppHashTable;
  379. while( pBucket != NULL )
  380. {
  381. pBucketTmp = pBucket;
  382. pBucket = pBucket->pNext;
  383. // subsetting hash table
  384. if (fl & FL_UFI_SUBSET)
  385. {
  386. if (pBucketTmp->fs1 & FLUFI_SERVER) // server, clean the merged font image
  387. {
  388. if (pBucketTmp->u.mvw.pjMem)
  389. {
  390. LocalFree(pBucketTmp->u.mvw.pjMem);
  391. }
  392. }
  393. else // client, clean the glyph indices list
  394. {
  395. if (pBucketTmp->u.ssi.pjDelta)
  396. {
  397. LocalFree(pBucketTmp->u.ssi.pjDelta);
  398. }
  399. }
  400. }
  401. LocalFree (pBucketTmp);
  402. }
  403. }
  404. }
  405. ULONG GetRecdEmbedFonts(PUFIHASH *ppHashTable)
  406. {
  407. PUFIHASH pBucket, *ppHashEnd;
  408. ULONG cEmbedFonts = 0;
  409. if( ppHashTable == NULL )
  410. return 0;
  411. for( ppHashEnd = ppHashTable + UFI_HASH_SIZE;
  412. ppHashTable < ppHashEnd;
  413. ppHashTable += 1 )
  414. {
  415. pBucket = *ppHashTable;
  416. while( pBucket != NULL )
  417. {
  418. cEmbedFonts++;
  419. pBucket = pBucket->pNext;
  420. }
  421. }
  422. return cEmbedFonts;
  423. }
  424. typedef union _DLHEADER
  425. {
  426. DOWNLOADFONTHEADER dfh;
  427. double f; // to achieve max alignment
  428. } DLHEADER;
  429. BOOL WriteFontToSpoolFile(PLDC pldc, PUNIVERSAL_FONT_ID pufi, FLONG fl)
  430. {
  431. BOOL bRet = FALSE;
  432. ULONG cwcPathname, cNumFiles;
  433. WCHAR *pwszFile = NULL;
  434. WCHAR pwszPathname[MAX_PATH * 3];
  435. CLIENT_SIDE_FILEVIEW fvw;
  436. DLHEADER dlh;
  437. ULONG cjView;
  438. PVOID pvView = NULL;
  439. BOOL bMemFont = FALSE, bMapOK = TRUE;
  440. #ifdef DBGSUBSET
  441. FILETIME fileTimeStart, fileTimeEnd;
  442. DbgPrint("\nWriteFontToSpoolFile called\n");
  443. if (gflSubset & FL_SS_SPOOLTIME)
  444. {
  445. GetSystemTimeAsFileTime(&fileTimeStart);
  446. }
  447. #endif
  448. RtlZeroMemory(&dlh, sizeof(DLHEADER));
  449. if (NtGdiGetUFIPathname(pufi,
  450. &cwcPathname,
  451. pwszPathname,
  452. &cNumFiles,
  453. fl,
  454. &bMemFont,
  455. &cjView,
  456. NULL,
  457. NULL,
  458. NULL))
  459. {
  460. if (cNumFiles == 1)
  461. {
  462. ASSERTGDI(cwcPathname <= MAX_PATH, "WriteFontToSpoolFile: cwcPathname\n");
  463. if (!bMemFont)
  464. {
  465. if (!bMapFileUNICODEClideSide(pwszPathname, &fvw, TRUE))
  466. {
  467. bMapOK = FALSE;
  468. WARNING("WriteFontToSpooler: error map the font file\n");
  469. }
  470. }
  471. else
  472. {
  473. // must allocate memory and call again to get the bits:
  474. pvView = LocalAlloc( LMEM_FIXED, cjView ) ;
  475. if (!pvView)
  476. {
  477. bMapOK = FALSE;
  478. WARNING("WriteFontToSpooler: error allocating mem for mem font\n");
  479. }
  480. // Write the bits into the buffer
  481. if (!NtGdiGetUFIPathname(pufi,NULL,NULL,NULL,fl,
  482. NULL,NULL,pvView,NULL,NULL))
  483. {
  484. bMapOK = FALSE;
  485. LocalFree(pvView);
  486. pvView = NULL;
  487. WARNING("WriteFontToSpooler: could not get mem bits\n");
  488. }
  489. }
  490. if (bMapOK)
  491. {
  492. DOWNLOADFONTHEADER* pdfh = &dlh.dfh;
  493. pdfh->Type1ID = 0;
  494. pdfh->NumFiles = cNumFiles;
  495. if (!bMemFont)
  496. {
  497. cjView = fvw.cjView;
  498. pvView = fvw.pvView;
  499. }
  500. pdfh->FileOffsets[0] = cjView;
  501. if (WriteFontDataAsEMFComment(
  502. pldc,
  503. EMRI_ENGINE_FONT,
  504. pdfh,
  505. sizeof(DLHEADER),
  506. pvView,
  507. cjView))
  508. {
  509. MFD1("Done writing UFI to printer\n");
  510. bRet = TRUE;
  511. }
  512. else
  513. {
  514. WARNING("WriteFontToSpooler: error writing to printer\n");
  515. }
  516. if (bMemFont)
  517. {
  518. if (pvView) { LocalFree(pvView);}
  519. }
  520. else
  521. {
  522. vUnmapFileClideSide(&fvw);
  523. }
  524. }
  525. }
  526. else
  527. {
  528. CLIENT_SIDE_FILEVIEW afvw[3];
  529. ULONG iFile;
  530. ULONG cjdh;
  531. if (cNumFiles > 3)
  532. return FALSE;
  533. ASSERTGDI(cwcPathname <= (cNumFiles * MAX_PATH), "cwcPathname too big\n");
  534. ASSERTGDI(!bMemFont, "there can not be memory type1 font\n");
  535. pwszFile = pwszPathname;
  536. bMapOK = TRUE;
  537. cjView = 0;
  538. for (iFile = 0; iFile < cNumFiles; iFile++)
  539. {
  540. if (!bMapFileUNICODEClideSide(pwszFile, &afvw[iFile], TRUE))
  541. {
  542. ULONG iFile2;
  543. bMapOK = FALSE;
  544. WARNING("WriteFontToSpooler: error mapping the font file\n");
  545. for (iFile2 = 0; iFile2 < cNumFiles; iFile2++)
  546. {
  547. vUnmapFileClideSide(&afvw[iFile2]);
  548. }
  549. break;
  550. }
  551. // advance to the path name of the next font file
  552. while (*pwszFile++);
  553. cjView += ALIGN4(afvw[iFile].cjView);
  554. }
  555. if (bMapOK)
  556. {
  557. cjdh = ALIGN8(offsetof(DOWNLOADFONTHEADER, FileOffsets) + cNumFiles * sizeof(ULONG));
  558. pvView = LocalAlloc(LMEM_FIXED, cjdh + cjView);
  559. if (pvView)
  560. {
  561. DOWNLOADFONTHEADER* pdfh = (DOWNLOADFONTHEADER *) pvView;
  562. ULONG dpFile;
  563. BYTE *pjFile = (BYTE *)pvView + cjdh;
  564. RtlZeroMemory(pvView, cjdh); // zero out top portion of the buffer only
  565. for (dpFile = 0, iFile = 0; iFile < cNumFiles; iFile++)
  566. {
  567. // first offset is implicit at cjdh, the second offset is
  568. // at ALIGN4(cjView) of the first file etc.
  569. dpFile += ALIGN4(afvw[iFile].cjView);
  570. pdfh->FileOffsets[iFile] = dpFile;
  571. RtlCopyMemory(pjFile, afvw[iFile].pvView, afvw[iFile].cjView);
  572. pjFile += ALIGN4(afvw[iFile].cjView);
  573. }
  574. pdfh->Type1ID = 0; // is this correct?
  575. pdfh->NumFiles = cNumFiles;
  576. if (WriteFontDataAsEMFComment(
  577. pldc,
  578. EMRI_TYPE1_FONT,
  579. pdfh,
  580. cjdh,
  581. (BYTE *)pvView + cjdh,
  582. cjView))
  583. {
  584. MFD1("Done writing UFI to printer\n");
  585. bRet = TRUE;
  586. }
  587. else
  588. {
  589. WARNING("WriteFontToSpooler: error writing to printer\n");
  590. }
  591. LocalFree(pvView);
  592. }
  593. // clean up
  594. for (iFile = 0; iFile < cNumFiles; iFile++)
  595. {
  596. vUnmapFileClideSide(&afvw[iFile]);
  597. }
  598. }
  599. }
  600. }
  601. else
  602. {
  603. WARNING("NtGdiGetUFIPathname failed\n");
  604. }
  605. //timing code
  606. #ifdef DBGSUBSET
  607. if (gflSubset & FL_SS_SPOOLTIME)
  608. {
  609. GetSystemTimeAsFileTime(&fileTimeEnd);
  610. DbgPrint("WriteFontToSpoolfile(millisec): %ld\n", (fileTimeEnd.dwLowDateTime - fileTimeStart.dwLowDateTime) / 10000);
  611. }
  612. #endif
  613. return(bRet);
  614. }
  615. /******************************Public*Routine******************************\
  616. *
  617. *
  618. *
  619. * Effects:
  620. *
  621. * Warnings:
  622. *
  623. * History:
  624. * 16-Jan-1997 -by- Bodin Dresevic [BodinD]
  625. * Wrote it.
  626. \**************************************************************************/
  627. BOOL WriteDesignVectorToSpoolFile (
  628. PLDC pldc,
  629. UNIVERSAL_FONT_ID *pufiBase,
  630. DESIGNVECTOR *pdv,
  631. ULONG cjDV
  632. )
  633. {
  634. BOOL bRet = FALSE;
  635. DOWNLOADDESIGNVECTOR ddv;
  636. ddv.ufiBase = *pufiBase;
  637. RtlCopyMemory(&ddv.dv, pdv, cjDV); // small copy
  638. if (WriteFontDataAsEMFComment(
  639. pldc,
  640. EMRI_DESIGNVECTOR,
  641. &ddv,
  642. offsetof(DOWNLOADDESIGNVECTOR,dv) + cjDV,
  643. NULL,
  644. 0))
  645. {
  646. MFD1("Done writing DesignVector to spool file\n");
  647. bRet = TRUE;
  648. }
  649. else
  650. {
  651. WARNING("WriteDesignVectorToSpooler: spooling error\n");
  652. }
  653. return(bRet);
  654. }
  655. /***********************************************************
  656. * BOOL bAddUFIandWriteSpool(HDC,PUNIVERSAL_FONT_ID,BOOL)
  657. * Called only on the print client when subsetter failed
  658. * or when we could not write a subsetted font to the spool file.
  659. *
  660. * History
  661. * Feb-03-1997 Xudong Wu [tessiew]
  662. * Wrote it.
  663. ************************************************************/
  664. BOOL bAddUFIandWriteSpool(
  665. HDC hdc,
  666. PUNIVERSAL_FONT_ID pufi,
  667. BOOL bSubset,
  668. FLONG fl
  669. )
  670. {
  671. PLDC pldc;
  672. UNIVERSAL_FONT_ID ufi = *pufi;
  673. pldc = GET_PLDC(hdc);
  674. if (pldc == NULL)
  675. {
  676. return (FALSE);
  677. }
  678. if(bSubset)
  679. {
  680. vRemoveUFIEntry(pldc->ppSubUFIHash, pufi);
  681. }
  682. // We might have freed the bucket entry,
  683. // which means that pufi pointer might not be valid anymore.
  684. // That is why we saved it above before calling vRemoveUFIEntry.
  685. if (!pufihAddUFIEntry(pldc->ppUFIHash, &ufi, 0, 0, fl) ||
  686. !WriteFontToSpoolFile(pldc, &ufi, fl))
  687. {
  688. return FALSE;
  689. }
  690. return TRUE;
  691. }
  692. #define QUICK_UFIS 8
  693. /**************************************************************************
  694. * BOOL bDoFontChange( HDC hdc )
  695. *
  696. * Called everytime the font changes in the DC. This routines checks to
  697. * see if the font has already been packaged in the spool file and if not
  698. * gets the raw bits for it and packages it into the spool file.
  699. *
  700. * History
  701. * Dec-12-96 Xudong Wu [tessiew]
  702. * Modify it so it can handle the font subsetting.
  703. * 1-27-95 Gerrit van Wingerden [gerritv]
  704. * Wrote it.
  705. *
  706. ***************************************************************************/
  707. BOOL bDoFontChange( HDC hdc, WCHAR *pwsz, int c, UINT flETO )
  708. {
  709. PLDC pldc;
  710. BOOL bRet = FALSE;
  711. UNIVERSAL_FONT_ID ufi;
  712. UNIVERSAL_FONT_ID ufiBase;
  713. DESIGNVECTOR dv;
  714. ULONG cjDV = 0;
  715. ULONG ulBaseCheckSum;
  716. FLONG fl = 0; // initialization essential
  717. pldc = GET_PLDC( hdc );
  718. if (pldc == NULL)
  719. {
  720. WARNING("bDoFontChange: unable to retrieve pldc\n");
  721. return(FALSE);
  722. }
  723. pldc->fl &= ~LDC_FONT_CHANGE;
  724. if (!NtGdiGetUFI(hdc, &ufi, &dv, &cjDV, &ulBaseCheckSum, &fl))
  725. {
  726. WARNING("bDoFontChange: call to GetUFI failed\n");
  727. return(FALSE);
  728. }
  729. // if the UFI to which we are forcing mapping does not match the new UFI then
  730. // set forced mapping to the new UFI
  731. if((pldc->fl & LDC_FORCE_MAPPING) &&
  732. (!UFI_SAME_FACE(&pldc->ufi,&ufi) || (pldc->fl & LDC_LINKED_FONTS)))
  733. {
  734. INT NumLinkedUFIs;
  735. if (!UFI_SAME_FACE(&pldc->ufi, &ufi))
  736. {
  737. if(!MF_ForceUFIMapping(hdc, &ufi))
  738. {
  739. WARNING("bDoFontChange: call to MF_ForceUFIMapping failed\n");
  740. return(FALSE);
  741. }
  742. pldc->ufi = ufi;
  743. }
  744. if(NtGdiAnyLinkedFonts())
  745. {
  746. UNIVERSAL_FONT_ID QuickLinks[QUICK_UFIS];
  747. PUNIVERSAL_FONT_ID pUFIs = NULL;
  748. NumLinkedUFIs = NtGdiGetLinkedUFIs(hdc, NULL, 0);
  749. if (NumLinkedUFIs > 0)
  750. {
  751. pldc->fl |= LDC_LINKED_FONTS;
  752. if(NumLinkedUFIs <= QUICK_UFIS)
  753. {
  754. pUFIs = QuickLinks;
  755. }
  756. else
  757. {
  758. pUFIs = LocalAlloc(LMEM_FIXED, NumLinkedUFIs * sizeof(UNIVERSAL_FONT_ID));
  759. }
  760. }
  761. if (pUFIs)
  762. {
  763. if(NumLinkedUFIs = NtGdiGetLinkedUFIs(hdc,pUFIs,NumLinkedUFIs))
  764. {
  765. INT u;
  766. WORD *pgi = NULL, agi[MAX_STACK_STRING];
  767. BOOL bNeedLinkFont = FALSE;
  768. bRet = TRUE;
  769. if((pldc->fl & LDC_DOWNLOAD_FONTS) &&
  770. c && pwsz && !(flETO & ETO_GLYPH_INDEX))
  771. {
  772. if (c > MAX_STACK_STRING)
  773. {
  774. pgi = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, c * sizeof(WORD));
  775. }
  776. else
  777. {
  778. pgi = agi;
  779. }
  780. // check whether there are glyphs from linked font
  781. if (pgi &&
  782. NtGdiGetGlyphIndicesW(hdc, pwsz, c, pgi, GGI_MARK_NONEXISTING_GLYPHS) != GDI_ERROR)
  783. {
  784. for (u = 0; u < c; u++)
  785. {
  786. if (pgi[u] == 0xffff)
  787. {
  788. bNeedLinkFont = TRUE;
  789. break;
  790. }
  791. }
  792. }
  793. else
  794. {
  795. bNeedLinkFont = TRUE; // ship them, just in case
  796. }
  797. if (bNeedLinkFont)
  798. {
  799. for(u = 0; u < NumLinkedUFIs; u++)
  800. {
  801. if(pufihFindUFIEntry(pldc->ppUFIHash, &pUFIs[u], FALSE))
  802. {
  803. // already in spool file or on remote machine so skip it
  804. continue;
  805. }
  806. #if DBG
  807. DbgPrint("Writing link to spooler\n");
  808. #endif
  809. // WHAT IS fs2 flag that should be passed to these 2 functions ???
  810. if(!pufihAddUFIEntry(pldc->ppUFIHash, &pUFIs[u], 0, 0, 0) ||
  811. !WriteFontToSpoolFile(pldc,&pUFIs[u], 0))
  812. {
  813. WARNING("GDI32:error writing linked font to spooler\n");
  814. bRet = FALSE;
  815. }
  816. }
  817. if (bRet)
  818. {
  819. pldc->fl &= ~LDC_LINKED_FONTS;
  820. }
  821. }
  822. }
  823. if (pgi && (pgi != agi))
  824. {
  825. LocalFree(pgi);
  826. }
  827. }
  828. if(bRet)
  829. {
  830. // If there are no linked UFI's we still need to metafile the call
  831. // so that the server knows to turn off linking.
  832. bRet = MF_SetLinkedUFIs(hdc, pUFIs, (UINT)NumLinkedUFIs);
  833. }
  834. if(pUFIs != QuickLinks)
  835. {
  836. LocalFree(pUFIs);
  837. }
  838. if(!bRet)
  839. {
  840. return(FALSE);
  841. }
  842. }
  843. }
  844. }
  845. if( UFI_DEVICE_FONT(&ufi) ||
  846. !(pldc->fl & LDC_DOWNLOAD_FONTS) )
  847. {
  848. return(TRUE);
  849. }
  850. // now comes the interesting part:
  851. // If this is a mm instance, we send the base font first (if not sent already)
  852. // and then we send the design vector with the ufi of the base font.
  853. ufiBase = ufi;
  854. if (fl & FL_UFI_DESIGNVECTOR_PFF)
  855. {
  856. // little bit dirty, we should not know what is in ufi
  857. ufiBase.CheckSum = ulBaseCheckSum;
  858. }
  859. // pldc->ppUFIHash is used to remember all remote fonts which have been
  860. // copied into the spool file without subset. Once it is in spool file,
  861. // there is no need to copy again.
  862. if (pufihFindUFIEntry(pldc->ppUFIHash, &ufiBase, FALSE) == NULL)
  863. {
  864. if (fl & FL_UFI_DESIGNVECTOR_PFF)
  865. {
  866. pufihAddUFIEntry(pldc->ppUFIHash, &ufiBase,0, 0, fl);
  867. bRet = WriteFontToSpoolFile(pldc, &ufiBase, fl);
  868. // now since this is a mm instance, write a design vector object in the spool file
  869. // if we have not done it already
  870. if (bRet)
  871. {
  872. if (!pufihFindUFIEntry(pldc->ppDVUFIHash, &ufi, FALSE))
  873. {
  874. pufihAddUFIEntry(pldc->ppDVUFIHash, &ufi,0, 0, fl);
  875. bRet = WriteDesignVectorToSpoolFile(pldc, &ufiBase, &dv, cjDV);
  876. }
  877. }
  878. }
  879. else
  880. {
  881. BOOL bFontSubset = TRUE, bSubsetFail = FALSE;
  882. PUFIHASH pBucket;
  883. // Check the ppSubUFIHash to see whether ufi already exists
  884. if ((pBucket = pufihFindUFIEntry(pldc->ppSubUFIHash, &ufi, TRUE)) == NULL)
  885. {
  886. ULONG ulCig = NtGdiGetGlyphIndicesW(hdc, NULL, 0, NULL, 0);
  887. DWORD cjGlyf = NtGdiGetFontData(hdc, 'fylg', 0, NULL, 0);
  888. // Subset only if ulCig > gulMaxCig AND this is a tt font, not OTF,
  889. // Which we test by making sure the font has 'glyf' table. ('fylg',)
  890. if (bFontSubset = ((ulCig != GDI_ERROR) && (ulCig > gulMaxCig) && (cjGlyf != GDI_ERROR) && cjGlyf))
  891. {
  892. #ifdef DBGSUBSET
  893. DbgPrint("bDoFontChange cig= %lx\n", ulCig);
  894. #endif
  895. if (!(pBucket = pufihAddUFIEntry(pldc->ppSubUFIHash, &ufi, ulCig, FL_UFI_SUBSET, fl)) ||
  896. !(bRet = bAddGlyphIndices(hdc, pBucket, pwsz, c, flETO)))
  897. {
  898. bSubsetFail = TRUE;
  899. }
  900. }
  901. }
  902. else
  903. {
  904. if (!(bRet = bAddGlyphIndices(hdc, pBucket, pwsz, c, flETO)))
  905. {
  906. bSubsetFail = TRUE;
  907. }
  908. }
  909. if (bFontSubset && !bSubsetFail)
  910. {
  911. pldc->fl |= LDC_FONT_SUBSET;
  912. }
  913. else
  914. {
  915. bRet = bAddUFIandWriteSpool(hdc, &ufi, bFontSubset,fl);
  916. }
  917. }
  918. }
  919. return(bRet);
  920. }
  921. BOOL bRecordEmbedFonts(HDC hdc)
  922. {
  923. ULONG cEmbedFonts;
  924. UNIVERSAL_FONT_ID ufi;
  925. DESIGNVECTOR dv;
  926. ULONG cjDV = 0;
  927. ULONG ulBaseCheckSum;
  928. KERNEL_PVOID embFontID;
  929. FLONG fl = 0;
  930. PLDC pldc;
  931. if (!NtGdiGetEmbUFI(hdc, &ufi, &dv, &cjDV, &ulBaseCheckSum, &fl, &embFontID)) // get UFI
  932. return FALSE;
  933. if ((fl & (FL_UFI_PRIVATEFONT | FL_UFI_MEMORYFONT)) && embFontID )
  934. {
  935. if ((pldc = GET_PLDC(hdc)) == NULL)
  936. return FALSE;
  937. if (!pufihFindUFIEntry(pldc->ppUFIHash, &ufi, FALSE)) // new UFI
  938. {
  939. if(!pufihAddUFIEntry(pldc->ppUFIHash, &ufi, 0, 0, 0))
  940. return FALSE;
  941. else
  942. {
  943. if (!NtGdiChangeGhostFont(&embFontID, TRUE))
  944. {
  945. vRemoveUFIEntry(pldc->ppUFIHash, &ufi);
  946. return FALSE;
  947. }
  948. if (!WriteFontDataAsEMFComment(
  949. pldc,
  950. EMRI_EMBED_FONT_EXT,
  951. &embFontID,
  952. sizeof(VOID *),
  953. NULL,
  954. 0))
  955. {
  956. NtGdiChangeGhostFont(&embFontID, FALSE); // Can't record it into the spool file
  957. return FALSE;
  958. }
  959. // check to see whether it gets all of the embedded fonts
  960. cEmbedFonts = NtGdiGetEmbedFonts();
  961. if (cEmbedFonts != 0xFFFFFFFF &&
  962. (cEmbedFonts == 1 || cEmbedFonts == GetRecdEmbedFonts(pldc->ppUFIHash)))
  963. {
  964. pldc->fl &= ~LDC_EMBED_FONTS;
  965. }
  966. }
  967. }
  968. }
  969. return TRUE;
  970. }
  971. /**************************************************************************
  972. * BOOL RemoteRasterizerCompatible()
  973. *
  974. * This routine is used if we are about to print using remote EMF. If a
  975. * Type 1 font rasterizer has been installed on the client machine, we need
  976. * to query the remote machine to make sure that it has a rasterizer that is
  977. * compatable with the local version. If it isn't, we will return false
  978. * telling the caller that we should go RAW.
  979. *
  980. * History
  981. * 6-4-96 Gerrit van Wingerden [gerritv]
  982. * Wrote it.
  983. *
  984. ***************************************************************************/
  985. BOOL gbQueriedRasterizerVersion = FALSE;
  986. UNIVERSAL_FONT_ID gufiLocalType1Rasterizer;
  987. BOOL RemoteRasterizerCompatible(HANDLE hSpooler)
  988. {
  989. // if we haven't queried the rasterizer for the version yet do so first
  990. UNIVERSAL_FONT_ID ufi;
  991. LARGE_INTEGER TimeStamp;
  992. if(!gbQueriedRasterizerVersion)
  993. {
  994. // we have a contract with NtGdiQueryFonts (the routine called by the spooler
  995. // on the remote machine) that if a Type1 rasterizer is installed, the UFI
  996. // for it will always be first in the UFI list returned. So we can call
  997. // NtGdiQueryFonts
  998. if(!NtGdiQueryFonts(&gufiLocalType1Rasterizer, 1, &TimeStamp))
  999. {
  1000. WARNING("Unable to get local Type1 information\n");
  1001. return(FALSE);
  1002. }
  1003. gbQueriedRasterizerVersion = TRUE;
  1004. }
  1005. if(!UFI_TYPE1_RASTERIZER(&gufiLocalType1Rasterizer))
  1006. {
  1007. // no need to disable remote printing if there is no ATM driver installed
  1008. return(TRUE);
  1009. }
  1010. // Since we made it this far there must be a Type1 rasterizer on the local machine.
  1011. // Let's find out the version number of the Type1 rasterizer (if one is installed)
  1012. // on the print server.
  1013. if((*fpQueryRemoteFonts)(hSpooler, &ufi, 1 ) &&
  1014. (UFI_SAME_RASTERIZER_VERSION(&gufiLocalType1Rasterizer,&ufi)))
  1015. {
  1016. return(TRUE);
  1017. }
  1018. else
  1019. {
  1020. WARNING("Remote Type1 rasterizer missing or wrong version. Going RAW\n");
  1021. return(FALSE);
  1022. }
  1023. }
  1024. /****************************************************************
  1025. * VOID* AllocCallback(VOID* pvBuffer, size_t size)
  1026. *
  1027. * Passed to CreateFontPackage() to allocate or reallocate memory
  1028. *
  1029. * History
  1030. * Jan-07-97 Xudong Wu [tessiew]
  1031. * Wrote it.
  1032. *****************************************************************/
  1033. void* WINAPIV AllocCallback(void* pvBuffer, size_t size)
  1034. {
  1035. if (size == 0)
  1036. {
  1037. return (void*)NULL;
  1038. }
  1039. else
  1040. {
  1041. return ((void*)(LocalAlloc(LMEM_FIXED, size)));
  1042. }
  1043. }
  1044. /****************************************************************
  1045. * VOID* ReAllocCallback(VOID* pvBuffer, size_t size)
  1046. *
  1047. * Passed to CreateFontPackage() to allocate or reallocate memory
  1048. *
  1049. * History
  1050. * Jan-07-97 Xudong Wu [tessiew]
  1051. * Wrote it.
  1052. *****************************************************************/
  1053. void* WINAPIV ReAllocCallback(void* pvBuffer, size_t size)
  1054. {
  1055. if (size == 0)
  1056. {
  1057. return (void*)NULL;
  1058. }
  1059. else if (pvBuffer == (void*)NULL)
  1060. {
  1061. return ((void*)(LocalAlloc(LMEM_FIXED, size)));
  1062. }
  1063. else
  1064. {
  1065. return ((void*)(LocalReAlloc(pvBuffer, size, LMEM_MOVEABLE)));
  1066. }
  1067. }
  1068. /*******************************************************
  1069. * VOID* FreeCallback(VOID* pvBuffer)
  1070. *
  1071. * Passed to CreateFontPackage() to free memory
  1072. *
  1073. * History
  1074. * Jan-07-97 Xudong Wu [tessiew]
  1075. * Wrote it.
  1076. ********************************************************/
  1077. void WINAPIV FreeCallback(void* pvBuffer)
  1078. {
  1079. if (pvBuffer)
  1080. {
  1081. if (LocalFree(pvBuffer))
  1082. {
  1083. WARNING("FreeCallback(): Can't free the local memory\n");
  1084. }
  1085. }
  1086. }
  1087. /*****************************************************************************
  1088. * BOOL bInitSubsetterFunctionPointer(PVOID *ppfn)
  1089. *
  1090. * the name says it all
  1091. *
  1092. * History
  1093. * Dec-18-96 Xudong Wu [tessiew]
  1094. * Wrote it.
  1095. *
  1096. ******************************************************************************/
  1097. BOOL bInitSubsetterFunctionPointer(PVOID *ppfn)
  1098. {
  1099. BOOL bRet = TRUE;
  1100. if (*ppfn == NULL)
  1101. {
  1102. HANDLE hFontSubset = LoadLibraryW(L"fontsub.dll");
  1103. if (hFontSubset)
  1104. {
  1105. *ppfn = (PVOID)GetProcAddress(hFontSubset,
  1106. (ppfn == (PVOID *)&gfpCreateFontPackage) ?
  1107. "CreateFontPackage" : "MergeFontPackage");
  1108. if (*ppfn == NULL)
  1109. {
  1110. FreeLibrary(hFontSubset);
  1111. WARNING("GetProcAddress(fontsub.dll) failed\n");
  1112. bRet = FALSE;
  1113. }
  1114. }
  1115. else
  1116. {
  1117. WARNING("LoadLibrary(fontsub.dll) failed\n");
  1118. bRet = FALSE;
  1119. }
  1120. }
  1121. return bRet;
  1122. }
  1123. /*****************************************************************************
  1124. * BOOL bDoFontSubset
  1125. *
  1126. * Called everytime we need to subset a font. This routine converts the bit
  1127. * fields of pjMemory/u.ssi.pjDelta in pBucket into a glyph index list and call the
  1128. * font subsetting functions to generate subset/delta font.
  1129. *
  1130. * History
  1131. * Dec-18-96 Xudong Wu [tessiew]
  1132. * Wrote it.
  1133. *
  1134. ******************************************************************************/
  1135. BOOL bDoFontSubset(PUFIHASH pBucket,
  1136. PUCHAR* ppuchDestBuff, // output: buffer will contain the subsetted image or delta
  1137. ULONG* pulDestSize, // output: size of the buffer above, may be more than needed
  1138. ULONG* pulBytesWritten // output: bytes written into the buffer above
  1139. )
  1140. {
  1141. BOOL bDelta = pBucket->fs1 & FLUFI_DELTA;
  1142. USHORT *pusSubsetKeepList = NULL;
  1143. ULONG cSubset; // number of glyphs to be subsetted
  1144. BOOL bRet = FALSE;
  1145. #ifdef DBGSUBSET
  1146. FILETIME fileTimeStart, fileTimeEnd;
  1147. if (gflSubset & FL_SS_SUBSETTIME)
  1148. {
  1149. GetSystemTimeAsFileTime(&fileTimeStart);
  1150. }
  1151. #endif
  1152. ENTERCRITICALSECTION(&semLocal);
  1153. bRet = bInitSubsetterFunctionPointer((PVOID *)&gfpCreateFontPackage);
  1154. LEAVECRITICALSECTION(&semLocal);
  1155. if (!bRet)
  1156. return FALSE;
  1157. bRet = FALSE;
  1158. cSubset = bDelta ? pBucket->u.ssi.cDeltaGlyphs : pBucket->u.ssi.cGlyphsSoFar;
  1159. #ifdef DBGSUBSET
  1160. if (gflSubset & FL_SS_KEEPLIST)
  1161. {
  1162. DbgPrint("\t%ld", cSubset);
  1163. }
  1164. #endif // DBGSUBSET
  1165. pusSubsetKeepList = (USHORT*)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(USHORT) * cSubset);
  1166. if (pusSubsetKeepList == NULL)
  1167. {
  1168. WARNING("bDoFontSubset unable to allocate memory for pusSubsetKeepList\n");
  1169. return FALSE;
  1170. }
  1171. // transfer appropriate bit field into glyph indices
  1172. if (bGetDistGlyphIndices(pBucket, pusSubsetKeepList, bDelta))
  1173. {
  1174. WCHAR pwszPathname[MAX_PATH * 3];
  1175. ULONG cwcPathname, cNumFiles;
  1176. BOOL bMemFont = FALSE, bMapOK = TRUE;
  1177. ULONG cjView;
  1178. PVOID pvView = NULL;
  1179. BOOL bTTC = FALSE;
  1180. ULONG iTTC = 0;
  1181. if (NtGdiGetUFIPathname(&pBucket->ufi,
  1182. &cwcPathname,
  1183. pwszPathname,
  1184. &cNumFiles,
  1185. pBucket->fs2,
  1186. &bMemFont,
  1187. &cjView,
  1188. NULL,
  1189. &bTTC,
  1190. &iTTC))
  1191. {
  1192. PVOID pvSrcBuff;
  1193. ULONG ulSrcSize;
  1194. CLIENT_SIDE_FILEVIEW fvw;
  1195. if (!bMemFont)
  1196. {
  1197. ASSERTGDI(cNumFiles == 1, "bDoFontSubset: cNumFiles != 1\n");
  1198. if (bMapOK = bMapFileUNICODEClideSide(pwszPathname, &fvw, TRUE))
  1199. {
  1200. pvSrcBuff = (PVOID)fvw.pvView;
  1201. ulSrcSize = fvw.cjView;
  1202. }
  1203. }
  1204. else
  1205. {
  1206. pvView = LocalAlloc(LMEM_FIXED, cjView);
  1207. if (pvView)
  1208. {
  1209. if (NtGdiGetUFIPathname(&pBucket->ufi,NULL,NULL,NULL,
  1210. pBucket->fs2,NULL,NULL,pvView,NULL,NULL))
  1211. {
  1212. bMapOK = TRUE;
  1213. pvSrcBuff = (PVOID)pvView;
  1214. ulSrcSize = cjView;
  1215. }
  1216. else
  1217. {
  1218. LocalFree(pvView);
  1219. }
  1220. }
  1221. }
  1222. if (bMapOK)
  1223. {
  1224. // font subsetting
  1225. ASSERTGDI(gfpCreateFontPackage != NULL, "fonsub.dll is not load\n");
  1226. if ((*gfpCreateFontPackage)((PUCHAR)pvSrcBuff,
  1227. ulSrcSize,
  1228. ppuchDestBuff,
  1229. pulDestSize,
  1230. pulBytesWritten,
  1231. (USHORT)(bTTC ? 0x000d : 0x0009), // TTFCFP_FLAGS_SUBSET | TTFCFP_FLAGS_GLYPHLIST
  1232. (USHORT)iTTC, // usTTCIndex
  1233. (USHORT)(bDelta ? 2 : 1), // usSubsetFormat
  1234. 0, // usSubsetLanguage
  1235. 3, // usSubsetPlatform TTFCFP_MS_PLATFORMID
  1236. 0xFFFF, // usSubsetEncoding TTFCFP_DONT_CARE
  1237. pusSubsetKeepList,
  1238. (USHORT)cSubset,
  1239. (CFP_ALLOCPROC)AllocCallback,
  1240. (CFP_REALLOCPROC)ReAllocCallback,
  1241. (CFP_FREEPROC)FreeCallback,
  1242. NULL) != 0)
  1243. {
  1244. WARNING("bDofontSubset failed on gfpCreateFontPackage\n");
  1245. }
  1246. else
  1247. {
  1248. if (bDelta) // clean up the u.ssi.pjDelta and u.ssi.cDeltaGlyphs
  1249. {
  1250. LocalFree(pBucket->u.ssi.pjDelta);
  1251. pBucket->u.ssi.pjDelta = NULL;
  1252. pBucket->u.ssi.cDeltaGlyphs = 0;
  1253. }
  1254. else // set fs1 to prepare for the next page.
  1255. {
  1256. pBucket->fs1 = FLUFI_DELTA;
  1257. }
  1258. bRet = TRUE;
  1259. }
  1260. if (bMemFont)
  1261. {
  1262. LocalFree(pvView);
  1263. }
  1264. else
  1265. {
  1266. vUnmapFileClideSide(&fvw);
  1267. }
  1268. }
  1269. else
  1270. {
  1271. WARNING("bDoFontSubset: failed on bMapFileUNICODEClideSide()\n");
  1272. }
  1273. }
  1274. else
  1275. {
  1276. WARNING("bDoFontSubset: failed on NtGdiGetUFIPathname()\n");
  1277. }
  1278. }
  1279. else
  1280. {
  1281. WARNING("bDoFontSubset: failed on bGetDistGlyphIndices()\n");
  1282. }
  1283. LocalFree(pusSubsetKeepList);
  1284. //Timing code
  1285. #ifdef DBGSUBSET
  1286. if (gflSubset & FL_SS_SUBSETTIME)
  1287. {
  1288. GetSystemTimeAsFileTime(&fileTimeEnd);
  1289. DbgPrint("\t%ld",
  1290. (fileTimeEnd.dwLowDateTime - fileTimeStart.dwLowDateTime) / 10000);
  1291. }
  1292. #endif
  1293. return bRet;
  1294. }
  1295. /************************************************************************************
  1296. * BOOL WriteSubFontToSpoolFile(HANDLE, PUCHAR, ULONG, UNIVERSAL_FONT_ID, BOOL)
  1297. *
  1298. * Write subsetted font or a delta in the print spool file.
  1299. *
  1300. * History
  1301. * Jan-09-97 Xudong Wu [tessiew]
  1302. * Wrote it.
  1303. *
  1304. *************************************************************************************/
  1305. BOOL WriteSubFontToSpoolFile(
  1306. PLDC pldc,
  1307. PUCHAR puchBuff, // image pointer
  1308. ULONG ulBytesWritten, // bytes to be written to spool file
  1309. UNIVERSAL_FONT_ID *pufi, // ufi of the original font file
  1310. BOOL bDelta // delta or first page
  1311. )
  1312. {
  1313. BOOL bRet = FALSE;
  1314. #ifdef DBGSUBSET
  1315. FILETIME fileTimeStart, fileTimeEnd;
  1316. if (gflSubset & FL_SS_SPOOLTIME)
  1317. {
  1318. GetSystemTimeAsFileTime(&fileTimeStart);
  1319. }
  1320. #endif
  1321. if (ulBytesWritten)
  1322. {
  1323. DWORD ulID = bDelta ? EMRI_DELTA_FONT : EMRI_SUBSET_FONT;
  1324. #ifdef DBGSUBSET
  1325. if (gflSubset & FL_SS_BUFFSIZE)
  1326. {
  1327. DbgPrint("\t%ld\n", ulBytesWritten);
  1328. }
  1329. #endif // DBGSUBSET
  1330. if (WriteFontDataAsEMFComment(
  1331. pldc,
  1332. ulID,
  1333. pufi,
  1334. sizeof(UNIVERSAL_FONT_ID),
  1335. puchBuff,
  1336. ulBytesWritten))
  1337. {
  1338. bRet = TRUE;
  1339. }
  1340. else
  1341. {
  1342. WARNING("WriteSubFontToSpooler: error writing to printer\n");
  1343. }
  1344. LocalFree(puchBuff);
  1345. }
  1346. else
  1347. {
  1348. WARNING("WriteSubFontToSpooler: input ulBytesWritten == 0\n");
  1349. }
  1350. //timing code
  1351. #ifdef DBGSUBSET
  1352. if (gflSubset & FL_SS_SPOOLTIME)
  1353. {
  1354. GetSystemTimeAsFileTime(&fileTimeEnd);
  1355. DbgPrint("\t%ld", (fileTimeEnd.dwLowDateTime - fileTimeStart.dwLowDateTime) / 10000);
  1356. }
  1357. #endif
  1358. return(bRet);
  1359. }
  1360. /************************************************************************************
  1361. * BOOL bMergeSubsetFont(HDC, PVOID, ULONG, PVOID*, ULONG*, BOOL, UNIVERSAL_FONT_ID*)
  1362. *
  1363. * Merge the font delta into a working font containing pages up to this one.
  1364. * This routine is only called on print server
  1365. *
  1366. * History
  1367. * Jan-12-97 Xudong Wu [tessiew]
  1368. * Wrote it.
  1369. *
  1370. *************************************************************************************/
  1371. BOOL bMergeSubsetFont(
  1372. HDC hdc,
  1373. PVOID pvBuf,
  1374. ULONG ulBuf,
  1375. PVOID* ppvOutBuf,
  1376. ULONG* pulOutSize,
  1377. BOOL bDelta,
  1378. UNIVERSAL_FONT_ID *pufi)
  1379. {
  1380. PLDC pldc;
  1381. PBYTE pjBase;
  1382. ULONG ulMergeBuf, ulBytesWritten, ulBaseFontSize = 0;
  1383. PVOID pvMergeBuf, pvBaseFont = NULL;
  1384. UFIHASH *pBucket = NULL;
  1385. BOOL bRet = FALSE;
  1386. #define SZDLHEADER ((sizeof(DOWNLOADFONTHEADER) + 7)&~7)
  1387. ENTERCRITICALSECTION(&semLocal);
  1388. bRet = bInitSubsetterFunctionPointer((PVOID *)&gfpMergeFontPackage);
  1389. LEAVECRITICALSECTION(&semLocal);
  1390. if (!bRet)
  1391. return FALSE;
  1392. // get the orignal UFI
  1393. *pufi = *(PUNIVERSAL_FONT_ID) pvBuf;
  1394. pjBase = (PBYTE)pvBuf + sizeof(UNIVERSAL_FONT_ID);
  1395. ulBuf -= sizeof(UNIVERSAL_FONT_ID);
  1396. pldc = GET_PLDC(hdc);
  1397. if (pldc == NULL)
  1398. {
  1399. WARNING("bMergeSubsetFont: unable to retrieve pldc\n");
  1400. return FALSE;
  1401. }
  1402. ASSERTGDI(!pldc->ppUFIHash, "printer server side ppUFIHash != NULL\n");
  1403. ASSERTGDI(!pldc->ppDVUFIHash,"printer server side ppDVUFIHash != NULL\n");
  1404. // init the hash table if needed
  1405. if (pldc->ppSubUFIHash == NULL)
  1406. {
  1407. pldc->ppSubUFIHash = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(PUFIHASH) * UFI_HASH_SIZE);
  1408. if(pldc->ppSubUFIHash == NULL)
  1409. {
  1410. WARNING("bMergeSubsetFont: unable to allocate UFI hash table2\n");
  1411. return FALSE;
  1412. }
  1413. }
  1414. // for delta merge, get the font image from pBucket->u.mvw.pjMem
  1415. if (bDelta)
  1416. {
  1417. pBucket = pufihFindUFIEntry(pldc->ppSubUFIHash, pufi, TRUE);
  1418. if (!pBucket)
  1419. return FALSE;
  1420. // We need to exclude the DOWNLOADFONTHEADER
  1421. // information from the pBucket->u.mvw.pjMem
  1422. pvBaseFont = pBucket->u.mvw.pjMem + SZDLHEADER;
  1423. ulBaseFontSize = pBucket->u.mvw.cjMem - SZDLHEADER;
  1424. }
  1425. if ((*gfpMergeFontPackage)((UCHAR*)pvBaseFont, ulBaseFontSize,
  1426. (PUCHAR)pjBase, ulBuf,
  1427. (PUCHAR*)&pvMergeBuf, &ulMergeBuf, &ulBytesWritten,
  1428. (USHORT) (bDelta ? 2 : 1), //usMode 1=generate font; 2=delta merge
  1429. (CFP_ALLOCPROC)AllocCallback,
  1430. (CFP_REALLOCPROC)ReAllocCallback,
  1431. (CFP_FREEPROC)FreeCallback,
  1432. NULL) != 0)
  1433. {
  1434. WARNING("MergeSubsetFont failed on funsub!MergeFontPackage\n");
  1435. }
  1436. else
  1437. {
  1438. // In order to use FreeFileView when we delete the font after printing,
  1439. // we need a fake DOWNLOADFONTHEADER
  1440. // before we pass the buffer into kenerl for NtGdiAddRemoteFontToDC call.
  1441. *pulOutSize = SZDLHEADER + ulBytesWritten;
  1442. *ppvOutBuf = (PVOID*)LocalAlloc(LMEM_FIXED, *pulOutSize);
  1443. if (*ppvOutBuf == NULL)
  1444. {
  1445. WARNING("bMergeSubsetFont failed to alloc memory\n");
  1446. }
  1447. else
  1448. {
  1449. DOWNLOADFONTHEADER *pdfh;
  1450. pdfh = (DOWNLOADFONTHEADER*)*ppvOutBuf;
  1451. pdfh->Type1ID = 0;
  1452. pdfh->NumFiles = 1;
  1453. pdfh->FileOffsets[0] = ulBytesWritten;
  1454. RtlCopyMemory((PVOID)((PBYTE)*ppvOutBuf + SZDLHEADER), pvMergeBuf, ulBytesWritten);
  1455. if (bWriteUFItoDC(pldc->ppSubUFIHash, pufi, pBucket, *ppvOutBuf, *pulOutSize))
  1456. {
  1457. bRet = TRUE;
  1458. }
  1459. else
  1460. {
  1461. LocalFree(*ppvOutBuf);
  1462. WARNING("bMergeSubsetFont failed on bWriteUFItoDC\n");
  1463. }
  1464. }
  1465. // pvMergeBuf comes from the merge routine which uses LMEM_MOVEABLE
  1466. // for memory allocation Needs to be freed by the handle.
  1467. LocalFree(pvMergeBuf);
  1468. }
  1469. return bRet;
  1470. }