Source code of Windows XP (NT5)
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.

2789 lines
90 KiB

  1. /******************************************************************************\
  2. *
  3. * $Workfile: textout.c $
  4. *
  5. * On every TextOut, GDI provides an array of 'GLYPHPOS' structures for every
  6. * glyph to be drawn. Each GLYPHPOS structure contains a glyph handle and a
  7. * pointer to a monochrome bitmap that describes the glyph. (Note that unlike
  8. * Windows 3.1, which provides a column-major glyph bitmap, Windows NT always
  9. * provides a row-major glyph bitmap.) As such, there are three basic methods
  10. * for drawing text with hardware acceleration:
  11. *
  12. * 1) Glyph caching -- Glyph bitmaps are cached by the accelerator (probably in
  13. * off-screen memory), and text is drawn by referring the hardware to the
  14. * cached glyph locations.
  15. *
  16. * 2) Glyph expansion -- Each individual glyph is color-expanded directly to the
  17. * screen from the monochrome glyph bitmap supplied by GDI.
  18. *
  19. * 3) Buffer expansion -- The CPU is used to draw all the glyphs into a 1bpp
  20. * monochrome bitmap, and the hardware is then used to color-expand the
  21. * result.
  22. *
  23. * The fastest method depends on a number of variables, such as the color
  24. * expansion speed, bus speed, CPU speed, average glyph size, and average string
  25. * length.
  26. *
  27. * Glyph expansion is typically faster than buffer expansion for very large
  28. * glyphs, even on the ISA bus, because less copying by the CPU needs to be
  29. * done. Unfortunately, large glyphs are pretty rare.
  30. *
  31. * An advantange of the buffer expansion method is that opaque text will never
  32. * flash -- the other two methods typically need to draw the opaquing rectangle
  33. * before laying down the glyphs, which may cause a flash if the raster is
  34. * caught at the wrong time.
  35. *
  36. * Copyright (c) 1992-1995 Microsoft Corporation
  37. *
  38. ********************************************************************************
  39. *
  40. * On the CL-GD5436/46 chips we use glyph caching which is a major performance
  41. * gain.
  42. *
  43. * Copyright (c) 1996 Cirrus Logic, Inc.
  44. *
  45. * $Log: S:/projects/drivers/ntsrc/display/textout.c_v $
  46. *
  47. * Rev 1.5 Jan 15 1997 09:43:28 unknown
  48. * Enable font cache for english.
  49. *
  50. * Rev 1.4 Jan 14 1997 15:16:58 unknown
  51. * take out GR33 clearing after 80 blt.
  52. *
  53. * Rev 1.2 Nov 07 1996 16:48:08 unknown
  54. *
  55. *
  56. * Rev 1.1 Oct 10 1996 15:39:28 unknown
  57. *
  58. *
  59. * Rev 1.9 12 Aug 1996 17:12:50 frido
  60. * Changed some comments.
  61. *
  62. * Rev 1.8 12 Aug 1996 16:55:08 frido
  63. * Removed unaccessed local variables.
  64. *
  65. * Rev 1.7 02 Aug 1996 14:50:42 frido
  66. * Fixed reported GPF during mode switching.
  67. * Used another way to bypass the hardware bug.
  68. *
  69. * Rev 1.6 31 Jul 1996 17:56:08 frido
  70. * Fixed clipping.
  71. *
  72. * Rev 1.5 26 Jul 1996 12:56:48 frido
  73. * Removed clipping for now.
  74. *
  75. * Rev 1.4 24 Jul 1996 20:19:26 frido
  76. * Added a chain of FONTCACHE structures.
  77. * Fixed bugs in vDrawGlyph and vClipGlyph.
  78. * Changed vAssertModeText to remove all cached fonts.
  79. *
  80. * Rev 1.3 23 Jul 1996 17:41:52 frido
  81. * Fixed a compile problem after commenting.
  82. *
  83. * Rev 1.2 23 Jul 1996 08:53:00 frido
  84. * Documentation done.
  85. *
  86. * Rev 1.1 22 Jul 1996 20:45:38 frido
  87. * Added font cache.
  88. *
  89. * jl01 10-08-96 Do Transparent BLT w/o Solid Fill. Refer to PDRs#5511/6817.
  90. \******************************************************************************/
  91. #include "precomp.h"
  92. // Handy macros.
  93. #define BUSY_BLT(ppdev, pjBase) (CP_MM_ACL_STAT(ppdev, pjBase) & 0x10)
  94. #define FIFTEEN_BITS ((1 << 15) - 1)
  95. /******************************Public*Routine******************************\
  96. * VOID vClipSolid
  97. *
  98. * Fills the specified rectangles with the specified color, honoring
  99. * the requested clipping. No more than four rectangles should be passed in.
  100. *
  101. * Intended for drawing the areas of the opaquing rectangle that extend
  102. * beyond the text box. The rectangles must be in left to right, top to
  103. * bottom order. Assumes there is at least one rectangle in the list.
  104. *
  105. * Also used as a simple way to do a rectangular solid fill while honoring
  106. * clipping (as in extra rectangles).
  107. *
  108. \**************************************************************************/
  109. VOID vClipSolid(
  110. PDEV* ppdev,
  111. LONG crcl,
  112. RECTL* prcl,
  113. ULONG iColor,
  114. CLIPOBJ* pco)
  115. {
  116. BOOL bMore; // Flag for clip enumeration
  117. CLIPENUM ce; // Clip enumeration object
  118. ULONG i;
  119. ULONG j;
  120. RECTL arclTmp[4];
  121. ULONG crclTmp;
  122. RECTL* prclTmp;
  123. RECTL* prclClipTmp;
  124. LONG iLastBottom;
  125. RECTL* prclClip;
  126. RBRUSH_COLOR rbc;
  127. ASSERTDD((crcl > 0) && (crcl <= 4), "Expected 1 to 4 rectangles");
  128. rbc.iSolidColor = iColor;
  129. if ((!pco) || (pco->iDComplexity == DC_TRIVIAL))
  130. {
  131. (ppdev->pfnFillSolid)(ppdev, 1, prcl, R4_PATCOPY, rbc, NULL);
  132. }
  133. else if (pco->iDComplexity == DC_RECT)
  134. {
  135. crcl = cIntersect(&pco->rclBounds, prcl, crcl);
  136. if (crcl != 0)
  137. {
  138. (ppdev->pfnFillSolid)(ppdev, crcl, prcl, R4_PATCOPY,
  139. rbc, NULL);
  140. }
  141. }
  142. else // iDComplexity == DC_COMPLEX
  143. {
  144. // Bottom of last rectangle to fill
  145. iLastBottom = prcl[crcl - 1].bottom;
  146. // Initialize the clip rectangle enumeration to right-down so we can
  147. // take advantage of the rectangle list being right-down:
  148. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
  149. // Scan through all the clip rectangles, looking for intersects
  150. // of fill areas with region rectangles:
  151. do {
  152. // Get a batch of region rectangles:
  153. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (VOID*)&ce);
  154. // Clip the rect list to each region rect:
  155. for (j = ce.c, prclClip = ce.arcl; j-- > 0; prclClip++)
  156. {
  157. // Since the rectangles and the region enumeration are both
  158. // right-down, we can zip through the region until we reach
  159. // the first fill rect, and are done when we've passed the
  160. // last fill rect.
  161. if (prclClip->top >= iLastBottom)
  162. {
  163. // Past last fill rectangle; nothing left to do:
  164. return;
  165. }
  166. // Do intersection tests only if we've reached the top of
  167. // the first rectangle to fill:
  168. if (prclClip->bottom > prcl->top)
  169. {
  170. // We've reached the top Y scan of the first rect, so
  171. // it's worth bothering checking for intersection.
  172. // Generate a list of the rects clipped to this region
  173. // rect:
  174. prclTmp = prcl;
  175. prclClipTmp = arclTmp;
  176. for (i = crcl, crclTmp = 0; i-- != 0; prclTmp++)
  177. {
  178. // Intersect fill and clip rectangles
  179. if (bIntersect(prclTmp, prclClip, prclClipTmp))
  180. {
  181. // Add to list if anything's left to draw:
  182. crclTmp++;
  183. prclClipTmp++;
  184. }
  185. }
  186. // Draw the clipped rects
  187. if (crclTmp != 0)
  188. {
  189. (ppdev->pfnFillSolid)(ppdev, crclTmp, &arclTmp[0],
  190. R4_PATCOPY, rbc, NULL);
  191. }
  192. }
  193. }
  194. } while (bMore);
  195. }
  196. }
  197. #if 0 //removed
  198. BOOL bVerifyStrObj(STROBJ* pstro)
  199. {
  200. BOOL bMoreGlyphs;
  201. LONG cGlyph;
  202. GLYPHPOS * pgp;
  203. LONG iGlyph = 0;
  204. RECTL * prclDraw;
  205. GLYPHPOS * pgpTmp;
  206. POINTL ptlPlace;
  207. do
  208. {
  209. // Get the next batch of glyphs:
  210. if (pstro->pgp != NULL)
  211. {
  212. // There's only the one batch of glyphs, so save ourselves
  213. // a call:
  214. pgp = pstro->pgp;
  215. cGlyph = pstro->cGlyphs;
  216. bMoreGlyphs = FALSE;
  217. }
  218. else
  219. {
  220. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyph, &pgp);
  221. }
  222. prclDraw = &pstro->rclBkGround;
  223. pgpTmp = pgp;
  224. ptlPlace = pgpTmp->ptl;
  225. while (cGlyph)
  226. {
  227. if (((ptlPlace.x + pgpTmp->pgdf->pgb->ptlOrigin.x + pgpTmp->pgdf->pgb->sizlBitmap.cx) > (prclDraw->right)) ||
  228. ((ptlPlace.x + pgpTmp->pgdf->pgb->ptlOrigin.x) < (prclDraw->left)) ||
  229. ((ptlPlace.y + pgpTmp->pgdf->pgb->ptlOrigin.y + pgpTmp->pgdf->pgb->sizlBitmap.cy) > (prclDraw->bottom)) ||
  230. ((ptlPlace.y + pgpTmp->pgdf->pgb->ptlOrigin.y) < (prclDraw->top))
  231. )
  232. {
  233. DISPDBG((0,"------------------------------------------------------------"));
  234. DISPDBG((0,"Glyph %d extends beyond pstro->rclBkGround", iGlyph));
  235. DISPDBG((0,"\tpstro->rclBkGround (%d,%d,%d,%d)",
  236. pstro->rclBkGround.left,
  237. pstro->rclBkGround.top,
  238. pstro->rclBkGround.right,
  239. pstro->rclBkGround.bottom));
  240. DISPDBG((0,"\teffective glyph rect (%d,%d,%d,%d)",
  241. (ptlPlace.x + pgpTmp->pgdf->pgb->ptlOrigin.x),
  242. (ptlPlace.y + pgpTmp->pgdf->pgb->ptlOrigin.y),
  243. (ptlPlace.x + pgpTmp->pgdf->pgb->ptlOrigin.x + pgpTmp->pgdf->pgb->sizlBitmap.cx),
  244. (ptlPlace.y + pgpTmp->pgdf->pgb->ptlOrigin.y + pgpTmp->pgdf->pgb->sizlBitmap.cy)));
  245. DISPDBG((0,"\tglyph pos (%d,%d)",ptlPlace.x,ptlPlace.y));
  246. DISPDBG((0,"\tglyph origin (%d,%d)",
  247. pgpTmp->pgdf->pgb->ptlOrigin.x,
  248. pgpTmp->pgdf->pgb->ptlOrigin.y));
  249. DISPDBG((0,"\tglyph sizl (%d,%d)",
  250. pgpTmp->pgdf->pgb->sizlBitmap.cx,
  251. pgpTmp->pgdf->pgb->sizlBitmap.cy));
  252. DISPDBG((0,"------------------------------------------------------------"));
  253. RIP("time to call the font guys...");
  254. return(FALSE);
  255. }
  256. cGlyph--;
  257. iGlyph++;
  258. pgpTmp++;
  259. if (pstro->ulCharInc == 0)
  260. {
  261. ptlPlace = pgpTmp->ptl;
  262. }
  263. else
  264. {
  265. ptlPlace.x += pstro->ulCharInc;
  266. }
  267. }
  268. } while (bMoreGlyphs);
  269. return(TRUE);
  270. }
  271. VOID vIoTextOutUnclipped(
  272. PPDEV ppdev,
  273. STROBJ* pstro,
  274. FONTOBJ* pfo,
  275. CLIPOBJ* pco,
  276. RECTL* prclOpaque,
  277. BRUSHOBJ* pboFore,
  278. BRUSHOBJ* pboOpaque)
  279. {
  280. BYTE* pjPorts = ppdev->pjPorts;
  281. LONG lDelta = ppdev->lDelta;
  282. LONG cBpp = ppdev->cBpp;
  283. ULONG *pulXfer;
  284. ULONG ulDstAddr;
  285. ULONG ulFgColor;
  286. ULONG ulBgColor;
  287. ULONG ulSolidColor;
  288. BYTE jMode = 0;
  289. BYTE jModeColor = 0;
  290. BOOL bTextPerfectFit;
  291. ULONG cGlyph;
  292. BOOL bMoreGlyphs;
  293. GLYPHPOS* pgp;
  294. GLYPHBITS* pgb;
  295. LONG cxGlyph;
  296. LONG cyGlyph;
  297. ULONG* pdSrc;
  298. ULONG* pdDst;
  299. LONG cj;
  300. LONG cd;
  301. POINTL ptlOrigin;
  302. LONG ulCharInc;
  303. ulFgColor = pboFore->iSolidColor;
  304. if (pboOpaque)
  305. {
  306. ulBgColor = pboOpaque->iSolidColor;
  307. }
  308. if (cBpp == 1)
  309. {
  310. ulFgColor |= ulFgColor << 8;
  311. ulFgColor |= ulFgColor << 16;
  312. ulBgColor |= ulBgColor << 8;
  313. ulBgColor |= ulBgColor << 16;
  314. }
  315. else if (cBpp == 2)
  316. {
  317. ulFgColor |= ulFgColor << 16;
  318. ulBgColor |= ulBgColor << 16;
  319. }
  320. pulXfer = ppdev->pulXfer;
  321. ppdev->pfnBankMap(ppdev, ppdev->lXferBank);
  322. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  323. CP_IO_DST_Y_OFFSET(ppdev, pjPorts, lDelta);
  324. if (prclOpaque != NULL)
  325. {
  326. ////////////////////////////////////////////////////////////
  327. // Opaque Initialization
  328. ////////////////////////////////////////////////////////////
  329. // If we paint the glyphs in 'opaque' mode, we may not actually
  330. // have to draw the opaquing rectangle up-front -- the process
  331. // of laying down all the glyphs will automatically cover all
  332. // of the pixels in the opaquing rectangle.
  333. //
  334. // The condition that must be satisfied is that the text must
  335. // fit 'perfectly' such that the entire background rectangle is
  336. // covered, and none of the glyphs overlap (if the glyphs
  337. // overlap, such as for italics, they have to be drawn in
  338. // transparent mode after the opaquing rectangle is cleared).
  339. bTextPerfectFit = (pstro->flAccel & (SO_ZERO_BEARINGS |
  340. SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE |
  341. SO_CHAR_INC_EQUAL_BM_BASE)) ==
  342. (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT |
  343. SO_MAXEXT_EQUAL_BM_SIDE | SO_CHAR_INC_EQUAL_BM_BASE);
  344. if (!(bTextPerfectFit) ||
  345. (pstro->rclBkGround.top > prclOpaque->top) ||
  346. (pstro->rclBkGround.left > prclOpaque->left) ||
  347. (pstro->rclBkGround.right < prclOpaque->right) ||
  348. (pstro->rclBkGround.bottom < prclOpaque->bottom))
  349. {
  350. vClipSolid(ppdev, 1, prclOpaque, pboOpaque->iSolidColor, pco);
  351. }
  352. if (bTextPerfectFit)
  353. {
  354. // If we have already drawn the opaquing rectangle (because
  355. // is was larger than the text rectangle), we could lay down
  356. // the glyphs in 'transparent' mode. But I've found the QVision
  357. // to be a bit faster drawing in opaque mode, so we'll stick
  358. // with that:
  359. jMode = jModeColor |
  360. ENABLE_COLOR_EXPAND |
  361. SRC_CPU_DATA;
  362. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  363. CP_IO_FG_COLOR(ppdev, pjPorts, ulFgColor);
  364. CP_IO_BG_COLOR(ppdev, pjPorts, ulBgColor);
  365. CP_IO_ROP(ppdev, pjPorts, CL_SRC_COPY);
  366. CP_IO_BLT_MODE(ppdev, pjPorts, jMode);
  367. goto SkipTransparentInitialization;
  368. }
  369. }
  370. ////////////////////////////////////////////////////////////
  371. // Transparent Initialization
  372. ////////////////////////////////////////////////////////////
  373. // Initialize the hardware for transparent text:
  374. jMode = jModeColor |
  375. ENABLE_COLOR_EXPAND |
  376. ENABLE_TRANSPARENCY_COMPARE |
  377. SRC_CPU_DATA;
  378. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  379. CP_IO_FG_COLOR(ppdev, pjPorts, ulFgColor);
  380. CP_IO_BG_COLOR(ppdev, pjPorts, ~ulFgColor);
  381. CP_IO_XPAR_COLOR(ppdev, pjPorts, ~ulFgColor);
  382. CP_IO_ROP(ppdev, pjPorts, CL_SRC_COPY);
  383. CP_IO_BLT_MODE(ppdev, pjPorts, jMode);
  384. CP_IO_BLT_EXT_MODE(ppdev, pjPorts, 0); // jl01
  385. SkipTransparentInitialization:
  386. do {
  387. if (pstro->pgp != NULL)
  388. {
  389. // There's only the one batch of glyphs, so save ourselves
  390. // a call:
  391. pgp = pstro->pgp;
  392. cGlyph = pstro->cGlyphs;
  393. bMoreGlyphs = FALSE;
  394. }
  395. else
  396. {
  397. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyph, &pgp);
  398. }
  399. if (cGlyph > 0)
  400. {
  401. if (pstro->ulCharInc == 0)
  402. {
  403. ////////////////////////////////////////////////////////////
  404. // Proportional Spacing
  405. pdDst = pulXfer;
  406. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  407. do {
  408. pgb = pgp->pgdf->pgb;
  409. ulDstAddr = ((pgp->ptl.y + pgb->ptlOrigin.y) * lDelta) +
  410. PELS_TO_BYTES(pgp->ptl.x + pgb->ptlOrigin.x);
  411. cxGlyph = pgb->sizlBitmap.cx;
  412. cyGlyph = pgb->sizlBitmap.cy;
  413. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  414. CP_IO_XCNT(ppdev, pjPorts, (PELS_TO_BYTES(cxGlyph) - 1));
  415. CP_IO_YCNT(ppdev, pjPorts, cyGlyph - 1);
  416. //
  417. // The 542x chips require a write to the Src Address Register when
  418. // doing a host transfer with color expansion. The value is
  419. // irrelevant, but the write is crucial. This is documented in
  420. // the manual, not the errata. Go figure.
  421. //
  422. CP_IO_SRC_ADDR(ppdev, pjPorts, 0);
  423. CP_IO_DST_ADDR(ppdev, pjPorts, ulDstAddr);
  424. CP_IO_START_BLT(ppdev, pjPorts);
  425. pdSrc = (ULONG*) pgb->aj;
  426. cj = cyGlyph * ((cxGlyph + 7) >> 3);
  427. cd = (cj + 3) >> 2;
  428. {
  429. do {
  430. WRITE_REGISTER_ULONG(pdDst, *pdSrc);
  431. // *pdDst = *pdSrc;
  432. CP_MEMORY_BARRIER();
  433. pdSrc++;
  434. } while (--cd != 0);
  435. }
  436. } while (pgp++, --cGlyph != 0);
  437. }
  438. else
  439. {
  440. ////////////////////////////////////////////////////////////
  441. // Mono Spacing
  442. ulCharInc = pstro->ulCharInc;
  443. pgb = pgp->pgdf->pgb;
  444. ptlOrigin.x = pgb->ptlOrigin.x + pgp->ptl.x;
  445. ptlOrigin.y = pgb->ptlOrigin.y + pgp->ptl.y;
  446. pdDst = pulXfer;
  447. do {
  448. pgb = pgp->pgdf->pgb;
  449. ulDstAddr = (ptlOrigin.y * lDelta) +
  450. PELS_TO_BYTES(ptlOrigin.x);
  451. cxGlyph = pgb->sizlBitmap.cx;
  452. cyGlyph = pgb->sizlBitmap.cy;
  453. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  454. CP_IO_XCNT(ppdev, pjPorts, (PELS_TO_BYTES(cxGlyph) - 1));
  455. CP_IO_YCNT(ppdev, pjPorts, cyGlyph - 1);
  456. //
  457. // The 542x chips require a write to the Src Address Register when
  458. // doing a host transfer with color expansion. The value is
  459. // irrelevant, but the write is crucial. This is documented in
  460. // the manual, not the errata. Go figure.
  461. //
  462. CP_IO_SRC_ADDR(ppdev, pjPorts, 0);
  463. CP_IO_DST_ADDR(ppdev, pjPorts, ulDstAddr);
  464. ptlOrigin.x += ulCharInc;
  465. CP_IO_START_BLT(ppdev, pjPorts);
  466. pdSrc = (ULONG*) pgb->aj;
  467. cj = cyGlyph * ((cxGlyph + 7) >> 3);
  468. cd = (cj + 3) >> 2;
  469. {
  470. do {
  471. WRITE_REGISTER_ULONG(pdDst, *pdSrc);
  472. // *pdDst = *pdSrc;
  473. MEMORY_BARRIER();
  474. pdSrc++;
  475. } while (--cd != 0);
  476. }
  477. } while (pgp++, --cGlyph != 0);
  478. }
  479. }
  480. } while (bMoreGlyphs);
  481. }
  482. #endif
  483. /******************************Public*Routine******************************\
  484. * BOOL DrvTextOut
  485. *
  486. * If it's the fastest method, outputs text using the 'glyph expansion'
  487. * method. Each individual glyph is color-expanded directly to the
  488. * screen from the monochrome glyph bitmap supplied by GDI.
  489. *
  490. * If it's not the fastest method, calls the routine that implements the
  491. * 'buffer expansion' method.
  492. *
  493. \**************************************************************************/
  494. BOOL DrvTextOut(
  495. SURFOBJ* pso,
  496. STROBJ* pstro,
  497. FONTOBJ* pfo,
  498. CLIPOBJ* pco,
  499. RECTL* prclExtra, // If we had set GCAPS_HORIZSTRIKE, we would have
  500. // to fill these extra rectangles (it is used
  501. // largely for underlines). It's not a big
  502. // performance win (GDI will call our DrvBitBlt
  503. // to draw the extra rectangles).
  504. RECTL* prclOpaque,
  505. BRUSHOBJ* pboFore,
  506. BRUSHOBJ* pboOpaque,
  507. POINTL* pptlBrush,
  508. MIX mix)
  509. {
  510. PDEV* ppdev;
  511. DSURF* pdsurf;
  512. OH* poh;
  513. BOOL bTextPerfectFit;
  514. LONG lDelta;
  515. BOOL bTmpAlloc;
  516. VOID* pvTmp;
  517. SURFOBJ* psoTmpMono;
  518. BOOL bOpaque;
  519. BRUSHOBJ boFore;
  520. BRUSHOBJ boOpaque;
  521. BOOL bRet;
  522. XLATECOLORS xlc; // Temporary for keeping colours
  523. XLATEOBJ xlo; // Temporary for passing colours
  524. ULONG ulBufferBytes;
  525. ULONG ulBufferHeight;
  526. // The DDI spec says we'll only ever get foreground and background
  527. // mixes of R2_COPYPEN:
  528. ASSERTDD(mix == 0x0d0d, "GDI should only give us a copy mix");
  529. // Pass the surface off to GDI if it's a device bitmap that we've
  530. // converted to a DIB:
  531. pdsurf = (DSURF*) pso->dhsurf;
  532. if (pdsurf->dt != DT_DIB)
  533. {
  534. // We'll be drawing to the screen or an off-screen DFB; copy the
  535. // surface's offset now so that we won't need to refer to the DSURF
  536. // again:
  537. poh = pdsurf->poh;
  538. ppdev = (PDEV*) pso->dhpdev;
  539. ppdev->xOffset = poh->x;
  540. ppdev->yOffset = poh->y;
  541. ppdev->xyOffset = poh->xy;
  542. if (HOST_XFERS_DISABLED(ppdev) && DIRECT_ACCESS(ppdev))
  543. {
  544. //
  545. // if HOST_XFERS_DISABLED(ppdev) is TRUE then the BitBlt used by
  546. // our text code will be VERY slow. We should just let the engine
  547. // draw the text if it can.
  548. //
  549. if (ppdev->bLinearMode)
  550. {
  551. SURFOBJ *psoPunt = ppdev->psoPunt;
  552. psoPunt->pvScan0 = poh->pvScan0;
  553. ppdev->pfnBankSelectMode(ppdev, BANK_ON);
  554. return(EngTextOut(psoPunt, pstro, pfo, pco, prclExtra,
  555. prclOpaque, pboFore, pboOpaque,
  556. pptlBrush, mix));
  557. }
  558. else
  559. {
  560. BANK bnk;
  561. BOOL b;
  562. RECTL rclDraw;
  563. RECTL *prclDst = &pco->rclBounds;
  564. // The bank manager requires that the 'draw' rectangle be
  565. // well-ordered:
  566. rclDraw = *prclDst;
  567. if (rclDraw.left > rclDraw.right)
  568. {
  569. rclDraw.left = prclDst->right;
  570. rclDraw.right = prclDst->left;
  571. }
  572. if (rclDraw.top > rclDraw.bottom)
  573. {
  574. rclDraw.top = prclDst->bottom;
  575. rclDraw.bottom = prclDst->top;
  576. }
  577. vBankStart(ppdev, &rclDraw, pco, &bnk);
  578. b = TRUE;
  579. do {
  580. b &= EngTextOut(bnk.pso,
  581. pstro,
  582. pfo,
  583. bnk.pco,
  584. prclExtra,
  585. prclOpaque,
  586. pboFore,
  587. pboOpaque,
  588. pptlBrush,
  589. mix);
  590. } while (bBankEnum(&bnk));
  591. return(b);
  592. }
  593. }
  594. if ((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL))
  595. {
  596. // I'm not entirely sure why, but GDI will occasionally send
  597. // us TextOut's where the opaquing rectangle does not intersect
  598. // with the clip object bounds -- meaning that the text out
  599. // should have already been trivially rejected. We will do so
  600. // here because the blt code usually assumes that all trivial
  601. // rejections will have already been performed, and we will be
  602. // passing this call on to the blt code:
  603. if ((pco->rclBounds.top >= pstro->rclBkGround.bottom) ||
  604. (pco->rclBounds.left >= pstro->rclBkGround.right) ||
  605. (pco->rclBounds.right <= pstro->rclBkGround.left) ||
  606. (pco->rclBounds.bottom <= pstro->rclBkGround.top))
  607. {
  608. // The entire operation was trivially rejected:
  609. if (prclOpaque)
  610. {
  611. vClipSolid(ppdev, 1, prclOpaque, pboOpaque->iSolidColor, pco);
  612. }
  613. return(TRUE);
  614. }
  615. }
  616. // Font cache.
  617. if ((ppdev->flStatus & STAT_FONT_CACHE) &&
  618. bFontCache(ppdev, pstro, pfo, pco, prclOpaque, pboFore, pboOpaque))
  619. {
  620. return(TRUE);
  621. }
  622. // See if the temporary buffer is big enough for the text; if
  623. // not, try to allocate enough memory. We round up to the
  624. // nearest dword multiple:
  625. lDelta = ((((pstro->rclBkGround.right + 31) & ~31) -
  626. (pstro->rclBkGround.left & ~31)) >> 3);
  627. ulBufferHeight = pstro->rclBkGround.bottom - pstro->rclBkGround.top;
  628. ulBufferBytes = lDelta * ulBufferHeight;
  629. if (((ULONG) lDelta > FIFTEEN_BITS) ||
  630. (ulBufferHeight > FIFTEEN_BITS))
  631. {
  632. // Fail if the math will have overflowed:
  633. return(FALSE);
  634. }
  635. // Use our temporary buffer if it's big enough, otherwise
  636. // allocate a buffer on the fly:
  637. if (ulBufferBytes >= TMP_BUFFER_SIZE)
  638. {
  639. // The textout is so big that I doubt this allocation will
  640. // cost a significant amount in performance:
  641. bTmpAlloc = TRUE;
  642. pvTmp = ALLOC(ulBufferBytes);
  643. if (pvTmp == NULL)
  644. return(FALSE);
  645. }
  646. else
  647. {
  648. bTmpAlloc = FALSE;
  649. pvTmp = ppdev->pvTmpBuffer;
  650. }
  651. psoTmpMono = ppdev->psoTmpMono;
  652. // Adjust 'lDelta' and 'pvScan0' of our temporary 1bpp surface object
  653. // so that when GDI starts drawing the text, it will begin in the
  654. // first dword
  655. psoTmpMono->pvScan0 = (BYTE*) pvTmp - (pstro->rclBkGround.top * lDelta)
  656. - ((pstro->rclBkGround.left & ~31) >> 3);
  657. psoTmpMono->lDelta = lDelta;
  658. ASSERTDD(((ULONG_PTR) psoTmpMono->pvScan0 & 3) == 0,
  659. "pvScan0 must be dword aligned");
  660. ASSERTDD((lDelta & 3) == 0, "lDelta must be dword aligned");
  661. // We always want GDI to draw in opaque mode to temporary 1bpp
  662. // buffer:
  663. // We only want GDI to opaque within the rclBkGround.
  664. // We'll handle the rest ourselves.
  665. bOpaque = (prclOpaque != NULL);
  666. // Get GDI to draw the text for us:
  667. boFore.iSolidColor = 1;
  668. boOpaque.iSolidColor = 0;
  669. bRet = EngTextOut(psoTmpMono,
  670. pstro,
  671. pfo,
  672. pco,
  673. prclExtra,
  674. &pstro->rclBkGround, //prclOpaque,
  675. &boFore,
  676. &boOpaque,
  677. pptlBrush,
  678. mix);
  679. if (bRet)
  680. {
  681. if (bOpaque)
  682. {
  683. bTextPerfectFit = (pstro->flAccel & (SO_ZERO_BEARINGS |
  684. SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE |
  685. SO_CHAR_INC_EQUAL_BM_BASE)) ==
  686. (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT |
  687. SO_MAXEXT_EQUAL_BM_SIDE | SO_CHAR_INC_EQUAL_BM_BASE);
  688. if (!(bTextPerfectFit) ||
  689. (pstro->rclBkGround.top > prclOpaque->top) ||
  690. (pstro->rclBkGround.left > prclOpaque->left) ||
  691. (pstro->rclBkGround.right < prclOpaque->right) ||
  692. (pstro->rclBkGround.bottom < prclOpaque->bottom))
  693. {
  694. //
  695. // Drawing the Opaque test will not completely cover the
  696. // opaque rectangle, so we must do it. Go to transparent
  697. // blt so we don't do the work twice (since opaque text is
  698. // done in two passes).
  699. //
  700. vClipSolid(ppdev, 1, prclOpaque, pboOpaque->iSolidColor, pco);
  701. goto Transparent_Text;
  702. }
  703. xlc.iForeColor = pboFore->iSolidColor;
  704. xlc.iBackColor = pboOpaque->iSolidColor;
  705. xlo.pulXlate = (ULONG*) &xlc;
  706. bRet = DrvBitBlt(pso,
  707. psoTmpMono,
  708. NULL,
  709. pco,
  710. &xlo,
  711. &pstro->rclBkGround,
  712. (POINTL*)&pstro->rclBkGround,
  713. NULL,
  714. NULL, //&boFore
  715. NULL,
  716. R4_SRCCOPY);
  717. }
  718. else
  719. {
  720. Transparent_Text:
  721. // Foreground colour must be 0xff for 8bpp and 0xffff for 16bpp:
  722. xlc.iForeColor = (ULONG)((1<<PELS_TO_BYTES(8)) - 1);
  723. xlc.iBackColor = 0;
  724. xlo.pulXlate = (ULONG*) &xlc;
  725. boFore.iSolidColor = pboFore->iSolidColor;
  726. //
  727. // Transparently blt the text bitmap
  728. //
  729. bRet = DrvBitBlt(pso,
  730. psoTmpMono,
  731. NULL,
  732. pco,
  733. &xlo,
  734. &pstro->rclBkGround,
  735. (POINTL*)&pstro->rclBkGround,
  736. NULL,
  737. &boFore,
  738. NULL,
  739. 0xe2e2);
  740. }
  741. }
  742. // Free up any memory we allocated for the temp buffer:
  743. if (bTmpAlloc)
  744. {
  745. FREE(pvTmp);
  746. }
  747. return(bRet);
  748. }
  749. else
  750. {
  751. // We're drawing to a DFB we've converted to a DIB, so just call GDI
  752. // to handle it:
  753. return(EngTextOut(pdsurf->pso, pstro, pfo, pco, prclExtra, prclOpaque,
  754. pboFore, pboOpaque, pptlBrush, mix));
  755. }
  756. return(TRUE);
  757. }
  758. /******************************Public*Routine******************************\
  759. * VOID vDisableText
  760. *
  761. * Performs the necessary clean-up for the text drawing subcomponent.
  762. *
  763. \**************************************************************************/
  764. VOID vDisableText(PDEV* ppdev)
  765. {
  766. // Here we free any stuff allocated in 'bEnableText'.
  767. }
  768. ////////////////////////////////////////////////////////////////////////////////
  769. // //
  770. // F O N T C A C H E S T U F F //
  771. // //
  772. ////////////////////////////////////////////////////////////////////////////////
  773. /*
  774. The font cache has quite an impact on the speed. First a little note on the
  775. necessaty of an off-screen font cache (it is an off-screen font cache). The
  776. original code calls the GDI to perform the character drawing on a temporary
  777. monochrome surface and then blits that surface to the screen. The problem
  778. is that GDI is realy too slow. So we need some sort of acceleration here.
  779. The best acceleration possible is to cache all glyphs off-screen so we can
  780. let the bitblt engine do its work while we calculate the stuff required for
  781. the next glyph to draw. Call it co-operate cacheing if you like.
  782. Okay, so now we know why we need a font cache, how do we do it? Calling
  783. the heap manager for every glyph we are going to cache is quite disasterous
  784. since the off-screen heap gets fragmented with a lot (and I mean a lot) of
  785. small chunks of data. We can do it better. We will implement our own very
  786. sneaky (simple and fast) memory manager. We just call the off-screen heap
  787. manager to allocate a big chunk (4Kb or so) rectengular memory and perform
  788. our own allocation in that chunk.
  789. We will use a simple linear allocation technique. Whenever we are required
  790. to allocate a number of bytes we will test if we have enough room in the
  791. last line accessed in the chunk. If we have, we decrease the size left on
  792. that line and return a pointer to it. If we don't have enough memory in the
  793. last line we simply move to the next line which will be free. If there is
  794. not enough memory there either, the requested glyph is too big and so we
  795. return NULL. The only problem here is when we run out of lines in the
  796. chunk. In this case we link in another chunk we allocate in off-screen
  797. memory and mark the current chunk 'full'. Okay, this may not be the best
  798. memory manager since it might leave lines in the chunk very empty if a
  799. large glyph needs to be allocated. But it is small and fast. And that's our
  800. main goal.
  801. We could copy the entire glyph into off-screen memory, but this would use
  802. up valueable memory since most glyphs will have a lot of white space in
  803. them. So we calculate the actual visible part of the glyph and only copy
  804. that data to the off-screen memory. This requires some extra overhead when
  805. a glyph is being cached, but that will happen only once. And we can detect
  806. empty glyphs (like the space) to speed up drawing in the process. This does
  807. however add the necessaty of first drawing an opaque rectangle if required.
  808. This does not matter that much, since the bitblt engine will draw it while
  809. we setup some loop variables.
  810. Okay, now we know about the memory manager. But how do we attach this glyph
  811. cache to a font? And how do we free its recourses? Windows NT has this nice
  812. feature called OEM extension. In the FONT object there is a field
  813. (vConsumer) which is for the display driver only. We can use this field to
  814. hook up a pointer to our FONTCACHE structure. And when the font is no
  815. longer required, Windows NT calls DrvDestroyFont so we can remove any
  816. resources attached to the font. There is only one glitch to this scheme.
  817. Windows NT does not free up the fonts when the screen goes to full-screen
  818. DOS mode. This does not matter but when the screen is reset to graphics
  819. mode all off-screen fonts are smashed and invalid. So I have added a
  820. counter that gets incremented when the screen is reset to graphics mode.
  821. When this counter does not match the copy in the FONTCACHE structure we
  822. must destroy the font first before caching it again.
  823. There might be some TrueType fonts out there that have many glyphs in them
  824. (the Unicode fonts for example). This would cause an extremely large font
  825. cache indeed. So we set a maximum (defaults to 256) of glyphs to cache.
  826. Whenever we are asked to draw a glyph outside the range we do it by
  827. bypassing the font cache for that particular glyph.
  828. Some glyphs might be too large to cache even though the font is small
  829. enough to be validated for cacheing. In this case we mark the specific
  830. glyph as uncacheable and draw it directly to screen, bypassing the font
  831. cache. Other glyphs might have no visble pixels at all (spaces) and we mark
  832. them as empty so they never get drawn.
  833. This covers most of the basics for the font cache. See the comments in the
  834. source for more details.
  835. EXTRA: Today (24-Jul-96) I have added a chain of FONTCACHE structures that
  836. keeps track of which FONTOBJs are loaded and cached. This chain will we
  837. walked to throw all cached fonts out of memory when a mode change to full-
  838. screen occurs or when DirectDraw is being initialized to give more memory
  839. to DirectDraw.
  840. */
  841. /******************************************************************************\
  842. *
  843. * Function: bEnableText
  844. *
  845. * This routine is called from DrvEnableSurface and should perform any actions
  846. * required to set up the font cache.
  847. *
  848. * Parameters: ppdev Pointer to physical device.
  849. *
  850. * Returns: TRUE.
  851. *
  852. \******************************************************************************/
  853. BOOL bEnableText(
  854. PDEV* ppdev)
  855. {
  856. // The font cache is only available on the CL-GD5436 like chips, direct
  857. // access to the frame buffer is enabled and we can do host transfers.
  858. if ((ppdev->flCaps & CAPS_AUTOSTART) &&
  859. DIRECT_ACCESS(ppdev) &&
  860. !(ppdev->flCaps & CAPS_NO_HOST_XFER))
  861. {
  862. // Don't enable the font cache in low memory situations.
  863. LONG cWidth = BYTES_TO_PELS(FONT_ALLOC_X);
  864. if ((cWidth <= ppdev->heap.cxMax) &&
  865. (FONT_ALLOC_Y <= ppdev->heap.cyMax) && FALSE)
  866. {
  867. // The font cache will be used.
  868. ppdev->flStatus |= STAT_FONT_CACHE;
  869. ppdev->pfcChain = NULL;
  870. }
  871. }
  872. return(TRUE);
  873. }
  874. /******************************************************************************\
  875. *
  876. * Function: vAssertModeText
  877. *
  878. * This routine is called from DrvAssertMode. When we switch to full screen we
  879. * destroy all cached fonts.
  880. *
  881. * Parameters: ppdev Pointer to physical device.
  882. * bEnable TRUE if switching to graphics mode, FALSE if
  883. * switching to full-screen MS-DOS mode.
  884. *
  885. * Returns: Nothing.
  886. *
  887. \******************************************************************************/
  888. VOID vAssertModeText(
  889. PDEV* ppdev,
  890. BOOL bEnable)
  891. {
  892. if (bEnable)
  893. {
  894. ppdev->ulFontCacheID++;
  895. }
  896. else
  897. {
  898. // Destroy all fonts in the chain.
  899. while (ppdev->pfcChain != NULL)
  900. {
  901. DrvDestroyFont(ppdev->pfcChain->pfo);
  902. }
  903. }
  904. }
  905. /******************************************************************************\
  906. *
  907. * Function: DrvDestroyFont
  908. *
  909. * This functin is called by NT when a font is being removed from memory. We
  910. * must free any resources we have attached to this font.
  911. *
  912. * Parameters: pfo Pointer to the font object being destroyed.
  913. *
  914. * Returns: Nothing.
  915. *
  916. \******************************************************************************/
  917. VOID DrvDestroyFont(
  918. FONTOBJ *pfo)
  919. {
  920. // Do we have any recourses allocated?
  921. if ((pfo->pvConsumer != NULL) && (pfo->pvConsumer != (VOID*) -1))
  922. {
  923. FONTCACHE* pfc = pfo->pvConsumer;
  924. FONTMEMORY* pfm;
  925. PDEV* ppdev;
  926. ppdev = pfc->ppdev;
  927. // Free all allocated memory blocks.
  928. pfm = pfc->pfm;
  929. while (pfm != NULL)
  930. {
  931. FONTMEMORY* pfmNext = pfm->pfmNext;
  932. if (pfm->poh != NULL)
  933. {
  934. pohFree(ppdev, pfm->poh);
  935. }
  936. FREE(pfm);
  937. pfm = pfmNext;
  938. }
  939. // Unhook the font cache from the chain.
  940. if (pfc->pfcPrev != NULL)
  941. {
  942. pfc->pfcPrev->pfcNext = pfc->pfcNext;
  943. }
  944. else
  945. {
  946. ppdev->pfcChain = pfc->pfcNext;
  947. }
  948. if (pfc->pfcNext != NULL)
  949. {
  950. pfc->pfcNext->pfcPrev = pfc->pfcPrev;
  951. }
  952. // Free the font cache.
  953. FREE(pfc);
  954. }
  955. // We don't have anything allocated anymore!
  956. pfo->pvConsumer = NULL;
  957. }
  958. /******************************************************************************\
  959. *
  960. * Function: cGetGlyphSize
  961. *
  962. * Get the width and height of a glyph. The height is its visble height, without
  963. * leading and trailing blank lines.
  964. *
  965. * Parameters: pgb Pointer to the glyph.
  966. * pptlOrigin Pointer to a POINTL which receives the origin of
  967. * the glyph.
  968. * psizlPixels Pointer to a SIZEL which receives the size of the
  969. * glyph in pixels.
  970. *
  971. * Returns: The width of the glyph in bytes or 0 if the glyph is empty.
  972. *
  973. \******************************************************************************/
  974. LONG cGetGlyphSize(
  975. GLYPHBITS* pgb,
  976. POINTL* pptlOrigin,
  977. SIZEL* psizlPixels)
  978. {
  979. LONG x, y;
  980. BYTE* pByte = pgb->aj;
  981. INT i;
  982. // Get width in bytes.
  983. x = (pgb->sizlBitmap.cx + 7) >> 3;
  984. if (x > 0)
  985. {
  986. // Find the first line in glyph that conatins data.
  987. for (y = 0; y < pgb->sizlBitmap.cy; y++, pByte += x)
  988. {
  989. // Walk through every byte on a line.
  990. for (i = 0; i < x; i++)
  991. {
  992. // If we have data here, we have found the first line.
  993. if (pByte[i])
  994. {
  995. // Find the last line in the glyph that contains data.
  996. LONG lHeight = pgb->sizlBitmap.cy - y;
  997. for (pByte += (lHeight - 1) * x; lHeight > 0; lHeight--)
  998. {
  999. // Walk through every byte on a line.
  1000. for (i = 0; i < x; i++)
  1001. {
  1002. if (pByte[i])
  1003. {
  1004. // Fill return parameters.
  1005. pptlOrigin->y = y;
  1006. psizlPixels->cx = pgb->sizlBitmap.cx;
  1007. psizlPixels->cy = lHeight;
  1008. return(x);
  1009. }
  1010. }
  1011. pByte -= x;
  1012. }
  1013. // Glyph is empty.
  1014. return(0);
  1015. }
  1016. }
  1017. }
  1018. }
  1019. // Glyph is empty.
  1020. return(0);
  1021. }
  1022. /******************************************************************************\
  1023. *
  1024. * Function: pjAllocateFontCache
  1025. *
  1026. * Allocate a number of bytes in the off-screen font cache.
  1027. *
  1028. * Parameters: pfc Pointer to the font cache.
  1029. * cBytes Number of bytes to allocate.
  1030. *
  1031. * Returns: Linear address of allocation or NULL if there was an error
  1032. * allocating memory.
  1033. *
  1034. \******************************************************************************/
  1035. BYTE* pjAllocateFontCache(
  1036. FONTCACHE* pfc,
  1037. LONG cBytes)
  1038. {
  1039. FONTMEMORY* pfm;
  1040. BYTE* pjLinear;
  1041. PDEV* ppdev = pfc->ppdev;
  1042. // Allocate first FONTMEMORY structure if not yet done.
  1043. if (pfc->pfm == NULL)
  1044. {
  1045. pfc->pfm = ALLOC(sizeof(FONTMEMORY));
  1046. if (pfc->pfm == NULL)
  1047. {
  1048. return(NULL);
  1049. }
  1050. }
  1051. // Walk through all FONTMEMORY structures to find enough space.
  1052. for (pfm = pfc->pfm; pfm != NULL; pfm = pfm->pfmNext)
  1053. {
  1054. // Allocate the off-screen node if not yet done so.
  1055. if (pfm->poh == NULL)
  1056. {
  1057. OH* poh = pohAllocate(ppdev, pfc->cWidth, pfc->cHeight,
  1058. FLOH_ONLY_IF_ROOM);
  1059. if (poh == NULL)
  1060. {
  1061. DISPDBG((4, "Not enough room for font cache"));
  1062. return(NULL);
  1063. }
  1064. // Make off-screen node PERMANENT.
  1065. poh->ofl = OFL_PERMANENT;
  1066. vCalculateMaximum(ppdev);
  1067. // Initialize memory manager.
  1068. pfm->poh = poh;
  1069. pfm->cx = PELS_TO_BYTES(poh->cx);
  1070. pfm->cy = poh->cy;
  1071. pfm->xy = poh->xy;
  1072. }
  1073. // Test if the font is too big to fit in any memory block.
  1074. if (cBytes > pfm->cx)
  1075. {
  1076. return(NULL);
  1077. }
  1078. // If the block is not yet full...
  1079. if (pfm->cy > 0)
  1080. {
  1081. // If the glyph fots on the current line...
  1082. if ((pfm->x + cBytes) <= pfm->cx)
  1083. {
  1084. pjLinear = (BYTE*)(ULONG_PTR)(pfm->xy + pfm->x);
  1085. pfm->x += cBytes;
  1086. return(pjLinear);
  1087. }
  1088. // Next line.
  1089. pfm->cy--;
  1090. // If this memory block is not yet full...
  1091. if (pfm->cy > 0)
  1092. {
  1093. pfm->xy += ppdev->lDelta;
  1094. pfm->x = cBytes;
  1095. return((BYTE*)(ULONG_PTR)pfm->xy);
  1096. }
  1097. }
  1098. // Allocate the next FONTMEMORY structure if not yet done.
  1099. if (pfm->pfmNext == NULL)
  1100. {
  1101. pfm->pfmNext = ALLOC(sizeof(FONTMEMORY));
  1102. }
  1103. }
  1104. return(NULL);
  1105. }
  1106. /******************************************************************************\
  1107. *
  1108. * Function: vAllocateGlyph
  1109. *
  1110. * Cache a glyph to the off-screen font cache.
  1111. *
  1112. * Parameters: pfc Pointer to the font cache.
  1113. * pgb Pointer to the glyph structure.
  1114. * pgc Pointer to the glyph cache.
  1115. *
  1116. * Returns: pgc->sizlBytes.cy.
  1117. *
  1118. \******************************************************************************/
  1119. LONG lAllocateGlyph(
  1120. FONTCACHE* pfc,
  1121. GLYPHBITS* pgb,
  1122. GLYPHCACHE* pgc)
  1123. {
  1124. PDEV* ppdev = pfc->ppdev;
  1125. LONG lDelta;
  1126. BYTE* pjSrc;
  1127. BYTE* pjDst;
  1128. LONG c;
  1129. // Get the size of the glyph.
  1130. lDelta = cGetGlyphSize(pgb, &pgc->ptlOrigin, &pgc->sizlPixels);
  1131. if (lDelta == 0)
  1132. {
  1133. // Glyph is empty.
  1134. pgc->pjGlyph = (BYTE*) -1;
  1135. pgc->sizlBytes.cy = GLYPH_EMPTY;
  1136. return(GLYPH_EMPTY);
  1137. }
  1138. // Allocate the glyph in the off-screen font cache.
  1139. pgc->lDelta = lDelta;
  1140. c = lDelta * pgc->sizlPixels.cy;
  1141. pgc->pjGlyph = pjAllocateFontCache(pfc, c);
  1142. if (pgc->pjGlyph == NULL)
  1143. {
  1144. // Glyph is uncacheable.
  1145. pgc->pjGlyph = (BYTE*) -1;
  1146. pgc->sizlBytes.cy = GLYPH_UNCACHEABLE;
  1147. return(GLYPH_UNCACHEABLE);
  1148. }
  1149. // Calculate the glyph and off-screen pointers.
  1150. pjSrc = &pgb->aj[pgc->ptlOrigin.y * lDelta];
  1151. pjDst = ppdev->pjScreen + (ULONG_PTR) pgc->pjGlyph;
  1152. // First, align the source to a DWORD boundary.
  1153. while (((ULONG_PTR)pjSrc & 3) && (c > 0))
  1154. {
  1155. *pjDst++ = *pjSrc++;
  1156. c--;
  1157. }
  1158. // Copy the data in DWORDs.
  1159. while (c >= 4)
  1160. {
  1161. *((UNALIGNED DWORD*) pjDst)++ = *((DWORD*) pjSrc)++;
  1162. c -= 4;
  1163. }
  1164. // Copy the remaining data.
  1165. while (c >= 0)
  1166. {
  1167. *pjDst++ = *pjSrc++;
  1168. c--;
  1169. }
  1170. // Calculate the glyph origin and size.
  1171. pgc->ptlOrigin.x = pgb->ptlOrigin.x;
  1172. pgc->ptlOrigin.y += pgb->ptlOrigin.y;
  1173. pgc->sizlBytes.cx = PELS_TO_BYTES(pgc->sizlPixels.cx) - 1;
  1174. pgc->sizlBytes.cy = pgc->sizlPixels.cy - 1;
  1175. return(pgc->sizlBytes.cy);
  1176. }
  1177. /******************************************************************************\
  1178. *
  1179. * Function: bFontCache
  1180. *
  1181. * This is the font cache routine which is called from DrvTextOut if the font
  1182. * cache is turned on.
  1183. *
  1184. * Parameters: ppdev Pointer to physical device.
  1185. * pstro Pointer to array of glyphs to draw.
  1186. * pfo Pointer to the font.
  1187. * pco Pointer to a CLIPOBJ structure.
  1188. * prclOpaque Pointer to the opaque rectangle.
  1189. * pboFore Pointer to the foreground brush.
  1190. * pboOpaque Pointer to the opaque brush.
  1191. *
  1192. * Returns: TRUE if the font has been drawn, FALSE if DrvTextOut should
  1193. * handle it.
  1194. *
  1195. \******************************************************************************/
  1196. BOOL bFontCache(
  1197. PDEV* ppdev,
  1198. STROBJ* pstro,
  1199. FONTOBJ* pfo,
  1200. CLIPOBJ* pco,
  1201. RECTL* prclOpaque,
  1202. BRUSHOBJ* pboFore,
  1203. BRUSHOBJ* pboOpaque)
  1204. {
  1205. BYTE iDComplexity;
  1206. BOOL bMoreGlyphs;
  1207. LONG cGlyphs;
  1208. GLYPHPOS* pgp;
  1209. BOOL bFirstTime;
  1210. POINTL ptlOrigin;
  1211. ULONG ulCharInc;
  1212. RECTL rclBounds;
  1213. ULONG ulDstOffset;
  1214. POINTL ptlDst;
  1215. SIZEL sizlDst;
  1216. FONTCACHE* pfc = pfo->pvConsumer;
  1217. BYTE* pjBase = ppdev->pjBase;
  1218. LONG lDelta = ppdev->lDelta;
  1219. BYTE jBltMode = ppdev->jModeColor;
  1220. // If the font is uncacheable, return FALSE.
  1221. if (pfc == (VOID*) -1)
  1222. {
  1223. DISPDBG((5, "bFontCache: pfo=0x%08X uncachable", pfo));
  1224. return(FALSE);
  1225. }
  1226. // We don't support complex clipping.
  1227. iDComplexity = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  1228. if (iDComplexity == DC_COMPLEX)
  1229. {
  1230. return(FALSE);
  1231. }
  1232. // If the font was invalidated by a mode switch (or DirectDraw), destroy it
  1233. // first.
  1234. if ((pfc != NULL) && (pfc->ulFontCacheID != ppdev->ulFontCacheID))
  1235. {
  1236. DISPDBG((5, "bFontCache: pfo=0x%08X invalidated (%d)", pfo,
  1237. pfc->ulFontCacheID));
  1238. DrvDestroyFont(pfo);
  1239. pfc = NULL;
  1240. }
  1241. // If the font has not been cached, allocate a cache structure now.
  1242. if (pfc == NULL)
  1243. {
  1244. // Mark the font uncacheable if it is too high. We could opt to cache
  1245. // even the largest of fonts, but that will only reject them later on
  1246. // if there is not enough font cache memory (remember we allocate off-
  1247. // screen fonts in rectangular areas) so it will be rejected anyway.
  1248. // This gives quite a bit of extra overhead we can better do without.
  1249. if ((pstro->rclBkGround.bottom - pstro->rclBkGround.top) > FONT_ALLOC_Y)
  1250. {
  1251. DISPDBG((5, "bFontCache: pfo(0x%08X) too large (%d > %d)", pfo,
  1252. pstro->rclBkGround.bottom - pstro->rclBkGround.top,
  1253. FONT_ALLOC_Y));
  1254. pfo->pvConsumer = (VOID*) -1;
  1255. return(FALSE);
  1256. }
  1257. // Allocate the font cache structure.
  1258. pfc = ALLOC(sizeof(FONTCACHE));
  1259. if (pfc == NULL)
  1260. {
  1261. // Not enough memory.
  1262. return(FALSE);
  1263. }
  1264. pfo->pvConsumer = pfc;
  1265. // Initialize the font cache structure.
  1266. pfc->ppdev = ppdev;
  1267. pfc->ulFontCacheID = ppdev->ulFontCacheID;
  1268. pfc->cWidth = BYTES_TO_PELS(FONT_ALLOC_X);
  1269. pfc->cHeight = FONT_ALLOC_Y;
  1270. pfc->pfo = pfo;
  1271. // Allocate the first block of off-screen memory.
  1272. if (pjAllocateFontCache(pfc, 0) == NULL)
  1273. {
  1274. // Not enough off-screen memory.
  1275. DISPDBG((5, "bFontCache: pfo(0x%08X) not enough memory", pfo));
  1276. if (pfc->pfm != NULL)
  1277. {
  1278. FREE(pfc->pfm);
  1279. }
  1280. FREE(pfc);
  1281. pfo->pvConsumer = NULL;
  1282. return(FALSE);
  1283. }
  1284. // Hook the font cache into the chain.
  1285. pfc->pfcPrev = NULL;
  1286. pfc->pfcNext = ppdev->pfcChain;
  1287. ppdev->pfcChain = pfc;
  1288. if (pfc->pfcNext != NULL)
  1289. {
  1290. pfc->pfcNext->pfcPrev = pfc;
  1291. }
  1292. }
  1293. // If we need to draw an opaque rectangle...
  1294. if (prclOpaque != NULL)
  1295. {
  1296. // Get opaque rectangle.
  1297. if (iDComplexity == DC_TRIVIAL)
  1298. {
  1299. ptlDst.x = prclOpaque->left;
  1300. ptlDst.y = prclOpaque->top;
  1301. sizlDst.cx = prclOpaque->right - ptlDst.x;
  1302. sizlDst.cy = prclOpaque->bottom - ptlDst.y;
  1303. }
  1304. else
  1305. {
  1306. ptlDst.x = max(prclOpaque->left, pco->rclBounds.left);
  1307. ptlDst.y = max(prclOpaque->top, pco->rclBounds.top);
  1308. sizlDst.cx = min(prclOpaque->right, pco->rclBounds.right)
  1309. - ptlDst.x;
  1310. sizlDst.cy = min(prclOpaque->bottom, pco->rclBounds.bottom)
  1311. - ptlDst.y;
  1312. }
  1313. // If the clipped opaque rectangle is valid...
  1314. if ((sizlDst.cx > 0) && (sizlDst.cy > 0))
  1315. {
  1316. ulDstOffset = (ptlDst.y * lDelta) + PELS_TO_BYTES(ptlDst.x);
  1317. sizlDst.cx = PELS_TO_BYTES(sizlDst.cx) - 1;
  1318. sizlDst.cy = sizlDst.cy - 1;
  1319. // Wait for bitblt engine.
  1320. while (BUSY_BLT(ppdev, pjBase));
  1321. // Program bitblt engine.
  1322. CP_MM_FG_COLOR(ppdev, pjBase, pboOpaque->iSolidColor);
  1323. CP_MM_XCNT(ppdev, pjBase, sizlDst.cx);
  1324. CP_MM_YCNT(ppdev, pjBase, sizlDst.cy);
  1325. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1326. CP_MM_SRC_ADDR(ppdev, pjBase, 0);
  1327. CP_MM_BLT_MODE(ppdev, pjBase, jBltMode |
  1328. ENABLE_COLOR_EXPAND |
  1329. ENABLE_8x8_PATTERN_COPY);
  1330. CP_MM_ROP(ppdev, pjBase, HW_P);
  1331. CP_MM_BLT_EXT_MODE(ppdev, pjBase, ENABLE_SOLID_FILL);
  1332. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1333. }
  1334. }
  1335. // Setup loop variables.
  1336. bFirstTime = TRUE;
  1337. ulCharInc = pstro->ulCharInc;
  1338. jBltMode |= ENABLE_COLOR_EXPAND | ENABLE_TRANSPARENCY_COMPARE;
  1339. // No clipping...
  1340. if (iDComplexity == DC_TRIVIAL)
  1341. {
  1342. #if 1 // D5480
  1343. ppdev->pfnGlyphOut(ppdev, pfc, pstro, pboFore->iSolidColor);
  1344. #else
  1345. do
  1346. {
  1347. // Get pointer to array of glyphs.
  1348. if (pstro->pgp != NULL)
  1349. {
  1350. pgp = pstro->pgp;
  1351. cGlyphs = pstro->cGlyphs;
  1352. bMoreGlyphs = FALSE;
  1353. }
  1354. else
  1355. {
  1356. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphs, &pgp);
  1357. }
  1358. // Setup the blitter if this is the first loop through.
  1359. if (bFirstTime)
  1360. {
  1361. // Wait for the bitblt engine.
  1362. while (BUSY_BLT(ppdev, pjBase));
  1363. // Setup the common bitblt registers.
  1364. CP_MM_FG_COLOR(ppdev, pjBase, pboFore->iSolidColor);
  1365. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1366. CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
  1367. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
  1368. // Mark registers as setup.
  1369. bFirstTime = FALSE;
  1370. }
  1371. // Get coordinates of first glyph.
  1372. ptlOrigin.x = pgp->ptl.x;
  1373. ptlOrigin.y = pgp->ptl.y;
  1374. // Loop through all glyphs.
  1375. while (cGlyphs-- > 0)
  1376. {
  1377. LONG cy;
  1378. GLYPHCACHE* pgc;
  1379. if (pgp->hg < MAX_GLYPHS)
  1380. {
  1381. // This is a cacheable glyph index.
  1382. pgc = &pfc->aGlyphs[pgp->hg];
  1383. cy = (pgc->pjGlyph == NULL)
  1384. ? lAllocateGlyph(pfc, pgp->pgdf->pgb, pgc)
  1385. : pgc->sizlBytes.cy;
  1386. }
  1387. else
  1388. {
  1389. // The glyph index is out of range.
  1390. cy = GLYPH_UNCACHEABLE;
  1391. }
  1392. if (cy >= 0) // The glyph is cached, expand it to the screen.
  1393. {
  1394. // Setup the destination variables.
  1395. ptlDst.x = ptlOrigin.x + pgc->ptlOrigin.x;
  1396. ptlDst.y = ptlOrigin.y + pgc->ptlOrigin.y;
  1397. ulDstOffset = (ptlDst.y * lDelta) + PELS_TO_BYTES(ptlDst.x);
  1398. // Wait for the bitblt engine.
  1399. while (BUSY_BLT(ppdev, pjBase));
  1400. // Perform the blit expansion.
  1401. CP_MM_XCNT(ppdev, pjBase, pgc->sizlBytes.cx);
  1402. CP_MM_YCNT(ppdev, pjBase, cy);
  1403. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, pgc->lDelta);
  1404. CP_MM_SRC_ADDR(ppdev, pjBase, pgc->pjGlyph);
  1405. CP_MM_BLT_MODE(ppdev, pjBase, jBltMode);
  1406. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1407. }
  1408. else if (cy == GLYPH_UNCACHEABLE)
  1409. {
  1410. // The glyph is uncacheable, draw it directly.
  1411. vDrawGlyph(ppdev, pgp->pgdf->pgb, ptlOrigin);
  1412. }
  1413. // Next glyph.
  1414. pgp++;
  1415. if (ulCharInc)
  1416. {
  1417. ptlOrigin.x += ulCharInc;
  1418. }
  1419. else
  1420. {
  1421. ptlOrigin.x = pgp->ptl.x;
  1422. ptlOrigin.y = pgp->ptl.y;
  1423. }
  1424. }
  1425. } while (bMoreGlyphs);
  1426. #endif // endif D5480
  1427. return(TRUE);
  1428. }
  1429. // Clipping...
  1430. rclBounds = pco->rclBounds;
  1431. #if 1 // D5480
  1432. ppdev->pfnGlyphOutClip(ppdev, pfc, pstro, &rclBounds, pboFore->iSolidColor);
  1433. #else
  1434. do
  1435. {
  1436. // Get pointer to array of glyphs.
  1437. if (pstro->pgp != NULL)
  1438. {
  1439. pgp = pstro->pgp;
  1440. cGlyphs = pstro->cGlyphs;
  1441. bMoreGlyphs = FALSE;
  1442. }
  1443. else
  1444. {
  1445. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphs, &pgp);
  1446. }
  1447. // Setup the blitter if this is the first loop through.
  1448. if (bFirstTime)
  1449. {
  1450. // Wait for the bitblt engine.
  1451. while (BUSY_BLT(ppdev, pjBase));
  1452. // Setup the common bitblt registers.
  1453. CP_MM_FG_COLOR(ppdev, pjBase, pboFore->iSolidColor);
  1454. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1455. CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
  1456. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
  1457. // Mark registers as setup.
  1458. bFirstTime = FALSE;
  1459. }
  1460. // Get coordinates of first glyph.
  1461. ptlOrigin.x = pgp->ptl.x;
  1462. ptlOrigin.y = pgp->ptl.y;
  1463. // Loop through all glyphs.
  1464. while (cGlyphs-- > 0)
  1465. {
  1466. LONG c, cy;
  1467. GLYPHCACHE* pgc;
  1468. if (pgp->hg < MAX_GLYPHS)
  1469. {
  1470. // This is a cacheable glyph index.
  1471. pgc = &pfc->aGlyphs[pgp->hg];
  1472. cy = (pgc->pjGlyph == NULL)
  1473. ? lAllocateGlyph(pfc, pgp->pgdf->pgb, pgc)
  1474. : pgc->sizlBytes.cy;
  1475. }
  1476. else
  1477. {
  1478. // The glyph index is out of range.
  1479. goto SoftwareClipping;
  1480. }
  1481. if (cy >= 0)
  1482. {
  1483. // The glyph is cached, expand it to the screen.
  1484. ULONG ulSrcOffset;
  1485. RECTL rcl;
  1486. LONG lSrcDelta;
  1487. LONG cSkipBits;
  1488. // Calculate the glyph bounding box.
  1489. rcl.left = ptlOrigin.x + pgc->ptlOrigin.x;
  1490. rcl.right = rcl.left + pgc->sizlPixels.cx;
  1491. if ((rcl.left >= rclBounds.right) ||
  1492. (rcl.right <= rclBounds.left))
  1493. {
  1494. goto NextGlyph;
  1495. }
  1496. rcl.top = ptlOrigin.y + pgc->ptlOrigin.y;
  1497. rcl.bottom = rcl.top + pgc->sizlPixels.cy;
  1498. if ((rcl.top >= rclBounds.bottom) ||
  1499. (rcl.bottom <= rclBounds.top))
  1500. {
  1501. goto NextGlyph;
  1502. }
  1503. // Setup source parameters.
  1504. ulSrcOffset = (ULONG) pgc->pjGlyph;
  1505. lSrcDelta = pgc->lDelta;
  1506. // Do the left side clipping.
  1507. c = rclBounds.left - rcl.left;
  1508. if (c > 0)
  1509. {
  1510. ulSrcOffset += c >> 3;
  1511. cSkipBits = c & 7;
  1512. rcl.left += c & ~7;
  1513. if (ppdev->cBpp == 3)
  1514. {
  1515. cSkipBits *= 3;
  1516. }
  1517. ulSrcOffset |= cSkipBits << 24;
  1518. }
  1519. // Do the top side clipping.
  1520. c = rclBounds.top - rcl.top;
  1521. if (c > 0)
  1522. {
  1523. rcl.top += c;
  1524. ulSrcOffset += c * lSrcDelta;
  1525. }
  1526. // Calculate size of the blit.
  1527. sizlDst.cx = min(rcl.right, rclBounds.right) - rcl.left;
  1528. sizlDst.cy = min(rcl.bottom, rclBounds.bottom) - rcl.top;
  1529. if ((sizlDst.cx <= 0) || (sizlDst.cy <= 0))
  1530. {
  1531. goto NextGlyph;
  1532. }
  1533. // Setup destination variables.
  1534. ulDstOffset = (rcl.top * lDelta) + PELS_TO_BYTES(rcl.left);
  1535. // HARDWARE BUG:
  1536. // ============
  1537. // A monochrome screen-to-screen expansion with a source pitch
  1538. // not equaling the width of the expansion (i.e. left- and/or
  1539. // right-side clipping) is not done correctly by the hardware.
  1540. // So we have to do the line increment by software.
  1541. if (((sizlDst.cx + 7) >> 3) != lSrcDelta)
  1542. {
  1543. // Wait for the bitblt engine.
  1544. while (BUSY_BLT(ppdev, pjBase));
  1545. // Setup the common bitblt registers.
  1546. CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(sizlDst.cx) - 1);
  1547. CP_MM_YCNT(ppdev, pjBase, 0);
  1548. CP_MM_BLT_MODE(ppdev, pjBase, jBltMode);
  1549. while (TRUE)
  1550. {
  1551. // Perform the expansion.
  1552. CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
  1553. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1554. // Next line.
  1555. if (--sizlDst.cy == 0)
  1556. {
  1557. goto NextGlyph;
  1558. }
  1559. ulSrcOffset += lSrcDelta;
  1560. ulDstOffset += lDelta;
  1561. // Wait for the bitblt engine.
  1562. while (BUSY_BLT(ppdev, pjBase));
  1563. }
  1564. }
  1565. // Wait for the bitblt engine.
  1566. while (BUSY_BLT(ppdev, pjBase));
  1567. // Perform the expansion.
  1568. CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(sizlDst.cx) - 1);
  1569. CP_MM_YCNT(ppdev, pjBase, sizlDst.cy - 1);
  1570. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, lSrcDelta);
  1571. CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
  1572. CP_MM_BLT_MODE(ppdev, pjBase, jBltMode);
  1573. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1574. }
  1575. else if (cy == GLYPH_UNCACHEABLE)
  1576. {
  1577. SoftwareClipping:
  1578. {
  1579. // The glyph is uncacheable, draw it directly.
  1580. vClipGlyph(ppdev, pgp->pgdf->pgb, ptlOrigin, rclBounds,
  1581. pboFore->iSolidColor);
  1582. }
  1583. }
  1584. // Next glyph.
  1585. NextGlyph:
  1586. {
  1587. pgp++;
  1588. if (ulCharInc)
  1589. {
  1590. ptlOrigin.x += ulCharInc;
  1591. }
  1592. else
  1593. {
  1594. ptlOrigin.x = pgp->ptl.x;
  1595. ptlOrigin.y = pgp->ptl.y;
  1596. }
  1597. }
  1598. }
  1599. } while (bMoreGlyphs);
  1600. #endif // D5480
  1601. return(TRUE);
  1602. }
  1603. /******************************************************************************\
  1604. *
  1605. * Function: vDrawGlyph
  1606. *
  1607. * Draw an uncacheable glyph directly to screen.
  1608. *
  1609. * Parameters: ppdev Pointer to physical device.
  1610. * pgb Pointer to glyph to draw.
  1611. * ptl Coordinates of the glyph.
  1612. *
  1613. * Returns: Nothing.
  1614. *
  1615. \******************************************************************************/
  1616. VOID vDrawGlyph(
  1617. PDEV* ppdev,
  1618. GLYPHBITS* pgb,
  1619. POINTL ptl)
  1620. {
  1621. BYTE* pjBase = ppdev->pjBase;
  1622. BYTE jBltMode;
  1623. ULONG dstOffset;
  1624. DWORD* pulSrc;
  1625. DWORD* pulDst;
  1626. LONG c, cx, cy;
  1627. LONG x, y;
  1628. // BLT Mode Register value.
  1629. jBltMode = ENABLE_COLOR_EXPAND
  1630. | ENABLE_TRANSPARENCY_COMPARE
  1631. | SRC_CPU_DATA
  1632. | ppdev->jModeColor;
  1633. // Calculate the destination offset.
  1634. x = ptl.x + pgb->ptlOrigin.x;
  1635. y = ptl.y + pgb->ptlOrigin.y;
  1636. dstOffset = (y * ppdev->lDelta) + PELS_TO_BYTES(x);
  1637. // Calculate the glyph variables.
  1638. pulSrc = (DWORD*) pgb->aj;
  1639. pulDst = (DWORD*) ppdev->pulXfer;
  1640. cx = pgb->sizlBitmap.cx;
  1641. cy = pgb->sizlBitmap.cy;
  1642. c = (((cx + 7) >> 3) * cy + 3) >> 2; // Number of DWORDs to transfer.
  1643. cx *= ppdev->cBpp;
  1644. // Wait for the blitter.
  1645. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  1646. // Setup the blitter registers.
  1647. CP_MM_XCNT(ppdev, pjBase, cx - 1);
  1648. CP_MM_YCNT(ppdev, pjBase, cy - 1);
  1649. CP_MM_BLT_MODE(ppdev, pjBase, jBltMode);
  1650. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
  1651. CP_MM_DST_ADDR(ppdev, pjBase, dstOffset);
  1652. // Copy the data from the glyph to the screen. Note that the glyph is
  1653. // always DWORD aligned, so we don't have to do anything weird here.
  1654. while (c-- > 0)
  1655. {
  1656. *pulDst = *pulSrc++;
  1657. }
  1658. }
  1659. /******************************************************************************\
  1660. *
  1661. * Function: vClipGlyph
  1662. *
  1663. * Draw an uncacheable glyph directly to screen using a clipping rectangle.
  1664. *
  1665. * Parameters: ppdev Pointer to physical device.
  1666. * pgb Pointer to glyph to draw.
  1667. * ptl Coordinates of the glyph.
  1668. * rclBounds Clipping rectangle.
  1669. * ulColor Foreground Color.
  1670. *
  1671. * Returns: Nothing.
  1672. *
  1673. \******************************************************************************/
  1674. VOID vClipGlyph(
  1675. PDEV* ppdev,
  1676. GLYPHBITS* pgb,
  1677. POINTL ptl,
  1678. RECTL* rclBounds,
  1679. ULONG ulColor)
  1680. {
  1681. BYTE jBltMode;
  1682. ULONG ulDstOffset;
  1683. BYTE* pjSrc;
  1684. LONG cx, cy;
  1685. RECTL rcl;
  1686. LONG lSrcDelta;
  1687. LONG i, cBytes;
  1688. BYTE* pjBase = ppdev->pjBase;
  1689. LONG lDelta = ppdev->lDelta;
  1690. ULONG* pulDst = (ULONG*) ppdev->pulXfer;
  1691. LONG cSkipBits = 0;
  1692. // Calculate glyph bounding box.
  1693. rcl.left = ptl.x + pgb->ptlOrigin.x;
  1694. rcl.top = ptl.y + pgb->ptlOrigin.y;
  1695. rcl.right = min(rcl.left + pgb->sizlBitmap.cx, rclBounds->right);
  1696. rcl.bottom = min(rcl.top + pgb->sizlBitmap.cy, rclBounds->bottom);
  1697. // Setup source variables.
  1698. pjSrc = pgb->aj;
  1699. lSrcDelta = (pgb->sizlBitmap.cx + 7) >> 3;
  1700. // Setup BLT Mode Register value.
  1701. jBltMode = ENABLE_COLOR_EXPAND
  1702. | ENABLE_TRANSPARENCY_COMPARE
  1703. | SRC_CPU_DATA
  1704. | ppdev->jModeColor;
  1705. // Do left side clipping.
  1706. cx = rclBounds->left - rcl.left;
  1707. if (cx > 0)
  1708. {
  1709. pjSrc += cx >> 3;
  1710. cSkipBits = cx & 7;
  1711. rcl.left += cx & ~7;
  1712. if (ppdev->cBpp == 3)
  1713. {
  1714. cSkipBits *= 3;
  1715. }
  1716. }
  1717. // Calculate width in pixels.
  1718. cx = rcl.right - rcl.left;
  1719. if (cx <= 0)
  1720. {
  1721. // Glyph is completely clipped.
  1722. return;
  1723. }
  1724. // Do top side clipping.
  1725. cy = rclBounds->top - rcl.top;
  1726. if (cy > 0)
  1727. {
  1728. pjSrc += cy * lSrcDelta;
  1729. rcl.top += cy;
  1730. }
  1731. // Calculate height in pixels.
  1732. cy = rcl.bottom - rcl.top;
  1733. if (cy <= 0)
  1734. {
  1735. // Glyph is completely clipped.
  1736. return;
  1737. }
  1738. // Setup destination variables.
  1739. ulDstOffset = (rcl.top * ppdev->lDelta) + PELS_TO_BYTES(rcl.left);
  1740. cBytes = (cx + 7) >> 3;
  1741. // Wait for the bitblt engine.
  1742. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  1743. // Setup the bitblt registers.
  1744. CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(cx) - 1);
  1745. CP_MM_YCNT(ppdev, pjBase, cy - 1);
  1746. CP_MM_DST_WRITE_MASK(ppdev, pjBase, cSkipBits);
  1747. CP_MM_BLT_MODE(ppdev, pjBase, jBltMode);
  1748. CP_MM_BLT_EXT_MODE(ppdev, pjBase, SOURCE_GRANULARITY);
  1749. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1750. while (cy--)
  1751. {
  1752. BYTE* pjSrcTmp = pjSrc;
  1753. // Copy one line of glyph data to the screen.
  1754. for (i = cBytes; i >= sizeof(ULONG); i -= sizeof(ULONG))
  1755. {
  1756. *pulDst = *((ULONG*)pjSrcTmp)++;
  1757. }
  1758. if (i == 1)
  1759. {
  1760. *pulDst = *(BYTE*)pjSrcTmp;
  1761. }
  1762. else if (i == 2)
  1763. {
  1764. *pulDst = *(USHORT*)pjSrcTmp;
  1765. }
  1766. else if (i == 3)
  1767. {
  1768. *pulDst = pjSrcTmp[0] | (pjSrcTmp[1] << 8) | (pjSrcTmp[2] << 16);
  1769. }
  1770. pjSrc += lSrcDelta;
  1771. }
  1772. while (BUSY_BLT(ppdev, pjBase));
  1773. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
  1774. }
  1775. #if 1 // D5480
  1776. /******************************************************************************\
  1777. *
  1778. * Function: vGlyphOut
  1779. *
  1780. * Draw an uncacheable glyph directly to screen.
  1781. *
  1782. * Parameters: ppdev Pointer to physical device.
  1783. * pfc Pointer to FONTCACHE.
  1784. * pstro Pointer to array of glyphs to draw.
  1785. * ulSolidColor Foreground Color.
  1786. *
  1787. * Returns: Nothing.
  1788. *
  1789. \******************************************************************************/
  1790. VOID vMmGlyphOut(
  1791. PDEV* ppdev,
  1792. FONTCACHE* pfc,
  1793. STROBJ* pstro,
  1794. ULONG ulSolidColor )
  1795. {
  1796. BOOL bMoreGlyphs;
  1797. LONG cGlyphs;
  1798. GLYPHPOS* pgp;
  1799. BOOL bFirstTime;
  1800. POINTL ptlOrigin;
  1801. ULONG ulCharInc;
  1802. ULONG ulDstOffset;
  1803. POINTL ptlDst;
  1804. BYTE* pjBase = ppdev->pjBase;
  1805. BYTE jBltMode = ppdev->jModeColor;
  1806. LONG lDelta = ppdev->lDelta;
  1807. bFirstTime = TRUE;
  1808. ulCharInc = pstro->ulCharInc;
  1809. jBltMode |= ENABLE_COLOR_EXPAND | ENABLE_TRANSPARENCY_COMPARE;
  1810. do
  1811. {
  1812. // Get pointer to array of glyphs.
  1813. if (pstro->pgp != NULL)
  1814. {
  1815. pgp = pstro->pgp;
  1816. cGlyphs = pstro->cGlyphs;
  1817. bMoreGlyphs = FALSE;
  1818. }
  1819. else
  1820. {
  1821. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphs, &pgp);
  1822. }
  1823. // Setup the blitter if this is the first loop through.
  1824. if (bFirstTime)
  1825. {
  1826. // Wait for the bitblt engine.
  1827. while (BUSY_BLT(ppdev, pjBase));
  1828. // Setup the common bitblt registers.
  1829. CP_MM_FG_COLOR(ppdev, pjBase, ulSolidColor);
  1830. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1831. CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
  1832. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
  1833. // Mark registers as setup.
  1834. bFirstTime = FALSE;
  1835. }
  1836. // Get coordinates of first glyph.
  1837. ptlOrigin.x = pgp->ptl.x;
  1838. ptlOrigin.y = pgp->ptl.y;
  1839. // Loop through all glyphs.
  1840. while (cGlyphs-- > 0)
  1841. {
  1842. LONG cy;
  1843. GLYPHCACHE* pgc;
  1844. if (pgp->hg < MAX_GLYPHS)
  1845. {
  1846. // This is a cacheable glyph index.
  1847. pgc = &pfc->aGlyphs[pgp->hg];
  1848. cy = (pgc->pjGlyph == NULL)
  1849. ? lAllocateGlyph(pfc, pgp->pgdf->pgb, pgc)
  1850. : pgc->sizlBytes.cy;
  1851. }
  1852. else
  1853. {
  1854. // The glyph index is out of range.
  1855. cy = GLYPH_UNCACHEABLE;
  1856. }
  1857. if (cy >= 0) // The glyph is cached, expand it to the screen.
  1858. {
  1859. // Setup the destination variables.
  1860. ptlDst.x = ptlOrigin.x + pgc->ptlOrigin.x;
  1861. ptlDst.y = ptlOrigin.y + pgc->ptlOrigin.y;
  1862. ulDstOffset = (ptlDst.y * lDelta) + PELS_TO_BYTES(ptlDst.x);
  1863. // Wait for the bitblt engine.
  1864. while (BUSY_BLT(ppdev, pjBase));
  1865. // Perform the blit expansion.
  1866. CP_MM_XCNT(ppdev, pjBase, pgc->sizlBytes.cx);
  1867. CP_MM_YCNT(ppdev, pjBase, cy);
  1868. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, pgc->lDelta);
  1869. CP_MM_SRC_ADDR(ppdev, pjBase, (ULONG_PTR)pgc->pjGlyph);
  1870. CP_MM_BLT_MODE(ppdev, pjBase, jBltMode);
  1871. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  1872. }
  1873. else if (cy == GLYPH_UNCACHEABLE)
  1874. {
  1875. // The glyph is uncacheable, draw it directly.
  1876. vDrawGlyph(ppdev, pgp->pgdf->pgb, ptlOrigin);
  1877. }
  1878. // Next glyph.
  1879. pgp++;
  1880. if (ulCharInc)
  1881. {
  1882. ptlOrigin.x += ulCharInc;
  1883. }
  1884. else
  1885. {
  1886. ptlOrigin.x = pgp->ptl.x;
  1887. ptlOrigin.y = pgp->ptl.y;
  1888. }
  1889. }
  1890. } while (bMoreGlyphs);
  1891. }
  1892. /******************************************************************************\
  1893. *
  1894. * Function: vGlyphOutClip
  1895. *
  1896. * Draw an uncacheable glyph directly to screen.
  1897. *
  1898. * Parameters: ppdev Pointer to physical device.
  1899. * pfc Pointer to FONTCACHE.
  1900. * pstro Pointer to array of glyphs to draw.
  1901. * rclBounds Clipping rectangle.
  1902. * ulSolidColor Foreground Color.
  1903. *
  1904. * Returns: Nothing.
  1905. *
  1906. \******************************************************************************/
  1907. VOID vMmGlyphOutClip(
  1908. PDEV* ppdev,
  1909. FONTCACHE* pfc,
  1910. STROBJ* pstro,
  1911. RECTL* rclBounds,
  1912. ULONG ulSolidColor )
  1913. {
  1914. BOOL bMoreGlyphs;
  1915. LONG cGlyphs;
  1916. GLYPHPOS* pgp;
  1917. BOOL bFirstTime;
  1918. POINTL ptlOrigin;
  1919. ULONG ulCharInc;
  1920. ULONG ulDstOffset;
  1921. POINTL ptlDst;
  1922. BYTE* pjBase = ppdev->pjBase;
  1923. BYTE jBltMode = ppdev->jModeColor;
  1924. LONG lDelta = ppdev->lDelta;
  1925. bFirstTime = TRUE;
  1926. ulCharInc = pstro->ulCharInc;
  1927. jBltMode |= ENABLE_COLOR_EXPAND | ENABLE_TRANSPARENCY_COMPARE;
  1928. do
  1929. {
  1930. // Get pointer to array of glyphs.
  1931. if (pstro->pgp != NULL)
  1932. {
  1933. pgp = pstro->pgp;
  1934. cGlyphs = pstro->cGlyphs;
  1935. bMoreGlyphs = FALSE;
  1936. }
  1937. else
  1938. {
  1939. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphs, &pgp);
  1940. }
  1941. // Setup the blitter if this is the first loop through.
  1942. if (bFirstTime)
  1943. {
  1944. // Wait for the bitblt engine.
  1945. while (BUSY_BLT(ppdev, pjBase));
  1946. // Setup the common bitblt registers.
  1947. CP_MM_FG_COLOR(ppdev, pjBase, ulSolidColor);
  1948. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  1949. CP_MM_ROP(ppdev, pjBase, CL_SRC_COPY);
  1950. CP_MM_BLT_EXT_MODE(ppdev, pjBase, 0);
  1951. // Mark registers as setup.
  1952. bFirstTime = FALSE;
  1953. }
  1954. // Get coordinates of first glyph.
  1955. ptlOrigin.x = pgp->ptl.x;
  1956. ptlOrigin.y = pgp->ptl.y;
  1957. // Loop through all glyphs.
  1958. while (cGlyphs-- > 0)
  1959. {
  1960. LONG c, cy;
  1961. GLYPHCACHE* pgc;
  1962. if (pgp->hg < MAX_GLYPHS)
  1963. {
  1964. // This is a cacheable glyph index.
  1965. pgc = &pfc->aGlyphs[pgp->hg];
  1966. cy = (pgc->pjGlyph == NULL)
  1967. ? lAllocateGlyph(pfc, pgp->pgdf->pgb, pgc)
  1968. : pgc->sizlBytes.cy;
  1969. }
  1970. else
  1971. {
  1972. // The glyph index is out of range.
  1973. goto SoftwareClipping;
  1974. }
  1975. if (cy >= 0)
  1976. {
  1977. // The glyph is cached, expand it to the screen.
  1978. ULONG ulSrcOffset;
  1979. RECTL rcl;
  1980. LONG lSrcDelta;
  1981. LONG cSkipBits;
  1982. SIZEL sizlDst;
  1983. // Calculate the glyph bounding box.
  1984. rcl.left = ptlOrigin.x + pgc->ptlOrigin.x;
  1985. rcl.right = rcl.left + pgc->sizlPixels.cx;
  1986. if ((rcl.left >= rclBounds->right) ||
  1987. (rcl.right <= rclBounds->left))
  1988. {
  1989. goto NextGlyph;
  1990. }
  1991. rcl.top = ptlOrigin.y + pgc->ptlOrigin.y;
  1992. rcl.bottom = rcl.top + pgc->sizlPixels.cy;
  1993. if ((rcl.top >= rclBounds->bottom) ||
  1994. (rcl.bottom <= rclBounds->top))
  1995. {
  1996. goto NextGlyph;
  1997. }
  1998. // Setup source parameters.
  1999. ulSrcOffset = (ULONG)((ULONG_PTR)pgc->pjGlyph);
  2000. lSrcDelta = pgc->lDelta;
  2001. // Do the left side clipping.
  2002. c = rclBounds->left - rcl.left;
  2003. if (c > 0)
  2004. {
  2005. ulSrcOffset += c >> 3;
  2006. cSkipBits = c & 7;
  2007. rcl.left += c & ~7;
  2008. if (ppdev->cBpp == 3)
  2009. {
  2010. cSkipBits *= 3;
  2011. }
  2012. ulSrcOffset |= cSkipBits << 24;
  2013. }
  2014. // Do the top side clipping.
  2015. c = rclBounds->top - rcl.top;
  2016. if (c > 0)
  2017. {
  2018. rcl.top += c;
  2019. ulSrcOffset += c * lSrcDelta;
  2020. }
  2021. // Calculate size of the blit.
  2022. sizlDst.cx = min(rcl.right, rclBounds->right) - rcl.left;
  2023. sizlDst.cy = min(rcl.bottom, rclBounds->bottom) - rcl.top;
  2024. if ((sizlDst.cx <= 0) || (sizlDst.cy <= 0))
  2025. {
  2026. goto NextGlyph;
  2027. }
  2028. // Setup destination variables.
  2029. ulDstOffset = (rcl.top * lDelta) + PELS_TO_BYTES(rcl.left);
  2030. // HARDWARE BUG:
  2031. // ============
  2032. // A monochrome screen-to-screen expansion with a source pitch
  2033. // not equaling the width of the expansion (i.e. left- and/or
  2034. // right-side clipping) is not done correctly by the hardware.
  2035. // So we have to do the line increment by software.
  2036. if (((sizlDst.cx + 7) >> 3) != lSrcDelta)
  2037. {
  2038. // Wait for the bitblt engine.
  2039. while (BUSY_BLT(ppdev, pjBase));
  2040. // Setup the common bitblt registers.
  2041. CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(sizlDst.cx) - 1);
  2042. CP_MM_YCNT(ppdev, pjBase, 0);
  2043. CP_MM_BLT_MODE(ppdev, pjBase, jBltMode);
  2044. while (TRUE)
  2045. {
  2046. // Perform the expansion.
  2047. CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
  2048. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  2049. // Next line.
  2050. if (--sizlDst.cy == 0)
  2051. {
  2052. goto NextGlyph;
  2053. }
  2054. ulSrcOffset += lSrcDelta;
  2055. ulDstOffset += lDelta;
  2056. // Wait for the bitblt engine.
  2057. while (BUSY_BLT(ppdev, pjBase));
  2058. }
  2059. }
  2060. // Wait for the bitblt engine.
  2061. while (BUSY_BLT(ppdev, pjBase));
  2062. // Perform the expansion.
  2063. CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(sizlDst.cx) - 1);
  2064. CP_MM_YCNT(ppdev, pjBase, sizlDst.cy - 1);
  2065. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, lSrcDelta);
  2066. CP_MM_SRC_ADDR(ppdev, pjBase, ulSrcOffset);
  2067. CP_MM_BLT_MODE(ppdev, pjBase, jBltMode);
  2068. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  2069. }
  2070. else if (cy == GLYPH_UNCACHEABLE)
  2071. {
  2072. SoftwareClipping:
  2073. {
  2074. // The glyph is uncacheable, draw it directly.
  2075. vClipGlyph(ppdev, pgp->pgdf->pgb, ptlOrigin, rclBounds,
  2076. ulSolidColor);
  2077. }
  2078. }
  2079. // Next glyph.
  2080. NextGlyph:
  2081. {
  2082. pgp++;
  2083. if (ulCharInc)
  2084. {
  2085. ptlOrigin.x += ulCharInc;
  2086. }
  2087. else
  2088. {
  2089. ptlOrigin.x = pgp->ptl.x;
  2090. ptlOrigin.y = pgp->ptl.y;
  2091. }
  2092. }
  2093. }
  2094. } while (bMoreGlyphs);
  2095. }
  2096. /******************************************************************************\
  2097. *
  2098. * Function: vGlyphOut80
  2099. *
  2100. * Draw an uncacheable glyph directly to screen.
  2101. *
  2102. * Parameters: ppdev Pointer to physical device.
  2103. * pfc Pointer to FONTCACHE.
  2104. * pstro Pointer to array of glyphs to draw.
  2105. * ulSolidColor Foreground Color.
  2106. *
  2107. * Returns: Nothing.
  2108. *
  2109. \******************************************************************************/
  2110. VOID vMmGlyphOut80(
  2111. PDEV* ppdev,
  2112. FONTCACHE* pfc,
  2113. STROBJ* pstro,
  2114. ULONG ulSolidColor )
  2115. {
  2116. ULONG_PTR* ulCLStart;
  2117. ULONG ulWidthHeight;
  2118. ULONG xCLOffset;
  2119. BOOL bMoreGlyphs;
  2120. LONG cGlyphs;
  2121. GLYPHPOS* pgp;
  2122. POINTL ptlOrigin;
  2123. ULONG ulCharInc;
  2124. POINTL ptlDst;
  2125. LONG cy;
  2126. GLYPHCACHE* pgc;
  2127. DWORD jSaveMode;
  2128. ULONG cCommandPacket = 0;
  2129. ULONG ulDstOffset = 0;
  2130. BOOL bCommandListOpen = FALSE;
  2131. BYTE* pjBase = ppdev->pjBase;
  2132. LONG lDelta = ppdev->lDelta;
  2133. DWORD jExtMode = ENABLE_XY_POSITION_PACKED
  2134. | CL_PACKED_SRC_COPY
  2135. | ppdev->jModeColor
  2136. | ENABLE_COLOR_EXPAND
  2137. | ENABLE_TRANSPARENCY_COMPARE;
  2138. ulCharInc = pstro->ulCharInc;
  2139. jSaveMode = jExtMode;
  2140. //
  2141. // Make sure we can write to the video registers.
  2142. //
  2143. // We need to change to wait for buffer ready
  2144. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  2145. // Setup the common bitblt registers.
  2146. CP_MM_FG_COLOR(ppdev, pjBase, ulSolidColor);
  2147. // Do we really need to set it every time?
  2148. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  2149. CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
  2150. do
  2151. {
  2152. // Get pointer to array of glyphs.
  2153. if (pstro->pgp != NULL)
  2154. {
  2155. pgp = pstro->pgp;
  2156. cGlyphs = pstro->cGlyphs;
  2157. bMoreGlyphs = FALSE;
  2158. }
  2159. else
  2160. {
  2161. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphs, &pgp);
  2162. }
  2163. // Get coordinates of first glyph.
  2164. ptlOrigin.x = pgp->ptl.x;
  2165. ptlOrigin.y = pgp->ptl.y;
  2166. // Loop through all glyphs.
  2167. while (cGlyphs-- > 0)
  2168. {
  2169. if (pgp->hg < MAX_GLYPHS)
  2170. {
  2171. // This is a cacheable glyph index.
  2172. pgc = &pfc->aGlyphs[pgp->hg];
  2173. cy = (pgc->pjGlyph == NULL)
  2174. ? lAllocateGlyph(pfc, pgp->pgdf->pgb, pgc)
  2175. : pgc->sizlBytes.cy;
  2176. }
  2177. else
  2178. {
  2179. // The glyph index is out of range.
  2180. cy = GLYPH_UNCACHEABLE;
  2181. }
  2182. if (cy >= 0) // The glyph is cached, expand it to the screen.
  2183. {
  2184. if ( bCommandListOpen )
  2185. {
  2186. // Command List
  2187. if( cCommandPacket == 0 )
  2188. {
  2189. jExtMode |= ENABLE_COMMAND_LIST_PACKED;
  2190. ulCLStart = ppdev->pCommandList;
  2191. ulDstOffset |= (ULONG)(((ULONG_PTR)ulCLStart
  2192. - (ULONG_PTR)ppdev->pjScreen) << 14);
  2193. CP_MM_CL_SWITCH(ppdev);
  2194. }
  2195. // Calculate the destination address and size.
  2196. *ulCLStart = PACKXY_FAST(pgc->sizlPixels.cx - 1, cy);
  2197. // XY
  2198. *(ulCLStart + 1) = PACKXY_FAST(ptlOrigin.x + pgc->ptlOrigin.x,
  2199. ptlOrigin.y + pgc->ptlOrigin.y);
  2200. // Source Start address
  2201. *(ulCLStart + 2) = (ULONG)((ULONG_PTR)pgc->pjGlyph);
  2202. // Dst/SRC pitch
  2203. *(ulCLStart + 3) = PACKXY_FAST(lDelta, pgc->lDelta);
  2204. ulCLStart += 4;
  2205. if( ++cCommandPacket > COMMAND_TOTAL_PACKETS )
  2206. {
  2207. // Indicate last Packet
  2208. *(ulCLStart - 4) |= COMMAND_LAST_PACKET;
  2209. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode);
  2210. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  2211. CP_MM_DST_X(ppdev, pjBase, xCLOffset);
  2212. bCommandListOpen = FALSE;
  2213. cCommandPacket = 0;
  2214. jExtMode = jSaveMode;
  2215. ulDstOffset = 0;
  2216. }
  2217. }
  2218. else
  2219. {
  2220. bCommandListOpen = TRUE;
  2221. //
  2222. // Make sure we can write to the video registers.
  2223. //
  2224. // We need to change to wait for buffer ready
  2225. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  2226. // Setup the first set.
  2227. xCLOffset = ptlOrigin.x + pgc->ptlOrigin.x;
  2228. CP_MM_DST_Y(ppdev, pjBase, ptlOrigin.y + pgc->ptlOrigin.y);
  2229. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, pgc->lDelta);
  2230. CP_MM_SRC_ADDR(ppdev,pjBase,(ULONG_PTR)pgc->pjGlyph);
  2231. // Perform the blit expansion.
  2232. CP_MM_XCNT(ppdev, pjBase, pgc->sizlPixels.cx - 1 );
  2233. CP_MM_YCNT(ppdev, pjBase, cy);
  2234. }
  2235. }
  2236. else if (cy == GLYPH_UNCACHEABLE)
  2237. {
  2238. if ( bCommandListOpen )
  2239. {
  2240. // Indicate last Packet
  2241. if ( cCommandPacket )
  2242. *(ulCLStart - 4) |= COMMAND_LAST_PACKET;
  2243. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode);
  2244. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  2245. CP_MM_DST_X(ppdev, pjBase, xCLOffset);
  2246. bCommandListOpen = FALSE;
  2247. jExtMode = jSaveMode;
  2248. cCommandPacket = 0;
  2249. ulDstOffset = 0;
  2250. }
  2251. // The glyph is uncacheable, draw it directly.
  2252. vDrawGlyph(ppdev, pgp->pgdf->pgb, ptlOrigin);
  2253. }
  2254. // Next glyph.
  2255. pgp++;
  2256. if (ulCharInc)
  2257. {
  2258. ptlOrigin.x += ulCharInc;
  2259. }
  2260. else
  2261. {
  2262. ptlOrigin.x = pgp->ptl.x;
  2263. ptlOrigin.y = pgp->ptl.y;
  2264. }
  2265. }
  2266. } while (bMoreGlyphs);
  2267. if ( bCommandListOpen )
  2268. {
  2269. // Indicate last Packet
  2270. if ( cCommandPacket )
  2271. *(ulCLStart - 4) |= COMMAND_LAST_PACKET;
  2272. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode);
  2273. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  2274. CP_MM_DST_X(ppdev, pjBase, xCLOffset);
  2275. }
  2276. }
  2277. /******************************************************************************\
  2278. *
  2279. * Function: vGlyphOutClip80
  2280. *
  2281. * Draw an uncacheable glyph directly to screen.
  2282. *
  2283. * Parameters: ppdev Pointer to physical device.
  2284. * pfc Pointer to FONTCACHE.
  2285. * pstro Pointer to array of glyphs to draw.
  2286. * rclBounds Clipping rectangle.
  2287. * ulSolidColor Foreground Color.
  2288. *
  2289. * Returns: Nothing.
  2290. *
  2291. \******************************************************************************/
  2292. VOID vMmGlyphOutClip80(
  2293. PDEV* ppdev,
  2294. FONTCACHE* pfc,
  2295. STROBJ* pstro,
  2296. RECTL* rclBounds,
  2297. ULONG ulSolidColor )
  2298. {
  2299. BOOL bMoreGlyphs;
  2300. LONG cGlyphs;
  2301. GLYPHPOS* pgp;
  2302. POINTL ptlOrigin;
  2303. ULONG ulCharInc;
  2304. POINTL ptlDst;
  2305. LONG cy;
  2306. GLYPHCACHE* pgc;
  2307. RECTL rclDst;
  2308. RECTL rclClip;
  2309. ULONG ulDstOffset;
  2310. BYTE* pjBase = ppdev->pjBase;
  2311. LONG lDelta = ppdev->lDelta;
  2312. DWORD jExtMode = ENABLE_XY_POSITION_PACKED
  2313. | ENABLE_CLIP_RECT_PACKED
  2314. | CL_PACKED_SRC_COPY
  2315. | ppdev->jModeColor
  2316. | ENABLE_COLOR_EXPAND
  2317. | ENABLE_TRANSPARENCY_COMPARE;
  2318. ulCharInc = pstro->ulCharInc;
  2319. //
  2320. // Make sure we can write to the video registers.
  2321. //
  2322. // We need to change to wait for buffer ready
  2323. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  2324. // Setup the common bitblt registers.
  2325. CP_MM_FG_COLOR(ppdev, pjBase, ulSolidColor);
  2326. // Do we really need to set it every time?
  2327. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  2328. CP_MM_SRC_XY_PACKED(ppdev, pjBase, 0);
  2329. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode);
  2330. do
  2331. {
  2332. // Get pointer to array of glyphs.
  2333. if (pstro->pgp != NULL)
  2334. {
  2335. pgp = pstro->pgp;
  2336. cGlyphs = pstro->cGlyphs;
  2337. bMoreGlyphs = FALSE;
  2338. }
  2339. else
  2340. {
  2341. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphs, &pgp);
  2342. }
  2343. // Get coordinates of first glyph.
  2344. ptlOrigin.x = pgp->ptl.x;
  2345. ptlOrigin.y = pgp->ptl.y;
  2346. // Loop through all glyphs.
  2347. while (cGlyphs-- > 0)
  2348. {
  2349. LONG c, cy;
  2350. GLYPHCACHE* pgc;
  2351. if (pgp->hg < MAX_GLYPHS)
  2352. {
  2353. // This is a cacheable glyph index.
  2354. pgc = &pfc->aGlyphs[pgp->hg];
  2355. cy = (pgc->pjGlyph == NULL)
  2356. ? lAllocateGlyph(pfc, pgp->pgdf->pgb, pgc)
  2357. : pgc->sizlBytes.cy;
  2358. }
  2359. else
  2360. {
  2361. // The glyph index is out of range.
  2362. cy = GLYPH_UNCACHEABLE;
  2363. }
  2364. if (cy >= 0)
  2365. {
  2366. // Calculate the glyph bounding box.
  2367. rclDst.left = ptlOrigin.x + pgc->ptlOrigin.x;
  2368. rclDst.right = rclDst.left + pgc->sizlPixels.cx;
  2369. if ((rclDst.left >= rclBounds->right) ||
  2370. (rclDst.right <= rclBounds->left))
  2371. {
  2372. goto NextGlyph;
  2373. }
  2374. rclDst.top = ptlOrigin.y + pgc->ptlOrigin.y;
  2375. rclDst.bottom = rclDst.top + pgc->sizlPixels.cy;
  2376. if ((rclDst.top >= rclBounds->bottom) ||
  2377. (rclDst.bottom <= rclBounds->top))
  2378. {
  2379. goto NextGlyph;
  2380. }
  2381. rclClip = *rclBounds;
  2382. ulDstOffset = 0;
  2383. //
  2384. // Handle X negtive
  2385. //
  2386. if (rclDst.left < 0)
  2387. {
  2388. rclClip.left -= rclDst.left;
  2389. rclClip.right -= rclDst.left;
  2390. ulDstOffset += PELS_TO_BYTES(rclDst.left);
  2391. rclDst.left = 0;
  2392. }
  2393. //
  2394. // Handle Y negtive
  2395. //
  2396. if (rclDst.top < 0)
  2397. {
  2398. rclClip.top -= rclDst.top;
  2399. rclClip.bottom -= rclDst.top;
  2400. ulDstOffset += (rclDst.top * lDelta);
  2401. rclDst.top = 0;
  2402. }
  2403. CP_MM_CLIP_ULXY(ppdev, pjBase, rclClip.left, rclClip.top);
  2404. CP_MM_CLIP_LRXY(ppdev, pjBase, rclClip.right - 1, rclClip.bottom - 1);
  2405. //
  2406. // Make sure we can write to the video registers.
  2407. //
  2408. // We need to change to wait for buffer ready
  2409. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  2410. CP_MM_DST_Y(ppdev, pjBase, rclDst.top);
  2411. CP_MM_SRC_Y_OFFSET(ppdev, pjBase, pgc->lDelta);
  2412. CP_MM_SRC_ADDR(ppdev, pjBase, (ULONG_PTR)pgc->pjGlyph);
  2413. // Perform the blit expansion.
  2414. CP_MM_XCNT(ppdev, pjBase, pgc->sizlPixels.cx - 1 );
  2415. CP_MM_YCNT(ppdev, pjBase, cy);
  2416. CP_MM_DST_ADDR(ppdev, pjBase, ulDstOffset);
  2417. CP_MM_DST_X(ppdev, pjBase, rclDst.left);
  2418. }
  2419. else if (cy == GLYPH_UNCACHEABLE)
  2420. {
  2421. // The glyph is uncacheable, draw it directly.
  2422. vClipGlyph(ppdev, pgp->pgdf->pgb, ptlOrigin, rclBounds,
  2423. ulSolidColor);
  2424. }
  2425. // Next glyph.
  2426. NextGlyph:
  2427. {
  2428. pgp++;
  2429. if (ulCharInc)
  2430. {
  2431. ptlOrigin.x += ulCharInc;
  2432. }
  2433. else
  2434. {
  2435. ptlOrigin.x = pgp->ptl.x;
  2436. ptlOrigin.y = pgp->ptl.y;
  2437. }
  2438. }
  2439. }
  2440. } while (bMoreGlyphs);
  2441. }
  2442. #endif // endif D5480