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.

4159 lines
122 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: textout.c
  3. *
  4. * Copyright (c) 1992-1995 Microsoft Corporation
  5. *
  6. \**************************************************************************/
  7. #include "precomp.h"
  8. BYTE gajBit[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
  9. // Converts bit index to set bit
  10. /******************************Public*Routine******************************\
  11. * VOID vClipSolid
  12. *
  13. * Fills the specified rectangle with the specified colour, honouring
  14. * the requested clipping.
  15. *
  16. \**************************************************************************/
  17. VOID vClipSolid(
  18. PDEV* ppdev,
  19. RECTL* prcl,
  20. ULONG iColor,
  21. CLIPOBJ* pco)
  22. {
  23. BOOL bMore; // Flag for clip enumeration
  24. CLIPENUM ce; // Clip enumeration object
  25. LONG c; // Count of non-empty rectangles
  26. RBRUSH_COLOR rbc; // For passing colour to vFillSolid
  27. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
  28. // Scan through all the clip rectangles, looking for intersects
  29. // of fill areas with region rectangles:
  30. rbc.iSolidColor = iColor;
  31. do {
  32. // Get a batch of region rectangles:
  33. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (VOID*) &ce);
  34. c = cIntersect(prcl, ce.arcl, ce.c);
  35. if (c != 0)
  36. ppdev->pfnFillSolid(ppdev, c, ce.arcl, 0xf0f0, rbc, NULL);
  37. } while (bMore);
  38. }
  39. /******************************Public*Routine******************************\
  40. * CACHEDFONT* pcfAllocateCachedFont()
  41. *
  42. * Initializes our font data structure.
  43. *
  44. \**************************************************************************/
  45. CACHEDFONT* pcfAllocateCachedFont(
  46. PDEV* ppdev)
  47. {
  48. CACHEDFONT* pcf;
  49. CACHEDGLYPH** ppcg;
  50. LONG i;
  51. pcf = AtiAllocMem(LPTR, FL_ZERO_MEMORY, sizeof(CACHEDFONT));
  52. if (pcf != NULL)
  53. {
  54. // Note that we rely on FL_ZERO_MEMORY to zero 'pgaChain' and
  55. // 'cjAlloc':
  56. pcf->cgSentinel.hg = HGLYPH_SENTINEL;
  57. // Initialize the hash table entries to all point to our sentinel:
  58. for (ppcg = &pcf->apcg[0], i = GLYPH_HASH_SIZE; i != 0; i--, ppcg++)
  59. {
  60. *ppcg = &pcf->cgSentinel;
  61. }
  62. }
  63. return(pcf);
  64. }
  65. /******************************Public*Routine******************************\
  66. * VOID vFreeCachedFont()
  67. *
  68. * Frees all memory associated with the cache we kept for this font.
  69. *
  70. \**************************************************************************/
  71. VOID vFreeCachedFont(
  72. CACHEDFONT* pcf)
  73. {
  74. GLYPHALLOC* pga;
  75. GLYPHALLOC* pgaNext;
  76. pga = pcf->pgaChain;
  77. while (pga != NULL)
  78. {
  79. pgaNext = pga->pgaNext;
  80. AtiFreeMem(pga);
  81. pga = pgaNext;
  82. }
  83. AtiFreeMem(pcf);
  84. }
  85. /******************************Public*Routine******************************\
  86. * VOID vTrimAndPackGlyph
  87. *
  88. \**************************************************************************/
  89. // expandto3 - expand one (monochrome) byte to three (24bpp) bytes, while
  90. // flipping the bits backwards.
  91. #define expandto3(a,b) \
  92. { \
  93. if ((a) & 0x80) *(b) |= 0x07; \
  94. if ((a) & 0x40) *(b) |= 0x38; \
  95. if ((a) & 0x20) {*(b) |= 0xC0; *((b)+1) |= 0x01;} \
  96. if ((a) & 0x10) *((b)+1) |= 0x0E; \
  97. if ((a) & 0x08) *((b)+1) |= 0x70; \
  98. if ((a) & 0x04) {*((b)+1) |= 0x80; *((b)+2) |= 0x03;} \
  99. if ((a) & 0x02) *((b)+2) |= 0x1C; \
  100. if ((a) & 0x01) *((b)+2) |= 0xE0; \
  101. }
  102. VOID vTrimAndPackGlyph(
  103. PDEV* ppdev,
  104. BYTE* pjBuf, // Note: Routine may touch preceding byte!
  105. BYTE* pjGlyph,
  106. LONG* pcxGlyph,
  107. LONG* pcyGlyph,
  108. POINTL* pptlOrigin)
  109. {
  110. LONG cxGlyph;
  111. LONG cyGlyph;
  112. POINTL ptlOrigin;
  113. LONG cAlign;
  114. LONG lDelta;
  115. BYTE* pj;
  116. BYTE jBit;
  117. LONG cjSrcWidth;
  118. LONG lSrcSkip;
  119. LONG lDstSkip;
  120. LONG cRem;
  121. BYTE* pjSrc;
  122. BYTE* pjDst;
  123. LONG i;
  124. LONG j;
  125. BYTE jSrc;
  126. ///////////////////////////////////////////////////////////////
  127. // Trim the glyph
  128. cyGlyph = *pcyGlyph;
  129. cxGlyph = *pcxGlyph;
  130. ptlOrigin = *pptlOrigin;
  131. cAlign = 0;
  132. lDelta = (cxGlyph + 7) >> 3;
  133. // Trim off any zero rows at the bottom of the glyph:
  134. pj = pjGlyph + cyGlyph * lDelta; // One past last byte in glyph
  135. while (cyGlyph > 0)
  136. {
  137. i = lDelta;
  138. do {
  139. if (*(--pj) != 0)
  140. goto Done_Bottom_Trim;
  141. } while (--i != 0);
  142. // The entire last row has no lit pixels, so simply skip it:
  143. cyGlyph--;
  144. }
  145. ASSERTDD(cyGlyph == 0, "cyGlyph should only be zero here");
  146. // We found a space character. Set both dimensions to zero, so
  147. // that it's easy to special-case later:
  148. cxGlyph = 0;
  149. Done_Bottom_Trim:
  150. // If cxGlyph != 0, we know that the glyph has at least one non-zero
  151. // row and column. By exploiting this knowledge, we can simplify our
  152. // end-of-loop tests, because we don't have to check to see if we've
  153. // decremented either 'cyGlyph' or 'cxGlyph' to zero:
  154. if (cxGlyph != 0)
  155. {
  156. // Trim off any zero rows at the top of the glyph:
  157. pj = pjGlyph; // First byte in glyph
  158. while (TRUE)
  159. {
  160. i = lDelta;
  161. do {
  162. if (*(pj++) != 0)
  163. goto Done_Top_Trim;
  164. } while (--i != 0);
  165. // The entire first row has no lit pixels, so simply skip it:
  166. cyGlyph--;
  167. ptlOrigin.y++;
  168. pjGlyph = pj;
  169. }
  170. Done_Top_Trim:
  171. // Trim off any zero columns at the right edge of the glyph:
  172. while (TRUE)
  173. {
  174. j = cxGlyph - 1;
  175. pj = pjGlyph + (j >> 3); // Last byte in first row of glyph
  176. jBit = gajBit[j & 0x7];
  177. i = cyGlyph;
  178. do {
  179. if ((*pj & jBit) != 0)
  180. goto Done_Right_Trim;
  181. pj += lDelta;
  182. } while (--i != 0);
  183. // The entire last column has no lit pixels, so simply skip it:
  184. cxGlyph--;
  185. }
  186. Done_Right_Trim:
  187. // Trim off any zero columns at the left edge of the glyph:
  188. while (TRUE)
  189. {
  190. pj = pjGlyph; // First byte in first row of glyph
  191. jBit = gajBit[cAlign];
  192. i = cyGlyph;
  193. do {
  194. if ((*pj & jBit) != 0)
  195. goto Done_Left_Trim;
  196. pj += lDelta;
  197. } while (--i != 0);
  198. // The entire first column has no lit pixels, so simply skip it:
  199. ptlOrigin.x++;
  200. cxGlyph--;
  201. cAlign++;
  202. if (cAlign >= 8)
  203. {
  204. cAlign = 0;
  205. pjGlyph++;
  206. }
  207. }
  208. }
  209. Done_Left_Trim:
  210. ///////////////////////////////////////////////////////////////
  211. // Pack the glyph
  212. //
  213. // N.B.: The glyph bits are packed in pjBuf backwards.
  214. // Failure to understand this cost me nearly a week's effort,
  215. // and gave me a whopping migraine. (This was for 24bpp.)
  216. if (ppdev->iBitmapFormat != BMF_24BPP)
  217. {
  218. cjSrcWidth = (cxGlyph + cAlign + 7) >> 3;
  219. lSrcSkip = lDelta - cjSrcWidth;
  220. lDstSkip = ((cxGlyph + 7) >> 3) - cjSrcWidth - 1;
  221. cRem = ((cxGlyph - 1) & 7) + 1; // 0 -> 8
  222. pjSrc = pjGlyph;
  223. pjDst = pjBuf;
  224. // Zero the buffer, because we're going to 'or' stuff into it:
  225. memset(pjBuf, 0, (cxGlyph * cyGlyph + 7) >> 3);
  226. // cAlign used to indicate which bit in the first byte of the unpacked
  227. // glyph was the first non-zero pixel column. Now, we flip it to
  228. // indicate which bit in the packed byte will receive the next non-zero
  229. // glyph bit:
  230. cAlign = (-cAlign) & 0x7;
  231. if (cAlign > 0)
  232. {
  233. // It would be bad if our trimming calculations were wrong, because
  234. // we assume any bits to the left of the 'cAlign' bit will be zero.
  235. // As a result of this decrement, we will 'or' those zero bits into
  236. // whatever byte precedes the glyph bits array:
  237. pjDst--;
  238. ASSERTDD((*pjSrc >> cAlign) == 0, "Trimmed off too many bits");
  239. }
  240. for (i = cyGlyph; i != 0; i--)
  241. {
  242. for (j = cjSrcWidth; j != 0; j--)
  243. {
  244. // Note that we may modify a byte past the end of our
  245. // destination buffer, which is why we reserved an
  246. // extra byte:
  247. jSrc = *pjSrc;
  248. *(pjDst) |= (jSrc >> (cAlign));
  249. *(pjDst + 1) |= (jSrc << (8 - cAlign));
  250. pjSrc++;
  251. pjDst++;
  252. }
  253. pjSrc += lSrcSkip;
  254. pjDst += lDstSkip;
  255. cAlign += cRem;
  256. if (cAlign >= 8)
  257. {
  258. cAlign -= 8;
  259. pjDst++;
  260. }
  261. }
  262. }
  263. else
  264. {
  265. BYTE cur_byte, last_byte, last_byte2, next_byte;
  266. cjSrcWidth = (cxGlyph + cAlign + 7) >> 3;
  267. lSrcSkip = lDelta - cjSrcWidth;
  268. lDstSkip = (((cxGlyph + 7) >> 3) - cjSrcWidth - 1) * 3;
  269. cRem = ((cxGlyph - 1) & 7) + 1; // 0 -> 8
  270. pjSrc = pjGlyph;
  271. pjDst = pjBuf;
  272. // Zero the buffer, because we're going to 'or' stuff into it:
  273. memset(pjBuf, 0, (3 * cxGlyph * cyGlyph + 7) >> 3);
  274. // cAlign used to indicate which bit in the first byte of the unpacked
  275. // glyph was the first non-zero pixel column. Now, we flip it to
  276. // indicate which bit in the packed byte will receive the next non-zero
  277. // glyph bit:
  278. cAlign = (-cAlign) & 0x7;
  279. if (cAlign > 0)
  280. {
  281. // It would be bad if our trimming calculations were wrong, because
  282. // we assume any bits to the left of the 'cAlign' bit will be zero.
  283. // As a result of this decrement, we will 'or' those zero bits into
  284. // whatever bytes precedes the glyph bits array:
  285. pjDst -= 3;
  286. ASSERTDD((*pjSrc >> cAlign) == 0, "Trimmed off too many bits");
  287. }
  288. cur_byte = last_byte = 0;
  289. for (i = cyGlyph; i != 0; i--)
  290. {
  291. for (j = cjSrcWidth; j != 0; j--)
  292. {
  293. // Note that we may modify a byte past the end of our
  294. // destination buffer, which is why we reserved an
  295. // extra three bytes:
  296. jSrc = *pjSrc;
  297. cur_byte |= (jSrc >> (cAlign));
  298. expandto3(cur_byte, pjDst);
  299. next_byte = (jSrc << (8 - cAlign));
  300. expandto3(next_byte, pjDst+3);
  301. pjSrc++;
  302. pjDst += 3;
  303. last_byte2 = last_byte;
  304. last_byte = cur_byte;
  305. cur_byte = next_byte;
  306. }
  307. pjSrc += lSrcSkip;
  308. pjDst += lDstSkip; // can be -3 or -6 (if cAlign is big enough) !!
  309. cAlign += cRem;
  310. cur_byte = (lDstSkip != -3)? last_byte2:last_byte;
  311. if (cAlign >= 8)
  312. {
  313. cAlign -= 8;
  314. pjDst += 3;
  315. cur_byte = (lDstSkip != -3)? last_byte:next_byte;
  316. }
  317. }
  318. cxGlyph *= 3;
  319. }
  320. ///////////////////////////////////////////////////////////////
  321. // Return results
  322. *pcxGlyph = cxGlyph;
  323. *pcyGlyph = cyGlyph;
  324. *pptlOrigin = ptlOrigin;
  325. }
  326. /******************************Public*Routine******************************\
  327. * VOID vPutGlyphInCache
  328. *
  329. * Figures out where to be a glyph in off-screen memory, copies it
  330. * there, and fills in any other data we'll need to display the glyph.
  331. *
  332. * This routine is rather device-specific, and will have to be extensively
  333. * modified for other display adapters.
  334. *
  335. * Returns TRUE if successful; FALSE if there wasn't enough room in
  336. * off-screen memory.
  337. *
  338. \**************************************************************************/
  339. VOID vPutGlyphInCache(
  340. PDEV* ppdev,
  341. CACHEDGLYPH* pcg,
  342. GLYPHBITS* pgb)
  343. {
  344. BYTE* pjGlyph;
  345. LONG cxGlyph;
  346. LONG cyGlyph;
  347. POINTL ptlOrigin;
  348. pjGlyph = pgb->aj;
  349. cyGlyph = pgb->sizlBitmap.cy;
  350. cxGlyph = pgb->sizlBitmap.cx;
  351. ptlOrigin = pgb->ptlOrigin;
  352. vTrimAndPackGlyph(ppdev, (BYTE*) &pcg->ad, pjGlyph, &cxGlyph, &cyGlyph, &ptlOrigin);
  353. ///////////////////////////////////////////////////////////////
  354. // Initialize the glyph fields
  355. pcg->ptlOrigin = ptlOrigin;
  356. pcg->cx = cxGlyph;
  357. pcg->cy = cyGlyph;
  358. pcg->cxy = pcg->cy | (pcg->cx << 16);
  359. pcg->cw = (cxGlyph * cyGlyph + 15) >> 4;
  360. pcg->cd = (pcg->cw + 1) >> 1;
  361. }
  362. /******************************Public*Routine******************************\
  363. * CACHEDGLYPH* pcgNew()
  364. *
  365. * Creates a new CACHEDGLYPH structure for keeping track of the glyph in
  366. * off-screen memory. bPutGlyphInCache is called to actually put the glyph
  367. * in off-screen memory.
  368. *
  369. * This routine should be reasonably device-independent, as bPutGlyphInCache
  370. * will contain most of the code that will have to be modified for other
  371. * display adapters.
  372. *
  373. \**************************************************************************/
  374. CACHEDGLYPH* pcgNew(
  375. PDEV* ppdev,
  376. CACHEDFONT* pcf,
  377. GLYPHPOS* pgp)
  378. {
  379. GLYPHBITS* pgb;
  380. GLYPHALLOC* pga;
  381. CACHEDGLYPH* pcg;
  382. LONG cjCachedGlyph;
  383. HGLYPH hg;
  384. LONG iHash;
  385. CACHEDGLYPH* pcgFind;
  386. // First, calculate the amount of storage we'll need for this glyph:
  387. pgb = pgp->pgdf->pgb;
  388. if (ppdev->iBitmapFormat != BMF_24BPP)
  389. {
  390. cjCachedGlyph = sizeof(CACHEDGLYPH)
  391. + ((pgb->sizlBitmap.cx * pgb->sizlBitmap.cy + 7) >> 3);
  392. // Reserve an extra byte at the end for temporary usage by our pack
  393. // routine:
  394. cjCachedGlyph++;
  395. }
  396. else
  397. {
  398. cjCachedGlyph = sizeof(CACHEDGLYPH)
  399. + ((3 * pgb->sizlBitmap.cx * pgb->sizlBitmap.cy + 7) >> 3);
  400. // Reserve 3 extra bytes at the end for temporary usage by our pack
  401. // routine:
  402. cjCachedGlyph += 3;
  403. }
  404. // We need to dword align it too:
  405. cjCachedGlyph = (cjCachedGlyph + 3) & ~3L;
  406. if (cjCachedGlyph > pcf->cjAlloc)
  407. {
  408. // Have to allocate a new glyph allocation structure:
  409. pga = AtiAllocMem(LPTR, FL_ZERO_MEMORY, GLYPH_ALLOC_SIZE);
  410. if (pga == NULL)
  411. {
  412. // It's safe to return at this time because we haven't
  413. // fatally altered any of our data structures:
  414. return(NULL);
  415. }
  416. // Add this allocation to the front of the allocation linked list,
  417. // so that we can free it later:
  418. pga->pgaNext = pcf->pgaChain;
  419. pcf->pgaChain = pga;
  420. // Now we've got a chunk of memory where we can store our cached
  421. // glyphs:
  422. pcf->pcgNew = &pga->acg[0];
  423. pcf->cjAlloc = GLYPH_ALLOC_SIZE - (sizeof(*pga) - sizeof(pga->acg[0]));
  424. // It would be bad if we let in any glyphs that would be bigger
  425. // than our basic allocation size:
  426. ASSERTDD(cjCachedGlyph <= GLYPH_ALLOC_SIZE, "Woah, this is one big glyph!");
  427. }
  428. pcg = pcf->pcgNew;
  429. // We only need to ensure 'dword' alignment of the next structure:
  430. pcf->pcgNew = (CACHEDGLYPH*) ((BYTE*) pcg + cjCachedGlyph);
  431. pcf->cjAlloc -= cjCachedGlyph;
  432. ///////////////////////////////////////////////////////////////
  433. // Insert the glyph, in-order, into the list hanging off our hash
  434. // bucket:
  435. hg = pgp->hg;
  436. pcg->hg = hg;
  437. iHash = GLYPH_HASH_FUNC(hg);
  438. pcgFind = pcf->apcg[iHash];
  439. if (pcgFind->hg > hg)
  440. {
  441. pcf->apcg[iHash] = pcg;
  442. pcg->pcgNext = pcgFind;
  443. }
  444. else
  445. {
  446. // The sentinel will ensure that we never fall off the end of
  447. // this list:
  448. while (pcgFind->pcgNext->hg < hg)
  449. pcgFind = pcgFind->pcgNext;
  450. // 'pcgFind' now points to the entry to the entry after which
  451. // we want to insert our new node:
  452. pcg->pcgNext = pcgFind->pcgNext;
  453. pcgFind->pcgNext = pcg;
  454. }
  455. vPutGlyphInCache(ppdev, pcg, pgp->pgdf->pgb);
  456. return(pcg);
  457. }
  458. /******************************Public*Routine******************************\
  459. * BOOL bI32CachedProportionalText
  460. *
  461. * Draws proportionally spaced glyphs via glyph caching.
  462. *
  463. \**************************************************************************/
  464. BOOL bI32CachedProportionalText(
  465. PDEV* ppdev,
  466. CACHEDFONT* pcf,
  467. GLYPHPOS* pgp,
  468. LONG cGlyph)
  469. {
  470. BYTE* pjIoBase;
  471. HGLYPH hg;
  472. CACHEDGLYPH* pcg;
  473. LONG xOffset;
  474. LONG yOffset;
  475. LONG x;
  476. LONG y;
  477. LONG cw;
  478. WORD* pw;
  479. pjIoBase = ppdev->pjIoBase;
  480. xOffset = ppdev->xOffset;
  481. yOffset = ppdev->yOffset;
  482. do {
  483. hg = pgp->hg;
  484. pcg = pcf->apcg[GLYPH_HASH_FUNC(hg)];
  485. while (pcg->hg < hg) {
  486. pcg = pcg->pcgNext;
  487. }
  488. if (pcg->hg > hg)
  489. {
  490. // This will hopefully not be the common case (that is,
  491. // we will have a high cache hit rate), so if I were
  492. // writing this in Asm I would have this out-of-line
  493. // to avoid the jump around for the common case.
  494. // But the Pentium has branch prediction, so what the
  495. // heck.
  496. pcg = pcgNew(ppdev, pcf, pgp);
  497. if (pcg == NULL)
  498. return(FALSE);
  499. }
  500. // Space glyphs are trimmed to a height of zero, and we don't
  501. // even have to touch the hardware for them:
  502. if (pcg->cx != 0)
  503. {
  504. // The glyph's origin y-coordinate may often be negative, so we
  505. // can't compute this as follows:
  506. //
  507. // x = pgp->ptl.x + pcg->ptlOrigin.x;
  508. // y = pgp->ptl.y + pcg->ptlOrigin.y;
  509. ASSERTDD((pgp->ptl.y + pcg->ptlOrigin.y) >= 0,
  510. "Can't have negative 'y' coordinates here");
  511. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 5);
  512. x = xOffset + pgp->ptl.x + pcg->ptlOrigin.x;
  513. I32_OW(pjIoBase, CUR_X, x);
  514. I32_OW(pjIoBase, DEST_X_START, x);
  515. I32_OW(pjIoBase, DEST_X_END, x + pcg->cx);
  516. y = yOffset + pgp->ptl.y + pcg->ptlOrigin.y;
  517. I32_OW(pjIoBase, CUR_Y, y);
  518. I32_OW(pjIoBase, DEST_Y_END, y + pcg->cy);
  519. // Take advantage of wait-stated I/O:
  520. pw = (WORD*) &pcg->ad[0];
  521. cw = pcg->cw;
  522. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 10);
  523. do {
  524. I32_OW_DIRECT(pjIoBase, PIX_TRANS, *pw);
  525. } while (pw++, --cw != 0);
  526. }
  527. } while (pgp++, --cGlyph != 0);
  528. return(TRUE);
  529. }
  530. /******************************Public*Routine******************************\
  531. * BOOL bI32CachedFixedText
  532. *
  533. * Draws fixed spaced glyphs via glyph caching.
  534. *
  535. \*************************************************************************/
  536. BOOL bI32CachedFixedText(
  537. PDEV* ppdev,
  538. CACHEDFONT* pcf,
  539. GLYPHPOS* pgp,
  540. LONG cGlyph,
  541. ULONG ulCharInc)
  542. {
  543. BYTE* pjIoBase;
  544. LONG xGlyph;
  545. LONG yGlyph;
  546. HGLYPH hg;
  547. CACHEDGLYPH* pcg;
  548. LONG x;
  549. LONG y;
  550. WORD* pw;
  551. LONG cw;
  552. pjIoBase = ppdev->pjIoBase;
  553. // Convert to absolute coordinates:
  554. xGlyph = pgp->ptl.x + ppdev->xOffset;
  555. yGlyph = pgp->ptl.y + ppdev->yOffset;
  556. do {
  557. hg = pgp->hg;
  558. pcg = pcf->apcg[GLYPH_HASH_FUNC(hg)];
  559. while (pcg->hg < hg) {
  560. pcg = pcg->pcgNext;
  561. }
  562. if (pcg->hg > hg)
  563. {
  564. // This will hopefully not be the common case (that is,
  565. // we will have a high cache hit rate), so if I were
  566. // writing this in Asm I would have this out-of-line
  567. // to avoid the jump around for the common case.
  568. // But the Pentium has branch prediction, so what the
  569. // heck.
  570. pcg = pcgNew(ppdev, pcf, pgp);
  571. if (pcg == NULL)
  572. return(FALSE);
  573. }
  574. // Space glyphs are trimmed to a height of zero, and we don't
  575. // even have to touch the hardware for them:
  576. if (pcg->cx != 0)
  577. {
  578. x = xGlyph + pcg->ptlOrigin.x;
  579. y = yGlyph + pcg->ptlOrigin.y;
  580. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 5);
  581. I32_OW(pjIoBase, CUR_X, x);
  582. I32_OW(pjIoBase, DEST_X_START, x);
  583. I32_OW(pjIoBase, DEST_X_END, x + pcg->cx);
  584. I32_OW(pjIoBase, CUR_Y, y);
  585. I32_OW(pjIoBase, DEST_Y_END, y + pcg->cy);
  586. // Take advantage of wait-stated I/O:
  587. pw = (WORD*) &pcg->ad[0];
  588. cw = pcg->cw;
  589. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 10);
  590. do {
  591. I32_OW_DIRECT(pjIoBase, PIX_TRANS, *pw);
  592. } while (pw++, --cw != 0);
  593. }
  594. xGlyph += ulCharInc;
  595. } while (pgp++, --cGlyph != 0);
  596. return(TRUE);
  597. }
  598. /******************************Public*Routine******************************\
  599. * BOOL bI32CachedClippedText
  600. *
  601. * Draws clipped text via glyph caching.
  602. *
  603. \**************************************************************************/
  604. BOOL bI32CachedClippedText(
  605. PDEV* ppdev,
  606. CACHEDFONT* pcf,
  607. STROBJ* pstro,
  608. CLIPOBJ* pco)
  609. {
  610. BOOL bRet;
  611. BYTE* pjIoBase;
  612. LONG xOffset;
  613. LONG yOffset;
  614. BOOL bMoreGlyphs;
  615. ULONG cGlyphOriginal;
  616. ULONG cGlyph;
  617. BOOL bClippingSet;
  618. GLYPHPOS* pgpOriginal;
  619. GLYPHPOS* pgp;
  620. LONG xGlyph;
  621. LONG yGlyph;
  622. LONG x;
  623. LONG y;
  624. LONG xRight;
  625. LONG yBottom;
  626. LONG cy;
  627. BOOL bMore;
  628. CLIPENUM ce;
  629. RECTL* prclClip;
  630. ULONG ulCharInc;
  631. HGLYPH hg;
  632. CACHEDGLYPH* pcg;
  633. WORD* pw;
  634. LONG cw;
  635. ASSERTDD((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL),
  636. "Don't expect trivial clipping in this function");
  637. bRet = TRUE;
  638. pjIoBase = ppdev->pjIoBase;
  639. xOffset = ppdev->xOffset;
  640. yOffset = ppdev->yOffset;
  641. ulCharInc = pstro->ulCharInc;
  642. do {
  643. if (pstro->pgp != NULL)
  644. {
  645. // There's only the one batch of glyphs, so save ourselves
  646. // a call:
  647. pgpOriginal = pstro->pgp;
  648. cGlyphOriginal = pstro->cGlyphs;
  649. bMoreGlyphs = FALSE;
  650. }
  651. else
  652. {
  653. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphOriginal, &pgpOriginal);
  654. }
  655. if (cGlyphOriginal > 0)
  656. {
  657. if (pco->iDComplexity == DC_RECT)
  658. {
  659. // We could call 'cEnumStart' and 'bEnum' when the clipping is
  660. // DC_RECT, but the last time I checked, those two calls took
  661. // more than 150 instructions to go through GDI. Since
  662. // 'rclBounds' already contains the DC_RECT clip rectangle,
  663. // and since it's such a common case, we'll special case it:
  664. bMore = FALSE;
  665. ce.c = 1;
  666. prclClip = &pco->rclBounds;
  667. goto SingleRectangle;
  668. }
  669. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  670. do {
  671. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  672. for (prclClip = &ce.arcl[0]; ce.c != 0; ce.c--, prclClip++)
  673. {
  674. SingleRectangle:
  675. // We don't always simply set the clipping rectangle here
  676. // because it may actually end up that no text intersects
  677. // this clip rectangle, so it would be for naught. This
  678. // actually happens a lot when using NT's analog clock set
  679. // to always-on-top, with a round shape:
  680. bClippingSet = FALSE;
  681. pgp = pgpOriginal;
  682. cGlyph = cGlyphOriginal;
  683. // We can't yet convert to absolute coordinates by adding
  684. // in 'xOffset' or 'yOffset' here because we have yet to
  685. // compare the coordinates to 'prclClip':
  686. xGlyph = pgp->ptl.x;
  687. yGlyph = pgp->ptl.y;
  688. // Loop through all the glyphs for this rectangle:
  689. while (TRUE)
  690. {
  691. hg = pgp->hg;
  692. pcg = pcf->apcg[GLYPH_HASH_FUNC(hg)];
  693. while (pcg->hg < hg)
  694. pcg = pcg->pcgNext;
  695. if (pcg->hg > hg)
  696. {
  697. // This will hopefully not be the common case (that is,
  698. // we will have a high cache hit rate), so if I were
  699. // writing this in Asm I would have this out-of-line
  700. // to avoid the jump around for the common case.
  701. // But the Pentium has branch prediction, so what the
  702. // heck.
  703. pcg = pcgNew(ppdev, pcf, pgp);
  704. if (pcg == NULL)
  705. {
  706. bRet = FALSE;
  707. goto AllDone;
  708. }
  709. }
  710. // Space glyphs are trimmed to a height of zero, and we don't
  711. // even have to touch the hardware for them:
  712. cy = pcg->cy;
  713. if (cy != 0)
  714. {
  715. y = pcg->ptlOrigin.y + yGlyph;
  716. x = pcg->ptlOrigin.x + xGlyph;
  717. xRight = pcg->cx + x;
  718. yBottom = pcg->cy + y;
  719. // Do trivial rejection:
  720. if ((prclClip->right > x) &&
  721. (prclClip->bottom > y) &&
  722. (prclClip->left < xRight) &&
  723. (prclClip->top < yBottom))
  724. {
  725. // Lazily set the hardware clipping:
  726. if (!bClippingSet)
  727. {
  728. bClippingSet = TRUE;
  729. vSetClipping(ppdev, prclClip);
  730. }
  731. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 5);
  732. I32_OW(pjIoBase, CUR_X, xOffset + x);
  733. I32_OW(pjIoBase, DEST_X_START, xOffset + x);
  734. I32_OW(pjIoBase, DEST_X_END, xOffset + xRight);
  735. I32_OW(pjIoBase, CUR_Y, yOffset + y);
  736. I32_OW(pjIoBase, DEST_Y_END, yOffset + yBottom);
  737. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 10);
  738. pw = (WORD*) &pcg->ad[0];
  739. cw = pcg->cw;
  740. do {
  741. I32_OW_DIRECT(pjIoBase, PIX_TRANS, *pw);
  742. } while (pw++, --cw != 0);
  743. }
  744. }
  745. if (--cGlyph == 0)
  746. break;
  747. // Get ready for next glyph:
  748. pgp++;
  749. if (ulCharInc == 0)
  750. {
  751. xGlyph = pgp->ptl.x;
  752. yGlyph = pgp->ptl.y;
  753. }
  754. else
  755. {
  756. xGlyph += ulCharInc;
  757. }
  758. }
  759. }
  760. } while (bMore);
  761. }
  762. } while (bMoreGlyphs);
  763. AllDone:
  764. vResetClipping(ppdev);
  765. return(bRet);
  766. }
  767. VOID vI32DataPortOutB(PDEV *ppdev, PBYTE pb, UINT count)
  768. {
  769. BYTE *pjIoBase = ppdev->pjIoBase;
  770. UINT i;
  771. for (i=0; i < count; i++)
  772. {
  773. if (i % 8 == 0)
  774. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 10);
  775. I32_OB(pjIoBase, PIX_TRANS + 1, *((PUCHAR)pb)++);
  776. }
  777. }
  778. /******************************Public*Routine******************************\
  779. * BOOL bI32GeneralText
  780. *
  781. \**************************************************************************/
  782. BOOL bI32GeneralText(
  783. PDEV* ppdev,
  784. STROBJ* pstro,
  785. CLIPOBJ* pco)
  786. {
  787. BYTE* pjIoBase;
  788. BYTE iDComplexity;
  789. BOOL bMoreGlyphs;
  790. ULONG cGlyphOriginal;
  791. ULONG cGlyph;
  792. GLYPHPOS* pgpOriginal;
  793. GLYPHPOS* pgp;
  794. GLYPHBITS* pgb;
  795. POINTL ptlOrigin;
  796. BOOL bMore;
  797. CLIPENUM ce;
  798. RECTL* prclClip;
  799. ULONG ulCharInc;
  800. LONG cxGlyph;
  801. LONG cyGlyph;
  802. LONG xBiasL = 0;
  803. LONG xBiasR = 0;
  804. LONG yBiasT = 0;
  805. LONG cy = 0;
  806. LONG cx = 0;
  807. BYTE* pjGlyph;
  808. LONG xLeft;
  809. LONG yTop;
  810. LONG xRight;
  811. LONG yBottom;
  812. RECTL NoClip;
  813. LONG x;
  814. LONG y;
  815. pjIoBase = ppdev->pjIoBase;
  816. /* Define Default Clipping area to be full video ram */
  817. NoClip.top = 0;
  818. NoClip.left = 0;
  819. NoClip.right = ppdev->cxScreen;
  820. NoClip.bottom = ppdev->cyScreen;
  821. if (pco == NULL)
  822. iDComplexity = DC_TRIVIAL;
  823. else
  824. iDComplexity = pco->iDComplexity;
  825. do {
  826. if (pstro->pgp != NULL)
  827. {
  828. // There's only the one batch of glyphs, so save ourselves
  829. // a call:
  830. pgpOriginal = pstro->pgp;
  831. cGlyphOriginal = pstro->cGlyphs;
  832. bMoreGlyphs = FALSE;
  833. }
  834. else
  835. {
  836. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphOriginal, &pgpOriginal);
  837. }
  838. if (cGlyphOriginal > 0)
  839. {
  840. ulCharInc = pstro->ulCharInc;
  841. if (iDComplexity != DC_COMPLEX)
  842. {
  843. // We could call 'cEnumStart' and 'bEnum' when the clipping is
  844. // DC_RECT, but the last time I checked, those two calls took
  845. // more than 150 instructions to go through GDI. Since
  846. // 'rclBounds' already contains the DC_RECT clip rectangle,
  847. // and since it's such a common case, we'll special case it:
  848. bMore = FALSE;
  849. ce.c = 1;
  850. if (iDComplexity == DC_TRIVIAL)
  851. prclClip = &NoClip;
  852. else
  853. prclClip = &pco->rclBounds;
  854. goto SingleRectangle;
  855. }
  856. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  857. do {
  858. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  859. for (prclClip = &ce.arcl[0]; ce.c != 0; ce.c--, prclClip++)
  860. {
  861. SingleRectangle:
  862. pgp = pgpOriginal;
  863. cGlyph = cGlyphOriginal;
  864. pgb = pgp->pgdf->pgb;
  865. ptlOrigin.x = pgb->ptlOrigin.x + pgp->ptl.x;
  866. ptlOrigin.y = pgb->ptlOrigin.y + pgp->ptl.y;
  867. vSetClipping(ppdev, prclClip);
  868. //ppdev->lRightScissor = rclRealClip.right; ???
  869. // Loop through all the glyphs for this rectangle:
  870. while (TRUE)
  871. {
  872. cxGlyph = pgb->sizlBitmap.cx;
  873. cyGlyph = pgb->sizlBitmap.cy;
  874. pjGlyph = (BYTE*) pgb->aj;
  875. if ((prclClip->left <= ptlOrigin.x) &&
  876. (prclClip->top <= ptlOrigin.y) &&
  877. (prclClip->right >= ptlOrigin.x + cxGlyph) &&
  878. (prclClip->bottom >= ptlOrigin.y + cyGlyph))
  879. {
  880. //-----------------------------------------------------
  881. // Unclipped glyph
  882. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 6);
  883. x = ppdev->xOffset + ptlOrigin.x;
  884. I32_OW(pjIoBase, CUR_X, LOWORD(x));
  885. I32_OW(pjIoBase, DEST_X_START, LOWORD(x));
  886. I32_OW(pjIoBase, DEST_X_END, LOWORD(x) + ROUND8(cxGlyph) );
  887. I32_OW(pjIoBase, SCISSOR_R, LOWORD(x) + cxGlyph-1);
  888. y = ppdev->yOffset + ptlOrigin.y;
  889. I32_OW(pjIoBase, CUR_Y, LOWORD(y));
  890. I32_OW(pjIoBase, DEST_Y_END, (LOWORD(y) + cyGlyph));
  891. vI32DataPortOutB(ppdev, pjGlyph, (ROUND8(cxGlyph) * cyGlyph) >> 3);
  892. /*
  893. _vBlit_DSC_SH1UP(ppdev,ptlOrigin.x, ptlOrigin.y,
  894. cxGlyph, cyGlyph, pjGlyph,
  895. (ROUND8(cxGlyph) * cyGlyph) >> 3);
  896. */
  897. }
  898. else
  899. {
  900. //-----------------------------------------------------
  901. // Clipped glyph
  902. // Find the intersection of the glyph rectangle
  903. // and the clip rectangle:
  904. xLeft = max(prclClip->left, ptlOrigin.x);
  905. yTop = max(prclClip->top, ptlOrigin.y);
  906. xRight = min(prclClip->right, ptlOrigin.x + cxGlyph);
  907. yBottom = min(prclClip->bottom, ptlOrigin.y + cyGlyph);
  908. // Check for trivial rejection:
  909. if ( ( ptlOrigin.x <= prclClip->left ) &&
  910. (ppdev->pModeInfo->ModeFlags & AMI_TEXTBAND) )
  911. {
  912. vResetClipping(ppdev);
  913. return FALSE;
  914. }
  915. if (((cx = xRight - xLeft) > 0) &&
  916. ((cy = yBottom - yTop) > 0))
  917. {
  918. /* Do software clipping */
  919. /* Calculated the Bias in pixels */
  920. yBiasT = (yTop - ptlOrigin.y);
  921. /* change address of pjGlyph to point +yBiasT
  922. scan lines into the Glyph */
  923. pjGlyph += (yBiasT * (ROUND8(cxGlyph) >> 3));
  924. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 6);
  925. x = ppdev->xOffset + ptlOrigin.x;
  926. I32_OW(pjIoBase, CUR_X, LOWORD(x));
  927. I32_OW(pjIoBase, DEST_X_START, LOWORD(x));
  928. I32_OW(pjIoBase, DEST_X_END, LOWORD(x) + ROUND8(cxGlyph) );
  929. I32_OW(pjIoBase, SCISSOR_R, LOWORD(x) + cxGlyph-1);
  930. y = ppdev->yOffset + ptlOrigin.y;
  931. I32_OW(pjIoBase, CUR_Y, LOWORD(y+yBiasT));
  932. I32_OW(pjIoBase, DEST_Y_END, (LOWORD(y+yBiasT) + cy));
  933. vI32DataPortOutB(ppdev, pjGlyph, (ROUND8(cxGlyph) >> 3) * cy);
  934. /*
  935. _vBlit_DSC_SH1UP(ppdev,ptlOrigin.x,ptlOrigin.y+yBiasT,
  936. cxGlyph, cy, pjGlyph,
  937. (ROUND8(cxGlyph) >>3) * cy);
  938. */
  939. } /*if*/
  940. }
  941. if (--cGlyph == 0)
  942. break;
  943. // Get ready for next glyph:
  944. pgp++;
  945. pgb = pgp->pgdf->pgb;
  946. if (ulCharInc == 0)
  947. {
  948. ptlOrigin.x = pgp->ptl.x + pgb->ptlOrigin.x;
  949. ptlOrigin.y = pgp->ptl.y + pgb->ptlOrigin.y;
  950. }
  951. else
  952. {
  953. ptlOrigin.x += ulCharInc;
  954. }
  955. }
  956. }
  957. } while (bMore);
  958. }
  959. } while (bMoreGlyphs);
  960. vResetClipping(ppdev);
  961. return TRUE;
  962. }
  963. /******************************Public*Routine******************************\
  964. * BOOL bI32TextOut
  965. *
  966. \**************************************************************************/
  967. BOOL bI32TextOut(
  968. PDEV* ppdev,
  969. STROBJ* pstro,
  970. FONTOBJ* pfo,
  971. CLIPOBJ* pco,
  972. RECTL* prclOpaque,
  973. BRUSHOBJ* pboFore,
  974. BRUSHOBJ* pboOpaque)
  975. {
  976. BYTE* pjIoBase;
  977. LONG xOffset;
  978. LONG yOffset;
  979. ULONG cGlyph;
  980. BOOL bMoreGlyphs;
  981. GLYPHPOS* pgp;
  982. BYTE iDComplexity;
  983. CACHEDFONT* pcf;
  984. RECTL rclOpaque;
  985. BOOL bTextPerfectFit;
  986. pjIoBase = ppdev->pjIoBase;
  987. xOffset = ppdev->xOffset;
  988. yOffset = ppdev->yOffset;
  989. iDComplexity = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  990. if (prclOpaque != NULL)
  991. {
  992. ////////////////////////////////////////////////////////////
  993. // Opaque Initialization
  994. ////////////////////////////////////////////////////////////
  995. if (iDComplexity == DC_TRIVIAL)
  996. {
  997. DrawOpaqueRect:
  998. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 8);
  999. I32_OW(pjIoBase, FRGD_COLOR, pboOpaque->iSolidColor);
  1000. I32_OW(pjIoBase, ALU_FG_FN, OVERPAINT);
  1001. I32_OW(pjIoBase, DP_CONFIG, FG_COLOR_SRC_FG | WRITE | DRAW);
  1002. I32_OW(pjIoBase, CUR_X, xOffset + prclOpaque->left);
  1003. I32_OW(pjIoBase, DEST_X_START, xOffset + prclOpaque->left);
  1004. I32_OW(pjIoBase, DEST_X_END, xOffset + prclOpaque->right);
  1005. I32_OW(pjIoBase, CUR_Y, yOffset + prclOpaque->top);
  1006. vI32QuietDown(ppdev, pjIoBase);
  1007. I32_OW(pjIoBase, DEST_Y_END, yOffset + prclOpaque->bottom);
  1008. }
  1009. else if (iDComplexity == DC_RECT)
  1010. {
  1011. if (bIntersect(prclOpaque, &pco->rclBounds, &rclOpaque))
  1012. {
  1013. prclOpaque = &rclOpaque;
  1014. goto DrawOpaqueRect;
  1015. }
  1016. }
  1017. else
  1018. {
  1019. vClipSolid(ppdev, prclOpaque, pboOpaque->iSolidColor, pco);
  1020. }
  1021. bTextPerfectFit = (pstro->flAccel & (SO_ZERO_BEARINGS |
  1022. SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE |
  1023. SO_CHAR_INC_EQUAL_BM_BASE)) ==
  1024. (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT |
  1025. SO_MAXEXT_EQUAL_BM_SIDE | SO_CHAR_INC_EQUAL_BM_BASE);
  1026. if (bTextPerfectFit)
  1027. {
  1028. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 5);
  1029. I32_OW(pjIoBase, ALU_BG_FN, OVERPAINT);
  1030. I32_OW(pjIoBase, BKGD_COLOR, pboOpaque->iSolidColor);
  1031. goto SkipTransparentInitialization;
  1032. }
  1033. }
  1034. ////////////////////////////////////////////////////////////
  1035. // Transparent Initialization
  1036. ////////////////////////////////////////////////////////////
  1037. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 4);
  1038. I32_OW(pjIoBase, ALU_BG_FN, LEAVE_ALONE);
  1039. SkipTransparentInitialization:
  1040. I32_OW(pjIoBase, DP_CONFIG, EXT_MONO_SRC_HOST | DRAW | WRITE |
  1041. FG_COLOR_SRC_FG | BG_COLOR_SRC_BG |
  1042. LSB_FIRST | BIT16);
  1043. I32_OW(pjIoBase, ALU_FG_FN, OVERPAINT);
  1044. I32_OW(pjIoBase, FRGD_COLOR, pboFore->iSolidColor);
  1045. if ((pfo->cxMax <= GLYPH_CACHE_CX) &&
  1046. ((pstro->rclBkGround.bottom - pstro->rclBkGround.top) <= GLYPH_CACHE_CY))
  1047. {
  1048. pcf = (CACHEDFONT*) pfo->pvConsumer;
  1049. if (pcf == NULL)
  1050. {
  1051. pcf = pcfAllocateCachedFont(ppdev);
  1052. if (pcf == NULL)
  1053. return(FALSE);
  1054. pfo->pvConsumer = pcf;
  1055. }
  1056. // Use our glyph cache:
  1057. if (iDComplexity == DC_TRIVIAL)
  1058. {
  1059. do {
  1060. if (pstro->pgp != NULL)
  1061. {
  1062. // There's only the one batch of glyphs, so save ourselves
  1063. // a call:
  1064. pgp = pstro->pgp;
  1065. cGlyph = pstro->cGlyphs;
  1066. bMoreGlyphs = FALSE;
  1067. }
  1068. else
  1069. {
  1070. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyph, &pgp);
  1071. }
  1072. if (cGlyph > 0)
  1073. {
  1074. if (pstro->ulCharInc == 0)
  1075. {
  1076. if (!bI32CachedProportionalText(ppdev, pcf, pgp, cGlyph))
  1077. return(FALSE);
  1078. }
  1079. else
  1080. {
  1081. if (!bI32CachedFixedText(ppdev, pcf, pgp, cGlyph, pstro->ulCharInc))
  1082. return(FALSE);
  1083. }
  1084. }
  1085. } while (bMoreGlyphs);
  1086. }
  1087. else
  1088. {
  1089. if (!bI32CachedClippedText(ppdev, pcf, pstro, pco))
  1090. return(FALSE);
  1091. }
  1092. }
  1093. else
  1094. {
  1095. DISPDBG((4, "Text too big to cache: %li x %li",
  1096. pfo->cxMax, pstro->rclBkGround.bottom - pstro->rclBkGround.top));
  1097. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 1);
  1098. I32_OW(pjIoBase, DP_CONFIG, EXT_MONO_SRC_HOST | DRAW | WRITE |
  1099. FG_COLOR_SRC_FG | BG_COLOR_SRC_BG);
  1100. return bI32GeneralText(ppdev, pstro, pco);
  1101. }
  1102. return(TRUE);
  1103. }
  1104. /******************************Public*Routine******************************\
  1105. * BOOL bM32CachedProportionalText
  1106. *
  1107. * Draws proportionally spaced glyphs via glyph caching.
  1108. *
  1109. \**************************************************************************/
  1110. BOOL bM32CachedProportionalText(
  1111. PDEV* ppdev,
  1112. CACHEDFONT* pcf,
  1113. GLYPHPOS* pgp,
  1114. LONG cGlyph)
  1115. {
  1116. BYTE* pjMmBase;
  1117. HGLYPH hg;
  1118. CACHEDGLYPH* pcg;
  1119. LONG xOffset;
  1120. LONG yOffset;
  1121. LONG x;
  1122. LONG y;
  1123. LONG cw;
  1124. WORD* pw;
  1125. pjMmBase = ppdev->pjMmBase;
  1126. xOffset = ppdev->xOffset;
  1127. yOffset = ppdev->yOffset;
  1128. do {
  1129. hg = pgp->hg;
  1130. pcg = pcf->apcg[GLYPH_HASH_FUNC(hg)];
  1131. while (pcg->hg < hg) {
  1132. pcg = pcg->pcgNext;
  1133. }
  1134. if (pcg->hg > hg)
  1135. {
  1136. // This will hopefully not be the common case (that is,
  1137. // we will have a high cache hit rate), so if I were
  1138. // writing this in Asm I would have this out-of-line
  1139. // to avoid the jump around for the common case.
  1140. // But the Pentium has branch prediction, so what the
  1141. // heck.
  1142. pcg = pcgNew(ppdev, pcf, pgp);
  1143. if (pcg == NULL)
  1144. return(FALSE);
  1145. }
  1146. // Space glyphs are trimmed to a height of zero, and we don't
  1147. // even have to touch the hardware for them:
  1148. if (pcg->cx != 0)
  1149. {
  1150. // The glyph's origin y-coordinate may often be negative, so we
  1151. // can't compute this as follows:
  1152. //
  1153. // x = pgp->ptl.x + pcg->ptlOrigin.x;
  1154. // y = pgp->ptl.y + pcg->ptlOrigin.y;
  1155. ASSERTDD((pgp->ptl.y + pcg->ptlOrigin.y) >= 0,
  1156. "Can't have negative 'y' coordinates here");
  1157. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 5);
  1158. x = xOffset + pgp->ptl.x + pcg->ptlOrigin.x;
  1159. M32_OW(pjMmBase, CUR_X, x);
  1160. M32_OW(pjMmBase, DEST_X_START, x);
  1161. M32_OW(pjMmBase, DEST_X_END, x + pcg->cx);
  1162. y = yOffset + pgp->ptl.y + pcg->ptlOrigin.y;
  1163. M32_OW(pjMmBase, CUR_Y, y);
  1164. M32_OW(pjMmBase, DEST_Y_END, y + pcg->cy);
  1165. // Take advantage of wait-stated I/O:
  1166. pw = (WORD*) &pcg->ad[0];
  1167. cw = pcg->cw;
  1168. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 10);
  1169. do {
  1170. M32_OW_DIRECT(pjMmBase, PIX_TRANS, *pw);
  1171. } while (pw++, --cw != 0);
  1172. }
  1173. } while (pgp++, --cGlyph != 0);
  1174. return(TRUE);
  1175. }
  1176. /******************************Public*Routine******************************\
  1177. * BOOL bM32CachedFixedText
  1178. *
  1179. * Draws fixed spaced glyphs via glyph caching.
  1180. *
  1181. \*************************************************************************/
  1182. BOOL bM32CachedFixedText(
  1183. PDEV* ppdev,
  1184. CACHEDFONT* pcf,
  1185. GLYPHPOS* pgp,
  1186. LONG cGlyph,
  1187. ULONG ulCharInc)
  1188. {
  1189. BYTE* pjMmBase;
  1190. LONG xGlyph;
  1191. LONG yGlyph;
  1192. HGLYPH hg;
  1193. CACHEDGLYPH* pcg;
  1194. LONG x;
  1195. LONG y;
  1196. WORD* pw;
  1197. LONG cw;
  1198. pjMmBase = ppdev->pjMmBase;
  1199. // Convert to absolute coordinates:
  1200. xGlyph = pgp->ptl.x + ppdev->xOffset;
  1201. yGlyph = pgp->ptl.y + ppdev->yOffset;
  1202. do {
  1203. hg = pgp->hg;
  1204. pcg = pcf->apcg[GLYPH_HASH_FUNC(hg)];
  1205. while (pcg->hg < hg) {
  1206. pcg = pcg->pcgNext;
  1207. }
  1208. if (pcg->hg > hg)
  1209. {
  1210. // This will hopefully not be the common case (that is,
  1211. // we will have a high cache hit rate), so if I were
  1212. // writing this in Asm I would have this out-of-line
  1213. // to avoid the jump around for the common case.
  1214. // But the Pentium has branch prediction, so what the
  1215. // heck.
  1216. pcg = pcgNew(ppdev, pcf, pgp);
  1217. if (pcg == NULL)
  1218. return(FALSE);
  1219. }
  1220. // Space glyphs are trimmed to a height of zero, and we don't
  1221. // even have to touch the hardware for them:
  1222. if (pcg->cx != 0)
  1223. {
  1224. x = xGlyph + pcg->ptlOrigin.x;
  1225. y = yGlyph + pcg->ptlOrigin.y;
  1226. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 5);
  1227. M32_OW(pjMmBase, CUR_X, x);
  1228. M32_OW(pjMmBase, DEST_X_START, x);
  1229. M32_OW(pjMmBase, DEST_X_END, x + pcg->cx);
  1230. M32_OW(pjMmBase, CUR_Y, y);
  1231. M32_OW(pjMmBase, DEST_Y_END, y + pcg->cy);
  1232. // Take advantage of wait-stated I/O:
  1233. pw = (WORD*) &pcg->ad[0];
  1234. cw = pcg->cw;
  1235. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 10);
  1236. do {
  1237. M32_OW_DIRECT(pjMmBase, PIX_TRANS, *pw);
  1238. } while (pw++, --cw != 0);
  1239. }
  1240. xGlyph += ulCharInc;
  1241. } while (pgp++, --cGlyph != 0);
  1242. return(TRUE);
  1243. }
  1244. /******************************Public*Routine******************************\
  1245. * BOOL bM32CachedClippedText
  1246. *
  1247. * Draws clipped text via glyph caching.
  1248. *
  1249. \**************************************************************************/
  1250. BOOL bM32CachedClippedText(
  1251. PDEV* ppdev,
  1252. CACHEDFONT* pcf,
  1253. STROBJ* pstro,
  1254. CLIPOBJ* pco)
  1255. {
  1256. BOOL bRet;
  1257. BYTE* pjMmBase;
  1258. LONG xOffset;
  1259. LONG yOffset;
  1260. BOOL bMoreGlyphs;
  1261. ULONG cGlyphOriginal;
  1262. ULONG cGlyph;
  1263. BOOL bClippingSet;
  1264. GLYPHPOS* pgpOriginal;
  1265. GLYPHPOS* pgp;
  1266. LONG xGlyph;
  1267. LONG yGlyph;
  1268. LONG x;
  1269. LONG y;
  1270. LONG xRight;
  1271. LONG yBottom;
  1272. LONG cy;
  1273. BOOL bMore;
  1274. CLIPENUM ce;
  1275. RECTL* prclClip;
  1276. ULONG ulCharInc;
  1277. HGLYPH hg;
  1278. CACHEDGLYPH* pcg;
  1279. WORD* pw;
  1280. LONG cw;
  1281. ASSERTDD((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL),
  1282. "Don't expect trivial clipping in this function");
  1283. bRet = TRUE;
  1284. pjMmBase = ppdev->pjMmBase;
  1285. xOffset = ppdev->xOffset;
  1286. yOffset = ppdev->yOffset;
  1287. ulCharInc = pstro->ulCharInc;
  1288. do {
  1289. if (pstro->pgp != NULL)
  1290. {
  1291. // There's only the one batch of glyphs, so save ourselves
  1292. // a call:
  1293. pgpOriginal = pstro->pgp;
  1294. cGlyphOriginal = pstro->cGlyphs;
  1295. bMoreGlyphs = FALSE;
  1296. }
  1297. else
  1298. {
  1299. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphOriginal, &pgpOriginal);
  1300. }
  1301. if (cGlyphOriginal > 0)
  1302. {
  1303. if (pco->iDComplexity == DC_RECT)
  1304. {
  1305. // We could call 'cEnumStart' and 'bEnum' when the clipping is
  1306. // DC_RECT, but the last time I checked, those two calls took
  1307. // more than 150 instructions to go through GDI. Since
  1308. // 'rclBounds' already contains the DC_RECT clip rectangle,
  1309. // and since it's such a common case, we'll special case it:
  1310. bMore = FALSE;
  1311. ce.c = 1;
  1312. prclClip = &pco->rclBounds;
  1313. goto SingleRectangle;
  1314. }
  1315. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  1316. do {
  1317. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  1318. for (prclClip = &ce.arcl[0]; ce.c != 0; ce.c--, prclClip++)
  1319. {
  1320. SingleRectangle:
  1321. // We don't always simply set the clipping rectangle here
  1322. // because it may actually end up that no text intersects
  1323. // this clip rectangle, so it would be for naught. This
  1324. // actually happens a lot when using NT's analog clock set
  1325. // to always-on-top, with a round shape:
  1326. bClippingSet = FALSE;
  1327. pgp = pgpOriginal;
  1328. cGlyph = cGlyphOriginal;
  1329. // We can't yet convert to absolute coordinates by adding
  1330. // in 'xOffset' or 'yOffset' here because we have yet to
  1331. // compare the coordinates to 'prclClip':
  1332. xGlyph = pgp->ptl.x;
  1333. yGlyph = pgp->ptl.y;
  1334. // Loop through all the glyphs for this rectangle:
  1335. while (TRUE)
  1336. {
  1337. hg = pgp->hg;
  1338. pcg = pcf->apcg[GLYPH_HASH_FUNC(hg)];
  1339. while (pcg->hg < hg)
  1340. pcg = pcg->pcgNext;
  1341. if (pcg->hg > hg)
  1342. {
  1343. // This will hopefully not be the common case (that is,
  1344. // we will have a high cache hit rate), so if I were
  1345. // writing this in Asm I would have this out-of-line
  1346. // to avoid the jump around for the common case.
  1347. // But the Pentium has branch prediction, so what the
  1348. // heck.
  1349. pcg = pcgNew(ppdev, pcf, pgp);
  1350. if (pcg == NULL)
  1351. {
  1352. bRet = FALSE;
  1353. goto AllDone;
  1354. }
  1355. }
  1356. // Space glyphs are trimmed to a height of zero, and we don't
  1357. // even have to touch the hardware for them:
  1358. cy = pcg->cy;
  1359. if (cy != 0)
  1360. {
  1361. y = pcg->ptlOrigin.y + yGlyph;
  1362. x = pcg->ptlOrigin.x + xGlyph;
  1363. xRight = pcg->cx + x;
  1364. yBottom = pcg->cy + y;
  1365. // Do trivial rejection:
  1366. if ((prclClip->right > x) &&
  1367. (prclClip->bottom > y) &&
  1368. (prclClip->left < xRight) &&
  1369. (prclClip->top < yBottom))
  1370. {
  1371. // Lazily set the hardware clipping:
  1372. if (!bClippingSet)
  1373. {
  1374. bClippingSet = TRUE;
  1375. vSetClipping(ppdev, prclClip);
  1376. }
  1377. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 5);
  1378. M32_OW(pjMmBase, CUR_X, xOffset + x);
  1379. M32_OW(pjMmBase, DEST_X_START, xOffset + x);
  1380. M32_OW(pjMmBase, DEST_X_END, xOffset + xRight);
  1381. M32_OW(pjMmBase, CUR_Y, yOffset + y);
  1382. M32_OW(pjMmBase, DEST_Y_END, yOffset + yBottom);
  1383. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 10);
  1384. pw = (WORD*) &pcg->ad[0];
  1385. cw = pcg->cw;
  1386. do {
  1387. M32_OW_DIRECT(pjMmBase, PIX_TRANS, *pw);
  1388. } while (pw++, --cw != 0);
  1389. }
  1390. }
  1391. if (--cGlyph == 0)
  1392. break;
  1393. // Get ready for next glyph:
  1394. pgp++;
  1395. if (ulCharInc == 0)
  1396. {
  1397. xGlyph = pgp->ptl.x;
  1398. yGlyph = pgp->ptl.y;
  1399. }
  1400. else
  1401. {
  1402. xGlyph += ulCharInc;
  1403. }
  1404. }
  1405. }
  1406. } while (bMore);
  1407. }
  1408. } while (bMoreGlyphs);
  1409. AllDone:
  1410. vResetClipping(ppdev);
  1411. return(bRet);
  1412. }
  1413. VOID vM32DataPortOutB(PDEV *ppdev, PBYTE pb, UINT count)
  1414. {
  1415. BYTE *pjMmBase = ppdev->pjMmBase;
  1416. UINT i;
  1417. for (i=0; i < count; i++)
  1418. {
  1419. if (i % 8 == 0)
  1420. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 10);
  1421. M32_OB(pjMmBase, PIX_TRANS + 1, *((PUCHAR)pb)++);
  1422. }
  1423. }
  1424. /******************************Public*Routine******************************\
  1425. * BOOL bM32GeneralText
  1426. *
  1427. \**************************************************************************/
  1428. BOOL bM32GeneralText(
  1429. PDEV* ppdev,
  1430. STROBJ* pstro,
  1431. CLIPOBJ* pco)
  1432. {
  1433. BYTE* pjMmBase;
  1434. BYTE iDComplexity;
  1435. BOOL bMoreGlyphs;
  1436. ULONG cGlyphOriginal;
  1437. ULONG cGlyph;
  1438. GLYPHPOS* pgpOriginal;
  1439. GLYPHPOS* pgp;
  1440. GLYPHBITS* pgb;
  1441. POINTL ptlOrigin;
  1442. BOOL bMore;
  1443. CLIPENUM ce;
  1444. RECTL* prclClip;
  1445. ULONG ulCharInc;
  1446. LONG cxGlyph;
  1447. LONG cyGlyph;
  1448. LONG xBiasL = 0;
  1449. LONG xBiasR = 0;
  1450. LONG yBiasT = 0;
  1451. LONG cy = 0;
  1452. LONG cx = 0;
  1453. BYTE* pjGlyph;
  1454. LONG xLeft;
  1455. LONG yTop;
  1456. LONG xRight;
  1457. LONG yBottom;
  1458. RECTL NoClip;
  1459. LONG x;
  1460. LONG y;
  1461. pjMmBase = ppdev->pjMmBase;
  1462. /* Define Default Clipping area to be full video ram */
  1463. NoClip.top = 0;
  1464. NoClip.left = 0;
  1465. NoClip.right = ppdev->cxScreen;
  1466. NoClip.bottom = ppdev->cyScreen;
  1467. if (pco == NULL)
  1468. iDComplexity = DC_TRIVIAL;
  1469. else
  1470. iDComplexity = pco->iDComplexity;
  1471. do {
  1472. if (pstro->pgp != NULL)
  1473. {
  1474. // There's only the one batch of glyphs, so save ourselves
  1475. // a call:
  1476. pgpOriginal = pstro->pgp;
  1477. cGlyphOriginal = pstro->cGlyphs;
  1478. bMoreGlyphs = FALSE;
  1479. }
  1480. else
  1481. {
  1482. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphOriginal, &pgpOriginal);
  1483. }
  1484. if (cGlyphOriginal > 0)
  1485. {
  1486. ulCharInc = pstro->ulCharInc;
  1487. if (iDComplexity != DC_COMPLEX)
  1488. {
  1489. // We could call 'cEnumStart' and 'bEnum' when the clipping is
  1490. // DC_RECT, but the last time I checked, those two calls took
  1491. // more than 150 instructions to go through GDI. Since
  1492. // 'rclBounds' already contains the DC_RECT clip rectangle,
  1493. // and since it's such a common case, we'll special case it:
  1494. bMore = FALSE;
  1495. ce.c = 1;
  1496. if (iDComplexity == DC_TRIVIAL)
  1497. prclClip = &NoClip;
  1498. else
  1499. prclClip = &pco->rclBounds;
  1500. goto SingleRectangle;
  1501. }
  1502. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  1503. do {
  1504. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  1505. for (prclClip = &ce.arcl[0]; ce.c != 0; ce.c--, prclClip++)
  1506. {
  1507. SingleRectangle:
  1508. pgp = pgpOriginal;
  1509. cGlyph = cGlyphOriginal;
  1510. pgb = pgp->pgdf->pgb;
  1511. ptlOrigin.x = pgb->ptlOrigin.x + pgp->ptl.x;
  1512. ptlOrigin.y = pgb->ptlOrigin.y + pgp->ptl.y;
  1513. vSetClipping(ppdev, prclClip);
  1514. //ppdev->lRightScissor = rclRealClip.right; ???
  1515. // Loop through all the glyphs for this rectangle:
  1516. while (TRUE)
  1517. {
  1518. cxGlyph = pgb->sizlBitmap.cx;
  1519. cyGlyph = pgb->sizlBitmap.cy;
  1520. pjGlyph = (BYTE*) pgb->aj;
  1521. if ((prclClip->left <= ptlOrigin.x) &&
  1522. (prclClip->top <= ptlOrigin.y) &&
  1523. (prclClip->right >= ptlOrigin.x + cxGlyph) &&
  1524. (prclClip->bottom >= ptlOrigin.y + cyGlyph))
  1525. {
  1526. //-----------------------------------------------------
  1527. // Unclipped glyph
  1528. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 6);
  1529. x = ppdev->xOffset + ptlOrigin.x;
  1530. M32_OW(pjMmBase, CUR_X, LOWORD(x));
  1531. M32_OW(pjMmBase, DEST_X_START, LOWORD(x));
  1532. M32_OW(pjMmBase, DEST_X_END, LOWORD(x) + ROUND8(cxGlyph) );
  1533. M32_OW(pjMmBase, SCISSOR_R, LOWORD(x) + cxGlyph-1);
  1534. y = ppdev->yOffset + ptlOrigin.y;
  1535. M32_OW(pjMmBase, CUR_Y, LOWORD(y));
  1536. M32_OW(pjMmBase, DEST_Y_END, (LOWORD(y) + cyGlyph));
  1537. vM32DataPortOutB(ppdev, pjGlyph, (ROUND8(cxGlyph) * cyGlyph) >> 3);
  1538. /*
  1539. _vBlit_DSC_SH1UP(ppdev,ptlOrigin.x, ptlOrigin.y,
  1540. cxGlyph, cyGlyph, pjGlyph,
  1541. (ROUND8(cxGlyph) * cyGlyph) >> 3);
  1542. */
  1543. }
  1544. else
  1545. {
  1546. //-----------------------------------------------------
  1547. // Clipped glyph
  1548. // Find the intersection of the glyph rectangle
  1549. // and the clip rectangle:
  1550. xLeft = max(prclClip->left, ptlOrigin.x);
  1551. yTop = max(prclClip->top, ptlOrigin.y);
  1552. xRight = min(prclClip->right, ptlOrigin.x + cxGlyph);
  1553. yBottom = min(prclClip->bottom, ptlOrigin.y + cyGlyph);
  1554. // Check for trivial rejection:
  1555. if ( ( ptlOrigin.x <= prclClip->left ) &&
  1556. (ppdev->pModeInfo->ModeFlags & AMI_TEXTBAND) )
  1557. {
  1558. vResetClipping(ppdev);
  1559. return FALSE;
  1560. }
  1561. if (((cx = xRight - xLeft) > 0) &&
  1562. ((cy = yBottom - yTop) > 0))
  1563. {
  1564. /* Do software clipping */
  1565. /* Calculated the Bias in pixels */
  1566. yBiasT = (yTop - ptlOrigin.y);
  1567. /* change address of pjGlyph to point +yBiasT
  1568. scan lines into the Glyph */
  1569. pjGlyph += (yBiasT * (ROUND8(cxGlyph) >> 3));
  1570. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 6);
  1571. x = ppdev->xOffset + ptlOrigin.x;
  1572. M32_OW(pjMmBase, CUR_X, LOWORD(x));
  1573. M32_OW(pjMmBase, DEST_X_START, LOWORD(x));
  1574. M32_OW(pjMmBase, DEST_X_END, LOWORD(x) + ROUND8(cxGlyph) );
  1575. M32_OW(pjMmBase, SCISSOR_R, LOWORD(x) + cxGlyph-1);
  1576. y = ppdev->yOffset + ptlOrigin.y;
  1577. M32_OW(pjMmBase, CUR_Y, LOWORD(y+yBiasT));
  1578. M32_OW(pjMmBase, DEST_Y_END, (LOWORD(y+yBiasT) + cy));
  1579. vM32DataPortOutB(ppdev, pjGlyph, (ROUND8(cxGlyph) >> 3) * cy);
  1580. /*
  1581. _vBlit_DSC_SH1UP(ppdev,ptlOrigin.x,ptlOrigin.y+yBiasT,
  1582. cxGlyph, cy, pjGlyph,
  1583. (ROUND8(cxGlyph) >>3) * cy);
  1584. */
  1585. } /*if*/
  1586. }
  1587. if (--cGlyph == 0)
  1588. break;
  1589. // Get ready for next glyph:
  1590. pgp++;
  1591. pgb = pgp->pgdf->pgb;
  1592. if (ulCharInc == 0)
  1593. {
  1594. ptlOrigin.x = pgp->ptl.x + pgb->ptlOrigin.x;
  1595. ptlOrigin.y = pgp->ptl.y + pgb->ptlOrigin.y;
  1596. }
  1597. else
  1598. {
  1599. ptlOrigin.x += ulCharInc;
  1600. }
  1601. }
  1602. }
  1603. } while (bMore);
  1604. }
  1605. } while (bMoreGlyphs);
  1606. vResetClipping(ppdev);
  1607. return TRUE;
  1608. }
  1609. /******************************Public*Routine******************************\
  1610. * BOOL bM32TextOut
  1611. *
  1612. \**************************************************************************/
  1613. BOOL bM32TextOut(
  1614. PDEV* ppdev,
  1615. STROBJ* pstro,
  1616. FONTOBJ* pfo,
  1617. CLIPOBJ* pco,
  1618. RECTL* prclOpaque,
  1619. BRUSHOBJ* pboFore,
  1620. BRUSHOBJ* pboOpaque)
  1621. {
  1622. BYTE* pjMmBase;
  1623. LONG xOffset;
  1624. LONG yOffset;
  1625. ULONG cGlyph;
  1626. BOOL bMoreGlyphs;
  1627. GLYPHPOS* pgp;
  1628. BYTE iDComplexity;
  1629. CACHEDFONT* pcf;
  1630. RECTL rclOpaque;
  1631. BOOL bTextPerfectFit;
  1632. pjMmBase = ppdev->pjMmBase;
  1633. xOffset = ppdev->xOffset;
  1634. yOffset = ppdev->yOffset;
  1635. iDComplexity = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  1636. if (prclOpaque != NULL)
  1637. {
  1638. ////////////////////////////////////////////////////////////
  1639. // Opaque Initialization
  1640. ////////////////////////////////////////////////////////////
  1641. if (iDComplexity == DC_TRIVIAL)
  1642. {
  1643. DrawOpaqueRect:
  1644. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 8);
  1645. M32_OW(pjMmBase, FRGD_COLOR, pboOpaque->iSolidColor);
  1646. M32_OW(pjMmBase, ALU_FG_FN, OVERPAINT);
  1647. M32_OW(pjMmBase, DP_CONFIG, FG_COLOR_SRC_FG | WRITE | DRAW);
  1648. M32_OW(pjMmBase, CUR_X, xOffset + prclOpaque->left);
  1649. M32_OW(pjMmBase, DEST_X_START, xOffset + prclOpaque->left);
  1650. M32_OW(pjMmBase, DEST_X_END, xOffset + prclOpaque->right);
  1651. M32_OW(pjMmBase, CUR_Y, yOffset + prclOpaque->top);
  1652. vM32QuietDown(ppdev, pjMmBase);
  1653. M32_OW(pjMmBase, DEST_Y_END, yOffset + prclOpaque->bottom);
  1654. }
  1655. else if (iDComplexity == DC_RECT)
  1656. {
  1657. if (bIntersect(prclOpaque, &pco->rclBounds, &rclOpaque))
  1658. {
  1659. prclOpaque = &rclOpaque;
  1660. goto DrawOpaqueRect;
  1661. }
  1662. }
  1663. else
  1664. {
  1665. vClipSolid(ppdev, prclOpaque, pboOpaque->iSolidColor, pco);
  1666. }
  1667. bTextPerfectFit = (pstro->flAccel & (SO_ZERO_BEARINGS |
  1668. SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE |
  1669. SO_CHAR_INC_EQUAL_BM_BASE)) ==
  1670. (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT |
  1671. SO_MAXEXT_EQUAL_BM_SIDE | SO_CHAR_INC_EQUAL_BM_BASE);
  1672. if (bTextPerfectFit)
  1673. {
  1674. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 5);
  1675. M32_OW(pjMmBase, ALU_BG_FN, OVERPAINT);
  1676. M32_OW(pjMmBase, BKGD_COLOR, pboOpaque->iSolidColor);
  1677. goto SkipTransparentInitialization;
  1678. }
  1679. }
  1680. ////////////////////////////////////////////////////////////
  1681. // Transparent Initialization
  1682. ////////////////////////////////////////////////////////////
  1683. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
  1684. M32_OW(pjMmBase, ALU_BG_FN, LEAVE_ALONE);
  1685. SkipTransparentInitialization:
  1686. M32_OW(pjMmBase, DP_CONFIG, EXT_MONO_SRC_HOST | DRAW | WRITE |
  1687. FG_COLOR_SRC_FG | BG_COLOR_SRC_BG |
  1688. LSB_FIRST | BIT16);
  1689. M32_OW(pjMmBase, ALU_FG_FN, OVERPAINT);
  1690. M32_OW(pjMmBase, FRGD_COLOR, pboFore->iSolidColor);
  1691. if ((pfo->cxMax <= GLYPH_CACHE_CX) &&
  1692. ((pstro->rclBkGround.bottom - pstro->rclBkGround.top) <= GLYPH_CACHE_CY))
  1693. {
  1694. pcf = (CACHEDFONT*) pfo->pvConsumer;
  1695. if (pcf == NULL)
  1696. {
  1697. pcf = pcfAllocateCachedFont(ppdev);
  1698. if (pcf == NULL)
  1699. return(FALSE);
  1700. pfo->pvConsumer = pcf;
  1701. }
  1702. // Use our glyph cache:
  1703. if (iDComplexity == DC_TRIVIAL)
  1704. {
  1705. do {
  1706. if (pstro->pgp != NULL)
  1707. {
  1708. // There's only the one batch of glyphs, so save ourselves
  1709. // a call:
  1710. pgp = pstro->pgp;
  1711. cGlyph = pstro->cGlyphs;
  1712. bMoreGlyphs = FALSE;
  1713. }
  1714. else
  1715. {
  1716. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyph, &pgp);
  1717. }
  1718. if (cGlyph > 0)
  1719. {
  1720. if (pstro->ulCharInc == 0)
  1721. {
  1722. if (!bM32CachedProportionalText(ppdev, pcf, pgp, cGlyph))
  1723. return(FALSE);
  1724. }
  1725. else
  1726. {
  1727. if (!bM32CachedFixedText(ppdev, pcf, pgp, cGlyph, pstro->ulCharInc))
  1728. return(FALSE);
  1729. }
  1730. }
  1731. } while (bMoreGlyphs);
  1732. }
  1733. else
  1734. {
  1735. if (!bM32CachedClippedText(ppdev, pcf, pstro, pco))
  1736. return(FALSE);
  1737. }
  1738. }
  1739. else
  1740. {
  1741. DISPDBG((4, "Text too big to cache: %li x %li",
  1742. pfo->cxMax, pstro->rclBkGround.bottom - pstro->rclBkGround.top));
  1743. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 1);
  1744. M32_OW(pjMmBase, DP_CONFIG, EXT_MONO_SRC_HOST | DRAW | WRITE |
  1745. FG_COLOR_SRC_FG | BG_COLOR_SRC_BG);
  1746. return bM32GeneralText(ppdev, pstro, pco);
  1747. }
  1748. return(TRUE);
  1749. }
  1750. /******************************Public*Routine******************************\
  1751. * BOOL bM64CachedProportionalText
  1752. *
  1753. * Draws proportionally spaced glyphs via glyph caching.
  1754. *
  1755. \**************************************************************************/
  1756. BOOL bM64CachedProportionalText(
  1757. PDEV* ppdev,
  1758. CACHEDFONT* pcf,
  1759. GLYPHPOS* pgp,
  1760. LONG cGlyph)
  1761. {
  1762. BYTE* pjMmBase;
  1763. HGLYPH hg;
  1764. CACHEDGLYPH* pcg;
  1765. LONG xOffset;
  1766. LONG yOffset;
  1767. LONG x;
  1768. LONG y;
  1769. LONG cd;
  1770. DWORD* pd;
  1771. LONG cFifo;
  1772. pjMmBase = ppdev->pjMmBase;
  1773. xOffset = ppdev->xOffset;
  1774. yOffset = ppdev->yOffset;
  1775. cFifo = 0;
  1776. do {
  1777. hg = pgp->hg;
  1778. pcg = pcf->apcg[GLYPH_HASH_FUNC(hg)];
  1779. while (pcg->hg < hg) {
  1780. pcg = pcg->pcgNext;
  1781. }
  1782. if (pcg->hg > hg)
  1783. {
  1784. // This will hopefully not be the common case (that is,
  1785. // we will have a high cache hit rate), so if I were
  1786. // writing this in Asm I would have this out-of-line
  1787. // to avoid the jump around for the common case.
  1788. // But the Pentium has branch prediction, so what the
  1789. // heck.
  1790. pcg = pcgNew(ppdev, pcf, pgp);
  1791. if (pcg == NULL)
  1792. return(FALSE);
  1793. }
  1794. // Space glyphs are trimmed to a height of zero, and we don't
  1795. // even have to touch the hardware for them:
  1796. if (pcg->cx != 0)
  1797. {
  1798. // The glyph's origin y-coordinate may often be negative, so we
  1799. // can't compute this as follows:
  1800. //
  1801. // x = pgp->ptl.x + pcg->ptlOrigin.x;
  1802. // y = pgp->ptl.y + pcg->ptlOrigin.y;
  1803. ASSERTDD((pgp->ptl.y + pcg->ptlOrigin.y) >= 0,
  1804. "Can't have negative 'y' coordinates here");
  1805. cFifo -= 2;
  1806. if (cFifo < 0)
  1807. {
  1808. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  1809. cFifo = 14;
  1810. }
  1811. x = xOffset + pgp->ptl.x + pcg->ptlOrigin.x;
  1812. y = yOffset + pgp->ptl.y + pcg->ptlOrigin.y;
  1813. M64_OD(pjMmBase, DST_Y_X, PACKXY_FAST(x, y));
  1814. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, pcg->cxy);
  1815. pd = (DWORD*) &pcg->ad[0];
  1816. cd = pcg->cd;
  1817. do {
  1818. if (--cFifo < 0)
  1819. {
  1820. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  1821. cFifo = 15;
  1822. }
  1823. M64_OD(pjMmBase, HOST_DATA0, *pd);
  1824. } while (pd++, --cd != 0);
  1825. }
  1826. } while (pgp++, --cGlyph != 0);
  1827. return(TRUE);
  1828. }
  1829. BOOL bM64CachedProportionalText24(
  1830. PDEV* ppdev,
  1831. CACHEDFONT* pcf,
  1832. GLYPHPOS* pgp,
  1833. LONG cGlyph)
  1834. {
  1835. BYTE* pjMmBase;
  1836. HGLYPH hg;
  1837. CACHEDGLYPH* pcg;
  1838. LONG xOffset;
  1839. LONG yOffset;
  1840. LONG x;
  1841. LONG y;
  1842. LONG cd;
  1843. DWORD* pd;
  1844. LONG cFifo;
  1845. pjMmBase = ppdev->pjMmBase;
  1846. xOffset = ppdev->xOffset;
  1847. yOffset = ppdev->yOffset;
  1848. cFifo = 0;
  1849. do {
  1850. hg = pgp->hg;
  1851. pcg = pcf->apcg[GLYPH_HASH_FUNC(hg)];
  1852. while (pcg->hg < hg) {
  1853. pcg = pcg->pcgNext;
  1854. }
  1855. if (pcg->hg > hg)
  1856. {
  1857. // This will hopefully not be the common case (that is,
  1858. // we will have a high cache hit rate), so if I were
  1859. // writing this in Asm I would have this out-of-line
  1860. // to avoid the jump around for the common case.
  1861. // But the Pentium has branch prediction, so what the
  1862. // heck.
  1863. pcg = pcgNew(ppdev, pcf, pgp);
  1864. if (pcg == NULL)
  1865. return(FALSE);
  1866. }
  1867. // Space glyphs are trimmed to a height of zero, and we don't
  1868. // even have to touch the hardware for them:
  1869. if (pcg->cx != 0)
  1870. {
  1871. // The glyph's origin y-coordinate may often be negative, so we
  1872. // can't compute this as follows:
  1873. //
  1874. // x = pgp->ptl.x + pcg->ptlOrigin.x;
  1875. // y = pgp->ptl.y + pcg->ptlOrigin.y;
  1876. ASSERTDD((pgp->ptl.y + pcg->ptlOrigin.y) >= 0,
  1877. "Can't have negative 'y' coordinates here");
  1878. cFifo -= 3;
  1879. if (cFifo < 0)
  1880. {
  1881. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  1882. cFifo = 13;
  1883. }
  1884. x = (xOffset + pgp->ptl.x + pcg->ptlOrigin.x) * 3;
  1885. y = yOffset + pgp->ptl.y + pcg->ptlOrigin.y;
  1886. M64_OD(pjMmBase, DST_CNTL, 0x83 | (((x + MAX_NEGX*3)/4 % 6) << 8));
  1887. M64_OD(pjMmBase, DST_Y_X, PACKXY_FAST(x, y));
  1888. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, pcg->cxy);
  1889. pd = (DWORD*) &pcg->ad[0];
  1890. cd = pcg->cd;
  1891. do {
  1892. if (--cFifo < 0)
  1893. {
  1894. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  1895. cFifo = 15;
  1896. }
  1897. M64_OD(pjMmBase, HOST_DATA0, *pd);
  1898. } while (pd++, --cd != 0);
  1899. }
  1900. } while (pgp++, --cGlyph != 0);
  1901. return(TRUE);
  1902. }
  1903. /******************************Public*Routine******************************\
  1904. * BOOL bM64CachedFixedText
  1905. *
  1906. * Draws fixed spaced glyphs via glyph caching.
  1907. *
  1908. \*************************************************************************/
  1909. BOOL bM64CachedFixedText(
  1910. PDEV* ppdev,
  1911. CACHEDFONT* pcf,
  1912. GLYPHPOS* pgp,
  1913. LONG cGlyph,
  1914. ULONG ulCharInc)
  1915. {
  1916. BYTE* pjMmBase;
  1917. LONG xGlyph;
  1918. LONG yGlyph;
  1919. HGLYPH hg;
  1920. CACHEDGLYPH* pcg;
  1921. LONG x;
  1922. LONG y;
  1923. DWORD* pd;
  1924. LONG cd;
  1925. LONG cFifo;
  1926. pjMmBase = ppdev->pjMmBase;
  1927. cFifo = 0;
  1928. // Convert to absolute coordinates:
  1929. xGlyph = pgp->ptl.x + ppdev->xOffset;
  1930. yGlyph = pgp->ptl.y + ppdev->yOffset;
  1931. do {
  1932. hg = pgp->hg;
  1933. pcg = pcf->apcg[GLYPH_HASH_FUNC(hg)];
  1934. while (pcg->hg < hg) {
  1935. pcg = pcg->pcgNext;
  1936. }
  1937. if (pcg->hg > hg)
  1938. {
  1939. // This will hopefully not be the common case (that is,
  1940. // we will have a high cache hit rate), so if I were
  1941. // writing this in Asm I would have this out-of-line
  1942. // to avoid the jump around for the common case.
  1943. // But the Pentium has branch prediction, so what the
  1944. // heck.
  1945. pcg = pcgNew(ppdev, pcf, pgp);
  1946. if (pcg == NULL)
  1947. return(FALSE);
  1948. }
  1949. // Space glyphs are trimmed to a height of zero, and we don't
  1950. // even have to touch the hardware for them:
  1951. if (pcg->cx != 0)
  1952. {
  1953. x = xGlyph + pcg->ptlOrigin.x;
  1954. y = yGlyph + pcg->ptlOrigin.y;
  1955. cFifo -= 2;
  1956. if (cFifo < 0)
  1957. {
  1958. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  1959. cFifo = 14;
  1960. }
  1961. M64_OD(pjMmBase, DST_Y_X, PACKXY_FAST(x, y));
  1962. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, pcg->cxy);
  1963. pd = (DWORD*) &pcg->ad[0];
  1964. cd = pcg->cd;
  1965. do {
  1966. if (--cFifo < 0)
  1967. {
  1968. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  1969. cFifo = 15;
  1970. }
  1971. M64_OD(pjMmBase, HOST_DATA0, *pd);
  1972. } while (pd++, --cd != 0);
  1973. }
  1974. xGlyph += ulCharInc;
  1975. } while (pgp++, --cGlyph != 0);
  1976. return(TRUE);
  1977. }
  1978. BOOL bM64CachedFixedText24(
  1979. PDEV* ppdev,
  1980. CACHEDFONT* pcf,
  1981. GLYPHPOS* pgp,
  1982. LONG cGlyph,
  1983. ULONG ulCharInc)
  1984. {
  1985. BYTE* pjMmBase;
  1986. LONG xGlyph;
  1987. LONG yGlyph;
  1988. HGLYPH hg;
  1989. CACHEDGLYPH* pcg;
  1990. LONG x;
  1991. LONG y;
  1992. DWORD* pd;
  1993. LONG cd;
  1994. LONG cFifo;
  1995. pjMmBase = ppdev->pjMmBase;
  1996. cFifo = 0;
  1997. // Convert to absolute coordinates:
  1998. xGlyph = pgp->ptl.x + ppdev->xOffset;
  1999. yGlyph = pgp->ptl.y + ppdev->yOffset;
  2000. do {
  2001. hg = pgp->hg;
  2002. pcg = pcf->apcg[GLYPH_HASH_FUNC(hg)];
  2003. while (pcg->hg < hg) {
  2004. pcg = pcg->pcgNext;
  2005. }
  2006. if (pcg->hg > hg)
  2007. {
  2008. // This will hopefully not be the common case (that is,
  2009. // we will have a high cache hit rate), so if I were
  2010. // writing this in Asm I would have this out-of-line
  2011. // to avoid the jump around for the common case.
  2012. // But the Pentium has branch prediction, so what the
  2013. // heck.
  2014. pcg = pcgNew(ppdev, pcf, pgp);
  2015. if (pcg == NULL)
  2016. return(FALSE);
  2017. }
  2018. // Space glyphs are trimmed to a height of zero, and we don't
  2019. // even have to touch the hardware for them:
  2020. if (pcg->cx != 0)
  2021. {
  2022. x = (xGlyph + pcg->ptlOrigin.x) * 3;
  2023. y = yGlyph + pcg->ptlOrigin.y;
  2024. cFifo -= 3;
  2025. if (cFifo < 0)
  2026. {
  2027. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  2028. cFifo = 13;
  2029. }
  2030. M64_OD(pjMmBase, DST_CNTL, 0x83 | (((x + MAX_NEGX*3)/4 % 6) << 8));
  2031. M64_OD(pjMmBase, DST_Y_X, PACKXY_FAST(x, y));
  2032. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, pcg->cxy);
  2033. pd = (DWORD*) &pcg->ad[0];
  2034. cd = pcg->cd;
  2035. do {
  2036. if (--cFifo < 0)
  2037. {
  2038. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  2039. cFifo = 15;
  2040. }
  2041. M64_OD(pjMmBase, HOST_DATA0, *pd);
  2042. } while (pd++, --cd != 0);
  2043. }
  2044. xGlyph += ulCharInc;
  2045. } while (pgp++, --cGlyph != 0);
  2046. return(TRUE);
  2047. }
  2048. /******************************Public*Routine******************************\
  2049. * BOOL bM64CachedClippedText
  2050. *
  2051. * Draws clipped text via glyph caching.
  2052. *
  2053. \**************************************************************************/
  2054. BOOL bM64CachedClippedText(
  2055. PDEV* ppdev,
  2056. CACHEDFONT* pcf,
  2057. STROBJ* pstro,
  2058. CLIPOBJ* pco)
  2059. {
  2060. BOOL bRet;
  2061. BYTE* pjMmBase;
  2062. LONG xOffset;
  2063. LONG yOffset;
  2064. BOOL bMoreGlyphs;
  2065. ULONG cGlyphOriginal;
  2066. ULONG cGlyph;
  2067. BOOL bClippingSet;
  2068. GLYPHPOS* pgpOriginal;
  2069. GLYPHPOS* pgp;
  2070. LONG xGlyph;
  2071. LONG yGlyph;
  2072. LONG x;
  2073. LONG y;
  2074. LONG xRight;
  2075. LONG yBottom;
  2076. LONG cy;
  2077. BOOL bMore;
  2078. CLIPENUM ce;
  2079. RECTL* prclClip;
  2080. ULONG ulCharInc;
  2081. HGLYPH hg;
  2082. CACHEDGLYPH* pcg;
  2083. DWORD* pd;
  2084. LONG cd;
  2085. LONG cFifo;
  2086. ASSERTDD((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL),
  2087. "Don't expect trivial clipping in this function");
  2088. bRet = TRUE;
  2089. pjMmBase = ppdev->pjMmBase;
  2090. xOffset = ppdev->xOffset;
  2091. yOffset = ppdev->yOffset;
  2092. ulCharInc = pstro->ulCharInc;
  2093. cFifo = 0;
  2094. do {
  2095. if (pstro->pgp != NULL)
  2096. {
  2097. // There's only the one batch of glyphs, so save ourselves
  2098. // a call:
  2099. pgpOriginal = pstro->pgp;
  2100. cGlyphOriginal = pstro->cGlyphs;
  2101. bMoreGlyphs = FALSE;
  2102. }
  2103. else
  2104. {
  2105. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphOriginal, &pgpOriginal);
  2106. }
  2107. if (cGlyphOriginal > 0)
  2108. {
  2109. if (pco->iDComplexity == DC_RECT)
  2110. {
  2111. // We could call 'cEnumStart' and 'bEnum' when the clipping is
  2112. // DC_RECT, but the last time I checked, those two calls took
  2113. // more than 150 instructions to go through GDI. Since
  2114. // 'rclBounds' already contains the DC_RECT clip rectangle,
  2115. // and since it's such a common case, we'll special case it:
  2116. bMore = FALSE;
  2117. ce.c = 1;
  2118. prclClip = &pco->rclBounds;
  2119. goto SingleRectangle;
  2120. }
  2121. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  2122. do {
  2123. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  2124. for (prclClip = &ce.arcl[0]; ce.c != 0; ce.c--, prclClip++)
  2125. {
  2126. SingleRectangle:
  2127. // We don't always simply set the clipping rectangle here
  2128. // because it may actually end up that no text intersects
  2129. // this clip rectangle, so it would be for naught. This
  2130. // actually happens a lot when using NT's analog clock set
  2131. // to always-on-top, with a round shape:
  2132. bClippingSet = FALSE;
  2133. pgp = pgpOriginal;
  2134. cGlyph = cGlyphOriginal;
  2135. // We can't yet convert to absolute coordinates by adding
  2136. // in 'xOffset' or 'yOffset' here because we have yet to
  2137. // compare the coordinates to 'prclClip':
  2138. xGlyph = pgp->ptl.x;
  2139. yGlyph = pgp->ptl.y;
  2140. // Loop through all the glyphs for this rectangle:
  2141. while (TRUE)
  2142. {
  2143. hg = pgp->hg;
  2144. pcg = pcf->apcg[GLYPH_HASH_FUNC(hg)];
  2145. while (pcg->hg < hg)
  2146. pcg = pcg->pcgNext;
  2147. if (pcg->hg > hg)
  2148. {
  2149. // This will hopefully not be the common case (that is,
  2150. // we will have a high cache hit rate), so if I were
  2151. // writing this in Asm I would have this out-of-line
  2152. // to avoid the jump around for the common case.
  2153. // But the Pentium has branch prediction, so what the
  2154. // heck.
  2155. pcg = pcgNew(ppdev, pcf, pgp);
  2156. if (pcg == NULL)
  2157. {
  2158. bRet = FALSE;
  2159. goto AllDone;
  2160. }
  2161. }
  2162. // Space glyphs are trimmed to a height of zero, and we don't
  2163. // even have to touch the hardware for them:
  2164. cy = pcg->cy;
  2165. if (cy != 0)
  2166. {
  2167. y = pcg->ptlOrigin.y + yGlyph;
  2168. x = pcg->ptlOrigin.x + xGlyph;
  2169. xRight = pcg->cx + x;
  2170. yBottom = pcg->cy + y;
  2171. // Do trivial rejection:
  2172. if ((prclClip->right > x) &&
  2173. (prclClip->bottom > y) &&
  2174. (prclClip->left < xRight) &&
  2175. (prclClip->top < yBottom))
  2176. {
  2177. // Lazily set the hardware clipping:
  2178. if (!bClippingSet)
  2179. {
  2180. bClippingSet = TRUE;
  2181. vSetClipping(ppdev, prclClip);
  2182. cFifo = 0; // Have to initialize count
  2183. }
  2184. cFifo -= 2;
  2185. if (cFifo < 0)
  2186. {
  2187. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  2188. cFifo = 14;
  2189. }
  2190. M64_OD(pjMmBase, DST_Y_X, PACKXY(xOffset + x, yOffset + y));
  2191. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, pcg->cxy);
  2192. pd = (DWORD*) &pcg->ad[0];
  2193. cd = pcg->cd;
  2194. do {
  2195. if (--cFifo < 0)
  2196. {
  2197. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  2198. cFifo = 15;
  2199. }
  2200. M64_OD(pjMmBase, HOST_DATA0, *pd);
  2201. } while (pd++, --cd != 0);
  2202. }
  2203. }
  2204. if (--cGlyph == 0)
  2205. break;
  2206. // Get ready for next glyph:
  2207. pgp++;
  2208. if (ulCharInc == 0)
  2209. {
  2210. xGlyph = pgp->ptl.x;
  2211. yGlyph = pgp->ptl.y;
  2212. }
  2213. else
  2214. {
  2215. xGlyph += ulCharInc;
  2216. }
  2217. }
  2218. }
  2219. } while (bMore);
  2220. }
  2221. } while (bMoreGlyphs);
  2222. AllDone:
  2223. vResetClipping(ppdev);
  2224. return(bRet);
  2225. }
  2226. BOOL bM64CachedClippedText24(
  2227. PDEV* ppdev,
  2228. CACHEDFONT* pcf,
  2229. STROBJ* pstro,
  2230. CLIPOBJ* pco)
  2231. {
  2232. BOOL bRet;
  2233. BYTE* pjMmBase;
  2234. LONG xOffset;
  2235. LONG yOffset;
  2236. BOOL bMoreGlyphs;
  2237. ULONG cGlyphOriginal;
  2238. ULONG cGlyph;
  2239. BOOL bClippingSet;
  2240. GLYPHPOS* pgpOriginal;
  2241. GLYPHPOS* pgp;
  2242. LONG xGlyph;
  2243. LONG yGlyph;
  2244. LONG x;
  2245. LONG y;
  2246. LONG xRight;
  2247. LONG yBottom;
  2248. LONG cy;
  2249. BOOL bMore;
  2250. CLIPENUM ce;
  2251. RECTL* prclClip;
  2252. ULONG ulCharInc;
  2253. HGLYPH hg;
  2254. CACHEDGLYPH* pcg;
  2255. DWORD* pd;
  2256. LONG cd;
  2257. LONG cFifo;
  2258. LONG xTmp;
  2259. ASSERTDD((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL),
  2260. "Don't expect trivial clipping in this function");
  2261. bRet = TRUE;
  2262. pjMmBase = ppdev->pjMmBase;
  2263. xOffset = ppdev->xOffset;
  2264. yOffset = ppdev->yOffset;
  2265. ulCharInc = pstro->ulCharInc;
  2266. cFifo = 0;
  2267. do {
  2268. if (pstro->pgp != NULL)
  2269. {
  2270. // There's only the one batch of glyphs, so save ourselves
  2271. // a call:
  2272. pgpOriginal = pstro->pgp;
  2273. cGlyphOriginal = pstro->cGlyphs;
  2274. bMoreGlyphs = FALSE;
  2275. }
  2276. else
  2277. {
  2278. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphOriginal, &pgpOriginal);
  2279. }
  2280. if (cGlyphOriginal > 0)
  2281. {
  2282. if (pco->iDComplexity == DC_RECT)
  2283. {
  2284. // We could call 'cEnumStart' and 'bEnum' when the clipping is
  2285. // DC_RECT, but the last time I checked, those two calls took
  2286. // more than 150 instructions to go through GDI. Since
  2287. // 'rclBounds' already contains the DC_RECT clip rectangle,
  2288. // and since it's such a common case, we'll special case it:
  2289. bMore = FALSE;
  2290. ce.c = 1;
  2291. prclClip = &pco->rclBounds;
  2292. goto SingleRectangle;
  2293. }
  2294. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  2295. do {
  2296. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  2297. for (prclClip = &ce.arcl[0]; ce.c != 0; ce.c--, prclClip++)
  2298. {
  2299. SingleRectangle:
  2300. // We don't always simply set the clipping rectangle here
  2301. // because it may actually end up that no text intersects
  2302. // this clip rectangle, so it would be for naught. This
  2303. // actually happens a lot when using NT's analog clock set
  2304. // to always-on-top, with a round shape:
  2305. bClippingSet = FALSE;
  2306. pgp = pgpOriginal;
  2307. cGlyph = cGlyphOriginal;
  2308. // We can't yet convert to absolute coordinates by adding
  2309. // in 'xOffset' or 'yOffset' here because we have yet to
  2310. // compare the coordinates to 'prclClip':
  2311. xGlyph = pgp->ptl.x;
  2312. yGlyph = pgp->ptl.y;
  2313. // Loop through all the glyphs for this rectangle:
  2314. while (TRUE)
  2315. {
  2316. hg = pgp->hg;
  2317. pcg = pcf->apcg[GLYPH_HASH_FUNC(hg)];
  2318. while (pcg->hg < hg)
  2319. pcg = pcg->pcgNext;
  2320. if (pcg->hg > hg)
  2321. {
  2322. // This will hopefully not be the common case (that is,
  2323. // we will have a high cache hit rate), so if I were
  2324. // writing this in Asm I would have this out-of-line
  2325. // to avoid the jump around for the common case.
  2326. // But the Pentium has branch prediction, so what the
  2327. // heck.
  2328. pcg = pcgNew(ppdev, pcf, pgp);
  2329. if (pcg == NULL)
  2330. {
  2331. bRet = FALSE;
  2332. goto AllDone;
  2333. }
  2334. }
  2335. // Space glyphs are trimmed to a height of zero, and we don't
  2336. // even have to touch the hardware for them:
  2337. cy = pcg->cy;
  2338. if (cy != 0)
  2339. {
  2340. y = pcg->ptlOrigin.y + yGlyph;
  2341. x = pcg->ptlOrigin.x + xGlyph;
  2342. xRight = pcg->cx + x;
  2343. yBottom = pcg->cy + y;
  2344. // Do trivial rejection:
  2345. if ((prclClip->right > x) &&
  2346. (prclClip->bottom > y) &&
  2347. (prclClip->left < xRight) &&
  2348. (prclClip->top < yBottom))
  2349. {
  2350. // Lazily set the hardware clipping:
  2351. if (!bClippingSet)
  2352. {
  2353. bClippingSet = TRUE;
  2354. vSetClipping(ppdev, prclClip);
  2355. cFifo = 0; // Have to initialize count
  2356. }
  2357. cFifo -= 3;
  2358. if (cFifo < 0)
  2359. {
  2360. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  2361. cFifo = 13;
  2362. }
  2363. xTmp = (xOffset + x) * 3;
  2364. M64_OD(pjMmBase, DST_CNTL, 0x83 | (((xTmp + MAX_NEGX*3)/4 % 6) << 8));
  2365. M64_OD(pjMmBase, DST_Y_X, PACKXY(xTmp, yOffset + y));
  2366. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, pcg->cxy);
  2367. pd = (DWORD*) &pcg->ad[0];
  2368. cd = pcg->cd;
  2369. do {
  2370. if (--cFifo < 0)
  2371. {
  2372. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  2373. cFifo = 15;
  2374. }
  2375. M64_OD(pjMmBase, HOST_DATA0, *pd);
  2376. } while (pd++, --cd != 0);
  2377. }
  2378. }
  2379. if (--cGlyph == 0)
  2380. break;
  2381. // Get ready for next glyph:
  2382. pgp++;
  2383. if (ulCharInc == 0)
  2384. {
  2385. xGlyph = pgp->ptl.x;
  2386. yGlyph = pgp->ptl.y;
  2387. }
  2388. else
  2389. {
  2390. xGlyph += ulCharInc;
  2391. }
  2392. }
  2393. }
  2394. } while (bMore);
  2395. }
  2396. } while (bMoreGlyphs);
  2397. AllDone:
  2398. vResetClipping(ppdev);
  2399. return(bRet);
  2400. }
  2401. /******************************Public*Routine******************************\
  2402. * BOOL bM64GeneralText
  2403. *
  2404. \**************************************************************************/
  2405. BOOL bM64GeneralText(
  2406. PDEV* ppdev,
  2407. STROBJ* pstro,
  2408. CLIPOBJ* pco)
  2409. {
  2410. BYTE* pjMmBase;
  2411. BYTE iDComplexity;
  2412. BOOL bMoreGlyphs;
  2413. ULONG cGlyphOriginal;
  2414. ULONG cGlyph;
  2415. GLYPHPOS* pgpOriginal;
  2416. GLYPHPOS* pgp;
  2417. GLYPHBITS* pgb;
  2418. POINTL ptlOrigin;
  2419. BOOL bMore;
  2420. CLIPENUM ce;
  2421. RECTL* prclClip;
  2422. ULONG ulCharInc;
  2423. LONG cxGlyph;
  2424. LONG cyGlyph;
  2425. LONG xBiasL = 0;
  2426. LONG xBiasR = 0;
  2427. LONG yBiasT = 0;
  2428. LONG cy = 0;
  2429. LONG cx = 0;
  2430. BYTE* pjGlyph;
  2431. LONG xLeft;
  2432. LONG yTop;
  2433. LONG xRight;
  2434. LONG yBottom;
  2435. RECTL NoClip;
  2436. pjMmBase = ppdev->pjMmBase;
  2437. /* Define Default Clipping area to be full video ram */
  2438. NoClip.top = 0;
  2439. NoClip.left = 0;
  2440. NoClip.right = ppdev->cxScreen;
  2441. NoClip.bottom = ppdev->cyScreen;
  2442. if (pco == NULL)
  2443. iDComplexity = DC_TRIVIAL;
  2444. else
  2445. iDComplexity = pco->iDComplexity;
  2446. do {
  2447. if (pstro->pgp != NULL)
  2448. {
  2449. // There's only the one batch of glyphs, so save ourselves
  2450. // a call:
  2451. pgpOriginal = pstro->pgp;
  2452. cGlyphOriginal = pstro->cGlyphs;
  2453. bMoreGlyphs = FALSE;
  2454. }
  2455. else
  2456. {
  2457. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphOriginal, &pgpOriginal);
  2458. }
  2459. if (cGlyphOriginal > 0)
  2460. {
  2461. ulCharInc = pstro->ulCharInc;
  2462. if (iDComplexity != DC_COMPLEX)
  2463. {
  2464. // We could call 'cEnumStart' and 'bEnum' when the clipping is
  2465. // DC_RECT, but the last time I checked, those two calls took
  2466. // more than 150 instructions to go through GDI. Since
  2467. // 'rclBounds' already contains the DC_RECT clip rectangle,
  2468. // and since it's such a common case, we'll special case it:
  2469. bMore = FALSE;
  2470. ce.c = 1;
  2471. if (iDComplexity == DC_TRIVIAL)
  2472. prclClip = &NoClip;
  2473. else
  2474. prclClip = &pco->rclBounds;
  2475. goto SingleRectangle;
  2476. }
  2477. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  2478. do {
  2479. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  2480. for (prclClip = &ce.arcl[0]; ce.c != 0; ce.c--, prclClip++)
  2481. {
  2482. SingleRectangle:
  2483. pgp = pgpOriginal;
  2484. cGlyph = cGlyphOriginal;
  2485. pgb = pgp->pgdf->pgb;
  2486. ptlOrigin.x = pgb->ptlOrigin.x + pgp->ptl.x;
  2487. ptlOrigin.y = pgb->ptlOrigin.y + pgp->ptl.y;
  2488. vSetClipping(ppdev, prclClip);
  2489. //ppdev->lRightScissor = rclRealClip.right; ???
  2490. // Loop through all the glyphs for this rectangle:
  2491. while (TRUE)
  2492. {
  2493. cxGlyph = pgb->sizlBitmap.cx;
  2494. cyGlyph = pgb->sizlBitmap.cy;
  2495. pjGlyph = (BYTE*) pgb->aj;
  2496. if ((prclClip->left <= ptlOrigin.x) &&
  2497. (prclClip->top <= ptlOrigin.y) &&
  2498. (prclClip->right >= ptlOrigin.x + cxGlyph) &&
  2499. (prclClip->bottom >= ptlOrigin.y + cyGlyph))
  2500. {
  2501. //-----------------------------------------------------
  2502. // Unclipped glyph
  2503. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 3);
  2504. M64_OD(pjMmBase, HOST_CNTL, 1);
  2505. M64_OD(pjMmBase, DST_Y_X, ((ppdev->yOffset+ptlOrigin.y) & 0xffff) |
  2506. ((ppdev->xOffset+ptlOrigin.x) << 16));
  2507. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, cyGlyph | cxGlyph << 16);
  2508. vM64DataPortOutB(ppdev, pjGlyph, (ROUND8(cxGlyph) * cyGlyph) >> 3);
  2509. /*
  2510. _vBlit_DSC_SH1UP(ppdev,ptlOrigin.x, ptlOrigin.y,
  2511. cxGlyph, cyGlyph, pjGlyph,
  2512. (ROUND8(cxGlyph) * cyGlyph) >> 3);
  2513. */
  2514. }
  2515. else
  2516. {
  2517. //-----------------------------------------------------
  2518. // Clipped glyph
  2519. // Find the intersection of the glyph rectangle
  2520. // and the clip rectangle:
  2521. xLeft = max(prclClip->left, ptlOrigin.x);
  2522. yTop = max(prclClip->top, ptlOrigin.y);
  2523. xRight = min(prclClip->right, ptlOrigin.x + cxGlyph);
  2524. yBottom = min(prclClip->bottom, ptlOrigin.y + cyGlyph);
  2525. // Check for trivial rejection:
  2526. if ( ( ptlOrigin.x <= prclClip->left ) &&
  2527. (ppdev->pModeInfo->ModeFlags & AMI_TEXTBAND) )
  2528. {
  2529. vResetClipping(ppdev);
  2530. return FALSE;
  2531. }
  2532. if (((cx = xRight - xLeft) > 0) &&
  2533. ((cy = yBottom - yTop) > 0))
  2534. {
  2535. /* Do software clipping */
  2536. /* Calculated the Bias in pixels */
  2537. yBiasT = (yTop - ptlOrigin.y);
  2538. /* change address of pjGlyph to point +yBiasT
  2539. scan lines into the Glyph */
  2540. pjGlyph += (yBiasT * (ROUND8(cxGlyph) >> 3));
  2541. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 3);
  2542. M64_OD(pjMmBase, HOST_CNTL, 1);
  2543. M64_OD(pjMmBase, DST_Y_X, ((ppdev->yOffset+ptlOrigin.y+yBiasT) & 0xffff) |
  2544. ((ppdev->xOffset+ptlOrigin.x) << 16));
  2545. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, cy | cxGlyph << 16);
  2546. vM64DataPortOutB(ppdev, pjGlyph, (ROUND8(cxGlyph) >> 3) * cy);
  2547. /*
  2548. _vBlit_DSC_SH1UP(ppdev,ptlOrigin.x,ptlOrigin.y+yBiasT,
  2549. cxGlyph, cy, pjGlyph,
  2550. (ROUND8(cxGlyph) >>3) * cy);
  2551. */
  2552. } /*if*/
  2553. }
  2554. if (--cGlyph == 0)
  2555. break;
  2556. // Get ready for next glyph:
  2557. pgp++;
  2558. pgb = pgp->pgdf->pgb;
  2559. if (ulCharInc == 0)
  2560. {
  2561. ptlOrigin.x = pgp->ptl.x + pgb->ptlOrigin.x;
  2562. ptlOrigin.y = pgp->ptl.y + pgb->ptlOrigin.y;
  2563. }
  2564. else
  2565. {
  2566. ptlOrigin.x += ulCharInc;
  2567. }
  2568. }
  2569. }
  2570. } while (bMore);
  2571. }
  2572. } while (bMoreGlyphs);
  2573. vResetClipping(ppdev);
  2574. // We must reset the HOST_CNTL register, or else BAD things happen when
  2575. // rendering text in the OTHER functions.
  2576. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 1);
  2577. M64_OD(pjMmBase, HOST_CNTL, 0);
  2578. return TRUE;
  2579. }
  2580. VOID vM64DataPortOutD_24bppmono(PDEV* ppdev, PBYTE pb, UINT count, LONG pitch)
  2581. {
  2582. BYTE* pjMmBase = ppdev->pjMmBase;
  2583. UINT i,j;
  2584. DWORD hostdata, remainder;
  2585. UINT l;
  2586. LONG data24;
  2587. unsigned char data8;
  2588. hostdata = 0;
  2589. l = 0;
  2590. for (i = 0; i < count; i++)
  2591. {
  2592. switch (l)
  2593. {
  2594. case 0:
  2595. // expand 8 to 24bpp
  2596. data24 = 0;
  2597. data8 = *pb++;
  2598. for (j = 0; j < 8; j++)
  2599. {
  2600. data24 <<= 3;
  2601. if ((data8 >> j) & 1)
  2602. {
  2603. data24 |= 7;
  2604. }
  2605. }
  2606. hostdata = data24;
  2607. // expand 8 to 24bpp
  2608. data24 = 0;
  2609. data8 = *pb++;
  2610. for (j = 0; j < 8; j++)
  2611. {
  2612. data24 <<= 3;
  2613. if ((data8 >> j) & 1)
  2614. {
  2615. data24 |= 7;
  2616. }
  2617. }
  2618. remainder = data24;
  2619. hostdata = hostdata | (remainder << 24);
  2620. break;
  2621. case 1:
  2622. data24 = 0;
  2623. data8 = *pb++;
  2624. for (j = 0; j < 8; j++)
  2625. {
  2626. data24 <<= 3;
  2627. if ((data8 >> j) & 1)
  2628. {
  2629. data24 |= 7;
  2630. }
  2631. }
  2632. remainder = data24;
  2633. hostdata = (hostdata >> 8) | (remainder << 16);
  2634. break;
  2635. case 2:
  2636. data24 = 0;
  2637. data8 = *pb++;
  2638. for (j = 0; j < 8; j++)
  2639. {
  2640. data24 <<= 3;
  2641. if ((data8 >> j) & 1)
  2642. {
  2643. data24 |= 7;
  2644. }
  2645. }
  2646. remainder = data24;
  2647. hostdata = (hostdata >> 16) | (remainder << 8);
  2648. break;
  2649. }
  2650. if ((i % 14) == 0)
  2651. {
  2652. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 16);
  2653. }
  2654. M64_OD(pjMmBase, HOST_DATA0, hostdata);
  2655. hostdata = remainder;
  2656. // 24 bpp alignment variable handling
  2657. l = (l+1) % 3;
  2658. }
  2659. }
  2660. BOOL bM64GeneralText24(
  2661. PDEV* ppdev,
  2662. STROBJ* pstro,
  2663. CLIPOBJ* pco)
  2664. {
  2665. BYTE* pjMmBase;
  2666. BYTE iDComplexity;
  2667. BOOL bMoreGlyphs;
  2668. ULONG cGlyphOriginal;
  2669. ULONG cGlyph;
  2670. GLYPHPOS* pgpOriginal;
  2671. GLYPHPOS* pgp;
  2672. GLYPHBITS* pgb;
  2673. POINTL ptlOrigin;
  2674. BOOL bMore;
  2675. CLIPENUM ce;
  2676. RECTL* prclClip;
  2677. ULONG ulCharInc;
  2678. LONG cxGlyph;
  2679. LONG cyGlyph;
  2680. LONG xBiasL = 0;
  2681. LONG xBiasR = 0;
  2682. LONG yBiasT = 0;
  2683. LONG cy = 0;
  2684. LONG cx = 0;
  2685. BYTE* pjGlyph;
  2686. LONG xLeft;
  2687. LONG yTop;
  2688. LONG xRight;
  2689. LONG yBottom;
  2690. RECTL NoClip;
  2691. BOOLEAN resetScissor;
  2692. LONG x;
  2693. DWORD dwCount;
  2694. pjMmBase = ppdev->pjMmBase;
  2695. /* Define Default Clipping area to be full video ram */
  2696. NoClip.top = 0;
  2697. NoClip.left = 0;
  2698. NoClip.right = ppdev->cxScreen;
  2699. NoClip.bottom = ppdev->cyScreen;
  2700. if (pco == NULL)
  2701. iDComplexity = DC_TRIVIAL;
  2702. else
  2703. iDComplexity = pco->iDComplexity;
  2704. do {
  2705. if (pstro->pgp != NULL)
  2706. {
  2707. // There's only the one batch of glyphs, so save ourselves
  2708. // a call:
  2709. pgpOriginal = pstro->pgp;
  2710. cGlyphOriginal = pstro->cGlyphs;
  2711. bMoreGlyphs = FALSE;
  2712. }
  2713. else
  2714. {
  2715. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphOriginal, &pgpOriginal);
  2716. }
  2717. if (cGlyphOriginal > 0)
  2718. {
  2719. ulCharInc = pstro->ulCharInc;
  2720. if (iDComplexity != DC_COMPLEX)
  2721. {
  2722. // We could call 'cEnumStart' and 'bEnum' when the clipping is
  2723. // DC_RECT, but the last time I checked, those two calls took
  2724. // more than 150 instructions to go through GDI. Since
  2725. // 'rclBounds' already contains the DC_RECT clip rectangle,
  2726. // and since it's such a common case, we'll special case it:
  2727. bMore = FALSE;
  2728. ce.c = 1;
  2729. if (iDComplexity == DC_TRIVIAL)
  2730. prclClip = &NoClip;
  2731. else
  2732. prclClip = &pco->rclBounds;
  2733. goto SingleRectangle;
  2734. }
  2735. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  2736. do {
  2737. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  2738. for (prclClip = &ce.arcl[0]; ce.c != 0; ce.c--, prclClip++)
  2739. {
  2740. SingleRectangle:
  2741. pgp = pgpOriginal;
  2742. cGlyph = cGlyphOriginal;
  2743. pgb = pgp->pgdf->pgb;
  2744. ptlOrigin.x = pgb->ptlOrigin.x + pgp->ptl.x;
  2745. ptlOrigin.y = pgb->ptlOrigin.y + pgp->ptl.y;
  2746. vSetClipping(ppdev, prclClip);
  2747. //ppdev->lRightScissor = rclRealClip.right; ???
  2748. // Loop through all the glyphs for this rectangle:
  2749. while (TRUE)
  2750. {
  2751. cxGlyph = pgb->sizlBitmap.cx;
  2752. cyGlyph = pgb->sizlBitmap.cy;
  2753. pjGlyph = (BYTE*) pgb->aj;
  2754. if ((prclClip->left <= ptlOrigin.x) &&
  2755. (prclClip->top <= ptlOrigin.y) &&
  2756. (prclClip->right >= ptlOrigin.x + cxGlyph) &&
  2757. (prclClip->bottom >= ptlOrigin.y + cyGlyph))
  2758. {
  2759. //-----------------------------------------------------
  2760. // Unclipped glyph
  2761. x = ppdev->xOffset+ptlOrigin.x;
  2762. resetScissor = FALSE;
  2763. if ((prclClip->right * 3) - 1 > (x - ppdev->xOffset + cxGlyph) * 3 - 1)
  2764. {
  2765. resetScissor = TRUE;
  2766. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
  2767. M64_OD(pjMmBase, SC_RIGHT, (x + cxGlyph) * 3 - 1);
  2768. }
  2769. else
  2770. {
  2771. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 3);
  2772. }
  2773. M64_OD(pjMmBase, DST_CNTL, 0x83 | (((x + MAX_NEGX)*3/4 % 6) << 8));
  2774. M64_OD(pjMmBase, DST_Y_X, ((ppdev->yOffset+ptlOrigin.y) & 0xffff) |
  2775. (x*3 << 16));
  2776. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, cyGlyph | (ROUND8(cxGlyph) * 3) << 16);
  2777. dwCount = (ROUND8(cxGlyph) * 3 * cyGlyph + 31) / 32;
  2778. vM64DataPortOutD_24bppmono(ppdev, pjGlyph, dwCount, cxGlyph);
  2779. if (resetScissor)
  2780. {
  2781. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 1);
  2782. M64_OD(pjMmBase, SC_RIGHT, (ppdev->xOffset + prclClip->right) * 3 - 1);
  2783. }
  2784. }
  2785. else
  2786. {
  2787. //-----------------------------------------------------
  2788. // Clipped glyph
  2789. // Find the intersection of the glyph rectangle
  2790. // and the clip rectangle:
  2791. xLeft = max(prclClip->left, ptlOrigin.x);
  2792. yTop = max(prclClip->top, ptlOrigin.y);
  2793. xRight = min(prclClip->right, ptlOrigin.x + cxGlyph);
  2794. yBottom = min(prclClip->bottom, ptlOrigin.y + cyGlyph);
  2795. // Check for trivial rejection:
  2796. if ( ( ptlOrigin.x <= prclClip->left ) &&
  2797. (ppdev->pModeInfo->ModeFlags & AMI_TEXTBAND) )
  2798. {
  2799. vResetClipping(ppdev);
  2800. return FALSE;
  2801. }
  2802. if (((cx = xRight - xLeft) > 0) &&
  2803. ((cy = yBottom - yTop) > 0))
  2804. {
  2805. /* Do software clipping */
  2806. /* Calculated the Bias in pixels */
  2807. yBiasT = (yTop - ptlOrigin.y);
  2808. /* change address of pjGlyph to point +yBiasT
  2809. scan lines into the Glyph */
  2810. pjGlyph += (yBiasT * (ROUND8(cxGlyph) >> 3));
  2811. x = ppdev->xOffset+ptlOrigin.x;
  2812. resetScissor = FALSE;
  2813. if ((prclClip->right * 3) - 1 > (x - ppdev->xOffset + cxGlyph) * 3 - 1)
  2814. {
  2815. resetScissor = TRUE;
  2816. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
  2817. M64_OD(pjMmBase, SC_RIGHT, (x + cxGlyph) * 3 - 1);
  2818. }
  2819. else
  2820. {
  2821. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 3);
  2822. }
  2823. M64_OD(pjMmBase, DST_CNTL, 0x83 | (((x + MAX_NEGX)*3/4 % 6) << 8));
  2824. M64_OD(pjMmBase, DST_Y_X, ((ppdev->yOffset+ptlOrigin.y+yBiasT) & 0xffff) |
  2825. (x*3 << 16));
  2826. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, cy | (ROUND8(cxGlyph) * 3) << 16);
  2827. dwCount = (ROUND8(cxGlyph) * 3 * cy + 31) / 32;
  2828. vM64DataPortOutD_24bppmono(ppdev, pjGlyph, dwCount, cxGlyph);
  2829. if (resetScissor)
  2830. {
  2831. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 1);
  2832. M64_OD(pjMmBase, SC_RIGHT, (ppdev->xOffset + prclClip->right) * 3 - 1);
  2833. }
  2834. } /*if*/
  2835. }
  2836. if (--cGlyph == 0)
  2837. break;
  2838. // Get ready for next glyph:
  2839. pgp++;
  2840. pgb = pgp->pgdf->pgb;
  2841. if (ulCharInc == 0)
  2842. {
  2843. ptlOrigin.x = pgp->ptl.x + pgb->ptlOrigin.x;
  2844. ptlOrigin.y = pgp->ptl.y + pgb->ptlOrigin.y;
  2845. }
  2846. else
  2847. {
  2848. ptlOrigin.x += ulCharInc;
  2849. }
  2850. }
  2851. }
  2852. } while (bMore);
  2853. }
  2854. } while (bMoreGlyphs);
  2855. vResetClipping(ppdev);
  2856. return TRUE;
  2857. }
  2858. /******************************Public*Routine******************************\
  2859. * BOOL bM64TextOut
  2860. *
  2861. \**************************************************************************/
  2862. BOOL bM64TextOut(
  2863. PDEV* ppdev,
  2864. STROBJ* pstro,
  2865. FONTOBJ* pfo,
  2866. CLIPOBJ* pco,
  2867. RECTL* prclOpaque,
  2868. BRUSHOBJ* pboFore,
  2869. BRUSHOBJ* pboOpaque)
  2870. {
  2871. BYTE* pjMmBase;
  2872. LONG xOffset;
  2873. LONG yOffset;
  2874. ULONG cGlyph;
  2875. BOOL bMoreGlyphs;
  2876. GLYPHPOS* pgp;
  2877. BYTE iDComplexity;
  2878. CACHEDFONT* pcf;
  2879. RECTL rclOpaque;
  2880. pjMmBase = ppdev->pjMmBase;
  2881. xOffset = ppdev->xOffset;
  2882. yOffset = ppdev->yOffset;
  2883. iDComplexity = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  2884. if (prclOpaque != NULL)
  2885. {
  2886. ////////////////////////////////////////////////////////////
  2887. // Opaque Initialization
  2888. ////////////////////////////////////////////////////////////
  2889. if (iDComplexity == DC_TRIVIAL)
  2890. {
  2891. DrawOpaqueRect:
  2892. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 5);
  2893. M64_OD(pjMmBase, DP_MIX, (OVERPAINT << 16));
  2894. M64_OD(pjMmBase, DP_FRGD_CLR, pboOpaque->iSolidColor);
  2895. M64_OD(pjMmBase, DP_SRC, DP_SRC_FrgdClr << 8);
  2896. M64_OD(pjMmBase, DST_Y_X, PACKXY_FAST(xOffset + prclOpaque->left,
  2897. yOffset + prclOpaque->top));
  2898. M64_OD(pjMmBase, DST_HEIGHT_WIDTH,
  2899. PACKXY_FAST(prclOpaque->right - prclOpaque->left,
  2900. prclOpaque->bottom - prclOpaque->top));
  2901. }
  2902. else if (iDComplexity == DC_RECT)
  2903. {
  2904. if (bIntersect(prclOpaque, &pco->rclBounds, &rclOpaque))
  2905. {
  2906. prclOpaque = &rclOpaque;
  2907. goto DrawOpaqueRect;
  2908. }
  2909. }
  2910. else
  2911. {
  2912. vClipSolid(ppdev, prclOpaque, pboOpaque->iSolidColor, pco);
  2913. }
  2914. // I didn't observe any performance difference between setting
  2915. // the ATI to opaque or transparent mode (when the font allowed
  2916. // it -- some don't).
  2917. }
  2918. ////////////////////////////////////////////////////////////
  2919. // Transparent Initialization
  2920. ////////////////////////////////////////////////////////////
  2921. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 5);
  2922. M64_OD(pjMmBase, CONTEXT_LOAD_CNTL, CONTEXT_LOAD_CmdLoad | ppdev->iDefContext );
  2923. M64_OD(pjMmBase, DP_MIX, (OVERPAINT << 16) | LEAVE_ALONE);
  2924. M64_OD(pjMmBase, DP_FRGD_CLR, pboFore->iSolidColor);
  2925. M64_OD(pjMmBase, DP_SRC, (DP_SRC_Host << 16) | (DP_SRC_FrgdClr << 8) |
  2926. (DP_SRC_BkgdClr));
  2927. // For some reason, the SRC color depth must be monochrome.
  2928. // Otherwise, it will cause wait-for-idle to hang.
  2929. M64_OD(pjMmBase, DP_PIX_WIDTH, ppdev->ulMonoPixelWidth & 0xFFFF00FF);
  2930. if ((pfo->cxMax <= GLYPH_CACHE_CX) &&
  2931. ((pstro->rclBkGround.bottom - pstro->rclBkGround.top) <= GLYPH_CACHE_CY))
  2932. {
  2933. pcf = (CACHEDFONT*) pfo->pvConsumer;
  2934. if (pcf == NULL)
  2935. {
  2936. pcf = pcfAllocateCachedFont(ppdev);
  2937. if (pcf == NULL)
  2938. goto ReturnFalse;
  2939. pfo->pvConsumer = pcf;
  2940. }
  2941. // Use our glyph cache:
  2942. if (iDComplexity == DC_TRIVIAL)
  2943. {
  2944. do {
  2945. if (pstro->pgp != NULL)
  2946. {
  2947. // There's only the one batch of glyphs, so save ourselves
  2948. // a call:
  2949. pgp = pstro->pgp;
  2950. cGlyph = pstro->cGlyphs;
  2951. bMoreGlyphs = FALSE;
  2952. }
  2953. else
  2954. {
  2955. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyph, &pgp);
  2956. }
  2957. if (cGlyph > 0)
  2958. {
  2959. if (pstro->ulCharInc == 0)
  2960. {
  2961. if (!bM64CachedProportionalText(ppdev, pcf, pgp, cGlyph))
  2962. goto ReturnFalse;
  2963. }
  2964. else
  2965. {
  2966. if (!bM64CachedFixedText(ppdev, pcf, pgp, cGlyph, pstro->ulCharInc))
  2967. goto ReturnFalse;
  2968. }
  2969. }
  2970. } while (bMoreGlyphs);
  2971. }
  2972. else
  2973. {
  2974. if (!bM64CachedClippedText(ppdev, pcf, pstro, pco))
  2975. goto ReturnFalse;
  2976. }
  2977. }
  2978. else
  2979. {
  2980. DISPDBG((4, "Text too big to cache: %li x %li",
  2981. pfo->cxMax, pstro->rclBkGround.bottom - pstro->rclBkGround.top));
  2982. if (!bM64GeneralText(ppdev, pstro, pco))
  2983. goto ReturnFalse;
  2984. }
  2985. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 1);
  2986. M64_OD(pjMmBase, DP_PIX_WIDTH, ppdev->ulMonoPixelWidth);
  2987. return(TRUE);
  2988. ReturnFalse:
  2989. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 1);
  2990. M64_OD(pjMmBase, DP_PIX_WIDTH, ppdev->ulMonoPixelWidth);
  2991. return(FALSE);
  2992. }
  2993. BOOL bM64TextOut24(
  2994. PDEV* ppdev,
  2995. STROBJ* pstro,
  2996. FONTOBJ* pfo,
  2997. CLIPOBJ* pco,
  2998. RECTL* prclOpaque,
  2999. BRUSHOBJ* pboFore,
  3000. BRUSHOBJ* pboOpaque)
  3001. {
  3002. BYTE* pjMmBase;
  3003. LONG xOffset;
  3004. LONG yOffset;
  3005. ULONG cGlyph;
  3006. BOOL bMoreGlyphs;
  3007. GLYPHPOS* pgp;
  3008. BYTE iDComplexity;
  3009. CACHEDFONT* pcf;
  3010. RECTL rclOpaque;
  3011. LONG x;
  3012. pjMmBase = ppdev->pjMmBase;
  3013. xOffset = ppdev->xOffset;
  3014. yOffset = ppdev->yOffset;
  3015. iDComplexity = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  3016. if (prclOpaque != NULL)
  3017. {
  3018. ////////////////////////////////////////////////////////////
  3019. // Opaque Initialization
  3020. ////////////////////////////////////////////////////////////
  3021. if (iDComplexity == DC_TRIVIAL)
  3022. {
  3023. DrawOpaqueRect:
  3024. x = (xOffset + prclOpaque->left) * 3;
  3025. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 6);
  3026. M64_OD(pjMmBase, DST_CNTL, 0x83 | ((x/4 % 6) << 8));
  3027. M64_OD(pjMmBase, DP_MIX, (OVERPAINT << 16));
  3028. M64_OD(pjMmBase, DP_FRGD_CLR, pboOpaque->iSolidColor);
  3029. M64_OD(pjMmBase, DP_SRC, DP_SRC_FrgdClr << 8);
  3030. M64_OD(pjMmBase, DST_Y_X, PACKXY_FAST(x,
  3031. yOffset + prclOpaque->top));
  3032. M64_OD(pjMmBase, DST_HEIGHT_WIDTH,
  3033. PACKXY_FAST((prclOpaque->right - prclOpaque->left) * 3,
  3034. prclOpaque->bottom - prclOpaque->top));
  3035. }
  3036. else if (iDComplexity == DC_RECT)
  3037. {
  3038. if (bIntersect(prclOpaque, &pco->rclBounds, &rclOpaque))
  3039. {
  3040. prclOpaque = &rclOpaque;
  3041. goto DrawOpaqueRect;
  3042. }
  3043. }
  3044. else
  3045. {
  3046. vClipSolid(ppdev, prclOpaque, pboOpaque->iSolidColor, pco);
  3047. }
  3048. // I didn't observe any performance difference between setting
  3049. // the ATI to opaque or transparent mode (when the font allowed
  3050. // it -- some don't).
  3051. }
  3052. ////////////////////////////////////////////////////////////
  3053. // Transparent Initialization
  3054. ////////////////////////////////////////////////////////////
  3055. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 5);
  3056. M64_OD(pjMmBase, CONTEXT_LOAD_CNTL, CONTEXT_LOAD_CmdLoad | ppdev->iDefContext );
  3057. M64_OD(pjMmBase, DP_MIX, (OVERPAINT << 16) | LEAVE_ALONE);
  3058. M64_OD(pjMmBase, DP_FRGD_CLR, pboFore->iSolidColor);
  3059. M64_OD(pjMmBase, DP_SRC, (DP_SRC_Host << 16) | (DP_SRC_FrgdClr << 8) |
  3060. (DP_SRC_BkgdClr));
  3061. // For some reason, the SRC color depth must be monochrome.
  3062. // Otherwise, it will cause wait-for-idle to hang.
  3063. M64_OD(pjMmBase, DP_PIX_WIDTH, ppdev->ulMonoPixelWidth & 0xFFFF00FF);
  3064. if ((pfo->cxMax <= GLYPH_CACHE_CX) &&
  3065. ((pstro->rclBkGround.bottom - pstro->rclBkGround.top) <= GLYPH_CACHE_CY))
  3066. {
  3067. pcf = (CACHEDFONT*) pfo->pvConsumer;
  3068. if (pcf == NULL)
  3069. {
  3070. pcf = pcfAllocateCachedFont(ppdev);
  3071. if (pcf == NULL)
  3072. goto ReturnFalse;
  3073. pfo->pvConsumer = pcf;
  3074. }
  3075. // Use our glyph cache:
  3076. if (iDComplexity == DC_TRIVIAL)
  3077. {
  3078. do {
  3079. if (pstro->pgp != NULL)
  3080. {
  3081. // There's only the one batch of glyphs, so save ourselves
  3082. // a call:
  3083. pgp = pstro->pgp;
  3084. cGlyph = pstro->cGlyphs;
  3085. bMoreGlyphs = FALSE;
  3086. }
  3087. else
  3088. {
  3089. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyph, &pgp);
  3090. }
  3091. if (cGlyph > 0)
  3092. {
  3093. if (pstro->ulCharInc == 0)
  3094. {
  3095. if (!bM64CachedProportionalText24(ppdev, pcf, pgp, cGlyph))
  3096. goto ReturnFalse;
  3097. }
  3098. else
  3099. {
  3100. if (!bM64CachedFixedText24(ppdev, pcf, pgp, cGlyph, pstro->ulCharInc))
  3101. goto ReturnFalse;
  3102. }
  3103. }
  3104. } while (bMoreGlyphs);
  3105. }
  3106. else
  3107. {
  3108. if (!bM64CachedClippedText24(ppdev, pcf, pstro, pco))
  3109. goto ReturnFalse;
  3110. }
  3111. }
  3112. else
  3113. {
  3114. DISPDBG((4, "Text too big to cache: %li x %li",
  3115. pfo->cxMax, pstro->rclBkGround.bottom - pstro->rclBkGround.top));
  3116. if (!bM64GeneralText24(ppdev, pstro, pco))
  3117. goto ReturnFalse;
  3118. }
  3119. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 2);
  3120. M64_OD(pjMmBase, DST_CNTL, DST_CNTL_XDir | DST_CNTL_YDir);
  3121. M64_OD(pjMmBase, DP_PIX_WIDTH, ppdev->ulMonoPixelWidth);
  3122. return(TRUE);
  3123. ReturnFalse:
  3124. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 2);
  3125. M64_OD(pjMmBase, DST_CNTL, DST_CNTL_XDir | DST_CNTL_YDir);
  3126. M64_OD(pjMmBase, DP_PIX_WIDTH, ppdev->ulMonoPixelWidth);
  3127. return(FALSE);
  3128. }
  3129. /******************************Public*Routine******************************\
  3130. * BOOL DrvTextOut
  3131. *
  3132. \**************************************************************************/
  3133. BOOL DrvTextOut(
  3134. SURFOBJ* pso,
  3135. STROBJ* pstro,
  3136. FONTOBJ* pfo,
  3137. CLIPOBJ* pco,
  3138. RECTL* prclExtra, // If we had set GCAPS_HORIZSTRIKE, we would have
  3139. // to fill these extra rectangles (it is used
  3140. // largely for underlines). It's not a big
  3141. // performance win (GDI will call our DrvBitBlt
  3142. // to draw the extra rectangles).
  3143. RECTL* prclOpaque,
  3144. BRUSHOBJ* pboFore,
  3145. BRUSHOBJ* pboOpaque,
  3146. POINTL* pptlBrush, // Always unused, unless GCAPS_ARBRUSHOPAQUE set
  3147. MIX mix) // Always a copy mix (0x0d0d)
  3148. {
  3149. PDEV* ppdev;
  3150. DSURF* pdsurf;
  3151. OH* poh;
  3152. // The DDI spec says we'll only ever get foreground and background
  3153. // mixes of R2_COPYPEN:
  3154. ASSERTDD(mix == 0x0d0d, "GDI should only give us a copy mix");
  3155. pdsurf = (DSURF*) pso->dhsurf;
  3156. if (pdsurf->dt != DT_DIB)
  3157. {
  3158. poh = pdsurf->poh;
  3159. ppdev = (PDEV*) pso->dhpdev;
  3160. ppdev->xOffset = poh->x;
  3161. ppdev->yOffset = poh->y;
  3162. if (!ppdev->pfnTextOut(ppdev, pstro, pfo, pco, prclOpaque, pboFore,
  3163. pboOpaque))
  3164. {
  3165. if (DIRECT_ACCESS(ppdev))
  3166. {
  3167. BANK bnk;
  3168. vBankStart(ppdev,
  3169. (prclOpaque != NULL) ? prclOpaque : &pstro->rclBkGround,
  3170. pco,
  3171. &bnk);
  3172. do {
  3173. EngTextOut(bnk.pso, pstro, pfo, bnk.pco, prclExtra, prclOpaque,
  3174. pboFore, pboOpaque, pptlBrush, mix);
  3175. } while (bBankEnum(&bnk));
  3176. }
  3177. else
  3178. {
  3179. BOOL b;
  3180. BYTE* pjBits;
  3181. BYTE* pjScan0;
  3182. HSURF hsurfDst;
  3183. LONG lDelta;
  3184. RECTL rclDst;
  3185. RECTL rclScreen;
  3186. SIZEL sizl;
  3187. SURFOBJ* psoTmp;
  3188. b = FALSE; // For error cases, assume we'll fail
  3189. /*
  3190. rclDst.left = 0;
  3191. rclDst.top = 0;
  3192. rclDst.right = pdsurf->sizl.cx;
  3193. rclDst.bottom = pdsurf->sizl.cy;
  3194. */
  3195. rclDst = (prclOpaque != NULL) ? *prclOpaque : pstro->rclBkGround;
  3196. if ((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL))
  3197. {
  3198. rclDst.left = max(rclDst.left, pco->rclBounds.left);
  3199. rclDst.top = max(rclDst.top, pco->rclBounds.top);
  3200. rclDst.right = min(rclDst.right, pco->rclBounds.right);
  3201. rclDst.bottom = min(rclDst.bottom, pco->rclBounds.bottom);
  3202. }
  3203. sizl.cx = rclDst.right - rclDst.left;
  3204. sizl.cy = rclDst.bottom - rclDst.top;
  3205. {
  3206. // We need to create a temporary work buffer. We have to do
  3207. // some fudging with the offsets so that the upper-left corner
  3208. // of the (relative coordinates) clip object bounds passed to
  3209. // GDI will be transformed to the upper-left corner of our
  3210. // temporary bitmap.
  3211. // The alignment doesn't have to be as tight as this at 16bpp
  3212. // and 32bpp, but it won't hurt:
  3213. lDelta = (((rclDst.right + 3) & ~3L) - (rclDst.left & ~3L))
  3214. * ppdev->cjPelSize;
  3215. // We're actually only allocating a bitmap that is 'sizl.cx' x
  3216. // 'sizl.cy' in size:
  3217. pjBits = AtiAllocMem(LMEM_FIXED, 0, lDelta * sizl.cy);
  3218. if (pjBits == NULL)
  3219. goto Error_2;
  3220. // We now adjust the surface's 'pvScan0' so that when GDI thinks
  3221. // it's writing to pixel (rclDst.top, rclDst.left), it will
  3222. // actually be writing to the upper-left pixel of our temporary
  3223. // bitmap:
  3224. pjScan0 = pjBits - (rclDst.top * lDelta)
  3225. - ((rclDst.left & ~3L) * ppdev->cjPelSize);
  3226. ASSERTDD((((ULONG_PTR) pjScan0) & 3) == 0,
  3227. "pvScan0 must be dword aligned!");
  3228. hsurfDst = (HSURF) EngCreateBitmap(
  3229. sizl, // Bitmap covers rectangle
  3230. lDelta, // Use this delta
  3231. ppdev->iBitmapFormat, // Same colour depth
  3232. BMF_TOPDOWN, // Must have a positive delta
  3233. pjScan0); // Where (0, 0) would be
  3234. if ((hsurfDst == 0) ||
  3235. (!EngAssociateSurface(hsurfDst, ppdev->hdevEng, 0)))
  3236. goto Error_3;
  3237. psoTmp = EngLockSurface(hsurfDst);
  3238. if (psoTmp == NULL)
  3239. goto Error_4;
  3240. // Make sure that the rectangle we Get/Put from/to the screen
  3241. // is in absolute coordinates:
  3242. rclScreen.left = rclDst.left + ppdev->xOffset;
  3243. rclScreen.right = rclDst.right + ppdev->xOffset;
  3244. rclScreen.top = rclDst.top + ppdev->yOffset;
  3245. rclScreen.bottom = rclDst.bottom + ppdev->yOffset;
  3246. ppdev->pfnGetBits(ppdev, psoTmp, &rclDst, (POINTL*) &rclScreen);
  3247. b = EngTextOut(psoTmp, pstro, pfo, pco, prclExtra, prclOpaque,
  3248. pboFore, pboOpaque, pptlBrush, mix);
  3249. ppdev->pfnPutBits(ppdev, psoTmp, &rclScreen, (POINTL*) &rclDst);
  3250. EngUnlockSurface(psoTmp);
  3251. Error_4:
  3252. EngDeleteSurface(hsurfDst);
  3253. Error_3:
  3254. AtiFreeMem(pjBits);
  3255. }
  3256. Error_2:
  3257. return(b);
  3258. }
  3259. }
  3260. }
  3261. else
  3262. {
  3263. // We're drawing to a DFB we've converted to a DIB, so just call GDI
  3264. // to handle it:
  3265. return(EngTextOut(pdsurf->pso, pstro, pfo, pco, prclExtra, prclOpaque,
  3266. pboFore, pboOpaque, pptlBrush, mix));
  3267. }
  3268. return(TRUE);
  3269. }
  3270. /******************************Public*Routine******************************\
  3271. * BOOL bEnableText
  3272. *
  3273. * Performs the necessary setup for the text drawing subcomponent.
  3274. *
  3275. \**************************************************************************/
  3276. BOOL bEnableText(
  3277. PDEV* ppdev)
  3278. {
  3279. return(TRUE);
  3280. }
  3281. /******************************Public*Routine******************************\
  3282. * VOID vDisableText
  3283. *
  3284. * Performs the necessary clean-up for the text drawing subcomponent.
  3285. *
  3286. \**************************************************************************/
  3287. VOID vDisableText(PDEV* ppdev)
  3288. {
  3289. }
  3290. /******************************Public*Routine******************************\
  3291. * VOID vAssertModeText
  3292. *
  3293. * Disables or re-enables the text drawing subcomponent in preparation for
  3294. * full-screen entry/exit.
  3295. *
  3296. \**************************************************************************/
  3297. VOID vAssertModeText(
  3298. PDEV* ppdev,
  3299. BOOL bEnable)
  3300. {
  3301. // If we were to do off-screen glyph caching, we would probably want
  3302. // to invalidate our cache here, because it will get destroyed when
  3303. // we switch to full-screen.
  3304. }
  3305. /******************************Public*Routine******************************\
  3306. * VOID DrvDestroyFont
  3307. *
  3308. * We're being notified that the given font is being deallocated; clean up
  3309. * anything we've stashed in the 'pvConsumer' field of the 'pfo'.
  3310. *
  3311. \**************************************************************************/
  3312. VOID DrvDestroyFont(
  3313. FONTOBJ* pfo)
  3314. {
  3315. CACHEDFONT* pcf;
  3316. pcf = pfo->pvConsumer;
  3317. if (pcf != NULL)
  3318. {
  3319. vFreeCachedFont(pcf);
  3320. pfo->pvConsumer = NULL;
  3321. }
  3322. }