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.

2564 lines
73 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: cache.cxx *
  3. * *
  4. * Non-inline methods for font cache objects. *
  5. * *
  6. * Created: 11-Apr-1991 16:54:54 *
  7. * Author: Gilman Wong [gilmanw] *
  8. * *
  9. * Copyright (c) 1991-1999 Microsoft Corporation *
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. extern "C" VOID vInitFontCache();
  13. #pragma alloc_text(INIT, vInitFontCache)
  14. #define COPYSMALLMETRICS(pgdn, pgd) \
  15. { \
  16. RtlCopyMemory((PVOID)(pgdn), (PVOID)(pgd), offsetof(GLYPHDATA,fxInkTop)); \
  17. }
  18. #define ROUND_TO_PAGE(x) (((x)+PAGE_SIZE-1)&~(PAGE_SIZE-1))
  19. // binary cache search
  20. extern const BYTE acBits[16];
  21. extern const INT aiStart[17];
  22. /******************************Public*Routine******************************\
  23. * vInitFontCache
  24. *
  25. * Initializes the CACHE_PARM structure from the [FontCache] section of
  26. * WIN.INI.
  27. *
  28. * Returns:
  29. * TRUE if successful, FALSE otherwise.
  30. *
  31. \**************************************************************************/
  32. #define CJMININCREMENT 0x2000
  33. #define CJMAX (8 * 0x2000)
  34. /******************************Public*Routine******************************\
  35. * RFONTOBJ::bInitCache
  36. *
  37. * UNICODE GLYPHDATA CACHE:
  38. *
  39. * Reserves and commits glyphbit cache memory and allocates GLYPHDATA memory
  40. * from the heap in 1024 bytes chunks.
  41. *
  42. * ______ ______ ______
  43. * pgdThreshold--> | | | | | |
  44. * | G D | | G D | | G D |
  45. * | l a | | l a | | l a |
  46. * pgdNext--> | y t | | y t | | y t |
  47. * | p a | | p a | | p a |
  48. * | h | | h | | h |
  49. * |------| |------| |------|
  50. * pc->pdblBase -->| link | --> | link | --> | NULL |
  51. * |______| |______| |______|
  52. * | WCPG |
  53. * |______|
  54. *
  55. *
  56. *
  57. *
  58. *
  59. *
  60. * Preloads the default glyph, in anticipation of need, and to avoid
  61. * loading it multiple times.
  62. *
  63. * Builds empty WCGP, sets RFONT mode to cache.
  64. *
  65. * Returns:
  66. * TRUE if successful, FALSE otherwise.
  67. *
  68. * History:
  69. *
  70. * 31-Nov-1994 -by- Gerrit van Wingerden
  71. * Re-rewrote it to cache GLYPHDATA more effieciently.
  72. *
  73. * 21-Apr-1992 -by- Paul Butzi
  74. * Rewrote it.
  75. *
  76. * 15-Apr-1991 -by- Gilman Wong [gilmanw]
  77. * Wrote it.
  78. \**************************************************************************/
  79. // we want number divisible by 8 containing about 75 glyphs,
  80. // almost an upper limit on number of glyphs in the metrics cache
  81. // when running winstone memory constrained scenario
  82. #define GD_INC (76 * offsetof(GLYPHDATA,fxInkTop))
  83. // GD_INC amounts to 1520 == 000005f0H, far less than a page.
  84. // according to Kirk's statistics, very few realizations cache more
  85. // than 60 glyphs, so we shall start with a block which contains about
  86. // 60 glyphs
  87. #define C_GLYPHS_IN_BLOCK 64
  88. BOOL RFONTOBJ::bInitCache(FLONG flType)
  89. {
  90. #if DBG
  91. IFIOBJ ifio(prfnt->ppfe->pifi);
  92. TRACE_CACHE((
  93. " -- TRACE_CACHE --\n"
  94. " RFONTOBJ::bInitCache\n"
  95. " FaceName = \"%ws\"\n"
  96. " ExAllocatePoolWithTag\n",
  97. ifio.pwszFaceName()
  98. ));
  99. #endif
  100. CACHE *pc = &(prfnt->cache);
  101. // Set the pointer to null. vDeleteCache will free memory from
  102. // any non-null pointers. This simplifies cleanup, since bRealize
  103. // ensures that vDeleteCache is called if this routine fails.
  104. // metrics portion
  105. pc->pdblBase = NULL;
  106. pc->cMetrics = 0; // no metrics in the cache yet
  107. // glyphbits portion
  108. pc->cjbbl = pc->cBlocks = pc->cBlocksMax = 0;
  109. pc->pbblBase = pc->pbblCur = NULL;
  110. pc->pgbNext = pc->pgbThreshold = NULL;
  111. pc->cjbblInitial = 0; // no bits in the cache to begin with.
  112. pc->cGlyphs = 0; // no bits in the cache to begin with.
  113. pc->cjTotal = 0; // nothing used yet
  114. // aux mem portion
  115. pc->pjAuxCacheMem = NULL;
  116. pc->cjAuxCacheMem = 0;
  117. prfnt->wcgp = NULL;
  118. // First, figure out how big the max glyph will be
  119. // Default is zero - glyphdata size is not counted!
  120. pc->cjGlyphMax = 0;
  121. switch ( prfnt->ulContent )
  122. {
  123. case FO_HGLYPHS:
  124. case FO_GLYPHBITS:
  125. pc->cjGlyphMax = prfnt->cjGlyphMax;
  126. break;
  127. case FO_PATHOBJ:
  128. // oh, yeah? Got a better guess?
  129. // Here we are putting an upper bound on glyph outline data.
  130. // Unlike the bitmap case, in the outline case the font driver
  131. // can not give us a cjGlyphMax number we can trust to be sufficient
  132. // for all glyphs.
  133. // Even if the font driver new this number, bFlatten may
  134. // alter ie. increase the number of points so much that even as huge a
  135. // number as cjMax/2 may not suffice for some glyphs. So we
  136. // had better be prepared to fail gracefully in the pgbCheckGlyphbits
  137. // routine if that is the case.
  138. pc->cjGlyphMax = CJMAX / 2;
  139. break;
  140. }
  141. // this is used in few places below, remember it:
  142. ULONG cjGlyphMaxX2 = 2 * pc->cjGlyphMax;
  143. // if we can't even get one glyph in a maximum size cache, don't cache
  144. // Note that we need room for the default glyph and one other glyph
  145. prfnt->flType = flType;
  146. if ((prfnt->ulContent != FO_HGLYPHS) && (cjGlyphMaxX2 > CJMAX))
  147. {
  148. //
  149. // Glyph exceeds maximum cache memory size, so we will revert to
  150. // caching just the metrics. This will speed up things like
  151. // GetCharWidths, and stuff that just *has* to have the glyphs
  152. // will use the lookaside stuff (previously called BigGlyph)
  153. prfnt->flType |= RFONT_TYPE_NOCACHE;
  154. }
  155. // get the width of the break character
  156. HGLYPH hg = hgXlat(prfnt->ppfe->pifi->wcBreakChar);
  157. // do not bother to store this in the cache
  158. PDEVOBJ pdo(prfnt->hdevProducer);
  159. // Call font driver to get the metrics.
  160. ULONG ulMode = QFD_GLYPHANDBITMAP;
  161. if (prfnt->ulContent == FO_PATHOBJ)
  162. {
  163. ulMode = QFD_GLYPHANDOUTLINE;
  164. }
  165. GLYPHDATA gd;
  166. if (pdo.QueryFontData(
  167. prfnt->dhpdev,
  168. pfo(),
  169. ulMode,
  170. hg,
  171. &gd,
  172. NULL,
  173. 0) == FD_ERROR)
  174. {
  175. WARNING("bGetBreak: QueryFontData failed\n");
  176. return FALSE;
  177. }
  178. prfnt->fxBreak = gd.fxD;
  179. prfnt->hgBreak = hg;
  180. // Now we have everything ready to fly. Handle some little details:
  181. // set up the cache semaphore.
  182. if(!(prfnt->ppfe->flPFE & PFE_EUDC))
  183. {
  184. prfnt->hsemEUDC = GreCreateSemaphore();
  185. if (!prfnt->hsemEUDC)
  186. return FALSE;
  187. }
  188. else
  189. prfnt->hsemEUDC = NULL;
  190. prfnt->hsemCache = GreCreateSemaphore();
  191. if (!prfnt->hsemCache)
  192. {
  193. if (prfnt->hsemEUDC)
  194. {
  195. GreDeleteSemaphore(prfnt->hsemEUDC);
  196. prfnt->hsemEUDC = NULL;
  197. }
  198. WARNING("Semaphore creation failed in bInitCache\n");
  199. return FALSE;
  200. }
  201. return TRUE;
  202. }
  203. BOOL
  204. RFONTOBJ::bAllocateCache(RFONTOBJ* prfoBase)
  205. {
  206. FLONG flType = prfnt->flType;
  207. WCGP *wcgp;
  208. CACHE *pc = &(prfnt->cache);
  209. ULONG cjGlyphMaxX2 = 2 * pc->cjGlyphMax;
  210. FLONG flEUDC = 0;
  211. // calculate the size of the WCGP structure
  212. GISET *pgiset;
  213. FD_GLYPHSET *pfdg;
  214. ULONG cRuns;
  215. ULONG cGlyphsTotal;
  216. if (flType & RFONT_TYPE_UNICODE)
  217. {
  218. pfdg = prfnt->pfdg;
  219. cRuns = pfdg->cRuns;
  220. cGlyphsTotal = pfdg->cGlyphsSupported;
  221. }
  222. else // RFONT_TYPE_HGLYPH
  223. {
  224. if (prfnt->ppfe->pgiset)
  225. {
  226. pgiset = prfnt->ppfe->pgiset;
  227. cRuns = pgiset->cGiRuns;
  228. cGlyphsTotal = pgiset->cgiTotal;
  229. }
  230. else
  231. {
  232. // The mapper should have prevented us from getting here.
  233. // However, in case we have a bug in the mapper we still do
  234. // not want to go down in flames:
  235. WARNING("gdi: attempting to init cache for non glyph index font\n");
  236. return FALSE;
  237. }
  238. }
  239. ULONGSIZE_T sizeWCGP = (ULONGSIZE_T)(offsetof(WCGP, agpRun) +
  240. cRuns * sizeof(GPRUN) +
  241. cGlyphsTotal * sizeof(GLYPHDATA*));
  242. #if DBG
  243. if (flType & RFONT_TYPE_UNICODE)
  244. {
  245. SIZE_T cGlyphs = 0;
  246. for (UINT i = 0; i < pfdg->cRuns; i += 1)
  247. {
  248. cGlyphs += pfdg->awcrun[i].cGlyphs;
  249. }
  250. ASSERTGDI(cGlyphs == pfdg->cGlyphsSupported, "cache.cxx, cGlyphs init\n");
  251. }
  252. #endif
  253. // The distribution of metics per realized font w/ Winstone97 is:
  254. //
  255. // 43% <= 0 Metrics
  256. // 50% <= 6 Metrics
  257. // 76% <= 32 Metrics
  258. // 99% <= 216 Metrics
  259. // 100% <= 249 Metrics
  260. //
  261. // Make the allocation either be smaller than a page or be multiples
  262. // of the pages size due to the current pool allocation scheme.
  263. //
  264. // If the 32 GD's + the runs and pointers fit with plenty of space
  265. // left then use that. Otherwize, otherwize round up to the page
  266. // boundary (but watch that at least a few fit).
  267. //
  268. // We round up to a page boundary if we're going to use more than 3K
  269. // on the premise that we are more likely to be able to page it out
  270. // if we don't have multiple uses for it.
  271. // now figure out how much space we will need for at least the WCPG
  272. // and one "block" of glyphdata structures.
  273. // Insure that the DATABLOCK's following the GLYPHDATA pointers is
  274. // maximally aligned
  275. ULONGSIZE_T dpDATABLOCK = ALIGN8(sizeWCGP);
  276. ULONGSIZE_T cjInitData;
  277. int GlyphDataSize = bSmallMetrics() ?
  278. offsetof(GLYPHDATA,fxInkTop) :
  279. sizeof(GLYPHDATA);
  280. if ((dpDATABLOCK + GDI_POOL_HEADER_SIZE + (GlyphDataSize * 32)) <= (PAGE_SIZE*3/4))
  281. {
  282. // Use a partial page
  283. cjInitData = dpDATABLOCK + (32 * GlyphDataSize);
  284. }
  285. else
  286. {
  287. // Use a full page but make sure that at least a few fit. If
  288. // there's less that 128 bytes left on the last page allocate
  289. // another.
  290. // round up to page, somewhat arbitrary
  291. cjInitData = ROUND_TO_PAGE(dpDATABLOCK);
  292. if ((cjInitData - dpDATABLOCK) < 128){
  293. cjInitData += PAGE_SIZE;
  294. }
  295. }
  296. BYTE *pjRunAndData;
  297. // Allocate enough memory for the WCGP and one GLYPHDATA block
  298. if ((pjRunAndData = (BYTE*)PALLOCNOZ(cjInitData, 'cacG')) == NULL)
  299. {
  300. WARNING("win32k!bAllocateCache failed on first attempt \n");
  301. // not enough memory, try to clean up all inactive RFONT lists
  302. // release the fmCache semaphores for both linked fonts if any
  303. // and the base font, otherwise it might cause deadlock
  304. if (prfoBase)
  305. {
  306. PRFONT prfntBase = prfoBase->prfntFont();
  307. {
  308. GreAcquireSemaphore(prfntBase->hsemEUDC);
  309. if (prfntBase->flEUDCState & TT_SYSTEM_INITIALIZED)
  310. {
  311. ASSERTGDI(prfoBase->prfntSystemTT(), "bAllocate cache NULL prfntSysTT\n");
  312. if (prfoBase->prfntSystemTT())
  313. {
  314. flEUDC |= TT_SYSTEM_INITIALIZED;
  315. prfntBase->flEUDCState &= ~TT_SYSTEM_INITIALIZED;
  316. GreReleaseSemaphore(prfoBase->prfntSystemTT()->hsemCache);
  317. }
  318. }
  319. if (prfntBase->flEUDCState & EUDC_INITIALIZED)
  320. {
  321. flEUDC |= EUDC_INITIALIZED;
  322. prfntBase->flEUDCState &= ~EUDC_INITIALIZED;
  323. if (prfoBase->prfntSysEUDC())
  324. {
  325. GreReleaseSemaphore(prfoBase->prfntSysEUDC()->hsemCache);
  326. }
  327. if (prfoBase->prfntDefEUDC())
  328. {
  329. GreReleaseSemaphore(prfoBase->prfntDefEUDC()->hsemCache);
  330. }
  331. for( UINT ii = 0; ii < prfoBase->uiNumFaceNameLinks(); ii++ )
  332. {
  333. if( prfntBase->paprfntFaceName[ii] != NULL )
  334. {
  335. GreReleaseSemaphore(prfntBase->paprfntFaceName[ii]->hsemCache);
  336. }
  337. }
  338. }
  339. GreReleaseSemaphore(prfntBase->hsemEUDC);
  340. }
  341. GreReleaseSemaphore(prfntBase->hsemCache);
  342. }
  343. else
  344. {
  345. GreReleaseSemaphore(prfnt->hsemCache);
  346. }
  347. //
  348. // Winbug 399722: instead of using semaphores to secure the
  349. // InactiveRont list cleanup process (which caused deadlock),
  350. // we restrict the process's access to the UMPD pdev's.
  351. //
  352. PPDEV ppdev;
  353. GreAcquireSemaphoreEx(ghsemDriverMgmt, SEMORDER_DRIVERMGMT, NULL);
  354. for (ppdev=gppdevList; ppdev; ppdev=ppdev->ppdevNext)
  355. {
  356. PDEVOBJ pdo((HDEV)ppdev);
  357. if (!pdo.bFontDriver()
  358. &&
  359. (!pdo.bUMPD() || pdo.pid() == (PW32PROCESS)W32GetCurrentProcess())
  360. )
  361. {
  362. ppdev->cPdevRefs++;
  363. break;
  364. }
  365. }
  366. GreReleaseSemaphoreEx(ghsemDriverMgmt);
  367. while(ppdev)
  368. {
  369. PDEVOBJ pdoCurrent((HDEV)ppdev);
  370. vRemoveAllInactiveRFONTs(ppdev);
  371. GreAcquireSemaphoreEx(ghsemDriverMgmt, SEMORDER_DRIVERMGMT, NULL);
  372. for (ppdev = ppdev->ppdevNext; ppdev; ppdev=ppdev->ppdevNext)
  373. {
  374. PDEVOBJ pdoNext((HDEV)ppdev);
  375. if (!pdoNext.bFontDriver()
  376. &&
  377. (!pdoNext.bUMPD() || pdoNext.pid() == (PW32PROCESS)W32GetCurrentProcess())
  378. )
  379. {
  380. ppdev->cPdevRefs++;
  381. break;
  382. }
  383. }
  384. GreReleaseSemaphoreEx(ghsemDriverMgmt);
  385. pdoCurrent.vUnreferencePdev();
  386. }
  387. // Grab the fmCache semaphore again
  388. if (prfoBase)
  389. {
  390. PRFONT prfntBase = prfoBase->prfntFont();
  391. GreAcquireSemaphore(prfntBase->hsemCache);
  392. {
  393. GreAcquireSemaphore(prfntBase->hsemEUDC);
  394. if ((flEUDC & TT_SYSTEM_INITIALIZED) &&
  395. !(prfntBase->flEUDCState & TT_SYSTEM_INITIALIZED) )
  396. {
  397. prfntBase->flEUDCState |= TT_SYSTEM_INITIALIZED;
  398. GreAcquireSemaphore(prfoBase->prfntSystemTT()->hsemCache);
  399. }
  400. if ((flEUDC & EUDC_INITIALIZED) &&
  401. !(prfntBase->flEUDCState & EUDC_INITIALIZED) )
  402. {
  403. prfntBase->flEUDCState |= EUDC_INITIALIZED;
  404. if (prfoBase->prfntSysEUDC())
  405. {
  406. GreAcquireSemaphore(prfoBase->prfntSysEUDC()->hsemCache);
  407. }
  408. if (prfoBase->prfntDefEUDC())
  409. {
  410. GreAcquireSemaphore(prfoBase->prfntDefEUDC()->hsemCache);
  411. }
  412. for( UINT ii = 0; ii < prfoBase->uiNumFaceNameLinks(); ii++ )
  413. {
  414. if( prfntBase->paprfntFaceName[ii] != NULL )
  415. {
  416. GreAcquireSemaphore(prfntBase->paprfntFaceName[ii]->hsemCache);
  417. }
  418. }
  419. }
  420. GreReleaseSemaphore(prfntBase->hsemEUDC);
  421. }
  422. }
  423. else
  424. {
  425. GreAcquireSemaphore(prfnt->hsemCache);
  426. }
  427. // Check whether the cache has been allocated
  428. // while we clean up the inactive RFONTs.
  429. // Don't allocate again if it has been done.
  430. if (prfnt->wcgp)
  431. {
  432. return TRUE;
  433. }
  434. else
  435. {
  436. if ((pjRunAndData = (BYTE*)PALLOCNOZ(cjInitData, 'cacG')) == NULL)
  437. {
  438. WARNING("win32k!bAllocateCache failed to on second attempt\n");
  439. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  440. return (FALSE);
  441. }
  442. }
  443. }
  444. // The debug pool allocation functions do not return
  445. // page aligned memory.
  446. #if 0
  447. #if DBG
  448. if (cjInitData >= (PAGE_SIZE - GDI_POOL_HEADER_SIZE))
  449. {
  450. if ((((ULONG_PTR)pjRunAndData) & (PAGE_SIZE - 1)) != 0)
  451. DbgPrint("pjRunAndData alignment (0x%08lx, 0x%p)\n",
  452. cjInitData, pjRunAndData);
  453. }
  454. #endif
  455. #endif
  456. // Set up the WCPG stucture
  457. prfnt->wcgp = (WCGP *) pjRunAndData;
  458. wcgp = prfnt->wcgp;
  459. wcgp->cRuns = cRuns;
  460. wcgp->pgdDefault = (GLYPHDATA *) NULL;
  461. GLYPHDATA **ppgd = (GLYPHDATA **)&(wcgp->agpRun[wcgp->cRuns]);
  462. // init all glyphdata pointers to zero
  463. RtlZeroMemory(ppgd, sizeof(GLYPHDATA*) * cGlyphsTotal);
  464. if (flType & RFONT_TYPE_UNICODE)
  465. {
  466. for (UINT i = 0; i < cRuns; i += 1 )
  467. {
  468. GPRUN *pRun = &wcgp->agpRun[i];
  469. WCRUN *pWCRun = &(pfdg->awcrun[i]);
  470. pRun->apgd = ppgd;
  471. pRun->wcLow = (UINT) pWCRun->wcLow;
  472. pRun->cGlyphs = pWCRun->cGlyphs;
  473. ppgd += pRun->cGlyphs;
  474. }
  475. }
  476. else // RFONT_TYPE_HGLYPH
  477. {
  478. for (UINT i = 0; i < cRuns; i += 1 )
  479. {
  480. GPRUN *pRun = &wcgp->agpRun[i];
  481. GIRUN *pgiRun = &(pgiset->agirun[i]);
  482. pRun->apgd = ppgd;
  483. pRun->wcLow = pgiRun->giLow;
  484. pRun->cGlyphs = pgiRun->cgi;
  485. ppgd += pRun->cGlyphs;
  486. }
  487. }
  488. // Now we will set up the parameters for the GLYPHDATA
  489. // part of the cache. We are assured we are aligned properly.
  490. pc->pdblBase = (DATABLOCK *)(pjRunAndData + dpDATABLOCK);
  491. // init head to null. This value will stay null always.
  492. pc->pdblBase->pdblNext = (DATABLOCK*)NULL;
  493. pc->pgdNext = &pc->pdblBase->agd[0];
  494. // end of the current block and first block, same in this case
  495. pc->pjFirstBlockEnd = pjRunAndData + cjInitData;
  496. pc->pgdThreshold = (GLYPHDATA *)pc->pjFirstBlockEnd;
  497. // Now, the GLYPHDATA portion is all set. Go ahead and set up the
  498. // space for the GLYPHBITS or PATHOBJS if needed.
  499. if ((prfnt->ulContent != FO_HGLYPHS) &&
  500. !(prfnt->flType & RFONT_TYPE_NOCACHE))
  501. {
  502. // 47% <= 0 Glyphs
  503. // 55% <= 1 Glyphs
  504. // 75% <= 16 Glyphs
  505. // 95% <= 58 Glyphs
  506. // 100% <= 217 Glyphs
  507. //
  508. // Special case the first allocation, since most realizations use
  509. // <= 16 Glyphs. Make the first allocation 16 glyphs if that size fits
  510. // well within a page boundary.
  511. //
  512. // Subsequent allocations will be in page aligned allocations w/
  513. // enough to hold 16 max sized glyphs. This will be limited to
  514. // CJMAX KB
  515. //
  516. // If caching glyphs, at least 2 glyphs (default one and another one,
  517. // see NOCACHE above, will fit in CJMAX).
  518. if (prfnt->ulContent == FO_PATHOBJ)
  519. {
  520. // this seems to work and this is what we did before DavidFie changes
  521. // for PATHOBJ case
  522. pc->cjbbl = pc->cjbblInitial = cjGlyphMaxX2;
  523. }
  524. else
  525. {
  526. ULONG cjBytes = 16 * pc->cjGlyphMax;
  527. ULONG AllocationSize = ROUND_TO_PAGE(cjBytes);
  528. if (AllocationSize <= CJMININCREMENT)
  529. {
  530. pc->cjbbl = AllocationSize;
  531. pc->cjbblInitial = (cjBytes < (PAGE_SIZE*3/4)) ?
  532. cjBytes : AllocationSize;
  533. }
  534. else
  535. {
  536. cjBytes = 8 * pc->cjGlyphMax;
  537. if (cjBytes <= CJMININCREMENT)
  538. {
  539. pc->cjbbl = pc->cjbblInitial = CJMININCREMENT;
  540. }
  541. else
  542. {
  543. AllocationSize = ROUND_TO_PAGE(cjBytes);
  544. pc->cjbbl = pc->cjbblInitial = MIN(AllocationSize, CJMAX);
  545. ASSERTGDI(pc->cjbbl >= cjGlyphMaxX2,
  546. "two glyphs don't fit in the cache\n");
  547. }
  548. }
  549. }
  550. // we shall re-interpret cjMax to mean the max number of bytes in
  551. // glyphbits portion of the cache per 1K of glyphs in the font.
  552. // That is for larger fonts we shall allow more glyphbits
  553. // memory per realization than for ordinary US fonts. This will be
  554. // particularly important for FE fonts. This same code will work fine
  555. // in their case too:
  556. pc->cBlocksMax =
  557. (CJMAX * ((cGlyphsTotal + 1024 - 1)/1024)) /
  558. pc->cjbbl;
  559. ASSERTGDI(pc->cjbbl <= CJMAX, "bogus cache initializaiton\n");
  560. }
  561. // We decide whether or not to invoke the binary search based on the
  562. // number of runs in the font. For large numbers of runs it makes
  563. // sense to do a binary search. For small numbers of runs a linear
  564. // search will be better. Right now I use 200 as the cutoff for
  565. // a linear search because I am sure that a binary search will be
  566. // faster for this number of runs. We should do some experimentation
  567. // to find the OPTIMAL cutoff in the future. [gerritv]\
  568. // Arial etc has about 90 runs, Lucida Sans Unicode 65
  569. #define BINARY_CUTOFF 200
  570. if(prfnt->wcgp->cRuns > BINARY_CUTOFF)
  571. {
  572. pc->iMax = prfnt->wcgp->cRuns - 1;
  573. if( pc->iMax & 0xF000 )
  574. {
  575. pc->cBits = acBits[(pc->iMax >> 12) & 0x00FF] + 12;
  576. }
  577. else if( pc->iMax & 0x0F00 )
  578. {
  579. pc->cBits = acBits[(pc->iMax >> 8) & 0x00FF] + 8;
  580. }
  581. else if( pc->iMax & 0x00F0 )
  582. {
  583. pc->cBits = acBits[(pc->iMax >> 4) & 0x00FF] + 4;
  584. }
  585. else
  586. {
  587. pc->cBits = acBits[pc->iMax];
  588. }
  589. pc->iFirst = aiStart[pc->cBits];
  590. }
  591. else
  592. {
  593. // setting iMax to zero signifies a linear search
  594. pc->iMax = 0;
  595. }
  596. return (TRUE);
  597. }
  598. /******************************Public*Routine******************************\
  599. * RFONTOBJ::vDeleteCache
  600. *
  601. * Destroy the font cache object (CACHE).
  602. *
  603. * Returns FALSE if the function fails.
  604. *
  605. * History:
  606. * 15-Apr-1991 -by- Gilman Wong [gilmanw]
  607. * Wrote it.
  608. *
  609. * 24-Nov-92 -by- Paul Butzi
  610. * Rewrote it.
  611. * Fri 08-Sep-1995 -by- Bodin Dresevic [BodinD]
  612. * update: Rewrote one more time
  613. \**************************************************************************/
  614. VOID RFONTOBJ::vDeleteCache ()
  615. {
  616. CACHE *pc = &prfnt->cache;
  617. // Free up glyph data portion of the cache:
  618. DATABLOCK *pdbl = pc->pdblBase;
  619. // We are counting on the while loop to free prfnt->wcpg so
  620. // ppv better always be non-NULL when prfnt->wcpg is.
  621. ASSERTGDI( ((prfnt->wcgp == NULL ) || (pdbl != (DATABLOCK*)NULL)),
  622. "vDeleteCache: prfnt->wcgp non-NULL but pc->pdblBase was NULL\n");
  623. // walks the list of blocks of GLYPHDATA and frees all of them.
  624. while (pdbl)
  625. {
  626. DATABLOCK *pdblTmp = pdbl;
  627. pdbl = pdbl->pdblNext;
  628. if (pdbl == NULL)
  629. {
  630. // this is the first block so wcpg really points to its base.
  631. VFREEMEM(prfnt->wcgp);
  632. }
  633. else
  634. {
  635. VFREEMEM(pdblTmp);
  636. }
  637. }
  638. pc->pdblBase = NULL;
  639. prfnt->wcgp = NULL;
  640. // Free up glyphbits portion of the cache, if it was ever allocated
  641. if (pc->pbblBase != NULL)
  642. {
  643. BITBLOCK * pbbl, *pbblNext;
  644. for (pbbl = pc->pbblBase; pbbl; pbbl = pbblNext)
  645. {
  646. pbblNext = pbbl->pbblNext;
  647. VFREEMEM(pbbl);
  648. }
  649. pc->pbblBase = NULL;
  650. }
  651. // free aux memory if it was used
  652. if (prfnt->cache.pjAuxCacheMem != NULL)
  653. {
  654. VFREEMEM((PVOID) prfnt->cache.pjAuxCacheMem);
  655. prfnt->cache.pjAuxCacheMem = NULL;
  656. prfnt->cache.cjAuxCacheMem = 0;
  657. }
  658. return;
  659. }
  660. /******************************Public*Routine******************************\
  661. * BOOL RFONTOBJ::bGetGlyphMetrics
  662. *
  663. * Translate wchars into an array of GLYPHPOS structures, filling in
  664. * the pointer to GLYPHDATA field. Only the metrics are assured to be
  665. * valid; no attempt is made to ensure that the glyph data itself is
  666. * present in the cache before the return to the caller.
  667. *
  668. * This routine is to be used primarily by GetTextExtent and GetCharWidths,
  669. * which have no need for anything except metrics.
  670. *
  671. * A zero return means that we failed to insert the metrics due to some
  672. * hard error, most likely a failure to commit memory in the glyph
  673. * insertion routine.
  674. *
  675. * History:
  676. * 13-Nov-92 -by- Paul Butzi
  677. * Wrote it.
  678. \**************************************************************************/
  679. #pragma optimize("t", on)
  680. BOOL RFONTOBJ::bGetGlyphMetrics (
  681. COUNT c,
  682. GLYPHPOS *pgp,
  683. WCHAR *pwc,
  684. XDCOBJ *pdco,
  685. ESTROBJ *pto
  686. )
  687. {
  688. if (prfnt->wcgp == NULL)
  689. {
  690. if (!bAllocateCache())
  691. {
  692. return(FALSE);
  693. }
  694. }
  695. WCGP *pwcgp = prfnt->wcgp;
  696. WCHAR *pwcInit = pwc;
  697. // need to check for empty glyphset
  698. if (pwcgp->cRuns == 0)
  699. {
  700. WARNING("bGetGlyphMetrics - empty glyphset\n");
  701. for (; c != 0; --c, ++pgp)
  702. {
  703. pgp->hg = hgDefault();
  704. pgp->pgdf = (GLYPHDEF *) pgdDefault();
  705. }
  706. return TRUE;
  707. }
  708. GPRUN *pwcRun = pwcgp->agpRun; // initialize with guess for loop below
  709. GLYPHDATA *wpgd;
  710. for (WCHAR *pwcEnd = pwc + c; pwc < pwcEnd; pwc+=1, pgp+=1)
  711. {
  712. WCHAR wc = *pwc;
  713. // Find the correct run, if any.
  714. // Try the current run first.
  715. UINT swc = (UINT)wc - pwcRun->wcLow;
  716. if ( swc >= pwcRun->cGlyphs )
  717. {
  718. // This path should go out of line
  719. pwcRun = gprunFindRun(wc);
  720. swc = (UINT)wc - pwcRun->wcLow;
  721. if ( swc < pwcRun->cGlyphs )
  722. {
  723. wpgd = pwcRun->apgd[swc];
  724. }
  725. else
  726. {
  727. BOOL bAccel;
  728. if ((wpgd = wpgdGetLinkMetricsPlus(pdco,pto, pwc, pwcInit, c, &bAccel, FALSE)) == NULL)
  729. {
  730. WARNING("wpgdGetLinkMetricsPlus return NULL\n");
  731. return FALSE;
  732. }
  733. }
  734. }
  735. else
  736. {
  737. // Look up entry in current run
  738. // This path should go in line
  739. wpgd = pwcRun->apgd[swc];
  740. }
  741. // check to make sure in cache, insert if needed
  742. if ( wpgd == NULL )
  743. {
  744. // This path should go out of line
  745. if ( !bInsertMetrics(&pwcRun->apgd[swc], wc) )
  746. {
  747. // when insert fails trying to get just metrics, it is a hard
  748. // failure. Get out of here!
  749. WARNING("bGetGlyphMetrics - bInsertMetrics failed\n");
  750. return FALSE;
  751. }
  752. wpgd = pwcRun->apgd[swc];
  753. }
  754. // set the pgp and go on to the next wc
  755. pgp->hg = wpgd->hg;
  756. pgp->pgdf = (GLYPHDEF *) wpgd;
  757. }
  758. return TRUE;
  759. }
  760. /******************************Public*Routine******************************\
  761. * BOOL RFONTOBJ::bGetGlyphMetricsPlus
  762. *
  763. * Translate wchars into an array of GLYPHPOS structures, filling in
  764. * the pointer to GLYPHDATA field. Although only the metrics are assured to be
  765. * valid, an attempt is made to ensure that the glyph data itself is
  766. * present in the cache before the return to the caller. Failure in this
  767. * attempt is indicated by clearing the flag *pbAccel. This allows the
  768. * text code to tell the device driver that the STROBJ_bEnum callback is
  769. * not needed.
  770. *
  771. * This routine is to be used primarily by TextOut and its kin.
  772. *
  773. * A zero return means that we failed to insert the metrics due to some
  774. * hard error, most likely a failure to commit memory in the glyph
  775. * insertion routine.
  776. *
  777. *
  778. * History:
  779. * 13-Nov-92 -by- Paul Butzi
  780. * Wrote it.
  781. \**************************************************************************/
  782. BOOL RFONTOBJ::bGetGlyphMetricsPlus (
  783. COUNT c,
  784. GLYPHPOS *pgp,
  785. WCHAR *pwc,
  786. BOOL *pbAccel,
  787. XDCOBJ *pdco,
  788. ESTROBJ *pto
  789. )
  790. {
  791. if (prfnt->wcgp == NULL)
  792. {
  793. if (!bAllocateCache())
  794. {
  795. return(FALSE);
  796. }
  797. }
  798. // if this realization is intended for the device that does not need bits,
  799. // let us make sure we do not rasterize these bits, unless the device driver
  800. // really wants the bits (for whatever reason),
  801. // in which case this device driver will have to call STROBJ_bEnum for the string
  802. // that it wants rasterized:
  803. PDEVOBJ po(hdevConsumer());
  804. if
  805. (
  806. (po.flGraphicsCapsNotDynamic() & GCAPS_FONT_RASTERIZER) &&
  807. (prfnt->ulContent == FO_GLYPHBITS)
  808. )
  809. {
  810. if (pbAccel)
  811. {
  812. *pbAccel = FALSE;
  813. }
  814. return bGetGlyphMetrics(c, pgp, pwc, pdco, pto);
  815. }
  816. WCHAR *pwcInit = pwc;
  817. *pbAccel = TRUE;
  818. // need to check for empty glyphset
  819. if (prfnt->wcgp->cRuns == 0)
  820. {
  821. WARNING("bGetGlyphMetricsPlus - empty glyphset\n");
  822. for (; c != 0; --c, ++pgp)
  823. {
  824. pgp->hg = hgDefault();
  825. pgp->pgdf = (GLYPHDEF *) pgdDefault();
  826. }
  827. return TRUE;
  828. }
  829. GPRUN *pwcRun = prfnt->wcgp->agpRun; // initialize with guess for loop below
  830. for (WCHAR *pwcEnd = pwc + c; pwc < pwcEnd; pwc+=1, pgp+=1)
  831. {
  832. GLYPHDATA *wpgd;
  833. // Find the correct run, if any.
  834. // Try the current run first.
  835. UINT swc = (UINT)*pwc - pwcRun->wcLow;
  836. if ( swc >= pwcRun->cGlyphs )
  837. {
  838. // This path should go out of line
  839. pwcRun = gprunFindRun(*pwc);
  840. swc = (UINT)*pwc - pwcRun->wcLow;
  841. if ( swc < pwcRun->cGlyphs )
  842. {
  843. wpgd = pwcRun->apgd[swc];
  844. }
  845. else
  846. {
  847. // wpgdGetLinkMetricsPlus should never return NULL
  848. if ((wpgd = wpgdGetLinkMetricsPlus(pdco, pto, pwc, pwcInit,c, pbAccel, TRUE)) == NULL)
  849. {
  850. WARNING("wpgdGetLinkMetricsPlus returns NULL\n");
  851. return FALSE;
  852. }
  853. }
  854. }
  855. else
  856. {
  857. // Look up entry in current run
  858. // This path should go in line
  859. wpgd = pwcRun->apgd[swc];
  860. }
  861. // check to make sure in cache, insert if needed
  862. if ( wpgd == NULL )
  863. {
  864. // This path should go out of line
  865. if ( !bInsertMetricsPlus(&pwcRun->apgd[swc], *pwc) )
  866. {
  867. // when insert fails trying to get just metrics, it is a hard
  868. // failure. Get out of here!
  869. WARNING("bGetGlyphMetricsPlus - bInsertMetrics failed\n");
  870. return FALSE;
  871. }
  872. wpgd = pwcRun->apgd[swc];
  873. }
  874. // Try to ensure that the glyph bits are there, too.
  875. // Don't bother if we already are going to mess with the driver
  876. if ( (wpgd->gdf.pgb == NULL) && *pbAccel )
  877. {
  878. // this path should go out of line
  879. if ( (prfnt->ulContent != FO_HGLYPHS) &&
  880. !bInsertGlyphbits(wpgd, pwc == pwcInit) )
  881. {
  882. *pbAccel = 0;
  883. }
  884. }
  885. // set the pgp and go on to the next wc
  886. pgp->hg = wpgd->hg;
  887. pgp->pgdf = (GLYPHDEF *) wpgd;
  888. }
  889. return TRUE;
  890. }
  891. #pragma optimize("", on)
  892. /******************************Public*Routine******************************\
  893. * COUNT RFONTOBJ::cGetGlyphDataCache
  894. *
  895. * Run along an array of GLYPHPOS structures which have been filled in
  896. * by a call to bGetGlyphMetricsPlus. Fill in any missing pointers to
  897. * the glyph data in the referenced GLYPHDATA structures, filling the
  898. * cache as needed. If the cache is full, and we are not trying to get
  899. * the very first GLYPHDATA referenced by the array passed in, just return.
  900. *
  901. * If, on the other hand, we are still dealing with the first element of
  902. * the array, we needn't be concerned about invalidating the pointers in
  903. * the already worked on portion, so we can tell the glyph insertion routine
  904. * that it can flush the cache with impunity.
  905. *
  906. * This routine is to be used exclusively by the STROBJ_bEnum callback.
  907. *
  908. * Historical Note:
  909. * In the olden days, we were not so clever, and font caches had the
  910. * metrics for glyphs and the glyphs themselves joined together. This
  911. * had the unpleasant effect of invalidating the pointers in the
  912. * GLYPHPOS array in addition to invalidating the pointers in the
  913. * (discarded) GLYPHDATA structures in the font cache.
  914. *
  915. * Now that that is no longer the case, the callback does not need to
  916. * pass the string down to this routine, and we never have to do the
  917. * wchar->GLYPHPOS* translation twice! Isn't that nice?
  918. *
  919. * History:
  920. * 13-Nov-92 -by- Paul Butzi
  921. * Wrote it.
  922. \**************************************************************************/
  923. COUNT RFONTOBJ::cGetGlyphDataCache(
  924. COUNT c,
  925. GLYPHPOS *pgpStart
  926. )
  927. {
  928. if ( prfnt->ulContent == FO_HGLYPHS )
  929. return c;
  930. GLYPHPOS *pgpEnd = pgpStart + c;
  931. for ( GLYPHPOS *pgp = pgpStart; pgp < pgpEnd; pgp += 1 )
  932. {
  933. GLYPHDEF *pgdf = pgp->pgdf;
  934. ASSERTGDI(pgdf != NULL, "cGetGlyphDataCache - pgdf == NULL");
  935. // If the pointer is already valid, just move on
  936. if ( pgdf->pgb != NULL )
  937. continue;
  938. // If the insertion attempt fails, we're full
  939. // Sundown: safe to truncate to COUNT since pgpEnd = pgpStart + c
  940. if ( !bInsertGlyphbits( (GLYPHDATA*)(pgp->pgdf), pgp == pgpStart) )
  941. return (COUNT)(pgp - pgpStart);
  942. }
  943. // Sundown: safe to truncate to COUNT since pgpEnd = pgpStart + c
  944. return (COUNT)(pgp - pgpStart);
  945. }
  946. /******************************Public*Routine******************************\
  947. * COUNT RFONTOBJ::cGetGlyphDataLookaside
  948. *
  949. * For now, just handle the first entry.
  950. *
  951. * History:
  952. * 13-Nov-92 -by- Paul Butzi
  953. * Wrote it.
  954. \**************************************************************************/
  955. COUNT RFONTOBJ::cGetGlyphDataLookaside(
  956. COUNT c,
  957. GLYPHPOS *pgp
  958. )
  959. {
  960. if ( c == 0 )
  961. return 0;
  962. if ( !bInsertGlyphbitsLookaside(pgp, prfnt->ulContent))
  963. return 0;
  964. return 1;
  965. }
  966. /******************************Public*Routine******************************\
  967. * GPRUN * RFONTOBJ::gprunFindRun
  968. *
  969. * Given a wchar, run along the GPRUN structures and find the
  970. * entry which contains the char, if any. If not found, return pointer
  971. * to last run examined.
  972. *
  973. * History:
  974. * 13-Nov-92 -by- Paul Butzi
  975. * Wrote it.
  976. \**************************************************************************/
  977. GPRUN * RFONTOBJ::gprunFindRun(
  978. WCHAR wc
  979. )
  980. {
  981. ASSERTGDI(prfnt->wcgp != NULL, "xprunFindRunRFONTOBJ: wcgp is NULL\n");
  982. WCGP *pwcgp = prfnt->wcgp;
  983. // callers handle cRuns == 0 case
  984. ASSERTGDI(pwcgp->cRuns != 0, "pwcgp->cRuns is 0\n");
  985. if(!prfnt->cache.iMax)
  986. {
  987. GPRUN *pwcRunLow = pwcgp->agpRun;
  988. GPRUN *pwcRunHi = pwcgp->agpRun + (pwcgp->cRuns - 1);
  989. // The worst case case is pwcRunHi->wcLow == 0xffff and pwcRunHi->cGlyphs == 1
  990. UINT swc = (UINT)(pwcRunHi->wcLow + pwcRunHi->cGlyphs - 1);
  991. if (wc > swc) {
  992. return pwcRunLow;
  993. }
  994. for ( GPRUN *pwcRun = pwcRunLow; pwcRun <= pwcRunHi; pwcRun += 1 )
  995. {
  996. UINT nwc = wc - pwcRun->wcLow;
  997. if ( nwc < pwcRun->cGlyphs )
  998. {
  999. return pwcRun;
  1000. }
  1001. }
  1002. return pwcRunLow;
  1003. }
  1004. else
  1005. {
  1006. // do a binary search
  1007. int iThis, iMax;
  1008. GPRUN *pwcRun;
  1009. GPRUN *pwcRunBase = pwcgp->agpRun;
  1010. if( wc < pwcRunBase->wcLow)
  1011. {
  1012. return( pwcRunBase );
  1013. }
  1014. iThis = prfnt->cache.iFirst;
  1015. iMax = prfnt->cache.iMax;
  1016. switch( prfnt->cache.cBits )
  1017. {
  1018. case 16:
  1019. iThis += (wc >= pwcRunBase[iThis].wcLow) ? 32768 : 0;
  1020. iThis -= 16384;
  1021. case 15:
  1022. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 16384 : 0;
  1023. iThis -= 8192;
  1024. case 14:
  1025. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 8192 : 0;
  1026. iThis -= 4096;
  1027. case 13:
  1028. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 4096 : 0;
  1029. iThis -= 2048;
  1030. case 12:
  1031. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 2048 : 0;
  1032. iThis -= 1024;
  1033. case 11:
  1034. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 1024 : 0;
  1035. iThis -= 512;
  1036. case 10:
  1037. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 512 : 0;
  1038. iThis -= 256;
  1039. case 9:
  1040. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 256 : 0;
  1041. iThis -= 128;
  1042. case 8:
  1043. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 128 : 0;
  1044. iThis -= 64;
  1045. case 7:
  1046. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 64 : 0;
  1047. iThis -= 32;
  1048. case 6:
  1049. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 32 : 0;
  1050. iThis -= 16;
  1051. case 5:
  1052. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 16 : 0;
  1053. iThis -= 8;
  1054. case 4:
  1055. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 8 : 0;
  1056. iThis -= 4;
  1057. case 3:
  1058. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 4 : 0;
  1059. iThis -= 2;
  1060. case 2:
  1061. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 2 : 0;
  1062. iThis -= 1;
  1063. case 1:
  1064. iThis += ((iThis <= iMax) && (wc >= pwcRunBase[iThis].wcLow)) ? 1 : 0;
  1065. iThis -= 1;
  1066. case 0:
  1067. break;
  1068. }
  1069. pwcRun = &pwcRunBase[iThis]; // This is our candidate.
  1070. if( wc - pwcRun->wcLow >= (INT) pwcRun->cGlyphs )
  1071. {
  1072. return( pwcRunBase );
  1073. }
  1074. return( pwcRun );
  1075. }
  1076. }
  1077. /******************************Public*Routine******************************\
  1078. * BOOL xInsertMetricsRFONTOBJ
  1079. *
  1080. * Insert the requested glyph's metrics into the font cache.
  1081. *
  1082. * History:
  1083. * 13-Nov-92 -by- Paul Butzi
  1084. * Wrote it.
  1085. \**************************************************************************/
  1086. extern "C" BOOL xInsertMetricsRFONTOBJ
  1087. (
  1088. PRFONTOBJ pRfont,
  1089. GLYPHDATA **ppgd,
  1090. WCHAR wc
  1091. )
  1092. {
  1093. HGLYPH hg;
  1094. WCGP *pwcgp;
  1095. pwcgp = pRfont->prfnt->wcgp;
  1096. if (pRfont->prfnt->flType & RFONT_TYPE_UNICODE)
  1097. {
  1098. hg = pRfont->hgXlat(wc);
  1099. }
  1100. else
  1101. {
  1102. hg = (HGLYPH)wc; // here is the tiny speed advantage
  1103. }
  1104. // Make sure we don't insert the default glyph more than once.
  1105. // Just return the correct answer if we know it.
  1106. if
  1107. (
  1108. (hg == pRfont->prfnt->hgDefault)
  1109. && (pwcgp->pgdDefault != (GLYPHDATA *) NULL)
  1110. )
  1111. {
  1112. *ppgd = pwcgp->pgdDefault;
  1113. return(TRUE);
  1114. }
  1115. CACHE *pc = &pRfont->prfnt->cache;
  1116. // Verify enough room in metrics cache area, grow if needed.
  1117. // Note that failure to fit a glyphdata is a hard error, get out now.
  1118. if (!pRfont->bCheckMetricsCache())
  1119. {
  1120. WARNING("xInsertMetricsRFONTOBJ - bCheckMetricsCache failed!\n");
  1121. return FALSE;
  1122. }
  1123. ASSERTGDI(pc->pgdNext < pc->pgdThreshold,
  1124. "xInsertMetricsRFONTOBJ - no room in cache\n");
  1125. // These constructors used to be in the calling routine - cGet*****
  1126. // That was the wrong place because we anticipate many calls that never
  1127. // miss the cache. Better to have them here and lock on every miss.
  1128. PDEVOBJ pdo(pRfont->prfnt->hdevProducer);
  1129. // Call font driver to get the metrics.
  1130. ULONG ulMode = QFD_GLYPHANDBITMAP;
  1131. if ( pRfont->prfnt->ulContent == FO_PATHOBJ )
  1132. {
  1133. ulMode = QFD_GLYPHANDOUTLINE;
  1134. }
  1135. GLYPHDATA gd;
  1136. if (pdo.QueryFontData(
  1137. pRfont->prfnt->dhpdev,
  1138. pRfont->pfo(),
  1139. ulMode,
  1140. hg,
  1141. pRfont->bSmallMetrics() ? &gd : pc->pgdNext,
  1142. NULL,
  1143. 0) == FD_ERROR)
  1144. {
  1145. WARNING("xInsertMetricsRFONTOBJ: QueryFontData failed\n");
  1146. return FALSE;
  1147. }
  1148. if (pRfont->bSmallMetrics())
  1149. COPYSMALLMETRICS(pc->pgdNext, &gd);
  1150. ASSERTGDI(pc->pgdNext->hg == hg, "xInsertMetricsRFONTOBJ - hg not set\n");
  1151. pc->pgdNext->gdf.pgb = NULL;
  1152. // Set returned value, adjust cache, indicate success
  1153. *ppgd = pc->pgdNext;
  1154. if( pRfont->bSmallMetrics() )
  1155. {
  1156. pc->pgdNext = (GLYPHDATA*) (((BYTE*) pc->pgdNext ) + offsetof(GLYPHDATA,fxInkTop));
  1157. }
  1158. else
  1159. {
  1160. pc->pgdNext += 1;
  1161. }
  1162. #if DBG
  1163. pc->cMetrics += 1;
  1164. #endif
  1165. return TRUE;
  1166. }
  1167. ULONG ulClearTypeFilter(GLYPHBITS *pgb, GLYPHDATA *pgd, PRFONT prfnt);
  1168. /******************************Public*Routine******************************\
  1169. * BOOL xInsertMetricsPlusRFONTOBJ
  1170. *
  1171. * Insert the requested glyph's metrics into the font cache.
  1172. * In addition, try to get the glyph data, too, but don't flush the
  1173. * cache to try to get them.
  1174. *
  1175. * History:
  1176. * 13-Nov-92 -by- Paul Butzi
  1177. * Wrote it.
  1178. \**************************************************************************/
  1179. extern "C" BOOL xInsertMetricsPlusRFONTOBJ(
  1180. PRFONTOBJ pRfont,
  1181. GLYPHDATA **ppgd,
  1182. WCHAR wc
  1183. )
  1184. {
  1185. HGLYPH hg;
  1186. WCGP *pwcgp;
  1187. pwcgp = pRfont->prfnt->wcgp;
  1188. if (pRfont->prfnt->flType & RFONT_TYPE_UNICODE)
  1189. {
  1190. hg = pRfont->hgXlat(wc);
  1191. }
  1192. else
  1193. {
  1194. hg = (HGLYPH)wc; // here is the tiny speed advantage
  1195. }
  1196. // Make sure we don't insert the default glyph more than once.
  1197. // Just return the correct answer if we know it.
  1198. if
  1199. (
  1200. (hg == pRfont->prfnt->hgDefault)
  1201. && (pwcgp->pgdDefault != (GLYPHDATA *) NULL)
  1202. )
  1203. {
  1204. *ppgd = pwcgp->pgdDefault;
  1205. return(TRUE);
  1206. }
  1207. CACHE *pc = &pRfont->prfnt->cache;
  1208. // If only getting hglyphs, use bInsertMetrics
  1209. if (pRfont->prfnt->ulContent == FO_HGLYPHS)
  1210. {
  1211. return pRfont->bInsertMetrics(ppgd, wc);
  1212. }
  1213. // Verify enough room in metrics cache area, grow if needed.
  1214. // Note that failure to fit a glyphdata is a hard error, get out now.
  1215. if (!pRfont->bCheckMetricsCache())
  1216. {
  1217. WARNING("bInsertMetricsPlus - bCheckMetricsCache failed!\n");
  1218. return FALSE;
  1219. }
  1220. ASSERTGDI(pc->pgdNext < pc->pgdThreshold,
  1221. "bInsertMetricsPlus - no room in cache\n");
  1222. // Handle paths somewhere else!
  1223. if ( pRfont->prfnt->ulContent == FO_PATHOBJ )
  1224. {
  1225. return pRfont->bInsertMetricsPlusPath(ppgd, wc);
  1226. }
  1227. // These constructors used to be in the calling routine - cGet*****
  1228. // That was the wrong place because we anticipate many calls that never
  1229. // miss the cache. Better to have them here and lock on every miss.
  1230. PDEVOBJ pdo(pRfont->prfnt->hdevProducer);
  1231. // Look to see if there is room in the glyphbits cache
  1232. // Grow the glyphbits cache if neccessary, but don't flush the cache
  1233. ULONG cjNeeded;
  1234. GLYPHDATA gd;
  1235. // If mode is paths, or max glyph will fit, assume max glyph
  1236. // otherwise, call up and ask how big
  1237. if (pc->cjGlyphMax < (SIZE_T)(pc->pgbThreshold - pc->pgbNext))
  1238. {
  1239. cjNeeded = pc->cjGlyphMax;
  1240. }
  1241. else
  1242. {
  1243. cjNeeded = pdo.QueryFontData(
  1244. pRfont->prfnt->dhpdev,
  1245. pRfont->pfo(),
  1246. QFD_GLYPHANDBITMAP,
  1247. hg,
  1248. &gd,
  1249. NULL,
  1250. 0);
  1251. if ( cjNeeded == FD_ERROR )
  1252. {
  1253. WARNING("bInsertGlyphMetricsPlus - qfd for size failed\n");
  1254. return FALSE;
  1255. }
  1256. if (pRfont->pfo()->flFontType & FO_CLEARTYPE_X)
  1257. {
  1258. ULONG cx = (ULONG)(gd.rclInk.right - gd.rclInk.left);
  1259. ULONG cy = (ULONG)(gd.rclInk.bottom - gd.rclInk.top);
  1260. cjNeeded = CJ_CTGD(cx+2,cy);
  1261. }
  1262. }
  1263. // We will try to fit the glyphbits in. If they fit, they'll go
  1264. // in at pc->pgbNext, so we set that as the default.
  1265. // If they won't fit, we'll set the pointer to null to avoid getting
  1266. // the bits
  1267. VOID *pgb = pRfont->pgbCheckGlyphCache(cjNeeded);
  1268. GLYPHDATA *pgd = pRfont->bSmallMetrics() ? &gd : pc->pgdNext;
  1269. // Call font driver to get the metrics.
  1270. cjNeeded = pdo.QueryFontData(
  1271. pRfont->prfnt->dhpdev,
  1272. pRfont->pfo(),
  1273. QFD_GLYPHANDBITMAP,
  1274. hg,
  1275. pgd,
  1276. pgb,
  1277. cjNeeded);
  1278. if ( cjNeeded == FD_ERROR )
  1279. {
  1280. WARNING("bInsertGlyphMetricsPlus - qfd for data failed\n");
  1281. return FALSE;
  1282. }
  1283. // need to add CLEARTYPE filtering correction again:
  1284. if (pRfont->pfo()->flFontType & FO_CLEARTYPE_X)
  1285. {
  1286. ULONG cx = (ULONG)(pgd->rclInk.right - pgd->rclInk.left);
  1287. ULONG cy = (ULONG)(pgd->rclInk.bottom - pgd->rclInk.top);
  1288. cjNeeded = CJ_CTGD(cx+2,cy);
  1289. if (pgb)
  1290. {
  1291. cjNeeded = ulClearTypeFilter((GLYPHBITS *)pgb, pgd, pRfont->prfnt);
  1292. }
  1293. }
  1294. #if DBG
  1295. if (pgb)
  1296. {
  1297. //TRACE_INSERT(("xInsertMetricsPlus: inserted hg = 0x%lx, cj = 0x%lx at pgbNext: 0x%lx\n", hg, cjNeeded, pgb));
  1298. }
  1299. else
  1300. {
  1301. TRACE_INSERT(("xInsertMetricsPlus: cound not insert hg = 0x%lx, cj = 0x%lx\n", hg, cjNeeded));
  1302. }
  1303. #endif
  1304. if (pRfont->bSmallMetrics())
  1305. COPYSMALLMETRICS(pc->pgdNext, &gd);
  1306. ASSERTGDI(pc->pgdNext->hg == hg, "bInsertMetricsPlus - hg not set\n");
  1307. ASSERTGDI(pc->pgdNext->gdf.pgb == pgb, "bInsertMetricsPlus - pgb not set\n");
  1308. // Set the returned value
  1309. *ppgd = pc->pgdNext;
  1310. // Adjust the cache next pointers as needed.
  1311. if (pRfont->bSmallMetrics())
  1312. {
  1313. pc->pgdNext = (GLYPHDATA*)(((BYTE*)pc->pgdNext) + offsetof(GLYPHDATA,fxInkTop));
  1314. }
  1315. else
  1316. {
  1317. pc->pgdNext += 1;
  1318. }
  1319. #if DBG
  1320. pc->cMetrics += 1;
  1321. #endif
  1322. if ( pgb != NULL )
  1323. {
  1324. pc->pgbNext += cjNeeded;
  1325. #if DBG
  1326. pc->cGlyphs += 1;
  1327. pc->cjTotal += cjNeeded;
  1328. #endif
  1329. }
  1330. return TRUE;
  1331. }
  1332. /******************************Public*Routine******************************\
  1333. * BOOL bInsertMetricsPlusPath
  1334. *
  1335. * Insert the requested glyph's metrics into the font cache.
  1336. * In addition, try to get the glyph data, too, but don't flush the
  1337. * cache to try to get them.
  1338. *
  1339. * History:
  1340. * 13-Nov-92 -by- Paul Butzi
  1341. * Wrote it.
  1342. \**************************************************************************/
  1343. BOOL RFONTOBJ::bInsertMetricsPlusPath(
  1344. GLYPHDATA **ppgd,
  1345. WCHAR wc
  1346. )
  1347. {
  1348. HGLYPH hg;
  1349. CACHE *pc = &prfnt->cache;
  1350. if (prfnt->wcgp == NULL)
  1351. {
  1352. if (!bAllocateCache())
  1353. {
  1354. return(FALSE);
  1355. }
  1356. }
  1357. if (prfnt->flType & RFONT_TYPE_UNICODE)
  1358. {
  1359. hg = hgXlat(wc);
  1360. }
  1361. else
  1362. {
  1363. hg = (HGLYPH)wc; // here is the tiny speed advantage
  1364. }
  1365. // These constructors used to be in the calling routine - cGet*****
  1366. // That was the wrong place because we anticipate many calls that never
  1367. // miss the cache. Better to have them here and lock on every miss.
  1368. PDEVOBJ pdo(prfnt->hdevProducer);
  1369. PATHMEMOBJ pmo;
  1370. if (!pmo.bValid())
  1371. return(FALSE);
  1372. // Call font driver to get the metrics.
  1373. GLYPHDATA gd;
  1374. ULONG cjNeeded = pdo.QueryFontData(
  1375. prfnt->dhpdev,
  1376. pfo(),
  1377. QFD_GLYPHANDOUTLINE,
  1378. hg,
  1379. bSmallMetrics() ? &gd : pc->pgdNext,
  1380. &pmo,
  1381. 0);
  1382. if ( cjNeeded == FD_ERROR )
  1383. return FALSE;
  1384. if (bSmallMetrics())
  1385. COPYSMALLMETRICS(pc->pgdNext, &gd);
  1386. PDEVOBJ pdoCon(prfnt->hdevConsumer);
  1387. // Don't cache bezier glyphs for display drivers even if GCAPS_BEZIERS is
  1388. // set because dynamic mode changes may cause this capability to change at
  1389. // any time.
  1390. if ( (pdo.bDisplayPDEV()) ||
  1391. ((pdo.flGraphicsCaps() & GCAPS_BEZIERS) == 0) )
  1392. {
  1393. if (!pmo.bFlatten())
  1394. return FALSE;
  1395. }
  1396. ASSERTGDI(pc->pgdNext->hg == hg, "bInsertMetricsPlus - hg not set\n");
  1397. cjNeeded = offsetof(EPATHFONTOBJ, pa.apr) + pmo.cjSize();
  1398. VOID *pgb = pgbCheckGlyphCache(cjNeeded);
  1399. if ( pgb != NULL )
  1400. {
  1401. EPATHFONTOBJ *epfo = (EPATHFONTOBJ *)pgb;
  1402. epfo->vInit(cjNeeded);
  1403. epfo->bClone(pmo);
  1404. pc->pgdNext->gdf.ppo = (PATHOBJ *)epfo;
  1405. }
  1406. else
  1407. {
  1408. pc->pgdNext->gdf.ppo = NULL;
  1409. }
  1410. // Set the returned value
  1411. *ppgd = pc->pgdNext;
  1412. // Adjust the cache next pointers as needed.
  1413. if( prfnt->cache.bSmallMetrics )
  1414. {
  1415. pc->pgdNext = (GLYPHDATA*)(((BYTE*)pc->pgdNext) + offsetof(GLYPHDATA,fxInkTop));
  1416. }
  1417. else
  1418. {
  1419. pc->pgdNext += 1;
  1420. }
  1421. #if DBG
  1422. pc->cMetrics += 1;
  1423. #endif
  1424. if ( pgb != NULL )
  1425. {
  1426. pc->pgbNext += cjNeeded;
  1427. #if DBG
  1428. pc->cGlyphs += 1;
  1429. pc->cjTotal += cjNeeded;
  1430. #endif
  1431. }
  1432. return TRUE;
  1433. }
  1434. /******************************Public*Routine******************************\
  1435. * BOOL xInsertGlyphbitsRFONTOBJ
  1436. *
  1437. * Insert the requested glyph into the glyph cache
  1438. *
  1439. * History:
  1440. * 13-Nov-92 -by- Paul Butzi
  1441. * Wrote it.
  1442. \**************************************************************************/
  1443. extern "C" BOOL xInsertGlyphbitsRFONTOBJ(
  1444. PRFONTOBJ pRfont,
  1445. GLYPHDATA *pgd,
  1446. ULONG bFlushOk
  1447. )
  1448. {
  1449. CACHE *pc = &pRfont->prfnt->cache;
  1450. if ( (pRfont->prfnt->flType & RFONT_TYPE_NOCACHE) ||
  1451. (pRfont->prfnt->ulContent == FO_HGLYPHS) )
  1452. {
  1453. return FALSE;
  1454. }
  1455. if ( pRfont->prfnt->ulContent == FO_PATHOBJ )
  1456. return pRfont->bInsertGlyphbitsPath(pgd, bFlushOk);
  1457. PDEVOBJ pdo(pRfont->prfnt->hdevProducer);
  1458. // Look to see if there is room in the glyphbits cache
  1459. // Grow the glyphbits cache if neccessary, but don't flush the cache
  1460. ULONG cjNeeded;
  1461. // If max glyph will fit, assume max glyph
  1462. // otherwise, call up and ask how big
  1463. GLYPHDATA gd;
  1464. if ( (pc->cjGlyphMax < (SIZE_T)(pc->pgbThreshold - pc->pgbNext)) )
  1465. {
  1466. cjNeeded = pc->cjGlyphMax;
  1467. }
  1468. else
  1469. {
  1470. cjNeeded = pdo.QueryFontData(
  1471. pRfont->prfnt->dhpdev,
  1472. pRfont->pfo(),
  1473. QFD_GLYPHANDBITMAP,
  1474. pgd->hg,
  1475. &gd,
  1476. NULL,
  1477. 0);
  1478. if ( cjNeeded == FD_ERROR )
  1479. return FALSE;
  1480. if (pRfont->pfo()->flFontType & FO_CLEARTYPE_X)
  1481. {
  1482. ULONG cx = (ULONG)(gd.rclInk.right - gd.rclInk.left);
  1483. ULONG cy = (ULONG)(gd.rclInk.bottom - gd.rclInk.top);
  1484. cjNeeded = CJ_CTGD(cx+2,cy);
  1485. }
  1486. }
  1487. // Now, we try to fit the bits in. If they fit, fine.
  1488. // If not, and we can flush the cache, we flush it and try again.
  1489. // If we couldn't flush, or we flushed and still fail, just return.
  1490. GLYPHBITS *pgb;
  1491. TRACE_INSERT(("InsertGlyphbits: attempting to insert bits at: 0x%lx\n", pc->pgbNext));
  1492. while ((pgb = (GLYPHBITS *)pRfont->pgbCheckGlyphCache(cjNeeded)) == NULL)
  1493. {
  1494. if ( !bFlushOk )
  1495. return FALSE;
  1496. TRACE_INSERT(("InsertGlyphbits: Flushing the cache\n"));
  1497. pRfont->vFlushCache();
  1498. bFlushOk = FALSE;
  1499. }
  1500. // Call font driver to get the metrics.
  1501. cjNeeded = pdo.QueryFontData(
  1502. pRfont->prfnt->dhpdev,
  1503. pRfont->pfo(),
  1504. QFD_GLYPHANDBITMAP,
  1505. pgd->hg,
  1506. &gd,
  1507. (VOID *)pgb,
  1508. cjNeeded);
  1509. if ( cjNeeded == FD_ERROR )
  1510. return FALSE;
  1511. if (pRfont->pfo()->flFontType & FO_CLEARTYPE_X)
  1512. {
  1513. ULONG cx = (ULONG)(gd.rclInk.right - gd.rclInk.left);
  1514. ULONG cy = (ULONG)(gd.rclInk.bottom - gd.rclInk.top);
  1515. cjNeeded = CJ_CTGD(cx+2,cy);
  1516. if (pgb)
  1517. {
  1518. cjNeeded = ulClearTypeFilter(pgb, &gd, pRfont->prfnt);
  1519. }
  1520. }
  1521. #if DBG
  1522. if(cjNeeded > pc->cjGlyphMax)
  1523. {
  1524. DbgPrint("cjNeeded = %x cjGlyphmax = %x\n", cjNeeded, pc->cjGlyphMax);
  1525. DbgBreakPoint();
  1526. }
  1527. #endif
  1528. TRACE_INSERT(("InsertGlyphbits: inserted hg = 0x%lx, cj = 0x%lx at pgbNext: 0x%lx\n", pgd->hg, cjNeeded, pc->pgbNext));
  1529. // Set the returned value
  1530. pgd->gdf.pgb = pgb;
  1531. // Adjust the cache next pointers as needed.
  1532. pc->pgbNext += cjNeeded;
  1533. #if DBG
  1534. pc->cGlyphs += 1;
  1535. pc->cjTotal += cjNeeded;
  1536. #endif
  1537. return TRUE;
  1538. }
  1539. /******************************Public*Routine******************************\
  1540. * BOOL bInsertGlyphbitsPath
  1541. *
  1542. * Insert the requested glyph into the glyph cache
  1543. *
  1544. * History:
  1545. * 13-Nov-92 -by- Paul Butzi
  1546. * Wrote it.
  1547. \**************************************************************************/
  1548. BOOL RFONTOBJ::bInsertGlyphbitsPath(
  1549. GLYPHDATA *pgd,
  1550. ULONG bFlushOk
  1551. )
  1552. {
  1553. CACHE *pc = &prfnt->cache;
  1554. ASSERTGDI(prfnt->wcgp != NULL, "bInsertGlyphbitsPath: wcgp is NULL\n");
  1555. ASSERTGDI(!(prfnt->flType & RFONT_TYPE_NOCACHE),
  1556. "bInsertGlyphbitsPath: NOCACHE cache type\n");
  1557. // These constructors used to be in the calling routine - cGet*****
  1558. // That was the wrong place because we anticipate many calls that never
  1559. // miss the cache. Better to have them here and lock on every miss.
  1560. PDEVOBJ pdo(prfnt->hdevProducer);
  1561. PATHMEMOBJ pmo;
  1562. if (!pmo.bValid())
  1563. {
  1564. return FALSE; // MEMORY ALLOC FAILED, HMGR routines log error code
  1565. }
  1566. // Call font driver to get the path
  1567. ULONG cjNeeded = pdo.QueryFontData(
  1568. prfnt->dhpdev,
  1569. pfo(),
  1570. QFD_GLYPHANDOUTLINE,
  1571. pgd->hg,
  1572. (GLYPHDATA *)NULL,
  1573. &pmo,
  1574. 0);
  1575. if ( cjNeeded == FD_ERROR )
  1576. return FALSE;
  1577. PDEVOBJ pdoCon(prfnt->hdevConsumer);
  1578. // Don't cache bezier glyphs for display drivers even if GCAPS_BEZIERS is
  1579. // set because dynamic mode changes may cause this capability to change at
  1580. // any time.
  1581. if ( (pdoCon.bDisplayPDEV()) ||
  1582. ((pdoCon.flGraphicsCaps() & GCAPS_BEZIERS) == 0) )
  1583. {
  1584. if (!pmo.bFlatten())
  1585. return FALSE;
  1586. }
  1587. cjNeeded = offsetof(EPATHFONTOBJ, pa.apr) + pmo.cjSize();
  1588. // Now, we try to fit the bits in. If they fit, fine.
  1589. // If not, and we can flush the cache, we flush it and try again.
  1590. // If we couldn't flush, or we flushed and still fail, just return.
  1591. VOID *pgb;
  1592. while ( (pgb = pgbCheckGlyphCache(cjNeeded)) == NULL )
  1593. {
  1594. if ( !bFlushOk )
  1595. return FALSE;
  1596. vFlushCache();
  1597. bFlushOk = FALSE;
  1598. }
  1599. EPATHFONTOBJ *epfo = (EPATHFONTOBJ *)pgb;
  1600. epfo->vInit(cjNeeded);
  1601. epfo->bClone(pmo);
  1602. // Set the returned value
  1603. pgd->gdf.ppo = (PATHOBJ *)epfo;
  1604. // Adjust the cache next pointers as needed.
  1605. pc->pgbNext += cjNeeded;
  1606. #if DBG
  1607. pc->cGlyphs += 1;
  1608. pc->cjTotal += cjNeeded;
  1609. #endif
  1610. return TRUE;
  1611. }
  1612. /******************************Public*Routine******************************\
  1613. * BOOL RFONTOBJ::bInsertGlyphbitsLookaside
  1614. *
  1615. * Get the glyph bits into the lookaside buffer
  1616. *
  1617. * History:
  1618. * 13-Nov-92 -by- Paul Butzi
  1619. * Wrote it.
  1620. \**************************************************************************/
  1621. BOOL RFONTOBJ::bInsertGlyphbitsLookaside(
  1622. GLYPHPOS *pgp,
  1623. ULONG imode
  1624. )
  1625. {
  1626. if ( imode == FO_PATHOBJ )
  1627. return bInsertPathLookaside(pgp);
  1628. CACHE *pc = &prfnt->cache;
  1629. // Make sure the lookaside buffer has enough room for the bitmap
  1630. ULONGSIZE_T cjMaxBitmap = prfnt->cjGlyphMax + sizeof(GLYPHDATA);
  1631. // ensure that cjGlyphMax > offsetof(GLYPHBITS,aj) and that
  1632. // the cjMaxBitmap calculation didn't overflow
  1633. if ( cjMaxBitmap < sizeof(GLYPHDATA)+ offsetof(GLYPHBITS,aj) )
  1634. {
  1635. WARNING("bGetGlyphbitsLookaside - cjGlyphMax invalid\n");
  1636. return FALSE;
  1637. }
  1638. // Allocate the buffer and save its size if existing buffer isn't big enough
  1639. if( prfnt->cache.cjAuxCacheMem < cjMaxBitmap )
  1640. {
  1641. if ( prfnt->cache.pjAuxCacheMem != NULL )
  1642. {
  1643. VFREEMEM(prfnt->cache.pjAuxCacheMem);
  1644. }
  1645. prfnt->cache.pjAuxCacheMem = (PBYTE)PALLOCMEM(cjMaxBitmap, 'cacG');
  1646. if ( prfnt->cache.pjAuxCacheMem == NULL )
  1647. {
  1648. prfnt->cache.cjAuxCacheMem = 0;
  1649. WARNING("bGetGlyphbitsLookaside - error allocating buffer\n");
  1650. return FALSE;
  1651. }
  1652. prfnt->cache.cjAuxCacheMem = cjMaxBitmap;
  1653. }
  1654. GLYPHDATA *pgd = (GLYPHDATA *)prfnt->cache.pjAuxCacheMem;
  1655. GLYPHBITS *pgb = (GLYPHBITS *)(pgd + 1);
  1656. // Call font driver to get the metrics.
  1657. PDEVOBJ pdo(prfnt->hdevProducer);
  1658. ULONG cjNeeded = pdo.QueryFontData(
  1659. prfnt->dhpdev,
  1660. pfo(),
  1661. QFD_GLYPHANDBITMAP,
  1662. pgp->hg,
  1663. pgd,
  1664. (VOID *)pgb,
  1665. prfnt->cjGlyphMax);
  1666. if ( cjNeeded == FD_ERROR )
  1667. return FALSE;
  1668. if (pfo()->flFontType & FO_CLEARTYPE_X)
  1669. {
  1670. ULONG cx = (ULONG)(pgd->rclInk.right - pgd->rclInk.left);
  1671. ULONG cy = (ULONG)(pgd->rclInk.bottom - pgd->rclInk.top);
  1672. cjNeeded = CJ_CTGD(cx+2,cy);
  1673. if (pgb)
  1674. {
  1675. cjNeeded = ulClearTypeFilter(pgb, pgd, prfnt);
  1676. }
  1677. }
  1678. #if DBG
  1679. if(cjNeeded > pc->cjGlyphMax)
  1680. {
  1681. KdPrint(("cjNeeded = %x cjGlyphmax = %x\n", cjNeeded, pc->cjGlyphMax));
  1682. DbgBreakPoint();
  1683. }
  1684. #endif
  1685. // Set the returned value
  1686. pgp->pgdf = (GLYPHDEF *)pgd;
  1687. pgd->gdf.pgb = pgb;
  1688. return TRUE;
  1689. }
  1690. /******************************Public*Routine******************************\
  1691. * BOOL RFONTOBJ::bInsertPathLookaside
  1692. *
  1693. * Get the glyph bits into the lookaside buffer
  1694. *
  1695. * History:
  1696. * 13-Nov-92 -by- Paul Butzi
  1697. * Wrote it.
  1698. \**************************************************************************/
  1699. BOOL RFONTOBJ::bInsertPathLookaside(
  1700. GLYPHPOS *pgp,
  1701. BOOL bFlatten
  1702. )
  1703. {
  1704. CACHE *pc = &prfnt->cache;
  1705. PDEVOBJ pdo(prfnt->hdevProducer);
  1706. GLYPHDATA gdTemp;
  1707. PATHMEMOBJ pmo;
  1708. if (!pmo.bValid())
  1709. return(FALSE);
  1710. // Call font driver to get the path
  1711. ULONG cjNeeded = pdo.QueryFontData(
  1712. prfnt->dhpdev,
  1713. pfo(),
  1714. QFD_GLYPHANDOUTLINE,
  1715. pgp->hg,
  1716. &gdTemp,
  1717. &pmo,
  1718. 0);
  1719. if ( cjNeeded == FD_ERROR )
  1720. return FALSE;
  1721. PDEVOBJ pdoCon(prfnt->hdevConsumer);
  1722. // Don't cache bezier glyphs for display drivers even if GCAPS_BEZIERS is
  1723. // set because dynamic mode changes may cause this capability to change at
  1724. // any time.
  1725. if ( ((pdoCon.bDisplayPDEV()) ||
  1726. ((pdoCon.flGraphicsCaps() & GCAPS_BEZIERS) == 0))
  1727. && bFlatten )
  1728. {
  1729. if (!pmo.bFlatten())
  1730. return FALSE;
  1731. }
  1732. cjNeeded = sizeof(GLYPHDATA) + offsetof(EPATHFONTOBJ, pa.apr) + pmo.cjSize();
  1733. // Make sure the lookaside buffer is allocated
  1734. if ( ( prfnt->cache.cjAuxCacheMem < cjNeeded ) &&
  1735. ( prfnt->cache.pjAuxCacheMem != NULL ))
  1736. {
  1737. #if DBG
  1738. IFIOBJ ifio(prfnt->ppfe->pifi);
  1739. TRACE_CACHE((
  1740. " -- TRACE_CACHE --\n"
  1741. " RFONTOBJ::bInsertPathLookaside\n"
  1742. " FaceName = \"%ws\"\n"
  1743. " ExFreePool\n"
  1744. " cache.pjAuxCacheMem = %-#x\n",
  1745. ifio.pwszFaceName(),
  1746. prfnt->cache.pjAuxCacheMem
  1747. ))
  1748. #endif
  1749. VFREEMEM((PVOID) prfnt->cache.pjAuxCacheMem);
  1750. prfnt->cache.pjAuxCacheMem = NULL;
  1751. prfnt->cache.cjAuxCacheMem = 0;
  1752. }
  1753. if ( prfnt->cache.pjAuxCacheMem == NULL )
  1754. {
  1755. prfnt->cache.pjAuxCacheMem = (PBYTE)PALLOCMEM(cjNeeded, 'cacG');
  1756. if ( prfnt->cache.pjAuxCacheMem == NULL )
  1757. {
  1758. WARNING("bGetGlyphbitsLookaside - error allocating buffer\n");
  1759. return FALSE;
  1760. }
  1761. prfnt->cache.cjAuxCacheMem = cjNeeded;
  1762. #if DBG
  1763. IFIOBJ ifio(prfnt->ppfe->pifi);
  1764. TRACE_CACHE((
  1765. " -- TRACE_CACHE --\n"
  1766. " RFONTOBJ::bInsertPathLookaside\n"
  1767. " FaceName = \"%ws\"\n"
  1768. " ExAllocatePoolWithTag\n"
  1769. " tag = Gcac\n"
  1770. " size = %-#x\n"
  1771. " cache.pjAuxCacheMem = %-#x\n",
  1772. ifio.pwszFaceName(),
  1773. cjNeeded,
  1774. prfnt->cache.pjAuxCacheMem
  1775. ));
  1776. #endif
  1777. }
  1778. GLYPHDATA *pgd = (GLYPHDATA *)prfnt->cache.pjAuxCacheMem;
  1779. EPATHFONTOBJ *epfo = (EPATHFONTOBJ *)(pgd + 1);
  1780. epfo->vInit(cjNeeded - sizeof(GLYPHDATA));
  1781. epfo->bClone(pmo);
  1782. // Set the returned value
  1783. *pgd = gdTemp;
  1784. pgp->pgdf = (GLYPHDEF *)pgd;
  1785. pgd->gdf.ppo = epfo;
  1786. return TRUE;
  1787. }
  1788. /******************************Public*Routine******************************\
  1789. * BOOL bCheckMetrics *
  1790. * *
  1791. * Make sure there's enough room for a GLYPHDATA in the metrics part of the *
  1792. * cache. Return FALSE if we failed to do so. *
  1793. * *
  1794. * History: *
  1795. * 25-Nov-92 -by- Paul Butzi *
  1796. * Wrote it. *
  1797. \**************************************************************************/
  1798. BOOL RFONTOBJ::bCheckMetricsCache()
  1799. {
  1800. CACHE *pc = &prfnt->cache;
  1801. ASSERTGDI(prfnt->wcgp != NULL, "bCheckMetricsCache: wcgp is NULL\n");
  1802. // Verify enough room in metrics cache area, grow if needed.
  1803. if ( ( bSmallMetrics() ?
  1804. ((GLYPHDATA*) ((BYTE*)(pc->pgdNext) + offsetof(GLYPHDATA,fxInkTop))) :
  1805. (pc->pgdNext + 1) ) > pc->pgdThreshold )
  1806. {
  1807. DATABLOCK *pdbl;
  1808. // allocate a new block of GLYPHDATA structs
  1809. if ((pdbl = (DATABLOCK*)PALLOCNOZ(GD_INC, 'cacG')) == (DATABLOCK*)NULL)
  1810. {
  1811. return(FALSE);
  1812. }
  1813. #if DBG
  1814. IFIOBJ ifio(prfnt->ppfe->pifi);
  1815. TRACE_CACHE((
  1816. " -- TRACE_CACHE --\n"
  1817. " RFONTOBJ::bCheckMetrics\n"
  1818. " FaceName = \"%ws\"\n"
  1819. " ExAllocatePoolWithTag\n"
  1820. " tag = Gcac\n"
  1821. " size = %-#x\n"
  1822. " cache.pdblBase = %-#x\n",
  1823. ifio.pwszFaceName(),
  1824. GD_INC,
  1825. pdbl
  1826. ));
  1827. #endif
  1828. // insert this block into the chain of GLYPHDATA blocks
  1829. pdbl->pdblNext = pc->pdblBase;
  1830. pc->pdblBase = pdbl;
  1831. pc->pgdThreshold = (GLYPHDATA*) ((BYTE *)pdbl + GD_INC);
  1832. pc->pgdNext = &pdbl->agd[0];
  1833. }
  1834. ASSERTGDI((( bSmallMetrics() ?
  1835. (GLYPHDATA*) ((BYTE*)(pc->pgdNext) + offsetof(GLYPHDATA,fxInkTop)) :
  1836. (pc->pgdNext + 1)) <= pc->pgdThreshold),
  1837. "bInsertMetrics - no room in cache\n" );
  1838. return TRUE;
  1839. }
  1840. /******************************Public*Routine******************************\
  1841. * PVOID pgbCheckGlyphCache
  1842. *
  1843. * Make sure there's enough room for a glyph in the glyph part of the
  1844. * cache. Return NULL if we failed to do so.
  1845. *
  1846. * History:
  1847. * 25-Nov-92 -by- Paul Butzi
  1848. * Wrote it.
  1849. \**************************************************************************/
  1850. PVOID RFONTOBJ::pgbCheckGlyphCache( SIZE_T cjNeeded )
  1851. {
  1852. CACHE *pc = &prfnt->cache;
  1853. ASSERTGDI(prfnt->wcgp != NULL, "pgbCheckGlyphCache: wcgp is NULL\n");
  1854. if ((pc->pgbNext + cjNeeded) > pc->pgbThreshold)
  1855. {
  1856. // there are two possible situations that can arise here.
  1857. // One is that there already is a block allocated, following the pbblCur
  1858. // in the linked list, which is presently unused. This would be the case
  1859. // after the cache was flushed and then partially refilled.
  1860. // The other possible situation is that the pbblCur is
  1861. // the last block allocated and we have to allocate
  1862. // another block if we are allowed to, i.e. if the total
  1863. // number of blocks is not exceeding cBlocksMax.
  1864. BITBLOCK *pbblNext;
  1865. if (pc->pbblCur && (pbblNext = pc->pbblCur->pbblNext))
  1866. {
  1867. TRACE_INSERT(("pgbCheckGlyphCache:Inserting into existing block at 0x%lx\n", pbblNext));
  1868. pc->pbblCur = pbblNext;
  1869. pc->pgbNext = pc->pbblCur->ajBits;
  1870. // we do not want to use the last 8 bytes in the BITBLOCK. Some drivers
  1871. // read the last dword (or quadword) past the end of the GLYPHBITS.
  1872. // If there is a GLYPHBITS at the very and of the BITBLOCK AND the
  1873. // allocation happens to be at the end of the page the read will AV.
  1874. pc->pgbThreshold = (PBYTE)pc->pbblCur + pc->cjbbl - sizeof(double);
  1875. ASSERTGDI(pc->cBlocks == pc->cBlocksMax,
  1876. "Glyphbits logic wrong, cBlocks ??? \n");
  1877. }
  1878. else
  1879. {
  1880. ULONG cjBlockSize = (pc->cBlocks == 0) ?
  1881. pc->cjbblInitial : pc->cjbbl;
  1882. if
  1883. (
  1884. !(prfnt->flType & RFONT_TYPE_NOCACHE) &&
  1885. (pc->cBlocks < pc->cBlocksMax) &&
  1886. ((offsetof(BITBLOCK,ajBits) + cjNeeded) <= cjBlockSize)
  1887. )
  1888. {
  1889. // The only reason we need the last check is the PATHOBJ case
  1890. // where cjNeeded may actually not fit in the block of cjbbl bytes.
  1891. // This is because we have no way of knowing how big the paths
  1892. // are going to be (especailly after doing bFlatten) and our
  1893. // pc->cjGlyphMax is just a good guess in this case.
  1894. // We are going to append another block at the end of the list
  1895. pbblNext = (BITBLOCK *) PALLOCNOZ(cjBlockSize,' bgG');
  1896. if (!pbblNext)
  1897. {
  1898. WARNING1("gdisrv!bInitCache(): glyphbit allocation failed\n");
  1899. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  1900. return NULL;
  1901. }
  1902. TRACE_CACHE((
  1903. " tag = Ggb"
  1904. " size = %-#x"
  1905. " pbbl = %-#x\n",
  1906. cjBlockSize,
  1907. pbblNext
  1908. ));
  1909. TRACE_INSERT((
  1910. "Block %ld, cGlyphs = %ld, tag = Ggb, cjBlockSize = 0x%lx, pbbl = %-#x\n",
  1911. pc->cBlocks, // do before incrementing cBlocks
  1912. pc->cGlyphs,
  1913. cjBlockSize,
  1914. pbblNext
  1915. ));
  1916. // we have just allocated another block, update cBlocks:
  1917. pc->cBlocks += 1;
  1918. // append this block to the end of the list
  1919. if (!pc->pbblCur) // first block ever for this rfont
  1920. {
  1921. ASSERTGDI(
  1922. (pc->pbblBase == NULL) && (pc->cBlocks == 1),
  1923. "The font cache is trashed\n");
  1924. pc->pbblBase = pc->pbblCur = pbblNext;
  1925. }
  1926. else
  1927. {
  1928. ASSERTGDI(
  1929. (pc->pbblCur->pbblNext == NULL),
  1930. "The end of the font cache linked list is trashed\n");
  1931. pc->pbblCur->pbblNext = pbblNext;
  1932. pc->pbblCur = pbblNext;
  1933. }
  1934. // init the header of the current block
  1935. pc->pbblCur->pbblNext = NULL; // essential initialization
  1936. pc->pgbNext = pc->pbblCur->ajBits;
  1937. // we do not want to use the last 8 bytes in the BITBLOCK. Some drivers
  1938. // read the last dword (or quadword) past the end of the GLYPHBITS.
  1939. // If there is a GLYPHBITS at the very and of the BITBLOCK AND the
  1940. // allocation happens to be at the end of the page the read will AV.
  1941. pc->pgbThreshold = (PBYTE)pc->pbblCur + cjBlockSize - sizeof(double);
  1942. }
  1943. else
  1944. {
  1945. // tough luck, we are not allowed to add more blocks
  1946. return NULL;
  1947. }
  1948. }
  1949. }
  1950. ASSERTGDI((pc->pgbNext + cjNeeded) <= pc->pgbThreshold,
  1951. "pgbCheckGlyphCache, we are about to trash the font cache\n");
  1952. return pc->pgbNext;
  1953. }
  1954. /******************************Public*Routine******************************\
  1955. * VOID vFlushCache()
  1956. *
  1957. * Flush the glyph cache.
  1958. *
  1959. * History:
  1960. * Fri 29-Sep-1995 -by- Bodin Dresevic [BodinD]
  1961. * rewrote.
  1962. * 25-Nov-92 -by- Paul Butzi
  1963. * Wrote it.
  1964. \**************************************************************************/
  1965. VOID RFONTOBJ::vFlushCache()
  1966. {
  1967. CACHE *pc = &prfnt->cache;
  1968. // all the pointers to glyphs bits will be invalidated and we will start
  1969. // filling the glyphbits cache all over again. Therefore, we set the current
  1970. // block to be the same as base block and pgbN to the first available field in
  1971. // in the Current block.
  1972. // Note that vFlushCache is allways called after pgbCheckGlyphCache has failed.
  1973. // pgbCheckGlyphCache could fail for one of the two following reasons:
  1974. //
  1975. // a) (pc->cBlocks == pc->cBlocksMax) && (no room in the last block)
  1976. // b) (pc->cBlocks < pc->cBlocksMax) &&
  1977. // (failed to alloc mem for the new bitblock).
  1978. //
  1979. // In the latter case we do not want to flush glyphbits cache.
  1980. // Instead we shall try to allocate one more time a bit later.
  1981. if (pc->pbblBase && (pc->cBlocks == pc->cBlocksMax))
  1982. {
  1983. pc->pbblCur = pc->pbblBase;
  1984. pc->pgbNext = pc->pbblCur->ajBits;
  1985. // we do not want to use the last 8 bytes in the BITBLOCK. Some drivers
  1986. // read the last dword (or quadword) past the end of the GLYPHBITS.
  1987. // If there is a GLYPHBITS at the very and of the BITBLOCK AND the
  1988. // allocation happens to be at the end of the page the read will AV.
  1989. pc->pgbThreshold = (PBYTE)pc->pbblCur + pc->cjbblInitial - sizeof(double);
  1990. }
  1991. // now go and invalidate the glyphbit pointers in the glyphdata cache
  1992. UINT cjGD = bSmallMetrics() ?
  1993. offsetof(GLYPHDATA,fxInkTop) : sizeof(GLYPHDATA);
  1994. BYTE *pjBegin;
  1995. BYTE *pjEnd;
  1996. if ( prfnt->wcgp->pgdDefault != NULL )
  1997. prfnt->wcgp->pgdDefault->gdf.pgb = NULL;
  1998. for
  1999. (
  2000. DATABLOCK *pdbl = pc->pdblBase;
  2001. pdbl != (DATABLOCK*)NULL;
  2002. pdbl = pdbl->pdblNext
  2003. )
  2004. {
  2005. if (pdbl == pc->pdblBase)
  2006. {
  2007. // this is the current block so pjEnd is just pc->pgdNext
  2008. pjEnd = (PBYTE) pc->pgdNext;
  2009. }
  2010. else if (pdbl->pdblNext == (DATABLOCK*)NULL)
  2011. {
  2012. // this is the first block and has the WCPG attached so we need to
  2013. // look into pc.pjFirstBlockEnd to determine the end of it
  2014. pjEnd = pc->pjFirstBlockEnd;
  2015. }
  2016. else
  2017. {
  2018. // this is a normal block so we know it must be GD_INC
  2019. // bytes long
  2020. pjEnd = ((BYTE*) pdbl) + GD_INC;
  2021. }
  2022. pjBegin = (BYTE*)&pdbl->agd[0];
  2023. for ( ; pjBegin < pjEnd ; pjBegin += cjGD)
  2024. {
  2025. ((GLYPHDATA*) pjBegin)->gdf.pgb = NULL;
  2026. }
  2027. }
  2028. }
  2029. // out of line method for assembler linkage
  2030. extern "C" GLYPHDATA *xpgdDefault(RFONTOBJ *pRfontobj)
  2031. {
  2032. return pRfontobj->pgdDefault();
  2033. }