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.

1221 lines
30 KiB

  1. /*++
  2. Copyright (c) 1996 - 1999 Microsoft Corporation
  3. Module Name:
  4. dlutils.c
  5. Abstract:
  6. Download Modules utilts functions.
  7. Environment:
  8. Windows NT Unidrv driver
  9. Revision History:
  10. 06/02/97 -ganeshp-
  11. Created
  12. --*/
  13. #include "font.h"
  14. #define HASH(num,tablesize) (num % tablesize)
  15. PDLGLYPH
  16. PDLGNewGlyph (
  17. DL_MAP *pDL
  18. )
  19. /*++
  20. Routine Description:
  21. Arguments:
  22. pDL Pointer to DownloadMap for the downloaded font.
  23. Return Value:
  24. Pointer to the new DLGLYPH for success and NULL for failure.
  25. Note:
  26. 06/02/97 -ganeshp-
  27. Created it.
  28. --*/
  29. {
  30. GLYPHTAB *pGlyphTab;
  31. PDLGLYPH pDLGlyph = NULL;
  32. if (pGlyphTab = pDL->GlyphTab.pGLTNext)
  33. {
  34. //
  35. //Go to the end of the List.
  36. //
  37. while (pGlyphTab && !pGlyphTab->cEntries)
  38. pGlyphTab = pGlyphTab->pGLTNext;
  39. }
  40. //
  41. //Allocate a new Chunk, if we need a new one.
  42. //
  43. if (!pGlyphTab)
  44. {
  45. INT cEntries = pDL->cHashTableEntries / 2; // Half the size of hash table.
  46. if (pGlyphTab = (GLYPHTAB *)MemAllocZ( sizeof(GLYPHTAB) +
  47. cEntries * sizeof(DLGLYPH) ))
  48. {
  49. PVOID pTemp;
  50. //
  51. //Skip the header.
  52. //
  53. pGlyphTab->pGlyph = (PDLGLYPH)(pGlyphTab + 1);
  54. pGlyphTab->cEntries = cEntries;
  55. //
  56. //Add in the begining of the list.
  57. //
  58. pTemp = pDL->GlyphTab.pGLTNext;
  59. pDL->GlyphTab.pGLTNext = pGlyphTab;
  60. pGlyphTab->pGLTNext = pTemp;
  61. }
  62. else
  63. ERR(("Unifont!PDLGNewGlyph:Can't Allocate the Glyph Chunk.\n"));
  64. }
  65. //
  66. //If the chunk has available entries, return the new pointer.
  67. //
  68. if (pGlyphTab && pGlyphTab->cEntries)
  69. {
  70. pDLGlyph = pGlyphTab->pGlyph;
  71. pGlyphTab->pGlyph++;
  72. pGlyphTab->cEntries--;
  73. }
  74. //
  75. // Initialize the hTTGlyphs to Invalid.
  76. //
  77. if (NULL != pDLGlyph)
  78. pDLGlyph->hTTGlyph = HGLYPH_INVALID;
  79. return pDLGlyph;
  80. }
  81. PDLGLYPH
  82. PDLGHashGlyph (
  83. DL_MAP *pDL,
  84. HGLYPH hTTGlyph
  85. )
  86. /*++
  87. Routine Description:
  88. This routine searches the Hash table for a given Glyph. If the
  89. Glyph is not found in the Has table it creats an entry and add
  90. that into the list. The new entry is not filled.
  91. Arguments:
  92. pDL Pointer to DownloadMap Structure for the downloaded font.
  93. hTTGlyph True Type Glyph Handle.
  94. Return Value:
  95. Pointer to the DLGLYPH for success and NULL for failure.
  96. Note:
  97. 06/02/97 -ganeshp-
  98. Created it.
  99. --*/
  100. {
  101. INT iHashedEntry;
  102. BOOL bFound;
  103. PDLGLYPH pDLHashedGlyph = NULL,
  104. pDLG = NULL;
  105. if (pDL->cHashTableEntries)
  106. {
  107. //
  108. // Hashing is done on TT handle.
  109. //
  110. iHashedEntry = HASH(hTTGlyph,pDL->cHashTableEntries);
  111. pDLG = pDLHashedGlyph = pDL->GlyphTab.pGlyph + iHashedEntry;
  112. //
  113. //Proceed if the pointer is valid
  114. //
  115. if (pDLHashedGlyph)
  116. {
  117. //
  118. // Check if this is the Glyph we are interested in.
  119. // We should test if this glyph is new glyph or not.
  120. //
  121. if (!GLYPHDOWNLOADED(pDLHashedGlyph) )
  122. {
  123. //
  124. // If this is a new glyph which is not downloaded then return
  125. // this pointer.
  126. //
  127. bFound = TRUE;
  128. }
  129. else if (pDLHashedGlyph->hTTGlyph != hTTGlyph)
  130. {
  131. pDLG = pDLHashedGlyph->pNext;
  132. bFound = FALSE;
  133. //
  134. // Not the same Glyph, It's a Collision. Search the Linked list.
  135. //
  136. while (pDLG)
  137. {
  138. if (pDLG->hTTGlyph == hTTGlyph)
  139. {
  140. bFound = TRUE;
  141. break;
  142. }
  143. else
  144. pDLG = pDLG->pNext;
  145. }
  146. //
  147. // If the Glyph is found in the linked list, return the pointer;
  148. // else create a new Glyph and add at the linked list. We add in
  149. // the begining.
  150. //
  151. if (!bFound)
  152. {
  153. if ( pDLG = PDLGNewGlyph(pDL) )
  154. {
  155. PDLGLYPH pTemp;
  156. //
  157. // Don't Fill in the Glyph. All the fields are set
  158. // by the DownLoad Glyph function.
  159. //
  160. //
  161. // Add the New Glyph at the begining of the list.
  162. //
  163. pTemp = pDLHashedGlyph->pNext;
  164. pDLHashedGlyph->pNext = pDLG;
  165. pDLG->pNext = pTemp;
  166. }
  167. else
  168. {
  169. pDLG = NULL;
  170. ERR(("Unifont!PDLGHashGlyph:Can't Create the Glyph.\n"));
  171. }
  172. }
  173. }
  174. }
  175. }
  176. ASSERTMSG(pDLG,("Unifont!PDLGHashGlyph:ERROR Null Hashed Glyph.\n"));
  177. return pDLG;
  178. }
  179. DL_MAP_LIST *
  180. PNewDLMapList()
  181. /*++
  182. Routine Description:
  183. Allocate and initialise a new DL_MAP_LIST structure. These
  184. are placed in a linked list (by our caller).
  185. Arguments: None
  186. Return Value:
  187. The address of the structure, or NULL on failure.
  188. Note:
  189. 3/5/1997 -ganeshp-
  190. Created it.
  191. --*/
  192. {
  193. DL_MAP_LIST *pdml;
  194. /*
  195. * Little to do: if we can allocate the storage, then set it to 0.
  196. */
  197. if( pdml = (DL_MAP_LIST *)MemAllocZ(sizeof( DL_MAP_LIST ) ) )
  198. return pdml;
  199. else
  200. return NULL;
  201. }
  202. DL_MAP *
  203. PNewDLMap (
  204. PFONTPDEV pFontPDev,
  205. INT *iFontIndex
  206. )
  207. /*++
  208. Routine Description:
  209. This routine return a new DL_MAP pointer.
  210. Arguments:
  211. pFontPDev Font Modules's PDEV.
  212. iFontIndex Index of the new DL_MAP. The index is used to
  213. identify the downloaded font.Filled by this function.
  214. Zero is first index.
  215. Return Value:
  216. Pointer to DL_MAP for success and NULL for failure
  217. Note:
  218. 06/02/97 -ganeshp-
  219. Created it.
  220. --*/
  221. {
  222. DL_MAP_LIST *pdml; // The linked list of font information
  223. DL_MAP *pdm; // Individual map element
  224. pdml = pFontPDev->pvDLMap;
  225. *iFontIndex = 0;
  226. pdm = NULL;
  227. //
  228. // If no DL List, create one.
  229. //
  230. if( pdml == NULL )
  231. {
  232. //
  233. // None there, so create an initial one.
  234. //
  235. if( pdml = PNewDLMapList() )
  236. {
  237. pFontPDev->pvDLMap = pdml;
  238. }
  239. else
  240. {
  241. ERR(("Unifont!PNewDLMap(1):Can't Allocate the DL_MAP_LIST Chunk.\n"));
  242. }
  243. }
  244. //
  245. // The list should be not null. else return NULL.
  246. //
  247. if (pdml)
  248. {
  249. for( pdml = pFontPDev->pvDLMap; pdml->pDMLNext; pdml = pdml->pDMLNext )
  250. {
  251. //
  252. // While looking for the end, also count the number we pass.
  253. //
  254. *iFontIndex += pdml->cEntries;
  255. }
  256. if( pdml->cEntries >= DL_MAP_CHUNK )
  257. {
  258. if( !(pdml->pDMLNext = PNewDLMapList()) )
  259. {
  260. ERR(("Unifont!PNewDLMap(2):Can't Allocate the DL_MAP_LIST Chunk.\n"));
  261. return NULL;
  262. }
  263. //
  264. // The new current model.
  265. //
  266. pdml = pdml->pDMLNext;
  267. //
  268. // Add in the full one.
  269. //
  270. *iFontIndex += DL_MAP_CHUNK;
  271. }
  272. pdm = &pdml->adlm[ pdml->cEntries ];
  273. //
  274. // Increment the iFontIndex first as the it is 0 based.
  275. // For 1st entry the index will be 0.
  276. //
  277. *iFontIndex += pdml->cEntries;
  278. pdml->cEntries++;
  279. }
  280. return pdm;
  281. }
  282. VOID
  283. VFreeDLMAP (
  284. DL_MAP *pdm
  285. )
  286. /*++
  287. Routine Description:
  288. This function fress DL_MAP structure contents - but NOT the map.
  289. Arguments:
  290. pdm Pointer to DL_MAP structure whose contents has to be freed.
  291. Return Value:
  292. Nothing.
  293. Note:
  294. 01/15/97 -ganeshp-
  295. Created it.
  296. --*/
  297. {
  298. FONTMAP *pFM;
  299. PVOID pTemp;
  300. GLYPHTAB *pGT;
  301. ULONG_PTR iTTUniq;
  302. /*
  303. * Simply free the storage contained within the FONTMAP structure.
  304. */
  305. if (pdm )
  306. {
  307. if (pFM = pdm->pfm)
  308. {
  309. //
  310. // Try to Free what we allocated.
  311. //
  312. MEMFREEANDRESET((LPSTR)pFM->pIFIMet );
  313. if (pFM->pfnFreePFM)
  314. {
  315. //
  316. // Free The pfm by calling the helper function.
  317. //
  318. pFM->pfnFreePFM(pFM);
  319. }
  320. else
  321. {
  322. ERR(("UniFont!VFreeDLMAP: NUll pfnFreePFM function pointer, Can't free pFM\n"));
  323. //
  324. // Try to Free what we know about.
  325. //
  326. MemFree( (LPSTR)pFM);
  327. }
  328. }
  329. //
  330. // Free the Glyph Table.
  331. //
  332. pGT = pdm->GlyphTab.pGLTNext;
  333. while (pGT)
  334. {
  335. pTemp = pGT->pGLTNext;
  336. MemFree((LPSTR)pGT);
  337. pGT = pTemp;
  338. }
  339. //
  340. // Now free the base hash table.
  341. //
  342. MEMFREEANDRESET( (LPSTR)pdm->GlyphTab.pGlyph );
  343. //
  344. // Zero the memory and make cGlyphs to -1 so that it's not used.
  345. // Save the iTTUniq for future reference.
  346. //
  347. iTTUniq = pdm->iTTUniq;
  348. ZeroMemory(pdm, sizeof(DL_MAP));
  349. pdm->iTTUniq = iTTUniq;
  350. pdm->cGlyphs = -1;
  351. }
  352. return;
  353. }
  354. VOID
  355. VFreeDL(
  356. PDEV *pPDev
  357. )
  358. /*++
  359. Routine Description:
  360. Function to free up all the downloaded information. Basically
  361. work through the list, calling VFreeDLMAP for each entry.
  362. Arguments:
  363. pPDev Access to our data.
  364. Return Value:
  365. Nothing.
  366. Note:
  367. 01/15/97 -ganeshp-
  368. Created it.
  369. --*/
  370. {
  371. DL_MAP_LIST *pdml; /* The linked list of font information */
  372. PFONTPDEV pFontPDev = PFDV; /* It's used a few times */
  373. if( pdml = pFontPDev->pvDLMap )
  374. {
  375. /*
  376. * There is downloaded data, so off we go.
  377. */
  378. INT iI;
  379. /*
  380. * Scan through each of the arrays of header data.
  381. */
  382. while( pdml )
  383. {
  384. DL_MAP_LIST *pdmlTmp = NULL;
  385. /*
  386. * Scan through each entry in the array of header data.
  387. */
  388. for( iI = 0; iI < pdml->cEntries; ++iI )
  389. VFreeDLMAP( &pdml->adlm[ iI ] );
  390. pdmlTmp = pdml;
  391. //
  392. // Remember the next one
  393. //
  394. pdml = pdml->pDMLNext;
  395. MemFree((LPSTR)pdmlTmp);
  396. }
  397. }
  398. //
  399. // Reset Download specific variables.
  400. //
  401. pFontPDev->pvDLMap = NULL;
  402. pFontPDev->iNextSFIndex = pFontPDev->iFirstSFIndex;
  403. pFontPDev->iUsedSoftFonts = 0;
  404. pFontPDev->ctl.iFont = INVALID_FONT;
  405. pFontPDev->ctl.iSoftFont = -1;
  406. return;
  407. }
  408. DL_MAP *
  409. PGetDLMapFromIdx (
  410. PFONTPDEV pFontPDev,
  411. INT iFontIndex
  412. )
  413. /*++
  414. Routine Description:
  415. This routine return a DL_MAP pointer, given it's index..
  416. Arguments:
  417. pFontPDev Font PDEV.
  418. iFontIndex Index of the DL_MAP. The index is used to
  419. identify the downloaded font. Zero is first index.
  420. Return Value:
  421. Pointer to DL_MAP for success and NULL for failure
  422. Note:
  423. 06/02/97 -ganeshp-
  424. Created it.
  425. --*/
  426. {
  427. DL_MAP_LIST *pdml; // The linked list of font information
  428. DL_MAP *pdm; // Individual map element
  429. pdml = pFontPDev->pvDLMap;
  430. pdm = NULL;
  431. //
  432. // If the index is negative that means this is a new font. So we should
  433. // search sequentially.
  434. //
  435. if (iFontIndex < 0)
  436. return NULL;
  437. //
  438. // The list should be not null. else return NULL.
  439. //
  440. while( pdml )
  441. {
  442. //
  443. // Is this chunk the one containing the entry?
  444. //
  445. if( iFontIndex >= pdml->cEntries )
  446. {
  447. //
  448. // Not this one, so onto the next.
  449. //
  450. iFontIndex -= pdml->cEntries;
  451. pdml = pdml->pDMLNext;
  452. }
  453. else
  454. {
  455. //
  456. // We got it!
  457. //
  458. pdm = &pdml->adlm[ iFontIndex ];
  459. break;
  460. }
  461. }
  462. return pdm;
  463. }
  464. BOOL
  465. BSameDLFont (
  466. PFONTPDEV pFontPDev,
  467. FONTOBJ *pfo,
  468. DL_MAP *pdm
  469. )
  470. /*++
  471. Routine Description:
  472. This routine finds out if input DL_MAP represents the FONTOBJ or not.
  473. Arguments:
  474. pFontPDev Font Modules's PDEV.
  475. pfo FontObj.
  476. pdm Individual download map element.
  477. Return Value:
  478. TRUE if DL_MAP represents FONTOBJ else FALSE.
  479. Note:
  480. 06/02/97 -ganeshp-
  481. Created it.
  482. --*/
  483. {
  484. //
  485. // The checks are different for download TT as outline and download
  486. // as TT OutLine. For Download a Bitmap we check iUniq and for download
  487. // as TT Outline we have to use iTTUniq. If the same printer can support
  488. // both format we may download the font as any one of the format.
  489. //
  490. FONTMAP *pfm = pdm->pfm;
  491. if (pfm)
  492. {
  493. if (pfm->dwFontType == FMTYPE_TTBITMAP)
  494. {
  495. return ((pdm->iUniq == pfo->iUniq) && (pdm->iTTUniq == pfo->iTTUniq));
  496. }
  497. else if (pfm->dwFontType == FMTYPE_TTOUTLINE)
  498. {
  499. //
  500. // The truetype font is equivalent if the iTTUniq is the same *and*
  501. // the font-type field matches.
  502. //
  503. PFONTMAP_TTO pFMTTO = (PFONTMAP_TTO) pdm->pfm->pSubFM;
  504. return (pdm->iTTUniq == pfo->iTTUniq) &&
  505. (pFMTTO->flFontType == pfo->flFontType);
  506. }
  507. else
  508. if (pfm->dwFontType == FMTYPE_TTOEM)
  509. {
  510. PFONTMAP_TTOEM pTTOEM = pfm->pSubFM;
  511. ASSERT(pTTOEM);
  512. //
  513. // TrueType Outline for OEM
  514. //
  515. if (pTTOEM->dwFlags & UFOFLAG_TTDOWNLOAD_TTOUTLINE)
  516. {
  517. return (pdm->iTTUniq == pfo->iTTUniq) &&
  518. (pTTOEM->flFontType == pfo->flFontType);
  519. }
  520. else
  521. //
  522. // Bitmap for OEM
  523. //
  524. if (pTTOEM->dwFlags & UFOFLAG_TTDOWNLOAD_BITMAP)
  525. {
  526. return ((pdm->iUniq == pfo->iUniq) &&
  527. (pdm->iTTUniq == pfo->iTTUniq));
  528. }
  529. }
  530. }
  531. return FALSE;
  532. }
  533. DL_MAP *
  534. PGetDLMap (
  535. PFONTPDEV pFontPDev,
  536. FONTOBJ *pfo
  537. )
  538. /*++
  539. Routine Description:
  540. This routine searches a FontObj in DL_MAP_LIST.If the FONTOBJ is found
  541. (Means this font has been downloaded), then this function return the
  542. DL_MAP pointer. If FONTOBJ can't be found (New font which is not
  543. downloaded), a new DL_MAP * is returned. In Case of error we return
  544. NULL. In that case we shouldn't download. A Bad DL_MAP is marked by
  545. having cGlyphs value to -1. This function will also set pvConsumer field
  546. of pfo, if a new DL_MAP is returned.
  547. Arguments:
  548. pFontPDev Font Modules's PDEV.
  549. pfo FontObj.
  550. Return Value:
  551. Pointer to DL_MAP for success and NULL if no match.
  552. Note:
  553. 06/02/97 -ganeshp-
  554. Created it.
  555. --*/
  556. {
  557. DL_MAP *pdm; // Individual download map element.
  558. BOOL bFound; // The font is found or not in the list.
  559. INT iFontIndex; // Download Font Index in DL_MAP List.
  560. //
  561. // All we have to do is look into the DL_MAP list and find a DL_MAP with
  562. // same signature. For optimization purposes we tag the pvConsumer field
  563. // with the FontIndex, which is index into the list. For example for first
  564. // downloaded font pvConsumer is set to 1. As pvConsumer field is not
  565. // cached for each DC, we will use this field with caution. So if pvConsumer
  566. // is > 0, then we get the DL_MAP using pvConsumer and then check iUniq and
  567. // iTTUniq. We only use the DL_MAP if these fields also match. Else we do
  568. // an exausitive linear search in DL_MAP list. This approach will optimize
  569. // for normal printing, because most of the time only one job is getting
  570. // printed.
  571. //
  572. bFound = FALSE;
  573. if( iFontIndex = PtrToLong(pfo->pvConsumer) )
  574. {
  575. /*
  576. * As we control the pvConsumer field, we have the choice
  577. * of what to put in there. SO, we decide as follows:
  578. * > 0 - index into our data structures for good DL_MAP.
  579. * 0 - virgin data, so look to see what to do.
  580. * < 0 - Index into our data str for Bad FONT. NO download.
  581. * In this case cGlyphs field is -1.
  582. */
  583. if( iFontIndex < 0 )
  584. {
  585. //
  586. // This seems like a bad font. In that case verify.
  587. // Make the fontIndex +ve and 0 Based.
  588. //
  589. iFontIndex = (-iFontIndex);
  590. --iFontIndex;
  591. }
  592. else
  593. {
  594. //
  595. // pvConsumer is 1 based.
  596. //
  597. --iFontIndex;
  598. }
  599. if ( pdm = PGetDLMapFromIdx (pFontPDev, iFontIndex))
  600. {
  601. //
  602. // Do not process this one, if we had encountered problem in past.
  603. // Make sure that the we are dealing with same TT font.
  604. //
  605. if (pdm->cGlyphs == -1 && (pdm->iTTUniq == pfo->iTTUniq))
  606. {
  607. //
  608. // Set the pvConsumer to a -ve index. make it 1 based first.
  609. //
  610. pfo->pvConsumer = (PLONG_PTR)IntToPtr((-(iFontIndex +1)));
  611. return NULL;
  612. }
  613. //
  614. // We have found a DL_MAP for this font. So now verify it.
  615. //
  616. if ( BSameDLFont (pFontPDev, pfo, pdm ) )
  617. {
  618. //
  619. // This DL_MAP matches the font. So return the pointer.
  620. //
  621. bFound = TRUE;
  622. }
  623. }
  624. }
  625. //
  626. // If the font is not cached, search sequentially through the list.
  627. //
  628. if (!bFound)
  629. {
  630. DL_MAP_LIST *pdml; // The linked list of font information
  631. INT iI;
  632. //
  633. // This case happens when the pvConsumer field is not correct
  634. // for this DC. The GDI doesn't gaurantee that the pvConsumer
  635. // will be reset for each job.So we need to do a linear search.
  636. //
  637. pdml = pFontPDev->pvDLMap;
  638. iFontIndex = 1;
  639. while (pdml)
  640. {
  641. for( iI = 0; iI < pdml->cEntries; ++iI )
  642. {
  643. pdm = &pdml->adlm[ iI ];
  644. if ( BSameDLFont (pFontPDev, pfo, pdm ) )
  645. {
  646. //
  647. // This DL_MAP matches the font. So return the pointer.
  648. // we also need to reset pvConsumer. iFontIndex is
  649. // one base same as pvConsumer.
  650. //
  651. bFound = TRUE;
  652. pfo->pvConsumer = (PLONG_PTR)IntToPtr(iFontIndex);
  653. break;
  654. }
  655. iFontIndex++;
  656. }
  657. //
  658. // Check if we have found the correct font or not.
  659. //
  660. if (bFound)
  661. break;
  662. else
  663. pdml = pdml->pDMLNext;
  664. }
  665. }
  666. //
  667. // Both cached and sequential search failed. So this is a new one.
  668. // Try downloading.
  669. //
  670. if (!bFound)
  671. {
  672. INT iFontIndex; // Download Font Index in DL_MAP List.
  673. //
  674. // The fontobj doesn't match the DL_MAP, or this is a new font.
  675. // So get a new one.
  676. //
  677. if (!(pdm = PNewDLMap (pFontPDev,&(iFontIndex)) ))
  678. {
  679. ERR(("UniFont!PGetDLMap:Can't Create a new DL_MAP.\n"));
  680. iFontIndex = -1;
  681. }
  682. //
  683. // FontIndex returned by PNewDLMap is 0 based, but pvConsumer is one
  684. // base. So add one.
  685. //
  686. pfo->pvConsumer = (PLONG_PTR)IntToPtr((iFontIndex + 1));
  687. }
  688. return pdm;
  689. }
  690. BOOL
  691. BInitDLMap (
  692. PDEV *pPDev,
  693. FONTOBJ *pfo,
  694. DL_MAP *pdm
  695. )
  696. /*++
  697. Routine Description:
  698. Initializes a DL_MAP structure.
  699. Arguments:
  700. pPDev Pointer to PDEV.
  701. pfo FontObj.
  702. pdm DL_MPA to be initialized.
  703. Return Value:
  704. TRUE success and FALSE for failure.
  705. Note:
  706. 06/09/97 -ganeshp-
  707. Created it.
  708. --*/
  709. {
  710. BOOL bRet = FALSE;
  711. DWORD iGlyphPerSoftFont; // Total number of glyph per downloaded font.
  712. FONTINFO fi; // Details about this font.
  713. PFONTPDEV pFontPDev = pPDev->pFontPDev;
  714. INT iDL_ID;
  715. pdm->iUniq = pfo->iUniq;
  716. pdm->iTTUniq = pfo->iTTUniq;
  717. FONTOBJ_vGetInfo( pfo, sizeof( fi ), &fi );
  718. //
  719. // Trunction may happen. But we are fine. We won't download if the number
  720. // glyphs or max size are more than MAXWORD.
  721. //
  722. pdm->cTotalGlyphs = (WORD)fi.cGlyphsSupported;
  723. pdm->wMaxGlyphSize = (WORD)fi.cjMaxGlyph1;
  724. //
  725. // In GPD if the DLSymbolSet has valid value, then we have to set
  726. // the Min and Max Glyph IDs, using the Symbol Set, else we will use
  727. // the GPD entries,dwMinGlyphID and dwMaxGlyphID.
  728. //
  729. if (pPDev->pGlobals->dlsymbolset != UNUSED_ITEM)
  730. {
  731. if (pPDev->pGlobals->dlsymbolset == DLSS_PC8)
  732. {
  733. //
  734. // Symbol Set is DLSS_PC8.
  735. //
  736. pdm->wNextDLGId =
  737. pdm->wFirstDLGId = 32;
  738. pdm->wLastDLGId = 255;
  739. }
  740. else
  741. {
  742. //
  743. // Symbol Set is DLSS_ROMAN8.
  744. //
  745. pdm->wNextDLGId =
  746. pdm->wFirstDLGId = 33;
  747. pdm->wLastDLGId = 127;
  748. }
  749. }
  750. else
  751. {
  752. //
  753. // DLsymbolset Not defined. Use Min and Max Glyph Ids.
  754. //
  755. pdm->wFirstDLGId = pdm->wNextDLGId
  756. = (WORD)pPDev->pGlobals->dwMinGlyphID;
  757. pdm->wLastDLGId = (WORD)pPDev->pGlobals->dwMaxGlyphID;
  758. if( !(pFontPDev->flFlags & FDV_ROTATE_FONT_ABLE ))
  759. {
  760. //
  761. // If the printer can't rotate font then we assume that it only
  762. // supports Roman 8 limited character set. This hack is needed for
  763. // old PCL printers.
  764. //
  765. pdm->wFirstDLGId = pdm->wNextDLGId
  766. = 33;
  767. pdm->wLastDLGId = 127;
  768. }
  769. }
  770. //
  771. // Find out that font is bounded or not. We do this by finding out
  772. // how many glyphs we can download per soft font. Add 1 as range is
  773. // inclusive.
  774. //
  775. iGlyphPerSoftFont = (pdm->wLastDLGId - pdm->wFirstDLGId) +1;
  776. if (iGlyphPerSoftFont < MIN_GLYPHS_PER_SOFTFONT)
  777. {
  778. //
  779. // This is an error condition. Basically we don't want to download
  780. // if there are less than 64 glyphs per downloaded font.return FALSE.
  781. //
  782. ERR(("UniFont:BInitDLMap:Can't download any glyph,bad GPD values\n"));
  783. goto ErrorExit;;
  784. }
  785. else
  786. {
  787. //
  788. // There are more than 64 glyphs per downloded font. So find out
  789. // if it's bounded or unbounded. If the number of Glyphs is >255
  790. // then the font is unbounded else it's bounded.
  791. //
  792. if (iGlyphPerSoftFont > 255)
  793. pdm->wFlags |= DLM_UNBOUNDED;
  794. else
  795. pdm->wFlags |= DLM_BOUNDED;
  796. }
  797. if( (iDL_ID = IGetDL_ID( pPDev )) < 0 )
  798. {
  799. //
  800. // We have run out of soft fonts - must not use any more.
  801. //
  802. ERR(("UniFont:BInitDLMap:Can't download Font, No IDs available\n"));
  803. goto ErrorExit;;
  804. }
  805. pdm->wBaseDLFontid = (WORD)iDL_ID;
  806. //
  807. // Hashtable is allocated based upon the number of Glyphs in the font.
  808. //
  809. if (pdm->cTotalGlyphs >= 1024)
  810. pdm->cHashTableEntries = HASHTABLESIZE_3;
  811. else if (pdm->cTotalGlyphs >= 512)
  812. pdm->cHashTableEntries = HASHTABLESIZE_2;
  813. else
  814. pdm->cHashTableEntries = HASHTABLESIZE_1;
  815. //
  816. // Now allocate the Glyph Table. We only allocate the hash table.
  817. //
  818. if (pdm->GlyphTab.pGlyph = (DLGLYPH *)MemAllocZ(
  819. pdm->cHashTableEntries * sizeof(DLGLYPH)) )
  820. {
  821. INT iIndex;
  822. PDLGLYPH pGlyph;
  823. //
  824. // Set the hTTGlyph to HGLYPH_INVALID as 0 is a valid handle for HGLYPH.
  825. // Also set the cGlyphs(Number of downloded Glyphs) to 0.
  826. //
  827. pGlyph = pdm->GlyphTab.pGlyph;
  828. for (iIndex = 0; iIndex < pdm->cHashTableEntries; iIndex++,pGlyph++)
  829. pGlyph->hTTGlyph = HGLYPH_INVALID;
  830. bRet = TRUE;
  831. }
  832. else
  833. {
  834. //
  835. // Error case. DL_MAP will be freeed by the caller, IDownloadFont.
  836. //
  837. ERR(("UniFont:BInitDLMap:Can't Allocate Glyph Hash table\n"));
  838. }
  839. ErrorExit:
  840. return bRet;
  841. }
  842. INT
  843. IGetDL_ID(
  844. PDEV *pPDev
  845. )
  846. /*++
  847. Routine Description:
  848. Returns the font index to use for the next download font. Verifies
  849. that the number is within range.
  850. Arguments:
  851. pPDev Pointer to PDEV
  852. Return Value:
  853. Font index if OK, else -1 on error (over limit).
  854. Note:
  855. 3/5/1997 -ganeshp-
  856. Created it.
  857. --*/
  858. {
  859. PFONTPDEV pFontPDev = pPDev->pFontPDev;
  860. INT iSFIndex;
  861. if( pFontPDev->iNextSFIndex > pFontPDev->iLastSFIndex ||
  862. pFontPDev->iUsedSoftFonts >= pFontPDev->iMaxSoftFonts )
  863. {
  864. ERR(( "softfont limit reached (%d/%d, %d/%d)\n",
  865. pFontPDev->iNextSFIndex, pFontPDev->iLastSFIndex,
  866. pFontPDev->iUsedSoftFonts, pFontPDev->iMaxSoftFonts ));
  867. return -1; /* Too many - stop now */
  868. }
  869. /*
  870. * We'll definitely use this one, so add to the used count.
  871. */
  872. pFontPDev->iUsedSoftFonts++;
  873. iSFIndex = pFontPDev->iNextSFIndex++;
  874. return iSFIndex;
  875. }
  876. BOOL
  877. BPrintADLGlyph(
  878. PDEV *pPDev,
  879. TO_DATA *pTod,
  880. PDLGLYPH pdlGlyph
  881. )
  882. /*++
  883. Routine Description:
  884. This functions output a single downloaded Glyph.
  885. Arguments:
  886. pPDev Unidriver PDEV
  887. pTod Textout Data.
  888. pdlGlyph Download Glyph information
  889. Return Value:
  890. TRUE for success and FALSE for failure.
  891. Note:
  892. 8/12/1997 -ganeshp-
  893. Created it.
  894. --*/
  895. {
  896. FONTMAP *pFM; // FontMap of interest
  897. DL_MAP *pdm; // Details of this downloaded font.
  898. FONTPDEV *pFontPDev; // Font PDev.
  899. BOOL bRet; // Return Value of this function.
  900. WORD wDLGlyphID; // Downloaded Glyph ID.
  901. //
  902. // Make sure that parameters are valid.
  903. //
  904. if (NULL == pPDev ||
  905. NULL == pTod ||
  906. NULL == pdlGlyph )
  907. {
  908. return FALSE;
  909. }
  910. //
  911. // Initialize locals
  912. //
  913. bRet = TRUE;
  914. pFontPDev = PFDV;
  915. pFM = pTod->pfm;
  916. wDLGlyphID = pdlGlyph->wDLGlyphID;
  917. //
  918. // Get pdm
  919. //
  920. if (pFM->dwFontType == FMTYPE_TTOUTLINE)
  921. {
  922. PFONTMAP_TTO pFMTO = (PFONTMAP_TTO) pFM->pSubFM;
  923. pdm = (DL_MAP*) pFMTO->pvDLData;
  924. }
  925. else if (pFM->dwFontType == FMTYPE_TTBITMAP)
  926. {
  927. PFONTMAP_TTB pFMTB = (PFONTMAP_TTB) pFM->pSubFM;
  928. pdm = pFMTB->u.pvDLData;
  929. }
  930. else if (pFM->dwFontType == FMTYPE_TTOEM)
  931. {
  932. PFONTMAP_TTOEM pFMTOEM = (PFONTMAP_TTOEM) pFM->pSubFM;
  933. pdm = pFMTOEM->u.pvDLData;
  934. }
  935. else
  936. {
  937. ASSERTMSG(FALSE, ("Incorrect font type %d in BPrintADLGlyph.\n",
  938. pFM->dwFontType));
  939. pdm = NULL;
  940. bRet = FALSE;
  941. }
  942. //
  943. // Before sending a glyph we have to make sure that this glyph is in
  944. // selected soft font. We have to do this only for segmented fonts, i.e
  945. // multiple softfonts for one system fonts. If BaseFontId is not same as
  946. // CurrFontId, that means the font has atleat two softfonts associated.
  947. // Then we need to check for currently selected SoftFont. If the fontid of
  948. // the glyph is different that the selected one, we need to select the new
  949. // softfontid.
  950. //
  951. // GLYPH_IN_NEW_SOFTFONT is defined as :
  952. // if ( (pdm->wFlags & DLM_BOUNDED) &&
  953. // (pdm->wBaseDLFontid != pdm->wCurrFontId) &&
  954. // (pdlGlyph->wDLFontId != (WORD)(pFontPDev->ctl.iSoftFont)) )
  955. //
  956. if (bRet && GLYPH_IN_NEW_SOFTFONT(pFontPDev, pdm, pdlGlyph))
  957. {
  958. //
  959. // Need to select the new softfont.We do this by setting pfm->ulDLIndex
  960. // to new softfontid.
  961. //
  962. pFM->ulDLIndex = pdlGlyph->wDLFontId;
  963. BNewFont(pPDev, pTod->iFace, pFM, 0);
  964. }
  965. //
  966. // The Soft font selection is done. So now sent the downloaded Glyph Id.
  967. // We have to be a bit careful about the size of the Glyph ID. If the
  968. // Glyphs ID is less than 256, then we need to send a BYTE else a WORD.
  969. //
  970. if (bRet)
  971. {
  972. if (wDLGlyphID > 0xFF)
  973. {
  974. //
  975. // Send as WORD.
  976. //
  977. SWAB (wDLGlyphID);
  978. bRet = WriteSpoolBuf( pPDev, (BYTE*)&wDLGlyphID, sizeof( wDLGlyphID ) )
  979. == sizeof( wDLGlyphID );
  980. }
  981. else
  982. {
  983. //
  984. // Send as Byte.
  985. //
  986. BYTE bData;
  987. bData = (BYTE)wDLGlyphID;
  988. bRet = WriteSpoolBuf( pPDev, &bData, sizeof( bData ) ) ==
  989. sizeof( bData );
  990. }
  991. }
  992. return bRet;
  993. }